summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals')
-rw-r--r--private/ntos/nthals/bushnd.c1641
-rw-r--r--private/ntos/nthals/dirs75
-rw-r--r--private/ntos/nthals/drivesup.c334
-rw-r--r--private/ntos/nthals/extender/pci/bus.c670
-rw-r--r--private/ntos/nthals/extender/pci/control.c662
-rw-r--r--private/ntos/nthals/extender/pci/devres.c1139
-rw-r--r--private/ntos/nthals/extender/pci/init.c357
-rw-r--r--private/ntos/nthals/extender/pci/makefile6
-rw-r--r--private/ntos/nthals/extender/pci/misc.c544
-rw-r--r--private/ntos/nthals/extender/pci/pcidata.c123
-rw-r--r--private/ntos/nthals/extender/pci/pciport.h570
-rw-r--r--private/ntos/nthals/extender/pci/pciport.rc11
-rw-r--r--private/ntos/nthals/extender/pci/port.c713
-rw-r--r--private/ntos/nthals/extender/pci/sources48
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/bus.c886
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/busdata.c902
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/busp.h499
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/control.c725
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/data.c159
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/init.c482
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/misc.c471
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbapi.h235
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c1562
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbios.h241
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm89
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbiosc.c773
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/resource.c367
-rw-r--r--private/ntos/nthals/extender/pnpbios/makefile6
-rw-r--r--private/ntos/nthals/extender/pnpbios/pnpbios.rc11
-rw-r--r--private/ntos/nthals/extender/pnpbios/sources49
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/bus.c962
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/busp.h473
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/convert.c1092
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/data.c58
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/init.c620
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/isolate.c1607
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/makefile6
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/misc.c1258
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/pbios.h241
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/pnpisa.h164
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc11
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/resource.c680
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/sources47
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/bus.c1036
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/busp.h576
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/control.c511
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/convert.c1077
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/data.c156
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/init.c506
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/isolate.c1574
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/misc.c626
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/pnpisa.h155
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/resource.c555
-rw-r--r--private/ntos/nthals/extender/pnpisa/makefile6
-rw-r--r--private/ntos/nthals/extender/pnpisa/pnpisa.rc11
-rw-r--r--private/ntos/nthals/extender/pnpisa/sources48
-rw-r--r--private/ntos/nthals/hal.src171
-rw-r--r--private/ntos/nthals/hal0jens/alpha/allstart.c55
-rw-r--r--private/ntos/nthals/hal0jens/alpha/axebsup.c786
-rw-r--r--private/ntos/nthals/hal0jens/alpha/axibsup.c1089
-rw-r--r--private/ntos/nthals/hal0jens/alpha/axlbsup.c84
-rw-r--r--private/ntos/nthals/hal0jens/alpha/axsysint.c473
-rw-r--r--private/ntos/nthals/hal0jens/alpha/bios.c105
-rw-r--r--private/ntos/nthals/hal0jens/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/hal0jens/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/hal0jens/alpha/halp.h223
-rw-r--r--private/ntos/nthals/hal0jens/alpha/halpal.s184
-rw-r--r--private/ntos/nthals/hal0jens/alpha/halvga.h72
-rw-r--r--private/ntos/nthals/hal0jens/alpha/idle.s62
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jenfonts.h231
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxbeep.c133
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxcache.c521
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxcalstl.c148
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxclock.c311
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxdisp.c752
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxenv.h160
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxhalp.h188
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxhltsup.s109
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxhwsup.c4290
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxinfo.c142
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxinitnt.c471
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxintsup.s205
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxioacc.s3523
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxiouser.c971
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxirql.h133
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxisa.h95
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxmapio.c86
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxmchk.c338
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxport.c604
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxprof.h77
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxprom.c1098
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxprom.h218
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxserp.h181
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxtime.c283
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxusage.c48
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxvtisup.s149
-rw-r--r--private/ntos/nthals/hal0jens/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/hal0jens/alpha/xxenvirv.c1451
-rw-r--r--private/ntos/nthals/hal0jens/alpha/xxhalp.h74
-rw-r--r--private/ntos/nthals/hal0jens/alpha/xxinithl.c606
-rw-r--r--private/ntos/nthals/hal0jens/alpha/xxmemory.c168
-rw-r--r--private/ntos/nthals/hal0jens/alpha/xxreturn.c120
-rw-r--r--private/ntos/nthals/hal0jens/drivesup.c7
-rw-r--r--private/ntos/nthals/hal0jens/hal.rc11
-rw-r--r--private/ntos/nthals/hal0jens/hal.src7
-rw-r--r--private/ntos/nthals/hal0jens/makefile6
-rw-r--r--private/ntos/nthals/hal0jens/makefile.inc9
-rw-r--r--private/ntos/nthals/hal0jens/sources89
-rw-r--r--private/ntos/nthals/hal486c/drivesup.c7
-rw-r--r--private/ntos/nthals/hal486c/hal.rc11
-rw-r--r--private/ntos/nthals/hal486c/hal.src7
-rw-r--r--private/ntos/nthals/hal486c/i386/halnls.h5
-rw-r--r--private/ntos/nthals/hal486c/i386/halp.h5
-rw-r--r--private/ntos/nthals/hal486c/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixclock.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixipi.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixpcibrd.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixproc.c168
-rw-r--r--private/ntos/nthals/hal486c/i386/ixprofil.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixstall.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixsysbus.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/mcirql.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/mcsysint.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/pcip.h5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/hal486c/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/hal486c/makefile6
-rw-r--r--private/ntos/nthals/hal486c/makefile.inc2
-rw-r--r--private/ntos/nthals/hal486c/sources97
-rw-r--r--private/ntos/nthals/halacr/drivesup.c7
-rw-r--r--private/ntos/nthals/halacr/hal.rc11
-rw-r--r--private/ntos/nthals/halacr/hal.src7
-rw-r--r--private/ntos/nthals/halacr/makefile6
-rw-r--r--private/ntos/nthals/halacr/makefile.inc6
-rw-r--r--private/ntos/nthals/halacr/mips/allstart.c56
-rw-r--r--private/ntos/nthals/halacr/mips/cacherr.s11
-rw-r--r--private/ntos/nthals/halacr/mips/halp.h139
-rw-r--r--private/ntos/nthals/halacr/mips/hm.h487
-rw-r--r--private/ntos/nthals/halacr/mips/j4cache.s963
-rw-r--r--private/ntos/nthals/halacr/mips/j4flshbf.s61
-rw-r--r--private/ntos/nthals/halacr/mips/j4flshio.c207
-rw-r--r--private/ntos/nthals/halacr/mips/j4prof.c291
-rw-r--r--private/ntos/nthals/halacr/mips/jazzs32.h745
-rw-r--r--private/ntos/nthals/halacr/mips/jxbeep.c125
-rw-r--r--private/ntos/nthals/halacr/mips/jxdisp.c1572
-rw-r--r--private/ntos/nthals/halacr/mips/jxdmadsp.s56
-rw-r--r--private/ntos/nthals/halacr/mips/jxebsup.c1231
-rw-r--r--private/ntos/nthals/halacr/mips/jxenvirv.c698
-rw-r--r--private/ntos/nthals/halacr/mips/jxhalp.h105
-rw-r--r--private/ntos/nthals/halacr/mips/jxhwsup.c2904
-rw-r--r--private/ntos/nthals/halacr/mips/jxidle.c46
-rw-r--r--private/ntos/nthals/halacr/mips/jxmapio.c107
-rw-r--r--private/ntos/nthals/halacr/mips/jxmaptb.c137
-rw-r--r--private/ntos/nthals/halacr/mips/jxport.c877
-rw-r--r--private/ntos/nthals/halacr/mips/jxreturn.c156
-rw-r--r--private/ntos/nthals/halacr/mips/jxsysint.c324
-rw-r--r--private/ntos/nthals/halacr/mips/jxtime.c289
-rw-r--r--private/ntos/nthals/halacr/mips/jxusage.c48
-rw-r--r--private/ntos/nthals/halacr/mips/vga.h342
-rw-r--r--private/ntos/nthals/halacr/mips/x4clock.s234
-rw-r--r--private/ntos/nthals/halacr/mips/x4tb.s115
-rw-r--r--private/ntos/nthals/halacr/mips/x86bios.c65
-rw-r--r--private/ntos/nthals/halacr/mips/xxcalstl.c291
-rw-r--r--private/ntos/nthals/halacr/mips/xxclock.c83
-rw-r--r--private/ntos/nthals/halacr/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halacr/mips/xxinithl.c252
-rw-r--r--private/ntos/nthals/halacr/mips/xxinitnt.c214
-rw-r--r--private/ntos/nthals/halacr/sources85
-rw-r--r--private/ntos/nthals/halalcor/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/alcor.h100
-rw-r--r--private/ntos/nthals/halalcor/alpha/alcorerr.c154
-rw-r--r--private/ntos/nthals/halalcor/alpha/alinitnt.c795
-rw-r--r--private/ntos/nthals/halalcor/alpha/alintsup.c599
-rw-r--r--private/ntos/nthals/halalcor/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/alsysint.c497
-rw-r--r--private/ntos/nthals/halalcor/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/busdata.c137
-rw-r--r--private/ntos/nthals/halalcor/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/cia.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ciaaddr.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ciaerr.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ciaio.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ciamapio.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ebsgdma.c6
-rw-r--r--private/ntos/nthals/halalcor/alpha/eisasup.c6
-rw-r--r--private/ntos/nthals/halalcor/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/info.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/inithal.c1059
-rw-r--r--private/ntos/nthals/halalcor/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halalcor/alpha/ioproc.c91
-rw-r--r--private/ntos/nthals/halalcor/alpha/iousage.c647
-rw-r--r--private/ntos/nthals/halalcor/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/halalcor/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halalcor/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/pcibus.c124
-rw-r--r--private/ntos/nthals/halalcor/alpha/pciesc.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halalcor/alpha/pintolin.h170
-rw-r--r--private/ntos/nthals/halalcor/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halalcor/drivesup.c7
-rw-r--r--private/ntos/nthals/halalcor/hal.rc11
-rw-r--r--private/ntos/nthals/halalcor/hal.src7
-rw-r--r--private/ntos/nthals/halalcor/makefile6
-rw-r--r--private/ntos/nthals/halalcor/makefile.inc5
-rw-r--r--private/ntos/nthals/halalcor/sources106
-rw-r--r--private/ntos/nthals/halalp/alpha/28f008sa.c1
-rw-r--r--private/ntos/nthals/halalp/alpha/29f040.c1
-rw-r--r--private/ntos/nthals/halalp/alpha/addrsup.c6
-rw-r--r--private/ntos/nthals/halalp/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/halalp/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/halalp/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/busdata.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halalp/alpha/cmos8k.c2
-rw-r--r--private/ntos/nthals/halalp/alpha/eb64pdef.h6
-rw-r--r--private/ntos/nthals/halalp/alpha/ebenv.c6
-rw-r--r--private/ntos/nthals/halalp/alpha/ebinitnt.c6
-rw-r--r--private/ntos/nthals/halalp/alpha/ebintsup.c585
-rw-r--r--private/ntos/nthals/halalp/alpha/ebmapio.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/ebsysint.c6
-rw-r--r--private/ntos/nthals/halalp/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halalp/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halalp/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/flash8k.c2
-rw-r--r--private/ntos/nthals/halalp/alpha/flashdrv.c3
-rw-r--r--private/ntos/nthals/halalp/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halalp/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halalp/alpha/info.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halalp/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/machdep.h6
-rw-r--r--private/ntos/nthals/halalp/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/pcibus.c6
-rw-r--r--private/ntos/nthals/halalp/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halalp/alpha/pintolin.h212
-rw-r--r--private/ntos/nthals/halalp/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halalp/drivesup.c7
-rw-r--r--private/ntos/nthals/halalp/hal.rc11
-rw-r--r--private/ntos/nthals/halalp/hal.src7
-rw-r--r--private/ntos/nthals/halalp/makefile6
-rw-r--r--private/ntos/nthals/halalp/makefile.inc5
-rw-r--r--private/ntos/nthals/halalp/sources107
-rw-r--r--private/ntos/nthals/halalpha/28f008sa.c317
-rw-r--r--private/ntos/nthals/halalpha/29f040.c420
-rw-r--r--private/ntos/nthals/halalpha/adjust.c149
-rw-r--r--private/ntos/nthals/halalpha/allstart.c55
-rw-r--r--private/ntos/nthals/halalpha/alphaio.s1368
-rw-r--r--private/ntos/nthals/halalpha/am29f400.c543
-rw-r--r--private/ntos/nthals/halalpha/am29f400.h97
-rw-r--r--private/ntos/nthals/halalpha/apecs.c337
-rw-r--r--private/ntos/nthals/halalpha/apecs.h647
-rw-r--r--private/ntos/nthals/halalpha/apecserr.c1542
-rw-r--r--private/ntos/nthals/halalpha/apecsio.s701
-rw-r--r--private/ntos/nthals/halalpha/axintsup.c763
-rw-r--r--private/ntos/nthals/halalpha/bios.c105
-rw-r--r--private/ntos/nthals/halalpha/cache.c225
-rw-r--r--private/ntos/nthals/halalpha/cia.c769
-rw-r--r--private/ntos/nthals/halalpha/cia.h1141
-rw-r--r--private/ntos/nthals/halalpha/ciaaddr.c567
-rw-r--r--private/ntos/nthals/halalpha/ciaerr.c1642
-rw-r--r--private/ntos/nthals/halalpha/ciaio.s2820
-rw-r--r--private/ntos/nthals/halalpha/ciamapio.c154
-rw-r--r--private/ntos/nthals/halalpha/cmos8k.c246
-rw-r--r--private/ntos/nthals/halalpha/cmos8k.h32
-rw-r--r--private/ntos/nthals/halalpha/devintr.s71
-rw-r--r--private/ntos/nthals/halalpha/ebsgdma.c2307
-rw-r--r--private/ntos/nthals/halalpha/ebsgdma.h180
-rw-r--r--private/ntos/nthals/halalpha/eeprom8k.c391
-rw-r--r--private/ntos/nthals/halalpha/eisaprof.c517
-rw-r--r--private/ntos/nthals/halalpha/eisasup.c1477
-rw-r--r--private/ntos/nthals/halalpha/environ.c952
-rw-r--r--private/ntos/nthals/halalpha/environ.h167
-rw-r--r--private/ntos/nthals/halalpha/errframe.h697
-rw-r--r--private/ntos/nthals/halalpha/errplat.h774
-rw-r--r--private/ntos/nthals/halalpha/ev4cache.c488
-rw-r--r--private/ntos/nthals/halalpha/ev4int.c1013
-rw-r--r--private/ntos/nthals/halalpha/ev4ints.s272
-rw-r--r--private/ntos/nthals/halalpha/ev4mchk.c709
-rw-r--r--private/ntos/nthals/halalpha/ev4mem.s146
-rw-r--r--private/ntos/nthals/halalpha/ev4parit.c336
-rw-r--r--private/ntos/nthals/halalpha/ev4prof.c591
-rw-r--r--private/ntos/nthals/halalpha/ev5cache.c475
-rw-r--r--private/ntos/nthals/halalpha/ev5int.c440
-rw-r--r--private/ntos/nthals/halalpha/ev5ints.s397
-rw-r--r--private/ntos/nthals/halalpha/ev5mchk.c677
-rw-r--r--private/ntos/nthals/halalpha/ev5mem.s231
-rw-r--r--private/ntos/nthals/halalpha/ev5prof.c741
-rw-r--r--private/ntos/nthals/halalpha/flash8k.c323
-rw-r--r--private/ntos/nthals/halalpha/flash8k.h130
-rw-r--r--private/ntos/nthals/halalpha/flashdrv.c23
-rw-r--r--private/ntos/nthals/halalpha/fwreturn.c255
-rw-r--r--private/ntos/nthals/halalpha/gru.h84
-rw-r--r--private/ntos/nthals/halalpha/haldebug.c58
-rw-r--r--private/ntos/nthals/halalpha/haldump.c83
-rw-r--r--private/ntos/nthals/halalpha/halisa.h89
-rw-r--r--private/ntos/nthals/halalpha/halp.h1095
-rw-r--r--private/ntos/nthals/halalpha/halpal.s276
-rw-r--r--private/ntos/nthals/halalpha/halpcsl.h187
-rw-r--r--private/ntos/nthals/halalpha/halprof.c179
-rw-r--r--private/ntos/nthals/halalpha/halprof.h77
-rw-r--r--private/ntos/nthals/halalpha/haltsup.s110
-rw-r--r--private/ntos/nthals/halalpha/halvfont.h233
-rw-r--r--private/ntos/nthals/halalpha/halvga.h72
-rw-r--r--private/ntos/nthals/halalpha/idle.s62
-rw-r--r--private/ntos/nthals/halalpha/info.c180
-rw-r--r--private/ntos/nthals/halalpha/inithal.c1052
-rw-r--r--private/ntos/nthals/halalpha/intsup.s256
-rw-r--r--private/ntos/nthals/halalpha/ioproc.c104
-rw-r--r--private/ntos/nthals/halalpha/iousage.c527
-rw-r--r--private/ntos/nthals/halalpha/iousage.h85
-rw-r--r--private/ntos/nthals/halalpha/isaaddr.h75
-rw-r--r--private/ntos/nthals/halalpha/lca4.c657
-rw-r--r--private/ntos/nthals/halalpha/lca4.h669
-rw-r--r--private/ntos/nthals/halalpha/lca4err.c1153
-rw-r--r--private/ntos/nthals/halalpha/lcaioacc.s746
-rw-r--r--private/ntos/nthals/halalpha/memory.c575
-rw-r--r--private/ntos/nthals/halalpha/nvenv.c533
-rw-r--r--private/ntos/nthals/halalpha/nvram.c1452
-rw-r--r--private/ntos/nthals/halalpha/nvram.h215
-rw-r--r--private/ntos/nthals/halalpha/pciesc.c477
-rw-r--r--private/ntos/nthals/halalpha/pcip.h178
-rw-r--r--private/ntos/nthals/halalpha/pcisio.c483
-rw-r--r--private/ntos/nthals/halalpha/pcisup.c2453
-rw-r--r--private/ntos/nthals/halalpha/pcrtc.c381
-rw-r--r--private/ntos/nthals/halalpha/pcrtc.h166
-rw-r--r--private/ntos/nthals/halalpha/pcserial.c596
-rw-r--r--private/ntos/nthals/halalpha/pcspeakr.c136
-rw-r--r--private/ntos/nthals/halalpha/perf8254.c457
-rw-r--r--private/ntos/nthals/halalpha/perfcntr.c260
-rw-r--r--private/ntos/nthals/halalpha/t2.c760
-rw-r--r--private/ntos/nthals/halalpha/t2.h550
-rw-r--r--private/ntos/nthals/halalpha/vga.c608
-rw-r--r--private/ntos/nthals/halast/drivesup.c7
-rw-r--r--private/ntos/nthals/halast/hal.rc11
-rw-r--r--private/ntos/nthals/halast/hal.src7
-rw-r--r--private/ntos/nthals/halast/i386/astclock.asm578
-rw-r--r--private/ntos/nthals/halast/i386/astdetct.c169
-rw-r--r--private/ntos/nthals/halast/i386/astdisp.h59
-rw-r--r--private/ntos/nthals/halast/i386/astebi.c181
-rw-r--r--private/ntos/nthals/halast/i386/astebi2.inc1227
-rw-r--r--private/ntos/nthals/halast/i386/astebiii.h745
-rw-r--r--private/ntos/nthals/halast/i386/astebini.c189
-rw-r--r--private/ntos/nthals/halast/i386/asthal.c364
-rw-r--r--private/ntos/nthals/halast/i386/astipi.asm268
-rw-r--r--private/ntos/nthals/halast/i386/astipirq.c155
-rw-r--r--private/ntos/nthals/halast/i386/astirql.asm1110
-rw-r--r--private/ntos/nthals/halast/i386/astmp.inc207
-rw-r--r--private/ntos/nthals/halast/i386/astmpint.c163
-rw-r--r--private/ntos/nthals/halast/i386/astnls.h29
-rw-r--r--private/ntos/nthals/halast/i386/astnmi.c168
-rw-r--r--private/ntos/nthals/halast/i386/astproc.c366
-rw-r--r--private/ntos/nthals/halast/i386/astproca.asm371
-rw-r--r--private/ntos/nthals/halast/i386/astspi.asm152
-rw-r--r--private/ntos/nthals/halast/i386/aststall.asm251
-rw-r--r--private/ntos/nthals/halast/i386/astsyint.asm592
-rw-r--r--private/ntos/nthals/halast/i386/halp.h5
-rw-r--r--private/ntos/nthals/halast/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halast/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halast/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halast/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halast/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halast/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halast/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halast/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/halast/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halast/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halast/i386/spprofil.asm5
-rw-r--r--private/ntos/nthals/halast/i386/spspin.asm5
-rw-r--r--private/ntos/nthals/halast/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halast/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halast/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halast/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halast/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halast/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halast/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halast/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halast/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halast/makefile6
-rw-r--r--private/ntos/nthals/halast/makefile.inc2
-rw-r--r--private/ntos/nthals/halast/sources102
-rw-r--r--private/ntos/nthals/halavant/alpha/addrsup.c587
-rw-r--r--private/ntos/nthals/halavant/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/halavant/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/halavant/alpha/avantdef.h181
-rw-r--r--private/ntos/nthals/halavant/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/busdata.c125
-rw-r--r--private/ntos/nthals/halavant/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halavant/alpha/ebinitnt.c857
-rw-r--r--private/ntos/nthals/halavant/alpha/ebintsup.c447
-rw-r--r--private/ntos/nthals/halavant/alpha/ebmapio.c153
-rw-r--r--private/ntos/nthals/halavant/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/ebsysint.c394
-rw-r--r--private/ntos/nthals/halavant/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halavant/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halavant/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halavant/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halavant/alpha/info.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halavant/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halavant/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/nvram.c279
-rw-r--r--private/ntos/nthals/halavant/alpha/pcibus.c117
-rw-r--r--private/ntos/nthals/halavant/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halavant/alpha/pintolin.h194
-rw-r--r--private/ntos/nthals/halavant/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halavant/drivesup.c7
-rw-r--r--private/ntos/nthals/halavant/hal.rc11
-rw-r--r--private/ntos/nthals/halavant/hal.src7
-rw-r--r--private/ntos/nthals/halavant/makefile6
-rw-r--r--private/ntos/nthals/halavant/makefile.inc5
-rw-r--r--private/ntos/nthals/halavant/sources103
-rw-r--r--private/ntos/nthals/halcaro/hal.rc11
-rw-r--r--private/ntos/nthals/halcaro/makefile6
-rw-r--r--private/ntos/nthals/halcaro/ppc/fwnvr.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxbbl.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxbeep.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxbl.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxbusdat.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxcache.s1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxcalstl.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxclksup.s1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxclock.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxdat.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxdisp.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxenviro.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxfirsup.c2044
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxflshbf.s1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxflshio.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxhwsup.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxidesup.c123
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxidesup.h30
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxidle.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxinfo.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxinithl.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxintmod.c78
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxintsup.s1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxirql.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxisabus.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxmapio.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxmemctl.c325
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxmemctl.h36
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxnatsup.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxp91.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxpcibrd.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxpcibus.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxpciint.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxpcisup.c299
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxport.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxproc.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxprof.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxreset.s1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxreturn.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxs3.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxshadbf.s2
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxstall.s1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxsysbus.c210
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxsysint.c242
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxtime.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxusage.c1
-rw-r--r--private/ntos/nthals/halcaro/ppc/pxwd.c2
-rw-r--r--private/ntos/nthals/halcaro/ppc/x86bios.c1
-rw-r--r--private/ntos/nthals/halcaro/sources105
-rw-r--r--private/ntos/nthals/halcbus/bushnd.c7
-rw-r--r--private/ntos/nthals/halcbus/dirs24
-rw-r--r--private/ntos/nthals/halcbus/drivesup.c7
-rw-r--r--private/ntos/nthals/halcbus/eisa/makefile6
-rw-r--r--private/ntos/nthals/halcbus/eisa/makefile.inc2
-rw-r--r--private/ntos/nthals/halcbus/eisa/sources112
-rw-r--r--private/ntos/nthals/halcbus/hal.rc11
-rw-r--r--private/ntos/nthals/halcbus/i386/cb1stall.asm932
-rw-r--r--private/ntos/nthals/halcbus/i386/cb2stall.asm1347
-rw-r--r--private/ntos/nthals/halcbus/i386/cbapic.c898
-rw-r--r--private/ntos/nthals/halcbus/i386/cbdetect.c545
-rw-r--r--private/ntos/nthals/halcbus/i386/cbdriver.c366
-rw-r--r--private/ntos/nthals/halcbus/i386/cbioacc.asm561
-rw-r--r--private/ntos/nthals/halcbus/i386/cbmapint.c579
-rw-r--r--private/ntos/nthals/halcbus/i386/cbswint.asm444
-rw-r--r--private/ntos/nthals/halcbus/i386/cbsysint.asm590
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus.c1281
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus.h97
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus.inc277
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus1.c1870
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus1.h70
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus1bt.asm314
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus2.c4170
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus2.h397
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus2cbc.asm283
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus2ecc.c475
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus_nt.h226
-rw-r--r--private/ntos/nthals/halcbus/i386/cbus_sw.c191
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusapic.asm715
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusapic.h256
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusboot.asm362
-rw-r--r--private/ntos/nthals/halcbus/i386/cbushal.c482
-rw-r--r--private/ntos/nthals/halcbus/i386/cbuslock.asm512
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusmem.c294
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusmisc.asm406
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusnls.h41
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusnmi.c204
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusproc.c427
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusprof.asm193
-rw-r--r--private/ntos/nthals/halcbus/i386/cbusrrd.h299
-rw-r--r--private/ntos/nthals/halcbus/i386/halp.h5
-rw-r--r--private/ntos/nthals/halcbus/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixmca.h5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixmcabus.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixmcasup.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixpcibrd.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixprofil.asm5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/pcip.h5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halcbus/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halcbus/mca/makefile6
-rw-r--r--private/ntos/nthals/halcbus/mca/makefile.inc2
-rw-r--r--private/ntos/nthals/halcbus/mca/sources116
-rw-r--r--private/ntos/nthals/halcbus/rangesup.c7
-rw-r--r--private/ntos/nthals/haldti/drivesup.c7
-rw-r--r--private/ntos/nthals/haldti/hal.rc11
-rw-r--r--private/ntos/nthals/haldti/hal.src7
-rw-r--r--private/ntos/nthals/haldti/makefile6
-rw-r--r--private/ntos/nthals/haldti/makefile.inc6
-rw-r--r--private/ntos/nthals/haldti/mips/allstart.c56
-rw-r--r--private/ntos/nthals/haldti/mips/dtidef.h147
-rw-r--r--private/ntos/nthals/haldti/mips/halp.h179
-rw-r--r--private/ntos/nthals/haldti/mips/j4cache.s1026
-rw-r--r--private/ntos/nthals/haldti/mips/j4flshbf.s61
-rw-r--r--private/ntos/nthals/haldti/mips/j4flshio.c264
-rw-r--r--private/ntos/nthals/haldti/mips/j4prof.c291
-rw-r--r--private/ntos/nthals/haldti/mips/jxbeep.c125
-rw-r--r--private/ntos/nthals/haldti/mips/jxdisp.c246
-rw-r--r--private/ntos/nthals/haldti/mips/jxebsup.c2376
-rw-r--r--private/ntos/nthals/haldti/mips/jxenvirv.c98
-rw-r--r--private/ntos/nthals/haldti/mips/jxhalp.h105
-rw-r--r--private/ntos/nthals/haldti/mips/jxhwsup.c2024
-rw-r--r--private/ntos/nthals/haldti/mips/jxmapio.c78
-rw-r--r--private/ntos/nthals/haldti/mips/jxport.c773
-rw-r--r--private/ntos/nthals/haldti/mips/jxreturn.c89
-rw-r--r--private/ntos/nthals/haldti/mips/jxsysint.c252
-rw-r--r--private/ntos/nthals/haldti/mips/jxtime.c278
-rw-r--r--private/ntos/nthals/haldti/mips/jxusage.c48
-rw-r--r--private/ntos/nthals/haldti/mips/x4clock.s210
-rw-r--r--private/ntos/nthals/haldti/mips/x86bios.c262
-rw-r--r--private/ntos/nthals/haldti/mips/x86bios.h11
-rw-r--r--private/ntos/nthals/haldti/mips/x86lator.c11
-rw-r--r--private/ntos/nthals/haldti/mips/xxcalstl.c291
-rw-r--r--private/ntos/nthals/haldti/mips/xxclock.c171
-rw-r--r--private/ntos/nthals/haldti/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/haldti/mips/xxinithl.c269
-rw-r--r--private/ntos/nthals/haldti/mips/xxinitnt.c158
-rw-r--r--private/ntos/nthals/haldti/mips/xxmemory.c170
-rw-r--r--private/ntos/nthals/haldti/sources84
-rw-r--r--private/ntos/nthals/halduomp/drivesup.c11
-rw-r--r--private/ntos/nthals/halduomp/hal.rc11
-rw-r--r--private/ntos/nthals/halduomp/hal.src7
-rw-r--r--private/ntos/nthals/halduomp/makefile6
-rw-r--r--private/ntos/nthals/halduomp/makefile.inc57
-rw-r--r--private/ntos/nthals/halduomp/mips/allstart.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/cacherr.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/halp.h11
-rw-r--r--private/ntos/nthals/halduomp/mips/j4cache.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/j4flshbf.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/j4flshio.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/j4prof.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxbeep.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxdisp.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxdmadsp.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxebsup.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxenvirv.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxhalp.h11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxhwsup.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxmapio.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxmaptb.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxport.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxreturn.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxsysint.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxtime.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/jxusage.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/x4clock.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/x4tb.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/x86bios.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/xxcalstl.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/xxclock.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/xxidle.s11
-rw-r--r--private/ntos/nthals/halduomp/mips/xxinithl.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/xxinitnt.c11
-rw-r--r--private/ntos/nthals/halduomp/mips/xxipiint.s11
-rw-r--r--private/ntos/nthals/halduomp/sources92
-rw-r--r--private/ntos/nthals/haleagle/hal.rc11
-rw-r--r--private/ntos/nthals/haleagle/makefile6
-rw-r--r--private/ntos/nthals/haleagle/ppc/ctrlops.c471
-rw-r--r--private/ntos/nthals/haleagle/ppc/fwnvr.c1745
-rw-r--r--private/ntos/nthals/haleagle/ppc/fwnvr.h37
-rw-r--r--private/ntos/nthals/haleagle/ppc/fwstatus.h17
-rw-r--r--private/ntos/nthals/haleagle/ppc/halp.h239
-rw-r--r--private/ntos/nthals/haleagle/ppc/mk48tdc.h68
-rw-r--r--private/ntos/nthals/haleagle/ppc/mk48time.c431
-rw-r--r--private/ntos/nthals/haleagle/ppc/pcibios.c1056
-rw-r--r--private/ntos/nthals/haleagle/ppc/pcibios.h58
-rw-r--r--private/ntos/nthals/haleagle/ppc/pcip.h186
-rw-r--r--private/ntos/nthals/haleagle/ppc/prepnvr.h134
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxbeep.c134
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxbusdat.c210
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxcache.s208
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxcalstl.c184
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxcirrus.h238
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxclksup.s145
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxclock.c243
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxdat.c110
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxdisp.c2211
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxds1385.c386
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxds1585.h106
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxenviro.c170
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxflshbf.s186
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxflshio.c128
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxhalp.h253
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxhwsup.c2199
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxidle.c65
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxinfo.c97
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxinithl.c396
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxintsup.s290
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxirql.c261
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxisabus.c130
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxl2.s551
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmapio.c124
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmemctl.c1643
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmemctl.h45
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmisc.s183
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcibrd.c544
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcibus.c2289
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpciint.c221
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcisup.c235
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcisup.h54
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxport.c849
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpower.s67
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxproc.c212
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxprof.c268
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxreset.s240
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxreturn.c133
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxs3.h760
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsiosup.c1761
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsiosup.h221
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxstall.s326
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsysbus.c204
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsysint.c214
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsystyp.c96
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsystyp.h44
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxtime.c137
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxusage.c503
-rw-r--r--private/ntos/nthals/haleagle/ppc/sysbios.c73
-rw-r--r--private/ntos/nthals/haleagle/ppc/sysbios.h31
-rw-r--r--private/ntos/nthals/haleagle/ppc/txtpalet.h97
-rw-r--r--private/ntos/nthals/haleagle/ppc/x86bios.c1156
-rw-r--r--private/ntos/nthals/haleagle/sources97
-rw-r--r--private/ntos/nthals/haleb164/alpha/28f008sa.c1
-rw-r--r--private/ntos/nthals/haleb164/alpha/29f040.c1
-rw-r--r--private/ntos/nthals/haleb164/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/bios.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/busdata.c125
-rw-r--r--private/ntos/nthals/haleb164/alpha/cache.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/cia.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ciaaddr.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ciaerr.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ciaio.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ciamapio.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/eb164.h133
-rw-r--r--private/ntos/nthals/haleb164/alpha/eb164err.c122
-rw-r--r--private/ntos/nthals/haleb164/alpha/eb164io.s139
-rw-r--r--private/ntos/nthals/haleb164/alpha/ebinitnt.c677
-rw-r--r--private/ntos/nthals/haleb164/alpha/ebintsup.c626
-rw-r--r--private/ntos/nthals/haleb164/alpha/ebsgdma.c6
-rw-r--r--private/ntos/nthals/haleb164/alpha/ebsysint.c425
-rw-r--r--private/ntos/nthals/haleb164/alpha/eisasup.c6
-rw-r--r--private/ntos/nthals/haleb164/alpha/environ.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/flash8k.c1
-rw-r--r--private/ntos/nthals/haleb164/alpha/flashdrv.c23
-rw-r--r--private/ntos/nthals/haleb164/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/idle.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/info.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/inithal.c1059
-rw-r--r--private/ntos/nthals/haleb164/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/haleb164/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/haleb164/alpha/memory.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/nvenv.c1
-rw-r--r--private/ntos/nthals/haleb164/alpha/nvram.c1
-rw-r--r--private/ntos/nthals/haleb164/alpha/pcibus.c124
-rw-r--r--private/ntos/nthals/haleb164/alpha/pcisio.c493
-rw-r--r--private/ntos/nthals/haleb164/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/haleb164/alpha/pintolin.h182
-rw-r--r--private/ntos/nthals/haleb164/alpha/vga.c7
-rw-r--r--private/ntos/nthals/haleb164/drivesup.c7
-rw-r--r--private/ntos/nthals/haleb164/hal.rc11
-rw-r--r--private/ntos/nthals/haleb164/hal.src7
-rw-r--r--private/ntos/nthals/haleb164/makefile6
-rw-r--r--private/ntos/nthals/haleb164/makefile.inc5
-rw-r--r--private/ntos/nthals/haleb164/sources109
-rw-r--r--private/ntos/nthals/haleb64p/alpha/28f008sa.c1
-rw-r--r--private/ntos/nthals/haleb64p/alpha/29f040.c1
-rw-r--r--private/ntos/nthals/haleb64p/alpha/addrsup.c595
-rw-r--r--private/ntos/nthals/haleb64p/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/bios.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/busdata.c125
-rw-r--r--private/ntos/nthals/haleb64p/alpha/cache.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/haleb64p/alpha/cmos8k.c5
-rw-r--r--private/ntos/nthals/haleb64p/alpha/eb64pdef.h134
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebenv.c61
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebinitnt.c880
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebintr.s75
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebintsup.c569
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebmapio.c147
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ebsysint.c422
-rw-r--r--private/ntos/nthals/haleb64p/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/environ.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/flash8k.c5
-rw-r--r--private/ntos/nthals/haleb64p/alpha/flashdrv.c23
-rw-r--r--private/ntos/nthals/haleb64p/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/idle.s7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/info.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/haleb64p/alpha/memory.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pcibus.c111
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/haleb64p/alpha/pintolin.h179
-rw-r--r--private/ntos/nthals/haleb64p/alpha/vga.c7
-rw-r--r--private/ntos/nthals/haleb64p/drivesup.c7
-rw-r--r--private/ntos/nthals/haleb64p/hal.rc11
-rw-r--r--private/ntos/nthals/haleb64p/hal.src7
-rw-r--r--private/ntos/nthals/haleb64p/makefile6
-rw-r--r--private/ntos/nthals/haleb64p/makefile.inc5
-rw-r--r--private/ntos/nthals/haleb64p/sources107
-rw-r--r--private/ntos/nthals/haleb66/alpha/28f008sa.c1
-rw-r--r--private/ntos/nthals/haleb66/alpha/29f040.c1
-rw-r--r--private/ntos/nthals/haleb66/alpha/addrsup.c636
-rw-r--r--private/ntos/nthals/haleb66/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/haleb66/alpha/bios.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/busdata.c127
-rw-r--r--private/ntos/nthals/haleb66/alpha/cache.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/haleb66/alpha/cmos8k.c5
-rw-r--r--private/ntos/nthals/haleb66/alpha/eb66def.h94
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebenv.c61
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebinitnt.c784
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebintr.s123
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebintsup.c612
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebmapio.c158
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ebsysint.c424
-rw-r--r--private/ntos/nthals/haleb66/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/environ.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/haleb66/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ev4parit.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/flash8k.c5
-rw-r--r--private/ntos/nthals/haleb66/alpha/flashdrv.c23
-rw-r--r--private/ntos/nthals/haleb66/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/haleb66/alpha/idle.s7
-rw-r--r--private/ntos/nthals/haleb66/alpha/info.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/haleb66/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/lca4.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/lca4err.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/lcaioacc.s7
-rw-r--r--private/ntos/nthals/haleb66/alpha/machdep.h43
-rw-r--r--private/ntos/nthals/haleb66/alpha/memory.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/mustdef.h56
-rw-r--r--private/ntos/nthals/haleb66/alpha/pcibus.c128
-rw-r--r--private/ntos/nthals/haleb66/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/haleb66/alpha/pintolin.h192
-rw-r--r--private/ntos/nthals/haleb66/alpha/vga.c7
-rw-r--r--private/ntos/nthals/haleb66/drivesup.c7
-rw-r--r--private/ntos/nthals/haleb66/hal.rc11
-rw-r--r--private/ntos/nthals/haleb66/hal.src7
-rw-r--r--private/ntos/nthals/haleb66/makefile6
-rw-r--r--private/ntos/nthals/haleb66/makefile.inc5
-rw-r--r--private/ntos/nthals/haleb66/sources106
-rw-r--r--private/ntos/nthals/halfire/hal.rc11
-rw-r--r--private/ntos/nthals/halfire/makefile6
-rw-r--r--private/ntos/nthals/halfire/makefile.inc22
-rw-r--r--private/ntos/nthals/halfire/ppc/ctrlops.c471
-rw-r--r--private/ntos/nthals/halfire/ppc/fp82091.c120
-rw-r--r--private/ntos/nthals/halfire/ppc/fp82091.h426
-rw-r--r--private/ntos/nthals/halfire/ppc/fparch.h46
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbat.c346
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbat.h20
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbt445.c413
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbt445.h180
-rw-r--r--private/ntos/nthals/halfire/ppc/fpcpu.h179
-rw-r--r--private/ntos/nthals/halfire/ppc/fpcpu.s387
-rw-r--r--private/ntos/nthals/halfire/ppc/fpdcc.c226
-rw-r--r--private/ntos/nthals/halfire/ppc/fpdcc.h142
-rw-r--r--private/ntos/nthals/halfire/ppc/fpdebug.h171
-rw-r--r--private/ntos/nthals/halfire/ppc/fpds1385.c372
-rw-r--r--private/ntos/nthals/halfire/ppc/fpds1385.h213
-rw-r--r--private/ntos/nthals/halfire/ppc/fpi2c.c1016
-rw-r--r--private/ntos/nthals/halfire/ppc/fpi2c.h39
-rw-r--r--private/ntos/nthals/halfire/ppc/fpi2csup.h232
-rw-r--r--private/ntos/nthals/halfire/ppc/fpints.c292
-rw-r--r--private/ntos/nthals/halfire/ppc/fpio.h230
-rw-r--r--private/ntos/nthals/halfire/ppc/fplibc.c114
-rw-r--r--private/ntos/nthals/halfire/ppc/fpnvram.h105
-rw-r--r--private/ntos/nthals/halfire/ppc/fppci.h189
-rw-r--r--private/ntos/nthals/halfire/ppc/fppcisup.c1101
-rw-r--r--private/ntos/nthals/halfire/ppc/fppcisup.h142
-rw-r--r--private/ntos/nthals/halfire/ppc/fpproto.h17
-rw-r--r--private/ntos/nthals/halfire/ppc/fpreg.h422
-rw-r--r--private/ntos/nthals/halfire/ppc/fprgstry.c871
-rw-r--r--private/ntos/nthals/halfire/ppc/halp.h267
-rw-r--r--private/ntos/nthals/halfire/ppc/pcibios.c1084
-rw-r--r--private/ntos/nthals/halfire/ppc/pcibios.h58
-rw-r--r--private/ntos/nthals/halfire/ppc/pcip.h249
-rw-r--r--private/ntos/nthals/halfire/ppc/phcalls.c120
-rw-r--r--private/ntos/nthals/halfire/ppc/phprods.c794
-rw-r--r--private/ntos/nthals/halfire/ppc/phsystem.h270
-rw-r--r--private/ntos/nthals/halfire/ppc/phsystem.s487
-rw-r--r--private/ntos/nthals/halfire/ppc/phvrsion.c433
-rw-r--r--private/ntos/nthals/halfire/ppc/pxbeep.c144
-rw-r--r--private/ntos/nthals/halfire/ppc/pxbusdat.c207
-rw-r--r--private/ntos/nthals/halfire/ppc/pxcache.s1105
-rw-r--r--private/ntos/nthals/halfire/ppc/pxcalstl.c150
-rw-r--r--private/ntos/nthals/halfire/ppc/pxcirrus.h234
-rw-r--r--private/ntos/nthals/halfire/ppc/pxclksup.s163
-rw-r--r--private/ntos/nthals/halfire/ppc/pxclock.c287
-rw-r--r--private/ntos/nthals/halfire/ppc/pxdat.c113
-rw-r--r--private/ntos/nthals/halfire/ppc/pxdisp.c2907
-rw-r--r--private/ntos/nthals/halfire/ppc/pxenviro.c729
-rw-r--r--private/ntos/nthals/halfire/ppc/pxflshbf.s159
-rw-r--r--private/ntos/nthals/halfire/ppc/pxflshio.c195
-rw-r--r--private/ntos/nthals/halfire/ppc/pxhalp.h291
-rw-r--r--private/ntos/nthals/halfire/ppc/pxhwsup.c2212
-rw-r--r--private/ntos/nthals/halfire/ppc/pxidaho.h149
-rw-r--r--private/ntos/nthals/halfire/ppc/pxidle.c77
-rw-r--r--private/ntos/nthals/halfire/ppc/pxinithl.c1114
-rw-r--r--private/ntos/nthals/halfire/ppc/pxintsup.s121
-rw-r--r--private/ntos/nthals/halfire/ppc/pxirql.c182
-rw-r--r--private/ntos/nthals/halfire/ppc/pxisabus.c576
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmapio.c134
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmemctl.c243
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmemctl.h68
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmisc.s282
-rw-r--r--private/ntos/nthals/halfire/ppc/pxnatsup.c90
-rw-r--r--private/ntos/nthals/halfire/ppc/pxnatsup.h67
-rw-r--r--private/ntos/nthals/halfire/ppc/pxnvrsup.h35
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpcibus.c2327
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpciint.c398
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpcisup.c267
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpcisup.h66
-rw-r--r--private/ntos/nthals/halfire/ppc/pxport.c855
-rw-r--r--private/ntos/nthals/halfire/ppc/pxproc.c250
-rw-r--r--private/ntos/nthals/halfire/ppc/pxprof.c277
-rw-r--r--private/ntos/nthals/halfire/ppc/pxreturn.c223
-rw-r--r--private/ntos/nthals/halfire/ppc/pxrtcsup.h37
-rw-r--r--private/ntos/nthals/halfire/ppc/pxs3.h770
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsiosup.c1866
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsiosup.h231
-rw-r--r--private/ntos/nthals/halfire/ppc/pxstall.s390
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsysbus.c298
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsysint.c243
-rw-r--r--private/ntos/nthals/halfire/ppc/pxtime.c340
-rw-r--r--private/ntos/nthals/halfire/ppc/pxusage.c512
-rw-r--r--private/ntos/nthals/halfire/ppc/sysbios.c73
-rw-r--r--private/ntos/nthals/halfire/ppc/sysbios.h31
-rw-r--r--private/ntos/nthals/halfire/ppc/txtpalet.h107
-rw-r--r--private/ntos/nthals/halfire/ppc/x86bios.c1201
-rw-r--r--private/ntos/nthals/halfire/ppc/x86bios.h24
-rw-r--r--private/ntos/nthals/halfire/sources235
-rw-r--r--private/ntos/nthals/halflex/adjust.c185
-rw-r--r--private/ntos/nthals/halflex/allstart.c56
-rw-r--r--private/ntos/nthals/halflex/alpha/addrsup.c820
-rw-r--r--private/ntos/nthals/halflex/alpha/alphaio.s1482
-rw-r--r--private/ntos/nthals/halflex/alpha/apoc.h167
-rw-r--r--private/ntos/nthals/halflex/alpha/arcssup.c87
-rw-r--r--private/ntos/nthals/halflex/alpha/dtidef.h149
-rw-r--r--private/ntos/nthals/halflex/alpha/ev4int.c955
-rw-r--r--private/ntos/nthals/halflex/alpha/ev4ints.s300
-rw-r--r--private/ntos/nthals/halflex/alpha/ev4prof.c585
-rw-r--r--private/ntos/nthals/halflex/alpha/ev5ints.s397
-rw-r--r--private/ntos/nthals/halflex/alpha/ev5prof.c747
-rw-r--r--private/ntos/nthals/halflex/alpha/evclock.s119
-rw-r--r--private/ntos/nthals/halflex/alpha/evxcache.c823
-rw-r--r--private/ntos/nthals/halflex/alpha/evxmem.s231
-rw-r--r--private/ntos/nthals/halflex/alpha/evxprof.c342
-rw-r--r--private/ntos/nthals/halflex/alpha/halpal.s276
-rw-r--r--private/ntos/nthals/halflex/alpha/info.c128
-rw-r--r--private/ntos/nthals/halflex/alpha/initsys.c579
-rw-r--r--private/ntos/nthals/halflex/alpha/intsup.c393
-rw-r--r--private/ntos/nthals/halflex/alpha/jxhalp.h404
-rw-r--r--private/ntos/nthals/halflex/alpha/jxmapio.c103
-rw-r--r--private/ntos/nthals/halflex/alpha/minitlb.c221
-rw-r--r--private/ntos/nthals/halflex/alpha/pcisup.c897
-rw-r--r--private/ntos/nthals/halflex/alpha/perfcntr.c262
-rw-r--r--private/ntos/nthals/halflex/alpha/portsup.c93
-rw-r--r--private/ntos/nthals/halflex/alpha/xxidle.s62
-rw-r--r--private/ntos/nthals/halflex/alpha/xxinitnt.c194
-rw-r--r--private/ntos/nthals/halflex/busdata.c175
-rw-r--r--private/ntos/nthals/halflex/bushnd.c7
-rw-r--r--private/ntos/nthals/halflex/drivesup.c7
-rw-r--r--private/ntos/nthals/halflex/hal.rc11
-rw-r--r--private/ntos/nthals/halflex/hal.src7
-rw-r--r--private/ntos/nthals/halflex/halp.h453
-rw-r--r--private/ntos/nthals/halflex/ioproc.c112
-rw-r--r--private/ntos/nthals/halflex/iousage.c515
-rw-r--r--private/ntos/nthals/halflex/iousage.h77
-rw-r--r--private/ntos/nthals/halflex/makefile6
-rw-r--r--private/ntos/nthals/halflex/makefile.inc5
-rw-r--r--private/ntos/nthals/halflex/mips/addrsup.c204
-rw-r--r--private/ntos/nthals/halflex/mips/arcssup.c144
-rw-r--r--private/ntos/nthals/halflex/mips/dtidef.h150
-rw-r--r--private/ntos/nthals/halflex/mips/flushio.c282
-rw-r--r--private/ntos/nthals/halflex/mips/gambit.h54
-rw-r--r--private/ntos/nthals/halflex/mips/info.c116
-rw-r--r--private/ntos/nthals/halflex/mips/initsys.c405
-rw-r--r--private/ntos/nthals/halflex/mips/intsup.c240
-rw-r--r--private/ntos/nthals/halflex/mips/j4cache.s1091
-rw-r--r--private/ntos/nthals/halflex/mips/j4flshbf.s61
-rw-r--r--private/ntos/nthals/halflex/mips/j4prof.c290
-rw-r--r--private/ntos/nthals/halflex/mips/jxhalp.h122
-rw-r--r--private/ntos/nthals/halflex/mips/jxmapio.c192
-rw-r--r--private/ntos/nthals/halflex/mips/pcisup.c1008
-rw-r--r--private/ntos/nthals/halflex/mips/portsup.c137
-rw-r--r--private/ntos/nthals/halflex/mips/x4clock.s210
-rw-r--r--private/ntos/nthals/halflex/mips/x4tb.s109
-rw-r--r--private/ntos/nthals/halflex/mips/xxcalstl.c253
-rw-r--r--private/ntos/nthals/halflex/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halflex/mips/xxinitnt.c159
-rw-r--r--private/ntos/nthals/halflex/pcip.h138
-rw-r--r--private/ntos/nthals/halflex/platform.h194
-rw-r--r--private/ntos/nthals/halflex/sources141
-rw-r--r--private/ntos/nthals/halflex/uniflex.h108
-rw-r--r--private/ntos/nthals/halflex/x86bios.c599
-rw-r--r--private/ntos/nthals/halflex/xxbeep.c125
-rw-r--r--private/ntos/nthals/halflex/xxclock.c174
-rw-r--r--private/ntos/nthals/halflex/xxdisp.c293
-rw-r--r--private/ntos/nthals/halflex/xxebsup.c2375
-rw-r--r--private/ntos/nthals/halflex/xxenvirv.c106
-rw-r--r--private/ntos/nthals/halflex/xxhwsup.c1250
-rw-r--r--private/ntos/nthals/halflex/xxinithl.c286
-rw-r--r--private/ntos/nthals/halflex/xxpcisup.c2391
-rw-r--r--private/ntos/nthals/halflex/xxport.c769
-rw-r--r--private/ntos/nthals/halflex/xxreturn.c101
-rw-r--r--private/ntos/nthals/halflex/xxsysint.c217
-rw-r--r--private/ntos/nthals/halflex/xxtime.c285
-rw-r--r--private/ntos/nthals/halfxs/drivesup.c7
-rw-r--r--private/ntos/nthals/halfxs/hal.rc11
-rw-r--r--private/ntos/nthals/halfxs/hal.src7
-rw-r--r--private/ntos/nthals/halfxs/makefile6
-rw-r--r--private/ntos/nthals/halfxs/makefile.inc9
-rw-r--r--private/ntos/nthals/halfxs/mips/allstart.c70
-rw-r--r--private/ntos/nthals/halfxs/mips/cacherr.s199
-rw-r--r--private/ntos/nthals/halfxs/mips/halp.h192
-rw-r--r--private/ntos/nthals/halfxs/mips/j4cache.s1038
-rw-r--r--private/ntos/nthals/halfxs/mips/j4flshbf.s61
-rw-r--r--private/ntos/nthals/halfxs/mips/j4flshio.c208
-rw-r--r--private/ntos/nthals/halfxs/mips/j4prof.c318
-rw-r--r--private/ntos/nthals/halfxs/mips/jxbeep.c133
-rw-r--r--private/ntos/nthals/halfxs/mips/jxdisp.c1718
-rw-r--r--private/ntos/nthals/halfxs/mips/jxdmadsp.s78
-rw-r--r--private/ntos/nthals/halfxs/mips/jxebsup.c1287
-rw-r--r--private/ntos/nthals/halfxs/mips/jxenvirv.c664
-rw-r--r--private/ntos/nthals/halfxs/mips/jxhalp.h106
-rw-r--r--private/ntos/nthals/halfxs/mips/jxhwsup.c2927
-rw-r--r--private/ntos/nthals/halfxs/mips/jxmapio.c108
-rw-r--r--private/ntos/nthals/halfxs/mips/jxmaptb.c137
-rw-r--r--private/ntos/nthals/halfxs/mips/jxport.c879
-rw-r--r--private/ntos/nthals/halfxs/mips/jxreturn.c169
-rw-r--r--private/ntos/nthals/halfxs/mips/jxsysint.c304
-rw-r--r--private/ntos/nthals/halfxs/mips/jxtime.c289
-rw-r--r--private/ntos/nthals/halfxs/mips/jxusage.c48
-rw-r--r--private/ntos/nthals/halfxs/mips/x4clock.s354
-rw-r--r--private/ntos/nthals/halfxs/mips/x4tb.s115
-rw-r--r--private/ntos/nthals/halfxs/mips/x86bios.c239
-rw-r--r--private/ntos/nthals/halfxs/mips/xxcalstl.c296
-rw-r--r--private/ntos/nthals/halfxs/mips/xxclock.c83
-rw-r--r--private/ntos/nthals/halfxs/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halfxs/mips/xxinithl.c547
-rw-r--r--private/ntos/nthals/halfxs/mips/xxinitnt.c295
-rw-r--r--private/ntos/nthals/halfxs/mips/xxipiint.s65
-rw-r--r--private/ntos/nthals/halfxs/sources91
-rw-r--r--private/ntos/nthals/halfxspc/drivesup.c11
-rw-r--r--private/ntos/nthals/halfxspc/hal.rc11
-rw-r--r--private/ntos/nthals/halfxspc/hal.src7
-rw-r--r--private/ntos/nthals/halfxspc/makefile6
-rw-r--r--private/ntos/nthals/halfxspc/makefile.inc57
-rw-r--r--private/ntos/nthals/halfxspc/mips/allstart.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/cacherr.s11
-rw-r--r--private/ntos/nthals/halfxspc/mips/halp.h11
-rw-r--r--private/ntos/nthals/halfxspc/mips/j4cache.s13
-rw-r--r--private/ntos/nthals/halfxspc/mips/j4flshbf.s11
-rw-r--r--private/ntos/nthals/halfxspc/mips/j4flshio.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/j4prof.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxbeep.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxdisp.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxdmadsp.s11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxebsup.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxenvirv.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxhalp.h11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxhwsup.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxmapio.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxmaptb.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxport.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxreturn.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxsysint.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxtime.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/jxusage.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/x4clock.s11
-rw-r--r--private/ntos/nthals/halfxspc/mips/x4tb.s11
-rw-r--r--private/ntos/nthals/halfxspc/mips/x86bios.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/xxcalstl.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/xxclock.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/xxidle.s11
-rw-r--r--private/ntos/nthals/halfxspc/mips/xxinithl.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/xxinitnt.c11
-rw-r--r--private/ntos/nthals/halfxspc/mips/xxipiint.s11
-rw-r--r--private/ntos/nthals/halfxspc/sources92
-rw-r--r--private/ntos/nthals/halgamma/alpha/addrsup.c6
-rw-r--r--private/ntos/nthals/halgamma/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/alphaio.s1368
-rw-r--r--private/ntos/nthals/halgamma/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/busdata.c6
-rw-r--r--private/ntos/nthals/halgamma/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halgamma/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/eeprom8k.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/gamma.h553
-rw-r--r--private/ntos/nthals/halgamma/alpha/gammaerr.c2395
-rw-r--r--private/ntos/nthals/halgamma/alpha/gammaio.s1046
-rw-r--r--private/ntos/nthals/halgamma/alpha/gammartc.h6
-rw-r--r--private/ntos/nthals/halgamma/alpha/gminitnt.c1321
-rw-r--r--private/ntos/nthals/halgamma/alpha/gmintr.s99
-rw-r--r--private/ntos/nthals/halgamma/alpha/gmintsup.c217
-rw-r--r--private/ntos/nthals/halgamma/alpha/gmmapio.c6
-rw-r--r--private/ntos/nthals/halgamma/alpha/gmsysint.c471
-rw-r--r--private/ntos/nthals/halgamma/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halgamma/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halgamma/alpha/icic.c1
-rw-r--r--private/ntos/nthals/halgamma/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halgamma/alpha/info.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halgamma/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/lyintsup.c1
-rw-r--r--private/ntos/nthals/halgamma/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halgamma/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/pcibus.c6
-rw-r--r--private/ntos/nthals/halgamma/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/perf8254.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/rattler.h214
-rw-r--r--private/ntos/nthals/halgamma/alpha/siintsup.c1
-rw-r--r--private/ntos/nthals/halgamma/alpha/t2.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halgamma/alpha/xiintsup.c1
-rw-r--r--private/ntos/nthals/halgamma/bushnd.c7
-rw-r--r--private/ntos/nthals/halgamma/dirs24
-rw-r--r--private/ntos/nthals/halgamma/drivesup.c7
-rw-r--r--private/ntos/nthals/halgamma/hal.rc11
-rw-r--r--private/ntos/nthals/halgamma/hal.src7
-rw-r--r--private/ntos/nthals/halgamma/mp/makefile6
-rw-r--r--private/ntos/nthals/halgamma/mp/makefile.inc5
-rw-r--r--private/ntos/nthals/halgamma/mp/sources107
-rw-r--r--private/ntos/nthals/halgamma/up/makefile6
-rw-r--r--private/ntos/nthals/halgamma/up/makefile.inc5
-rw-r--r--private/ntos/nthals/halgamma/up/sources107
-rw-r--r--private/ntos/nthals/hallego/alpha/addrsup.c590
-rw-r--r--private/ntos/nthals/hallego/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/hallego/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/hallego/alpha/bios.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/busdata.c129
-rw-r--r--private/ntos/nthals/hallego/alpha/cache.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/hallego/alpha/cmos8k.c2
-rw-r--r--private/ntos/nthals/hallego/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/hallego/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/hallego/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/hallego/alpha/idle.s7
-rw-r--r--private/ntos/nthals/hallego/alpha/info.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/hallego/alpha/ioproc.c74
-rw-r--r--private/ntos/nthals/hallego/alpha/iousage.c647
-rw-r--r--private/ntos/nthals/hallego/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/hallego/alpha/legodef.h671
-rw-r--r--private/ntos/nthals/hallego/alpha/lginitnt.c1409
-rw-r--r--private/ntos/nthals/hallego/alpha/lgintr.s121
-rw-r--r--private/ntos/nthals/hallego/alpha/lgintsup.c732
-rw-r--r--private/ntos/nthals/hallego/alpha/lgmapio.c232
-rw-r--r--private/ntos/nthals/hallego/alpha/lgsysint.c679
-rw-r--r--private/ntos/nthals/hallego/alpha/machdep.h46
-rw-r--r--private/ntos/nthals/hallego/alpha/memory.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/nvenv.c1
-rw-r--r--private/ntos/nthals/hallego/alpha/nvram.c1
-rw-r--r--private/ntos/nthals/hallego/alpha/pcd8584.c653
-rw-r--r--private/ntos/nthals/hallego/alpha/pcd8584.h196
-rw-r--r--private/ntos/nthals/hallego/alpha/pcf8574.c336
-rw-r--r--private/ntos/nthals/hallego/alpha/pcf8574.h175
-rw-r--r--private/ntos/nthals/hallego/alpha/pcibus.c111
-rw-r--r--private/ntos/nthals/hallego/alpha/pciir.c646
-rw-r--r--private/ntos/nthals/hallego/alpha/pcisio.c587
-rw-r--r--private/ntos/nthals/hallego/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/hallego/alpha/pintolin.h273
-rw-r--r--private/ntos/nthals/hallego/alpha/smerr.c390
-rw-r--r--private/ntos/nthals/hallego/alpha/smir.c722
-rw-r--r--private/ntos/nthals/hallego/alpha/smsup.c363
-rw-r--r--private/ntos/nthals/hallego/alpha/vga.c7
-rw-r--r--private/ntos/nthals/hallego/bushnd.c7
-rw-r--r--private/ntos/nthals/hallego/drivesup.c7
-rw-r--r--private/ntos/nthals/hallego/hal.aps0
-rw-r--r--private/ntos/nthals/hallego/hal.rc11
-rw-r--r--private/ntos/nthals/hallego/hal.src7
-rw-r--r--private/ntos/nthals/hallego/makefile6
-rw-r--r--private/ntos/nthals/hallego/makefile.inc5
-rw-r--r--private/ntos/nthals/hallego/sources111
-rw-r--r--private/ntos/nthals/hallx3/alpha/addrsup.c587
-rw-r--r--private/ntos/nthals/hallx3/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/hallx3/alpha/am29f400.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/hallx3/alpha/bios.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/busdata.c125
-rw-r--r--private/ntos/nthals/hallx3/alpha/cache.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/hallx3/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/environ.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/hallx3/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/hallx3/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/flash8k.c518
-rw-r--r--private/ntos/nthals/hallx3/alpha/flash8k.h80
-rw-r--r--private/ntos/nthals/hallx3/alpha/flashbus.h9
-rw-r--r--private/ntos/nthals/hallx3/alpha/flashdrv.c19
-rw-r--r--private/ntos/nthals/hallx3/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/hallx3/alpha/idle.s187
-rw-r--r--private/ntos/nthals/hallx3/alpha/info.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/hallx3/alpha/ioproc.c102
-rw-r--r--private/ntos/nthals/hallx3/alpha/iousage.c554
-rw-r--r--private/ntos/nthals/hallx3/alpha/iousage.h92
-rw-r--r--private/ntos/nthals/hallx3/alpha/lx3.h155
-rw-r--r--private/ntos/nthals/hallx3/alpha/lxinitnt.c900
-rw-r--r--private/ntos/nthals/hallx3/alpha/lxintsup.c396
-rw-r--r--private/ntos/nthals/hallx3/alpha/lxmapio.c160
-rw-r--r--private/ntos/nthals/hallx3/alpha/lxsgdma.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/lxsysint.c394
-rw-r--r--private/ntos/nthals/hallx3/alpha/machdep.h44
-rw-r--r--private/ntos/nthals/hallx3/alpha/memory.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/nvenv.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/nvram.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/pcibus.c108
-rw-r--r--private/ntos/nthals/hallx3/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/hallx3/alpha/pflash.c91
-rw-r--r--private/ntos/nthals/hallx3/alpha/pflash.h31
-rw-r--r--private/ntos/nthals/hallx3/alpha/vga.c7
-rw-r--r--private/ntos/nthals/hallx3/drivesup.c7
-rw-r--r--private/ntos/nthals/hallx3/hal.rc11
-rw-r--r--private/ntos/nthals/hallx3/hal.src7
-rw-r--r--private/ntos/nthals/hallx3/makefile6
-rw-r--r--private/ntos/nthals/hallx3/makefile.inc5
-rw-r--r--private/ntos/nthals/hallx3/sources107
-rw-r--r--private/ntos/nthals/halmca/drivesup.c7
-rw-r--r--private/ntos/nthals/halmca/hal.rc11
-rw-r--r--private/ntos/nthals/halmca/hal.src7
-rw-r--r--private/ntos/nthals/halmca/i386/halnls.h5
-rw-r--r--private/ntos/nthals/halmca/i386/halp.h5
-rw-r--r--private/ntos/nthals/halmca/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halmca/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixclock.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halmca/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixipi.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halmca/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halmca/i386/ixmca.h113
-rw-r--r--private/ntos/nthals/halmca/i386/ixmcabus.c117
-rw-r--r--private/ntos/nthals/halmca/i386/ixmcasup.c1344
-rw-r--r--private/ntos/nthals/halmca/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixpcibrd.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixproc.c163
-rw-r--r--private/ntos/nthals/halmca/i386/ixprofil.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixstall.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixsysbus.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halmca/i386/mcirql.asm1121
-rw-r--r--private/ntos/nthals/halmca/i386/mcsysint.asm385
-rw-r--r--private/ntos/nthals/halmca/i386/pcip.h5
-rw-r--r--private/ntos/nthals/halmca/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halmca/makefile6
-rw-r--r--private/ntos/nthals/halmca/makefile.inc2
-rw-r--r--private/ntos/nthals/halmca/sources100
-rw-r--r--private/ntos/nthals/halmikas/alpha/addrsup.c576
-rw-r--r--private/ntos/nthals/halmikas/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/halmikas/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/halmikas/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/busdata.c138
-rw-r--r--private/ntos/nthals/halmikas/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halmikas/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halmikas/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halmikas/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halmikas/alpha/info.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halmikas/alpha/ioproc.c74
-rw-r--r--private/ntos/nthals/halmikas/alpha/iousage.c648
-rw-r--r--private/ntos/nthals/halmikas/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/halmikas/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halmikas/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/mikasa.h722
-rw-r--r--private/ntos/nthals/halmikas/alpha/mkinitnt.c1031
-rw-r--r--private/ntos/nthals/halmikas/alpha/mkintr.s115
-rw-r--r--private/ntos/nthals/halmikas/alpha/mkintsup.c827
-rw-r--r--private/ntos/nthals/halmikas/alpha/mkmapio.c219
-rw-r--r--private/ntos/nthals/halmikas/alpha/mksysint.c551
-rw-r--r--private/ntos/nthals/halmikas/alpha/pcibus.c100
-rw-r--r--private/ntos/nthals/halmikas/alpha/pciesc.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/pciir.c499
-rw-r--r--private/ntos/nthals/halmikas/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halmikas/alpha/pintolin.h219
-rw-r--r--private/ntos/nthals/halmikas/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halmikas/drivesup.c7
-rw-r--r--private/ntos/nthals/halmikas/hal.rc11
-rw-r--r--private/ntos/nthals/halmikas/hal.src7
-rw-r--r--private/ntos/nthals/halmikas/makefile6
-rw-r--r--private/ntos/nthals/halmikas/makefile.inc5
-rw-r--r--private/ntos/nthals/halmikas/sources105
-rw-r--r--private/ntos/nthals/halmps/bushnd.c7
-rw-r--r--private/ntos/nthals/halmps/dirs22
-rw-r--r--private/ntos/nthals/halmps/drivesup.c7
-rw-r--r--private/ntos/nthals/halmps/hal.rc11
-rw-r--r--private/ntos/nthals/halmps/i386/apic.inc283
-rw-r--r--private/ntos/nthals/halmps/i386/halnls.h5
-rw-r--r--private/ntos/nthals/halmps/i386/halp.h15
-rw-r--r--private/ntos/nthals/halmps/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halmps/i386/ixaddr.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halmps/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halmps/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halmps/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halmps/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halmps/i386/ixisabus.c6
-rw-r--r--private/ntos/nthals/halmps/i386/ixisasup.c7
-rw-r--r--private/ntos/nthals/halmps/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halmps/i386/ixmca.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixmca.h6
-rw-r--r--private/ntos/nthals/halmps/i386/ixmcaa.asm5
-rw-r--r--private/ntos/nthals/halmps/i386/ixmcabus.c8
-rw-r--r--private/ntos/nthals/halmps/i386/ixmcasup.c8
-rw-r--r--private/ntos/nthals/halmps/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixpcibrd.c7
-rw-r--r--private/ntos/nthals/halmps/i386/ixpcibus.c7
-rw-r--r--private/ntos/nthals/halmps/i386/ixpciint.c7
-rw-r--r--private/ntos/nthals/halmps/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halmps/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halmps/i386/mpaddr.c812
-rw-r--r--private/ntos/nthals/halmps/i386/mpclock.asm1000
-rw-r--r--private/ntos/nthals/halmps/i386/mpclockc.c167
-rw-r--r--private/ntos/nthals/halmps/i386/mpconfig.asm530
-rw-r--r--private/ntos/nthals/halmps/i386/mpdat.c280
-rw-r--r--private/ntos/nthals/halmps/i386/mpdebug.c683
-rw-r--r--private/ntos/nthals/halmps/i386/mpdetect.c522
-rw-r--r--private/ntos/nthals/halmps/i386/mphal.c683
-rw-r--r--private/ntos/nthals/halmps/i386/mpinfo.c61
-rw-r--r--private/ntos/nthals/halmps/i386/mpipi.asm1044
-rw-r--r--private/ntos/nthals/halmps/i386/mpirql.asm517
-rw-r--r--private/ntos/nthals/halmps/i386/mppciint.c529
-rw-r--r--private/ntos/nthals/halmps/i386/mpprofil.asm466
-rw-r--r--private/ntos/nthals/halmps/i386/mpspin.asm547
-rw-r--r--private/ntos/nthals/halmps/i386/mpsproc.c1117
-rw-r--r--private/ntos/nthals/halmps/i386/mpsproca.asm558
-rw-r--r--private/ntos/nthals/halmps/i386/mpswint.asm332
-rw-r--r--private/ntos/nthals/halmps/i386/mpsys.c1682
-rw-r--r--private/ntos/nthals/halmps/i386/mpsysbus.c341
-rw-r--r--private/ntos/nthals/halmps/i386/mpsysint.asm244
-rw-r--r--private/ntos/nthals/halmps/i386/pcip.h7
-rw-r--r--private/ntos/nthals/halmps/i386/pcmp.inc465
-rw-r--r--private/ntos/nthals/halmps/i386/pcmp_nt.inc560
-rw-r--r--private/ntos/nthals/halmps/i386/pcmpdtct.c581
-rw-r--r--private/ntos/nthals/halmps/i386/sources55
-rw-r--r--private/ntos/nthals/halmps/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halmps/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halmps/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halmps/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halmps/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halmps/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halmps/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halmps/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halmps/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halmps/mp/makefile6
-rw-r--r--private/ntos/nthals/halmps/mp/makefile.inc2
-rw-r--r--private/ntos/nthals/halmps/mp/sources56
-rw-r--r--private/ntos/nthals/halmps/mpmca/makefile6
-rw-r--r--private/ntos/nthals/halmps/mpmca/makefile.inc2
-rw-r--r--private/ntos/nthals/halmps/mpmca/sources57
-rw-r--r--private/ntos/nthals/halmps/rangesup.c7
-rw-r--r--private/ntos/nthals/halmps/up/makefile6
-rw-r--r--private/ntos/nthals/halmps/up/makefile.inc2
-rw-r--r--private/ntos/nthals/halmps/up/sources55
-rw-r--r--private/ntos/nthals/halmps/upmca/makefile6
-rw-r--r--private/ntos/nthals/halmps/upmca/makefile.inc2
-rw-r--r--private/ntos/nthals/halmps/upmca/sources56
-rw-r--r--private/ntos/nthals/halncr/drivesup.c7
-rw-r--r--private/ntos/nthals/halncr/hal.rc11
-rw-r--r--private/ntos/nthals/halncr/hal.src20
-rw-r--r--private/ntos/nthals/halncr/i386/halnls.h5
-rw-r--r--private/ntos/nthals/halncr/i386/halp.h5
-rw-r--r--private/ntos/nthals/halncr/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halncr/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halncr/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halncr/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halncr/i386/ixmca.h5
-rw-r--r--private/ntos/nthals/halncr/i386/ixmcabus.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixmcasup.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixpcibrd.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixprofil.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/ixstall.asm481
-rw-r--r--private/ntos/nthals/halncr/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/ixsysbus.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ncr.h94
-rw-r--r--private/ntos/nthals/halncr/i386/ncr.inc453
-rw-r--r--private/ntos/nthals/halncr/i386/ncrarb.h157
-rw-r--r--private/ntos/nthals/halncr/i386/ncrcat.c3223
-rw-r--r--private/ntos/nthals/halncr/i386/ncrcat.h308
-rw-r--r--private/ntos/nthals/halncr/i386/ncrcatlk.asm120
-rw-r--r--private/ntos/nthals/halncr/i386/ncrcatp.h232
-rw-r--r--private/ntos/nthals/halncr/i386/ncrclock.asm724
-rw-r--r--private/ntos/nthals/halncr/i386/ncrdetct.c5
-rw-r--r--private/ntos/nthals/halncr/i386/ncrhwsup.c170
-rw-r--r--private/ntos/nthals/halncr/i386/ncrintr.asm823
-rw-r--r--private/ntos/nthals/halncr/i386/ncrioacc.asm730
-rw-r--r--private/ntos/nthals/halncr/i386/ncripi.asm362
-rw-r--r--private/ntos/nthals/halncr/i386/ncrirql.asm1223
-rw-r--r--private/ntos/nthals/halncr/i386/ncrlarc.c392
-rw-r--r--private/ntos/nthals/halncr/i386/ncrlock.asm103
-rw-r--r--private/ntos/nthals/halncr/i386/ncrmcabs.c243
-rw-r--r--private/ntos/nthals/halncr/i386/ncrmem.h494
-rw-r--r--private/ntos/nthals/halncr/i386/ncrmp.c2443
-rw-r--r--private/ntos/nthals/halncr/i386/ncrnls.h62
-rw-r--r--private/ntos/nthals/halncr/i386/ncrnmi.c422
-rw-r--r--private/ntos/nthals/halncr/i386/ncrpsi.h291
-rw-r--r--private/ntos/nthals/halncr/i386/ncrqic.c329
-rw-r--r--private/ntos/nthals/halncr/i386/ncrstart.asm987
-rw-r--r--private/ntos/nthals/halncr/i386/ncrstop.c219
-rw-r--r--private/ntos/nthals/halncr/i386/ncrsus.c678
-rw-r--r--private/ntos/nthals/halncr/i386/ncrsus.h361
-rw-r--r--private/ntos/nthals/halncr/i386/ncrsyint.asm711
-rw-r--r--private/ntos/nthals/halncr/i386/pcip.h5
-rw-r--r--private/ntos/nthals/halncr/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halncr/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halncr/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halncr/makefile6
-rw-r--r--private/ntos/nthals/halncr/makefile.inc2
-rw-r--r--private/ntos/nthals/halncr/sources110
-rw-r--r--private/ntos/nthals/halnecmp/drivesup.c7
-rw-r--r--private/ntos/nthals/halnecmp/hal.rc11
-rw-r--r--private/ntos/nthals/halnecmp/hal.src7
-rw-r--r--private/ntos/nthals/halnecmp/makefile6
-rw-r--r--private/ntos/nthals/halnecmp/makefile.inc53
-rw-r--r--private/ntos/nthals/halnecmp/mips/allstart.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/cacherr.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/cirrus.h294
-rw-r--r--private/ntos/nthals/halnecmp/mips/cmdcnst.h105
-rw-r--r--private/ntos/nthals/halnecmp/mips/halp.h11
-rw-r--r--private/ntos/nthals/halnecmp/mips/j4cache.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/j4flshbf.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/j4flshio.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/j4prof.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxbeep.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxdisp.c2589
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxdmadsp.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxebsup.c1344
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxenvirv.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxhalp.h11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxhwsup.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxmapio.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxmaptb.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxport.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxreturn.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxsysint.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxtime.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/jxusage.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/mode542x.h1302
-rw-r--r--private/ntos/nthals/halnecmp/mips/modeset.h85
-rw-r--r--private/ntos/nthals/halnecmp/mips/x4clock.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/x4tb.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/x86bios.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/xxcalstl.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/xxclock.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/xxidle.s11
-rw-r--r--private/ntos/nthals/halnecmp/mips/xxinithl.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/xxinitnt.c11
-rw-r--r--private/ntos/nthals/halnecmp/mips/xxipiint.s11
-rw-r--r--private/ntos/nthals/halnecmp/sources91
-rw-r--r--private/ntos/nthals/halnonme/alpha/addrsup.c635
-rw-r--r--private/ntos/nthals/halnonme/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/halnonme/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/busdata.c126
-rw-r--r--private/ntos/nthals/halnonme/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halnonme/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ebinitnt.c762
-rw-r--r--private/ntos/nthals/halnonme/alpha/ebintsup.c448
-rw-r--r--private/ntos/nthals/halnonme/alpha/ebmapio.c158
-rw-r--r--private/ntos/nthals/halnonme/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ebsysint.c390
-rw-r--r--private/ntos/nthals/halnonme/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halnonme/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ev4parit.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halnonme/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halnonme/alpha/info.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halnonme/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/lca4.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/lca4err.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/lcaioacc.s7
-rw-r--r--private/ntos/nthals/halnonme/alpha/machdep.h43
-rw-r--r--private/ntos/nthals/halnonme/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/nondef.h137
-rw-r--r--private/ntos/nthals/halnonme/alpha/pcibus.c127
-rw-r--r--private/ntos/nthals/halnonme/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halnonme/alpha/pintolin.h175
-rw-r--r--private/ntos/nthals/halnonme/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halnonme/drivesup.c7
-rw-r--r--private/ntos/nthals/halnonme/hal.rc11
-rw-r--r--private/ntos/nthals/halnonme/hal.src7
-rw-r--r--private/ntos/nthals/halnonme/makefile6
-rw-r--r--private/ntos/nthals/halnonme/makefile.inc5
-rw-r--r--private/ntos/nthals/halnonme/sources101
-rw-r--r--private/ntos/nthals/halntp/bushnd.c11
-rw-r--r--private/ntos/nthals/halntp/drivesup.c11
-rw-r--r--private/ntos/nthals/halntp/hal.rc11
-rw-r--r--private/ntos/nthals/halntp/hal.src7
-rw-r--r--private/ntos/nthals/halntp/makefile6
-rw-r--r--private/ntos/nthals/halntp/makefile.inc5
-rw-r--r--private/ntos/nthals/halntp/mips/allstart.c71
-rw-r--r--private/ntos/nthals/halntp/mips/cacherr.s196
-rw-r--r--private/ntos/nthals/halntp/mips/faldef.h1542
-rw-r--r--private/ntos/nthals/halntp/mips/falnvram.h1075
-rw-r--r--private/ntos/nthals/halntp/mips/falreg.h393
-rw-r--r--private/ntos/nthals/halntp/mips/fxbusdat.c202
-rw-r--r--private/ntos/nthals/halntp/mips/fxdat.c73
-rw-r--r--private/ntos/nthals/halntp/mips/fxdisp.c1127
-rw-r--r--private/ntos/nthals/halntp/mips/fxerrlog.c1305
-rw-r--r--private/ntos/nthals/halntp/mips/fxhalp.h146
-rw-r--r--private/ntos/nthals/halntp/mips/fxhwsup.c3078
-rw-r--r--private/ntos/nthals/halntp/mips/fxinfo.c94
-rw-r--r--private/ntos/nthals/halntp/mips/fxintr.s141
-rw-r--r--private/ntos/nthals/halntp/mips/fxnvram.c30
-rw-r--r--private/ntos/nthals/halntp/mips/fxpcibrd.c825
-rw-r--r--private/ntos/nthals/halntp/mips/fxpcibus.c2595
-rw-r--r--private/ntos/nthals/halntp/mips/fxpmpsup.c11
-rw-r--r--private/ntos/nthals/halntp/mips/fxusage.c523
-rw-r--r--private/ntos/nthals/halntp/mips/halp.h538
-rw-r--r--private/ntos/nthals/halntp/mips/j4cache.s1804
-rw-r--r--private/ntos/nthals/halntp/mips/j4flshbf.s51
-rw-r--r--private/ntos/nthals/halntp/mips/j4flshio.c610
-rw-r--r--private/ntos/nthals/halntp/mips/j4prof.c316
-rw-r--r--private/ntos/nthals/halntp/mips/jxbeep.c143
-rw-r--r--private/ntos/nthals/halntp/mips/jxebsup.c1387
-rw-r--r--private/ntos/nthals/halntp/mips/jxenvirv.c679
-rw-r--r--private/ntos/nthals/halntp/mips/jxmapio.c264
-rw-r--r--private/ntos/nthals/halntp/mips/jxmaptb.c440
-rw-r--r--private/ntos/nthals/halntp/mips/jxport.c845
-rw-r--r--private/ntos/nthals/halntp/mips/jxreturn.c130
-rw-r--r--private/ntos/nthals/halntp/mips/jxsysint.c340
-rw-r--r--private/ntos/nthals/halntp/mips/jxtime.c285
-rw-r--r--private/ntos/nthals/halntp/mips/jxusage.c48
-rw-r--r--private/ntos/nthals/halntp/mips/modes.h182
-rw-r--r--private/ntos/nthals/halntp/mips/pcieisa.h326
-rw-r--r--private/ntos/nthals/halntp/mips/pcip.h140
-rw-r--r--private/ntos/nthals/halntp/mips/pmpsup.h69
-rw-r--r--private/ntos/nthals/halntp/mips/sidewind.h447
-rw-r--r--private/ntos/nthals/halntp/mips/vga.h343
-rw-r--r--private/ntos/nthals/halntp/mips/x4clock.s338
-rw-r--r--private/ntos/nthals/halntp/mips/x4tb.s109
-rw-r--r--private/ntos/nthals/halntp/mips/x86bios.c260
-rw-r--r--private/ntos/nthals/halntp/mips/xxcalstl.c273
-rw-r--r--private/ntos/nthals/halntp/mips/xxclock.c120
-rw-r--r--private/ntos/nthals/halntp/mips/xxidle.s75
-rw-r--r--private/ntos/nthals/halntp/mips/xxinithl.c774
-rw-r--r--private/ntos/nthals/halntp/mips/xxinitnt.c929
-rw-r--r--private/ntos/nthals/halntp/mips/xxipiint.s159
-rw-r--r--private/ntos/nthals/halntp/rangesup.c11
-rw-r--r--private/ntos/nthals/halntp/sources105
-rw-r--r--private/ntos/nthals/haloli/drivesup.c7
-rw-r--r--private/ntos/nthals/haloli/hal.rc11
-rw-r--r--private/ntos/nthals/haloli/hal.src7
-rw-r--r--private/ntos/nthals/haloli/i386/halnls.h5
-rw-r--r--private/ntos/nthals/haloli/i386/halp.h5
-rw-r--r--private/ntos/nthals/haloli/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/haloli/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/haloli/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/haloli/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/haloli/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixstall.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/haloli/i386/oliclock.asm1281
-rw-r--r--private/ntos/nthals/haloli/i386/olidtect.asm98
-rw-r--r--private/ntos/nthals/haloli/i386/oliipi.asm571
-rw-r--r--private/ntos/nthals/haloli/i386/oliirql.asm669
-rw-r--r--private/ntos/nthals/haloli/i386/olimapin.c168
-rw-r--r--private/ntos/nthals/haloli/i386/olimp.inc166
-rw-r--r--private/ntos/nthals/haloli/i386/oliproca.asm478
-rw-r--r--private/ntos/nthals/haloli/i386/olisproc.c581
-rw-r--r--private/ntos/nthals/haloli/i386/olisyint.asm386
-rw-r--r--private/ntos/nthals/haloli/i386/pcip.h5
-rw-r--r--private/ntos/nthals/haloli/i386/spspin.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/haloli/makefile6
-rw-r--r--private/ntos/nthals/haloli/makefile.inc2
-rw-r--r--private/ntos/nthals/haloli/sources96
-rw-r--r--private/ntos/nthals/halpinna/alpha/addrsup.c596
-rw-r--r--private/ntos/nthals/halpinna/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/busdata.c138
-rw-r--r--private/ntos/nthals/halpinna/alpha/cache.c1
-rw-r--r--private/ntos/nthals/halpinna/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halpinna/alpha/cia.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ciaaddr.c1
-rw-r--r--private/ntos/nthals/halpinna/alpha/ciaerr.c1636
-rw-r--r--private/ntos/nthals/halpinna/alpha/ciaio.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ev5ints.s6
-rw-r--r--private/ntos/nthals/halpinna/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/info.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halpinna/alpha/ioproc.c74
-rw-r--r--private/ntos/nthals/halpinna/alpha/iousage.c648
-rw-r--r--private/ntos/nthals/halpinna/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/halpinna/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halpinna/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/mikasa.h796
-rw-r--r--private/ntos/nthals/halpinna/alpha/mkinitnt.c970
-rw-r--r--private/ntos/nthals/halpinna/alpha/mkintsup.c1075
-rw-r--r--private/ntos/nthals/halpinna/alpha/mkmapio.c240
-rw-r--r--private/ntos/nthals/halpinna/alpha/mksysint.c545
-rw-r--r--private/ntos/nthals/halpinna/alpha/nvenv.c1
-rw-r--r--private/ntos/nthals/halpinna/alpha/nvram.c1
-rw-r--r--private/ntos/nthals/halpinna/alpha/pcibus.c100
-rw-r--r--private/ntos/nthals/halpinna/alpha/pciesc.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/pciir.c703
-rw-r--r--private/ntos/nthals/halpinna/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halpinna/alpha/pinnaerr.c157
-rw-r--r--private/ntos/nthals/halpinna/alpha/pintolin.h251
-rw-r--r--private/ntos/nthals/halpinna/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halpinna/drivesup.c7
-rw-r--r--private/ntos/nthals/halpinna/hal.rc11
-rw-r--r--private/ntos/nthals/halpinna/hal.src7
-rw-r--r--private/ntos/nthals/halpinna/makefile6
-rw-r--r--private/ntos/nthals/halpinna/makefile.inc7
-rw-r--r--private/ntos/nthals/halpinna/sources107
-rw-r--r--private/ntos/nthals/halppc/hal.rc11
-rw-r--r--private/ntos/nthals/halppc/makefile6
-rw-r--r--private/ntos/nthals/halppc/makefile.inc3
-rw-r--r--private/ntos/nthals/halppc/ppc/bbldef.h446
-rw-r--r--private/ntos/nthals/halppc/ppc/bblfont.h1499
-rw-r--r--private/ntos/nthals/halppc/ppc/bblrastz.h113
-rw-r--r--private/ntos/nthals/halppc/ppc/bblrmdac.h802
-rw-r--r--private/ntos/nthals/halppc/ppc/bldef.h144
-rw-r--r--private/ntos/nthals/halppc/ppc/blfw.h121
-rw-r--r--private/ntos/nthals/halppc/ppc/blrastz.h348
-rw-r--r--private/ntos/nthals/halppc/ppc/blrmdac.h152
-rw-r--r--private/ntos/nthals/halppc/ppc/fwdebug.h99
-rw-r--r--private/ntos/nthals/halppc/ppc/fwnvr.c2033
-rw-r--r--private/ntos/nthals/halppc/ppc/fwnvr.h313
-rw-r--r--private/ntos/nthals/halppc/ppc/fwstatus.h17
-rw-r--r--private/ntos/nthals/halppc/ppc/halp.h503
-rw-r--r--private/ntos/nthals/halppc/ppc/ibmppc.h60
-rw-r--r--private/ntos/nthals/halppc/ppc/pcip.h186
-rw-r--r--private/ntos/nthals/halppc/ppc/prepnvr.h134
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbbl.c1546
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbeep.c134
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbl.c1700
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbusdat.c200
-rw-r--r--private/ntos/nthals/halppc/ppc/pxcache.s1188
-rw-r--r--private/ntos/nthals/halppc/ppc/pxcalstl.c132
-rw-r--r--private/ntos/nthals/halppc/ppc/pxclksup.s153
-rw-r--r--private/ntos/nthals/halppc/ppc/pxclock.c283
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdakota.h67
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdat.c123
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdisp.c1733
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdisp.h360
-rw-r--r--private/ntos/nthals/halppc/ppc/pxds1585.h106
-rw-r--r--private/ntos/nthals/halppc/ppc/pxenviro.c170
-rw-r--r--private/ntos/nthals/halppc/ppc/pxfirsup.c1606
-rw-r--r--private/ntos/nthals/halppc/ppc/pxfirsup.h219
-rw-r--r--private/ntos/nthals/halppc/ppc/pxflshbf.s121
-rw-r--r--private/ntos/nthals/halppc/ppc/pxflshio.c197
-rw-r--r--private/ntos/nthals/halppc/ppc/pxhalp.h345
-rw-r--r--private/ntos/nthals/halppc/ppc/pxhwsup.c2188
-rw-r--r--private/ntos/nthals/halppc/ppc/pxidaho.h139
-rw-r--r--private/ntos/nthals/halppc/ppc/pxidle.c62
-rw-r--r--private/ntos/nthals/halppc/ppc/pxinfo.c213
-rw-r--r--private/ntos/nthals/halppc/ppc/pxinithl.c325
-rw-r--r--private/ntos/nthals/halppc/ppc/pxintmod.c79
-rw-r--r--private/ntos/nthals/halppc/ppc/pxintrpt.c105
-rw-r--r--private/ntos/nthals/halppc/ppc/pxintsup.s35
-rw-r--r--private/ntos/nthals/halppc/ppc/pxirql.c284
-rw-r--r--private/ntos/nthals/halppc/ppc/pxisabus.c133
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmapio.c124
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmemctl.c311
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmemctl.h38
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmisc.s159
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmp.h59
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmpic2.h309
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmpint.c323
-rw-r--r--private/ntos/nthals/halppc/ppc/pxnatsup.c80
-rw-r--r--private/ntos/nthals/halppc/ppc/pxnatsup.h57
-rw-r--r--private/ntos/nthals/halppc/ppc/pxp91.c1334
-rw-r--r--private/ntos/nthals/halppc/ppc/pxp91.h1380
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpcibrd.c1028
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpcibus.c2386
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpciint.c254
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpcisup.c326
-rw-r--r--private/ntos/nthals/halppc/ppc/pxport.c848
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpower.s123
-rw-r--r--private/ntos/nthals/halppc/ppc/pxproc.c212
-rw-r--r--private/ntos/nthals/halppc/ppc/pxprof.c268
-rw-r--r--private/ntos/nthals/halppc/ppc/pxreset.s455
-rw-r--r--private/ntos/nthals/halppc/ppc/pxreturn.c187
-rw-r--r--private/ntos/nthals/halppc/ppc/pxrtcsup.h28
-rw-r--r--private/ntos/nthals/halppc/ppc/pxs3.c677
-rw-r--r--private/ntos/nthals/halppc/ppc/pxs3.h445
-rw-r--r--private/ntos/nthals/halppc/ppc/pxshadbf.s37
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsiosup.c2218
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsiosup.h219
-rw-r--r--private/ntos/nthals/halppc/ppc/pxstall.s324
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsysbus.c111
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsysint.c227
-rw-r--r--private/ntos/nthals/halppc/ppc/pxtime.c386
-rw-r--r--private/ntos/nthals/halppc/ppc/pxusage.c499
-rw-r--r--private/ntos/nthals/halppc/ppc/pxvgaequ.h141
-rw-r--r--private/ntos/nthals/halppc/ppc/pxvm.c297
-rw-r--r--private/ntos/nthals/halppc/ppc/pxwd.c938
-rw-r--r--private/ntos/nthals/halppc/ppc/pxwd.h706
-rw-r--r--private/ntos/nthals/halppc/ppc/txtpalet.h97
-rw-r--r--private/ntos/nthals/halppc/ppc/x86bios.c359
-rw-r--r--private/ntos/nthals/halppc/sources106
-rw-r--r--private/ntos/nthals/halps/hal.rc11
-rw-r--r--private/ntos/nthals/halps/makefile6
-rw-r--r--private/ntos/nthals/halps/ppc/ctrlops.c1
-rw-r--r--private/ntos/nthals/halps/ppc/fwnvr.c1
-rw-r--r--private/ntos/nthals/halps/ppc/mk48time.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pcibios.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxbeep.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxbusdat.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxcache.s1
-rw-r--r--private/ntos/nthals/halps/ppc/pxcalstl.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxclksup.s1
-rw-r--r--private/ntos/nthals/halps/ppc/pxclock.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxdakota.h57
-rw-r--r--private/ntos/nthals/halps/ppc/pxdat.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxdisp.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxds1385.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxenviro.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxflshbf.s117
-rw-r--r--private/ntos/nthals/halps/ppc/pxflshio.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxhwsup.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxidle.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxinfo.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxinithl.c384
-rw-r--r--private/ntos/nthals/halps/ppc/pxintsup.s1
-rw-r--r--private/ntos/nthals/halps/ppc/pxirql.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxisabus.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxl2.s183
-rw-r--r--private/ntos/nthals/halps/ppc/pxmapio.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxmemctl.c1132
-rw-r--r--private/ntos/nthals/halps/ppc/pxmisc.s1
-rw-r--r--private/ntos/nthals/halps/ppc/pxpcibrd.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxpcibus.c2289
-rw-r--r--private/ntos/nthals/halps/ppc/pxpciint.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxpcisup.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxport.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxpower.s1
-rw-r--r--private/ntos/nthals/halps/ppc/pxproc.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxprof.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxreset.s433
-rw-r--r--private/ntos/nthals/halps/ppc/pxreturn.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxsiosup.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxstall.s1
-rw-r--r--private/ntos/nthals/halps/ppc/pxsysbus.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxsysint.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxsystyp.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxtime.c1
-rw-r--r--private/ntos/nthals/halps/ppc/pxusage.c1
-rw-r--r--private/ntos/nthals/halps/ppc/sysbios.c1
-rw-r--r--private/ntos/nthals/halps/ppc/x86bios.c1
-rw-r--r--private/ntos/nthals/halps/sources97
-rw-r--r--private/ntos/nthals/halqs/alpha/addrsup.c605
-rw-r--r--private/ntos/nthals/halqs/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/alphaio.s7
-rw-r--r--private/ntos/nthals/halqs/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/busdata.c126
-rw-r--r--private/ntos/nthals/halqs/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halqs/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/ebinitnt.c749
-rw-r--r--private/ntos/nthals/halqs/alpha/ebintsup.c449
-rw-r--r--private/ntos/nthals/halqs/alpha/ebmapio.c158
-rw-r--r--private/ntos/nthals/halqs/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/ebsysint.c394
-rw-r--r--private/ntos/nthals/halqs/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halqs/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halqs/alpha/ev4parit.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halqs/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halqs/alpha/info.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halqs/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/lca4.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/lca4err.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/lcaioacc.s7
-rw-r--r--private/ntos/nthals/halqs/alpha/machdep.h43
-rw-r--r--private/ntos/nthals/halqs/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/pcibus.c99
-rw-r--r--private/ntos/nthals/halqs/alpha/pcisio.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halqs/alpha/pintolin.h175
-rw-r--r--private/ntos/nthals/halqs/alpha/qsdef.h137
-rw-r--r--private/ntos/nthals/halqs/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halqs/drivesup.c7
-rw-r--r--private/ntos/nthals/halqs/hal.rc11
-rw-r--r--private/ntos/nthals/halqs/hal.src7
-rw-r--r--private/ntos/nthals/halqs/makefile6
-rw-r--r--private/ntos/nthals/halqs/makefile.inc5
-rw-r--r--private/ntos/nthals/halqs/sources102
-rw-r--r--private/ntos/nthals/halr94a/drivesup.c7
-rw-r--r--private/ntos/nthals/halr94a/hal.rc11
-rw-r--r--private/ntos/nthals/halr94a/hal.src7
-rw-r--r--private/ntos/nthals/halr94a/makefile6
-rw-r--r--private/ntos/nthals/halr94a/makefile.inc36
-rw-r--r--private/ntos/nthals/halr94a/mips/allstart.c276
-rw-r--r--private/ntos/nthals/halr94a/mips/busdat.c1231
-rw-r--r--private/ntos/nthals/halr94a/mips/cacherr.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/cirrus.h281
-rw-r--r--private/ntos/nthals/halr94a/mips/cmdcnst.h105
-rw-r--r--private/ntos/nthals/halr94a/mips/eisadumy.s70
-rw-r--r--private/ntos/nthals/halr94a/mips/esm.c1182
-rw-r--r--private/ntos/nthals/halr94a/mips/esmnvram.h688
-rw-r--r--private/ntos/nthals/halr94a/mips/glint.h580
-rw-r--r--private/ntos/nthals/halr94a/mips/halp.h367
-rw-r--r--private/ntos/nthals/halr94a/mips/j4cache.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/j4flshbf.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/j4flshio.c236
-rw-r--r--private/ntos/nthals/halr94a/mips/j4prof.c11
-rw-r--r--private/ntos/nthals/halr94a/mips/jxbeep.c215
-rw-r--r--private/ntos/nthals/halr94a/mips/jxdisp.c3605
-rw-r--r--private/ntos/nthals/halr94a/mips/jxdmadsp.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/jxebsup.c1398
-rw-r--r--private/ntos/nthals/halr94a/mips/jxenvirv.c800
-rw-r--r--private/ntos/nthals/halr94a/mips/jxhalp.h228
-rw-r--r--private/ntos/nthals/halr94a/mips/jxhwsup.c4265
-rw-r--r--private/ntos/nthals/halr94a/mips/jxmapio.c11
-rw-r--r--private/ntos/nthals/halr94a/mips/jxmaptb.c11
-rw-r--r--private/ntos/nthals/halr94a/mips/jxport.c11
-rw-r--r--private/ntos/nthals/halr94a/mips/jxreturn.c258
-rw-r--r--private/ntos/nthals/halr94a/mips/jxsysint.c355
-rw-r--r--private/ntos/nthals/halr94a/mips/jxtime.c377
-rw-r--r--private/ntos/nthals/halr94a/mips/jxusage.c510
-rw-r--r--private/ntos/nthals/halr94a/mips/mipsdat.c145
-rw-r--r--private/ntos/nthals/halr94a/mips/mode542x.h1302
-rw-r--r--private/ntos/nthals/halr94a/mips/modeset.h85
-rw-r--r--private/ntos/nthals/halr94a/mips/pcibrd.c1020
-rw-r--r--private/ntos/nthals/halr94a/mips/pcibus.c3585
-rw-r--r--private/ntos/nthals/halr94a/mips/pciint.c376
-rw-r--r--private/ntos/nthals/halr94a/mips/pcip.h200
-rw-r--r--private/ntos/nthals/halr94a/mips/pcisup.c632
-rw-r--r--private/ntos/nthals/halr94a/mips/r94adbg.c157
-rw-r--r--private/ntos/nthals/halr94a/mips/r94adef.h266
-rw-r--r--private/ntos/nthals/halr94a/mips/r94adma.h433
-rw-r--r--private/ntos/nthals/halr94a/mips/r94ainfo.c99
-rw-r--r--private/ntos/nthals/halr94a/mips/r94aint.h35
-rw-r--r--private/ntos/nthals/halr94a/mips/r94aio.s149
-rw-r--r--private/ntos/nthals/halr94a/mips/r94anmi.s621
-rw-r--r--private/ntos/nthals/halr94a/mips/rgb525.h468
-rw-r--r--private/ntos/nthals/halr94a/mips/tga.h93
-rw-r--r--private/ntos/nthals/halr94a/mips/x4clock.s433
-rw-r--r--private/ntos/nthals/halr94a/mips/x4tb.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/x86bios.c1261
-rw-r--r--private/ntos/nthals/halr94a/mips/xxcalstl.c302
-rw-r--r--private/ntos/nthals/halr94a/mips/xxclock.c11
-rw-r--r--private/ntos/nthals/halr94a/mips/xxidle.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/xxinithl.c959
-rw-r--r--private/ntos/nthals/halr94a/mips/xxinitnt.c11
-rw-r--r--private/ntos/nthals/halr94a/mips/xxipiint.s11
-rw-r--r--private/ntos/nthals/halr94a/mips/xxmvmem.s264
-rw-r--r--private/ntos/nthals/halr94a/sources131
-rw-r--r--private/ntos/nthals/halr96b/drivesup.c7
-rw-r--r--private/ntos/nthals/halr96b/hal.rc11
-rw-r--r--private/ntos/nthals/halr96b/hal.src7
-rw-r--r--private/ntos/nthals/halr96b/makefile6
-rw-r--r--private/ntos/nthals/halr96b/makefile.inc36
-rw-r--r--private/ntos/nthals/halr96b/mips/allstart.c272
-rw-r--r--private/ntos/nthals/halr96b/mips/busdat.c1231
-rw-r--r--private/ntos/nthals/halr96b/mips/cacherr.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/cirrus.h281
-rw-r--r--private/ntos/nthals/halr96b/mips/cmdcnst.h105
-rw-r--r--private/ntos/nthals/halr96b/mips/esm.c1182
-rw-r--r--private/ntos/nthals/halr96b/mips/esmnvram.h688
-rw-r--r--private/ntos/nthals/halr96b/mips/glint.h580
-rw-r--r--private/ntos/nthals/halr96b/mips/halp.h365
-rw-r--r--private/ntos/nthals/halr96b/mips/j4cache.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/j4flshbf.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/j4flshio.c236
-rw-r--r--private/ntos/nthals/halr96b/mips/j4prof.c11
-rw-r--r--private/ntos/nthals/halr96b/mips/jxbeep.c215
-rw-r--r--private/ntos/nthals/halr96b/mips/jxdisp.c3605
-rw-r--r--private/ntos/nthals/halr96b/mips/jxdmadsp.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/jxebsup.c1398
-rw-r--r--private/ntos/nthals/halr96b/mips/jxenvirv.c800
-rw-r--r--private/ntos/nthals/halr96b/mips/jxhalp.h224
-rw-r--r--private/ntos/nthals/halr96b/mips/jxhwsup.c4265
-rw-r--r--private/ntos/nthals/halr96b/mips/jxmapio.c11
-rw-r--r--private/ntos/nthals/halr96b/mips/jxmaptb.c11
-rw-r--r--private/ntos/nthals/halr96b/mips/jxport.c11
-rw-r--r--private/ntos/nthals/halr96b/mips/jxreturn.c258
-rw-r--r--private/ntos/nthals/halr96b/mips/jxsysint.c355
-rw-r--r--private/ntos/nthals/halr96b/mips/jxtime.c377
-rw-r--r--private/ntos/nthals/halr96b/mips/jxusage.c510
-rw-r--r--private/ntos/nthals/halr96b/mips/mipsdat.c145
-rw-r--r--private/ntos/nthals/halr96b/mips/mode542x.h1302
-rw-r--r--private/ntos/nthals/halr96b/mips/modeset.h85
-rw-r--r--private/ntos/nthals/halr96b/mips/pcibrd.c1020
-rw-r--r--private/ntos/nthals/halr96b/mips/pcibus.c3585
-rw-r--r--private/ntos/nthals/halr96b/mips/pciint.c376
-rw-r--r--private/ntos/nthals/halr96b/mips/pcip.h200
-rw-r--r--private/ntos/nthals/halr96b/mips/pcisup.c632
-rw-r--r--private/ntos/nthals/halr96b/mips/r94adbg.c157
-rw-r--r--private/ntos/nthals/halr96b/mips/r94adef.h266
-rw-r--r--private/ntos/nthals/halr96b/mips/r94adma.h433
-rw-r--r--private/ntos/nthals/halr96b/mips/r94ainfo.c99
-rw-r--r--private/ntos/nthals/halr96b/mips/r94aint.h35
-rw-r--r--private/ntos/nthals/halr96b/mips/r94aio.s149
-rw-r--r--private/ntos/nthals/halr96b/mips/r94anmi.s621
-rw-r--r--private/ntos/nthals/halr96b/mips/rgb525.h468
-rw-r--r--private/ntos/nthals/halr96b/mips/tga.h93
-rw-r--r--private/ntos/nthals/halr96b/mips/x4clock.s433
-rw-r--r--private/ntos/nthals/halr96b/mips/x4tb.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/x86bios.c1261
-rw-r--r--private/ntos/nthals/halr96b/mips/xxcalstl.c302
-rw-r--r--private/ntos/nthals/halr96b/mips/xxclock.c11
-rw-r--r--private/ntos/nthals/halr96b/mips/xxidle.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/xxinithl.c934
-rw-r--r--private/ntos/nthals/halr96b/mips/xxinitnt.c11
-rw-r--r--private/ntos/nthals/halr96b/mips/xxipiint.s11
-rw-r--r--private/ntos/nthals/halr96b/mips/xxmvmem.s264
-rw-r--r--private/ntos/nthals/halr96b/sources122
-rw-r--r--private/ntos/nthals/halr98b/drivesup.c7
-rw-r--r--private/ntos/nthals/halr98b/hal.rc11
-rw-r--r--private/ntos/nthals/halr98b/hal.src8
-rw-r--r--private/ntos/nthals/halr98b/makefile6
-rw-r--r--private/ntos/nthals/halr98b/makefile.inc5
-rw-r--r--private/ntos/nthals/halr98b/mips/allstart.c412
-rw-r--r--private/ntos/nthals/halr98b/mips/cacherr.h225
-rw-r--r--private/ntos/nthals/halr98b/mips/cacherr.s1435
-rw-r--r--private/ntos/nthals/halr98b/mips/cirrus.h298
-rw-r--r--private/ntos/nthals/halr98b/mips/cmdcnst.h105
-rw-r--r--private/ntos/nthals/halr98b/mips/esmnvram.h271
-rw-r--r--private/ntos/nthals/halr98b/mips/glint.h580
-rw-r--r--private/ntos/nthals/halr98b/mips/halp.h674
-rw-r--r--private/ntos/nthals/halr98b/mips/j4cache.s1190
-rw-r--r--private/ntos/nthals/halr98b/mips/j4flshbf.s58
-rw-r--r--private/ntos/nthals/halr98b/mips/j4flshio.c212
-rw-r--r--private/ntos/nthals/halr98b/mips/j4prof.c340
-rw-r--r--private/ntos/nthals/halr98b/mips/jxbeep.c131
-rw-r--r--private/ntos/nthals/halr98b/mips/jxdisp.c3544
-rw-r--r--private/ntos/nthals/halr98b/mips/jxebsup.c1178
-rw-r--r--private/ntos/nthals/halr98b/mips/jxenvirv.c691
-rw-r--r--private/ntos/nthals/halr98b/mips/jxmapio.c124
-rw-r--r--private/ntos/nthals/halr98b/mips/jxmaptb.c68
-rw-r--r--private/ntos/nthals/halr98b/mips/jxport.c779
-rw-r--r--private/ntos/nthals/halr98b/mips/jxreturn.c181
-rw-r--r--private/ntos/nthals/halr98b/mips/jxsysint.c327
-rw-r--r--private/ntos/nthals/halr98b/mips/jxtime.c319
-rw-r--r--private/ntos/nthals/halr98b/mips/jxusage.c541
-rw-r--r--private/ntos/nthals/halr98b/mips/mipsdat.c137
-rw-r--r--private/ntos/nthals/halr98b/mips/mode542x.h1302
-rw-r--r--private/ntos/nthals/halr98b/mips/modeset.h86
-rw-r--r--private/ntos/nthals/halr98b/mips/pcip.h189
-rw-r--r--private/ntos/nthals/halr98b/mips/r98bdef.h228
-rw-r--r--private/ntos/nthals/halr98b/mips/r98breg.h649
-rw-r--r--private/ntos/nthals/halr98b/mips/rgb525.h468
-rw-r--r--private/ntos/nthals/halr98b/mips/rxbusdat.c290
-rw-r--r--private/ntos/nthals/halr98b/mips/rxclock.s368
-rw-r--r--private/ntos/nthals/halr98b/mips/rxdisp.c61
-rw-r--r--private/ntos/nthals/halr98b/mips/rxdspt.c547
-rw-r--r--private/ntos/nthals/halr98b/mips/rxecc.c791
-rw-r--r--private/ntos/nthals/halr98b/mips/rxeif.c694
-rw-r--r--private/ntos/nthals/halr98b/mips/rxesm.c761
-rw-r--r--private/ntos/nthals/halr98b/mips/rxesm.h84
-rw-r--r--private/ntos/nthals/halr98b/mips/rxhalp.h212
-rw-r--r--private/ntos/nthals/halr98b/mips/rxhwlog.c1409
-rw-r--r--private/ntos/nthals/halr98b/mips/rxhwlog.h469
-rw-r--r--private/ntos/nthals/halr98b/mips/rxhwsup.c2124
-rw-r--r--private/ntos/nthals/halr98b/mips/rxinfo.c95
-rw-r--r--private/ntos/nthals/halr98b/mips/rxint.s1564
-rw-r--r--private/ntos/nthals/halr98b/mips/rxipiint.s79
-rw-r--r--private/ntos/nthals/halr98b/mips/rxisabus.c729
-rw-r--r--private/ntos/nthals/halr98b/mips/rxnvr.h176
-rw-r--r--private/ntos/nthals/halr98b/mips/rxpcibrd.c1157
-rw-r--r--private/ntos/nthals/halr98b/mips/rxpcibus.c2826
-rw-r--r--private/ntos/nthals/halr98b/mips/rxpciint.c615
-rw-r--r--private/ntos/nthals/halr98b/mips/rxsysbus.c214
-rw-r--r--private/ntos/nthals/halr98b/mips/tga.h101
-rw-r--r--private/ntos/nthals/halr98b/mips/x86bios.c1256
-rw-r--r--private/ntos/nthals/halr98b/mips/xxcalstl.c260
-rw-r--r--private/ntos/nthals/halr98b/mips/xxclock.c207
-rw-r--r--private/ntos/nthals/halr98b/mips/xxidle.s76
-rw-r--r--private/ntos/nthals/halr98b/mips/xxinithl.c894
-rw-r--r--private/ntos/nthals/halr98b/mips/xxinitnt.c424
-rw-r--r--private/ntos/nthals/halr98b/rangesup.c7
-rw-r--r--private/ntos/nthals/halr98b/sources107
-rw-r--r--private/ntos/nthals/halr98mp/drivesup.c7
-rw-r--r--private/ntos/nthals/halr98mp/hal.rc11
-rw-r--r--private/ntos/nthals/halr98mp/hal.src7
-rw-r--r--private/ntos/nthals/halr98mp/makefile6
-rw-r--r--private/ntos/nthals/halr98mp/makefile.inc5
-rw-r--r--private/ntos/nthals/halr98mp/mips/allstart.c200
-rw-r--r--private/ntos/nthals/halr98mp/mips/cacherr.s196
-rw-r--r--private/ntos/nthals/halr98mp/mips/cirrus.h298
-rw-r--r--private/ntos/nthals/halr98mp/mips/cmdcnst.h105
-rw-r--r--private/ntos/nthals/halr98mp/mips/esmnvram.h687
-rw-r--r--private/ntos/nthals/halr98mp/mips/halp.h708
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4cache.s1056
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4flshbf.s58
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4flshio.c238
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4prof.c362
-rw-r--r--private/ntos/nthals/halr98mp/mips/jazznvr.h164
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxbeep.c131
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxdisp.c3132
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxebsup.c1275
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxenvirv.c818
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxhalp.h99
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxmapio.c153
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxmaptb.c84
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxport.c897
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxreturn.c189
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxsysint.c454
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxtime.c313
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxusage.c497
-rw-r--r--private/ntos/nthals/halr98mp/mips/mipsdat.c144
-rw-r--r--private/ntos/nthals/halr98mp/mips/mode542x.h1302
-rw-r--r--private/ntos/nthals/halr98mp/mips/modeset.h86
-rw-r--r--private/ntos/nthals/halr98mp/mips/pcibrd.c1020
-rw-r--r--private/ntos/nthals/halr98mp/mips/pcip.h214
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98busdt.c1181
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98busdt.h142
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98clock.s471
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98def.h471
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98dspt.c704
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98eif.c801
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98esm.c1026
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98hal.h132
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98hwsup.c4771
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98info.c99
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98int.s522
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98ipint.s176
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98led.c252
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98pci.c289
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98pcibs.c3180
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98pcint.c384
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98reg.h475
-rw-r--r--private/ntos/nthals/halr98mp/mips/tga.h101
-rw-r--r--private/ntos/nthals/halr98mp/mips/x86bios.c2
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxcalstl.c290
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxclock.c131
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxidle.s76
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxinithl.c660
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxinitnt.c556
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxmemory.c184
-rw-r--r--private/ntos/nthals/halr98mp/sources103
-rw-r--r--private/ntos/nthals/halraw/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/as4000.h62
-rw-r--r--private/ntos/nthals/halraw/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/bitmap.c3007
-rw-r--r--private/ntos/nthals/halraw/alpha/bitmap.h252
-rw-r--r--private/ntos/nthals/halraw/alpha/busdata.c137
-rw-r--r--private/ntos/nthals/halraw/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/drivesup.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/eeprom8k.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/eisaprof.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/info.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/inithal.c1126
-rw-r--r--private/ntos/nthals/halraw/alpha/intsup.s256
-rw-r--r--private/ntos/nthals/halraw/alpha/iod.c1467
-rw-r--r--private/ntos/nthals/halraw/alpha/iod.h1669
-rw-r--r--private/ntos/nthals/halraw/alpha/iodaddr.c731
-rw-r--r--private/ntos/nthals/halraw/alpha/ioderr.c2304
-rw-r--r--private/ntos/nthals/halraw/alpha/iodio.s2997
-rw-r--r--private/ntos/nthals/halraw/alpha/iodmapio.c163
-rw-r--r--private/ntos/nthals/halraw/alpha/ioproc.c75
-rw-r--r--private/ntos/nthals/halraw/alpha/iousage.c647
-rw-r--r--private/ntos/nthals/halraw/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/halraw/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halraw/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/nvenv.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/nvram.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pcibus.c146
-rw-r--r--private/ntos/nthals/halraw/alpha/pciesc.c489
-rw-r--r--private/ntos/nthals/halraw/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pcrtc.c383
-rw-r--r--private/ntos/nthals/halraw/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/perf8254.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pintolin.h214
-rw-r--r--private/ntos/nthals/halraw/alpha/rawerr.c154
-rw-r--r--private/ntos/nthals/halraw/alpha/rawerror.h301
-rw-r--r--private/ntos/nthals/halraw/alpha/rawhide.h349
-rw-r--r--private/ntos/nthals/halraw/alpha/rwclock.c308
-rw-r--r--private/ntos/nthals/halraw/alpha/rwinitnt.c1324
-rw-r--r--private/ntos/nthals/halraw/alpha/rwintbal.c1762
-rw-r--r--private/ntos/nthals/halraw/alpha/rwintbal.h200
-rw-r--r--private/ntos/nthals/halraw/alpha/rwintsup.c2364
-rw-r--r--private/ntos/nthals/halraw/alpha/rwref.h109
-rw-r--r--private/ntos/nthals/halraw/alpha/rwsysint.c501
-rw-r--r--private/ntos/nthals/halraw/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halraw/bushnd.c7
-rw-r--r--private/ntos/nthals/halraw/dirs24
-rw-r--r--private/ntos/nthals/halraw/drivesup.c7
-rw-r--r--private/ntos/nthals/halraw/hal.rc11
-rw-r--r--private/ntos/nthals/halraw/hal.src7
-rw-r--r--private/ntos/nthals/halraw/mp/makefile6
-rw-r--r--private/ntos/nthals/halraw/mp/makefile.inc5
-rw-r--r--private/ntos/nthals/halraw/mp/sources109
-rw-r--r--private/ntos/nthals/halraw/up/makefile6
-rw-r--r--private/ntos/nthals/halraw/up/makefile.inc5
-rw-r--r--private/ntos/nthals/halraw/up/sources109
-rw-r--r--private/ntos/nthals/halsable/alpha/addrsup.c883
-rw-r--r--private/ntos/nthals/halsable/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/alphaio.s1332
-rw-r--r--private/ntos/nthals/halsable/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/busdata.c136
-rw-r--r--private/ntos/nthals/halsable/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halsable/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/eeprom8k.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4parit.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/icic.c94
-rw-r--r--private/ntos/nthals/halsable/alpha/icic.h62
-rw-r--r--private/ntos/nthals/halsable/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/info.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/lyintsup.c517
-rw-r--r--private/ntos/nthals/halsable/alpha/lyintsup.h50
-rw-r--r--private/ntos/nthals/halsable/alpha/lynxref.h111
-rw-r--r--private/ntos/nthals/halsable/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halsable/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcibus.c118
-rw-r--r--private/ntos/nthals/halsable/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcrtc.h102
-rw-r--r--private/ntos/nthals/halsable/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/perf8254.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pintolin.h544
-rw-r--r--private/ntos/nthals/halsable/alpha/sable.h519
-rw-r--r--private/ntos/nthals/halsable/alpha/sableerr.c2081
-rw-r--r--private/ntos/nthals/halsable/alpha/sableio.s956
-rw-r--r--private/ntos/nthals/halsable/alpha/sableref.h280
-rw-r--r--private/ntos/nthals/halsable/alpha/sablertc.h194
-rw-r--r--private/ntos/nthals/halsable/alpha/sbinitnt.c1292
-rw-r--r--private/ntos/nthals/halsable/alpha/sbintr.s94
-rw-r--r--private/ntos/nthals/halsable/alpha/sbintsup.c113
-rw-r--r--private/ntos/nthals/halsable/alpha/sbmapio.c205
-rw-r--r--private/ntos/nthals/halsable/alpha/sbsysint.c456
-rw-r--r--private/ntos/nthals/halsable/alpha/siintsup.c1332
-rw-r--r--private/ntos/nthals/halsable/alpha/siintsup.h50
-rw-r--r--private/ntos/nthals/halsable/alpha/t2.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/xiintsup.c912
-rw-r--r--private/ntos/nthals/halsable/alpha/xiintsup.h50
-rw-r--r--private/ntos/nthals/halsable/alpha/xioref.h148
-rw-r--r--private/ntos/nthals/halsable/bushnd.c7
-rw-r--r--private/ntos/nthals/halsable/dirs24
-rw-r--r--private/ntos/nthals/halsable/drivesup.c7
-rw-r--r--private/ntos/nthals/halsable/hal.rc11
-rw-r--r--private/ntos/nthals/halsable/hal.src7
-rw-r--r--private/ntos/nthals/halsable/mp/makefile6
-rw-r--r--private/ntos/nthals/halsable/mp/makefile.inc5
-rw-r--r--private/ntos/nthals/halsable/mp/sources107
-rw-r--r--private/ntos/nthals/halsable/up/makefile6
-rw-r--r--private/ntos/nthals/halsable/up/makefile.inc5
-rw-r--r--private/ntos/nthals/halsable/up/sources107
-rw-r--r--private/ntos/nthals/halsgi/drivesup.c7
-rw-r--r--private/ntos/nthals/halsgi/hal.rc11
-rw-r--r--private/ntos/nthals/halsgi/hal.src7
-rw-r--r--private/ntos/nthals/halsgi/makefile6
-rw-r--r--private/ntos/nthals/halsgi/makefile.inc6
-rw-r--r--private/ntos/nthals/halsgi/mips/allstart.c56
-rw-r--r--private/ntos/nthals/halsgi/mips/halp.h134
-rw-r--r--private/ntos/nthals/halsgi/mips/s4cache.s1192
-rw-r--r--private/ntos/nthals/halsgi/mips/s4flshio.c208
-rw-r--r--private/ntos/nthals/halsgi/mips/s4prof.c291
-rw-r--r--private/ntos/nthals/halsgi/mips/sxbeep.c50
-rw-r--r--private/ntos/nthals/halsgi/mips/sxdisp.c1384
-rw-r--r--private/ntos/nthals/halsgi/mips/sxenvirv.c610
-rw-r--r--private/ntos/nthals/halsgi/mips/sxflshbf.s76
-rw-r--r--private/ntos/nthals/halsgi/mips/sxhwsup.c2387
-rw-r--r--private/ntos/nthals/halsgi/mips/sxmapio.c61
-rw-r--r--private/ntos/nthals/halsgi/mips/sxmaptb.c54
-rw-r--r--private/ntos/nthals/halsgi/mips/sxport.c294
-rw-r--r--private/ntos/nthals/halsgi/mips/sxreturn.c80
-rw-r--r--private/ntos/nthals/halsgi/mips/sxsysint.c294
-rw-r--r--private/ntos/nthals/halsgi/mips/sxtime.c281
-rw-r--r--private/ntos/nthals/halsgi/mips/sxusage.c48
-rw-r--r--private/ntos/nthals/halsgi/mips/x4clock.s210
-rw-r--r--private/ntos/nthals/halsgi/mips/x4tb.s5
-rw-r--r--private/ntos/nthals/halsgi/mips/x86bios.c65
-rw-r--r--private/ntos/nthals/halsgi/mips/xxcalstl.c299
-rw-r--r--private/ntos/nthals/halsgi/mips/xxclock.c64
-rw-r--r--private/ntos/nthals/halsgi/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halsgi/mips/xxinithl.c237
-rw-r--r--private/ntos/nthals/halsgi/mips/xxinitnt.c220
-rw-r--r--private/ntos/nthals/halsgi/sources87
-rw-r--r--private/ntos/nthals/halsni4x/drivesup.c7
-rw-r--r--private/ntos/nthals/halsni4x/hal.rc17
-rw-r--r--private/ntos/nthals/halsni4x/hal.src7
-rw-r--r--private/ntos/nthals/halsni4x/makefile6
-rw-r--r--private/ntos/nthals/halsni4x/makefile.inc5
-rw-r--r--private/ntos/nthals/halsni4x/mips/allstart.c59
-rw-r--r--private/ntos/nthals/halsni4x/mips/cacherr.s196
-rw-r--r--private/ntos/nthals/halsni4x/mips/deskdef.h93
-rw-r--r--private/ntos/nthals/halsni4x/mips/duocache.s774
-rw-r--r--private/ntos/nthals/halsni4x/mips/halp.h161
-rw-r--r--private/ntos/nthals/halsni4x/mips/i82c54.h34
-rw-r--r--private/ntos/nthals/halsni4x/mips/j4cache.s1064
-rw-r--r--private/ntos/nthals/halsni4x/mips/j4flshbf.s53
-rw-r--r--private/ntos/nthals/halsni4x/mips/j4flshio.c202
-rw-r--r--private/ntos/nthals/halsni4x/mips/j4prof.c325
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxbeep.c132
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxebsup.c2851
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxenvirv.c192
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxhwsup.c2437
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxmapio.c133
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxport.c805
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxreturn.c239
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxsysint.c380
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxtime.c334
-rw-r--r--private/ntos/nthals/halsni4x/mips/jxusage.c47
-rw-r--r--private/ntos/nthals/halsni4x/mips/minidef.h141
-rw-r--r--private/ntos/nthals/halsni4x/mips/mpagent.c681
-rw-r--r--private/ntos/nthals/halsni4x/mips/mpagent.h535
-rw-r--r--private/ntos/nthals/halsni4x/mips/orcache.s628
-rw-r--r--private/ntos/nthals/halsni4x/mips/r4intdsp.c1052
-rw-r--r--private/ntos/nthals/halsni4x/mips/snidef.h215
-rw-r--r--private/ntos/nthals/halsni4x/mips/snidisp.c1475
-rw-r--r--private/ntos/nthals/halsni4x/mips/snihalp.h338
-rw-r--r--private/ntos/nthals/halsni4x/mips/sniregs.h139
-rw-r--r--private/ntos/nthals/halsni4x/mips/unicache.s1098
-rw-r--r--private/ntos/nthals/halsni4x/mips/vgadata.h406
-rw-r--r--private/ntos/nthals/halsni4x/mips/x4clock.s325
-rw-r--r--private/ntos/nthals/halsni4x/mips/x4misc.s472
-rw-r--r--private/ntos/nthals/halsni4x/mips/x4tb.s110
-rw-r--r--private/ntos/nthals/halsni4x/mips/x86bios.c191
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxcache.c399
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxcalstl.c270
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxclock.c233
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxidle.s78
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxinithl.c746
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxinitnt.c369
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxipiint.s56
-rw-r--r--private/ntos/nthals/halsni4x/mips/xxmemory.c179
-rw-r--r--private/ntos/nthals/halsni4x/sources91
-rw-r--r--private/ntos/nthals/halsnip/hal.rc17
-rw-r--r--private/ntos/nthals/halsnip/hal.src7
-rw-r--r--private/ntos/nthals/halsnip/makefile6
-rw-r--r--private/ntos/nthals/halsnip/makefile.inc5
-rw-r--r--private/ntos/nthals/halsnip/mips/allstart.c65
-rw-r--r--private/ntos/nthals/halsnip/mips/cacherr.s645
-rw-r--r--private/ntos/nthals/halsnip/mips/duocache.s780
-rw-r--r--private/ntos/nthals/halsnip/mips/halp.h280
-rw-r--r--private/ntos/nthals/halsnip/mips/i82c54.h34
-rw-r--r--private/ntos/nthals/halsnip/mips/j4flshbf.s53
-rw-r--r--private/ntos/nthals/halsnip/mips/j4flshio.c199
-rw-r--r--private/ntos/nthals/halsnip/mips/j4prof.c316
-rw-r--r--private/ntos/nthals/halsnip/mips/jxbeep.c132
-rw-r--r--private/ntos/nthals/halsnip/mips/jxebsup.c2760
-rw-r--r--private/ntos/nthals/halsnip/mips/jxenvirv.c192
-rw-r--r--private/ntos/nthals/halsnip/mips/jxhwsup.c2250
-rw-r--r--private/ntos/nthals/halsnip/mips/jxmapio.c120
-rw-r--r--private/ntos/nthals/halsnip/mips/jxport.c805
-rw-r--r--private/ntos/nthals/halsnip/mips/jxreturn.c286
-rw-r--r--private/ntos/nthals/halsnip/mips/jxsysint.c335
-rw-r--r--private/ntos/nthals/halsnip/mips/jxtime.c359
-rw-r--r--private/ntos/nthals/halsnip/mips/jxusage.c47
-rw-r--r--private/ntos/nthals/halsnip/mips/mpagent.c745
-rw-r--r--private/ntos/nthals/halsnip/mips/mpagent.h594
-rw-r--r--private/ntos/nthals/halsnip/mips/orcache.s561
-rw-r--r--private/ntos/nthals/halsnip/mips/r4intdsp.c1307
-rw-r--r--private/ntos/nthals/halsnip/mips/snidef.h225
-rw-r--r--private/ntos/nthals/halsnip/mips/snidisp.c1201
-rw-r--r--private/ntos/nthals/halsnip/mips/snihalp.h422
-rw-r--r--private/ntos/nthals/halsnip/mips/snipbus.c2051
-rw-r--r--private/ntos/nthals/halsnip/mips/snipbus.h104
-rw-r--r--private/ntos/nthals/halsnip/mips/snipci.h366
-rw-r--r--private/ntos/nthals/halsnip/mips/sniregs.h139
-rw-r--r--private/ntos/nthals/halsnip/mips/unicache.s1155
-rw-r--r--private/ntos/nthals/halsnip/mips/vgadata.h420
-rw-r--r--private/ntos/nthals/halsnip/mips/x4clock.s457
-rw-r--r--private/ntos/nthals/halsnip/mips/x4misc.s410
-rw-r--r--private/ntos/nthals/halsnip/mips/x4tb.s110
-rw-r--r--private/ntos/nthals/halsnip/mips/x86bios.c191
-rw-r--r--private/ntos/nthals/halsnip/mips/xxcache.c346
-rw-r--r--private/ntos/nthals/halsnip/mips/xxcache.h30
-rw-r--r--private/ntos/nthals/halsnip/mips/xxcalstl.c278
-rw-r--r--private/ntos/nthals/halsnip/mips/xxclock.c277
-rw-r--r--private/ntos/nthals/halsnip/mips/xxerror.c293
-rw-r--r--private/ntos/nthals/halsnip/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halsnip/mips/xxinithl.c695
-rw-r--r--private/ntos/nthals/halsnip/mips/xxinitnt.c345
-rw-r--r--private/ntos/nthals/halsnip/mips/xxipiint.s56
-rw-r--r--private/ntos/nthals/halsnip/mips/xxmemory.c246
-rw-r--r--private/ntos/nthals/halsnip/sources92
-rw-r--r--private/ntos/nthals/halsp/drivesup.c7
-rw-r--r--private/ntos/nthals/halsp/hal.rc11
-rw-r--r--private/ntos/nthals/halsp/hal.src7
-rw-r--r--private/ntos/nthals/halsp/i386/halnls.h5
-rw-r--r--private/ntos/nthals/halsp/i386/halp.h5
-rw-r--r--private/ntos/nthals/halsp/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halsp/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halsp/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halsp/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halsp/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halsp/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halsp/i386/ixmca.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixmcaa.asm5
-rw-r--r--private/ntos/nthals/halsp/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixpcibrd.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixstall.asm5
-rw-r--r--private/ntos/nthals/halsp/i386/ixsysbus.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halsp/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halsp/i386/pcip.h5
-rw-r--r--private/ntos/nthals/halsp/i386/spacer.c227
-rw-r--r--private/ntos/nthals/halsp/i386/spacer.h193
-rw-r--r--private/ntos/nthals/halsp/i386/spbeep.asm246
-rw-r--r--private/ntos/nthals/halsp/i386/spclock.asm1096
-rw-r--r--private/ntos/nthals/halsp/i386/spdetect.asm559
-rw-r--r--private/ntos/nthals/halsp/i386/spipi.asm750
-rw-r--r--private/ntos/nthals/halsp/i386/spirql.asm799
-rw-r--r--private/ntos/nthals/halsp/i386/spmp.inc258
-rw-r--r--private/ntos/nthals/halsp/i386/spprofil.asm453
-rw-r--r--private/ntos/nthals/halsp/i386/spreboot.asm151
-rw-r--r--private/ntos/nthals/halsp/i386/spspin.asm382
-rw-r--r--private/ntos/nthals/halsp/i386/spsproc.c501
-rw-r--r--private/ntos/nthals/halsp/i386/spsproca.asm373
-rw-r--r--private/ntos/nthals/halsp/i386/spswint.asm325
-rw-r--r--private/ntos/nthals/halsp/i386/spsysbus.c249
-rw-r--r--private/ntos/nthals/halsp/i386/spsysint.asm393
-rw-r--r--private/ntos/nthals/halsp/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halsp/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halsp/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halsp/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halsp/makefile6
-rw-r--r--private/ntos/nthals/halsp/makefile.inc2
-rw-r--r--private/ntos/nthals/halsp/sources106
-rw-r--r--private/ntos/nthals/haltimbr/alpha/28f008sa.c1
-rw-r--r--private/ntos/nthals/haltimbr/alpha/29f040.c1
-rw-r--r--private/ntos/nthals/haltimbr/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/bios.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/busdata.c125
-rw-r--r--private/ntos/nthals/haltimbr/alpha/cache.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/cia.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ciaaddr.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ciaerr.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ciaio.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ciamapio.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/eb164.h120
-rw-r--r--private/ntos/nthals/haltimbr/alpha/eb164err.c122
-rw-r--r--private/ntos/nthals/haltimbr/alpha/eb164io.s139
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ebinitnt.c658
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ebintsup.c619
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ebsgdma.c6
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ebsysint.c425
-rw-r--r--private/ntos/nthals/haltimbr/alpha/eisasup.c6
-rw-r--r--private/ntos/nthals/haltimbr/alpha/environ.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/flash8k.c1
-rw-r--r--private/ntos/nthals/haltimbr/alpha/flashdrv.c3
-rw-r--r--private/ntos/nthals/haltimbr/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/idle.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/info.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/inithal.c6
-rw-r--r--private/ntos/nthals/haltimbr/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/haltimbr/alpha/memory.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/nvenv.c1
-rw-r--r--private/ntos/nthals/haltimbr/alpha/nvram.c1
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pcibus.c6
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pcisio.c493
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pcisup.c6
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/haltimbr/alpha/pintolin.h174
-rw-r--r--private/ntos/nthals/haltimbr/alpha/vga.c7
-rw-r--r--private/ntos/nthals/haltimbr/drivesup.c7
-rw-r--r--private/ntos/nthals/haltimbr/hal.rc11
-rw-r--r--private/ntos/nthals/haltimbr/hal.src7
-rw-r--r--private/ntos/nthals/haltimbr/makefile6
-rw-r--r--private/ntos/nthals/haltimbr/makefile.inc5
-rw-r--r--private/ntos/nthals/haltimbr/sources109
-rw-r--r--private/ntos/nthals/haltyne/drivesup.c7
-rw-r--r--private/ntos/nthals/haltyne/hal.rc11
-rw-r--r--private/ntos/nthals/haltyne/hal.src7
-rw-r--r--private/ntos/nthals/haltyne/makefile6
-rw-r--r--private/ntos/nthals/haltyne/makefile.inc6
-rw-r--r--private/ntos/nthals/haltyne/mips/allstart.c56
-rw-r--r--private/ntos/nthals/haltyne/mips/dtidef.h112
-rw-r--r--private/ntos/nthals/haltyne/mips/halp.h154
-rw-r--r--private/ntos/nthals/haltyne/mips/j4cache.s1326
-rw-r--r--private/ntos/nthals/haltyne/mips/j4flshbf.s61
-rw-r--r--private/ntos/nthals/haltyne/mips/j4flshio.c166
-rw-r--r--private/ntos/nthals/haltyne/mips/j4prof.c291
-rw-r--r--private/ntos/nthals/haltyne/mips/jxbeep.c125
-rw-r--r--private/ntos/nthals/haltyne/mips/jxdisp.c249
-rw-r--r--private/ntos/nthals/haltyne/mips/jxebsup.c2182
-rw-r--r--private/ntos/nthals/haltyne/mips/jxenvirv.c98
-rw-r--r--private/ntos/nthals/haltyne/mips/jxhalp.h105
-rw-r--r--private/ntos/nthals/haltyne/mips/jxhwsup.c1882
-rw-r--r--private/ntos/nthals/haltyne/mips/jxmapio.c139
-rw-r--r--private/ntos/nthals/haltyne/mips/jxport.c878
-rw-r--r--private/ntos/nthals/haltyne/mips/jxreturn.c90
-rw-r--r--private/ntos/nthals/haltyne/mips/jxsysint.c259
-rw-r--r--private/ntos/nthals/haltyne/mips/jxtime.c285
-rw-r--r--private/ntos/nthals/haltyne/mips/jxusage.c48
-rw-r--r--private/ntos/nthals/haltyne/mips/x4clock.s210
-rw-r--r--private/ntos/nthals/haltyne/mips/x4tb.s109
-rw-r--r--private/ntos/nthals/haltyne/mips/x86bios.c262
-rw-r--r--private/ntos/nthals/haltyne/mips/x86bios.h75
-rw-r--r--private/ntos/nthals/haltyne/mips/x86lator.c5881
-rw-r--r--private/ntos/nthals/haltyne/mips/xxcalstl.c291
-rw-r--r--private/ntos/nthals/haltyne/mips/xxclock.c174
-rw-r--r--private/ntos/nthals/haltyne/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/haltyne/mips/xxinithl.c212
-rw-r--r--private/ntos/nthals/haltyne/mips/xxinitnt.c158
-rw-r--r--private/ntos/nthals/haltyne/sources84
-rw-r--r--private/ntos/nthals/halvict/hal.rc11
-rw-r--r--private/ntos/nthals/halvict/makefile6
-rw-r--r--private/ntos/nthals/halvict/ppc/fwnvr.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbbl.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbeep.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbl.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbusdat.c281
-rw-r--r--private/ntos/nthals/halvict/ppc/pxcache.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxcalstl.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxclksup.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxclock.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxdat.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxdisp.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxenviro.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxfirsup.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxflshbf.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxflshio.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxhwsup.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxidle.c85
-rw-r--r--private/ntos/nthals/halvict/ppc/pxinfo.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxinithl.c506
-rw-r--r--private/ntos/nthals/halvict/ppc/pxintrpt.c1505
-rw-r--r--private/ntos/nthals/halvict/ppc/pxintrpt.h103
-rw-r--r--private/ntos/nthals/halvict/ppc/pxirql.c337
-rw-r--r--private/ntos/nthals/halvict/ppc/pxisabus.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmapio.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmemctl.c706
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmemctl.h143
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmisc.s2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxnatsup.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxp91.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpcibrd.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpcibus.c2318
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpciint.c290
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpcisup.c708
-rw-r--r--private/ntos/nthals/halvict/ppc/pxport.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpower.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxproc.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxprof.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxreset.s557
-rw-r--r--private/ntos/nthals/halvict/ppc/pxreturn.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxs3.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxshadbf.s2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxstall.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxsysbus.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxtime.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxusage.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxvm.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxwd.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/x86bios.c1
-rw-r--r--private/ntos/nthals/halvict/sources107
-rw-r--r--private/ntos/nthals/halwood/hal.rc11
-rw-r--r--private/ntos/nthals/halwood/makefile6
-rw-r--r--private/ntos/nthals/halwood/ppc/fwnvr.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxbeep.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxbusdat.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxcache.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxcalstl.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxclksup.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxclock.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxdat.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxdisp.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxenviro.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxflshbf.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxflshio.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxhwsup.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxidle.c62
-rw-r--r--private/ntos/nthals/halwood/ppc/pxinfo.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxinithl.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxintmod.c78
-rw-r--r--private/ntos/nthals/halwood/ppc/pxintrpt.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxintsup.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxirql.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxisabus.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxmapio.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxmemctl.c338
-rw-r--r--private/ntos/nthals/halwood/ppc/pxmemctl.h36
-rw-r--r--private/ntos/nthals/halwood/ppc/pxnatsup.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpcibrd.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpcibus.c2404
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpciint.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpcisup.c259
-rw-r--r--private/ntos/nthals/halwood/ppc/pxport.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpower.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxproc.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxprof.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxreset.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxreturn.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxs3.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxshadbf.s2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxsiosup.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxstall.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxsysbus.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxsysint.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxtime.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxusage.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxwd.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/wdvga.c745
-rw-r--r--private/ntos/nthals/halwood/ppc/x86bios.c1
-rw-r--r--private/ntos/nthals/halwood/sources103
-rw-r--r--private/ntos/nthals/halws3/drivesup.c7
-rw-r--r--private/ntos/nthals/halws3/hal.rc11
-rw-r--r--private/ntos/nthals/halws3/hal.src7
-rw-r--r--private/ntos/nthals/halws3/i386/apic.inc556
-rw-r--r--private/ntos/nthals/halws3/i386/halp.h5
-rw-r--r--private/ntos/nthals/halws3/i386/halver.h42
-rw-r--r--private/ntos/nthals/halws3/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halws3/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halws3/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halws3/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halws3/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halws3/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halws3/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halws3/i386/w3.inc341
-rw-r--r--private/ntos/nthals/halws3/i386/w3clock.asm782
-rw-r--r--private/ntos/nthals/halws3/i386/w3detect.asm106
-rw-r--r--private/ntos/nthals/halws3/i386/w3hal.c660
-rw-r--r--private/ntos/nthals/halws3/i386/w3ipi.asm955
-rw-r--r--private/ntos/nthals/halws3/i386/w3irql.asm776
-rw-r--r--private/ntos/nthals/halws3/i386/w3nmi.c78
-rw-r--r--private/ntos/nthals/halws3/i386/w3profil.asm223
-rw-r--r--private/ntos/nthals/halws3/i386/w3space.asm1346
-rw-r--r--private/ntos/nthals/halws3/i386/w3spin.asm389
-rw-r--r--private/ntos/nthals/halws3/i386/w3sproc.c710
-rw-r--r--private/ntos/nthals/halws3/i386/w3sproca.asm377
-rw-r--r--private/ntos/nthals/halws3/i386/w3stall.asm382
-rw-r--r--private/ntos/nthals/halws3/i386/w3swint.asm317
-rw-r--r--private/ntos/nthals/halws3/i386/w3swint.bak267
-rw-r--r--private/ntos/nthals/halws3/i386/w3sysbus.c233
-rw-r--r--private/ntos/nthals/halws3/i386/w3sysint.asm613
-rw-r--r--private/ntos/nthals/halws3/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halws3/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halws3/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halws3/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halws3/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halws3/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halws3/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halws3/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halws3/makefile6
-rw-r--r--private/ntos/nthals/halws3/makefile.inc2
-rw-r--r--private/ntos/nthals/halws3/sources98
-rw-r--r--private/ntos/nthals/halwyse7/drivesup.c7
-rw-r--r--private/ntos/nthals/halwyse7/hal.rc11
-rw-r--r--private/ntos/nthals/halwyse7/hal.src7
-rw-r--r--private/ntos/nthals/halwyse7/i386/halnls.h5
-rw-r--r--private/ntos/nthals/halwyse7/i386/halp.h5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/wy7000mp.inc368
-rw-r--r--private/ntos/nthals/halwyse7/i386/wyclock.asm1292
-rw-r--r--private/ntos/nthals/halwyse7/i386/wydetect.asm167
-rw-r--r--private/ntos/nthals/halwyse7/i386/wyhal.c378
-rw-r--r--private/ntos/nthals/halwyse7/i386/wyipi.asm775
-rw-r--r--private/ntos/nthals/halwyse7/i386/wyirql.asm667
-rw-r--r--private/ntos/nthals/halwyse7/i386/wymapint.c185
-rw-r--r--private/ntos/nthals/halwyse7/i386/wynmi.asm108
-rw-r--r--private/ntos/nthals/halwyse7/i386/wyspin.asm449
-rw-r--r--private/ntos/nthals/halwyse7/i386/wysproc.c465
-rw-r--r--private/ntos/nthals/halwyse7/i386/wysproca.asm436
-rw-r--r--private/ntos/nthals/halwyse7/i386/wyswint.asm336
-rw-r--r--private/ntos/nthals/halwyse7/i386/wysysint.asm615
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halwyse7/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halwyse7/makefile6
-rw-r--r--private/ntos/nthals/halwyse7/makefile.inc2
-rw-r--r--private/ntos/nthals/halwyse7/sources96
-rw-r--r--private/ntos/nthals/halx86/drivesup.c7
-rw-r--r--private/ntos/nthals/halx86/hal.rc11
-rw-r--r--private/ntos/nthals/halx86/hal.src7
-rw-r--r--private/ntos/nthals/halx86/i386/halnls.h29
-rw-r--r--private/ntos/nthals/halx86/i386/halp.h428
-rw-r--r--private/ntos/nthals/halx86/i386/ix8259.inc199
-rw-r--r--private/ntos/nthals/halx86/i386/ixbeep.asm181
-rw-r--r--private/ntos/nthals/halx86/i386/ixbusdat.c373
-rw-r--r--private/ntos/nthals/halx86/i386/ixclock.asm760
-rw-r--r--private/ntos/nthals/halx86/i386/ixcmos.asm1135
-rw-r--r--private/ntos/nthals/halx86/i386/ixcmos.inc66
-rw-r--r--private/ntos/nthals/halx86/i386/ixdat.c159
-rw-r--r--private/ntos/nthals/halx86/i386/ixenvirv.c183
-rw-r--r--private/ntos/nthals/halx86/i386/ixfirm.c79
-rw-r--r--private/ntos/nthals/halx86/i386/ixhwsup.c758
-rw-r--r--private/ntos/nthals/halx86/i386/ixidle.asm88
-rw-r--r--private/ntos/nthals/halx86/i386/ixinfo.c285
-rw-r--r--private/ntos/nthals/halx86/i386/ixipi.asm188
-rw-r--r--private/ntos/nthals/halx86/i386/ixirql.asm1297
-rw-r--r--private/ntos/nthals/halx86/i386/ixisa.h110
-rw-r--r--private/ntos/nthals/halx86/i386/ixisabus.c640
-rw-r--r--private/ntos/nthals/halx86/i386/ixisasup.c1980
-rw-r--r--private/ntos/nthals/halx86/i386/ixkdcom.c684
-rw-r--r--private/ntos/nthals/halx86/i386/ixkdcom.h165
-rw-r--r--private/ntos/nthals/halx86/i386/ixlock.asm475
-rw-r--r--private/ntos/nthals/halx86/i386/ixmca.c868
-rw-r--r--private/ntos/nthals/halx86/i386/ixmcaa.asm420
-rw-r--r--private/ntos/nthals/halx86/i386/ixnmi.c137
-rw-r--r--private/ntos/nthals/halx86/i386/ixpcibrd.c1029
-rw-r--r--private/ntos/nthals/halx86/i386/ixpcibus.c2520
-rw-r--r--private/ntos/nthals/halx86/i386/ixpciint.c458
-rw-r--r--private/ntos/nthals/halx86/i386/ixphwsup.c535
-rw-r--r--private/ntos/nthals/halx86/i386/ixproc.c160
-rw-r--r--private/ntos/nthals/halx86/i386/ixprofil.asm437
-rw-r--r--private/ntos/nthals/halx86/i386/ixreboot.c143
-rw-r--r--private/ntos/nthals/halx86/i386/ixstall.asm480
-rw-r--r--private/ntos/nthals/halx86/i386/ixswint.asm327
-rw-r--r--private/ntos/nthals/halx86/i386/ixsysbus.c188
-rw-r--r--private/ntos/nthals/halx86/i386/ixsysint.asm582
-rw-r--r--private/ntos/nthals/halx86/i386/ixthunk.c82
-rw-r--r--private/ntos/nthals/halx86/i386/ixusage.c535
-rw-r--r--private/ntos/nthals/halx86/i386/ncrdetct.c253
-rw-r--r--private/ntos/nthals/halx86/i386/pcip.h186
-rw-r--r--private/ntos/nthals/halx86/i386/xxbiosa.asm712
-rw-r--r--private/ntos/nthals/halx86/i386/xxbiosc.c299
-rw-r--r--private/ntos/nthals/halx86/i386/xxdisp.c476
-rw-r--r--private/ntos/nthals/halx86/i386/xxflshbf.c52
-rw-r--r--private/ntos/nthals/halx86/i386/xxhal.c462
-rw-r--r--private/ntos/nthals/halx86/i386/xxioacc.asm386
-rw-r--r--private/ntos/nthals/halx86/i386/xxkdsup.c404
-rw-r--r--private/ntos/nthals/halx86/i386/xxmemory.c368
-rw-r--r--private/ntos/nthals/halx86/i386/xxstubs.c131
-rw-r--r--private/ntos/nthals/halx86/i386/xxtime.c91
-rw-r--r--private/ntos/nthals/halx86/makefile6
-rw-r--r--private/ntos/nthals/halx86/makefile.inc2
-rw-r--r--private/ntos/nthals/halx86/sources100
-rw-r--r--private/ntos/nthals/halxlt/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/alcor.h100
-rw-r--r--private/ntos/nthals/halxlt/alpha/alcorerr.c154
-rw-r--r--private/ntos/nthals/halxlt/alpha/alinitnt.c750
-rw-r--r--private/ntos/nthals/halxlt/alpha/alintsup.c599
-rw-r--r--private/ntos/nthals/halxlt/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/alsysint.c497
-rw-r--r--private/ntos/nthals/halxlt/alpha/apecs.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/apecserr.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/apecsio.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/busdata.c137
-rw-r--r--private/ntos/nthals/halxlt/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/cia.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ciaaddr.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ciaerr.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ciaio.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ciamapio.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/cmos8k.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ebsgdma.c6
-rw-r--r--private/ntos/nthals/halxlt/alpha/eisasup.c6
-rw-r--r--private/ntos/nthals/halxlt/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/info.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/inithal.c1063
-rw-r--r--private/ntos/nthals/halxlt/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halxlt/alpha/ioproc.c91
-rw-r--r--private/ntos/nthals/halxlt/alpha/iousage.c647
-rw-r--r--private/ntos/nthals/halxlt/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/halxlt/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halxlt/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/nvenv.c1
-rw-r--r--private/ntos/nthals/halxlt/alpha/nvram.c1
-rw-r--r--private/ntos/nthals/halxlt/alpha/pcibus.c124
-rw-r--r--private/ntos/nthals/halxlt/alpha/pciesc.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/perfcntr.c7
-rw-r--r--private/ntos/nthals/halxlt/alpha/pintolin.h170
-rw-r--r--private/ntos/nthals/halxlt/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halxlt/drivesup.c7
-rw-r--r--private/ntos/nthals/halxlt/hal.rc11
-rw-r--r--private/ntos/nthals/halxlt/hal.src7
-rw-r--r--private/ntos/nthals/halxlt/makefile6
-rw-r--r--private/ntos/nthals/halxlt/makefile.inc5
-rw-r--r--private/ntos/nthals/halxlt/sources107
-rw-r--r--private/ntos/nthals/inc/hali.h109
-rw-r--r--private/ntos/nthals/rangesup.c1144
-rw-r--r--private/ntos/nthals/x86new/addops.c603
-rw-r--r--private/ntos/nthals/x86new/asciiops.c288
-rw-r--r--private/ntos/nthals/x86new/bitops.c256
-rw-r--r--private/ntos/nthals/x86new/condops.c310
-rw-r--r--private/ntos/nthals/x86new/ctrlops.c468
-rw-r--r--private/ntos/nthals/x86new/data.c1375
-rw-r--r--private/ntos/nthals/x86new/debug.c443
-rw-r--r--private/ntos/nthals/x86new/divops.c182
-rw-r--r--private/ntos/nthals/x86new/emulate.c410
-rw-r--r--private/ntos/nthals/x86new/emulate.h1614
-rw-r--r--private/ntos/nthals/x86new/i386/sources24
-rw-r--r--private/ntos/nthals/x86new/inoutops.c235
-rw-r--r--private/ntos/nthals/x86new/jmpops.c290
-rw-r--r--private/ntos/nthals/x86new/logops.c247
-rw-r--r--private/ntos/nthals/x86new/main.c1499
-rw-r--r--private/ntos/nthals/x86new/makefile6
-rw-r--r--private/ntos/nthals/x86new/mips/sources24
-rw-r--r--private/ntos/nthals/x86new/miscops.c179
-rw-r--r--private/ntos/nthals/x86new/moveops.c179
-rw-r--r--private/ntos/nthals/x86new/mulops.c202
-rw-r--r--private/ntos/nthals/x86new/operand.c2026
-rw-r--r--private/ntos/nthals/x86new/pcibios.c618
-rw-r--r--private/ntos/nthals/x86new/ppc/sources24
-rw-r--r--private/ntos/nthals/x86new/regmode.c1239
-rw-r--r--private/ntos/nthals/x86new/setops.c133
-rw-r--r--private/ntos/nthals/x86new/shiftops.c580
-rw-r--r--private/ntos/nthals/x86new/sources46
-rw-r--r--private/ntos/nthals/x86new/stackops.c195
-rw-r--r--private/ntos/nthals/x86new/stringop.c496
-rw-r--r--private/ntos/nthals/x86new/utility.c541
-rw-r--r--private/ntos/nthals/x86new/x86bios.c837
-rw-r--r--private/ntos/nthals/x86new/x86new.h168
-rw-r--r--private/ntos/nthals/x86new/xm86.h129
3138 files changed, 756933 insertions, 0 deletions
diff --git a/private/ntos/nthals/bushnd.c b/private/ntos/nthals/bushnd.c
new file mode 100644
index 000000000..4266c99d3
--- /dev/null
+++ b/private/ntos/nthals/bushnd.c
@@ -0,0 +1,1641 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ bushnd.c
+
+Abstract:
+
+ Functions which take either BusType-BusNumber or ConfigType-BusNumberm
+ and route to a the appropiate registered handler.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+typedef struct _ARRAY {
+ ULONG ArraySize;
+ PVOID Element[]; // must be last field
+} ARRAY, *PARRAY;
+
+#define ARRAY_SIZE_IN_BYTES(a) ( (a + 1) * sizeof(PARRAY) + \
+ FIELD_OFFSET(ARRAY, Element) )
+
+typedef struct _HAL_BUS_HANDLER {
+ LIST_ENTRY AllHandlers;
+ ULONG ReferenceCount;
+ BUS_HANDLER Handler;
+} HAL_BUS_HANDLER, *PHAL_BUS_HANDLER;
+
+//
+// Event to serialize with adding new buses
+//
+
+KEVENT HalpBusDatabaseEvent;
+
+//
+// Lock to serialize routing functions from accessing handler arrays while
+// new buses are added
+//
+
+KSPIN_LOCK HalpBusDatabaseSpinLock;
+
+//
+// HalpBusTable - pointers to BusHandlers mapped by InterfaceType,BusNumber
+//
+
+PARRAY HalpBusTable;
+
+//
+// HalpConfigTable - pointers to BusHandlers mapped by ConfigType,BusNumber
+//
+
+PARRAY HalpConfigTable;
+
+//
+// List of all installed bus handlers
+//
+
+LIST_ENTRY HalpAllBusHandlers;
+
+//
+// Lock is high_level since some routed functions can occurs at ISR time
+//
+
+#define LockBusDatabase(oldirql) \
+ KeRaiseIrql(HIGH_LEVEL, oldirql); \
+ KiAcquireSpinLock(&HalpBusDatabaseSpinLock);
+
+#define UnlockBusDatabase(oldirql) \
+ KiReleaseSpinLock(&HalpBusDatabaseSpinLock); \
+ KeLowerIrql(oldirql);
+
+
+#ifdef _PNP_POWER_
+extern HAL_CALLBACKS HalCallback;
+#endif
+
+//
+// Internal prototypes
+//
+
+PARRAY
+HalpAllocateArray (
+ IN ULONG Type
+ );
+
+VOID
+HalpGrowArray (
+ IN PARRAY *CurrentArray,
+ IN PARRAY *NewArray
+ );
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpNoAdjustResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpNoAssignSlotResources (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+NTSTATUS
+HalpNoQueryBusSlots (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+HalpNoDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+PDEVICE_HANDLER_OBJECT
+HalpNoReferenceDeviceHandler (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber
+ );
+
+ULONG
+HalpNoGetDeviceData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpNoSetDeviceData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+
+//
+// Prototypes for DeviceControls
+//
+
+typedef struct _SYNCHRONOUS_REQUEST {
+ NTSTATUS Status;
+ KEVENT Event;
+} SYNCHRONOUS_REQUEST, *PSYNCHRONOUS_REQUEST;
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitBusHandler)
+#pragma alloc_text(PAGELK,HaliRegisterBusHandler)
+#pragma alloc_text(PAGELK,HalpAllocateArray)
+#pragma alloc_text(PAGELK,HalpGrowArray)
+#pragma alloc_text(PAGE,HalAdjustResourceList)
+#pragma alloc_text(PAGE,HalAssignSlotResources)
+#pragma alloc_text(PAGE,HalGetInterruptVector)
+#pragma alloc_text(PAGE,HalpNoAssignSlotResources)
+#pragma alloc_text(PAGE,HalpNoQueryBusSlots)
+#pragma alloc_text(PAGE,HalpNoReferenceDeviceHandler)
+#pragma alloc_text(PAGE,HaliQueryBusSlots)
+#pragma alloc_text(PAGE,HalpQueryInstalledBusInformation)
+
+#ifdef _PNP_POWER_
+#pragma alloc_text(PAGELK,HaliSuspendHibernateSystem)
+#endif
+
+#endif
+
+VOID
+HalpInitBusHandler (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes global BusHandler data
+
+--*/
+{
+ //
+ // Initialize bus handler spinlock used to synchronize against
+ // buses additions while array lookups are done
+ //
+
+ KeInitializeSpinLock (&HalpBusDatabaseSpinLock);
+
+ //
+ // Initialize bus handler synchronzation event used to serialize
+ // bus additions from < DPC_LVEL
+ //
+
+ KeInitializeEvent (&HalpBusDatabaseEvent, SynchronizationEvent, TRUE);
+
+ //
+ // Initialize global arrays
+ //
+
+ HalpBusTable = HalpAllocateArray (0);
+ HalpConfigTable = HalpAllocateArray (0);
+ InitializeListHead (&HalpAllBusHandlers);
+
+ //
+ // Fill in HAL API handlers
+ //
+
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalDeviceControl = HaliDeviceControl;
+ HalCompleteDeviceControl = HaliCompleteDeviceControl;
+ HalReferenceHandlerForBus = HaliReferenceHandlerForBus;
+ HalReferenceBusHandler = HaliReferenceBusHandler;
+ HalDereferenceBusHandler = HaliDereferenceBusHandler;
+}
+
+NTSTATUS
+HaliRegisterBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE ConfigType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusType,
+ IN ULONG ParentBusNumber,
+ IN ULONG SizeofBusExtensionData,
+ IN PINSTALL_BUS_HANDLER InstallBusHandler,
+ OUT PBUS_HANDLER *ReturnedBusHandler
+ )
+/*++
+
+Routine Description:
+
+ Adds a BusHandler for InterfaceType,BusNumber and for ConfigType,BusNumber.
+
+ Bus specific or Configuration space specific APIs are routed to the
+ bus or configuration specific handlers added by this routine.
+
+Arguments:
+
+ InterfaceType - Identifies the bus type
+ InterfaceTypeUndefined if no interface type for this
+ handler.
+
+ ConfigType - Identifies the configuration space type
+ ConfigurationSpaceUndefined if no configuration space
+ type for this handler.
+
+ BusNumber - Identifies the instance of the bus & config space.
+ -1 if the next available bus number for this bus
+ should be used.
+
+ ParentBusType - If this bus is a child of a bus, then ParentBusType
+ ParentBusNumber and ParentBusNumber identifies that bus.
+ ParentBusType is -1 if no parent bus.
+
+ SizeofBusExetensionData - Sizeof bus specific exentsion data required.
+
+ InstallBusHandler - Function to call to get the bus specific handlers
+ added to the bus handler structure.
+
+Return Value:
+
+ success; otherwise error code of failure.
+
+--*/
+{
+ PHAL_BUS_HANDLER Bus, *pBusHandler, OldHandler;
+ PBUS_HANDLER ParentHandler;
+ KIRQL OldIrql;
+ NTSTATUS Status;
+ PARRAY InterfaceArray, InterfaceBusNumberArray;
+ PARRAY ConfigArray, ConfigBusNumberArray;
+ PVOID CodeLockHandle;
+
+ //
+ // Must add the handler to at least one table
+ //
+
+ ASSERT (InterfaceType != InterfaceTypeUndefined || ConfigType != ConfigurationSpaceUndefined);
+
+ Status = STATUS_SUCCESS;
+ OldHandler = NULL;
+
+ //
+ // Allocate storage for new bus handler structure
+ //
+
+ Bus = (PHAL_BUS_HANDLER)
+ ExAllocatePoolWithTag (
+ NonPagedPool,
+ sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData,
+ 'HsuB'
+ );
+
+ if (!Bus) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Lock pagable code down
+ //
+
+ CodeLockHandle = MmLockPagableCodeSection (&HaliRegisterBusHandler);
+
+ //
+ // Synchronize adding new bus handlers
+ //
+
+ *ReturnedBusHandler = &Bus->Handler;
+
+ KeWaitForSingleObject (
+ &HalpBusDatabaseEvent,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+
+ //
+ // If BusNumber not defined, use next available number for this BusType
+ //
+
+ if (BusNumber == -1) {
+ ASSERT (InterfaceType != InterfaceTypeUndefined);
+
+ BusNumber = 0;
+ while (HaliHandlerForBus (InterfaceType, BusNumber)) {
+ BusNumber++;
+ }
+ }
+
+ //
+ // Allocate memory for each array in case any index needs to grow
+ //
+
+ InterfaceArray = HalpAllocateArray (InterfaceType);
+ InterfaceBusNumberArray = HalpAllocateArray (BusNumber);
+ ConfigArray = HalpAllocateArray (ConfigType);
+ ConfigBusNumberArray = HalpAllocateArray (BusNumber);
+
+ if (!Bus ||
+ !InterfaceArray ||
+ !InterfaceBusNumberArray ||
+ !ConfigArray ||
+ !ConfigBusNumberArray) {
+
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Lookup parent handler (if any)
+ //
+
+ ParentHandler = HaliReferenceHandlerForBus (ParentBusType, ParentBusNumber);
+
+ //
+ // Initialize new bus handlers values
+ //
+
+ RtlZeroMemory (Bus, sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData);
+
+ Bus->ReferenceCount = 1;
+
+ Bus->Handler.BusNumber = BusNumber;
+ Bus->Handler.InterfaceType = InterfaceType;
+ Bus->Handler.ConfigurationType = ConfigType;
+ Bus->Handler.ParentHandler = ParentHandler;
+
+ //
+ // Set to dumby handlers
+ //
+
+ Bus->Handler.GetBusData = HalpNoBusData;
+ Bus->Handler.SetBusData = HalpNoBusData;
+ Bus->Handler.AdjustResourceList = HalpNoAdjustResourceList;
+ Bus->Handler.AssignSlotResources = HalpNoAssignSlotResources;
+ Bus->Handler.QueryBusSlots = HalpNoQueryBusSlots;
+ Bus->Handler.ReferenceDeviceHandler = HalpNoReferenceDeviceHandler;
+ Bus->Handler.DeviceControl = HalpNoDeviceControl;
+ Bus->Handler.GetDeviceData = HalpNoGetDeviceData;
+ Bus->Handler.SetDeviceData = HalpNoSetDeviceData;
+
+ if (SizeofBusExtensionData) {
+ Bus->Handler.BusData = Bus + 1;
+ }
+
+ //
+ // If bus has a parent, inherit handlers from parent as default
+ //
+
+ if (ParentHandler) {
+ Bus->Handler.GetBusData = ParentHandler->GetBusData;
+ Bus->Handler.SetBusData = ParentHandler->SetBusData;
+ Bus->Handler.AdjustResourceList = ParentHandler->AdjustResourceList;
+ Bus->Handler.AssignSlotResources = ParentHandler->AssignSlotResources;
+ Bus->Handler.TranslateBusAddress = ParentHandler->TranslateBusAddress;
+ Bus->Handler.GetInterruptVector = ParentHandler->GetInterruptVector;
+ Bus->Handler.QueryBusSlots = ParentHandler->QueryBusSlots;
+ Bus->Handler.ReferenceDeviceHandler = ParentHandler->ReferenceDeviceHandler;
+ Bus->Handler.DeviceControl = ParentHandler->DeviceControl;
+ Bus->Handler.GetDeviceData = ParentHandler->GetDeviceData;
+ Bus->Handler.SetDeviceData = ParentHandler->SetDeviceData;
+ }
+
+ //
+ // Install bus specific handlers
+ //
+
+ if (InstallBusHandler) {
+ Status = InstallBusHandler (&Bus->Handler);
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Might change addresses of some arrays synchronize
+ // with routing handlers
+ //
+
+ LockBusDatabase (&OldIrql);
+
+ //
+ // Grow HalpBusTable if needed
+ //
+
+ HalpGrowArray (&HalpBusTable, &InterfaceArray);
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+
+ //
+ // Grow HalpBusTable if needed
+ //
+
+ HalpGrowArray (
+ (PARRAY *) &HalpBusTable->Element[InterfaceType],
+ &InterfaceBusNumberArray
+ );
+
+
+ //
+ // Get registered handler for InterfaceType,BusNumber
+ //
+
+ pBusHandler = &((PHAL_BUS_HANDLER)
+ ((PARRAY) HalpBusTable->Element[InterfaceType])->Element[BusNumber]);
+
+ //
+ // If handler already defiend, remove the old one
+ //
+
+ if (*pBusHandler) {
+ OldHandler = *pBusHandler;
+ }
+
+ //
+ // Set new handler for supplied InterfaceType,BusNumber
+ //
+
+ *pBusHandler = Bus;
+ }
+
+ //
+ // Grow HalpConfigTable if needed
+ //
+
+ HalpGrowArray (&HalpConfigTable, &ConfigArray);
+
+ if (ConfigType != ConfigurationSpaceUndefined) {
+
+ //
+ // Grow HalpConfigTable if needed
+ //
+
+ HalpGrowArray (
+ (PARRAY *) &HalpConfigTable->Element[ConfigType],
+ &ConfigBusNumberArray
+ );
+
+ //
+ // Get registered handler for ConfigType,BusNumber
+ //
+
+ pBusHandler = &((PHAL_BUS_HANDLER)
+ ((PARRAY) HalpConfigTable->Element[ConfigType])->Element[BusNumber]);
+
+ if (*pBusHandler) {
+ ASSERT (OldHandler == NULL || OldHandler == *pBusHandler);
+ OldHandler = *pBusHandler;
+ }
+
+ //
+ // Set new handler for supplied ConfigType,BusNumber
+ //
+
+ *pBusHandler = Bus;
+ }
+
+ //
+ // Add new bus handler to list of all installed handlers
+ //
+
+ InsertTailList (&HalpAllBusHandlers, &Bus->AllHandlers);
+
+ //
+ // Remove old bus handler
+ //
+
+ Bus = OldHandler;
+ if (Bus) {
+ RemoveEntryList (&Bus->AllHandlers);
+ }
+
+ //
+ // Lookup array modification complete, release lock
+ //
+
+ UnlockBusDatabase (OldIrql);
+ } else {
+ if (ParentHandler) {
+ HaliDereferenceBusHandler (ParentHandler);
+ }
+ }
+ }
+
+ //
+ // Bus addition modifications complete, set event
+ //
+
+ KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
+
+ //
+ // Unlock pagable code
+ //
+
+ MmUnlockPagableImageSection (CodeLockHandle);
+
+ //
+ // Free memory which is not in use
+ //
+
+ if (Bus) {
+ ExFreePool (Bus);
+ }
+
+ if (InterfaceArray) {
+ ExFreePool (InterfaceArray);
+ }
+
+ if (InterfaceBusNumberArray) {
+ ExFreePool (InterfaceBusNumberArray);
+ }
+
+ if (ConfigArray) {
+ ExFreePool (ConfigArray);
+ }
+
+ if (ConfigBusNumberArray) {
+ ExFreePool (ConfigBusNumberArray);
+ }
+
+#ifdef _PNP_POWER_
+ //
+ // A bus was added to the system, notify the BusInsertionCheck callback
+ // of this bus
+ //
+
+ if (NT_SUCCESS(Status) && InterfaceType != InterfaceTypeUndefined) {
+ ExNotifyCallback (
+ HalCallback.BusCheck,
+ (PVOID) InterfaceType,
+ (PVOID) BusNumber
+ );
+ }
+#endif
+
+ return Status;
+}
+
+PARRAY
+HalpAllocateArray (
+ IN ULONG ArraySize
+ )
+/*++
+
+Routine Description:
+
+ Allocate an array of size ArraySize.
+
+Arguments:
+
+ ArraySize - Size of array in elements
+
+Return Value:
+
+ pointer to ARRAY
+
+--*/
+{
+ PARRAY Array;
+
+ if (ArraySize == -1) {
+ ArraySize = 0;
+ }
+
+ Array = ExAllocatePoolWithTag (
+ NonPagedPool,
+ ARRAY_SIZE_IN_BYTES(ArraySize),
+ 'HsuB'
+ );
+
+ //
+ // Initialize array
+ //
+
+ Array->ArraySize = ArraySize;
+ RtlZeroMemory (Array->Element, sizeof(PVOID) * (ArraySize+1));
+ return Array;
+}
+
+VOID
+HalpGrowArray (
+ IN PARRAY *CurrentArray,
+ IN PARRAY *NewArray
+ )
+/*++
+
+Routine Description:
+
+ If NewArray is larger then CurrentArray, then the CurrentArray
+ is grown to the sizeof NewArray by swapping the pointers and
+ moving the arrays contents.
+
+Arguments:
+
+ CurrentArray - Address of the current array pointer
+ NewArray - Address of the new array pointer
+
+--*/
+{
+ PVOID Tmp;
+
+ if (!*CurrentArray || (*NewArray)->ArraySize > (*CurrentArray)->ArraySize) {
+
+ //
+ // Copy current array ontop of new array
+ //
+
+ if (*CurrentArray) {
+ RtlCopyMemory (&(*NewArray)->Element,
+ &(*CurrentArray)->Element,
+ sizeof(PVOID) * ((*CurrentArray)->ArraySize + 1)
+ );
+ }
+
+
+ //
+ // swap current with new such that the new array is the current
+ // one, and the old memory will be freed back to pool
+ //
+
+ Tmp = *CurrentArray;
+ *CurrentArray = *NewArray;
+ *NewArray = Tmp;
+ }
+}
+
+PBUS_HANDLER
+FASTCALL
+HalpLookupHandler (
+ IN PARRAY Array,
+ IN ULONG Type,
+ IN ULONG Number,
+ IN BOOLEAN AddReference
+ )
+{
+ PHAL_BUS_HANDLER Bus;
+ PBUS_HANDLER Handler;
+ KIRQL OldIrql;
+
+ LockBusDatabase (&OldIrql);
+
+ //
+ // Index by type
+ //
+
+ Handler = NULL;
+ if (Array->ArraySize >= Type) {
+ Array = (PARRAY) Array->Element[Type];
+
+ //
+ // Index by instance numberr
+ //
+
+ if (Array && Array->ArraySize >= Number) {
+ Bus = (PHAL_BUS_HANDLER) Array->Element[Number];
+ Handler = &Bus->Handler;
+
+ if (AddReference) {
+ Bus->ReferenceCount += 1;
+ }
+ }
+ }
+
+ UnlockBusDatabase (OldIrql);
+ return Handler;
+}
+
+VOID
+FASTCALL
+HaliReferenceBusHandler (
+ IN PBUS_HANDLER Handler
+ )
+/*++
+
+Routine Description:
+
+
+--*/
+{
+ KIRQL OldIrql;
+ PHAL_BUS_HANDLER Bus;
+
+
+ LockBusDatabase (&OldIrql);
+
+ Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
+ Bus->ReferenceCount += 1;
+
+ UnlockBusDatabase (OldIrql);
+}
+
+VOID
+FASTCALL
+HaliDereferenceBusHandler (
+ IN PBUS_HANDLER Handler
+ )
+/*++
+
+Routine Description:
+
+
+--*/
+{
+ KIRQL OldIrql;
+ PHAL_BUS_HANDLER Bus;
+
+
+ LockBusDatabase (&OldIrql);
+
+ Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
+ Bus->ReferenceCount -= 1;
+
+ UnlockBusDatabase (OldIrql);
+
+ // BUGBUG: for now totally removing a bus is not supported
+ ASSERT (Bus->ReferenceCount != 0);
+}
+
+
+PBUS_HANDLER
+FASTCALL
+HaliHandlerForBus (
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ Returns the BusHandler structure InterfaceType,BusNumber
+ or NULL if no such handler exists.
+
+--*/
+{
+ return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, FALSE);
+}
+
+PBUS_HANDLER
+FASTCALL
+HaliHandlerForConfigSpace (
+ IN BUS_DATA_TYPE ConfigType,
+ IN ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ Returns the BusHandler structure ConfigType,BusNumber
+ or NULL if no such handler exists.
+
+--*/
+{
+ return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, FALSE);
+}
+
+
+PBUS_HANDLER
+FASTCALL
+HaliReferenceHandlerForBus (
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ Returns the BusHandler structure InterfaceType,BusNumber
+ or NULL if no such handler exists.
+
+--*/
+{
+ return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, TRUE);
+}
+
+PBUS_HANDLER
+FASTCALL
+HaliReferenceHandlerForConfigSpace (
+ IN BUS_DATA_TYPE ConfigType,
+ IN ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ Returns the BusHandler structure ConfigType,BusNumber
+ or NULL if no such handler exists.
+
+--*/
+{
+ return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, TRUE);
+}
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns an array HAL_BUS_INFORMATION, one for each
+ bus handler installed.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_BUS_INFORMATION Info;
+ PHAL_BUS_HANDLER Handler;
+ ULONG i, j;
+ ULONG Length;
+ NTSTATUS Status;
+ PARRAY Array;
+
+ PAGED_CODE ();
+
+ //
+ // Synchronize adding new bus handlers
+ //
+
+ KeWaitForSingleObject (
+ &HalpBusDatabaseEvent,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ //
+ // Determine sizeof return buffer
+ //
+
+ Length = 0;
+ for (i=0; i <= HalpBusTable->ArraySize; i++) {
+ Array = (PARRAY) HalpBusTable->Element[i];
+ if (Array) {
+ Length += sizeof (HAL_BUS_INFORMATION) *
+ (Array->ArraySize + 1);
+ }
+ }
+
+ //
+ // Return size of buffer returning, or size of buffer needed
+ //
+
+ *ReturnedLength = Length;
+
+ //
+ // Fill in the return buffer
+ //
+
+ if (Length <= BufferLength) {
+
+ Info = (PHAL_BUS_INFORMATION) Buffer;
+
+ for (i=0; i <= HalpBusTable->ArraySize; i++) {
+ Array = (PARRAY) HalpBusTable->Element[i];
+ if (Array) {
+ for (j=0; j <= Array->ArraySize; j++) {
+ Handler = (PHAL_BUS_HANDLER) Array->Element[j];
+
+ if (Handler) {
+ Info->BusType = Handler->Handler.InterfaceType;
+ Info->ConfigurationType = Handler->Handler.ConfigurationType;
+ Info->BusNumber = Handler->Handler.BusNumber;
+ Info->Reserved = 0;
+ Info += 1;
+ }
+ }
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+
+ } else {
+
+ //
+ // Return buffer too small
+ //
+
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
+ return Status;
+}
+
+//
+// Default dispatchers to BusHandlers
+//
+
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+{
+ return HalGetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
+}
+
+
+ULONG
+HalGetBusDataByOffset (
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for GetBusData
+
+--*/
+{
+ PBUS_HANDLER Handler;
+ NTSTATUS Status;
+
+ Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
+ if (!Handler) {
+ return 0;
+ }
+
+ Status = Handler->GetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
+ HaliDereferenceBusHandler (Handler);
+ return Status;
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+{
+ return HalSetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for SetBusData
+
+--*/
+{
+ PBUS_HANDLER Handler;
+ NTSTATUS Status;
+
+ Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
+ if (!Handler) {
+ return 0;
+ }
+
+ Status = Handler->SetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
+ HaliDereferenceBusHandler (Handler);
+ return Status;
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for AdjustResourceList
+
+--*/
+{
+ PBUS_HANDLER Handler;
+ NTSTATUS Status;
+
+ Handler = HaliReferenceHandlerForBus (
+ (*pResourceList)->InterfaceType,
+ (*pResourceList)->BusNumber
+ );
+ if (!Handler) {
+ return STATUS_SUCCESS;
+ }
+
+ Status = Handler->AdjustResourceList (Handler, Handler, pResourceList);
+ HaliDereferenceBusHandler (Handler);
+ return Status;
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for AssignSlotResources
+
+--*/
+{
+ PBUS_HANDLER Handler;
+ NTSTATUS Status;
+
+ Handler = HaliReferenceHandlerForBus (BusType, BusNumber);
+ if (!Handler) {
+ return STATUS_NOT_FOUND;
+ }
+
+ Status = Handler->AssignSlotResources (
+ Handler,
+ Handler,
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ SlotNumber,
+ AllocatedResources
+ );
+
+ HaliDereferenceBusHandler (Handler);
+ return Status;
+}
+
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for GetInterruptVector
+
+--*/
+{
+ PBUS_HANDLER Handler;
+ ULONG Vector;
+
+ Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
+ *Irql = 0;
+ *Affinity = 0;
+
+ if (!Handler) {
+ return 0;
+ }
+
+ Vector = Handler->GetInterruptVector (Handler, Handler,
+ BusInterruptLevel, BusInterruptVector, Irql, Affinity);
+
+ HaliDereferenceBusHandler (Handler);
+ return Vector;
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for TranslateBusAddress
+
+--*/
+{
+ PBUS_HANDLER Handler;
+ BOOLEAN Status;
+
+ Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
+ if (!Handler) {
+ return FALSE;
+ }
+
+ Status = Handler->TranslateBusAddress (Handler, Handler,
+ BusAddress, AddressSpace, TranslatedAddress);
+
+ HaliDereferenceBusHandler (Handler);
+ return Status;
+}
+
+NTSTATUS
+HaliQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Dispatcher for QueryBusSlots
+
+--*/
+{
+ PAGED_CODE();
+
+ return BusHandler->QueryBusSlots (BusHandler, BusHandler,
+ BufferSize, SlotNumbers, ReturnedLength);
+}
+
+NTSTATUS
+HaliDeviceControl (
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG ControlCode,
+ IN OUT PVOID Buffer OPTIONAL,
+ IN OUT PULONG BufferLength OPTIONAL,
+ IN PVOID CompletionContext,
+ IN PDEVICE_CONTROL_COMPLETION CompletionRoutine
+ )
+/*++
+
+Routine Description:
+
+ Allocates and initializes a HalDeviceControlContext and then dispatches
+ that context to the appriopate bus handler.
+
+--*/
+{
+ NTSTATUS Status;
+ PHAL_DEVICE_CONTROL_CONTEXT pContext;
+ HAL_DEVICE_CONTROL_CONTEXT Context;
+ SYNCHRONOUS_REQUEST SyncRequest;
+
+ //
+ // Initialize local DeviceControl context
+ //
+
+ Context.DeviceControl.DeviceHandler = DeviceHandler;
+ Context.DeviceControl.DeviceObject = DeviceObject;
+ Context.DeviceControl.ControlCode = ControlCode;
+ Context.DeviceControl.Buffer = Buffer;
+ Context.DeviceControl.BufferLength = BufferLength;
+ Context.DeviceControl.Context = CompletionContext;
+ Context.CompletionRoutine = CompletionRoutine;
+ Context.Handler = DeviceHandler->BusHandler;
+ Context.RootHandler = DeviceHandler->BusHandler;
+
+ //
+ // Allocate HalDeviceControlContext structure
+ // (for now, just do it from pool)
+ //
+
+ pContext = ExAllocatePoolWithTag (
+ NonPagedPool,
+ sizeof (HAL_DEVICE_CONTROL_CONTEXT) +
+ Context.Handler->DeviceControlExtensionSize,
+ 'sLAH'
+ );
+
+
+ if (pContext) {
+
+ //
+ // Initialize HalDeviceControlContext
+ //
+
+ RtlCopyMemory (pContext, &Context, sizeof (HAL_DEVICE_CONTROL_CONTEXT));
+
+ pContext->BusExtensionData = NULL;
+ if (pContext->Handler->DeviceControlExtensionSize) {
+ pContext->BusExtensionData = pContext + 1;
+ }
+
+
+ if (!Context.CompletionRoutine) {
+
+ //
+ // There's no completion routine, associate an event to make it a
+ // synchronous request
+ //
+
+ KeInitializeEvent (&SyncRequest.Event, SynchronizationEvent, FALSE);
+ pContext->DeviceControl.Context = &SyncRequest;
+ }
+
+ //
+ // If there's no buffer length, pass in a zero
+ //
+
+ if (!pContext->DeviceControl.BufferLength) {
+ pContext->DeviceControl.BufferLength = pContext->HalReserved;
+ pContext->HalReserved[0] = 0;
+ }
+
+ //
+ // Allocated context complete, dispatch it to the appopiate bus handler
+ //
+
+ pContext->DeviceControl.Status = STATUS_PENDING;
+ Status = Context.Handler->DeviceControl(pContext);
+
+ //
+ // If the DeviceControl is pending and this is a synchronous call
+ // wait for it to complete
+ //
+
+ if (Status == STATUS_PENDING && CompletionRoutine == NULL) {
+
+ //
+ // Wait for it to complete
+ //
+
+ KeWaitForSingleObject (
+ &SyncRequest.Event,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ //
+ // Return results
+ //
+
+ Status = SyncRequest.Status;
+ ASSERT (Status != STATUS_PENDING);
+ }
+
+ return Status;
+
+ } else {
+
+ //
+ // Out of memory
+ //
+
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ //
+ // Immediate error, complete request with local context
+ // structure with error code
+ //
+
+ if (CompletionRoutine) {
+ Context.DeviceControl.Status = Status;
+ CompletionRoutine (&Context.DeviceControl);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliCompleteDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ NTSTATUS Status;
+ PSYNCHRONOUS_REQUEST SyncRequest;
+
+ //
+ // Get results
+ //
+
+ Status = Context->DeviceControl.Status;
+
+ if (Context->CompletionRoutine) {
+
+ //
+ // Notify completion routine
+ //
+
+ Context->CompletionRoutine (&Context->DeviceControl);
+
+
+ } else {
+
+ //
+ // This is a synchronous request, return the status, and set
+ // the event
+ //
+
+ SyncRequest = (PSYNCHRONOUS_REQUEST) Context->DeviceControl.Context;
+ SyncRequest->Status = Context->DeviceControl.Status;
+ KeSetEvent (&SyncRequest->Event, 0, FALSE);
+ }
+
+ //
+ // Free context structure
+ //
+
+ ExFreePool (Context);
+ return Status;
+}
+
+//
+// Null handlers
+//
+
+ULONG HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Stub handler for buses which do not have a configuration space
+
+--*/
+{
+ return 0;
+}
+
+NTSTATUS
+HalpNoAdjustResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Stub handler for buses which do not have a configuration space
+
+--*/
+{
+ PAGED_CODE ();
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+NTSTATUS
+HalpNoAssignSlotResources (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Stub handler for buses which do not have a configuration space
+
+--*/
+{
+ PAGED_CODE ();
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpNoQueryBusSlots (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+{
+ PAGED_CODE ();
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+NTSTATUS
+HalpNoDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ Context->DeviceControl.Status = STATUS_NOT_SUPPORTED;
+ return HaliCompleteDeviceControl (Context);
+}
+
+PDEVICE_HANDLER_OBJECT
+HalpNoReferenceDeviceHandler (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber
+ )
+{
+ return NULL;
+}
+
+ULONG
+HalpNoGetDeviceData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ return 0;
+}
+
+ULONG
+HalpNoSetDeviceData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ return 0;
+}
+
+#ifdef _PNP_POWER_
+NTSTATUS
+HaliSuspendHibernateSystem (
+ IN PTIME_FIELDS ResumeTime OPTIONAL,
+ IN PHIBERNATE_CALLBACK SystemCallback
+ )
+/*++
+
+Routine Description:
+
+ This function is invokved by the to suspend or hibernate the system.
+ By this point all device drivers have been turned off. All bus
+ extenders are notified, and then a platform specific suspend function
+ is called.
+
+Arguments:
+
+ ResumeTime - Time to set resume alarm
+ SystemCallback - If NULL, suspend; else call this function.
+
+Return Value:
+
+ SUCCESS if machine was suspended/hibernated.
+
+--*/
+{
+ KIRQL OldIrql;
+ PHAL_BUS_HANDLER Handler;
+ PLIST_ENTRY HibernateLink, ResumeLink;
+ NTSTATUS Status;
+
+ LockBusDatabase (&OldIrql);
+ ASSERT (OldIrql == HIGH_LEVEL);
+
+ //
+ // Notify bus handlers in reserved order for which they were installed
+ //
+
+ Status = STATUS_SUCCESS;
+ for (HibernateLink = HalpAllBusHandlers.Blink;
+ HibernateLink != &HalpAllBusHandlers && NT_SUCCESS(Status);
+ HibernateLink = HibernateLink->Blink) {
+
+ //
+ // Give this handler hibernate notification
+ //
+
+ Handler = CONTAINING_RECORD(HibernateLink, HAL_BUS_HANDLER, AllHandlers);
+ if (Handler->Handler.HibernateBus) {
+ Status = Handler->Handler.HibernateBus (
+ &Handler->Handler,
+ &Handler->Handler
+ );
+ }
+ }
+
+ //
+ // Suspend or Hibernate the system now
+ //
+
+ if (NT_SUCCESS (Status)) {
+ Status = HalpSuspendHibernateSystem (ResumeTime, SystemCallback);
+ }
+
+ //
+ // Notify bus handlers which were hibernated to restore state
+ //
+
+ for (ResumeLink = HibernateLink->Flink;
+ ResumeLink != &HalpAllBusHandlers;
+ ResumeLink = ResumeLink->Flink) {
+
+ //
+ // Give this handler resume notification
+ //
+
+ Handler = CONTAINING_RECORD(ResumeLink, HAL_BUS_HANDLER, AllHandlers);
+ if (Handler->Handler.ResumeBus) {
+ Handler->Handler.ResumeBus (
+ &Handler->Handler,
+ &Handler->Handler
+ );
+ }
+ }
+
+ UnlockBusDatabase (OldIrql);
+ return Status;
+}
+#endif
diff --git a/private/ntos/nthals/dirs b/private/ntos/nthals/dirs
new file mode 100644
index 000000000..dc034691d
--- /dev/null
+++ b/private/ntos/nthals/dirs
@@ -0,0 +1,75 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=x86new \
+ halacr \
+ haldti \
+ halfxs \
+ halfxspc \
+ halduomp \
+ halnecmp \
+ halntp \
+ halsnip \
+ halsni4x \
+ halr94a \
+ halr96b \
+ halr98b \
+ halr98mp \
+ hal0jens \
+ halalcor \
+ halavant \
+ haleb164 \
+ haleb64p \
+ haleb66 \
+ hallego \
+ hallx3 \
+ halmikas \
+ halnonme \
+ halpinna \
+ halqs \
+ halraw \
+ halsable \
+ halgamma \
+ halxlt \
+ halx86 \
+ hal486c \
+ halmca \
+ halast \
+ halcbus \
+ halsp \
+ haloli \
+ haltyne \
+ halws3 \
+ halwyse7 \
+ halmps \
+ halflex \
+ halppc \
+ halwood \
+ halcaro \
+ halvict \
+ halfire \
+ haleagle \
+ halps \
+ halalp \
+ haltimbr
+
+OPTIONAL_DIRS=halncr
diff --git a/private/ntos/nthals/drivesup.c b/private/ntos/nthals/drivesup.c
new file mode 100644
index 000000000..29e6e79f3
--- /dev/null
+++ b/private/ntos/nthals/drivesup.c
@@ -0,0 +1,334 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ drivesup.c
+
+Abstract:
+
+ This module contains the subroutines for drive support. This includes
+ such things as how drive letters are assigned on a particular platform,
+ how device partitioning works, etc.
+
+Author:
+
+ Darryl E. Havens (darrylh) 23-Apr-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+
+#include "ntddft.h"
+#include "ntdddisk.h"
+#include "ntdskreg.h"
+#include "stdio.h"
+#include "string.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, IoAssignDriveLetters)
+#pragma alloc_text(PAGE, IoReadPartitionTable)
+#pragma alloc_text(PAGE, IoSetPartitionInformation)
+#pragma alloc_text(PAGE, IoWritePartitionTable)
+#endif
+
+VOID
+IoAssignDriveLetters(
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ PSTRING NtDeviceName,
+ OUT PUCHAR NtSystemPath,
+ OUT PSTRING NtSystemPathString
+ )
+
+/*++
+
+Routine Description:
+
+ This routine assigns DOS drive letters to eligible disk partitions
+ and CDROM drives. It also maps the partition containing the NT
+ boot path to \SystemRoot. In NT, objects are built for all partition
+ types except 0 (unused) and 5 (extended). But drive letters are assigned
+ only to recognized partition types (1, 4, 6, and 7).
+
+ Drive letter assignment is done in several stages:
+
+ 1) For each CdRom:
+ Determine if sticky letters are assigned and reserve the letter.
+
+ 2) For each disk:
+ Determine how many primary partitions and which is bootable.
+ Determine which partitions already have 'sticky letters'
+ and create their symbolic links.
+ Create a bit map for each disk that idicates which partitions
+ require default drive letter assignments.
+
+ 3) For each disk:
+ Assign default drive letters for the bootable
+ primary partition or the first nonbootable primary partition.
+
+ 4) For each disk:
+ Assign default drive letters for the partitions in
+ extended volumes.
+
+ 5) For each disk:
+ Assign default drive letters for the remaining (ENHANCED)
+ primary partitions.
+
+ 6) Assign A: and B: to the first two floppies in the system if they
+ exist. Then assign remaining floppies next available drive letters.
+
+ 7) Assign drive letters to CdRoms (either sticky or default).
+
+Arguments:
+
+ LoaderBlock - pointer to a loader parameter block.
+
+ NtDeviceName - pointer to the boot device name string used
+ to resolve NtSystemPath.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Stub to call extensible routine in ke so that hal vendors
+ // don't have to support.
+ //
+
+ HalIoAssignDriveLetters(
+ LoaderBlock,
+ NtDeviceName,
+ NtSystemPath,
+ NtSystemPathString
+ );
+
+} // end IoAssignDriveLetters()
+
+NTSTATUS
+IoReadPartitionTable(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SectorSize,
+ IN BOOLEAN ReturnRecognizedPartitions,
+ OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine walks the disk reading the partition tables and creates
+ an entry in the partition list buffer for each partition.
+
+ The algorithm used by this routine is two-fold:
+
+ 1) Read each partition table and for each valid, recognized
+ partition found, to build a descriptor in a partition list.
+ Extended partitions are located in order to find other
+ partition tables, but no descriptors are built for these.
+ The partition list is built in nonpaged pool that is allocated
+ by this routine. It is the caller's responsibility to free
+ this pool after it has gathered the appropriate information
+ from the list.
+
+ 2) Read each partition table and for each and every entry, build
+ a descriptor in the partition list. Extended partitions are
+ located to find each partition table on the disk, and entries
+ are built for these as well. The partition list is build in
+ nonpaged pool that is allocated by this routine. It is the
+ caller's responsibility to free this pool after it has copied
+ the information back to its caller.
+
+ The first algorithm is used when the ReturnRecognizedPartitions flag
+ is set. This is used to determine how many partition device objects
+ the device driver is to create, and where each lives on the drive.
+
+ The second algorithm is used when the ReturnRecognizedPartitions flag
+ is clear. This is used to find all of the partition tables and their
+ entries for a utility such as fdisk, that would like to revamp where
+ the partitions live.
+
+Arguments:
+
+ DeviceObject - Pointer to device object for this disk.
+
+ SectorSize - Sector size on the device.
+
+ ReturnRecognizedPartitions - A flag indicated whether only recognized
+ partition descriptors are to be returned, or whether all partition
+ entries are to be returned.
+
+ PartitionBuffer - Pointer to the pointer of the buffer in which the list
+ of partition will be stored.
+
+Return Value:
+
+ The functional value is STATUS_SUCCESS if at least one sector table was
+ read.
+
+Notes:
+
+ It is the responsibility of the caller to deallocate the partition list
+ buffer allocated by this routine.
+
+--*/
+
+{
+ //
+ // Stub to call extensible routine in ke so that hal vendors
+ // don't have to support.
+ //
+
+ return HalIoReadPartitionTable(
+ DeviceObject,
+ SectorSize,
+ ReturnRecognizedPartitions,
+ PartitionBuffer
+ );
+}
+
+NTSTATUS
+IoSetPartitionInformation(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SectorSize,
+ IN ULONG PartitionNumber,
+ IN ULONG PartitionType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked when a disk device driver is asked to set the
+ partition type in a partition table entry via an I/O control code. This
+ control code is generally issued by the format utility just after it
+ has formatted the partition. The format utility performs the I/O control
+ function on the partition and the driver passes the address of the base
+ physical device object and the number of the partition associated with
+ the device object that the format utility has open. If this routine
+ returns success, then the disk driver should updates its notion of the
+ partition type for this partition in its device extension.
+
+Arguments:
+
+ DeviceObject - Pointer to the base physical device object for the device
+ on which the partition type is to be set.
+
+ SectorSize - Supplies the size of a sector on the disk in bytes.
+
+ PartitionNumber - Specifies the partition number on the device whose
+ partition type is to be changed.
+
+ PartitionType - Specifies the new type for the partition.
+
+Return Value:
+
+ The function value is the final status of the operation.
+
+Notes:
+
+ This routine is synchronous. Therefore, it MUST be invoked by the disk
+ driver's dispatch routine, or by a disk driver's thread. Likewise, all
+ users, FSP threads, etc., must be prepared to enter a wait state when
+ issuing the I/O control code to set the partition type for the device.
+
+ Note also that this routine assumes that the partition number passed
+ in by the disk driver actually exists since the driver itself supplies
+ this parameter.
+
+ Finally, note that this routine may NOT be invoked at APC_LEVEL. It
+ must be invoked at PASSIVE_LEVEL. This is due to the fact that this
+ routine uses a kernel event object to synchronize I/O completion on the
+ device. The event cannot be set to the signaled state without queueing
+ the I/O system's special kernel APC routine for I/O completion and
+ executing it. (This rules is a bit esoteric since it only holds true
+ if the device driver returns something other than STATUS_PENDING, which
+ it will probably never do.)
+
+--*/
+
+{
+ //
+ // Stub to call extensible routine in ke so that hal vendors
+ // don't have to support.
+ //
+
+ return HalIoSetPartitionInformation(
+ DeviceObject,
+ SectorSize,
+ PartitionNumber,
+ PartitionType
+ );
+
+}
+
+NTSTATUS
+IoWritePartitionTable(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SectorSize,
+ IN ULONG SectorsPerTrack,
+ IN ULONG NumberOfHeads,
+ IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine walks the disk writing the partition tables from
+ the entries in the partition list buffer for each partition.
+
+ Applications that create and delete partitions should issue a
+ IoReadPartitionTable call with the 'return recognized partitions'
+ boolean set to false to get a full description of the system.
+
+ Then the drive layout structure can be modified by the application to
+ reflect the new configuration of the disk and then is written back
+ to the disk using this routine.
+
+Arguments:
+
+ DeviceObject - Pointer to device object for this disk.
+
+ SectorSize - Sector size on the device.
+
+ SectorsPerTrack - Track size on the device.
+
+ NumberOfHeads - Same as tracks per cylinder.
+
+ PartitionBuffer - Pointer drive layout buffer.
+
+Return Value:
+
+ The functional value is STATUS_SUCCESS if all writes are completed
+ without error.
+
+--*/
+
+{
+
+ //
+ // Stub to call extensible routine in ke so that hal vendors
+ // don't have to support.
+ //
+
+ return HalIoWritePartitionTable(
+ DeviceObject,
+ SectorSize,
+ SectorsPerTrack,
+ NumberOfHeads,
+ PartitionBuffer
+ );
+}
diff --git a/private/ntos/nthals/extender/pci/bus.c b/private/ntos/nthals/extender/pci/bus.c
new file mode 100644
index 000000000..bd6e3aaf5
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/bus.c
@@ -0,0 +1,670 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ bus.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipCheckBus)
+#pragma alloc_text(PAGE,PciCtlCheckDevice)
+#pragma alloc_text(PAGE,PcipCrackBAR)
+#pragma alloc_text(PAGE,PcipVerifyBarBits)
+#pragma alloc_text(PAGE,PcipGetBarBits)
+#pragma alloc_text(PAGE,PcipFindDeviceData)
+#endif
+
+
+VOID
+PcipCheckBus (
+ PPCI_PORT PciPort,
+ BOOLEAN Initialize
+ )
+{
+ NTSTATUS Status;
+ PBUS_HANDLER Handler;
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG Device, Function;
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ BOOLEAN BusCheck, SkipDevice;
+ PDEVICE_DATA DeviceData;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ ULONG ObjectSize;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE Handle;
+ PSINGLE_LIST_ENTRY *Link;
+ BOOLEAN State;
+ POWER_STATE PowerState;
+ ULONG BufferSize;
+
+ PAGED_CODE();
+
+ Handler = PciPort->Handler;
+ BusCheck = FALSE;
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ //
+ // We may be removing references to this bus handler, so add
+ // a reference now
+ //
+
+ HalReferenceBusHandler (Handler);
+
+ //
+ // Check for any obslete device data entries
+ //
+
+ ExAcquireFastMutex (&PcipMutex);
+
+ Link = &PciPort->ValidSlots.Next;
+ while (*Link) {
+ DeviceData = CONTAINING_RECORD (*Link, DEVICE_DATA, Next);
+ if (!DeviceData->Valid) {
+
+ //
+ // Remove it from the list
+ //
+
+ *Link = (*Link)->Next;
+ BusCheck = TRUE;
+ PciPort->NoValidSlots -= 1;
+ HalDereferenceBusHandler (Handler);
+
+ //
+ // Dereference each obsolete device handler object once. This
+ // counters the original reference made to the device handler
+ // object when the object was created by this driver.
+ //
+
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+ ObDereferenceObject (DeviceHandler);
+ continue;
+ }
+
+ Link = & ((*Link)->Next);
+ }
+
+ ExReleaseFastMutex (&PcipMutex);
+
+
+ //
+ // Check the bus for new devices
+ //
+
+ SlotNumber.u.AsULONG = 0;
+ for (Device=0; Device < PCI_MAX_DEVICES; Device++) {
+ SlotNumber.u.bits.DeviceNumber = Device;
+ for (Function=0; Function < PCI_MAX_FUNCTION; Function++) {
+ SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read in the device id
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If not valid, skip it
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0) {
+ break;
+ }
+
+ //
+ // Check to see if this known configuration type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case PCI_DEVICE_TYPE:
+ case PCI_BRIDGE_TYPE:
+ SkipDevice = FALSE;
+ break;
+ default:
+ SkipDevice = TRUE;
+ break;
+ }
+
+ if (SkipDevice) {
+ break;
+ }
+
+ ExAcquireFastMutex (&PcipMutex);
+ DeviceData = PcipFindDeviceData (PciPort, SlotNumber);
+
+ if (DeviceData == NULL) {
+
+ //
+ // Initialize the object attributes that will be used to create the
+ // Device Handler Object.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+
+ ObjectSize = PcipDeviceHandlerObjectSize + sizeof (DEVICE_DATA);
+
+ //
+ // Create the object
+ //
+
+ Status = ObCreateObject(
+ KernelMode,
+ *IoDeviceHandlerObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ ObjectSize,
+ 0,
+ 0,
+ (PVOID *) &DeviceHandler
+ );
+
+ if (NT_SUCCESS(Status)) {
+ RtlZeroMemory (DeviceHandler, ObjectSize);
+
+ DeviceHandler->Type = (USHORT) *IoDeviceHandlerObjectType;
+ DeviceHandler->Size = (USHORT) ObjectSize;
+ DeviceHandler->SlotNumber = SlotNumber.u.AsULONG;
+
+ //
+ // Get a reference to the object
+ //
+
+ Status = ObReferenceObjectByPointer(
+ DeviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Insert it into the object table
+ //
+
+ Status = ObInsertObject(
+ DeviceHandler,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ NULL,
+ &Handle
+ );
+ }
+
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // Object not created correctly
+ //
+
+ ExReleaseFastMutex (&PcipMutex);
+ break;
+ }
+
+ ZwClose (Handle);
+
+
+ //
+ // Intialize structure to track device
+ //
+
+ DebugPrint ((8, "PCI: adding slot %x (for device %04x-%04x)\n",
+ SlotNumber,
+ PciData->VendorID,
+ PciData->DeviceID
+ ));
+
+ DeviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Get BAR decode bits which are supported
+ //
+
+ Status = PcipGetBarBits (DeviceData, PciPort->Handler);
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ DeviceHandler->BusHandler = Handler;
+ HalReferenceBusHandler (Handler);
+
+ DeviceData->Valid = TRUE;
+ PciPort->NoValidSlots += 1;
+ PushEntryList (&PciPort->ValidSlots, &DeviceData->Next);
+ BusCheck = TRUE;
+ }
+
+ //
+ // Obtain an extra reference to the device handler for
+ // sending some DeviceControls
+ //
+
+ ObReferenceObjectByPointer (
+ DeviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ //
+ // If we are installing the initail bus support, then
+ // all devices are installed as locked & powered up.
+ // If this is a dynamically located new device, then
+ // the device is started as unlocked & powered down.
+ //
+
+ if (Initialize) {
+
+ //
+ // Set initial state as locked
+ //
+
+ State = TRUE;
+ BufferSize = sizeof (State);
+ HalDeviceControl (
+ DeviceHandler,
+ NULL,
+ BCTL_SET_LOCK,
+ &State,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+
+ //
+ // Set initial power state as Powered Up
+ //
+
+ PowerState = PowerUp;
+ BufferSize = sizeof (PowerState);
+ HalDeviceControl (
+ DeviceHandler,
+ NULL,
+ BCTL_SET_POWER,
+ (PVOID) &PowerState,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+ }
+
+ //
+ // Free once
+ //
+
+ ObDereferenceObject (DeviceHandler);
+ }
+
+ ExReleaseFastMutex (&PcipMutex);
+ }
+ }
+
+ //
+ // Undo reference to bus handler from top of function
+ //
+
+ HalDereferenceBusHandler (Handler);
+
+ //
+ // Do we need to notify the system buscheck callback?
+ //
+
+ if (BusCheck) {
+ ExNotifyCallback (
+ PciHalCallbacks.BusCheck,
+ (PVOID) PciPort->Handler->InterfaceType,
+ (PVOID) PciPort->Handler->BusNumber
+ );
+ }
+
+}
+
+NTSTATUS
+PcipVerifyBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ )
+{
+ NTSTATUS Status;
+
+ PAGED_CODE ();
+
+ Status = STATUS_SUCCESS;
+ if (!DeviceData->BARBitsSet) {
+
+ DeviceData->BARBitsSet = TRUE;
+ Status = PcipGetBarBits (DeviceData, Handler);
+
+ if (!NT_SUCCESS(Status)) {
+ DeviceData->BARBitsSet = FALSE;
+ }
+ }
+
+ return Status;
+}
+
+
+
+NTSTATUS
+PcipGetBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ )
+{
+ PPCIBUSDATA PciBusData;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress2[PCI_TYPE0_ADDRESSES + 1];
+ ULONG NoBaseAddress2, RomIndex2;
+ ULONG j;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ LONGLONG bits, base, length, max;
+ BOOLEAN BrokenDevice;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE ();
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // Get the device's current configuration
+ //
+
+ if (!DeviceData->CurrentConfig) {
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePoolWithTag (NonPagedPool, PCI_COMMON_HDR_LENGTH, 'cICP');
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ RtlCopyMemory (DeviceData->CurrentConfig, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Get BaseAddress array, and check if ROM was originally enabled
+ //
+
+ DeviceData->EnableRom = PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // If the device's current configuration isn't enabled, then set for
+ // not powered on
+ //
+
+ if (!(PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
+ DeviceData->Power = FALSE;
+ DeviceData->Locked = FALSE;
+ }
+
+ //
+ // Check to see if there are any BARs
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ DeviceData->BARBits[j] = 0;
+ if (*BaseAddress[j]) {
+ DeviceData->BARBitsSet = TRUE;
+ }
+ }
+
+ //
+ // If not BarBitsSet, then don't attempt to determine the possible
+ // device settings now
+ //
+
+ if (!DeviceData->BARBitsSet) {
+ DebugPrint ((2, "PCI: ghost added device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber));
+
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Set BARs to all on, and read them back
+ //
+
+ DebugPrint ((3, "PCI: getting valid BAR bits on device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber
+ ));
+
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ DeviceData->CurrentConfig,
+ BaseAddress2,
+ &NoBaseAddress2,
+ &RomIndex2
+ );
+
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ //
+ // Remember the original bits
+ //
+
+ DeviceData->BARBits[j] = *BaseAddress[j];
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ DeviceData->BARBits[j+1] = *BaseAddress[j+1];
+ }
+
+ //
+ // Crack bits & check for BrokenDevice
+ //
+
+ BrokenDevice = PcipCrackBAR (
+ BaseAddress2,
+ DeviceData->BARBits,
+ &j,
+ &base,
+ &length,
+ &max
+ );
+
+ if (BrokenDevice) {
+ DeviceData->BrokenDevice = TRUE;
+ }
+ }
+ }
+
+ if (DeviceData->BrokenDevice) {
+ DebugPrint ((2, "PCI: added defective device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber));
+
+ } else {
+ DebugPrint ((2, "PCI: added device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber));
+ }
+
+ return STATUS_SUCCESS;
+}
+
+PDEVICE_DATA
+PcipFindDeviceData (
+ IN PPCI_PORT PciPort,
+ IN PCI_SLOT_NUMBER SlotNumber
+ )
+{
+ PDEVICE_DATA DeviceData;
+ PSINGLE_LIST_ENTRY Link;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+
+ PAGED_CODE ();
+
+ for (Link = PciPort->ValidSlots.Next; Link; Link = Link->Next) {
+ DeviceData = CONTAINING_RECORD (Link, DEVICE_DATA, Next);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+ if (DeviceHandler->SlotNumber == SlotNumber.u.AsULONG) {
+ break;
+ }
+ }
+
+ if (!Link) {
+ return NULL;
+ }
+
+ return DeviceData;
+}
+
+
+BOOLEAN
+PcipCrackBAR (
+ IN PULONG *BaseAddress,
+ IN PULONG BarBits,
+ IN OUT PULONG Index,
+ OUT PLONGLONG pbase,
+ OUT PLONGLONG plength,
+ OUT PLONGLONG pmax
+ )
+{
+ LONGLONG base, length, max, bits;
+ BOOLEAN Status;
+
+ PAGED_CODE ();
+
+ //
+ // Get initial base & bits
+ //
+
+ base = *BaseAddress[*Index];
+ bits = BarBits[*Index];
+
+ if (Is64BitBaseAddress(base)) {
+ *Index += 1;
+ base |= ((LONGLONG) *BaseAddress[*Index]) << 32;
+ bits |= ((LONGLONG) BarBits[*Index]) << 32;
+ }
+
+ //
+ // Scan for first set bit, that's the BARs length and alignment
+ //
+
+ length = (base & PCI_ADDRESS_IO_SPACE) ? 1 << 2 : 1 << 4;
+ while (!(bits & length) && length) {
+ length <<= 1;
+ }
+
+ //
+ // Scan for last set bit, that's that BARs max address + 1
+ //
+
+ for (max = length; bits & max; max <<= 1) ;
+ max -= 1;
+
+ //
+ // Check for defective BAR
+ //
+
+ Status = (bits & ~max) ? TRUE : FALSE;
+
+ //
+ // return results
+ //
+
+ *pbase = base;
+ *plength = length;
+ *pmax = max;
+ return Status;
+}
diff --git a/private/ntos/nthals/extender/pci/control.c b/private/ntos/nthals/extender/pci/control.c
new file mode 100644
index 000000000..2ac6e2b24
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/control.c
@@ -0,0 +1,662 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ control.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipControlWorker)
+#pragma alloc_text(PAGE,PciCtlEject)
+#pragma alloc_text(PAGE,PciCtlLock)
+#pragma alloc_text(PAGE,PciCtlForward)
+#pragma alloc_text(PAGE,PcipCompleteDeviceControl)
+#endif
+
+
+VOID
+PcipStartWorker (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used to verify a worker thread is dispatched
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ULONG WorkerQueued;
+
+ if (!PcipWorkerQueued) {
+ WorkerQueued = ExInterlockedExchangeUlong (
+ &PcipWorkerQueued,
+ 1,
+ PcipSpinLock
+ );
+
+ if (!WorkerQueued) {
+ ExQueueWorkItem (&PcipWorkItem, DelayedWorkQueue);
+ }
+ }
+}
+
+VOID
+PcipQueueCheckBus (
+ PBUS_HANDLER Handler
+ )
+{
+ PPCI_PORT PciPort;
+
+ PciPort = PCIPORTDATA(Handler);
+ ExInterlockedInsertTailList (
+ &PcipCheckBusList,
+ &PciPort->CheckBus,
+ &PcipSpinlock
+ );
+
+ PcipStartWorker();
+}
+
+
+VOID
+PcipControlWorker (
+ IN PVOID WorkerContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called by a system worker thread.
+
+ The worker thread dequeues any DeviceControls which need to be
+ processed and dispatches them.
+
+ It then checks for any
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PLIST_ENTRY Entry;
+ PPCI_PORT PciPort;
+ PHAL_DEVICE_CONTROL_CONTEXT Context;
+
+ PAGED_CODE ();
+
+ //
+ // Dispatch pending slot controls
+ //
+
+ for (; ;) {
+ Entry = ExInterlockedRemoveHeadList (
+ &PcipControlWorkerList,
+ &PcipSpinlock
+ );
+
+ if (!Entry) {
+ break;
+ }
+
+ Context = CONTAINING_RECORD (
+ Entry,
+ HAL_DEVICE_CONTROL_CONTEXT,
+ ContextWorkQueue,
+ );
+
+ PcipDispatchControl (Context);
+ }
+
+ //
+ // Reset worker item for next time
+ //
+
+ ExInitializeWorkItem (&PcipWorkItem, PcipControlWorker, NULL);
+ ExInterlockedExchangeUlong (&PcipWorkerQueued, 0, PcipSpinLock);
+
+ //
+ // Process check buses
+ //
+
+ for (; ;) {
+ Entry = ExInterlockedRemoveHeadList (
+ &PcipCheckBusList,
+ &PcipSpinlock
+ );
+
+ if (!Entry) {
+ break;
+ }
+
+ PciPort = CONTAINING_RECORD (
+ Entry,
+ PCI_PORT,
+ CheckBus
+ );
+
+ PcipCheckBus (PciPort, FALSE);
+ }
+}
+
+
+VOID
+PcipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function dispatches a DeviceControl to the appropiate handler.
+ If the slot is busy, the DeviceControl may be queued for dispatching at
+ a later time
+
+Arguments:
+
+ Context - The DeviceControl context to dispatch
+
+Return Value:
+
+--*/
+{
+ PDEVICE_CONTROL_HANDLER DeviceControlHandler;
+ PDEVICE_DATA DeviceData;
+ PPCI_PORT PciPort;
+ KIRQL OldIrql;
+ BOOLEAN EnqueueIt;
+ PLIST_ENTRY Link;
+
+ DeviceControlHandler = (PDEVICE_CONTROL_HANDLER) Context->ContextControlHandler;
+ PciPort = PCIPORTDATA(Context->Handler);
+ DeviceData = DeviceHandler2DeviceData (Context->DeviceControl.DeviceHandler);
+
+ //
+ // Get access to the device specific data.
+ //
+
+ KeAcquireSpinLock (&PcipSpinlock, &OldIrql);
+
+ //
+ // Verify the device data is still valid
+ //
+
+ if (!DeviceData->Valid) {
+
+ //
+ // Caller has invalid handle, or handle to a different device
+ //
+
+ DebugPrint ((2, "PCI: DeviceControl has invalid device handler \n" ));
+ Context->DeviceControl.Status = STATUS_NO_SUCH_DEVICE;
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+ HalCompleteDeviceControl (Context);
+ return ;
+ }
+
+ //
+ // Check to see if this request can be begun now
+ //
+
+ Link = (PLIST_ENTRY) &Context->ContextWorkQueue;
+ EnqueueIt = DeviceControlHandler->BeginDeviceControl (DeviceData, Context);
+
+ if (EnqueueIt) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ InsertTailList (&PciPort->DeviceControl, Link);
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+ return ;
+ }
+
+ //
+ // Dispatch the function to it's handler
+ //
+
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+ DeviceControlHandler->ControlHandler (DeviceData, Context);
+}
+
+VOID
+PcipiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData,
+ PBOOLEAN Sync
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a DeviceControl. If another DeviceControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ KIRQL OldIrql;
+ PPCI_PORT PciPort;
+ PLIST_ENTRY Link;
+ PBOOLEAN BusyFlag;
+ BOOLEAN StartWorker;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+
+
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+ BusyFlag = (PBOOLEAN) Context->ContextBusyFlag;
+ PciPort = PCIPORTDATA(Context->Handler);
+
+ //
+ // Pass it to the hal for completion
+ //
+
+ Context->DeviceControl.Status = Status;
+ HalCompleteDeviceControl (Context);
+ StartWorker = FALSE;
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ KeAcquireSpinLock (&PcipSpinlock, &OldIrql);
+
+ //
+ // Clear appropiate busy flag
+ //
+
+ *BusyFlag = FALSE;
+
+ //
+ // Check to see if there are any pending slot controls for
+ // this device. If so, requeue them to the worker thread.
+ // (yes, this code is not efficient, but doing it this way
+ // saves a little on the nonpaged pool device_data structure size)
+ //
+
+ for (Link = PciPort->DeviceControl.Flink; Link != &PciPort->DeviceControl; Link = Link->Flink) {
+ Context = CONTAINING_RECORD (Link, HAL_DEVICE_CONTROL_CONTEXT, ContextWorkQueue);
+ if (Context->DeviceControl.DeviceHandler == DeviceHandler) {
+ RemoveEntryList (Link);
+ InsertTailList (&PcipControlWorkerList, Link);
+ StartWorker = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+
+ if (StartWorker) {
+ PcipStartWorker ();
+ }
+}
+
+VOID
+PcipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a DeviceControl. If another DeviceControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PAGED_CODE();
+
+ PcipiCompleteDeviceControl (
+ Status,
+ Context,
+ DeviceData,
+ &DeviceData->SyncBusy
+ );
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ if ( *((PPOWER_STATE) Context->DeviceControl.Buffer) == PowerUp ) {
+
+ //
+ // This is a power on, there can only be one of these on the
+ // slot at any one time
+ //
+
+ ASSERT (DeviceData->AsyncBusy == FALSE);
+
+ //
+ // If PowerUp needs to pend, then queue the request
+ //
+
+ if (DeviceData->PendPowerUp) {
+ return TRUE;
+ }
+
+ DeviceData->AsyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceData->AsyncBusy;
+ return FALSE;
+ }
+
+ //
+ // Something other then a PowerUp. Some form of power down,
+ // treat it like any other sync request
+ //
+
+ return PciBCtlSync (DeviceData, Context);
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlSync (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ //
+ // This is a sync command, verify the slot is not busy with a different
+ // command.
+ //
+
+ if (DeviceData->SyncBusy || DeviceData->AsyncBusy) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ return TRUE;
+ }
+
+ //
+ // Don't enqueue, dispatch it now
+ //
+
+ DeviceData->SyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceData->SyncBusy;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ BOOLEAN Busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ Busy = PciBCtlSync (DeviceData, Context);
+
+ if (!Busy) {
+
+ //
+ // Just trying to eject a device will invalidate the current
+ // device handler object for it...
+ //
+
+ DeviceData->Valid = FALSE;
+ DebugPrint ((5, "PCI: set handle invalid - slot %x\n", DeviceDataSlot(DeviceData)));
+ }
+
+ return Busy;
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ BOOLEAN Busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ Busy = PciBCtlSync (DeviceData, Context);
+ if (!Busy &&
+ ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer) ) {
+
+ //
+ // About to perform an unlock, set PendPowerUp
+ // This will stop any async power up requests
+ //
+
+ ASSERT (DeviceData->PendPowerUp == FALSE);
+ DeviceData->PendPowerUp = TRUE;
+ }
+
+ return Busy;
+}
+
+VOID
+PciCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // We don't know how to lock or unlock, but we track various
+ // device state. Event attempting to ejecting a device effectively
+ // unlocks & powers it down.
+ //
+
+ DeviceData->Locked = FALSE;
+ Status = PcipPowerDownSlot (Context->Handler, DeviceData);
+
+ //
+ // Pass the eject request
+ //
+
+ if (NT_SUCCESS(Status)) {
+ Status = BugBugSubclass ();
+ }
+
+ DebugPrint ((2, "PCI: Eject complete - Slot %x, Status %x\n",
+ DeviceDataSlot(DeviceData), Status));
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+VOID
+PciCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ BOOLEAN Lock;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // We don't know how to lock or unlock, but we track the
+ // device's locked state
+ //
+
+ Lock = ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer)->Control;
+
+ //
+ // If this is an unlock request, powered down the slot
+ //
+
+ Status = STATUS_SUCCESS;
+ if (!Lock) {
+ Status = PcipPowerDownSlot (Context->Handler, DeviceData);
+ }
+
+ //
+ // Pass the lock request to miniport driver to lock/unlock the slot
+ //
+
+ if (NT_SUCCESS(Status)) {
+ Status = BugBugSubclass ();
+ }
+
+ //
+ // If it worked, set the new locked state
+ //
+
+ if (NT_SUCCESS(Status)) {
+ DeviceData->Locked = Lock;
+ }
+
+ //
+ // Allow power requests to continue
+ //
+
+ DeviceData->PendPowerUp = FALSE;
+ DebugPrint ((2, "PCI: %s complete - Slot %x, Status %x\n",
+ Lock ? "Lock" : "Unlock", DeviceDataSlot(DeviceData), Status));
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ POWER_STATE Power;
+ NTSTATUS Status;
+
+ // not pagable
+
+ //
+ // We don't know how to power on or off the device, but we track the
+ // device's power state
+ //
+
+ Power = *((PPOWER_STATE) Context->DeviceControl.Buffer);
+
+ //
+ // If this is a power down request, complete it
+ //
+
+ if (Power != PowerUp) {
+ Status = PcipPowerDownSlot (Context->Handler, DeviceData);
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+ return ;
+ }
+
+ //
+ // Device must be locked, or the power up request should have
+ // received an invalid device error.
+ //
+
+ ASSERT (DeviceData->Locked);
+
+ //
+ // If the device already has power, then there's nothing to do
+ //
+
+ if (DeviceData->Power) {
+ PcipiCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceData, &DeviceData->AsyncBusy);
+ return ;
+ }
+
+ // bugbug pass it to a child driver, for now just complete it
+
+ PcipCompletePowerUp (DeviceData, Context);
+}
+
+VOID
+PcipCompletePowerUp (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ NTSTATUS Status;
+
+ //
+ // Put the device's prior configuration back.
+ //
+
+ DeviceData->Power = TRUE;
+ Status = PcipFlushConfig (Context->Handler, DeviceData);
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // The device's state could not be restored. The decodes
+ // for the device shouldn't be enabled, so there's no immidiate
+ // problem. But break the current handle to the device and
+ // kick off a bus check. This will cause us to assign the
+ // device a new handle, and to power it off.
+ //
+
+ DeviceData->Valid = FALSE;
+ PcipQueueCheckBus (Context->Handler);
+ }
+
+ if (Context->DeviceControl.ControlCode == BCTL_SET_POWER) {
+ DebugPrint ((2, "PCI: Powerup complete - Slot %x, Status %x\n",
+ DeviceDataSlot(DeviceData), Status));
+
+ PcipiCompleteDeviceControl (Status, Context, DeviceData, &DeviceData->AsyncBusy);
+ }
+}
+
+
+VOID
+PciCtlForward (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ PAGED_CODE ();
+
+ DbgPrint ("PCI: BUGBUG Forward\n");
+ PcipCompleteDeviceControl (STATUS_NOT_IMPLEMENTED, Context, DeviceData);
+}
diff --git a/private/ntos/nthals/extender/pci/devres.c b/private/ntos/nthals/extender/pci/devres.c
new file mode 100644
index 000000000..578c4ac46
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/devres.c
@@ -0,0 +1,1139 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ Device Resources
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+NTSTATUS
+PcipQueryResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList
+ );
+
+NTSTATUS
+PcipSetResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PCM_RESOURCE_LIST ResourceList,
+ ULONG ListSize
+ );
+
+
+#pragma alloc_text(PAGE,PciCtlQueryDeviceId)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,PciCtlSetDeviceResources)
+#pragma alloc_text(PAGE,PciCtlAssignSlotResources)
+#pragma alloc_text(PAGE,PcipQueryResourceRequirements)
+#pragma alloc_text(PAGE,PcipSetResources)
+
+
+
+
+VOID
+PciCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular slot.
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+ PPCI_COMMON_CONFIG PciData;
+ PWCHAR DeviceID;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ ULONG length;
+ ULONG IDNumber;
+
+ PAGED_CODE();
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ IDNumber = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // For PCI devices:
+ // ID #0 is the specific PCI device ID.
+ // ID #1 is the compatible device ID based on the BaseClass & SubClass fields
+ //
+
+ Status = STATUS_NO_MORE_ENTRIES;
+ DeviceID = (PWCHAR) Context->DeviceControl.Buffer;
+
+ if (IDNumber == 0) {
+
+ //
+ // Return the PCI device ID
+ //
+
+ swprintf (DeviceID, PCI_ID, PciData->VendorID, PciData->DeviceID);
+ Status = STATUS_SUCCESS;
+ }
+
+ if (IDNumber == 1) {
+
+ //
+ // Return the first compatible device id for the device
+ //
+
+ if ( (PciData->BaseClass == 0 &&
+ PciData->SubClass == 1 &&
+ PciData->ProgIf == 0) ||
+
+ (PciData->BaseClass == 3 &&
+ PciData->SubClass == 0 &&
+ PciData->ProgIf == 0) ) {
+
+ //
+ // This is an industry standard VGA controller
+ //
+
+ swprintf (DeviceID, PNP_VGA);
+ Status = STATUS_SUCCESS;
+ }
+
+ if (PciData->BaseClass == 1 &&
+ PciData->SubClass == 0 &&
+ PciData->ProgIf == 0) {
+
+ //
+ // This is an industry standard IDE controller
+ //
+
+ swprintf (DeviceID, PNP_IDE);
+ Status = STATUS_SUCCESS;
+
+ }
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns a unique device id for the particular slot.
+ The id is a sequence of numbers separated by dots ('.'). The first
+ number is the bus number of the root of the heirarchy of PCI buses
+ that the slot belongs to. The last number in the sequence is the
+ slot number in question. A possibly empty set of numbers in between
+ these two, represents the slot numbers of intermediate PCI-PCI bridges
+ in the hierarchy between the root bus and the slot.
+
+ For example, L"0.1.2.3":
+ 0 PCI bus number of the root of the heirarchy.
+ 1 Slot number within PCI bus 0 were a PCI-PCI bridge is
+ located, the secondary bus that it bridges to is PCI bus X.
+ 2 Slot number within PCI bus X were a PCI-PCI bridge is
+ located, the secondary bus that it bridges to is PCI bus Y.
+ 3 Slot number within PCI bus Y for which we are wanting to
+ obtain the unique id (i.e. the targer of this control operation).
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+ PBUS_HANDLER BusHandler;
+ PBUS_HANDLER ParentHandler;
+ PWCHAR UniqueDeviceId;
+ PWCHAR UniqueDeviceIdEnd;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ BOOLEAN Done;
+ UCHAR UidComponent;
+ PPCIBUSDATA PciBusData;
+ PWCHAR DelimiterPointer;
+ WCHAR Delimiter;
+
+ PAGED_CODE();
+
+ //
+ // Set [UniqueDeviceId, UniqueDeviceIdEnd) to the range of
+ // wide characters for which the caller provided storage.
+ //
+
+ Status = STATUS_SUCCESS;
+ UniqueDeviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ UniqueDeviceIdEnd = UniqueDeviceId
+ + *Context->DeviceControl.BufferLength / sizeof(WCHAR);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+
+ //
+ // Determine the memory required for the unique id.
+ // Note that this loop exits in the middle and that it will
+ // always be executed at least 1.5 times. If there are PCI-PCI
+ // bridges between the slot's bus and the root bus of the PCI
+ // hierarchy, then an extra iteration of the loop will be done
+ // for each one of them.
+ //
+ // The bus hierarchy is being walked backwards (from leaf to root).
+ // Finally, note that the rightmost uid component is the slot's
+ // number (set before we enter the loop).
+ //
+
+ BusHandler = DeviceHandler->BusHandler;
+ UidComponent = (UCHAR) DeviceHandler->SlotNumber;
+ Done = FALSE;
+
+ for (;;) {
+
+ //
+ // On each iteration, given the value of one of the components of
+ // the unique id, determine how much memory the swprintf would use
+ // for it (note that the 2, 3 & 4 below include a +1, which is
+ // for the nul terminator or for the '.' delimiter between two
+ // unique id components.
+ //
+
+ if (UidComponent <= 9) {
+ UniqueDeviceId += 2;
+ } else if (UidComponent <= 99) {
+ UniqueDeviceId += 3;
+ } else {
+ UniqueDeviceId += 4;
+ }
+
+ if (Done) {
+ break;
+ }
+
+ //
+ // If there is no parent bus handler for the current bus,
+ // or if it is not a PCI bus, then we are at the root of
+ // this hierarchy of PCI buses. In this case the unique id
+ // component is the bus number (instead of a slot number),
+ // furthermore, we are almost done (just account for the
+ // space required in the unique id for it).
+ //
+ // Otherwise, the current bus is a PCI-PCI bridge and its
+ // unique id component is the slot number of the bridge
+ // within its parent bus.
+ //
+
+ ParentHandler = BusHandler->ParentHandler;
+ if (!ParentHandler || ParentHandler->InterfaceType != PCIBus) {
+ UidComponent = (UCHAR) BusHandler->BusNumber;
+ Done = TRUE;
+ } else {
+ PciBusData = (PPCIBUSDATA) BusHandler->BusData;
+ UidComponent = (UCHAR) PciBusData->ParentSlot.u.AsULONG;
+ BusHandler = ParentHandler;
+ }
+ }
+
+ //
+ // If there is not enough space for the unique id, fail
+ // and return the size required.
+ //
+
+ if (UniqueDeviceId > UniqueDeviceIdEnd) {
+ *Context->DeviceControl.BufferLength = (UniqueDeviceIdEnd
+ - (PWCHAR) Context->DeviceControl.Buffer) * sizeof(WCHAR);
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+
+ //
+ // Otherwise, traverse the bus heirarchy again (just like
+ // above), except that this time we decrement the UniqueDeviceId
+ // on each iteration and swprintf the uid component. Note that
+ // for all components except for the right most one we store
+ // a delimiter after it (i.e. a '.').
+ //
+
+ BusHandler = DeviceHandler->BusHandler;
+ UidComponent = (UCHAR) DeviceHandler->SlotNumber;
+ Done = FALSE;
+ Delimiter = L'\0';
+ for (;;) {
+ DelimiterPointer = UniqueDeviceId;
+ if (UidComponent <= 9) {
+ UniqueDeviceId -= 2;
+ } else if (UidComponent <= 99) {
+ UniqueDeviceId -= 3;
+ } else {
+ UniqueDeviceId -= 4;
+ }
+ swprintf(UniqueDeviceId, L"%d", UidComponent);
+ DelimiterPointer[-1] = Delimiter;
+ Delimiter = L'.';
+
+ if (Done) {
+ break;
+ }
+
+ ParentHandler = BusHandler->ParentHandler;
+ if (!ParentHandler || ParentHandler->InterfaceType != PCIBus) {
+ UidComponent = (UCHAR) BusHandler->BusNumber;
+ Done = TRUE;
+ } else {
+ PciBusData = (PPCIBUSDATA) BusHandler->BusData;
+ UidComponent = (UCHAR) PciBusData->ParentSlot.u.AsULONG;
+ BusHandler = ParentHandler;
+ }
+ }
+ }
+
+ PcipCompleteDeviceControl(Status, Context, DeviceData);
+}
+
+
+VOID
+PciCtlQueryDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCES DeviceControl
+ which returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PCM_RESOURCE_LIST CompleteList;
+ PCM_PARTIAL_RESOURCE_LIST PartialList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ LONGLONG base, length, max;
+ NTSTATUS Status;
+ PUCHAR WorkingPool;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+// BUGBUG if the device is a pci-2-pci bus controller, then
+// this function should return the addresses which are bridged
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ PcipCompleteDeviceControl (STATUS_INSUFFICIENT_RESOURCES, Context, DeviceData);
+ return ;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Build a CM_RESOURCE_LIST for the PCI device
+ //
+
+ CompleteList->Count = 1;
+ CompleteList->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ CompleteList->List[0].BusNumber = Context->RootHandler->BusNumber;
+
+ PartialList = &CompleteList->List[0].PartialResourceList;
+ Descriptor = PartialList->PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+
+ PciBusData->Pin2Line (
+ Context->Handler,
+ Context->RootHandler,
+ SlotNumber,
+ PciData
+ );
+
+ Descriptor->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+
+ PartialList->Count++;
+ Descriptor++;
+ }
+
+ //
+ // Add any memory / port resources being used
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ ASSERT (DeviceData->BARBitsSet);
+ PcipCrackBAR (BaseAddress, DeviceData->BARBits, &j, &base, &length, &max);
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+
+ if (PciData->Command & PCI_ENABLE_IO_SPACE) {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Port.Start.QuadPart = base & ~0x3;
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Port.Length = (ULONG) length;
+ }
+
+
+ } else {
+
+ if (PciData->Command & PCI_ENABLE_MEMORY_SPACE) {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == RomIndex) {
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (base & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ Descriptor->u.Memory.Start.QuadPart = base & ~0xF;
+ ASSERT (length < 0xFFFFFFFF);
+ Descriptor->u.Memory.Length = (ULONG) length;
+ }
+ }
+
+ PartialList->Count++;
+ Descriptor++;
+ }
+ }
+
+ //
+ // Return results
+ //
+
+ i = (ULONG) ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+ if (i > *Context->DeviceControl.BufferLength) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, CompleteList, i);
+ Status = STATUS_SUCCESS;
+ }
+
+ *Context->DeviceControl.BufferLength = i;
+ ExFreePool (WorkingPool);
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlQueryDeviceResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCE_REQUIREMENTS DeviceControl
+ which returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipQueryResourceRequirements (DeviceData, Context, &ResourceList);
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Return results
+ //
+
+ if (ResourceList->ListSize > *Context->DeviceControl.BufferLength) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ResourceList, ResourceList->ListSize);
+ Status = STATUS_SUCCESS;
+ }
+
+ *Context->DeviceControl.BufferLength = ResourceList->ListSize;
+
+ }
+
+ if (ResourceList) {
+ ExFreePool (ResourceList);
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+NTSTATUS
+PcipQueryResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList
+ )
+/*++
+
+Routine Description:
+
+ This function allocates and returns the specified devices
+ IO_RESOURCE_REQUIREMENTS_LIST
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ LONGLONG base, length, max;
+ NTSTATUS Status;
+ PUCHAR WorkingPool;
+
+ PAGED_CODE();
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ *ResourceList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ if (!*ResourceList) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = Context->RootHandler->InterfaceType;
+ CompleteList->BusNumber = Context->RootHandler->BusNumber;
+ CompleteList->SlotNumber = DeviceDataSlot(DeviceData);
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+
+ // BUGBUG: this is not correct
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+
+ //
+ // Add any memory / port resources being used
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ PcipCrackBAR (BaseAddress, DeviceData->BARBits, &j, &base, &length, &max);
+
+ //
+ // Add a descriptor for this address
+ //
+
+ Descriptor->Option = 0;
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Port.Alignment = (ULONG) length;
+ Descriptor->u.Port.Length = (ULONG) length;
+ Descriptor->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = max;
+
+ } else {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (base & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Memory.Alignment = (ULONG) length;
+ Descriptor->u.Memory.Length = (ULONG) length;
+ Descriptor->u.Memory.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Memory.MaximumAddress.QuadPart = max;
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+ }
+
+ if (DeviceData->BrokenDevice) {
+
+ //
+ // This device has something wrong with its base address register implementation
+ //
+
+ ExFreePool (WorkingPool);
+ return STATUS_DEVICE_PROTOCOL_ERROR;
+ }
+
+ //
+ // Return results
+ //
+
+ CompleteList->ListSize = (ULONG) ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+ *ResourceList = CompleteList;
+ return STATUS_SUCCESS;
+}
+
+VOID
+PciCtlSetDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the SET_DEVICE_RESOURCES DeviceControl
+ which configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipSetResources (
+ DeviceData,
+ Context,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer,
+ *Context->DeviceControl.BufferLength
+ );
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+NTSTATUS
+PcipSetResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PCM_RESOURCE_LIST ResourceList,
+ ULONG ListSize
+ )
+/*++
+
+Routine Description:
+
+ This function set the specified device to the CM_RESOURCE_LIST
+
+Arguments:
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ LONGLONG base, length;
+ NTSTATUS Status;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // If BARBits haven't been deteremined, go do it now
+ //
+
+ Status = PcipVerifyBarBits (DeviceData, Context->Handler);
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+
+ //
+ // Get current device configuration
+ //
+
+ if (DeviceData->Power) {
+ ASSERT (DeviceData->CurrentConfig == NULL);
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePool (NonPagedPool, PCI_COMMON_HDR_LENGTH);
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciData = DeviceData->CurrentConfig;
+ PciOrigData = (PPCI_COMMON_CONFIG) buffer;
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Save current config
+ //
+
+ RtlCopyMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ //
+ // Assign the interrupt line
+ //
+
+ if (CmDescriptor->Type != CmResourceTypeInterrupt) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+
+ PciBusData->Pin2Line (
+ Context->Handler,
+ Context->RootHandler,
+ SlotNumber,
+ PciData
+ );
+
+ CmDescriptor++;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ base = *BaseAddress[j];
+ if (base) {
+ //
+ // Set 32bits and mask
+ //
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ if (CmDescriptor->Type != CmResourceTypePort) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+
+ } else {
+ if (CmDescriptor->Type != CmResourceTypeMemory) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+
+ if (Is64BitBaseAddress(base)) {
+
+ //
+ // Set upper 32bits
+ //
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j+1] = CmDescriptor->u.Port.Start.HighPart;
+ } else {
+ *BaseAddress[j+1] = CmDescriptor->u.Memory.Start.HighPart;
+ }
+
+ j++;
+ }
+
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Enabel decodes and set the new addresses
+ //
+
+ if (DeviceData->EnableRom && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ }
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ //
+ // If the device is powered on, flush the cached config information
+ // to the device; otherwise, leave the new configuration in memory -
+ // it will get flushed to the device when it's powered on
+ //
+
+ Status = STATUS_SUCCESS;
+ if (DeviceData->Power) {
+ Status = PcipFlushConfig (Context->Handler, DeviceData);
+ }
+
+CleanUp:
+ //
+ // If there was an error, and the device still has a cached current
+ // config, put the configuration back as it was when we found it
+ //
+
+ if (!NT_SUCCESS (Status) && DeviceData->CurrentConfig) {
+ RtlCopyMemory (DeviceData->CurrentConfig, PciOrigData, PCI_COMMON_HDR_LENGTH);
+ }
+
+ return Status;
+}
+
+
+VOID
+PciCtlAssignSlotResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the internal AssignSlotResources DeviceControl
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+ PCTL_ASSIGN_RESOURCES AssignResources;
+ PCM_RESOURCE_LIST AllocatedResources;
+ NTSTATUS Status;
+ ULONG l;
+ POWER_STATE PowerControl;
+
+ PAGED_CODE();
+
+ ResourceList = NULL;
+ AllocatedResources = NULL;
+ AssignResources = (PCTL_ASSIGN_RESOURCES) Context->DeviceControl.Buffer;
+
+ //
+ // If BARBits haven't been deteremined, go do it now
+ //
+
+ Status = PcipVerifyBarBits (DeviceData, Context->Handler);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipQueryResourceRequirements (DeviceData, Context, &ResourceList);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Get device settings from IO
+ //
+
+ Status = IoAssignResources (
+ AssignResources->RegistryPath,
+ AssignResources->DriverClassName,
+ AssignResources->DriverObject,
+ Context->DeviceControl.DeviceObject,
+ ResourceList,
+ &AllocatedResources
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Set the resources into the device
+ //
+
+ Status = PcipSetResources (DeviceData, Context, AllocatedResources, 0xFFFFFFFF);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Turn the device on
+ //
+
+ PowerControl = PowerUp;
+ l = sizeof (PowerControl);
+
+ Status = HalDeviceControl (
+ Context->DeviceControl.DeviceHandler,
+ Context->DeviceControl.DeviceObject,
+ BCTL_SET_POWER,
+ &PowerControl,
+ &l,
+ NULL,
+ NULL
+ );
+
+CleanUp:
+ *AssignResources->AllocatedResources = AllocatedResources;
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (AllocatedResources) {
+ IoAssignResources (
+ AssignResources->RegistryPath,
+ AssignResources->DriverClassName,
+ AssignResources->DriverObject,
+ Context->DeviceControl.DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (AllocatedResources);
+ *AssignResources->AllocatedResources = NULL;
+ }
+ }
+
+ if (ResourceList) {
+ ExFreePool (ResourceList);
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
diff --git a/private/ntos/nthals/extender/pci/init.c b/private/ntos/nthals/extender/pci/init.c
new file mode 100644
index 000000000..f33acf18f
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/init.c
@@ -0,0 +1,357 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ initialization code for pciport.sys
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "pciport.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(PAGE,PciPortInitialize)
+#endif
+
+#if DBG
+VOID
+PcipTestIds (
+ PBUS_HANDLER PciBus
+ )
+{
+ NTSTATUS Status;
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG Device, Function;
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PDEVICE_DATA DeviceData;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ ULONG BufferSize;
+ PWCHAR Wptr;
+ WCHAR Wchar;
+ WCHAR DeviceId[64];
+ PPCI_PORT PciPort;
+
+ PAGED_CODE();
+
+ PciPort = PciBus->DeviceObject->DeviceExtension;
+ PciBusData = (PPCIBUSDATA) (PciBus->BusData);
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ SlotNumber.u.AsULONG = 0;
+ for (Device=0; Device < PCI_MAX_DEVICES; Device++) {
+ SlotNumber.u.bits.DeviceNumber = Device;
+ for (Function=0; Function < PCI_MAX_FUNCTION; Function++) {
+ SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read in the device id
+ //
+
+ PciBusData->ReadConfig (
+ PciBus,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If not valid, skip it
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0 ||
+ (PCI_CONFIG_TYPE(PciData) != PCI_DEVICE_TYPE &&
+ PCI_CONFIG_TYPE(PciData) != PCI_BRIDGE_TYPE)) {
+ break;
+ }
+
+ DeviceData = PcipFindDeviceData (PciPort, SlotNumber);
+ ASSERT(DeviceData);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+
+ BufferSize = sizeof (DeviceId);
+ Status = HalDeviceControl (
+ DeviceHandler,
+ NULL,
+ BCTL_QUERY_DEVICE_UNIQUE_ID,
+ DeviceId,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+
+ ASSERT(NT_SUCCESS(Status));
+ DebugPrint ((2, "PCI: Device Unique ID: "));
+ for (Wptr = DeviceId; Wchar = *Wptr++; ) {
+ char buf[2];
+ buf[0] = (char) Wchar;
+ buf[1] = 0;
+ DebugPrint ((2, buf));
+ }
+ DebugPrint ((2, "\n"));
+ }
+ }
+}
+#endif // DBG
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ Finds any currently installed PCI buses and initializes them as
+ pci miniport drivers
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PDEVICE_OBJECT DeviceObject;
+ PBUS_HANDLER PciBus;
+ NTSTATUS Status;
+ UNICODE_STRING unicodeString;
+ ULONG BusNo, junk;
+ BOOLEAN Install;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PCALLBACK_OBJECT CallbackObject;
+
+
+ PciDriverObject = DriverObject;
+
+ //
+ // Add IRP handler for IRPs we care about
+ //
+
+ // DriverObject->MajorFunction[IRP_MJ_CREATE] =
+ // DriverObject->MajorFunction[IRP_MJ_CLOSE] =
+ // DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
+ // DriverObject->MajorFunction[IRP_MJ_SET_POWER] =
+
+ //
+ // Initialize globals
+ //
+
+ ExInitializeWorkItem (&PcipWorkItem, PcipControlWorker, NULL);
+ KeInitializeSpinLock (&PcipSpinlock);
+ InitializeListHead (&PcipControlWorkerList);
+ InitializeListHead (&PcipControlDpcList);
+ InitializeListHead (&PcipCheckBusList);
+ ExInitializeFastMutex (&PcipMutex);
+ ASSERT(PcipMutex.Owner == NULL);
+ PcipDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
+
+ //
+ // Register on system suspend/hibernate callback
+ //
+
+ RtlInitUnicodeString(&unicodeString, rgzSuspendCallbackName);
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = ExCreateCallback (&CallbackObject, &ObjectAttributes, FALSE, FALSE);
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ PciSuspendRegistration = ExRegisterCallback (
+ CallbackObject,
+ PcipSuspendNotification,
+ NULL
+ );
+
+ ObDereferenceObject (CallbackObject);
+
+ //
+ // Get access to the HAL callback objects
+ //
+
+ HalQuerySystemInformation (
+ HalCallbackInformation,
+ sizeof (PciHalCallbacks),
+ &PciHalCallbacks,
+ &junk
+ );
+
+ //
+ // For each installed PCI bus
+ //
+
+ _asm int 3;
+
+ Install = FALSE;
+ for (BusNo=0; TRUE; BusNo += 1) {
+ PciBus = HalHandlerForBus (PCIBus, BusNo);
+
+ if (!PciBus) {
+ break;
+ }
+
+ Status = PciPortInitialize (PciBus);
+ if (NT_SUCCESS(Status)) {
+ Install = TRUE;
+ }
+ }
+
+ if (Install) {
+ DebugPrint ((1, "PCI: Installed\n"));
+#if DBG
+ for (BusNo=0; PciBus = HalHandlerForBus (PCIBus, BusNo); BusNo += 1) {
+ PcipTestIds(PciBus);
+ }
+#endif
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Not installing - uninitialize
+ //
+
+ DebugPrint ((1, "PCI: No internal PCI buses found - not installing\n"));
+ ExUnregisterCallback (PciSuspendRegistration);
+
+ return STATUS_NO_SUCH_DEVICE;
+}
+
+
+NTSTATUS
+PciPortInitialize (
+ PBUS_HANDLER PciBus
+ )
+{
+ PPCIBUSDATA PciBusData;
+ PDEVICE_OBJECT BusDeviceObject;
+ WCHAR buffer[100];
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ UNICODE_STRING unicodeString;
+ PPCI_PORT PciPort;
+
+ PAGED_CODE();
+
+ //
+ // Verify bus handler is a PCI miniport driver
+ //
+
+ PciBusData = (PPCIBUSDATA) PciBus->BusData;
+ if (PciBus->InterfaceType != PCIBus ||
+ PciBus->ConfigurationType != PCIConfiguration ||
+ !PciBusData ||
+ PciBusData->Tag != PCI_DATA_TAG ||
+ PciBusData->Version != PCI_DATA_VERSION) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Create device object for this bus extention
+ //
+
+ swprintf (buffer, rgzPCIDeviceName, PciBus->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ Status = IoCreateDevice(
+ PciDriverObject,
+ sizeof (PCI_PORT),
+ &unicodeString,
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &BusDeviceObject
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ DebugPrint ((1, "PCI: Adding PCI bus %d\n", PciBus->BusNumber));
+
+ //
+ // Install pointer to pci extension structure
+ //
+
+ PciBusData->Version = 0;
+ PciBusData->PciExtension = (PVOID) BusDeviceObject->DeviceExtension;
+ PciBus->DeviceObject = BusDeviceObject;
+
+ //
+ // Initialize internal pci port structure
+ //
+
+ PciPort = (PPCI_PORT) BusDeviceObject->DeviceExtension;
+ RtlZeroMemory (PciPort, sizeof (PCI_PORT));
+ PciPort->Handler = PciBus;
+ InitializeListHead (&PciPort->CheckBus);
+ InitializeListHead (&PciPort->DeviceControl);
+
+ //
+ // Intall bus specific handlers
+ //
+
+ PciBus->GetBusData = (PGETSETBUSDATA) PcipGetBusData;
+ PciBus->SetBusData = (PGETSETBUSDATA) PcipSetBusData;
+ PciBus->AssignSlotResources = (PASSIGNSLOTRESOURCES) PcipAssignSlotResources;
+ PciBus->QueryBusSlots = (PQUERY_BUS_SLOTS) PcipQueryBusSlots;
+ PciBus->DeviceControl = (PDEVICE_CONTROL) PcipDeviceControl;
+ PciBus->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) PcipReferenceDeviceHandler;
+ PciBus->GetDeviceData = (PGET_SET_DEVICE_DATA) PcipGetDeviceData;
+ PciBus->SetDeviceData = (PGET_SET_DEVICE_DATA) PcipSetDeviceData;
+ PciBus->HibernateBus = (PHIBERNATEBRESUMEBUS) PcipHibernateBus;
+ PciBus->ResumeBus = (PHIBERNATEBRESUMEBUS) PcipResumeBus;
+
+ //
+ // We don't need power control irps - we'll handle all system power
+ // requests via the SystemSuspendHiberante callback and the
+ // bus extender Hibernate & Resume bus entry points
+ //
+
+ BusDeviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE;
+
+ //
+ // BUGBUG: we need to report the resources this PCI bus is using
+ //
+
+ //
+ // Perform initial bus check
+ //
+
+ PcipCheckBus (PciPort, TRUE);
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pci/makefile b/private/ntos/nthals/extender/pci/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/extender/pci/misc.c b/private/ntos/nthals/extender/pci/misc.c
new file mode 100644
index 000000000..beffbc80b
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/misc.c
@@ -0,0 +1,544 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipReadConfig)
+#pragma alloc_text(PAGE,PcipPowerDownSlot)
+#endif
+
+NTSTATUS
+PcipPowerDownSlot (
+ PBUS_HANDLER Handler,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is called to power down a particular slot.
+
+Arguments:
+
+Return Value:
+
+ returns once the slot has powered down
+
+--*/
+{
+ USHORT Command;
+ PPCIBUSDATA PciBusData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // If already powered down, do nothing
+ //
+
+ if (!DeviceData->Power) {
+ return STATUS_SUCCESS;
+ }
+
+ DebugPrint ((2, "PCI: Powering down device - slot %d\n", SlotNumber ));
+
+ //
+ // Allocate buffer to save current device configuration
+ //
+
+ ASSERT (DeviceData->CurrentConfig == NULL);
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePoolWithTag (NonPagedPool, PCI_COMMON_HDR_LENGTH, 'cICP');
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Read the current configuration
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ DeviceData->CurrentConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // Power down the device
+ //
+
+ DeviceData->Power = FALSE;
+
+ // BUGBUG: should pass this request on
+
+ //
+ // Emulate a powered down device by turning off the device decodes
+ //
+
+ Command = DeviceData->CurrentConfig->Command;
+ Command &= ~(PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ &Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Command)
+ );
+
+ DebugPrint ((2, "PCI: Powerdown complete - Slot %x, Status %x\n",
+ SlotNumber, STATUS_SUCCESS));
+
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+PcipPowerUpSlot (
+ PBUS_HANDLER Handler,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is called to power down a particular slot.
+
+Arguments:
+
+Return Value:
+
+ returns once the slot has powered down
+
+--*/
+{
+ //
+ // If already powered up, do nothing
+ //
+
+ if (!DeviceData->Power) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Power up the device
+ //
+
+ DebugPrint ((2, "PCI: Powering up device - slot %d\n", DeviceDataSlot(DeviceData) ));
+
+ DeviceData->Power = TRUE;
+
+ // BUGBUG: should pass this request on
+
+}
+
+
+
+VOID
+PcipReadConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData,
+ OUT PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+Routine Description:
+
+ This function returns the current PCI_COMMON_HDR for the device.
+ If the device is powered off, then the pci_common_hdr is returned
+ from it's memory image; otherwise, it is read from the device.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot (DeviceData);
+
+ if (!DeviceData->Power) {
+
+ //
+ // The slot is powered down, return the devices
+ // current configuration from memory
+ //
+
+ RtlCopyMemory (PciData, DeviceData->CurrentConfig, PCI_COMMON_HDR_LENGTH);
+ return ;
+ }
+
+ //
+ // Read the devices current configuration from the device
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+}
+
+NTSTATUS
+PcipFlushConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the cached configuration to the PCI device.
+ It properly handles disabling & enabling of the memory & io decodes,
+ and verifies the new base address register settings. If the device
+ does not take the new settings, if the original settings are known
+ they are put back into the device.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ USHORT HoldCommand;
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ NTSTATUS Status;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ PciData2 = (PPCI_COMMON_CONFIG) buffer;
+ PciData = DeviceData->CurrentConfig;
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // To flush the settings, the device must be in the powered on state
+ //
+
+ ASSERT (DeviceData->Power);
+
+ //
+ // Read what is currently in the device
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData2,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // Had better be correct device
+ //
+
+ ASSERT (PciData->VendorID == PciData2->VendorID);
+ ASSERT (PciData->DeviceID == PciData2->DeviceID);
+
+ //
+ // If decodes aren't the same, then clear decode enables before
+ // performing initial set
+ //
+
+ HoldCommand = DeviceData->CurrentConfig->Command;
+ if (!PcipCompareDecodes (DeviceData, PciData, PciData2)) {
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+ }
+
+ //
+ // Write the current device condifuragtion
+ //
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ DeviceData->CurrentConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // Read back the configuration and verify it took
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData2,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // See if configuration matches
+ //
+
+ if (!PcipCompareDecodes (DeviceData, PciData, PciData2)) {
+
+ //
+ // The CurrentConfig did not get successfully set
+ //
+
+ DebugPrint ((1, "PCI: defective device - slot %d\n", SlotNumber));
+ DeviceData->BrokenDevice = TRUE;
+ Status = STATUS_DEVICE_PROTOCOL_ERROR;
+
+ } else {
+
+ //
+ // Settings are fine - write final decode enable bits
+ //
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ &HoldCommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (HoldCommand)
+ );
+
+ Status = STATUS_SUCCESS;
+ }
+
+ //
+ // Current config now flushed to the device. Free memory.
+ //
+
+ if (DeviceData->CurrentConfig) {
+ ExFreePool (DeviceData->CurrentConfig);
+ DeviceData->CurrentConfig = NULL;
+ }
+
+ return Status;
+}
+
+BOOLEAN
+PcipCompareDecodes (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ IN PPCI_COMMON_CONFIG PciData2
+ )
+/*++
+
+Routine Description:
+
+ This function compares the base address registers of PciData and PciData2.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG BaseAddress2[PCI_TYPE0_ADDRESSES + 1];
+ ULONG NoBaseAddress, RomIndex;
+ ULONG NoBaseAddress2, RomIndex2;
+ ULONG i, j;
+ BOOLEAN Match;
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData2,
+ BaseAddress2,
+ &NoBaseAddress2,
+ &RomIndex2
+ );
+
+ if (NoBaseAddress != NoBaseAddress2 ||
+ RomIndex != RomIndex2) {
+ return FALSE;
+ }
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) != (*BaseAddress2[j] & i)) {
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ j++;
+ if ((*BaseAddress[j] & i) != (*BaseAddress2[j] & i)) {
+ Match = FALSE;
+ }
+ }
+ }
+ }
+
+ return Match;
+}
+
+
+
+BOOLEAN
+PcipCalcBaseAddrPointers (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ OUT PULONG *BaseAddress,
+ OUT PULONG NoBaseAddress,
+ OUT PULONG RomIndex
+ )
+/*++
+
+Routine Description:
+
+ This function returns the an array of BaseAddress pointers
+ in PciData.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ULONG j;
+ BOOLEAN RomEnabled;
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case PCI_DEVICE_TYPE:
+ *NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ *RomIndex = j;
+ break;
+
+ case PCI_BRIDGE_TYPE:
+ *NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ *RomIndex = j;
+ break;
+
+ default:
+
+ // BUGBUG: unkown type
+
+ *NoBaseAddress = 0;
+ ASSERT (*NoBaseAddress);
+ }
+
+ RomEnabled = (*BaseAddress[*RomIndex] & PCI_ROMADDRESS_ENABLED) ? TRUE : FALSE;
+
+ //
+ // The device's Rom Base Address register is only enabled if it
+ // was originaly found that way.
+ //
+
+ // Clear ROM reserved bits
+ *BaseAddress[*RomIndex] &= ~0x7FF;
+
+ if (!DeviceData->EnableRom) {
+ ASSERT (*RomIndex+1 == *NoBaseAddress);
+ *NoBaseAddress -= 1;
+ }
+
+ return RomEnabled;
+}
+
+
+#if DBG
+ULONG ApmDebug = 9;
+
+VOID
+PciDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ if (Level <= ApmDebug) {
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ }
+
+ va_end(ap);
+}
+#endif
+
+
+
+NTSTATUS
+BugBugSubclass (
+ VOID
+ )
+{
+ DbgPrint ("PCI: BUGBUG SUBCLASS\n");
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pci/pcidata.c b/private/ntos/nthals/extender/pci/pcidata.c
new file mode 100644
index 000000000..b6783c526
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/pcidata.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "pciport.h"
+
+//
+// PcipWorkdListLock - Lock to protect DeviceControl globals
+// PcipControlWorkerList - List of slot control's which are pending for worker thread
+// PcipControlDpcList - List of slot control's which are waiting, but are non-paged
+// PcipWorkItem - Enqueue for DeviceControl worker thread
+// PcipWorkDpc - Enqueue for DeviceControl DPC
+//
+
+FAST_MUTEX PcipMutex;
+KSPIN_LOCK PcipSpinlock;
+LIST_ENTRY PcipControlWorkerList;
+LIST_ENTRY PcipControlDpcList;
+LIST_ENTRY PcipCheckBusList;
+ULONG PcipWorkerQueued;
+WORK_QUEUE_ITEM PcipWorkItem;
+KDPC PcipWorkDpc;
+ULONG PcipDeviceHandlerObjectSize;
+
+//
+// DeviceControl dispatch table
+//
+
+#define B_EJECT BCTL_EJECT
+#define B_ID BCTL_QUERY_DEVICE_ID
+#define B_UID BCTL_QUERY_DEVICE_UNIQUE_ID
+#define B_CAPABILITIES BCTL_QUERY_DEVICE_CAPABILITIES
+#define B_RES BCTL_QUERY_DEVICE_RESOURCES
+#define B_RES_REQ BCTL_QUERY_DEVICE_RESOURCE_REQUIREMENTS
+#define B_QUERY_EJECT BCTL_QUERY_EJECT
+#define B_SET_LOCK BCTL_SET_LOCK
+#define B_SET_POWER BCTL_SET_POWER
+#define B_SET_RESUME BCTL_SET_RESUME
+#define B_SET_RES BCTL_SET_DEVICE_RESOURCES
+#define B_ASSIGN_RES BCTL_ASSIGN_SLOT_RESOURCES
+
+#define SIZE_BRES sizeof(CTL_ASSIGN_RESOURCES)
+#define SIZE_CAP sizeof(BCTL_DEVICE_CAPABILITIES)
+#define SIZE_CALL sizeof(PCALLBACK_OBJECT)
+
+DEVICE_CONTROL_HANDLER PcipControl[] = {
+ B_EJECT, 0, PciBCtlEject, PciCtlEject,
+ B_ID, 128, PciBCtlSync, PciCtlQueryDeviceId,
+ B_UID, 128, PciBCtlSync, PciCtlQueryDeviceUniqueId,
+ B_CAPABILITIES, SIZE_CAP, PciBCtlSync, PciCtlForward, // bugbug
+ B_RES, sizeof(ULONG), PciBCtlSync, PciCtlQueryDeviceResources,
+ B_RES_REQ, sizeof(ULONG), PciBCtlSync, PciCtlQueryDeviceResourceRequirements,
+ B_QUERY_EJECT, SIZE_CALL, PciBCtlSync, PciCtlForward,
+ B_SET_LOCK, sizeof(BOOLEAN), PciBCtlLock, PciCtlLock,
+ B_SET_RESUME, sizeof(BOOLEAN), PciBCtlSync, PciCtlForward,
+ B_SET_POWER, sizeof(POWER_STATE), PciBCtlPower, PciCtlPower,
+ B_SET_RES, 0, PciBCtlSync, PciCtlSetDeviceResources,
+ B_ASSIGN_RES, SIZE_BRES, PciBCtlSync, PciCtlAssignSlotResources,
+ 0, 0, NULL, NULL
+};
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("PAGE")
+#endif
+
+//
+// PciDriverObject - the driver object for pciport.sys
+//
+
+
+PDRIVER_OBJECT PciDriverObject;
+
+//
+// PciCodeLock - Handle for locked code (only used during system
+// Suspend/Hibernate/Resume procedure)
+//
+
+PVOID PciCodeLock;
+
+//
+// PciSuspendRegistration - A registration to the systems
+// Suspend/Hibernate/Resume callback
+//
+
+HAL_CALLBACKS PciHalCallbacks;
+
+//
+// PciSuspendRegistration - A registration to the systems
+// Suspend/Hibernate/Resume callback
+//
+
+PVOID PciSuspendRegistration;
+
+//
+// Some global strings
+//
+
+WCHAR rgzPCIDeviceName[] = L"\\Device\\PciBus_%d";
+WCHAR rgzSuspendCallbackName[] = L"\\Callback\\SuspendHibernateSystem";
+
+WCHAR PCI_ID[] = L"PCI\\%04x_%04x";
+WCHAR PNP_VGA[] = L"PCI\\*PNP_VGA";
+WCHAR PNP_IDE[] = L"PCI\\*PNP_IDE";
diff --git a/private/ntos/nthals/extender/pci/pciport.h b/private/ntos/nthals/extender/pci/pciport.h
new file mode 100644
index 000000000..9e4870ebc
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/pciport.h
@@ -0,0 +1,570 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ pciport.h
+
+Abstract:
+
+ header file for pciport.sys
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "pci.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+//
+// Structures
+//
+
+
+#define PciExtension Reserved[0]
+
+//
+// When queued, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextWorkQueue BusExtenderReserved[0]
+#define ContextControlHandler BusExtenderReserved[2]
+
+//
+// When in progress, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextArgument1 BusExtenderReserved[0]
+#define ContextArgument2 BusExtenderReserved[1]
+#define ContextBusyFlag BusExtenderReserved[2]
+
+#define PCIPORTDATA(a) \
+ ((PPCI_PORT) ( ((PPCIBUSDATA) (a)->BusData)->PciExtension))
+
+#define PCI_CONFIG_TYPE(PciData) \
+ ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#define MAX_VALID_DEVICE_HANDLE 0x7FFFFFFF
+
+// the follow are handle value states when the handle is > MAX_VALID_DEVICE_HANDLE
+#define INITIALIZE_DEVICE_HANDLE 0x80000000
+#define TRANSISTION_DEVICE_HANDLE 0x80000001
+#define INVALID_DEVICE_HANDLE 0x80000002
+
+typedef struct _DEVICE_DATA_ {
+ SINGLE_LIST_ENTRY Next;
+
+ //
+ // SlotNumber for which this device data corrisponds
+ //
+
+ //PCI_SLOT_NUMBER SlotNumber;
+
+ //
+ //
+ //
+
+ BOOLEAN Valid;
+
+ //
+ // DeviceControl in progress flags
+ //
+
+ BOOLEAN SyncBusy;
+ BOOLEAN AsyncBusy;
+
+
+ //
+ // Track the lock state of the device
+ // PendPowerUp is used while an Unlock is in progress
+ // to cause a power up request to wait
+ //
+
+ BOOLEAN Locked;
+ BOOLEAN PendPowerUp;
+
+ //
+ // Track the power state of the device.
+ // If it's powered off, track the device's configuration.
+ //
+ // If the powered off configuration has changed, track the
+ // original configuration in case the new configuration is
+ // not supported by the h/w. (would be a defective device)
+ //
+
+ BOOLEAN Power;
+ PPCI_COMMON_CONFIG CurrentConfig;
+
+ //
+ // Since PCI doesn't have a runtime safe way to determine
+ // the length of it's base register's will we keep track
+ // of them here.
+ //
+
+ ULONG BARBits[PCI_TYPE0_ADDRESSES+1];
+
+ //
+ //
+ //
+
+ BOOLEAN BARBitsSet;
+
+
+ //
+ // Determine if the device's rom base address register should
+ // be enabled
+ //
+
+ BOOLEAN EnableRom;
+
+ //
+ // Flag defective hardware which we've noticed that it's base
+ // address registers do not function properly.
+ //
+
+ BOOLEAN BrokenDevice;
+
+} DEVICE_DATA, *PDEVICE_DATA;
+
+extern POBJECT_TYPE *IoDeviceHandlerObjectType;
+extern PULONG IoDeviceHandlerObjectSize;
+#define DeviceHandler2DeviceData(a) ((PDEVICE_DATA) (((PUCHAR) a) + PcipDeviceHandlerObjectSize))
+#define DeviceData2DeviceHandler(a) ((PDEVICE_HANDLER_OBJECT) (((PUCHAR) a) - PcipDeviceHandlerObjectSize))
+#define DeviceDataSlot(a) DeviceData2DeviceHandler(a)->SlotNumber
+
+typedef struct {
+ BOOLEAN Control;
+} *PBCTL_SET_CONTROL;
+
+typedef struct {
+ PBUS_HANDLER Handler;
+ LIST_ENTRY CheckBus;
+ LIST_ENTRY DeviceControl;
+
+ ULONG NoValidSlots;
+ SINGLE_LIST_ENTRY ValidSlots;
+
+ PVOID Spare;
+} PCI_PORT, *PPCI_PORT;
+
+
+//
+// Internal DeviceControls
+//
+
+#define BCTL_ASSIGN_SLOT_RESOURCES 0x90000001
+#define BCTL_CHECK_DEVICE 0x90000002
+#define BCTL_INITIAL_DEVICE 0x90000003
+
+typedef struct {
+ PUNICODE_STRING RegistryPath;
+ PUNICODE_STRING DriverClassName;
+ PDRIVER_OBJECT DriverObject;
+ PCM_RESOURCE_LIST *AllocatedResources;
+} CTL_ASSIGN_RESOURCES, *PCTL_ASSIGN_RESOURCES;
+
+typedef BOOLEAN (FASTCALL * BGNFNC)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+typedef VOID (* CTLFNC)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+
+typedef struct {
+ ULONG ControlCode;
+ ULONG MinBuffer;
+ BGNFNC BeginDeviceControl;
+ CTLFNC ControlHandler;
+} DEVICE_CONTROL_HANDLER, *PDEVICE_CONTROL_HANDLER;
+
+//
+//
+//
+
+#if DBG
+VOID PciDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+#define DebugPrint(arg) PciDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
+
+//
+// Globals
+//
+
+extern FAST_MUTEX PcipMutex;
+extern KSPIN_LOCK PcipSpinlock;
+extern LIST_ENTRY PcipControlWorkerList;
+extern LIST_ENTRY PcipControlDpcList;
+extern LIST_ENTRY PcipCheckBusList;
+extern ULONG PcipWorkerQueued;
+extern WORK_QUEUE_ITEM PcipWorkItem;
+extern KDPC PcipWorkDpc;
+extern ULONG PcipNextHandle;
+extern DEVICE_CONTROL_HANDLER PcipControl[];
+extern PDRIVER_OBJECT PciDriverObject;
+extern HAL_CALLBACKS PciHalCallbacks;
+extern PVOID PciSuspendRegistration;
+extern PVOID PciCodeLock;
+extern WCHAR rgzPCIDeviceName[];
+extern WCHAR rgzSuspendCallbackName[];
+extern WCHAR PCI_ID[];
+extern WCHAR PNP_VGA[];
+extern WCHAR PNP_IDE[];
+extern BOOLEAN PcipNoBusyFlag;
+extern ULONG PcipDeviceHandlerObjectSize;
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+
+NTSTATUS
+PciPortInitialize (
+ PBUS_HANDLER PciBus
+ );
+
+ULONG
+PcipGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PcipGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PcipSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PcipSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+PcipAssignSlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+NTSTATUS
+PcipQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+PDEVICE_HANDLER_OBJECT
+PcipReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber
+ );
+
+NTSTATUS
+PcipDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+NTSTATUS
+PcipHibernateBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+PcipResumeBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+VOID
+PcipSuspendNotification (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ );
+
+VOID
+PcipStartWorker (
+ VOID
+ );
+
+VOID
+PcipControlWorker (
+ IN PVOID WorkerContext
+ );
+
+VOID
+PcipControlDpc (
+ PKDPC Dpc,
+ PVOID DeferredContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2
+ );
+
+VOID
+PcipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlNone (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlSync (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlSetDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlAssignSlotResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlNone (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlResume (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlForward (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PcipCompletePowerUp (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PcipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData
+ );
+
+VOID
+PcipReadConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData,
+ OUT PPCI_COMMON_CONFIG PciData
+ );
+
+NTSTATUS
+PcipFlushConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData
+ );
+
+BOOLEAN
+PcipCompareDecodes (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ IN PPCI_COMMON_CONFIG PciData2
+ );
+
+BOOLEAN
+PcipCalcBaseAddrPointers (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ OUT PULONG *BaseAddress,
+ OUT PULONG NoBaseAddress,
+ OUT PULONG RomIndex
+ );
+
+NTSTATUS
+PcipPowerDownSlot (
+ PBUS_HANDLER Handler,
+ PDEVICE_DATA DeviceData
+ );
+
+VOID
+PciCtlCheckDevice (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+NTSTATUS
+PcipVerifyBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ );
+
+NTSTATUS
+PcipGetBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ );
+
+PDEVICE_DATA
+PcipFindDeviceData (
+ IN PPCI_PORT PciPort,
+ IN PCI_SLOT_NUMBER SlotNumber
+ );
+
+VOID
+PcipCheckBus (
+ PPCI_PORT PciPort,
+ BOOLEAN Initialize
+ );
+
+BOOLEAN
+PcipCrackBAR (
+ IN PULONG *BaseAddress,
+ IN PULONG BarBits,
+ IN OUT PULONG Index,
+ OUT PLONGLONG pbase,
+ OUT PLONGLONG plength,
+ OUT PLONGLONG pmax
+ );
+
+NTSTATUS
+BugBugSubclass (
+ VOID
+ );
diff --git a/private/ntos/nthals/extender/pci/pciport.rc b/private/ntos/nthals/extender/pci/pciport.rc
new file mode 100644
index 000000000..a9a5fec4b
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/pciport.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "PCI Bus Class Driver"
+#define VER_INTERNALNAME_STR "pciext.sys"
+#define VER_ORIGINALFILENAME_STR "pciext.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pci/port.c b/private/ntos/nthals/extender/pci/port.c
new file mode 100644
index 000000000..e78ba1537
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/port.c
@@ -0,0 +1,713 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ port.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipAssignSlotResources)
+#pragma alloc_text(PAGE,PcipQueryBusSlots)
+#pragma alloc_text(PAGE,PcipHibernateBus)
+#pragma alloc_text(PAGE,PcipResumeBus)
+#pragma alloc_text(PAGE,PcipSuspendNotification)
+#pragma alloc_text(PAGE,PcipReferenceDeviceHandler)
+#endif
+
+
+ULONG
+PcipGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ BusData = (PPCIBUSDATA) BusHandler->BusData;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, sizeof (ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->Pin2Line (BusHandler, RootHandler, SlotNumber, PciData);
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ BusData->ReadConfig (BusHandler, SlotNumber, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+
+ULONG
+PcipGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ ULONG Status;
+ PDEVICE_DATA DeviceData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ Status = 0;
+ DeviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!DeviceData->Valid) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ return 0;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ if (DataType == 0) {
+
+ //
+ // Type 0 is the same as GetBusData for the slot
+ //
+
+ SlotNumber.u.AsULONG = DeviceHandler->SlotNumber;
+ Status = PcipGetBusData (
+ BusHandler,
+ RootHandler,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+
+ return Status;
+}
+
+
+ULONG
+PcipSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIBUSDATA BusData;
+ ULONG Len, cnt;
+
+ BusData = (PPCIBUSDATA) BusHandler->BusData;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->Pin2Line (BusHandler, RootHandler, SlotNumber, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->Line2Pin (BusHandler, RootHandler, SlotNumber, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ BusData->WriteConfig (BusHandler, SlotNumber, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ BusData->WriteConfig (BusHandler, SlotNumber, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+PcipSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ ULONG Status;
+ PDEVICE_DATA DeviceData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ Status = 0;
+ DeviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!DeviceData->Valid) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ return 0;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ if (DataType == 0) {
+
+ //
+ // Type 0 is the same as SetBusData for the slot
+ //
+
+ SlotNumber.u.AsULONG = DeviceHandler->SlotNumber;
+ Status = PcipGetBusData (
+ BusHandler,
+ RootHandler,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+
+ return Status;
+}
+
+
+
+NTSTATUS
+PcipAssignSlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+{
+ CTL_ASSIGN_RESOURCES AssignResources;
+ KEVENT CompletionEvent;
+ ULONG BufferSize;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ NTSTATUS Status;
+
+ PAGED_CODE ();
+
+ //
+ // Foreward this request through a DeviceControl such that it
+ // gets the proper synchronzation on the device
+ //
+
+ DeviceHandler = BusHandler->ReferenceDeviceHandler (
+ BusHandler,
+ BusHandler,
+ SlotNumber
+ );
+
+ if (!DeviceHandler) {
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ AssignResources.RegistryPath = RegistryPath;
+ AssignResources.DriverClassName = DriverClassName;
+ AssignResources.DriverObject = DriverObject;
+ AssignResources.AllocatedResources = AllocatedResources;
+ BufferSize = sizeof (AssignResources);
+
+ //
+ // Make synchrous DeviceControl request
+ //
+
+ Status = HalDeviceControl (
+ DeviceHandler,
+ DeviceObject,
+ BCTL_ASSIGN_SLOT_RESOURCES,
+ &AssignResources,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+
+ //
+ // Free the reference to DeviceHandler
+ //
+
+ ObDereferenceObject (DeviceHandler);
+
+ //
+ // Done
+ //
+
+ return Status;
+}
+
+
+NTSTATUS
+PcipQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+{
+ PSINGLE_LIST_ENTRY Link;
+ PPCI_PORT PciPort;
+ PDEVICE_DATA DeviceData;
+ ULONG cnt;
+
+ PAGED_CODE ();
+
+ PciPort = PCIPORTDATA (BusHandler);
+
+ //
+ // Synchronize will new devices being added
+ //
+
+ ExAcquireFastMutex (&PcipMutex);
+
+ //
+ // Fill in returned buffer length, or what size buffer is needed
+ //
+
+
+ *ReturnedLength = PciPort->NoValidSlots * sizeof (ULONG);
+ if (BufferSize < *ReturnedLength) {
+
+ //
+ // Callers buffer is not large enough
+ //
+
+ ExReleaseFastMutex (&PcipMutex);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Return caller all the possible slot number
+ //
+
+ cnt = 0;
+ for (Link = PciPort->ValidSlots.Next; Link; Link = Link->Next) {
+ DeviceData = CONTAINING_RECORD (Link, DEVICE_DATA, Next);
+ if (DeviceData->Valid) {
+ cnt += 1;
+ *(SlotNumbers++) = DeviceDataSlot(DeviceData);
+ }
+ }
+
+ *ReturnedLength = cnt * sizeof (ULONG);
+ ExReleaseFastMutex (&PcipMutex);
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+PcipDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ ULONG i;
+ ULONG ControlCode;
+ ULONG Junk;
+ PULONG BufferLength;
+ PLIST_ENTRY OldTail;
+ BOOLEAN UseWorker;
+
+ for (i=0; PcipControl[i].ControlHandler; i++) {
+ if (PcipControl[i].ControlCode == Context->DeviceControl.ControlCode) {
+
+ //
+ // Found DeviceControl handler
+ //
+
+ Context->ContextControlHandler = (ULONG) (PcipControl + i);
+
+ //
+ // Verify callers buffer is the min required length
+ //
+
+
+ if (*Context->DeviceControl.BufferLength < PcipControl[i].MinBuffer) {
+ Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
+ *Context->DeviceControl.BufferLength = PcipControl[i].MinBuffer;
+ HalCompleteDeviceControl (Context);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL ||
+ (Context->DeviceControl.ControlCode == BCTL_SET_POWER &&
+ *((PPOWER_STATE) Context->DeviceControl.Buffer) == PowerUp)){
+
+ //
+ // All slot controls, expect a power up request, may touch
+ // paged code or data. If the current irql is low enough or
+ // this is a power up go dispatch now; otherwise, queue the
+ // request to a worker thread.
+ //
+
+ PcipDispatchControl (Context);
+
+ } else {
+
+ //
+ // Enqueue to worker thread
+ //
+
+ ExInterlockedInsertTailList (
+ &PcipControlWorkerList,
+ (PLIST_ENTRY) &Context->ContextWorkQueue,
+ &PcipSpinlock
+ );
+
+ //
+ // Make sure worker is requested
+ //
+
+ PcipStartWorker ();
+ }
+
+
+ return STATUS_PENDING;
+ }
+ }
+
+ //
+ // Unkown control code
+ //
+
+ return STATUS_INVALID_PARAMETER;
+}
+
+PDEVICE_HANDLER_OBJECT
+PcipReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber
+ )
+{
+ PDEVICE_DATA DeviceData;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ PPCI_PORT PciPort;
+ NTSTATUS Status;
+
+ PAGED_CODE ();
+
+ ExAcquireFastMutex (&PcipMutex);
+
+ PciPort = PCIPORTDATA(BusHandler);
+ DeviceData = PcipFindDeviceData (PciPort, SlotNumber);
+ DeviceHandler = NULL;
+ if (DeviceData) {
+ DeviceHandler = DeviceData2DeviceHandler (DeviceData);
+ Status = ObReferenceObjectByPointer(
+ DeviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ DeviceHandler = NULL;
+ }
+ }
+
+ ExReleaseFastMutex (&PcipMutex);
+ return DeviceHandler;
+}
+
+
+
+NTSTATUS
+PcipHibernateBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ )
+{
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+
+
+NTSTATUS
+PcipResumeBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ )
+{
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+PcipSuspendNotification (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ PAGED_CODE();
+
+ switch ((ULONG) Argument1) {
+ case 0:
+ //
+ // Lock code down which might be needed to perform a suspend
+ //
+
+ ASSERT (PciCodeLock == NULL);
+ PciCodeLock = MmLockPagableCodeSection (&PcipHibernateBus);
+ break;
+
+ case 1:
+ //
+ // Release the code lock
+ //
+
+ MmUnlockPagableImageSection (PciCodeLock);
+ PciCodeLock = NULL;
+ break;
+ }
+}
diff --git a/private/ntos/nthals/extender/pci/sources b/private/ntos/nthals/extender/pci/sources
new file mode 100644
index 000000000..4f5a2e927
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=dd
+
+TARGETNAME=pciport
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=pciport.rc \
+ pcidata.c \
+ bus.c \
+ control.c \
+ devres.c \
+ init.c \
+ misc.c \
+ port.c
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=
diff --git a/private/ntos/nthals/extender/pnpbios/i386/bus.c b/private/ntos/nthals/extender/pnpbios/i386/bus.c
new file mode 100644
index 000000000..b002bf1cf
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/bus.c
@@ -0,0 +1,886 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ port.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) May-20-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+VOID
+MbpInvalidateSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ );
+
+VOID
+MbpDeleteSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,MbQueryBusSlots)
+#pragma alloc_text(PAGE,MbpCheckBus)
+#pragma alloc_text(PAGE,MbpReferenceDeviceHandler)
+#endif
+
+
+ULONG
+MbGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+MbSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function sets the Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to be set.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+MbGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ ULONG dataLength;
+ PDEVICE_DATA deviceData;
+
+ UNREFERENCED_PARAMETER ( DataType);
+
+ dataLength = 0;
+ deviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!(deviceData->Flags & DEVICE_FLAGS_VALID)) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ return dataLength;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ //
+ // Synchronize with other pnp bios service functions.
+ //
+
+ ExAcquireFastMutex(&MbpMutex);
+
+ dataLength = deviceData->BusDataLength;
+ if (Offset < dataLength) {
+ dataLength -= Offset;
+ if (dataLength > Length) {
+ dataLength = Length;
+ }
+ RtlMoveMemory(Buffer, (PUCHAR)deviceData->BusData + Offset, dataLength);
+ } else {
+ dataLength = 0;
+ }
+
+ ExReleaseFastMutex(&MbpMutex);
+ return dataLength;
+}
+
+ULONG
+MbSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data set.
+
+--*/
+{
+ //
+ // We don't let drivers change Pnp device data.
+ //
+
+ return 0;
+}
+
+NTSTATUS
+MbQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns a list of currently available SlotNumber.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ SlotNumber - Supplies a variable to receives the number of available slots.
+
+ Length - Supplies a count in bytes of the stored data. If this function
+ returns STATUS_BUFFER_TOO_SMALL, this variable supplies the required
+ size.
+
+Return Value:
+
+ STATUS_BUFFER_TOO_SMALL if caller supplied buffer is not big enough.
+
+--*/
+
+{
+ PMB_BUS_EXTENSION busExtension;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_DATA deviceData;
+ ULONG count = 0;
+
+ PAGED_CODE ();
+
+ busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
+
+ //
+ // Synchronize with other pnp bios device handle assignment.
+ //
+
+ ExAcquireFastMutex(&MbpMutex);
+
+ //
+ // Fill in returned buffer length, or what size buffer is needed
+ //
+
+
+ *ReturnedLength = busExtension->NoValidSlots * sizeof (ULONG);
+ if (BufferSize < *ReturnedLength) {
+
+ //
+ // Callers buffer is not large enough
+ //
+
+ ExReleaseFastMutex (&MbpMutex);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Return caller all the possible slot number
+ //
+
+ for (link = busExtension->ValidSlots.Next; link; link = link->Next) {
+ deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
+ if (deviceData->Flags & DEVICE_FLAGS_VALID) {
+ *SlotNumbers = DeviceDataSlot(deviceData);
+ SlotNumbers++;
+ count += 1;
+ }
+ }
+
+ *ReturnedLength = count * sizeof (ULONG);
+ ExReleaseFastMutex (&MbpMutex);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ The function is the bus handler specific verion of HalDeviceControl.
+
+Arguments:
+
+ Context - The DeviceControl context. The context has all the information
+ for the HalDeviceControl operation being performed.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ ULONG i, junk;
+ ULONG controlCode;
+ PULONG bufferLength;
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ for (i = 0; i < NUMBER_DEVICE_CONTROL_FUNCTIONS; i++) {
+
+ if (MbpDeviceControl[i].ControlCode == Context->DeviceControl.ControlCode) {
+ if (MbpDeviceControl[i].ControlHandler == NULL) {
+ Context->DeviceControl.Status = STATUS_NOT_IMPLEMENTED;
+ status = STATUS_NOT_IMPLEMENTED;
+ goto deviceControlDone;
+ }
+
+ //
+ // Found DeviceControl handler
+ //
+
+ Context->ContextControlHandler = (ULONG)(MbpDeviceControl + i);
+
+ //
+ // Verify callers buffer is the min required length
+ //
+
+ if (*Context->DeviceControl.BufferLength < MbpDeviceControl[i].MinBuffer) {
+ Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
+ *Context->DeviceControl.BufferLength = MbpDeviceControl[i].MinBuffer;
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto deviceControlDone;
+ }
+
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
+
+ //
+ // All supported slot control functions touch paged code or data.
+ // If the current irql is low enough go dispatch now; otherwise,
+ // queue the request to a worker thread.
+ //
+
+ MbpDispatchControl (Context);
+
+ } else {
+
+ //
+ // Enqueue to worker thread
+ //
+
+ ExInterlockedInsertTailList (
+ &MbpControlWorkerList,
+ (PLIST_ENTRY) &Context->ContextWorkQueue,
+ &MbpSpinlock
+ );
+
+ //
+ // Make sure worker is requested
+ //
+
+ MbpStartWorker ();
+ }
+ return STATUS_PENDING;
+ }
+ }
+
+deviceControlDone:
+ HalCompleteDeviceControl (Context);
+ return status;
+}
+
+VOID
+MbpCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+
+/*++
+
+Routine Description:
+
+ The function reenumerates the bus specified by BusHandler.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the BusHandler of the bus to be enumerated.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG slotNumber, nextSlotNumber;
+ BOOLEAN dockConnector;
+ PDEVICE_DATA deviceData;
+ PPNP_BIOS_DEVICE_NODE busData;
+ PMB_BUS_EXTENSION busExtension;
+ ULONG length, noSlots;
+ NTSTATUS status;
+ PHAL_SYSTEM_DOCK_INFORMATION dockInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ ULONG objectSize;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ BOOLEAN notifyBusCheck;
+
+ PAGED_CODE();
+
+ busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
+ notifyBusCheck = FALSE;
+
+ //
+ // We may be removing references to this bus handler, so add
+ // a reference now
+ //
+
+ HalReferenceBusHandler (BusHandler);
+
+ //
+ // Acquire fast mutex to access device data
+ //
+
+ ExAcquireFastMutex (&MbpMutex);
+ MbpInvalidateSlots(busExtension);
+
+ //
+ // Check the bus for new devices
+ //
+
+ nextSlotNumber = 0;
+ while (nextSlotNumber != (ULONG) -1) {
+ slotNumber = nextSlotNumber;
+ status = MbpGetBusData(BusHandler->BusNumber,
+ &nextSlotNumber,
+ &busData,
+ &length,
+ &dockConnector);
+ if (NT_SUCCESS(status)) {
+ deviceData = MbpFindDeviceData (busExtension, slotNumber);
+ if (deviceData == NULL ||
+ length != deviceData->BusDataLength ||
+ RtlCompareMemory(busData, deviceData->BusData, length) != length) {
+
+ notifyBusCheck = TRUE;
+
+ //
+ // if Not found - this is a newly added device or
+ // if devicedata exists already, make sure its busdata is not changed.
+ // Otherwise, we assign a new handler to this slot. This invalidate
+ // the access to the old bus data.
+ //
+
+ //
+ // Initialize the object attributes that will be used to create the
+ // Device Handler Object.
+ //
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+
+ objectSize = MbpDeviceHandlerObjectSize + sizeof (DEVICE_DATA);
+
+ //
+ // Create the object
+ //
+
+ status = ObCreateObject(
+ KernelMode,
+ *IoDeviceHandlerObjectType,
+ &objectAttributes,
+ KernelMode,
+ NULL,
+ objectSize,
+ 0,
+ 0,
+ (PVOID *) &deviceHandler
+ );
+
+ if (NT_SUCCESS(status)) {
+ RtlZeroMemory (deviceHandler, objectSize);
+
+ deviceHandler->Type = (USHORT) *IoDeviceHandlerObjectType;
+ deviceHandler->Size = (USHORT) objectSize;
+ if (dockConnector) {
+ deviceHandler->SlotNumber = DOCK_VIRTUAL_SLOT_NUMBER;
+ } else {
+ deviceHandler->SlotNumber = slotNumber;
+ }
+
+ //
+ // Get a reference to the object
+ //
+
+ status = ObReferenceObjectByPointer(
+ deviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // Insert it into the object table
+ //
+
+ status = ObInsertObject(
+ deviceHandler,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ NULL,
+ &handle
+ );
+ }
+
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Object not created correctly. Skip this slot.
+ //
+
+ continue;
+ }
+
+ ZwClose (handle);
+
+ //
+ // Intialize device tracking structure
+ //
+
+ deviceHandler->BusHandler = BusHandler;
+ HalReferenceBusHandler(BusHandler);
+
+ deviceData = DeviceHandler2DeviceData(deviceHandler);
+ deviceData->BusData = busData;
+ deviceData->BusDataLength = length;
+ deviceData->Flags |= DEVICE_FLAGS_VALID;
+
+ DebugPrint ((DEBUG_MESSAGE, "PnpBios: adding slot %x\n", DeviceDataSlot(deviceData)));
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ busExtension->NoValidSlots += 1;
+ ExInterlockedPushEntryList (
+ &busExtension->ValidSlots,
+ &deviceData->Next,
+ &MbpSpinlock
+ );
+ } else {
+ ExFreePool(busData);
+ deviceData->Flags |= DEVICE_FLAGS_VALID;
+ }
+
+ //
+ // If this is the docking station slot, remember it.
+ //
+
+ if (dockConnector) {
+ busExtension->DockingStationDevice = deviceData;
+ deviceData->Flags |= DEVICE_FLAGS_DOCKING_STATION;
+ }
+ }
+ }
+
+ //
+ // Go through the slot data link list to delete all the removed slots.
+ //
+
+ noSlots = busExtension->NoValidSlots;
+ MbpDeleteSlots(busExtension);
+ if (noSlots != busExtension->NoValidSlots) {
+ notifyBusCheck = TRUE;
+ }
+ ExReleaseFastMutex (&MbpMutex);
+
+ //
+ // If this is top level pnp bios bus we will determine docking station information
+ // and all Hal to set dock information.
+ //
+
+ if (BusHandler->BusNumber == MbpBusNumber[0] &&
+ NT_SUCCESS(MbpGetDockInformation(&dockInfo, &length)) ) {
+ HalSetSystemInformation(HalSystemDockInformation, length, dockInfo);
+ ExFreePool(dockInfo);
+ }
+
+ //
+ // Undo reference to bus handler from top of function
+ //
+
+ HalDereferenceBusHandler (BusHandler);
+
+ //
+ // Do we need to notify the system buscheck callback?
+ //
+
+ if (notifyBusCheck) {
+ HAL_BUS_INFORMATION busInfo;
+
+ busInfo.BusType = BusHandler->InterfaceType;
+ busInfo.ConfigurationType = BusHandler->ConfigurationType;
+ busInfo.BusNumber = BusHandler->BusNumber;
+ busInfo.Reserved = 0;
+ ExNotifyCallback (
+ MbpHalCallbacks.BusCheck,
+ &busInfo,
+ (PVOID)BusHandler->BusNumber
+ );
+ }
+}
+
+PDEVICE_HANDLER_OBJECT
+MbpReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function returns a reference to the devce handler specified by SlotNumber
+ and BusHandler.
+
+Arguments:
+
+ BusHandler -
+
+ RootHanler -
+
+ SlotNumber -
+
+Return Value:
+
+ a reference to DEVICE_HANDLER_OBJECT.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PMB_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+
+ PAGED_CODE ();
+
+ ExAcquireFastMutex (&MbpMutex);
+
+ busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
+ deviceData = MbpFindDeviceData (busExtension, SlotNumber);
+ deviceHandler = NULL;
+ if (deviceData) {
+ deviceHandler = DeviceData2DeviceHandler (deviceData);
+ status = ObReferenceObjectByPointer(
+ deviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ if (!NT_SUCCESS(status)) {
+ deviceHandler = NULL;
+ }
+ }
+
+ ExReleaseFastMutex (&MbpMutex);
+ return deviceHandler;
+}
+
+PDEVICE_DATA
+MbpFindDeviceData (
+ IN PMB_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list to find the desired SlotNumber's
+ device data. The caller must hold the MbpMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to current bus'es extension.
+
+ SlotNumber - specified the desired device data. -1 means docking station device data.
+
+Return Value:
+
+ A pointer to the DEVICE_DATA if found. Otherwise a value of NULL is returned.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ //
+ // Go through the slot data link list to find a match.
+ //
+
+ if (SlotNumber == DOCK_VIRTUAL_SLOT_NUMBER) {
+ return BusExtension->DockingStationDevice;
+ } else {
+ for (link = BusExtension->ValidSlots.Next; link; link = link->Next) {
+ deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
+ if (DeviceDataSlot(deviceData) == SlotNumber) {
+ break;
+ }
+ }
+ }
+
+ if (!link) {
+ return NULL;
+ } else {
+ return deviceData;
+ }
+}
+
+VOID
+MbpInvalidateSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list and marks all the devices as invalid.
+ The caller must acquire MbpMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PSINGLE_LIST_ENTRY link;
+
+ //
+ // Go through the slot data link list to mark ALL the slots as
+ // in transition state.
+ //
+
+ for (link = BusExtension->ValidSlots.Next; link; link = link->Next) {
+ deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
+ deviceData->Flags &= ~DEVICE_FLAGS_VALID;
+ }
+
+ //
+ // Invalidate the docking station slot pointer
+ //
+
+ BusExtension->DockingStationDevice = NULL;
+ BusExtension->DockingStationId = UNKNOWN_DOCKING_IDENTIFIER;
+ BusExtension->DockingStationSerialNumber = 0;
+}
+
+VOID
+MbpDeleteSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list and deletes all the invalid
+ slots/devices.
+ Note the MbpMutex must be acquired before calling this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PSINGLE_LIST_ENTRY *link;
+
+ //
+ // Go through the slot data link list to free all the slot
+ // marked as invalid.
+ //
+
+ link = &BusExtension->ValidSlots.Next;
+ while (*link) {
+ deviceData = CONTAINING_RECORD (*link, DEVICE_DATA, Next);
+ if (!(deviceData->Flags & DEVICE_FLAGS_VALID)) {
+ DebugPrint((DEBUG_MESSAGE, "Remove slot %x\n", DeviceDataSlot(deviceData)));
+
+ //
+ // In theory I should deallocate the BusData only when the ref count of the
+ // deviceData down to zero and deallocated. Here I am safe to do so because
+ // the DeviceDispatchContol routine checks the DeviceData flag is valid before
+ // reference the BusData.
+ //
+
+ if (deviceData->BusData) {
+ ExFreePool(deviceData->BusData);
+ }
+ *link = (*link)->Next;
+ deviceHandler = DeviceData2DeviceHandler(deviceData);
+ ObDereferenceObject (deviceHandler);
+ HalDereferenceBusHandler (BusExtension->BusHandler);
+ BusExtension->NoValidSlots--;
+ } else {
+ link = &((*link)->Next);
+ }
+ }
+}
+
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/busdata.c b/private/ntos/nthals/extender/pnpbios/i386/busdata.c
new file mode 100644
index 000000000..58dded523
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/busdata.c
@@ -0,0 +1,902 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains code to query/set pnp bios slot data.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-25-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+PUCHAR
+MbpFindNextPnpEndTag (
+ IN PUCHAR BusData,
+ IN LONG Limit
+ );
+
+#pragma alloc_text(PAGE,MbpGetBusData)
+#pragma alloc_text(PAGE,MbpGetCompatibleDeviceId)
+#pragma alloc_text(PAGE,MbpGetSlotResources)
+#pragma alloc_text(PAGE,MbpGetSlotResourceRequirements)
+#pragma alloc_text(PAGE,MbpSetSlotResources)
+#pragma alloc_text(PAGE,MbpFindNextPnpEndTag)
+
+NTSTATUS
+MbpGetBusData (
+ ULONG BusNumber,
+ PULONG SlotNumber,
+ PVOID *BusData,
+ PULONG Length,
+ PBOOLEAN DockingSlot
+ )
+/*++
+
+Routine Description:
+
+ This function returns the pnp bios bus data to the caller.
+ Caller is responsible to release the data buffer. No mater what the returned
+ status is, this routine always returns a valid next slot number.
+
+Arguments:
+
+ BusNumber - specifies the desired bus.
+
+ SlotNumber - specifies a variable to indicate the slot whoes data is desired and
+ to receive the next slot number (-1 if no more slot.)
+
+ BusData - supplies a variable to receive the data buffer pointer.
+
+ Length - supplies a variable to receive the length of the data buffer
+
+ DockingSlot - supplies a variable to receive if the slot is a docking station slot.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ PPNP_BIOS_DEVICE_NODE busData;
+ PUCHAR p, source;
+ ULONG size, bufferSize, nextSlot = 0;
+ USHORT junk;
+ PB_PARAMETERS biosParameters;
+
+ PAGED_CODE();
+
+ //
+ // If registry data is availble, we will get it from registry data.
+ // Note, the registry data is available at init time only.
+ //
+
+ source = NULL;
+ *DockingSlot = FALSE;
+ if (PbBiosRegistryData) {
+
+ //
+ // First skip Pnp Bios installation check data
+ //
+
+ p = (PUCHAR)(PbBiosRegistryData + 1);
+ size = ((PKEY_VALUE_FULL_INFORMATION)PbBiosKeyInformation)->DataLength;
+ size -= sizeof(PNP_BIOS_INSTALLATION_CHECK) + sizeof(CM_PARTIAL_RESOURCE_LIST);
+ while (size >= sizeof(PNP_BIOS_DEVICE_NODE)) {
+ if (*SlotNumber == ((PPNP_BIOS_DEVICE_NODE)p)->Node) {
+
+ //
+ // Find the desired slot data, determine next slot and
+ // do some more checks.
+ //
+
+ bufferSize = ((PPNP_BIOS_DEVICE_NODE)p)->Size;
+ size -= bufferSize;
+ if (size >= sizeof(PNP_BIOS_DEVICE_NODE)) {
+ nextSlot = ((PPNP_BIOS_DEVICE_NODE)(p + bufferSize))->Node;
+ } else {
+ nextSlot = (ULONG) -1;
+ }
+
+ if (((PPNP_BIOS_DEVICE_NODE)p)->DeviceType[0] == BASE_TYPE_DOCKING_STATION) {
+ if (BusNumber == MbpBusNumber[0]) {
+
+ //
+ // If this is a docking station slot and the target BusNumber is the first bus,
+ // return the data and indicate this is a docking station slot.
+ //
+
+ *DockingSlot = TRUE;
+ source = p;
+ }
+ break;
+ }
+
+ //
+ // If this is a device in the deocking station, it can only belong to BusNumber 1
+ // If this is a device in the system board, it can only belong to BusNumber 0
+ //
+
+ if (((PPNP_BIOS_DEVICE_NODE)p)->DeviceAttributes & DEVICE_DOCKING) {
+ if (BusNumber == MbpBusNumber[1]) {
+ source = p;
+ }
+ } else if (BusNumber == MbpBusNumber[0]) {
+ source = p;
+ }
+ break;
+ }
+ size -= ((PPNP_BIOS_DEVICE_NODE)p)->Size;
+ p = p + ((PPNP_BIOS_DEVICE_NODE)p)->Size;
+ }
+
+ if (!source) {
+ if (*SlotNumber == 0) {
+ p = (PUCHAR)(PbBiosRegistryData + 1);
+ *SlotNumber = ((PPNP_BIOS_DEVICE_NODE)p)->Node;
+ } else {
+ *SlotNumber = nextSlot;
+ }
+ return STATUS_NO_SUCH_DEVICE;
+ }
+ } else {
+
+ //
+ // Registry data is not available. Call pnp bios or hardware to
+ // get the max buffer size if necessary.
+ //
+
+ if (MbpMaxDeviceData == 0) {
+ biosParameters.Function = PNP_BIOS_GET_NUMBER_DEVICE_NODES;
+ biosParameters.u.GetNumberDeviceNodes.NumberNodes = &junk;
+ biosParameters.u.GetNumberDeviceNodes.NodeSize = (PUSHORT)&MbpMaxDeviceData;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_BREAK, "GetBusData: calling BIOS GET_NUMBER_NODES failed.\n"));
+ *SlotNumber = 0;
+ return STATUS_NO_SUCH_DEVICE;
+ } else {
+ bufferSize = MbpMaxDeviceData;
+ }
+ }
+ }
+
+ //
+ // Allocate space to return the slot data
+ //
+
+ busData = (PPNP_BIOS_DEVICE_NODE) ExAllocatePoolWithTag (
+ PagedPool, bufferSize, 'bPnP');
+
+ if (busData == NULL) {
+
+ //
+ // Leave Slot unchanged, so it wil be the next slot number to try. This gives
+ // us another chance to retry the operation.
+ //
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // If the data is available already copy it to data buffer and return.
+ //
+
+ if (source) {
+ RtlMoveMemory(busData, source, bufferSize);
+ *SlotNumber = nextSlot;
+ *BusData = busData;
+ *Length = busData->Size;
+ } else {
+
+ //
+ // Else we need to resort to Pnp Bios runtime API or hardware ...
+ //
+
+ nextSlot = *SlotNumber;
+ biosParameters.Function = PNP_BIOS_GET_DEVICE_NODE;
+ biosParameters.u.GetDeviceNode.NodeBuffer = busData;
+ biosParameters.u.GetDeviceNode.Node = (PUSHORT)&nextSlot;
+ biosParameters.u.GetDeviceNode.Control = GET_CURRENT_CONFIGURATION;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ *SlotNumber = 0;
+ ExFreePool(busData);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ if (nextSlot == 0xFF) {
+ nextSlot = (ULONG) -1;
+ }
+
+ //
+ // Make sure the slot matches the bus number.
+ //
+
+ if (*SlotNumber != (ULONG)busData->Node) {
+
+ //
+ // This happens when *SlotNumber == 0. In this case, bios
+ // gives us the first valid slot data.
+ //
+
+ *SlotNumber = (ULONG)busData->Node;
+ return STATUS_NO_SUCH_DEVICE;
+ } else {
+ *SlotNumber = nextSlot;
+ }
+ if ((busData->DeviceType[0] == BASE_TYPE_DOCKING_STATION && BusNumber != MbpBusNumber[0]) ||
+ (busData->DeviceAttributes & DEVICE_DOCKING && BusNumber == MbpBusNumber[0]) ||
+ (!(busData->DeviceAttributes & DEVICE_DOCKING) && BusNumber == MbpBusNumber[1]) ) {
+ ExFreePool(busData);
+ return STATUS_NO_SUCH_DEVICE;
+ } else {
+ *BusData = busData;
+ *Length = busData->Size;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbpGetCompatibleDeviceId (
+ PVOID BusData,
+ ULONG IdIndex,
+ PWCHAR Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp bios id for the specified Busdata
+ and Id index. If Id index = 0, the Hardware ID will be return; if id
+ index = n, the Nth compatible id will be returned.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ IdIndex - supplies the index of the compatible id desired.
+
+ Buffer - supplies a pointer to a buffer to the compatible Id. Caller must
+ make sure the buffer is big enough.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p, end;
+ UCHAR tag;
+ ULONG count = 0;
+ LONG size;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ ULONG id;
+
+ PAGED_CODE();
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
+ if (IdIndex == 0) {
+
+ //
+ // Caller is asking for hardware id
+ //
+
+ id = slotData->ProductId;
+ } else {
+
+ //
+ // caller is asking for compatible id
+ //
+
+ IdIndex--;
+ p = (PUCHAR)(slotData + 1);
+ size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
+ end = p + size;
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
+ if (!p) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ p += 2;
+ p = MbpFindNextPnpEndTag(p, (LONG)(end - p)); // skip possible resources
+ if (!p) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ p += 2;
+ status = STATUS_NO_MORE_ENTRIES;
+ while ((tag = *p) != TAG_COMPLETE_END) {
+ ASSERT (tag == TAG_COMPLETE_COMPATIBLE_ID);
+ if (count == IdIndex) {
+ id = *(PULONG)(p + 1);
+ status = STATUS_SUCCESS;
+ break;
+ } else {
+ count++;
+ }
+
+ //
+ // Advance to next compatible id.
+ //
+
+ p += (TAG_COMPLETE_COMPATIBLE_ID & SMALL_TAG_SIZE_MASK) + 1;
+ }
+ }
+
+ if (NT_SUCCESS(status)) {
+ PbDecompressEisaId(id, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ swprintf(Buffer, L"BIOS\\*%s", unicodeString.Buffer);
+ RtlFreeUnicodeString(&unicodeString);
+ }
+ return status;
+}
+
+NTSTATUS
+MbpGetSlotResources (
+ IN ULONG BusNumber,
+ IN PVOID BusData,
+ IN OUT PCM_RESOURCE_LIST *CmResources,
+ OUT PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp bios slot/device resource in CM
+ format. Caller is responsible to free the resource buffer.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ CmResources - supplies a variable to receive the returned resource list.
+
+ Length - supplies a variable to receive the length of the data buffer
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
+ p = (PUCHAR)(slotData + 1);
+ status = PbBiosResourcesToNtResources (
+ BusNumber,
+ slotData->Node,
+ &p,
+ PB_CM_FORMAT,
+ (PUCHAR *) CmResources,
+ Length
+ );
+ return status;
+}
+
+NTSTATUS
+MbpGetSlotResourceRequirements (
+ ULONG BusNumber,
+ PVOID BusData,
+ PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp bios slot/device resource in IO
+ format. Caller is responsible to free the resource buffer.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ IoResources - supplies a variable to receive the returned resource requirements list.
+
+ Length - supplies a variable to receive the length of the data buffer
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p;
+ LONG size;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ *IoResources = NULL;
+ *Length = 0;
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
+ p = (PUCHAR)(slotData + 1);
+ size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
+
+ //
+ // Skip allocated resource descriptors
+ //
+
+ p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
+ if (p) {
+ p += 2;
+ status = PbBiosResourcesToNtResources (
+ BusNumber,
+ slotData->Node,
+ &p,
+ PB_IO_FORMAT,
+ (PUCHAR *)IoResources,
+ Length
+ );
+ }
+ return status;
+}
+
+NTSTATUS
+MbpSetSlotResources (
+ PVOID *BusData,
+ PCM_RESOURCE_LIST CmResources,
+ ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function sets the caller specified resource to pnp bios slot/device
+ data.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ CmResources - supplies a variable to receive the returned resource list.
+
+ Length - supplies the length of the resource data
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p, pEnd, src, requirements;
+ PUCHAR biosResources;
+ ULONG biosResourceSize, totalSize;
+ LONG size;
+ PB_PARAMETERS biosParameters;
+
+ PAGED_CODE();
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)(*BusData);
+ p = (PUCHAR)(slotData + 1);
+ size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
+ pEnd = p + size;
+
+ //
+ // Skip allocated resource descriptors to find requirements list
+ //
+
+ p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
+ if (!p) {
+ DebugPrint((DEBUG_BREAK, "SetResource:Could not find allocated resource END tag\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ p += 2;
+ requirements = p;
+ size = (ULONG)pEnd - (ULONG)p;
+
+ status = PbCmResourcesToBiosResources (
+ CmResources,
+ requirements,
+ &biosResources,
+ &biosResourceSize
+ );
+ if (NT_SUCCESS(status)) {
+ p = ExAllocatePoolWithTag(
+ PagedPool,
+ size + sizeof(PNP_BIOS_DEVICE_NODE) + biosResourceSize,
+ 'bPnP');
+ if (!p) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(p, slotData, sizeof(PNP_BIOS_DEVICE_NODE));
+ slotData = (PPNP_BIOS_DEVICE_NODE)p;
+ p += sizeof(PNP_BIOS_DEVICE_NODE);
+ RtlMoveMemory(p, biosResources, biosResourceSize);
+ p += biosResourceSize;
+ RtlMoveMemory(p, requirements, size);
+ totalSize = size + sizeof(PNP_BIOS_DEVICE_NODE) + biosResourceSize;
+ slotData->Size = (USHORT)totalSize;
+
+ //
+ // call Pnp Bios to set the resources
+ //
+
+ biosParameters.Function = PNP_BIOS_SET_DEVICE_NODE;
+ biosParameters.u.SetDeviceNode.Node = slotData->Node;
+ biosParameters.u.SetDeviceNode.NodeBuffer = slotData;
+ biosParameters.u.SetDeviceNode.Control = SET_CONFIGURATION_NOW;
+ status = PbHardwareService (&biosParameters);
+ if (NT_SUCCESS(status)) {
+
+ //
+ // Update slotdat pointer
+ //
+
+ ExFreePool(*BusData);
+ *BusData = slotData;
+ } else {
+ ExFreePool(slotData);
+ }
+ }
+ }
+ return status;
+}
+
+NTSTATUS
+MbpGetDockInformation (
+ OUT PHAL_SYSTEM_DOCK_INFORMATION *DockInfo,
+ PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function returns the docking station Id and serial number.
+ Caller must free the Buffer.
+
+Arguments:
+
+ DockInfo - supplies a pointer to a variable to receive the dock information.
+
+ Length - supplies a pointer to a variable to receive the length of the information.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PB_DOCKING_STATION_INFORMATION biosDockInfo;
+ PB_PARAMETERS biosParameters;
+ NTSTATUS status;
+ PUNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ PHAL_SYSTEM_DOCK_INFORMATION dock;
+ ULONG dockIdLength = 0, serialLength = 0;
+ USHORT dockState;
+
+ PAGED_CODE();
+
+ //
+ // Invoke pnp bios to get docking station information
+ //
+
+ biosParameters.Function = PNP_BIOS_GET_DOCK_INFORMATION;
+ biosParameters.u.GetDockInfo.DockingStationInfo = &biosDockInfo;
+ biosParameters.u.GetDockInfo.DockState = &dockState;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Allocate memory to return dock information
+ //
+
+ dock = (PHAL_SYSTEM_DOCK_INFORMATION)ExAllocatePool (
+ PagedPool,
+ sizeof(HAL_SYSTEM_DOCK_INFORMATION));
+ if (dock == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (dockState == SYSTEM_NOT_DOCKED) {
+
+ //
+ // System is not docked, simply return the dock state.
+ //
+
+ dock->DockState = SystemUndocked;
+ } else {
+
+ //
+ // else system is docked, remember its dock id and serial number.
+ //
+
+ dock->DockState = SystemDocked;
+#if 1
+ MbpBusExtension[0]->DockingStationId = biosDockInfo.LocationId;
+ MbpBusExtension[0]->DockingStationSerialNumber = biosDockInfo.SerialNumber;
+ ExAcquireFastMutex (&MbpMutex);
+ if (biosDockInfo.Capabilities && DOCKING_CAPABILITIES_MASK != DOCKING_CAPABILITIES_COLD_DOCKING) {
+ MbpBusExtension[0]->DockingStationDevice->Flags |= DEVICE_FLAGS_EJECT_SUPPORTED;
+ }
+ ExReleaseFastMutex (&MbpMutex);
+#else
+ if (biosDockInfo.LocationId != UNKNOWN_DOCKING_IDENTIFIER) {
+
+ //
+ // If docking station location Id is present...
+ //
+
+ unicodeString = &MbpBusExtension[0]->DockingStationId;
+ PbDecompressEisaId(biosDockInfo.LocationId, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ dockIdLength = sizeof(WCHAR) * (ansiString.Length + 1);
+ unicodeString->Buffer = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ dockIdLength);
+ if (unicodeString->Buffer == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ unicodeString->MaximumLength = (USHORT)dockIdLength;
+ RtlAnsiStringToUnicodeString(unicodeString, &ansiString, FALSE);
+ }
+// if (biosDockInfo.SerialNumber != 0) {
+
+ //
+ // If docking station serial number is present ...
+ //
+
+ serialLength = sizeof(ULONG) * 2 * sizeof(WCHAR) + sizeof(WCHAR);
+ unicodeString = &MbpBusExtension[0]->DockingStationSerialNo;
+ unicodeString->Buffer = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ serialLength);
+ if (unicodeString->Buffer == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ unicodeString->MaximumLength = (USHORT)serialLength;
+ unicodeString->Length = sizeof(ULONG) * 2 * sizeof(WCHAR);
+ swprintf(unicodeString->Buffer, L"%8x", biosDockInfo.SerialNumber);
+// }
+#endif
+ }
+ dock->DeviceBusType = Internal;
+ dock->DeviceBusNumber = MbpBusNumber[0];
+ dock->SlotNumber = DOCK_VIRTUAL_SLOT_NUMBER;
+ *Length = sizeof(HAL_SYSTEM_DOCK_INFORMATION);
+ *DockInfo = dock;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbpReplyEjectEvent (
+ ULONG SlotNumber,
+ BOOLEAN Eject
+ )
+/*++
+
+Routine Description:
+
+ This function sends message to pnp bios for event processing.
+
+Arguments:
+
+ SlotNumber - specifies the slot whoes data is desired.
+
+ Eject - indicates if EJECT operation should be performed.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ PB_PARAMETERS biosParameters;
+ USHORT message;
+
+ PAGED_CODE();
+
+ //
+ // Else we need to resort to Pnp Bios runtime API or hardware ...
+ //
+
+ biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
+ if (Eject) {
+ biosParameters.u.SendMessage.Message = OK_TO_CHANGE_CONFIG;
+ } else {
+ biosParameters.u.SendMessage.Message = ABORT_CONFIG_CHANGE;
+ }
+
+ status = PbHardwareService(&biosParameters);
+ return status;
+}
+
+PUCHAR
+MbpFindNextPnpEndTag (
+ IN PUCHAR BusData,
+ IN LONG Limit
+ )
+/*++
+
+Routine Description:
+
+ This function searches the Pnp BIOS device data for the frist END_TAG encountered.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios resource descriptor.
+
+ Limit - maximum length of the search.
+
+Return Value:
+
+ The address of the END_TAG location. Null if not found.
+
+--*/
+{
+ UCHAR tag;
+ USHORT size;
+
+ tag = *BusData;
+ while (tag != TAG_COMPLETE_END && Limit > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(BusData + 1);
+ size += 3; // length of large tag
+ }
+
+ BusData += size;
+ Limit -= size;
+ tag = *BusData;
+ }
+ if (tag == TAG_COMPLETE_END) {
+ return BusData;
+ } else {
+ return NULL;
+ }
+}
+
+BOOLEAN
+MbpConfigAboutToChange (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is invoked by low level component to signal a dock\undock event
+ is about to happen.
+
+ This function is called at DPC level.
+
+Arguments:
+
+ SlotNumber - supplies the docking connector slot number.
+
+Return Value:
+
+ TRUE - allow the change to happen; FALSE - ignore it for now.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ HAL_BUS_INFORMATION busInfo;
+ PBUS_HANDLER busHandler;
+
+ //
+ // Get docking station slot data
+ //
+
+ deviceData = MbpFindDeviceData (MbpBusExtension[0], DOCK_VIRTUAL_SLOT_NUMBER);
+ if (deviceData) {
+
+ //
+ // if docking station slot is present
+ //
+
+ ASSERT (deviceData->Flags & DEVICE_FLAGS_DOCKING_STATION);
+
+ //
+ // If it is presently docked, the change is about-to-undock.
+ // We need to notify Eject callback.
+ //
+
+ DebugPrint((DEBUG_MESSAGE, "pnpbios: About to UNDOCK...\n"));
+ busHandler = MbpBusExtension[0]->BusHandler;
+ busInfo.BusType = busHandler->InterfaceType;
+ busInfo.ConfigurationType = busHandler->ConfigurationType;
+ busInfo.BusNumber = busHandler->BusNumber;
+ busInfo.Reserved = 0;
+ ExNotifyCallback (
+ MbpEjectCallbackObject,
+ &busInfo,
+ (PVOID)busHandler->BusNumber
+ );
+ } else {
+
+ DebugPrint((DEBUG_MESSAGE, "pnpbios: About to DOCK...\n"));
+
+ //
+ // Otherwise, it is about-to-dock. Simply let it happen.
+ //
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+VOID
+MbpConfigChanged (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is invoked by low level component to signal a dock-changed,
+ a system-device-changed, or a config-change_failed event. We simply notify
+ bus check callbacks.
+ This function is called at DPC level.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER busHandler;
+ ULONG i;
+
+ //
+ // Notify buscheck for ALL the supported buses and queue check bus requests.
+ //
+
+ for (i = 0; i <= 1; i++) {
+ busHandler = MbpBusExtension[i]->BusHandler;
+ if (busHandler) {
+ MbpQueueCheckBus(busHandler);
+ }
+ }
+}
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/busp.h b/private/ntos/nthals/extender/pnpbios/i386/busp.h
new file mode 100644
index 000000000..ca894ea05
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/busp.h
@@ -0,0 +1,499 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busp.h
+
+Abstract:
+
+ Hardware independent header file for pnp bios bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-21-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pbapi.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+//
+// Structures
+//
+
+//
+// When queued, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextWorkQueue BusExtenderReserved[0]
+#define ContextControlHandler BusExtenderReserved[2]
+
+//
+// When in progress, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextArgument1 BusExtenderReserved[0]
+#define ContextArgument2 BusExtenderReserved[1]
+#define ContextBusyFlag BusExtenderReserved[2]
+
+//
+// Define virtual slot number for docking station. (We need to return docking
+// station slot number before knowing the real slot number. )
+//
+
+#define DOCK_VIRTUAL_SLOT_NUMBER 0xFFFF
+
+//
+// DEVICE_DATA Flags masks
+//
+
+#define DEVICE_FLAGS_DOCKING_STATION 0x10000000
+#define DEVICE_FLAGS_VALID 0x00000001
+#define DEVICE_FLAGS_WARM_DOCKING 0x00000002
+#define DEVICE_FLAGS_COLD_DOCKING 0x00000004
+#define DEVICE_FLAGS_EJECT_SUPPORTED 0x00000008
+
+typedef struct _DEVICE_DATA_ {
+ SINGLE_LIST_ENTRY Next;
+ ULONG Flags;
+
+ //
+ // DeviceControl in progress flags
+ //
+
+ BOOLEAN SyncBusy;
+
+ //
+ // Pointer to bus specific data
+ //
+
+ PVOID BusData;
+
+ //
+ // Length of the bus data
+ //
+
+ ULONG BusDataLength;
+
+} DEVICE_DATA, *PDEVICE_DATA;
+
+//
+// Extension data for Bus extender
+//
+
+typedef struct _MB_BUS_EXTENSION {
+
+ //
+ // BusHandler points back to the BUS_HANDLER structure for this extension
+ //
+
+ PBUS_HANDLER BusHandler;
+
+ //
+ // Bus Check request list
+ //
+
+ LIST_ENTRY CheckBus;
+
+ //
+ // Device control request list
+ //
+
+ LIST_ENTRY DeviceControl;
+
+ //
+ // Slot Data link list
+ //
+
+ SINGLE_LIST_ENTRY ValidSlots;
+ ULONG NoValidSlots;
+
+ //
+ // Pointer to docking station device data.
+ // This is mainly for convenience.
+ //
+
+ PDEVICE_DATA DockingStationDevice;
+ ULONG DockingStationId;
+ ULONG DockingStationSerialNumber;
+} MB_BUS_EXTENSION, *PMB_BUS_EXTENSION;
+
+typedef struct {
+ BOOLEAN Control;
+} *PBCTL_SET_CONTROL;
+
+//
+// Pnp Bios bus extender device object extension
+//
+
+typedef struct _MB_DEVICE_EXTENSION {
+ PBUS_HANDLER BusHandler;
+} MB_DEVICE_EXTENSION, *PMB_DEVICE_EXTENSION;
+
+//
+// Only support 2 buses: main bus and docking station bus.
+//
+
+#define MAXIMUM_BUS_NUMBER 2
+
+//
+// SlotControl related internal definitions
+//
+
+typedef BOOLEAN (FASTCALL * BEGIN_FUNCTION)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+typedef VOID (* CONTROL_FUNCTION)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+
+typedef struct _DEVICE_CONTROL_HANDLER {
+ ULONG ControlCode;
+ ULONG MinBuffer;
+ BEGIN_FUNCTION BeginDeviceControl;
+ CONTROL_FUNCTION ControlHandler;
+} DEVICE_CONTROL_HANDLER, *PDEVICE_CONTROL_HANDLER;
+
+#define NUMBER_DEVICE_CONTROL_FUNCTIONS 11
+
+//
+// misc. definitions
+//
+
+#define BUS_0_SIGNATURE 0xabababab
+#define MIN_DETECT_SIGNATURE_SIZE (FIELD_OFFSET(CM_RESOURCE_LIST, List) + \
+ FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList))
+
+//
+// Globals
+//
+
+extern FAST_MUTEX MbpMutex;
+extern KSPIN_LOCK MbpSpinlock;
+extern LIST_ENTRY MbpControlWorkerList;
+extern LIST_ENTRY MbpCheckBusList;
+extern ULONG MbpWorkerQueued;
+extern WORK_QUEUE_ITEM MbpWorkItem;
+extern ULONG MbpNextHandle;
+extern DEVICE_CONTROL_HANDLER MbpDeviceControl[];
+extern PDRIVER_OBJECT MbpDriverObject;
+extern HAL_CALLBACKS MbpHalCallbacks;
+extern PCALLBACK_OBJECT MbpEjectCallbackObject;
+extern BOOLEAN MbpNoBusyFlag;
+extern ULONG MbpMaxDeviceData;
+extern PMB_BUS_EXTENSION MbpBusExtension[];
+extern WCHAR rgzBIOSDeviceName[];
+extern ULONG MbpNextBusId;
+extern ULONG MbpBusNumber[];
+
+extern POBJECT_TYPE *IoDeviceHandlerObjectType;
+extern PULONG IoDeviceHandlerObjectSize;
+extern ULONG MbpDeviceHandlerObjectSize;
+
+#define DeviceHandler2DeviceData(a) ((PDEVICE_DATA) (((PUCHAR) a) + MbpDeviceHandlerObjectSize))
+#define DeviceData2DeviceHandler(a) ((PDEVICE_HANDLER_OBJECT) (((PUCHAR) a) - MbpDeviceHandlerObjectSize))
+#define DeviceDataSlot(a) (DeviceData2DeviceHandler(a)->SlotNumber)
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NTSTATUS
+MbAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN OUT PULONG InstanceNumber
+ );
+
+NTSTATUS
+MbCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ );
+
+ULONG
+MbGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+MbSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+MbGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+MbSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+MbQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+MbDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbpCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+PDEVICE_DATA
+MbpFindDeviceData (
+ IN PMB_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ );
+
+VOID
+MbpStartWorker (
+ VOID
+ );
+
+VOID
+MbpControlWorker (
+ IN PVOID WorkerContext
+ );
+
+VOID
+MbpQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+VOID
+MbpDispatchControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbpCompleteDeviceControl (
+ IN NTSTATUS Status,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context,
+ IN PDEVICE_DATA DeviceData
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlNone (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlSync (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlEject (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlLock (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceId (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceResources (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceResourceRequirements (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlSetDeviceResources (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceUniqueId (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceCapabilities (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryEject (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlEject (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlLock (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+NTSTATUS
+MbpGetBusData (
+ IN ULONG BusNumber,
+ IN PULONG SlotNumber,
+ IN OUT PVOID *BusData,
+ OUT PULONG Length,
+ OUT PBOOLEAN DockConnector
+ );
+
+NTSTATUS
+MbpGetCompatibleDeviceId (
+ IN PVOID BusData,
+ IN ULONG IdIndex,
+ IN PWCHAR CompatibleId
+ );
+
+NTSTATUS
+MbpGetSlotResources (
+ IN ULONG BusNumber,
+ IN PVOID BusData,
+ OUT PCM_RESOURCE_LIST *CmResources,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+MbpGetSlotResourceRequirements (
+ IN ULONG BusNumber,
+ IN PVOID BusData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+MbpSetSlotResources (
+ OUT PVOID *BusData,
+ IN PCM_RESOURCE_LIST CmResources,
+ IN ULONG Length
+ );
+
+NTSTATUS
+MbpReplyEjectEvent (
+ IN ULONG SlotNumber,
+ IN BOOLEAN Eject
+ );
+
+NTSTATUS
+MbpGetDockInformation (
+ OUT PHAL_SYSTEM_DOCK_INFORMATION *DockInfo,
+ PULONG Length
+ );
+
+PDEVICE_HANDLER_OBJECT
+MbpReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ );
+
+#if 0
+
+//
+// BUGBUG - should be removed...
+//
+
+NTSTATUS
+IoRegisterDetectedDevice(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN PCM_RESOURCE_LIST DetectSignature,
+ OUT PULONG InstanceNumber
+ );
+
+typedef enum _DEVICE_STATUS {
+ DeviceStatusOK,
+ DeviceStatusMalfunction,
+ DeviceStatusDisabled,
+ DeviceStatusRemoved,
+ MaximumDeviceStatus
+} DEVICE_STATUS, *PDEVICE_STATUS;
+
+NTSTATUS
+IoRegisterDevicePath(
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN PUNICODE_STRING NtDeviceObjectPath,
+ IN BOOLEAN PhysicalDevicePath,
+ IN PCM_RESOURCE_LIST Configuration,
+ IN DEVICE_STATUS DeviceStatus
+ );
+
+NTSTATUS
+IoGetDeviceHandler(
+ IN PUNICODE_STRING ServicekeyName,
+ IN ULONG InstanceOrdinal,
+ OUT PDEVICE_HANDLER_OBJECT DeviceHandler
+ );
+
+VOID
+IoReleaseDevicehandler (
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler
+ );
+#endif
diff --git a/private/ntos/nthals/extender/pnpbios/i386/control.c b/private/ntos/nthals/extender/pnpbios/i386/control.c
new file mode 100644
index 000000000..ca9942df7
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/control.c
@@ -0,0 +1,725 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ control.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-23-1995
+ Most of the code is adapted from PCI bus extender.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+VOID
+MbpiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData,
+ PBOOLEAN Sync
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,MbpControlWorker)
+#pragma alloc_text(PAGE,MbpCompleteDeviceControl)
+#endif
+
+VOID
+MbpStartWorker (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used to start a worker thread.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG workerQueued;
+
+ if (!MbpWorkerQueued) {
+ workerQueued = ExInterlockedExchangeUlong (
+ &MbpWorkerQueued,
+ 1,
+ MbpSpinLock
+ );
+
+ if (!workerQueued) {
+ ExQueueWorkItem (&MbpWorkItem, DelayedWorkQueue);
+ }
+ }
+}
+
+VOID
+MbpQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+/*++
+
+Routine Description:
+
+ This function enqueues Bus check request to buscheck list.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the bus handler of the bus to be checked.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ExInterlockedInsertTailList (
+ &MbpCheckBusList,
+ &((PMB_BUS_EXTENSION)BusHandler->BusData)->CheckBus,
+ &MbpSpinlock
+ );
+
+ MbpStartWorker();
+}
+
+VOID
+MbpControlWorker (
+ IN PVOID WorkerContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by a system worker thread.
+
+ The worker thread dequeues any SlotControls which need to be
+ processed and dispatches them.
+
+ It then checks for any check bus request.
+
+Arguments:
+
+ WorkerContext - supplies a pointer to a context for the worker. Here
+ it is always NULL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PLIST_ENTRY entry;
+ PMB_BUS_EXTENSION busExtension;
+ PHAL_DEVICE_CONTROL_CONTEXT context;
+
+ PAGED_CODE ();
+
+ //
+ // process check bus
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &MbpCheckBusList,
+ &MbpSpinlock
+ );
+
+ if (!entry) {
+ break;
+ }
+ busExtension = CONTAINING_RECORD (
+ entry,
+ MB_BUS_EXTENSION,
+ CheckBus
+ );
+
+ MbpCheckBus (busExtension->BusHandler);
+ }
+
+ //
+ // Reset worker item for next time
+ //
+
+ ExInitializeWorkItem (&MbpWorkItem, MbpControlWorker, NULL);
+ ExInterlockedExchangeUlong (&MbpWorkerQueued, 0, MbpSpinLock);
+
+ //
+ // Dispatch pending device controls
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &MbpControlWorkerList,
+ &MbpSpinlock
+ );
+
+ if (!entry) {
+
+ //
+ // All done, exit the loop.
+ //
+
+ break;
+ }
+
+ context = CONTAINING_RECORD (
+ entry,
+ HAL_DEVICE_CONTROL_CONTEXT,
+ ContextWorkQueue,
+ );
+
+ MbpDispatchControl (context);
+ }
+}
+
+VOID
+MbpDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function dispatches a DeviceControl to the appropiate handler.
+ If the slot is busy, the DeviceControl may be queued for dispatching at
+ a later time
+
+Arguments:
+
+ Context - The DeviceControl context to dispatch
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_CONTROL_HANDLER deviceControlHandler;
+ PMB_BUS_EXTENSION busExtension;
+ PDEVICE_DATA deviceData;
+ KIRQL oldIrql;
+ BOOLEAN enqueueIt;
+ PLIST_ENTRY link;
+
+ deviceControlHandler = (PDEVICE_CONTROL_HANDLER) Context->ContextControlHandler;
+ deviceData = DeviceHandler2DeviceData (Context->DeviceControl.DeviceHandler);
+ busExtension = (PMB_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ ExAcquireFastMutex(&MbpMutex);
+
+ //
+ // Verify the device data is still valid
+ //
+
+ if (!deviceData->Flags & DEVICE_FLAGS_VALID) {
+
+ //
+ // Caller has invalid handle, or handle to a different device
+ //
+
+ DebugPrint ((DEBUG_MESSAGE, "PnpBios: DeviceControl has invalid device handler \n" ));
+ Context->DeviceControl.Status = STATUS_NO_SUCH_DEVICE;
+ ExReleaseFastMutex(&MbpMutex);
+ HalCompleteDeviceControl (Context);
+ return ;
+ }
+
+ //
+ // Check to see if this request can be begun now
+ //
+
+ link = (PLIST_ENTRY) &Context->ContextWorkQueue;
+ enqueueIt = deviceControlHandler->BeginDeviceControl (deviceData, Context);
+
+ if (enqueueIt) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ KeAcquireSpinLock (&MbpSpinlock, &oldIrql);
+ InsertTailList (&busExtension->DeviceControl, link);
+ KeReleaseSpinLock (&MbpSpinlock, oldIrql);
+ ExReleaseFastMutex(&MbpMutex);
+ return ;
+ }
+
+ //
+ // Dispatch the function to it's handler
+ //
+
+ ExReleaseFastMutex(&MbpMutex);
+ deviceControlHandler->ControlHandler (deviceData, Context);
+}
+
+VOID
+MbpiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData,
+ PBOOLEAN Sync
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a SlotControl. If another SlotControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+ Status - supplies a NTSTATUS code for the completion.
+
+ Context - supplies a pointer to the original device control context.
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Sync - supplies a BOOLEAN variable to indicate
+
+Return Value:
+
+--*/
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY link;
+ PBOOLEAN busyFlag;
+ BOOLEAN startWorker = FALSE;
+ PMB_BUS_EXTENSION busExtension;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ busyFlag = (PBOOLEAN) Context->ContextBusyFlag;
+ deviceHandler = DeviceData2DeviceHandler(DeviceData);
+ busExtension = (PMB_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Pass it to the hal for completion
+ //
+
+ Context->DeviceControl.Status = Status;
+ HalCompleteDeviceControl (Context);
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ KeAcquireSpinLock (&MbpSpinlock, &oldIrql);
+
+ //
+ // Clear appropiate busy flag
+ //
+
+ *busyFlag = FALSE;
+
+ //
+ // Check to see if there are any pending device controls for
+ // this device. If so, requeue them to the worker thread
+ //
+
+ for (link = busExtension->DeviceControl.Flink;
+ link != &busExtension->DeviceControl;
+ link = link->Flink) {
+
+ Context = CONTAINING_RECORD (link, HAL_DEVICE_CONTROL_CONTEXT, ContextWorkQueue);
+ if (Context->DeviceControl.DeviceHandler == deviceHandler) {
+ RemoveEntryList (link);
+ InsertTailList (&MbpControlWorkerList, link);
+ startWorker = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock (&MbpSpinlock, oldIrql);
+
+ if (startWorker) {
+ MbpStartWorker ();
+ }
+}
+
+VOID
+MbpCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a DeviceControl. If another DeviceControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PAGED_CODE();
+
+ MbpiCompleteDeviceControl (
+ Status,
+ Context,
+ DeviceData,
+ &DeviceData->SyncBusy
+ );
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlNone (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to indicate there is no synchronization for this
+ device control function.
+
+Arguments:
+
+ Context - supplies a pointer to the device control context.
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // No synchronization needed for this SlotControl
+ //
+
+ Context->ContextBusyFlag = (ULONG) &MbpNoBusyFlag;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlSync (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize device control request. it checks the
+ state (busy/not busy) of the slot and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // This is a sync command, verify the slot is not busy with a different
+ // command.
+ //
+
+ if (DeviceData->SyncBusy) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ return TRUE;
+ }
+
+ //
+ // Don't enqueue, dispatch it now
+ //
+
+ DeviceData->SyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceData->SyncBusy;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize Eject device control request. it checks the
+ state (busy/not busy) of the device and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the slot control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ BOOLEAN busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ busy = MbBCtlSync (DeviceData, Context);
+
+ if (!busy) {
+
+ //
+ // Set no device in the slot
+ //
+
+ DeviceData->Flags &= ~DEVICE_FLAGS_VALID;
+ DebugPrint ((DEBUG_MESSAGE, "PnpBios: set handle invalid - slot %x for Eject request.\n",
+ DeviceDataSlot(DeviceData)));
+ }
+
+ return busy;
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize LOCK device control request. it checks the
+ state (busy/not busy) of the device and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ BOOLEAN busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ busy = MbBCtlSync (DeviceData, Context);
+#if 0
+ if (!busy) {
+
+ lock = ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer)->Control;
+ if (!lock) {
+
+ //
+ // Set no device in the slot
+ //
+
+ DeviceData->Flags &= ~DEVICE_FLAGS_VALID;
+ }
+ }
+#endif
+ return busy;
+}
+
+VOID
+MbCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to eject the docking station in the docking station
+ slot.
+
+Arguments:
+
+ Context - supplies a pointer to the device control context.
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ if (DeviceData->Flags & DEVICE_FLAGS_DOCKING_STATION) {
+ status = MbpReplyEjectEvent(DeviceDataSlot(DeviceData), TRUE);
+ }
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to reject the Pnp Bios About-to-undock event.
+ To accept the about-to-undock event, the EJECT device control function
+ should be used. If lock = TRUE, it will be handled as a reject eject
+ request. If lock = FALSE, it will be handled as an accept reject rquest.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN lock;
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ lock = ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer)->Control;
+
+ if (DeviceData->Flags & DEVICE_FLAGS_DOCKING_STATION) {
+ status = MbpReplyEjectEvent(DeviceDataSlot(DeviceData), (BOOLEAN)!lock);
+ }
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns a referenced pointer to a callback object which
+ the bus extender will notify whenever a given device's eject botton is
+ pressed.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+ PULONG callback;
+
+ callback =(PULONG)((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer);
+ if (DeviceData->Flags == DEVICE_FLAGS_DOCKING_STATION) {
+ if (MbpEjectCallbackObject) {
+ status = STATUS_SUCCESS;
+ *callback = (ULONG)MbpEjectCallbackObject;
+ } else {
+ status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceCapabilities (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the BCTL_DEVICE_CAPABILITIES structure to the caller
+ specified buffer.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBCTL_DEVICE_CAPABILITIES capabilities;
+
+ capabilities = (PBCTL_DEVICE_CAPABILITIES) Context->DeviceControl.Buffer;
+
+ capabilities->PowerSupported = FALSE;
+ capabilities->ResumeSupported = FALSE;
+ capabilities->LockSupported = FALSE;
+ if (DeviceData->Flags && DEVICE_FLAGS_EJECT_SUPPORTED) {
+ capabilities->EjectSupported = TRUE;
+ } else {
+ capabilities->EjectSupported = FALSE;
+ }
+ MbpCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceData);
+}
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/data.c b/private/ntos/nthals/extender/pnpbios/i386/data.c
new file mode 100644
index 000000000..e3c44e2ff
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/data.c
@@ -0,0 +1,159 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbdata.c
+
+Abstract:
+
+ Declares various data which is specific to bus extender architecture and
+ is independent of BIOS.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+//
+// MbpMutex - To synchronize with device handle changes
+//
+
+FAST_MUTEX MbpMutex;
+
+//
+// MbpSpinLock - Lock to protect DeviceControl globals
+//
+
+KSPIN_LOCK MbpSpinlock;
+
+//
+// MbpControlWorkerList - List of device control's which are pending for worker thread
+//
+
+LIST_ENTRY MbpControlWorkerList;
+ULONG MbpWorkerQueued;
+
+//
+// MbpWorkItem - Enqueue for DeviceControl worker thread
+//
+
+WORK_QUEUE_ITEM MbpWorkItem;
+
+//
+// MbpCheckBusList -
+//
+
+LIST_ENTRY MbpCheckBusList;
+
+//
+// Eject callback object
+//
+
+PCALLBACK_OBJECT MbpEjectCallbackObject;
+
+//
+// regBIOSDeviceName
+//
+
+WCHAR rgzBIOSDeviceName[] = L"\\Device\\PnpBios_%d";
+
+//
+// Size of DeviceHandlerObject
+//
+
+ULONG MbpDeviceHandlerObjectSize;
+
+//
+// DeviceControl dispatch table
+//
+
+#define B_EJECT BCTL_EJECT
+#define B_UID BCTL_QUERY_DEVICE_UNIQUE_ID
+#define B_CAPABILITIES BCTL_QUERY_DEVICE_CAPABILITIES
+#define B_ID BCTL_QUERY_DEVICE_ID
+#define B_RES BCTL_QUERY_DEVICE_RESOURCES
+#define B_RES_REQ BCTL_QUERY_DEVICE_RESOURCE_REQUIREMENTS
+#define B_QUERY_EJECT BCTL_QUERY_EJECT
+#define B_SET_LOCK BCTL_SET_LOCK
+#define B_SET_POWER BCTL_SET_POWER
+#define B_SET_RESUME BCTL_SET_RESUME
+#define B_SET_RES BCTL_SET_DEVICE_RESOURCES
+
+//
+// declare slot control function table.
+// NOTE if the number of entries is changed, the NUMBER_SLOT_CONTROL_FUNCTIONS defined in
+// busp.h must be chnaged accordingly.
+//
+
+DEVICE_CONTROL_HANDLER MbpDeviceControl[] = {
+ B_EJECT, 0, MbBCtlEject, MbCtlEject,
+ B_ID, 32, MbBCtlSync, MbCtlQueryDeviceId,
+ B_UID, 32, MbBCtlSync, MbCtlQueryDeviceUniqueId,
+ B_CAPABILITIES, sizeof(BCTL_DEVICE_CAPABILITIES), MbBCtlSync, MbCtlQueryDeviceCapabilities,
+ B_RES, sizeof(ULONG), MbBCtlSync, MbCtlQueryDeviceResources,
+ B_RES_REQ, sizeof(ULONG), MbBCtlSync, MbCtlQueryDeviceResourceRequirements,
+ B_QUERY_EJECT, sizeof(PVOID), MbBCtlNone, MbCtlQueryEject,
+ B_SET_LOCK, sizeof(BOOLEAN), MbBCtlLock, MbCtlLock,
+ B_SET_RESUME, sizeof(BOOLEAN), NULL, NULL,
+ B_SET_POWER, sizeof(POWER_STATE), NULL, NULL,
+ B_SET_RES, 0, MbBCtlSync, MbCtlSetDeviceResources,
+};
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("PAGE")
+#endif
+
+//
+// Bus Extender driver object
+//
+
+PDRIVER_OBJECT MbpDriverObject;
+
+//
+// Pointers to Hal callback objects
+//
+
+HAL_CALLBACKS MbpHalCallbacks;
+
+//
+// MbpNoBusyFlag - scratch memory location to point at
+//
+
+BOOLEAN MbpNoBusyFlag;
+
+//
+// MbpMaxDeviceData - the maximum device data size
+//
+
+ULONG MbpMaxDeviceData;
+
+//
+// Pointers to bus extension data.
+//
+
+PMB_BUS_EXTENSION MbpBusExtension[2];
+
+//
+// Next Bus number index (i.e. logical bus number)
+//
+
+ULONG MbpNextBusId;
+
+//
+// Array to record bus number of buses
+//
+
+ULONG MbpBusNumber[MAXIMUM_BUS_NUMBER];
diff --git a/private/ntos/nthals/extender/pnpbios/i386/init.c b/private/ntos/nthals/extender/pnpbios/i386/init.c
new file mode 100644
index 000000000..0a921bc07
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/init.c
@@ -0,0 +1,482 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+
+ DriverEntry initialization code for pnp bios bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 21-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+NTSTATUS
+MbInstallBusHandler (
+ IN PBUS_HANDLER MbBus
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(PAGE,MbAddBusDevices)
+#pragma alloc_text(PAGE,MbInstallBusHandler)
+#endif
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if mother board device info is accessible. If yes it
+ initializes its data structures and invokes h/w dependent initialization
+ routine.
+
+Arguments:
+
+ DriverObject - specifies the driver object for the bus extender.
+
+ RegistryPath - supplies a pointer to a unicode string of the service key name in
+ the CurrentControlSet\Services key for the bus extender.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PVOID p;
+ ULONG length, count, i, bufferSize;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ HAL_BUS_INFORMATION busInfo;
+ PCM_RESOURCE_LIST configuration = NULL;
+ ULONG deviceFlags;
+
+ //
+ // Verify Pnp BIOS is present - perform h/w dependent phase 0 initialization.
+ //
+
+ status = PbInitialize(0, NULL);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Pnp Bios data phase 0 Initialization failed.\n"));
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Get pointers to the Hals callback objects. The one we are really interested
+ // in is Bus Check callback.
+ //
+
+ status = HalQuerySystemInformation (
+ HalCallbackInformation,
+ sizeof (MbpHalCallbacks),
+ &MbpHalCallbacks,
+ &length
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Failed to query Hal callbacks\n"));
+ return status;
+ }
+
+ //
+ // Initialize globals
+ //
+
+ MbpDriverObject = DriverObject;
+ ExInitializeWorkItem (&MbpWorkItem, MbpControlWorker, NULL);
+ KeInitializeSpinLock (&MbpSpinlock);
+ InitializeListHead (&MbpControlWorkerList);
+ InitializeListHead (&MbpCheckBusList);
+ ExInitializeFastMutex (&MbpMutex);
+ MbpDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
+
+ for (i = 0; i < MAXIMUM_BUS_NUMBER; i++) {
+ MbpBusNumber[i] = (ULONG) -1;
+ }
+
+ //
+ // Initialize driver object add and detect device entries.
+ //
+
+ DriverObject->DriverExtension->AddDevice = MbAddBusDevices;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = MbCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = MbCreateClose;
+
+ //
+ // Query the devices/buses currently controlled by the bus extender
+ //
+
+ status = IoQueryDeviceEnumInfo (&DriverObject->DriverExtension->ServiceKeyName, &count);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+ for (i = 0; i < count; i++) {
+ status = IoGetDeviceHandler(&DriverObject->DriverExtension->ServiceKeyName,
+ i,
+ &deviceHandler);
+ if (NT_SUCCESS(status)) {
+ bufferSize = sizeof(CM_RESOURCE_LIST);
+tryAgain:
+ configuration = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool,
+ bufferSize
+ );
+ if (!configuration) {
+ IoReleaseDeviceHandler(deviceHandler);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ status = IoQueryDeviceConfiguration(deviceHandler,
+ &busInfo,
+ &deviceFlags,
+ configuration,
+ bufferSize, // buffer size
+ &length // Actual size
+ );
+ IoReleaseDeviceHandler(deviceHandler);
+ if (NT_SUCCESS(status)) {
+
+ //
+ // We know we have two buses at most. If this is the first bus, we will add it
+ // and exit. We don't touch 2nd bus at init time. It should be enumerated
+ // later.
+
+ if (length >= MIN_DETECT_SIGNATURE_SIZE &&
+ configuration->List[0].BusNumber == 0 &&
+ configuration->List[0].InterfaceType == BUS_0_SIGNATURE) {
+ if (deviceFlags == DeviceStatusOK) {
+ MbAddBusDevices(&DriverObject->DriverExtension->ServiceKeyName, &i);
+ ExFreePool(configuration);
+ break;
+ }
+ }
+ } else if (status == STATUS_BUFFER_TOO_SMALL) {
+ ExFreePool(configuration);
+ bufferSize = length;
+ goto tryAgain;
+ }
+ ExFreePool(configuration);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN OUT PULONG InstanceNumber
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ PBUS_HANDLER busHandler;
+ PCM_RESOURCE_LIST detectSignature;
+ UCHAR configuration[sizeof(CM_RESOURCE_LIST)];
+ UNICODE_STRING unicodeString;
+ WCHAR buffer[60];
+ ULONG VirtualBusNumber;
+ PDEVICE_HANDLER_OBJECT deviceHandler = NULL;
+
+ PAGED_CODE();
+ RtlZeroMemory(configuration, sizeof(CM_RESOURCE_LIST));
+
+ //
+ // Check if DriverEntry succeeded ...
+ //
+
+ if (!MbpDriverObject) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ if (*InstanceNumber == PLUGPLAY_NO_INSTANCE) {
+ if (MbpBusNumber[0] == (ULONG) -1) {
+
+ //
+ // If bus handler for Pnp Bios bus 0 has not been installed,
+ // add this bus.
+ //
+ // Register bus handler for bus 0 - motherboard devices
+ //
+
+ status = HalRegisterBusHandler (
+ Internal,
+ -1,
+ (ULONG)-1,
+ Isa, // child of Isa bus # 0
+ 0,
+ sizeof (MB_BUS_EXTENSION),
+ MbInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus 0 handler failed\n"));
+ return status;
+ }
+
+ //
+ // Register the bus with Pnp manager.
+ //
+
+ detectSignature = (PCM_RESOURCE_LIST)configuration;
+ detectSignature->Count = 1;
+ detectSignature->List[0].InterfaceType = BUS_0_SIGNATURE;
+ detectSignature->List[0].BusNumber = 0;
+ status = IoRegisterDetectedDevice (&MbpDriverObject->DriverExtension->ServiceKeyName,
+ detectSignature,
+ InstanceNumber);
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // BUGBUG - unregister bus handler? How?
+ //
+
+ DebugPrint((DEBUG_BREAK,"PnpBios: Failed to register bus 0 to Pnp Mgr\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ } else {
+
+ //
+ // Enumerator should be able to find the docking station bus, if present,
+ // and should call this routine with a valid InstanceNumber. So, if after
+ // bus 0 is registered and enumerator calls this function again with
+ // *InstanceNumber == PLUGPLAY_NO_INSTANCE, it means there is no docking
+ // station bus - bus 1, we can simply return STATUS_NO_MORE_ENTRIES.
+ //
+
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ } else {
+
+ if (MbpBusNumber[0] == (ULONG) -1) {
+
+ //
+ // If bus handler for Pnp Bios bus 0 has not been installed,
+ // add this bus.
+ //
+ // Register bus handler for bus 0 - motherboard devices
+ //
+
+ status = HalRegisterBusHandler (
+ Internal,
+ -1,
+ (ULONG)-1,
+ Isa, // child of Isa bus # 0
+ 0,
+ sizeof (MB_BUS_EXTENSION),
+ MbInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus 0 handler failed\n"));
+ return status;
+ }
+
+ } else if (MbpBusNumber[1] == (ULONG) -1 && MbpBusExtension[0]->DockingStationDevice ) {
+
+ //
+ // If bus 1 has not been registered and docking station is present,
+ // Register bus handler for bus 1 - docking station devices
+ //
+
+ status = HalRegisterBusHandler (
+ Internal,
+ -1,
+ (ULONG)-1,
+ Internal,
+ MbpBusNumber[0],
+ sizeof (MB_BUS_EXTENSION),
+ MbInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus handler for bus 1 failed\n"));
+ return status;
+ }
+ } else {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ }
+
+ //
+ // Call Pnp Io Mgr to register the new device object path
+ //
+
+ swprintf (buffer, rgzBIOSDeviceName, busHandler->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ if (!NT_SUCCESS(status = IoGetDeviceHandler(&MbpDriverObject->DriverExtension->ServiceKeyName,
+ *InstanceNumber, &deviceHandler)) ||
+ !NT_SUCCESS(status = IoRegisterDevicePath(deviceHandler, &unicodeString, TRUE, NULL,
+ DeviceStatusOK))) {
+
+ //
+ // BUGBUG - unregister bus handler? How?
+ //
+
+ if (deviceHandler) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register NT device path failed\n"));
+ IoReleaseDeviceHandler(deviceHandler);
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Unable to get device handler\n"));
+ }
+ }
+
+ IoReleaseDeviceHandler(deviceHandler);
+
+ //
+ // Perform initial bus check
+ //
+
+ MbpCheckBus(busHandler);
+
+ //
+ // Give non portable part of initialization another chance - phase 1 initialization.
+ //
+
+ PbInitialize(1, busHandler->DeviceObject);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbInstallBusHandler (
+ PBUS_HANDLER MbBus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked by Hal to initialize BUS_HANDLER structure and its
+ extension.
+
+Arguments:
+
+ MbBus - spplies a pointer to Pnp BIOS bus handler's BUS_HANDLER structure.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ WCHAR buffer[60];
+ UNICODE_STRING unicodeString;
+ PMB_DEVICE_EXTENSION deviceExtension;
+ PMB_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+ PDEVICE_OBJECT deviceObject;
+
+ PAGED_CODE();
+
+ //
+ // Verify there's a parent handler
+ //
+
+ if (!MbBus->ParentHandler) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Create device object for Motherboard/PnpBios bus extender.
+ //
+
+ swprintf (buffer, rgzBIOSDeviceName, MbBus->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ status = IoCreateDevice(
+ MbpDriverObject,
+ sizeof(MB_DEVICE_EXTENSION), // No device extension space
+ &unicodeString,
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &deviceObject
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Failed to create device object\n"));
+ return status;
+ }
+
+ // ===================================
+ // BUGBUG - need to find a solution
+ //
+
+ deviceObject->Flags &= ~0x80;
+
+ // ==================================
+ deviceExtension = (PMB_DEVICE_EXTENSION) deviceObject->DeviceExtension;
+ deviceExtension->BusHandler = MbBus;
+
+ //
+ // Initialize bus handlers
+ //
+
+ MbBus->DeviceObject = deviceObject;
+ MbBus->GetBusData = (PGETSETBUSDATA) MbGetBusData;
+ MbBus->SetBusData = (PGETSETBUSDATA) MbSetBusData;
+ MbBus->QueryBusSlots = (PQUERY_BUS_SLOTS) MbQueryBusSlots;
+ MbBus->DeviceControl = (PDEVICE_CONTROL) MbDeviceControl;
+ MbBus->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) MbpReferenceDeviceHandler;
+ MbBus->GetDeviceData = (PGET_SET_DEVICE_DATA) MbGetDeviceData;
+ MbBus->SetDeviceData = (PGET_SET_DEVICE_DATA) MbSetDeviceData;
+
+ //
+ // Intialize bus extension
+ //
+
+ busExtension = (PMB_BUS_EXTENSION)MbBus->BusData;
+ RtlZeroMemory(busExtension, sizeof(MB_BUS_EXTENSION));
+ busExtension->BusHandler = MbBus;
+
+ MbpBusNumber[MbpNextBusId] = MbBus->BusNumber;
+ MbpBusExtension[MbpNextBusId] = busExtension;
+ MbpNextBusId++;
+
+ InitializeListHead (&busExtension->CheckBus);
+ InitializeListHead (&busExtension->DeviceControl);
+
+ return STATUS_SUCCESS;
+}
+
+
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/misc.c b/private/ntos/nthals/extender/pnpbios/i386/misc.c
new file mode 100644
index 000000000..2fb2210fe
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/misc.c
@@ -0,0 +1,471 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+ This file contains pnp bios bus extender support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 20-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,MbCreateClose)
+#pragma alloc_text(PAGE,PbGetRegistryValue)
+#pragma alloc_text(PAGE,PbDecompressEisaId)
+#endif
+
+
+NTSTATUS
+MbCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles open and close requests such that our device objects
+ can be opened. All it does it to complete the Irp with success.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer to the device object to be opened or closed.
+
+ Irp - supplies a pointer to I/O request packet.
+
+Return Value:
+
+ Always returns STATUS_SUCCESS, since this is a null operation.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( DeviceObject );
+
+ PAGED_CODE();
+
+ //
+ // Null operation. Do not give an I/O boost since no I/O was
+ // actually done. IoStatus.Information should be
+ // FILE_OPENED for an open; it's undefined for a close.
+ //
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+
+ IoCompleteRequest( Irp, 0);
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+PbDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompressed compressed Eisa Id and returns the Id to caller
+ specified character buffer.
+
+Arguments:
+
+ CompressedId - supplies the compressed Eisa Id.
+
+ EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT c1, c2;
+ LONG i;
+
+ PAGED_CODE();
+
+ CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
+ c1 = c2 = (USHORT)CompressedId;
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ for (i = 2; i >= 0; i--) {
+ *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
+ c1 >>= 5;
+ }
+ EisaId += 3;
+ c1 = c2 = (USHORT)(CompressedId >> 16);
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ sprintf (EisaId, "%04x", c1);
+}
+
+NTSTATUS
+PbGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to retrieve the data for a registry key's value.
+ This is done by querying the value of the key with a zero-length buffer
+ to determine the size of the value, and then allocating a buffer and
+ actually querying the value into the buffer.
+
+ It is the responsibility of the caller to free the buffer.
+
+Arguments:
+
+ KeyHandle - Supplies the key handle whose value is to be queried
+
+ ValueName - Supplies the null-terminated Unicode name of the value.
+
+ Information - Returns a pointer to the allocated data buffer.
+
+Return Value:
+
+ The function value is the final status of the query operation.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PKEY_VALUE_FULL_INFORMATION infoBuffer;
+ ULONG keyValueLength;
+
+ PAGED_CODE();
+
+ RtlInitUnicodeString( &unicodeString, ValueName );
+
+ //
+ // Figure out how big the data value is so that a buffer of the
+ // appropriate size can be allocated.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ (PVOID) NULL,
+ 0,
+ &keyValueLength );
+ if (status != STATUS_BUFFER_OVERFLOW &&
+ status != STATUS_BUFFER_TOO_SMALL) {
+ return status;
+ }
+
+ //
+ // Allocate a buffer large enough to contain the entire key data value.
+ //
+
+ infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
+ if (!infoBuffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Query the data for the key value.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ infoBuffer,
+ keyValueLength,
+ &keyValueLength );
+ if (!NT_SUCCESS( status )) {
+ ExFreePool( infoBuffer );
+ return status;
+ }
+
+ //
+ // Everything worked, so simply return the address of the allocated
+ // buffer to the caller, who is now responsible for freeing it.
+ //
+
+ *Information = infoBuffer;
+ return STATUS_SUCCESS;
+}
+#if DBG
+
+VOID
+PbDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This routine displays debugging message or causes a break.
+
+Arguments:
+
+ Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
+ DEBUG_BREAK - displays message and break.
+
+ DebugMessage - supplies a pointer to the debugging message.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ if (Level == DEBUG_BREAK) {
+ DbgBreakPoint();
+ }
+
+ va_end(ap);
+}
+
+VOID
+MbpDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR c = ' ';
+
+ if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
+ c = 'A';
+ } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
+ c = 'P';
+ }
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
+ Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
+ Desc->u.Port.Alignment,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
+ Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
+ Desc->u.Memory.Alignment,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Interrupt.MinimumVector,
+ Desc->u.Interrupt.MaximumVector
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Dma.MinimumChannel,
+ Desc->u.Dma.MaximumChannel
+ );
+ break;
+ }
+}
+
+VOID
+MbpDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays Io resource requirements list.
+
+Arguments:
+
+ IoList - supplies a pointer to the Io resource requirements list to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIO_RESOURCE_LIST resList;
+ PIO_RESOURCE_DESCRIPTOR resDesc;
+ ULONG listCount, count, i, j;
+
+ DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
+ listCount = IoList->AlternativeLists;
+ resList = &IoList->List[0];
+ for (i = 0; i < listCount; i++) {
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
+ resList->Revision, resList->Count);
+ resDesc = &resList->Descriptors[0];
+ count = resList->Count;
+ for (j = 0; j < count; j++) {
+ MbpDumpIoResourceDescriptor(" ", resDesc);
+ resDesc++;
+ }
+ resList = (PIO_RESOURCE_LIST) resDesc;
+ }
+}
+
+VOID
+MbpDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
+ Indent,
+ Desc->u.Interrupt.Level,
+ Desc->u.Interrupt.Vector,
+ Desc->u.Interrupt.Affinity
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA Channel: %x, Port: %x\n",
+ Indent,
+ Desc->u.Dma.Channel,
+ Desc->u.Dma.Port
+ );
+ break;
+ }
+}
+
+VOID
+MbpDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine displays CM resource list.
+
+Arguments:
+
+ CmList - supplies a pointer to CM resource list
+
+ SlotNumber - slot number of the resources
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG count, i;
+
+ fullDesc = &CmList->List[0];
+ DbgPrint("Pnp Bios Cm Resource List for Slot %x -\n", SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
+ partialDesc = &fullDesc->PartialResourceList;
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
+ partialDesc->Revision, partialDesc->Count);
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ MbpDumpCmResourceDescriptor(" ", desc);
+ desc++;
+ }
+}
+#endif
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbapi.h b/private/ntos/nthals/extender/pnpbios/i386/pbapi.h
new file mode 100644
index 000000000..70193117a
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbapi.h
@@ -0,0 +1,235 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ bpapi.h
+
+Abstract:
+
+ This module contins definitions/declarations for pnp bios independent code
+ to call Pnp bios dependent code. This module is considered portable code.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-26-1995
+
+Revision History:
+
+--*/
+
+#include "pbios.h"
+
+//
+// internal structures for resource translation
+//
+
+typedef struct _PB_DEPENDENT_RESOURCES {
+ ULONG Count;
+ UCHAR Flags;
+ UCHAR Priority;
+ struct _PB_DEPENDENT_RESOURCES *Next;
+} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
+
+#define DEPENDENT_FLAGS_END 1
+
+typedef struct _PB_ATERNATIVE_INFORMATION {
+ PPB_DEPENDENT_RESOURCES Resources;
+ ULONG NoDependentFunctions;
+ ULONG TotalResourceCount;
+} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
+
+#define PB_CM_FORMAT 0
+#define PB_IO_FORMAT 1
+
+//
+// A big structure for calling Pnp BIOS functions
+//
+
+#define PNP_BIOS_GET_NUMBER_DEVICE_NODES 0
+#define PNP_BIOS_GET_DEVICE_NODE 1
+#define PNP_BIOS_SET_DEVICE_NODE 2
+#define PNP_BIOS_GET_EVENT 3
+#define PNP_BIOS_SEND_MESSAGE 4
+#define PNP_BIOS_GET_DOCK_INFORMATION 5
+// Function 6 is reserved
+#define PNP_BIOS_SELECT_BOOT_DEVICE 7
+#define PNP_BIOS_GET_BOOT_DEVICE 8
+#define PNP_BIOS_SET_OLD_ISA_RESOURCES 9
+#define PNP_BIOS_GET_OLD_ISA_RESOURCES 0xA
+#define PNP_BIOS_GET_ISA_CONFIGURATION 0x40
+
+typedef struct _PB_DOCKING_STATION_INFORMATION {
+ ULONG LocationId;
+ ULONG SerialNumber;
+ USHORT Capabilities;
+} PB_DOCKING_STATION_INFORMATION, *PPB_DOCKING_STATION_INFORMATION;
+
+//
+// definitions of Docking station capabilities.
+//
+
+#define DOCKING_CAPABILITIES_MASK 6
+#define DOCKING_CAPABILITIES_COLD_DOCKING 0
+#define DOCKING_CAPABILITIES_WARM_DOCKING 1
+#define DOCKING_CAPABILITIES_HOT_DOCKING 2
+
+typedef struct _PB_PARAMETERS {
+ USHORT Function;
+ union {
+ struct {
+ USHORT *NumberNodes;
+ USHORT *NodeSize;
+ } GetNumberDeviceNodes;
+
+ struct {
+ USHORT *Node;
+ PPNP_BIOS_DEVICE_NODE NodeBuffer;
+ USHORT Control;
+ } GetDeviceNode;
+
+ struct {
+ USHORT Node;
+ PPNP_BIOS_DEVICE_NODE NodeBuffer;
+ USHORT Control;
+ } SetDeviceNode;
+
+ struct {
+ USHORT *Message;
+ } GetEvent;
+
+ struct {
+ USHORT Message;
+ } SendMessage;
+
+ struct {
+ PB_DOCKING_STATION_INFORMATION *DockingStationInfo;
+ USHORT *DockState;
+ } GetDockInfo;
+ } u;
+} PB_PARAMETERS, *PPB_PARAMETERS;
+
+#define PB_MAXIMUM_STACK_SIZE (sizeof(PB_PARAMETERS) + sizeof(USHORT) * 2)
+
+//
+// PNP BIOS send message api definitions
+//
+
+#define OK_TO_CHANGE_CONFIG 00
+#define ABORT_CONFIG_CHANGE 01
+#define PNP_OS_ACTIVE 0x42
+
+//
+// Control Flags for Get_Device_Node
+//
+
+#define GET_CURRENT_CONFIGURATION 1
+#define GET_NEXT_BOOT_CONFIGURATION 2
+
+//
+// Control Flags for Set_Device_node
+//
+
+#define SET_CONFIGURATION_NOW 1
+#define SET_CONFIGURATION_FOR_NEXT_BOOT 2
+
+//
+// Debug functions
+//
+
+#if DBG
+
+VOID
+MbpDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ );
+
+VOID
+MbpDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ );
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_BREAK 2
+
+VOID PbDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+#define DebugPrint(arg) PbDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
+//
+// External References
+//
+
+extern PPNP_BIOS_INSTALLATION_CHECK PbBiosRegistryData;
+extern PVOID PbBiosKeyInformation;
+
+//
+// prototypes
+//
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ IN UCHAR Format,
+ OUT PUCHAR *ReturnedList,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+PbCmResourcesToBiosResources (
+ IN PCM_RESOURCE_LIST CmResources,
+ IN PUCHAR BiosRequirements,
+ IN PUCHAR *BiosResources,
+ IN PULONG Length
+ );
+
+NTSTATUS
+PbInitialize (
+ IN ULONG Phase,
+ IN PDEVICE_OBJECT DeviceObject
+ );
+
+NTSTATUS
+PbGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ );
+
+NTSTATUS
+PbHardwareService (
+ IN PPB_PARAMETERS Parameters
+ );
+
+VOID
+PbDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ );
+
+BOOLEAN
+PbVerifyBusAdd (
+ VOID
+ );
+
+BOOLEAN
+MbpConfigAboutToChange (
+ VOID
+ );
+
+VOID
+MbpConfigChanged (
+ VOID
+ );
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c b/private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c
new file mode 100644
index 000000000..49a9fbaa3
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c
@@ -0,0 +1,1562 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xlate.c
+
+Abstract:
+
+ This file contains routines to translate resources between PnP ISA/BIOS
+ format and Windows NT formats.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "pbapi.h"
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ );
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ );
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbCmIrqToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PbCmDmaToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PbCmPortToBiosDescriptor (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PbCmMemoryToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(PAGE,PbBiosResourcesToNtResources)
+#pragma alloc_text(PAGE,PbIoDescriptorToCmDescriptor)
+#pragma alloc_text(PAGE,PbAddDependentResourcesToList)
+#pragma alloc_text(PAGE,PbBiosIrqToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosDmaToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortFixedToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosMemoryToIoDescriptor)
+#pragma alloc_text(PAGE,PbCmIrqToBiosDescriptor)
+#pragma alloc_text(PAGE,PbCmDmaToBiosDescriptor)
+#pragma alloc_text(PAGE,PbCmPortToBiosDescriptor)
+#pragma alloc_text(PAGE,PbCmMemoryToBiosDescriptor)
+#endif
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ IN UCHAR Format,
+ OUT PUCHAR *ReturnedList,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Bios resource list and generates
+ a NT resource list. The returned Nt resource list could be either IO
+ format or CM format. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ SlotNumber - specifies the slot number of the BIOS resource.
+
+ BiosData - Supplies a pointer to a variable which specifies the bios resource
+ data buffer and which to receive the pointer to next bios resource data.
+
+ Format - PB_CM_FORMAT (0) if convert bios resources to Cm format;
+ PB_IO_FORMAT (1) if convert bios resources to Io format.
+
+ ReturnedList - supplies a variable to receive the desired resource list.
+
+ ReturnedLength - Supplies a variable to receive the length of the resource list.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PUCHAR buffer;
+ USHORT mask16, increment;
+ UCHAR tagName, mask8;
+ NTSTATUS status;
+ PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
+ ULONG commonResCount = 0, dependDescCount = 0, i, j;
+ ULONG alternativeListCount = 0, dependFunctionCount = 0;
+ PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
+ PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
+ BOOLEAN dependent = FALSE;
+ PCM_RESOURCE_LIST cmResourceList;
+ ULONG listSize, noResLists;
+ PUCHAR resourceList = NULL;
+
+ //
+ // First, scan the bios data to determine the memory requirement and
+ // the information to build internal data structures.
+ //
+
+ *ReturnedLength = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ while (tagName != TAG_COMPLETE_END) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ tagName &= SMALL_TAG_MASK;
+ } else {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ }
+
+ //
+ // Based on the type of the BIOS resource, determine the count of
+ // the IO descriptors.
+ //
+
+ switch (tagName) {
+ case TAG_IRQ:
+ mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
+ i = 0;
+ while (mask16) {
+ if (mask16 & 1) {
+ i++;
+ }
+ mask16 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_DMA:
+ mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
+ i = 0;
+ while (mask8) {
+ if (mask8 & 1) {
+ i++;
+ }
+ mask8 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ dependFunctionCount++;
+ break;
+ case TAG_END_DEPEND:
+ dependent = FALSE;
+ alternativeListCount++;
+ break;
+ case TAG_IO_FIXED:
+ case TAG_IO:
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (!dependent) {
+ commonResCount++;
+ } else {
+ dependDescCount++;
+ }
+ break;
+ default:
+
+ //
+ // Unknown tag. Skip it.
+ //
+
+ DebugPrint((DEBUG_BREAK, "BiosToNtResources: unknown tag.\n"));
+ break;
+ }
+
+ //
+ // Move to next bios resource descriptor.
+ //
+
+ buffer += increment;
+ tagName = *buffer;
+ }
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (commonResCount == 0 && dependFunctionCount == 0) {
+ *ReturnedList = NULL;
+ *ReturnedLength = 0;
+ *BiosData = buffer + 2;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Allocate memory for our internal data structures
+ //
+
+ if (dependFunctionCount) {
+ dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
+ PagedPool,
+ dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
+ dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
+ 'bPnP'
+ );
+ if (!dependResources) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ dependResList = dependResources; // remember it so we can free it.
+ }
+
+ if (alternativeListCount) {
+ ASSERT(dependFunctionCount != 0);
+ alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
+ 'bPnP'
+ );
+ if (!alternativeList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit0;
+ }
+ RtlZeroMemory(alternativeList,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
+ );
+ alternativeList[0].Resources = dependResources;
+ }
+ if (commonResCount) {
+ commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
+ 'bPnP'
+ );
+ if (!commonResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit1;
+ }
+ }
+
+ //
+ // Now start over again to process the bios data and initialize our internal
+ // resource representation.
+ //
+
+ commonIoDesc = commonResources;
+ dependDescCount = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ dependent = FALSE;
+ while (tagName != TAG_COMPLETE_END) {
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ tagName &= SMALL_TAG_MASK;
+ }
+ switch (tagName) {
+ case TAG_IRQ:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_DMA:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ alternativeList[alternativeListCount].NoDependentFunctions++;
+ if (dependDescCount != 0) {
+
+ //
+ // End of current dependent function
+ //
+
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = 0;
+ dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = dependResources->Next;
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ }
+ if (*buffer & SMALL_TAG_SIZE_MASK) {
+ dependResources->Priority = *(buffer + 1);
+ }
+ dependDescCount = 0;
+ dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
+ buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
+ break;
+ case TAG_END_DEPEND:
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = DEPENDENT_FLAGS_END;
+ dependResources->Next = alternativeList[alternativeListCount].Resources;
+ dependent = FALSE;
+ dependDescCount = 0;
+ alternativeListCount++;
+ alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = alternativeList[alternativeListCount].Resources;
+ buffer++;
+ break;
+ case TAG_IO:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_IO_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ dependDescCount;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ default:
+
+ //
+ // Don't-care tag simpley advance the buffer pointer to next tag.
+ //
+
+ if (*buffer & LARGE_RESOURCE_TAG) {
+ increment = *(buffer+1);
+ increment += 3; // length of large tag
+ } else {
+ increment = (UCHAR)(*buffer) & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ buffer += increment;
+ }
+ tagName = *buffer;
+ }
+
+ if (alternativeListCount != 0) {
+ alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
+ }
+ *BiosData = buffer + 2; // Skip END_TAG
+
+ //
+ // prepare Cm/IoResourceList
+ //
+
+ if (Format == PB_CM_FORMAT) {
+ listSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
+ (commonResCount - 1);
+ } else {
+ ULONG totalDescCount, descCount;
+
+ noResLists = 1;
+ for (i = 0; i < alternativeListCount; i++) {
+ noResLists *= alternativeList[i].NoDependentFunctions;
+ }
+ totalDescCount = 0;
+ for (i = 0; i < alternativeListCount; i++) {
+ descCount = 1;
+ for (j = 0; j < alternativeListCount; j++) {
+ if (j == i) {
+ descCount *= alternativeList[j].TotalResourceCount;
+ } else {
+ descCount *= alternativeList[j].NoDependentFunctions;
+ }
+ }
+ totalDescCount += descCount;
+ }
+ listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
+ sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
+ }
+ resourceList = ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
+ if (!resourceList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit2;
+ }
+ if (Format == PB_CM_FORMAT) {
+ PCM_PARTIAL_RESOURCE_LIST partialResList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+
+ cmResourceList = (PCM_RESOURCE_LIST)resourceList;
+ cmResourceList->Count = 1;
+ cmResourceList->List[0].InterfaceType = Internal;
+ cmResourceList->List[0].BusNumber = BusNumber;
+ partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResourceList->List[0].PartialResourceList;
+ partialResList->Version = 0;
+ partialResList->Revision = 0;
+ partialResList->Count = commonResCount;
+ commonIoDesc = commonResources;
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
+ for (i = 0; i < commonResCount; i++) {
+ PbIoDescriptorToCmDescriptor(commonIoDesc, partialDesc);
+ partialDesc++;
+ commonIoDesc++;
+ }
+ } else {
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
+ PIO_RESOURCE_LIST ioResList;
+
+ ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)resourceList;
+ ioResReqList->ListSize = listSize;
+ ioResReqList->InterfaceType = Internal;
+ ioResReqList->BusNumber = BusNumber;
+ ioResReqList->SlotNumber = SlotNumber;
+ ioResReqList->Reserved[0] = 0;
+ ioResReqList->Reserved[1] = 0;
+ ioResReqList->Reserved[2] = 0;
+ ioResReqList->AlternativeLists = noResLists;
+ ioResList = &ioResReqList->List[0];
+
+ //
+ // Build resource lists
+ //
+
+ for (i = 0; i < noResLists; i++) {
+ ULONG size;
+
+ ioResList->Version = 1;
+ ioResList->Revision = 1;
+ buffer = (PUCHAR)&ioResList->Descriptors[0];
+
+ //
+ // Copy common resources to the list
+ //
+
+ if (commonResources) {
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
+ RtlMoveMemory(buffer, commonResources, size);
+ buffer += size;
+ }
+
+ //
+ // Copy dependent functions if any.
+ //
+
+ if (alternativeList) {
+ PbAddDependentResourcesToList(&buffer, 0, alternativeList);
+ }
+
+ //
+ // Update io resource list ptr
+ //
+
+ ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
+ sizeof(IO_RESOURCE_DESCRIPTOR);
+ ioResList = (PIO_RESOURCE_LIST)buffer;
+ }
+ }
+ *ReturnedLength = listSize;
+ status = STATUS_SUCCESS;
+ *ReturnedList = resourceList;
+exit2:
+ if (commonResources) {
+ ExFreePool(commonResources);
+ }
+exit1:
+ if (alternativeList) {
+ ExFreePool(alternativeList);
+ }
+exit0:
+ if (dependResList) {
+ ExFreePool(dependResList);
+ }
+ return status;
+}
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds dependent functions to caller specified list.
+
+Arguments:
+
+ ResourceDescriptor - supplies a pointer to the descriptor buffer.
+
+ ListNo - supplies an index to the AlternativeList.
+
+ AlternativeList - supplies a pointer to the alternativelist array.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPB_DEPENDENT_RESOURCES dependentResources, ptr;
+ ULONG size;
+
+ //
+ // Copy dependent resources to caller supplied list buffer and
+ // update the list buffer pointer.
+ //
+
+ dependentResources = AlternativeList[ListNo].Resources;
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
+ RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
+ *ResourceDescriptor = *ResourceDescriptor + size;
+
+ //
+ // Add dependent resource of next list to caller's buffer
+ //
+
+ if (AlternativeList[ListNo + 1].Resources) {
+ ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
+ } else {
+ ptr = NULL;
+ }
+ if (ptr == NULL) {
+ AlternativeList[ListNo].Resources = dependentResources->Next;
+ if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
+ ptr = dependentResources->Next;
+ }
+ }
+ return ptr;
+}
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Arguments:
+
+ IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
+
+ CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CmDescriptor->Type = IoDescriptor->Type;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ switch (CmDescriptor->Type) {
+ case CmResourceTypePort:
+ CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
+ CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
+ break;
+ case CmResourceTypeInterrupt:
+ CmDescriptor->u.Interrupt.Level =
+ CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
+ CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
+ break;
+ case CmResourceTypeMemory:
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
+ break;
+ case CmResourceTypeDma:
+ CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
+ CmDescriptor->u.Dma.Port = 0;
+ CmDescriptor->u.Dma.Reserved1 = 0;
+ break;
+ }
+}
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IRQ information to NT usable format.
+ This routine stops when an irq io resource is generated. if there are
+ more irq io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ USHORT mask;
+ ULONG irq;
+ PPNP_IRQ_DESCRIPTOR buffer;
+ UCHAR size, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ size = buffer->Tag & SMALL_TAG_SIZE_MASK;
+ mask = buffer->IrqMask;
+ mask >>= bitPosition;
+ irq = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ irq = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (irq != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeInterrupt;
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (size == 3 && buffer->Information & 0x0C) {
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ IoDescriptor->ShareDisposition = CmResourceShareShared;
+ }
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Interrupt.MinimumVector = irq;
+ IoDescriptor->u.Interrupt.MaximumVector = irq;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current irq tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ *BiosData = (PUCHAR)buffer + size + 1;
+ return status;
+}
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS DMA information to NT usable format.
+ This routine stops when an dma io resource is generated. if there are
+ more dma io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ ULONG dma;
+ PPNP_DMA_DESCRIPTOR buffer;
+ UCHAR mask, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ mask = buffer->ChannelMask;
+ mask >>= bitPosition;
+ dma = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ dma = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (dma != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeDma;
+ IoDescriptor->Flags = 0;
+ IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Dma.MinimumChannel = dma;
+ IoDescriptor->u.Dma.MaximumChannel = dma;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current dma tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return status;
+}
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS FIXED IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_FIXED_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = 1;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS MEMORY information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PUCHAR buffer;
+ UCHAR tag;
+ PHYSICAL_ADDRESS minAddr, maxAddr;
+ ULONG alignment, length;
+ USHORT increment;
+
+ buffer = *BiosData;
+ tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
+ increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
+
+ minAddr.HighPart = 0;
+ maxAddr.HighPart = 0;
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
+ maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
+ maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
+ maxAddr.LowPart = minAddr.LowPart + length - 1;
+ alignment = 1;
+ break;
+ }
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypeMemory;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Memory.MinimumAddress = minAddr;
+ IoDescriptor->u.Memory.MaximumAddress = maxAddr;
+ IoDescriptor->u.Memory.Alignment = alignment;
+ IoDescriptor->u.Memory.Length = length;
+
+ //
+ // Done with current tag, advance pointer to next tag
+ //
+
+ buffer += increment;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbCmResourcesToBiosResources (
+ IN PCM_RESOURCE_LIST CmResources,
+ IN PUCHAR BiosRequirements,
+ IN PUCHAR *BiosResources,
+ IN PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Cm resource list and generates
+ a Pnp BIOS resource list. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ CmResources - Supplies a pointer to a Cm resource list buffer.
+
+ BiosRequirements - supplies a pointer to the PnP BIOS possible resources.
+
+ BiosResources - Supplies a variable to receive the pointer to the
+ converted bios resource buffer.
+
+ Length - supplies a pointer to a variable to receive the length
+ of the Pnp Bios resources.
+
+Return Value:
+
+ a pointer to a Pnp Bios resource list if succeeded. Else,
+ a NULL pointer will be returned.
+
+--*/
+{
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
+ ULONG i, count, length, totalSize = 0;
+ PUCHAR p, biosDesc;
+ NTSTATUS status;
+
+ count = CmResources->List[0].PartialResourceList.Count;
+ if (count == 0 || CmResources->Count != 1) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate max amount of memory
+ //
+
+ p= ExAllocatePoolWithTag(PagedPool,
+ count * sizeof(PNP_MEMORY_DESCRIPTOR),
+ 'bPnP');
+ if (!p) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
+ for (i = 0; i < count; i++) {
+ switch (cmDesc->Type) {
+ case CmResourceTypePort:
+ status = PbCmPortToBiosDescriptor (
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeInterrupt:
+ status = PbCmIrqToBiosDescriptor(
+ BiosRequirements,
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeMemory:
+ status = PbCmMemoryToBiosDescriptor (
+ BiosRequirements,
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeDma:
+ status = PbCmDmaToBiosDescriptor (
+ BiosRequirements,
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeDeviceSpecific:
+ length = cmDesc->u.DeviceSpecificData.DataSize;
+ cmDesc++;
+ cmDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDesc + length);
+ continue;
+ }
+ if (NT_SUCCESS(status)) {
+ cmDesc++;
+ RtlMoveMemory(p, biosDesc, length);
+ ExFreePool(biosDesc);
+ p += length;
+ totalSize += length;
+ } else {
+ ExFreePool(p);
+ break;
+ }
+ }
+ if (NT_SUCCESS(status)) {
+ *p = TAG_COMPLETE_END;
+ p++;
+ *p = 0; // checksum ignored
+ totalSize += 2;
+ }
+ return status;
+}
+
+NTSTATUS
+PbCmIrqToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM IRQ information to Pnp BIOS format.
+ Since there is not enough information in the CM int descriptor to
+ convert it to Pnp BIOS descriptor. We will search the Bios
+ possible resource lists for the corresponding resource information.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the bios possible resource lists.
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+Return Value:
+
+ return a pointer to the desired dma descriptor in the BiosRequirements. Null
+ if not found.
+
+--*/
+{
+ USHORT irqMask;
+ UCHAR tag;
+ PPNP_IRQ_DESCRIPTOR biosDesc;
+ PUCHAR returnDesc;
+ NTSTATUS status;
+ ULONG increment;
+
+ if (!BiosRequirements) {
+ return STATUS_UNSUCCESSFUL;
+ }
+ status = STATUS_UNSUCCESSFUL;
+ if (!(CmDescriptor->u.Interrupt.Level & 0xfffffff0)) {
+ irqMask = 1 << CmDescriptor->u.Interrupt.Level;
+ tag = *BiosRequirements;
+ while (tag != TAG_COMPLETE_END) {
+ if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
+ biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->IrqMask & irqMask) {
+ *Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
+ returnDesc = ExAllocatePoolWithTag(PagedPool,
+ *Length,
+ 'bPnP' );
+ if (!returnDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(returnDesc, BiosRequirements, *Length);
+ *BiosDescriptor = returnDesc;
+ status = STATUS_SUCCESS;
+ }
+
+ break;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ return status;
+}
+
+NTSTATUS
+PbCmDmaToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM DMA information to Pnp BIOS format.
+ Since there is not enough information in the CM descriptor to
+ convert it to Pnp BIOS descriptor. We will search the Bios
+ possible resource lists for the corresponding resource information.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the bios possible resource lists.
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+Return Value:
+
+ return a pointer to the desired dma descriptor in the BiosRequirements. Null
+ if not found.
+
+--*/
+{
+ NTSTATUS status;
+ UCHAR dmaMask, tag;
+ PPNP_DMA_DESCRIPTOR biosDesc;
+ PUCHAR returnDesc;
+ ULONG increment;
+
+ if (!BiosRequirements) {
+ return STATUS_UNSUCCESSFUL;
+ }
+ status = STATUS_UNSUCCESSFUL;
+ if (!(CmDescriptor->u.Dma.Channel & 0xfffffff0)) {
+ dmaMask = 1 << CmDescriptor->u.Dma.Channel;
+ tag = *BiosRequirements;
+ while (tag != TAG_COMPLETE_END) {
+ if ((tag & SMALL_TAG_MASK) == TAG_DMA) {
+ biosDesc = (PPNP_DMA_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->ChannelMask & dmaMask) {
+ *Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
+ returnDesc = ExAllocatePoolWithTag(PagedPool,
+ *Length,
+ 'bPnP' );
+ if (!returnDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(returnDesc, BiosRequirements, *Length);
+ *BiosDescriptor = returnDesc;
+ status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ return status;
+}
+
+NTSTATUS
+PbCmPortToBiosDescriptor (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM PORT information to Pnp BIOS format.
+ Since there is not enough information in the CM descriptor to
+ convert it to Pnp BIOS full function port descriptor. We will
+ convert it to Pnp Bios fixed PORT descriptor. It is caller's
+ responsibility to release the returned data buffer.
+
+Arguments:
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+ BiosDescriptor - supplies a variable to receive the buffer which contains
+ the desired Bios Port descriptor.
+
+ Length - supplies a variable to receive the size the returned bios port
+ descriptor.
+
+Return Value:
+
+ A NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status;
+ PPNP_PORT_DESCRIPTOR portDesc;
+
+ if (CmDescriptor->u.Port.Start.HighPart != 0 ||
+ CmDescriptor->u.Port.Start.LowPart & 0xffff0000 ||
+ CmDescriptor->u.Port.Length & 0xffffff00) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ portDesc = (PPNP_PORT_DESCRIPTOR) ExAllocatePoolWithTag(
+ PagedPool, sizeof(PNP_PORT_DESCRIPTOR), 'bPnP' );
+ if (!portDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Set the return port descriptor
+ //
+
+ portDesc->Tag = TAG_IO | (sizeof(PNP_PORT_DESCRIPTOR) - 1);
+ portDesc->Information = 1; // 16 bit decoding
+ portDesc->Length = (UCHAR)CmDescriptor->u.Port.Length;
+ portDesc->Alignment = 0; // 1?
+ portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
+ portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
+ *BiosDescriptor = (PUCHAR)portDesc;
+ *Length = sizeof(PNP_PORT_DESCRIPTOR);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbCmMemoryToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM Memory information to Pnp BIOS format.
+ Since there is not enough information in the CM descriptor to
+ convert it to Pnp BIOS descriptor. We will search the Bios
+ possible resource lists for the corresponding resource information and
+ build a Pnp BIOS memory descriptor from there. It is caller's responsibility
+ to release the returned buffer.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the bios possible resource lists.
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+ BiosDescriptor - supplies a variable to receive the buffer which contains
+ the desired Bios Port descriptor.
+
+ Length - supplies a variable to receive the size the returned bios port
+ descriptor.
+
+Return Value:
+
+ A NTSTATUS code.
+
+--*/
+{
+ UCHAR tag, information;
+ PPNP_FIXED_MEMORY32_DESCRIPTOR memoryDesc;
+ ULONG address, size, length, minAddr, maxAddr, alignment;
+ USHORT increment;
+
+ //
+ // Search the possible resource list to get the information
+ // for the memory range described by CmDescriptor.
+ //
+
+ address = CmDescriptor->u.Memory.Start.LowPart;
+ size = CmDescriptor->u.Memory.Length;
+
+ tag = *BiosRequirements;
+ while (tag != TAG_COMPLETE_END) {
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
+ maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
+ + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
+ maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
+ + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
+ maxAddr = minAddr + length - 1;
+ alignment = 1;
+ break;
+ }
+
+ if (minAddr <= address && maxAddr >= (address + size - 1)) {
+ information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUSHORT)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ if (tag == TAG_COMPLETE_END) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Set up Pnp BIOS memory descriptor
+ //
+
+ memoryDesc = (PPNP_FIXED_MEMORY32_DESCRIPTOR) ExAllocatePoolWithTag(
+ PagedPool, sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR), 'bPnP' );
+ if (!memoryDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ memoryDesc->Tag = TAG_MEMORY32_FIXED;
+ memoryDesc->Length = sizeof (PNP_FIXED_MEMORY32_DESCRIPTOR);
+ memoryDesc->Information = information;
+ memoryDesc->BaseAddress = address;
+ memoryDesc->MemorySize = size;
+ *BiosDescriptor = (PUCHAR)memoryDesc;
+ *Length = sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR);
+ return STATUS_SUCCESS;
+ }
+}
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbios.h b/private/ntos/nthals/extender/pnpbios/i386/pbios.h
new file mode 100644
index 000000000..b400da35a
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbios.h
@@ -0,0 +1,241 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbiosp.h
+
+Abstract:
+
+ PnP BIOS/ISA configuration data definitions
+
+Author:
+
+ Shie-Lin Tzong (shielint) April 12, 1995
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+
+//
+// Constants
+//
+
+#define SMALL_RESOURCE_TAG (UCHAR)(0x00)
+#define LARGE_RESOURCE_TAG (UCHAR)(0x80)
+#define SMALL_TAG_MASK 0xf8
+#define SMALL_TAG_SIZE_MASK 7
+
+//
+// Small Resouce Tags with length bits stripped off
+//
+
+#define TAG_VERSION 0x08
+#define TAG_LOGICAL_ID 0x10
+#define TAG_COMPATIBLE_ID 0x18
+#define TAG_IRQ 0x20
+#define TAG_DMA 0x28
+#define TAG_START_DEPEND 0x30
+#define TAG_END_DEPEND 0x38
+#define TAG_IO 0x40
+#define TAG_IO_FIXED 0x48
+#define TAG_VENDOR 0x70
+#define TAG_END 0x78
+
+//
+// Large Resouce Tags
+//
+
+#define TAG_MEMORY 0x81
+#define TAG_ANSI_ID 0x82
+#define TAG_UNICODE_ID 0x83
+#define TAG_LVENDOR 0x84
+#define TAG_MEMORY32 0x85
+#define TAG_MEMORY32_FIXED 0x86
+
+//
+// Complete TAG if applicable.
+//
+
+#define TAG_COMPLETE_COMPATIBLE_ID 0x1C
+#define TAG_COMPLETE_END 0x79
+
+#include "pshpack1.h"
+
+//
+// PNP ISA Port descriptor definition
+//
+
+typedef struct _PNP_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01000111B, small item name = 08, length = 7
+ UCHAR Information; // bit [0] = 1 device decodes full 16 bit addr
+ // = 0 device decodes ISA addr bits[9-0]
+ USHORT MinimumAddress;
+ USHORT MaximumAddress;
+ UCHAR Alignment; // Increment in 1 byte blocks
+ UCHAR Length; // # contiguous Port requested
+} PNP_PORT_DESCRIPTOR, *PPNP_PORT_DESCRIPTOR;
+
+//
+// PNP ISA fixed Port descriptor definition
+//
+
+typedef struct _PNP_FIXED_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01001011B, small item name = 09, length = 3
+ USHORT MinimumAddress;
+ UCHAR Length; // # contiguous Port requested
+} PNP_FIXED_PORT_DESCRIPTOR, *PPNP_FIXED_PORT_DESCRIPTOR;
+
+//
+// PNP ISA IRQ descriptor definition
+//
+
+typedef struct _PNP_IRQ_DESCRIPTOR_ {
+ UCHAR Tag; // 0010001XB small item name = 4 length = 2/3
+ USHORT IrqMask; // bit 0 is irq 0
+ UCHAR Information; // Optional
+} PNP_IRQ_DESCRIPTOR, *PPNP_IRQ_DESCRIPTOR;
+
+//
+// Masks for PNP_IRQ_DESCRIPTOR Information byte
+//
+
+#define PNP_IRQ_LEVEL_MASK 0xC
+#define PNP_IRQ_EDGE_MASK 0x3
+
+//
+// PNP ISA DMA descriptor definition
+//
+
+typedef struct _PNP_DMA_DESCRIPTOR_ {
+ UCHAR Tag; // 00101010B, small item name = 05, length = 2
+ UCHAR ChannelMask; // bit 0 is channel 0
+ UCHAR Flags; // see spec
+} PNP_DMA_DESCRIPTOR, *PPNP_DMA_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY descriptor
+//
+
+typedef struct _PNP_MEMORY_DESCRIPTOR_ {
+ UCHAR Tag; // 10000001B, Large item name = 1
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ USHORT MinimumAddress; // address bit [8-23]
+ USHORT MaximumAddress; // address bit [8-23]
+ USHORT Alignment; // 0x0000 = 64KB
+ USHORT MemorySize; // In 256 byte blocks
+} PNP_MEMORY_DESCRIPTOR, *PPNP_MEMORY_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY32 descriptor
+//
+
+typedef struct _PNP_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000101B, Large item name = 5
+ USHORT Length; // Length of the descriptor = 17
+ UCHAR Information; // See def below
+ ULONG MinimumAddress; // 32 bit addr
+ ULONG MaximumAddress; // 32 bit addr
+ ULONG Alignment; // 32 bit alignment
+ ULONG MemorySize; // 32 bit length
+} PNP_MEMORY32_DESCRIPTOR, *PPNP_MEMORY32_DESCRIPTOR;
+
+//
+// PNP ISA FIXED MEMORY32 descriptor
+//
+
+typedef struct _PNP_FIXED_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000110B, Large item name = 6
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ ULONG BaseAddress; // 32 bit addr
+ ULONG MemorySize; // 32 bit length
+} PNP_FIXED_MEMORY32_DESCRIPTOR, *PPNP_FIXED_MEMORY32_DESCRIPTOR;
+
+#define PNP_MEMORY_ROM_MASK 0x40
+#define PNP_MEMORY_SHADOWABLE_MASK 0x20
+#define PNP_MEMORY_CONTROL_MASK 0x18
+ #define PNP_MEMORY_CONTROL_8BIT 00
+ #define PNP_MEMORY_CONTROL_16BIT 01
+ #define PNP_MEMORY_CONTROL_8AND16BIT 02
+ #define PNP_MEMORY_CONTROL_32BIT 03
+#define PNP_MEMORY_SUPPORT_TYPE_MASK 04
+#define PNP_MEMORY_CACHE_SUPPORT_MASK 02
+#define PNP_MEMORY_WRITE_STATUS_MASK 01
+
+#define UNKNOWN_DOCKING_IDENTIFIER 0xffffffff
+#define UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
+#define FUNCTION_NOT_SUPPORTED 0x82
+#define SYSTEM_NOT_DOCKED 0x87
+
+//
+// Pnp BIOS device node structure
+//
+
+typedef struct _PNP_BIOS_DEVICE_NODE {
+ USHORT Size;
+ UCHAR Node;
+ ULONG ProductId;
+ UCHAR DeviceType[3];
+ USHORT DeviceAttributes;
+ // followed by AllocatedResourceBlock, PossibleResourceBlock
+ // and CompatibleDeviceId
+} PNP_BIOS_DEVICE_NODE, *PPNP_BIOS_DEVICE_NODE;
+
+//
+// DeviceType definition
+//
+
+#define BASE_TYPE_DOCKING_STATION 0xA
+
+//
+// Device attributes definitions
+//
+
+#define DEVICE_DOCKING 0x20
+#define DEVICE_REMOVABLE 0x40
+
+//
+// Pnp BIOS Installation check
+//
+
+typedef struct _PNP_BIOS_INSTALLATION_CHECK {
+ UCHAR Signature[4]; // $PnP (ascii)
+ UCHAR Revision;
+ UCHAR Length;
+ USHORT ControlField;
+ UCHAR Checksum;
+ ULONG EventFlagAddress; // Physical address
+ USHORT RealModeEntryOffset;
+ USHORT RealModeEntrySegment;
+ USHORT ProtectedModeEntryOffset;
+ ULONG ProtectedModeCodeBaseAddress;
+ ULONG OemDeviceId;
+ USHORT RealModeDataBaseAddress;
+ ULONG ProtectedModeDataBaseAddress;
+} PNP_BIOS_INSTALLATION_CHECK, *PPNP_BIOS_INSTALLATION_CHECK;
+
+#include "poppack.h"
+
+//
+// Pnp BIOS ControlField masks
+//
+
+#define PNP_BIOS_CONTROL_MASK 0x3
+#define PNP_BIOS_EVENT_NOT_SUPPORTED 0
+#define PNP_BIOS_EVENT_POLLING 1
+#define PNP_BIOS_EVENT_ASYNC 2
+
+//
+// Pnp Bios event
+//
+
+#define ABOUT_TO_CHANGE_CONFIG 1
+#define DOCK_CHANGED 2
+#define SYSTEM_DEVICE_CHANGED 3
+#define CONFIG_CHANGE_FAILED 4
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm b/private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm
new file mode 100644
index 000000000..4d7857f14
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm
@@ -0,0 +1,89 @@
+ title "Pnp Bios Bus Extender ASM support routines"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; Biosa.asm
+;
+; Abstract:
+;
+; This file contains Pnp Bios Bus Extender ASM support routines.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) Apr 16, 1995
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+.xlist
+include callconv.inc ; calling convention macros
+.list
+
+ EXTRNP _RtlMoveMemory, 3
+ EXTRNP _KeI386Call16BitCStyleFunction, 4
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; PbCallPnpBiosWorker (
+; IN ULONG EntryOffset,
+; IN ULONG EntrySelector,
+; IN PUSHORT Parameters,
+; IN ULONG ParameterSize
+; );
+;
+; Routine Description:
+;
+; This routines copies the specified parameters to stack and invokes
+; Pnp Bios Entry point.
+;
+; Arguments:
+;
+; EntryOffset and EntrySelector - supplies the entry point of the bios function.
+;
+; Parameters - Supplies a pointer to argument block.
+;
+; ParameterSize - Size of the argument block
+;
+; Return Value:
+;
+; Registers/context contains the register values returned from pnp bios.
+;
+;--
+
+EntryOffset equ [ebp + 8]
+EntrySelector equ [ebp + 12]
+Parameters equ [ebp + 16]
+ParameterSize equ [ebp + 20]
+
+cPublicProc _PbCallPnpBiosWorker, 4
+
+ push ebp
+ mov ebp, esp
+ sub esp, ParameterSize
+ mov eax, esp
+
+ stdCall _RtlMoveMemory, <eax, Parameters, ParameterSize>
+
+ stdCall _KeI386Call16BitCStyleFunction, <EntryOffset, EntrySelector, Parameters, ParameterSize>
+
+ mov esp, ebp
+ pop ebp
+ stdRET _PbCallPnpBiosWorker
+
+stdENDP _PbCallPnpBiosWorker
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbiosc.c b/private/ntos/nthals/extender/pnpbios/i386/pbiosc.c
new file mode 100644
index 000000000..0afce8e4b
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbiosc.c
@@ -0,0 +1,773 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbiosc.c
+
+Abstract:
+
+ This module contains Pnp BIOS dependent routines. It includes code to initialize
+ 16 bit GDT selectors and to call pnp bios api.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 26-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzBIOSIdentifier[] = L"PNP BIOS";
+
+//
+// PbBiosKeyInformation points to the registry data information
+// which includes key value full information and data.
+//
+
+PVOID PbBiosKeyInformation;
+
+//
+// PbBiosRegistryData points to the pnp bios data
+//
+
+PPNP_BIOS_INSTALLATION_CHECK PbBiosRegistryData;
+
+//
+// PbBiosCodeSelector contains the selector of the PNP
+// BIOS code.
+//
+
+USHORT PbBiosCodeSelector;
+
+//
+// PbBiosDataSelector contains the selector of the PNP
+// BIOS data area (F0000-FFFFF)
+//
+
+USHORT PbBiosDataSelector;
+
+//
+// PbSelectors[] contains general purpose preallocated selectors
+//
+
+USHORT PbSelectors[2];
+
+//
+// PbBiosEventAddress contains the virtual address of the PNP
+// BIOS Event Flag.
+//
+
+PUCHAR PbBiosEventAddress;
+
+//
+// PbBiosEntryPoint contains the Pnp Bios entry offset
+//
+
+ULONG PbBiosEntryPoint;
+
+//
+// PbDockConnectorRegistered
+//
+
+BOOLEAN PbDockConnectorRegistered;
+
+//
+// SpinLock to serialize Pnp Bios call
+//
+
+KSPIN_LOCK PbBiosSpinlock;
+
+//
+// 16 bit protected mode event message address
+//
+
+USHORT PbEventMessageOffset;
+USHORT PbEventMessageSelector;
+USHORT PbBiosEventMessage;
+
+//
+// External References
+//
+
+extern
+USHORT
+PbCallPnpBiosWorker (
+ IN ULONG EntryOffset,
+ IN ULONG EntrySelector,
+ IN PUSHORT Parameters,
+ IN USHORT Size
+ );
+
+extern
+BOOLEAN
+RtlEqualUnicodeString(
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2,
+ IN BOOLEAN CaseInSensitive
+ );
+
+extern
+NTSTATUS
+KeI386AllocateGdtSelectors(
+ OUT PUSHORT SelectorArray,
+ IN USHORT NumberOfSelectors
+ );
+
+extern
+NTSTATUS
+KeI386SetGdtSelector (
+ IN ULONG Selector,
+ IN PKGDTENTRY GdtValue
+ );
+
+VOID
+PbTimerRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ );
+
+//
+// Internal prototypes
+//
+
+VOID
+PbAddress32ToAddress16 (
+ IN PVOID Address32,
+ IN PUSHORT Address16,
+ IN USHORT Selector
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PbInitialize)
+#pragma alloc_text(PAGE,PbAddress32ToAddress16)
+#endif
+
+NTSTATUS
+PbInitialize (
+ ULONG Phase,
+ PDEVICE_OBJECT DeviceObject
+ )
+
+/*++
+
+Routine Description:
+
+ At phase 0, this routine checks registry for the data collected by
+ ntdetect.com to make sure PnP Bios is present and initializes the
+ internal data structures for pnp bios bus extender.
+
+ Phase 0 init is called only once at DriverEntry. Phase 1 is called
+ whenever a new bus is registered. If phase 1 is called for bus number
+ 1 (i.e. docking station bus), a timer will be start to poll Pnp Bios
+ event if necessary.
+
+ Note, only Bus 0 (mother board devices) and bus 1 (docking station devices)
+ are supported.
+
+Arguments:
+
+ Phase - supplies a number to indicate the phase of the initialization.
+
+ DeviceObject - a pointer to the bus extender device object. At phase 0,
+ it is NULL.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+{
+ KGDTENTRY gdtEntry;
+ UNICODE_STRING unicodeString, unicodeValueName, biosId;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ WCHAR wbuffer[10];
+ ULONG codeBase, i, length;
+ PWSTR p;
+ PKEY_VALUE_FULL_INFORMATION valueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+ NTSTATUS status;
+ BOOLEAN same;
+ USHORT selectors[4];
+ PHYSICAL_ADDRESS physicalAddr;
+ PVOID virtualAddr;
+ PB_PARAMETERS biosParameters;
+ USHORT pnpControl;
+
+ if (Phase == 1) {
+ if (((PMB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->BusHandler->BusNumber ==
+ MbpBusNumber[0]) {
+ if (PbBiosEventAddress) {
+
+ //
+ // First disable pnp bios default event timeout
+ //
+
+ biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
+ biosParameters.u.SendMessage.Message = PNP_OS_ACTIVE;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpBios: Disable Event timeout failed\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Create timer to poll for PNP BIOS events.
+ //
+
+ IoInitializeTimer (DeviceObject, PbTimerRoutine, NULL);
+ IoStartTimer (DeviceObject);
+ }
+ }
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Look in the registery for the "PNP BIOS bus" data
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpBIos:Can not open MultifunctionAdapter registry key.\n"));
+ return status;
+ }
+
+ unicodeString.Buffer = wbuffer;
+ unicodeString.MaximumLength = sizeof(wbuffer);
+ RtlInitUnicodeString(&biosId, rgzBIOSIdentifier);
+
+ for (i = 0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ DebugPrint((DEBUG_MESSAGE, "PnpBIos: Pnp BIOS MultifunctionAdapter registry key not found.\n"));
+ ZwClose (hMFunc);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Check the Indentifier to see if this is a Pnp BIOS entry
+ //
+
+ status = PbGetRegistryValue (hBus, rgzIdentifier, &valueInfo);
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) valueInfo + valueInfo->DataOffset);
+ unicodeValueName.Buffer = p;
+ unicodeValueName.MaximumLength = (USHORT)valueInfo->DataLength;
+ length = valueInfo->DataLength;
+
+ //
+ // Determine the real length of the ID string
+ //
+
+ while (length) {
+ if (p[length / sizeof(WCHAR) - 1] == UNICODE_NULL) {
+ length -= 2;
+ } else {
+ break;
+ }
+ }
+ unicodeValueName.Length = (USHORT)length;
+ same = RtlEqualUnicodeString(&biosId, &unicodeValueName, TRUE);
+ ExFreePool(valueInfo);
+ if (!same) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ status = PbGetRegistryValue(hBus, rgzConfigurationData, &valueInfo);
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ valueInfo + valueInfo->DataOffset);
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ desc->PartialResourceList.PartialDescriptors);
+
+ if (partialDesc->Type == CmResourceTypeDeviceSpecific) {
+
+ //
+ // got it.. Perform sanity check
+ //
+
+ PbBiosRegistryData = (PPNP_BIOS_INSTALLATION_CHECK) (partialDesc+1);
+ if (PbBiosRegistryData->Signature[0] == '$'&&
+ PbBiosRegistryData->Signature[1] == 'P'&&
+ PbBiosRegistryData->Signature[2] == 'n'&&
+ PbBiosRegistryData->Signature[3] == 'P') {
+ PbBiosKeyInformation = (PVOID)valueInfo;
+ ZwClose (hMFunc);
+ break;
+ }
+ }
+ ExFreePool(valueInfo);
+ }
+
+ //
+ // We find the Pnp BIOS data stored by ntdetect.com. Initialize Pnp BIOS
+ // get/set event if supported.
+ //
+
+ pnpControl = PbBiosRegistryData->ControlField & PNP_BIOS_CONTROL_MASK;
+ if ((pnpControl & PNP_BIOS_CONTROL_MASK) != PNP_BIOS_EVENT_NOT_SUPPORTED) {
+ if ((pnpControl & PNP_BIOS_CONTROL_MASK) == PNP_BIOS_EVENT_POLLING) {
+
+ //
+ // Pnp BIOS event notification is supported thru polling. We need
+ // to map event address to non paged pool virtual address.
+ //
+
+ physicalAddr.LowPart = PbBiosRegistryData->EventFlagAddress;
+ physicalAddr.HighPart = 0;
+ virtualAddr = MmMapIoSpace (physicalAddr, 1, FALSE);
+ PbBiosEventAddress = (PUCHAR)virtualAddr;
+ } else if ((pnpControl & PNP_BIOS_CONTROL_MASK) == PNP_BIOS_EVENT_ASYNC) {
+
+ //
+ // Add code here
+ //
+ }
+
+ //
+ // Create eject callback object to notify dock/undock events
+ //
+
+ RtlInitUnicodeString(&unicodeString, L"\\Callback\\PnpBiosEvent");
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ status = ExCreateCallback (&MbpEjectCallbackObject, &objectAttributes, TRUE, TRUE);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ }
+
+ //
+ // Allocate 4 or 5 selectors for calling PnP Bios Apis.
+ // If event notification is supported thru polling, we set up an selector for the event
+ // addr (16 bit.). Because the GET EVENT call is made from DPC level and we can not
+ // call kernel routine to set selector at DPC level.
+ //
+
+ if (PbBiosEventAddress) {
+ i = 5;
+ } else {
+ i = 4;
+ }
+ status = KeI386AllocateGdtSelectors (selectors, (USHORT) i);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpBios: Failed to allocate selectors\n"));
+ ExFreePool(valueInfo);
+ return status;
+ }
+
+ PbBiosCodeSelector = selectors[0];
+ PbBiosDataSelector = selectors[1];
+ PbSelectors[0] = selectors[2];
+ PbSelectors[1] = selectors[3];
+
+ PbBiosEntryPoint = (ULONG)PbBiosRegistryData->ProtectedModeEntryOffset;
+
+ //
+ // Initialize selectors to use PNP bios code
+ //
+
+ //
+ // initialize 16 bit code selector
+ //
+
+ gdtEntry.LimitLow = 0xFFFF;
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 31;
+ gdtEntry.HighWord.Bits.Default_Big = 0;
+ physicalAddr.LowPart = PbBiosRegistryData->ProtectedModeCodeBaseAddress;
+ virtualAddr = MmMapIoSpace (physicalAddr, 0x10000, TRUE);
+ codeBase = (ULONG)virtualAddr;
+ gdtEntry.BaseLow = (USHORT) (codeBase & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (codeBase >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (codeBase >> 24) & 0xff;
+ KeI386SetGdtSelector (PbBiosCodeSelector, &gdtEntry);
+
+ //
+ // initialize 16 bit data selector for Pnp BIOS
+ //
+
+ gdtEntry.LimitLow = 0xFFFF;
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 19;
+ gdtEntry.HighWord.Bits.Default_Big = 1;
+ physicalAddr.LowPart = PbBiosRegistryData->ProtectedModeDataBaseAddress;
+ virtualAddr = MmMapIoSpace (physicalAddr, 0x10000, TRUE);
+ codeBase = (ULONG)virtualAddr;
+ gdtEntry.BaseLow = (USHORT) (codeBase & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (codeBase >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (codeBase >> 24) & 0xff;
+ KeI386SetGdtSelector (PbBiosDataSelector, &gdtEntry);
+
+ //
+ // initialize selecot part of message address for calling BIOS
+ //
+
+ if (PbBiosEventAddress) {
+ PbEventMessageSelector = selectors[4];
+ PbEventMessageOffset = 0;
+
+ gdtEntry.LimitLow = 0x3; // 1?
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 19;
+ gdtEntry.HighWord.Bits.Default_Big = 1;
+ codeBase = (ULONG)&PbBiosEventMessage;
+ gdtEntry.BaseLow = (USHORT) (codeBase & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (codeBase >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (codeBase >> 24) & 0xff;
+ KeI386SetGdtSelector (PbEventMessageSelector, &gdtEntry);
+ }
+
+
+ //
+ // Initialize the other two general purpose data selector such that
+ // on subsequent init we only need to init the base addr.
+ //
+
+ KeI386SetGdtSelector (PbSelectors[0], &gdtEntry);
+ KeI386SetGdtSelector (PbSelectors[1], &gdtEntry);
+
+ //
+ // Initialize BIOS call spinlock
+ //
+
+ KeInitializeSpinLock (&PbBiosSpinlock);
+
+ //
+ // Get maximum pnp bios slot data size
+ //
+
+ biosParameters.Function = PNP_BIOS_GET_NUMBER_DEVICE_NODES;
+ biosParameters.u.GetNumberDeviceNodes.NumberNodes = (PUSHORT)&i;
+ biosParameters.u.GetNumberDeviceNodes.NodeSize = (PUSHORT) &MbpMaxDeviceData;
+ status = PbHardwareService(&biosParameters);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbHardwareService (
+ IN PPB_PARAMETERS Parameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up stack parameters and calls an
+ assembly worker routine to actually invoke the PNP BIOS code.
+
+Arguments:
+
+ Parameters - supplies a pointer to the parameter block.
+
+Return Value:
+
+ An NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ USHORT stackParameters[PB_MAXIMUM_STACK_SIZE / 2];
+ ULONG i = 0;
+ USHORT retCode;
+ KIRQL oldIrql;
+
+ //
+ // Convert and copy the caller's parameters to the format that
+ // will be used to invoked pnp bios.
+ //
+
+ stackParameters[i] = Parameters->Function;
+ i++;
+
+ switch (Parameters->Function) {
+ case PNP_BIOS_GET_NUMBER_DEVICE_NODES:
+ PbAddress32ToAddress16(Parameters->u.GetNumberDeviceNodes.NumberNodes,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ PbAddress32ToAddress16(Parameters->u.GetNumberDeviceNodes.NodeSize,
+ &stackParameters[i],
+ PbSelectors[1]);
+ i += 2;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_GET_DEVICE_NODE:
+ PbAddress32ToAddress16(Parameters->u.GetDeviceNode.Node,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ PbAddress32ToAddress16(Parameters->u.GetDeviceNode.NodeBuffer,
+ &stackParameters[i],
+ PbSelectors[1]);
+ i += 2;
+ stackParameters[i++] = Parameters->u.GetDeviceNode.Control;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_SET_DEVICE_NODE:
+ stackParameters[i++] = Parameters->u.SetDeviceNode.Node;
+ PbAddress32ToAddress16(Parameters->u.SetDeviceNode.NodeBuffer,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ stackParameters[i++] = Parameters->u.SetDeviceNode.Control;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_GET_EVENT:
+ stackParameters[i++] = PbEventMessageOffset;
+ stackParameters[i++] = PbEventMessageSelector;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_SEND_MESSAGE:
+ stackParameters[i++] = Parameters->u.SendMessage.Message;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_GET_DOCK_INFORMATION:
+ PbAddress32ToAddress16(Parameters->u.GetDockInfo.DockingStationInfo,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ default:
+ return STATUS_NOT_IMPLEMENTED;
+
+ }
+
+ //
+ // Copy the parameters to stack and invoke Pnp Bios.
+ //
+
+ KeAcquireSpinLock (&PbBiosSpinlock, &oldIrql);
+
+ retCode = PbCallPnpBiosWorker (
+ PbBiosEntryPoint,
+ PbBiosCodeSelector,
+ stackParameters,
+ (USHORT)(i * sizeof(USHORT)));
+
+ KeReleaseSpinLock (&PbBiosSpinlock, oldIrql);
+
+ //
+ // Special handling for Get Docking station information. We need to
+ // return the docking state (i.e. the returned code.)
+ //
+
+ if (Parameters->Function == PNP_BIOS_GET_DOCK_INFORMATION) {
+ *(Parameters->u.GetDockInfo.DockState) = 0;
+ if (retCode == SYSTEM_NOT_DOCKED) {
+ *(Parameters->u.GetDockInfo.DockState) = retCode;
+ retCode = 0;
+ } else if (retCode == UNABLE_TO_DETERMINE_DOCK_CAPABILITIES) {
+ Parameters->u.GetDockInfo.DockingStationInfo->Capabilities = (USHORT) -1;
+ retCode = 0;
+ }
+ }
+
+ //
+ // Map Bios returned code to nt status code.
+ //
+
+ if (retCode == 0) {
+ return STATUS_SUCCESS;
+ } else {
+ DebugPrint((DEBUG_BREAK, "PnpBios: Bios API call failed.\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+}
+
+VOID
+PbAddress32ToAddress16 (
+ IN PVOID Address32,
+ IN PUSHORT Address16,
+ IN USHORT Selector
+ )
+
+/*++
+
+Routine Description:
+
+ This routine converts the 32 bit address to 16 bit selector:offset address
+ and stored in user specified location.
+
+Arguments:
+
+ Address32 - the 32 bit address to be converted.
+
+ Address16 - supplies the location to receive the 16 bit sel:offset address
+
+ Selector - the 16 bit selector for seg:offset address
+
+Return Value:
+
+ None.
+
+--*/
+{
+ KGDTENTRY gdtEntry;
+ ULONG baseAddr;
+
+ //
+ // Map virtual address to selector:0 address
+ //
+
+ gdtEntry.LimitLow = 0xFFFF;
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 19;
+ gdtEntry.HighWord.Bits.Default_Big = 1;
+ baseAddr = (ULONG)Address32;
+ gdtEntry.BaseLow = (USHORT) (baseAddr & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (baseAddr >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (baseAddr >> 24) & 0xff;
+ KeI386SetGdtSelector (Selector, &gdtEntry);
+ *Address16 = 0;
+ *(Address16 + 1) = Selector;
+}
+
+VOID
+PbTimerRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ )
+{
+ PB_PARAMETERS biosParameters;
+ NTSTATUS status;
+ USHORT junk;
+
+ //
+ // Check for Pnp BIOS event
+ //
+
+ if (*PbBiosEventAddress & 1) {
+
+ //
+ // Get Pnp BIOS event.
+ //
+
+ biosParameters.Function = PNP_BIOS_GET_EVENT;
+ biosParameters.u.GetEvent.Message = &PbBiosEventMessage;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Process the event ...
+ //
+
+ switch (PbBiosEventMessage) {
+ case ABOUT_TO_CHANGE_CONFIG:
+ DebugPrint((DEBUG_MESSAGE, "PnpBios:Configuration about to change ...\n"));
+ if (MbpConfigAboutToChange()) {
+ biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
+ biosParameters.u.SendMessage.Message = OK_TO_CHANGE_CONFIG;
+ PbHardwareService(&biosParameters);
+ }
+ break;
+
+ case DOCK_CHANGED:
+ case SYSTEM_DEVICE_CHANGED:
+
+ //
+ // For dock, undock and system device changes, we invalidate cached
+ // pnp bios data and notify enumerator to reenumerate the devices.
+ //
+
+ DebugPrint((DEBUG_MESSAGE, "PnpBios:Configuration changed\n"));
+ if (PbBiosKeyInformation) {
+ PbBiosKeyInformation = NULL;
+ PbBiosRegistryData = NULL;
+ ExFreePool(PbBiosKeyInformation);
+ }
+
+ //
+ // Invalidate maximum slot data information after configuration changed.
+ //
+
+ MbpMaxDeviceData = 0;
+
+ MbpConfigChanged();
+ break;
+
+ case CONFIG_CHANGE_FAILED:
+
+ //
+ // do nothing.
+ // BUGBUG - We should define someway to notify the dock/undock
+ // failed. So, user can be notified.
+ //
+
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/private/ntos/nthals/extender/pnpbios/i386/resource.c b/private/ntos/nthals/extender/pnpbios/i386/resource.c
new file mode 100644
index 000000000..daad0c72c
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/resource.c
@@ -0,0 +1,367 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ This module contains the high level device resources support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-25-1995
+ Adapted from Pci bus extender.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+#pragma alloc_text(PAGE,MbCtlQueryDeviceId)
+#pragma alloc_text(PAGE,MbCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,MbCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,MbCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,MbCtlSetDeviceResources)
+
+VOID
+MbCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the unique id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWCHAR deviceId;
+ ULONG idNumber;
+ PMB_BUS_EXTENSION busExtension;
+
+ PAGED_CODE();
+
+ //
+ // Set up device's unique id.
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+
+ //
+ // If the device is a docking station, we return its docking station
+ // serial number. Else its device id/slot number is returned as the
+ // unique id.
+ //
+
+ if (DeviceData->Flags & DEVICE_FLAGS_DOCKING_STATION) {
+ busExtension = (PMB_BUS_EXTENSION)Context->Handler->BusData;
+ idNumber = busExtension->DockingStationSerialNumber;
+ } else {
+ idNumber = DeviceDataSlot(DeviceData);
+ }
+ swprintf (deviceId, L"%04x", idNumber);
+
+#if DBG
+ {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, (PWCHAR)Context->DeviceControl.Buffer);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x Unique Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceDataSlot(DeviceData),
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ MbpCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+ PWCHAR deviceId;
+ ULONG idIndex;
+
+ PAGED_CODE();
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ idIndex = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // Call worker routine to get the desired Id.
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ status = MbpGetCompatibleDeviceId(DeviceData->BusData,
+ idIndex,
+ (PWCHAR) deviceId);
+
+#if DBG
+ if (NT_SUCCESS(status)) {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, deviceId);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x IdIndex %x Compatible Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceDataSlot(DeviceData),
+ idIndex,
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCES DeviceControl
+ which returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceData - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length;
+ PCM_RESOURCE_LIST cmResources;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ status = MbpGetSlotResources(Context->RootHandler->BusNumber,
+ DeviceData->BusData,
+ &cmResources,
+ &length);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ cmResources = (PCM_RESOURCE_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(CM_RESOURCE_LIST), 'bPnP');
+ if (!cmResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ cmResources->Count = 0;
+ cmResources->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ cmResources->List[0].BusNumber = Context->RootHandler->BusNumber;
+ cmResources->List[0].PartialResourceList.Version = 0;
+ cmResources->List[0].PartialResourceList.Revision = 0;
+ cmResources->List[0].PartialResourceList.Count = 0;
+ length = sizeof(CM_RESOURCE_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, cmResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if DBG
+ if (NT_SUCCESS(status)) {
+ MbpDumpCmResourceList(cmResources, DeviceDataSlot(DeviceData));
+ }
+#endif
+ ExFreePool(cmResources);
+ }
+exitLocal:
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCE_REQUIREMENTS DeviceControl
+ which returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ status = MbpGetSlotResourceRequirements(Context->RootHandler->BusNumber,
+ DeviceData->BusData,
+ &ioResources,
+ &length);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST), 'bPnP');
+ if (!ioResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ ioResources->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResources->InterfaceType = Context->RootHandler->InterfaceType;
+ ioResources->BusNumber = Context->RootHandler->BusNumber;
+ ioResources->SlotNumber = DeviceDataSlot(DeviceData);
+ ioResources->Reserved[0] = 0;
+ ioResources->Reserved[1] = 0;
+ ioResources->Reserved[2] = 0;
+ ioResources->AlternativeLists = 0;
+ ioResources->List[0].Version = 1;
+ ioResources->List[0].Revision = 1;
+ ioResources->List[0].Count = 0;
+ length = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ioResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if DBG
+ if (NT_SUCCESS(status)) {
+ MbpDumpIoResourceList(ioResources);
+ }
+#endif
+ ExFreePool(ioResources);
+ }
+exitLocal:
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlSetDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the SET_DEVICE_RESOURCES DeviceControl
+ which configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceData - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ status = MbpSetSlotResources (
+ &DeviceData->BusData,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer,
+ *Context->DeviceControl.BufferLength
+ );
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
diff --git a/private/ntos/nthals/extender/pnpbios/makefile b/private/ntos/nthals/extender/pnpbios/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/extender/pnpbios/pnpbios.rc b/private/ntos/nthals/extender/pnpbios/pnpbios.rc
new file mode 100644
index 000000000..5a305dd63
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/pnpbios.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "PNP BIOS Extension Driver"
+#define VER_INTERNALNAME_STR "pnpbios.sys"
+#define VER_ORIGINALFILENAME_STR "pnpbios.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pnpbios/sources b/private/ntos/nthals/extender/pnpbios/sources
new file mode 100644
index 000000000..85413d9ed
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=extender
+
+TARGETNAME=pnpbios
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=
+
+i386_SOURCES=pnpbios.rc \
+ i386\bus.c \
+ i386\data.c \
+ i386\init.c \
+ i386\control.c \
+ i386\resource.c \
+ i386\busdata.c \
+ i386\pbcnvrt.c \
+ i386\pbiosa.asm \
+ i386\pbiosc.c \
+ i386\misc.c
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=
diff --git a/private/ntos/nthals/extender/pnpisa.sur/bus.c b/private/ntos/nthals/extender/pnpisa.sur/bus.c
new file mode 100644
index 000000000..24955bbf3
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/bus.c
@@ -0,0 +1,962 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ bus.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+
+//
+// Internal references
+//
+
+BOOLEAN
+PipIsDeviceInstanceInstalled(
+ IN HANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PipCheckBus)
+#pragma alloc_text(INIT,PipCheckDevices)
+#pragma alloc_text(INIT,PipDeleteCards)
+#pragma alloc_text(INIT,PipIsDeviceInstanceInstalled)
+#endif
+
+
+VOID
+PipCheckBus (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+
+/*++
+
+Routine Description:
+
+ The function enumerates the bus specified by BusExtension
+
+Arguments:
+
+ BusExtension - supplies a pointer to the BusExtension structure of the bus
+ to be enumerated.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status;
+ ULONG objectSize, noDevices;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ PUCHAR cardData;
+ ULONG dataLength;
+ USHORT csn, i, detectedCsn = 0;
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ UCHAR tmp;
+ PSINGLE_LIST_ENTRY link;
+
+ //
+ // Perform Pnp isolation process. This will assign card select number for each
+ // Pnp Isa card isolated by the system. All the isolated cards will be put into
+ // wait-for-key state.
+ //
+
+ PipIsolateCards(&BusExtension->NumberCSNs);
+
+ //
+ // send initiation key to put cards into sleep state
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // For each card selected build CardInformation and DeviceInformation structures.
+ //
+
+ for (csn = 1; csn <= BusExtension->NumberCSNs; csn++) {
+
+ status = PipReadCardResourceData (
+ csn,
+ &noDevices,
+ &cardData,
+ &dataLength);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ }
+
+ detectedCsn++;
+
+ //
+ // Allocate and initialize card information and its associate device
+ // information structures.
+ //
+
+ cardInfo = (PCARD_INFORMATION)ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(CARD_INFORMATION),
+ 'iPnP');
+ if (!cardInfo) {
+ ExFreePool(cardData);
+ DebugPrint((DEBUG_MESSAGE, "PnpIsaCheckBus: failed to allocate CARD_INFO structure\n"));
+ continue;
+ }
+
+ //
+ // Initialize card information structure
+ //
+
+ RtlZeroMemory(cardInfo, sizeof(CARD_INFORMATION));
+ cardInfo->CardSelectNumber = csn;
+ cardInfo->NumberLogicalDevices = noDevices;
+ cardInfo->CardData = cardData;
+ cardInfo->CardDataLength = dataLength;
+
+ PushEntryList (&BusExtension->CardList,
+ &cardInfo->CardList
+ );
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsaCheckBus: adding one pnp card %x\n"));
+
+ //
+ // For each logical device supported by the card build its DEVICE_INFORMATION
+ // structures.
+ //
+
+ cardData += sizeof(SERIAL_IDENTIFIER);
+ dataLength -= sizeof(SERIAL_IDENTIFIER);
+ PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+ for (i = 0; i < noDevices; i++) { // logical device number starts from 0
+
+ //
+ // Create and initialize device tracking structure (Device_Information.)
+ //
+
+ deviceInfo = (PDEVICE_INFORMATION) ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(DEVICE_INFORMATION),
+ 'iPnP');
+ if (!deviceInfo) {
+ DebugPrint((DEBUG_MESSAGE, "PnpIsa:failed to allocate DEVICEINFO structure\n"));
+ continue;
+ }
+
+ deviceInfo->CardInformation = cardInfo;
+ deviceInfo->LogicalDeviceNumber = i;
+ deviceInfo->DeviceData = cardData;
+ deviceInfo->DeviceDataLength = PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+
+ //
+ // Add it to the logical device list of the pnp isa card.
+ //
+
+ PushEntryList (&cardInfo->LogicalDeviceList,
+ &deviceInfo->LogicalDeviceList
+ );
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ BusExtension->NoValidSlots += 1;
+ PushEntryList (&BusExtension->DeviceList,
+ &deviceInfo->DeviceList
+ );
+
+ //
+ // Select the logical device, disable its io range check
+ // (Card is not enabled yet.)
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(i);
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+ BusExtension->NumberCSNs = detectedCsn;
+}
+
+VOID
+PipCheckDevices (
+ PUNICODE_STRING RegistryPath,
+ PPI_BUS_EXTENSION BusExtension
+ )
+
+/*++
+
+Routine Description:
+
+ The function goes through every pnp device and check if it is *installed*,
+ if yes, the device will be enabled. Otherwise, we create a device instance
+ key for the device and leave the device disabled.
+
+Arguments:
+
+ RegistryPath - Supplies a pointer to the registry path passed to the driver
+ entry.
+
+ BusExtension - supplies a pointer to the pnp isa bus extension structure.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status;
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_INFORMATION deviceInfo;
+ PSINGLE_LIST_ENTRY cardLink, deviceLink;
+ PWCHAR cardId, deviceId, uniqueId, compatibleId, ids;
+ WCHAR buffer[128];
+ ULONG disposition, tmpValue, length, cardIdLength;
+ UNICODE_STRING unicodeDeviceId, unicodeUniqueId, unicodeBusId;
+ UNICODE_STRING unicodeDeviceInstance, unicodeString;
+ HANDLE handle, busIdHandle, deviceIdHandle, uniqueIdHandle, logConfHandle;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ PCM_RESOURCE_LIST cmResource;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ UNICODE_STRING madeupInstancePath;
+ HANDLE madeupKeyHandle;
+
+ //
+ // If there is no PnpISA card, we are done.
+ // Oterwise, open HKLM\System\CCS\ENUM\PNPISA.
+ //
+
+ if (BusExtension->NumberCSNs == 0) {
+ return;
+ }
+
+ RtlInitUnicodeString(
+ &unicodeString,
+ L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ FALSE
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open HKLM\\SYSTEM\\CCS\\ENUM"));
+ return;
+ }
+
+ //
+ // Open/Create PNPISA key under HKLM\CCS\System\Enum
+ //
+
+ RtlInitUnicodeString(&unicodeBusId, L"ISAPNP");
+ status = PipOpenRegistryKeyPersist(&busIdHandle,
+ handle,
+ &unicodeBusId,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &disposition
+ );
+ ZwClose(handle);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open ENUM\\PNPISA"));
+ return;
+ }
+
+ //
+ // Since this driver always return failure, Pnp manager will clean up the
+ // madeup key for this driver. If we detect any pnp isa card and create
+ // IsaPnP key. We need to keep the madeup key by deleting its *NewlyCreated*
+ // value entry.
+ //
+
+ status = PipServiceInstanceToDeviceInstance (
+ RegistryPath,
+ 0,
+ &madeupInstancePath,
+ &madeupKeyHandle,
+ KEY_ALL_ACCESS
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open madeup key"));
+ return;
+ }
+ RtlInitUnicodeString(&unicodeString, L"Control");
+ status = PipOpenRegistryKey(&handle,
+ madeupKeyHandle,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ FALSE
+ );
+ if (NT_SUCCESS(status)) {
+ RtlInitUnicodeString(&unicodeString, L"*NewlyCreated*");
+ ZwDeleteValueKey(handle, &unicodeString);
+ ZwClose(handle);
+ }
+
+ //
+ // Go through the card link list to process each of its logical device.
+ //
+
+ for (cardLink = BusExtension->CardList.Next; cardLink; cardLink = cardLink->Next) {
+ cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
+
+ PipGetCardIdentifier((PUCHAR)cardInfo->CardData + NUMBER_CARD_ID_BYTES,
+ &cardId,
+ &cardIdLength);
+
+ //
+ // For each logical device of the card, check if device instance key installed
+ // if yes, we will configure the resource and turn on the device. Otherwise
+ // we create a device instance key and store possible configuration and leave
+ // the device disabled.
+ //
+
+ for (deviceLink = cardInfo->LogicalDeviceList.Next; deviceLink; deviceLink = deviceLink->Next) {
+ deviceInfo = CONTAINING_RECORD (deviceLink,
+ DEVICE_INFORMATION,
+ LogicalDeviceList);
+
+ //
+ // First, get the device id this will be the device key name
+ //
+
+ status = PipQueryDeviceId(deviceInfo, &deviceId, 0);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ } else {
+
+ //
+ // Open/create this registry path under HKLM\CCS\System\Enum\PnPIsa
+ //
+
+ RtlInitUnicodeString(
+ &unicodeDeviceId,
+ deviceId + (unicodeBusId.Length / sizeof(WCHAR)) + 1 );
+ status = PipOpenRegistryKeyPersist(&deviceIdHandle,
+ busIdHandle,
+ &unicodeDeviceId,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &disposition
+ );
+ if (!NT_SUCCESS(status)) {
+ ExFreePool(deviceId);
+ continue;
+ }
+
+ //
+ // Query the unique id for the device
+ //
+
+ status = PipQueryDeviceUniqueId(deviceInfo, &uniqueId);
+ if (!NT_SUCCESS(status)) {
+ ZwClose(deviceIdHandle);
+ ExFreePool(deviceId);
+ continue;
+ }
+
+ //
+ // Open/create this registry device instance path under
+ // HKLM\System\Enum\IsaPnp\deviceId
+ //
+
+ RtlInitUnicodeString(&unicodeUniqueId, uniqueId);
+ status = PipOpenRegistryKeyPersist(&uniqueIdHandle,
+ deviceIdHandle,
+ &unicodeUniqueId,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &disposition
+ );
+ ZwClose(deviceIdHandle);
+ if (!NT_SUCCESS(status)) {
+ ExFreePool(deviceId);
+ ExFreePool(uniqueId);
+ continue;
+ }
+
+ RtlInitUnicodeString(&unicodeString, L"FoundAtEnum");
+ tmpValue = 1;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"LogConf");
+ status = PipOpenRegistryKeyPersist(&logConfHandle,
+ uniqueIdHandle,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &tmpValue
+ );
+ if (!NT_SUCCESS(status)) {
+ logConfHandle = NULL; // just to make sure
+ }
+
+ swprintf(buffer, L"%s\\%s", deviceId, uniqueId);
+ RtlInitUnicodeString(&unicodeDeviceInstance, buffer);
+
+ if (disposition == REG_CREATED_NEW_KEY) {
+
+ //
+ // Create all the default value entry for the newly created key.
+ // DeviceDesc = Card Identifier string
+ // BaseDevicePath = PNPISA a default parent
+ // Configuration = REG_RESOURCE_LIST
+ // ConfigurationVector = REG_RESOUCE_REQUIREMENTS_LIST
+ // HardwareID = MULTI_SZ
+ // CompatibleIDs = MULTI_SZ
+ // ConfigFlags = REG_DWORD CONFIGFLAG_REINSTALL
+ // Status = REG_DWORD DN_HAS_PROBLEM
+ // Problem = REG_DWORD CM_PROB_REINSTALL
+ // Create "Control" volatile subkey.
+ //
+
+ RtlInitUnicodeString(&unicodeString, L"Control");
+ PipOpenRegistryKey(&handle,
+ uniqueIdHandle,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ ZwClose(handle);
+ }
+
+ if (cardId) {
+ RtlInitUnicodeString(&unicodeString, L"DeviceDesc");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_SZ,
+ cardId,
+ cardIdLength
+ );
+ }
+
+ RtlInitUnicodeString(&unicodeString, L"BaseDevicePath");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_SZ,
+ madeupInstancePath.Buffer,
+ madeupInstancePath.Length + sizeof(UNICODE_NULL)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"ConfigFlags");
+ tmpValue = CONFIGFLAG_REINSTALL;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"Problem");
+ tmpValue = CM_PROB_REINSTALL;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"StatusFlags");
+ tmpValue = DN_HAS_PROBLEM;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ if (logConfHandle) {
+ status = PipQueryDeviceResources (
+ deviceInfo,
+ 0, // BusNumber
+ &cmResource,
+ &length
+ );
+
+ if (NT_SUCCESS(status) && cmResource) {
+ RtlInitUnicodeString(&unicodeString, L"BootConfig");
+ ZwSetValueKey(
+ logConfHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_RESOURCE_LIST,
+ cmResource,
+ length
+ );
+ ExFreePool(cmResource);
+ }
+
+ status = PipQueryDeviceResourceRequirements (
+ deviceInfo,
+ 0, // Bus Number
+ 0, // Slot number??
+ &ioResource,
+ &length
+ );
+ if (NT_SUCCESS(status) && ioResource) {
+ RtlInitUnicodeString(&unicodeString, L"BasicConfigVector");
+ ZwSetValueKey(logConfHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_RESOURCE_REQUIREMENTS_LIST,
+ ioResource,
+ length
+ );
+ ExFreePool(ioResource);
+ }
+ }
+
+ status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, 0, &compatibleId);
+ if (NT_SUCCESS(status) && compatibleId) {
+
+ //
+ // create HardwareId value name. Even though it is a MULTI_SZ,
+ // we know there is only one HardwareId for PnpIsa.
+ //
+
+ length = wcslen(compatibleId) * sizeof(WCHAR) + 2 * sizeof(WCHAR);
+ ids = (PWCHAR)ExAllocatePool(PagedPool, length);
+ if (ids) {
+ RtlMoveMemory(ids, compatibleId, length - 2 *sizeof(WCHAR));
+ ids[length / sizeof(WCHAR) - 1] = UNICODE_NULL;
+ ids[length / sizeof(WCHAR) - 2] = UNICODE_NULL;
+ RtlInitUnicodeString(&unicodeString, L"HardwareID");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ ids,
+ length
+ );
+ ExFreePool(ids);
+ }
+ ExFreePool(compatibleId);
+ }
+
+ ids = (PWCHAR)ExAllocatePool(PagedPool, 0x1000);
+ if (ids) {
+ PWCHAR p1;
+ ULONG i;
+
+ p1 = ids;
+ length = 0;
+ for (i = 1; TRUE; i++) {
+ status = PipGetCompatibleDeviceId(
+ deviceInfo->DeviceData,
+ i,
+ &compatibleId);
+ if (NT_SUCCESS(status) && compatibleId) {
+ if ((length + wcslen(compatibleId) * sizeof(WCHAR) + 2 * sizeof(WCHAR))
+ <= 0x1000) {
+ RtlMoveMemory(p1, compatibleId, wcslen(compatibleId) * sizeof(WCHAR));
+ p1 += wcslen(compatibleId);
+ *p1 = UNICODE_NULL;
+ p1++;
+ length += wcslen(compatibleId) * sizeof(WCHAR) + sizeof(WCHAR);
+ ExFreePool(compatibleId);
+ } else {
+ ExFreePool(compatibleId);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ *p1 = UNICODE_NULL;
+ length += sizeof(WCHAR);
+ RtlInitUnicodeString(&unicodeString, L"CompatibleIDs");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ ids,
+ length
+ );
+ ExFreePool(ids);
+ }
+
+ //
+ // Add this device instance key to ENUM\PNPISA AttachedComponents
+ // value entry.
+ //
+
+ PipRemoveStringFromValueKey(
+ madeupKeyHandle,
+ L"AttachedComponents",
+ &unicodeDeviceInstance
+ );
+ PipAppendStringToValueKey(
+ madeupKeyHandle,
+ L"AttachedComponents",
+ &unicodeDeviceInstance,
+ TRUE
+ );
+
+ } else {
+
+ //
+ // The device instance key exists. We need to propagate the ConfigFlag
+ // to problem and StatusFlags
+ //
+
+ ULONG configFlags;
+
+ configFlags = 0;
+ status = PipGetRegistryValue(uniqueIdHandle,
+ L"ConfigFlags",
+ &keyValueInformation);
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_DWORD) &&
+ (keyValueInformation->DataLength >= sizeof(ULONG))) {
+ configFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
+ }
+ ExFreePool(keyValueInformation);
+ }
+ if (configFlags & CONFIGFLAG_REINSTALL) {
+
+ RtlInitUnicodeString(&unicodeString, L"Problem");
+ tmpValue = CM_PROB_REINSTALL;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"StatusFlags");
+ tmpValue = DN_HAS_PROBLEM;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+ } else {
+
+ RtlInitUnicodeString(&unicodeString, L"Problem");
+ tmpValue = 0;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"StatusFlags");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ }
+
+
+ //
+ // The device instance key exists. we will enabled the device
+ // if it is installed.
+ //
+
+ if (logConfHandle && PipIsDeviceInstanceInstalled(uniqueIdHandle, &unicodeDeviceInstance)) {
+
+ //
+ // Read the boot config selected by user and activate the device.
+ // First check if ForcedConfig is set. If not, check BootConfig.
+ //
+
+ status = PipGetRegistryValue(logConfHandle,
+ L"ForcedConfig",
+ &keyValueInformation);
+ if (!NT_SUCCESS(status)) {
+ status = PipGetRegistryValue(logConfHandle,
+ L"BootConfig",
+ &keyValueInformation);
+ }
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_RESOURCE_LIST) &&
+ (keyValueInformation->DataLength != 0)) {
+ cmResource = (PCM_RESOURCE_LIST)
+ KEY_VALUE_DATA(keyValueInformation);
+ status = PipSetDeviceResources (deviceInfo, cmResource);
+ if (NT_SUCCESS(status)) {
+ RtlInitUnicodeString(&unicodeString, L"AllocConfig");
+ ZwSetValueKey(logConfHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_RESOURCE_LIST,
+ cmResource,
+ keyValueInformation->DataLength
+ );
+ PipSelectLogicalDevice(
+ deviceInfo->CardInformation->CardSelectNumber,
+ deviceInfo->LogicalDeviceNumber,
+ TRUE
+ );
+ }
+ }
+ ExFreePool(keyValueInformation);
+ }
+ }
+ }
+
+ //
+ // Clean up
+ //
+
+ ZwClose(logConfHandle);
+ ZwClose(uniqueIdHandle);
+ ExFreePool(deviceId);
+ ExFreePool(uniqueId);
+ }
+ }
+ if (cardId) {
+ ExFreePool(cardId);
+ }
+ }
+
+ //
+ // Clean up
+ //
+
+ ZwClose(madeupKeyHandle);
+ ZwClose(busIdHandle);
+ ExFreePool(madeupInstancePath.Buffer);
+}
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through card list and deletes all the invalid
+ cards and their associated logical devices.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PSINGLE_LIST_ENTRY *cardLink, *deviceLink ;
+
+ //
+ // Go through the card link list to free all the devices
+ // marked as invalid.
+ //
+
+ cardLink = &BusExtension->CardList.Next;
+ while (*cardLink) {
+ cardInfo = CONTAINING_RECORD (*cardLink, CARD_INFORMATION, CardList);
+
+ //
+ // For each logical device of the card mark it as invalid
+ //
+
+ deviceLink = &cardInfo->LogicalDeviceList.Next;
+ while (*deviceLink) {
+ deviceInfo = CONTAINING_RECORD (*deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
+ BusExtension->NoValidSlots--;
+ *deviceLink = (*deviceLink)->Next; // Get the next addr before releasing pool
+ ExFreePool(deviceInfo);
+ }
+
+ *cardLink = (*cardLink)->Next; // Get the next addr before releasing pool
+ if (cardInfo->CardData) {
+ ExFreePool(cardInfo->CardData);
+ }
+ ExFreePool(cardInfo);
+ }
+
+ //
+ // Reset the CSN number, card and device link lists.
+ //
+
+ BusExtension->NumberCSNs = 0;
+ BusExtension->CardList.Next = NULL;
+ BusExtension->DeviceList.Next = NULL;
+}
+
+BOOLEAN
+PipIsDeviceInstanceInstalled(
+ IN HANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if the device instance is installed.
+
+Arguments:
+
+ Handle - Supplies a handle to the device instanace key to be checked.
+
+ DeviceInstanceName - supplies a pointer to a UNICODE_STRING which specifies
+ the path of the device instance to be checked.
+
+Returns:
+
+ A BOOLEAN value.
+
+--*/
+
+{
+ NTSTATUS status;
+ ULONG deviceFlags;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ BOOLEAN installed;
+ UNICODE_STRING serviceName, unicodeString;
+ HANDLE handle, handlex;
+
+ //
+ // Check if the "Service=" value entry initialized. If no, its driver
+ // is not installed yet.
+ //
+ status = PipGetRegistryValue(Handle,
+ L"Service",
+ &keyValueInformation);
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_SZ) &&
+ (keyValueInformation->DataLength != 0)) {
+ serviceName.Buffer = (PWSTR)((PCHAR)keyValueInformation +
+ keyValueInformation->DataOffset);
+ serviceName.MaximumLength = serviceName.Length = (USHORT)keyValueInformation->DataLength;
+ if (serviceName.Buffer[keyValueInformation->DataLength / sizeof(WCHAR)] == UNICODE_NULL) {
+ serviceName.Length -= sizeof(WCHAR);
+ }
+
+ //
+ // try open the service key to make sure it is a valid key
+ //
+
+ RtlInitUnicodeString(
+ &unicodeString,
+ L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES");
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ &unicodeString,
+ KEY_READ,
+ FALSE
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsaCheckDeviceInstalled: Can not open CCS\\SERVICES key"));
+ ExFreePool(keyValueInformation);
+ return FALSE;
+ }
+
+ status = PipOpenRegistryKey(&handlex,
+ handle,
+ &serviceName,
+ KEY_READ,
+ FALSE
+ );
+ ZwClose (handle);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsaCheckDeviceInstalled: Can not open CCS\\SERVICES key"));
+ ExFreePool(keyValueInformation);
+ return FALSE;
+ }
+ ZwClose(handlex);
+ }
+ ExFreePool(keyValueInformation);
+ } else {
+ return FALSE;
+ }
+
+ //
+ // Check if the device instance has been disabled.
+ // First check global flag: CONFIGFLAG and then CSCONFIGFLAG.
+ //
+
+ deviceFlags = 0;
+ status = PipGetRegistryValue(Handle,
+ L"ConfigFlags",
+ &keyValueInformation);
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_DWORD) &&
+ (keyValueInformation->DataLength >= sizeof(ULONG))) {
+ deviceFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
+ }
+ ExFreePool(keyValueInformation);
+ }
+
+ if (!(deviceFlags & CONFIGFLAG_DISABLED)) {
+ deviceFlags = 0;
+ status = PipGetDeviceInstanceCsConfigFlags(
+ DeviceInstanceName,
+ &deviceFlags
+ );
+ if (NT_SUCCESS(status)) {
+ if ((deviceFlags & CSCONFIGFLAG_DISABLED) ||
+ (deviceFlags & CSCONFIGFLAG_DO_NOT_CREATE)) {
+ deviceFlags = CONFIGFLAG_DISABLED;
+ } else {
+ deviceFlags = 0;
+ }
+ }
+ }
+
+ installed = TRUE;
+ if (deviceFlags & CONFIGFLAG_DISABLED) {
+ installed = FALSE;
+ }
+
+ return installed;
+}
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/busp.h b/private/ntos/nthals/extender/pnpisa.sur/busp.h
new file mode 100644
index 000000000..d8fd12f07
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/busp.h
@@ -0,0 +1,473 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busp.h
+
+Abstract:
+
+ Hardware independent header file for Pnp Isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+#ifndef _KERNEL_PNPI_
+#define _KERNEL_PNPI_
+#endif
+
+#include <ntddk.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <regstr.h>
+
+#define TITLE_INDEX_VALUE 0
+#define CM_PROB_REINSTALL (0x00000012) // HACK
+#define DN_HAS_PROBLEM (0x00000400)
+#define KEY_VALUE_DATA(k) ((PCHAR)(k) + (k)->DataOffset)
+
+//
+// Structures
+//
+
+//
+// CARD_INFORMATION Flags masks
+//
+
+typedef struct _CARD_INFORMATION_ {
+
+ //
+ // Next points to next CARD_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+
+ //
+ // Card select number for this Pnp Isa card.
+ //
+
+ USHORT CardSelectNumber;
+
+ //
+ // Number logical devices in the card.
+ //
+
+ ULONG NumberLogicalDevices;
+
+ //
+ // Logical device link list
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // Pointer to card data which includes:
+ // 9 byte serial identifier for the pnp isa card
+ // PlugPlay Version number type for the pnp isa card
+ // Identifier string resource type for the pnp isa card
+ // Logical device Id resource type (repeat for each logical device)
+ //
+
+ PVOID CardData;
+ ULONG CardDataLength;
+
+} CARD_INFORMATION, *PCARD_INFORMATION;
+
+//
+// DEVICE_INFORMATION Flags masks
+//
+
+typedef struct _DEVICE_INFORMATION_ {
+
+ //
+ // Link list for ALL the Pnp Isa logical devices.
+ // NextDevice points to next DEVICE_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+
+ //
+ // Pointer to the CARD_INFORMATION for this device
+ //
+
+ PCARD_INFORMATION CardInformation;
+
+ //
+ // Link list for all the logical devices in a Pnp Isa card.
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // LogicalDeviceNumber selects the corresponding logical device in the
+ // pnp isa card specified by CSN.
+ //
+
+ USHORT LogicalDeviceNumber;
+
+ //
+ // Pointer to device specific data
+ //
+
+ PUCHAR DeviceData;
+
+ //
+ // Length of the device data
+ //
+
+ ULONG DeviceDataLength;
+
+} DEVICE_INFORMATION, *PDEVICE_INFORMATION;
+
+//
+// Extension data for Bus extender
+//
+
+typedef struct _PI_BUS_EXTENSION {
+
+ //
+ // Number of cards selected
+ //
+
+ ULONG NumberCSNs;
+
+ //
+ // ReadDataPort addr
+ //
+
+ PUCHAR ReadDataPort;
+ BOOLEAN DataPortMapped;
+
+ //
+ // Address Port
+ //
+
+ PUCHAR AddressPort;
+ BOOLEAN AddrPortMapped;
+
+ //
+ // Command port
+ //
+
+ PUCHAR CommandPort;
+ BOOLEAN CmdPortMapped;
+
+ //
+ // Next Slot Number to assign
+ //
+
+ ULONG NextSlotNumber;
+
+ //
+ // DeviceList is the DEVICE_INFORMATION link list.
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+
+ //
+ // NoValidSlots is the number of valid slots
+ //
+
+ ULONG NoValidSlots;
+
+ //
+ // CardList is the list of CARD_INFORMATION
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+
+} PI_BUS_EXTENSION, *PPI_BUS_EXTENSION;
+
+//
+// The read data port range is from 0x200 - 0x3ff.
+// We will try the following optimal ranges first
+// if they all fail, we then pick any port from 0x200 - 0x3ff
+//
+// BEST:
+// One 4-byte range in 274-2FF
+// One 4-byte range in 374-3FF
+// One 4-byte range in 338-37F
+// One 4-byte range in 238-27F
+//
+// NORMAL:
+// One 4-byte range in 200-3FF
+//
+
+#define READ_DATA_PORT_RANGE_CHOICES 5
+typedef struct _READ_DATA_PORT_RANGE {
+ ULONG MinimumAddress;
+ ULONG MaximumAddress;
+ ULONG Alignment;
+} READ_DATA_PORT_RANGE, *PREAD_DATA_PORT_RANGE;
+
+//
+// Global Data references
+//
+
+extern PI_BUS_EXTENSION PipBusExtension;
+extern WCHAR rgzPNPISADeviceName[];
+extern PUCHAR PipReadDataPort;
+extern PUCHAR PipCommandPort;
+extern PUCHAR PipAddressPort;
+extern READ_DATA_PORT_RANGE PipReadDataPortRanges[];
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NTSTATUS
+PipGetCardIdentifier (
+ PUCHAR CardData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ );
+
+NTSTATUS
+PipGetFunctionIdentifier (
+ PUCHAR DeviceData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ );
+
+NTSTATUS
+PipQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId
+ );
+
+NTSTATUS
+PipQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId,
+ ULONG IdIndex
+ );
+
+NTSTATUS
+PipQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ PCM_RESOURCE_LIST *CmResources,
+ PULONG Length
+ );
+
+NTSTATUS
+PipQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ ULONG Slot,
+ PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ ULONG *Size
+ );
+
+NTSTATUS
+PipSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ );
+
+NTSTATUS
+PipOpenRegistryKey(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create
+ );
+
+NTSTATUS
+PipOpenRegistryKeyPersist(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create,
+ OUT PULONG Disposition OPTIONAL
+ );
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ );
+
+NTSTATUS
+PipOpenCurrentHwProfileDeviceInstanceKey(
+ OUT PHANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName,
+ IN ACCESS_MASK DesiredAccess
+ );
+
+NTSTATUS
+PipGetDeviceInstanceCsConfigFlags(
+ IN PUNICODE_STRING DeviceInstance,
+ OUT PULONG CsConfigFlags
+ );
+
+NTSTATUS
+PipRemoveStringFromValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String
+ );
+
+NTSTATUS
+PipAppendStringToValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String,
+ IN BOOLEAN Create
+ );
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ );
+
+VOID
+PipCheckBus (
+ IN PPI_BUS_EXTENSION BusExtension
+ );
+
+VOID
+PipCheckDevices (
+ IN PUNICODE_STRING RegistryPath,
+ IN PPI_BUS_EXTENSION BusExtension
+ );
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PVOID *ResourceData,
+ OUT PULONG ResourceDataLength
+ );
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber,
+ IN BOOLEAN ActivateDevice
+ );
+
+VOID
+PipLFSRInitiation (
+ VOID
+ );
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs
+ );
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ );
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION busExtension
+ );
+
+NTSTATUS
+PipServiceInstanceToDeviceInstance (
+ IN PUNICODE_STRING RegistryPath,
+ IN ULONG ServiceInstanceOrdinal,
+ OUT PUNICODE_STRING DeviceInstanceRegistryPath OPTIONAL,
+ OUT PHANDLE DeviceInstanceHandle OPTIONAL,
+ IN ACCESS_MASK DesiredAccess
+ );
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR *Buffer
+ );
+
+NTSTATUS
+ZwDeleteValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName
+ );
+
+#if DBG
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_BREAK 2
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ );
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList
+ );
+
+#define DebugPrint(arg) PipDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/convert.c b/private/ntos/nthals/extender/pnpisa.sur/convert.c
new file mode 100644
index 000000000..1e144bb5e
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/convert.c
@@ -0,0 +1,1092 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xlate.c
+
+Abstract:
+
+ This file contains routines to translate resources between PnP ISA/BIOS
+ format and Windows NT formats.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "pbios.h"
+
+//
+// internal structures for resource translation
+//
+
+typedef struct _PB_DEPENDENT_RESOURCES {
+ ULONG Count;
+ UCHAR Flags;
+ UCHAR Priority;
+ struct _PB_DEPENDENT_RESOURCES *Next;
+} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
+
+#define DEPENDENT_FLAGS_END 1
+
+typedef struct _PB_ATERNATIVE_INFORMATION {
+ PPB_DEPENDENT_RESOURCES Resources;
+ ULONG NoDependentFunctions;
+ ULONG TotalResourceCount;
+} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
+
+//
+// Internal function references
+//
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ );
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ );
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(INIT,PbBiosResourcesToNtResources)
+#pragma alloc_text(INIT,PbIoDescriptorToCmDescriptor)
+#pragma alloc_text(INIT,PbAddDependentResourcesToList)
+#pragma alloc_text(INIT,PbBiosIrqToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosDmaToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosPortFixedToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosPortToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosMemoryToIoDescriptor)
+#endif
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Bios resource list and generates
+ a NT resource list. The returned Nt resource list could be either IO
+ format or CM format. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ SlotNumber - specifies the slot number of the BIOS resource.
+
+ BiosData - Supplies a pointer to a variable which specifies the bios resource
+ data buffer and which to receive the pointer to next bios resource data.
+
+ ReturnedList - supplies a variable to receive the desired resource list.
+
+ ReturnedLength - Supplies a variable to receive the length of the resource list.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PUCHAR buffer;
+ USHORT mask16, increment;
+ UCHAR tagName, mask8;
+ NTSTATUS status;
+ PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
+ ULONG commonResCount = 0, dependDescCount = 0, i, j;
+ ULONG alternativeListCount = 0, dependFunctionCount = 0;
+ PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
+ PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
+ BOOLEAN dependent = FALSE;
+ ULONG listSize, noResLists;
+ ULONG totalDescCount, descCount;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
+ PIO_RESOURCE_LIST ioResList;
+
+ //
+ // First, scan the bios data to determine the memory requirement and
+ // the information to build internal data structures.
+ //
+
+ *ReturnedLength = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ while (tagName != TAG_COMPLETE_END) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ tagName &= SMALL_TAG_MASK;
+ } else {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ }
+
+ //
+ // Based on the type of the BIOS resource, determine the count of
+ // the IO descriptors.
+ //
+
+ switch (tagName) {
+ case TAG_IRQ:
+ mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
+ i = 0;
+ while (mask16) {
+ if (mask16 & 1) {
+ i++;
+ }
+ mask16 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_DMA:
+ mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
+ i = 0;
+ while (mask8) {
+ if (mask8 & 1) {
+ i++;
+ }
+ mask8 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ dependFunctionCount++;
+ break;
+ case TAG_END_DEPEND:
+ dependent = FALSE;
+ alternativeListCount++;
+ break;
+ case TAG_IO_FIXED:
+ case TAG_IO:
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (!dependent) {
+ commonResCount++;
+ } else {
+ dependDescCount++;
+ }
+ break;
+ default:
+
+ //
+ // Unknown tag. Skip it.
+ //
+
+ break;
+ }
+
+ //
+ // Move to next bios resource descriptor.
+ //
+
+ buffer += increment;
+ tagName = *buffer;
+ if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ break;
+ }
+ }
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (commonResCount == 0 && dependFunctionCount == 0) {
+ *ReturnedList = NULL;
+ *ReturnedLength = 0;
+ *BiosData = buffer + 2;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Allocate memory for our internal data structures
+ //
+
+ if (dependFunctionCount) {
+ dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
+ PagedPool,
+ dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
+ dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
+ 'bPnP'
+ );
+ if (!dependResources) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ dependResList = dependResources; // remember it so we can free it.
+ }
+
+ if (alternativeListCount) {
+ ASSERT(dependFunctionCount != 0);
+ alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
+ 'bPnP'
+ );
+ if (!alternativeList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit0;
+ }
+ RtlZeroMemory(alternativeList,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
+ );
+ alternativeList[0].Resources = dependResources;
+ }
+ if (commonResCount) {
+ commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
+ 'bPnP'
+ );
+ if (!commonResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit1;
+ }
+ }
+
+ //
+ // Now start over again to process the bios data and initialize our internal
+ // resource representation.
+ //
+
+ commonIoDesc = commonResources;
+ dependDescCount = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ dependent = FALSE;
+ while (tagName != TAG_COMPLETE_END) {
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ tagName &= SMALL_TAG_MASK;
+ }
+ switch (tagName) {
+ case TAG_IRQ:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_DMA:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ alternativeList[alternativeListCount].NoDependentFunctions++;
+ if (dependDescCount != 0) {
+
+ //
+ // End of current dependent function
+ //
+
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = 0;
+ dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = dependResources->Next;
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ }
+ if (*buffer & SMALL_TAG_SIZE_MASK) {
+ dependResources->Priority = *(buffer + 1);
+ }
+ dependDescCount = 0;
+ dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
+ buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
+ break;
+ case TAG_END_DEPEND:
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = DEPENDENT_FLAGS_END;
+ dependResources->Next = alternativeList[alternativeListCount].Resources;
+ dependent = FALSE;
+ dependDescCount = 0;
+ alternativeListCount++;
+ alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = alternativeList[alternativeListCount].Resources;
+ buffer++;
+ break;
+ case TAG_IO:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_IO_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ dependDescCount;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ default:
+
+ //
+ // Don't-care tag simpley advance the buffer pointer to next tag.
+ //
+
+ if (*buffer & LARGE_RESOURCE_TAG) {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ } else {
+ increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ }
+ buffer += increment;
+ }
+ tagName = *buffer;
+ if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ break;
+ }
+ }
+
+ if (alternativeListCount != 0) {
+ alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
+ }
+ *BiosData = buffer + 2; // Skip END_TAG
+
+ //
+ // prepare IoResourceList
+ //
+
+ noResLists = 1;
+ for (i = 0; i < alternativeListCount; i++) {
+ noResLists *= alternativeList[i].NoDependentFunctions;
+ }
+ totalDescCount = 0;
+ for (i = 0; i < alternativeListCount; i++) {
+ descCount = 1;
+ for (j = 0; j < alternativeListCount; j++) {
+ if (j == i) {
+ descCount *= alternativeList[j].TotalResourceCount;
+ } else {
+ descCount *= alternativeList[j].NoDependentFunctions;
+ }
+ }
+ totalDescCount += descCount;
+ }
+ listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
+ sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
+
+ ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
+ if (!ioResReqList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit2;
+ }
+
+ ioResReqList->ListSize = listSize;
+ ioResReqList->InterfaceType = Internal;
+ ioResReqList->BusNumber = BusNumber;
+ ioResReqList->SlotNumber = SlotNumber;
+ ioResReqList->Reserved[0] = 0;
+ ioResReqList->Reserved[1] = 0;
+ ioResReqList->Reserved[2] = 0;
+ ioResReqList->AlternativeLists = noResLists;
+ ioResList = &ioResReqList->List[0];
+
+ //
+ // Build resource lists
+ //
+
+ for (i = 0; i < noResLists; i++) {
+ ULONG size;
+ USHORT j;
+
+ ioResList->Version = 1;
+ ioResList->Revision = 0x30 | (USHORT)i;
+ buffer = (PUCHAR)&ioResList->Descriptors[0];
+
+ //
+ // Copy common resources to the list
+ //
+
+ if (commonResources) {
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
+ RtlMoveMemory(buffer, commonResources, size);
+ buffer += size;
+ }
+
+ //
+ // Copy dependent functions if any.
+ //
+
+ if (alternativeList) {
+ PbAddDependentResourcesToList(&buffer, 0, alternativeList);
+ }
+
+ //
+ // Update io resource list ptr
+ //
+
+ ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
+ sizeof(IO_RESOURCE_DESCRIPTOR);
+
+ //
+ // Hack for user mode pnp mgr
+ //
+
+ for (j = 0; j < ioResList->Count; j++) {
+ ioResList->Descriptors[j].Spare2 = j;
+ }
+ ioResList = (PIO_RESOURCE_LIST)buffer;
+ }
+
+ *ReturnedLength = listSize;
+ status = STATUS_SUCCESS;
+ *ReturnedList = ioResReqList;
+exit2:
+ if (commonResources) {
+ ExFreePool(commonResources);
+ }
+exit1:
+ if (alternativeList) {
+ ExFreePool(alternativeList);
+ }
+exit0:
+ if (dependResList) {
+ ExFreePool(dependResList);
+ }
+ return status;
+}
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds dependent functions to caller specified list.
+
+Arguments:
+
+ ResourceDescriptor - supplies a pointer to the descriptor buffer.
+
+ ListNo - supplies an index to the AlternativeList.
+
+ AlternativeList - supplies a pointer to the alternativelist array.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPB_DEPENDENT_RESOURCES dependentResources, ptr;
+ ULONG size;
+
+ //
+ // Copy dependent resources to caller supplied list buffer and
+ // update the list buffer pointer.
+ //
+
+ dependentResources = AlternativeList[ListNo].Resources;
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
+ RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
+ *ResourceDescriptor = *ResourceDescriptor + size;
+
+ //
+ // Add dependent resource of next list to caller's buffer
+ //
+
+ if (AlternativeList[ListNo + 1].Resources) {
+ ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
+ } else {
+ ptr = NULL;
+ }
+ if (ptr == NULL) {
+ AlternativeList[ListNo].Resources = dependentResources->Next;
+ if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
+ ptr = dependentResources->Next;
+ }
+ }
+ return ptr;
+}
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Arguments:
+
+ IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
+
+ CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CmDescriptor->Type = IoDescriptor->Type;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ switch (CmDescriptor->Type) {
+ case CmResourceTypePort:
+ CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
+ CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
+ break;
+ case CmResourceTypeInterrupt:
+ CmDescriptor->u.Interrupt.Level =
+ CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
+ CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
+ break;
+ case CmResourceTypeMemory:
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
+ break;
+ case CmResourceTypeDma:
+ CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
+ CmDescriptor->u.Dma.Port = 0;
+ CmDescriptor->u.Dma.Reserved1 = 0;
+ break;
+ }
+}
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IRQ information to NT usable format.
+ This routine stops when an irq io resource is generated. if there are
+ more irq io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ USHORT mask;
+ ULONG irq;
+ PPNP_IRQ_DESCRIPTOR buffer;
+ UCHAR size, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ size = buffer->Tag & SMALL_TAG_SIZE_MASK;
+ mask = buffer->IrqMask;
+ mask >>= bitPosition;
+ irq = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ irq = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (irq != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeInterrupt;
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (size == 3 && buffer->Information & 0x0C) {
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ IoDescriptor->ShareDisposition = CmResourceShareShared;
+ }
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Interrupt.MinimumVector = irq;
+ IoDescriptor->u.Interrupt.MaximumVector = irq;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current irq tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ *BiosData = (PUCHAR)buffer + size + 1;
+ return status;
+}
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS DMA information to NT usable format.
+ This routine stops when an dma io resource is generated. if there are
+ more dma io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ ULONG dma;
+ PPNP_DMA_DESCRIPTOR buffer;
+ UCHAR mask, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ mask = buffer->ChannelMask;
+ mask >>= bitPosition;
+ dma = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ dma = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (dma != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeDma;
+ IoDescriptor->Flags = 0;
+ IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Dma.MinimumChannel = dma;
+ IoDescriptor->u.Dma.MaximumChannel = dma;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current dma tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return status;
+}
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS FIXED IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_FIXED_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = 1;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS MEMORY information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PUCHAR buffer;
+ UCHAR tag;
+ PHYSICAL_ADDRESS minAddr, maxAddr;
+ ULONG alignment, length;
+ USHORT increment;
+
+ buffer = *BiosData;
+ tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
+ increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
+
+ minAddr.HighPart = 0;
+ maxAddr.HighPart = 0;
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
+ maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
+ maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
+ maxAddr.LowPart = minAddr.LowPart + length - 1;
+ alignment = 1;
+ break;
+ }
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypeMemory;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Memory.MinimumAddress = minAddr;
+ IoDescriptor->u.Memory.MaximumAddress = maxAddr;
+ IoDescriptor->u.Memory.Alignment = alignment;
+ IoDescriptor->u.Memory.Length = length;
+
+ //
+ // Done with current tag, advance pointer to next tag
+ //
+
+ buffer += increment;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pnpisa.sur/data.c b/private/ntos/nthals/extender/pnpisa.sur/data.c
new file mode 100644
index 000000000..8afb53ce0
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/data.c
@@ -0,0 +1,58 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbdata.c
+
+Abstract:
+
+ Declares various data which is specific to PNP ISA bus extender architecture and
+ is independent of BIOS.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+//
+// regPNPISADeviceName
+//
+
+WCHAR rgzPNPISADeviceName[] = L"\\Device\\PnpIsa_%d";
+
+//
+// Pointers to bus extension data.
+//
+
+PI_BUS_EXTENSION PipBusExtension;
+
+//
+// Read_data_port address
+// (This is mainly for convinience. It duplicates the
+// ReadDataPort field in BUS extension structure.)
+//
+
+PUCHAR PipReadDataPort;
+PUCHAR PipCommandPort;
+PUCHAR PipAddressPort;
+
+//
+// Read data port range selection array
+//
+
+READ_DATA_PORT_RANGE
+PipReadDataPortRanges[READ_DATA_PORT_RANGE_CHOICES] =
+ {{0x274, 0x2ff, 4}, {0x374, 0x3ff, 4}, {0x338, 0x37f, 4}, {0x238, 0x27f, 4}, {0x200, 0x3ff}};
diff --git a/private/ntos/nthals/extender/pnpisa.sur/init.c b/private/ntos/nthals/extender/pnpisa.sur/init.c
new file mode 100644
index 000000000..538820af1
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/init.c
@@ -0,0 +1,620 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ DriverEntry initialization code for pnp isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 29-Apr-1996
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+//
+// Internal References
+//
+
+PVOID
+PipGetMappedAddress(
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS IoAddress,
+ IN ULONG NumberOfBytes,
+ IN ULONG AddressSpace,
+ OUT PBOOLEAN MappedAddress
+ );
+
+NTSTATUS
+PipAcquirePortResources(
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath,
+ IN PHYSICAL_ADDRESS BaseAddressLow,
+ IN PHYSICAL_ADDRESS BaseAddressHi,
+ IN ULONG Alignment,
+ IN ULONG PortLength,
+ OUT PCM_RESOURCE_LIST *CmResourceList
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(INIT,PipAcquirePortResources)
+#pragma alloc_text(INIT,PipGetMappedAddress)
+#endif
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This is a temporary driver. It isolates all the PNP ISA cards. For each
+ Pnp Isa device, if its driver is installed, we retrieve user specified
+ resource information to configure the card and turn on the device.
+ Otherwise, we create a device instance for the device and record its resource
+ requirements list.
+
+ All the work is done in the Init/DriverEntry routine. So, this driver always
+ return failure to let itself be unloaded.
+
+Arguments:
+
+ DriverObject - specifies the driver object for the bus extender.
+
+ RegistryPath - supplies a pointer to a unicode string of the service key name in
+ the CurrentControlSet\Services key for the bus extender.
+
+Return Value:
+
+ Always return STATUS_UNSUCCESSFUL.
+
+--*/
+
+{
+ NTSTATUS status;
+ ULONG size, i, j, csn, cardDetected, maxCardDetected = 0;
+ PHYSICAL_ADDRESS baseAddrHi, baseAddrLow;
+ PUCHAR readDataPort = NULL;
+ PCM_RESOURCE_LIST cmResource, maxCmResource = NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
+
+ //
+ // In the first pass, we try to isolate pnpisa cards in the machine
+ // using read data port from each predefined ranges. One some machine
+ // different number of isapnp cards can be detected. We will choose
+ // the read data port which gives the max number of pnpisa cards.
+ //
+
+ for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
+
+ baseAddrLow.LowPart = PipReadDataPortRanges[i].MinimumAddress;
+ baseAddrLow.HighPart = 0;
+ baseAddrHi.LowPart = PipReadDataPortRanges[i].MaximumAddress;
+ baseAddrHi.HighPart = 0;
+ status = PipAcquirePortResources(
+ &PipBusExtension,
+ DriverObject,
+ RegistryPath,
+ baseAddrLow,
+ baseAddrHi,
+ PipReadDataPortRanges[i].Alignment,
+ 4,
+ &cmResource
+ );
+ if (!NT_SUCCESS(status)) {
+ continue;
+ }
+
+ //
+ // Perform Pnp isolation process. This will assign card select number for each
+ // Pnp Isa card isolated by the system. All the isolated cards will be put into
+ // wait-for-key state.
+ //
+
+ PipIsolateCards(&csn);
+
+ //
+ // send initiation key to put cards into sleep state
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // For each card selected, make sure it returns valid card resource data
+ //
+
+ cardDetected = 0;
+ for (j = 1; j <= csn; j++) {
+
+ ULONG noDevices, dataLength;
+ PUCHAR cardData;
+
+ status = PipReadCardResourceData (
+ j,
+ &noDevices,
+ &cardData,
+ &dataLength);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ } else {
+ ExFreePool(cardData);
+ cardDetected++;
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ if ((cardDetected != 0) && (cardDetected >= maxCardDetected)) {
+ maxCardDetected = cardDetected;
+ readDataPort = PipReadDataPort;
+ if (maxCmResource) {
+ ExFreePool(maxCmResource);
+ }
+ maxCmResource = cmResource;
+ } else {
+ ExFreePool(cmResource);
+ }
+ }
+
+ if (readDataPort != NULL) {
+
+ if (readDataPort != PipReadDataPort) {
+ if (PipReadDataPort) {
+ if (PipBusExtension.DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort - 3, 4);
+ }
+ PipReadDataPort = NULL;
+ }
+ cmResourceDescriptor =
+ &maxCmResource->List->PartialResourceList.PartialDescriptors[0];
+ PipReadDataPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &PipBusExtension.DataPortMapped
+ );
+ if (PipReadDataPort) {
+ PipReadDataPort += 3;
+ ASSERT(readDataPort == PipReadDataPort);
+ PipBusExtension.ReadDataPort = PipReadDataPort;
+ } else {
+ goto exit;
+ }
+ }
+
+ //
+ // Perform initial bus check to find all the PnP ISA devices
+ //
+
+ PipCheckBus(&PipBusExtension);
+ ASSERT(PipBusExtension.NumberCSNs == maxCardDetected);
+
+ //
+ // Perform PnP ISA device check to see if we should enable it.
+ //
+
+ PipCheckDevices(RegistryPath, &PipBusExtension);
+
+ //
+ // Delete all the device info structures and card info structures
+ //
+
+ PipDeleteCards(&PipBusExtension);
+ }
+
+ //
+ // Release address, command and read data port resources.
+ //
+
+exit:
+ if (maxCmResource) {
+ ExFreePool(maxCmResource);
+ }
+
+ if (PipCommandPort && PipBusExtension.CmdPortMapped) {
+ MmUnmapIoSpace(PipCommandPort, 1);
+ }
+ if (PipAddressPort && PipBusExtension.AddrPortMapped) {
+ MmUnmapIoSpace(PipAddressPort, 1);
+ }
+ if (PipReadDataPort && PipBusExtension.DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort - 3, 4);
+ }
+
+ IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ NULL,
+ NULL);
+
+ //
+ // Finally, return failure to get ourself unloaded.
+ //
+
+ return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+PipAcquirePortResources(
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath,
+ IN PHYSICAL_ADDRESS BaseAddressLow,
+ IN PHYSICAL_ADDRESS BaseAddressHi,
+ IN ULONG Alignment,
+ IN ULONG PortLength,
+ OUT PCM_RESOURCE_LIST *CmResourceList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine acquires specified port resources.
+
+Arguments:
+
+ BusExtension - Supplies a pointer to the pnp bus extension.
+
+ BaseAddressLow,
+ BaseAddressHi - Supplies the read data port base address range to be mapped.
+
+ Alignment - supplies the port allignment.
+
+ PortLength = Number of ports required.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+
+#if 1
+
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
+ NTSTATUS status;
+ ULONG size;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ ULONG i;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ *CmResourceList = NULL;
+
+ //
+ // Create a static Io resource requirements list and
+ // Call I/O mgr to get address, command and read data port addresses assigned.
+ //
+
+ size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResource = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
+ RtlZeroMemory(ioResource, size);
+ ioResource->ListSize = size;
+ ioResource->InterfaceType = Isa;
+ ioResource->AlternativeLists = 1;
+ ioResource->List[0].Version = 1;
+ ioResource->List[0].Revision = 1;
+ ioResource->List[0].Count = 1;
+ ioResource->List[0].Descriptors[0].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[0].u.Port.Length = PortLength;
+ ioResource->List[0].Descriptors[0].u.Port.Alignment = Alignment;
+ ioResource->List[0].Descriptors[0].u.Port.MinimumAddress = BaseAddressLow;
+ ioResource->List[0].Descriptors[0].u.Port.MaximumAddress = BaseAddressHi;
+
+ status = IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ ioResource,
+ &cmResource);
+ ExFreePool(ioResource);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ return status;
+ }
+
+ //
+ // Map port addr to memory addr if necessary.
+ //
+
+ if (PipAddressPort == NULL) {
+ physicalAddress.LowPart = ADDRESS_PORT;
+ physicalAddress.HighPart = 0;
+ BusExtension->AddressPort =
+ PipAddressPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ physicalAddress,
+ 1,
+ CM_RESOURCE_PORT_IO,
+ &BusExtension->AddrPortMapped
+ );
+ if (PipAddressPort == NULL) {
+ goto exit0;
+ }
+ }
+ if (PipCommandPort == NULL) {
+ physicalAddress.LowPart = COMMAND_PORT;
+ physicalAddress.HighPart = 0;
+ BusExtension->CommandPort =
+ PipCommandPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ physicalAddress,
+ 1,
+ CM_RESOURCE_PORT_IO,
+ &BusExtension->CmdPortMapped
+ );
+ if (PipCommandPort == NULL) {
+ goto exit0;
+ }
+ }
+ cmResourceDescriptor =
+ &cmResource->List->PartialResourceList.PartialDescriptors[0];
+ if ((cmResourceDescriptor->u.Port.Start.LowPart & 0xf) == 0) {
+
+ //
+ // Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
+ //
+
+ DebugPrint((DEBUG_BREAK, "PnpIsa:ReadDataPort is at yy3\n"));
+ goto exit0;
+ }
+ if (PipReadDataPort && BusExtension->DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort - 3, 4);
+ PipReadDataPort = NULL;
+ BusExtension->DataPortMapped = FALSE;
+ }
+ PipReadDataPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->DataPortMapped
+ );
+ if (PipReadDataPort) {
+ PipReadDataPort += 3;
+ PipBusExtension.ReadDataPort = PipReadDataPort;
+ }
+exit0:
+ //ExFreePool(cmResource);
+ if (PipReadDataPort && PipCommandPort && PipAddressPort) {
+ *CmResourceList = cmResource;
+ return STATUS_SUCCESS;
+ } else {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+#else
+
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
+ NTSTATUS status;
+ ULONG size;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ ULONG i;
+
+ //
+ // Create a static Io resource requirements list and
+ // Call I/O mgr to get address, command and read data port addresses assigned.
+ //
+
+ size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * 2;
+ ioResource = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
+ RtlZeroMemory(ioResource, size);
+ ioResource->ListSize = size;
+ ioResource->InterfaceType = Isa;
+ ioResource->AlternativeLists = 1;
+ ioResource->List[0].Version = 1;
+ ioResource->List[0].Revision = 1;
+ ioResource->List[0].Count = 3;
+ ioResource->List[0].Descriptors[0].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[0].u.Port.Length = PortLength;
+ ioResource->List[0].Descriptors[0].u.Port.Alignment = Alignment;
+ ioResource->List[0].Descriptors[0].u.Port.MinimumAddress = BaseAddressLow;
+ ioResource->List[0].Descriptors[0].u.Port.MaximumAddress = BaseAddressHi;
+ ioResource->List[0].Descriptors[1].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[1].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[1].u.Port.Length = 1;
+ ioResource->List[0].Descriptors[1].u.Port.Alignment = 1;
+ ioResource->List[0].Descriptors[1].u.Port.MinimumAddress.LowPart = ADDRESS_PORT;
+ ioResource->List[0].Descriptors[1].u.Port.MaximumAddress.LowPart = ADDRESS_PORT;
+ ioResource->List[0].Descriptors[2].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[2].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[2].u.Port.Length = 1;
+ ioResource->List[0].Descriptors[2].u.Port.Alignment = 1;
+ ioResource->List[0].Descriptors[2].u.Port.MinimumAddress.LowPart = COMMAND_PORT;
+ ioResource->List[0].Descriptors[2].u.Port.MaximumAddress.LowPart = COMMAND_PORT;
+
+ status = IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ ioResource,
+ &cmResource);
+ ExFreePool(ioResource);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ return status;
+ }
+
+ //
+ // Map port addr to memory addr if necessary.
+ //
+
+ ASSERT(cmResource->List->PartialResourceList.Count == 3);
+ for (i = 0; i < cmResource->List->PartialResourceList.Count; i++) {
+ cmResourceDescriptor =
+ &cmResource->List->PartialResourceList.PartialDescriptors[i];
+ ASSERT(cmResourceDescriptor->Type == CmResourceTypePort);
+ if (cmResourceDescriptor->u.Port.Start.LowPart == ADDRESS_PORT) {
+ if (PipAddressPort == NULL) {
+ BusExtension->AddressPort =
+ PipAddressPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->AddrPortMapped
+ );
+ }
+ } else if (cmResourceDescriptor->u.Port.Start.LowPart == COMMAND_PORT) {
+ if (PipCommandPort == NULL) {
+ BusExtension->CommandPort =
+ PipCommandPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->CmdPortMapped
+ );
+ }
+ } else {
+ if ((cmResourceDescriptor->u.Port.Start.LowPart & 0xf) == 0) {
+
+ //
+ // Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
+ //
+
+ DebugPrint((DEBUG_BREAK, "PnpIsa:ReadDataPort is at yy3\n"));
+ goto exit0;
+ }
+ if (PipReadDataPort && BusExtension->DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort, 4);
+ PipReadDataPort = NULL;
+ BusExtension->DataPortMapped = FALSE;
+ }
+ PipReadDataPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->DataPortMapped
+ );
+ if (PipReadDataPort) {
+ PipReadDataPort += 3;
+ PipBusExtension.ReadDataPort = PipReadDataPort;
+ }
+ }
+ }
+exit0:
+ ExFreePool(cmResource);
+ if (PipReadDataPort && PipCommandPort && PipAddressPort) {
+ return STATUS_SUCCESS;
+ } else {
+ IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ NULL,
+ NULL);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+#endif // 1
+}
+
+PVOID
+PipGetMappedAddress(
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS IoAddress,
+ IN ULONG NumberOfBytes,
+ IN ULONG AddressSpace,
+ OUT PBOOLEAN MappedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps an IO address to system address space.
+
+Arguments:
+
+ BusType - Supplies the type of bus - eisa, mca, isa...
+
+ IoBusNumber - Supplies the bus number.
+
+ IoAddress - Supplies the base device address to be mapped.
+
+ NumberOfBytes - Supplies the number of bytes for which the address is
+ valid.
+
+ AddressSpace - Supplies whether the address is in io space or memory.
+
+ MappedAddress - Supplies whether the address was mapped. This only has
+ meaning if the address returned is non-null.
+
+Return Value:
+
+ The mapped address.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS cardAddress;
+ PVOID address;
+
+ HalTranslateBusAddress(BusType, BusNumber, IoAddress, &AddressSpace,
+ &cardAddress);
+
+ //
+ // Map the device base address into the virtual address space
+ // if the address is in memory space.
+ //
+
+ if (!AddressSpace) {
+
+ address = MmMapIoSpace(cardAddress, NumberOfBytes, FALSE);
+ *MappedAddress = (address ? TRUE : FALSE);
+
+ } else {
+
+ address = (PVOID) cardAddress.LowPart;
+ *MappedAddress = FALSE;
+ }
+
+ return address;
+}
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/isolate.c b/private/ntos/nthals/extender/pnpisa.sur/isolate.c
new file mode 100644
index 000000000..8e050358f
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/isolate.c
@@ -0,0 +1,1607 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ isolate.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-10-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pbios.h"
+#include "pnpisa.h"
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG Base,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ );
+
+VOID
+PipReadCardResourceDataBytes (
+ IN USHORT BytesToRead,
+ IN PUCHAR Buffer
+ );
+
+//
+// Internal type definitions
+//
+
+typedef struct _MEMORY_DESC_{
+ ULONG Base;
+ ULONG Length;
+ BOOLEAN Memory32;
+} MEMORY_DESC, *PMEMORY_DESC;
+
+typedef struct _IRQ_DESC_{
+ UCHAR Level;
+ ULONG Type;
+}IRQ_DESC, *PIRQ_DESC;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PipFindIrqInformation)
+#pragma alloc_text(INIT,PipFindMemoryInformation)
+#pragma alloc_text(INIT,PipFindIoPortInformation)
+#pragma alloc_text(INIT,PipReadCardResourceData)
+#pragma alloc_text(INIT,PipReadDeviceBootResourceData)
+#pragma alloc_text(INIT,PipWriteDeviceBootResourceData)
+#pragma alloc_text(INIT,PipLFSRInitiation)
+#pragma alloc_text(INIT,PipIsolateCards)
+#pragma alloc_text(INIT,PipFindNextLogicalDeviceTag)
+#pragma alloc_text(INIT,PipSelectLogicalDevice)
+#pragma alloc_text(INIT,PipReadCardResourceDataBytes)
+#endif
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Irq descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. On input, the BiosRequirements points to current
+ logical id tag.
+
+Arguments:
+
+ IrqLevel - Supplies the irq level.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ ULONG increment;
+ USHORT irqMask;
+ PPNP_IRQ_DESCRIPTOR biosDesc;
+
+ //
+ // Skip current logical id tag
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the Irq.
+ //
+
+ irqMask = 1 << IrqLevel;
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
+ biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->IrqMask & irqMask) {
+ if ((tag & SMALL_TAG_SIZE_MASK) == 2) {
+
+ //
+ // if no irq info is available, a value of zero is returned.
+ // (o is not a valid irq information.)
+ //
+
+ *Information = 0;
+ } else {
+ *Information = biosDesc->Information;
+ }
+ return TRUE;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG BaseAddress,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ memory descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. Note, the memory range specified by Base
+ and Limit must be within a single Pnp ISA memory descriptor.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the memory range.
+
+ Limit - Supplies the upper limit of the memory range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ NameTag - Supplies a variable to receive the Tag of the memory descriptor which
+ describes the memory information.
+
+ Information - supplies a pointer to a UCHAR to receive the memory information
+ for the specified memory range.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+
+ //
+ // Skip current logical id tag.
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the memory range described by Base and Limit.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
+ maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
+ + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
+ maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
+ + length - 1;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
+ maxAddr = minAddr + length - 1;
+ break;
+ }
+
+ if (minAddr <= BaseAddress && maxAddr >= Limit) {
+ *Information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
+ *NameTag = tag;
+ found = TRUE;
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Io port descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the Io port range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+ Alignment - supplies a pointer to a UCHAR to receive the port alignment
+ information.
+
+ RangeLength - supplies a pointer to a UCHAR to receive the port range length
+ information.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+ PPNP_PORT_DESCRIPTOR portDesc;
+ PPNP_FIXED_PORT_DESCRIPTOR fixedPortDesc;
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the io port range described by Base.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag & SMALL_TAG_MASK) {
+ case TAG_IO:
+ portDesc = (PPNP_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = portDesc->MinimumAddress;
+ maxAddr = portDesc->MaximumAddress;
+ if (minAddr <= BaseAddress && maxAddr >= BaseAddress) {
+ *Information = portDesc->Information;
+ *Alignment = portDesc->Alignment;
+ *RangeLength = portDesc->Length;
+ found = TRUE;
+ }
+ break;
+ case TAG_IO_FIXED:
+ fixedPortDesc = (PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = fixedPortDesc->MinimumAddress;
+ if (BaseAddress == minAddr) {
+ *Information = 0; // 10 bit decode
+ *Alignment = 1;
+ *RangeLength = fixedPortDesc->Length;
+ found = TRUE;
+ }
+ break;
+ }
+
+ if (found) {
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PUCHAR *ResourceData,
+ OUT PULONG ResourceDataLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads resources data from a specified PnP ISA card. It is
+ caller's responsibility to release the memory. Before calling this routine,
+ the Pnp ISA card should be in sleep state (i.e. Initiation Key was sent.)
+ After exiting this routine, the card will be left in Config state.
+
+Arguments:
+
+ Csn - Specifies the CardSelectNumber to indicate which PNP ISA card.
+
+ NumberLogicalDevices - supplies a variable to receive the number of logical devices
+ associated with the Pnp Isa card.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ ResourceDataLength - Supplies a variable to receive the length of the ResourceData.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ PUCHAR buffer, p;
+ LONG sizeToRead, limit, i;
+ USHORT size;
+ UCHAR tag;
+ ULONG noDevices;
+ BOOLEAN failed;
+
+ //
+ // Allocate memory to store the resource data.
+ // N.B. The buffer size should cover 99.999% of the machines.
+ //
+
+ sizeToRead = 4096;
+
+tryAgain:
+
+ noDevices = 0;
+ buffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, sizeToRead, 'iPnP');
+ if (!buffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Send card from sleep state to configuration state
+ // Note, by doing this the resource data includes 9 bytes Id.
+ //
+
+ PipWriteAddress (WAKE_CSN_PORT);
+ PipWriteData((UCHAR)Csn);
+
+ //
+ // Read card id bytes
+ //
+
+ p = buffer;
+ PipReadCardResourceDataBytes(NUMBER_CARD_ID_BYTES, p);
+ i = NUMBER_CARD_ID_BYTES;
+ p += NUMBER_CARD_ID_BYTES;
+
+ //
+ // read all the tag descriptors of the card resource data
+ //
+
+ failed = FALSE;
+ limit = sizeToRead - 4 - NUMBER_CARD_ID_BYTES;;
+
+ while (TRUE) {
+
+ //
+ // Read tag byte. Make sure it's a valid tag and determine
+ // the size of the descriptor.
+ //
+
+ PipReadCardResourceDataBytes(1, p);
+ tag = *p;
+ i++;
+ p++;
+ if (tag == TAG_COMPLETE_END) {
+ PipReadCardResourceDataBytes(1, p);
+ p++;
+ i++;
+ break;
+ }
+ if (tag & LARGE_RESOURCE_TAG) {
+ if (tag & 0x70) {
+ failed = TRUE;
+ break;
+ } else {
+ PipReadCardResourceDataBytes(2, p);
+ size = *((PUSHORT)p);
+ p += 2;
+ i += 2;
+ }
+ } else {
+ if ((tag & 0x70) == 0x50 || (tag & 0x70) == 0x60 || (((tag & 0x70) == 0) && (tag != 0xa))) {
+ failed = TRUE;
+ break;
+ } else {
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ noDevices++;
+ }
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ }
+ }
+
+ //
+ // read 'size' number of bytes for the current descriptor
+ //
+
+ i += size;
+ if (i < limit) {
+ PipReadCardResourceDataBytes(size, p);
+ p += size;
+ } else {
+ ExFreePool(buffer);
+ sizeToRead <<= 1; // double the buffer
+
+ //
+ // If we can find the END tag with 32K byte, assume the resource
+ // requirement list is bad.
+ //
+
+ if (sizeToRead > 0x80000) {
+ return STATUS_INVALID_PARAMETER;
+ } else {
+ goto tryAgain;
+ }
+ }
+ }
+ if (failed) {
+ ExFreePool(buffer);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Determine the real size of the buffer required and
+ // resize the buffer.
+ //
+
+ size = p - buffer; // i
+ p = (PUCHAR)ExAllocatePoolWithTag(PagedPool, size, 'iPnP');
+ if (p) {
+ RtlMoveMemory(p, buffer, size);
+ ExFreePool(buffer);
+ } else {
+
+ //
+ // Fail to resize the buffer. Simply leave it alone.
+ //
+
+ p = buffer;
+ }
+
+ //
+ // Should we leave card in config state???
+ //
+
+ *ResourceData = p;
+ *NumberLogicalDevices = noDevices;
+ *ResourceDataLength = size;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads boot resource data from an enabled logical device of a PNP ISA
+ card. Caller must put the card into configuration state and select the logical
+ device before calling this function. It is caller's responsibility to release
+ the memory. ( The boot resource data is the resources that a card assigned during
+ boot.)
+
+Arguments:
+
+ BusNumber - specifies the bus number of the device whose resource data to be read.
+
+ BiosRequirements - Supplies a pointer to the resource requirement list for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ Length - Supplies a variable to recieve the length of the resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ UCHAR c, junk1, junk2;
+ PUCHAR base;
+ ULONG l, resourceCount;
+ BOOLEAN limit;
+ LONG i, j, noMemoryDesc = 0, noIoDesc = 0, noDmaDesc =0, noIrqDesc = 0;
+ MEMORY_DESC memoryDesc[NUMBER_MEMORY_DESCRIPTORS + NUMBER_32_MEMORY_DESCRIPTORS];
+ IRQ_DESC irqDesc[NUMBER_IRQ_DESCRIPTORS];
+ UCHAR dmaDesc[NUMBER_DMA_DESCRIPTORS];
+ USHORT ioDesc[NUMBER_IO_DESCRIPTORS];
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_LIST partialResList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+
+#if 0
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpIsa-ReadDeviceBootResourceData:The logical device has not been activated\n"));
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if (!BiosRequirements && ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Read memory configuration
+ //
+
+ base = (PUCHAR)ADDRESS_MEMORY_BASE;
+ for (i = 0; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+
+ //
+ // Read memory base address
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8; // l = memory base address
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8;
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ memoryDesc[noMemoryDesc].Memory32 = FALSE;
+ noMemoryDesc++;
+ base += ADDRESS_MEMORY_INCR;
+ }
+
+ //
+ // Read memory 32 configuration
+ //
+
+ for (i = 0; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+
+ base = ADDRESS_32_MEMORY_BASE(i);
+
+ //
+ // Read memory base address
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_B3; j <= ADDRESS_32_MEMORY_B0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_32_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_E3; j <= ADDRESS_32_MEMORY_E0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ memoryDesc[noMemoryDesc].Memory32 = TRUE;
+ noMemoryDesc++;
+ }
+
+ //
+ // Read Io Port Configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IO_BASE;
+ for (i = 0; i < NUMBER_IO_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IO_BASE_HI);
+ c = PipReadData();
+ l = c;
+ PipWriteAddress(base + ADDRESS_IO_BASE_LO);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ if (l == 0) {
+ break;
+ }
+ ioDesc[noIoDesc++] = (USHORT)l;
+ base += ADDRESS_IO_INCR;
+ }
+
+ //
+ // Read Interrupt configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IRQ_BASE;
+ for (i = 0; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IRQ_VALUE);
+ c = PipReadData() & 0xf;
+ if (c == 0) {
+ break;
+ }
+ irqDesc[noIrqDesc].Level = c;
+ PipWriteAddress(base + ADDRESS_IRQ_TYPE);
+ c = PipReadData();
+ irqDesc[noIrqDesc++].Type = c;
+ base += ADDRESS_IRQ_INCR;
+ }
+
+ //
+ // Read DMA configuration
+ //
+
+ base = (PUCHAR)ADDRESS_DMA_BASE;
+ for (i = 0; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_DMA_VALUE);
+ c = PipReadData() & 0x7;
+ if (c == 4) {
+ break;
+ }
+ dmaDesc[noDmaDesc++] = c;
+ base += ADDRESS_DMA_INCR;
+ }
+
+ //
+ // Construct CM_RESOURCE_LIST structure based on the resource data
+ // we collect so far.
+ //
+
+ resourceCount = noMemoryDesc + noIoDesc + noDmaDesc + noIrqDesc;
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (resourceCount == 0) {
+ *ResourceData = NULL;
+ *Length = 0;
+ return STATUS_SUCCESS;
+ }
+
+ l = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
+ ( resourceCount - 1);
+ cmResource = ExAllocatePoolWithTag(PagedPool, l, 'iPnP');
+ if (!cmResource) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(cmResource, l);
+ *Length = l; // Set returned resource data length
+ cmResource->Count = 1;
+ cmResource->List[0].InterfaceType = Isa;
+ cmResource->List[0].BusNumber = BusNumber;
+ partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResource->List[0].PartialResourceList;
+ partialResList->Version = 0;
+ partialResList->Revision = 0x3000;
+ partialResList->Count = resourceCount;
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
+
+ //
+ // Set up all the CM memory descriptors
+ //
+
+ for (i = 0; i < noMemoryDesc; i++) {
+ partialDesc->Type = CmResourceTypeMemory;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->u.Memory.Length = memoryDesc[i].Length;
+ partialDesc->u.Memory.Start.HighPart = 0;
+ partialDesc->u.Memory.Start.LowPart = memoryDesc[i].Base;
+
+ //
+ // Need to consult configuration data for the Flags
+ //
+
+ l = memoryDesc[i].Base + memoryDesc[i].Length - 1;
+ if (PipFindMemoryInformation (memoryDesc[i].Base, l, BiosRequirements, &junk1, &c)) {
+ if (c & PNP_MEMORY_WRITE_STATUS_MASK) {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+ } else {
+ DebugPrint((DEBUG_BREAK, "PnpIsa-ReadDeviceBootResourceData:No matched memory information in config data\n"));
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+ if (memoryDesc[i].Memory32 == FALSE) {
+ partialDesc->Flags |= CM_RESOURCE_MEMORY_24;
+ }
+ partialDesc++;
+ }
+
+ //
+ // Set up all the CM io/port descriptors
+ //
+
+ for (i = 0; i < noIoDesc; i++) {
+ partialDesc->Type = CmResourceTypePort;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = CM_RESOURCE_PORT_IO;
+ partialDesc->u.Port.Start.LowPart = ioDesc[i];
+
+ //
+ // Need to consult configuration data for the Port length
+ //
+
+ if (PipFindIoPortInformation (ioDesc[i], BiosRequirements, &junk1, &junk2, &c)) {
+ partialDesc->u.Port.Length = c;
+ partialDesc++;
+ } else {
+ DebugPrint((DEBUG_BREAK, "PnpIsa-ReadDeviceBootResourceData:No matched port length in config data\n"));
+ ExFreePool(cmResource);
+ *ResourceData = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ //
+ // Set up all the CM DMA descriptors
+ //
+
+ for (i = 0; i < noDmaDesc; i++) {
+ partialDesc->Type = CmResourceTypeDma;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = 0; // no flags for DMA descriptor
+ partialDesc->u.Dma.Channel = (ULONG) dmaDesc[i];
+ partialDesc->u.Dma.Port = 0;
+ partialDesc->u.Dma.Reserved1 = 0;
+ partialDesc++;
+ }
+
+ //
+ // Set up all the CM interrupt descriptors
+ //
+
+ for (i = 0; i < noIrqDesc; i++) {
+ partialDesc->Type = CmResourceTypeInterrupt;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (irqDesc[i].Type & 1) {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ }
+ partialDesc->u.Interrupt.Vector =
+ partialDesc->u.Interrupt.Level = irqDesc[i].Level;
+ partialDesc->u.Interrupt.Affinity = (ULONG)-1;
+ partialDesc++;
+ }
+
+ *ResourceData = cmResource;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes boot resource data to an enabled logical device of
+ a Pnp ISA card. Caller must put the card into configuration state and select
+ the logical device before calling this function.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the possible resources for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a pointer to the cm resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+ UCHAR c, information;
+ ULONG count, i, j, pass, base, limit;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
+ ULONG noIrq =0, noIo = 0, noDma = 0, noMemory = 0, no32Memory = 0;
+ PUCHAR memoryBase, irqBase, dmaBase, ioBase, tmp;
+ ULONG memory32Base;
+
+#if 0
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DbgPrint("PnpIsa-WriteDeviceBootResourceData:The logical device has not been activated\n");
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ count = CmResources->List[0].PartialResourceList.Count;
+ memoryBase = (PUCHAR)ADDRESS_MEMORY_BASE;
+ memory32Base = 0;
+ ioBase = (PUCHAR)ADDRESS_IO_BASE;
+ irqBase = (PUCHAR)ADDRESS_IRQ_BASE;
+ dmaBase = (PUCHAR)ADDRESS_DMA_BASE;
+ for (pass = 1; pass <= 2; pass++) {
+
+ //
+ // First pass we make sure the resources to be set is acceptable.
+ // Second pass we actually write the resources to the logical device's
+ // configuration space.
+ //
+
+ cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
+ for (i = 0; i < count; i++) {
+ switch (cmDesc->Type) {
+ case CmResourceTypePort:
+ if (pass == 1) {
+ noIo++;
+ if (noIo > NUMBER_IO_DESCRIPTORS ||
+ cmDesc->u.Port.Start.HighPart != 0 ||
+ cmDesc->u.Port.Start.LowPart & 0xffff0000 ||
+ cmDesc->u.Port.Length & 0xffffff00) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Io port base address to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Port.Start.LowPart;
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_LO);
+ PipWriteData(c);
+ c = (UCHAR)(cmDesc->u.Port.Start.LowPart >> 8);
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_HI);
+ PipWriteData(c);
+ ioBase += ADDRESS_IO_INCR;
+ }
+ break;
+ case CmResourceTypeInterrupt:
+ if (pass == 1) {
+ noIrq++;
+ if (noIrq > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Interrupt.Level & 0xfffffff0)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // See if we can get the interrupt information from possible resource
+ // data. We need it to set the configuration register.
+ //
+
+ if (!PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Irq to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Interrupt.Level;
+ PipWriteAddress(irqBase + ADDRESS_IRQ_VALUE);
+ PipWriteData(c);
+ PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information);
+ if (information != 0) {
+ switch (information & 0xf) {
+ case 1: // High true edge sensitive
+ c = 2;
+ break;
+ case 2: // Low true edge sensitive
+ c = 0;
+ break;
+ case 4: // High true level sensitive
+ c = 3;
+ break;
+ case 8: // Low true level sensitive
+ c = 1;
+ break;
+ }
+ PipWriteAddress(irqBase + ADDRESS_IRQ_TYPE);
+ PipWriteData(c);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ break;
+ case CmResourceTypeDma:
+ if (pass == 1) {
+ noDma++;
+ if (noDma > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Dma.Channel & 0xfffffff8)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Dma channel to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Dma.Channel;
+ PipWriteAddress(dmaBase + ADDRESS_DMA_VALUE);
+ PipWriteData(c);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ break;
+ case CmResourceTypeMemory:
+ if (pass == 1) {
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ if (!PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ } else {
+ if (cmDesc->Flags & CM_RESOURCE_MEMORY_24) {
+ noMemory++;
+
+ //
+ // Make sure the lower 8 bits of the base address are zero.
+ //
+
+ if (noMemory > NUMBER_MEMORY_DESCRIPTORS ||
+ base & 0xff) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+ no32Memory++;
+ if (no32Memory > NUMBER_32_MEMORY_DESCRIPTORS) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ } else {
+
+ //
+ // Find information in BiosRequirements to help determine how to write
+ // the memory configuration space.
+ //
+
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information);
+ if (cmDesc->Flags & CM_RESOURCE_MEMORY_24) {
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_LO);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_HI);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_CTL);
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT; // assume 16 bit memory
+ if (information & 0x18 == 0) { // 8 bit memory only
+ c = 0 + ADDRESS_MEMORY_CTL_LIMIT;
+ }
+ PipWriteData(c);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_LO);
+ PipWriteData((UCHAR)limit);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_HI);
+ PipWriteData((UCHAR)limit);
+ memoryBase += ADDRESS_MEMORY_INCR;
+ } else {
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B0);
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B1);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B2);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B3);
+ base >>= 8;
+ PipWriteData(base);
+ switch (information & 0x18) {
+ case 0: // 8 bit only
+ c = ADDRESS_MEMORY_CTL_LIMIT;
+ case 8: // 16 bit only
+ case 0x10: // 8 and 16 bit supported
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ case 0x18: // 32 bit only
+ c = 6 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ }
+ PipWriteAddress(ADDRESS_32_MEMORY_CTL);
+ PipWriteData(c);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E0);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E1);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E2);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E3);
+ PipWriteData(limit);
+ memory32Base++;
+ }
+ }
+ }
+ cmDesc++;
+ }
+ }
+
+ //
+ // Finally, mark all the unused descriptors as disabled.
+ //
+
+ for (i = noMemory; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+ for (j = 0; j < 5; j++) {
+ PipWriteAddress(memoryBase + j);
+ PipWriteData(0);
+ }
+ memoryBase += ADDRESS_MEMORY_INCR;
+ }
+ for (i = no32Memory; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ for (j = 0; j < 9; j++) {
+ PipWriteAddress(tmp + j);
+ PipWriteData(0);
+ }
+ memory32Base++;
+ }
+ for (i = noIo; i < NUMBER_IO_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(ioBase + j);
+ PipWriteData(0);
+ }
+ ioBase += ADDRESS_IO_INCR;
+ }
+ for (i = noIrq; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(irqBase + j);
+ PipWriteData(0);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ for (i = noDma; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(dmaBase);
+ PipWriteData(4);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID
+PipLFSRInitiation (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insures the LFSR (linear feedback shift register) is in its
+ initial state and then performs 32 writes to the ADDRESS port to initiation
+ LFSR function.
+
+ Pnp software sends the initiation key to all the Pnp ISA cards to place them
+ into configuration mode. The software then ready to perform isolation
+ protocol.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR seed, bit7;
+ ULONG i;
+
+ //
+ // First perform two writes of value zero to insure the LFSR is in the
+ // initial state.
+ //
+
+ PipWriteAddress (0);
+ PipWriteAddress (0);
+
+ //
+ // Perform the initiation key.
+ //
+
+ seed = LFSR_SEED; // initial value of 0x6a
+ for (i = 0; i < 32; i++) {
+ PipWriteAddress (seed);
+ bit7=(((seed & 2) >> 1) ^ (seed & 1)) << 7;
+ seed =(seed >> 1) | bit7;
+ }
+}
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs PnP ISA cards isolation sequence.
+
+Arguments:
+
+ NumberCSNs - supplies the addr of a variable to receive the number of
+ Pnp Isa cards isolated.
+
+ ReadDataPort - Supplies the address of a variable to supply ReadData port
+ address.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT j, i;
+ UCHAR cardId[NUMBER_CARD_ID_BYTES];
+ UCHAR bit, bit7, checksum, byte1, byte2;
+ ULONG csn = 0;
+
+ *NumberCSNs = 0;
+
+ //
+ // First send Initiation Key to all the PNP ISA cards to enable PnP auto-config
+ // ports and put all cards in configuration mode.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Reset all Pnp ISA cards' CSN to 0 and return to wait-for-key state
+ //
+
+ PipWriteAddress (CONFIG_CONTROL_PORT);
+ PipWriteData (CONTROL_WAIT_FOR_KEY | CONTROL_RESET_CSN);
+
+ //
+ // Delay 2 msec for cards to load initial configuration state.
+ //
+
+ KeStallExecutionProcessor(20000); // delay 2 msec
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ // The hardware on each PnP Isa card expects 72 pairs of I/O read
+ // access to the read data port.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Starting Pnp Isa card isolation process.
+ //
+
+ //
+ // Send WAKE[CSN=0] to force all cards without CSN into isolation
+ // state to set READ DATA PORT.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ //
+ // Set read data port to current testing value.
+ //
+
+ PipWriteAddress(SET_READ_DATA_PORT);
+ PipWriteData((UCHAR)((ULONG)PipReadDataPort >> 2));
+
+ //
+ // Isolate one PnP ISA card until fail
+ //
+
+ while (TRUE) {
+
+ //
+ // Read serial isolation port to cause PnP cards in the isolation
+ // state to compare one bit of the boards ID.
+ //
+
+ PipWriteAddress(SERIAL_ISOLATION_PORT);
+
+ //
+ // We need to delay 1 msec prior to starting the first pair of isolation
+ // reads and must wait 250usec between each subsequent pair of isolation
+ // reads. This delay gives the ISA cards time to access information from
+ // possible very slow storage device.
+ //
+
+ KeStallExecutionProcessor(10000); // delay 1 msec
+
+ RtlZeroMemory(cardId, NUMBER_CARD_ID_BYTES);
+ checksum = LFSR_SEED;
+ for (j = 0; j < NUMBER_CARD_ID_BITS; j++) {
+
+ //
+ // Read card id bit by bit
+ //
+
+ byte1 = PipReadData();
+ byte2 = PipReadData();
+ bit = (byte1 == ISOLATION_TEST_BYTE_1) && (byte2 == ISOLATION_TEST_BYTE_2);
+ cardId[j / 8] |= bit << (j % 8);
+ if (j < CHECKSUMED_BITS) {
+
+ //
+ // Calculate checksum and only do it for the first 64 bits
+ //
+
+ bit7 = (((checksum & 2) >> 1) ^ (checksum & 1) ^ (bit)) << 7;
+ checksum = (checksum >> 1) | bit7;
+ }
+ KeStallExecutionProcessor(2500); // delay 250 usec
+ }
+
+ //
+ // Verify the card id we read is legitimate
+ // First make sure checksum is valid. Note zero checksum is considered valid.
+ //
+
+ if (cardId[8] == 0 || checksum == cardId[8]) {
+
+ //
+ // Next make sure cardId is not zero
+ //
+
+ byte1 = 0;
+ for (j = 0; j < NUMBER_CARD_ID_BYTES; j++) {
+ byte1 |= cardId[j];
+ }
+ if (byte1 != 0) {
+
+ //
+ // We found a valid Pnp Isa card, assign it a CSN number
+ //
+
+ PipWriteAddress(SET_CSN_PORT);
+
+ PipWriteData(++csn);
+
+ //
+ // Do Wake[CSN] command to put the newly isolated card to
+ // sleep state and other un-isolated cards to isolation
+ // state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ continue; // ... to isolate more cards ...
+ }
+ }
+ break; // could not isolate more cards ...
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+ *NumberCSNs = csn;
+}
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the Pnp Isa card data for the Next logical
+ device tag encountered. The input *CardData should point to an logical device id tag,
+ which is the current logical device tag. If the *CardData does not point to a logical
+ device id tag (but, it must point to some kind of tag), it will be moved to next
+ logical device id tag.
+
+Arguments:
+
+ CardData - a variable to supply a pointer to the pnp Isa resource descriptors and to
+ receive next logical device tag pointer.
+
+ Limit - a variable to supply the maximum length of the search and to receive the new
+ lemit after the search.
+
+Return Value:
+
+ Length of the data between current and next logical device tags, ie the data length
+ of the current logical device.
+ In case there is no 'next' logical device tag, the returned *CardData = NULL,
+ *Limit = zero and the data length of current logical tag is returned as function
+ returned value.
+
+--*/
+{
+ UCHAR tag;
+ USHORT size;
+ LONG l;
+ ULONG retLength;
+ PUCHAR p;
+ BOOLEAN atIdTag = FALSE;;
+
+ p = *CardData;
+ l = *Limit;
+ tag = *p;
+ retLength = 0;
+ while (tag != TAG_COMPLETE_END && l > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *((PUSHORT)(p + 1));
+ size += 3; // length of large tag
+ }
+
+ p += size;
+ retLength += size;
+ l -= size;
+ tag = *p;
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ *CardData = p;
+ *Limit = l;
+ return retLength;
+ }
+ }
+ *CardData = NULL;
+ *Limit = 0;
+ if (tag == TAG_COMPLETE_END) {
+ return (retLength + 2); // add 2 for the length of end tag descriptor
+ } else {
+ return 0;
+ }
+}
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber,
+ IN BOOLEAN Activate
+ )
+
+/*++
+
+Routine Description:
+
+ This function selects the logical logical device in the specified device.
+
+Arguments:
+
+ Csn - Supplies a CardSelectNumber to select the card.
+
+ LogicalDeviceNumber - supplies a logical device number to select the logical device.
+
+ Activate - supplies a BOOLEAN variable to specify if the logical device should be
+ enabled.
+
+Return Value:
+
+ None
+--*/
+{
+ UCHAR tmp;
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Send WAKE[CSN] to force the card into config state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(Csn);
+
+ //
+ // Select the logical device.
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(LogicalDeviceNumber);
+ if (Activate) {
+
+ //
+ // If we need to activate the logical device, disable its io range check and
+ // then enable the device.
+ //
+
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+ PipWriteAddress(ACTIVATE_PORT);
+ PipWriteData(1);
+ }
+}
+
+VOID
+PipReadCardResourceDataBytes (
+ IN USHORT BytesToRead,
+ IN PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads specified number of bytes of card resource data .
+
+Arguments:
+
+ BytesToRead - supplies number of bytes to read.
+
+ Buffer - supplies a pointer to a buffer to receive the read bytes.
+
+Return Value:
+
+ None
+--*/
+{
+ USHORT i;
+ PUCHAR p;
+
+ for (i = 0, p = Buffer; i < BytesToRead; i++, p++) {
+
+ PipWriteAddress(CONFIG_DATA_STATUS_PORT);
+
+ //
+ // Waiting for data ready status bit
+ //
+
+ while ((PipReadData() & 1) != 1) {
+ }
+
+ //
+ // Read the data ...
+ //
+
+ PipWriteAddress(CONFIG_DATA_PORT);
+ *p = PipReadData();
+ }
+
+}
diff --git a/private/ntos/nthals/extender/pnpisa.sur/makefile b/private/ntos/nthals/extender/pnpisa.sur/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/extender/pnpisa.sur/misc.c b/private/ntos/nthals/extender/pnpisa.sur/misc.c
new file mode 100644
index 000000000..df32be4a8
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/misc.c
@@ -0,0 +1,1258 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+ This file contains pnp isa bus extender support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 27-Jusly-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PipDecompressEisaId)
+#pragma alloc_text(INIT,PipOpenRegistryKey)
+#pragma alloc_text(INIT,PipOpenRegistryKeyPersist)
+#pragma alloc_text(INIT,PipGetRegistryValue)
+#pragma alloc_text(INIT,PipOpenCurrentHwProfileDeviceInstanceKey)
+#pragma alloc_text(INIT,PipGetDeviceInstanceCsConfigFlags)
+#pragma alloc_text(INIT,PipRemoveStringFromValueKey)
+#pragma alloc_text(INIT,PipAppendStringToValueKey)
+#pragma alloc_text(INIT,PipServiceInstanceToDeviceInstance)
+#if DBG
+#pragma alloc_text(INIT,PipDebugPrint)
+#pragma alloc_text(INIT,PipDumpIoResourceDescriptor)
+#pragma alloc_text(INIT,PipDumpIoResourceList)
+#pragma alloc_text(INIT,PipDumpCmResourceDescriptor)
+#pragma alloc_text(INIT,PipDumpCmResourceList)
+#endif
+#endif
+
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompressed compressed Eisa Id and returns the Id to caller
+ specified character buffer.
+
+Arguments:
+
+ CompressedId - supplies the compressed Eisa Id.
+
+ EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT c1, c2;
+ LONG i;
+
+ PAGED_CODE();
+
+ CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
+ c1 = c2 = (USHORT)CompressedId;
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ for (i = 2; i >= 0; i--) {
+ *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
+ c1 >>= 5;
+ }
+ EisaId += 3;
+ c1 = c2 = (USHORT)(CompressedId >> 16);
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ sprintf (EisaId, "%04x", c1);
+}
+
+NTSTATUS
+PipOpenRegistryKey(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create
+ )
+
+/*++
+
+Routine Description:
+
+ Opens or creates a VOLATILE registry key using the name passed in based
+ at the BaseHandle node.
+
+Arguments:
+
+ Handle - Pointer to the handle which will contain the registry key that
+ was opened.
+
+ BaseHandle - Handle to the base path from which the key must be opened.
+
+ KeyName - Name of the Key that must be opened/created.
+
+ DesiredAccess - Specifies the desired access that the caller needs to
+ the key.
+
+ Create - Determines if the key is to be created if it does not exist.
+
+Return Value:
+
+ The function value is the final status of the operation.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ ULONG disposition;
+
+ PAGED_CODE();
+
+ //
+ // Initialize the object for the key.
+ //
+
+ InitializeObjectAttributes( &objectAttributes,
+ KeyName,
+ OBJ_CASE_INSENSITIVE,
+ BaseHandle,
+ (PSECURITY_DESCRIPTOR) NULL );
+
+ //
+ // Create the key or open it, as appropriate based on the caller's
+ // wishes.
+ //
+
+ if (Create) {
+ return ZwCreateKey( Handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ } else {
+ return ZwOpenKey( Handle,
+ DesiredAccess,
+ &objectAttributes );
+ }
+}
+NTSTATUS
+PipOpenRegistryKeyPersist(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create,
+ OUT PULONG Disposition OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Opens or creates a PERSIST (non-volatile) registry key using the name
+ passed in based at the BaseHandle node. This name may specify a key
+ that is actually a registry path, in which case each intermediate subkey
+ will be created (if Create is TRUE).
+
+ NOTE: Creating a registry path (i.e., more than one of the keys in the path
+ do not presently exist) requires that a BaseHandle be specified.
+
+Arguments:
+
+ Handle - Pointer to the handle which will contain the registry key that
+ was opened.
+
+ BaseHandle - Optional handle to the base path from which the key must be opened.
+ If KeyName specifies a registry path that must be created, then this parameter
+ must be specified, and KeyName must be a relative path.
+
+ KeyName - Name of the Key that must be opened/created (possibly a registry path)
+
+ DesiredAccess - Specifies the desired access that the caller needs to
+ the key.
+
+ Create - Determines if the key is to be created if it does not exist.
+
+ Disposition - If Create is TRUE, this optional pointer receives a ULONG indicating
+ whether the key was newly created:
+
+ REG_CREATED_NEW_KEY - A new Registry Key was created
+ REG_OPENED_EXISTING_KEY - An existing Registry Key was opened
+
+Return Value:
+
+ The function value is the final status of the operation.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ ULONG disposition, baseHandleIndex = 0, keyHandleIndex = 1, closeBaseHandle;
+ HANDLE handles[2];
+ BOOLEAN continueParsing;
+ PWCHAR pathEndPtr, pathCurPtr, pathBeginPtr;
+ ULONG pathComponentLength;
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ InitializeObjectAttributes(&objectAttributes,
+ KeyName,
+ OBJ_CASE_INSENSITIVE,
+ BaseHandle,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+ if(Create) {
+ //
+ // Attempt to create the path as specified. We have to try it this
+ // way first, because it allows us to create a key without a BaseHandle
+ // (if only the last component of the registry path is not present).
+ //
+ status = ZwCreateKey(&(handles[keyHandleIndex]),
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition
+ );
+
+ if(!((status == STATUS_OBJECT_NAME_NOT_FOUND) && ARGUMENT_PRESENT(BaseHandle))) {
+ //
+ // Then either we succeeded, or failed, but there's nothing we can do
+ // about it. In either case, prepare to return.
+ //
+ goto PrepareForReturn;
+ }
+
+ } else {
+ //
+ // Simply attempt to open the path, as specified.
+ //
+ return ZwOpenKey(Handle,
+ DesiredAccess,
+ &objectAttributes
+ );
+ }
+
+ //
+ // If we get to here, then there must be more than one element of the
+ // registry path that does not currently exist. We will now parse the
+ // specified path, extracting each component and doing a ZwCreateKey on it.
+ //
+ handles[baseHandleIndex] = NULL;
+ handles[keyHandleIndex] = BaseHandle;
+ closeBaseHandle = 0;
+ continueParsing = TRUE;
+ pathBeginPtr = KeyName->Buffer;
+ pathEndPtr = (PWCHAR)((PCHAR)pathBeginPtr + KeyName->Length);
+ status = STATUS_SUCCESS;
+
+ while(continueParsing) {
+ //
+ // There's more to do, so close the previous base handle (if necessary),
+ // and replace it with the current key handle.
+ //
+ if(closeBaseHandle > 1) {
+ ZwClose(handles[baseHandleIndex]);
+ }
+ baseHandleIndex = keyHandleIndex;
+ keyHandleIndex = (keyHandleIndex + 1) & 1; // toggle between 0 and 1.
+ handles[keyHandleIndex] = NULL;
+
+ //
+ // Extract next component out of the specified registry path.
+ //
+ for(pathCurPtr = pathBeginPtr;
+ ((pathCurPtr < pathEndPtr) && (*pathCurPtr != OBJ_NAME_PATH_SEPARATOR));
+ pathCurPtr++);
+
+ if (pathComponentLength = (PCHAR)pathCurPtr - (PCHAR)pathBeginPtr) {
+ //
+ // Then we have a non-empty path component (key name). Attempt
+ // to create this key.
+ //
+ unicodeString.Buffer = pathBeginPtr;
+ unicodeString.Length = unicodeString.MaximumLength = (USHORT)pathComponentLength;
+
+ InitializeObjectAttributes(&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ handles[baseHandleIndex],
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+ status = ZwCreateKey(&(handles[keyHandleIndex]),
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition
+ );
+ if (NT_SUCCESS(status)) {
+ //
+ // Increment the closeBaseHandle value, which basically tells us whether
+ // the BaseHandle passed in has been 'shifted out' of our way, so that
+ // we should start closing our base handles when we're finished with them.
+ //
+ closeBaseHandle++;
+ } else {
+ continueParsing = FALSE;
+ continue;
+ }
+ } else {
+ //
+ // Either a path separator ('\') was included at the beginning of
+ // the path, or we hit 2 consecutive separators.
+ //
+ status = STATUS_INVALID_PARAMETER;
+ continueParsing = FALSE;
+ continue;
+ }
+
+ if ((pathCurPtr == pathEndPtr) ||
+ ((pathBeginPtr = pathCurPtr + 1) == pathEndPtr)) {
+ //
+ // Then we've reached the end of the path
+ //
+ continueParsing = FALSE;
+ }
+ }
+
+ if (closeBaseHandle > 1) {
+ ZwClose(handles[baseHandleIndex]);
+ }
+
+PrepareForReturn:
+
+ if (NT_SUCCESS(status)) {
+ *Handle = handles[keyHandleIndex];
+
+ if(ARGUMENT_PRESENT(Disposition)) {
+ *Disposition = disposition;
+ }
+ }
+
+ return status;
+}
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to retrieve the data for a registry key's value.
+ This is done by querying the value of the key with a zero-length buffer
+ to determine the size of the value, and then allocating a buffer and
+ actually querying the value into the buffer.
+
+ It is the responsibility of the caller to free the buffer.
+
+Arguments:
+
+ KeyHandle - Supplies the key handle whose value is to be queried
+
+ ValueName - Supplies the null-terminated Unicode name of the value.
+
+ Information - Returns a pointer to the allocated data buffer.
+
+Return Value:
+
+ The function value is the final status of the query operation.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PKEY_VALUE_FULL_INFORMATION infoBuffer;
+ ULONG keyValueLength;
+
+ PAGED_CODE();
+
+ *Information = NULL;
+ RtlInitUnicodeString( &unicodeString, ValueName );
+
+ //
+ // Figure out how big the data value is so that a buffer of the
+ // appropriate size can be allocated.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ (PVOID) NULL,
+ 0,
+ &keyValueLength );
+ if (status != STATUS_BUFFER_OVERFLOW &&
+ status != STATUS_BUFFER_TOO_SMALL) {
+ return status;
+ }
+
+ //
+ // Allocate a buffer large enough to contain the entire key data value.
+ //
+
+ infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
+ if (!infoBuffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Query the data for the key value.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ infoBuffer,
+ keyValueLength,
+ &keyValueLength );
+ if (!NT_SUCCESS( status )) {
+ ExFreePool( infoBuffer );
+ return status;
+ }
+
+ //
+ // Everything worked, so simply return the address of the allocated
+ // buffer to the caller, who is now responsible for freeing it.
+ //
+
+ *Information = infoBuffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipOpenCurrentHwProfileDeviceInstanceKey(
+ OUT PHANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName,
+ IN ACCESS_MASK DesiredAccess
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the csconfig flags for the specified device
+ which is specified by the instance number under ServiceKeyName\Enum.
+
+Arguments:
+
+ ServiceKeyName - Supplies a pointer to the name of the subkey in the
+ system service list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
+ that caused the driver to load. This is the RegistryPath parameter
+ to the DriverEntry routine.
+
+ Instance - Supplies the instance value under ServiceKeyName\Enum key
+
+ DesiredAccess - Specifies the desired access that the caller needs to
+ the key.
+
+ Create - Determines if the key is to be created if it does not exist.
+
+Return Value:
+
+ status
+
+--*/
+
+{
+ NTSTATUS status;
+ UNICODE_STRING unicodeString;
+ HANDLE profileEnumHandle;
+
+ //
+ // See if we can open the device instance key of current hardware profile
+ //
+ RtlInitUnicodeString (
+ &unicodeString,
+ L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT\\SYSTEM\\CURRENTCONTROLSET\\ENUM"
+ );
+ status = PipOpenRegistryKey(&profileEnumHandle,
+ NULL,
+ &unicodeString,
+ KEY_READ,
+ FALSE
+ );
+ if (NT_SUCCESS(status)) {
+ status = PipOpenRegistryKey(Handle,
+ profileEnumHandle,
+ DeviceInstanceName,
+ DesiredAccess,
+ FALSE
+ );
+ ZwClose(profileEnumHandle);
+ }
+ return status;
+}
+
+NTSTATUS
+PipGetDeviceInstanceCsConfigFlags(
+ IN PUNICODE_STRING DeviceInstance,
+ OUT PULONG CsConfigFlags
+ )
+
+/*++
+
+Routine Description:
+
+ This routine retrieves the csconfig flags for the specified device
+ which is specified by the instance number under ServiceKeyName\Enum.
+
+Arguments:
+
+ ServiceKeyName - Supplies a pointer to the name of the subkey in the
+ system service list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
+ that caused the driver to load.
+
+// Instance - Supplies the instance value under ServiceKeyName\Enum key
+//
+ CsConfigFlags - Supplies a variable to receive the device's CsConfigFlags
+
+Return Value:
+
+ status
+
+--*/
+
+{
+ NTSTATUS status;
+ HANDLE handle;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+
+ *CsConfigFlags = 0;
+
+ status = PipOpenCurrentHwProfileDeviceInstanceKey(&handle,
+ DeviceInstance,
+ KEY_READ
+ );
+ if(NT_SUCCESS(status)) {
+ status = PipGetRegistryValue(handle,
+ L"CsConfigFlags",
+ &keyValueInformation
+ );
+ if(NT_SUCCESS(status)) {
+ if((keyValueInformation->Type == REG_DWORD) &&
+ (keyValueInformation->DataLength >= sizeof(ULONG))) {
+ *CsConfigFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
+ }
+ ExFreePool(keyValueInformation);
+ }
+ ZwClose(handle);
+ }
+ return status;
+}
+
+NTSTATUS
+PipRemoveStringFromValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine remove a string from a value entry specified by ValueName
+ under an already opened registry handle. Note, this routine will not
+ delete the ValueName entry even it becomes empty after the removal.
+
+Parameters:
+
+ Handle - Supplies the handle to a registry key whose value entry will
+ be modified.
+
+ ValueName - Supplies a unicode string to specify the value entry.
+
+ String - Supplies a unicode string to remove from value entry.
+
+Return Value:
+
+ Status code that indicates whether or not the function was successful.
+
+--*/
+
+{
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ UNICODE_STRING unicodeString;
+ PWSTR nextString, currentString;
+ ULONG length, leftLength;
+ NTSTATUS status;
+ BOOLEAN found = FALSE;
+
+ if (String == NULL || String->Length / sizeof(WCHAR) == 0) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Read registry value entry data
+ //
+
+ status = PipGetRegistryValue(Handle, ValueName, &keyValueInformation);
+
+ if (!NT_SUCCESS( status )) {
+ return status;
+ } else if ((keyValueInformation->Type != REG_MULTI_SZ) ||
+ (keyValueInformation->DataLength == 0)) {
+
+ ExFreePool(keyValueInformation);
+ return (keyValueInformation->Type == REG_MULTI_SZ) ? STATUS_SUCCESS
+ : STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Scan through the multi_sz string to find the matching string
+ // and remove it.
+ //
+
+ status = STATUS_SUCCESS;
+ currentString = (PWSTR)KEY_VALUE_DATA(keyValueInformation);
+ leftLength = keyValueInformation->DataLength;
+ while (!found && leftLength >= String->Length + sizeof(WCHAR)) {
+ unicodeString.Buffer = currentString;
+ length = wcslen( currentString ) * sizeof( WCHAR );
+ unicodeString.Length = (USHORT)length;
+ length += sizeof(UNICODE_NULL);
+ unicodeString.MaximumLength = (USHORT)length;
+ nextString = currentString + length / sizeof(WCHAR);
+ leftLength -= length;
+
+ if (RtlEqualUnicodeString(&unicodeString, String, TRUE)) {
+ found = TRUE;
+ RtlMoveMemory(currentString, nextString, leftLength);
+ RtlInitUnicodeString(&unicodeString, ValueName);
+ status = ZwSetValueKey(
+ Handle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ KEY_VALUE_DATA(keyValueInformation),
+ keyValueInformation->DataLength - length
+ );
+ break;
+ } else {
+ currentString = nextString;
+ }
+ }
+ ExFreePool(keyValueInformation);
+ return status;
+}
+
+NTSTATUS
+PipAppendStringToValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String,
+ IN BOOLEAN Create
+ )
+
+/*++
+
+Routine Description:
+
+ This routine appends a string to a value entry specified by ValueName
+ under an already opened registry handle. If the ValueName is not present
+ and Create is TRUE, a new value entry will be created using the name
+ ValueName.
+
+Parameters:
+
+ Handle - Supplies the handle to a registry key whose value entry will
+ be modified.
+
+ ValueName - Supplies a pointer to a string to specify the value entry.
+
+ String - Supplies a unicode string to append to the value entry.
+
+ Create - Supplies a BOOLEAN variable to indicate if the ValueName
+ value entry should be created if it is not present.
+
+Return Value:
+
+ Status code that indicates whether or not the function was successful.
+
+--*/
+
+{
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ PWSTR destinationString, p;
+ UNICODE_STRING unicodeValueName;
+ ULONG size;
+ NTSTATUS status;
+
+ if ( !String || (String->Length < sizeof(WCHAR)) ) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Read registry value entry data
+ //
+
+ status = PipGetRegistryValue(Handle, ValueName, &keyValueInformation);
+
+ if(!NT_SUCCESS( status )) {
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND && Create) {
+
+ //
+ // if no valid entry exists and user said ok to create one
+ //
+
+ keyValueInformation = NULL;
+ } else {
+ return status;
+ }
+ } else if(keyValueInformation->Type != REG_MULTI_SZ) {
+
+ ExFreePool(keyValueInformation);
+
+ if(Create) {
+ keyValueInformation = NULL;
+ } else {
+ return STATUS_INVALID_PARAMETER_2;
+ }
+
+ } else if(keyValueInformation->DataLength < sizeof(WCHAR)) {
+
+ ExFreePool(keyValueInformation);
+ keyValueInformation = NULL;
+ }
+
+ //
+ // Allocate a buffer to hold new data for the specified key value entry
+ // Make sure the buffer is at least an empty MULTI_SZ big.
+ //
+
+ if (keyValueInformation) {
+ size = keyValueInformation->DataLength + String->Length + sizeof (UNICODE_NULL);
+ } else {
+ size = String->Length + 2 * sizeof(UNICODE_NULL);
+ }
+
+ destinationString = p = (PWSTR)ExAllocatePool(PagedPool, size);
+ if (destinationString == NULL) {
+ if (keyValueInformation) {
+ ExFreePool(keyValueInformation);
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Copy the existing data to our newly allocated buffer, if any
+ //
+
+ if (keyValueInformation) {
+
+ //
+ // Note we need to remove a UNICODE_NULL because the
+ // MULTI_SZ has two terminating UNICODE_NULL.
+ //
+
+ RtlMoveMemory(p,
+ KEY_VALUE_DATA(keyValueInformation),
+ keyValueInformation->DataLength - sizeof(WCHAR)
+ );
+ p += keyValueInformation->DataLength / sizeof(WCHAR) - 1;
+
+ ExFreePool(keyValueInformation);
+ }
+
+ //
+ // Append the user specified unicode string to our buffer
+ //
+ RtlMoveMemory(p,
+ String->Buffer,
+ String->Length
+ );
+ p += String->Length / sizeof(WCHAR);
+ *p = UNICODE_NULL;
+ p++;
+ *p = UNICODE_NULL;
+
+ //
+ // Finally write the data to the specified registy value entry
+ //
+
+ RtlInitUnicodeString(&unicodeValueName, ValueName);
+ status = ZwSetValueKey(
+ Handle,
+ &unicodeValueName,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ destinationString,
+ size
+ );
+
+ ExFreePool(destinationString);
+ return status;
+}
+
+NTSTATUS
+PipServiceInstanceToDeviceInstance (
+ IN PUNICODE_STRING RegistryPath,
+ IN ULONG ServiceInstanceOrdinal,
+ OUT PUNICODE_STRING DeviceInstanceRegistryPath OPTIONAL,
+ OUT PHANDLE DeviceInstanceHandle OPTIONAL,
+ IN ACCESS_MASK DesiredAccess
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the service node enum entry to find the desired device instance
+ under the System\Enum tree. It then optionally returns the registry path of the
+ specified device instance (relative to HKLM\System\Enum) and an open handle
+ to that registry key.
+
+ It is the caller's responsibility to close the handle returned if
+ DeviceInstanceHandle is supplied, and also to free the (PagedPool) memory
+ allocated for the unicode string buffer of DeviceInstanceRegistryPath, if
+ supplied.
+
+Parameters:
+
+ RegistryPath - Supplies the name of the service entry that controls
+ the device instance. This is the registry path passed to DriverEntry.
+
+ ServiceInstanceOrdinal - Supplies the instance value under the service entry's
+ volatile Enum subkey that references the desired device instance.
+
+ DeviceInstanceRegistryPath - Optionally, supplies a pointer to a unicode string
+ that will be initialized with the registry path (relative to HKLM\System\Enum)
+ to the device instance key.
+
+ DeviceInstanceHandle - Optionally, supplies a pointer to a variable that will
+ receive a handle to the opened device instance registry key.
+
+ DesiredAccess - If DeviceInstanceHandle is specified (i.e., the device instance
+ key is to be opened), then this variable specifies the access that is needed
+ to this key.
+
+Return Value:
+
+ NT status code indicating whether the function was successful.
+
+--*/
+
+{
+ WCHAR unicodeBuffer[20];
+ UNICODE_STRING unicodeKeyName, unicodeString;
+ NTSTATUS status;
+ HANDLE handle, handlex;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ PWSTR buffer;
+
+ //
+ // Open registry ServiceKeyName\Enum branch
+ //
+
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ RegistryPath,
+ KEY_ALL_ACCESS,
+ FALSE
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open Service RegistryPath\n"));
+ return status;
+ }
+
+ RtlInitUnicodeString(&unicodeKeyName, L"ENUM");
+ status = PipOpenRegistryKey(&handlex,
+ handle,
+ &unicodeKeyName,
+ KEY_READ,
+ FALSE
+ );
+ ZwClose(handle);
+ if (!NT_SUCCESS( status )) {
+
+ //
+ // There is no registry key for the ServiceKeyName\Enum information.
+ //
+
+ return status;
+ }
+
+ //
+ // Read a path to System\Enum hardware tree branch specified by the service
+ // instance ordinal
+ //
+
+ swprintf(unicodeBuffer, L"%u", ServiceInstanceOrdinal);
+ status = PipGetRegistryValue ( handlex,
+ unicodeBuffer,
+ &keyValueInformation
+ );
+
+ ZwClose(handlex);
+ if (!NT_SUCCESS( status )) {
+ return status;
+ } else {
+ if (keyValueInformation->Type == REG_SZ) {
+ unicodeKeyName.Buffer = (PWSTR)KEY_VALUE_DATA(keyValueInformation);
+ unicodeKeyName.MaximumLength = (USHORT)keyValueInformation->DataLength;
+ unicodeKeyName.Length = unicodeKeyName.MaximumLength - sizeof(UNICODE_NULL);
+ if(!unicodeKeyName.Length) {
+ status = STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ } else {
+ status = STATUS_INVALID_PLUGPLAY_DEVICE_PATH;
+ }
+
+ if(!NT_SUCCESS(status)) {
+ goto PrepareForReturn;
+ }
+ }
+
+ //
+ // If the DeviceInstanceHandle argument was specified, open the device instance
+ // key under HKLM\System\CurrentControlSet\Enum
+ //
+
+ if (ARGUMENT_PRESENT(DeviceInstanceHandle)) {
+ RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ &unicodeString,
+ KEY_READ,
+ FALSE
+ );
+
+ if (NT_SUCCESS( status )) {
+
+ status = PipOpenRegistryKey (DeviceInstanceHandle,
+ handle,
+ &unicodeKeyName,
+ DesiredAccess,
+ FALSE
+ );
+ ZwClose(handle);
+ }
+
+ if (!NT_SUCCESS( status )) {
+ goto PrepareForReturn;
+ }
+ }
+
+ //
+ // If the DeviceInstanceRegistryPath argument was specified, then store a
+ // copy of the device instance path in the supplied unicode string variable.
+ //
+
+ if (ARGUMENT_PRESENT(DeviceInstanceRegistryPath)) {
+
+ buffer = (PWSTR)ExAllocatePool(PagedPool, unicodeKeyName.MaximumLength);
+ if (!buffer) {
+ if(ARGUMENT_PRESENT(DeviceInstanceHandle)) {
+ ZwClose(*DeviceInstanceHandle);
+ }
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(buffer, unicodeKeyName.Buffer, unicodeKeyName.MaximumLength);
+ DeviceInstanceRegistryPath->Buffer = buffer;
+ DeviceInstanceRegistryPath->Length = unicodeKeyName.Length;
+ DeviceInstanceRegistryPath->MaximumLength = unicodeKeyName.MaximumLength;
+ }
+ }
+
+PrepareForReturn:
+
+ ExFreePool(keyValueInformation);
+ return status;
+}
+#if DBG
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This routine displays debugging message or causes a break.
+
+Arguments:
+
+ Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
+ DEBUG_BREAK - displays message and break.
+
+ DebugMessage - supplies a pointer to the debugging message.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ if (Level == DEBUG_BREAK) {
+ DbgBreakPoint();
+ }
+
+ va_end(ap);
+}
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR c = ' ';
+
+ if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
+ c = 'A';
+ } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
+ c = 'P';
+ }
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
+ Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
+ Desc->u.Port.Alignment,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
+ Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
+ Desc->u.Memory.Alignment,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Interrupt.MinimumVector,
+ Desc->u.Interrupt.MaximumVector
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Dma.MinimumChannel,
+ Desc->u.Dma.MaximumChannel
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays Io resource requirements list.
+
+Arguments:
+
+ IoList - supplies a pointer to the Io resource requirements list to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIO_RESOURCE_LIST resList;
+ PIO_RESOURCE_DESCRIPTOR resDesc;
+ ULONG listCount, count, i, j;
+
+ if (IoList == NULL) {
+ return;
+ }
+ DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
+ listCount = IoList->AlternativeLists;
+ resList = &IoList->List[0];
+ for (i = 0; i < listCount; i++) {
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
+ resList->Revision, resList->Count);
+ resDesc = &resList->Descriptors[0];
+ count = resList->Count;
+ for (j = 0; j < count; j++) {
+ PipDumpIoResourceDescriptor(" ", resDesc);
+ resDesc++;
+ }
+ resList = (PIO_RESOURCE_LIST) resDesc;
+ }
+}
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
+ Indent,
+ Desc->u.Interrupt.Level,
+ Desc->u.Interrupt.Vector,
+ Desc->u.Interrupt.Affinity
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA Channel: %x, Port: %x\n",
+ Indent,
+ Desc->u.Dma.Channel,
+ Desc->u.Dma.Port
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays CM resource list.
+
+Arguments:
+
+ CmList - supplies a pointer to CM resource list
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG count, i;
+
+ if (CmList) {
+ fullDesc = &CmList->List[0];
+ DbgPrint("Pnp Bios Cm Resource List -\n");
+ DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
+ partialDesc = &fullDesc->PartialResourceList;
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
+ partialDesc->Revision, partialDesc->Count);
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ PipDumpCmResourceDescriptor(" ", desc);
+ desc++;
+ }
+ }
+}
+#endif
diff --git a/private/ntos/nthals/extender/pnpisa.sur/pbios.h b/private/ntos/nthals/extender/pnpisa.sur/pbios.h
new file mode 100644
index 000000000..6c1b2e333
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/pbios.h
@@ -0,0 +1,241 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbiosp.h
+
+Abstract:
+
+ PnP BIOS/ISA configuration data definitions
+
+Author:
+
+ Shie-Lin Tzong (shielint) April 12, 1995
+
+Revision History:
+
+--*/
+
+//#include "nthal.h"
+//#include "hal.h"
+
+//
+// Constants
+//
+
+#define SMALL_RESOURCE_TAG (UCHAR)(0x00)
+#define LARGE_RESOURCE_TAG (UCHAR)(0x80)
+#define SMALL_TAG_MASK 0xf8
+#define SMALL_TAG_SIZE_MASK 7
+
+//
+// Small Resouce Tags with length bits stripped off
+//
+
+#define TAG_VERSION 0x08
+#define TAG_LOGICAL_ID 0x10
+#define TAG_COMPATIBLE_ID 0x18
+#define TAG_IRQ 0x20
+#define TAG_DMA 0x28
+#define TAG_START_DEPEND 0x30
+#define TAG_END_DEPEND 0x38
+#define TAG_IO 0x40
+#define TAG_IO_FIXED 0x48
+#define TAG_VENDOR 0x70
+#define TAG_END 0x78
+
+//
+// Large Resouce Tags
+//
+
+#define TAG_MEMORY 0x81
+#define TAG_ANSI_ID 0x82
+#define TAG_UNICODE_ID 0x83
+#define TAG_LVENDOR 0x84
+#define TAG_MEMORY32 0x85
+#define TAG_MEMORY32_FIXED 0x86
+
+//
+// Complete TAG if applicable.
+//
+
+#define TAG_COMPLETE_COMPATIBLE_ID 0x1C
+#define TAG_COMPLETE_END 0x79
+
+#include "pshpack1.h"
+
+//
+// PNP ISA Port descriptor definition
+//
+
+typedef struct _PNP_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01000111B, small item name = 08, length = 7
+ UCHAR Information; // bit [0] = 1 device decodes full 16 bit addr
+ // = 0 device decodes ISA addr bits[9-0]
+ USHORT MinimumAddress;
+ USHORT MaximumAddress;
+ UCHAR Alignment; // Increment in 1 byte blocks
+ UCHAR Length; // # contiguous Port requested
+} PNP_PORT_DESCRIPTOR, *PPNP_PORT_DESCRIPTOR;
+
+//
+// PNP ISA fixed Port descriptor definition
+//
+
+typedef struct _PNP_FIXED_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01001011B, small item name = 09, length = 3
+ USHORT MinimumAddress;
+ UCHAR Length; // # contiguous Port requested
+} PNP_FIXED_PORT_DESCRIPTOR, *PPNP_FIXED_PORT_DESCRIPTOR;
+
+//
+// PNP ISA IRQ descriptor definition
+//
+
+typedef struct _PNP_IRQ_DESCRIPTOR_ {
+ UCHAR Tag; // 0010001XB small item name = 4 length = 2/3
+ USHORT IrqMask; // bit 0 is irq 0
+ UCHAR Information; // Optional
+} PNP_IRQ_DESCRIPTOR, *PPNP_IRQ_DESCRIPTOR;
+
+//
+// Masks for PNP_IRQ_DESCRIPTOR Information byte
+//
+
+#define PNP_IRQ_LEVEL_MASK 0xC
+#define PNP_IRQ_EDGE_MASK 0x3
+
+//
+// PNP ISA DMA descriptor definition
+//
+
+typedef struct _PNP_DMA_DESCRIPTOR_ {
+ UCHAR Tag; // 00101010B, small item name = 05, length = 2
+ UCHAR ChannelMask; // bit 0 is channel 0
+ UCHAR Flags; // see spec
+} PNP_DMA_DESCRIPTOR, *PPNP_DMA_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY descriptor
+//
+
+typedef struct _PNP_MEMORY_DESCRIPTOR_ {
+ UCHAR Tag; // 10000001B, Large item name = 1
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ USHORT MinimumAddress; // address bit [8-23]
+ USHORT MaximumAddress; // address bit [8-23]
+ USHORT Alignment; // 0x0000 = 64KB
+ USHORT MemorySize; // In 256 byte blocks
+} PNP_MEMORY_DESCRIPTOR, *PPNP_MEMORY_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY32 descriptor
+//
+
+typedef struct _PNP_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000101B, Large item name = 5
+ USHORT Length; // Length of the descriptor = 17
+ UCHAR Information; // See def below
+ ULONG MinimumAddress; // 32 bit addr
+ ULONG MaximumAddress; // 32 bit addr
+ ULONG Alignment; // 32 bit alignment
+ ULONG MemorySize; // 32 bit length
+} PNP_MEMORY32_DESCRIPTOR, *PPNP_MEMORY32_DESCRIPTOR;
+
+//
+// PNP ISA FIXED MEMORY32 descriptor
+//
+
+typedef struct _PNP_FIXED_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000110B, Large item name = 6
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ ULONG BaseAddress; // 32 bit addr
+ ULONG MemorySize; // 32 bit length
+} PNP_FIXED_MEMORY32_DESCRIPTOR, *PPNP_FIXED_MEMORY32_DESCRIPTOR;
+
+#define PNP_MEMORY_ROM_MASK 0x40
+#define PNP_MEMORY_SHADOWABLE_MASK 0x20
+#define PNP_MEMORY_CONTROL_MASK 0x18
+ #define PNP_MEMORY_CONTROL_8BIT 00
+ #define PNP_MEMORY_CONTROL_16BIT 01
+ #define PNP_MEMORY_CONTROL_8AND16BIT 02
+ #define PNP_MEMORY_CONTROL_32BIT 03
+#define PNP_MEMORY_SUPPORT_TYPE_MASK 04
+#define PNP_MEMORY_CACHE_SUPPORT_MASK 02
+#define PNP_MEMORY_WRITE_STATUS_MASK 01
+
+#define UNKNOWN_DOCKING_IDENTIFIER 0xffffffff
+#define UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
+#define FUNCTION_NOT_SUPPORTED 0x82
+#define SYSTEM_NOT_DOCKED 0x87
+
+//
+// Pnp BIOS device node structure
+//
+
+typedef struct _PNP_BIOS_DEVICE_NODE {
+ USHORT Size;
+ UCHAR Node;
+ ULONG ProductId;
+ UCHAR DeviceType[3];
+ USHORT DeviceAttributes;
+ // followed by AllocatedResourceBlock, PossibleResourceBlock
+ // and CompatibleDeviceId
+} PNP_BIOS_DEVICE_NODE, *PPNP_BIOS_DEVICE_NODE;
+
+//
+// DeviceType definition
+//
+
+#define BASE_TYPE_DOCKING_STATION 0xA
+
+//
+// Device attributes definitions
+//
+
+#define DEVICE_DOCKING 0x20
+#define DEVICE_REMOVABLE 0x40
+
+//
+// Pnp BIOS Installation check
+//
+
+typedef struct _PNP_BIOS_INSTALLATION_CHECK {
+ UCHAR Signature[4]; // $PnP (ascii)
+ UCHAR Revision;
+ UCHAR Length;
+ USHORT ControlField;
+ UCHAR Checksum;
+ ULONG EventFlagAddress; // Physical address
+ USHORT RealModeEntryOffset;
+ USHORT RealModeEntrySegment;
+ USHORT ProtectedModeEntryOffset;
+ ULONG ProtectedModeCodeBaseAddress;
+ ULONG OemDeviceId;
+ USHORT RealModeDataBaseAddress;
+ ULONG ProtectedModeDataBaseAddress;
+} PNP_BIOS_INSTALLATION_CHECK, *PPNP_BIOS_INSTALLATION_CHECK;
+
+#include "poppack.h"
+
+//
+// Pnp BIOS ControlField masks
+//
+
+#define PNP_BIOS_CONTROL_MASK 0x3
+#define PNP_BIOS_EVENT_NOT_SUPPORTED 0
+#define PNP_BIOS_EVENT_POLLING 1
+#define PNP_BIOS_EVENT_ASYNC 2
+
+//
+// Pnp Bios event
+//
+
+#define ABOUT_TO_CHANGE_CONFIG 1
+#define DOCK_CHANGED 2
+#define SYSTEM_DEVICE_CHANGED 3
+#define CONFIG_CHANGE_FAILED 4
diff --git a/private/ntos/nthals/extender/pnpisa.sur/pnpisa.h b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.h
new file mode 100644
index 000000000..15b12eeda
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.h
@@ -0,0 +1,164 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pnpisa.h
+
+Abstract:
+
+ This module contins definitions/declarations for PNP ISA related
+ definitions.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-12-1995
+
+Revision History:
+
+--*/
+
+//
+// External references
+//
+
+extern PUCHAR PipReadDataPort;
+extern PUCHAR PipAddressPort;
+extern PUCHAR PipCommandPort;
+
+//
+// Definitions
+//
+
+#ifndef NEC_98
+
+#define ADDRESS_PORT 0x0279
+#define COMMAND_PORT 0x0a79
+
+#else
+
+#define ADDRESS_PORT 0x0259
+#define COMMAND_PORT 0x0a59
+
+#endif // NEC_98
+
+//
+// Plug and Play Card Control Registers
+//
+
+#define SET_READ_DATA_PORT 0x00
+#define SERIAL_ISOLATION_PORT 0x01
+#define CONFIG_CONTROL_PORT 0x02
+#define WAKE_CSN_PORT 0x03
+#define CONFIG_DATA_PORT 0x04
+#define CONFIG_DATA_STATUS_PORT 0x05
+#define SET_CSN_PORT 0x06
+#define LOGICAL_DEVICE_PORT 0x07
+
+//
+// Plug and Play Logical Device Control Registers
+//
+
+#define ACTIVATE_PORT 0x30
+#define IO_RANGE_CHECK_PORT 0x31
+
+//
+// Config Control command
+//
+
+#define CONTROL_WAIT_FOR_KEY 0x02
+#define CONTROL_RESET_CSN 0x04
+
+//
+// Memory Space Configuration
+//
+
+#define NUMBER_MEMORY_DESCRIPTORS 4
+#define ADDRESS_MEMORY_BASE 0x40
+#define ADDRESS_MEMORY_INCR 0x08
+#define ADDRESS_MEMORY_HI 0x00
+#define ADDRESS_MEMORY_LO 0x01
+#define ADDRESS_MEMORY_CTL 0x02
+#define ADDRESS_MEMORY_CTL_LIMIT 0x01
+#define ADDRESS_MEMORY_UPPER_HI 0x03
+#define ADDRESS_MEMORY_UPPER_LO 0x04
+
+//
+// 32 Bit Memory Space Configuration
+//
+
+#define NUMBER_32_MEMORY_DESCRIPTORS 4
+#define ADDRESS_32_MEMORY_BASE(x) ((PUCHAR)(0x70+((x)*0x10)+((x==0) ? 6 : 0)))
+#define ADDRESS_32_MEMORY_B3 0x0
+#define ADDRESS_32_MEMORY_B2 0x1
+#define ADDRESS_32_MEMORY_B1 0x2
+#define ADDRESS_32_MEMORY_B0 0x3
+#define ADDRESS_32_MEMORY_CTL 0x4
+#define ADDRESS_32_MEMORY_E3 0x5
+#define ADDRESS_32_MEMORY_E2 0x6
+#define ADDRESS_32_MEMORY_E1 0x7
+#define ADDRESS_32_MEMORY_E0 0x8
+
+//
+// Io Space Configuration
+//
+
+#define NUMBER_IO_DESCRIPTORS 8
+#define ADDRESS_IO_BASE 0x60
+#define ADDRESS_IO_INCR 0x02
+#define ADDRESS_IO_BASE_HI 0x00
+#define ADDRESS_IO_BASE_LO 0x01
+
+//
+// Interrupt Configuration
+//
+
+#define NUMBER_IRQ_DESCRIPTORS 2
+#define ADDRESS_IRQ_BASE 0x70
+#define ADDRESS_IRQ_INCR 0x02
+#define ADDRESS_IRQ_VALUE 0x00
+#define ADDRESS_IRQ_TYPE 0x01
+
+//
+// DMA Configuration
+//
+
+#define NUMBER_DMA_DESCRIPTORS 2
+#define ADDRESS_DMA_BASE 0x74
+#define ADDRESS_DMA_INCR 0x01
+#define ADDRESS_DMA_VALUE 0x00
+#define NO_DMA 0x04
+
+//
+// 9 byte serial identifier of a PNP ISA Card
+//
+
+#include "pshpack1.h"
+typedef struct _SERIAL_IDENTIFIER_ {
+ ULONG VenderId;
+ ULONG SerialNumber;
+ UCHAR Checksum;
+} SERIAL_IDENTIFIER, *PSERIAL_IDENTIFIER;
+#include "poppack.h"
+
+//
+// Misc. definitions
+//
+
+#define MIN_READ_DATA_PORT 0x200
+#define MAX_READ_DATA_PORT 0x3ff
+#define MAX_CHARACTER_LENGTH 255
+#define NUMBER_CARD_ID_BYTES 9
+#define NUMBER_CARD_ID_BITS (NUMBER_CARD_ID_BYTES * 8)
+#define CHECKSUMED_BITS 64
+#define LFSR_SEED 0x6A
+#define ISOLATION_TEST_BYTE_1 0x55
+#define ISOLATION_TEST_BYTE_2 0xAA
+
+#define PipWriteAddress(data) WRITE_PORT_UCHAR (PipAddressPort, (UCHAR)(data))
+#define PipWriteData(data) WRITE_PORT_UCHAR (PipCommandPort, (UCHAR)(data))
+#define PipReadData() READ_PORT_UCHAR (PipReadDataPort)
+
+
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc
new file mode 100644
index 000000000..4422bbfd2
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "PNP ISA Driver"
+#define VER_INTERNALNAME_STR "pnpisa.sys"
+#define VER_ORIGINALFILENAME_STR "pnpisa.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pnpisa.sur/resource.c b/private/ntos/nthals/extender/pnpisa.sur/resource.c
new file mode 100644
index 000000000..4e81668a5
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/resource.c
@@ -0,0 +1,680 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ This module contains the high level device resources support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-27-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "pbios.h"
+
+#define IDBG 0
+
+#pragma alloc_text(INIT,PipGetCardIdentifier)
+#pragma alloc_text(INIT,PipGetFunctionIdentifier)
+#pragma alloc_text(INIT,PipGetCompatibleDeviceId)
+#pragma alloc_text(INIT,PipQueryDeviceId)
+#pragma alloc_text(INIT,PipQueryDeviceUniqueId)
+#pragma alloc_text(INIT,PipQueryDeviceResources)
+#pragma alloc_text(INIT,PipQueryDeviceResourceRequirements)
+#pragma alloc_text(INIT,PipSetDeviceResources)
+
+NTSTATUS
+PipGetCardIdentifier (
+ PUCHAR CardData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ This function returns the identifier for a pnpisa card.
+
+Arguments:
+
+ CardData - supplies a pointer to the pnp isa device data.
+
+ Buffer - supplies a pointer to variable to receive a pointer to the Id.
+
+ BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ UCHAR tag;
+ LONG size, length;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ PCHAR ansiBuffer;
+
+ *Buffer = NULL;
+ *BufferLength = 0;
+
+ tag = *CardData;
+
+ //
+ // Make sure CardData does *NOT* point to a Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ DbgPrint("PipGetCardIdentifier: CardData is at a Logical Id tag\n");
+ return status;
+ }
+
+ //
+ // Find the resource descriptor which describle identifier string
+ //
+
+ do {
+
+ //
+ // Do we find the identifer resource tag?
+ //
+
+ if (tag == TAG_ANSI_ID) {
+ CardData++;
+ length = *(PUSHORT)CardData;
+ CardData += 2;
+ ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
+ if (ansiBuffer == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ RtlMoveMemory(ansiBuffer, CardData, length);
+ ansiBuffer[length] = 0;
+ RtlInitAnsiString(&ansiString, ansiBuffer);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ ExFreePool(ansiBuffer);
+ *Buffer = unicodeString.Buffer;
+ *BufferLength = unicodeString.Length + sizeof(WCHAR);
+ break;
+ }
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(CardData + 1);
+ size += 3; // length of large tag
+ }
+
+ CardData += size;
+ tag = *CardData;
+
+ } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
+
+ return status;
+}
+
+NTSTATUS
+PipGetFunctionIdentifier (
+ PUCHAR DeviceData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp isa identifier for the specified
+ DeviceData/LogicalFunction. The Identifier for a logical function is
+ optional. If no Identifier available , Buffer is set to NULL.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the pnp isa device data.
+
+ Buffer - supplies a pointer to variable to receive a pointer to the Id.
+
+ BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ UCHAR tag;
+ LONG size, length;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ PCHAR ansiBuffer;
+
+ *Buffer = NULL;
+ *BufferLength = 0;
+
+ tag = *DeviceData;
+
+#if DBG
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ DbgPrint("PipGetFunctionIdentifier: DeviceData is not at a Logical Id tag\n");
+ }
+#endif
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ do {
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(DeviceData + 1);
+ size += 3; // length of large tag
+ }
+
+ DeviceData += size;
+ tag = *DeviceData;
+
+ //
+ // Do we find the identifer resource tag?
+ //
+
+ if (tag == TAG_ANSI_ID) {
+ DeviceData++;
+ length = *(PUSHORT)DeviceData;
+ DeviceData += 2;
+ ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
+ if (ansiBuffer == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ RtlMoveMemory(ansiBuffer, DeviceData, length);
+ ansiBuffer[length] = 0;
+ RtlInitAnsiString(&ansiString, ansiBuffer);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ ExFreePool(ansiBuffer);
+ *Buffer = unicodeString.Buffer;
+ *BufferLength = unicodeString.Length + sizeof(WCHAR);
+ break;
+ }
+
+ } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
+
+ return status;
+}
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR *Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp isa id for the specified DeviceData
+ and Id index. If Id index = 0, the Hardware ID will be return; if id
+ index = n, the Nth compatible id will be returned.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the pnp isa device data.
+
+ IdIndex - supplies the index of the compatible id desired.
+
+ Buffer - supplies a pointer to variable to receive a pointer to the compatible Id.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_NO_MORE_ENTRIES;
+ UCHAR tag;
+ ULONG count = 0;
+ LONG size;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ ULONG id;
+
+ tag = *DeviceData;
+
+#if DBG
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
+ }
+#endif
+
+ if (IdIndex == 0) {
+
+ //
+ // Caller is asking for hardware id
+ //
+
+ DeviceData++; // Skip tag
+ id = *(PULONG)DeviceData;
+ status = STATUS_SUCCESS;
+ } else {
+
+ //
+ // caller is asking for compatible id
+ //
+
+ IdIndex--;
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ do {
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(DeviceData + 1);
+ size += 3; // length of large tag
+ }
+
+ DeviceData += size;
+ tag = *DeviceData;
+
+ //
+ // Do we reach the compatible ID descriptor?
+ //
+
+ if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
+ if (count == IdIndex) {
+ id = *(PULONG)(DeviceData + 1);
+ status = STATUS_SUCCESS;
+ break;
+ } else {
+ count++;
+ }
+ }
+
+ } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
+ }
+
+ if (NT_SUCCESS(status)) {
+ PipDecompressEisaId(id, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ *Buffer = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ sizeof(L"*") + sizeof(WCHAR) + unicodeString.Length
+ );
+ if (*Buffer) {
+ swprintf(*Buffer, L"*%s", unicodeString.Buffer);
+ } else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlFreeUnicodeString(&unicodeString);
+ }
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId
+ )
+/*++
+
+Routine Description:
+
+ This function returns the unique id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ DeviceId - supplies a pointer to a variable to receive device id.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // Set up device's unique id.
+ // device unique id = SerialNumber of the card
+ //
+
+ *DeviceId = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ (8 + 1) * sizeof(WCHAR) // serial number + null
+ );
+ if (*DeviceId) {
+ swprintf (*DeviceId,
+ L"%08X",
+ ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber
+ );
+#if IDBG
+ {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, *DeviceId);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("PnpIsa: return Unique Id = %s\n", ansiString.Buffer);
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+ } else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId,
+ ULONG IdIndex
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular device.
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied device.
+
+ DeviceId - supplies a pointer to a variable to receive the device id.
+
+ IdIndex - specifies device id or compatible id (0 - device id)
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWSTR format;
+ ULONG size;
+ UCHAR eisaId[8];
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+
+ //
+ // Set up device's id.
+ // device id = VenderId + Logical device number
+ //
+
+ if (DeviceInfo->CardInformation->NumberLogicalDevices == 1) {
+ format = L"ISAPNP\\%s";
+ size = sizeof(L"ISAPNP\\*") + sizeof(WCHAR);
+ } else {
+ format = L"ISAPNP\\%s_DEV%04X";
+ size = sizeof(L"ISAPNP\\_DEV") + 4 * sizeof(WCHAR) + sizeof(WCHAR);
+ }
+ PipDecompressEisaId(
+ ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->VenderId,
+ eisaId
+ );
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ size += unicodeString.Length;
+ *DeviceId = (PWCHAR)ExAllocatePool (PagedPool, size);
+ if (*DeviceId) {
+ swprintf (*DeviceId,
+ format,
+ unicodeString.Buffer,
+ DeviceInfo->LogicalDeviceNumber
+ );
+#if IDBG
+ {
+ ANSI_STRING dbgAnsiString;
+ UNICODE_STRING dbgUnicodeString;
+
+ RtlInitUnicodeString(&dbgUnicodeString, *DeviceId);
+ RtlUnicodeStringToAnsiString(&dbgAnsiString, &dbgUnicodeString, TRUE);
+ DbgPrint("PnpIsa: return device Id = %s\n", dbgAnsiString.Buffer);
+ RtlFreeAnsiString(&dbgAnsiString);
+ }
+#endif
+ } else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlFreeUnicodeString(&unicodeString);
+
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ PCM_RESOURCE_LIST *CmResources,
+ ULONG *Size
+ )
+/*++
+
+Routine Description:
+
+ This function returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied slot
+
+ BusNumber - should always be 0
+
+ CmResources - supplies a pointer to a variable to receive the device resource
+ data.
+
+ Size - Supplies a pointer to avariable to receive the size of device resource
+ data.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ ULONG length;
+ NTSTATUS status;
+ PCM_RESOURCE_LIST cmResources;
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber,
+ FALSE
+ );
+
+ status = PipReadDeviceBootResourceData (
+ BusNumber,
+ DeviceInfo->DeviceData,
+ &cmResources,
+ &length
+ );
+
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+ cmResources = NULL; // Just to make sure.
+ }
+ *CmResources = cmResources;
+ *Size = length;
+#if IDBG
+ PipDumpCmResourceList(cmResources);
+#endif
+ }
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ ULONG Slot,
+ PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ ULONG *Size
+ )
+/*++
+
+Routine Description:
+
+ This function returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied slot
+
+ BusNumber - Supplies the bus number
+
+ Slot - supplies the slot number of the BusNumber
+
+ IoResources - supplies a pointer to a variable to receive the IO resource
+ requirements list
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length = 0;
+ NTSTATUS status;
+ PUCHAR deviceData;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
+
+ deviceData = DeviceInfo->DeviceData;
+ status = PbBiosResourcesToNtResources (
+ BusNumber,
+ Slot,
+ &deviceData,
+ &ioResources,
+ &length
+ );
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+ ioResources = NULL; // Just ot make sure
+ }
+ *IoResources = ioResources;
+ *Size = length;
+#if IDBG
+ PipDumpIoResourceList(ioResources);
+#endif
+ }
+ return status;
+}
+
+NTSTATUS
+PipSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PCM_RESOURCE_LIST CmResources
+ )
+/*++
+
+Routine Description:
+
+ This function configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied slot
+
+ CmResources - pointer to the desired resource list
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber,
+ FALSE
+ );
+
+ //
+ // Set resource settings for the device
+ //
+
+ status = PipWriteDeviceBootResourceData (
+ DeviceInfo->DeviceData,
+ (PCM_RESOURCE_LIST) CmResources
+ );
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ return status;
+}
diff --git a/private/ntos/nthals/extender/pnpisa.sur/sources b/private/ntos/nthals/extender/pnpisa.sur/sources
new file mode 100644
index 000000000..f0b391be2
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/sources
@@ -0,0 +1,47 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+ALT_PROJECT_TARGET=dlibbin
+
+MAJORCOMP=ntos
+MINORCOMP=extender
+
+TARGETNAME=pnpisa
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=pnpisa.rc \
+ bus.c \
+ data.c \
+ init.c \
+ isolate.c \
+ misc.c \
+ convert.c \
+ resource.c
+
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=
diff --git a/private/ntos/nthals/extender/pnpisa/i386/bus.c b/private/ntos/nthals/extender/pnpisa/i386/bus.c
new file mode 100644
index 000000000..f4c6dd4df
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/bus.c
@@ -0,0 +1,1036 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ bus.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+
+PDEVICE_INFORMATION
+PipFindDeviceInformation (
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ );
+
+PCARD_INFORMATION
+PipFindCardInformation (
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN PSERIAL_IDENTIFIER Id
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PiQueryBusSlots)
+#pragma alloc_text(PAGE,PiReferenceDeviceHandler)
+#pragma alloc_text(PAGE,PipCheckBus)
+#endif
+
+
+ULONG
+PiGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Isa bus data for a device.
+ This API is not supported.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+PiSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function sets the Pnp Isa bus data for a device.
+ This API is not supported.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to be set.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+PiGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Isa device data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ ULONG dataLength;
+ PDEVICE_INFORMATION deviceInfo;
+
+ UNREFERENCED_PARAMETER ( DataType);
+
+ dataLength = 0;
+ deviceInfo = DeviceHandler2DeviceInfo (DeviceHandler);
+
+ //
+ // Synchronize with other pnp Isa service functions accessing device data.
+ //
+
+ ExAcquireFastMutex(&PipMutex);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!(deviceInfo->Flags & DEVICE_FLAGS_VALID)) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ ExReleaseFastMutex(&PipMutex);
+ return dataLength;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ dataLength = deviceInfo->DeviceDataLength;
+ if (Offset < dataLength) {
+ dataLength -= Offset;
+ if (dataLength > Length) {
+ dataLength = Length;
+ }
+ RtlMoveMemory(Buffer, (PUCHAR)deviceInfo->DeviceData + Offset, dataLength);
+ } else {
+ dataLength = 0;
+ }
+
+ ExReleaseFastMutex(&PipMutex);
+ return dataLength;
+}
+
+ULONG
+PiSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets Pnp Isa device data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data set.
+
+--*/
+{
+ //
+ // We don't let drivers change Pnp device data.
+ //
+
+ return 0;
+}
+
+NTSTATUS
+PiQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns a list of currently available SlotNumber.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ SlotNumber - Supplies a variable to receives the number of available slots.
+
+ Length - Supplies a count in bytes of the stored data. If this function
+ returns STATUS_BUFFER_TOO_SMALL, this variable supplies the required
+ size.
+
+Return Value:
+
+ STATUS_BUFFER_TOO_SMALL if caller supplied buffer is not big enough.
+
+--*/
+
+{
+ PPI_BUS_EXTENSION busExtension;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_INFORMATION deviceInfo;
+ ULONG count = 0;
+
+ PAGED_CODE ();
+
+ busExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+
+ //
+ // Synchronize with other pnp Isa device handle assignment.
+ //
+
+ ExAcquireFastMutex(&PipMutex);
+
+ //
+ // Fill in returned buffer length, or what size buffer is needed
+ //
+
+ *ReturnedLength = busExtension->NoValidSlots * sizeof (ULONG);
+ if (BufferSize < *ReturnedLength) {
+
+ //
+ // Callers buffer is not large enough
+ //
+
+ ExReleaseFastMutex (&PipMutex);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Return caller all the possible slot number
+ //
+
+ for (link = busExtension->DeviceList.Next; link; link = link->Next) {
+ deviceInfo = CONTAINING_RECORD (link, DEVICE_INFORMATION, DeviceList);
+ if (deviceInfo->Flags & DEVICE_FLAGS_VALID) {
+ *SlotNumbers = DeviceInfoSlot(deviceInfo);
+ SlotNumbers++;
+ count += 1;
+ }
+ }
+
+ *ReturnedLength = count * sizeof (ULONG);
+ ExReleaseFastMutex (&PipMutex);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PiDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ The function is the bus handler specific verion of HalDeviceControl.
+
+Arguments:
+
+ Context - The DeviceControl context. The context has all the information
+ for the HalDeviceControl operation being performed.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ ULONG i, junk;
+ ULONG controlCode;
+ PULONG bufferLength;
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ for (i = 0; i < NUMBER_DEVICE_CONTROL_FUNCTIONS; i++) {
+
+ if (PipDeviceControl[i].ControlCode == Context->DeviceControl.ControlCode) {
+ if (PipDeviceControl[i].ControlHandler == NULL) {
+ status = Context->DeviceControl.Status = STATUS_NOT_IMPLEMENTED;
+ goto deviceControlDone;
+ }
+
+ //
+ // Found DeviceControl handler and save it to HAL_DEVICE_CONTROL_CONTEXT
+ // structure.
+ //
+
+ Context->ContextControlHandler = (ULONG)(PipDeviceControl + i);
+
+ //
+ // Verify callers buffer is the min required length
+ //
+
+ if (*Context->DeviceControl.BufferLength < PipDeviceControl[i].MinBuffer) {
+ Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
+ *Context->DeviceControl.BufferLength = PipDeviceControl[i].MinBuffer;
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto deviceControlDone;
+ }
+
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
+
+ //
+ // All supported slot control functions touch paged code or data.
+ // If the current irql is low enough go dispatch now; otherwise,
+ // queue the request to a worker thread.
+ //
+
+ PipDispatchControl (Context);
+
+ } else {
+
+ //
+ // Enqueue to worker thread
+ //
+
+ ExInterlockedInsertTailList (
+ &PipControlWorkerList,
+ (PLIST_ENTRY) &Context->ContextWorkQueue,
+ &PipSpinlock
+ );
+
+ //
+ // Make sure worker is requested
+ //
+
+ PipStartWorker ();
+ }
+ return STATUS_PENDING;
+ }
+ }
+
+deviceControlDone:
+ HalCompleteDeviceControl (Context);
+ return status;
+}
+
+PDEVICE_HANDLER_OBJECT
+PiReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function returns a reference to the devce handler specified by SlotNumber
+ and BusHandler.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler structure for the bus
+
+ RootHanler - Supplies a pointer to the root bus handler structure for the bus
+
+ SlotNumber - Specifies the SlotNumber of the device to be referenced
+
+Return Value:
+
+ a reference to DEVICE_HANDLER_OBJECT.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PPI_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+
+ PAGED_CODE ();
+
+ ExAcquireFastMutex (&PipMutex);
+
+ busExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+ deviceInfo = PipFindDeviceInformation (busExtension, SlotNumber);
+ deviceHandler = NULL;
+ if (deviceInfo) {
+ deviceHandler = DeviceInfo2DeviceHandler (deviceInfo);
+ status = ObReferenceObjectByPointer(
+ deviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ if (!NT_SUCCESS(status)) {
+ deviceHandler = NULL;
+ }
+ }
+
+ ExReleaseFastMutex (&PipMutex);
+ return deviceHandler;
+}
+
+PDEVICE_INFORMATION
+PipFindDeviceInformation (
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list to find the desired SlotNumber's
+ device data. The caller must hold the PipMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to current bus'es extension.
+
+ SlotNumber - specified the desired device data.
+
+Return Value:
+
+ A pointer to the DEVICE_INFORMATION if found. Otherwise a value of NULL is returned.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ //
+ // Go through the slot data link list to find a match.
+ //
+
+ for (link = BusExtension->DeviceList.Next; link; link = link->Next) {
+ deviceInfo = CONTAINING_RECORD (link, DEVICE_INFORMATION, DeviceList);
+ if (DeviceInfoSlot(deviceInfo) == SlotNumber) {
+ break;
+ }
+ }
+
+ if (!link) {
+ return NULL;
+ } else {
+ return deviceInfo;
+ }
+}
+
+VOID
+PipCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+
+/*++
+
+Routine Description:
+
+ The function enumerates the bus specified by BusHandler.
+ BUGBUG, Currently the bus extender will not unload even if all the pnp isa
+ cards are gone.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the BusHandler of the bus to be enumerated.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PPI_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ ULONG objectSize, noDevices;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ PUCHAR cardData;
+ ULONG dataLength;
+ USHORT csn, i;
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ UCHAR tmp;
+ BOOLEAN notifyBusCheck;
+ PSINGLE_LIST_ENTRY link;
+
+ PAGED_CODE();
+
+ busExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+ notifyBusCheck = FALSE;
+
+ //
+ // We may be removing references to this bus handler, so add
+ // a reference now.
+ //
+
+ HalReferenceBusHandler (BusHandler);
+
+ //
+ // Acquire fast mutex to access device data
+ //
+
+ ExAcquireFastMutex (&PipMutex);
+ PipInvalidateCards(busExtension);
+
+ //
+ // Perform Pnp isolation process. This will assign card select number for each
+ // Pnp Isa card isolated by the system. All the isolated cards will be put into
+ // wait-for-key state.
+ //
+
+ ExAcquireFastMutex(&PipPortMutex);
+
+ PipIsolateCards(&busExtension->NumberCSNs, &busExtension->ReadDataPort);
+ PipLFSRInitiation (); // send initiation key to put cards into sleep state
+
+ //
+ // For each card selected build CardInformation and DeviceInformation structures.
+ //
+
+ for (csn = 1; csn <= busExtension->NumberCSNs; csn++) {
+
+ status = PipReadCardResourceData (
+ csn,
+ &noDevices,
+ &cardData,
+ &dataLength);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ }
+ cardInfo = PipFindCardInformation(busExtension, (PSERIAL_IDENTIFIER)cardData);
+ if (cardInfo) {
+
+ //
+ // Find an existing card information structure with the same serial identifier
+ // Go validate the card information and its associated device information.
+ //
+
+ cardInfo->Flags |= CARD_FLAGS_VALID;
+ cardInfo->CardSelectNumber = csn;
+ for (link = cardInfo->LogicalDeviceList.Next; link; link = link->Next) {
+ deviceInfo = CONTAINING_RECORD (link, DEVICE_INFORMATION, LogicalDeviceList);
+ deviceInfo->Flags |= DEVICE_FLAGS_VALID;
+ }
+ ExFreePool(cardData);
+ } else {
+
+ //
+ // Did not find an existing card information matched the card data.
+ // Allocate and initialize new card information and its associate device
+ // information structures.
+ //
+
+ cardInfo = (PCARD_INFORMATION)ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(CARD_INFORMATION),
+ 'iPnP');
+ if (!cardInfo) {
+ ExFreePool(cardData);
+#if DBG
+ DebugPrint((DEBUG_MESSAGE, "PnpIsa:failed to allocate CARD_INFO structure\n"));
+#endif
+ continue;
+ }
+
+ //
+ // Initialize card information structure
+ //
+
+ RtlZeroMemory(cardInfo, sizeof(CARD_INFORMATION));
+ cardInfo->Flags = CARD_FLAGS_VALID;
+ cardInfo->CardSelectNumber = csn;
+ cardInfo->NumberLogicalDevices = noDevices;
+ cardInfo->CardData = cardData;
+ cardInfo->CardDataLength = dataLength;
+
+ ExInterlockedPushEntryList (
+ &busExtension->CardList,
+ &cardInfo->CardList,
+ &PipSpinlock
+ );
+#if DBG
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsa: adding one pnp card %x\n"));
+#endif
+ //
+ // For each logical device supported by the card build its DEVICE_INFORMATION
+ // structures and enable it.
+ //
+
+ cardData += sizeof(SERIAL_IDENTIFIER);
+ dataLength -= sizeof(SERIAL_IDENTIFIER);
+ PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+ for (i = 0; i < noDevices; i++) { // logical device number starts from 0
+
+ //
+ // Select the logical device, disable its io range check and
+ // enable the device.
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(i);
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+// PipWriteAddress(ACTIVATE_PORT);
+// PipWriteData(1);
+
+ notifyBusCheck = TRUE;
+
+ //
+ // Initialize the object attributes that will be used to create the
+ // Device Handler Object.
+ //
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+
+ objectSize = PipDeviceHandlerObjectSize + sizeof (DEVICE_INFORMATION);
+
+ //
+ // Create the object
+ //
+
+ status = ObCreateObject(
+ KernelMode,
+ *IoDeviceHandlerObjectType,
+ &objectAttributes,
+ KernelMode,
+ NULL,
+ objectSize,
+ 0,
+ 0,
+ (PVOID *) &deviceHandler
+ );
+
+ if (NT_SUCCESS(status)) {
+ RtlZeroMemory (deviceHandler, objectSize);
+
+ deviceHandler->Type = (USHORT) *IoDeviceHandlerObjectType;
+ deviceHandler->Size = (USHORT) objectSize;
+ deviceHandler->SlotNumber = busExtension->NextSlotNumber++;
+
+ //
+ // Get a reference to the object
+ //
+
+ status = ObReferenceObjectByPointer(
+ deviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // Insert it into the object table
+ //
+
+ status = ObInsertObject(
+ deviceHandler,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ NULL,
+ &handle
+ );
+ }
+
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // BUGBUG, Deallocate, free reference of the device handler?
+ //
+
+ //
+ // Object not created correctly. Skip this slot.
+ //
+
+ continue;
+ }
+
+ ZwClose (handle);
+
+ //
+ // Intialize device tracking structure
+ //
+
+ deviceHandler->BusHandler = BusHandler;
+ HalReferenceBusHandler(BusHandler);
+
+ deviceInfo = DeviceHandler2DeviceInfo(deviceHandler);
+ deviceInfo->Flags |= DEVICE_FLAGS_VALID;
+ deviceInfo->CardInformation = cardInfo;
+ deviceInfo->LogicalDeviceNumber = i;
+ deviceInfo->DeviceData = cardData;
+ deviceInfo->DeviceDataLength = PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+
+ ExInterlockedPushEntryList (
+ &cardInfo->LogicalDeviceList,
+ &deviceInfo->LogicalDeviceList,
+ &PipSpinlock
+ );
+#if DBG
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsa: adding slot %x\n", DeviceInfoSlot(deviceInfo)));
+#endif
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ busExtension->NoValidSlots += 1;
+ ExInterlockedPushEntryList (
+ &busExtension->DeviceList,
+ &deviceInfo->DeviceList,
+ &PipSpinlock
+ );
+
+ }
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ ExReleaseFastMutex(&PipPortMutex);
+
+ //
+ // Go through the slot data link list to delete all the removed slots.
+ //
+
+ noDevices = busExtension->NoValidSlots;
+ PipDeleteCards(busExtension);
+ if (noDevices != busExtension->NoValidSlots) {
+ notifyBusCheck = TRUE;
+ }
+ ExReleaseFastMutex (&PipMutex);
+
+ //
+ // Undo reference to bus handler from top of function
+ //
+
+ HalDereferenceBusHandler (BusHandler);
+
+ //
+ // Do we need to notify the system buscheck callback?
+ //
+
+ if (notifyBusCheck) {
+ HAL_BUS_INFORMATION busInfo;
+
+ busInfo.BusType = BusHandler->InterfaceType;
+ busInfo.ConfigurationType = BusHandler->ConfigurationType;
+ busInfo.BusNumber = BusHandler->BusNumber;
+ busInfo.Reserved = 0;
+ ExNotifyCallback (
+ PipHalCallbacks.BusCheck,
+ &busInfo,
+ (PVOID)BusHandler->BusNumber
+ );
+ }
+}
+
+VOID
+PipInvalidateCards (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+
+/*++
+
+Routine Description:
+
+ The function goes through Pnp Isa Card list and marks all the cards and
+ the devices associated with the cards as invalid.
+ The caller must acquire PipMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_INFORMATION deviceInfo;
+ PSINGLE_LIST_ENTRY cardLink, deviceLink;
+
+ //
+ // Go through the card link list to mark ALL the devices as
+ // in transition state.
+ //
+
+ for (cardLink = BusExtension->CardList.Next; cardLink; cardLink = cardLink->Next) {
+ cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
+ cardInfo->Flags &= ~CARD_FLAGS_VALID;
+
+ //
+ // For each logical device of the card mark it as invalid
+ //
+
+ for (deviceLink = cardInfo->LogicalDeviceList.Next; deviceLink; deviceLink = deviceLink->Next) {
+ deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
+ deviceInfo->Flags &= ~DEVICE_FLAGS_VALID;
+ }
+ }
+
+ //
+ // Reset the CSN number.
+ //
+
+ BusExtension->NumberCSNs = 0;
+}
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through card list and deletes all the invalid
+ cards and their associated logical devices.
+ Note the PipMutex must be acquired before calling this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PSINGLE_LIST_ENTRY *cardLink, *deviceLink ;
+
+ //
+ // Go through the card link list to free all the devices
+ // marked as invalid.
+ //
+
+ cardLink = &BusExtension->CardList.Next;
+ while (*cardLink) {
+ cardInfo = CONTAINING_RECORD (*cardLink, CARD_INFORMATION, CardList);
+ if (!(cardInfo->Flags & CARD_FLAGS_VALID)) {
+
+ //
+ // For each logical device of the card mark it as invalid
+ //
+
+ deviceLink = &cardInfo->LogicalDeviceList.Next;
+ while (*deviceLink) {
+ deviceInfo = CONTAINING_RECORD (*deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
+#if DBG
+ DebugPrint((DEBUG_MESSAGE, "Remove slot %x on PnpIsa bus\n", DeviceInfoSlot(deviceInfo)));
+#endif
+ deviceHandler = DeviceInfo2DeviceHandler(deviceInfo);
+ ObDereferenceObject (deviceHandler);
+ HalDereferenceBusHandler (BusExtension->BusHandler);
+ BusExtension->NoValidSlots--;
+ *deviceLink = (*deviceLink)->Next;
+ }
+
+ //
+ // In theory I can't deallocate the card data and card info structures. Because device
+ // info structure may still exist. The deallocation should be done after device info
+ // structure ref count is decremented to zero and deallocated. Here I am safe to do
+ // so because DispatchControl routine checks DeviceInfo flag to make sure it is valid
+ // before reference card data and card info.
+ //
+
+ if (cardInfo->CardData) {
+ ExFreePool(cardInfo->CardData);
+ }
+ *cardLink = (*cardLink)->Next;
+ ExFreePool(cardInfo);
+ } else {
+ cardLink = &((*cardLink)->Next);
+ }
+ }
+}
+
+PCARD_INFORMATION
+PipFindCardInformation (
+ PPI_BUS_EXTENSION BusExtension,
+ PSERIAL_IDENTIFIER Id
+ )
+
+/*++
+
+Routine Description:
+
+ The function goes through card list to find the card information structure
+ which matches the caller supplied Id. Note, this routine ignore the card
+ structure flags. So, it may return the card information whcih is marked
+ as invalid.
+ Note the PipMutex must be acquired before calling this routine.
+
+Arguments:
+
+ Id - supplies a pointer to the serial identifier of the card.
+
+Return Value:
+
+ If succeed, the pointer to the card information structure is return.
+ Otherwise a NULL pointer is returned.
+
+--*/
+{
+ PCARD_INFORMATION cardInfo;
+ PSINGLE_LIST_ENTRY cardLink;
+
+ //
+ // Go through the card link list to match the id.
+ //
+
+ cardLink = BusExtension->CardList.Next;
+ while (cardLink) {
+ cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
+ ASSERT (cardInfo->CardData);
+ if (RtlEqualMemory(cardInfo->CardData, Id, sizeof(SERIAL_IDENTIFIER))) {
+ return cardInfo;
+ }
+ cardLink = cardLink->Next;
+ }
+ return NULL;
+}
+
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/busp.h b/private/ntos/nthals/extender/pnpisa/i386/busp.h
new file mode 100644
index 000000000..bef6851ee
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/busp.h
@@ -0,0 +1,576 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busp.h
+
+Abstract:
+
+ Hardware independent header file for Pnp Isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+//
+// Structures
+//
+
+//
+// When queued, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextWorkQueue BusExtenderReserved[0]
+#define ContextControlHandler BusExtenderReserved[2]
+
+//
+// When in progress, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextArgument1 BusExtenderReserved[0]
+#define ContextArgument2 BusExtenderReserved[1]
+#define ContextBusyFlag BusExtenderReserved[2]
+
+//
+// CARD_INFORMATION Flags masks
+//
+
+#define CARD_FLAGS_VALID 0x00000001
+
+typedef struct _CARD_INFORMATION_ {
+
+ //
+ // Next points to next CARD_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+ ULONG Flags;
+
+ //
+ // Card select number for this Pnp Isa card.
+ //
+
+ USHORT CardSelectNumber;
+
+ //
+ // Number logical devices in the card.
+ //
+
+ ULONG NumberLogicalDevices;
+
+ //
+ // Logical device link list
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // Pointer to card data which includes:
+ // 9 byte serial identifier for the pnp isa card
+ // PlugPlay Version number type for the pnp isa card
+ // Identifier string resource type for the pnp isa card
+ // Logical device Id resource type (repeat for each logical device)
+ //
+
+ PVOID CardData;
+ ULONG CardDataLength;
+
+} CARD_INFORMATION, *PCARD_INFORMATION;
+
+//
+// DEVICE_INFORMATION Flags masks
+//
+
+#define DEVICE_FLAGS_VALID 0x00000001
+
+typedef struct _DEVICE_INFORMATION_ {
+
+ //
+ // Link list for ALL the Pnp Isa logical devices.
+ // NextDevice points to next DEVICE_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+ ULONG Flags;
+
+ //
+ // Pointer to the CARD_INFORMATION for this device
+ //
+
+ PCARD_INFORMATION CardInformation;
+
+ //
+ // Link list for all the logical devices in a Pnp Isa card.
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // LogicalDeviceNumber selects the corresponding logical device in the
+ // pnp isa card specified by CSN.
+ //
+
+ USHORT LogicalDeviceNumber;
+
+ //
+ // DeviceControl in progress flags
+ //
+
+ BOOLEAN SyncBusy;
+
+ //
+ // Pointer to device specific data
+ //
+
+ PUCHAR DeviceData;
+
+ //
+ // Length of the device data
+ //
+
+ ULONG DeviceDataLength;
+
+} DEVICE_INFORMATION, *PDEVICE_INFORMATION;
+
+//
+// Extension data for Bus extender
+//
+
+typedef struct _PI_BUS_EXTENSION {
+
+ //
+ // BusHandler points back to the BUS_HANDLER structure for this extension
+ //
+
+ PBUS_HANDLER BusHandler;
+
+ //
+ // Number of cards selected
+ //
+
+ ULONG NumberCSNs;
+
+ //
+ // ReadDataPort addr
+ //
+
+ PUCHAR ReadDataPort;
+
+ //
+ // Next Slot Number to assign
+ //
+
+ ULONG NextSlotNumber;
+
+ //
+ // Bus Check request list
+ //
+
+ LIST_ENTRY CheckBus;
+
+ //
+ // Device control request list
+ //
+
+ LIST_ENTRY DeviceControl;
+
+ //
+ // DeviceList is the DEVICE_INFORMATION link list.
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+
+ //
+ // NoValidSlots is the number of valid slots
+ //
+
+ ULONG NoValidSlots;
+
+ //
+ // CardList is the list of CARD_INFORMATION
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+
+ //
+ // NoValidCards is the number of valid card in the CardList
+ //
+
+// ULONG NoValidCards;
+
+} PI_BUS_EXTENSION, *PPI_BUS_EXTENSION;
+
+typedef struct {
+ BOOLEAN Control;
+} *PBCTL_SET_CONTROL;
+
+//
+// Pnp Bios bus extender device object extension
+//
+
+typedef struct _PI_DEVICE_EXTENSION {
+
+ //
+ // BusHandler points to the BusHandler structure for the bus
+ // extender device object.
+ //
+
+ PBUS_HANDLER BusHandler;
+
+} PI_DEVICE_EXTENSION, *PPI_DEVICE_EXTENSION;
+
+//
+// SlotControl related internal definitions
+//
+
+typedef VOID (* CONTROL_FUNCTION)(PDEVICE_INFORMATION, PHAL_DEVICE_CONTROL_CONTEXT);
+
+typedef struct _DEVICE_CONTROL_HANDLER {
+
+ ULONG ControlCode; // Operation code
+ ULONG MinBuffer; // Minimum buffer requirement for the operation
+ CONTROL_FUNCTION ControlHandler; // Function to do the actual work
+
+} DEVICE_CONTROL_HANDLER, *PDEVICE_CONTROL_HANDLER;
+
+#define NUMBER_DEVICE_CONTROL_FUNCTIONS 11
+
+//
+// Global Data references
+//
+
+extern FAST_MUTEX PipMutex;
+extern FAST_MUTEX PipPortMutex;
+extern KSPIN_LOCK PipSpinlock;
+extern LIST_ENTRY PipControlWorkerList;
+extern LIST_ENTRY PipCheckBusList;
+extern ULONG PipWorkerQueued;
+extern WORK_QUEUE_ITEM PipWorkItem;
+extern ULONG PipNextHandle;
+extern DEVICE_CONTROL_HANDLER PipDeviceControl[];
+extern PDRIVER_OBJECT PipDriverObject;
+extern HAL_CALLBACKS PipHalCallbacks;
+extern PCALLBACK_OBJECT PipEjectCallbackObject;
+extern BOOLEAN PipNoBusyFlag;
+extern PPI_BUS_EXTENSION PipBusExtension;
+extern WCHAR rgzPNPISADeviceName[];
+extern POBJECT_TYPE *IoDeviceHandlerObjectType;
+extern PULONG IoDeviceHandlerObjectSize;
+extern ULONG PipDeviceHandlerObjectSize;
+
+#define DeviceHandler2DeviceInfo(a) ((PDEVICE_INFORMATION) (((PUCHAR) a) + PipDeviceHandlerObjectSize))
+#define DeviceInfo2DeviceHandler(a) ((PDEVICE_HANDLER_OBJECT) (((PUCHAR) a) - PipDeviceHandlerObjectSize))
+#define DeviceInfoSlot(a) (DeviceInfo2DeviceHandler(a)->SlotNumber)
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NTSTATUS
+PiAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN PULONG InstanceNumber
+ );
+
+NTSTATUS
+PiCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ );
+
+VOID
+PiUnload (
+ IN PDRIVER_OBJECT DriverObject
+ );
+
+NTSTATUS
+PiReconfigureResources (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN DRIVER_RECONFIGURE_OPERATION Operation,
+ IN PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ );
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ );
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ );
+
+VOID
+PipStartWorker (
+ VOID
+ );
+
+VOID
+PipQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+VOID
+PipControlWorker (
+ IN PVOID WorkerContext
+ );
+
+VOID
+PipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceData
+ );
+
+BOOLEAN
+FASTCALL
+PiBCtlNone (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PiBCtlSync (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceCapabilities (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+ULONG
+PiGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PiSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PiGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PiSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+PiQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+PiDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+PDEVICE_HANDLER_OBJECT
+PiReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ );
+
+VOID
+PipCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PVOID *ResourceData,
+ OUT PULONG ResourceDataLength
+ );
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber
+ );
+
+VOID
+PipLFSRInitiation (
+ VOID
+ );
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs,
+ IN OUT PUCHAR *ReadDataPort
+ );
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ );
+
+VOID
+PipInvalidateCards (
+ IN PPI_BUS_EXTENSION busExtension
+ );
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION busExtension
+ );
+
+#if DBG
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_BREAK 2
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ );
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ );
+
+#define DebugPrint(arg) PipDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/control.c b/private/ntos/nthals/extender/pnpisa/i386/control.c
new file mode 100644
index 000000000..451a86d91
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/control.c
@@ -0,0 +1,511 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ control.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-23-1995
+ Most of the code is adapted from PCI bus extender.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+VOID
+PipiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceData,
+ PBOOLEAN Sync
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PipControlWorker)
+#pragma alloc_text(PAGE,PipCompleteDeviceControl)
+#endif
+
+VOID
+PipStartWorker (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used to start a worker thread.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG workerQueued;
+
+ if (!PipWorkerQueued) {
+ workerQueued = ExInterlockedExchangeUlong (
+ &PipWorkerQueued,
+ 1,
+ PipSpinLock
+ );
+
+ if (!workerQueued) {
+ ExQueueWorkItem (&PipWorkItem, DelayedWorkQueue);
+ }
+ }
+}
+
+VOID
+PipQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+/*++
+
+Routine Description:
+
+ This function enqueues Bus check request to buscheck list.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the bus handler of the bus to be checked.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ExInterlockedInsertTailList (
+ &PipCheckBusList,
+ &((PPI_BUS_EXTENSION)BusHandler->BusData)->CheckBus,
+ &PipSpinlock
+ );
+
+ PipStartWorker();
+}
+
+VOID
+PipControlWorker (
+ IN PVOID WorkerContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by a system worker thread.
+
+ The worker thread dequeues any SlotControls which need to be
+ processed and dispatches them.
+
+ It then checks for any check bus request.
+
+Arguments:
+
+ WorkerContext - supplies a pointer to a context for the worker. Here
+ it is always NULL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PLIST_ENTRY entry;
+ PPI_BUS_EXTENSION busExtension;
+ PHAL_DEVICE_CONTROL_CONTEXT context;
+
+ PAGED_CODE ();
+
+ //
+ // process check bus
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &PipCheckBusList,
+ &PipSpinlock
+ );
+
+ if (!entry) {
+ break;
+ }
+ busExtension = CONTAINING_RECORD (
+ entry,
+ PI_BUS_EXTENSION,
+ CheckBus
+ );
+
+ PipCheckBus (busExtension->BusHandler);
+ }
+
+ //
+ // Reset worker item for next time
+ //
+
+ ExInitializeWorkItem (&PipWorkItem, PipControlWorker, NULL);
+ ExInterlockedExchangeUlong (&PipWorkerQueued, 0, PipSpinLock);
+
+ //
+ // Dispatch pending device controls
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &PipControlWorkerList,
+ &PipSpinlock
+ );
+
+ if (!entry) {
+
+ //
+ // All done, exit the loop.
+ //
+
+ break;
+ }
+
+ context = CONTAINING_RECORD (
+ entry,
+ HAL_DEVICE_CONTROL_CONTEXT,
+ ContextWorkQueue,
+ );
+
+ PipDispatchControl (context);
+ }
+}
+
+VOID
+PipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function dispatches a DeviceControl to the appropiate handler.
+ If the slot is busy, the DeviceControl may be queued for dispatching at
+ a later time
+
+Arguments:
+
+ Context - The DeviceControl context to dispatch
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_CONTROL_HANDLER deviceControlHandler;
+ PPI_BUS_EXTENSION busExtension;
+ PDEVICE_INFORMATION deviceInfo;
+ KIRQL oldIrql;
+ BOOLEAN enqueueIt;
+ PLIST_ENTRY link;
+
+ deviceControlHandler = (PDEVICE_CONTROL_HANDLER) Context->ContextControlHandler;
+ deviceInfo = DeviceHandler2DeviceInfo (Context->DeviceControl.DeviceHandler);
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ ExAcquireFastMutex(&PipMutex);
+
+ //
+ // Verify the device data is still valid
+ //
+
+ if (!(deviceInfo->Flags & DEVICE_FLAGS_VALID)) {
+
+ //
+ // Caller has invalid handle, or handle to a different device
+ //
+
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsa: DeviceControl has invalid device handler \n" ));
+ Context->DeviceControl.Status = STATUS_NO_SUCH_DEVICE;
+ ExReleaseFastMutex(&PipMutex);
+ HalCompleteDeviceControl (Context);
+ return ;
+ }
+ busExtension = (PPI_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Check to see if this request can be begun now
+ //
+
+ link = (PLIST_ENTRY) &Context->ContextWorkQueue;
+ enqueueIt = PiBCtlSync (deviceInfo, Context);
+
+ if (enqueueIt) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ KeAcquireSpinLock (&PipSpinlock, &oldIrql);
+ InsertTailList (&busExtension->DeviceControl, link);
+ KeReleaseSpinLock (&PipSpinlock, oldIrql);
+ ExReleaseFastMutex(&PipMutex);
+ return ;
+ }
+
+ //
+ // Dispatch the function to it's handler
+ //
+
+ ExReleaseFastMutex(&PipMutex);
+ deviceControlHandler->ControlHandler (deviceInfo, Context);
+}
+
+VOID
+PipiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceInfo,
+ PBOOLEAN Sync
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a SlotControl. If another SlotControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+ Status - supplies a NTSTATUS code for the completion.
+
+ Context - supplies a pointer to the original device control context.
+
+ DeviceInfo - supplies a pointer to the device info structure to be completed.
+
+ Sync - supplies a BOOLEAN variable to indicate
+
+Return Value:
+
+--*/
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY link;
+ PBOOLEAN busyFlag;
+ BOOLEAN startWorker = FALSE;
+ PPI_BUS_EXTENSION busExtension;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ busyFlag = (PBOOLEAN) Context->ContextBusyFlag;
+ deviceHandler = DeviceInfo2DeviceHandler(DeviceInfo);
+ busExtension = (PPI_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Pass it to the hal for completion
+ //
+
+ Context->DeviceControl.Status = Status;
+ HalCompleteDeviceControl (Context);
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ KeAcquireSpinLock (&PipSpinlock, &oldIrql);
+
+ //
+ // Clear appropiate busy flag
+ //
+
+ *busyFlag = FALSE;
+
+ //
+ // Check to see if there are any pending device controls for
+ // this device. If so, requeue them to the worker thread
+ //
+
+ for (link = busExtension->DeviceControl.Flink;
+ link != &busExtension->DeviceControl;
+ link = link->Flink) {
+
+ Context = CONTAINING_RECORD (link, HAL_DEVICE_CONTROL_CONTEXT, ContextWorkQueue);
+ if (Context->DeviceControl.DeviceHandler == deviceHandler) {
+ RemoveEntryList (link);
+ InsertTailList (&PipControlWorkerList, link);
+ startWorker = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock (&PipSpinlock, oldIrql);
+
+ if (startWorker) {
+ PipStartWorker ();
+ }
+}
+
+VOID
+PipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceInfo
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a DeviceControl. If another DeviceControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PAGED_CODE();
+
+ PipiCompleteDeviceControl (
+ Status,
+ Context,
+ DeviceInfo,
+ &DeviceInfo->SyncBusy
+ );
+}
+
+BOOLEAN
+FASTCALL
+PiBCtlNone (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to indicate there is no synchronization for this
+ device control function.
+
+Arguments:
+
+ Context - supplies a pointer to the device control context.
+
+ DeviceInfo - supplies a pointer to the device data to be completed.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // No synchronization needed for this SlotControl
+ //
+
+ Context->ContextBusyFlag = (ULONG) &PipNoBusyFlag;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+PiBCtlSync (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize device control request. it checks the
+ state (busy/not busy) of the slot and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceInfo - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // This is a sync command, verify the slot is not busy with a different
+ // command.
+ //
+
+ if (DeviceInfo->SyncBusy) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ return TRUE;
+ }
+
+ //
+ // Don't enqueue, dispatch it now
+ //
+
+ DeviceInfo->SyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceInfo->SyncBusy;
+ return FALSE;
+}
+
+VOID
+PiCtlQueryDeviceCapabilities (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the BCTL_DEVICE_CAPABILITIES structure to the caller
+ specified buffer.
+
+Arguments:
+
+ DeviceInfo - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBCTL_DEVICE_CAPABILITIES capabilities;
+
+ capabilities = (PBCTL_DEVICE_CAPABILITIES) Context->DeviceControl.Buffer;
+
+ capabilities->PowerSupported = FALSE;
+ capabilities->ResumeSupported = FALSE;
+ capabilities->LockSupported = FALSE;
+ capabilities->EjectSupported = FALSE;
+ PipCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceInfo);
+}
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/convert.c b/private/ntos/nthals/extender/pnpisa/i386/convert.c
new file mode 100644
index 000000000..36cf35f99
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/convert.c
@@ -0,0 +1,1077 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xlate.c
+
+Abstract:
+
+ This file contains routines to translate resources between PnP ISA/BIOS
+ format and Windows NT formats.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "..\..\pnpbios\i386\pbios.h"
+
+//
+// internal structures for resource translation
+//
+
+typedef struct _PB_DEPENDENT_RESOURCES {
+ ULONG Count;
+ UCHAR Flags;
+ UCHAR Priority;
+ struct _PB_DEPENDENT_RESOURCES *Next;
+} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
+
+#define DEPENDENT_FLAGS_END 1
+
+typedef struct _PB_ATERNATIVE_INFORMATION {
+ PPB_DEPENDENT_RESOURCES Resources;
+ ULONG NoDependentFunctions;
+ ULONG TotalResourceCount;
+} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
+
+//
+// Internal function references
+//
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ );
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ );
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(PAGE,PbBiosResourcesToNtResources)
+#pragma alloc_text(PAGE,PbIoDescriptorToCmDescriptor)
+#pragma alloc_text(PAGE,PbAddDependentResourcesToList)
+#pragma alloc_text(PAGE,PbBiosIrqToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosDmaToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortFixedToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosMemoryToIoDescriptor)
+#endif
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Bios resource list and generates
+ a NT resource list. The returned Nt resource list could be either IO
+ format or CM format. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ SlotNumber - specifies the slot number of the BIOS resource.
+
+ BiosData - Supplies a pointer to a variable which specifies the bios resource
+ data buffer and which to receive the pointer to next bios resource data.
+
+ ReturnedList - supplies a variable to receive the desired resource list.
+
+ ReturnedLength - Supplies a variable to receive the length of the resource list.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PUCHAR buffer;
+ USHORT mask16, increment;
+ UCHAR tagName, mask8;
+ NTSTATUS status;
+ PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
+ ULONG commonResCount = 0, dependDescCount = 0, i, j;
+ ULONG alternativeListCount = 0, dependFunctionCount = 0;
+ PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
+ PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
+ BOOLEAN dependent = FALSE;
+ ULONG listSize, noResLists;
+ ULONG totalDescCount, descCount;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
+ PIO_RESOURCE_LIST ioResList;
+
+ //
+ // First, scan the bios data to determine the memory requirement and
+ // the information to build internal data structures.
+ //
+
+ *ReturnedLength = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ while (tagName != TAG_COMPLETE_END) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ tagName &= SMALL_TAG_MASK;
+ } else {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ }
+
+ //
+ // Based on the type of the BIOS resource, determine the count of
+ // the IO descriptors.
+ //
+
+ switch (tagName) {
+ case TAG_IRQ:
+ mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
+ i = 0;
+ while (mask16) {
+ if (mask16 & 1) {
+ i++;
+ }
+ mask16 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_DMA:
+ mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
+ i = 0;
+ while (mask8) {
+ if (mask8 & 1) {
+ i++;
+ }
+ mask8 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ dependFunctionCount++;
+ break;
+ case TAG_END_DEPEND:
+ dependent = FALSE;
+ alternativeListCount++;
+ break;
+ case TAG_IO_FIXED:
+ case TAG_IO:
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (!dependent) {
+ commonResCount++;
+ } else {
+ dependDescCount++;
+ }
+ break;
+ default:
+
+ //
+ // Unknown tag. Skip it.
+ //
+
+ break;
+ }
+
+ //
+ // Move to next bios resource descriptor.
+ //
+
+ buffer += increment;
+ tagName = *buffer;
+ }
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (commonResCount == 0 && dependFunctionCount == 0) {
+ *ReturnedList = NULL;
+ *ReturnedLength = 0;
+ *BiosData = buffer + 2;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Allocate memory for our internal data structures
+ //
+
+ if (dependFunctionCount) {
+ dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
+ PagedPool,
+ dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
+ dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
+ 'bPnP'
+ );
+ if (!dependResources) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ dependResList = dependResources; // remember it so we can free it.
+ }
+
+ if (alternativeListCount) {
+ ASSERT(dependFunctionCount != 0);
+ alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
+ 'bPnP'
+ );
+ if (!alternativeList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit0;
+ }
+ RtlZeroMemory(alternativeList,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
+ );
+ alternativeList[0].Resources = dependResources;
+ }
+ if (commonResCount) {
+ commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
+ 'bPnP'
+ );
+ if (!commonResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit1;
+ }
+ }
+
+ //
+ // Now start over again to process the bios data and initialize our internal
+ // resource representation.
+ //
+
+ commonIoDesc = commonResources;
+ dependDescCount = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ dependent = FALSE;
+ while (tagName != TAG_COMPLETE_END) {
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ tagName &= SMALL_TAG_MASK;
+ }
+ switch (tagName) {
+ case TAG_IRQ:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_DMA:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ alternativeList[alternativeListCount].NoDependentFunctions++;
+ if (dependDescCount != 0) {
+
+ //
+ // End of current dependent function
+ //
+
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = 0;
+ dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = dependResources->Next;
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ }
+ if (*buffer & SMALL_TAG_SIZE_MASK) {
+ dependResources->Priority = *(buffer + 1);
+ }
+ dependDescCount = 0;
+ dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
+ buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
+ break;
+ case TAG_END_DEPEND:
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = DEPENDENT_FLAGS_END;
+ dependResources->Next = alternativeList[alternativeListCount].Resources;
+ dependent = FALSE;
+ dependDescCount = 0;
+ alternativeListCount++;
+ alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = alternativeList[alternativeListCount].Resources;
+ buffer++;
+ break;
+ case TAG_IO:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_IO_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ dependDescCount;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ default:
+
+ //
+ // Don't-care tag simpley advance the buffer pointer to next tag.
+ //
+
+ if (*buffer & LARGE_RESOURCE_TAG) {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ } else {
+ increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ }
+ buffer += increment;
+ }
+ tagName = *buffer;
+ }
+
+ if (alternativeListCount != 0) {
+ alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
+ }
+ *BiosData = buffer + 2; // Skip END_TAG
+
+ //
+ // prepare IoResourceList
+ //
+
+ noResLists = 1;
+ for (i = 0; i < alternativeListCount; i++) {
+ noResLists *= alternativeList[i].NoDependentFunctions;
+ }
+ totalDescCount = 0;
+ for (i = 0; i < alternativeListCount; i++) {
+ descCount = 1;
+ for (j = 0; j < alternativeListCount; j++) {
+ if (j == i) {
+ descCount *= alternativeList[j].TotalResourceCount;
+ } else {
+ descCount *= alternativeList[j].NoDependentFunctions;
+ }
+ }
+ totalDescCount += descCount;
+ }
+ listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
+ sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
+
+ ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
+ if (!ioResReqList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit2;
+ }
+
+ ioResReqList->ListSize = listSize;
+ ioResReqList->InterfaceType = Internal;
+ ioResReqList->BusNumber = BusNumber;
+ ioResReqList->SlotNumber = SlotNumber;
+ ioResReqList->Reserved[0] = 0;
+ ioResReqList->Reserved[1] = 0;
+ ioResReqList->Reserved[2] = 0;
+ ioResReqList->AlternativeLists = noResLists;
+ ioResList = &ioResReqList->List[0];
+
+ //
+ // Build resource lists
+ //
+
+ for (i = 0; i < noResLists; i++) {
+ ULONG size;
+
+ ioResList->Version = 1;
+ ioResList->Revision = 1;
+ buffer = (PUCHAR)&ioResList->Descriptors[0];
+
+ //
+ // Copy common resources to the list
+ //
+
+ if (commonResources) {
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
+ RtlMoveMemory(buffer, commonResources, size);
+ buffer += size;
+ }
+
+ //
+ // Copy dependent functions if any.
+ //
+
+ if (alternativeList) {
+ PbAddDependentResourcesToList(&buffer, 0, alternativeList);
+ }
+
+ //
+ // Update io resource list ptr
+ //
+
+ ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
+ sizeof(IO_RESOURCE_DESCRIPTOR);
+ ioResList = (PIO_RESOURCE_LIST)buffer;
+ }
+
+ *ReturnedLength = listSize;
+ status = STATUS_SUCCESS;
+ *ReturnedList = ioResReqList;
+exit2:
+ if (commonResources) {
+ ExFreePool(commonResources);
+ }
+exit1:
+ if (alternativeList) {
+ ExFreePool(alternativeList);
+ }
+exit0:
+ if (dependResList) {
+ ExFreePool(dependResList);
+ }
+ return status;
+}
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds dependent functions to caller specified list.
+
+Arguments:
+
+ ResourceDescriptor - supplies a pointer to the descriptor buffer.
+
+ ListNo - supplies an index to the AlternativeList.
+
+ AlternativeList - supplies a pointer to the alternativelist array.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPB_DEPENDENT_RESOURCES dependentResources, ptr;
+ ULONG size;
+
+ //
+ // Copy dependent resources to caller supplied list buffer and
+ // update the list buffer pointer.
+ //
+
+ dependentResources = AlternativeList[ListNo].Resources;
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
+ RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
+ *ResourceDescriptor = *ResourceDescriptor + size;
+
+ //
+ // Add dependent resource of next list to caller's buffer
+ //
+
+ if (AlternativeList[ListNo + 1].Resources) {
+ ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
+ } else {
+ ptr = NULL;
+ }
+ if (ptr == NULL) {
+ AlternativeList[ListNo].Resources = dependentResources->Next;
+ if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
+ ptr = dependentResources->Next;
+ }
+ }
+ return ptr;
+}
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Arguments:
+
+ IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
+
+ CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CmDescriptor->Type = IoDescriptor->Type;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ switch (CmDescriptor->Type) {
+ case CmResourceTypePort:
+ CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
+ CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
+ break;
+ case CmResourceTypeInterrupt:
+ CmDescriptor->u.Interrupt.Level =
+ CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
+ CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
+ break;
+ case CmResourceTypeMemory:
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
+ break;
+ case CmResourceTypeDma:
+ CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
+ CmDescriptor->u.Dma.Port = 0;
+ CmDescriptor->u.Dma.Reserved1 = 0;
+ break;
+ }
+}
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IRQ information to NT usable format.
+ This routine stops when an irq io resource is generated. if there are
+ more irq io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ USHORT mask;
+ ULONG irq;
+ PPNP_IRQ_DESCRIPTOR buffer;
+ UCHAR size, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ size = buffer->Tag & SMALL_TAG_SIZE_MASK;
+ mask = buffer->IrqMask;
+ mask >>= bitPosition;
+ irq = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ irq = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (irq != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeInterrupt;
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (size == 3 && buffer->Information & 0x0C) {
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ IoDescriptor->ShareDisposition = CmResourceShareShared;
+ }
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Interrupt.MinimumVector = irq;
+ IoDescriptor->u.Interrupt.MaximumVector = irq;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current irq tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ *BiosData = (PUCHAR)buffer + size + 1;
+ return status;
+}
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS DMA information to NT usable format.
+ This routine stops when an dma io resource is generated. if there are
+ more dma io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ ULONG dma;
+ PPNP_DMA_DESCRIPTOR buffer;
+ UCHAR mask, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ mask = buffer->ChannelMask;
+ mask >>= bitPosition;
+ dma = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ dma = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (dma != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeDma;
+ IoDescriptor->Flags = 0;
+ IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Dma.MinimumChannel = dma;
+ IoDescriptor->u.Dma.MaximumChannel = dma;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current dma tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return status;
+}
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS FIXED IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_FIXED_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = 1;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS MEMORY information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PUCHAR buffer;
+ UCHAR tag;
+ PHYSICAL_ADDRESS minAddr, maxAddr;
+ ULONG alignment, length;
+ USHORT increment;
+
+ buffer = *BiosData;
+ tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
+ increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
+
+ minAddr.HighPart = 0;
+ maxAddr.HighPart = 0;
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
+ maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
+ maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
+ maxAddr.LowPart = minAddr.LowPart + length - 1;
+ alignment = 1;
+ break;
+ }
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypeMemory;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Memory.MinimumAddress = minAddr;
+ IoDescriptor->u.Memory.MaximumAddress = maxAddr;
+ IoDescriptor->u.Memory.Alignment = alignment;
+ IoDescriptor->u.Memory.Length = length;
+
+ //
+ // Done with current tag, advance pointer to next tag
+ //
+
+ buffer += increment;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pnpisa/i386/data.c b/private/ntos/nthals/extender/pnpisa/i386/data.c
new file mode 100644
index 000000000..be0a9a08f
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/data.c
@@ -0,0 +1,156 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbdata.c
+
+Abstract:
+
+ Declares various data which is specific to PNP ISA bus extender architecture and
+ is independent of BIOS.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+//
+// PipMutex - To synchronize with device handle changes
+//
+
+FAST_MUTEX PipMutex;
+
+//
+// PipPortMutex - To synchronize with Read data port access.
+// Note, you can *not* ask for PipMutex while owning PipPortMutex.
+//
+
+FAST_MUTEX PipPortMutex;
+
+//
+// PipSpinLock - Lock to protect DeviceControl globals
+//
+
+KSPIN_LOCK PipSpinlock;
+
+//
+// PipControlWorkerList - List of device control's which are pending for worker thread
+//
+
+LIST_ENTRY PipControlWorkerList;
+ULONG PipWorkerQueued;
+
+//
+// PipWorkItem - Enqueue for DeviceControl worker thread
+//
+
+WORK_QUEUE_ITEM PipWorkItem;
+
+//
+// PipCheckBusList - List to enqueue bus check request
+//
+
+LIST_ENTRY PipCheckBusList;
+
+//
+// Eject callback object
+//
+
+PCALLBACK_OBJECT PipEjectCallbackObject;
+
+//
+// regPNPISADeviceName
+//
+
+WCHAR rgzPNPISADeviceName[] = L"\\Device\\PnpIsa_%d";
+
+//
+// Size of DeviceHandlerObject
+//
+
+ULONG PipDeviceHandlerObjectSize;
+
+//
+// DeviceControl dispatch table
+//
+
+#define B_EJECT BCTL_EJECT
+#define B_UID BCTL_QUERY_DEVICE_UNIQUE_ID
+#define B_CAPABILITIES BCTL_QUERY_DEVICE_CAPABILITIES
+#define B_ID BCTL_QUERY_DEVICE_ID
+#define B_RES BCTL_QUERY_DEVICE_RESOURCES
+#define B_RES_REQ BCTL_QUERY_DEVICE_RESOURCE_REQUIREMENTS
+#define B_QUERY_EJECT BCTL_QUERY_EJECT
+#define B_SET_LOCK BCTL_SET_LOCK
+#define B_SET_POWER BCTL_SET_POWER
+#define B_SET_RESUME BCTL_SET_RESUME
+#define B_SET_RES BCTL_SET_DEVICE_RESOURCES
+
+//
+// declare slot control function table.
+// NOTE if the number of entries is changed, the NUMBER_SLOT_CONTROL_FUNCTIONS defined in
+// busp.h must be chnaged accordingly.
+//
+
+DEVICE_CONTROL_HANDLER PipDeviceControl[] = {
+ B_EJECT, 0, NULL,
+ B_ID, 32, PiCtlQueryDeviceId,
+ B_UID, 32, PiCtlQueryDeviceUniqueId,
+ B_CAPABILITIES, sizeof(BCTL_DEVICE_CAPABILITIES), PiCtlQueryDeviceCapabilities,
+ B_RES, sizeof(ULONG), PiCtlQueryDeviceResources,
+ B_RES_REQ, sizeof(ULONG), PiCtlQueryDeviceResourceRequirements,
+ B_QUERY_EJECT, sizeof(PVOID), NULL,
+ B_SET_LOCK, sizeof(BOOLEAN), NULL,
+ B_SET_RESUME, sizeof(BOOLEAN), NULL,
+ B_SET_POWER, sizeof(POWER_STATE), NULL,
+ B_SET_RES, 0, PiCtlSetDeviceResources,
+};
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("PAGE")
+#endif
+
+//
+// Bus Extender driver object
+//
+
+PDRIVER_OBJECT PipDriverObject;
+
+//
+// Pointers to Hal callback objects
+//
+
+HAL_CALLBACKS PipHalCallbacks;
+
+//
+// PipNoBusyFlag - scratch memory location to point at
+//
+
+BOOLEAN PipNoBusyFlag;
+
+//
+// Pointers to bus extension data.
+//
+
+PPI_BUS_EXTENSION PipBusExtension;
+
+//
+// Read_data_port address
+// (This is mainly for convinience. It duplicates the
+// ReadDataPort field in BUS extension structure.)
+//
+
+PUCHAR PipReadDataPort;
diff --git a/private/ntos/nthals/extender/pnpisa/i386/init.c b/private/ntos/nthals/extender/pnpisa/i386/init.c
new file mode 100644
index 000000000..68108ed7c
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/init.c
@@ -0,0 +1,506 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ DriverEntry initialization code for pnp isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 3-Aug-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+NTSTATUS
+PiInstallBusHandler (
+ IN PBUS_HANDLER PiBus
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(PAGE,PiAddBusDevices)
+#pragma alloc_text(PAGE,PiInstallBusHandler)
+#endif
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if pnp isa bus exists. if yes, it builds and
+ initializes pnp isa card information and its associated device information
+ structure.
+
+Arguments:
+
+ DriverObject - specifies the driver object for the bus extender.
+
+ RegistryPath - supplies a pointer to a unicode string of the service key name in
+ the CurrentControlSet\Services key for the bus extender.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PVOID p;
+ PHAL_BUS_INFORMATION pBusInfo;
+ HAL_BUS_INFORMATION busInfo;
+ ULONG length, i, bufferSize, count;
+ PCM_RESOURCE_LIST configuration = NULL;
+ ULONG deviceFlags;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ //
+ // First make sure this is the only pnp Isa bus extender running in the system.
+ //
+
+ status = HalQuerySystemInformation (
+ HalInstalledBusInformation,
+ 0,
+ pBusInfo,
+ &length
+ );
+tryAgain:
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+ pBusInfo = ExAllocatePool(PagedPool, length);
+ if (pBusInfo == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to query installed bus info.\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ status = HalQuerySystemInformation (
+ HalInstalledBusInformation,
+ length,
+ pBusInfo,
+ &length
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // We need to check the buffer size again. It is possible another bus was added
+ // between the two HalQuerySystemInformation calls. In this case, the buffer
+ // requirement is changed.
+ //
+
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+ ExFreePool(pBusInfo);
+ goto tryAgain;
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to query installed bus info.\n"));
+ return status;
+ }
+ }
+
+ //
+ // Check installed bus information to make sure there is no existing Pnp Isa
+ // bus extender.
+ //
+
+ p = pBusInfo;
+ for (i = 0; i < length / sizeof(HAL_BUS_INFORMATION); i++, pBusInfo++) {
+ if (pBusInfo->BusType == PNPISABus &&
+ pBusInfo->ConfigurationType == PNPISAConfiguration) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: A Pnp Isa bus extender is currently running in the system.\n"));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ ExFreePool(p);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ //
+ // Get pointers to the Hals callback objects. The one we are really interested
+ // in is Bus Check callback.
+ //
+
+ status = HalQuerySystemInformation (
+ HalCallbackInformation,
+ sizeof (PipHalCallbacks),
+ &PipHalCallbacks,
+ &length
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to query Hal callbacks\n"));
+ return status;
+ }
+
+ //
+ // Initialize globals
+ //
+
+ PipDriverObject = DriverObject;
+ ExInitializeWorkItem (&PipWorkItem, PipControlWorker, NULL);
+ KeInitializeSpinLock (&PipSpinlock);
+ InitializeListHead (&PipControlWorkerList);
+ InitializeListHead (&PipCheckBusList);
+ ExInitializeFastMutex (&PipMutex);
+ ExInitializeFastMutex (&PipPortMutex);
+ PipDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
+
+ //
+ // Initialize driver object add and detect device entries.
+ //
+
+ DriverObject->DriverExtension->AddDevice = PiAddBusDevices;
+ DriverObject->DriverExtension->ReconfigureDevice = PiReconfigureResources;
+ DriverObject->DriverUnload = PiUnload;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = PiCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = PiCreateClose;
+ //
+ // Query the devices/buses currently controlled by the bus extender
+ //
+
+ status = IoQueryDeviceEnumInfo (&DriverObject->DriverExtension->ServiceKeyName, &count);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ ASSERT(count == 0 || count == 1);
+ for (i = 0; i < count; i++) {
+ status = IoGetDeviceHandler(&DriverObject->DriverExtension->ServiceKeyName,
+ i,
+ &deviceHandler);
+ if (NT_SUCCESS(status)) {
+ bufferSize = sizeof(CM_RESOURCE_LIST);
+tryAgain1:
+ configuration = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool,
+ bufferSize
+ );
+ if (!configuration) {
+ IoReleaseDeviceHandler(deviceHandler);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ status = IoQueryDeviceConfiguration(deviceHandler,
+ &busInfo,
+ &deviceFlags,
+ configuration,
+ bufferSize, // buffer size
+ &length // Actual size
+ );
+ if (NT_SUCCESS(status)) {
+
+ IoReleaseDeviceHandler(deviceHandler);
+
+ //
+ // We know we have two buses at most. If this is the first bus, we will add it
+ // and exit. We don't touch 2nd bus at init time. It should be enumerated
+ // later.
+
+ if (configuration->List[0].BusNumber == 0 &&
+ configuration->List[0].InterfaceType == PNPISABus) {
+ if (deviceFlags == DeviceStatusOK) {
+ PiAddBusDevices(&DriverObject->DriverExtension->ServiceKeyName, &i);
+ ExFreePool(configuration);
+ break;
+ }
+ }
+ } else if (status == STATUS_BUFFER_TOO_SMALL) {
+ ExFreePool(configuration);
+ bufferSize = length;
+ goto tryAgain1;
+ }
+ ExFreePool(configuration);
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PiAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN PULONG InstanceNumber
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ PBUS_HANDLER busHandler;
+ HAL_BUS_INFORMATION busInfo;
+ ULONG deviceInstanceFlags, actualSize;
+ PCM_RESOURCE_LIST detectSignature;
+ UCHAR configuration[sizeof(CM_RESOURCE_LIST)];
+ UNICODE_STRING unicodeString;
+ WCHAR buffer[60];
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ IO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ PCM_RESOURCE_LIST cmResource;
+ PWSTR str;
+
+ PAGED_CODE();
+
+ //
+ // Check if DriverEntry succeeded and if the Pnp Isa bus has been
+ // added already. (There is ONE and only one Pnp Isa bus)
+ //
+
+ if (!PipDriverObject || (PipBusExtension && PipBusExtension->ReadDataPort)) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ //
+ // Register bus handler for Pnp Isa bus
+ //
+
+ status = HalRegisterBusHandler (
+ PNPISABus,
+ PNPISAConfiguration,
+ (ULONG)-1,
+ Internal,
+ 0,
+ sizeof (PI_BUS_EXTENSION),
+ PiInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Register Pnp bus handler failed\n"));
+ return status;
+ }
+
+ if (*InstanceNumber == PLUGPLAY_NO_INSTANCE) {
+
+ //
+ // Register the bus with Pnp manager as a detected bus.
+ //
+
+ RtlZeroMemory(configuration, sizeof(CM_RESOURCE_LIST));
+ detectSignature = (PCM_RESOURCE_LIST)configuration;
+ detectSignature->Count = 1;
+ detectSignature->List[0].InterfaceType = PNPISABus;
+ detectSignature->List[0].BusNumber = 0;
+ status = IoRegisterDetectedDevice (ServiceKeyName, detectSignature, InstanceNumber);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_BREAK,"PnpIsa: Failed to register bus as detected bus\n"));
+ goto errorExit;
+ }
+ }
+
+ //
+ // Call Pnp Io Mgr to register the new device object path
+ //
+
+ swprintf (buffer, rgzPNPISADeviceName, busHandler->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ if (!NT_SUCCESS(status = IoGetDeviceHandler(&PipDriverObject->DriverExtension->ServiceKeyName,
+ *InstanceNumber, &deviceHandler)) ||
+ !NT_SUCCESS(status = IoRegisterDevicePath(deviceHandler, &unicodeString, TRUE, NULL,
+ DeviceStatusOK))) {
+
+ //
+ // BUGBUG - unregister bus handler? How?
+ //
+
+ if (deviceHandler) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Register NT device path failed\n"));
+ IoReleaseDeviceHandler(deviceHandler);
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Unable to get device handler\n"));
+ }
+ goto errorExit;
+ }
+
+ IoReleaseDeviceHandler(deviceHandler);
+
+
+ //
+ // Call I/O mgr to get read data port addr
+ //
+
+ RtlZeroMemory(&ioResource, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
+ ioResource.ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResource.InterfaceType = Isa;
+ ioResource.AlternativeLists = 1;
+ ioResource.List[0].Version = 1;
+ ioResource.List[0].Revision = 1;
+ ioResource.List[0].Count = 1;
+ ioResource.List[0].Descriptors[0].Type = CmResourceTypePort;
+ ioResource.List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource.List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
+ ioResource.List[0].Descriptors[0].u.Port.Length = 4;
+ ioResource.List[0].Descriptors[0].u.Port.Alignment = 4;
+ ioResource.List[0].Descriptors[0].u.Port.MinimumAddress.LowPart = MIN_READ_DATA_PORT;
+ ioResource.List[0].Descriptors[0].u.Port.MaximumAddress.LowPart = MAX_READ_DATA_PORT;
+ str = (PWSTR)ExAllocatePool(PagedPool, 512);
+ if (!str) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ goto errorExit;
+ }
+ swprintf(str, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s",
+ ServiceKeyName->Buffer);
+ RtlInitUnicodeString(&unicodeString, str);
+ status = IoAssignResources(&unicodeString,
+ NULL,
+ PipDriverObject,
+ PipBusExtension->BusHandler->DeviceObject,
+ &ioResource,
+ &cmResource);
+ ExFreePool(str);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ goto errorExit;
+ }
+
+ PipBusExtension->ReadDataPort = (PUCHAR)(cmResource->List[0].PartialResourceList.
+ PartialDescriptors[0].u.Port.Start.LowPart + 3);
+ ExFreePool(cmResource);
+
+ //
+ // Perform initial bus check
+ //
+
+ PipCheckBus(busHandler);
+
+ return STATUS_SUCCESS;
+
+errorExit:
+
+ //
+ // BUGBUG We should unregister the bus handler and exit.
+ // HalUnregisterBusHandler is not supported.
+ //
+
+ return status;
+}
+
+NTSTATUS
+PiInstallBusHandler (
+ PBUS_HANDLER BusHandler
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked by Hal to initialize BUS_HANDLER structure and its
+ extension.
+
+Arguments:
+
+ BusHandler - spplies a pointer to Pnp Isa bus handler's BUS_HANDLER structure.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ WCHAR buffer[60];
+ UNICODE_STRING unicodeString;
+ PPI_DEVICE_EXTENSION deviceExtension;
+ NTSTATUS status;
+ PDEVICE_OBJECT deviceObject;
+
+ PAGED_CODE();
+
+ //
+ // Verify there's a parent handler
+ //
+
+ if (!BusHandler->ParentHandler) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Create device object for Pnp Isa bus extender.
+ //
+
+ swprintf (buffer, rgzPNPISADeviceName, BusHandler->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ status = IoCreateDevice(
+ PipDriverObject,
+ sizeof(PI_DEVICE_EXTENSION),
+ &unicodeString,
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &deviceObject
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to create device object for Pnp isa bus\n"));
+ return status;
+ }
+
+ // ===================================
+ // BUGBUG - need to find a solution
+ //
+
+ deviceObject->Flags &= ~0x80;
+
+ // ==================================
+ deviceExtension = (PPI_DEVICE_EXTENSION) deviceObject->DeviceExtension;
+ deviceExtension->BusHandler = BusHandler;
+
+ //
+ // Initialize bus handlers
+ //
+
+ BusHandler->DeviceObject = deviceObject;
+ BusHandler->GetBusData = (PGETSETBUSDATA) PiGetBusData;
+ BusHandler->SetBusData = (PGETSETBUSDATA) PiSetBusData;
+ BusHandler->QueryBusSlots = (PQUERY_BUS_SLOTS) PiQueryBusSlots;
+ BusHandler->DeviceControl = (PDEVICE_CONTROL) PiDeviceControl;
+ BusHandler->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) PiReferenceDeviceHandler;
+ BusHandler->GetDeviceData = (PGET_SET_DEVICE_DATA) PiGetDeviceData;
+ BusHandler->SetDeviceData = (PGET_SET_DEVICE_DATA) PiSetDeviceData;
+
+ //
+ // Intialize bus extension
+ //
+
+ PipBusExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+ RtlZeroMemory(PipBusExtension, sizeof(PI_BUS_EXTENSION));
+ PipBusExtension->BusHandler = BusHandler;
+
+ InitializeListHead (&PipBusExtension->CheckBus);
+ InitializeListHead (&PipBusExtension->DeviceControl);
+
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pnpisa/i386/isolate.c b/private/ntos/nthals/extender/pnpisa/i386/isolate.c
new file mode 100644
index 000000000..53983ef71
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/isolate.c
@@ -0,0 +1,1574 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ isolate.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-10-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "..\..\pnpbios\i386\pbios.h"
+#include "pnpisa.h"
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG Base,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ );
+
+//
+// Internal type definitions
+//
+
+typedef struct _MEMORY_DESC_{
+ ULONG Base;
+ ULONG Length;
+} MEMORY_DESC, *PMEMORY_DESC;
+
+typedef struct _IRQ_DESC_{
+ UCHAR Level;
+ ULONG Type;
+}IRQ_DESC, *PIRQ_DESC;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PipFindIrqInformation)
+#pragma alloc_text(PAGE,PipFindMemoryInformation)
+#pragma alloc_text(PAGE,PipFindIoPortInformation)
+#pragma alloc_text(PAGE,PipReadCardResourceData)
+#pragma alloc_text(PAGE,PipWriteDeviceBootResourceData)
+#pragma alloc_text(PAGE,PipLFSRInitiation)
+#pragma alloc_text(PAGE,PipIsolateCards)
+#endif
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Irq descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. On input, the BiosRequirements points to current
+ logical id tag.
+
+Arguments:
+
+ IrqLevel - Supplies the irq level.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ ULONG increment;
+ USHORT irqMask;
+ PPNP_IRQ_DESCRIPTOR biosDesc;
+
+ //
+ // Skip current logical id tag
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the Irq.
+ //
+
+ irqMask = 1 << IrqLevel;
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
+ biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->IrqMask & irqMask) {
+ if ((tag & SMALL_TAG_MASK) == 2) {
+
+ //
+ // if no irq info is available, a value of zero is returned.
+ // (o is not a valid irq information.)
+ //
+
+ *Information = 0;
+ } else {
+ *Information = biosDesc->Information;
+ }
+ return TRUE;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG BaseAddress,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ memory descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. Note, the memory range specified by Base
+ and Limit must be within a single Pnp ISA memory descriptor.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the memory range.
+
+ Limit - Supplies the upper limit of the memory range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ NameTag - Supplies a variable to receive the Tag of the memory descriptor which
+ describes the memory information.
+
+ Information - supplies a pointer to a UCHAR to receive the memory information
+ for the specified memory range.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+
+ //
+ // Skip current logical id tag.
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the memory range described by Base and Limit.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
+ maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
+ + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
+ maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
+ + length - 1;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
+ maxAddr = minAddr + length - 1;
+ break;
+ }
+
+ if (minAddr <= BaseAddress && maxAddr >= Limit) {
+ *Information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
+ *NameTag = tag;
+ found = TRUE;
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Io port descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the Io port range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+ Alignment - supplies a pointer to a UCHAR to receive the port alignment
+ information.
+
+ RangeLength - supplies a pointer to a UCHAR to receive the port range length
+ information.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+ PPNP_PORT_DESCRIPTOR portDesc;
+ PPNP_FIXED_PORT_DESCRIPTOR fixedPortDesc;
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the io port range described by Base.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag & SMALL_TAG_MASK) {
+ case TAG_IO:
+ portDesc = (PPNP_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = portDesc->MinimumAddress;
+ maxAddr = portDesc->MaximumAddress;
+ if (minAddr <= BaseAddress && maxAddr >= BaseAddress) {
+ *Information = portDesc->Information;
+ *Alignment = portDesc->Alignment;
+ *RangeLength = portDesc->Length;
+ found = TRUE;
+ }
+ break;
+ case TAG_IO_FIXED:
+ fixedPortDesc = (PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = fixedPortDesc->MinimumAddress;
+ if (BaseAddress == minAddr) {
+ *Information = 0; // 10 bit decode
+ *Alignment = 1;
+ *RangeLength = fixedPortDesc->Length;
+ found = TRUE;
+ }
+ break;
+ }
+
+ if (found) {
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PUCHAR *ResourceData,
+ OUT PULONG ResourceDataLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads resources data from a specified PnP ISA card. It is
+ caller's responsibility to release the memory. Before calling this routine,
+ the Pnp ISA card should be in sleep state (i.e. Initiation Key was sent.)
+ After exiting this routine, the card will be left in Config state.
+
+Arguments:
+
+ Csn - Specifies the CardSelectNumber to indicate which PNP ISA card.
+
+ NumberLogicalDevices - supplies a variable to receive the number of logical devices
+ associated with the Pnp Isa card.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ ResourceDataLength - Supplies a variable to receive the length of the ResourceData.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ PUCHAR buffer, p;
+ USHORT sizeToRead, size, limit, i;
+ UCHAR tag;
+ ULONG noDevices;
+
+ //
+ // Allocate memory to store the resource data.
+ // N.B. The buffer size should cover 99.999% of the machines.
+ //
+
+ sizeToRead = 4096;
+
+tryAgain:
+
+ noDevices = 0;
+ buffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, sizeToRead, 'iPnP');
+ if (!buffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Send card from sleep state to configuration state
+ // Note, by doing this the resource data includes 9 bytes Id.
+ //
+
+ PipWriteAddress (WAKE_CSN_PORT);
+ PipWriteData((UCHAR)Csn);
+
+ //
+ // Read the data until the buffer is full.
+ //
+
+ for (i = 0, p = buffer; i < sizeToRead; i++, p++) {
+ PipWriteAddress(CONFIG_DATA_STATUS_PORT);
+
+ //
+ // Waiting for data ready status bit
+ //
+
+ while ((PipReadData() & 1) != 1) {
+ }
+
+ //
+ // Read the data ...
+ //
+
+ PipWriteAddress(CONFIG_DATA_PORT);
+ *p = PipReadData();
+ }
+
+ //
+ // Next check if we got all the resource data and find out the real
+ // size of the resource data.
+ //
+
+ p = buffer + NUMBER_CARD_ID_BYTES;
+
+ //
+ // set search limit to be one byte less the (buffer size -
+ // size of ID bytes) to make sure the END TAG can be found before
+ // the last byte of the buffer. (This is because END tag contains
+ // one byte checksum.)
+ //
+
+ limit = sizeToRead - NUMBER_CARD_ID_BYTES - 1;
+ tag = *p;
+ while (tag != TAG_COMPLETE_END && limit > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // move to next descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ noDevices++;
+ }
+ } else {
+ size = *(PUSHORT)(p + 1);
+ size += 3; // length of large tag
+ }
+
+ p += size;
+ limit -= size;
+ tag = *p;
+ }
+ if (tag == TAG_COMPLETE_END) {
+
+ //
+ // Determine the real size of the buffer required and
+ // resize the buffer.
+ //
+
+ size = p - buffer + 1 + 1; // add 1 for end tag checksum byte
+ p = (PUCHAR)ExAllocatePoolWithTag(PagedPool, size, 'iPnP');
+ if (p) {
+ RtlMoveMemory(p, buffer, size);
+ ExFreePool(buffer);
+ } else {
+
+ //
+ // Fail to resize the buffer. Simply leave it alone.
+ //
+
+ p = buffer;
+ }
+
+ //
+ // Should we leave card in config state???
+ //
+
+ *ResourceData = p;
+ *NumberLogicalDevices = noDevices;
+ *ResourceDataLength = size;
+ return STATUS_SUCCESS;
+ } else {
+
+ //
+ // We did not find the resource END TAG. This means we did not
+ // get all the resource data on previous read. Try to expand the
+ // data buffer and read again.
+ //
+#if DBG
+ DbgBreakPoint();
+#endif
+ ExFreePool(buffer);
+ sizeToRead <<= 1; // double the buffer
+
+ //
+ // If we can find the END tag with 32K byte, assume the resource
+ // requirement list is bad.
+ //
+
+ if (sizeToRead > 0x80000) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ goto tryAgain;
+ }
+}
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads boot resource data from an enabled logical device of a PNP ISA card.
+ Caller must put the card into configuration state and select the logical device before
+ calling this function. It is caller's responsibility to release the memory. ( The boot
+ resource data is the resources that a card assigned during boot.)
+
+Arguments:
+
+ BusNumber - specifies the bus number of the device whose resource data to be read.
+
+ BiosRequirements - Supplies a pointer to the resource requirement list for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ Length - Supplies a variable to recieve the length of the resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ UCHAR c, junk1, junk2;
+ PUCHAR base;
+ ULONG l, resourceCount;
+ BOOLEAN limit;
+ LONG i, j, noMemoryDesc = 0, noIoDesc = 0, noDmaDesc =0, noIrqDesc = 0;
+ MEMORY_DESC memoryDesc[NUMBER_MEMORY_DESCRIPTORS + NUMBER_32_MEMORY_DESCRIPTORS];
+ IRQ_DESC irqDesc[NUMBER_IRQ_DESCRIPTORS];
+ UCHAR dmaDesc[NUMBER_DMA_DESCRIPTORS];
+ USHORT ioDesc[NUMBER_IO_DESCRIPTORS];
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_LIST partialResList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+
+#if DBG
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DbgPrint("PnpIsa-ReadDeviceBootResourceData:The logical device has not been activated\n");
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Read memory configuration
+ //
+
+ base = (PUCHAR)ADDRESS_MEMORY_BASE;
+ for (i = 0; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+
+ //
+ // Read memory base address
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8; // l = memory base address
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8;
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ noMemoryDesc++;
+ base += ADDRESS_MEMORY_INCR;
+ }
+
+ //
+ // Read memory 32 configuration
+ //
+
+ for (i = 0; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+
+ base = ADDRESS_32_MEMORY_BASE(i);
+
+ //
+ // Read memory base address
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_B3; j <= ADDRESS_32_MEMORY_B0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_32_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_E3; j <= ADDRESS_32_MEMORY_E0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ noMemoryDesc++;
+ }
+
+ //
+ // Read Io Port Configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IO_BASE;
+ for (i = 0; i < NUMBER_IO_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IO_BASE_HI);
+ c = PipReadData();
+ l = c;
+ PipWriteAddress(base + ADDRESS_IO_BASE_LO);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ if (l == 0) {
+ break;
+ }
+ ioDesc[noIoDesc++] = (USHORT)l;
+ base += ADDRESS_IO_INCR;
+ }
+
+ //
+ // Read Interrupt configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IRQ_BASE;
+ for (i = 0; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IRQ_VALUE);
+ c = PipReadData();
+ if (c == 0) {
+ break;
+ }
+ irqDesc[noIrqDesc].Level = c;
+ PipWriteAddress(base + ADDRESS_IRQ_TYPE);
+ c = PipReadData();
+ irqDesc[noIrqDesc++].Type = c;
+ base += ADDRESS_IRQ_INCR;
+ }
+
+ //
+ // Read DMA configuration
+ //
+
+ base = (PUCHAR)ADDRESS_DMA_BASE;
+ for (i = 0; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_DMA_VALUE);
+ c = PipReadData();
+ if (c == 4) {
+ break;
+ }
+ dmaDesc[noDmaDesc++] = c;
+ base += ADDRESS_IRQ_INCR;
+ }
+
+ //
+ // Construct CM_RESOURCE_LIST structure based on the resource data
+ // we collect so far.
+ //
+
+ resourceCount = noMemoryDesc + noIoDesc + noDmaDesc + noIrqDesc;
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (resourceCount == 0) {
+ *ResourceData = NULL;
+ *Length = 0;
+ return STATUS_SUCCESS;
+ }
+
+ l = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
+ ( resourceCount - 1);
+ cmResource = ExAllocatePoolWithTag(PagedPool, l, 'iPnP');
+ if (!cmResource) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(cmResource, l);
+ *Length = l; // Set returned resource data length
+ cmResource->Count = 1;
+ cmResource->List[0].InterfaceType = Isa;
+ cmResource->List[0].BusNumber = BusNumber;
+ partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResource->List[0].PartialResourceList;
+ partialResList->Version = 0;
+ partialResList->Revision = 0;
+ partialResList->Count = resourceCount;
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
+
+ //
+ // Set up all the CM memory descriptors
+ //
+
+ for (i = 0; i < noMemoryDesc; i++) {
+ partialDesc->Type = CmResourceTypeMemory;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->u.Memory.Length = memoryDesc[i].Length;
+ partialDesc->u.Memory.Start.HighPart = 0;
+ partialDesc->u.Memory.Start.LowPart = memoryDesc[i].Base;
+
+ //
+ // Need to consult configuration data for the Flags
+ //
+
+ l = memoryDesc[i].Base + memoryDesc[i].Length - 1;
+ if (PipFindMemoryInformation (memoryDesc[i].Base, l, BiosRequirements, &junk1, &c)) {
+ if (c & PNP_MEMORY_WRITE_STATUS_MASK) {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+ partialDesc++;
+ } else {
+#if DBG
+ DbgPrint("PnpIsa-ReadDeviceBootResourceData:No matched memory information in config data\n");
+ DbgBreakPoint();
+#endif
+ }
+ }
+
+ //
+ // Set up all the CM io/port descriptors
+ //
+
+ for (i = 0; i < noIoDesc; i++) {
+ partialDesc->Type = CmResourceTypePort;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = CM_RESOURCE_PORT_IO;
+ partialDesc->u.Port.Start.LowPart = ioDesc[i];
+
+ //
+ // Need to consult configuration data for the Port length
+ //
+
+ if (PipFindIoPortInformation (ioDesc[i], BiosRequirements, &junk1, &junk2, &c)) {
+ partialDesc->u.Port.Length = c;
+ partialDesc++;
+ } else {
+#if DBG
+ DbgPrint("PnpIsa-ReadDeviceBootResourceData:No matched port length in config data\n");
+ DbgBreakPoint();
+#endif
+ }
+ }
+
+ //
+ // Set up all the CM DMA descriptors
+ //
+
+ for (i = 0; i < noDmaDesc; i++) {
+ partialDesc->Type = CmResourceTypeDma;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = 0; // no flags for DMA descriptor
+ partialDesc->u.Dma.Channel = (ULONG) dmaDesc[i];
+ partialDesc->u.Dma.Port = 0;
+ partialDesc->u.Dma.Reserved1 = 0;
+ partialDesc++;
+ }
+
+ //
+ // Set up all the CM interrupt descriptors
+ //
+
+ for (i = 0; i < noIrqDesc; i++) {
+ partialDesc->Type = CmResourceTypeInterrupt;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (irqDesc[i].Type & 1) {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ }
+ partialDesc->u.Interrupt.Vector =
+ partialDesc->u.Interrupt.Level = irqDesc[i].Level;
+ partialDesc->u.Interrupt.Affinity = (ULONG)-1;
+ partialDesc++;
+ }
+
+ *ResourceData = cmResource;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes boot resource data to an enabled logical device of
+ a Pnp ISA card. Caller must put the card into configuration state and select
+ the logical device before calling this function.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the possible resources for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a pointer to the cm resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+ UCHAR c, information;
+ ULONG count, i, j, pass, base, limit;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
+ ULONG noIrq =0, noIo = 0, noDma = 0, noMemory = 0, no32Memory = 0;
+ PUCHAR memoryBase, irqBase, dmaBase, ioBase, tmp;
+ ULONG memory32Base;
+
+#if DBG
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DbgPrint("PnpIsa-WriteDeviceBootResourceData:The logical device has not been activated\n");
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ count = CmResources->List[0].PartialResourceList.Count;
+ memoryBase = (PUCHAR)ADDRESS_MEMORY_BASE;
+ memory32Base = 0;
+ ioBase = (PUCHAR)ADDRESS_IO_BASE;
+ irqBase = (PUCHAR)ADDRESS_IRQ_BASE;
+ dmaBase = (PUCHAR)ADDRESS_DMA_BASE;
+ for (pass = 1; pass <= 2; pass++) {
+
+ //
+ // First pass we make sure the resources to be set is acceptable.
+ // Second pass we actually write the resources to the logical device's
+ // configuration space.
+ //
+
+ cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
+ for (i = 0; i < count; i++) {
+ switch (cmDesc->Type) {
+ case CmResourceTypePort:
+ if (pass == 1) {
+ noIo++;
+ if (noIo > NUMBER_IO_DESCRIPTORS ||
+ cmDesc->u.Port.Start.HighPart != 0 ||
+ cmDesc->u.Port.Start.LowPart & 0xffff0000 ||
+ cmDesc->u.Port.Length & 0xffffff00) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Io port base address to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Port.Start.LowPart;
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_LO);
+ PipWriteData(c);
+ c = (UCHAR)(cmDesc->u.Port.Start.LowPart >> 8);
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_HI);
+ PipWriteData(c);
+ ioBase += ADDRESS_IO_INCR;
+ }
+ break;
+ case CmResourceTypeInterrupt:
+ if (pass == 1) {
+ noIrq++;
+ if (noIrq > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Interrupt.Level & 0xfffffff0)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // See if we can get the interrupt information from possible resource
+ // data. We need it to set the configuration register.
+ //
+
+ if (!PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Irq to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Interrupt.Level;
+ PipWriteAddress(irqBase + ADDRESS_IRQ_VALUE);
+ PipWriteData(c);
+ PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information);
+ if (information != 0) {
+ switch (information & 0xf) {
+ case 1: // High true edge sensitive
+ c = 2;
+ break;
+ case 2: // Low true edge sensitive
+ c = 0;
+ break;
+ case 4: // High true level sensitive
+ c = 3;
+ break;
+ case 8: // Low true level sensitive
+ c = 1;
+ break;
+ }
+ PipWriteAddress(irqBase + ADDRESS_IRQ_TYPE);
+ PipWriteData(c);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ break;
+ case CmResourceTypeDma:
+ if (pass == 1) {
+ noDma++;
+ if (noDma > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Dma.Channel & 0xfffffff8)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Dma channel to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Dma.Channel;
+ PipWriteAddress(dmaBase + ADDRESS_DMA_VALUE);
+ PipWriteData(c);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ break;
+ case CmResourceTypeMemory:
+ if (pass == 1) {
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ if (!PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ } else {
+ switch (c) {
+ case TAG_MEMORY:
+ noMemory++;
+
+ //
+ // Make sure the lower 8 bits of the base address are zero.
+ //
+
+ if (noMemory > NUMBER_MEMORY_DESCRIPTORS ||
+ base & 0xff) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ no32Memory++;
+ if (no32Memory > NUMBER_32_MEMORY_DESCRIPTORS) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+ } else {
+
+ //
+ // Find information in BiosRequirements to help determine how to write
+ // the memory configuration space.
+ //
+
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information);
+ switch (c) {
+ case TAG_MEMORY:
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_LO);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_HI);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_CTL);
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT; // assume 16 bit memory
+ if (information & 0x18 == 0) { // 8 bit memory only
+ c = 0 + ADDRESS_MEMORY_CTL_LIMIT;
+ }
+ PipWriteData(c);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_LO);
+ PipWriteData((UCHAR)limit);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_HI);
+ PipWriteData((UCHAR)limit);
+ memoryBase += ADDRESS_MEMORY_INCR;
+ break;
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B0);
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B1);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B2);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B3);
+ base >>= 8;
+ PipWriteData(base);
+ switch (information & 0x18) {
+ case 0: // 8 bit only
+ c = ADDRESS_MEMORY_CTL_LIMIT;
+ case 8: // 16 bit only
+ case 0x10: // 8 and 16 bit supported
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ case 0x18: // 32 bit only
+ c = 6 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ }
+ PipWriteAddress(ADDRESS_32_MEMORY_CTL);
+ PipWriteData(c);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E0);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E1);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E2);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E3);
+ PipWriteData(limit);
+ memory32Base++;
+ break;
+ }
+ }
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+ cmDesc++;
+ }
+ }
+
+ //
+ // Finally, mark all the unused descriptors as disabled.
+ //
+
+ for (i = noMemory; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+ for (j = 0; j < 5; j++) {
+ PipWriteAddress(memoryBase + j);
+ PipWriteData(0);
+ }
+ memoryBase += ADDRESS_MEMORY_INCR;
+ }
+ for (i = no32Memory; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ for (j = 0; j < 9; j++) {
+ PipWriteAddress(tmp + j);
+ PipWriteData(0);
+ }
+ memory32Base++;
+ }
+ for (i = noIo; i < NUMBER_IO_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(ioBase + j);
+ PipWriteData(0);
+ }
+ ioBase += ADDRESS_IO_INCR;
+ }
+ for (i = noIrq; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(irqBase + j);
+ PipWriteData(0);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ for (i = noDma; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(dmaBase);
+ PipWriteData(4);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID
+PipLFSRInitiation (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insures the LFSR (linear feedback shift register) is in its
+ initial state and then performs 32 writes to the ADDRESS port to initiation
+ LFSR function.
+
+ Pnp software sends the initiation key to all the Pnp ISA cards to place them
+ into configuration mode. The software then ready to perform isolation
+ protocol.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR seed, bit7;
+ ULONG i;
+
+ //
+ // First perform two writes of value zero to insure the LFSR is in the
+ // initial state.
+ //
+
+ PipWriteAddress (0);
+ PipWriteAddress (0);
+
+ //
+ // Perform the initiation key.
+ //
+
+ seed = LFSR_SEED; // initial value of 0x6a
+ for (i = 0; i < 32; i++) {
+ PipWriteAddress (seed);
+ bit7=(((seed & 2) >> 1) ^ (seed & 1)) << 7;
+ seed =(seed >> 1) | bit7;
+ }
+}
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs,
+ IN OUT PUCHAR *ReadDataPort
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs PnP ISA cards isolation sequence.
+
+Arguments:
+
+ NumberCSNs - supplies the addr of a variable to receive the number of
+ Pnp Isa cards isolated.
+
+ ReadDataPort - Supplies the address of a variable to supply ReadData port
+ address. If NULL is supplied, this function returns detected ReadData
+ port to this variable.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT j, i;
+ UCHAR cardId[NUMBER_CARD_ID_BYTES];
+ UCHAR bit, bit7, checksum, byte1, byte2;
+ ULONG csn = 0;
+
+ //
+ // First send Initiation Key to all the PNP ISA cards to put them into
+ // configuration mode.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Reset all Pnp ISA cards' CSN to 0 and return to wait-for-key state
+ //
+
+ PipWriteAddress (CONFIG_CONTROL_PORT);
+ PipWriteData (CONTROL_WAIT_FOR_KEY | CONTROL_RESET_CSN);
+
+ //
+ // Delay 2 msec for cards to load initial configuration state.
+ //
+
+ KeStallExecutionProcessor(20000); // delay 2 msec
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Starting Pnp Isa card isolation process.
+ // Try Read_Data_port from 200 to 3ff if ReadData port addr is not supplied.
+ //
+
+ for (i = MIN_READ_DATA_PORT; i < MAX_READ_DATA_PORT; i += 4) {
+
+ if ((i & 0xf) == 0) {
+
+ //
+ // Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
+ //
+
+ continue;
+ }
+ if (*ReadDataPort) {
+ PipReadDataPort = *ReadDataPort;
+ } else {
+ PipReadDataPort = (PUCHAR)(i + 3);;
+ }
+
+ //
+ // Send WAKE[CSN=0] to force all cards without CSN into isolation
+ // state to set READ DATA PORT.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ //
+ // Set read data port to current testing value.
+ //
+
+ PipWriteAddress(SET_READ_DATA_PORT);
+ PipWriteData((UCHAR)((ULONG)PipReadDataPort >> 2));
+
+ //
+ // Isolate one PnP ISA card until fail
+ //
+
+ while (TRUE) {
+
+ //
+ // Read serial isolation port to cause PnP cards in the isolation
+ // state to compare one bit of the boards ID.
+ //
+
+ PipWriteAddress(SERIAL_ISOLATION_PORT);
+
+ //
+ // We need to delay 1msec prior to starting the first pair of isolation
+ // reads and must wait 250usec between each subsequent pair of isolation
+ // reads. This delay gives the ISA cards time to access information from
+ // possible very slow storage device.
+ //
+
+ KeStallExecutionProcessor(10000); // delay 1 msec
+
+ RtlZeroMemory(cardId, NUMBER_CARD_ID_BYTES);
+ checksum = LFSR_SEED;
+ for (j = 0; j < NUMBER_CARD_ID_BITS; j++) {
+
+ //
+ // Read card id bit by bit
+ //
+
+ byte1 = READ_PORT_UCHAR (PipReadDataPort);
+ byte2 = READ_PORT_UCHAR (PipReadDataPort);
+ bit = (byte1 == ISOLATION_TEST_BYTE_1) && (byte2 == ISOLATION_TEST_BYTE_2);
+ cardId[j / 8] |= bit << (j % 8);
+ if (j < CHECKSUMED_BITS) {
+
+ //
+ // Calculate checksum
+ //
+
+ bit7 = (((checksum & 2) >> 1) ^ (checksum & 1) ^ (bit)) << 7;
+ checksum = (checksum >> 1) | bit7;
+ }
+ KeStallExecutionProcessor(2500); // delay 250 usec
+ }
+
+ //
+ // Verify the card id we read is legitimate
+ // First make sure checksum is valid. Note zero checksum is considered valid.
+ //
+
+ if (cardId[8] == 0 || checksum == cardId[8]) {
+
+ //
+ // Next make sure cardId is not zero
+ //
+
+ byte1 = 0;
+ for (j = 0; j < NUMBER_CARD_ID_BYTES; j++) {
+ byte1 |= cardId[j];
+ }
+ if (byte1 != 0) {
+
+ //
+ // We found a valid Pnp Isa card, assign it a CSN number
+ //
+
+ PipWriteAddress(SET_CSN_PORT);
+
+ PipWriteData(++csn);
+
+ //
+ // Do Wake[CSN] command to put the newly isolated card to
+ // sleep state and other un-isolated cards to isolation
+ // state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ continue; // ... to isolate more cards ...
+ }
+ }
+ break; // could not isolate more cards ...
+ }
+
+ //
+ // If we isolated at least one card, it means the read data port we use
+ // must be good and we can stop the isolation process. Otherwise try another
+ // read data port address.
+ //
+
+ if (csn != 0 || *ReadDataPort) {
+ if (*ReadDataPort == NULL) {
+ *ReadDataPort = PipReadDataPort;
+ }
+ break;
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+ *NumberCSNs = csn;
+}
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the Pnp Isa card data for the Next logical
+ device tag encountered. The input *CardData should point to an logical device id tag,
+ which is the current logical device tag. If the *CardData does not point to a logical
+ device id tag, it will be moved to next tag.
+
+Arguments:
+
+ CardData - a variable to supply a pointer to the pnp Isa resource descriptors and to
+ receive next logical device tag pointer.
+
+ Limit - a variable to supply the maximum length of the search and to receive the new
+ lemit after the search.
+
+Return Value:
+
+ Length of the data between current and next logical device tags, ie the data length
+ of the current logical device.
+ In case there is no 'next' logical device tag, the returned *CardData = NULL,
+ *Limit = zero and the data length of current logical tag is returned as function
+ returned value.
+
+--*/
+{
+ UCHAR tag;
+ USHORT size;
+ LONG l;
+ ULONG retLength;
+ PUCHAR p;
+ BOOLEAN atIdTag = FALSE;;
+
+ p = *CardData;
+ l = *Limit;
+ tag = *p;
+ retLength = 0;
+ while (tag != TAG_COMPLETE_END && l > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(p + 1);
+ size += 3; // length of large tag
+ }
+
+ p += size;
+ retLength += size;
+ l -= size;
+ tag = *p;
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ *CardData = p;
+ *Limit = l;
+ return retLength;
+ }
+ }
+ *CardData = NULL;
+ *Limit = 0;
+ if (tag == TAG_COMPLETE_END) {
+ return (retLength + 2); // add 2 for the length of end tag descriptor
+ } else {
+ return 0;
+ }
+}
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function selects the logical logical device in the specified device.
+
+Arguments:
+
+ Csn - Supplies a CardSelectNumber to select the card.
+
+ LogicalDeviceNumber - supplies a logical device number to select the logical device.
+
+Return Value:
+
+ None
+--*/
+{
+ UCHAR tmp;
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Send WAKE[CSN] to force the card into config state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(Csn);
+
+ //
+ // Select the logical device, disable its io range check and
+ // enable the device.
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(LogicalDeviceNumber);
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+ PipWriteAddress(ACTIVATE_PORT);
+ PipWriteData(1);
+}
diff --git a/private/ntos/nthals/extender/pnpisa/i386/misc.c b/private/ntos/nthals/extender/pnpisa/i386/misc.c
new file mode 100644
index 000000000..0ba14e5ec
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/misc.c
@@ -0,0 +1,626 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+ This file contains pnp isa bus extender support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 27-Jusly-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PiCreateClose)
+#pragma alloc_text(PAGE,PiUnload)
+#pragma alloc_text(PAGE,PipGetRegistryValue)
+#pragma alloc_text(PAGE,PipDecompressEisaId)
+#endif
+
+
+NTSTATUS
+PiCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles open and close requests such that our device objects
+ can be opened. All it does it to complete the Irp with success.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer to the device object to be opened or closed.
+
+ Irp - supplies a pointer to I/O request packet.
+
+Return Value:
+
+ Always returns STATUS_SUCCESS, since this is a null operation.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( DeviceObject );
+
+ PAGED_CODE();
+
+ //
+ // Null operation. Do not give an I/O boost since no I/O was
+ // actually done. IoStatus.Information should be
+ // FILE_OPENED for an open; it's undefined for a close.
+ //
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+
+ IoCompleteRequest( Irp, 0);
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+PiUnload(
+ IN PDRIVER_OBJECT DriverObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine cleans up all of the memory associated with
+ any of the devices belonging to the driver.
+
+Arguments:
+
+ DriverObject - Supplies a pointer to the driver object controling
+ all of the devices.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PVOID lockPtr;
+
+ //
+ // Lock the pageable code section
+ //
+
+ lockPtr = MmLockPagableCodeSection(PiUnload);
+
+ ExAcquireFastMutex (&PipMutex);
+
+ ObDereferenceObject(PipBusExtension->BusHandler->DeviceObject);
+
+ //
+ // Delete all the device info structures and card info structures
+ //
+
+ PipInvalidateCards(PipBusExtension);
+ PipDeleteCards(PipBusExtension);
+
+ //
+ // Finally remove the bus handler reference.
+ //
+
+ HalDereferenceBusHandler (PipBusExtension->BusHandler);
+
+ ExReleaseFastMutex (&PipMutex);
+
+ //
+ // Unlock pageable code section
+ //
+
+ MmUnlockPagableImageSection(lockPtr);
+}
+
+NTSTATUS
+PiReconfigureResources (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN DRIVER_RECONFIGURE_OPERATION Operation,
+ IN PCM_RESOURCE_LIST CmResources
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reconfigures Read Data Port address.
+
+Arguments:
+
+ DriverObject - Supplies a pointer to the driver object controling
+ all of the devices.
+
+ DeviceObject - Supplies a pointer to the device object whoes resources
+ are going to be reconfigured.
+
+ Operation - the operation of the reconfiguration request.
+
+ CmResources - supplies a pointer to the cm resource list.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG port, count, i;
+
+ UNREFERENCED_PARAMETER( DriverObject );
+ UNREFERENCED_PARAMETER( DeviceObject );
+
+ switch (Operation) {
+ case ReconfigureResources:
+ ExAcquireFastMutex(&PipPortMutex);
+
+ //
+ // retrieve the new read data port address
+ //
+
+ ASSERT(CmResources->Count == 1);
+ partialDesc = &CmResources->List[0].PartialResourceList;
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ switch (desc->Type) {
+ case CmResourceTypePort:
+ port = desc->u.Port.Start.LowPart;
+ if (desc->u.Port.Length != 4 || port & 0x3) {
+ return STATUS_UNSUCCESSFUL;
+ } else {
+ port += 3;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeDma:
+ break;
+ }
+ desc++;
+ }
+
+ //
+ // Set read data port to the new setting.
+ //
+
+ PipBusExtension->ReadDataPort = (PUCHAR)port;
+ PipReadDataPort = (PUCHAR)port;
+
+ PipWriteAddress(SET_READ_DATA_PORT);
+ PipWriteData((UCHAR)((ULONG)PipReadDataPort >> 2));
+
+ ExReleaseFastMutex(&PipPortMutex);
+ break;
+
+ case QueryReconfigureResources:
+ case CancelReconfigureQuery:
+ case QueryHardwareProfileChange:
+ case HardwareProfileChanged:
+ default:
+ break;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompressed compressed Eisa Id and returns the Id to caller
+ specified character buffer.
+
+Arguments:
+
+ CompressedId - supplies the compressed Eisa Id.
+
+ EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT c1, c2;
+ LONG i;
+
+ PAGED_CODE();
+
+ CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
+ c1 = c2 = (USHORT)CompressedId;
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ for (i = 2; i >= 0; i--) {
+ *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
+ c1 >>= 5;
+ }
+ EisaId += 3;
+ c1 = c2 = (USHORT)(CompressedId >> 16);
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ sprintf (EisaId, "%04x", c1);
+}
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to retrieve the data for a registry key's value.
+ This is done by querying the value of the key with a zero-length buffer
+ to determine the size of the value, and then allocating a buffer and
+ actually querying the value into the buffer.
+
+ It is the responsibility of the caller to free the buffer.
+
+Arguments:
+
+ KeyHandle - Supplies the key handle whose value is to be queried
+
+ ValueName - Supplies the null-terminated Unicode name of the value.
+
+ Information - Returns a pointer to the allocated data buffer.
+
+Return Value:
+
+ The function value is the final status of the query operation.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PKEY_VALUE_FULL_INFORMATION infoBuffer;
+ ULONG keyValueLength;
+
+ PAGED_CODE();
+
+ RtlInitUnicodeString( &unicodeString, ValueName );
+
+ //
+ // Figure out how big the data value is so that a buffer of the
+ // appropriate size can be allocated.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ (PVOID) NULL,
+ 0,
+ &keyValueLength );
+ if (status != STATUS_BUFFER_OVERFLOW &&
+ status != STATUS_BUFFER_TOO_SMALL) {
+ return status;
+ }
+
+ //
+ // Allocate a buffer large enough to contain the entire key data value.
+ //
+
+ infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
+ if (!infoBuffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Query the data for the key value.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ infoBuffer,
+ keyValueLength,
+ &keyValueLength );
+ if (!NT_SUCCESS( status )) {
+ ExFreePool( infoBuffer );
+ return status;
+ }
+
+ //
+ // Everything worked, so simply return the address of the allocated
+ // buffer to the caller, who is now responsible for freeing it.
+ //
+
+ *Information = infoBuffer;
+ return STATUS_SUCCESS;
+}
+#if DBG
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This routine displays debugging message or causes a break.
+
+Arguments:
+
+ Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
+ DEBUG_BREAK - displays message and break.
+
+ DebugMessage - supplies a pointer to the debugging message.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ if (Level == DEBUG_BREAK) {
+ DbgBreakPoint();
+ }
+
+ va_end(ap);
+}
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR c = ' ';
+
+ if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
+ c = 'A';
+ } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
+ c = 'P';
+ }
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
+ Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
+ Desc->u.Port.Alignment,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
+ Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
+ Desc->u.Memory.Alignment,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Interrupt.MinimumVector,
+ Desc->u.Interrupt.MaximumVector
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Dma.MinimumChannel,
+ Desc->u.Dma.MaximumChannel
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays Io resource requirements list.
+
+Arguments:
+
+ IoList - supplies a pointer to the Io resource requirements list to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIO_RESOURCE_LIST resList;
+ PIO_RESOURCE_DESCRIPTOR resDesc;
+ ULONG listCount, count, i, j;
+
+ DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
+ listCount = IoList->AlternativeLists;
+ resList = &IoList->List[0];
+ for (i = 0; i < listCount; i++) {
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
+ resList->Revision, resList->Count);
+ resDesc = &resList->Descriptors[0];
+ count = resList->Count;
+ for (j = 0; j < count; j++) {
+ PipDumpIoResourceDescriptor(" ", resDesc);
+ resDesc++;
+ }
+ resList = (PIO_RESOURCE_LIST) resDesc;
+ }
+}
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
+ Indent,
+ Desc->u.Interrupt.Level,
+ Desc->u.Interrupt.Vector,
+ Desc->u.Interrupt.Affinity
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA Channel: %x, Port: %x\n",
+ Indent,
+ Desc->u.Dma.Channel,
+ Desc->u.Dma.Port
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine displays CM resource list.
+
+Arguments:
+
+ CmList - supplies a pointer to CM resource list
+
+ SlotNumber - slot number of the resources
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG count, i;
+
+ fullDesc = &CmList->List[0];
+ DbgPrint("Pnp Bios Cm Resource List for Slot %x -\n", SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
+ partialDesc = &fullDesc->PartialResourceList;
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
+ partialDesc->Revision, partialDesc->Count);
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ PipDumpCmResourceDescriptor(" ", desc);
+ desc++;
+ }
+}
+#endif
diff --git a/private/ntos/nthals/extender/pnpisa/i386/pnpisa.h b/private/ntos/nthals/extender/pnpisa/i386/pnpisa.h
new file mode 100644
index 000000000..b36f77d16
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/pnpisa.h
@@ -0,0 +1,155 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pnpisa.h
+
+Abstract:
+
+ This module contins definitions/declarations for PNP ISA related
+ definitions.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-12-1995
+
+Revision History:
+
+--*/
+
+#ifndef NEC_98
+#define ADDRESS_PORT 0x0279
+#define COMMAND_PORT 0x0a79
+#else
+#define ADDRESS_PORT 0x0259
+#define COMMAND_PORT 0x0a59
+#endif // NEC_98
+
+//
+// Plug and Play Card Control Registers
+//
+
+#define SET_READ_DATA_PORT 0x00
+#define SERIAL_ISOLATION_PORT 0x01
+#define CONFIG_CONTROL_PORT 0x02
+#define WAKE_CSN_PORT 0x03
+#define CONFIG_DATA_PORT 0x04
+#define CONFIG_DATA_STATUS_PORT 0x05
+#define SET_CSN_PORT 0x06
+#define LOGICAL_DEVICE_PORT 0x07
+
+//
+// Plug and Play Logical Device Control Registers
+//
+
+#define ACTIVATE_PORT 0x30
+#define IO_RANGE_CHECK_PORT 0x31
+
+//
+// Config Control command
+//
+
+#define CONTROL_WAIT_FOR_KEY 0x02
+#define CONTROL_RESET_CSN 0x04
+
+//
+// Memory Space Configuration
+//
+
+#define NUMBER_MEMORY_DESCRIPTORS 4
+#define ADDRESS_MEMORY_BASE 0x40
+#define ADDRESS_MEMORY_INCR 0x08
+#define ADDRESS_MEMORY_HI 0x00
+#define ADDRESS_MEMORY_LO 0x01
+#define ADDRESS_MEMORY_CTL 0x02
+#define ADDRESS_MEMORY_CTL_LIMIT 0x01
+#define ADDRESS_MEMORY_UPPER_HI 0x03
+#define ADDRESS_MEMORY_UPPER_LO 0x04
+
+//
+// 32 Bit Memory Space Configuration
+//
+
+#define NUMBER_32_MEMORY_DESCRIPTORS 4
+#define ADDRESS_32_MEMORY_BASE(x) ((PUCHAR)(0x70+((x)*0x10)+((x==0) ? 6 : 0)))
+#define ADDRESS_32_MEMORY_B3 0x0
+#define ADDRESS_32_MEMORY_B2 0x1
+#define ADDRESS_32_MEMORY_B1 0x2
+#define ADDRESS_32_MEMORY_B0 0x3
+#define ADDRESS_32_MEMORY_CTL 0x4
+#define ADDRESS_32_MEMORY_E3 0x5
+#define ADDRESS_32_MEMORY_E2 0x6
+#define ADDRESS_32_MEMORY_E1 0x7
+#define ADDRESS_32_MEMORY_E0 0x8
+
+//
+// Io Space Configuration
+//
+
+#define NUMBER_IO_DESCRIPTORS 8
+#define ADDRESS_IO_BASE 0x60
+#define ADDRESS_IO_INCR 0x02
+#define ADDRESS_IO_BASE_HI 0x00
+#define ADDRESS_IO_BASE_LO 0x01
+
+//
+// Interrupt Configuration
+//
+
+#define NUMBER_IRQ_DESCRIPTORS 2
+#define ADDRESS_IRQ_BASE 0x70
+#define ADDRESS_IRQ_INCR 0x02
+#define ADDRESS_IRQ_VALUE 0x00
+#define ADDRESS_IRQ_TYPE 0x01
+
+//
+// DMA Configuration
+//
+
+#define NUMBER_DMA_DESCRIPTORS 2
+#define ADDRESS_DMA_BASE 0x74
+#define ADDRESS_DMA_INCR 0x01
+#define ADDRESS_DMA_VALUE 0x00
+#define NO_DMA 0x04
+
+//
+// 9 byte serial identifier of a PNP ISA Card
+//
+
+#include "pshpack1.h"
+typedef struct _SERIAL_IDENTIFIER_ {
+ ULONG VenderId;
+ ULONG SerialNumber;
+ UCHAR Checksum;
+} SERIAL_IDENTIFIER, *PSERIAL_IDENTIFIER;
+#include "poppack.h"
+
+//
+// Misc. definitions
+//
+
+#define MIN_READ_DATA_PORT 0x200
+#define MAX_READ_DATA_PORT 0x3ff
+#define MAX_CHARACTER_LENGTH 255
+#define NUMBER_CARD_ID_BYTES 9
+#define NUMBER_CARD_ID_BITS (NUMBER_CARD_ID_BYTES * 8)
+#define CHECKSUMED_BITS 64
+#define LFSR_SEED 0x6A
+#define ISOLATION_TEST_BYTE_1 0x55
+#define ISOLATION_TEST_BYTE_2 0xAA
+
+#define PipWriteAddress(data) WRITE_PORT_UCHAR ((PUCHAR)ADDRESS_PORT, (UCHAR)(data))
+#define PipWriteData(data) WRITE_PORT_UCHAR ((PUCHAR)COMMAND_PORT, (UCHAR)(data))
+#define PipReadData() READ_PORT_UCHAR (PipReadDataPort)
+
+//
+// External references
+//
+
+
+extern PUCHAR PipReadDataPort;
+
+
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/resource.c b/private/ntos/nthals/extender/pnpisa/i386/resource.c
new file mode 100644
index 000000000..f1b4c2fee
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/resource.c
@@ -0,0 +1,555 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ This module contains the high level device resources support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-27-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "..\..\pnpbios\i386\pbios.h"
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR Buffer
+ );
+
+#define IDBG 1
+
+#pragma alloc_text(PAGE,PipGetCompatibleDeviceId)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceId)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,PiCtlSetDeviceResources)
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp isa id for the specified DeviceData
+ and Id index. If Id index = 0, the Hardware ID will be return; if id
+ index = n, the Nth compatible id will be returned.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the pnp isa device data.
+
+ IdIndex - supplies the index of the compatible id desired.
+
+ Buffer - supplies a pointer to a buffer to receive the compatible Id.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_NO_MORE_ENTRIES;
+ UCHAR tag;
+ ULONG count = 0;
+ LONG size;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ ULONG id;
+
+ PAGED_CODE();
+
+ tag = *DeviceData;
+
+#if DBG
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
+ }
+#endif
+
+ if (IdIndex == 0) {
+
+ //
+ // Caller is asking for hardware id
+ //
+
+ DeviceData++; // Skip tag
+ id = *(PULONG)DeviceData;
+ status = STATUS_SUCCESS;
+ } else {
+
+ //
+ // caller is asking for compatible id
+ //
+
+ IdIndex--;
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ while (tag != TAG_COMPLETE_END) {
+
+ //
+ // Do we reach the compatible ID descriptor?
+ //
+
+ if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
+ if (count == IdIndex) {
+ id = *(PULONG)(DeviceData + 1);
+ status = STATUS_SUCCESS;
+ break;
+ } else {
+ count++;
+ }
+ }
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(DeviceData + 1);
+ size += 3; // length of large tag
+ }
+
+ DeviceData += size;
+ tag = *DeviceData;
+ }
+ }
+
+ if (NT_SUCCESS(status)) {
+ PipDecompressEisaId(id, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ swprintf(Buffer, L"PNPISA\\*%s", unicodeString.Buffer);
+ RtlFreeUnicodeString(&unicodeString);
+ }
+ return status;
+}
+
+VOID
+PiCtlQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the unique id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWCHAR deviceId;
+ PUCHAR deviceData;
+ ULONG eisaid;
+
+ PAGED_CODE();
+
+ //
+ // Set up device's unique id.
+ // device unique id = card series number + logical device eisa id in compressed form
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ deviceData = DeviceInfo->DeviceData;
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((*deviceData & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+
+ //
+ // Can not get the eisa compressed id. Use logical device number instead.
+ //
+#if DBG
+ DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
+#endif
+ eisaid = DeviceInfo->LogicalDeviceNumber;
+ } else {
+
+ //
+ // Get the eisa compressed id for the logical device.
+ //
+
+ deviceData++; // Skip tag
+ eisaid = *(PULONG)deviceData;
+ }
+ swprintf (deviceId,
+ L"%08x%08x",
+ ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber,
+ eisaid
+ );
+#if IDBG
+ {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, (PWCHAR)Context->DeviceControl.Buffer);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x Unique Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceInfoSlot(DeviceInfo),
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ PipCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceInfo);
+}
+
+VOID
+PiCtlQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular device.
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+ PWCHAR deviceId;
+ ULONG idIndex;
+
+ PAGED_CODE();
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ idIndex = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // Call worker routine to get the desired Id.
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ status = PipGetCompatibleDeviceId(DeviceInfo->DeviceData,
+ idIndex,
+ (PWCHAR) deviceId);
+
+#if IDBG
+ if (NT_SUCCESS(status)) {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, deviceId);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x IdIndex %x Compatible Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceInfoSlot(DeviceInfo),
+ idIndex,
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
+
+VOID
+PiCtlQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCES DeviceControl
+ which returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length;
+ PCM_RESOURCE_LIST cmResources;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // protect port access
+ //
+
+ ExAcquireFastMutex(&PipPortMutex);
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber
+ );
+
+ status = PipReadDeviceBootResourceData (
+ Context->Handler->BusNumber,
+ DeviceInfo->DeviceData,
+ &cmResources,
+ &length
+ );
+
+ PipWriteAddress(ACTIVATE_PORT);
+ PipWriteData(0);
+
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ ExReleaseFastMutex(&PipPortMutex);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ cmResources = (PCM_RESOURCE_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(CM_RESOURCE_LIST), 'iPnP');
+ if (!cmResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ cmResources->Count = 0;
+ cmResources->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ cmResources->List[0].BusNumber = Context->RootHandler->BusNumber;
+ cmResources->List[0].PartialResourceList.Version = 0;
+ cmResources->List[0].PartialResourceList.Revision = 0;
+ cmResources->List[0].PartialResourceList.Count = 0;
+ length = sizeof(CM_RESOURCE_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, cmResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if IDBG
+ if (NT_SUCCESS(status)) {
+ PipDumpCmResourceList(cmResources, DeviceInfoSlot(DeviceInfo));
+ }
+#endif
+ ExFreePool(cmResources);
+ }
+exitLocal:
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
+
+VOID
+PiCtlQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCE_REQUIREMENTS DeviceControl
+ which returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length = 0;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResources = NULL;
+ NTSTATUS status;
+ PUCHAR deviceData;
+ PAGED_CODE();
+
+ deviceData = DeviceInfo->DeviceData;
+ status = PbBiosResourcesToNtResources (
+ Context->RootHandler->BusNumber,
+ DeviceInfoSlot(DeviceInfo),
+ &deviceData,
+ &ioResources,
+ &length
+ );
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST), 'bPnP');
+ if (!ioResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ ioResources->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResources->InterfaceType = Context->RootHandler->InterfaceType;
+ ioResources->BusNumber = Context->RootHandler->BusNumber;
+ ioResources->SlotNumber = DeviceInfoSlot(DeviceInfo);
+ ioResources->Reserved[0] = 0;
+ ioResources->Reserved[1] = 0;
+ ioResources->Reserved[2] = 0;
+ ioResources->AlternativeLists = 0;
+ ioResources->List[0].Version = 1;
+ ioResources->List[0].Revision = 1;
+ ioResources->List[0].Count = 0;
+ length = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ioResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if IDBG
+ if (NT_SUCCESS(status)) {
+ PipDumpIoResourceList(ioResources);
+ }
+#endif
+ ExFreePool(ioResources);
+ }
+exitLocal:
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
+
+VOID
+PiCtlSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the SET_DEVICE_RESOURCES DeviceControl
+ which configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // Protect port access
+ //
+
+ ExAcquireFastMutex(&PipPortMutex);
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber
+ );
+
+ //
+ // Set resource settings for the device
+ //
+
+ status = PipWriteDeviceBootResourceData (
+ DeviceInfo->DeviceData,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer
+ );
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ ExReleaseFastMutex(&PipPortMutex);
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
diff --git a/private/ntos/nthals/extender/pnpisa/makefile b/private/ntos/nthals/extender/pnpisa/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/extender/pnpisa/pnpisa.rc b/private/ntos/nthals/extender/pnpisa/pnpisa.rc
new file mode 100644
index 000000000..1a87276e5
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/pnpisa.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "PNP ISA Extension Driver"
+#define VER_INTERNALNAME_STR "pnpisa.sys"
+#define VER_ORIGINALFILENAME_STR "pnpisa.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pnpisa/sources b/private/ntos/nthals/extender/pnpisa/sources
new file mode 100644
index 000000000..cbea7153e
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=extender
+
+TARGETNAME=pnpisa
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=
+
+i386_SOURCES=pnpisa.rc \
+ i386\bus.c \
+ i386\control.c \
+ i386\data.c \
+ i386\init.c \
+ i386\isolate.c \
+ i386\misc.c \
+ i386\convert.c \
+ i386\resource.c
+
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=
diff --git a/private/ntos/nthals/hal.src b/private/ntos/nthals/hal.src
new file mode 100644
index 000000000..8a8824d32
--- /dev/null
+++ b/private/ntos/nthals/hal.src
@@ -0,0 +1,171 @@
+LIBRARY HAL
+
+DESCRIPTION 'HAL DLL'
+
+EXPORTS
+ HalAcquireDisplayOwnership
+ HalAdjustResourceList
+ HalAllocateAdapterChannel
+ HalAllocateCommonBuffer
+ HalAllocateCrashDumpRegisters
+ HalAllProcessorsStarted
+ HalAssignSlotResources
+ HalCalibratePerformanceCounter
+ HalDisableSystemInterrupt
+ HalDisplayString
+ HalEnableSystemInterrupt
+ HalFlushCommonBuffer
+ HalFreeCommonBuffer
+ HalGetAdapter
+ HalGetBusData
+ HalGetBusDataByOffset
+ HalGetEnvironmentVariable
+ HalGetInterruptVector
+ HalInitializeProcessor
+ HalInitSystem
+ HalMakeBeep
+ HalProcessorIdle
+ HalQueryDisplayParameters
+ HalQueryRealTimeClock
+ HalReadDmaCounter
+ HalReportResourceUsage
+ HalRequestIpi
+ HalReturnToFirmware
+ HalSetBusData
+ HalSetBusDataByOffset
+ HalSetDisplayParameters
+ HalSetEnvironmentVariable
+ HalSetProfileInterval
+ HalSetRealTimeClock
+ HalSetTimeIncrement
+ HalStartNextProcessor
+ HalStartProfileInterrupt
+ HalStopProfileInterrupt
+ HalTranslateBusAddress
+
+ IoAssignDriveLetters
+ IoFlushAdapterBuffers
+ IoFreeAdapterChannel
+ IoFreeMapRegisters
+ IoMapTransfer
+ IoReadPartitionTable
+ IoSetPartitionInformation
+ IoWritePartitionTable
+
+ KdPortGetByte
+ KdPortInitialize
+ KdPortPollByte
+ KdPortPutByte
+ KdPortRestore
+ KdPortSave
+
+ KeFlushWriteBuffer
+ KeQueryPerformanceCounter
+ KeStallExecutionProcessor
+
+#if defined(i386)
+
+ KeRaiseIrql
+ KeLowerIrql
+ KfRaiseIrql
+ KfLowerIrql
+ KeRaiseIrqlToDpcLevel
+ KeRaiseIrqlToSynchLevel
+ KeGetCurrentIrql
+ KeAcquireSpinLock
+ KeReleaseSpinLock
+ KfAcquireSpinLock
+ KfReleaseSpinLock
+ KeAcquireSpinLockRaiseToSynch
+ ExAcquireFastMutex
+ ExTryToAcquireFastMutex
+ ExReleaseFastMutex
+ HalClearSoftwareInterrupt
+ HalRequestSoftwareInterrupt
+ HalSystemVectorDispatchEntry
+ HalBeginSystemInterrupt
+ HalEndSystemInterrupt
+ HalHandleNMI
+
+ READ_PORT_UCHAR
+ READ_PORT_USHORT
+ READ_PORT_ULONG
+ READ_PORT_BUFFER_UCHAR
+ READ_PORT_BUFFER_USHORT
+ READ_PORT_BUFFER_ULONG
+ WRITE_PORT_UCHAR
+ WRITE_PORT_USHORT
+ WRITE_PORT_ULONG
+ WRITE_PORT_BUFFER_UCHAR
+ WRITE_PORT_BUFFER_USHORT
+ WRITE_PORT_BUFFER_ULONG
+
+#endif
+
+ KdComPortInUse CONSTANT // *BUGBUG* - remove when cfgmgr works
+
+#if defined(MIPS) || defined(ALPHA)
+
+ HalCallBios
+ HalChangeColorPage
+ HalFlushDcachePage
+ HalFlushIoBuffers
+ HalGetDmaAlignmentRequirement
+ HalPurgeDcachePage
+ HalPurgeIcachePage
+ HalSweepDcache
+ HalSweepDcacheRange
+ HalSweepIcache
+ HalSweepIcacheRange
+ HalZeroPage
+
+#endif
+
+#if defined(ALPHA)
+
+ HalCreateQva
+ HalDereferenceQva
+
+ READ_REGISTER_UCHAR
+ READ_REGISTER_USHORT
+ READ_REGISTER_ULONG
+ READ_REGISTER_BUFFER_UCHAR
+ READ_REGISTER_BUFFER_USHORT
+ READ_REGISTER_BUFFER_ULONG
+ WRITE_REGISTER_UCHAR
+ WRITE_REGISTER_USHORT
+ WRITE_REGISTER_ULONG
+ WRITE_REGISTER_BUFFER_UCHAR
+ WRITE_REGISTER_BUFFER_USHORT
+ WRITE_REGISTER_BUFFER_ULONG
+ READ_PORT_UCHAR
+ READ_PORT_USHORT
+ READ_PORT_ULONG
+ READ_PORT_BUFFER_UCHAR
+ READ_PORT_BUFFER_USHORT
+ READ_PORT_BUFFER_ULONG
+ WRITE_PORT_UCHAR
+ WRITE_PORT_USHORT
+ WRITE_PORT_ULONG
+ WRITE_PORT_BUFFER_UCHAR
+ WRITE_PORT_BUFFER_USHORT
+ WRITE_PORT_BUFFER_ULONG
+
+#endif
+
+#if defined(PPC)
+
+ KeRaiseIrql
+ KeLowerIrql
+
+ HalCallBios
+
+ HalSweepDcache
+ HalSweepDcacheRange
+ HalSweepIcache
+ HalSweepIcacheRange
+
+ HalGetDmaAlignmentRequirement
+ HalFlushIoBuffers
+
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/allstart.c b/private/ntos/nthals/hal0jens/alpha/allstart.c
new file mode 100644
index 000000000..9bb5501bc
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/allstart.c
@@ -0,0 +1,55 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ John Vert (jvert) 23-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+ return TRUE;
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/axebsup.c b/private/ntos/nthals/hal0jens/alpha/axebsup.c
new file mode 100644
index 000000000..b34b07320
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/axebsup.c
@@ -0,0 +1,786 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ axebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for Alpha/Jensen systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+ Miche Baker-Harvey (miche) 13-May-1992
+ Jeff McLeman (DEC) 1-Jun-1992
+
+Revision History:
+
+ 11-Mar-1993 Joe Mitchell (DEC)
+ Added support for NMI interrupts: Added interrupt service routine
+ HalHandleNMI. Added code to HalpCreateEisaStructures to initialize
+ NMI interrupts.
+
+ 22-Jul-1992 Jeff McLeman (mcleman)
+ Removed eisa xfer routines, since this is done in JXHWSUP
+
+ 02-Jul-92 Jeff McLeman (mcleman)
+ Removed alphadma.h header file. This file was not needed since
+ the DMA structure is described in the eisa header. Also add
+ a note describing eisa references in this module.
+
+ 13-May-92 Stole file jxebsup.c and converted for Alpha/Jensen
+
+
+--*/
+
+// ** note **
+// This module has routines that manipulate eisa on alpha machines. On
+// the jensen machine, this is done in jxhwsup.c . These routines
+// would be used for an alpha machine that had a local bus and an
+// eisa bus.
+//
+
+
+#include "halp.h"
+#include "jnsndef.h"
+#include "jnsnint.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Declare the interupt structure and spinlock for the intermediate EISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpEisaInterrupt;
+
+/* [jrm 3/8/93] Add support for NMI interrupts */
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ESIA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask registers and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Enable Software-Generated NMI interrupts by setting bit 1 of port 0x461.
+ //
+
+ DataByte = 0x02;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ //
+ // Initialize the EISA interrupt dispatcher for Jazz I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpEisaInterrupt,
+ HalpEisaDispatch,
+ (PVOID) EISA_INTA_CYCLE_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL,
+ PIC_VECTOR,
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpEisaInterrupt )) {
+
+ return(FALSE);
+ }
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_LEVEL, EISA_LEVEL, EISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ //
+ // schedule the read
+ //
+
+ HalpMb();
+
+ KeStallExecutionProcessor(1);
+
+ interruptVector = READ_PORT_UCHAR(ServiceContext);
+
+
+ if ((interruptVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return(TRUE);
+
+ }
+
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+ PCRInOffset = interruptVector + EISA_VECTORS;
+ DispatchCode = PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH) InterruptObject->DispatchAddress)(
+ InterruptObject,
+ NULL);
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2, it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+ }
+
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ BusAddress.HighPart = 0;
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++)
+ {
+ BusAddress.LowPart = (EisaPort << 12) + 0xC80;
+
+ Status = HalTranslateBusAddress(Eisa, // InterfaceType
+ 0, // BusNumber (0 for Jensen)
+ BusAddress,
+ &AddressSpace, // 1=I/O address space
+ &TranslatedAddress); // QVA
+ if (Status == FALSE)
+ {
+ UCHAR pbuf[80];
+ sprintf(pbuf,
+ "Unable to translate bus address %x for EISA slot %d\n",
+ BusAddress.LowPart, EisaPort);
+ HalDisplayString(pbuf);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+
+ port = TranslatedAddress.LowPart;
+
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+#if 0
+ // Reset NMI interrupts (for debugging purposes only).
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02);
+#endif
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/axibsup.c b/private/ntos/nthals/hal0jens/alpha/axibsup.c
new file mode 100644
index 000000000..5a35ec785
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/axibsup.c
@@ -0,0 +1,1089 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ axibsup.c
+
+Abstract:
+
+ The module provides the ISA bus support for Alpha/Beta
+ (Alpha PC) systems.
+ The system uses the 82380 chip set, defined in the 386 microprocessor
+ handbook. Only PICs B and C have ISA devices attached to them.
+ There is some problem with DMA on Beta; it might not work.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+ Miche Baker-Harvey (miche) 13-May-1992
+
+Revision History:
+ 13-May-92 Stole file jxebsup.c and converted for Alpha/Beta
+
+--*/
+
+#include "halp.h"
+// MBH: should these files really be alpha, or should they be Beta
+#include "alphadma.h"
+#include "alphadef.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Declare the interupt structure and spinlock for the intermediate ISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpIsaInterrupt;
+
+//
+// Define save area for SIA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpIsaInterrupt1Mask;
+UCHAR HalpIsaInterrupt2Mask;
+UCHAR HalpIsaInterrupt3Mask;
+UCHAR HalpIsaInterrupt1Level;
+UCHAR HalpIsaInterrupt2Level;
+UCHAR HalpIsaInterrupt3Level;
+
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter( // MBH: not touched
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4) {
+ return(NULL);
+ }
+
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) IopAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_PORT_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateIsaStructures ( // MBH: not touched
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for ISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ ISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA interrupt dispatcher for Jazz I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpEisaInterrupt,
+ HalpEisaDispatch,
+ (PVOID) &(DMA_CONTROL->InterruptAcknowledge.Long),
+ (PKSPIN_LOCK)NULL,
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpEisaInterrupt )) {
+
+ return(FALSE);
+ }
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // TEMP: Reset the Eisa bus, since the firmware does not do for a reboot.
+ //
+
+ DataByte = 0;
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(3);
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ //
+
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpIsaDispatch( // MBH: not touched
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the ISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the ISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_LEVEL, EISA_LEVEL, EISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ //
+ // Get the PRCB.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[EISA_VECTORS + interruptVector])(
+ PCR->InterruptRoutine[EISA_VECTORS + interruptVector]
+ );
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableIsaInterrupt(
+ IN CCHAR Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the ISA bus specified ISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the ISA interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2 or 3.
+ //
+
+ if (Vector & 0x10) {
+
+ //
+ // The interrupt is in controller 3.
+ // Write the mask into OCW1 (same address as ICW2)
+ //
+
+ Vector &= 0x7;
+
+ HalpIsaInterrupt3Mask |= 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PISA_CONTROL) HalpIsaControlBase)->Interrupt3ControlPort1,
+ HalpIsaInterrupt3Mask
+ );
+
+ } else if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpIsaInterrupt2Mask |= 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PISA_CONTROL) HalpIsaControlBase)->Interrupt2ControlPort1,
+ HalpIsaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // Only allowed ISA devices in banks B and C, so this is an error
+ //
+
+ HalDisplayString("Disabling ISA Interrupt in Bank A");
+// MBH: I made up this bug check number - where are they defined?
+ KeBugCheck(0x81);
+
+ }
+
+}
+
+VOID
+HalpIsaMapTransfer( // MBH: not touched
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the ISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT((Offset >= 0x100000 && !(Length & 1)));
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+}
+
+VOID
+HalpEnableIsaInterrupt(
+ IN CCHAR Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the ISA bus specified ISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the ISA interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1, 2 or 3.
+ //
+
+ if (Vector & 0x10) {
+
+ //
+ // The interrupt is in controller 3.
+ //
+
+ Vector &= 0x7;
+
+ HalpIsaInterrupt3Mask &= ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PISA_CONTROL) HalpIsaControlBase)->Interrupt3ControlPort1,
+ HalpIsaInterrupt3Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpIsaInterrupt3Level |= (1 << Vector);
+
+ } else {
+
+ HalpIsaInterrupt3Level &= ~(1 << Vector);
+
+ }
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpIsaInterrupt2Mask &= ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PISA_CONTROL) HalpIsaControlBase)->Interrupt2ControlPort1,
+ HalpIsaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpIsaInterrupt2Level |= (1 << Vector);
+
+ } else {
+
+ HalpIsaInterrupt2Level &= ~(1 << Vector);
+
+ }
+
+ } else {
+
+ //
+ // Only allowed ISA devices in banks B and C, so this is an error
+ //
+
+ HalDisplayString("Enabling ISA Interrupt in Bank A");
+// MBH: I made up this bug check number - where are they defined?
+ KeBugCheck(0x82);
+
+ }
+
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/axlbsup.c b/private/ntos/nthals/hal0jens/alpha/axlbsup.c
new file mode 100644
index 000000000..41566ff77
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/axlbsup.c
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ .../ntos/hal/alpha/axlbsup.c
+
+Abstract:
+
+
+ These routines are used to access the 82C106 on various platforms.
+ It is local for both Beta and Jensen, but Beta accesses it through
+ the Xbus while Jensen accesses it through the Hbus.
+ These routines assume that a port number and data is sufficient.
+
+ Stolen from Joe Notarangelo's hal.c in nttools
+
+Author:
+
+ Joe Notarangelo
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalpWriteVti(
+ ULONG Port,
+ UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This function writes a byte to the specified port in the VTI 82C106
+
+Arguments:
+
+ Port - Supplies the local port number
+ Data - Byte of data to be written to the port
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ outVti( Port, Data );
+}
+
+UCHAR
+HalpReadVti(
+ ULONG Port
+ )
+/*++
+
+Routine Description:
+
+ This function writes a byte to the specified port in the VTI 82C106.
+
+
+Arguments:
+
+ Port - Supplies the local port number
+
+
+Return Value:
+
+ Data byte read from port
+
+--*/
+{
+ return( (UCHAR)inVti( Port ) );
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/axsysint.c b/private/ntos/nthals/hal0jens/alpha/axsysint.c
new file mode 100644
index 000000000..102818113
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/axsysint.c
@@ -0,0 +1,473 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ axsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the alpha system JENSEN.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+ Miche Baker-Harvey (miche) 13-May-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 08-Jul-1992 Joe Notarangelo
+ Add support for performance counter interrupts.
+ Add support to enable/disable serial and keyboard interrupts via the
+ standard HalEnable/Disable interfaces.
+ NOTE: This module is now, decidely JENSEN-specific.
+
+ 28-Jul-1992 Jeff McLeman (DEC)
+ Remove reference to ISA
+
+ 13-May-92 Converted to Alpha Beta and Jensen (EV4-based)
+ systems. Stole from jxsysint.c
+ Beta is ISA/82380; Jensen is EISA/82357, as is Jazz
+
+--*/
+
+#include "halp.h"
+#include "jnsnint.h"
+#include "jnsndef.h"
+#include "axp21064.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors (serial and keyboard/mouse for JENSEN) then disable the
+ // interrupt in the IET and alert the PAL to re-cache the interrupt
+ // enable masks.
+ //
+
+ if( (Vector == SERIAL_VECTOR) ||
+ (Vector == KEYBOARD_MOUSE_VECTOR) ||
+ (Vector == PC0_VECTOR) ||
+ (Vector == PC1_VECTOR) ){
+
+ IetEntry = (PIETEntry_21064)&PCR->IrqlTable;
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 0;
+ break;
+
+ case PC1_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 0;
+ break;
+
+ case SERIAL_VECTOR:
+
+ IetEntry[IrqlIndex].Irq5Enable = 0;
+ break;
+
+ case KEYBOARD_MOUSE_VECTOR:
+
+ IetEntry[IrqlIndex].Irq3Enable = 0;
+ break;
+
+ } //end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ } //end if Vector == SERIAL_VECTOR, etc.
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors (serial or keyboard/mouse) then enable the
+ // interrupt in the IET and alert the PAL to re-cache the interrupt
+ // enable masks.
+ //
+
+ if( (Vector == SERIAL_VECTOR) ||
+ (Vector == KEYBOARD_MOUSE_VECTOR) ||
+ (Vector == PC0_VECTOR) ||
+ (Vector == PC1_VECTOR) ){
+
+ IetEntry = (PIETEntry_21064)&PCR->IrqlTable;
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 1;
+ break;
+
+ case PC1_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 1;
+ break;
+
+ case SERIAL_VECTOR:
+
+ IetEntry[IrqlIndex].Irq5Enable = 1;
+ break;
+
+ case KEYBOARD_MOUSE_VECTOR:
+
+ IetEntry[IrqlIndex].Irq3Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ } //end if Vector == SERIAL_VECTOR, etc.
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ *Affinity = 1;
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if(InterfaceType == ProcessorInternal) {
+
+ *Irql = IPI_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_VECTOR;
+
+ //
+ // Unrecognized.
+ //
+
+ default:
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end switch( BusInterruptLevel )
+
+ } // end if InterfaceType == ProcessorInternal
+
+ //
+ // If this is for the internal bus then everything but the serial
+ // lines comes in on DEVICE_LOW, and the vector depends on the
+ // particular device. We have coded things like "SERIAL_VECTOR"
+ // into the drivers for the built-in devices.
+ //
+
+ if (InterfaceType == Internal) {
+
+ if (BusInterruptVector == SERIAL_VECTOR) {
+
+ //
+ // This is the only device which interrupts at DEVICE_HIGH_LEVEL
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ } else {
+
+ *Irql = DEVICE_LOW_LEVEL;
+
+ }
+
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType == Isa) {
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the Jensen system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+
+ }
+
+ if (InterfaceType == Eisa) {
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+ }
+
+ //
+ // Not an interface supported on Alpha systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ For all currently known machines - there's only one processor
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/bios.c b/private/ntos/nthals/hal0jens/alpha/bios.c
new file mode 100644
index 000000000..52b5dc898
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/bios.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ bios.c
+
+Abstract:
+
+ This module implements ROM BIOS call support for Alpha AXP NT.
+
+Author:
+
+ Eric Rehm (rehm@zso.dec.com) 9-December-1993
+
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "alpharef.h"
+#include "fwcallbk.h"
+
+
+//
+// Static data.
+//
+// none.
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG pEax,
+ IN OUT PULONG pEbx,
+ IN OUT PULONG pEcx,
+ IN OUT PULONG pEdx,
+ IN OUT PULONG pEsi,
+ IN OUT PULONG pEdi,
+ IN OUT PULONG pEbp
+ )
+
+/*++
+
+Routine Description:
+
+ This function invokes specified ROM BIOS code by executing
+ "INT BiosCommand." A callback to the i386 emulator loaded by
+ the firmware accomplishes this task. This function always
+ returns success reguardless of the result of the BIOS call.
+
+
+Arguments:
+
+ BiosCommand - specifies which ROM BIOS function to invoke.
+
+ BiosArguments - specifies a pointer to the context which will be used
+ to invoke ROM BIOS.
+
+Return Value:
+
+ TRUE if function succees, FALSE otherwise.
+
+--*/
+{
+
+ X86_BIOS_ARGUMENTS context;
+
+ context.Edi = *pEdi;
+ context.Esi = *pEsi;
+ context.Eax = *pEax;
+ context.Ebx = *pEbx;
+ context.Ecx = *pEcx;
+ context.Edx = *pEdx;
+ context.Ebp = *pEbp;
+
+ //
+ // Now call the firmware to actually perform the int 10 operation.
+ //
+
+ VenCallBios(BiosCommand, &context);
+
+ //
+ // fill in struct with any return values from the context
+ //
+
+ *pEdi = context.Edi;
+ *pEsi = context.Esi;
+ *pEax = context.Eax;
+ *pEbx = context.Ebx;
+ *pEcx = context.Ecx;
+ *pEdx = context.Edx;
+ *pEbp = context.Ebp;
+
+
+ //
+ // Indicate success
+ //
+
+ return TRUE;
+}
+
diff --git a/private/ntos/nthals/hal0jens/alpha/ev4ints.s b/private/ntos/nthals/hal0jens/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/hal0jens/alpha/ev4prof.c b/private/ntos/nthals/hal0jens/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/hal0jens/alpha/halp.h b/private/ntos/nthals/hal0jens/alpha/halp.h
new file mode 100644
index 000000000..25d7a66c0
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/halp.h
@@ -0,0 +1,223 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 22-Apr-1992
+
+
+Revision History:
+
+ 09-Jul-1992 Jeff McLeman (mcleman)
+ If processor is an Alpha, include XXHALP.C for Alpha.
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "hal.h"
+
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+VOID
+HalpPerformanceCounter0Interrupt (
+ VOID
+ );
+
+VOID
+HalpPerformanceCounter1Interrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ );
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberOfPages
+ );
+
+PVOID
+HalpRemapVirtualAddress(
+ IN PVOID VirtualAddress,
+ IN PVOID PhysicalAddress
+ );
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NumberOfPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ );
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpVideoReboot(
+ VOID
+ );
+
+//
+// Define Bus Handler support function prototypes.
+//
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+#if defined(JENSEN)
+
+#include "jxhalp.h"
+
+#endif
+
+#if defined(FLAMINGO)
+
+#include "fxhalp.h"
+
+#endif
+
+//
+// Include alpha processor interfaces
+//
+
+#include "xxhalp.h"
+
+//
+// Define external references.
+//
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextRateSelect;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+extern ULONG HalpClockFrequency;
+extern ULONG HalpClockMegaHertz;
+
+extern ULONG HalpProfileCountRate;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern BOOLEAN LessThan16Mb;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+extern ULONG HalpCpuType;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/hal0jens/alpha/halpal.s b/private/ntos/nthals/hal0jens/alpha/halpal.s
new file mode 100644
index 000000000..1a0ea3a36
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/halpal.s
@@ -0,0 +1,184 @@
+// TITLE("Alpha PAL funtions for HAL")
+//++
+//
+// Copyright (c) 1992-1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// palhalt.s
+//
+// Abstract:
+//
+// This module implements routines to call PAL functions
+// from the Hal.
+//
+//
+// Author:
+//
+// Jeff McLeman (mcleman) 09-Jul-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 13-Jul-1992 Jeff McLeman (mcleman)
+// add HalpMb to functions.
+//
+// 14-Dec-1993 Joe Notarangelo
+// Change HalpHalt to HalpReboot to fit new call pal encodings.
+//--
+
+#include "ksalpha.h"
+
+//++
+//
+// VOID
+// HalpReboot(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to reboot the Alpha processor.
+// THis is used to restart the console firmware. (Note, MIPS does
+// not have a REBOOT instruction, so there had to be a mechanism to
+// restart the firware. Alpha merely reboots, which causes a jump
+// to firmware PAL, which restarts the firmware.)
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReboot)
+
+ REBOOT // call the PAL to reboot to firmware
+
+ .end HalpReboot
+
+//++
+//
+// VOID
+// HalpImb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue an Instruction
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpImb)
+
+ IMB // call the PAL to do an IMB
+
+ ret zero,(ra)
+
+ .end HalpImb
+
+
+//++
+//
+// VOID
+// HalpMb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a general
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpMb)
+
+ mb // memory barrier
+
+ ret zero, (ra)
+
+ .end HalpMb
+
+//++
+//
+// VOID
+// HalpCachePcrValues(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to cache values in the
+// PCR for faster access.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCachePcrValues)
+
+ CACHE_PCR_VALUES // call the palcode
+
+ ret zero,(ra)
+
+ .end HalpCachePcrValues
+//++
+//
+// ULONG
+// HalpRpcc(
+// )
+//
+// Routine Description:
+//
+// This function executes the RPCC (read processor cycle counter)
+// instruction.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The low-order 32 bits of the processor cycle counter is returned
+// as the function value.
+// N.B. At 125 MHz this counter wraps about every 30 seconds. It is
+// the caller's responsibility to deal with overflow or wraparound.
+//
+//--
+
+ LEAF_ENTRY(HalpRpcc)
+
+ rpcc v0 // get rpcc value
+ addl v0, zero, v0 // extend
+
+ ret zero, (ra) // return
+
+ .end HalpRpcc
+
diff --git a/private/ntos/nthals/hal0jens/alpha/halvga.h b/private/ntos/nthals/hal0jens/alpha/halvga.h
new file mode 100644
index 000000000..c1727bd4a
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/halvga.h
@@ -0,0 +1,72 @@
+/*
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ halvga.h
+
+
+Abstract:
+
+ Defines registers for standard VGA alphanumeric color mode video.
+ (graphics, bw mode are not defined.)
+
+ Addresses are based on the VGA video ISA base address.
+
+
+Author:
+
+ John DeRosa 4/30/92
+
+
+Revision History:
+
+ 17-Feb-1994 Eric Rehm
+ Remove all references to VGA. HAL display routines are
+ now device-independent.
+
+*/
+
+#ifndef _HALVGA_
+#define _HALVGA_
+
+//
+// Define special character values for device-indpendent control functions.
+//
+
+#define ASCII_NUL 0x00
+#define ASCII_BEL 0x07
+#define ASCII_BS 0x08
+#define ASCII_HT 0x09
+#define ASCII_LF 0x0A
+#define ASCII_VT 0x0B
+#define ASCII_FF 0x0C
+#define ASCII_CR 0x0D
+#define ASCII_CSI 0x9B
+#define ASCII_ESC 0x1B
+#define ASCII_SYSRQ 0x80
+
+//
+// Define colors, HI = High Intensity
+//
+//
+
+#define FW_COLOR_BLACK 0x00
+#define FW_COLOR_RED 0x01
+#define FW_COLOR_GREEN 0x02
+#define FW_COLOR_YELLOW 0x03
+#define FW_COLOR_BLUE 0x04
+#define FW_COLOR_MAGENTA 0x05
+#define FW_COLOR_CYAN 0x06
+#define FW_COLOR_WHITE 0x07
+#define FW_COLOR_HI_BLACK 0x08
+#define FW_COLOR_HI_RED 0x09
+#define FW_COLOR_HI_GREEN 0x0A
+#define FW_COLOR_HI_YELLOW 0x0B
+#define FW_COLOR_HI_BLUE 0x0C
+#define FW_COLOR_HI_MAGENTA 0x0D
+#define FW_COLOR_HI_CYAN 0x0E
+#define FW_COLOR_HI_WHITE 0x0F
+
+#endif // _HALVGA_
diff --git a/private/ntos/nthals/hal0jens/alpha/idle.s b/private/ntos/nthals/hal0jens/alpha/idle.s
new file mode 100644
index 000000000..0d53d7aed
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/idle.s
@@ -0,0 +1,62 @@
+// TITLE("Processor Idle Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// idle.s
+//
+// Abstract:
+//
+// This module implements the HalProcessorIdle interface
+//
+// Author:
+//
+// John Vert (jvert) 11-May-1994
+//
+// Environment:
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with interrupts disabled. This routine
+// must do any power management enabling necessary, enable interrupts,
+// then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+ ENABLE_INTERRUPTS // no power management, just
+ // enable interrupts and return
+ ret zero, (ra)
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/hal0jens/alpha/jenfonts.h b/private/ntos/nthals/hal0jens/alpha/jenfonts.h
new file mode 100644
index 000000000..3a4113621
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jenfonts.h
@@ -0,0 +1,231 @@
+/*
+
+Module Name:
+
+ jenfonts.h
+
+Abstract:
+
+ 8x16 pixel fonts for the VGA video boot driver. Stolen from
+ David Conroy's Beta-machine fonts.
+
+
+
+Author:
+
+ John DeRosa 5/7/1992
+
+
+
+Revision History:
+
+ Jeff McLeman (DEC) 28-Jul-1992
+ Stole from FW to use with HAL and renamed to header file
+
+*/
+
+
+/*
+ * ASCII characters 0x20 -- 0x7f (space -- del). Each byte is one
+ * scan line, and each character is 2 rows.
+ */
+
+unsigned char vga8x16undef[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+unsigned char vga8x16chars[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0xFF, 0xFF, 0x66, 0x66,
+ 0xFF, 0xFF, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x3E, 0x7E, 0x60, 0x60, 0x7C, 0x3E,
+ 0x06, 0x06, 0x7E, 0x7C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x6C, 0x0C, 0x18, 0x18,
+ 0x30, 0x36, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x38, 0x7C, 0x6C, 0x6C, 0x38, 0x38, 0x70, 0x70,
+ 0xDE, 0xDE, 0xCC, 0xCC, 0xFE, 0x76, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x1C, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x1C, 0x0C, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x30, 0x38, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x38, 0x30, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x3C, 0x3C, 0xFF, 0xFF,
+ 0x3C, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E,
+ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x30, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x18,
+ 0x18, 0x30, 0x30, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x6E,
+ 0x76, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x38, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x0C, 0x0C,
+ 0x18, 0x18, 0x30, 0x30, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x0C, 0x0C, 0x18, 0x18,
+ 0x0C, 0x0C, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x1C, 0x1C, 0x3C, 0x3C,
+ 0x6C, 0x6C, 0x7E, 0x7E, 0x0C, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7E,
+ 0x06, 0x06, 0x06, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x3C, 0x70, 0x60, 0x60, 0x7C,
+ 0x7E, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x06, 0x06, 0x0C, 0x0C,
+ 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x3C, 0x3C,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3E,
+ 0x06, 0x06, 0x06, 0x0E, 0x3C, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x30, 0x20,
+ 0x00, 0x00, 0x00, 0x0E, 0x1C, 0x38, 0x70, 0xE0,
+ 0x70, 0x38, 0x1C, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00,
+ 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
+ 0x1C, 0x38, 0x70, 0xE0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x0C, 0x0C,
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x7C, 0xE6, 0xC2, 0xDA, 0xD6,
+ 0xD6, 0xDC, 0xC0, 0xE2, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0x66, 0x66,
+ 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x7E, 0x7C,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x60, 0x60,
+ 0x60, 0x60, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x7C, 0x6E, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7C,
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7C,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x60, 0x6E, 0x6E,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7E,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xD8, 0xD8, 0xF0, 0xF0,
+ 0xD8, 0xD8, 0xCC, 0xCC, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xEE, 0xEE, 0xFE, 0xD6,
+ 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x76, 0x76, 0x7E,
+ 0x7E, 0x6E, 0x6E, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x66, 0x66,
+ 0x7E, 0x7C, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x6A, 0x7C, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0xF8, 0xFC, 0xCC, 0xCC, 0xCC, 0xFC,
+ 0xF8, 0xD8, 0xCC, 0xCC, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x60, 0x70, 0x38,
+ 0x1C, 0x0E, 0x06, 0x06, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6,
+ 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x82, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18,
+ 0x18, 0x3C, 0x3C, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x3C,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x0C, 0x0C, 0x18, 0x18,
+ 0x30, 0x30, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x1E, 0x1E, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1E, 0x1E, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x30, 0x30, 0x18,
+ 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x78, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x78, 0x78, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x38, 0x38, 0x6C, 0x6C, 0xC6,
+ 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
+ 0x40, 0x60, 0x70, 0x38, 0x1C, 0x0C, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x06,
+ 0x3E, 0x7E, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x60,
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x3E, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0x7E, 0x60, 0x60, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x1E, 0x18, 0x18, 0x7E, 0x7E,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x7E, 0x7C,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x38, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x78,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xCC, 0xDC, 0xF8,
+ 0xF0, 0xF8, 0xD8, 0xCC, 0xCE, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE,
+ 0xD6, 0xD6, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x60, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x60,
+ 0x70, 0x3C, 0x0E, 0x06, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x7E, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1E, 0x0E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6,
+ 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x82, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C,
+ 0x3C, 0x18, 0x3C, 0x3C, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x7E, 0x7C,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x0C,
+ 0x18, 0x18, 0x30, 0x30, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x38, 0xF0,
+ 0xF0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0xE0, 0x30, 0x30, 0x30, 0x30, 0x38, 0x1E,
+ 0x1E, 0x38, 0x30, 0x30, 0x30, 0x30, 0xE0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xF2, 0xBE,
+ 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/private/ntos/nthals/hal0jens/alpha/jxbeep.c b/private/ntos/nthals/hal0jens/alpha/jxbeep.c
new file mode 100644
index 000000000..633f75ac0
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxbeep.c
@@ -0,0 +1,133 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for the
+ Alpha/Jensen system.
+
+Author:
+
+ Jeff McLeman (mcleman) 23-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeLowerIrql(oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_PORT_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_PORT_UCHAR(&controlBase->SpeakerTone, newCount);
+ WRITE_PORT_UCHAR(&controlBase->SpeakerTone, (newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ KeLowerIrql(oldIrql);
+
+ return(TRUE);
+
+}
+
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/jxcache.c b/private/ntos/nthals/hal0jens/alpha/jxcache.c
new file mode 100644
index 000000000..cde92dab0
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxcache.c
@@ -0,0 +1,521 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxcache.c
+
+Abstract:
+
+ This file contains the routines for managing the caches on Jensen.
+
+ Jensen is based on EV4, which has primary I and D caches, both
+ write-through. Jensen has a single back-up cache. This cache is
+ write-back, but it is also coherent with all DMA operations. The
+ primary caches are shadowed by the backup, and on a write hit, the
+ primary data (but not instruction) cache is invalidated.
+ Consequently, the routines to flush,sweep,purge,etc the data
+ stream are nops on Jensen, but the corresponding routines for the
+ Istream must ensure that we cannot hit in the primary I cache
+ after a DMA operation.
+
+ Jensen has a write buffer which contains 4 32-byte entries, which
+ must be flushable before DMA operations. The MB instruction is
+ used to accomplish this.
+
+ There is no coloring support on Jensen, so Color operations are
+ null. Zero page is unsupported because it has no users. Copy
+ page is not special because we lack coloring.
+
+ We had to make a philosophical decision about what interfaces to
+ support in this file. (Almost) none of the interfaces defined in
+ the HAL spec are actually supported in either the i386 or MIPS
+ code. The i386 stream has almost no cache support at all. The
+ Mips stream has cache support, but most routines also refer to
+ coloring. Should we use the Spec'ed interfaces, or the Mips
+ interfaces? I have elected the Mips interfaces because they are
+ in use, and we are stealing much of the Mips code which expects
+ these interfaces. Besides, the only change we might make is to
+ remove the coloring arguments, but they may be used on Alpha
+ machines at some future date.
+
+Author:
+
+ Miche Baker-Harvey (miche) 29-May-1992
+
+Revision History:
+
+
+ 13-Jul-1992 Jeff McLeman (mcleman)
+ use HalpMb to do a memory barrier. Also, alter code and use super
+ pages to pass to rtl memory routines.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ use HalpImb to call pal.
+
+ 06-Jul-1992 Jeff McLeman (mcleman)
+ Move routine KeFlushDcache into this module.
+ Use only one memory barrier in the KeFlushWriteBuffer
+ routine. This is because the PAL for the EVx will
+ make sure the proper write ordering is done in PAL mode.
+
+--*/
+ // Include files
+
+#include "halp.h"
+
+
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ );
+
+//
+// Cache and write buffer flush functions.
+//
+
+
+VOID
+HalChangeColorPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+/*++
+
+Routine Description:
+
+ This function changes the color of a page if the old and new colors
+ do not match. Jensen machines do not have page coloring, and
+ therefore, this function performs no operation.
+
+Arguments:
+
+ NewColor - Supplies the page aligned virtual address of the
+ new color of the page to change.
+
+ OldColor - Supplies the page aligned virtual address of the
+ old color of the page to change.
+
+ pageFrame - Supplies the page frame number of the page that
+ is changed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is flushed.
+ PageFrame - Supplies the page frame number of the page that
+ is flushed.
+
+ Length - Supplies the length of the region in the page that is
+ flushed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ if (ReadOperation) {
+ HalpMb(); // force all previous writes off chip
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+
+}
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+Routine Description:
+
+ This function purges (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalPurgeIcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function purges (invalidates) up to a page fo data from the
+ instruction cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+}
+
+VOID
+HalSweepDcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire data cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepDcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the data
+ cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the data cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the data cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire instruction cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+ return;
+}
+
+VOID
+HalSweepIcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the
+ instruction cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the instruction cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the instruction cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+
+}
+
+VOID
+HalZeroPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+/*++
+
+Routine Description:
+
+ This function zeros a page of memory.
+
+Arguments:
+
+ NewColor - Supplies the page aligned virtual address of the
+ new color of the page that is zeroed.
+
+ OldColor - Supplies the page aligned virtual address of the
+ old color of the page that is zeroed.
+
+ PageFrame - Supplies the page frame number of the page that
+ is zeroed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID tmp;
+
+ tmp = (PVOID)((PageFrame << PAGE_SHIFT) | KSEG0_BASE);
+
+ RtlZeroMemory(tmp, PAGE_SIZE);
+}
+
+VOID
+KeFlushWriteBuffer (
+ VOID
+ )
+
+{
+ //
+ // We flush the write buffer by doing a series of memory
+ // barrier operations. It still isn't clear if we need
+ // to do two/four of them to flush the buffer, or if one
+ // to order the writes is suffcient
+ //
+
+ HalpMb;
+ return;
+}
+
+VOID
+KeFlushDcache (
+ IN BOOLEAN AllProcessors,
+ IN PVOID BaseAddress OPTIONAL,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(BaseAddress);
+ UNREFERENCED_PARAMETER(Length);
+
+ HalFlushDcache(AllProcessors);
+ return;
+}
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sweep (index/writeback/invalidate) the data cache.
+ //
+
+ HalSweepDcache();
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 8;
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/jxcalstl.c b/private/ntos/nthals/hal0jens/alpha/jxcalstl.c
new file mode 100644
index 000000000..651eab2db
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxcalstl.c
@@ -0,0 +1,148 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for an Alpha/Jensen system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jeff McLeman (mcleman) 09-Jun-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jeff McLeman 09-Jun-92
+ Make a Alpha/Jensen specific version of this file.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+#include "jnsndef.h"
+#include "jnsnrtc.h"
+
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ CHAR Buffer[128];
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpStallExecution(MicroSeconds);
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR data;
+
+ //
+ // Acknowledge the clock interrupt.
+ //
+
+
+ HalpWriteVti( RTC_APORT, RTC_CONTROL_REGISTERC );
+ data = HalpReadVti( RTC_DPORT );
+
+
+ return;
+}
+
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/jxclock.c b/private/ntos/nthals/hal0jens/alpha/jxclock.c
new file mode 100644
index 000000000..918a7a22b
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxclock.c
@@ -0,0 +1,311 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxclock.c
+
+Abstract:
+
+ This module handles the RTC interrupt ,Profile Counter
+ interupt and all Profile counter functions for the
+ Alpha/Jensen paltform.
+
+Author:
+
+ Jeff McLeman (mcleman) 05-June-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+ Rod Gamache [DEC] 9-Mar-1993
+ Fix profile clock.
+
+
+--*/
+
+#include "halp.h"
+#include "jnsnrtc.h"
+#include "eisa.h"
+#include "jxprof.h"
+
+//
+// Define global data.
+//
+
+//
+// Values used for Profile Clock
+//
+
+// Convert the interval to rollover count for 8254 timer. Since
+// the 8254 counts down a 16 bit value at the clock rate of 1.193 MHZ,
+// the computation is:
+//
+// RolloverCount = (Interval * 0.0000001) * (1193 * 1000000)
+// = Interval * .1193
+// = Interval * 1193 / 10000
+
+#define PROFILE_INTERVAL 1193
+#define PROFILE_INTERVALS_PER_100NS 10000/1193
+#define MIN_PROFILE_TICKS 4
+#define MAX_PROFILE_TICKS 0x10000 // 16 bit counter (zero is max)
+
+//
+// Since the profile timer interrupts at a frequency of 1.193 MHZ, we
+// have .1193 intervals each 100ns. So we need a more reasonable value.
+// If we compute the timer based on 1600ns intervals, we get 16 * .1193 or
+// about 1.9 ticks per 16 intervals.
+//
+// We round this to 2 ticks per 1600ns intervals.
+//
+
+#define PROFILE_TIMER_1600NS_TICKS 2
+
+//
+// Default Profile Interval to be about 1ms.
+//
+
+ULONG HalpProfileInterval = PROFILE_TIMER_1600NS_TICKS * PROFILE_INTERVALS_PER_100NS * 10000 / 16; // ~1ms
+
+//
+// Default Number of Profile Clock Ticks per sample
+//
+
+ULONG HalpNumberOfTicks = 1;
+
+//
+// HalpRpccTime is the software maintained 64-bit processor cycle counter.
+//
+
+LARGE_INTEGER HalpRpccTime;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+Arguments:
+
+ RateSelect - Supplies rate select to be placed in the clock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG DataByte;
+
+ //
+ // Set the new rate
+ //
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->RateSelect = RateSelect;
+ HalpWriteVti( RTC_APORT, RTC_CONTROL_REGISTERA );
+ HalpWriteVti( RTC_DPORT, DataByte );
+
+ //
+ // Set the correct mode
+ //
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ HalpWriteVti( RTC_APORT, RTC_CONTROL_REGISTERB );
+ HalpWriteVti( RTC_DPORT, DataByte );
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Obtain the current value of the processor cycle counter and adjust
+ // the upper 32 bits if a roll-over occurred since the last time the
+ // Rpcc value was checked (at least oncce per clock interrupt). This
+ // code may be interrupted so we must fetch HalpRpccTimec atomically.
+ //
+
+ *(PULONGLONG)&LocalRpccTime = *(PULONGLONG)&HalpRpccTime;
+ RpccValue = HalpRpcc();
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+ LocalRpccTime.LowPart = RpccValue;
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->LowPart = HalpClockFrequency;
+ Frequency->HighPart = 0;
+ }
+
+ //
+ // Return the current processor cycle counter as the function value.
+ //
+
+ return LocalRpccTime;
+}
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // ****** Warning ******
+ //
+ // This is a stub routine. It should clear the current value of the
+ // performance counter. It is really only needed in an MP system where,
+ // close, but not exact synchronization of the performance counters
+ // are needed. See MIPS code in halfxs\mips\j4prof.c for a method of
+ // synchronizing.
+ //
+
+ return;
+}
+
diff --git a/private/ntos/nthals/hal0jens/alpha/jxdisp.c b/private/ntos/nthals/hal0jens/alpha/jxdisp.c
new file mode 100644
index 000000000..3fe848081
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxdisp.c
@@ -0,0 +1,752 @@
+#if defined (JENSEN)
+
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for the Alpha Jensen system
+
+ It was stolen from a combination of the jxdisp.c routine in the firmware
+ directory, written by John DeRosa, and the jxdisp.c routines in the MIPS
+ HAL directory.
+
+Author:
+
+ Miche Baker-Harvey (miche) 10-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 12-July-1994 Eric Rehm
+ Support RESET_DISPLAY_PARAMETERS callback registered during
+ HalAcquireDisplayOwnership. This callback is supplied by
+ the Video Miniport driver's HwResetHw entry in the HW_INITIALIZATION_DATA
+ structure.
+
+ 17-Feb-1994 Eric Rehm
+ Rewrite ouput routines to be device-independent through callback
+ to firmware VenPrint routine.
+
+ 04-Mar-1993 Joe Mitchell (DEC)
+ Modify HalpScrollDisplay to pause after displaying each screenful of
+ information during a bugcheck.
+ Modify InitializeVGA to call the firmware to init the video display
+ rather than doing the initialization itself.
+
+ 10-Aug-1992 Jeff McLeman (DEC)
+ Put in debug fixes.
+
+ 22-Jul-1992 Jeff McLeman (mcleman)
+ Remove inline asm(MB)s , because Hal access routines manage
+ read/write ordering.
+
+--*/
+
+//
+// Need some include files here
+#include "halp.h"
+#include "arc.h"
+#include "halvga.h"
+#include "jnsndef.h"
+#include "fwcallbk.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpSetLoc (
+ );
+
+BOOLEAN
+InitializeDisplay (
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpScrollDisplay(
+ VOID
+ );
+
+VOID
+HalpFlushKeyboardBuffer (
+ VOID
+ );
+
+VOID
+HalpWaitForKeyPress (
+ VOID
+ );
+typedef
+ULONG
+(*PFW_INITIALIZE_VIDEO_CALLBACK) (
+ OUT ULONG AlphaVideoType
+ );
+
+
+//
+// Define static data.
+//
+
+BOOLEAN HalpBootDisplay = TRUE;
+BOOLEAN HalpDisplayInitialized = FALSE;
+BOOLEAN HalpDisplayOwnedByHal;
+ULONG HalpColumn;
+ULONG HalpRow;
+PUCHAR HalpDestination;
+ULONG HalpForegroundColor;
+ULONG HalpBackgroundColor;
+ULONG DisplayWidth;
+ULONG DisplayHeight;
+ULONG MaxRow;
+ULONG MaxColumn;
+ULONG HalpNewTopLine;
+
+#define CONTROL_SEQUENCE_MAX_PARAMETER 10
+ULONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+//
+// Declare externally defined data.
+//
+// none.
+
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes and clears the display.
+
+ This is called during phase 0 of the Hal initialization.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize static data.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (InitializeDisplay() == TRUE) {
+
+ //
+ // Mark the display as successfully initialized.
+ //
+
+ HalpDisplayInitialized = TRUE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+InitializeDisplay (
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes and clears the display.
+
+ It is initialized to: alphanumeric mode, 16 colors fore & background,
+ 8x16 pixel fonts, 80x25 characters, 640 x 400 display.
+ This is not ARC compliant (no underline, no monochrome support)
+ but its good enough for now and can be enhanced later. (For booting,
+ the ARC spec is overkill anyway.)
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the video was initialized, TRUE is returned, otherwise FALSE
+
+--*/
+
+{
+ ULONG UnusedParameter;
+ PARC_DISPLAY_STATUS DisplayStatus;
+ char String[16];
+
+ //
+ // Initialize static data.
+ //
+
+ HalpForegroundColor = FW_COLOR_HI_WHITE;
+ HalpBackgroundColor = FW_COLOR_BLUE;
+
+ DisplayStatus = ArcGetDisplayStatus(ARC_CONSOLE_OUTPUT);
+ DisplayWidth = DisplayStatus->CursorMaxXPosition;
+ DisplayHeight = DisplayStatus->CursorMaxYPosition;
+
+ MaxRow = DisplayHeight -1;
+ MaxColumn = DisplayWidth -1;
+ HalpNewTopLine = 0;
+
+ //
+ // [ecr] Call the video driver to intialize the video display,
+ // if it has supplied a reset routine.
+ //
+
+ if (HalpResetDisplayParameters) {
+ HalpDisplayOwnedByHal = HalpResetDisplayParameters(MaxColumn+1, MaxRow+1);
+ }
+
+ //
+ // [jrm] Call the firmware to initialize the video display.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ VenVideoDisplayInitialize(&UnusedParameter);
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ //
+ // Set the video memory to blue.
+ //
+
+ sprintf(String, "%c%dm%c%2J", ASCII_CSI, HalpBackgroundColor+40,
+ ASCII_CSI);
+ VenPrint(String);
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ HalpBootDisplay = FALSE;
+ HalpResetDisplayParameters=ResetDisplayParameters;
+
+ //
+ // Reset the display to begin in the upper left corner.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+
+ return;
+}
+
+VOID
+HalpVideoReboot(
+ VOID
+ )
+{
+
+ if (HalpResetDisplayParameters && !HalpDisplayOwnedByHal) {
+
+ //
+ // Video work-around. The video driver has a reset function,
+ // call it before resetting the system in case the bios doesn't
+ // know how to reset the display's video mode.
+ //
+
+ HalpResetDisplayParameters(MaxColumn+1, MaxRow+1);
+ }
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Note that the MIPS version of this routine goes through mapping
+ // the device into the users space; since we have reserved the top
+ // PDE in system space, we dont have to do this - its always mapped.
+ //
+
+ //
+ // Check if the display has already been successfully initialized.
+ // If it has not then we cannot print on the display.
+ //
+
+ if( HalpDisplayInitialized != TRUE ){
+
+#if (DBG) || (HALDBG)
+
+ DbgPrint( "HDS: %s\n", String );
+
+#endif //DBG || HALDBG
+
+ return;
+
+ }
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ InitializeDisplay();
+ }
+
+ while (*String)
+ {
+ switch (*String)
+ {
+ case '\n':
+ if (HalpRow == MaxRow-1-1) {
+ HalpScrollDisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+ break;
+
+ case '\b':
+ if(HalpColumn != 0) {
+ --HalpColumn;
+ }
+ break;
+
+ case '\r':
+ HalpColumn = 0;
+ break;
+
+ default:
+ if (HalpColumn > MaxColumn)
+ {
+ if (HalpRow == MaxRow-1-1) {
+ HalpScrollDisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+ }
+ HalpDisplayCharacter(*String);
+ HalpColumn++;
+ }
+ ++String;
+ }
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = DisplayWidth;
+ *HeightInLines = DisplayHeight;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > DisplayWidth) {
+ CursorColumn = DisplayWidth;
+ }
+
+ if (CursorRow > DisplayHeight) {
+ CursorRow = DisplayHeight;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer.
+
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ char String[16];
+
+ sprintf(String, "%c%d;%dH%c%d;%dm%c",
+ ASCII_CSI, HalpRow+1, HalpColumn+1,
+ ASCII_CSI, HalpForegroundColor+30, HalpBackgroundColor+40,
+ Character);
+ VenPrint(String);
+
+}
+
+
+VOID
+HalpScrollDisplay (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scrolls the display up one line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Source, Destination;
+ int i;
+ ULONG SaveColumn;
+ char String[16];
+ char *ContinueString = "Press any key to continue...";
+
+ //
+ // If this is not boot time, then we are displaying a bugcheck, and we
+ // do not want it to scroll off the screen before the user has a chance
+ // to read it. Basically, we will track when we do the first line of a
+ // new scroll and we will only ask the user for intervention when the
+ // new line reaches the top of the display.
+ //
+
+ if (HalpBootDisplay == FALSE)
+ {
+ if (HalpNewTopLine == 0)
+ {
+ HalpColumn = 0;
+ HalpRow++;
+ HalpFlushKeyboardBuffer();
+ //
+ // Display a string.
+ //
+ while (*ContinueString) {
+ HalpDisplayCharacter(*ContinueString);
+ ContinueString++;
+ HalpColumn++;
+ }
+ HalpWaitForKeyPress();
+ //
+ // Erase the ContinueString message.
+ //
+ for (HalpColumn = 0; HalpColumn <= MaxColumn ; ++HalpColumn ) {
+ HalpDisplayCharacter(' ');
+ }
+
+ HalpNewTopLine = MaxRow-1-1;
+ HalpRow--;
+ }
+ else {
+ HalpNewTopLine--;
+ }
+ }
+
+ //
+ // Force a FwScrollDisplay by positioning FwRow off the
+ // bottom of the screen and then doing a line feed.
+ //
+
+ sprintf(String, "%c%dB%c", ASCII_CSI, 255, ASCII_LF);
+ VenPrint(String);
+
+}
+
+#define KBD_STATUS_OBF 0x1 /* output buffer full bit */
+#define KBD_STATUS_ODS 0x20 /* data source bit (set for mouse input) */
+#define KBD_STATUS_PORT 0x64
+#define KBD_OUTPUT_BUFFER_PORT 0x60
+
+VOID
+HalpFlushKeyboardBuffer (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the keyboard buffer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG KeyboardInput;
+
+ KeyboardInput = inVti(KBD_STATUS_PORT);
+ //DbgPrint("HalpFlushKeyboardBuffer: status=%x\n", KeyboardInput);
+
+ while ((KeyboardInput & KBD_STATUS_OBF) != 0)
+ {
+ HalpStallExecution(1000);
+ KeyboardInput = inVti(KBD_OUTPUT_BUFFER_PORT);
+ //DbgPrint("HalpFlushKeyboardBuffer: input=%x\n", KeyboardInput);
+ HalpStallExecution(1000);
+ KeyboardInput = inVti(KBD_STATUS_PORT);
+ }
+}
+
+VOID
+HalpWaitForKeyPress (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine waits for a character to be entered at the keyboard.
+ Ignore mouse input (KBD_STATUS_ODS bit).
+
+ **jrmfix - temporary until keyboard problem resolved
+ When data is received from
+ the keyboard port, make sure that bit 7 is not set. Sometimes (e.g.
+ during an NMI interrupt), garbage characters are entered into the
+ keyboard buffer (with bit 7 set). Any key entered at the keyboard
+ will not have bit 7 set.
+ **jrmfix
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG KeyboardStatus;
+ ULONG KeyboardInput = 0x80;
+
+ KeyboardStatus = inVti(KBD_STATUS_PORT);
+
+ //
+ //jrmfix** Ignore non-ASCII keyboard input (bit 7 set).
+ //
+ while ((KeyboardInput & 0x80) != 0)
+ {
+ //
+ // Wait for a key to be entered. Ignore any mouse input.
+ //
+ while (((KeyboardStatus & KBD_STATUS_OBF) == 0) ||
+ ((KeyboardStatus & KBD_STATUS_ODS) != 0))
+ {
+ //
+ // If this is mouse input, read from the output port to reset
+ // the status register (KBD_STATUS_PORT).
+ //
+ if (KeyboardStatus & KBD_STATUS_ODS) {
+ HalpStallExecution(1000);
+ KeyboardStatus = inVti(KBD_OUTPUT_BUFFER_PORT);
+ DbgPrint("HalpWaitForKeyPress: MouseInput=%x\n",
+ KeyboardStatus);
+ }
+ HalpStallExecution(1000);
+ KeyboardStatus = inVti(KBD_STATUS_PORT);
+ }
+
+ HalpStallExecution(1000);
+ KeyboardInput = inVti(KBD_OUTPUT_BUFFER_PORT);
+ DbgPrint("HalpWaitForKeyPress: KeyboardInput=%x\n", KeyboardInput);
+ KeyboardStatus = inVti(KBD_STATUS_PORT);
+ }
+}
+
+#endif // JENSEN
diff --git a/private/ntos/nthals/hal0jens/alpha/jxenv.h b/private/ntos/nthals/hal0jens/alpha/jxenv.h
new file mode 100644
index 000000000..90763ef56
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxenv.h
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ xxenv.h
+
+Abstract:
+
+ This module contains definitions for environment variable support
+ under the HAL. (Parts taken from J. Derosa's FWP.H)
+
+Author:
+
+ Jeff McLeman (DEC) 17-Sep-1992
+
+Revision History:
+
+--*/
+
+
+
+//
+// If any aspect of the NVRAM component / configuration data structure
+// is changed for the Alpha/Jensen machine, the module jencds.c may also need
+// to be changed.
+//
+
+
+//
+// Define the private configuration packet structure, which contains a
+// configuration component as well as pointers to the component's parent,
+// peer, child, and configuration data.
+//
+
+typedef struct _CONFIGURATION_PACKET {
+ CONFIGURATION_COMPONENT Component;
+ struct _CONFIGURATION_PACKET *Parent;
+ struct _CONFIGURATION_PACKET *Peer;
+ struct _CONFIGURATION_PACKET *Child;
+ PVOID ConfigurationData;
+} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET;
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ UCHAR Version;
+ UCHAR Revision;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+//
+// Defines for the volatile and non-volatile configuration tables.
+//
+
+#define NUMBER_OF_ENTRIES 104
+#define LENGTH_OF_IDENTIFIER 2000
+#define LENGTH_OF_DATA 2048
+#define LENGTH_OF_ENVIRONMENT 1500
+#define LENGTH_OF_EISA_DATA 2500
+
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+#define MAX_NUMBER_OF_ENVIRONMENT_VARIABLES 28
+
+//
+// The volatile configuration table structure.
+//
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+ UCHAR EisaData[LENGTH_OF_EISA_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+//
+// The non-volatile configuration table structure.
+//
+
+typedef struct _NV_CONFIGURATION {
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+ UCHAR Checksum1[4];
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT];
+ UCHAR Checksum2[4];
+ UCHAR EisaData[LENGTH_OF_EISA_DATA];
+ UCHAR Checksum3[4];
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+//
+// Define identifier index, data index, pointer to configuration table, and
+// the system identifier.
+//
+
+extern ULONG IdentifierIndex;
+extern ULONG DataIndex;
+extern ULONG EisaDataIndex;
+extern SYSTEM_ID SystemId;
+
+
+
+//
+// PROM layout.
+//
+
+#define PROM_VIRTUAL_BASE 0xA0D00000
+
+//
+// Start of firmware executable code. Code lives in blocks 7, 8, 9, A and B.
+//
+#define PROM_PAGE7 ( PROM_VIRTUAL_BASE+0x70000 )
+
+
+//
+// Component Data Structure, environment variables.
+// These contain their own checksums.
+//
+#define PROM_PAGEC ( PROM_VIRTUAL_BASE+0xC0000 )
+#define NVRAM_CONFIGURATION PROM_PAGEC
+
+//
+// Alpha/Jensen PROM command definitions.
+//
+
+#define PROM_ERASE_SETUP 0x20
+#define PROM_ERASE_CONFIRM 0xD0
+#define PROM_BYTEWRITE_SETUP 0x40
+#define PROM_READ_STATUS 0x70
+#define PROM_CLEAR_STATUS 0x50
+#define PROM_READ_ARRAY 0xff
+
+//
+// The following structures are used for the timer mechanism for
+// updating the ROM
+//
+
+typedef struct _PROMTIMER_ {
+ KTIMER Timer;
+ KDPC Dpc;
+} PROMTIMER, *PPROMTIMER;
+
+
diff --git a/private/ntos/nthals/hal0jens/alpha/jxhalp.h b/private/ntos/nthals/hal0jens/alpha/jxhalp.h
new file mode 100644
index 000000000..1f1126f81
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxhalp.h
@@ -0,0 +1,188 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jensen specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+ Miche Baker-Harvey (miche) 13-May-92
+
+
+Revision History:
+ 21-Jul-1992 Jeff McLeman (mcleman)
+ Modify adpater object structure to reflect what we are
+ using.
+
+
+ MBH - Stole Jazz version of this file, since it also uses the 82357 for EISA
+
+--*/
+
+// Might get in trouble for using the same define as Jazz?? MBH
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+#include "hal.h"
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+
+extern BOOLEAN LessThan16Mb;
+
+extern POBJECT_TYPE *IoAdapterObjectType;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN IsaDevice;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN EisaAdapter;
+ BOOLEAN Dma32BitAddresses;
+} ADAPTER_OBJECT;
+
+//
+// Define memory region structure
+//
+
+typedef struct _MEMORY_REGION {
+ struct _MEMORY_REGION *Next;
+ ULONG PfnBase;
+ ULONG PfnCount;
+} MEMORY_REGION, *PMEMORY_REGION;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+//
+// Environment variable support
+//
+
+PCHAR
+HalpEnvironmentLoad(
+ VOID
+ );
+
+VOID
+HalpClearPromStatus(
+ VOID
+ );
+
+VOID
+HalpSetPromReadMode(
+ VOID
+ );
+
+ARC_STATUS
+HalpCheckPromStatusAndClear(
+ IN ULONG WhichToCheck
+ );
+
+ARC_STATUS
+HalpErasePromBlock(
+ IN PUCHAR EraseAddress
+ );
+
+ARC_STATUS
+HalpWritePromByte(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ );
+
+ARC_STATUS
+HalpSaveConfiguration(
+ VOID
+ );
+
+VOID
+HalpInitializeSpecialMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+#endif // _JXHALP_
+
+
+
+
diff --git a/private/ntos/nthals/hal0jens/alpha/jxhltsup.s b/private/ntos/nthals/hal0jens/alpha/jxhltsup.s
new file mode 100644
index 000000000..e5db9fe29
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxhltsup.s
@@ -0,0 +1,109 @@
+// TITLE("Halt Interrupt Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+//
+// Module Name:
+//
+// jxhltsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field the halt button
+// interrupt on JENSEN.
+//
+// Author:
+//
+// Joe Notarangelo 18-Dec-1992
+//
+// Environment:
+//
+// Kernel mode only, IRQL halt synchronization level.
+//
+// Revision History:
+//
+//--
+
+#if !(DBG)
+
+//
+// Boolean value that controls whether to break or not for a halt button
+// interrupt on a free build. The default value is zero and must be set
+// in the debugger to a non-zero value to trigger the breakpoint action
+// when the halt button is pressed.
+//
+
+ .data
+
+ .globl HalpHaltButtonBreak
+HalpHaltButtonBreak:
+ .long 0 : 1
+
+#endif //!DBG
+
+
+#include "ksalpha.h"
+
+ SBTTL("Halt Interrupt Support")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of a halt interrupt caused by
+// a human pushing the halt switch on JENSEN. This routine is connected
+// directly into the IDT. The halt interrupt is mechanical and does not
+// require an interrupt acknowledge.
+//
+// Arguments:
+//
+// s6/fp - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+HaltRa: .space 8 // saved return address
+ .space 8 // fill for alignment
+HaltFrameLength:
+
+ NESTED_ENTRY(HalpHaltInterrupt, ExceptionFrameLength, zero)
+
+ lda sp, -HaltFrameLength(sp) // allocate stack frame
+ stq ra, HaltRa(sp) // save ra
+
+ PROLOGUE_END
+
+
+#if DBG
+
+//
+// Always stop in the debugger if this is a checked build.
+//
+
+ BREAK_DEBUG_STOP // stop in the debugger
+
+#else
+
+//
+// If this is a free build then check the variable HalpHaltButtonBreak,
+// if it is non-zero then take the breakpoint, otherwise ignore it.
+//
+
+ lda t0, HalpHaltButtonBreak // get the address of the boolean
+ ldl t0, 0(t0) // read the boolean
+ beq t0, 10f // if eq, don't stop
+
+ BREAK_DEBUG_STOP // stop in the debugger
+
+10:
+
+#endif //DBG
+
+ ldq ra, HaltRa(sp) // save ra
+ lda sp, HaltFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // interrupt is dismissed
+
+ .end HalpHaltInterrupt
diff --git a/private/ntos/nthals/hal0jens/alpha/jxhwsup.c b/private/ntos/nthals/hal0jens/alpha/jxhwsup.c
new file mode 100644
index 000000000..94309cb7f
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxhwsup.c
@@ -0,0 +1,4290 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+ Miche Baker-Harvey (miche) 22-May-1992
+ Jeff McLeman (mcleman) 27-May-1992
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "jnsndef.h"
+#include "jnsnint.h"
+#include "jnsndma.h"
+#include "eisa.h"
+#include "jxisa.h"
+#include "string.h"
+
+
+
+#define HAL_32MB 0x2000000
+
+#define HALF_MEGABYTE 0x80000
+
+#define NUMBER_OF_SPECIAL_REGIONS 6
+
+#define SPECIAL_BUFFER_SIZE NUMBER_OF_SPECIAL_REGIONS*sizeof(MEMORY_REGION)
+
+PVOID HalpEisaControlBase;
+
+//
+// We have one fixed special memory region at half a megabyte.
+//
+
+MEMORY_REGION HalpHalfMeg;
+
+//
+// Pointer to special memory regions that must be checked on every I/O.
+// Use to check if PFN is contained in a special memory region.
+//
+
+PMEMORY_REGION HalpSpecialRegions = NULL;
+
+//
+// Buffers used for MEMORY_REGION descriptors. We cannot allocate non-paged
+// pool when we are building the MEMORY_REGION descriptors. So we will have
+// our own little pool.
+//
+
+UCHAR HalpMemoryRegionFree[SPECIAL_BUFFER_SIZE];
+
+//
+// We have one fixed pool to allocate MEMORY_REGIONS from.
+//
+
+PVOID HalpMemoryRegionBuffers = HalpMemoryRegionFree;
+ULONG HalpMemoryRegionSize = SPECIAL_BUFFER_SIZE;
+
+//
+// The following is the interrupt object used by the DMA controller dispatch
+// routine to provide synchronization to the DMA controller. It is initialized
+// by the I/O system during system initialization.
+//
+
+KINTERRUPT HalpDmaInterrupt;
+
+//
+// The HaeIndex, used in creating QVAs for EISA memory space.
+//
+ULONG HaeIndex;
+
+//
+// This is the HAE table. The first table entry is used to map the lowest
+// 32MB in a Jensen system. The second entry is used to map the next 32MB
+// entry so that graphics cards, etc., will work.
+//
+
+CHAR HalpHaeTable[4] = { 0, 1, 0, 0 };
+
+//
+// The following is an array of adapter object structures for the Eisa DMA
+// channels.
+//
+
+//
+// Define the area for the Eisa objects
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+BOOLEAN LessThan16Mb;
+BOOLEAN HalpEisaDma;
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ );
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY translationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+ULONG
+HalpGetEisaData(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpSpecialMemory(
+ IN ULONG PFN
+ );
+
+BOOLEAN
+HalpAnySpecialMemory(
+ IN PMDL Mdl,
+ IN ULONG Length,
+ IN ULONG Offset
+ );
+
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY translationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specified data between the user buffer and the
+ map register buffer. First, the user buffer is mapped, if need be then
+ the data is copied. Finally, the user buffer will be unmapped, if need be.
+
+Arguments:
+
+ Mdl - Pointer to the Mdl that describes the pages of memory that are
+ being read or written.
+
+ translationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the xfer.
+
+ CurrentVa - Current Virtual Address in the buffer described by the Mdl
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - A Boolean value that indicates whether this is a write
+ to the device from memory of vise-versa.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) translationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and the map buffer.
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory ( bufferAddress, mapAddress, Length);
+
+ }
+}
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = TRUE;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ if (AdapterObject->EisaAdapter) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | EISA_ADAPTER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumerOfMapRegisters - Number of map registers required. Updated to show
+ actual number of registers allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ if ( MasterAdapter == NULL ) {
+ if ( MasterAdapterObject == NULL ) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ } else {
+ MasterAdapter = MasterAdapterObject;
+ AdapterObject->MapRegistersPerChannel = 16;
+ }
+ }
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ if (AdapterObject->EisaAdapter) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | EISA_ADAPTER);
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(CacheEnabled);
+
+ //
+ // Assume below 16M to support ISA devices
+ //
+
+ physicalAddress.LowPart = MAXIMUM_ISA_PHYSICAL_ADDRESS-1;
+ physicalAddress.HighPart = 0;
+
+ //
+ // If the caller supports 32bit addresses, and it's a master, let
+ // it have any memory below 1G
+ //
+
+ if (AdapterObject->Dma32BitAddresses && AdapterObject->MasterDevice) {
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ }
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (!HALP_IS_PHYSICAL_ADDRESS(virtualAddress)) {
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ } else {
+
+ LogicalAddress->QuadPart = (ULONG)virtualAddress & (~KSEG0_BASE);
+
+ }
+ return(virtualAddress);
+}
+
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(Length);
+ UNREFERENCED_PARAMETER(LogicalAddress);
+ UNREFERENCED_PARAMETER(VirtualAddress);
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(Length);
+ UNREFERENCED_PARAMETER(LogicalAddress);
+ UNREFERENCED_PARAMETER(CacheEnabled);
+
+ MmFreeContiguousMemory(VirtualAddress);
+
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+ UCHAR DataByte;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Support for ISA local bus machines:
+ // If the driver is a Master but really does not want a channel since it
+ // is using the local bus DMA, just don't use an ISA channel.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->DmaChannel > 7) {
+
+ useChannel = FALSE;
+ }
+
+ //
+ // Determine if Eisa DMA is supported.
+ //
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ HalpEisaDma = FALSE;
+
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2, 0x55);
+ DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2);
+
+ if (DataByte == 0x55) {
+ HalpEisaDma = TRUE;
+ }
+
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!HalpEisaDma &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+
+ //
+ // If the device is not a master and does scatter/gather then
+ // it only needs one map register.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus to
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+ //
+ // Indicate whether the device is an Eisa adapter.
+ //
+
+ if ( DeviceDescriptor->InterfaceType == Eisa ) {
+ adapterObject->EisaAdapter = TRUE;
+ } else {
+ adapterObject->EisaAdapter = FALSE;
+ }
+
+
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (HalpEisaDma) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_PORT_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be accessed with the routines WRITE/READ_
+ REGISTER_UCHAR/USHORT/ULONG, and they must be the ones in module
+ JXIOUSER.C. The user CANNOT call the above routines in the HAL from
+ usermode. (Which is pointless, since the HAL is superpage access
+ only).
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ HaeIndex = 0;
+
+ //
+ // If this is for the internal bus then the device is on the combo chip.
+ // BusAddress.LowPart should contains the port of the device.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ TranslatedAddress->LowPart = 0xC0000000 + (BusAddress.LowPart << COMBO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva(
+ *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ //
+ // Jensen only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch (*AddressSpace) {
+
+ case 0 : {
+
+ //
+ // The address is in EISA memory space, kernel mode.
+ //
+
+ //
+ // If the address cannot be mapped into the predefined low 32MB
+ // 'default' region, then find a free or matching region in the HAE
+ // Table. NB: slot zero is predefined to the lowest 32MB and cannot
+ // be overwritten.
+ //
+ if ( BusAddress.LowPart >= HAL_32MB ) {
+ ULONG HaeValue;
+
+ HaeValue = (BusAddress.LowPart >> 25);
+
+ for ( HaeIndex = 1; HaeIndex < 4; HaeIndex++ ) {
+ if ( HalpHaeTable[HaeIndex] == 0 ||
+ HalpHaeTable[HaeIndex] == HaeValue ) {
+ break;
+ }
+ }
+
+ // Check if no HAE slots were available, if so return error.
+
+ if ( HaeIndex == 4 ) {
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ } else {
+ HalpHaeTable[HaeIndex] = HaeValue;
+ }
+
+ }
+
+ TranslatedAddress->HighPart = 0x2;
+
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva(
+ *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // don't let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case 1 : {
+ //
+ // The address is in EISA I/O space, kernel mode.
+ //
+
+ TranslatedAddress->HighPart = 0x3;
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva(
+ *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+ case 2 : {
+
+ //
+ // The address is in EISA memory space, user mode.
+ //
+
+
+ TranslatedAddress->HighPart = 0x2;
+
+
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case 3 : {
+ //
+ // The address is in EISA I/O space, user mode.
+ //
+
+ TranslatedAddress->HighPart = 0x3;
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the access
+ routines in JXIOUSER.C
+
+ If the PA is not an I/O space address (Combo chip, Eisa I/O, Eisa
+ memory), then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then JXIOUSER.C should be built
+ into the users code.
+
+--*/
+{
+
+ PVOID qva;
+
+ if (PA.HighPart == 2) {
+
+ //
+ // in EISA MEMORY space
+ //
+
+ if (VA == 0) {
+
+ //
+ // Remember, the PA.LowPart has already been shifted up 7 bits. We
+ // must first make room at bits <31:30> to insert the HaeIndex.
+ //
+ PA.LowPart = PA.LowPart >> 2;
+ PA.LowPart |= (HaeIndex << 30);
+ qva = (PVOID)(PA.QuadPart >> EISA_BIT_SHIFT-2);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> EISA_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | EISA_QVA);
+
+ return(qva);
+ }
+
+ if (PA.HighPart == 3) {
+
+ //
+ // in EISA IO space
+ //
+
+ if (VA == 0) {
+
+ PA.LowPart = PA.LowPart >> 2;
+ qva = (PVOID)(PA.QuadPart >> EISA_BIT_SHIFT-2);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> EISA_BIT_SHIFT);
+
+ }
+
+ qva = (PVOID)((ULONG)qva | EISA_QVA);
+
+ return(qva);
+ }
+
+ if (PA.HighPart == 1) {
+
+ //
+ // on the combo chip (82C106)
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> COMBO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> COMBO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | COMBO_QVA);
+
+ return(qva);
+ }
+
+ //
+ // It is not an I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Jensen we have only 2 buses:
+ //
+ // Internal(0)
+ // Eisa(0)
+ //
+ // We will allow Isa as an alias for Eisa. All other values not named
+ // above will be considered bogus. Bus Number must be zero.
+ //
+
+ if( BusNumber != 0 ){
+ return NULL;
+ }
+
+ switch (InterfaceType ){
+
+ case Internal:
+
+ return( (PVOID)( (ULONG)Qva << COMBO_BIT_SHIFT ) );
+
+ case Isa:
+ case Eisa:
+
+ return( (PVOID)( (ULONG)Qva << EISA_BIT_SHIFT ) );
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocating a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access thru KSEG0, since we don't want to
+ // use translation entries.
+ //
+
+ MapBufferVirtualAddress =
+ (PVOID)(HalpMapBufferPhysicalAddress.LowPart |
+ (ULONG)KSEG0_BASE);
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_ISA_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ if (!HALP_IS_PHYSICAL_ADDRESS(MapBufferVirtualAddress)) {
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ } else {
+
+ MapBufferPhysicalAddress = (ULONG)MapBufferVirtualAddress &
+ (~KSEG0_BASE);
+ }
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (ULONG) i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!HalpEisaDma &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1 &&
+ MapRegistersPerChannel) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *IoAdapterObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoAdapterObjectType,
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ RtlZeroMemory (AdapterObject, sizeof (ADAPTER_OBJECT));
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = TRUE;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ if (AdapterObject->EisaAdapter) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | EISA_ADAPTER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase &
+ ~(NO_SCATTER_GATHER | EISA_ADAPTER));
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ if (AdapterObject->EisaAdapter) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | EISA_ADAPTER);
+
+ }
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ //
+ // Init the Eisa interrupts
+ //
+
+ return HalpCreateEisaStructures ();
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+ BOOLEAN specialMemory;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ if ( MapRegisterBase != NULL ) {
+ specialMemory = HalpAnySpecialMemory( Mdl, *Length, pageOffset);
+ } else {
+ specialMemory = FALSE;
+ }
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous and does not cross a 64 K bountry then
+ // just extend the buffer. The 64 K bountry restriction does not apply
+ // to Eisa systems.
+ //
+ //
+
+ if ( !specialMemory ) {
+ if (HalpEisaDma) {
+
+ while( transferLength < *Length ) {
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ } else {
+
+ while( transferLength < *Length ) {
+
+ if (*pageFrame + 1 != *(pageFrame + 1) ||
+ (*pageFrame & ~0x07) != (*(pageFrame + 1) & ~0x07)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+ }
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ }
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase &
+ ~(NO_SCATTER_GATHER | EISA_ADAPTER));
+
+
+ if ( specialMemory ) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = HOLE_BUFFER;
+ transferLength = *Length;
+
+ //
+ // Copy the data.
+ //
+
+ if (WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+
+ } else {
+
+ if (((ULONG) MapRegisterBase & NO_SCATTER_GATHER) ||
+ !((ULONG)MapRegisterBase & EISA_ADAPTER)) {
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+
+ }
+
+ //
+ // For devices with no scatter/gather or non-Eisa devices:
+ // It must require memory to be at less than 16 MB. If the logical
+ // address is greater than 16MB then map registers must be used.
+ //
+
+ if (logicalAddress+transferLength > MAXIMUM_ISA_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress
+ + pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ translationEntry->Index = SKIP_BUFFER;
+
+ }
+ }
+
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpEisaDma) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpEisaDma) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+ return(returnAddress);
+}
+
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jensen system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+{
+
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+ ULONG index;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase &
+ ~(NO_SCATTER_GATHER | EISA_ADAPTER));
+
+ if ( translationEntry->Index == SKIP_BUFFER ) {
+ translationEntry->Index = 0;
+ return(TRUE);
+ }
+
+ if (!WriteToDevice) {
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if (translationEntry->Index == HOLE_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ } else if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+ }
+
+ } else if (!((ULONG) MapRegisterBase & NO_SCATTER_GATHER) &&
+ !((ULONG) MapRegisterBase & EISA_ADAPTER)) {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_ISA_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will
+ // be transfered after the next loop; thus, it is updated
+ // with the new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+ if (partialLength && (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_ISA_PHYSICAL_ADDRESS))) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase &
+ ~(NO_SCATTER_GATHER | EISA_ADAPTER));
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+ULONG
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // If this is a 16 bit dma the multiply the count by 2.
+ //
+
+ if (AdapterObject->Width16Bits) {
+
+ count *= 2;
+
+ }
+
+ return(count);
+
+
+}
+
+
+BOOLEAN
+HalpSpecialMemory(
+ IN ULONG PFN
+ )
+/*++
+
+Routine Description:
+
+ This function checks if the supplied PFN is contained within a section
+ of special memory.
+
+Arguments:
+
+ PFN - Page Frame Number of the page in question.
+
+Return Value:
+
+ Returns TRUE if the specified page is part of special memory.
+
+--*/
+
+{
+ PMEMORY_REGION specialMemoryRegion = HalpSpecialRegions;
+
+ while ( specialMemoryRegion != NULL ) {
+ if ( PFN >= specialMemoryRegion->PfnBase &&
+ PFN < specialMemoryRegion->PfnBase + specialMemoryRegion->PfnCount ) {
+ return TRUE;
+ }
+ specialMemoryRegion = specialMemoryRegion->Next;
+ }
+ return FALSE;
+}
+
+
+VOID
+HalpInitializeSpecialMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the special memory regions on Jensen.
+
+Arguments:
+
+ LoaderBlock - pointer to the Loader Parameter Block.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PMEMORY_REGION MemoryRegion;
+
+ //
+ // Initialize the fixed half-meg region, length is half-meg also.
+ //
+
+ HalpHalfMeg.PfnBase = HALF_MEGABYTE / PAGE_SIZE;
+ HalpHalfMeg.PfnCount = HALF_MEGABYTE / PAGE_SIZE;
+
+ //
+ // Link the half-meg region into the special regions list
+ //
+
+ HalpHalfMeg.Next = HalpSpecialRegions;
+ HalpSpecialRegions = &HalpHalfMeg;
+
+ return;
+
+#if 0
+ //
+ // Scan through all memory descriptors looking for special memory regions
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while ( NextMd != &LoaderBlock->MemoryDescriptorListHead ) {
+
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+ if ( Descriptor->MemoryType == LoaderSpecialMemory ) {
+
+ //
+ // Allocate pool and copy info into MemoryRegion and insert in list
+ //
+
+ if ( sizeof(MEMORY_REGION) > HalpMemoryRegionSize ) {
+ return;
+ }
+
+ HalpMemoryRegionSize -= sizeof(MEMORY_REGION);
+ MemoryRegion = (PMEMORY_REGION) HalpMemoryRegionBuffers;
+ HalpMemoryRegionBuffers = (PVOID) (MemoryRegion + 1);
+
+ MemoryRegion->PfnBase = Descriptor->BasePage;
+ MemoryRegion->PfnCount = Descriptor->PageCount;
+ MemoryRegion->Next = HalpSpecialRegions;
+ HalpSpecialRegions = MemoryRegion;
+ Descriptor->MemoryType = LoaderFree;
+
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ return;
+
+#endif // 0
+
+}
+
+
+BOOLEAN
+HalpAnySpecialMemory(
+ IN PMDL Mdl,
+ IN ULONG Length,
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This function checks an MDL to see if any pages contained in the MDL
+ are from 'special memory'.
+
+Arguments:
+
+ Mdl - pointer to an MDL.
+
+ Length - length of requested transfer.
+
+ Offset - offset of first byte within the first page for this transfer.
+
+Return Value:
+
+ Reutrns TRUE if any of the pages in the MDL are in 'special memory',
+ otherwise returns FALSE.
+
+--*/
+
+{
+ ULONG i;
+ PULONG pageFrame;
+ ULONG numRegs;
+
+ pageFrame = (PULONG)(Mdl + 1);
+
+ // Calculate number of PFNs to scan
+
+ numRegs = (Length + Offset - 1) >> PAGE_SHIFT;
+
+ for ( i = 0; i <= numRegs; i++ ) {
+ if ( HalpSpecialMemory(*pageFrame) ) {
+ return TRUE;
+ }
+ pageFrame++;
+ }
+ return FALSE;
+}
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+}
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/jxinfo.c b/private/ntos/nthals/hal0jens/alpha/jxinfo.c
new file mode 100644
index 000000000..370c6198e
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxinfo.c
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ info.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+#endif // _PNP_POWER_
+
+//
+// External references
+//
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ The function returns system-wide information controlled by the HAL for a
+ variety of classes.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the space to store the data.
+
+ ReturnedLength - Supplies a count in bytes of the amount of data returned.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ case HalProfileSourceInformation:
+ Status = HalpProfileSourceInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return(Status);
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+/*++
+
+Routine Description:
+
+ The function allows setting of various fields return by
+ HalQuerySystemInformation.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the data to be set.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/jxinitnt.c b/private/ntos/nthals/hal0jens/alpha/jxinitnt.c
new file mode 100644
index 000000000..e1fb48218
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxinitnt.c
@@ -0,0 +1,471 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ .../ntos/hal/alpha/jxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for an Alpha/Jensen
+ system. Contains the VLSI 82C106, the 82357 and an EISA bus.
+
+ Stolen from Dave Cutler's jxinitnt.c in ../mips
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jeff McLeman (DEC) 18-May-1992
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jeff McLeman (DEC) 30-Jul-1992
+ Remove Clock interrupt from this module, because it is done
+ in JXCLOCK.C
+--*/
+
+#include "halp.h"
+#include "jnsnrtc.h"
+#include "jnsndef.h"
+#include "jxserp.h"
+#include "eisa.h"
+
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low (All devices except)
+// irql 4 - device high (the serial lines)
+// irql 5 - clock
+// irql 6 - real time
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11 keyboard/mouse
+// 4 serial 12 errors
+// 5 clock 13 parallel
+// 6 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// clock
+// serial
+// parallel
+// keyboard/mouse
+// pic
+
+//
+// This is the HalpIrqlMask for Jensen
+// Jensen interrupt pins:
+//
+// eirq 0 interval timer from 82c106
+// eirq 1 PIC - 82357 interrupts
+// eirq 2 NMI from the ISP
+// eirq 3 Keyboard and Mouse (82c106)
+// eirq 4 Front-panel HALT switch
+// eirq 5 serial ports A and B.
+// (note that the parallel printer from the 82c106 comes in on the PIC)
+
+#include "jxirql.h"
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+VOID
+HalpClearInterrupts(
+ );
+
+VOID
+HalpHaltInterrupt(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ extern VOID KeUpdateSystemTime(VOID);
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Initialize the IRQL translation table in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new irql, and to
+ // determine the vector into the IDT. This is a bit different from
+ // "normal" NT, which uses the IRQL to index into the vector table directly.
+ // Since we have more information about who has interrupted (from the CPU
+ // interrupt pins), we use that information to get directly to the vector
+ // for the builting device which has interrupted.
+ //
+
+
+ for (Index = 0; Index < (sizeof(HalpIrqlMask)/4); Index++){
+ PCR->IrqlMask[Index].IrqlTableIndex = HalpIrqlMask[Index].IrqlTableIndex;
+ PCR->IrqlMask[Index].IDTIndex = HalpIrqlMask[Index].IDTIndex;
+ }
+
+ for (Index = 0; Index < (sizeof(HalpIET)/4); Index++){
+ PCR->IrqlTable[Index] = HalpIET[Index];
+ }
+
+
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Register the Halt interrupt
+ //
+
+ PCR->InterruptRoutine[HALT_VECTOR] = (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ HalpInitializeProfiler();
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Later there must be initialization for the local interrupts
+ // and PIC, but not now ....
+
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function clears all pending interrupts on the Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+PSP_READ_REGISTERS SP_READ;
+PSP_WRITE_REGISTERS SP_WRITE;
+UCHAR tmp;
+int i;
+UCHAR btmp;
+UCHAR DataByte;
+
+//
+// clear out VTI interrupts, except the RTC
+//
+
+#ifdef JMBUG
+ //
+ // Reset the EISA bus. This is a draconian way of clearing out any
+ // residual interrupts. It has to be done here in Phase 0, because
+ // unlike the Jazz machine, our I/O and graphics are on EISA. If we
+ // were to pull EISA reset in Phase 1, we would lose device context.
+ // Sort of like changing your sparkplugs while driving 65 MPH on
+ // interstate 5.
+
+ DataByte = 0;
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_PORT_UCHAR(
+ (PUCHAR)(&((PEISA_CONTROL)DMA_VIRTUAL_BASE)->ExtendedNmiResetControl),
+ DataByte
+ );
+
+ //
+ // Use a stall loop since KeStallExecutionProcessor isn't available in
+ // Phase 0.
+ //
+
+ HalpStallExecution(4);
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ (PUCHAR)(&((PEISA_CONTROL)DMA_VIRTUAL_BASE)->ExtendedNmiResetControl),
+ DataByte
+ );
+#endif
+
+ //
+ // COM1
+ //
+
+ //
+ // clear the interrupt enable
+ //
+
+ outVti(0x3f9, 0x0);
+ HalpStallExecution(3);
+
+ //
+ // clear out port 1 interrupts
+ //
+
+ outVti(0x3fc, 0x0f);
+ HalpStallExecution(3);
+
+ tmp = inVti(0x3fb);
+ tmp &= ~0xc0;
+ outVti(0x3fb, tmp);
+ HalpStallExecution(3);
+
+ for (i = 0; i< 15; i++) {
+ tmp = inVti(0x3f8);
+ HalpStallExecution(3);
+ if (!inVti(0x3fd) & 1) {
+ break;
+ }
+ }
+
+ for (i = 0; i< 1000; i++) {
+ if(!(0x3fe & 0x0f)) {
+ break;
+ }
+ }
+
+ for (i = 0; i< 5; i++) {
+ if (inVti(0x3fa) & 1) {
+ break;
+ }
+ }
+
+ //
+ // clear the interrupt enable
+ //
+
+ outVti(0x3f9, 0x0);
+ HalpStallExecution(3);
+ //DbgPrint("COM1: Interrupt Enable = %x\n", inVti(0x3f9));
+
+ //
+ // COM2
+ //
+
+ //
+ // clear the interrupt enable
+ //
+
+ outVti(0x2f9, 0x0);
+ HalpStallExecution(3);
+
+ //
+ // clear out port 2 interrupts
+ //
+
+ outVti(0x2fc, 0x0f);
+ HalpStallExecution(3);
+
+ tmp = inVti(0x2fb);
+ tmp &= ~0xc0;
+ outVti(0x2fb, tmp);
+ HalpStallExecution(3);
+
+ for (i = 0; i< 15; i++) {
+ tmp = inVti(0x2f8);
+ HalpStallExecution(3);
+ if (!inVti(0x2fd) & 1) {
+ break;
+ }
+ }
+
+ for (i = 0; i< 1000; i++) {
+ if(!(0x2fe & 0x0f)) {
+ break;
+ }
+ }
+
+ for (i = 0; i< 5; i++) {
+ if (inVti(0x2fa) & 1) {
+ break;
+ }
+ }
+
+ //
+ // clear the interrupt enable
+ //
+
+ outVti(0x2f9, 0x0);
+ HalpStallExecution(3);
+ //DbgPrint("COM2: Interrupt Enable = %x\n", inVti(0x2f9));
+
+ //
+ // Kbd and Mouse
+ //
+
+ outVti(0x64, 0x60);
+ HalpStallExecution(3);
+ outVti(0x60, 0x0);
+ HalpStallExecution(3);
+ tmp = inVti(0x60);
+ while (inVti(0x64) & 1) {
+ HalpStallExecution(3);
+ tmp = inVti(0x60);
+ }
+
+
+ return;
+}
+
+VOID
+HalpStallExecution(
+ ULONG Microseconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used internally to the HAL on Alpha AXP systems to
+ stall execution before KeStallExecutionProcessor is available.
+
+Arguments:
+
+ Microseconds - Supplies the number of microseconds to stall.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LONG StallCyclesRemaining; // signed value
+ ULONG PreviousRpcc, CurrentRpcc;
+
+
+ //
+ // Get the value of the RPCC as soon as we enter
+ //
+
+ PreviousRpcc = HalpRpcc();
+
+ //
+ // Compute the number of cycles to stall
+ //
+
+ StallCyclesRemaining = Microseconds * HalpClockMegaHertz;
+
+ //
+ // Wait while there are stall cycles remaining.
+ // The accuracy of this routine is limited by the
+ // length of this while loop.
+ //
+
+ while (StallCyclesRemaining > 0) {
+
+ CurrentRpcc = HalpRpcc();
+
+ //
+ // The subtraction always works because the Rpcc
+ // is a wrapping long-word. If it wraps, we still
+ // get the positive number we want.
+ //
+
+ StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc);
+
+ //
+ // remember this RPCC value
+ //
+
+ PreviousRpcc = CurrentRpcc;
+ }
+
+}
+
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/jxintsup.s b/private/ntos/nthals/hal0jens/alpha/jxintsup.s
new file mode 100644
index 000000000..94198c45f
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxintsup.s
@@ -0,0 +1,205 @@
+// TITLE("Clock and Eisa Interrupt Handlers")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// jxintsup.s
+//
+// Abstract:
+//
+// This module implements the first level interrupt handlers
+// for JENSEN.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+#include "jnsnrtc.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// VOID
+// HalpClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the JENSEN. The routine is responsible for acknowledging the
+// interrupt and calling the kernel to update the system time.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+CiRa: .space 8 // space for return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt, by reading the control register c of
+// the Real Time Clock in the 82C106 (VTI Combo Chip).
+//
+
+ ldil a0, RTC_APORT // get the address port for rtc
+ ldil a1, RTC_CONTROL_REGISTERC // address for control register
+ bsr ra, HalpWriteVti // write the address port
+
+ ldil a0, RTC_DPORT // get the data port for the rtc
+ bsr ra, HalpReadVti // read the data port
+
+//
+// Call the kernel to update the system time.
+//
+
+ ldl a1, HalpCurrentTimeIncrement
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateSystemTime
+ jsr ra, (t0) // call kernel to update system time
+
+ ldl t0, HalpNextTimeIncrement // Get next time increment
+ stl t0, HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+
+ ldl a0, HalpNextRateSelect // Get NextIntervalCount. If 0, no change required
+ beq a0, 5f
+
+ stl zero, HalpNextRateSelect // Set NextRateSelect to 0
+ bsr ra, HalpProgramIntervalTimer // Program timer with new rate select
+
+ ldl t0, HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+
+5:
+
+//
+// Update the 64-bit performance counter.
+//
+// N.B. - This code is careful to update the 64-bit counter atomically.
+//
+
+ lda t0, HalpRpccTime // get address of 64-bit rpcc global
+ ldq t4, 0(t0) // read rpcc global
+ rpcc t1 // read processor cycle counter
+ addl t1, zero, t1 // make t1 a longword
+ addl t4, 0, t2 // get low longword of rpcc global
+ cmpult t1, t2, t3 // is new rpcc < old rpcc
+ bne t3, 10f // if ne[true] rpcc wrapped
+ br zero, 20f // rpcc did not wrap
+
+//
+// The rpcc has wrapped, increment the high part of the 64-bit counter.
+//
+
+10:
+ lda t2, 1(zero) // t2 = 1
+ sll t2, 32, t2 // t2 = 1 0000 0000
+ addq t4, t2, t4 // increment high part by one
+
+20:
+
+ zap t4, 0x0f, t4 // clean low part of rpcc global
+ zap t1, 0xf0, t1 // clean high part of rpcc
+ addq t4, t1, t4 // merge new rpcc as low part of global
+ stq t4, 0(t0) // store the updated counter
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ ldl t0, __imp_DbgBreakPointWithStatus
+ lda a0, DBG_STATUS_CONTROL_C
+ jsr ra, (t0) // send status to debugger
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpClockInterrupt
+
+
+ SBTTL("Eisa Interrupt")
+//++
+//
+// VOID
+// HalpEisaInterruptHandler
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on the EISA
+// bus. The function is responsible for calling HalpEisaDispatch to
+// appropriately dispatch the EISA interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpEisaDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// EISA interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpEisaInterruptHandler)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpEisaDispatch // dispatch the interrupt
+
+ ret zero, (ra) // will never get here
+
+ .end HalpEisaInterruptHandler
+
diff --git a/private/ntos/nthals/hal0jens/alpha/jxioacc.s b/private/ntos/nthals/hal0jens/alpha/jxioacc.s
new file mode 100644
index 000000000..1bc9b5c52
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxioacc.s
@@ -0,0 +1,3523 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxioacc.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Alpha/Jensen machine.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+
+Author:
+
+ Rod Gamache [DEC] 19-May-1993
+ Jeff McLeman [DEC]
+ Joe Notarangelo [DEC]
+ Steve Jenness [DEC]
+
+ Completely rewrote all the ACCESS routines to use new design from
+ 14-May-1993. Work was based largely on work originally done by
+ Jeff Mcleman on 15-Jul-1992. Format of new QVA is shown below.
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+
+#include "jnsndef.h"
+#include "ksalpha.h"
+
+#define BAD_QVA 0xBADABADA
+#define BAD_LONG 1
+#define BAD_WORD 2
+#define SUPERVA 0xfffffc0000000000
+#define SUPERVA_SHORT 0xfffffc0000000020
+#define SUPERVA_LONG 0xfffffc0000000060
+
+#define HAE_PHYSICAL_BASEL 0xd0000000
+
+#define EISA_QUAD_OFFSET EISA_LONG_OFFSET*2 // To read next quadword
+#define EISA_SECOND_LONG EISA_LONG_OFFSET + EISA_LONG_LEN
+//
+// Format of QVA:
+//
+
+// +----------------------------------------------+
+// QVA: | 3 | 1 | 1 | 27 bit EISA offset |
+// +----------------------------------------------+
+// | | |
+// v | v (upper 2 bits used as HAE index)
+// KSEG1 | IO/
+// v MEM
+// EISA/
+// COMBO
+//
+// if EISA/COMBO bit: 1 is EISA space; 0 is COMBO space
+// if IO/MEM bit: 1 is IO space; 0 is MEMORY space
+//
+
+#define EISA_MEMORY -0x3fe0 // Used to generate EISA MEMORY address
+#define EISA_IO -0x3fd0 // Used to generate EISA IO address
+#define COMBO_IO -0x3ff0 // Used to generate COMBO IO address
+
+#define IO_HI_SHIFT 28 // Used with preceeding masks to form
+ // upper bits of Superpage address
+
+#define QVA_HAE_SHIFT 25 // Shift to get HAE selector bits
+
+// Mask to get selector bits (KSEG1) after HAE shift
+#define QVA_SELECTORS_SHIFTED 0x70
+
+#define QVA_ENABLE_SHIFTED 0x50 // Mask to get QVA bits after HAE shift
+
+#define EISA_BITS_ONEZERO 3*EISA_BYTE_OFFSET // mask for EISA address 1..0
+
+// Mask to clear SELECTOR bits plus EISA/COMBO and IO/MEM bits, when
+// used with LDAH this mask generates the QVA_CONTROL_FULL bit pattern plus
+// bits <63:32> are 1's. We can then cleanly pick off bits <63:25>.
+#define QVA_CONTROL -0x200
+
+// Full mask to clear SELECTOR bits plus EISA/COMBO, IO/MEM bits, and HAE bits
+#define QVA_CONTROL_FULL 0xfe000000
+
+
+
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Reads a byte location in bus memory space. Since there are
+ no register buffers (RAM) in COMBO space on Jensen, we will
+ only support EISA access.
+
+
+Arguments:
+
+ a0 QVA of byte to be read.
+
+
+Return Value:
+
+ v0 Register data.
+
+--*/
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 20f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We have already ignored the COMBO/EISA bit... we will now ignore
+ // the IO/MEM bit. This will save 2 instructions and we require that
+ // the REGISTER routines only be used for access to MEMORY space.
+ //
+
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 40f # br if HAE has to be set up
+
+ ldl v0, (t0) # get the longword
+ extbl v0, t3, v0 # get correct byte
+
+ ret zero, (ra)
+
+20:
+ //
+ // On non-I/O space access, do a normal memory operation
+ //
+ ldq_u v0, (a0) # get entire quad,don't assume aligned
+ extbl v0, a0, v0 # get the byte
+ ret zero, (ra) # return
+
+40:
+
+//
+// setup HAE.
+//
+// a0 = QVA
+// t0 = superpage address for QVA
+// t4 = HAE index
+// t3 = byte within longword
+// t2 = upper bits of EISA superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 90f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t5, (t1) # get original HAE value
+ bne t5, 90f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the byte from the EISA bus
+ //
+ ldl v0, (t0) # get the longword
+ extbl v0, t3, t4 # get correct byte
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL
+ //
+ SWAP_IRQL # restore original IRQL
+ bis t4, zero, v0 # put result in v0
+
+ ret zero, (ra)
+
+#if DBG
+90:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+ .end READ_REGISTER_UCHAR
+
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+/*++
+
+Routine Description:
+
+ Reads a byte location in bus memory space. Since there are
+ no register buffers (RAM) in COMBO space on Jensen, we will
+ only support EISA access. Note: a0 should be word aligned.
+
+
+Arguments:
+
+ a0 QVA of word to be read.
+
+
+Return Value:
+
+ v0 Register data.
+
+
+--*/
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get word within longword
+ bne t1, 20f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index alone
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We have already ignored the COMBO/EISA bit... we will now ignore
+ // the IO/MEM bit. This will save 2 instructions and we require that
+ // the REGISTER routines only be used for access to MEMORY space.
+ //
+
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 40f # br if HAE has to be set up
+
+ ldl v0, EISA_WORD_LEN(t0) # get the word within longword
+ extwl v0, t3, v0 # get the correct word
+
+ ret zero, (ra)
+
+20:
+
+ //
+ // On non-I/O space access, do a normal memory operation
+ //
+ ldq_u v0, (a0) # get entire quad,don't assume aligned
+ extwl v0, a0, v0 # get the word
+ ret zero, (ra) # return
+
+40:
+
+//
+// setup HAE.
+//
+// a0 = QVA
+// t0 = superpage address for QVA
+// t4 = HAE index
+// t3 = word within longword
+// t2 = upper bits of superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 90f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t5, (t1) # get original HAE value
+ bne t5, 90f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the word from the EISA bus
+ //
+ ldl v0, EISA_WORD_LEN(t0) # get the word within longword
+ extwl v0, t3, t4 # get correct word
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL
+ //
+ SWAP_IRQL # restore original IRQL
+ bis t4, zero, v0 # put result in v0
+
+ ret zero, (ra)
+
+#if DBG
+90:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end READ_REGISTER_USHORT
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Reads a longword location in bus memory space. Since there are
+ no register buffers (RAM) in COMBO space on Jensen, we will
+ only support EISA access. Note: a0 should be longword aligned.
+
+
+Arguments:
+
+ a0 QVA of longword to be read.
+
+
+
+Return Value:
+
+ v0 Register data
+
+
+--*/
+
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bne t1, 20f # br if not a bus address
+
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We have already ignored the COMBO/EISA bit... we will now ignore
+ // the IO/MEM bit. This will save 2 instructions and we require that
+ // the REGISTER routines only be used for access to MEMORY space.
+ //
+
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 40f # br if HAE has to be set up
+
+ ldl v0, EISA_LONG_LEN(t0) # read the longword
+ ret zero, (ra)
+
+20:
+ //
+ // On non-I/O space access, do a normal memory operation
+ //
+ ldl v0, (a0) # read the longword
+ ret zero, (ra)
+
+
+40:
+
+//
+// setup HAE.
+//
+// a0 = QVA
+// t0 = superpage address for QVA
+// t4 = HAE index
+// t2 = upper bits of superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 90f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t5, (t1) # get original HAE value
+ bne t5, 90f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the longword from the EISA bus
+ //
+ ldl t4, EISA_LONG_LEN(t0) # read the longword
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL
+ //
+ SWAP_IRQL # restore original IRQL
+ bis t4, zero, v0 # put result in v0
+
+ ret zero, (ra)
+
+#if DBG
+90:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+//
+// HAE has to be set up... this requires a lot of extra work!
+//
+ ret zero, (ra)
+
+
+ .end READ_REGISTER_ULONG
+
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Writes a byte location in bus memory space. Since there are no
+ register buffers (RAM) in COMBO space on Jensen, we will only
+ support access to EISA space.
+
+
+Arguments:
+
+ a0 QVA of byte to be written.
+ a1 Byte Datum to be written.
+
+Return Value:
+
+ v0 Register data.
+
+--*/
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 20f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index alone
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We have already ignored the COMBO/EISA bit... we will now ignore
+ // the IO/MEM bit. This will save 2 instructions and we require that
+ // the REGISTER routines only be used for access to MEMORY space.
+ //
+
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ insbl a1, t3, t3 # put byte in correct position
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 40f # br if HAE has to be set up
+
+ stl t3, (t0) # write the byte
+ mb # order the write
+ ret zero, (ra)
+
+20:
+ //
+ // If a non I/O space address, do normal memory operations
+ //
+ ldq_u t0, (a0) # get the quad
+ mskbl t0, a0, t0 # mask the proper byte
+ insbl a1, a0, t1 # put byte into position
+ bis t1, t0, t0 # merge byte in result
+ stq_u t0, (a0) # store the result
+ ret zero, (ra)
+
+40:
+
+//
+// setup HAE.
+//
+// a0 = QVA
+// t0 = superpage address for QVA
+// t4 = HAE index
+// t3 = data to be written (already put into correct lane position)
+// t2 = upper bits of superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 90f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t5, (t1) # get original HAE value
+ bne t5, 90f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can write the byte to the EISA bus
+ //
+ stl t3, (t0) # put byte out on bus
+ //mb # order the writes, we rely on
+ # the fact that EV4 will not reorder
+ # writes, but only merge writes. The
+ # next mb below will handle our flush.
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+90:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+ .end WRITE_REGISTER_UCHAR
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+/*++
+
+Routine Description:
+
+ Writes a word location in bus memory space. Since there are no
+ register buffers (RAM) in COMBO space on Jensen, we will only
+ support access to EISA space. Note: a0 should be word aligned.
+
+
+Arguments:
+
+ a0 QVA of word to be written.
+ a1 Word Datum to be written
+
+
+Return Value:
+
+ v0 Register data.
+
+
+--*/
+
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 20f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We have already ignored the COMBO/EISA bit... we will now ignore
+ // the IO/MEM bit. This will save 2 instructions and we require that
+ // the REGISTER routines only be used for access to MEMORY space.
+ //
+
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ inswl a1, t3, t3 # put the word into correct place
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 40f # br if HAE has to be set up
+
+ stl t3, EISA_WORD_LEN(t0) # write the word
+ mb # order the write
+ ret zero, (ra)
+
+20:
+ //
+ // If a non I/O space address, do normal memory operations
+ //
+ ldq_u t0, (a0) # get the quad
+ mskwl t0, a0, t0 # mask the proper word
+ inswl a1, a0, t1 # put word into position
+ bis t0, t1, t0 # merge in result
+ stq_u t0, (a0) # store the result
+ ret zero, (ra)
+
+
+40:
+
+//
+// setup HAE.
+//
+// a0 = QVA
+// t0 = superpage address for QVA
+// t4 = HAE index
+// t3 = data to be written (already put into correct lane position)
+// t2 = upper bits of superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 90f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t5, (t1) # get original HAE value
+ bne t5, 90f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can write the word to the EISA bus
+ //
+ stl t3, EISA_WORD_LEN(t0) # write the word
+ //mb # order the writes, we rely on
+ # the fact that EV4 will not reorder
+ # writes, but only merge writes. The
+ # next mb below will handle our flush.
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+90:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end WRITE_REGISTER_USHORT
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Writes a longword location in bus memory space. Since there are no
+ register buffers (RAM) in COMBO space on Jensen, we will only
+ support access to EISA space. Note: a0 should be longword aligned.
+
+
+Arguments:
+
+ a0 QVA of longword to be written.
+ a1 Longword to be written.
+
+
+Return Value:
+
+ v0 Register data
+
+
+--*/
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bne t1, 20f # br if not a bus address
+
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We have already ignored the COMBO/EISA bit... we will now ignore
+ // the IO/MEM bit. This will save 2 instructions and we require that
+ // the REGISTER routines only be used for access to MEMORY space.
+ //
+
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 40f # br if HAE has to be set up
+
+ stl a1, EISA_LONG_LEN(t0) # write the longword
+ mb # order the write
+ ret zero, (ra)
+
+20:
+ //
+ // On non-I/O space access, do a normal memory operation
+ //
+ stl a1, (a0) # store the longword
+ ret zero, (ra)
+
+40:
+
+//
+// setup HAE.
+//
+// a0 = QVA
+// a1 = data to be written
+// t0 = superpage address for QVA
+// t4 = HAE index
+// t2 = upper bits of superpage address
+//
+ bis a1, zero, t3 # move data to safe register
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 90f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t5, (t1) # get original HAE value
+ bne t5, 90f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can write the data to the EISA bus
+ //
+ stl t3, EISA_LONG_LEN(t0) # write the longword
+ //mb # order the writes, we rely on
+ # the fact that EV4 will not reorder
+ # writes, but only merge writes. The
+ # next mb below will handle our flush.
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+90:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end WRITE_REGISTER_ULONG
+
+
+ LEAF_ENTRY(READ_PORT_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Reads a byte location in I/O space. Unlike the _REGISTER_ routines,
+ these routines do not support access to main memory. This routine
+ supports both EISA IO and COMBO space.
+
+
+Arguments:
+
+ a0 QVA of byte to be read.
+
+
+Return Value:
+
+ v0 Register data.
+
+--*/
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ s8addl a0, zero, t2 # get COMBO/EISA bit in sign bit
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+ bge t2, 20f # br if COMBO address
+
+ //
+ // EISA address
+ //
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ and a0, 3, t3 # get byte within longword
+ ldl v0, (t0) # get the longword
+ extbl v0, t3, v0 # get correct byte
+
+ ret zero, (ra)
+
+20:
+ //
+ // COMBO address
+ //
+
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in COMBO IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, COMBO_IO # form upper bits of PA
+ sll t0, COMBO_BIT_SHIFT, t0 # shift for combo
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ ldl v0, (t0) # get the longword
+ //
+ // Our C compiler expects returned UCHAR values to be zero-extended.
+ //
+ zapnot v0, 1, v0
+
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end READ_PORT_UCHAR
+
+ LEAF_ENTRY(READ_PORT_USHORT)
+
+/*++
+
+Routine Description:
+
+ Reads a word location from I/O space. Since during a triple boot,
+ and at other times, drivers may probe for the existence of PORTs on
+ any bus, we must support all modes of access, even though the COMBO
+ space does not have any SHORT PORTs. Note: a0 should be word aligned.
+
+
+Arguments:
+
+ a0 QVA of word to be read.
+
+
+Return Value:
+
+ v0 Register data.
+
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ s8addl a0, zero, t2 # get COMBO/EISA bit in sign bit
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+ bge t2, 20f # br if COMBO address
+
+ //
+ // EISA address
+ //
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ and a0, 3, t3 # get byte within longword
+ ldl v0, EISA_WORD_LEN(t0) # get the word within longword
+ extwl v0, t3, v0 # get correct word
+ ret zero, (ra)
+
+20:
+ //
+ // COMBO Address
+ //
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in COMBO IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, COMBO_IO # form upper bits of PA
+ sll t0, COMBO_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ ldl v0, (t0) # get the longword
+ //
+ // Our C compiler expects returned USHORT values to be zero-extended.
+ //
+ zapnot v0, 3, v0 # clear all but low 2 bytes
+
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end READ_PORT_USHORT
+
+ LEAF_ENTRY(READ_PORT_ULONG)
+
+/*++
+
+Routine Description:
+
+ Reads a longword location from I/O space. Since during a triple boot,
+ and at other times, drivers may probe for the existence of PORTs on
+ any bus, we must support all modes of access, even though the COMBO
+ space does not have any LONG PORTs. Note: a0 should be longword aligned.
+
+
+Arguments:
+
+ a0 QVA of longword to be read.
+
+
+
+Return Value:
+
+ v0 Register data
+
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ s8addl a0, zero, t2 # get COMBO/EISA bit in sign bit
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+ bge t2, 20f # br if COMBO address - error
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ ldl v0, EISA_LONG_LEN(t0) # get the longword
+ ret zero, (ra)
+
+20:
+ //
+ // COMBO Address
+ //
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in COMBO IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, COMBO_IO # form upper bits of PA
+ sll t0, COMBO_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ ldl v0, (t0) # get the longword
+
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end READ_PORT_ULONG
+
+
+ LEAF_ENTRY(WRITE_PORT_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Writes a byte location in I/O space. Unlike the _REGISTER_ routines,
+ these routines do not support access to main memory. This routine
+ supports both EISA IO and COMBO space.
+
+
+Arguments:
+
+ a0 QVA of byte to be written.
+ a1 Byte Datum to be written.
+
+Return Value:
+
+ v0 Register data.
+
+--*/
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ s8addl a0, zero, t2 # get COMBO/EISA bit in sign bit
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+ bge t2, 20f # br if COMBO address
+
+ //
+ // EISA address
+ //
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ and a0, 3, t3 # get byte within longword
+ or t0, t4, t0 # generate superpage address
+ insbl a1, t3, t1 # put the byte in the correct position
+ stl t1, (t0) # write the byte
+ mb # order the writes
+
+ ret zero, (ra)
+
+20:
+ //
+ // COMBO address
+ //
+
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in COMBO IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, COMBO_IO # form upper bits of PA
+ sll t0, COMBO_BIT_SHIFT, t0 # shift for combo
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ stl a1, (t0) # write the byte
+ mb # order the writes
+
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end WRITE_PORT_UCHAR
+
+ LEAF_ENTRY(WRITE_PORT_USHORT)
+
+/*++
+
+Routine Description:
+
+ Writes a word location in I/O space. Since during a triple boot,
+ and at other times, drivers may probe for the existence of PORTs on
+ any bus, we must support all modes of access, even though the COMBO
+ space does not have any SHORT PORTs. Note: a0 should be word aligned.
+
+
+Arguments:
+
+ a0 QVA of word to be written.
+ a1 Word Datum to be written
+
+
+Return Value:
+
+ v0 Register data.
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ s8addl a0, zero, t2 # get COMBO/EISA bit in sign bit
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+ bge t2, 20f # br if COMBO address - error
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ and a0, 3, t3 # get word within longword
+ or t0, t4, t0 # generate superpage address
+ inswl a1, t3, t1 # put the byte in the correct position
+ stl t1, EISA_WORD_LEN(t0) # write the word
+ mb # order the writes
+
+ ret zero, (ra)
+
+20:
+ //
+ // COMBO address
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in COMBO IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, COMBO_IO # form upper bits of PA
+ sll t0, COMBO_BIT_SHIFT, t0 # shift for combo
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ stl a1, (t0) # write the byte
+ mb # order the writes
+
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end WRITE_PORT_USHORT
+
+ LEAF_ENTRY(WRITE_PORT_ULONG)
+
+/*++
+
+Routine Description:
+
+ Writes a longword location in I/O space. Since during a triple boot
+ and at other times, drivers may probe for the existence of PORTs on
+ any bus, we must support all modes of access, even though the COMBO
+ space does not have any LONG PORTs. Note: a0 should be longword
+ aligned.
+
+
+Arguments:
+
+ a0 QVA of longword to be written.
+ a1 Longword to be written.
+
+
+Return Value:
+
+ v0 Register data
+
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ s8addl a0, zero, t2 # get COMBO/EISA bit in sign bit
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+ bge t2, 20f # br if COMBO address - error
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ stl a1, EISA_LONG_LEN(t0) # write the longword
+ mb # order the writes
+
+ ret zero, (ra)
+
+20:
+ //
+ // COMBO address
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in COMBO IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+
+ ldiq t4, COMBO_IO # form upper bits of PA
+ sll t0, COMBO_BIT_SHIFT, t0 # shift for combo
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ stl a1, (t0) # write the byte
+ mb # order the writes
+
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end WRITE_PORT_ULONG
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Reads from the specified port buffer address. Since there are no
+ PORT buffers on Jensen, there is no code to handle COMBO space in
+ this routine.
+
+
+Arguments:
+
+ a0 QVA of source port.
+ a1 VA of destination buffer in memory.
+ a2 Number of bytes to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ beq a2, 30f # leave now if nothing to move
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ and a0, 3, t3 # get byte within longword
+
+20:
+ ldl v0, (t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ bne a2, 20b # loop if more bytes to move
+30:
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end READ_PORT_BUFFER_UCHAR
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+/*++
+
+Routine Description:
+
+ Reads from the specified port buffer address. Since there are no
+ PORT buffers on Jensen, there is no code to handle COMBO space in
+ this routine. Note: a0, a1 should be word aligned.
+
+
+Arguments:
+
+ a0 QVA of source port.
+ a1 VA of destination buffer in memory.
+ a2 Number of words to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ beq a2, 30f # leave now if nothing to move
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ and a0, 3, t3 # get word within longword
+
+20:
+ ldl v0, EISA_WORD_LEN(t0) # get the word within the longword
+ subl a2, 1, a2 # decrement count
+ extwl v0, t3, v0 # get the correct word
+ stw v0, (a1) # cheat and let the assembler do it
+ addl a1, 2, a1 # next word in buffer
+ bne a2, 20b # loop if more bytes to move
+30:
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end READ_PORT_BUFFER_USHORT
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Reads from the specified port buffer address. Since there are no
+ PORT buffers on Jensen, there is no code to handle COMBO space in
+ this routine. Note: a0, a1 should be longword aligned.
+
+
+Arguments:
+
+ a0 QVA of source port.
+ a1 VA of destination buffer in memory.
+ a2 Number of longs to move (Count).
+
+Return Value:
+
+ None
+
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ beq a2, 30f # leave now if nothing to move
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+
+20:
+ ldl v0, EISA_LONG_LEN(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ stl v0, (a1) # save the longword
+ addl a1, 4, a1 # next byte in buffer
+ bne a2, 20b # loop if more bytes to move
+30:
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Writes to the specified port buffer address. Since there are no
+ PORT buffers on Jensen, there is no code to handle COMBO space in
+ this routine.
+
+
+Arguments:
+
+ a0 QVA of destination port.
+ a1 VA of source buffer in memory.
+ a2 Number of bytes to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ beq a2, 30f # leave now if nothing to move
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ and a0, 3, t3 # get byte within longword
+
+20:
+ ldq_u t1, 0(a1) # get quad surrounding byte
+ subl a2, 1, a2 # decrement count
+ extbl t1, a1, t1 # extract appropriate byte
+ addl a1, 1, a1 # increment buffer pointer
+ insbl t1, t3, t1 # put byte to appropriate lane
+ stl t1, 0(t0) # store to port
+ mb # push writes off chip
+ bne a2, 20b # loop if more bytes to move
+30:
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+/*++
+
+Routine Description:
+
+ Writes to the specified port buffer address. Since there are no
+ PORT buffers on Jensen, there is no code to handle COMBO space in
+ this routine. Note: a0, a1 should be word aligned.
+
+
+Arguments:
+
+ a0 QVA of destination port.
+ a1 VA of source buffer in memory.
+ a2 Number of words to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ beq a2, 30f # leave now if nothing to move
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+ and a0, 3, t3 # get byte within longword
+
+20:
+ ldq_u t1, (a1) # get quad surrounding word
+ subl a2, 1, a2 # decrement count
+ extwl t1, a1, t1 # extract appropriate word
+ addl a1, 2, a1 # increment buffer pointer
+ inswl t1, t3, t1 # put word to appropriate lane
+ stl t1, EISA_WORD_LEN(t0) # store the word to the port
+ mb # push writes off chip
+ bne a2, 20b # loop if more bytes to move
+30:
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Writes to the specified port buffer address. Since there are no
+ PORT buffers on Jensen, there is no code to handle COMBO space in
+ this routine. Note: a0, a1 should be longword aligned.
+
+
+Arguments:
+
+ a0 QVA of destination port.
+ a1 VA of source buffer in memory.
+ a2 Number of longs to move (Count).
+
+Return Value:
+
+ None
+
+
+--*/
+
+
+#if DBG
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address - error
+ and t2, 3, t4 # get HAE index
+
+ //
+ // Check if HAE is non-zero. For IO space access this should never
+ // be non-zero!
+ //
+ bne t4, 40f # br if HAE non-zero - error
+#endif
+
+ beq a2, 30f # leave now if nothing to move
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // We will now ignore the IO/MEM bit and generate bits PA<63:32>
+ // knowing that we are in EISA IO space. This will save 2 instructions
+ // and require that the PORT routines only be used for access to IO
+ // space.
+ //
+ ldiq t4, EISA_IO # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t4, IO_HI_SHIFT, t4 # shift bits PA<63:32> into position
+ or t0, t4, t0 # generate superpage address
+
+20:
+ ldl t1, (a1) # a1 must be longword aligned
+ subl a2, 1, a2 # decrement count
+ stl t1, EISA_LONG_LEN(t0) # store longword to port
+ mb # push writes off chip
+ addl a1, 4, a1 # increment buffer pointer
+ bne a2, 20b # loop if more bytes to move
+30:
+ ret zero, (ra)
+
+#if DBG
+40:
+ //
+ // HAE is non-zero or not a bus address, this should never happen!
+ //
+ BREAK_DEBUG_STOP
+ or a0, zero, a2 # save bad address in a2
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if illegal access
+#endif
+
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+/*++
+
+Routine Description:
+
+ Reads from the specified buffer address. This routine only works
+ with EISA memory space, since there are no REGISTER buffers in
+ COMBO space on Jensen.
+
+
+Arguments:
+
+ a0 QVA of source buffer.
+ a1 VA of destination buffer in memory.
+ a2 Number of bytes to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 120f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t2, IO_HI_SHIFT, t2 # shift upper bits into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 130f # br if HAE has to be set up
+
+ //
+ // get source buffer aligned
+ //
+ // t0 = superpage bus address of source
+ // a1 = destination va
+ // a2 = byte count
+ // t3 = byte offset (in a LONGWORD)
+ //
+
+ ldiq t10, EISA_BITS_ONEZERO # mask for EISA address 1..0
+ and t0, t10, t9 # t9 holds EISA address bits 1..0
+ srl t9, EISA_BIT_SHIFT, t9 # position bits down low
+ and a1, 3, t8 # 1..0 of destination VA
+ xor t9, t8, t8 # compare alignment of src and dst
+ bne t8, 70f # use unaligned code if not aligned
+
+ // transfer can be done using longword fetch/store since the
+ // source and destination are sympathetically aligned
+
+ beq t9, 20f # branch if src is already longaligned
+
+ // Move bytes until source is at a longword boundary
+
+10: beq a2, 60f # while count > 0
+
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ bne t3, 10b # while unaligned loop here
+
+ // move aligned longwords
+
+20: srl a2, 2, t3 # longwords to move
+ beq t3, 40f # done moving longwords?
+
+ lda t11, EISA_LONG_OFFSET(zero) # longword stride in EISA space
+30: ldl t4, EISA_LONG_LEN(t0) # fetch longword from EISA
+ addl a1, 4, a1 # increment dst VA
+ subl t3, 1, t3 # decr longwords to move
+ stl t4, -4(a1) # store to dst
+ addq t0, t11, t0 # increment src pointer
+ bne t3, 30b # while longwords remain
+
+40: and a2, 3, a2 # bytes remaining
+ //bis zero, zero, t3 # byte lane 0
+
+
+ // non-aligned and driblets move
+
+50: beq a2, 60f # while count > 0
+
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ br zero, 50b # end while
+60:
+
+ ret zero, (ra)
+//
+// source EISA alignment != destination memory alignment
+// move enough bytes to longword align the EISA source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// t0 = superpage address of source
+// a1 = virtual address of destination
+// a2 = bytes to move
+// t9 = low 2 bits of EISA superpage address
+// t3 = low 2 bits of EISA QVA
+//
+
+70:
+ beq t9, 90f # branch if src is longaligned
+
+// Move bytes until EISA src is at a longword boundary or bytes exhausted
+
+80: beq a2, 60b # while count > 0
+
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ bne t3, 80b # while not aligned
+
+// align EISA source, unaligned memory destination
+
+90:
+ srl a2, 3, t3 # t3 = quadwords to move
+ beq t3, 110f # finish if no longwords
+
+100:
+ ldl t1, EISA_LONG_LEN(t0) # load longword 0 from EISA
+ ldq_u t4, 0(a1) # load destination quad for merge
+ ldq_u t5, 7(a1) #
+ subl t3, 1, t3 # decrement quadwords to move
+ ldl t2, EISA_SECOND_LONG(t0) # load longword 1 from EISA
+ mskql t4, a1, t4 # mask of merge bytes
+ mskqh t5, a1, t5 # mask of merge bytes
+ zap t1, 0xf0, t1 # clear high longword for long 0
+ sll t2, 32, t2 # get long 1 to high longword
+ bis t1, t2, t1 # merge read quadword together
+ lda t0, EISA_QUAD_OFFSET(t0) # increment to next quadword
+ insql t1, a1, t6 # position low quadword for merge
+ insqh t1, a1, t7 # position high quadword for merge
+ bis t4, t6, t4 # merge new data, low quadword
+ bis t5, t7, t5 # merge new data, high quadword
+ stq_u t5, 7(a1) # write high quadword
+ stq_u t4, 0(a1) # write low quadword
+ lda a1, 8(a1) # increment memory pointer
+ bne t3, 100b # while quadwords to move
+
+110:
+ and a2, 7, a2 # bytes remaining to move
+ //bis zero, zero, t3 # byte line position of next byte
+ br zero, 50b # go back to byte mover
+
+120:
+
+//
+// This must be non I/O space access
+//
+ bis a0, zero, t0 # save source address
+ bis a1, zero, a0 # move destination address to a0
+ bis t0, zero, a1 # move source address to a1
+ br zero, RtlMoveMemory # Let Rtl routine handle move
+
+
+
+130:
+
+//
+// setup HAE
+//
+// a0 = QVA
+// a1 = destination va
+// a2 = byte count
+// t0 = superpage bus address of source
+// t3 = byte offset (in a LONGWORD)
+// t4 = HAE index
+// t2 = upper bits of EISA superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 250f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ bis a1, zero, t6 # save a1, since SWAP_IRQL destroys it
+ bis a2, zero, t7 # save a2, since SWAP_IRQL destroys it
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ bis t6, zero, a1 # restore a1
+ bis t7, zero, a2 # restore a2
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t8, (t1) # get original HAE value
+ bne t8, 250f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the bytes from the EISA bus
+ //
+ // t8 = original HAE value (debug only)
+ // a0 = original IRQL
+ //
+ // t0 = superpage bus address of source
+ // t1 = address of HAE register
+ // a1 = destination va
+ // a2 = byte count
+ // t3 = byte offset (in a LONGWORD)
+ //
+
+ ldiq t10, EISA_BITS_ONEZERO # mask for EISA address 1..0
+ and t0, t10, t9 # t9 holds EISA address bits 1..0
+ srl t9, EISA_BIT_SHIFT, t9 # position bits down low
+ and a1, 3, t10 # 1..0 of destination VA
+ xor t9, t10, t10 # compare alignment of src and dst
+ bne t10, 200f # use unaligned code if not aligned
+
+ // transfer can be done using longword fetch/store since the
+ // source and destination are sympathetically aligned
+
+ beq t9, 150f # branch if src is already longaligned
+
+ // Move bytes until source is at a longword boundary
+
+140: beq a2, 190f # while count > 0
+
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ bne t3, 140b # while unaligned loop here
+
+ // move aligned longwords
+
+150: srl a2, 2, t3 # longwords to move
+ beq t3, 170f # done moving longwords?
+
+ lda t11, EISA_LONG_OFFSET(zero) # longword stride in EISA space
+160: ldl t4, EISA_LONG_LEN(t0) # fetch longword from EISA
+ addl a1, 4, a1 # increment dst VA
+ subl t3, 1, t3 # decr longwords to move
+ stl t4, -4(a1) # store to dst
+ addq t0, t11, t0 # increment src pointer
+ bne t3, 160b # while longwords remain
+
+170: and a2, 3, a2 # bytes remaining
+ //bis zero, zero, t3 # byte lane 0
+
+
+ // non-aligned and driblets move
+
+180: beq a2, 190f # while count > 0
+
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ br zero, 180b # end while
+190:
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL, original IRQL in a0
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+//
+// source EISA alignment != destination memory alignment
+// move enough bytes to longword align the EISA source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// t8 = original HAE value (debug only)
+// a0 = original IRQL
+//
+// t0 = superpage address of source
+// a1 = virtual address of destination
+// a2 = bytes to move
+// t9 = low 2 bits of EISA superpage address
+// t3 = low 2 bits of EISA QVA
+//
+
+200:
+ beq t9, 220f # branch if src is longaligned
+
+// Move bytes until EISA src is at a longword boundary or bytes exhausted
+
+210: beq a2, 190b # while count > 0
+
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extbl v0, t3, v0 # get the correct byte
+ stb v0, (a1) # cheat and let the assembler do it
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ bne t3, 210b # while not aligned
+
+// align EISA source, unaligned memory destination
+
+220:
+ srl a2, 3, t3 # t3 = quadwords to move
+ beq t3, 240f # finish if no longwords
+
+230:
+ ldl v0, EISA_LONG_LEN(t0) # load longword 0 from EISA
+ ldq_u t4, 0(a1) # load destination quad for merge
+ ldq_u t5, 7(a1) #
+ subl t3, 1, t3 # decrement quadwords to move
+ ldl t2, EISA_SECOND_LONG(t0) # load longword 1 from EISA
+ mskql t4, a1, t4 # mask of merge bytes
+ mskqh t5, a1, t5 # mask of merge bytes
+ zap v0, 0xf0, v0 # clear high longword for long 0
+ sll t2, 32, t2 # get long 1 to high longword
+ bis v0, t2, v0 # merge read quadword together
+ lda t0, EISA_QUAD_OFFSET(t0) # increment to next quadword
+ insql v0, a1, t6 # position low quadword for merge
+ insqh v0, a1, t7 # position high quadword for merge
+ bis t4, t6, t4 # merge new data, low quadword
+ bis t5, t7, t5 # merge new data, high quadword
+ stq_u t5, 7(a1) # write high quadword
+ stq_u t4, 0(a1) # write low quadword
+ lda a1, 8(a1) # increment memory pointer
+ bne t3, 230b # while quadwords to move
+
+240:
+ and a2, 7, a2 # bytes remaining to move
+ //bis zero, zero, t3 # byte line position of next byte
+ br zero, 180b # go back to byte mover
+
+#if DBG
+250:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end READ_REGISTER_BUFFER_UCHAR
+
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+/*++
+
+Routine Description:
+
+ Reads from the specified buffer address. This routine only works
+ with EISA memory space, since there are no REGISTER buffers in
+ COMBO space on Jensen.
+
+ Both the input buffer and output buffer should be word aligned.
+
+Arguments:
+
+ a0 QVA of source buffer.
+ a1 VA of destination buffer in memory.
+ a2 Number of words to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+ beq a2, 30f # leave is nothing to do
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 40f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index alone
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t2, IO_HI_SHIFT, t2 # shift upper bits into position
+ or t0, t2, t0 # generate superpage address
+ or t0, EISA_WORD_LEN, t0 # or in the WORD byte enables
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 100f # br if HAE has to be set up
+
+20:
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ extwl v0, t3, v0 # get the correct
+ stw v0, (a1) # cheat and let the assembler do it
+ addl a1, 2, a1 # next word in buffer
+ addq t0, EISA_SHORT_OFFSET, t0 # next I/O address
+ addl t3, 2, t3 # next word in lane
+ and t3, 3, t3 # longword lanes
+ bne a2, 20b # end while
+30:
+ ret zero, (ra)
+
+40:
+ //
+ // This must be non I/O space access
+ //
+ bis a0, zero, t0 # save source address
+ sll a2, 1, a2 # convert word count to byte count
+ bis a1, zero, a0 # move destination address to a0
+ bis t0, zero, a1 # move source address to a1
+ br zero, RtlMoveMemory # Let Rtl routine handle move
+
+100:
+
+//
+// setup HAE
+//
+// a0 = QVA of source
+// a1 = destination va
+// a2 = word count
+// t0 = superpage bus address of source
+// t3 = byte offset for source (within a LONGWORD)
+// t4 = HAE index
+// t2 = upper bits of EISA superpage address
+//
+
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 150f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ bis a1, zero, t6 # save a1, since SWAP_IRQL destroys it
+ bis a2, zero, t7 # save a2, since SWAP_IRQL destroys it
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t8, (t1) # get original HAE value
+ bne t8, 150f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the words from the EISA bus
+ //
+ // t8 = original HAE value (debug only)
+ // a0 = original IRQL
+ //
+ // t0 = superpage bus address of source
+ // t1 = address of HAE register
+ // t6 = destination va
+ // t7 = word count
+ // t3 = byte offset for source (within a LONGWORD)
+ //
+
+120:
+ ldl v0, 0(t0) # get the longword
+ subl t7, 1, t7 # decrement count
+ extwl v0, t3, v0 # get the correct
+ stw v0, (t6) # cheat and let the assembler do it
+ addl t6, 2, t6 # next word in buffer
+ addq t0, EISA_SHORT_OFFSET, t0 # next I/O address
+ addl t3, 2, t3 # next word in lane
+ and t3, 3, t3 # longword lanes
+ bne t7, 120b # end while
+130:
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL, original IRQL in a0
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+150:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end READ_REGISTER_BUFFER_USHORT
+
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Reads from the specified buffer address. This routine only works
+ with EISA memory space, since there are no REGISTER buffers in
+ COMBO space on Jensen.
+
+ Both the input buffer and output buffer should be longword aligned.
+
+Arguments:
+
+ a0 QVA of source buffer.
+ a1 VA of destination buffer in memory.
+ a2 Number of longs to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+ beq a2, 30f # leave if nothing to do
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t2, IO_HI_SHIFT, t2 # shift upper bits into position
+ or t0, t2, t0 # generate superpage address
+ or t0, EISA_LONG_LEN, t0 # or in the LONGWORD byte enables
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 100f # br if HAE has to be set up
+
+20:
+ ldl v0, 0(t0) # get the longword
+ subl a2, 1, a2 # decrement count
+ stl v0,(a1) # cheat and let the assembler do it
+ addl a1, 4, a1 # next longword in buffer
+ addq t0, EISA_LONG_OFFSET, t0 # next I/O address
+ bne a2, 20b # end while
+30:
+ ret zero, (ra)
+
+40:
+ //
+ // This must be non I/O space access
+ //
+
+ bis a0, zero, t0 # save source address
+ s4addl a2, zero, a2 # convert longword count to byte count
+ bis a1, zero, a0 # move destination address to a0
+ bis t0, zero, a1 # move source address to a1
+ br zero, RtlMoveMemory # Let Rtl routine handle move
+
+100:
+
+//
+// setup HAE
+//
+// a0 = QVA of source
+// a1 = destination va
+// a2 = longword count
+// t0 = superpage bus address of source
+// t4 = HAE index
+// t2 = upper bits of EISA superpage address
+//
+
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 150f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ bis a1, zero, t6 # save a1, since SWAP_IRQL destroys it
+ bis a2, zero, t7 # save a2, since SWAP_IRQL destroys it
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t8, (t1) # get original HAE value
+ bne t8, 150f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the words from the EISA bus
+ //
+ // t8 = original HAE value (debug only)
+ // a0 = original IRQL
+ //
+ // t0 = superpage bus address of source
+ // t1 = address of HAE register
+ // t6 = destination va
+ // t7 = longword count
+ //
+
+120:
+ ldl v0, 0(t0) # get the longword
+ subl t7, 1, t7 # decrement count
+ stl v0, (t6) # cheat and let the assembler do it
+ addl t6, 4, t6 # next word in buffer
+ addq t0, EISA_LONG_OFFSET, t0 # next I/O address
+ bne t7, 120b # end while
+130:
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL, original IRQL in a0
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+150:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end READ_REGISTER_BUFFER_ULONG
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+/*++
+
+Routine Description:
+
+ Writes to the specified buffer address. This routine only works
+ with EISA memory space, since there are no REGISTER buffers in
+ COMBO space on Jensen.
+
+
+Arguments:
+
+ a0 QVA of destination buffer in I/O space.
+ a1 VA of source buffer in memory.
+ a2 Number of bytes to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 120f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t2, IO_HI_SHIFT, t2 # shift upper bits into position
+ or t0, t2, t0 # generate superpage address
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 130f # br if HAE has to be set up
+
+ //
+ //
+ // get destination buffer aligned
+ //
+ // t0 = superpage destination bus address
+ // a1 = source va
+ // a2 = byte count
+ // t3 = byte offset (in a LONGWORD)
+ //
+
+ ldiq t10, EISA_BITS_ONEZERO # mask for EISA address 1..0
+ and t0, t10, t9 # t9 holds EISA address bits 1..0
+ srl t9, EISA_BIT_SHIFT, t9 # position bits
+ and a1, 3, t8 # 1..0 of destination VA
+ xor t9, t8, t8 # compare alignment of src and dst
+ bne t8, 70f # use unaligned move if not aligned
+
+ // transfer can be done using longword fetch/store since the
+ // source and destination are sympathetically aligned
+
+ beq t9, 20f # br if dest is already longaligned
+
+// Move bytes until destination is at a longword boundary or bytes exhausted
+
+10: beq a2, 60f # while count > 0
+
+ ldq_u t1, 0(a1) # get quad surrounding byte
+ subl a2, 1, a2 # decrement count
+ extbl t1, a1, t1 # extract appropriate byte
+ addl a1, 1, a1 # increment buffer pointer
+ insbl t1, t3, t1 # get proper lane
+ stl t1, 0(t0) # store to buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # increment I/O buffer
+ addl t3, 1, t3
+ and t3, 3, t3 # longwords only
+ bne t3, 10b # loop if not long aligned
+
+ // move aligned longwords
+
+20: srl a2, 2, t3 # longwords to move
+ beq t3, 40f # done moving longwords?
+
+ lda t11, EISA_LONG_OFFSET(zero) # longword stride in EISA space
+30: ldl t4, 0(a1) # fetch longword from memory
+ addl a1, 4, a1 # increment to next longword
+ subl t3, 1, t3 # decrement longwords to move
+ stl t4, EISA_LONG_LEN(t0) # store longword to EISA
+ addq t0, t11, t0 # increment EISA pointer
+ bne t3, 30b # while longwords remain
+
+40: and a2, 3, a2 # bytes remaining
+ //bis zero, zero, t3 # byte lane 0
+
+
+ // non-aligned and driblets move
+50: beq a2, 60f # copy while a2 > 0
+
+ ldq_u t1, 0(a1) # get quad surrounding byte
+ subl a2, 1, a2 # decrement count
+ extbl t1, a1, t1 # extract appropriate byte
+ addl a1, 1, a1 # increment buffer pointer
+ insbl t1, t3, t1 # get proper lane
+ stl t1, 0(t0) # store to buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # increment I/O buffer
+ addl t3, 1, t3
+ and t3, 3, t3 # longwords only
+ br zero, 50b # end while
+
+60: mb
+
+ ret zero, (ra)
+
+//
+// source EISA alignment != destination memory alignment
+// move enough bytes to longword align the EISA destination
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+// t0 = superpage address of destination
+// a1 = virtual address of source
+// a2 = bytes to move
+// t9 = low 2 bits of EISA superpage address
+// t3 = low 2 bits of EISA QVA
+//
+
+70:
+ beq t9, 90f # branch if destination is longaligned
+
+// Move bytes until EISA src is at a longword boundary or bytes exhausted
+
+80: beq a2, 60b # while count > 0
+
+ ldq_u v0, 0(a1) # get byte
+ extbl v0, a1, v0 #
+ insbl v0, t3, v0 # get proper lane
+ stl v0, 0(t0) # store byte to EISA buffer
+ subl a2, 1, a2 # decrement count
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ bne t3, 80b # loop while not aligned
+
+ // aligned EISA source, unaligned memory destination
+
+90:
+ srl a2, 3, t3 # t3 = quadwords to move
+ beq t3, 110f # finish if no quadwords
+
+100:
+ ldq_u t1, 0(a1) # load low source quadword
+ ldq_u t2, 7(a1) # load high source quadword
+ extql t1, a1, t1 # extract low portion of quadword
+ extqh t2, a1, t2 # extract high portion of quadword
+ bis t1, t2, t1 # merge to get source quadword
+ stl t1, EISA_LONG_LEN(t0) # store low longword to EISA
+ lda a1, 8(a1) # increment to next source quadword
+ srl t1, 32, t1 # get high longword into position
+ subl t3, 1, t3 # decrement quadwords to move
+ stl t1, EISA_SECOND_LONG(t0) # store high longword
+ lda t0, EISA_QUAD_OFFSET(t0) # increment to next dest. quadword
+ bne t3, 100b # while quadwords to move
+
+110:
+ and a2, 7, a2 # bytes remaining to move
+ //bis zero, zero, t3 # byte line position of next byte
+ br zero, 50b # go back to byte mover
+
+120:
+ //
+ // This must be non I/O space access
+ //
+ br zero, RtlMoveMemory # Let Rtl routine handle move
+
+
+
+130:
+
+//
+// setup HAE
+//
+// a0 = QVA
+// a1 = source va
+// a2 = byte count
+// t0 = superpage bus address of destination
+// t3 = byte offset for destination (within a LONGWORD)
+// t4 = HAE index
+// t2 = upper bits of EISA superpage address
+//
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 250f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ bis a1, zero, t6 # save a1, since SWAP_IRQL destroys it
+ bis a2, zero, t7 # save a2, since SWAP_IRQL destroys it
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ bis t6, zero, a1 # restore a1
+ bis t7, zero, a2 # restore a2
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t8, (t1) # get original HAE value
+ bne t8, 250f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can write the bytes to the EISA bus
+ //
+ // t8 = original HAE value (debug only)
+ // a0 = original IRQL
+ //
+ // t0 = superpage bus address of destination
+ // t1 = address of HAE register
+ // a1 = source va
+ // a2 = byte count
+ // t3 = byte offset of destination (within a LONGWORD)
+ //
+
+ ldiq t10, EISA_BITS_ONEZERO # mask for EISA address 1..0
+ and t0, t10, t9 # t9 holds EISA address bits 1..0
+ srl t9, EISA_BIT_SHIFT, t9 # position bits
+ and a1, 3, t10 # 1..0 of destination VA
+ xor t9, t10, t10 # compare alignment of src and dst
+ bne t10, 200f # use unaligned move if not aligned
+
+ // transfer can be done using longword fetch/store since the
+ // source and destination are sympathetically aligned
+
+ beq t9, 150f # br if dest is already longaligned
+
+// Move bytes until destination is at a longword boundary or bytes exhausted
+
+140: beq a2, 190f # while count > 0
+
+ ldq_u v0, 0(a1) # get quad surrounding byte
+ subl a2, 1, a2 # decrement count
+ extbl v0, a1, v0 # extract appropriate byte
+ addl a1, 1, a1 # increment buffer pointer
+ insbl v0, t3, v0 # get proper lane
+ stl v0, 0(t0) # store to buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # increment I/O buffer
+ addl t3, 1, t3
+ and t3, 3, t3 # longwords only
+ bne t3, 140b # loop if not long aligned
+
+ // move aligned longwords
+
+150: srl a2, 2, t3 # longwords to move
+ beq t3, 170f # done moving longwords?
+
+ lda t11, EISA_LONG_OFFSET(zero) # longword stride in EISA space
+160: ldl t4, 0(a1) # fetch longword from memory
+ addl a1, 4, a1 # increment to next longword
+ subl t3, 1, t3 # decrement longwords to move
+ stl t4, EISA_LONG_LEN(t0) # store longword to EISA
+ addq t0, t11, t0 # increment EISA pointer
+ bne t3, 160b # while longwords remain
+
+170: and a2, 3, a2 # bytes remaining
+ //bis zero, zero, t3 # byte lane 0
+
+
+ // non-aligned and driblets move
+180: beq a2, 190f # copy while a2 > 0
+
+ ldq_u v0, 0(a1) # get quad surrounding byte
+ subl a2, 1, a2 # decrement count
+ extbl v0, a1, v0 # extract appropriate byte
+ addl a1, 1, a1 # increment buffer pointer
+ insbl v0, t3, v0 # get proper lane
+ stl v0, 0(t0) # store to buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # increment I/O buffer
+ addl t3, 1, t3
+ and t3, 3, t3 # longwords only
+ br zero, 180b # end while
+
+190:
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out + previous writes
+
+ //
+ // Lower IRQL, original IRQL in a0
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+//
+// source EISA alignment != destination memory alignment
+// move enough bytes to longword align the EISA destination
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+// t0 = superpage address of destination
+// a1 = virtual address of source
+// a2 = bytes to move
+// t9 = low 2 bits of EISA superpage address
+// t3 = low 2 bits of EISA QVA
+//
+
+200:
+ beq t9, 220f # branch if destination is longaligned
+
+// Move bytes until EISA src is at a longword boundary or bytes exhausted
+
+210: beq a2, 190b # while count > 0
+
+ ldq_u v0, 0(a1) # get byte
+ extbl v0, a1, v0 #
+ insbl v0, t3, v0 # get proper lane
+ stl v0, 0(t0) # store byte to EISA buffer
+ subl a2, 1, a2 # decrement count
+ addl a1, 1, a1 # next byte in buffer
+ addq t0, EISA_BYTE_OFFSET, t0 # next I/O address
+ addl t3, 1, t3 # next byte in lane
+ and t3, 3, t3 # longword lanes
+ bne t3, 210b # loop while not aligned
+
+ // aligned EISA source, unaligned memory destination
+
+220:
+ srl a2, 3, t3 # t3 = quadwords to move
+ beq t3, 240f # finish if no quadwords
+
+230:
+ ldq_u v0, 0(a1) # load low source quadword
+ ldq_u t2, 7(a1) # load high source quadword
+ extql v0, a1, v0 # extract low portion of quadword
+ extqh t2, a1, t2 # extract high portion of quadword
+ bis v0, t2, v0 # merge to get source quadword
+ stl v0, EISA_LONG_LEN(t0) # store low longword to EISA
+ lda a1, 8(a1) # increment to next source quadword
+ srl v0, 32, v0 # get high longword into position
+ subl t3, 1, t3 # decrement quadwords to move
+ stl v0, EISA_SECOND_LONG(t0) # store high longword
+ lda t0, EISA_QUAD_OFFSET(t0) # increment to next dest. quadword
+ bne t3, 230b # while quadwords to move
+
+240:
+ and a2, 7, a2 # bytes remaining to move
+ //bis zero, zero, t3 # byte line position of next byte
+ br zero, 180b # go back to byte mover
+
+#if DBG
+250:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end WRITE_REGISTER_BUFFER_UCHAR
+
+
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+/*++
+
+Routine Description:
+
+ Writes to the specified buffer address. This routine only works
+ with EISA memory space, since there are no REGISTER buffers in
+ COMBO space on Jensen.
+
+ Both the input buffer and output buffer should be word aligned.
+
+Arguments:
+
+ a0 QVA of destination buffer.
+ a1 VA of source buffer in memory.
+ a2 Number of bytes to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+ beq a2, 30f # leave if nothing to do
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ and a0, 3, t3 # get byte within longword
+ bne t1, 40f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t2, IO_HI_SHIFT, t2 # shift upper bits into position
+ or t0, t2, t0 # generate superpage address
+ or t0, EISA_WORD_LEN, t0 # or in the WORD byte enables
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 100f # br if HAE has to be set up
+
+20:
+ ldq_u t1, 0(a1) # get quad surrounding word
+ subl a2, 1, a2 # decrement count
+ extwl t1, a1, t1 # extract appropriate word
+ addl a1, 2, a1 # increment buffer pointer
+ inswl t1, t3, t1 # get proper lane
+ stl t1, 0(t0) # store to buffer
+ addq t0, EISA_SHORT_OFFSET, t0 # increment I/O buffer
+ addl t3, 2, t3
+ and t3, 3, t3 # longwords only
+ bne a2, 20b # end while
+
+30:
+ ret zero, (ra)
+
+40:
+ //
+ // This must be non I/O space access
+ //
+ sll a2, 1, a2 # convert word count to byte count
+ br zero, RtlMoveMemory # Let Rtl routine handle move
+
+
+100:
+
+//
+// setup HAE
+//
+// a0 = QVA of destination
+// a1 = source va
+// a2 = word count
+// t0 = superpage bus address of destination
+// t3 = byte offset for destination (within a LONGWORD)
+// t4 = HAE index
+// t2 = upper bits of EISA superpage address
+//
+
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 150f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ bis a1, zero, t6 # save a1, since SWAP_IRQL destroys it
+ bis a2, zero, t7 # save a2, since SWAP_IRQL destroys it
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t8, (t1) # get original HAE value
+ bne t8, 150f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the words from the EISA bus
+ //
+ // t8 = original HAE value (debug only)
+ // a0 = original IRQL
+ //
+ // t0 = superpage bus address of source
+ // t1 = address of HAE register
+ // t6 = destination va
+ // t7 = word count
+ // t3 = byte offset for source (within a LONGWORD)
+ //
+
+120:
+ ldq_u v0, 0(t6) # get quad surrounding word
+ subl t7, 1, t7 # decrement count
+ extwl v0, t6, v0 # extract appropriate word
+ addl t6, 2, t6 # increment buffer pointer
+ inswl v0, t3, v0 # get proper lane
+ stl v0, 0(t0) # store to buffer
+ addq t0, EISA_SHORT_OFFSET, t0 # increment I/O buffer
+ addl t3, 2, t3
+ and t3, 3, t3 # longwords only
+ bne t7, 120b # end while
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL, original IRQL in a0
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+150:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end WRITE_REGISTER_BUFFER_USHORT
+
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Writes to the specified buffer address. This routine only works
+ with EISA memory space, since there are no REGISTER buffers in
+ COMBO space on Jensen.
+
+ Both the input buffer and output buffer should be longword aligned.
+
+Arguments:
+
+ a0 QVA of destination buffer in I/O space.
+ a1 VA of source buffer in memory.
+ a2 Number of longwords to move (Count).
+
+
+Return Value:
+
+ None
+
+--*/
+
+
+ beq a2, 30f # leave if nothing to do
+ srl a0, QVA_HAE_SHIFT, t2 # get control and HAE index bits
+ and t2, QVA_SELECTORS_SHIFTED, t1 # get QVA selector bits
+ xor t1, QVA_ENABLE_SHIFTED, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 40f # br if not a bus address
+
+ ldah t0, QVA_CONTROL(zero) # get mask clear bits
+ and t2, 3, t4 # get HAE index
+ bic a0, t0, t0 # clear QVA control bits a0<63:25>
+
+ ldiq t2, EISA_MEMORY # form upper bits of PA
+ sll t0, EISA_BIT_SHIFT, t0 # t0 contains PA<31:0>
+ sll t2, IO_HI_SHIFT, t2 # shift upper bits into position
+ or t0, t2, t0 # generate superpage address
+ or t0, EISA_LONG_LEN, t0 # or in the byte enables
+
+ //
+ // Note - at this point we know bits t0<63:25> = 0
+ //
+ // Check if we have to load the HAE with a non-zero value. This
+ // is considered non-standard, but it is supported. Loading the HAE
+ // requires additional synchronization.
+ //
+ bne t4, 100f # br if HAE has to be set up
+
+20:
+ ldl t1, 0(a1) # get longword
+ subl a2, 1, a2 # decrement count
+ addl a1, 4, a1 # increment buffer pointer
+ stl t1, 0(t0) # store to buffer
+ addq t0, EISA_LONG_OFFSET, t0 # increment I/O buffer
+ bne a2, 20b # end while
+
+30:
+ ret zero, (ra)
+
+40:
+ //
+ // This must be non I/O space access
+ //
+ s4addl a2, zero, a2 # convert longword count to byte count
+ br zero, RtlMoveMemory # Let Rtl routine handle move
+
+
+100:
+
+//
+// setup HAE
+//
+// a0 = QVA of destination
+// a1 = source va
+// a2 = longword count
+// t0 = superpage bus address of destination
+// t4 = HAE index
+// t2 = upper bits of EISA superpage address
+//
+
+ lda t1, HalpHaeTable # get address of HAE table
+ ldiq t2, COMBO_IO # form upper bits of HAE
+ addl t4, t1, t1 # get address of new HAE value
+ sll t2, IO_HI_SHIFT, t2 # shift bits PA<63:32> into position
+ ldq_u t4, (t1) # get new HAE value
+ extbl t4, t1, t4 # ...
+
+#if DBG
+ // Note: the value in t4 should never be zero!
+ beq t4, 150f # br if new HAE value is zero!
+#endif
+
+ ldiq t1, HAE_PHYSICAL_BASEL # get base address of HAE register
+ or t1, t2, t1 # generate HAE superpage address
+
+ bis a1, zero, t6 # save a1, since SWAP_IRQL destroys it
+ bis a2, zero, t7 # save a2, since SWAP_IRQL destroys it
+ //
+ // Raise IRQL to device level to block other accesses to EISA memory
+ //
+ ldiq a0, DEVICE_LEVEL # get device level IRQL
+ SWAP_IRQL # raise IRQL to DEVICE_LEVEL
+ bis v0, zero, a0 # save original IRQL
+
+ //
+ // We will not bother to save the original HAE value. The value
+ // in the HAE must be zero... otherwise synchronization is broken.
+ // In debug mode, we will check the HAE however.
+ //
+#if DBG
+ ldl t8, (t1) # get original HAE value
+ bne t8, 150f # br if HAE is non-zero - error!
+#endif
+
+ stl t4, (t1) # write new HAE value
+ mb # force it out
+
+ //
+ // Now we can read the words from the EISA bus
+ //
+ // t8 = original HAE value (debug only)
+ // a0 = original IRQL
+ //
+ // t0 = superpage bus address of source
+ // t1 = address of HAE register
+ // t6 = destination va
+ // t7 = word count
+ // t3 = byte offset for source (within a LONGWORD)
+ //
+
+120:
+ ldl v0, 0(t6) # get longword
+ subl t7, 1, t7 # decrement count
+ addl t6, 4, t6 # increment buffer pointer
+ stl v0, 0(t0) # store to buffer
+ addq t0, EISA_LONG_OFFSET, t0 # increment I/O buffer
+ bne t7, 120b # end while
+
+ //
+ // Restore HAE before exiting
+ //
+ stl zero, (t1) # restore original HAE value
+ mb # force it out
+
+ //
+ // Lower IRQL, original IRQL in a0
+ //
+ SWAP_IRQL # restore original IRQL
+
+ ret zero, (ra)
+
+#if DBG
+150:
+ // New HAE value is zero!
+ BREAK_DEBUG_STOP
+ ldil a0, BAD_QVA
+ jsr t12, KeBugCheck # crash if bad HAE index
+#endif
+
+
+ .end WRITE_REGISTER_BUFFER_ULONG
+
diff --git a/private/ntos/nthals/hal0jens/alpha/jxiouser.c b/private/ntos/nthals/hal0jens/alpha/jxiouser.c
new file mode 100644
index 000000000..8ab422c06
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxiouser.c
@@ -0,0 +1,971 @@
+#if defined (JENSEN)
+
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxioacc.c
+
+Abstract:
+
+ This module contains the Jensen I/O space access routines for user mode
+ mapped addresses.
+
+ The READ_PORT_Uxxx MACROs simply call the equivalent READ_REGISTER_Uxxx
+ routine. Similarly, the WRITE_PORT_Uxxx MACROs call the equivalent
+ WRITE_REGISTER_Uxxx routines. Since Jensen uses 64 bit super pages for
+ Virtual I/O, and that super pages are only accessable through kernel
+ mode, these routines here will decode a QVA and do the access, but
+ through normal translations.
+
+ All these routines ensure that the calling argument is a QVA, such
+ as would be returned by the wrapper around MmMapIoSpace - this should
+ have QVA_ENABLE set. They determine which type of shift should be
+ used, based on the next bit in the longword.
+
+ Note that the argument is declared as PUCHAR or PUSHORT or
+ whatever, even though it really is a QUASI_VIRTUAL_ADDRESS. This
+ is for driver compatibility: all the drivers out there get a
+ PVOID from MmMapIoSpace, then cast it to PU* before calling these
+ routines. If we insisted on declaring them correctly, we would
+ have to change all the drivers, which is what we are trying to avoid.
+
+ Lane shifting: the Jensen box will not do lane shifting in EISA
+ space. That means that for access shorter than a longword, the
+ data will NOT show up in the lowest bit position, but will be in
+ the byte/word that it would have started in. For longwords, the
+ value will show up on the data path correctly. For, say, the 3rd
+ byte in a word, a longword would be returned, and bytes 0, 1 and 3
+ would be garbage, and the value in byte 2 would be the one you
+ wanted. The same applies for writing: a longword will always be
+ sent out onto the bus, and we must move the valid data byte into
+ the correct position, and set the byte enables to say which byte
+ to use. Note that what you cannot do is leave the byte in the
+ lowest position, and set the byte enable to the lowest byte,
+ because this would generate an unaligned longword access, which
+ the chip cannot handle.
+
+ So, for bytes, the access must be an aligned longword, with byte
+ enables set to indicate which byte to get/set, and the byte moved
+ to/from the desired position within the longword. Similarly for
+ shorts. Tribytes are not supported.
+
+ Lane shifting is not an issue for accessing the Combo chip, which
+ only allows byte accesses, and for which the data is always moved
+ to the low 8 bits of the HBUS data longword, according to the spec.
+
+ Performance: If the buffer routines get used alot, something we
+ could do to improve performance would be to send four byte or two
+ shorts out to the bus at a time (or get them). This would work
+ because the PIC queries the device about the size of transfer that
+ it can accept (or the device rejects a transfer that it cannot
+ handle) and parcels the data out in correct size chunks.
+
+Author:
+
+ Rod N. Gamache (DEC) 5-May-1992
+ Miche Baker-Harvey (miche) 21-May-1992
+ Jeff McLeman (DEC) 30-Jul-1992
+
+Revision History:
+
+--*/
+// Include files
+
+#include "halp.h"
+#include "jnsndef.h"
+
+
+UCHAR
+READ_REGISTER_UCHAR(
+ volatile PUCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+
+Return Value:
+
+ Returns the value read from the specified register address.
+
+--*/
+
+{
+ ULONG mv; // Local value
+ ULONG byte; // which byte we want
+ volatile PULONG ma; // Local address
+
+ HalpMb;
+
+ //
+ // If it's an EISA address, use EISA shifts, byte enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+ //
+ // Determine which byte it is that we want.
+ //
+
+ byte = (ULONG)Register & 0x3;
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a byte.
+ //
+ // The desired byte enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual byte addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_BYTE_LEN | ((ULONG)Register << EISA_BIT_SHIFT));
+
+ //
+ // Get the longword value, which will only have one valid byte
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out and return the desired byte
+ // The compiler should convert the multiplication
+ //
+
+ return((UCHAR)(mv >> (byte * 8)));
+
+ }
+
+ //
+ // If it's a Combo Chip address, use those shifts, byte enables
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+ return ((UCHAR)(*(volatile PULONG )(COMBO_BYTE_LEN |
+ ((ULONG)Register << COMBO_BIT_SHIFT))));
+ }
+
+ //
+ // It's not a valid QVA
+ //
+
+ KeBugCheck("Invalid QVA in READ_REGISTER_UCHAR\n");
+}
+
+
+
+USHORT
+READ_REGISTER_USHORT(
+ volatile PUSHORT Register
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified Register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+
+Return Value:
+
+ Returns the value read from the specified register address.
+
+--*/
+
+{
+ ULONG mv, word; // Local value and word we want
+ volatile PULONG ma; // Local address
+
+ //
+ // This works as long as we don't want the fourth short!
+ //
+ ASSERT(((ULONG)Register & 0x3) != 0x3);
+
+ //
+ // If it's an EISA address, use EISA shifts, word enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+ //
+ // Determine which word it is that we want.
+ //
+
+ word = (ULONG)Register & 0x3;
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a word.
+ //
+ // The desired word enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual word addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_WORD_LEN | ((ULONG)Register << EISA_BIT_SHIFT));
+
+ //
+ // Get the longword value, which will only have one valid word
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out and return the desired word
+ // The compiler should convert the multiplication
+ //
+
+ return((USHORT)(mv >> (8 * word)));
+
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_REGISTER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_REGISTER_USHORT\n");
+}
+
+
+ULONG
+READ_REGISTER_ULONG(
+ volatile PULONG Register
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+
+Return Value:
+
+ Returns the value read from the specified register address.
+
+--*/
+
+{
+
+ //
+ // We are assuming that the longword is aligned
+ //
+ ASSERT(((ULONG)Register & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Register)) {
+
+ HalpMb;
+ return (*(volatile PULONG)(EISA_LONG_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)));
+
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_REGISTER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_REGISTER_ULONG\n");
+}
+
+
+VOID
+WRITE_REGISTER_UCHAR(
+ volatile PUCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+ Value - The value to be written to the register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG mv; // local copy of value for shifting
+ ULONG byte; // the byte position requested
+
+ //
+ // If it's an EISA address, use EISA shifts, byte enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+ //
+ // Determine which byte it is that we want.
+ //
+
+ byte = (ULONG)Register & 0x3;
+
+ //
+ // Move value into appropriate byte position in longword
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(Value << (8 * byte));
+
+ //
+ // The address is long aligned and the byte enables set
+ // automagically by the way the Jensen physical map is set
+ //
+ *(volatile PULONG)(EISA_BYTE_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)) = mv;
+ HalpMb;
+ return;
+ }
+
+ //
+ // If it's a Combo Chip address, use those shifts, byte enables
+ // No lane shifting is required for the Combo chip.
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ *(volatile PULONG)(COMBO_BYTE_LEN |
+ ((ULONG)Register << COMBO_BIT_SHIFT)) = Value;
+ HalpMb;
+ return;
+ }
+
+ //
+ // It's not a valid QVA
+ //
+
+ KeBugCheck("Invalid QVA in WRITE_REGISTER_UCHAR\n");
+}
+
+
+VOID
+WRITE_REGISTER_USHORT(
+ volatile PUSHORT Register,
+ USHORT Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+ Value - The value to be written to the register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG mv; // local copy of value for shifting
+ UCHAR word; // the word position requested
+
+ //
+ // This works as long as we don't want the fourth short!
+ //
+ ASSERT(((ULONG)Register & 0x3) != 0x3);
+
+ //
+ // If it's an EISA address, use EISA shifts, word enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+
+ //
+ // Determine which word it is that we want.
+ //
+
+ word = (ULONG)Register & 0x3;
+
+ //
+ // Move value into appropriate word position in longword
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(Value << (8 * word));
+
+ //
+ // The address is long aligned and the word enables set
+ // automagically by the way the Jensen physical map is set
+ //
+
+ *(volatile PULONG)(EISA_WORD_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)) = mv;
+ HalpMb;
+ return;
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_REGISTER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_REGISTER_USHORT\n");
+}
+
+
+VOID
+WRITE_REGISTER_ULONG(
+ volatile PULONG Register,
+ ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+ Value - The value to be written to the register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // We are assuming that the longword is aligned
+ //
+ ASSERT(((ULONG)Register & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Register)) {
+
+ *(volatile PULONG)(EISA_LONG_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)) = Value;
+ HalpMb;
+ return;
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_REGISTER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_REGISTER_ULONG\n");
+}
+
+
+
+VOID
+READ_PORT_BUFFER_UCHAR(
+ volatile PUCHAR Port,
+ PUCHAR Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data to.
+ Count - the number of bytes to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG byte;
+
+ HalpMb;
+ if (IS_EISA_QVA(Port)) {
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a byte.
+ //
+ // The desired byte enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual byte addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_BYTE_LEN | ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which byte it is that we want.
+ //
+
+ byte = (ULONG)ma & (0x3 << EISA_BIT_SHIFT);
+
+ //
+ // Get the longword value, which will only have one valid byte
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out the desired byte
+ // The compiler should convert the multiplication
+ //
+
+ *Buffer++ = ((UCHAR)(mv >> (8 * byte)));
+
+
+ }
+
+ } else if (IS_COMBO_QVA(Port)) {
+
+ ma = (volatile PULONG) (COMBO_BYTE_LEN |
+ ((ULONG)Port << COMBO_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *Buffer++ = *ma;
+ ma = (PULONG)((PUCHAR)ma + COMBO_BYTE_OFFSET);
+ }
+
+ } else {
+
+ //
+ // Invalid QVA
+ //
+ KeBugCheck("Invalid QVA in READ_PORT_BUFFER_UCHAR\n");
+ }
+}
+
+
+VOID
+READ_PORT_BUFFER_USHORT(
+ volatile PUSHORT Port,
+ PUSHORT Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data to.
+ Count - the number of shorts to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG word;
+
+ //
+ // The code gets really ugly if shorts are not aligned!
+ //
+ ASSERT(((ULONG)Port & 0x1) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+
+ HalpMb;
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a word.
+ //
+ // The desired word enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual word addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_WORD_LEN | ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which word it is that we want; the low
+ // order bit cannot be set.
+ //
+
+ word = (ULONG)ma & (0x2 << EISA_BIT_SHIFT);
+
+ //
+ // Get the longword value, which will only have one valid word
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out the desired word
+ // The compiler should convert the multiplication
+ //
+
+ *Buffer++ = ((USHORT)(mv >> (8 * word)));
+
+
+ }
+ return;
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_PORT_BUFFER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_PORT_BUFFER_USHORT\n");
+
+}
+
+
+VOID
+READ_PORT_BUFFER_ULONG(
+ volatile PULONG Port,
+ PULONG Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified port address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data to.
+ Count - the number of longs to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i;
+ volatile PULONG ptr;
+
+ //
+ // We are assuming that the longword is aligned
+ //
+ ASSERT(((ULONG)Port & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+ HalpMb;
+ ptr = (volatile ULONG *) (EISA_LONG_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *Buffer++ = *ptr;
+ }
+ return;
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_PORT_BUFFER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_PORT_BUFFER_ULONG\n");
+
+}
+
+
+VOID
+WRITE_PORT_BUFFER_UCHAR(
+ volatile PUCHAR Port,
+ PUCHAR Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified port buffer address.
+
+ If the Port and Buffer addresses are aligned with respect to each
+ other, we don't have to do a shift on each move - which would be a
+ bit faster. On the other hand, no one calls this routine, and it
+ would be more complicated to handle the two cases, so let it be.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data from.
+ Count - the number of bytes to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG byte;
+
+
+ if (IS_EISA_QVA(Port)) {
+
+ ma = (volatile PULONG) (EISA_BYTE_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which byte it is that we want to write to
+ // This changes with every byte written.
+ //
+
+ byte = (ULONG)ma & (0x3 << EISA_BIT_SHIFT);
+
+ //
+ // Move value into appropriate byte position in longword,
+ // and advance our position in the buffer.
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(*Buffer << (8 * byte));
+ Buffer++;
+
+ //
+ // send the lane shifted value to the EISA bus
+ //
+
+ *ma = mv;
+
+ }
+
+ HalpMb;
+ return;
+ }
+
+ if (IS_COMBO_QVA(Port)) {
+
+ ma = (volatile PULONG) (COMBO_BYTE_LEN |
+ ((ULONG)Port << COMBO_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *ma = *Buffer++;
+ ma = (PULONG)((PUCHAR)ma + COMBO_BYTE_OFFSET);
+ }
+ HalpMb;
+ return;
+
+ }
+
+ //
+ // Invalid QVA
+ //
+ KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_UCHAR\n");
+
+}
+
+
+VOID
+WRITE_PORT_BUFFER_USHORT(
+ volatile PUSHORT Port,
+ PUSHORT Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data from.
+ Count - the number of shorts to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG word;
+
+ //
+ // The code gets really ugly if shorts are not aligned!
+ //
+ ASSERT(((ULONG)Port & 0x1) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+
+ ma = (volatile PULONG) (EISA_WORD_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which word it is that we want to write to
+ // This changes with every word written.
+ //
+
+ word = (ULONG)ma & (0x2 << EISA_BIT_SHIFT);
+
+ //
+ // Move value into appropriate word position in longword,
+ // and advance our position in the buffer.
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(*Buffer++ << (8 * word));
+
+ //
+ // send the lane shifted value to the EISA bus
+ //
+
+ *ma = mv;
+
+ }
+
+ HalpMb;
+ return;
+
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_PORT_BUFFER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_USHORT\n");
+
+}
+
+
+VOID
+WRITE_PORT_BUFFER_ULONG(
+ volatile PULONG Port,
+ PULONG Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Write to teh specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data from.
+ Count - the number of longs to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i;
+ volatile PULONG ptr;
+
+ //
+ // We are assuming that the port address is long aligned
+ //
+ ASSERT(((ULONG)Port & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+ ptr = (volatile ULONG *) (EISA_LONG_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *ptr = *Buffer++;
+ }
+ HalpMb;
+ return;
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_PORT_BUFFER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_ULONG\n");
+
+}
+#endif // JENSEN
diff --git a/private/ntos/nthals/hal0jens/alpha/jxirql.h b/private/ntos/nthals/hal0jens/alpha/jxirql.h
new file mode 100644
index 000000000..c40492d11
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxirql.h
@@ -0,0 +1,133 @@
+//++
+//
+// Module Name:
+//
+// jxirql.h
+//
+// Description:
+//
+// The platform-specific interrupt tables, defined by the HAL
+// and used by the PAL to define interrupt synchronization
+// and prioritization.
+//
+// Author:
+//
+// Joe Notarangelo, generated via VB program IRQL
+//
+// Environment
+//
+// HAL private data structures
+//
+// Revision History:
+//
+// Joe Notarangelo 8-Jul-1993
+// Edited this file by hand to:
+// a. Create appropriate mask values for the performance counter
+// interrupts
+// b. Disable keyboard and serial interrupts by default, they
+// will now be enabled/disabled by the standard HAL interfaces
+//
+//--
+
+//
+// Interrupt Enable Table
+//
+//
+// III III
+// RRR RRRC PPDA
+// QQQ QQQR CCPP
+// 543 210D 10CC
+//
+
+ULONG HalpIET[] = {
+ 0x2f3 , // irql 0
+ 0x2f2 , // irql 1
+ 0x2f0 , // irql 2
+ 0x2b0 , // irql 3
+ 0x2b0 , // irql 4
+ 0x290 , // irql 5
+ 0x280 , // irql 6
+ 0x000 // irql 7
+};
+
+//
+// Interrupt Synchronization and Vector Table
+//
+
+struct _IRQLMASK HalpIrqlMask[] = {
+ // sfw interrupt table
+ { 0 , 0 }, // 00
+ { 1 , 1 }, // 01
+ { 2 , 2 }, // 10
+ { 2 , 2 }, // 11
+ // performance counter interrupts
+ { 0 , 0 }, // 00
+ { 6 , 6 }, // 01
+ { 6 , 8 }, // 10
+ { 6 , 8 }, // 11
+ // high priority hardware interrupts
+ { 0 , 0 }, // 000000
+ { 5 , 5 }, // 000001
+ { 3 , 10 }, // 000010
+ { 5 , 5 }, // 000011
+ { 7 , 7 }, // 000100
+ { 7 , 7 }, // 000101
+ { 7 , 7 }, // 000110
+ { 7 , 7 }, // 000111
+ { 3 , 11 }, // 001000
+ { 5 , 5 }, // 001001
+ { 3 , 11 }, // 001010
+ { 5 , 5 }, // 001011
+ { 7 , 7 }, // 001100
+ { 7 , 7 }, // 001101
+ { 7 , 7 }, // 001110
+ { 7 , 7 }, // 001111
+ { 7 , 14 }, // 010000
+ { 7 , 14 }, // 010001
+ { 7 , 14 }, // 010010
+ { 7 , 14 }, // 010011
+ { 7 , 14 }, // 010100
+ { 7 , 14 }, // 010101
+ { 7 , 14 }, // 010110
+ { 7 , 14 }, // 010111
+ { 7 , 14 }, // 011000
+ { 7 , 14 }, // 011001
+ { 7 , 14 }, // 011010
+ { 7 , 14 }, // 011011
+ { 7 , 14 }, // 011100
+ { 7 , 14 }, // 011101
+ { 7 , 14 }, // 011110
+ { 7 , 14 }, // 011111
+ { 4 , 4 }, // 100000
+ { 5 , 5 }, // 100001
+ { 4 , 4 }, // 100010
+ { 5 , 5 }, // 100011
+ { 7 , 7 }, // 100100
+ { 7 , 7 }, // 100101
+ { 7 , 7 }, // 100110
+ { 7 , 7 }, // 100111
+ { 4 , 4 }, // 101000
+ { 5 , 5 }, // 101001
+ { 4 , 4 }, // 101010
+ { 5 , 5 }, // 101011
+ { 7 , 7 }, // 101100
+ { 7 , 7 }, // 101101
+ { 7 , 7 }, // 101110
+ { 7 , 7 }, // 101111
+ { 7 , 14 }, // 110000
+ { 7 , 14 }, // 110001
+ { 7 , 14 }, // 110010
+ { 7 , 14 }, // 110011
+ { 7 , 14 }, // 110100
+ { 7 , 14 }, // 110101
+ { 7 , 14 }, // 110110
+ { 7 , 14 }, // 110111
+ { 7 , 14 }, // 111000
+ { 7 , 14 }, // 111001
+ { 7 , 14 }, // 111010
+ { 7 , 14 }, // 111011
+ { 7 , 14 }, // 111100
+ { 7 , 14 }, // 111101
+ { 7 , 14 }, // 111110
+ { 7 , 14 }, // 111111
+};
diff --git a/private/ntos/nthals/hal0jens/alpha/jxisa.h b/private/ntos/nthals/hal0jens/alpha/jxisa.h
new file mode 100644
index 000000000..a59dede50
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxisa.h
@@ -0,0 +1,95 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxisa.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ EISA/ISA specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+ Jeff McLeman (mcleman) 01-Jun-1992
+
+Revision History:
+
+ 17-Jul-1992 Jeff McLeman (mcleman)
+ Remove adapter object structure from here.
+
+ 01-Jun-1992 Jeff McLeman
+ modify for Jensen EISA/ISA
+
+--*/
+
+#ifndef _JXISA_
+#define _JXISA_
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x20000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_ISA_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the EISA_ADAPTER flag for the Map Register Base.
+//
+
+#define EISA_ADAPTER 0x00000002
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+#define HOLE_BUFFER 0XFFFFFFFE
+#define SKIP_BUFFER 0XFFFFFFFD
+
+
+#endif // _JXISA_
diff --git a/private/ntos/nthals/hal0jens/alpha/jxmapio.c b/private/ntos/nthals/hal0jens/alpha/jxmapio.c
new file mode 100644
index 000000000..647fff414
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxmapio.c
@@ -0,0 +1,86 @@
+#if defined (JENSEN)
+
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This maps I/O addresses used by the HAL on Alpha/Jensen.
+
+Author:
+
+ Jeff McLeman (mcleman) 24-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 12-Jul-1992 Jeff McLeman (mcleman)
+ Remove RTC mapping since this is done with VTI access routines.
+
+--*/
+
+#include "halp.h"
+#include "jnsndef.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for an Alpha/Jensen
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map EISA control space.
+ //
+
+
+
+ HalpEisaControlBase = (PVOID)DMA_VIRTUAL_BASE;
+
+
+ //
+ // If mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if (HalpEisaControlBase == NULL) {
+ return FALSE;
+
+ } else {
+ return TRUE;
+ }
+}
+
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/jxmchk.c b/private/ntos/nthals/hal0jens/alpha/jxmchk.c
new file mode 100644
index 000000000..b13655791
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxmchk.c
@@ -0,0 +1,338 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ .../ntos/hal/alpha/jxinitnt.c
+
+Abstract:
+
+
+ This module implements machine check handling for JENSEN.
+
+Author:
+
+ Joe Notarangelo 11-Feb-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+VOID
+HalpDisplayLogout21064( PLOGOUT_FRAME_21064 LogoutFrame );
+
+
+BOOLEAN
+HalMachineCheck (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This function fields machine checks for JENSEN.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record for the
+ machine check. Included in the exception information
+ is the pointer to the logout frame.
+
+ ExceptionFrame - Supplies a pointer to the kernel exception frame.
+
+ TrapFrame - Supplies a pointer to the kernel trap frame.
+
+Return Value:
+
+ A value of TRUE is returned if the machine check has been
+ handled by the HAL. If it has been handled then execution may
+ resume at the faulting address. Otherwise, a value of FALSE
+ is returned.
+
+ N.B. - under some circumstances this routine may not return at
+ all.
+
+--*/
+
+{
+
+ PMCHK_STATUS MachineCheckStatus;
+
+ //
+ // JENSEN is a parity machine. If we receive a machine check it
+ // is uncorrectable. We will print the logout frame and then we
+ // will bugcheck.
+ //
+ // However, we will first check that the machine check is not
+ // marked as correctable. If the machine check is correctable it uses
+ // a differently formatted logout frame. We will ignore the frame
+ // for any machine check marked as correctable since it is an impossible
+ // condition on JENSEN.
+ //
+
+ MachineCheckStatus =
+ (PMCHK_STATUS)&ExceptionRecord->ExceptionInformation[0];
+
+ if( MachineCheckStatus->Correctable == 0 ){
+
+ HalpDisplayLogout21064(
+ (PLOGOUT_FRAME_21064)(ExceptionRecord->ExceptionInformation[1])
+ );
+
+ }
+
+ //
+ // Bugcheck to dump the rest of the machine state, this will help
+ // if the machine check is software-related.
+ //
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ (ULONG)MachineCheckStatus->Correctable,
+ (ULONG)MachineCheckStatus->Retryable,
+ 0,
+ 0 );
+
+}
+
+
+#define MAX_ERROR_STRING 100
+
+VOID
+HalpDisplayLogout21064 (
+ IN PLOGOUT_FRAME_21064 LogoutFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This function displays the logout frame for a 21064.
+
+Arguments:
+
+ LogoutFrame - Supplies a pointer to the logout frame generated
+ by the 21064.
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+
+ //
+ // Acquire ownership of the display. This is done here in case we take
+ // a machine check before the display has been taken away from the HAL.
+ // When the HAL begins displaying strings after it has lost the
+ // display ownership then the HAL will be careful not to scroll information
+ // off of the screen. This is a JENSEN feature.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the machine state via the logout frame.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+
+ sprintf( OutBuffer, "BIU_STAT : %016Lx BIU_ADDR: %016Lx\n",
+ BIUSTAT_ALL_21064( LogoutFrame->BiuStat ),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "FILL_ADDR: %016Lx FILL_SYN: %016Lx\n",
+ LogoutFrame->FillAddr.QuadPart,
+ FILLSYNDROME_ALL_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "DC_STAT : %016Lx BC_TAG : %016Lx\n",
+ DCSTAT_ALL_21064(LogoutFrame->DcStat),
+ BCTAG_ALL_21064(LogoutFrame->BcTag) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "ICCSR : %016Lx ABOX_CTL: %016Lx EXC_SUM: %016Lx\n",
+ ICCSR_ALL_21064(LogoutFrame->Iccsr),
+ ABOXCTL_ALL_21064(LogoutFrame->AboxCtl),
+ EXCSUM_ALL_21064(LogoutFrame->ExcSum) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "EXC_ADDR : %016Lx VA : %016Lx MM_CSR : %016Lx\n",
+ LogoutFrame->ExcAddr.QuadPart,
+ LogoutFrame->Va.QuadPart,
+ MMCSR_ALL_21064(LogoutFrame->MmCsr) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "HIRR : %016Lx HIER : %016Lx PS : %016Lx\n",
+ IRR_ALL_21064(LogoutFrame->Hirr),
+ IER_ALL_21064(LogoutFrame->Hier),
+ PS_ALL_21064(LogoutFrame->Ps) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "PAL_BASE : %016Lx \n",
+ LogoutFrame->PalBase.QuadPart );
+ HalDisplayString( OutBuffer );
+
+ //
+ // Print out interpretation of the error.
+ //
+
+
+ HalDisplayString( "\n" );
+
+ //
+ // Check for tag control parity error.
+ //
+
+ if( BIUSTAT_TCPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer,
+ "Tag control parity error, Tag control: P: %1x D: %1x S: %1x V: %1x\n",
+ BCTAG_TAGCTLP_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLD_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLS_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLV_21064( LogoutFrame->BcTag ) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for tag parity error.
+ //
+
+ if( BIUSTAT_TPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer,
+ "Tag parity error, Tag: 0b%17b Parity: %1x\n",
+ BCTAG_TAG_21064(LogoutFrame->BcTag),
+ BCTAG_TAGP_21064(LogoutFrame->BcTag) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for hard error.
+ //
+
+ if( BIUSTAT_HERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Hard error acknowledge: BIU CMD: %x PA: %16Lx\n",
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for soft error.
+ //
+
+ if( BIUSTAT_SERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Soft error acknowledge: BIU CMD: %x PA: %16Lx\n",
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+
+ //
+ // Check for fill ECC errors.
+ //
+
+ if( BIUSTAT_FILLECC_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "ECC error: %s\n",
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\n",
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for fill Parity errors.
+ //
+
+ if( BIUSTAT_FILLDPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Parity error: %s\n",
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\n",
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for multiple hard errors.
+ //
+
+ if( BIUSTAT_FATAL1_21064(LogoutFrame->BiuStat) == 1 ){
+
+ HalDisplayString( "Multiple external/tag errors detected.\n" );
+
+ }
+
+ //
+ // Check for multiple fill errors.
+ //
+
+ if( BIUSTAT_FATAL2_21064(LogoutFrame->BiuStat) == 1 ){
+
+ HalDisplayString( "Multiple fill errors detected.\n" );
+
+ }
+
+
+ //
+ // return to caller
+ //
+
+ return;
+}
+
+#endif //JENSEN
diff --git a/private/ntos/nthals/hal0jens/alpha/jxport.c b/private/ntos/nthals/hal0jens/alpha/jxport.c
new file mode 100644
index 000000000..df9fcf4ad
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxport.c
@@ -0,0 +1,604 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a Jensen system and the host system.
+
+ Stolen from ../mips/jxport.c
+
+Author:
+
+ Miche Baker-Harvey (miche) 01-June-1992
+ Jeff McLeman [DEC] 02-Feb-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Joe Notarangelo 21-Jun-1992
+ update to use super-page access to serial port so we aren't depend
+ on translation code, this will allow us to debug the translation
+ code, use serial line 2
+
+
+--*/
+
+
+#include "halp.h"
+#include "jxserp.h"
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+//
+// Define serial port read and write addresses.
+//
+PSP_READ_REGISTERS SP_READ;
+PSP_WRITE_REGISTERS SP_WRITE;
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 0;
+
+
+ULONG
+HalpGetByte (
+ IN PUCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input data
+ byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+ CP_GET_ERROR is returned if error encountered during reading.
+ CP_GET_NODATA is returned if timeout.
+
+--*/
+{
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = inVti(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = inVti(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+ ULONG Remainder;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud rate divisor to
+ // six, which is 19.2Kbps on Jensen. Otherwise, set the baud rate divisor
+ // to the correct value for 19.2 baud communication.
+ //
+
+ BaudClock = 1843200;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpBaudRateDivisor = (UCHAR)(BaudClock / (BaudRate*16));
+
+ //
+ // round up
+ //
+ Remainder = BaudClock % (BaudRate*16);
+ if ((Remainder*2) > BaudClock) {
+ HalpBaudRateDivisor++;
+ }
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ //
+ // Establish pointers to serial line register structures
+ // Note: the natural port number addresses are used
+ //
+
+ if ( DebugParameters->CommunicationPort == 1 ) {
+ SP_READ = ((PSP_READ_REGISTERS)(COMA_PORT_BASE));
+ SP_WRITE = ((PSP_WRITE_REGISTERS)(COMA_PORT_BASE));
+ KdComPortInUse = (PUCHAR)0x3f8;
+ } else {
+ SP_READ = ((PSP_READ_REGISTERS)(COMB_PORT_BASE));
+ SP_WRITE = ((PSP_WRITE_REGISTERS)(COMB_PORT_BASE));
+ KdComPortInUse = (PUCHAR)0x2f8;
+ }
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ outVti( &SP_WRITE->LineControl, 0x0 );
+ outVti( &SP_WRITE->InterruptEnable, 0x0 );
+
+
+ // We shouldn't have to do anything with the FIFO here -
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ // Note: the references to TransmitBuffer and InterruptEnable are
+ // actually the Divisor Latch LSB and MSB registers respectively
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ outVti(&SP_WRITE->LineControl, DataByte);
+ outVti(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ outVti(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ outVti(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ outVti(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = inVti(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = inVti(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ outVti(&SP_WRITE->TransmitBuffer, Output);
+ return;
+
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a receive or a transmit.
+ //
+
+ DataLsr = inVti(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = inVti(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+#endif // JENSEN
diff --git a/private/ntos/nthals/hal0jens/alpha/jxprof.h b/private/ntos/nthals/hal0jens/alpha/jxprof.h
new file mode 100644
index 000000000..73869b657
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxprof.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxprof.h
+
+Abstract:
+
+ This header file defines profile counter hardware in the
+ 82357 PIC chip used on the Alpha/Jensen Platform.
+
+Author:
+
+ Jeff McLeman (mcleman) 5-June-1992
+
+Revision History:
+
+--*/
+
+#ifndef _JXPROF_
+#define _JXPROF_
+
+
+//
+// Define the timer values for the Profiler
+//
+
+#define PIC_BINARY 0
+#define PIC_BCD 1
+
+#define PIC_MODE0 0x00 // xxxx000x
+#define PIC_MODE1 0x02 // xxxx001x
+#define PIC_MODE2 0x04 // xxxx010x
+#define PIC_MODE3 0x06 // xxxx011x
+#define PIC_MODE4 0x08 // xxxx100x
+#define PIC_MODE5 0x0A // xxxx101x
+
+#define PIC_CLC 0x00 // xx00xxxx
+#define PIC_RWLSBO 0x10 // xx01xxxx
+#define PIC_RWMSBO 0x20 // xx10xxxx
+#define PIC_RWLSBMSB 0x30 // xx11xxxx
+
+#define PIC_SC0 0x00 // 00xxxxxx
+#define PIC_SC1 0x40 // 01xxxxxx
+#define PIC_SC2 0x80 // 10xxxxxx
+#define PIC_RBC 0xC0 // 11xxxxxx
+
+
+#define PIC_SCALE_FACTOR 10 * 1000 // # of microsecond units times 10.
+
+//
+// Define a macro to set and enable the system profiler timer.
+// Note that the interval 'c' is in 100nS units.
+// Note that also the interval is incremented AFTER it is scaled.
+// This is due to the fact that the timer counts down to 1 in mode 2
+//
+
+#define PIC_PROFILER_ON(c)\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->CommandMode1,\
+ (ULONG)(PIC_BINARY | PIC_MODE2 | PIC_RWLSBMSB | PIC_SC0));\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Timer1,\
+ (ULONG)((c) & 0xff) );\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Timer1,\
+ (ULONG)(((c)>> 8) & 0xff) )
+
+//
+// Define a macro to shut down the profiler
+//
+
+#define PIC_PROFILER_OFF()\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->CommandMode1,\
+ (ULONG)(PIC_BINARY | PIC_MODE4 | PIC_RWLSBMSB | PIC_SC0))
+
+
+#endif // _JXPROF_
diff --git a/private/ntos/nthals/hal0jens/alpha/jxprom.c b/private/ntos/nthals/hal0jens/alpha/jxprom.c
new file mode 100644
index 000000000..bd3eaa4d9
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxprom.c
@@ -0,0 +1,1098 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxprom.c
+
+Abstract:
+
+ This module provides support for different kinds of ROMs/PROMs/Flash
+ ROMs in Alpha AXP machines.
+
+ This file, and rom.c, make no attempt at universal ROM-support.
+
+ Current support set:
+
+ Intel: 28F008SA 1 megabyte Flash Memory
+
+ AMD: Am29F010 128KB Sector Erase Flash Memory
+
+
+Author:
+
+ John DeRosa 4-May-1993
+
+Revision History:
+
+ Jeff McLeman 13-May-1993
+ Adapted for HAL use from Firmware module.
+
+--*/
+
+#include "halp.h"
+#include "jxenv.h"
+#include "jxprom.h"
+#include "arccodes.h"
+
+//
+// Function prototypes
+//
+
+ARC_STATUS
+HalpErase28F008SA(
+ IN PUCHAR EraseAddress
+ );
+
+
+ARC_STATUS
+HalpByteWrite28F008SA(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ );
+
+ARC_STATUS
+HalpEraseAM29F010 (
+ IN PUCHAR EraseAddress
+ );
+
+ARC_STATUS
+HalpByteWriteAM29F010 (
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ );
+
+//
+// ROM identification and control valueds.
+//
+// These are based on:
+//
+// Am29F010: AMD publication #16736, Rev. C, Amendment/0, September 1992.
+// 28F008SA: Intel order number 290429-003, September 1992.
+//
+// Table notes:
+//
+// Addresses for the ID command and response sequences are absolute,
+// since this code assumes homogeneous ROM arrays. The code will only
+// test the chip at the lowest Jensen ROM address.
+//
+// Offsets for the Reset and Set Read-mode commands are relative to the
+// base address of the individual ROM chip.
+//
+// Addresses passed to the erase-block function are within the block
+// to be erased.
+//
+// Addresses passed to the write-byte function are the address of the byte
+// to be written.
+//
+// The chip block size must be less than or equal to 64KB.
+//
+// N.B. The function that determines the ROM type will test each entry
+// in RomValues, starting at the beginning. This involves issuing write
+// commands to the ROM chip. So care must be taken that the ID command
+// write sequence for ROM type "n" will not have a deliterious effect on
+// other ROM types which may be in the machine, but are not identified until
+// RomValues entry "n + x".
+//
+//
+
+ROM_VALUES RomValues[InvalidROM] = {
+
+ { 16, // Standard stall amount
+ 1, // ID command length
+ 2, // ID response length
+ 1, // Reset command length
+ 1, // Read command length
+ I28F008SA, // ROM being described
+ 0x100000, // 1MB per chip
+ 0x10000, // 64KB per block
+ { {(PUCHAR)PROM_VIRTUAL_BASE, 0x90} }, // ID command sequence
+ { {(PUCHAR)PROM_VIRTUAL_BASE, 0x89}, // ID response sequence
+ {(PUCHAR)PROM_VIRTUAL_BASE+1, 0xa2} },
+ { {0, 0x50} }, // Reset command sequence
+ { {0, 0xff} }, // Read command sequence
+ HalpErase28F008SA, // Sector erase function
+ HalpByteWrite28F008SA // Byte write function
+ },
+
+ { 14, // Standard stall amount
+ 3, // ID command length
+ 2, // ID response length
+ 3, // Reset command length
+ 3, // Read command length
+ Am29F010, // ROM being described
+ 0x20000, // 128KB per chip
+ 0x4000, // 16KB per block
+ { {(PUCHAR)PROM_VIRTUAL_BASE+0x5555, 0xaa},
+ {(PUCHAR)PROM_VIRTUAL_BASE+0x2aaa, 0x55},
+ {(PUCHAR)PROM_VIRTUAL_BASE+0x5555, 0x90} }, // ID command sequence
+ { {(PUCHAR)PROM_VIRTUAL_BASE, 1}, // ID response sequence
+ {(PUCHAR)PROM_VIRTUAL_BASE+1, 0x20} },
+ { {0x5555, 0xaa},
+ {0x2aaa, 0x55},
+ {0x5555, 0xf0} }, // Reset command sequence
+ { {0x5555, 0xaa},
+ {0x2aaa, 0x55},
+ {0x5555, 0xf0} }, // Read command sequence
+ HalpEraseAM29F010, // Sector erase function
+ HalpByteWriteAM29F010 // Byte write function
+ }
+};
+
+
+//
+// Miscellaneous notes.
+//
+// A call must first be made to HalpROMDetermineMachineROMType. If this
+// returns ESUCCESS, then it has loaded the ROM type into the global variable
+// MachineROMType.
+//
+// After MachineROMType has been loaded, these functions may be called
+// to manipulate the system ROM:
+//
+// HalpROMByteWrite
+// HalpROMErase64KB
+// HalpROMEraseBlock
+// HalpROMResetStatus
+// HalpROMSetARCDataToReadMode
+// HalpROMSetReadMode
+//
+// HalpROMErase64KB and HalpROMSetARCDataToReadMode work on a "virtual"
+// 64KB ROM block, for compatibility with the first version of Jensen
+// hardware.
+//
+//
+// The type of ROM in this machine.
+//
+
+ROM_TYPE MachineROMType = 0;
+
+
+ARC_STATUS
+Check28F008SAStatusAndClear (
+ IN ULONG WhichToCheck
+ )
+/*++
+
+Routine Description:
+
+ This checks the status of an Intel 28F008SA 1MB Flash ROM. The
+ base address of the Jensen space, PROM_VIRTUAL_BASE, is used since
+ we know there is only one of these chips in the machine.
+
+ Hack: The hardwired values here should be changed to come out of
+ the RomValues array.
+
+Arguments:
+
+ WhichToCheck = 0 if a block-erase status check is desired.
+ = 1 if a byte-write status check is desired.
+
+ROM state on exit:
+
+ The status register is cleared.
+
+Return Value:
+
+ Returns ESUCCESS if the status is OK.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ UCHAR FooBar;
+
+ //
+ // Check the full status when the PROM's write state machine is ready.
+ //
+
+ while (((FooBar = READ_PORT_UCHAR((PUCHAR)PROM_VIRTUAL_BASE)) &
+ 0x80) == 0 ) {
+ KeStallExecutionProcessor(10);
+ }
+
+ KeStallExecutionProcessor(10);
+ HalpROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+
+ switch (WhichToCheck) {
+
+ //
+ // block-erase status check
+ //
+
+ case 0:
+
+ if ( ((FooBar & 0x28) != 0) || ((FooBar & 0x30) == 0x30) ) {
+ // Error in erase
+ return EIO;
+ } else {
+ // Erase was successful
+ return ESUCCESS;
+ }
+
+ //
+ // byte-write status check
+ //
+
+ case 1:
+
+ if (FooBar & 0x18) {
+ // Error in write
+ return EIO;
+ } else {
+ // Write was successful
+ return ESUCCESS;
+ }
+
+
+ //
+ // We should never get here.
+ //
+
+ default:
+ return EIO;
+ }
+}
+
+
+ARC_STATUS
+HalpErase28F008SA(
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a block in an Intel 28F008SA 1MB Flash ROM. The
+ base address of the Jensen space, PROM_VIRTUAL_BASE, is used since
+ we know there is only one of these chips in the machine.
+
+ Hack: The hardwired values here should be changed to come out of
+ the RomValues array.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ The status register is left in a cleared (reset) state.
+ The ROM is left in read-array mode.
+
+Return Value:
+
+ Returns ESUCCESS if the erase was successful.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ ULONG FooBar;
+ KIRQL OldIrql;
+
+ for (FooBar = 0; FooBar <= 10; FooBar++) {
+
+ HalpROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ WRITE_PORT_UCHAR (EraseAddress, 0x20);
+ HalpMb();
+ WRITE_PORT_UCHAR (EraseAddress, 0xd0);
+ HalpMb();
+
+ KeLowerIrql(OldIrql);
+
+ // Stall 1 seconds
+ HalpPromDelay(3000);
+
+ if (Check28F008SAStatusAndClear(0) == ESUCCESS) {
+ HalpROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ return ESUCCESS;
+ }
+
+ // In case the device is busy, give it some time to settle.
+ HalpPromDelay(6000);
+ }
+
+
+ //
+ // If we get here, we have tried unsuccessfully 10 times to erase
+ // this block. Return an error.
+ //
+
+ HalpROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ return EIO;
+}
+
+
+ARC_STATUS
+HalpByteWrite28F008SA(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ )
+
+/*++
+
+Routine Description:
+
+ This writes a byte in the Alpha/Jensen 1MB PROM. It retries up to
+ 20 times if the write status register indicates failure, or a read
+ of the location indicates that the write was partially done
+ by the device.
+
+ Hack: The hardwired values here should be changed to come out of
+ the RomValues array.
+
+Arguments:
+
+ WriteAddress = meta-virtual address of the byte to be written.
+ WriteData = byte to be written.
+
+ROM state on exit:
+
+ The byte is written, and the WSM status register is modified.
+
+Return Value:
+
+ ESUCCESS if the write was successful.
+ Otherwise, EIO.
+
+--*/
+
+{
+ ULONG Index;
+ UCHAR WSMStatus;
+ KIRQL OldIrql;
+
+ HalpROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+
+ for (Index = 0; Index < 20; Index++) {
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ WRITE_PORT_UCHAR (WriteAddress, 0x40);
+ HalpMb();
+ WRITE_PORT_UCHAR (WriteAddress, WriteData);
+ HalpMb();
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // The device should need only 14 microseconds.
+ //
+
+ KeStallExecutionProcessor(14);
+
+ if (Check28F008SAStatusAndClear(1) != ESUCCESS) {
+
+ //
+ // The write failed. Ensure status is clear and see if we
+ // can retry.
+ //
+
+ HalpROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+ HalpROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ DbgPrint("? Write failed to address %x. Wrote %x, ",
+ WriteAddress, WriteData);
+ DbgPrint("verify returns %x.\r\n",
+ READ_PORT_UCHAR((PUCHAR)WriteAddress));
+
+ if (READ_PORT_UCHAR(WriteAddress) != 0xff) {
+ DbgPrint("RETRY ABORTED!\r\n");
+ return EIO;
+ } else {
+ DbgPrint("Retrying..\r\n");
+ }
+
+ } else {
+
+ //
+ // The write succeeded.
+ //
+
+ return ESUCCESS;
+ }
+
+ }
+
+
+ //
+ // We failed to write the byte after 20 tries.
+ //
+
+ return EIO;
+
+}
+
+
+ARC_STATUS
+CheckAM29F010Status (
+ IN BOOLEAN SectorErase,
+ IN PUCHAR Address,
+ IN UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This checks the status of an AMD 29F010 128KB ROM chip after a
+ byte write or sector erase command has been issued. Data Polling
+ is used.
+
+Arguments:
+
+ SectorErase - TRUE if a sector erase is under way.
+ FALSE if a byte write is under way.
+
+ Address - The address of the ROM byte that was just
+ written, or an address within the chip that
+ was just given an erase command.
+
+ Data - If a byte write is under way, this is the byte
+ that was written.
+
+ If a sector erase is under way, this must be
+ a value in the range 0xf0 -- 0xff.
+
+ROM state on exit:
+
+ The ROM is left at the end of its sector erase or byte write algorithm.
+
+Return Value:
+
+ Returns ESUCCESS if the status is OK.
+
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ UCHAR Character;
+ ULONG Retries;
+
+ //
+ // If we are doing an erase command, check whether the erase command
+ // was accepted. This is supposed to happen within the first 100 usec.
+ //
+
+ if (SectorErase) {
+
+ Retries = 0;
+
+ while ((READ_PORT_UCHAR(Address) & 0x08) != 0x08) {
+ Retries++;
+ KeStallExecutionProcessor(20);
+ if (Retries == 10) {
+ return (EIO);
+ }
+ }
+ }
+
+ //
+ // Do data polling until the device signals success or a timeout.
+ //
+
+ while (TRUE) {
+
+ Character = READ_PORT_UCHAR(Address);
+
+ //
+ // Has the device finished?
+ //
+
+ if (((Character ^ Data) & 0x80) == 0) {
+
+ //
+ // DQ7 says yes!
+ //
+
+ return (ESUCCESS);
+ }
+
+ //
+ // Check for time-out. If a possible time-out condition, DQ7 is
+ // re-read and re-checked to account for the case of simultaneous
+ // updates to DQ5 and DQ7.
+ //
+
+ if (Character & 0x20) {
+
+ if (((READ_PORT_UCHAR(Address) ^ Data) & 0x80) == 0) {
+
+ // DQ7 says success!
+ return (ESUCCESS);
+
+ } else {
+
+ // DQ5 and DQ7 say time-out.
+ return (EIO);
+ }
+ }
+ }
+}
+
+ARC_STATUS
+HalpEraseAM29F010 (
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a block in an AMD AM29F010 128KB Flash ROM.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ The status register is left in a cleared (reset) state.
+ The ROM is left in read-array mode.
+
+Return Value:
+
+ Returns ESUCCESS if the erase was successful.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ ULONG FooBar;
+ PUCHAR Address;
+ KIRQL OldIrql;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)EraseAddress &
+ ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ for (FooBar = 0; FooBar <= 10; FooBar++) {
+
+ HalpROMResetStatus(EraseAddress);
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ WRITE_PORT_UCHAR (Address+0x5555, 0xaa);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (Address+0x2aaa, 0x55);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (Address+0x5555, 0x80);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (Address+0x5555, 0xaa);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (Address+0x2aaa, 0x55);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (EraseAddress, 0x30);
+
+ KeLowerIrql(OldIrql);
+
+ if (CheckAM29F010Status(TRUE, EraseAddress, 0xff) == ESUCCESS) {
+ HalpROMSetReadMode(EraseAddress);
+ return ESUCCESS;
+ }
+
+ //
+ // We have to retry the erase. Give the device some time to settle.
+ //
+
+ HalpPromDelay(3000);
+ }
+
+
+ //
+ // If we get here, we have tried unsuccessfully 10 times to erase
+ // this block. Return an error.
+ //
+
+ HalpROMSetReadMode(EraseAddress);
+
+ return EIO;
+}
+
+ARC_STATUS
+HalpByteWriteAM29F010 (
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ )
+
+/*++
+
+Routine Description:
+
+ This writes a byte in an AMD AM29F010 128KB Flash ROM. It retries up to
+ 20 times if the write status register indicates failure, or a read
+ of the location indicates that the write was partially done
+ by the device.
+
+Arguments:
+
+ WriteAddress = meta-virtual address of the byte to be written.
+ WriteData = byte to be written.
+
+ROM state on exit:
+
+ The byte is written, and the WSM status register is modified.
+
+Return Value:
+
+ ESUCCESS if the write was successful.
+ Otherwise, EIO.
+
+--*/
+
+{
+ ULONG Index;
+ UCHAR WSMStatus;
+ PUCHAR Address;
+ KIRQL OldIrql;
+
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)WriteAddress &
+ ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ HalpROMResetStatus(WriteAddress);
+
+ for (Index = 0; Index < 20; Index++) {
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ WRITE_PORT_UCHAR (Address+0x5555, 0xaa);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (Address+0x2aaa, 0x55);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (Address+0x5555, 0xa0);
+ KeStallExecutionProcessor(2);
+ WRITE_PORT_UCHAR (WriteAddress, WriteData);
+ KeStallExecutionProcessor(2);
+
+ KeLowerIrql(OldIrql);
+
+ if (CheckAM29F010Status(FALSE, WriteAddress, WriteData) != ESUCCESS) {
+
+ //
+ // The write failed. Ensure status is clear and see if we
+ // can retry.
+ //
+
+ HalpROMResetStatus(WriteAddress);
+ HalpROMSetReadMode(WriteAddress);
+ DbgPrint("? Write failed to address %x. Wrote %x, ",
+ WriteAddress, WriteData);
+ DbgPrint("verify returns %x.\r\n",
+ READ_PORT_UCHAR((PUCHAR)WriteAddress));
+
+ if (READ_PORT_UCHAR(WriteAddress) != 0xff) {
+ DbgPrint("RETRY ABORTED!\r\n");
+ return EIO;
+ } else {
+ DbgPrint("Retrying..\r\n");
+ }
+
+ } else {
+
+ //
+ // The write succeeded.
+ //
+
+ return ESUCCESS;
+ }
+
+ }
+
+
+ //
+ // We failed to write the byte after 20 tries.
+ //
+
+ return EIO;
+}
+
+
+ARC_STATUS
+HalpROMDetermineMachineROMType (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This determines what kind of Flash ROM is in the machine.
+
+ The ROMs making up the Flash ROM space are assumed to be
+ homogeneous. So, we only check one chip.
+
+ N.B. The RomValues array must be tested in ascending order,
+
+ N.B. This function must not call any of the HalpROM... functions!
+
+Arguments:
+
+ ROMType - A pointer to a variable that will receive the type
+ of ROM in the machine, if the return value is ESUCCESS.
+
+ROM state on exit:
+
+ Left in read-array mode.
+
+Return Value:
+
+ ESUCCESS if we could successfully identify the ROM.
+ Otherwise, and error condition.
+
+--*/
+
+{
+ BOOLEAN Match;
+ ROM_TYPE Index;
+ ULONG IDIndex;
+
+ //
+ // Loop through each ROM type, trying the ID Command Sequence for
+ // each.
+ //
+
+ for (Index = 0; Index < InvalidROM; Index++) {
+
+ //
+ // Send the command.
+ //
+
+ for (IDIndex = 0;
+ IDIndex < RomValues[Index].IdCommandLength;
+ IDIndex++) {
+
+ WRITE_PORT_UCHAR(RomValues[Index].IdCommand[IDIndex].Address,
+ RomValues[Index].IdCommand[IDIndex].Value);
+
+ KeStallExecutionProcessor(RomValues[MachineROMType].StallAmount);
+ }
+
+ //
+ // Check the response.
+ //
+
+ Match = TRUE;
+
+ for (IDIndex = 0;
+ IDIndex < RomValues[Index].IdResponseLength;
+ IDIndex++) {
+
+ if (RomValues[Index].IdResponse[IDIndex].Value !=
+ READ_PORT_UCHAR(RomValues[Index].IdResponse[IDIndex].Address)) {
+ //
+ // This portion of the Response sequence did not match.
+ //
+
+ Match = FALSE;
+ break;
+ }
+ }
+
+ if (Match == FALSE) {
+ continue;
+ }
+
+ //
+ // We have found a match. Set the ROM to read-array mode, and then
+ // return the current entry as the ROM type.
+ //
+
+ MachineROMType = RomValues[Index].ROMType;
+ HalpROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+ HalpROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ return (ESUCCESS);
+ }
+
+ //
+ // We have not found a match. Return an error.
+ //
+
+ return (EIO);
+}
+
+VOID
+HalpROMResetStatus(
+ IN PUCHAR Address
+ )
+/*++
+
+Routine Description:
+
+ This clears the status register in a ROM chip.
+
+Arguments:
+
+ Address - An address within the chip that is to be reset.
+
+ROM state on exit:
+
+ The status register is left in a cleared (reset) state.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+ // Remember, C is call by value!
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)Address & ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ for (Index = 0;
+ Index < RomValues[MachineROMType].ResetCommandLength;
+ Index++) {
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+ WRITE_PORT_UCHAR (Address +
+ RomValues[MachineROMType].ResetCommand[Index].Offset,
+ RomValues[MachineROMType].ResetCommand[Index].Value);
+ HalpMb();
+ KeLowerIrql(OldIrql);
+
+ KeStallExecutionProcessor(RomValues[MachineROMType].StallAmount);
+ }
+}
+
+VOID
+HalpROMSetReadMode(
+ IN PUCHAR Address
+ )
+/*++
+
+Routine Description:
+
+ This returns a ROM chip to read-array mode.
+
+Arguments:
+
+ Address - An address within the chip that is to be set to
+ read-array mode.
+
+ROM state on exit:
+
+ The chip is left in read-array mode.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+ // Remember, C is call by value!
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)Address & ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ for (Index = 0;
+ Index < RomValues[MachineROMType].ReadCommandLength;
+ Index++) {
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+ WRITE_PORT_UCHAR (Address +
+ RomValues[MachineROMType].ReadCommand[Index].Offset,
+ RomValues[MachineROMType].ReadCommand[Index].Value);
+ HalpMb();
+ KeLowerIrql(OldIrql);
+
+ KeStallExecutionProcessor(RomValues[MachineROMType].StallAmount);
+ }
+}
+
+VOID
+HalpROMSetARCDataToReadMode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine sets the virtual 64KB ROM block that houses the
+ CDS tree, environment variables, and EISA configuration data to
+ read-array mode. For devices with a block size smaller than
+ 64KB, we issues set read-mode commands to every block within this
+ virtual 64KB block. This is overkill, but it is easy.
+
+Arguments:
+
+ None.
+
+ROM state on exit:
+
+ Set to read-array mode.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PUCHAR Address;
+ ULONG Index;
+
+ Address = (PUCHAR)NVRAM_CONFIGURATION;
+
+ //
+ // Hackhack: At some point change this to eliminate the division.
+ //
+
+ for (Index = 0;
+ Index < (SIXTY_FOUR_KB / RomValues[MachineROMType].BytesPerBlock);
+ Index++) {
+ HalpROMSetReadMode(Address);
+ Address += RomValues[MachineROMType].BytesPerBlock;
+ }
+}
+
+ARC_STATUS
+HalpROMByteWrite(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ )
+
+/*++
+
+Routine Description:
+
+ This writes a byte in the Alpha/Jensen ROM space.
+
+Arguments:
+
+ WriteAddress = meta-virtual address of the byte to be written.
+ WriteData = byte to be written.
+
+ROM state on exit:
+
+ The byte is written, and the WSM status register is modified.
+
+Return Value:
+
+ Whatever is returned from the ROM-specific write function.
+
+--*/
+
+{
+ return ((*RomValues[MachineROMType].ByteWrite)(WriteAddress, WriteData));
+}
+
+ARC_STATUS
+HalpROMEraseBlock(
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a single block in the Alpha/Jensen ROM space. The number
+ of bytes erased is dependent on the underlying chip being manipulated.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ On a successful return, the status register is left in a reset state and
+ the ROM is in read-array mode.
+
+Return Value:
+
+ Whatever is returned from the ROM-specific erase function.
+
+--*/
+
+{
+ return ((*RomValues[MachineROMType].SectorErase)(EraseAddress));
+}
+
+ARC_STATUS
+HalpROMErase64KB(
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a 64KB logical block in the Alpha/Jensen ROM space.
+
+ To minimize code changes with the previous version of the firmware,
+ the PROM space is treated as though it has a block size of 64KB, even
+ if the block size is must less than that.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ On a successful return, the status register is left in a reset state and
+ the ROM is in read-array mode.
+
+Return Value:
+
+ Returns ESUCCESS if the erase was successful.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ ULONG Index;
+
+ //
+ // Create the base address of the 64KB block to be cleared.
+ //
+ // Remember, C is call by value!
+ //
+
+ EraseAddress = (PUCHAR)((ULONG)EraseAddress & ~(SIXTY_FOUR_KB - 1));
+
+ //
+ // Now erase as many blocks as is necessary to erase a 64KB virtual block.
+ //
+ // Hack: I should eliminate the integer division.
+ //
+
+ for (Index = 0;
+ Index < (SIXTY_FOUR_KB / RomValues[MachineROMType].BytesPerBlock);
+ Index++) {
+
+ if ((Status = (*RomValues[MachineROMType].SectorErase)(EraseAddress))
+ != ESUCCESS) {
+ break;
+ }
+
+ EraseAddress += RomValues[MachineROMType].BytesPerBlock;
+ }
+
+ return (Status);
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/jxprom.h b/private/ntos/nthals/hal0jens/alpha/jxprom.h
new file mode 100644
index 000000000..66c0aa09e
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxprom.h
@@ -0,0 +1,218 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxprom.h
+
+Abstract:
+
+ This module defines structures and datatypes for use in reading
+ and writing ROMs/PROMs/Flash ROMs.
+
+ This file, and rom.c, makes no attempt at universal ROM-support.
+
+Author:
+
+ John DeRosa 4-May-1993
+
+Revision History:
+
+ Jeff McLeman 13-May-1993
+
+ Adapted for use in Hal
+
+--*/
+
+//
+// All ROM manipulations (reading, writing, etc.) are done through
+// an array. The array contains one entry per ROM type, and the values
+// in each entry dictate how to talk to the ROM.
+//
+// Supported ROMs are assumed to have the following characteristics:
+//
+// The ROM space in the machine is made up of all the same parts.
+// I.e., the space is homogeneous.
+//
+// Each chip has a byte path for data in and data out.
+//
+// Each chip has a way to identify itself.
+//
+// Each chip has a way to be reset.
+//
+// Each chip has a finite erase, write, set read-mode, and identify
+// sequence.
+//
+// The chip block size is less than or equal to 64KB.
+//
+
+//
+// Define the maximum length of certain commands.
+//
+
+#define MAXIMUM_ROM_ID_COMMAND_LENGTH 3
+#define MAXIMUM_ROM_ID_RESPONSE_LENGTH 2
+#define MAXIMUM_ROM_READ_COMMAND_LENGTH 3
+#define MAXIMUM_ROM_RESET_COMMAND_LENGTH 3
+
+//
+//
+//
+
+#define SIXTY_FOUR_KB 0x10000
+
+
+//
+// Define supported Rom types
+//
+
+typedef enum _ROM_TYPE {
+ I28F008SA,
+ Am29F010,
+ InvalidROM
+} ROM_TYPE, *PROM_TYPE;
+
+
+//
+// Define function time for erase and byte-write entries.
+//
+
+typedef ARC_STATUS (*PROMSECTORERASE) (IN PUCHAR EraseAddress);
+
+typedef ARC_STATUS (*PROMBYTEWRITE) (IN PUCHAR WriteAddress,
+ IN UCHAR WriteData);
+
+//
+// Define structure to store ROM address and byte pairs.
+//
+
+typedef struct _ABSOLUTE_ROM_COMMAND {
+ PUCHAR Address;
+ UCHAR Value;
+} ABSOLUTE_ROM_COMMAND, *PABSOLUTE_ROM_COMMAND;
+
+typedef struct _OFFSET_ROM_COMMAND {
+ ULONG Offset;
+ UCHAR Value;
+} OFFSET_ROM_COMMAND, *POFFSET_ROM_COMMAND;
+
+//
+// Define the entries in the ROM values table. These are organized for
+// memory efficiency.
+//
+
+typedef struct _ROM_VALUES {
+
+ //
+ // Microseconds to stall after most ROM commands.
+ //
+
+ UCHAR StallAmount;
+
+ //
+ // Length of the Identification command sequence.
+ //
+
+ UCHAR IdCommandLength;
+
+ //
+ // Length of the Identification response.
+ //
+
+ UCHAR IdResponseLength;
+
+ //
+ // Length of the Reset command.
+ //
+
+ UCHAR ResetCommandLength;
+
+ //
+ // Length of the Set read-mode command.
+ //
+
+ UCHAR ReadCommandLength;
+
+ //
+ // The ROM supported by this entry.
+ //
+
+ ROM_TYPE ROMType;
+
+ //
+ // Number of bytes per chip.
+ //
+
+ ULONG BytesPerChip;
+
+ //
+ // Number of bytes per block.
+ //
+
+ ULONG BytesPerBlock;
+
+ //
+ // Identification command sequence.
+ //
+ // Each step in the sequence is two bytes: address to be written,
+ // and data to be written.
+ //
+
+ ABSOLUTE_ROM_COMMAND IdCommand[MAXIMUM_ROM_ID_COMMAND_LENGTH];
+
+ //
+ // Identification response sequence.
+ //
+ // Each step in the seqeuence is two bytes: address to be read, and
+ // the byte that should be returned.
+ //
+
+ ABSOLUTE_ROM_COMMAND IdResponse[MAXIMUM_ROM_ID_RESPONSE_LENGTH];
+
+ //
+ // Reset command sequence.
+ //
+ // Each step in the sequence is two bytes: address to be written,
+ // and data to be written.
+ //
+
+ OFFSET_ROM_COMMAND ResetCommand[MAXIMUM_ROM_RESET_COMMAND_LENGTH];
+
+ //
+ // Set read-mode command sequence.
+ //
+ // Each step in the sequence is two bytes: address to be written,
+ // and data to be written.
+ //
+
+ OFFSET_ROM_COMMAND ReadCommand[MAXIMUM_ROM_READ_COMMAND_LENGTH];
+
+ //
+ // The function to be called to do a block erase.
+ //
+
+ PROMSECTORERASE SectorErase;
+
+ //
+ // The function to be called to do a byte write.
+ //
+
+ PROMBYTEWRITE ByteWrite;
+
+} ROM_VALUES, *PROM_VALUES;
+
+//
+// Define function protoypes
+//
+
+VOID
+HalpROMResetStatus(
+ IN PUCHAR Address
+ );
+
+VOID
+HalpROMSetReadMode(
+ IN PUCHAR Address
+ );
+
diff --git a/private/ntos/nthals/hal0jens/alpha/jxserp.h b/private/ntos/nthals/hal0jens/alpha/jxserp.h
new file mode 100644
index 000000000..2fc556ea3
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxserp.h
@@ -0,0 +1,181 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxserp.h
+
+Abstract:
+
+ This header file defines the Jensen serial port registers.
+
+ Stolen from jazzserp.h, which is a slightly different chip-
+ it has a 16 byte fifo - we are just double buffered.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Miche Baker-Harvey (miche) 01-June-1992
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXSERP_
+#define _JXSERP_
+
+
+//
+// Define base port numbers for serial lines inside the combo chip
+//
+
+#define COMA_PORT_BASE 0x3f8
+#define COMB_PORT_BASE 0x2f8
+
+
+//
+// Define serial port read registers structure.
+//
+
+typedef struct _SP_READ_REGISTERS {
+ UCHAR ReceiveBuffer;
+ UCHAR InterruptEnable;
+ UCHAR InterruptId;
+ UCHAR LineControl;
+ UCHAR ModemControl;
+ UCHAR LineStatus;
+ UCHAR ModemStatus;
+ UCHAR ScratchPad;
+} SP_READ_REGISTERS, *PSP_READ_REGISTERS;
+
+//
+// Define define serial port write registers structure.
+//
+
+typedef struct _SP_WRITE_REGISTERS {
+ UCHAR TransmitBuffer;
+ UCHAR InterruptEnable;
+ UCHAR FifoControl;
+ UCHAR LineControl;
+ UCHAR ModemControl;
+ UCHAR Reserved1;
+ UCHAR ModemStatus;
+ UCHAR ScratchPad;
+} SP_WRITE_REGISTERS, *PSP_WRITE_REGISTERS;
+
+//
+// Define serial port interrupt enable register structure.
+//
+
+typedef struct _SP_INTERRUPT_ENABLE {
+ UCHAR ReceiveEnable : 1;
+ UCHAR TransmitEnable : 1;
+ UCHAR LineStatusEnable : 1;
+ UCHAR ModemStatusEnable : 1;
+ UCHAR Reserved1 : 4;
+} SP_INTERRUPT_ENABLE, *PSP_INTERRUPT_ENABLE;
+
+//
+// Define serial port interrupt id register structure.
+//
+
+typedef struct _SP_INTERRUPT_ID {
+ UCHAR InterruptPending : 1;
+ UCHAR Identification : 3;
+ UCHAR Reserved1 : 2;
+ UCHAR FifoEnabled : 2; // always read as 0
+} SP_INTERRUPT_ID, *PSP_INTERRUPT_ID;
+
+//
+// Define serial port fifo control register structure.
+// This register is here for software compatibility, but there is
+// no FIFO on the 16C452
+//
+
+typedef struct _SP_FIFO_CONTROL {
+ UCHAR FifoEnable : 1;
+ UCHAR ReceiveFifoReset : 1;
+ UCHAR TransmitFifoReset : 1;
+ UCHAR DmaModeSelect : 1;
+ UCHAR Reserved1 : 2;
+ UCHAR ReceiveFifoLevel : 2;
+} SP_FIFO_CONTROL, *PSP_FIFO_CONTROL;
+
+//
+// Define serial port line control register structure.
+//
+
+typedef struct _SP_LINE_CONTROL {
+ UCHAR CharacterSize : 2;
+ UCHAR StopBits : 1;
+ UCHAR ParityEnable : 1;
+ UCHAR EvenParity : 1;
+ UCHAR StickParity : 1;
+ UCHAR SetBreak : 1;
+ UCHAR DivisorLatch : 1;
+} SP_LINE_CONTROL, *PSP_LINE_CONTROL;
+
+//
+// Line status register character size definitions.
+//
+
+#define FIVE_BITS 0x0 // five bits per character
+#define SIX_BITS 0x1 // six bits per character
+#define SEVEN_BITS 0x2 // seven bits per character
+#define EIGHT_BITS 0x3 // eight bits per character
+
+//
+// Line speed divisor definition. We get our baud rate clock
+// from the 82C106.
+//
+
+#define BAUD_RATE_9600 12 // divisor for 9600 baud
+#define BAUD_RATE_19200 6 // divisor for 19200 baud
+
+//
+// Define serial port modem control register structure.
+//
+
+typedef struct _SP_MODEM_CONTROL {
+ UCHAR DataTerminalReady : 1;
+ UCHAR RequestToSend : 1;
+ UCHAR Reserved1 : 1;
+ UCHAR Interrupt : 1;
+ UCHAR loopBack : 1;
+ UCHAR Reserved2 : 3;
+} SP_MODEM_CONTROL, *PSP_MODEM_CONTROL;
+
+//
+// Define serial port line status register structure.
+//
+
+typedef struct _SP_LINE_STATUS {
+ UCHAR DataReady : 1;
+ UCHAR OverrunError : 1;
+ UCHAR ParityError : 1;
+ UCHAR FramingError : 1;
+ UCHAR BreakIndicator : 1;
+ UCHAR TransmitHoldingEmpty : 1;
+ UCHAR TransmitEmpty : 1;
+ UCHAR ReceiveFifoError : 1;
+} SP_LINE_STATUS, *PSP_LINE_STATUS;
+
+//
+// Define serial port modem status register structure.
+//
+
+typedef struct _SP_MODEM_STATUS {
+ UCHAR DeltaClearToSend : 1;
+ UCHAR DeltaDataSetReady : 1;
+ UCHAR TrailingRingIndicator : 1;
+ UCHAR DeltaReceiveDetect : 1;
+ UCHAR ClearToSend : 1;
+ UCHAR DataSetReady : 1;
+ UCHAR RingIndicator : 1;
+ UCHAR ReceiveDetect : 1;
+} SP_MODEM_STATUS, *PSP_MODEM_STATUS;
+
+#endif // _JAZZSERP_
diff --git a/private/ntos/nthals/hal0jens/alpha/jxtime.c b/private/ntos/nthals/hal0jens/alpha/jxtime.c
new file mode 100644
index 000000000..642182045
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxtime.c
@@ -0,0 +1,283 @@
+#if defined(JENSEN)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ the Alpha based Jensen system
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+ Jeff McLeman (mcleman) 3-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 13-Jul-1992 Jeff McLeman
+ use VTI access routines to access clock
+
+ 3-June-1992 Jeff McLeman
+ Adapt this module into a Jensen specific module
+
+--*/
+
+#include "halp.h"
+#include "jnsnrtc.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Status;
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ Status = TRUE;
+
+ } else {
+ Status = FALSE;
+ }
+
+ KeLowerIrql(OldIrql);
+ return(Status);
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ UCHAR DataByte;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ // (Make sure periodic interrupt is enabled)
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ HalpWriteVti(RTC_APORT, Register);
+
+ DataByte = HalpReadVti(RTC_DPORT);
+
+ return DataByte;
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // Write the realtime clock register value.
+ //
+
+ HalpWriteVti(RTC_APORT, Register);
+
+ HalpWriteVti(RTC_DPORT, Value);
+
+ return;
+}
+
+#endif
diff --git a/private/ntos/nthals/hal0jens/alpha/jxusage.c b/private/ntos/nthals/hal0jens/alpha/jxusage.c
new file mode 100644
index 000000000..75ecdcad1
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxusage.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the alpha hal.
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/jxvtisup.s b/private/ntos/nthals/hal0jens/alpha/jxvtisup.s
new file mode 100644
index 000000000..49a20b0a1
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxvtisup.s
@@ -0,0 +1,149 @@
+// TITLE("Alpha PAL funtions for HAL")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+//
+// Module Name:
+//
+// jxvtisup.s
+//
+// Abstract:
+//
+// This module implements routines to i/o to the on-board vti chip on
+// the JENSEN system board via the 64-bit super-pages.
+// Unfortunately, these routines had to be coded in assembly language
+// since it's not a particularly good idea to require a 64-bit compilation
+// mode for the otherwise 32-bit compiler. Still, the C code was awfully
+// clean.
+//
+//
+// Author:
+//
+// Joe Notarangelo 15-Jul-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "kxalpha.h"
+
+//++
+//
+// VOID
+// outVti(
+// ULONG port
+// ULONG data
+// )
+//
+// Routine Description:
+//
+// This function uses the 64-bit super-page to write data to a port
+// of the on-board VTI combo chip for JENSEN.
+//
+// Arguments:
+//
+// port (a0) - port number on VTI chip to which to write data
+// data (a1) - data to write to the port, only low byte is significant
+// to the VTI
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(outVti)
+
+ //
+ // generate super-page address of vti, base address
+ // N.B. - upper bits must be sign extension of bit 42
+ // va<42:41> = 10 (binary) for super-page address
+ //
+
+ lda t0, 0xc01c(zero) // t0 = 0000 0000 0000 c01c
+ ldah t0, -1(t0) // t0 = ffff ffff ffff c01c
+ sll t0, 28, t0 // t0 = ffff fc01 c000 0000
+
+
+ //
+ // Shift in the port number to generate the port address we
+ // wish to access
+ // N.B. - access width is always zero = byte access for VTI
+ //
+
+ sll a0, 9, a0 // a0 << 9
+ bis t0, a0, t0 // t0 = address of VTI port
+
+
+ //
+ // Do the port write, guarantee that subsequent writes (and reads)
+ // are ordered with respect to this write and return to caller
+ //
+
+ stl a1, 0(t0) // write data to port
+ mb // guarantee write ordering
+
+ ret zero, (ra) // return
+
+ .end outVti
+
+//++
+//
+// ULONG
+// inVti(
+// ULONG port
+// )
+//
+// Routine Description:
+//
+// This function uses the 64-bit super-page to read data from a port
+// of the on-board VTI combo chip for JENSEN.
+//
+// Arguments:
+//
+// port (a0) - port number on VTI chip to which to write data
+//
+// Return Value:
+//
+// data (v0) - the data read from the VTI chip, only the low byte will
+// be valid
+//
+//--
+
+ LEAF_ENTRY(inVti)
+
+ //
+ // generate super-page address of vti, base address
+ // N.B. - upper bits must be sign extension of bit 42
+ // va<42:41> = 10 (binary) for super-page address
+ //
+
+ lda t0, 0xc01c(zero) // t0 = 0000 0000 0000 c01c
+ ldah t0, -1(t0) // t0 = ffff ffff ffff c01c
+ sll t0, 28, t0 // t0 = ffff fc01 c000 0000
+
+
+ //
+ // Shift in the port number to generate the port address we
+ // wish to access
+ // N.B. - access width for VTI is always 0 = byte access
+ //
+
+ sll a0, 9, a0 // a0 << 9
+ bis t0, a0, t0 // t0 = address of VTI port
+
+
+ //
+ // Do the super-page i/o access and return data to caller
+ //
+
+ ldl v0, 0(t0) // read data from port
+
+ ret zero, (ra) // return
+
+ .end inVti
+
diff --git a/private/ntos/nthals/hal0jens/alpha/machdep.h b/private/ntos/nthals/hal0jens/alpha/machdep.h
new file mode 100644
index 000000000..e25a3967f
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ Dummy file so the Jensen HAL can include some things from halalpha
+
+Author:
+
+ John Vert (jvert) 17-Aug-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV4 processor.
+//
+
+typedef struct _JENSEN_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} JENSEN_PCR, *PJENSEN_PCR;
+
+#define HAL_PCR ( (PJENSEN_PCR)(&(PCR->HalReserved)) )
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/hal0jens/alpha/xxenvirv.c b/private/ntos/nthals/hal0jens/alpha/xxenvirv.c
new file mode 100644
index 000000000..b25b32beb
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/xxenvirv.c
@@ -0,0 +1,1451 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ xxenvir.c
+
+Abstract:
+
+ This module implements the ARC firmware Environment Variable functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.11, for the Alpha Jensen system.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+
+Revision History:
+
+ Jeff McLeman (DEC) 31-Jul-1992
+
+ modify for Jensen
+
+
+ This module is for Jensen only. Jensen uses a 1 Mbyte sector eraseable
+ flash prom. Due to the long delays needed to store the environment in the
+ prom, we must implement a timer, instead of using
+ KeStallExecutionProcessor(). The prom may take up to a second to perform
+ the function, so we will go away while it is still running, and comeback
+ when it is done.
+
+--*/
+
+#include "halp.h"
+
+#if defined(JENSEN)
+#include "jxenv.h"
+#endif
+
+#include "arccodes.h"
+
+//
+// Static data.
+//
+
+UCHAR OutputString[MAXIMUM_ENVIRONMENT_VALUE];
+PUCHAR VolatileEnvironment;
+PCHAR VolatileConfig;
+PCHAR VolatileEisaData;
+PCONFIGURATION Configuration;
+
+PROMTIMER PromTimer;
+KEVENT PromEvent;
+
+//
+// Routine prototypes.
+//
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ );
+
+ARC_STATUS
+HalpEnvironmentSetChecksum (
+ VOID
+ );
+
+ARC_STATUS
+HalpConfigurationSetChecksum (
+ VOID
+ );
+
+ARC_STATUS
+HalpEisaSetChecksum (
+ VOID
+ );
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ );
+
+VOID
+HalpInitializePromTimer(
+ IN OUT PPROMTIMER PrmTimer,
+ IN PVOID FunctionContext
+ );
+
+VOID
+HalpSetPromTimer(
+ IN PPROMTIMER PrmTimer,
+ IN ULONG MillisecondsToDelay
+ );
+
+VOID
+HalpPromDpcHandler(
+ IN PVOID SystemSpecific,
+ IN PVOID Context,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+ );
+
+VOID
+HalpPromDelay(
+ IN ULONG Milliseconds
+ );
+
+
+ARC_STATUS
+HalpEnvironmentInitialize (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the environment routine addresses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG status = 0;
+
+ //
+ // Determine the ROM type in this machine
+ //
+ if (HalpROMDetermineMachineROMType() != ESUCCESS) {
+ HalDisplayString("*** Unknown ROM Type in Machine ***\n");
+ HalDisplayString(" Please contact Digital Field Services \n");
+ HalpPromDelay(10*1000);
+ HalpReboot();
+ }
+
+ //
+ // Allocate enough memory to load the environment for loaded programs.
+ //
+
+ VolatileEnvironment = ExAllocatePool(NonPagedPool, LENGTH_OF_ENVIRONMENT);
+
+ if (VolatileEnvironment == 0) {
+ status = FALSE;
+ }
+
+ HalpEnvironmentLoad();
+
+ HalpInitializePromTimer(&PromTimer,0);
+
+ return(status);
+}
+
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the environment area checksum.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1, Checksum2;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_ENVIRONMENT;
+ Index++ ) {
+ Checksum1 += READ_PORT_UCHAR( NvChars++ );
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+ Checksum2 = (ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[0] ) |
+ (ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[1] ) << 8 |
+ (ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[2] ) << 16 |
+ (ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[3] ) << 24 ;
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+}
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the non-volatile ram for
+ Variable, and if found returns a pointer to a zero terminated string that
+ contains the value, otherwise a NULL pointer is returned.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+ Length - Supplies the length of the vlaue buffer in bytes
+
+ Buffer - Supplies a pointer to a buffer that will recieve the
+ environment variable.
+
+Return Value:
+
+ If successful, returns a zero terminated string that is the value of
+ Variable, otherwise NULL is returned.
+
+--*/
+
+{
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG Index;
+ ARC_STATUS Status;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to synchronize
+ //
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // If checksum is wrong, or the variable can't be found, return NULL.
+ //
+
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) != ESUCCESS)) {
+ Status = ENOENT;
+ } else {
+
+ //
+ // Copy value to an output string, break on zero terminator or string max.
+ //
+
+ for ( Index = 0 ; Index < length ; Index += 1 ) {
+
+ *Buffer =
+ READ_PORT_UCHAR( &NvConfiguration->Environment[ValueIndex] );
+
+ if (*Buffer== 0) {
+ break;
+ }
+
+ Buffer += 1;
+
+ ValueIndex += 1;
+
+ }
+ if (Index == length) {
+ Status = ENOMEM;
+ } else {
+ Status = ESUCCESS;
+ }
+
+ }
+
+ //
+ // Lower IRQL back to where it was
+ //
+
+ KeLowerIrql(OldIrql);
+
+ return Status;
+}
+
+
+#ifdef JENSEN
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets Variable (not case sensitive) to Value.
+
+ The MIPS version of this code modified the NVRAM directly.
+ For Alpha/Jensen, we have to modify the volatile area and then
+ update the PROM configuration block.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+ Value - Supplies a zero terminated string containing an environment
+ variable value.
+
+Return Value:
+
+ Returns ESUCCESS if the set completed successfully, otherwise one of
+ the following error codes is returned.
+
+ ENOSPC No space in NVRAM for set operation.
+
+ EIO Invalid Checksum.
+
+--*/
+
+{
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG TopOfEnvironment;
+ PCHAR String;
+ PUCHAR VChars;
+ LONG Count;
+ CHAR Char;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+
+ //
+ // Raise Irql to Synchronize
+ //
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // If checksum is wrong, return EIO;
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ KeLowerIrql(OldIrql);
+ return EIO;
+ }
+
+
+ VChars = VolatileEnvironment;
+
+
+ //
+ // Determine the top of the environment space by looking for the first
+ // non-null character from the top.
+ //
+
+ TopOfEnvironment = LENGTH_OF_ENVIRONMENT - 1;
+ while (VChars[--TopOfEnvironment] == 0) {
+ if (TopOfEnvironment == 0) {
+ break;
+ }
+ }
+
+ //
+ // Adjust TopOfEnvironment to the first new character, unless environment
+ // space is empty.
+ //
+
+ if (TopOfEnvironment != 0) {
+ TopOfEnvironment += 2;
+ }
+
+ //
+ // Check to see if the variable already has a value.
+ //
+
+ Count = LENGTH_OF_ENVIRONMENT - TopOfEnvironment;
+
+ if (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) == ESUCCESS) {
+
+ //
+ // Count free space, starting with the free area at the top and adding
+ // the old variable value.
+ //
+
+ for ( String = VChars + ValueIndex ;
+ *String != 0 ;
+ String++ ) {
+ Count++;
+ }
+
+ //
+ // Determine if free area is large enough to handle new value, if not
+ // return error.
+ //
+
+ for ( String = Value ; *String != 0 ; String++ ) {
+ if (Count-- == 0) {
+ KeLowerIrql(OldIrql);
+ return ENOSPC;
+ }
+ }
+
+ //
+ // Move ValueIndex to the end of the value and compress strings.
+ //
+
+ while(VChars[ValueIndex++] != 0) {
+ }
+
+ while (ValueIndex < TopOfEnvironment ) {
+ VChars[VariableIndex++] = VChars[ValueIndex++];
+ }
+
+ //
+ // Adjust new top of environment.
+ //
+
+ TopOfEnvironment = VariableIndex;
+
+ //
+ // Zero to the end.
+ //
+
+ while (VariableIndex < LENGTH_OF_ENVIRONMENT) {
+ VChars[VariableIndex++] = 0;
+ }
+
+ } else {
+
+ //
+ // Variable is new.
+ //
+
+ //
+ // Determine if free area is large enough to handle new value, if not
+ // return error.
+ //
+
+ //
+ // From the length of free space subtract new variable's length,
+ // Value's length and 2 chars, one for the '=' sign and one of the
+ // null terminator.
+ //
+
+ Count -= ( strlen(Variable) + strlen(Value) + 2 );
+
+ //
+ // Check if there is space to fit the new variable.
+ //
+
+ if (Count < 0) {
+ KeLowerIrql(OldIrql);
+ return ENOSPC;
+ }
+ }
+
+ //
+ // If Value is not zero, write new variable and value.
+ //
+
+ if (*Value != 0) {
+
+ //
+ // Write new variable, converting to upper case.
+ //
+
+ while (*Variable != 0) {
+ VChars[TopOfEnvironment++] =
+ ((*Variable >= 'a') && (*Variable <= 'z') ? (*Variable - 'a' + 'A') : *Variable);
+ Variable++;
+ }
+
+ //
+ // Write equal sign.
+ //
+
+ VChars[TopOfEnvironment++] = '=';
+
+ //
+ // Write new value.
+ //
+
+ while (*Value != 0) {
+ VChars[TopOfEnvironment++] = *Value++;
+ }
+ }
+
+ //
+ // Lower Irql back to where it was
+ //
+
+ KeLowerIrql(OldIrql);
+
+
+ /* Now update the Jensen PROM */
+
+ Status = HalpSaveConfiguration();
+
+ return Status;
+// return ESUCCESS;
+
+}
+
+#endif
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the non-volatile ram for
+ Variable.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+Return Value:
+
+ If successful, returns ESUCCESS, otherwise returns ENOENT.
+
+--*/
+
+{
+ PNV_CONFIGURATION NvConfiguration;
+ PUCHAR String;
+ PUCHAR Environment;
+ ULONG Index;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // If Variable is null, return immediately.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ Environment = NvConfiguration->Environment;
+ Index = 0;
+
+ while (TRUE) {
+
+ //
+ // Set string to beginning of Variable.
+ //
+
+ String = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of NVRAM.
+ //
+
+ while ( Index < LENGTH_OF_ENVIRONMENT ) {
+
+ //
+ // Convert to uppercase and break if mismatch.
+ //
+
+ if ( READ_PORT_UCHAR( &Environment[Index] ) !=
+ ((*String >= 'a') &&
+ (*String <= 'z') ?
+ (*String - 'a' + 'A') : *String) ) {
+ break;
+ }
+
+ String++;
+ Index++;
+ }
+
+ //
+ // Check to see if we're at the end of the string and the variable,
+ // which means a match.
+ //
+
+ if ((*String == 0) && (READ_PORT_UCHAR( &Environment[Index] ) == '=')) {
+ *ValueIndex = ++Index;
+ return ESUCCESS;
+ }
+
+ //
+ // Move index to the start of the next variable.
+ //
+
+ while (READ_PORT_UCHAR( &Environment[Index++] ) != 0) {
+ if (Index >= LENGTH_OF_ENVIRONMENT) {
+ return ENOENT;
+ }
+ }
+ }
+}
+
+PCHAR
+HalpEnvironmentLoad (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine loads the entire environment into the volatile environment
+ area.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, a pointer to the environment in returned,
+ otherwise NULL is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PUCHAR NvChars;
+ PUCHAR VChars;
+ PNV_CONFIGURATION NvConfiguration;
+
+ if (HalpEnvironmentCheckChecksum() == ESUCCESS) {
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Copy the data into the volatile area.
+ //
+
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+ VChars = VolatileEnvironment;
+
+// READ_PORT_BUFFER_UCHAR(NvChars, VChars, LENGTH_OF_ENVIRONMENT);
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_ENVIRONMENT;
+ Index++ ) {
+ *VChars++ = READ_PORT_UCHAR( NvChars++ );
+ }
+
+ return (PCHAR)VolatileEnvironment;
+ } else {
+ return NULL;
+ }
+
+}
+
+
+ARC_STATUS
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the environment area checksum.
+
+ For Alpha/Jensen builds, this must ONLY be called from
+ HalpEnvironmentStore, as the previous block erase & storage
+ of the entire environment variable area must have been done.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum;
+ KIRQL OldIrql;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum = 0;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ HalpROMSetReadMode(NvChars);
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_ENVIRONMENT;
+ Index++ ) {
+ Checksum += READ_PORT_UCHAR( NvChars++ );
+ }
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Write environment checksum.
+ //
+
+
+ HalpROMResetStatus((PUCHAR)&NvConfiguration->Environment[0]);
+
+ if ((HalpROMByteWrite( &NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24)) != ESUCCESS)) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+
+ }
+}
+
+ARC_STATUS
+HalpEnvironmentStore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This loads the entire environment into the non-volatile environment area.
+
+ It's needed only in Jensen, which uses a segmented block-erase
+ PROM. When the code wants to store one environment variable,
+ it has to store all of them. This causes the least pertubations
+ in the firmware code.
+
+ This routine must *only* be called from HalpSaveConfiguration, which
+ does the block-erase and the store of the other part of the
+ non-volatile configuration information.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS if the writes were OK.
+ EIO otherwise.
+
+
+--*/
+
+{
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+ PUCHAR NvChars, VChars;
+ extern PUCHAR VolatileEnvironment; // defined in jxenvir.c
+
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+ VChars = VolatileEnvironment;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+
+#if DBG
+ DbgPrint("WriteEnv: NvChars=%x, VChars=%x, loe = %x\n",
+ NvChars,VChars,LENGTH_OF_ENVIRONMENT);
+
+#endif
+
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index++) {
+ if (HalpROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
+ return EIO;
+ }
+
+ }
+
+ if (HalpEnvironmentSetChecksum() != ESUCCESS) {
+ return EIO;
+ }
+
+ return ESUCCESS;
+
+ }
+
+ARC_STATUS
+HalpSaveConfiguration (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine stores all of the configuration entries into NVRAM,
+ including the associated identifier strings and configuration data.
+
+ The Alpha/Jensen version of this code saves the entire configuration
+ structure, i.e. including the environment variables. The ARC CDS
+ + environment variables are all in one structure, and unfortunately
+ Jensen has a segmented block-erase PROM instead of an NVRAM. Doing
+ a complete save is a change that is least likely to break anything.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns ESUCCESS if the save completed successfully, otherwise one of the
+ following error codes is returned.
+
+ ENOSPC Not enough space in the NVRAM to save all of the data.
+
+ EIO Some write error happened in the PROM.
+
+--*/
+
+{
+ ULONG EntryIndex;
+ ULONG Index;
+// ULONG NumBytes;
+ PNV_CONFIGURATION NvConfiguration;
+ PUCHAR NvChars, VChars;
+ ULONG ConfigSize;
+ KIRQL OldIrql;
+ ULONG EisaSize = LENGTH_OF_EISA_DATA;
+
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Entered\n");
+
+#endif
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ ConfigSize= (
+ (sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES) +
+ LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA);
+
+
+ VolatileConfig = ExAllocatePool(NonPagedPool, PAGE_SIZE);
+ if (VolatileConfig == NULL) {
+ return(ENOMEM);
+ }
+
+ VolatileEisaData = ExAllocatePool(NonPagedPool, PAGE_SIZE);
+ if (VolatileEisaData == NULL) {
+ ExFreePool(VolatileConfig);
+ return(ENOMEM);
+ }
+
+ //
+ // Copy the component structure first
+ //
+
+ VChars = VolatileConfig;
+ NvChars = (PUCHAR)NVRAM_CONFIGURATION;
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ //
+ // Copy the config data from the rom to the volatile pool
+ //
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Reading Config data\n");
+ DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
+ DbgPrint("ConfigSize = %X\n",ConfigSize);
+
+#endif
+
+ for (Index = 0; Index < ConfigSize; Index++) {
+ *VChars++ = READ_PORT_UCHAR(NvChars++);
+ }
+
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Now copy the EISA data
+ //
+
+ VChars = VolatileEisaData;
+ NvChars = (PUCHAR)&NvConfiguration->EisaData[0];
+
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ //
+ // Copy the eisa data from the rom to the volatile pool
+ //
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Reading Eisa data\n");
+ DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
+ DbgPrint("ConfigSize = %X\n",EisaSize);
+
+#endif
+
+ for (Index = 0; Index < EisaSize; Index++) {
+ *VChars++ = READ_PORT_UCHAR(NvChars++);
+ }
+
+
+ KeLowerIrql(OldIrql);
+
+ /*
+ * Erase the PROM block we are going to update.
+ */
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Erasing prom block \n");
+
+#endif
+ if (HalpROMEraseBlock((PUCHAR)NVRAM_CONFIGURATION) != ESUCCESS) {
+ ExFreePool(VolatileEisaData);
+ ExFreePool(VolatileConfig);
+ return ENOSPC;
+ }
+
+
+ //
+ // Write the configuration stuff back into the rom.
+ //
+
+ VChars = VolatileConfig;
+ NvChars = (PUCHAR)NVRAM_CONFIGURATION;
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Writing Config data\n");
+ DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
+ DbgPrint("ConfigSize = %X\n",ConfigSize);
+
+#endif
+ for (Index = 0; Index < ConfigSize; Index++) {
+ if (HalpROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
+ DbgPrint("HalpSaveConfig: Error Writing the Prom byte\n");
+ DbgPrint("ERROR: Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
+ ExFreePool(VolatileEisaData);
+ ExFreePool(VolatileConfig);
+ return EIO;
+ }
+ }
+
+#if DBG
+ DbgPrint("HalpSaveConfig: Wrote Config data to rom\n");
+
+
+ DbgPrint("Writing Config Checksum...\n");
+
+#endif
+ if (HalpConfigurationSetChecksum() != ESUCCESS) {
+ DbgPrint("HalpSaveConfig: Error setting checksum\n");
+ HalpROMSetReadMode((PUCHAR)NvConfiguration);
+ ExFreePool(VolatileEisaData);
+ ExFreePool(VolatileConfig);
+ return EIO;
+ }
+
+
+ //
+ // Free up the pool
+ //
+
+ ExFreePool(VolatileConfig);
+
+
+ /*
+ * If the PROM status is OK then update the environment
+ * variables. If *that* is done OK too, return ESUCCESS.
+ */
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Writing Environment Variables\n");
+
+#endif
+ if (HalpEnvironmentStore() != ESUCCESS) {
+ HalpROMSetReadMode((PUCHAR)NVRAM_CONFIGURATION);
+ return EIO;
+ }
+
+
+ //
+ // Write the eisa data back into the rom.
+ //
+
+ VChars = VolatileEisaData;
+ NvChars = (PUCHAR)&NvConfiguration->EisaData[0];
+
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: Writing Eisa Data to Prom\n");
+
+ DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
+ DbgPrint("ConfigSize = %X\n",EisaSize);
+
+#endif
+ for (Index = 0; Index < EisaSize; Index++) {
+ if (HalpROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
+ return EIO;
+ }
+ }
+
+
+ if (HalpEisaSetChecksum() != ESUCCESS) {
+ HalpROMSetReadMode((PUCHAR)NVRAM_CONFIGURATION);
+ return EIO;
+ }
+
+
+ //
+ // Free up the pool
+ //
+
+ ExFreePool(VolatileEisaData);
+
+ HalpROMSetReadMode((PUCHAR)NVRAM_CONFIGURATION);
+
+ //
+ // Re-read the prom block back into pool for later use
+ //
+
+#if DBG
+ DbgPrint("HalpSaveConfiguration: ReLoading Environment\n");
+
+#endif
+ HalpEnvironmentLoad();
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+HalpConfigurationSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the configuration checksum.
+
+ This has been coded for Alpha/Jensen. It assumes that the
+ block containing the checksum has already been erased and
+ written to, and that the status of these previous operations
+ has already been checked. This is because we have to set the
+ PROM into ReadArray mode in order to compute the checksum,
+ and this will cause previous status to be lost.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. The PROM status is *not* checked by this function!
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1;
+ KIRQL OldIrql;
+
+#if DBG
+
+ DbgPrint("In set Config Checksum\n");
+
+#endif
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration;
+
+ HalpROMSetReadMode(NvChars);
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES +
+ LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA;
+ Index++ ) {
+ Checksum1 += READ_PORT_UCHAR( NvChars++ );
+ }
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Set checksum.
+ //
+
+ HalpROMResetStatus((PUCHAR)NvConfiguration);
+
+ if ((HalpROMByteWrite( &NvConfiguration->Checksum1[0],
+ (UCHAR)(Checksum1 & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum1[1],
+ (UCHAR)((Checksum1 >> 8) & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum1[2],
+ (UCHAR)((Checksum1 >> 16) & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum1[3],
+ (UCHAR)(Checksum1 >> 24)) != ESUCCESS)) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+
+
+}
+
+ARC_STATUS
+HalpEisaSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the eisa data checksum.
+
+ This has been coded for Alpha/Jensen. It assumes that the
+ block containing the checksum has already been erased and
+ written to, and that the status of these previous operations
+ has already been checked. This is because we have to set the
+ PROM into ReadArray mode in order to compute the checksum,
+ and this will cause previous status to be lost.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. The PROM status is *not* checked by this function!
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum3;
+ KIRQL OldIrql;
+
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum3 = 0;
+ NvChars = (PUCHAR)&NvConfiguration->EisaData[0];
+
+ HalpROMSetReadMode(NvChars);
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_EISA_DATA;
+ Index++ ) {
+ Checksum3 += READ_PORT_UCHAR( NvChars++ );
+ }
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Set checksum.
+ //
+
+
+ HalpROMResetStatus((PUCHAR)&NvConfiguration->EisaData[0]);
+
+ if ((HalpROMByteWrite( &NvConfiguration->Checksum3[0],
+ (UCHAR)(Checksum3 & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum3[1],
+ (UCHAR)((Checksum3 >> 8) & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum3[2],
+ (UCHAR)((Checksum3 >> 16) & 0xFF)) != ESUCCESS) ||
+ (HalpROMByteWrite( &NvConfiguration->Checksum3[3],
+ (UCHAR)(Checksum3 >> 24)) != ESUCCESS)) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+
+
+}
+
+VOID
+HalpInitializePromTimer(
+ IN OUT PPROMTIMER PrmTimer,
+ IN PVOID FunctionContext
+ )
+/*++
+
+Routine Description:
+
+ This routine will initialize the timer needed for waits on prom updates
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Initialize the signaling event
+ //
+
+ KeInitializeEvent(
+ &PromEvent,
+ NotificationEvent,
+ FALSE
+ );
+
+ //
+ // Initialize the timer
+ //
+
+ KeInitializeTimer(
+ &(PrmTimer->Timer)
+ );
+
+
+ //
+ // Setup the DPC that will signal the event
+ //
+
+ KeInitializeDpc(
+ &(PrmTimer->Dpc),
+ (PKDEFERRED_ROUTINE)HalpPromDpcHandler,
+ FunctionContext
+ );
+
+
+ }
+
+VOID
+HalpSetPromTimer(
+ IN PPROMTIMER PrmTimer,
+ IN ULONG MillisecondsToDelay
+ )
+/*++
+
+Routine Description:
+
+ This routine will initialize the timer needed for waits on prom updates
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ LARGE_INTEGER FireUpTime;
+
+ if (MillisecondsToDelay == 0 ) {
+ MillisecondsToDelay = 1;
+ }
+
+ FireUpTime.LowPart = -10000 * MillisecondsToDelay;
+ FireUpTime.HighPart = -1;
+
+ //
+ // Set the timer
+ //
+
+ KeSetTimer(
+ &PrmTimer->Timer,
+ FireUpTime,
+ &PrmTimer->Dpc
+ );
+}
+
+VOID
+HalpPromDpcHandler(
+ IN PVOID SystemSpecific,
+ IN PVOID Context,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+ )
+/*++
+
+Routine Description:
+
+ This routine is the DPC handler for the prom timer
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER(SystemSpecific);
+ UNREFERENCED_PARAMETER(SystemArgument1);
+ UNREFERENCED_PARAMETER(SystemArgument2);
+
+
+ //
+ // Set the event so the waiting thread will continue.
+ //
+
+ KeSetEvent(
+ &PromEvent,
+ 0L,
+ FALSE
+ );
+
+ return;
+}
+
+VOID
+HalpPromDelay(
+ IN ULONG Milliseconds
+ )
+/*++
+
+Routine Description:
+
+ This routine calls the timer and waits for it to fire
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LARGE_INTEGER TimeOut;
+ NTSTATUS status;
+
+ TimeOut.LowPart = -10000 * (Milliseconds * 2);
+ TimeOut.HighPart = -1;
+
+
+ //
+ // Start the timer
+ //
+
+ HalpSetPromTimer(&PromTimer, Milliseconds);
+
+ //
+ // Wait for the event to be signaled
+ //
+
+ status =
+ KeWaitForSingleObject(
+ &PromEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ &TimeOut
+ );
+
+ //
+ // Reset the event
+ //
+
+ KeResetEvent(
+ &PromEvent
+ );
+
+
+ return;
+}
diff --git a/private/ntos/nthals/hal0jens/alpha/xxhalp.h b/private/ntos/nthals/hal0jens/alpha/xxhalp.h
new file mode 100644
index 000000000..f77348016
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/xxhalp.h
@@ -0,0 +1,74 @@
+/*
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ xxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Alpha non-platform specific interfaces, defines and structures.
+
+Author:
+
+ Jeff McLeman (mcleman) 09-Jul-92
+
+
+Revision History:
+
+--*/
+
+
+#ifndef _XXHALP_
+#define _XXHALP_
+
+
+
+//
+// Determine if an virtual address is really a physical address.
+//
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+
+extern BOOLEAN LessThan16Mb;
+
+VOID
+HalpHalt(
+ VOID
+ );
+
+VOID
+HalpImb(
+ VOID
+ );
+
+VOID
+HalpMb(
+ VOID
+ );
+
+VOID
+HalpCachePcrValues(
+ VOID
+ );
+
+ULONG
+HalpRpcc(
+ VOID
+ );
+
+ULONG
+HalpGetTrapFrame (
+ VOID
+ );
+
+VOID
+HalpStallExecution(
+ ULONG Microseconds
+ );
+
+#endif // _XXHALP_
diff --git a/private/ntos/nthals/hal0jens/alpha/xxinithl.c b/private/ntos/nthals/hal0jens/alpha/xxinithl.c
new file mode 100644
index 000000000..bcef74730
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/xxinithl.c
@@ -0,0 +1,606 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "jxisa.h"
+#include "jnsnrtc.h"
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+
+typedef
+BOOLEAN
+KBUS_ERROR_ROUTINE (
+ IN struct _EXCEPTION_RECORD *ExceptionRecord,
+ IN struct _KEXCEPTION_FRAME *ExceptionFrame,
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+KBUS_ERROR_ROUTINE HalMachineCheck;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz;
+
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+ HalpMapIoSpace();
+ HalpInitializeInterrupts();
+ HalpCreateDmaStructures();
+ HalpInitializeDisplay(LoaderBlock);
+ HalpCachePcrValues();
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Establish the machine check handler for in the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ //
+ // Now alocate a mapping buffer for buffered DMA.
+ //
+
+ LessThan16Mb = FALSE;
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_ISA_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+ HalpMapBufferSize = 0;
+ }
+
+ //
+ // Setup special memory AFTER we've allocated our COMMON BUFFER!
+ //
+
+ HalpInitializeSpecialMemory( LoaderBlock );
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpCalibrateStall();
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Allocate pool for evnironment variable support
+ //
+
+ if (HalpEnvironmentInitialize() != 0) {
+ HalDisplayString(" No pool available for Environment Variables\n");
+ }
+
+ return TRUE;
+
+ }
+}
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ return FALSE;
+}
+VOID
+HalpVerifyPrcbVersion ()
+{
+
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return ((Count2 - Count1)*(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the performance counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+}
+
+#if 0
+VOID
+HalpGatherProcessorParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
diff --git a/private/ntos/nthals/hal0jens/alpha/xxmemory.c b/private/ntos/nthals/hal0jens/alpha/xxmemory.c
new file mode 100644
index 000000000..131517d8a
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/xxmemory.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow tha HAL to map physical memory
+
+Author:
+
+ Jeff McLeman (DEC) 11-June-1992
+
+Environment:
+
+ Phase 0 initialization only
+
+--*/
+
+#include "halp.h"
+
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The pyhsical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+
+ PhysicalAddress =
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) << PAGE_SHIFT;
+
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // orgial block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+ return PhysicalAddress;
+}
+
+
diff --git a/private/ntos/nthals/hal0jens/alpha/xxreturn.c b/private/ntos/nthals/hal0jens/alpha/xxreturn.c
new file mode 100644
index 000000000..911a4dc1f
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/xxreturn.c
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ xxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+ Stolen wholesale from s3return.c in ../mips.
+ Assumes that the firmware entry vector defined in the HAL spec has
+ been set up and is reachable through the System Parameter Block.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+ Miche Baker-Harvey (miche) 4-Jun-1992
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+Revision History:
+
+ 09-Jul-1992 Jeff McLeman (mcleman)
+ In all cases, except for ArcEnterInteractiveMode, invoke a
+ halt to restart the firmware. (Enter PAL)
+ 04-Mar-1993 Joe Mitchell (DEC)
+ Invoke a routine to call halt in ALL cases. Before calling this routine,
+ pass a value to the firmware indicating the desired function via
+ the Restart Block save area.
+
+--*/
+
+{
+ PALPHA_RESTART_SAVE_AREA AlphaSaveArea;
+ PRESTART_BLOCK RestartBlock;
+
+ //
+ // Check for a valid restart block.
+ //
+
+
+ if ((PCR->RestartBlock < (PVOID)(KSEG0_BASE) ) ||
+ (PCR->RestartBlock >= (PVOID)(KSEG2_BASE) ))
+ {
+ DbgPrint("**HalReturnToFirmware - Invalid PCR RestartBlock address\n");
+ //DbgBreakPoint();
+ HalpReboot();
+ }
+
+ RestartBlock = (PRESTART_BLOCK) PCR->RestartBlock;
+ AlphaSaveArea = (PALPHA_RESTART_SAVE_AREA) &RestartBlock->u.SaveArea;
+
+ //
+ // Reset video using NT driver's HwResetHw routine
+ //
+
+ HalpVideoReboot();
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine)
+ {
+ case HalHaltRoutine:
+ AlphaSaveArea->HaltReason = AXP_HALT_REASON_POWEROFF;
+ HalpReboot();
+ break;
+ case HalPowerDownRoutine:
+ AlphaSaveArea->HaltReason = AXP_HALT_REASON_POWERFAIL;
+ HalpReboot();
+ break;
+ case HalRestartRoutine:
+ AlphaSaveArea->HaltReason = AXP_HALT_REASON_RESTART;
+ HalpReboot();
+ break;
+ case HalRebootRoutine:
+ AlphaSaveArea->HaltReason = AXP_HALT_REASON_REBOOT;
+ HalpReboot();
+ break;
+ case HalInteractiveModeRoutine:
+ AlphaSaveArea->HaltReason = AXP_HALT_REASON_HALT;
+ HalpReboot();
+ break;
+ default:
+ HalDisplayString("Unknown ARCS restart function.\n");
+ DbgBreakPoint();
+ }
+
+ /* NOTREACHED */
+ HalDisplayString("Illegal return from ARCS restart function.\n");
+ DbgBreakPoint();
+}
diff --git a/private/ntos/nthals/hal0jens/drivesup.c b/private/ntos/nthals/hal0jens/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/hal0jens/hal.rc b/private/ntos/nthals/hal0jens/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/hal0jens/hal.src b/private/ntos/nthals/hal0jens/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/hal0jens/makefile b/private/ntos/nthals/hal0jens/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/hal0jens/makefile.inc b/private/ntos/nthals/hal0jens/makefile.inc
new file mode 100644
index 000000000..07fcc7d47
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/makefile.inc
@@ -0,0 +1,9 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\hal0jens.lib
+ copy $** $@
+
+$(TARGETPATH)\alpha\hal.dll: $(TARGETPATH)\alpha\hal0jens.dll
+ copy $** $@
+ binplace $(BINPLACE_FLAGS) $@
diff --git a/private/ntos/nthals/hal0jens/sources b/private/ntos/nthals/hal0jens/sources
new file mode 100644
index 000000000..fb87d538e
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/sources
@@ -0,0 +1,89 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=hal0jens
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+C_DEFINES=-D_JENSEN_ -DJENSEN -DEV4 -DEISA_PLATFORM
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\bldr;..\..\bldr\alpha;..\..\fw\alpha;..\..\fastfat
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\axlbsup.c \
+ alpha\axsysint.c \
+ alpha\bios.c \
+ alpha\ev4prof.c \
+ alpha\ev4ints.s \
+ alpha\jxbeep.c \
+ alpha\jxcalstl.c \
+ alpha\jxdisp.c \
+ alpha\jxhwsup.c \
+ alpha\jxhltsup.c \
+ alpha\idle.s \
+ alpha\jxinfo.c \
+ alpha\jxinitnt.c \
+ alpha\jxioacc.s \
+ alpha\jxmapio.c \
+ alpha\jxport.c \
+ alpha\jxtime.c \
+ alpha\jxusage.c \
+ alpha\xxmemory.c \
+ alpha\axebsup.c \
+ alpha\jxcache.c \
+ alpha\halpal.s \
+ alpha\jxvtisup.s \
+ alpha\xxenvirv.c \
+ alpha\jxprom.c \
+ alpha\xxinithl.c \
+ alpha\xxreturn.c \
+ alpha\jxmchk.c \
+ alpha\jxclock.c \
+ alpha\jxintsup.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/hal486c/drivesup.c b/private/ntos/nthals/hal486c/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/hal486c/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/hal486c/hal.rc b/private/ntos/nthals/hal486c/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/hal486c/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/hal486c/hal.src b/private/ntos/nthals/hal486c/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/hal486c/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/hal486c/i386/halnls.h b/private/ntos/nthals/hal486c/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/hal486c/i386/halp.h b/private/ntos/nthals/hal486c/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/hal486c/i386/ix8259.inc b/private/ntos/nthals/hal486c/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/hal486c/i386/ixbeep.asm b/private/ntos/nthals/hal486c/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixbusdat.c b/private/ntos/nthals/hal486c/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixclock.asm b/private/ntos/nthals/hal486c/i386/ixclock.asm
new file mode 100644
index 000000000..fa1155436
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixclock.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixclock.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixcmos.asm b/private/ntos/nthals/hal486c/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixcmos.inc b/private/ntos/nthals/hal486c/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/hal486c/i386/ixdat.c b/private/ntos/nthals/hal486c/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixenvirv.c b/private/ntos/nthals/hal486c/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixfirm.c b/private/ntos/nthals/hal486c/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixhwsup.c b/private/ntos/nthals/hal486c/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixidle.asm b/private/ntos/nthals/hal486c/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixinfo.c b/private/ntos/nthals/hal486c/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixipi.asm b/private/ntos/nthals/hal486c/i386/ixipi.asm
new file mode 100644
index 000000000..17eea3bf1
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixipi.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixipi.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixisa.h b/private/ntos/nthals/hal486c/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/hal486c/i386/ixisabus.c b/private/ntos/nthals/hal486c/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixisasup.c b/private/ntos/nthals/hal486c/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixkdcom.c b/private/ntos/nthals/hal486c/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixkdcom.h b/private/ntos/nthals/hal486c/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/hal486c/i386/ixnmi.c b/private/ntos/nthals/hal486c/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixpcibrd.c b/private/ntos/nthals/hal486c/i386/ixpcibrd.c
new file mode 100644
index 000000000..02fd82821
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixpcibrd.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixpcibus.c b/private/ntos/nthals/hal486c/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixpciint.c b/private/ntos/nthals/hal486c/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixphwsup.c b/private/ntos/nthals/hal486c/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixproc.c b/private/ntos/nthals/hal486c/i386/ixproc.c
new file mode 100644
index 000000000..1085a42d3
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixproc.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixsproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PC Compatible Eisa/Isa HAL (486 C Stepping)";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitOtherBuses (VOID);
+VOID HalpInitializePciBus (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ // do nothing
+ return TRUE;
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2();
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+}
+
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+
+VOID
+HalpMcaQueueDpc (
+ VOID
+ )
+{
+}
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/hal486c/i386/ixprofil.asm b/private/ntos/nthals/hal486c/i386/ixprofil.asm
new file mode 100644
index 000000000..c33b273ae
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixprofil.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixprofil.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixreboot.c b/private/ntos/nthals/hal486c/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixstall.asm b/private/ntos/nthals/hal486c/i386/ixstall.asm
new file mode 100644
index 000000000..115c6c9c1
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixstall.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixstall.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixswint.asm b/private/ntos/nthals/hal486c/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixswint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixswint.asm
diff --git a/private/ntos/nthals/hal486c/i386/ixsysbus.c b/private/ntos/nthals/hal486c/i386/ixsysbus.c
new file mode 100644
index 000000000..b4776da76
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixsysbus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixsysbus.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixthunk.c b/private/ntos/nthals/hal486c/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/hal486c/i386/ixusage.c b/private/ntos/nthals/hal486c/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/hal486c/i386/mcirql.asm b/private/ntos/nthals/hal486c/i386/mcirql.asm
new file mode 100644
index 000000000..a228d8702
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/mcirql.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halmca\i386\mcirql.asm
diff --git a/private/ntos/nthals/hal486c/i386/mcsysint.asm b/private/ntos/nthals/hal486c/i386/mcsysint.asm
new file mode 100644
index 000000000..079da5b7b
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/mcsysint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halmca\i386\mcsysint.asm
diff --git a/private/ntos/nthals/hal486c/i386/pcip.h b/private/ntos/nthals/hal486c/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/hal486c/i386/xxbiosa.asm b/private/ntos/nthals/hal486c/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/hal486c/i386/xxbiosc.c b/private/ntos/nthals/hal486c/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxdisp.c b/private/ntos/nthals/hal486c/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxflshbf.c b/private/ntos/nthals/hal486c/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxhal.c b/private/ntos/nthals/hal486c/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxhal.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxhal.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxioacc.asm b/private/ntos/nthals/hal486c/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/hal486c/i386/xxkdsup.c b/private/ntos/nthals/hal486c/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxmemory.c b/private/ntos/nthals/hal486c/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxstubs.c b/private/ntos/nthals/hal486c/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/hal486c/i386/xxtime.c b/private/ntos/nthals/hal486c/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/hal486c/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/hal486c/makefile b/private/ntos/nthals/hal486c/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/hal486c/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/hal486c/makefile.inc b/private/ntos/nthals/hal486c/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/hal486c/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/hal486c/sources b/private/ntos/nthals/hal486c/sources
new file mode 100644
index 000000000..bd53b19af
--- /dev/null
+++ b/private/ntos/nthals/hal486c/sources
@@ -0,0 +1,97 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=hal486c
+TARGETPATH=\nt\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixdat.c \
+ i386\ixinfo.c \
+ i386\ixisabus.c \
+ i386\ixpcibus.c \
+ i386\ixpciint.c \
+ i386\ixpcibrd.c \
+ i386\ixsysbus.c \
+ i386\ixclock.asm \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixipi.asm \
+ i386\mcirql.asm \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\ixnmi.c \
+ i386\ixphwsup.c \
+ i386\ixprofil.asm \
+ i386\ixproc.c \
+ i386\ixreboot.c \
+ i386\ixstall.asm \
+ i386\ixswint.asm \
+ i386\mcsysint.asm \
+ i386\ixthunk.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxhal.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\hal486c.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halacr/drivesup.c b/private/ntos/nthals/halacr/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halacr/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halacr/hal.rc b/private/ntos/nthals/halacr/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halacr/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halacr/hal.src b/private/ntos/nthals/halacr/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halacr/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halacr/makefile b/private/ntos/nthals/halacr/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halacr/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halacr/makefile.inc b/private/ntos/nthals/halacr/makefile.inc
new file mode 100644
index 000000000..12e9ae03a
--- /dev/null
+++ b/private/ntos/nthals/halacr/makefile.inc
@@ -0,0 +1,6 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halacr.lib
+ copy $** $@
+
diff --git a/private/ntos/nthals/halacr/mips/allstart.c b/private/ntos/nthals/halacr/mips/allstart.c
new file mode 100644
index 000000000..8d81b6eb8
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/allstart.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halacr/mips/cacherr.s b/private/ntos/nthals/halacr/mips/cacherr.s
new file mode 100644
index 000000000..0b3cdf5ce
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/cacherr.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\cacherr.s"
diff --git a/private/ntos/nthals/halacr/mips/halp.h b/private/ntos/nthals/halacr/mips/halp.h
new file mode 100644
index 000000000..43dbaf26f
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/halp.h
@@ -0,0 +1,139 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "jazzdef.h"
+#include "jazzdma.h"
+#include "jazzint.h"
+#include "hal.h"
+#include "jxhalp.h"
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+//
+// Define external references.
+//
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halacr/mips/hm.h b/private/ntos/nthals/halacr/mips/hm.h
new file mode 100644
index 000000000..a534ac4a4
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/hm.h
@@ -0,0 +1,487 @@
+/*++
+
+Copyright (c) 1994 NeTpower, Inc.
+Copyright (c) 1992 Pellucid, inc.
+
+Module Name:
+
+ hm.h
+
+Abstract:
+
+ Hm board register definitions.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef __HM_H__
+#define __HM_H__
+
+
+//
+// Addresses used for accessing hardware.
+//
+
+#define PEL_GFX1_PBASE 0x40000000
+#define PEL_GFX1_SIZE 0x01100000
+
+//
+// Define for write buffer flushing.
+//
+#define FLUSHIO()
+
+//
+// Cursor chip registers.
+//
+
+typedef struct
+{
+ volatile ULONG jAddressLo; // Address low
+ volatile ULONG jAddressHi; // Address high
+ volatile ULONG jGlyph; // Glyph data
+ volatile ULONG jControl; // Control
+}
+CURSOR, * PCURSOR;
+
+//
+// Control register offsets.
+//
+
+#define CURS_CMD 0
+#define CURS_XLO 1
+#define CURS_XHI 2
+#define CURS_YLO 3
+#define CURS_YHI 4
+#define CURS_WINXLO 5
+#define CURS_WINXHI 6
+#define CURS_WINYLO 7
+#define CURS_WINYHI 8
+#define CURS_WINWLO 9
+#define CURS_WINWHI 10
+#define CURS_WINHLO 11
+#define CURS_WINHHI 12
+
+//
+// Cursor chip commands.
+//
+
+#define CURS_BLOCK 0x40
+#define CURS_CROSS 0x20
+#define CURS_FMT 0x01
+#define CURS_1TO1MUX 0x00
+#define CURS_4TO1MUX 0x04
+#define CURS_5TO1MUX 0x08
+
+//
+// Cursor offsets for different monitor types.
+//
+
+#define CURS_XHOTOFF 31
+#define CURS_YHOTOFF 32
+#define CURS_XOFF_60HZ 221
+#define CURS_YOFF_60HZ 998
+#define CURS_XOFF_30HZ 39
+#define CURS_YOFF_30HZ 18
+#define CURS_XOFF_NTSC 25
+#define CURS_YOFF_NTSC 437
+#define CURS_XOFF_PAL 57
+#define CURS_YOFF_PAL 535
+
+//
+// RAMDAC registers.
+//
+
+typedef struct
+{
+ volatile ULONG jRamDacAddress; // RAMDAC address;
+ volatile ULONG jPalette; // Color palette RAM
+ volatile ULONG jData; // Data register for RAMDAC address
+ volatile ULONG jOverlayPalette; // Overlay palette RAM
+}
+RAMDAC, * PRAMDAC;
+
+//
+// RAMDAC definitions.
+//
+
+#define DAC_READMASK 0x04
+#define DAC_BLINKMASK 0x05
+#define DAC_CMD 0x06
+#define DAC_TEST 0x07
+
+//
+// DAC command bit definitions.
+//
+
+#define DAC_5TO1MUX 0x80
+#define DAC_PALENABLE 0x40
+#define DAC_BLINK0 0x00
+#define DAC_BLINK1 0x10
+#define DAC_BLINK2 0x20
+#define DAC_BLINK3 0x30
+#define DAC_OL1BLINKENABLE 0x08
+#define DAC_OL0BLINKENABLE 0x04
+#define DAC_OL1ENABLE 0x02
+#define DAC_OL0ENABLE 0x01
+
+#define CURSOR_WIDTH 32
+#define CURSOR_HEIGHT 32
+#define CURSOR_MAXIMUM ((CURSOR_WIDTH / 8) * CURSOR_HEIGHT)
+
+//
+// Offsets within the graphics space.
+//
+
+#define HM_RGB_LINEAR 0x00000000
+#define HM_REG_OFF 0x01000000
+#define HM_RGB_Y0 (HM_REG_OFF + 0x00000000)
+#define HM_RGB_Y1 (HM_REG_OFF + 0x00010000)
+#define HM_BLK_Y0 (HM_REG_OFF + 0x00020000)
+#define HM_BLK_Y1 (HM_REG_OFF + 0x00030000)
+#define HM_BLTLOAD_Y0 (HM_REG_OFF + 0x00040000)
+#define HM_BLTLOAD_Y1 (HM_REG_OFF + 0x00050000)
+#define HM_BLTSTORE_Y0 (HM_REG_OFF + 0x00060000)
+#define HM_BLTSTORE_Y1 (HM_REG_OFF + 0x00070000)
+#define HM_BT457 (HM_REG_OFF + 0x00080000)
+#define HM_BT431 (HM_REG_OFF + 0x00090000)
+#define HM_COLOR (HM_REG_OFF + 0x000A0000)
+#define HM_WRITEMASK (HM_REG_OFF + 0x000B0000)
+#define HM_Y0 (HM_REG_OFF + 0x000C0000)
+#define HM_Y1 (HM_REG_OFF + 0x000C0004)
+#define HM_GENERAL (HM_REG_OFF + 0x000D0000)
+#define HM_VIDTIM (HM_REG_OFF + 0x000E0000)
+#define HM_CLRINTR (HM_REG_OFF + 0x000F0000)
+
+// general control/status bit assignments
+
+#define G_REDLANE 0x00000003
+#define G_GRNLANE 0x0000000C
+#define G_BLULANE 0x00000030
+#define G_MODE1280 0x00000040 /* 1=1280/1024, 0=1024/768 */
+#define G_FASTREF 0x00000080 /* always 0 */
+#define G_MASKVINTR 0x00000100 /* 0=vertical retrace intr enabled */
+#define G_VGAPASS 0x00000200 /* 1 = VGA passthrough enabled */
+#define G_RST439 0x00000400 /* 0 = reset BT439 chip */
+#define G_SYNCPOL 0x00000800 /* 0 = active high, 1 = active low */
+#define G_UCTRL2 0x00001000 /* unused */
+#define G_SEL1 0x00002000 /* ICD2062 SEL1 pin */
+#define G_SEL0 0x00004000 /* ICD2062 SEL0 pin */
+#define G_NOSYNCGRN 0x00008000 /* 1 = disable sync on green channel */
+#define G_BLKSENSE 0x00010000 /* ??? */
+#define G_WAIT2 0x00020000 /* 1 = 0 wait states */
+#define G_WAIT3 0x00040000 /* 1 = 1 wait state */
+#define G_IRQSEL1 0x00080000 /* IRQSEL[1:0] 11 = IRQ 7 10 = IRQ 11
+#define G_IRQSEL0 0x00100000 /* 01 = IRQ 10 00 = IRQ 9(2)
+#define G_RAWINTR 0x00200000 /* raw value of vertical interrupt */
+#define G_USTAT1 0x00400000 /* unused */
+#define G_USTAT0 0x00800000 /* ICD2062 ERR* pin */
+
+//
+// Define the write-only Control Port (Port 1) bits.
+//
+
+#define CP_PORT_EN 0x01 // Port enable - enable this port if = 1.
+#define CP_HUE_EN 0x02 // HUE-1 enable - enable the HUE ASIC if = 1.
+#define CP_NVRAM_CLK 0x04 // NVRAM clock (sk) signal.
+#define CP_NVRAM_EN 0x08 // NVRAM enable (cs) signal.
+#define CP_NVRAM_DATA 0x10 // NVRAM data out (do) signal.
+#define CP_HIRES_EN 0x20 // Hi-Resolution enable - goto hires if = 1.
+
+//
+// Define the read-only Status Port (Port 0 or 1) bits.
+//
+
+#define SP_SIGNATURE_MASK 0x0F // Signature mask.
+#define SP_SIGNATURE 0x0A // Signature (4 bits).
+#define SP_NVRAM_DATA 0x10 // NVRAM di (data in) signal.
+#define SP_HIRES_EN 0x20 // Hi-resolution enable - goto hires if = 1.
+#define SP_PORT_SEL_MASK 0xC0 // I/O port select lines
+#define SP_PORT_SEL_0 0x00 // 00 = Port Choice 0 = 0538h-0539h.
+#define SP_PORT_SEL_1 0x40 // 40 = Port Choice 1 = 0E88h-0E89h.
+#define SP_PORT_SEL_2 0x80 // 80 = Port Choice 2 = 0F48h-0F49h.
+#define SP_PORT_SEL_3 0xC0 // C0 = Port Choice 3 = 060Ch-060Dh.
+
+
+//
+// Define device extension structure.
+//
+
+typedef struct _HW_DEVICE_EXTENSION
+{
+ PHYSICAL_ADDRESS PhysicalGraphicsAddress0;
+ ULONG GraphicsLength0;
+
+ USHORT HorizontalResolution;
+ USHORT HorizontalScreenSize;
+ USHORT VerticalResolution;
+ USHORT VerticalScreenSize;
+
+ ULONG fxVBase;
+ ULONG NumAvailableModes;
+ ULONG iCurrentMode;
+
+ PVOID VideoAddress;
+}
+HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
+
+//
+// This is the mode structure definitions.
+//
+
+// temporary - 3/9/93 - roey - used to hardcode certain values
+
+#define HM_GFX_IRQ 11 // vertical retrace IRQ
+#define HM_GFX_IRQ_SEL G_IRQSEL1 // GENERAL REG IRQ select lines
+ // IRQ 11 : sel1 = 1, sel0 = 0
+#define HM_MAPPING_PORT ((PUCHAR)0x538) // The framebuffer mapping I/O port.
+#define HM_CONTROL_PORT ((PUCHAR)0x539) // The control I/O port.
+
+typedef struct _VIDEO_MODE_INFORMATION {
+ ULONG Length;
+ ULONG ModeIndex;
+ ULONG VisScreenWidth;
+ ULONG VisScreenHeight;
+ ULONG ScreenStride;
+ ULONG NumberOfPlanes;
+ ULONG BitsPerPlane;
+ ULONG Frequency;
+ ULONG XMillimeter;
+ ULONG YMillimeter;
+ ULONG NumberRedBits;
+ ULONG NumberGreenBits;
+ ULONG NumberBlueBits;
+ ULONG RedMask;
+ ULONG GreenMask;
+ ULONG BlueMask;
+ ULONG AttributeFlags;
+ ULONG VideoMemoryBitmapWidth;
+ ULONG VideoMemoryBitmapHeight;
+} VIDEO_MODE_INFORMATION, *PVIDEO_MODE_INFORMATION;
+
+typedef struct {
+ ULONG mClkData,
+ vClkData;
+} MVPG_ICD2062;
+
+typedef MVPG_ICD2062 *PMVPG_ICD2062;
+
+typedef struct {
+ ULONG hBlankOn,
+ hBlankOff,
+ hSyncOn,
+ hSyncOff,
+ vBlankOn,
+ vBlankOff,
+ vSyncOn,
+ vSyncOff;
+} MVPG_TIMINGS;
+
+typedef MVPG_TIMINGS *PMVPG_TIMINGS;
+
+typedef struct {
+ UCHAR szModeName[32];
+ VIDEO_MODE_INFORMATION VideoModeInformation;
+ MVPG_TIMINGS mvpgTimings;
+ MVPG_ICD2062 mvpgIcd2062;
+ ULONG mvpgGeneralRegister;
+ ULONG Bt457CommandReg;
+
+} MVPG_MODE;
+
+typedef MVPG_MODE *PMVPG_MODE;
+
+BOOLEAN HmInitHw(PHW_DEVICE_EXTENSION);
+VOID VideoTiming(PHW_DEVICE_EXTENSION, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG);
+VOID InitHM(PHW_DEVICE_EXTENSION);
+VOID ResetBT439(PHW_DEVICE_EXTENSION);
+VOID Write_BT457(PHW_DEVICE_EXTENSION, ULONG, ULONG);
+VOID InitBT457(PHW_DEVICE_EXTENSION);
+VOID ProgramICD2062(PHW_DEVICE_EXTENSION, ULONG, ULONG);
+
+/***************************************************************************
+ *
+ * NeTpower NeTgraphics 1280 mode tables.
+ *
+ * Created:
+ * August 27, 1993 -by- Jeffrey Newman (NewCon)
+ *
+ * Copyright (c) Newman Consulting 1993
+ * Copyright (c) Media Vision 1993
+ ***************************************************************************/
+
+MVPG_MODE aMvpgModes[] = {
+ {
+ {"1280X1024X32bpp@60Hz"},
+ { sizeof(VIDEO_MODE_INFORMATION),
+ 0,
+ 1280,
+ 1024,
+ 2048 * 4,
+ 1,
+ 32,
+ 60,
+ 800,
+ 600,
+ 8,
+ 8,
+ 8,
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF,
+#if 1
+ 0,
+#else
+ VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
+#endif
+ 1280,
+ 1024
+ },
+ {
+ 253,
+ 333,
+ 269,
+ 291,
+ 1023,
+ 1066,
+ 1024,
+ 1029
+ },
+ {
+ 0x000f71a0 | (3 << 21),
+ 0x00183002
+ },
+ {
+ 0x06 | // Define byte lanes as RGB, from LSB to MSB.
+ G_MODE1280 | // Select 1280x1024 mode.
+ G_MASKVINTR | // Mask off the vertical retrace interrupt.
+ G_RST439 | // Stop resetting the BT439 chip.
+ G_SYNCPOL | // Sync polarity is active low.
+ G_WAIT3 | // Select 0 wait states.
+ G_NOSYNCGRN | // Disable sync on green channel.
+ HM_GFX_IRQ_SEL // Select vertical retrace IRQ.
+ },
+ {
+ 0xC0C0C0
+ }
+ },
+
+ {
+ {"1024X768X32bpp@60Hz"},
+ { sizeof(VIDEO_MODE_INFORMATION),
+ 1,
+ 1024,
+ 768,
+ 2048 * 4,
+ 1,
+ 32,
+ 60,
+ 800,
+ 600,
+ 8,
+ 8,
+ 8,
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF,
+#if 1
+ 0,
+#else
+ VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
+#endif
+ 1024,
+ 768
+ },
+ {
+ 253,
+ 330,
+ 268,
+ 294,
+ 768,
+ 805,
+ 770,
+ 776
+ },
+ {
+ 0x000f71a0 | (3 << 21),
+ 0x00068c0f
+ },
+ {
+ 0x06 | // Define byte lanes as RGB, from LSB to MSB.
+ G_MASKVINTR | // Mask off the vertical retrace interrupt.
+ G_RST439 | // Stop resetting the BT439 chip.
+ G_SYNCPOL | // Sync polarity is active low.
+ G_WAIT3 | // Select 0 wait states.
+ G_NOSYNCGRN | // Disable sync on green channel.
+ HM_GFX_IRQ_SEL // Select vertical retrace IRQ.
+ },
+ {
+ 0x404040
+ }
+ },
+
+ {
+ // This is a special debug mode that returns a 1024 mode
+ // to the display driver, but really sets the chip to 1280 mode.
+
+ {"1024X768X32bpp@70Hz"},
+ { sizeof(VIDEO_MODE_INFORMATION),
+ 2,
+ 1024,
+ 768,
+ 2048 * 4,
+ 1,
+ 32,
+ 70,
+ 800,
+ 600,
+ 8,
+ 8,
+ 8,
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF,
+#if 1
+ 0,
+#else
+ VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
+#endif
+ 1024,
+ 768
+ },
+ {
+ 253,
+ 333,
+ 269,
+ 291,
+ 1023,
+ 1066,
+ 1024,
+ 1029
+ },
+ {
+ 0x000f71a0 | (3 << 21),
+ 0x00183002
+ },
+ {
+ 0x06 | // Define byte lanes as RGB, from LSB to MSB.
+ G_MODE1280 | // Select 1280x1024 mode.
+ G_MASKVINTR | // Mask off the vertical retrace interrupt.
+ G_RST439 | // Stop resetting the BT439 chip.
+ G_SYNCPOL | // Sync polarity is active low.
+ G_WAIT3 | // Select 0 wait states.
+ G_NOSYNCGRN | // Disable sync on green channel.
+ HM_GFX_IRQ_SEL // Select vertical retrace IRQ.
+ },
+ {
+ 0xC0C0C0
+ }
+ }
+
+};
+
+#endif // __HM_H__
diff --git a/private/ntos/nthals/halacr/mips/j4cache.s b/private/ntos/nthals/halacr/mips/j4cache.s
new file mode 100644
index 000000000..98332fb3b
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/j4cache.s
@@ -0,0 +1,963 @@
+#if defined(R4000)
+
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30: j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,ZpA1(sp) // get old color value
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
+
+#endif
diff --git a/private/ntos/nthals/halacr/mips/j4flshbf.s b/private/ntos/nthals/halacr/mips/j4flshbf.s
new file mode 100644
index 000000000..ff3a32f78
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/j4flshbf.s
@@ -0,0 +1,61 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halacr/mips/j4flshio.c b/private/ntos/nthals/halacr/mips/j4flshio.c
new file mode 100644
index 000000000..f9ab38430
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/j4flshio.c
@@ -0,0 +1,207 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, export or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then export the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halacr/mips/j4prof.c b/private/ntos/nthals/halacr/mips/j4prof.c
new file mode 100644
index 000000000..3fa8ecc4d
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/j4prof.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter;
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter;
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ HalpPerformanceCounter.QuadPart = 0;
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halacr/mips/jazzs32.h b/private/ntos/nthals/halacr/mips/jazzs32.h
new file mode 100644
index 000000000..1ed59420d
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jazzs32.h
@@ -0,0 +1,745 @@
+/*++
+
+Copyright (c) 1992 ACER Labs Inc.
+
+Module Name:
+
+ jazzs32.h
+
+Abstract:
+
+ This header file defines the S3 86C911 GUI accelerator registers.
+
+Author:
+
+ Version 1.0 Kevin Chen 2-Apr-1992
+ Version 2.0 Andrew Chou Nov-24-1992
+
+--*/
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+UCHAR DAC_Table[64] = {
+ // DAC for mode 3
+ 0,16, 4,20, 1,17, 5,21,
+ 32,48,36,52,33,49,37,53,
+ 8,24,12,28, 9,25,13,29,
+ 40,56,44,60,41,57,45,61,
+ 2,18, 6,22, 3,19, 7,23,
+ 34,50,38,54,35,51,39,55,
+ 10,26,14,30,11,27,15,31,
+ 42,58,46,62,43,59,47,63
+ };
+
+UCHAR DAC_Color[4] = {0x00, 0x2a, 0x15, 0x3f};
+
+//
+// Define virtual address of the video memory and control registers.
+//
+// starting virtual memory address
+#define VIDEO_MEMORY_BASE 0X40000000
+
+// starting virtual control address
+#define VIDEO_CONTROL_BASE 0X40200000
+
+//
+// Define S3 register I/O Macros
+//
+PVOID VPORT;
+#define WRITE_S3_UCHAR(port,data) \
+ VPORT = (PVOID)(VIDEO_CONTROL_BASE+(port)); \
+ *((PUCHAR) VPORT) = (UCHAR)(data); \
+ KeFlushWriteBuffer()
+
+#define WRITE_S3_USHORT(port,data) \
+ VPORT = (PVOID)(VIDEO_CONTROL_BASE+(port)); \
+ *((PUSHORT) VPORT) = (USHORT)(data); \
+ KeFlushWriteBuffer()
+
+#define READ_S3_UCHAR(port) \
+ *(PUCHAR)(VPORT = (PVOID)(VIDEO_CONTROL_BASE+(port)))
+
+#define READ_S3_USHORT(port) \
+ *(PUSHORT)(VPORT = (PVOID)(VIDEO_CONTROL_BASE+(port)))
+
+#define READ_S3_VRAM(port) \
+ *(PUCHAR)(VPORT = (PVOID)(VIDEO_MEMORY_BASE+(port)))
+
+#define WRITE_S3_VRAM(port,data) \
+ VPORT = (PVOID)(VIDEO_MEMORY_BASE+(port)); \
+ *((PUCHAR) VPORT) = (UCHAR) (data); \
+ KeFlushWriteBuffer()
+
+#define DISPLAY_BITS_PER_PIXEL 8 // display bits per pixel
+#define NUMBER_OF_COLORS 256 // number of colors
+
+#define CURSOR_WIDTH 64 // width of hardware cursor
+#define CURSOR_HEIGHT 64 // height of hardware cursor
+#define CURSOR_BITS_PER_PIXEL 2 // hardware cursor bits per pixel
+
+//
+// S3 86C911 GUI, accelerator Video Controller Definitions.
+//
+// Define video register format.
+//
+#define PosID_LO 0x100 // R/W
+#define PosID_HI 0x101 // R/W
+#define Setup_OP 0x102 // R/W
+#define Chck_Ind 0x105 // R
+#define Mono_3B4 0x3B4 // R/W
+#define Mono_3B5 0x3B5 // R/W
+#define MDA_Mode 0x3B8 // W
+#define HGC_SLPEN 0x3B9 // R/W
+#define Stat1_MonoIn 0x3BA // R
+#define FC_MonoW 0x3BA // W
+#define HGC_CLPEN 0x3BB // W
+#define HGC_Config 0x3BF // W
+#define Attr_Index 0x3C0 // R/W
+#define Attr_Data 0x3C0 // R/W
+#define Stat0_In 0x3C2 // R
+#define MiscOutW 0x3C2 // W
+#define VSub_EnB 0x3C3 // R/W
+#define Seq_Index 0x3C4 // R/W
+#define Seq_Data 0x3C5 // R/W
+#define DAC_Mask 0x3C6 // R/W
+#define DAC_RIndex 0x3C7 // W
+#define DAC_Status 0x3C7 // W
+#define DAC_WIndex 0x3C8 // R/W
+#define DAC_Data 0x3C9 // R/W
+#define FC_Read 0x3CA // R
+#define MiscOutR 0x3CC // R
+#define GC_Index 0x3CE // R/W
+#define GC_Data 0x3CF // R/W
+#define S3_3D4_Index 0x3D4 // R/W
+#define S3_3D5_Data 0x3D5 // R/W
+
+#define CGA_Mode 0x3D8 // W
+#define CGA_Color 0x3D9 // W
+#define Stat1_In 0x3DA // R
+#define FC_Write 0x3DA // W
+#define CLPEN 0x3DB
+#define SLPEN 0x3DC
+
+//
+// Define Enhanced registers for S3_86C911
+//
+
+#define SUBSYS_STAT 0x42E8 // R
+#define SUBSYS_CNTL 0x42E8 // W
+#define SUBSYS_ENB 0x46E8 // R/W
+#define ADVFUNC_CNTL 0x4AE8 // W
+#define CUR_Y 0x82E8 // R/W
+#define CUR_X 0x86E8 // R/W
+#define DESTY 0x8AE8 // W
+#define AXIAL_STEP 0x8AE8 // W
+#define DESTX 0x8EE8 // W
+#define DIAG_STEP 0x8EE8 // W
+#define ERR_TERM 0x92E8 // R
+#define MAJ_AXIS_PCNT 0x96E8 // W
+#define RWIDTH 0x96E8 // W
+#define GP_STAT 0x9AE8 // R
+#define DRAW_CMD 0x9AE8 // W
+#define SHORT_STROKE 0x9EE8 // W
+#define BKGD_COLOR 0xA2E8 // W
+#define FRGD_COLOR 0xA6E8 // W
+#define WRITE_MASK 0xAAE8 // W
+#define READ_MASK 0xAEE8 // W
+#define BKGD_MIX 0xB6E8 // W
+#define FRGD_MIX 0xBAE8 // W
+#define MULTIFUNC_CNTL 0xBEE8 // W
+#define RHEIGHT 0xBEE8 // W
+#define PIX_TRANS 0xE2E8 // W
+
+
+//
+// Define Attribute Controller Indexes : ( out 3C0, Index )
+//
+
+#define PALETTE0 0
+#define PALETTE1 1
+#define PALETTE2 2
+#define PALETTE3 3
+#define PALETTE4 4
+#define PALETTE5 5
+#define PALETTE6 6
+#define PALETTE7 7
+#define PALETTE8 8
+#define PALETTE9 9
+#define PALETTE10 10
+#define PALETTE11 11
+#define PALETTE12 12
+#define PALETTE13 13
+#define PALETTE14 14
+#define PALETTE15 15
+#define ATTR_MODE_CTRL 16
+#define BORDER_COLOR 17
+#define COLOR_PLANE_ENABLE 18
+#define HORI_PIXEL_PANNING 19
+#define PIXEL_PADDING 20
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Define Graphics Controller Index ( out 3CE, Index )
+//
+
+#define SET_RESET 0
+#define ENABLE_SET_RESET 1
+#define COLOR_COMPARE 2
+#define DATA_ROTATE 3
+#define READ_PLANE_SELECT 4
+#define GRAPHICS_CTRL_MODE 5
+#define MEMORY_MAP_MODE 6
+#define COLOR_DONT_CARE 7
+#define BIT_MASK 8
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA S3 Indexes
+//
+#define S3R0 0x30
+#define S3R1 0x31
+#define S3R2 0x32
+#define S3R3 0x33
+#define S3R4 0x34
+#define S3R5 0x35
+#define S3R6 0x36
+#define S3R7 0x37
+#define S3R8 0x38
+#define S3R9 0x39
+#define S3R0A 0x3A
+#define S3R0B 0x3B
+#define S3R0C 0x3C
+#define SC0 0x40
+#define SC2 0x42
+#define SC3 0x43
+#define SC5 0x45
+
+//
+// Define System Control Indexes
+//
+#define SYS_CNFG 64
+#define SOFT_STATUS 65
+#define MODE_CTRL 66
+#define EXT_MODE 67
+#define HGC_MODE 69
+#define HGC_ORGX0 70
+#define HGC_ORGX1 71
+#define HGC_ORGY0 72
+#define HGC_ORGY1 73
+#define HGC_YSTART0 76
+#define HGC_YSTART1 77
+#define HGC_DISPX 78
+#define HGC_DISPY 79
+
+#define ENABLE_HARDWARE_CURSOR 1
+#define DISABLE_HARDWARE_CURSOR 0
+
+//
+// define advanced function control register structure
+//
+#define RES_640x480 0
+#define RES_1024x768 1
+#define RES_800x600 1
+
+#define ENABLE_VGA 6
+#define ENABLE_ENHANCED 7
+
+//
+// define draw command register values
+//
+#define NOP_COMMAND 0x0
+#define DRAW_LINE_COMMAND 0x2000
+#define RECTANGLE_FILL_COMMAND 0x4000
+#define BITBLT_COMMAND 0xc000
+#define BYTE_SWAP 0x1000
+#define NO_BYTE_SWAP 0x0
+#define SIXTEEN_BIT_BUS 0x0200
+#define EIGHT_BIT_BUS 0x0
+#define WAIT 0x0100
+#define NO_WAIT 0x0
+#define R0 0x0
+#define R45 0x20
+#define R90 0x40
+#define R135 0x60
+#define R180 0x80
+#define R225 0xa0
+#define R270 0xc0
+#define R315 0xe0
+#define XMAJ 0x0
+#define YMAJ 0x40
+#define XPositive 0x20
+#define YPositive 0x80
+#define XNegative 0x0
+#define YNegative 0x0
+
+#define DRAW_YES 0x10
+#define DRAW_NO 0x0
+#define RADIAL 8
+#define XY_BASE 0
+#define LAST_PIXEL_OFF 4
+#define LAST_PIXEL_ON 0
+#define MULTIPLE_PIXEL 2
+#define SINGLE_PIXEL 0
+#define DRAW_READ 0
+#define DRAW_WRITE 1
+
+#define SSV_DRAW 0x1000
+#define SSV_MOVE 0x0
+
+#define OneEmpty 0x80
+#define TwoEmpty 0x40
+#define ThreeEmpty 0x20
+#define FourEmpty 0x10
+#define FiveEmpty 0x8
+#define SixEmpty 0x4
+#define SevenEmpty 0x2
+#define EightEmpty 0x1
+
+#define BACKGROUND_COLOR 0
+#define FOREGROUND_COLOR 0x20
+#define CPU_DATA 0x40
+#define DISPLAY_MEMORTY 0x60
+#define NOT_SCREEN 0
+#define LOGICAL_ZERO 1
+#define LOGICAL_ONE 2
+#define LEAVE_ALONE 3
+#define NOT_NEW 4
+#define SCREEN_XOR_NEW 5
+#define NOT_SCREEN_XOR_NEW 6
+#define OVERPAINT 7 //( NEW )
+#define NOT_SCREEN_OR_NOT_NEW 8
+#define SCREEN_OR_NOT_NEW 9
+#define NOT_SCREEN_OR_NEW 10
+#define SCREEN_OR_NEW 11
+#define SCREEN_AND_NEW 12
+#define NOT_SCREEN_AND_NEW 13
+#define SCREEN_AND_NOT_NEW 14
+#define NOT_SCREEN_AND_NOT_NEW 15
+
+#define BEE8_1H 1
+#define BEE8_2H 2
+#define BEE8_3H 3
+#define BEE8_4H 4
+#define BEE8_0H 0
+#define L_CLIP 0x1000
+#define R_CLIP 0x2000
+#define B_CLIP 0x3000
+#define T_CLIP 0x4000
+
+#define DATA_EXTENSION 0xa000 // 10100000B
+#define CPU_EXT 0x80
+#define DISPLAY_EXT 0xc0
+#define NO_EXTENSION 0x0
+#define PACK_DATA 0x4
+#define NO_PACK_DATA 0x0
+#define SET_THIS_BIT_TO_ZERO 0;
+
+//
+// Define bits per pixel codes.
+//
+#define ONE_BIT_PER_PIXEL 0 // 1-bit per pixel
+#define TWO_BITS_PER_PIXEL 1 // 2-bits per pixel
+#define FOUR_BITS_PER_PIXEL 2 // 4-bits per pixel
+#define EIGHT_BITS_PER_PIXEL 3 // 8-bits per pixel
+
+//
+// Define address step value.
+//
+#define ADDRESS_STEP_INCREMENT 1 // vram transfer address increment
+
+//
+// Define cross hair thickness values.
+//
+#define ONE_PIXEL_THICK 0x0 // one pixel in thickness
+#define THREE_PIXELS_THICK 0x1 // three pixels in thickness
+#define FIVE_PIXELS_THICK 0x2 // five pixels in thickness
+#define SEVEN_PIXELS_THICK 0x3 // seven pixels in thickness
+
+//
+// Define multiplexer control values.
+//
+#define ONE_TO_ONE 0x0 // 1:1 multiplexing
+#define FOUR_TO_ONE 0x1 // 4:1 multiplexing
+#define FIVE_TO_ONE 0x2 // 5:1 multiplexing
+
+//
+// Define cursor origin values.
+//
+
+#define CURSOR_X_ORIGIN (((2*HORIZONAL_SYNC_VALUE)+BACK_PORCH_VALUE)*4-36)
+#define CURSOR_Y_ORIGIN ((VERTICAL_BLANK_VALUE/2)+24)
+
+ULONG HotspotX, HotspotY;
+
+// Extended VGA BIOS
+#define SUPER_VGA_SUPPORT 4FH
+#define RET_EXT_VGA_INFO 00H
+#define RET_EXT_VGA_MODE_INFO 01H
+#define SET_EXT_VGA_MODE 02H
+#define QUERY_CUR_EXT_VGA_MODE 03H
+
+#define SAVE_RESTORE_FUNCTION 04H
+// Function 04.0 Query Save/Restore Buffer Size
+#define GET_SAVE_BUFFER_SIZE 00H
+// Function 04.1 Save Extended Video state
+#define SAVE_STATE 01H
+// Function 04.2 Restore Extended VGA state
+#define RESTORE_STATE 02H
+
+#define WINDOWS_CONTROL 05H
+// Function 05.0 Set Window Control
+#define SELECT_PAGE_TO_BE_MAPPED 00H
+// fUNCTION 05.1 Get Window Control Setting
+#define GET_PAGE_MAPPED 01H
+
+#define SET_RESET_DUAL_DISPLAY_MODE FFH
+
+BOOLEAN ColorMonitor;
+PVOID S3_3x4, S3_3x5;
+UCHAR VideoParam[62] = {
+// Mode +3 480 Lines
+// External Registers 3C3, 3C2
+0x01,0x67,
+
+// CRT Controller Registers 3D4, 3D5
+0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,
+0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+
+// Sequencer Registers 3C4, 3C5
+// 0x01,0x01,0x03,0x00,0x02,
+0x01,0x20,0x03,0x00,0x02,
+
+// Graphic Control Registers
+0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff,
+
+// Attribute Controller Registers
+0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,
+0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00};
+
+
+UCHAR VGAFont8x16[4096] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00
+0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7E,0xFF,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // 8
+0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, // 9
+0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, // a
+0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, // 10
+0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, // 4
+0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 20
+0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // 1
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x18,0x18,0x7C,0xC6,0xC2,0x7C,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 30
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // b
+0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // 40
+0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 50
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // d
+0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, // f
+
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 60
+0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00, // 7
+0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // a
+0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 70
+0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, // 80
+0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, // 7
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // d
+0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // 90
+0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 8
+0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, // b
+0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, // f
+
+0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a0
+0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 1
+0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // 4
+0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 5
+0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, // b
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, // c
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // b0
+0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // 1
+0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // a
+0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // f
+
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c0
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // c
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // e
+0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d0
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 2
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // a
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // c
+0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // d
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // e
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, // e0
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00, // 1
+0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, // f0
+0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, // 3
+0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, // b
+0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // f
+ };
diff --git a/private/ntos/nthals/halacr/mips/jxbeep.c b/private/ntos/nthals/halacr/mips/jxbeep.c
new file mode 100644
index 000000000..f93411bd1
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxbeep.c
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeLowerIrql(oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halacr/mips/jxdisp.c b/private/ntos/nthals/halacr/mips/jxdisp.c
new file mode 100644
index 000000000..3816128fc
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxdisp.c
@@ -0,0 +1,1572 @@
+/*++
+
+Copyright (c) 1994 NeTpower, Inc.
+
+Module Name:
+
+jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for the NeTpower Series 100, 200, 300, Server 1000 with 805 S3 cards,
+ 928 S3 cards and the NeTpower NeTgraphics 1280 24-bit card. Since the
+ NeTpower machines are derived from the ACER PICA machines, this HAL will
+ work on those machines as well.
+
+Author:
+
+ Mike Dove (mdove), 28-Mar-94
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "vga.h"
+#include "string.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacter (
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayVGASetup (
+ VOID
+ );
+
+VOID
+HalpDisplayPG1280Setup(
+ VOID
+ );
+
+//
+// The video cards that we support
+//
+
+#define PICA_VGA 0
+#define PICA_PG1280 1
+#define ISA_VGA 2
+
+#define IS_DISPLAY_VGA ( HalpDisplayType == PICA_VGA || \
+ HalpDisplayType == ISA_VGA )
+#define IS_DISPLAY_PG1280 ( HalpDisplayType == PICA_PG1280 )
+
+//
+// Define virtual address of the video memory and control registers.
+// Video memory for the PICA S3 card and the PICA PG1280 card are
+// at 40000000. The PICA S3 card has its Control space at 60000000.
+// When an S3 card is on the ISA bus, its Memory is at 91000000 and the
+// Control Space is at 90000000.
+//
+
+ULONG VideoMemoryVirtualBase[] = {
+ 0x40000000, // PICA VGA
+ 0x40000000, // PICA PG1280 card
+ 0x40000000 // ISA VGA
+ };
+
+ULONG VideoMemoryPhysicalBase[] = {
+ 0x40000000, // PICA VGA
+ 0x40000000, // PICA PG1280 card
+ 0x91000000 // ISA VGA
+ };
+
+ULONG ControlMemoryVirtualBase[] = {
+ 0x40200000, // PICA VGA
+ 0x41000000, // PICA PG1280 card
+ 0x40200000 // ISA VGA
+ };
+
+ULONG ControlMemoryPhysicalBase[] = {
+ 0x60000000, // PICA VGA
+ 0x41000000, // PICA PG1280 card
+ 0x90000000 // ISA VGA
+ };
+
+ULONG VideoMemoryBase[] = {
+ 0x400b8000, // PICA VGA
+ 0x40000000, // PICA PG1280
+ 0x400b8000, // ISA VGA
+ };
+
+//
+// The PICA S3 card simply needs a single PDE page, while the PG1280
+// card needs 5 PDE's...
+//
+
+ULONG PDEPages[] = {
+ 1, // PICA VGA
+ 5, // PICA PG1280 card
+ 1, // ISA VGA
+ };
+
+#define MAX_PDE_PAGES 5
+
+#define PG1280_PALETTE_BLUE 0x000000B0
+#define PG1280_PALETTE_HI_WHITE 0xFFFFFFFF
+
+//
+//
+//
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+
+//
+// Define static data.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+BOOLEAN HalpDisplayOwnedByHal;
+
+ENTRYLO HalpDisplayPte[MAX_PDE_PAGES];
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+
+ULONG HalpColumn;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+ULONG HalpDisplayText;
+ULONG HalpDisplayControlBase = 0;
+
+
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+ULONG HalpDisplayType = 0;
+
+//
+// Define macros for reading/writing VGA control and memory space.
+//
+
+#define VGA_CREAD ((volatile PVGA_READ_PORT) \
+ (ControlMemoryVirtualBase[HalpDisplayType]))
+#define VGA_CWRITE ((volatile PVGA_WRITE_PORT) \
+ (ControlMemoryVirtualBase[HalpDisplayType]))
+#define VIDEO_MEMORY ((volatile PUCHAR)(VideoMemoryBase[HalpDisplayType]))
+#define FONT_MEMORY ((volatile PUCHAR)(VideoMemoryVirtualBase[HalpDisplayType]\
+ + 0xA0000))
+
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+ ULONG PDECount;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "ALI_S3")) {
+
+ HalpDisplayType = PICA_VGA;
+ HalpDisplayControllerSetup = HalpDisplayVGASetup;
+ HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
+
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "S3" )) {
+
+ HalpDisplayType = ISA_VGA;
+ HalpDisplayControllerSetup = HalpDisplayVGASetup;
+ HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "PG1280P")) {
+
+ HalpDisplayType = PICA_PG1280;
+ HalpDisplayControllerSetup = HalpDisplayPG1280Setup;
+ HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
+ } else {
+ // Failure condition...
+ return FALSE;
+ }
+
+ Child = ConfigurationEntry->Child;
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+ if ( IS_DISPLAY_PG1280 ) {
+ HalpDisplayText = 768 / HalpCharacterHeight;
+ HalpScrollLine = 8192*HalpCharacterHeight;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayWidth = 1024 / HalpCharacterWidth;
+ } else {
+ // Assume VGA...
+ HalpDisplayText = 400 / HalpCharacterHeight;
+ HalpScrollLine = 160; // 80 characters + 80
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayWidth = 80;
+ }
+
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte[PDECount] = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ }
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VideoMemoryVirtualBase[HalpDisplayType]
+ >> (PDI_SHIFT - PTI_SHIFT)));
+
+ Pte.PFN = VideoMemoryPhysicalBase[HalpDisplayType] >> PAGE_SHIFT;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // page table entries of the video memory
+ //
+
+ for (Index = 0; Index < ( PDEPages[HalpDisplayType] *
+ (PAGE_SIZE / sizeof(ENTRYLO)) /
+ (HalpDisplayType != PICA_PG1280 ? 2 : 1));
+ Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if ( HalpDisplayType != PICA_PG1280 ) {
+ Pte.PFN = ControlMemoryPhysicalBase[HalpDisplayType] >> PAGE_SHIFT;
+
+ for ( Index = 0; Index < 0x10; Index+=1 ) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+ }
+
+ //
+ // Initialize the display controller.
+ //
+ HalpDisplayControllerSetup();
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+VOID
+HalpDisplayVGASetup (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA display controller chip on the PICA
+ or ISA bus.
+
+ Initialized configuration is to be:
+ 640 x 480
+ 80 x 33 characters (with 8x12 font), or 80 x 50 (with 8x8 font)
+ 16 colors
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+//
+// Initialize the VGA for either PICA or ISA VGA card. This routine is
+// generic VGA, and will attempt NOT to take advantage of any specific VGA
+// implementation. In order to have cleaner code, the eventual goal will be
+// to put the VGA in graphics mode, and address is the same way as a frame
+// buffer. In addition the font is passed to us by the OS loader, thus that
+// is taken care of.
+//
+// Note, that the register sets are loosely configured in order. The values
+// for these registers are taken from page 318 of the Programmers Guide to
+// the EGA and VGA cards, Second Edition by Richard E. Ferraro.
+//
+
+ ULONG RegisterIndex, RGBIndex, IndexI, IndexJ;
+ ULONG DoS3 = 1;
+ UCHAR Byte;
+ PUCHAR FontData;
+ UCHAR Character;
+ volatile PUCHAR MemoryByte;
+
+ // S3 - Put video subsystem into setup mode, and enable it...
+ if ( DoS3 ) {
+ VGA_CWRITE->VideoSubsystemEnable = ENTER_SETUP_MODE;
+ VGA_CWRITE->SetupOptionSelect = VIDEO_SUBSYSTEM_ALIVE;
+ VGA_CWRITE->VideoSubsystemEnable = ENABLE_VIDEO_SUBSYSTEM;
+
+ // The rest of the code in this if statement is to properly
+ // re-initalize the S3 chip specifically when coming from
+ // graphics mode (bug check for example).
+
+ // This DISABLES the Enhanced Functions...
+ VGA_CWRITE->AdvancedFunctionControl = 0x2;
+
+ // Unlock the register sets that need modification...
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_1;
+ VGA_CWRITE->CRTCData = 0x48;
+
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_2;
+ VGA_CWRITE->CRTCData = 0xa0;
+
+ // Re-initialize the S3 to a sane mode...
+ VGA_CWRITE->CRTCAddress = S3_MEMORY_CONFIGURATION;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_BACKWARD_COMPATIBILITY_3;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_CRT_REGISTER_LOCK;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_MISCELLANEOUS_1;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_MODE_CONTROL;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_HARDWARE_GRAPHICS_CURSOR;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_EXTENDED_MEMORY_CONTROL_1;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_EXTENDED_MEMORY_CONTROL_2;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_LINEAR_ADDRESS_WINDOW_LOW;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ // DISABLES access to Enhanced registers...
+ VGA_CWRITE->CRTCAddress = S3_SYSTEM_CONFIGURATION;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ // Lock the register sets that were modified...
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_2;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_1;
+ VGA_CWRITE->CRTCData = 0x0;
+ }
+
+ // Do initial synchronus reset...
+ VGA_CWRITE->SequencerAddress = SEQ_RESET;
+ VGA_CWRITE->SequencerData = SYNCHRONUS_RESET;
+
+ // Set up initial configuration using the Miscellaneous Output Register
+ VGA_CWRITE->MiscOutput = INITIAL_CONFIG;
+
+ // Do synchronus reset...
+ VGA_CWRITE->SequencerAddress = SEQ_RESET;
+ VGA_CWRITE->SequencerData = SYNCHRONUS_RESET;
+
+ // Set up Sequencer registers. Run through the array of data stuffing
+ // the values into the VGA. After the Sequencer values have been stuffed,
+ // we will return the VGA to normal operation.
+ for ( RegisterIndex = SEQ_CLOCKING_MODE; RegisterIndex <= SEQ_MEMORY_MODE;
+ RegisterIndex++ ) {
+
+ VGA_CWRITE->SequencerAddress = (UCHAR)RegisterIndex;
+ VGA_CWRITE->SequencerData = SequencerSetup[RegisterIndex];
+
+ }
+
+ // Next setup the CRT Controller registers. The registers 0-7 might
+ // be write-protected if bit 7 of the Vertical Retrace End register is
+ // set. First we will clear that bit, then set all the registers.
+
+ VGA_CWRITE->CRTCAddress = CRT_VERTICAL_RETRACE_END;
+ Byte = VGA_CREAD->CRTCData;
+ Byte &= 0x7f;
+ VGA_CWRITE->CRTCData = Byte;
+
+ // Adjust Maximum Scan Lines based on the size of the font passed in
+ // by the OSLOADER...
+
+ CRTCSetup[CRT_MAXIMUM_SCAN_LINE] = (UCHAR)(
+ ( CRTCSetup[CRT_MAXIMUM_SCAN_LINE] & 0xe0 ) |
+ ( ( HalpCharacterHeight - 1 ) & 0x1f ));
+
+ for ( RegisterIndex = CRT_HORIZONTAL_TOTAL;
+ RegisterIndex <= CRT_LINE_COMPARE; RegisterIndex++ ) {
+
+ VGA_CWRITE->CRTCAddress = (UCHAR)RegisterIndex;
+ VGA_CWRITE->CRTCData = CRTCSetup[RegisterIndex];
+
+ }
+
+ // Next setup the Graphics Controller registers. Straight from the
+ // table...
+
+ for ( RegisterIndex = GFX_SET_RESET; RegisterIndex <= GFX_BIT_MASK;
+ RegisterIndex++ ) {
+
+ VGA_CWRITE->GraphicsAddress = (UCHAR)RegisterIndex;
+ VGA_CWRITE->GraphicsData = GraphicsSetup[RegisterIndex];
+
+ }
+
+ // Next we need to setup the Attribute Controller registers. Instead
+ // of a separate Address and Data register, they are combined into a
+ // single register with its output directed by a two-state flip-flop.
+ // When the flip-flop is clear, the first write to the
+ // AttributeAddressAndData register is the index, and the second write
+ // is the data. In order to be sure the flip-flop is in a known state,
+ // we will clear it first by reading the InputStatus1 register...
+
+ for ( RegisterIndex = ATT_PALETTE_00; RegisterIndex <= ATT_COLOR_SELECT;
+ RegisterIndex++ ) {
+
+ Byte = VGA_CREAD->InputStatus1; // Reset flip-flop...
+ VGA_CWRITE->AttributeAddressAndData = (UCHAR)RegisterIndex;
+ KeStallExecutionProcessor(10);
+ VGA_CWRITE->AttributeAddressAndData = AttributeSetup[RegisterIndex];
+ KeStallExecutionProcessor(10);
+ VGA_CWRITE->AttributeAddressAndData = 0x20; // Return to normal mode
+
+ }
+
+ // Sequencer register setup, so return VGA to operation
+ VGA_CWRITE->SequencerAddress = SEQ_RESET;
+ VGA_CWRITE->SequencerData = NORMAL_OPERATION;
+
+ // Now that the Attribute and Color Palette registers are set up,
+ // now it is time to fill in the value into the Color registers.
+ // First initialize PEL Mask to FF as the BIOS would.
+
+ VGA_CWRITE->PELMask = 0xff;
+ VGA_CWRITE->PELAddressWriteMode = 0; // Set Index to 0...
+
+ for ( RegisterIndex = 0; RegisterIndex < 16; RegisterIndex++ ) {
+ for ( RGBIndex = 0; RGBIndex < 3; RGBIndex++ ) {
+
+ VGA_CWRITE->PELData = ColorValues[RegisterIndex][RGBIndex];
+
+ }
+ }
+
+ // Now we are ready to load the fonts into bit plane 2...
+
+ VGA_CWRITE->SequencerAddress = SEQ_MAP_MASK;
+ VGA_CWRITE->SequencerData = ENABLE_PLANE_2;
+
+ VGA_CWRITE->SequencerAddress = SEQ_MEMORY_MODE;
+ VGA_CWRITE->SequencerData = SEQUENTIAL_ADDRESSING | EXTENDED_MEMORY;
+
+ VGA_CWRITE->GraphicsAddress = GFX_MODE;
+ VGA_CWRITE->GraphicsData = WRITE_MODE_0;
+
+ VGA_CWRITE->GraphicsAddress = GFX_MISCELLANEOUS;
+ VGA_CWRITE->GraphicsData = MEMORY_MODE_1 | ALPHA_MODE;
+
+ // /**/VGA_CWRITE->GraphicsAddress = GFX_READ_MAP_SELECT;
+ // /**/VGA_CWRITE->GraphicsData = 0x2;
+
+ MemoryByte = FONT_MEMORY;
+
+ // Use font provided by OSLOADER...
+ for ( IndexI = 0; IndexI < 256; IndexI++ ) {
+ if (( IndexI < HalpFontHeader->FirstCharacter) ||
+ ( IndexI > HalpFontHeader->LastCharacter )) {
+ Character = HalpFontHeader->DefaultCharacter;
+ } else {
+ Character = (UCHAR)IndexI;
+ }
+ Character -= HalpFontHeader->FirstCharacter;
+ FontData = ((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ // Assumption, HalpCharacterHeight <= 16...
+ for ( IndexJ = 0; IndexJ < HalpCharacterHeight; IndexJ++ ) {
+ *MemoryByte = *FontData++;
+ MemoryByte++;
+ }
+ for ( IndexJ = HalpCharacterHeight; IndexJ < 32; IndexJ++ ) {
+ *MemoryByte = 0;
+ MemoryByte++;
+ }
+ }
+
+
+ // Now reload the default values into the above 4 registers...
+
+ VGA_CWRITE->SequencerAddress = SEQ_MAP_MASK;
+ VGA_CWRITE->SequencerData = SequencerSetup[SEQ_MAP_MASK];
+
+ VGA_CWRITE->SequencerAddress = SEQ_MEMORY_MODE;
+ VGA_CWRITE->SequencerData = SequencerSetup[SEQ_MEMORY_MODE];
+
+ VGA_CWRITE->GraphicsAddress = GFX_MODE;
+ VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_MODE];
+
+ VGA_CWRITE->GraphicsAddress = GFX_MISCELLANEOUS;
+ VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_MISCELLANEOUS];
+
+ // /**/VGA_CWRITE->GraphicsAddress = GFX_READ_MAP_SELECT;
+ // /**/VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_READ_MAP_SELECT];
+
+ // Now set the screen to blue... For the attribute byte, the upper 4 bits
+ // are the background color, while the low 4 bits are the foreground
+ // color...
+
+ MemoryByte = VIDEO_MEMORY;
+ for ( IndexI = 0; IndexI < (HalpDisplayWidth*HalpDisplayText*2);
+ IndexI++ ) {
+ *MemoryByte++ = SPACE;
+ *MemoryByte++ = ( ( COLOR_BLUE << 4 ) | COLOR_INTENSE_WHITE );
+ }
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[MAX_PDE_PAGES];
+ ULONG PDECount;
+
+ //
+ // Raise IRQL to the highest level, flush the TB, and map the display
+ // frame buffer into the address space of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+ SavedPte[PDECount] = *((PENTRYLO)(PDE_BASE |
+ (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc)));
+ }
+ KeFlushCurrentTb();
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+ *((PENTRYLO)(PDE_BASE |
+ (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte[PDECount];
+ }
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+
+ KeFlushCurrentTb();
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+ *((PENTRYLO)(PDE_BASE | (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte[PDECount];
+ }
+ KeLowerIrql(OldIrql);
+
+ return;
+} /* end of HalpDisplayString() */
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+SlowMoveMemory (
+ OUT PUCHAR Destination,
+ IN PUCHAR Source,
+ IN ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is a slower memory move routine for the PG1280P.
+ Scrolling performance of the HAL is not that critical. This routine
+ can be replace with a hardware scroll assist routine at a later date
+ if it is deemed important.
+
+--*/
+
+{
+ ULONG Index;
+
+ for ( Index = 0; Index < Count/4; Index++ ) {
+ *(PULONG)Destination = *(PULONG)Source;
+ Destination += 4;
+ Source += 4;
+ }
+}
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PUCHAR Destination;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ // Scroll the screen one line
+ if ( IS_DISPLAY_PG1280 ) {
+ SlowMoveMemory((PVOID)VideoMemoryVirtualBase[HalpDisplayType],
+ (PVOID)(VideoMemoryVirtualBase[HalpDisplayType]
+ + HalpScrollLine),
+ HalpScrollLength);
+
+ Destination = (PUCHAR)VideoMemoryVirtualBase[HalpDisplayType]
+ + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine/4; Index += 1) {
+ *(PULONG)Destination = PG1280_PALETTE_BLUE;
+ Destination+=4;
+ }
+ } else {
+
+ RtlMoveMemory((PVOID)VIDEO_MEMORY,
+ (PVOID)(VIDEO_MEMORY + HalpScrollLine),
+ HalpScrollLength);
+
+ Destination = (PUCHAR)VIDEO_MEMORY + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 2) {
+ *Destination++ = 0x20;
+ Destination++; // Skip attribute byte...
+ }
+ }
+
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ //
+ // Note, this is done a bit different than the original Jazz HAL. Here, we
+ // pass the address of the Character itself. Since this HAL supports a
+ // character based VGA, and a bit-mapped based 24-bit card, passing a
+ // pointer to the character itself is easier and makes the following code
+ // a bit easier to understand.
+ //
+
+ // Original Jazz
+ // Character -= HalpFontHeader->FirstCharacter;
+ // HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+
+ HalpOutputCharacter(&Character);
+ }
+
+ return;
+
+} /* end of HalpDisplayCharacter() */
+
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination, FontGlyph;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ if ( IS_DISPLAY_PG1280 ) {
+ FontGlyph =
+ (PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[(*Glyph)-
+ HalpFontHeader->FirstCharacter].Offset;
+ Destination = (PUCHAR)(VIDEO_MEMORY +
+ (HalpRow * HalpScrollLine) +
+ (HalpColumn * HalpCharacterWidth * 4));
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(FontGlyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ FontGlyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if ( FontValue >> 31 ) {
+ *(PULONG)Destination = PG1280_PALETTE_HI_WHITE;
+ }
+ Destination+=4;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (8192 - ( HalpCharacterWidth * 4 ) );
+ }
+
+ } else {
+ Destination = (PUCHAR)(VIDEO_MEMORY +
+ (HalpRow * HalpScrollLine) + (HalpColumn*2));
+ *Destination = *Glyph;
+
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+#include "hm.h"
+
+HW_DEVICE_EXTENSION MVHwDeviceExtension = { 0 };
+PHW_DEVICE_EXTENSION pMVHwDeviceExtension = &MVHwDeviceExtension;
+
+VOID
+HalpDisplayPG1280Setup (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the NeTpower NeTgraphics 1280 card on the
+ PICA bus.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PULONG Buffer;
+ ULONG Limit, Index;
+
+ //
+ // Put display into 1024x768 @ 60Hz mode. This is the least common
+ // denominator for systems this card will be put in.
+ //
+ pMVHwDeviceExtension->iCurrentMode = 1;
+ HmInitHw( pMVHwDeviceExtension );
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY;
+ Limit = ((8192 * 768) / sizeof(ULONG));
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = PG1280_PALETTE_BLUE;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+
+/***************************************************************************
+ *
+ **************************************************************************/
+BOOLEAN HmInitHw
+(
+ PHW_DEVICE_EXTENSION HwDeviceExtension
+)
+
+/*++
+
+Routine Description:
+
+ This routine does hardware initializtion for Harley.
+
+Arguments:
+
+ HwDeviceExtension - Supplies the miniport driver's adapter storage. This
+ storage is initialized to zero before this call.
+
+Return Value:
+
+ This routine must return:
+
+ TRUE - Harley was initialized.
+
+ FALSE - Harley not initialized.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS Address;
+ ULONG i;
+
+ //
+ // Map the framebuffer into the PICA virtual address space.
+ //
+
+ Address.HighPart = 0;
+ Address.LowPart = PEL_GFX1_PBASE;
+ HwDeviceExtension->fxVBase = (ULONG) VideoMemoryVirtualBase[PICA_PG1280];
+
+ i = HwDeviceExtension->iCurrentMode;
+
+ ProgramICD2062(HwDeviceExtension,
+ aMvpgModes[i].mvpgIcd2062.mClkData,
+ aMvpgModes[i].mvpgIcd2062.vClkData);
+
+ VideoTiming(HwDeviceExtension,
+ aMvpgModes[i].mvpgTimings.hBlankOn,
+ aMvpgModes[i].mvpgTimings.hBlankOff,
+ aMvpgModes[i].mvpgTimings.hSyncOn,
+ aMvpgModes[i].mvpgTimings.hSyncOff,
+ aMvpgModes[i].mvpgTimings.vBlankOn,
+ aMvpgModes[i].mvpgTimings.vBlankOff,
+ aMvpgModes[i].mvpgTimings.vSyncOn,
+ aMvpgModes[i].mvpgTimings.vSyncOff);
+
+ // program general config register in HUE
+
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) =
+ aMvpgModes[i].mvpgGeneralRegister;
+
+ // time delay to allow ECL clocks to fire up
+ // 1000 microseconds.
+
+ KeStallExecutionProcessor(1000);
+
+ /* program color ramps for DACs */
+ InitBT457(HwDeviceExtension);
+ ResetBT439(HwDeviceExtension);
+
+ *(PULONG)(HM_WRITEMASK + HwDeviceExtension->fxVBase) = 0xffffffff;
+
+ return(TRUE);
+}
+
+/***************************************************************************
+ * VideoTiming( hblankon, hblankoff, hsyncon, hsyncoff,
+ * vblankon, vblankoff, vsyncon, vsyncoff)
+ * This routine takes the monitor parameters (available from any
+ * monitor spec) and programs the video timing circuit appropriately.
+ ***************************************************************************/
+
+VOID VideoTiming
+(
+ PHW_DEVICE_EXTENSION HwDeviceExtension,
+ ULONG hblankon,
+ ULONG hblankoff,
+ ULONG hsyncon,
+ ULONG hsyncoff,
+ ULONG vblankon,
+ ULONG vblankoff,
+ ULONG vsyncon,
+ ULONG vsyncoff
+)
+{
+ /* write them out to F2D */
+
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[0] = hblankon;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[1] = hblankoff;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[2] = hsyncon;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[3] = hsyncoff;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[4] = vblankon;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[5] = vblankoff;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[6] = vsyncon;
+ ((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[7] = vsyncoff;
+}
+
+
+/****************************************************************************
+ *
+ ***************************************************************************/
+VOID ResetBT439(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+ unsigned long old;
+
+ old = *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase);
+ old &= 0xfffffbff;
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) = old;
+
+ /* time delay for BT439 PLL sampling */
+
+ KeStallExecutionProcessor(1000);
+
+ old |= 0x00000400;
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) = old;
+
+ /* time delay for BT439 PLL sampling */
+
+ KeStallExecutionProcessor(1000);
+
+}
+
+
+/****************************************************************************
+ *
+ ***************************************************************************/
+VOID Write_BT457
+(
+ PHW_DEVICE_EXTENSION HwDeviceExtension,
+ ULONG addr,
+ ULONG value
+)
+{
+ ((PULONG)(HM_BT457 + HwDeviceExtension->fxVBase))[addr] = value;
+
+ /* This delay might not be needed */
+
+ KeStallExecutionProcessor(1000);
+
+}
+
+
+/****************************************************************************
+ * InitBT457() sets up the RAMDACs for 1280x1024, linear color ramp,
+ * no overlays (no cursor)
+ * Also resets the BT439 pipeline delay to 8 clocks
+ ***************************************************************************/
+VOID InitBT457(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+ unsigned long x, i, Bt457CmdReg;
+
+ /* BT457 control register initialization */
+
+ Write_BT457(HwDeviceExtension, 0, 0x040404); /* addr reg */
+ Write_BT457(HwDeviceExtension, 2, 0xFFFFFF); /* read mask reg */
+ Write_BT457(HwDeviceExtension, 0, 0x050505); /* addr reg */
+ Write_BT457(HwDeviceExtension, 2, 0x000000); /* blink mask reg */
+ Write_BT457(HwDeviceExtension, 0, 0x060606); /* addr reg */
+
+ i = HwDeviceExtension->iCurrentMode;
+ Bt457CmdReg = aMvpgModes[i].Bt457CommandReg;
+
+ Write_BT457(HwDeviceExtension, 2, Bt457CmdReg); /* command reg 1024 */
+
+ Write_BT457(HwDeviceExtension, 0, 0x070707); /* addr reg */
+ Write_BT457(HwDeviceExtension, 2, 0x010204); /* test reg */
+
+ /* BT457 color map initialization */
+
+ Write_BT457(HwDeviceExtension, 0, 0x000000); /* addr reg */
+ for (x=0; x < 256; x++)
+ {
+ Write_BT457(HwDeviceExtension, 1, x | (x << 8) | (x << 16)); /* RAM */
+ Write_BT457(HwDeviceExtension, 1, x | (x << 8) | (x << 16)); /* RAM */
+ Write_BT457(HwDeviceExtension, 1, x | (x << 8) | (x << 16)); /* RAM */
+ }
+
+}
+
+/***************************************************************************
+ * ProgramICD2062(mclkdata, vclkdata)
+ * program the ICD2062 programmable clock chip refresh clock (mclk) and
+ * video clock (vclk) using precalculated data.
+ ***************************************************************************/
+VOID ProgramICD2062
+(
+ PHW_DEVICE_EXTENSION HwDeviceExtension,
+ ULONG mclkdata,
+ ULONG vclkdata
+)
+{
+ int k;
+ unsigned long j;
+ volatile unsigned long junk;
+
+ // /* REFRESH CLOCK */
+ /* OK. now perform the serial programming trick */
+ /* first do the unlock sequence */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA = 1 */
+ FLUSHIO();
+
+ for (k=0; k < 10; k++)
+ {
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0;
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0;
+ FLUSHIO();
+ }
+ /* unlock */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+
+ /* start bit */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+
+ /* now clock in 24 bits of manchester encoded mclkdata */
+ for (k=0; k < 24; k++)
+ {
+ if ((mclkdata & 1) == 0)
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
+ else
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+
+ if ((mclkdata & 1) == 0)
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ else
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
+
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+ mclkdata = mclkdata >> 1;
+ }
+ /* stop bit */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+
+ /* select clock 0 */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+
+ /* delay at least 5ms */
+ for (j=0; j < 100000; j++)
+ junk = *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase);
+
+ /* VIDEO CLOCK */
+
+ /* OK. now perform the serial programming trick */
+ /* first do the unlock sequence */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA = 1 */
+ FLUSHIO();
+
+ for (k=0; k < 10; k++)
+ {
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0;
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0;
+ FLUSHIO();
+ }
+ /* unlock */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+
+ /* start bit */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+
+ /* now clock in 24 bits of manchester encoded vclkdata */
+ for (k=0; k < 24; k++)
+ {
+ if ((vclkdata & 1) == 0)
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
+ else
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+
+ if ((vclkdata & 1) == 0)
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ else
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
+
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+ vclkdata = vclkdata >> 1;
+ }
+ /* stop bit */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
+ FLUSHIO();
+
+ /* select clock 0 */
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
+ FLUSHIO();
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
+ FLUSHIO();
+
+ /* delay at least 5ms */
+ for (j=0; j < 100000; j++)
+ junk = *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase);
+}
+
+VOID DevpResetVideo(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+ *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_VGAPASS;
+}
+
diff --git a/private/ntos/nthals/halacr/mips/jxdmadsp.s b/private/ntos/nthals/halacr/mips/jxdmadsp.s
new file mode 100644
index 000000000..4e93ee555
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxdmadsp.s
@@ -0,0 +1,56 @@
+// TITLE("Jazz I/O Interrupt Dispatch")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// jxdmadsp.s
+//
+// Abstract:
+//
+// This module implements the code necessary to do the second level dispatch
+// for I/O interrupts on Jazz.
+//
+// Author:
+//
+// David N. Cutler (davec) 12-May-1990
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "jazzdef.h"
+
+ SBTTL("Local Device First Level Dispatch")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt being generated
+// for a local device.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpDmaDispatch)
+
+ lbu t0,INTERRUPT_VIRTUAL_BASE + 0x0 // get interrupt source value
+ lw a0,KiPcr + PcInterruptRoutine + (DEVICE_VECTORS * 4)(t0) //
+ lw t1,InDispatchAddress - InDispatchCode(a0) // get dispatch address
+ subu a0,a0,InDispatchCode // compute address of interrupt object
+ j t1 // transfer control to interrupt routine
+
+ .end HalpDmaDispatch
diff --git a/private/ntos/nthals/halacr/mips/jxebsup.c b/private/ntos/nthals/halacr/mips/jxebsup.c
new file mode 100644
index 000000000..57b2b8341
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxebsup.c
@@ -0,0 +1,1231 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+
+--*/
+
+#include "halp.h"
+#include "jazzdma.h"
+#include "jazzdef.h"
+#include "jazzint.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+#define ISA
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ESIA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+#if 0
+ //
+ // TEMP: Reset the Eisa bus, since the firmware does not do for a reboot.
+ //
+
+ DataByte = 0;
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(3);
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+#endif
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = (UCHAR)(0xFF);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+
+ PULONG dispatchCode;
+ UCHAR interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+ PUCHAR Acknowledge = (PUCHAR)&DMA_CONTROL->InterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(Acknowledge);
+
+ //
+ // If the vector is nonzero, then there is an EISA interrupt.
+ // Otherwise, the interrupt is no longer present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT(Offset >= 0x100000);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+#ifndef ISA
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+#endif
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halacr/mips/jxenvirv.c b/private/ntos/nthals/halacr/mips/jxenvirv.c
new file mode 100644
index 000000000..4578e3c40
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxenvirv.c
@@ -0,0 +1,698 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "jazznvr.h"
+#include "string.h"
+
+//
+// Define base address at which to map NVRAM.
+//
+
+#define NVRAM_MEMORY_BASE PTE_BASE
+
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which receives the old NVRAM
+ PTE values.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO NvramPte;
+ PENTRYLO PtePointer;
+
+ //
+ // Construct a PTE to map NVRAM into the address space of the current
+ // process.
+ //
+
+ NvramPte.X1 = 0;
+ NvramPte.PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
+ NvramPte.G = 0;
+ NvramPte.V = 1;
+ NvramPte.D = 1;
+
+#if defined(R3000)
+
+ NvramPte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ NvramPte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Raise IRQL to the highest level, flush the TB, map the NVRAM into
+ // the address space of the current process, and return the previous
+ // IRQL.
+ //
+
+ PtePointer = (PENTRYLO)PDE_BASE;
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ SavedPte[0] = PtePointer[0];
+ SavedPte[1] = PtePointer[1];
+ KeFlushCurrentTb();
+ PtePointer[0] = NvramPte;
+ NvramPte.PFN += 1;
+ PtePointer[1] = NvramPte;
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which contains the old NVRAM
+ PTE values.
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PENTRYLO PtePointer;
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+
+ PtePointer = (PENTRYLO)PDE_BASE;
+ KeFlushCurrentTb();
+ PtePointer[0] = SavedPte[0];
+ PtePointer[1] = SavedPte[1];
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return Status;
+}
diff --git a/private/ntos/nthals/halacr/mips/jxhalp.h b/private/ntos/nthals/halacr/mips/jxhalp.h
new file mode 100644
index 000000000..90a5d24fe
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxhalp.h
@@ -0,0 +1,105 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halacr/mips/jxhwsup.c b/private/ntos/nthals/halacr/mips/jxhwsup.c
new file mode 100644
index 000000000..927b9bec1
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxhwsup.c
@@ -0,0 +1,2904 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "jazzint.h"
+#include "eisa.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCreateDmaStructures)
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+#define ACER
+
+#if defined(ACER)
+#define INTERNAL_DMA_CHANNEL 4
+#else
+#define INTERNAL_DMA_CHANNEL 8
+#endif
+#define IOBUS_DMA_CHANNEL 8
+
+
+
+//
+// The jazz DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpDmaChannelInterrupt;
+
+UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. ";
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+//
+// The following function is called when a DMA channel interrupt occurs.
+//
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[INTERNAL_DMA_CHANNEL];
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG Hint;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+ if (virtualAddress == NULL) {
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ FALSE
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Required number of map registers. Updated to show
+ actual number allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG)-1;
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ Hint,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = Hint;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+ return;
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ Jazz system: Internal, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) {
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+ }
+
+ if (DeviceDescription->InterfaceType == Internal) {
+
+
+ //
+ // Return the adapter pointer for internal adapters.
+ //
+ // If this is a master controler such as the SONIC then return the
+ // last channel.
+ //
+
+ if (DeviceDescription->Master) {
+
+ //
+ // Create an adapter if necessary.
+ //
+
+ if (HalpInternalAdapters[INTERNAL_DMA_CHANNEL-1] == NULL) {
+
+ HalpInternalAdapters[INTERNAL_DMA_CHANNEL-1] = HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[INTERNAL_DMA_CHANNEL-1],
+ NULL
+ );
+
+ }
+
+ return(HalpInternalAdapters[INTERNAL_DMA_CHANNEL-1]);
+
+ }
+
+ //
+ // Make sure the DMA channel range is valid. Only use channels 0-6.
+ //
+
+ if (DeviceDescription->DmaChannel >= (INTERNAL_DMA_CHANNEL-1)) {
+
+ return(NULL);
+ }
+
+ //
+ // If necessary allocate an adapter; otherwise,
+ // just return the adapter for the requested channel.
+ //
+
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel] == NULL) {
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel] =
+ HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[DeviceDescription->DmaChannel],
+ NULL
+ );
+
+ }
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+ return(HalpInternalAdapters[DeviceDescription->DmaChannel]);
+ }
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != Eisa) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ return(TRUE);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Jazz only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+
+#if defined(ACER)
+ // For the Acer ARC PC does not have the revision register
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+#else
+ if (DMA_CONTROL->RevisionLevel.Long < 2) {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ } else {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+ }
+#endif
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+ ULONG Mode;
+
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter( 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if (AdapterBaseVa == NULL) {
+
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (SHORT)Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+ AdapterObject->PagePort = NULL;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+ ULONG MapRegisterSize;
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG1_BASE);
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationBase.Long,
+ HalpMapRegisterPhysicalBase
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationLimit.Long,
+ MapRegisterSize
+ );
+
+ //
+ // Initialize the DMA mode registers for the Floppy, SCSI and Sound.
+ // The initialization values come fomr the Jazz System Specification.
+ //
+
+ Mode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_120NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_8BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[FLOPPY_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+#if defined(ACER)
+
+// For the Acer ARC PC does not have the on board sound
+
+#else // For Jazz system
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_A].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_B].Mode.Long,
+ (ULONG) Mode
+ );
+#endif
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ return AdapterObject;
+
+ return (PADAPTER_OBJECT) NULL;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ ULONG Hint;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize the DMA interrupt dispatcher for Jazz I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpDmaChannelInterrupt,
+ HalpDmaChannel,
+ (PVOID) NULL,
+ (PKSPIN_LOCK) NULL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpDmaChannelInterrupt );
+
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ PCR->InterruptRoutine[DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpDmaDispatch;
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ return HalpCreateEisaStructures ();
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+ KIRQL irql;
+
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+
+ //
+ // Set the offset to point to the map register plus the offset.
+ //
+
+ Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+
+ //
+ // Invalidate the translation entry.
+ //
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long, 1);
+
+ if ( AdapterObject == NULL) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+
+ if (AdapterObject->PagePort == NULL) {
+
+ //
+ // Set the local DMA Registers.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Address.Long, Offset);
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long, *Length);
+
+ i = 0;
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 1;
+ ((PDMA_CHANNEL_ENABLE) &i)->TransferDirection =
+ WriteToDevice ? DMA_WRITE_OP : DMA_READ_OP;
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, i);
+
+
+ } else {
+
+ //
+ // Start the EISA DMA controller.
+ //
+
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+{
+ ULONG i;
+ ULONG wordPtr, j;
+ UCHAR DataByte;
+
+ if (AdapterObject == NULL) {
+
+ //
+ // This is a master adadapter so there is nothing to do.
+ //
+
+ return(TRUE);
+ }
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else {
+
+ //
+ // Clear on board DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ i = READ_REGISTER_USHORT(
+ &((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable
+ );
+ }
+
+ return(TRUE);
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ return(DataLength);
+}
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ } else {
+
+ //
+ // Disable the DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ saveEnable = i;
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ //
+ // Read the transfer count.
+ //
+
+ count = READ_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long);
+
+ //
+ // Reset the Enable register.
+ //
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ saveEnable
+ );
+
+ }
+
+ return(count);
+}
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a DMA channel interrupt occurs.
+ These should never occur. Bugcheck is called if an error does occur.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+
+ ULONG DataWord;
+ ULONG Channel;
+ DMA_CHANNEL_ENABLE ChannelWord;
+
+ //
+ // Read the DMA channel interrupt source register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long);
+
+ for (Channel = 0; Channel < 8; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << Channel))) {
+ continue;
+ }
+
+ DmaChannelMsg[18] = (UCHAR)(Channel + '0');
+
+ HalDisplayString(DmaChannelMsg);
+
+ *((PULONG) &ChannelWord) =
+ READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long);
+
+ if (ChannelWord.TerminalCount) {
+ HalDisplayString("Terminal count was reached.\n");
+ }
+
+ if (ChannelWord.MemoryError) {
+ HalDisplayString("A memory error was detected.\n");
+ }
+
+ if (ChannelWord.TranslationError) {
+ HalDisplayString("A translation error occured.\n");
+ }
+
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ return(TRUE);
+}
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ HalpMapRegisterPhysicalBase = PhysicalAddress;
+
+}
diff --git a/private/ntos/nthals/halacr/mips/jxidle.c b/private/ntos/nthals/halacr/mips/jxidle.c
new file mode 100644
index 000000000..19fd8a792
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxidle.c
@@ -0,0 +1,46 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxidle.c
+
+Abstract:
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalProcessorIdle(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called when the current processor is idle.
+
+ The current processors interrupts are disabled, and it is known
+ to be idle until it receives an interrupts. This call does not
+ need to return until an interrupt is received by the current
+ processor.
+
+ This is the lowest level of processor idle. It occurs frequently,
+ and this function (alone) should not put the processor into a
+ power savings mode which requeres large amount of time to enter & exit.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ // no power savings mode...
+}
diff --git a/private/ntos/nthals/halacr/mips/jxmapio.c b/private/ntos/nthals/halacr/mips/jxmapio.c
new file mode 100644
index 000000000..6b95c48db
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxmapio.c
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpRealTimeClockBase;
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ physicalAddress.HighPart = 0;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.LowPart = RTCLOCK_PHYSICAL_BASE;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase == NULL) ||
+ (HalpRealTimeClockBase == NULL)) {
+ return FALSE;
+
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halacr/mips/jxmaptb.c b/private/ntos/nthals/halacr/mips/jxmaptb.c
new file mode 100644
index 000000000..2b972a02d
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxmaptb.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmaptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for a MIPS R3000
+ or R4000 Jazz system. It also sets the instruction and data cache line
+ sizes for a MIPS R3000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapFixedTbEntries)
+
+#endif
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine loads the fixed TB entries that map the DMA control and
+ interrupt sources registers for a MIPS R3000 or R4000 Jazz system. It
+ also sets the instruction and data cache line sizes for a MIPS R3000
+ Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ ENTRYLO Pte[2];
+
+ //
+ // Map the DMA control and interrupt source register by loading fixed
+ // TB entry(s).
+ //
+
+ Pte[0].PFN = DMA_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+#if defined(R3000)
+
+ Pte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte[0].C = UNCACHED_POLICY;
+
+#endif
+
+ Pte[1].PFN = INTERRUPT_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[1].G = 1;
+ Pte[1].V = 1;
+ Pte[1].D = 1;
+
+#if defined(R3000)
+
+ Pte[1].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte[1].C = UNCACHED_POLICY;
+
+#endif
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+#if defined(R3000)
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[1],
+ (PVOID)INTERRUPT_VIRTUAL_BASE,
+ INTERRUPT_ENTRY);
+
+#endif
+
+ //
+ // Set the instruction and data cache line sizes.
+ //
+
+#if defined(R3000)
+
+ PCR->DcacheFillSize = 0x10;
+ PCR->DcacheAlignment = 0x10 - 1;
+ PCR->FirstLevelDcacheFillSize = 0x10;
+ PCR->FirstLevelIcacheFillSize = 0x20;
+
+#endif
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halacr/mips/jxport.c b/private/ntos/nthals/halacr/mips/jxport.c
new file mode 100644
index 000000000..3dbb6a846
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxport.c
@@ -0,0 +1,877 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)(SP_VIRTUAL_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SP_VIRTUAL_BASE))
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 0;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was found, then set baud clock
+ // for 8000000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = SP_PHYSICAL_BASE >> PAGE_SHIFT;
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry and set the noncached bit in the PTE that will
+ // map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+ HalpPte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+#endif
+
+ KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff));
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG KdPortEntry;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+
+#endif
+
+ //
+ // Map the serial controller through a allocated TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
+
diff --git a/private/ntos/nthals/halacr/mips/jxreturn.c b/private/ntos/nthals/halacr/mips/jxreturn.c
new file mode 100644
index 000000000..029c80620
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxreturn.c
@@ -0,0 +1,156 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+--*/
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ ENTRYLO Pte[2];
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ //
+ // Map the keyboard controller
+ //
+
+ Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ Pte[0].C = UNCACHED_POLICY;
+
+ //
+ // set second page to global and not valid.
+ //
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map keyboard controller using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+ KbdStoreData(0);
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halacr/mips/jxsysint.c b/private/ntos/nthals/halacr/mips/jxsysint.c
new file mode 100644
index 000000000..8a55404f1
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxsysint.c
@@ -0,0 +1,324 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzint.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // enable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector.
+ The system interrupt vector and IRQL are suitable for use in a
+ subsequent call to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // ****** temp ******
+ //
+ // MP code to be added
+ //
+ // ****** temp ******
+ //
+
+ *Affinity = 1;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ *Irql = (UCHAR)BusInterruptLevel;
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+
+ }
+
+ //
+ // Jazz only has one I/O bus which is an EISA, so the bus number and the
+ // bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Target;
+
+ //
+ // Scan the processor set and request an interprocessor interrupt on
+ // each of the specified targets.
+ //
+
+#if !defined(NT_UP)
+
+ Target = 0;
+ do {
+ if ((Mask & 1) != 0) {
+
+ //
+ // Request interprocessor interrupt on target.
+ //
+
+ }
+
+ Mask >>= 1;
+ Target += 1;
+ } while (Mask != 0);
+
+#endif
+
+ return;
+}
diff --git a/private/ntos/nthals/halacr/mips/jxtime.c b/private/ntos/nthals/halacr/mips/jxtime.c
new file mode 100644
index 000000000..34ee1a150
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxtime.c
@@ -0,0 +1,289 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ Register |= 0x80;
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ Register |= 0x80;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/halacr/mips/jxusage.c b/private/ntos/nthals/halacr/mips/jxusage.c
new file mode 100644
index 000000000..0c1d01efc
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/jxusage.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/halacr/mips/vga.h b/private/ntos/nthals/halacr/mips/vga.h
new file mode 100644
index 000000000..d682d2df4
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/vga.h
@@ -0,0 +1,342 @@
+/*++
+
+Copyright (c) 1993, NeTpower, Inc. All rights reserved.
+
+Module Name:
+
+ vga.h
+
+Abstract:
+
+ Standard VGA support header file. Everything needed to initialize,
+ and talk to standard VGA cards on either the PICA or the ISA bus.
+
+ Reference: Programmers Guide to the EGA and VGA, Second Edition.
+ by Richard F. Ferraro. ISBN 0-201-57025-4, 1990.
+
+Author:
+
+ Mike Dove (mdove), 8-Oct-93
+
+--*/
+
+#ifndef _VGA_
+#define _VGA_
+
+//
+// Set up typedef's for the VGA ports. Depending on whether you are
+// reading or writing, some of the registers appear at different addresses.
+// Therefore, there are two typedef structures defined depending on
+// whether you are doing reads or writes... These registers start at
+// offset 0x3C0.
+//
+
+typedef volatile struct _VGA_READ_PORT {
+ /* 000 */ UCHAR None_0[0x102];
+ /* 102 */ UCHAR SetupOptionSelect; // S3 only...
+ /* 103 */ UCHAR None_1[0x2be];
+ /* 3C1 */ UCHAR AttributeAddressAndData;
+ /* 3C2 */ UCHAR InputStatus0;
+ /* 3C3 */ UCHAR None_2;
+ /* 3C4 */ UCHAR SequencerAddress;
+ /* 3C5 */ UCHAR SequencerData;
+ /* 3C6 */ UCHAR PELMask;
+ /* 3C7 */ UCHAR DACState;
+ /* 3C8 */ UCHAR PELAddressWriteMode;
+ /* 3C9 */ UCHAR PELData;
+ /* 3CA */ UCHAR FeatureControl;
+ /* 3CB */ UCHAR None_3;
+ /* 3CC */ UCHAR MiscOutput;
+ /* 3CD */ UCHAR None_4;
+ /* 3CE */ UCHAR GraphicsAddress;
+ /* 3CF */ UCHAR GraphicsData;
+ /* 3D0 */ UCHAR None_5[4];
+ /* 3D4 */ UCHAR CRTCAddress;
+ /* 3D5 */ UCHAR CRTCData;
+ /* 3D6 */ UCHAR None_6[4];
+ /* 3DA */ UCHAR InputStatus1;
+} VGA_READ_PORT, *PVGA_READ_PORT;
+
+typedef volatile struct _VGA_WRITE_PORT {
+ /* 000 */ UCHAR None_0[0x102];
+ /* 102 */ UCHAR SetupOptionSelect; // S3 only...
+ /* 103 */ UCHAR None_1[0x2bd];
+ /* 3C0 */ UCHAR AttributeAddressAndData;
+ /* 3C1 */ UCHAR None_2;
+ /* 3C2 */ UCHAR MiscOutput;
+ /* 3C3 */ UCHAR None_3;
+ /* 3C4 */ UCHAR SequencerAddress;
+ /* 3C5 */ UCHAR SequencerData;
+ /* 3C6 */ UCHAR PELMask;
+ /* 3C7 */ UCHAR PELAddressReadMode;
+ /* 3C8 */ UCHAR PELAddressWriteMode;
+ /* 3C9 */ UCHAR PELData;
+ /* 3CA */ UCHAR None_4[4];
+ /* 3CE */ UCHAR GraphicsAddress;
+ /* 3CF */ UCHAR GraphicsData;
+ /* 3D0 */ UCHAR None_5[4];
+ /* 3D4 */ UCHAR CRTCAddress;
+ /* 3D5 */ UCHAR CRTCData;
+ /* 3D6 */ UCHAR None_6[4];
+ /* 3DA */ UCHAR FeatureControl;
+ /* 3DB */ UCHAR None_7[0x3f0d];
+ /* 42E8 */ USHORT SubsystemControlRegister; // S3 only...
+ /* 42E9 */ UCHAR None_8[0x3fe];
+ /* 46E8 */ UCHAR VideoSubsystemEnable; // S3 only...
+ /* 46E9 */ UCHAR None_9[0x3ff];
+ /* 4AE8 */ USHORT AdvancedFunctionControl; // S3 only...
+
+} VGA_WRITE_PORT, *PVGA_WRITE_PORT;
+
+//
+// The following #defines represent the indexes used for the Address/Data
+// register sets. The data for the *Setup arrays was taken from pages 318-319
+// in the Programmers Guide to the EGA and VGA for video mode 3.
+//
+
+// Sequencer Registers
+
+#define SEQ_RESET 0
+#define SYNCHRONUS_RESET 0x01
+#define NORMAL_OPERATION 0x03
+#define SEQ_CLOCKING_MODE 1
+#define SEQ_MAP_MASK 2
+#define ENABLE_PLANE_2 0x04
+#define SEQ_CHARACTER_MAP_SELECT 3
+#define SEQ_MEMORY_MODE 4
+#define SEQUENTIAL_ADDRESSING 0x04
+#define EXTENDED_MEMORY 0x02
+
+static UCHAR SequencerSetup[] = {
+ 0x03, // Reset
+ 0x00, // Clocking Mode
+ 0x03, // Map Mask
+ 0x00, // Character Map Select
+ 0x02, // Memory Mode
+};
+
+
+// CRT Controller Registers
+
+#define CRT_HORIZONTAL_TOTAL 0
+#define CRT_HORIZONTAL_DISPLAY_END 1
+#define CRT_START_HORIZONTAL_BLANKING 2
+#define CRT_END_HORIZONTAL_BLANKING 3
+#define CRT_START_HORIZONTAL_RETRACE 4
+#define CRT_END_HORIZONTAL_RETRACE 5
+#define CRT_VERTICAL_TOTAL 6
+#define CRT_OVERFLOW 7
+#define CRT_PRESET_ROW_SCAN 8
+#define CRT_MAXIMUM_SCAN_LINE 9
+#define CRT_CURSOR_START 10
+#define CRT_CURSOR_END 11
+#define CRT_START_ADDRESS_HIGH 12
+#define CRT_START_ADDRESS_LOW 13
+#define CRT_CURSOR_LOCATION_HIGH 14
+#define CRT_CURSOR_LOCATION_LOW 15
+#define CRT_VERTICAL_RETRACE_START 16
+#define CRT_VERTICAL_RETRACE_END 17
+#define CRT_VERTICAL_DISPLAY_END 18
+#define CRT_OFFSET 19
+#define CRT_UNDERLINE_LOCATION 20
+#define CRT_START_VERTICAL_BLANK 21
+#define CRT_END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define CRT_LINE_COMPARE 24
+
+static UCHAR CRTCSetup[] = {
+ 0x5f, // Horizontal Total
+ 0x4f, // Horizontal Display End
+ 0x50, // Start Horizontal Blanking
+ 0x82, // End Horizontal Blanking
+ 0x55, // Start Horizontal Retrace
+ 0x81, // End Horizontal Retrace
+ 0xbf, // Vertical Total
+ 0x1f, // Overflow
+ 0x00, // Preset Row Scan
+ 0x4b, // Maximum Scan Line - Changes: 2T4 turned off, 12 row characters
+ 0x0e, // Cursor Start - Changes: 16 row characters, move cursor down
+ 0x0f, // Cursor End - Changes: 16 row characters, move cursor down
+ 0x00, // Start Address High
+ 0x00, // Start Address Low
+ 0x00, // Cursor Location High
+ 0x00, // Cursor Location Low - Changes: Start at 0
+ 0x9c, // Vertical Retrace Start
+ 0x8e, // Vertical Retrace End - also write protects CRT registers 0-7.
+ 0x8f, // Vertical Display End
+ 0x28, // Offset
+ 0x1f, // Underline Location
+ 0x96, // Start Vertical Blank
+ 0xb9, // End Vertical Blank
+ 0xa3, // Mode Control
+ 0xff, // Line Compare
+};
+
+// Graphics Registers
+
+#define GFX_SET_RESET 0
+#define GFX_ENABLE_SET_RESET 1
+#define GFX_COLOR_COMPARE 2
+#define GFX_DATA_ROTATE 3
+#define GFX_READ_MAP_SELECT 4
+#define GFX_MODE 5
+#define WRITE_MODE_0 0x00
+#define GFX_MISCELLANEOUS 6
+#define MEMORY_MODE_1 0x04
+#define ALPHA_MODE 0x00
+#define GFX_COLOR_DONT_CARE 7
+#define GFX_BIT_MASK 8
+
+static UCHAR GraphicsSetup[] = {
+ 0x00, // Set/Reset
+ 0x00, // Enable Set/Reset
+ 0x00, // Color Compare
+ 0x00, // Data Rotate
+ 0x00, // Read Map Select
+ 0x10, // Mode
+ 0x0e, // Miscellaneous
+ 0x00, // Color Don't Care
+ 0xff, // Bit Mask
+};
+
+// Attribute Registers
+
+#define ATT_PALETTE_00 0
+#define ATT_PALETTE_01 1
+#define ATT_PALETTE_02 2
+#define ATT_PALETTE_03 3
+#define ATT_PALETTE_04 4
+#define ATT_PALETTE_05 5
+#define ATT_PALETTE_06 6
+#define ATT_PALETTE_07 7
+#define ATT_PALETTE_08 8
+#define ATT_PALETTE_09 9
+#define ATT_PALETTE_10 10
+#define ATT_PALETTE_11 11
+#define ATT_PALETTE_12 12
+#define ATT_PALETTE_13 13
+#define ATT_PALETTE_14 14
+#define ATT_PALETTE_15 15
+#define ATT_MODE 16
+#define ATT_OVERSCAN_COLOR 17
+#define ATT_COLOR_PLANE_ENABLE 18
+#define ATT_HORIZONTAL_PIXEL_PANNING 19
+#define ATT_COLOR_SELECT 20
+
+static UCHAR AttributeSetup[] = {
+ 0x00, // Palette 00 Index - Black
+ 0x01, // Palette 01 Index - Red
+ 0x02, // Palette 02 Index - Green
+ 0x03, // Palette 03 Index - Yellow
+ 0x04, // Palette 04 Index - Blue
+ 0x05, // Palette 05 Index - Magenta
+ 0x06, // Palette 06 Index - Cyan
+ 0x07, // Palette 07 Index - White
+ 0x08, // Palette 08 Index - Intense Black (read Grey)
+ 0x09, // Palette 09 Index - Intense Red
+ 0x0a, // Palette 10 Index - Intense Green
+ 0x0b, // Palette 11 Index - Intense Yellow
+ 0x0c, // Palette 12 Index - Intense Blue
+ 0x0d, // Palette 13 Index - Intense Magenta
+ 0x0e, // Palette 14 Index - Intense Cyan
+ 0x0f, // Palette 15 Index - Intense White
+ 0x04, // Mode
+ 0x00, // Overscan Color
+ 0x0F, // Color Plane Enable
+ 0x08, // Horizontal Pixel Panning
+ 0x00, // Color Select
+};
+
+static UCHAR ColorValues[16][3] = {
+// Red Grn Blue
+ 00, 00, 00, // Black
+ 42, 00, 00, // Red
+ 00, 42, 00, // Green
+ 42, 21, 00, // Brown
+ 00, 00, 42, // Blue
+ 42, 00, 42, // Magenta
+ 00, 42, 42, // Cyan
+ 42, 42, 42, // White
+ 21, 21, 21, // Intense Black (read Grey)
+ 63, 21, 21, // Intense Red
+ 21, 63, 21, // Intense Green
+ 63, 63, 21, // Intense Brown
+ 21, 21, 63, // Intense Blue
+ 63, 21, 63, // Intense Magenta
+ 21, 63, 63, // Intense Cyan
+ 63, 63, 63, // Intense White
+};
+
+#define COLOR_BLACK 0
+#define COLOR_RED 1
+#define COLOR_GREEN 2
+#define COLOR_BROWN 3
+#define COLOR_BLUE 4
+#define COLOR_MAGENTA 5
+#define COLOR_CYAN 6
+#define COLOR_WHITE 7
+#define COLOR_GREY 8
+#define COLOR_INTENSE_RED 9
+#define COLOR_INTENSE_GREEN 10
+#define COLOR_INTENSE_BROWN 11
+#define COLOR_INTENSE_BLUE 12
+#define COLOR_INTENSE_MAGENTA 13
+#define COLOR_INTENSE_CYAN 14
+#define COLOR_INTENSE_WHITE 15
+
+// Other register bit definitions...
+
+// Miscellaneous Output Register
+#define IOA_COLOR 0x01
+#define ER_ENABLE 0x02
+#define CS_25MHZ 0x00
+#define CS_28MHZ 0x04
+#define CS_ENHANCED 0x06
+#define DVD_ENABLE 0x00
+#define PB_HIGH64K 0x20
+#define HSP_NEGATIVE 0x40
+#define VSP_POSITIVE 0x00
+#define VSP_NEGATIVE 0x80
+#define INITIAL_CONFIG ( IOA_COLOR \
+ | ER_ENABLE \
+ | CS_ENHANCED \
+ | DVD_ENABLE \
+ | PB_HIGH64K \
+ | HSP_NEGATIVE \
+ | VSP_POSITIVE \
+ )
+
+// S3 specific #defines
+
+#define ENTER_SETUP_MODE 0x10
+#define ENABLE_VIDEO_SUBSYSTEM 0x08
+#define VIDEO_SUBSYSTEM_ALIVE 0x01
+
+#define S3_CHIP_ID 0x30
+#define S3_MEMORY_CONFIGURATION 0x31
+#define S3_BACKWARD_COMPATIBILITY_1 0x32
+#define S3_BACKWARD_COMPATIBILITY_2 0x33
+#define S3_BACKWARD_COMPATIBILITY_3 0x34
+#define S3_CRT_REGISTER_LOCK 0x35
+#define S3_CONFIGURATION_1 0x36
+#define S3_CONFIGURATION_2 0x37
+#define S3_REGISTER_LOCK_1 0x38
+#define S3_REGISTER_LOCK_2 0x39
+#define S3_MISCELLANEOUS_1 0x3a
+#define S3_DATA_TRANSFER_EXECUTE 0x3b
+#define S3_INTERLACE_RETRACE_START 0x3c
+#define S3_SYSTEM_CONFIGURATION 0x40
+#define S3_MODE_CONTROL 0x42
+#define S3_EXTENDED_MODE 0x43
+#define S3_HARDWARE_GRAPHICS_CURSOR 0x45
+#define S3_EXTENDED_MEMORY_CONTROL_1 0x53
+#define S3_EXTENDED_MEMORY_CONTROL_2 0x54
+#define S3_LINEAR_ADDRESS_WINDOW_HIGH 0x59
+#define S3_LINEAR_ADDRESS_WINDOW_LOW 0x5A
+
+
+// Other #defines
+
+#define SPACE 0x20 // Ascii space
+
+#endif
diff --git a/private/ntos/nthals/halacr/mips/x4clock.s b/private/ntos/nthals/halacr/mips/x4clock.s
new file mode 100644
index 000000000..9894d37ea
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/x4clock.s
@@ -0,0 +1,234 @@
+#if defined(R4000)
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "jazzdef.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+ lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
+ .set reorder
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ jal KeUpdateSystemTime // update system time
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,10f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+10: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,20f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+ sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
+ sw t3,HalpNextTimeIncrement // set next time increment value
+20: beq zero,t0,30f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,30f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+30: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ la t1,HalpPerformanceCounter // get performance counter address
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ j KeProfileInterrupt // process profile entries
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+#endif
diff --git a/private/ntos/nthals/halacr/mips/x4tb.s b/private/ntos/nthals/halacr/mips/x4tb.s
new file mode 100644
index 000000000..a997f57d9
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/x4tb.s
@@ -0,0 +1,115 @@
+#if defined(R4000)
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Author:
+//
+// David N. Cutler (davec) 29-Dec-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halacr/mips/x86bios.c b/private/ntos/nthals/halacr/mips/x86bios.c
new file mode 100644
index 000000000..d931c324e
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/x86bios.c
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halacr/mips/xxcalstl.c b/private/ntos/nthals/halacr/mips/xxcalstl.c
new file mode 100644
index 000000000..0a1e8aa81
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/xxcalstl.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (PCR->StallScaleFactor <= 0) {
+ PCR->StallScaleFactor = 1;
+ }
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the clock interrupt.
+ //
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halacr/mips/xxclock.c b/private/ntos/nthals/halacr/mips/xxclock.c
new file mode 100644
index 000000000..118b7ca19
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/xxclock.c
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ NextIntervalCount = DesiredIncrement / MINIMUM_INCREMENT;
+ NewTimeIncrement = NextIntervalCount * MINIMUM_INCREMENT;
+ HalpNextIntervalCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halacr/mips/xxidle.s b/private/ntos/nthals/halacr/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halacr/mips/xxinithl.c b/private/ntos/nthals/halacr/mips/xxinithl.c
new file mode 100644
index 000000000..c83ef479a
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/xxinithl.c
@@ -0,0 +1,252 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Map the fixed TB entries and initiakize the display.
+ //
+
+ HalpMapFixedTbEntries();
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ //
+ // Verify that the procressor block major version number conforms
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Initialize interrupts
+ //
+ //
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ HalpMapIoSpace();
+ HalpCalibrateStall();
+ HalpCreateDmaStructures();
+ return TRUE;
+ }
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halacr/mips/xxinitnt.c b/private/ntos/nthals/halacr/mips/xxinitnt.c
new file mode 100644
index 000000000..43ef3358c
--- /dev/null
+++ b/private/ntos/nthals/halacr/mips/xxinitnt.c
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpCountInterrupt (
+ VOID
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+#pragma alloc_text(INIT, HalpCountInterrupt)
+
+#endif
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+#if defined(R4000)
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+#endif
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ USHORT DataShort;
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Clear all builtin device interrupt enables.
+ //
+
+ HalpBuiltinInterruptEnable = 0;
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ 0);
+
+ do {
+ DataShort = READ_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Source) & 0x3ff;
+ } while (DataShort != 0);
+
+ //
+ // Connect the clock interrupt to the stall interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Start the system clock to interrupt at MAXIMUM_INCREMENT intervals.
+ //
+ // N.B. MAXIMUM_INCREMENT is in 100ns units.
+ //
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptInterval.Long, CLOCK_INTERVAL);
+
+ //
+ // Connect the R4000 count/compare interrupt to the early interrupt
+ // routine.
+ //
+
+#if defined(R4000)
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+#endif
+
+ //
+ // Reserve the local device interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= ((1 << DEVICE_LEVEL) | (1 << EISA_DEVICE_LEVEL));
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halacr/sources b/private/ntos/nthals/halacr/sources
new file mode 100644
index 000000000..c5eb1ec30
--- /dev/null
+++ b/private/ntos/nthals/halacr/sources
@@ -0,0 +1,85 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halacr
+TARGETPATH=\nt\public\sdk\lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halalcor/alpha/adjust.c b/private/ntos/nthals/halalcor/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/alcor.h b/private/ntos/nthals/halalcor/alpha/alcor.h
new file mode 100644
index 000000000..90931ecfa
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/alcor.h
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alcor.h
+
+Abstract:
+
+ This file contains definitions specific to the Alcor platform
+
+Author:
+
+ Steve Brooks 11-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _ALCORH_
+#define _ALCORH_
+
+//
+// Include definitions for the components that make up Alcor.
+//
+
+#include "axp21164.h" // 21164 (EV5) microprocessor definitions
+#include "cia.h" // CIA controller definitions
+#include "gru.h" // GRU controller definitions
+
+//
+// Define number of PCI, EISA, and combo slots
+//
+
+#define NUMBER_EISA_SLOTS 4
+#define NUMBER_PCI_SLOTS 5
+#define NUMBER_COMBO_SLOTS 1
+
+//
+// Define the data and csr ports for the I2C bus and OCP.
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x550
+#define I2C_INTERFACE_CSR_PORT 0x551
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+//
+// Define the index and data ports for the NS Super IO chip.
+//
+
+#define SUPERIO_INDEX_PORT 0x398
+#define SUPERIO_DATA_PORT 0x399
+#define SUPERIO_PORT_LENGTH 0x2
+
+//
+// PCI bus address values:
+//
+
+#define PCI_MAX_LOCAL_DEVICE 12
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+//
+// Define numbers and names of cpus.
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0)
+
+//
+// Define default processor frequency.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (250)
+
+//
+// Define Alcor-specific routines that are really macros for performance.
+//
+
+#define HalpAcknowledgeEisaInterrupt(x) (UCHAR)(INTERRUPT_ACKNOWLEDGE(x))
+
+//
+// Define the per-processor data structures allocated in the PCR.
+//
+
+typedef struct _ALCOR_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+ } ALCOR_PCR, *PALCOR_PCR;
+
+#define HAL_PCR ( (PALCOR_PCR)(&(PCR->HalReserved)) )
+
+#endif //_ALCORH_
diff --git a/private/ntos/nthals/halalcor/alpha/alcorerr.c b/private/ntos/nthals/halalcor/alpha/alcorerr.c
new file mode 100644
index 000000000..dfd3bc8cf
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/alcorerr.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alcorerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Alcor platform.
+
+Author:
+
+ Joe Notarangelo 27-Jul-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "alcor.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+VOID
+HalpAlcorErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for an ALCOR machine check interrupt
+ The function calls HalpCiaReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // If this is a CIA uncorrectable error then report the error and
+ // crash the system.
+ //
+
+ if( HalpCiaUncorrectableError() == TRUE ){
+
+ HalpCiaReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+
+ }
+
+ //
+ // It was not a CIA uncorrectable error, therefore this must be an
+ // NMI interrupt.
+ //
+
+ HalHandleNMI( NULL, NULL );
+
+ return; // never
+
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+ //
+ // All machine check handling on Alcor is determined by the CIA.
+ //
+
+ return( HalpCiaMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ) );
+
+}
diff --git a/private/ntos/nthals/halalcor/alpha/alinitnt.c b/private/ntos/nthals/halalcor/alpha/alinitnt.c
new file mode 100644
index 000000000..f80290d23
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/alinitnt.c
@@ -0,0 +1,795 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an Alcor system.
+
+Author:
+
+ Joe Notarangelo 19-Jul-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "alcor.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpProductName;
+PCHAR HalpFamilyName = "AlphaStation";
+ULONG HalpProcessorNumber = 5;
+
+#define MAX_INIT_MSG (80)
+
+
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// Define external references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Function prototypes.
+//
+
+BOOLEAN
+HalpInitializeAlcorInterrupts (
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpAlcorErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ );
+
+
+//
+// Irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - interval clock
+// irql 6 - not used
+// irql 7 - error, mchk, nmi, performance counters
+//
+//
+
+//
+// The hardware interrupt pins are used as follows for Alcor
+//
+// IRQ0 = CIA_INT
+// IRQ1 = SYS_INT (PCI and ESC interrupts)
+// IRQ2 = Interval Clock
+// IRQ3 = Reserved
+//
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alcor system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern ULONG HalpCiaErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+ extern ULONG HalpHaltInterrupt();
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize Alcor interrupts.
+ //
+
+ HalpInitializeAlcorInterrupts();
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpCiaErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpAlcorErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_CRD_VECTOR] =
+ (PKINTERRUPT_ROUTINE)Halp21164CorrectedErrorInterrupt;
+
+ HalpStart21164Interrupts();
+
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV5
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is a NOOP for Alcor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Platform-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ ULONG Model;
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the PCI parity checking.
+ //
+
+ if( HalDisablePCIParityChecking != 0 ){
+ PciParityChecking = FALSE;
+ } else {
+ PciParityChecking = TRUE;
+ }
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = TRUE,
+ PciParityChecking );
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Determine model type.
+ //
+
+ Model= READ_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntReq);
+ Model= (Model >> 24) & 0xf;
+
+ if (Model >= 0x8) {
+
+ //
+ // Maverick.
+ //
+
+ HalpProductName = "500";
+
+ //
+ // Print a message with version number. Yes, it's the
+ // final official name now.
+ //
+
+ sprintf(MsgBuffer,
+ "Digital Equipment Corporation %s %s/%d",
+ HalpFamilyName,
+ HalpProductName,
+ HalpClockMegaHertz );
+
+ } else {
+
+ //
+ // Alcor.
+ //
+
+ HalpProductName = "600";
+
+ //
+ // Print a message with version number.
+ //
+
+ sprintf(MsgBuffer,
+ "Digital Equipment Corporation %s %s %d/%d",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+ }
+
+ HalDisplayString( MsgBuffer );
+
+ HalDisplayString("\n");
+
+ //
+ // Build the string to register the HAL.
+ //
+
+ strcat(MsgBuffer, " PCI/EISA HAL");
+
+
+ HalpRegisterPlatformResources( MsgBuffer );
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Eisa);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ Resource.u.Start = SUPERIO_INDEX_PORT;
+ Resource.u.Length = SUPERIO_PORT_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaChannel = 0x4;
+ Resource.u.DmaPort = 0x0;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function is called from HalpAllocateUncorrectableErrorFrame.
+ This function retuns the size of the system specific error frame
+ sizes.
+
+Arguments:
+
+ RawProcessorSize - Processor-specific uncorrectable frame size.
+
+ RawSystemInfoSize - system-specific uncorrectable frame size.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(CIA_UNCORRECTABLE_FRAME);
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ Fills in the system information structure.
+ NOTE: Must later investigate the Fw call to get the firmware revision
+ ID. Must also figure out a way to get the OS version (preferebly the
+ build number).
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION structure.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char systemtype[] = "Alcor";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+
+ return;
+}
+
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to Alcor and the call should be
+// ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+//
+//jnfix - this variable is needed because the clock interrupt handler
+// - in intsup.s was made to be familiar with ev4prof.c, unfortunate
+// - since we don't use ev4prof.c, so for now this is a hack, later
+// - we will either fix intsup.s or create a new intsup.s that does
+// - not have this hack
+//
+
+ULONG HalpNumberOfTicksReload;
diff --git a/private/ntos/nthals/halalcor/alpha/alintsup.c b/private/ntos/nthals/halalcor/alpha/alintsup.c
new file mode 100644
index 000000000..ddb18d70f
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/alintsup.c
@@ -0,0 +1,599 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Alcor systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Chao Chen (DEC) 26-July-1994
+ Adapted from Avanti module for Alcor.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "alcor.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+
+//
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+
+KINTERRUPT HalpPciInterrupt;
+KINTERRUPT HalpEisaInterrupt;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Declare the interrupt handler for the EISA bus. The interrupt dispatch
+// routine, HalpEisaDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following functions handle the PCI interrupts.
+//
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitializeAlcorInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the EISA interrupt controller; the Alcor ESC's interrupt controller is
+ compatible with the EISA interrupt contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) AlcorPCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize the ESC's PICs for EISA interrupts.
+ //
+
+ HalpInitializeEisaInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Alcor comes from a Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+
+//
+// The enable mask for all interrupts sourced from the GRU (all device
+// interrupts, and all from PCI). A "1" indicates the interrupt is enabled.
+//
+
+ULONG HalpPciInterruptMask;
+
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Alcor PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Disable interrupts except EISA.
+ //
+
+ HalpPciInterruptMask = GRU_ENABLE_EISA_INT;
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntMask,
+ HalpPciInterruptMask);
+
+ //
+ // Set all interrupts to level.
+ //
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntEdge,
+ GRU_SET_LEVEL_INT);
+
+ //
+ // Set all interrupts to active low except EISA.
+ //
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntHiLo,
+ GRU_SET_LOW_INT);
+
+ //
+ // Clear the interrupt clear register.
+ //
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntClear, 0);
+
+
+}
+
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ HalpPciInterruptMask &= (ULONG) ~(1 << Vector);
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntMask,
+ HalpPciInterruptMask);
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Alcor PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to one,
+ // to ensable that PCI interrupt.
+ //
+
+ HalpPciInterruptMask |= (ULONG) 1 << Vector;
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntMask,
+ HalpPciInterruptMask);
+
+}
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ ULONG IdtIndex;
+ ULONG IntNumber;
+ PKINTERRUPT InterruptObject;
+ ULONG PCIVector;
+ ULONG Slot;
+
+ //
+ // Read in the interrupt register.
+ //
+
+ PCIVector=READ_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntReq);
+
+ //
+ // Consider only those interrupts which are currently enabled.
+ //
+
+ PCIVector &= HalpPciInterruptMask;
+
+ //
+ // Continue processing interrupts while any are requested.
+ //
+
+ while( (PCIVector & (GRU_EISA_MASK_INT | GRU_PCI_MASK_INT)) != 0 ){
+
+ //
+ // Did PCI or EISA interrupt occur?
+ //
+
+ if (PCIVector & GRU_EISA_MASK_INT) {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ HalpEisaDispatch( Interrupt, (PVOID)CIA_PCI_INTACK_QVA, TrapFrame);
+
+ } else {
+
+ //
+ // PCI interrupt. Find out which slot.
+ //
+
+ for (Slot = 0; Slot < NUMBER_PCI_SLOTS; Slot++) {
+
+ if (PCIVector & 0xf)
+ break;
+ else
+ PCIVector = PCIVector >> 4;
+ }
+
+ //
+ // Find out which of the IntA, IntB, IntC, or IntD occurred.
+ //
+
+ for (IntNumber = 0; IntNumber < 4; IntNumber++) {
+
+ if (PCIVector & 0x1)
+ break;
+ else
+ PCIVector = PCIVector >> 1;
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ IdtIndex = (Slot * (NUMBER_PCI_SLOTS - 1) + IntNumber) +
+ PCI_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+ }
+
+ //
+ // Check for more interrupts.
+ //
+
+ PCIVector = READ_GRU_REGISTER(
+ &((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntReq);
+ PCIVector &= HalpPciInterruptMask;
+
+ } //end while( (PCIVector & (GRU_EISA_MASK_INT | GRU_PCI_MASK_INT)) != 0 )
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halalcor/alpha/allstart.c b/private/ntos/nthals/halalcor/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/alsysint.c b/private/ntos/nthals/halalcor/alpha/alsysint.c
new file mode 100644
index 000000000..384133a2e
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/alsysint.c
@@ -0,0 +1,497 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Alcor system.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "alcor.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Disable the correctable error interrupt.
+ //
+
+ {
+ CIA_ERR_MASK CiaErrMask;
+
+ CiaErrMask.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.CorErr = 0x0;
+
+ WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnablePciInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Enable the correctable error interrupt.
+ //
+
+ {
+ CIA_ERR_MASK CiaErrMask;
+
+ CiaErrMask.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.CorErr = 0x1;
+
+ WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ }
+
+ Enabled = TRUE;
+ break;
+
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ ULONG BusNumber = BusHandler->BusNumber;
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else if ((Vector = HalpGet21164CorrectableVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Correctable error interrupt was sucessfully recognized.
+ //
+
+ *Affinity = 1;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus ISA_VECTORS.
+ // N.B.: this encoding technique uses the notion of defining a
+ // base interrupt vector in the space defined by the constant,
+ // ISA_VECTORS, which may or may not differ from EISA_VECTORS or
+ // PCI_VECTORS.
+ //
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR
+ //
+ // N.B. The BusInterruptLevel is one-based while the vectors
+ // themselves are zero-based. The BusInterruptLevel must be
+ // one-based because if scsiport sees a zero vector then it
+ // will believe the interrupt is not connected. So in PCI
+ // configuration we have made the interrupt vector correspond
+ // to the slot and interrupt pin.
+ //
+ // N.B - bias for disjoint bus levels
+ //
+
+ return( (BusInterruptLevel - 0x11) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on Alcor systems.
+ //
+
+#if defined(HALDBG)
+
+ DbgPrint("ALSYSINT: InterfaceType (%x) not supported on Alcor\n",
+ InterfaceType);
+
+#endif
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Alcor because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/halalcor/alpha/apecs.c b/private/ntos/nthals/halalcor/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/apecserr.c b/private/ntos/nthals/halalcor/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/apecsio.s b/private/ntos/nthals/halalcor/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/bios.c b/private/ntos/nthals/halalcor/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/busdata.c b/private/ntos/nthals/halalcor/alpha/busdata.c
new file mode 100644
index 000000000..f3c197f82
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/busdata.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+ Steve Brooks 30-Jun-1994
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halalcor/alpha/cache.c b/private/ntos/nthals/halalcor/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/cia.c b/private/ntos/nthals/halalcor/alpha/cia.c
new file mode 100644
index 000000000..7948bfe16
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/cia.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cia.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ciaaddr.c b/private/ntos/nthals/halalcor/alpha/ciaaddr.c
new file mode 100644
index 000000000..b85818ac0
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ciaaddr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaaddr.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ciaerr.c b/private/ntos/nthals/halalcor/alpha/ciaerr.c
new file mode 100644
index 000000000..bfb9efc93
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ciaerr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaerr.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ciaio.s b/private/ntos/nthals/halalcor/alpha/ciaio.s
new file mode 100644
index 000000000..16202a7e1
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ciaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaio.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ciamapio.c b/private/ntos/nthals/halalcor/alpha/ciamapio.c
new file mode 100644
index 000000000..3e9f7a9c1
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ciamapio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciamapio.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/cmos8k.c b/private/ntos/nthals/halalcor/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/devintr.s b/private/ntos/nthals/halalcor/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ebsgdma.c b/private/ntos/nthals/halalcor/alpha/ebsgdma.c
new file mode 100644
index 000000000..e2d35353d
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ebsgdma.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
diff --git a/private/ntos/nthals/halalcor/alpha/eisasup.c b/private/ntos/nthals/halalcor/alpha/eisasup.c
new file mode 100644
index 000000000..1b52e85e7
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/eisasup.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
diff --git a/private/ntos/nthals/halalcor/alpha/environ.c b/private/ntos/nthals/halalcor/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ev5cache.c b/private/ntos/nthals/halalcor/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ev5int.c b/private/ntos/nthals/halalcor/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ev5ints.s b/private/ntos/nthals/halalcor/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ev5mchk.c b/private/ntos/nthals/halalcor/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ev5mem.s b/private/ntos/nthals/halalcor/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ev5prof.c b/private/ntos/nthals/halalcor/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/fwreturn.c b/private/ntos/nthals/halalcor/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/haldebug.c b/private/ntos/nthals/halalcor/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/halpal.s b/private/ntos/nthals/halalcor/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/haltsup.s b/private/ntos/nthals/halalcor/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/idle.s b/private/ntos/nthals/halalcor/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/info.c b/private/ntos/nthals/halalcor/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/inithal.c b/private/ntos/nthals/halalcor/alpha/inithal.c
new file mode 100644
index 000000000..c9a9e2076
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/inithal.c
@@ -0,0 +1,1059 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inithal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+ 24-Sep-1993 Joe Notarangelo
+ Restructured to make this module platform-independent.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+PERROR_FRAME PUncorrectableError;
+
+//
+// external
+//
+
+ULONG HalDisablePCIParityChecking = 0xffffffff;
+
+//
+// Define HAL spinlocks.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Mask of all of the processors that are currently active.
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// Mapping of the logical processor numbers to the physical processors.
+//
+
+ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ULONG AlreadySet = 0;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ;
+
+ULONGLONG HalpContiguousPhysicalMemorySize;
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ );
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ );
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Perform initialization for the primary processor.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+ if (Phase == 0) {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+ HalpDumpMemoryDescriptors( LoaderBlock );
+
+#endif //HALDBG
+ //
+ // Get the memory Size.
+ //
+ HalpContiguousPhysicalMemorySize = HalpGetContiguousMemorySize(
+ LoaderBlock );
+
+
+ //
+ // Set second level cache size
+ // NOTE: Although we set the PCR with the right cache size this
+ // could be overridden by setting the Registry key
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
+ // \Control\Session Manager
+ // \Memory Management\SecondLevelDataCache.
+ //
+ //
+ //
+ // If the secondlevel cache size is 0 or 512KB then it is
+ // possible that the firmware is an old one. In which case
+ // we determine the cache size here. If the value is anything
+ // other than these then it is a new firmware and probably
+ // reporting the correct cache size hence use this value.
+ //
+
+ if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 ||
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){
+ PCR->SecondLevelCacheSize = HalpGetBCacheSize(
+ HalpContiguousPhysicalMemorySize
+ );
+ } else {
+ PCR->SecondLevelCacheSize =
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize;
+ }
+
+
+ //
+ // Initialize HAL spinlocks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpInitializeCia( LoaderBlock );
+
+ HalpSetTimeIncrement();
+ HalpMapIoSpace();
+ HalpCreateDmaStructures(LoaderBlock);
+ HalpEstablishErrorHandler();
+ HalpInitializeDisplay(LoaderBlock);
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+ HalpInitializeInterrupts();
+ HalpVerifyPrcbVersion();
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+ //
+ // Initialize the logical to physical processor mapping
+ // for the primary processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[0] = HAL_PRIMARY_PROCESSOR;
+
+ return TRUE;
+
+ } else {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpInitializeClockInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Allocate memory for the uncorrectable frame
+ //
+
+ HalpAllocateUncorrectableFrame();
+
+ //
+ // Initialize the Buffer for Uncorrectable Error.
+ //
+
+ HalpInitializeUncorrectableErrorFrame();
+
+ return TRUE;
+
+ }
+ }
+
+ //
+ // Perform necessary processor-specific initialization for
+ // secondary processors. Phase is ignored as this will be called
+ // only once on each secondary processor.
+ //
+
+ HalpMapIoSpace();
+ HalpInitializeInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors |= 1 << Prcb->Number;
+
+#if HALDBG
+
+ DbgPrint( "Secondary %d is alive\n", Prcb->Number );
+
+#endif //HALDBG
+
+ return TRUE;
+}
+
+
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called after the Phase1 Machine Dependent initialization.
+ It must be called only after Phase1 machine dependent initialization.
+ This function allocates the necessary amountof memory for storing the
+ uncorrectable error frame. This function makes a call to a machine
+ dependent function 'HalpGetMachineDependentErrorFrameSizes' for
+ getting the size of the Processor Specific and System Specific error
+ frame size. The machine dependent code will
+ know the size of these frames after the machine depedant Phase1
+ initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG RawProcessorFrameSize;
+ ULONG RawSystemFrameSize;
+ ULONG EntireErrorFrameSize;
+
+ //
+ // First get the machine dependent error frame sizes.
+ //
+ HalpGetMachineDependentErrorFrameSizes(
+ &RawProcessorFrameSize,
+ &RawSystemFrameSize);
+
+ //
+ // Compute the total size of the error frame
+ //
+ EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize +
+ RawSystemFrameSize;
+
+ //
+ // Allocate space to store the error frame.
+ // Not sure if it is OK to use ExAllocatePool at this instant.
+ // We will give this a try if it doesn't work What do we do??!!
+ //
+
+ PUncorrectableError = ExAllocatePool(NonPagedPool,
+ EntireErrorFrameSize);
+ if(PUncorrectableError == NULL) {
+ return;
+ }
+
+ PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize;
+
+ //
+ // if the size is not equal to zero then set the RawInformation pointers
+ // to point to the right place. If not set the pointer to NULL and set
+ // size to 0.
+ //
+
+ //
+ // make Raw processor info to point right after the error frame.
+ //
+ if(RawProcessorFrameSize) {
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ (PVOID)((PUCHAR)PUncorrectableError + sizeof(ERROR_FRAME) );
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ RawProcessorFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ 0;
+ }
+ if(RawSystemFrameSize){
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame.
+ RawProcessorInformation + RawProcessorFrameSize);
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ RawSystemFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ 0;
+ }
+}
+
+
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+)
+/*++
+
+Routine Description:
+
+ Collects the Processor Information and fills in the buffer.
+
+Arguments:
+
+ pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which
+ the processor information will be filled in.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+
+ pProcessorInfo->ProcessorType = PCR->ProcessorType;
+ pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision;
+
+ Prcb = PCR->Prcb;
+ pProcessorInfo->LogicalProcessorNumber = Prcb->Number;
+ pProcessorInfo->PhysicalProcessorNumber =
+ HalpLogicalToPhysicalProcessor[Prcb->Number];
+ return;
+}
+
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ ULONG LogicalNumber;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PhysicalNumber;
+ PKPRCB Prcb;
+
+#if !defined(NT_UP)
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ LogicalNumber = 0;
+ PhysicalNumber = 0;
+ do {
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){
+
+ PhysicalNumber += 1;
+
+ } else {
+
+ //
+ // Check if this processor has already been started.
+ // If it has not then start it now.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){
+
+ RtlZeroMemory( &NextRestartBlock->u.Alpha,
+ sizeof(ALPHA_RESTART_STATE));
+ NextRestartBlock->u.Alpha.IntA0 =
+ ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Alpha.IntSp =
+ ProcessorState->ContextFrame.IntSp;
+ NextRestartBlock->u.Alpha.ReiRestartAddress =
+ (ULONG)ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)LogicalNumber;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Ensure that the logical to physical mapping has been
+ // established for this processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ }
+
+ LogicalNumber += 1;
+ PhysicalNumber += 1;
+ }
+
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+
+ } while (NextRestartBlock != NULL);
+
+#endif // !defined(NT_UP)
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the HAL matches the kernel. If there
+ is a mismatch the HAL bugchecks the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PKPRCB Prcb;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+
+}
+
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PWSTR NameString;
+
+ //
+ // Quick out
+ //
+
+ if (AlreadySet) {
+ return;
+ }
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+ HalDisablePCIParityChecking = Component->Flags.ConsoleOut;
+ AlreadySet = TRUE;
+#if HALDBG
+ DbgPrint("ARC tree sets PCI parity checking to %s\n",
+ HalDisablePCIParityChecking ? "OFF" : "ON");
+#endif
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return (ULONG) ((Count2 - Count1)*(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the processor counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+#if DBG
+ DbgPrint(
+ "Frequency = %d\nMegaHertz = %d\n",
+ HalpClockFrequency,
+ HalpClockMegaHertz
+ );
+#endif
+
+}
+
+
+
+
+#if 0
+VOID
+HalpGatherPerformanceParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
diff --git a/private/ntos/nthals/halalcor/alpha/intsup.s b/private/ntos/nthals/halalcor/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halalcor/alpha/ioproc.c b/private/ntos/nthals/halalcor/alpha/ioproc.c
new file mode 100644
index 000000000..36d338384
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/ioproc.c
@@ -0,0 +1,91 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halalcor/alpha/iousage.c b/private/ntos/nthals/halalcor/alpha/iousage.c
new file mode 100644
index 000000000..6ac8f6f4e
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/iousage.c
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/halalcor/alpha/iousage.h b/private/ntos/nthals/halalcor/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/halalcor/alpha/machdep.h b/private/ntos/nthals/halalcor/alpha/machdep.h
new file mode 100644
index 000000000..21a40d2f0
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Alcor platform-specific definitions.
+//
+
+#include "alcor.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halalcor/alpha/memory.c b/private/ntos/nthals/halalcor/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/pcibus.c b/private/ntos/nthals/halalcor/alpha/pcibus.c
new file mode 100644
index 000000000..3ce95ed54
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pcibus.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+ Steve Brooks 30-Jun-1994
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+#if HALDBG
+
+ DbgPrint( "PCI Config Access: Bus = %d, Device = %d, Type = %d\n",
+ BusNumber, Slot.u.bits.DeviceNumber, ConfigType );
+
+#endif //HALDBG
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Note that HalpValidPCISlot has already done bounds checking
+ // on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+
+ //
+ // Encoding of the configuration addresses differs between
+ // passes of the CIA. Use the pre-determined global HalpCiaRevision
+ // to decide which encoding to use.
+ //
+
+ if( HalpCiaRevision == CIA_REVISION_1 ){
+
+ //
+ // CIA Pass 1
+ //
+
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+
+ } else {
+
+ //
+ // CIA Pass 2 or later.
+ //
+
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+
+ }
+
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+ } else {
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halalcor/alpha/pciesc.c b/private/ntos/nthals/halalcor/alpha/pciesc.c
new file mode 100644
index 000000000..49142ea83
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pciesc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pciesc.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/pcisup.c b/private/ntos/nthals/halalcor/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/pcrtc.c b/private/ntos/nthals/halalcor/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/pcserial.c b/private/ntos/nthals/halalcor/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/pcspeakr.c b/private/ntos/nthals/halalcor/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/perfcntr.c b/private/ntos/nthals/halalcor/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halalcor/alpha/pintolin.h b/private/ntos/nthals/halalcor/alpha/pintolin.h
new file mode 100644
index 000000000..5595b6c19
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/pintolin.h
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+ Steve Brooks 6-July 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for Alcor.
+//
+// Alcor PCI interrupts are mapped to arbitrary interrupt numbers
+// in the table below. The values are a 1-1 map of the bit numbers
+// in the Alcor PCI interrupt register that are connected to PCI
+// devices. N.B.: there are two other interrupts in this register,
+// but they are not connected to I/O devices, so they're not
+// represented in the table.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_MIKASA.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+//
+// N.B. - Have biased the bus interrupt vectors/levels for PCI to start
+// at 0x11 so they are disjoint from EISA levels
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG AlcorPCIPinToLineTable[][4]=
+{
+
+//
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+//
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0x1e, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] Maverick Ethernet Controller
+ { 0x19, 0x1a, 0x1b, 0x1c }, // Virtual Slot 7 = PCI_AD[18] 64 bit Slot #0
+ { 0x21, 0x22, 0x23, 0x24 }, // Virtual Slot 8 = PCI_AD[19] 32 bit Slot #0
+ { 0x1d, 0x1e, 0x1f, 0x20 }, // Virtual Slot 9 = PCI_AD[20] 32 bit Slot #1
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] Eisa Bridge
+ { 0x11, 0x12, 0x13, 0x14 }, // Virtual Slot 11 = PCI_AD[22] 64 bit Slot #2
+ { 0x15, 0x16, 0x17, 0x18 }, // Virtual Slot 12 = PCI_AD[23] 64 bit Slot #1
+};
diff --git a/private/ntos/nthals/halalcor/alpha/vga.c b/private/ntos/nthals/halalcor/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halalcor/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halalcor/drivesup.c b/private/ntos/nthals/halalcor/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halalcor/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halalcor/hal.rc b/private/ntos/nthals/halalcor/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halalcor/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halalcor/hal.src b/private/ntos/nthals/halalcor/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halalcor/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halalcor/makefile b/private/ntos/nthals/halalcor/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halalcor/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halalcor/makefile.inc b/private/ntos/nthals/halalcor/makefile.inc
new file mode 100644
index 000000000..6a15e8199
--- /dev/null
+++ b/private/ntos/nthals/halalcor/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halalcor.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halalcor/sources b/private/ntos/nthals/halalcor/sources
new file mode 100644
index 000000000..375630c42
--- /dev/null
+++ b/private/ntos/nthals/halalcor/sources
@@ -0,0 +1,106 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halalcor
+TARGETPATH=\nt\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+
+#C_DEFINES=-DEV5 -DEISA_PLATFORM -DCIA_PASS1
+C_DEFINES=-DEV5 -DEISA_PLATFORM -DCIA_PASS1
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\adjust.c \
+ alpha\allstart.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cia.c \
+ alpha\ciaaddr.c \
+ alpha\ciaerr.c \
+ alpha\ciaio.s \
+ alpha\ciamapio.c \
+ alpha\cmos8k.c \
+ alpha\devintr.s \
+ alpha\environ.c \
+ alpha\ev5cache.c \
+ alpha\ev5int.c \
+ alpha\ev5mchk.c \
+ alpha\ev5mem.s \
+ alpha\ev5prof.c \
+ alpha\ev5ints.s \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\haltsup.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\pciesc.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\alcorerr.c \
+ alpha\alinitnt.c \
+ alpha\alintsup.c \
+ alpha\alsysint.c \
+ alpha\busdata.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halalp/alpha/28f008sa.c b/private/ntos/nthals/halalp/alpha/28f008sa.c
new file mode 100644
index 000000000..2865a2061
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/28f008sa.c
@@ -0,0 +1 @@
+#include "../halalpha/28f008sa.c"
diff --git a/private/ntos/nthals/halalp/alpha/29f040.c b/private/ntos/nthals/halalp/alpha/29f040.c
new file mode 100644
index 000000000..2c2b423af
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/29f040.c
@@ -0,0 +1 @@
+#include "../halalpha/29f040.c"
diff --git a/private/ntos/nthals/halalp/alpha/addrsup.c b/private/ntos/nthals/halalp/alpha/addrsup.c
new file mode 100644
index 000000000..b49efb042
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/addrsup.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\addrsup.c"
diff --git a/private/ntos/nthals/halalp/alpha/adjust.c b/private/ntos/nthals/halalp/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/allstart.c b/private/ntos/nthals/halalp/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/alphaio.s b/private/ntos/nthals/halalp/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/apecs.c b/private/ntos/nthals/halalp/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/apecserr.c b/private/ntos/nthals/halalp/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/apecsio.s b/private/ntos/nthals/halalp/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/bios.c b/private/ntos/nthals/halalp/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/busdata.c b/private/ntos/nthals/halalp/alpha/busdata.c
new file mode 100644
index 000000000..2782bbbd2
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/busdata.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\busdata.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/cache.c b/private/ntos/nthals/halalp/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/chipset.h b/private/ntos/nthals/halalp/alpha/chipset.h
new file mode 100644
index 000000000..0a72ef8cb
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/chipset.h
@@ -0,0 +1 @@
+#include "apecs.h"
diff --git a/private/ntos/nthals/halalp/alpha/cmos8k.c b/private/ntos/nthals/halalp/alpha/cmos8k.c
new file mode 100644
index 000000000..3656af8db
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/cmos8k.c
@@ -0,0 +1,2 @@
+#include "..\haleb64p\alpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/eb64pdef.h b/private/ntos/nthals/halalp/alpha/eb64pdef.h
new file mode 100644
index 000000000..8e7a0971b
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/eb64pdef.h
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\eb64pdef.h"
diff --git a/private/ntos/nthals/halalp/alpha/ebenv.c b/private/ntos/nthals/halalp/alpha/ebenv.c
new file mode 100644
index 000000000..a993ecec8
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ebenv.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\ebenv.c"
diff --git a/private/ntos/nthals/halalp/alpha/ebinitnt.c b/private/ntos/nthals/halalp/alpha/ebinitnt.c
new file mode 100644
index 000000000..60e8d2cb8
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ebinitnt.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\ebinitnt.c"
diff --git a/private/ntos/nthals/halalp/alpha/ebintsup.c b/private/ntos/nthals/halalp/alpha/ebintsup.c
new file mode 100644
index 000000000..c4d181860
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ebintsup.c
@@ -0,0 +1,585 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for EB64+ systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "eb64pdef.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Global to control interrupt handling for EB64+
+//
+
+UCHAR IntMask0, IntMask1, IntMask2;
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// Declare the interupt handler for the PCI and ISA bus.
+//
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ ISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = (PKINTERRUPT_ROUTINE)HalpPCIDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, DEVICE_LEVEL, LevelSensitive);
+
+ if (SystemIsAlphaPC64)
+ (PVOID) HalpPCIPinToLineTable = (PVOID) AlphaPC64PCIPinToLineTable;
+ else
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB64PPCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize the SIO Interrupt Controller
+ //
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the PCI and ISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the ISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpPCIDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, PCI_LEVEL, PCI_LEVEL, PCI_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the ISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR PciVector, IntNumber;
+ ULONG PCRInOffset = 0xffff;
+ KPCR *pcr;
+
+ //
+ // Read in the 1st interrupt register.
+ //
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK0_QVA) & IntMask0;
+
+ //
+ // Was it an ISA (SIO) interrupt?
+ //
+ if (PciVector & SIO_INTERRUPT_MASK) {
+ //
+ // ISA interrupt - call HalpSioDispatch().
+ //
+ return HalpSioDispatch();
+ }
+
+ //
+ // Which PCI interrupt was it?
+ //
+ if (PciVector) {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ } else {
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK1_QVA) & IntMask1;
+
+ if (PciVector) {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber + 8;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ } else if (INTERRUPT_MASK2_QVA != NULL) {
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK2_QVA) & IntMask2;
+/*!!!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!!*/
+ if (PciVector)
+ {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber + 16;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ }
+/*!!!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!!*/
+ }
+ }
+
+ if (PCRInOffset == 0xffff) {
+ return FALSE;
+ }
+
+ PCRInOffset += PCI_VECTORS;
+ PCRInOffset++;
+ return ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset], TrapFrame);
+}
+
+
+VOID
+HalpDisablePCIInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the PCI bus specified PCI bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector.
+ //
+
+ Vector -= PCI_VECTORS;
+ Vector--;
+
+ //
+ // Clear the corresponding bit in the appropriate interrupt mask
+ // shadow and write it out to the interrupt mask.
+ //
+ if (Vector >= 0 && Vector <= 7) {
+ IntMask0 &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ } else if (Vector >= 8 && Vector <= 0xf) {
+ IntMask1 &= (UCHAR) ~(1 << (Vector - 8));
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+/*!!!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!!*/
+ } else if ((Vector >= 0x10 && Vector <=0x17) &&
+ (INTERRUPT_MASK2_QVA != NULL)) {
+ IntMask2 &= (UCHAR) ~(1 << (Vector - 16));;
+/*!!!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!!*/
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ } else {
+#ifdef HALDBG
+ DbgPrint("HalpDisablePCIInterrupt: bad vector\n");
+#endif // HALDBG
+ }
+}
+
+
+VOID
+HalpEnablePCIInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector.
+ //
+
+ Vector -= PCI_VECTORS;
+ Vector--;
+
+ //
+ // Set the corresponding bit in the appropriate interrupt mask
+ // shadow and write it out to the interrupt mask.
+ //
+ if (Vector >= 0 && Vector <= 7) {
+ IntMask0 |= (UCHAR) (1 << Vector);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ } else if (Vector >= 8 && Vector <= 0xf) {
+ IntMask1 |= (UCHAR) (1 << (Vector - 8));
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+/*!!!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!!*/
+ } else if ((Vector >= 0x10 && Vector <= 0x17) &&
+ (INTERRUPT_MASK2_QVA != NULL)) {
+ IntMask2 |= (UCHAR) (1 << (Vector - 16));
+/*!!!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!!*/
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ } else {
+#ifdef HALDBG
+ DbgPrint("HalpEnablePCIInterrupt: bad vector\n");
+#endif // HALDBG
+ }
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Sio machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the PCI device interrupt mask.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Initialize the shadow copies of the interrupt masks to enable only
+ // the SIO interrupt.
+ //
+
+ IntMask0 = (UCHAR)SIO_INTERRUPT_MASK;
+ IntMask1 = 0;
+ IntMask2 = 0;
+
+ //
+ // Write the masks.
+ //
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ if (INTERRUPT_MASK2_QVA != NULL) {
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ }
+}
+
diff --git a/private/ntos/nthals/halalp/alpha/ebmapio.c b/private/ntos/nthals/halalp/alpha/ebmapio.c
new file mode 100644
index 000000000..60869cd20
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ebmapio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\ebmapio.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/ebsgdma.c b/private/ntos/nthals/halalp/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/ebsysint.c b/private/ntos/nthals/halalp/alpha/ebsysint.c
new file mode 100644
index 000000000..3147f4b1e
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ebsysint.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\ebsysint.c"
diff --git a/private/ntos/nthals/halalp/alpha/eisasup.c b/private/ntos/nthals/halalp/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/environ.c b/private/ntos/nthals/halalp/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/ev4cache.c b/private/ntos/nthals/halalp/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/ev4int.c b/private/ntos/nthals/halalp/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/ev4ints.s b/private/ntos/nthals/halalp/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/ev4mchk.c b/private/ntos/nthals/halalp/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/ev4mem.s b/private/ntos/nthals/halalp/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/ev4prof.c b/private/ntos/nthals/halalp/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/flash8k.c b/private/ntos/nthals/halalp/alpha/flash8k.c
new file mode 100644
index 000000000..6e2b80345
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/flash8k.c
@@ -0,0 +1,2 @@
+#include "..\haleb64p\alpha\flash8k.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/flashdrv.c b/private/ntos/nthals/halalp/alpha/flashdrv.c
new file mode 100644
index 000000000..ad0994d4d
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/flashdrv.c
@@ -0,0 +1,3 @@
+#include "../halalpha/flashdrv.c"
+
+
diff --git a/private/ntos/nthals/halalp/alpha/fwreturn.c b/private/ntos/nthals/halalp/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/haldebug.c b/private/ntos/nthals/halalp/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/halpal.s b/private/ntos/nthals/halalp/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/idle.s b/private/ntos/nthals/halalp/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/info.c b/private/ntos/nthals/halalp/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/inithal.c b/private/ntos/nthals/halalp/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/intsup.s b/private/ntos/nthals/halalp/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halalp/alpha/ioproc.c b/private/ntos/nthals/halalp/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/iousage.c b/private/ntos/nthals/halalp/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/machdep.h b/private/ntos/nthals/halalp/alpha/machdep.h
new file mode 100644
index 000000000..63664c856
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/machdep.h
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\machdep.h"
diff --git a/private/ntos/nthals/halalp/alpha/memory.c b/private/ntos/nthals/halalp/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/pcibus.c b/private/ntos/nthals/halalp/alpha/pcibus.c
new file mode 100644
index 000000000..56eb21557
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pcibus.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\haleb64p\alpha\pcibus.c"
diff --git a/private/ntos/nthals/halalp/alpha/pcisio.c b/private/ntos/nthals/halalp/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/pcisup.c b/private/ntos/nthals/halalp/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/pcrtc.c b/private/ntos/nthals/halalp/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/pcserial.c b/private/ntos/nthals/halalp/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/pcspeakr.c b/private/ntos/nthals/halalp/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/perfcntr.c b/private/ntos/nthals/halalp/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halalp/alpha/pintolin.h b/private/ntos/nthals/halalp/alpha/pintolin.h
new file mode 100644
index 000000000..988686a2f
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/pintolin.h
@@ -0,0 +1,212 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Table.
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen [DEC] 13-Sep-1994
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// On Cabriolet, the interrupt vector is the Interrupt Request Register bit
+// representing the interrupt + 1. The value also represents the interrupt
+// mask register bit since the mask register and the request register have
+// the same format.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+//
+// Interrupt Vector Table Mapping for eb64p
+//
+// eb64p PCI interrupts are mapped to ISA IRQs in the table below.
+//
+// Limit init table to 14 entries, which is MAX_PCI_LOCAL_DEVICES_AVANTI.
+// We won't ever try to set an InterruptLine register of a slot greater
+// than Virtual slot 13 = PCI_AD[24].
+//
+
+/*!!!!!!!!!!!!!!!!!!CHANGE!!!!!!!!!!!!!!!!!!!!!*/
+ULONG AlphaPC64PCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x3, 0x8, 0xc, 0x10 }, // Virtual Slot 5 = PCI_AD[16] bridge
+ { 0x1, 0x6, 0xa, 0xe }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+ { 0x2, 0x7, 0xb, 0xf }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+ { 0x5, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x4, 0x9, 0xd, 0x11 }, // Virtual Slot 9 = PCI_AD[20] Slot #2
+ { 0x12, 0x13, 0x14, 0x15 } // Virtual Slot 10 = PCI_AD[21] Slot #3
+};
+//ULONG AlphaPC64PCIPinToLineTable[][4]=
+//{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+// { 0x3, 0x8, 0xc, 0x10 }, // Virtual Slot 5 = PCI_AD[16] Slot #2
+// { 0x1, 0x6, 0xa, 0xe }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+// { 0x2, 0x7, 0xb, 0xf }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+// { 0x5, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+// { 0x4, 0x9, 0xd, 0x11 } // Virtual Slot 9 = PCI_AD[20] Slot #3
+//};
+
+ULONG EB64PPCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x8, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] SCSI
+ { 0x1, 0x3, 0x5, 0x5 }, // Virtual Slot 6 = PCI_AD[17] Slot B
+ { 0x2, 0x4, 0x9, 0x9 }, // Virtual Slot 7 = PCI_AD[18] Slot C
+ { 0x6, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x7, 0xa, 0xb, 0xb } // Virtual Slot 9 = PCI_AD[20] Slot A
+};
+//ULONG EB64PPCIPinToLineTable[][4]=
+//{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+// { 0x8, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] SCSI
+// { 0x1, 0x3, 0x5, 0xa }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+// { 0x2, 0x4, 0x9, 0xb }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+// { 0x6, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+// { 0x7, 0xff, 0xff, 0xff } // Virtual Slot 9 = PCI_AD[20] Tulip
+//};
+
diff --git a/private/ntos/nthals/halalp/alpha/vga.c b/private/ntos/nthals/halalp/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halalp/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halalp/drivesup.c b/private/ntos/nthals/halalp/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halalp/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halalp/hal.rc b/private/ntos/nthals/halalp/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halalp/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halalp/hal.src b/private/ntos/nthals/halalp/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halalp/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halalp/makefile b/private/ntos/nthals/halalp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halalp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halalp/makefile.inc b/private/ntos/nthals/halalp/makefile.inc
new file mode 100644
index 000000000..98c1275cf
--- /dev/null
+++ b/private/ntos/nthals/halalp/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ cl /EP hal.src -DALPHA=1 $(C_DEFINES) > obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\haleb64p.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halalp/sources b/private/ntos/nthals/halalp/sources
new file mode 100644
index 000000000..d6ce6569d
--- /dev/null
+++ b/private/ntos/nthals/halalp/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halalp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DAPECS
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\28f008sa.c \
+ alpha\29f040.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\apecs.c \
+ alpha\apecserr.c \
+ alpha\apecsio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cmos8k.c \
+ alpha\ebenv.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mchk.c \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\flash8k.c \
+ alpha\flashdrv.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\ebinitnt.c \
+ alpha\ebintsup.c \
+ alpha\ebmapio.c \
+ alpha\ebsysint.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halalpha/28f008sa.c b/private/ntos/nthals/halalpha/28f008sa.c
new file mode 100644
index 000000000..487a908d8
--- /dev/null
+++ b/private/ntos/nthals/halalpha/28f008sa.c
@@ -0,0 +1,317 @@
+#include "halp.h"
+#include "arccodes.h"
+#include "flash8k.h"
+
+#define I28F008SA_DEVICE_SIZE 0x100000
+
+#define SET_READ_ARRAY 0xff
+#define SET_BYTE_WRITE 0x40
+#define SET_ERASE_BLOCK 0x20
+#define CONFIRM_ERASE_BLOCK 0xd0
+#define READ_STATUS 0x70
+#define RESET_STATUS 0x50
+#define ID_REQUEST 0x90
+
+#define MANUFACTURER_ID 0x89
+#define DEVICE_ID 0xa2
+
+#define BLOCK_SIZE 0x10000
+#define BLANK_DATA 0xff
+
+#define TIMEOUT_VALUE 5000000
+
+#define STATUS_READY 0x80
+#define STATUS_ERASE_SUSP 0x40
+#define STATUS_ERASE_ERR 0x20
+#define STATUS_WRITE_ERR 0x10
+#define STATUS_VPP_LOW 0x08
+#define STATUS_CMD_SEQ_ERR (STATUS_WRITE_ERR | STATUS_READ_ERR)
+
+//
+// Local function prototypes
+//
+PFLASH_DRIVER
+I28F008SA_Initialize(
+ IN PUCHAR NvRamPtr
+ );
+
+ARC_STATUS
+I28F008SA_SetReadMode(
+ IN PUCHAR Address
+ );
+
+ARC_STATUS
+I28F008SA_WriteByte(
+ IN PUCHAR Address,
+ IN UCHAR Data
+ );
+
+ARC_STATUS
+I28F008SA_EraseBlock(
+ IN PUCHAR Address
+ );
+
+ARC_STATUS
+I28F008SA_CheckStatus(
+ IN PUCHAR Address,
+ FLASH_OPERATIONS Operation
+ );
+
+PUCHAR
+I28F008SA_BlockAlign(
+ IN PUCHAR Address
+ );
+
+UCHAR
+I28F008SA_ReadByte(
+ IN PUCHAR Address
+ );
+
+BOOLEAN
+I28F008SA_OverwriteCheck(
+ IN UCHAR OldData,
+ IN UCHAR NewData
+ );
+
+ULONG
+I28F008SA_BlockSize(
+ IN PUCHAR Address
+ );
+
+ULONG
+I28F008SA_GetLastError(
+ VOID
+ );
+
+static
+VOID
+I28F008SA_SetLastError(
+ ULONG FlashStatus
+ );
+
+FLASH_DRIVER I28F008SA_DriverInformation = {
+ "Intel 28F008SA",
+ I28F008SA_SetReadMode, // SetReadModeFunction
+ I28F008SA_WriteByte, // WriteByteFunction
+ I28F008SA_EraseBlock, // EraseBlockFunction
+ I28F008SA_BlockAlign, // AlignBlockFunction
+ I28F008SA_ReadByte, // ReadByteFunction
+ I28F008SA_OverwriteCheck, // OverwriteCheckFunction
+ I28F008SA_BlockSize, // BlockSizeFunction
+ I28F008SA_GetLastError, // GetLastErrorFunction
+ I28F008SA_DEVICE_SIZE, // DeviceSize
+ BLANK_DATA // ErasedData
+ };
+
+static ULONG I28F008SA_LastError;
+
+PFLASH_DRIVER
+I28F008SA_Initialize(
+ IN PUCHAR NvRamPtr
+ )
+{
+ PFLASH_DRIVER ReturnDriver = NULL;
+ UCHAR ManufacturerID;
+ UCHAR DeviceID;
+
+ NvRamPtr = I28F008SA_BlockAlign(NvRamPtr);
+
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, ID_REQUEST);
+
+ ManufacturerID = READ_CONFIG_RAM_DATA(NvRamPtr);
+ DeviceID = READ_CONFIG_RAM_DATA((PUCHAR)((ULONG)NvRamPtr + 1));
+
+ if ((ManufacturerID == MANUFACTURER_ID) && (DeviceID == DEVICE_ID)) {
+ I28F008SA_LastError = 0;
+ I28F008SA_SetReadMode(NvRamPtr);
+ ReturnDriver = &I28F008SA_DriverInformation;
+ }
+
+ return ReturnDriver;
+}
+
+ARC_STATUS
+I28F008SA_SetReadMode(
+ IN PUCHAR NvRamPtr
+ )
+{
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, SET_READ_ARRAY);
+ HalpMb();
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+I28F008SA_WriteByte(
+ IN PUCHAR NvRamPtr,
+ IN UCHAR Data
+ )
+{
+ ARC_STATUS ReturnStatus;
+
+ I28F008SA_SetReadMode(NvRamPtr);
+
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, SET_BYTE_WRITE);
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, Data);
+
+ ReturnStatus = I28F008SA_CheckStatus(NvRamPtr, FlashByteWrite);
+
+ I28F008SA_SetReadMode(NvRamPtr);
+
+ return ReturnStatus;
+}
+
+ARC_STATUS
+I28F008SA_EraseBlock (
+ IN PUCHAR NvRamPtr
+ )
+{
+ ARC_STATUS ReturnStatus;
+
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, SET_ERASE_BLOCK);
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, CONFIRM_ERASE_BLOCK);
+
+ ReturnStatus = I28F008SA_CheckStatus(NvRamPtr, FlashEraseBlock);
+
+ I28F008SA_SetReadMode(NvRamPtr);
+
+ return ReturnStatus;
+}
+
+ARC_STATUS
+I28F008SA_CheckStatus (
+ IN PUCHAR NvRamPtr,
+ IN FLASH_OPERATIONS Operation
+ )
+{
+ ARC_STATUS ReturnStatus = EIO;
+ ULONG Timeout;
+ UCHAR FlashStatus;
+
+ //
+ // Keep reading the status until the device is done with its
+ // current operation.
+ //
+ Timeout = TIMEOUT_VALUE;
+ do {
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, READ_STATUS);
+ FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr);
+ KeStallExecutionProcessor(1);
+ Timeout--;
+ } while (((FlashStatus & 0x80) == 0) && (Timeout > 0));
+
+ //
+ // Check the status for the operation requested.
+ //
+ switch(Operation) {
+ case FlashByteWrite:
+ if ((FlashStatus & 0x18) == 0) {
+ ReturnStatus = ESUCCESS;
+ } else {
+ I28F008SA_SetLastError(FlashStatus & 0x18);
+ }
+ break;
+ case FlashEraseBlock:
+ if (((FlashStatus & 0x28) == 0) && ((FlashStatus & 0x30) != 0x30)) {
+ ReturnStatus = ESUCCESS;
+ } else {
+ I28F008SA_SetLastError(FlashStatus & 0x28);
+ }
+ break;
+ }
+ if ((FlashStatus & 0x80) == 0) {
+ ReturnStatus = EIO;
+ I28F008SA_SetLastError(0);
+ }
+
+ //
+ // Clear the flash status register
+ // This is a silent operation. The status that gets returned is the
+ // status of the real operation as determined above.
+ //
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, RESET_STATUS);
+ Timeout = TIMEOUT_VALUE;
+ do {
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, READ_STATUS);
+ FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr);
+ KeStallExecutionProcessor(1);
+ Timeout--;
+ } while (((FlashStatus & 0x80) == 0) && (Timeout > 0));
+
+ return ReturnStatus;
+}
+
+PUCHAR
+I28F008SA_BlockAlign(
+ IN PUCHAR Address
+ )
+{
+ return (PUCHAR)((ULONG)Address & ~(BLOCK_SIZE-1));
+}
+
+UCHAR
+I28F008SA_ReadByte(
+ IN PUCHAR Address
+ )
+{
+ return READ_CONFIG_RAM_DATA(Address);
+}
+
+BOOLEAN
+I28F008SA_OverwriteCheck(
+ IN UCHAR OldData,
+ IN UCHAR NewData
+ )
+/*++
+
+Return Value:
+
+ Zero if OldData can be overwritten with NewData.
+ Non-zero if device must be erased to write NewData.
+
+--*/
+{
+ return (~OldData & NewData) ? FALSE : TRUE;
+}
+
+ULONG
+I28F008SA_BlockSize(
+ IN PUCHAR Address
+ )
+/*++
+
+Return Value:
+
+ The block size of the device. This is a constant because all
+ blocks in the 28f008sa are the same size.
+
+--*/
+{
+ return BLOCK_SIZE;
+}
+
+ULONG
+I28F008SA_GetLastError(
+ VOID
+ )
+{
+ return I28F008SA_LastError;
+}
+
+static
+VOID
+I28F008SA_SetLastError(
+ ULONG FlashStatus
+ )
+{
+ I28F008SA_LastError = ERROR_UNKNOWN;
+ if (FlashStatus == 0)
+ I28F008SA_LastError = ERROR_TIMEOUT;
+ if (FlashStatus & STATUS_WRITE_ERR)
+ I28F008SA_LastError = ERROR_WRITE_ERROR;
+ if (FlashStatus & STATUS_ERASE_ERR)
+ I28F008SA_LastError = ERROR_ERASE_ERROR;
+ if (FlashStatus & STATUS_VPP_LOW)
+ I28F008SA_LastError = ERROR_VPP_LOW;
+}
+
diff --git a/private/ntos/nthals/halalpha/29f040.c b/private/ntos/nthals/halalpha/29f040.c
new file mode 100644
index 000000000..331b32584
--- /dev/null
+++ b/private/ntos/nthals/halalpha/29f040.c
@@ -0,0 +1,420 @@
+/*++
+
+File: 29f040.c
+
+Purpose: Firmware/HAL driver for AMD Am29F040 512kB flash device.
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "flash8k.h"
+
+#define Am29F040_DEVICE_SIZE 0x80000
+#define Am29F080_DEVICE_SIZE 0x100000
+
+#define Am29F040_DEVICE_NAME "AMD Am29F040"
+#define Am29F080_DEVICE_NAME "AMD Am29F080"
+
+#define COMMAND_OFFSET 0x5555
+
+#define COMMAND_PREFIX_OFFSET1 (COMMAND_OFFSET)
+#define COMMAND_PREFIX_COMMAND1 0xaa
+
+#define COMMAND_PREFIX_OFFSET2 0x2aaa
+#define COMMAND_PREFIX_COMMAND2 0x55
+
+#define SET_READ_ARRAY 0xf0 // write to COMMAND_ADDRESS
+#define SET_BYTE_WRITE 0xa0 // write to COMMAND_ADDRESS
+#define SET_ERASE 0x80 // write to COMMAND_ADDRESS
+#define CONFIRM_ERASE_BLOCK 0x30 // write to the base address of the block
+#define ID_REQUEST 0x90 // write to COMMAND_ADDRESS
+
+#define MANUFACTURER_ID 0x01
+#define Am29F040_DEVICE_ID 0xa4
+#define Am29F080_DEVICE_ID 0xd5
+
+#define BLOCK_SIZE 0x10000
+#define BLANK_DATA 0xff
+
+#define TIMEOUT_VALUE 5000000
+
+#define COMMAND_PREFIX(address) { \
+ PUCHAR PrefixAddress1; \
+ PUCHAR PrefixAddress2; \
+ PrefixAddress1 = PrefixAddress2 = Am29F040_BlockAlign(address); \
+ PrefixAddress1 = (PUCHAR)((ULONG)PrefixAddress1 + COMMAND_PREFIX_OFFSET1); \
+ PrefixAddress2 = (PUCHAR)((ULONG)PrefixAddress2 + COMMAND_PREFIX_OFFSET2); \
+ WRITE_CONFIG_RAM_DATA(PrefixAddress1, COMMAND_PREFIX_COMMAND1); \
+ HalpMb(); \
+ WRITE_CONFIG_RAM_DATA(PrefixAddress2, COMMAND_PREFIX_COMMAND2); \
+ HalpMb(); \
+ }
+
+#define COMMAND_ADDRESS(address) \
+ ((PUCHAR)(((ULONG)(BLOCK_ALIGN(address)) + (COMMAND_OFFSET))))
+
+#define BLOCK_ALIGN(address) \
+ ((PUCHAR)((ULONG)(address) & ~(BLOCK_SIZE-1)))
+
+//
+// Local function prototypes
+//
+PFLASH_DRIVER
+Am29F040_Initialize(
+ IN PUCHAR NvRamPtr
+ );
+
+ARC_STATUS
+Am29F040_SetReadMode(
+ IN PUCHAR Address
+ );
+
+ARC_STATUS
+Am29F040_WriteByte(
+ IN PUCHAR Address,
+ IN UCHAR Data
+ );
+
+ARC_STATUS
+Am29F040_EraseBlock(
+ IN PUCHAR Address
+ );
+
+ARC_STATUS
+Am29F040_CheckStatus(
+ IN PUCHAR Address,
+ IN UCHAR Data,
+ IN FLASH_OPERATIONS Operation
+ );
+
+PUCHAR
+Am29F040_BlockAlign(
+ IN PUCHAR Address
+ );
+
+UCHAR
+Am29F040_ReadByte(
+ IN PUCHAR Address
+ );
+
+BOOLEAN
+Am29F040_OverwriteCheck(
+ IN UCHAR OldData,
+ IN UCHAR NewData
+ );
+
+ULONG
+Am29F040_BlockSize(
+ IN PUCHAR Address
+ );
+
+ULONG
+Am29F040_GetLastError(
+ VOID
+ );
+
+static
+VOID
+Am29F040_SetLastError(
+ ULONG FlashStatus
+ );
+
+FLASH_DRIVER Am29F040_DriverInformation = {
+ Am29F040_DEVICE_NAME,
+ Am29F040_SetReadMode, // SetReadModeFunction
+ Am29F040_WriteByte, // WriteByteFunction
+ Am29F040_EraseBlock, // EraseBlockFunction
+ Am29F040_BlockAlign, // AlignBlockFunction
+ Am29F040_ReadByte, // ReadByteFunction
+ Am29F040_OverwriteCheck, // OverwriteCheckFunction
+ Am29F040_BlockSize, // BlockSizeFunction
+ Am29F040_GetLastError, // GetLastErrorFunction
+ Am29F040_DEVICE_SIZE, // DeviceSize
+ BLANK_DATA // ErasedData
+ };
+
+FLASH_DRIVER Am29F080_DriverInformation = {
+ Am29F080_DEVICE_NAME,
+ Am29F040_SetReadMode, // SetReadModeFunction
+ Am29F040_WriteByte, // WriteByteFunction
+ Am29F040_EraseBlock, // EraseBlockFunction
+ Am29F040_BlockAlign, // AlignBlockFunction
+ Am29F040_ReadByte, // ReadByteFunction
+ Am29F040_OverwriteCheck, // OverwriteCheckFunction
+ Am29F040_BlockSize, // BlockSizeFunction
+ Am29F040_GetLastError, // GetLastErrorFunction
+ Am29F080_DEVICE_SIZE, // DeviceSize
+ BLANK_DATA // ErasedData
+ };
+
+
+static ULONG Am29F040_LastError;
+
+PFLASH_DRIVER
+Am29F040_Initialize(
+ IN PUCHAR NvRamPtr
+ )
+{
+ PFLASH_DRIVER ReturnDriver = NULL;
+ UCHAR ManufacturerID;
+ UCHAR DeviceID;
+
+ NvRamPtr = Am29F040_BlockAlign(NvRamPtr);
+
+ COMMAND_PREFIX(NvRamPtr);
+ WRITE_CONFIG_RAM_DATA(COMMAND_ADDRESS(NvRamPtr), ID_REQUEST);
+
+ ManufacturerID = READ_CONFIG_RAM_DATA(NvRamPtr);
+ DeviceID = READ_CONFIG_RAM_DATA((PUCHAR)((ULONG)NvRamPtr + 1));
+
+ if ((ManufacturerID == MANUFACTURER_ID) &&
+ (DeviceID == Am29F040_DEVICE_ID)) {
+
+ Am29F040_LastError = 0;
+ Am29F040_SetReadMode(NvRamPtr);
+ ReturnDriver = &Am29F040_DriverInformation;
+ }
+
+ return ReturnDriver;
+}
+
+PFLASH_DRIVER
+Am29F080_Initialize(
+ IN PUCHAR NvRamPtr
+ )
+{
+ PFLASH_DRIVER ReturnDriver = NULL;
+ UCHAR ManufacturerID;
+ UCHAR DeviceID;
+
+ NvRamPtr = Am29F040_BlockAlign(NvRamPtr);
+
+ COMMAND_PREFIX(NvRamPtr);
+ WRITE_CONFIG_RAM_DATA(COMMAND_ADDRESS(NvRamPtr), ID_REQUEST);
+
+ ManufacturerID = READ_CONFIG_RAM_DATA(NvRamPtr);
+ DeviceID = READ_CONFIG_RAM_DATA((PUCHAR)((ULONG)NvRamPtr + 1));
+
+ if ((ManufacturerID == MANUFACTURER_ID) &&
+ (DeviceID == Am29F080_DEVICE_ID)) {
+
+ Am29F040_LastError = 0;
+ Am29F040_SetReadMode(NvRamPtr);
+ ReturnDriver = &Am29F080_DriverInformation;
+ }
+
+ return ReturnDriver;
+}
+
+ARC_STATUS
+Am29F040_SetReadMode(
+ IN PUCHAR NvRamPtr
+ )
+{
+ COMMAND_PREFIX(NvRamPtr);
+ WRITE_CONFIG_RAM_DATA(COMMAND_ADDRESS(NvRamPtr), SET_READ_ARRAY);
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+Am29F040_WriteByte(
+ IN PUCHAR NvRamPtr,
+ IN UCHAR Data
+ )
+{
+ ARC_STATUS ReturnStatus;
+
+ Am29F040_SetReadMode(NvRamPtr);
+
+ COMMAND_PREFIX(NvRamPtr);
+ WRITE_CONFIG_RAM_DATA(COMMAND_ADDRESS(NvRamPtr), SET_BYTE_WRITE);
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, Data);
+
+ ReturnStatus = Am29F040_CheckStatus(NvRamPtr, Data, FlashByteWrite);
+
+ Am29F040_SetReadMode(NvRamPtr);
+
+ return ReturnStatus;
+}
+
+ARC_STATUS
+Am29F040_EraseBlock (
+ IN PUCHAR NvRamPtr
+ )
+{
+ ARC_STATUS ReturnStatus;
+
+ NvRamPtr = Am29F040_BlockAlign(NvRamPtr);
+
+ COMMAND_PREFIX(NvRamPtr);
+ WRITE_CONFIG_RAM_DATA(COMMAND_ADDRESS(NvRamPtr), SET_ERASE);
+ COMMAND_PREFIX(NvRamPtr);
+ WRITE_CONFIG_RAM_DATA(COMMAND_ADDRESS(NvRamPtr), CONFIRM_ERASE_BLOCK);
+
+ ReturnStatus = Am29F040_CheckStatus(NvRamPtr, 0xff, FlashEraseBlock);
+
+ Am29F040_SetReadMode(NvRamPtr);
+
+ return ReturnStatus;
+}
+
+ARC_STATUS
+Am29F040_CheckStatus (
+ IN PUCHAR NvRamPtr,
+ IN UCHAR Data,
+ IN FLASH_OPERATIONS Operation
+ )
+{
+ ARC_STATUS ReturnStatus = EIO;
+ BOOLEAN StopReading = FALSE;
+ UCHAR FlashStatus;
+ ULONG Timeout;
+
+#if 0
+ //
+ // Keep reading the status until the device is done with its
+ // current operation.
+ //
+ do {
+ FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr);
+ if (FlashStatus & 0x20) {
+ StopReading = TRUE;
+ FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr);
+ }
+ } while (!StopReading && (((FlashStatus ^ Data) & 0x80) != 0));
+
+ if ((FlashStatus ^ Data) != 0) {
+ ReturnStatus = ESUCCESS;
+ } else {
+ ReturnStatus = EIO;
+ }
+
+ return ReturnStatus;
+#else
+ //
+ // If we are doing an erase command, check whether the erase command
+ // was accepted. This is supposed to happen within the first 100 usec.
+ //
+
+ if (Operation == FlashEraseBlock) {
+ Timeout = TIMEOUT_VALUE;
+
+ while (((READ_CONFIG_RAM_DATA(NvRamPtr) & 0x08) != 0x08) &&
+ (Timeout > 0)) {
+ KeStallExecutionProcessor(1);
+ Timeout--;
+ }
+
+ if (Timeout == 0) {
+ ReturnStatus = EIO;
+ Am29F040_SetLastError(0);
+ return ReturnStatus;
+ }
+ }
+
+ //
+ // Now wait for the actual status
+ //
+ Timeout = TIMEOUT_VALUE;
+ do {
+ FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr);
+
+ if (((FlashStatus ^ Data) & 0x80) == 0) {
+ ReturnStatus = ESUCCESS;
+ break;
+ }
+
+ if (FlashStatus & 0x20) {
+ if (((READ_CONFIG_RAM_DATA(NvRamPtr) ^ Data) & 0x80) == 0) {
+ ReturnStatus = ESUCCESS;
+ break;
+ } else {
+ ReturnStatus = EIO;
+ Am29F040_SetLastError(Operation | 0x80000000);
+ break;
+ }
+ }
+ KeStallExecutionProcessor(1);
+ Timeout--;
+ } while (Timeout > 0);
+
+ if (Timeout == 0) {
+ ReturnStatus = EIO;
+ Am29F040_SetLastError(0);
+ }
+
+ return ReturnStatus;
+#endif
+}
+
+PUCHAR
+Am29F040_BlockAlign(
+ IN PUCHAR Address
+ )
+{
+ return BLOCK_ALIGN(Address);
+}
+
+UCHAR
+Am29F040_ReadByte(
+ IN PUCHAR Address
+ )
+{
+ return READ_CONFIG_RAM_DATA(Address);
+}
+
+BOOLEAN
+Am29F040_OverwriteCheck(
+ IN UCHAR OldData,
+ IN UCHAR NewData
+ )
+/*++
+
+Return Value:
+
+ TRUE if OldData can be overwritten with NewData.
+ FALSE if OldData must be erased before writing NewData.
+
+--*/
+{
+ return (~OldData & NewData) ? FALSE : TRUE;
+}
+
+ULONG
+Am29F040_BlockSize(
+ IN PUCHAR Address
+ )
+{
+ return BLOCK_SIZE;
+}
+
+ULONG
+Am29F040_GetLastError(
+ VOID
+ )
+{
+ return Am29F040_LastError;
+}
+
+static
+VOID
+Am29F040_SetLastError(
+ ULONG FlashStatus
+ )
+{
+ Am29F040_LastError = ERROR_UNKNOWN;
+ if (FlashStatus == 0) {
+ Am29F040_LastError = ERROR_TIMEOUT;
+ } else {
+ switch(FlashStatus & ~0x80000000) {
+ case FlashByteWrite:
+ Am29F040_LastError = ERROR_WRITE_ERROR;
+ break;
+ case FlashEraseBlock:
+ Am29F040_LastError = ERROR_ERASE_ERROR;
+ break;
+ }
+ }
+}
diff --git a/private/ntos/nthals/halalpha/adjust.c b/private/ntos/nthals/halalpha/adjust.c
new file mode 100644
index 000000000..cc8aa4e84
--- /dev/null
+++ b/private/ntos/nthals/halalpha/adjust.c
@@ -0,0 +1,149 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ adjust.c
+
+Abstract:
+
+ This module contains platform-independent slot resource adjust routines.
+
+Author:
+
+ Eric Rehm 6-January-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpAdjustResourceListUpperLimits)
+#endif
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ )
+/*++
+
+Routine Description:
+
+ Adjust a pResource list with respect to the upper bounds supplied.
+ (A resource is changed only if it execceds the maximum.)
+
+Arguments:
+
+ pResouceList - Resource list to be checked.
+
+ MaximumPortAddress - Maximum I/O port allowed.
+
+ MaximumMemoryAddress - Maximum I/O memory address allowed.
+
+ MaximumInterruptVector - Maximum interrupt vector allowed.
+
+ MaximumDmaChannel - Maximum dma channel allowed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+
+ //
+ // Walk each ResourceList and shrink any values to system limits
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ //
+ // Make sure descriptor limits fall within the
+ // CompleteList->InterfaceType & CompleteList->BusNumber.
+ //
+ //
+
+ switch (Descriptor->Type) {
+ case CmResourceTypePort:
+ if (Descriptor->u.Port.MaximumAddress.QuadPart >
+ MaximumPortAddress.QuadPart) {
+
+ Descriptor->u.Port.MaximumAddress = MaximumPortAddress;
+ }
+
+ break;
+
+ case CmResourceTypeInterrupt:
+ if (Descriptor->u.Interrupt.MaximumVector >
+ MaximumInterruptVector ) {
+
+ Descriptor->u.Interrupt.MaximumVector =
+ MaximumInterruptVector;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+ if (Descriptor->u.Memory.MaximumAddress.QuadPart >
+ MaximumMemoryAddress.QuadPart) {
+
+ Descriptor->u.Memory.MaximumAddress =
+ MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (Descriptor->u.Dma.MaximumChannel >
+ MaximumDmaChannel ) {
+
+ Descriptor->u.Dma.MaximumChannel =
+ MaximumDmaChannel;
+ }
+ break;
+
+#if DBG
+ default:
+ DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
+ break;
+#endif
+ }
+
+ //
+ // Next descriptor
+ //
+ Descriptor++;
+ }
+
+ //
+ // Next Resource List
+ //
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+ }
+
+}
+
diff --git a/private/ntos/nthals/halalpha/allstart.c b/private/ntos/nthals/halalpha/allstart.c
new file mode 100644
index 000000000..9bb5501bc
--- /dev/null
+++ b/private/ntos/nthals/halalpha/allstart.c
@@ -0,0 +1,55 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ John Vert (jvert) 23-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halalpha/alphaio.s b/private/ntos/nthals/halalpha/alphaio.s
new file mode 100644
index 000000000..ce9dd652b
--- /dev/null
+++ b/private/ntos/nthals/halalpha/alphaio.s
@@ -0,0 +1,1368 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alphaio.s
+
+
+Abstract:
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ 12-Jul-1994 - Eric Rehm - Added dense space I/O
+
+ 27-July-1994 - Sameer Dekate
+
+ Make a common file for all machines and optimize Read/Write
+ register buffer routines. Made a common routine with different
+ entry points for READ & WRITE_REGISTER_BUFFER routines
+
+--*/
+
+#include "chipset.h"
+#include "halalpha.h"
+
+
+
+ SBTTL( "Read I/O byte" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(READ_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ mb
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extbl v0, t3, v0 // get correct byte
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_UCHAR
+
+
+ SBTTL( "Read I/O word(16 bits)" )
+//++
+//
+// USHORT
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(READ_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // get the longword
+ extwl v0,t3,v0 // get the correct word
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0,t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extwl v0, t3, v0 // get correct word
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_USHORT
+
+
+ SBTTL( "Read I/O longword(32 bits)" )
+//++
+//
+// ULONG
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(READ_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // read the longword
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_ULONG
+
+ SBTTL( "Write I/O byte" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva,
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Writes a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ insbl a1,t3,t4 // put the byte in the correct position
+ stl t4, (t0) // write the byte
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+ insbl a1, t3, t2 // put byte into position
+ bis t1, t2, t1 // merge byte in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write I/O word (16 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva,
+// IN USHORT Value
+// )
+//
+// Routine Description:
+//
+// Writes a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1,t3,t2 // put the word in the correct place
+ stl t2, (t0) // write the word
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, t2 // put word into position
+ bis t1, t2, t1 // merge in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write I/O longword (32 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ stl a1, (a0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_ULONG
+
+
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ addl a1, 4, a1 // increment buffer
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ ldil t8, 1 // DENSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ ldil t8, 0 // SPARSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+ beq t8, 11f // if not DENSE goto 11f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 12f
+11:
+ ldl v0, 0(t0) // get the longword
+12:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ beq t8, 51f // if not DENSE goto 51f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 52f
+51:
+ ldl v0, 0(t0) // get the longword
+52:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+ beq t8, 81f // if not DENSE goto 81f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 82f
+81:
+ ldl v0, 0(t0) // get the longword
+82:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ beq t8, 121f // if not DENSE goto 121f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 122f
+121:
+ ldl v0, 0(t0) // get the longword
+122:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ ldil t7, 1 // DENSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ ldil t7, 0 // SPARSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 11f // if not DENSE goto 11f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 12f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+11:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+
+12:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 51f // if not DENSE goto 51f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 52f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+51:
+ stl t1, 0(t0) // store to buffer
+
+52:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 81f // if not DENSE goto 81f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 82f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+81:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+
+82:
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 121f // if not DENSE goto 122f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 122f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+121:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+
+122:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
diff --git a/private/ntos/nthals/halalpha/am29f400.c b/private/ntos/nthals/halalpha/am29f400.c
new file mode 100644
index 000000000..319583a84
--- /dev/null
+++ b/private/ntos/nthals/halalpha/am29f400.c
@@ -0,0 +1,543 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ am29f400.c
+
+Abstract:
+
+ This module contains the platform independent code to access the AMD
+ flash ROM part AM29F400.
+
+Author:
+
+ Wim Colgate, 5/12/95
+
+Environment:
+
+ Firmware/Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include <flash8k.h>
+#include "flashbus.h"
+#include "am29f400.h"
+
+//
+// External prototypes
+//
+
+VOID pWriteFlashByte(
+ IN ULONG FlashOffset,
+ IN UCHAR Data
+ );
+
+UCHAR pReadFlashByte(
+ IN ULONG FlashOffset
+ );
+
+//
+// Local function prototypes
+//
+
+PFLASH_DRIVER
+Am29F400_Initialize(
+ IN ULONG FlashOffset
+ );
+
+ARC_STATUS
+Am29F400_SetReadMode(
+ IN PUCHAR FlashOffset
+ );
+
+ARC_STATUS
+Am29F400_WriteByte(
+ IN PUCHAR FlashOffset,
+ IN UCHAR Data
+ );
+
+ARC_STATUS
+Am29F400_EraseSector(
+ IN PUCHAR FlashOffset
+ );
+
+ARC_STATUS
+Am29F400_CheckStatus(
+ IN PUCHAR FlashOffset,
+ IN FLASH_OPERATIONS Operation,
+ IN UCHAR OptionalData
+ );
+
+PUCHAR
+Am29F400_SectorAlign(
+ IN PUCHAR FlashOffset
+ );
+
+UCHAR
+Am29F400_ReadByte(
+ IN PUCHAR FlashOffset
+ );
+
+BOOLEAN
+Am29F400_OverwriteCheck(
+ IN UCHAR OldData,
+ IN UCHAR NewData
+ );
+
+ULONG
+Am29F400_SectorSize(
+ IN PUCHAR FlashOffset
+ );
+
+FLASH_DRIVER Am29F400_DriverInformation = {
+ "AMD Am29F400",
+ Am29F400_SetReadMode, // SetReadModeFunction
+ Am29F400_WriteByte, // WriteByteFunction
+ Am29F400_EraseSector, // EraseSectorFunction
+ Am29F400_SectorAlign, // AlignSectorFunction
+ Am29F400_ReadByte, // ReadByteFunction
+ Am29F400_OverwriteCheck, // OverwriteCheckFunction
+ Am29F400_SectorSize, // SectorSizeFunction
+// NULL, // Get last error
+ Am29F400_DEVICE_SIZE, // DeviceSize
+ Am29F400_ERASED_DATA // What an erased data looks like
+ };
+
+//
+// This variable tells us which bank of 8K 'nvram' are we using
+// The LX3 nvram is actually two separate 8K sections of the FLASH ROM.
+// One living at 0x4000, the other at 0x6000.
+//
+// This is NOT a QVA (which will is aliased by HalpCMOSBase in common
+// code. Rather it is an offset within the FLASH ROM where the NVRAM lives.
+//
+
+extern PVOID HalpCMOSRamBase;
+ULONG Am29F400NVRAMBase;
+
+
+static UCHAR am29F400_GetSectorNumber(
+ IN PUCHAR FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine figures out which sector number we are in (for use in
+ clearing the sector...)
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+Return Value:
+
+ The sector number within the range of the offset.
+
+--*/
+{
+ ULONG Offset = (ULONG)FlashOffset;
+
+ if (Offset < SECTOR_1_BASE) {
+ return 0;
+ } else if (Offset < SECTOR_2_BASE) {
+ return 1;
+ } else if (Offset < SECTOR_3_BASE) {
+ return 2;
+ } else if (Offset < SECTOR_4_BASE) {
+ return 3;
+ } else {
+
+ //
+ // All other sectors are 0x10000, 0x20000, etc, so shift right by 64K,
+ // Then add the preceding section offset's
+ //
+
+ return (UCHAR)((Offset >> 16) + 3);
+ }
+
+ return 0;
+
+}
+
+
+PFLASH_DRIVER
+Am29F400_Initialize(
+ IN ULONG FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine spanks the FLASH ROM with the auto select command, which
+ allows us to make sure that the device is what we think it is.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+Return Value:
+
+ NULL for no driver, or the address of the FLASH_DRIVER structure for
+ this driver.
+
+--*/
+{
+ PFLASH_DRIVER ReturnDriver = NULL;
+ UCHAR ManufacturerID;
+ UCHAR DeviceID;
+ UCHAR temp;
+
+ Am29F400_SetReadMode((PUCHAR)SECTOR_2_BASE); // first 8K section (NVRAM)
+
+ HalpStallExecution(50); // wkc -- GACK! what a bogus part
+
+ pWriteFlashByte(COMMAND_ADDR1, COMMAND_DATA1);
+ pWriteFlashByte(COMMAND_ADDR2, COMMAND_DATA2);
+ pWriteFlashByte(COMMAND_ADDR3, COMMAND_DATA3_AUTOSELECT);
+
+ //
+ // Get manufacturer and device ID. Note spec says device ID lives
+ // at byte 1, but empirical evidence says it is at byte 2.
+ //
+
+ ManufacturerID = Am29F400_ReadByte((PUCHAR)0x00);
+ DeviceID = Am29F400_ReadByte((PUCHAR)0x02);
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Manufacturer ID (expect 0x1) %x\n", ManufacturerID);
+ DbgPrint("Device ID (expect 0xab) %x\n", DeviceID);
+#endif
+
+ if ((ManufacturerID == MANUFACTURER_ID) && (DeviceID == DEVICE_ID)) {
+ Am29F400_SetReadMode(0x0);
+ Am29F400_SetReadMode((PUCHAR)SECTOR_2_BASE);
+
+ // wkcfix -- check which NVRAM section we should use.
+ // currently use the first one setup in the HalpMapIoSpace() routine.
+
+ Am29F400NVRAMBase = (ULONG)HalpCMOSRamBase;
+ ReturnDriver = &Am29F400_DriverInformation;
+ }
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ if (ReturnDriver == NULL) {
+ DbgPrint("FLASH part unknown; AMD Am29F400 not loaded\n");
+ }
+#endif
+
+ return ReturnDriver;
+}
+
+
+ARC_STATUS
+Am29F400_SetReadMode(
+ IN PUCHAR FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine spanks the FLASH ROM with the read reset routine.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM -- but not used.
+
+Return Value:
+
+ The value of the check status routine (EIO or ESUCCESS)
+
+--*/
+{
+
+ pWriteFlashByte((ULONG)FlashOffset, COMMAND_READ_RESET);
+
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+Am29F400_WriteByte(
+ IN PUCHAR FlashOffset,
+ IN UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This routine spanks the FLASH ROM with the program command, then calls
+ the check status routine -- then resets the device to read.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+ Data - the data byte to write.
+
+Return Value:
+
+ The value of the check status routine (EIO or ESUCCESS)
+
+--*/
+{
+ ARC_STATUS ReturnStatus;
+
+ pWriteFlashByte(COMMAND_ADDR1, COMMAND_DATA1);
+ pWriteFlashByte(COMMAND_ADDR2, COMMAND_DATA2);
+ pWriteFlashByte(COMMAND_ADDR3, COMMAND_DATA3_PROGRAM);
+
+ ASSERT((FlashOffset >= (PUCHAR)0x4000) && (FlashOffset < (PUCHAR)0x8000));
+
+ pWriteFlashByte((ULONG)FlashOffset, Data);
+
+ ReturnStatus = Am29F400_CheckStatus(FlashOffset, FlashByteWrite, Data);
+
+ Am29F400_SetReadMode(FlashOffset);
+
+ return ReturnStatus;
+}
+
+
+ARC_STATUS
+Am29F400_EraseSector(
+ IN PUCHAR FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine spanks the FLASH ROM with the erase sector command, then calls
+ the check status routine
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+Return Value:
+
+ The value of the check status routine (EIO or ESUCCESS)
+
+--*/
+{
+ ARC_STATUS ReturnStatus;
+ UCHAR ReadBack;
+ ULONG Count = MAX_FLASH_READ_ATTEMPTS;
+
+ Am29F400_SetReadMode(FlashOffset);
+
+ pWriteFlashByte(COMMAND_ADDR1, COMMAND_DATA1);
+ pWriteFlashByte(COMMAND_ADDR2, COMMAND_DATA2);
+ pWriteFlashByte(COMMAND_ADDR3, COMMAND_DATA3);
+ pWriteFlashByte(COMMAND_ADDR4, COMMAND_DATA4);
+ pWriteFlashByte(COMMAND_ADDR5, COMMAND_DATA5);
+ pWriteFlashByte((ULONG)FlashOffset, COMMAND_DATA6_SECTOR_ERASE);
+
+ HalpStallExecution(80); // short stall for erase command to take
+
+ ReturnStatus = Am29F400_CheckStatus(FlashOffset,
+ FlashEraseSector,
+ 0xff);
+
+ Am29F400_SetReadMode(FlashOffset);
+
+ return ReturnStatus;
+
+}
+
+
+ARC_STATUS
+Am29F400_CheckStatus (
+ IN PUCHAR FlashOffset,
+ IN FLASH_OPERATIONS Operation,
+ IN UCHAR OptionalData
+ )
+/*++
+
+Routine Description:
+
+ This routine checks the status of the flashbus operation. The operation
+ may be specific, so different actions may be taken.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+ Opertaion - the operation performed on the FlashOffset.
+ OptionalData - an optional data value that may be needed for verification.
+
+Return Value:
+
+ EIO for faiure
+ ESUCCESS for success
+
+--*/
+{
+ ARC_STATUS ReturnStatus = EIO;
+ UCHAR FlashRead;
+ ULONG Count = 0;
+ ULONG DataOK = FALSE;
+
+ while ((DataOK == FALSE) && (Count < MAX_FLASH_READ_ATTEMPTS)) {
+
+ FlashRead = Am29F400_ReadByte(FlashOffset);
+
+ //
+ // Both FlashByteWrite & FlashEraseBlock checks use polling
+ // algorithm found on page 1-131 of the AMD part specification
+ //
+
+ if ((FlashRead & 0x80) == (OptionalData & 0x80)) {
+ DataOK = TRUE;
+ } else if (FlashRead & 0x20) {
+ FlashRead = Am29F400_ReadByte(FlashOffset);
+ if ((FlashRead & 0x80) == (OptionalData & 0x80)) {
+ DataOK = TRUE;
+ } else {
+ break;
+ }
+ }
+ Count++;
+ }
+
+ if (DataOK == TRUE) {
+ ReturnStatus = ESUCCESS;
+ }
+
+ return ReturnStatus;
+}
+
+
+PUCHAR
+Am29F400_SectorAlign(
+ IN PUCHAR FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the base offset that the current offset within
+ a sector of the flash ROM.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+Return Value:
+
+ The base offset of the current sector -- as defined by the FlashOffset.
+
+--*/
+{
+ ULONG Offset = (ULONG)FlashOffset;
+
+ if (Offset < SECTOR_2_BASE) {
+ return (PUCHAR)SECTOR_1_BASE;
+ } else if (Offset < SECTOR_3_BASE) {
+ return (PUCHAR)SECTOR_2_BASE;
+ } else if (Offset < SECTOR_4_BASE) {
+ return (PUCHAR)SECTOR_3_BASE;
+ } else if (Offset < SECTOR_5_BASE) {
+ return (PUCHAR)SECTOR_4_BASE;
+ } else {
+ return (PUCHAR)(ULONG)(Offset & ~(SECTOR_5_SIZE-1));
+ }
+}
+
+
+UCHAR
+Am29F400_ReadByte(
+ IN PUCHAR FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine spanks the FLASH ROM with the read command, then calls
+ the read flash bus function.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+
+Return Value:
+
+ The character at the appropriate location.
+
+--*/
+{
+ UCHAR ReturnVal;
+
+ //
+ // Assume Read mode is on
+ //
+
+ ReturnVal = pReadFlashByte((ULONG)FlashOffset);
+
+ return ReturnVal;
+}
+
+
+BOOLEAN
+Am29F400_OverwriteCheck(
+ IN UCHAR OldData,
+ IN UCHAR NewData
+ )
+/*++
+
+Routine Description:
+
+ This routine returns if we can safely overwrite an existing data
+ with new data. Flash Rom's can go from 1-->1, 1-->0 and 0-->0, but
+ cannot go from 0-->1.
+
+Return Value:
+
+
+ TRUE if we can safely overwrite
+ FALSE if we cannot safely overwrite
+
+--*/
+{
+ return ((NewData & ~OldData) == 0) ? TRUE: FALSE;
+}
+
+
+ULONG
+Am29F400_SectorSize(
+ IN PUCHAR FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the size of the sector that the offset is within.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+
+Return Value:
+
+ The block size of the sector.
+
+--*/
+{
+ if (FlashOffset < (PUCHAR)SECTOR_2_BASE) {
+ return SECTOR_1_SIZE;
+ } else if (FlashOffset < (PUCHAR)SECTOR_3_BASE) {
+ return SECTOR_2_SIZE;
+ } else if (FlashOffset < (PUCHAR)SECTOR_4_BASE) {
+ return SECTOR_3_SIZE;
+ } else if (FlashOffset < (PUCHAR)SECTOR_5_BASE) {
+ return SECTOR_4_SIZE;
+ } else {
+ return SECTOR_5_SIZE;
+ }
+}
diff --git a/private/ntos/nthals/halalpha/am29f400.h b/private/ntos/nthals/halalpha/am29f400.h
new file mode 100644
index 000000000..61e3f1774
--- /dev/null
+++ b/private/ntos/nthals/halalpha/am29f400.h
@@ -0,0 +1,97 @@
+#ifndef _AM29F400_H_
+#define _AM29F400_H_
+
+//
+// The AMD is a full 1/2 megabyte broken into the following sectors:
+//
+// 0x00000 .. 0x03fff -- > Section 1 // SROM
+// 0x04000 .. 0x05fff -- > Section 2 // NVRAM_0
+// 0x06000 .. 0x07fff -- > Section 3 // NVRAM_1
+// 0x08000 .. 0x0ffff -- > Section 4 // DROM
+// 0x10000 .. 0x1ffff -- > Section 5 // ARC starts here
+// 0x20000 .. 0x2ffff -- > Section 6
+// 0x30000 .. 0x3ffff -- > Section 7
+// 0x40000 .. 0x4ffff -- > Section 8
+// 0x50000 .. 0x5ffff -- > Section 8
+// 0x60000 .. 0x6ffff -- > Section 9
+// 0x70000 .. 0x7ffff -- > Section 10
+
+//
+// Name the blocks
+//
+
+#define SECTOR_1_BASE 0x0
+#define SECTOR_2_BASE 0x4000
+#define SECTOR_3_BASE 0x6000
+#define SECTOR_4_BASE 0x8000
+#define SECTOR_5_BASE 0x10000
+
+#define SECTOR_1_SIZE (SECTOR_2_BASE - SECTOR_1_BASE)
+#define SECTOR_2_SIZE (SECTOR_3_BASE - SECTOR_2_BASE)
+#define SECTOR_3_SIZE (SECTOR_4_BASE - SECTOR_3_BASE)
+#define SECTOR_4_SIZE (SECTOR_5_BASE - SECTOR_4_BASE)
+#define SECTOR_5_SIZE 0x10000
+#define ARC_SECTOR_SIZE SECTOR_5_SIZE
+
+//
+// The largest addressable offset
+//
+
+#define Am29F400_DEVICE_SIZE 0x7ffff
+
+//
+// What an erased data byte looks like
+//
+
+#define Am29F400_ERASED_DATA 0xff
+
+//
+// The command writing sequence for read/auto select/write
+//
+
+#define COMMAND_READ_RESET 0xf0
+
+#define COMMAND_ADDR1 0xaaaa
+#define COMMAND_DATA1 0xaa
+
+#define COMMAND_ADDR2 0x5555
+#define COMMAND_DATA2 0x55
+
+#define COMMAND_ADDR3 0xaaaa
+#define COMMAND_DATA3_READ 0xf0 // then {addr,data}
+#define COMMAND_DATA3_AUTOSELECT 0x90
+#define COMMAND_DATA3_PROGRAM 0xA0 // then {addr,data}
+#define COMMAND_DATA3 0x80 // for the additional ops
+
+//
+// and additional bus cyles for chip and sector erase
+//
+
+#define COMMAND_ADDR4 0xaaaa
+#define COMMAND_DATA4 0xaa
+
+#define COMMAND_ADDR5 0x5555
+#define COMMAND_DATA5 0x55
+
+// for SECTOR ERASE, the addr is the sector number
+#define COMMAND_DATA6_SECTOR_ERASE 0x30
+
+#define COMMAND_ADDR6 0xaaaa
+#define COMMAND_DATA6_CHIP_ERASE 0x10
+
+//
+// This is the Am29F400 made by AMD
+//
+
+#define MANUFACTURER_ID 0x01
+#define DEVICE_ID 0xab
+
+//
+// Max attempts
+//
+
+#define MAX_FLASH_READ_ATTEMPTS 0x800000
+
+#include "pflash.h"
+
+#endif // _AM29F400_H_
diff --git a/private/ntos/nthals/halalpha/apecs.c b/private/ntos/nthals/halalpha/apecs.c
new file mode 100644
index 000000000..7c5a5918a
--- /dev/null
+++ b/private/ntos/nthals/halalpha/apecs.c
@@ -0,0 +1,337 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ apecs.c
+
+Abstract:
+
+ This module implements functions that are specific to the APECS
+ chip-set.
+
+Author:
+
+ Joe Notarangelo 18-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "apecs.h"
+
+VOID
+DumpEpic(
+ VOID
+ );
+
+//
+// Globals
+//
+
+//
+// Parity checking is a tri-state variable, unknown == all f's. Which means
+// Keep checking disabled until we can determine what we want to set it to,
+// which then means 1 or 0.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+
+VOID
+HalpApecsInitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ APECS_WINDOW_NUMBER WindowNumber
+ )
+/*++
+
+Routine Description:
+
+ Initialize the DMA Control software window registers for the specified
+ DMA Window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control.
+
+ WindowNumber - Supplies the window number initialized. (0 = Isa Dma
+ Window, 1 = Master Dma Window).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ switch( WindowNumber ){
+
+ //
+ // The ISA DMA Window.
+ //
+
+ case ApecsIsaWindow:
+
+ WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->TranslatedBase1Register;
+ WindowRegisters->WindowBaseRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciBase1Register;
+ WindowRegisters->WindowMaskRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciMask1Register;
+ WindowRegisters->WindowTbiaRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->TbiaRegister;
+
+ break;
+
+ case ApecsMasterWindow:
+
+ WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->TranslatedBase2Register;
+ WindowRegisters->WindowBaseRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciBase2Register;
+ WindowRegisters->WindowMaskRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciMask2Register;
+ WindowRegisters->WindowTbiaRegister =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->TbiaRegister;
+
+ break;
+
+ default:
+
+#if DBG
+
+ DbgPrint( "ApecsInitializeSfwWindow: Bad Window Number = %x\n",
+ WindowNumber );
+
+#endif //DBG
+
+ break;
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpApecsProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ Program the control windows in the hardware so that DMA can be started
+ to the DMA window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ MapRegisterBase - Supplies the logical address of the scatter/gather
+ array in system memory.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ EPIC_ECSR Ecsr;
+ EPIC_PCIBASE PciBase;
+ EPIC_PCIMASK PciMask;
+ EPIC_TBASE TBase;
+ PVOID RegisterQva;
+
+ PciBase.Reserved = 0;
+ PciBase.Wenr = 1;
+ PciBase.Sgen = 1;
+ PciBase.BaseValue = (ULONG)(WindowRegisters->WindowBase) >> 20;
+
+ PciMask.Reserved = 0;
+ PciMask.MaskValue = (WindowRegisters->WindowSize >> 20) - 1;
+
+ TBase.Reserved = 0;
+ TBase.TBase = (ULONG)(MapRegisterBase) >> 10;
+
+#if DBG
+
+ //
+ // Dump the EPIC registers.
+ //
+
+ DumpEpic();
+
+#endif //DBG
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_EPIC_REGISTER( WindowRegisters->WindowBaseRegister, (ULONG)0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_EPIC_REGISTER( WindowRegisters->TranslatedBaseRegister,
+ *(PULONG)&TBase );
+
+ WRITE_EPIC_REGISTER( WindowRegisters->WindowMaskRegister,
+ *(PULONG)&PciMask );
+
+ WRITE_EPIC_REGISTER( WindowRegisters->WindowBaseRegister,
+ *(PULONG)&PciBase );
+
+ //
+ // Invalidate any translations that might have existed for this window.
+ //
+
+ WRITE_EPIC_REGISTER( WindowRegisters->WindowTbiaRegister, 0 );
+
+ //
+ // Enable the translation buffer inside of the EPIC.
+ //
+
+ RtlZeroMemory( &Ecsr, sizeof(EPIC_ECSR) );
+ Ecsr.Tenb = 1;
+
+ //
+ // Tri state parity checking - keep disabled if not determined
+ // yet. otherwise, Whack the PCI parity disable bit with the stored
+ // value
+ //
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+ Ecsr.Dpec = 1;
+ } else {
+ Ecsr.Dpec = HalDisablePCIParityChecking;
+ }
+
+#if HALDBG
+ if (HalDisablePCIParityChecking == 0) {
+ DbgPrint("apecs: PCI Parity Checking ON\n");
+ } else if (HalDisablePCIParityChecking == 1) {
+ DbgPrint("apecs: PCI Parity Checking OFF\n");
+ } else {
+ DbgPrint("apecs: PCI Parity Checking OFF - not set by ARC yet\n");
+ }
+#endif
+
+ RegisterQva =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister;
+ WRITE_EPIC_REGISTER( RegisterQva,
+ *(PULONG)&Ecsr );
+
+#if DBG
+
+ //
+ // Dump the EPIC registers.
+ //
+
+ DumpEpic();
+
+#endif //DBG
+
+ return;
+}
+
+ULONG
+READ_EPIC_REGISTER(
+ PVOID
+ );
+
+#if DBG
+
+VOID
+DumpEpic(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting EPIC registers and print them to the debug port.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ ULONG Value;
+
+ DbgPrint( "Dumping the EPIC registers\n" );
+
+ RegisterQva =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "ECSR = %x\n", Value );
+
+ RegisterQva =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->TranslatedBase1Register;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "TBASE1 = %x\n", Value );
+
+ RegisterQva =
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->TranslatedBase2Register;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "TBASE2 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciBase1Register;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "PCIBASE1 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciBase2Register;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "PCIBASE2 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciMask1Register;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "PCIMASK1 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciMask2Register;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "PCIMASK2 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr0;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "HAXR0 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "HAXR1 = %x\n", Value );
+
+ RegisterQva = &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2;
+ Value = READ_EPIC_REGISTER( RegisterQva );
+ DbgPrint( "HAXR2 = %x\n", Value );
+
+ DbgPrint( "--end EPIC dump\n\n" );
+
+ return;
+
+}
+
+#endif //DBG
diff --git a/private/ntos/nthals/halalpha/apecs.h b/private/ntos/nthals/halalpha/apecs.h
new file mode 100644
index 000000000..97b24809d
--- /dev/null
+++ b/private/ntos/nthals/halalpha/apecs.h
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 1993, 1996 Digital Equipment Corporation
+
+Module Name:
+
+ apecs.h
+
+Abstract:
+
+ This file defines the structures and definitions common to all
+ APECS-based platforms.
+
+Author:
+
+ Joe Notarangelo 12-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Chao Chen 31-Aug-1995 Fix the broken Comanche register data structure.
+ Gene Morgan 27-Feb-1996 Add missing Comanche register defns
+
+--*/
+
+#ifndef _APECSH_
+#define _APECSH_
+
+
+//
+// Define QVA constants for APECS.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xA0000000) // Identify VA as a QVA
+
+#endif //!QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+//
+// Define size of I/O and memory space for APECS
+//
+
+#define PCI_MAX_IO_ADDRESS 0xFFFFFF // 16 Mb of IO Space
+
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS ((128*1024*1024) - 1)
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MAX_SPARSE_MEMORY_ADDRESS + 1
+#define PCI_MAX_DENSE_MEMORY_ADDRESS (0xa0000000 -1) // 2.5 Gb
+
+//
+// Constant used by dense space I/O routines
+//
+
+#define PCI_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc0300000000
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | (ULONG)((PA) >> IO_BIT_SHIFT) ) )
+
+
+//
+// Define physical address spaces for APECS.
+//
+
+#define APECS_COMANCHE_BASE_PHYSICAL ((ULONGLONG)0x180000000)
+#define APECS_EPIC_BASE_PHYSICAL ((ULONGLONG)0x1A0000000)
+#define APECS_PCI_INTACK_BASE_PHYSICAL ((ULONGLONG)0x1B0000000)
+#define APECS_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x1C0000000)
+#define APECS_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0x1E0000000)
+#define APECS_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x200000000)
+#define APECS_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x300000000)
+
+#define APECS_PCI_CONFIG_BASE_QVA (HAL_MAKE_QVA(APECS_PCI_CONFIG_BASE_PHYSICAL))
+
+#define EPIC_HAXR1_BASE_PHYSICAL ((ULONGLONG)0x1A00001A0)
+#define EPIC_HAXR2_BASE_PHYSICAL ((ULONGLONG)0x1A00001C0)
+#define EPIC_HAXR1_QVA (HAL_MAKE_QVA(EPIC_HAXR1_BASE_PHYSICAL))
+#define EPIC_HAXR2_QVA (HAL_MAKE_QVA(EPIC_HAXR2_BASE_PHYSICAL))
+
+
+//
+// Define COMANCHE CSRs.
+//
+
+
+#define APECS_COMANCHE_BASE_QVA (HAL_MAKE_QVA(APECS_COMANCHE_BASE_PHYSICAL))
+
+//
+// N.B. The structure below defines the address offsets of the control
+// registers when used with the base QVA. It does NOT define the
+// size or structure of the individual registers.
+//
+
+typedef struct _COMANCHE_CSRS{
+ UCHAR GeneralControlRegister;
+ UCHAR Reserved;
+ UCHAR ErrorAndDiagnosticStatusRegister;
+ UCHAR TagEnableRegister;
+ UCHAR ErrorLowAddressRegister;
+ UCHAR ErrorHighAddressRegister;
+ UCHAR Ldx_lLowAddressRegister;
+ UCHAR Ldx_lHighAddressRegister;
+ UCHAR Reserved1[8];
+ UCHAR GlobalTimingRegister;
+ UCHAR RefreshTimingRegister;
+ UCHAR VideoFramePointerRegister;
+ UCHAR PresenceDetectLowDataRegister;
+ UCHAR PresenceDetectHighDataRegister;
+ UCHAR Reserved2[43];
+ UCHAR Bank0BaseAddressRegister;
+ UCHAR Bank1BaseAddressRegister;
+ UCHAR Bank2BaseAddressRegister;
+ UCHAR Bank3BaseAddressRegister;
+ UCHAR Bank4BaseAddressRegister;
+ UCHAR Bank5BaseAddressRegister;
+ UCHAR Bank6BaseAddressRegister;
+ UCHAR Bank7BaseAddressRegister;
+ UCHAR Bank8BaseAddressRegister;
+ UCHAR Reserved3[7];
+ UCHAR Bank0ConfigurationRegister;
+ UCHAR Bank1ConfigurationRegister;
+ UCHAR Bank2ConfigurationRegister;
+ UCHAR Bank3ConfigurationRegister;
+ UCHAR Bank4ConfigurationRegister;
+ UCHAR Bank5ConfigurationRegister;
+ UCHAR Bank6ConfigurationRegister;
+ UCHAR Bank7ConfigurationRegister;
+ UCHAR Bank8ConfigurationRegister;
+ UCHAR Reserved4[7];
+ UCHAR Bank0TimingRegisterA;
+ UCHAR Bank1TimingRegisterA;
+ UCHAR Bank2TimingRegisterA;
+ UCHAR Bank3TimingRegisterA;
+ UCHAR Bank4TimingRegisterA;
+ UCHAR Bank5TimingRegisterA;
+ UCHAR Bank6TimingRegisterA;
+ UCHAR Bank7TimingRegisterA;
+ UCHAR Bank8TimingRegisterA;
+ UCHAR Reserved5[7];
+ UCHAR Bank0TimingRegisterB;
+ UCHAR Bank1TimingRegisterB;
+ UCHAR Bank2TimingRegisterB;
+ UCHAR Bank3TimingRegisterB;
+ UCHAR Bank4TimingRegisterB;
+ UCHAR Bank5TimingRegisterB;
+ UCHAR Bank6TimingRegisterB;
+ UCHAR Bank7TimingRegisterB;
+ UCHAR Bank8TimingRegisterB;
+} COMANCHE_CSRS, *PCOMANCHE_CSRS;
+
+//
+// Define formats of useful COMANCHE registers.
+//
+
+//
+// Error Diagnostic and Status Register
+//
+typedef union _COMANCHE_EDSR{
+ struct{
+ ULONG Losterr: 1;
+ ULONG Bctaperr: 1;
+ ULONG Bctcperr: 1;
+ ULONG Nxmerr: 1;
+ ULONG Dmacause: 1;
+ ULONG Viccause: 1;
+ ULONG Creqcause: 3;
+ ULONG Reserved: 4;
+ ULONG Pass2: 1;
+ ULONG Ldxllock: 1;
+ ULONG Wrpend: 1;
+ };
+ ULONG all;
+} COMANCHE_EDSR, *PCOMANCHE_EDSR;
+
+//
+// General Control Register
+//
+typedef union _COMANCHE_GCR {
+ struct {
+ ULONG Reserved1: 1;
+ ULONG Sysarb: 2;
+ ULONG Reserved2: 1;
+ ULONG Widemem: 1;
+ ULONG Bcen: 1;
+ ULONG Bcnoalloc: 1;
+ ULONG Bclongwr: 1;
+ ULONG Bcigntflag: 1;
+ ULONG Bcfrctflag: 1;
+ ULONG Bcfrcd: 1;
+ ULONG Bcfrcz: 1;
+ ULONG Bcfrcp: 1;
+ ULONG Bcbadap: 1;
+ ULONG Reserved3: 2;
+ };
+ ULONG all;
+} COMANCHE_GCR, *PCOMANCHE_GCR;
+
+//
+// Tag Enable Register
+//
+typedef union _COMANCHE_TER {
+ struct {
+ ULONG Tagen: 16; // Bit zero is reserved and MBZ
+ };
+ ULONG all;
+} COMANCHE_TER, *PCOMANCHE_TER;
+
+//
+// Bank<n> Base Address Register [0..8]
+//
+typedef union _COMANCHE_BASE_ADDRESS_REGISTER {
+ struct {
+ ULONG Reserved: 5;
+ ULONG BaseAdr: 11;
+ };
+ ULONG all;
+} COMANCHE_BASE_ADDRESS_REGISTER, *PCOMANCHE_BASE_ADDRESS_REGISTER;
+
+//
+// Bank<n> Configuration Register [0..8]
+//
+typedef union _COMANCHE_BANK_CONFIGURATION_REGISTER {
+ struct {
+ ULONG SetValid: 1;
+ ULONG SetSize: 4;
+ ULONG SetSubEna: 1;
+ ULONG SetColSel: 3;
+ ULONG Reserved: 7;
+ };
+ ULONG all;
+}COMANCHE_BANK_CONFIGURATION_REGISTER, *PCOMANCHE_BANK_CONFIGURATION_REGISTER;
+
+
+//
+// Define EPIC CSRs.
+//
+
+
+#define APECS_EPIC_BASE_QVA (HAL_MAKE_QVA(APECS_EPIC_BASE_PHYSICAL))
+
+//
+// N.B. The structure below defines the address offsets of the control
+// registers when used with the base QVA. It does NOT define the
+// size or structure of the individual registers.
+//
+
+typedef struct _EPIC_CSRS{
+ UCHAR EpicControlAndStatusRegister;
+ UCHAR SysbusErrorAddressRegister;
+ UCHAR PciErrorAddressRegister;
+ UCHAR DummyRegister1;
+ UCHAR DummyRegister2;
+ UCHAR DummyRegister3;
+ UCHAR TranslatedBase1Register;
+ UCHAR TranslatedBase2Register;
+ UCHAR PciBase1Register;
+ UCHAR PciBase2Register;
+ UCHAR PciMask1Register;
+ UCHAR PciMask2Register;
+ UCHAR Haxr0;
+ UCHAR Haxr1;
+ UCHAR Haxr2;
+ UCHAR DummyRegister4;
+ UCHAR TlbTag0Register;
+ UCHAR TlbTag1Register;
+ UCHAR TlbTag2Register;
+ UCHAR TlbTag3Register;
+ UCHAR TlbTag4Register;
+ UCHAR TlbTag5Register;
+ UCHAR TlbTag6Register;
+ UCHAR TlbTag7Register;
+ UCHAR TlbData0Register;
+ UCHAR TlbData1Register;
+ UCHAR TlbData2Register;
+ UCHAR TlbData3Register;
+ UCHAR TlbData4Register;
+ UCHAR TlbData5Register;
+ UCHAR TlbData6Register;
+ UCHAR TlbData7Register;
+ UCHAR TbiaRegister;
+} EPIC_CSRS, *PEPIC_CSRS;
+
+//
+// Define formats of useful EPIC registers. Note that P1 is a vestige,
+// and direct access for P2 definitions are the default.
+//
+
+typedef union _EPIC_ECSR{
+
+ struct{
+ ULONG Tenb: 1;
+ ULONG Prst: 1;
+ ULONG Penb: 1;
+ ULONG Dcei: 1;
+ ULONG Rsvd1: 1;
+ ULONG Iort: 1;
+ ULONG Lost: 1;
+ ULONG Rdwr: 1;
+ ULONG Ddpe: 1;
+ ULONG Iope: 1;
+ ULONG Tabt: 1;
+ ULONG Ndev: 1;
+ ULONG Cmrd: 1;
+ ULONG Umrd: 1;
+ ULONG Iptl: 1;
+ ULONG Merr: 1;
+ ULONG DisRdByp: 2;
+ ULONG Rsvd2: 14;
+ } P1;
+ struct{
+ ULONG Tenb: 1;
+ ULONG Rsvd1: 1;
+ ULONG Penb: 1;
+ ULONG Dcei: 1;
+ ULONG Dpec: 1;
+ ULONG Iort: 1;
+ ULONG Lost: 1;
+ ULONG Rsvd2: 1;
+ ULONG Ddpe: 1;
+ ULONG Iope: 1;
+ ULONG Tabt: 1;
+ ULONG Ndev: 1;
+ ULONG Cmrd: 1;
+ ULONG Umrd: 1;
+ ULONG Iptl: 1;
+ ULONG Merr: 1;
+ ULONG DisRdByp: 2;
+ ULONG Pcmd: 4;
+ ULONG Rsvd3: 9;
+ ULONG Pass2: 1;
+ };
+ ULONG all;
+} EPIC_ECSR, *PEPIC_ECSR;
+
+typedef struct _EPIC_PCIMASK{
+ ULONG Reserved: 20;
+ ULONG MaskValue: 12;
+} EPIC_PCIMASK, *PEPIC_PCIMASK;
+
+typedef struct _EPIC_PCIBASE{
+ ULONG Reserved: 18;
+ ULONG Sgen: 1;
+ ULONG Wenr: 1;
+ ULONG BaseValue: 12;
+} EPIC_PCIBASE, *PEPIC_PCIBASE;
+
+typedef struct _EPIC_TBASE{
+ ULONG Reserved: 9;
+ ULONG TBase: 23;
+} EPIC_TBASE, *PEPIC_TBASE;
+
+
+//
+// DMA Window Values.
+//
+// The APECs will be initialized to allow 2 DMA windows.
+// The first window will be for the use of of ISA devices and DMA slaves
+// and therefore must have logical addresses below 16MB.
+// The second window will be for bus masters (non-ISA) and so may be
+// above 16MB.
+//
+// The arrangement of the windows will be as follows:
+//
+// Window Logical Start Address Window Size
+// ------ --------------------- -----------
+// Isa 8MB 8MB
+// Master 16MB 16MB
+//
+
+#define ISA_DMA_WINDOW_BASE (__8MB)
+#define ISA_DMA_WINDOW_SIZE (__8MB)
+
+#define MASTER_DMA_WINDOW_BASE (__16MB)
+#define MASTER_DMA_WINDOW_SIZE (__16MB)
+
+
+//
+// Define the software control registers for a DMA window.
+//
+
+typedef struct _WINDOW_CONTROL_REGISTERS{
+ PVOID WindowBase;
+ ULONG WindowSize;
+ PVOID TranslatedBaseRegister;
+ PVOID WindowBaseRegister;
+ PVOID WindowMaskRegister;
+ PVOID WindowTbiaRegister;
+} WINDOW_CONTROL_REGISTERS, *PWINDOW_CONTROL_REGISTERS;
+
+//
+// Define types of windows.
+//
+
+typedef enum _APECS_WINDOW_NUMBER{
+ ApecsIsaWindow,
+ ApecsMasterWindow
+} APECS_WINDOW_NUMBER, *PAPECS_WINDOW_NUMBER;
+
+//
+// Define APECS Window Control routines.
+//
+
+VOID
+HalpApecsInitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ APECS_WINDOW_NUMBER WindowNumber
+ );
+
+VOID
+HalpApecsProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ );
+
+
+//
+// VOID
+// INITIALIZE_ISA_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_ISA_DMA_CONTROL( WR ) \
+ HalpApecsInitializeSfwWindow( (WR), ApecsIsaWindow );
+
+
+//
+// VOID
+// INITIALIZE_MASTER_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_MASTER_DMA_CONTROL( WR ) \
+ HalpApecsInitializeSfwWindow( (WR), ApecsMasterWindow );
+
+
+//
+// VOID
+// INITIALIZE_DMA_WINDOW(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters,
+// PTRANSLATION_ENTRY MapRegisterBase
+// )
+//
+// Routine Description:
+//
+// Program the control windows so that DMA can be started to the
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window register
+// control structure.
+//
+// MapRegisterBase - Supplies the logical address of the scatter/gather
+// array in system memory.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_DMA_WINDOW( WR, MRB ) \
+ HalpApecsProgramDmaWindow( (WR), (MRB) );
+
+
+//
+// VOID
+// INVALIDATE_DMA_TRANSLATIONS(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Invalidate all of the cached translations for a DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control
+// registers.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INVALIDATE_DMA_TRANSLATIONS( WR ) \
+ WRITE_EPIC_REGISTER( \
+ ((PWINDOW_CONTROL_REGISTERS)WR)->WindowTbiaRegister, 0 );
+
+
+//
+// Define the format of a translation entry aka a scatter/gather entry
+// or map register.
+//
+typedef struct _TRANSLATION_ENTRY{
+ ULONG Valid: 1;
+ ULONG Pfn: 31;
+ ULONG Reserved;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+
+//
+// VOID
+// HAL_MAKE_VALID_TRANSLATION(
+// PTRANSLATION_ENTRY Entry,
+// ULONG PageFrameNumber
+// )
+//
+// Routine Description:
+//
+// Make the scatter/gather entry pointed to by Entry valid with
+// a translation to the page indicated by PageFrameNumber.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation entry to make valid.
+//
+// PageFrameNumber - Supplies the page frame of the valid translation.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_MAKE_VALID_TRANSLATION( ENTRY, PFN ) \
+ { \
+ (ENTRY)->Valid = 1; \
+ (ENTRY)->Pfn = PFN; \
+ (ENTRY)->Reserved = 0; \
+ }
+
+
+//
+// VOID
+// HAL_INVALIDATE_TRANSLATION(
+// PTRANSLATION_ENTRY Entry
+// )
+//
+// Routine Description:
+//
+// Invalidate the translation indicated by Entry.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation to be invalidated.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_INVALIDATE_TRANSLATION( ENTRY ) \
+ (ENTRY)->Valid = 0;
+
+//
+// APECS-specific functions.
+//
+
+VOID
+WRITE_COMANCHE_REGISTER(
+ IN PVOID RegisterQva,
+ IN ULONG Value
+ );
+
+ULONG
+READ_COMANCHE_REGISTER(
+ IN PVOID RegisterQva
+ );
+
+VOID
+WRITE_EPIC_REGISTER(
+ IN PVOID RegisterQva,
+ IN ULONG Value
+ );
+
+ULONG
+READ_EPIC_REGISTER(
+ IN PVOID RegisterQva
+ );
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_APECSH_
diff --git a/private/ntos/nthals/halalpha/apecserr.c b/private/ntos/nthals/halalpha/apecserr.c
new file mode 100644
index 000000000..5464a8936
--- /dev/null
+++ b/private/ntos/nthals/halalpha/apecserr.c
@@ -0,0 +1,1542 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ apecserr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for machines based on the APECS chip-set.
+
+Author:
+
+ Joe Notarangelo 14-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 31-Aug-1995 Added in ECC correctable error handling.
+
+ Balakumar.N 26-Sep-1995 added Uncorrectable Error Logging code and
+ merged Chao's changes to handle correctable error.
+
+--*/
+
+#include "halp.h"
+#include "apecs.h"
+#include "stdio.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpApecsReportFatalError(
+ VOID
+ );
+
+ULONG
+HalpSimm(
+ ULONGLONG Address
+ );
+
+VOID
+HalpApecsCorrectableError(
+ VOID
+ );
+
+VOID
+HalpApecsConfig(
+ PAPECS_CONFIGURATION Config
+ );
+
+// jnfix - temp count
+ULONG CorrectedMemoryReads = 0;
+#define MAX_ERROR_STRING 128
+
+extern ULONG HalDisablePCIParityChecking;
+
+
+VOID
+HalpInitializeMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for an APECS-based
+ system by clearing all pending errors in the COMANCHE and EPIC and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Dummy;
+ EPIC_ECSR Ecsr;
+ COMANCHE_EDSR Edsr;
+
+ //
+ // Clear the lost error bit in the Comanche EDSR.
+ //
+
+ Edsr.all = 0;
+ Edsr.Losterr = 1;
+ WRITE_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorAndDiagnosticStatusRegister,
+ Edsr.all );
+
+ //
+ // Unlock the other error bits of the EDSR by reading the error address
+ // registers.
+ //
+
+ Dummy = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorHighAddressRegister
+ );
+
+ Dummy = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorLowAddressRegister
+ );
+
+ //
+ // Clear all of the error bits in the Epic ECSR. Set correctable error
+ // reporting as requested.
+ //
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+ //
+ // For the common registers, simply set them - common in that the P1
+ // definition matches the P2 definition (same structure offset).
+ //
+
+ Ecsr.Merr = 1;
+ Ecsr.Iptl = 1;
+ Ecsr.Umrd = 1;
+ Ecsr.Cmrd = 1;
+ Ecsr.Ndev = 1;
+ Ecsr.Tabt = 1;
+ Ecsr.Iope = 1;
+ Ecsr.Ddpe = 1;
+ Ecsr.Lost = 1;
+ Ecsr.Iort = 1;
+
+ if( ReportCorrectableErrors == TRUE ){
+ Ecsr.Dcei = 0;
+ } else {
+ Ecsr.Dcei = 1;
+ }
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+ Ecsr.Dpec = 1;
+ } else {
+ Ecsr.Dpec = HalDisablePCIParityChecking;
+ }
+#if HALDBG
+ if (HalDisablePCIParityChecking == 0) {
+ DbgPrint("apecserr: PCI Parity Checking ON\n");
+ } else if (HalDisablePCIParityChecking == 1) {
+ DbgPrint("apecserr: PCI Parity Checking OFF\n");
+ } else {
+ DbgPrint("apecserr: PCI Parity Checking OFF - not set by ARC yet\n");
+ }
+#endif
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all );
+
+ //
+ // Set the machine check enables with the EV4.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ } else {
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ return;
+
+}
+
+VOID
+HalpReadApecsErrorRegisters(
+ VOID
+ )
+{
+ COMANCHE_EDSR Edsr;
+ EPIC_ECSR Ecsr;
+ ULONG ErrorAddress;
+ ULONG ErrorHighAddress;
+ ULONG ErrorLowAddress;
+ ULONG Pear;
+ ULONG Sear;
+ ULONG SystemErrorAddress;
+ PAPECS_UNCORRECTABLE_FRAME apecserr = NULL;
+
+ if(PUncorrectableError){
+ apecserr = (PAPECS_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ }
+
+ if(apecserr)
+ HalpApecsConfig( &apecserr->Configuration);
+
+ //
+ // Read both of the error registers. It is possible that more
+ // than one error was reported simulataneously.
+ //
+
+ Edsr.all = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorAndDiagnosticStatusRegister );
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+
+ //
+ // Read all of the relevant error address registers.
+ //
+
+ ErrorLowAddress = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorLowAddressRegister );
+
+ ErrorHighAddress = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorHighAddressRegister);
+
+ ErrorAddress = ((ULONG)(ErrorHighAddress) << 21) +
+ ((ULONG)(ErrorLowAddress) << 5);
+
+ Sear = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->SysbusErrorAddressRegister );
+
+ SystemErrorAddress = (ULONG)(Sear) << 2;
+
+ Pear = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciErrorAddressRegister );
+
+ //
+ // Fill in the Apecs uncorrectbale frame
+ //
+ if(apecserr)
+ apecserr->ComancheEdsr = Edsr.all;
+
+ if( PUncorrectableError &&
+ ( (Edsr.Bctaperr == 1) ||
+ (Edsr.Bctcperr == 1) ||
+ (Edsr.Nxmerr == 1) ) ) {
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ ErrorAddress;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_MEMORY;
+ }
+
+ if(apecserr)
+ apecserr->EpicEcsr = Ecsr.all;
+
+ if( PUncorrectableError &&
+ ( (Ecsr.Merr == 1) ||
+ (Ecsr.Umrd == 1) ) ) {
+
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ SystemErrorAddress;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_MEMORY;
+ }
+
+ if( PUncorrectableError &&
+ ( (Ecsr.Ndev == 1) ||
+ (Ecsr.Tabt == 1) ||
+ (Ecsr.Iope == 1) ||
+ (Ecsr.Ddpe == 1) ||
+ (Ecsr.Iptl == 1) ||
+ (Ecsr.Iort == 1) ) ){
+
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ Pear;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = 0;
+ }
+
+ if(apecserr){
+ apecserr->EpicPciErrAddr = Pear;
+ apecserr->EpicSysErrAddr = SystemErrorAddress;
+ apecserr->ComancheErrAddr = ErrorAddress;
+ }
+
+ return;
+
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the APECS chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ COMANCHE_EDSR Edsr;
+ EPIC_ECSR Ecsr;
+
+ PAPECS_UNCORRECTABLE_FRAME apecserr = NULL;
+
+ //
+ // Check if there are any memory errors pending in the Comanche.
+ //
+ // A lost error, tag parity, tag control or non-existent memory
+ // error indicates a non-dismissable error.
+ //
+
+ HalpReadApecsErrorRegisters();
+
+ if(PUncorrectableError)
+ apecserr = (PAPECS_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+
+ if(apecserr == NULL){
+ Edsr.all = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->
+ ErrorAndDiagnosticStatusRegister );
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->
+ EpicControlAndStatusRegister );
+
+ }
+ else {
+
+ Edsr.all = apecserr->ComancheEdsr;
+
+ Ecsr.all = apecserr->EpicEcsr;
+ }
+
+ if( (Edsr.Losterr == 1) ||
+ (Edsr.Bctaperr == 1) ||
+ (Edsr.Bctcperr == 1) ||
+ (Edsr.Nxmerr == 1) ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Check if there are any non-recoverable I/O errors.
+ //
+ // Memory errors, invalid page table lookups, uncorrectable
+ // memory errors, target aborts, io parity errors, dma parity
+ // errors, lost errors, and retry timeouts are all considered
+ // non-dismissable errors.
+ //
+
+ if( (Ecsr.Merr == 1) ||
+ (Ecsr.Iptl == 1) ||
+ (Ecsr.Umrd == 1) ||
+ (Ecsr.Tabt == 1) ||
+ (Ecsr.Iope == 1) ||
+ (Ecsr.Ddpe == 1) ||
+ (Ecsr.Iort == 1) ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // A Pass1 APECS chip bug will erroneously report a lost operation,
+ // so, if a Pass1 chip, then ignore the error.
+ //
+
+ if ( (Ecsr.Lost == 1) && (Ecsr.Pass2 == 1)) {
+ goto FatalError;
+ }
+
+ //
+ // Check for a PCI configuration read error. An error is a
+ // candidate if the I/O controller has signalled a NoDevice error.
+ //
+
+ if( Ecsr.Ndev == 1 ){
+
+ //
+ // So far, the error looks like a PCI configuration space read
+ // that accessed a device that does not exist. In order to fix
+ // this up we expect that the faulting instruction or the instruction
+ // previous to the faulting instruction must be a load with v0 as
+ // the destination register. If this condition is met then simply
+ // update v0 in the register set and return. However, be careful
+ // not to re-execute the load.
+ //
+ // jnfix - add condition to check if Rb contains the superpage
+ // address for config space?
+
+ ALPHA_INSTRUCTION FaultingInstruction;
+ BOOLEAN PreviousInstruction = FALSE;
+ BOOLEAN WasLost = (Ecsr.Lost == 1 ? TRUE : FALSE);
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
+ if( (FaultingInstruction.Memory.Ra != V0_REG) ||
+ (FaultingInstruction.Memory.Opcode != LDL_OP) ){
+
+ //
+ // Faulting instruction did not match, try the previous
+ // instruction.
+ //
+
+ PreviousInstruction = TRUE;
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir - 4);
+ if( (FaultingInstruction.Memory.Ra != V0_REG) ||
+ (FaultingInstruction.Memory.Opcode != LDL_OP) ){
+
+ //
+ // No match, we can't fix this up.
+ //
+
+ goto FatalError;
+ }
+ }
+
+ //
+ // The error has matched all of our conditions. Fix it up by
+ // writing the value 0xffffffff into the destination of the load.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
+
+ //
+ // If the faulting instruction was the load the restart execution
+ // at the instruction after the load.
+ //
+
+ if( PreviousInstruction == FALSE ){
+ TrapFrame->Fir += 4;
+ }
+
+ //
+ // Clear the error condition in the ECSR.
+ //
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister);
+
+ Ecsr.Ndev = 1;
+ Ecsr.Dcei = 1;
+
+ if (WasLost) {
+ Ecsr.Lost = 1;
+ }
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all );
+
+ return TRUE;
+
+ } //endif Ecsr.Ndev == 1
+
+
+ //
+ // Handle any ECC correctable errors.
+ //
+
+ if( Ecsr.Cmrd ) {
+
+ //
+ // Handle the error and then clear the error bit.
+ //
+
+ HalpApecsCorrectableError();
+ Ecsr.Cmrd = 0;
+ Ecsr.Lost = 0;
+
+ //
+ // If there are no other outstanding errors, then return.
+ //
+
+ if ( Ecsr.all )
+ return TRUE;
+ }
+
+ //
+ // A Pass1 APECS chip bug will erroneously report a lost operation,
+ // so, if a Pass1 chip, then ignore the error.
+ //
+
+ if ( (Ecsr.Lost == 1) && (Ecsr.Pass2 == 1)) {
+ goto FatalError;
+ }
+
+ //
+ // The system is not well and cannot continue reliable execution.
+ // Print some useful messages and return FALSE to indicate that the error
+ // was not handled.
+ //
+
+FatalError:
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Uncorrectable Error From Apecs Chipset Detected");
+ }
+
+ HalpApecsReportFatalError();
+
+ return FALSE;
+
+}
+
+
+VOID
+HalpApecsErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an error interrupt on the
+ APECS chipset. This function determines if the error is fatal
+ or recoverable and if recoverable performs the recovery and
+ error logging.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ COMANCHE_EDSR Edsr;
+ EPIC_ECSR Ecsr;
+ PAPECS_UNCORRECTABLE_FRAME apecserr = NULL;
+
+ HalpReadApecsErrorRegisters();
+
+ if(PUncorrectableError)
+ apecserr = (PAPECS_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+
+ if(apecserr == NULL){
+ Edsr.all = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->
+ ErrorAndDiagnosticStatusRegister );
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->
+ EpicControlAndStatusRegister );
+
+ }
+ else {
+
+ Edsr.all = apecserr->ComancheEdsr;
+
+ Ecsr.all = apecserr->EpicEcsr;
+ }
+
+ //
+ // Any error from the COMANCHE represents a fatal condition.
+ //
+
+ if( (Edsr.Losterr == 1) ||
+ (Edsr.Bctaperr == 1) ||
+ (Edsr.Bctcperr == 1) ||
+ (Edsr.Nxmerr == 1) ){
+
+ goto FatalErrorInterrupt;
+
+ }
+
+ //
+ // Almost any error from the EPIC is also fatal. The only exception
+ // is the correctable memory read error. Any other error is fatal.
+ //
+
+ if( (Ecsr.Merr == 1) ||
+ (Ecsr.Iptl == 1) ||
+ (Ecsr.Umrd == 1) ||
+ (Ecsr.Tabt == 1) ||
+ (Ecsr.Ndev == 1) ||
+ (Ecsr.Iope == 1) ||
+ (Ecsr.Ddpe == 1) ||
+ (Ecsr.Iort == 1) ){
+
+ goto FatalErrorInterrupt;
+
+ }
+
+ //
+ // A Pass1 APECS chip bug will erroneously report a lost operation,
+ // so, if a Pass1 chip, then ignore the error.
+ //
+
+ if ( (Ecsr.Lost == 1) && (Ecsr.Pass2 == 1)) {
+ goto FatalErrorInterrupt;
+ }
+
+ //
+ // The error may be correctable. If the correctable error bit is
+ // set in the ECSR then log the error and clear the condition.
+ //
+
+ if( Ecsr.Cmrd == 1 ){
+
+ ULONG Sear;
+ ULONGLONG SystemErrorAddress;
+
+ CorrectedMemoryReads += 1;
+
+ Sear = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->SysbusErrorAddressRegister );
+
+ SystemErrorAddress = (ULONGLONG)(Sear) << 2;
+
+ //jnfix - temporary debug logging only
+#if (DBG) || (HALDBG)
+
+ if( (CorrectedMemoryReads % 32) == 0 ){
+ DbgPrint( "APECS: CorrectedMemoryReads = %d, Address = 0x%Lx\n",
+ CorrectedMemoryReads,
+ SystemErrorAddress );
+ }
+
+#endif //DBG || HALDBG
+
+ //
+ // Clear the error condition.
+ //
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all
+ );
+
+ return;
+
+ } //endif Ecsr.Cmrd == 1
+
+//
+// The interrupt indicates a fatal system error.
+// Display information about the error and shutdown the machine.
+//
+
+FatalErrorInterrupt:
+
+ HalpApecsReportFatalError();
+
+//jnfix - add some of the address registers?
+//
+// Add the address of the error frame as 4th parameter.
+//
+ KeBugCheckEx( DATA_BUS_ERROR,
+ Edsr.all,
+ Ecsr.all,
+ 0,
+ (ULONG)PUncorrectableError );
+
+
+}
+
+
+VOID
+HalpApecsReportFatalError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error on
+ the APECS chipset. The COMANCHE Error and Diagnostic Status Register
+ and the EPIC Error and Status Register are read to determine how
+ to interpret the error.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ COMANCHE_EDSR Edsr;
+ EPIC_ECSR Ecsr;
+ ULONGLONG ErrorAddress;
+ ULONG ErrorHighAddress;
+ ULONG ErrorLowAddress;
+ ULONG Pear;
+ ULONG Sear;
+ ULONGLONG SystemErrorAddress;
+ UCHAR OutBuffer[MAX_ERROR_STRING];
+ PAPECS_UNCORRECTABLE_FRAME apecserr = NULL;
+ PEXTENDED_ERROR PExtErr = NULL;
+
+ //
+ // Begin the error output by acquiring ownership of the display
+ // and printing the dreaded banner.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // Extract register values to report from Error Frame.
+ //
+ if(PUncorrectableError){
+ apecserr = (PAPECS_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ if(apecserr == NULL){
+ Edsr.all = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->
+ ErrorAndDiagnosticStatusRegister );
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->
+ EpicControlAndStatusRegister );
+
+ ErrorLowAddress = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorLowAddressRegister );
+
+ ErrorHighAddress = READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->ErrorHighAddressRegister);
+
+ ErrorAddress = ((ULONGLONG)(ErrorHighAddress) << 21) +
+ ((ULONGLONG)(ErrorLowAddress) << 5);
+
+ Sear = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->SysbusErrorAddressRegister );
+
+ SystemErrorAddress = (ULONGLONG)(Sear) << 2;
+
+ Pear = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->PciErrorAddressRegister );
+
+ }
+ else {
+
+ Edsr.all = apecserr->ComancheEdsr;
+
+ Ecsr.all = apecserr->EpicEcsr;
+
+ Pear = apecserr->EpicPciErrAddr;
+ SystemErrorAddress = apecserr->EpicSysErrAddr;
+ ErrorAddress = apecserr->ComancheErrAddr;
+ }
+
+
+
+ //
+ // Interpret any errors from the COMANCHE EDSR.
+ //
+
+ sprintf( OutBuffer, "Comanche EDSR = 0x%x\n", Edsr.all );
+ HalDisplayString( OutBuffer );
+
+ if( Edsr.Bctaperr == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "B-Cache Tag Address Parity Error");
+
+ PUncorrectableError->UncorrectableFrame.Flags.MemoryErrorSource =
+ SYSTEM_CACHE;
+ //
+ // At present the HalpSimm routine doesn't do anything
+ // it expected to be fixed in the near future.
+ //
+ PExtErr->CacheError.Flags.CacheSimmValid = 1;
+ PExtErr->CacheError.CacheSimm = HalpSimm(ErrorAddress);
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+ if( Edsr.Dmacause == 1 ){
+ PExtErr->CacheError.TransferType = BUS_DMA_OP;
+ }
+ if( Edsr.Viccause == 1 ){
+ PExtErr->CacheError.TransferType = VICTIM_WRITE;
+ }
+
+ }
+
+ sprintf( OutBuffer,
+ "Bcache Tag Address Parity Error, Address: %Lx, SIMM = %d\n",
+ ErrorAddress, HalpSimm(ErrorAddress) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Edsr.Bctcperr == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "B-Cache Tag Control Parity Error");
+
+ PUncorrectableError->UncorrectableFrame.Flags.MemoryErrorSource =
+ SYSTEM_CACHE;
+ //
+ // At present the HalpSimm routine doesn't do anything
+ // it is expected to be fixed in the near future.
+ //
+ PExtErr->CacheError.Flags.CacheSimmValid = 1;
+ PExtErr->CacheError.CacheSimm = HalpSimm(ErrorAddress);
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+ if( Edsr.Dmacause == 1 ){
+ PExtErr->CacheError.TransferType = BUS_DMA_OP;
+ }
+ if( Edsr.Viccause == 1 ){
+ PExtErr->CacheError.TransferType = VICTIM_WRITE;
+ }
+
+
+ }
+
+
+ sprintf( OutBuffer,
+ "Bcache Tag Control Parity Error, Address: %Lx, SIMM = %d\n",
+ ErrorAddress, HalpSimm(ErrorAddress) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Edsr.Nxmerr == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Non-existent memory error");
+
+ PUncorrectableError->UncorrectableFrame.Flags.MemoryErrorSource =
+ SYSTEM_MEMORY;
+ //
+ // At present the HalpSimm routine doesn't do anything
+ // it expected to be fixed in the near future.
+ //
+ PExtErr->MemoryError.Flags.MemorySimmValid = 1;
+ PExtErr->MemoryError.MemorySimm = HalpSimm(ErrorAddress);
+ HalpGetProcessorInfo(&PExtErr->MemoryError.ProcessorInfo);
+ if( Edsr.Dmacause == 1 ){
+ PExtErr->MemoryError.TransferType = BUS_DMA_OP;
+ }
+ if( Edsr.Viccause == 1 ){
+ PExtErr->MemoryError.TransferType = VICTIM_WRITE;
+ }
+
+
+ }
+
+ sprintf( OutBuffer,
+ "Non-existent memory error, Address: %Lx\n",
+ ErrorAddress );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( (Edsr.Bctaperr == 1) || (Edsr.Bctcperr == 1) ||
+ (Edsr.Nxmerr == 1) ){
+
+ if( Edsr.Dmacause == 1 ){
+ HalDisplayString( "Error caused on DMA.\n" );
+ }
+
+ if( Edsr.Viccause == 1 ){
+ HalDisplayString( "Victim write caused error.\n" );
+ }
+
+ }
+
+ if( Edsr.Losterr == 1 ){
+ HalDisplayString( "Multiple Cache/Memory errors.\n" );
+ }
+
+ //
+ // Interpret any errors from the EPIC Ecsr.
+ //
+
+ sprintf( OutBuffer, "EPIC ECSR = 0x%lx\n", Ecsr.all );
+ HalDisplayString( OutBuffer );
+
+ if( Ecsr.Iort == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "PCI Retry timeout error");
+ PExtErr->IoError.Interface = PCIBus;
+
+ //
+ // Since APECS supports only one PCI Bus we will simply set
+ // the busnumber to 0.
+ //
+ PExtErr->IoError.BusNumber = 0;
+
+ }
+
+ sprintf( OutBuffer,
+ "PCI Retry timeout error, PCI Address: 0x%x\n",
+ Pear );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Ddpe == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "DMA Data Parity Error");
+ PExtErr->IoError.Interface = PCIBus;
+
+ //
+ // Since APECS supports only one PCI Bus we will simply set
+ // the busnumber to 0.
+ //
+ PExtErr->IoError.BusNumber = 0;
+
+ }
+ sprintf( OutBuffer,
+ "DMA Data Parity Error at PCI Address: 0x%x\n",
+ Pear );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Iope == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "I/O Data Parity Error");
+ PExtErr->IoError.Interface = PCIBus;
+
+ //
+ // Since APECS supports only one PCI Bus we will simply set
+ // the busnumber to 0.
+ //
+ PExtErr->IoError.BusNumber = 0;
+
+ }
+ sprintf( OutBuffer,
+ "I/O Data Parity Error at PCI Address: 0x%x\n",
+ Pear );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Tabt == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Target Abort Error");
+ PExtErr->IoError.Interface = PCIBus;
+
+ //
+ // Since APECS supports only one PCI Bus we will simply set
+ // the busnumber to 0.
+ //
+ PExtErr->IoError.BusNumber = 0;
+
+ }
+ sprintf( OutBuffer,
+ "Target Abort Error at PCI Address: 0x%x\n",
+ Pear );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Ndev == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "No Device Error");
+ PExtErr->IoError.Interface = PCIBus;
+
+ //
+ // Since APECS supports only one PCI Bus we will simply set
+ // the busnumber to 0.
+ //
+ PExtErr->IoError.BusNumber = 0;
+
+ }
+ sprintf( OutBuffer,
+ "No Device Error at PCI Address: 0x%x\n",
+ Pear );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Iptl == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Invalid Page Table Lookup");
+ PExtErr->IoError.Interface = PCIBus;
+
+ //
+ // Since APECS supports only one PCI Bus we will simply set
+ // the busnumber to 0.
+ //
+ PExtErr->IoError.BusNumber = 0;
+
+ }
+ sprintf( OutBuffer,
+ "Invalid Page Table Lookup at PCI Address: 0x%x\n",
+ Pear );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Umrd == 1 ){
+
+ if(PExtErr){
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid =
+ 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "memory read error");
+
+ PUncorrectableError->UncorrectableFrame.Flags.MemoryErrorSource =
+ SYSTEM_MEMORY;
+ //
+ // At present the HalpSimm routine doesn't do anything
+ // it expected to be fixed in the near future.
+ //
+ PExtErr->MemoryError.Flags.MemorySimmValid = 1;
+ PExtErr->MemoryError.MemorySimm = HalpSimm(ErrorAddress);
+ HalpGetProcessorInfo(&PExtErr->MemoryError.ProcessorInfo);
+
+
+ }
+ sprintf( OutBuffer,
+ "Uncorrectable memory read error, System Address: 0x%Lx\n",
+ SystemErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+
+ if( Ecsr.Merr == 1 ){
+
+ sprintf( OutBuffer,
+ "Memory error, System Address: 0x%Lx\n",
+ SystemErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Ecsr.Lost == 1 ){
+ HalDisplayString( "Multiple I/O errors detected.\n" );
+ }
+
+ return;
+
+}
+
+ULONG
+HalpSimm(
+ ULONGLONG Address
+ )
+/*++
+
+Routine Description:
+
+ Return the number of the SIMM corresponding to the supplied physical
+ address.
+
+Arguments:
+
+ Address - Supplies the physical address of a byte in memory.
+
+Return Value:
+
+ The number of the SIMM that contains the byte of physical memory is
+ returned. If the Address does not fit within a SIMM or the SIMM number
+ cannot be determined 0xffffffff is returned.
+
+--*/
+{
+
+//jnfix - see if this can be determined exclusively from memory registers
+//jnfix - or is this platform-dependent
+
+ return( 0xffffffff );
+
+}
+
+
+VOID
+HalpApecsCorrectableError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle ECC correctable errors from the APECS.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ static ERROR_FRAME Frame;
+ static APECS_CORRECTABLE_FRAME ApecsFrame;
+
+ ERROR_FRAME TempFrame;
+ PCORRECTABLE_ERROR CorrPtr;
+ PBOOLEAN ErrorlogBusy;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+ EPIC_ECSR Ecsr;
+ ULONG Sear;
+ ULONGLONG SystemErrorAddress;
+
+ //
+ // Read the Epic control and status register.
+ //
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+ //
+ // Get the system address. Note, bits 2-4 of the address not available.
+ //
+
+ Sear = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->SysbusErrorAddressRegister );
+
+ SystemErrorAddress = (ULONGLONG)Sear << 2;
+
+#if (DBG) || (HALDBG)
+
+ if( (CorrectedMemoryReads % 32) == 0 ){
+ DbgPrint("APECS: CorrectedMemoryReads = %d, Address = 0x%Lx\n",
+ CorrectedMemoryReads,
+ SystemErrorAddress );
+ }
+
+#endif
+
+ //
+ // Get the interrupt object.
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Update the number of correctable errors.
+ //
+
+ CorrectedMemoryReads += 1;
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Fill in the error frame information.
+ //
+
+ TempFrame.Signature = ERROR_FRAME_SIGNATURE;
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = CorrectedMemoryReads;
+ TempFrame.PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Check for lost error.
+ //
+
+ if( Ecsr.Lost ) {
+
+ //
+ // Since the error registers are locked from a previous error,
+ // we don't know where the error came from. Mark everything
+ // as UNIDENTIFIED.
+ //
+
+ CorrPtr->Flags.LostCorrectable = 1;
+ CorrPtr->Flags.LostAddressSpace = UNIDENTIFIED;
+ CorrPtr->Flags.LostMemoryErrorSource = UNIDENTIFIED;
+ }
+
+ //
+ // Either a DMA read or DMA TLB read ECC error. We can't tell
+ // since the EPIC chip doesn't provid enough information. Just
+ // log everything as a DMA ECC error.
+ //
+
+ CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
+ CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_READ;
+
+ //
+ // Get the physical address where the error occurred.
+ //
+
+ CorrPtr->Flags.PhysicalAddressValid = 1;
+ CorrPtr->PhysicalAddress = SystemErrorAddress;
+
+ //
+ // Scrub the error if it's any type of memory error.
+ //
+
+ if (CorrPtr->Flags.AddressSpace == MEMORY_SPACE &&
+ CorrPtr->Flags.PhysicalAddressValid )
+ CorrPtr->Flags.ScrubError = 1;
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ //
+
+ if (!*ErrorlogBusy) {
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read. Read the error registers relevant
+ // to this error.
+ //
+
+ ApecsFrame.EpicEcsr = Ecsr.all;
+
+ ApecsFrame.EpicSysErrAddr = Sear;
+
+ //
+ // Read the CIA configuration registers for logging information.
+ //
+
+ ApecsFrame.Configuration.ApecsRev = Ecsr.Pass2;
+ HalpApecsConfig( &ApecsFrame.Configuration );
+
+ //
+ // Set the raw system information.
+ //
+
+ CorrPtr->RawSystemInformationLength = sizeof(APECS_CORRECTABLE_FRAME);
+ CorrPtr->RawSystemInformation = &ApecsFrame;
+
+ //
+ // Set the raw processor information. Disregard at the moment.
+ //
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // Set reporting processor information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+
+ //
+ // Set system information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.SystemInformationValid = 0;
+
+ //
+ // Copy the information that we need to log.
+ //
+
+ RtlCopyMemory(&Frame,
+ &TempFrame,
+ sizeof(ERROR_FRAME));
+
+ //
+ // Put frame into ISR service context.
+ //
+
+ *(PERROR_FRAME *)InterruptObject->ServiceContext = &Frame;
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext);
+
+ //
+ // Clear lost and correctable error bit.
+ //
+
+ if (Ecsr.Lost) {
+
+ Ecsr.all = 0;
+ Ecsr.Cmrd = 1;
+ Ecsr.Lost = 1;
+
+ } else {
+
+ Ecsr.all = 0;
+ Ecsr.Cmrd = 1;
+ }
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all);
+
+ return;
+}
+
+
+VOID
+HalpApecsConfig(
+ PAPECS_CONFIGURATION Config
+ )
+/*++
+
+Routine Description:
+
+ Reads in the configuration registers from the Comanche chip.
+
+Arguments:
+
+ Pointer to the configuration frame.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Read in all the registers.
+ //
+
+ Config->CGcr =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->GeneralControlRegister
+ );
+
+ Config->CTer =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->TagEnableRegister
+ );
+
+ Config->CGtr =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->GlobalTimingRegister
+ );
+
+ Config->CRtr =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->RefreshTimingRegister
+ );
+
+ Config->CBank0 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank0ConfigurationRegister
+ );
+
+ Config->CBank1 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank1ConfigurationRegister
+ );
+
+ Config->CBank2 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank2ConfigurationRegister
+ );
+
+ Config->CBank3 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank3ConfigurationRegister
+ );
+
+ Config->CBank4 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank4ConfigurationRegister
+ );
+
+ Config->CBank5 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank5ConfigurationRegister
+ );
+
+ Config->CBank6 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank6ConfigurationRegister
+ );
+
+ Config->CBank7 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank7ConfigurationRegister
+ );
+
+ Config->CBank8 =
+ READ_COMANCHE_REGISTER(
+ &((PCOMANCHE_CSRS)(APECS_COMANCHE_BASE_QVA))->Bank8ConfigurationRegister
+ );
+}
diff --git a/private/ntos/nthals/halalpha/apecsio.s b/private/ntos/nthals/halalpha/apecsio.s
new file mode 100644
index 000000000..9ae932d10
--- /dev/null
+++ b/private/ntos/nthals/halalpha/apecsio.s
@@ -0,0 +1,701 @@
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ apecsio.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Alpha AXP Eval Board eb64+.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ Sameer Dekate 28-July-1994
+
+ Made a common file alphaio.s for machine independent routines.
+
+
+--*/
+
+#include "apecs.h"
+#include "halalpha.h"
+
+
+
+ SBTTL( "Write Control Register" )
+//++
+//
+// VOID
+// WRITE_EPIC_REGISTER(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Write a control register in the APECS memory or PCI controller
+// (COMANCHE and EPIC respectively).
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Value(a1) - Longword value to be written to the control register.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_EPIC_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_COMANCHE_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, 5, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ .set volatile
+
+ stl a1, (t0) // write the longword
+ ldl t4, (t0) // read the the longword, to force
+ // consistency (EPIC chip bug).
+ mb // order the write
+ .set novolatile
+
+ ret zero, (ra) // return
+
+2: // flag bad QVAs
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end WRITE_EPIC_REGISTER
+
+
+ SBTTL( "Read Control Register" )
+//++
+//
+// ULONG
+// READ_EPIC_REGISTER(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Read a control register in the APECS memory or PCI controller
+// (COMANCHE and EPIC respectively).
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Return Value:
+//
+// v0 - Return the value read from the control register.
+//
+//--
+
+ LEAF_ENTRY(READ_EPIC_REGISTER)
+
+ ALTERNATE_ENTRY(READ_COMANCHE_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, 5, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ ldl v0, (t0) // read the register
+
+ ret zero, (ra) // return
+
+2: // flag bad QVAs
+ BREAK_DEBUG_STOP // take a breakpoint
+
+ ret zero, (ra) // return
+
+ .end READ_EPIC_REGISTER
+
+
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the QVA for the Configuration Cycle Type register within the
+// IOC. Physical Address = 1 A000 01C0
+//
+
+#define EPIC_HAXR2_QVA (0xad00000e)
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved ConfigurationAddress
+CfgA1: .space 8 // saved ConfigurationData/CycleType
+CfgA2: .space 8 // saved ConfigurationCycleType
+CfgFrameLength:
+
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Merge the configuration cycle type into the HAXR2 register within
+// the EPIC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration cycle type
+
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, READ_EPIC_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore configuration cycle type
+ bic v0, 0x3, t0 // clear config cycle type field
+ bis a1, t0, a1 // merge config cycle type
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extbl v0, t3, v0 // return byte from requested lane
+ // also, consume loaded value to cause
+ // a pipeline stall
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Merge the configuration cycle type into the HAXR2 register within
+// the EPIC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+ stq a2, CfgA2(sp) // save configuration cycle type
+
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, READ_EPIC_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ bic v0, 0x3, t0 // clear config cycle type field
+ bis a1, t0, a1 // merge config cycle type
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t0) // write the configuration byte
+ mb // synchronize
+
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Merge the configuration cycle type into the HAXR2 register within
+// the EPIC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration cycle type
+
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, READ_EPIC_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore configuration cycle type
+ bic v0, 0x3, t0 // clear config cycle type field
+ bis a1, t0, a1 // merge config cycle type
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extwl v0, t3, v0 // return word from requested lanes
+ // also, consume loaded value to cause
+ // a pipeline stall
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// USHORT ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Merge the configuration cycle type into the HAXR2 register within
+// the EPIC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+ stq a2, CfgA2(sp) // save configuration cycle type
+
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, READ_EPIC_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ bic v0, 0x3, t0 // clear config cycle type field
+ bis a1, t0, a1 // merge config cycle type
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1, t3, t4 // put data to appropriate lane
+ stl t4, (t0) // read the longword
+ mb // synchronize
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Merge the configuration cycle type into the HAXR2 register within
+// the EPIC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration cycle type
+
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, READ_EPIC_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore configuration cycle type
+ bic v0, 0x3, t0 // clear config cycle type field
+ bis a1, t0, a1 // merge config cycle type
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ bis v0, zero, t1 // consume loaded value to cause
+ // a pipeline stall
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Merge the configuration cycle type into the HAXR2 register within
+// the EPIC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+ stq a2, CfgA2(sp) // save configuration cycle type
+
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, READ_EPIC_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ bic v0, 0x3, t0 // clear config cycle type field
+ bis a1, t0, a1 // merge config cycle type
+ ldil a0, EPIC_HAXR2_QVA // address of HAXR2
+ bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // synchronize
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
diff --git a/private/ntos/nthals/halalpha/axintsup.c b/private/ntos/nthals/halalpha/axintsup.c
new file mode 100644
index 000000000..031241f5d
--- /dev/null
+++ b/private/ntos/nthals/halalpha/axintsup.c
@@ -0,0 +1,763 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ eisasup.c
+
+Abstract:
+
+ The module provides the EISA bus support for Alpha systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+ Miche Baker-Harvey (miche) 13-May-1992
+ Jeff McLeman (DEC) 1-Jun-1992
+
+Revision History:
+
+ 11-Mar-1993 Joe Mitchell (DEC)
+ Added support for NMI interrupts: Added interrupt service routine
+ HalHandleNMI. Added code to HalpCreateEisaStructures to initialize
+ NMI interrupts.
+
+ 22-Jul-1992 Jeff McLeman (mcleman)
+ Removed eisa xfer routines, since this is done in JXHWSUP
+
+ 02-Jul-92 Jeff McLeman (mcleman)
+ Removed alphadma.h header file. This file was not needed since
+ the DMA structure is described in the eisa header. Also add
+ a note describing eisa references in this module.
+
+ 13-May-92 Stole file jxebsup.c and converted for Alpha/Jensen
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Declare the interupt structure and spinlock for the intermediate EISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpEisaInterrupt;
+
+/* [jrm 3/8/93] Add support for NMI interrupts */
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for EISA interrupt mask registers and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+BOOLEAN
+HalpInitializeEisaInterrupts (
+//HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Enable Software-Generated NMI interrupts by setting bit 1 of port 0x461.
+ //
+
+ DataByte = 0x02;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ //
+ // Initialize the EISA interrupt dispatcher for EISA I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpEisaInterrupt,
+ HalpEisaInterruptHandler,
+ (PVOID) HalpEisaIntAckBase,
+ (PKSPIN_LOCK)NULL,
+ PIC_VECTOR,
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpEisaInterrupt )) {
+
+ return(FALSE);
+ }
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_LEVEL, EISA_LEVEL, EISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ interruptVector = HalpAcknowledgeEisaInterrupt(ServiceContext);
+
+
+ if ((interruptVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return;
+
+ }
+
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+ PCRInOffset = interruptVector + EISA_VECTORS;
+
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset],
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2, it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+ }
+
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ BusAddress.HighPart = 0;
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++)
+ {
+ BusAddress.LowPart = (EisaPort << 12) + 0xC80;
+
+ Status = HalTranslateBusAddress(Eisa, // InterfaceType
+ 0, // BusNumber
+ BusAddress,
+ &AddressSpace, // 1=I/O address space
+ &TranslatedAddress); // QVA
+ if (Status == FALSE)
+ {
+ UCHAR pbuf[80];
+ sprintf(pbuf,
+ "Unable to translate bus address %x for EISA slot %d\n",
+ BusAddress.LowPart, EisaPort);
+ HalDisplayString(pbuf);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+
+ port = TranslatedAddress.LowPart;
+
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+#if 0
+ // Reset NMI interrupts (for debugging purposes only).
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02);
+#endif
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halalpha/bios.c b/private/ntos/nthals/halalpha/bios.c
new file mode 100644
index 000000000..52b5dc898
--- /dev/null
+++ b/private/ntos/nthals/halalpha/bios.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ bios.c
+
+Abstract:
+
+ This module implements ROM BIOS call support for Alpha AXP NT.
+
+Author:
+
+ Eric Rehm (rehm@zso.dec.com) 9-December-1993
+
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "alpharef.h"
+#include "fwcallbk.h"
+
+
+//
+// Static data.
+//
+// none.
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG pEax,
+ IN OUT PULONG pEbx,
+ IN OUT PULONG pEcx,
+ IN OUT PULONG pEdx,
+ IN OUT PULONG pEsi,
+ IN OUT PULONG pEdi,
+ IN OUT PULONG pEbp
+ )
+
+/*++
+
+Routine Description:
+
+ This function invokes specified ROM BIOS code by executing
+ "INT BiosCommand." A callback to the i386 emulator loaded by
+ the firmware accomplishes this task. This function always
+ returns success reguardless of the result of the BIOS call.
+
+
+Arguments:
+
+ BiosCommand - specifies which ROM BIOS function to invoke.
+
+ BiosArguments - specifies a pointer to the context which will be used
+ to invoke ROM BIOS.
+
+Return Value:
+
+ TRUE if function succees, FALSE otherwise.
+
+--*/
+{
+
+ X86_BIOS_ARGUMENTS context;
+
+ context.Edi = *pEdi;
+ context.Esi = *pEsi;
+ context.Eax = *pEax;
+ context.Ebx = *pEbx;
+ context.Ecx = *pEcx;
+ context.Edx = *pEdx;
+ context.Ebp = *pEbp;
+
+ //
+ // Now call the firmware to actually perform the int 10 operation.
+ //
+
+ VenCallBios(BiosCommand, &context);
+
+ //
+ // fill in struct with any return values from the context
+ //
+
+ *pEdi = context.Edi;
+ *pEsi = context.Esi;
+ *pEax = context.Eax;
+ *pEbx = context.Ebx;
+ *pEcx = context.Ecx;
+ *pEdx = context.Edx;
+ *pEbp = context.Ebp;
+
+
+ //
+ // Indicate success
+ //
+
+ return TRUE;
+}
+
diff --git a/private/ntos/nthals/halalpha/cache.c b/private/ntos/nthals/halalpha/cache.c
new file mode 100644
index 000000000..c9d997f70
--- /dev/null
+++ b/private/ntos/nthals/halalpha/cache.c
@@ -0,0 +1,225 @@
+/*++
+
+Copyright (c) 1996 Digital Equipment Corporation
+
+Module Name:
+
+ cache.c
+
+Abstract:
+
+ Provides routine to compute the backup cache size
+
+Author:
+
+ Bala Nagarajan 5-Jan-1996
+ Adopted from Mark Baxter's user level code.
+
+Environment:
+
+ Phase 0 initialization only
+ Also Called from the firmware.
+
+--*/
+
+#include "halp.h"
+
+
+
+#define __1KB (1024)
+#define __128KB (128 * 1024)
+
+#define THRESHOLD_RPCC_PERCENT 120 // percent value
+
+static
+ULONG
+HalpTimeTheBufferAccess(
+ PUCHAR DataBuffer,
+ ULONG NumberOfAccess,
+ ULONG CacheSizeLimit,
+ ULONG CacheStride
+ )
+/*++
+
+Routine Description :
+
+ This function times the main loop that the HalpGetBCacheSize uses.
+ This is a separate function because we want to time the
+ access accurately with exactly one load in the loop.
+
+Arguments:
+
+ DataBuffer - Start address of the buffer.
+
+ NumberOfAccess - Total Nubmer of Access that needs to be made
+
+ CacheSizeLimit - The Current Cache size that is being checked
+
+ CacheStride - The stride value to access the buffer.
+
+Return Value:
+
+ The time taken to access the buffer with specified number of access.
+
+--*/
+{
+ ULONG MemoryLocation;
+ ULONG CacheSizeMask;
+ ULONG startRpcc;
+ ULONG endRpcc;
+
+ for(MemoryLocation = 0; MemoryLocation < CacheSizeLimit ;
+ MemoryLocation += CacheStride){
+ *(volatile ULONG * const)(&DataBuffer[MemoryLocation]) ;
+ }
+
+ CacheSizeMask = CacheSizeLimit - 1;
+
+ startRpcc = __RCC();
+ for ( MemoryLocation = 0;
+ NumberOfAccess > 0;
+ NumberOfAccess--, MemoryLocation += CacheStride) {
+ *(volatile LONG *)&(DataBuffer[MemoryLocation & CacheSizeMask] );
+ }
+ endRpcc = __RCC();
+
+ return (endRpcc - startRpcc);
+
+}
+
+
+ULONG
+HalpGetBCacheSize(
+ ULONGLONG ContiguousPhysicalMemorySize
+ )
+/*++
+
+Routine Description:
+
+ This function computes the size of the direct mapped backup cache.
+
+ This code checks for cache sizes from 128KB to the physical memory
+ size in steps of multiple of 2. In systems that has no cache or cache
+ larger than physical memory (!!) this algorithm will report the cache
+ size to be Zero. Since the cache size
+ is now being used only for the Secondary Page Coloring mechanism, and
+ since page coloring mechanism does not make any sense in a machine
+ without a direct mapped backup cache, the size of the cache does not
+ really affect system performance in any way.
+ [Note: Page Coloring Mechanism is used to reduce cache conflicts
+ between adjacent pages of a process in a direct mapped backup cache.]
+ In case where the cache is larger than memory itself (!!!! How often
+ have you encountered such a machine??), I think the entire page
+ coloring mechanism can break. Because you now have more colors
+ than total number of pages, meaning, there are some colors which
+ has no pages.
+
+Arguments:
+
+ ContiguousPhysicalMemorySize - The size of the physical memory.
+
+Return Value:
+
+ The size of the Backup cache in Bytes.
+
+--*/
+{
+ ULONG CacheSizeLimit = 128*__1KB;
+ ULONG NumberOfAccess;
+ ULONG CacheStride = 32*__1KB ;
+ ULONG CacheSize;
+ ULONG BaseLineElapsedRpcc;
+ ULONG ThresholdRpcc;
+ ULONG CurSizeElapsedRpcc;
+ PUCHAR DataBuffer;
+
+
+ //
+ // Set DataBuffer to point to KSEG0
+ //
+ DataBuffer = (PUCHAR) KSEG0_BASE;
+
+ //
+ // Compute the number of access we will make for each buffer
+ // size. Assume that for the largest buffer size we will make
+ // only one pass.
+ // NOTE: hopefully the division will limit the number of access to
+ // within a ULONG.
+ //
+
+ NumberOfAccess = (ULONG)(ContiguousPhysicalMemorySize/CacheStride);
+
+#if DBG
+ DbgPrint("HalpGetBCacheSize: Memory Size = %lu Bytes, "
+ "Number of Access = %lu\n",
+ ContiguousPhysicalMemorySize, NumberOfAccess);
+#endif
+ //
+ // Compute the baseline Rpcc.
+ // We touch only every cachestride(32KB) memory locations.
+ // We do this because we want to make sure that the entire set
+ // of the 3-way set associative on chip 96KB secondary cache gets
+ // filled in. This also means that we need to make the lower limit
+ // on the Bcache to be something greater than the OnChip
+ // secondary cache.
+ // First we touch all the locations to bring them into the
+ // cache before computing the baseline
+ //
+
+ BaseLineElapsedRpcc = HalpTimeTheBufferAccess(DataBuffer,
+ NumberOfAccess,
+ CacheSizeLimit, CacheStride);
+
+ //
+ // Compute the threshold Rpcc to equal to 120% of the baseline
+ // Rpcc
+ //
+ ThresholdRpcc = (BaseLineElapsedRpcc * THRESHOLD_RPCC_PERCENT) / 100;
+
+ while(CacheSizeLimit <= ContiguousPhysicalMemorySize){
+
+ CurSizeElapsedRpcc = HalpTimeTheBufferAccess(DataBuffer, NumberOfAccess,
+ CacheSizeLimit, CacheStride);
+
+#if DBG
+ DbgPrint("HalpGetBCacheSize: Size = %3ld%s"
+ " ElapsedRpcc = %7lu Threshold = %7lu\n",
+ (( CacheSizeLimit < __1MB) ?
+ ( CacheSizeLimit/__1KB) :
+ ( CacheSizeLimit /__1MB) ),
+ (( CacheSizeLimit < __1MB) ?
+ "KB" : "MB" ),
+ CurSizeElapsedRpcc,
+ ThresholdRpcc
+ );
+#endif
+
+ //
+ // if the current elapsed Rpcc is greater than threshold rpcc
+ //
+ if(CurSizeElapsedRpcc > ThresholdRpcc ){
+ break;
+ }
+ CacheSize = CacheSizeLimit;
+
+ CacheSizeLimit *= 2;
+ }
+
+ //
+ // In the following case the chance that this is a cacheless machine
+ // is very high, so we will return CacheSize to be Zero.
+ //
+ if(CacheSizeLimit >= ContiguousPhysicalMemorySize)
+ CacheSize = 0;
+
+#if DBG
+ DbgPrint("HalpGetBCacheSize: Cache Size = %lu Bytes\n",
+ CacheSize);
+#endif
+
+ //
+ // return cache size in number of bytes.
+ //
+ return (CacheSize);
+}
+
diff --git a/private/ntos/nthals/halalpha/cia.c b/private/ntos/nthals/halalpha/cia.c
new file mode 100644
index 000000000..cfdc6ce52
--- /dev/null
+++ b/private/ntos/nthals/halalpha/cia.c
@@ -0,0 +1,769 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ cia.c
+
+Abstract:
+
+ This module implements functions that are specific to the CIA ASIC.
+ The CIA ASIC is a control ASIC for cache, memory, and PCI on EV5-based
+ systems.
+
+Author:
+
+ Joe Notarangelo 26-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cia.h"
+
+BOOLEAN CiaInitialized = FALSE;
+
+//
+// The revision of the CIA. Software visible differences exist between
+// passes of the CIA. The revision is determined once at the start of
+// run-time and used in places where the software must diverge.
+//
+
+ULONG HalpCiaRevision = CIA_REVISION_1;
+
+
+VOID
+HalpInitializeCia(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ Initialize the CIA.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CIA_CONFIG CiaConfig;
+ CIA_CONTROL CiaControl;
+ CIA_ERR CiaError;
+ CIA_WBASE Wbase;
+ CIA_TBASE Tbase;
+ CIA_WMASK Wmask;
+ CIA_TBIA Tbia;
+
+ //
+ // Read the CIA revision.
+ //
+ // N.B. The revision must be read assuming pass 1 CIA.
+ //
+ // N.B. The revision must be determined before reading PCI configuration.
+ //
+
+ HalpCiaRevision =
+ READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision );
+
+#if HALDBG
+
+ DbgPrint( "Cia Revision = 0x%x\n", HalpCiaRevision );
+
+#endif //HALDBG
+
+ //
+ // Initialize CIA Control.
+ //
+
+ CiaControl.all =
+ READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ //
+ // Set CIA to optimal setting according to Paul Lemmon.
+ //
+
+ CiaControl.PciEn = 1;
+ CiaControl.PciLockEn = 0;
+ CiaControl.PciLoopEn = 1;
+ CiaControl.FstBbEn = 0;
+ CiaControl.PciMstEn = 1;
+ CiaControl.PciMemEn = 1;
+
+ //
+ // Specifically disable PCI parity checking so firmware would work.
+ // Parity can be re-enabled later by the HAL for the OS.
+ //
+
+ CiaControl.AddrPeEn = 0;
+ CiaControl.PerrEn = 0;
+
+ CiaControl.FillErrEn = 1;
+ CiaControl.MchkErrEn = 1;
+ CiaControl.EccChkEn = 1;
+ CiaControl.AssertIdleBc = 0;
+ CiaControl.ConIdleBc = 1;
+ CiaControl.CsrIoaBypass = 0;
+ CiaControl.IoFlushReqEn = 0;
+ CiaControl.CpuFlushReqEn = 0;
+ CiaControl.ArbEv5En = 0;
+
+ //
+ // Old revisions of CIA should have ArbLink off since it doesn't work.
+ //
+
+ if (HalpCiaRevision < CIA_REVISION_3) {
+
+ CiaControl.EnArbLink = 0;
+ } else {
+
+ CiaControl.EnArbLink = 1;
+ }
+
+ CiaControl.RdType = 0;
+ CiaControl.RlType = 1;
+ CiaControl.RmType = 2;
+ CiaControl.EnDmaRdPerf = 0;
+
+ WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl,
+ CiaControl.all );
+
+ //
+ // Initialize CIA Config. Turn on the performance enhancement features of
+ // CIA2. No-op for rev 1 CIA.
+ //
+
+ CiaConfig.all =
+ READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCnfg );
+
+ CiaConfig.IoaBwen = 0;
+ CiaConfig.PciDwen = 1;
+
+ WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCnfg,
+ CiaConfig.all );
+
+ //
+ // Disable all of the scatter/gather windows.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 0;
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase0,
+ Wbase.all );
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase1,
+ Wbase.all );
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase2,
+ Wbase.all );
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase3,
+ Wbase.all );
+
+ //
+ // Invalidate all of the TLB Entries:
+ //
+
+ Tbia.all = 0;
+ Tbia.InvalidateType = InvalidateAll;
+
+ //
+ // Perform the invalidation.
+ //
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia,
+ Tbia.all );
+
+ //
+ // Clear any pending error bits in the CIA_ERR register:
+ //
+
+ CiaError.all = 0; // Clear all bits
+
+ CiaError.CorErr = 1; // Correctable error
+ CiaError.UnCorErr = 1; // Uncorrectable error
+ CiaError.CpuPe = 1; // Ev5 bus parity error
+ CiaError.MemNem = 1; // Nonexistent memory error
+ CiaError.PciSerr = 1; // PCI bus serr detected
+ CiaError.PciPerr = 1; // PCI bus perr detected
+ CiaError.PciAddrPe = 1; // PCI bus address parity error
+ CiaError.RcvdMasAbt = 1; // Pci Master Abort
+ CiaError.RcvdTarAbt = 1; // Pci Target Abort
+ CiaError.PaPteInv = 1; // Invalid Pte
+ CiaError.FromWrtErr = 1; // Invalid write to flash rom
+ CiaError.IoaTimeout = 1; // Io Timeout occurred
+ CiaError.LostCorErr = 1; // Lost correctable error
+ CiaError.LostUnCorErr = 1; // Lost uncorrectable error
+ CiaError.LostCpuPe = 1; // Lost Ev5 bus parity error
+ CiaError.LostMemNem = 1; // Lost Nonexistent memory error
+ CiaError.LostPciPerr = 1; // Lost PCI bus perr detected
+ CiaError.LostPciAddrPe = 1; // Lost PCI bus address parity error
+ CiaError.LostRcvdMasAbt = 1; // Lost Pci Master Abort
+ CiaError.LostRcvdTarAbt = 1; // Lost Pci Target Abort
+ CiaError.LostPaPteInv = 1; // Lost Invalid Pte
+ CiaError.LostFromWrtErr = 1; // Lost Invalid write to flash rom
+ CiaError.LostIoaTimeout = 1; // Lost Io Timeout occurred
+ CiaError.ErrValid = 1; // Self explanatory
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all
+ );
+
+
+#if defined(CIA_PASS1)
+
+ {
+
+ ULONG Allocated;
+ PTRANSLATION_ENTRY MapRegister;
+ ULONG MaxPhysicalAddress;
+ ULONG NumberOfPages;
+ BOOLEAN __64KAlignment;
+ ULONG i;
+
+
+ //
+ // Create a special scatter/gather window to use for diagnostic
+ // DMAs that we can use to insure that the TLB is flushed of any
+ // other entries.
+ //
+
+ //
+ // Allocate a page of memory to hold the scatter/gather entries.
+ //
+
+ Allocated = HalpAllocPhysicalMemory( LoaderBlock,
+ MaxPhysicalAddress = __1GB - 1,
+ NumberOfPages = 1,
+ __64KAlignment = TRUE ); // FALSE );
+
+ //
+ // Make the first 32 entries in the new table valid, point them
+ // to the first 32 pages in memory.
+ //
+
+ MapRegister = (PTRANSLATION_ENTRY)(Allocated | KSEG0_BASE);
+
+ for( i=0; i < 32; i++ ){
+
+ ULONG Pfn = 0x700000 >> PAGE_SHIFT;
+
+ HAL_MAKE_VALID_TRANSLATION( MapRegister, Pfn );
+ MapRegister += 1;
+
+ Pfn += 1;
+
+ }
+
+ //
+ // Enable window 3 for the diagnostic dmas to the special scatter/gather
+ // table. Base of the window in PCI space is 32MB, size of the window
+ // is 1MB.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 1;
+ Wbase.SgEn = 1;
+ Wbase.Wbase = (ULONG)(__1MB * 32) >> 20;
+
+ Wmask.all = 0;
+ Wmask.Wmask = 0;
+
+ Tbase.all = 0;
+ Tbase.Tbase = (ULONG)(Allocated) >> 10;
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase3,
+ Tbase.all );
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask3,
+ Wmask.all );
+
+ WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase3,
+ Wbase.all );
+
+ }
+
+
+#endif //CIA_PASS1
+
+ CiaInitialized = TRUE;
+
+}
+
+
+VOID
+HalpCiaInitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ CIA_WINDOW_NUMBER WindowNumber
+ )
+/*++
+
+Routine Description:
+
+ Initialize the DMA Control software window registers for the specified
+ DMA Window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control.
+
+ WindowNumber - Supplies the window number initialized. (0 = Isa Dma
+ Window, 1 = Master Dma Window).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ switch( WindowNumber ){
+
+ //
+ // The ISA DMA Window.
+ //
+
+ case CiaIsaWindow:
+
+ WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase1;
+ WindowRegisters->WindowBaseRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase1;
+ WindowRegisters->WindowMaskRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask1;
+ WindowRegisters->WindowTbiaRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia;
+
+ break;
+
+ case CiaMasterWindow:
+
+ WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase0;
+ WindowRegisters->WindowBaseRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase0;
+ WindowRegisters->WindowMaskRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask0;
+ WindowRegisters->WindowTbiaRegister =
+ &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia;
+
+ break;
+
+ default:
+
+#if HALDBG
+
+ DbgPrint( "CiaInitializeSfwWindow: Bad Window Number = %x\n",
+ WindowNumber );
+
+#endif //HALDBG
+
+ break;
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpCiaProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ Program the control windows in the hardware so that DMA can be started
+ to the DMA window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ MapRegisterBase - Supplies the logical address of the scatter/gather
+ array in system memory.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CIA_WBASE Wbase;
+ CIA_TBASE Tbase;
+ CIA_WMASK Wmask;
+
+ //
+ // Program the windows as specified by the caller.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 1;
+ Wbase.SgEn = 1;
+ Wbase.Wbase = (ULONG)(WindowRegisters->WindowBase) >> 20;
+
+ Wmask.all = 0;
+ Wmask.Wmask = (WindowRegisters->WindowSize >> 20) - 1;
+
+ Tbase.all = 0;
+ Tbase.Tbase = (ULONG)MapRegisterBase >> 10;
+
+ //
+ // Dump the CIA registers.
+ //
+
+#if HALDBG
+
+ DumpCia( CiaScatterGatherRegisters );
+
+#endif //HALDBG
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_CIA_REGISTER( WindowRegisters->WindowBaseRegister, 0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_CIA_REGISTER( WindowRegisters->TranslatedBaseRegister,
+ Tbase.all );
+
+ WRITE_CIA_REGISTER( WindowRegisters->WindowMaskRegister,
+ Wmask.all );
+
+ WRITE_CIA_REGISTER( WindowRegisters->WindowBaseRegister,
+ Wbase.all );
+
+ //
+ // Flush the volatile entries in the CIA's scatter/gather Tlb.
+ //
+
+ HalpCiaInvalidateTlb( WindowRegisters, InvalidateVolatile );
+
+ //
+ // Dump the CIA registers.
+ //
+
+#if HALDBG
+
+ DumpCia( CiaScatterGatherRegisters | CiaGeneralRegisters );
+
+#endif //HALDBG
+
+ return;
+}
+
+
+VOID
+HalpCiaInvalidateTlb(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ CIA_INVALIDATE_TYPE InvalidateType
+ )
+/*++
+
+Routine Description:
+
+ Invalidate the DMA Scatter/Gather TLB in the CIA. The TLB is invalidated
+ whenever the scatter/gather translation entries are modified.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ InvalidateType - Supplies the type of invalidate the caller requires.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Perform the invalidation based on the pass of the CIA.
+ //
+
+ if( HalpCiaRevision == CIA_REVISION_1 ){
+
+ ULONG LoopbackAddress;
+ ULONG i;
+
+ //
+ // Perform 8 reads to PCI Dense space through the special loopback
+ // scatter/gather window to invalidate each entry in the CIA TLB.
+ // Each TLB fill prefetches 4 entries so our 8 reads must each be
+ // 32K bytes apart.
+ //
+
+ LoopbackAddress = __1MB * 32;
+
+ HalpMb();
+
+ for( i=0; i < 8; i++ ){
+
+ ULONG dummy;
+
+ dummy = READ_REGISTER_ULONG( (PULONG)LoopbackAddress );
+
+ LoopbackAddress += __1K * 32;
+
+ }
+
+ HalpMb();
+
+ } else {
+
+ CIA_TBIA Tbia;
+
+ //
+ // Set the invalidate as specified by the flush type.
+ //
+
+ Tbia.all = 0;
+ Tbia.InvalidateType = InvalidateType;
+
+ //
+ // Perform the invalidation.
+ //
+
+ WRITE_CIA_REGISTER( WindowRegisters->WindowTbiaRegister, Tbia.all );
+
+ } //end if( HalpCiaRevision == CIA_REVISION_1 )
+
+}
+
+
+#if HALDBG
+
+VOID
+DumpCia(
+ CIA_REGISTER_CLASS RegistersToDump
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting Cia registers and print them to the debug port.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ ULONG Value;
+
+ DbgPrint( "CIA Register Dump: \n" );
+
+ //
+ // Dump the CIA General Control registers.
+ //
+
+ if( (RegistersToDump & CiaGeneralRegisters) != 0 ){
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CiaRevision = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->PciLat;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "PciLat = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CiaCtrl = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCnfg;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CiaCnfg = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->HaeMem;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "HaeMem = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->HaeIo;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "HaeIo = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->ConfigType;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "ConfigType = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CackEn;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CackEn = 0x%x\n", Value );
+
+ }
+
+ //
+ // Dump the CIA Error registers.
+ //
+
+ if( (RegistersToDump & CiaErrorRegisters) != 0 ){
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CpuErr0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CpuErr1 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CiaErr = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CiaStat = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "ErrMask = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "CiaSyn = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "MemErr0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "MemErr1 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "PciErr0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "PciErr1 = 0x%x\n", Value );
+
+ }
+
+ //
+ // Dump the PCI Scatter/Gather registers.
+ //
+
+ if( (RegistersToDump & CiaScatterGatherRegisters) != 0 ){
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Tbia = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wbase0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wmask0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Tbase0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wbase1 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wmask1 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Tbase1 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase2;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wbase2 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask2;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wmask2 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase2;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Tbase2 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase3;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wbase3 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask3;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Wmask3 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase3;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Tbase3 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Dac;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "Dac = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag0;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "LtbTag0 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag1;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "LtbTag1 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag2;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "LtbTag2 = 0x%x\n", Value );
+
+ RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag3;
+ Value = READ_CIA_REGISTER( RegisterQva );
+ DbgPrint( "LtbTag3 = 0x%x\n", Value );
+ }
+
+
+ DbgPrint( "--end CIA Register dump\n\n" );
+
+ return;
+
+}
+
+#endif //HALDBG
+
diff --git a/private/ntos/nthals/halalpha/cia.h b/private/ntos/nthals/halalpha/cia.h
new file mode 100644
index 000000000..510b02c96
--- /dev/null
+++ b/private/ntos/nthals/halalpha/cia.h
@@ -0,0 +1,1141 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ cia.h
+
+Abstract:
+
+ This file defines the structures and definitions for the CIA ASIC.
+
+Author:
+
+ Steve Brooks 30-Jun-1994
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Chao Chen 31-Aug-1995 Add in new data structures for misc cia registers.
+
+--*/
+
+#ifndef _CIAH_
+#define _CIAH_
+
+
+//
+// CIA Revision definitions.
+//
+
+#define CIA_REVISION_1 (0)
+#define CIA_REVISION_2 (1)
+#define CIA_REVISION_3 (2)
+
+
+//
+// Define QVA constants.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xA0000000) // Identify VA as a QVA
+
+#endif //QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+//
+// Define size of I/O and memory space for the CIA.
+// Assume that the HAE==0.
+//
+
+#define PCI_MAX_IO_ADDRESS (__64MB - 1) // I/O: 0 - 64MB
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS (__512MB - 1) // Mem: 0 - 512MB
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MAX_SPARSE_MEMORY_ADDRESS + 1
+#define PCI_MAX_DENSE_MEMORY_ADDRESS (__2GB + __512MB - 1) // Dense: .5 - 2.5 Gb
+
+//
+// Defines for cia correctable errors.
+//
+
+#define CIA_IO_WRITE_ECC 0x2
+#define CIA_DMA_READ_ECC 0x6
+#define CIA_DMA_WRITE_ECC 0x7
+#define CIA_IO_READ_ECC 0xb
+#define CIA_PROCESSOR_CACHE_ECC 0x2
+#define CIA_SYSTEM_CACHE_ECC 0x3
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+#define CIA_QVA_PHYSICAL_BASE ((ULONGLONG)0x8400000000)
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | \
+ (ULONG)( (PA - CIA_QVA_PHYSICAL_BASE) >> IO_BIT_SHIFT) ) )
+
+
+//
+// Define physical address space for CIA.
+//
+
+#define CIA_PCI_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x8400000000)
+#define CIA_PCI_SPARSE_IO_PHYSICAL ((ULONGLONG)0x8580000000)
+#define CIA_PCI_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x8600000000)
+#define CIA_PCI_CONFIGURATION_PHYSICAL ((ULONGLONG)0x8700000000)
+#define CIA_PCI_INTACK_PHYSICAL ((ULONGLONG)0x8720000000)
+#define CIA_MAIN_CSRS_PHYSICAL ((ULONGLONG)0x8740000000)
+
+#define CIA_PCI_CONFIG_BASE_QVA (HAL_MAKE_QVA(CIA_PCI_CONFIGURATION_PHYSICAL))
+#define CIA_PCI_SPARSE_IO_QVA (HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL))
+#define CIA_PCI_SPARSE_MEMORY_QVA (HAL_MAKE_QVA(CIA_PCI_SPARSE_MEMORY_PHYSICAL))
+#define CIA_PCI_INTACK_QVA (HAL_MAKE_QVA(CIA_PCI_INTACK_PHYSICAL))
+
+//
+// Define the classes of CIA registers.
+//
+
+typedef enum _CIA_REGISTER_CLASS{
+ CiaGeneralRegisters = 0x1,
+ CiaErrorRegisters = 0x2,
+ CiaScatterGatherRegisters = 0x4,
+ CiaAllRegisters = 0xffffffff
+} CIA_REGISTER_CLASS, *PCIA_REGISTER_CLASS;
+
+//
+// Define the structures to access the CIA general csrs.
+//
+
+#define CIA_GENERAL_CSRS_PHYSICAL ((ULONGLONG)0x8740000080)
+#define CIA_GENERAL_CSRS_QVA HAL_MAKE_QVA(CIA_GENERAL_CSRS_PHYSICAL)
+
+typedef struct _CIA_GENERAL_CSRS{
+ UCHAR CiaRevision; // (80) PCI Revision
+ UCHAR Filler1; // (a0)
+ UCHAR PciLat; // (c0) PCI Latency
+ UCHAR Filler2; // (e0)
+ UCHAR CiaCtrl; // (100) CIA control
+ UCHAR Filler3[1]; // (120)
+ UCHAR CiaCnfg; // (140) CIA config
+ UCHAR Filler4[21]; // (160 - 3e0)
+ UCHAR HaeMem; // (400) Host address extension, sparse memory
+ UCHAR Filler5; // (420)
+ UCHAR HaeIo; // (440) Host address extension, space i/o
+ UCHAR Filler6; // (460)
+ UCHAR ConfigType; // (480) Configuration register
+ UCHAR Filler7[11]; // (4a0 - 5e0)
+ UCHAR CackEn; // (600) CIA Acknowledgement
+} CIA_GENERAL_CSRS, *PCIA_GENERAL_CSRS;
+
+extern ULONG HalpCiaRevision; // global containing CIA revision id
+
+typedef union _CIA_REVISION{
+ struct{
+ ULONG CiaRev: 8; // CIA Revision Id
+ ULONG Reserved: 24; //
+ };
+ ULONG all;
+} CIA_REVISION, *PCIA_REVISION;
+
+typedef union _CIA_PCI_LAT{
+ struct{
+ ULONG Reserved0: 8; //
+ ULONG Latency: 8; // PCI Master Latency timer (in PCI clocks)
+ ULONG Reserved1: 16; //
+ };
+ ULONG all;
+} CIA_PCI_LAT, *PCIA_PCI_LAT;
+
+typedef union _CIA_CONTROL{
+ struct{
+ ULONG PciEn: 1; // PCI Reset Enable
+ ULONG PciLockEn: 1; // Enables PCI locking of CIA
+ ULONG PciLoopEn: 1; // Enables CIA as a target
+ ULONG FstBbEn: 1; // Enables fast back to back PCI
+ ULONG PciMstEn: 1; // Enables initiating PCI transactions
+ ULONG PciMemEn: 1; // Enables CIA response to PCI transactions
+ ULONG PciReq64: 1; // Enables initiating 64-bit PCI
+ ULONG PciAck64: 1; // Enables accepting 64-bit PCI transactions
+ ULONG AddrPeEn: 1; // Enables PCI address parity checking
+ ULONG PerrEn: 1; // Enables PCI data parity checking
+ ULONG FillErrEn: 1; // Enables fill error assertion
+ ULONG MchkErrEn: 1; // Enables machine check error assertion
+ ULONG EccChkEn: 1; // Enables ECC error checking
+ ULONG AssertIdleBc: 1; // ????
+ ULONG ConIdleBc: 1; // ????
+ ULONG CsrIoaBypass: 1; // Allow CIA to bypass I/O address queue
+ ULONG IoFlushReqEn: 1; // Enables CIA to accept flush requests
+ ULONG CpuFlushReqEn: 1; // Enables CIA to accept CPU flush requests
+ ULONG ArbEv5En: 1; // Enables EV5 bypass path to memory and io
+ ULONG EnArbLink: 1; // Enable CPU memory reads to link
+ ULONG RdType: 2; // Controls memory pre-fetch algorithm
+ ULONG Reserved1: 2; //
+ ULONG RlType: 2; // Controls memory line pre-fetch algorithm
+ ULONG Reserved2: 2; //
+ ULONG RmType: 2; // Controls memory multiple pre-fetch
+ ULONG Reserved3: 1; //
+ ULONG EnDmaRdPerf: 1; // ????
+ };
+ ULONG all;
+} CIA_CONTROL, *PCIA_CONTROL;
+
+
+typedef union _CIA_CONFIG{
+ struct{
+ ULONG IoaBwen: 1; // EV56 byte/word I/O access enable
+ ULONG Reserved0: 3;
+ ULONG PciMwen: 1; // PCI target monster window enable
+ ULONG PciDwen: 1; // 2nd PCI target DMA write buffer enable
+ ULONG Reserved1: 2;
+ ULONG PciWlen: 1; // CIA link consecutive writes into a
+ ULONG Reserved2: 23; // single PCI transaction.
+ };
+ ULONG all;
+} CIA_CONFIG, *PCIA_CONFIG;
+
+typedef union _CIA_HAE_MEM{
+ struct{
+ ULONG Reserved0: 2; //
+ ULONG Region3: 6; // sets HAE for region 3
+ ULONG Reserved1: 3; //
+ ULONG Region2: 5; // sets HAE for region 2
+ ULONG Reserved: 13; //
+ ULONG Region1: 3; // sets HAE for region 1
+ };
+ ULONG all;
+} CIA_HAE_MEM, *PCIA_HAE_MEM;
+
+typedef union _CIA_HAE_IO{
+ struct{
+ ULONG Reserved0: 25; //
+ ULONG HaeIo: 7; // sets HAE for i/o space
+ };
+ ULONG all;
+} CIA_HAE_IO, *PCIA_HAE_IO;
+
+typedef union _CIA_CONFIG_TYPE{
+ struct{
+ ULONG Cfg: 2; // PCI<10> config address
+ ULONG Reserved0: 30; //
+ };
+ ULONG all;
+} CIA_CONFIG_TYPE, *PCIA_CONFIG_TYPE;
+
+typedef union _CIA_CACK_EN{
+ struct{
+ ULONG CackEn: 4; // Controls CIA acks to EV5
+ ULONG Reserved0: 28; //
+ };
+ ULONG all;
+} CIA_CACK_EN, *PCIA_CACK_EN;
+
+
+//
+// Define the structures and definitions for the CIA diagnostic registers.
+//
+
+#define CIA_DIAG_CSRS_PHYSICAL ((ULONGLONG)0x8740002000)
+#define CIA_DIAG_CSRS_QVA HAL_MAKE_QVA(CIA_DIAG_CSRS_PHYSICAL)
+
+typedef struct _CIA_DIAG_CSRS{
+ UCHAR CiaDiag; // (2000) Diagnostic Control register
+ UCHAR Filler[127]; // (2020-2fe0)
+ UCHAR DiagCheck; // (3000) Diagnostic Check register
+
+} CIA_DIAG_CSRS, *PCIA_DIAG_CSRS;
+
+typedef union _CIA_DIAG {
+ struct{
+ ULONG FromWrtEn: 1; // Flash ROM write enable bit
+ ULONG UseCheck: 1; // use known ecc pattern for writes
+ ULONG Reserved0: 26; //
+ ULONG FpePci: 2; // Force bad parity to PCI bus (if != 0)
+ ULONG Reserved1: 1; //
+ ULONG FpeToEv5: 1; // Force bad parity to the EV5 bus
+ };
+ ULONG all;
+
+} CIA_DIAG, *PCIA_DIAG;
+
+typedef union _CIA_DIAG_CHECK {
+ struct{
+ ULONG DiagCheck: 8; // ECC pattern to use when UseCheck bit set
+ ULONG Reserved: 24;
+ };
+ ULONG all;
+
+} CIA_DIAG_CHECK, *PCIA_DIAG_CHECK;
+
+//
+// Define the structures and definitions for the CIA performance registers.
+//
+
+typedef union _CIA_PERF_MONITOR{
+ struct{
+ ULONG LowCount: 16; // Low Counter Value
+ ULONG HighCount: 16; // High Counter Value
+ };
+ ULONG all;
+} CIA_PERF_MONITOR, *PCIA_PERF_MONITOR;
+
+typedef union _CIA_PERF_CONTROL{
+ struct{
+ ULONG LowSelect: 8; // Low Counter - event to count
+ ULONG Reserved1: 5; //
+ ULONG LowCountClear: 1; // Clear low counter value
+ ULONG LowErrStop: 1; // Stop low counter
+ ULONG LowCountStart: 1; // Start low counter
+ ULONG HighSelect: 8; // High Counter - event to count
+ ULONG Reserved2: 5; //
+ ULONG HighCountClear: 1; // Clear high counter value
+ ULONG HighErrStop: 1; // Stop high counter
+ ULONG HighCountStart: 1; // Start high counter
+ };
+ ULONG all;
+} CIA_PERF_CONTROL, *PCIA_PERF_CONTROL;
+
+typedef enum _CIA_PERF_SELECTS{
+ CiaUseHigh32 = 0x00,
+ CiaClockCycles = 0x01,
+ CiaRefreshCycles = 0x02,
+ CiaEv5CmdAcks = 0x10,
+ CiaEv5Reads = 0x11,
+ CiaEv5ReadMiss = 0x12,
+ CiaEv5ReadMissModify = 0x13,
+ CiaEv5BcacheVictimAcks = 0x14,
+ CiaEv5LockAcks = 0x15,
+ CiaEv5MbAcks = 0x16,
+ CiaEv5Fetch = 0x17,
+ CiaEv5WriteBlocks = 0x18,
+ CiaEv5MemoryCmds = 0x20,
+ CiaEv5IoCmds = 0x21,
+ CiaEv5IoReadCmds = 0x22,
+ CiaEv5IoWriteCmds = 0x23,
+ CiaSystemCommands = 0x24,
+ CiaEv5SystemReads = 0x25,
+ CiaEv5SystemFlushes = 0x26,
+ CiaReceivedNoAck = 0x27,
+ CiaReceivedScacheAck = 0x28,
+ CiaReceivedBcacheAck = 0x29,
+ CiaDmaReadsTotal = 0x30,
+ CiaDmaReads = 0x31,
+ CiaDmaReadLines = 0x32,
+ CiaDmaReadMultiples = 0x33,
+ CiaDmaWritesTotal = 0x34,
+ CiaDmaWrites = 0x35,
+ CiaDmaWriteInvalidates = 0x36,
+ CiaDmaDualAddressCycles = 0x37,
+ CiaDmaCycleRetries = 0x38,
+ CiaIoCycleRetries = 0x39,
+ CiaPciLocks = 0x40,
+ CiaEv5LockAccesses = 0x41,
+ CiaDmaVictimHit = 0x42,
+ CiaRefillTlb = 0x50,
+ CiaSingleBitEccErrors = 0x60
+} CIA_PERF_SELECTORS, *PCIA_PERF_SELECTORS;
+
+
+//
+// Define the structures and definitions for the CIA error registers.
+//
+
+
+#define CIA_ERROR_CSRS_PHYSICAL ((ULONGLONG)0x8740008000)
+#define CIA_ERROR_CSRS_QVA HAL_MAKE_QVA(CIA_ERROR_CSRS_PHYSICAL)
+
+typedef struct _CIA_ERROR_CSRS{
+ UCHAR CpuErr0; // (8000) CPU errors
+ UCHAR Filler0; // (8020)
+ UCHAR CpuErr1; // (8040) CPU errors
+ UCHAR Filler1[13]; // (8060 - 81e0)
+ UCHAR CiaErr; // (8200) Cia errors
+ UCHAR Filler2; // (8020)
+ UCHAR CiaStat; // (8240) Cia error status
+ UCHAR Filler3; // (8060)
+ UCHAR ErrMask; // (8280) Masks off specified errors
+ UCHAR Filler4[3]; // (82a0 - 82e0)
+ UCHAR CiaSyn; // (8300) CIA error syndrome
+ UCHAR Filler5[7]; // (8320 - 83e0)
+ UCHAR MemErr0; // (8400) Memory errors
+ UCHAR Filler6; // (8420)
+ UCHAR MemErr1; // (8440) Memory errors
+ UCHAR Filler7[29]; // (8460 - 87e0)
+ UCHAR PciErr0; // (8800) PCI errors
+ UCHAR Filler8; // (8820)
+ UCHAR PciErr1; // (8840) PCI errors
+ UCHAR Filler9; // (8860)
+ UCHAR PciErr2; // (8880) PCI errors
+} CIA_ERROR_CSRS, *PCIA_ERROR_CSRS;
+
+typedef union _CIA_CPU_ERR0{
+ struct{
+ ULONG Reserved: 4; //
+ ULONG Addr: 28; // CPU addresss bus contents on EV5 error
+ };
+ ULONG all;
+} CIA_CPU_ERR0, *PCIA_CPU_ERR0;
+
+typedef union _CIA_CPU_ERR1{
+ struct{
+ ULONG Addr34_32: 3; // address bits 34-32
+ ULONG Reserved0: 4; //
+ ULONG Addr39: 1; // address bit 39
+ ULONG Cmd: 4; // Cpu address command bus value
+ ULONG Int4Valid: 4; // Contains Int4 valid bits from CPU bus
+ ULONG Reserved1: 5; //
+ ULONG AddrCmdPar: 1; // Contains CPU bus parity bit
+ ULONG Reserved2: 8; //
+ ULONG Fpe_2_Ev5: 1; // ????
+ ULONG CpuPe: 1; // Indicates CPU interface detected parity
+ };
+ ULONG all;
+} CIA_CPU_ERR1, *PCIA_CPU_ERR1;
+
+typedef union _CIA_ERR{
+ struct{
+ ULONG CorErr: 1; // Correctable error
+ ULONG UnCorErr: 1; // Uncorrectable error
+ ULONG CpuPe: 1; // Ev5 bus parity error
+ ULONG MemNem: 1; // Nonexistent memory error
+ ULONG PciSerr: 1; // PCI bus serr detected
+ ULONG PciPerr: 1; // PCI bus perr detected
+ ULONG PciAddrPe: 1; // PCI bus address parity error
+ ULONG RcvdMasAbt: 1; // Pci Master Abort
+ ULONG RcvdTarAbt: 1; // Pci Target Abort
+ ULONG PaPteInv: 1; // Invalid Pte
+ ULONG FromWrtErr: 1; // Invalid write to flash rom
+ ULONG IoaTimeout: 1; // Io Timeout occurred
+ ULONG Reserved0: 4; //
+ ULONG LostCorErr: 1; // Lost correctable error
+ ULONG LostUnCorErr: 1; // Lost uncorrectable error
+ ULONG LostCpuPe: 1; // Lost Ev5 bus parity error
+ ULONG LostMemNem: 1; // Lost Nonexistent memory error
+ ULONG Reserved1: 1; //
+ ULONG LostPciPerr: 1; // Lost PCI bus perr detected
+ ULONG LostPciAddrPe: 1; // Lost PCI bus address parity error
+ ULONG LostRcvdMasAbt: 1; // Lost Pci Master Abort
+ ULONG LostRcvdTarAbt: 1; // Lost Pci Target Abort
+ ULONG LostPaPteInv: 1; // Lost Invalid Pte
+ ULONG LostFromWrtErr: 1; // Lost Invalid write to flash rom
+ ULONG LostIoaTimeout: 1; // Lost Io Timeout occurred
+ ULONG Reserved2: 3; //
+ ULONG ErrValid: 1; // Self explanatory
+ };
+ ULONG all;
+} CIA_ERR, *PCIA_ERR;
+
+#define CIA_ERR_FATAL_MASK 0x00000ffe
+#define CIA_ERR_LOST_MASK 0x0fff0000
+
+typedef union _CIA_STAT{
+ struct{
+ ULONG PciStatus: 2; // Pci Status
+ ULONG Reserved0: 1; //
+ ULONG MemSource: 1; // 0=ev5 1=Pci
+ ULONG IoaValid: 4; // Valid bits for Io command address queue
+ ULONG CpuQueue: 3; // Valid bits for Cpu command address queue
+ ULONG TlbMiss: 1; // Tlb Miss refill in progress
+ ULONG DmSt: 4; // state machine values
+ ULONG PaCpuRes: 2; // Ev5 response for DMA
+ ULONG Reserved1: 14; //
+ };
+ ULONG all;
+} CIA_STAT, *PCIA_STAT;
+
+
+typedef union _CIA_ERR_MASK{
+ struct{
+ ULONG CorErr: 1; // Enable Correctable error
+ ULONG UnCorErr: 1; // Enable Uncorrectable error
+ ULONG CpuPe: 1; // Enable Ev5 bus parity error
+ ULONG MemNem: 1; // Enable Nonexistent memory error
+ ULONG PciSerr: 1; // Enable PCI bus serr detected
+ ULONG PciPerr: 1; // Enable PCI bus perr detected
+ ULONG PciAddrPe: 1; // Enable PCI bus address parity error
+ ULONG RcvdMasAbt: 1; // Enable Pci Master Abort
+ ULONG RcvdTarAbt: 1; // Enable Pci Target Abort
+ ULONG PaPteInv: 1; // Enable Invalid Pte
+ ULONG FromWrtErr: 1; // Enable Invalid write to flash rom
+ ULONG IoaTimeout: 1; // Enable Io Timeout occurred
+ ULONG Reserved0: 20; //
+ };
+ ULONG all;
+} CIA_ERR_MASK, *PCIA_ERR_MASK;
+
+typedef union _CIA_SYN{
+ struct{
+ ULONG EccSyndrome: 8; // Ecc syndrome
+ ULONG Reserved0: 24; //
+ };
+ ULONG all;
+} CIA_SYN, *PCIA_SYN;
+
+typedef union _CIA_MEM_ERR0{
+ struct{
+ ULONG Reserved0: 4; //
+ ULONG Addr31_4: 28; // Memory port address bits
+ };
+ ULONG all;
+} CIA_MEM_ERR0, *PCIA_MEM_ERR0;
+
+typedef union _CIA_MEM_ERR1{
+ struct{
+ ULONG Addr33_32: 2; // memory port address bits
+ ULONG Reserved0: 5; //
+ ULONG Addr39: 1; // Address bit 39
+ ULONG MemPortCmd: 4; // Memory port command
+ ULONG MemPortMask: 4; // Mask bits when error occurred
+ ULONG SeqSt: 4; // Memory sequencer state
+ ULONG MemPortSrc: 1; // 0=cpu, 1=dma
+ ULONG Reserved1: 3; //
+ ULONG SetSel: 5; // Indicates active memory set
+ ULONG Reserved2: 3; //
+ };
+ ULONG all;
+} CIA_MEM_ERR1, *PCIA_MEM_ERR1;
+
+typedef union _CIA_PCI_ERR0{
+ struct{
+ ULONG Cmd: 4; // Pci command
+ ULONG LockState: 1; // Indicates CIA locked
+ ULONG DacCycle: 1; // indicates PCI dual address cycle
+ ULONG Reserved0: 2; //
+ ULONG Window: 4; // Selected DMA window
+ ULONG Reserved1: 4; //
+ ULONG MasterState: 4; // State of PCI master
+ ULONG TargetState: 3; // State of PCI target
+ ULONG Reserved2: 9; //
+ };
+ ULONG all;
+} CIA_PCI_ERR0, *PCIA_PCI_ERR0;
+
+typedef struct _CIA_PCI_ERR1{
+ ULONG PciAddress; // Pci Address
+} CIA_PCI_ERR1, *PCIA_PCI_ERR1;
+
+typedef struct _CIA_PCI_ERR2{
+ ULONG PciAddress; // Pci Address
+} CIA_PCI_ERR2, *PCIA_PCI_ERR2;
+
+//
+// Define the structures and definitions for the CIA memory registers.
+//
+
+#define CIA_MEMORY_CSRS_PHYSICAL ((ULONGLONG)0x8750000000)
+#define CIA_MEMORY_CSRS_QVA HAL_MAKE_QVA(CIA_MEMORY_CSRS_PHYSICAL)
+
+typedef struct _CIA_MEMORY_CSRS{
+ UCHAR Mcr; // (0000) MCR register
+ UCHAR Filler0[47]; // (0020 - 05e0)
+ UCHAR Mba0; // (0600) Mba0 register
+ UCHAR Filler1[3]; // (0620 - 0660)
+ UCHAR Mba2; // (0680) Mba2 register
+ UCHAR Filler2[3]; // (06a0 - 06e0)
+ UCHAR Mba4; // (0700) Mba4 register
+ UCHAR Filler3[3]; // (0720 - 0760)
+ UCHAR Mba6; // (0780) Mba6 register
+ UCHAR Filler4[3]; // (07a0 - 07e0)
+ UCHAR Mba8; // (0800) Mba8 register
+ UCHAR Filler5[3]; // (0820 - 0860)
+ UCHAR MbaA; // (0880) MbaA register
+ UCHAR Filler6[3]; // (08a0 - 08e0)
+ UCHAR MbaC; // (0900) MbaC register
+ UCHAR Filler7[3]; // (0920 - 960)
+ UCHAR MbaE; // (0980) MbaE register
+ UCHAR Filler8[8]; // (0a00 - ae0)
+ UCHAR Tmg0; // (0b00) Tmg0 register
+ UCHAR Filer9; // (0b20)
+ UCHAR Tmg1; // (0b40) Tmg1 register
+ UCHAR Filer10; // (0b60)
+ UCHAR Tmg2; // (0b80) Tmg2 register
+} CIA_MEMORY_CSRS, *PCIA_MEMORY_CSRS;
+
+//
+// Define structures and definitions for Memory control registers:
+//
+
+typedef union _CIA_MCR{
+ struct{
+ ULONG MemSize: 1; // Memory path width (256 vs. 128)
+ ULONG Reserved1: 3; //
+ ULONG CacheSize: 3; // Bcache size
+ ULONG Reserved2: 1; //
+ ULONG RefRate: 10; // Memory refresh rate
+ ULONG RefBurst: 2; // Refresh configuration
+ ULONG TmgR0: 2; // Row address setup control
+ ULONG LongCbrCas: 1; // CAS pulse width
+ ULONG Reserved3: 3; //
+ ULONG DelayIdleBc: 2; // ??
+ ULONG Reserved4: 1; //
+ ULONG EarlyIdleBc: 1; // ??
+ ULONG Reserved5: 2; //
+ };
+ ULONG all;
+} CIA_MCR, *PCIA_MCR;
+
+typedef union _CIA_MBA{
+ struct{
+ ULONG MbaS0Valid: 1; // Indiates side 0 of bank is valid
+ ULONG MbaRowType: 2; // Row and column configuration
+ ULONG Reserved1: 1; //
+ ULONG MbaMask: 5; // Comparision Mask
+ ULONG Reserved2: 6; //
+ ULONG MbaS1Valid: 1; // Indicates side 1 of bank is valid
+ ULONG MbaPattern: 10; // Address decode pattern
+ ULONG Reserved3: 2; //
+ ULONG MbaTiming: 2; // TMGx CSR select
+ ULONG Reserved4: 2; //
+ };
+ ULONG all;
+} CIA_MBA, *PCIA_MBA;
+
+typedef union _CIA_TMG{
+ struct{
+ ULONG TmgR1: 2; // Read starting, data delay
+ ULONG TmgR2: 2; // Row address hold
+ ULONG TmgR3: 2; // Read cycle time
+ ULONG TmgR4: 2; // Read, CAS assertion delay
+ ULONG TmgR5: 2; // Read, CAS pulse width
+ ULONG TmgR6: 2; // Read, column address hold
+ ULONG TmgW1: 2; // Write, data delay
+ ULONG TmgW4: 3; // Write, CAS assertion delay
+ ULONG TmgPre: 1; // RAS precharge delay
+ ULONG TmgV3: 2; // Write, cycle time
+ ULONG TmgV4: 3; // Linked victim, CAS assertion delay
+ ULONG Reserved1: 1; //
+ ULONG TmgV5: 2; // Victim/Write, CAS pulse width
+ ULONG TmgV6: 2; // Victim/Write, Column address hold
+ ULONG TmgRv: 2; // Read to victim start delay
+ ULONG TmgRdDelay: 2; // Read data delay
+ };
+ ULONG all;
+} CIA_TMG, *PCIA_TMG;
+
+//
+// Define structures and definitions for Scatter/Gather control registers:
+//
+
+#define CIA_SCATTER_GATHER_CSRS_PHYSICAL ((ULONGLONG)0x8760000100)
+#define CIA_SG_CSRS_QVA (HAL_MAKE_QVA(CIA_SCATTER_GATHER_CSRS_PHYSICAL))
+
+typedef struct _CIA_SG_CSRS{
+ UCHAR Tbia; // (100) Translation buffer invalidate all
+ UCHAR Filler0[23]; // (120-3e0)
+ UCHAR Wbase0; // (400) Base address, DMA window 0
+ UCHAR Filler1; // (420)
+ UCHAR Wmask0; // (440) Mask Register, DMA window 0
+ UCHAR Filler2; // (460)
+ UCHAR Tbase0; // (480) Translation Base, DMA window 0
+ UCHAR Filler3[3]; // (4a0 - 4e0)
+ UCHAR Wbase1; // (500) Base address, DMA window 1
+ UCHAR Filler4; // (520)
+ UCHAR Wmask1; // (540) Mask Register, DMA window 1
+ UCHAR Filler5; // (560)
+ UCHAR Tbase1; // (580) Translation Base, DMA window 1
+ UCHAR Filler6[3]; // (5a0 - 5e0)
+ UCHAR Wbase2; // (600) Base address, DMA window 2
+ UCHAR Filler7; // (620)
+ UCHAR Wmask2; // (640) Mask Register, DMA window 2
+ UCHAR Filler8; // (660)
+ UCHAR Tbase2; // (680) Translation Base, DMA window 2
+ UCHAR Filler9[3]; // (6a0 - 6e0)
+ UCHAR Wbase3; // (700) Base address, DMA window 3
+ UCHAR Filler10; // (720)
+ UCHAR Wmask3; // (740) Mask Register, DMA window 3
+ UCHAR Filler11; // (760)
+ UCHAR Tbase3; // (780) Translation Base, DMA window 3
+ UCHAR Filler12; // (7a0)
+ UCHAR Dac; // (7c0) Window DAC Base
+ UCHAR Filler13; // (7e0)
+ UCHAR LtbTag0; // (800) Lockable Translation Buffer Tag 0
+ UCHAR Filler14; // (820)
+ UCHAR LtbTag1; // (840) Lockable Translation Buffer Tag 1
+ UCHAR Filler15; // (860)
+ UCHAR LtbTag2; // (880) Lockable Translation Buffer Tag 2
+ UCHAR Filler16; // (8a0)
+ UCHAR LtbTag3; // (8c0) Lockable Translation Buffer Tag 3
+ UCHAR Filler17; // (8e0)
+ UCHAR TbTag0; // (900) Translation Buffer Tag 0
+ UCHAR Filler18; // (920)
+ UCHAR TbTag1; // (940) Translation Buffer Tag 1
+ UCHAR Filler19; // (960)
+ UCHAR TbTag2; // (980) Translation Buffer Tag 2
+ UCHAR Filler20; // (9a0)
+ UCHAR TbTag3; // (9c0) Translation Buffer Tag 3
+ UCHAR Filler21; // (9e0)
+ UCHAR Tb0Page0; // (1000) Translation Buffer 0 Page 0
+ UCHAR Filler22; // (1020)
+ UCHAR Tb0Page1; // (1040) Translation Buffer 0 Page 1
+ UCHAR Filler23; // (1060)
+ UCHAR Tb0Page2; // (1080) Translation Buffer 0 Page 2
+ UCHAR Filler24; // (10a0)
+ UCHAR Tb0Page3; // (10c0) Translation Buffer 0 Page 3
+ UCHAR Filler25; // (10e0)
+ UCHAR Tb1Page0; // (1100) Translation Buffer 1 Page 0
+ UCHAR Filler26; // (1120)
+ UCHAR Tb1Page1; // (1140) Translation Buffer 1 Page 1
+ UCHAR Filler27; // (1160)
+ UCHAR Tb1Page2; // (1180) Translation Buffer 1 Page 2
+ UCHAR Filler28; // (11a0)
+ UCHAR Tb1Page3; // (11c0) Translation Buffer 1 Page 3
+ UCHAR Filler29; // (11e0)
+ UCHAR Tb2Page0; // (1200) Translation Buffer 2 Page 0
+ UCHAR Filler30; // (1220)
+ UCHAR Tb2Page1; // (1240) Translation Buffer 2 Page 1
+ UCHAR Filler31; // (1260)
+ UCHAR Tb2Page2; // (1280) Translation Buffer 2 Page 2
+ UCHAR Filler32; // (12a0)
+ UCHAR Tb2Page3; // (12c0) Translation Buffer 2 Page 3
+ UCHAR Filler33; // (12e0)
+ UCHAR Tb3Page0; // (1300) Translation Buffer 3 Page 0
+ UCHAR Filler34; // (1320)
+ UCHAR Tb3Page1; // (1340) Translation Buffer 3 Page 1
+ UCHAR Filler35; // (1360)
+ UCHAR Tb3Page2; // (1380) Translation Buffer 3 Page 2
+ UCHAR Filler36; // (13a0)
+ UCHAR Tb3Page3; // (13c0) Translation Buffer 3 Page 3
+ UCHAR Filler37; // (13e0)
+ UCHAR Tb4Page0; // (1400) Translation Buffer 4 Page 0
+ UCHAR Filler38; // (1420)
+ UCHAR Tb4Page1; // (1440) Translation Buffer 4 Page 1
+ UCHAR Filler39; // (1460)
+ UCHAR Tb4Page2; // (1480) Translation Buffer 4 Page 2
+ UCHAR Filler40; // (14a0)
+ UCHAR Tb4Page3; // (14c0) Translation Buffer 4 Page 3
+ UCHAR Filler41; // (14e0)
+ UCHAR Tb5Page0; // (1500) Translation Buffer 5 Page 0
+ UCHAR Filler42; // (1520)
+ UCHAR Tb5Page1; // (1540) Translation Buffer 5 Page 1
+ UCHAR Filler43; // (1560)
+ UCHAR Tb5Page2; // (1580) Translation Buffer 5 Page 2
+ UCHAR Filler44; // (15a0)
+ UCHAR Tb5Page3; // (15c0) Translation Buffer 5 Page 3
+ UCHAR Filler45; // (15e0)
+ UCHAR Tb6Page0; // (1600) Translation Buffer 6 Page 0
+ UCHAR Filler46; // (1620)
+ UCHAR Tb6Page1; // (1640) Translation Buffer 6 Page 1
+ UCHAR Filler47; // (1660)
+ UCHAR Tb6Page2; // (1680) Translation Buffer 6 Page 2
+ UCHAR Filler48; // (16a0)
+ UCHAR Tb6Page3; // (16c0) Translation Buffer 6 Page 3
+ UCHAR Filler49; // (16e0)
+ UCHAR Tb7Page0; // (1700) Translation Buffer 7 Page 0
+ UCHAR Filler50; // (1720
+ UCHAR Tb7Page1; // (1740) Translation Buffer 7 Page 1
+ UCHAR Filler51; // (1760)
+ UCHAR Tb7Page2; // (1780) Translation Buffer 7 Page 2
+ UCHAR Filler52; // (17a0)
+ UCHAR Tb7Page3; // (17c0) Translation Buffer 7 Page 3
+
+} CIA_SG_CSRS, *PCIA_SG_CSRS;
+
+
+typedef union _CIA_TBIA{
+ struct{
+ ULONG InvalidateType: 2; // Type of invalidation
+ ULONG Reserved0: 30; //
+ };
+ ULONG all;
+} CIA_TBIA, *PCIA_TBIA;
+
+typedef union _CIA_WBASE{
+ struct{
+ ULONG Wen: 1; // Window enable
+ ULONG SgEn: 1; // Scatter Gather enable
+ ULONG MemcsEn: 1; // Memory Cs Enable
+ ULONG DacEn: 1; // DAC Enable
+ ULONG Reserved0: 16; //
+ ULONG Wbase: 12; // Base address of DMA window
+ };
+ ULONG all;
+} CIA_WBASE, *PCIA_WBASE;
+
+typedef union _CIA_WMASK{
+ struct{
+ ULONG Reserved0: 20; //
+ ULONG Wmask: 12; // Window mask
+ };
+ ULONG all;
+} CIA_WMASK, *PCIA_WMASK;
+
+typedef union _CIA_TBASE{
+ struct{
+ ULONG Reserved0: 8; //
+ ULONG Tbase: 24; // Translation base address
+ };
+ ULONG all;
+} CIA_TBASE, *PCIA_TBASE;
+
+typedef union _CIA_LTB_TAG{
+ struct{
+ ULONG Valid: 1;
+ ULONG Locked: 1;
+ ULONG Dac: 1;
+ ULONG Reserved0: 12;
+ ULONG TbTag: 17;
+ };
+ ULONG all;
+} CIA_LTB_TAG, *PCIA_LTB_TAG;
+
+typedef union _CIA_TB_TAG{
+ struct{
+ ULONG Valid: 1;
+ ULONG Reserved0: 1;
+ ULONG Dac: 1;
+ ULONG Reserved1: 12;
+ ULONG TbTag: 17;
+ };
+ ULONG all;
+} CIA_TB_TAG, *PCIA_TB_TAG;
+
+
+//
+// DMA Window Values.
+//
+// The CIA will be initialized to allow 2 DMA windows.
+// The first window will be for the use of of ISA devices and DMA slaves
+// and therefore must have logical addresses below 16MB.
+// The second window will be for bus masters (non-ISA) and so may be
+// above 16MB.
+//
+// The arrangement of the windows will be as follows:
+//
+// Window Logical Start Address Window Size
+// ------ --------------------- -----------
+// Isa 8MB 8MB
+// Master 16MB 16MB
+//
+
+#define ISA_DMA_WINDOW_BASE (__8MB)
+#define ISA_DMA_WINDOW_SIZE (__8MB)
+
+#define MASTER_DMA_WINDOW_BASE (__16MB)
+#define MASTER_DMA_WINDOW_SIZE (__16MB)
+
+
+//
+// Define the software control registers for a DMA window.
+//
+
+typedef struct _WINDOW_CONTROL_REGISTERS{
+ PVOID WindowBase;
+ ULONG WindowSize;
+ PVOID TranslatedBaseRegister;
+ PVOID WindowBaseRegister;
+ PVOID WindowMaskRegister;
+ PVOID WindowTbiaRegister;
+} WINDOW_CONTROL_REGISTERS, *PWINDOW_CONTROL_REGISTERS;
+
+//
+// Define types of windows.
+//
+
+typedef enum _CIA_WINDOW_NUMBER{
+ CiaIsaWindow,
+ CiaMasterWindow
+} CIA_WINDOW_NUMBER, *PCIA_WINDOW_NUMBER;
+
+//
+// Define the types of invalidates that can be performed by the CIA.
+//
+
+typedef enum _CIA_INVALIDATE_TYPE{
+ InvalidateNoop = 0x0,
+ InvalidateLocked = 0x1,
+ InvalidateVolatile = 0x2,
+ InvalidateAll = 0x3
+} CIA_INVALIDATE_TYPE, *PCIA_INVALIDATE_TYPE;
+
+//
+// Define CIA Window Control routines.
+//
+
+VOID
+HalpCiaInitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ CIA_WINDOW_NUMBER WindowNumber
+ );
+
+VOID
+HalpCiaProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ );
+
+VOID
+HalpCiaInvalidateTlb(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ CIA_INVALIDATE_TYPE InvalidateType
+ );
+
+VOID
+WRITE_CIA_REGISTER(
+ PVOID,
+ ULONGLONG
+ );
+
+ULONG
+READ_CIA_REGISTER(
+ PVOID
+ );
+
+VOID
+WRITE_GRU_REGISTER(
+ PVOID,
+ ULONGLONG
+ );
+
+ULONG
+READ_GRU_REGISTER(
+ PVOID
+ );
+
+ULONG
+INTERRUPT_ACKNOWLEDGE(
+ PVOID
+ );
+
+BOOLEAN
+HalpCiaUncorrectableError(
+ VOID
+ );
+
+VOID
+HalpCiaReportFatalError(
+ VOID
+ );
+
+BOOLEAN
+HalpCiaMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+VOID
+HalpInitializeCia(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpInitializeCiaMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ );
+
+#if HALDBG
+
+VOID
+DumpCia(
+ CIA_REGISTER_CLASS RegistersToDump
+ );
+
+#endif //HALDBG
+
+
+//
+// VOID
+// INITIALIZE_ISA_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_ISA_DMA_CONTROL( WR ) \
+ HalpCiaInitializeSfwWindow( (WR), CiaIsaWindow );
+
+
+//
+// VOID
+// INITIALIZE_MASTER_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_MASTER_DMA_CONTROL( WR ) \
+ HalpCiaInitializeSfwWindow( (WR), CiaMasterWindow );
+
+
+//
+// VOID
+// INITIALIZE_DMA_WINDOW(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters,
+// PTRANSLATION_ENTRY MapRegisterBase
+// )
+//
+// Routine Description:
+//
+// Program the control windows so that DMA can be started to the
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window register
+// control structure.
+//
+// MapRegisterBase - Supplies the logical address of the scatter/gather
+// array in system memory.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_DMA_WINDOW( WR, MRB ) \
+ HalpCiaProgramDmaWindow( (WR), (MRB) );
+
+
+//
+// VOID
+// INVALIDATE_DMA_TRANSLATIONS(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Invalidate all of the cached translations for a DMA window.
+//
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control
+// registers.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INVALIDATE_DMA_TRANSLATIONS( WR ) \
+ HalpCiaInvalidateTlb( (WR), InvalidateAll );
+
+
+//
+// Define the format of a translation entry aka a scatter/gather entry
+// or map register.
+//
+
+typedef struct _TRANSLATION_ENTRY{
+ ULONG Valid: 1;
+ ULONG Pfn: 31;
+ ULONG Reserved;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+
+//
+// VOID
+// HAL_MAKE_VALID_TRANSLATION(
+// PTRANSLATION_ENTRY Entry,
+// ULONG PageFrameNumber
+// )
+//
+// Routine Description:
+//
+// Make the scatter/gather entry pointed to by Entry valid with
+// a translation to the page indicated by PageFrameNumber.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation entry to make valid.
+//
+// PageFrameNumber - Supplies the page frame of the valid translation.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_MAKE_VALID_TRANSLATION( ENTRY, PFN ) \
+ { \
+ (ENTRY)->Valid = 1; \
+ (ENTRY)->Pfn = PFN; \
+ (ENTRY)->Reserved = 0; \
+ }
+
+
+//
+// VOID
+// HAL_INVALIDATE_TRANSLATION(
+// PTRANSLATION_ENTRY Entry
+// )
+//
+// Routine Description:
+//
+// Invalidate the translation indicated by Entry.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation to be invalidated.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_INVALIDATE_TRANSLATION( ENTRY ) \
+ (ENTRY)->Valid = 0;
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_CIAH_
diff --git a/private/ntos/nthals/halalpha/ciaaddr.c b/private/ntos/nthals/halalpha/ciaaddr.c
new file mode 100644
index 000000000..52d53a696
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ciaaddr.c
@@ -0,0 +1,567 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ciaaddr.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Alcor system.
+
+Author:
+
+ Joe Notarangelo 30-Jun-1994
+ Steve Brooks 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call HalCreateQva to
+ build a Quasi Virtual Address and return that to the caller. We then
+ set AddressSpace to a 1, so that the caller will not call MmMapIoSpace.
+ The Caller will use the low 32 bits of the physical address we return
+ as the VA. (Which we built a QVA in).
+
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The buses available on Alcor are EISA and PCI.
+ // We support any translations for ISA devices as well,
+ // since they can plug into EISA slots just fine.
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system; return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory:
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa:
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ case PCIBus: {
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ case Eisa:
+
+ break;
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart = (ULONG)HalCreateQva(
+ *TranslatedAddress,
+ va);
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // don't let the user call
+ // MmMapIoSpace
+ return(TRUE);
+
+ case BusIo:
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa:
+
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ case PCIBus:
+
+ //
+ // PCI IO space is always below 64MB (26 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+
+ if( BusAddress.LowPart >= __64MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ case Eisa:
+
+ break;
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_IO_PHYSICAL;
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG)HalCreateQva(
+ *TranslatedAddress,
+ va);
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // make sure user doesn't call
+ // MmMapIoSpace.
+ return(TRUE);
+
+ case UserBusMemory:
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ case UserBusIo:
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_IO_PHYSICAL;
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_DENSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ default:
+
+ //
+ // Unsupported address space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PHYSICAL_ADDRESS PhysicalOffset;
+ PVOID qva;
+
+ if( (PA.QuadPart >= CIA_PCI_DENSE_MEMORY_PHYSICAL) &&
+ (PA.QuadPart <= (CIA_PCI_DENSE_MEMORY_PHYSICAL +
+ PCI_MAX_DENSE_MEMORY_ADDRESS)) ){
+
+ //
+ // Kernel-mode physical dense address, return VA.
+ //
+
+ return(VA);
+
+ } else if( (PA.QuadPart >=
+ (CIA_PCI_DENSE_MEMORY_PHYSICAL | EV5_USER_IO_ADDRESS_SPACE) ) &&
+ (PA.QuadPart <
+ (CIA_PCI_DENSE_MEMORY_PHYSICAL | EV5_USER_IO_ADDRESS_SPACE +
+ PCI_MAX_DENSE_MEMORY_ADDRESS) ) ){
+
+ //
+ // User-mode physical dense address, return VA.
+ //
+
+ return(VA);
+
+ } else {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ PhysicalOffset.QuadPart = PA.QuadPart - CIA_QVA_PHYSICAL_BASE;
+ qva = (PVOID)(PhysicalOffset.QuadPart >> IO_BIT_SHIFT);
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+
+}
+
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+ //
+ // For Alcor we support three bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support PCI Dense space: check to see if it's really
+ // a QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+
+ break;
+
+ default:
+
+ return NULL;
+ }
+}
diff --git a/private/ntos/nthals/halalpha/ciaerr.c b/private/ntos/nthals/halalpha/ciaerr.c
new file mode 100644
index 000000000..ef984011e
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ciaerr.c
@@ -0,0 +1,1642 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ciaerr.c
+
+Abstract:
+
+ This module implements error handling functions for the CIA ASIC.
+
+Author:
+
+ Joe Notarangelo 26-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cia.h"
+#include "stdio.h"
+
+//
+// Externals and globals.
+//
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+extern ULONG HalDisablePCIParityChecking;
+ULONG CiaCorrectedErrors = 0;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ );
+
+//
+// Allocate a flag that indicates when a PCI Master Abort is expected.
+// PCI Master Aborts are signaled on configuration reads to non-existent
+// PCI slots. A non-zero value indicates that a Master Abort is expected.
+//
+
+ULONG HalpMasterAbortExpected = 0;
+
+
+VOID
+HalpInitializeCiaMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for a CIA-based
+ system by clearing all pending errors in the CIA registers and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CIA_CONTROL CiaControl;
+ CIA_ERR CiaError;
+ CIA_ERR_MASK CiaErrMask;
+
+ //
+ // Clear any pending error bits in the CIA_ERR register:
+ //
+
+ CiaError.all = 0; // Clear all bits
+
+ CiaError.CorErr = 1; // Correctable error
+ CiaError.UnCorErr = 1; // Uncorrectable error
+ CiaError.CpuPe = 1; // Ev5 bus parity error
+ CiaError.MemNem = 1; // Nonexistent memory error
+ CiaError.PciSerr = 1; // PCI bus serr detected
+ CiaError.PciPerr = 1; // PCI bus perr detected
+ CiaError.PciAddrPe = 1; // PCI bus address parity error
+ CiaError.RcvdMasAbt = 1; // Pci Master Abort
+ CiaError.RcvdTarAbt = 1; // Pci Target Abort
+ CiaError.PaPteInv = 1; // Invalid Pte
+ CiaError.FromWrtErr = 1; // Invalid write to flash rom
+ CiaError.IoaTimeout = 1; // Io Timeout occurred
+ CiaError.LostCorErr = 1; // Lost correctable error
+ CiaError.LostUnCorErr = 1; // Lost uncorrectable error
+ CiaError.LostCpuPe = 1; // Lost Ev5 bus parity error
+ CiaError.LostMemNem = 1; // Lost Nonexistent memory error
+ CiaError.LostPciPerr = 1; // Lost PCI bus perr detected
+ CiaError.LostPciAddrPe = 1; // Lost PCI bus address parity error
+ CiaError.LostRcvdMasAbt = 1; // Lost Pci Master Abort
+ CiaError.LostRcvdTarAbt = 1; // Lost Pci Target Abort
+ CiaError.LostPaPteInv = 1; // Lost Invalid Pte
+ CiaError.LostFromWrtErr = 1; // Lost Invalid write to flash rom
+ CiaError.LostIoaTimeout = 1; // Lost Io Timeout occurred
+ CiaError.ErrValid = 1; // Self explanatory
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all
+ );
+
+ //
+ // Set the Mask Bits in the CIA_MASK register:
+ //
+
+ CiaErrMask.all = 0; // Clear all bits
+
+ CiaErrMask.UnCorErr = 1; // Enable Uncorrectable error
+ CiaErrMask.CpuPe = 1; // Enable Ev5 bus parity error
+ CiaErrMask.MemNem = 1; // Enable Nonexistent memory error
+ CiaErrMask.PciSerr = 1; // Enable PCI bus serr detected
+ CiaErrMask.RcvdMasAbt = 1; // Enable Pci Master Abort
+ CiaErrMask.RcvdTarAbt = 1; // Enable Pci Target Abort
+ CiaErrMask.PaPteInv = 1; // Enable Invalid Pte
+ CiaErrMask.FromWrtErr = 1; // Enable Invalid write to flash rom
+ CiaErrMask.IoaTimeout = 1; // Enable Io Timeout occurred
+
+ //
+ // Determine PCI parity checking.
+ //
+
+ CiaControl.all = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ if (PciParityChecking == FALSE) {
+
+ CiaControl.AddrPeEn = 0; // Disable PCI address parity checking
+ CiaControl.PerrEn = 0; // Disable PCI data parity checking
+
+ CiaErrMask.PciPerr = 0; // Disable PCI bus perr detected
+ CiaErrMask.PciAddrPe = 0; // Disable PCI bus address parity error
+
+ } else {
+
+ CiaControl.AddrPeEn = PciParityChecking;
+ CiaControl.PerrEn = PciParityChecking;
+
+ CiaErrMask.PciPerr = PciParityChecking;
+ CiaErrMask.PciAddrPe = PciParityChecking;
+
+ }
+
+ CiaErrMask.CorErr = (ReportCorrectableErrors == TRUE);
+
+ WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl,
+ CiaControl.all
+ );
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ //
+ // Set the machine check enables within the EV5.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+
+ } else {
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ return;
+
+}
+
+#define MAX_ERROR_STRING 128
+
+
+BOOLEAN
+HalpCiaUncorrectableError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the CIA error register and determine if an uncorrectable error
+ is latched in the error bits.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE is returned if an uncorrectable error has been detected. FALSE
+ is returned otherwise.
+
+--*/
+{
+ CIA_ERR CiaError;
+
+
+ CiaError.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
+
+ //
+ // If no error is valid then an uncorrectable error was not detected.
+ //
+
+ if( CiaError.ErrValid == 0 ){
+ return FALSE;
+ }
+
+ //
+ // Check each of the individual uncorrectable error bits, if any is set
+ // then return TRUE.
+ //
+
+ if( (CiaError.UnCorErr == 1) ||
+ (CiaError.CpuPe == 1) ||
+ (CiaError.MemNem == 1) ||
+ (CiaError.PciSerr == 1) ||
+ (CiaError.PciPerr == 1) ||
+ (CiaError.PciAddrPe == 1) ||
+ (CiaError.RcvdMasAbt == 1) ||
+ (CiaError.RcvdTarAbt == 1) ||
+ (CiaError.PaPteInv == 1) ||
+ (CiaError.FromWrtErr == 1) ||
+ (CiaError.IoaTimeout == 1) ){
+
+ return TRUE;
+
+ }
+
+ //
+ // None of the uncorrectable error conditions were detected.
+ //
+
+ return FALSE;
+
+}
+
+
+VOID
+HalpBuildCiaConfigurationFrame(
+ PCIA_CONFIGURATION pConfiguration
+ )
+{
+ pConfiguration->CiaRev = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision );
+
+ pConfiguration->CiaCtrl = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ pConfiguration->Mcr = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mcr );
+
+ pConfiguration->Mba0 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba0 );
+
+ pConfiguration->Mba2 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba2 );
+
+ pConfiguration->Mba4 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba4 );
+
+ pConfiguration->Mba6 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba6 );
+
+ pConfiguration->Mba8 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba8 );
+
+ pConfiguration->MbaA = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaA );
+
+ pConfiguration->MbaC = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaC );
+
+ pConfiguration->MbaE = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaE );
+
+ pConfiguration->Tmg0 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg0 );
+
+ pConfiguration->Tmg1 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg1 );
+
+ pConfiguration->Tmg2 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg2 );
+
+}
+
+
+VOID
+HalpCiaReportFatalError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error
+ detected by the CIA chipset. It is assumed that HalGetDisplayOwnership()
+ has been called prior to this function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ CIA_ERR CiaError;
+ CIA_STAT CiaStat;
+ CIA_SYN CiaSyn;
+ CIA_CONTROL CiaControl;
+ CIA_MEM_ERR0 MemErr0;
+ CIA_MEM_ERR1 MemErr1;
+ CIA_PCI_ERR0 PciErr0;
+ CIA_PCI_ERR1 PciErr1;
+ CIA_PCI_ERR2 PciErr2;
+ CIA_CPU_ERR0 CpuErr0;
+ CIA_CPU_ERR1 CpuErr1;
+
+ PUNCORRECTABLE_ERROR uncorr = NULL;
+ PCIA_UNCORRECTABLE_FRAME ciauncorr = NULL;
+ PEXTENDED_ERROR PExtErr;
+
+ //
+ // We will Build the uncorrectable error frame as we read
+ // the registers to report the error to the blue screen.
+ // We generate the extended error frame as we generate
+ // extended messages to print to the screen.
+ //
+
+ if(PUncorrectableError){
+ uncorr = (PUNCORRECTABLE_ERROR)
+ &PUncorrectableError->UncorrectableFrame;
+ ciauncorr = (PCIA_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+ if(uncorr){
+ uncorr->Flags.ProcessorInformationValid = 1;
+ HalpGetProcessorInfo(&uncorr->ReportingProcessor);
+ }
+
+ if(ciauncorr)
+ HalpBuildCiaConfigurationFrame(&ciauncorr->Configuration);
+ //
+ // Read the CIA Error register and decode its contents:
+ //
+
+ CiaError.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr
+ );
+
+ if(ciauncorr)
+ ciauncorr->CiaErr = CiaError.all ;
+
+ //
+ // Read the rest of the error registers and then unlock them by
+ // writing to CIA_ERR
+ //
+
+ CiaStat.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat
+ );
+
+
+ CiaSyn.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn
+ );
+
+
+ MemErr0.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0
+ );
+
+
+ MemErr1.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1
+ );
+
+
+ PciErr0.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0
+ );
+
+
+ PciErr1.PciAddress = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1
+ );
+
+ PciErr2.PciAddress = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2
+ );
+
+ CpuErr0.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr0
+ );
+
+
+ CpuErr1.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr1
+ );
+
+ CiaControl.all = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl);
+
+ if(ciauncorr){
+ ciauncorr->CiaStat = CiaStat.all;
+ ciauncorr->CiaSyn = CiaSyn.all;
+ ciauncorr->MemErr0 = MemErr0.all;
+ ciauncorr->MemErr1 = MemErr1.all;
+ ciauncorr->PciErr0 = PciErr0.all;
+ ciauncorr->PciErr1 = PciErr1.PciAddress;
+
+ ciauncorr->PciErr2 = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2
+ );
+ ciauncorr->CpuErr0 = CpuErr0.all;
+
+ ciauncorr->CpuErr1 = CpuErr1.all;
+
+ ciauncorr->ErrMask = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask
+ );
+
+ }
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all
+ );
+
+
+ sprintf( OutBuffer, "CIA_CTRL : %08x\n", CiaControl.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CIA_ERR : %08x\n", CiaError.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CIA_STAT : %08x\n", CiaStat.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CIA_SYN : %08x\n", CiaSyn.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "PCI_ERR0 : %08x\n", PciErr0.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "PCI_ERR1 : %08x\n", PciErr1.PciAddress );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "PCI_ERR2 : %08x\n", PciErr2.PciAddress );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CPU_ERR0 : %08x\n", CpuErr0.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CPU_ERR1 : %08x\n", CpuErr1.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "MEM_ERR0 : %08x\n", MemErr0.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "MEM_ERR1 : %08x\n", MemErr1.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ //
+ // If no valid error then no interpretation.
+ //
+
+ if ( CiaError.ErrValid == 0 ){
+
+ return; // No CIA error detected
+
+ }
+
+ //
+ // Interpret any detected errors:
+ //
+
+ if ( CiaError.UnCorErr == 1 ){
+
+ sprintf( OutBuffer,
+ "CIA Uncorrectable ECC error, Addr=%x%x, Cmd=%x\n",
+ CpuErr1.Addr34_32, // bits 34:32
+ CpuErr0.Addr, // bits 31:4
+ CpuErr1.Cmd
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.CpuPe == 1 ){
+
+ sprintf( OutBuffer,
+ "EV5 bus parity error, Addr=%x%x, Cmd=%x\n",
+ CpuErr1.Addr34_32, // bits 34:32
+ CpuErr0.Addr, // bits 31:4
+ CpuErr1.Cmd
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.MemNem == 1 ){
+
+ sprintf( OutBuffer,
+ "CIA Access to non-existent memory, Source=%s, Addr=%x%x\n",
+ MemErr1.MemPortSrc == 1 ? "DMA" : "CPU",
+ MemErr1.MemPortSrc == 1 ? 0 : MemErr1.Addr33_32,
+ MemErr1.MemPortSrc == 1 ? PciErr1.PciAddress : MemErr0.Addr31_4
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.PciSerr == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI bus SERR detected, Cmd=%x, Window=%d, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.PciPerr == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI bus Data Parity error, Cmd=%x, Window=%d, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.PciAddrPe == 1 ){
+
+ sprintf( OutBuffer,
+ "Pci bus Address Parity error, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.RcvdMasAbt == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI Master abort occurred, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.RcvdTarAbt == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI Target abort occurred, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.PaPteInv == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid Scatter/Gather PTE, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.FromWrtErr == 1 ){
+
+ sprintf( OutBuffer,
+ "Write to Flash ROM with FROM_WRT_EN clear"
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.IoaTimeout == 1){
+
+ sprintf( OutBuffer,
+ "PCI bus I/O timeout occurred, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+ }
+
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( "\n" );
+ HalDisplayString( OutBuffer );
+
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+
+
+ //
+ // Check for lost errors and output message if any occurred:
+ //
+
+ if ( (CiaError.all & CIA_ERR_LOST_MASK) != 0 ){
+
+ HalDisplayString("\nCIA Lost errors were detected\n\n");
+ }
+
+ return; // Fatal error detected
+}
+
+
+BOOLEAN
+HalpCiaMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ CIA_ERR CiaError;
+
+ //
+ // Read the CIA error register to determine the source of the
+ // error.
+ //
+
+ CiaError.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
+
+#if HALDBG
+
+ DbgPrint( "Cia Mchk: 0x%x\n", CiaError.all );
+
+#endif //HALDBG
+
+ //
+ // Check that an error is valid. If it is not this is a pretty
+ // weird fatal condition.
+ //
+
+ if( CiaError.ErrValid == 0 ){
+ DbgPrint( "Error reported but error valid = 0, CiaErr = 0x%x\n",
+ CiaError.all );
+ goto FatalError;
+ }
+
+ //
+ // Check for any uncorrectable error other than a master abort
+ // on a PCI transaction. Any of these other errors indicate a
+ // fatal condition.
+ //
+
+ if( (CiaError.UnCorErr == 1) || // Uncorrectable error
+ (CiaError.CpuPe == 1) || // Ev5 bus parity error
+ (CiaError.MemNem == 1) || // Nonexistent memory error
+ (CiaError.PciSerr == 1) || // PCI bus serr detected
+ (CiaError.PciPerr == 1) || // PCI bus perr detected
+ (CiaError.PciAddrPe == 1) || // PCI bus address parity error
+ (CiaError.RcvdTarAbt == 1) || // Pci Target Abort
+ (CiaError.PaPteInv == 1) || // Invalid Pte
+ (CiaError.FromWrtErr == 1) || // Invalid write to flash rom
+ (CiaError.IoaTimeout == 1) || // Io Timeout occurred
+ (CiaError.LostUnCorErr == 1) || // Lost uncorrectable error
+ (CiaError.LostCpuPe == 1) || // Lost Ev5 bus parity error
+ (CiaError.LostMemNem == 1) || // Lost Nonexistent memory error
+ (CiaError.LostPciPerr == 1) || // Lost PCI bus perr detected
+ (CiaError.LostPciAddrPe == 1) || // Lost PCI address parity error
+ (CiaError.LostRcvdMasAbt == 1) || // Lost Pci Master Abort
+ (CiaError.LostRcvdTarAbt == 1) || // Lost Pci Target Abort
+ (CiaError.LostPaPteInv == 1) || // Lost Invalid Pte
+ (CiaError.LostFromWrtErr == 1) || // Lost Invalid write to flash rom
+ (CiaError.LostIoaTimeout == 1) // Lost Io Timeout occurred
+ ){
+ DbgPrint( "Explicit fatal error, CiaErr = 0x%x\n",
+ CiaError.all );
+ goto FatalError;
+ }
+
+ //
+ // Check for a PCI configuration read error. The CIA experiences
+ // a master abort on a read to a non-existent PCI slot.
+ //
+
+ if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) ){
+
+ //
+ // So far, the error looks like a PCI configuration space read
+ // that accessed a device that does not exist. In order to fix
+ // this up we expect that the original faulting instruction must
+ // be a load with v0 as the destination register. Unfortunately,
+ // machine checks are not precise exceptions so we may have exectued
+ // many instructions since the faulting load. For EV5 a pair of
+ // memory barrier instructions following the load will stall the pipe
+ // waiting for load completion before the second memory barrier can
+ // be issued. Therefore, we expect the exception PC to point to either
+ // the load instruction of one of the two memory barriers. We will
+ // assume that if the exception pc is not an mb that instead it
+ // points to the load that machine checked. We must be careful to
+ // not reexectute the load.
+ //
+
+ ALPHA_INSTRUCTION FaultingInstruction;
+ BOOLEAN PreviousInstruction = FALSE;
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
+ if( FaultingInstruction.Memory.Opcode != MEMSPC_OP ){
+
+ //
+ // Exception pc does not point to a memory barrier, return
+ // to the instruction after the exception pc.
+ //
+
+ TrapFrame->Fir += 4;
+
+ }
+
+ //
+ // The error has matched all of our conditions. Fix it up by
+ // writing the value 0xffffffff into the destination of the load.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
+
+ //
+ // Clear the error condition in CIA_ERR.
+ //
+
+ CiaError.all = 0;
+ CiaError.RcvdMasAbt = 1;
+ CiaError.ErrValid = 1;
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all );
+
+ return TRUE;
+
+ } //end if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) )
+
+ DbgPrint( "Unexpected master abort\n" );
+
+//
+// The system is not well and cannot continue reliable execution.
+// Print some useful messages and return FALSE to indicate that the error
+// was not handled.
+//
+
+FatalError:
+
+ DbgPrint( "Handling fatal error\n" );
+
+ //
+ // Clear the error condition in the MCES register.
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ //
+ // Proceed to display the error.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+
+ HalpCiaReportFatalError();
+
+ return( FALSE );
+
+}
+
+BOOLEAN
+HalpTranslateSynToEcc(
+ PULONG Syndrome
+ )
+/*++
+
+Routine Description:
+
+ Translate a syndrome code to ECC error bit code.
+
+Arguments:
+
+ Syndrome - pointer to the syndrome.
+
+Return Value:
+
+ True if a data bit is in error. False otherwise.
+
+--*/
+{
+ static UCHAR SynToEccTable[0xff] = {0, };
+ static BOOLEAN SynToEccTableInitialized = FALSE;
+ ULONG Temp;
+
+ //
+ // Initialize the table.
+ //
+
+ if (!SynToEccTableInitialized) {
+
+ SynToEccTableInitialized = TRUE;
+
+ //
+ // Fill in the table.
+ //
+
+ SynToEccTable[0x01] = 0;
+ SynToEccTable[0x02] = 1;
+ SynToEccTable[0x04] = 2;
+ SynToEccTable[0x08] = 3;
+ SynToEccTable[0x10] = 4;
+ SynToEccTable[0x20] = 5;
+ SynToEccTable[0x40] = 6;
+ SynToEccTable[0x80] = 7;
+ SynToEccTable[0xce] = 0;
+ SynToEccTable[0xcb] = 1;
+ SynToEccTable[0xd3] = 2;
+ SynToEccTable[0xd5] = 3;
+ SynToEccTable[0xd6] = 4;
+ SynToEccTable[0xd9] = 5;
+ SynToEccTable[0xda] = 6;
+ SynToEccTable[0xdc] = 7;
+ SynToEccTable[0x23] = 8;
+ SynToEccTable[0x25] = 9;
+ SynToEccTable[0x26] = 10;
+ SynToEccTable[0x29] = 11;
+ SynToEccTable[0x2a] = 12;
+ SynToEccTable[0x2c] = 13;
+ SynToEccTable[0x31] = 14;
+ SynToEccTable[0x34] = 15;
+ SynToEccTable[0x0e] = 16;
+ SynToEccTable[0x0b] = 17;
+ SynToEccTable[0x13] = 18;
+ SynToEccTable[0x15] = 19;
+ SynToEccTable[0x16] = 20;
+ SynToEccTable[0x19] = 21;
+ SynToEccTable[0x1a] = 22;
+ SynToEccTable[0x1c] = 23;
+ SynToEccTable[0xe3] = 24;
+ SynToEccTable[0xe5] = 25;
+ SynToEccTable[0xe6] = 26;
+ SynToEccTable[0xe9] = 27;
+ SynToEccTable[0xea] = 28;
+ SynToEccTable[0xec] = 29;
+ SynToEccTable[0xf1] = 30;
+ SynToEccTable[0xf4] = 31;
+ SynToEccTable[0x4f] = 32;
+ SynToEccTable[0x4a] = 33;
+ SynToEccTable[0x52] = 34;
+ SynToEccTable[0x54] = 35;
+ SynToEccTable[0x57] = 36;
+ SynToEccTable[0x58] = 37;
+ SynToEccTable[0x5b] = 38;
+ SynToEccTable[0x5d] = 39;
+ SynToEccTable[0xa2] = 40;
+ SynToEccTable[0xa4] = 41;
+ SynToEccTable[0xa7] = 42;
+ SynToEccTable[0xa8] = 43;
+ SynToEccTable[0xab] = 44;
+ SynToEccTable[0xad] = 45;
+ SynToEccTable[0xb0] = 46;
+ SynToEccTable[0xb5] = 47;
+ SynToEccTable[0x8f] = 48;
+ SynToEccTable[0x8a] = 49;
+ SynToEccTable[0x92] = 50;
+ SynToEccTable[0x94] = 51;
+ SynToEccTable[0x97] = 52;
+ SynToEccTable[0x98] = 53;
+ SynToEccTable[0x9b] = 54;
+ SynToEccTable[0x9d] = 55;
+ SynToEccTable[0x62] = 56;
+ SynToEccTable[0x64] = 57;
+ SynToEccTable[0x67] = 58;
+ SynToEccTable[0x68] = 59;
+ SynToEccTable[0x6b] = 60;
+ SynToEccTable[0x6d] = 61;
+ SynToEccTable[0x70] = 62;
+ SynToEccTable[0x75] = 63;
+ }
+
+ //
+ // Tranlate the syndrome code.
+ //
+
+ Temp = *Syndrome;
+ *Syndrome = SynToEccTable[Temp];
+
+ //
+ // Is it a data bit or a check bit in error?
+ //
+
+ if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 ||
+ Temp == 0x10 || Temp == 0x20 || Temp == 0x40 || Temp == 0x80) {
+
+ return FALSE;
+
+ } else {
+
+ return TRUE;
+ }
+}
+
+
+
+VOID
+HalpCiaErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle a CIA correctable error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ static ERROR_FRAME Frame;
+ static CIA_CORRECTABLE_FRAME AlcorFrame;
+
+ ERROR_FRAME TempFrame;
+ PCORRECTABLE_ERROR CorrPtr;
+ PBOOLEAN ErrorlogBusy;
+ PULONG DispatchCode;
+ ULONG Syndrome;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+
+ CIA_ERR CiaError;
+ CIA_STAT CiaStat;
+ CIA_SYN CiaSyn;
+ CIA_MEM_ERR0 MemErr0;
+ CIA_MEM_ERR1 MemErr1;
+ CIA_PCI_ERR0 PciErr0;
+ CIA_PCI_ERR1 PciErr1;
+ CIA_PCI_ERR2 PciErr2;
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read/write. Read the error registers relevant
+ // to this error.
+ //
+
+ CiaError.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
+
+ //
+ // Check if an error is latched into the CIA.
+ //
+
+ if( CiaError.ErrValid == 0 ){
+
+#if HALDBG
+
+ DbgPrint( "Cia error interrupt without valid CIA error\n" );
+
+#endif //HALDBG
+
+ return;
+ }
+
+ //
+ // Check for the correctable error bit.
+ //
+
+ if( CiaError.CorErr == 0 ){
+
+#if HALDBG
+
+ DbgPrint( "Cia error interrupt without correctable error indicated\n" );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Real error, get the interrupt object.
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Increment the number of CIA correctable errors.
+ //
+
+ CiaCorrectedErrors += 1;
+
+ CiaStat.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat );
+
+ CiaSyn.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn );
+
+ MemErr0.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0 );
+
+ MemErr1.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1 );
+
+ PciErr0.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0 );
+
+ PciErr1.PciAddress = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1 );
+
+ PciErr2.PciAddress = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2 );
+
+
+ //
+ // Print a correctable error message to the debugger.
+ //
+
+#if HALDBG
+ DbgPrint( "CIA Correctable Error Number %d, state follows: \n",
+ CiaCorrectedErrors );
+ DbgPrint( "\tCIA_ERR : 0x%x\n", CiaError.all );
+ DbgPrint( "\tCIA_STAT: 0x%x\n", CiaStat.all );
+ DbgPrint( "\tCIA_SYN : 0x%x\n", CiaSyn.all );
+ DbgPrint( "\tCIA_MEM0: 0x%x\n", MemErr0.all );
+ DbgPrint( "\tCIA_MEM1: 0x%x\n", MemErr1.all );
+ DbgPrint( "\tPCI_ERR0: 0x%x\n", PciErr0.all );
+#endif //HALDBG
+
+ //
+ // Fill in the error frame information.
+ //
+
+ TempFrame.Signature = ERROR_FRAME_SIGNATURE;
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = CiaCorrectedErrors;
+ TempFrame.PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Check for lost error.
+ //
+
+ if( CiaError.LostCorErr ) {
+
+ //
+ // Since the error registers are locked from a previous error,
+ // we don't know where the error came from. Mark everything
+ // as UNIDENTIFIED.
+ //
+
+ CorrPtr->Flags.LostCorrectable = 1;
+ CorrPtr->Flags.LostAddressSpace = UNIDENTIFIED;
+ CorrPtr->Flags.LostMemoryErrorSource = UNIDENTIFIED;
+ }
+
+ //
+ // Set error bit error masks.
+ //
+
+ CorrPtr->Flags.ErrorBitMasksValid = 1;
+ Syndrome = CiaSyn.all;
+
+ if ( HalpTranslateSynToEcc(&Syndrome) )
+ CorrPtr->DataBitErrorMask = 1 << Syndrome;
+ else
+ CorrPtr->CheckBitErrorMask = 1 << Syndrome;
+
+ //
+ // Determine error type.
+ //
+ switch (CiaStat.DmSt) {
+
+ case CIA_IO_WRITE_ECC:
+
+ //
+ // I/O write ECC error occurred.
+ //
+
+ CorrPtr->Flags.AddressSpace = IO_SPACE;
+
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->ErrorInformation.IoError.Interface = PCIBus;
+ CorrPtr->ErrorInformation.IoError.BusNumber = 0;
+ CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress;
+ CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_WRITE;
+ break;
+
+ case CIA_DMA_READ_ECC:
+
+ CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+
+ //
+ // Where did the error come from?
+ //
+
+ if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from processor cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE;
+
+ //
+ // DMA read or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ;
+
+ } else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from system cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE;
+
+ //
+ // DMA read or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ;
+
+ } else {
+
+ //
+ // Correctable error comes from system memory.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
+
+ //
+ // DMA read or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_READ;
+ else
+ CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_READ;
+ }
+
+ break;
+
+ case CIA_DMA_WRITE_ECC:
+
+ CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+
+ //
+ // Where did the error come from?
+ //
+
+ if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from processor cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE;
+
+ //
+ // DMA write or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE;
+
+ } else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from system cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE;
+
+ //
+ // DMA write or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE;
+
+ } else {
+
+ //
+ // Correctable error comes from system memory.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
+
+ //
+ // DMA write or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_WRITE;
+ else
+ CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_WRITE;
+
+ //
+ //
+ }
+
+ break;
+
+ case CIA_IO_READ_ECC:
+
+ //
+ // I/O read ECC error occurred.
+ //
+
+ CorrPtr->Flags.AddressSpace = IO_SPACE;
+
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->ErrorInformation.IoError.Interface = PCIBus;
+ CorrPtr->ErrorInformation.IoError.BusNumber = 0;
+ CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress;
+ CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_READ;
+ break;
+
+ default:
+
+ //
+ // Something strange happened. Don't know where the error occurred.
+ //
+
+ CorrPtr->Flags.AddressSpace = UNIDENTIFIED;
+ break;
+ }
+
+ //
+ // Get the physical address where the error occurred.
+ //
+
+ CorrPtr->Flags.PhysicalAddressValid = 1;
+ CorrPtr->PhysicalAddress = (MemErr1.all & 0xff) << 32;
+ CorrPtr->PhysicalAddress |= MemErr0.all;
+
+ //
+ // Get bits 7:0 of the address from the PCI address.
+ //
+
+ CorrPtr->PhysicalAddress |= PciErr1.PciAddress & 0xff;
+
+ //
+ // Scrub the error if it's any type of memory error.
+ //
+
+ if ( CorrPtr->Flags.AddressSpace == MEMORY_SPACE &&
+ CorrPtr->Flags.PhysicalAddressValid )
+ CorrPtr->Flags.ScrubError = 1;
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ //
+
+ if (!*ErrorlogBusy) {
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read/write. Read the error registers relevant
+ // to this error.
+ //
+
+ AlcorFrame.CiaErr = CiaError.all;
+
+ AlcorFrame.CiaStat = CiaStat.all;
+
+ AlcorFrame.CiaSyn = CiaSyn.all;
+
+ AlcorFrame.MemErr0 = MemErr0.all;
+
+ AlcorFrame.MemErr1 = MemErr1.all;
+
+ AlcorFrame.PciErr0 = PciErr0.all;
+
+ AlcorFrame.PciErr1 = PciErr1.PciAddress;
+
+ AlcorFrame.PciErr2 = PciErr2.PciAddress;
+
+ //
+ // Read the CIA configuration registers for logging information.
+ //
+
+ AlcorFrame.Configuration.CiaRev =
+ READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS)
+ (CIA_GENERAL_CSRS_QVA))->CiaRevision );
+
+ AlcorFrame.Configuration.CiaCtrl =
+ READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS)
+ (CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ AlcorFrame.Configuration.Mcr =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mcr );
+
+ AlcorFrame.Configuration.Mba0 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba0 );
+
+ AlcorFrame.Configuration.Mba2 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba2 );
+
+ AlcorFrame.Configuration.Mba4 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba4 );
+
+ AlcorFrame.Configuration.Mba6 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba6 );
+
+ AlcorFrame.Configuration.Mba8 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba8 );
+
+ AlcorFrame.Configuration.MbaA =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->MbaA );
+
+ AlcorFrame.Configuration.MbaC =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->MbaC );
+
+ AlcorFrame.Configuration.MbaE =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->MbaE );
+
+ AlcorFrame.Configuration.Tmg0 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Tmg0 );
+
+ AlcorFrame.Configuration.Tmg1 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Tmg1 );
+
+ AlcorFrame.Configuration.Tmg2 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Tmg2 );
+
+ AlcorFrame.Configuration.CacheCnfg =
+ PCR->SecondLevelCacheSize;
+
+ //
+ // Set the raw system information.
+ //
+
+ CorrPtr->RawSystemInformationLength = sizeof(CIA_CORRECTABLE_FRAME);
+ CorrPtr->RawSystemInformation = &AlcorFrame;
+
+ //
+ // Set the raw processor information. Disregard at the moment.
+ //
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // Set reporting processor information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+
+ //
+ // Set system information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.SystemInformationValid = 0;
+
+ //
+ // Copy the information that we need to log.
+ //
+
+ RtlCopyMemory(&Frame,
+ &TempFrame,
+ sizeof(ERROR_FRAME));
+
+ //
+ // Put frame into ISR service context.
+ //
+
+ *(PERROR_FRAME *)InterruptObject->ServiceContext = &Frame;
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+
+ //
+ // Clear the corrected error status bit and return to continue
+ // execution.
+ //
+
+ CiaError.all = 0;
+ CiaError.CorErr = 1;
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halalpha/ciaio.s b/private/ntos/nthals/halalpha/ciaio.s
new file mode 100644
index 000000000..073a25ea6
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ciaio.s
@@ -0,0 +1,2820 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ciaio.s
+
+Abstract:
+
+ This module implements the I/O access routines for the CIA ASIC.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+
+Author:
+
+ Steve Brooks 1-Jul-1994
+ Joe Notarangelo 1-Jul-1994
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "cia.h"
+#include "halalpha.h"
+
+
+//
+// Superpage VAs
+//
+// The following constants are used to construct the physical addresses
+// used to access i/o space.
+//
+// assembler BUGBUG:
+//
+// The following values are hacks to get around the intelligent
+// Alpha assemblers. Instead of sign extending 16 bit quantities greater
+// than 32K-1, the assembler generates a ldah/lda pair to load exactly
+// the sixteen bit quantity specified, without sign extending.
+//
+// By specifying the quantity as a negative number, the assembler allows
+// a single lda instruction, with sign extension.
+//
+
+#define CIA_DENSE_MEM_SVA -0x37a0 // negative of 0xc860
+#define CIA_SPARSE_MEM_SVA -0x3800 // negative of 0xc800
+#define CIA_SPARSE_IO_SVA -0x37a8 // negative of 0xc858
+#define CIA_PCI_CONFIG_SVA -0x3790 // negative of 0xc870
+#define CIA_REGISTER_SVA -0x3790 // negative of 0xc870
+#define CIA_PCI_INTACK_SVA -0x378e // negative of 0xc872
+
+
+ SBTTL( "Read byte from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, 3, t3 // capture byte offset
+ bic a0, 3, a0 // clear byte offset
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ bis t0, a0, t0 // 0xffff fc86 xxxx xxxx
+ mb // ensure all writes are visible
+ ldl v0, 0(t0) // read from dense space
+ extbl v0, t3, v0 // extract appropriate byte
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_UCHAR
+
+
+
+ SBTTL( "Read byte from PCI sparse i/o" )
+//++
+//
+// UCHAR
+// READ_PORT_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff c858 0000
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_UCHAR
+
+
+ SBTTL( "Read short from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a short location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory short to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI memory.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // set size to short
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extwl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, 3, t3 // capture byte offset
+ bic a0, 3, a0 // clear byte offset
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ bis t0, a0, t0 // 0xffff fc86 xxxx xxxx
+ ldl v0, 0(t0) // read from dense space
+ extwl v0, t3, v0 // extract appropriate word
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_USHORT
+
+
+ SBTTL( "Read short from PCI sparse I/O" )
+//++
+//
+// UCHAR
+// READ_PORT_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a short location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the i/o short to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI I/O.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // set size to short
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extwl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_USHORT
+
+
+ SBTTL( "Read long from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a long location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory long to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI memory.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // set size to long
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ bis t0, a0, t0 // 0xffff fc86 xxxx xxxx
+ ldl v0, 0(t0) // read from dense space
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_ULONG
+
+
+ SBTTL( "Read long from PCI sparse I/O" )
+//++
+//
+// UCHAR
+// READ_PORT_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a long location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the i/o long to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI I/O.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // set size to short
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_ULONG
+
+
+ SBTTL( "Write byte to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ insbl a1, t3, v0 // insert to proper byte lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear byte offset
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ bis t0, a0, t0 // 0xffff fc86 xxxx xxxx
+
+ ldl t1, (t0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+
+ insbl a1, t3, a1 // insert to appropriate byte lane
+ bis a1, t1, a1 // merge byte in result
+ stl a1, (t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write byte to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_UCHAR(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+
+ insbl a1, t3, v0 // insert to proper byte lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_UCHAR
+
+
+ SBTTL( "Write short to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory short to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // set size to short
+
+ inswl a1, t3, v0 // insert to proper short lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear byte offset
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ bis t0, a0, t0 // 0xffff fc86 xxxx xxxx
+ ldl t1, (t0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, a1 // insert to appropriate short lane
+ bis a1, t1, a1 // merge in result
+ stl a1, (t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write short to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_USHORT(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // set size to short
+
+ inswl a1, t3, v0 // insert to proper short lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_USHORT
+
+
+
+ SBTTL( "Write long to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a long to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory long to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // set size to long
+
+ stl a1, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ bis t0, a0, t0 // 0xffff fc86 xxxx xxxx
+ stl a1, 0(t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_ULONG
+
+
+ SBTTL( "Write long to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_ULONG(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a long to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O long to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // set size to long
+
+ stl a1, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_ULONG
+
+
+ SBTTL( "Write CIA Register" )
+//++
+//
+// VOID
+// WRITE_CIA_REGISTER(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Write a CIA control register.
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Value(a1) - Longword value to be written to the control register.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. Since the physical address of the CIA CSRS exceed the 34 bit
+// capacity of the QVAs, the QVA values of the CIA CSRS specify
+// the offset of the QVAs from the CIA CSR base address (87.4000.0000)
+//--
+
+ LEAF_ENTRY(WRITE_CIA_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_GRU_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, 5, t0 //
+ lda t4, CIA_REGISTER_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ or t0, t4, t0 // superpage mode
+ stl a1, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end WRITE_CIA_REGISTER
+
+
+ SBTTL( "Read Control Register" )
+//++
+//
+// ULONG
+// READ_CIA_REGISTER(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Read a CIA Control register
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Return Value:
+//
+// v0 - Return the value read from the control register.
+//
+//--
+
+ LEAF_ENTRY(READ_CIA_REGISTER)
+
+ ALTERNATE_ENTRY(READ_GRU_REGISTER)
+
+//
+// Generate the superpage address of the requested CIA register.
+//
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 20f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, 5, t0 //
+ lda t4, CIA_REGISTER_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ or t0, t4, t0 // superpage mode
+
+//
+// Read the CIA revision saved in a global variable.
+//
+
+ lda t1, HalpCiaRevision // get revision id global address
+ ldl t1, 0(t1) // get revision id
+ bne t1, 10f // if ne, not pass 1 CIA
+
+//
+// Pass 1 CIA required the following work-around to avoid IBOX timeout
+// errors.
+//
+
+ ldil t5, 100 // iterations to wait for istream
+ // prefetches to settle
+
+1:
+ subl t5, 1, t5 // decrement wait count
+ bgt t5, 2f // continue wait until count = 0
+
+ mb // wait for write buffer
+ ldl v0, (t0) // read the register
+ bis v0, zero, v0 // wait for read to complete
+
+2:
+ bgt t5, 1b // if gt, still waiting
+
+ ret zero, (ra) // return
+
+//
+// Perform the read of the requested CIA register and return.
+//
+
+10:
+ ldl v0, (t0) // read the register
+
+ ret zero, (ra) // return
+
+//
+// The requested CIA register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+20: // flag bad QVAs
+ BREAK_DEBUG_STOP // take a breakpoint
+
+ ret zero, (ra) // return
+
+ .end READ_CIA_REGISTER
+
+
+ SBTTL( "Read Buffer from Port Space in Uchars")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push the write off the chip
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t4, 28, t4 // 0xffff fc85 8000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push write off the chip
+ addl a1, 4, a1 // increment buffer
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ ldil t8, 1 // DENSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ ldil t8, 0 // SPARSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+ beq t8, 11f // if not DENSE goto 11f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 12f
+11:
+ ldl v0, 0(t0) // get the longword
+12:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ beq t8, 51f // if not DENSE goto 51f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 52f
+51:
+ ldl v0, 0(t0) // get the longword
+52:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+ beq t8, 81f // if not DENSE goto 81f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 82f
+81:
+ ldl v0, 0(t0) // get the longword
+82:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ beq t8, 121f // if not DENSE goto 121f
+ bic t0, 3, t9 // clear bits <1:0> of src
+ ldl v0, 0(t9) // get the longword
+ br zero, 122f
+121:
+ ldl v0, 0(t0) // get the longword
+122:
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ ldil t7, 1 // DENSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ lda t0, CIA_DENSE_MEM_SVA(zero) // 0xffff ffff ffff c860
+ sll t0, 28, t0 // 0xffff fc86 0000 0000
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ ldil t7, 0 // SPARSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, CIA_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 11f // if not DENSE goto 11f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 12f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+11:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+
+12:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 51f // if not DENSE goto 51f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 52f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+51:
+ stl t1, 0(t0) // store to buffer
+
+52:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 81f // if not DENSE goto 81f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 82f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+81:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+
+82:
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 121f // if not DENSE goto 122f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 122f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+121:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+
+122:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the QVA for the CIA Configuration Cycle Type register
+//
+// Physical address is 87 4000 0480. The QVA specifies the offset from
+// the base of the CIA CSRS (87.4000.0000) since the physical address of
+// the CSRS exceeds the capacity of a QVA.
+//
+
+#define CIA_CFG_QVA (0xba000024)
+#define CIA_ERR_QVA (0xba000410)
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved ConfigurationAddress
+CfgA1: .space 8 // saved ConfigurationData/CycleType
+CfgA2: .space 8 // saved ConfigurationCycleType
+CfgFrameLength:
+
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the configuration cycle type (a1) into the CIA CFG register
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+
+ ldil a0, CIA_CFG_QVA // offset of CIA CFG register
+ bsr ra, WRITE_CIA_REGISTER // write the cycle type
+
+//
+// Set the flag indicating that a PCI master abort may be expected by
+// the machine check handler.
+//
+ lda t0, HalpMasterAbortExpected // get address of flag
+ bis zero, 1, t1 // get a non-zero flag value
+ DISABLE_INTERRUPTS // sequence cannot be interrupted
+ stl t1, 0(t0) // store the non-zero flag
+ mb // order the write
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, CIA_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte enables
+
+ .set noreorder // cannot reorder these instructions
+
+ ldl v0, (t0) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+ extbl v0, t3, v0 // return byte from requested lane
+
+ .set reorder // reordering can begin again
+
+//
+// If this is not a pass 1 CIA then skip the work-around code.
+//
+
+ lda t1, HalpCiaRevision // get address of CIA revision
+ ldl t1, 0(t1) // load CIA revision
+ bne t1, 10f // if ne, not pass 1
+
+//
+// CIA Pass 1 will not machine check if no device exists. Instead we must
+// check the CIA error register that indicates a master abort occurred.
+//
+
+ bis v0, zero, t10 // save v0, special calling std
+
+ ldil a0, CIA_ERR_QVA // offset of CIA_ERR register
+ bsr ra, READ_CIA_REGISTER // read error register
+
+ srl v0, 31, t0 // get error valid bit
+ bis t10, zero, v0 // restore read value
+ blbc t0, 10f // if lbc, no error use read data
+
+ ldil a0, CIA_ERR_QVA // offset of CIA_ERR register
+ ldil a1, -1 // clear all bits mask
+ bsr ra, WRITE_CIA_REGISTER // clear pending errors
+
+ ldil v0, -1 // show no device present
+ extbl v0, 0, v0 // return 0xff
+
+//
+// Set the flag indicating that a PCI master abort is not expected.
+//
+
+10:
+ lda t0, HalpMasterAbortExpected // get address of flag
+ stl zero, 0(t0) // clear flag
+ ENABLE_INTERRUPTS // re-enable interrupts
+
+//
+// Restore the frame and return.
+//
+
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write an unsigned byte to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the configuration cycle type to the CIA CFG register
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+
+ bis a2, a2, a1 // put the cycle type in a1
+ ldil a0, CIA_CFG_QVA // offset of CIA CFG register
+ bsr ra, WRITE_CIA_REGISTER // write cycle type to CFG
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, CIA_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t0) // write the configuration byte
+ mb // synchronize
+
+10: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a short from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the configuration cycle type (in a1) into the CIA CFG register
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+
+ ldil a0, CIA_CFG_QVA // offset of CFG register
+ bsr ra, WRITE_CIA_REGISTER // write cycle type to CFG register
+
+//
+// Set the flag indicating that a PCI master abort may be expected by
+// the machine check handler.
+//
+ lda t0, HalpMasterAbortExpected // get address of flag
+ bis zero, 1, t1 // get a non-zero flag value
+ DISABLE_INTERRUPTS // sequence cannot be interrupted
+ stl t1, 0(t0) // store the non-zero flag
+ mb // order the write
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, CIA_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ .set noreorder // cannot reorder these instructions
+
+ ldl v0, (t0) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+ extwl v0, t3, v0 // return word from requested lanes
+
+ .set reorder // reordering can begin again
+
+//
+// If this is not a pass 1 CIA then skip the work-around code.
+//
+
+ lda t1, HalpCiaRevision // get address of CIA revision
+ ldl t1, 0(t1) // load CIA revision
+ bne t1, 10f // if ne, not pass 1
+
+//
+// CIA Pass 1 will not machine check if no device exists. Instead we must check
+// the CIA error register that indicates a master abort occurred.
+//
+
+ bis v0, zero, t10 // save v0, special calling std
+
+ ldil a0, CIA_ERR_QVA // offset of CIA_ERR register
+ bsr ra, READ_CIA_REGISTER // read error register
+
+ srl v0, 31, t0 // get error valid bit
+ bis t10, zero, v0 // restore read value
+ blbc t0, 10f // if lbc, no error use read data
+
+ ldil a0, CIA_ERR_QVA // offset of CIA_ERR register
+ ldil a1, -1 // clear all bits mask
+ bsr ra, WRITE_CIA_REGISTER // clear pending errors
+
+ ldil v0, -1 // show no device present
+ extwl v0, 0, v0 // return 0xffff
+
+//
+// Set the flag indicating that a PCI master abort is not expected.
+//
+
+10:
+ lda t0, HalpMasterAbortExpected // get address of flag
+ stl zero, 0(t0) // clear flag
+ ENABLE_INTERRUPTS // re-enable interrupts
+
+//
+// Restore the frame and return.
+//
+
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// USHORT ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the configuration cycle type (a2) into the CFG register
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+
+ bis a2, a2, a1 // put the cycle type in a1
+ ldil a0, CIA_CFG_QVA // offset of CFG register
+ bsr ra, WRITE_CIA_REGISTER // write config type to CFG
+
+//
+// Perform the write to configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, CIA_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1, t3, t4 // put data to appropriate lane
+ stl t4, (t0) // read the longword
+ mb // synchronize
+10: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the configuration cycle type (a1) to the CIA CFG register
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+
+ ldil a0, CIA_CFG_QVA // offset of CIA CFG register
+ bsr ra, WRITE_CIA_REGISTER // write cycle type to CFG
+
+//
+// Set the flag indicating that a PCI master abort may be expected by
+// the machine check handler.
+//
+ lda t0, HalpMasterAbortExpected // get address of flag
+ bis zero, 1, t1 // get a non-zero flag value
+ DISABLE_INTERRUPTS // sequence cannot be interrupted
+ stl t1, 0(t0) // store the non-zero flag
+ mb // order the write
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, CIA_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ .set noreorder // cannot reorder these instructions
+
+ ldl v0, (t0) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+
+ .set reorder // reordering can begin again
+
+//
+// If this is not a pass 1 CIA then skip the work-around code.
+//
+
+ lda t1, HalpCiaRevision // get address of CIA revision
+ ldl t1, 0(t1) // load CIA revision
+ bne t1, 10f // if ne, not pass 1
+
+//
+// CIA Pass 1 will not machine check if no device exists. Instead we must check
+// the CIA error register that indicates a master abort occurred.
+//
+
+ bis v0, zero, t10 // save v0, special calling std
+
+ ldil a0, CIA_ERR_QVA // offset of CIA_ERR register
+ bsr ra, READ_CIA_REGISTER // read error register
+
+ srl v0, 31, t0 // get error valid bit
+ bis t10, zero, v0 // restore read value
+ blbc t0, 10f // if lbc, no error use read data
+
+ ldil a0, CIA_ERR_QVA // offset of CIA_ERR register
+ ldil a1, -1 // clear all bits mask
+ bsr ra, WRITE_CIA_REGISTER // clear pending errors
+
+ ldil v0, -1 // show no device present
+
+//
+// Set the flag indicating that a PCI master abort is not expected.
+//
+
+10:
+ lda t0, HalpMasterAbortExpected // get address of flag
+ stl zero, 0(t0) // clear flag
+ ENABLE_INTERRUPTS // re-enable interrupts
+
+//
+// Restore the frame and return.
+//
+
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the configuration cycle type to the CIA CFG register
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+
+ ldil a0, CIA_CFG_QVA // offset of CIA CFG register
+ bis a2, a2, a1 // cycle type in a1
+ bsr ra, WRITE_CIA_REGISTER // write cycle type to CFG
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, CIA_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c870
+ sll t4, 28, t4 // 0xffff fc87 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // synchronize
+10: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
+
+
+//++
+//
+// ULONG
+// INTERRUPT_ACKNOWLEDGE(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Perform an interrupt acknowledge cycle on the PCI bus.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// (v0) Returns the vector returned by the interrupt acknowledge
+// read.
+//
+//--
+
+ LEAF_ENTRY( INTERRUPT_ACKNOWLEDGE )
+
+ lda t0, CIA_PCI_INTACK_SVA(zero) // 0xffff ffff ffff c872
+ sll t0, 28, t0 // 0xffff fc87 2000 0000
+
+ ldl v0, 0(t0) // perform intack, get vector
+
+ ret zero, (ra) // return
+
+ .end INTERRUPT_ACKNOWLEDGE
+
+
+//++
+//
+// VOID
+// CIA_INVALIDATE_TLB(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Invalidate the TLB for the CIA scatter/gather.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+//jnfix - big warnings - this is a special work-around for CIA invalidate bug
+//jnfix - the 3rd DMA window is set up so that by convention with this code
+//jnfix - offset 0x10 within the firware PAL is overwritten
+
+#define CIA_TBIA_SVA -0x378a // negative of 0xc876
+#define CIA_DIAG_SVA -0x3794 // negative of 0xc86c
+
+ LEAF_ENTRY( CIA_INVALIDATE_TLB )
+
+ ldil t0, 0x100 // get stall count
+
+ lda t1, CIA_TBIA_SVA(zero) // 0xffff ffff ffff c876
+ sll t1, 28, t1 // 0xffff fc87 6000 0000
+ lda t1, 0x100(t1) // 0xffff fc87 6000 0100
+
+ lda t2, CIA_DIAG_SVA(zero) // 0xffff ffff ffff c86c
+ sll t2, 28, t2 // 0xffff fc86 c000 0000
+ lda t2, 0x10(t2) // 0xffff fc86 c000 0010
+
+ lda t3, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t3, 28, t3 // 0xffff fc85 8000 0000
+ lda t4, 0x70(zero) // get port 0x70
+ sll t4, 5, t4 // shift into position
+ bis t3, t4, t3 // merge in port address
+
+ ldil t4, 0x3 // get tlb invalidate value
+
+ DISABLE_INTERRUPTS // sequence cannot be interrupted
+
+10:
+ subq t0, 1, t0 // decrement stall count
+ bgt t0, 20f // if gt, continue stall
+
+ mb // clear write buffer
+
+ stl zero, 0(t3) // do i/o write
+ wmb // issue wmb
+
+ stl zero, 0(t2) // issue diagnostic write
+ wmb // issue wmb
+
+ stl t4, 0(t1) // issue invalidate
+ mb // flush write buffer
+
+20:
+ bgt t0, 10b // continue stall loop
+
+ ENABLE_INTERRUPTS // re-enable interrupts
+
+ ret zero, (ra) // return
+
+ .end CIA_INVALIDATE_TLB
+
diff --git a/private/ntos/nthals/halalpha/ciamapio.c b/private/ntos/nthals/halalpha/ciamapio.c
new file mode 100644
index 000000000..6174c7ba0
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ciamapio.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ciamapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on CIA-based systems.
+
+Author:
+
+ Joe Notarangelo 30-Jun-1994
+ Steve Brooks 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "isaaddr.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpPciIrQva;
+PVOID HalpPciImrQva;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a Alcor system using
+ the Quasi VA mechanism.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( CIA_PCI_SPARSE_IO_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( CIA_PCI_INTACK_PHYSICAL );
+
+ //
+ // Map CMOS RAM address.
+ //
+
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halalpha/cmos8k.c b/private/ntos/nthals/halalpha/cmos8k.c
new file mode 100644
index 000000000..6de80feb1
--- /dev/null
+++ b/private/ntos/nthals/halalpha/cmos8k.c
@@ -0,0 +1,246 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ xxnvram.c
+
+Abstract:
+
+ This module implements the device-specific routines necessary to
+ Read and Write the Non Volatile RAM containing the system environment
+ variables. The routines implemented here are:
+
+ HalpReadNVRamBuffer() - copy data from NVRAM into memory
+ HalpWriteNVRamBuffer() - write memory data to NVRAM
+ HalpCopyNVRamBuffer() - move data within the NVRAM
+
+Author:
+
+ Steve Brooks 5-Oct 93
+
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "cmos8k.h"
+
+#include "arccodes.h"
+
+//
+// Local function prototypes.
+//
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ );
+
+#ifdef AXP_FIRMWARE
+
+#pragma alloc_text(DISTEXT, HalpReadNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpWriteNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpCopyNVRamBuffer )
+
+#endif
+
+
+//
+//
+//
+ARC_STATUS HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Reads data from the NVRam into main memory
+
+Arguments:
+
+ DataPtr - Pointer to memory location to receive data
+ NvRamPtr - Pointer (qva) to NVRam location to read data from
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+{
+ ULONG PageSelect, ByteSelect;
+
+ PageSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ while ( Length -- )
+ {
+ *DataPtr++ = READ_CONFIG_RAM_DATA(NvRamPtr);
+ NvRamPtr ++;
+
+ ByteSelect = (ByteSelect + 1) & CONFIG_RAM_BYTE_MASK;
+ if (ByteSelect == 0)
+ {
+ PageSelect++;
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ }
+ }
+
+ return(ESUCCESS);
+}
+
+//
+//
+//
+ARC_STATUS HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Writes data from memory into the NVRam
+
+Arguments:
+
+ NvRamPtr - Pointer (qva) to NVRam location to write data into
+ DataPtr - Pointer to memory location of data to be written
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+{
+ ULONG PageSelect, ByteSelect;
+
+ PageSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ while ( Length -- )
+ {
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, *DataPtr);
+ NvRamPtr ++;
+ DataPtr ++;
+
+ ByteSelect = (ByteSelect + 1) & CONFIG_RAM_BYTE_MASK;
+ if (ByteSelect == 0)
+ {
+ PageSelect++;
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ }
+ }
+
+ return(ESUCCESS);
+}
+
+//
+//
+//
+ARC_STATUS HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length )
+/*++
+
+Routine Description:
+
+ This routine copies data between two locations within the NVRam. It is
+ the callers responsibility to assure that the destination region does not
+ overlap the src region i.e. if the regions overlap, NvSrcPtr > NvDestPtr.
+
+Arguments:
+
+ NvDestPtr - Pointer (qva) to NVRam location to write data into
+ NvSrcPtr - Pointer (qva) to NVRam location of data to copy
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+
+{
+ ULONG PageSelect0, ByteSelect0; // Src Pointer Page & offset
+ ULONG PageSelect1, ByteSelect1; // Dest Pointer Page & offset
+
+
+ PageSelect0 = (NvSrcPtr - (PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect0 = (NvSrcPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ PageSelect1 = (NvDestPtr-(PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect1 = (NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect0);
+ while ( Length -- )
+ {
+ UCHAR AChar;
+
+ //
+ // Check the Page select for the src pointer, and write the
+ // select register if necessary:
+ //
+ if (ByteSelect0 == 0)
+ {
+ PageSelect0++;
+ }
+ if ( PageSelect0 != PageSelect1 )
+ {
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect0);
+ }
+
+ AChar = READ_CONFIG_RAM_DATA(NvSrcPtr);
+ ByteSelect0 = (ByteSelect0 + 1) & CONFIG_RAM_BYTE_MASK;
+
+ //
+ // Check the page select for the dest pointer, and write
+ // the select register if necessary:
+ //
+ if (ByteSelect1 == 0)
+ {
+ PageSelect1++;
+ }
+ if ( PageSelect1 != PageSelect0 )
+ {
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect1);
+ }
+
+ WRITE_CONFIG_RAM_DATA(NvDestPtr, AChar);
+ ByteSelect1 = (ByteSelect1 + 1) & CONFIG_RAM_BYTE_MASK;
+
+ NvSrcPtr ++;
+ NvDestPtr ++;
+ }
+
+ return(ESUCCESS);
+}
diff --git a/private/ntos/nthals/halalpha/cmos8k.h b/private/ntos/nthals/halalpha/cmos8k.h
new file mode 100644
index 000000000..192730a32
--- /dev/null
+++ b/private/ntos/nthals/halalpha/cmos8k.h
@@ -0,0 +1,32 @@
+//
+// Non-volatile ram layout.
+//
+
+//
+// The value of HalpCMOSRamBase must be set at initialization
+//
+
+#define CONFIG_RAM_PAGE_SELECT ((PUCHAR)HalpCMOSRamBase + 0x0400)
+#define CONFIG_RAM_PAGE_COUNT 32
+#define CONFIG_RAM_PAGE_SIZE 256
+#define CONFIG_RAM_PAGE_MASK ((CONFIG_RAM_PAGE_COUNT - 1) << 8)
+#define CONFIG_RAM_PAGE_SHIFT 8
+#define CONFIG_RAM_BYTE_MASK (CONFIG_RAM_PAGE_SIZE - 1)
+
+
+// To address any byte of the CMOS 8K configuration RAM, the PAGE select
+// address bits from from I/O register at CONFIG_RAM_PAGE_SELECT are
+// OR'd with the lower address bits. Use the following macro to write
+// the page select register:
+
+#define WRITE_CONFIG_RAM_PAGE_SELECT(page) \
+ WRITE_PORT_UCHAR((PUCHAR)CONFIG_RAM_PAGE_SELECT, \
+ (UCHAR)(page & (CONFIG_RAM_PAGE_COUNT - 1)))
+
+#define WRITE_CONFIG_RAM_DATA(boffset,data) \
+ WRITE_PORT_UCHAR((PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ ((ULONG)boffset & CONFIG_RAM_BYTE_MASK)), (data & 0xff))
+
+#define READ_CONFIG_RAM_DATA(boffset) \
+ READ_PORT_UCHAR((PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ ((ULONG)boffset & CONFIG_RAM_BYTE_MASK)))
diff --git a/private/ntos/nthals/halalpha/devintr.s b/private/ntos/nthals/halalpha/devintr.s
new file mode 100644
index 000000000..63c17df5a
--- /dev/null
+++ b/private/ntos/nthals/halalpha/devintr.s
@@ -0,0 +1,71 @@
+// TITLE("First Level Device Interrupt Handlers")
+//++
+//
+// Copyright (c) 1994 Digital Equipment Corporation
+//
+// Module Name:
+//
+// devintr.s
+//
+// Abstract:
+//
+// This module implements first level device interrupt handlers for
+// systems that need to capture the trap frame for interrupt handling.
+//
+// Author:
+//
+// Joe Notarangelo 19-Sep-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halalpha.h"
+
+ SBTTL("Device Interrupt")
+//++
+//
+// VOID
+// HalpDeviceInterrupt(
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of a device interrupt.
+// The function is responsible for capturing the trap frame and calling
+// the system-specific device interrupt dispatcher.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpDeviceDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// Sable interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpDeviceInterrupt)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpDeviceDispatch // dispatch the interrupt
+
+ ret zero, (ra) // will never get here
+
+ .end HalpDeviceInterrupt
+
diff --git a/private/ntos/nthals/halalpha/ebsgdma.c b/private/ntos/nthals/halalpha/ebsgdma.c
new file mode 100644
index 000000000..e50fe05bb
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ebsgdma.c
@@ -0,0 +1,2307 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebsgdma.c
+
+Abstract:
+
+ This module contains the hardware dependent routines to support
+ Io Adapters, Map Registers, and Common buffers for Scatter/Gather
+ Eisa/Isa bus Alpha AXP systems. The systems supported must include
+ support for 2 scatter/gather windows. Originally, this module will
+ support APECS- and LCA-based systems.
+
+Author:
+
+ Joe Notarangelo 11-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen (DEC) 01-Nov-1993
+ Forced scatter/gather tables to be aligned with table size
+
+ Joe Notarangelo 24-Nov-1993
+ Do not program DMA controllers for ISA masters in IoMapTransfer and
+ IoFlushAdapterBuffers. Previous code did so if the device was an
+ Isa device without regard to whether or not it was a master device.
+
+ Joe Notarangelo 02-Feb-1994
+ Various bug fixes. Don't adjust mapRegister in IoMapTransfer and
+ IoFlushAdapterBuffers. Fix alignment adjustment code for Isa
+ machines. Initialize map registers to zero. Initialize bitmap
+ for map allocations by calling RtlClearAllBits. Add debugging
+ prints to fit new module haldebug.c
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+//
+// There are 2 map register adapters that are created to control access
+// to each of the 2 mapping windows that exist for APECS and LCA.
+//
+// The first adapter (IsaMapAdapter) controls access to the first mapping
+// windows which maps 8MB : 16MB-1 in bus space. The window is chosen
+// to be as large as possible and must be below 16MB to support ISA
+// bus masters and the standard EISA/ISA dma controllers.
+//
+// The second adapter (MasterMapAdapter) controls access to the second
+// mapping windows which maps a large region in bus space that may
+// begin above 16MB. This window is used for bus masters that are not
+// constrained by the ISA 24-bit limit.
+//
+
+PMAP_REGISTER_ADAPTER HalpIsaMapAdapter = NULL;
+PMAP_REGISTER_ADAPTER HalpMasterMapAdapter = NULL;
+
+//
+// Pointer to superpage address memory for map registers.
+//
+
+PTRANSLATION_ENTRY HalpIsaMapRegisterBase = NULL;
+PTRANSLATION_ENTRY HalpMasterMapRegisterBase = NULL;
+
+//
+// Control structures for each of the map register windows.
+//
+
+WINDOW_CONTROL_REGISTERS HalpIsaWindowControl;
+WINDOW_CONTROL_REGISTERS HalpMasterWindowControl;
+
+
+
+//
+// Local function prototypes.
+//
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+PMAP_REGISTER_ADAPTER
+HalpAllocateMapAdapter(
+ IN PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ IN HAL_ADAPTER_TYPE AdapterType,
+ IN PTRANSLATION_ENTRY MapRegisterBase
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ VOID
+ );
+
+BOOLEAN
+HalpAllocateMapRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG NumberOfMapRegisters,
+ IN BOOLEAN MapAdapterLocked
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations.
+ Specifically, this routine allocates the physical pages to be used
+ to contain the scatter/gather entries for all DMA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE is returned.
+
+--*/
+
+{
+ ULONG Allocated;
+ ULONG ByteSize;
+ ULONG MaxPhysicalAddress;
+
+ //
+ // Initialize the window control structures for each of the 2
+ // DMA windows.
+ //
+
+ INITIALIZE_ISA_DMA_CONTROL( &HalpIsaWindowControl );
+ INITIALIZE_MASTER_DMA_CONTROL( &HalpMasterWindowControl );
+
+ //
+ // Insure that the maximum address allocated will guarantee that the
+ // entirety of each allocation can be accessed via the 32-bit superpage.
+ //
+
+ MaxPhysicalAddress = __1GB - 1;
+
+ //
+ // Allocate the pages to contain the scatter/gather entries for the
+ // ISA DMA region (logical address range 8MB: 16MB-1).
+ //
+
+ ByteSize = ((HalpIsaWindowControl.WindowSize / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)) + PAGE_SIZE-1;
+
+ //
+ // Memory allocation for the Isa scatter/gather table will always
+ // align on a 8K boundry.
+ //
+
+ Allocated = HalpAllocPhysicalMemory( LoaderBlock,
+ MaxPhysicalAddress,
+ ByteSize >> PAGE_SHIFT,
+ FALSE );
+
+ ASSERT( Allocated != 0 );
+
+ HalpIsaMapRegisterBase = (PTRANSLATION_ENTRY)(Allocated | KSEG0_BASE);
+
+ RtlZeroMemory( HalpIsaMapRegisterBase,
+ (ByteSize >> PAGE_SHIFT) << PAGE_SHIFT );
+
+ //
+ // Allocate the pages to contain the scatter/gather entries for the
+ // bus master DMA region. Allocation of scatter/gather tables MUST
+ // be aligned based on the size of the scatter/gather table (16k).
+ //
+
+ ByteSize = ((HalpMasterWindowControl.WindowSize / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)) + PAGE_SIZE-1;
+
+ //
+ // Allocated on an aligned 64k boundry will ensure table alignment
+ // on a 16K boundry for a 16MB window size.
+ //
+
+ Allocated = HalpAllocPhysicalMemory( LoaderBlock,
+ MaxPhysicalAddress,
+ ByteSize >> PAGE_SHIFT,
+ TRUE );
+
+ ASSERT( Allocated != 0 );
+
+ HalpMasterMapRegisterBase = (PTRANSLATION_ENTRY)(Allocated | KSEG0_BASE);
+
+ RtlZeroMemory( HalpMasterMapRegisterBase,
+ (ByteSize >> PAGE_SHIFT) << PAGE_SHIFT );
+
+ //
+ // Perform any Eisa/Isa initialization.
+ //
+
+ HalpEisaInitializeDma();
+
+ //
+ // Program the DMA windows to reflect the translations.
+ //
+
+ INITIALIZE_DMA_WINDOW( &HalpMasterWindowControl,
+ (PVOID)( (ULONG)HalpMasterMapRegisterBase &
+ ~KSEG0_BASE ) );
+
+ INITIALIZE_DMA_WINDOW( &HalpIsaWindowControl,
+ (PVOID)( (ULONG)HalpIsaMapRegisterBase &
+ ~KSEG0_BASE ) );
+
+ return TRUE;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Eisa/Isa bus types and all master
+ devices are supported for the system.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ ULONG MaximumMapRegistersPerChannel;
+ PADAPTER_OBJECT adapterObject;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA PciBusData;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // If the device is not a bus master, then it must be an ISA, EISA
+ // or PCI device on hardware bus 0. PCI devices on hardware busses
+ // other than 0 cannot support slave DMA devices because the DMAC
+ // needed to support slave DMA is part of the ISA/EISA bridge, (which
+ // is located on h/w bus 0).
+ //
+
+ if( DeviceDescription->Master != TRUE ){
+
+ //
+ // This device requires slave DMA h/w support. Determine which
+ // type of device it is.
+ //
+
+ switch( DeviceDescription->InterfaceType ){
+
+ case Isa:
+ case Eisa:
+
+ //
+ // The ISA/EISA bridge implements the DMA controller logic
+ // needed to support slave DMA.
+ //
+
+ break;
+
+ case PCIBus:
+
+ //
+ // Get the bus handler for the PCI bus.
+ //
+
+ BusHandler = HaliHandlerForBus(
+ PCIBus,
+ DeviceDescription->BusNumber
+ );
+
+ //
+ // If a bus handler does not exist, then there is a s/w bug
+ // somewhere. Just return failure.
+ //
+
+ if( BusHandler == NULL ){
+
+ return NULL;
+
+ }
+
+ //
+ // Get a pointer to the PCI private bus data for this bus.
+ // The h/w bus number is located therein.
+ //
+
+ PciBusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // The DMA controller we use to support slave DMA is located
+ // on the ISA/EISA bridge in h/w bus 0. If this PCI bus is
+ // not located on h/w bus 0, return failure.
+ //
+
+ if( PciBusData->HwBusNumber != 0 ){
+
+ return NULL;
+
+ }
+
+ break;
+
+ default:
+
+ //
+ // We only support ISA, EISA and PCI slave DMA.
+ //
+
+ return NULL;
+
+ }
+
+ }
+
+ //
+ // Create an EISA adapter if this device is an ISA device
+ // or is not a master device.
+ //
+
+ if( (DeviceDescription->Master != TRUE) ||
+ (DeviceDescription->InterfaceType == Isa ) ){
+
+ //
+ // Allocate the Isa Map Register Adapter if it has not
+ // already been allocated.
+ //
+
+ if( HalpIsaMapAdapter == NULL ){
+ HalpIsaMapAdapter = HalpAllocateMapAdapter(
+ &HalpIsaWindowControl,
+ IsaAdapter,
+ HalpIsaMapRegisterBase );
+ if( HalpIsaMapAdapter == NULL ){
+ return NULL;
+ }
+ }
+
+ adapterObject = HalpAllocateEisaAdapter(
+ DeviceDescription,
+ NumberOfMapRegisters );
+
+ if( adapterObject == NULL ){
+ return NULL;
+ }
+
+ adapterObject->Type = IsaAdapter;
+ adapterObject->MapAdapter = HalpIsaMapAdapter;
+ adapterObject->MapRegisterBase = NULL;
+ adapterObject->NumberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Allocate the master map register adapter if it has not
+ // already been allocated.
+ //
+
+ if( HalpMasterMapAdapter == NULL ){
+ HalpMasterMapAdapter = HalpAllocateMapAdapter(
+ &HalpMasterWindowControl,
+ BusMasterAdapter,
+ HalpMasterMapRegisterBase );
+ if( HalpMasterMapAdapter == NULL ){
+ return NULL;
+ }
+ }
+
+ //
+ // Allocate an adapter for this master device.
+ //
+
+ adapterObject = HalpAllocateAdapter();
+
+ if( adapterObject == NULL ){
+ return NULL;
+ }
+
+ //
+ // Initialize the adapter object.
+ //
+
+ adapterObject->Type = BusMasterAdapter;
+ adapterObject->MasterDevice = TRUE;
+ adapterObject->MapAdapter = HalpMasterMapAdapter;
+ adapterObject->MapRegisterBase = NULL;
+ adapterObject->NumberOfMapRegisters = 0;
+
+ //
+ // Calculate maximum number of map registers for this adapter.
+ //
+
+ if (NumberOfMapRegisters != NULL) {
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(
+ DeviceDescription->MaximumLength ) + 1;
+
+ //
+ // Limit the number of map registers to no more than 1/4 of all
+ // of the map registers available for this DMA window.
+ //
+
+ MaximumMapRegistersPerChannel =
+ (HalpMasterMapAdapter->WindowSize >> PAGE_SHIFT) / 4;
+ if( *NumberOfMapRegisters > MaximumMapRegistersPerChannel ){
+ *NumberOfMapRegisters = MaximumMapRegistersPerChannel;
+ }
+
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+
+ } else {
+
+ adapterObject->MapRegistersPerChannel = 0;
+
+ }
+ }
+
+ return(adapterObject);
+}
+
+PMAP_REGISTER_ADAPTER
+HalpAllocateMapAdapter(
+ IN PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ IN HAL_ADAPTER_TYPE AdapterType,
+ IN PTRANSLATION_ENTRY MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes the structure for the bus
+ master map register adapter.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control
+ registers that describes the DMA window associated
+ with this map adapter.
+
+ AdapterType - Supplies the type of the adapter.
+
+ MapRegisterBase - Supplies the starting virtual address of the map
+ registers for this adapter.
+
+Return Value:
+
+ Returns the pointer to the allocated and initialized map
+ adapter if allocation was successful, NULL otherwise.
+
+--*/
+
+{
+ ULONG NumberMapRegisters;
+ ULONG Size;
+ PMAP_REGISTER_ADAPTER mapAdapter;
+
+ Size = sizeof(MAP_REGISTER_ADAPTER);
+
+ NumberMapRegisters = WindowRegisters->WindowSize / PAGE_SIZE;
+
+ //
+ // Add size of bitmap. Size of bitmap is the number of bytes required,
+ // computed by dividing map registers by 8 (>>3) and then rounding up
+ // to the nearest value divisible by 4.
+ //
+
+ Size += sizeof(RTL_BITMAP) + (( ((NumberMapRegisters+7) >> 3) + 3) & ~3);
+
+ //
+ // Allocate the map register adapter.
+ //
+
+ mapAdapter = ExAllocatePool( NonPagedPool, Size );
+
+ if( mapAdapter == NULL ){
+ return NULL;
+ }
+
+ //
+ // Initialize the fields within the map adapter structure.
+ //
+
+ mapAdapter->Type = AdapterType;
+
+ KeInitializeSpinLock( &mapAdapter->SpinLock );
+ InitializeListHead( &mapAdapter->RegisterWaitQueue );
+
+ mapAdapter->MapRegisterBase = MapRegisterBase;
+ mapAdapter->NumberOfMapRegisters = NumberMapRegisters;
+ mapAdapter->MapRegisterAllocation = (PRTL_BITMAP)(mapAdapter + 1);
+ RtlInitializeBitMap( mapAdapter->MapRegisterAllocation,
+ (PULONG)((PCHAR)(mapAdapter->MapRegisterAllocation) +
+ sizeof(RTL_BITMAP)),
+ NumberMapRegisters );
+ RtlClearAllBits( mapAdapter->MapRegisterAllocation );
+
+
+ mapAdapter->WindowBase = WindowRegisters->WindowBase;
+ mapAdapter->WindowSize = WindowRegisters->WindowSize;
+
+ mapAdapter->WindowControl = WindowRegisters;
+
+ return mapAdapter;
+}
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ IO_ALLOCATION_ACTION Action;
+ BOOLEAN Busy = FALSE;
+ PMAP_REGISTER_ADAPTER MapAdapter;
+
+ //
+ // Begin by obtaining a pointer to the map register adapter associated
+ // with this request.
+ //
+
+ MapAdapter = AdapterObject->MapAdapter;
+
+ DebugPrint( (HALDBG_MAPREG,
+ "\nHalAllocateAdapter, Adapter=%x, MapA=%x, Maps=%x\n",
+ AdapterObject, MapAdapter, NumberOfMapRegisters) );
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+
+ //
+ // Validate that the requested number of map registers is
+ // within the maximum limit.
+ //
+
+ if (NumberOfMapRegisters > MapAdapter->NumberOfMapRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ Busy = HalpAllocateMapRegisters( AdapterObject,
+ NumberOfMapRegisters,
+ FALSE );
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (Busy == FALSE) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the
+ // number allocated to zero and set the action to deallocate
+ // object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ } else {
+
+ DebugPrint( (HALDBG_MAPREG,
+ "No map registers available, Adapter= %x, Maps= %x\n",
+ AdapterObject, NumberOfMapRegisters) );
+
+ }
+
+ } else {
+
+ DebugPrint( (HALDBG_MAPREG,
+ "Device Queue is busy, AdapterObject = %x\n",
+ AdapterObject) );
+
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+BOOLEAN
+HalpAllocateMapRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG NumberOfMapRegisters,
+ IN BOOLEAN MapAdapterLocked
+ )
+/*++
+
+Routine Description:
+
+ Allocate the requested number of contiguous map registers from
+ the Map adapter.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object for which the
+ map registers are to be allocated.
+
+ NumberOfMapRegisters - Supplies the number of map registers to allocate.
+
+ MapAdapterLocked - Supplies a boolean which indicates if the map adapter
+ for the AdapterObject is already locked.
+
+Return Value:
+
+ The value returned indicates if the map registers are busy.
+ The value FALSE is returned if the map registers were allocated.
+ Otherwise, the Adapter is put on the register wait queue for its
+ associated map adapter and TRUE is returned.
+
+--*/
+{
+ ULONG AllocationMask;
+ BOOLEAN Busy = FALSE;
+ ULONG ExtentBegin;
+ ULONG HintIndex;
+ KIRQL Irql;
+ ULONG MapRegisterIndex;
+ PMAP_REGISTER_ADAPTER mapAdapter;
+
+ //
+ // Some devices do DMA prefetch. This is bad since it will cause certain
+ // chipsets to generate a PFN error because a map register has not been
+ // allocated and validated. To fix this, we'll put in a hack. We'll
+ // allocate one extra map register and map it to some junk page to avoid
+ // this nasty problem.
+ //
+
+ NumberOfMapRegisters += 1;
+
+ //
+ // Acquire a pointer to the map adapter that contains the map registers
+ // for the adapter.
+ //
+
+ mapAdapter = AdapterObject->MapAdapter;
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object.
+ //
+
+ if( MapAdapterLocked == FALSE ){
+ KeAcquireSpinLock( &mapAdapter->SpinLock, &Irql );
+ }
+
+ MapRegisterIndex = MAXULONG;
+
+ if (IsListEmpty( &mapAdapter->RegisterWaitQueue)) {
+
+ //
+ // If this is an Isa machine and the requested DMA is for an
+ // Isa device then we must be careful that the DMA does not cross
+ // a 64K boundary on the bus.
+ //
+
+ if( (HalpBusType == MACHINE_TYPE_ISA) &&
+ (mapAdapter->Type == IsaAdapter) ){
+
+ ASSERT( (NumberOfMapRegisters * PAGE_SIZE) <= __64K );
+
+ //
+ // This is an Isa allocation, guarantee that the allocation
+ // of map registers will not span a 64K boundary. We do this by
+ // looking for a contiguous allocation of:
+ // NumberOfMapRegisters * 2 - 1
+ // Any allocation of this size will guarantee that:
+ // (a) The allocation fits before the next 64K boundary or
+ // (b) The allocation can be made on the next 64K boundary.
+ //
+ // N.B. - This algorithm depends on RtlFindClear* to find
+ // the first available extent of cleared bits.
+ //
+
+ ExtentBegin = RtlFindClearBits(
+ mapAdapter->MapRegisterAllocation,
+ NumberOfMapRegisters + 7,
+ 0 );
+
+ if( ExtentBegin != -1 ){
+
+ //
+ // Compute the hint index. If ExtentBegin + NumberOfMaps
+ // does not cross a 64K boundary then ExtentBegin will be
+ // the hint index. Otherwise, align the hint to the next
+ // 64K boundary above ExtentBegin.
+ //
+
+ AllocationMask = (__64K >> PAGE_SHIFT) - 1;
+ HintIndex = (ExtentBegin+AllocationMask) & ~AllocationMask;
+
+ MapRegisterIndex = RtlFindClearBitsAndSet(
+ mapAdapter->MapRegisterAllocation,
+ NumberOfMapRegisters,
+ HintIndex );
+
+ }
+
+
+ } else {
+
+ //
+ // This allocation is not subject to the Isa 64K restriction.
+ //
+
+ ExtentBegin = RtlFindClearBits(
+ mapAdapter->MapRegisterAllocation,
+ NumberOfMapRegisters + 7,
+ 0 );
+
+ AllocationMask = (__64K >> PAGE_SHIFT) - 1;
+
+ HintIndex = (ExtentBegin + AllocationMask) & ~AllocationMask;
+
+ MapRegisterIndex = RtlFindClearBitsAndSet(
+ mapAdapter->MapRegisterAllocation,
+ NumberOfMapRegisters,
+ HintIndex );
+
+ } //endif HalpBusType == MACHINE_TYPE_ISA
+
+ } //endif IsListEmpty
+
+ if (MapRegisterIndex == MAXULONG) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the map adapter where it will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &mapAdapter->RegisterWaitQueue,
+ &AdapterObject->AdapterQueue );
+ Busy = TRUE;
+
+ }
+
+ //
+ // Unlock the map adapter (unless locked by the caller).
+ //
+
+ if( MapAdapterLocked == FALSE ){
+ KeReleaseSpinLock( &mapAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If map registers were allocated, return the index of the first
+ // map register in the contiguous extent.
+ //
+
+ if( Busy == FALSE ){
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY) mapAdapter->MapRegisterBase
+ + MapRegisterIndex);
+ }
+
+ return Busy;
+
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The function value is a pointer to the allocated adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoAdapterObjectType,
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose(Handle);
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+ return AdapterObject;
+
+}
+
+
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and updated to
+ show number actually allocated.
+
+Return Value:
+
+ Returns a pointer to the allocated map register base.
+
+--*/
+
+{
+ ULONG AllocationMask;
+ PMAP_REGISTER_ADAPTER MapAdapter;
+ ULONG HintIndex;
+ ULONG MapRegisterIndex;
+ ULONG ExtentBegin;
+
+ //
+ // Begin by obtaining a pointer to the map adapter associated with this
+ // request.
+ //
+
+ MapAdapter = AdapterObject->MapAdapter;
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > MapAdapter->NumberOfMapRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ MapRegisterIndex = (ULONG)-1;
+
+ //
+ // If this is an Isa machine and the requested DMA is for an
+ // Isa device then we must be areful that the DMA does not cross
+ // a 64K boundary on the bus.
+ //
+
+ if( (HalpBusType == MACHINE_TYPE_ISA) &&
+ (MapAdapter->Type == IsaAdapter) ){
+
+ //
+ // This is an Isa allocation, guarantee that the allocation
+ // of map registers will not span a 64K boundary. We do this by
+ // looking for a consiguous allocation of:
+ // NumberOfMapRegisters * 2 - 1
+ // Any allocation of this size will guarantee that:
+ // (a) The allocation fitst before the next 64K boundary or
+ // (b) The allocation can be made on the next 64K boundary.
+ //
+ // N.B. - This algorithm depends on RtlFindClear* to find
+ // the first available extent of cleared bits.
+ //
+
+ ExtentBegin = RtlFindClearBits(
+ MapAdapter->MapRegisterAllocation,
+ (*NumberOfMapRegisters * 2) - 1,
+ 0 );
+ if( ExtentBegin != -1){
+
+ //
+ // Compute the hint index. If ExtentBegin + NumberOfMaps
+ // does not cross a 64K boundary then ExtentBegin will be
+ // the hint index. Otherwise, align the hint to the next
+ // 64K boundary above ExtentBegin.
+ //
+
+ AllocationMask = (__64K >> PAGE_SHIFT) - 1;
+ HintIndex = ExtentBegin;
+
+ if( (ExtentBegin + *NumberOfMapRegisters) >
+ ((ExtentBegin + AllocationMask) & ~AllocationMask) ){
+
+ //
+ // Allocation would have spanned a 64K boundary.
+ // Round up to next 64K boundary.
+ //
+
+ HintIndex = (ExtentBegin+AllocationMask) & ~AllocationMask;
+
+ }
+
+ MapRegisterIndex = RtlFindClearBitsAndSet(
+ MapAdapter->MapRegisterAllocation,
+ *NumberOfMapRegisters,
+ HintIndex );
+
+ }
+
+ } else {
+
+ //
+ // This allocation is not subject to the Isa 64K restriction.
+ //
+
+ HintIndex = 0;
+
+ MapRegisterIndex = RtlFindClearBitsAndSet(
+ MapAdapter->MapRegisterAllocation,
+ *NumberOfMapRegisters,
+ 0 );
+
+ }
+
+ if (MapRegisterIndex == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MapAdapter->MapRegisterAllocation,
+ HintIndex,
+ *NumberOfMapRegisters
+ );
+ MapRegisterIndex = HintIndex;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MapAdapter->MapRegisterBase + MapRegisterIndex);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ IO_ALLOCATION_ACTION Action;
+ BOOLEAN Busy = FALSE;
+ KIRQL Irql;
+ LONG MapRegisterIndex;
+ PLIST_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PMAP_REGISTER_ADAPTER mapAdapter;
+
+
+ //
+ // Deallocate the extra map register that we originally allocated to fix
+ // the DMA prefetch problem.
+ //
+
+ NumberOfMapRegisters += 1;
+
+ //
+ // Begin by getting the address of the map register adapter.
+ //
+
+ mapAdapter = AdapterObject->MapAdapter;
+
+ DebugPrint( (HALDBG_MAPREG,
+ "IoFreeMapRegisters, Adapter=%x, MapA=%x, Maps=%x\n",
+ AdapterObject, mapAdapter, NumberOfMapRegisters) );
+
+ MapRegisterIndex = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) mapAdapter->MapRegisterBase;
+
+ //
+ // Acquire the map adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&mapAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( mapAdapter->MapRegisterAllocation,
+ MapRegisterIndex,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&mapAdapter->RegisterWaitQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &mapAdapter->RegisterWaitQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ DebugPrint( (HALDBG_MAPREG,
+ "IoFreeMaps, waking Adapter=%x\n", AdapterObject) );
+
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate the map registers.
+ //
+
+ Busy = HalpAllocateMapRegisters( AdapterObject,
+ Wcb->NumberOfMapRegisters,
+ TRUE );
+
+ if( Busy == TRUE ){
+ DebugPrint( (HALDBG_MAPREG,
+ "IoFreeMaps, Not enough maps, Adapter=%x, Maps=%x\n",
+ AdapterObject, Wcb->NumberOfMapRegisters) );
+ break;
+ }
+
+ KeReleaseSpinLock( &mapAdapter->SpinLock, Irql );
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if
+ // there are no requests in the map adapter queue, then
+ // IoFreeMapRegisters will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &mapAdapter->SpinLock, &Irql );
+
+ MapRegisterIndex =
+ (PTRANSLATION_ENTRY)AdapterObject->MapRegisterBase -
+ (PTRANSLATION_ENTRY)mapAdapter->MapRegisterBase;
+
+ RtlClearBits( mapAdapter->MapRegisterAllocation,
+ MapRegisterIndex,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &mapAdapter->SpinLock, Irql );
+
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &mapAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &mapAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PMAP_REGISTER_ADAPTER mapAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the map register adapter.
+ //
+
+ mapAdapter = AdapterObject->MapAdapter;
+
+ DebugPrint( (HALDBG_MAPREG,
+ "IoFreeChannel, Adapter=%x, MapAdapter=%x\n",
+ AdapterObject, mapAdapter) );
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ DebugPrint( (HALDBG_MAPREG,
+ "IoFreeChannel, waking for Maps=%x\n",
+ Wcb->NumberOfMapRegisters) );
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+
+ Busy = HalpAllocateMapRegisters( AdapterObject,
+ Wcb->NumberOfMapRegisters,
+ FALSE );
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (Busy == FALSE) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ DebugPrint( (HALDBG_MAPREG,
+ "IoFreeChannel, not enough maps, Adapter=%x, Maps=%x\n",
+ AdapterObject, Wcb->NumberOfMapRegisters) );
+
+ break;
+ }
+ }
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+N.B. - The MapRegisterBase must point to the mapping intended for
+ the start virtual address of the Mdl.
+
+--*/
+
+{
+ ULONG NumberOfPages;
+ ULONG Offset;
+ PULONG PageFrameNumber;
+ ULONG i;
+ PMAP_REGISTER_ADAPTER mapAdapter;
+ PTRANSLATION_ENTRY mapRegister;
+ PHYSICAL_ADDRESS ReturnAddress;
+
+ DebugPrint( (HALDBG_IOMT,
+ "\nIoMT: CurrentVA = %x, Length = %x, WriteToDevice = %x\n",
+ CurrentVa, *Length, WriteToDevice ) );
+
+ //
+ // Determine the Map Register Adapter.
+ //
+
+ mapAdapter = NULL;
+
+ if( AdapterObject == NULL ){
+
+ //
+ // The caller did not supply the adapter object, we will determine
+ // the map adapter by matching the MapRegisterBase to the ranges
+ // allocated for each map adapter.
+ //
+
+ if( (HalpIsaMapAdapter != NULL) &&
+ (MapRegisterBase >= HalpIsaMapAdapter->MapRegisterBase) &&
+ ((PTRANSLATION_ENTRY)MapRegisterBase <
+ (PTRANSLATION_ENTRY)HalpIsaMapAdapter->MapRegisterBase +
+ HalpIsaMapAdapter->NumberOfMapRegisters ) ){
+
+ mapAdapter = HalpIsaMapAdapter;
+
+ }
+
+ if( (HalpMasterMapAdapter != NULL) &&
+ (MapRegisterBase >= HalpMasterMapAdapter->MapRegisterBase) &&
+ ((PTRANSLATION_ENTRY)MapRegisterBase <
+ (PTRANSLATION_ENTRY)HalpMasterMapAdapter->MapRegisterBase +
+ HalpMasterMapAdapter->NumberOfMapRegisters ) ){
+
+ mapAdapter = HalpMasterMapAdapter;
+
+ }
+
+ } else {
+
+ //
+ // The adapter object has been provided and will always have
+ // a pointer to the map adapter.
+ //
+
+ mapAdapter = AdapterObject->MapAdapter;
+
+ }
+
+ ASSERT( mapAdapter != NULL );
+
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+ Offset = BYTE_OFFSET( (PCHAR)CurrentVa - (PCHAR)Mdl->StartVa );
+ DebugPrint( (HALDBG_IOMT, "Offset (1) = %x\n", Offset ) );
+
+ //
+ // Compute number of pages that this transfer spans.
+ //
+
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ DebugPrint( (HALDBG_IOMT, "NumberOfPages = %x\n", NumberOfPages ) );
+
+ //
+ // Compute a pointer to the page frame of the starting page of the transfer.
+ //
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ PageFrameNumber += ( ((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa)
+ >> PAGE_SHIFT );
+
+ //
+ // Compute a pointer to the map register that maps the starting page of
+ // the transfer.
+ //
+
+ mapRegister = MapRegisterBase;
+
+ //
+ // For each page, establish the mapping in the scatter/gather tables.
+ //
+
+ for (i = 0; i < NumberOfPages; i++) {
+ HAL_MAKE_VALID_TRANSLATION( mapRegister, *PageFrameNumber );
+ DebugPrint( (HALDBG_IOMT,
+ "Validate: *PageFrameNumber = %x, mapRegister = %x\n",
+ *PageFrameNumber, mapRegister ) );
+ PageFrameNumber += 1;
+ mapRegister += 1;
+ }
+
+ //
+ // If the operation is a write to device (transfer from memory to device),
+ // we will validate the extra map register so we don't generate a PFN
+ // error due to DMA prefetch by some devices.
+ //
+
+ if (WriteToDevice) {
+ PageFrameNumber -= 1;
+ HAL_MAKE_VALID_TRANSLATION( mapRegister, *PageFrameNumber );
+ }
+
+ //
+ // Synchronize the scatter/gather entry writes with any subsequent writes
+ // to the device.
+ //
+
+ HalpMb(); //jnfix - create HalpWmb();
+
+ //
+ // Invalidate any cached translations in the DMA window.
+ //
+
+ INVALIDATE_DMA_TRANSLATIONS( mapAdapter->WindowControl );
+
+ //
+ // Set the offset to point to the map register plus the offset.
+ //
+
+ Offset += ((PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) mapAdapter->MapRegisterBase) << PAGE_SHIFT;
+
+ Offset += (ULONG)mapAdapter->WindowBase;
+ DebugPrint( (HALDBG_IOMT, "Offset(3) = %x\n", Offset ) );
+
+ if( (AdapterObject != NULL) &&
+ (AdapterObject->Type == IsaAdapter) &&
+ (AdapterObject->MasterDevice != TRUE) ){
+
+ //
+ // Start the EISA DMA controller.
+ //
+
+ HalpMapEisaTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+
+ ReturnAddress.QuadPart = Offset;
+ return(ReturnAddress);
+}
+
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+ ULONG NumberOfPages;
+ ULONG Offset;
+ BOOLEAN Result;
+ ULONG i;
+ PMAP_REGISTER_ADAPTER mapAdapter;
+ PTRANSLATION_ENTRY mapRegister;
+
+ DebugPrint( (HALDBG_IOMT,
+ "\nIoFlush: CurrentVA = %x, Length = %x, WriteToDevice = %x\n",
+ CurrentVa, Length, WriteToDevice ) );
+
+ //
+ // Determine the Map Register Adapter.
+ //
+
+ mapAdapter = NULL;
+
+ if( AdapterObject == NULL ){
+
+ //
+ // The caller did not supply the adapter object, we will determine
+ // the map adapter by matching the MapRegisterBase to the ranges
+ // allocated for each map adapter.
+ //
+
+ if( (HalpIsaMapAdapter != NULL) &&
+ (MapRegisterBase >= HalpIsaMapAdapter->MapRegisterBase) &&
+ ((PTRANSLATION_ENTRY)MapRegisterBase <
+ (PTRANSLATION_ENTRY)HalpIsaMapAdapter->MapRegisterBase +
+ HalpIsaMapAdapter->NumberOfMapRegisters ) ){
+
+ mapAdapter = HalpIsaMapAdapter;
+
+ }
+
+ if( (HalpMasterMapAdapter != NULL) &&
+ (MapRegisterBase >= HalpMasterMapAdapter->MapRegisterBase) &&
+ ((PTRANSLATION_ENTRY)MapRegisterBase <
+ (PTRANSLATION_ENTRY)HalpMasterMapAdapter->MapRegisterBase +
+ HalpMasterMapAdapter->NumberOfMapRegisters ) ){
+
+ mapAdapter = HalpMasterMapAdapter;
+
+ }
+
+ } else {
+
+ //
+ // The adapter object has been provided and will always have
+ // a pointer to the map adapter.
+ //
+
+ mapAdapter = AdapterObject->MapAdapter;
+
+ }
+
+ //
+ // Set the result of the flush to success.
+ //
+
+ Result = TRUE;
+
+ //
+ // If this is an Isa compatiable adapter or an adapter that uses
+ // the ISA/EISA Dma controllers then use the standard routines
+ // to clear the Dma controller.
+ //
+
+ if( (AdapterObject != NULL) &&
+ (AdapterObject->Type == IsaAdapter) &&
+ (AdapterObject->MasterDevice != TRUE) ){
+
+ Result = HalpFlushEisaAdapter( AdapterObject,
+ Mdl,
+ MapRegisterBase,
+ CurrentVa,
+ Length,
+ WriteToDevice );
+ }
+
+ //
+ // The Mdl->StartVa must point to a page boundary.
+ //
+
+ ASSERT( ( (ULONG)Mdl->StartVa & (PAGE_SIZE-1) ) == 0 );
+
+ //
+ // Compute the starting offset of the transfer.
+ //
+
+ Offset = BYTE_OFFSET( (PCHAR)CurrentVa - (PCHAR)Mdl->StartVa );
+
+ //
+ // Compute the number of pages that this transfer spanned.
+ //
+
+ NumberOfPages = (Offset + Length + PAGE_SIZE-1) >> PAGE_SHIFT;
+
+ //
+ // Compute a pointer to the first translation entry that mapped this
+ // transfer.
+ //
+
+ mapRegister = (PTRANSLATION_ENTRY)MapRegisterBase;
+
+ //
+ // Mark each translation as invalid.
+ //
+
+ for( i=0; i < NumberOfPages; i++ ){
+ HAL_INVALIDATE_TRANSLATION( mapRegister );
+ DebugPrint( (HALDBG_IOMT,
+ "Invalidate mapRegister = %x, PageFrame=%x\n",
+ mapRegister, (PTRANSLATION_ENTRY)mapRegister->Pfn) );
+ mapRegister += 1;
+ }
+
+ if( WriteToDevice ){
+ HAL_INVALIDATE_TRANSLATION( mapRegister );
+ }
+
+ //
+ // Invalidate any cached translations in the DMA window.
+ //
+
+ INVALIDATE_DMA_TRANSLATIONS( mapAdapter->WindowControl );
+
+ //
+ // Synchronize the updated translations with any subsequent device
+ // accesses.
+ // Also, synchronize any reads of the newly written DMA data by
+ // ensuring this processors view of memory is coherent.
+ // jnfix - actually this second task must be handled by HalFlushIoBuffers
+ //
+
+ HalpMb();
+
+ return Result;
+
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+
+ //
+ // If this is an Isa compatiable adapter or an adapter that uses
+ // the ISA/EISA Dma controllers then use the standard routines
+ // to return the Dma count.
+ //
+
+ if( AdapterObject->Type == IsaAdapter ){
+
+ return HalpReadEisaDmaCounter( AdapterObject );
+
+ }
+
+ return 0;
+
+}
+
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+ PHYSICAL_ADDRESS MaxPhysicalAddress;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer and limit its physical address
+ // below 1GB. The 1GB limitation guarantees that the buffer will
+ // be accessible via 32-bit superpage.
+ //
+
+ MaxPhysicalAddress.HighPart = 0;
+ MaxPhysicalAddress.LowPart = __1GB - 1;
+ virtualAddress = MmAllocateContiguousMemory( Length, MaxPhysicalAddress );
+
+ if (virtualAddress == NULL) {
+
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ MmFreeContiguousMemory( virtualAddress );
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ MmFreeContiguousMemory( virtualAddress );
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ FALSE
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PMAP_REGISTER_ADAPTER mapAdapter;
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG mapRegisterIndex;
+ ULONG numberOfMapRegisters;
+
+ mapAdapter = AdapterObject->MapAdapter;
+
+ //
+ // Calculate the number of map registers, the map register index and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES( VirtualAddress,
+ Length );
+ mapRegisterIndex = (LogicalAddress.LowPart - (ULONG)mapAdapter->WindowBase)
+ >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) mapAdapter->MapRegisterBase
+ + mapRegisterIndex;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ MmFreeContiguousMemory( VirtualAddress );
+
+ return;
+
+}
+
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
diff --git a/private/ntos/nthals/halalpha/ebsgdma.h b/private/ntos/nthals/halalpha/ebsgdma.h
new file mode 100644
index 000000000..2548b8134
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ebsgdma.h
@@ -0,0 +1,180 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebsgdma.h
+
+Abstract:
+
+ This file defines the data structures for scatter/gather DMA
+ support for Eisa/Isa bus systems.
+
+Author:
+
+ Joe Notarangelo 12-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _EBSGDMA_
+#define _EBSGDMA_
+
+#include "eisa.h"
+
+
+//
+// Define the structures for Io Adapters.
+//
+
+typedef enum _HAL_ADAPTER_TYPE{
+ IsaAdapter,
+ BusMasterAdapter
+} HAL_ADAPTER_TYPE, *PHAL_ADAPTER_TYPE;
+
+typedef struct _MAP_REGISTER_ADAPTER{
+
+ //
+ // The type of the map register adapter.
+ //
+
+ HAL_ADAPTER_TYPE Type;
+
+ //
+ // Access control for allocating map registers.
+ // The SpinLock guarantees exclusive access to this adapter.
+ // The RegisterWaitQueue is a list of adapters waiting for
+ // map registers. The spinlock is also used to grant exclusive
+ // access to other resources which may be shared by the adapters
+ // that have this map adapter in common (in particular, access to the
+ // DMA controller hardware in Eisa/Isa machines).
+ //
+
+ KSPIN_LOCK SpinLock;
+ LIST_ENTRY RegisterWaitQueue;
+
+ //
+ // MapRegisterBase is the base address of the scatter/gather entry
+ // array. NumberOfMapRegisters is the number of scatter/gather entries
+ // allocated for this adapter. MapRegisterAllocation points to the
+ // allocation bitmap for the scatter/gather entry array.
+ //
+
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ PRTL_BITMAP MapRegisterAllocation;
+
+ //
+ // WindowBase is the base bus address of the DMA window controlled
+ // by this adapter. WindowSize is the size of the window in bytes.
+ //
+
+ PVOID WindowBase;
+ ULONG WindowSize;
+
+ //
+ // WindowControl is a pointer to the window control registers
+ // structure that defines the QVAs of the window registers.
+ //
+
+ PVOID WindowControl;
+
+} MAP_REGISTER_ADAPTER, *PMAP_REGISTER_ADAPTER;
+
+
+typedef struct _ADAPTER_OBJECT{
+
+ //
+ // Object header fields, type and size.
+ ///
+
+ CSHORT ObjectType;
+ CSHORT Size;
+
+ //
+ // The type of the adapter, either an adapter that requires Isa
+ // support or an adapter that does not.
+ //
+
+ HAL_ADAPTER_TYPE Type;
+
+ //
+ // Pointer to the adapter that controls the map registers for this
+ // adapter.
+ //
+
+ PMAP_REGISTER_ADAPTER MapAdapter;
+
+ //
+ // Indicate if this is a master device or not.
+ //
+
+ BOOLEAN MasterDevice;
+
+ //
+ // The maximum map registers for this adapter.
+ //
+
+ ULONG MapRegistersPerChannel;
+
+ //
+ // The map registers currently allocated to this adapter, the base
+ // address and the number. The number will be the number desired for
+ // allocation if this adapter is waiting on the map adapters queue.
+ //
+
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+
+ //
+ // The device queue for waiters trying to all allocate this adapter.
+ //
+
+ KDEVICE_QUEUE ChannelWaitQueue;
+
+ //
+ // The wait context block of the driver that has currently allocated
+ // the adapter.
+ //
+
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+
+ //
+ // The list entry used when this adapter is queue to a map adapter,
+ // waiting for map registers.
+ //
+
+ LIST_ENTRY AdapterQueue;
+
+ //
+ // Values describing the programming of a DMA channel for this
+ // adapter. The values describe the programming for a standard PC
+ // DMA controller.
+ //
+ // AdapterBaseVa - pointer to base address of DMA controller.
+ // AdapterNumber - the number of the DMA controller.
+ // ChannelNumber - the DMA channel number used by the adapter.
+ // AdapterMode - the mode used to program the DMA channel.
+ // ExtendedMode - the value used to program extended mode for the channel.
+ // SingleMaskPort - port address for unmasking the DMA controller.
+ // PagePort - port address of the page register for the DMA channel.
+ //
+
+ PVOID AdapterBaseVa;
+ UCHAR AdapterNumber;
+ UCHAR ChannelNumber;
+ UCHAR AdapterMode;
+ DMA_EXTENDED_MODE ExtendedMode;
+ PUCHAR PagePort;
+ BOOLEAN Width16Bits;
+
+} ADAPTER_OBJECT;
+
+#endif //_EBSGDMA_
diff --git a/private/ntos/nthals/halalpha/eeprom8k.c b/private/ntos/nthals/halalpha/eeprom8k.c
new file mode 100644
index 000000000..c4e73260f
--- /dev/null
+++ b/private/ntos/nthals/halalpha/eeprom8k.c
@@ -0,0 +1,391 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ eeprom8k.c
+
+Abstract:
+
+ This module implements the device-specific routines necessary to
+ Read and Write the Electrically Eraseable Programmable Read Only
+ Memory (EEPROM) containing the system environment variables. Note
+ that this module is used in exclusion of CMOS NVram support for the
+ same variables.
+
+ This module assumes that a standard PC NVRAM interface to the EEPROM
+ is being provided (for example the one provide by the Intel ESC
+ chip). This interface gives a 256 byte NVRAM page window into the
+ device. The current NVRAM page is selected through a page select
+ register.
+
+ Parts support by this module include:
+
+ Xicor X2864A
+
+ The routines implemented here are:
+
+ HalpReadNVRamBuffer() - copy data from NVRAM into memory
+ HalpWriteNVRamBuffer() - write memory data to NVRAM
+ HalpCopyNVRamBuffer() - move data within the NVRAM
+
+Author:
+
+ Steve Brooks 5-Oct 93
+
+
+Revision History:
+
+ Steve Jenness 10-Nov 93
+ Joe Notarangelo 10-Nov 93
+ Matthew Buchman 09-May 96 Stall instead of polling for Write complete.
+ Scott Lee 23-Sept-96 Use original write algorithm and add a check
+ for the last write.
+
+--*/
+
+
+#include "halp.h"
+#include "cmos8k.h" // This is ok for eeprom8k.c
+
+#include "arccodes.h"
+
+#ifdef HAL_DBG
+ULONG EepromDebug = 0;
+#define EepromDbgPrint(x) if (EepromDebug) DbgPrint(x)
+#else
+#define EepromDbgPrint(x)
+#endif //HAL_DBG
+
+//
+// Routine prototypes.
+//
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ );
+
+
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads data from the EEPROM into main memory.
+
+Arguments:
+
+ DataPtr - Pointer to memory location to receive data
+ NvRamPtr - Pointer (qva) to EEPROM location to read data from
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+{
+ ULONG PageSelect, ByteSelect;
+
+ PageSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ while ( Length -- )
+ {
+ *DataPtr++ = READ_CONFIG_RAM_DATA(NvRamPtr);
+ NvRamPtr ++;
+
+ ByteSelect = (ByteSelect + 1) & CONFIG_RAM_BYTE_MASK;
+ if (ByteSelect == 0)
+ {
+ PageSelect++;
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ }
+ }
+
+ return(ESUCCESS);
+}
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine Writes data from memory into the EEPROM. EEPROM page
+ mode write is used.
+
+ N.B. - This routine could have problems if interrupts are enabled
+ and the writing time between two bytes is over 20uSec.
+
+ N.B. - The ESC provides the NVRAM interface on 256
+ byte NVRAM pages. The EEPROM internally uses 16byte pages for
+ grouped programming. A EEPROM 16byte page commits (programs into
+ the EEPROM) in the same amount of time as a single byte does.
+ A EEPROM page has to be committed before switching to another
+ page. This is true if only 1 byte is written or all 16.
+
+ N.B. - This routine assumes that the base address of the 256 byte
+ page buffer is on a 256 byte boundary.
+
+ N.B. - With the increase in processor speed and compiler technology,
+ we seem to violate a time increment that must occur between
+ Writes followed by Reads. This results in invaliding the
+ last write of the page. By first waiting the amount of a
+ write cycle, (specified in the Data Sheet as 5ms) after the last
+ write before reading, we don't run into this problem.
+
+ N.B. - The last write algorithm used did not worked with the 120 nsec part.
+ We have reverted back to the original algorithm and added a
+ modification. On the last write, if it is on a 256 byte page
+ boundary, do not increment and write the page select. Doing so will
+ cause the verification of the last write to fail.
+
+Arguments:
+
+ NvRamPtr - Pointer (qva) to EEPROM location to write data into
+ DataPtr - Pointer to memory location of data to be written
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+{
+ ULONG PageSelect;
+
+#define EEPROM_PAGE_SIZE 16
+#define EEPROM_OFFSET_MASK 0xF
+
+ ULONG EepromPageDataValid = FALSE;
+ UCHAR EepromPageData[EEPROM_PAGE_SIZE];
+ ULONG EepromPageOffset = 0;
+
+ BOOLEAN ByteWritten = FALSE;
+ PCHAR LastWrittenByteAddress;
+ ULONG LastWrittenByteValue;
+
+ //
+ // Calculate which NVRAM 256 byte page to select first.
+ //
+
+ PageSelect = (NvRamPtr - (PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+
+ //
+ // Loop until no more data to write.
+ //
+
+ while ( (Length --) != 0) {
+
+ //
+ // If the current page of EEPROM data hasn't been read from the
+ // device, do so now. The whole EEPROM page is read at once so
+ // that it doesn't interfere with the EEPROM programming timeout.
+ //
+
+ if (EepromPageDataValid == FALSE) {
+ PCHAR TmpNvRamPtr = NvRamPtr;
+
+ EepromPageOffset = (ULONG)NvRamPtr & EEPROM_OFFSET_MASK;
+
+ while (EepromPageOffset < EEPROM_PAGE_SIZE) {
+ EepromPageData[EepromPageOffset++] =
+ READ_CONFIG_RAM_DATA(TmpNvRamPtr);
+ TmpNvRamPtr++;
+ }
+
+ EepromPageDataValid = TRUE;
+ EepromPageOffset = (ULONG)NvRamPtr & EEPROM_OFFSET_MASK;
+ }
+
+ //
+ // If the EEPROM data matches the data to be written, short-circuit
+ // the write. This potentially saves lots of time.
+ // If the data is different, write it and remember that a byte
+ // was written for the NOT-DATA polling done later.
+ //
+
+ if (EepromPageData[EepromPageOffset] != *DataPtr) {
+
+ WRITE_CONFIG_RAM_DATA(NvRamPtr, *DataPtr);
+ ByteWritten = TRUE;
+ LastWrittenByteValue = *DataPtr;
+ LastWrittenByteAddress = NvRamPtr;
+
+ EepromDbgPrint( "." );
+ } else {
+ EepromDbgPrint( "o" );
+ }
+
+ EepromPageOffset ++;
+ NvRamPtr ++;
+ DataPtr ++;
+
+ //
+ // If we're stepping into the next EEPROM 16 byte page first make
+ // sure that the data for the previous page has been programmed.
+ // Invalidate the current EEPROM page data buffer so that the next
+ // page will be read in (for the short-circuit above).
+ //
+
+ if (EepromPageOffset >= EEPROM_PAGE_SIZE) {
+ if (ByteWritten == TRUE) {
+ while((READ_CONFIG_RAM_DATA(LastWrittenByteAddress) & 0xff) !=
+ (UCHAR)(LastWrittenByteValue & 0xff));
+ ByteWritten = FALSE;
+ }
+ EepromPageDataValid = FALSE;
+ }
+
+ //
+ // If we are stepping into the next NVRAM 256 byte page, switch
+ // the NVRAM page select. Don't step into the next page on the
+ // last write, however.
+ //
+
+ if ((Length != 0) &&
+ (((ULONG)NvRamPtr & CONFIG_RAM_BYTE_MASK) == 0 ) ) {
+ PageSelect++;
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect);
+ }
+ }
+
+ //
+ // Poll until the last byte written is programmed into the EEPROM.
+ //
+
+ if (ByteWritten == TRUE) {
+ while((READ_CONFIG_RAM_DATA(LastWrittenByteAddress) & 0xff) !=
+ (UCHAR)(LastWrittenByteValue & 0xff));
+ }
+
+ return(ESUCCESS);
+}
+
+ARC_STATUS
+HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies data between two locations within the EEPROM. It is
+ the callers responsibility to assure that the destination region does not
+ overlap the src region i.e. if the regions overlap, NvSrcPtr > NvDestPtr.
+
+ This routine does not use page mode access since we're unsure that
+ we can guarantee the 20uSec inter-byte timing required during a
+ page write. Currently, each byte is written and then checked for
+ commit into the EEPROM.
+
+ N.B. - This routine has not been optimized like HalpWriteNVRamBuffer.
+
+ N.B. - This routine doesn't appear to be used anywhere in either the
+ firmware, the HAL, or the kernel. It might not work.
+
+Arguments:
+
+ NvDestPtr - Pointer (qva) to NVRam location to write data into
+ NvSrcPtr - Pointer (qva) to NVRam location of data to copy
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+
+{
+ ULONG PageSelect0, ByteSelect0; // Src Pointer Page & offset
+ ULONG PageSelect1, ByteSelect1; // Dest Pointer Page & offset
+
+
+ PageSelect0 = (NvSrcPtr - (PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect0 = (NvSrcPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ PageSelect1 = (NvDestPtr-(PUCHAR)HalpCMOSRamBase) >> CONFIG_RAM_PAGE_SHIFT;
+ ByteSelect1 = (NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
+
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect0);
+ while ( Length -- )
+ {
+ UCHAR AChar;
+
+ //
+ // Check the Page select for the src pointer, and write the
+ // select register if necessary:
+ //
+ if (ByteSelect0 == 0)
+ {
+ PageSelect0++;
+ }
+ if ( PageSelect0 != PageSelect1 )
+ {
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect0);
+ }
+
+ AChar = READ_CONFIG_RAM_DATA(NvSrcPtr);
+ ByteSelect0 = (ByteSelect0 + 1) & CONFIG_RAM_BYTE_MASK;
+
+ //
+ // Check the page select for the dest pointer, and write
+ // the select register if necessary:
+ //
+ if (ByteSelect1 == 0)
+ {
+ PageSelect1++;
+ }
+ if ( PageSelect1 != PageSelect0 )
+ {
+ WRITE_CONFIG_RAM_PAGE_SELECT(PageSelect1);
+ }
+
+ WRITE_CONFIG_RAM_DATA(NvDestPtr, AChar);
+
+ while ( READ_CONFIG_RAM_DATA(NvDestPtr) != AChar )
+ ;
+ ByteSelect1 = (ByteSelect1 + 1) & CONFIG_RAM_BYTE_MASK;
+
+ NvSrcPtr ++;
+ NvDestPtr ++;
+ }
+
+ return(ESUCCESS);
+}
diff --git a/private/ntos/nthals/halalpha/eisaprof.c b/private/ntos/nthals/halalpha/eisaprof.c
new file mode 100644
index 000000000..71350f4f6
--- /dev/null
+++ b/private/ntos/nthals/halalpha/eisaprof.c
@@ -0,0 +1,517 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ eisaprof.c
+
+Abstract:
+
+ This module handles the Profile Counter and all Profile counter functions
+ for the standard EISA interval timer.
+
+Author:
+
+ Jeff McLeman (mcleman) 05-June-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+ Rod Gamache [DEC] 9-Mar-1993
+ Fix profile clock.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "halprof.h"
+
+//
+// Define global data.
+//
+
+//
+// Values used for Profile Clock
+//
+
+// Convert the interval to rollover count for 8254 timer. Since
+// the 8254 counts down a 16 bit value at the clock rate of 1.193 MHZ,
+// the computation is:
+//
+// RolloverCount = (Interval * 0.0000001) * (1193 * 1000000)
+// = Interval * .1193
+// = Interval * 1193 / 10000
+
+#define PROFILE_INTERVAL 1193
+#define PROFILE_INTERVALS_PER_100NS 10000/1193
+#define MIN_PROFILE_TICKS 4
+#define MAX_PROFILE_TICKS 0x10000 // 16 bit counter (zero is max)
+
+//
+// Since the profile timer interrupts at a frequency of 1.193 MHZ, we
+// have .1193 intervals each 100ns. So we need a more reasonable value.
+// If we compute the timer based on 1600ns intervals, we get 16 * .1193 or
+// about 1.9 ticks per 16 intervals.
+//
+// We round this to 2 ticks per 1600ns intervals.
+//
+
+#define PROFILE_TIMER_1600NS_TICKS 2
+
+//
+// Default Profile Interval to be about 1ms.
+//
+
+ULONG HalpProfileInterval = PROFILE_TIMER_1600NS_TICKS * PROFILE_INTERVALS_PER_100NS * 10000 / 16; // ~1ms
+
+//
+// Default Number of Profile Clock Ticks per sample
+//
+
+ULONG HalpNumberOfTicks = 1;
+
+//
+// Define the profile interrupt object.
+//
+
+PKINTERRUPT HalpProfileInterruptObject;
+
+//
+// Declare profile interrupt handler.
+//
+
+BOOLEAN
+HalpProfileInterrupt(
+ PKSERVICE_ROUTINE InterruptRoutine,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Function prototypes.
+//
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+//
+// Function definitions.
+//
+
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval = HalpProfileInterval * HalpNumberOfTicks;
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the profiler by setting initial values and connecting
+ the profile interrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the interface type of the bus on which the
+ profiler will be connected.
+
+ BusNumber - Supplies the number of the bus on which the profiler will
+ be connected.
+
+ BusInterruptLevel - Supplies the bus interrupt level to connect the
+ profile interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ KAFFINITY Affinity;
+ KIRQL Irql;
+ ULONG Vector;
+
+ //
+ // Get the interrupt vector and synchronization Irql.
+ //
+
+ Vector = HalGetInterruptVector( Eisa,
+ 0,
+ 0,
+ 0,
+ &Irql,
+ &Affinity );
+
+ IoConnectInterrupt( &HalpProfileInterruptObject,
+ (PKSERVICE_ROUTINE)HalpProfileInterrupt,
+ NULL,
+ NULL,
+ Vector,
+ Irql,
+ Irql,
+ Latched,
+ FALSE,
+ Affinity,
+ FALSE );
+
+ return;
+}
+
+
+BOOLEAN
+HalpProfileInterrupt(
+ PKSERVICE_ROUTINE InterruptRoutine,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an interrupt generated by
+ the profile timer. Its function is to acknowlege the interrupt and
+ transfer control to the standard system routine to update the
+ system profile time.
+
+Arguments:
+
+ InterruptRoutine - not used.
+
+ ServiceContext - not used.
+
+ TrapFrame - Supplies a pointer to the trap frame for the profile interrupt.
+
+Returned Value:
+
+ None
+
+--*/
+{
+
+ //
+ // See if profiling is active
+ //
+
+ if ( HAL_PCR->ProfileCount ) {
+
+ //
+ // Check to see if the interval has expired
+ // If it has then call the kernel routine for profile
+ // and reset the count, else return.
+
+
+ if ( !(--HAL_PCR->ProfileCount) ) {
+
+ KeProfileInterrupt( TrapFrame );
+ HAL_PCR->ProfileCount = HalpNumberOfTicks;
+
+ }
+ }
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (ProfileSource == ProfileTime)
+ return(TRUE);
+ else
+ return(FALSE);
+}
+
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ if (ProfileSource != ProfileTime)
+ return(STATUS_NOT_IMPLEMENTED);
+
+ //
+ // Set the interval.
+ //
+
+ *Interval = HalSetProfileInterval(*Interval);
+
+ //
+ // We're done.
+ //
+
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ HalpProfileInterval = (Interval/16) * PROFILE_TIMER_1600NS_TICKS;
+
+ HalpProfileInterval = ( HalpProfileInterval < MIN_PROFILE_TICKS ) ?
+ MIN_PROFILE_TICKS : HalpProfileInterval;
+
+ return HalpProfileInterval * PROFILE_INTERVALS_PER_100NS;
+}
+
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource != ProfileTime)
+ return;
+
+ //
+ // Assume that we only need 1 clock tick before we collect data
+ //
+
+ HalpNumberOfTicks = 1;
+
+ if ( HalpProfileInterval > MAX_PROFILE_TICKS ) {
+
+ HalpNumberOfTicks = HalpProfileInterval / (MAX_PROFILE_TICKS / 4);
+ HalpNumberOfTicks = 4 * HalpNumberOfTicks;
+ HalpProfileInterval = MAX_PROFILE_TICKS / 4;
+
+ }
+
+ //
+ // Set current profile count and interval.
+ //
+
+ HAL_PCR->ProfileCount = HalpNumberOfTicks;
+
+ PIC_PROFILER_ON(HalpProfileInterval);
+
+ return;
+}
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource != ProfileTime)
+ return;
+
+ //
+ // Clear the current profile count and turn off the profiler timer.
+ //
+
+ HAL_PCR->ProfileCount = 0;
+
+ PIC_PROFILER_OFF();
+
+ return;
+}
diff --git a/private/ntos/nthals/halalpha/eisasup.c b/private/ntos/nthals/halalpha/eisasup.c
new file mode 100644
index 000000000..4f907fa1d
--- /dev/null
+++ b/private/ntos/nthals/halalpha/eisasup.c
@@ -0,0 +1,1477 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ eisasup.c
+
+Abstract:
+
+ The module provides the platform-independent
+ EISA bus support for Alpha systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+ Miche Baker-Harvey (miche) 13-May-1992
+ Jeff McLeman (DEC) 1-Jun-1992
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+
+//
+// Define save area for ESIA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// This value indicates if Eisa DMA is supported on this system.
+//
+
+BOOLEAN HalpEisaDma;
+
+
+VOID
+HalpEisaInitializeDma(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize DMA support for Eisa/Isa systems.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Determine if Eisa DMA is supported.
+ //
+
+ HalpEisaDma = FALSE;
+
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2, 0x55);
+ DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2);
+
+ if (DataByte == 0x55) {
+ HalpEisaDma = TRUE;
+ }
+}
+
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the device.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+ UCHAR DataByte;
+
+ useChannel = TRUE;
+
+ //
+ // Support for ISA local bus machines:
+ // If the driver is a Master but really does not want a channel since it
+ // is using the local bus DMA, just don't use an ISA channel.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->DmaChannel > 7) {
+
+ useChannel = FALSE;
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length. Limit the maximum transfer to 64K.
+ //
+
+#define MAXIMUM_ISA_MAP_REGISTER (__64K >> PAGE_SHIFT)
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength) + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = HalpAllocateAdapter();
+
+ if (adapterObject == NULL) {
+ return(NULL);
+ }
+
+ if (useChannel == TRUE) {
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Establish the base va used to program the DMA controller.
+ //
+
+ adapterObject->AdapterBaseVa = adapterBaseVa;
+
+ }
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (DeviceDescriptor->Master) {
+ adapterObject->MasterDevice = TRUE;
+ } else {
+ adapterObject->MasterDevice = FALSE;
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (useChannel == FALSE) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (HalpEisaDma) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ //
+ // Save the extended mode in the adapter.
+ // Then write the extended mode value for this channel.
+ //
+
+ adapterObject->ExtendedMode = *((PDMA_EXTENDED_MODE)&extendedMode);
+
+ WRITE_PORT_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (DeviceDescriptor->Master == FALSE) {
+
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpMapEisaTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG LogicalAddress,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to perform the actual programming of the
+ DMA controllers to perform a transfer for Eisa/Isa systems.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+ LogicalAddress - Supplies the logical address of the transfer.
+
+Return Value:
+
+ Returns a boolean identifying if the operation was successful.
+
+--*/
+
+{
+ KIRQL Irql;
+ UCHAR adapterMode;
+ PUCHAR bytePointer;
+ UCHAR dataByte;
+ ULONG logicalAddress;
+ ULONG transferLength;
+
+ logicalAddress = LogicalAddress;
+ transferLength = Length;
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+//jnfix - this code not in Jensen
+ if( ((PDMA_EISA_MODE)&adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, disable the request and return.
+ //
+
+ if( AdapterObject->AdapterNumber == 1 ){
+
+ //
+ // Request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR( &dmaControl->SingleMask,
+ (UCHAR)(DMA_CLEARMASK | AdapterObject->ChannelNumber) );
+
+ } else {
+
+ //
+ // Request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR( &dmaControl->SingleMask,
+ (UCHAR)(DMA_CLEARMASK | AdapterObject->ChannelNumber) );
+
+ }
+
+ return TRUE;
+
+ }
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ }
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MapAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpEisaDma) {
+
+ //
+ // Write the high page register with zero value. This enable a
+ // special mode which allows ties the page register and base
+ // count into a single 24 bit address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpEisaDma) {
+
+ //
+ // Write the high page register with zero value. This enable
+ // a special mode which allows ties the page register and base
+ // count into a single 24 bit address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MapAdapter->SpinLock, Irql);
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpFlushEisaAdapter(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For EISA systems
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+{
+
+ BOOLEAN masterDevice;
+ KIRQL Irql;
+
+ masterDevice = AdapterObject->MasterDevice;
+
+ KeAcquireSpinLock( &AdapterObject->MapAdapter->SpinLock, &Irql );
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (masterDevice == FALSE) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ KeReleaseSpinLock( &AdapterObject->MapAdapter->SpinLock, Irql );
+
+ return TRUE;
+
+}
+
+ULONG
+HalpReadEisaDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MapAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->MapAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // If this is a 16 bit dma the multiply the count by 2.
+ //
+
+ if (AdapterObject->Width16Bits) {
+
+ count *= 2;
+
+ }
+
+ return(count);
+
+}
+
+#if !defined(AXP_FIRMWARE)
+
+ULONG
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset into data to begin access.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts pResourceList to keep it in the bounds of the EISA bus
+ resources.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ LARGE_INTEGER li64k, li4g;
+
+ li64k.QuadPart = 0xffff;
+ li4g.QuadPart = 0xffffffff;
+
+ HalpAdjustResourceListUpperLimits (
+ pResourceList,
+ li64k, // Bus supports up to I/O port 0xFFFF
+ li4g, // Bus supports up to memory 0xFFFFFFFF
+ 15, // Bus supports up to 15 IRQs
+ 7 // Bus supports up to Dma channel 7
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts pResourceList to keep it in the bounds of ISA bus
+ resources.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ LARGE_INTEGER li64k, limem;
+
+ li64k.QuadPart = 0xffff;
+ limem.QuadPart = 0xffffff;
+
+ HalpAdjustResourceListUpperLimits (
+ pResourceList,
+ li64k, // Bus supports up to I/O port 0xFFFF
+ limem, // Bus supports up to memory 0xFFFFFF
+ 15, // Bus supports up to 15 IRQs
+ 7 // Bus supports up to Dma channel 7
+ );
+
+ return STATUS_SUCCESS;
+}
+#endif // AXP_FIRMWARE
diff --git a/private/ntos/nthals/halalpha/environ.c b/private/ntos/nthals/halalpha/environ.c
new file mode 100644
index 000000000..3831214a5
--- /dev/null
+++ b/private/ntos/nthals/halalpha/environ.c
@@ -0,0 +1,952 @@
+//smjfix - This code needs to be made MP safe if it isn't being called
+// by MP safe code.
+//jwlfix - It's currently being called by the kernel (ex, actually) in
+// an MP-safe fashion, and by config during phase 1 (?) of
+// bootstrapping the system.
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ environ.c
+
+Abstract:
+
+ This module implements the ARC firmware Environment Variable functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.11.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+
+Revision History:
+
+ James Livingston 94.05.17
+
+ Fix a coding error that caused NVRAM to get trashed in the attempt
+ to update a nearly full environment variable space.
+
+ Steve Jenness 93.12.20
+
+ The firmware still requires the naked checksum set and check
+ routines. Add them back in under the AXP_FIRMWARE conditional
+ until the jxenvir.c in the firmware and the environ.c files
+ are rationalized.
+
+ Steve Jenness. 93.12.17
+
+ Reduce the reads and writes to the NVRAM part. Some parts are
+ slow to access (especially on writes). Do NVRAM access only when
+ really necessary. Remove use of HalpCopyNVRamBuffer because it is
+ too difficult to make generically fast (put more intelligence
+ in higher code instead).
+
+ Steve Brooks. 6-Oct 1993 remove all platform and device specific references
+
+ These routines have been restructured to be platform and device
+ independant. All calls access the NVRAM via the calls
+ HalpReadNVRamBuffer, HalpWriteNVRamBuffer, and HalpCopyNVRamBuffer
+
+ Jeff McLeman (DEC) 31-Jul-1992 modify for Jensen
+
+--*/
+
+#include "halp.h"
+#include "environ.h"
+
+#include "arccodes.h"
+
+//
+// Static data.
+//
+
+UCHAR Environment[LENGTH_OF_ENVIRONMENT];
+ULONG EnvironmentChecksum;
+BOOLEAN EnvironmentValid = FALSE;
+
+UCHAR OutputString[MAXIMUM_ENVIRONMENT_VALUE];
+PCONFIGURATION Configuration;
+
+//
+// Routine prototypes.
+//
+
+ARC_STATUS
+HalpReadAndChecksumEnvironment (
+ );
+
+ARC_STATUS
+HalpWriteAndChecksumEnvironment (
+ );
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT length,
+ OUT PCHAR Buffer
+ );
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ );
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ );
+
+#if defined(AXP_FIRMWARE)
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ );
+
+ARC_STATUS
+HalpEnvironmentSetChecksum (
+ VOID
+ );
+
+#endif //AXP_FIRMWARE
+
+#ifdef AXP_FIRMWARE
+
+#pragma alloc_text(DISTEXT, HalpReadAndChecksumEnvironment )
+#pragma alloc_text(DISTEXT, HalpWriteAndChecksumEnvironment )
+#pragma alloc_text(DISTEXT, HalGetEnvironmentVariable )
+#pragma alloc_text(DISTEXT, HalSetEnvironmentVariable )
+#pragma alloc_text(DISTEXT, HalpFindEnvironmentVariable )
+#pragma alloc_text(DISTEXT, HalpEnvironmentCheckChecksum )
+#pragma alloc_text(DISTEXT, HalpEnvironmentSetChecksum )
+
+#endif // AXP_FIRMWARE
+
+
+ARC_STATUS
+HalpReadAndChecksumEnvironment(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the part of the NVRAM containing the environment
+ variables into a memory buffer. It checksums the data as read.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS - checksum is good.
+ EIO - checksum is bad.
+
+--*/
+
+{
+ PUCHAR BufChar;
+ ULONG Index;
+ ULONG Checksum1, Checksum2;
+
+#ifndef EISA_PLATFORM
+ UCHAR Nvram[LENGTH_OF_ENVIRONMENT+16];
+#endif // EISA_PLATFORM
+
+ //
+ // Read checksum of environment data from the NVRAM.
+ // For non eisa machines we have only one checksum for the whole nvram.
+ // And it is stored in Checksum
+ //
+
+ HalpReadNVRamBuffer(
+ (PUCHAR)&Checksum2,
+#ifdef EISA_PLATFORM
+ &((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum2[0],
+#else // EISA_PLATFORM
+ &((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum[0],
+#endif // EISA_PLATFORM
+ 4);
+
+ //
+ // If the environment data stored in the buffer is already valid,
+ // short-circuit the NVRAM read.
+ //
+
+ if (EnvironmentValid == TRUE) {
+ if (Checksum2 == EnvironmentChecksum) {
+ return ESUCCESS;
+ }
+ }
+
+#ifdef EISA_PLATFORM
+ //
+ // Read the NVRAM environment data into the buffer.
+ //
+
+ HalpReadNVRamBuffer(
+ &Environment[0],
+ &((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Environment[0],
+ LENGTH_OF_ENVIRONMENT);
+
+ //
+ // Form checksum of data read from NVRAM.
+ //
+
+ BufChar = &Environment[0];
+ Checksum1 = 0;
+ for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
+ Checksum1 += *BufChar++;
+ }
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+ } else {
+ EnvironmentValid = TRUE;
+ EnvironmentChecksum = Checksum1;
+ return ESUCCESS;
+ }
+#else // EISA_PLATFORM
+
+ //
+ // Read the NVRAM into Nvram.
+ //
+
+ HalpReadNVRamBuffer( &Nvram[0],
+ NVRAM_CONFIGURATION,
+ LENGTH_OF_ENVIRONMENT + 16 );
+
+ //
+ // Form checksum of data read from NVRAM.
+ //
+
+ BufChar = &Nvram[0];
+ Checksum1 = 0;
+ for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT+16; Index++ ) {
+ Checksum1 += *BufChar++;
+ }
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+ } else {
+ EnvironmentValid = TRUE;
+ EnvironmentChecksum = Checksum1;
+
+ //
+ // Nvram checksum was ok. Save the read Environment part of NVRAM
+ // in global Environment[].
+ //
+ BufChar = &Environment[0];
+ for( Index = 16; Index < LENGTH_OF_ENVIRONMENT+16; Index++ ) {
+ *BufChar++ = Nvram[Index];
+ }
+
+ return ESUCCESS;
+ }
+#endif // EISA_PLATFORM
+}
+
+
+ARC_STATUS
+HalpWriteAndChecksumEnvironment (
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the environment data back to the NVRAM, calculates
+ a new checksum, and stores the checksum.
+
+ N.B. - For this method of rewriting the environment variables to be
+ effective (minimal NVRAM access and quick overall), the
+ HalpWriteNVRamBuffer is assumed to do block access and to
+ suppress writes it doesn't need to do.
+
+ N.B. - To allow the HalpWriteNVRamBuffer to suppress writes, the new data
+ should have as many bytes in common with the current NVRAM
+ contents as possible. For example, the environment variables
+ should not be reordered unless needed.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS - NVRAM write succeeded.
+ EIO - NVRAM write failed.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Checksum;
+ KIRQL OldIrql;
+ PUCHAR BufChar;
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ //
+ // Form checksum from new NVRAM data.
+ //
+
+ Checksum = 0;
+
+ BufChar = &Environment[0];
+ for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
+ Checksum += *BufChar++;
+ }
+
+#ifndef EISA_PLATFORM
+ {
+ UCHAR TempBuffer[16];
+ HalpReadNVRamBuffer( TempBuffer, (PUCHAR)NVRAM_CONFIGURATION, 16 );
+ for ( Index = 0 ; Index < 16; Index++ ) {
+ Checksum += TempBuffer[ Index ];
+ }
+ }
+#endif // !EISA_PLATFORM
+
+ //
+ // Write environment variables to NVRAM.
+ //
+
+ HalpWriteNVRamBuffer(
+ &((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Environment[0],
+ &Environment[0],
+ LENGTH_OF_ENVIRONMENT);
+
+ //
+ // Write environment checksum.
+ //
+
+ HalpWriteNVRamBuffer(
+#ifdef EISA_PLATFORM
+ &((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum2[0],
+#else // EISA_PLATFORM
+ &((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum[0],
+#endif // EISA_PLATFORM
+ (PUCHAR)&Checksum,
+ 4);
+
+ EnvironmentChecksum = Checksum;
+ EnvironmentValid = TRUE;
+
+ KeLowerIrql(OldIrql);
+
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the non-volatile ram for
+ Variable, and if found returns a pointer to a zero terminated string that
+ contains the value, otherwise a NULL pointer is returned.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+ Length - Supplies the length of the value buffer in bytes
+
+ Buffer - Supplies a pointer to a buffer that will recieve the
+ environment variable.
+
+Return Value:
+
+ ESUCCESS - Buffer contains the zero terminated string value of Variable.
+ ENOENT - The variable doesn't exist in the environment.
+ ENOMEM - The variable exists, but the value is longer than Length.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG Index;
+ ARC_STATUS Status;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to synchronize
+ //
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ //
+ // If checksum is wrong, or the variable can't be found, return NULL.
+ //
+
+ if ((HalpReadAndChecksumEnvironment() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+ Status = ENOENT;
+ } else {
+
+ //
+ // Copy value to an output string, break on zero terminator
+ // or string max.
+ //
+
+ NvChars = &Environment[ValueIndex];
+ for ( Index = 0 ; Index < length ; Index += 1 ) {
+ if ( (*Buffer++ = *NvChars++) == 0 ) {
+ break;
+ }
+ }
+
+ if (Index == length) {
+ Status = ENOMEM;
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Lower IRQL back to where it was
+ //
+
+ KeLowerIrql(OldIrql);
+
+ return Status;
+}
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets Variable (not case sensitive) to Value.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+ Value - Supplies a zero terminated string containing an environment
+ variable value.
+
+Return Value:
+
+ ESUCCESS - The set completed successfully
+ ENOSPC - No space in NVRAM for set operation.
+ EIO - Invalid Checksum.
+
+--*/
+
+{
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ PUCHAR TopOfEnvironment;
+ PCHAR String;
+ PUCHAR NvChars;
+ LONG Count;
+ CHAR Char;
+ KIRQL OldIrql;
+
+ //
+ // Raise Irql to Synchronize
+ //
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ //
+ // If checksum is wrong, return EIO;
+ //
+
+ if (HalpReadAndChecksumEnvironment() != ESUCCESS) {
+ KeLowerIrql(OldIrql);
+ return EIO;
+ }
+
+//
+//smjfix - examine the boundary condition where the environment space
+// is exactly filled.
+
+ //
+ // Determine the top of the environment space by looking for the first
+ // non-null character from the top.
+ //
+
+ TopOfEnvironment = &Environment[LENGTH_OF_ENVIRONMENT-1];
+
+ do {
+ Char = *TopOfEnvironment;
+
+ } while ( Char == 0 && (--TopOfEnvironment > Environment) );
+
+ //
+ // Adjust TopOfEnvironment to the first new character, unless environment
+ // space is empty, or the environment is exactly full. In the latter
+ // case, the new value MUST fit into the space taken by the old.
+ //
+
+ if (TopOfEnvironment != Environment
+ && TopOfEnvironment < &Environment[LENGTH_OF_ENVIRONMENT-2]) {
+ TopOfEnvironment += 2;
+ }
+
+ //
+ // Handle the case where the content of the NVRAM has been corrupted
+ // such that the last character in the environment is non-zero.
+ //
+
+ Count = &Environment[LENGTH_OF_ENVIRONMENT-1] - TopOfEnvironment;
+ if (Count < 0) {
+ KeLowerIrql(OldIrql);
+ return ENOSPC;
+ }
+
+
+ //
+ // Check to see if the variable already has a value.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex)
+ == ESUCCESS) {
+ ULONG SizeOfValue = strlen(Value);
+
+ if (SizeOfValue == strlen(&Environment[ValueIndex])) {
+
+ //
+ // Overwrite the current variable in place.
+ //
+
+ RtlMoveMemory(&Environment[ValueIndex],
+ Value,
+ SizeOfValue);
+ //
+ // Suppress the append of the variable to the end of the
+ // environment variable data.
+ //
+
+ *Value = 0;
+
+ } else {
+
+ //
+ // Count free space, starting with the free area at the top and
+ // adding the old variable value.
+ //
+
+ for ( NvChars = &Environment[ValueIndex];
+ NvChars <= TopOfEnvironment;
+ NvChars++ ) {
+
+ Char = *NvChars;
+ if ( Char == 0 )
+ break;
+ Count++;
+ }
+
+ //
+ // Determine if free area is large enough to handle new value, if
+ // not return error.
+ //
+
+ for ( String = Value ; *String != 0 ; String++ ) {
+ if (Count-- == 0) {
+ KeLowerIrql(OldIrql);
+ return ENOSPC;
+ }
+ }
+
+ //
+ // Move ValueIndex to the end of the value and compress strings.
+ //
+
+ do {
+ Char = Environment[ValueIndex++];
+ } while( Char != 0 );
+
+ Count = TopOfEnvironment - &Environment[ValueIndex];
+ RtlMoveMemory(&Environment[VariableIndex],
+ &Environment[ValueIndex],
+ Count);
+
+ //
+ // Adjust new top of environment.
+ //
+
+ TopOfEnvironment = &Environment[VariableIndex+Count];
+
+ //
+ // Zero to the end.
+ //
+
+ Count = &Environment[LENGTH_OF_ENVIRONMENT] - TopOfEnvironment;
+ Char = 0;
+ while ( Count -- ) {
+ TopOfEnvironment[Count] = Char;
+ }
+ }
+
+ } else {
+
+ //
+ // Variable is new.
+ //
+
+ //
+ // Determine if free area is large enough to handle new value, if not
+ // return error.
+ //
+
+ //
+ // From the length of free space subtract new variable's length,
+ // Value's length and 2 chars, one for the '=' sign and one of the
+ // null terminator.
+ //
+
+ Count -= ( strlen(Variable) + strlen(Value) + 2 );
+
+ //
+ // Check if there is space to fit the new variable.
+ //
+
+ if (Count < 0) {
+ KeLowerIrql(OldIrql);
+ return ENOSPC;
+ }
+
+ }
+
+ //
+ // If Value is not zero, append the new variable and value.
+ //
+
+ if (*Value != 0) {
+
+ //
+ // Write new variable, converting to upper case.
+ //
+ while ( *Variable != 0 ) {
+
+ Char = ((*Variable >= 'a') && (*Variable <= 'z') ?
+ (*Variable - 'a' + 'A') : *Variable);
+
+ *TopOfEnvironment = Char;
+
+ Variable ++;
+ TopOfEnvironment ++;
+ }
+
+ //
+ // Write equal sign.
+ //
+
+ Char = '=';
+ *TopOfEnvironment++ = Char;
+
+ //
+ // Write new value.
+ //
+
+ for ( Count = 0; Value[Count] != 0; Count ++ )
+ ;
+
+ RtlMoveMemory(&TopOfEnvironment[0], Value, Count);
+
+ }
+
+ //
+ // Write the environment variables out to NVRAM and checksum it.
+ //
+
+ if (HalpWriteAndChecksumEnvironment() != ESUCCESS) {
+ KeLowerIrql(OldIrql);
+ return EIO;
+ }
+
+ //
+ // Lower Irql back to where it was
+ //
+
+ KeLowerIrql(OldIrql);
+
+
+ return ESUCCESS;
+
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the supplied NVRAM image
+ for the given Variable.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+ VariableIndex - Returned byte offset into Environment of the
+ Variable if found.
+ ValueIndex - Returned byte offset into Environment of the
+ value of the Variable if found.
+
+Return Value:
+
+ ESUCCESS - Variable found and indicies returned.
+ ENOENT - Variable not found.
+
+--*/
+
+{
+ PUCHAR String;
+ UCHAR Char;
+ ULONG Index;
+
+ //
+ // If Variable is null, return immediately.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ Index = 0;
+
+ while (TRUE) {
+
+ //
+ // Set string to beginning of Variable.
+ //
+
+ String = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of NVRAM.
+ //
+
+ while ( Index < LENGTH_OF_ENVIRONMENT ) {
+
+ //
+ // Convert to uppercase and break if mismatch.
+ //
+
+ Char = Environment[Index];
+
+ if ( Char != ((*String >= 'a') && (*String <= 'z') ?
+ (*String - 'a' + 'A') : *String) ) {
+ break;
+ }
+
+ String++;
+ Index++;
+ }
+
+ if ( Index == LENGTH_OF_ENVIRONMENT )
+ return ENOENT;
+
+ //
+ // Check to see if we're at the end of the string and the variable,
+ // which means a match.
+ //
+
+ Char = Environment[Index];
+ if ((*String == 0) && (Char == '=')) {
+ *ValueIndex = ++Index;
+ return ESUCCESS;
+ }
+
+ //
+ // Move index to the start of the next variable.
+ //
+
+ do {
+ Char = Environment[Index++];
+
+ if (Index >= LENGTH_OF_ENVIRONMENT) {
+ return ENOENT;
+ }
+
+ } while (Char != 0);
+
+ }
+}
+
+#if defined(AXP_FIRMWARE)
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the environment area checksum.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ UCHAR Char;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1, Checksum2;
+ BOOLEAN AllZeroBytes;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ AllZeroBytes = TRUE;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
+
+ HalpReadNVRamBuffer(&Char,NvChars++,1);
+ Checksum1 += Char;
+ if (Char != 0) {
+ AllZeroBytes = FALSE;
+ }
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+#ifdef EISA_PLATFORM
+ HalpReadNVRamBuffer((PCHAR)&Checksum2,&NvConfiguration->Checksum2[0],4);
+#else // EISA_PLATFORM
+ HalpReadNVRamBuffer((PCHAR)&Checksum2,&NvConfiguration->Checksum[0],4);
+#endif // EISA_PLATFORM
+
+ //
+ // We return an error condition if the Checksum does not match the sum
+ // of all the protected bytes, *or* if all the protected bytes are zero.
+ // The latter check covers the condition of a completely zeroed NVRAM;
+ // such a condition would appear to have a valid checksum.
+ //
+ // We do not use a better checksum algorithm because the pain of
+ // orchestrating a change in the existing SRM consoles (which read our
+ // stored Nvram information for various purposes) has been deemed to be
+ // too high.
+ //
+
+ if ((Checksum1 != Checksum2) || (AllZeroBytes == TRUE)) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+}
+
+
+ARC_STATUS
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the environment area checksum.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ UCHAR Char;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum;
+ KIRQL OldIrql;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum = 0;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
+
+ for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
+ HalpReadNVRamBuffer(&Char, NvChars ++, 1);
+ Checksum += Char;
+ }
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Write environment checksum.
+ //
+
+ if (
+#ifdef EISA_PLATFORM
+ HalpWriteNVRamBuffer((PCHAR)NvConfiguration->Checksum2, (PCHAR)&Checksum, 4)
+#else // EISA_PLATFORM
+ HalpWriteNVRamBuffer((PCHAR)NvConfiguration->Checksum, (PCHAR)&Checksum, 4)
+#endif // EISA_PLATFORM
+ != ESUCCESS ) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+
+ }
+}
+
+#endif //AXP_FIRMWARE
diff --git a/private/ntos/nthals/halalpha/environ.h b/private/ntos/nthals/halalpha/environ.h
new file mode 100644
index 000000000..8a1abc91c
--- /dev/null
+++ b/private/ntos/nthals/halalpha/environ.h
@@ -0,0 +1,167 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ environ.h
+
+Abstract:
+
+ This module contains definitions for environment variable support
+ under the HAL. (Parts taken from J. Derosa's FWP.H)
+
+Author:
+
+ Jeff McLeman (DEC) 17-Sep-1992
+
+Revision History:
+
+--*/
+
+
+
+//
+// Define the private configuration packet structure, which contains a
+// configuration component as well as pointers to the component's parent,
+// peer, child, and configuration data.
+//
+
+typedef struct _CONFIGURATION_PACKET {
+ CONFIGURATION_COMPONENT Component;
+ struct _CONFIGURATION_PACKET *Parent;
+ struct _CONFIGURATION_PACKET *Peer;
+ struct _CONFIGURATION_PACKET *Child;
+ PVOID ConfigurationData;
+} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET;
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ UCHAR Version;
+ UCHAR Revision;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+#ifdef EISA_PLATFORM
+//
+// Defines for the non-volatile configuration tables.
+//
+
+#define NV_NUMBER_OF_ENTRIES 40
+#define NV_LENGTH_OF_IDENTIFIER (1024 - (NV_NUMBER_OF_ENTRIES * 16) - 8)
+#define NV_LENGTH_OF_DATA (2048 -16)
+#define LENGTH_OF_ENVIRONMENT 1024
+#define LENGTH_OF_EISA_DATA 2044
+
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+#define MAX_NUMBER_OF_ENVIRONMENT_VARIABLES 40
+
+//
+// The non-volatile configuration table structure.
+//
+
+typedef struct _NV_CONFIGURATION {
+ COMPRESSED_CONFIGURATION_PACKET Packet[NV_NUMBER_OF_ENTRIES]; // 0 to 640-4
+ UCHAR Identifier[NV_LENGTH_OF_IDENTIFIER]; // 640 to (1K - 8 - 4)
+ ULONG Monitor; // 1K-8
+ ULONG Floppy; // 1K-4
+ ULONG Floppy2; // 1K
+ ULONG KeyboardType; // 1K+4
+ UCHAR Data[NV_LENGTH_OF_DATA]; // Unused space 1K+8 to 3K-8-4
+ UCHAR Checksum1[4]; // Data checksum 3K-8
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT]; // Env Variables 3K-4 to 4K-4-4
+ UCHAR Checksum2[4]; // Env checksum 4K-4
+ UCHAR EisaData[LENGTH_OF_EISA_DATA]; // Eisa Data (4K to 6K-4)
+ UCHAR Checksum3[4]; // EisaData checksum
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+//
+// Defines for the volatile configuration tables.
+// smd - Increased the number of entries, length of Identifier and length
+// of data.
+//
+
+#define NUMBER_OF_ENTRIES 200
+#define LENGTH_OF_IDENTIFIER (3*1024)
+#define LENGTH_OF_DATA 2048
+
+//
+// The volatile configuration table structure.
+//
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+ UCHAR EisaData[LENGTH_OF_EISA_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+#else // EISA_PLATFORM
+
+//
+// Defines for the Non-Volatile configuration tables.
+//
+// SMD - We have reduced the size of the NVRAM from 6K to 3K
+// If needed we could take a few bytes from ENVIRONMENT
+// since there is tons of empty space there.
+//
+
+#define LENGTH_OF_ENVIRONMENT ((3*1024) - 16 - 4)
+
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+#define MAXIMUM_NUMBER_OF_ENVIRONMENT_VARIABLES 28
+#define MAX_NUMBER_OF_ENVIRONMENT_VARIABLES 28
+//
+// The non-volatile configuration table structure.
+//
+
+typedef struct _NV_CONFIGURATION {
+ ULONG Monitor; //0
+ ULONG Floppy; //4
+ ULONG Floppy2; //8
+ ULONG KeyboardType; //12
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT]; //16 to (3K-4)
+ UCHAR Checksum[4];
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+//
+// Defines for the Volatile configuration tables.
+//
+
+#define NUMBER_OF_ENTRIES 40
+#define LENGTH_OF_IDENTIFIER (1024 - (NUMBER_OF_ENTRIES * 16))
+#define LENGTH_OF_DATA 2048
+
+//
+// The volatile configuration table structure.
+//
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+#endif // EISA_PLATFORM
+
+//
+// The value of HalpCMOSRamBase must be set at initialization:
+//
+#define NVRAM_CONFIGURATION HalpCMOSRamBase
diff --git a/private/ntos/nthals/halalpha/errframe.h b/private/ntos/nthals/halalpha/errframe.h
new file mode 100644
index 000000000..ced43eb08
--- /dev/null
+++ b/private/ntos/nthals/halalpha/errframe.h
@@ -0,0 +1,697 @@
+/*++
+
+Copyright (c) 1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ errframe.h
+
+Abstract:
+
+ Definitions for both the correctable and uncorrectable error
+ frames.
+
+Author:
+
+ Joe Notarangelo 10-Mar-1995
+ Chao Chen 24-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+0.1 28-Feb-1995 Joe Notarangelo Initial version.
+
+0.2 10-Mar-1995 Joe Notarangelo Incorporate initial review comments from
+ 6-Mar-95 review with: C. Chen, S. Jenness,
+ Bala, E. Rehm.
+
+0.3 24-Apr-1995 Chao Chen Made into .h file for inclusion by other
+ modules.
+
+0.4 16-Apr-1996 Gene Morgan Add fields to SystemError struct for PSU,
+ Wachdog events.
+
+--*/
+
+#ifndef ERRFRAME_H
+#define ERRFRAME_H
+
+#include "errplat.h"
+
+/*
+ *
+ * Common defines.
+ *
+ */
+
+#define ERROR_FRAME_VERSION 0x1
+
+#define UNIDENTIFIED 0x0
+#define MEMORY_SPACE 0x1
+#define IO_SPACE 0x2
+#define PROCESSOR_CACHE 0x2
+#define SYSTEM_CACHE 0x3
+#define PROCESSOR_MEMORY 0x4
+#define SYSTEM_MEMORY 0x5
+
+#define CACHE_ERROR_MASK 0x2
+#define MEMORY_ERROR_MASK 0x4
+
+#define BUS_DMA_READ 0x1
+#define BUS_DMA_WRITE 0x2
+#define BUS_DMA_OP 0x3
+#define BUS_IO_READ 0x4
+#define BUS_IO_WRITE 0x5
+#define BUS_IO_OP 0x6
+#define TLB_MISS_READ 0x7
+#define TLB_MISS_WRITE 0x8
+#define VICTIM_WRITE 0x9
+
+#define MAX_UNCORRERR_STRLEN 128
+
+#define ERROR_FRAME_SIGNATURE 0xE22F2F2A // ERRORFRA R=2 (18%16)
+
+/*
+ *
+ * Definitions for the correctable error frame.
+ *
+ */
+
+//
+// Correctable Error Flags
+//
+
+typedef struct _CORRECTABLE_FLAGS{
+
+ //
+ // Address space
+ // Unidentified: 00
+ // Memory Space: 01
+ // I/O Space: 10
+ // Reserved: 11
+ //
+
+ ULONGLONG AddressSpace: 2;
+
+ //
+ // Error Interpretation Validity.
+ //
+
+ ULONGLONG ServerManagementInformationValid: 1;
+ ULONGLONG PhysicalAddressValid: 1;
+ ULONGLONG ErrorBitMasksValid: 1;
+ ULONGLONG ExtendedErrorValid: 1;
+ ULONGLONG ProcessorInformationValid: 1;
+ ULONGLONG SystemInformationValid: 1;
+
+ //
+ // Memory Space Error Source:
+ //
+ // Unidentified: 000
+ // ProcessorCache: 010
+ // SystemCache: 011
+ // ProcessorMemory: 100
+ // SystemMemory: 101
+ //
+
+ ULONGLONG MemoryErrorSource: 4;
+
+ //
+ // Driver Actions.
+ //
+
+ ULONGLONG ScrubError: 1;
+
+ //
+ // Lost errors.
+ //
+
+ ULONGLONG LostCorrectable: 1;
+ ULONGLONG LostAddressSpace: 2;
+ ULONGLONG LostMemoryErrorSource: 4;
+
+} CORRECTABLE_FLAGS, *PCORRECTABLE_FLAGS;
+
+ //
+ // Description of CORRECTABLE_FLAG structure:
+ //
+ // AddressSpace
+ //
+ // Identifies the system address space that was the source of the
+ // correctable error.
+ //
+ // PhysicalAddressValid
+ //
+ // Indicates if the physical address in the CORRECTABLE_ERROR
+ // structure is valid. A value of 1 indicates the physical address
+ // is valid, a value of 0 indicates the physical address is not
+ // valid.
+ //
+ // ErrorBitMasksValid
+ //
+ // Indicates if the error bit mask fields in the CORRECTABLE_ERROR
+ // structure are valid. A value of 1 indicates the DataBitErrorMask
+ // and the CheckBitErrorMask are valid, a value of 0 indicates they
+ // are not valid.
+ //
+ // ExtendedErrorValid
+ //
+ // Indicates if the extended error information structure in the
+ // CORRECTABLE_ERROR structure is valid. A value of 1 indicates the
+ // extended error information structure is valid, a value of 0
+ // indicates that it is not.
+ //
+ // ProcessorInformationValid
+ //
+ // Indicates if the raw processor information pointer in the
+ // CORRECTABLE_ERROR structure is valid. A value of 1 indicates the
+ // processor information is valid, a value of 0 indicates it is not.
+ //
+ // SystemInformationValid
+ //
+ // Indicates if the raw system information pointer in the
+ // CORRECTABLE_ERROR structure is valid. A value of 1 indicates the
+ // system information is valid, a value of 0 indicates it is not.
+ //
+ // ServerManagementInformationValid
+ //
+ // Indicates that the server management information in the extended
+ // error information structure is valid. The server management
+ // information relays information about failed fans or high
+ // temperature in the system.
+ //
+ //
+ // MemoryErrorSource
+ //
+ // Identifies the source of a memory error as either main error
+ // or cache for either a system or processor.
+ //
+ // ScrubError
+ //
+ // Instructs the driver to scrub the correctable error. If the
+ // value is 1 the driver should scrub the error, if the value is
+ // 0 the driver must not scrub the error.
+ //
+ // LostCorrectable
+ //
+ // Identifies if a lost correctable error has been reported. A
+ // lost error is an error that reported by the hardware while
+ // correctable error handling for a previous error was in progress.
+ // A value of 1 indicates that a correctable error report was lost.
+ //
+ // LostAddressSpace
+ //
+ // Identifies the system address space that was the source of the
+ // correctable error. Valid only if LostCorrectable == 1.
+ //
+ // LostMemoryErrorSource
+ //
+ // Identifies the source of a memory error as either main error
+ // or cache for either a system or processor. Valid only if
+ // LostCorrectable == 1.
+ //
+
+//
+// Processor information.
+//
+
+typedef struct _PROCESSOR_INFO{
+
+ ULONG ProcessorType;
+ ULONG ProcessorRevision;
+ ULONG PhysicalProcessorNumber;
+ ULONG LogicalProcessorNumber;
+
+} PROCESSOR_INFO, *PPROCESSOR_INFO;
+
+ //
+ // Description of PROCESSOR_INFO structure:
+ //
+ // ProcessorType
+ //
+ // Identifies the type of processor running on the system
+ // (eg. 21064, 21066, 21164). Note that the type of processor
+ // is expected to be consistent across the system for MP machines.
+ //
+ // ProcessorRevision
+ //
+ // Identifies the revision number of the processor running on
+ // the system. Note that the revision is expected to be consistent
+ // across the system for MP machines.
+ //
+ // PhysicalProcessorNumber
+ //
+ // The physical processor number as numbered in the hardware
+ // specifications.
+ //
+ // LogicalProcessorNumber
+ //
+ // The logical processor number assigned to the processor by NT.
+ //
+
+//
+// System Information.
+//
+
+typedef struct _SYSTEM_INFORMATION{
+
+ UCHAR SystemType[8];
+ ULONG ClockSpeed;
+ ULONG OsRevisionId;
+ ULONG PalMajorVersion;
+ ULONG PalMinorVersion;
+ UCHAR FirmwareRevisionId[16];
+ ULONG SystemVariant;
+ ULONG SystemRevision;
+ UCHAR SystemSerialNumber[16];
+ ULONG ModuleVariant;
+ ULONG ModuleRevision;
+ ULONG ModuleSerialNumber;
+} SYSTEM_INFORMATION, *PSYSTEM_INFORMATION;
+
+ //
+ // Description of SYSTEM_INFORMATION structure:
+ //
+ // SystemType
+ //
+ // Identifies the type of system that reported the error
+ // (eg. "Sable", "Gamma"). The actual format and value of the
+ // SystemType string is system-specific.
+ //
+ // OsRevisionId
+ //
+ // A numeric value that identifies the OS revision executing
+ // on the system that reported the fault.
+ //
+ // PalRevisionId
+ //
+ // A numeric value that identifies the pal revision executing
+ // on the system that reported the fault.
+ //
+ // FirmwareRevisionId
+ //
+ // A numeric value that identifies the firmware revision executing
+ // on the system that reported the fault.
+ //
+ // SystemVariant
+ //
+ // A numeric value used to distinguish variants of the same system
+ // type. The values and their interpretation are system_specific.
+ //
+ // SystemRevision
+ //
+ // A numeric value used to distinguish revisions of the same system
+ // type. The values and their interpretation are system_specific.
+ //
+ //
+
+//
+// Extended Error Information.
+//
+
+typedef union _EXTENDED_ERROR{
+
+ struct{
+ struct{
+ ULONG CacheLevelValid: 1;
+ ULONG CacheBoardValid: 1;
+ ULONG CacheSimmValid: 1;
+ } Flags;
+ PROCESSOR_INFO ProcessorInfo;
+ ULONG CacheLevel;
+ ULONG CacheBoardNumber;
+ ULONG CacheSimm;
+ ULONG TransferType;
+ ULONG Reserved;
+ } CacheError;
+
+ struct{
+ struct{
+ ULONG MemoryBoardValid: 1;
+ ULONG MemorySimmValid: 1;
+ } Flags;
+ PROCESSOR_INFO ProcessorInfo;
+ ULONG MemoryBoard;
+ ULONG MemorySimm;
+ ULONG TransferType;
+ ULONG Reserved[2];
+ } MemoryError;
+
+ struct{
+ INTERFACE_TYPE Interface;
+ ULONG BusNumber;
+ PHYSICAL_ADDRESS BusAddress;
+ ULONG TransferType;
+ ULONG Reserved[5];
+ } IoError;
+
+ struct{
+ struct{
+ ULONG FanNumberValid: 1;
+ ULONG TempSensorNumberValid: 1;
+ ULONG PowerSupplyNumberValid: 1;
+ ULONG WatchDogExpiredValid: 1;
+ } Flags;
+ ULONG FanNumber;
+ ULONG TempSensorNumber;
+ ULONG PowerSupplyNumber;
+ ULONG WatchdogExpiration;
+ ULONG Reserved[5];
+ } SystemError;
+
+} EXTENDED_ERROR, *PEXTENDED_ERROR;
+
+ //
+ // Description of EXTENDED_ERROR union:
+ //
+ // The EXTENDED_ERROR union has different interpretation depending
+ // upon the AddressSpace and MemoryErrorSource fields of the
+ // CORRECTABLE_FLAGS structure according to the following table:
+ //
+ // 1. AddressSpace=MemorySpace
+ // MemoryErrorSource = 01x use CacheError structure
+ //
+ // 2. AddressSpace=MemorySpace
+ // MemoryErrorSource = 10x use MemoryError structure
+ //
+ // 3. AddressSpace=IoSpace use IoError
+ //
+ // 4. AddressSpace=Unidentified use SystemError
+ // MemoryErrorSource = 0x0 (note: ServerManagementInformationValid
+ // should be set)
+ //
+ //
+ // CacheError.Flags
+ //
+ // Identifies which fields of the CacheError structure are valid.
+ // CacheLevelValid = 1 indicates CacheLevel is valid.
+ // CacheBoardValid = 1 indicates CacheBoardNumber is valid.
+ // CacheSimmValid = 1 indicates CacheSimm is valid.
+ //
+ // CacheError.ProcessorInfo
+ //
+ // Identifies the processor associated with the error. Most
+ // frequently will identify the processor that experienced and
+ // reported the error. However, it is possible that the processor
+ // that is reporting has experienced the error from another
+ // processor's cache. This field is valid only if the
+ // MemoryErrorSource = 010 .
+ //
+ // CacheError.CacheLevel
+ //
+ // Identifies the level of the cache that caused the error. Primary
+ // caches are Level 1, Secondary are Level 2, etc.. This field
+ // only valid if CacheError.Flags.CacheLevelValid == 1.
+ //
+ // CacheError.CacheBoardNumber
+ //
+ // Identifies the board number of the cache that caused the error.
+ // This field only valid if
+ // CacheError.Flags.CacheBoardNumberValid == 1.
+ //
+ // CacheError.CacheSimm
+ //
+ // Identifies the Cache Simm that caused the error.
+ // This field only valid if CacheError.Flags.CacheSimmValid == 1.
+ //
+ //
+ // MemoryError.Flags
+ //
+ // Identifies which fields of the CacheError structure are valid.
+ // CacheLevelValid = 1 indicates CacheLevel is valid.
+ // CacheBoardValid = 1 indicates CacheBoardNumber is valid.
+ // CacheSimmValid = 1 indicates CacheSimm is valid.
+ //
+ // MemoryError.ProcessorInfo
+ //
+ // Identifies the processor associated with the error. Most
+ // frequently will identify the processor that experienced and
+ // reported the error. However, it is possible that the processor
+ // that is reporting has experienced the error from another
+ // processor's cache. This field is valid only if the
+ // MemoryErrorSource = 010 .
+ //
+ // MemoryError.MemoryBoardNumber
+ //
+ // Identifies the board number of the cache that caused the error.
+ // This field only valid if MemoryError.Flags.MemoryBoardValid == 1.
+ //
+ // MemoryError.MemorySimm
+ //
+ // Identifies the memory SIMM that caused the error.
+ // This field only valid if MemoryError.Flags.MemorySimmValid == 1.
+ //
+ //
+ // IoError.Interface
+ //
+ // Identifies the bus interface type (eg. PCI) of the bus that caused
+ // the correctable error.
+ //
+ // IoError.BusNumber
+ //
+ // Identifies the bus number of the bus that caused the correctable
+ // error.
+ //
+ // IoError.BusAddress
+ //
+ // Identifies the bus address of the bus that caused the correctable
+ // error.
+ //
+
+//
+// Correctable Error Frame.
+//
+
+typedef struct _CORRECTABLE_ERROR{
+
+ CORRECTABLE_FLAGS Flags;
+ ULONGLONG PhysicalAddress;
+ ULONGLONG DataBitErrorMask;
+ ULONGLONG CheckBitErrorMask;
+ EXTENDED_ERROR ErrorInformation;
+ PROCESSOR_INFO ReportingProcessor;
+ SYSTEM_INFORMATION System;
+ ULONG RawProcessorInformationLength;
+ PVOID RawProcessorInformation;
+ ULONG RawSystemInformationLength;
+ PVOID RawSystemInformation;
+ ULONG Reserved;
+
+} CORRECTABLE_ERROR, *PCORRECTABLE_ERROR;
+
+ //
+ // Description of CORRECTABLE_ERROR structure:
+ //
+ // Flags
+ //
+ // The flags describe the various aspects of the error report. The
+ // CORRECTABLE_FLAGS structure is described below.
+ //
+ // PhysicalAddress
+ //
+ // The physical CPU address of the quadword that caused the correctable
+ // error report. This value is optional, its validiity is indicated
+ // in the Flags.
+ //
+ // DataBitErrorMask
+ //
+ // A mask that describes which data bits in the corrected word were
+ // in error. A value of one in the mask indicates that the
+ // corresponding bit in the data word were in error.
+ //
+ // CheckBitErrorMask
+ //
+ // A mask that describes which check bits in the corrected word were
+ // in error. A value of one in the mask indicates that the
+ // corresponding bit in the check bits were in error.
+ //
+ // ErrorInformation
+ //
+ // A structure that desribes interpretation of the error. The values
+ // in the structure are optional, the EXTENDED_ERROR structure is
+ // described below.
+ //
+ // ReportingProcessor
+ //
+ // A structure that describes the processor type on the system and
+ // the processor that reported the error. PROCESSOR_INFO structure
+ // is described below.
+ //
+ // RawProcessorInformationLength
+ //
+ // The length of the raw processor error information structure in
+ // bytes.
+ //
+ // RawProcessorInformation
+ //
+ // A pointer to the raw processor error information structure. The
+ // definition of the structure is processor-specific. The definitions
+ // for the known processors is defined in Appendix A below.
+ //
+ // System
+ //
+ // A structure that describes the type of system for which the
+ // error was reported. SYSTEM_INFORMATION structure is described below.
+ //
+ // RawSystemInformationLength
+ //
+ // The length of the raw processor error information structure in
+ // bytes.
+ //
+ // RawSystemInformation
+ //
+ // A pointer to the raw system error information structure. The
+ // definition of the structure is system/ASIC-specific. The
+ // definitions for the known systems/ASICs is defined in Appendix B.
+ //
+ //
+
+
+/*
+ *
+ * Definitions for the uncorrectable error frame.
+ *
+ */
+
+//
+// Uncorrectable Error Flags.
+//
+
+typedef struct _UNCORRECTABLE_FLAGS{
+
+ //
+ // Address space
+ // Unidentified: 00
+ // Memory Space: 01
+ // I/O Space: 10
+ // Reserved: 11
+ //
+
+ ULONGLONG AddressSpace: 2;
+
+ //
+ // Error Interpretation Validity.
+ //
+
+ ULONGLONG ErrorStringValid: 1;
+ ULONGLONG PhysicalAddressValid: 1;
+ ULONGLONG ErrorBitMasksValid: 1;
+ ULONGLONG ExtendedErrorValid: 1;
+ ULONGLONG ProcessorInformationValid: 1;
+ ULONGLONG SystemInformationValid: 1;
+
+ //
+ // Memory Space Error Source:
+ //
+ // Unidentified: 000
+ // ProcessorCache: 010
+ // SystemCache: 011
+ // ProcessorMemory: 100
+ // SystemMemory: 101
+ //
+
+ ULONGLONG MemoryErrorSource: 4;
+
+} UNCORRECTABLE_FLAGS, *PUNCORRECTABLE_FLAGS;
+
+ //
+ // The extended error information, processor information and system
+ // information structures are identical for correctable and uncorrectable
+ // errors. The rules for printing the failing FRU are also identical
+ // to the rules for the correctable errors.
+ //
+
+//
+// Uncorrectable Error Frame.
+//
+
+typedef struct _UNCORRECTABLE_ERROR{
+
+ UNCORRECTABLE_FLAGS Flags;
+ CHAR ErrorString[MAX_UNCORRERR_STRLEN];
+ ULONGLONG PhysicalAddress;
+ ULONGLONG DataBitErrorMask;
+ ULONGLONG CheckBitErrorMask;
+ EXTENDED_ERROR ErrorInformation;
+ PROCESSOR_INFO ReportingProcessor;
+ SYSTEM_INFORMATION System;
+ ULONG RawProcessorInformationLength;
+ PVOID RawProcessorInformation;
+ ULONG RawSystemInformationLength;
+ PVOID RawSystemInformation;
+ ULONG Reserved;
+
+} UNCORRECTABLE_ERROR, *PUNCORRECTABLE_ERROR;
+
+
+/*
+ *
+ * Generic definitions for the error frame.
+ *
+ */
+
+//
+// Generic error frame.
+//
+
+typedef enum _FRAME_TYPE{
+ CorrectableFrame,
+ UncorrectableFrame
+} FRAME_TYPE, *PFRAME_TYPE;
+
+typedef struct _ERROR_FRAME{
+
+ ULONG Signature; // Needed to make sure that the buffer is infact
+ // an error frame.
+ ULONG LengthOfEntireErrorFrame;
+ FRAME_TYPE FrameType;
+ ULONG VersionNumber;
+ ULONG SequenceNumber;
+ ULONGLONG PerformanceCounterValue;
+
+ union {
+ CORRECTABLE_ERROR CorrectableFrame;
+ UNCORRECTABLE_ERROR UncorrectableFrame;
+ };
+
+} ERROR_FRAME, *PERROR_FRAME;
+
+ //
+ // Description of the generic error frame structure:
+ //
+ // FrameType
+ //
+ // Specify which frame type we have. Either correctable or
+ // uncorrectable.
+ //
+ // VersionNumber
+ //
+ // Defines the version of the error structure. Current version
+ // number = 1.
+ //
+ // SequenceNumber
+ //
+ // A number that identifies a particular error frame.
+ //
+ // PerformanceCounterValue
+ //
+ // The value of the system performance counter when the error was
+ // reported. The value is determined during error processing by the
+ // HAL and so may be captured significantly after the hardware
+ // detected the error. The value cannot be used for fine grained
+ // timing of when errors occurred but can be used for coarse grained
+ // timing and approximate timing.
+ //
+ // CorrectableFrame
+ //
+ // Shared common area for a correctable frame.
+ //
+ // UncorrectableFrame
+ //
+ // Shared common area for an uncorrectable frame.
+ //
+
+#endif //ERRFRAME_H
diff --git a/private/ntos/nthals/halalpha/errplat.h b/private/ntos/nthals/halalpha/errplat.h
new file mode 100644
index 000000000..99133ed2c
--- /dev/null
+++ b/private/ntos/nthals/halalpha/errplat.h
@@ -0,0 +1,774 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ errplat.h
+
+Abstract:
+
+ Definitions for the platform specific correctable and uncorrectable error
+ frames for processors and systems.
+
+Author:
+
+ Joe Notarangelo 10-Mar-1995
+ Chao Chen 24-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+0.1 28-Feb-1995 Joe Notarangelo Initial version.
+
+0.2 10-Mar-1995 Joe Notarangelo Incorporate initial review comments from
+ 6-Mar-95 review with: C. Chen, S. Jenness,
+ Bala, E. Rehm.
+
+0.3 24-Apr-1995 Chao Chen Made into .h file for inclusion by other
+ modules.
+
+0.4 Jun-July-1995 Bala Nagarajan Added Uncorrectable Error frames for
+ APECS, SABLE, GAMMA etc.
+--*/
+#ifndef ERRPLAT_H
+#define ERRPLAT_H
+
+/*
+ *
+ * Processor specific definitions for error frame.
+ *
+ */
+
+//
+// EV5:
+//
+
+//
+// Processor information structure for processor detected correctable read
+// on the EV5.
+//
+
+typedef struct PROCESSOR_EV5_CORRECTABLE{
+ ULONGLONG EiAddr;
+ ULONGLONG FillSyn;
+ ULONGLONG EiStat;
+ ULONGLONG BcConfig;
+ ULONGLONG BcControl;
+} PROCESSOR_EV5_CORRECTABLE, *PPROCESSOR_EV5_CORRECTABLE;
+
+//
+// Processor information structure for processor-detected uncorrectable errors
+// on the EV5.
+//
+
+typedef struct PROCESSOR_EV5_UNCORRECTABLE{
+ ULONGLONG IcPerrStat;
+ ULONGLONG DcPerrStat;
+ ULONGLONG ScStat;
+ ULONGLONG ScAddr;
+ ULONGLONG EiStat;
+ ULONGLONG BcTagAddr;
+ ULONGLONG EiAddr;
+ ULONGLONG FillSyn;
+ ULONGLONG BcConfig;
+ ULONGLONG BcControl;
+} PROCESSOR_EV5_UNCORRECTABLE, *PPROCESSOR_EV5_UNCORRECTABLE;
+
+
+//
+// EV4(5):
+//
+
+//
+// Processor information structure for processor detected correctable read
+// on the EV4(5).
+//
+
+typedef struct PROCESSOR_EV4_CORRECTABLE{
+ ULONGLONG BiuStat;
+ ULONGLONG BiuAddr;
+ ULONGLONG AboxCtl;
+ ULONGLONG BiuCtl;
+ ULONGLONG CStat; // a.k.a. DcStat for EV4
+} PROCESSOR_EV4_CORRECTABLE, *PPROCESSOR_EV4_CORRECTABLE;
+
+//
+// Processor information structure for processor detected uncorrectable errors
+// on the EV4(5).
+//
+
+typedef struct PROCESSOR_EV4_UNCORRECTABLE{
+ ULONGLONG BiuStat;
+ ULONGLONG BiuAddr;
+ ULONGLONG AboxCtl;
+ ULONGLONG BiuCtl;
+ ULONGLONG CStat; // a.k.a. DcStat for EV4
+ ULONGLONG BcTag;
+ ULONGLONG FillAddr;
+ ULONGLONG FillSyndrome;
+} PROCESSOR_EV4_UNCORRECTABLE, *PPROCESSOR_EV4_UNCORRECTABLE;
+
+
+//
+// LCA:
+//
+
+//
+// Processor information structure for processor detected correctable read
+// on the LCA.
+//
+
+typedef struct PROCESSOR_LCA_CORRECTABLE{
+ ULONG VersionNumber; // Version Number of this structure not the LCA.
+ ULONGLONG Esr;
+ ULONGLONG Ear;
+ ULONGLONG AboxCtl;
+ ULONG BankConfig0;
+ ULONG BankConfig1;
+ ULONG BankConfig2;
+ ULONG BankConfig3;
+ ULONG BankMask0;
+ ULONG BankMask1;
+ ULONG BankMask2;
+ ULONG BankMask3;
+ ULONG Car;
+ ULONG Gtr;
+} PROCESSOR_LCA_CORRECTABLE, *PPROCESSOR_LCA_CORRECTABLE;
+
+//
+// Processor information structure for processor detected uncorrectable errors
+// on the LCA.
+//
+
+typedef struct PROCESSOR_LCA_UNCORRECTABLE{
+ ULONG VersionNumber; // Version Number of this structure not the LCA.
+ ULONGLONG CStat; // a.k.a. DcStat for LCA4
+ ULONGLONG Esr;
+ ULONGLONG Ear;
+ ULONGLONG IocStat0;
+ ULONGLONG IocStat1;
+ ULONGLONG AboxCtl;
+ ULONGLONG MmCsr;
+ ULONGLONG BankConfig0;
+ ULONGLONG BankConfig1;
+ ULONGLONG BankConfig2;
+ ULONGLONG BankConfig3;
+ ULONGLONG BankMask0;
+ ULONGLONG BankMask1;
+ ULONGLONG BankMask2;
+ ULONGLONG BankMask3;
+ ULONGLONG Car;
+ ULONGLONG Gtr;
+} PROCESSOR_LCA_UNCORRECTABLE, *PPROCESSOR_LCA_UNCORRECTABLE;
+
+//
+// The generic raw processor frame.
+//
+
+typedef union _RAW_PROCESSOR_FRAME{
+
+ PROCESSOR_EV5_CORRECTABLE Ev5Correctable;
+ PROCESSOR_EV5_UNCORRECTABLE Ev5Uncorrectable;
+ PROCESSOR_EV4_CORRECTABLE Ev4Correctable;
+ PROCESSOR_EV4_UNCORRECTABLE Ev4Uncorrectable;
+ PROCESSOR_LCA_CORRECTABLE LcaCorrectable;
+ PROCESSOR_LCA_UNCORRECTABLE LcaUncorrectable;
+
+} RAW_PROCESSOR_FRAME, *PRAW_PROCESSOR_FRAME;
+
+/*
+ *
+ * System specific definitions for error frame.
+ *
+ */
+
+//
+// Cia:
+//
+
+//
+// Cia configuration information
+//
+
+typedef struct _CIA_CONFIGURATION{
+
+ ULONG CiaRev;
+ ULONG CiaCtrl;
+ ULONG Mcr;
+ ULONG Mba0;
+ ULONG Mba2;
+ ULONG Mba4;
+ ULONG Mba6;
+ ULONG Mba8;
+ ULONG MbaA;
+ ULONG MbaC;
+ ULONG MbaE;
+ ULONG Tmg0;
+ ULONG Tmg1;
+ ULONG Tmg2;
+ ULONG CacheCnfg;
+ ULONG Scr;
+
+} CIA_CONFIGURATION, *PCIA_CONFIGURATION;
+
+//
+// Cia system detected correctable.
+//
+
+typedef struct _CIA_CORRECTABLE_FRAME{
+ ULONG VersionNumber; // Version Number of this structure.
+ ULONG CiaErr;
+ ULONG CiaStat;
+ ULONG CiaSyn;
+ ULONG MemErr0;
+ ULONG MemErr1;
+ ULONG PciErr0;
+ ULONG PciErr1;
+ ULONG PciErr2;
+ CIA_CONFIGURATION Configuration;
+
+} CIA_CORRECTABLE_FRAME, *PCIA_CORRECTABLE_FRAME;
+
+ //
+ // Note: it appears that the only correctable errors that are detected
+ // are:
+ //
+ // a. ECC on DMA Read (memory or cache)
+ // b. ECC on S/G TLB fill for DMA Read (memory or cache)
+ // c. ECC on DMA Write (probably CIA)
+ // d. ECC on S/G TLB fill for DMA write (memory or cache) (no PA?)
+ // e. I/O Write (ASIC problem) (no PA)
+ //
+
+//
+// Cia System-detected Uncorrectable Error
+//
+
+typedef struct _CIA_UNCORRECTABLE_FRAME{
+ ULONG VersionNumber; // Version Number of this structure.
+ ULONG CiaErr;
+ ULONG ErrMask;
+ ULONG CiaStat;
+ ULONG CiaSyn;
+ ULONG CpuErr0;
+ ULONG CpuErr1;
+ ULONG MemErr0;
+ ULONG MemErr1;
+ ULONG PciErr0;
+ ULONG PciErr1;
+ ULONG PciErr2;
+ CIA_CONFIGURATION Configuration;
+
+} CIA_UNCORRECTABLE_FRAME, *PCIA_UNCORRECTABLE_FRAME;
+
+//
+// Apecs:
+//
+
+//
+// Apecs Configuration Information
+//
+
+typedef struct _APECS_CONFIGURATION {
+ ULONG ApecsRev;
+ ULONG CGcr; // General Control register
+ ULONG CTer; // Tag Enable Register
+ ULONG CGtr; // Global Timer Register
+ ULONG CRtr; // refresh Timer register
+ ULONG CBank0; // Bank Configuration registers.
+ ULONG CBank1;
+ ULONG CBank2;
+ ULONG CBank3;
+ ULONG CBank4;
+ ULONG CBank5;
+ ULONG CBank6;
+ ULONG CBank7;
+ ULONG CBank8;
+
+} APECS_CONFIGURATION, *PAPECS_CONFIGURATION;
+
+//
+// Apecs based system-detected Correctable Error
+//
+
+typedef struct _APECS_CORRECTABLE_FRAME{
+ ULONG VersionNumber; // Version Number of this structure not the APECS.
+ ULONG EpicEcsr;
+ ULONG EpicSysErrAddr;
+ APECS_CONFIGURATION Configuration;
+
+} APECS_CORRECTABLE_FRAME, *PAPECS_CORRECTABLE_FRAME;
+
+ //
+ // Note: it appears that the only correctable errors that are detected
+ // are:
+ //
+ // a. ECC on DMA Read (memory)
+ // b. ECC on S/G TLB fill for DMA Read (memory)
+ //
+
+//
+// Apecs based system-detected Uncorrectable Error
+//
+
+typedef struct _APECS_UNCORRECTABLE_FRAME{
+ ULONG VersionNumber; // Version Number of this structure not the APECS.
+ ULONG EpicEcsr;
+ ULONG ComancheEdsr;
+ ULONG EpicPciErrAddr;
+ ULONG EpicSysErrAddr;
+ ULONG ComancheErrAddr;
+ APECS_CONFIGURATION Configuration;
+
+} APECS_UNCORRECTABLE_FRAME, *PAPECS_UNCORRECTABLE_FRAME;
+
+
+//
+// T2, T3, T4 Chipset error frame.
+//
+
+typedef struct _TX_ERROR_FRAME {
+ ULONGLONG Cerr1; // CBUS Error Register 1
+ ULONGLONG Cerr2; // CBUS Error Register 2
+ ULONGLONG Cerr3; // CBUS Error Register 3
+ ULONGLONG Perr1; // PCI Error Register 1
+ ULONGLONG Perr2; // PCI Error Register 2
+} TX_ERROR_FRAME, *PTX_ERROR_FRAME;
+
+
+//
+// Sable CPU Module configuration information.
+//
+
+typedef struct _SABLE_CPU_CONFIGURATION {
+ ULONGLONG Cbctl;
+ ULONGLONG Pmbx;
+ ULONGLONG C4rev;
+} SABLE_CPU_CONFIGURATION, *PSABLE_CPU_CONFIGURATION;
+
+//
+// Sable Memory Module configuration information.
+//
+
+typedef struct _SABLE_MEMORY_CONFIGURATION {
+ ULONGLONG Conifg; // CSR 3
+ ULONGLONG EdcCtl; // Error detection/correction control register
+ ULONGLONG StreamBfrCtl;
+ ULONGLONG RefreshCtl;
+ ULONGLONG CrdFilterCtl;
+} SABLE_MEMORY_CONFIGURATION, *PSABLE_MEMORY_CONFIGURATION;
+
+
+//
+// Sable System Configuration
+//
+
+typedef struct _SABLE_CONFIGURATION {
+ ULONG T2Revision; // Revision number of the T2 chipset.
+ ULONG NumberOfCpus; // Number of CPUs in the system.
+ ULONG NumberOfMemModules; // Number of memory modules in the system.
+ ULONGLONG T2IoCsr;
+ SABLE_CPU_CONFIGURATION CpuConfigs[4]; // 4 is the max CPU's
+ SABLE_MEMORY_CONFIGURATION MemConfigs[4]; // Maximum of 4 memory modules.
+} SABLE_CONFIGURATION, *PSABLE_CONFIGURATION;
+
+//
+// Sable CPU-module Error Information
+//
+
+typedef struct _SABLE_CPU_ERROR {
+
+ union {
+ struct {
+ ULONGLONG Bcue; // BCacheUncorrectableError
+ ULONGLONG Bcuea; // BCacheUncorrectableErrorAddress
+ } Uncorrectable;
+
+ struct {
+ ULONGLONG Bcce; // BCacheCorrectableError
+ ULONGLONG Bccea; // BCacheCorrectableErrorAddress
+ } Correctable;
+ };
+ ULONGLONG Dter; // Duplicate Tag Error Register
+ ULONGLONG Cberr; // CBUS2 Error (System Bus Error)
+ ULONGLONG Cbeal; // system bus error address register low.
+ ULONGLONG Cbeah; // system bus error address register high.
+} SABLE_CPU_ERROR, *PSABLE_CPU_ERROR;
+
+typedef struct _SABLE_MEMORY_ERROR {
+
+ ULONGLONG MemError; // CSR0 of memory module
+ ULONGLONG EdcStatus1;
+ ULONGLONG EdcStatus2;
+
+} SABLE_MEMORY_ERROR, *PSABLE_MEMORY_ERROR;
+
+//
+// Sable Correctable and Uncorrectable Error Frame.
+//
+
+typedef struct _SABLE_ERROR_FRAME {
+
+ SABLE_CPU_ERROR CpuError[4];
+ SABLE_MEMORY_ERROR MemError[4];
+ TX_ERROR_FRAME IoChipsetError;
+ SABLE_CONFIGURATION Configuration;
+} SABLE_UNCORRECTABLE_FRAME, *PSABLE_UNCORRECTABLE_FRAME,
+ SABLE_CORRECTABLE_FRAME, *PSABLE_CORRECTABLE_FRAME;
+
+
+
+//
+// Gamma CPU Module configuration information.
+//
+
+typedef struct _GAMMA_CPU_CONFIGURATION {
+ ULONGLONG Cbctl; // Cbus2 Control Register.
+ ULONGLONG Dtctr; // Duplicate Tag control register.
+ ULONGLONG Creg; // Rattler Control Register.
+} GAMMA_CPU_CONFIGURATION, *PGAMMA_CPU_CONFIGURATION;
+
+
+//
+// Gamma System Configuration
+//
+
+typedef struct _GAMMA_CONFIGURATION {
+ ULONG T2Revision; // Revision number of the T2 chipset.
+ ULONG NumberOfCpus; // Number of CPUs in the system.
+ ULONG NumberOfMemModules; // Number of memory modules in the system.
+ ULONGLONG T2IoCsr;
+ GAMMA_CPU_CONFIGURATION CpuConfigs[4]; // 4 is the max CPU's
+ SABLE_MEMORY_CONFIGURATION MemConfigs[4]; // Maximum of 4 memory modules.
+} GAMMA_CONFIGURATION, *PGAMMA_CONFIGURATION;
+
+//
+// Gamma CPU-module Error Information
+//
+
+typedef struct _GAMMA_CPU_ERROR {
+ ULONGLONG Esreg; // Error Summary
+ union {
+ struct {
+ ULONGLONG Evbuer; // EVB Uncorrectable Error
+ ULONGLONG Evbuear; // EVB Uncorrectable Error Address
+ } Uncorrectable;
+
+ struct {
+ ULONGLONG Evbcer; // EVB Correctable Error
+ ULONGLONG Evbcear; // EVB Correctable error address
+ } Correctable;
+ };
+ ULONGLONG Vear; // Victim Error Address
+ // valid only if bit 5 or bit 37
+ // of Evbuer is set.
+
+ ULONGLONG Dter; // Duplicate Tag Error Register
+ ULONGLONG Cberr; // CBUS2 Error (System Bus Error)
+ ULONGLONG Cbeal; // system bus error address register low.
+ ULONGLONG Cbeah; // system bus error address register high.
+} GAMMA_CPU_ERROR, *PGAMMA_CPU_ERROR;
+
+
+//
+// Gamma Correctable and Uncorrectable Error Frame.
+//
+
+typedef struct _GAMMA_ERROR_FRAME {
+
+ GAMMA_CPU_ERROR CpuError[4];
+ SABLE_MEMORY_ERROR MemError[4];
+ TX_ERROR_FRAME IoChipsetError;
+ GAMMA_CONFIGURATION Configuration;
+} GAMMA_UNCORRECTABLE_FRAME, *PGAMMA_UNCORRECTABLE_FRAME,
+ GAMMA_CORRECTABLE_FRAME, *PGAMMA_CORRECTABLE_FRAME;
+
+
+//
+// Rawhide Error Frame Definitions
+//
+
+//
+// CPU Daughter Card (CUD) Header
+//
+
+typedef struct _RAWHIDE_CUD_HEADER { // As Per Rawhide SPM
+ ULONG ActiveCpus; // (0x00)
+ ULONG HwRevision; // (0x04)
+ UCHAR SystemSN[10]; // (0x08-0x11) Same as FRU System Serial Number
+ UCHAR Reserved2[6]; // (0x12-0x17)
+ UCHAR ModuleSN[10]; // (0x18-0x21) Module (processor) S/N, if available
+ USHORT ModType; // (0x22)
+ ULONG Reserved3; // (0x24)
+ ULONG DisabledResources; // (0x28)
+ UCHAR SystemRev[4]; // (0x2c) Same as FRU System Revision Level?
+} RAWHIDE_CUD_HEADER, *PRAWHIDE_CUD_HEADER;
+
+
+
+//
+// IOD Error Frame Valid Bits
+//
+// Corresponds to bitfields of ValidBits in the Iod Error Frame
+//
+
+typedef union _IOD_ERROR_FRAME_VALID_BITS {
+ struct {
+ ULONG IodBaseAddrValid: 1; // <0>
+ ULONG WhoAmIValid: 1; // <1>
+ ULONG PciRevValid: 1; // <2>
+ ULONG CapCtrlValid: 1; // <3>
+ ULONG HaeMemValid: 1; // <4>
+ ULONG HaeIoValid: 1; // <5>
+ ULONG IntCtrlValid: 1; // <6>
+ ULONG IntReqValid: 1; // <7>
+ ULONG IntMask0Valid: 1; // <8>
+ ULONG IntMask1Valid: 1; // <9>
+ ULONG McErr0Valid: 1; // <10>
+ ULONG McErr1Valid: 1; // <11>
+ ULONG CapErrValid: 1; // <12>
+ ULONG PciErr1Valid: 1; // <13>
+ ULONG MdpaStatValid: 1; // <14>
+ ULONG MdpaSynValid: 1; // <15>
+ ULONG MdpbStatValid: 1; // <16>
+ ULONG MdpbSynValid: 1; // <17>
+ };
+ ULONG all;
+} IOD_ERROR_FRAME_VALID_BITS, *PIOD_ERROR_FRAME_VALID_BITS;
+
+//
+// IOD Error Frame
+//
+// N.B. Used in Uncorrectable *and* correctable error frames for
+// information on the IOD that recevied the machine check.
+// It is uses as well in MC Bus snapshot (for each IOD) and Iod Register
+// Subpacket.
+// As far as I'm concerned, they IOD information is the same in each case.
+// We can use the ValidBits field to optionally disable irrelevant
+// fields.
+//
+
+typedef struct _IOD_ERROR_FRAME {
+ ULONGLONG BaseAddress; // (0x00)
+ ULONG WhoAmI; // (0x08)
+ IOD_ERROR_FRAME_VALID_BITS ValidBits; // (0x0c)
+ ULONG PciRevision; // (0x10)
+ ULONG CapCtrl; // (0x14)
+ ULONG HaeMem; // (0x18)
+ ULONG HaeIo; // (0x1c)
+ ULONG IntCtrl; // (0x20)
+ ULONG IntReq; // (0x24)
+ ULONG IntMask0; // (0x28)
+ ULONG IntMask1; // (0x2c)
+ ULONG McErr0; // (0x30)
+ ULONG McErr1; // (0x34)
+ ULONG CapErr; // (0x38)
+ ULONG Reserved0; // (0x3c)
+ ULONG PciErr1; // (0x40)
+ ULONG MdpaStat; // (0x44)
+ ULONG MdpaSyn; // (0x48)
+ ULONG MdpbStat; // (0x4c)
+ ULONG MdpbSyn; // (0x50)
+ ULONG Reserved1[3]; // (0x54-0x5f)
+} IOD_ERROR_FRAME, *PIOD_ERROR_FRAME;
+
+
+//
+// Optional Snapshots for which headers or frames are defined below:
+// PCI Bus Snapshot
+// MC Bus Snapshot
+// Memory Size Frame
+// System Managment Frame
+// ESC Frame
+//
+
+//
+// Flags indicating which of the optional snapshots or frames are present
+// in a correctable or uncorrectable error frame
+//
+
+typedef union _RAWHIDE_ERROR_SUBPACKET_FLAGS {
+ struct {
+ ULONGLONG Reserved0: 10; // <0:9> Reserved
+ ULONGLONG SysEnvPresent : 1; // <10>
+ ULONGLONG MemSizePreset : 1; // <11>
+ ULONGLONG Reserved1: 8; // <12:19> Reserved
+ ULONGLONG McBusPresent: 1; // <20>
+ ULONGLONG GcdBusPresent: 1; // <21>
+ ULONGLONG Reserved2: 8; // <22:29> Reserved
+ ULONGLONG IodSubpacketPresent: 1; // <30>
+ ULONGLONG PciSnapshotPresent: 1; // <31>
+ ULONGLONG EscSubpacketPresent: 1; // <32>
+ ULONGLONG Reserved3: 7; // <33:39> Reserved
+ ULONGLONG Iod2SubpacketPresent: 1; // <40> ???
+ ULONGLONG Pci2SnapshotPresent: 1; // <41> ???
+ };
+ ULONGLONG all;
+} RAWHIDE_ERROR_SUBPACKET_FLAGS, *PRAWHIDE_ERROR_SUBPACKET_FLAGS;
+
+
+//
+// PCI Bus Snapshot Header
+//
+// Header is followed PCI_COMMON_CONFIG packets (256 bytes each) for each PCI
+// device present in the system. Therefore,
+// Length = sizeof (PCI_BUS_SNAPSHOT) + NumberOfNodes*sizeof(PCI_COMMON_CONFIG)
+//
+// N.B. PCI_COMMON_CONFIG is defined \nt\private\ntos\inc\pci.h
+//
+
+
+typedef struct _PCI_BUS_SNAPSHOT {
+ ULONG Length; // (0x00)
+ USHORT BusNumber; // (0x04)
+ USHORT NumberOfNodes; // (0x06)
+ //
+ // NumberOfNodes packets follow (0x08)
+ //
+} PCI_BUS_SNAPSHOT, *PPCI_BUS_SNAPSHOT;
+
+
+
+//
+// MC Bus Snapshot Header
+//
+// Header is followed a IOD_ERROR_FRAME for each IOD on the system;
+// Therefore,
+// Length = sizeof (MC_BUS_SNAPSHOT) + NumberOfIods*sizeof(IOD_ERROR_FRAME)
+//
+
+typedef struct _MC_BUS_SNAPSHOT {
+ ULONG Length; // (0x00)
+ ULONG NumberOfIods; // (0x04)
+ ULONGLONG ReportingCpuBaseAddr; // (0x08)
+
+ //
+ // NumberOfIods packets follow (0x10)
+ //
+
+} MC_BUS_SNAPSHOT, *PMC_BUS_SNAPSHOT;
+
+
+//
+// Memory Size Frame
+//
+
+typedef union _RAWHIDE_MEMORY_SIZE {
+ struct {
+ ULONGLONG MemorySize0: 8; // <0:7>
+ ULONGLONG MemorySize1: 8; // <8:15>
+ ULONGLONG MemorySize2: 8; // <16:23>
+ ULONGLONG MemorySize3: 8; // <24:31>
+ ULONGLONG Reserved: 24; // <32:55>
+ ULONGLONG MemorySize0Valid: 1; // <56>
+ ULONGLONG MemorySize1Valid: 1; // <57>
+ ULONGLONG MemorySize2Valid: 1; // <58>
+ ULONGLONG MemorySize3Valid: 1; // <59>
+ };
+ ULONGLONG all;
+} RAWHIDE_MEMORY_SIZE, *PRAWHIDE_MEMORY_SIZE;
+
+
+//
+// System Managment Frame
+//
+
+typedef struct _RAWHIDE_SYSTEM_MANAGEMENT_FRAME {
+ ULONGLONG SystemEnvironment; // (0x00)
+ ULONG Elcr2; // (0x08) (see IOD_ELCR2 in iod.h)
+ ULONG Reserved0; // (0x0c)
+} SYSTEM_MANAGEMENT_FRAME, *PSYSTEM_MANAGEMENT_FRAME;
+
+typedef union _RAWHIDE_SYSTEM_ENVIRONMENT {
+ struct {
+ ULONGLONG FanFailReg: 8; // <0:7> I2C Fain Fail Register
+ ULONGLONG SensorReg1: 8; // <8:15> I2C Sensor Register 1
+ ULONGLONG OpcControl: 8; // <16:23> I2C OPC Control
+ ULONGLONG SensorReg2: 8; // <24:31> I2C Sensor Register 2
+ ULONGLONG Reserved: 24; // <32:55> I2C Sensor Register 1
+ ULONGLONG FanFailValid: 1; // <56>
+ ULONGLONG SensorReg1Valid: 1; // <57>
+ ULONGLONG OpcControlValid: 1; // <58>
+ ULONGLONG SensorReg2Valid: 1; // <59>
+ };
+ ULONGLONG all;
+} RAWHIDE_SYSTEM_ENVIRONMENT, *PRAWHIDE_SYSTEM_ENVIRONMENT;
+
+
+//
+// ESC Frame
+//
+// This isn't just and ESC frame. EISA Id information is also contained herein.
+//
+// N.B. "index" refers to an indexed config ESC register accessed at index/data
+// ports 0x22/0x23.
+//
+
+
+typedef struct _ESC_FRAME {
+ UCHAR Id[4]; // (0x00) "ESC\0"
+ ULONG ByteCount; // (0x04) ???
+ UCHAR EscId; // (0x08) ESC ID Register (index 0x02)
+ UCHAR Filler0[7]; // (0x09-0x0f)
+ UCHAR Rid; // (0x0c) Revision Id (index 0x08)
+ UCHAR Filler1[3]; // (0x0d-0x0f)
+ UCHAR ModeSel; // (0x10) Mode Select Reg (index 0x40)
+ UCHAR Filler2[3]; // (0x11-0x13)
+ UCHAR EisaId[4]; // (0x14-0x17) EisaId of devices in EISA Slots
+ UCHAR SgRba; // (0x18) S-G Reloate Base Addr Reg (index 57)
+ UCHAR Filler3[3]; // (0x19-0x1b)
+ UCHAR Pirq[4]; // (0x1c-0x1f) PIRQ Route Ctrl (index 0x60-0x63)
+ UCHAR NmiSc; // (0x20) NMI Status & Ctrl (port 0x61)
+ UCHAR Filler4[3]; // (0x21-0x23)
+ UCHAR NmiEsc; // (0x24) NMI Ext. Status & Ctrl (port 0x461)
+ UCHAR Filler5[3]; // (0x25-0x27)
+ UCHAR LEisaMg; // (0x28) Last EISA Master Granted (port 0x464)
+ UCHAR Filler6[3]; // (0x29-0x2b)
+} ESC_FRAME, *PESC_FRAME;
+
+
+//
+// Rawhide Correctable (Soft) Error Frame
+// Rawhide Uncorrectable (Hard) Error Frame
+//
+
+#define RAWHIDE_UNCORRECTABLE_FRAME_REVISION 0x10 // V1.0
+#define RAWHIDE_CORRECTABLE_FRAME_REVISION 0x10 // V1.0
+
+typedef struct _RAWHIDE_UNCORRECTABLE_FRAME {
+ ULONG Revision; // (0x00)
+ ULONG WhoAmI; // (0x04)
+ RAWHIDE_ERROR_SUBPACKET_FLAGS ErrorSubpacketFlags; // (0x08)
+ RAWHIDE_CUD_HEADER CudHeader; // (0x10-0x4f)
+ MC_BUS_SNAPSHOT McBusSnapshot; // (0x50-0x5f)
+
+ //
+ // Uncorrectable Error Frame will have:
+ // a) two (Dodge) or four (Durango) IOD_ERROR_FRAMEs (0x60 - ???)
+ //
+ // b) Optional Error Subpackets as per ErrorSubpacketFlags
+ //
+
+} RAWHIDE_UNCORRECTABLE_FRAME, *PRAWHIDE_UNCORRECTABLE_FRAME;
+
+typedef struct _RAWHIDE_CORRECTABLE_FRAME {
+ ULONG Revision; // (0x00)
+ ULONG WhoAmI; // (0x04)
+ RAWHIDE_ERROR_SUBPACKET_FLAGS ErrorSubpacketFlags; // (0x08)
+ RAWHIDE_CUD_HEADER CudHeader; // (0x10-0x4f)
+ IOD_ERROR_FRAME IodErrorFrame; // (0x50-0xaf)
+
+ //
+ // Correctable Error will always have only
+ // one IOD in the McBusSnapshot, that of the IOD with
+ // the correctable error.
+ //
+
+} RAWHIDE_CORRECTABLE_FRAME, *PRAWHIDE_CORRECTABLE_FRAME;
+
+
+#endif //ERRPLAT_H
diff --git a/private/ntos/nthals/halalpha/ev4cache.c b/private/ntos/nthals/halalpha/ev4cache.c
new file mode 100644
index 000000000..506dd581f
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4cache.c
@@ -0,0 +1,488 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ev4cache.c
+
+Abstract:
+
+ This file contains the routines for managing the caches on machines
+ based on the DECchip 21064 microprocessor.
+
+ EV4 has primary I and D caches of 8KB each, both write-through.
+ Any systems based on EV4 are expected to have an external backup cache
+ which is write-back, but it is also coherent with all DMA operations. The
+ primary caches are shadowed by the backup, and on a write hit, the
+ primary data (but not instruction) cache is invalidated.
+ Consequently, the routines to flush,sweep,purge,etc the data
+ stream are nops on EV4, but the corresponding routines for the
+ Istream must ensure that we cannot hit in the primary I cache
+ after a DMA operation.
+
+ EV4 has a write buffer which contains 4 32-byte entries, which
+ must be flushable before DMA operations. The MB instruction is
+ used to accomplish this.
+
+ There is no coloring support on EV4, so Color operations are
+ null. Zero page is unsupported because it has no users. Copy
+ page is not special because we lack coloring.
+
+ We had to make a philosophical decision about what interfaces to
+ support in this file. (Almost) none of the interfaces defined in
+ the HAL spec are actually supported in either the i386 or MIPS
+ code. The i386 stream has almost no cache support at all. The
+ Mips stream has cache support, but most routines also refer to
+ coloring. Should we use the Spec'ed interfaces, or the Mips
+ interfaces? I have elected the Mips interfaces because they are
+ in use, and we are stealing much of the Mips code which expects
+ these interfaces. Besides, the only change we might make is to
+ remove the coloring arguments, but they may be used on Alpha
+ machines at some future date.
+
+Author:
+
+ Miche Baker-Harvey (miche) 29-May-1992
+
+Revision History:
+
+
+ 13-Jul-1992 Jeff McLeman (mcleman)
+ use HalpMb to do a memory barrier. Also, alter code and use super
+ pages to pass to rtl memory routines.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ use HalpImb to call pal.
+
+ 06-Jul-1992 Jeff McLeman (mcleman)
+ Move routine KeFlushDcache into this module.
+ Use only one memory barrier in the KeFlushWriteBuffer
+ routine. This is because the PAL for the EVx will
+ make sure the proper write ordering is done in PAL mode.
+
+--*/
+ // Include files
+
+#include "halp.h"
+
+
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ );
+
+//
+// Cache and write buffer flush functions.
+//
+
+
+VOID
+HalChangeColorPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+/*++
+
+Routine Description:
+
+ This function changes the color of a page if the old and new colors
+ do not match. DECchip 21064-based machines do not have page coloring, and
+ therefore, this function performs no operation.
+
+Arguments:
+
+ NewColor - Supplies the page aligned virtual address of the
+ new color of the page to change.
+
+ OldColor - Supplies the page aligned virtual address of the
+ old color of the page to change.
+
+ pageFrame - Supplies the page frame number of the page that
+ is changed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is flushed.
+ PageFrame - Supplies the page frame number of the page that
+ is flushed.
+
+ Length - Supplies the length of the region in the page that is
+ flushed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+}
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+Routine Description:
+
+ This function purges (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalPurgeIcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function purges (invalidates) up to a page fo data from the
+ instruction cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+}
+
+VOID
+HalSweepDcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire data cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepDcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the data
+ cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the data cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the data cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire instruction cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+ return;
+}
+
+VOID
+HalSweepIcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the
+ instruction cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the instruction cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the instruction cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+
+}
+
+VOID
+KeFlushWriteBuffer (
+ VOID
+ )
+
+{
+ //
+ // We flush the write buffer by doing a series of memory
+ // barrier operations. It still isn't clear if we need
+ // to do two/four of them to flush the buffer, or if one
+ // to order the writes is suffcient
+ //
+
+ HalpMb;
+ return;
+}
+
+VOID
+KeFlushDcache (
+ IN BOOLEAN AllProcessors,
+ IN PVOID BaseAddress OPTIONAL,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(BaseAddress);
+ UNREFERENCED_PARAMETER(Length);
+
+ HalFlushDcache(AllProcessors);
+ return;
+}
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sweep (index/writeback/invalidate) the data cache.
+ //
+
+ HalSweepDcache();
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 8;
+}
diff --git a/private/ntos/nthals/halalpha/ev4int.c b/private/ntos/nthals/halalpha/ev4int.c
new file mode 100644
index 000000000..71a4c9dd1
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4int.c
@@ -0,0 +1,1013 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ev4int.c
+
+Abstract:
+
+ This module implements the support routines to enable/disable DECchip
+ 21064-specific interrupts.
+
+Author:
+
+ Joe Notarangelo 27-Sep-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+VOID
+HalpUpdate21064PriorityTable(
+ VOID
+ );
+
+VOID
+HalpCachePcrValues(
+ VOID
+ );
+
+
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the data structures for the 21064
+ interrupt enable/disable routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ EV4Irq Irq;
+
+ //
+ // Initialize each entry in the Irq Status Table.
+ //
+
+ for( Irq=Irq0; Irq<MaximumIrq; Irq++ ){
+ HAL_PCR->IrqStatusTable[Irq].Enabled = FALSE;
+ HAL_PCR->IrqStatusTable[Irq].Irql = PASSIVE_LEVEL;
+ HAL_PCR->IrqStatusTable[Irq].Vector = PASSIVE_VECTOR;
+ HAL_PCR->IrqStatusTable[Irq].Priority = 0;
+ }
+
+ HalpUpdate21064PriorityTable();
+
+ //
+ // Write IrqlMask table entries for the Software Subtable.
+ //
+
+ Index = IRQLMASK_SFW_SUBTABLE_21064;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = APC_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = APC_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR;
+
+ //
+ // Write the IrqlMask table entries for the Performance Counter Subtable.
+ //
+
+ Index = IRQLMASK_PC_SUBTABLE_21064;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC0_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR;
+
+ return;
+
+}
+
+VOID
+HalpUpdate21064PriorityTable(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function updates the Irql Mask Table in the PCR of the current
+ processor. It is called whenever an interrupt is enabled or disabled.
+ The source of the data used to update the table is the global
+ IrqStatusTable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG InterruptMask;
+ EV4Irq Irq;
+ KIRQL Irql;
+ ULONG IrqlMaskIndex;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Cycle through each entry of the interrupt mask table for the
+ // hardware entries. For each entry, compute the highest priority
+ // entry that could be asserted for the mask entry and is enabled.
+ // The priority is determined first by Irql level, higher Irql
+ // indicates higher priority, and then, if there are multiple
+ // enabled, asserted interrupts of the same Irql, by a relative
+ // priority that was assigned by the caller when the interrupt
+ // was enabled.
+ //
+
+ for( InterruptMask=0;
+ InterruptMask < IRQLMASK_HDW_SUBTABLE_21064_ENTRIES;
+ InterruptMask++ ){
+
+ Vector = PASSIVE_VECTOR;
+ Irql = PASSIVE_LEVEL;
+ Priority = 0;
+
+ //
+ // Check if each Irq is asserted and enabled for this interrupt
+ // mask.
+ //
+
+ for( Irq=Irq0; Irq<MaximumIrq; Irq++ ){
+ ULONG IrqMask = 1 << Irq;
+
+ if( (IrqMask & InterruptMask) &&
+ (HAL_PCR->IrqStatusTable[Irq].Enabled == TRUE) &&
+ (HAL_PCR->IrqStatusTable[Irq].Irql >= Irql) ){
+
+ //
+ // If the new Irq has a higher Irql than the highest
+ // currently selected or has a higher relative priority
+ // then this is the Irq to be selected if this mask
+ // pattern is selected.
+ //
+
+ if( (HAL_PCR->IrqStatusTable[Irq].Irql > Irql) ||
+ (HAL_PCR->IrqStatusTable[Irq].Priority > Priority) ){
+
+ Irql = HAL_PCR->IrqStatusTable[Irq].Irql;
+ Priority = HAL_PCR->IrqStatusTable[Irq].Priority;
+ Vector = HAL_PCR->IrqStatusTable[Irq].Vector;
+
+ }
+
+ }
+ }
+
+ IrqlMaskIndex = IRQLMASK_HDW_SUBTABLE_21064 + InterruptMask;
+ PCR->IrqlMask[IrqlMaskIndex].IrqlTableIndex = Irql;
+ PCR->IrqlMask[IrqlMaskIndex].IDTIndex = (USHORT)Vector;
+ }
+}
+
+VOID
+HalpDisable21064HardwareInterrupt(
+ IN ULONG Irq
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the interrupt connected to the specified Irq
+ pin on the 21064.
+
+Arguments:
+
+ Irq - Supplies the number of the Irq pin for the interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Irq ){
+
+ case Irq0:
+
+ IetEntry[IrqlIndex].Irq0Enable = 0;
+ break;
+
+ case Irq1:
+
+ IetEntry[IrqlIndex].Irq1Enable = 0;
+ break;
+
+ case Irq2:
+
+ IetEntry[IrqlIndex].Irq2Enable = 0;
+ break;
+
+ case Irq3:
+
+ IetEntry[IrqlIndex].Irq3Enable = 0;
+ break;
+
+ case Irq4:
+
+ IetEntry[IrqlIndex].Irq4Enable = 0;
+ break;
+
+ case Irq5:
+
+ IetEntry[IrqlIndex].Irq5Enable = 0;
+ break;
+
+
+ } //end switch( Irq )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Update the Irq status table and reflect the changes in the
+ // PCR IrqlMask table.
+ //
+
+ HAL_PCR->IrqStatusTable[Irq].Enabled = FALSE;
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpDisable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the indicated software interrupt level.
+
+Arguments:
+
+ Irql - Supplies the software interrupt level to disable (APC_LEVEL or
+ DISPATCH_LEVEL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+
+ switch( Irql ){
+
+ //
+ // APC Interrupt level.
+ //
+
+ case APC_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].ApcEnable = 0;
+ break;
+
+ //
+ // DPC Interrupt level.
+ //
+
+ case DISPATCH_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].DispatchEnable = 0;
+ IetEntry[APC_LEVEL].DispatchEnable = 0;
+ break;
+
+ //
+ // Unrecognized software interrupt level.
+ //
+
+ default:
+
+ NOTHING;
+
+#if HALDBG
+
+ DbgPrint( "HalpDisable21064SoftwareInterrupt, Bad software level= %x\n",
+ Irql );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+VOID
+HalpDisable21064PerformanceInterrupt(
+ IN ULONG Vector
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the specified performance counter interrupt.
+
+Arguments:
+
+ Vector - Supplies the interrupt vector number of the performance counter
+ interrupt which is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 0;
+ break;
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 0;
+ break;
+
+
+ } //end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisable21064CorrectableInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the correctable read error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ IetEntry[IrqlIndex].CorrectableReadEnable = 0;
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpEnable21064HardwareInterrupt (
+ IN ULONG Irq,
+ IN KIRQL Irql,
+ IN ULONG Vector,
+ IN UCHAR Priority
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Irq - Supplies the IRQ pin number of the interrupt that is enabled.
+
+ Irql - Supplies the Irql of the interrupting source.
+
+ Vector - Supplies the interrupt vector for the enabled interrupt.
+
+ Priority - Supplies the relative priority of the interrupt in comparison
+ with other Irqs of the same Irql.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Irq ){
+
+ case Irq0:
+
+ IetEntry[IrqlIndex].Irq0Enable = 1;
+ break;
+
+ case Irq1:
+
+ IetEntry[IrqlIndex].Irq1Enable = 1;
+ break;
+
+ case Irq2:
+
+ IetEntry[IrqlIndex].Irq2Enable = 1;
+ break;
+
+ case Irq3:
+
+ IetEntry[IrqlIndex].Irq3Enable = 1;
+ break;
+
+ case Irq4:
+
+ IetEntry[IrqlIndex].Irq4Enable = 1;
+ break;
+
+ case Irq5:
+
+ IetEntry[IrqlIndex].Irq5Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Populate the interrupt status table and then update the Irql Mask
+ // table.
+ //
+
+ HAL_PCR->IrqStatusTable[Irq].Enabled = TRUE;
+ HAL_PCR->IrqStatusTable[Irq].Vector = Vector;
+ HAL_PCR->IrqStatusTable[Irq].Irql = Irql;
+ HAL_PCR->IrqStatusTable[Irq].Priority = Priority;
+
+ HalpUpdate21064PriorityTable();
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+VOID
+HalpEnable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This routine enables the indicated software interrupt level.
+
+Arguments:
+
+ Irql - Supplies the software interrupt level to enable (APC_LEVEL or
+ DISPATCH_LEVEL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+
+ switch( Irql ){
+
+ //
+ // APC Interrupt level.
+ //
+
+ case APC_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].ApcEnable = 1;
+ break;
+
+ //
+ // DPC Interrupt level.
+ //
+
+ case DISPATCH_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].DispatchEnable = 1;
+ IetEntry[APC_LEVEL].DispatchEnable = 1;
+ break;
+
+ //
+ // Unrecognized software interrupt level.
+ //
+
+ default:
+
+ NOTHING;
+
+#if HALDBG
+
+ DbgPrint( "HalpEnable21064SoftwareInterrupt, Bad software level= %x\n",
+ Irql );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpEnable21064PerformanceInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified performance counter interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the performance counter interrupt that is
+ enabled.
+
+ Irql - Supplies the Irql of the performance counter interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 1;
+ break;
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpEnable21064CorrectableInterrupt (
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the correctable read error interrupt.
+
+Arguments:
+
+ Irql - Supplies the Irql of the correctable read error interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ IetEntry[IrqlIndex].CorrectableReadEnable = 1;
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+ULONG
+HalpGet21064PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified performance counter interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ *Irql = PROFILE_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_SECONDARY_VECTOR;
+
+ } //end switch( BusInterruptLevel )
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+
+}
+
+
+ULONG
+HalpGet21064CorrectableVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified correctable interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ //
+ // Get the correctable interrupt vector.
+ //
+
+ if (BusInterruptLevel == 5) {
+
+ //
+ // Correctable error interrupt was sucessfully recognized.
+ //
+
+ *Irql = DEVICE_LEVEL;
+ return CORRECTABLE_VECTOR;
+
+
+ } else {
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+ }
+}
+
diff --git a/private/ntos/nthals/halalpha/ev4ints.s b/private/ntos/nthals/halalpha/ev4ints.s
new file mode 100644
index 000000000..aaa06db87
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4ints.s
@@ -0,0 +1,272 @@
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// ev4ints.s
+//
+// Abstract:
+//
+// This module implements EV4-specific interrupt handlers.
+// (the performance counters)
+//
+// Author:
+//
+// John Vert (jvert) 15-Nov-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+#define PC0_SECONDARY_VECTOR 11
+#define PC1_SECONDARY_VECTOR 13
+#define PcProfileCount0 PcHalReserved+8
+#define PcProfileCount1 PcProfileCount0+4
+#define PcProfileCountReload0 PcProfileCount1+4
+#define PcProfileCountReload1 PcProfileCountReload0+4
+
+ .struct 0
+ .space 8 // reserved for alignment
+PrRa: .space 8 // space for return address
+PrFrameLength: //
+
+ SBTTL("Performance Counter 0 Interrupt")
+//++
+//
+// VOID
+// HalpPerformanceCounter0Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 0. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 0.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(HalpPerformanceCounter0Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount0(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload0(v0) // get the new tick count
+ stl t0, PcProfileCount0(v0) // reset the profile interval count
+
+ ldl a1, HalpProfileSource0
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount0(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end HalpPerformanceCounter0Interrupt
+
+
+ SBTTL("Performance Counter 1 Interrupt")
+//++
+//
+// VOID
+// HalpPerformanceCounter1Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 1. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 1.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(HalpPerformanceCounter1Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount1(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload1(v0) // get the new tick count
+ stl t0, PcProfileCount1(v0) // reset the profile interval count
+
+ ldl a1, HalpProfileSource1
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount1(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end HalpPerformanceCounter1Interrupt
+
+//++
+//
+// VOID
+// HalpWritePerformanceCounter(
+// IN ULONG PerformanceCounter,
+// IN BOOLEAN Enable,
+// IN ULONG MuxControl OPTIONAL,
+// IN ULONG EventCount OPTIONAL
+// )
+//
+// Routine Description:
+//
+// Write the specified microprocessor internal performance counter.
+//
+// Arguments:
+//
+// PerformanceCounter(a0) - Supplies the number of the performance counter
+// to write.
+//
+// Enable(a1) - Supplies a boolean that indicates if the performance
+// counter should be enabled or disabled.
+//
+// MuxControl(a2) - Supplies the mux control value which selects which
+// type of event to count when the counter is enabled.
+//
+// EventCount(a3) - Supplies the event interval when the counter is
+// enabled.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWritePerformanceCounter)
+
+ call_pal wrperfmon // write the counter
+
+ ret zero, (ra) // return
+
+ .end HalpWritePerformanceCounter
diff --git a/private/ntos/nthals/halalpha/ev4mchk.c b/private/ntos/nthals/halalpha/ev4mchk.c
new file mode 100644
index 000000000..57fe29312
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4mchk.c
@@ -0,0 +1,709 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev4mchk.c
+
+Abstract:
+
+ This module implements generalized machine check handling for
+ platforms based on the DECchip 21064 (EV4) microprocessor.
+
+Author:
+
+ Joe Notarangelo 14-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+#include "stdio.h"
+
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+VOID
+HalpDisplayLogout21064(
+ IN PLOGOUT_FRAME_21064 LogoutFrame );
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ );
+
+//
+// MAX_RETRYABLE_ERRORS is the number of times to retry machine checks before
+// just giving up.
+//
+
+#define MAX_RETRYABLE_ERRORS 32
+
+//
+// System-wide controls for machine check reporting.
+//
+
+ProcessorCorrectableDisable = FALSE;
+SystemCorrectableDisable = FALSE;
+MachineCheckDisable = FALSE;
+
+//
+//jnfix - temporary counts
+//
+
+ULONG CorrectableErrors = 0;
+ULONG RetryableErrors = 0;
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ )
+/*++
+
+Routine Description:
+
+ This function sets the enables that define which machine check
+ errors will be signaled by the processor.
+
+ N.B. - The system has the capability to ignore all machine checks
+ by indicating DisableMachineChecks = TRUE. This is intended
+ for debugging purposes on broken hardware. If you disable
+ this you will get no machine check no matter what error the
+ system/processor detects. Consider the consequences.
+
+Arguments:
+
+ DisableMachineChecks - Supplies a boolean which indicates if all
+ machine checks should be disabled and not
+ reported. (see note above).
+
+ DisableProcessorCorrectables - Supplies a boolean which indicates if
+ processor correctable error reporting
+ should be disabled.
+ DisableSystemCorrectables - Supplies a boolean which indicates if
+ system correctable error reporting
+ should be disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ProcessorCorrectableDisable = DisableProcessorCorrectables;
+ SystemCorrectableDisable = DisableSystemCorrectables;
+ MachineCheckDisable = DisableMachineChecks;
+
+ HalpUpdateMces( FALSE, FALSE );
+
+ return;
+}
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ )
+/*++
+
+Routine Description:
+
+ This function updates the state of the MCES internal processor
+ register.
+
+Arguments:
+
+ ClearMachineCheck - Supplies a boolean that indicates if the machine
+ check indicator in the MCES should be cleared.
+
+ ClearCorrectableError - Supplies a boolean that indicates if the
+ correctable error indicators in the MCES should
+ be cleared.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MCES Mces;
+
+ Mces.MachineCheck = ClearMachineCheck;
+ Mces.SystemCorrectable = ClearCorrectableError;
+ Mces.ProcessorCorrectable = ClearCorrectableError;
+ Mces.DisableProcessorCorrectable = ProcessorCorrectableDisable;
+ Mces.DisableSystemCorrectable = SystemCorrectableDisable;
+ Mces.DisableMachineChecks = MachineCheckDisable;
+
+ HalpWriteMces( Mces );
+
+}
+
+
+BOOLEAN
+HalMachineCheck (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This function fields machine check for 21064-based machines with
+ parity memory protection.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record for the
+ machine check. Included in the exception information
+ is the pointer to the logout frame.
+
+ ExceptionFrame - Supplies a pointer to the kernel exception frame.
+
+ TrapFrame - Supplies a pointer to the kernel trap frame.
+
+Return Value:
+
+ A value of TRUE is returned if the machine check has been
+ handled by the HAL. If it has been handled then execution may
+ resume at the faulting address. Otherwise, a value of FALSE
+ is returned.
+
+ N.B. - under some circumstances this routine may not return at
+ all.
+
+--*/
+
+{
+
+ PBIU_STAT_21064 BiuStat;
+ BOOLEAN Handled;
+ PLOGOUT_FRAME_21064 LogoutFrame;
+ PMCHK_STATUS MachineCheckStatus;
+ MCES Mces;
+ BOOLEAN UnhandledPlatformError = FALSE;
+
+ PUNCORRECTABLE_ERROR uncorrerr = NULL;
+ PPROCESSOR_EV4_UNCORRECTABLE ev4uncorr = NULL;
+
+
+ //
+ // This is a parity machine. If we receive a machine check it
+ // is uncorrectable. We will print the logout frame and then we
+ // will bugcheck.
+ //
+ // However, we will first check that the machine check is not
+ // marked as correctable. If the machine check is correctable it uses
+ // a differently formatted logout frame. We will ignore the frame
+ // for any machine check marked as correctable since it is an impossible
+ // condition on a parity machine.
+ //
+
+ MachineCheckStatus =
+ (PMCHK_STATUS)&ExceptionRecord->ExceptionInformation[0];
+
+ //
+ // Handle any processor correctable errors.
+ //
+
+ if( MachineCheckStatus->Correctable == 1 ){
+
+ //
+ // Log the error.
+ //
+ //jnfix - temporary code
+ // simply assume this was a fill ecc correctable for now, print
+ // a debug message periodically
+
+ CORRECTABLE_FRAME_21064 *CorrectableFrame;
+
+ CorrectableFrame =
+ (CORRECTABLE_FRAME_21064 *)ExceptionRecord->ExceptionInformation[1];
+
+ CorrectableErrors += 1;
+
+#if (DBG) || (HALDBG)
+
+ if( (CorrectableErrors % 32) == 0 ){
+ DbgPrint( "Correctable errors = %d, Error Address = 0x%016Lx\n",
+ CorrectableFrame->FillAddr );
+ }
+
+#endif //DBG || HALDBG
+
+ //
+ // Acknowledge receipt of the correctable error by clearing
+ // the error in the MCES register.
+ //
+
+ HalpUpdateMces( FALSE, TRUE );
+
+ return TRUE;
+ }
+
+ //
+ // Handle any retryable errors.
+ //
+
+ if( MachineCheckStatus->Retryable == 1 ){
+
+ //
+ // Increment the number of retryable machine checks.
+ //
+
+ RetryableErrors += 1;
+
+#if (DBG) || (HALDBG)
+
+ DbgPrint( "HAL Retryable Errors = %d\n", RetryableErrors );
+
+#endif //DBG || HALDBG
+
+ //
+ // We'll retry MAX_RETRYABLE_ERRORS times and then give up. We
+ // do this to avoid infinite retry loops.
+ //
+
+ if( RetryableErrors <= MAX_RETRYABLE_ERRORS ){
+
+ //
+ // Acknowledge receipt of the retryable machine check.
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ return TRUE;
+ }
+ }
+
+ //
+ // Capture the logout frame pointer.
+ //
+
+ LogoutFrame =
+ (PLOGOUT_FRAME_21064)ExceptionRecord->ExceptionInformation[1];
+
+ if(PUncorrectableError) {
+
+ //
+ // Fill in the processor specific uncorrectable error frame
+ //
+ uncorrerr = (PUNCORRECTABLE_ERROR)
+ &PUncorrectableError->UncorrectableFrame;
+
+ //
+ // first fill in some generic processor Information.
+ // For the Current (Reporting) Processor.
+ //
+ HalpGetProcessorInfo(&uncorrerr->ReportingProcessor);
+ uncorrerr->Flags.ProcessorInformationValid = 1;
+
+ ev4uncorr = (PPROCESSOR_EV4_UNCORRECTABLE)
+ uncorrerr->RawProcessorInformation;
+ }
+ if(ev4uncorr) {
+
+ ev4uncorr->BiuStat = ((ULONGLONG)LogoutFrame->BiuStat.all.HighPart <<
+ 32) | LogoutFrame->BiuStat.all.LowPart;
+
+ ev4uncorr->BiuAddr = ((ULONGLONG)LogoutFrame->BiuAddr.HighPart << 32) |
+ LogoutFrame->BiuAddr.LowPart;
+
+ ev4uncorr->AboxCtl = ((ULONGLONG)LogoutFrame->AboxCtl.all.HighPart <<
+ 32) | LogoutFrame->AboxCtl.all.LowPart;
+
+ ev4uncorr->BiuCtl = ((ULONGLONG)LogoutFrame->BiuCtl.HighPart << 32) |
+ LogoutFrame->BiuCtl.LowPart;
+
+ ev4uncorr->CStat = ((ULONGLONG)LogoutFrame->DcStat.all.HighPart <<
+ 32) | LogoutFrame->DcStat.all.LowPart;
+
+ ev4uncorr->BcTag = ((ULONGLONG)LogoutFrame->BcTag.all.HighPart <<
+ 32 ) | LogoutFrame->BcTag.all.LowPart;
+
+ ev4uncorr->FillAddr = ((ULONGLONG)LogoutFrame->FillAddr.HighPart <<
+ 32) | LogoutFrame->FillAddr.LowPart;
+
+ ev4uncorr->FillSyndrome =
+ ((ULONGLONG)LogoutFrame->FillSyndrome.all.HighPart << 32) |
+ LogoutFrame->FillSyndrome.all.LowPart;
+ }
+
+ //
+ // Check for any hard errors that cannot be dismissed.
+ // They are:
+ // Tag parity error
+ // Tag control parity error
+ // Multiple external errors
+ // Fill ECC error
+ // Fill parity error
+ // Multiple fill errors
+ //
+
+ BiuStat = (PBIU_STAT_21064)&LogoutFrame->BiuStat;
+
+ if( (BiuStat->bits.BcTperr == 1) ||
+ (BiuStat->bits.BcTcperr == 1) ||
+ (BiuStat->bits.Fatal1 == 1) ||
+ (BiuStat->bits.FillEcc == 1) ||
+ (BiuStat->bits.FillDperr == 1) ||
+ (BiuStat->bits.Fatal2 == 1) ) {
+
+ //
+ // set the flag to indicate that the processor information is valid.
+ //
+ uncorrerr->Flags.ProcessorInformationValid = 1;
+ uncorrerr->Flags.ErrorStringValid = 1;
+ sprintf(uncorrerr->ErrorString,"Uncorrectable Error From "
+ "Processor Detected");
+
+ //
+ // A serious, uncorrectable error has occured, under no circumstances
+ // can it be simply dismissed.
+ //
+
+ goto FatalError;
+
+ }
+
+//jnfix - dcache parity error checking for EV45?
+
+ //
+ // It is possible that the system has experienced a hard error and
+ // that nonetheless the error is recoverable. This is a system-specific
+ // decision - allow it to be handled as such.
+ //
+
+ UnhandledPlatformError = TRUE;
+ if( (Handled = HalpPlatformMachineCheck(
+ ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame )) == TRUE ){
+
+ //
+ // The system-specific code has handled the error. Dismiss
+ // the error and continue execution.
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ return TRUE;
+
+ }
+
+//
+// The system has experienced a fatal error that cannot be corrected.
+// Print any possible relevant information and crash the system.
+//
+// N.B. - In the future some of these fatal errors could be potential
+// recovered. Example, a user process gets a fatal error on one
+// of its pages - we kill the user process, mark the page as bad
+// and continue executing.
+//
+
+FatalError:
+
+ //
+ // Begin the error output if this is a processor error. If this is
+ // an unhandled platform error than that code is responsible for
+ // beginning the error output.
+ //
+
+ if( UnhandledPlatformError == FALSE ){
+
+ //
+ // Acquire ownership of the display. This is done here in case we take
+ // a machine check before the display has been taken away from the HAL.
+ // When the HAL begins displaying strings after it has lost the
+ // display ownership then the HAL will be careful not to scroll
+ // information off of the screen.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ }
+
+ //
+ // Display the EV4 logout frame.
+ //
+
+ HalpDisplayLogout21064( LogoutFrame );
+
+ //
+ // Bugcheck to dump the rest of the machine state, this will help
+ // if the machine check is software-related.
+ //
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ (ULONG)MachineCheckStatus->Correctable,
+ (ULONG)MachineCheckStatus->Retryable,
+ (ULONG)0,
+ (ULONG)PUncorrectableError );
+
+}
+
+#define MAX_ERROR_STRING 100
+
+VOID
+HalpDisplayLogout21064 (
+ IN PLOGOUT_FRAME_21064 LogoutFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This function displays the logout frame for a 21064.
+
+Arguments:
+
+ LogoutFrame - Supplies a pointer to the logout frame generated
+ by the 21064.
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ ULONG Index;
+ PKPRCB Prcb;
+ extern HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ sprintf( OutBuffer, "BIU_STAT : %016Lx BIU_ADDR: %016Lx\n",
+ BIUSTAT_ALL_21064( LogoutFrame->BiuStat ),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "FILL_ADDR: %016Lx FILL_SYN: %016Lx\n",
+ LogoutFrame->FillAddr.QuadPart,
+ FILLSYNDROME_ALL_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "DC_STAT : %016Lx BC_TAG : %016Lx\n",
+ DCSTAT_ALL_21064(LogoutFrame->DcStat),
+ BCTAG_ALL_21064(LogoutFrame->BcTag) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "ICCSR : %016Lx ABOX_CTL: %016Lx EXC_SUM: %016Lx\n",
+ ICCSR_ALL_21064(LogoutFrame->Iccsr),
+ ABOXCTL_ALL_21064(LogoutFrame->AboxCtl),
+ EXCSUM_ALL_21064(LogoutFrame->ExcSum) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "EXC_ADDR : %016Lx VA : %016Lx MM_CSR : %016Lx\n",
+ LogoutFrame->ExcAddr.QuadPart,
+ LogoutFrame->Va.QuadPart,
+ MMCSR_ALL_21064(LogoutFrame->MmCsr) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "HIRR : %016Lx HIER : %016Lx PS : %016Lx\n",
+ IRR_ALL_21064(LogoutFrame->Hirr),
+ IER_ALL_21064(LogoutFrame->Hier),
+ PS_ALL_21064(LogoutFrame->Ps) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "Waiting 15 seconds...\n");
+ HalDisplayString( OutBuffer );
+
+ for( Index=0; Index<1500; Index++)
+ KeStallExecutionProcessor( 10000 ); // ~15 second delay
+
+ sprintf( OutBuffer, "PAL_BASE : %016Lx \n",
+ LogoutFrame->PalBase.QuadPart );
+ HalDisplayString( OutBuffer );
+
+ //
+ // Print out interpretation of the error.
+ //
+
+ //
+ // First print the processor on which we saw the error
+ //
+
+ Prcb = PCR->Prcb;
+ sprintf( OutBuffer, "Error on processor number: %d\n",
+ HalpLogicalToPhysicalProcessor[Prcb->Number] );
+ HalDisplayString( OutBuffer );
+
+ //
+ // If we got a Data Cache Parity Error print a message on screen.
+ //
+
+ if( DCSTAT_DCPARITY_ERROR_21064(LogoutFrame->DcStat) ){
+ sprintf( OutBuffer, "Data Cache Parity Error.\n" );
+ HalDisplayString( OutBuffer );
+ }
+
+ //
+ // Check for tag control parity error.
+ //
+
+ if( BIUSTAT_TCPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer,
+ "Tag control parity error, Tag control: P: %1x D: %1x S: %1x V: %1x\n",
+ BCTAG_TAGCTLP_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLD_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLS_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLV_21064( LogoutFrame->BcTag ) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for tag parity error.
+ //
+
+ if( BIUSTAT_TPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer,
+ "Tag parity error, Tag: %x Parity: %1x\n",
+ BCTAG_TAG_21064(LogoutFrame->BcTag),
+ BCTAG_TAGP_21064(LogoutFrame->BcTag) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for hard error.
+ //
+
+ if( BIUSTAT_HERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Hard error acknowledge: BIU CMD: %x PA: %16Lx\n",
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for soft error.
+ //
+
+ if( BIUSTAT_SERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Soft error acknowledge: BIU CMD: %x PA: %16Lx\n",
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+
+ //
+ // Check for fill ECC errors.
+ //
+
+ if( BIUSTAT_FILLECC_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "ECC error: %s\n",
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\n",
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for fill Parity errors.
+ //
+
+ if( BIUSTAT_FILLDPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Parity error: %s\n",
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\n",
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for multiple hard errors.
+ //
+
+ if( BIUSTAT_FATAL1_21064(LogoutFrame->BiuStat) == 1 ){
+
+ HalDisplayString( "Multiple external/tag errors detected.\n" );
+
+ }
+
+ //
+ // Check for multiple fill errors.
+ //
+
+ if( BIUSTAT_FATAL2_21064(LogoutFrame->BiuStat) == 1 ){
+
+ HalDisplayString( "Multiple fill errors detected.\n" );
+
+ }
+
+
+ //
+ // return to caller
+ //
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halalpha/ev4mem.s b/private/ntos/nthals/halalpha/ev4mem.s
new file mode 100644
index 000000000..ab6815a91
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4mem.s
@@ -0,0 +1,146 @@
+// TITLE("EV4 Memory Operations")
+//++
+//
+// Copyright (c) 1994 Digital Equipment Corporation
+//
+// Module Name:
+//
+// ev4mem.s
+//
+// Abstract:
+//
+// This module implements EV4 memory operations that require assembly
+// language.
+//
+// Author:
+//
+// Joe Notarangelo 1-Jun-1994
+//
+// Environment:
+//
+// HAL, Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalZeroPage)
+
+ .set noreorder // hand scheduled
+
+#define ZERO_BLOCK_SIZE (256)
+#define ZERO_LOOPS (PAGE_SIZE/ZERO_BLOCK_SIZE)
+
+//
+// Map the page via the 43-bit super-page on EV4.
+//
+
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll a2, PAGE_SHIFT, t1 // physical address of page
+
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+ ldil t2, ZERO_LOOPS // set count of loops to run
+
+ bis t0, t1, t0 // set super-page enable + physical
+ bis zero, zero, zero // for branch alignment
+
+//
+// Zero the page in a loop, zeroing 256 bytes per iteration. This number
+// was chosen to tradeoff loop overhead versus the overhead of fetching
+// Icache blocks.
+//
+
+10:
+ stq zero, 0x00(t0) //
+ subl t2, 1, t2 // decrement the loop count
+
+ stq zero, 0x08(t0) //
+ stt f31, 0x10(t0) //
+
+ stq zero, 0x18(t0) //
+ stt f31, 0x20(t0) //
+
+ stq zero, 0x28(t0) //
+ stt f31, 0x30(t0) //
+
+ stq zero, 0x38(t0) //
+ stt f31, 0x40(t0) //
+
+ stq zero, 0x48(t0) //
+ stt f31, 0x50(t0) //
+
+ stq zero, 0x58(t0) //
+ stt f31, 0x60(t0) //
+
+ stq zero, 0x68(t0) //
+ stt f31, 0x70(t0) //
+
+ stq zero, 0x78(t0) //
+ stt f31, 0x80(t0) //
+
+ stq zero, 0x88(t0) //
+ stt f31, 0x90(t0) //
+
+ stq zero, 0x98(t0) //
+ stt f31, 0xa0(t0) //
+
+ stq zero, 0xa8(t0) //
+ stt f31, 0xb0(t0) //
+
+ bis t0, zero, t1 // copy base register
+ stq zero, 0xb8(t0) //
+
+ stq zero, 0xc0(t0) //
+ stt f31, 0xc8(t0) //
+
+ stq zero, 0xd0(t0) //
+ stt f31, 0xd8(t0) //
+
+ stq zero, 0xe0(t0) //
+ lda t0, 0x100(t0) // increment to next block
+
+ stq zero, 0xe8(t1) //
+ stt f31, 0xf0(t1) //
+
+ stt f31, 0xf8(t1) // use stt for dual issue with bne
+ bne t2, 10b // while count > 0
+
+ ret zero, (ra) // return
+
+
+ .set reorder //
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halalpha/ev4parit.c b/private/ntos/nthals/halalpha/ev4parit.c
new file mode 100644
index 000000000..bd9527680
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4parit.c
@@ -0,0 +1,336 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ev4parit.c
+
+Abstract:
+
+ This module implements machine check handling for machines with
+ parity memory protection that are based on the DECchip 21064
+ microprocessor.
+
+Author:
+
+ Joe Notarangelo 11-Feb-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+VOID
+HalpDisplayLogout21064( PLOGOUT_FRAME_21064 LogoutFrame );
+
+
+BOOLEAN
+HalMachineCheck (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This function fields machine check for 21064-based machines with
+ parity memory protection.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record for the
+ machine check. Included in the exception information
+ is the pointer to the logout frame.
+
+ ExceptionFrame - Supplies a pointer to the kernel exception frame.
+
+ TrapFrame - Supplies a pointer to the kernel trap frame.
+
+Return Value:
+
+ A value of TRUE is returned if the machine check has been
+ handled by the HAL. If it has been handled then execution may
+ resume at the faulting address. Otherwise, a value of FALSE
+ is returned.
+
+ N.B. - under some circumstances this routine may not return at
+ all.
+
+--*/
+
+{
+
+ PMCHK_STATUS MachineCheckStatus;
+
+ //
+ // This is a parity machine. If we receive a machine check it
+ // is uncorrectable. We will print the logout frame and then we
+ // will bugcheck.
+ //
+ // However, we will first check that the machine check is not
+ // marked as correctable. If the machine check is correctable it uses
+ // a differently formatted logout frame. We will ignore the frame
+ // for any machine check marked as correctable since it is an impossible
+ // condition on a parity machine.
+ //
+
+ MachineCheckStatus =
+ (PMCHK_STATUS)&ExceptionRecord->ExceptionInformation[0];
+
+ if( MachineCheckStatus->Correctable == 0 ){
+
+ HalpDisplayLogout21064(
+ (PLOGOUT_FRAME_21064)(ExceptionRecord->ExceptionInformation[1])
+ );
+
+ }
+
+ //
+ // Bugcheck to dump the rest of the machine state, this will help
+ // if the machine check is software-related.
+ //
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ (ULONG)MachineCheckStatus->Correctable,
+ (ULONG)MachineCheckStatus->Retryable,
+ 0,
+ 0 );
+
+}
+
+
+#define MAX_ERROR_STRING 100
+
+VOID
+HalpDisplayLogout21064 (
+ IN PLOGOUT_FRAME_21064 LogoutFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This function displays the logout frame for a 21064.
+
+Arguments:
+
+ LogoutFrame - Supplies a pointer to the logout frame generated
+ by the 21064.
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+
+ //
+ // Acquire ownership of the display. This is done here in case we take
+ // a machine check before the display has been taken away from the HAL.
+ // When the HAL begins displaying strings after it has lost the
+ // display ownership then the HAL will be careful not to scroll information
+ // off of the screen.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the machine state via the logout frame.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+
+ sprintf( OutBuffer, "BIU_STAT : %016Lx BIU_ADDR: %016Lx\n",
+ BIUSTAT_ALL_21064( LogoutFrame->BiuStat ),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "FILL_ADDR: %016Lx FILL_SYN: %016Lx\n",
+ LogoutFrame->FillAddr.QuadPart,
+ FILLSYNDROME_ALL_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "DC_STAT : %016Lx BC_TAG : %016Lx\n",
+ DCSTAT_ALL_21064(LogoutFrame->DcStat),
+ BCTAG_ALL_21064(LogoutFrame->BcTag) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "ICCSR : %016Lx ABOX_CTL: %016Lx EXC_SUM: %016Lx\n",
+ ICCSR_ALL_21064(LogoutFrame->Iccsr),
+ ABOXCTL_ALL_21064(LogoutFrame->AboxCtl),
+ EXCSUM_ALL_21064(LogoutFrame->ExcSum) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "EXC_ADDR : %016Lx VA : %016Lx MM_CSR : %016Lx\n",
+ LogoutFrame->ExcAddr.QuadPart,
+ LogoutFrame->Va.QuadPart,
+ MMCSR_ALL_21064(LogoutFrame->MmCsr) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "HIRR : %016Lx HIER : %016Lx PS : %016Lx\n",
+ IRR_ALL_21064(LogoutFrame->Hirr),
+ IER_ALL_21064(LogoutFrame->Hier),
+ PS_ALL_21064(LogoutFrame->Ps) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "PAL_BASE : %016Lx \n",
+ LogoutFrame->PalBase.QuadPart );
+ HalDisplayString( OutBuffer );
+
+ //
+ // Print out interpretation of the error.
+ //
+
+
+ HalDisplayString( "\n" );
+
+ //
+ // Check for tag control parity error.
+ //
+
+ if( BIUSTAT_TCPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer,
+ "Tag control parity error, Tag control: P: %1x D: %1x S: %1x V: %1x\n",
+ BCTAG_TAGCTLP_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLD_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLS_21064( LogoutFrame->BcTag ),
+ BCTAG_TAGCTLV_21064( LogoutFrame->BcTag ) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for tag parity error.
+ //
+
+ if( BIUSTAT_TPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer,
+ "Tag parity error, Tag: 0b%17b Parity: %1x\n",
+ BCTAG_TAG_21064(LogoutFrame->BcTag),
+ BCTAG_TAGP_21064(LogoutFrame->BcTag) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for hard error.
+ //
+
+ if( BIUSTAT_HERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Hard error acknowledge: BIU CMD: %x PA: %16Lx\n",
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for soft error.
+ //
+
+ if( BIUSTAT_SERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Soft error acknowledge: BIU CMD: %x PA: %16Lx\n",
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+
+ //
+ // Check for fill ECC errors.
+ //
+
+ if( BIUSTAT_FILLECC_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "ECC error: %s\n",
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\n",
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for fill Parity errors.
+ //
+
+ if( BIUSTAT_FILLDPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ sprintf( OutBuffer, "Parity error: %s\n",
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\n",
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for multiple hard errors.
+ //
+
+ if( BIUSTAT_FATAL1_21064(LogoutFrame->BiuStat) == 1 ){
+
+ HalDisplayString( "Multiple external/tag errors detected.\n" );
+
+ }
+
+ //
+ // Check for multiple fill errors.
+ //
+
+ if( BIUSTAT_FATAL2_21064(LogoutFrame->BiuStat) == 1 ){
+
+ HalDisplayString( "Multiple fill errors detected.\n" );
+
+ }
+
+
+ //
+ // return to caller
+ //
+
+ return;
+}
diff --git a/private/ntos/nthals/halalpha/ev4prof.c b/private/ntos/nthals/halalpha/ev4prof.c
new file mode 100644
index 000000000..513187b0d
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev4prof.c
@@ -0,0 +1,591 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev4prof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV4 core. This module is appropriate for all
+ machines based on microprocessors using the EV4 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Joe Notarangelo 22-Feb-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+
+//
+// Define space in the HAL-reserved part of the PCR structure for each
+// performance counter's interval count
+//
+// Note that ev4ints.s depends on these positions in the PCR.
+//
+#define PCRProfileCount ((PULONG)(HAL_PCR->ProfileCount.ProfileCount))
+#define PCRProfileCountReload ((PULONG)(&HAL_PCR->ProfileCount.ProfileCountReload))
+
+
+//
+// Define the currently selected profile source for each counter
+//
+KPROFILE_SOURCE HalpProfileSource0;
+KPROFILE_SOURCE HalpProfileSource1;
+
+#define INTERVAL_DELTA (10)
+
+//
+// Define the mapping between possible profile sources and the
+// CPU-specific settings.
+//
+typedef struct _HALP_PROFILE_MAPPING {
+ BOOLEAN Supported;
+ ULONG MuxControl;
+ ULONG Counter;
+ ULONG EventCount;
+ ULONG NumberOfTicks;
+} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING;
+
+HALP_PROFILE_MAPPING HalpProfileMapping[ProfileMaximum] =
+ {
+ {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4TotalIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4PipelineDry, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4LoadInstruction, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4PipelineFrozen, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4BranchInstructions, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4TotalNonIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4DcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4IcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4BranchMispredicts, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4StoreInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4FPInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4IntegerOperate, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4DualIssues, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4PalMode, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {FALSE, 0, 0, 0, 0},
+ {FALSE, 0, 0, 0, 0}
+ };
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ HalpProfileMapping[SourceInfo->Source].EventCount *
+ HalpProfileMapping[SourceInfo->Source].NumberOfTicks;
+ if (SourceInfo->Source == ProfileTotalIssues) {
+ //
+ // Convert total issues/2 back into total issues
+ //
+ SourceInfo->Interval = SourceInfo->Interval * 2;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKINTERRUPT InterruptObject;
+ KIRQL Irql;
+ PKPRCB Prcb = PCR->Prcb;
+ ULONG Vector;
+
+ //
+ // Establish the profile interrupt as the interrupt handler for
+ // all performance counter interrupts.
+ //
+
+ PCR->InterruptRoutine[PC0_VECTOR] = HalpPerformanceCounter0Interrupt;
+ PCR->InterruptRoutine[PC1_VECTOR] = HalpPerformanceCounter1Interrupt;
+
+ return;
+
+}
+
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) {
+ return(FALSE);
+ }
+
+ return(HalpProfileMapping[Source].Supported);
+}
+
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ ULONG FastTickPeriod;
+ ULONG SlowTickPeriod;
+ ULONG TickPeriod;
+ ULONGLONG CountEvents;
+ ULONG FastCountEvents;
+ ULONG SlowCountEvents;
+ ULONGLONG TempInterval;
+
+ if (!HalQueryProfileInterval(ProfileSource)) {
+ return(STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (ProfileSource == ProfileTime) {
+
+ //
+ // Convert the clock tick period (in 100ns units ) into
+ // a cycle count period
+ //
+
+ CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod;
+ } else if (ProfileSource == ProfileTotalIssues) {
+
+ //
+ // Convert the total issue events into the wonky
+ // total issues/2 form implemented by EV4.
+ //
+
+ CountEvents = (ULONGLONG)(*Interval / 2);
+ } else {
+ CountEvents = (ULONGLONG)*Interval;
+ }
+
+ if (HalpProfileMapping[ProfileSource].Counter == Ev4PerformanceCounter1) {
+ FastCountEvents = Ev4CountEvents2xx8;
+ SlowCountEvents = Ev4CountEvents2xx12;
+ } else {
+ FastCountEvents = Ev4CountEvents2xx12;
+ SlowCountEvents = Ev4CountEvents2xx16;
+ }
+
+ //
+ // Limit the interval to the smallest interval we can time.
+ //
+ if (CountEvents < FastCountEvents) {
+ CountEvents = (ULONGLONG)FastCountEvents;
+ }
+
+ //
+ // Assume we will use the fast event count
+ //
+ HalpProfileMapping[ProfileSource].EventCount = FastCountEvents;
+ HalpProfileMapping[ProfileSource].NumberOfTicks =
+ (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents);
+
+ //
+ // See if we can successfully use the slower period. If the requested
+ // interval is greater than the slower tick period and the difference
+ // between the requested interval and the interval that we can deliver
+ // with the slower clock is acceptable, then use the slower clock.
+ // We define an acceptable difference as a difference of less than
+ // INTERVAL_DELTA of the requested interval.
+ //
+ if (CountEvents > SlowCountEvents) {
+ ULONG NewInterval;
+
+ NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) /
+ SlowCountEvents) * SlowCountEvents);
+ if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) {
+ HalpProfileMapping[ProfileSource].EventCount = SlowCountEvents;
+ HalpProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents;
+ }
+ }
+
+ *Interval = HalpProfileMapping[ProfileSource].EventCount *
+ HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ if (ProfileSource == ProfileTime) {
+ //
+ // Convert cycle count back into 100ns clock ticks
+ //
+ // Use 64-bit integer to prevent overflow.
+ //
+ TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod);
+ *Interval = (ULONG)(TempInterval / 100000);
+ } else if (ProfileSource == ProfileTotalIssues) {
+ //
+ // Convert issues/2 count back into issues
+ //
+ TempInterval = (ULONGLONG)(*Interval) * 2;
+ *Interval = (ULONG)TempInterval;
+ }
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG MuxControl;
+ ULONG EventCount;
+
+ //
+ // Check input to see if we are turning on a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!HalpProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Set the performance counter within the processor to begin
+ // counting total cycles.
+ //
+ PerformanceCounter = HalpProfileMapping[ProfileSource].Counter;
+ MuxControl = HalpProfileMapping[ProfileSource].MuxControl;
+
+ if (PerformanceCounter == Ev4PerformanceCounter0) {
+
+ HalpProfileSource0 = ProfileSource;
+ EventCount = (HalpProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ?
+ Ev4EventCountHigh :
+ Ev4EventCountLow;
+ HalpWritePerformanceCounter( PerformanceCounter,
+ TRUE,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[0] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[0] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC0_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+
+ } else {
+
+ HalpProfileSource1 = ProfileSource;
+ EventCount = (HalpProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ?
+ Ev4EventCountLow :
+ Ev4EventCountHigh;
+ HalpWritePerformanceCounter( PerformanceCounter,
+ TRUE,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[1] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[1] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC1_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+ }
+
+ return;
+}
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG Vector;
+
+ //
+ // Check input to see if we are turning off a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!HalpProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Stop the performance counter from interrupting.
+ //
+
+ PerformanceCounter = HalpProfileMapping[ProfileSource].Counter;
+ HalpWritePerformanceCounter( PerformanceCounter,
+ FALSE,
+ 0,
+ 0 );
+
+ //
+ // Disable the performance counter interrupt.
+ //
+ if (PerformanceCounter == Ev4PerformanceCounter0) {
+ HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+ } else {
+ HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+ }
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halalpha/ev5cache.c b/private/ntos/nthals/halalpha/ev5cache.c
new file mode 100644
index 000000000..2ab2e09bf
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev5cache.c
@@ -0,0 +1,475 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev5cache.c
+
+Abstract:
+
+ This file contains the routines for managing the caches on machines
+ based on the DECchip 21164 microprocessor (aka EV5).
+
+ EV5 has primary I and D caches of 8KB each, Dcache is write-through.
+ EV5 also contains a 96K, 3-way set associative, write-back secondary cache.
+ Many EV5 systems will also have an external 3rd level backup cache.
+ The data caches (internal and external) must be kept coherent by the
+ hardware. Instruction cache coherency is maintained by software.
+
+ EV5 has a write buffer which contains 6 32-byte entries, which
+ must be flushable before DMA operations. The MB instruction is
+ used to accomplish this.
+
+ There is no coloring support on EV5, so Color operations are
+ null. Zero page is implemented in ev5mem.s Copy page is not
+ special because we lack coloring.
+
+Author:
+
+ Miche Baker-Harvey (miche) 29-May-1992 (EV4 version)
+ Steve Brooks 30-Jun-1994 (EV5 version)
+ Joe Notarangelo 30-Jun-1994 (EV5 version)
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ );
+
+
+//
+// Cache and write buffer flush functions.
+//
+
+
+VOID
+HalChangeColorPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+/*++
+
+Routine Description:
+
+ This function changes the color of a page if the old and new colors
+ do not match. DECchip 21064-based machines do not have page coloring, and
+ therefore, this function performs no operation.
+
+Arguments:
+
+ NewColor - Supplies the page aligned virtual address of the
+ new color of the page to change.
+
+ OldColor - Supplies the page aligned virtual address of the
+ old color of the page to change.
+
+ pageFrame - Supplies the page frame number of the page that
+ is changed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalFlushDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is flushed.
+ PageFrame - Supplies the page frame number of the page that
+ is flushed.
+
+ Length - Supplies the length of the region in the page that is
+ flushed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+}
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+Routine Description:
+
+ This function purges (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalPurgeIcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function purges (invalidates) up to a page fo data from the
+ instruction cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+
+ HalpImb();
+}
+
+
+VOID
+HalSweepDcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire data cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalSweepDcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the data
+ cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the data cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the data cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire instruction cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+
+ HalpImb();
+ return;
+}
+
+
+VOID
+HalSweepIcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the
+ instruction cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the instruction cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the instruction cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+
+ HalpImb;
+
+}
+
+
+VOID
+KeFlushWriteBuffer (
+ VOID
+ )
+
+{
+ //
+ // We flush the write buffer by doing a series of memory
+ // barrier operations, the flush method is specific to the 21164.
+ //
+
+ HalpMb();
+ HalpMb();
+
+ return;
+}
+
+
+VOID
+KeFlushDcache (
+ IN BOOLEAN AllProcessors,
+ IN PVOID BaseAddress OPTIONAL,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(BaseAddress);
+ UNREFERENCED_PARAMETER(Length);
+
+ HalFlushDcache(AllProcessors);
+ return;
+}
+
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sweep (index/writeback/invalidate) the data cache.
+ //
+
+ HalSweepDcache();
+ return;
+}
+
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 8;
+}
diff --git a/private/ntos/nthals/halalpha/ev5int.c b/private/ntos/nthals/halalpha/ev5int.c
new file mode 100644
index 000000000..3fa1eec25
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev5int.c
@@ -0,0 +1,440 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev5int.c
+
+Abstract:
+
+ This module implements the support routines to control DECchip 21164
+ interrupts.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21164.h"
+
+//
+// Function prototype.
+//
+
+VOID
+HalpCachePcrValues(
+ ULONG InterruptMask
+ );
+
+
+VOID
+HalpInitialize21164Interrupts(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the data structures for the 21164
+ interrupt routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIMSK_21164 InterruptMask;
+ PBOOLEAN InterruptsStarted;
+
+ //
+ // Set up the standard correspondence of NT IRQLs to EV5 IPLs.
+ // It is possible that some machines may need a different correspondence
+ // then the one below - HALs that change this table do so at their
+ // own risk.
+ //
+ // NT IRQL EV5 IPL
+ // ------- -------
+ // PASSIVE_LEVEL 0
+ // APC_LEVEL 1
+ // DISPATCH_LEVEL 2
+ // DEVICE_LEVEL 20
+ // DEVICE_HIGH_LEVEL 21
+ // CLOCK_LEVEL 22
+ // IPI_LEVEL 23
+ // HIGH_LEVEL 31
+ //
+
+ PCR->IrqlTable[PASSIVE_LEVEL] = EV5_IPL0;
+ PCR->IrqlTable[APC_LEVEL] = EV5_IPL1;
+ PCR->IrqlTable[DISPATCH_LEVEL] = EV5_IPL2;
+ PCR->IrqlTable[DEVICE_LEVEL] = EV5_IPL20;
+ PCR->IrqlTable[DEVICE_HIGH_LEVEL] = EV5_IPL21;
+ PCR->IrqlTable[CLOCK_LEVEL] = EV5_IPL22;
+ PCR->IrqlTable[IPI_LEVEL] = EV5_IPL23;
+ PCR->IrqlTable[HIGH_LEVEL] = EV5_IPL31;
+
+ //
+ // Define the default set of disables (masks) for the EV5 interrupt
+ // pins INT0 - INT3. All interrupts are enabled by default and may
+ // be disabled by the interface: HalpDisable21164HardwareInterrupt().
+ //
+
+ InterruptMask = (PIMSK_21164)(&PCR->IrqlMask[0]);
+
+ InterruptMask->all = 0;
+
+ //
+ // Indicate that interrupts have not been started yet.
+ //
+
+ InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
+ *InterruptsStarted = FALSE;
+
+ return;
+
+}
+
+
+VOID
+HalpStart21164Interrupts(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function starts interrupt dispatching on the current 21164.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIMSK_21164 InterruptMask;
+ PBOOLEAN InterruptsStarted;
+
+ //
+ // Issue the initpcr call pal to alert the PALcode that it can
+ // begin taking interrupts, pass the disable mask for the hardware
+ // interrupts.
+ //
+
+ InterruptMask = (PIMSK_21164)(&PCR->IrqlMask);
+ HalpCachePcrValues( InterruptMask->all );
+
+ //
+ // Indicate that interrupts have been started yet.
+ //
+
+ InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
+ *InterruptsStarted = TRUE;
+
+ return;
+}
+
+
+#if 0 // used ??
+
+VOID
+HalpEnable21164HardwareInterrupt(
+ IN ULONG Irq
+ )
+/*++
+
+Routine Description:
+
+ Clear the mask value for the desired Irq pin so that interrupts
+ are enabled from that pin.
+
+Arguments:
+
+ Irq - Supplies the interrupt pin number to be enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIMSK_21164 InterruptMask;
+ PBOOLEAN InterruptsStarted;
+ KIRQL OldIrql;
+
+ //
+ // Raise Irql to HIGH_LEVEL to prevent any interrupts.
+ //
+
+ KeRaiseIrql( HIGH_LEVEL, &OldIrql );
+
+ //
+ // Clear the mask value for the desired Irq pin.
+ //
+
+ InterruptMask = (PIMSK_21164)(&PCR->IrqlMask);
+
+ switch( Irq ){
+
+ case Irq0:
+
+ InterruptMask->Irq0Mask = 0;
+ break;
+
+ case Irq1:
+
+ InterruptMask->Irq1Mask = 0;
+ break;
+
+ case Irq2:
+
+ InterruptMask->Irq2Mask = 0;
+ break;
+
+ case Irq3:
+
+ InterruptMask->Irq3Mask = 0;
+ break;
+
+ } //end switch (Irq)
+
+ //
+ // Set the new masks in the PALcode.
+ //
+
+ InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
+ if( *InterruptsStarted == TRUE ){
+ HalpCachePcrValues( InterruptMask->all );
+ }
+
+ //
+ // Lower Irql to the previous level and return.
+ //
+
+ KeLowerIrql( OldIrql );
+ return;
+
+}
+
+
+VOID
+HalpDisable21164HardwareInterrupt(
+ IN ULONG Irq
+ )
+/*++
+
+Routine Description:
+
+ Set the mask value for the desired Irq pin so that interrupts
+ are disabled from that pin.
+
+Arguments:
+
+ Irq - Supplies the interrupt pin number to be disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIMSK_21164 InterruptMask;
+ PBOOLEAN InterruptsStarted;
+ KIRQL OldIrql;
+
+ //
+ // Raise Irql to HIGH_LEVEL to prevent any interrupts.
+ //
+
+ KeRaiseIrql( HIGH_LEVEL, &OldIrql );
+
+ //
+ // Set the mask value for the desired Irq pin.
+ //
+
+ InterruptMask = (PIMSK_21164)(&PCR->IrqlMask);
+
+ switch( Irq ){
+
+ case Irq0:
+
+ InterruptMask->Irq0Mask = 1;
+ break;
+
+ case Irq1:
+
+ InterruptMask->Irq1Mask = 1;
+ break;
+
+ case Irq2:
+
+ InterruptMask->Irq2Mask = 1;
+ break;
+
+ case Irq3:
+
+ InterruptMask->Irq3Mask = 1;
+ break;
+
+ } //end switch (Irq)
+
+ //
+ // Set the new masks in the PALcode, if interrupts have been started.
+ //
+
+ InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
+ if( *InterruptsStarted == TRUE ){
+ HalpCachePcrValues( InterruptMask->all );
+ }
+
+ //
+ // Lower Irql to the previous level and return.
+ //
+
+ KeLowerIrql( OldIrql );
+ return;
+
+}
+
+#endif // Used ??
+
+
+ULONG
+HalpGet21164PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified performance counter interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21164.
+ //
+
+ *Irql = PROFILE_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 2
+ //
+
+ case 2:
+
+ return PC2_SECONDARY_VECTOR;
+
+ } //end switch( BusInterruptLevel )
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+
+}
+
+ULONG
+HalpGet21164CorrectableVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified correctable interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ //
+ // Get the correctable interrupt vector.
+ //
+
+ if (BusInterruptLevel == 5) {
+
+ //
+ // Correctable error interrupt was sucessfully recognized.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ return CORRECTABLE_VECTOR;
+
+
+ } else {
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+ }
+}
+
diff --git a/private/ntos/nthals/halalpha/ev5ints.s b/private/ntos/nthals/halalpha/ev5ints.s
new file mode 100644
index 000000000..1970c83fe
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev5ints.s
@@ -0,0 +1,397 @@
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// ev5ints.s
+//
+// Abstract:
+//
+// This module implements EV5-specific interrupt handlers.
+// (the performance counters)
+//
+// Author:
+//
+// John Vert (jvert) 15-Nov-1994
+// Steve Brooks 14-Feb-1994 (modified from ev4ints.s)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+#define PC0_SECONDARY_VECTOR 11
+#define PC1_SECONDARY_VECTOR 13
+#define PC2_SECONDARY_VECTOR 16 // SjBfix. This is actually PC3_VECTOR
+#define PcProfileCount0 PcHalReserved+20
+#define PcProfileCount1 PcProfileCount0+4
+#define PcProfileCount2 PcProfileCount1+4
+#define PcProfileCountReload0 PcProfileCount2+4
+#define PcProfileCountReload1 PcProfileCountReload0+4
+#define PcProfileCountReload2 PcProfileCountReload1+4
+
+ .struct 0
+ .space 8 // reserved for alignment
+PrRa: .space 8 // space for return address
+PrFrameLength: //
+
+ SBTTL("Performance Counter 0 Interrupt")
+//++
+//
+// VOID
+// HalpPerformanceCounter0Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 0. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 0.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(HalpPerformanceCounter0Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount0(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload0(v0) // get the new tick count
+ stl t0, PcProfileCount0(v0) // reset the profile interval count
+
+ ldl a1, HalpProfileSource0
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount0(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end HalpPerformanceCounter0Interrupt
+
+
+ SBTTL("Performance Counter 1 Interrupt")
+//++
+//
+// VOID
+// HalpPerformanceCounter1Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 1. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 1.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(HalpPerformanceCounter1Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount1(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload1(v0) // get the new tick count
+ stl t0, PcProfileCount1(v0) // reset the profile interval count
+
+ ldl a1, HalpProfileSource1
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount1(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end HalpPerformanceCounter1Interrupt
+
+ SBTTL("Performance Counter 2 Interrupt")
+//++
+//
+// VOID
+// HalpPerformanceCounter2Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 2. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 2.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(HalpPerformanceCounter2Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount2(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload2(v0) // get the new tick count
+ stl t0, PcProfileCount2(v0) // reset the profile interval count
+
+ ldl a1, HalpProfileSource2
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount2(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC2_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end HalpPerformanceCounter2Interrupt
+
+//++
+//
+// ULONGLONG
+// HalpRead21164PerformanceCounter(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Read the processor performance counter register
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The current value of the performance counter register.
+//
+//--
+
+ LEAF_ENTRY(HalpRead21164PerformanceCounter)
+
+ bis zero, 1, a1 // indicate read operation
+ call_pal wrperfmon // read the performance counter
+
+ ret zero, (ra) // return to caller
+
+ .end HalpRead21164PerformanceCounter
+
+
+//++
+//
+// VOID
+// HalpWrite21164PerformanceCounter(
+// ULONGLONG PmCtr
+// ULONG CboxMux1
+// ULONG CboxMux2
+// )
+//
+// Routine Description:
+//
+// Write the processor performance counter register
+//
+// Arguments:
+//
+// PmCtr(a0) - value to be written to the performance counter
+// CboxMux1(a1) - value to be written to Cbox mux 1 select (optional)
+// CboxMux2(a2) - value to be written to Cbox mux 2 select (optional)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWrite21164PerformanceCounter)
+
+ bis zero, a2, a3 // move arguments up
+ bis zero, a1, a2 //
+ bis zero, zero, a1 // indicate write operation
+ call_pal wrperfmon // write the performance counter
+
+ ret zero, (ra)
+
+ .end HalpWrite21164PerformanceCounter
diff --git a/private/ntos/nthals/halalpha/ev5mchk.c b/private/ntos/nthals/halalpha/ev5mchk.c
new file mode 100644
index 000000000..400c2a95c
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev5mchk.c
@@ -0,0 +1,677 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev5mchk.c
+
+Abstract:
+
+ This module implements generalized machine check handling for
+ platforms based on the DECchip 21164 (EV5) microprocessor.
+
+Author:
+
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21164.h"
+#include "stdio.h"
+
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+VOID
+HalpDisplayLogout21164(
+ IN PLOGOUT_FRAME_21164 LogoutFrame );
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ );
+
+//
+// System-wide controls for machine check reporting.
+//
+
+ProcessorCorrectableDisable = FALSE;
+SystemCorrectableDisable = FALSE;
+MachineCheckDisable = FALSE;
+
+//
+// Error counts.
+//
+
+ULONG CorrectableErrors = 0;
+ULONG RetryableErrors = 0;
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ )
+/*++
+
+Routine Description:
+
+ This function sets the enables that define which machine check
+ errors will be signaled by the processor.
+
+ N.B. - The system has the capability to ignore all machine checks
+ by indicating DisableMachineChecks = TRUE. This is intended
+ for debugging purposes on broken hardware. If you disable
+ this you will get no machine check no matter what error the
+ system/processor detects. Consider the consequences.
+
+Arguments:
+
+ DisableMachineChecks - Supplies a boolean which indicates if all
+ machine checks should be disabled and not
+ reported. (see note above).
+
+ DisableProcessorCorrectables - Supplies a boolean which indicates if
+ processor correctable error reporting
+ should be disabled.
+ DisableSystemCorrectables - Supplies a boolean which indicates if
+ system correctable error reporting
+ should be disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ProcessorCorrectableDisable = DisableProcessorCorrectables;
+ SystemCorrectableDisable = DisableSystemCorrectables;
+ MachineCheckDisable = DisableMachineChecks;
+
+ HalpUpdateMces( FALSE, FALSE );
+
+ return;
+}
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ )
+/*++
+
+Routine Description:
+
+ This function updates the state of the MCES internal processor
+ register.
+
+Arguments:
+
+ ClearMachineCheck - Supplies a boolean that indicates if the machine
+ check indicator in the MCES should be cleared.
+
+ ClearCorrectableError - Supplies a boolean that indicates if the
+ correctable error indicators in the MCES should
+ be cleared.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MCES Mces;
+
+ Mces.MachineCheck = ClearMachineCheck;
+ Mces.SystemCorrectable = ClearCorrectableError;
+ Mces.ProcessorCorrectable = ClearCorrectableError;
+ Mces.DisableProcessorCorrectable = ProcessorCorrectableDisable;
+ Mces.DisableSystemCorrectable = SystemCorrectableDisable;
+ Mces.DisableMachineChecks = MachineCheckDisable;
+
+ HalpWriteMces( Mces );
+
+}
+
+
+BOOLEAN
+HalMachineCheck (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This function fields machine check for 21164-based machines.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record for the
+ machine check. Included in the exception information
+ is the pointer to the logout frame.
+
+ ExceptionFrame - Supplies a pointer to the kernel exception frame.
+
+ TrapFrame - Supplies a pointer to the kernel trap frame.
+
+Return Value:
+
+ A value of TRUE is returned if the machine check has been
+ handled by the HAL. If it has been handled then execution may
+ resume at the faulting address. Otherwise, a value of FALSE
+ is returned.
+
+ N.B. - Under some circumstances this routine may not return at
+ all.
+
+--*/
+
+{
+
+ BOOLEAN Handled;
+ PLOGOUT_FRAME_21164 LogoutFrame;
+ PMCHK_STATUS MachineCheckStatus;
+ MCES Mces;
+ PICPERR_STAT_21164 icPerrStat;
+ PDC_PERR_STAT_21164 dcPerrStat;
+ PSC_STAT_21164 scStat;
+ PEI_STAT_21164 eiStat;
+ BOOLEAN UnhandledPlatformError = FALSE;
+
+ PUNCORRECTABLE_ERROR uncorrerr = NULL;
+ PPROCESSOR_EV5_UNCORRECTABLE ev5uncorr = NULL;
+
+ //
+ // Check for retryable errors. These are usually I-stream parity
+ // errors, which may be retried following a cache flush (the cache
+ // flush is handled by the PAL).
+ //
+
+ MachineCheckStatus =
+ (PMCHK_STATUS)&ExceptionRecord->ExceptionInformation[0];
+
+ //
+ // Handle any retryable errors.
+ //
+
+ if( MachineCheckStatus->Retryable == 1 ){
+
+ //
+ // Log the error.
+ //
+
+ RetryableErrors += 1;
+
+#if (DBG) || (HALDBG)
+
+ if( (RetryableErrors % 32) == 0 ){
+ DbgPrint( "HAL Retryable Errors = %d\n", RetryableErrors );
+ }
+
+#endif //DBG || HALDBG
+
+ //
+ // Acknowledge receipt of the retryable machine check.
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ return TRUE;
+
+ }
+
+ //
+ // Capture the logout frame pointer.
+ //
+
+ LogoutFrame =
+ (PLOGOUT_FRAME_21164)ExceptionRecord->ExceptionInformation[1];
+
+ //
+ // Check for any hard errors that cannot be dismissed.
+ // They are:
+ // Tag parity error
+ // Tag control parity error
+ // Multiple external errors
+ // Fill ECC error
+ // Fill parity error
+ // Multiple fill errors
+ //
+
+ icPerrStat = (PICPERR_STAT_21164)&LogoutFrame->IcPerrStat;
+ dcPerrStat = (PDC_PERR_STAT_21164)&LogoutFrame->DcPerrStat;
+ scStat = (PSC_STAT_21164)&LogoutFrame->ScStat;
+ eiStat = (PEI_STAT_21164)&LogoutFrame->EiStat;
+
+ if(PUncorrectableError) {
+ //
+ // Fill in the processor specific uncorrectable error frame
+ //
+ uncorrerr = (PUNCORRECTABLE_ERROR)
+ &PUncorrectableError->UncorrectableFrame;
+
+ //
+ // first fill in some generic processor Information.
+ // For the Current (Reporting) Processor.
+ //
+ HalpGetProcessorInfo(&uncorrerr->ReportingProcessor);
+ uncorrerr->Flags.ProcessorInformationValid = 1;
+
+ ev5uncorr = (PPROCESSOR_EV5_UNCORRECTABLE)
+ uncorrerr->RawProcessorInformation;
+ }
+ if(ev5uncorr){
+ ev5uncorr->IcPerrStat = LogoutFrame->IcPerrStat.all;
+ ev5uncorr->DcPerrStat = LogoutFrame->DcPerrStat.all;
+ ev5uncorr->ScStat = LogoutFrame->ScStat.all;
+ ev5uncorr->ScAddr = LogoutFrame->ScAddr.all;
+ ev5uncorr->EiStat = LogoutFrame->EiStat.all;
+ ev5uncorr->BcTagAddr = LogoutFrame->BcTagAddr.all;
+ ev5uncorr->EiAddr = LogoutFrame->EiAddr.all;
+ ev5uncorr->FillSyn = LogoutFrame->FillSyn.all;
+ ev5uncorr->BcConfig = LogoutFrame->BcConfig.all;
+ ev5uncorr->BcControl = LogoutFrame->BcControl.all;
+ }
+
+//
+// SjBfix. The External parity error checking is disabled due to bug
+// Rattler chipset on Gamma which causes the parity error on
+// machine checks due to reads to PCI config space. (fixed in pass 2)
+//
+
+ if ( icPerrStat->Dpe == 1 || icPerrStat->Tpe == 1 ||
+ icPerrStat->Tmr == 1 || dcPerrStat->Lock == 1 ||
+ scStat->ScTperr == 1 || scStat->ScDperr == 1 ||
+ eiStat->BcTperr == 1 || eiStat->BcTcperr == 1 ||
+// eiStat->UncEccErr == 1 || eiStat->EiParErr == 1 ||
+ eiStat->SeoHrdErr == 1 || scStat->ScScndErr == 1 ){
+
+ //
+ // A serious, uncorrectable error has occured, under no circumstances
+ // can it be simply dismissed.
+ //
+
+ goto FatalError;
+
+ }
+
+ //
+ // It is possible that the system has experienced a hard error and
+ // that nonetheless the error is recoverable. This is a system-specific
+ // decision - allow it to be handled as such.
+ //
+
+ UnhandledPlatformError = TRUE;
+ if( (Handled = HalpPlatformMachineCheck(
+ ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame )) == TRUE ){
+
+ //
+ // The system-specific code has handled the error. Dismiss
+ // the error and continue execution.
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ return TRUE;
+
+ }
+
+//
+// The system has experienced a fatal error that cannot be corrected.
+// Print any possible relevant information and crash the system.
+//
+// N.B. - In the future some of these fatal errors could be potential
+// recovered. Example, a user process gets a fatal error on one
+// of its pages - we kill the user process, mark the page as bad
+// and continue executing.
+//
+
+FatalError:
+
+ uncorrerr->Flags.ErrorStringValid = 1;
+ sprintf(uncorrerr->ErrorString,"Uncorrectable Error From "
+ "Processor Detected");
+ //
+ // Begin the error output if this is a processor error. If this is
+ // an unhandled platform error than that code is responsible for
+ // beginning the error output.
+ //
+
+ if( UnhandledPlatformError == FALSE ){
+
+ //
+ // Acquire ownership of the display. This is done here in case we take
+ // a machine check before the display has been taken away from the HAL.
+ // When the HAL begins displaying strings after it has lost the
+ // display ownership then the HAL will be careful not to scroll
+ // information off of the screen.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ }
+
+ //
+ // Display the EV5 logout frame.
+ //
+
+ HalpDisplayLogout21164( LogoutFrame );
+
+ //
+ // Bugcheck to dump the rest of the machine state, this will help
+ // if the machine check is software-related.
+ //
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ (ULONG)MachineCheckStatus->Correctable,
+ (ULONG)MachineCheckStatus->Retryable,
+ 0,
+ (ULONG)PUncorrectableError );
+
+}
+
+#define MAX_ERROR_STRING 100
+
+VOID
+HalpDisplayLogout21164 (
+ IN PLOGOUT_FRAME_21164 LogoutFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This function displays the logout frame for a 21164.
+
+Arguments:
+
+ LogoutFrame - Supplies a pointer to the logout frame generated
+ by the 21164.
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+
+ sprintf( OutBuffer, "ICSR : %016Lx ICPERR_STAT : %016Lx\n",
+ LogoutFrame->Icsr.all, LogoutFrame->IcPerrStat.all );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "MM_STAT : %016Lx DC_PERR_STAT : %016Lx\n",
+ LogoutFrame->MmStat.all,
+ LogoutFrame->DcPerrStat.all );
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "PS : %016Lx VA : %016Lx VA_FORM : %016Lx\n",
+ LogoutFrame->Ps,
+ LogoutFrame->Va,
+ LogoutFrame->VaForm );
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "ISR : %016Lx IPL : %016Lx INTID : %016Lx\n",
+ LogoutFrame->Isr.all,
+ LogoutFrame->Ipl,
+ LogoutFrame->IntId );
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "SC_STAT : %016Lx SC_CTL : %016Lx SC_ADDR : %016Lx\n",
+ LogoutFrame->ScStat.all,
+ LogoutFrame->ScCtl.all,
+ LogoutFrame->ScAddr.all );
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "EI_STAT : %016Lx EI_ADDR : %016Lx\n",
+ LogoutFrame->EiStat.all, LogoutFrame->EiAddr.all );
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "BC_TAG_ADDR : %016Lx FILL_SYN : %016Lx\n",
+ LogoutFrame->BcTagAddr.all, LogoutFrame->FillSyn.all );
+
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "BC_CONTROL : %016Lx BC_CONFIG : %016Lx\n",
+ LogoutFrame->BcControl.all, LogoutFrame->BcConfig.all );
+
+ HalDisplayString( OutBuffer );
+
+
+ sprintf( OutBuffer, "EXC_ADDR : %016Lx PAL_BASE : %016Lx\n",
+ LogoutFrame->ExcAddr, LogoutFrame->PalBase );
+
+ HalDisplayString( OutBuffer );
+
+ //
+ // Print out interpretation of the error.
+ //
+
+ HalDisplayString( "\n" );
+
+ //
+ // Check for tag parity error.
+ //
+
+ if ( LogoutFrame->IcPerrStat.Dpe == 1 ||
+ LogoutFrame->IcPerrStat.Tpe == 1 ){
+
+ //
+ // Note: The excAddr may contain the address of the instruction
+ // the caused the parity error but it is not guaranteed:
+ //
+ sprintf( OutBuffer, "Icache %s parity error, Addr: %x\n",
+ LogoutFrame->IcPerrStat.Dpe ? "Data" : "Tag",
+ LogoutFrame->ExcAddr );
+
+ HalDisplayString( OutBuffer );
+
+ } else if ( LogoutFrame->DcPerrStat.Lock == 1 ){
+
+ sprintf( OutBuffer, "Dcache %s parity error, Addr: %x\n",
+ LogoutFrame->DcPerrStat.Dp0 || LogoutFrame->DcPerrStat.Dp1 ?
+ "Data" : "Tag",
+ LogoutFrame->Va );
+
+ HalDisplayString( OutBuffer );
+
+ } else if ( LogoutFrame->ScStat.ScTperr != 0 ) {
+
+ sprintf( OutBuffer,
+ "Scache Tag parity error, Addr: %x Tag: %x Cmd: %x\n",
+ LogoutFrame->ScAddr.ScAddr,
+ LogoutFrame->ScStat.ScTperr,
+ LogoutFrame->ScStat.CboxCmd);
+
+ HalDisplayString( OutBuffer );
+
+
+ } else if ( LogoutFrame->ScStat.ScDperr != 0 ) {
+
+ sprintf( OutBuffer,
+ "Scache Data parity error, Addr: %x Tag: %x Cmd: %x\n",
+ LogoutFrame->ScAddr.ScAddr,
+ LogoutFrame->ScStat.ScDperr,
+ LogoutFrame->ScStat.CboxCmd);
+
+ HalDisplayString( OutBuffer );
+
+
+ } else if ( LogoutFrame->EiStat.BcTperr == 1 ||
+ LogoutFrame->EiStat.BcTcperr == 1 ){
+
+ sprintf( OutBuffer,
+ "Bcache Tag Parity error, Addr: %x Tag: %x\n",
+ LogoutFrame->EiAddr.EiAddr,
+ LogoutFrame->BcTagAddr.Tag1);
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for timeout reset error:
+ //
+
+ if ( LogoutFrame->IcPerrStat.Tmr == 1 ){
+
+ sprintf( OutBuffer, "Timeout Reset Error\n" );
+
+ HalDisplayString( OutBuffer );
+ }
+
+ //
+ // Check for fill ECC errors.
+ //
+
+ if( LogoutFrame->EiStat.UncEccErr == 1 ){
+
+ sprintf( OutBuffer, "Uncorrectable ECC error: %s\n",
+ LogoutFrame->EiStat.FilIrd ? "Icache Fill" : "Dcache Fill" );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "PA: %16Lx Longword0: %x Longword1: %x\n",
+ LogoutFrame->EiAddr.EiAddr,
+ LogoutFrame->FillSyn.Lo,
+ LogoutFrame->FillSyn.Hi );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for address/command parity error
+ //
+
+ if( LogoutFrame->EiStat.EiParErr == 1 ){
+
+ sprintf( OutBuffer, "Address/Command parity error, Addr=%x\n",
+ LogoutFrame->EiAddr.EiAddr );
+
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for multiple hard errors.
+ //
+
+ if ( LogoutFrame->ScStat.ScScndErr == 1 ){
+
+ HalDisplayString( "Multiple Scache parity errors detected.\n" );
+ }
+
+ if( LogoutFrame->EiStat.SeoHrdErr == 1 ){
+
+ HalDisplayString( "Multiple external/tag errors detected.\n" );
+
+ }
+
+ return;
+}
+
+
+BOOLEAN
+Halp21164CorrectedErrorInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt handler for the 21164 processor corrected error
+ interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Handle any processor correctable errors.
+ //
+
+
+ //
+ // Log the error.
+ //
+ // simply assume this was a fill ecc correctable for now, print
+ // a debug message periodically
+
+ CorrectableErrors += 1;
+
+#if 0 //jnfix
+#if (DBG) || (HALDBG)
+
+ if( (CorrectableErrors % 32) == 0 ){
+ DbgPrint( "Correctable errors = %d\n", CorrectableErrors );
+ }
+
+#endif //DBG || HALDBG
+#endif //0 jnfix
+
+ //
+ // Acknowledge receipt of the correctable error by clearing
+ // the error in the MCES register.
+ //
+
+ HalpUpdateMces( FALSE, TRUE );
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halalpha/ev5mem.s b/private/ntos/nthals/halalpha/ev5mem.s
new file mode 100644
index 000000000..bd82d7f52
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev5mem.s
@@ -0,0 +1,231 @@
+// TITLE("EV5 Memory Operations")
+//++
+//
+// Copyright (c) 1994 Digital Equipment Corporation
+//
+// Module Name:
+//
+// ev5mem.s
+//
+// Abstract:
+//
+// This module implements EV5 memory operations that require assembly
+// language.
+//
+// Author:
+//
+// Joe Notarangelo 30-Jun-1994
+//
+// Environment:
+//
+// HAL, Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalZeroPage)
+
+ .set noreorder // hand scheduled
+
+#define ZERO_BLOCK_SIZE (256)
+#define ZERO_LOOPS (PAGE_SIZE/ZERO_BLOCK_SIZE)
+
+//
+// Map the page via the 43-bit super-page on EV5.
+//
+
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll a2, PAGE_SHIFT, t1 // physical address of page
+
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+ ldil t2, ZERO_LOOPS // set count of loops to run
+
+ bis t0, t1, t0 // set super-page enable + physical
+ br zero, 10f // start the zeroing
+
+//
+// Zero the page in a loop, zeroing 256 bytes per iteration. This number
+// was chosen to tradeoff loop overhead versus the overhead of fetching
+// Icache blocks.
+//
+
+ .align 4 // align as branch target
+10:
+ stq zero, 0x00(t0) //
+ subl t2, 1, t2 // decrement the loop count
+
+ stq zero, 0x08(t0) //
+ stq zero, 0x10(t0) //
+
+ stq zero, 0x18(t0) //
+ stq zero, 0x20(t0) //
+
+ stq zero, 0x28(t0) //
+ stq zero, 0x30(t0) //
+
+ stq zero, 0x38(t0) //
+ stq zero, 0x40(t0) //
+
+ stq zero, 0x48(t0) //
+ stq zero, 0x50(t0) //
+
+ stq zero, 0x58(t0) //
+ stq zero, 0x60(t0) //
+
+ stq zero, 0x68(t0) //
+ stq zero, 0x70(t0) //
+
+ stq zero, 0x78(t0) //
+ stq zero, 0x80(t0) //
+
+ stq zero, 0x88(t0) //
+ stq zero, 0x90(t0) //
+
+ stq zero, 0x98(t0) //
+ stq zero, 0xa0(t0) //
+
+ stq zero, 0xa8(t0) //
+ stq zero, 0xb0(t0) //
+
+ stq zero, 0xb8(t0) //
+ bis t0, zero, t1 // copy base register
+
+ stq zero, 0xc0(t0) //
+ stq zero, 0xc8(t0) //
+
+ stq zero, 0xd0(t0) //
+ stq zero, 0xd8(t0) //
+
+ stq zero, 0xe0(t0) //
+ lda t0, 0x100(t0) // increment to next block
+
+ stq zero, 0xe8(t1) //
+ stq zero, 0xf0(t1) //
+
+ stq zero, 0xf8(t1) // use stt for dual issue with bne
+ bne t2, 10b // while count > 0
+
+ ret zero, (ra) // return
+
+
+ .set reorder //
+
+ .end HalZeroPage
+
+//++
+//
+// ULONGLONG
+// EV5_READ_PHYSICAL (
+// IN ULONGLONG Physical
+// )
+//
+// Routine Description:
+//
+// This function reads a 64 bit value from the specified physical address
+// The intended use of this function is to read the EV-5 C-Box registers,
+// which reside in uncached memory space.
+//
+// Arguments:
+//
+// Physical (a0) - Supplies the physical address from which to read
+//
+// Return Value:
+//
+// v0 - 64 bit value read from the specified physical address
+//
+//--
+
+ LEAF_ENTRY(READ_EV5_PHYSICAL)
+
+//
+// Create superpage address:
+//
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+
+ bis a0, t0, t0
+ ldq v0, 0(t0) // get the quadword
+
+ ret zero, (ra)
+
+ .end READ_EV5_PHYSICAL
+
+
+//++
+//
+// VOID
+// WRITE_EV5_PHYSICAL (
+// IN ULONGLONG Physical,
+// IN ULONGLONG Value
+// )
+//
+// Routine Description:
+//
+// This function writes a 64 bit value to the specified physical address.
+// The intended use of this function is to write the EV-5 C-Box registers,
+// which reside in uncached memory space.
+//
+// Arguments:
+//
+// Physical (a0) - Supplies the physical address to write
+//
+// Value (a1) - Supplies the value to write
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_EV5_PHYSICAL)
+
+//
+// Create superpage address:
+//
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+
+ bis a0, t0, t0
+ stq a1, 0(t0) // write the value
+ mb // order the write
+ mb // for sure, for sure
+
+ ret zero, (ra)
+
+ .end WRITE_EV5_PHYSICAL
+
+
diff --git a/private/ntos/nthals/halalpha/ev5prof.c b/private/ntos/nthals/halalpha/ev5prof.c
new file mode 100644
index 000000000..d5bab69aa
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ev5prof.c
@@ -0,0 +1,741 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev5prof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV5 core. This module is appropriate for all
+ machines based on microprocessors using the EV5 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Steve Brooks 14-Feb-1995 (adapted from ev4prof.c)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21164.h"
+
+
+//
+// Define space in the HAL-reserved part of the PCR structure for each
+// performance counter's interval count
+//
+// Note that ev5ints.s depends on these positions in the PCR.
+//
+#define PCRProfileCount ((PULONG)(HAL_PCR->ProfileCount.ProfileCount))
+#define PCRProfileCountReload ((PULONG)(&HAL_PCR->ProfileCount.ProfileCountReload))
+
+
+//
+// Define the currently selected profile source for each counter
+//
+KPROFILE_SOURCE HalpProfileSource0;
+KPROFILE_SOURCE HalpProfileSource1;
+KPROFILE_SOURCE HalpProfileSource2;
+
+#define INTERVAL_DELTA (10)
+
+//
+// Define the mapping between possible profile sources and the
+// CPU-specific settings.
+//
+typedef struct _HALP_PROFILE_MAPPING {
+ BOOLEAN Supported;
+ ULONG MuxControl;
+ ULONG Counter;
+ ULONG EventCount;
+ ULONG NumberOfTicks;
+} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING;
+
+HALP_PROFILE_MAPPING HalpProfileMapping[ProfileMaximum] =
+{
+ {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5Instructions, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5PipeDry, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5LoadsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5AllFlowIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5NonIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DcacheLDMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5IcacheRFBMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5BRMispredicts, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5StoresIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5FPOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5IntOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DualIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5TripleIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5QuadIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5IcacheIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DcacheAccesses,Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5MBStallCycles, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5LDxLInstIssued,Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}
+};
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+VOID
+HalpUpdatePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN ULONG MuxControl,
+ IN ULONG EventCount
+ );
+
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ HalpProfileMapping[SourceInfo->Source].EventCount *
+ HalpProfileMapping[SourceInfo->Source].NumberOfTicks;
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Establish the profile interrupt as the interrupt handler for
+ // all performance counter interrupts.
+ //
+
+ PCR->InterruptRoutine[PC0_VECTOR] = HalpPerformanceCounter0Interrupt;
+ PCR->InterruptRoutine[PC1_VECTOR] = HalpPerformanceCounter1Interrupt;
+ PCR->InterruptRoutine[PC2_VECTOR] = HalpPerformanceCounter2Interrupt;
+
+ return;
+
+}
+
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) {
+ return(FALSE);
+ }
+
+ return(HalpProfileMapping[Source].Supported);
+}
+
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ ULONG FastTickPeriod;
+ ULONG SlowTickPeriod;
+ ULONG TickPeriod;
+ ULONG FastCountEvents;
+ ULONG SlowCountEvents;
+ ULONGLONG CountEvents;
+ ULONGLONG TempInterval;
+
+ if (!HalQueryProfileInterval(ProfileSource)) {
+ return(STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (ProfileSource == ProfileTime) {
+
+ //
+ // Convert the clock tick period (in 100ns units ) into
+ // a cycle count period
+ //
+
+ CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod;
+ } else {
+ CountEvents = (ULONGLONG)*Interval;
+ }
+
+ FastCountEvents = Ev5CountEvents2xx8;
+ SlowCountEvents = Ev5CountEvents2xx16;
+
+ if (HalpProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter0) {
+ FastCountEvents = Ev5CountEvents2xx16;
+ }
+ else if (HalpProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter2) {
+ SlowCountEvents = Ev5CountEvents2xx14;
+ }
+
+ //
+ // Limit the interval to the smallest interval we can time.
+ //
+ if (CountEvents < FastCountEvents) {
+ CountEvents = (ULONGLONG)FastCountEvents;
+ }
+
+ //
+ // Assume we will use the fast event count
+ //
+ HalpProfileMapping[ProfileSource].EventCount = FastCountEvents;
+ HalpProfileMapping[ProfileSource].NumberOfTicks =
+ (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents);
+
+ //
+ // See if we can successfully use the slower period. If the requested
+ // interval is greater than the slower tick period and the difference
+ // between the requested interval and the interval that we can deliver
+ // with the slower clock is acceptable, then use the slower clock.
+ // We define an acceptable difference as a difference of less than
+ // INTERVAL_DELTA of the requested interval.
+ //
+ if (CountEvents > SlowCountEvents) {
+ ULONG NewInterval;
+
+ NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) /
+ SlowCountEvents) * SlowCountEvents);
+ if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) {
+ HalpProfileMapping[ProfileSource].EventCount = SlowCountEvents;
+ HalpProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents;
+ }
+ }
+
+ *Interval = HalpProfileMapping[ProfileSource].EventCount *
+ HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ if (ProfileSource == ProfileTime) {
+ //
+ // Convert cycle count back into 100ns clock ticks
+ //
+ // Use 64-bit integer to prevent overflow.
+ //
+ TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod);
+ *Interval = (ULONG)(TempInterval / 100000);
+ }
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG MuxControl;
+ ULONG EventCount;
+
+ //
+ // Check input to see if we are turning on a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!HalpProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Set the performance counter within the processor to begin
+ // counting total cycles.
+ //
+ PerformanceCounter = HalpProfileMapping[ProfileSource].Counter;
+ MuxControl = HalpProfileMapping[ProfileSource].MuxControl;
+
+ if (PerformanceCounter == Ev5PerformanceCounter0) {
+
+ EventCount = (HalpProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx16) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ HalpProfileSource0 = ProfileSource;
+ HalpUpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[0] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[0] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC0_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter1) {
+
+ EventCount = (HalpProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx16) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ HalpProfileSource1 = ProfileSource;
+ HalpUpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[1] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[1] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC1_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter2) {
+
+ EventCount = (HalpProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx14) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ HalpProfileSource2 = ProfileSource;
+ HalpUpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[2] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[2] = HalpProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC2_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+ }
+
+ return;
+}
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG Vector;
+
+ //
+ // Check input to see if we are turning off a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!HalpProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Stop the performance counter from interrupting.
+ //
+
+ PerformanceCounter = HalpProfileMapping[ProfileSource].Counter;
+ HalpUpdatePerformanceCounter( PerformanceCounter,
+ 0,
+ Ev5CounterDisable );
+
+ //
+ // Disable the performance counter interrupt.
+ //
+ if (PerformanceCounter == Ev5PerformanceCounter0) {
+
+ HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter1) {
+
+ HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[1] = 0;
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter2) {
+
+ HalDisableSystemInterrupt( PC2_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[2] = 0;
+ }
+
+ return;
+}
+
+
+VOID
+HalpUpdatePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN ULONG MuxControl,
+ IN ULONG EventCount
+ )
+//++
+//
+// Routine Description:
+//
+// Write the specified microprocessor internal performance counter.
+//
+// Arguments:
+//
+// PerformanceCounter(a0) - Supplies the number of the performance counter
+// to write.
+//
+// MuxControl(a2) - Supplies the mux control value which selects which
+// type of event to count when the counter is enabled.
+//
+// EventCount(a3) - Supplies the event interval when the counter is
+// enabled.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+{
+ PMCTR_21164 PmCtr; // the performance counter register
+ ULONG CboxMux1 = 0; // CBOX select 1 mux value
+ ULONG CboxMux2 = 0; // CBOX select 2 mux value
+
+ PmCtr.all = HalpRead21164PerformanceCounter();
+
+ //
+ // Check for special values first:
+ //
+
+ if ( MuxControl >= Ev5PcSpecial ) {
+
+ switch( MuxControl ) {
+
+ //
+ // Count JsrRet Issued
+ //
+
+ case Ev5JsrRetIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+ PmCtr.Sel2 = Ev5PCMispredicts;
+ break;
+
+ //
+ // Count CondBr Issued
+ //
+
+ case Ev5CondBrIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+ PmCtr.Sel2 = Ev5BRMispredicts;
+ break;
+
+ //
+ // Count all flow change inst Issued
+ //
+
+ case Ev5AllFlowIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+
+ if ( (PmCtr.Sel2 == Ev5PCMispredicts) ||
+ (PmCtr.Sel2 == Ev5BRMispredicts)) {
+
+ PmCtr.Sel2 = Ev5LongStalls;
+
+ }
+ break;
+
+ //
+ // Must be an Scache counter. Select the appropriate counter
+ // in Sel1 or Sel2, and pass the CBOX mux value to WritePerfCounter
+ //
+
+ default:
+
+ if ( MuxControl <= Ev5ScSystemCmdReq ) {
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5CBOXInput1;
+ CboxMux1 = MuxControl - Ev5ScMux1;
+
+ } else if ( MuxControl <= Ev5ScSysReadReq ) {
+
+ PmCtr.Ctl2 = EventCount;
+ PmCtr.Sel2 = Ev5CBOXInput2;
+ CboxMux2 = MuxControl - Ev5ScMux2;
+
+ }
+
+ } // switch
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter0 ) {
+
+ PmCtr.Ctl0 = EventCount;
+ PmCtr.Sel0 = MuxControl;
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter1 ) {
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = MuxControl;
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter2 ) {
+
+ PmCtr.Ctl2 = EventCount;
+ PmCtr.Sel2 = MuxControl;
+
+ }
+
+ HalpWrite21164PerformanceCounter(PmCtr.all, CboxMux1, CboxMux2);
+}
diff --git a/private/ntos/nthals/halalpha/flash8k.c b/private/ntos/nthals/halalpha/flash8k.c
new file mode 100644
index 000000000..96d198845
--- /dev/null
+++ b/private/ntos/nthals/halalpha/flash8k.c
@@ -0,0 +1,323 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ flash8k.c
+
+Abstract:
+
+ This module implements the flash-specific, device-independent routines
+ necessary to Read and Write the flash ROM containing the system environment
+ variables. The routines implemented here are:
+
+ HalpReadNVRamBuffer() - copy data from Flash into memory
+ HalpWriteNVRamBuffer() - write memory data to Flash
+ HalpCopyNVRamBuffer() - stubbed for compatibility with NVRAM
+
+Author:
+
+ Steve Brooks 5-Oct 93
+
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "flash8k.h"
+
+#include "arccodes.h"
+
+//
+// Variables:
+//
+// PFLASH_DRIVER HalpFlashDriver
+// Pointer to the device-specific flash driver.
+//
+PFLASH_DRIVER HalpFlashDriver = NULL;
+
+//
+// Flash Drivers
+//
+// Each platform which uses this module must define FlashDriverList as an
+// array of pointers to the initialize functions of any flash drivers for
+// which the flash device might be used for the environment in the system.
+//
+extern PFLASH_DRIVER (*FlashDriverList[])(PUCHAR);
+
+
+#ifdef AXP_FIRMWARE
+
+#pragma alloc_text(DISTEXT, HalpReadNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpWriteNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpCopyNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpInitializeFlashDriver )
+
+#endif
+
+ARC_STATUS HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Reads data from the NVRam into main memory
+
+Arguments:
+
+ DataPtr - Pointer to memory location to receive data
+ NvRamPtr - Pointer (qva) to NVRam location to read data from
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+ ENODEV if no flash driver is loaded
+
+--*/
+{
+ //
+ // If there is no flash driver, return an error.
+ //
+ if ((HalpFlashDriver == NULL) &&
+ ((HalpFlashDriver = HalpInitializeFlashDriver(NvRamPtr)) == NULL)) {
+
+ return ENODEV;
+ }
+
+ //
+ // Read from the flash.
+ //
+ while(Length--) {
+ *DataPtr = HalpFlash8kReadByte(NvRamPtr);
+ DataPtr++;
+ NvRamPtr++;
+ }
+
+ return ESUCCESS;
+}
+
+//
+//
+//
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Writes data from memory into the NVRam
+
+Arguments:
+
+ NvRamPtr - Pointer (qva) to NVRam location to write data into
+ DataPtr - Pointer to memory location of data to be written
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+ ENODEV if no flash driver is loaded
+ EIO if a device error was detected
+
+--*/
+{
+ ARC_STATUS ReturnStatus = ESUCCESS;
+ UCHAR NeedToErase = FALSE;
+ UCHAR Byte;
+ ULONG Index;
+ ULONG Address;
+
+ //
+ // If there is no flash driver, return an error.
+ //
+ if ((HalpFlashDriver == NULL) &&
+ ((HalpFlashDriver = HalpInitializeFlashDriver(NvRamPtr)) == NULL)) {
+
+ return ENODEV;
+ }
+
+ //
+ // Try to do the udate without erasing the flash block if possible.
+ // We don't write bytes which agree with the current contents of the
+ // flash. If the byte to be written is not the same as what is already
+ // in the flash, write it if the new byte can overwrite the old byte.
+ // On the first byte that cannot be overwritten, abort this loop with
+ // NeedToErase == TRUE and fall through to the failsafe case below.
+ //
+ NeedToErase = FALSE;
+ for(Index = Length;
+ !NeedToErase && (ReturnStatus == ESUCCESS) && Index--;) {
+
+ Address = (ULONG)NvRamPtr + Index;
+ if (((Byte = HalpFlash8kReadByte((PUCHAR)Address)) !=
+ (UCHAR)DataPtr[Index])) {
+
+ if (HalpFlash8kOverwriteCheck(Byte, (UCHAR)DataPtr[Index])) {
+ ReturnStatus = HalpFlash8kWriteByte(Address, DataPtr[Index]);
+ } else {
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Need to erase flash because byte at %08x (%02x) ",
+ Address, Byte);
+ DbgPrint("Cannot be written with %02x\r\n",
+ (UCHAR)DataPtr[Index]);
+#endif
+
+ NeedToErase = TRUE;
+ }
+ }
+ }
+
+ if (NeedToErase) {
+ ULONG BlockSize;
+ ULONG BlockBase;
+ ULONG DataBase;
+ PUCHAR pShadow = NULL;
+
+ //
+ // We need to erase the flash block in order to write some of the
+ // requested data. We take the safe approach of copy the entire
+ // flash block into memory (we don't know what else is there), modify
+ // the copy in memory, erase the flash block, and write the entire
+ // block.
+ //
+
+ DataBase = (ULONG)NvRamPtr & ~(ULONG)HalpCMOSRamBase;
+ BlockBase = (ULONG)HalpFlash8kBlockAlign(NvRamPtr);
+ BlockSize = HalpFlash8kBlockSize(BlockBase);
+
+ pShadow = ExAllocatePool(NonPagedPool, BlockSize);
+
+ if (pShadow != NULL) {
+ for(Index = 0; Index < BlockSize; Index++) {
+ pShadow[Index] = HalpFlash8kReadByte(BlockBase + Index);
+ }
+
+ for(Index = 0; Index < Length; Index++) {
+ pShadow[DataBase + Index] = DataPtr[Index];
+ }
+
+ ReturnStatus = HalpFlash8kEraseBlock(BlockBase);
+
+ for(Index = 0;
+ (Index < BlockSize) && (ReturnStatus == ESUCCESS);
+ Index++) {
+
+ if (pShadow[Index] != HalpFlashDriver->ErasedData) {
+ ReturnStatus = HalpFlash8kWriteByte(BlockBase + Index,
+ pShadow[Index]);
+ }
+ }
+
+ ExFreePool(pShadow);
+ } else {
+#if defined(ALPHA_KDHOOKS) || defined(HALDBG)
+ DbgPrint("HalpWriteNVRamBuffer: Could not allocate shadow...\r\n");
+#endif
+ ReturnStatus = ENOMEM;
+ }
+ }
+
+ HalpFlash8kSetReadMode(NvRamPtr);
+ return ReturnStatus;
+}
+
+//
+//
+//
+ARC_STATUS HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length )
+/*++
+
+Routine Description:
+
+ This routine is not supported.
+
+Arguments:
+
+ NvDestPtr - Pointer (qva) to NVRam location to write data into
+ NvSrcPtr - Pointer (qva) to NVRam location of data to copy
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ENODEV if no flash driver is loaded
+ EIO if a flash driver is loaded
+
+--*/
+
+{
+ //
+ // If there is no flash driver, return an error.
+ //
+ if (HalpFlashDriver == NULL) {
+ return ENODEV;
+ }
+
+ return EIO;
+}
+
+PFLASH_DRIVER
+HalpInitializeFlashDriver(
+ IN PCHAR NvRamPtr
+ )
+/*++
+
+Routine Description:
+
+ This routine attempts to recognize the flash device present in the
+ system by calling each known flash driver's Initialize() function
+ with the address passed in. The Initialize() functions will each
+ return NULL if they do not recognize the flash device at the specified
+ address and a pointer to a FLASH_DRIVER structure if the device is
+ recognized. This routine looks until it either recognizes a flash device
+ or runs out of known flash devices.
+
+Arguments:
+
+ NvRamPtr - a pointer to an address within the flash device
+
+Return Value:
+
+ A pointer to the FLASH_DRIVER structure of the driver which corresponds
+ to the flash device in the system. NULL if no known flash device was
+ recognized.
+
+--*/
+{
+ PFLASH_DRIVER FlashDriver = NULL;
+ ULONG DriverNumber;
+
+ for(DriverNumber=0; FlashDriverList[DriverNumber] != NULL; DriverNumber++) {
+ FlashDriver = FlashDriverList[DriverNumber](NvRamPtr);
+ if (FlashDriver != NULL) {
+ break;
+ }
+ }
+
+#ifdef ALPHA_FW_SERDEB
+ if (FlashDriver != NULL) {
+ SerFwPrint("Flash device found at %08x: %s\r\n",
+ NvRamPtr,
+ FlashDriver->DeviceName);
+ } else {
+ SerFwPrint("ERROR: No flash device found at %08x\r\n", NvRamPtr);
+ }
+#endif
+
+ return FlashDriver;
+}
+
diff --git a/private/ntos/nthals/halalpha/flash8k.h b/private/ntos/nthals/halalpha/flash8k.h
new file mode 100644
index 000000000..32a5f18f2
--- /dev/null
+++ b/private/ntos/nthals/halalpha/flash8k.h
@@ -0,0 +1,130 @@
+// flash8k.h
+
+#ifndef _FLASH8K_H_
+#define _FLASH8K_H_
+
+#ifdef FLASH8K_INCLUDE_FILES
+#include "halp.h"
+#include "arccodes.h"
+#endif //FLASH8K_DONT_INCLUDE_FILES
+
+//
+// The value of HalpCMOSRamBase must be set at initialization
+//
+
+typedef enum _FLASH_OPERATIONS {
+ FlashByteWrite,
+ FlashEraseBlock
+} FLASH_OPERATIONS, *PFLASH_OPERATIONS;
+
+typedef struct _FLASH_DRIVER {
+ PCHAR DeviceName;
+ ARC_STATUS (*SetReadModeFunction)(PUCHAR address);
+ ARC_STATUS (*WriteByteFunction)(PUCHAR address, UCHAR data);
+ ARC_STATUS (*EraseBlockFunction)(PUCHAR address);
+ PUCHAR (*BlockAlignFunction)(PUCHAR address);
+ UCHAR (*ReadByteFunction)(PUCHAR address);
+ BOOLEAN (*OverwriteCheckFunction)(UCHAR olddata, UCHAR newdata);
+ ULONG (*BlockSizeFunction)(PUCHAR address);
+ ULONG (*GetLastErrorFunction)(VOID);
+ ULONG DeviceSize;
+ UCHAR ErasedData;
+} FLASH_DRIVER, *PFLASH_DRIVER;
+
+extern PFLASH_DRIVER HalpFlashDriver;
+
+#define WRITE_CONFIG_RAM_DATA(boffset,data) \
+ WRITE_REGISTER_UCHAR((PUCHAR)(boffset),((data) & 0xff))
+
+#define READ_CONFIG_RAM_DATA(boffset) \
+ READ_REGISTER_UCHAR((PUCHAR)(boffset))
+
+
+PFLASH_DRIVER
+HalpInitializeFlashDriver(
+ IN PCHAR NvRamPtr
+ );
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ );
+
+
+//
+// The following macros define the HalpFlash8k*() functions in terms
+// of the FlashDriver variable. FlashDriver points to a structure
+// containing information about the currently active flash driver.
+// Information in the structure pointed to by FlashDriver includes
+// functions within the driver to perform all device-dependent operations.
+//
+
+#define HalpFlash8kSetReadMode(boffset) \
+ HalpFlashDriver->SetReadModeFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kReadByte(boffset) \
+ HalpFlashDriver->ReadByteFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kWriteByte(boffset, data) \
+ HalpFlashDriver->WriteByteFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)), ((data) & 0xff))
+
+#define HalpFlash8kOverwriteCheck(olddata, newdata) \
+ HalpFlashDriver->OverwriteCheckFunction( \
+ (olddata) & 0xff, (newdata) & 0xff)
+
+#define HalpFlash8kEraseBlock(boffset) \
+ HalpFlashDriver->EraseBlockFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kBlockAlign(boffset) \
+ HalpFlashDriver->BlockAlignFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kBlockSize(boffset) \
+ HalpFlashDriver->BlockSizeFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kCheckStatus(boffset, operation) \
+ HalpFlashDriver->CheckStatusFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)), (operation))
+
+#define HalpFlash8kGetLastError() \
+ HalpFlashDriver->GetLastErrorFunction()
+
+
+//
+// Error codes for GetLastError()
+//
+#define ERROR_VPP_LOW 1L
+#define ERROR_ERASE_ERROR 2L
+#define ERROR_WRITE_ERROR 3L
+#define ERROR_TIMEOUT 4L
+#define ERROR_UNKNOWN 127L
+
+#endif // _FLASH8K_H_
diff --git a/private/ntos/nthals/halalpha/flashdrv.c b/private/ntos/nthals/halalpha/flashdrv.c
new file mode 100644
index 000000000..6c87efecd
--- /dev/null
+++ b/private/ntos/nthals/halalpha/flashdrv.c
@@ -0,0 +1,23 @@
+//
+// Flash Drivers
+//
+// extern declarations of each known flash driver's Initialize() funcion
+// are needed here for addition into the list of known drivers.
+//
+// FlashDriverList is an array of driver Initialize() functions used to
+// identify the flash device present in the system. The last entry
+// in FlashDriverList must be NULL.
+//
+#include "halp.h"
+#include "flash8k.h"
+
+extern PFLASH_DRIVER I28F008SA_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F080_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F040_Initialize(PUCHAR);
+
+PFLASH_DRIVER (*FlashDriverList[])(PUCHAR) = {
+ I28F008SA_Initialize,
+ Am29F080_Initialize,
+ Am29F040_Initialize,
+ NULL};
+
diff --git a/private/ntos/nthals/halalpha/fwreturn.c b/private/ntos/nthals/halalpha/fwreturn.c
new file mode 100644
index 000000000..bf11d8c27
--- /dev/null
+++ b/private/ntos/nthals/halalpha/fwreturn.c
@@ -0,0 +1,255 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+ Stolen wholesale from s3return.c in ../mips.
+ Assumes that the firmware entry vector defined in the HAL spec has
+ been set up and is reachable through the System Parameter Block.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+ Miche Baker-Harvey (miche) 4-Jun-1992
+
+Revision History:
+
+ 14-Dec-1993 Joe Notarangelo
+ Add MP support, use reboot encoding to return to firmware
+
+--*/
+
+#include "halp.h"
+
+#if !defined(NT_UP)
+
+
+VOID // #definition of KiIpiSendPacket
+KiIpiSendPacket( // not in ntmp.h. Define here
+ IN KAFFINITY TargetProcessors,
+ IN PKIPI_WORKER WorkerFunction,
+ IN PVOID Parameter1,
+ IN PVOID Parameter2,
+ IN PVOID Parameter3
+ );
+#endif
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ );
+
+VOID
+HalpShutdownSystem(
+ ULONG HaltReasonCode
+ );
+
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+Revision History:
+
+ 09-Jul-1992 Jeff McLeman (mcleman)
+ In all cases, except for ArcEnterInteractiveMode, invoke a
+ halt to restart the firmware. (Enter PAL)
+ 04-Mar-1993 Joe Mitchell (DEC)
+ Invoke a routine to call halt in ALL cases. Before calling this routine,
+ pass a value to the firmware indicating the desired function via
+ the Restart Block save area.
+
+--*/
+
+{
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine)
+ {
+ case HalHaltRoutine:
+ HalpShutdownSystem( AXP_HALT_REASON_POWEROFF );
+ break;
+ case HalPowerDownRoutine:
+ HalpShutdownSystem( AXP_HALT_REASON_POWERFAIL );
+ break;
+ case HalRestartRoutine:
+ HalpShutdownSystem( AXP_HALT_REASON_RESTART );
+ break;
+ case HalRebootRoutine:
+ HalpShutdownSystem( AXP_HALT_REASON_REBOOT );
+ break;
+ case HalInteractiveModeRoutine:
+ HalpShutdownSystem( AXP_HALT_REASON_HALT );
+ break;
+ default:
+ HalDisplayString("Unknown ARCS restart function.\n");
+ DbgBreakPoint();
+ }
+
+ /* NOTREACHED */
+ HalDisplayString("Illegal return from ARCS restart function.\n");
+ DbgBreakPoint();
+}
+
+VOID
+HalpShutdownSystem(
+ ULONG HaltReasonCode
+ )
+/*++
+
+Routine Description:
+
+ This function causes a system shutdown so that each processor in
+ the system will return to the firmware. A processor returns to
+ the firmware by executing the reboot call pal function.
+
+Arguments:
+
+ HaltReasonCode - Supplies the reason code for the halt.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESTART_BLOCK RestartBlock; // Boot Master Restart Block
+#if !defined(NT_UP)
+ KAFFINITY TargetProcessors;
+ KIRQL OldIrql;
+ PKPRCB Prcb = PCR->Prcb;
+ ULONG Wait;
+#endif
+
+ //
+ // Reset video using NT driver's HwResetHw routine
+ //
+
+ HalpVideoReboot();
+
+ //
+ // Reset the HAE Registers to 0
+ //
+
+ HalpResetHAERegisters();
+
+ //
+ // Write the halt reason code into the restart block of the
+ // boot master processor.
+ //
+
+ RestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if( RestartBlock != NULL ){
+ RestartBlock->u.Alpha.HaltReason = HaltReasonCode;
+ }
+
+#if !defined(NT_UP)
+
+#define REBOOT_WAIT_LIMIT (5 * 1000) // loop count for 5 second wait
+
+ //
+ // Raise Irql to block all interrupts except errors and IPIs.
+ //
+
+ KeRaiseIrql( CLOCK_LEVEL, &OldIrql );
+
+ //
+ // Send an IPI to each processor.
+ //
+ TargetProcessors = HalpActiveProcessors;
+ TargetProcessors &= ~Prcb->SetMember;
+
+#if HALDBG
+
+ DbgPrint( "HalpShutdown: TargetProcessors = %x, Active = %x\n",
+ TargetProcessors, HalpActiveProcessors );
+
+#endif //HALDBG
+
+
+ KiIpiSendPacket( TargetProcessors,
+ (PKIPI_WORKER) HalpReboot,
+ NULL,
+ NULL,
+ NULL );
+
+
+ //
+ // If the current processor is the primary, it must reboot and handle
+ // the firmware restart. If a secondary processor is executing this
+ // shutdown, then it waits to verify that the primary has shutdown so
+ // that the restart can be performed. If the primary doesn't reach the
+ // firmware, the system is toasted and a message is printed.
+ //
+ if ( Prcb->Number == HAL_PRIMARY_PROCESSOR )
+ {
+ HalpReboot; // Never to return
+ }
+
+ //
+ // Wait until the primary processor has rebooted and signalled that
+ // it has returned to the firmware by indicating that the processor
+ // is not started in the BootStatus of its restart block. (ProcessorStart=0)
+ // However, put a timeout on the check in case the primary processor
+ // is currently wedged (it may not be able to receive the IPI).
+ //
+
+ Wait = 0;
+ while( RestartBlock->BootStatus.ProcessorStart == 0 &&
+ Wait < REBOOT_WAIT_LIMIT ) {
+ //
+ // The Primary processor is still running. Stall for a while
+ // and increment the wait count.
+ //
+
+ KeStallExecutionProcessor( 1000 ); // 1000000 );
+ Wait ++;
+
+ } //end while( Wait < REBOOT_WAIT_LIMIT )
+
+
+ //
+ // if the wait timed out print messages to alert the user.
+ //
+ if ( Wait >= REBOOT_WAIT_LIMIT )
+ {
+ HalDisplayString( "The Primary Processor was not shutdown.\n" );
+ HalDisplayString( "Power off your system before restarting.\n" );
+ }
+
+#endif //!NT_UP
+
+ //
+ // Reboot this processor.
+ //
+
+ HalpReboot();
+
+}
+
diff --git a/private/ntos/nthals/halalpha/gru.h b/private/ntos/nthals/halalpha/gru.h
new file mode 100644
index 000000000..f1cbe1067
--- /dev/null
+++ b/private/ntos/nthals/halalpha/gru.h
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ gru.h
+
+Abstract:
+
+ This file defines the structures and definitions for the GRU ASIC.
+
+Author:
+
+ Steve Brooks 7-July-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _GRUH_
+#define _GRUH_
+
+//
+// Define locations of the GRU ASIC registers
+//
+
+#define GRU_CSRS_PHYSICAL ((ULONGLONG)0x8780000000)
+#define GRU_CSRS_QVA HAL_MAKE_QVA(GRU_CSRS_PHYSICAL)
+
+#define GRU_CACHECNFG_CSRS_PHYSICAL ((ULONGLONG)0x8780000200)
+#define GRU_CACHECNFG_CSRS_QVA HAL_MAKE_QVA(GRU_CSRS_PHYSICAL)
+
+//
+// Define various masks for the GRU registers
+//
+
+#define GRU_ENABLE_EISA_INT 0x80000000
+#define GRU_SET_LEVEL_INT 0x00000000
+#define GRU_SET_LOW_INT 0x8F000000
+#define GRU_PCI_MASK_INT 0x000FFFFF
+#define GRU_EISA_MASK_INT 0x80000000
+
+//
+// Define GRU Interrupt register access structure:
+//
+
+typedef struct _GRU_INTERRUPT_CSRS{
+ UCHAR IntReq; // (00) Interrupt Request Register
+ UCHAR Filler1; // (20)
+ UCHAR IntMask; // (40) Interrupt Mask Register
+ UCHAR Filler2; // (60)
+ UCHAR IntEdge; // (80) Edge/Level Interrupt Select
+ UCHAR Filler3; // (a0)
+ UCHAR IntHiLo; // (c0) Active High/Low select register
+ UCHAR Filler4; // (e0)
+ UCHAR IntClear; // (100) Interrupt Clear register
+} GRU_INTERRUPT_CSRS, *PGRU_INTERRUPT_CSRS;
+
+//
+// Define GRU cache register structure.
+//
+
+typedef union _GRU_CACHECNFG{
+ struct{
+ ULONG Reserved0 : 4; //
+ ULONG ClockDivisor: 4; // Clock divisor for EV5.
+ ULONG Reserved1 : 3; //
+ ULONG CacheSpeed : 2; // SRAM cache access time.
+ ULONG CacheSize : 3; // SRAM cache size.
+ ULONG Mmb0Config : 4; // Presence and type of MMB0.
+ ULONG Reserved2 : 4; //
+ ULONG Mmb1Config : 4; // Presence and type of MMB1.
+ ULONG Reserved3 : 4; //
+ };
+ ULONG all;
+} GRU_CACHECNFG, *PGRU_CACHECNFG;
+
+#endif // _GRUH_
diff --git a/private/ntos/nthals/halalpha/haldebug.c b/private/ntos/nthals/halalpha/haldebug.c
new file mode 100644
index 000000000..543354e72
--- /dev/null
+++ b/private/ntos/nthals/halalpha/haldebug.c
@@ -0,0 +1,58 @@
+#if HALDBG
+
+/*++
+
+Copyright (c) 1993-1994 Digital Equipment Corporation
+
+Module Name:
+
+ haldebug.c
+
+Abstract:
+
+ This module contains debugging code for the HAL.
+
+Author:
+
+ Steve Jenness 09-Nov-1993
+ Joe Notarangelo 28-Jan-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+#include <stdarg.h>
+#include <stdio.h>
+
+ULONG HalDebugMask = 0;
+UCHAR HalDebugBuffer[512];
+
+VOID
+HalDebugPrint(
+ ULONG DebugPrintMask,
+ PCCHAR DebugMessage,
+ ...
+ )
+{
+ va_list ap;
+ va_start(ap, DebugMessage);
+
+ if( (DebugPrintMask & HalDebugMask) != 0 )
+ {
+ vsprintf(HalDebugBuffer, DebugMessage, ap);
+ DbgPrint(HalDebugBuffer);
+ }
+
+ va_end(ap);
+}
+
+#endif // HALDBG
+
diff --git a/private/ntos/nthals/halalpha/haldump.c b/private/ntos/nthals/halalpha/haldump.c
new file mode 100644
index 000000000..2b95e24d8
--- /dev/null
+++ b/private/ntos/nthals/halalpha/haldump.c
@@ -0,0 +1,83 @@
+#ifdef HAL_DBG
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ haldump.c
+
+Abstract:
+
+ This module is used to dump blocks of data during debugging and unit
+ testing.
+
+Author:
+
+ Steve Jenness 93.12.17
+
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalpDumpBlock (
+ IN PUCHAR Buffer,
+ IN LONG BufferLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dumps a block of data to the debugger.
+
+Arguments:
+
+ Buffer - Pointer to data to be dumped.
+ BufferLength - Number of bytes to be dumped.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Offset = 0;
+ ULONG ByteCount = 0;
+ UCHAR CharBuffer[17];
+ PUCHAR CharPtr;
+
+ CharBuffer[16] = 0;
+ while (BufferLength > 0) {
+ DbgPrint(" %08x: ", Offset);
+ CharPtr = &CharBuffer[0];
+
+ DbgPrint(" %02x %02x %02x %02x %02x %02x %02x %02x",
+ Buffer[0], Buffer[1], Buffer[2], Buffer[3],
+ Buffer[4], Buffer[5], Buffer[6], Buffer[7]);
+ DbgPrint(" %02x %02x %02x %02x %02x %02x %02x %02x",
+ Buffer[8], Buffer[9], Buffer[10], Buffer[11],
+ Buffer[11], Buffer[13], Buffer[14], Buffer[15]);
+ do {
+ if ((*Buffer >= 0x20) && (*Buffer <= 0x7e)) {
+ *CharPtr++ = *Buffer++;
+ } else {
+ *CharPtr++ = '.';
+ Buffer++;
+ }
+ Offset++;
+ } while ((Offset & 0xf) != 0);
+
+ DbgPrint(" %s\n", &CharBuffer[0]);
+ Offset += 16;
+ BufferLength -= 16;
+ }
+}
+
+#endif //HAL_DBG
diff --git a/private/ntos/nthals/halalpha/halisa.h b/private/ntos/nthals/halalpha/halisa.h
new file mode 100644
index 000000000..2ebe313ae
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halisa.h
@@ -0,0 +1,89 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ halisa.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ EISA/ISA specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+ Jeff McLeman (mcleman) 01-Jun-1992
+
+Revision History:
+
+ 17-Jul-1992 Jeff McLeman (mcleman)
+ Remove adapter object structure from here.
+
+ 01-Jun-1992 Jeff McLeman
+ modify for Jensen EISA/ISA
+
+--*/
+
+#ifndef _HALISA_
+#define _HALISA_
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define __64K (0x10000)
+#define MAXIMUM_ISA_MAP_REGISTER (__64K >> PAGE_SHIFT)
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define __16MB (0x1000000)
+#define MAXIMUM_ISA_PHYSICAL_ADDRESS (__16MB)
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+
+#endif // _HALISA_
diff --git a/private/ntos/nthals/halalpha/halp.h b/private/ntos/nthals/halalpha/halp.h
new file mode 100644
index 000000000..c36428a82
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halp.h
@@ -0,0 +1,1095 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992,1993 Digital Equipment Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 22-Apr-1992
+
+
+Revision History:
+
+ 09-Jul-1992 Jeff McLeman (mcleman)
+ If processor is an Alpha, include XXHALP.C for Alpha.
+
+ 24-Sep-1993 Joe Notarangelo
+ Incorporate definitions from xxhalp.h and jxhalp.h.
+ Restructure so that related modules are together.
+
+ 5-Jan-1994 Eric Rehm
+ Incorport support for PCI and IoAssignResources.
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#include "nthal.h"
+#include "hal.h"
+#include "pci.h"
+#include "errframe.h"
+
+
+//
+// Declare HAL spinlocks.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Define external references.
+//
+
+extern ULONG HalpClockFrequency;
+extern ULONG HalpClockMegaHertz;
+
+extern ULONG HalpProfileCountRate;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern BOOLEAN LessThan16Mb;
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+
+//
+// Define global data used to relate PCI devices to their interrupt
+// vector.
+//
+
+extern ULONG *HalpPCIPinToLineTable;
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaIntAckBase;
+extern PVOID HalpCMOSRamBase;
+extern PVOID HalpRtcAddressPort;
+extern PVOID HalpRtcDataPort;
+
+extern POBJECT_TYPE *IoAdapterObjectType;
+
+//
+// Determine if a virtual address is really a physical address.
+//
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+//
+// Define the different address spaces.
+//
+
+typedef enum _ADDRESS_SPACE_TYPE{
+ BusMemory=0,
+ BusIo = 1,
+ UserBusMemory = 2,
+ UserBusIo = 3,
+ KernelPciDenseMemory = 4,
+ UserPciDenseMemory = 6,
+} ADDRESS_SPACE_TYPE, *PADDRESS_SPACE_TYPE;
+
+//
+// Prototype for Memory Size determination routine
+//
+ULONGLONG
+HalpGetMemorySize(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+ULONGLONG
+HalpGetContiguousMemorySize(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+//
+// Prototype for BCache Size determination routine
+//
+ULONG
+HalpGetBCacheSize(
+ ULONGLONG ContiguousMemorySize
+ );
+
+//
+// Define initialization routine prototypes.
+//
+
+BOOLEAN
+HalpCreateDmaStructures (
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ );
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+ULONG
+HalpMapDebugPort (
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ );
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ );
+
+//
+// Error Frame Initialization and Support Routines
+//
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ );
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ );
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+ );
+
+VOID
+HalpGetSystemInfo(
+ SYSTEM_INFORMATION *SystemInfo
+ );
+
+//
+// Define profiler function prototypes.
+//
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+//
+// Define interrupt function prototypes.
+//
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+VOID
+HalpSecondaryClockInterrupt (
+ VOID
+ );
+
+VOID
+HalpIpiInterruptHandler (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpPerformanceCounter0Interrupt (
+ VOID
+ );
+
+VOID
+HalpPerformanceCounter1Interrupt (
+ VOID
+ );
+
+VOID
+HalpPerformanceCounter2Interrupt (
+ VOID
+ );
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpVideoReboot(
+ VOID
+ );
+
+//
+// Define microprocessor-specific function prototypes and structures.
+//
+
+//
+// 21064 (EV4) processor family.
+//
+
+typedef enum _EV4Irq{
+ Irq0 = 0,
+ Irq1 = 1,
+ Irq2 = 2,
+ Irq3 = 3,
+ Irq4 = 4,
+ Irq5 = 5,
+ MaximumIrq
+} EV4Irq, *PEV4Irq;
+
+typedef struct _EV4IrqStatus{
+ ULONG Vector;
+ BOOLEAN Enabled;
+ KIRQL Irql;
+ UCHAR Priority;
+} EV4IrqStatus, *PEV4IrqStatus;
+
+typedef struct _EV4ProfileCount {
+ ULONG ProfileCount[2];
+ ULONG ProfileCountReload[2];
+} EV4ProfileCount, *PEV4ProfileCount;
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ );
+
+VOID
+HalpDisable21064HardwareInterrupt(
+ IN ULONG Irq
+ );
+
+VOID
+HalpDisable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ );
+
+VOID
+HalpDisable21064PerformanceInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnable21064HardwareInterrupt(
+ IN ULONG Irq,
+ IN KIRQL Irql,
+ IN ULONG Vector,
+ IN UCHAR Priority
+ );
+
+VOID
+HalpEnable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ );
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ );
+
+VOID
+HalpEnable21064PerformanceInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql
+ );
+
+ULONG
+HalpGet21064PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+ULONG
+HalpGet21064CorrectableVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+//
+// 21164 processor family.
+//
+
+#ifdef EV5
+
+typedef struct _EV5ProfileCount {
+ ULONG ProfileCount[3];
+ ULONG ProfileCountReload[3];
+} EV5ProfileCount, *PEV5ProfileCount;
+
+VOID
+HalpInitialize21164Interrupts(
+ VOID
+ );
+
+VOID
+HalpStart21164Interrupts(
+ VOID
+ );
+
+ULONG
+HalpGet21164PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+ULONGLONG
+HalpRead21164PerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpWrite21164PerformanceCounter(
+ ULONGLONG PmCtr,
+ ULONG CBOXMux1,
+ ULONG CBOXMux2
+ );
+
+ULONG
+HalpGet21164CorrectableVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+#endif // EV5 specific definitions
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Define memory utility function prototypes.
+//
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NumberOfPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberOfPages
+ );
+
+PVOID
+HalpRemapVirtualAddress(
+ IN PVOID VirtualAddress,
+ IN PVOID PhysicalAddress
+ );
+
+#if HALDBG
+
+VOID
+HalpDumpMemoryDescriptors(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+#endif
+
+//
+// Low-level routine interfaces.
+//
+
+VOID
+HalpReboot(
+ VOID
+ );
+
+VOID
+HalpImb(
+ VOID
+ );
+
+VOID
+HalpMb(
+ VOID
+ );
+
+ULONG
+HalpRpcc(
+ VOID
+ );
+
+MCES
+HalpReadMces(
+ VOID
+ );
+
+MCES
+HalpWriteMces(
+ IN MCES Mces
+ );
+
+VOID
+HalpWritePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN BOOLEAN Enable,
+ IN ULONG MuxControl OPTIONAL,
+ IN ULONG EventCount OPTIONAL
+ );
+
+//
+// Define synonym for KeStallExecutionProcessor.
+//
+
+#define HalpStallExecution KeStallExecutionProcessor
+
+//
+// Define Bus Handler support function prototypes.
+//
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ );
+
+//
+// Define SIO support function prototypes.
+//
+
+VOID
+HalpInitializeSioInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ );
+
+//
+// Define EISA support function prototypes.
+//
+
+BOOLEAN
+HalpInitializeEisaInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaInitializeDma(
+ VOID
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ VOID
+ );
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters
+ );
+
+BOOLEAN
+HalpMapEisaTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG LogicalAddress,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpFlushEisaAdapter(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+ULONG
+HalpReadEisaDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ );
+
+
+ULONG
+HalpGetEisaData(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+//
+// Define PCI support function prototypes.
+//
+
+VOID
+HalpInitializePCIBus (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPCIBusHandler (
+ IN ULONG BusNo,
+ IN ULONG HwBusNo,
+ IN BOOLEAN BusIsAcrossPPB,
+ IN ULONG PPBBusNumber,
+ IN PCI_SLOT_NUMBER PPBSlotNumber
+ );
+
+VOID
+HalpRegisterPCIInstallHandler(
+ IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
+);
+
+NTSTATUS
+HalpDefaultPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+VOID
+HalpDeterminePCIDevicesPresent(
+ IN PBUS_HANDLER Bus
+);
+
+BOOLEAN
+HalpInitializePCIInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnablePCIInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePCIInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpPCIInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+//
+// Environment variable support
+//
+
+ARC_STATUS
+HalpReadNVRamBuffer(
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpWriteNVRamBuffer(
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCopyNVRamBuffer(
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ );
+
+#if defined(TAGGED_NVRAM)
+
+//
+// NVRAM API
+//
+
+UCHAR
+HalpGetNVRamUchar(
+ IN ULONG Offset
+ );
+
+VOID
+HalpSetNVRamUchar(
+ IN ULONG Offset,
+ IN UCHAR Data
+ );
+
+USHORT
+HalpGetNVRamUshort(
+ IN ULONG Offset
+ );
+
+VOID
+HalpSetNVRamUshort(
+ IN ULONG Offset,
+ IN USHORT Data
+ );
+
+ULONG
+HalpGetNVRamUlong(
+ IN ULONG Offset
+ );
+
+VOID
+HalpSetNVRamUlong(
+ IN ULONG Offset,
+ IN ULONG Data
+ );
+
+VOID
+HalpMoveMemoryToNVRam(
+ IN ULONG Offset,
+ IN PVOID Data,
+ IN ULONG Length
+ );
+
+VOID
+HalpMoveNVRamToMemory(
+ IN PVOID Data,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpMoveNVRamToNVRam(
+ IN ULONG Destination,
+ IN ULONG Source,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetNVRamStringLength(
+ IN ULONG Offset
+ );
+
+VOID
+HalpMoveMemoryStringToNVRam(
+ IN ULONG Offset,
+ IN PCHAR Data
+ );
+
+VOID
+HalpMoveNVRamStringToMemory(
+ IN PUCHAR Data,
+ IN ULONG Offset
+ );
+
+VOID
+HalpZeroNVRam(
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpComputeNVRamChecksum(
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpIsNVRamRegion0Valid(
+ VOID
+ );
+
+BOOLEAN
+HalpSynchronizeNVRamRegion0(
+ IN BOOLEAN RecomputeChecksum
+ );
+
+BOOLEAN
+HalpInitializeNVRamRegion0(
+ IN BOOLEAN Synchronize
+ );
+
+ULONG
+HalpGetNVRamFwConfigOffset(
+ VOID
+ );
+
+ULONG
+HalpGetNVRamFwConfigLength(
+ VOID
+ );
+
+ULONG
+HalpGetNVRamLanguageOffset(
+ VOID
+ );
+
+ULONG
+HalpGetNVRamLanguageLength(
+ VOID
+ );
+
+ULONG
+HalpGetNVRamEnvironmentOffset(
+ VOID
+ );
+
+ULONG
+HalpGetNVRamEnvironmentLength(
+ VOID
+ );
+
+#if defined(EISA_PLATFORM)
+
+BOOLEAN
+HalpIsNVRamRegion1Valid(
+ VOID
+ );
+
+BOOLEAN
+HalpSynchronizeNVRamRegion1(
+ IN BOOLEAN RecomputeChecksum
+ );
+
+BOOLEAN
+HalpInitializeNVRamRegion1(
+ IN BOOLEAN Synchronize
+ );
+
+#endif // EISA_PLATFORM
+
+#endif // TAGGED_NVRAM
+
+//
+// Error handling function prototype.
+//
+
+typedef
+BOOLEAN
+KBUS_ERROR_ROUTINE(
+ IN struct _EXCEPTION_RECORD *ExceptionRecord,
+ IN struct _KEXCEPTION_FRAME *ExceptionFrame,
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+KBUS_ERROR_ROUTINE HalMachineCheck;
+
+VOID
+HalpInitializeMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors
+ );
+
+//
+// Low-level I/O function prototypes.
+//
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ );
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ IN PVOID ServiceContext
+ );
+
+UCHAR
+HalpReadClockRegister(
+ IN UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister(
+ IN UCHAR Register,
+ IN UCHAR Value
+ );
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+//
+// Define the I/O superpage enable VA base.
+//
+
+#define SUPERPAGE_ENABLE ((ULONGLONG)0xfffffc0000000000)
+
+//
+// Numeric constants used in the HAL.
+//
+
+#define __1K (0x400)
+#define __2K (0x800)
+#define __4K (0x1000)
+#define __8K (0x2000)
+#define __16K (0x4000)
+#define __32K (0x8000)
+#define __64K (0x10000)
+#define __128K (0x20000)
+#define __256K (0x40000)
+#define __512K (0x80000)
+#define __1MB (0x100000)
+#define __2MB (0x200000)
+#define __4MB (0x400000)
+#define __8MB (0x800000)
+#define __16MB (0x1000000)
+#define __32MB (0x2000000)
+#define __64MB (0x4000000)
+#define __128MB (0x8000000)
+#define __256MB (0x10000000)
+#define __512MB (0x20000000)
+#define __1GB (0x40000000)
+#define __2GB (0x80000000)
+
+//
+// CPU mask values. Used to interpret cpu bitmap values.
+//
+#define HAL_CPU0_MASK ((ULONG)0x1)
+#define HAL_CPU1_MASK ((ULONG)0x2)
+#define HAL_CPU2_MASK ((ULONG)0x4)
+#define HAL_CPU3_MASK ((ULONG)0x8)
+
+//
+// HAL Debugging Support.
+//
+
+#if HALDBG
+
+#define DebugPrint(x) HalDebugPrint x
+
+VOID
+HalDebugPrint(
+ ULONG DebugPrintLevel,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+#else //HALDBG
+
+#define DebugPrint(x)
+
+#endif //HALDBG
+
+//
+// Define HAL debugging masks.
+//
+
+//
+// Trace IoMapTransfer, IoFlushAdapterBuffers
+//
+
+#define HALDBG_IOMT (0x1)
+
+//
+// Trace Map Register allocations and frees
+//
+
+#define HALDBG_MAPREG (0x2)
+
+//
+// Include machine-dependent definitions.
+//
+// N.B. - Each platform that includes this file must have a machdep.h
+// include file in its private directory.
+//
+
+#include <machdep.h>
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halalpha/halpal.s b/private/ntos/nthals/halalpha/halpal.s
new file mode 100644
index 000000000..d34a29084
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halpal.s
@@ -0,0 +1,276 @@
+// TITLE("Alpha PAL funtions for HAL")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// halpal.s
+//
+// Abstract:
+//
+// This module implements routines to call PAL functions
+// from the Hal.
+//
+//
+// Author:
+//
+// Jeff McLeman (mcleman) 09-Jul-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 13-Jul-1992 Jeff McLeman (mcleman)
+// add HalpMb to functions.
+//
+// 14-Dec-1993 Joe Notarangelo
+// use new encoding to return to firmware: HalpReboot instead of
+// HalpHalt
+//--
+
+#include "halalpha.h"
+
+//++
+//
+// VOID
+// HalpReboot(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to reboot the Alpha processor.
+// This is used to restart the console firmware. (Note, MIPS does
+// not have a HALT instruction, so there had to be a mechanism to
+// restart the firware. Alpha merely reboots, which causes a jump
+// to firmware PAL, which restarts the firmware.)
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReboot)
+
+ REBOOT // call the PAL to reboot
+
+ .end HalpReboot
+
+//++
+//
+// VOID
+// HalpSwppal(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a SWPPAL
+// on the Alpha processor...
+//
+// Arguments:
+//
+// a0 The physical address to do the Swappal to.
+// a1 -- a5 Any other arguments to the PALcode.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSwppal)
+
+ SWPPAL // call the PAL to do a swap_pal
+
+ ret zero,(ra)
+
+ .end HalpSwppal
+
+
+//++
+//
+// VOID
+// HalpImb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue an Instruction
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpImb)
+
+ IMB // call the PAL to do an IMB
+
+ ret zero,(ra)
+
+ .end HalpImb
+
+
+//++
+//
+// VOID
+// HalpMb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a general
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpMb)
+
+ mb // memory barrier
+
+ ret zero, (ra)
+
+ .end HalpMb
+
+//++
+//
+// VOID
+// HalpCachePcrValues(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to cache values in the
+// PCR for faster access.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCachePcrValues)
+
+ CACHE_PCR_VALUES // call the palcode
+
+ ret zero,(ra)
+
+ .end HalpCachePcrValues
+//++
+//
+// ULONG
+// HalpRpcc(
+// )
+//
+// Routine Description:
+//
+// This function executes the RPCC (read processor cycle counter)
+// instruction.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The low-order 32 bits of the processor cycle counter is returned
+// as the function value.
+// N.B. At 125 MHz this counter wraps about every 30 seconds. It is
+// the caller's responsibility to deal with overflow or wraparound.
+//
+//--
+
+ LEAF_ENTRY(HalpRpcc)
+
+ rpcc v0 // get rpcc value
+ addl v0, zero, v0 // extend
+
+ ret zero, (ra) // return
+
+ .end HalpRpcc
+
+
+//++
+//
+// MCES
+// HalpReadMces(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Read the state of the MCES (Machine Check Error Summary)
+// internal processor register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// v0 - Current MCES value.
+//--
+
+ LEAF_ENTRY(HalpReadMces)
+
+ GET_MACHINE_CHECK_ERROR_SUMMARY // v0 = current value
+
+ ret zero, (ra) // return
+
+ .end HalpReadMces
+
+
+//++
+//
+// MCES
+// HalpWriteMces(
+// IN MCES Mces
+// )
+//
+// Routine Description:
+//
+// Update the current value of the MCES internal processor register.
+//
+// Arguments:
+//
+// Mces(a0) - Supplies the new value for the MCES register.
+//
+// Return Value:
+//
+// v0 - Previous MCES value.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteMces)
+
+ WRITE_MACHINE_CHECK_ERROR_SUMMARY // v0 = previous value
+
+ ret zero, (ra) // return
+
+ .end HalpWriteMces
diff --git a/private/ntos/nthals/halalpha/halpcsl.h b/private/ntos/nthals/halalpha/halpcsl.h
new file mode 100644
index 000000000..21b7d49df
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halpcsl.h
@@ -0,0 +1,187 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ halpcsl.h
+
+Abstract:
+
+ This header file includes the definitions for standard PC serial
+ port UARTs.
+
+ Stolen from jazzserp.h, which is a slightly different chip-
+ it has a 16 byte fifo - we are just double buffered.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Miche Baker-Harvey (miche) 01-June-1992
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALPCSL_
+#define _HALPCSL_
+
+
+//
+// Define base port numbers for serial lines inside the combo chip
+//
+
+#define COMA_PORT_BASE 0x3f8
+#define COMB_PORT_BASE 0x2f8
+
+
+//
+// Define serial port read registers structure.
+//
+
+typedef struct _SP_READ_REGISTERS {
+ UCHAR ReceiveBuffer;
+ UCHAR InterruptEnable;
+ UCHAR InterruptId;
+ UCHAR LineControl;
+ UCHAR ModemControl;
+ UCHAR LineStatus;
+ UCHAR ModemStatus;
+ UCHAR ScratchPad;
+} SP_READ_REGISTERS, *PSP_READ_REGISTERS;
+
+//
+// Define define serial port write registers structure.
+//
+
+typedef struct _SP_WRITE_REGISTERS {
+ UCHAR TransmitBuffer;
+ UCHAR InterruptEnable;
+ UCHAR FifoControl;
+ UCHAR LineControl;
+ UCHAR ModemControl;
+ UCHAR Reserved1;
+ UCHAR ModemStatus;
+ UCHAR ScratchPad;
+} SP_WRITE_REGISTERS, *PSP_WRITE_REGISTERS;
+
+//
+// Define serial port interrupt enable register structure.
+//
+
+typedef struct _SP_INTERRUPT_ENABLE {
+ UCHAR ReceiveEnable : 1;
+ UCHAR TransmitEnable : 1;
+ UCHAR LineStatusEnable : 1;
+ UCHAR ModemStatusEnable : 1;
+ UCHAR Reserved1 : 4;
+} SP_INTERRUPT_ENABLE, *PSP_INTERRUPT_ENABLE;
+
+//
+// Define serial port interrupt id register structure.
+//
+
+typedef struct _SP_INTERRUPT_ID {
+ UCHAR InterruptPending : 1;
+ UCHAR Identification : 3;
+ UCHAR Reserved1 : 2;
+ UCHAR FifoEnabled : 2; // always read as 0
+} SP_INTERRUPT_ID, *PSP_INTERRUPT_ID;
+
+//
+// Define serial port fifo control register structure.
+// This register is here for software compatibility, but there is
+// no FIFO on the 16C452
+//
+
+typedef struct _SP_FIFO_CONTROL {
+ UCHAR FifoEnable : 1;
+ UCHAR ReceiveFifoReset : 1;
+ UCHAR TransmitFifoReset : 1;
+ UCHAR DmaModeSelect : 1;
+ UCHAR Reserved1 : 2;
+ UCHAR ReceiveFifoLevel : 2;
+} SP_FIFO_CONTROL, *PSP_FIFO_CONTROL;
+
+//
+// Define serial port line control register structure.
+//
+
+typedef struct _SP_LINE_CONTROL {
+ UCHAR CharacterSize : 2;
+ UCHAR StopBits : 1;
+ UCHAR ParityEnable : 1;
+ UCHAR EvenParity : 1;
+ UCHAR StickParity : 1;
+ UCHAR SetBreak : 1;
+ UCHAR DivisorLatch : 1;
+} SP_LINE_CONTROL, *PSP_LINE_CONTROL;
+
+//
+// Line status register character size definitions.
+//
+
+#define FIVE_BITS 0x0 // five bits per character
+#define SIX_BITS 0x1 // six bits per character
+#define SEVEN_BITS 0x2 // seven bits per character
+#define EIGHT_BITS 0x3 // eight bits per character
+
+//
+// Line speed divisor definition. We get our baud rate clock
+// from the 82C106.
+//
+
+#define BAUD_RATE_2400 48 // divisor for 2400 baud
+#define BAUD_RATE_4800 24 // divisor for 4800 baud
+#define BAUD_RATE_9600 12 // divisor for 9600 baud
+#define BAUD_RATE_19200 6 // divisor for 19200 baud
+#define BAUD_RATE_38400 3 // divisor for 38400 baud
+#define BAUD_RATE_57600 2 // divisor for 57600 baud
+#define BAUD_RATE_115200 1 // divisor for 115200 baud
+
+//
+// Define serial port modem control register structure.
+//
+
+typedef struct _SP_MODEM_CONTROL {
+ UCHAR DataTerminalReady : 1;
+ UCHAR RequestToSend : 1;
+ UCHAR Reserved1 : 1;
+ UCHAR Interrupt : 1;
+ UCHAR loopBack : 1;
+ UCHAR Reserved2 : 3;
+} SP_MODEM_CONTROL, *PSP_MODEM_CONTROL;
+
+//
+// Define serial port line status register structure.
+//
+
+typedef struct _SP_LINE_STATUS {
+ UCHAR DataReady : 1;
+ UCHAR OverrunError : 1;
+ UCHAR ParityError : 1;
+ UCHAR FramingError : 1;
+ UCHAR BreakIndicator : 1;
+ UCHAR TransmitHoldingEmpty : 1;
+ UCHAR TransmitEmpty : 1;
+ UCHAR ReceiveFifoError : 1;
+} SP_LINE_STATUS, *PSP_LINE_STATUS;
+
+//
+// Define serial port modem status register structure.
+//
+
+typedef struct _SP_MODEM_STATUS {
+ UCHAR DeltaClearToSend : 1;
+ UCHAR DeltaDataSetReady : 1;
+ UCHAR TrailingRingIndicator : 1;
+ UCHAR DeltaReceiveDetect : 1;
+ UCHAR ClearToSend : 1;
+ UCHAR DataSetReady : 1;
+ UCHAR RingIndicator : 1;
+ UCHAR ReceiveDetect : 1;
+} SP_MODEM_STATUS, *PSP_MODEM_STATUS;
+
+#endif // _HALPCSL_
diff --git a/private/ntos/nthals/halalpha/halprof.c b/private/ntos/nthals/halalpha/halprof.c
new file mode 100644
index 000000000..62235fc7c
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halprof.c
@@ -0,0 +1,179 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ halprof.c
+
+Abstract:
+
+ This module implements the high level Profile Counter interface.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Steve Brooks 14-Feb-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ HalpProfileMapping[SourceInfo->Source].EventCount *
+ HalpProfileMapping[SourceInfo->Source].NumberOfTicks;
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source >= ProfileMaximum) {
+ return(FALSE);
+ }
+
+ return(HalpProfileMapping[Source].Supported);
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
diff --git a/private/ntos/nthals/halalpha/halprof.h b/private/ntos/nthals/halalpha/halprof.h
new file mode 100644
index 000000000..bb02e1ff0
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halprof.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ halprof.h
+
+Abstract:
+
+ This header file defines profile counter hardware in the
+ 82357 PIC chip.
+
+Author:
+
+ Jeff McLeman (mcleman) 5-June-1992
+
+Revision History:
+
+--*/
+
+#ifndef _HALPROF_
+#define _HALPROF_
+
+
+//
+// Define the timer values for the Profiler
+//
+
+#define PIC_BINARY 0
+#define PIC_BCD 1
+
+#define PIC_MODE0 0x00 // xxxx000x
+#define PIC_MODE1 0x02 // xxxx001x
+#define PIC_MODE2 0x04 // xxxx010x
+#define PIC_MODE3 0x06 // xxxx011x
+#define PIC_MODE4 0x08 // xxxx100x
+#define PIC_MODE5 0x0A // xxxx101x
+
+#define PIC_CLC 0x00 // xx00xxxx
+#define PIC_RWLSBO 0x10 // xx01xxxx
+#define PIC_RWMSBO 0x20 // xx10xxxx
+#define PIC_RWLSBMSB 0x30 // xx11xxxx
+
+#define PIC_SC0 0x00 // 00xxxxxx
+#define PIC_SC1 0x40 // 01xxxxxx
+#define PIC_SC2 0x80 // 10xxxxxx
+#define PIC_RBC 0xC0 // 11xxxxxx
+
+
+#define PIC_SCALE_FACTOR 10 * 1000 // # of microsecond units times 10.
+
+//
+// Define a macro to set and enable the system profiler timer.
+// Note that the interval 'c' is in 100nS units.
+// Note that also the interval is incremented AFTER it is scaled.
+// This is due to the fact that the timer counts down to 1 in mode 2
+//
+
+#define PIC_PROFILER_ON(c)\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->CommandMode1,\
+ (UCHAR)(PIC_BINARY | PIC_MODE2 | PIC_RWLSBMSB | PIC_SC0));\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Timer1,\
+ (UCHAR)((c) & 0xff) );\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Timer1,\
+ (UCHAR)(((c)>> 8) & 0xff) )
+
+//
+// Define a macro to shut down the profiler
+//
+
+#define PIC_PROFILER_OFF()\
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->CommandMode1,\
+ (ULONG)(PIC_BINARY | PIC_MODE4 | PIC_RWLSBMSB | PIC_SC0))
+
+
+#endif // _HALPROF_
diff --git a/private/ntos/nthals/halalpha/haltsup.s b/private/ntos/nthals/halalpha/haltsup.s
new file mode 100644
index 000000000..0fa6c8d0e
--- /dev/null
+++ b/private/ntos/nthals/halalpha/haltsup.s
@@ -0,0 +1,110 @@
+// TITLE("Halt Interrupt Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// haltsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field halt button
+// interrupts.
+//
+// Author:
+//
+// Joe Notarangelo 18-Dec-1992
+//
+// Environment:
+//
+// Kernel mode only, IRQL halt synchronization level.
+//
+// Revision History:
+//
+//--
+
+#if !(DBG)
+
+//
+// Boolean value that controls whether to break or not for a halt button
+// interrupt on a free build. The default value is zero and must be set
+// in the debugger to a non-zero value to trigger the breakpoint action
+// when the halt button is pressed.
+//
+
+ .data
+
+ .globl HalpHaltButtonBreak
+HalpHaltButtonBreak:
+ .long 0 : 1
+
+#endif //!DBG
+
+
+#include "halalpha.h"
+
+ SBTTL("Halt Interrupt Support")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of a halt interrupt caused by
+// a human pushing the halt switch on the system box. This routine is
+// connected directly into the IDT. The halt interrupt is mechanical and
+// does not require an interrupt acknowledge.
+//
+// Arguments:
+//
+// s6/fp - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+HaltRa: .space 8 // saved return address
+ .space 8 // fill for alignment
+HaltFrameLength:
+
+ NESTED_ENTRY(HalpHaltInterrupt, ExceptionFrameLength, zero)
+
+ lda sp, -HaltFrameLength(sp) // allocate stack frame
+ stq ra, HaltRa(sp) // save ra
+
+ PROLOGUE_END
+
+
+#if DBG
+
+//
+// Always stop in the debugger if this is a checked build.
+//
+
+ BREAK_DEBUG_STOP // stop in the debugger
+
+#else
+
+//
+// If this is a free build then check the variable HalpHaltButtonBreak,
+// if it is non-zero then take the breakpoint, otherwise ignore it.
+//
+
+ lda t0, HalpHaltButtonBreak // get the address of the boolean
+ ldl t0, 0(t0) // read the boolean
+ beq t0, 10f // if eq, don't stop
+
+ BREAK_DEBUG_STOP // stop in the debugger
+
+10:
+
+#endif //DBG
+
+ ldq ra, HaltRa(sp) // save ra
+ lda sp, HaltFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // interrupt is dismissed
+
+ .end HalpHaltInterrupt
diff --git a/private/ntos/nthals/halalpha/halvfont.h b/private/ntos/nthals/halalpha/halvfont.h
new file mode 100644
index 000000000..df634a336
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halvfont.h
@@ -0,0 +1,233 @@
+/*
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ halvfont.h
+
+Abstract:
+
+ 8x16 pixel fonts for the VGA video boot driver. Stolen from
+ David Conroy's Beta-machine fonts.
+
+
+
+Author:
+
+ John DeRosa 5/7/1992
+
+
+
+Revision History:
+
+ Jeff McLeman (DEC) 28-Jul-1992
+ Stole from FW to use with HAL and renamed to header file
+
+*/
+
+
+/*
+ * ASCII characters 0x20 -- 0x7f (space -- del). Each byte is one
+ * scan line, and each character is 2 rows.
+ */
+
+unsigned char vga8x16undef[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+unsigned char vga8x16chars[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0xFF, 0xFF, 0x66, 0x66,
+ 0xFF, 0xFF, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x3E, 0x7E, 0x60, 0x60, 0x7C, 0x3E,
+ 0x06, 0x06, 0x7E, 0x7C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x6C, 0x0C, 0x18, 0x18,
+ 0x30, 0x36, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x38, 0x7C, 0x6C, 0x6C, 0x38, 0x38, 0x70, 0x70,
+ 0xDE, 0xDE, 0xCC, 0xCC, 0xFE, 0x76, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x1C, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x1C, 0x0C, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x30, 0x38, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x38, 0x30, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x3C, 0x3C, 0xFF, 0xFF,
+ 0x3C, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E,
+ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x30, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x18,
+ 0x18, 0x30, 0x30, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x6E,
+ 0x76, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x38, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x0C, 0x0C,
+ 0x18, 0x18, 0x30, 0x30, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x0C, 0x0C, 0x18, 0x18,
+ 0x0C, 0x0C, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x1C, 0x1C, 0x3C, 0x3C,
+ 0x6C, 0x6C, 0x7E, 0x7E, 0x0C, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7E,
+ 0x06, 0x06, 0x06, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x3C, 0x70, 0x60, 0x60, 0x7C,
+ 0x7E, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x06, 0x06, 0x0C, 0x0C,
+ 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x3C, 0x3C,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3E,
+ 0x06, 0x06, 0x06, 0x0E, 0x3C, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x30, 0x20,
+ 0x00, 0x00, 0x00, 0x0E, 0x1C, 0x38, 0x70, 0xE0,
+ 0x70, 0x38, 0x1C, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00,
+ 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
+ 0x1C, 0x38, 0x70, 0xE0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x0C, 0x0C,
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x7C, 0xE6, 0xC2, 0xDA, 0xD6,
+ 0xD6, 0xDC, 0xC0, 0xE2, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0x66, 0x66,
+ 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x7E, 0x7C,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x60, 0x60,
+ 0x60, 0x60, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x7C, 0x6E, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7C,
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7C,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x60, 0x6E, 0x6E,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7E,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xD8, 0xD8, 0xF0, 0xF0,
+ 0xD8, 0xD8, 0xCC, 0xCC, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xEE, 0xEE, 0xFE, 0xD6,
+ 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x76, 0x76, 0x7E,
+ 0x7E, 0x6E, 0x6E, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x66, 0x66,
+ 0x7E, 0x7C, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x6A, 0x7C, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0xF8, 0xFC, 0xCC, 0xCC, 0xCC, 0xFC,
+ 0xF8, 0xD8, 0xCC, 0xCC, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x60, 0x70, 0x38,
+ 0x1C, 0x0E, 0x06, 0x06, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6,
+ 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x82, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18,
+ 0x18, 0x3C, 0x3C, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x3C,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x0C, 0x0C, 0x18, 0x18,
+ 0x30, 0x30, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x1E, 0x1E, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1E, 0x1E, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x30, 0x30, 0x18,
+ 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x78, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x78, 0x78, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x38, 0x38, 0x6C, 0x6C, 0xC6,
+ 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
+ 0x40, 0x60, 0x70, 0x38, 0x1C, 0x0C, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x06,
+ 0x3E, 0x7E, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x60,
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x3E, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0x7E, 0x60, 0x60, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x1E, 0x18, 0x18, 0x7E, 0x7E,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x7E, 0x7C,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x38, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x78,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xCC, 0xDC, 0xF8,
+ 0xF0, 0xF8, 0xD8, 0xCC, 0xCE, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE,
+ 0xD6, 0xD6, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x60, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x60,
+ 0x70, 0x3C, 0x0E, 0x06, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x7E, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1E, 0x0E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6,
+ 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x82, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C,
+ 0x3C, 0x18, 0x3C, 0x3C, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x7E, 0x7C,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x0C,
+ 0x18, 0x18, 0x30, 0x30, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x38, 0xF0,
+ 0xF0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0xE0, 0x30, 0x30, 0x30, 0x30, 0x38, 0x1E,
+ 0x1E, 0x38, 0x30, 0x30, 0x30, 0x30, 0xE0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xF2, 0xBE,
+ 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/private/ntos/nthals/halalpha/halvga.h b/private/ntos/nthals/halalpha/halvga.h
new file mode 100644
index 000000000..c393d49c7
--- /dev/null
+++ b/private/ntos/nthals/halalpha/halvga.h
@@ -0,0 +1,72 @@
+/*
+
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ halvga.h
+
+
+Abstract:
+
+ Defines registers for standard VGA alphanumeric color mode video.
+ (graphics, bw mode are not defined.)
+
+ Addresses are based on the VGA video ISA base address.
+
+
+Author:
+
+ John DeRosa 4/30/92
+
+
+Revision History:
+
+ 17-Feb-1994 Eric Rehm
+ Remove all references to VGA. HAL display routines are
+ now device-independent.
+
+*/
+
+#ifndef _HALVGA_
+#define _HALVGA_
+
+//
+// Define special character values for device-indpendent control functions.
+//
+
+#define ASCII_NUL 0x00
+#define ASCII_BEL 0x07
+#define ASCII_BS 0x08
+#define ASCII_HT 0x09
+#define ASCII_LF 0x0A
+#define ASCII_VT 0x0B
+#define ASCII_FF 0x0C
+#define ASCII_CR 0x0D
+#define ASCII_CSI 0x9B
+#define ASCII_ESC 0x1B
+#define ASCII_SYSRQ 0x80
+
+//
+// Define colors, HI = High Intensity
+//
+//
+
+#define FW_COLOR_BLACK 0x00
+#define FW_COLOR_RED 0x01
+#define FW_COLOR_GREEN 0x02
+#define FW_COLOR_YELLOW 0x03
+#define FW_COLOR_BLUE 0x04
+#define FW_COLOR_MAGENTA 0x05
+#define FW_COLOR_CYAN 0x06
+#define FW_COLOR_WHITE 0x07
+#define FW_COLOR_HI_BLACK 0x08
+#define FW_COLOR_HI_RED 0x09
+#define FW_COLOR_HI_GREEN 0x0A
+#define FW_COLOR_HI_YELLOW 0x0B
+#define FW_COLOR_HI_BLUE 0x0C
+#define FW_COLOR_HI_MAGENTA 0x0D
+#define FW_COLOR_HI_CYAN 0x0E
+#define FW_COLOR_HI_WHITE 0x0F
+
+#endif // _HALVGA_
diff --git a/private/ntos/nthals/halalpha/idle.s b/private/ntos/nthals/halalpha/idle.s
new file mode 100644
index 000000000..0d53d7aed
--- /dev/null
+++ b/private/ntos/nthals/halalpha/idle.s
@@ -0,0 +1,62 @@
+// TITLE("Processor Idle Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// idle.s
+//
+// Abstract:
+//
+// This module implements the HalProcessorIdle interface
+//
+// Author:
+//
+// John Vert (jvert) 11-May-1994
+//
+// Environment:
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with interrupts disabled. This routine
+// must do any power management enabling necessary, enable interrupts,
+// then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+ ENABLE_INTERRUPTS // no power management, just
+ // enable interrupts and return
+ ret zero, (ra)
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halalpha/info.c b/private/ntos/nthals/halalpha/info.c
new file mode 100644
index 000000000..141ceff53
--- /dev/null
+++ b/private/ntos/nthals/halalpha/info.c
@@ -0,0 +1,180 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ info.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+#endif // _PNP_POWER_
+
+//
+// External references
+//
+
+extern WINDOW_CONTROL_REGISTERS HalpIsaWindowControl;
+extern WINDOW_CONTROL_REGISTERS HalpMasterWindowControl;
+
+
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ The function returns system-wide information controlled by the HAL for a
+ variety of classes.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the space to store the data and pass additional info.
+
+ ReturnedLength - Supplies a count in bytes of the amount of data returned.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+ PULONG mapRegisters;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ case HalProfileSourceInformation:
+ Status = HalpProfileSourceInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength);
+ break;
+
+ case HalMapRegisterInformation:
+ mapRegisters = (PULONG)Buffer;
+ if ( BufferSize < 4 ) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ switch ( *(PULONG)Buffer ) {
+ case Isa:
+ *mapRegisters = HalpIsaWindowControl.WindowSize / PAGE_SIZE;
+ *ReturnedLength = 4;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case Eisa:
+ case PCIBus:
+ *mapRegisters = HalpMasterWindowControl.WindowSize / PAGE_SIZE;
+ *ReturnedLength = 4;
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return(Status);
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+/*++
+
+Routine Description:
+
+ The function allows setting of various fields return by
+ HalQuerySystemInformation.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the data to be set.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ case HalProfileSourceInterval:
+ Status = HalpProfileSourceInterval (
+ Buffer,
+ BufferSize);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
diff --git a/private/ntos/nthals/halalpha/inithal.c b/private/ntos/nthals/halalpha/inithal.c
new file mode 100644
index 000000000..a3bc08c7a
--- /dev/null
+++ b/private/ntos/nthals/halalpha/inithal.c
@@ -0,0 +1,1052 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inithal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+ 24-Sep-1993 Joe Notarangelo
+ Restructured to make this module platform-independent.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+PERROR_FRAME PUncorrectableError;
+
+//
+// external
+//
+
+ULONG HalDisablePCIParityChecking = 0xffffffff;
+
+//
+// Define HAL spinlocks.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Mask of all of the processors that are currently active.
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// Mapping of the logical processor numbers to the physical processors.
+//
+
+ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ULONG AlreadySet = 0;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ;
+
+ULONGLONG HalpContiguousPhysicalMemorySize;
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ );
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ );
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Perform initialization for the primary processor.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+ if (Phase == 0) {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+ HalpDumpMemoryDescriptors( LoaderBlock );
+
+#endif //HALDBG
+ //
+ // Get the memory Size.
+ //
+ HalpContiguousPhysicalMemorySize =
+ HalpGetContiguousMemorySize( LoaderBlock );
+
+ //
+ // Set second level cache size
+ // NOTE: Although we set the PCR with the right cache size this
+ // could be overridden by setting the Registry key
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
+ // \Control\Session Manager
+ // \Memory Management\SecondLevelDataCache.
+ //
+ // If the secondlevel cache size is 0 or 512KB then it is
+ // possible that the firmware is an old one. In which case
+ // we determine the cache size here. If the value is anything
+ // other than these then it is a new firmware and probably
+ // reporting the correct cache size hence use this value.
+ //
+
+ if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 ||
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){
+ PCR->SecondLevelCacheSize = HalpGetBCacheSize(
+ HalpContiguousPhysicalMemorySize
+ );
+ } else {
+ PCR->SecondLevelCacheSize =
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize;
+ }
+
+ //
+ // Initialize HAL spinlocks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpSetTimeIncrement();
+ HalpMapIoSpace();
+ HalpEstablishErrorHandler();
+ HalpInitializeDisplay(LoaderBlock);
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+ HalpCreateDmaStructures(LoaderBlock);
+ HalpInitializeInterrupts();
+ HalpVerifyPrcbVersion();
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+ //
+ // Initialize the logical to physical processor mapping
+ // for the primary processor.
+ //
+ HalpLogicalToPhysicalProcessor[0] = HAL_PRIMARY_PROCESSOR;
+
+ return TRUE;
+
+ } else {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpInitializeClockInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Allocate memory for the uncorrectable frame
+ //
+
+ HalpAllocateUncorrectableFrame();
+
+ //
+ // Initialize the Buffer for Uncorrectable Error.
+ //
+
+ HalpInitializeUncorrectableErrorFrame();
+
+ return TRUE;
+
+ }
+ }
+
+ //
+ // Perform necessary processor-specific initialization for
+ // secondary processors. Phase is ignored as this will be called
+ // only once on each secondary processor.
+ //
+
+ HalpMapIoSpace();
+ HalpInitializeInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors |= 1 << Prcb->Number;
+
+#if HALDBG
+
+ DbgPrint( "Secondary %d is alive\n", Prcb->Number );
+
+#endif //HALDBG
+
+ return TRUE;
+}
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called after the Phase1 Machine Dependent initialization.
+ It must be called only after Phase1 machine-dependent initialization.
+ This function allocates the necessary amountof memory for storing the
+ uncorrectable error frame. This function makes a call to a machine-
+ dependent function 'HalpGetMachineDependentErrorFrameSizes' for
+ getting the size of the Processor Specific and System Specific error
+ frame size. The machine-dependent code will know the size of these
+ frames after the machine-dependent Phase1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG RawProcessorFrameSize;
+ ULONG RawSystemFrameSize;
+ ULONG EntireErrorFrameSize;
+
+ //
+ // First get the machine-dependent error frame sizes.
+ //
+ HalpGetMachineDependentErrorFrameSizes(
+ &RawProcessorFrameSize,
+ &RawSystemFrameSize);
+
+ //
+ // Compute the total size of the error frame
+ //
+ EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize +
+ RawSystemFrameSize;
+
+ //
+ // Allocate space to store the error frame.
+ // Not sure if it is OK to use ExAllocatePool at this instant.
+ // We will give this a try if it doesn't work What do we do??!!
+ //
+
+ PUncorrectableError = ExAllocatePool(NonPagedPool,
+ EntireErrorFrameSize);
+ if(PUncorrectableError == NULL) {
+ return;
+ }
+
+ PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize;
+
+ //
+ // if the size is not equal to zero then set the RawInformation pointers
+ // to point to the right place. If not set the pointer to NULL and set
+ // size to 0.
+ //
+
+ //
+ // make Raw processor info to point right after the error frame.
+ //
+ if(RawProcessorFrameSize) {
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ (PVOID)((PUCHAR)PUncorrectableError + sizeof(ERROR_FRAME) );
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ RawProcessorFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ 0;
+ }
+ if(RawSystemFrameSize){
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame.
+ RawProcessorInformation + RawProcessorFrameSize);
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ RawSystemFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ 0;
+ }
+}
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+)
+/*++
+
+Routine Description:
+
+ Collects the Processor Information and fills in the buffer.
+
+Arguments:
+
+ pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which
+ the processor information will be filled in.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+
+ pProcessorInfo->ProcessorType = PCR->ProcessorType;
+ pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision;
+
+ Prcb = PCR->Prcb;
+ pProcessorInfo->LogicalProcessorNumber = Prcb->Number;
+ pProcessorInfo->PhysicalProcessorNumber =
+ HalpLogicalToPhysicalProcessor[Prcb->Number];
+ return;
+}
+
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+//jnfix - for mp systems if processor != 0 then init PALcode?
+//either here or in next module?
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ ULONG LogicalNumber;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PhysicalNumber;
+ PKPRCB Prcb;
+
+#if !defined(NT_UP)
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ LogicalNumber = 0;
+ PhysicalNumber = 0;
+ do {
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){
+
+ PhysicalNumber += 1;
+
+ } else {
+
+ //
+ // Check if this processor has already been started.
+ // If it has not then start it now.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){
+
+ RtlZeroMemory( &NextRestartBlock->u.Alpha,
+ sizeof(ALPHA_RESTART_STATE));
+ NextRestartBlock->u.Alpha.IntA0 =
+ ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Alpha.IntSp =
+ ProcessorState->ContextFrame.IntSp;
+ NextRestartBlock->u.Alpha.ReiRestartAddress =
+ (ULONG)ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)LogicalNumber;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Ensure that the logical to physical mapping has been
+ // established for this processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ }
+
+ LogicalNumber += 1;
+ PhysicalNumber += 1;
+ }
+
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+
+ } while (NextRestartBlock != NULL);
+
+#endif // !defined(NT_UP)
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the HAL matches the kernel. If there
+ is a mismatch the HAL bugchecks the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PKPRCB Prcb;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+
+}
+
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PWSTR NameString;
+
+ //
+ // Quick out
+ //
+
+ if (AlreadySet) {
+ return;
+ }
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+ HalDisablePCIParityChecking = Component->Flags.ConsoleOut;
+ AlreadySet = TRUE;
+#if HALDBG
+ DbgPrint("ARC tree sets PCI parity checking to %s\n",
+ HalDisablePCIParityChecking ? "OFF" : "ON");
+#endif
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return (ULONG) ((Count2 - Count1)*(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the processor counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+#if DBG
+ DbgPrint(
+ "Frequency = %d\nMegaHertz = %d\n",
+ HalpClockFrequency,
+ HalpClockMegaHertz
+ );
+#endif
+
+
+}
+
+
+
+
+#if 0
+VOID
+HalpGatherPerformanceParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
+
diff --git a/private/ntos/nthals/halalpha/intsup.s b/private/ntos/nthals/halalpha/intsup.s
new file mode 100644
index 000000000..40d484db4
--- /dev/null
+++ b/private/ntos/nthals/halalpha/intsup.s
@@ -0,0 +1,256 @@
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// intsup.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 24-Sep-93 Joe Notarangelo
+// Make this module platform-independent.
+//--
+
+#include "halalpha.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// VOID
+// HalpClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the primary processor. The routine is responsible for acknowledging the
+// interrupt and calling the kernel to update the system time.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+CiRa: .space 8 // space for return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt.
+//
+
+ bsr ra, HalpAcknowledgeClockInterrupt // ack the interrupt
+
+//
+// Call the kernel to update the system time.
+//
+ ldl a1, HalpCurrentTimeIncrement // Get current time increment
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateSystemTime
+ jsr ra, (t0) // call kernel
+
+ ldl t0, HalpNextTimeIncrement // Get next time increment
+ stl t0, HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+
+ ldl a0, HalpNextRateSelect // Get NextIntervalCount. If 0, no change required
+ beq a0, 10f
+
+ stl zero, HalpNextRateSelect // Set NextRateSelect to 0
+ bsr ra, HalpProgramIntervalTimer // Program timer with new rate select
+
+ ldl t0, HalpNewTimeIncrement
+ stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+
+//
+// Call to handle performance counter wrap.
+//
+10:
+ bsr ra, HalpCheckPerformanceCounter // check for perf. counter wrap
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ ldl t0, __imp_DbgBreakPointWithStatus
+ lda a0, DBG_STATUS_CONTROL_C
+ jsr ra, (t0) // send status to debugger
+
+ BREAK_BREAKIN // execute breakin breakpoint
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpClockInterrupt
+
+
+#ifndef NT_UP
+
+ SBTTL("Secondary Processor Clock Interrupt")
+//++
+//
+// VOID
+// HalpSecondaryClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the current secondary processor. The routine is responsible for
+// acknowledging the interrupt and calling the kernel to update the
+// run time for the current processor.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ NESTED_ENTRY(HalpSecondaryClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt.
+//
+
+ bsr ra, HalpAcknowledgeClockInterrupt // ack the interrupt
+
+//
+// Call the kernel to update the run time.
+//
+
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateRunTime
+ jsr ra, (t0) // call kernel
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ BREAK_BREAKIN // execute breakin breakpoint
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpSecondaryClockInterrupt
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// VOID
+// HalpIpiInterruptHandler
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interprocessor
+// interrupt asserted on the current processor. This function is
+// responsible for acknowledging the interrupt and dispatching to
+// the kernel for processing.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+IpiRa: .space 8 // space for return address
+IpiFrameLength: //
+
+ NESTED_ENTRY(HalpIpiInterruptHandler, IpiFrameLength, zero )
+
+ lda sp, -IpiFrameLength(sp) // allocate stack frame
+ stq ra, IpiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ bsr ra, HalpAcknowledgeIpiInterrupt // acknowledge interrupt
+
+ ldl t0, __imp_KeIpiInterrupt
+ jsr ra, (t0) // call kernel to process
+
+ ldq ra, IpiRa(sp) // restore return address
+ ret zero, (ra) // return
+
+ .end HalpIpiInterruptHandler
+
+
+#endif //NT_UP
+
diff --git a/private/ntos/nthals/halalpha/ioproc.c b/private/ntos/nthals/halalpha/ioproc.c
new file mode 100644
index 000000000..ec0ee051d
--- /dev/null
+++ b/private/ntos/nthals/halalpha/ioproc.c
@@ -0,0 +1,104 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+#if 0
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+#endif // 0
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halalpha/iousage.c b/private/ntos/nthals/halalpha/iousage.c
new file mode 100644
index 000000000..b1f9ce006
--- /dev/null
+++ b/private/ntos/nthals/halalpha/iousage.c
@@ -0,0 +1,527 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Alpha (Avanti Hals) (Sameer Dekate) 5-4-94
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Define constants for system IDTs
+//
+
+#define MAXIMUM_IDTVECTOR 0xff
+#define MAXIMUM_PRIMARY_VECTOR 0xff
+#define PRIMARY_VECTOR_BASE 0x30 // 0-2f are x86 trap vectors
+
+//
+// Array to remember hal's IDT usage
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+#if 0
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+#endif //0
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS TempAddress;
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 3; pass++) {
+
+ switch(pass) {
+
+ case 0: {
+#if DBG
+DbgPrint("Device LIST...\n");
+#endif // DBG
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ break;
+ }
+
+ case 1: {
+#if DBG
+DbgPrint("Internal LIST...\n");
+#endif // DBG
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ break;
+ }
+
+ case 2: {
+#if DBG
+DbgPrint("PCI LIST...\n");
+#endif // DBG
+ //
+ // Third pass = build reousce lists for resources reported
+ // as PCI usage.
+ //
+
+ reporton = PCIUsage & ~IDTOwned;
+ interfacetype = PCIBus;
+ break;
+ }
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+#if DBG
+DbgPrint("Start=0x%x Lenght=0x%x\n", RPartialDesc.u.Memory.Start.LowPart, RPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TempAddress ); // aligned translated address
+
+ TPartialDesc.u.Memory.Start = TempAddress; // TPartialDesc is pack(4)
+
+#if DBG
+DbgPrint("TRANSLATED ADDRESS Start=0x%x Lenght=0x%x\n", TPartialDesc.u.Memory.Start.LowPart, TPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halalpha/iousage.h b/private/ntos/nthals/halalpha/iousage.h
new file mode 100644
index 000000000..8a128d56e
--- /dev/null
+++ b/private/ntos/nthals/halalpha/iousage.h
@@ -0,0 +1,85 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992,1993 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Most pieces have be stolen from Microsofts halp.h
+
+--*/
+
+//
+// External Function Prototypes
+//
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+//
+// Resource usage information
+//
+
+#pragma pack(1)
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ ULONG Length;
+ } Element[];
+} ADDRESS_USAGE;
+#pragma pack()
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+#define PCIUsage 0x41 // Report usage on PCI bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
diff --git a/private/ntos/nthals/halalpha/isaaddr.h b/private/ntos/nthals/halalpha/isaaddr.h
new file mode 100644
index 000000000..832a48d49
--- /dev/null
+++ b/private/ntos/nthals/halalpha/isaaddr.h
@@ -0,0 +1,75 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ isaaddr.h
+
+Abstract:
+
+ This module defines the standard device addresses on the ISA/EISA bus.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Revision History:
+
+
+--*/
+
+#ifndef _ISAADDR_
+#define _ISAADDR_
+
+//
+// Standard VGA video adapter offsets
+//
+
+#define VIDEO_MEMORY_OFFSET 0xb8000
+#define VIDEO_FONT_MEMORY_OFFSET 0xa0000
+
+//
+// Define the base port address for the PC standard floppy.
+//
+
+#define FLOPPY_ISA_PORT_ADDRESS 0x3f0
+
+//
+// Define the base port address for the PC standard keyboard and mouse.
+//
+
+#define KEYBOARD_ISA_PORT_ADDRESS 0x060
+#define MOUSE_ISA_PORT_ADDRESS 0x060
+#define KBD_ISA_OUTPUT_BUFFER_PORT 0x060
+#define KBD_ISA_STATUS_PORT 0x064
+
+//
+// Define the base port address for the PC standard parallel port.
+//
+
+#define PARALLEL_ISA_PORT_ADDRESS 0x3bc
+
+//
+// Define the base port addresses for the PC standard serial lines.
+//
+
+#define COM1_ISA_PORT_ADDRESS 0x3f8
+#define COM2_ISA_PORT_ADDRESS 0x2f8
+
+//
+// Define the port addresses for the PC standard real time clock.
+//
+
+#define RTC_ISA_ADDRESS_PORT 0x070
+#define RTC_ISA_DATA_PORT 0x071
+#define RTC_ALT_ISA_ADDRESS_PORT 0x170
+#define RTC_ALT_ISA_DATA_PORT 0x171
+
+//
+// Define the base port address for the PC standard 8K CMOS RAM.
+//
+
+#define CMOS_ISA_PORT_ADDRESS 0x800
+
+#endif // _ISAADDR_
diff --git a/private/ntos/nthals/halalpha/lca4.c b/private/ntos/nthals/halalpha/lca4.c
new file mode 100644
index 000000000..64e28dba4
--- /dev/null
+++ b/private/ntos/nthals/halalpha/lca4.c
@@ -0,0 +1,657 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ lca4.c
+
+Abstract:
+
+ This module implements functions that are specific to the LCA4
+ microprocessor.
+
+Author:
+
+ Joe Notarangelo 20-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "lca4.h"
+#include "axp21066.h"
+
+#ifndef AXP_FIRMWARE
+VOID
+DumpIoc(
+ VOID
+ );
+#endif
+
+//
+// Globals
+//
+
+//
+// Parity checking is a tri-state variable, unknown == all f's. Which means
+// Keep checking disabled until we can determine what we want to set it to,
+// which then means 1 or 0.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+#ifdef AXP_FIRMWARE
+
+//
+// Put these functions in the discardable text section.
+//
+
+//
+// Local function prototypes
+//
+
+ULONG
+HalpDetermineLca4Revision(
+ VOID
+ );
+
+VOID
+HalpLca4MapAddressSpaces(
+ VOID
+ );
+
+ULONG
+HalpLca4Revision(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4IocTbTagPhysical(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4PciIntAckPhysical(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4PciIoPhysical(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4PciDensePhysical(
+ VOID
+ );
+
+#pragma alloc_text(DISTEXT, HalpDetermineLca4Revision)
+#pragma alloc_text(DISTEXT, HalpLca4MapAddressSpaces)
+#pragma alloc_text(DISTEXT, HalpLca4Revision)
+#pragma alloc_text(DISTEXT, HalpLca4IocTbTagPhysical)
+#pragma alloc_text(DISTEXT, HalpLca4PciIntAckPhysical)
+#pragma alloc_text(DISTEXT, HalpLca4PciIoPhysical)
+#pragma alloc_text(DISTEXT, HalpLca4PciDensePhysical)
+
+#endif // AXP_FIRMWARE
+
+
+ULONG
+HalpDetermineLca4Revision(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Determine the revision of the LCA4 processor we are currently executing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Return the recognized revision of the LCA4 processor executing.
+
+--*/
+{
+ CAR_21066 Car;
+ ULONG Revision;
+
+ //
+ // Pass 1 and Pass 2 LCA processors can be distinguished by the
+ // PWR bit of the Cache Register (CAR). For Pass 1 the bit is RAZ
+ // while for Pass 2 the bit is read/write.
+ //
+ // Read the current value of the CAR. If it is 1, then we know that
+ // it is Pass 2. Else, set the PWR bit and write it back.
+ // Then read CAR again. If PWR is still set then we are executing on
+ // Pass 2. Don't forget to reset the PWR bit before finishing.
+ //
+
+ Car.all.QuadPart = READ_MEMC_REGISTER(
+ &((PLCA4_MEMC_CSRS)(0))->CacheControl );
+
+ if( Car.Pwr == 1 ) {
+
+ Revision = Lca4Pass2;
+
+ } else {
+
+ Car.Pwr = 1;
+
+ WRITE_MEMC_REGISTER( &((PLCA4_MEMC_CSRS)(0))->CacheControl,
+ Car.all.QuadPart );
+
+ Car.all.QuadPart = READ_MEMC_REGISTER(
+ &((PLCA4_MEMC_CSRS)(0))->CacheControl );
+
+ if( Car.Pwr == 1 ){
+ Revision = Lca4Pass2;
+ } else {
+ Revision = Lca4Pass1;
+ }
+
+ Car.Pwr = 0;
+
+ WRITE_MEMC_REGISTER( &((PLCA4_MEMC_CSRS)(0))->CacheControl,
+ Car.all.QuadPart );
+
+ }
+
+
+ return Revision;
+
+}
+
+//
+// Define the Revision variable for LCA4.
+//
+
+ULONG Lca4Revision;
+
+//
+// Define the Physical Address space variables for LCA4.
+//
+
+ULONGLONG Lca4IocTbTagPhysical;
+ULONGLONG Lca4PciIntAckPhysical;
+ULONGLONG Lca4PciIoPhysical;
+ULONGLONG Lca4PciDensePhysical;
+
+
+VOID
+HalpLca4MapAddressSpaces(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Map the address spaces of the LCA4 dependent upon which revision
+ of the chip is executing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ Lca4Revision = HalpDetermineLca4Revision();
+
+ switch (Lca4Revision){
+
+ //
+ // Pass 1 LCA4
+ //
+
+ case Lca4Pass1:
+
+ Lca4IocTbTagPhysical = LCA4_PASS1_IOC_TBTAG_PHYSICAL;
+ Lca4PciIntAckPhysical = LCA4_PASS1_PCI_INTACK_BASE_PHYSICAL;
+ Lca4PciIoPhysical = LCA4_PASS1_PCI_IO_BASE_PHYSICAL;
+ Lca4PciDensePhysical = 0;
+
+ break;
+
+ //
+ // Pass 2 LCA4
+ //
+
+ case Lca4Pass2:
+
+ Lca4IocTbTagPhysical = LCA4_PASS2_IOC_TBTAG_PHYSICAL;
+ Lca4PciIntAckPhysical = LCA4_PASS2_PCI_INTACK_BASE_PHYSICAL;
+ Lca4PciIoPhysical = LCA4_PASS2_PCI_IO_BASE_PHYSICAL;
+ Lca4PciDensePhysical = LCA4_PASS2_PCI_DENSE_BASE_PHYSICAL;
+
+ break;
+
+#if (DBG) || (HALDBG)
+
+ default:
+
+ DbgPrint( "Unrecognized LCA4 Revision = %x (execution is hopeless)\n",
+ Lca4Revision );
+ DbgBreakPoint();
+
+#endif //DBG || HALDBG
+
+ }
+
+ return;
+
+}
+
+//
+// The following routines could be in-lined (it that were supported) or
+// made into macros to save space (time isn't any issue with these values).
+// To do so the variables above would have to be exported.
+//
+
+ULONG
+HalpLca4Revision(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return the version of the LCA4 processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The version of the LCA4 processor.
+
+--*/
+{
+
+ return Lca4Revision;
+
+}
+
+ULONGLONG
+HalpLca4IocTbTagPhysical(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return the base address of the IOC TB Tag registers on the currently
+ executing LCA4 processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The base physical address of the IOC TB Tag registers.
+
+--*/
+{
+
+ return Lca4IocTbTagPhysical;
+
+}
+
+
+ULONGLONG
+HalpLca4PciIntAckPhysical(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return the base physical address of PCI Interrupt Acknowledge space
+ on the currently executing LCA4 processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The base physical address of PCI Interrupt Acknowledge.
+
+--*/
+{
+
+ return Lca4PciIntAckPhysical;
+
+}
+
+ULONGLONG
+HalpLca4PciIoPhysical(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return the base physical address of PCI I/O space on the currently
+ executing LCA4 processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The base physical address of PCI I/O space.
+
+--*/
+{
+
+ return Lca4PciIoPhysical;
+
+}
+
+ULONGLONG
+HalpLca4PciDensePhysical(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return the base physical address of PCI Dense Memory space on the
+ currently executing LCA4 processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The base physical address of PCI Dense Memory space.
+
+--*/
+{
+
+ return Lca4PciDensePhysical;
+
+}
+
+#if !defined(AXP_FIRMWARE)
+
+
+VOID
+HalpLca4InitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ LCA4_WINDOW_NUMBER WindowNumber
+ )
+/*++
+
+Routine Description:
+
+ Initialize the DMA Control software window registers for the specified
+ DMA Window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control.
+
+ WindowNumber - Supplies the window number initialized. (0 = Isa Dma
+ Window, 1 = Master Dma Window).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ switch( WindowNumber ){
+
+ //
+ // The ISA DMA Window.
+ //
+
+ case Lca4IsaWindow:
+
+ WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->TranslatedBase0;
+ WindowRegisters->WindowBaseRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowBase0;
+ WindowRegisters->WindowMaskRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowMask0;
+ WindowRegisters->WindowTbiaRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->Tbia;
+
+ break;
+
+ //
+ // The Master DMA Window.
+ //
+
+ case Lca4MasterWindow:
+
+ WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->TranslatedBase1;
+ WindowRegisters->WindowBaseRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowBase1;
+ WindowRegisters->WindowMaskRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowMask1;
+ WindowRegisters->WindowTbiaRegister =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->Tbia;
+
+ break;
+
+ default:
+
+#if DBG
+
+ DbgPrint( "Lca4InitializeSfwWindow: Bad Window Number = %x\n",
+ WindowNumber );
+
+#endif //DBG
+
+ break;
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpLca4ProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ Program the control windows in the hardware so that DMA can be started
+ to the DMA window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ MapRegisterBase - Supplies the logical address of the scatter/gather
+ array in system memory.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LCA4_IOC_WMASK WindowMask;
+ LCA4_IOC_WBASE WindowBase;
+ LCA4_IOC_TBEN TbEnable;
+ LCA4_IOC_PCIPD PciPD;
+ LCA4_IOC_TBASE TranslatedBase;
+
+ PVOID RegisterQva;
+
+ WindowBase.Reserved1 = 0;
+ WindowBase.Reserved2 = 0;
+ WindowBase.Sg = 1;
+ WindowBase.Wen = 1;
+ WindowBase.BaseValue = (ULONG)(WindowRegisters->WindowBase) >> 20;
+
+ WindowMask.Reserved1 = 0;
+ WindowMask.Reserved = 0;
+ WindowMask.MaskValue = (WindowRegisters->WindowSize >> 20) - 1;
+
+ TranslatedBase.Reserved1 = 0;
+ TranslatedBase.Reserved = 0;
+ TranslatedBase.TBase = (ULONG)(MapRegisterBase) >> 10;
+
+#if DBG
+
+ //
+ // Dump the EPIC registers.
+ //
+
+ DumpIoc();
+
+#endif //DBG
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_IOC_REGISTER( WindowRegisters->WindowBaseRegister, (ULONGLONG)0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_IOC_REGISTER( WindowRegisters->TranslatedBaseRegister,
+ *(PULONGLONG)&TranslatedBase );
+
+ WRITE_IOC_REGISTER( WindowRegisters->WindowMaskRegister,
+ *(PULONGLONG)&WindowMask );
+
+ WRITE_IOC_REGISTER( WindowRegisters->WindowBaseRegister,
+ *(PULONGLONG)&WindowBase );
+
+ //
+ // Invalidate any translations that might have existed for this window.
+ //
+
+ WRITE_IOC_REGISTER( WindowRegisters->WindowTbiaRegister, (ULONGLONG)0 );
+
+ //
+ // Enable the translation buffer inside of the IOC.
+ //
+
+ RtlZeroMemory( &TbEnable, sizeof(LCA4_IOC_TBEN) );
+ TbEnable.Ten = 1;
+
+ WRITE_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->TbEnable,
+ *(PULONGLONG)&TbEnable );
+
+ //
+ // Tri state parity checking - keep disabled if not determined
+ // yet. otherwise, Whack the PCI parity disable bit with the stored
+ // value
+ //
+
+ RtlZeroMemory( &PciPD, sizeof(LCA4_IOC_PCIPD) );
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+ PciPD.Par = 1;
+ } else {
+ PciPD.Par = HalDisablePCIParityChecking;
+ }
+
+ WRITE_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->PciParityDisable,
+ *(PULONGLONG)&PciPD );
+
+#if DBG
+
+ //
+ // Dump the IOC registers.
+ //
+
+ DumpIoc();
+
+#endif //DBG
+
+ return;
+}
+
+ULONGLONG
+READ_IOC_REGISTER(
+ PVOID
+ );
+
+#if DBG
+
+VOID
+DumpIoc(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting IOC registers and print them to the debug port.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ ULONGLONG Value;
+
+ DbgPrint( "Dumping the IOC registers\n" );
+
+ RegisterQva =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat0;
+ Value = READ_IOC_REGISTER( RegisterQva );
+ DbgPrint( "IOSTAT[0] = %Lx\n", Value );
+
+ RegisterQva =
+ &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat1;
+ Value = READ_IOC_REGISTER( RegisterQva );
+ DbgPrint( "IOSTAT[1] = %Lx\n", Value );
+
+ DbgPrint( "--end IOC dump\n\n" );
+
+ return;
+
+}
+
+#endif //DBG
+
+#endif //!AXP_FIRMWARE
diff --git a/private/ntos/nthals/halalpha/lca4.h b/private/ntos/nthals/halalpha/lca4.h
new file mode 100644
index 000000000..0fd7ab02f
--- /dev/null
+++ b/private/ntos/nthals/halalpha/lca4.h
@@ -0,0 +1,669 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ lca4.h
+
+Abstract:
+
+ This file defines the structures and definitions common to all
+ LCA4-based platforms (Low Cost Alpha in Hudson CMOS 4).
+
+Author:
+
+ Joe Notarangelo 20-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _LCA4H_
+#define _LCA4H_
+
+
+//
+// Define QVA constants for LCA4.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xa0000000) // Identify VA as QVA
+
+#endif //QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // Identify QVA bits
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+//
+// Define size of I/O and memory space for LCA4
+//
+
+#define PCI_MAX_IO_ADDRESS 0xFFFFFF // 16 Mb of IO Space
+
+//
+// Due we have 128MB total sparse space, of which some of it are holes
+//
+
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS ((128*1024*1024) - 1)
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MAX_SPARSE_MEMORY_ADDRESS + 1 // 128 Mb
+#define PCI_MAX_DENSE_MEMORY_ADDRESS (0xa0000000 -1) // 2.5 Gb
+
+//
+// Constant used by dense space I/O routines
+//
+
+#define PCI_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc0300000000
+
+
+//
+// Protect the assembly language code from C definitions.
+//
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | (ULONG)(PA >> IO_BIT_SHIFT) ) )
+
+
+//
+// Define the different supported passes of the LCA4 processor.
+//
+
+typedef enum _LCA4_REVISIONS{
+ Lca4Pass1 = 1,
+ Lca4Pass2 = 2
+}LCA4_REVISIONS, *PLCA4_REVISIONS;
+
+//
+// Define physical address spaces for LCA4.
+//
+
+#define LCA4_MEMC_BASE_PHYSICAL ((ULONGLONG)0x120000000)
+#define LCA4_IOC_BASE_PHYSICAL ((ULONGLONG)0x180000000)
+#define LCA4_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x200000000)
+#define LCA4_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0x1E0000000)
+
+#define LCA4_PASS1_IOC_TBTAG_PHYSICAL ((ULONGLONG)0x181000000)
+#define LCA4_PASS1_PCI_INTACK_BASE_PHYSICAL ((ULONGLONG)0x1C0000000)
+#define LCA4_PASS1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x300000000)
+
+#define LCA4_PASS2_IOC_TBTAG_PHYSICAL ((ULONGLONG)0x181000000)
+#define LCA4_PASS2_PCI_INTACK_BASE_PHYSICAL ((ULONGLONG)0x1A0000000)
+#define LCA4_PASS2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x1C0000000)
+#define LCA4_PASS2_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x300000000)
+
+
+//
+// Define the Memory Controller CSRs.
+//
+
+
+#define LCA4_MEMC_BASE_QVA (HAL_MAKE_QVA(LCA4_MEMC_BASE_PHYSICAL))
+
+//
+// N.B. The structure below defines the offsets of the registers within
+// the memory controller. These are "real" address offsets, not
+// QVA offsets. Unfortunately, since these offsets represent "real"
+// quadword addresses, they cannot be used as QVAs. Therefore,
+// the routines to read and write the memory controller will take
+// the base QVA and an offset as 2 address parameters, rather than
+// using a single address parameter. This is inconvenient but
+// manageable.
+//
+
+typedef struct _LCA4_MEMC_CSRS{
+ ULONGLONG BankConfiguration0;
+ ULONGLONG BankConfiguration1;
+ ULONGLONG BankConfiguration2;
+ ULONGLONG BankConfiguration3;
+ ULONGLONG BankMask0;
+ ULONGLONG BankMask1;
+ ULONGLONG BankMask2;
+ ULONGLONG BankMask3;
+ ULONGLONG BankTiming0;
+ ULONGLONG BankTiming1;
+ ULONGLONG BankTiming2;
+ ULONGLONG BankTiming3;
+ ULONGLONG GlobalTiming;
+ ULONGLONG ErrorStatus;
+ ULONGLONG ErrorAddress;
+ ULONGLONG CacheControl;
+ ULONGLONG VideoGraphicsControl;
+ ULONGLONG PlaneMask;
+ ULONGLONG Foreground;
+} LCA4_MEMC_CSRS, *PLCA4_MEMC_CSRS;
+
+
+//
+// Define IO Controller CSRs.
+//
+
+#define LCA4_IOC_BASE_QVA (HAL_MAKE_QVA(LCA4_IOC_BASE_PHYSICAL))
+#define LCA4_IOC_TBTAG_QVA (HAL_MAKE_QVA(LCA4_IOC_TBTAG_PHYSICAL))
+
+//
+// N.B. The structures below defines the address offsets of the control
+// registers when used with the base QVA. It does NOT define the
+// size or structure of the individual registers.
+//
+
+typedef struct _LCA4_IOC_CSRS{
+ UCHAR HostAddressExtension;
+ UCHAR ConfigurationCycleType;
+ UCHAR IocStat0;
+ UCHAR IocStat1;
+ UCHAR Tbia;
+ UCHAR TbEnable;
+ UCHAR PciSoftReset;
+ UCHAR PciParityDisable;
+ UCHAR WindowBase0;
+ UCHAR WindowBase1;
+ UCHAR WindowMask0;
+ UCHAR WindowMask1;
+ UCHAR TranslatedBase0;
+ UCHAR TranslatedBase1;
+} LCA4_IOC_CSRS, *PLCA4_IOC_CSRS;
+
+#define LCA4_IOC_TB_ENTRIES (8)
+
+typedef struct _LCA4_IOC_TBTAGS{
+ UCHAR IocTbTag[LCA4_IOC_TB_ENTRIES];
+} LCA4_IOC_TBTAGS, *PLCA4_IOC_TBTAGS;
+
+//
+// Define formats of useful IOC registers.
+//
+
+typedef struct _LCA4_IOC_HAE{
+ ULONG Reserved1: 27;
+ ULONG Hae: 5;
+ ULONG Reserved;
+} LCA4_IOC_HAE, *PLCA4_IOC_HAE;
+
+typedef struct _LCA4_IOC_CCT{
+ ULONG CfgAd: 2;
+ ULONG Reserved1: 30;
+ ULONG Reserved;
+} LCA4_IOC_CCT, *PLCA4_IOC_CCT;
+
+typedef struct _LCA4_IOC_TBEN{
+ ULONG Reserved1: 7;
+ ULONG Ten: 1;
+ ULONG Reserved2: 24;
+ ULONG Reserved;
+} LCA4_IOC_TBEN, *PLCA4_IOC_TBEN;
+
+typedef struct _LCA4_IOC_PCISR{
+ ULONG Reserved1: 6;
+ ULONG Rst: 1;
+ ULONG Reserved2: 25;
+ ULONG Reserved;
+} LCA4_IOC_PCISR, *PLCA4_IOC_PCISR;
+
+typedef struct _LCA4_IOC_PCIPD{
+ ULONG Reserved1: 5;
+ ULONG Par: 1;
+ ULONG Reserved2: 26;
+ ULONG Reserved;
+} LCA4_IOC_PCIPD, *PLCA4_IOC_PCIPD;
+
+typedef struct _LCA4_IOC_STAT0{
+ ULONG Cmd: 4;
+ ULONG Err: 1;
+ ULONG Lost: 1;
+ ULONG THit: 1;
+ ULONG TRef: 1;
+ ULONG Code: 3;
+ ULONG Reserved1: 2;
+ ULONG Pnbr: 19;
+ ULONG Reserved;
+} LCA4_IOC_STAT0, *PLCA4_IOC_STAT0;
+
+typedef enum _LCA4_IOC_STAT0_CODE{
+ IocErrorRetryLimit = 0x0,
+ IocErrorNoDevice = 0x1,
+ IocErrorBadDataParity = 0x2,
+ IocErrorTargetAbort = 0x3,
+ IocErrorBadAddressParity = 0x4,
+ IocErrorPageTableReadError = 0x5,
+ IocErrorInvalidPage = 0x6,
+ IocErrorDataError = 0x7,
+ MaximumIocError
+} LCA4_IOC_STAT0_CODE, *PLCA4_IOC_STAT0_CODE;
+
+typedef struct _LCA4_IOC_STAT1{
+ ULONG Addr;
+ ULONG Reserved;
+} LCA4_IO_STAT1, *PLCA4_IO_STAT1;
+
+typedef struct _LCA4_IOC_WMASK{
+ ULONG Reserved1: 20;
+ ULONG MaskValue: 12;
+ ULONG Reserved;
+} LCA4_IOC_WMASK, *PLCA4_IOC_WMASK;
+
+typedef struct _LCA4_IOC_WBASE{
+ ULONG Reserved1: 20;
+ ULONG BaseValue: 12;
+ ULONG Sg: 1;
+ ULONG Wen: 1;
+ ULONG Reserved2: 30;
+} LCA4_IOC_WBASE, *PLCA4_IOC_WBASE;
+
+typedef struct _LCA4_IOC_TBASE{
+ ULONG Reserved1: 10;
+ ULONG TBase: 22;
+ ULONG Reserved;
+} LCA4_IOC_TBASE, *PLCA4_IOC_TBASE;
+
+typedef struct _LCA4_IOC_TBTAG{
+ ULONG Reserved1: 13;
+ ULONG TbTag: 19;
+ ULONG Reserved;
+} LCA4_IOC_TBTAG, *PLCA4_IOC_TBTAG;
+
+typedef struct _LCA4_IOC_CTRL{
+ ULONG CfgAd: 2;
+ ULONG Reserved1: 2;
+ ULONG Cerr: 1;
+ ULONG Clost: 1;
+ ULONG Rst: 1;
+ ULONG Ten: 1;
+ ULONG Reserved2: 19;
+ ULONG Hae: 5;
+ ULONG Reserved;
+} LCA4_IOC_CTRL, *PLCA4_IOC_CTRL;
+
+//
+// Define formats of useful Memory Controller registers.
+//
+
+typedef struct _LCA4_MEMC_ESR{
+ ULONG Eav: 1;
+ ULONG Cee: 1;
+ ULONG Uee: 1;
+ ULONG Wre: 1;
+ ULONG Sor: 1;
+ ULONG Reserved1: 2;
+ ULONG Cte: 1;
+ ULONG Reserved2: 1;
+ ULONG Mse: 1;
+ ULONG Mhe: 1;
+ ULONG Ice: 1;
+ ULONG Nxm: 1;
+ ULONG Reserved3: 19;
+ ULONG Reserved;
+} LCA4_MEMC_ESR, *PLCA4_MEMC_ESR;
+
+
+//
+// Define PCI Config Space QVA
+//
+
+#define LCA4_PCI_CONFIG_BASE_QVA (HAL_MAKE_QVA(LCA4_PCI_CONFIG_BASE_PHYSICAL))
+
+#if !defined(AXP_FIRMWARE)
+
+
+//
+// DMA Window Values.
+//
+// The LCA4 will be initialized to allow 2 DMA windows.
+// The first window will be for the use of of ISA devices and DMA slaves
+// and therefore must have logical addresses below 16MB.
+// The second window will be for bus masters (non-ISA) and so may be
+// above 16MB.
+//
+// The arrangement of the windows will be as follows:
+//
+// Window Logical Start Address Window Size
+// ------ --------------------- -----------
+// Isa 8MB 8MB
+// Master 16MB 16MB
+//
+
+#define ISA_DMA_WINDOW_BASE (__8MB)
+#define ISA_DMA_WINDOW_SIZE (__8MB)
+
+#define MASTER_DMA_WINDOW_BASE (__16MB)
+#define MASTER_DMA_WINDOW_SIZE (__16MB)
+
+
+//
+// Define the software control registers for a DMA window.
+//
+
+typedef struct _WINDOW_CONTROL_REGISTERS{
+ PVOID WindowBase;
+ ULONG WindowSize;
+ PVOID TranslatedBaseRegister;
+ PVOID WindowBaseRegister;
+ PVOID WindowMaskRegister;
+ PVOID WindowTbiaRegister;
+} WINDOW_CONTROL_REGISTERS, *PWINDOW_CONTROL_REGISTERS;
+
+//
+// Define types of windows.
+//
+
+typedef enum _LCA4_WINDOW_NUMBER{
+ Lca4IsaWindow,
+ Lca4MasterWindow
+} LCA4_WINDOW_NUMBER, *PLCA4_WINDOW_NUMBER;
+
+//
+// Define LCA4 Window Control routines.
+//
+
+VOID
+HalpLca4InitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ LCA4_WINDOW_NUMBER WindowNumber
+ );
+
+VOID
+HalpLca4ProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ );
+
+
+//
+// VOID
+// INITIALIZE_ISA_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_ISA_DMA_CONTROL( WR ) \
+ HalpLca4InitializeSfwWindow( (WR), Lca4IsaWindow );
+
+
+//
+// VOID
+// INITIALIZE_MASTER_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the Master
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_MASTER_DMA_CONTROL( WR ) \
+ HalpLca4InitializeSfwWindow( (WR), Lca4MasterWindow );
+
+
+//
+// VOID
+// INITIALIZE_DMA_WINDOW(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters,
+// PTRANSLATION_ENTRY MapRegisterBase
+// )
+//
+// Routine Description:
+//
+// Program the control windows so that DMA can be started to the
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window register
+// control structure.
+//
+// MapRegisterBase - Supplies the logical address of the scatter/gather
+// array in system memory.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_DMA_WINDOW( WR, MRB ) \
+ HalpLca4ProgramDmaWindow( (WR), (MRB) );
+
+
+//
+// VOID
+// INVALIDATE_DMA_TRANSLATIONS(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Invalidate all of the cached translations for a DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control
+// registers.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INVALIDATE_DMA_TRANSLATIONS( WR ) \
+ WRITE_IOC_REGISTER( \
+ ((PWINDOW_CONTROL_REGISTERS)WR)->WindowTbiaRegister, 0 );
+
+
+//
+// Define the format of a translation entry aka a scatter/gather entry
+// or map register.
+//
+
+typedef struct _TRANSLATION_ENTRY{
+ ULONG Valid: 1;
+ ULONG Pfn: 31;
+ ULONG Reserved;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+
+//
+// VOID
+// HAL_MAKE_VALID_TRANSLATION(
+// PTRANSLATION_ENTRY Entry,
+// ULONG PageFrameNumber
+// )
+//
+// Routine Description:
+//
+// Make the scatter/gather entry pointed to by Entry valid with
+// a translation to the page indicated by PageFrameNumber.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation entry to make valid.
+//
+// PageFrameNumber - Supplies the page frame of the valid translation.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_MAKE_VALID_TRANSLATION( ENTRY, PFN ) \
+ { \
+ (ENTRY)->Valid = 1; \
+ (ENTRY)->Pfn = PFN; \
+ (ENTRY)->Reserved = 0; \
+ }
+
+
+//
+// VOID
+// HAL_INVALIDATE_TRANSLATION(
+// PTRANSLATION_ENTRY Entry
+// )
+//
+// Routine Description:
+//
+// Invalidate the translation indicated by Entry.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation to be invalidated.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_INVALIDATE_TRANSLATION( ENTRY ) \
+ (ENTRY)->Valid = 0;
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each LCA4 processor.
+//
+
+typedef struct _LCA4_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} LCA4_PCR, *PLCA4_PCR;
+
+#define HAL_PCR ( (PLCA4_PCR)(&(PCR->HalReserved)) )
+
+#endif //!AXP_FIRMWARE
+
+
+//
+// Define LCA4-specific function prototypes.
+//
+
+ULONG
+HalpDetermineLca4Revision(
+ VOID
+ );
+
+VOID
+HalpLca4MapAddressSpaces(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4IocTbTagPhysical(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4PciIntAckPhysical(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4PciIoPhysical(
+ VOID
+ );
+
+ULONGLONG
+HalpLca4PciDensePhysical(
+ VOID
+ );
+
+ULONG
+HalpLca4Revision(
+ VOID
+ );
+
+VOID
+WRITE_MEMC_REGISTER(
+ IN PVOID RegisterOffset,
+ IN ULONGLONG Value
+ );
+
+ULONGLONG
+READ_MEMC_REGISTER(
+ IN PVOID RegisterOffset
+ );
+
+VOID
+WRITE_IOC_REGISTER(
+ IN PVOID RegisterQva,
+ IN ULONGLONG Value
+ );
+
+ULONGLONG
+READ_IOC_REGISTER(
+ IN PVOID RegisterQva
+ );
+
+VOID
+HalpClearAllErrors(
+ IN BOOLEAN EnableCorrectableErrors
+ );
+
+
+
+//
+// Define primary (and only) CPU for an LCA system
+//
+
+#define HAL_PRIMARY_PROCESSOR (0)
+#define HAL_MAXIMUM_PROCESSOR (0)
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_LCA4H_
+
diff --git a/private/ntos/nthals/halalpha/lca4err.c b/private/ntos/nthals/halalpha/lca4err.c
new file mode 100644
index 000000000..edf050f1e
--- /dev/null
+++ b/private/ntos/nthals/halalpha/lca4err.c
@@ -0,0 +1,1153 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ lca4err.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for machines based on the DECchip 21066
+ microprocessor.
+
+Author:
+
+ Joe Notarangelo 8-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21066.h"
+#include "lca4.h"
+#include "stdio.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// MAX_RETRYABLE_ERRORS is the number of times to retry machine checks before
+// just giving up.
+//
+
+#define MAX_RETRYABLE_ERRORS 32
+
+//
+//jnfix - temporary counts
+//
+
+ULONG CorrectableErrors = 0;
+ULONG RetryableErrors = 0;
+
+
+VOID
+HalpDisplayLogout21066 (
+ IN ESR_21066 Esr,
+ IN IOC_STAT0_21066 IoStat0,
+ IN PLOGOUT_FRAME_21066 LogoutFrame
+ );
+
+VOID
+HalpClearMachineCheck(
+ VOID
+ );
+
+ULONG
+HalpBankError(
+ ULONG PhysicalAddress,
+ PLOGOUT_FRAME_21066 LogoutFrame
+ );
+
+//jnfix - should be exported from platform-specific
+ULONG
+HalpSimmError(
+ ULONG PhysicalAddress,
+ PLOGOUT_FRAME_21066 LogoutFrame
+ );
+
+
+VOID
+HalpClearAllErrors(
+ IN BOOLEAN SignalMemoryCorrectables
+ )
+/*++
+
+Routine Description:
+
+ This routine clears all of the error bits in the LCA4 memory
+ controller and I/O controller.
+
+Arguments:
+
+ SignalMemoryCorrectables - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled in the memory controller.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ ESR_21066 ErrorStatus;
+ IOC_STAT0_21066 IoStat0;
+
+ //
+ // The error status bits of the ESR are all write one to clear.
+ // Clear the value and then set all of the error bits. Then set
+ // correctable enable according to specified input.
+ //
+
+ ErrorStatus.all.QuadPart = (ULONGLONG)0;
+
+ ErrorStatus.Eav = 1;
+ ErrorStatus.Cee = 1;
+ ErrorStatus.Uee = 1;
+ ErrorStatus.Cte = 1;
+ ErrorStatus.Mse = 1;
+ ErrorStatus.Mhe = 1;
+ ErrorStatus.Nxm = 1;
+
+ if( SignalMemoryCorrectables == TRUE ){
+ ErrorStatus.Ice = 0;
+ } else {
+ ErrorStatus.Ice = 1;
+ }
+
+ WRITE_MEMC_REGISTER( &((PLCA4_MEMC_CSRS)(0))->ErrorStatus,
+ ErrorStatus.all.QuadPart );
+
+ //
+ // The ERR and LOST bits of the IO_STAT0 are write one to clear.
+ //
+
+ IoStat0.all.QuadPart = (ULONGLONG)0;
+
+ IoStat0.Err = 1;
+ IoStat0.Lost = 1;
+
+ WRITE_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat0,
+ IoStat0.all.QuadPart );
+
+ return;
+
+}
+
+VOID
+HalpBuildLCAUncorrectableErrorFrame(
+ VOID
+ )
+{
+ PPROCESSOR_LCA_UNCORRECTABLE LcaUncorrerr = NULL;
+ PEXTENDED_ERROR PExtErr;
+ EAR_21066 Ear;
+
+ if(PUncorrectableError){
+ LcaUncorrerr = (PPROCESSOR_LCA_UNCORRECTABLE)
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation;
+
+ //
+ // first fill in some generic processor Information.
+ // For the Current (Reporting) Processor.
+ //
+ HalpGetProcessorInfo(
+ &PUncorrectableError->UncorrectableFrame.ReportingProcessor);
+ PUncorrectableError->
+ UncorrectableFrame.Flags.ProcessorInformationValid = 1;
+
+
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ if(LcaUncorrerr) {
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Uncorrectable Error From "
+ "LCA4 Detected");
+ LcaUncorrerr->IocStat0 = (ULONGLONG)
+ READ_IOC_REGISTER(&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat0);
+
+ LcaUncorrerr->IocStat1 = (ULONGLONG)
+ READ_IOC_REGISTER(&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat1);
+
+ LcaUncorrerr->Esr = (ULONGLONG)
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->ErrorStatus);
+
+ Ear.all.QuadPart = LcaUncorrerr->Ear = (ULONGLONG)
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->ErrorAddress);
+
+ PUncorrectableError->UncorrectableFrame.Flags.PhysicalAddressValid = 1;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ Ear.ErrorAddress;
+
+ LcaUncorrerr->BankConfig0 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankConfiguration0);
+
+ LcaUncorrerr->BankConfig1 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankConfiguration1);
+
+ LcaUncorrerr->BankConfig2 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankConfiguration2);
+
+ LcaUncorrerr->BankConfig3 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankConfiguration3);
+
+ LcaUncorrerr->BankMask0 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankMask0);
+
+ LcaUncorrerr->BankMask1 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankMask1);
+
+ LcaUncorrerr->BankMask2 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankMask2);
+
+ LcaUncorrerr->BankMask3 =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->BankMask3);
+
+ LcaUncorrerr->Car =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->CacheControl);
+
+ LcaUncorrerr->Gtr =
+ READ_MEMC_REGISTER(&((PLCA4_MEMC_CSRS)(0))->GlobalTiming);
+ }
+}
+
+
+BOOLEAN
+HalMachineCheck (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This function fields machine checks for 21066-based machines.
+
+ The following errors may be the cause of the machine check:
+
+ (a) Uncorrectable Dcache error
+ (b) Uncorrectable Load from Memory Controller
+ (c) Uncorrectable Load from I/O Controller
+ (d) Non-existent device in PCI Configuration Space (I/O Controller)
+ (e) Retryable Icache parity error
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record for the
+ machine check. Included in the exception information
+ is the pointer to the logout frame.
+
+ ExceptionFrame - Supplies a pointer to the kernel exception frame.
+
+ TrapFrame - Supplies a pointer to the kernel trap frame.
+
+Return Value:
+
+ A value of TRUE is returned if the machine check has been
+ handled by the HAL. If it has been handled then execution may
+ resume at the faulting address. Otherwise, a value of FALSE
+ is returned.
+
+ N.B. - When a fatal error is recognized this routine does not
+ return at all.
+
+--*/
+
+{
+
+ PMCHK_STATUS MachineCheckStatus;
+ ESR_21066 ErrorStatus;
+ IOC_STAT0_21066 IoStat0;
+ PPROCESSOR_LCA_UNCORRECTABLE LcaUncorrerr = NULL;
+
+ MachineCheckStatus =
+ (PMCHK_STATUS)&ExceptionRecord->ExceptionInformation[0];
+
+ //
+ // Print an error message if a correctable machine check is signalled.
+ // Correctable machine checks are not possible on the 21066.
+ //
+
+ if( MachineCheckStatus->Correctable == 1 ){
+
+#if DBG
+
+ DbgPrint( "Illegal correctable error for LCA4\n" );
+
+#endif //DBG
+
+ }
+
+ //
+ // If the machine check is retryable then log the error and
+ // and restart the operation.
+ //
+
+ if( MachineCheckStatus->Retryable == 1 ){
+
+ //
+ // jnfix Log the error, interface undefined.
+ //
+
+ //
+ // Increment the number of retryable machine checks.
+ //
+
+ RetryableErrors += 1;
+
+
+#if (DBG) || (HALDBG)
+
+ DbgPrint( "HAL Retryable Errors = %d\n", RetryableErrors );
+ // if( (RetryableErrors % 32) == 0 ){
+ // DbgPrint( "HAL Retryable Errors = %d\n", RetryableErrors );
+ // }
+
+#endif //DBG || HALDBG
+
+
+ //
+ // We'll retry MAX_RETRYABLE_ERRORS times and then give up. We
+ // do this to avoid infinite retry loops.
+ //
+
+ if( RetryableErrors > MAX_RETRYABLE_ERRORS ){
+
+ //
+ // Acknowledge receipt of the retryable machine check.
+ //
+ DbgPrint("Got too many Retryable Errors errors\n");
+ }
+
+ //
+ // Clear the machine check in the MCES register.
+ //
+
+ HalpClearMachineCheck();
+
+ //
+ // Attempt to retry the operation.
+ //
+
+ return TRUE;
+
+ }
+
+ //
+ // The machine check is uncorrectable according to the processor.
+ // Read the error registers in the Memory and I/O Controller.
+ // If the operation was a read to PCI configuration space and no
+ // device is the error then we will fix up the operation and continue,
+ // otherwise the machine has taken a fatal error.
+ //
+
+//jnfix - code here to check for dcache parity error?
+
+
+ ErrorStatus.all.QuadPart =
+ READ_MEMC_REGISTER(
+ &((PLCA4_MEMC_CSRS)(0))->ErrorStatus );
+
+ IoStat0.all.QuadPart =
+ READ_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat0 );
+
+ //
+ // If any of the following errors are indicated in the memory controller
+ // then process a fatal error:
+ // Uncorrectable Error
+ // Cache Tag Error
+ // Multiple Hard Errors
+ // Non-existent Memory
+ //
+
+ if( (ErrorStatus.Uee == 1) ||
+ (ErrorStatus.Cte == 1) ||
+ (ErrorStatus.Mhe == 1) ||
+ (ErrorStatus.Nxm == 1) ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Check for a PCI configuration read error. An error is a
+ // candidate if the I/O controller has signalled an error, there
+ // are no lost errors and the error was a no device error on the PCI.
+ //
+
+ if( (IoStat0.Err == 1) && (IoStat0.Code == IocErrorNoDevice) &&
+ (IoStat0.Lost == 0) ){
+
+ //
+ // So far, the error looks like a PCI configuration space read
+ // that accessed a device that does not exist. In order to fix
+ // this up we expect that the faulting instruction or the instruction
+ // previous to the faulting instruction must be a load with v0 as
+ // the destination register. If this condition is met then simply
+ // update v0 in the register set and return. However, be careful
+ // not to re-execute the load.
+ //
+ // jnfix - add condition to check if Rb contains the superpage
+ // address for config space?
+
+ ALPHA_INSTRUCTION FaultingInstruction;
+ BOOLEAN PreviousInstruction = FALSE;
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
+ if( (FaultingInstruction.Memory.Ra != V0_REG) ||
+ (FaultingInstruction.Memory.Opcode != LDL_OP) ){
+
+ //
+ // Faulting instruction did not match, try the previous
+ // instruction.
+ //
+
+ PreviousInstruction = TRUE;
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir - 4);
+ if( (FaultingInstruction.Memory.Ra != V0_REG) ||
+ (FaultingInstruction.Memory.Opcode != LDL_OP) ){
+
+ //
+ // No match, we can't fix this up.
+ //
+
+ goto FatalError;
+ }
+ }
+
+ //
+ // The error has matched all of our conditions. Fix it up by
+ // writing the value 0xffffffff into the destination of the load.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
+
+ //
+ // Clear the machine check condition in the processor.
+ //
+
+ HalpClearMachineCheck();
+
+ //
+ // Clear the error condition in the io controller.
+ // The Err bit is write one to clear.
+ //
+
+ IoStat0.all.QuadPart = (ULONGLONG)0;
+ IoStat0.Err = 1;
+ WRITE_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat0,
+ IoStat0.all.QuadPart );
+
+ //
+ // If the faulting instruction was the load the restart execution
+ // at the instruction after the load.
+ //
+
+ if( PreviousInstruction == FALSE ){
+ TrapFrame->Fir += 4;
+ }
+
+ return TRUE;
+
+ } //end if (IoStat0.Err == 1) && (IoStat0.Code == IocErrorNoDevice) ){
+
+
+//
+// The system is not well and cannot continue reliable execution.
+// Print some useful messages and shutdown the machine.
+//
+
+FatalError:
+
+ HalpBuildLCAUncorrectableErrorFrame();
+
+ if(PUncorrectableError){
+ LcaUncorrerr = (PPROCESSOR_LCA_UNCORRECTABLE)
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation;
+
+ LcaUncorrerr->AboxCtl = (ULONGLONG)
+ ((PLOGOUT_FRAME_21066)
+ (ExceptionRecord->ExceptionInformation[1] ))->AboxCtl.all.QuadPart;
+
+ LcaUncorrerr->CStat = (ULONGLONG)
+ ((PLOGOUT_FRAME_21066)
+ (ExceptionRecord->ExceptionInformation[1] ))->DcStat.all.QuadPart;
+
+ LcaUncorrerr->MmCsr = (ULONGLONG)
+ ((PLOGOUT_FRAME_21066)
+ (ExceptionRecord->ExceptionInformation[1] ))->MmCsr.all.QuadPart;
+ }
+
+ //
+ // Display the logout frame.
+ //
+
+ HalpDisplayLogout21066(
+ ErrorStatus,
+ IoStat0,
+ (PLOGOUT_FRAME_21066)(ExceptionRecord->ExceptionInformation[1]) );
+
+ //
+ //
+ // Bugcheck to dump the rest of the machine state, this will help
+ // if the machine check is software-related.
+ //
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ (ULONG)MachineCheckStatus->Correctable,
+ (ULONG)MachineCheckStatus->Retryable,
+ 0,
+ (ULONG)PUncorrectableError );
+
+}
+
+VOID
+HalpClearMachineCheck(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Clear the machine check which is currently pending. Clearing the
+ pending machine check bit will allow us to take machine checks in
+ the future without detecting a double machine check condition.
+ The machine check pending bit must be cleared in the MCES register
+ within the PALcode.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MCES MachineCheckSummary;
+
+ MachineCheckSummary.MachineCheck = 1;
+ MachineCheckSummary.SystemCorrectable = 0;
+ MachineCheckSummary.ProcessorCorrectable = 0;
+ MachineCheckSummary.DisableProcessorCorrectable = 0;
+ MachineCheckSummary.DisableSystemCorrectable = 0;
+ MachineCheckSummary.DisableMachineChecks = 0;
+
+ HalpWriteMces( MachineCheckSummary );
+
+ return;
+
+}
+
+#define MAX_ERROR_STRING 100
+
+VOID
+HalpDisplayLogout21066 (
+ IN ESR_21066 Esr,
+ IN IOC_STAT0_21066 IoStat0,
+ IN PLOGOUT_FRAME_21066 LogoutFrame
+ )
+/*++
+
+Routine Description:
+
+ This function displays the logout frame for a 21066.
+
+Arguments:
+
+ Esr - Supplies the value of the memory controller error status register.
+
+ IoStat0 - Supplies the value of the i/o controller status register 0.
+
+ LogoutFrame - Supplies a pointer to the logout frame generated
+ by the 21066.
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ EAR_21066 Ear;
+ CAR_21066 Car;
+ IOC_STAT1_21066 IoStat1;
+ ULONG Index;
+ PKPRCB Prcb;
+ extern HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+ PCHAR parityErrString = NULL;
+ PEXTENDED_ERROR exterr;
+
+
+ if(PUncorrectableError) {
+ exterr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ parityErrString = PUncorrectableError->UncorrectableFrame.ErrorString;
+ }
+
+
+ //
+ // Capture other useful registers, EAR, CAR, and IO_STAT1.
+ //
+
+ Ear.all.QuadPart =
+ READ_MEMC_REGISTER(
+ &((PLCA4_MEMC_CSRS)(0))->ErrorAddress );
+
+ Car.all.QuadPart =
+ READ_MEMC_REGISTER(
+ &((PLCA4_MEMC_CSRS)(0))->CacheControl );
+
+ IoStat1.all.QuadPart =
+ READ_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat1);
+
+ //
+ // Acquire ownership of the display. This is done here in case we take
+ // a machine check before the display has been taken away from the HAL.
+ // When the HAL begins displaying strings after it has lost the
+ // display ownership then the HAL will be careful not to scroll information
+ // off of the screen.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the machine state via the logout frame.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+
+ sprintf( OutBuffer, "MEMC_ESR: %16Lx MEMC_EAR: %16Lx CAR: %16Lx\n",
+ Esr.all.QuadPart,
+ Ear.all.QuadPart,
+ Car.all.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "IO_STAT0: %16Lx IO_STAT1: %16Lx\n",
+ IoStat0.all.QuadPart,
+ IoStat1.all.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "ICCSR : %016Lx ABOX_CTL: %016Lx DC_STAT: %016Lx\n",
+ ICCSR_ALL_21064(LogoutFrame->Iccsr),
+ ABOXCTL_ALL_21064(LogoutFrame->AboxCtl),
+ DCSTAT_ALL_21064(LogoutFrame->DcStat) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "EXC_ADDR : %016Lx VA : %016Lx MM_CSR : %016Lx\n",
+ LogoutFrame->ExcAddr.QuadPart,
+ LogoutFrame->Va.QuadPart,
+ MMCSR_ALL_21064(LogoutFrame->MmCsr) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "HIRR : %016Lx HIER : %016Lx PS : %016Lx\n",
+ IRR_ALL_21064(LogoutFrame->Hirr),
+ IER_ALL_21064(LogoutFrame->Hier),
+ PS_ALL_21064(LogoutFrame->Ps) );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "PAL_BASE : %016Lx \n",
+ LogoutFrame->PalBase.QuadPart );
+
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer, "Waiting 15 seconds...\n");
+ HalDisplayString( OutBuffer );
+
+ for( Index=0; Index<1500; Index++)
+ KeStallExecutionProcessor( 10000 ); // ~15 second delay
+
+ //
+ // Print out interpretation of the error.
+ //
+
+ //
+ // First print the processor on which we saw the error
+ //
+
+ Prcb = PCR->Prcb;
+ sprintf( OutBuffer, "Error on processor number: %d\n",
+ HalpLogicalToPhysicalProcessor[Prcb->Number] );
+ HalDisplayString( OutBuffer );
+
+ //
+ // If we got a Data Cache Parity Error print a message on screen.
+ //
+
+ if( DCSTAT_DCPARITY_ERROR_21064(LogoutFrame->DcStat) ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = PROCESSOR_CACHE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( parityErrString,
+ "Data Cache Parity Error.\n");
+ HalpGetProcessorInfo(&exterr->CacheError.ProcessorInfo);
+
+ sprintf( OutBuffer, "Data Cache Parity Error.\n" );
+ HalDisplayString( OutBuffer );
+ }
+
+ //
+ // Check for uncorrectable error.
+ //
+
+ if( Esr.Uee == 1 ){
+
+ if( Esr.Sor == 0 ){
+
+ //
+ // Uncorrectable error from cache.
+ //
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = PROCESSOR_CACHE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ HalpGetProcessorInfo(&exterr->CacheError.ProcessorInfo);
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Uncorrectable error from cache on %s, Tag: 0x%x\n",
+ Esr.Wre ? "write" : "read",
+ Car.Tag );
+ HalDisplayString( parityErrString );
+
+ } else {
+
+ //
+ // Uncorrectable error from memory.
+ //
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_MEMORY;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ HalpGetProcessorInfo(&exterr->MemoryError.ProcessorInfo);
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Uncorrectable error from memory on %s\n",
+ Esr.Wre ? "write" : "read" );
+ HalDisplayString( parityErrString );
+
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ Ear.ErrorAddress;
+
+ exterr->MemoryError.Flags.MemorySimmValid = 1;
+ exterr->MemoryError.MemorySimm =
+ HalpSimmError( Ear.ErrorAddress, LogoutFrame );
+
+ sprintf( OutBuffer,
+ "Physical Address: 0x%x, Bank: %d, SIMM: %d\n",
+ Ear.ErrorAddress,
+ HalpBankError( Ear.ErrorAddress, LogoutFrame ),
+ HalpSimmError( Ear.ErrorAddress, LogoutFrame ) );
+ HalDisplayString( OutBuffer );
+
+ } //end if( Esr.Sor == 0 )
+
+ } //end if( Esr.Uee == 1 )
+
+ //
+ // Check for cache tag errors.
+ //
+
+ if( Esr.Cte == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = PROCESSOR_CACHE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ HalpGetProcessorInfo(&exterr->CacheError.ProcessorInfo);
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+
+ sprintf( parityErrString,
+ "Cache Tag Error, Tag: 0x%x, Hit: %d\n",
+ Car.Tag, Car.Hit );
+ HalDisplayString( parityErrString );
+
+ }
+
+ //
+ // Check for non-existent memory error.
+ //
+
+ if( Esr.Nxm == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_MEMORY;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ HalpGetProcessorInfo(&exterr->MemoryError.ProcessorInfo);
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Non-existent memory accessed\n" );
+ sprintf( OutBuffer,
+ "Non-existent memory accessed, Physical Address: 0x%x.\n",
+ Ear.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Check for multiple hard errors.
+ //
+
+ if( Esr.Mhe == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ MEMORY_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_MEMORY;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ HalpGetProcessorInfo(&exterr->MemoryError.ProcessorInfo);
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Multiple hard errors detected\n" );
+
+ sprintf( OutBuffer,
+ "Multiple hard errors detected.\n" );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // If an I/O Error was pending print the interpretation.
+ //
+
+ if( IoStat0.Err == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ exterr->IoError.Interface = PCIBus;
+ exterr->IoError.BusNumber = 0;
+ exterr->IoError.BusAddress.QuadPart = IoStat1.Address;
+ PUncorrectableError->UncorrectableFrame.Flags.PhysicalAddressValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ IoStat1.Address;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+
+ switch( IoStat0.Code ){
+
+ //
+ // Retry Limit.
+ //
+
+ case IocErrorRetryLimit:
+ sprintf(parityErrString,
+ "Retry Limit Error, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+ sprintf( OutBuffer,
+ "Retry Limit Error, PCI Address 0x%x PCI Cmd 0x%x\n",
+ IoStat1.Address,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // No device error.
+ //
+
+ case IocErrorNoDevice:
+ sprintf(parityErrString,
+ "No Device Error, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+
+ sprintf( OutBuffer,
+ "No Device Error, PCI Address 0x%x PCI Cmd 0x%x\n",
+ IoStat1.Address,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Bad data parity.
+ //
+
+ case IocErrorBadDataParity:
+ sprintf(parityErrString,
+ "Bad Data Parity Error, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+
+ sprintf( OutBuffer,
+ "Bad Data Parity Error, PCI Address 0x%x PCI Cmd 0x%x\n",
+ IoStat1.Address,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Target abort.
+ //
+
+ case IocErrorTargetAbort:
+ sprintf(parityErrString,
+ "Target Abort, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+
+ sprintf( OutBuffer,
+ "Target Abort, PCI Address 0x%x PCI Cmd 0x%x\n",
+ IoStat1.Address,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Bad address parity.
+ //
+
+ case IocErrorBadAddressParity:
+ sprintf(parityErrString,
+ "Bad Address Parity, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+
+ sprintf( OutBuffer,
+ "Bad Address Parity, PCI Address 0x%x PCI Cmd 0x%x\n",
+ IoStat1.Address,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Page Table Read Error.
+ //
+
+ case IocErrorPageTableReadError:
+ sprintf(parityErrString,
+ "Page Table Read Error, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+
+ sprintf( OutBuffer,
+ "Page Table Read Error, PCI Pfn 0x%x PCI Cmd 0x%x\n",
+ IoStat0.PageNumber,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Invalid page.
+ //
+
+ case IocErrorInvalidPage:
+ sprintf(parityErrString,
+ "Invalid Page Error, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+
+ sprintf( OutBuffer,
+ "Invalid Page Error, PCI Pfn 0x%x PCI Cmd 0x%x\n",
+ IoStat0.PageNumber,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Data error.
+ //
+
+ case IocErrorDataError:
+
+ sprintf(parityErrString,
+ "Data Error, PCI Cmd 0x%x\n",
+ IoStat0.Cmd );
+
+ sprintf( OutBuffer,
+ "Data Error, PCI Address 0x%x PCI Cmd 0x%x\n",
+ IoStat1.Address,
+ IoStat0.Cmd );
+ break;
+
+ //
+ // Unrecognized error code.
+ //
+
+ default:
+
+ sprintf(parityErrString,
+ "Unrecognized I/O Error.\n" );
+
+ sprintf( OutBuffer, "Unrecognized I/O Error.\n" );
+ break;
+
+ } //end switch (IoStat0.Code)
+
+ HalDisplayString( OutBuffer );
+
+ if( IoStat0.Lost == 1 ){
+ sprintf(parityErrString,
+ "Additional I/O errors were lost.\n" );
+
+ HalDisplayString( "Additional I/O errors were lost.\n" );
+ }
+
+ } //end if( IoStat0.Err == 1 )
+
+ //
+ // return to caller
+ //
+
+ return;
+
+}
+
+
+ULONG
+HalpBankError(
+ ULONG PhysicalAddress,
+ PLOGOUT_FRAME_21066 LogoutFrame
+ )
+/*++
+
+Routine Description:
+
+ Return the bank of memory that the physical address fails within.
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address to locate.
+
+ LogoutFrame - Supplies a pointer to the logout frame that contains the
+ bank configuration information.
+
+Return Value:
+
+ Returns the number of the bank that contains the physical address.
+ Returns 0xffffffff if the physical address is not contained within any of
+ the banks.
+
+--*/
+{
+
+ ULONG Bank;
+
+ for( Bank=0; Bank < MEMORY_BANKS_21066; Bank++ ){
+
+ //
+ // If the bank is valid and the physical address is within the
+ // bank then we have found the correct bank.
+ //
+
+ if( (LogoutFrame->BankConfig[Bank].Bav == 1) &&
+ ((PhysicalAddress >> 20) &
+ (~LogoutFrame->BankMask[Bank].BankAddressMask)) ==
+ LogoutFrame->BankConfig[Bank].BankBase ){
+
+ return Bank;
+
+ }
+
+ }
+
+ //
+ // Did not find a bank which contains physical address.
+ //
+
+ return (0xffffffff);
+
+}
+
+//jnfix - this should be move to platform-specific
+//jnfix - and made real depending upon how memory is configured
+//jnfix - this current code is a simple guess which provides a model
+
+ULONG
+HalpSimmError(
+ ULONG PhysicalAddress,
+ PLOGOUT_FRAME_21066 LogoutFrame
+ )
+/*++
+
+Routine Description:
+
+ Return the SIMM number that the physical address fails within.
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address to locate.
+
+ LogoutFrame - Supplies a pointer to the logout frame that contains the
+ bank configuration information.
+
+Return Value:
+
+ Returns the number of the SIMM that contains the physical address.
+ Returns 0xffffffffif the physical address is not contained within any of
+ the SIMMs.
+
+--*/
+{
+ ULONG Bank;
+ ULONG Simm;
+
+ for( Bank=0; Bank < MEMORY_BANKS_21066; Bank++ ){
+
+ //
+ // If the bank is valid and the physical address is within the
+ // bank then we have found the correct bank.
+ //
+
+ if( (LogoutFrame->BankConfig[Bank].Bav == 1) &&
+ ((PhysicalAddress >> 20) &
+ (~LogoutFrame->BankMask[Bank].BankAddressMask)) ==
+ LogoutFrame->BankConfig[Bank].BankBase ){
+
+ //
+ // Assume that each bank contains 2 SIMMs and that they are
+ // numbered 0..N. We need to determine which SIMM within the
+ // bank. We will guess that the SIMMs are 32-bits wide and
+ // that the low 32-bits are in the low SIMM while the high
+ // 32-bits are in the high SIMM. So addresses 0..3 are low
+ // and 4..7 are high.
+ //
+
+ Simm = Bank * 2;
+ if( PhysicalAddress & 4 ) Simm += 1;
+ return Simm;
+
+ }
+
+ }
+
+ //
+ // Did not find a bank which contains physical address.
+ //
+
+ return (0xffffffff);
+
+}
diff --git a/private/ntos/nthals/halalpha/lcaioacc.s b/private/ntos/nthals/halalpha/lcaioacc.s
new file mode 100644
index 000000000..8d6f98760
--- /dev/null
+++ b/private/ntos/nthals/halalpha/lcaioacc.s
@@ -0,0 +1,746 @@
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ lcaioacc.s
+
+
+Abstract:
+
+ This module implements the low-level I/O access routines for the
+ DECchip 21066 microprocessor (a.k.a. Low Cost Alpha or LCA).
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using the 43-bit superpage mode.)
+
+
+Author:
+
+ Jeff Mcleman (mcleman) 13-Jan-1993
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ 9-Mar-1993 - Bruce Butts - replaced hardcoded constants with
+ IO_BIT_SHIFT, IO_xxxx_LEN, and IO_xxxx_OFFSET
+ values defined in mrgndef.h. Commented out several
+ unused defines.
+
+ 3-Mar-1993 - Jeff McLeman - Bring up to rev.
+
+ 28-July-1994 - Sameer Dekate -
+
+ Made a common file alphaio.s for machine independent IO routines.
+
+
+--*/
+
+
+#include "lca4.h"
+#include "halalpha.h"
+
+
+
+ SBTTL( "Write I/O control register" )
+//++
+//
+// VOID
+// WRITE_IOC_REGISTER(
+// QVA RegisterQva,
+// ULONGLONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a quadword location to LCA IOC register space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of register to be written.
+// Value(a1) - Supplies the quadword to be written.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_IOC_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+ stq a1, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+2:
+ stq a1, (a0) // store the longword
+ ret zero, (ra) // return
+
+ .end WRITE_IOC_REGISTER
+
+
+
+#define LCA4_MEMC_BASE_PHYSICAL 0x120000000
+
+ SBTTL( "Write memory control register" )
+//++
+//
+// VOID
+// WRITE_MEMC_REGISTER(
+// ULONG RegisterOffset,
+// ULONGLONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a quadword location to LCA MEMC register space.
+//
+// Arguments:
+//
+// RegisterOffset(a0) - Supplies the offset of the memory controller
+// register within memory controller physical space.
+// Value(a1) - Supplies the quadword to be written.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_MEMC_REGISTER)
+
+ ldiq t0, LCA4_MEMC_BASE_PHYSICAL // get memory cntlr physical address
+
+ ldiq t4, -0x4000 // create superpage mask
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+
+ bis t0, t4, t0 // get superpage address of mem ctlr
+ bis t0, a0, t0 // add offset of specified register
+
+ stq a1, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+ .end WRITE_MEMC_REGISTER
+
+
+
+ SBTTL( "Read I/O control register" )
+//++
+//
+// ULONGLONG
+// READ_IOC_REGISTER(
+// QVA RegisterQva
+// )
+//
+// Routine Description:
+//
+// Read a quadword location from LCA IOC register space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of register to be read.
+//
+// Return Value:
+//
+// v0 - Return the value read from the controller register.
+//
+//--
+
+ LEAF_ENTRY(READ_IOC_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+ ldq v0, (t0) // read the quadword
+
+ ret zero, (ra) // return
+
+2:
+ ldq v0, (a0) // read the quadword
+ ret zero, (ra) // return
+
+ .end READ_IOC_REGISTER
+
+
+
+ SBTTL( "Read memory control register" )
+//++
+//
+// ULONGLONG
+// READ_MEMC_REGISTER(
+// ULONG RegisterOffset,
+// )
+//
+// Routine Description:
+//
+// Read a quadword location from LCA MEMC register space.
+//
+// Arguments:
+//
+// RegisterOffset(a0) - Supplies the offset of the memory controller
+// register within memory controller physical space.
+//
+// Return Value:
+//
+// v0 - Return the value read from the controller register.
+//
+//--
+
+ LEAF_ENTRY(READ_MEMC_REGISTER)
+
+ ldiq t0, LCA4_MEMC_BASE_PHYSICAL // get memory cntlr physical address
+
+ ldiq t4, -0x4000 // create superpage mask
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+
+ bis t0, t4, t0 // get superpage address of mem ctlr
+ bis t0, a0, t0 // add offset of specified register
+
+ ldq v0, (t0) // read the quadword
+ ret zero, (ra) // return
+
+ .end READ_MEMC_REGISTER
+
+
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the QVA for the Configuration Cycle Type register within the
+// IOC.
+//
+
+#define IOC_CONFIG_CYCLE_TYPE_QVA (0xac000001)
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved ConfigurationAddress
+CfgA1: .space 8 // saved ConfigurationData
+ .space 8 // padding for 16 byte alignment
+CfgFrameLength:
+
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the cycle type into the ConfigurationCycleType register in
+// the IOC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+
+ ldil a0, IOC_CONFIG_CYCLE_TYPE_QVA // address of cycle type register
+ bsr ra, WRITE_IOC_REGISTER // update the configuration cycle type
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extbl v0, t3, v0 // return the byte from the right lane
+ // also, consume loaded value to cause
+ // a pipeline stall
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write an unsigned byte to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the cycle type into the ConfigurationCycleType register in
+// the IOC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+
+ ldil a0, IOC_CONFIG_CYCLE_TYPE_QVA // address of cycle type register
+ bis a2, zero, a1 // set cycle type
+
+ bsr ra, WRITE_IOC_REGISTER // update the configuration cycle type
+
+//
+// Perform the write to configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t0) // write the configuration byte
+ mb // synchronize
+
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a short from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the cycle type into the ConfigurationCycleType register in
+// the IOC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+
+ ldil a0, IOC_CONFIG_CYCLE_TYPE_QVA // address of cycle type register
+ bsr ra, WRITE_IOC_REGISTER // update the configuration cycle type
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extwl v0, t3, v0 // return word from requested lanes
+ // also, consume loaded value to cause
+ // a pipeline stall
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// USHORT ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the cycle type into the ConfigurationCycleType register in
+// the IOC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+
+ ldil a0, IOC_CONFIG_CYCLE_TYPE_QVA // address of cycle type register
+ bis a2, zero, a1 // set configuration cycle type
+
+ bsr ra, WRITE_IOC_REGISTER // update the configuration cycle type
+
+//
+// Perform the write to configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1, t3, t4 // put data to appropriate lane
+ stl t4, (t0) // write the longword
+ mb // synchronize
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the cycle type into the ConfigurationCycleType register in
+// the IOC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+
+ ldil a0, IOC_CONFIG_CYCLE_TYPE_QVA // address of cycle type register
+ bsr ra, WRITE_IOC_REGISTER // update the configuration cycle type
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ bis v0, zero, t1 // consume loaded value to cause
+ // a pipeline stall
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write a longword to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Write the cycle type into the ConfigurationCycleType register in
+// the IOC.
+//
+
+ stq a0, CfgA0(sp) // save configuration space address
+ stq a1, CfgA1(sp) // save configuration data
+
+ ldil a0, IOC_CONFIG_CYCLE_TYPE_QVA // address of cycle type register
+ bis a2, zero, a1 // set configuration cycle type
+
+ bsr ra, WRITE_IOC_REGISTER // update the configuration cycle type
+
+//
+// Perform the write to configuration space after restoring the
+// configuration space address and data.
+//
+
+ ldq a0, CfgA0(sp) // restore configuration space address
+ ldq a1, CfgA1(sp) // restore configuration data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // synchronize
+2: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
diff --git a/private/ntos/nthals/halalpha/memory.c b/private/ntos/nthals/halalpha/memory.c
new file mode 100644
index 000000000..306b9be61
--- /dev/null
+++ b/private/ntos/nthals/halalpha/memory.c
@@ -0,0 +1,575 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ memory.c
+
+Abstract:
+
+ Provides routines to allow tha HAL to map physical memory
+
+Author:
+
+ Jeff McLeman (DEC) 11-June-1992
+
+Revision History:
+
+ Joe Notarangelo 20-Oct-1993
+ - Fix bug where physical address was rounded up without referencing
+ AlignmentOffset, resulting in an incorrect physical address
+ - Remove magic numbers
+ - Create a routine to dump all of the descriptors to the debugger
+
+Environment:
+
+ Phase 0 initialization only
+
+--*/
+
+#include "halp.h"
+
+#define __1KB (1024)
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN AlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block which
+ contains the system memory descriptors.
+
+ MaxPhysicalAddress - Supplies the maximum address below which the memory
+ must be allocated.
+
+ NoPages - Supplies the number of pages to allocate.
+
+ AlignOn64k - Supplies a boolean that specifies if the requested memory
+ allocation must start on a 64K boundary.
+
+Return Value:
+
+ The pyhsical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ ULONG AlignmentMask;
+ ULONG AlignmentOffset;
+ PMEMORY_ALLOCATION_DESCRIPTOR BestFitDescriptor;
+ ULONG BestFitAlignmentOffset;
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+ AlignmentMask = (__64K >> PAGE_SHIFT) - 1;
+
+ BestFitDescriptor = NULL;
+ BestFitAlignmentOffset = AlignmentMask + 1;
+
+ //
+ // Scan the memory allocation descriptors for an eligible descriptor from
+ // which we can allocate the requested block of memory.
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if( AlignOn64k ){
+
+ AlignmentOffset =
+ ((Descriptor->BasePage + AlignmentMask) & ~AlignmentMask) -
+ Descriptor->BasePage;
+
+ } else {
+
+ AlignmentOffset = 0;
+
+ }
+
+ //
+ // Search for a block of memory which is contains a memory chunk
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset <
+ MaxPageAddress) )
+ {
+
+ //
+ // Check for a perfect fit where we need not split the descriptor
+ // because AlignmentOffset == 0. No need to search further if
+ // there is a perfect fit.
+ //
+
+ if( AlignmentOffset == 0 ){
+ BestFitDescriptor = Descriptor;
+ BestFitAlignmentOffset = AlignmentOffset;
+ break;
+ }
+
+ //
+ // If not a perfect fit check for the best fit so far.
+ //
+
+ if( AlignmentOffset < BestFitAlignmentOffset ){
+ BestFitDescriptor = Descriptor;
+ BestFitAlignmentOffset = AlignmentOffset;
+ }
+
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Verify that we have found an eligible descriptor.
+ //
+
+ ASSERT( BestFitDescriptor != NULL );
+
+ if( BestFitDescriptor == NULL ){
+ return (ULONG)NULL;
+ }
+
+ //
+ // Compute the physical address of the memory block we have found.
+ //
+
+ PhysicalAddress = (BestFitDescriptor->BasePage + BestFitAlignmentOffset)
+ << PAGE_SHIFT;
+ //
+ // Adjust the memory descriptors to account for the memory we have
+ // allocated.
+ //
+
+ if (BestFitAlignmentOffset == 0) {
+
+ BestFitDescriptor->BasePage += NoPages;
+ BestFitDescriptor->PageCount -= NoPages;
+
+ if (BestFitDescriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&BestFitDescriptor->ListEntry);
+
+ }
+
+ } else {
+
+ //
+ // The descriptor will be split into 3 pieces, the beginning
+ // segment up to our allocation, our allocation, and the trailing
+ // segment. We have one spare memory descriptor to handle this
+ // case, use it if it is not already used otherwise preserve as
+ // much memory as possible.
+ //
+
+ if( (BestFitDescriptor->PageCount - NoPages - BestFitAlignmentOffset)
+ == 0 ){
+
+ //
+ // The third segment is empty, use the original descriptor to
+ // map the first segment.
+ //
+
+ BestFitDescriptor->PageCount -= NoPages;
+
+ } else {
+
+ if( HalpExtraAllocationDescriptor.PageCount == 0 ){
+
+ //
+ // The extra descriptor can be used to map the third segment.
+ //
+
+ HalpExtraAllocationDescriptor.PageCount =
+ BestFitDescriptor->PageCount - NoPages -
+ BestFitAlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ BestFitDescriptor->BasePage + NoPages +
+ BestFitAlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+
+ InsertTailList(
+ &BestFitDescriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry );
+
+ //
+ // Use the original descriptor to map the first segment.
+ //
+
+ BestFitDescriptor->PageCount = BestFitAlignmentOffset;
+
+ } else {
+
+ //
+ // We need to split the original descriptor into 3 segments
+ // but we've already used the spare descriptor. Use the
+ // original descriptor to map the largest segment.
+ //
+
+ ULONG WastedPages;
+
+ if( (BestFitDescriptor->PageCount - BestFitAlignmentOffset -
+ NoPages) > BestFitAlignmentOffset ){
+
+ WastedPages = BestFitAlignmentOffset;
+
+ //
+ // Map the third segment using the original descriptor.
+ //
+
+ BestFitDescriptor->BasePage += BestFitAlignmentOffset +
+ NoPages;
+ BestFitDescriptor->PageCount -= BestFitAlignmentOffset +
+ NoPages;
+
+ } else {
+
+ WastedPages = BestFitDescriptor->PageCount -
+ BestFitAlignmentOffset - NoPages;
+
+ //
+ // Map the first segment using the original descriptor.
+ //
+
+ BestFitDescriptor->PageCount = BestFitAlignmentOffset;
+
+ } //end if( (BestFitDescriptor->PageCount - BestFitAlignm ...
+
+ //
+ // Report that we have had to waste pages.
+ //
+
+ DbgPrint( "HalpAllocPhysicalMemory: wasting %d pages\n",
+ WastedPages );
+
+ } //end if( HalpExtraAllocationDescriptor.PageCount == 0 )
+
+ } //end if( (BestFitDescriptor->PageCount - NoPages - BestFitAlign ...
+
+ } //end if (BestFitAlignmentOffset == 0)
+
+
+ return PhysicalAddress;
+}
+
+ULONGLONG
+HalpGetMemorySize(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ Computes the size of the memory from the descriptor list.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+
+Return Value:
+
+ Size of Memory in Bytes.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG PageCounts = 0;
+
+ //
+ // Scan the memory allocation descriptors and
+ // compute the Total pagecount
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // ignore bad memory descriptors.
+ //
+ if(Descriptor->MemoryType != LoaderBad){
+ PageCounts += Descriptor->PageCount;
+ }
+
+
+ NextMd = NextMd->Flink;
+ }
+
+ return (PageCounts << PAGE_SHIFT) ;
+
+}
+
+TYPE_OF_MEMORY
+HalpGetMemoryType (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG PageAddress,
+ OUT PULONG EndPageAddressInDesc
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks to see how the specified address is mapped.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ PageAddress - The page address of memory to probe.
+
+Return Value:
+
+ The memory type of the specified address, if it is mapped. If the
+ address is not mapped, then LoaderMaximum is returned.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG PageCounts = 0;
+ TYPE_OF_MEMORY MemoryType = LoaderMaximum;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((PageAddress >= Descriptor->BasePage) &&
+ (PageAddress <
+ Descriptor->BasePage + Descriptor->PageCount)) {
+
+ MemoryType = Descriptor->MemoryType;
+ *EndPageAddressInDesc = Descriptor->BasePage +
+ Descriptor->PageCount - 1;
+ break; // we found the descriptor.
+ }
+
+ NextMd = NextMd->Flink;
+ }
+ return MemoryType;
+}
+
+
+ULONGLONG
+HalpGetContiguousMemorySize(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ Computes the size of initial contiguous memory from the
+ descriptor list. Contiguous memory means, that there is
+ no hole or Bad memory in this range.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+
+Return Value:
+
+ Size of Memory in Bytes.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG PageCounts = 0;
+ TYPE_OF_MEMORY MemoryType;
+ ULONG EndPageAddressInDesc = 0;
+
+ //
+ // Start from Page Address 0 and go until we hit a page
+ // with no descriptor or Bad Descriptor.
+ //
+
+ MemoryType = HalpGetMemoryType(LoaderBlock,
+ PageCounts,
+ &EndPageAddressInDesc
+ );
+ while(MemoryType != LoaderMaximum && MemoryType != LoaderBad){
+ PageCounts = EndPageAddressInDesc + 1;
+ MemoryType = HalpGetMemoryType(LoaderBlock,
+ PageCounts,
+ &EndPageAddressInDesc
+ );
+ }
+
+ return (PageCounts << PAGE_SHIFT) ;
+
+}
+
+
+#if HALDBG
+
+
+VOID
+HalpDumpMemoryDescriptors(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ Print the contents of the memory descriptors built by the
+ firmware and OS loader and passed through to the kernel.
+ This routine is intended as a sanity check that the descriptors
+ have been prepared properly and that no memory has been wasted.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG PageCounts[LoaderMaximum];
+ PCHAR MemoryTypeStrings[] = {
+ "ExceptionBlock",
+ "SystemBlock",
+ "Free",
+ "Bad",
+ "LoadedProgram",
+ "FirmwareTemporary",
+ "FirmwarePermanent",
+ "OsloaderHeap",
+ "OsloaderStack",
+ "SystemCode",
+ "HalCode",
+ "BootDriver",
+ "ConsoleInDriver",
+ "ConsoleOutDriver",
+ "StartupDpcStack",
+ "StartupKernelStack",
+ "StartupPanicStack",
+ "StartupPcrPage",
+ "StartupPdrPage",
+ "RegistryData",
+ "MemoryData",
+ "NlsData",
+ "SpecialMemory"
+ };
+ ULONG i;
+
+ //
+ // Clear the summary information structure.
+ //
+
+ RtlZeroMemory( PageCounts, sizeof(ULONG) * LoaderMaximum );
+
+ //
+ // Scan the memory allocation descriptors print each descriptor and
+ // collect summary information.
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if( (Descriptor->MemoryType >= LoaderExceptionBlock) &&
+ (Descriptor->MemoryType < LoaderMaximum) )
+ {
+
+ PageCounts[Descriptor->MemoryType] += Descriptor->PageCount;
+ DbgPrint( "%08x: %08x Type = %s\n",
+ (Descriptor->BasePage << PAGE_SHIFT) | KSEG0_BASE,
+ ( ( (Descriptor->BasePage + Descriptor->PageCount)
+ << PAGE_SHIFT) - 1) | KSEG0_BASE,
+ MemoryTypeStrings[Descriptor->MemoryType] );
+
+
+ } else {
+
+ DbgPrint( "%08x: %08x Unrecognized Memory Type = %x\n",
+ (Descriptor->BasePage << PAGE_SHIFT) | KSEG0_BASE,
+ ( ( (Descriptor->BasePage + Descriptor->PageCount)
+ << PAGE_SHIFT) - 1) | KSEG0_BASE,
+ Descriptor->MemoryType );
+
+ DbgPrint( "Unrecognized memory type\n" );
+
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+
+ //
+ // Print the summary information.
+ //
+
+ for( i=LoaderExceptionBlock; i<LoaderMaximum; i++ ){
+
+ //
+ // Only print those memory types that have non-zero allocations.
+ //
+
+ if( PageCounts[i] != 0 ){
+
+ DbgPrint( "%8dK %s\n",
+ (PageCounts[i] << PAGE_SHIFT) / __1K,
+ MemoryTypeStrings[i] );
+
+ }
+
+ }
+
+ return;
+}
+
+#endif //HALDBG
diff --git a/private/ntos/nthals/halalpha/nvenv.c b/private/ntos/nthals/halalpha/nvenv.c
new file mode 100644
index 000000000..45c4a6f70
--- /dev/null
+++ b/private/ntos/nthals/halalpha/nvenv.c
@@ -0,0 +1,533 @@
+#if defined(TAGGED_NVRAM)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ nvenv.c
+
+Abstract:
+
+ This module implements the ARC firmware Environment Variable functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.11.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+
+Revision History:
+
+ Dave Richards 94.11.03
+
+ Added support for the tagged NVRAM layout/API.
+
+ James Livingston 94.05.17
+
+ Fix a coding error that caused NVRAM to get trashed in the attempt
+ to update a nearly full environment variable space.
+
+ Steve Jenness 93.12.20
+
+ The firmware still requires the naked checksum set and check
+ routines. Add them back in under the AXP_FIRMWARE conditional
+ until the jxenvir.c in the firmware and the environ.c files
+ are rationalized.
+
+ Steve Jenness. 93.12.17
+
+ Reduce the reads and writes to the NVRAM part. Some parts are
+ slow to access (especially on writes). Do NVRAM access only when
+ really necessary. Remove use of HalpCopyNVRamBuffer because it is
+ too difficult to make generically fast (put more intelligence
+ in higher code instead).
+
+ Steve Brooks. 6-Oct 1993 remove all platform and device specific references
+
+ These routines have been restructured to be platform and device
+ independant. All calls access the NVRAM via the calls
+ HalpReadNVRamBuffer, HalpWriteNVRamBuffer, and HalpCopyNVRamBuffer
+
+ Jeff McLeman (DEC) 31-Jul-1992 modify for Jensen
+
+--*/
+
+#include "arccodes.h"
+#include "halp.h"
+#include "nvram.h"
+
+//
+// Routine prototypes.
+//
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ );
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT length,
+ OUT PCHAR Buffer
+ );
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ );
+
+#ifdef AXP_FIRMWARE
+
+#pragma alloc_text(DISTEXT, HalpFindEnvironmentVariable )
+#pragma alloc_text(DISTEXT, HalGetEnvironmentVariable )
+#pragma alloc_text(DISTEXT, HalSetEnvironmentVariable )
+
+#endif // AXP_FIRMWARE
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the supplied NVRAM image
+ for the given Variable.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+ VariableIndex - Returned byte offset into Environment of the
+ Variable if found.
+ ValueIndex - Returned byte offset into Environment of the
+ value of the Variable if found.
+
+Return Value:
+
+ ESUCCESS - Variable found and indicies returned.
+ ENOENT - Variable not found.
+
+--*/
+
+{
+ ULONG EnvironmentOffset;
+ ULONG EnvironmentLength;
+ PUCHAR String;
+ UCHAR Char;
+ ULONG Index;
+
+ //
+ // If Variable is null, return immediately.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Get the offset and length of the environment in NVRAM.
+ //
+
+ EnvironmentOffset = HalpGetNVRamEnvironmentOffset();
+ EnvironmentLength = HalpGetNVRamEnvironmentLength();
+
+ Index = 0;
+
+ while (TRUE) {
+
+ //
+ // Set string to beginning of Variable.
+ //
+
+ String = Variable;
+ *VariableIndex = EnvironmentOffset + Index;
+
+ //
+ // Search until the end of NVRAM.
+ //
+
+ while ( Index < EnvironmentLength ) {
+
+ //
+ // Convert to uppercase and break if mismatch.
+ //
+
+ Char = HalpGetNVRamUchar(EnvironmentOffset + Index);
+
+ if ( Char != ((*String >= 'a') && (*String <= 'z') ?
+ (*String - 'a' + 'A') : *String) ) {
+ break;
+ }
+
+ String++;
+ Index++;
+ }
+
+ if ( Index == EnvironmentLength )
+ return ENOENT;
+
+ //
+ // Check to see if we're at the end of the string and the variable,
+ // which means a match.
+ //
+
+ Char = HalpGetNVRamUchar(EnvironmentOffset + Index);
+ if ((*String == 0) && (Char == '=')) {
+ *ValueIndex = EnvironmentOffset + ++Index;
+ return ESUCCESS;
+ }
+
+ //
+ // Move index to the start of the next variable.
+ //
+
+ do {
+ Char = HalpGetNVRamUchar(EnvironmentOffset + Index++);
+
+ if (Index >= EnvironmentLength) {
+ return ENOENT;
+ }
+
+ } while (Char != 0);
+
+ }
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the non-volatile ram for
+ Variable, and if found returns a pointer to a zero terminated string that
+ contains the value, otherwise a NULL pointer is returned.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+ Length - Supplies the length of the value buffer in bytes
+
+ Buffer - Supplies a pointer to a buffer that will recieve the
+ environment variable.
+
+Return Value:
+
+ ESUCCESS - Buffer contains the zero terminated string value of Variable.
+ ENOENT - The variable doesn't exist in the environment.
+ ENOMEM - The variable exists, but the value is longer than Length.
+
+--*/
+
+{
+ ULONG NvChars;
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG Index;
+ ARC_STATUS Status;
+
+ //
+ // If checksum is wrong, or the variable can't be found, return NULL.
+ //
+
+ if ((!HalpIsNVRamRegion0Valid()) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+ Status = ENOENT;
+ } else {
+
+ //
+ // Copy value to an output string, break on zero terminator
+ // or string max.
+ //
+
+ NvChars = ValueIndex;
+ for ( Index = 0 ; Index < length ; Index += 1 ) {
+ if ( (*Buffer++ = HalpGetNVRamUchar(NvChars++)) == 0 ) {
+ break;
+ }
+ }
+
+ if (Index == length) {
+ Status = ENOMEM;
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets Variable (not case sensitive) to Value.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+ Value - Supplies a zero terminated string containing an environment
+ variable value.
+
+Return Value:
+
+ ESUCCESS - The set completed successfully
+ ENOSPC - No space in NVRAM for set operation.
+ EIO - Invalid Checksum.
+
+--*/
+
+{
+ ULONG EnvironmentOffset;
+ ULONG EnvironmentLength;
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG TopOfEnvironment;
+ PCHAR String;
+ ULONG NvChars;
+ LONG Count;
+ CHAR Char;
+
+ //
+ // If checksum is wrong, return EIO;
+ //
+
+ if (!HalpIsNVRamRegion0Valid()) {
+ return EIO;
+ }
+
+ //
+ // Get the offset and length of the environment in NVRAM.
+ //
+
+ EnvironmentOffset = HalpGetNVRamEnvironmentOffset();
+ EnvironmentLength = HalpGetNVRamEnvironmentLength();
+
+//
+//smjfix - examine the boundary condition where the environment space
+// is exactly filled.
+
+ //
+ // Determine the top of the environment space by looking for the first
+ // non-null character from the top.
+ //
+
+ TopOfEnvironment = EnvironmentOffset + EnvironmentLength - 1;
+
+ do {
+ Char = HalpGetNVRamUchar(TopOfEnvironment);
+
+ } while ( Char == 0 && (--TopOfEnvironment > EnvironmentOffset) );
+
+ //
+ // Adjust TopOfEnvironment to the first new character, unless environment
+ // space is empty, or the environment is exactly full. In the latter
+ // case, the new value MUST fit into the space taken by the old.
+ //
+
+ if (TopOfEnvironment != EnvironmentOffset &&
+ TopOfEnvironment < EnvironmentOffset + EnvironmentLength - 2) {
+ TopOfEnvironment += 2;
+ }
+
+ //
+ // Handle the case where the content of the NVRAM has been corrupted
+ // such that the last character in the environment is non-zero.
+ //
+
+ Count = (EnvironmentOffset + EnvironmentLength - 1) - TopOfEnvironment;
+ if (Count < 0) {
+ return ENOSPC;
+ }
+
+
+ //
+ // Check to see if the variable already has a value.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex)
+ == ESUCCESS) {
+ ULONG SizeOfValue = strlen(Value);
+
+ if (SizeOfValue == HalpGetNVRamStringLength(ValueIndex)) {
+
+ //
+ // Overwrite the current variable in place.
+ //
+
+ HalpMoveMemoryToNVRam(ValueIndex, Value, SizeOfValue);
+
+ //
+ // Suppress the append of the variable to the end of the
+ // environment variable data.
+ //
+
+ *Value = 0;
+
+ } else {
+
+ //
+ // Count free space, starting with the free area at the top and
+ // adding the old variable value.
+ //
+
+ for ( NvChars = ValueIndex;
+ NvChars <= TopOfEnvironment;
+ NvChars++ ) {
+
+ Char = HalpGetNVRamUchar(NvChars);
+ if ( Char == 0 )
+ break;
+ Count++;
+ }
+
+ //
+ // Determine if free area is large enough to handle new value, if
+ // not return error.
+ //
+
+ for ( String = Value ; *String != 0 ; String++ ) {
+ if (Count-- == 0) {
+ return ENOSPC;
+ }
+ }
+
+ //
+ // Move ValueIndex to the end of the value and compress strings.
+ //
+
+ do {
+ Char = HalpGetNVRamUchar(ValueIndex++);
+ } while( Char != 0 );
+
+ Count = TopOfEnvironment - ValueIndex;
+
+ HalpMoveNVRamToNVRam(VariableIndex, ValueIndex, Count);
+
+ //
+ // Adjust new top of environment.
+ //
+
+ TopOfEnvironment = VariableIndex+Count;
+
+ //
+ // Zero to the end.
+ //
+
+ Count = EnvironmentOffset + EnvironmentLength - TopOfEnvironment;
+ Char = 0;
+ while ( Count -- ) {
+ HalpSetNVRamUchar(TopOfEnvironment + Count, Char);
+ }
+ }
+
+ } else {
+
+ //
+ // Variable is new.
+ //
+
+ //
+ // Determine if free area is large enough to handle new value, if not
+ // return error.
+ //
+
+ //
+ // From the length of free space subtract new variable's length,
+ // Value's length and 2 chars, one for the '=' sign and one of the
+ // null terminator.
+ //
+
+ Count -= ( strlen(Variable) + strlen(Value) + 2 );
+
+ //
+ // Check if there is space to fit the new variable.
+ //
+
+ if (Count < 0) {
+ return ENOSPC;
+ }
+
+ }
+
+ //
+ // If Value is not zero, append the new variable and value.
+ //
+
+ if (*Value != 0) {
+
+ //
+ // Write new variable, converting to upper case.
+ //
+ while ( *Variable != 0 ) {
+
+ Char = ((*Variable >= 'a') && (*Variable <= 'z') ?
+ (*Variable - 'a' + 'A') : *Variable);
+
+ HalpSetNVRamUchar(TopOfEnvironment, Char);
+
+ Variable ++;
+ TopOfEnvironment ++;
+ }
+
+ //
+ // Write equal sign.
+ //
+
+ Char = '=';
+ HalpSetNVRamUchar(TopOfEnvironment++, Char);
+
+ //
+ // Write new value.
+ //
+
+ for ( Count = 0; Value[Count] != 0; Count ++ )
+ ;
+
+ HalpMoveMemoryToNVRam(TopOfEnvironment, Value, Count);
+
+ }
+
+ //
+ // Write the environment variables out to NVRAM and checksum it.
+ //
+
+ if (HalpSynchronizeNVRamRegion0(TRUE)) {
+ return ESUCCESS;
+ } else {
+ return EIO;
+ }
+}
+
+#endif // TAGGED_NVRAM
diff --git a/private/ntos/nthals/halalpha/nvram.c b/private/ntos/nthals/halalpha/nvram.c
new file mode 100644
index 000000000..7bb392148
--- /dev/null
+++ b/private/ntos/nthals/halalpha/nvram.c
@@ -0,0 +1,1452 @@
+/*++
+
+Copyright (c) 1994, 1995 Digital Equipment Corporation
+
+Module Name:
+
+ nvram.c
+
+Abstract:
+
+ This module implements the new non-volatile RAM API. The new API
+ supports a cache interface and is layered on top of the old
+ Halp*NVRamBuffer() abstraction.
+
+Author:
+
+ Dave Richards 12-Jan-1995
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+--*/
+
+#include "arccodes.h"
+#include "halp.h"
+#include "nvram.h"
+
+//
+// Global data structures.
+//
+
+BOOLEAN HalpNVRamCacheIsValid = FALSE;
+BOOLEAN HalpNVRamRegion0IsValid;
+BOOLEAN HalpNVRamRegion1IsValid;
+UCHAR HalpNVRamCache[NVR_LENGTH];
+BOOLEAN HalpNVRamCacheIsDirty;
+ULONG HalpNVRamCacheDirtyLo = NVR_LENGTH - 1;
+ULONG HalpNVRamCacheDirtyHi = 0;
+
+BOOLEAN
+HalpIsNVRamCacheValid(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function fills the NVRAM cache (if the current contents are
+ not valid).
+
+ This function should not be called outside this module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the cache represents the contents
+ of NVRAM.
+
+--*/
+{
+ ARC_STATUS Status;
+
+ //
+ // If the NVRAM cache is valid, return success.
+ //
+
+ if (HalpNVRamCacheIsValid) {
+ return TRUE;
+ }
+
+ //
+ // Read the NVRAM contents into the cache.
+ //
+
+ Status = HalpReadNVRamBuffer(
+ HalpNVRamCache,
+ HalpCMOSRamBase,
+ NVR_LENGTH
+ );
+
+ //
+ // If we were unable to fill the cache, return failure.
+ //
+
+ if (Status != ESUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // The cache is valid.
+ //
+
+ HalpNVRamCacheIsValid = TRUE;
+
+ //
+ // The cache is clean.
+ //
+
+ HalpNVRamCacheIsDirty = FALSE;
+ HalpNVRamCacheDirtyLo = NVR_LENGTH - 1;
+ HalpNVRamCacheDirtyHi = 0;
+
+ //
+ // The validity of regions 0 and 1 is not known.
+ //
+
+ HalpNVRamRegion0IsValid = FALSE;
+ HalpNVRamRegion1IsValid = FALSE;
+
+ //
+ // Return success.
+ //
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpSynchronizeNVRamCache(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the cache to NVRAM.
+
+ This function should not be called outside this module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the contents of the NVRAM cache
+ were written to NVRAM.
+
+--*/
+{
+ ULONG Lo;
+ ULONG Hi;
+ ARC_STATUS Status;
+
+ //
+ // If the cache is clean, return success.
+ //
+
+ if (!HalpNVRamCacheIsDirty) {
+ return TRUE;
+ }
+
+ //
+ // Write the dirty portion of the cache back to NVRAM.
+ //
+
+ Lo = HalpNVRamCacheDirtyLo;
+ Hi = HalpNVRamCacheDirtyHi;
+
+ Status = HalpWriteNVRamBuffer(
+ (UCHAR *)HalpCMOSRamBase + Lo,
+ &HalpNVRamCache[Lo],
+ Hi - Lo + 1
+ );
+
+ //
+ // If we were unable to flush the cache, return failure.
+ //
+
+ if (Status != ESUCCESS) {
+
+ //
+ // The cache and NVRAM are no longer synchronized!
+ //
+
+ HalpNVRamCacheIsValid = FALSE;
+
+ return FALSE;
+ }
+
+ //
+ // The cache is valid.
+ //
+
+ HalpNVRamCacheIsValid = TRUE;
+
+ //
+ // The cache is clean.
+ //
+
+ HalpNVRamCacheIsDirty = FALSE;
+ HalpNVRamCacheDirtyLo = NVR_LENGTH - 1;
+ HalpNVRamCacheDirtyHi = 0;
+
+ //
+ // Return success.
+ //
+
+ return TRUE;
+}
+
+VOID
+HalpMarkNVRamCacheDirty(
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function marks the NVRAM cache region between Offset and
+ Offset + Length - 1 as dirty.
+
+ This function should not be called outside this module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Lo;
+ ULONG Hi;
+
+ //
+ // Compute the new lower and upper bounds.
+ //
+
+ Lo = Offset;
+ Hi = Offset + Length - 1;
+
+ if (Lo < HalpNVRamCacheDirtyLo) {
+ HalpNVRamCacheDirtyLo = Lo;
+ }
+
+ if (Hi > HalpNVRamCacheDirtyHi) {
+ HalpNVRamCacheDirtyHi = Hi;
+ }
+
+ //
+ // The cache is dirty.
+ //
+
+ HalpNVRamCacheIsDirty = TRUE;
+}
+
+UCHAR
+HalpGetNVRamUchar(
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This function reads a byte from the NVRAM cache.
+
+Arguments:
+
+ The offset in NVRAM.
+
+Return Value:
+
+ The byte read from the NVRAM cache.
+
+--*/
+{
+ //
+ // Read a byte.
+ //
+
+ return HalpNVRamCache[Offset];
+}
+
+VOID
+HalpSetNVRamUchar(
+ IN ULONG Offset,
+ IN UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This function writes a byte to the NVRAM cache.
+
+Arguments:
+
+ Offset - The offset in NVRAM.
+
+ Data - The byte written.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Write a byte.
+ //
+
+ HalpNVRamCache[Offset] = Data;
+
+ //
+ // Mark the cache as dirty.
+ //
+
+ HalpMarkNVRamCacheDirty(Offset, sizeof (UCHAR));
+}
+
+USHORT
+HalpGetNVRamUshort(
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This function reads a word from the NVRAM cache.
+
+Arguments:
+
+ The offset in NVRAM.
+
+Return Value:
+
+ The word read from the NVRAM cache.
+
+--*/
+{
+ USHORT Data;
+
+ //
+ // Read a short.
+ //
+
+ RtlMoveMemory(&Data, &HalpNVRamCache[Offset], sizeof (USHORT));
+
+ return Data;
+}
+
+VOID
+HalpSetNVRamUshort(
+ IN ULONG Offset,
+ IN USHORT Data
+ )
+/*++
+
+Routine Description:
+
+ This function writes a word to the NVRAM cache.
+
+Arguments:
+
+ Offset - The offset in NVRAM.
+
+ Data - The word written.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Write a short.
+ //
+
+ RtlMoveMemory(&HalpNVRamCache[Offset], &Data, sizeof (USHORT));
+
+ //
+ // Mark the cache as dirty.
+ //
+
+ HalpMarkNVRamCacheDirty(Offset, sizeof (USHORT));
+}
+
+ULONG
+HalpGetNVRamUlong(
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This function reads a longword from the NVRAM cache.
+
+Arguments:
+
+ The offset in NVRAM.
+
+Return Value:
+
+ The longword read from the NVRAM cache.
+
+--*/
+{
+ ULONG Data;
+
+ //
+ // Read a long.
+ //
+
+ RtlMoveMemory(&Data, &HalpNVRamCache[Offset], sizeof (ULONG));
+
+ return Data;
+}
+
+VOID
+HalpSetNVRamUlong(
+ IN ULONG Offset,
+ IN ULONG Data
+ )
+/*++
+
+Routine Description:
+
+ This function writes a longword to the NVRAM cache.
+
+Arguments:
+
+ Offset - The offset in NVRAM.
+
+ Data - The longword written.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Write a long.
+ //
+
+ RtlMoveMemory(&HalpNVRamCache[Offset], &Data, sizeof (ULONG));
+
+ //
+ // Mark the cache as dirty.
+ //
+
+ HalpMarkNVRamCacheDirty(Offset, sizeof (ULONG));
+}
+
+VOID
+HalpMoveMemoryToNVRam(
+ IN ULONG Offset,
+ IN PVOID Data,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function copies a region of memory to the NVRAM cache.
+
+Arguments:
+
+ Offset - The offset in NVRAM (destination).
+
+ Data - A memory pointer (source).
+
+ Length - The length of the region to copy.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Move memory to the NVRAM cache.
+ //
+
+ RtlMoveMemory(&HalpNVRamCache[Offset], Data, Length);
+
+ //
+ // Mark the cache as dirty.
+ //
+
+ HalpMarkNVRamCacheDirty(Offset, Length);
+}
+
+VOID
+HalpMoveNVRamToMemory(
+ IN PVOID Data,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function copies a portion of the NVRAM cache to memory.
+
+Arguments:
+
+ Data - A memory pointer (destination).
+
+ Offset - The offset in NVRAM (source).
+
+ Length - The length of the region to copy.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Move memory from the NVRAM cache.
+ //
+
+ RtlMoveMemory(Data, &HalpNVRamCache[Offset], Length);
+}
+
+VOID
+HalpMoveNVRamToNVRam(
+ IN ULONG Destination,
+ IN ULONG Source,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function copies a one region of the NVRAM cache to another.
+
+Arguments:
+
+ Destination - An offset in NVRAM.
+
+ Source - An offset in NVRAM.
+
+ Length - The length of the region to copy.
+
+Return Value:
+
+--*/
+{
+ //
+ // Move memory within the NVRAM cache.
+ //
+
+ RtlMoveMemory(
+ &HalpNVRamCache[Destination],
+ &HalpNVRamCache[Source],
+ Length
+ );
+
+ //
+ // Mark the cache as dirty.
+ //
+
+ HalpMarkNVRamCacheDirty(Destination, Length);
+}
+
+ULONG
+HalpGetNVRamStringLength(
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This function returns the length of a '\0'-terminated string in
+ the NVRAM cache.
+
+Arguments:
+
+ Offset - A pointer to the beginning of the string in NVRAM.
+
+Return Value:
+
+ An integer value representing the length of the string.
+
+--*/
+{
+ //
+ // Return the length of a string in the NVRAM cache.
+ //
+
+ return strlen(&HalpNVRamCache[Offset]);
+}
+
+VOID
+HalpMoveMemoryStringToNVRam(
+ IN ULONG Offset,
+ IN PCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This function copies a string to the NVRAM cache.
+
+Arguments:
+
+ Offset - The offset in NVRAM.
+
+ Data - A pointer to the beginning of the string in memory.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Length;
+
+ //
+ // Compute the length of the string.
+ //
+
+ Length = strlen(Data);
+
+ //
+ // Move string to NVRAM.
+ //
+
+ HalpMoveMemoryToNVRam(Offset, Data, Length + 1);
+}
+
+VOID
+HalpMoveNVRamStringToMemory(
+ IN PUCHAR Data,
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This function copies a string from the NVRAM cache to memory.
+
+Arguments:
+
+ Data - A pointer in memory.
+
+ Offset - An offset in NVRAM to the string to copy.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Length;
+
+ //
+ // Compute the length of the string.
+ //
+
+ Length = HalpGetNVRamStringLength(Offset);
+
+ //
+ // Move string to memory.
+ //
+
+ HalpMoveNVRamToMemory(Data, Offset, Length + 1);
+}
+
+VOID
+HalpZeroNVRam(
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function zeroes the contents of a region in the NVRAM cache.
+
+Arguments:
+
+ Offset - The offset in NVRAM of the region to zero.
+
+ Length - The length of the region to zero.
+
+Return Value:
+
+--*/
+{
+ //
+ // Zero the NVRAM cache.
+ //
+
+ RtlZeroMemory(&HalpNVRamCache[Offset], Length);
+
+ //
+ // Mark the cache as dirty.
+ //
+
+ HalpMarkNVRamCacheDirty(Offset, Length);
+}
+
+ULONG
+HalpComputeNVRamChecksum(
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function computes the checksum for a region in the NVRAM cache.
+
+Arguments:
+
+ Offset - An offset in NVRAM.
+
+ Length - The length of the region to checksum.
+
+Return Value:
+
+ The 32-bit checksum of the region.
+
+--*/
+{
+ ULONG Checksum;
+ ULONG Index;
+
+ //
+ // Compute the checksum.
+ //
+
+ Checksum = 0;
+
+ for (Index = 0; Index < Length; Index++) {
+ Checksum = (Checksum << 1) + HalpGetNVRamUchar(Offset++) +
+ (Checksum >> 31 & 0x1);
+ }
+
+ return ~Checksum;
+}
+
+BOOLEAN
+HalpIsNVRamRegion0Valid(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function fills the NVRAM cache (if necessary) and ascertains
+ whether the contents of region 0 of the NVRAM are valid. It verifies
+ that the signature, version and checksum are valid.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the contents of the region are valid.
+
+--*/
+{
+ ULONG Signature;
+ UCHAR Version;
+ ULONG Checksum1;
+ ULONG Checksum2;
+
+ //
+ // If the contents of the NVRAM cache are invalid, return failure.
+ //
+
+ if (!HalpIsNVRamCacheValid()) {
+ return FALSE;
+ }
+
+ //
+ // If region 0 is valid, return success.
+ //
+
+ if (HalpNVRamRegion0IsValid) {
+ return TRUE;
+ }
+
+ //
+ // If the signature is invalid, return failure.
+ //
+
+ Signature = HalpGetNVRamUlong(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Signature)
+ );
+
+ if (Signature != NVR_REGION0_SIGNATURE) {
+ return FALSE;
+ }
+
+ //
+ // If the version is invalid, return failure.
+ //
+
+ Version = HalpGetNVRamUchar(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Version)
+ );
+
+ if (Version == 0) {
+ return FALSE;
+ }
+
+ //
+ // If the checksum is invalid, return failure.
+ //
+
+ Checksum1 = HalpComputeNVRamChecksum(
+ NVR_REGION0_OFFSET,
+ FIELD_OFFSET(NVR_REGION0, Checksum)
+ );
+
+ Checksum2 = HalpGetNVRamUlong(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Checksum)
+ );
+
+ if (Checksum1 != Checksum2) {
+ return FALSE;
+ }
+
+ //
+ // Region 0 is valid.
+ //
+
+ HalpNVRamRegion0IsValid = TRUE;
+
+ //
+ // Return success.
+ //
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpSynchronizeNVRamRegion0(
+ IN BOOLEAN RecomputeChecksum
+ )
+/*++
+
+Routine Description:
+
+ This function writes the contents of the NVRAM cache region 0
+ back to NVRAM and optionally updates the checksum field.
+
+Arguments:
+
+ RecomputeChecksum - Update the checksum?
+
+Return Value:
+
+ A boolean value indicating whether the NVRAM was correctly updated.
+
+--*/
+{
+ ULONG Checksum;
+
+ //
+ // If we are unable to synchronize the NVRAM cache, return failure.
+ //
+
+ if (!HalpSynchronizeNVRamCache()) {
+ return FALSE;
+ }
+
+ //
+ // If we do not need to re-compute the checksum, return success.
+ //
+
+ if (!RecomputeChecksum) {
+ return TRUE;
+ }
+
+ //
+ // Re-compute the checksum and store it in NVRAM.
+ //
+
+ Checksum = HalpComputeNVRamChecksum(
+ NVR_REGION0_OFFSET,
+ FIELD_OFFSET(NVR_REGION0, Checksum)
+ );
+
+ HalpSetNVRamUlong(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Checksum),
+ Checksum
+ );
+
+ //
+ // Synchronize the NVRAM cache.
+ //
+
+ return HalpSynchronizeNVRamCache();
+}
+
+BOOLEAN
+HalpInitializeNVRamRegion0(
+ BOOLEAN Synchronize
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the contents of region 0.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the NVRAM was properly initialized.
+
+--*/
+{
+ ULONG Checksum;
+
+ //
+ // Zero the contents of region 0.
+ //
+
+ HalpZeroNVRam(NVR_REGION0_OFFSET, NVR_REGION0_LENGTH);
+
+ //
+ // Initialize the signature.
+ //
+
+ HalpSetNVRamUlong(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Signature),
+ NVR_REGION0_SIGNATURE
+ );
+
+ //
+ // Initialize the version.
+ //
+
+ HalpSetNVRamUchar(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Version),
+ NVR_REGION0_VERSION
+ );
+
+ //
+ // Initialize the directory.
+ //
+
+ HalpSetNVRamUchar(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, DirectoryEntries),
+ NVR_REGION0_DIR_SIZE
+ );
+
+ HalpSetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Directory[NVR_REGION0_DIR_FW_CONFIG]),
+ (USHORT)FIELD_OFFSET(NVR_REGION0, Opaque[0])
+ );
+
+ HalpSetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Directory[NVR_REGION0_DIR_LANGUAGE]),
+ FIELD_OFFSET(NVR_REGION0, Opaque[0]) +
+ NVR_FW_CONFIG_LENGTH
+ );
+
+ HalpSetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Directory[NVR_REGION0_DIR_ENVIRONMENT]),
+ FIELD_OFFSET(NVR_REGION0, Opaque[0]) +
+ NVR_FW_CONFIG_LENGTH +
+ NVR_LANGUAGE_LENGTH
+ );
+
+ HalpSetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Directory[NVR_REGION0_DIR_END]),
+ FIELD_OFFSET(NVR_REGION0, Checksum)
+ );
+
+ //
+ // Re-compute the checksum and store it in NVRAM.
+ //
+
+ Checksum = HalpComputeNVRamChecksum(
+ NVR_REGION0_OFFSET,
+ FIELD_OFFSET(NVR_REGION0, Checksum)
+ );
+
+ HalpSetNVRamUlong(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0, Checksum),
+ Checksum
+ );
+
+ //
+ // Synchronize the cache and NVRAM.
+ //
+
+ if (Synchronize) {
+ return HalpSynchronizeNVRamRegion0(TRUE);
+ }
+}
+
+ULONG
+HalpGetNVRamFwConfigOffset(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function returns the NVRAM offset of the firmware configuration
+ section in NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The offset in NVRAM of the firmware configuration section.
+
+--*/
+{
+ //
+ // Return the firmware configuration offset.
+ //
+
+ return HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_FW_CONFIG])
+ );
+}
+
+ULONG
+HalpGetNVRamFwConfigLength(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function returns the length of the firmware configuration
+ section of NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The length of the firmware configuration section.
+
+--*/
+{
+ //
+ // Return the firmware configuration length.
+ //
+
+ return HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_FW_CONFIG + 1])
+ ) -
+ HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_FW_CONFIG])
+ );
+}
+
+ULONG
+HalpGetNVRamLanguageOffset(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function returns the NVRAM offset of the language section.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The NVRAM offset of the language section.
+
+--*/
+{
+ //
+ // Return the language offset.
+ //
+
+ return HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_LANGUAGE])
+ );
+}
+
+ULONG
+HalpGetNVRamLanguageLength(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function returns the length of the language section in NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The length of the language section.
+
+--*/
+{
+ //
+ // Return the language length.
+ //
+
+ return HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_LANGUAGE + 1])
+ ) -
+ HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_LANGUAGE])
+ );
+}
+
+ULONG
+HalpGetNVRamEnvironmentOffset(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function returns the NVRAM offset of the environment section.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The NVRAM offset of the environment section.
+
+--*/
+{
+ //
+ // Return the environment offset;
+ //
+
+ return HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_ENVIRONMENT])
+ );
+}
+
+ULONG
+HalpGetNVRamEnvironmentLength(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function returns the length of the environment section.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The length of the environment section in NVRAM.
+
+--*/
+{
+ //
+ // Return the environment length.
+ //
+
+ return HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_ENVIRONMENT + 1])
+ ) -
+ HalpGetNVRamUshort(
+ NVR_REGION0_OFFSET +
+ FIELD_OFFSET(NVR_REGION0,
+ Directory[NVR_REGION0_DIR_ENVIRONMENT])
+ );
+}
+
+#if defined(EISA_PLATFORM)
+
+BOOLEAN
+HalpIsNVRamRegion1Valid(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function fills the NVRAM cache (if necessary) and ascertains
+ whether the contents of region 1 of the NVRAM are valid. It verifies
+ that the signature, version and checksum are valid.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the contents of the region are valid.
+
+--*/
+{
+ ULONG Signature;
+ UCHAR Version;
+ ULONG Checksum1;
+ ULONG Checksum2;
+
+ //
+ // If the contents of the NVRAM cache are invalid, return failure.
+ //
+
+ if (!HalpIsNVRamCacheValid()) {
+ return FALSE;
+ }
+
+ //
+ // If region 1 is valid, return success.
+ //
+
+ if (HalpNVRamRegion1IsValid) {
+ return TRUE;
+ }
+
+ //
+ // If the signature is invalid, return failure.
+ //
+
+ Signature = HalpGetNVRamUlong(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Signature)
+ );
+
+ if (Signature != NVR_REGION1_SIGNATURE) {
+ return FALSE;
+ }
+
+ //
+ // If the version is invalid, return failure.
+ //
+
+ Version = HalpGetNVRamUchar(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Version)
+ );
+
+ if (Version == 0) {
+ return FALSE;
+ }
+
+ //
+ // If the checksum is invalid, return failure.
+ //
+
+ Checksum1 = HalpComputeNVRamChecksum(
+ NVR_REGION1_OFFSET,
+ FIELD_OFFSET(NVR_REGION1, Checksum)
+ );
+
+ Checksum2 = HalpGetNVRamUlong(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Checksum)
+ );
+
+ if (Checksum1 != Checksum2) {
+ return FALSE;
+ }
+
+ //
+ // Region 1 is valid.
+ //
+
+ HalpNVRamRegion1IsValid = TRUE;
+
+ //
+ // Return success.
+ //
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpSynchronizeNVRamRegion1(
+ IN BOOLEAN RecomputeChecksum
+ )
+/*++
+
+Routine Description:
+
+ This function writes the contents of the NVRAM cache region 1
+ back to NVRAM and optionally updates the checksum field.
+
+Arguments:
+
+ RecomputeChecksum - Update the checksum?
+
+Return Value:
+
+ A boolean value indicating whether the NVRAM was correctly updated.
+
+--*/
+{
+ ULONG Checksum;
+
+ //
+ // If we are unable to synchronize the NVRAM cache, return failure.
+ //
+
+ if (!HalpSynchronizeNVRamCache()) {
+ return FALSE;
+ }
+
+ //
+ // If we do not need to re-compute the checksum, return success.
+ //
+
+ if (!RecomputeChecksum) {
+ return TRUE;
+ }
+
+ //
+ // Re-compute the checksum and store it in NVRAM.
+ //
+
+ Checksum = HalpComputeNVRamChecksum(
+ NVR_REGION1_OFFSET,
+ FIELD_OFFSET(NVR_REGION1, Checksum)
+ );
+
+ HalpSetNVRamUlong(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Checksum),
+ Checksum
+ );
+
+ //
+ // Synchronize the NVRAM cache.
+ //
+
+ return HalpSynchronizeNVRamCache();
+}
+
+BOOLEAN
+HalpInitializeNVRamRegion1(
+ BOOLEAN Synchronize
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the contents of region 1.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the NVRAM was properly initialized.
+
+--*/
+{
+ ULONG Checksum;
+
+ //
+ // Zero the contents of region 1.
+ //
+
+ HalpZeroNVRam(NVR_REGION1_OFFSET, NVR_REGION1_LENGTH);
+
+ //
+ // Initialize the signature.
+ //
+
+ HalpSetNVRamUlong(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Signature),
+ NVR_REGION1_SIGNATURE
+ );
+
+ //
+ // Initialize the version.
+ //
+
+ HalpSetNVRamUchar(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Version),
+ NVR_REGION1_VERSION
+ );
+
+ //
+ // Re-compute the checksum and store it in NVRAM.
+ //
+
+ Checksum = HalpComputeNVRamChecksum(
+ NVR_REGION1_OFFSET,
+ FIELD_OFFSET(NVR_REGION1, Checksum)
+ );
+
+ HalpSetNVRamUlong(
+ NVR_REGION1_OFFSET +
+ FIELD_OFFSET(NVR_REGION1, Checksum),
+ Checksum
+ );
+
+ //
+ // Synchronize the cache and NVRAM.
+ //
+
+ if (Synchronize) {
+ return HalpSynchronizeNVRamRegion1(TRUE);
+ }
+}
+
+#endif // EISA_PLATFORM
diff --git a/private/ntos/nthals/halalpha/nvram.h b/private/ntos/nthals/halalpha/nvram.h
new file mode 100644
index 000000000..6126a4b38
--- /dev/null
+++ b/private/ntos/nthals/halalpha/nvram.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 1994, 1995 Digital Equipment Corporation
+
+Module Name:
+
+ nvram.h
+
+Abstract:
+
+ This module declares the NVRAM data structures.
+
+Author:
+
+ Dave Richards 12-Jan-1995
+
+Revision History:
+
+--*/
+
+#ifndef _NVRAM_H_
+#define _NVRAM_H_
+
+//
+// NVRAM Region 0 definitions.
+//
+
+#define NVR_REGION0_OFFSET FIELD_OFFSET(NVRAM, Region0)
+#define NVR_REGION0_LENGTH (3 * 1024)
+#define NVR_REGION0_SIGNATURE 0x06201993
+#define NVR_REGION0_VERSION 1
+
+//
+// NVRAM Region 0 Directory definitions.
+//
+
+#define NVR_REGION0_DIR_FW_CONFIG 0
+#define NVR_REGION0_DIR_LANGUAGE 1
+#define NVR_REGION0_DIR_ENVIRONMENT 2
+#define NVR_REGION0_DIR_END 3
+#define NVR_REGION0_DIR_SIZE 4
+
+//
+// NVRAM Region 0 structure.
+//
+
+#define NVR_REGION0_OPAQUE_LENGTH \
+ NVR_REGION0_LENGTH - \
+ (sizeof (ULONG) /* Signature */ + \
+ sizeof (UCHAR) /* Version */ + \
+ sizeof (UCHAR) /* DirectoryEntries */ + \
+ sizeof (USHORT) * NVR_REGION0_DIR_SIZE /* Directory */ + \
+ sizeof (ULONG)) /* Checksum */
+
+typedef struct {
+ ULONG Signature;
+ UCHAR Version;
+ UCHAR DirectoryEntries;
+ USHORT Directory[NVR_REGION0_DIR_SIZE];
+ UCHAR Opaque[NVR_REGION0_OPAQUE_LENGTH];
+ ULONG Checksum;
+} NVR_REGION0, *PNVR_REGION0;
+
+//
+// NVRAM Region 0 Section 0 structure. (Firmware configuration)
+//
+
+#define NVR_FW_CONFIG_LENGTH sizeof (NVR_FW_CONFIG)
+
+typedef struct {
+ ULONG Monitor;
+ ULONG Floppy;
+ ULONG Floppy2;
+ ULONG KeyboardType;
+} NVR_FW_CONFIG, *PNVR_FW_CONFIG;
+
+//
+// NVRAM Region 0 Section 1 structure. (Language configuration)
+//
+
+#define MAXIMUM_LANGUAGE_PATH 128
+#define NVR_LANGUAGE_LENGTH sizeof (NVR_LANGUAGE)
+
+typedef struct {
+ CHAR Path[MAXIMUM_LANGUAGE_PATH];
+ LONG Id;
+ LONG Source;
+ LONG Spare1;
+ LONG Spare2;
+} NVR_LANGUAGE, *PNVR_LANGUAGE;
+
+//
+// NVRAM Region 0 Section 2 definitions. (Environment)
+//
+
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+#define MAX_NUMBER_OF_ENVIRONMENT_VARIABLES 28
+
+//
+// NVRAM Region 1 definitions.
+//
+
+#define NVR_REGION1_OFFSET FIELD_OFFSET(NVRAM, Region1)
+#define NVR_REGION1_LENGTH (3 * 1024)
+#define NVR_REGION1_SIGNATURE 0x865D8546
+#define NVR_REGION1_VERSION 1
+
+//
+// EISA NVRAM Definitions
+//
+
+#if defined(EISA_PLATFORM)
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+//
+// Defines for the region 1 table sizes.
+//
+
+#define NV_NUMBER_OF_ENTRIES 33
+#define NV_LENGTH_OF_IDENTIFIER 496
+#define LENGTH_OF_EISA_DATA 2032
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ UCHAR Version;
+ UCHAR Revision;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+#endif // EISA_PLATFORM
+
+//
+// Region 1 structure.
+//
+
+typedef struct {
+
+#if defined(EISA_PLATFORM)
+
+ //
+ // EISA configuration information.
+ //
+
+ ULONG Signature;
+ UCHAR Version;
+ UCHAR CompressedPacketSize;
+ UCHAR IdentifierSize;
+ UCHAR EisaDataSize;
+ COMPRESSED_CONFIGURATION_PACKET
+ Packet[NV_NUMBER_OF_ENTRIES];
+ UCHAR Identifier[NV_LENGTH_OF_IDENTIFIER];
+ UCHAR EisaData[LENGTH_OF_EISA_DATA];
+ ULONG Spare;
+ ULONG Checksum;
+
+#else
+
+ //
+ // Reserved for the SRM Console.
+ //
+
+ UCHAR Opaque[NVR_REGION1_LENGTH];
+
+#endif
+
+} NVR_REGION1, *PNVR_REGION1;
+
+//
+// NVRAM Region 2 definitions.
+//
+
+#define NVR_REGION2_OFFSET FIELD_OFFSET(NVRAM, Region2)
+#define NVR_REGION2_LENGTH (2 * 1024)
+
+//
+// NVRAM Region 2 structure.
+//
+
+typedef struct {
+ UCHAR Opaque[NVR_REGION2_LENGTH];
+} NVR_REGION2, *PNVR_REGION2;
+
+//
+// NVRAM definitions.
+//
+
+#define NVR_LENGTH sizeof (NVRAM)
+
+//
+// NVRAM structure.
+//
+
+typedef struct {
+ NVR_REGION0 Region0;
+ NVR_REGION1 Region1;
+ NVR_REGION2 Region2;
+} NVRAM, *PNVRAM;
+
+#endif
diff --git a/private/ntos/nthals/halalpha/pciesc.c b/private/ntos/nthals/halalpha/pciesc.c
new file mode 100644
index 000000000..9a54e38ec
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pciesc.c
@@ -0,0 +1,477 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pciesc.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI ESC's
+ cascaded 82c59 programmable interrupt controllers.
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from pcisio.c module for Intel 82374EB (ESC).
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Import save area for ESC interrupt mask registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+BOOLEAN
+HalpInitializeEisaInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 82c59 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must be initialized with 4
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word sets the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0, which is the default
+ // edge-sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ return (TRUE);
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is for controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2; it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+ }
+ }
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second-level
+ interrupt dispatch routine and acknowledge the interrupt at the ESC
+ controller.
+
+ This service routine could be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, ISA_LEVEL, ISA_LEVEL, ISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR EISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ EISAVector = HalpAcknowledgeEisaInterrupt(ServiceContext);
+
+
+ if ((EISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return FALSE; // ecrfix - now returns a value
+
+ }
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = EISAVector + EISA_VECTORS;
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset],
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the ESC interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (EISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+}
diff --git a/private/ntos/nthals/halalpha/pcip.h b/private/ntos/nthals/halalpha/pcip.h
new file mode 100644
index 000000000..8cd3f6cc4
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcip.h
@@ -0,0 +1,178 @@
+/*++ BUILD Version: 0000 Increment this if a change has global effects
+
+Copyright (c) 1994 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pcip.h
+
+Abstract:
+
+ This header file defines the private PCI bus HAL interfaces and
+ data types.
+
+Author:
+
+ Eric Rehm (rehm) 14-August-1994
+
+Revision History:
+
+ 14-Jul-1994 (rehm)
+ Original
+
+ 5-Dec-1994 (rehm)
+ Added DevicePresent bitmap and PlatformSpecificData pointer to PCIBUSDATA
+ data type.
+
+--*/
+
+#ifndef _PCIPH_
+#define _PCIPH_
+
+//
+// Hal specific PCI bus structures
+//
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define PCI_MAX_BUSSES 256
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev)
+
+//
+// Define PCI configuration cycle types.
+//
+typedef enum _PCI_CONFIGURATION_TYPES {
+ PciConfigTypeInvalid = -1,
+ PciConfigType0 = 0,
+ PciConfigType1 = 1
+} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES;
+
+typedef struct _PCI_CFG_CYCLE_BITS {
+ union {
+ struct {
+ ULONG Reserved1:2;
+ ULONG Reserved2:30;
+ } bits; // Generic Config Cycle
+
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG Idsel:21;
+ } bits0; // Type0 Config Cycle
+
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG DeviceNumber:5;
+ ULONG BusNumber:8;
+ ULONG Reserved2:7;
+ ULONG Enable:1;
+ } bits1; // Type 1 Config Cycle
+
+ ULONG AsULONG;
+ } u;
+} PCI_CFG_CYCLE_BITS, *PPCI_CFG_CYCLE_BITS;
+
+//
+// Define PCI cycle/command types.
+//
+
+typedef enum _PCI_COMMAND_TYPES{
+ PciCommandInterruptAcknowledge = 0x0,
+ PciCommandSpecialCycle = 0x1,
+ PciCommandIoRead = 0x2,
+ PciCommandIoWrite = 0x3,
+ PciCommandMemoryRead = 0x6,
+ PciCommandMemoryWrite = 0x7,
+ PciCommandConfigurationRead = 0xa,
+ PciCommandConfigurationWrite = 0xb,
+ PciCommandMemoryReadMultiple = 0xc,
+ PciCommandDualAddressCycle = 0xd,
+ PciCommandMemoryReadLine = 0xe,
+ PciCommandMemoryWriteAndInvalidate = 0xf,
+ MaximumPciCommand
+} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES;
+
+//
+// PCI platform-specific functions
+//
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ );
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ );
+
+
+//
+// Define PCI configuration cycle types.
+//
+
+typedef enum _PCI_TYPE0_CONFIG_TYPE {
+ PciConfigType0AsIdsel,
+ PciConfigType0AsDeviceNumber
+} PCI_TYPE0_CONFIG_TYPE, *PPCI_TYPE0_CONFIG_TYPE;
+
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // NT Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Common alpha hal specific data
+ //
+
+ PVOID ConfigBaseQva;
+ PCI_TYPE0_CONFIG_TYPE PciType0ConfigType;
+ ULONG HwBusNumber;
+ BOOLEAN BusIsAcrossPPB;
+
+ RTL_BITMAP DevicePresent;
+ ULONG DevicePresentBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+
+ ULONG MaxDevice;
+
+ ULONG PPBBusNumber;
+ PCI_SLOT_NUMBER PPBSlotNumber;
+
+ //
+ // Platform-specific storage
+ //
+
+ PVOID PlatformSpecificData;
+
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+//
+// The following structure is used to communicate PCI bus information
+// between the ARC firmware and HAL. This structure is passed as
+// configuration information on the PCI multifunction adapter nodes of the
+// ARC configuration tree.
+//
+
+typedef struct _ARC_PCI_CONFIGURATION {
+ ULONG Version;
+ ULONG BusNumber;
+ ULONG HwBusNumber;
+ BOOLEAN BusIsAcrossPPB;
+ ULONG DevicePresentBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} ARC_PCI_CONFIGURATION, *PARC_PCI_CONFIGURATION;
+
+#define ARC_PCI_CONFIGURATION_VERSION 1
+
+#endif // _PCIPH_
diff --git a/private/ntos/nthals/halalpha/pcisio.c b/private/ntos/nthals/halalpha/pcisio.c
new file mode 100644
index 000000000..76021c879
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcisio.c
@@ -0,0 +1,483 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pic8259.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI SIO
+ programmable interrupt controller.
+
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Import save area for SIO interrupt mask registers.
+//
+
+UCHAR HalpSioInterrupt1Mask;
+UCHAR HalpSioInterrupt2Mask;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+
+VOID
+HalpInitializeSioInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 8259 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ return;
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO bus specified SIO bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2, it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+ }
+
+ }
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO bus specified SIO bus interrupt.
+Arguments:
+
+ Vector - Supplies the vector of the SIO interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to an interrupt object that
+ describes the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR ISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase);
+
+
+ if ((ISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return FALSE; // ecrfix - now returns a value
+
+ }
+
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = ISAVector + ISA_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (ISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+}
+
+
diff --git a/private/ntos/nthals/halalpha/pcisup.c b/private/ntos/nthals/halalpha/pcisup.c
new file mode 100644
index 000000000..34147cc91
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcisup.c
@@ -0,0 +1,2453 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ Platform-independent PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+typedef ULONG (*FncConfigIO) (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef struct {
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} CONFIG_HANDLER, *PCONFIG_HANDLER;
+
+
+//
+// Define PCI slot validity
+//
+typedef enum _VALID_SLOT {
+ InvalidBus = 0,
+ InvalidSlot,
+ ValidSlot
+} VALID_SLOT;
+
+//
+// Local prototypes for routines supporting PCI bus handler routines
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+ULONG HalpPCIReadUlong (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUchar (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshort (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlong (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUchar (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshort (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpPCILine2PinNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+VOID
+HalpPCIPin2LineNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+#if DBG
+BOOLEAN
+HalpValidPCIAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PHYSICAL_ADDRESS BAddr,
+ IN ULONG Length,
+ IN ULONG AddressSpace
+ );
+#endif
+
+//
+// Local prototypes of functions that are not built for Alpha AXP firmware
+//
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+#if DBG
+VOID
+HalpTestPci (
+ ULONG
+ );
+#endif
+
+//
+// Pragmas to assign functions to different kinds of pages.
+//
+
+#if !defined(AXP_FIRMWARE)
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePCIBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPCIBusHandler)
+#pragma alloc_text(INIT,HalpRegisterPCIInstallHandler )
+#pragma alloc_text(INIT,HalpDefaultPCIInstallHandler )
+#pragma alloc_text(INIT,HalpDeterminePCIDevicesPresent )
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif // ALLOC_PRAGMA
+#endif // !defined(AXP_FIRMWARE)
+
+#ifdef AXP_FIRMWARE
+
+#define ExFreePool(PoolData)
+
+#pragma alloc_text(DISTEXT, HalpInitializePCIBus )
+#pragma alloc_text(DISTEXT, HalpAllocateAndInitPCIBusHandler)
+#pragma alloc_text(DISTEXT, HalpRegisterPCIInstallHandler )
+#pragma alloc_text(DISTEXT, HalpDefaultPCIInstallHandler )
+#pragma alloc_text(DISTEXT, HalpDeterminePCIDevicesPresent )
+#pragma alloc_text(DISTEXT, HalpGetPCIData )
+#pragma alloc_text(DISTEXT, HalpSetPCIData )
+#pragma alloc_text(DISTEXT, HalpReadPCIConfig )
+#pragma alloc_text(DISTEXT, HalpWritePCIConfig )
+#pragma alloc_text(DISTEXT, HalpValidPCISlot )
+#if DBG
+#pragma alloc_text(DISTEXT, HalpValidPCIAddr )
+#endif
+#pragma alloc_text(DISTEXT, HalpPCIConfig )
+#pragma alloc_text(DISTEXT, HalpPCIReadUchar )
+#pragma alloc_text(DISTEXT, HalpPCIReadUshort )
+#pragma alloc_text(DISTEXT, HalpPCIReadUlong )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUchar )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUshort )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUlong )
+#pragma alloc_text(DISTEXT, HalpAssignPCISlotResources)
+#pragma alloc_text(DISTEXT, HalpAdjustPCIResourceList)
+
+#endif // AXP_FIRMWARE
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+BOOLEAN PCIInitialized = FALSE;
+ULONG PCIMaxLocalDevice;
+ULONG PCIMaxDevice;
+ULONG PCIMaxBus;
+PINSTALL_BUS_HANDLER PCIInstallHandler = HalpDefaultPCIInstallHandler;
+
+CONFIG_HANDLER PCIConfigHandlers = {
+ {
+ HalpPCIReadUlong, // 0
+ HalpPCIReadUchar, // 1
+ HalpPCIReadUshort // 2
+ },
+ {
+ HalpPCIWriteUlong, // 0
+ HalpPCIWriteUchar, // 1
+ HalpPCIWriteUshort // 2
+ }
+};
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+#if !defined(AXP_FIRMWARE)
+
+VOID
+HalpRegisterPciBus(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PVOID ConfigurationData
+ )
+/*++
+
+Routine Description:
+
+ This function uses information obtained from the ARC configuration
+ tree to create PCI bus handlers. If configuration data was passed
+ with the PCI component, then that information is used to create the
+ bus handler. Otherwise, we use a priori knowledge (and bus scanning)
+ to generate the bus handler data. This function supports firmware
+ that both provide and do not provide configuration data payloads.
+
+Arguments:
+
+ Component - The ARC configuration component for this bus.
+
+ ConfigurationData - The configuration data payload (or NULL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ConfigurationDataPresent;
+ ARC_PCI_CONFIGURATION ArcPciConfiguration;
+ ULONG BusNumber;
+ ULONG HwBusNumber;
+ BOOLEAN BusIsAcrossPPB;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ RTL_BITMAP DevicePresent;
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ PCI_COMMON_CONFIG CommonConfig;
+ PCI_SLOT_NUMBER Dummy;
+
+ memset(&Dummy, 0, sizeof(PCI_SLOT_NUMBER) );
+
+ //
+ // Ascertain whether the ARC firmware provided configuration data as part
+ // of the multi-function adapter component.
+ //
+
+ ConfigurationDataPresent = Component->ConfigurationDataLength != 0;
+
+ //
+ // If configuration data was provided use it to allocate and initialize
+ // the handler for this bus. Otherwise, use a priori knowledge to
+ // generate reasonable values.
+ //
+
+ if (ConfigurationDataPresent) {
+
+ //
+ // Copy the configuration data from the component.
+ //
+
+ RtlCopyMemory(
+ &ArcPciConfiguration,
+ ConfigurationData,
+ sizeof (ARC_PCI_CONFIGURATION)
+ );
+
+ //
+ // Use the values provided.
+ //
+
+ BusNumber = ArcPciConfiguration.BusNumber;
+ HwBusNumber = ArcPciConfiguration.HwBusNumber;
+ BusIsAcrossPPB = ArcPciConfiguration.BusIsAcrossPPB;
+
+ //
+ // Despite its name, PCIMaxBus is really the number of busses present
+ // in the system.
+ //
+
+ if (PCIMaxBus < BusNumber + 1) {
+ PCIMaxBus = BusNumber + 1;
+ }
+
+ } else {
+
+ //
+ // PCIMaxBus keeps a running count of the number of busses seen up
+ // to this point. Use the current value as the bus number and advance
+ // the counter. Set HwBusNumber and BusIsAcrossPPB to reasonable
+ // values.
+ //
+
+ BusNumber = PCIMaxBus++;
+ HwBusNumber = 0;
+ BusIsAcrossPPB = BusNumber != 0;
+
+ }
+
+ //
+ // Allocate and initialize the handler for this bus. N.B. device-present
+ // checking is disabled at this point. We will enable it below.
+ //
+
+ BusHandler = HalpAllocateAndInitPCIBusHandler(
+ BusNumber,
+ HwBusNumber,
+ BusIsAcrossPPB,
+ 0, // MS here
+ Dummy // MS here
+ );
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Compute the device-present bitmap for this bus. If configuration
+ // data is present then the bitmap has been pre-computed for us by the
+ // firmware. In this case, use the bitmap provided. otherwise, we
+ // have to do the work now of generating the bitmap.
+ //
+
+ if (ConfigurationDataPresent) {
+
+ //
+ // Initialize the device-present bitmap for this bus.
+ //
+
+ RtlInitializeBitMap(
+ &BusData->DevicePresent,
+ BusData->DevicePresentBits,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ //
+ // The firmware has already computed the device-present bitmap for
+ // us. Copy the bitmap from the configuration data.
+ //
+
+ RtlCopyMemory(
+ BusData->DevicePresentBits,
+ ArcPciConfiguration.DevicePresentBits,
+ sizeof (BusData->DevicePresentBits)
+ );
+
+
+ } else {
+
+ //
+ // Initialize a bitmap which we will use to accumulate the results
+ // of the device-present scan. N.B. Device-present checking is
+ // currently disabled.
+ //
+
+ RtlInitializeBitMap(
+ &DevicePresent,
+ BusData->DevicePresentBits,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ RtlClearBits(
+ &DevicePresent,
+ 0,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ //
+ // Initialize the slot number.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+
+ //
+ // Loop through each device number.
+ //
+
+ for (DeviceNumber = 0;
+ DeviceNumber < PCI_MAX_DEVICES;
+ DeviceNumber++) {
+
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function number.
+ //
+
+ for (FunctionNumber = 0;
+ FunctionNumber < PCI_MAX_FUNCTION;
+ FunctionNumber++) {
+
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the common configuration header.
+ //
+
+ HalpReadPCIConfig(
+ BusHandler,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If the Vendor ID is invalid, then no device is present
+ // at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+ if (FunctionNumber == 0) {
+ break;
+ }
+ continue;
+ }
+
+ //
+ // Set a bit indicating a device is present.
+ //
+
+ RtlSetBits(
+ &DevicePresent,
+ PciBitIndex(DeviceNumber, FunctionNumber),
+ 1
+ );
+
+ //
+ // If this is not a multi-function device, then terminate
+ // the function number loop.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+ }
+ }
+
+ //
+ // Enable device-present checking.
+ //
+
+ BusData->DevicePresent = DevicePresent;
+ }
+}
+
+#endif
+
+#if !defined(AXP_FIRMWARE)
+
+VOID
+HalpQueryPciBusConfiguration(
+ IN PCONFIGURATION_COMPONENT_DATA Root
+ )
+/*++
+
+Routine Description:
+
+ This function loops through each multi-function adapter component
+ in the ARC configuration tree and calls HalpRegisterPciBus() to create
+ a bus handler for it.
+
+Arguments:
+
+ Root - The root of the ARC configuration tree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Key;
+ PCONFIGURATION_COMPONENT_DATA Adapter;
+
+ //
+ // Loop through each multi-function adapter component in the ARC
+ // configuration tree.
+ //
+
+ for (Key = 0; TRUE; Key++) {
+
+ //
+ // Get a pointer to the component data.
+ //
+
+ Adapter = KeFindConfigurationEntry(
+ Root,
+ AdapterClass,
+ MultiFunctionAdapter,
+ &Key
+ );
+
+ //
+ // If there are no more multi-function adapters in the ARC
+ // configuration tree, then we're done.
+ //
+
+ if (Adapter == NULL) {
+ break;
+ }
+
+ //
+ // Ascertain whether this is a PCI multi-function adapter component.
+ // If so, register a bus handler for it.
+ //
+
+ if (_stricmp(Adapter->ComponentEntry.Identifier, "PCI") == 0) {
+ HalpRegisterPciBus(
+ &Adapter->ComponentEntry,
+ Adapter->ConfigurationData
+ );
+ }
+ }
+}
+
+#endif
+
+VOID
+HalpInitializePCIBus(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ The function intializes global PCI bus state from the registry.
+
+ The Arc firmware is responsible for building configuration information
+ about the number of PCI buses on the system and nature (local vs. secondary
+ - across a PCI-PCI bridge) of the each bus.
+
+ The maximum virtual slot number on the local (type 0 config cycle)
+ PCI bus is registered here, based on the machine dependent define
+ PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice.
+
+ The maximum number of virtual slots on a secondary bus is fixed by the
+ PCI Specification and is represented by PCI_MAX_DEVICES. This
+ state is held in PCIMaxDevice.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Only initialize the PCI subsystem once.
+ //
+
+ if (PCIInitialized) {
+ return;
+ }
+
+ //
+ // Initialize PCI subsystem variables.
+ //
+
+#ifdef AXP_FIRMWARE
+ PCIMaxBus = PCI_MAX_BUSSES;
+#else
+ PCIMaxBus = 0;
+#endif
+ PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+
+ //
+ // Initialize the PCI configuration spinlock.
+ //
+
+ KeInitializeSpinLock(&HalpPCIConfigLock);
+
+#if !AXP_FIRMWARE
+
+ //
+ // Consult the ARC configuration tree and register bus handlers for
+ // all PCI multi-function adapter nodes.
+ //
+
+ HalpQueryPciBusConfiguration(LoaderBlock->ConfigurationRoot);
+
+#endif
+
+ //
+ // The PCI subsystem has been initialized.
+ //
+
+ PCIInitialized = TRUE;
+}
+
+PBUS_HANDLER
+HalpAllocateAndInitPCIBusHandler (
+ IN ULONG BusNo,
+ IN ULONG HwBusNo,
+ IN BOOLEAN BusIsAcrossPPB,
+ IN ULONG PPBBusNumber,
+ IN PCI_SLOT_NUMBER PPBSlotNumber
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ HaliRegisterBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // Bus Number
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA), // sizeof bus specific buffer
+ PCIInstallHandler, // PCI install handler
+ &Bus); // Bushandler return
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+ BusData->HwBusNumber = HwBusNo;
+ BusData->BusIsAcrossPPB = BusIsAcrossPPB;
+ BusData->PPBBusNumber = PPBBusNumber;
+ BusData->PPBSlotNumber = PPBSlotNumber;
+
+ return Bus;
+}
+
+NTSTATUS
+HalpDefaultPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ )
+{
+ PPCIPBUSDATA BusData;
+
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2LineNop;
+ BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCILine2PinNop;
+
+
+ // set defaults
+ //
+ // ecrfix - if we knew more about the PCI bus at this
+ // point (e.g., local vs. across bridge, PCI config
+ // space base QVA, APECS vs. Sable T2/T4 vs. LCA4 vs. ??? config
+ // cycle type 0 mechanism), we could put this info into
+ // the "BusData" structure. The nice thing about this is
+ // that we could eliminate the platform-dependent module
+ // PCIBUS.C.
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES - 1; // not currently used anywhere
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpRegisterPCIInstallHandler(
+ IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
+)
+/*++
+
+Routine Description:
+
+ The function register's a machine-specific PCI Install Handler.
+ This allows a specific platform to override the default PCI install
+ handler, DefaultPCIInstallHandler().
+
+Arguments:
+
+ MachineSpecificPCIInstallHandler - Function that provides machine
+ specific PCI Bus Handler setup.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+ PCIInstallHandler = MachineSpecificPCIInstallHandler;
+
+ return;
+}
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the PCI bus data for a device.
+
+Arguments:
+
+ BusHandler - Registered BUS_HANDLER for the target configuration space
+
+ RootHandler - Register BUS_HANDLER for the orginating HalGetBusData request.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusHandler - Registered BUS_HANDLER for the target configuration space
+
+ RootHandler - Register BUS_HANDLER for the orginating HalSetBusData request.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00) {
+
+ // no device
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configation value changed\n");
+ DbgBreakPoint ();
+ }
+#endif // DBG
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpPCILine2PinNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+{
+ // line-pin mappings not needed on alpha machines
+ return ;
+}
+
+VOID
+HalpPCIPin2LineNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+{
+ // line-pin mappings not needed on alpha machines
+ return ;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+#if 0
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigRead);
+#endif // 0
+
+ //
+ // Read the slot, if it's valid.
+ // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
+ // or a null (zero) buffer if we have a non-existant bus.
+ //
+
+ switch (HalpValidPCISlot (BusHandler, Slot))
+ {
+
+ case ValidSlot:
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigRead);
+ break;
+
+ case InvalidSlot:
+
+ //
+ // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ break ;
+
+ case InvalidBus:
+
+ //
+ // Invalid Bus, return return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) 0);
+ break ;
+ }
+
+ return;
+
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+
+ if (HalpValidPCISlot (BusHandler, Slot) != ValidSlot) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigWrite);
+}
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ ULONG BusNumber;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER Slot2;
+ PCI_CONFIGURATION_TYPES PciConfigType;
+ UCHAR HeaderType;
+ ULONG i, bit;
+
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ //
+ // If the initial device probe has been completed and no device
+ // is present for this slot then simply return invalid slot.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+
+ if( ( (BusData->DevicePresent).Buffer != NULL) &&
+ !RtlCheckBit(&BusData->DevicePresent, bit) ) {
+
+ return InvalidSlot;
+ }
+
+
+ //
+ // Get the config cycle type for the proposed bus.
+ // (PciConfigTypeInvalid indicates a non-existent bus.)
+ //
+
+ PciConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ //
+ // The number of devices allowed on a local PCI bus may be different
+ // than that across a PCI-PCI bridge.
+ //
+
+ switch(PciConfigType) {
+ case PciConfigType0:
+
+ if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) {
+#if HALDBG
+ DbgPrint("Invalid local PCI Slot %x\n", Slot.u.bits.DeviceNumber);
+#endif
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigType1:
+
+ if (Slot.u.bits.DeviceNumber > PCIMaxDevice) {
+#if HALDBG
+ DbgPrint("Invalid remote PCI Slot %x\n", Slot.u.bits.DeviceNumber);
+#endif
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigTypeInvalid:
+
+#if HALDBG
+ DbgPrint("Invalid PCI Bus %x\n", BusNumber);
+#endif
+ return InvalidBus;
+ break;
+
+ }
+
+ //
+ // Check function number
+ //
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return ValidSlot;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return InvalidSlot;
+ }
+
+ return ValidSlot;
+}
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ PCI_CFG_CYCLE_BITS PciAddr;
+ ULONG BusNumber;
+
+ //
+ // Setup platform-dependent state for configuration space access
+ //
+
+ HalpPCIConfigAddr(BusHandler, Slot, &PciAddr);
+
+ //
+ // Synchronize with PCI config space
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ //
+ // Do the I/O to PCI configuration space
+ //
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (&PciAddr, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ //
+ // Release spinlock
+ //
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+
+ return;
+}
+
+ULONG
+HalpPCIReadUchar (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ //
+ // The configuration cycle type is extracted from bits[1:0] of PciCfg.
+ //
+ // Since an LCA4 register generates the configuration cycle type
+ // on the PCI bus, and because Offset bits[1:0] are used to
+ // generate the PCI byte enables (C/BE[3:0]), clear PciCfg bits [1:0]
+ // out before adding in Offset.
+ //
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *Buffer = READ_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshort (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *((PUSHORT) Buffer) = READ_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlong (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *((PULONG) Buffer) = READ_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUchar (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset), *Buffer,
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshort (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset), *((PUSHORT) Buffer),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlong (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset), *((PULONG) Buffer),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (ULONG);
+}
+
+#if DBG
+
+BOOLEAN
+HalpValidPCIAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PHYSICAL_ADDRESS BAddr,
+ IN ULONG Length,
+ IN ULONG AddressSpace)
+/*++
+
+Routine Description:
+
+ Checks to see that the begining and ending 64 bit PCI bus addresses
+ of the 32 bit range of length Length are supported on the system.
+
+Arguments:
+
+ BAddr - the 64 bit starting address
+
+ Length - a 32 bit length
+
+ AddressSpace - is this I/O (1) or memory space (0)
+
+Return Value:
+
+ TRUE or FALSE
+
+--*/
+{
+ PHYSICAL_ADDRESS EAddr, TBAddr, TEAddr;
+ LARGE_INTEGER LiILen;
+ ULONG inIoSpace, inIoSpace2;
+ BOOLEAN flag, flag2;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ //
+ // Translated address to system global setting and verify
+ // resource is available.
+ //
+ // Note that this code will need to be changed to support
+ // 64 bit PCI bus addresses.
+ //
+
+ LiILen.QuadPart = (ULONG)(Length - 1); // Inclusive length
+ EAddr.QuadPart = BAddr.QuadPart + LiILen.QuadPart;
+
+ inIoSpace = inIoSpace2 = AddressSpace;
+
+ flag = HalTranslateBusAddress ( PCIBus,
+ BusNumber,
+ BAddr,
+ &inIoSpace,
+ &TBAddr
+ );
+
+ flag2 = HalTranslateBusAddress (PCIBus,
+ BusNumber,
+ EAddr,
+ &inIoSpace2,
+ &TEAddr
+ );
+
+ if (flag == FALSE || flag2 == FALSE || inIoSpace != inIoSpace2) {
+
+ //
+ // HalAdjustResourceList should ensure that the returned range
+ // for the bus is within the bus limits and no translation
+ // within those limits should ever fail
+ //
+
+ DbgPrint ("HalpValidPCIAddr: Error return for HalTranslateBusAddress %x.%x:%x %x.%x:%x\n",
+ BAddr.HighPart, BAddr.LowPart, flag,
+ EAddr.HighPart, EAddr.LowPart, flag2);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine the firmwaire-assigned resources.
+ Calls IoReportResources to report/confirm them.
+ Returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ PCI_SLOT_NUMBER PciSlot;
+
+ PCM_RESOURCE_LIST CmRes;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc;
+ PHYSICAL_ADDRESS BAddr;
+ ULONG addr;
+ ULONG Command;
+ ULONG cnt, len;
+ BOOLEAN conflict;
+
+ ULONG i, j, m, length, holdvalue;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH * 2;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory - here we allocate
+ // a single chunk of memory and partition it into three pieces, pointed
+ // to by three separate pointers.
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CmRes = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read the PCI device configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID || // empty slot
+ PciData->VendorID == 0x00) { // non-existant bus
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the devices current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData->u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ PciData->u.type0.ROMBaseAddress &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Build an CM_RESOURCE_LIST for the PCI device to report resources
+ // to IoReportResourceUsage.
+ //
+ // This code does *not* use IoAssignoResources, as the PCI
+ // address space resources have been previously assigned by the ARC firmware
+ //
+
+ CmRes->Count = 1;
+ CmRes->List[0].InterfaceType = PCIBus;
+ CmRes->List[0].BusNumber = BusNumber;
+
+ CmRes->List[0].PartialResourceList.Count = 0;
+
+ //
+ // Set current CM_RESOURCE_LIST version and revision
+ //
+
+ CmRes->List[0].PartialResourceList.Version = 0;
+ CmRes->List[0].PartialResourceList.Revision = 0;
+
+ CmDesc = CmRes->List[0].PartialResourceList.PartialDescriptors;
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: Resource List V%d.%d for slot %x:\n",
+ CmRes->List[0].PartialResourceList.Version,
+ CmRes->List[0].PartialResourceList.Revision,
+ Slot);
+
+#endif
+
+ //
+ // Interrupt resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ CmDesc->Type = CmResourceTypeInterrupt;
+ CmDesc->ShareDisposition = CmResourceShareShared;
+ CmDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ CmDesc->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ CmDesc->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+
+#if DBG
+ DbgPrint (" INT Level %x, Vector %x\n",
+ CmDesc->u.Interrupt.Level, CmDesc->u.Interrupt.Vector );
+#endif
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDesc++;
+ }
+
+ //
+ // Add a memory or port resoruce for each PCI resource
+ // (Compute the ROM address as well. Just append it to the Base
+ // Address table.)
+ //
+
+ holdvalue = PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES];
+ PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES] =
+ PciData->u.type0.ROMBaseAddress & ~PCI_ADDRESS_IO_SPACE;
+
+ Command = PciOrigData->Command;
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ addr = i = PciData->u.type0.BaseAddresses[j];
+
+ //
+ // calculate the length necessary - note there is more complicated
+ // code in the x86 HAL that probably isn't necessary
+ //
+
+ length = ~(i & ~((i & 1) ? 3 : 15)) + 1;
+
+ //
+ // I/O space resource
+ //
+
+ if (addr & PCI_ADDRESS_IO_SPACE) {
+
+ CmDesc->Type = CmResourceTypePort;
+ CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDesc->Flags = CM_RESOURCE_PORT_IO;
+
+ BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~3;
+ BAddr.HighPart = 0;
+
+#if DBG
+ HalpValidPCIAddr(BusHandler, BAddr, length, 1); // I/O space
+#endif
+
+ CmDesc->u.Port.Start = BAddr;
+ CmDesc->u.Port.Length = length;
+ Command |= PCI_ENABLE_IO_SPACE;
+#if DBG
+ DbgPrint (" IO Start %x:%08x, Len %x\n",
+ CmDesc->u.Port.Start.HighPart, CmDesc->u.Port.Start.LowPart,
+ CmDesc->u.Port.Length );
+#endif
+ //
+ // Memory space resource
+ //
+
+ } else {
+
+ CmDesc->Type = CmResourceTypeMemory;
+ CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == PCI_TYPE0_ADDRESSES) {
+ // this is a ROM address
+ if ((PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) == 0) {
+ //
+ // Ignore expansion ROMs which are not enabled by
+ // the firmware/ROM BIOS.
+ //
+
+ continue;
+ }
+ CmDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ BAddr.LowPart = PciOrigData->u.type0.ROMBaseAddress &
+ ~PCI_ROMADDRESS_ENABLED;
+ BAddr.HighPart = 0;
+ } else {
+ // this is a memory space base address
+ CmDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~15;
+ BAddr.HighPart = 0;
+ }
+
+#if DBG
+ HalpValidPCIAddr(BusHandler, BAddr, length, 0); // Memory space
+#endif
+
+ CmDesc->u.Memory.Start = BAddr;
+ CmDesc->u.Memory.Length = length;
+#if DBG
+ DbgPrint (" MEM Start %x:%08x, Len %x\n",
+ CmDesc->u.Memory.Start.HighPart, CmDesc->u.Memory.Start.LowPart,
+ CmDesc->u.Memory.Length );
+#endif
+ }
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDesc++;
+
+ if (Is64BitBaseAddress(addr)) {
+ // skip upper half of 64 bit address since we
+ // only supports 32 bits PCI addresses for now.
+ j++;
+ }
+ }
+ }
+
+ //
+ // Setup the resource list.
+ // Count only the acquired resources.
+ //
+
+ *pAllocatedResources = CmRes;
+ cnt = CmRes->List[0].PartialResourceList.Count;
+ len = sizeof (CM_RESOURCE_LIST) +
+ cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)",
+ cnt, len, *pAllocatedResources);
+#endif
+
+ //
+ // Report the IO resource assignments
+ //
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ *pAllocatedResources, // DriverList
+ len, // DriverListSize
+ DeviceObject, // DeviceObject
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ *pAllocatedResources, // DeviceList
+ len, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ if (NT_SUCCESS(status) && conflict) {
+
+ //
+ // IopReportResourceUsage saw a conflict?
+ //
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n",
+ status);
+#endif
+ status = STATUS_CONFLICTING_ADDRESSES;
+ goto CleanUp;
+ }
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status);
+#endif
+ goto CleanUp;
+ }
+
+ //
+ // Restore orginial data, turning on the appropiate decodes
+ //
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: IoReportResourseUsage succeeded\n");
+#endif
+
+ // enable IO & Memory decodes
+
+ PciOrigData->Command |= (USHORT) Command;
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: PCI Config Space updated with Command = %x\n",
+ Command);
+#endif
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ i = 0;
+ if (*pAllocatedResources) {
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts a PCI pResourceList and forces it to match the
+ pre-configured values in PCI configuration space for this device.
+
+Arguments:
+
+ BusHandler - Registered BUS_HANDLER for the target configuration space
+
+ RootHandler - Register BUS_HANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER PciSlot;
+ PPCI_COMMON_CONFIG PciData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt, bcnt;
+ ULONG MemoryBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+
+ //
+ // Fix any requested resources for this device to be the
+ // value set in PCI configuration space for this device.
+ //
+
+ //
+ // Get PCI common configuration space for this slot
+ //
+
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber),
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Copy base addresses based on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ for (bcnt=0; bcnt < PCI_TYPE0_ADDRESSES; bcnt++) {
+ BaseAddress[bcnt] = &PciData->u.type0.BaseAddresses[bcnt];
+ }
+ BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = bcnt;
+ break;
+ case 1:
+ for (bcnt=0; bcnt < PCI_TYPE1_ADDRESSES; bcnt++) {
+ BaseAddress[bcnt] = &PciData->u.type1.BaseAddresses[bcnt];
+ }
+ BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = bcnt;
+ break;
+
+ default:
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Walk each ResourceList and confine resources
+ // to preconfigured settings.
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+ ResourceList->Version = 1;
+ ResourceList->Revision = 1;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+ Descriptor = ResourceList->Descriptors;
+
+ //
+ // For each alternative list, reset to review entire
+ // set of Base Address registers
+ //
+ // We assume that the order of resource descriptors for
+ // each alternative list matches the order of the
+ // PCI configuration space base address registers
+ //
+
+ bcnt = 0;
+
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ //
+ // Limit desctiptor to to preconfigured setting
+ // held in the InterruptLine register.
+ //
+
+ switch (Descriptor->Type) {
+ case CmResourceTypeInterrupt:
+
+ //
+ // Confine interrupt vector to preconfigured setting.
+ //
+
+ Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine;
+ break;
+
+ case CmResourceTypePort:
+
+ //
+ // Assure that requested descriptor is valid
+ //
+
+ if (bcnt > RomIndex) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Confine to preconfigured setting.
+ //
+
+ Descriptor->u.Port.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~0x3;
+
+ Descriptor->u.Port.MaximumAddress.QuadPart =
+ Descriptor->u.Port.MinimumAddress.QuadPart +
+ Descriptor->u.Port.Length - 1;
+
+#if HALDBG
+ DbgPrint("AdjustPCIResourceList\nPort: MinimumAddress set to %x\n",
+ Descriptor->u.Port.MinimumAddress.QuadPart);
+
+ DbgPrint(" MaximumAddress set to %x\n",
+ Descriptor->u.Port.MaximumAddress.QuadPart);
+#endif
+
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Assure that requested descriptor is valid
+ //
+
+ if (bcnt > RomIndex) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Confine to preconfigured setting.
+ //
+
+ MemoryBaseAddress = *BaseAddress[bcnt];
+
+ if (bcnt == RomIndex) {
+ Descriptor->u.Memory.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~PCI_ROMADDRESS_ENABLED;
+ } else {
+ Descriptor->u.Memory.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~0xF;
+ }
+
+ Descriptor->u.Memory.MaximumAddress.QuadPart =
+ Descriptor->u.Memory.MinimumAddress.QuadPart +
+ Descriptor->u.Memory.Length - 1;
+
+ if (Is64BitBaseAddress(MemoryBaseAddress)) {
+ // skip upper half of 64 bit address since we
+ // only supports 32 bits PCI addresses for now.
+ bcnt++;
+ }
+
+
+#if HALDBG
+ DbgPrint("AdjustPCIResourceList\nMemory: MinimumAddress set to %x\n",
+ Descriptor->u.Memory.MinimumAddress.QuadPart);
+
+ DbgPrint(" MaximumAddress set to %x\n",
+ Descriptor->u.Memory.MaximumAddress.QuadPart);
+#endif
+ break;
+
+ case CmResourceTypeDma:
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Next descriptor
+ //
+ Descriptor++;
+ }
+
+ //
+ // Next Resource List
+ //
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+#define TEST_PCI 1
+
+#if DBG && TEST_PCI
+
+VOID HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < 32; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+
+ }
+ DbgBreakPoint();
+}
+
+#endif // DBG && TEST_PCI
diff --git a/private/ntos/nthals/halalpha/pcrtc.c b/private/ntos/nthals/halalpha/pcrtc.c
new file mode 100644
index 000000000..6e8bd954a
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcrtc.c
@@ -0,0 +1,381 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ pcrtc.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ the standard pc-compatible real time clock use on Alpha AXP systems.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+ Jeff McLeman (mcleman) 3-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 13-Jul-1992 Jeff McLeman
+ use VTI access routines to access clock
+
+ 3-June-1992 Jeff McLeman
+ Adapt this module into a Jensen specific module
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+
+//
+// Local function prototypes.
+//
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ );
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+#ifdef AXP_FIRMWARE
+
+//
+// Put these functions in the discardable text section.
+//
+
+#pragma alloc_text(DISTEXT, HalQueryRealTimeClock )
+#pragma alloc_text(DISTEXT, HalSetRealTimeClock )
+#pragma alloc_text(DISTEXT, HalpReadClockRegister )
+#pragma alloc_text(DISTEXT, HalpWriteClockRegister )
+
+#endif // AXP_FIRMWARE
+
+//
+// Define globals used to map the realtime clock address and data ports.
+//
+
+PVOID HalpRtcAddressPort = NULL;
+PVOID HalpRtcDataPort = NULL;
+
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Status;
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ Status = TRUE;
+
+ } else {
+ Status = FALSE;
+ }
+
+ KeLowerIrql(OldIrql);
+ return(Status);
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ UCHAR DataByte;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+
+#ifdef RTC_SQE
+
+ //
+ // If the platform requires it, make sure that the Square
+ // Wave output of the RTC is turned on.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1;
+
+#endif //RTC_SQE
+
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ // (Make sure periodic interrupt is enabled)
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Read the realtime clock register value.
+ //
+
+ WRITE_PORT_UCHAR( HalpRtcAddressPort, Register );
+
+ return READ_PORT_UCHAR( HalpRtcDataPort );
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_PORT_UCHAR( HalpRtcAddressPort, Register );
+
+ WRITE_PORT_UCHAR( HalpRtcDataPort, Value );
+
+ return;
+}
+
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+ On Sable the periodic interrupt comes from the square ware output of
+ the Dallas 1489A RTC on the Standard I/O board. Each processor
+ receives this clock phase shifted by at least 90 degrees from all
+ other processors. The periodic interrupt from the RTC is not used and
+ thus doesn't need to be enabled or acknowledged. Each processor has
+ its own clock interrupt latch that is cleared locally. This routine is
+ not used for Sable platforms.
+
+ Because of the phase shifting among the processors, the clock is
+ half the rate given to the RTC. So, the RTC is programmed twice
+ as fast as on a system that takes the RTC periodic interrupt in
+ directly.
+
+Arguments:
+
+ RateSelect - Supplies rate select to be placed in the clock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Set the new rate
+ //
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->RateSelect = (UCHAR)RateSelect;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->TimebaseDivisor = RTC_TIMEBASE_DIVISOR;
+ HalpWriteClockRegister( RTC_CONTROL_REGISTERA, DataByte );
+
+ //
+ // Set the correct mode
+ //
+ DataByte = 0;
+#if defined(RTC_SQE)
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1;
+#else
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+#endif
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ HalpWriteClockRegister( RTC_CONTROL_REGISTERB, DataByte );
+}
diff --git a/private/ntos/nthals/halalpha/pcrtc.h b/private/ntos/nthals/halalpha/pcrtc.h
new file mode 100644
index 000000000..bff457f05
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcrtc.h
@@ -0,0 +1,166 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ pcrtc.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the standard compatible PC Toy clock.
+
+Author:
+
+ David N. Cutler (davec) 3-May-1991
+ Jeff McLeman (mcleman) 4-Jun-1992
+
+Revision History:
+
+ 13-Jul-1992 Jeff McLeman
+ Add port offsets for use with VTI access routines.
+
+ 4-Jun-1992 Jeff McLeman
+ Adapt module to Jensen specific
+
+--*/
+
+#ifndef _PCRTC_
+#define _PCRTC_
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_REGNUMBER_RTC_CR1 0x6A // control register 1
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Definitions for NT area of NVRAM
+//
+typedef struct _RTC_RAM_NT_FLAGS_0 {
+ UCHAR ConfigurationBit : 1; // Serial line console only
+ UCHAR Fill : 6;
+ UCHAR AutoRunECU : 1; // Go directly to ECU
+} RTC_RAM_NT_FLAGS_0, *PRTC_RAM_NT_FLAGS_0;
+
+#define RTC_RAM_NT_FLAGS_0_RUNARCAPP (0x80)
+#define RTC_RAM_NT_FLAGS_0_RESERVED (0x7E)
+#define RTC_RAM_NT_FLAGS_0_USECOM1FORIO (0x01)
+
+//
+// Values for RTC_RAM_CONSOLE_SELECTION
+//
+
+#define RTC_RAM_CONSOLE_SELECTION_NT 1
+#define RTC_RAM_CONSOLE_SELECTION_VMS 2
+#define RTC_RAM_CONSOLE_SELECTION_OSF 3
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+//
+// Common routine for programming the interval timer
+//
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ );
+
+#endif // _LANGUAGE_ASSEMBLY
+
+//
+// Define initialization values for Jensen interval timer
+// There are four different rates that are used under NT
+// (see page 9-8 of KN121 System Module Programmer's Reference)
+//
+// .976562 ms
+// 1.953125 ms
+// 3.90625 ms
+// 7.8125 ms
+//
+#define RTC_TIMEBASE_DIVISOR 0x02
+
+#define RTC_RATE_SELECT1 6
+#define RTC_RATE_SELECT2 7
+#define RTC_RATE_SELECT3 8
+#define RTC_RATE_SELECT4 9
+
+//
+// note that rates 1-3 have some rounding error,
+// since they are not expressible in even 100ns units
+//
+
+#define RTC_PERIOD_IN_CLUNKS1 9766
+#define RTC_PERIOD_IN_CLUNKS2 19531
+#define RTC_PERIOD_IN_CLUNKS3 39063
+#define RTC_PERIOD_IN_CLUNKS4 78125
+
+//
+// Defaults
+//
+#define MINIMUM_INCREMENT RTC_PERIOD_IN_CLUNKS1
+#define MAXIMUM_INCREMENT RTC_PERIOD_IN_CLUNKS4
+#define MAXIMUM_RATE_SELECT RTC_RATE_SELECT4
+
+#endif // _PCRTC_
diff --git a/private/ntos/nthals/halalpha/pcserial.c b/private/ntos/nthals/halalpha/pcserial.c
new file mode 100644
index 000000000..6d22448a6
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcserial.c
@@ -0,0 +1,596 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ pcserial.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger stub and the kernel debugger via a standard
+ PC serial UART.
+
+ Stolen from ../mips/jxport.c
+
+Author:
+
+ Miche Baker-Harvey (miche) 01-June-1992
+ Jeff McLeman [DEC] 02-Feb-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Joe Notarangelo 21-Jun-1992
+ update to use super-page access to serial port so we aren't depend
+ on translation code, this will allow us to debug the translation
+ code, use serial line 2
+
+
+--*/
+
+
+#include "halp.h"
+#include "halpcsl.h"
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+//
+// Define serial port read and write addresses.
+//
+PSP_READ_REGISTERS SP_READ;
+PSP_WRITE_REGISTERS SP_WRITE;
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 0;
+
+
+ULONG
+HalpGetByte (
+ IN PUCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input data
+ byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+ CP_GET_ERROR is returned if error encountered during reading.
+ CP_GET_NODATA is returned if timeout.
+
+--*/
+{
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_PORT_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_PORT_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudClock;
+ ULONG BaudRate;
+ ULONG Remainder;
+
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud rate divisor to
+ // six, which is 19.2Kbps. Otherwise, set the baud rate divisor
+ // to the correct value for 19.2 baud communication.
+ //
+
+ BaudClock = 1843200;
+
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpBaudRateDivisor = (UCHAR)(BaudClock / (BaudRate*16));
+
+ //
+ // round up
+ //
+ Remainder = BaudClock % (BaudRate*16);
+ if ((Remainder*2) > BaudClock) {
+ HalpBaudRateDivisor++;
+ }
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ //
+ // Establish pointers to serial line register structures
+ //
+
+ KdComPortInUse = (PUCHAR)HalpMapDebugPort(
+ DebugParameters->CommunicationPort,
+ (PULONG)&SP_READ,
+ (PULONG)&SP_WRITE );
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_PORT_UCHAR( &SP_WRITE->LineControl, 0x0 );
+ WRITE_PORT_UCHAR( &SP_WRITE->InterruptEnable, 0x0 );
+
+
+ // We shouldn't have to do anything with the FIFO here -
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ // Note: the references to TransmitBuffer and InterruptEnable are
+ // actually the Divisor Latch LSB and MSB registers respectively
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_PORT_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_PORT_UCHAR(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ WRITE_PORT_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_PORT_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_PORT_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_PORT_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_PORT_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_PORT_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a receive or a transmit.
+ //
+
+ DataLsr = READ_PORT_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_PORT_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
diff --git a/private/ntos/nthals/halalpha/pcspeakr.c b/private/ntos/nthals/halalpha/pcspeakr.c
new file mode 100644
index 000000000..912a87b2a
--- /dev/null
+++ b/private/ntos/nthals/halalpha/pcspeakr.c
@@ -0,0 +1,136 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ pcspeakr.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for the
+ Alpha system that use the standard PC speaker driven by an interval
+ timer.
+
+Author:
+
+ Jeff McLeman (mcleman) 23-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Raise the IRQL to dispatch level and acquire the beep spinlock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeReleaseSpinLock(&HalpBeepLock, oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeReleaseSpinLock(&HalpBeepLock, oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_PORT_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_PORT_UCHAR(&controlBase->SpeakerTone, (UCHAR)newCount);
+ WRITE_PORT_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Release the beep spinlock and restore the IRQL.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, oldIrql);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halalpha/perf8254.c b/private/ntos/nthals/halalpha/perf8254.c
new file mode 100644
index 000000000..7a2160408
--- /dev/null
+++ b/private/ntos/nthals/halalpha/perf8254.c
@@ -0,0 +1,457 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ perf82454.c
+
+Abstract:
+
+ This module implements the interfaces that access the system
+ performance counter and the calibrated stall for systems that
+ use an external 8254 timer chip to implement the performance counter.
+ This module is suitable for use in multiprocessor systems.
+
+Author:
+
+ Joe Notarangelo 14-Mar-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Declare the global that contains the current value of the performance
+// counter.
+//
+
+ULONG HalpLastTimer;
+ULONGLONG HalpTimerWrapCount;
+
+//
+// Declare globals used to control the access to and initialization of
+// the performance counter.
+//
+
+BOOLEAN HalpPerformanceCounterInitialized = FALSE;
+ULONG HalpPerformanceCounterFrequency;
+KSPIN_LOCK HalpPerformanceCounterSpinLock;
+
+#define TIMER_START_VALUE (0xffff)
+
+//
+// Define local routine prototypes.
+//
+
+VOID
+HalpStartTimer(
+ VOID
+ );
+
+ULONG
+HalpReadTimerValue(
+ VOID
+ );
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is responsible for synchronizing the performance
+ counter across all processors in the system configuration.
+ For an 8254-based performance counter all that is necessary is that
+ the counter be initialized.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKPRCB Prcb = PCR->Prcb;
+
+ //
+ // If this isn't the primary processor, then return.
+ //
+
+ if( Prcb->Number != HAL_PRIMARY_PROCESSOR ){
+ return;
+ }
+
+ //
+ // If the counter has already been initialized then simply return.
+ //
+
+ if( HalpPerformanceCounterInitialized == TRUE ){
+ return;
+ }
+
+ //
+ // Initialize the spinlock for controlling access to the counter.
+ //
+
+ KeInitializeSpinLock( &HalpPerformanceCounterSpinLock );
+
+ //
+ // Set the frequency of the counter.
+ //
+
+ HalpPerformanceCounterFrequency = TIMER_CLOCK_IN;
+
+ //
+ // Initialize the wrap count.
+ //
+
+ HalpTimerWrapCount = 0;
+
+ //
+ // Initialize the counter and start it.
+ //
+
+ HalpStartTimer();
+
+ HalpLastTimer = HalpReadTimerValue();
+
+ //
+ // Mark the counter as initialized.
+ //
+
+ HalpPerformanceCounterInitialized = TRUE;
+
+}
+
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ LARGE_INTEGER LocalPerformanceCount;
+ KIRQL OldIrql;
+ ULONG TimerValue;
+
+ //
+ // Return 0 if the performance counter has not been initialized yet.
+ //
+
+ if( HalpPerformanceCounterInitialized == FALSE ){
+ LocalPerformanceCount.QuadPart = 0;
+ return LocalPerformanceCount;
+ }
+
+ //
+ // Synchronize the calculation of the performance counter with the
+ // clock routine executing on the boot processor.
+ //
+
+ KeRaiseIrql( CLOCK_LEVEL, &OldIrql );
+ KiAcquireSpinLock( &HalpPerformanceCounterSpinLock );
+
+ //
+ // Read the current value of the timer count.
+ //
+
+ TimerValue = HalpReadTimerValue();
+
+ //
+ // If the timer is greater than the last timer value then the timer
+ // has wrapped since the last time we have read it.
+ //
+
+ if( TimerValue > HalpLastTimer ){
+
+ HalpTimerWrapCount += (1 << 15);
+ }
+
+ HalpLastTimer = TimerValue;
+
+ LocalPerformanceCount.QuadPart = HalpTimerWrapCount +
+ (TIMER_START_VALUE - TimerValue)/2;
+
+ //
+ // Once the value is calculated synchronization is no longer
+ // required.
+ //
+
+ KiReleaseSpinLock( &HalpPerformanceCounterSpinLock );
+ KeLowerIrql( OldIrql );
+
+ //
+ // If the frequency parameter is specified, then return the frequency
+ // of the 8254 counter.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->LowPart = HalpPerformanceCounterFrequency;
+ Frequency->HighPart = 0;
+ }
+
+ //
+ // Return the calculated performance count.
+ //
+
+ return LocalPerformanceCount;
+
+}
+
+
+VOID
+HalpCheckPerformanceCounter(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called every system clock interrupt in order to
+ check for wrap of the performance counter. The function must handle
+ a wrap if it is detected.
+
+ N.B. - This function must be called at CLOCK_LEVEL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ ULONG TimerValue;
+
+ //
+ // Synchronize the performance counter check with any possible
+ // readers.
+ //
+
+ KiAcquireSpinLock( &HalpPerformanceCounterSpinLock );
+
+ //
+ // Read the current value of the timer count.
+ //
+
+ TimerValue = HalpReadTimerValue();
+
+ //
+ // If the timer is greater than the last timer value then the timer
+ // has wrapped since the last time we have read it.
+ //
+
+ if( TimerValue > HalpLastTimer ){
+
+ HalpTimerWrapCount += (1 << 15);
+ }
+
+ HalpLastTimer = TimerValue;
+
+ KiReleaseSpinLock( &HalpPerformanceCounterSpinLock );
+
+ return;
+
+}
+
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalll execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LONG StallCyclesRemaining; // signed value
+ ULONG PreviousRpcc, CurrentRpcc;
+
+ //
+ // Get the value of the RPCC as soon as we enter
+ //
+
+ PreviousRpcc = HalpRpcc();
+
+ //
+ // Compute the number of cycles to stall
+ //
+
+ StallCyclesRemaining = MicroSeconds * HalpClockMegaHertz;
+
+ //
+ // Wait while there are stall cycles remaining.
+ // The accuracy of this routine is limited by the
+ // length of this while loop.
+ //
+
+ while (StallCyclesRemaining > 0) {
+
+ CurrentRpcc = HalpRpcc();
+
+ //
+ // The subtraction always works because the Rpcc
+ // is a wrapping long-word. If it wraps, we still
+ // get the positive number we want.
+ //
+
+ StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc);
+
+ //
+ // remember this RPCC value
+ //
+
+ PreviousRpcc = CurrentRpcc;
+ }
+
+}
+
+
+VOID
+HalpStartTimer(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Start the timer used to maintain the performance count. The timer used
+ is counter 0 in timer 1 - it is an 8254-compatible timer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ TIMER_CONTROL TimerControl;
+
+ //
+ // Set the timer for counter 0 in binary mode. Write the counter
+ // with the LSB then MSB of the TIMER_START_VALUE.
+ //
+
+ TimerControl.BcdMode = 0;
+ TimerControl.Mode = TM_SQUARE_WAVE;
+ TimerControl.SelectByte = SB_LSB_THEN_MSB;
+ TimerControl.SelectCounter = SELECT_COUNTER_0;
+
+ WRITE_PORT_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->CommandMode1,
+ *(PUCHAR)&TimerControl );
+
+ WRITE_PORT_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Timer1,
+ TIMER_START_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Timer1,
+ (TIMER_START_VALUE >> 8) & 0xff );
+
+
+ return;
+
+}
+
+
+ULONG
+HalpReadTimerValue(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the current value from the timer used to maintain the performance
+ count. The timer used is counter 0 in timer - it is an 8254-compatible
+ timer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The current count value of the timer is returned.
+
+--*/
+{
+ UCHAR Lsb;
+ UCHAR Msb;
+ TIMER_CONTROL TimerControl;
+
+ //
+ // Set the counter for a latched read, read it Lsb then Msb.
+ //
+
+ TimerControl.BcdMode = 0;
+ TimerControl.Mode = 0;
+ TimerControl.SelectByte = SB_COUNTER_LATCH;
+ TimerControl.SelectCounter = SELECT_COUNTER_0;
+
+ WRITE_PORT_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->CommandMode1,
+ *(PUCHAR)&TimerControl );
+
+ Lsb = READ_PORT_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Timer1 );
+
+ Msb = READ_PORT_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Timer1 );
+
+ return (ULONG)( (Msb << 8) | Lsb );
+
+}
diff --git a/private/ntos/nthals/halalpha/perfcntr.c b/private/ntos/nthals/halalpha/perfcntr.c
new file mode 100644
index 000000000..6e1791443
--- /dev/null
+++ b/private/ntos/nthals/halalpha/perfcntr.c
@@ -0,0 +1,260 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ perfcntr.c
+
+Abstract:
+
+ This module implements the interfaces that access the system
+ performance counter and the calibrated stall. The functions implemented
+ in this module are suitable for uniprocessor systems only.
+
+Author:
+
+ Jeff McLeman (mcleman) 05-June-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+ Rod Gamache [DEC] 9-Mar-1993
+ Fix profile clock.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define and initialize the 64-bit count of total system cycles used
+// as the performance counter.
+//
+
+ULONGLONG HalpCycleCount = 0;
+
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Obtain the current value of the processor cycle counter and adjust
+ // the upper 32 bits if a roll-over occurred since the last time the
+ // Rpcc value was checked (at least oncce per clock interrupt). This
+ // code may be interrupted so we must fetch HalpRpccTimec atomically.
+ //
+
+ *(PULONGLONG)&LocalRpccTime = HalpCycleCount;
+ RpccValue = HalpRpcc();
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+ LocalRpccTime.LowPart = RpccValue;
+
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->LowPart = HalpClockFrequency;
+ Frequency->HighPart = 0;
+ }
+
+ //
+ // Return the current processor cycle counter as the function value.
+ //
+
+ return LocalRpccTime;
+}
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // ****** Warning ******
+ //
+ // This is a stub routine. It should clear the current value of the
+ // performance counter. It is really only needed in an MP system where,
+ // close, but not exact synchronization of the performance counters
+ // are needed. See MIPS code in halfxs\mips\j4prof.c for a method of
+ // synchronizing.
+ //
+
+ return;
+}
+
+
+VOID
+HalpCheckPerformanceCounter(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called every system clock interrupt in order to
+ check for wrap of the performance counter. The function must handle
+ a wrap if it is detected.
+
+ N.B. - This function must be called at CLOCK_LEVEL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Update the low part of the performance counter directly from the
+ // rpcc count. Check for wrap of the rpcc count, if wrap has occurred
+ // then increment the high part of the performance counter.
+ //
+
+ LocalRpccTime.QuadPart = HalpCycleCount;
+ RpccValue = HalpRpcc();
+
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+
+ LocalRpccTime.LowPart = RpccValue;
+
+ HalpCycleCount = LocalRpccTime.QuadPart;
+
+ return;
+
+}
+
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG Microseconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalll execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ Microseconds - Supplies the number of microseconds to stall.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LONG StallCyclesRemaining; // signed value
+ ULONG PreviousRpcc, CurrentRpcc;
+
+ //
+ // Get the value of the RPCC as soon as we enter
+ //
+
+ PreviousRpcc = HalpRpcc();
+
+ //
+ // Compute the number of cycles to stall
+ //
+
+ StallCyclesRemaining = Microseconds * HalpClockMegaHertz;
+
+ //
+ // Wait while there are stall cycles remaining.
+ // The accuracy of this routine is limited by the
+ // length of this while loop.
+ //
+
+ while (StallCyclesRemaining > 0) {
+
+ CurrentRpcc = HalpRpcc();
+
+ //
+ // The subtraction always works because the Rpcc
+ // is a wrapping long-word. If it wraps, we still
+ // get the positive number we want.
+ //
+
+ StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc);
+
+ //
+ // remember this RPCC value
+ //
+
+ PreviousRpcc = CurrentRpcc;
+ }
+
+}
+
diff --git a/private/ntos/nthals/halalpha/t2.c b/private/ntos/nthals/halalpha/t2.c
new file mode 100644
index 000000000..19ada2b78
--- /dev/null
+++ b/private/ntos/nthals/halalpha/t2.c
@@ -0,0 +1,760 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ t2.c
+
+Abstract:
+
+ This module implements functions that are specific to the T2 chip.
+ The T2 chip is a system support chip that bridges between the
+ CBUS2 and the PCI bus.
+
+Author:
+
+ Joe Notarangelo 18-Oct-1993
+ Steve Jenness 18-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Steve Brooks 30-Dec-1994
+
+ Remove sable specific references and move to common halalpha directory
+
+--*/
+
+#include "halp.h"
+
+extern ULONG HalDisablePCIParityChecking;
+
+#ifdef HALDBG
+
+ULONG T2Debug;
+
+VOID
+DumpT2(
+ VOID
+ );
+
+VOID
+DumpT4(
+ VOID
+ );
+
+#define DebugDumpT2(DebugPrintLevel) \
+ if (DebugPrintLevel <= T2Debug) \
+ DumpT2()
+
+#else //HALDBG
+
+#define DebugDumpT2(a)
+
+#endif //HALDBG
+
+VOID
+HalpT2InitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ T2_WINDOW_NUMBER WindowNumber
+ )
+/*++
+
+Routine Description:
+
+ Initialize the DMA Control software window registers for the specified
+ DMA Window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control.
+
+ WindowNumber - Supplies the window number initialized. (0 = Isa Dma
+ Window, 1 = Master Dma Window).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ switch( WindowNumber ){
+
+ //
+ // The ISA DMA Window.
+ //
+
+ case T2IsaWindow:
+
+ WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
+
+ WindowRegisters->TranslatedBaseRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Tbase1;
+ WindowRegisters->WindowBaseRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Wbase1;
+ WindowRegisters->WindowMaskRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Wmask1;
+ WindowRegisters->WindowTbiaRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr;
+
+ WindowRegisters->TranslatedBaseRegister[1] = NULL;
+ WindowRegisters->WindowBaseRegister[1] = NULL;
+ WindowRegisters->WindowMaskRegister[1] = NULL;
+ WindowRegisters->WindowTbiaRegister[1] = NULL;
+
+ break;
+
+ case T2MasterWindow:
+
+ WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
+
+ WindowRegisters->TranslatedBaseRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Tbase2;
+ WindowRegisters->WindowBaseRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Wbase2;
+ WindowRegisters->WindowMaskRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Wmask2;
+ WindowRegisters->WindowTbiaRegister[0] =
+ &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr;
+
+ WindowRegisters->TranslatedBaseRegister[1] =
+ &((PT2_CSRS)(T4_CSRS_QVA))->Tbase2;
+ WindowRegisters->WindowBaseRegister[1] =
+ &((PT2_CSRS)(T4_CSRS_QVA))->Wbase2;
+ WindowRegisters->WindowMaskRegister[1] =
+ &((PT2_CSRS)(T4_CSRS_QVA))->Wmask2;
+ WindowRegisters->WindowTbiaRegister[1] =
+ &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr;
+
+
+ break;
+
+ default:
+
+#if HALDBG
+
+ DbgPrint( "T2InitializeSfwWindow: Bad Window Number = %x\n",
+ WindowNumber );
+
+#endif //HALDBG
+
+ break;
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpT2ProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ Program the control windows in the hardware so that DMA can be started
+ to the DMA window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ MapRegisterBase - Supplies the logical address of the scatter/gather
+ array in system memory.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_WBASE PciBase;
+ T2_WMASK PciMask;
+ T2_TBASE Tbase;
+
+ PciBase.all = 0;
+ PciBase.EnablePciWindow = 1;
+ PciBase.EnableScatterGather = 1;
+ PciBase.PciWindowStartAddress = (ULONG)(WindowRegisters->WindowBase) >> 20;
+ PciBase.PciWindowEndAddress =
+ ((ULONG)(WindowRegisters->WindowBase) +
+ WindowRegisters->WindowSize - 1) >> 20;
+
+ PciMask.all = 0;
+ PciMask.PciWindowMask = (WindowRegisters->WindowSize >> 20) - 1;
+
+ Tbase.all = 0;
+ Tbase.TranslatedBaseAddress = (ULONG)(MapRegisterBase) >> 10;
+
+ //
+ // Dump the T2 registers.
+ //
+
+ DebugDumpT2(5);
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_T2_REGISTER( WindowRegisters->WindowBaseRegister[0], (ULONGLONG)0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_T2_REGISTER( WindowRegisters->TranslatedBaseRegister[0],
+ *(PULONGLONG)&Tbase );
+
+ WRITE_T2_REGISTER( WindowRegisters->WindowMaskRegister[0],
+ *(PULONGLONG)&PciMask );
+
+ WRITE_T2_REGISTER( WindowRegisters->WindowBaseRegister[0],
+ *(PULONGLONG)&PciBase );
+
+// smjfix - Turn on Hole 1 and 2 to make access to
+// Eisa memory space work. This is currently used to
+// to allow access to the Qvision frame buffer at 4Mbytes.
+// Note that the StartAddress and EndAddress need to be
+// shifted by 1 bit (in contrast to the T2 spec).
+// Currently memory devices on Sable have to be 0-16Mbytes or
+// above 2Gbytes.
+
+ {
+ T2_HBASE Hbase;
+
+ Hbase.all = 0;
+ Hbase.HoleStartAddress = 0x40 << 1; // 4 Mbytes
+ Hbase.HoleEndAddress = 0x4f << 1; // 5 Mbytes - 1
+ Hbase.Hole1Enable = 1;
+ Hbase.Hole2Enable = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hbase,
+ *(PULONGLONG)&Hbase );
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the external I/O module is present and this is *not* the ISA
+ // DMA window, initialize the T4 similarly.
+ //
+
+ if( HalpXioPresent && WindowRegisters->WindowBaseRegister[1] != NULL ) {
+
+#if HALDBG
+ DumpT4();
+#endif
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_T2_REGISTER( WindowRegisters->WindowBaseRegister[1],
+ (ULONGLONG)0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_T2_REGISTER( WindowRegisters->TranslatedBaseRegister[1],
+ *(PULONGLONG)&Tbase );
+
+ WRITE_T2_REGISTER( WindowRegisters->WindowMaskRegister[1],
+ *(PULONGLONG)&PciMask );
+
+ WRITE_T2_REGISTER( WindowRegisters->WindowBaseRegister[1],
+ *(PULONGLONG)&PciBase );
+
+ //
+ // The external I/O module does not have a co-resident EISA/ISA
+ // bus, therefore, no holes are necessary.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hbase,
+ (ULONGLONG)0 );
+
+#if HALDBG
+ DumpT4();
+#endif
+ }
+
+#endif
+
+ //
+ // Flush and enable the translation buffer inside of the T2.
+ // Since the TLB is maintained by bus snooping, this should be the
+ // only time a flush is needed.
+ //
+
+
+ {
+ ULONGLONG Value;
+ T2_IOCSR Iocsr;
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T2_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+ Iocsr.EnableTlb = 0;
+ Iocsr.FlushTlb = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+ Iocsr.EnableTlb = 1;
+ Iocsr.FlushTlb = 0;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent ) {
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T4_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+ Iocsr.EnableTlb = 0;
+ Iocsr.FlushTlb = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+ Iocsr.EnableTlb = 0;
+ Iocsr.FlushTlb = 0;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+#if HALDBG
+ DumpT4();
+#endif
+ }
+
+#endif
+
+ }
+
+ //
+ // Dump the T2 registers.
+ //
+
+ DebugDumpT2(5);
+
+ return;
+}
+
+VOID
+HalpT2InvalidateTLB(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters
+ )
+/*++
+
+Routine Description:
+
+ Invalidate the DMA Scatter/Gather TLB in the T2. This routine
+ is called when initializing the window registers. It is *not*
+ called by HAL_INVALIDATE_TRANSLATIONS because invalidating the
+ TLB when DMAs are in progress doesn't work on the T2.
+
+ There is a single TLB in the T2; the WindowRegisters argument is
+ ignored.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONGLONG Value;
+ T2_IOCSR Iocsr;
+
+#if 0
+
+ // Pass2 appears to be broken also.
+
+#ifndef T2PASS1ONLY
+
+ //
+ // If the T2 is a Pass2 or later, flush and enable the TLB.
+ //
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T2_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+
+ if (Iocsr.T2RevisionNumber != 0) {
+
+ Iocsr.FlushTlb = 1;
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+ Iocsr.EnableTlb = 1;
+ Iocsr.FlushTlb = 0;
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // Invalidate the T4's TLB...
+ //
+
+ if( HalpXioPresent ){
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T4_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+
+ Iocsr.FlushTlb = 1;
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+ Iocsr.EnableTlb = 0;
+ Iocsr.FlushTlb = 0;
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ *(PULONGLONG)&Iocsr );
+
+ }
+
+#endif
+
+#endif //T2PASS1ONLY
+#endif //0
+}
+
+#if HALDBG
+
+VOID
+DumpT2(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting T2 registers and print them to the debug port.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ PVOID TestQva;
+ ULONGLONG Value;
+ ULONG LongValue;
+ T2_TDR Tdr;
+
+// DbgPrint( "Dumping the T2 registers, " );
+
+#if 0
+//
+// This code tests whether the windows and holes allow access to
+// the address in I/O memory space set in PhysicalAddress.
+// See also the companion code at the end of this routine.
+//
+ {
+ ULONG AddressSpace;
+ PHYSICAL_ADDRESS PhysicalAddress;
+
+ AddressSpace = 0;
+ PhysicalAddress.LowPart = 0xD0000; // DE422
+// PhysicalAddress.LowPart = 0x2200000; // 34Mbytes
+// PhysicalAddress.LowPart = 0x0400000; // 4Mbytes
+ PhysicalAddress.HighPart = 0;
+ HalTranslateBusAddress( Isa, 0, PhysicalAddress, &AddressSpace, &TestQva );
+
+ LongValue = READ_REGISTER_ULONG( TestQva );
+ DbgPrint( "TestQva = %lx, Value = %x, writing 0xa5a5a5a5..\n",
+ TestQva, LongValue );
+ LongValue = 0xa5a5a5a5;
+ WRITE_REGISTER_ULONG( TestQva, LongValue );
+ LongValue = READ_REGISTER_ULONG( TestQva );
+ DbgPrint( "TestQva = %lx, Value = %x\n", TestQva, LongValue );
+ }
+#endif // 0
+
+#if 0
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Iocsr = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Ivrpr;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Ivrpr = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hae0_1 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hae0_2 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Hbase;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hbase = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wbase1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wbase1 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wmask1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wmask1 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tbase1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Tbase1 = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wbase2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wbase2 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wmask2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wmask2 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tbase2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Tbase2 = %Lx\n", Value );
+
+#endif // 0
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr0;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr0 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr1 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr2 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr3;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr3 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr4;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr4 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr5;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr5 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr6;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr6 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr7;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr7 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+#if 0
+ LongValue = READ_REGISTER_ULONG( TestQva );
+ DbgPrint( "TestQva = %lx, Value = %x, writing 0xc3c3c3c3..\n",
+ TestQva, LongValue );
+ LongValue = 0xc3c3c3c3;
+ WRITE_REGISTER_ULONG( TestQva, LongValue );
+ LongValue = READ_REGISTER_ULONG( TestQva );
+ DbgPrint( "TestQva = %lx, Value = %x\n", TestQva, LongValue );
+#endif // 0
+
+// DbgPrint( "--end T2 dump\n\n" );
+
+ return;
+
+}
+
+#endif //HALDBG
+
+#if HALDBG && defined(XIO_PASS1) || defined(XIO_PASS2)
+
+VOID
+DumpT4(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting T2 registers and print them to the debug port.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ ULONGLONG Value;
+ ULONG LongValue;
+ T2_TDR Tdr;
+
+ if( !HalpXioPresent ){
+ DbgPrint( "XIO module not present.\n" );
+ return;
+ }
+
+ DbgPrint( "Dumping the T4 registers:\n" );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Iocsr = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Ivrpr;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Ivrpr = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hae0_1 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hae0_2 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_3;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hae0_3 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_4;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hae0_4 = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Hbase;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Hbase = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wbase1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wbase1 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wmask1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wmask1 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tbase1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Tbase1 = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wbase2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wbase2 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wmask2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wmask2 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tbase2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Tbase2 = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wbase3;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wbase3 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wmask3;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wmask3 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tbase3;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Tbase3 = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wbase4;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wbase4 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Wmask4;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Wmask4 = %Lx, ", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tbase4;
+ Value = READ_T2_REGISTER( RegisterQva );
+ DbgPrint( "Tbase4 = %Lx\n", Value );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr0;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr0 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr1;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr1 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr2;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr2 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr3;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr3 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr4;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr4 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr5;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr5 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr6;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr6 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ RegisterQva = &((PT2_CSRS)(T4_CSRS_QVA))->Tdr7;
+ Value = READ_T2_REGISTER( RegisterQva );
+ Tdr = *(PT2_TDR)&Value;
+ DbgPrint( "Tdr7 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag );
+
+ DbgPrint( "--end T4 dump\n\n" );
+}
+
+#endif //HALDBG
diff --git a/private/ntos/nthals/halalpha/t2.h b/private/ntos/nthals/halalpha/t2.h
new file mode 100644
index 000000000..40b0c5136
--- /dev/null
+++ b/private/ntos/nthals/halalpha/t2.h
@@ -0,0 +1,550 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ t2.h
+
+Abstract:
+
+ This file defines the structures and definitions describing the
+ T2 chipset
+
+Author:
+
+ Steve Brooks 28-Dec 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Extracted from sable.h to be platform independent for sable, gamma & lynx
+
+--*/
+
+#ifndef _T2H_
+#define _T2H_
+
+//
+// N.B. The structure below defines the address offsets of the control
+// registers when used with the base QVA. It does NOT define the
+// size or structure of the individual registers.
+//
+
+
+typedef struct _T2_CSRS {
+ UCHAR Iocsr; // I/O Control/Status Register
+ UCHAR Cerr1; // CBUS Error Register 1
+ UCHAR Cerr2; // CBUS Error Register 2
+ UCHAR Cerr3; // CBUS Error Register 3
+ UCHAR Perr1; // PCI Error Register 1
+ UCHAR Perr2; // PCI Error Register 2
+ UCHAR Pscr; // PCI Special Cycle Register
+ UCHAR Hae0_1; // High Address Extension Register 1
+ UCHAR Hae0_2; // High Address Extension Register 2
+ UCHAR Hbase; // PCI Hole Base Register
+ UCHAR Wbase1; // Window Base Register 1
+ UCHAR Wmask1; // Window Mask Register 1
+ UCHAR Tbase1; // Translated Base Register 1
+ UCHAR Wbase2; // Window Base Register 2
+ UCHAR Wmask2; // Window Mask Register 2
+ UCHAR Tbase2; // Translated Base Register 2
+ UCHAR Tlbbr; // TLB Bypass Register
+ UCHAR Ivrpr; // IVR Passive Release Register
+ UCHAR Hae0_3; // High Address Extension Register 3
+ UCHAR Hae0_4; // High Address Extension Register 4
+ UCHAR Wbase3; // Window Base Register 3 (T3/T4)
+ UCHAR Wmask3; // Window Mask Register 3 (T3/T4)
+ UCHAR Tbase3; // Translated Base Register 3 (T3/T4)
+ UCHAR filler0;
+ UCHAR Tdr0; // TLB Data Register 0
+ UCHAR Tdr1; // TLB Data Register 1
+ UCHAR Tdr2; // TLB Data Register 2
+ UCHAR Tdr3; // TLB Data Register 3
+ UCHAR Tdr4; // TLB Data Register 4
+ UCHAR Tdr5; // TLB Data Register 5
+ UCHAR Tdr6; // TLB Data Register 6
+ UCHAR Tdr7; // TLB Data Register 7
+ UCHAR Wbase4; // Window Base Register 4 (T3/T4)
+ UCHAR Wmask4; // Window Mask Register 4 (T3/T4)
+ UCHAR Tbase4; // Translated Base Register 4 (T3/T4)
+ UCHAR Air; // Address Indirection Register (T3/T4)
+ UCHAR Var; // Vector Access Register (T3/T4)
+ UCHAR Dir; // Data Indirection Register (T3/T4)
+ UCHAR Ice; // IC Enable Register (T3/T4)
+} T2_CSRS, *PT2_CSRS;
+
+//
+// Define formats of useful T2 registers.
+//
+
+typedef union _T2_IOCSR {
+ struct {
+ ULONG EnableReadIoReq: 1; // 00 - P2 Defunct, MBZ
+ ULONG EnableLoopBack: 1; // 01
+ ULONG EnableStateMachineVisibility: 1; // 02
+ ULONG PciDriveBadParity: 1; // 03
+ ULONG Mba0: 1; // 04
+ ULONG Mba1: 1; // 05
+ ULONG PciInterrupt: 1; // 06
+ ULONG EnableTlbErrorCheck: 1; // 07
+ ULONG EnableCxAckCheckForDma: 1; // 08
+ ULONG EnableDenseWrap: 1; // 09
+ ULONG CbusEnableExclusiveExchange: 1; // 10
+ ULONG Pci64Enable: 1; // 11
+ ULONG CbusCAWriteWrongParity0: 1; // 12
+ ULONG CbusCAWriteWrongParity2: 1; // 13
+ ULONG CbusCADataWriteWrongParityEven: 1; // 14
+ ULONG Mba5: 1; // 15
+ ULONG Mba6: 1; // 16 - P2 Power Supply Error
+ ULONG Mba7: 1; // 17
+ ULONG Mba2: 1; // 18
+ ULONG Mba3: 1; // 19
+ ULONG PciDmaWriteWrongParityHW1: 1; // 20
+ ULONG PciDmaWriteWrongParityHW0: 1; // 21
+ ULONG PciBusReset: 1; // 22
+ ULONG PciInterfaceReset: 1; // 23
+ ULONG EnableCbusErrorInterrupt: 1; // 24
+ ULONG EnablePciMemorySpace: 1; // 25
+ ULONG EnableTlb: 1; // 26
+ ULONG EnableHogMode: 1; // 27
+ ULONG FlushTlb: 1; // 28
+ ULONG EnableCbusParityCheck: 1; // 29
+ ULONG CbusInterfaceReset: 1; // 30
+ ULONG EnablePciLock: 1; // 31
+ ULONG EnableCbusBackToBackCycle: 1; // 32
+ ULONG T2RevisionNumber: 3; // 33
+ ULONG StateMachineVisibilitySelect: 3; // 36
+ ULONG Mba4: 1; // 39
+ ULONG EnablePassiveRelease: 1; // 40
+ ULONG EnablePciRdp64: 1; // 41 (T4)
+ ULONG EnablePciAp64: 1; // 42 (T4)
+ ULONG EnablePciWdp64: 1; // 43 (T4)
+ ULONG CbusCAWriteWrongParity1: 1; // 44
+ ULONG CbusCAWriteWrongParity3: 1; // 45
+ ULONG CbusCADataWriteWrongParityOdd: 1; // 46
+ ULONG T2T4Status: 1; // 47
+ ULONG EnablePpc1: 1; // 48 (T3/T4)
+ ULONG EnablePpc2: 1; // 49 (T3/T4)
+ ULONG EnablePciStall: 1; // 50 (T3/T4)
+ ULONG Mbz0: 1; // 51
+ ULONG PciReadMultiple: 1; // 52
+ ULONG PciWriteMultiple: 1; // 53
+ ULONG ForcePciRdpeDetect: 1; // 54
+ ULONG ForcePciApeDetect: 1; // 55
+ ULONG ForcePciWdpeDetect: 1; // 56
+ ULONG EnablePciNmi: 1; // 57
+ ULONG EnablePciDti: 1; // 58
+ ULONG EnablePciSerr: 1; // 59
+ ULONG EnablePciPerr: 1; // 60
+ ULONG EnablePciRdp: 1; // 61
+ ULONG EnablePciAp: 1; // 62
+ ULONG EnablePciWdp: 1; // 63
+ };
+ ULONGLONG all;
+} T2_IOCSR, *PT2_IOCSR;
+
+typedef union _T2_CERR1 {
+ struct {
+ ULONG UncorrectableReadError: 1; // 00
+ ULONG NoAcknowledgeError: 1; // 01
+ ULONG CommandAddressParityError: 1; // 02
+ ULONG MissedCommandAddressParity: 1; // 03
+ ULONG ResponderWriteDataParityError: 1; // 04
+ ULONG MissedRspWriteDataParityError: 1; // 05
+ ULONG ReadDataParityError: 1; // 06
+ ULONG MissedReadDataParityError: 1; // 07
+ ULONG CaParityErrorLw0: 1; // 08
+ ULONG CaParityErrorLw2: 1; // 09
+ ULONG DataParityErrorLw0: 1; // 10
+ ULONG DataParityErrorLw2: 1; // 11
+ ULONG DataParityErrorLw4: 1; // 12
+ ULONG DataParityErrorLw6: 1; // 13
+ ULONG Reserved1: 2; // 14-15
+ ULONG CmdrWriteDataParityError: 1; // 16
+ ULONG BusSynchronizationError: 1; // 17
+ ULONG InvalidPfnError: 1; // 18
+ ULONG Mbz0: 13; // 19-31
+ ULONG Mbz1: 8; // 32-39
+ ULONG CaParityErrorLw1: 1; // 40
+ ULONG CaParityErrorLw3: 1; // 41
+ ULONG DataParityErrorLw1: 1; // 42
+ ULONG DataParityErrorLw3: 1; // 43
+ ULONG DataParityErrorLw5: 1; // 44
+ ULONG DataParityErrorLw7: 1; // 45
+ ULONG Mbz2: 18; // 46-63
+ };
+ ULONGLONG all;
+} T2_CERR1, *PT2_CERR1;
+
+typedef ULONGLONG T2_CERR2;
+typedef ULONGLONG T2_CERR3;
+
+typedef union _T2_PERR1 {
+ struct {
+ ULONG WriteDataParityError: 1; // 00
+ ULONG AddressParityError: 1; // 01
+ ULONG ReadDataParityError: 1; // 02
+ ULONG ParityError: 1; // 03
+ ULONG SystemError: 1; // 04
+ ULONG DeviceTimeoutError: 1; // 05
+ ULONG NonMaskableInterrupt: 1; // 06
+ ULONG PpcSizeError: 1; // 07 (T3/T4)
+ ULONG WriteDataParityError64: 1; // 08 (T3/T4)
+ ULONG AddressParityError64: 1; // 09 (T3/T4)
+ ULONG ReadDataParityError64: 1; // 10 (T3/T4)
+ ULONG TargetAbort: 1; // 11 (T3/T4)
+ ULONG Mbz0: 4; // 12-15
+ ULONG ForceReadDataParityError64: 1; // 16 (T3/T4)
+ ULONG ForceAddressParityError64: 1; // 17 (T3/T4)
+ ULONG ForceWriteDataParityError64: 1; // 18 (T3/T4)
+ ULONG DetectTargetAbort: 1; // 19 (T3/T4)
+ ULONG Reserved1: 12; // 20-31
+ ULONG Reserved; // 32-63
+ };
+ ULONGLONG all;
+} T2_PERR1, *PT2_PERR1;
+
+typedef union _T2_PERR2 {
+ struct {
+ ULONG ErrorAddress; // 00
+ ULONG PciCommand: 4; // 32
+ ULONG Reserved: 28; // 36-63
+ };
+ ULONGLONG all;
+} T2_PERR2, *PT2_PERR2;
+
+typedef struct _T2_WBASE {
+ union {
+ struct {
+ ULONG PciWindowEndAddress: 12; // 00
+ ULONG Reserved0: 5; // 12
+ ULONG EnablePeerToPeer: 1; // 17
+ ULONG EnableScatterGather: 1; // 18
+ ULONG EnablePciWindow: 1; // 19
+ ULONG PciWindowStartAddress: 12; // 20
+ ULONG Reserved; // 32-63
+ };
+ ULONGLONG all;
+ };
+} T2_WBASE, *PT2_WBASE;
+
+typedef struct _T2_WMASK {
+ union {
+ struct {
+ ULONG Reserved0: 20; // 00
+ ULONG PciWindowMask: 11; // 20
+ ULONG Reserved1: 1; // 31
+ ULONG Reserved; // 32-63
+ };
+ ULONGLONG all;
+ };
+} T2_WMASK, *PT2_WMASK;
+
+typedef struct _T2_TBASE {
+ union {
+ struct {
+ ULONG Reserved0: 9; // 00
+ ULONG TranslatedBaseAddress: 22; // 09
+ ULONG Reserved1: 1; // 31
+ ULONG Reserved; // 32-63
+ };
+ ULONGLONG all;
+ };
+} T2_TBASE, *PT2_TBASE;
+
+typedef struct _T2_HBASE {
+ union {
+ struct {
+ ULONG HoleEndAddress: 9; // 00
+ ULONG Reserved1: 4; // 09
+ ULONG Hole1Enable: 1; // 13
+ ULONG Hole2Enable: 1; // 14
+ ULONG HoleStartAddress: 9; // 15
+ ULONG Reserved2: 8; // 24
+ ULONG Reserved3; // 32-63
+ };
+ ULONGLONG all;
+ };
+} T2_HBASE, *PT2_HBASE;
+
+typedef struct _T2_TDR {
+ ULONG Tag: 30; // 00
+ ULONG Reserved1: 2; // 30
+ ULONG Valid: 1; // 32
+ ULONG Pfn: 18; // 33
+ ULONG Reserved2: 13; // 51
+} T2_TDR, *PT2_TDR;
+
+typedef union _T2_VAR { // T3/T4 Vector Address Register
+ struct {
+ ULONGLONG Vector: 6; // 00-05
+ ULONGLONG Eisa: 1; // 06
+ ULONGLONG PassiveRelease: 1; // 07
+ ULONGLONG Reserved: 56; // 08-63
+ };
+ ULONGLONG all;
+} T2_VAR, *PT2_VAR;
+
+typedef union _T2_ICE { // T3/T4 ICIC Enable Register
+ struct {
+ ULONGLONG EisaFlushAddress: 24; // 00-23
+ ULONGLONG IcEnable: 1; // 24
+ ULONGLONG HalfSpeedEnable: 1; // 25
+ ULONGLONG Reserved: 38; // 26-63
+ };
+ ULONGLONG all;
+} T2_ICE, *PT2_ICE;
+
+//
+// DMA Window Values.
+//
+// The T2 will be initialized to allow 2 DMA windows.
+// The first window will be for the use of of ISA devices and DMA slaves
+// and therefore must have logical addresses below 16MB.
+// The second window will be for bus masters (non-ISA) and so may be
+// above 16MB.
+//
+// The arrangement of the windows will be as follows:
+//
+// Window Logical Start Address Window Size
+// ------ --------------------- -----------
+// Isa 8MB 8MB
+// Master 16MB 16MB
+//
+
+#define ISA_DMA_WINDOW_BASE (__8MB)
+#define ISA_DMA_WINDOW_SIZE (__8MB)
+
+#define MASTER_DMA_WINDOW_BASE (__16MB)
+#define MASTER_DMA_WINDOW_SIZE (__16MB)
+
+
+//
+// Define the software control registers for a DMA window.
+//
+
+typedef struct _WINDOW_CONTROL_REGISTERS {
+ PVOID WindowBase;
+ ULONG WindowSize;
+ PVOID TranslatedBaseRegister[2];
+ PVOID WindowBaseRegister[2];
+ PVOID WindowMaskRegister[2];
+ PVOID WindowTbiaRegister[2];
+} WINDOW_CONTROL_REGISTERS, *PWINDOW_CONTROL_REGISTERS;
+
+//
+// Define types of windows.
+//
+
+typedef enum _T2_WINDOW_NUMBER {
+ T2IsaWindow,
+ T2MasterWindow
+} T2_WINDOW_NUMBER, *PT2_WINDOW_NUMBER;
+
+//
+// Define T2 Window Control routines.
+//
+
+VOID
+HalpT2InitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ T2_WINDOW_NUMBER WindowNumber
+ );
+
+VOID
+HalpT2ProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ );
+
+VOID
+HalpT2InvalidateTLB(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters
+ );
+
+VOID
+WRITE_T2_REGISTER(
+ PVOID,
+ ULONGLONG
+ );
+
+ULONGLONG
+READ_T2_REGISTER(
+ PVOID
+ );
+
+
+//
+// VOID
+// INITIALIZE_ISA_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_ISA_DMA_CONTROL( WR ) \
+ HalpT2InitializeSfwWindow( (WR), T2IsaWindow );
+
+
+//
+// VOID
+// INITIALIZE_MASTER_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_MASTER_DMA_CONTROL( WR ) \
+ HalpT2InitializeSfwWindow( (WR), T2MasterWindow );
+
+
+//
+// VOID
+// INITIALIZE_DMA_WINDOW(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters,
+// PTRANSLATION_ENTRY MapRegisterBase
+// )
+//
+// Routine Description:
+//
+// Program the control windows so that DMA can be started to the
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window register
+// control structure.
+//
+// MapRegisterBase - Supplies the logical address of the scatter/gather
+// array in system memory.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_DMA_WINDOW( WR, MRB ) \
+ HalpT2ProgramDmaWindow( (WR), (MRB) );
+
+
+//
+// VOID
+// INVALIDATE_DMA_TRANSLATIONS(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Invalidate all of the cached translations for a DMA window.
+// This function does not need to do any action on the T2 chip
+// because the T2 snoops the bus and keeps the translations coherent
+// via hardware.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control
+// registers.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INVALIDATE_DMA_TRANSLATIONS( WR )
+
+
+//
+// Define the format of a translation entry aka a scatter/gather entry
+// or map register.
+//
+
+typedef struct _TRANSLATION_ENTRY{
+ ULONG Valid: 1;
+ ULONG Pfn: 31;
+ ULONG Reserved;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+
+//
+// VOID
+// HAL_MAKE_VALID_TRANSLATION(
+// PTRANSLATION_ENTRY Entry,
+// ULONG PageFrameNumber
+// )
+//
+// Routine Description:
+//
+// Make the scatter/gather entry pointed to by Entry valid with
+// a translation to the page indicated by PageFrameNumber.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation entry to make valid.
+//
+// PageFrameNumber - Supplies the page frame of the valid translation.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_MAKE_VALID_TRANSLATION( ENTRY, PFN ) \
+ { \
+ (ENTRY)->Valid = 1; \
+ (ENTRY)->Pfn = PFN; \
+ (ENTRY)->Reserved = 0; \
+ }
+
+
+//
+// VOID
+// HAL_INVALIDATE_TRANSLATION(
+// PTRANSLATION_ENTRY Entry
+// )
+//
+// Routine Description:
+//
+// Invalidate the translation indicated by Entry.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation to be invalidated.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_INVALIDATE_TRANSLATION( ENTRY ) \
+ (ENTRY)->Valid = 0;
+
+#endif // T2H
diff --git a/private/ntos/nthals/halalpha/vga.c b/private/ntos/nthals/halalpha/vga.c
new file mode 100644
index 000000000..c8b10394f
--- /dev/null
+++ b/private/ntos/nthals/halalpha/vga.c
@@ -0,0 +1,608 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ vga.c
+
+Abstract:
+
+ This module implements device-independent HAL display initialization and
+ output routines for Alpha systems.
+
+ It was stolen from a combination of the jxdisp.c routine in the firmware
+ directory, written by John DeRosa, and the jxdisp.c routines in the MIPS
+ HAL directory.
+
+Author:
+
+ Miche Baker-Harvey (miche) 10-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 12-July-1994 Eric Rehm
+ Support RESET_DISPLAY_PARAMETERS callback registered during
+ HalAcquireDisplayOwnership. This callback is supplied by
+ the Video Miniport driver's HwResetHw entry in the HW_INITIALIZATION_DATA
+ structure.
+
+ 17-Feb-1994 Eric Rehm
+ Rewrite ouput routines to be device-independent through callback
+ to firmware VenPrint routine.
+
+ 30-Dec-1993 Joe Notarangelo
+ Eliminate the video initialization code that was compiled only
+ when VIDEO_CALLBACK_IMPLEMENTED is not defined. It is now a
+ requirement that the firmware implement the callback.
+
+ 04-Mar-1993 Joe Mitchell (DEC)
+ Modify HalpScrollDisplay to pause after displaying each screenful of
+ information during a bugcheck.
+ Modify InitializeVGA to call the firmware to init the video display
+ rather than doing the initialization itself.
+
+ 10-Aug-1992 Jeff McLeman (DEC)
+ Put in debug fixes.
+
+ 22-Jul-1992 Jeff McLeman (mcleman)
+ Remove inline asm(MB)s , because Hal access routines manage
+ read/write ordering.
+
+--*/
+
+//
+// Need some include files here
+#include "halp.h"
+#include "arc.h"
+#include "halvga.h"
+#include "fwcallbk.h"
+#include "stdio.h"
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpSetLoc (
+ );
+
+BOOLEAN
+InitializeDisplay (
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpScrollDisplay(
+ VOID
+ );
+
+VOID
+HalpFlushKeyboardBuffer (
+ VOID
+ );
+
+VOID
+HalpWaitForKeyPress (
+ VOID
+ );
+typedef
+ULONG
+(*PFW_INITIALIZE_VIDEO_CALLBACK) (
+ OUT ULONG AlphaVideoType
+ );
+
+
+//
+// Define static data.
+//
+
+BOOLEAN HalpDisplayInitialized = FALSE;
+BOOLEAN HalpDisplayOwnedByHal;
+ULONG HalpColumn;
+ULONG HalpRow;
+PUCHAR HalpDestination;
+ULONG HalpForegroundColor;
+ULONG HalpBackgroundColor;
+ULONG DisplayWidth;
+ULONG DisplayHeight;
+ULONG MaxRow;
+ULONG MaxColumn;
+
+#define CONTROL_SEQUENCE_MAX_PARAMETER 10
+ULONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+//
+// Declare externally defined data.
+//
+// none.
+
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes and clears the display.
+
+ This is called during phase 0 of the Hal initialization.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize static data.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (InitializeDisplay() == TRUE) {
+
+ //
+ // Mark the display as successfully initialized.
+ //
+
+ HalpDisplayInitialized = TRUE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+InitializeDisplay (
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes and clears the display.
+
+ It is initialized to: alphanumeric mode, 16 colors fore & background,
+ 8x16 pixel fonts, 80x25 characters, 640 x 400 display.
+ This is not ARC compliant (no underline, no monochrome support)
+ but its good enough for now and can be enhanced later. (For booting,
+ the ARC spec is overkill anyway.)
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the video was initialized, TRUE is returned, otherwise FALSE
+
+--*/
+
+{
+ ULONG UnusedParameter;
+ PARC_DISPLAY_STATUS DisplayStatus;
+ char String[16];
+
+ //
+ // Initialize static data.
+ //
+
+ HalpForegroundColor = FW_COLOR_HI_WHITE;
+ HalpBackgroundColor = FW_COLOR_BLUE;
+
+ DisplayStatus = ArcGetDisplayStatus(ARC_CONSOLE_OUTPUT);
+ DisplayWidth = DisplayStatus->CursorMaxXPosition;
+ DisplayHeight = DisplayStatus->CursorMaxYPosition;
+
+ MaxRow = DisplayHeight -1;
+ MaxColumn = DisplayWidth -1;
+
+ //
+ // [ecr] Call the video driver to intialize the video display,
+ // if it has supplied a reset routine.
+ //
+
+ if (HalpResetDisplayParameters) {
+ HalpDisplayOwnedByHal = HalpResetDisplayParameters(MaxColumn+1, MaxRow+1);
+ }
+
+ //
+ // [jrm] Call the firmware to initialize the video display.
+ //
+
+ VenVideoDisplayInitialize(&UnusedParameter);
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ //
+ // Set the video memory to blue.
+ //
+
+ sprintf(String, "%c%dm%c%2J", ASCII_CSI, HalpBackgroundColor+40,
+ ASCII_CSI);
+ VenPrint(String);
+
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ HalpResetDisplayParameters=ResetDisplayParameters;
+
+ //
+ // Reset the display to begin in the upper left corner.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+
+ return;
+}
+
+VOID
+HalpVideoReboot(
+ VOID
+ )
+{
+
+ if (HalpResetDisplayParameters && !HalpDisplayOwnedByHal) {
+
+ //
+ // Video work-around. The video driver has a reset function,
+ // call it before resetting the system in case the bios doesn't
+ // know how to reset the display's video mode.
+ //
+#if HALDBG
+ DbgPrint("HalpVideoReboot: calling HalpResetDisplayParameters (%x,%x)\n",
+ MaxColumn+1, MaxRow+1);
+#endif
+
+ HalpResetDisplayParameters(MaxColumn+1, MaxRow+1);
+ }
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Note that the MIPS version of this routine goes through mapping
+ // the device into the users space; since we have reserved the top
+ // PDE in system space, we dont have to do this - its always mapped.
+ //
+
+ //
+ // Check if the display has already been successfully initialized.
+ // If it has not then we cannot print on the display.
+ //
+
+ if( HalpDisplayInitialized != TRUE ){
+
+#if (DBG) || (HALDBG)
+
+ DbgPrint( "HDS: %s\n", String );
+
+#endif //DBG || HALDBG
+
+ return;
+
+ }
+
+ //
+ // Raise the IRQL to dispatch level and acquire the display adapter lock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ InitializeDisplay();
+ }
+
+ while (*String)
+ {
+ switch (*String)
+ {
+ case '\n':
+ if (HalpRow == MaxRow-1-1) {
+ HalpScrollDisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+ break;
+
+ case '\b':
+ if(HalpColumn != 0) {
+ --HalpColumn;
+ }
+ break;
+
+ case '\r':
+ HalpColumn = 0;
+ break;
+
+ default:
+ if (HalpColumn > MaxColumn)
+ {
+ if (HalpRow == MaxRow-1-1) {
+ HalpScrollDisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+ }
+ HalpDisplayCharacter(*String);
+ HalpColumn++;
+ }
+ ++String;
+ }
+
+ //
+ // Release the display adapter lock and restore the IRQL.
+ //
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = DisplayWidth;
+ *HeightInLines = DisplayHeight;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > DisplayWidth) {
+ CursorColumn = DisplayWidth;
+ }
+
+ if (CursorRow > DisplayHeight) {
+ CursorRow = DisplayHeight;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer.
+
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ char String[16];
+
+ sprintf(String, "%c%d;%dH%c%d;%dm%c",
+ ASCII_CSI, HalpRow+1, HalpColumn+1,
+ ASCII_CSI, HalpForegroundColor+30, HalpBackgroundColor+40,
+ Character);
+ VenPrint(String);
+
+}
+
+
+VOID
+HalpScrollDisplay (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scrolls the display up one line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ char String[16];
+
+ //
+ // Force a FwScrollDisplay by positioning FwRow off the
+ // bottom of the screen and then doing a line feed.
+ //
+
+ sprintf(String, "%c%dB%c", ASCII_CSI, 255, ASCII_LF);
+ VenPrint(String);
+
+}
diff --git a/private/ntos/nthals/halast/drivesup.c b/private/ntos/nthals/halast/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halast/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halast/hal.rc b/private/ntos/nthals/halast/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halast/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halast/hal.src b/private/ntos/nthals/halast/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halast/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halast/i386/astclock.asm b/private/ntos/nthals/halast/i386/astclock.asm
new file mode 100644
index 000000000..9f02059f9
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astclock.asm
@@ -0,0 +1,578 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1992 AST Research Inc.
+;
+; Module Name:
+;
+; astclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT. It works on UP and SystemPro.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Quang Phan (v-quangp) 11-Aug-1992
+; Convert to ASTMP system. All processors receive interrupts from the
+; system clock and profile interrupts. Added support for the CPU leds.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\astmp.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalRequestIpi,1
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ extrn _HalpSystemHardwareLock:DWORD
+ EXTRNP _DisplPanel,1
+ extrn _HalpIRQLtoVector:BYTE
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193182
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_STATUS_BUSY EQU 80H ; Time update in progress
+RTC_OFFSET_SECOND EQU 0 ; second field of RTC memory
+RTC_OFFSET_MINUTE EQU 2 ; minute field of RTC memory
+RTC_OFFSET_HOUR EQU 4 ; hour field of RTC memory
+RTC_OFFSET_DAY_OF_WEEK EQU 6 ; day-of-week field of RTC memory
+RTC_OFFSET_DATE_OF_MONTH EQU 7 ; date-of-month field of RTC memory
+RTC_OFFSET_MONTH EQU 8 ; month field of RTC memory
+RTC_OFFSET_YEAR EQU 9 ; year field of RTC memory
+RTC_OFFSET_CENTURY EQU 32h ; Century field of RTC memory
+
+;
+; ==== Values used for System Clock ====
+;
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec.
+;
+; The best fit value closest to 10ms (but not below) is 10.0144012689ms:
+; ROLLOVER_COUNT 11949
+; TIME_INCREMENT 100144
+; Calculated error is -.0109472 s/day
+;
+; The best fit value closest to 15ms (but not above) is 14.9952019ms:
+; ROLLOVER_COUNT 17892
+; TIME_INCREMENT 149952
+; Calculated error is -.0109472 s/day
+;
+; On 486 class machines or better we use a 10ms tick, on 386
+; class machines we use a 15ms tick
+;
+
+ROLLOVER_COUNT EQU 11949
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+
+_Halp8254Lock dd 0
+
+;
+; PerfCounter value lock. locks access to the HalpPerfCounterLow/High vars.
+;
+
+_HalpPerfCounterLock dd 0
+
+ public HalpPerfCounterLow
+ public HalpPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpPerfCounterInit dd 0
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0
+;
+; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock,0
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov ecx, ROLLOVER_COUNT
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+
+;
+; Fill in PCR value with TIME_INCREMENT
+;
+ mov edx, TIME_INCREMENT
+ stdCall _KeSetTimeIncrement, <edx, edx>
+
+ mov HalpPerfCounterInit, 1 ; Indicate performance counter
+ ; has been initialized.
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter,1
+
+ push ebx
+ push esi
+
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before 8254
+; initialization has occured. Reading garbage off the 8254 is not reasonable.
+;
+ cmp HalpPerfCounterInit, 0
+ jne Kqpc01 ; ok, perf counter has been initialized
+
+;
+; Initialization hasn't occured yet, so just return zeroes.
+;
+ mov eax, 0
+ mov edx, 0
+ jmp Kqpc20
+
+Kqpc01:
+Kqpc11: pushfd
+ cli
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+endif
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+; NOTE:
+; Need to watch for Px reading the 'CounterLow', P0 updates both
+; then Px finishes reading 'CounterHigh' [getting the wrong value].
+; After reading both, make sure that 'CounterLow' didn't change.
+; If it did, read it again. This way, we won't have to use a spinlock.
+;
+
+@@:
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+ cmp ebx, HalpPerfCounterLow ;
+ jne @b
+;
+; Fetch the current counter value from the hardware
+;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+endif
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+ jmp $+2
+
+
+;
+; Fetch the base value again.
+;
+
+@@:
+ mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+
+ cmp eax, HalpPerfCounterLow
+ jne @b
+
+;
+; Compare the two reads of Performance counter. If they are different,
+; simply returns the new Performance counter. Otherwise, we add the hardware
+; count to the performance counter to form the final result.
+;
+
+ cmp eax, ebx
+ jne short Kqpc20
+ cmp edx, esi
+ jne short Kqpc20
+ neg ecx ; PIT counts down from 0h
+ add ecx, ROLLOVER_COUNT
+ add eax, ecx
+ adc edx, 0 ; [edx:eax] = Final result
+
+;
+; Return the counter
+;
+
+Kqpc20:
+ ; return value is in edx:eax
+
+;
+; Return the freq. if caller wants it.
+;
+
+ or dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc99 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc99:
+ pop esi ; restore esi and ebx
+ pop ebx
+ stdRET _KeQueryPerformanceCounter
+
+ifndef NT_UP
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc11>
+endif
+
+stdENDP _KeQueryPerformanceCounter
+
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ mov eax, [esp+4] ; ponter to Number
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ ;
+ ; Nothing to calibrate on a AST MP machine. There is only a single
+ ; 8254 device
+ ;
+
+ popfd ; restore interrupt flag
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; dismiss interrupt and raise Irql
+;
+
+ movzx eax,_HalpIRQLtoVector[CLOCK2_LEVEL]
+ push eax
+ sub esp, 4 ; allocate space to save OldIrql
+
+; esp - OldIrql
+ stdCall _HalBeginSystemInterrupt,<CLOCK2_LEVEL,eax,esp>
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; Update performance counter
+;
+ cmp fs:PcHal.PcrEBI2ProcessorID, 0
+ jnz short @f
+
+ add HalpPerfCounterLow, ROLLOVER_COUNT ; update performace counter
+ adc HalpPerfCounterHigh, 0
+
+@@:
+;
+; Check for Idle state and log processor state to the front panel CPU leds.
+;
+ inc fs:PcHal.PcrCpuLedRateCount
+ cmp fs:PcHal.PcrCpuLedRateCount, CpuLedSamplingRate
+ jne Hci010 ; Don't update LED yet
+ mov fs:PcHal.PcrCpuLedRateCount,0 ;reset rate count
+ mov edx, fs:PcPrcb
+ mov eax, [edx].PbIdleThread
+ cmp eax, [edx].PbCurrentThread
+ je ProcIdle
+ CALL_EBI2 LogProcBusy,1
+ jmp Hci010
+ProcIdle:
+ CALL_EBI2 LogProcIdle,1
+
+Hci010:
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; (ebp) = address of trap frame
+; (eax) = time increment
+;
+ mov eax, TIME_INCREMENT
+
+ cmp fs:PcHal.PcrEBI2ProcessorID, 0 ; is this the master cpu?
+ je _KeUpdateSystemTime@0 ; if it is, update system time
+
+ sti
+ stdCall _KeUpdateRunTime,<dword ptr [esp]> ; othewise update runtime
+
+ INTERRUPT_EXIT ; lower irql to old value, iret
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpClockInterrupt
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, TIME_INCREMENT
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+
+
+_TEXT ends
+ end
+
diff --git a/private/ntos/nthals/halast/i386/astdetct.c b/private/ntos/nthals/halast/i386/astdetct.c
new file mode 100644
index 000000000..cf2c00e90
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astdetct.c
@@ -0,0 +1,169 @@
+/*++
+
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ astdetct.c
+
+Abstract:
+
+
+Author:
+
+ Bob Beard (v-bobb) 24-Jul-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Bob Beard (v-bobb) 19-Aug-1992 detect if MP
+ Quang Phan (v-quangp) 27-Aug-1992 modified to work with the NT Setup
+ program.
+
+--*/
+
+#ifndef _NTOS_
+#include "nthal.h"
+#endif
+
+#include "halp.h"
+#include "astebiii.h"
+
+#define AST_MANUFACTURER_ID 0x0674
+#define AST_EBI2_STRING 0x32494245
+
+ULONG ProcCount;
+//#define MAX_EBI_SLOTS 32L
+//VOID* EBI2_MMIOTable[MAX_EBI_SLOTS];
+
+//
+// EBI_II function offset table
+//
+
+EBI_II EBI2_CallTab;
+
+//
+// Global pointer to BIOS
+//
+
+PVOID BiosPtr;
+
+BOOLEAN
+GetProcCount()
+/*++
+
+Routine Description:
+ Call EBI2 to get the number of processors in the system.
+ To make this call work with the NT current Setup environment,
+ (memory address limited to 16MB), a fake MMIOTable is passed to EBI.
+ ProcCount contains the number of processors in the system.
+
+Arguments:
+ none.
+
+Return Value:
+ True if successfully initialized. False otherwise.
+
+--*/
+{
+
+ULONG i;
+ULONG *Alias = (ULONG *)&EBI2_CallTab;
+ebi_iiSig *Sig = (ebi_iiSig*)((ULONG)BiosPtr + EBI_II_SIGNATURE);
+ULONG *OffTab;
+
+//
+// Build the EBI II offset table
+//
+
+ OffTab =(ULONG *) ((ULONG)BiosPtr + (REAL_TO_LIN(Sig->seg,Sig->off) -
+ REAL_TO_LIN(BIOS_SEG, 0)));
+ for( i = 0; i < ( sizeof( offsetTable ) / sizeof( ULONG )); i++ )
+ Alias[i] = OffTab[i] + (ULONG)BiosPtr;
+
+//
+// Find out the number of good processors
+//
+
+if ( (EBI2_CallTab.GetNumProcs)( (VOID *) 0, &ProcCount ) )
+ return(FALSE);
+
+ return(TRUE);
+}
+
+
+
+ULONG
+DetectAST(
+ OUT PBOOLEAN IsConfiguredMp
+)
+/*++
+
+Routine Description:
+ Determine on which AST platform we are running. Special HAL is needed
+ for EBI II based AST machines.
+
+Arguments:
+ PBOOLEAN IsConfiguredMp returns with value of TRUE if MP. FALSE if
+ UP.
+
+Return Value:
+ Boolean that indicates if AST EBI II platform is detected. TRUE means
+ an AST EBI II platform was detected. FALSE indicates it was not.
+
+
+--*/
+{
+
+USHORT ManufacturerId;
+PULONG EBI2StringPtr;
+ULONG ProcCount;
+UCHAR ProductId;
+
+//
+// Read the EISA ManufactuerID and check for AST
+//
+
+ManufacturerId = (((USHORT)(READ_PORT_UCHAR((PUCHAR)0xc80))) << 8)
+ | (READ_PORT_UCHAR((PUCHAR)0xc81));
+if (ManufacturerId != AST_MANUFACTURER_ID)
+ return(FALSE);
+
+//
+//This HAL works with Manhattans that have EISA's ProductId 0x40-0x4F.
+//
+
+ProductId = ((READ_PORT_UCHAR((PUCHAR)0xc82)));
+if ((ProductId & 0xF0) != 0x40)
+ return(FALSE);
+
+//
+// Map in all of AST BIOS for EBI II calls
+//
+
+BiosPtr = (PVOID)((ULONG)REAL_TO_LIN( BIOS_SEG, 0 ));
+BiosPtr = HalpMapPhysicalMemory(BiosPtr, 0x10000/PAGE_SIZE); // assumes PAGE_SIZE <= 64k
+if (BiosPtr == NULL)
+ return(FALSE);
+
+EBI2StringPtr = (PULONG)((ULONG)BiosPtr + EBI_II_SIGNATURE);
+if (*EBI2StringPtr != AST_EBI2_STRING)
+ return(FALSE);
+
+//
+// Call EBI II to get num. of processors
+//
+if (!GetProcCount())
+ return(FALSE);
+
+//
+// This is an MP hal
+//
+
+ *IsConfiguredMp = TRUE;
+
+return(TRUE);
+}
diff --git a/private/ntos/nthals/halast/i386/astdisp.h b/private/ntos/nthals/halast/i386/astdisp.h
new file mode 100644
index 000000000..36a78f35c
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astdisp.h
@@ -0,0 +1,59 @@
+/*++
+
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ astdisp.h
+
+Abstract:
+
+ Display codes for debugging of AST HAL and AST EBI errors.
+
+Author:
+
+ Bob Beard (v-bobb) 25-Jul-1992
+
+Environment:
+
+
+Revision History:
+
+--*/
+
+VOID DisplPanel(ULONG x);
+
+#ifdef BBTEST
+// Debugging codes 0x00 - 0x9f
+#define HALEnterDetect 0x01
+#define HALASTMachineDetected 0x02
+#define HALBIOSMappedOK 0x03
+#define HALBIOSSignatureOK 0x04
+
+#define HALEnterEBIInit 0x05
+#define HALInitMMIOTable 0x06
+#define HALExitEBIInit 0x07
+
+#define HALInitIpi 0x08
+#define HALInitIpiExit 0x09
+#define HALDoRequestIPI 0x0a
+#define HALInitInterrupts 0x0b
+#define HALEnterASTHAL 0x0c
+#define HALExitASTHAL 0x0d
+#define HALEnterInitMp 0x0e
+#endif
+
+// Error codes 0xa0 - 0xff
+#define HALSlotProblem 0xa0
+#define HALMMIOProblem 0xa1
+#define HALPhysicalAllocProblem 0xa2
+#define HALEBIInitProblem 0xa3
+#define HALEBIGetProcProblem 0xa4
+#define HALEBINoProcsProblem 0xa5
+#define HALMemoryProblem 0xa6
+#define HALIpiInitVecProblem 0xa7
+#define HALIpiInitIDProblem 0xa8
+#define HALIntSubsystemProblem 0xa9
+#define HALCacheEnableProblem 0xaa
+#define HALSpiInitVecProblem 0xab
+#define HALGetRevisionProblem 0xac
diff --git a/private/ntos/nthals/halast/i386/astebi.c b/private/ntos/nthals/halast/i386/astebi.c
new file mode 100644
index 000000000..95903b5a5
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astebi.c
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ astebi.c
+
+Abstract:
+
+ NT HAL to AST EBI2 translation file. This file contains routines that
+ convert NT HAL calls to AST EBI2 calls.
+
+Author:
+
+ Bob Beard (v-bobb) 24-Jul-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+ Quang Phan (v-quangp) 27-Aug-1992: Moved DisplPanel from astdetct.c
+ into to this module because astdetct is also used for the NT setup
+ program.
+
+--*/
+
+#include "halp.h"
+#include "astebiii.h"
+#include "astdisp.h"
+
+extern VOID* EBI2_MMIOTable[];
+extern EBI_II EBI2_CallTab;
+
+#define IRQ0_VECTOR_BASE PRIMARY_VECTOR_BASE
+#define ALL_IRQS (0x0000fffb)
+#define ALL_PROCS (0xffffffff)
+
+static UCHAR hex_to_asc(SHORT x)
+{
+ return(x < 0xa ? x+'0' : x-10+'A');
+}
+
+
+VOID
+HalpInitializePICs()
+/*++
+
+Routine Description:
+ Initialize the AST Interrupt environment. Called once by P0 during
+ Phase 0.
+
+Arguments:
+ none.
+
+Return Value:
+ NONE
+
+--*/
+{
+
+ dWord subsystemType;
+
+ //
+ // Turn off all interrupts while setting the interrupt environment
+ //
+
+ _asm pushfd
+ _asm cli
+
+ //
+ // Check to see the type of interrupt subsystem
+ //
+
+ EBI2_CallTab.GetIntSubsysType( EBI2_MMIOTable, &subsystemType );
+ if ( subsystemType != EBI_INT_SUBSYS_ADI)
+ DisplPanel(HALIntSubsystemProblem);
+
+ //
+ // Set the IRQ vectors 0 & 8
+ //
+
+ if ( EBI2_CallTab.SetIRQVectorAssign( EBI2_MMIOTable, 0, IRQ0_VECTOR_BASE) )
+ DisplPanel(HALIntSubsystemProblem);
+ if ( EBI2_CallTab.SetIRQVectorAssign( EBI2_MMIOTable, 8, IRQ0_VECTOR_BASE+8) )
+ DisplPanel(HALIntSubsystemProblem);
+
+ //
+ // Mask off all Interrupts for All Processors Globally
+ // ( Except chain interrupt, IPI and SPI )
+ //
+
+ if ( EBI2_CallTab.SetGlobalIntMask( EBI2_MMIOTable, ALL_IRQS) )
+ DisplPanel(HALIntSubsystemProblem);
+
+ //
+ // Switch to Distributed Interrupt Handling
+ //
+
+ EBI2_CallTab.SetAdvIntMode( EBI2_MMIOTable );
+
+ //
+ // Cancel all pending interrupts (except IPI and SPI)
+ //
+
+ if ( EBI2_CallTab.CancelInterrupt( EBI2_MMIOTable, ALL_IRQS, ALL_PROCS) )
+ DisplPanel(HALIntSubsystemProblem);
+
+ //
+ // Return interrupts to entry state
+ //
+
+ _asm popfd
+
+}
+
+
+VOID
+ASTEnableCaches()
+/*++
+
+Routine Description:
+ Enable the internal and external caches of the processor that calls
+ this routine.
+
+Arguments:
+ none.
+
+Return Value:
+ NONE
+
+--*/
+{
+
+ if ( EBI2_CallTab.DisableRAMCache( EBI2_MMIOTable ) )
+ DisplPanel(HALCacheEnableProblem);
+
+ if ( EBI2_CallTab.EnableRAMCache( EBI2_MMIOTable ) )
+ DisplPanel(HALCacheEnableProblem);
+
+}
+
+
+VOID
+DisplPanel(ULONG x)
+/*++
+
+Routine Description:
+ Display 2 hex digits on front panel of AST Manhattan. All digits
+ are preceded by a "H " (H blank) to indicate HAL output.
+
+Arguments:
+ A SHORT value to output as hex digits.
+
+Return Value:
+ none.
+
+--*/
+{
+UCHAR digit1,digit2;
+
+#define DISP_ADR (PUCHAR) 0xec
+#define DISP_DAT (PUCHAR) 0xed
+
+ digit1 = hex_to_asc((SHORT)((x & 0xf0) >> 4));
+ digit2 = hex_to_asc((SHORT)(x & 0x0f));
+
+// digit 4
+ WRITE_PORT_UCHAR(DISP_ADR, 7);
+ WRITE_PORT_UCHAR(DISP_DAT, 'H');
+// digit 3
+ WRITE_PORT_UCHAR(DISP_ADR, 6);
+ WRITE_PORT_UCHAR(DISP_DAT, ' ');
+// digit 2
+ WRITE_PORT_UCHAR(DISP_ADR, 5);
+ WRITE_PORT_UCHAR(DISP_DAT, digit1);
+// digit 1
+ WRITE_PORT_UCHAR(DISP_ADR, 4);
+ WRITE_PORT_UCHAR(DISP_DAT, digit2);
+}
diff --git a/private/ntos/nthals/halast/i386/astebi2.inc b/private/ntos/nthals/halast/i386/astebi2.inc
new file mode 100644
index 000000000..3f8343327
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astebi2.inc
@@ -0,0 +1,1227 @@
+;
+;~~~
+; 06/16/92 Added an error message and few equates to help
+; with the UPS LED translation.
+;
+;~~~
+; 06/08/92 Updating EBI II to meet the 2.8 EBI II specification.
+; Adding Multi-threading support for EBI II
+;
+;~~~
+; 5/21/92 Reved version of EBI implementation to 2.8
+; Support for specific EOI.
+; A number of new equates.
+;
+;~~~
+; 4/28/92 MPX updates.
+;
+; Added IRQ0_Vector and IRQ8_Vector to EBI 2 memory
+; structure.
+;
+; created a macro EDI_EBI_MEM_ADD
+;
+; Added an IPI_ID_Valid_Mask
+;
+;~~~
+;
+; 4/17/92
+;
+; Added Bios Time out Bit mask in NMICR
+; Added SMEARRegister entry to the EBI 2 memory structure.
+;
+;~~~
+; 4/15/92 Coding OEM0 function to help NMI generation and
+; debugging.
+;
+;~~~
+; 4/13/92 Updating this module to reflect the new EBI II Spec rel
+; 2.7.
+; All functions will be re-arranged. This file will
+; contain all EBI II functions need for the SCO EFS
+; Implementation. Refer to EBI2STAT.DOC for a
+; condensed list of these functions.
+;
+;~~~
+; 4/2/92 Added more equates, new error messages.
+;
+;~~~
+; 3/20/92 Added new equates and MemTable_To_Edi macro
+;
+;~~~
+; 3/16/92 Adding more EBI 2 functionality to support the SCO
+; EFS implementation.
+;~~~
+
+
+;*****************************************************************************
+; Compilation debugging switches
+;*****************************************************************************
+;SIMULATE_MANHATTAN EQU 1
+;SIMULATE_MPSYSTEM EQU 1
+;FAKE_MMIOTABLE EQU 1
+DELETED_FUNCTIONS EQU 1 ;a flag to not compile the functions
+ ;that were in an older rev of the
+ ;EBI II spec but no longer are
+ ;needed.
+;UGLY EQU 1
+
+;*****************************************************************************
+; Declare Equates
+;*****************************************************************************
+
+;
+;Equates for the AST OEM call Set_Irq13_Latch
+;
+
+SET_IRQ13_LATCH equ 6 ;subfunc#
+IRQ13_LATCH_ON equ 1
+IRQ13_LATCH_OFF equ 0
+
+;
+; The structure and the definitions for the new local int mask call
+;
+
+PORT_TYPE_MASK equ 3
+PORT_TYPE_MEMORY equ 0
+PORT_TYPE_IO equ 1
+
+PORT_WIDTH_MASK equ 01CH
+EIGHT_BIT_PORTS equ 000H
+SIXTEEN_BIT_PORTS equ 004H
+THIRTY_TWO_BIT_PORT equ 008H
+
+;Function return successfull codes.
+OK equ 0
+PROC_RUNNING equ 1
+PROC_STOPPED equ 2
+PROC_NO_CACHE equ 3
+NO_MEMORY_ERRORS EQU 4 ;No RAM errors were found
+MEMORY_ERRORS_FOUND EQU 5 ;Hardware detected a RAM error.
+WRONG_GRAPH_MODE EQU 6 ;can not write to Graph Mode in this mode.
+
+;Function return ERROR codes
+ERR_BAD EQU 0FFFFFFFFH ;-1
+ERR_NOT_SUPPORTED EQU 0FFFFFFFEH ;-2
+ERR_NONESUCH EQU 0FFFFFFFDH ;-3
+ERR_BAD_PROC_ID EQU 0FFFFFFFCH ;-4
+ERR_PROC_ABSENT EQU 0FFFFFFFBH ;-5
+ERR_PROC_BAD EQU 0FFFFFFFAH ;-6
+ERR_UNKNOWN_INT EQU 0FFFFFFF9H ;-7
+ERR_DISPLAY_OVERFLOW EQU 0FFFFFFF8H ;-8
+ERR_BAD_CHARS EQU 0FFFFFFF7H ;-9
+ERR_BAD_SELECTOR EQU 0FFFFFFF6H ;-10
+ERR_BAD_CACHE_MODE EQU 0FFFFFFF5H ;-11
+ERR_BAD_VECTOR EQU 0FFFFFFF4H ;-12
+ERR_BAD_COLOR EQU 0FFFFFFF3H ;-13
+ERR_BAD_GRAPH_MODE EQU 0FFFFFFF2H ;-14
+ERR_BAD_BOARD_NUM EQU 0FFFFFFF1H ;-15
+ERR_BAD_MODULE_NUM EQU 0FFFFFFF0H ;-16
+ERR_BAD_IRQ_NUM EQU 0FFFFFFEFH ;-17
+ERR_BAD_OFFSWITCH EQU 0FFFFFFEEH ;-18
+ERR_BAD_PHYS_ADDR EQU 0FFFFFFEDH ;-19
+ERR_BAD_LENGTH EQU 0FFFFFFECH ;-20
+ERR_BAD_BLOCK_NUM EQU 0FFFFFFEBH ;-21
+ERR_BAD_GLOB_MASK_IRQ EQU 0FFFFFFEAH ;-22
+ERR_BAD_LOC_MASK_IRQ EQU 0FFFFFFE9H ;-23
+ERR_CANT_CANCEL_INT EQU 0FFFFFFE8H ;-24
+ERR_PROC_STILL_RUNNING EQU 0FFFFFFE7H ;-25
+ERR_BAD_POWER_SUPPLY_NUM EQU 0FFFFFFE6H ;-26
+ERR_BAD_FRONT_PANEL_MODE EQU 0FFFFFFE5H ;-27
+ERR_MULTI_TIME_OUT EQU 0FFFFFFE4H ;-28
+ERR_FRONT_PANEL_DISABLED EQU 0FFFFFFE3H ;-29
+
+;OEM function error return codes
+OEM0_ERR_BAD_EISA_REF EQU 0FFFF0000H ; 0
+OEM0_ERR_BAD_COM2_OVERRIDE EQU 0FFFEFFFFH ; 1
+OEM0_ERR_BAD_GEN_MULTIBIT EQU 0FFFEFFFEH ; 2
+OEM0_ERR_BAD_GEN_SINGLEBIT EQU 0FFFEFFFDH ; 3
+OEM0_ERR_BAD_IRQ13_LATCH EQU 0FFFEFFFCH ; 4
+OEM0_ERR_BAD_CACHE_MODE EQU 0FFFEFFFBH ; 5
+
+;OEM completion codes.
+OEM0_INFO_BANK_ABSENT EQU 10000 ;0
+
+;ERR_BAD EQU 0FFFFFFFFH ;-1
+;ERR_NOT_SUPPORTED EQU 0FFFFFFFEH ;-2
+;ERR_NONESUCH EQU 0FFFFFFFDH ;-3
+;ERR_INVALID_PROC_ID EQU 0FFFFFFFCH ;-4
+;ERR_PROC_ABSENT EQU 0FFFFFFFBH ;-5
+;ERR_PROC_BAD EQU 0FFFFFFFAH ;-6
+;ERR_UNKNOWN_NMI EQU 0FFFFFFF9H ;-7
+;ERR_DISPLAY_OVERFLOW EQU 0FFFFFFF8H ;-8
+;ERR_BAD_CHARS EQU 0FFFFFFF7H ;-9
+;ERR_BAD_SELECTOR EQU 0FFFFFFF6H ;-10
+;ERR_BAD_CACHE_MODE EQU 0FFFFFFF5H ;-11
+;ERR_BAD_VECTOR EQU 0FFFFFFF4H ;-12
+;ERR_BAD_COLOR EQU 0FFFFFFF3H ;-13
+;ERR_BAD_GRAPH_MODE EQU 0FFFFFFF2H ;-14
+;ERR_INVALID_BOARD_NUM EQU 0FFFFFFF1H ;-15
+;ERR_INVALID_MODULE_NUM EQU 0FFFFFFF0H ;-16
+;ERR_INVALID_IRQ_NUM EQU 0FFFFFFEFH ;-17
+;ERR_INVALID_OFFSWITCH_MODE EQU 0FFFFFFEEH ;-18
+;ERR_INVALID_PHYS_ADR EQU 0FFFFFFEDH ;-19
+;ERR_INVALID_LENGTH EQU 0FFFFFFECH ;-20
+;ERR_INVALID_BLOCK_NUM EQU 0FFFFFFEBH ;-21
+;ERR_INVALID_GLOB_MASK_IRQ EQU 0FFFFFFEAH ;-22
+;ERR_INVALID_LOC_MASK_IRQ EQU 0FFFFFFE9H ;-23
+;ERR_CANT_CANCEL_INT EQU 0FFFFFFE8H ;-24
+;ERR_INVALID_EISA_REF EQU 0FFFFFFE7H ;-25
+;ERR_INVALID_COM2_OVER EQU 0FFFFFFE6H ;-26
+;ERR_INVALID_GEN_MULTI EQU 0FFFFFFE5H ;-27
+;ERR_INVALID_GEN_SINGLE EQU 0FFFFFFE4H ;-28
+;ERR_INVALID_IRQ13_LATCH EQU 0FFFFFFE3H ;-29
+
+;NMI and SPI SOURCE equates
+NMI_SRC_NONE EQU 0 ;No source was found
+;1 is reserved.
+NMI_SRC_LOCALSOFTNMI EQU 2 ;Software generated NMI
+NMI_SRC_MEM EQU 3 ;Memory Double bit ECC error
+NMI_SRC_PROCESSOR EQU 4 ;PROCESSOR error.
+;5 is reserved.
+NMI_SRC_SYS_PARITY EQU 6 ;System bus Parity, address or data
+NMI_SRC_SYS_TIMEOUT EQU 7 ;System bus timeout.
+NMI_SRC_SHUTDOWN EQU 8 ;Shutdown Button.
+NMI_SRC_ATTENTION EQU 9 ;Attention Button.
+NMI_SRC_POWERFAIL EQU 0AH ;Power Fail.
+NMI_SRC_EISA_FAIL_SAFE EQU 0BH ;Eisa Fail safe timer error
+NMI_SRC_EISA_BUSTIMEOUT EQU 0CH ;EISA Bus timeout
+NMI_SRC_EISA_IOCHECK EQU 0DH ;EISA IO Check
+NMI_SRC_EISA_SWGEN EQU 0EH ;EISA software generated NMI
+NMI_SRC_SYS_IO EQU 0FH ;System I/O error
+
+NMI_SRC_MASK EQU 7 ;Mask for bits 0 - 2.
+
+;Interrupt Subsystem Type
+INT_SUBSYS_EISA EQU 0 ;EISA interrupt subsystem type.
+INT_SUBSYS_ISA EQU 1 ;ISA interrupt subsystem type.
+INT_SUBSYS_ADI EQU 2 ;ADI interrupt subsystem type.
+INT_SUBSYS_MPIC EQU 3 ;MPIC interrupt subsystem type.
+
+INT_MODE_BYPASS EQU 1 ;Bypass mode flag.
+INT_MODE_ADI EQU 2 ;Advanced Distributed int. mode
+
+IVR_0_ADR EQU 20H ;I/O port for 8259 Init. Master.
+IVR_8_ADR EQU 0A0H ;I/O port for 8259 Init. Slave.
+IVR_0_EISA_ADR EQU 4D0H ;EISA 8259 I/O port for Master.
+IVR_8_EISA_ADR EQU 4D1H ;EISA 8259 I/O port for Slave.
+IMR_0_ADR EQU 21H ;I/O port address for IRQ 0 - 7
+IMR_8_ADR EQU 0A1H ;I/O prot address for IRQ 8 - 15
+IRQ_MAX EQU 15 ;Highest IRQ number supported.
+ICW1_MASK EQU 11H ;8259 ICW1 settings. Cascade Mode
+ICW3_MASK_MASTER EQU 4 ;8259 ICW3 settings. Slave is on IRQ2
+ICW3_MASK_SLAVE EQU 2 ;8259 ICW3 settings. Slave ID
+ICW4_MASK EQU 1 ;8259 ICW4 settings. 8086 mode, Normal
+ ;EOI, fully nested mode, non buffered.
+
+OCW2_MASK EQU 60H ;Specific EOI Mask, bit 0-2 should
+ ;be the irq number.
+IRQ2_EOI_MASK EQU 62H ;Mask command to EOI IRQ 2.
+READ_ISR_COM EQU 0BH ;command to 8259 to read ISR
+READ_IRR_COM EQU 0AH ;command to 8259 to read IRR
+
+MAX_SPI_VECTOR EQU 255 ;Maximum SPI Vector number currently
+ ;supported by our hardware.
+MAX_IPI_VECTOR EQU 255 ;Maximum IPI Vector number currently
+ ;supported by our hardware.
+
+;EISA EOI registers
+NMISTATUSREG EQU 61H
+MIENABLEREG EQU 70H
+EXTENDEDNMIREG EQU 461H
+
+;
+
+;Bit positions.
+BIT_0 EQU 01H
+BIT_1 EQU 02H
+BIT_2 EQU 04H
+BIT_3 EQU 08H
+BIT_4 EQU 10H
+BIT_5 EQU 20H
+BIT_6 EQU 40H
+BIT_7 EQU 80H
+BIT_8 EQU 0100H
+BIT_9 EQU 0200H
+BIT_10 EQU 0400H
+BIT_11 EQU 0800H
+BIT_12 EQU 1000H
+BIT_13 EQU 2000H
+BIT_14 EQU 4000H
+BIT_15 EQU 8000H
+
+ ;The Bits that are set(1) indicated that such an interrupt
+ ;is supported in the Interrupt Mask Bitmap Definition.
+LOCAL_INT_VALID_MASK EQU 0700FFFFH
+GLOBAL_INT_VALID_MASK EQU 0000FFFFH
+CANCEL_INT_VALID_MASK EQU 0100FFFFH
+
+IRQ0_IRQ15_MASK EQU 0000FFFFH
+IPI_ID_VALID_MASK EQU 0FFFFFF00H
+SPI_INT_MASK EQU 01000000H
+LSI_INT_MASK EQU 02000000H
+IPI_INT_MASK EQU 04000000H
+CLRSPI EQU BIT_2 ;clear SPI bit in ICR regs.
+ ;bit definition in the ADI for ISR and IRR for following Interrupts.
+LSI_ADI_IR_BIT EQU BIT_5
+LSI_ADI_IS_BIT EQU BIT_5
+IPI_ADI_IR_BIT EQU BIT_6
+IPI_ADI_IS_BIT EQU BIT_6
+SPI_ADI_IR_BIT EQU BIT_7
+SPI_ADI_IS_BIT EQU BIT_7
+
+TRUE EQU 01H ;Boolean True.
+FALSE EQU 00H ;Boolean False.
+
+ADIEOI_MASK EQU 40h ;bit 6 of ICR
+IGN_IPI EQU 08h ;IPI ignore bit in the ICR
+
+SWNMI EQU BIT_0 ;Software NMI bit in NMICR
+SIOEM EQU BIT_1 ;SIOEM in NMICR
+BTEM_BIT EQU BIT_2 ;BTEM in NMICR
+
+IOI_IR EQU BIT_3 ;in IRR register.
+
+BYP_BIT EQU BIT_7 ;in CMCR
+
+MASTER_BIT EQU BIT_7 ;in ICR
+
+ENABLE_INT EQU BIT_2 ;in CMCR
+
+;Type of ECC error from a memory board. This will be the values
+;returned to the caller in the memErrFlags.
+MEM_ERR_PARITY EQU 1 ;memory parity error.
+MEM_ERR_SINGLE_BIT EQU 2 ;memory single bit ECC error.
+MEM_ERR_MULTI_BIT EQU 3 ;memory Multi bit ECC error.
+MEM_ERR_INDETERMINTE EQU 0FFFFFFFFH ;-1 Info requested in indeterminate.
+INDETERMINITE EQU 0FFFFFFFFH ;-1
+
+ZERO EQU 0
+ONE EQU 1 ;Decimal One.
+TWO EQU 2
+THREE EQU 3
+FOUR EQU 4
+SIXTY4_KB EQU 10000H ;64 K Bytes.
+Sixteen_KB EQU 4000H ;16 KB bytes
+ONE_MB EQU 100000H ;1 MB.
+Eight_MB EQU 800000H ;8 MB.
+Sixteen_MB EQU 1000000H ;16 MB.
+Thirty2_MB EQU 2000000H ;32 MB.
+NEGONE EQU 0FFFFFFFFH ;-1
+
+CPUBOARD_SETABLEREGS EQU 10000H ;Offset to the CPU board
+ ;settable registers from
+ ;the base address for the
+ ;slot it currently occupies.
+MEMBOARD_SETABLEREGS EQU 10100H ;Offset to the memory board
+ ;settable registers from the base
+ ;of DISTC address.
+
+VALID_UPS_LEDCOLORS EQU 3 ;highest color setting
+VALID_OFFSWITCH_MODES EQU 1 ;highest off switch mode setting
+VALID_CACHE_CONTROL_MODES EQU 1 ;highest cache control mode setting
+VALID_FRONT_PANEL_MODES EQU 1 ;highest valid front panel modes.
+
+ENABLE_FRONT_PANEL_INT EQU 1 ;enable front panel mode command.
+
+FIRST_PAIR_SIMMS EQU 10H ;Mem Config mask indicating
+SECOND_PAIR_SIMMS EQU 20H ;which pair of SIMMS are
+THIRD_PAIR_SIMMS EQU 40H ;present on the current
+FOURTH_PAIR_SIMMS EQU 80H ;memory board.
+
+MEM_BOARD_RESERVED EQU 0 ;reseved equate for mem board
+
+CACHE_READ_ONLY equ 1 ; Selectable cache modes.
+CACHE_WRITE_THRU equ 2 ; Mode 0 is default, which
+CACHE_WRITE_BACK equ 3 ; is NOT readonly and write
+CACHE_READ_WRITE equ 4 ; back.
+
+ASCII_ALPHA_NUM_DISP equ 1 ; Code for full ASCII display.
+ASCII_ALPHA_NUM_WID equ 4 ; Number of chars on FP disp.
+ATTENTION_MASK equ 20h ; Mask for attention button.
+
+CACHE_MASK equ 0ch ; Mask for bits 2,3.
+CACHE_RDONLY_MASK equ 4 ; Mask for bit 2 of CMMS reg.
+CACHE_WR_THRU_MASK equ 8 ; Mask for bit 3 of CMMS reg.
+DISABLE_CACHE equ 60000000h ; Set bits 29, 30 of CR0.
+CACHE_MODE_VALID EQU 07H ; valid mode masks.
+CACHE_MODE_MASK EQU 1CH ; CMMS cache mode mask.
+
+EBI_2_MAJOR equ 02h ; Revision 02.08.01
+EBI_2_MINOR equ 08h ; of the EBI II Specification.
+EBI_2_ZZ equ 01h
+
+FLUSH_MODE_MASK equ 3 ; Mask for bits 0,1.
+FP_MODE_MASK equ 1 ; Mask for bit 0.
+FP_SHUTDWN equ 80h ; Bit position for shutdown.
+FP_ENABLE_SHUTDOWN EQU 40h ;bit possition for enabling shutdown
+FP_THERMAL_MASK equ 10h ; Mask for bit 4.
+MAX_FP_DIGITS equ 4 ; 4-digit ASCII display.
+MEM_MAP_IO_BASE_ADDR equ 0d0000000h ; Start of hw i/o addresses.
+MEM_MAP_IO_SIZE equ 10000000h ; Size used for hw i/o.
+MEM_MAX_BANKS equ 4 ;max # of banks per mem board.
+MP_SPECIFIC_EOI equ 60h ; Sends specific EOI to PIC.
+FP_INTMODE_DISABLED EQU 0 ;indicates front panel interr
+ ;mode is disabled.
+
+KEYLOCK_LOCKED_HW EQU 6
+KEYLOCK_SERVICE_HW EQU 5
+KEYLOCK_UNLOCK_HW EQU 3
+KEYLOCK_OFF_HW EQU 7
+
+KEYLOCK_LOCKED_SW EQU 0
+KEYLOCK_SERVICE_SW EQU 1
+KEYLOCK_UNLOCK_SW EQU 2
+KEYLOCK_OFF_SW EQU 3
+
+
+NUM_KEY_POSITIONS equ 4 ; FP has 4 key positions.
+KEYLOCK_MASK equ 7 ; KEYLOCK POSITION MASK
+SHUTDOWN_MASK equ 8 ; Mask for bit 3.
+SHUTDOWN_NMI_SRC equ 8 ; Numerical equiv for OFF btn.
+TIMER_FREQ equ 1000 ; Hard code to 1000 KHz.
+UPS_LED_MASK equ 30h ; Mask for bits 4,5.
+NULL equ 0
+
+
+;hardware led setting.
+UPS_HARD_DARK EQU 0
+UPS_HARD_RED EQU 2
+UPS_HARD_GREEN EQU 1
+UPS_HARD_AMBER EQU 3
+
+;EBI II specified led setting.
+UPS_EBI_DARK EQU 0
+UPS_EBI_RED EQU 1
+UPS_EBI_GREEN EQU 2
+UPS_EBI_AMBER EQU 3
+
+REGIONAL_CACHE_CONTROL_ENABLED EQU 1 ;Cache control flag.
+CACHE_CONTROL_GRANULARITY EQU 100000H;Current granularity is 1MB
+
+EBI2_MEM_ENTRY EQU 16 ;This is the entry number for
+ ;EBI II memory in the MMIO
+ ;Table. 0 based table.
+EBI2_MEM_LENGTH EQU 400H ;1KB of RAM
+
+
+VALID_GRAPH_MODES EQU 2 ;highest graph mode setting
+FP_HISTOGRAM EQU 0H ;currently definied Front
+FP_STATUS EQU 1H ;panel Graph Modes.
+FP_OVERRIDE EQU 2H ;
+
+
+
+IRQ_0 EQU 0 ;PIC #1 (Master)
+IRQ_1 EQU 1 ;PIC #1 (Master)
+IRQ_2 EQU 2 ;Inaccessable in cascaded PIC system
+IRQ_3 EQU 3 ;PIC #1 (Master)
+IRQ_4 EQU 4 ;PIC #1 (Master)
+IRQ_5 EQU 5 ;PIC #1 (Master)
+IRQ_6 EQU 6 ;PIC #1 (Master)
+IRQ_7 EQU 7 ;PIC #1 (Master)
+IRQ_8 EQU 8 ;PIC #2 (1st slave)
+IRQ_9 EQU 9 ;PIC #2 (1st slave)
+IRQ_10 EQU 10 ;PIC #2 (1st slave)
+IRQ_11 EQU 11 ;PIC #2 (1st slave)
+IRQ_12 EQU 12 ;PIC #2 (1st slave)
+IRQ_13 EQU 13 ;PIC #2 (1st slave)
+IRQ_14 EQU 14 ;PIC #2 (1st slave)
+IRQ_15 EQU 15 ;PIC #2 (1st slave)
+IRQ_16 EQU 16 ;Unused.
+IRQ_17 EQU 17 ;Unused.
+IRQ_18 EQU 18 ;Unused.
+IRQ_19 EQU 19 ;Unused.
+IRQ_20 EQU 20 ;Unused.
+IRQ_21 EQU 21 ;Unused.
+IRQ_22 EQU 22 ;Unused.
+IRQ_23 EQU 23 ;Unused.
+IRQ_24 EQU 24 ;SPI (See below)
+IRQ_25 EQU 25 ;LSI (See below)
+IRQ_26 EQU 26 ;IPI (See below)
+IRQ_27 EQU 27 ;Unused.
+IRQ_28 EQU 28 ;Unused.
+IRQ_29 EQU 29 ;Unused.
+IRQ_30 EQU 30 ;Unused.
+IRQ_31 EQU 31 ;Unused.
+
+IRQ_SPI EQU IRQ_24
+IRQ_LSI EQU IRQ_25
+IRQ_IPI EQU IRQ_26
+
+NUM_POWER_SUPPLIES_SUPPORTED EQU 2 ;Current # of power supplies
+ ;supported on a Manhattan.
+PS_0_OK EQU BIT_6 ;Power supply 0 OK
+PS_1_OK EQU BIT_7 ;Power Supply 1 OK
+PS_0_INSTALLED EQU BIT_8 ;Power Supply 0 Installed
+PS_1_INSTALLED EQU BIT_9 ;Power Supply 1 Installed.
+
+;BIT definitions for the EBI_SEM, a semaphore dword to control
+;access to EBI II multi-threadable functions.
+
+SEM_EnableRAMCache EQU 1 ;bit 1 of EBI_SEM
+SEM_DisableRAMCache EQU 2
+SEM_FlushRAMCache EQU 3
+SEM_LogProcIdle EQU 4
+SEM_LogProcBusy EQU 5
+SEM_GetPanellAttnSwitch EQU 6
+SEM_GetPanelOffSwitch EQU 7
+SEM_GetNMISource EQU 8
+SEM_NonMaskableIntEOI EQU 9
+SEM_GetSPISource EQU 10
+SEM_MaskableIntEOI EQU 11
+SEM_GetLocalIRQStatus EQU 12
+SEM_GetGLobalIRQStatus EQU 13
+
+
+;*****************************************************************************
+; Declare Structure Templates
+;*****************************************************************************
+;
+;Interrupt Mask Info.
+;
+EBI2maskInfo struc
+ numPorts dd 0
+ flags dd 0
+ portAddress0 dd 0
+ portAddress1 dd 0
+ portAddress2 dd 0
+ portAddress3 dd 0
+ reserved0 dd 0
+ reserved1 dd 0
+EBI2maskInfo ends
+
+
+EBI2_Mstruc struc
+ FP_GraphMode DD ? ;Front Panel Graph Mode
+ FP_IntMode DD ? ;Front Panel Interrupt Mode
+ IntSubSysMode DD ? ;Interrupt subsystem mode
+ SMEARRegister DD ? ;storage for SMEAR
+ IRQ0_Vector DD ? ;Vector number for IRQ0-7
+ IRQ8_Vector DD ? ;and IRQ8-15
+ EBI_SEM DD ? ;Semaphor for Multi-threadable
+ ;functions.
+ EBI_2TEMP DD ? ;temporary location for debug
+ CPU_Activity DB ? ;CPU Activity value.
+ SimPowerFail DB ? ;Set if we are simulate a PFI
+
+EBI2_Mstruc ends
+
+
+parm_list struc
+ ebp_reg dd ? ;EBP register
+ ret_addr_off dd ? ;32 bit function return add.
+ MMIOPtr dd ? ;MMIOPtr
+ parm1dd dd ? ;1st 32 bit parameter
+ parm2dd dd ? ;2nd 32 bit parameter
+ parm3dd dd ? ;3RD 32 bit parameter
+ parm4dd dd ? ;4th 32 bit parameter
+
+parm_list ends
+
+
+;real mode parameter list.
+
+RMparm_list struc
+ RMebp_reg dw ? ;EBP register
+ RMret_addr dd ? ;32 bit function return add.
+ RMparm1 dd ? ;1st 32 bit parameter
+ RMparm2 dd ? ;2nd 32 bit parameter
+
+RMparm_list ends
+
+
+
+procConfigData struc
+ processorStatus db ?
+ processorType db ?
+ coprocessorType db ?
+ serialNum DD ?
+ boardRev db ?
+ board_Type db ?
+ manufacturing_1 DB ?
+ manufacturing_2 DB ?
+ manufacturing_3 DB ?
+ manufacturing_4 DB ?
+ manufacturing_5 DB ?
+ manufacturing_6 DB ?
+ manufacturing_7 DB ?
+ manufacturing_8 DB ?
+ board_Info_1 DB ?
+ board_Info_2 DB ?
+ board_Info_3 DB ?
+ board_Info_4 DB ?
+ board_Info_5 DB ?
+ board_Info_6 DB ?
+ board_Info_7 DB ?
+ board_Info_8 DB ?
+ board_Info_9 DB ?
+ board_Info_10 DB ?
+ board_Info_11 DB ?
+ board_Info_12 DB ?
+ board_Info_13 DB ?
+ board_Info_14 DB ?
+ board_Info_15 DB ?
+ board_Info_16 DB ?
+ board_Info_17 DB ?
+ board_Info_18 DB ?
+ board_Info_19 DB ?
+ board_Info_20 DB ?
+ slotNumber DD ?
+
+procConfigData ends
+
+SIZE_OF_MEMDESCE EQU 4 ;number of DD entries in MemDescEntry
+SIZE_OF_MMIO_TE EQU 4 ;number of DD in MMIO_Table_Entry
+
+MMIO_Table_Entry struc
+
+ slot_add_low DD ? ;physical slot address, lower 32 bits
+ slot_add_high DD ? ;physical slot address, upper 32 bits
+ slot_length DD ? ;length of address space required
+ slot_reserved DD ? ;reserved
+
+MMIO_Table_Entry ends
+
+memBankInfo struc
+
+ bankStartAddr_low DD ?
+ bankStartAddr_high DD ?
+ bankSize DD ?
+ bankECCSoftErrors DD ?
+ bankECCHardErrors DD ?
+ memBankInfoReserved DD ?
+
+memBankInfo ends
+
+
+memBoardInfo struc
+ attributes DD ?
+ numBanks DD ?
+ slotNum DD ?
+ mBI_Reserved DD ?
+memBoardInfo ends
+
+memoryErrorInfo struc
+ mEI_StartAddr_low DD ?
+ mEI_StartAddr_high DD ?
+ mEI_Length DD ? ;Length of block containing error.
+ mEI_Count DD ? ;Number of errors in this block
+ mEI_memErrFlags DD ? ;Additional info.
+ mEI_slotNumber DD ? ;Physical slot number of board
+ mEI_moduleNumber DD ? ;Module on board experiencing error.
+memoryErrorInfo ends
+
+
+cacheContInfo struc
+ cCI_Flags DD ? ;type of regional cache control
+ ;available by this hardware
+ cCI_Granularity DD ? ;Granularity of control region
+ cCI_Reserved DD ? ; ???NULL???
+cacheContInfo ends
+
+PhysicalAddress struc
+ PhsyAddrLow DD ? ;Lower 32 bits of a 64 Bit
+ ;physical address
+ PhsyAddrHi DD ? ;Upper 32 bits of a 64 bit
+ ;physical address.
+PhysicalAddress ends
+
+OEM0ParmPacket Struc
+ OEM0_subfunc DD ?
+ OEM0_parm1dd DD ?
+ OEM0_parm2dd DD ?
+ OEM0_parm3dd DD ?
+ OEM0_parm4dd DD ?
+OEM0ParmPacket ends
+
+revisionCode struc
+ major db ? ;revision number of
+ minor db ? ;EBI II in accordance with
+ ZZ db ? ;AST Revision number specification.
+revisionCode ends
+
+powerSupplyInfo struc
+ present DD ? ;1 - Supply installed,
+ ;0 - not present
+ onLine DD ? ;1- Supply providing nominal
+ ;power, 0 - no power
+ PSI_Reserved DD ? ;AST reserved.
+powerSupplyInfo ends
+
+;*****************************************************************************
+; Declare Macros
+;*****************************************************************************
+
+
+;*****************************************************************************
+; Macro: ProcTable_To_ESI
+;*****************************************************************************
+; We need to determine the offset to the begining of proc table.
+; It is a requirement for DS and SS to be the same becuase we are
+; running in a flat model addressing system.
+;
+; we need to determine the current address.
+; we need to determine the difference between the current
+; address and the begining of ProcTable. Keep in mind ProcTable
+; is in a different segment.
+; Then we subtract the difference from the current address and
+; we have an offset that is pointing to the begining of ProcTable.
+;
+; Inputs : name of a near label
+;
+; Outputs : ESI will point to the begining of ProcTableLen
+;
+;
+; Register Usage : ESI
+;
+;-----------------------------------------------------------------------------
+
+ProcTable_To_ESI MACRO
+ LOCAL current_add
+ call current_add
+
+current_add:
+ pop esi ;esi contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset current_add
+ sub eax,offset ProcTableLen ;eax contains the difference between
+ ;our address and begining of PorcTableLen
+
+ sub esi,eax ;esi is pointing to start of ProcTableLen
+ pop eax
+
+ ;sub esi,(offset addres- offset ProcTableLen) ;this does not work.
+
+ENDM
+
+;*****************************************************************************
+; Macro: MemDesc_To_ESI
+;*****************************************************************************
+; We need to determine the offset to the begining of Memory Description table.
+; It is a requirement for DS and SS to be the same becuase we are
+; running in a flat model addressing system.
+;
+; we need to determine the current address.
+; we need to determine the difference between the current
+; address and the begining of MemDescTable. Keep in mind MemDescTable
+; is in a different segment.
+; Then we subtract the difference from the current address and
+; we have an offset that is pointing to the begining of MemDescLen
+;
+; Inputs : name of a near label
+;
+; Outputs : ESI will point to the begining of MemDescLen
+;
+;
+; Register Usage : ESI
+;
+;-----------------------------------------------------------------------------
+
+MemDesc_To_ESI MACRO
+ LOCAL MemDesc_add
+
+
+ call MemDesc_add
+
+MemDesc_add:
+ pop esi ;esi contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset MemDesc_add
+ sub eax,offset MemDescLen ;eax contains the difference between
+ ;our address and begining of MemDescLen
+
+ sub esi,eax ;esi is pointing to start of MemDescLen
+ pop eax
+
+
+ENDM
+
+;*****************************************************************************
+; Macro: MemDesc_To_SI_16
+;*****************************************************************************
+;
+; Only in Real Mode or 16 bit protected mode.
+;
+; We need to determine the offset to the begining of Memory Description table.
+; It is a requirement for DS and SS to be the same becuase we are
+; running in a flat model addressing system.
+;
+; we need to determine the current address.
+; we need to determine the difference between the current
+; address and the begining of MemDescTable. Keep in mind MemDescTable
+; is in a different segment.
+; Then we subtract the difference from the current address and
+; we have an offset that is pointing to the begining of MemDescLen
+;
+; Inputs : name of a near label
+;
+; Outputs : SI will point to the begining of MemDescLen
+;
+;
+; Register Usage : SI
+;
+;-----------------------------------------------------------------------------
+
+MemDesc_To_SI_16 MACRO
+ LOCAL MemDesc_add_16
+
+
+ call MemDesc_add_16
+
+MemDesc_add_16:
+ pop si ;si contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset MemDesc_add_16
+ sub eax,offset MemDescLen ;ax contains the difference between
+ ;our address and begining of MemDescLen
+
+ sub si,ax ;si is pointing to start of MemDescLen
+ pop eax
+
+
+ENDM
+
+
+;*****************************************************************************
+; Macro: MemTable_To_ESI
+;*****************************************************************************
+; We need to determine the offset to the begining of Memoryc table.
+; It is a requirement for DS and SS to be the same becuase we are
+; running in a flat model addressing system.
+;
+; we need to determine the current address.
+; we need to determine the difference between the current
+; address and the begining of MemTable. Keep in mind MemTable
+; is in a different segment.
+; Then we subtract the difference from the current address and
+; we have an offset that is pointing to the begining of MemTable.
+;
+; Inputs : name of a near label
+;
+; Outputs : ESI will point to the begining of MemTableLen
+;
+;
+; Register Usage : ESI
+;
+;-----------------------------------------------------------------------------
+
+MemTable_To_ESI MACRO
+ LOCAL MemTable_add
+
+ call MemTable_add
+
+MemTable_add:
+ pop esi ;esi contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset MemTable_add
+ sub eax,offset MemTableLen ;eax contains the difference between
+ ;our address and begining of MemTableLen
+
+ sub esi,eax ;esi is pointing to start of MemTableLen
+ pop eax
+
+ENDM
+
+MemTable_To_EDI MACRO
+ LOCAL MemTable_add_edi
+
+ call MemTable_add_edi
+
+MemTable_add_edi:
+ pop edi ;edi contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset MemTable_add_edi
+ sub eax,offset MemTableLen ;eax contains the difference between
+ ;our address and begining of MemTableLen
+
+ sub edi,eax ;edi is pointing to start of MemTableLen
+ pop eax
+
+ENDM
+
+
+;*****************************************************************************
+; Macro: MMIO_Table_To_ESI
+;*****************************************************************************
+; We need to determine the offset to the begining of MMIO_Table
+; It is a requirement for DS and SS to be the same becuase we are
+; running in a flat model addressing system.
+;
+; we need to determine the current address.
+; we need to determine the difference between the current
+; address and the begining of MMIO_Table. Keep in mind MMIO_Table
+; is in a different segment.
+; Then we subtract the difference from the current address and
+; we have an offset that is pointing to the begining of MMIO_TableLen.
+;
+; Inputs : name of a near label
+;
+; Outputs : ESI will point to the begining of MMIO_TableLen
+;
+;
+; Register Usage : ESI
+;
+;-----------------------------------------------------------------------------
+MMIOTable_To_ESI MACRO
+ LOCAL MMIOTable_add
+
+
+ call MMIOTable_add
+
+MMIOTable_add:
+ pop esi ;esi contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset MMIOTable_add
+ sub eax,offset MMIO_TableLen ;eax contains the difference between
+ ;our address and begining of MMIO_TableLen
+
+ sub esi,eax ;esi is pointing to start of MMIO_TableLen
+ pop eax
+
+
+ENDM
+
+;*****************************************************************************
+; Macro: OEM0_SubFuncStart_To_ESI
+;*****************************************************************************
+;
+;-----------------------------------------------------------------------------
+OEM0_SubFuncStart_To_ESI MACRO
+ LOCAL OEM0_SubFuncStart_add
+
+
+ call OEM0_SubFuncStart_add
+
+OEM0_SubFuncStart_add:
+ pop esi ;esi contains the address of the
+ ;current instruciton.
+ push eax
+ mov eax,offset OEM0_SubFuncStart_add
+ sub eax,offset OEM0_SubFuncLen
+
+ ;eax contains the difference between
+ ;our address and begining of OEM0_SubFuncLen
+
+ sub esi,eax ;esi is pointing to start of OEM0_SubFuncLen
+ pop eax
+
+
+ENDM
+
+;*****************************************************************************
+; Macro: BaseofROM_To_ESI
+;*****************************************************************************
+;
+;-----------------------------------------------------------------------------
+BaseofROM_To_ESI MACRO
+ LOCAL BaseofROM_add
+
+
+ call BaseofROM_add
+
+BaseofROM_add:
+ pop esi ;esi contains the address of the
+ ;current instruciton.
+
+ sub esi,offset BaseofROM_add;esi contains the virtual address
+ ;to base of ROM.
+
+
+
+ENDM
+
+;*****************************************************************************
+; Macro: ESI_MMIO_NUM_SLOT
+;*****************************************************************************
+;
+; The following Macro will determine the virtual memory mapped I/O address
+; for a certain slot number.
+; The slot number is passed in EAX, and the virtual address is returned
+; in ESI.
+;
+; Inputs : EBP.parm_list.MMIOPTR
+; EAX slot number.
+;
+; Outputs : ESI will contain the virtual memory mapped I/O address for
+; the specificed slot.
+;
+; Register Usage : ESI and EAX
+;
+; NOTE : For future enhancements or requirements, this macro should
+; only use ESI and EAX and NO OTHER REGISTERS.
+;
+;
+;-----------------------------------------------------------------------------
+
+ESI_MMIO_NUM_SLOT MACRO
+
+
+ ;Since MMIOPtr passed by the EBI II caller is a pointer to a
+ ;table containing the virtual address created by the OS for
+ ;the Manhattan memory mapped I/O address space.
+ ;
+ ;The first entry in the table is the virtual address for the
+ ;global (IOSM) MM I/O virtual address.
+
+ ;setup ESI to point to the MM IO Table provide to us by the
+ ;EBI II caller.
+ mov esi, dword ptr [ebp.parm_list.MMIOPtr]
+
+ ;eax is now the offset in to the MM IO Table to the virtual
+ ;address of memory mapped I/O for this slot.
+
+ ;update ESI to containing the virtual address of the memory
+ ;mapped I/O for the callers slot.
+ mov esi,[esi][eax*4]
+
+
+ENDM
+;*****************************************************************************
+; Macro: ESI_MMIO_CURR_SLOT
+;*****************************************************************************
+;
+; The following Macro will determine the current CPU slot memory
+; mapped I/O address. This value will be returned in ESI.
+;
+;
+; Inputs : EBP.parm_list.MMIOPTR
+;
+; Outputs : ESI will point to the begining of the current slots
+; MM I/O address
+;
+;
+; Register Usage : ESI and EAX
+;
+; NOTE : For future enhancements or requirements, this macro should
+; only use ESI and EAX and NO OTHER REGISTERS.
+;
+;
+;-----------------------------------------------------------------------------
+
+ESI_MMIO_CURR_SLOT MACRO
+
+
+ ;Since MMIOPtr passed by the EBI II caller is a pointer to a
+ ;table containing the virtual address created by the OS for
+ ;the Manhattan memory mapped I/O address space.
+ ;
+ ;The first entry in the table is the virtual address for the
+ ;global (IOSM) MM I/O virtual address.
+
+ ;setup ESI to point to the MM IO Table provide to us by the
+ ;EBI II caller.
+
+ push eax ;save eax
+
+ mov esi, dword ptr [ebp.parm_list.MMIOPtr]
+
+ ;get the first entry from the table, which is the virtual address
+ ;for the global MM IO address space, also known as Slot 0
+ mov eax, [esi]
+
+ ;determine the caller SLOT number.
+ mov al, byte ptr [eax].G_SlotID
+ NOT al ;invert it back to 1 based.
+ and al,0FH ;clear upper nibble.
+
+ ;clear the upper 24 bits of eax.
+ and eax,0ffH
+
+ ;eax is now the offset in to the MM IO Table to the virtual
+ ;address of memory mapped I/O for this slot.
+
+ ;update ESI to containing the virtual address of the memory
+ ;mapped I/O for the callers slot.
+ mov esi,[esi][eax*4]
+ pop eax
+
+
+ENDM
+
+
+;*****************************************************************************
+; Macro: ESI_MMIO_GLOBAL
+;*****************************************************************************
+;
+; The following Macro will determine the Global memory
+; mapped I/O address. This value will be returned in ESI.
+;
+;
+; Inputs : EBP.parm_list.MMIOPTR
+;
+; Outputs : ESI will point to the begining of the Global memory
+; mapped I/O address
+;
+;
+; Register Usage : ESI
+;
+; NOTE : For future enhancements or requirements, this macro should
+; only use ESI and NO OTHER REGISTERS.
+;
+;-----------------------------------------------------------------------------
+
+ESI_MMIO_GLOBAL MACRO
+
+ ;Since MMIOPtr passed by the EBI II caller is a pointer to a
+ ;table containing the virtual address created by the OS for
+ ;the Manhattan memory mapped I/O address space.
+ ;
+ ;The first entry in the table is the virtual address for the
+ ;global (IOSM) MM I/O virtual address.
+
+ ;setup ESI to point to the MM IO Table provide to us by the
+ ;EBI II caller.
+ mov esi, dword ptr [ebp.parm_list.MMIOPtr]
+
+ ;get the first entry from the table, which is the virtual address
+ ;for the global MM IO address space, also known as Slot 0
+
+ mov esi, [esi]
+
+ENDM
+
+
+;*****************************************************************************
+; Macro: ESI_EBI_MEM_ADD
+;*****************************************************************************
+;
+; The following Macro will determine the virtual memory mapped I/O address
+; for the memory reserved for EBI II.
+;
+; Inputs : EBP.parm_list.MMIOPTR
+;
+; Outputs : ESI will contain the virtual memory mapped I/O address for
+; the memory reserved for EBI II.
+;
+; Register Usage : ESI
+;
+; NOTE : For future enhancements or requirements, this macro should
+; only use ESI NO OTHER REGISTERS.
+;
+;
+;-----------------------------------------------------------------------------
+
+ESI_EBI_MEM_ADD MACRO
+
+
+ ;Since MMIOPtr passed by the EBI II caller is a pointer to a
+ ;table containing the virtual address created by the OS for
+ ;the Manhattan memory mapped I/O address space.
+ ;
+ ;The first entry in the table is the virtual address for the
+ ;global (IOSM) MM I/O virtual address.
+
+ ;setup ESI to point to the MM IO Table provide to us by the
+ ;EBI II caller.
+
+ mov esi, dword ptr [ebp.parm_list.MMIOPtr]
+
+ ;eax is now the offset in to the MM IO Table to the virtual
+ ;address of memory mapped I/O for this slot.
+
+ ;update ESI to containing the virtual address of the memory
+ ;mapped I/O for the memory reserved for EBI II.
+
+ mov esi,dword ptr [esi][EBI2_MEM_ENTRY*4]
+
+
+ENDM
+EDI_EBI_MEM_ADD MACRO
+
+
+ mov edi, dword ptr [ebp.parm_list.MMIOPtr]
+
+ ;eax is now the offset in to the MM IO Table to the virtual
+ ;address of memory mapped I/O for this slot.
+
+ ;update ESI to containing the virtual address of the memory
+ ;mapped I/O for the memory reserved for EBI II.
+
+ mov edi,dword ptr [edi][EBI2_MEM_ENTRY*4]
+
+
+ENDM
+
+;*****************************************************************************
+; Macro: LOCK_SEMAPHORE
+;*****************************************************************************
+;
+;-----------------------------------------------------------------------------
+LOCK_SEMAPHORE MACRO SEM_NUM
+ LOCAL LS_CheckSem,LS_QuickCheck,LS_ProbableSucess
+ LOCAL LS_Sucess
+
+
+ push esi ;save esi
+ ESI_EBI_MEM_ADD ;point esi to EBI II memory space.
+
+LS_CheckSem:
+ lock bts dword ptr [esi].EBI2_Mstruc.EBI_SEM,SEM_NUM
+
+ jnc LS_Sucess ;the semaphore was previously not set
+
+ ;Some one has already locked this semaphore, do a quick check
+ ;hoping for it to free, if we time out then we return with the
+ ;carry set and an error code in eax.
+ push ecx
+ mov ecx, NEGONE
+
+LS_QuickCheck:
+ bt dword ptr [esi].EBI2_Mstruc.EBI_SEM,SEM_NUM
+ jnc LS_ProbableSucess ;it must have clear, make sure it is so
+
+ loop LS_QuickCheck ;do another quick check, until ecx is 0
+
+ ;we must have timeout, in order to prevent a dead lock
+ ;return an error code.
+ pop ecx
+ mov eax, ERR_MULTI_TIME_OUT
+ stc ;set the carry indicating a problem with the macro
+ jmp LS_Sucess ;exit macro.
+
+LS_ProbableSucess:
+ ;the Semaphore seems to have cleared, but we need to make
+ ;sure by doing a lock bts
+ pop ecx
+ jmp LS_CheckSem
+
+LS_Sucess:
+ pop esi
+ENDM
+
+;*****************************************************************************
+; Macro: UNLOCK_SEMAPHORE
+;*****************************************************************************
+;
+;-----------------------------------------------------------------------------
+UNLOCK_SEMAPHORE MACRO UN_SEM_NUM
+
+
+ push esi ;save esi
+ ESI_EBI_MEM_ADD ;point esi to EBI II memory space.
+
+ ;clear the semaphore in question.
+ LOCK btr dword ptr [esi].EBI2_Mstruc.EBI_SEM,UN_SEM_NUM
+
+ pop esi
+ENDM
+
+
+
+;*****************************************************************************
+; Macro: IODELAY
+;*****************************************************************************
+
+IODELAY MACRO
+ jmp Short $+2
+ jmp Short $+2
+ jmp Short $+2
+ jmp Short $+2
+ENDM
+
diff --git a/private/ntos/nthals/halast/i386/astebiii.h b/private/ntos/nthals/halast/i386/astebiii.h
new file mode 100644
index 000000000..251c200c8
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astebiii.h
@@ -0,0 +1,745 @@
+/***************************************************************************\
+* File: ebi_ii.h - Standard definitions for EBI II interfacing. *
+* *
+* Data structures, defined values and function prototypes for accessing *
+* AST EBI II compliant function libraries. *
+* *
+* By D. Shively II (dash) *
+* *
+* *
+* ------------------------------------------------------------------------- *
+* Edit history: *
+* *
+* Who Date Comment *
+* ----- -------- ----------------------------------------------- *
+* Dash 10/11/91 Inception *
+* Dash 10/16/91 Version 2.1 *
+* Dash 10/28/91 Version 2.2 *
+* Dash 11/13/91 Version 2.3 *
+* Dash 12/03/91 Version 2.4 *
+* Dash 12/13/91 Version 2.4a *
+* Dash 12/17/91 Version 2.4b *
+* Dash 12/20/91 Version 2.4c *
+* Dash 1/02/92 Version 2.5 *
+* Dash 2/10/92 Version 2.5a (Note: was previously erroneously 2.6) *
+* Dash & *
+* rossw 3/03/92 Version 2.6 *
+* Dash 4/14/92 Version 2.7 *
+* Dash 4/26/92 Version 2.7.01 *
+* Dash 4/30/92 Version 2.7.02 *
+* Dash 6/02/92 Version 2.8 *
+* Dash 9/21/92 Version 2.9 *
+* *
+\***************************************************************************/
+
+#ifndef EBI_II_H
+#define EBI_II_H
+
+
+/*
+ * Portable data type definitions
+ */
+typedef unsigned char byte; // 8-bit quantity
+typedef unsigned short word; // 16-bit quantity
+typedef unsigned long dWord; // 32-bit quantity
+typedef long status; // Completion status return data type
+
+/*
+ * The structure and the definitions for the new local int mask call
+ */
+
+#define PORT_TYPE_MASK (3)
+#define PORT_TYPE_MEMORY (0)
+#define PORT_TYPE_IO (1)
+
+#define PORT_WIDTH_MASK (0x1C)
+#define EIGHT_BIT_PORTS (0)
+#define SIXTEEN_BIT_PORTS (4)
+#define THIRTY_TWO_BIT_PORT (8)
+
+typedef struct {
+ dWord numPorts;
+ dWord flags;
+ dWord portAddress[4];
+ dWord reserved[2];
+} maskInfo;
+
+
+/*
+ * Macro to convert a segmented real mode address into a linear
+ * physical address.
+ */
+#define REAL_TO_LIN(seg,off) ((seg << 4) + off)
+
+
+/*
+ * The EBI II signature is located in the BIOS segment at offset
+ * EBI_II_SIGNATURE. Thus, to derive it's linear address we
+ * use REAL_TO_LIN( BIOS_SEG, EBI_II_SIGNATURE )
+ */
+#define BIOS_SEG (0xf000)
+#define EBI_II_SIGNATURE (0xffe2)
+
+
+/*
+ * Data structure defining EBI II signature/pointer area.
+ */
+typedef struct {
+ char sig[4]; // Signature string: literally "EBI2"
+ word seg; // Real mode segment
+ word off; // Real mode offset
+} ebi_iiSig;
+
+
+/*
+ * System board control register defines
+ */
+#define CFRAM_BIT 0x2
+#define CFRAM_OFFSET 0x20000
+#define CMMS_BIT 0x3
+#define CMMS_OFFSET 0x10008L
+#define CMAS_BIT 0x1F
+#define CMAS_OFFSET 0x10010L
+#define MEMSLOT_BASEADDR 0xD0000000
+#define CPU_BOARD 0x10000L
+#define CMCR_OFFSET 0x178L
+#define BRSEL_BIT 0x40
+#define IBSR01_OFFSET 0x118L
+#define ICR_OFFSET 0x128L
+
+
+/*
+ * EBI II function completion codes. Non-error values are zero
+ * or greater. Erroneous results are less than zero.
+ */
+#define OK (0)
+#define PROC_RUNNING (1)
+#define PROC_STOPPED (2)
+#define NO_CACHE (3)
+#define NO_MEMORY_ERRORS (4)
+#define MEMORY_ERROR_FOUND (5)
+#define WRONG_PROC_GRAPH_MODE (6)
+#define EMPTY_MEMORY_BANK (10000)
+
+#define BAD (-1)
+#define ERR_NOT_SUPPORTED (-2)
+#define ERR_NONESUCH (-3)
+#define ERR_BAD_PROC_ID (-4)
+#define ERR_PROC_ABSENT (-5)
+#define ERR_PROC_BAD (-6)
+#define ERR_UNKNOWN_INT (-7)
+#define ERR_DISPLAY_OVERFLOW (-8)
+#define ERR_BAD_CHARS (-9)
+#define ERR_BAD_SELECTOR (-10)
+#define ERR_BAD_CACHE_MODE (-11)
+#define ERR_BAD_VECTOR (-12)
+#define ERR_BAD_COLOR (-13)
+#define ERR_BAD_GRAPH_MODE (-14)
+#define ERR_BAD_BOARD_NUM (-15)
+#define ERR_BAD_MODULE_NUM (-16)
+#define ERR_BAD_IRQ_NUM (-17)
+#define ERR_BAD_OFFSWITCH (-18)
+#define ERR_BAD_PHYS_ADDR (-19)
+#define ERR_BAD_LENGTH (-20)
+#define ERR_BAD_BLOCK_NUM (-21)
+#define ERR_BAD_GLOB_MASK_IRQ (-22)
+#define ERR_BAD_LOC_MASK_IRQ (-23)
+#define ERR_CANT_CANCEL_INT (-24)
+#define ERR_PROC_STILL_RUNNING (-25)
+#define ERR_POWER_SUPPLY_NUM (-26)
+#define ERR_BAD_VIS_MODE (-27)
+
+#define IsOK(n) ( n >= OK )
+#define IsBad(n) ( n < OK )
+
+
+/*
+ * Independent hardware manufacturers and OEMs are allowed to define
+ * function extensions to the calling system in the OEM function array
+ * at the end of the ebi_ii structure. To avoid collisions in OEM
+ * specified completion/error codes, use the following system:
+ * To define a non-error completion code, define it as:
+ * #define name OEMCompCode(OEMNum,sequenceNum)
+ *
+ * Define an error code as:
+ * #define name OEMErrorCode( OEMNum,sequenceNum)
+ *
+ * Where:
+ *
+ * OEMNum The OEM number assigned you by AST (if you don't
+ * have one, contact them. Really, go ahead.) For
+ * example, AST themselves are OEM #0.
+ *
+ * sequenceNum The conditions sequential number. I.e.- the
+ * 1st condition defined is 0, then next 1, etc.
+ *
+ * Example:
+ * AST uses the following definition in it's OEM include file, astoem.h:
+ *
+ * #define ERR_BAD_COM2_OVERRIDE OEMErrorCode(0,-1)
+ *
+ * (See astoem.h for additional examples.)
+ */
+
+/*
+ * Macros for OEM completion code definition.
+ */
+#define EBI2_OEM_COMP_CODE_BASE (65536L)
+#define EBI2_OEM_ERR_CODE_BASE (-65536L)
+#define EBI2_OEM_COMP_CODE_GAP (65536L)
+
+#define OEMCompCode(OEMNum,sequenceNum) \
+ ( EBI2_OEM_COMP_CODE_BASE + (OEMNum * EBI2_OEM_COMP_CODE_GAP) \
+ + sequenceNum )
+
+#define OEMErrorCode(OEMNum,sequenceNum) \
+ ( EBI2_OEM_ERR_CODE_BASE - (OEMNum * EBI2_OEM_COMP_CODE_GAP) \
+ - sequenceNum )
+
+
+/*
+ * Processor configuration data table
+ */
+typedef struct procConfigData {
+ byte processorStatus; // See Table 3
+ byte processorType; // See Table 4
+ byte coprocessorType; // See Table 6
+ byte serialNum[4]; // Packed BCD board serial number
+ byte boardRev; // 2 byte Hex board revision
+ byte boardType; // See table 5
+ byte manufacturing[8]; // Unused bytes, NULL filled
+ byte boardInfo[20]; // Board specific info, format
+ // to be defined
+ dWord slotNumber; // Physical slot this board occupies
+} procConfigData;
+
+
+/*
+ * ProcessorType codes
+ */
+#define PTYPE_80386 (0x10) // Intel family of processors
+#define PTYPE_80486 (0x11)
+#define PTYPE_80586 (0x12)
+#define PTYPE_80686 (0x13)
+#define PTYPE_80786 (0x14)
+
+#define PTYPE_SPARC (0x20) // Sun SPARC type processor
+
+#define PTYPE_MIPS4000 (0x30) // Mips
+#define PTYPE_MIPS5000 (0x31)
+
+#define PTYPE_68030 (0x40) // Motorola 68000 family
+#define PTYPE_68040 (0x41)
+#define PTYPE_68050 (0x42)
+
+#define PTYPE_88000 (0x50) // Motorola 88000 RISC family
+#define PTYPE_88110 (0x51)
+
+#define PTYPE_34010 (0x60) // TI 34000 graphics processor family
+#define PTYPE_34020 (0x61)
+#define PTYPE_34030 (0x62)
+
+#define PTYPE_R6000 (0x70) // IBM
+
+#define PTYPE_80860 (0x80) // Intel i860 RISC processor family
+#define PTYPE_80960 (0x81)
+
+
+/*
+ * ProcessorStatus codes
+ */
+#define PSTAT_ABSENT (0)
+#define PSTAT_RUNNING (1)
+#define PSTAT_RESET (2)
+#define PSTAT_FAULT (0x0f)
+
+
+/*
+ * coprocessorType codes
+ */
+#define CPTYPE_387 (0x10) // Intel type coprocessor family
+#define CPTYPE_487 (0x11)
+#define CPTYPE_587 (0x12)
+
+#define CPTYPE_3167 (0x20) // Weitek coprocessors for 80x86 processors
+#define CPTYPE_4167 (0x21)
+#define CPTYPE_5167 (0x22)
+
+#define CPTYPE_68881 (0x30) // Motorola mathco's
+#define CPTYPE_68882 (0x31)
+
+#define CPTYPE_34081 (0x40) // Floating point coprocessors for TI 34000
+#define CPTYPE_34082 (0x41) // family
+
+
+/*
+ * ProcessorGraph mode values
+ */
+#define HISTO_MODE 0 // Histogram mode
+#define STATUS_MODE 1
+#define OVERRIDE_MODE 2
+
+
+/*
+ * Define data type for a 64-bit linear physical address.
+ */
+typedef struct {
+ dWord low;
+ dWord high;
+} physAddr;
+
+/*
+ * Define cache mode values
+ */
+#define ENABLE_CACHE (0)
+#define DISABLE_CACHE (4)
+#define AUTO_WRITE_THRU (0)
+#define FORCE_WRITE_THRU (2)
+#define AUTO_READ_ONLY (0)
+#define FORCE_READ_ONLY (1)
+#define DEFAULT_CACHE_MODE (0)
+
+
+/*
+ * cache region control word values
+ */
+#define ENABLE_REGION_CACHING (1)
+#define DISABLE_REGION_CACHING (0)
+
+
+/*
+ * The Cache control information structure; returned GetCacheControlInfo().
+ */
+typedef struct cacheControlInfo {
+ dWord flags; // See table 9.
+ dWord controlGranularity; // In bytes.
+ dWord RESERVED;
+} cacheControlInfo;
+
+
+typedef struct {
+ dWord r_eax;
+ dWord r_ebx;
+ dWord r_ecx;
+ dWord r_edx;
+ dWord r_edi;
+ dWord r_esi;
+ dWord r_ebp;
+} poss_regs;
+
+
+/*
+ * memoryBlockInfo definition
+ */
+typedef struct memoryBlockInfo {
+ physAddr blockStartAddr; // Start address of this memory block
+ dWord blockSize; // Size of this block
+ dWord blockAttributes; // Attributes of this block
+} memoryBlockInfo;
+
+
+/*
+ * Module attribute bit definitions and macros. Also used on
+ * GetMemBankInfoPacket (See astoem.h).
+ */
+#define RAM_WIDTH_MASK (0x0f)
+#define extractRAMWidth(n) ((n) & RAM_WIDTH_MASK )
+#define RAM_PRESENT (0x10)
+#define ECC_PRESENT (0x100)
+#define INTERLEAVED (0x200)
+#define BIT_MODE_MASK (0xfc00)
+#define BIT_MODE_64 (0)
+#define BIT_MODE_128 (0x400)
+#define extractBitMode(n) ((n) & BIT_MODE_MASK)
+
+
+/*
+ * memoryErrorInfo definition
+ */
+typedef struct memoryErrorInfo {
+ physAddr location; // Location of block containing error
+ dWord length; // Length of block containing errors in bytes
+ dWord count; // Number of errors in this block
+ dWord memErrFlags; // Additional info; see definitions below and Table 20
+ dWord slotNumber; // Physical slot number of board experiencing error
+ dWord moduleNumber; // Module on board experiencing error
+} memoryErrorInfo;
+
+
+/*
+ * memErrFlags bits definitions
+ */
+#define MEM_ERR_TYPE_MASK 0x0f
+#define GETMEMERRTYPE(n) ((n) & MEM_ERR_TYPE_MASK)
+
+#define MEM_NO_ERROR (0)
+#define MEM_ERR_PARITY (1)
+#define MEM_ERR_SINGLEBIT_ECC (2)
+#define MEM_ERR_MULTIBIT_ECC (3)
+
+#define SLOT_NUM_INDETERMINATE (-1)
+#define MOD_NUM_INDETERMINATE (-1)
+
+
+/*
+ * Front panel UPS light color codes
+ */
+#define UPS_COLOR_DARK (0)
+#define UPS_COLOR_GREEN (2)
+#define UPS_COLOR_AMBER (3)
+#define UPS_COLOR_RED (1)
+
+
+/*
+ * Font panel key position codes
+ */
+#define KEY_POS_LOCKED 0
+#define KEY_POS_SERVICE 1
+#define KEY_POS_UNLOCKED 2
+#define KEY_POS_OFF 3
+
+
+/*
+ * The EBI II revision code structure
+ */
+typedef struct revisionCode {
+ byte major; // EBI II revision major number (the XX in XX.YY)
+ byte minor; // EBI II revision minor number (the YY in XX.YY)
+ byte RESERVED;
+} revisionCode;
+
+
+/*
+ * Define data type describing the in ROM offset table.
+ */
+typedef dWord offsetTable[128]; // Unresolved BIOS offset table
+
+
+/*
+ * IOInfoTable structure. The address of such a table must be
+ * provided during virtually any EBI II call.
+ */
+typedef struct {
+ physAddr address; // Physical address of this slot's I/O area
+ dWord length; // Length of area, or 0 if no I/O area
+ dWord flags; // Allocation type flags} IOInfoTable;
+} IOInfoTable;
+
+#define ALLOCATE_RAM (1) // Only one bit used so far
+
+
+/*
+ * NMI and SPI Source constants
+ */
+#define NMI_NONE_FOUND (0)
+// RESERVED (1)
+#define NMI_SW_GEN_NMI (2)
+#define NMI_MEMORY_ERROR (3)
+#define NMI_PROC_ERROR (4)
+// RESERVED (5)
+#define NMI_BUS_PARITY (6)
+#define NMI_BUS_TIMEOUT (7)
+#define NMI_FP_SHUTDOWN (8)
+#define NMI_FP_ATTENTION (9)
+#define NMI_POWERFAIL (10)
+#define NMI_EISA_FAILSAFE_TIMER (11)
+#define NMI_EISA_BUS_TIMEOUT (12)
+#define NMI_EISA_IO_CHECK (13)
+#define NMI_EISA_SW_GEN_NMI (14)
+#define NMI_SYS_IO_ERROR (15)
+
+#define OEM_NMI_BASE (0x10000000L)
+#define OEM_NMI_GAP (0x01000000L)
+#define OEM_NMI_NUM(OEM,NMI_NUM) ( \
+ OEM_NMI_BASE + \
+ (OEM_NMI_GAP * OEM) + \
+ NMI_NUM \
+ )
+
+
+#define SPI_NONE_FOUND (0)
+// RESERVED (1)
+// RESERVED (2)
+#define SPI_MEMORY_ERROR (3)
+#define SPI_PROC_ERROR (4)
+// RESERVED (5)
+#define SPI_BUS_PARITY (6)
+#define SPI_BUS_TIMEOUT (7)
+#define SPI_FP_SHUTDOWN (8)
+#define SPI_FP_ATTENTION (9)
+#define SPI_POWERFAIL (10)
+#define SPI_EISA_FAILSAFE_TIMER (11)
+#define SPI_EISA_BUS_TIMEOUT (12)
+#define SPI_EISA_IO_CHECK (13)
+#define SPI_EISA_SW_GEN_NMI (14)
+#define SPI_SYS_IO_ERROR (15)
+
+#define OEM_SPI_BASE (0x10000000L)
+#define OEM_SPI_GAP (0x01000000L)
+#define OEM_SPI_NUM(OEM,SPI_NUM) ( \
+ OEM_SPI_BASE + \
+ (OEM_SPI_GAP * OEM) + \
+ SPI_NUM \
+ )
+
+
+/*
+ * Front panel OFF switch mode constants
+ */
+#define OFF_SWITCH_NMI (0)
+#define OFF_SWITCH_HW_SHUTDOWN (1)
+
+
+/*
+ * Interrupt subsystem typecodes
+ */
+#define EBI_INT_SUBSYS_EISA (0)
+#define EBI_INT_SUBSYS_ISA (1)
+#define EBI_INT_SUBSYS_ADI (2)
+#define EBI_INT_SUBSYS_MPIC (3)
+
+
+/*
+ * IRQ numbers.
+ */
+#define EBI_IRQ0 (0L) // PIC #1 (Master)
+#define EBI_IRQ1 (1L) // PIC #1 (Master)
+#define EBI_IRQ2 (2L) // Inaccessable in cascaded PIC system
+#define EBI_IRQ3 (3L) // PIC #1 (Master)
+#define EBI_IRQ4 (4L) // PIC #1 (Master)
+#define EBI_IRQ5 (5L) // PIC #1 (Master)
+#define EBI_IRQ6 (6L) // PIC #1 (Master)
+#define EBI_IRQ7 (7L) // PIC #1 (Master)
+#define EBI_IRQ8 (8L) // PIC #2 (1st slave)
+#define EBI_IRQ9 (9L) // PIC #2 (1st slave)
+#define EBI_IRQ10 (10L) // PIC #2 (1st slave)
+#define EBI_IRQ11 (11L) // PIC #2 (1st slave)
+#define EBI_IRQ12 (12L) // PIC #2 (1st slave)
+#define EBI_IRQ13 (13L) // PIC #2 (1st slave)
+#define EBI_IRQ14 (14L) // PIC #2 (1st slave)
+#define EBI_IRQ15 (15L) // PIC #2 (1st slave)
+#define EBI_IRQ16 (16L) // PIC #3 (2nd slave)
+#define EBI_IRQ17 (17L) // PIC #3 (2nd slave)
+#define EBI_IRQ18 (18L) // PIC #3 (2nd slave)
+#define EBI_IRQ19 (19L) // PIC #3 (2nd slave)
+#define EBI_IRQ20 (20L) // PIC #3 (2nd slave)
+#define EBI_IRQ21 (21L) // PIC #3 (2nd slave)
+#define EBI_IRQ22 (22L) // PIC #3 (2nd slave)
+#define EBI_IRQ23 (23L) // PIC #3 (2nd slave)
+#define EBI_IRQ24 (24L) // SPI (See below)
+#define EBI_IRQ25 (25L) // LSI (See below)
+#define EBI_IRQ26 (26L) // IPI (See below)
+#define EBI_IRQ27 (27L) // Reserved
+#define EBI_IRQ28 (28L) // Reserved
+#define EBI_IRQ29 (29L) // Reserved
+#define EBI_IRQ30 (30L) // Reserved
+#define EBI_IRQ31 (31L) // Reserved
+
+#define EBI_SPI_IRQ (EBI_IRQ24)
+#define EBI_LSI_IRQ (EBI_IRQ25)
+#define EBI_IPI_IRQ (EBI_IRQ26)
+
+#define EBI_IRQBIT0 (0x1L) // PIC #1 (Master)
+#define EBI_IRQBIT1 (0x2L) // PIC #1 (Master)
+#define EBI_IRQBIT2 (0x4L) // Inaccessable in cascaded PIC system
+#define EBI_IRQBIT3 (0x8L) // PIC #1 (Master)
+#define EBI_IRQBIT4 (0x10L) // PIC #1 (Master)
+#define EBI_IRQBIT5 (0x20L) // PIC #1 (Master)
+#define EBI_IRQBIT6 (0x40L) // PIC #1 (Master)
+#define EBI_IRQBIT7 (0x80L) // PIC #1 (Master)
+#define EBI_IRQBIT8 (0x100L) // PIC #2 (1st slave)
+#define EBI_IRQBIT9 (0x200L) // PIC #2 (1st slave)
+#define EBI_IRQBIT10 (0x400L) // PIC #2 (1st slave)
+#define EBI_IRQBIT11 (0x800L) // PIC #2 (1st slave)
+#define EBI_IRQBIT12 (0x1000L) // PIC #2 (1st slave)
+#define EBI_IRQBIT13 (0x2000L) // PIC #2 (1st slave)
+#define EBI_IRQBIT14 (0x4000L) // PIC #2 (1st slave)
+#define EBI_IRQBIT15 (0x8000L) // PIC #2 (1st slave)
+#define EBI_IRQBIT16 (0x10000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT17 (0x20000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT18 (0x40000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT19 (0x80000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT20 (0x100000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT21 (0x200000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT22 (0x400000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT23 (0x800000L) // PIC #3 (2nd slave)
+#define EBI_IRQBIT24 (0x1000000L) // SPI (See below)
+#define EBI_IRQBIT25 (0x2000000L) // LSI (See below)
+#define EBI_IRQBIT26 (0x4000000L) // IPI (See below)
+#define EBI_IRQBIT27 (0x8000000L) // Reserved
+#define EBI_IRQBIT28 (0x10000000L) // Reserved
+#define EBI_IRQBIT29 (0x20000000L) // Reserved
+#define EBI_IRQBIT30 (0x40000000L) // Reserved
+#define EBI_IRQBIT31 (0x80000000L) // Reserved
+
+#define EBI_SPI_IRQBIT (EBI_IRQBIT24)
+#define EBI_LSI_IRQBIT (EBI_IRQBIT25)
+#define EBI_IPI_IRQBIT (EBI_IRQBIT26)
+
+
+/*
+ * Constants used in powerSupplyInfo.present and onLine (See Below)
+ */
+#define POWER_SUPPLY_PRESENT (1)
+#define POWER_SUPPLY_ABSENT (0)
+#define POWER_SUPPLY_ONLINE (1)
+#define POWER_SUPPLY_OFFLINE (0)
+
+
+/*
+ * Power supply information structure.
+ */
+typedef struct {
+ dWord present; // 1 - Supply installed, 0 - absent
+ dWord onLine; // 1 - Supply providing nominal power, 0 - no power provided
+ dWord RESERVED[8]; // Unused at this time, reserved by AST
+} powerSupplyInfo;
+
+
+/*
+ * Front panel switch visibility values
+ */
+#define PANEL_SWITCHES_INVISIBLE (0)
+#define PANEL_SWITCHES_VISIBLE (1)
+
+
+/*
+ * 32-bit protected mode EBI II call structure. This structure is built
+ * based on the ROM offset table.
+ * Calls are made thusly:
+ *
+ * EBI_II callTab;
+ * void *MMIOTable;
+ * dWord numProcs;
+ *
+ * retStat = (callTab.GetNumProcs)( MMIOTable, &numProcsPtr );
+ */
+typedef struct EBI_II {
+ status (__cdecl *GetNumProcs)( void *MMIOTable, dWord *numProcs ); // 1
+ status (__cdecl *GetProcConf)( void *MMIOTable,
+ dWord processorID,
+ procConfigData *configData ); // 2
+ status (__cdecl *StartProc)( void *MMIOTable, dWord processorID ); // 3
+ status (__cdecl *StopProc)( void *MMIOTable, dWord processorID ); // 4
+ status (__cdecl *GetProcID)( void *MMIOTable, dWord *processorID ); // 5
+ status (__cdecl *EnableRAMCache)( void *MMIOTable ); // 6
+ status (__cdecl *DisableRAMCache)( void *MMIOTable ); // 7
+ status (__cdecl *FlushRAMCache)( void *MMIOTable, dWord flushType ); // 8
+ status (__cdecl *ControlCacheRegion)( void *MMIOTable,
+ dWord control,
+ physAddr start,
+ dWord length ); // 9
+ status (__cdecl *GetCacheControlInfo)( void *MMIOTable,
+ cacheControlInfo *info ); // 10
+ status (__cdecl *SetPanelUPS)( void *MMIOTable, dWord LEDColor ); // 11
+ status (__cdecl *GetPanelUPS)( void *MMIOTable, dWord *LEDColor ); // 12
+ status (__cdecl *SetPanelProcGraphMode)( void *MMIOTable,
+ dWord displayMode ); // 13
+ status (__cdecl *GetPanelProcGraphMode)( void *MMIOTable,
+ dWord *displayMode ); // 14
+ status (__cdecl *SetPanelProcGraphValue)( void *MMIOTable, dWord value ); // 15
+ status (__cdecl *GetPanelProcGraphValue)( void *MMIOTable, dWord *value ); // 16
+ status (__cdecl *LogProcIdle)( void *MMIOTable ); // 17
+ status (__cdecl *LogProcBusy)( void *MMIOTable ); // 18
+ status (__cdecl *GetPanelAttnSwitchLatch)( void *MMIOTable, dWord *latch ); // 19
+ status (__cdecl *GetPanelOffSwitchLatch)( void *MMIOTable, dWord *latch ); // 20
+ status (__cdecl *GetPanelKeyPos)( void *MMIOTable, dWord *keyPos ); // 21
+ status (__cdecl *GetPanelAlphaNumInfo)( void *MMIOTable,
+ dWord *displayType,
+ dWord *width ); // 22
+ status (__cdecl *GetPanelAlphaNum)( void *MMIOTable, byte *contents ); // 23
+ status (__cdecl *SetPanelAlphaNum)( void *MMIOTable, byte *string ); // 24
+ status (__cdecl *SetPanelOffSwitchMode)( void *MMIOTable, dWord mode ); // 25
+ status (__cdecl *GetPanelOffSwitchMode)( void *MMIOTable, dWord *mode ); // 26
+ status (__cdecl *GetIntSubsysType)( void *MMIOTable, dWord *subsystemType ); // 27
+ status (__cdecl *SetGlobalIntMask)( void *MMIOTable, dWord mask ); // 28
+ status (__cdecl *GetGlobalIntMask)( void *MMIOTable, dWord *mask ); // 29
+ status (__cdecl *SetLocalIntMask)( void *MMIOTable,
+ dWord mask,
+ dWord processorID ); // 30
+ status (__cdecl *GetLocalIntMask)( void *MMIOTable,
+ dWord *mask,
+ dWord processorID ); // 31
+ status (__cdecl *SetAdvIntMode)( void *MMIOTable ); // 32
+ status (__cdecl *SetIRQVectorAssign)( void *MMIOTable,
+ dWord IRQNum,
+ dWord vectorNum ); // 33
+ status (__cdecl *GetIRQVectorAssign)( void *MMIOTable,
+ dWord IRQNum,
+ dWord *vectorNum ); // 34
+ status (__cdecl *GetNumPowerSupplies)( void *MMIOTable,
+ dWord *numSupplies ); // 35
+ status (__cdecl *GetPowerSupplyInfo)( void *MMIOTable,
+ dWord supplyNum,
+ powerSupplyInfo *info ); // 36
+ status (__cdecl *DeInitEBI)( void *MMIOTable ); // 37
+ status (__cdecl *SetLSIVector)( void *MMIOTable,
+ dWord processorID,
+ dWord vector ); // 38
+ status (__cdecl *GetLSIVector)( void *MMIOTable,
+ dWord processorID,
+ dWord *vector ); // 39
+ status (__cdecl *SetSPIVector)( void *MMIOTable,
+ dWord processorID,
+ dWord vector ); // 40
+ status (__cdecl *GetSPIVector)( void *MMIOTable,
+ dWord processorID,
+ dWord *vector ); // 41
+ status (__cdecl *SetIPIVector)( void *MMIOTable,
+ dWord processorID,
+ dWord vector ); // 42
+ status (__cdecl *GetIPIVector)( void *MMIOTable,
+ dWord processorID,
+ dWord *vector ); // 43
+ status (__cdecl *SetIPIID)( void *MMIOTable, dWord processorID, dWord ID ); // 44
+ status (__cdecl *GetIPIID)( void *MMIOTable, dWord processorID, dWord *ID ); // 45
+ status (__cdecl *GenIPI)( void *MMIOTable, dWord ID ); // 46
+ status (__cdecl *GenLSI)( void *MMIOTable ); // 47
+ status (__cdecl *GetNMISource)( void *MMIOTable, dWord *NMISource ); // 48
+ status (__cdecl *GetSPISource)( void *MMIOTable, dWord *SPISource ); // 49
+ status (__cdecl *GetLocalIRQStatus)( void *MMIOTable,
+ dWord processorID,
+ dWord *inService,
+ dWord *requested ); // 50
+ status (__cdecl *MaskableIntEOI)( void *MMIOTable, dWord intNum ); // 51
+ status (__cdecl *NonMaskableIntEOI)( void *MMIOTable ); // 52
+ status (__cdecl *CancelInterrupt)( void *MMIOTable,
+ dWord mask,
+ dWord processorID ); // 53
+ status (__cdecl *GetSysTimer)( void *MMIOTable, dWord *timerValue ); // 54
+ status (__cdecl *GetSysTimerFreq)( void *MMIOTable, dWord *frequency ); // 55
+ status (__cdecl *GetNumMemBlocks)( void *MMIOTable, dWord *numBlocks ); // 56
+ dWord GetNumMemBlocks16; // Not accessable in protected mode // 57
+ status (__cdecl *GetMemBlockInfo)( void *MMIOTable,
+ memoryBlockInfo *blockInfo,
+ dWord blockNum ); // 58
+ dWord GetMemBlockInfo16; // Not accessable in protected mode // 59
+ status (__cdecl *GetMemErrorInfo)( void *MMIOTable, memoryErrorInfo *info ); // 60
+ status (__cdecl *GetRevision)( void *MMIOTable, revisionCode *rev ); // 61
+ status (__cdecl *GetNumSlots)( dWord *numSlots ); // 62
+ status (__cdecl *GetMMIOTable)( IOInfoTable *infoTable ); // 63
+ status (__cdecl *InitEBI)( void *MMIOTable ); // 64
+ status (__cdecl *GetThermalState)( void *MMIOTable, dWord *temperature ); // 65
+ status (__cdecl *ShutdownPowerSupply)( void *MMIOTable ); // 66
+ status (__cdecl *SimulatePowerFail)( void *MMIOTable,
+ dWord processorID ); // 67
+ status (__cdecl *SetPanelSwitchVisibility)( void *MMIOTable, dWord mode ); // 68
+ status (__cdecl *GetPanelSwitchVisibility)( void *MMIOTable, dWord *mode ); // 69
+ status (__cdecl *GetGlobalIRQStatus)( void *MMIOTable,
+ dWord *inService,
+ dWord *requested ); // 70
+ status (__cdecl *FastSetLocalIntMask)( dWord handle, dWord mask ); // 71
+ status (__cdecl *GetProcIntHandle)( void *MMIOTable,
+ dWord processorID,
+ dWord *handle ); // 72
+ status (__cdecl *RegSetLocalIntMask)(); //73
+ status (__cdecl *GetLocalIntMaskInfo)( void *MMIOTable, //74
+ maskInfo *info,
+ dWord proccessorID );
+ status (__cdecl *ASTx[22])( void *MMIOTable, ... ); // 75..96
+ status (__cdecl *OEM[32])( void *MMIOTable, ... ); // 97..128
+} EBI_II;
+
+#endif
+
+/* ----------------------- End of ebi_ii.h ----------------------- */
diff --git a/private/ntos/nthals/halast/i386/astebini.c b/private/ntos/nthals/halast/i386/astebini.c
new file mode 100644
index 000000000..5984377d3
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astebini.c
@@ -0,0 +1,189 @@
+/*++
+
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ astebini.c
+
+Abstract:
+
+ Initialization code for AST Manhattan system.
+
+Author:
+
+ Bob Beard (v-bobb) 24-Jul-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _NTOS_
+#include "nthal.h"
+#endif
+
+#include "halp.h"
+#include "astebiii.h"
+#include "astdisp.h"
+
+VOID DisplPanel(ULONG x);
+
+extern PVOID BiosPtr;
+
+// *** temporary way to do MMIOTable & EbiMemory
+#define MAX_EBI_SLOTS 32L
+VOID* EBI2_MMIOTable[MAX_EBI_SLOTS];
+#define MAX_EBI_MEMORY 1024L
+static UCHAR EbiMemory[MAX_EBI_MEMORY];
+
+//
+// EBI Revision
+//
+
+revisionCode EBI2_revision;
+
+//
+// Number of good processors in the system
+//
+
+ULONG EBI2_ProcCnt;
+ULONG MpCount; // zero based version for HalStartNextProcessor
+
+//
+// EBI_II function offset table
+//
+
+extern EBI_II EBI2_CallTab;
+
+
+BOOLEAN
+ASTInitEBI2()
+/*++
+
+Routine Description:
+ Initialize the AST EBI II environment. Only called if an AST machine
+ with EBI II capability. Gets table of EBI II call addresses in ebi_call_table.
+ Sets up EBI2_MMIOTable (EBI II Memory Mapped I/O Table).
+
+Arguments:
+ none.
+
+Return Value:
+ True if EBI II successfully initialized. False otherwise.
+
+--*/
+{
+
+ULONG i;
+//ULONG *Alias = (ULONG *)&EBI2_CallTab;
+//ebi_iiSig *Sig = (ebi_iiSig*)((ULONG)BiosPtr + EBI_II_SIGNATURE);
+//ULONG *OffTab;
+IOInfoTable IOInfo[MAX_EBI_SLOTS];
+dWord NumSlots;
+ULONG Pages;
+procConfigData ConfigData;
+ULONG ProcCount;
+
+//*** v-quangp: This table is already build at astdetct.c **
+//
+// Build the EBI II offset table
+//
+//
+// OffTab =(ULONG *) ((ULONG)BiosPtr + (REAL_TO_LIN(Sig->seg,Sig->off) -
+// REAL_TO_LIN(BIOS_SEG, 0)));
+// for( i = 0; i < ( sizeof( offsetTable ) / sizeof( ULONG )); i++ )
+// Alias[i] = OffTab[i] + (ULONG)BiosPtr;
+//
+//
+// Get the number of "slots" (logical address spaces)
+//
+
+EBI2_CallTab.GetNumSlots( &NumSlots );
+if (NumSlots > MAX_EBI_SLOTS)
+ { DisplPanel(HALSlotProblem); return(FALSE); }
+
+//
+// Get the Memory Mapped I/O Information
+//
+
+if ( (EBI2_CallTab.GetMMIOTable( IOInfo )))
+ { DisplPanel(HALMMIOProblem); return(FALSE); }
+
+for( i = 0; i < NumSlots; i++ )
+ if( IOInfo[i].length ) {
+
+//
+// Allocate some memory for EBI II
+//
+
+ if ( IOInfo[i].flags & ALLOCATE_RAM )
+ { if (IOInfo[i].length > MAX_EBI_MEMORY)
+ { DisplPanel(HALMemoryProblem); return(FALSE); }
+ EBI2_MMIOTable[i] = EbiMemory;
+ }
+
+//
+// Allocate a virtual address spanning the memory mapped I/O range
+// for a given slot.
+//
+
+ else {
+ Pages = IOInfo[i].length / PAGE_SIZE;
+ if ( IOInfo[i].length % PAGE_SIZE )
+ Pages++;
+ EBI2_MMIOTable[i] = HalpMapPhysicalMemory( (PVOID)IOInfo[i].address.low, Pages );
+ if ( EBI2_MMIOTable[i] == NULL )
+ { DisplPanel(HALPhysicalAllocProblem); return(FALSE); }
+ }
+ }
+
+//
+// Initialize EBI II
+//
+
+ if ( (EBI2_CallTab.InitEBI)( EBI2_MMIOTable ) )
+ { DisplPanel(HALEBIInitProblem); return(FALSE); }
+
+//
+// Put NT on the front panel display
+//
+
+ EBI2_CallTab.SetPanelAlphaNum( EBI2_MMIOTable, " NT ");
+
+//
+// Find out the number of good processors
+//
+
+ if ( (EBI2_CallTab.GetNumProcs)( EBI2_MMIOTable, &ProcCount ) )
+ { DisplPanel(HALEBIGetProcProblem); return(FALSE); }
+
+ EBI2_ProcCnt = ProcCount;
+ for (i=0; i<ProcCount; i++)
+ if ( (EBI2_CallTab.GetProcConf)( EBI2_MMIOTable, i, &ConfigData ) )
+ EBI2_ProcCnt--;
+
+ if (EBI2_ProcCnt == 0)
+ { DisplPanel(HALEBINoProcsProblem); return(FALSE); }
+
+ MpCount = EBI2_ProcCnt - 1;
+
+//
+// Turn on the front panel cpu activity bar graph in histogram mode
+//
+
+ EBI2_CallTab.SetPanelProcGraphMode( EBI2_MMIOTable, 0 );
+
+//
+// Get EBI2 Revision
+//
+
+if ( (EBI2_CallTab.GetRevision( EBI2_MMIOTable, &EBI2_revision )))
+ { DisplPanel(HALGetRevisionProblem); return(FALSE); }
+
+
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halast/i386/asthal.c b/private/ntos/nthals/halast/i386/asthal.c
new file mode 100644
index 000000000..d3be648dc
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/asthal.c
@@ -0,0 +1,364 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ asthal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ AST EBI2 (Manhattan) system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Bob Beard (v-bobb) 31-Jul-1992 convert for AST EBI2 system
+--*/
+
+#include "halp.h"
+#include "astdisp.h"
+
+ULONG HalpBusType;
+
+ADDRESS_USAGE HalpDefaultASTIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ // Standard PC ISA I/O space used...
+ 0x000, 0x10, // ISA DMA
+ 0x0C0, 0x10, // ISA DMA
+ 0x080, 0x10, // DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ 0x048, 0x4, // Timer2, Failsafe
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+ 0x0F0, 0x10, // coprocessor ports
+
+ // Standard PC EISA I/O space used...
+ 0x0D0, 0x10, // DMA
+ 0x400, 0x10, // DMA
+ 0x480, 0x10, // DMA
+ 0x4C2, 0xE, // DMA
+ 0x4D4, 0x2C, // DMA
+
+ 0x461, 0x2, // Extended NMI
+ 0x464, 0x2, // Last Eisa Bus Muster granted
+
+ 0x4D0, 0x2, // edge/level control registers
+
+ 0xC84, 0x1, // System board enable
+
+ // AST I/O Space used...
+
+ 0x0E8, 0x1, // XBus configuration register
+ 0x0EB, 0x1, // BIOS Flash register
+ 0x0EC, 0x2, // Front panel display addr/data registers
+
+ 0x36E, 0x2, // SuperIO Index/Data register set#1
+ 0x398, 0x2, // SuperIO Index/Data register set#2
+
+ 0, 0
+ }
+};
+
+
+ULONG
+HalpInitMP(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+EBI2_InitIpi(
+ IN ULONG ProcessorID
+ );
+
+BOOLEAN
+EBI2_InitSpi(
+ IN ULONG ProcessorID
+ );
+
+VOID
+ASTEnableCaches();
+
+extern CCHAR HalpIRQLtoVector[];
+extern ULONG MpCount;
+
+KSPIN_LOCK HalpSystemHardwareLock;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ x86 AST Manhattan system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ KIRQL CurrentIrql;
+ PKPRCB pPRCB;
+ ULONG BuildType;
+
+
+ pPRCB = KeGetCurrentPrcb();
+
+ if (Phase == 0) {
+
+ HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
+
+ //
+ // Verify Prcb version and build flags conform to
+ // this image
+ //
+
+ BuildType = 0;
+#if DBG
+ BuildType |= PRCB_BUILD_DEBUG;
+#endif
+#ifdef NT_UP
+ BuildType |= PRCB_BUILD_UNIPROCESSOR;
+#endif
+
+ if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ if (pPRCB->BuildType != BuildType) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 2, pPRCB->BuildType, BuildType, 0);
+ }
+
+
+ //
+ // Phase 0 initialization
+ // only called by P0
+ //
+
+
+ HalpInitializePICs();
+
+ //
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ CurrentIrql = KfRaiseIrql(CurrentIrql);
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Initialize CMOS
+ //
+
+ HalpInitializeCmos();
+
+ //
+ // Register base IO space used by hal
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultASTIoSpace);
+
+ HalpInitializeDisplay();
+
+ //
+ // Initialize spinlock used by HalGetBusData hardware access routines
+ //
+
+ KeInitializeSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ } else {
+
+ //
+ // Phase 1 initialization
+ //
+
+ //
+ // Enable caching on the processor
+ //
+
+ ASTEnableCaches();
+
+ if (pPRCB->Number == 0) {
+ HalpRegisterInternalBusHandlers ();
+ }
+
+ //
+ // Initialize the profile interrupt vector.
+ //
+
+ KiSetHandlerAddressToIDT( HalpIRQLtoVector[PROFILE_LEVEL],
+ HalpProfileInterrupt);
+
+ //
+ // enable PROFILE interrupt
+ //
+
+ HalEnableSystemInterrupt( HalpIRQLtoVector[PROFILE_LEVEL],
+ PROFILE_LEVEL, Latched);
+
+ //
+ // Initialize stall execution on each processor
+ //
+
+ HalpInitializeStallExecution(KeGetPcr()->Prcb->Number);
+
+ HalStopProfileInterrupt(0);
+
+ //
+ // Initialize the clock interrupt vector
+ //
+ //
+
+ KiSetHandlerAddressToIDT( HalpIRQLtoVector[CLOCK2_LEVEL],
+ HalpClockInterrupt);
+
+ //
+ // enable CLOCK2 interrupt
+ //
+
+ HalEnableSystemInterrupt( HalpIRQLtoVector[CLOCK2_LEVEL],
+ CLOCK2_LEVEL, Latched);
+
+// HalpEnableInterruptHandler (
+// DeviceUsage, // Report as device vector
+// 8, // Bus interrupt level
+// HalpIRQLtoVector[CLOCK2_LEVEL], // System IDT
+// CLOCK2_LEVEL, // System Irql
+// HalpClockInterrupt, // ISR
+// Latched );
+
+ //
+ // Initialize the IPI vector
+ //
+
+ EBI2_InitIpi(KeGetPcr()->Prcb->Number);
+
+ //
+ // Initialize the SPI vector
+ //
+
+ EBI2_InitSpi(KeGetPcr()->Prcb->Number);
+
+ //
+ // If this is the first processor, initialize the clock
+ //
+
+ if (pPRCB->Number == 0) {
+ HalpInitializeClock();
+ }
+ }
+
+ HalpInitMP(Phase, LoaderBlock);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halast/i386/astipi.asm b/private/ntos/nthals/halast/i386/astipi.asm
new file mode 100644
index 000000000..bb8467d6a
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astipi.asm
@@ -0,0 +1,268 @@
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 AST Research Inc.
+;
+;Module Name:
+;
+; astipi.asm
+;
+;Abstract:
+;
+; AST Manhattan IPI code.
+; Provides the HAL support for Interprocessor Interrupts for the
+; MP Manhattan implementation.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+; Bob Beard (v-bobb) 24-Jul-1992 added support for AST EBI2 machines
+;
+;Revision History:
+;
+; Quang Phan (v-quangp) 15-Dec-1992: Added code to get ProcIntHandle
+; for FastSetLocalIntMask calls.
+;
+; Quang Phan (v-quangp) 27-Aug-1992: Changed back to call ASTInitEBI2
+; at HalInitialzeProcessor (was at detectAST()).
+;--
+.386p
+ .xlist
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include callconv.inc
+include i386\astmp.inc
+include i386\kimacro.inc
+include i386\ix8259.inc
+
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalpInitializePICs,0
+ EXTRNP _HalDisplayString,1
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalDisableSystemInterrupt,2
+ EXTRNP _DetectAST,1
+ EXTRNP _DisplPanel,1
+ EXTRNP _EBI2_InitIpi,1
+ EXTRNP _ASTInitEBI2,0
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ extrn _HalpIRQLtoVector:BYTE
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+ extrn EBI2_InitLocalIntFunctions:NEAR
+ extrn _HalpDefaultInterruptAffinity:DWORD
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ public _HalpProcessorPCR, _HalpInitializedProcessors
+_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
+_HalpInitializedProcessors dd 0
+
+BadHalString db 'HAL: AST HAL.DLL cannot be run on non AST MP machine',cr,lf
+ db ' or AST MP machine not configured properly.',cr, lf
+ db ' Replace the hal.dll with the correct hal', cr, lf
+ db ' or configure the machine properly', cr, lf
+ db ' System is HALTING *********', 0
+
+BadEBIString db 'HAL: AST EBI2 cannot be initialized',cr,lf
+ db ' System is HALTING *********', 0
+
+MPFlag db 0 ; Flag for MP determination
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . Enable IPI interrupt (makes sense for P1, P2, ...).
+; . Save Processor Number in PCR.
+; . if (P0)
+; . determine what kind of system is it,
+; . if (NotAST_EBI2) Halt;
+; . Enable PINTs on CPU.
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor,1
+
+ ; Set initial interrupt bit mask for this processor
+
+ mov dword ptr fs:PcIDR, MaskAllIrqs ; Set to EBI2 Bit mask
+
+ ; EBI2 processor ID = NT processor ID
+
+ mov eax, [esp+4] ; Save processor # in PCR
+ mov fs:PcHal.PcrEBI2ProcessorID, eax
+ lock bts _HalpDefaultInterruptAffinity, eax
+ lock inc _HalpInitializedProcessors
+
+ mov ecx, fs:PcSelfPcr ; Flat address of this PCR
+ mov _HalpProcessorPCR[eax*4], ecx ; Save it away
+
+ mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
+
+ push eax
+ mov eax, TIME_INCREMENT
+ stdCall _KeSetTimeIncrement, <eax, eax>
+ pop eax
+
+ mov dword ptr fs:PcHal.PcrCpuLedRateCount, 0 ;init CpuLed rate count
+
+ or eax, eax
+ jnz ipi_10
+
+ ; Run on P0 only
+
+; Detect if AST machine
+ stdCall _DetectAST,<offset MPFlag>
+ or eax, eax
+ jz NotAST
+
+ stdCall _ASTInitEBI2 ; Init EBI2
+ or eax,eax
+ jz EBI2InitProblem
+
+ ; Done with P0 initialization
+
+ipi_10:
+
+ifdef QPTEST
+
+; Enable IPIs for each processor
+
+; push the processor number
+ stdCall _EBI2_InitIpi,<[esp+4]>
+ or eax, eax
+ jz NotAST
+
+endif
+;
+;Initialize data structure for EBI SetLocalMask call
+;
+ call EBI2_InitLocalIntFunctions
+ or eax,eax
+ jnz EBI2InitProblem
+
+;
+;Store EBI2 MMIO_Table for later use.
+;
+ lea eax,_EBI2_MMIOTable
+ mov fs:PcHal.PcrEBI2MMIOtable, eax
+
+ stdRET _HalInitializeProcessor
+
+NotAST:
+ stdCall _HalDisplayString, <offset BadHalString>
+@@: jmp short @b
+
+EBI2InitProblem:
+ stdCall _HalDisplayString, <offset BadEBIString>
+@@: jmp short @b
+
+stdENDP _HalInitializeProcessor
+
+
+;++
+;
+; VOID
+; HalpIPInterrupt (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by the
+; IPI hardware.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hipi_a, Hipi_t
+cPublicProc _HalpIPInterrupt,0
+
+;
+; Save machine state in trap frame
+;
+ ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
+;
+; Save previous IRQL
+;
+
+ movzx eax, _HalpIRQLtoVector[IPI_LEVEL]
+ push eax ;interrupt vector
+ sub esp, 4 ;space for OldIrql
+
+; esp &OldIrql
+; eax interrupt vector
+; IPI_LEVEL new Irql
+ ;raise to new Irql
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,eax,esp>
+ or al, al
+ jz Hipi100 ;jump if spurrious interrupt
+
+; Pass Null ExceptionFrame
+; Pass TrapFrame to Ipi service rtn
+
+ stdCall _KiIpiServiceRoutine,<ebp,0>
+
+
+;
+; Do interrupt exit processing
+;
+ INTERRUPT_EXIT ; will return to caller
+
+Hipi100:
+
+ DisplPanel HalSpuriousInterrupt4
+
+ add esp, 8 ; spurious, no EndOfInterrupt
+ EXIT_ALL ,,NoPreviousMode ; without lowering irql
+
+stdENDP _HalpIPInterrupt
+
+_TEXT ENDS
+ END
+
diff --git a/private/ntos/nthals/halast/i386/astipirq.c b/private/ntos/nthals/halast/i386/astipirq.c
new file mode 100644
index 000000000..88d7beb83
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astipirq.c
@@ -0,0 +1,155 @@
+/*++
+
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ astipirq.c
+
+Abstract:
+
+ IPI interrupt generation and initialization
+
+
+Author:
+
+ Bob Beard (v-bobb) 24-Jul-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "astebiii.h"
+#include "astdisp.h"
+
+extern VOID* EBI2_MMIOTable[];
+extern EBI_II EBI2_CallTab;
+extern CCHAR HalpIRQLtoVector[];
+VOID DisplPanel(ULONG x);
+VOID HalpIPInterrupt(VOID);
+VOID HalpSPInterrupt(VOID);
+
+KSPIN_LOCK EBI2_ipi_lock;
+
+BOOLEAN
+EBI2_InitIpi(
+ IN ULONG ProcessorID
+ )
+/*++
+
+Routine Description:
+ Initialize the IPI for this processor
+
+Arguments:
+ ProcessorID - The EBI2 processor to be initialized for IPI
+
+Return Value:
+ TRUE if IPI set up properly. FALSE otherwise.
+
+--*/
+{
+
+// *** Hack to get around EBI2 problem of destroying ebx on call
+// to SetIpiVector
+ULONG EBI2_Hack_Val;
+
+EBI2_Hack_Val = ProcessorID+1;
+
+if ( EBI2_CallTab.SetIPIVector( EBI2_MMIOTable, ProcessorID,
+ HalpIRQLtoVector[IPI_LEVEL] ) )
+ {DisplPanel(HALIpiInitVecProblem); return(FALSE); }
+
+//if ( EBI2_CallTab.SetIPIID( EBI2_MMIOTable, ProcessorID,
+// (1 << ProcessorID) ) )
+if ( EBI2_CallTab.SetIPIID( EBI2_MMIOTable, (EBI2_Hack_Val-1),
+ (1 << (EBI2_Hack_Val-1) ) ) )
+ {DisplPanel(HALIpiInitIDProblem); return(FALSE); }
+
+
+KiSetHandlerAddressToIDT( HalpIRQLtoVector[IPI_LEVEL], HalpIPInterrupt );
+
+KeInitializeSpinLock( &EBI2_ipi_lock );
+
+HalEnableSystemInterrupt( HalpIRQLtoVector[IPI_LEVEL], IPI_LEVEL, Latched );
+
+return(TRUE);
+
+}
+
+VOID
+HalRequestIpi(
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+ Generate an IPI to each processor requested in the Mask
+
+Arguments:
+ Mask - a bit mask of the processors to be interrupted
+
+Return Value:
+ None.
+
+--*/
+{
+
+ _asm {
+ pushfd
+ cli
+ }
+
+ KiAcquireSpinLock( &EBI2_ipi_lock);
+ EBI2_CallTab.GenIPI( EBI2_MMIOTable, Mask );
+ KiReleaseSpinLock( &EBI2_ipi_lock);
+
+ _asm {
+ popfd
+ }
+}
+
+BOOLEAN
+EBI2_InitSpi(
+ IN ULONG ProcessorID
+ )
+/*++
+
+Routine Description:
+ Initialize the SPI for this processor
+
+Arguments:
+ ProcessorID - The EBI2 processor to be initialized for SPI
+
+Return Value:
+ TRUE if SPI set up properly. FALSE otherwise.
+
+--*/
+{
+
+//
+// Set the vector for SPI
+//
+
+if ( EBI2_CallTab.SetSPIVector( EBI2_MMIOTable, ProcessorID,
+ HalpIRQLtoVector[POWER_LEVEL] ) )
+ {DisplPanel(HALSpiInitVecProblem); return(FALSE); }
+
+
+KiSetHandlerAddressToIDT( HalpIRQLtoVector[POWER_LEVEL], HalpSPInterrupt );
+
+HalEnableSystemInterrupt( HalpIRQLtoVector[POWER_LEVEL], POWER_LEVEL, Latched );
+
+//
+// Make the switches visible to software
+//
+
+EBI2_CallTab.SetPanelSwitchVisibility( EBI2_MMIOTable, PANEL_SWITCHES_VISIBLE);
+
+return(TRUE);
+
+}
diff --git a/private/ntos/nthals/halast/i386/astirql.asm b/private/ntos/nthals/halast/i386/astirql.asm
new file mode 100644
index 000000000..349984167
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astirql.asm
@@ -0,0 +1,1110 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1992 AST Research Inc.
+;
+; Module Name:
+;
+; astirql.asm
+;
+; Abstract:
+;
+; ASTMP IRQL
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the AST MP hardware.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Quang Phan (v-quangp) 15-Dec-92
+; Implemented the fast SetLocalInterruptMask in Raise/LowerIrql.
+; Removed spinlock in Raise/LowerIrql routines.
+;
+; Quang Phan (v-quangp) 24-Jul-1992
+; Converted to AST MP hardware.
+;
+; John Vert (jvert) 27-Nov-1991
+; Moved from kernel into HAL
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include mac386.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include i386\astebi2.inc
+include i386\astmp.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ extrn _HalpApcInterrupt:NEAR
+ extrn _HalpDispatchInterrupt:NEAR
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+ extrn _KiUnexpectedInterrupt:NEAR
+ extrn _HalpBusType:DWORD
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+ extrn _EBI2_Lock:DWORD
+ extrn HalpIRQLtoEBIIntNumber:DWORD
+ extrn _EBI2_revision:DWORD
+ EXTRNP _DisplPanel,1
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+;
+; Interrupt flag bit maks for EFLAGS
+;
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+;
+;
+; IRQL level of hardware interrupts
+;
+HARDWARE_LEVEL equ 12
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+;
+;;;;;;;;;;;;;;;;
+;
+; Information for irq, irql and mask (EBI2) translation
+;
+;System System Bus
+;IRQL EBI Vector IRQ Common use Name
+;----- --- ------ ------ ---------- ----
+; 00 LOW_LEV
+; 01 APC_LEVEL
+; 02 25 ??? LSI DPC_LEVEL
+; 03 WAKE_LEVEL
+; 04
+; 05
+; 06
+; 07
+; 08
+; 09
+; 10
+; 11
+; 12 7 PVB+7 EISA IRQ7 LPT1
+; 13 6 PVB+6 EISA IRQ6 Flpy
+; 14 5 PVB+5 EISA IRQ5 LPT2
+; 15 4 PVB+4 EISA IRQ4 COM1
+; 16 3 PVB+3 EISA IRQ3 COM2
+; 17 15 PVB+15 EISA IRQ15
+; 18 14 PVB+14 EISA IRQ14 AT disk
+; 19 13 PVB+13 EISA IRQ13
+; 20 12 PVB+12 EISA IRQ12
+; 21 11 PVB+11 EISA IRQ11
+; 22 10 PVB+10 EISA IRQ10
+; 23 9 PVB+9 EISA IRQ9
+; 24 8 PVB+8 EISA IRQ8
+; 25 2 PVB+9 EISA IRQ2 (IRQ chaining)
+; 26 1 PVB+1 EISA IRQ1 Kbd
+; 27 0 PVB+0 EISA IRQ8 RTC PROFILE_LEVEL
+; 28 8 PVB EISA IRQ0 CLOCK2_LEVEL
+; 29 26 PVB+26 IPI IPI_LEVELx
+; 30 24 PVB+24 SPI POWER_LEVEL
+; 31 HIGH_LEVEL
+;
+;
+; Notes:
+; 1. PVB: PRIMARY_VECTOR_BASE = 30h (PIC1BASE = 30h, PIC2BASE = 38h)
+;
+;;;;;;;;;;;;;;;;
+;
+; CCHAR HalpIRQLtoEBIBitMask[32]; This array is used to get the value
+; for the EBI bitmask from the KIRQL.
+ Public _HalpIRQLtoEBIBitMask
+ align 4
+_HalpIRQLtoEBIBitMask Label Byte
+ dd 0 ;IRQL 0 (Unused Mask)
+ dd 0 ;IRQL 1
+ dd 1 SHL (IRQ_25) ;IRQL 2 (EBI IRQ-25)
+ dd 0 ;IRQL 3
+ dd 0 ;IRQL 4
+ dd 0 ;IRQL 5
+ dd 0 ;IRQL 6
+ dd 0 ;IRQL 7
+ dd 0 ;IRQL 8
+ dd 0 ;IRQL 9
+ dd 0 ;IRQL 10
+ dd 0 ;IRQL 11
+ dd 1 SHL (IRQ_7) ;IRQL 12
+ dd 1 SHL (IRQ_6) ;IRQL 13
+ dd 1 SHL (IRQ_5) ;IRQL 14
+ dd 1 SHL (IRQ_4) ;IRQL 15
+ dd 1 SHL (IRQ_3) ;IRQL 16
+ dd 1 SHL (IRQ_15) ;IRQL 17
+ dd 1 SHL (IRQ_14) ;IRQL 18
+ dd 1 SHL (IRQ_13) ;IRQL 19
+ dd 1 SHL (IRQ_12) ;IRQL 20
+ dd 1 SHL (IRQ_11) ;IRQL 21
+ dd 1 SHL (IRQ_10) ;IRQL 22
+ dd 1 SHL (IRQ_9) ;IRQL 23
+ dd 1 SHL (IRQ_8) ;IRQL 24
+ dd 1 SHL (IRQ_2) ;IRQL 25
+ dd 1 SHL (IRQ_1) ;IRQL 26
+ dd 1 SHL (IRQ_8) ;IRQL 27 (IRQ-8) (Profile clock)
+ dd 0 ;IRQL 28 (IRQ-0) (clock)
+ dd 1 SHL (IRQ_26) ;IRQL 29 (IPI-0)
+ dd 1 SHL (IRQ_24) ;IRQL 30 (SPI-0)
+ dd 0 ;IRQL 31
+;
+; CCHAR HalpIRQLtoVector[36]; this array is used to get the interrupt
+; vector used for a given KIRQL, zero
+; means no vector is used for the KIRQL
+ Public _HalpIRQLtoVector
+_HalpIRQLtoVector Label Byte
+; ;IRQL
+ db 0 ;0
+ db 0 ;1 APC_LEVEL
+ db 0 ;2 DISPATCH_LEVEL
+ db 0 ;3 WAKE_LEVEL
+ db 0 ;4
+ db 0 ;5
+ db 0 ;6
+ db 0 ;7
+ db 0 ;8
+ db 0 ;9
+ db 0 ;10
+ db 0 ;11
+ db PRIMARY_VECTOR_BASE+7 ;12 irq7
+ db PRIMARY_VECTOR_BASE+6 ;13 irq6
+ db PRIMARY_VECTOR_BASE+5 ;14 irq5
+ db PRIMARY_VECTOR_BASE+4 ;15 irq4
+ db PRIMARY_VECTOR_BASE+3 ;16 irq3
+ db PRIMARY_VECTOR_BASE+15 ;17 irq15
+ db PRIMARY_VECTOR_BASE+14 ;18 irq14
+ db PRIMARY_VECTOR_BASE+13 ;19 irq13
+ db PRIMARY_VECTOR_BASE+12 ;20 irq12
+ db PRIMARY_VECTOR_BASE+11 ;21 irq11
+ db PRIMARY_VECTOR_BASE+10 ;22 irq10
+ db PRIMARY_VECTOR_BASE+9 ;23 irq9
+ db PRIMARY_VECTOR_BASE+8 ;24 irq8
+ db 0 ;25 irq2 (used for chaining)
+ db PRIMARY_VECTOR_BASE+1 ;26 irq1
+ db PRIMARY_VECTOR_BASE+8 ;27 irq8 PROFILE_LEVEL
+ db PRIMARY_VECTOR_BASE ;28 irq0 CLOCK2_LEVEL
+ db PRIMARY_VECTOR_BASE+26 ;29 IPI_LEVEL
+ db PRIMARY_VECTOR_BASE+24 ;30 POWER_LEVEL (SPI)
+ db 0 ;prevent CPL 0 enable changes ;HIGH_LEVEL
+ db 0, 0, 0, 0 ;four extra levels for good luck
+
+;
+; CCHAR HalpBusIntToIRQL[16]; this array is used to get the IRQL
+; from the the Bus Interrupt number
+ Public _HalpBusIntToIRQL
+_HalpBusIntToIRQL Label Byte
+; IRQL ;Bus Interrupt number
+ db CLOCK2_LEVEL ;0
+ db PROFILE_LEVEL-1 ;1
+ db 0 ;2
+ db PROFILE_LEVEL-11 ;3
+ db PROFILE_LEVEL-12 ;4
+ db PROFILE_LEVEL-13 ;5
+ db PROFILE_LEVEL-14 ;6
+ db PROFILE_LEVEL-15 ;7
+ db PROFILE_LEVEL-3 ;8
+ db PROFILE_LEVEL-4 ;9
+ db PROFILE_LEVEL-5 ;10
+ db PROFILE_LEVEL-6 ;11
+ db PROFILE_LEVEL-7 ;12
+ db PROFILE_LEVEL-8 ;13
+ db PROFILE_LEVEL-9 ;14
+ db PROFILE_LEVEL-10 ;15
+
+;
+;Translation table from Irql to EBI interrupt bit mask. This table is
+;used for setting the processor interrupt level (irql)
+;
+ public KiEBI2IntMaskTable
+KiEBI2IntMaskTable label dword
+ align 4
+
+; ILS <--- irqs ----->
+; PSP
+; III 11.. ..10
+; ... 54 ..
+; vvv vv vv
+;
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 00000000000000000000000000000000B ; irql 4
+ dd 00000010000000000000000000000000B ; irql 5
+ dd 00000010000000000000000000000000B ; irql 6
+ dd 00000010000000000000000000000000B ; irql 7
+ dd 00000010000000000000000000000000B ; irql 8
+ dd 00000010000000000000000000000000B ; irql 9
+ dd 00000010000000000000000000000000B ; irql 10
+ dd 00000010000000000000000000000000B ; irql 11
+ dd 00000010000000000000000010000000B ; irql 12 irq7
+ dd 00000010000000000000000011000000B ; irql 13 irq6
+ dd 00000010000000000000000011100000B ; irql 14 irq5
+ dd 00000010000000000000000011110000B ; irql 15 irq4
+ dd 00000010000000000000000011111000B ; irql 16 irq3
+ dd 00000010000000001000000011111000B ; irql 17 irq15
+ dd 00000010000000001100000011111000B ; irql 18 irq14
+ dd 00000010000000001110000011111000B ; irql 19 irq13
+ dd 00000010000000001111000011111000B ; irql 20 irq12
+ dd 00000010000000001111100011111000B ; irql 21 irq11
+ dd 00000010000000001111110011111000B ; irql 22 irq10
+ dd 00000010000000001111111011111000B ; irql 23 irq9
+ dd 00000010000000001111111111111010B ; irql 24 irq8
+ dd 00000010000000001111111011111000B ; irql 25 irq2
+ dd 00000010000000001111111011111010B ; irql 26 irq1
+ dd 00000010000000001111111111111010B ; irql 27 irq8 (Profile)
+ dd 00000010000000001111111111111011B ; irql 28 irq0
+ dd 00000110000000001111111111111011B ; irql 29 ipi
+ dd 00000111000000001111111111111011B ; irql 30 spi
+ dd 00000111000000001111111111111011B ; irql 31
+;
+; 10987654321098765432109876543210- ; bit position
+;
+ align 4
+;
+; The following tables define the addresses of software interrupt routers
+; Use this table if there is NO machine state frame on stack already
+;
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 4
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 5
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 6
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 7
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 8
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 9
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 10
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 11
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 12
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 13
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 14
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 15
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 16
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 17
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 18
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 19
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 20
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 21
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 22
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 23
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 24
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 25
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 26
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 27
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 28
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 29)
+
+ public ASTSWInterruptHandlerTable
+ASTSWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_ASTDispatchInterrupt ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 4
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 5
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 6
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 7
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 8
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 9
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 10
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 11
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 12
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 13
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 14
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 15
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 16
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 17
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 18
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 19
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 20
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 21
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 22
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 23
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 24
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 25
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 26
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 27
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 28
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 29)
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+ db 3 ; SWIRR=8, so highest pending SW irql= 3
+ db 3 ; SWIRR=9, so highest pending SW irql= 3
+ db 3 ; SWIRR=A, so highest pending SW irql= 3
+ db 3 ; SWIRR=B, so highest pending SW irql= 3
+ db 3 ; SWIRR=C, so highest pending SW irql= 3
+ db 3 ; SWIRR=D, so highest pending SW irql= 3
+ db 3 ; SWIRR=E, so highest pending SW irql= 3
+ db 3 ; SWIRR=F, so highest pending SW irql= 3
+
+ db 4 ; SWIRR=10, so highest pending SW irql= 4
+ db 4 ; SWIRR=11, so highest pending SW irql= 4
+ db 4 ; SWIRR=12, so highest pending SW irql= 4
+ db 4 ; SWIRR=13, so highest pending SW irql= 4
+ db 4 ; SWIRR=14, so highest pending SW irql= 4
+ db 4 ; SWIRR=15, so highest pending SW irql= 4
+ db 4 ; SWIRR=16, so highest pending SW irql= 4
+ db 4 ; SWIRR=17, so highest pending SW irql= 4
+ db 4 ; SWIRR=18, so highest pending SW irql= 4
+ db 4 ; SWIRR=19, so highest pending SW irql= 4
+ db 4 ; SWIRR=1A, so highest pending SW irql= 4
+ db 4 ; SWIRR=1B, so highest pending SW irql= 4
+ db 4 ; SWIRR=1C, so highest pending SW irql= 4
+ db 4 ; SWIRR=1D, so highest pending SW irql= 4
+ db 4 ; SWIRR=1E, so highest pending SW irql= 4
+ db 4 ; SWIRR=1F, so highest pending SW irql= 4
+
+
+ public EBI2_ProcIntHandle
+ public EBI2_maskInfo
+EBI2_maskInfo dd 8 dup(0)
+EBI2_ProcIntHandle dd 0
+
+
+
+
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (ecx) = NewIrql - the new irql to be raised to
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+; equates for accessing arguments
+; since eflags and iret addr are pushed into stack, all the arguments
+; offset by 8 bytes
+;
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,1
+
+ pushfd
+ cli
+ movzx eax,cl ; get new irql value
+ movzx ecx,byte ptr fs:PcIrql ; get current irql
+
+if DBG
+ cmp cl,al ; old > new?
+ jbe short Kri99 ; no, we're OK
+ push eax ; put new irql where we can find it
+ push ecx ; put old irql where we can find it
+ mov byte ptr fs:PcIrql,0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL>
+Kri99:
+endif
+ mov fs:PcIrql, al ; set the new irql
+ cmp al,HARDWARE_LEVEL ; software level?
+ jb short kri10 ; go skip setting 8259 hardware
+
+;
+;Disable interrupt locally. Depending on type of hardware this function
+;will jump to the appropriate code that was setup priviously via the
+;PcrEBI2SetLocalIntMaskFunction pointer
+;
+ mov eax,KiEBI2IntMaskTable[eax*4] ;get ebi2 bitmask (eax=irql)
+ or eax,fs:PcIDR ;mask off irq which disabled
+ jmp dword ptr fs:[PcHal.PcrEBI2RaiseIrqlFunction]
+
+
+;----------------------------
+;
+;Code for using direct hardware access (32-bit interface hw)
+;
+KriDirectAccessIntMask32:
+
+ mov edx,fs:PcHal.PcrEBI2portAddress0
+ mov dword ptr [edx], eax
+ mov eax, dword ptr [edx] ;flush write buffer
+;
+;
+; Note: It is very important that we set the old irql AFTER we raised to
+; the new irql. Otherwise, if there is an interrupt that comes in between
+; and the OldIrql is not a local variable, the caller will get the wrong
+; OldIrql. The bottom line is the raising irql and returning old irql has
+; to be atomic to the caller.
+
+kri10:
+ mov eax, ecx ; (al) = OldIrql
+ popfd ; restore flags (including interrupts)
+
+ fstRET KfRaiseIrql
+
+
+
+;----------------------------
+;
+;Code for using direct hardware access (8-bit interface hw)
+;
+KriDirectAccessIntMask8:
+
+ mov edx,fs:PcHal.PcrEBI2portAddress0
+ mov byte ptr [edx], al
+ mov edx,fs:PcHal.PcrEBI2portAddress1
+ mov byte ptr [edx], ah
+ shr eax,24 ;get mask bit 24-31
+ mov edx,fs:PcHal.PcrEBI2portAddress3
+ mov byte ptr [edx], al
+ mov al, byte ptr [edx] ;flush write buffer
+
+ mov eax, ecx ; (al) = OldIrql
+ popfd ; restore flags (including interrupts)
+
+ fstRET KfRaiseIrql
+
+
+
+;----------------------------
+;
+;Code for using RegisterEBI2 Call
+;eax=intMask
+;
+KriRegSetLocalIntMask:
+
+ push esi
+ push ecx
+ mov esi,fs:PcHal.PcrEBI2ProcInterruptHandle
+ lea edx, _EBI2_CallTab
+ call [edx]+RegSetLocalIntMask
+ pop esi ;restore esi
+ pop eax
+
+ popfd ; restore flags (including interrupts)
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+
+ page ,132
+ subttl "Lower irql"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+cPublicFastCall KfLowerIrql,1
+ pushfd ; save caller's eflags
+ cli
+ movzx ecx, cl ; get new irql value
+ mov al, fs:PcIrql ; get old irql value
+
+if DBG
+ cmp cl,al
+ jbe short Kli99
+ push ecx ; new irql for debugging
+ push fs:PcIrql ; old irql for debugging
+ mov byte ptr fs:PcIrql,HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
+Kli99:
+endif
+ cmp al,HARDWARE_LEVEL ; see if hardware was masked
+ jb short Soft_Ints
+
+
+;
+;Disable interrupt locally. Depending on type of hardware this function
+;will jump to the appropriate code that was setup priviously via the
+;PcrEBI2SetLocalIntMaskFunction pointer
+;
+ mov eax,KiEBI2IntMaskTable[ecx*4] ;get ebi2 bitmask (eax=irql)
+ jmp dword ptr fs:[PcHal.PcrEBI2LowerIrqlFunction]
+
+
+;----------------------------
+;
+;Code for using direct hardware access (32-bit interface hw)
+;
+KliDirectAccessIntMask32:
+
+ or eax,fs:PcIDR ;mask off irq which disabled
+ mov edx,fs:PcHal.PcrEBI2portAddress0
+ mov dword ptr [edx], eax
+ mov eax, dword ptr [edx] ;flush write buffer
+
+Soft_Ints:
+ mov fs:PcIrql, cl ; save new IRQL
+Kli02a:
+ mov edx, fs:dword ptr PcIRR
+ and edx,0Eh ; mask for valid IRR bits
+ jnz short Kli09a ; jump if yes
+
+Kli08a:
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql ; RETURN
+
+Kli09a:
+ movzx eax, SWInterruptLookUpTable[edx]
+;
+;When we come to Kli10a, (eax) = soft interrupt index
+;
+Kli10a:
+ cmp al, fs:PcIrql ; compare with current IRQL
+ jna short Kli08a ; jump if higher priority
+
+ call ASTSWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+ jmp short Kli02a ; check for another
+
+
+
+;----------------------------
+;
+;Code for using direct hardware access (8-bit interface hw)
+;
+KliDirectAccessIntMask8:
+
+ or eax,fs:PcIDR ;mask off irq which disabled
+ mov edx,fs:PcHal.PcrEBI2portAddress0
+ mov byte ptr [edx], al
+ mov edx,fs:PcHal.PcrEBI2portAddress1
+ mov byte ptr [edx], ah
+ shr eax,24 ;get mask bit 24-31
+ mov edx,fs:PcHal.PcrEBI2portAddress3
+ mov byte ptr [edx], al
+ mov al, byte ptr [edx] ;flush write buffer
+
+ mov fs:PcIrql, cl ; save new IRQL
+Kli02:
+ mov edx, fs:dword ptr PcIRR
+ and edx,0Eh ; mask for valid IRR bits
+ jnz short Kli09 ; jump if yes
+
+Kli08:
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql ; RETURN
+
+Kli09:
+ movzx eax, SWInterruptLookUpTable[edx]
+;
+;When we come to Kli10, (eax) = soft interrupt index
+;
+Kli10:
+ cmp al, fs:PcIrql ; compare with current IRQL
+ jna short Kli08 ; jump if higher priority
+
+ call ASTSWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+ jmp short Kli02 ; check for another
+
+
+;----------------------------
+;
+;Code for using RegisterEBI2 Call
+;eax=intMask
+;
+KliRegSetLocalIntMask:
+
+ or eax,fs:PcIDR ;mask off irq which disabled
+ push esi
+ mov esi,fs:PcHal.PcrEBI2ProcInterruptHandle
+ lea edx, _EBI2_CallTab
+ call [edx]+RegSetLocalIntMask
+ pop esi
+
+ mov fs:PcIrql, cl ; save new IRQL
+Kli02b:
+ mov edx, fs:dword ptr PcIRR
+ and edx,0Eh ; mask for valid IRR bits
+ jnz short Kli09b ; jump if yes
+
+Kli08b:
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql ; RETURN
+
+Kli09b:
+ movzx eax, SWInterruptLookUpTable[edx]
+;
+;When we come to Kli10b, (eax) = soft interrupt index
+;
+Kli10b:
+ cmp al, fs:PcIrql ; compare with current IRQL
+ jna short Kli08b ; jump if higher priority
+
+ call ASTSWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+ jmp short Kli02b ; check for another
+fstENDP KfLowerIrql
+
+cPublicProc _HalpEndSoftwareInterrupt,1
+cPublicFpo 1,0
+ mov ecx, [esp+4]
+ fstCall KfLowerIrql
+ stdRet _HalpEndSoftwareInterrupt
+stdENDP _HalpEndSoftwareInterrupt
+
+
+
+;++
+;
+; VOID
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+HeiNewIrql equ byte ptr [esp + 4]
+HeiVector equ byte ptr [esp + 8]
+
+cPublicProc _HalEndSystemInterrupt,2
+
+ lea eax, _EBI2_Lock
+EndIntAcquire:
+ cli
+ ACQUIRE_SPINLOCK eax, EndIntSpin
+;
+ movzx eax, HeiVector
+ ; to EOI
+ sub eax, PRIMARY_VECTOR_BASE ; get EBI2 Interrupt number
+ push eax ; EOI the interrupt
+ CALL_EBI2 MaskableIntEOI,2
+
+if DBG
+ or eax, eax
+ je EOI_OK
+ DisplPanel HalEndSystemInterruptEnter
+EOI_OK:
+endif ;DBG
+;
+ lea eax, _EBI2_Lock
+EndIntRelease:
+ RELEASE_SPINLOCK eax
+
+ mov ecx, dword ptr HeiNewIrql
+ fstCall KfLowerIrql
+ stdRet _HalEndSystemInterrupt
+
+EndIntSpin:
+ SPIN_ON_SPINLOCK eax, EndIntAcquire
+
+
+stdENDP _HalEndSystemInterrupt
+
+;++
+;
+; VOID
+; ASTDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This is HalpDispatchInterrupt from IXSWINT.ASM. It's a pre-ship
+; fix for a stack overflow condition found on an AST machine.
+; This function assumes that the caller will re-check for a DPC
+; interrupt and loop, whereas the normal HalpDispatchInterrupt calls
+; lowerirql.
+;
+; Arguments:
+; Return Value:
+;--
+
+ ENTER_DR_ASSIST ahdpi_a, ahdpi_t
+
+ align dword
+ public _ASTDispatchInterrupt
+_ASTDispatchInterrupt proc
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT ahdpi_a, ahdpi_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+; Save previous IRQL and set new priority level
+
+ push PCR[PcIrql] ; save previous IRQL
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
+ btr dword ptr PCR[PcIRR], DISPATCH_LEVEL; clear the pending bit in IRR
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; Go do Dispatch Interrupt processing
+;
+ stdCall _KiDispatchInterrupt
+
+;
+; Do interrupt exit processing
+;
+ cli
+ pop eax ; saved irql
+ mov PCR[PcIrql], al ; restore it
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI
+ ; (return to loop in LowerIrql)
+_ASTDispatchInterrupt endp
+
+ page ,132
+ subttl "Specific Raise irql functions"
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+
+ mov ecx, DISPATCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+
+ mov ecx, SYNCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+ page ,132
+ subttl "Get current irql"
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql,0
+ movzx eax, byte ptr fs:PcIrql ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+
+ ;
+ ; Raising to HIGH_LEVEL disables interrupts for the ast HAL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+
+
+;++
+;
+; EBI2_InitLocalMaskFunctionPtr
+;
+; Routine Description:
+;
+; This routine is called during processor initialization (P1).
+; It will setup the data structure used by RaiseIrql and LowerIrql.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None
+;
+;--
+
+
+ Public EBI2_InitLocalIntFunctions
+EBI2_InitLocalIntFunctions Proc
+
+;
+; Get EBI2 Revision#. This version of HAL requires EBI2 rev >= 2.9
+; If 2.9 then use RegSetLocalIntMask; Else, use directly access hw
+; to set LocalIntMask.
+;
+ lea eax, _EBI2_revision
+ cmp [eax].major,2
+ jb EBI2_InitLocalIntRet
+
+ cmp [eax].minor,9
+ jb EBI2_InitLocalIntRet
+;
+; Get Processor's Interrupt handler for each processor
+;
+ mov eax,offset EBI2_ProcIntHandle
+ push eax
+ mov eax,fs:PcHal.PcrEBI2ProcessorID
+ push eax ; push the processor number
+ CALL_EBI2 GetProcIntHandle,3
+ or eax, eax
+ jnz EBI2_InitLocalIntRet
+ mov eax,EBI2_ProcIntHandle
+ mov dword ptr fs:PcHal.PcrEBI2ProcInterruptHandle,eax ;save int hdlr
+
+;
+;Set function pointer for Raise and Lower Irql functions to use
+;RegSetLocalIntMask as default
+;
+ mov eax,offset FLAT:KriRegSetLocalIntMask
+ mov fs:PcHal.PcrEBI2RaiseIrqlFunction,eax
+
+ mov eax,offset FLAT:KliRegSetLocalIntMask
+ mov fs:PcHal.PcrEBI2LowerIrqlFunction,eax
+;
+;Check for Rev.minor >= 10. If it is then use direct hardware access
+;to set LocalIntMask.
+;
+ lea eax, _EBI2_revision
+ cmp [eax].minor,10
+ jb EBI2_InitLocalIntRet2
+
+;
+; Get Processor's LocalMaskInfo for each processor
+;
+ mov eax,fs:PcHal.PcrEBI2ProcessorID
+ push eax ; push the processor number
+ mov eax,offset EBI2_maskInfo
+ push eax
+ CALL_EBI2 GetLocalIntMaskInfo,3
+ or eax, eax
+ jnz EBI2_InitLocalIntRet
+ mov eax,EBI2_MaskInfo.portAddress0
+ mov dword ptr fs:PcHal.PcrEBI2portAddress0,eax
+ mov eax,EBI2_MaskInfo.portAddress1
+ mov dword ptr fs:PcHal.PcrEBI2portAddress1,eax
+ mov eax,EBI2_MaskInfo.portAddress2
+ mov dword ptr fs:PcHal.PcrEBI2portAddress2,eax
+ mov eax,EBI2_MaskInfo.portAddress3
+ mov dword ptr fs:PcHal.PcrEBI2portAddress3,eax
+
+ mov eax,EBI2_MaskInfo.flags
+ and eax,PORT_TYPE_MASK
+ cmp eax,PORT_TYPE_MEMORY
+ jne short EBI2_InitLocalIntRet ;else set error exit
+
+ mov eax,EBI2_MaskInfo.flags
+ and eax,PORT_WIDTH_MASK
+ cmp eax,THIRTY_TWO_BIT_PORT
+ je short EBI2_ILIF32
+ cmp eax,EIGHT_BIT_PORTS
+ je short EBI2_ILIF08
+ jmp short EBI2_InitLocalIntRet ;else set error exit
+
+EBI2_ILIF08:
+;
+;Set function pointer for Raise and Lower Irql to use
+;direct hw access for setting LocalIntMask (8-bit hw).
+;
+ mov eax,offset FLAT:KriDirectAccessIntMask8
+ mov fs:PcHal.PcrEBI2RaiseIrqlFunction,eax
+
+ mov eax,offset FLAT:KliDirectAccessIntMask8
+ mov fs:PcHal.PcrEBI2LowerIrqlFunction,eax
+ jmp short EBI2_InitLocalIntRet2
+
+EBI2_ILIF32:
+;
+;Set function pointer for Raise and Lower Irql to use
+;direct hw access for setting LocalIntMask. (32-bit hw)
+;
+ mov eax,offset FLAT:KriDirectAccessIntMask32
+ mov fs:PcHal.PcrEBI2RaiseIrqlFunction,eax
+
+ mov eax,offset FLAT:KliDirectAccessIntMask32
+ mov fs:PcHal.PcrEBI2LowerIrqlFunction,eax
+
+
+EBI2_InitLocalIntRet2:
+ xor eax,eax ;return status
+
+EBI2_InitLocalIntRet:
+ ret
+
+EBI2_InitLocalIntFunctions Endp
+
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halast/i386/astmp.inc b/private/ntos/nthals/halast/i386/astmp.inc
new file mode 100644
index 000000000..ebb46a101
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astmp.inc
@@ -0,0 +1,207 @@
+;++
+;
+; Module Name:
+;
+; astmp.inc
+;
+; Abstract:
+;
+; ASTMP include file
+;
+; Author:
+; Quang Phan (v-quangp) 25-Jul-1992
+;
+; Modification:
+; Quang Phan (v-quangp) 15-Sep-1993:
+; Save MMIOtable and SPIsource in Pcr area.
+; Quang Phan (v-quangp) 15-Dec-1992:
+; Added new functions to the EBI2 call table.
+;
+;--
+;*****************************
+;
+; The kernel leaves some space (64 byte) of the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation
+; dependant.
+;
+PcHalData struc
+ PcrEBI2ProcessorID dd 0 ; EBI2 ProcessorID
+ PcrCpuLedRateCount dd 0 ; Cur. cnt for sampling CPU LED
+ PcrEBI2ProcInterruptHandle dd 0 ; EBI2 Processor Interrupt handle
+ PcrEBI2RaiseIrqlFunction dd 0 ; EBI2 ProcessorID
+ PcrEBI2LowerIrqlFunction dd 0 ; EBI2 ProcessorID
+ PcrEBI2portAddress0 dd 0 ; EBI2 Addr for Port0
+ PcrEBI2portAddress1 dd 0 ; EBI2 Addr for Port1
+ PcrEBI2portAddress2 dd 0 ; EBI2 Addr for Port2
+ PcrEBI2portAddress3 dd 0 ; EBI2 Addr for Port3
+ PcrEBI2MMIOtable dd 0 ; Addr of EBI2MMIO_Table
+ PcrEBI2SPIsource dd 0 ; SPI sources
+PcHalData ends
+;
+;EBI2 Function call table:
+;
+ebi_2_func_tbl struc
+ GetNumProcs dd ? ;Func # 1
+ GetProcConf dd ? ;Func # 2
+ StartProc dd ? ;Func # 3
+ StopProc dd ? ;Func # 4
+ GetProcID dd ? ;Func # 5
+ EnableRAMCache dd ? ;Func # 6
+ DisableRAMCache dd ? ;Func # 7
+ FlushRAMCache dd ? ;Func # 8
+ ControlCacheRegion dd ? ;Func # 9
+ GetCacheControlInfo dd ? ;Func # 10
+ SetPanelUPS dd ? ;Func # 11
+ GetPanelUPS dd ? ;Func # 12
+ SetPanelProcGraphMode dd ? ;Func # 13
+ GetPanelProcGraphMode dd ? ;Func # 14
+ SetPanelProcGraphValue dd ? ;Func # 15
+ GetPanelProcGraphValue dd ? ;Func # 16
+ LogProcIdle dd ? ;Func # 17
+ LogProcBusy dd ? ;Func # 18
+ GetPanelAttnSwitchLatch dd ? ;Func # 19
+ GetPanelOffSwitchLatch dd ? ;Func # 20
+ GetPanelKeyPos dd ? ;Func # 21
+ GetPanelAlphaNumInfo dd ? ;Func # 22
+ GetPanelAlphaNum dd ? ;Func # 23
+ SetPanelAlphaNum dd ? ;Func # 24
+ SetPanelOffSwitchMode dd ? ;Func # 25
+ GetPanelOffSwitchMode dd ? ;Func # 26
+ GetIntSybsysType dd ? ;Func # 27
+ SetGlobalIntMask dd ? ;Func # 28
+ GetGlobalIntMask dd ? ;Func # 29
+ SetLocalIntMask dd ? ;Func # 30
+ GetLocalIntMask dd ? ;Func # 31
+ SetAdvIntMode dd ? ;Func # 32
+ SetIRQVectorAssign dd ? ;Func # 33
+ GetIRQVectorAssign dd ? ;Func # 34
+ GetNumPowerSupplies dd ? ;Func # 35
+ GetPowerSupplyInfo dd ? ;Func # 36
+ DeInitEBI dd ? ;Func # 37
+ SetLSIVector dd ? ;Func # 38
+ GetLSIVector dd ? ;Func # 39
+ SetSPIVector dd ? ;Func # 40
+ GetSPIVector dd ? ;Func # 41
+ SetIPIVector dd ? ;Func # 42
+ GetIPIVector dd ? ;Func # 43
+ SetIPIID dd ? ;Func # 44
+ GetIPIID dd ? ;Func # 45
+ GenIPI dd ? ;Func # 46
+ GenerateLSI dd ? ;Func # 47
+ GetNMISource dd ? ;Func # 48
+ GetSPISource dd ? ;Func # 49
+ GetLocalIRQStatus dd ? ;Func # 50
+ MaskableIntEOI dd ? ;Func # 51
+ NonMaskableIntEOI dd ? ;Func # 52
+ CancelInterrupt dd ? ;Func # 53
+ GetSysTimer dd ? ;Func # 54
+ GetSysTimerFreq dd ? ;Func # 55
+ GetNumMemBlocks dd ? ;Func # 56
+ GetNumMemBlocks16 dd ? ;Func # 57
+ GetMemInfoTable dd ? ;Func # 58
+ GetMemInfoTable16 dd ? ;Func # 59
+ GetMemoryErrorInfo dd ? ;Func # 60
+ GetRevision dd ? ;Func # 61
+ GetMMIOTableLen dd ? ;Func # 62
+ GetMMIOTable dd ? ;Func # 63
+ InitEBI dd ? ;Func # 64
+ GetThermalState dd ? ;Func # 65
+ ShutdownPowerSupply dd ? ;Func # 66
+ SimulatePowerFail dd ? ;Func # 67
+ SetPanelSwitchVisibility dd ? ;Func # 68
+ GetPanelSwitchVisibility dd ? ;Func # 69
+ GetGlobalIRQStatus dd ? ;Func # 70
+ FastSetLocalIntMask dd ? ;Func # 71
+ GetProcIntHandle dd ? ;Func # 72
+ RegSetLocalIntMask dd ? ;Func # 73
+ GetLocalIntMaskInfo dd ? ;Func # 74
+ AST_Invalid_Func dd 22 DUP (?)
+ OEM0 dd ? ;Func #97
+ OEM_Invalid_Func dd 31 DUP (?)
+ebi_2_func_tbl ends
+
+;
+;*****************************
+; Equates.
+cr equ 0ah
+lf equ 0dh
+MaskAllIrqs equ 0700FFFBh ; EBI2's mask for all irqs
+ ; (but irq2 for chaining)
+NOT_ASSIGNED equ 0FFh ;used in IrqlToProcessor table,
+ ;(irql not assigned to any proc yet)
+;
+;##qp: Temp fix the stall scale to a fix number for now.
+;
+DefaultStallScaleFactor equ 9 ; temp default value for Stall scale
+WarmResetVector equ 0467h
+CpuLedSamplingRate equ 10 ; 15ms * X
+
+TIME_INCREMENT EQU 100144
+
+;*****************************
+;
+;
+; The following equates used for debugging HAL (ifdef'ed by DBG). The
+; hex number will be displayed to the front panel as 'H xx'
+; e.g. "DisplPanel HalEnableSystemInterruptEnter" will display as 'H 10'
+; where HalEnableSystemInterruptEnter is equated to 010h.
+;
+HalEnableSystemInterruptEnter equ 010h
+HalEnableSystemInterruptExit equ 011h
+HalEnableSystemInterruptError equ 012h
+HalDisableSystemInterruptEnter equ 015h
+HalDisableSystemInterruptExit equ 016h
+HalDisableSystemInterruptError equ 017h
+HalEndSystemInterruptEnter equ 018h
+HalEndSystemInterruptExit equ 019h
+HalLowerIrqlEnter equ 020h
+HalLowerIrqlExit equ 021h
+HalRaiseIrqlEnter equ 022h
+HalRaiseIrqlExit equ 023h
+HalBeginSystemInterruptEnter equ 024h
+HalBeginSystemInterruptExit equ 025h
+HalStartProfileInterruptEnter equ 026h
+HalStartProfileInterruptExit equ 027h
+HalStopProfileInterruptEnter equ 028h
+HalStopProfileInterruptExit equ 029h
+HalClockInterruptEnter equ 030h
+HalStartNextProcEnter equ 040h
+HalStartNextProcExit equ 041h
+HalStartNextProcProblem equ 0c0h
+HalSpuriousInterrupt equ 0c1h
+HalDisableInterruptProblem equ 0c2h
+HalRaiseIrqlProblem equ 0c3h
+HalSpuriousInterrupt2 equ 0c4h
+HalSpuriousInterrupt3 equ 0c5h
+HalSpuriousInterrupt4 equ 0c6h
+;
+;*** MACRO ***
+;
+;DisplPanel displays 'DisplCode' in hex to the front panel display
+
+DisplPanel macro DisplCode
+ if DBG
+ stdCall _DisplPanel,<DisplCode>
+ endif ;DBG
+ endm
+;
+;CALL_EBI2 setups the MMIOTable argument, calls the specified EBI function
+;'EBI2Function', and then cleans up the stack according to the number of
+;arguments 'NumArg'
+;
+CALL_EBI2 macro EBI2Function,NumArg
+ lea eax,_EBI2_MMIOTable
+ push eax
+ lea edx, _EBI2_CallTab
+ call [edx]+EBI2Function
+ add esp,NumArg * 4 ;clean stack
+ endm
+;
+CALL_FastEBI2 macro EBI2Function,NumArg
+ lea edx, _EBI2_CallTab
+ call [edx]+EBI2Function
+ add esp,NumArg * 4 ;clean stack
+ endm
+;
+;end
diff --git a/private/ntos/nthals/halast/i386/astmpint.c b/private/ntos/nthals/halast/i386/astmpint.c
new file mode 100644
index 000000000..42cbe4bd6
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astmpint.c
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ astmpint.c
+
+Abstract:
+
+ This module implements the HAL HalGetInterruptVector routine
+ for an x86 system
+
+Author:
+
+ John Vert (jvert) 17-Jul-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Bob Beard 7-Aug-92 For AST Manhattan system
+--*/
+#include "halp.h"
+
+extern CCHAR HalpBusIntToIRQL[];
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+
+ if (BusAddress.HighPart != 0 || *AddressSpace > 1) {
+ return (FALSE);
+ }
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+
+ return(TRUE);
+}
+
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ SystemVector = BusInterruptLevel + PRIMARY_VECTOR_BASE;
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ SystemVector > PRIMARY_VECTOR_BASE + HIGHEST_LEVEL_FOR_8259 ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = (KIRQL) HalpBusIntToIRQL[BusInterruptLevel];
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+ return SystemVector;
+}
+
diff --git a/private/ntos/nthals/halast/i386/astnls.h b/private/ntos/nthals/halast/i386/astnls.h
new file mode 100644
index 000000000..d63073815
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astnls.h
@@ -0,0 +1,29 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ astnls.h
+
+Abstract:
+
+ Strings which are used in the HAL
+
+ English
+
+--*/
+
+
+#define MSG_NMI_EBI2_ERR "EBI2 Problem: Cannot get NMI Source\n"
+#define MSG_NMI_SYS_IO_ERR "NMI: System I/O error\n"
+#define MSG_NMI_SW_GEN_NMI "NMI: Software generated NMI\n"
+#define MSG_NMI_MEMORY_ERR "NMI: Memory error\n"
+#define MSG_NMI_PROCESSOR_ERR "NMI: Processor error\n"
+#define MSG_NMI_POWER_FAILURE "NMI: Power Failure\n"
+#define MSG_NMI_BUS_ERR "NMI: Bus Address/Data error\n"
+#define MSG_NMI_TIMEOUT_ERR "NMI: System Timeout error\n"
+#define MSG_NMI_SHUTDOWN "NMI: Shutdown Button\n"
+#define MSG_NMI_ATTENTION "NMI: Attention Button\n"
+#define MSG_NMI_NO_NMI_FOUND "NMI: No NMI found\n"
+#define MSG_NMI_UNKOWN "NMI: Unkown NMI error\n"
diff --git a/private/ntos/nthals/halast/i386/astnmi.c b/private/ntos/nthals/halast/i386/astnmi.c
new file mode 100644
index 000000000..c8e5af31b
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astnmi.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ astnmi.c
+
+Abstract:
+
+ -Provides standard x86 NMI handler
+ -This code is AST specific.
+
+Author:
+
+ kenr
+
+Revision History:
+
+ Quang Phan (v-quangp) 17-Dec-92: Check for other NMI sources and
+ print out the proper messages.
+
+--*/
+#include "halp.h"
+#include "bugcodes.h"
+#include "astebiii.h"
+#include "astdisp.h"
+#include "astnls.h"
+
+extern VOID* EBI2_MMIOTable[];
+extern EBI_II EBI2_CallTab;
+
+
+#define SYSTEM_CONTROL_PORT_A 0x92
+#define SYSTEM_CONTROL_PORT_B 0x61
+#define EISA_EXTENDED_NMI_STATUS 0x461
+
+UCHAR EisaNMIMsg[] = MSG_NMI_EISA_IOCHKERR;
+
+
+VOID
+HalHandleNMI(
+ IN OUT PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ Called DURING an NMI. The system will BugCheck when an NMI occurs.
+ This function can return the proper bugcheck code, bugcheck itself,
+ or return success which will cause the system to iret from the nmi.
+
+ This function is called during an NMI - no system services are available.
+ In addition, you don't want to touch any spinlock which is normally
+ used since we may have been interrupted while owning it, etc, etc...
+
+Warnings:
+
+ Do NOT:
+ Make any system calls
+ Attempt to acquire any spinlock used by any code outside the NMI handler
+ Change the interrupt state. Do not execute any IRET inside this code
+
+ Passing data to non-NMI code must be done using manual interlocked
+ functions. (xchg instructions).
+
+Arguments:
+
+ NmiInfo - Pointer to NMI information structure (TBD)
+ - NULL means no NMI information structure was passed
+
+Return Value:
+
+ BugCheck code
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ UCHAR c;
+ ULONG port, i;
+ ULONG EBI2NMISource;
+ PUCHAR p;
+
+ HalDisplayString (MSG_HARDWARE_ERROR1);
+ HalDisplayString (MSG_HARDWARE_ERROR2);
+
+ StatusByte = READ_PORT_UCHAR((PUCHAR) SYSTEM_CONTROL_PORT_B);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_PARITY);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_CHANNEL_CHECK);
+ }
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR((PUCHAR) EISA_EXTENDED_NMI_STATUS);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_FAIL_SAFE);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_BUS_TIMEOUT);
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString (MSG_NMI_SOFTWARE_NMI);
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 1; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ c = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ for (i=0; EisaNMIMsg[i]; i++) {
+ if (EisaNMIMsg[i] == '%') {
+ EisaNMIMsg[i] = c;
+ break;
+ }
+ }
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+ }
+
+ if ( (EBI2_CallTab.GetNMISource)( EBI2_MMIOTable, &EBI2NMISource ) )
+ { HalDisplayString (MSG_NMI_EBI2_ERR); }
+
+ switch (EBI2NMISource) {
+ case NMI_SYS_IO_ERROR: p = MSG_NMI_SYS_IO_ERR; break;
+ case NMI_SW_GEN_NMI: p = MSG_NMI_SW_GEN_NMI; break;
+ case NMI_MEMORY_ERROR: p = MSG_NMI_MEMORY_ERR; break;
+ case NMI_PROC_ERROR: p = MSG_NMI_PROCESSOR_ERR; break;
+ case NMI_POWERFAIL: p = MSG_NMI_POWER_FAILURE; break;
+ case NMI_BUS_PARITY: p = MSG_NMI_BUS_ERR; break;
+ case NMI_BUS_TIMEOUT: p = MSG_NMI_TIMEOUT_ERR; break;
+ case NMI_FP_SHUTDOWN: p = MSG_NMI_SHUTDOWN; break;
+ case NMI_FP_ATTENTION: p = MSG_NMI_ATTENTION; break;
+ case NMI_NONE_FOUND: p = MSG_NMI_NO_NMI_FOUND; break;
+ default: p = MSG_NMI_UNKOWN; break;
+ }
+
+ HalDisplayString (p);
+
+ HalDisplayString (MSG_HALT);
+ KeEnterKernelDebugger();
+}
diff --git a/private/ntos/nthals/halast/i386/astproc.c b/private/ntos/nthals/halast/i386/astproc.c
new file mode 100644
index 000000000..2cf10da6e
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astproc.c
@@ -0,0 +1,366 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 AST Research Inc.
+
+Module Name:
+
+ spsproc.c
+
+Abstract:
+
+ AST EBI2 Start Next Processor c code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ AST Manhattan EBI2 system.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Bob Beard (v-bobb) 3-Aug-1992
+
+--*/
+
+#include "halp.h"
+#include "astdisp.h"
+
+UCHAR HalName[] = "AST Manhattan MP HAL";
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+
+#define MAX_PT 8
+#define LOW_MEMORY 0x000100000
+extern __cdecl StartPx_PMStub();
+
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR MppIDT; // pointer to physical memory 0:0
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+extern ULONG HalpIpiClock; // bitmask of processors to ipi
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ PKPCR pPCR;
+
+ pPCR = KeGetPcr();
+
+ if (Phase == 0) {
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress)
+ return TRUE;
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+ return TRUE;
+
+ }
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Eisa // Manhattan's are Eisa machines
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+}
+
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other buses
+}
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halast/i386/astproca.asm b/private/ntos/nthals/halast/i386/astproca.asm
new file mode 100644
index 000000000..401c0dd3b
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astproca.asm
@@ -0,0 +1,371 @@
+ title "MP primitives for AST Manhattan EBI2"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 AST Research Inc.
+;
+;Module Name:
+;
+; spsproca.asm
+;
+;Abstract:
+;
+; AST Manhattan Start Next Processor assemble code
+;
+; This module along with astproc.c implement the code to start
+; off additional processors on the AST Manhattan.
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+;Revision History:
+;
+; Bob Beard (v-bobb) 4-Aug-1992
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\astebi2.inc
+include i386\astmp.inc
+ .list
+
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+ EXTRNP _DisplPanel,1
+
+ extrn _MppIDT:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+ extrn _MpCount:DWORD
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_ProcNum dd ?
+ SPx_PB db processorstatelength dup (?)
+PxParamBlock ends
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+
+
+cPublicProc _HalStartNextProcessor ,2
+
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.SPx_flag, eax
+
+ cmp _MpCount, eax
+ je snp_exit ; exit FALSE
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+ mov edi, _MpLowStub ; Copy RMStub to low memory
+ add edi, size PxParamBlock
+ rep movsb
+
+ lea edi, PxFrame.SPx_PB
+ mov esi, pProcessorState
+ mov ecx, processorstatelength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+ stdCall _HalpBuildTiledCR3,<pProcessorState>
+
+ mov PxFrame.SPx_TiledCR3, eax
+ mov PxFrame.SPx_P0EBP, ebp
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+ mov PxFrame.SPx_ProcNum, eax
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _MpLowStub
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx ; patch realmode stub with
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
+
+ mov ebx, _MppIDT
+ add ebx, WarmResetVector
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+ push ebx
+
+ mov eax, _MpLowStubPhysicalAddress
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+
+
+ push PxFrame.SPx_ProcNum
+ CALL_EBI2 StartProc,2
+
+ifdef DBG
+ or eax,eax
+ je Start_Ok
+ push 0ffh
+ DisplPanel HalStartNextProcProblem
+ add esp,4
+ int 3
+Start_Ok:
+endif
+
+loop_till_started:
+ cmp PxFrame.SPx_flag, 0
+ jz loop_till_started
+
+ pop ebx
+ pop dword ptr [ebx] ; restore vector
+
+ sti
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+
+ dec _MpCount ; one less
+ mov eax, 1 ; return TRUE
+
+snp_exit:
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ stdRET _HalStartNextProcessor
+stdENDP _HalStartNextProcessor
+
+
+_TEXT ends ; end 32 bit code
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+ public StartPx_RMStub
+
+StartPx_RMStub proc
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+StartPx_RMStub endp
+
+
+_TEXT16 ends ; End 16 bit code
+
+_TEXT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+ align 16 ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+ public _StartPx_PMStub
+_StartPx_PMStub proc
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+
+ ; eax, ebx, edx are still free
+spxpm01:
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with it's data
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ ret ; Set eip
+
+_StartPx_PMStub endp
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/halast/i386/astspi.asm b/private/ntos/nthals/halast/i386/astspi.asm
new file mode 100644
index 000000000..427b6544f
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astspi.asm
@@ -0,0 +1,152 @@
+ title "Special Interrupt"
+;++
+;
+;Copyright (c) 1992 AST Research Inc.
+;
+;Module Name:
+;
+; astspi.asm
+;
+;Abstract:
+;
+; AST Manhattan SPI code.
+; Provides the HAL support for Special Interrupts for the
+; MP Manhattan implementation.
+;
+;Author:
+;
+; Bob Beard (v-bobb) 14-Aug-1992
+;
+;Revision History:
+;
+;--
+.386p
+ .xlist
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include callconv.inc
+include i386\astebi2.inc
+include i386\astmp.inc
+include i386\kimacro.inc
+
+ EXTRNP _DisplPanel,1
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+ extrn _HalpIRQLtoVector:BYTE
+
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+_EBI2_SpiSource dd 0 ; Global variable indicating SPI source
+_EBI2_SetIrq13Packet dd 3 dup (0) ;Parameter packet for OEMfunc SetIrq13Latch
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; HalpSpiInterrupt
+;
+;Routine Description:
+;
+; Determine type of SPI interrupt that occurred.
+; EOI the interrupt.
+; Defer all works to the device driver by latching IRQ13
+;
+;Arguments:
+;
+; None
+; Interrupt is disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+ ENTER_DR_ASSIST Hsi_a, Hsi_t
+cPublicProc _HalpSPInterrupt,0
+
+;
+; Save Machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hsi_a, Hsi_t
+
+;
+; (esp) - base of trap frame
+;
+
+
+;
+; get the SPI interrupt source and store in _EBI2_SpiSource
+;
+ push offset _EBI2_SpiSource
+ CALL_EBI2 GetSPISource, 2
+
+if DBG
+ int 3
+ or eax,eax
+ jz Spi_10
+ int 3
+Spi_10:
+endif ;DBG
+
+;
+;Defer any processing to the device driver by set IRQ13 latche
+;
+ mov eax,_EBI2_SpiSource ;save SPI sources
+ mov fs:PcHal.PcrEBI2SPIsource,eax ;
+
+ mov eax,offset _EBI2_SetIrq13Packet
+ mov [eax].OEM0_subfunc,SET_IRQ13_LATCH
+ mov [eax].OEM0_parm1dd,IRQ13_LATCH_ON ;latch mode
+ mov [eax].OEM0_parm2dd,0 ;set to processor 0
+ push eax
+ CALL_EBI2 OEM0, 2
+
+if DBG
+ or eax,eax
+ jz Spi_20
+ int 3
+Spi_20:
+endif ;DBG
+
+
+ movzx eax, _HalpIRQLtoVector[POWER_LEVEL]
+ push eax
+ sub esp,4 ; space for OldIrql
+ stdCall _HalBeginSystemInterrupt,<POWER_LEVEL,eax,esp>
+ or al,al ; check for spurious interrupt
+ jz Spi_100
+
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+
+ INTERRUPT_EXIT
+
+
+Spi_100:
+ add esp,8 ; spurious
+ EXIT_ALL ,,NoPreviousMode ; no EOI or lowering irql
+
+stdENDP _HalpSPInterrupt
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halast/i386/aststall.asm b/private/ntos/nthals/halast/i386/aststall.asm
new file mode 100644
index 000000000..184407832
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/aststall.asm
@@ -0,0 +1,251 @@
+ title "Stall Execution Support"
+;++
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+; aststall.asm
+;
+; Abstract:
+; This module implements the code necessary to initialize the per
+; microsecond count used by the KeStallExecution.
+; This implementation is very specific to the AST Manhattan system.
+;
+; Author:
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Landy Wang (corollary!landy) 04-Dec-92
+; Created this module by moving routines from ixclock.asm to here.
+;
+; Quang Phan (v-quangp) 07-Jan-93
+; Modified for AST MP system.
+;--
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ixcmos.inc
+include i386\astmp.inc
+include i386\astebi2.inc
+ .list
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+;
+; Constants
+;
+BaseStallCount EQU 40h ; Init. count
+UpperLimitCount EQU 400h ; Upper limit count for debbuging
+SysTimerUpperLimit EQU 0FFFFFFC0h ; SysTimer nears wrap arround
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+EBI2_SysTimerCount dd 0 ;loc for EBI2GetSysTimer data
+
+_DATA ends
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; HalpInitializeStallExecution (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor.
+;
+; This function does not use the interval clock interrupt. Instead,
+; it use the global system timer of 1 microsecond available in the
+; AST Manhattan system.
+;
+; Arguments:
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+; None.
+;
+; Note:
+;--
+
+cPublicProc _HalpInitializeStallExecution ,1
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+ push ebx ; save ebx for internal use
+ mov ecx,BaseStallCount
+;
+;Sync on transition of the system timer.
+;
+Kise10:
+ lea eax, EBI2_SysTimerCount ;ptr to data
+ push eax
+ CALL_EBI2 GetSysTimer,2
+if DBG
+ or eax,eax
+ je @f
+ int 3 ;trap for debugging
+@@:
+endif
+ mov ebx, EBI2_SysTimerCount ;save last SysTimer
+ lea eax, EBI2_SysTimerCount ;ptr to data
+ push eax
+ CALL_EBI2 GetSysTimer,2
+if DBG
+ or eax,eax
+ je @f
+ int 3 ;trap for debugging
+@@:
+endif
+ cmp ebx, EBI2_SysTimerCount ;cmp with last SysTimer
+ jae Kise10 ;if wrap or the same.
+
+ mov ebx, EBI2_SysTimerCount ;last SysTimer
+ cmp ebx, SysTimerUpperLimit ; if near wrap around
+ ja kise10 ; then try again.
+
+ add ebx, 32 ;sample in 32 us.
+ mov eax, ecx ;init loop count
+ALIGN 4
+@@:
+ sub eax, 1 ; dec loop count
+ jnz short @b
+
+;
+;Check if system timer roll over.
+;
+ lea eax, EBI2_SysTimerCount ;ptr to data
+ push eax
+ CALL_EBI2 GetSysTimer,2
+if DBG
+ or eax,eax
+ je short @f
+ int 3 ;trap for debugging
+@@:
+endif
+ cmp EBI2_SysTimerCount, ebx ;cmp with last SysTimer
+ jb Kise30 ;go increment BaseStallCount
+
+ shr ecx,5 ;/32=count for 1us
+ mov PCR[PcStallScaleFactor], ecx
+
+if DBG
+ cmp ecx, 0
+ jnz short @f
+ stdCall _DbgBreakPoint
+@@:
+ cmp ecx, UpperLimitCount
+ jb short @f
+ stdCall _DbgBreakPoint
+@@:
+endif
+ pop ebx
+ popfd ; restore caller's eflags
+
+ stdRET _HalpInitializeStallExecution
+
+
+;-------
+;
+;SysTimer does not reach the reference yet, increment stall count then retry.
+;
+Kise30:
+ inc ecx
+ jmp Kise10 ;try again
+
+stdENDP _HalpInitializeStallExecution
+
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+cPublicProc _KeStallExecutionProcessor ,1
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ ; loop count for the processor
+ mul ecx ; (eax) = desired loop count
+
+if DBG
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+ cmp edx, 0
+ jz short @f
+ int 3
+
+@@: cmp eax,0
+ jnz short @f
+ int 3
+@@:
+endif
+
+ALIGN 4
+@@: sub eax, 1 ; (eax) = (eax) - 1
+ jnz short @b
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halast/i386/astsyint.asm b/private/ntos/nthals/halast/i386/astsyint.asm
new file mode 100644
index 000000000..e30022ed2
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/astsyint.asm
@@ -0,0 +1,592 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 AST Research Inc.
+;
+;Module Name:
+;
+; astsyint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts, for the AST MP (Manhattan) implementation
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+; Quang Phan (v-quangp) 24-Jul-1992
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+; Quang Phan (v-quangp) 15-Dec-1992:
+; Used different display codes for different spurious interrupt status.
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\astebi2.inc
+include i386\astmp.inc
+ .list
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ extrn KiEBI2IntMaskTable:DWORD
+ extrn _HalpIRQLtoEBIBitMask:DWORD
+ extrn _EBI2_CallTab:DWORD
+ extrn _EBI2_MMIOTable:DWORD
+ extrn _HalpInitializedProcessors:DWORD
+ extrn _HalpIRQLtoVector:BYTE
+ EXTRNP _DisplPanel,1
+ EXTRNP _KeRaiseIrql,2
+ EXTRNP KfRaiseIrql,1,,FASTCALL
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+;spinlock for EBI2 access
+;
+ align dword
+ public _EBI2_Lock
+_EBI2_Lock dd 0 ;for Enable/DisableSystemInterrupt
+EBI2_GlobalIntMask dd 0 ;loc for EBI2GetGlobalIntMask data
+
+;HalpInterruptToProc table is used by HAL to figure out which interrupt
+;(irql) will be assigned to which processor. The current implementation
+;assigns interrupts to processors on a round-robin basis.
+;
+ public IrqlAssignToProcTable ;InterruptToProcessor assignment table
+IrqlAssigntoProcTable label dword
+ dd 32 dup(0FFh) ;irql -> ProcID
+CurrentAssignProcessor dd 0 ; Current proc. assigned to irql
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irql 0
+ dd offset FLAT:HalpDismissNormal ; irql 1
+ dd offset FLAT:HalpDismissNormal ; irql 2
+ dd offset FLAT:HalpDismissNormal ; irql 3
+ dd offset FLAT:HalpDismissNormal ; irql 4
+ dd offset FLAT:HalpDismissNormal ; irql 5
+ dd offset FLAT:HalpDismissNormal ; irql 6
+ dd offset FLAT:HalpDismissNormal ; irql 7
+ dd offset FLAT:HalpDismissNormal ; irql 8
+ dd offset FLAT:HalpDismissNormal ; irql 9
+ dd offset FLAT:HalpDismissNormal ; irql 10
+ dd offset FLAT:HalpDismissNormal ; irql 11
+ dd offset FLAT:HalpDismissIrq07 ; irql 12 (irq7)
+ dd offset FLAT:HalpDismissNormal ; irql 13
+ dd offset FLAT:HalpDismissNormal ; irql 14
+ dd offset FLAT:HalpDismissNormal ; irql 15
+ dd offset FLAT:HalpDismissNormal ; irql 16
+ dd offset FLAT:HalpDismissIrq0f ; irql 17 (irq15)
+ dd offset FLAT:HalpDismissNormal ; irql 18
+ dd offset FLAT:HalpDismissNormal ; irql 19
+ dd offset FLAT:HalpDismissNormal ; irql 20
+ dd offset FLAT:HalpDismissNormal ; irql 21
+ dd offset FLAT:HalpDismissNormal ; irql 22
+ dd offset FLAT:HalpDismissNormal ; irql 23
+ dd offset FLAT:HalpDismissNormal ; irql 24
+ dd offset FLAT:HalpDismissNormal ; irql 25
+ dd offset FLAT:HalpDismissNormal ; irql 26
+ dd offset FLAT:HalpDismissNormal ; irql 27
+ dd offset FLAT:HalpDismissNormal ; irql 28
+ dd offset FLAT:HalpDismissNormal ; irql 29
+ dd offset FLAT:HalpDismissNormal ; irql 30
+ dd offset FLAT:HalpDismissNormal ; irql 31
+;
+;Translation table from system IRQL to EBI's IntNum used in MaskableIntEOI.
+;
+ Public HalpIRQLtoEBIIntNumber
+ align 4
+HalpIRQLtoEBIIntNumber Label Dword
+ dd 0 ;IRQL 0 (Unused Mask)
+ dd 0 ;IRQL 1
+ dd IRQ_25 ;IRQL 2 (EBI IRQ-25)
+ dd 0 ;IRQL 3
+ dd 0 ;IRQL 4
+ dd 0 ;IRQL 5
+ dd 0 ;IRQL 6
+ dd 0 ;IRQL 7
+ dd 0 ;IRQL 8
+ dd 0 ;IRQL 9
+ dd 0 ;IRQL 10
+ dd 0 ;IRQL 11
+ dd IRQ_7 ;IRQL 12
+ dd IRQ_6 ;IRQL 13
+ dd IRQ_5 ;IRQL 14
+ dd IRQ_4 ;IRQL 15
+ dd IRQ_3 ;IRQL 16
+ dd IRQ_15 ;IRQL 17
+ dd IRQ_14 ;IRQL 18
+ dd IRQ_13 ;IRQL 19
+ dd IRQ_12 ;IRQL 20
+ dd IRQ_11 ;IRQL 21
+ dd IRQ_10 ;IRQL 22
+ dd IRQ_9 ;IRQL 23
+ dd IRQ_8 ;IRQL 24
+ dd IRQ_2 ;IRQL 25
+ dd IRQ_1 ;IRQL 26
+ dd IRQ_8 ;IRQL 27
+ dd IRQ_0 ;IRQL 28
+ dd IRQ_26 ;IRQL 29 (IPI)
+ dd IRQ_24 ;IRQL 30 (SPI)
+ dd 0 ;IRQL 31
+;
+
+_DATA ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt,3
+
+ movzx eax,HbsiIrql ; (eax) = System Irql
+ movzx ecx,byte ptr fs:PcIrql ; (ecx) = Current Irql
+
+if DBG
+ cmp eax, 31 ; Irql in table?
+ ja hbsi00 ; no go handle
+
+ cmp cl, al
+ ja hbsi00 ; Dismiss as spurious
+endif ;DBG
+
+ jmp HalpSpecialDismissTable[eax*4] ; ck for spurious int's
+
+hbsi00:
+;
+; Interrupt is out of range. There's no EOI here since it wouldn't
+; have been out of range if it occured on either interrupt controller
+; which is known about.
+;
+ DisplPanel HalSpuriousInterrupt
+ int 3
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+;
+;
+;-------------------
+;Normal handler
+;-------------------
+;
+HalpDismissNormal2:
+ movzx eax,HbsiIrql ; (eax) = System Irql
+ movzx ecx,byte ptr fs:PcIrql ; (ecx) = Current Irql
+HalpDismissNormal:
+ mov dl, _HalpIRQLtoVector[eax] ; Does irql match interrupt
+ cmp dl, HbsiVector ; vector?
+ jne short hbsi10 ; no, (then it's higher) go raise
+
+ mov edx, HbsiOldIrql ; (edx) = OldIrql address
+ mov fs:PcIrql, al ; Set new irql
+ mov byte ptr[edx], cl ; return OldIrql
+; mov dword ptr[edx], ecx
+
+ mov eax, 1 ; set return value to true
+ sti
+ stdRET _HalBeginSystemInterrupt
+
+hbsi10:
+ mov edx, HbsiOldIrql ; (edx) = OldIrql address
+ stdCall _KeRaiseIrql <eax, edx>
+ mov eax, 1 ; set return value to true
+ sti
+ stdRET _HalBeginSystemInterrupt
+
+
+
+;
+;-------------------
+;Handler for irq0Fh
+;-------------------
+;
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt by reading the global IRQ status
+;
+
+ sub esp, 8 ;alloc room in stack for 2 dword
+ mov eax,esp
+ add eax,4
+ push eax ;ptr to GlobalIRR
+ mov eax,esp
+ add eax,4
+ push eax ;ptr to GlobalISR
+ CALL_EBI2 GetGlobalIRQStatus,3
+
+if DBG
+ or eax,eax
+ je BeginSysInt4_OK
+ int 3 ;trap for debugging
+BeginSysInt4_OK:
+endif
+
+ bt dword ptr [esp],IRQ_15 ;chk In-Service for irq15
+ pop eax ;dummy pop to adj stack
+ pop eax ;..
+ jc short HalpDismissNormal2 ; =1: NOT a spurious int
+;
+;Else, is a spurious interrupt. In this case, we have to send EOI to
+;the ADI to dismiss the interrupt.
+;
+ DisplPanel HalSpuriousInterrupt2
+ push IRQ_15 ;EOI Irq_15
+ CALL_EBI2 MaskableIntEOI,2
+
+if DBG
+ or eax,eax
+ je BeginSysInt3_OK
+ int 3 ;trap for debugging
+BeginSysInt3_OK:
+endif
+;
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+;
+;-------------------
+;Handler for irq07
+;-------------------
+;
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt by reading the global IRQ status
+;
+
+ sub esp, 8 ;alloc room in stack for 2 dword
+ mov eax,esp
+ add eax, 4
+ push eax ;ptr to GlobalIRR
+ mov eax,esp
+ add eax, 4
+ push eax ;ptr to GlobalISR
+ CALL_EBI2 GetGlobalIRQStatus,3
+
+if DBG
+ or eax,eax
+ je BeginSysInt2_OK
+ int 3 ;trap for debugging
+BeginSysInt2_OK:
+endif
+
+ bt dword ptr [esp],IRQ_7 ; chk In-Service for irq7
+ pop eax ;dummy pop to adj stack
+ pop eax ;..
+ jc HalpDismissNormal2 ; =1: NOT a spurious int
+;
+;Else, is a spurious interrupt. In this case, we have to send EOI to
+;the ADI to dismiss the interrupt.
+;
+ DisplPanel HalSpuriousInterrupt3
+ push IRQ_7 ;EOI Irq_7
+ CALL_EBI2 MaskableIntEOI,2
+
+if DBG
+ or eax,eax
+ je BeginSysInt1_OK
+ int 3 ;trap for debugging
+BeginSysInt1_OK:
+endif
+;
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt,2
+
+ movzx ecx, byte ptr [esp+4] ;get vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc DisSysIntError ;jump if not H/W interrupt
+ cmp ecx, CLOCK2_LEVEL
+ jnc DisSysIntError
+ movzx ecx, byte ptr [esp+8] ;get IRQL (ecx)
+ mov ecx, HalpIRQLtoEBIIntNumber[ecx*4] ;get ebi2 int# (edx)
+ cli
+ bts fs:PcIDR, ecx ;disable int locally
+ jc DisSysIntExit ;jump if already disabled
+
+ lea eax, _EBI2_Lock
+DisSysIntAquire:
+ ACQUIRE_SPINLOCK eax, DisSysIntSpin
+;
+;Mark the appropirate entry in the Irql assign table to NOT_ASSIGNED.
+;
+ movzx eax, byte ptr [esp+8] ;get IRQL
+ mov IrqlAssignToProcTable[eax*4],NOT_ASSIGNED
+;
+;Get the global interrupt mask
+;
+ lea eax, EBI2_GlobalIntMask
+ push eax
+ CALL_EBI2 GetGlobalIntMask,2
+
+if DBG
+ or eax,eax
+ je DisableSysInt4_OK
+ int 3 ;trap for debugging
+DisableSysInt4_OK:
+endif
+
+;
+;Disable interrupt globally at PIC
+;
+ bts EBI2_GlobalIntMask,ecx ;disable int at global mask
+ push EBI2_GlobalIntMask
+ CALL_EBI2 SetGlobalIntMask,2
+
+if DBG
+ or eax,eax
+ je DisableSysInt1_OK
+ int 3 ;trap for debugging
+DisableSysInt1_OK:
+endif
+;
+;Disable interrupt locally
+;
+ mov cl, fs:PcIrql
+ fstCall KfRaiseIrql
+
+ lea eax, _EBI2_Lock
+DisSysIntRelease:
+ RELEASE_SPINLOCK eax
+
+DisSysIntExit:
+;## DisplPanel HalDisableSystemInterruptExit
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+DisSysIntError:
+ DisplPanel HalDisableSystemInterruptError
+if DBG
+ int 3
+endif
+ sti
+ xor eax,eax
+ ret
+
+DisSysIntSpin:
+ SPIN_ON_SPINLOCK eax, DisSysIntAquire
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt,3
+;## DisplPanel HalEnableSystemInterruptEnter
+; int 3
+ movzx eax, byte ptr [esp+4] ;get vector
+ sub eax, PRIMARY_VECTOR_BASE
+ jc EnbSysIntError ;jump if not H/W interrupt
+; cmp eax, CLOCK2_LEVEL
+; jnc EnbSysIntError
+;
+;Determine if this irq is to be assigned to this processor.
+;Irqs are to be assigned to the available processors on a round-robin
+;basis
+;
+ movzx ecx, byte ptr [esp+8] ;get IRQL
+ cmp ecx,PROFILE_LEVEL
+ jae HESI_010 ;skip for PROFILE irql and above.
+;
+;To have the fpanel switch work properly, irq13 must be assigned to P0.
+;This is because EBI2 clears switch status when asthal eoi SPI interrupt.
+;The current implementation is that switch status will be read and saved
+;by SPI handler.
+;
+ cmp eax,13 ;irq13 vector?
+ jne HSEI_006
+ mov eax,fs:PcHal.PcrEBI2ProcessorID
+ or eax,eax
+ jne EnbSysIntExit
+ mov IrqlAssignToProcTable[ecx*4],eax ;update IrqlAssingnTable
+ jmp short HESI_010 ;go assign irq13 to P0
+
+HSEI_006:
+ cmp IrqlAssignToProcTable[ecx*4],NOT_ASSIGNED
+ jne EnbSysIntExit ;skip if irql already assigned
+ mov eax,CurrentAssignProcessor
+ cmp eax,fs:PcHal.PcrEBI2ProcessorID
+ jne EnbSysIntExit
+ mov IrqlAssignToProcTable[ecx*4],eax ;update IrqlAssingnTable
+ cmp _HalpInitializedProcessors,1
+ je HESI_010 ;skip if only one processor
+ inc eax ;1-base count
+ cmp eax,_HalpInitializedProcessors
+ jae HESI_008
+ inc CurrentAssignProcessor
+ jmp HESI_010
+HESI_008:
+ mov CurrentAssignProcessor,0 ;reset to 0
+
+HESI_010:
+ mov eax, HalpIRQLtoEBIIntNumber[ecx*4] ;get ebi2 int #
+ cli
+ btr fs:PcIDR, eax ;enable int locally
+ jnc EnbSysIntExit ;jump if already enabled
+;
+ lea eax, _EBI2_Lock
+EnbSysIntAquire:
+ ACQUIRE_SPINLOCK eax, EnbSysIntSpin
+;
+;Enable interrupt locally
+;
+ mov cl, fs:PcIrql
+ fstCall KfRaiseIrql
+
+;
+;Get the global interrupt mask
+;
+ lea eax, EBI2_GlobalIntMask
+ push eax
+ CALL_EBI2 GetGlobalIntMask,2
+
+if DBG
+ or eax,eax
+ je EnableSysInt4_OK
+ int 3 ;trap for debugging
+EnableSysInt4_OK:
+endif
+
+;
+;Enable interrupt globally at PIC
+;
+ mov eax,EBI2_GlobalIntMask ;current Global mask
+ and eax,fs:PcIDR ;enable int according PcIDR
+ and eax,0FFFFh ;EBI allows only irqs
+ push eax
+ CALL_EBI2 SetGlobalIntMask,2
+
+if DBG
+ or eax,eax
+ je EnableSysInt3_OK
+ int 3 ;trap for debugging
+EnableSysInt3_OK:
+endif
+
+EnbSysIntRelease:
+ lea eax, _EBI2_Lock
+ RELEASE_SPINLOCK eax
+
+EnbSysIntExit:
+;## DisplPanel HalEnableSystemInterruptExit
+ sti
+ mov eax, 1
+ stdRET _HalEnableSystemInterrupt
+
+EnbSysIntError:
+ DisplPanel HalEnableSystemInterruptError
+if DBG
+ int 3
+endif
+ sti
+ xor eax,eax
+ stdRET _HalEnableSystemInterrupt
+
+EnbSysIntSpin:
+ SPIN_ON_SPINLOCK eax, EnbSysIntAquire
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halast/i386/halp.h b/private/ntos/nthals/halast/i386/halp.h
new file mode 100644
index 000000000..49a60e028
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halast/i386/ix8259.inc b/private/ntos/nthals/halast/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halast/i386/ixbeep.asm b/private/ntos/nthals/halast/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halast/i386/ixbusdat.c b/private/ntos/nthals/halast/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halast/i386/ixcmos.asm b/private/ntos/nthals/halast/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halast/i386/ixcmos.inc b/private/ntos/nthals/halast/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halast/i386/ixdat.c b/private/ntos/nthals/halast/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halast/i386/ixenvirv.c b/private/ntos/nthals/halast/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halast/i386/ixfirm.c b/private/ntos/nthals/halast/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halast/i386/ixhwsup.c b/private/ntos/nthals/halast/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halast/i386/ixidle.asm b/private/ntos/nthals/halast/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halast/i386/ixinfo.c b/private/ntos/nthals/halast/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halast/i386/ixisa.h b/private/ntos/nthals/halast/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halast/i386/ixisabus.c b/private/ntos/nthals/halast/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halast/i386/ixisasup.c b/private/ntos/nthals/halast/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halast/i386/ixkdcom.c b/private/ntos/nthals/halast/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halast/i386/ixkdcom.h b/private/ntos/nthals/halast/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halast/i386/ixphwsup.c b/private/ntos/nthals/halast/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halast/i386/ixreboot.c b/private/ntos/nthals/halast/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halast/i386/ixswint.asm b/private/ntos/nthals/halast/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixswint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixswint.asm
diff --git a/private/ntos/nthals/halast/i386/ixthunk.c b/private/ntos/nthals/halast/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halast/i386/ixusage.c b/private/ntos/nthals/halast/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halast/i386/spprofil.asm b/private/ntos/nthals/halast/i386/spprofil.asm
new file mode 100644
index 000000000..8bc9f5e3e
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/spprofil.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halsp\i386\spprofil.asm
diff --git a/private/ntos/nthals/halast/i386/spspin.asm b/private/ntos/nthals/halast/i386/spspin.asm
new file mode 100644
index 000000000..0d70c442f
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/spspin.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halsp
+; This is a cpp style symbolic link
+
+include ..\halsp\i386\spspin.asm
diff --git a/private/ntos/nthals/halast/i386/xxbiosa.asm b/private/ntos/nthals/halast/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halast/i386/xxbiosc.c b/private/ntos/nthals/halast/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halast/i386/xxdisp.c b/private/ntos/nthals/halast/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halast/i386/xxflshbf.c b/private/ntos/nthals/halast/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halast/i386/xxioacc.asm b/private/ntos/nthals/halast/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halast/i386/xxkdsup.c b/private/ntos/nthals/halast/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halast/i386/xxmemory.c b/private/ntos/nthals/halast/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halast/i386/xxstubs.c b/private/ntos/nthals/halast/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halast/i386/xxtime.c b/private/ntos/nthals/halast/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halast/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halast/makefile b/private/ntos/nthals/halast/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halast/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halast/makefile.inc b/private/ntos/nthals/halast/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halast/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halast/sources b/private/ntos/nthals/halast/sources
new file mode 100644
index 000000000..ea2bfddce
--- /dev/null
+++ b/private/ntos/nthals/halast/sources
@@ -0,0 +1,102 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halast
+TARGETPATH=\nt\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixdat.c \
+ i386\ixisabus.c \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixinfo.c \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\ixphwsup.c \
+ i386\ixreboot.c \
+ i386\ixswint.asm \
+ i386\ixthunk.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c \
+ i386\spspin.asm \
+ i386\spprofil.asm \
+ i386\astdetct.c \
+ i386\astebi.c \
+ i386\asthal.c \
+ i386\astipirq.c \
+ i386\astebini.c \
+ i386\astipi.asm \
+ i386\astclock.asm \
+ i386\astirql.asm \
+ i386\astsyint.asm \
+ i386\astproc.c \
+ i386\astmpint.c \
+ i386\astspi.asm \
+ i386\aststall.asm \
+ i386\astproca.asm \
+ i386\astnmi.c
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halast.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halavant/alpha/addrsup.c b/private/ntos/nthals/halavant/alpha/addrsup.c
new file mode 100644
index 000000000..5f3d69f09
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/addrsup.c
@@ -0,0 +1,587 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "avantdef.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on Avanti are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAXR2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ // Note that ISA and EISA buses can also request this space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_DENSE_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ if( (PA.QuadPart >= APECS_COMANCHE_BASE_PHYSICAL)
+ && (PA.QuadPart < APECS_PCI_DENSE_BASE_PHYSICAL)
+ )
+ {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Avanti we have only bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halavant/alpha/adjust.c b/private/ntos/nthals/halavant/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/allstart.c b/private/ntos/nthals/halavant/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/alphaio.s b/private/ntos/nthals/halavant/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/apecs.c b/private/ntos/nthals/halavant/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/apecserr.c b/private/ntos/nthals/halavant/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/apecsio.s b/private/ntos/nthals/halavant/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/avantdef.h b/private/ntos/nthals/halavant/alpha/avantdef.h
new file mode 100644
index 000000000..43ce52fa0
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/avantdef.h
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ avantdef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Avanti modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+
+--*/
+
+#ifndef _AVANTIDEF_
+#define _AVANTIDEF_
+
+#include "alpharef.h"
+#include "apecs.h"
+#include "isaaddr.h"
+
+#define NUMBER_ISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 2
+#define NUMBER_COMBO_SLOTS 1
+
+// Highest Virtual local PCI Slot is 13 == IDSEL PCI_AD[24]
+
+#define PCI_MAX_LOCAL_DEVICE 13
+
+// Highest PCI interrupt vector is in ISA Vector Space
+
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_ISA_VECTOR - ISA_VECTORS)
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV4 processor.
+//
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+typedef struct _AVANTI_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} AVANTI_PCR, *PAVANTI_PCR;
+
+#define HAL_PCR ( (PAVANTI_PCR)(&(PCR->HalReserved)) )
+
+#define PCI_SPARSE_IO_BASE_QVA ((ULONG)(HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL)))
+
+//
+// PCI-E/ISA Bridge chip configuration space base is at physical address
+// 0x1e0000000. The equivalent QVA is:
+// ((0x1e0000000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+// N.B.: The PCI configuration space address is what we're really referring
+// to, here; both symbols are useful.
+//
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+
+#define PCI_CONFIGURATION_BASE_QVA 0xaf000000
+#define PCI_BRIDGE_CONFIGURATION_BASE_QVA 0xaf000000
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device
+
+#define PCI_ISA_BRIDGE_HEADER_OFFSET_P2 (0x00070000 >> IO_BIT_SHIFT) // AD[18]
+#define PCI_ISA_BRIDGE_HEADER_OFFSET_P1 (0x00800000 >> IO_BIT_SHIFT) // AD[18]
+
+//
+// PCI-ISA Bridge Non-Configuration control register offsets.
+//
+#define SIO_II_EDGE_LEVEL_CONTROL_1 (0x9a00 >> IO_BIT_SHIFT)
+#define SIO_II_EDGE_LEVEL_CONTROL_2 (0x9a20 >> IO_BIT_SHIFT)
+
+//
+// PCI Sparse I/O space offsets for unique functions on Avanti.
+//
+
+#define PCI_INDEX (0x04c0 >> IO_BIT_SHIFT)
+#define PCI_DATA (0x04e0 >> IO_BIT_SHIFT)
+#define PCI_INT_REGISTER 0x14
+#define PCI_INT_LEVEL_REGISTER 0x15
+#define PCI_ISA_CONTROL_REGISTER 0x16
+#define DISABLE_PINTA_0 0x0f
+#define DISABLE_PINTA_1 0xf0
+#define DISABLE_PINTA_2 0x0f
+#define ENABLE_PINTA_0_AT_IRQ9 0x0d
+#define ENABLE_PINTA_1_AT_IRQ10 0xb0
+#define ENABLE_PINTA_2_AT_IRQ15 0x07
+#define L2EEN0_LEVEL 0x10
+#define L2EEN1_LEVEL 0x20
+#define L2EEN2_LEVEL 0x40
+#define ENABLE_FLOPPY_WRITE 0x10
+#define DISABLE_IDE_DMA 0x08
+#define DISABLE_SCSI_TERMINATION 0x04
+#define DISABLE_SCSI_IRQL_11 0x02
+#define DISABLE_MOUSE_IRQL_12 0x00
+
+//
+// PCI-ISA Bridge Configuration register offsets.
+//
+#define PCI_VENDOR_ID (0x0000 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_ID (0x0040 >> IO_BIT_SHIFT)
+#define PCI_COMMAND (0x0080 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_STATUS (0x00c0 >> IO_BIT_SHIFT)
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+#define PCI_CONTROL (0x0800 >> IO_BIT_SHIFT)
+#define PCI_ARBITER_CONTROL (0x0820 >> IO_BIT_SHIFT)
+#define ISA_ADDR_DECODER_CONTROL (0x0900 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_A (0x09c0 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_B (0x09e0 >> IO_BIT_SHIFT)
+#define PIRQ0_ROUTE_CONTROL (0x0c00 >> IO_BIT_SHIFT)
+#define PIRQ1_ROUTE_CONTROL (0x0c20 >> IO_BIT_SHIFT)
+#define PIRQ2_ROUTE_CONTROL (0x0c40 >> IO_BIT_SHIFT)
+#define PIRQ3_ROUTE_CONTROL (0x0c60 >> IO_BIT_SHIFT)
+
+//
+// SIO-II value for setting edge/level operation in the control words.
+//
+#define IRQ0_LEVEL_SENSITIVE 0x01
+#define IRQ1_LEVEL_SENSITIVE 0x02
+#define IRQ2_LEVEL_SENSITIVE 0x04
+#define IRQ3_LEVEL_SENSITIVE 0x08
+#define IRQ4_LEVEL_SENSITIVE 0x10
+#define IRQ5_LEVEL_SENSITIVE 0x20
+#define IRQ6_LEVEL_SENSITIVE 0x40
+#define IRQ7_LEVEL_SENSITIVE 0x80
+#define IRQ8_LEVEL_SENSITIVE 0x01
+#define IRQ9_LEVEL_SENSITIVE 0x02
+#define IRQ10_LEVEL_SENSITIVE 0x04
+#define IRQ11_LEVEL_SENSITIVE 0x08
+#define IRQ12_LEVEL_SENSITIVE 0x10
+#define IRQ13_LEVEL_SENSITIVE 0x20
+#define IRQ14_LEVEL_SENSITIVE 0x40
+#define IRQ15_LEVEL_SENSITIVE 0x80
+
+//
+// Values for enabling an IORQ route control setting.
+//
+#define PIRQX_ROUTE_IRQ3 0x03
+#define PIRQX_ROUTE_IRQ4 0x04
+#define PIRQX_ROUTE_IRQ5 0x05
+#define PIRQX_ROUTE_IRQ6 0x06
+#define PIRQX_ROUTE_IRQ7 0x07
+#define PIRQX_ROUTE_IRQ9 0x09
+#define PIRQX_ROUTE_IRQ10 0x0a
+#define PIRQX_ROUTE_IRQ11 0x0b
+#define PIRQX_ROUTE_IRQ12 0x0c
+#define PIRQX_ROUTE_IRQ14 0x0d
+#define PIRQX_ROUTE_IRQ15 0x0f
+#define PIRQX_ROUTE_ENABLE 0x00
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+//
+// Define primary (and only) CPU on an Avanti system
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0)
+
+//
+// Define the default processor clock frequency used before the actual
+// value can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (200)
+
+#endif // _AVANTIDEF_
+
+
+
+
diff --git a/private/ntos/nthals/halavant/alpha/bios.c b/private/ntos/nthals/halavant/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/busdata.c b/private/ntos/nthals/halavant/alpha/busdata.c
new file mode 100644
index 000000000..cc2a153c1
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/busdata.c
@@ -0,0 +1,125 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halavant/alpha/cache.c b/private/ntos/nthals/halavant/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/chipset.h b/private/ntos/nthals/halavant/alpha/chipset.h
new file mode 100644
index 000000000..0a72ef8cb
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/chipset.h
@@ -0,0 +1 @@
+#include "apecs.h"
diff --git a/private/ntos/nthals/halavant/alpha/ebinitnt.c b/private/ntos/nthals/halavant/alpha/ebinitnt.c
new file mode 100644
index 000000000..d11f3c79d
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ebinitnt.c
@@ -0,0 +1,857 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "avantdef.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+#if DBG
+VOID
+DumpEpic(
+ VOID
+ );
+#endif // DBG
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Avanti
+//
+// IRQ_H[0] = EPIC Error
+// IRQ_H[1] = unused
+// IRQ_H[2] = PIC
+// IRQ_H[3] = NMI
+// IRQ_H[4] = Clock
+// IRQ_H[5] = Halt
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// These globals make available the specifics of the Avanti platform
+// we're running in.
+//
+BOOLEAN ApecsPass2;
+BOOLEAN SioCStep;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+ADDRESS_USAGE
+AvantiPCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
+ 0,0
+ }
+};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpClearInterrupts(
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+//jnfix, wkc - init the Eisa interrupts after the chip, don't init the
+// PIC here, fix halenablesysteminterrupt to init the pic
+// interrrupt, as in sable
+
+ //
+ // Initialize the PCI/ISA interrupt controller.
+ //
+
+ HalpInitializePCIInterrupts();
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize error handling for APECS.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG PciBridgeHeaderOffset;
+ ULONG SioRevision;
+ COMANCHE_EDSR Edsr;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish the error handler, to reflect the parity checking
+ //
+
+ HalpEstablishErrorHandler();
+
+ //
+ // Find out what sort of APECS chip set we have in this Avanti. Clear
+ // the structure, first.
+ //
+ Edsr.all = 0;
+ Edsr.all = READ_COMANCHE_REGISTER( &((PCOMANCHE_CSRS)
+ (APECS_COMANCHE_BASE_QVA))->ErrorAndDiagnosticStatusRegister);
+ ApecsPass2 = (Edsr.Pass2 ? TRUE : FALSE);
+
+#ifdef HALDBG
+ DbgPrint("HalpInitializeMachineDependent: ApecsPass2 is %x\n",ApecsPass2);
+#endif
+
+ //
+ // Determine if we have a SIO-II, rather than SIO. If the result
+ // is 0x3, it's SIO-II, else the result will be 0x0.
+ //
+
+ if (ApecsPass2) {
+ PciBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET_P2;
+ } else {
+ PciBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET_P1;
+ }
+ SioRevision = READ_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciBridgeHeaderOffset | PCI_REVISION),
+ PCI_CONFIG_CYCLE_TYPE_0);
+ SioCStep = (SioRevision == 0x3 ? TRUE : FALSE);
+
+#ifdef HALDBG
+ DbgPrint("HalpInitializeMachineDependent: SioCStep is %x\n",SioCStep);
+#endif
+
+ HalpInitializeHAERegisters();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the EPIC/APECS chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // We set HAXR1 to 0. This means no address extension
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0);
+
+ //
+ // We set HAXR2 to 0. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. HAXR2 Not used in address translation
+ // 64K to 16MB VALID. HAXR2 is used in the address translation
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0);
+
+ //
+ // Report that the apecs mapping to the Io subsystem
+ //
+
+ HalpRegisterAddressUsage (&AvantiPCIMemorySpace);
+
+#if DBG
+ DumpEpic();
+#endif // DBG
+}
+
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the EPIC/APECS chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0 );
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0 );
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(APECS_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Avanti";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV4_UNCORRECTABLE processorFrame;
+ APECS_UNCORRECTABLE_FRAME AvantiUnCorrrectable;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/halavant/alpha/ebintsup.c b/private/ntos/nthals/halavant/alpha/ebintsup.c
new file mode 100644
index 000000000..4306a1469
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ebintsup.c
@@ -0,0 +1,447 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for EB66/Mustang, and
+ Avanti systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "avantdef.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Reference the boolean variable for SIO-II vs. SIO, i.e., the
+// Avanti pass 2 MLB, and the boolean for the APECS pass 2 on the
+// Avanti pass 2 daughter card.
+//
+extern BOOLEAN SioCStep;
+extern BOOLEAN ApecsPass2;
+
+//
+// Declare the interrupt handler for the PCI and ISA bus.
+//
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ ISA interrupt controller; in the case of the SIO-II in Avanti, the
+ integral interrupt controller is compatible with the EISA interrupt
+ contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG PciIsaBridgeHeaderOffset;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive);
+
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // We must declare the right form for the APECS PCI/ISA bridge
+ // configuration space device selector for use in the initialization
+ // of the interrupts.
+ //
+ if (ApecsPass2) {
+ PciIsaBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET_P2;
+ } else {
+ PciIsaBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET_P1;
+ }
+
+//
+// Now done completely in the Firmware - wkc
+//
+
+#if 0
+ if (SioCStep) {
+
+ //
+ // Pass2 MLB pin to line table
+ //
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) AvantiPCIPinToLineTable;
+
+ //
+ // Setup the Avanti interrupt assignments for the C-Step SIO; this
+ // is done with registers that are internal to the SIO-II, PIRQ0,
+ // PIRQ1, PIRQ2, and PIRQ3. They're at offsets 0x60, 0x61, 0x62,
+ // and 0x63 of the SIO-II's configuration registers. The effect
+ // of these registers is to steer the PCI interrupts into the IRQx
+ // inputs of the SIO's internal cascaded 82C59 interrupt controllers.
+ // These controllers are then programmed in their usual fashion.
+ //
+ // Set up interrupts from PCI slots 0, 1, and 2, compatible with
+ // Avanti pass 1 MLB, i.e., steer the interrupt from each PCI
+ // slot or device into the default IRQL from pass 1 Avanti; enable
+ // the routings.
+ //
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ0_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ10 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ1_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ15 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ2_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ9 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ //
+ // Set up interrupt from SCSI (IRQ11), and enable the routing.
+ //
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ3_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ11 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ //
+ // Select "level" operation for PCI PIRQx interrupt lines, and
+ // "edge" for ISA devices, e.g., mouse at IRQL12. Default is "edge"
+ // so no mention means "edge".
+ //
+ WRITE_REGISTER_UCHAR((PCHAR)(PCI_SPARSE_IO_BASE_QVA
+ | SIO_II_EDGE_LEVEL_CONTROL_2),
+ IRQ11_LEVEL_SENSITIVE | IRQ10_LEVEL_SENSITIVE |
+ IRQ9_LEVEL_SENSITIVE | IRQ15_LEVEL_SENSITIVE);
+
+ } else {
+
+ //
+ // Pass1 MLB pin to line table
+ //
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) AvantiPCIPinToLineTableP1;
+
+ //
+ //
+ // Anything prior to a C-step SIO chip has a funny MUX register pair
+ // for PCI interrupts.
+ //
+ // Avanti Pass1 only: Intialize PCI Interrupt translation mux
+ //
+ // Select PCI Int Register.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)(PCI_SPARSE_IO_BASE_QVA | PCI_INDEX),
+ PCI_INT_REGISTER); // PCI Index Register 0x14
+ //
+ // Enable interrupts from PCI slots 0 and 1
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)(PCI_SPARSE_IO_BASE_QVA | PCI_DATA),
+ ENABLE_PINTA_0_AT_IRQ9 |
+ ENABLE_PINTA_1_AT_IRQ10);
+
+ //
+ // Select PCI Int/Level Register.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)(PCI_SPARSE_IO_BASE_QVA | PCI_INDEX),
+ PCI_INT_LEVEL_REGISTER); // PCI Index Register 0x15
+ //
+ // Enable interrupts from PCI slot 2; select "level" operation for
+ // all three interrupt lines.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)(PCI_SPARSE_IO_BASE_QVA | PCI_DATA),
+ ENABLE_PINTA_2_AT_IRQ15 |
+ L2EEN0_LEVEL | L2EEN1_LEVEL | L2EEN2_LEVEL);
+ }
+// end AVANTI_PROTO1
+
+#endif // wkc
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Sio machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ return( InterruptVector );
+
+}
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
diff --git a/private/ntos/nthals/halavant/alpha/ebmapio.c b/private/ntos/nthals/halavant/alpha/ebmapio.c
new file mode 100644
index 000000000..850894769
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ebmapio.c
@@ -0,0 +1,153 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "avantdef.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for an Avanti
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // CMOS ram addresses encoded in nvram.c - kept for commonality
+ // in environ.c
+ //
+
+ HalpCMOSRamBase = (PVOID) 0;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( APECS_PCI_IO_BASE_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( APECS_PCI_INTACK_BASE_PHYSICAL );
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halavant/alpha/ebsgdma.c b/private/ntos/nthals/halavant/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/ebsysint.c b/private/ntos/nthals/halavant/alpha/ebsysint.c
new file mode 100644
index 000000000..fb10ba0d1
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ebsysint.c
@@ -0,0 +1,394 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "avantdef.h"
+#include "axp21064.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR
+ //
+
+ return((BusInterruptLevel) + ISA_VECTORS);
+
+ break;
+
+
+
+ default:
+
+ //
+ // Not an interface supported on EB66/Mustang systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Avanti because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halavant/alpha/eisasup.c b/private/ntos/nthals/halavant/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/environ.c b/private/ntos/nthals/halavant/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/ev4cache.c b/private/ntos/nthals/halavant/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/ev4int.c b/private/ntos/nthals/halavant/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/ev4ints.s b/private/ntos/nthals/halavant/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/ev4mchk.c b/private/ntos/nthals/halavant/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/ev4mem.s b/private/ntos/nthals/halavant/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/ev4prof.c b/private/ntos/nthals/halavant/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/fwreturn.c b/private/ntos/nthals/halavant/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/haldebug.c b/private/ntos/nthals/halavant/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/halpal.s b/private/ntos/nthals/halavant/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/idle.s b/private/ntos/nthals/halavant/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/info.c b/private/ntos/nthals/halavant/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/inithal.c b/private/ntos/nthals/halavant/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/intsup.s b/private/ntos/nthals/halavant/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halavant/alpha/ioproc.c b/private/ntos/nthals/halavant/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/iousage.c b/private/ntos/nthals/halavant/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/machdep.h b/private/ntos/nthals/halavant/alpha/machdep.h
new file mode 100644
index 000000000..72294adba
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Avanti platform-specific definitions.
+//
+
+#include "avantdef.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halavant/alpha/memory.c b/private/ntos/nthals/halavant/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/nvram.c b/private/ntos/nthals/halavant/alpha/nvram.c
new file mode 100644
index 000000000..7fb21c1ea
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/nvram.c
@@ -0,0 +1,279 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ xxnvram.c
+
+Abstract:
+
+ This module implements the device-specific routines necessary to
+ Read and Write the Non Volatile RAM containing the system environment
+ variables. The routines implemented here are:
+
+ HalpReadNVRamBuffer() - copy data from NVRAM into memory
+ HalpWriteNVRamBuffer() - write memory data to NVRAM
+ HalpCopyNVRamBuffer() - move data within the NVRAM
+
+Author:
+
+ Steve Brooks 5-Oct 93
+
+
+Revision History:
+
+
+ Wim Colgate 20-Dec-93
+
+ This module has been changed to reflect Avanti's notion of FLASH BUS.
+ Basically, the offset in the 8K flash buffer is plave into the CMOS
+ port address, and the data in the CMOS data adress.
+
+--*/
+
+
+#include "halp.h"
+
+#include "arccodes.h"
+
+//
+// Routine prototypes.
+//
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ );
+
+
+#define CMOS_ADDRESS_PORT HAL_MAKE_QVA( 0x100000000 )
+#define CMOS_DATA_PORT HAL_MAKE_QVA( 0x100100000 )
+
+#define CMOS_ADDR_SHIFT 8
+
+#define CMOS_WRITE_HARBINGER (1 << 31)
+
+#define NVRAM_8K_BASE 0x100000
+
+#define BANKSET8_CONFIGURATION_REGISTER HAL_MAKE_QVA( 0x180000B00 )
+#define BANKSET8_ENABLE 0x1
+
+
+static UCHAR
+HalpReadCMOSByte( ULONG ByteOffset )
+{
+ UCHAR inChar;
+ ULONG Address;
+
+ //
+ // Output the offset to the index register.
+ //
+
+ Address = (ULONG)( (ByteOffset | NVRAM_8K_BASE) << CMOS_ADDR_SHIFT );
+ WRITE_EPIC_REGISTER(CMOS_ADDRESS_PORT, Address);
+
+ //
+ // Now read the data register:
+ //
+
+ inChar = (UCHAR)READ_EPIC_REGISTER( CMOS_DATA_PORT) & 0xff;
+
+ return inChar;
+}
+
+static VOID
+HalpWriteCMOSByte( ULONG ByteOffset, UCHAR Byte )
+{
+ ULONG Address;
+
+ //
+ // Output the offset to the index register.
+ //
+
+ Address = (ULONG)( (ByteOffset | NVRAM_8K_BASE) << CMOS_ADDR_SHIFT );
+ WRITE_EPIC_REGISTER( CMOS_ADDRESS_PORT, CMOS_WRITE_HARBINGER | Address );
+
+ //
+ // Now output the data to the data port.
+ //
+
+ WRITE_EPIC_REGISTER( CMOS_DATA_PORT, (ULONG) Byte) ;
+}
+
+//
+//
+//
+
+ARC_STATUS HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Reads data from the NVRam into main memory
+
+Arguments:
+
+ DataPtr - Pointer to memory location to receive data
+ NvRamPtr - Offset in the CMOS area
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+{
+
+ ULONG CsrMask;
+
+ //
+ // Enable Bankset 8
+ //
+
+ CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER );
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER,
+ CsrMask | BANKSET8_ENABLE );
+
+ while ( Length -- ) {
+ *DataPtr = HalpReadCMOSByte( (ULONG)NvRamPtr );
+ NvRamPtr++;
+ DataPtr++;
+ }
+
+ //
+ // Disable Bankset 8 (Restore original state)
+ //
+
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask );
+
+ return(ESUCCESS);
+}
+
+//
+//
+//
+ARC_STATUS HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Writes data from memory into the NVRam
+
+Arguments:
+
+ NvRamPtr - Pointer (qva) to NVRam location to write data into
+ DataPtr - Pointer to memory location of data to be written
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+{
+ ULONG CsrMask;
+
+ //
+ // Enable Bankset 8
+ //
+
+ CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER );
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER,
+ CsrMask | BANKSET8_ENABLE );
+
+ while ( Length -- ) {
+ HalpWriteCMOSByte((ULONG)NvRamPtr, *DataPtr);
+ NvRamPtr ++;
+ DataPtr ++;
+ }
+
+ //
+ // Disable Bankset 8 (Restore original state)
+ //
+
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask );
+
+ return(ESUCCESS);
+}
+
+//
+//
+//
+ARC_STATUS HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length )
+/*++
+
+Routine Description:
+
+ This routine copies data between two locations within the NVRam. It is
+ the callers responsibility to assure that the destination region does not
+ overlap the src region i.e. if the regions overlap, NvSrcPtr > NvDestPtr.
+
+Arguments:
+
+ NvDestPtr - Byte offset into CMOS area for destination
+ NvSrcPtr - Byte offset into CMOS area for source
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+
+--*/
+
+{
+ UCHAR tmpChar;
+
+ ULONG CsrMask;
+
+ //
+ // Enable Bankset 8
+ //
+
+ CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER );
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER,
+ CsrMask | BANKSET8_ENABLE );
+
+ while ( Length -- )
+ {
+ tmpChar = HalpReadCMOSByte((ULONG)NvSrcPtr);
+ HalpWriteCMOSByte((ULONG)NvDestPtr, tmpChar);
+ NvSrcPtr ++;
+ NvDestPtr ++;
+ }
+
+ //
+ // Disable Bankset 8 (Restore original state)
+ //
+
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask );
+
+ return(ESUCCESS);
+}
diff --git a/private/ntos/nthals/halavant/alpha/pcibus.c b/private/ntos/nthals/halavant/alpha/pcibus.c
new file mode 100644
index 000000000..e9307c1e9
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pcibus.c
@@ -0,0 +1,117 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+//
+// This references a boolean variable that identifies the APECS revision.
+//
+
+extern BOOLEAN ApecsPass2;
+
+extern ULONG PCIMaxBus;
+
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0)
+ {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24, which, in APECS
+ // pass 1, are wired to IDSEL pins. In pass 2, the format of a type
+ // 0 cycle is the same as the format of a type 1. Note that
+ // HalpValidPCISlot has already done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: ApecsPass2 is %x\n", ApecsPass2);
+#endif // DBG
+ if (ApecsPass2) {
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+ } else {
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+ }
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ else
+ {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if HALDBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halavant/alpha/pcisio.c b/private/ntos/nthals/halavant/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/pcisup.c b/private/ntos/nthals/halavant/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/pcrtc.c b/private/ntos/nthals/halavant/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/pcserial.c b/private/ntos/nthals/halavant/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/pcspeakr.c b/private/ntos/nthals/halavant/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/perfcntr.c b/private/ntos/nthals/halavant/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halavant/alpha/pintolin.h b/private/ntos/nthals/halavant/alpha/pintolin.h
new file mode 100644
index 000000000..5723d3fbd
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/pintolin.h
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang and EB66, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for EB66
+//
+// You can limit init table to MAX_PCI_LOCAL_DEVICES entries.
+// The highest virtual slot between EB66 and Mustang is 9, so
+// MAX_PCI_LOCAL_DEVICE is defined as 9 in the platform dependent
+// header file (MUSTDEF.H). HalpValidPCISlot assures us that
+// we won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 9 = PCI_AD[20].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+//
+// Interrupt Vector Table Mapping for Avanti
+//
+// Avanti PCI interrupts are mapped to ISA IRQs in the table below.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_AVANTI.
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+
+ULONG AvantiPCIPinToLineTable[][4]=
+{
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xb, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] SIO
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0xa, 0x9, 0xf, 0xa }, // Virtual Slot 11 = PCI_AD[22] Slot #0
+ { 0xf, 0xa, 0x9, 0xf }, // Virtual Slot 12 = PCI_AD[23] Slot #1
+ { 0x9, 0xf, 0xa, 0x9 } // Virtual Slot 13 = PCI_AD[24] Slot #2
+};
+
+ULONG AvantiPCIPinToLineTableP1[][4]=
+{
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xb, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] SIO
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0x9, 0xf, 0xa, 0x9 }, // Virtual Slot 13 = PCI_AD[24] Slot #0
+ { 0xa, 0x9, 0xf, 0xa }, // Virtual Slot 11 = PCI_AD[22] Slot #1
+ { 0xf, 0xa, 0x9, 0xf } // Virtual Slot 12 = PCI_AD[23] Slot #2
+};
diff --git a/private/ntos/nthals/halavant/alpha/vga.c b/private/ntos/nthals/halavant/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halavant/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halavant/drivesup.c b/private/ntos/nthals/halavant/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halavant/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halavant/hal.rc b/private/ntos/nthals/halavant/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halavant/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halavant/hal.src b/private/ntos/nthals/halavant/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halavant/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halavant/makefile b/private/ntos/nthals/halavant/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halavant/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halavant/makefile.inc b/private/ntos/nthals/halavant/makefile.inc
new file mode 100644
index 000000000..0f5a8b41c
--- /dev/null
+++ b/private/ntos/nthals/halavant/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halavant.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halavant/sources b/private/ntos/nthals/halavant/sources
new file mode 100644
index 000000000..0afb762e0
--- /dev/null
+++ b/private/ntos/nthals/halavant/sources
@@ -0,0 +1,103 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halavant
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DAPECS
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\apecs.c \
+ alpha\apecserr.c \
+ alpha\apecsio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mchk.c \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\ebinitnt.c \
+ alpha\ebintsup.c \
+ alpha\ebmapio.c \
+ alpha\ebsysint.c \
+ alpha\nvram.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halcaro/hal.rc b/private/ntos/nthals/halcaro/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halcaro/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halcaro/makefile b/private/ntos/nthals/halcaro/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halcaro/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halcaro/ppc/fwnvr.c b/private/ntos/nthals/halcaro/ppc/fwnvr.c
new file mode 100644
index 000000000..74d30689e
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/fwnvr.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\fwnvr.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxbbl.c b/private/ntos/nthals/halcaro/ppc/pxbbl.c
new file mode 100644
index 000000000..5466a07f1
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxbbl.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxbbl.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxbeep.c b/private/ntos/nthals/halcaro/ppc/pxbeep.c
new file mode 100644
index 000000000..cb3db8ccc
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxbeep.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxbeep.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxbl.c b/private/ntos/nthals/halcaro/ppc/pxbl.c
new file mode 100644
index 000000000..c80af0ce0
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxbl.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxbl.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxbusdat.c b/private/ntos/nthals/halcaro/ppc/pxbusdat.c
new file mode 100644
index 000000000..cbc199e71
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxbusdat.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxbusdat.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxcache.s b/private/ntos/nthals/halcaro/ppc/pxcache.s
new file mode 100644
index 000000000..2c5630a60
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxcache.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcache.s>
diff --git a/private/ntos/nthals/halcaro/ppc/pxcalstl.c b/private/ntos/nthals/halcaro/ppc/pxcalstl.c
new file mode 100644
index 000000000..3d972b02b
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxcalstl.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcalstl.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxclksup.s b/private/ntos/nthals/halcaro/ppc/pxclksup.s
new file mode 100644
index 000000000..8452d5e05
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxclksup.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclksup.s>
diff --git a/private/ntos/nthals/halcaro/ppc/pxclock.c b/private/ntos/nthals/halcaro/ppc/pxclock.c
new file mode 100644
index 000000000..16cb61886
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxclock.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclock.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxdat.c b/private/ntos/nthals/halcaro/ppc/pxdat.c
new file mode 100644
index 000000000..978438ac0
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxdat.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxdat.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxdisp.c b/private/ntos/nthals/halcaro/ppc/pxdisp.c
new file mode 100644
index 000000000..103883cc6
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxdisp.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxdisp.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxenviro.c b/private/ntos/nthals/halcaro/ppc/pxenviro.c
new file mode 100644
index 000000000..0f822c840
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxenviro.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxenviro.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxfirsup.c b/private/ntos/nthals/halcaro/ppc/pxfirsup.c
new file mode 100644
index 000000000..21d6ffc71
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxfirsup.c
@@ -0,0 +1,2044 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1993-1996 International Business Machines Corporation
+
+Module Name:
+
+ pxfirsup.c
+
+Abstract:
+
+ The module provides the support for the fire coral PCI-ISA bridge.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxfirsup.h"
+#include <pxmemctl.h>
+#include "bugcodes.h"
+#include "pxidesup.h"
+
+extern UCHAR VectorToIrqlTable[];
+
+#define SioId 0x04848086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPhase0GetPciDataByOffset();
+extern ULONG HalpPhase0SetPciDataByOffset();
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+//
+// Declare the interupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+
+//
+// Define Isa bus interrupt affinity.
+//
+
+KAFFINITY HalpIsaBusAffinity;
+
+
+//
+// The following function is called when a IDE interrupt occurs.
+//
+
+BOOLEAN
+HalpHandleIdeInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern USHORT Halp8259MaskTable[];
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+#if defined(SOFT_HDD_LAMP)
+
+//
+// On PowerPC machines the HDD lamp is software driven. We
+// turn it on any time we take an interrupt from a Mass Storage
+// Controller (assuming it isn't already on) and turn it off the 2nd
+// clock tick after we turn it on if we have not received
+// any more MSC interrupts since the first clock tick.
+//
+// N.B. Hardwired to cause any IDE interrupt to turn the light on.
+//
+
+HDD_LAMP_STATUS HalpHddLamp;
+
+ULONG HalpMassStorageControllerVectors = 1 << IDE_DISPATCH_VECTOR;
+
+#endif
+
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG Vector;
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+
+ //
+ // All IDE interrupts come thru the IDE_DISPATCH_VECTOR. Install
+ // a handler for that vector that will determine the actual IDE
+ // device and dispatch appropriately.
+ //
+
+ PCR->InterruptRoutine[DEVICE_VECTORS + IDE_DISPATCH_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleIdeInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt;
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber;
+ ULONG ChipId;
+ ULONG BufferLength;
+
+
+ Found = FALSE;
+ SlotNumber = 0;
+
+ while (!Found && SlotNumber < HalpPciMaxSlots) {
+
+ BufferLength = HalpPhase0GetPciDataByOffset(0,
+ SlotNumber,
+ &ChipId,
+ 0,
+ sizeof(ChipId));
+ if (ChipId == SioId)
+ Found = TRUE;
+ else
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found)
+ return FALSE;
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0GetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0SetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+
+ DataByte |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+
+ WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+
+ //
+ // Disable Gauranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo())
+
+ return FALSE;
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine in entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ UCHAR Irql;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask;
+
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (interruptVector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+#if DBG
+ //DbgPrint("A spurious interrupt occurred. \n");
+ HalpSpuriousInterruptCount++;
+#endif
+ return(0);
+
+ }
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( HalpMassStorageControllerVectors & (1 << interruptVector) ) {
+ //
+ // On any Mass Storage Controller interrupt, light the HDD lamp.
+ // The system timer routines will turn it off again in a little
+ // while.
+ //
+
+ if ( !HalpHddLamp.Count ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1;
+ }
+ HalpHddLamp.Count = SOFT_HDD_TICK_COUNT;
+ }
+
+#endif
+
+
+ //
+ // raise irql
+ //
+
+ Irql = VectorToIrqlTable[interruptVector];
+
+ //
+ // Raise Irql to appropriate device level
+ //
+
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = Irql;
+
+ HalpEnableInterrupts();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers. We disable
+ // interrupts first so we won't get multiple interrupts at this level
+ // without popping the stack.
+ //
+
+ HalpDisableInterrupts();
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Lower IRQL but leave external interrupts disabled.
+ // Return to caller with interrupts disabled.
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ //
+ // Partial lazy irql - if hardware irql mask isn't what is should be
+ // set it and the interrupt controllers mask.
+ //
+
+ if (HALPCR->HardPriority > PCR->CurrentIrql) {
+
+ HALPCR->HardPriority = OldIrql;
+
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[OldIrql] & 0x00FF);
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get contoller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[OldIrql] >> 8 );
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ }
+
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ //
+ // bit 2 in the extended mode register must be set to 1 for ISA busmastering to work
+ // correctly on Firecoral
+ //
+
+ if (DeviceDescriptor->Master) {
+ extendedMode.TransferSize |= 1;
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // DMA high page must be set to 0x80 for ISA bus masters to work on
+ // FireCoral.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)adapterObject->PagePort,
+ 0x80
+ );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // DMA high page must be set to 0x80 for ISA bus masters to work on
+ // FireCoral.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)adapterObject->PagePort,
+ 0x80
+ );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
diff --git a/private/ntos/nthals/halcaro/ppc/pxflshbf.s b/private/ntos/nthals/halcaro/ppc/pxflshbf.s
new file mode 100644
index 000000000..b2e4b591d
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxflshbf.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshbf.s>
diff --git a/private/ntos/nthals/halcaro/ppc/pxflshio.c b/private/ntos/nthals/halcaro/ppc/pxflshio.c
new file mode 100644
index 000000000..5817b14f5
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxflshio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshio.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxhwsup.c b/private/ntos/nthals/halcaro/ppc/pxhwsup.c
new file mode 100644
index 000000000..9164059ae
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxhwsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxhwsup.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxidesup.c b/private/ntos/nthals/halcaro/ppc/pxidesup.c
new file mode 100644
index 000000000..187d05eee
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxidesup.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 1995-1996 International Business Machines Corporation
+
+Module Name:
+
+ pxidesup.c
+
+Abstract:
+
+ The module provides IDE interrupt dispatching support
+ for Carolina and Delmar systems.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+ Chris Karamatas (ckaramats@vnet.ibm.com)
+ 5.19.95 - Moved clearing of Utah to before DD ISR is run
+ - Consolodated code path for setting IdeVector & IdeInterruptRequest
+
+
+--*/
+
+
+#include "halp.h"
+#include "pxidesup.h"
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+
+BOOLEAN
+HalpHandleIdeInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine in entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ BOOLEAN returnValue;
+ UCHAR IdeInterruptRequest;
+ USHORT IdeVector;
+
+ IdeInterruptRequest = READ_REGISTER_UCHAR(
+ (PUCHAR)HalpIoControlBase +
+ IDE_INTERRUPT_REQUEST_REGISTER);
+
+ if (IdeInterruptRequest & IDE_PRIMARY_INTERRUPT_REQUEST){
+ IdeVector = PRIMARY_IDE_VECTOR;
+ IdeInterruptRequest = IDE_SECONDARY_INTERRUPT_REQUEST;
+ } else if (IdeInterruptRequest & IDE_SECONDARY_INTERRUPT_REQUEST ) {
+ IdeVector = SECONDARY_IDE_VECTOR;
+ IdeInterruptRequest = IDE_PRIMARY_INTERRUPT_REQUEST;
+ } else {
+ return ( FALSE);
+ }
+
+
+ //
+ // Clear the interrupt in the UTAH IDE interrupt request register.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase +
+ IDE_INTERRUPT_REQUEST_REGISTER,
+ IdeInterruptRequest);
+
+
+ //
+ // Dispatch to the IDE interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + IdeVector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+
+ return(returnValue);
+
+}
diff --git a/private/ntos/nthals/halcaro/ppc/pxidesup.h b/private/ntos/nthals/halcaro/ppc/pxidesup.h
new file mode 100644
index 000000000..e0e7529e8
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxidesup.h
@@ -0,0 +1,30 @@
+/*++
+
+Module Name:
+
+ pxidesup.h
+
+Abstract:
+
+ The module provides data structures for
+ IDE support in DELMAR and CAROLINA systems.
+
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#define IDE_DISPATCH_VECTOR 13
+#define PRIMARY_IDE_VECTOR 16
+#define SECONDARY_IDE_VECTOR 17
+
+#define IDE_INTERRUPT_REQUEST_REGISTER 0x838
+#define IDE_PRIMARY_INTERRUPT_REQUEST 0x1
+#define IDE_SECONDARY_INTERRUPT_REQUEST 0x2
diff --git a/private/ntos/nthals/halcaro/ppc/pxidle.c b/private/ntos/nthals/halcaro/ppc/pxidle.c
new file mode 100644
index 000000000..f8a2cb40c
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxidle.c
@@ -0,0 +1 @@
+#include "..\..\halppc\ppc\pxidle.c"
diff --git a/private/ntos/nthals/halcaro/ppc/pxinfo.c b/private/ntos/nthals/halcaro/ppc/pxinfo.c
new file mode 100644
index 000000000..812bd48b4
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxinfo.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxinfo.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxinithl.c b/private/ntos/nthals/halcaro/ppc/pxinithl.c
new file mode 100644
index 000000000..f99a85307
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxinithl.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxinithl.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxintmod.c b/private/ntos/nthals/halcaro/ppc/pxintmod.c
new file mode 100644
index 000000000..e9b1070cd
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxintmod.c
@@ -0,0 +1,78 @@
+/*++
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ This module implements interrupt mode translation for PowerPC machines.
+
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+
+
+#include "halp.h"
+
+
+//
+// Get the translated interrupt mode for the given vector
+//
+
+
+KINTERRUPT_MODE
+HalpGetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+{
+
+ //
+ // On Polo irq 15 is reserved for PCI interrupts and must be programmed level sensitive
+ // all other interrupts are edge triggered
+ //
+
+ if ((Vector == DEVICE_VECTORS + 15) || (Vector == DEVICE_VECTORS + 13)) {
+
+ return LevelSensitive;
+
+ } else {
+
+ return InterruptMode;
+
+ }
+
+
+
+}
+
+//
+// Correct the interrupt mode for the given vector.
+// On Polo this function simply returns since all interrupt mode translations can be performed
+// at HalpGetInterruptMode time with the interrupt vector.
+//
+
+
+VOID
+HalpSetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+{
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halcaro/ppc/pxintsup.s b/private/ntos/nthals/halcaro/ppc/pxintsup.s
new file mode 100644
index 000000000..f72297f65
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxintsup.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxintsup.s>
diff --git a/private/ntos/nthals/halcaro/ppc/pxirql.c b/private/ntos/nthals/halcaro/ppc/pxirql.c
new file mode 100644
index 000000000..7ad12df0b
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxirql.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxirql.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxisabus.c b/private/ntos/nthals/halcaro/ppc/pxisabus.c
new file mode 100644
index 000000000..a38788df8
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxisabus.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxisabus.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxmapio.c b/private/ntos/nthals/halcaro/ppc/pxmapio.c
new file mode 100644
index 000000000..38b6ef09e
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxmapio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxmapio.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxmemctl.c b/private/ntos/nthals/halcaro/ppc/pxmemctl.c
new file mode 100644
index 000000000..4f49a326f
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxmemctl.c
@@ -0,0 +1,325 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1994, 95, 96 International Buisness Machines Corporation.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) - added HalpHandleMemoryError
+
+--*/
+
+
+
+#include "halp.h"
+#include <pxmemctl.h>
+#include "pxidaho.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+
+ return TRUE;
+
+}
+
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ HalpPciConfigBase = (PVOID) IO_CONTROL_PHYSICAL_BASE;
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ HalpPciConfigBase = (PVOID) IO_CONTROL_PHYSICAL_BASE;
+
+ if (HalpIoControlBase == NULL) {
+ HalpIoControlBase = (PUCHAR)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x400000);
+ }
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+}
+
+
+VOID
+HalpDisplayRegister(
+ PUCHAR RegHex,
+ int Bytes
+ )
+
+/*++
+
+Routine Description:
+
+ Displays (via HalDisplayString) a new-line terminated
+ string of hex digits representing the input value. The
+ input value is pointed to by the first argument is
+ from 1 to 4 bytes in length.
+
+Arguments:
+
+ RegHex Pointer to the value to be displayed.
+ Bytes Length of input value in bytes (1-4).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#define DISP_MAX 4
+ UCHAR RegString[(DISP_MAX * 2) + 2];
+ UCHAR Num, High, Low;
+ PUCHAR Byte = &RegString[(DISP_MAX * 2) + 1];
+
+ *Byte = '\0';
+ *--Byte = '\n';
+
+ if ( (unsigned)Bytes > DISP_MAX ) {
+ Bytes = DISP_MAX;
+ }
+
+ while (Bytes--) {
+ Num = *RegHex++;
+ High = (Num >> 4) + '0';
+ Low = (Num & 0xf) + '0';
+ if ( High > '9' ) {
+ High += ('A' - '0' - 0xA);
+ }
+ if ( Low > '9' ) {
+ Low += ('A' - '0' - 0xA);
+ }
+ *--Byte = Low;
+ *--Byte = High;
+ }
+ HalDisplayString(Byte);
+}
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+ int byte;
+ IDAHO_CONFIG PCI_Config_Space;
+ UCHAR BusAddress[4];
+
+ //
+ // Make sure Options Reg.1 (0xBA) and Enable Detection Reg. (0xC0)
+ // are programed. Reset Error Det Reg when done ?
+ //
+
+ HalGetBusData(PCIConfiguration,
+ 0,
+ 0,
+ &PCI_Config_Space,
+ sizeof(IDAHO_CONFIG));
+
+ //
+ // Dump Error Detection Reg, Bus Address, Status Error,
+ //
+
+ HalDisplayString ("TEA/MCP: System Error.\n");
+
+ HalDisplayString ("Error Detection Register 1: ");
+ HalpDisplayRegister (&PCI_Config_Space.ErrorDetection1,1);
+
+ //
+ // The error may have been detected during xfers on: cpu (local),
+ // memory, or pci bus.
+ //
+ // Idaho will NOT generate/check Local Bus Parity
+ //
+
+ if (PCI_Config_Space.ErrorDetection1 & 0x03) {
+ //
+ // idaho <-> 603 :Local bus Cycle
+ //
+
+ HalDisplayString ("Unsupported Local Bus Cycle\n");
+
+ for (byte = 0; byte < 4; byte++) {
+ //
+ // Correct endianess if address is local
+ //
+ BusAddress[byte] = PCI_Config_Space.ErrorAddress[3-byte];
+ }
+ HalDisplayString ("Local Bus Error Address: ");
+ HalpDisplayRegister(BusAddress,4);
+
+ HalDisplayString ("CPU Bus Error Status - TT(0:4);TSIZ(0:2): ");
+ HalpDisplayRegister(&PCI_Config_Space.CpuBusErrorStatus,1);
+
+ } else if (PCI_Config_Space.ErrorDetection1 & 0x08) {
+ //
+ // PCI Cycle
+ //
+ HalDisplayString ("PCI Cycle\n");
+
+ for (byte=0; byte<4; byte++) {
+ BusAddress[byte] = PCI_Config_Space.ErrorAddress[byte];
+ }
+ HalDisplayString ("PCI Bus Address: ");
+ HalpDisplayRegister(BusAddress,4);
+
+ HalDisplayString ("PCI Bus Error Status: ");
+ HalpDisplayRegister(&PCI_Config_Space.PciBusErrorStatus,1);
+
+ HalDisplayString ("PCI Device Status Register D(15:8): ");
+ HalpDisplayRegister(&PCI_Config_Space.DeviceStatus[1],1);
+ }
+}
diff --git a/private/ntos/nthals/halcaro/ppc/pxmemctl.h b/private/ntos/nthals/halcaro/ppc/pxmemctl.h
new file mode 100644
index 000000000..1c0ca1966
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxmemctl.h
@@ -0,0 +1,36 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define physical base addresses of planar
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxnatsup.c b/private/ntos/nthals/halcaro/ppc/pxnatsup.c
new file mode 100644
index 000000000..45b71d905
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxnatsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxnatsup.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxp91.c b/private/ntos/nthals/halcaro/ppc/pxp91.c
new file mode 100644
index 000000000..0427a3f5f
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxp91.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxp91.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxpcibrd.c b/private/ntos/nthals/halcaro/ppc/pxpcibrd.c
new file mode 100644
index 000000000..d10d244dd
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxpcibrd.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpcibrd.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxpcibus.c b/private/ntos/nthals/halcaro/ppc/pxpcibus.c
new file mode 100644
index 000000000..894176e9b
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxpcibus.c
@@ -0,0 +1 @@
+#include "..\..\halppc\ppc\pxpcibus.c"
diff --git a/private/ntos/nthals/halcaro/ppc/pxpciint.c b/private/ntos/nthals/halcaro/ppc/pxpciint.c
new file mode 100644
index 000000000..089386edd
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxpciint.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpciint.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxpcisup.c b/private/ntos/nthals/halcaro/ppc/pxpcisup.c
new file mode 100644
index 000000000..57b7c3671
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxpcisup.c
@@ -0,0 +1,299 @@
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1995-96 International Business Machines Corporation
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+extern PVOID HalpPciConfigBase;
+#define PCI_INTERRUPT_ROUTING_OTHER 15 //IBMCPK: should we really have seperate scsi int??
+#define PCI_INTERRUPT_ROUTING_SCSI PCI_INTERRUPT_ROUTING_OTHER
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#endif
+
+
+
+ULONG HalpPciMaxSlots = PCI_MAX_DEVICES;
+
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+ This is a sandalfoot memory map implementation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ PCI_TYPE1_CFG_BITS PciConfig;
+ PCI_SLOT_NUMBER PciSlotNumber;
+
+ PciSlotNumber.u.AsULONG = SlotNumber;
+
+ PciConfig.u.AsULONG = 0;
+ PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber;
+ PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber;
+ PciConfig.u.bits.BusNumber = BusNumber;
+ PciConfig.u.bits.Enable = TRUE;
+
+ return (PciConfig.u.AsULONG);
+
+
+}
+
+
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ ULONG to;
+ PUCHAR from;
+ ULONG tmpLength;
+ ULONG i;
+
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ to = (ULONG) HalpPciConfigBase + (SlotNumber << 11);
+ to += Offset;
+ from = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, to );
+ i = to % sizeof(ULONG);
+ WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*from);
+ to++;
+ from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PUCHAR to;
+ ULONG from;
+ ULONG tmpLength;
+ ULONG i;
+
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+
+ from = (ULONG) HalpPciConfigBase + (SlotNumber << 11);
+ from += Offset;
+ to = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+
+ WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, from);
+ i = from % sizeof(ULONG);
+ *((PUCHAR) to) = READ_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i);
+ to++;
+ from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ ULONG buffer[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)];
+ PPCI_COMMON_CONFIG PciData;
+
+#define PCI_VENDOR_NCR 0x1000
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+
+ if (PciSlot.u.bits.DeviceNumber == 2) {
+ (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_SCSI;
+ (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_SCSI;
+ } else {
+ (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_OTHER;
+ (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_OTHER;
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( (PciData->BaseClass == 1) ||
+ ( (PciData->VendorID == PCI_VENDOR_NCR) && (PciData->DeviceID == 1) ) ) {
+ //
+ // This device is a Mass Storage Controller, set flag to
+ // turn on the HDD Lamp when interrupts come in on this
+ // vector.
+ //
+ // N.B. We recognize NCR 810 controllers as they were implemented
+ // before class codes.
+ //
+
+ extern ULONG HalpMassStorageControllerVectors;
+
+ HalpMassStorageControllerVectors |= 1 << (*Interrupt)->Base;
+ }
+
+#endif
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpMapPlugInPciBridges(
+ UCHAR NoBuses
+ )
+
+/*++
+
+Routine Description:
+
+ Looks for any unexpected (plug-in) PCI-PCI bridges so
+ that interrupts can be mapped from these buses back
+ into the interrupt controller.
+
+Arguments:
+
+ NoBuses -- This is the number of buses that HalpGetPciBridgeConfig found
+
+Return Value:
+
+ none
+
+--*/
+{
+ // Carolina supports some plug-in PCI busses, but this
+ // HAL doesn't need to build the map because all Carolina PCI
+ // interrupts are routed to the same IRQ. Hence the
+ // map reduces to nothing.
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxport.c b/private/ntos/nthals/halcaro/ppc/pxport.c
new file mode 100644
index 000000000..19c0841dc
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxport.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxport.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxproc.c b/private/ntos/nthals/halcaro/ppc/pxproc.c
new file mode 100644
index 000000000..5a8ee0570
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxproc.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxproc.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxprof.c b/private/ntos/nthals/halcaro/ppc/pxprof.c
new file mode 100644
index 000000000..5e9e3dc20
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxprof.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxprof.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxreset.s b/private/ntos/nthals/halcaro/ppc/pxreset.s
new file mode 100644
index 000000000..5aca035e2
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxreset.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxreset.s>
diff --git a/private/ntos/nthals/halcaro/ppc/pxreturn.c b/private/ntos/nthals/halcaro/ppc/pxreturn.c
new file mode 100644
index 000000000..f205f2c6b
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxreturn.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxreturn.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxs3.c b/private/ntos/nthals/halcaro/ppc/pxs3.c
new file mode 100644
index 000000000..0b7211142
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxs3.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxs3.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxshadbf.s b/private/ntos/nthals/halcaro/ppc/pxshadbf.s
new file mode 100644
index 000000000..d637a3763
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxshadbf.s
@@ -0,0 +1,2 @@
+#include <..\..\halppc\ppc\pxshadbf.s>
+
diff --git a/private/ntos/nthals/halcaro/ppc/pxstall.s b/private/ntos/nthals/halcaro/ppc/pxstall.s
new file mode 100644
index 000000000..50d947500
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxstall.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxstall.s>
diff --git a/private/ntos/nthals/halcaro/ppc/pxsysbus.c b/private/ntos/nthals/halcaro/ppc/pxsysbus.c
new file mode 100644
index 000000000..fa8498016
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxsysbus.c
@@ -0,0 +1,210 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Copyright (c) 1995-96 International Business Machines Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - ported to PowerPC
+
+
+--*/
+
+#include "halp.h"
+
+#include "eisa.h"
+#include "pxmemctl.h"
+#include "pxidesup.h"
+
+extern UCHAR VectorToIrqlTable[];
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ *Affinity = 1;
+
+
+//NOTE - this should probably go in pxsiosup.c since it is specific to the SIO
+ //
+ // Set the IRQL level. Map the interrupt controllers priority scheme to
+ // NT irql values. The SIO prioritizes irq's as follows:
+ //
+ // irq0, irq1, irq8, irq9 ... irq15, irq3, irq4 ... irq7.
+ //
+
+
+ *Irql = (KIRQL) VectorToIrqlTable[BusInterruptLevel];
+
+ //
+ // Calculate vector and irql for IDE devices on delmar/carolina systems
+ //
+
+ if (BusInterruptLevel == PRIMARY_IDE_VECTOR ) {
+ *Irql = (KIRQL) (MAXIMUM_DEVICE_LEVEL - IDE_DISPATCH_VECTOR + 5);
+ return(PRIMARY_IDE_VECTOR + DEVICE_VECTORS);
+
+ } else if (BusInterruptLevel == SECONDARY_IDE_VECTOR){
+ *Irql = (KIRQL) (MAXIMUM_DEVICE_LEVEL - IDE_DISPATCH_VECTOR + 5);
+ return(SECONDARY_IDE_VECTOR + DEVICE_VECTORS);
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+}
diff --git a/private/ntos/nthals/halcaro/ppc/pxsysint.c b/private/ntos/nthals/halcaro/ppc/pxsysint.c
new file mode 100644
index 000000000..bf51c0607
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxsysint.c
@@ -0,0 +1,242 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+--*/
+
+#include "halp.h"
+#include "pxidesup.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrupt.
+ //
+
+ if (Vector == DEVICE_VECTORS + PRIMARY_IDE_VECTOR ||
+ Vector == DEVICE_VECTORS + SECONDARY_IDE_VECTOR) {
+ HalpDisableSioInterrupt(IDE_DISPATCH_VECTOR + DEVICE_VECTORS);
+ }
+ else if (Vector >= DEVICE_VECTORS &&
+ Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrupt and set the Level/Edge register.
+ //
+
+ if (Vector == DEVICE_VECTORS + PRIMARY_IDE_VECTOR ||
+ Vector == DEVICE_VECTORS + SECONDARY_IDE_VECTOR) {
+ TranslatedInterruptMode = HalpGetInterruptMode(DEVICE_VECTORS +
+ IDE_DISPATCH_VECTOR,
+ Irql, InterruptMode);
+
+
+ HalpEnableSioInterrupt( DEVICE_VECTORS + IDE_DISPATCH_VECTOR,
+ TranslatedInterruptMode);
+ }
+ else if (Vector >= DEVICE_VECTORS &&
+ Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+
+ //
+ // get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector, Irql, InterruptMode);
+
+
+ HalpEnableSioInterrupt( Vector, TranslatedInterruptMode);
+ // HalpEnableSioInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/halcaro/ppc/pxtime.c b/private/ntos/nthals/halcaro/ppc/pxtime.c
new file mode 100644
index 000000000..5fe5a500a
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxtime.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxtime.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxusage.c b/private/ntos/nthals/halcaro/ppc/pxusage.c
new file mode 100644
index 000000000..3be115176
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxusage.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxusage.c>
diff --git a/private/ntos/nthals/halcaro/ppc/pxwd.c b/private/ntos/nthals/halcaro/ppc/pxwd.c
new file mode 100644
index 000000000..bcfc1f5e9
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/pxwd.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxwd.c"
+
diff --git a/private/ntos/nthals/halcaro/ppc/x86bios.c b/private/ntos/nthals/halcaro/ppc/x86bios.c
new file mode 100644
index 000000000..ba7969c5d
--- /dev/null
+++ b/private/ntos/nthals/halcaro/ppc/x86bios.c
@@ -0,0 +1 @@
+#include "..\..\halppc\ppc\x86bios.c"
diff --git a/private/ntos/nthals/halcaro/sources b/private/ntos/nthals/halcaro/sources
new file mode 100644
index 000000000..9dfc412cd
--- /dev/null
+++ b/private/ntos/nthals/halcaro/sources
@@ -0,0 +1,105 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revision Histoy:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halcaro
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+!IF $(PPC)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-DEAGLE -DCAROLINA -DSAM_256 -D_HALNVR_ -DSOFT_HDD_LAMP
+
+INCLUDES=..\halppc\ppc;..\x86new;$(BASEDIR)\private\ntos\inc
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxfirsup.c \
+ ppc\pxmemctl.c \
+ ppc\pxpcisup.c \
+ ppc\pxdisp.c \
+ ppc\pxstall.s \
+ ppc\pxshadbf.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxenviro.c \
+ ppc\pxmapio.c \
+ ppc\pxsysint.c \
+ ppc\pxtime.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxintsup.s \
+ ppc\pxinithl.c \
+ ppc\pxport.c \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxp91.c \
+ ppc\pxwd.c \
+ ppc\pxs3.c \
+ ppc\pxbbl.c \
+ ppc\pxbl.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxsysbus.c \
+ ppc\pxidle.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\fwnvr.c \
+ ppc\pxinfo.c \
+ ppc\pxflshio.c \
+ ppc\pxpcibrd.c \
+ ppc\pxintmod.c \
+ ppc\pxidesup.c \
+ ppc\x86bios.c
+
+DLLDEF=obj\*\hal.def
+
diff --git a/private/ntos/nthals/halcbus/bushnd.c b/private/ntos/nthals/halcbus/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halcbus/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halcbus/dirs b/private/ntos/nthals/halcbus/dirs
new file mode 100644
index 000000000..89282b95a
--- /dev/null
+++ b/private/ntos/nthals/halcbus/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=eisa mca
+
+OPTIONAL_DIRS=
diff --git a/private/ntos/nthals/halcbus/drivesup.c b/private/ntos/nthals/halcbus/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halcbus/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halcbus/eisa/makefile b/private/ntos/nthals/halcbus/eisa/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halcbus/eisa/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halcbus/eisa/makefile.inc b/private/ntos/nthals/halcbus/eisa/makefile.inc
new file mode 100644
index 000000000..e2bb55a56
--- /dev/null
+++ b/private/ntos/nthals/halcbus/eisa/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: ..\..\hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) ..\..\hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halcbus/eisa/sources b/private/ntos/nthals/halcbus/eisa/sources
new file mode 100644
index 000000000..a79192498
--- /dev/null
+++ b/private/ntos/nthals/halcbus/eisa/sources
@@ -0,0 +1,112 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halcbus
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\..\inc;..\..\..\ke;..\..\;..;..\..\halx86\i386
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ..\i386\ixbeep.asm \
+ ..\i386\ixbusdat.c \
+ ..\i386\ixdat.c \
+ ..\i386\ixinfo.c \
+ ..\i386\ixisabus.c \
+ ..\i386\ixpcibus.c \
+ ..\i386\ixpciint.c \
+ ..\i386\ixpcibrd.c \
+ ..\i386\ixcmos.asm \
+ ..\i386\ixenvirv.c \
+ ..\i386\ixfirm.c \
+ ..\i386\ixhwsup.c \
+ ..\i386\ixidle.asm \
+ ..\i386\ixisasup.c \
+ ..\i386\ixkdcom.c \
+ ..\i386\ixphwsup.c \
+ ..\i386\ixprofil.asm \
+ ..\i386\ixreboot.c \
+ ..\i386\ixthunk.c \
+ ..\i386\ixusage.c \
+ ..\i386\xxbiosa.asm \
+ ..\i386\xxbiosc.c \
+ ..\i386\xxdisp.c \
+ ..\i386\xxkdsup.c \
+ ..\i386\xxmemory.c \
+ ..\i386\xxstubs.c \
+ ..\i386\xxtime.c \
+ ..\i386\cbapic.c \
+ ..\i386\cbioacc.asm \
+ ..\i386\cb1stall.asm \
+ ..\i386\cb2stall.asm \
+ ..\i386\cbswint.asm \
+ ..\i386\cbsysint.asm \
+ ..\i386\cbmapint.c \
+ ..\i386\cbdriver.c \
+ ..\i386\cbusnmi.c \
+ ..\i386\cbusboot.asm \
+ ..\i386\cbuslock.asm \
+ ..\i386\cbusprof.asm \
+ ..\i386\cbusmisc.asm \
+ ..\i386\cbus2cbc.asm \
+ ..\i386\cbusapic.asm \
+ ..\i386\cbus2.c \
+ ..\i386\cbus1.c \
+ ..\i386\cbus1bt.asm \
+ ..\i386\cbus2ecc.c \
+ ..\i386\cbus.c \
+ ..\i386\cbus_sw.c \
+ ..\i386\cbusmem.c \
+ ..\i386\cbushal.c \
+ ..\i386\cbusproc.c
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halcbus.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halcbus/hal.rc b/private/ntos/nthals/halcbus/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halcbus/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halcbus/i386/cb1stall.asm b/private/ntos/nthals/halcbus/i386/cb1stall.asm
new file mode 100644
index 000000000..719627aef
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cb1stall.asm
@@ -0,0 +1,932 @@
+ title "Initialize Stall Execution for the Corollary MP machines"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+;Module Name:
+;
+; cb1stall.asm
+;
+;Abstract:
+;
+; This module contains various stall initialization, clock and performance
+; counter routines.
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 05-Oct-1992
+;
+;Revision History:
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include i386\kimacro.inc
+include callconv.inc ; calling convention macros
+include cbus.inc
+include mac386.inc
+include i386\ix8259.inc
+
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+
+ .list
+
+;
+; the CLKIN pin of the 82489DX is clocking at 32MHz (32000000) on the bridge,
+; and 33-1/3 (333333333) MHz on the additional processor cards.
+;
+; divide this by 1,000,000 to get clocking in a microsecond --> ~33.
+; 33 * 16 microseconds == 528 == 0x210
+;
+
+CLKIN_ONE_SECOND EQU 32000000 ; in APIC CLKIN units
+; CLKIN_ONE_SECOND EQU 33333333 ; in APIC CLKIN units
+CLKIN_SIXTEEN_MS EQU 210h ; 16 microseconds (CLKIN)
+CLKIN_SIXTEEN_MS_SHIFT EQU 4 ; shift 16 microseconds to 1ms
+CLKIN_ENABLE_ONESHOT EQU 0h ; enable one-shot CLKIN interrupt
+CLKIN_ENABLE_PERIODIC EQU 20000h ; enable periodic CLKIN interrupts
+CLKIN_DISABLE EQU 10000h ; mask off CLKIN interrupts
+
+APIC_TIMER_MILLISECOND EQU 32000 ; timer units to == 1 millisecond
+APIC_TIMER_MICROSECOND EQU 33 ; timer units to == 1 microsecond
+
+TIMER_VECTOR_ENTRY EQU 320h ; timer vector table entry 0 address
+INITIAL_COUNT_REG EQU 380h ; poke here to set the initial count
+CURRENT_COUNT_REG EQU 390h ; current counter countdown is here
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 int gate
+
+CBUS1_PERF_TASKPRI EQU 0DDh ; vector generated by 8254 timer
+
+;
+; The default interval between clock interrupts is
+; 10 milliseconds == 10000 microseconds == 100000 (in 100 ns units).
+; Remember the NT executive expects this value to be in
+; 100 nanosecond units (not microseconds), so multiply
+; accordingly when referencing KeTimeIncrement.
+;
+; the maxclock rates below are not the slowest that the hardware can support -
+; they are the slowest we want NT to restore it whenever it is rolled back.
+;
+MAXCLOCK_RATE_IN_MS EQU 10 ; specify in milliseconds
+
+;
+; We will support clock interrupt generation with a minimum of 300
+; nanosecond separations to as much as 10 milliseconds apart.
+;
+MINCLOCK_DELTA_IN_100NS EQU 3 ; specify in 100-nanosecond units
+MAXCLOCK_DELTA_IN_100NS EQU 100000 ; specify in 100-nanosecond units
+
+;
+; "Convert" the interval to rollover count for 8254 Timer1 device.
+; timer1 counts down a 16 bit value at a rate of 1.193M counts-per-sec.
+; So that's what we'll use to get the finest granularity. Note that
+; this is solely for the performance counter and has NOTHING to do
+; with the system clock, which is driven directly from the APIC.
+; We'd like for the interrupt rate to be even lower (ie: once per
+; second rather than approximately 17 times per second, but the 8254
+; only gives us two bytes to feed in the interrupt counter.
+;
+
+ROLLOVER_COUNT EQU 0ffffH ; must fit in the 8254's two bytes
+PERFORMANCE_FREQUENCY EQU 1193000
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+;
+; default clock rate is 10 milliseconds
+;
+CbusClockRateInMillis dd 10 ; in milliseconds
+
+Cbus1PerfCounterInit dd 0
+Cbus1PerfCounterLow dd 0
+Cbus1PerfCounterHigh dd 0
+Cbus1LastReadPerfLow dd 0
+Cbus1LastReadPerfHigh dd 0
+Cbus18254Late dd 0
+Cbus1CurrentTimeIncrement dd 0
+
+if DBG
+Cbus18254LateCount dd 0
+Cbus1Queries dd 0
+endif
+
+_DATA ends
+
+
+INIT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; Cbus1InitializeStall (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initializes the per Microsecond counter for
+; KeStallExecutionProcessor.
+;
+; All Corollary processors have their own local APIC and
+; their own local timers. each processor independently
+; calibrates himself here, thus supporting processors of
+; varying speeds.
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _Cbus1InitializeStall ,1
+cPublicFpo 1,2
+
+ push ebp ; save ebp
+ mov ebp, esp
+ sub esp, 8 ; save room for idtr
+
+ pushfd ; save caller's eflag
+
+ cli ; disable interrupts
+
+ ;
+ ; save the current CbusClockVector IDT entry, as we are
+ ; going to temporarily repoint it at a private handler.
+ ;
+
+ sidt fword ptr [ebp-8] ; get IDTR (base & limit)
+ mov ecx, [ebp-6] ; get IDTR base value
+
+ mov eax, [_CbusClockVector]
+
+ shl eax, 3 ; 8 bytes per IDT entry
+ add ecx, eax ; now at the correct IDT RTC entry
+
+ push dword ptr [ecx] ; (TOS) = original desc of IRQ 8
+ push dword ptr [ecx + 4] ; each descriptor has 8 bytes
+ push ecx ; (TOS) -> &IDT[CbusClockVector]
+
+ mov eax, offset FLAT:TimerExpired
+
+ mov word ptr [ecx], ax ; Lower half of handler addr
+ mov word ptr [ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [ecx+4], D_INT032 ; 386 interrupt gate
+
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [ecx+6], ax
+
+ mov eax, [_CbusClockVector] ; we expect this vector to...
+ or eax, CLKIN_ENABLE_ONESHOT ; use one-shot CLKIN to interrupt us
+
+ ; get the base of APIC space, so we can then access
+ ; the addr of hardware interrupt command register below
+
+ mov ecx, [_CbusLocalApic]
+
+ ; the count register appears to decrement approx 0x30 per
+ ; asm instruction on a 486/33, just fyi. so load it up with
+ ; a "real high value" so we don't get an interrupt whilst setting
+ ; up the local time vector entry, etc, and then at the last
+ ; possible moment, fill it in with the desired starting value.
+
+ mov dword ptr INITIAL_COUNT_REG[ecx], CLKIN_ONE_SECOND
+
+ ; initialize the local timer vector table entry with
+ ; appropriate Vector, Timer Base, Timer Mode and Mask.
+
+ mov TIMER_VECTOR_ENTRY[ecx], eax
+
+ ; poke initial count reg to interrupt us in 16 microseconds
+
+ mov dword ptr INITIAL_COUNT_REG[ecx], CLKIN_SIXTEEN_MS
+
+ xor eax, eax ; initialize our register counter
+ALIGN 16
+ sti ; enable the interrupt
+ jmp kise10
+
+ALIGN 16
+kise10:
+ sub eax, 1 ; increment the loopcount
+ jnz short kise10
+
+if DBG
+ stdCall _DbgBreakPoint ; Counter overflowed!
+endif
+ jmp short kise10
+
+TimerExpired:
+
+ ; take the timer expiration interrupt here
+
+if DBG
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint ; Counter was never bumped!
+ ; never return
+kise30:
+endif
+
+ neg eax
+ shr eax, CLKIN_SIXTEEN_MS_SHIFT ; convert to microseconds
+
+ mov dword ptr PCR[PcStallScaleFactor], eax
+
+ mov eax, [_CbusLocalApic]
+
+ ; mask off local timer vector table entry now that we're done with it.
+
+ mov dword ptr TIMER_VECTOR_ENTRY[eax], CLKIN_DISABLE
+
+ ;
+ ; Dismiss the interrupt AFTER disabling the timer entry so
+ ; we don't get an extra interrupt later that was already pending.
+ ;
+
+ mov eax, _CbusClockVector ; mark interrupting vector
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ add esp, 12 ; unload flags, cs, ip
+
+ pop ecx ; (ecx) -> &IDT[CbusClockVector]
+ pop [ecx+4] ; restore higher half of RTC desc
+ pop [ecx] ; restore lower half of RTC desc
+
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+
+ stdRET _Cbus1InitializeStall
+
+stdENDP _Cbus1InitializeStall
+
+ page ,132
+ subttl "Cbus1 Initialize Performance Counter"
+;++
+;
+; VOID
+; Cbus1InitializePerf (
+; )
+;
+; Routine Description:
+;
+; Initialize the 8254 to interrupt the minimum number of times
+; per second on the boot processor only to support the performance counter.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _Cbus1InitializePerf ,0
+
+ ;
+ ; Since ke\i386\allproc.c no longer boots all the available
+ ; processors in the machine, the first processor to boot must
+ ; initialize the 8254 and take the extra 8254 ticks.
+ ;
+
+ mov eax, PCR[PcHal.PcrNumber]
+ cmp eax, 0
+ jne short @f
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+ ;
+ ; Initialize the APIC so that 8254 interrupts go only to the boot
+ ; processor - there is no need for all of them to get this interrupt
+ ; when all it is doing is updating a global counter.
+ ;
+
+ ; stdCall _HalEnableSystemInterrupt,<CBUS1_PERF_TASKPRI,CLOCK2_LEVEL,0>
+ ; no need to enable - it's done by our caller
+
+ ;
+ ; Set clock rate at the 8254
+ ;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov ecx, ROLLOVER_COUNT
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+
+ mov Cbus1PerfCounterInit, 1
+
+ align 4
+@@:
+
+ stdRET _Cbus1InitializePerf
+
+stdENDP _Cbus1InitializePerf
+
+ INIT ends
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Cbus1 Initialize Clock"
+;++
+;
+; VOID
+; Cbus1InitializeClock (
+; )
+;
+; Routine Description:
+;
+; Initializes the clock and the kernel variable for the amount of
+; time between timer ticks. The kernel needs this information by the end
+; of phase 0.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _Cbus1InitializeClock,0
+
+ ;
+ ; Fill in value with the time between clock ticks,
+ ; remember the NT executive expects this value to be in
+ ; 100 nanosecond units, not microseconds, so multiply accordingly.
+ ;
+
+ mov eax, CbusClockRateInMillis ; current rate in milliseconds
+
+ mov ecx, 10000 ; converting back to 100 ns
+ mul ecx ; eax == 100ns unit value
+
+ ;
+ ; The Cbus1CurrentTimeIncrement value is used by the clock
+ ; interrupt routine to pass to the kernel, so set it now.
+ ;
+ mov Cbus1CurrentTimeIncrement, eax
+
+ stdCall _Cbus1ProgramClock
+
+ stdCall _KeSetTimeIncrement, <MAXCLOCK_DELTA_IN_100NS, MINCLOCK_DELTA_IN_100NS>
+
+ stdRET _Cbus1InitializeClock
+
+stdENDP _Cbus1InitializeClock
+
+;++
+;
+; VOID
+; Cbus1ProgramClock (
+; )
+;
+; Routine Description:
+;
+; This routine initializes the system time clock for each calling
+; processor to generate periodic interrupts at the specified rate using
+; this processor's local APIC timer. Thus, each processor must call
+; this routine to set or change his clock rate. During startup, each
+; processor will call this routine to set his own clock rate. Later,
+; when the system is running, the HalSetTimerResolution API is only
+; supposed to change the clock rate for the boot processor - this is
+; for multimedia apps that want timeouts serviced at a better than
+; 5 millisecond granularity.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _Cbus1ProgramClock ,0
+
+ mov ecx, CbusClockRateInMillis ; new rate in milliseconds
+
+ mov eax, APIC_TIMER_MILLISECOND ; counter per microsecond
+
+ mul ecx ; eax == new APIC countdown val
+
+ mov edx, [_CbusClockVector] ; we expect this vector to...
+ or edx, CLKIN_ENABLE_PERIODIC ; use CLKIN to interrupt us
+
+ mov ecx, [_CbusLocalApic]
+
+ pushfd
+ cli
+
+ ; as a frame of reference, the count register decrements
+ ; approximately 0x30 per asm instruction on a 486/33.
+
+ ; initialize the local timer vector table entry with
+ ; appropriate Vector, Timer Base, Timer Mode and Mask.
+
+ mov TIMER_VECTOR_ENTRY[ecx], edx
+
+ ; poke initial count reg to start the periodic clock timer interrupts.
+ ; the IDT entry is valid & enabled on entry to this routine.
+
+ mov dword ptr INITIAL_COUNT_REG[ecx], eax
+
+ mov eax, CbusClockRateInMillis ; new rate in milliseconds
+ mov ecx, 10000 ; converting back to 100 ns
+ xor edx, edx
+ mul ecx ; eax == 100ns unit value
+
+ ;
+ ; store it here so the clock ISR can tell it to the kernel
+ ;
+ mov Cbus1CurrentTimeIncrement, eax
+
+ popfd
+ stdRET _Cbus1ProgramClock
+
+stdENDP _Cbus1ProgramClock
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; Cbus1QueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns the current 64-bit performance counter.
+; The Performance Frequency is also returned if asked for.
+;
+; Also note that the performance counter returned by this routine
+; is not necessarily the value exactly when this routine was entered.
+; The value returned is actually the counter value at any point
+; between the routine's entrance and exit times.
+;
+; This routine is not susceptible to the 2 problems that plague most
+; multiprocessor HALs. Their problems are as follows:
+;
+; a) If the boot processor (or whoever updates the global performance
+; counters) misses an interrupt, the counter rolls over undetected,
+; and the performance counter returned can actually roll backwards!
+;
+; b) If you are on an additional processor and for some reason,
+; the boot processor is holding off a pending clock interrupt for
+; the entire time the additional processor is executing in
+; KeQueryPerfomanceCounter. The boot processor hasn't necessarily
+; lost a clock interrupt, it's just that he hasn't dropped IRQL
+; enough to get it yet, and there isn't any good way for the
+; additional processor to force him to. Since the boot processor
+; is the only one maintaining the PerfCounter[High,Low], this can
+; result in processors returning potentially non-uniform snapshots,
+; which can even roll backwards!
+;
+; Both of these problems have been solved in the Corollary HAL by
+; using separate clocks for the system timer and the performance counter.
+; Ie: the APIC timer is used for the system timer and interrupts each
+; processor every 15 milliseconds. The 8254 interrupts ONLY the boot
+; processor once every second. Thus, case a) above cannot happen
+; unless the boot processor disables interrupts for more than one second.
+; If this happens, the entire system will be badly broken. case b)
+; is also bypassed by using a global lock in the performance counter
+; interrupt handler. Since the interrupt only occurs once per second
+; and only on one processor, the global lock will not hinder performance.
+; This allows us to take globally synchronized performance counter
+; snapshots and also detect in software if case b) is happening, and
+; handle it in software. Because the 8254 timer register is only 16 bits
+; wide, the actual 8254 synchronization interrupt will occur approximately
+; seventeen times per second instead of once. This is still at least 4
+; times better than the system timer (approximately 70 times per second).
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+4] ; User supplied Performance Frequency
+
+cPublicProc _Cbus1QueryPerformanceCounter ,1
+
+ ;
+ ; First check to see if the performance counter has been
+ ; initialized yet. Since the kernel debugger calls
+ ; KeQueryPerformanceCounter to support the !timer command
+ ; _VERY_ early on, we need to return something reasonable
+ ; even though timer initialization hasn't occured yet.
+ ;
+ cmp Cbus1PerfCounterInit, 0
+ jne short @f ; ok, perf counter has been initialized
+
+ ;
+ ; Initialization hasn't occured yet, so just return zeros.
+ ;
+ mov eax, 0
+ mov edx, 0
+ jmp retfreq ; retfreq too far away for short jmp
+
+ align 4
+@@:
+if DBG
+ inc dword ptr [Cbus1Queries]
+endif
+ push ebx
+ push esi
+ ;
+ ; all interrupts must be disabled prior to lock acquisition to
+ ; prevent deadlock.
+ ;
+ pushfd
+ cli
+
+ lea esi, _Halp8254Lock
+
+ align 4
+Kqpc00:
+ ACQUIRE_SPINLOCK esi, Kqpc01
+
+ ;
+ ; get the global timer counters which are incremented
+ ; one processor only.
+ ;
+
+ mov esi, Cbus1PerfCounterLow
+ mov ebx, Cbus1PerfCounterHigh ; [ebx:esi] = Performance counter
+
+ ;
+ ; Fetch the current counter value from the hardware
+ ;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ neg ecx ; PIT counts down to 0h
+ add ecx, ROLLOVER_COUNT
+ add esi, ecx
+ adc ebx, 0 ; [ebx:esi] = Final result
+
+ ;
+ ; Check whether case b) could be happening right now - this is
+ ; possible no matter which processor is currently calling us.
+ ;
+
+ cmp ebx, dword ptr [Cbus1LastReadPerfHigh]
+ jl short caseb
+
+ cmp esi, dword ptr [Cbus1LastReadPerfLow]
+ jl short caseb
+
+ jmp short notpending
+
+ align 4
+caseb:
+ ;
+ ; Detected case b) happening RIGHT NOW!
+ ; Update the Cbus1 performance counter NOW, and
+ ; set a flag so the interrupt handler will NOT.
+ ; This case actually happens fairly frequently,
+ ; ie: at least every few seconds on an idle
+ ; uniprocessor, so this code is quite useful.
+ ;
+
+ add Cbus1PerfCounterLow, ROLLOVER_COUNT ; update performance counter
+ adc Cbus1PerfCounterHigh, 0
+ inc dword ptr [Cbus18254Late]
+
+if DBG
+ inc dword ptr [Cbus18254LateCount]
+endif
+
+ align 4
+notpending:
+ ;
+ ; save last performance counter read so future callers can compare
+ ;
+
+ mov Cbus1LastReadPerfLow, esi
+ mov Cbus1LastReadPerfHigh, ebx
+
+ mov edx, ebx ; save return value
+ mov eax, esi ; save return value
+
+ lea esi, _Halp8254Lock
+ RELEASE_SPINLOCK esi
+
+ popfd
+ pop esi
+ pop ebx
+
+ ;
+ ; if asked to, return the frequency in units/second
+ ;
+
+ align 4
+retfreq:
+
+ or dword ptr KqpcFrequency, 0 ; is it NULL?
+ jz short @f ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; frequency pointer
+ mov dword ptr [ecx], PERFORMANCE_FREQUENCY ; set frequency
+ mov dword ptr [ecx+4], 0 ; currently < 4Gig!
+
+ align 4
+@@:
+ stdRET _Cbus1QueryPerformanceCounter
+
+ align 4
+Kqpc01:
+ SPIN_ON_SPINLOCK esi,<Kqpc00>
+
+stdENDP _Cbus1QueryPerformanceCounter
+
+ page ,132
+ subttl "Cbus1 Perf Interrupt"
+;++
+;
+; VOID
+; Cbus1PerfInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for the Cbus1 performance
+; counter interrupt at a priority just below that of normal clocks.
+; Its function is to update the global performance counter so that
+; KeQueryPerformanceCounter can return meaningful values.
+;
+; This routine is executed only by one processor at a rate of seventeen
+; times per second, as there is no need for all processors to update
+; the same global counter. The only reason the rate is so high is
+; because the interrupt interval must fit into a 16 bit register in the
+; 8254. Otherwise, it would have been more like once per second.
+;
+; Since this routine is entered directly via an interrupt gate, interrupt
+; protection via cli is not necessary.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hipi_a, hipi_t
+
+cPublicProc _Cbus1PerfInterrupt ,0
+
+ ;
+ ; Save machine state on trap frame
+ ;
+
+ ENTER_INTERRUPT hipi_a, hipi_t
+
+ ; keep it simple, just issue the EOI right now.
+ ; no changing of taskpri/irql is needed here.
+ ; Thus, the EOI serves as the HalEndSystemInterrupt.
+
+ mov eax, CBUS1_PERF_TASKPRI ; mark interrupting vector
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ ;
+ ; (esp) - base of trap frame
+ ;
+
+ifdef MCA
+
+ ;
+ ; Special hack for MCA machines
+ ;
+
+ in al, 61h
+ jmp $+2
+ or al, 80h
+ out 61h, al
+ jmp $+2
+
+endif ; MCA
+
+ lea esi, _Halp8254Lock
+
+ align 4
+Kcpi00:
+ ACQUIRE_SPINLOCK esi, Kcpi01
+
+ ;
+ ; Update Cbus1 performance counter if a performance counter query
+ ; hasn't done so already.
+ ;
+
+ cmp dword ptr [Cbus18254Late], 0
+ jne short @f
+
+ add Cbus1PerfCounterLow, ROLLOVER_COUNT ; update performance counter
+ adc Cbus1PerfCounterHigh, 0
+ jmp short noroll
+
+ align 4
+@@:
+ dec dword ptr [Cbus18254Late]
+
+ align 4
+noroll:
+ RELEASE_SPINLOCK esi
+
+ ;
+ ; Call this directly instead of through INTERRUPT_EXIT
+ ; because the HalEndSystemInterrupt has already been done,
+ ; and must only be done ONCE per interrupt.
+ ;
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+ align 4
+Kcpi01:
+ SPIN_ON_SPINLOCK esi,<Kcpi00>
+
+stdENDP _Cbus1PerfInterrupt
+
+;++
+;
+; ULONG
+; Cbus1SetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initializes the system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick in
+; 100ns units.
+;
+; Return Value:
+;
+; The *REAL* time increment set - this can be different from what he
+; requested due to hardware limitations - currently to keep the math
+; simple, we limit the interval to between 1 and 32000 milliseconds,
+; on millisecond boundaries (ie 1.3 milliseconds is rounded to 1
+; millisecond).
+;--
+
+cPublicProc _Cbus1SetTimeIncrement,1
+
+ mov eax, [esp+4] ; caller's desired setting
+ xor edx, edx
+ mov ecx, 10000
+ div ecx ; round to milliseconds
+
+ cmp eax, MAXCLOCK_RATE_IN_MS ; desired > max?
+ jc short @f
+ mov eax, MAXCLOCK_RATE_IN_MS ; yes, use max
+@@:
+
+ or eax, eax ; MS < min?
+ jnz short @f
+ inc eax ; yes, use min
+@@:
+
+ mov CbusClockRateInMillis, eax ; set new rate in milliseconds
+
+ ;
+ ; inform this processor's local APIC hardware of the change.
+ ; and then tell all the other processors to update theirs too...
+ ;
+ stdCall _Cbus1ProgramClock
+
+ mov eax, Cbus1CurrentTimeIncrement
+
+ stdRET _Cbus1SetTimeIncrement
+
+stdENDP _Cbus1SetTimeIncrement
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by CLOCK.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread and process.
+;
+; Note spurious interrupts are always sent to the spurious interrupt IDT
+; entry, and hence, no need to check for one here.
+;
+; See also Cbus1ClockInterruptPx() - it's used by the non-boot processors,
+; since additional processors don't need to bump any global counters.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; must set up eax with the increment value, also leave ebp pointing at
+; base of trap frame.
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hck_a, Hck_t
+
+cPublicProc _Cbus1ClockInterrupt ,0
+
+ ;
+ ; Save machine state in trap frame
+ ; (esp) - base of trap frame
+ ;
+
+ ENTER_INTERRUPT Hck_a, Hck_t
+
+ ;
+ ; Dismiss interrupt and raise irq level to clock2 level
+ ;
+
+ push _CbusClockVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL, _CbusClockVector, esp>
+
+ POKE_LEDS eax, edx
+
+ ;
+ ; (esp) = OldIrql
+ ; (esp+4) = Vector
+ ; (esp+8) = base of trap frame
+ ; (ebp) = address of trap frame
+ ; (eax) = time increment
+ ;
+ mov eax, Cbus1CurrentTimeIncrement
+
+ jmp _KeUpdateSystemTime@0
+
+stdENDP _Cbus1ClockInterrupt
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cb2stall.asm b/private/ntos/nthals/halcbus/i386/cb2stall.asm
new file mode 100644
index 000000000..7be774f4f
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cb2stall.asm
@@ -0,0 +1,1347 @@
+
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; cb2stall.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are declared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Landy Wang (corollary!landy) 04-Dec-92
+; Move much code into separate modules for easy inclusion by various
+; HAL builds.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ixcmos.inc
+include cbus.inc
+ .list
+
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+if DBG
+ EXTRNP _HalDisplayString,1
+endif
+ifdef CBC_REV1
+ EXTRNP _Cbus2RequestSoftwareInterrupt,1
+endif
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER2_DATA_PORT0 EQU 48H ; Timer1, channel 0 data port
+TIMER2_CONTROL_PORT0 EQU 4BH ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_MODE3 EQU 6 ; Use mode 3
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 10000000
+
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+;
+; RegisterAInitByte sets 8Hz clock rate, used during init to set up
+; KeStallExecutionProcessor, etc. (See RegASystemClockByte below.)
+;
+
+RegisterAInitByte EQU 00101101B ; RT/CMOS Register 'A' init byte
+ ; 32.768KHz Base divider rate
+
+ ; 8Hz int rate, period = 125.0ms
+PeriodInMicroSecond EQU 125000 ;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+D_INT032 EQU 8E00h ; access word for 386 ring 0 int gate
+
+;
+; ==== Values used for System Clock ====
+;
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+ public HalpPerfCounterLow, HalpPerfCounterHigh
+if DBG
+ public CbusClockCount
+ public CbusClockLate
+ public _CbusCatchClock
+endif
+Cbus2PerfInit dd 0
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+if DBG
+CbusClockCount dd 0
+CbusClockLate dd 0
+_CbusCatchClock dd 0
+endif
+
+ public Cbus2NumberSpuriousClocks
+Cbus2NumberSpuriousClocks dd 0
+
+ public HalpCurrentRollOver, HalpCurrentTimeIncrement
+HalpCurrentRollOver dd 0
+HalpCurrentTimeIncrement dd 0
+
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec.
+;
+; The best fit value closest to 10ms is 10.0144012689ms:
+; ROLLOVER_COUNT 11949
+; TIME_INCREMENT 100144
+; Calculated error is -.0109472 s/day
+;
+;
+; The following table contains 8254 values timer values to use at
+; any given ms setting from 1ms - 15ms. All values work out to the
+; same error per day (-.0109472 s/day).
+;
+
+ public HalpRollOverTable
+
+ ; RollOver Time
+ ; Count Increment MS
+HalpRollOverTable dd 1197, 10032 ; 1 ms
+ dd 2394, 20064 ; 2 ms
+ dd 3591, 30096 ; 3 ms
+ dd 4767, 39952 ; 4 ms
+ dd 5964, 49984 ; 5 ms
+ dd 7161, 60016 ; 6 ms
+ dd 8358, 70048 ; 7 ms
+ dd 9555, 80080 ; 8 ms
+ dd 10731, 89936 ; 9 ms
+ dd 11949, 100144 ; 10 ms
+ dd 13125, 110000 ; 11 ms
+ dd 14322, 120032 ; 12 ms
+ dd 15519, 130064 ; 13 ms
+ dd 16695, 139920 ; 14 ms
+ dd 17892, 149952 ; 15 ms
+
+TimeIncr equ 4
+RollOver equ 0
+
+ public HalpLargestClockMS, HalpNextMSRate, HalpPendingMSRate
+HalpLargestClockMS dd 10 ; Table goes to 15MS, but since we
+ ; use only 486 & above, limit to 10ms.
+HalpNextMSRate dd 0
+HalpPendingMSRate dd 0
+
+;
+; This value is used by CPUx (x>0) during the clock interrupt
+; routine to re-trigger the call to KeUpdateRunTime. Processors
+; calling KeUpdateRunTime call at the maximum supported rate as
+; reported by KeSetTimeIncrement.
+; (HAL Development Reference Guide 5.12)
+;
+ public HalpMaxTimeIncrement
+HalpMaxTimeIncrement dd 0
+
+;
+; Holds the next time increment. HalpCurrentTimeIncrement is
+; initialized with this value just before calling KeUpdateSystemTime.
+;
+ public HalpNewTimeIncrement
+HalpNewTimeIncrement dd 0
+
+if DBG
+;
+; Cbus2MaxTimeStamp... max value of time stamp ever.
+; Cbus2MinTimeStamp... min value of time stamp ever.
+; Cbus2CountOverflowTimeStamp...# of overflows of time stamp.
+; Cbus2SumTimeStampHi... Sum of all time stamps.
+; Cbus2SumTimeStampLow...
+; Cbus2CountClockInt... # of clock interrupts.
+;
+ public Cbus2MaxTimeStamp, Cbus2MinTimeStamp,
+ Cbus2CountOverflowTimeStamp, Cbus2SumTimeStampHi,
+ Cbus2SumTimeStampLow, Cbus2CountClockInt
+
+Cbus2MaxTimeStamp dd 0
+Cbus2MinTimeStamp dd -1
+Cbus2CountOverflowTimeStamp dd 0
+Cbus2SumTimeStampHi dd 0
+Cbus2SumTimeStampLow dd 0
+Cbus2CountClockInt dd 0
+endif
+
+_DATA ends
+
+
+INIT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+if DBG
+RTC_toofast db 'RTC IRQ8 HARDWARE ERROR\n', 0
+endif
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; Cbus2InitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0.
+;
+; See the definitions of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; All processors call this routine, but only the first call needs
+; to do anything.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _Cbus2InitializeClock ,0
+ cmp dword ptr PCR[PcHal.PcrNumber], 0
+
+ jz @f
+
+ ;
+ ; Initialize the 'TickOffset' field for CPUx (x>0).
+ ; It indicates the number of nsec left before calling the
+ ; KeUpdateRunTime routine. This routine is called at the
+ ; maximum supported rate as reported by KeSetTimeIncrement.
+ ;
+ mov eax, HalpMaxTimeIncrement
+ mov PCR[PcHal.PcrTickOffset], eax
+
+ stdRET _Cbus2InitializeClock
+
+@@:
+ mov eax, HalpLargestClockMS
+ mov ecx, HalpRollOverTable.TimeIncr
+ mov edx, HalpRollOverTable[eax*8-8].TimeIncr
+ mov eax, HalpRollOverTable[eax*8-8].RollOver
+
+ mov HalpCurrentTimeIncrement, edx
+
+;
+; (ecx) = Min time_incr
+; (edx) = Max time_incr
+; (eax) = max roll over count
+;
+
+ ;
+ ; This value is used by CPUx (x>0) during the clock interrupt
+ ; routine to re-trigger the call to KeUpdateRunTime. Processors
+ ; calling KeUpdateRunTime call at the maximum supported rate as
+ ; reported by KeSetTimeIncrement.
+ ; (HAL Development Reference Guide 5.12)
+ ;
+ mov HalpMaxTimeIncrement, edx
+
+ push eax
+ stdCall _KeSetTimeIncrement, <edx, ecx>
+ pop ecx
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+; (ecx) = RollOverCount
+;
+
+ ;
+ ; use a 50% duty cycle for the system clock
+ ;
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE3
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+ mov HalpCurrentRollOver, ecx ; Set RollOverCount & initialized
+
+ ;
+ ; Set up the performance counter mechanism as well:
+ ; Zero the global system timer for all of the processors.
+ ;
+ mov eax, dword ptr [_CbusTimeStamp]
+ mov dword ptr [eax], 0
+ mov Cbus2PerfInit, 1 ; calibration done
+
+ stdRET _Cbus2InitializeClock
+
+stdENDP _Cbus2InitializeClock
+
+INIT ends
+
+_TEXT$03 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by CLOCK.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread and process.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _Cbus2ClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; Note that during this phase the interrupts are already disabled.
+; This is important because we don't want to take an IPI during this phase
+; which may force us to discard the next clock interrupt.
+; The call to HalBeginSystemInterrupt below will enable the interrupts.
+;
+
+ifdef MCA
+;
+; Special hack for MCA machines
+;
+
+ in al, 61h
+ jmp $+2
+ or al, 80h
+ out 61h, al
+ jmp $+2
+
+endif ; MCA
+
+ cmp [_Cbus2CheckSpuriousClock], 1 ; Check for spurious clock?
+ je Hci200
+Hci05:
+
+ifdef CBC_REV1
+ ;
+ ; because we can miss an interrupt due to a hardware bug in the
+ ; CBC rev 1 silicon, send ourselves an IPI on every clock.
+ ; since we don't know when we've missed one, this will ensure
+ ; we don't cause lock timeouts if nothing else!
+ ;
+
+ stdCall _Cbus2RequestSoftwareInterrupt, <IPI_LEVEL>
+endif
+
+;
+; Dismiss interrupt and raise irq level to clock2 level
+;
+
+Hci10:
+ push _CbusClockVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL, _CbusClockVector, esp>
+ POKE_LEDS eax, edx
+
+if DBG
+ inc dword ptr [CbusClockCount]
+endif
+ ;
+ ; Update our software 64-bit performance counter and zero the
+ ; 32-bit high resolution CBC timestamp counter. we'd like to
+ ; read off the real amount of elapsed time, ie:
+ ;
+ ; mov eax, dword ptr [ecx]
+ ; add HalpPerfCounterLow, eax
+ ;
+ ; but we can't because when the debugger is enabled, NT holds off
+ ; interrupts for long periods of time, ie: like in DbgLoadImageSymbols()
+ ; for over 700 _milliseconds_ !!!. so just fib like all the other
+ ; HALs do, and tell NT only 10ms have gone by.
+ ;
+if DBG
+ ;
+ ; we had a problem where clock interrupts are getting
+ ; held off for approximately 700 ms once per second! here is
+ ; the debug code which caught DbgLoadImageSymbols.
+ ;
+ ;mov ecx, dword ptr [_CbusTimeStamp]
+ ;mov eax, dword ptr [ecx]
+
+ ;cmp _CbusCatchClock, 0 ; debug breakpoint desired?
+ ;je short @f
+
+ ;cmp eax, 2000000 ; if more than 200 milliseconds since
+ ; the last clockintr, then trigger
+ ; the analyzer and go into debug
+ ;jb short @f
+ ;inc dword ptr [CbusClockLate] ; trigger analyzer
+ ;int 3
+@@:
+endif
+
+ mov eax, HalpCurrentTimeIncrement ; current time increment
+ mov HalpNewTimeIncrement, eax ; next time increment
+
+Hci30:
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; ebp = trap frame
+; eax = current time increment
+;
+
+ cmp HalpNextMSRate, 0 ; New clock rate desired?
+ jnz short Hci60 ; Yes, program timer h/w.
+
+Hci40:
+
+ mov ebx, HalpNewTimeIncrement
+
+;
+; Update performance counters.
+; Do not change without reason the order of the following instractions.
+; They are crafted in this way for the HalQueryPerformanceCounter
+; routine (it can run at the same time on a different processor).
+; The interrupts are disabled because we don't want to take an IPI
+; during this process.
+;
+
+;
+; eax = current time increment
+; ebx = next time increment
+;
+
+ mov ecx, dword ptr [_CbusTimeStamp]
+ cmp [_Cbus2CheckSpuriousClock], 1 ; Calculate new SystemTimer.
+ pushfd ; Save and disable flags.
+ cli
+ je Hci210
+ sub edx, edx
+Hci50:
+
+;
+; Awkward ordering done to place the resetting of the SystemTimer
+; as close to the update of the 64-bit performance counter --
+;
+
+ mov dword ptr [ecx], edx ; New TimeStamp value.
+ add HalpPerfCounterLow, eax
+ adc HalpPerfCounterHigh, dword ptr 0
+ mov HalpCurrentTimeIncrement, ebx ; Next time increment.
+
+ popfd ; Restore flags.
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; ebp = trap frame
+; eax = time increment
+;
+
+ jmp _KeUpdateSystemTime@0 ; dispatch this tick
+
+Hci60:
+;
+; Time of clock frequency is being changed. See if the 8254 was
+; was reprogrammed for a new rate during last tick
+;
+; (eax) = time increment for current tick
+
+ cmp HalpPendingMSRate, 0 ; Was a new rate set durning last
+ jnz short Hci80 ; tick? Yes, go update globals
+
+Hci70:
+
+;
+; A new clock rate needs to be set. Setting the rate here will
+; cause the tick after the next tick to be at the new rate.
+
+;
+; The next tick is already in progress by the 8254 and will occur
+; at the following rate : ~(old rate + new rate)/2 because the new
+; count will be loaded at the end of the current half-cycle.
+;
+; (eax) = time increment for current tick
+
+ mov ebx, HalpNextMSRate
+ mov HalpPendingMSRate, ebx ; pending rate
+
+ ;
+ ; Next tick increment = ~(current TimeIncr + new TimeIncr)/2
+ ;
+ mov ecx, HalpNewTimeIncrement
+ add ecx, HalpRollOverTable[ebx*8-8].TimeIncr
+ shr ecx, 1
+ mov HalpNewTimeIncrement, ecx
+
+ mov ecx, HalpRollOverTable[ebx*8-8].RollOver
+
+ ;
+ ; Set clock rate
+ ; (ecx) = RollOverCount
+ ;
+
+ push eax ; save current tick's rate
+
+ ;
+ ; use a 50% duty cycle for the system clock
+ ;
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE3
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ pop eax
+ jmp short Hci40 ; dispatch this tick
+
+Hci80:
+
+;
+; The next tick will occur at the rate which was programmed during the last
+; tick. Update globals for new rate which starts with the next tick.
+;
+; (eax) = time increment for current tick
+;
+ mov ebx, HalpPendingMSRate
+ mov ecx, HalpRollOverTable[ebx*8-8].RollOver
+ mov edx, HalpRollOverTable[ebx*8-8].TimeIncr
+
+ mov HalpCurrentRollOver, ecx
+ mov HalpNewTimeIncrement, edx ; next tick rate
+ mov HalpPendingMSRate, 0 ; no longer pending, clear it
+
+ cmp ebx, HalpNextMSRate ; new rate == NextRate?
+ jne short Hci70 ; no, go set new pending rate
+
+ mov HalpNextMSRate, 0 ; we are at this rate, clear it
+ jmp Hci30 ; process this tick
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+;
+; Check if this is a spurious interrupt.
+;
+Hci200:
+ mov ecx, dword ptr [_CbusTimeStamp]
+ mov edx, dword ptr [ecx] ; Get its value
+ sub edx, HalpCurrentTimeIncrement ; In range ?
+ jb short Hci240 ; No, this is spurious.
+ jmp Hci05
+
+;
+; Ensure that the time stamp is no larger than HalpCurrentTimeIncrement.
+; We couldn't perform this code earlier when Hci200 was called
+; because it would open a window where the System Timer has been
+; reset, but the 64-bit performance counter has not been updated.
+; An additional CPU, in this case, could get a smaller value than
+; previously requested. To minimize this case, the resetting of
+; the SystemTimer should be as close to the 64-bit performance counter
+; as possible.
+;
+; in: ecx = time stamp address.
+; eax = current time increment.
+; ebx = next time increment.
+;
+; out: ecx = time stamp address.
+; eax = current time increment.
+; ebx = next time increment.
+; edx = new time stamp value to set.
+;
+
+Hci210:
+ mov edx, dword ptr [ecx] ; Get its value
+ sub edx, eax ; Remove current increment.
+if DBG
+ ;
+ ; Collect data for average.
+ ;
+ cmp edx, 20000000 ; Debugging if above 2 sec.
+ ja short @f
+ inc Cbus2CountClockInt
+ add Cbus2SumTimeStampLow, edx
+ adc Cbus2SumTimeStampHi, 0
+@@:
+ ;
+ ; Compute minimum.
+ ;
+ cmp Cbus2MinTimeStamp, edx
+ jbe short @f
+ mov Cbus2MinTimeStamp, edx
+@@:
+endif
+ cmp edx, eax ; Time stamp must be <= unit.
+ jbe Hci50 ; Yes, process the int.
+if DBG
+ ;
+ ; Compute maximum.
+ ;
+ cmp edx, 20000000 ; Debugging if above 2 sec.
+ ja short @f
+ inc Cbus2CountOverflowTimeStamp
+ cmp Cbus2MaxTimeStamp, edx
+ ja short @f
+ mov Cbus2MaxTimeStamp, edx
+@@:
+endif
+
+;
+; Use the whole time increment.
+;
+ mov edx, eax
+ jmp Hci50
+
+;
+; This is a spurious interrupt.
+;
+Hci240:
+ inc [Cbus2NumberSpuriousClocks]
+ mov eax, [_Cbus2ClockVector] ; get the interrupting vector
+ CBUS_EOI eax, edx ; ack the interrupt controller
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _Cbus2ClockInterrupt
+
+ page ,132
+ subttl "System Clock Interrupt for Additional Processors"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by CLOCK.
+; This routine is entered only by additional (non-boot) processors, so it
+; must NOT update the performance counter or update the system time.
+;
+; instead, it just dismisses the interrupt, raises system Irql to
+; CLOCK2_LEVEL and transfers control to the standard system routine
+; to update the execution time of the current thread and process.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateRunTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hcix2_a, Hcix2_t
+
+cPublicProc _Cbus2ClockInterruptPx ,0
+
+ ;
+ ; Save machine state in trap frame
+ ; (esp) - base of trap frame
+ ;
+
+ ENTER_INTERRUPT Hcix2_a, Hcix2_t
+
+ mov eax, HalpCurrentTimeIncrement ; Get the clock period.
+ mov ecx, dword ptr [_CbusTimeStamp] ; Get the time stamp address.
+
+ ;
+ ; Note that during this phase the interrupts are already disabled.
+ ; This is important because we don't want to take an IPI during this
+ ; phase which may force us to discard the next clock interrupt.
+ ; The call to HalBeginSystemInterrupt below will enable the interrupts.
+ ;
+
+ cmp [_Cbus2CheckSpuriousClock], 1 ; Check for spurious clock?
+ je short Hcix70
+ sub edx, edx ;
+Hcix50:
+ mov dword ptr [ecx], edx ; New SystemTimer value.
+
+ ;
+ ; We call the KeUpdateRunTime routine only at the maximum
+ ; rate reported by KeSetTimeIncrement.
+ ;
+ sub PCR[PcHal.PcrTickOffset], eax ; subtract time increment.
+ jg short Hcix100 ; if greater, not complete tick.
+ mov eax, HalpMaxTimeIncrement ; Re-trigger the call.
+ add PCR[PcHal.PcrTickOffset], eax ;
+
+ifdef CBC_REV1
+ ;
+ ; because we can miss an interrupt due to a hardware bug in the
+ ; CBC rev 1 silicon, send ourselves an IPI on every clock.
+ ; since we don't know when we've missed one, this will ensure
+ ; we don't cause lock timeouts if nothing else!
+ ;
+
+ stdCall _Cbus2RequestSoftwareInterrupt, <IPI_LEVEL>
+endif
+
+ ;
+ ; Dismiss interrupt and raise irq level to clock2 level
+ ;
+
+ push _CbusClockVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL, _CbusClockVector, esp>
+
+ ; Spurious interrupts on Corollary hardware are
+ ; directed to a different interrupt gate, so no need
+ ; to check return value above.
+
+ POKE_LEDS eax, edx
+
+ ;
+ ; (esp) = OldIrql
+ ; (esp+4) = Vector
+ ; (esp+8) = base of trap frame
+ ;
+ ; (ebp) = base of trap frame for KeUpdateRunTime, this was set
+ ; up by the ENTER_INTERRUPT macro above
+
+ stdCall _KeUpdateRunTime,<dword ptr [esp]>
+
+ INTERRUPT_EXIT
+;
+; Check if this is a spurious interrupt.
+;
+; in: ecx = time stamp address.
+; eax = current time increment.
+;
+; out: ecx = time stamp address.
+; eax = current time increment.
+; edx = new time stamp value to set.
+;
+Hcix70:
+ mov edx, dword ptr [ecx] ; Get its value
+ sub edx, eax ; In range ?
+ jb short Hcix100 ; No, this is spurious.
+ cmp edx, eax ; Time stamp must be <= unit.
+ jbe short Hcix50 ; Yes, process the int.
+;
+; Use the whole time-stamp unit.
+;
+ mov edx, eax
+ jmp short Hcix50
+
+;
+; This is a spurious interrupt.
+;
+Hcix100:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI
+
+stdENDP _Cbus2ClockInterruptPx
+
+;++
+;
+; ULONG
+; Cbus2SetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initializes the system time clock to generate an
+; interrupt at every DesiredIncrement interval. No lock synchronization
+; is needed here, since it is done by the executive prior to calling us.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _Cbus2SetTimeIncrement,1
+
+ mov eax, [esp+4] ; desired setting
+ xor edx, edx
+ mov ecx, 10000
+ div ecx ; round to MS
+
+ cmp eax, HalpLargestClockMS ; MS > max?
+ jc short @f
+ mov eax, HalpLargestClockMS ; yes, use max
+@@:
+ or eax, eax ; MS < min?
+ jnz short @f
+ inc eax ; yes, use min
+@@:
+ mov HalpNextMSRate, eax
+
+ mov eax, HalpRollOverTable[eax*8-8].TimeIncr
+ stdRET _Cbus2SetTimeIncrement
+
+stdENDP _Cbus2SetTimeIncrement
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; Cbus2QueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+4] ; User supplied Performance Frequency
+
+cPublicProc _Cbus2QueryPerformanceCounter ,1
+
+ ;
+ ; First check to see if the performance counter has been initialized
+ ; yet. Since the kernel debugger calls KeQueryPerformanceCounter to
+ ; support the !timer command, we need to return something reasonable
+ ; before performance counter calibration has occured.
+ ;
+ cmp Cbus2PerfInit, 0 ; calibration finished yet?
+ jne @f ; yes, we can read the perf counter
+
+ ;
+ ; Initialization hasn't occurred yet, so just return zeroes.
+ ;
+ mov eax, 0
+ mov edx, 0
+ jmp ret_freq
+
+@@:
+ ;
+ ; Merge our software 64-bit performance counter and the
+ ; 32-bit high resolution CBC timestamp counter into edx:eax
+ ;
+
+ push ebx ; ebx will be destroyed
+@@:
+ mov ebx, HalpCurrentTimeIncrement
+
+ mov edx, HalpPerfCounterHigh
+ mov eax, HalpPerfCounterLow
+ mov ecx, dword ptr [_Cbus2TimeStamp0]
+ mov ecx, dword ptr [ecx]
+
+ ;
+ ; re-read the global counters until we see we didn't get a torn read.
+ ;
+ cmp ebx, HalpCurrentTimeIncrement
+ jne short @b
+
+ cmp edx, HalpPerfCounterHigh
+ jne short @b
+
+ cmp eax, HalpPerfCounterLow
+ jne short @b
+
+ ;
+ ; This code can run on any CPU while the 'perf counters'
+ ; are updated only by CPU 0. If the first CPU is unable
+ ; to receive the clock interrupt because it is 'cli-ed'
+ ; or 'ipi-ed' for a long time, we need to return a value
+ ; greater than the provious returned value but less or equal
+ ; to any future value.
+ ;
+ cmp ecx, ebx ; Time stamp must be <= unit
+ jbe short @f ; Yes, it is
+ mov ecx, ebx ; else use unit
+@@:
+ pop ebx ; Restore ebx
+
+ ;
+ ; since the time stamp register and our 64-bit software register
+ ; are already both in 100ns units, there's no need for conversion here.
+ ;
+ add eax, ecx
+ adc edx, dword ptr 0
+
+ret_freq:
+
+ ;
+ ; return value is in edx:eax, return the performance counter
+ ; frequency if the caller wants it.
+ ;
+
+ or dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short @f ; it's NULL, so bail
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+
+ ;
+ ; Set frequency to a hardcoded clock speed of 66Mhz for now.
+ ;
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY
+ mov DWORD PTR [ecx+4], 0
+
+@@:
+ stdRET _Cbus2QueryPerformanceCounter
+
+stdENDP _Cbus2QueryPerformanceCounter
+
+_TEXT$03 ends
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+;
+; CMOS_WRITE
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; (AH) = data to be written
+;
+; Return: None
+;
+
+CMOS_WRITE MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ MOV AL,AH ; (AL) = DATA
+ OUT CMOS_DATA_PORT,AL ; PLACE IN REQUESTED CMOS LOCATION
+ IODelay ; I/O DELAY
+ENDM
+
+INIT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; Cbus2InitializeStall (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor. Note that the additional processors
+; execute this loop in Phase1, so they are already getting clock
+; interrupts as well as the RTC interrupts they expect from this
+; routine. We should disable clock interrupts during this period
+; to ensure a really accurate result, but it should be "good enough"
+; for now.
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+KiseInterruptCount equ [ebp-12] ; local variable
+
+cPublicProc _Cbus2InitializeStall ,1
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 12 bytes for local use
+ sub esp, 12
+
+ pushfd ; save caller's eflag
+
+ ;
+ ; Initialize Real Time Clock to interrupt us every 125ms at
+ ; IRQ 8.
+ ;
+
+ cli ; make sure interrupts are disabled
+
+ ;
+ ; Since RTC interrupt will come from IRQ 8, we need to save
+ ; the original irq 8 descriptor and set the descriptor to point to
+ ; our own handler.
+ ;
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov ecx, [ebp-6] ; (edx)->IDT
+
+ ;
+ ; the profile vector varies for each platform
+ ;
+ mov eax, dword ptr [_ProfileVector]
+
+ shl eax, 3 ; 8 bytes per IDT entry
+ add ecx, eax ; now at the correct IDT RTC entry
+
+ push dword ptr [ecx] ; (TOS) = original desc of IRQ 8
+ push dword ptr [ecx + 4] ; each descriptor has 8 bytes
+
+ ;
+ ; Pushing the appropriate entry address now (instead of
+ ; the IDT start address later) to make the pop at the end simpler.
+ ; we actually will retrieve this value twice, but only pop it once.
+ ;
+ push ecx ; (TOS) -> &IDT[HalProfileVector]
+
+ ;
+ ; No need to get and save current interrupt masks - only IPI
+ ; and software interrupts are enabled at this point in the kernel
+ ; startup. since other processors are still in reset, the profile
+ ; interrupt is the only one we will see. we really don't need to save
+ ; the old IDT[PROFILE_VECTOR] entry either, by the way - it's just
+ ; going to be overwritten in HalInitSystem Phase 1 anyway.
+ ;
+ ; note we are not saving edx before calling this function
+
+ stdCall _HalEnableSystemInterrupt,<dword ptr [_ProfileVector],PROFILE_LEVEL,0>
+
+ mov ecx, dword ptr [esp] ; restore IDT pointer
+
+ mov eax, offset FLAT:RealTimeClockHandler
+
+ mov word ptr [ecx], ax ; Lower half of handler addr
+ mov word ptr [ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [ecx+4], D_INT032 ; 386 interrupt gate
+
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [ecx+6], ax
+
+ mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+
+ ;
+ ; register C _MUST_ be read before register B is initialized,
+ ; otherwise an interrupt which was already pending will happen
+ ; immediately.
+ ;
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ ;
+ ; Don't clobber the Daylight Savings Time bit in register B, because we
+ ; stash the LastKnownGood "environment variable" there.
+ ;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ mov dword ptr [KiseInterruptCount], 0
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ ;
+ ; Now enable the interrupt and start the counter
+ ; (As a matter of fact, only IRQ8 can come through.)
+ ;
+
+ xor eax, eax ; (eax) = 0, initialize loopcount
+ALIGN 16
+ sti
+ jmp kise10
+
+ALIGN 16
+kise10:
+ sub eax, 1 ; increment the loopcount
+ jnz short kise10
+
+if DBG
+ ;
+ ; Counter overflowed
+ ;
+
+ stdCall _DbgBreakPoint
+endif
+ jmp short kise10
+
+ ;
+ ; Our RealTimeClock interrupt handler. The control comes here through
+ ; irq 8.
+ ; Note: we discard the first real time clock interrupt and compute the
+ ; permicrosecond loopcount on receiving of the second real time
+ ; interrupt. This is because the first interrupt is generated
+ ; based on the previous real time tick interval.
+ ;
+
+RealTimeClockHandler:
+
+ inc dword ptr KiseInterruptCount ; increment interrupt count
+ cmp dword ptr KiseInterruptCount,1 ; Is this the first interrupt?
+ jnz kise25 ; no, its the second go process it
+ pop eax ; get rid of original ret addr
+ push offset FLAT:kise10 ; set new return addr
+
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+
+ ;
+ ; register C _MUST_ be read before register B is initialized,
+ ; otherwise an interrupt which was already pending will happen
+ ; immediately.
+ ;
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+
+ ;
+ ; Don't clobber the Daylight Savings Time bit in register B, because we
+ ; stash the LastKnownGood "environment variable" there.
+ ;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ mov eax, _ProfileVector ; mark interrupting vec
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ xor eax, eax ; reset loop counter
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ iretd
+
+ align 4
+kise25:
+
+
+if DBG
+ ;
+ ; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount
+ ;
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint
+
+ ; never return
+ ;
+ ; ** End temporary code
+ ;
+
+kise30:
+endif
+ neg eax
+ xor edx, edx ; (edx:eax) = divident
+ mov ecx, PeriodInMicroSecond; (ecx) = time spent in the loop
+ div ecx ; (eax) = loop count per microsecond
+ cmp edx, 0 ; Is remainder =0?
+ jz short kise40 ; yes, go kise40
+ inc eax ; increment loopcount by 1
+
+ align 4
+kise40:
+
+ mov PCR[PcStallScaleFactor], eax
+
+ ;
+ ; Reset return address to kexit
+ ;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+
+ ;
+ ; Shutdown the periodic RTC interrupt
+ ;
+ stdCall _HalpAcquireCmosSpinLock
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_DISABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending interrupt
+ stdCall _HalpReleaseCmosSpinLock
+
+ stdCall _HalDisableSystemInterrupt,<dword ptr [_ProfileVector],PROFILE_LEVEL>
+ mov eax, _ProfileVector ; mark interrupting vec
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+ iretd
+
+ align 4
+kexit: ; Interrupts are disabled
+
+ pop ecx ; (ecx) -> &IDT[HalProfileVector]
+ pop [ecx+4] ; restore higher half of RTC desc
+ pop [ecx] ; restore lower half of RTC desc
+
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+ stdRET _Cbus2InitializeStall
+
+stdENDP _Cbus2InitializeStall
+
+INIT ends
+
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbapic.c b/private/ntos/nthals/halcbus/i386/cbapic.c
new file mode 100644
index 000000000..ab12868e1
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbapic.c
@@ -0,0 +1,898 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbapic.c
+
+Abstract:
+
+ This module implements the initialization of the APIC in Corollary
+ Cbus1 and Cbus2 systems. Note that Cbus1 uses only the APIC, where
+ Cbus2 can use either the APIC or the CBC - the HAL is told (by RRD) which
+ interrupt controller to use when operating under Windows NT.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 05-Oct-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cbusrrd.h" // HAL <-> RRD interface definitions
+#include "cbus.h" // Cbus1 & Cbus2 max number of elements is here
+#include "cbus1.h" // Cbus1 & Cbus2 max number of elements is here
+#include "cbus_nt.h" // C-bus NT-specific implementation stuff
+#include "bugcodes.h"
+#include "stdio.h"
+#include "cbusnls.h"
+#include "cbusapic.h"
+
+VOID
+ApicArbSync(
+VOID
+);
+
+VOID
+CbusApicBrandIOUnitID(
+IN ULONG Processor
+);
+
+VOID
+CbusInitializeLocalApic(
+IN ULONG Processor,
+IN PVOID PhysicalApicLocation,
+IN ULONG SpuriousVector
+);
+
+
+VOID
+CbusInitializeIOApic(
+IN ULONG Processor,
+IN PVOID PhysicalApicLocation,
+IN ULONG RedirVector,
+IN ULONG RebootVector,
+IN ULONG IrqPolarity
+);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, CbusApicBrandIOUnitID)
+#pragma alloc_text(INIT, CbusInitializeLocalApic)
+#pragma alloc_text(INIT, CbusInitializeIOApic)
+#endif
+
+ULONG
+READ_IOAPIC_ULONG(ULONG, ULONG);
+
+VOID
+WRITE_IOAPIC_ULONG(ULONG, ULONG, ULONG);
+
+VOID
+CbusApicRedirectionRequest(PULONG);
+
+VOID
+CbusDisable8259s( USHORT );
+
+VOID
+HalpSpuriousInterrupt(VOID);
+
+VOID
+IOApicUpdate( VOID );
+
+VOID
+CbusApicArbsync(VOID);
+
+VOID
+CbusRebootHandler( VOID );
+
+extern PULONG CbusVectorToEoi[MAXIMUM_IDTVECTOR + 1];
+
+extern ULONG CbusBootedProcessors;
+
+ULONG CbusIOApicCount;
+PVOID CbusIOApic[MAX_CBUS_ELEMENTS];
+PAPIC_REGISTERS CbusLocalApic;
+
+//
+// used for IPI vector enabling/disabling since each I/O
+// APIC is visible only to its attached processor.
+//
+REDIR_PORT_T CbusApicRedirPort[MAX_ELEMENT_CSRS];
+
+VOID
+CbusApicBrandIOUnitID(
+IN ULONG Processor
+)
+/*++
+
+Routine Description:
+
+ Each processor assigns an APIC ID to his I/O APIC so
+ it can arbitrate for the APIC bus, etc. Intel documentation
+ says that every local and I/O APIC must have a unique id.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+{
+ WRITE_IOAPIC_ULONG(0, IO_APIC_ID_OFFSET, (2 * Processor) << APIC_BIT_TO_ID);
+
+ CbusApicArbsync();
+}
+
+/*++
+
+Routine Description:
+
+ Called to get the EOI address for this particular vector.
+
+Arguments:
+
+ Vector - Supplies the APIC vector that will generate this interrupt
+
+Return Value:
+
+ The EOI address needed for this vector.
+
+--*/
+PULONG
+CbusApicVectorToEoi(
+IN ULONG Vector
+)
+{
+ UNREFERENCED_PARAMETER(Vector);
+
+ return (PULONG)(&CbusLocalApic->ApicEOI);
+}
+
+/*++
+
+Routine Description:
+
+ Called by each processor to initialize his local APIC.
+ The first processor to run this routine will map the
+ local APICs for all processors.
+
+ Note that all interrupts are blocked on entry since
+ we are being called from HalInitializeProcessor().
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+CbusInitializeLocalApic(
+IN ULONG Processor,
+IN PVOID PhysicalApicLocation,
+IN ULONG SpuriousVector
+)
+{
+ ULONG ProcessorBit;
+ ULONG ApicIDBit;
+ REDIRECTION_T RedirectionEntry = { 0 };
+
+ //
+ // If the APIC mapping has not been set up yet,
+ // do it now. Given the NT startup architecture,
+ // this will always be done by the boot processor.
+ //
+ // We map in the APIC into global space instead of in
+ // the PCR because all processors see it at the
+ // same _physical_ address. Note the page is mapped PWT.
+ //
+
+ //
+ // Note that all idle threads will share a common
+ // page directory, and the HAL PDE is inherited when
+ // new processes are created. Hence, a single
+ // HalpMapMemory for the APIC is enough for all
+ // processors to be able to see their APICs.
+ //
+ if (!CbusLocalApic) {
+ CbusLocalApic = (PAPIC_REGISTERS) HalpMapPhysicalMemoryWriteThrough (
+ PhysicalApicLocation,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ PhysicalApicLocation, LOCAL_APIC_SIZE));
+ }
+
+ (PTASKPRI) KeGetPcr()->HalReserved[PCR_TASKPRI] =
+ &CbusLocalApic->ApicTaskPriority;
+
+ //
+ // Here we initialize our destination format and
+ // logical destination registers so that we can get IPIs
+ // from other processors.
+ //
+ // Specify full decode mode in the destination format register -
+ // ie: each processor sets only his own bit, and a "match" requires
+ // that at least one bit match. The alternative is encoded mode,
+ // in which _ALL_ encoded bits must match the sender's target for
+ // this processor to see the sent IPI.
+ //
+ CbusLocalApic->ApicDestinationFormat = APIC_ALL_PROCESSORS;
+
+ //
+ // the logical destination register is what the redirection destination
+ // entry compares against. only the high 8 bits will be supported
+ // in Intel's future APICs, although this isn't documented anywhere!
+ //
+ ProcessorBit = KeGetPcr()->HalReserved[PCR_BIT];
+
+ ApicIDBit = (ProcessorBit << APIC_BIT_TO_ID);
+
+ CbusLocalApic->ApicLogicalDestination = ApicIDBit;
+
+ //
+ // designate the spurious interrupt vector we want to see,
+ // and inform this processor's APIC to enable interrupt
+ // acceptance.
+ //
+ CbusLocalApic->ApicSpuriousVector =
+ SpuriousVector | LOCAL_APIC_ENABLE;
+
+ //
+ // as each processor comes online here, we must have ALL
+ // processors resync their arbitration IDs to take into
+ // account the new processor. note that we will set:
+ // arb id == APIC id == processor number.
+ //
+ // the strange ID setting is to satisfy Intel's need for
+ // uniqueness amongst I/O and local unit ID numbering.
+ //
+
+ CbusLocalApic->LocalUnitID = ((2 * Processor + 1) << APIC_BIT_TO_ID);
+
+ //
+ // sync up our new ID with everyone else
+ //
+
+ CbusApicArbsync();
+
+ //
+ // Create the NMI routing linkage for this processor
+ // It is set as level sensitive, enabled and generating NMI trap 2.
+ //
+
+ RedirectionEntry.ra.Trigger = APIC_LEVEL;
+ RedirectionEntry.ra.Mask = APIC_INTR_UNMASKED;
+ RedirectionEntry.ra.Delivery_mode = APIC_INTR_NMI;
+ RedirectionEntry.ra.Vector = 2;
+ RedirectionEntry.ra.Destination = ApicIDBit;
+ CbusLocalApic->ApicLocalInt1 = RedirectionEntry;
+
+ //
+ // Create the spurious interrupt IDT entry for this processor
+ //
+
+ KiSetHandlerAddressToIDT(SpuriousVector, HalpSpuriousInterrupt);
+
+ //
+ // we must specify HIGH_LEVEL when we enable the spurious vector
+ // here because it will overwrite the CbusVectorToIrql[] entry
+ // for the HIGH_LEVEL (0xFF!). the spurious vector really only
+ // needs an IDT entry and doesn't need any other software tables,
+ // but make the enable call for tracking purposes.
+ //
+ HalEnableSystemInterrupt(SpuriousVector, HIGH_LEVEL, Latched);
+
+ //
+ // start off at IRQL 0 - we are still protected by cli.
+ //
+ CbusLocalApic->ApicTaskPriority.rb.LowDword = 0;
+}
+
+/*++
+
+Routine Description:
+
+ Note that all interrupts are blocked on entry since
+ this routine is called from HalInitializeProcessor.
+ Initialize this processor's local and I/O APIC units.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+CbusInitializeIOApic(
+IN ULONG Processor,
+IN PVOID PhysicalApicLocation,
+IN ULONG RedirVector,
+IN ULONG RebootVector,
+IN ULONG IrqPolarity
+)
+{
+ ULONG ProcessorBit;
+ ULONG ApicIDBit;
+ ULONG ApicBusNumber;
+ ULONG RedirectionAddress;
+ REDIRECTION_T RedirectionEntry = { 0 };
+
+ if (CbusIOApicCount >= MAX_CBUS_ELEMENTS) {
+ return;
+ }
+
+ CbusIOApic[CbusIOApicCount] =
+ (PVOID) HalpMapPhysicalMemoryWriteThrough (
+ PhysicalApicLocation,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ PhysicalApicLocation, IO_APIC_SIZE));
+
+ CbusApicBrandIOUnitID(Processor);
+
+ //
+ // Disable all 8259 inputs except the irq0 clock.
+ // remember the irq0 clock and the irq13 DMA
+ // chaining interrupts are internal to the Intel EISA
+ // chipset (specifically, the ISP chip), and if the HAL
+ // wants to enable them, it must be done here.
+ // This is done by enabling the 8259 ISP to send them
+ // to the processor(s) via the APIC. However, the Corollary HAL
+ // currently uses the local APIC timers for clocks. The irq0
+ // clock is enabled solely for the performance counter because
+ // we want to use a separate clock for it, (rather than the system
+ // timer which creates race conditions).
+ //
+ // Note that all other EISA bus device interrupts only need to
+ // be enabled in the APIC for processors to see them.
+ //
+ CbusDisable8259s(0xFFFE);
+
+ //
+ // All redirection table entries are disabled by default when the
+ // processor emerges from reset. Later, each entry is individually
+ // enabled from their respective drivers via HalEnableSystemInterrupt.
+
+ //
+ // Indicate the APIC (not the 8259s) will now handle provide
+ // the interrupt vectors to the processor during an INTA cycle.
+ // This is done by writing to the APMode port. Note that at this
+ // time we will also sync the APIC polarity control registers with
+ // the ELCR. Since irq0 has no polarity control, the hardware
+ // uses bit0 for the APMode enable, so make sure this bit is on too.
+ //
+
+ CbusLocalApic->APMode = (UCHAR)((IrqPolarity & 0xFF) | 0x1);
+ CbusLocalApic->PolarityPortHigh = (UCHAR)((IrqPolarity >> 8) & 0xFF);
+
+ //
+ // Create an interrupt gate so other processors can
+ // let the boot processor know about desired I/O APIC
+ // modifications (ie: enabling & disabling interrupts).
+ // This is necessary since each processor can only access
+ // his own I/O APIC, and only the boot processor's I/O APIC
+ // is attached to the EISA bus interrupt inputs. this only
+ // needs to be done once regardless of how many I/O APICs are
+ // present in the system.
+ //
+
+ if (CbusIOApicCount == 0) {
+ KiSetHandlerAddressToIDT(RedirVector, IOApicUpdate);
+ HalEnableSystemInterrupt(RedirVector, IPI_LEVEL, Latched);
+
+ KiSetHandlerAddressToIDT(RebootVector, CbusRebootHandler);
+ HalEnableSystemInterrupt(RebootVector, IPI_LEVEL, Latched);
+ }
+
+#define TRAP2 2
+
+ ProcessorBit = (ULONG) KeGetPcr()->HalReserved[PCR_BIT];
+
+ ApicIDBit = (ProcessorBit << APIC_BIT_TO_ID);
+
+ /*
+ * support NMIs from the EISA bridge as trap 2.
+ */
+ RedirectionEntry.ra.Mask = APIC_INTR_UNMASKED;
+ RedirectionEntry.ra.Trigger = APIC_LEVEL;
+ RedirectionEntry.ra.Dest_mode = APIC_LOGICAL_MODE;
+ RedirectionEntry.ra.Vector = TRAP2;
+ RedirectionEntry.ra.Destination = ApicIDBit;
+ RedirectionEntry.ra.Delivery_mode = APIC_INTR_FIXED;
+
+ //
+ // support multiple I/O buses by initializiing
+ // our current bus number...
+ //
+ ApicBusNumber = CbusIOApicCount;
+
+ RedirectionAddress = (ULONG)CbusApicLinkVector((PBUS_HANDLER)0,
+ (ULONG)-1, TRAP2);
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress + 1,
+ RedirectionEntry.ra.Destination);
+ WRITE_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress,
+ RedirectionEntry.rb.dword1);
+
+ //
+ // we've initialized another I/O APIC...
+ //
+ CbusIOApicCount++;
+}
+
+/*++
+
+Routine Description:
+
+ Enable the specified interrupt for the calling processor.
+ Remember only the boot processor can add/remove processors from
+ the I/O APIC's redirection entries.
+
+ This operation is trivial for the boot processor. However, additional
+ processors must interrupt the boot processor with an "enable interrupt"
+ request and then spin waiting for the boot processor to acknowledge that
+ the entry has been modified. Note that the caller holds the HAL's
+ CbusVectorLock at CLOCK_LEVEL on entry.
+
+Arguments:
+
+ Vector - Supplies a vector number to enable
+
+ HardwarePtr - Supplies a redirection entry address
+
+ LowestInGroup - TRUE if this vector should be sent to lowest-in-group
+ processor when the interrupt occurs.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+CbusEnableApicInterrupt(
+IN ULONG ApicBusNumber,
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG FirstAttach,
+IN BOOLEAN LowestInGroup,
+IN BOOLEAN LevelTriggered
+)
+{
+ ULONG Processor, ProcessorBit;
+ ULONG ApicIDBit;
+ ULONG ParticipatingProcessors;
+ REDIRECTION_T RedirectionEntry = { 0 };
+ ULONG RedirectionAddress;
+
+ ASSERT(ApicBusNumber < MAX_CBUS_ELEMENTS);
+
+ RedirectionAddress = (ULONG)HardwarePtr;
+
+ //
+ // Let the I/O APIC know that the calling processor wishes to
+ // participate in receipt of the interrupt. This must be done
+ // regardless of whether or not any other processors have already
+ // enabled the interrupt.
+ //
+ RedirectionEntry.ra.Vector = Vector;
+
+ //
+ // Mark the caller's interrupt as level or edge triggered,
+ // based on the ELCR register we read earlier.
+ //
+ if (LevelTriggered == TRUE) {
+ RedirectionEntry.ra.Trigger = APIC_LEVEL;
+ }
+ else {
+ RedirectionEntry.ra.Trigger = APIC_EDGE;
+ }
+
+ RedirectionEntry.ra.Mask = APIC_INTR_UNMASKED;
+ RedirectionEntry.ra.Dest_mode = APIC_LOGICAL_MODE;
+
+ //
+ // Only enable APIC LIG arbitration delay (at least 4 cycles on
+ // our 10Mhz APIC bus, which is 0.4 microseconds) if our caller
+ // told us to do it and there is more than one processor in the
+ // machine.
+ //
+
+ if (CbusProcessors > 1 && LowestInGroup == TRUE) {
+ RedirectionEntry.ra.Delivery_mode = APIC_INTR_LIG;
+ }
+ else {
+ RedirectionEntry.ra.Delivery_mode = APIC_INTR_FIXED;
+ }
+
+ //
+ // Add this processor's bit field number to the
+ // I/O APIC in order to be considered for receipt of
+ // the interrupt. Note the CbusVectorLock must be held
+ // whilst issuing reads and writes to the I/O APIC.
+ // Remember, each processor can only access his own I/O APIC.
+ //
+
+ Processor = (ULONG) KeGetPcr()->HalReserved[PCR_PROCESSOR];
+
+ ProcessorBit = (ULONG) KeGetPcr()->HalReserved[PCR_BIT];
+
+ ApicIDBit = (ProcessorBit << APIC_BIT_TO_ID);
+
+ if (Processor == 0) {
+
+ ParticipatingProcessors =
+ READ_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress + 1);
+
+#ifdef LANDY_DBG
+ DbgPrint("Boot processor enabling apic bus %d, vec %x, redir %x, 1stattach=%x, lig=%x, leveltrig=%x, prevpart=%x\n",
+ ApicBusNumber,
+ Vector,
+ HardwarePtr,
+ FirstAttach,
+ LowestInGroup,
+ LevelTriggered, ParticipatingProcessors);
+#endif
+
+ RedirectionEntry.ra.Destination =
+ (ParticipatingProcessors | ApicIDBit);
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress + 1,
+ RedirectionEntry.ra.Destination);
+ WRITE_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress,
+ RedirectionEntry.rb.dword1);
+
+ }
+ else {
+
+ //
+ // The boot processor controls the I/O APIC which distributes
+ // the interrupts. Only he can enable the interrupt for
+ // the calling processor, so send him an IPI now to
+ // fufill our request. This request must be satisfied before
+ // returning to our caller.
+ //
+ CbusApicRedirPort[Processor].Status =
+ (REDIR_ACTIVE_REQUEST | REDIR_ENABLE_REQUEST);
+
+ CbusApicRedirPort[Processor].ApicID = ApicIDBit;
+ CbusApicRedirPort[Processor].BusNumber = ApicBusNumber;
+ CbusApicRedirPort[Processor].RedirectionAddress =
+ RedirectionAddress;
+
+#ifdef LANDY_DBG
+ DbgPrint("Processor %d enabling apic bus %d, vec %x, redir %x, 1stattach=%x, lig=%x, leveltrig=%x\n",
+ Processor,
+ ApicBusNumber,
+ Vector,
+ HardwarePtr,
+ FirstAttach,
+ LowestInGroup,
+ LevelTriggered);
+#endif
+
+ if (FirstAttach) {
+ CbusApicRedirPort[Processor].Status |=
+ REDIR_FIRSTATTACH_REQUEST;
+ CbusApicRedirPort[Processor].RedirectionCommand =
+ RedirectionEntry.rb.dword1;
+ CbusApicRedirPort[Processor].RedirectionDestination =
+ ApicIDBit;
+ }
+
+ //
+ // Issue the command and wait for it to finish
+ //
+
+ CbusApicRedirectionRequest((PULONG)&CbusApicRedirPort[Processor].Status);
+
+#ifdef LANDY_DBG
+ DbgPrint("Processor %d done waiting for apic enable vec %x\n",
+ Processor, Vector);
+#endif
+ }
+}
+
+VOID
+CbusDisableApicInterrupt(
+IN ULONG ApicBusNumber,
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG LastDetach
+)
+/*++
+
+Routine Description:
+
+ Disable the specified interrupt so it can not occur on the calling
+ processor upon return from this routine. Remember only the boot processor
+ can add/remove processors from his I/O APIC's redirection entries.
+
+ This operation is trivial for the boot processor. However, additional
+ processors must interrupt the boot processor with a "disable interrupt"
+ request and then spin waiting for the boot processor to acknowledge that
+ the entry has been modified. Note that the caller holds the HAL's
+ CbusVectorLock at CLOCK_LEVEL on entry.
+
+Arguments:
+
+ Vector - Supplies a vector number to disable
+
+ HardwarePtr - Supplies a redirection entry address
+
+ LastDetach - TRUE if this is the last processor to detach from the
+ specified vector
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Processor, ProcessorBit, ApicIDBit;
+ REDIRECTION_T RedirectionEntry;
+ ULONG RedirectionAddress;
+
+ ASSERT(ApicBusNumber < MAX_CBUS_ELEMENTS);
+
+ RedirectionAddress = (ULONG)HardwarePtr;
+
+ Processor = (ULONG) KeGetPcr()->HalReserved[PCR_PROCESSOR];
+
+ ProcessorBit = (ULONG) KeGetPcr()->HalReserved[PCR_BIT];
+
+ // convert processor logical bit number to Intel ID register format...
+
+ ApicIDBit = (ProcessorBit << APIC_BIT_TO_ID);
+
+ if (Processor) {
+#ifdef LANDY_DBG
+ DbgPrint("Processor %d disabling apic bus %d, vec %x, redir %x \n",
+ Processor,
+ ApicBusNumber,
+ Vector,
+ HardwarePtr);
+#endif
+
+ //
+ // The boot processor controls the I/O APIC which distributes
+ // the interrupts. Since only he can disable the interrupt
+ // preventing it from coming to the calling processor, we
+ // IPI him here with our request. This request must be
+ // satisfied before returning to our caller.
+ //
+ CbusApicRedirPort[Processor].Status = (REDIR_ACTIVE_REQUEST |
+ REDIR_DISABLE_REQUEST);
+ if (LastDetach) {
+ CbusApicRedirPort[Processor].Status |=
+ REDIR_LASTDETACH_REQUEST;
+ }
+
+ CbusApicRedirPort[Processor].ApicID = ApicIDBit;
+ CbusApicRedirPort[Processor].BusNumber = ApicBusNumber;
+ CbusApicRedirPort[Processor].RedirectionAddress =
+ RedirectionAddress;
+
+ CbusApicRedirectionRequest((PULONG)&CbusApicRedirPort[Processor].Status);
+
+#ifdef LANDY_DBG
+ DbgPrint("Processor %d done waiting for apic disable vec %x\n",
+ Processor, Vector);
+#endif
+ return;
+ }
+
+ //
+ // Let the I/O APIC know that this CPU is no longer participating in
+ // receipt of the interrupt. Note the CbusVectorLock must be held
+ // whilst issuing reads and writes to the I/O APIC.
+ //
+
+ RedirectionEntry.rb.dword1 = READ_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress);
+
+ RedirectionEntry.rb.dword2 = READ_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress+1);
+
+ //
+ // Remove this processor's bit field number from the interrupt
+ // participation list. If this is the last processor to detach,
+ // mask off the interrupt at the source as well, so no one will
+ // need to arbitrate for it should it get asserted later.
+ //
+
+#ifdef LANDY_DBG
+ DbgPrint("Boot Processor disabling apic bus %d, vec %x, redir %x, 1stattach=%x, lig=%x, leveltrig=%x\n",
+ ApicBusNumber,
+ Vector,
+ HardwarePtr);
+#endif
+
+
+ RedirectionEntry.ra.Destination &= ~ApicIDBit;
+
+ if (LastDetach) {
+ RedirectionEntry.ra.Mask |= APIC_INTR_MASKED;
+ }
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress,
+ RedirectionEntry.rb.dword1);
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber, RedirectionAddress + 1,
+ RedirectionEntry.rb.dword2);
+}
+
+//
+// The interrupt handler run by the boot processor to process requests
+// from other processors to change the I/O APIC redirection entries. In
+// Cbus1, only the boot processor can reach the EISA I/O APIC, and thus,
+// requests from other processors are funnelled through to here.
+//
+// this function is running whilst cli'd, and some additional processor
+// is holding the CbusVectorLock.
+//
+VOID
+CbusApicRedirectionInterrupt()
+{
+ ULONG ApicBusNumber;
+ ULONG ParticipatingProcessors;
+ ULONG RedirectionAddress;
+ REDIRECTION_T RedirectionEntry;
+ PREDIR_PORT_T CurrentPort = CbusApicRedirPort;
+ PREDIR_PORT_T FinalPort = &CbusApicRedirPort[CbusBootedProcessors];
+#if DBG
+ ULONG OrigStatus;
+ ULONG Processor;
+
+ Processor = (ULONG) KeGetPcr()->HalReserved[PCR_PROCESSOR];
+ ASSERT(Processor == 0);
+#endif
+
+ //
+ // get the base of APIC space, so we can then access
+ // the addr of hardware interrupt command register below
+ //
+
+ for ( ; CurrentPort < FinalPort; CurrentPort++) {
+
+ //
+ // first check for an entry that needs servicing.
+ // when one is found, load up the requestor's APIC ID
+ // and the I/O address of the redirection table to modify.
+ // immediately bump to the destination register (high word)
+ // of the redirection table entry since that must be modified
+ // first. then capture the current value.
+ //
+
+ if ((CurrentPort->Status & REDIR_ACTIVE_REQUEST) == 0)
+ continue;
+
+ RedirectionAddress = CurrentPort->RedirectionAddress;
+ ApicBusNumber = CurrentPort->BusNumber;
+
+ //
+ // now that we have a valid request, see whether it was a
+ // DISABLE or ENABLE, and if it was the LAST detach or
+ // FIRST attach. take action appropriately...
+ //
+
+ ParticipatingProcessors = READ_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress + 1);
+
+ if (CurrentPort->Status & REDIR_ENABLE_REQUEST) {
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress + 1,
+ ParticipatingProcessors|CurrentPort->ApicID);
+
+ if (CurrentPort->Status&REDIR_FIRSTATTACH_REQUEST) {
+ WRITE_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress,
+ CurrentPort->RedirectionCommand);
+ }
+ }
+ else {
+ ASSERT(CurrentPort->Status & REDIR_DISABLE_REQUEST);
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress + 1,
+ ParticipatingProcessors &
+ ~CurrentPort->ApicID);
+
+ //
+ // Remove this processor's bit field number from
+ // the interrupt participation list. If this is
+ // the last processor to detach, mask off the
+ // interrupt at the source as well, so no one will
+ // need to arbitrate for it should it get asserted
+ // later.
+ //
+
+ if (CurrentPort->Status & REDIR_LASTDETACH_REQUEST) {
+ RedirectionEntry.rb.dword1 =
+ READ_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress);
+
+ RedirectionEntry.ra.Mask |= APIC_INTR_MASKED;
+
+ WRITE_IOAPIC_ULONG(ApicBusNumber,
+ RedirectionAddress,
+ RedirectionEntry.rb.dword1);
+ }
+ }
+#if DBG
+ OrigStatus = CurrentPort->Status;
+#endif
+
+ CurrentPort->Status = 0;
+#ifdef LANDY_DBG
+ DbgPrint("Boot processor touching APIC at intr time, apic bus %d, redir %x, status=%x, callerid=%x, redircmd=%x, prevpart=%x\n",
+ ApicBusNumber,
+ RedirectionAddress,
+ OrigStatus,
+ CurrentPort->ApicID,
+ CurrentPort->RedirectionCommand,
+ ParticipatingProcessors);
+#endif
+
+ }
+}
+
+PVOID
+CbusApicLinkVector(
+IN PBUS_HANDLER Bus,
+IN ULONG Vector,
+IN ULONG Irqline
+)
+/*++
+
+Routine Description:
+
+ "Link" a given vector to the passed BusNumber/irqline, returning
+ a "handle" that can be used to reference it later for operations
+ that need to access the hardware (ie: Enable & DisableInterrupt).
+
+Arguments:
+
+ Vector - Supplies the system interrupt vector corresponding to the
+ specified BusNumber/Irqline.
+
+ Irqline - Supplies the IRQ line of the specified interrupt
+
+Return Value:
+
+ A hardware-specific pointer (actually a redirection entry address)
+ that is interpreted only by the Cbus1 backend.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( Bus );
+
+ //
+ // Set up the EOI address now
+ //
+ if (Vector != (ULONG)-1) {
+ CbusVectorToEoi[Vector] = CbusApicVectorToEoi(Vector);
+ }
+
+ //
+ // Warning - there is built-in knowledge of this math in
+ // Cbus1EnableDeviceInterrupt(). Check there before making
+ // changes here. This was not the best way to do things,
+ // but this bug wasn't discovered until just before release.
+ //
+ return (PVOID)(IO_APIC_REDIRLO + 2 * Irqline);
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbdetect.c b/private/ntos/nthals/halcbus/i386/cbdetect.c
new file mode 100644
index 000000000..3ad224b47
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbdetect.c
@@ -0,0 +1,545 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbdetect.c
+
+Abstract:
+
+ This module detects the presence of a Corollary architecture machine
+ which can utilize the Corollary-developed HAL for Windows NT. Currently,
+ the picture looks as follows:
+
+ C-bus I original: uses standard Windows NT HAL
+ C-bus I XM: uses standard Windows NT HAL
+
+ C-bus I Symmetric XM: uses Corollary-developed Windows NT HAL
+ C-bus II: uses Corollary-developed Windows NT HAL
+
+ Thus, we return 0 for the first two cases, and non-zero for the last two.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 05-Oct-1992
+
+Environment:
+
+ Kernel mode only. This module must compile standalone,
+ and thus, any needed #defines have been copied directly
+ into this module.
+
+--*/
+
+#ifndef _NTOS_
+#include "nthal.h"
+#endif
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+
+//
+// address of configuration passed
+//
+#define RRD_RAM 0xE0000
+
+//
+// extended structures passed by RRD ROMs to various kernels/HALs
+// for the Corollary smp architectures
+//
+// layout of information passed to the kernels/HALs:
+// The exact format of the configuration structures is hard
+// coded in info.s (rrd). The layout is designed such that
+// the ROM version need not be in sync with the kernel/HAL version.
+//
+// checkword: ULONG
+// - extended configuration list must be terminated
+// with EXT_CFG_END (0)
+// length: ULONG
+// - length is for structure body only; does not include
+// either the checkword or length word
+//
+// structure body: format determined by checkword
+//
+//
+
+typedef struct _ext_cfg_header {
+
+ ULONG ext_cfg_checkword;
+ ULONG ext_cfg_length;
+
+} EXT_CFG_HEADER_T, *PEXT_CFG_HEADER;
+
+//
+// slot parameter structure (overrides any matching previous entry,
+// but is usually used in conjunction with the ext_cfg_override)
+// in processor_configuration or ext_memory_board.
+//
+// checkword is EXT_ID_INFO
+//
+// each structure is 16 bytes wide, and any number
+// of these structures can be presented by the ROM.
+// the kernel/HAL will keep reading them until either:
+//
+// a) an entry with id == 0x7f (this is treated as the list delimiter)
+// OR
+// b) the kernel (or HAL)'s internal tables fill up. at which point, only
+// the entries read thus far will be used and the rest ignored.
+//
+#define EXT_ID_INFO 0x01badcab
+typedef struct _ext_id_info {
+
+ ULONG id:7;
+ ULONG pm:1;
+ ULONG proc_type:4;
+ ULONG proc_attr:4;
+ ULONG io_function:8;
+ ULONG io_attr:8;
+ ULONG pel_start;
+ ULONG pel_size;
+
+ ULONG pel_features;
+
+ ULONG io_start;
+ ULONG io_size;
+
+} EXT_ID_INFO_T, *PEXT_ID_INFO;
+
+#define LAST_EXT_ID 0x7f // delimit the extended ID list
+
+//
+// configuration parameter override structure
+//
+// checkword is EXT_CFG_OVERRIDE.
+// can be any length up to the kernel/HAL limit. this
+// is a SYSTEMWIDE configuration override structure.
+//
+#define EXT_CFG_OVERRIDE 0xdeedcafe
+
+typedef struct _ext_cfg_override {
+ ULONG baseram;
+ ULONG memory_ceiling;
+ ULONG resetvec;
+ //
+ // cbusio is the base of global C-bus I/O space.
+ //
+ ULONG cbusio;
+
+ UCHAR bootid;
+ UCHAR useholes;
+ UCHAR rrdarb;
+ UCHAR nonstdecc;
+ ULONG smp_creset;
+ ULONG smp_creset_val;
+ ULONG smp_sreset;
+
+ ULONG smp_sreset_val;
+ ULONG smp_contend;
+ ULONG smp_contend_val;
+ ULONG smp_setida;
+
+ ULONG smp_setida_val;
+ ULONG smp_cswi;
+ ULONG smp_cswi_val;
+ ULONG smp_sswi;
+
+ ULONG smp_sswi_val;
+ ULONG smp_cnmi;
+ ULONG smp_cnmi_val;
+ ULONG smp_snmi;
+
+ ULONG smp_snmi_val;
+ ULONG smp_sled;
+ ULONG smp_sled_val;
+ ULONG smp_cled;
+
+ ULONG smp_cled_val;
+
+ ULONG machine_type;
+ ULONG supported_environments;
+ ULONG broadcast_id;
+
+} EXT_CFG_OVERRIDE_T, *PEXT_CFG_OVERRIDE;
+
+#define EXT_CFG_END 0
+
+#define MAX_CBUS_ELEMENTS 32 // max number of processors + I/O
+
+//
+// Bit fields of pel_features if pm indicates it's a processor
+//
+#define ELEMENT_SIO 0x00001 // SIO present
+#define ELEMENT_SCSI 0x00002 // SCSI present
+#define ELEMENT_IOBUS 0x00004 // IO bus is accessible
+#define ELEMENT_BRIDGE 0x00008 // IO bus Bridge
+#define ELEMENT_HAS_8259 0x00010 // local 8259s present
+#define ELEMENT_HAS_CBC 0x00020 // local Corollary CBC
+#define ELEMENT_HAS_APIC 0x00040 // local Intel APIC
+#define ELEMENT_RRD_RESERVED 0x20000 // Old RRDs used this
+
+
+//
+// Bit fields of machine types
+//
+#define MACHINE_CBUS1 0x1 // Original C-bus 1
+#define MACHINE_CBUS1_XM 0x2 // XM C-bus 1
+#define MACHINE_CBUS2 0x4 // C-bus 2
+
+//
+// Bit fields of supported environment types - each bit signifies that
+// the specified operating system release is supported in full multiprocessor
+// mode. Note that since the Cbus2 hardware changed, and initial hardware
+// wasn't available until Q2 1994, Cbus2 RRDs will _NEVER_ set the
+// 0x4 bit, and will instead set the 0x10 bit. This will have the effect
+// of Cbus2 being supported in MP mode by NT release 3.5 and up. Cbus1
+// will be supported in MP mode by all NT releases (3.1 and up).
+//
+#define SCO_UNIX 0x01
+#define USL_UNIX 0x02
+#define WINDOWS_NT 0x04 // release 3.1 and up (July 1993)
+#define NOVELL 0x08
+#define OS2 0x10
+#define WINDOWS_NT_R2 0x20 // release 3.5 and up (June 1994)
+
+extern ULONG CorollaryHalNeeded(PEXT_CFG_OVERRIDE, PEXT_ID_INFO,
+ PBOOLEAN);
+
+
+PUCHAR
+CbusFindString (
+IN PUCHAR Str,
+IN PUCHAR StartAddr,
+IN LONG Len
+)
+
+/*++
+
+Routine Description:
+
+ Searches a given virtual address for the specified string
+ up to the specified length.
+
+Arguments:
+
+ Str - Supplies a pointer to the string
+
+ StartAddr - Supplies a pointer to memory to be searched
+
+ Len - Maximum length for the search
+
+Return Value:
+
+ Pointer to the string if found, 0 if not.
+
+--*/
+
+{
+ LONG Index, n;
+
+ for (n = 0; Str[n]; ++n)
+ ;
+
+ if (--n < 0) {
+ return StartAddr;
+ }
+
+ for (Len -= n; Len > 0; --Len, ++StartAddr) {
+ if ((StartAddr[0] == Str[0]) && (StartAddr[n] == Str[n])) {
+ for (Index = 1; Index < n; ++Index)
+ if (StartAddr[Index] != Str[Index])
+ break;
+ if (Index >= n) {
+ return StartAddr;
+ }
+ }
+ }
+
+ return (PUCHAR)0;
+}
+
+
+//
+// for robustness, we check for the following before concluding that
+// we are indeed a Corollary C-bus I or C-bus II licensee:
+//
+// a) Corollary C-bus II string in the BIOS ROM 64K area (0x000F0000)
+// b) Corollary C-bus II string in the RRD RAM/ROM 64K area (0xFFFE0000)
+// c) 2 Corollary extended configuration tables
+// in the RRD RAM/ROM 64K area (0xFFFE0000)
+//
+// if any of the above fail, we assume we are not a Corollary
+// C-bus I or C-bus II box, and revert to normal uniprocessor
+// behavior.
+//
+
+static ULONG RRDextsignature[] = { 0xfeedbeef, 0 };
+
+static CHAR crllry_owns[] = "Copyright(C) Corollary, Inc. 1991. All Rights Reserved";
+
+ULONG
+DetectCbusII(
+ OUT PBOOLEAN IsConfiguredMp
+)
+/*++
+
+Routine Description:
+ Determine which Corollary platform, if any, is present.
+
+Arguments:
+ none.
+
+Return Value:
+
+ Return TRUE to indicate the machine is a Corollary MP machine
+ which requires the Corollary Windows NT HAL for full performance.
+
+ We only set IsConfiguredMp if we find more than 1 processor,
+ since it is only then that we want to incur the overhead of the
+ fully-built multiprocessor kernel. note that as long as we return
+ TRUE, our HAL will be used, so we will still get our improved
+ interrupt controller, ECC, additional memory, etc, etc.
+
+ All other cases will return FALSE, and clear IsConfiguredMp as well.
+
+--*/
+{
+ PEXT_CFG_HEADER p;
+ PEXT_ID_INFO Idp = (PEXT_ID_INFO)0;
+ PEXT_CFG_OVERRIDE CbusGlobal = (PEXT_CFG_OVERRIDE)0;
+ ULONG EntryLength;
+ PUCHAR Bios;
+
+ //
+ // assume it's not a Corollary MP machine (requiring the
+ // Corollary Windows NT HAL for full performance)
+ // unless we detect otherwise below.
+ //
+ *IsConfiguredMp = FALSE;
+
+ //
+ // map in the 64K (== 0x10 pages) of BIOS ROM @ 0xF0000
+ // and scan it for our signature. Note that when this
+ // code runs, the entire low 16MB address space is
+ // identity mapped, so the HalpMapPhysicalMemory call
+ // just returns (virtual address == physical address).
+ // the upshot of this, is that we need not worry about
+ // exhausting PTEs and doing Remaps or Frees. however,
+ // this also means we cannot map in the 64K of
+ // RRD @ 0xFFFE0000 since HalpMapPhysicalMemory will fail.
+ // so skip this second check until HalpMapPhysicalMemory is fixed.
+ //
+
+ Bios = (PUCHAR)HalpMapPhysicalMemory ((PVOID)0xF0000, 0x10);
+
+ if (!CbusFindString((PUCHAR)"Corollary", Bios, (LONG)0x10000))
+ return 0;
+
+ //
+ // we'd like to map in the 64K (== 0x10 pages) of RRD @ 0xFFFE0000 and
+ // scan it for our signature. but we can't in the detect code,
+ // because HalpMapPhysicalMemory() can't deal with memory over
+ // the 16MB boundary. so leave it for the HAL to check this.
+ //
+#if 0
+ Bios = (PUCHAR)HalpMapPhysicalMemory ((PVOID)0xFFFE0000, 0x10);
+
+ if (!CbusFindString((PULONG)"Corollary", Bios, (LONG)0x10000))
+ return 0;
+#endif
+
+ //
+ // map in the 32K (== 8 pages) of RRD RAM information @ 0xE0000,
+ //
+ Bios = (PUCHAR)HalpMapPhysicalMemory ((PVOID)RRD_RAM, 8);
+
+ if (!CbusFindString((PUCHAR)crllry_owns, Bios, (LONG)0x8000))
+ return 0;
+
+ //
+ // at this point, we are assured that it is indeed a
+ // Corollary architecture machine. search for our
+ // extended configuration tables, note we don't require
+ // (or even look for!) the existence of our earliest
+ // 'configuration' structure, ie: the 0xdeadbeef version.
+ // if there is no extended configuration structure,
+ // this must be an old rom. NO SUPPORT FOR THESE.
+ //
+
+ p = (PEXT_CFG_HEADER)CbusFindString((PUCHAR)RRDextsignature,
+ Bios, (LONG)0x8000);
+
+ //
+ // check for no extended configuration table: if it's not there,
+ // something is really wrong. we found our copyrights but not our
+ // machine? someone is copying us! no support for them!
+ //
+
+ if (!p)
+ return 0;
+
+ //
+ // Read in the 'extended ID information' table which,
+ // among other things, will give us the processor
+ // configuration.
+ //
+ // Multiple structures are strung together with a "checkword",
+ // "length", and "data" structure. The first null "checkword"
+ // entry marks the end of the extended configuration
+ // structure.
+ //
+ // we let the HAL deal with all the other extended configuration
+ // entries built by RRD.
+ //
+
+ do {
+ EntryLength = p->ext_cfg_length;
+
+ switch (p->ext_cfg_checkword) {
+
+ case EXT_ID_INFO:
+ Idp = (PEXT_ID_INFO)(p + 1);
+ break;
+
+ case EXT_CFG_OVERRIDE:
+ //
+ // reference up to the size of the structures
+ // we know about. if an rrd tries to pass us
+ // more than we know about, we ignore the
+ // overflow. underflow is interpreted as
+ // "this must be a pre-XM machine", and such
+ // machines must default to the standard Windows NT
+ // uniprocessor HAL.
+ //
+
+ if (EntryLength < sizeof(EXT_CFG_OVERRIDE_T))
+ return 0;
+
+ CbusGlobal = (PEXT_CFG_OVERRIDE)(p + 1);
+ break;
+
+ case EXT_CFG_END:
+
+ //
+ // If ancient C-bus box, it's not supported in MP mode
+ //
+ if (!Idp || !CbusGlobal)
+ return 0;
+
+ return CorollaryHalNeeded(
+ CbusGlobal,
+ Idp,
+ IsConfiguredMp);
+
+ default:
+ //
+ // skip unused or unrecognized configuration entries
+ // note that here we only care about EXT_ID_INFO as far
+ // as presence checking goes, but the HAL will care
+ // about more than just that.
+ //
+
+ break;
+ }
+
+ //
+ // get past the header, add in the length and then
+ // we're at the next entry.
+ //
+ p = (PEXT_CFG_HEADER) ((PUCHAR)(p + 1) + EntryLength);
+
+ } while (1);
+}
+
+
+//
+// process the tables we have built to determine whether
+// the machine is a Corollary MP machine which requires
+// the Corollary Windows NT HAL for full performance.
+//
+// We always set IsConfiguredMp for this case even if
+// this machine is configured as a uniprocessor, because it
+// will still see improved performance from our HAL.
+//
+
+ULONG
+CorollaryHalNeeded(
+IN PEXT_CFG_OVERRIDE CbusGlobal,
+IN PEXT_ID_INFO p,
+IN OUT PBOOLEAN IsConfiguredMp
+)
+{
+ ULONG Index;
+ ULONG Processors = 0;
+ BOOLEAN MachineSupported = FALSE;
+ ULONG machine;
+
+ machine = CbusGlobal->machine_type;
+
+ //
+ // first check global platform data. if this indicates that
+ // this is an early C-bus machine (which will be
+ // supported in uniprocessor mode only by Windows NT),
+ // and thus, should use the default Windows NT HAL.
+ //
+ if (machine & MACHINE_CBUS2) {
+
+ if ((CbusGlobal->supported_environments & WINDOWS_NT_R2) == 0)
+ return 0;
+
+ MachineSupported = TRUE;
+ }
+
+ if (machine & MACHINE_CBUS1_XM) {
+
+ if ((CbusGlobal->supported_environments & (WINDOWS_NT|WINDOWS_NT_R2)) == 0)
+ return 0;
+
+ MachineSupported = TRUE;
+ }
+
+ if (MachineSupported == FALSE)
+ return 0;
+
+ //
+ // then scan the table of IDs to make sure everything's ok
+ //
+
+ for (Index = 0; Index < MAX_CBUS_ELEMENTS; Index++, p++)
+ {
+
+ if (p->id == LAST_EXT_ID) {
+ break;
+ }
+
+ // check only processor elements...
+
+ if (p->pm == 0)
+ continue;
+
+ //
+ // at least the base bridge must have a
+ // distributed interrupt chip (because
+ // any CPUs without them will be disabled).
+ //
+
+ if (p->pel_features&(ELEMENT_HAS_APIC|ELEMENT_HAS_CBC)) {
+ Processors++;
+ }
+ else {
+ if (CbusGlobal->bootid == p->id)
+ return 0;
+
+ }
+ }
+
+ // This is an MP hal
+
+ *IsConfiguredMp = TRUE;
+
+ return 1;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbdriver.c b/private/ntos/nthals/halcbus/i386/cbdriver.c
new file mode 100644
index 000000000..b321895b4
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbdriver.c
@@ -0,0 +1,366 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbdrivers.c
+
+Abstract:
+
+ This Windows NT module creates a software-viewable table of the valid
+ element spaces present in a Corollary C-bus II machine. Since
+ searching through non-existent memory space can cause NMIs,
+ it is highly recommended that all areas needing this information
+ consult the built software table rather than rescanning themselves.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "cbus.h" // C-bus hardware architecture definitions
+#include "cbus_nt.h" // C-bus NT-specific implementation #defines
+
+VOID
+CbusIOPresent(
+ IN ULONG Id,
+ IN ULONG IoFunction,
+ IN ULONG IoAttribute,
+ IN ULONG IoStart,
+ IN ULONG IoSize,
+ IN PVOID Csr
+);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,CbusIOPresent)
+#endif
+
+#define MIN(a,b) (((a)>(b))?(b):(a))
+
+//
+// C-bus II half-card device driver interface:
+//
+// this scheme allows a single driver can have multiple
+// cards (ie: elements) present, and the single driver can
+// support all of them.
+//
+// to identify what I/O devices exist on the Cbus2 bus, software
+// would need to disable NMI, and check all element spaces for
+// valid element_type IDs (ie: NOT 0xff == BUS_TIMEOUT). since this
+// work is HIGHLY Cbus2 specific (poking the interrupt control
+// registers, turning off fault-enables, etc), this will be done
+// by our ROM and passed to the HAL.
+//
+// the kernel will build a software table of all elements,
+// CbusIoElements[]. software can scan this table at any time,
+// looking for specific io_type IDs. no entries in this table
+// should ever change once the table has been initially built.
+// in this way, other pieces of NT can determine what's in the
+// machine without worrying about generating NMIs, etc, etc.
+// this software still needs to be integrated into the registry.
+//
+// it is assumed drivers MUST use the same intr map lines on all
+// CBCs where his cards are attached. ie: it is ILLEGAL for a
+// SCSI driver to use local irq4 for CPU1's adapter 6 and local
+// irq5 for CPU2's adapter 6.
+//
+// it is legal for CPU3's localirq 5 can be a SCSI, whilst CPU4's
+// localirq 5 can be an SIO. we distinguish them in the kernel
+// because SIO and SCSI will have different io_type IDs.
+//
+// public I/O devices, control I/O, Prog I/O space of each
+// element is to be mapped in by the drivers themselves. the
+// HAL will not do this. the driver is provided the physical
+// start and length of each element space via CbusIoElements[].
+// as described above. hence, no driver should scan global memory
+// space searching for elements, which can cause NMIs, etc.
+//
+
+typedef struct _cbus_io_elements {
+
+ ULONG EntryLength;
+ ULONG ElementID;
+ ULONG ElementType;
+ ULONG IoAttribute;
+ ULONG AddressStart; // physical address in bytes
+ ULONG AddressLength; // length in bytes
+ ULONG CbcNumber; // BusNumber to drivers
+ PVOID Csr; // virtually mapped space
+
+} CBUS_IO_ELEMENTS_T, *PCBUS_IO_ELEMENTS;
+
+CBUS_IO_ELEMENTS_T CbusIoElements[MAX_ELEMENT_CSRS];
+
+ULONG CbusIoElementIndex;
+
+ULONG CBCIndex;
+
+PVOID CbusCBCtoCSR(
+ IN ULONG CbcNumber
+)
+/*++
+
+Routine Description:
+
+ Convert the CBC number to a CSR pointer.
+
+Arguments:
+
+ CbcNumber - Supplies the CBC number whose registers need to be accessed.
+
+Return Value:
+
+ Pointer to the CSR referenced by the argument CBC number, 0 if the
+ argument was invalid.
+
+--*/
+
+{
+ PCBUS_IO_ELEMENTS p;
+
+ if (CbcNumber >= CBCIndex) {
+ return (PVOID)0;
+ }
+
+ for (p = CbusIoElements; p < &CbusIoElements[CbusIoElementIndex]; p++) {
+ if (p->CbcNumber == CbcNumber) {
+ return (PVOID)(p->Csr);
+ }
+ }
+
+ return (PVOID)0;
+}
+
+
+
+VOID
+CbusIOPresent(
+ IN ULONG Id,
+ IN ULONG IoFunction,
+ IN ULONG IoAttribute,
+ IN ULONG IoStart,
+ IN ULONG IoSize,
+ IN PVOID Csr
+)
+/*++
+
+Routine Description:
+
+ Add the passed I/O entry to the table of Cbus I/O devices.
+ Note this table is for Cbus I/O devices only - EISA/ISA/MCA
+ devices are not part of this table.
+
+ This table containing all the elements is constructed so we can
+ give Cbus hardware drivers (and the rest of NT) meaningful information.
+
+Arguments:
+
+ From - Supplies a pointer to the RRD source table
+
+ To - Supplies a pointer to the destination storage for the table
+
+Return Value:
+
+ Number of valid table entries.
+
+--*/
+
+{
+ PCBUS_IO_ELEMENTS p, q;
+
+ //
+ // If no room, can't register this I/O device. Should never happen.
+ //
+
+ if (CbusIoElementIndex < MAX_ELEMENT_CSRS) {
+
+ p = &CbusIoElements[CbusIoElementIndex];
+
+ //
+ // Storing the length field allows the HAL to add more
+ // information to an entry in the future, and still
+ // maintain compatibility with older driver binaries.
+ //
+ p->EntryLength = sizeof (CBUS_IO_ELEMENTS_T);
+
+ //
+ // Process valid elements - these may or may
+ // not have a CPU on the card, but all can be accessed
+ // from any CPU in the system. memory cards and processors
+ // are not included here - this is for device drivers only.
+ //
+ p->ElementID = Id;
+ p->ElementType = IoFunction;
+ p->IoAttribute = IoAttribute;
+ p->AddressStart = IoStart;
+ p->AddressLength = IoSize;
+ p->Csr = Csr;
+
+ //
+ // More than one I/O element may share a single CBC.
+ // This is handled right here.
+ //
+ for (q = CbusIoElements; q < p; q++) {
+ if (q->ElementID == Id) {
+ p->CbcNumber = q->CbcNumber;
+ break;
+ }
+ }
+ if (q == p) {
+ p->CbcNumber = CBCIndex++;
+ }
+
+ CbusIoElementIndex++;
+ }
+}
+
+
+ULONG
+Cbus2GetCbusData(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Corollary Cbus data for a slot or address.
+ Drivers will be expected to call this function repeatedly with
+ incrementing BusNumbers & SlotNumbers, until this function returns 0,
+ indicating that the last slot has been read. Only one slot is
+ allowed per bus, with each I/O CBC representing a "bus". This is
+ necessary for interrupt vector allocation since slot numbers are
+ not passed into GetInterruptVector()...
+
+ Each chunk of slot data should then be examined by the driver.
+ The driver may skip any chunk that doesn't belong to him.
+ Once a chunk is encountered that belongs to him, the CBCNumber
+ field must be treated as the "Cbus BusNumber" (it's really a CBC number,
+ not including the CBCs of the EISA bridges), to pass in when he asks for
+ an interrupt vector via HalGetInterruptVector().
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ SlotNumber - Indicates which entry.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ ULONG BusNumber = RootHandler->BusNumber;
+ PUCHAR From;
+ ULONG MaxLength;
+
+ //
+ // let our caller know when he's hit the end
+ //
+
+ if (BusNumber >= CbusIoElementIndex) {
+ return 0;
+ }
+
+ if (SlotNumber != 0) {
+ return 0;
+ }
+
+ From = (PUCHAR)(CbusIoElements + BusNumber);
+ MaxLength = (CbusIoElementIndex - BusNumber) * sizeof (CBUS_IO_ELEMENTS_T);
+
+ if (Offset >= MaxLength) {
+ return 0;
+ }
+
+ if (Length+Offset > MaxLength) {
+ Length = MaxLength - Offset;
+ }
+
+ RtlMoveMemory(Buffer, From+Offset, Length);
+
+ return Length;
+}
+
+
+ULONG
+Cbus2SetCbusData(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the Corollary Cbus data for a slot or address.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ SlotNumber - Indicates which entry.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ ULONG BusNumber = RootHandler->BusNumber;
+ PUCHAR To;
+ ULONG MaxLength;
+
+ //
+ // don't allow writes beyond the end
+ //
+ if (BusNumber >= CbusIoElementIndex) {
+ return 0;
+ }
+
+ if (SlotNumber != 0) {
+ return 0;
+ }
+
+ To = (PUCHAR)(CbusIoElements + BusNumber);
+ MaxLength = (CbusIoElementIndex - BusNumber) * sizeof (CBUS_IO_ELEMENTS_T);
+
+ if (Offset >= MaxLength) {
+ return 0;
+ }
+
+ if (Length+Offset > MaxLength) {
+ Length = MaxLength - Offset;
+ }
+
+ RtlMoveMemory(To+Offset, Buffer, Length);
+
+ return Length;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbioacc.asm b/private/ntos/nthals/halcbus/i386/cbioacc.asm
new file mode 100644
index 000000000..8d4e94313
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbioacc.asm
@@ -0,0 +1,561 @@
+ title "Cbus ioaccess"
+;++
+;
+; Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+; Module Name:
+;
+; cbioacc.asm
+;
+; Abstract:
+;
+; Procedures to correctly touch I/O registers.
+; This is different from that of the standard PC HAL because
+; we support multiple I/O buses as part of Cbus2.
+;
+; Author:
+;
+; Landy Wang (landy@corollary.com) 19 Mar 1994
+;
+; Environment:
+;
+; User or Kernel, although privilege (IOPL) may be required.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+ .list
+
+_TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; I/O port space read and write functions.
+;
+; These have to be actual functions on the 386, because we need
+; to use assembler, but cannot return a value if we inline it.
+;
+; This set of functions manipulates I/O registers in PORT space.
+; (Uses x86 in and out instructions)
+;
+; WARNING: Port addresses must always be in the range 0 to 64K, because
+; that's the range the hardware understands. Any address with
+; the high bit on is assumed to be a HAL-memory-mapped equivalent
+; of an I/O address, so it can just (and must!) be read/written
+; directly.
+;
+;--
+
+
+
+;++
+;
+; UCHAR
+; READ_PORT_UCHAR(
+; PUCHAR Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_UCHAR ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+ in al,dx
+ stdRET _READ_PORT_UCHAR
+
+ align 4
+@@:
+ mov al, [edx]
+ stdRET _READ_PORT_UCHAR
+
+stdENDP _READ_PORT_UCHAR
+
+
+
+;++
+;
+; USHORT
+; READ_PORT_USHORT(
+; PUSHORT Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_USHORT ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+ in ax,dx
+ stdRET _READ_PORT_USHORT
+
+ align 4
+@@:
+ mov ax, [edx]
+ stdRET _READ_PORT_USHORT
+
+stdENDP _READ_PORT_USHORT
+
+
+
+;++
+;
+; ULONG
+; READ_PORT_ULONG(
+; PULONG Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_ULONG ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+ in eax,dx
+ stdRET _READ_PORT_ULONG
+
+ align 4
+@@:
+ mov eax, [edx]
+ stdRET _READ_PORT_ULONG
+
+stdENDP _READ_PORT_ULONG
+
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_UCHAR(
+; PUCHAR Port,
+; PUCHAR Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_UCHAR ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ rep insb
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_UCHAR
+
+ align 4
+@@:
+ push eax ; save eax (really the orig edi)
+
+ ;
+ ; this code to handle I/O to the extra busses should be written better
+ ;
+ align 4
+@@:
+ mov al, [edx]
+ mov [edi], al
+ inc edi
+ dec ecx
+ jnz @b
+ pop edi ; restore caller's edi
+ stdRET _READ_PORT_BUFFER_UCHAR
+
+stdENDP _READ_PORT_BUFFER_UCHAR
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_USHORT(
+; PUSHORT Port,
+; PUSHORT Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count (in 2-byte word units)
+;
+;--
+cPublicProc _READ_PORT_BUFFER_USHORT ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ rep insw
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_USHORT
+
+ align 4
+@@:
+ push eax ; save eax (really the orig edi)
+
+ ;
+ ; this code to handle I/O to the extra busses should be written better
+ ;
+ align 4
+@@:
+ mov ax, [edx]
+ mov [edi], ax
+ add edi, 2
+ dec ecx
+ jnz @b
+ pop edi ; restore caller's edi
+ stdRET _READ_PORT_BUFFER_USHORT
+
+stdENDP _READ_PORT_BUFFER_USHORT
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_ULONG(
+; PULONG Port,
+; PULONG Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count (in 4-byte dword units)
+;
+;--
+cPublicProc _READ_PORT_BUFFER_ULONG ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ rep insd
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_ULONG
+
+ align 4
+@@:
+ push eax ; save eax (really the orig edi)
+
+ ;
+ ; this code to handle I/O to the extra busses should be written better
+ ;
+ align 4
+@@:
+ mov eax, [edx]
+ mov [edi], eax
+ add edi, 4
+ dec ecx
+ jnz @b
+ pop edi ; restore caller's edi
+ stdRET _READ_PORT_BUFFER_ULONG
+
+stdENDP _READ_PORT_BUFFER_ULONG
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_UCHAR(
+; PUCHAR Port,
+; UCHAR Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_UCHAR ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov al,[esp+8] ; (al) = Value
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+ out dx,al
+ stdRET _WRITE_PORT_UCHAR
+
+ align 4
+@@:
+ mov [edx], al
+ stdRET _WRITE_PORT_UCHAR
+
+stdENDP _WRITE_PORT_UCHAR
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_USHORT(
+; PUSHORT Port,
+; USHORT Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_USHORT ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov eax,[esp+8] ; (ax) = Value
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+ out dx,ax
+
+ stdRET _WRITE_PORT_USHORT
+
+ align 4
+@@:
+ mov [edx], ax
+ stdRET _WRITE_PORT_USHORT
+
+stdENDP _WRITE_PORT_USHORT
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_ULONG(
+; PULONG Port,
+; ULONG Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_ULONG ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov eax,[esp+8] ; (eax) = Value
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ out dx,eax
+ stdRET _WRITE_PORT_ULONG
+
+ align 4
+@@:
+ mov [edx], eax
+ stdRET _WRITE_PORT_ULONG
+
+stdENDP _WRITE_PORT_ULONG
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_UCHAR(
+; PUCHAR Port,
+; PUCHAR Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_UCHAR ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ rep outsb
+
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_UCHAR
+
+ align 4
+@@:
+ push eax ; save eax (really the orig esi)
+
+ ;
+ ; this code to handle I/O to the extra busses should be written better
+ ;
+ align 4
+@@:
+ mov al, byte ptr [esi]
+ mov byte ptr [edx], al
+ inc esi
+ dec ecx
+ jnz @b
+ pop esi ; restore caller's esi
+ stdRET _WRITE_PORT_BUFFER_UCHAR
+
+stdENDP _WRITE_PORT_BUFFER_UCHAR
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_USHORT(
+; PUSHORT Port,
+; PUSHORT Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_USHORT ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ rep outsw
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_USHORT
+
+ align 4
+@@:
+ push eax ; save eax (really the orig esi)
+
+ ;
+ ; this code to handle I/O to the extra busses should be written better
+ ;
+ align 4
+@@:
+ mov ax, word ptr [esi]
+ mov word ptr [edx], ax
+ add esi, 2
+ dec ecx
+ jnz @b
+ pop esi ; restore caller's esi
+ stdRET _WRITE_PORT_BUFFER_USHORT
+
+stdENDP _WRITE_PORT_BUFFER_USHORT
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_ULONG(
+; PULONG Port,
+; PULONG Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_ULONG ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+
+ test edx, 080000000h ; high bit on?
+ jnz short @f ; yes, it is memory-mapped
+
+ rep outsd
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_ULONG
+
+ align 4
+@@:
+ push eax ; save eax (really the orig esi)
+
+ ;
+ ; this code to handle I/O to the extra busses should be written better
+ ;
+ align 4
+@@:
+ mov eax, dword ptr [esi]
+ mov dword ptr [edx], eax
+ add esi, 4
+ dec ecx
+ jnz @b
+ pop esi ; restore caller's esi
+ stdRET _WRITE_PORT_BUFFER_ULONG
+
+stdENDP _WRITE_PORT_BUFFER_ULONG
+
+
+_TEXT$00 ends
+
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbmapint.c b/private/ntos/nthals/halcbus/i386/cbmapint.c
new file mode 100644
index 000000000..7e65f67e6
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbmapint.c
@@ -0,0 +1,579 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbmapint.c
+
+Abstract:
+
+ This module implements the HalGetInterruptVector(),
+ HalDisableSystemInterrupt(), HalEnableSystemInterrupt(),
+ HalpInitializePICs() routines for the Corollary architectures
+ under Windows NT.
+
+ As part of the move from Product1 to Product2, HalGetInterruptVector()
+ may no longer be called before Phase1 !
+
+ This is because we want HalGetInterruptVector() to eventually call our
+ routine (the parent handler) HalpGetSystemInterruptVector(). However,
+ the linkage is not established until the Phase 1 call to
+ HalpInitBusHandlers().
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Apr-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "cbus_nt.h" // C-bus NT-specific implementation definitions
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+CbusPreparePhase0Interrupts(
+IN ULONG,
+IN ULONG,
+IN PVOID
+);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, HalpGetSystemInterruptVector)
+#pragma alloc_text(PAGE, CbusPreparePhase0Interrupts)
+#endif
+
+
+//
+// map the IRQLs to hardware interrupt vectors and vice versa
+//
+ULONG CbusIrqlToVector[HIGH_LEVEL + 1];
+
+ULONG CbusVectorToIrql[MAXIMUM_IDTVECTOR + 1];
+
+PULONG CbusVectorToEoi[MAXIMUM_IDTVECTOR + 1];
+
+//
+// the CbusVectorTable[] structure is used to communicate information
+// between HalGetInterruptVector() and HalEnableSystemInterrupt().
+// it would be nicer if it were built into an object instead of us
+// having to carry it around, but that's life.
+//
+// ANY call to HalEnableSystemInterrupt() WITHOUT a preceding call
+// to HalGetInterruptVector (by any processor) is ILLEGAL, unless
+// it has been special cased and detected here.
+//
+// CbusVectorTable[] dimensioning must match the x86 IDT size as well.
+//
+typedef struct _vectortable_t {
+ ULONG CpusEnabled; // count of CPUs that have called
+ // HalEnableSystemInterrupt()
+
+ PVOID hardware; // used by Cbus1 & Cbus2 backends
+ // to poke hardware
+
+ USHORT BusNumber; // which bus # of a given class
+
+ USHORT irqline; // only valid for actual I/O
+ // interrupts - not APC/DPC/IPI,etc.
+
+} VECTORTABLE_T, *PVECTORTABLE;
+
+VECTORTABLE_T CbusVectorTable[MAXIMUM_IDTVECTOR + 1];
+
+//
+// needed to synchronize allocation of new interrupt vectors as
+// loading drivers request them.
+//
+KSPIN_LOCK CbusVectorLock;
+
+/*++
+
+Routine Description:
+
+ Called by each hardware backend from HalInitProcessor() at Phase 0
+ by the boot cpu. All other cpus are still in reset.
+
+ software(APC, DPC, wake) and IPI vectors have already been initialized
+ and enabled.
+
+ all we're doing here is setting up some software structures for two
+ EISA interrupts (clock and profile) so they can be enabled later.
+
+ most of the PIC initialization really happened via HalInitializeProcessor()
+ because the boot CPU needed to disable his interrupts right away. this
+ is because KiSystemStartup() calls KiInitializeKernel() which drops IRQL
+ to APC level. this happens LONG before HalpInitializePICs is ever called.
+
+ As part of the move from Product1 to Product2, HalGetInterruptVector()
+ may no longer be called before Phase1 !
+
+ This is because we want HalGetInterruptVector() to eventually call our
+ routine (the parent handler) HalpGetSystemInterruptVector(). However,
+ the linkage is not established until the Phase 1 call to
+ HalpInitBusHandlers(). So this routine provides all the interrupt setup
+ that HalGetInterruptVector() does, but provides it at Phase0 init time.
+
+Arguments:
+
+ SystemVector - the vector the interrupt will occur on.
+
+ Opaque - an opaque hardware pointer that can only be interpreted by
+ the backend hardware portions of the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+CbusPreparePhase0Interrupts(
+IN ULONG SystemVector,
+IN ULONG Irqline,
+IN PVOID Opaque
+)
+{
+ CbusVectorTable[SystemVector].hardware = Opaque;
+ CbusVectorTable[SystemVector].irqline = (USHORT)Irqline;
+}
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt. Since this operation is highly architecture
+ specific, we will defer the entire routine to our hardware backend handler.
+
+ HalGetInterruptVector() must maintain a "vector to interrupt"
+ mapping so when the interrupt is enabled later via
+ HalEnableSystemInterrupt(), something intelligent can be done -
+ ie: which CBC's hardware interrupt maps to enable!
+ this applies both to EISA bridge CBCs and C-bus II half-card CBC's.
+
+ note that HalEnableSystemInterrupt() will be CALLED by
+ EACH processor wishing to participate in the interrupt receipt.
+
+Arguments:
+
+ BusHandler - the parent bus handler (ie: Internal)
+
+ RootHandler - the root bus handler (ie: Cbus, Eisa, MCA, PCI, etc)
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+ULONG
+HalpGetSystemInterruptVector(
+ IN PVOID Bhandler,
+ IN PVOID Rhandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+{
+ PBUS_HANDLER BusHandler = (PBUS_HANDLER)Bhandler;
+ PBUS_HANDLER RootHandler = (PBUS_HANDLER)Rhandler;
+ ULONG SystemVector;
+ PVECTORTABLE VectorObject;
+ extern ULONG HalpDefaultInterruptAffinity;
+
+ SystemVector = (*CbusBackend->MapVector)(
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql
+ );
+
+ if ( SystemVector > MAXIMUM_IDTVECTOR ||
+ (HalpIDTUsage[SystemVector].Flags & IDTOwned) ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+ return 0;
+ }
+
+ if (SystemVector) {
+
+ VectorObject = &CbusVectorTable[SystemVector];
+
+ if (RootHandler)
+ VectorObject->BusNumber = (USHORT)RootHandler->BusNumber;
+ else
+ VectorObject->BusNumber = 0;
+
+ VectorObject->irqline = (USHORT)BusInterruptLevel;
+
+ VectorObject->hardware =
+
+ (*CbusBackend->LinkVector)(
+ RootHandler,
+ SystemVector,
+ BusInterruptLevel);
+
+ //
+ // for the Corollary symmetric architectures, the
+ // interrupt affinity is always for all processors
+ //
+
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+
+ }
+
+ return SystemVector;
+}
+
+/*++
+
+Routine Description:
+
+ Enables a system interrupt, written in C as this
+ is not expected to be a frequently used operation.
+
+ this should not be called at interrupt level, as there
+ is not IRQL protection around CbusVectorLock
+ throughout the HAL. (there is IRQL protection here
+ against interrupt corruption, but not against lock
+ deadlocks).
+
+ When enabling an interrupt on multiple CPUs,
+ _EACH_ CPU will run this routine - see IoConnectInterrupt
+ and KeConnectInterrupt and the thread affinity mechanism.
+
+ virtually all interrupts are marked as LIG as far as the hardware
+ is concerned. This will be the "common" scenario, as most
+ drivers are fully multithreaded. Non multithreaded drivers
+ should only be calling this routine on ONE processor, and
+ thus, only that processor will participate in the "LIG"!
+
+ The only interrupts NOT marked LIG are profile, timer and IPI.
+ Note that since there is no general kernel mechanism to notify
+ the HAL of this characteristic, the HAL must special case these,
+ which currently happens based on IRQL. So let NO OTHER INTERRUPTS
+ share the CLOCK2, IPI or PROFILE irqls!!!
+
+ A conceptual difference between the APIC and the CBC is that when
+ an I/O APIC or CBC first gets a LIG interrupt from a device:
+
+ - The CBC broadcasts it on the bus, and each processor that
+ is a member of the receiving group will contend for the interrupt.
+ The lowest priority processor will be the one to take it.
+
+ - The I/O APIC knows what the set of the receiving group looks
+ like, and broadcasts it only to them, where the lowest priority
+ processor will be the one to take it.
+
+ This difference (transparent in hardware) does influence software
+ setup and teardown of the interrupt which is why the Enable and
+ Disable routines are not common to both Cbus1 and Cbus2.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt to be enabled
+
+ Irql - Supplies the interrupt level of the intr to be enabled
+
+ InterruptMode - Supplies the interrupt mode of the interrupt
+
+Return Value:
+
+ TRUE if enabled, FALSE if not.
+--*/
+
+BOOLEAN
+HalEnableSystemInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+{
+ KIRQL OldIrql;
+ ULONG FirstAttach;
+ PVECTORTABLE VectorObject;
+
+ ASSERT(Vector <= MAXIMUM_IDTVECTOR);
+
+ UNREFERENCED_PARAMETER( InterruptMode );
+
+ //
+ // maintain a "vector-to-irql" mapping here for fast
+ // translation when accepting an interrupt. this is
+ // better than continually keeping fs:PcIrql updated,
+ // as it allows us to remove instructions from KfRaiseIrql
+ // and KfLowerIrql, the hot paths.
+ //
+ CbusVectorToIrql[Vector] = Irql;
+
+ //
+ // first, try to enable it as a non-device interrupt - ie:
+ // without having to initialize an I/O bus to deliver it.
+ // if that succeeds (ie: for IPI or software interrupts like
+ // DPC or APC), then we're done. otherwise, go the
+ // long way.
+ //
+ if ((*CbusBackend->EnableNonDeviceInterrupt)(Vector) == TRUE) {
+ return TRUE;
+ }
+
+ //
+ // it's a legitimate hardware device interrupt...
+ //
+ // for Cbus2, we need to poke the generating bridge's
+ // CBC registers (first enable only) to allow the I/O
+ // interrupt to look for a participating CBC to receive
+ // it, as well as this processor's CBC to notify the I/O
+ // CBC that this processor would like to participate
+ // in the interrupt arbitration.
+ //
+ // for Cbus1, we need to poke the I/O APIC of the generating
+ // bus, as well as this processor's local APIC.
+ //
+ // note that currently clock, profile & IPI are initialized via
+ // the KiSetHandlerAddresstoIDT() macro & HalEnableSystemInterrupt().
+ // ie: HalGetInterruptVector() is NEVER called for them!
+ //
+ VectorObject = &CbusVectorTable[Vector];
+
+ //
+ // block all device interrupts (clock is the highest).
+ // do not block the HAL-private IPI which is used for
+ // Cbus1 (only) redirection table access, otherwise you
+ // will create a deadlock race condition.
+ //
+ OldIrql = KfRaiseIrql(CLOCK2_LEVEL);
+
+ KiAcquireSpinLock(&CbusVectorLock);
+
+ //
+ // check for "impossible" case...
+ // ie: where HalEnableSystemInterrupt has been called,
+ // but HalGetInterruptVector has NOT! with the exception
+ // of clock, profile, APC, DPC and IPI (which have hardcoded
+ // vectors), all drivers intending to receive interrupts must
+ // call HalGetInterruptVector to get a vector.
+ //
+ ASSERT (VectorObject->hardware);
+
+ VectorObject->CpusEnabled += 1;
+
+ FirstAttach = (VectorObject->CpusEnabled == 1 ? 1 : 0);
+
+ (*CbusBackend->EnableDeviceInterrupt)(
+ Vector,
+ VectorObject->hardware,
+ FirstAttach,
+ VectorObject->BusNumber,
+ VectorObject->irqline);
+
+ KiReleaseSpinLock(&CbusVectorLock);
+
+ //
+ // unblock I/O interrupts
+ //
+ KfLowerIrql(OldIrql);
+
+ return TRUE;
+}
+
+
+VOID
+HalDisableSystemInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+/*++
+
+ Routine Description:
+
+ Disables a system interrupt, written in C as this
+ is not expected to be a frequently used operation.
+ should not be called at interrupt level, as there
+ is not IRQL protection around CbusVectorLock
+ throughout the HAL. (there is IRQL protection here
+ against interrupt corruption, but not against lock
+ deadlocks).
+
+ This routine is only called when the interrupt may
+ actually be disabled - ie: it doesn't need to worry
+ about drivers sharing the interrupt line and one of
+ them disabling the line without the other's knowledge.
+
+ Arguments:
+
+ Vector - Supplies the vector of the interrupt to be disabled
+
+ Irql - Supplies the interrupt level of the intr to be disabled
+
+ Return Value:
+
+ None.
+--*/
+
+{
+ KIRQL OldIrql;
+ ULONG LastDetach = 0;
+ PVECTORTABLE VectorObject;
+
+ UNREFERENCED_PARAMETER( Irql );
+
+ ASSERT(Vector < MAXIMUM_IDTVECTOR + 1);
+
+ VectorObject = &CbusVectorTable[Vector];
+
+ //
+ // Block all device interrupts (clock is the highest).
+ // Do not block the HAL-private IPI which is used for
+ // Cbus1 (only) redirection table access since this
+ // would create a deadlock race condition.
+ //
+ OldIrql = KfRaiseIrql(CLOCK2_LEVEL);
+
+ KiAcquireSpinLock(&CbusVectorLock);
+
+ VectorObject->CpusEnabled -= 1;
+
+ if (VectorObject->CpusEnabled == 0) {
+ LastDetach = 1;
+ }
+
+ (*CbusBackend->DisableInterrupt)(
+ Vector,
+ (PVOID)VectorObject->hardware,
+ LastDetach,
+ VectorObject->BusNumber,
+ VectorObject->irqline);
+
+ KiReleaseSpinLock(&CbusVectorLock);
+
+ //
+ // unblock interrupts
+ //
+ KfLowerIrql(OldIrql);
+}
+
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/private/ntos/nthals/halcbus/i386/cbswint.asm b/private/ntos/nthals/halcbus/i386/cbswint.asm
new file mode 100644
index 000000000..56d633d72
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbswint.asm
@@ -0,0 +1,444 @@
+ title "Software Interrupts"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+;Module Name:
+;
+; cbswint.asm
+;
+;Abstract:
+;
+; This module implements the HAL software interrupt routines
+; for the MP Corollary implementation under Windows NT.
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include i386\cbus.inc
+include mac386.inc
+
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+
+ .list
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; FASTCALL
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to issue a software interrupt to the
+; calling processor. Since this is all done in hardware, the
+; code to implement this is trivial. Our hardware supports
+; sending the interrupt to lowest-in-group processors, which
+; would be useful for a good number of DPCs, for example, but
+; the kernel doesn't currently tell us which kinds of software
+; interrupts need to go to the caller versus which can go to
+; any processor.
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+
+ push ecx
+ call dword ptr [_CbusRequestSoftwareInterrupt]
+ fstRet HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+;++
+;
+; VOID
+; HalClearSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to clear a possible pending software interrupt.
+; Support for this function is optional, and allows the kernel to
+; reduce the number of spurious software interrupts it receives. Since
+; neither the APIC nor the CBC can clear an interrupt once it is sent,
+; this optional function becomes a no-op in the Cbus HAL.
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalClearSoftwareInterrupt ,1
+ fstRET HalClearSoftwareInterrupt
+fstENDP HalClearSoftwareInterrupt
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Note that the "software" interrupt has in fact been
+; generated by software, but delivered by hardware - thus, no iret
+; frame needs to be constructed here by software.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+cPublicProc _HalpDispatchInterrupt ,0
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+
+ ;
+ ; The only thing we need to save here is the interrupted taskpri.
+ ; We must EOI the APIC immediately as there is no interrupt source,
+ ; and if we context switch and exit this thread, then we may never EOI!
+ ; the above macro will save all our registers, so we don't need to
+ ; below. Thus, the EOI serves as the HalEndSystemInterrupt.
+ ;
+
+ mov eax, DPC_TASKPRI ; mark interrupting vec
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ mov esi, dword ptr PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ push dword ptr [esi] ; save entry taskpri
+if DBG
+ cmp dword ptr [esi], 0 ; old irql not zero?
+ je short irqlok
+ cmp dword ptr [esi], 01fh ; old irql not zero?
+ je short irqlok
+ int 3
+irqlok:
+endif
+
+ mov dword ptr [esi], DPC_TASKPRI ; set new h/w taskpri
+ sti ; and allow interrupts
+
+ ;
+ ; Go do Dispatch Interrupt processing - we may context switch away from
+ ; this thread here, resume the idle thread and either much later (or
+ ; never) continue onward. so we must EOI _before_ dispatching with
+ ; this call.
+ ;
+
+ stdCall _KiDispatchInterrupt
+
+ ;
+ ; restore our original IRQL by programming it into the interrupt
+ ; controller since we will read it out of the interrupt controller
+ ; on the next KfRaiseIrql(). We must re-read the address of the
+ ; task priority register for the current processor before setting
+ ; it because we may be resuming a thread on a different processor
+ ; from the one that originally entered this routine. For the APIC,
+ ; this wouldn't matter because the task priority register is at the
+ ; same physical address for all processors. But for the CBC, each
+ ; task priority lies in global physical space (at different addresses).
+ ; since we are at DISPATCH_LEVEL here, we cannot be pre-empted as
+ ; we do this.
+ ;
+
+ifdef CBC_REV1
+ pop eax ; get entry taskpri
+if DBG
+ cmp eax, 0 ; old irql not zero?
+ je short irqlok2
+ cmp eax, 01fh ; old irql not zero?
+ je short irqlok2
+ int 3
+irqlok2:
+endif
+ pushfd
+ cli
+ mov esi, dword ptr PCR[PcHal.PcrTaskpri]
+ mov dword ptr [esi], eax ; restore entry taskpri
+ popfd
+else
+ mov esi, dword ptr PCR[PcHal.PcrTaskpri]
+ pop dword ptr [esi] ; restore entry taskpri
+endif
+
+ ;
+ ; Call this directly instead of through INTERRUPT_EXIT
+ ; because the HalEndSystemInterrupt has already been done,
+ ; and must only be done ONCE per interrupt.
+ ;
+
+ cli
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI
+
+stdENDP _HalpDispatchInterrupt
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Note that the "software" interrupt has in fact been
+; generated by software, but delivered by hardware - thus, no iret
+; frame needs to be constructed here by software.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+cPublicProc _HalpApcInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+ ENTER_INTERRUPT hapc_a, hapc_t
+
+ ; The only thing we need to save here is the interrupted taskpri.
+ ; We must EOI the APIC immediately as there is no interrupt source,
+ ; and if we context switch and exit this thread, then we may never EOI!
+ ; the above macro will save all our registers, so we don't need to
+ ; below. Thus, the EOI serves as the HalEndSystemInterrupt.
+
+ mov eax, APC_TASKPRI ; mark interrupting vec
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ mov esi, dword ptr PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ push dword ptr [esi] ; save entry taskpri
+
+if DBG
+ cmp dword ptr [esi], 0 ; old irql not zero?
+ je short @f
+ int 3
+@@:
+endif
+
+ mov dword ptr [esi], APC_TASKPRI ; set new h/w taskpri
+ sti ; and allow interrupts
+
+ ; call the APC delivery routine(previous mode,Null exception frame,
+ ; trap frame)
+
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ stdCall _KiDeliverApc, <eax, 0, ebp>
+
+ ;
+ ; restore our original IRQL by programming it into the interrupt
+ ; controller since we will read it out of the interrupt controller
+ ; on the next KfRaiseIrql(). We must re-read the address of the
+ ; task priority register for the current processor before setting
+ ; it because we may be resuming a thread on a different processor
+ ; from the one that originally entered this routine. For the APIC,
+ ; this wouldn't matter because the task priority register is at the
+ ; same physical address for all processors. But for the CBC, each
+ ; task priority lies in global physical space (at different addresses).
+ ; since we are at APC_LEVEL here, we must protect against a context
+ ; switch happening between reading the taskpri address and actually
+ ; setting its value, hence the cli...
+ ;
+
+ifdef CBC_REV1
+ cli
+endif
+if DBG
+ cmp dword ptr [esp], 0 ; old irql not zero?
+ je short @f
+ int 3
+@@:
+endif
+ mov esi, dword ptr PCR[PcHal.PcrTaskpri]
+ pop dword ptr [esi] ; restore entry taskpri
+
+if DBG
+ cmp dword ptr [esi], 0 ; old irql not zero?
+ je short @f
+ int 3
+@@:
+endif
+ ;
+ ; Call this directly instead of through INTERRUPT_EXIT
+ ; because the HalEndSystemInterrupt has already been done,
+ ; and must only be done ONCE per interrupt.
+ ;
+
+ cli
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpApcInterrupt
+
+
+ page ,132
+ subttl "HalRequestIpi"
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+; Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+; for Windows NT (and MPX 2.1), we use full distributed
+; interrupt capability, and, thus, we will IGNORE the sswi address
+; that RRD passes us and prioritize IPI as we see fit, given the
+; other devices configured into the system. see the backend Cbus1
+; and Cbus2 handlers for more details.
+;
+; Arguments:
+;
+; Mask - Mask of processors to be interrupted
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalRequestIpi ,1
+
+ jmp dword ptr [_CbusRequestIPI]
+
+stdENDP _HalRequestIpi
+
+;++
+;
+; VOID
+; HalpIpiHandler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by inter
+; processor communication. Its function is to call its handler.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hipi_a, Hipi_t
+
+ align 4
+
+cPublicProc _HalpIpiHandler ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
+
+ ;
+ ; Save interrupting vector and previous IRQL. previous IRQL will
+ ; be filled in by our call to HalBeginSystemInterrupt, and the
+ ; stack space for both will be removed via INTERRUPT_EXIT's
+ ; call to HalEndSystemInterrupt.
+ ;
+ push dword ptr [_CbusIpiVector]
+ sub esp, 4 ; space for OldIrql
+
+ ;
+ ; We now dismiss the interprocessor interrupt
+ ; (Irql, Vector, stack location of OldIrql)
+
+ stdCall _HalBeginSystemInterrupt, <IPI_LEVEL, dword ptr [_CbusIpiVector], esp>
+
+ ; Pass Null ExceptionFrame
+ ; Pass TrapFrame to Ipi service rtn
+
+ stdCall _KiIpiServiceRoutine, <ebp, 0>
+
+ ;
+ ; Do interrupt exit processing
+ ;
+
+ INTERRUPT_EXIT ; will return to caller
+
+stdENDP _HalpIpiHandler
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halcbus/i386/cbsysint.asm b/private/ntos/nthals/halcbus/i386/cbsysint.asm
new file mode 100644
index 000000000..27b492bb8
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbsysint.asm
@@ -0,0 +1,590 @@
+;++
+;
+;Copyright (C) 1992-1995 Corollary Inc
+;
+;Module Name:
+;
+; cbsysint.asm
+;
+;Abstract:
+;
+; This module implements some of the HAL routines to
+; deal with interrupts for the MP Corollary implementations
+; under Windows NT. The Cbus1 architecture uses the Intel
+; APIC interrupt controller chip which is somewhat restricted
+; in its capabilities. See cbus_nt.h for more details.
+; The Cbus2 architecture can use the Corollary CBC or the Intel APIC,
+; providing much greater interrupt granularity with the CBC.
+;
+; General HAL interrupt routines are coded in C for easy
+; modification/portability; HAL interrupt routines which
+; are frequently called are written here in assembly for
+; greater speed.
+;
+;Environment:
+;
+; Kernel Mode
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include cbus.inc
+ .list
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value,
+; and update the hardware task priority register. Since our
+; underlying hardware supports "software" interrupts, the
+; only need for KfRaiseIrql & KfLowerIrql to be different is
+; because KfRaiseIrql must return the old irql.
+;
+; we cannot allow an interrupt between storing the old irql and
+; raising irql to the requested level. this is only because some
+; callers may specify a global store address for the previous irql.
+;
+; the sequence of instructions looks unusual in order to optimize
+; memory fetches by separating the fetch from the usage wherever possible.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfRaiseIrql,1
+
+ movzx ecx, cl ; get new irql value
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ mov edx, [eax] ; get old taskpri val
+
+ mov ecx, [_CbusIrqlToVector+4*ecx] ; convert new irql to taskpri
+
+if DBG
+ cmp ecx, edx ; new irql less than old?
+ jb short rfail
+endif
+
+ mov [eax], ecx ; set new hardware taskpri
+
+ mov eax, [_CbusVectorToIrql+4*edx] ; convert old taskpri to irql
+
+ifdef CBC_REV1
+ popfd
+endif
+
+ fstRET KfRaiseIrql
+
+if DBG
+rfail:
+ push edx ; save old irql
+ push ecx ; save new irql
+ mov dword ptr [eax], 0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; no return
+endif
+
+fstENDP KfRaiseIrql
+
+
+;++
+;
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ ;
+ ; Raise to DISPATCH_LEVEL
+ ;
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ mov edx, [eax] ; get old taskpri val
+
+ mov dword ptr [eax], DPC_TASKPRI ; set new hardware taskpri
+
+ifdef CBC_REV1
+ popfd
+endif
+
+ mov eax, [_CbusVectorToIrql+4*edx] ; convert old taskpri to irql
+ stdRET _KeRaiseIrqlToDpcLevel
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+cPublicFpo 0, 0
+
+ ; This should be optimized
+
+ mov ecx, SYNCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+
+ page ,132
+ subttl "Lower irql"
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; Any pending software interrupts will be generated to the processor by
+; hardware after the task priority/sti allows.
+;
+; the sequence of instructions looks unusual in order to optimize
+; memory fetches by separating the fetch from the usage wherever possible.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall KfLowerIrql, 1
+
+ movzx ecx, cl ; get new irql value
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get hardware taskpri addr
+
+ mov ecx, [_CbusIrqlToVector+4*ecx] ; convert irql to taskpri
+
+if DBG
+ cmp ecx, dword ptr [eax] ; is new greater than old?
+ ja lfail
+endif
+
+ mov [eax], ecx ; set new hardware taskpri
+
+ ;
+ ; we must re-read the task priority register because this read
+ ; forces the write above to be flushed out of the write buffers.
+ ; otherwise the write above can get stuck and result in a pending
+ ; interrupt not being immediately delivered. in situations like
+ ; KeConnectInterrupt, the interrupt must be delivered in less than
+ ; 12 assembly instructions (the processor sends himself a rescheduling
+ ; DPC and has to execute it to switch to another CPU before continuing)
+ ; or corruption will result. because he thinks he has switched
+ ; processors and he really hasn't. and having the interrupt come in
+ ; after the 12 assembly instructions is _TOO LATE_!!!
+ ;
+ mov ecx, [eax] ; ensure it's lowered
+ifdef CBC_REV1
+ popfd
+endif
+
+ fstRET KfLowerIrql
+
+if DBG
+lfail:
+ push ecx ; save new taskpri
+ push dword ptr [eax] ; save old taskpri
+ mov dword ptr [eax], 0ffh ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; no return
+endif
+
+ fstRET KfLowerIrql
+fstENDP KfLowerIrql
+
+;++
+;
+; VOID
+; HalEndSystemInterrupt (
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; Any pending software interrupts will be generated to the processor by
+; hardware after the task priority/sti allows.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt - (note this is different from
+; the level we need to return to because multiple vectors may
+; need to be blocked at given irql level).
+;
+; Note that esp+12 is the beginning of the interrupt/trap frame and upon
+; entering this routine, interrupts are off.
+;
+; the sequence of instructions looks unusual in order to optimize
+; memory fetches by separating the fetch from the usage wherever possible.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; equates for accessing arguments
+; since eflags and ret addr are pushed into stack, all the arguments
+; offset by 8 bytes
+;
+
+HeiNewIrql equ [esp+4]
+HeiNewVector equ [esp+8]
+
+cPublicProc _HalEndSystemInterrupt , 2
+
+ ;
+ ; issue the EOI for the interrupting vector now that the ISR has run
+ ;
+ mov eax, HeiNewVector ; get the interrupting vector
+ xor ecx, ecx ; faster than movzx
+
+ CBUS_EOI eax, edx ; ack the interrupt controller
+ mov cl, byte ptr HeiNewIrql ; get new irql value
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get hardware taskpri addr
+
+ mov ecx, [_CbusIrqlToVector+4*ecx] ; convert new irql to taskpri
+ mov [eax], ecx ; set new hardware taskpri
+ifdef CBC_REV1
+ popfd
+endif
+
+ stdRET _HalEndSystemInterrupt
+
+stdENDP _HalEndSystemInterrupt
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql,
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified Irql number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+; for 8259 architectures, vector == PIC_VECTBASE + irq line.
+; for machines like ours (which can map arbitrary IRQ LINES to
+; arbitrary interrupt VECTORS, unlike the 8259), vector is a
+; completely independent value. notice that the higher numerical
+; vector is the higher priority vector. When using the APIC,
+; the EOI must be done after the s/w handler executes because
+; EOI'ing the APIC will lower the APIC priority and allow interrupts.
+;
+; the sequence of instructions looks unusual in order to optimize
+; memory fetches by separating the fetch from the usage wherever possible.
+; note that "xor reg,reg & mov byte ptr" have been used instead of movzx
+; since it's faster (on a Pentium).
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored - we
+; have re-routed the spurious interrupt vector to a
+; routine which just irets. thus, this routine will
+; NEVER be called for a spurious interrupt and thus,
+; will NEVER return FALSE.
+;
+; the CBC & APIC can receive spurious interrupts.
+; barring I/O devices that float the line, spurious
+; interrupts should only occur when:
+;
+; - the taskpri has been raised but is still in
+; the CPU write buffer.
+;
+; - a lower priority interrupt comes in and the CBC/APIC
+; signals an interrupt to the CPU.
+;
+; - the INTA cycles force the write buffers out,
+; and the CBC/APIC realizes this lower-priority
+; interrupt should really be blocked until later.
+;
+; - now the CBC/APIC will send a spurious interrupt to
+; the CPU, and send the lower-priority interrupt
+; later.
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt , 3
+
+ ;
+ ; Get the hardware task priority register address
+ifdef CBC_REV1
+ ; we're already cli'd, so don't worry about switching processors
+ ; after getting the task priority address
+endif
+ ;
+ xor ecx, ecx ; faster than movzx
+ mov eax, PCR[PcHal.PcrTaskpri]
+
+ ;
+ ; Capture the current hardware priority so we can return the old
+ ; IRQL to our caller. Then raise IRQL to requested level - this
+ ; is Cbus2 specific since the Cbus1 APIC automatically does this
+ ; in hardware.
+ ;
+ ; Crank hardware to new task priority level - we must use the
+ ; numerically lowest taskpri corresponding to the requested irql.
+ ; We cannot just use the vector passed in because multiple devices
+ ; may be configured at the same irql level, and have intertwined
+ ; dependencies.
+ ;
+ ; Note for the APIC, the hardware priority register
+ ; is automatically updated to block all the interrupts in
+ ; the bucket (and lower buckets) when this interrupt was
+ ; delivered. Also, that the priority is raised in an
+ ; APIC internal register, not the hardware task priority
+ ; register that is manipulated via KfRaiseIrql & KfLowerIrql.
+ ;
+ ; Raise the APIC priority explicitly here anyway in order to
+ ; maintain a common set of code with Cbus2.
+ ;
+
+ mov cl, HbsiIrql ; get new irql value
+
+ mov edx, [eax] ; get old taskpri val
+
+ mov ecx, [_CbusIrqlToVector+4*ecx] ; irql --> taskpri
+
+ mov [eax], ecx ; set new h/w taskpri
+
+ ;
+ ; Done raising the new priority and getting the old priority,
+ ; now give our caller back the old priority in IRQL units.
+ ;
+
+ mov ecx, HbsiOldIrql ; old irql savearea
+ mov edx, [_CbusVectorToIrql+4*edx] ; old taskpri --> irql
+
+ mov byte ptr [ecx], dl
+
+ sti
+ mov eax, 1 ; ALWAYS return TRUE
+
+ stdRET _HalBeginSystemInterrupt
+
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+; Note that for speed, we do NOT maintain a PCR
+; version of the current irql (ie: movzx eax, fs:PcIrql).
+; NOT doing this allows us to trim 3 instructions out of
+; KfRaiseIrql & KfLowerIrql. Since KeGetCurrentIrql is
+; rarely called, we take the hit of two extra instructions here
+; instead.
+
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+ mov eax, [eax] ; get taskpri value
+ifdef CBC_REV1
+ popfd
+endif
+
+ mov eax, [_CbusVectorToIrql+4*eax] ; convert to irql
+
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+;++
+;
+; VOID
+; CbusDisable8259s (IN USHORT MASK)
+;
+; Routine Description:
+;
+; Called to disable 8259 input lines as we switch into full
+; distributed interrupt chip mode. our distributed interrupt
+; chip logic in the CBC will handle all interrupts from this
+; point on. the only reason we have to leave irq0 enabled is
+; because Intel's EISA chipset doesn't leave an external irq0
+; clock line for us to wire into the CBC. hence, we have wired
+; it from the 8259 into the CBC, and must leave it enabled in
+; the 8259 IMR. note that we will never allow the now passive
+; 8259 to respond to a CPU INTA cycle, but we do need to see the
+; interrupt ourselves in the CBC so we can drive an appropriate
+; vector during the INTA.
+;
+; For the Cbus1 architecture, we mask off ALL the interrupts coming
+; from the EISA chipset, since timers are generated by each local APIC.
+;
+; This is the ONLY place in the Corollary HAL (and all of NT!)
+; where the 8259s are accessed.
+;
+;
+; Arguments:
+;
+; Mask to put on the master and slave 8259.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _CbusDisable8259s ,1
+ mov ax, word ptr [esp+4] ; use specified 8259 mask
+ SET_8259_MASK
+ stdRET _CbusDisable8259s
+stdENDP _CbusDisable8259s
+
+
+ page ,132
+ subttl "HalpSpuriousInterrupt"
+;++
+;
+; VOID
+; HalpSpuriousInterrupt(VOID)
+; );
+;
+; Routine Description:
+;
+; Entered directly from an interrupt gate to handle a spurious interrupt
+; generated by the CBC or APIC interrupt controller. Just return, the
+; real interrupt will be reposted by the hardware when our task priority
+; drops later.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpSpuriousInterrupt, 0
+
+ iretd ; IRET to clear the stack
+
+stdENDP _HalpSpuriousInterrupt
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halcbus/i386/cbus.c b/private/ntos/nthals/halcbus/i386/cbus.c
new file mode 100644
index 000000000..d581e2a84
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus.c
@@ -0,0 +1,1281 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus.c
+
+Abstract:
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for the
+ MP Corollary machines under Windows NT.
+
+ This includes the Corollary C-bus II machines which use Corollary's
+ CBC chips as well as Corollary C-bus I machines which use the Intel APIC.
+ Hardware dependencies of each C-bus backend are isolated in their
+ independent hardware modules. This module is completely hardware
+ independent.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "cbus.h" // Cbus1 & Cbus2 max number of elements is here
+#include "cbusrrd.h" // HAL <-> RRD interface definitions
+#include "cbus_nt.h" // C-bus NT-specific implementation stuff
+#include "cbusnls.h"
+
+
+PVOID
+HalpRemapVirtualAddress(IN PVOID, IN PVOID, IN BOOLEAN);
+
+BOOLEAN
+CbusMPMachine(VOID);
+
+PUCHAR
+CbusFindString (
+IN PUCHAR Str,
+IN PUCHAR StartAddr,
+IN LONG Len
+);
+
+ULONG
+CbusStringLength (
+IN PUCHAR Str
+);
+
+ULONG
+CbusReadExtIDs(
+IN PEXT_ID_INFO From,
+IN PEXT_ID_INFO To
+);
+
+PVOID
+CbusMappings(
+IN ULONG Processor,
+IN PEXT_ID_INFO Idp
+);
+
+VOID
+CbusMapMemoryRegisters(
+IN PEXT_ID_INFO Idp
+);
+
+VOID
+CbusEstablishMaps(
+IN PEXT_ID_INFO Table,
+IN ULONG Count
+);
+
+VOID
+CbusReadRRD(VOID);
+
+VOID
+CbusCheckBusRanges(VOID);
+
+VOID
+CbusAddMemoryHoles(VOID);
+
+VOID
+CbusInitializeOtherPciBus(VOID);
+
+VOID
+HalInitializeProcessor(
+IN ULONG Processor
+);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, CbusStringLength)
+#pragma alloc_text(INIT, CbusFindString)
+#pragma alloc_text(INIT, CbusReadExtIDs)
+#pragma alloc_text(INIT, CbusMappings)
+#pragma alloc_text(INIT, CbusMapMemoryRegisters)
+#pragma alloc_text(INIT, CbusEstablishMaps)
+#pragma alloc_text(INIT, CbusReadRRD)
+#pragma alloc_text(PAGE, HalInitializeProcessor)
+#endif
+
+#define MIN(a,b) (((a)>(b))?(b):(a))
+
+EXT_CFG_OVERRIDE_T CbusGlobal;
+
+ULONG CbusProcessors;
+ULONG CbusProcessorMask;
+ULONG CbusBootedProcessors;
+ULONG CbusBootedProcessorsMask;
+
+ULONG CbusTemp;
+
+//
+// 8254 spinlock. This must be acquired before touching the 8254 chip.
+//
+
+ULONG Halp8254Lock;
+
+ULONG HalpDefaultInterruptAffinity;
+
+extern ULONG CbusVectorToIrql[MAXIMUM_IDTVECTOR + 1];
+
+PULONG CbusTimeStamp;
+
+//
+// For Cbus1, the CbusCSR[] & CbusBroadcastCSR really point at
+// Cbus1 I/O space which can vary from platform to platform.
+//
+// For Cbus2, the CbusCSR[] & CbusBroadcastCSR really do point at
+// the Cbus2 CSR for the particular element.
+//
+PVOID CbusBroadcastCSR;
+
+//
+// Cbus information table for all elements (an element may not
+// necessarily contain an x86 processor; ie: it may be a pure
+// I/O element).
+//
+ELEMENT_T CbusCSR[MAX_CBUS_ELEMENTS];
+
+
+MEMORY_CARD_T CbusMemoryBoards[MAX_ELEMENT_CSRS];
+ULONG CbusMemoryBoardIndex;
+
+//
+// hardcoded size for now - see cbus.inc for the register definition
+// and layout of CbusRebootRegs[].
+//
+ULONG CbusRebootRegs[8];
+
+RRD_CONFIGURATION_T CbusJumpers;
+
+EXT_ID_INFO_T CbusExtIDTable[MAX_CBUS_ELEMENTS];
+ULONG CbusValidIDs;
+
+ULONG CbusVectorToHwmap[MAXIMUM_IDTVECTOR + 1];
+
+//
+// Declare the task priority system vectors which vary from APIC to CBC.
+// About the only ones that remain constant are high, low and APC & DPC.
+// This is primarily due to shortcomings and errata in the APIC.
+//
+
+ULONG ProfileVector;
+ULONG CbusIpiVector;
+ULONG CbusClockVector;
+ULONG CbusRedirVector;
+ULONG CbusRebootVector;
+
+//
+// Declare these two pointers here for speed - it eliminates an
+// extra asm instruction each time they are called.
+//
+
+VOID (*CbusRequestIPI)(IN ULONG);
+VOID (*CbusRequestSoftwareInterrupt) ( IN KIRQL);
+LARGE_INTEGER (*CbusQueryPerformanceCounter) ( IN OUT PLARGE_INTEGER);
+
+ADDRESS_USAGE HalpCbusMemoryHole = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0
+
+ }
+};
+
+//
+// this structure differs from the one above in that it only contains
+// memory ranges that we want reserved for the HAL and ensure that
+// devices do not get dynamically assigned memory from these ranges.
+// specifically, the table above will include more ranges that the
+// BIOS E820 function will remove, but that need to remain available
+// for resources on the secondary peer PCI bus for C-bus II.
+//
+ADDRESS_USAGE HalpCbusMemoryResource = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0
+
+ }
+};
+
+ULONG CbusMemoryHoleIndex;
+ULONG CbusMemoryResourceIndex;
+
+
+ULONG
+CbusStringLength (
+IN PUCHAR Str
+)
+
+/*++
+
+Routine Description:
+
+ Return the length of the input NULL-terminated Ansi string, including
+ the NULL terminator at the end.
+
+Arguments:
+
+ Str - Supplies a pointer to the string
+
+Return Value:
+
+ Length of the string in bytes
+
+--*/
+
+{
+ ULONG n;
+
+ for (n = 0; Str[n]; ++n)
+ ;
+
+ return ++n;
+}
+
+
+PUCHAR
+CbusFindString (
+IN PUCHAR Str,
+IN PUCHAR StartAddr,
+IN LONG Len
+)
+
+/*++
+
+Routine Description:
+
+ Searches a given virtual address for the specified string
+ up to the specified length.
+
+Arguments:
+
+ Str - Supplies a pointer to the string
+
+ StartAddr - Supplies a pointer to memory to be searched
+
+ Len - Maximum length for the search
+
+Return Value:
+
+ Pointer to the string if found, 0 if not.
+
+--*/
+
+{
+ LONG Index, n;
+
+ for (n = 0; Str[n]; ++n)
+ ;
+
+ if (--n < 0) {
+ return StartAddr;
+ }
+
+ for (Len -= n; Len > 0; --Len, ++StartAddr) {
+ if ((StartAddr[0] == Str[0]) && (StartAddr[n] == Str[n])) {
+ for (Index = 1; Index < n; ++Index)
+ if (StartAddr[Index] != Str[Index])
+ break;
+ if (Index >= n) {
+ return StartAddr;
+ }
+ }
+ }
+
+ return (PUCHAR)0;
+}
+
+ULONG
+CbusReadExtIDs(
+IN PEXT_ID_INFO From,
+IN PEXT_ID_INFO To
+)
+
+/*++
+
+Routine Description:
+
+ Read in the C-bus II extended id information table.
+
+Arguments:
+
+ From - Supplies a pointer to the RRD source table
+
+ To - Supplies a pointer to the destination storage for the table
+
+Return Value:
+
+ Number of valid table entries.
+
+--*/
+
+{
+ ULONG Index = 0;
+ ULONG ValidEntries = 0;
+
+ for ( ; Index < MAX_CBUS_ELEMENTS && From->id != LAST_EXT_ID; Index++) {
+
+ //
+ // we cannot skip blank RRD entries
+ //
+ // if (From->pm == 0 && From->io_function == IOF_INVALID_ENTRY)
+ // continue;
+
+ RtlMoveMemory((PVOID)To, (PVOID)From, sizeof(EXT_ID_INFO_T));
+
+ From++;
+ To++;
+ ValidEntries++;
+ }
+
+ //
+ // WARNING: this is not necessarily the number of valid CPUs !!!
+ //
+ return ValidEntries;
+}
+
+PVOID
+CbusMappings(
+IN ULONG Processor,
+IN PEXT_ID_INFO Idp
+)
+/*++
+
+Routine Description:
+
+ Map a given processor's CSR space and save an idp pointer as well.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+ Idp - Supplies an RRD extended ID pointer for this processor element
+
+Return Value:
+
+ Opaque pointer to this processor's CSR space.c
+
+--*/
+{
+ //
+ // RRD specifies how much to map in per processor - this
+ // will usually be just 8K of the 64K CSR space for Cbus2.
+ // For Cbus1, RRD must give us a size which includes any
+ // processor-specific registers the HAL may access,
+ // generally indicated via the CbusGlobal structure.
+ //
+ CbusCSR[Processor].csr = HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)Idp->pel_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ Idp->pel_start, Idp->pel_size));
+
+ CbusCSR[Processor].idp = (PVOID)Idp;
+
+ return CbusCSR[Processor].csr;
+}
+
+VOID
+CbusMapMemoryRegisters(
+IN PEXT_ID_INFO Idp
+)
+/*++
+
+Routine Description:
+
+ Maps a given RRD entry into the HAL's memory board structures.
+ This is used later to determine ECC error addresses, etc.
+
+Arguments:
+
+ Idp - Supplies a pointer to the RRD extended information structure entry
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_CARD pm;
+
+ pm = &CbusMemoryBoards[CbusMemoryBoardIndex];
+
+ pm->physical_start = Idp->pel_start;
+ pm->physical_size = Idp->pel_size;
+ pm->io_attr = (ULONG)Idp->io_attr;
+
+ //
+ // map in the csr space for this memory card
+ //
+ pm->regmap = HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)Idp->io_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ Idp->io_start, Idp->io_size));
+
+ CbusMemoryBoardIndex++;
+}
+
+VOID
+CbusEstablishMaps(
+IN PEXT_ID_INFO Table,
+IN ULONG Count
+)
+/*++
+
+Routine Description:
+
+ Parse the given RRD extended ID configuration table, and construct
+ various HAL data structures accordingly.
+
+Arguments:
+
+ Table - Supplies a pointer to the RRD extended information table
+
+ Count - Supplies a count of the maximum number of entries.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index, processor = 0;
+ ULONG HighVector;
+ ULONG Length;
+ PEXT_ID_INFO Idp = Table;
+ PUCHAR csr;
+ extern VOID CbusMemoryFree(ULONG, ULONG);
+ extern VOID CbusIOPresent(ULONG, ULONG, ULONG, ULONG, ULONG, PVOID);
+ extern ULONG IxProfileVector;
+
+ for (Index = 0; Index < Count; Index++, Idp++) {
+
+ //
+ // Map in the broadcast CSR. Note this is not a processor.
+ //
+
+ if (Idp->id == CbusGlobal.broadcast_id) {
+ CbusBroadcastCSR = HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)Idp->pel_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ Idp->pel_start, Idp->pel_size));
+ //
+ // Register the broadcast element's memory
+ // mapped I/O space
+ //
+ continue;
+ }
+
+
+ //
+ // Establish virtual maps for each processor
+ //
+
+ if (Idp->pm) {
+
+ if ((UCHAR)Idp->id == CbusGlobal.bootid) {
+ CbusMappings(0, Idp);
+ }
+ else {
+
+ //
+ // We have an additional processor - set up
+ // his maps and put him in reset. We will
+ // boot him shortly.
+ //
+
+ processor++;
+
+ csr = (PUCHAR)CbusMappings(processor, Idp);
+
+ csr += CbusGlobal.smp_sreset;
+
+ *((PULONG)csr) = CbusGlobal.smp_sreset_val;
+ }
+ }
+
+ //
+ // Establish virtual maps for each I/O and/or
+ // memory board. Note that I/O devices may or may
+ // not have an attached processor - a CPU is NOT required!
+ // memory, on the other hand, may NOT have a processor
+ // on the same board.
+ //
+
+ switch (Idp->io_function) {
+ case IOF_INVALID_ENTRY:
+ case IOF_NO_IO:
+ break;
+
+ case IOF_MEMORY:
+ //
+ // If not a processor, must be a memory card.
+ // Add this memory card to our list
+ // of memory cards in the machine.
+ //
+
+ if (Idp->pm)
+ break;
+
+ CbusMapMemoryRegisters(Idp);
+
+ //
+ // Add this memory range to our list
+ // of additional memory to free later.
+ //
+
+ CbusMemoryFree(Idp->pel_start, Idp->pel_size);
+ break;
+
+ default:
+ //
+ // Add this I/O functionality to our table
+ // to make available to Cbus hardware drivers.
+ // Since I/O card interpretation of the RRD
+ // table is strictly up to the driver, do not
+ // try to register any of this element's space
+ // in the HAL's public consumption list, as we
+ // do for memory and processor cards.
+ //
+
+ if (Idp->pel_features & ELEMENT_HAS_IO) {
+
+ //
+ // If there was an attached processor,
+ // we already mapped in the CSR. If
+ // no attached processor, map in the
+ // CSR now. We'll need it later for
+ // interrupt vector enabling.
+ //
+
+ if (Idp->pm == 0) {
+ csr = HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)Idp->pel_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ Idp->pel_start, Idp->pel_size));
+ }
+
+ CbusIOPresent(
+ (ULONG)Idp->id,
+ (ULONG)Idp->io_function,
+ (ULONG)Idp->io_attr,
+ Idp->pel_start,
+ Idp->pel_size,
+ (PVOID)csr );
+ }
+ break;
+ }
+ }
+
+ //
+ // Ensure that the memory subsystem does not use areas mapped out by
+ // e820 in determining the system memory ranges.
+ //
+ Length = 0xffffffff - CbusGlobal.cbusio;
+ AddMemoryHole(CbusGlobal.cbusio, Length + 1);
+ if (CbusBackend->AddMemoryHoles)
+ (*CbusBackend->AddMemoryHoles)();
+ HalpRegisterAddressUsage (&HalpCbusMemoryResource);
+
+ //
+ // Set total number of processors and their global mask
+ //
+
+ CbusProcessors = processor + 1;
+ CbusProcessorMask = (1 << CbusProcessors) - 1;
+
+ //
+ // Initialize the platform data - done only ONCE.
+ // Backends are expected to initialize the global Cbus
+ // spurious interrupt vector and the irqltovec[] table.
+ // We then pull the dispatch, wake and profile vectors
+ // from the table.
+ //
+
+ (*CbusBackend->InitializePlatform)();
+
+ CbusRequestIPI = CbusBackend->HalRequestInterrupt;
+ CbusRequestSoftwareInterrupt = CbusBackend->HalRequestSoftwareInterrupt;
+ CbusQueryPerformanceCounter = CbusBackend->HalQueryPerformanceCounter;
+
+ ProfileVector = CbusIrqlToVector[PROFILE_LEVEL];
+ CbusClockVector = CbusIrqlToVector[CLOCK2_LEVEL];
+ CbusIpiVector = CbusIrqlToVector[IPI_LEVEL];
+
+ HighVector = CbusIrqlToVector[HIGH_LEVEL];
+ CbusVectorToIrql[HighVector] = HIGH_LEVEL;
+
+ //
+ // Initialize the standard IxProfileVector so that we can
+ // reuse the standard profile code.
+ //
+
+ IxProfileVector = ProfileVector;
+}
+
+VOID
+HalpResetAllProcessors(VOID)
+/*++
+
+Routine Description:
+
+ Called to put all the other processors in reset prior to reboot for
+ the Corollary architectures. Highly architecture specific.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Processor;
+
+ Processor = KeGetPcr()->HalReserved[PCR_PROCESSOR];
+
+ (*CbusBackend->ResetAllOtherProcessors)(Processor);
+}
+
+UCHAR ObsoleteMachine[] = MSG_OBSOLETE;
+
+VOID
+FatalError(
+IN PUCHAR ErrorString
+)
+/*++
+
+Routine Description:
+
+ Called to halt the HAL due to a fatal error, printing out a
+ string describing the cause of the failure.
+
+Arguments:
+
+ ErrorString - Supplies a pointer to failure message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalDisplayString(ErrorString);
+ HalDisplayString(MSG_HALT);
+
+ while (1)
+ ;
+}
+
+static ULONG RRDextsignature[] = { 0xfeedbeef, 0 };
+
+static ULONG RRDsignature[] = { 0xdeadbeef, 0 };
+
+static UCHAR CorollaryOwns[] = "Copyright(C) Corollary, Inc. 1991. All Rights Reserved";
+
+VOID
+CbusReadRRD(VOID)
+
+/*++
+
+ Routine Description:
+
+ For robustness, we check for the following before concluding that
+ we are indeed a Corollary C-bus I or C-bus II licensee supported
+ in multiprocessor mode under this HAL:
+
+ a) Corollary string in the BIOS ROM 64K area (0x000F0000)
+ b) Corollary string in the RRD RAM/ROM 64K area (0xFFFE0000)
+ c) 2 Corollary extended configuration tables
+ in the RRD RAM/ROM 64K area (0xFFFE0000)
+
+ If any of the above checks fail, it is assumed that this machine
+ is either a non-Corollary machine or an early Corollary machine
+ not supported by this HAL. Both of these types of machines are,
+ however, supported (in uniprocessor mode) by the standard
+ uniprocessor HAL.
+
+ If the above checks succeed, then we proceed to fill in various
+ configuration structures for later use.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ PEXT_CFG_HEADER p;
+ PVOID s;
+ ULONG OverrideLength = 0, EntryLength;
+ PUCHAR Bios;
+
+ //
+ // Map in the 64K (== 0x10 pages) of BIOS ROM @ 0xF0000
+ // and scan it for our signature...
+ //
+
+ Bios = (PUCHAR)HalpMapPhysicalMemory ((PVOID)0xF0000, 0x10);
+
+ if (!CbusFindString((PUCHAR)"Corollary", Bios, (LONG)0x10000))
+ KeBugCheck (MISMATCHED_HAL);
+
+ //
+ // Map in the 64K (== 0x10 pages) of RRD @ 0xFFFE0000 and
+ // scan it for our signature. (Note we are taking advantage
+ // of the fact that the lengths are the same, thus reusing
+ // the above PTEs, as opposed to allocating new ones).
+ //
+
+ for (Index = 0; Index < 0x10; Index++) {
+ HalpRemapVirtualAddress(
+ Bios + (Index << PAGE_SHIFT),
+ (PVOID)(0xFFFE0000 + (Index << PAGE_SHIFT)),
+ FALSE);
+ }
+
+ if (!CbusFindString((PUCHAR)"Corollary", Bios, (LONG)0x10000))
+ KeBugCheck (MISMATCHED_HAL);
+
+ //
+ // Map in the 32K (== 8 pages) of RRD RAM information @ 0xE0000,
+ // again reusing previously gained PTEs. Note we are only reusing
+ // the low half this time.
+ //
+
+ for (Index = 0; Index < 8; Index++) {
+ HalpRemapVirtualAddress(
+ Bios + (Index << PAGE_SHIFT),
+ (PVOID)(RRD_RAM + (Index << PAGE_SHIFT)),
+ FALSE);
+ }
+
+ if (!CbusFindString((PUCHAR)CorollaryOwns, Bios, (LONG)0x8000))
+ FatalError(ObsoleteMachine);
+
+ //
+ // At this point, we are assured that it is indeed a
+ // Corollary architecture machine. Search for our
+ // extended configuration tables, note we still search for
+ // the existence of our earliest 'configuration' structure,
+ // ie: the 0xdeadbeef version. This is not to find out where
+ // the memory is, but to find out which Cbus1 megabytes have been
+ // 'jumpered' so that I/O cards can use the RAM address(es) for
+ // their own dual-ported RAM buffers. This early configuration
+ // structure will not be present in Cbus2.
+ //
+ // If there is no extended configuration structure,
+ // this must be an old rom. NO SUPPORT FOR THESE.
+ //
+
+ s = (PVOID)CbusFindString((PUCHAR)RRDsignature, Bios,
+ (LONG)0x8000);
+
+ if (s) {
+ RtlMoveMemory((PVOID)&CbusJumpers, (PVOID)s, JUMPER_SIZE);
+ }
+#if DBG
+ else {
+ //
+ // RRD configuration is not expected on Cbus2, but is for Cbus1
+ //
+ HalDisplayString("HAL: No RRD ROM configuration table\n");
+ }
+#endif
+
+ //
+ // Now go for the extended configuration structure which will tell
+ // us about memory, processors and I/O devices.
+ //
+
+ p = (PEXT_CFG_HEADER)CbusFindString((PUCHAR)RRDextsignature,
+ Bios, (LONG)0x8000);
+
+ if (!p) {
+#if DBG
+ HalDisplayString("HAL: No extended configuration table\n");
+#endif
+ FatalError(ObsoleteMachine);
+ }
+
+ //
+ // Read in the 'extended ID information' table which,
+ // among other things, will give us the processor
+ // configuration.
+ //
+ // Multiple structures are strung together with a "checkword",
+ // "length", and "data" structure. The first null "checkword"
+ // entry marks the end of the extended configuration
+ // structure.
+ //
+ // We are only actively reading two types of structures, and
+ // they MUST be in the following order, although not necessarily
+ // consecutive:
+ //
+ // - ext_id_info
+ //
+ // - ext_cfg_override
+ //
+ // We ignore all other extended configuration entries built
+ // by RRD - they are mainly for early UNIX kernels.
+ //
+
+ do {
+ EntryLength = p->ext_cfg_length;
+
+ switch (p->ext_cfg_checkword) {
+
+ case EXT_ID_INFO:
+
+ CbusValidIDs = CbusReadExtIDs((PEXT_ID_INFO)(p+1),
+ (PEXT_ID_INFO)CbusExtIDTable);
+
+ break;
+
+ case EXT_CFG_OVERRIDE:
+ //
+ // We just copy the size of the structures
+ // we know about. If an rrd tries to pass us
+ // more than we know about, we ignore the
+ // overflow. Underflow is interpreted as
+ // "this must be a pre-XM machine", and such
+ // machines must default to the standard Windows NT
+ // uniprocessor HAL.
+ //
+
+ if (EntryLength < sizeof(EXT_CFG_OVERRIDE_T)) {
+ FatalError(MSG_RRD_ERROR);
+ }
+
+ OverrideLength = MIN(sizeof(EXT_CFG_OVERRIDE_T),
+ EntryLength);
+
+ RtlMoveMemory((PVOID)&CbusGlobal,
+ (PVOID)(p + 1), OverrideLength);
+
+ break;
+
+ case EXT_CFG_END:
+
+ //
+ // If ancient C-bus box, it's not supported in MP mode
+ //
+ if (CbusValidIDs == 0 || OverrideLength == 0) {
+#if DBG
+ HalDisplayString("HAL: Missing RRD tables\n");
+#endif
+ FatalError(ObsoleteMachine);
+ }
+
+ if (CbusMPMachine() == FALSE) {
+#if DBG
+ HalDisplayString("HAL: This Corollary machine is not supported under this HAL\n");
+#endif
+ FatalError(ObsoleteMachine);
+ }
+
+ (*CbusBackend->ParseRRD)((PVOID)CbusExtIDTable,
+ &CbusValidIDs);
+
+
+ CbusEstablishMaps(CbusExtIDTable, CbusValidIDs);
+
+ return;
+
+ default:
+ //
+ // Skip unused or unrecognized configuration entries
+ //
+
+ break;
+ }
+
+ //
+ // Get past the header, add in the length and then
+ // we're at the next entry.
+ //
+ p = (PEXT_CFG_HEADER) ((PUCHAR)(p + 1) + EntryLength);
+
+ } while (1);
+
+ // never reached
+}
+
+VOID
+CbusCheckBusRanges(VOID)
+/*++
+
+Routine Description:
+
+ Check all buses and determine SystemBase
+ for all ranges within all buses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (CbusBackend->CheckBusRanges) {
+ (*CbusBackend->CheckBusRanges)();
+ }
+}
+
+VOID
+CbusAddMemoryHoles(VOID)
+/*++
+
+Routine Description:
+
+ Find the holes in the C-bus memory space that is not
+ useable for device allocation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (CbusBackend->AddMemoryHoles) {
+ (*CbusBackend->AddMemoryHoles)();
+ }
+}
+
+VOID
+CbusInitializeOtherPciBus(VOID)
+/*++
+
+Routine Description:
+
+ Find and initialize other PCI system buses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (CbusBackend->InitializeOtherPciBus) {
+ (*CbusBackend->InitializeOtherPciBus)();
+ }
+}
+
+VOID
+HalpDisableAllInterrupts (VOID)
+/*++
+
+Routine Description:
+ This routine is called during a system crash. The Hal needs all
+ interrupts disabled. Interrupts will NOT be enabled upon leaving
+ this routine, nor is it allowed to turn them back on later. this
+ is a one-time thing, done as the system is coming down.
+
+ Disables all incoming interrupts for the calling processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None - all interrupts are masked off
+
+--*/
+{
+ KfRaiseIrql(HIGH_LEVEL);
+}
+
+
+/*++
+
+Routine Description:
+
+ Called by each processor in turn, to initialize himself.
+
+ - This is the earliest point at which the HAL gets control of
+ the system on each processor.
+
+ - The boot CPU runs it early on in kernel startup. Much later,
+ each additional CPU will also run it shortly after they are
+ brought out of reset during Phase 1.
+
+ - When called by the boot processor, this routine also reads in
+ the global RRD information which pertains to the entire system,
+ including all the processors.
+
+ - Later, the boot cpu will run HalInitSystem --> HalpInitMP.
+ This all occurs at Phase 0.
+
+ Much later, the Phase1 thread runs on the boot cpu, and calls
+ HalInitSystem --> HalpInitMP again, this time at Phase 1.
+ Then the boot cpu runs KeStartAllProcessors. this serially
+ invokes HalStartNextProcessor for each of our additional cpus
+ to start them running KiSystemStartup.
+
+ As each additional processor runs KiSystemStartup, he then
+ runs HalInitializeProcessor. This is when we will enable the
+ additional processor's incoming IPIs. After that, he will proceed
+ to KiInitializeKernel & ExpInitializeExecutive, who then calls
+ HalInitSystem. Each additional processor is always running
+ at Phase 1, never Phase 0.
+
+ The above dictates the actions of these routines:
+
+ - HalInitializeProcessor will read in (ONCE only, ie: only the
+ boot cpu will do this) all of the element space and set up
+ _global_ maps for each processor's CSR. each CPU will map
+ his own _local_ CSR into his HAL pcr. each CPU will
+ enable his incoming IPI here, and disable all other interrupts,
+ including all of this CPU's half-card CBC I/O interrupts.
+
+ - It would be nice to move some of the HalInitializeProcessor Phase0
+ code to HalInitSystem Phase0, but we need full mappings, etc,
+ for entering the debugger from KiSystemStartup early on.
+
+ - KeReadir/LowerIrq's must be available once this function
+ returns. (IPI's are only used once two or more processors are
+ available)
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+HalInitializeProcessor(
+IN ULONG Processor
+)
+{
+ extern VOID i486cacheon(VOID);
+ extern VOID HalpInitializeCoreIntrs(VOID);
+ extern VOID CbusDefaultStall(VOID);
+ extern VOID HalpIpiHandler( VOID );
+ extern PULONG CbusVectorToEoi[MAXIMUM_IDTVECTOR + 1];
+ extern KSPIN_LOCK CbusVectorLock;
+ ULONG i;
+ ELEMENT_T csr;
+ PEXT_ID_INFO Idp;
+ extern KAFFINITY HalpActiveProcessors;
+
+ if (Processor == 0) {
+
+ //
+ // Find our signature and configuration information
+ //
+ CbusReadRRD();
+
+ //
+ // CbusVectorLock needs to be initialized before
+ // any CBC interrupt vectors are given out via
+ // HalGetInterruptVector().
+ //
+ KeInitializeSpinLock(&CbusVectorLock);
+
+ //
+ // Initialize the Eoi addresses to point at a known don't-care.
+ // Any interrupt that gets enabled later will get the correct
+ // EOI address filled in by the hardware backend interrupt
+ // enabling code.
+ //
+ for (i = 0 ; i <= MAXIMUM_IDTVECTOR; i++) {
+ CbusVectorToEoi[i] = &CbusTemp;
+ }
+ CbusTimeStamp = &CbusTemp;
+ }
+
+ //
+ // Default stall execution to something reasonable
+ // until we initialize it later in HalInitSystem.
+ //
+ CbusDefaultStall();
+
+ //
+ // Enable this processor's internal cache - do this
+ // before stall execution is initialized in HalInitSystem.
+ //
+ csr = CbusCSR[Processor];
+
+ Idp = (PEXT_ID_INFO)csr.idp;
+
+ //
+ // Enable the processor internal cache here...
+ //
+ if (Idp->proc_attr == PA_CACHE_ON) {
+ i486cacheon();
+ }
+
+ //
+ // Map this CPU's CSR stuff into his local address space for
+ // fast access. Also his logical # and bit position.
+ //
+
+ (PVOID) KeGetPcr()->HalReserved[PCR_CSR] = CbusCSR[Processor].csr;
+
+ (ULONG) KeGetPcr()->HalReserved[PCR_PROCESSOR] = Processor;
+
+ (ULONG) KeGetPcr()->HalReserved[PCR_BIT] = (1 << Processor);
+
+ (ULONG) KeGetPcr()->HalReserved[PCR_ALL_OTHERS] =
+ (CbusProcessorMask & ~(1 << Processor));
+
+ (PVOID) KeGetPcr()->HalReserved[PCR_LED_ON] = (PVOID)
+ ((PUCHAR)CbusCSR[Processor].csr + CbusGlobal.smp_sled);
+
+ (PVOID) KeGetPcr()->HalReserved[PCR_LED_OFF] = (PVOID)
+ ((PUCHAR)CbusCSR[Processor].csr + CbusGlobal.smp_cled);
+
+ //
+ // Since our architecture is completely symmetric,
+ // update affinity to contain each booted processor.
+ //
+ HalpDefaultInterruptAffinity |= (1 << Processor);
+
+ //
+ // This parameter is returned by the HAL when the system asks
+ // for the HAL's configured resources list.
+ //
+ HalpActiveProcessors = HalpDefaultInterruptAffinity;
+
+ CbusBootedProcessors += 1;
+ CbusBootedProcessorsMask = (1 << CbusBootedProcessors) - 1;
+
+ //
+ // Initialize this processor's data - done ONCE by each processor.
+ //
+ // Typically, this processor's interrupt controller is initialized
+ // here. Also, if it's the first processor, any I/O interrupt
+ // controllers will also be initialized here, ie: EISA bridges or
+ // I/O APICs.
+ //
+ (*CbusBackend->InitializeCPU)(Processor);
+
+ //
+ // This is where we actually enable IPI, APC, DPC and
+ // SPURIOUS interrupts. Device interrupts (like clock and
+ // profile) will not be enabled until HalInitSystem calls
+ // HalpInitializePICs later. Since we are still cli'd, no
+ // interrupt could actually bop us until KiSystemStartup
+ // calls KiInitializeKernel who drops IRQL.
+ //
+ HalpInitializeCoreIntrs();
+}
+
+#define CBUS1_NMI_MASK (PUCHAR)0x70
+#define CBUS1_IO_CHANNEL_CHECK (PUCHAR)0x61
+
+VOID
+CbusClearEISANMI(VOID)
+/*++
+
+Routine Description:
+
+ This function clears the NMI on the EISA bus. Typically this
+ was generated by one of Corollary's "NMI cards", used for
+ debugging purposes. Our caller will have pointed us at the
+ correct bus bridge prior to calling us. note therefore we cannot
+ display anything because we may not be pointing at the default
+ display - if we want to display, we must map the bridge containing
+ the default video adapter!
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR IoChannelCheck;
+
+ WRITE_PORT_UCHAR(CBUS1_NMI_MASK, (UCHAR)0);
+
+ IoChannelCheck = READ_PORT_UCHAR(CBUS1_IO_CHANNEL_CHECK);
+ WRITE_PORT_UCHAR(CBUS1_IO_CHANNEL_CHECK,
+ (UCHAR)((IoChannelCheck & 0xF) | 0x08));
+
+ IoChannelCheck = READ_PORT_UCHAR(CBUS1_IO_CHANNEL_CHECK);
+ WRITE_PORT_UCHAR(CBUS1_IO_CHANNEL_CHECK,
+ (UCHAR)(IoChannelCheck & 0x7));
+
+ //
+ // Since the NMI we are clearing was caused by pressing the button,
+ // which generated an EISA NMI (not a Cbus NMI), don't clear the
+ // NMI in Cbus space.
+ //
+ // COUTB(CbusCSR[Processor].csr, CbusGlobal.smp_cnmi,
+ // CbusGlobal.smp_cnmi_val);
+ //
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbus.h b/private/ntos/nthals/halcbus/i386/cbus.h
new file mode 100644
index 000000000..68ab7d425
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus.h
@@ -0,0 +1,97 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus.h
+
+Abstract:
+
+ Cbus architecture definitions for the Corollary C-bus I & II
+ multiprocessor HAL modules. The common hardware definitions
+ needed for the Windows NT HAL reside here. Hardware
+ architecture-specific definitions are in their respective modules.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+#ifndef _CBUS_
+#define _CBUS_
+//
+// used to read/write the current task priority. reads DO NOT
+// have to be AND'ed with 0xff - this register has been
+// guaranteed by both Corollary (for the CBC) and Intel
+// (for the APIC) so that bits 8-31 will always read zero.
+// (The Corollary guarantee is written, the Intel is verbal).
+//
+// note that this definition is being used both for the
+// 64-bit CBC and the 32-bit APIC, even though the APIC
+// really only has the low 32 bits.
+//
+// Task Priority ranges from a low of 0 (all interrupts unmasked)
+// to a high of 0xFF (all interrupts masked) on both CBC and APIC.
+//
+typedef union _taskpri_t {
+ struct {
+ ULONG pri : 8;
+ ULONG zero : 24;
+ ULONG reserved1 : 32;
+ } ra;
+ struct {
+ ULONG LowDword;
+ ULONG HighDword;
+ } rb;
+} TASKPRI_T, *PTASKPRI;
+
+//
+// max number of C-bus II elements & processors.
+// (processors == elements - broadcast element).
+//
+
+#define MAX_ELEMENT_CSRS 15
+#define MAX_CBUS_ELEMENTS (MAX_ELEMENT_CSRS + 1)
+
+typedef struct _element_t {
+ PVOID csr; // opaque pointer to this CPU's CSR
+ PVOID idp; // opaque pointer to this CPU's RRD info entry
+} ELEMENT_T, PELEMENT;
+
+extern ELEMENT_T CbusCSR[];
+
+//
+// list of memory boards in the system
+//
+typedef struct _memory_card_t {
+
+ PULONG regmap;
+ ULONG io_attr;
+ ULONG physical_start;
+ ULONG physical_size;
+
+} MEMORY_CARD_T, *PMEMORY_CARD;
+
+extern MEMORY_CARD_T CbusMemoryBoards [MAX_ELEMENT_CSRS];
+extern ULONG CbusMemoryBoardIndex;
+
+#define PAGES_TO_BYTES(Page) (Page << PAGE_SHIFT)
+
+#define AddMemoryHole(start, length) \
+ HalpCbusMemoryHole.Element[CbusMemoryHoleIndex].Start = start; \
+ HalpCbusMemoryHole.Element[CbusMemoryHoleIndex].Length = length; \
+ CbusMemoryHoleIndex++;
+
+#define AddMemoryResource(start, length) \
+ HalpCbusMemoryResource.Element[CbusMemoryResourceIndex].Start = start; \
+ HalpCbusMemoryResource.Element[CbusMemoryResourceIndex].Length = length; \
+ CbusMemoryResourceIndex++;
+
+#endif // _CBUS_
diff --git a/private/ntos/nthals/halcbus/i386/cbus.inc b/private/ntos/nthals/halcbus/i386/cbus.inc
new file mode 100644
index 000000000..11484238e
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus.inc
@@ -0,0 +1,277 @@
+;++
+;
+; Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+; Module Name:
+;
+; cbus.inc
+;
+; Abstract:
+;
+; Corollary MP include file
+;
+; Author:
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+;--
+
+
+
+;*****************************
+;
+; Corollary MP defines
+;
+; this should be built from a C header file to minimize
+; the possiblity of falling out of sync.
+;
+;*****************************
+
+
+;
+; Well known virtual address of the task priority register
+;
+
+LOCALAPIC equ 0fffe0000h
+APIC equ ds:[LOCALAPIC]
+
+;
+; The SPURIOUS task priority varies depending on Cbus platform.
+; It is set when we initialize the platform and cannot be declared
+; here. APC and DPC vectors are the same for Cbus1 and Cbus2
+; so they can be inlined here.
+;
+
+APC_TASKPRI equ 01Fh ; Hardware priority of APCs
+DPC_TASKPRI equ 02Fh ; Hardware priority of DPCs
+
+CBUS2_LEVEL_TRIGGERED_INTERRUPT equ 1
+CBUS2_EDGE_TRIGGERED_INTERRUPT equ 2
+
+;
+; Here is the assembly version of the CBUS_NTHAL structure declared in cbus_nt.h
+;
+
+RequestIPI equ 000h
+HalRequestSWIntr equ 004h
+HalQueryPerformanceCounter equ 008h
+HalBootCPU equ 00ch
+
+HalInitializePlatform equ 010h
+HalInitializeCPU equ 014h
+EnableNonDeviceInterrupt equ 018h
+EnableDeviceInterrupt equ 01ch
+
+DisableInterrupt equ 020h
+LinkInterrupt equ 024h
+MapVector equ 028h
+ParseRRD equ 02ch
+
+ResolveNMI equ 030h
+HalInitInterrupts equ 034h
+HalResetAllOtherProcessors equ 038h
+HalInitOtherBuses equ 03ch
+
+HalSetTimeIncrement equ 040h
+HalTranslateAddress equ 044h
+
+;
+; The kernel leaves some space in the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation
+; dependent. this order MUST match the definitions in cbus_nt.h.
+;
+
+PcrE struc
+ PcrNumber dd 0 ; this CPU's logical CPU number
+ PcrBit dd 0 ; this CPU's logical bit number
+ PcrCSR dd 0 ; pointer to this CPU's CSR
+ PcrTaskpri dd 0 ; taskpri reg ptr
+ PcrBroadcast dd 0 ; interrupt everyone but this CPU
+ PcrAllOthers dd 0 ; all other CPUs but this one
+ PcrLEDOn dd 0 ; pointer to this CPU's LED ON
+ PcrLEDOff dd 0 ; pointer to this CPU's LED OFF
+ PcrTickOffset dd 0 ; nsec left before calling
+ ; KeUpdateRunTime on CPU1 or above
+PcrE ends
+
+;
+; Offsets of various registers needed for the context switch when
+; a system reboot is initiated by an additional processor.
+; the space for this array is declared in cbus.c - so bump it there
+; if you need more...
+;
+
+REBOOT_EIP equ 0
+REBOOT_ESP equ 4
+REBOOT_EBP equ 8
+REBOOT_EBX equ 12
+REBOOT_ESI equ 16
+REBOOT_EDI equ 20
+REBOOT_EFL equ 24
+REBOOT_CR3 equ 28
+
+
+;
+; ack the interrupt controller (CBC or APIC).
+;
+; we must derive the bus number so we know which bus' interrupt
+; controller to EOI for systems with multiple I/O busses.
+; so translate the vector to a bus/irqline pair for the EOI...
+;
+; WARNING: for the APIC, this will automatically lower the
+; internal priority register to the level it was prior to
+; receipt of the interrupt.
+;
+; the caller must initialize scratchreg to the interrupting vector.
+;
+
+CBUS_EOI macro reg1, reg2
+local fix_level
+local check_cpu
+local do_eoi
+local no_eoi
+ ;
+ ; reg1 holds the vector that originally interrupted execution,
+ ; now translate the vector to the correct bridge-based EOI address.
+ ;
+ cmp reg1, [_Cbus2ClockVector]
+ je short check_cpu
+ cmp [_Cbus2FixLevelInterrupts], 1
+ jne short do_eoi
+ ;
+ ; first check the polarity of the interrupt (ie. level or edge)
+ ; to determine whether the level-triggered interrupt hardware
+ ; work-around need be applied. need to ensure that no interrupts
+ ; occur while we're performing the workaround for the level-triggered
+ ; interrupt fix. the fix consists of clearing and resetting the
+ ; hardware interrupt map entry for this vector. this will cause
+ ; an internal latch in the CBC to be cleared. this problem will
+ ; be fixed with the PCIB, at which time, RRD will pass a bit in
+ ; the configuration table which will cause this code to no longer
+ ; be executed.
+ ;
+fix_level:
+ movzx reg2, byte ptr [_Cbus2InterruptPolarity + reg1]
+ cmp reg2, CBUS2_LEVEL_TRIGGERED_INTERRUPT
+ jne short do_eoi
+ mov reg2, dword ptr [_CbusVectorToEoi+4*reg1]
+ sub reg2, [_Cbus2EoiToHwmap]
+ mov reg1, dword ptr [_CbusVectorToHwmap+4*reg1]
+ pushfd
+ cli
+ mov dword ptr [reg2], 0
+ mov dword ptr [reg2], reg1 ; must _write_ EOI
+ popfd
+ jmp short no_eoi
+check_cpu:
+ ;
+ ; on C-bus II, the clock interrupt must only be EOI'd by
+ ; a single CPU. make it the boot CPU so that this code
+ ; will work when only 1 CPU is present.
+ ;
+ cmp dword ptr PCR[PcHal.PcrNumber], 0
+ jne short no_eoi
+ cmp [_Cbus2FixLevelInterrupts], 1
+ je short fix_level
+do_eoi:
+ mov reg2, dword ptr [_CbusVectorToEoi+4*reg1]
+ mov dword ptr dword ptr [reg2], reg1 ; must _write_ EOI
+no_eoi:
+endm
+
+POKE_LEDS macro reg1, reg2
+local ledset
+ mov reg1, PCR[PcPrcb] ; point at Prcb
+ mov reg2, [reg1].PbCurrentThread ; Current thread
+ cmp reg2, [reg1].PbIdleThread ; Idle Thread
+ je short @f
+
+ mov reg1, PCR[PcHal.PcrLEDOn] ; get my LED ON address
+ mov dword ptr [reg1], 1 ; set it
+ jmp short ledset
+
+@@:
+ mov reg1, PCR[PcHal.PcrLEDOff] ; get my LED OFF address
+ mov dword ptr [reg1], 0 ; set it
+ledset:
+ endm
+
+;
+; Declare all the externs that most of our MASM code will be using
+;
+
+ extrn _CbusLocalApic: DWORD
+ extrn _CbusApicRedirPort: DWORD
+ extrn _CbusIOApic: DWORD
+
+ extrn _ProfileVector: DWORD
+
+ ;
+ ; vectors used to communicate reboot and redirection table requested
+ ; changes to the boot processor. also the global interprocessor ; interrupt vector that any processor can use to interrupt any other
+ ; processor(s).
+ ;
+ extrn _CbusIpiVector: DWORD
+ extrn _CbusRebootVector: DWORD
+ extrn _CbusRedirVector: DWORD
+
+ extrn _CbusClockVector: DWORD
+ extrn _CbusQueryPerformanceCounter: DWORD
+ extrn _CbusVectorToIrql: DWORD
+ extrn _CbusIrqlToVector: DWORD
+ extrn _CbusBackend: DWORD
+ extrn _CbusRequestIPI: DWORD
+ extrn _CbusRequestSoftwareInterrupt: DWORD
+ extrn _CbusProcessorMask: DWORD
+ extrn _CbusBootedProcessors: DWORD
+ extrn _CbusRebootRegs: DWORD
+
+ extrn _Cbus2BridgesFound: DWORD
+ extrn _Cbus2SendIPI: DWORD
+ extrn _Cbus2Poke8042: DWORD
+ extrn _Cbus2IrqlToCbus2Addr: DWORD
+ extrn _Cbus2FixLevelInterrupts: DWORD
+ extrn _Cbus2CheckSpuriousClock: DWORD
+ extrn _Cbus2EnableBroadcast: DWORD
+ extrn _Cbus2ClockVector: DWORD
+ extrn _Cbus2InterruptPolarity: DWORD
+ extrn _Cbus2EoiToHwmap: DWORD
+ extrn _CbusTimeStamp: DWORD
+ extrn _Cbus2TimeStamp0: DWORD
+ extrn _CbusVectorToEoi: DWORD
+ extrn _CbusVectorToHwmap: DWORD
+ extrn _CbusProcessors: DWORD
+
+ extrn _HalpFindFirstSetRight: BYTE
+ extrn _Halp8254Lock: DWORD
+ extrn _MppIDT: DWORD
+ extrn _MpLowStub: DWORD
+ extrn _MpLowStubPhysicalAddress: DWORD
+ extrn _MpCount: DWORD
+
+;
+; Declare all the functions that our MASM code will be calling
+;
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+
+ EXTRNP _HalEnableSystemInterrupt, 3
+ EXTRNP _HalDisableSystemInterrupt, 2
+ EXTRNP _HalpAcquireCmosSpinLock, 0
+ EXTRNP _HalpReleaseCmosSpinLock, 0
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP Kei386EoiHelper,0,IMPORT
+
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+
+ EXTRNP _ExAllocatePool,2,IMPORT
+
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+ EXTRNP _HalpProfileInterrupt2ndEntry,0
diff --git a/private/ntos/nthals/halcbus/i386/cbus1.c b/private/ntos/nthals/halcbus/i386/cbus1.c
new file mode 100644
index 000000000..0c64667bc
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus1.c
@@ -0,0 +1,1870 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus1.c
+
+Abstract:
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for the
+ Corollary Cbus1 MP machines under Windows NT.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 05-Oct-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cbusrrd.h" // HAL <-> RRD interface definitions
+#include "cbus.h" // Cbus1 & Cbus2 max number of elements is here
+#include "cbus1.h" // Cbus1 hardware architecture stuff
+#include "cbus_nt.h" // C-bus NT-specific implementation stuff
+#include "bugcodes.h"
+#include "stdio.h"
+#include "cbusnls.h"
+#include "cbusapic.h" // Cbus APIC generic definitions
+
+
+PULONG
+CbusApicVectorToEoi(
+IN ULONG Vector
+);
+
+VOID
+Cbus1PerfInterrupt(VOID);
+
+PVOID
+Cbus1LinkVector(
+IN PBUS_HANDLER Bus,
+IN ULONG Vector,
+IN ULONG Irqline
+);
+
+VOID
+Cbus1InitializeStall(IN ULONG);
+
+VOID
+Cbus1InitializeClock(VOID);
+
+VOID
+Cbus1InitializePerf(VOID);
+
+ULONG
+Cbus1QueryInterruptPolarity(VOID);
+
+VOID
+Cbus1BootCPU(
+IN ULONG Processor,
+IN ULONG RealModeSegOff
+);
+
+VOID
+Cbus1InitializePlatform(VOID);
+
+VOID
+CbusPreparePhase0Interrupts(
+IN ULONG,
+IN ULONG,
+IN PVOID
+);
+
+VOID
+Cbus1InitializeCPU(
+IN ULONG Processor
+);
+
+VOID
+Cbus1ECCEnable(VOID);
+
+VOID
+Cbus1ECCDisable(VOID);
+
+PUCHAR
+CbusIDtoCSR(
+IN ULONG ArbID
+);
+
+VOID
+Cbus1Arbitrate(VOID);
+
+VOID
+Cbus1HandleJumpers();
+
+VOID
+Cbus1ParseRRD(
+IN PEXT_ID_INFO Table,
+IN OUT PULONG Count
+);
+
+PVOID
+Cbus1FindDeadID(
+IN ULONG ArbID
+);
+
+VOID
+Cbus1InitializePlatform();
+
+VOID
+Cbus1InitializeDeviceIntrs(
+IN ULONG Processor
+);
+
+VOID
+Cbus1SetupPrivateVectors(VOID);
+
+VOID
+CbusRebootHandler( VOID );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, Cbus1SetupPrivateVectors)
+#pragma alloc_text(INIT, Cbus1BootCPU)
+#pragma alloc_text(INIT, Cbus1InitializePlatform)
+#pragma alloc_text(INIT, Cbus1InitializeCPU)
+#pragma alloc_text(INIT, Cbus1ECCEnable)
+#pragma alloc_text(INIT, Cbus1ECCDisable)
+#pragma alloc_text(INIT, CbusIDtoCSR)
+#pragma alloc_text(INIT, Cbus1Arbitrate)
+#pragma alloc_text(INIT, Cbus1HandleJumpers)
+#pragma alloc_text(INIT, Cbus1ParseRRD)
+#pragma alloc_text(INIT, Cbus1FindDeadID)
+#pragma alloc_text(INIT, Cbus1InitializeDeviceIntrs)
+#pragma alloc_text(INIT, Cbus1QueryInterruptPolarity)
+#endif
+
+extern PULONG CbusVectorToEoi[MAXIMUM_IDTVECTOR + 1];
+
+PUCHAR Cbus1ID0CSR;
+
+//
+// Used for holding IDs of disabled Cbus1 processors. This is
+// done to detect whether the user has inserted any obsolete
+// boards, since they can still win arbitrations. Thus, we can
+// detect disabled arbitration winners from just plain broken systems.
+//
+PEXT_ID_INFO Cbus1DeadIDs[MAX_ELEMENT_CSRS];
+ULONG Cbus1DeadIDsIndex;
+
+//
+// The limited priority scheme employed by the Intel APIC is as follows:
+//
+// there are 256 vectors, but since the APIC ignores the least
+// significant 4 bits, we really only have 16 distinct priority levels
+// to work with.
+//
+// processor traps, NT system calls and APC/DPC use up the first 0x30 vectors.
+// after the required Power, IPI, Clock and Profiling levels,
+// there really isn't much left. see the picture below:
+//
+// APC: 0x1F (lowest priority)
+// DPC: 0x2F
+//
+// Lowest Priority EISA: 0x30 real devices here
+// Highest Priority EISA: 0xBF real devices here
+//
+// EISA Profile: 0xCF
+// EISA Clock(Perf Counter): 0xDD
+// APIC Clock (System Timer): 0xDF
+// Spurious Vector: 0xEC
+// CBUS1_REBOOT_IPI: 0xED
+// CBUS1_REDIR_IPI: 0xEE
+// IPI: 0xEF
+// Power: 0xFF
+// High: 0xFF (highest priority)
+//
+// we have only 9 distinct priority levels left!!!
+//
+// due to this APIC shortcoming, we are forced to share levels between
+// various EISA irq lines. each line will be assigned a different vector,
+// and the IRQL mappings will work, but they will not be optimal.
+//
+// note that the Cbus2 CBC suffers from none of these shortcomings.
+//
+
+//
+// set unused irql levels to the priority of the irql level above it
+// so that if they are inadvertently called from the kernel,
+// executive or drivers, nothing bad will happen.
+//
+
+#define UNUSED_PRI CBUS1_PROFILE_TASKPRI
+
+#define CBUS1_DEVICELOW_TASKPRI 0x30
+#define CBUS1_DEVICEHI_TASKPRI 0xBF
+
+#define CBUS1_IRQ2_TASKPRI 0xCE // not expected to happen
+#define CBUS1_PROFILE_TASKPRI 0xCF
+#define CBUS1_PERF_TASKPRI 0xDD // also in cb1stall.asm
+#define CBUS1_CLOCK_TASKPRI 0xDF
+
+#define CBUS1_REBOOT_IPI 0xED
+#define CBUS1_REDIR_IPI 0xEE
+#define CBUS1_IPI_TASKPRI 0xEF
+
+#define CBUS1_POWER_TASKPRI 0xFE
+
+//
+// we don't really care what the spurious value is, but the APIC
+// spec seems to imply that this must be hardcoded at 0xff for future
+// compatibility.
+//
+#define CBUS1_SPURIOUS_TASKPRI 0xFF
+
+//
+// since we have 9 priority levels and 13 irq lines, priorities are ordered
+// in buckets as follows, from high priority to low priority:
+//
+// highest priority to keyboard: (usually irq1)
+//
+// next highest priority to serial port/mouse/network card. (usually irq3)
+//
+// next highest priority to serial port/network card. (usually irq4)
+//
+// next highest priority to SCSI/hard disks/networks. (usually irq9)
+//
+// next highest priority to SCSI/hard disks/networks. (usually irqA)
+//
+// next highest priority to SCSI/hard disks/networks. (usually irqB or C)
+//
+// next highest priority to SCSI/hard disks/networks. (usually irqD or E)
+//
+// next highest priority to SCSI/disks/networks/printers. (usually irqF or 5)
+//
+// lowest device priority to floppy, printers. (usually irq6 or 7)
+//
+#define EISA_IRQ0PRI CBUS1_PERF_TASKPRI // 8254 line (perf ctr) & pri
+#define EISA_IRQ1PRI (CBUS1_DEVICELOW_TASKPRI + 0x80)
+#define EISA_IRQ2PRI CBUS1_IRQ2_TASKPRI
+#define EISA_IRQ3PRI (CBUS1_DEVICELOW_TASKPRI + 0x70)
+
+#define EISA_IRQ4PRI (CBUS1_DEVICELOW_TASKPRI + 0x60)
+#define EISA_IRQ5PRI (CBUS1_DEVICELOW_TASKPRI + 0x10)
+#define EISA_IRQ6PRI (CBUS1_DEVICELOW_TASKPRI + 0x01)
+#define EISA_IRQ7PRI (CBUS1_DEVICELOW_TASKPRI + 0x00)
+
+#define EISA_IRQ8PRI CBUS1_PROFILE_TASKPRI // profile line & priority
+#define EISA_IRQ9PRI (CBUS1_DEVICELOW_TASKPRI + 0x50)
+#define EISA_IRQAPRI (CBUS1_DEVICELOW_TASKPRI + 0x40)
+#define EISA_IRQBPRI (CBUS1_DEVICELOW_TASKPRI + 0x31)
+
+#define EISA_IRQCPRI (CBUS1_DEVICELOW_TASKPRI + 0x30)
+#define EISA_IRQDPRI (CBUS1_DEVICELOW_TASKPRI + 0x21)
+#define EISA_IRQEPRI (CBUS1_DEVICELOW_TASKPRI + 0x20)
+#define EISA_IRQFPRI (CBUS1_DEVICELOW_TASKPRI + 0x11)
+
+//
+// an EISA_IRQ2PRI is declared above just to flesh out arrays that will
+// be indexed by irq line. the EISA_IRQ2PRI should never actually be used
+//
+
+#if (HIGH_LEVEL + 1 != 32)
+Cbus1IrqlToVector[] NOT dimensioned and indexed properly
+#endif
+
+ULONG Cbus1IrqlToVector[HIGH_LEVEL + 1 ] = {
+
+ LOW_TASKPRI, APC_TASKPRI, DPC_TASKPRI, EISA_IRQ7PRI,
+ EISA_IRQ6PRI, EISA_IRQ5PRI, EISA_IRQFPRI, EISA_IRQEPRI,
+ EISA_IRQDPRI, EISA_IRQCPRI, EISA_IRQBPRI, EISA_IRQAPRI,
+ EISA_IRQ9PRI, EISA_IRQ4PRI, EISA_IRQ3PRI, EISA_IRQ1PRI,
+
+ EISA_IRQ2PRI, UNUSED_PRI, UNUSED_PRI, UNUSED_PRI,
+ UNUSED_PRI, UNUSED_PRI, UNUSED_PRI, UNUSED_PRI,
+ UNUSED_PRI, UNUSED_PRI, UNUSED_PRI, CBUS1_PROFILE_TASKPRI,
+ CBUS1_CLOCK_TASKPRI, CBUS1_IPI_TASKPRI, CBUS1_POWER_TASKPRI, HIGH_TASKPRI,
+
+};
+
+ULONG Cbus1IrqPolarity;
+
+#define IRQPERFLINE 0
+#define EISA_IRQLINES 16
+
+typedef struct _cbus1_irqline_t {
+ ULONG Vector;
+ KIRQL Irql;
+} CBUS1_IRQLINE_T, *PCBUS1_IRQLINE;
+
+//
+// map EISA irqline to Cbus1 programmable vectors & IRQL levels,
+// as defined above.
+//
+
+#define FIRST_DEVICE_LEVEL (DISPATCH_LEVEL+1)
+
+CBUS1_IRQLINE_T Cbus1Irqlines[EISA_IRQLINES] =
+{
+ EISA_IRQ0PRI, CLOCK2_LEVEL,
+ EISA_IRQ1PRI, FIRST_DEVICE_LEVEL+12,
+ EISA_IRQ2PRI, FIRST_DEVICE_LEVEL+13,
+ EISA_IRQ3PRI, FIRST_DEVICE_LEVEL+11,
+
+ EISA_IRQ4PRI, FIRST_DEVICE_LEVEL+10,
+ EISA_IRQ5PRI, FIRST_DEVICE_LEVEL+2,
+ EISA_IRQ6PRI, FIRST_DEVICE_LEVEL+1,
+ EISA_IRQ7PRI, FIRST_DEVICE_LEVEL,
+
+ EISA_IRQ8PRI, PROFILE_LEVEL,
+ EISA_IRQ9PRI, FIRST_DEVICE_LEVEL+9,
+ EISA_IRQAPRI, FIRST_DEVICE_LEVEL+8,
+ EISA_IRQBPRI, FIRST_DEVICE_LEVEL+7,
+
+ EISA_IRQCPRI, FIRST_DEVICE_LEVEL+6,
+ EISA_IRQDPRI, FIRST_DEVICE_LEVEL+5,
+ EISA_IRQEPRI, FIRST_DEVICE_LEVEL+4,
+ EISA_IRQFPRI, FIRST_DEVICE_LEVEL+3
+};
+
+PUCHAR Cbus1ResetVector;
+
+extern ULONG CbusRedirVector;
+extern ULONG CbusRebootVector;
+
+extern ADDRESS_USAGE HalpCbusMemoryResource;
+extern ULONG CbusMemoryResourceIndex;
+
+//
+// defines for the Cbus1 ECC syndrome
+//
+#define MULTIBIT 3
+#define DOUBLEBIT 2
+#define SINGLEBIT 1
+#define NOECCERROR 0x7f
+
+//
+// defines for the Cbus1 ECC error register
+//
+typedef struct _extmear_t {
+ ULONG offset:24;
+ ULONG SyndromeHigh:5;
+ ULONG SyndromeLow:2;
+ ULONG simmtype:1;
+} EXTMEAR_T, *PEXTMEAR;
+
+UCHAR Cbus1EdacSyndrome[] = {
+
+MULTIBIT, /* 00 */ DOUBLEBIT, /* 01 */ DOUBLEBIT, /* 02 */ MULTIBIT, /* 03 */
+DOUBLEBIT, /* 04 */ MULTIBIT, /* 05 */ MULTIBIT, /* 06 */ DOUBLEBIT, /* 07 */
+DOUBLEBIT, /* 08 */ MULTIBIT, /* 09 */ SINGLEBIT, /* 0A */ DOUBLEBIT, /* 0B */
+MULTIBIT, /* 0C */ DOUBLEBIT, /* 0D */ DOUBLEBIT, /* 0E */ SINGLEBIT, /* 0F */
+DOUBLEBIT, /* 10 */ MULTIBIT, /* 11 */ SINGLEBIT, /* 12 */ DOUBLEBIT, /* 13 */
+SINGLEBIT, /* 14 */ DOUBLEBIT, /* 15 */ DOUBLEBIT, /* 16 */ SINGLEBIT, /* 17 */
+SINGLEBIT, /* 18 */ DOUBLEBIT, /* 19 */ DOUBLEBIT, /* 1A */ SINGLEBIT, /* 1B */
+DOUBLEBIT, /* 1C */ SINGLEBIT, /* 1D */ MULTIBIT, /* 1E */ DOUBLEBIT, /* 1F */
+DOUBLEBIT, /* 20 */ MULTIBIT, /* 21 */ SINGLEBIT, /* 22 */ DOUBLEBIT, /* 23 */
+MULTIBIT, /* 24 */ DOUBLEBIT, /* 25 */ DOUBLEBIT, /* 26 */ SINGLEBIT, /* 27 */
+SINGLEBIT, /* 28 */ DOUBLEBIT, /* 29 */ DOUBLEBIT, /* 2A */ SINGLEBIT, /* 2B */
+DOUBLEBIT, /* 2C */ SINGLEBIT, /* 2D */ MULTIBIT, /* 2E */ DOUBLEBIT, /* 2F */
+SINGLEBIT, /* 30 */ DOUBLEBIT, /* 31 */ DOUBLEBIT, /* 32 */ MULTIBIT, /* 33 */
+DOUBLEBIT, /* 34 */ SINGLEBIT, /* 35 */ MULTIBIT, /* 36 */ DOUBLEBIT, /* 37 */
+DOUBLEBIT, /* 38 */ MULTIBIT, /* 39 */ MULTIBIT, /* 3A */ DOUBLEBIT, /* 3B */
+MULTIBIT, /* 3C */ DOUBLEBIT, /* 3D */ DOUBLEBIT, /* 3E */ SINGLEBIT, /* 3F */
+DOUBLEBIT, /* 40 */ MULTIBIT, /* 41 */ MULTIBIT, /* 42 */ DOUBLEBIT, /* 43 */
+MULTIBIT, /* 44 */ DOUBLEBIT, /* 45 */ DOUBLEBIT, /* 46 */ MULTIBIT, /* 47 */
+MULTIBIT, /* 48 */ DOUBLEBIT, /* 49 */ DOUBLEBIT, /* 4A */ SINGLEBIT, /* 4B */
+DOUBLEBIT, /* 4C */ MULTIBIT, /* 4D */ SINGLEBIT, /* 4E */ DOUBLEBIT, /* 4F */
+MULTIBIT, /* 50 */ DOUBLEBIT, /* 51 */ DOUBLEBIT, /* 52 */ SINGLEBIT, /* 53 */
+DOUBLEBIT, /* 54 */ SINGLEBIT, /* 55 */ SINGLEBIT, /* 56 */ DOUBLEBIT, /* 57 */
+DOUBLEBIT, /* 58 */ SINGLEBIT, /* 59 */ SINGLEBIT, /* 5A */ DOUBLEBIT, /* 5B */
+SINGLEBIT, /* 5C */ DOUBLEBIT, /* 5D */ DOUBLEBIT, /* 5E */ SINGLEBIT, /* 5F */
+MULTIBIT, /* 60 */ DOUBLEBIT, /* 61 */ DOUBLEBIT, /* 62 */ SINGLEBIT, /* 63 */
+DOUBLEBIT, /* 64 */ SINGLEBIT, /* 65 */ SINGLEBIT, /* 66 */ DOUBLEBIT, /* 67 */
+DOUBLEBIT, /* 68 */ SINGLEBIT, /* 69 */ SINGLEBIT, /* 6A */ DOUBLEBIT, /* 6B */
+SINGLEBIT, /* 6C */ DOUBLEBIT, /* 6D */ DOUBLEBIT, /* 6E */ SINGLEBIT, /* 6F */
+DOUBLEBIT, /* 70 */ SINGLEBIT, /* 71 */ MULTIBIT, /* 72 */ DOUBLEBIT, /* 73 */
+SINGLEBIT, /* 74 */ MULTIBIT, /* 75 */ DOUBLEBIT, /* 76 */ SINGLEBIT, /* 77 */
+MULTIBIT, /* 78 */ DOUBLEBIT, /* 79 */ DOUBLEBIT, /* 7A */ SINGLEBIT, /* 7B */
+DOUBLEBIT, /* 7C */ SINGLEBIT, /* 7D */ SINGLEBIT, /* 7E */ NOECCERROR,/* 7F */
+
+};
+
+VOID
+FatalError(
+IN PUCHAR ErrorString
+);
+
+VOID
+CbusHardwareFailure(
+IN PUCHAR HardwareMessage
+);
+
+VOID
+CbusClockInterruptPx( VOID );
+
+VOID
+HalpProfileInterruptPx( VOID );
+
+VOID
+Cbus1Boot1(
+IN ULONG Processor,
+IN PQUAD Dest,
+IN PQUAD Code,
+IN ULONG ResetAddress,
+IN ULONG ResetValue
+);
+
+extern ULONG Cbus1Boot1End;
+
+VOID
+Cbus1Boot2(
+IN ULONG Processor,
+IN PQUAD Dest,
+IN PQUAD Code,
+IN ULONG ResetAddress,
+IN ULONG ResetValue
+);
+
+//
+// defines for resetting the keyboard controller used
+// in Cbus1ResetAllOtherProcessors().
+//
+#define RESET 0xfe
+#define KEYBPORT (PUCHAR )0x64
+
+#define IRQ0 0
+#define IRQ8 8
+
+/*++
+
+Routine Description:
+
+ This routine is called only once from HalInitProcessor() at Phase 0
+ by the boot cpu. All other cpus are still in reset.
+
+ software(APC, DPC, wake) and IPI vectors have already been initialized
+ and enabled.
+
+ all we're doing here is setting up some software structures for two
+ EISA interrupts (8254 perfctr and RTC profile) so they can be enabled later.
+
+ The bus handler data structures are not initialized until Phase 1,
+ so HalGetInterruptVector() may not be called before Phase1.
+
+ Hence we cannot pass a valid BusHandler parameter to the Link code.
+ That's ok, since it doesn't currently use it.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus1SetupPrivateVectors(VOID)
+{
+ PVOID Opaque;
+ extern ULONG ProfileVector;
+
+ //
+ // we are defaulting to the EISA (or MCA) bridge 0
+ // for all of these interrupts which need enabling during Phase 0.
+ //
+
+ Opaque = Cbus1LinkVector((PBUS_HANDLER)0, CBUS1_PERF_TASKPRI, IRQ0);
+ CbusPreparePhase0Interrupts(CBUS1_PERF_TASKPRI, IRQ0, Opaque);
+
+ Opaque = Cbus1LinkVector((PBUS_HANDLER)0, ProfileVector, IRQ8);
+ CbusPreparePhase0Interrupts(ProfileVector, IRQ8, Opaque);
+}
+
+VOID
+Cbus1BootCPU(
+IN ULONG Processor,
+IN ULONG RealModeSegOff
+)
+/*++
+
+Routine Description:
+
+ Remove reset from the specified processor, allowing him to boot,
+ beginning execution at the specified start address. This ends up
+ being tricky due to cache flushing concepts generally hidden in ROMs,
+ but in the HAL for the Cbus1 platform.
+
+Arguments:
+
+ Processor - Supplies a logical processor number to boot
+
+ StartAddress - Supplies a start address containing real-mode code
+ for the processor to execute.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PHYSICAL_ADDRESS Bootcode;
+ ULONG BeginAddress, EndAddress;
+ ULONG BeginCacheLineIndex;
+ ULONG EndCacheLineIndex;
+ UCHAR StartVectorCode[5];
+ PVOID PhysicalResetVector;
+ ULONG ip = RealModeSegOff & 0xFFFF;
+ ULONG cs = ((RealModeSegOff >> 16) & 0xFFFF);
+ ULONG CacheFlush = CBUS1_CACHE_SIZE;
+ ULONG LastCacheLineIndex;
+
+ //
+ // if we haven't yet mapped in the reset vector, do so now.
+ //
+
+ if (!Cbus1ResetVector) {
+
+ PhysicalResetVector =
+ (PUCHAR)CbusGlobal.resetvec - CBUS1_CACHE_LINE;
+
+ Cbus1ResetVector = (PUCHAR)HalpMapPhysicalMemory (
+ PhysicalResetVector, 1);
+ }
+
+
+ //
+ // build start vector (entry offset followed by cs load base)
+ //
+ StartVectorCode[0] = (UCHAR)0xea;
+ StartVectorCode[1] = (UCHAR)ip & 0xff;
+ StartVectorCode[2] = (UCHAR)(ip >> 8) & 0xff;
+ StartVectorCode[3] = (UCHAR)cs & 0xff;
+ StartVectorCode[4] = (UCHAR)(cs >> 8) & 0xff;
+
+ //
+ // determine which low-level boot function to use. although
+ // the 2 functions are exactly the same, we must make sure that
+ // we don't call one which would cause the cache line containing
+ // the reset vector to be evicted prematurely.
+ //
+
+ LastCacheLineIndex = ((CacheFlush - 1) >> CBUS1_CACHE_SHIFT);
+
+ Bootcode = MmGetPhysicalAddress(&Cbus1Boot1);
+ BeginAddress = Bootcode.LowPart;
+ BeginCacheLineIndex =
+ (BeginAddress & (CacheFlush - 1)) >> CBUS1_CACHE_SHIFT;
+
+ Bootcode = MmGetPhysicalAddress((PVOID)&Cbus1Boot1End);
+ EndAddress = Bootcode.LowPart;
+ EndCacheLineIndex =
+ (EndAddress & (CacheFlush - 1)) >> CBUS1_CACHE_SHIFT;
+
+ //
+ // in order to startup additional CPUs, we need to write its
+ // startup vector in the last 16 bytes of the memory
+ // address space. this memory may or may not be
+ // present. more specifically, a partially populated
+ // memory card which doesn't have memory at the end of
+ // the space, ie: a memory card at 48Mb->56Mb in a
+ // system with a 64Mb upper limit) will cause an ecc
+ // error if ecc is enabled.
+ //
+ // thus we must disable ecc to prevent such boards from
+ // generating ecc errors. note that the errors are only
+ // generated on the read when we initially fill the
+ // startvector. it's ok to enable ecc after startup
+ // even though the cacheline containing the StartVectorCode
+ // has not necessarily been flushed. when it is flushed,
+ // it will go in the bit bucket and ecc errors are
+ // generated only on reads (not writes).
+ //
+
+ Cbus1ECCDisable();
+
+ //
+ // call Cbus1Boot1 if there is no wrap...
+ // see the detailed comment at the top of Cbus1Boot1 for more details.
+ //
+ if ((EndCacheLineIndex != LastCacheLineIndex) && EndAddress > BeginAddress) {
+ Cbus1Boot1(Processor,
+ (PQUAD) Cbus1ResetVector,
+ (PQUAD) StartVectorCode,
+ (ULONG)CbusCSR[Processor].csr +
+ CbusGlobal.smp_creset,
+ CbusGlobal.smp_creset_val);
+ }
+ else {
+ Cbus1Boot2(Processor,
+ (PQUAD) Cbus1ResetVector,
+ (PQUAD) StartVectorCode,
+ (ULONG)CbusCSR[Processor].csr +
+ CbusGlobal.smp_creset,
+ CbusGlobal.smp_creset_val);
+ }
+
+ Cbus1ECCEnable();
+}
+
+VOID
+Cbus1InitializePlatform(VOID)
+/*++
+
+Routine Description:
+
+ Overlay the irql-to-vector mappings with the Cbus1 vector maps.
+ Give all additional processors proper bus arbitration IDs.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RtlMoveMemory( (PVOID)CbusIrqlToVector,
+ (PVOID)Cbus1IrqlToVector,
+ (HIGH_LEVEL + 1) * sizeof (ULONG));
+
+ Cbus1IrqPolarity = Cbus1QueryInterruptPolarity();
+
+ //
+ // if there are any Cbus1 additional processors present,
+ // put them into reset and arbitrate them so they get
+ // branded with proper IDs.
+ //
+ if (CbusProcessors > 1)
+ Cbus1Arbitrate();
+
+ CbusRedirVector = CBUS1_REDIR_IPI;
+ CbusRebootVector = CBUS1_REBOOT_IPI;
+}
+
+
+VOID
+Cbus1InitializeCPU(
+IN ULONG Processor
+)
+/*++
+
+Routine Description:
+
+ Initialize this processor's local and I/O APIC units.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CbusInitializeLocalApic(Processor, CBUS1_LOCAL_APIC_LOCATION,
+ CBUS1_SPURIOUS_TASKPRI);
+
+ //
+ // Only the boot processor needs to initialize the I/O APIC
+ // on the EISA bridge. Each additional processor just needs
+ // to give his I/O APIC (since it won't be used) an arbitration ID.
+ //
+
+ if (Processor == 0) {
+ CbusInitializeIOApic(Processor, CBUS1_IO_APIC_LOCATION,
+ CBUS1_REDIR_IPI, CBUS1_REBOOT_IPI, Cbus1IrqPolarity);
+ }
+ else {
+ KiSetHandlerAddressToIDT(CBUS1_REBOOT_IPI, CbusRebootHandler);
+ HalEnableSystemInterrupt(CBUS1_REBOOT_IPI, IPI_LEVEL, Latched);
+ CbusApicBrandIOUnitID(Processor);
+ }
+}
+
+
+BOOLEAN
+Cbus1EnableNonDeviceInterrupt(
+IN ULONG Vector
+)
+/*++
+
+Routine Description:
+
+ Determine if the supplied vector belongs to an EISA device - if so,
+ then the corresponding I/O APIC entry will need to be modified to
+ enable the line, so return FALSE here. Otherwise, no work is needed,
+ so just return TRUE immediately.
+
+Arguments:
+
+ Vector - Supplies a vector number to enable
+
+Return Value:
+
+ TRUE if the vector was enabled, FALSE if not.
+
+--*/
+{
+ //
+ // If pure software interrupt, no action needed.
+ // Note both APIC timer interrupts and IPIs are
+ // treated as "software" interrupts. Note that
+ // an EOI will still be needed, so set that up here.
+ //
+
+ if (Vector != CBUS1_SPURIOUS_TASKPRI)
+ CbusVectorToEoi[Vector] = CbusApicVectorToEoi(Vector);
+
+ if (Vector < CBUS1_DEVICELOW_TASKPRI || Vector >= CBUS1_CLOCK_TASKPRI) {
+ return TRUE;
+ }
+
+ //
+ // indicate that Enable_Device_Interrupt will need to be run
+ // in order to enable this vector, as it associated with an I/O
+ // bus device which will need enabling within a locked critical
+ // section.
+ //
+
+ return FALSE;
+}
+
+
+VOID
+Cbus1EnableDeviceInterrupt(
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG FirstAttach,
+IN USHORT BusNumber,
+IN USHORT Irqline
+)
+/*++
+
+Routine Description:
+
+ Enable the specified interrupt for the calling processor.
+ Remember only the boot processor can add/remove processors from
+ the I/O APIC's redirection entries.
+
+ This operation is trivial for the boot processor. However, additional
+ processors must interrupt the boot processor with an "enable interrupt"
+ request and then spin waiting for the boot processor to acknowledge that
+ the entry has been modified. Note that the caller holds the HAL's
+ CbusVectorLock at CLOCK_LEVEL on entry.
+
+Arguments:
+
+ Vector - Supplies a vector number to enable
+
+ HardwarePtr - Supplies a redirection entry address
+
+ FirstAttach - TRUE if this is the first processor to enable the
+ specified vector
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN LowestInGroup;
+ BOOLEAN LevelTriggered;
+
+ //
+ // Only 1 I/O bus in Cbus1 systems, only Cbus2 can have more
+ //
+ ASSERT(BusNumber == 0);
+
+ //
+ // Set up the EOI address
+ //
+ CbusVectorToEoi[Vector] = CbusApicVectorToEoi(Vector);
+
+ //
+ // Enable APIC LIG arbitration delay (at least 4 cycles on
+ // our 10Mhz APIC bus, which is 0.4 microseconds).
+ //
+
+ switch (Vector) {
+
+ case CBUS1_PERF_TASKPRI:
+ case CBUS1_CLOCK_TASKPRI:
+ case CBUS1_PROFILE_TASKPRI:
+ case CBUS1_POWER_TASKPRI:
+
+ // These stay in APIC "FIXED" mode
+
+ LowestInGroup = FALSE;
+ break;
+
+ default:
+
+ // All others utilize APIC "Lowest-In-Group"
+
+ LowestInGroup = TRUE;
+ break;
+ }
+
+ //
+ // Note that non-EISA interrupts (ie: APIC clocks or IPI) are
+ // correctly handled in the EnableNonDeviceInterrupt case, and
+ // hence calls to enable those will never enter this routine.
+ // If this changes, the code below needs to be modified because
+ // these interrupts do NOT have an ELCR entry (there are only
+ // 16 of those).
+ //
+
+ if (((Cbus1IrqPolarity >> Irqline)) & 0x1) {
+ LevelTriggered = TRUE;
+ }
+ else {
+ LevelTriggered = FALSE;
+ }
+
+ CbusEnableApicInterrupt(BusNumber, Vector, HardwarePtr, FirstAttach,
+ LowestInGroup, LevelTriggered);
+}
+
+VOID
+Cbus1DisableInterrupt(
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG LastDetach,
+IN USHORT BusNumber,
+IN USHORT Irqline
+)
+/*++
+
+Routine Description:
+
+ Disable the specified interrupt so it can not occur on the calling
+ processor upon return from this routine. Remember only the boot processor
+ can add/remove processors from his I/O APIC's redirection entries.
+
+ This operation is trivial for the boot processor. However, additional
+ processors must interrupt the boot processor with a "disable interrupt"
+ request and then spin waiting for the boot processor to acknowledge that
+ the entry has been modified. Note that the caller holds the HAL's
+ CbusVectorLock at CLOCK_LEVEL on entry.
+
+Arguments:
+
+ Vector - Supplies a vector number to disable
+
+ HardwarePtr - Supplies a redirection entry address
+
+ LastDetach - TRUE if this is the last processor to detach from the
+ specified vector
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( Irqline );
+
+ //
+ // Only 1 I/O bus in Cbus1 systems, only Cbus2 can have more
+ //
+ ASSERT(BusNumber == 0);
+
+ CbusDisableApicInterrupt(BusNumber, Vector, HardwarePtr, LastDetach);
+}
+
+
+ULONG
+Cbus1MapVector(
+ PBUS_HANDLER Bus,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ HalGetInterruptVector() must maintain a "vector to interrupt"
+ mapping so when the interrupt is enabled later via
+ HalEnableSystemInterrupt(), something intelligent can be done -
+ ie: which CBC's hardware interrupt maps to enable!
+ this applies both to EISA bridge CBCs and C-bus II half-card CBC's.
+
+ Note that HalEnableSystemInterrupt() will be CALLED by
+ EACH processor wishing to participate in the interrupt receipt.
+
+ Do not detect collisions here because interrupts are allowed to be
+ shared at a higher level - the ke\i386\intobj.c will take care of
+ the sharing. Just make sure that for any given irq line, only one
+ vector is generated, regardless of how many drivers may try to share
+ the line.
+
+Arguments:
+
+
+ BusHandler - per bus specific structure
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ SystemVector = Cbus1Irqlines[BusInterruptLevel].Vector;
+ *Irql = Cbus1Irqlines[BusInterruptLevel].Irql;
+ return SystemVector;
+}
+
+PVOID
+Cbus1LinkVector(
+IN PBUS_HANDLER Bus,
+IN ULONG Vector,
+IN ULONG Irqline
+)
+/*++
+
+Routine Description:
+
+ "Link" a given vector to the passed BusNumber/irqline, returning
+ a "handle" that can be used to reference it later for operations
+ that need to access the hardware (ie: Enable & DisableInterrupt).
+
+Arguments:
+
+ Vector - Supplies the system interrupt vector corresponding to the
+ specified BusNumber/Irqline.
+
+ Irqline - Supplies the IRQ line of the specified interrupt
+
+Return Value:
+
+ A hardware-specific pointer (actually a redirection entry address)
+ that is interpreted only by the Cbus1 backend.
+
+--*/
+{
+ return CbusApicLinkVector(Bus, Vector, Irqline);
+}
+
+#if DBG
+#define NMI_BUTTON_PRESSED() 1
+#else
+#define NMI_BUTTON_PRESSED() 0
+#endif
+
+NTSTATUS
+Cbus1ResolveNMI(
+ IN PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ This function determines the cause of the NMI so that the user can
+ replace any offending SIMMs.
+
+Arguments:
+
+ NmiInfo - pointer to the NMI information structure
+
+Return Value:
+
+ Returns the byte address which caused the NMI, 0 if indeterminate
+
+--*/
+{
+ ULONG Board;
+ PMEMORY_CARD pm;
+ ULONG Syndrome;
+ PEXTMEAR Mear;
+ PHYSICAL_ADDRESS FaultAddress;
+ UCHAR NmiMessage[80];
+ BOOLEAN founderror = FALSE;
+ extern VOID CbusClearEISANMI(VOID);
+ extern NTSTATUS DefaultHalHandleNMI( IN OUT PVOID);
+
+ if (NMI_BUTTON_PRESSED()) {
+
+ //
+ // NMI button was pressed, so go to the debugger
+ //
+
+ _asm {
+ int 3
+ }
+
+ //
+ // Clear the NMI in hardware so the system can continue
+ //
+
+ CbusClearEISANMI();
+
+ return STATUS_SUCCESS; // ignore this NMI
+ }
+
+ if (CbusGlobal.nonstdecc)
+ return DefaultHalHandleNMI(NmiInfo);
+
+ FaultAddress.LowPart = 0;
+ FaultAddress.HighPart = 0;
+
+ pm = CbusMemoryBoards;
+
+ for (Board = 0; Board < CbusMemoryBoardIndex; Board++, pm++) {
+
+ if (pm->io_attr == 0)
+ continue;
+
+ //
+ // the syndrome/page routines below are for
+ // the Corollary Cbus1 smp/XM architecture.
+ // this architecture currently supports 256Mb of RAM.
+ //
+ // this method is the defacto standard for Corollary
+ // Cbus1 licensees with > 64Mb.
+ //
+
+ Mear = (PEXTMEAR)pm->regmap;
+
+ //
+ // check whether this memory board generated the ecc error
+ // double check all the byte vs. clicks conversions and
+ // also the baseram (for jumpered megabytes)
+ //
+
+ Syndrome =
+ Cbus1EdacSyndrome[(Mear->SyndromeHigh<<2)|Mear->SyndromeLow];
+
+ if (Syndrome == NOECCERROR || Syndrome == SINGLEBIT)
+ continue;
+
+ //
+ // Cbus1 will always have less than 4Gig of physical memory,
+ // so just calculate LowPart here. no need to add in
+ // CbusGlobal.baseram, because that will always be zero.
+ //
+ // the Mear->offset will always be zero based, regardless of
+ // whether the memory was reclaimed above 256MB or not.
+ //
+
+ FaultAddress.LowPart = (Mear->offset << 4);
+
+ founderror = TRUE;
+
+ //
+ // Disable ecc so the system can be safely taken down
+ // without getting another double-bit error (because the
+ // kernel may iret later).
+ //
+
+ Cbus1ECCDisable();
+
+ break;
+ }
+
+ if (founderror == TRUE) {
+ sprintf(NmiMessage, MSG_CBUS1NMI_ECC, 0, FaultAddress.LowPart);
+ CbusHardwareFailure (NmiMessage);
+ }
+
+ //
+ // No errors found in Cbus RAM, so check for EISA errors
+ //
+
+ DefaultHalHandleNMI(NmiInfo);
+}
+
+VOID
+Cbus1ResetAllOtherProcessors(
+ IN ULONG Processor
+ )
+/*++
+
+Routine Description:
+
+ Called to put all the other processors in reset prior to reboot.
+ In order to safely put the other processors in reset, an IPI is
+ sent to the other processors to force them to write-invalidate
+ their L1 cache and halt. The calling processor will wait 5 seconds
+ for the IPI to take affect.
+
+ Shadowing is then disabled. The keyboard controller is then
+ reset and ThisProcessor spins awaiting the reboot.
+
+ This routine can be called at any IRQL. The boot processor can
+ call whilst cli'd at interrupt time.
+
+Arguments:
+
+ Processor - Supplies the caller's logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PUCHAR BiosProcessorCSR;
+ extern VOID Cbus1RebootRequest(IN ULONG);
+
+ _asm {
+ cli
+ }
+
+ //
+ // IPI the other processors to get them to flush
+ // their internal caches and halt. this will be more
+ // conducive for the subsequent reset.
+ //
+ Cbus1RebootRequest(Processor);
+
+ //
+ // Delay 5 seconds to give the additional processors
+ // a chance to get the previous IPI.
+ //
+ KeStallExecutionProcessor(5000000);
+
+ //
+ // issue a global reset to the broadcast address
+ //
+ *(PULONG)((PUCHAR)CbusBroadcastCSR + CbusGlobal.smp_sreset) =
+ CbusGlobal.smp_sreset_val;
+
+ //
+ // Disable BIOS shadowing until RRD recopies the BIOS ROM
+ // into shadow RAM again. This is because we "reclaim" the
+ // BIOS hole up at 256MB + 640K, to use it as general purpose
+ // (shadowed) RAM for NT. Referring to the ROM at 640K (NOT
+ // 256MB + 640K) you will see a pristine BIOS copy, but
+ // accessing it at the high address is like using any other
+ // area of general-purpose DRAM.
+ //
+ // thus, during NT, the shadowed copy will be overwritten with
+ // random data as the pages are used, and we must warn the BIOS
+ // to recopy the ROM into the shadowed RAM on bootup. Here's
+ // the magic to instruct the BIOS accordingly:
+ //
+ // Note that once RRD regains control, he will again
+ // shadow the BIOS as long as the EISA Config CMOS bits
+ // instruct him to. The shadowing is only being disabled
+ // here because the BIOS will initially get control _before_
+ // the Corollary RRD ROM does.
+ //
+ // if this code wasn't here, the user would have to cycle
+ // power to boot up successfully.
+ //
+ BiosProcessorCSR = (PUCHAR)(KeGetPcr()->HalReserved[PCR_CSR]);
+
+ *(BiosProcessorCSR + CBUS1_SHADOW_REGISTER) =
+ DISABLE_BIOS_SHADOWING;
+
+ //
+ // reset the keyboard controller.
+ //
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+loop:
+ goto loop;
+}
+
+//
+//
+// most internal Cbus1 support routines begin here.
+//
+// the exception is the internal routines needed for booting,
+// which must be adjacent to the externally-visible boot
+// routine above. see the above comments for more details.
+//
+//
+//
+
+VOID
+Cbus1ECCEnable(VOID)
+/*++
+
+Routine Description:
+
+ Enable Cbus1 ECC detection as ordered by the RRD.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ PMEMORY_CARD pm;
+
+ if (CbusGlobal.nonstdecc)
+ return;
+
+ pm = CbusMemoryBoards;
+
+ for (Index = 0; Index < CbusMemoryBoardIndex; Index++, pm++) {
+
+ if (pm->io_attr)
+ COUTB(pm->regmap, 0, pm->io_attr);
+
+ }
+}
+
+
+VOID
+Cbus1ECCDisable(VOID)
+/*++
+
+Routine Description:
+
+ Disable Cbus1 ECC
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ PMEMORY_CARD pm;
+
+ if (CbusGlobal.nonstdecc)
+ return;
+
+ pm = CbusMemoryBoards;
+
+ for (Index = 0; Index < CbusMemoryBoardIndex; Index++, pm++) {
+
+ if (pm->io_attr)
+ COUTB(pm->regmap, 0, pm->io_attr & ~CBUS1_EDAC_EN);
+ }
+}
+
+PUCHAR
+CbusIDtoCSR(
+IN ULONG ArbID
+)
+/*++
+
+Routine Description:
+
+ Search for the given arbitration ID in the
+ global extended ID table, then return its CSR.
+
+Arguments:
+
+ ArbID - Supplies an arbitration ID (that just won the contention cycle)
+
+Return Value:
+
+ CSR of the specified arbitration ID, 0 if none found
+
+--*/
+{
+ ULONG Index;
+ PEXT_ID_INFO Idp;
+
+ for ( Index = 0; Index < CbusProcessors; Index++) {
+
+ Idp = (PEXT_ID_INFO)CbusCSR[Index].idp;
+
+ if (Idp->id == ArbID) {
+
+ return (PUCHAR)CbusCSR[Index].csr;
+
+ }
+ }
+
+ return (PUCHAR)0;
+}
+
+
+VOID
+Cbus1Arbitrate(VOID)
+/*++
+
+Routine Description:
+
+ Called by the boot processor to arbitrate the other processors
+ out of reset, and brand them with IDs.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index, ArbID;
+ PUCHAR csr, ArbCSR;
+ ULONG AdditionalProcessors = 0;
+ extern PVOID Cbus1FindDeadID( ULONG );
+
+ //
+ // issue a global broadcast to put all additional processors into reset.
+ //
+
+ csr = (PUCHAR)CbusBroadcastCSR + CbusGlobal.smp_sreset;
+ *((PULONG)csr) = CbusGlobal.smp_sreset_val;
+
+ //
+ // access ID 0's C-bus I/O space - this is different from the boot CPU.
+ //
+ for (Index = 0; Index < CbusGlobal.broadcast_id; Index++) {
+
+ COUTB(Cbus1ID0CSR, CbusGlobal.smp_contend,
+ CbusGlobal.smp_contend_val);
+
+ COUTB(CbusBroadcastCSR, CbusGlobal.smp_contend,
+ CbusGlobal.smp_contend_val);
+
+
+ ArbID = READ_PORT_UCHAR(ATB_STATREG) & BS_ARBVALUE;
+
+ ArbCSR = CbusIDtoCSR(ArbID);
+
+ if (ArbCSR) {
+ COUTB(ArbCSR, CbusGlobal.smp_setida,
+ CbusGlobal.smp_setida_val);
+
+ if (ArbID >= LOWCPUID && ArbID <= HICPUID)
+ AdditionalProcessors++;
+ }
+ else {
+ if (!Cbus1FindDeadID(ArbID)) {
+ CbusHardwareFailure(MSG_ARBITRATE_ID_ERR);
+ }
+ }
+
+ ArbID = READ_PORT_UCHAR(ATB_STATREG) & BS_ARBVALUE;
+
+ if (ArbID == 0) {
+ ASSERT(AdditionalProcessors == CbusProcessors - 1);
+ return;
+ }
+ };
+
+ CbusHardwareFailure(MSG_ARBITRATE_FAILED);
+}
+
+
+VOID
+Cbus1HandleJumpers()
+
+/*++
+
+Routine Description:
+
+ "Recover" any low memory which has been repointed at the EISA bus
+ via EISA config. This typically happens when ISA/EISA cards with
+ dual-ported memory are in the machine, and memory accesses need
+ to be pointed at the card, as opposed to C-bus general purpose memory.
+ The Corollary architecture provides a way to still gain use of the
+ general purpose memory, as well as be able to use the I/O dual-port
+ memory, by double mapping the C-bus memory at a high memory address.
+
+ note that memory accesses in the 640K-1MB hole are by default, pointed
+ at the EISA bus, and don't need to be repointed via EISA config.
+
+ note this is where jumper decoding and memory_holes set up
+ happens, but the actual memory will not be released (and
+ hence used), until HalInitSystem Phase 0.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG i, j;
+ ULONG DoublyMapped;
+ ULONG Address;
+ extern RRD_CONFIGURATION_T CbusJumpers;
+ extern VOID CbusMemoryFree(ULONG, ULONG);
+
+ if (CbusGlobal.useholes == 0) {
+ return;
+ }
+
+ //
+ // if the base of RAM is _zero_ (ie: XM or later), then we
+ // will recover the holes up above the "top of RAM", so any
+ // I/O device dual-port RAM at the low address will continue to work.
+ //
+ // if the base of RAM is NON-ZERO, then we are on an older
+ // Corollary system which is not supported by this HAL - the
+ // standard Windows NT uniprocessor HAL should be used instead.
+ //
+
+ if (CbusGlobal.baseram != 0)
+ return;
+
+ DoublyMapped = CbusGlobal.memory_ceiling;
+
+ //
+ // reclaim the 640K->1MB hole first
+ //
+ CbusMemoryFree(DoublyMapped + 640 * 1024, 384 * 1024);
+
+ //
+ // see if this memory span has been dipswitch
+ // disabled. if this memory exists (in C-bus
+ // space and it has been jumpered, add it to
+ // the list so it will be freed later.
+ //
+ for (i = 0; i < ATMB; i++) {
+ if (CbusJumpers.jmp[i] && CbusJumpers.mem[i]) {
+ Address = MB(i) + DoublyMapped;
+ j = 1;
+ for (i++; i < ATMB && CbusJumpers.jmp[i] && CbusJumpers.mem[i]; i++)
+ j++;
+ CbusMemoryFree(Address, MB(j));
+ }
+ }
+}
+
+
+VOID
+Cbus1ParseRRD(
+IN PEXT_ID_INFO Table,
+IN OUT PULONG Count
+)
+/*++
+
+Routine Description:
+
+ Check for Cbus1 system boards being up to date for running NT.
+ Obsolete additional CPU boards are removed from the configuration
+ structure, and are not booted later. If the boot CPU is obsolete,
+ the system is halted.
+
+Arguments:
+
+ Table - Supplies a pointer to the RRD extended ID information table
+
+ Count - Supplies a pointer to the number of valid entries in the
+ RRD extended ID information table
+
+Return Value:
+
+ Shuffles the input table, and modifies the count of valid entries,
+ in order to remove any obsolete processors.
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ ULONG Length;
+ ULONG j;
+ PEXT_ID_INFO p;
+ PEXT_ID_INFO s;
+ UCHAR HalObsoleteBoardsMsg[80];
+
+ Cbus1DeadIDsIndex = 0;
+ p = Table;
+
+ for (Index = 0; Index < *Count; Index++, p++) {
+
+ //
+ // check for the ID 0 entry, which must be the first one.
+ // although this is NOT a processor, it is needed to
+ // arbitrate all the Cbus1 additional processors and set their
+ // IDs. so capture it now.
+ //
+
+ if (Index == 0) {
+ //
+ // RRD specifies how much to map in per processor -
+ // for Cbus1, RRD must give us a size which includes any
+ // processor-specific registers the HAL may access,
+ // generally indicated via the CbusGlobal structure.
+ //
+ Cbus1ID0CSR = (PUCHAR)HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)p->pel_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ p->pel_start, p->pel_size));
+
+ continue;
+ }
+
+ if (p->pm == 0)
+ continue;
+
+ if ((p->pel_features & ELEMENT_HAS_APIC) == 0) {
+
+ //
+ // the boot processor MUST have an APIC
+ // so that we can support distributed
+ // interrupts on Cbus1 platforms.
+ //
+ if ((UCHAR)p->id == CbusGlobal.bootid) {
+ FatalError(MSG_OBSOLETE_PIC);
+ }
+
+ *(PEXT_ID_INFO)&Cbus1DeadIDs[Cbus1DeadIDsIndex] =
+ *p;
+
+ Cbus1DeadIDsIndex++;
+
+ //
+ // remove old board from "found" array
+ //
+
+ s = p;
+ for (j = Index+1; j < *Count; j++, s++) {
+ *s = *(s + 1);
+ }
+
+ }
+
+ }
+
+ if (Cbus1DeadIDsIndex) {
+
+ //
+ // can't let any disabled processors be found,
+ // warn the user that we are disabling some number
+ // of processor boards because they cannot access
+ // the EISA bus.
+ //
+ *Count -= Cbus1DeadIDsIndex;
+
+ sprintf(HalObsoleteBoardsMsg, MSG_OBSOLETE_PROC, Cbus1DeadIDsIndex);
+ HalDisplayString(HalObsoleteBoardsMsg);
+ }
+
+ Cbus1HandleJumpers();
+
+ //
+ // Inform the rest of the system of the resources the HAL has reserved
+ // from the base of C-bus I/O to 4GB.
+ //
+ Length = 0xffffffff - CbusGlobal.cbusio;
+ AddMemoryResource(CbusGlobal.cbusio, Length + 1);
+}
+
+PVOID
+Cbus1FindDeadID(
+IN ULONG ArbID
+)
+/*++
+
+Routine Description:
+
+ Check for a given arbitration ID (that just won) is a "dead" Cbus1
+ system board - ie: one that we have software disabled because it is
+ a processor incapable of symmetric I/O.
+
+Arguments:
+
+ ArbID - Supplies an arbitration ID to match
+
+Return Value:
+
+ An opaque pointer to the disabled processor's CSR space, 0
+ if the ID was not found.
+
+--*/
+{
+ ULONG Dead;
+ PUCHAR csr = (PUCHAR)0;
+ PEXT_ID_INFO Idp = (PEXT_ID_INFO)Cbus1DeadIDs;
+ extern VOID CbusIOPresent(ULONG, ULONG, ULONG, ULONG, ULONG, PVOID);
+
+ for (Dead = 0; Dead < Cbus1DeadIDsIndex; Dead++, Idp++) {
+ if (Idp->id != ArbID) {
+ continue;
+ }
+
+ csr = (PUCHAR)HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)Idp->pel_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ Idp->pel_start, Idp->pel_size));
+
+ COUTB(csr, CbusGlobal.smp_setida,
+ CbusGlobal.smp_setida_val);
+
+ switch (Idp->io_function) {
+ case IOF_INVALID_ENTRY:
+ case IOF_NO_IO:
+ case IOF_MEMORY:
+ break;
+ default:
+ //
+ // Add this I/O functionality to our table
+ // to make available to Cbus hardware drivers.
+ //
+ // pel_features wasn't set for the old boards,
+ // so check io_function instead.
+ //
+
+ if (Idp->io_function == IOF_CBUS1_SIO ||
+ (Idp->io_function == IOF_CBUS1_SCSI)) {
+
+ //
+ // Add this I/O card to our list of
+ // available I/O peripherals.
+ //
+ CbusIOPresent(
+ (ULONG)Idp->id,
+ (ULONG)Idp->io_function,
+ (ULONG)Idp->io_attr,
+ Idp->pel_start,
+ Idp->pel_size,
+ (PVOID)csr);
+ }
+ break;
+ }
+
+ }
+
+ return (PVOID)csr;
+}
+
+
+/*++
+
+Routine Description:
+
+ This function calculates the stall execution, and initializes the
+ HAL-specific hardware device (CLOCK & PROFILE) interrupts for the
+ Corollary Cbus1 architecture.
+
+Arguments:
+
+ Processor - Supplies a logical processor number to initialize
+
+Return Value:
+
+ VOID
+
+--*/
+
+VOID
+Cbus1InitializeInterrupts(
+IN ULONG Processor
+)
+{
+ //
+ // Cbus1: stall uses the APIC to figure it out (needed in phase0).
+ // the clock uses the APIC (needed in phase0)
+ // the perfcounter uses irq0 (not needed till all cpus boot)
+ // the profile uses RTC irq8 (not needed till all cpus boot)
+ //
+ // Cbus2: stall uses the RTC irq8 to figure it out (needed in phase0).
+ // the clock uses the irq0 (needed in phase0)
+ // the perfcounter uses RTC irq8 (not needed till all cpus boot)
+ //
+
+ if (Processor == 0) {
+ //
+ // we must be at Phase0 of system initialization. we need to
+ // assign vectors for interrupts needed during Phase0.
+ // currently only the APIC clock is needed during Phase0.
+ //
+ CbusVectorToEoi[CBUS1_CLOCK_TASKPRI] =
+ CbusApicVectorToEoi(CBUS1_CLOCK_TASKPRI);
+ }
+
+ //
+ // Note that for Cbus1, InitializeClock MUST be called after
+ // HalpInitializeStallExecution, since both program the APIC timer.
+ // Note that stall execution sets up his own IDT entry for handling
+ // the incoming interrupt, so only the above EOI setup is needed.
+ //
+
+ Cbus1InitializeStall(Processor);
+
+ //
+ // Call the hardware backend handler to generate an
+ // interrupt every 10 milliseconds to be used as the system timer.
+ //
+
+ Cbus1InitializeClock();
+
+ //
+ // Set up the irq0 performance counter and irq8 profile interrupts.
+ //
+
+ if (Processor == 0) {
+ Cbus1SetupPrivateVectors();
+ Cbus1InitializePerf();
+ }
+
+ //
+ // enable both the irq0 and irq8 interrupts as well as the APIC clocks.
+ // This also registers the resources being used by these interrupts
+ // so other subsystems know the HAL has reserved them.
+ //
+
+ Cbus1InitializeDeviceIntrs(Processor);
+
+ //
+ // APC, DPC and IPI have already been initialized and enabled
+ // as part of HalInitializeProcessor.
+ //
+}
+
+/*++
+
+Routine Description:
+
+ This function initializes the HAL-specific hardware device
+ (CLOCK & PROFILE) interrupts for the Corollary Cbus1 architecture.
+
+Arguments:
+
+ none.
+
+Return Value:
+
+ VOID
+
+--*/
+
+VOID
+Cbus1InitializeDeviceIntrs(
+IN ULONG Processor
+)
+{
+ extern VOID Cbus1ClockInterrupt(VOID);
+
+ //
+ // here we initialize & enable all the device interrupts.
+ // this routine is called from HalInitSystem.
+ //
+ // each processor needs to call KiSetHandlerAddressToIDT()
+ // and HalEnableSystemInterrupt() for himself.
+ //
+
+ if (Processor == 0) {
+
+ //
+ // Support the HAL's exported interface to the rest of the
+ // system for the IDT configuration. This routine will
+ // also set up the IDT entry and enable the actual interrupt.
+ //
+ // Only one processor needs to do this, especially since
+ // the additional processors are vectoring elsewhere for speed.
+ //
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ CBUS1_CLOCK_TASKPRI, // Bus interrupt level
+ CBUS1_CLOCK_TASKPRI, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ Cbus1ClockInterrupt, // ISR
+ Latched);
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ IRQ8, // Bus interrupt level
+ CBUS1_PROFILE_TASKPRI,
+ PROFILE_LEVEL, // System Irql
+ HalpProfileInterrupt, // ISR
+ Latched);
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ IRQ0, // Bus interrupt level
+ CBUS1_PERF_TASKPRI, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ Cbus1PerfInterrupt, // ISR
+ Latched);
+
+ }
+ else {
+ KiSetHandlerAddressToIDT(CBUS1_CLOCK_TASKPRI, CbusClockInterruptPx);
+ HalEnableSystemInterrupt(CBUS1_CLOCK_TASKPRI, CLOCK2_LEVEL, Latched);
+
+ KiSetHandlerAddressToIDT(CBUS1_PROFILE_TASKPRI, HalpProfileInterruptPx);
+ HalEnableSystemInterrupt(CBUS1_PROFILE_TASKPRI, PROFILE_LEVEL, Latched);
+ }
+}
+
+//
+// Mask for valid bits of edge/level control register (ELCR) in 82357 ISP:
+// ie: ensure irqlines 0, 1, 2, 8 and 13 are always marked edge, as the
+// I/O register will not have them set correctly. All other bits in the
+// I/O register will be valid without us having to poke them.
+//
+#define ELCR_MASK 0xDEF8
+
+#define PIC1_ELCR_PORT (PUCHAR)0x4D0 // ISP edge/level control regs
+#define PIC2_ELCR_PORT (PUCHAR)0x4D1
+
+ULONG
+Cbus1QueryInterruptPolarity(
+VOID
+)
+/*++
+
+Routine Description:
+
+ Called once to read the EISA interrupt configuration registers.
+ This will tell us which interrupt lines are level-triggered and
+ which are edge-triggered. Note that irqlines 0, 1, 2, 8 and 13
+ are not valid in the 4D0/4D1 registers and are defaulted to edge.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The interrupt line polarity of all the EISA irqlines in the system.
+
+--*/
+{
+ ULONG InterruptLines = 0;
+
+ //
+ // Read the edge-level control register (ELCR) so we'll know how
+ // to mark each driver's interrupt line (ie: edge or level triggered).
+ // in the APIC I/O unit redirection table entry.
+ //
+
+ InterruptLines = ( ((ULONG)READ_PORT_UCHAR(PIC2_ELCR_PORT) << 8) |
+ ((ULONG)READ_PORT_UCHAR(PIC1_ELCR_PORT)) );
+
+ //
+ // Explicitly mark irqlines 0, 1, 2, 8 and 13 as edge. Leave all
+ // other irqlines at their current register values.
+ //
+
+ InterruptLines &= ELCR_MASK;
+
+ return InterruptLines;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbus1.h b/private/ntos/nthals/halcbus/i386/cbus1.h
new file mode 100644
index 000000000..a2ba56077
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus1.h
@@ -0,0 +1,70 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus1.h
+
+Abstract:
+
+ Cbus1 architecture definitions for the Corollary Cbus1
+ multiprocessor HAL modules.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 05-Oct-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _CBUS1_
+#define _CBUS1_
+
+//
+//
+// FIRST, THE CBUS1 HARDWARE ARCHITECTURE DEFINITIONS
+//
+//
+
+#define COUTB(addr, reg, val) (((PUCHAR)(addr))[reg] = (UCHAR)val)
+
+#define CBUS1_CACHE_LINE 16 // 16 byte lines
+#define CBUS1_CACHE_SHIFT 4 // byte size to line size
+#define CBUS1_CACHE_SIZE 0x100000 // 1 Mb caches
+
+#define ATB_STATREG (PUCHAR)0xf1 // EISA bridge status register
+#define BS_ARBVALUE 0xf // arbitration value
+
+#define LOWCPUID 0x1 // lowest arbitration slot id
+#define HICPUID 0xf // highest arbitration slot id
+
+#define CBUS1_SHADOW_REGISTER 0xB0 // offset of shadow register
+
+#define DISABLE_BIOS_SHADOWING 0x0 // disable ROM BIOS shadowing
+
+//
+// defines for the Cbus1 ecc control register
+//
+#define CBUS1_EDAC_SAEN 0x80
+#define CBUS1_EDAC_1MB 0x40
+#define CBUS1_EDAC_WDIS 0x20
+#define CBUS1_EDAC_EN 0x10
+#define CBUS1_EDAC_SAMASK 0xf
+
+//
+// Physical address of the Cbus1 local APIC
+//
+#define CBUS1_LOCAL_APIC_LOCATION (PVOID)0xFEE00000
+
+//
+// Physical address of the Cbus1 I/O APIC
+//
+#define CBUS1_IO_APIC_LOCATION (PVOID)0xFEE00000
+
+#endif // _CBUS1_
diff --git a/private/ntos/nthals/halcbus/i386/cbus1bt.asm b/private/ntos/nthals/halcbus/i386/cbus1bt.asm
new file mode 100644
index 000000000..5f36b92ad
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus1bt.asm
@@ -0,0 +1,314 @@
+ title "MP primitives for the Corollary Cbus machines"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc.
+;
+;Module Name:
+;
+; cbus1bt.asm
+;
+;Abstract:
+;
+; Corollary Cbus1 Boot Code
+;
+; This module implements the low-level highly cache
+; architecture dependent code to boot the additional
+; processors in the Corollary Cbus1 based machines.
+
+; This consists of two functions which are exactly the
+; same (Cbus1Boot1 & Cbus1Boot2). The calling code
+; determines which one is safe to call (depending on the
+; linker, sometimes both may be ok). The reason for this
+; is that the boot processor fills in the reset vector at
+; 0xFFFFFFF0 for the next processor and that cache line
+; must not be inadvertently flushed before the next processor
+; gets out of reset to see where to go (it's filled in with
+; a real-mode jmp cs:ip). Note that this code is highly
+; dependent on the linker placing all this code contiguous
+; and the hardware architecture of the Corollary L2 caches.
+; unless the system is fully populated, memory will not exist
+; at 0xFFFFFFF0. hence, we must ensure that the cacheline is
+; not evicted until the processor has done the jump!
+
+
+; the order of Cbus1Boot1, ciboot, and Cbus1Boot2 is critical.
+; Cbus1Boot1 and Cbus1Boot2 must be separated by Cbus1BootCPU;
+; Cbus1Boot1 must be defined before Cbus1Boot2.
+; the size of all three must be less than 4K.
+
+; WARNING!!! WARNING!!! WARNING!!!
+
+; do not put any routines between Cbus1Boot1 and Cbus1Boot2. there
+; are tricky games being played with the write back caches so
+; that StartVector[] does not get flushed.
+
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 23-Jun-1993
+;
+;Environment:
+; Kernel mode.
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+
+ .list
+
+INIT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; Cbus1Boot1 (
+; IN ULONG Processor,
+; IN PQUAD Dest,
+; IN PQUAD Source,
+; IN ULONG ResetAddress,
+; IN ULONG ResetValue
+; )
+;
+;
+; Routine Description:
+;
+; Clear reset on the specified logical processor number, setting his
+; reset vector to point at the specified code location. The Dest
+; generally points at a reset vector, and thus, unless the system is
+; fully populated, memory will not exist at that address. hence, we
+; must ensure that the cacheline is not evicted until the processor
+; has done the jump!
+;
+; Arguments:
+;
+; Processor - Supplies a logical processor number
+;
+; Dest - Supplies the address of the reset vector where the code below
+; will go.
+;
+; Source - Supplies startup code for this processor, currently a 5 byte
+; intrasegment jump, ie: "jmp cs:ip"
+;
+; Note the reset vector length is hardcoded here to 8 bytes. (ie: Dest
+; and Source must point at arrays of 8 bytes each).
+;
+; ResetAddress - Supplies the address to poke to clear reset
+;
+; ResetValue - Supplies the value to poke to clear reset
+;
+; Return Value:
+;
+; None.
+;--
+
+ProcessorNumber equ dword ptr [ebp+8] ; zero based
+Destination equ dword ptr [ebp+12]
+Source equ dword ptr [ebp+16]
+ResetAddress equ dword ptr [ebp+20]
+ResetValue equ dword ptr [ebp+24]
+
+cPublicProc _Cbus1Boot1 ,5
+ push ebp
+ mov ebp, esp
+ push ebx
+ push esi
+ push edi
+
+ ;
+ ; set up all variables to be used after the cache line
+ ; initialization. this is because we want to load up
+ ; our register variables with these values and avoid
+ ; memory references. see the comment below.
+ ;
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ ; loop count for the processor
+
+ mov ecx, 40 ; 40 microsecond stall
+ mul ecx ; (eax) = desired loop count
+
+ mov edx, ResetAddress
+ mov ebx, ResetValue
+
+ mov esi, Source ; point at the source code
+
+ mov ecx, dword ptr [esi] ; get first dword into a reg
+ mov esi, dword ptr [esi+4] ; and 2nd dword into a reg
+
+ mov edi, Destination
+
+ ;
+ ; now start filling in the cache line for the processor coming out
+ ; of reset. no memory references which may flush this cache line
+ ; can be made after the below fill UNTIL the booting processor
+ ; has read the line. (the only memory references made here in this
+ ; critical time period is the code fetching, but our caller has
+ ; already determined that none of the code in this function could
+ ; cause the cache line to be flushed).
+ ;
+
+ mov dword ptr [edi], ecx ; 1st dword now in the cacheline
+ mov dword ptr [edi+4], esi ; and 2nd dword now in
+
+ ;
+ ; cache line is initialized, we must let it get flushed now, or
+ ; the additional processor will fly blind.
+ ;
+
+ mov byte ptr [edx], bl ; clear reset
+
+ ;
+ ; wait approximately 40 microseconds, but don't call
+ ; KeStallExecutionProcessor() as this might flush the
+ ; cache line prematurely. inline the function instead.
+ ;
+
+ align 4
+@@:
+ sub eax, 1 ; (eax) = (eax) - 1
+ jnz short @b
+
+
+ pop edi
+ pop esi
+ pop ebx
+ mov esp, ebp
+ pop ebp
+ stdRET _Cbus1Boot1
+
+stdENDP _Cbus1Boot1
+
+ ;
+ ; force enough spacing between the two boot functions so
+ ; that at least one of them will always be safe to call.
+ ; currently that would be 16 bytes (the current cache line
+ ; size), but make it bigger so any of our OEMs will be safe
+ ; even if they modify the size of the cache line.
+ ;
+
+ public _Cbus1Boot1End
+_Cbus1Boot1End label byte
+ db 64 dup (?)
+
+;++
+;
+; VOID
+; Cbus1Boot2 (
+; IN ULONG Processor,
+; IN PQUAD Dest,
+; IN PQUAD Source,
+; IN ULONG ResetAddress,
+; IN ULONG ResetValue
+; )
+;
+;
+; Routine Description:
+;
+; Clear reset on the specified logical processor number, setting his
+; reset vector to point at the specified code location. The Dest
+; generally points at a reset vector, and thus, unless the system is
+; fully populated, memory will not exist at that address. hence, we
+; must ensure that the cacheline is not evicted until the processor
+; has done the jump!
+;
+; Arguments:
+;
+; Processor - Supplies a logical processor number
+;
+; Dest - Supplies the address of the reset vector where the code below
+; will go.
+;
+; Source - Supplies startup code for this processor, currently a 5 byte
+; intrasegment jump, ie: "jmp cs:ip"
+;
+; Note the reset vector length is hardcoded here to 8 bytes. (ie: Dest
+; and Source must point at arrays of 8 bytes each).
+;
+; ResetAddress - Supplies the address to poke to clear reset
+;
+; ResetValue - Supplies the value to poke to clear reset
+;
+; Return Value:
+;
+; None.
+;--
+
+cPublicProc _Cbus1Boot2 ,5
+ push ebp
+ mov ebp, esp
+ push ebx
+ push esi
+ push edi
+
+ ;
+ ; set up all variables to be used after the cache line
+ ; initialization. this is because we want to load up
+ ; our register variables with these values and avoid
+ ; memory references. see the comment below.
+ ;
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ ; loop count for the processor
+
+ mov ecx, 40 ; 40 microsecond stall
+ mul ecx ; (eax) = desired loop count
+
+ mov edx, ResetAddress
+ mov ebx, ResetValue
+
+ mov esi, Source ; point at the source code
+
+ mov ecx, dword ptr [esi] ; get first dword into a reg
+ mov esi, dword ptr [esi+4] ; and 2nd dword into a reg
+
+ mov edi, Destination
+
+ ;
+ ; now start filling in the cache line for the processor coming out
+ ; of reset. no memory references which may flush this cache line
+ ; can be made after the below fill UNTIL the booting processor
+ ; has read the line. (the only memory references made here in this
+ ; critical time period is the code fetching, but our caller has
+ ; already determined that none of the code in this function could
+ ; cause the cache line to be flushed).
+ ;
+
+ mov dword ptr [edi], ecx ; 1st dword now in the cacheline
+ mov dword ptr [edi+4], esi ; and 2nd dword now in
+
+ ;
+ ; cache line is initialized, we must let it get flushed now, or
+ ; the additional processor will fly blind.
+ ;
+
+ mov byte ptr [edx], bl ; clear reset
+
+ ;
+ ; wait approximately 40 microseconds, but don't call
+ ; KeStallExecutionProcessor() as this might flush the
+ ; cache line prematurely. inline the function instead.
+ ;
+
+ align 4
+@@:
+ sub eax, 1 ; (eax) = (eax) - 1
+ jnz short @b
+
+
+ pop edi
+ pop esi
+ pop ebx
+ mov esp, ebp
+ pop ebp
+ stdRET _Cbus1Boot2
+
+stdENDP _Cbus1Boot2
+
+INIT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbus2.c b/private/ntos/nthals/halcbus/i386/cbus2.c
new file mode 100644
index 000000000..82ab6278a
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus2.c
@@ -0,0 +1,4170 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus2.c
+
+Abstract:
+
+ This module implements the Corollary Cbus2 specific functions that
+ define the Hardware Architecture Layer (HAL) for Windows NT.
+
+ Cbus2 architecture includes a 400MB/sec processor-memory bus, as well
+ as multiple EISA and PCI buses. Up to 10 Pentium processors are supported
+ in Cbus2, as well as multiple native Cbus2 I/O cards (ie: SCSI, FDDI, VGA,
+ SIO, etc). Cbus2 is fully symmetric: all processors can reach all
+ memory and I/O devices, and similarly, all memory and I/O devices can
+ reach all processors. The CBC supports fully distributed, lowest in group
+ interrupts, as well as broadcast capabilities. Each Cbus2 processor has
+ an internal processor write back cache, as well as up to 2MB of L2 direct
+ mapped write back cache and a fully associative L3 write back victim cache.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Notes:
+
+ Open Issues:
+
+ - Should move the task priority from an fs segment to a ds segment
+ now that CBC revision2 will have the identity maps.
+
+ - The multiple I/O bus code is complete and ready for testing.
+
+ - The code that supports Cbus2 systems using APICs (local units on
+ processors and I/O units on both EISA and CBC I/O cards)
+ is complete and ready for testing.
+
+ - Support for a variable number of Cbus2 CBC hardware interrupt maps
+ still needs to be coded.
+
+ - Cbus2 ECC enable, disable and handler code is not fleshed out.
+ when this is done, HandleNMI needs to be fixed for
+ xx_PORT_UCHAR multiple bridge issues.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "cbus.h" // Cbus1 & Cbus2 max number of elements is here
+#include "cbusrrd.h" // HAL <-> RRD interface definitions
+#include "cbus2.h" // Cbus2 hardware architecture stuff
+#include "cbus_nt.h" // Cbus NT-specific implementation stuff
+#include "cbusnls.h" // Cbus error messages
+#include "cbusapic.h" // Cbus APIC generic definitions
+#include "stdio.h"
+
+PULONG
+CbusApicVectorToEoi(
+IN ULONG Vector
+);
+
+VOID
+Cbus2BootCPU (
+IN ULONG Processor,
+IN ULONG StartAddress
+);
+
+VOID
+Cbus2InitInterruptPolarity(VOID);
+
+PVOID
+Cbus2LinkVector(
+IN PBUS_HANDLER RootHandler,
+IN ULONG Vector,
+IN ULONG Irqline
+);
+
+ULONG
+Cbus2ReadCSR(PULONG);
+
+VOID
+Cbus2WriteCSR(PULONG, ULONG);
+
+VOID
+Cbus2InitializeStall(IN ULONG);
+
+VOID
+Cbus2InitializeClock(VOID);
+
+VOID
+FatalError(
+IN PUCHAR ErrorString
+);
+
+VOID
+HalpIpiHandler( VOID );
+
+VOID
+Cbus2InitializeCBC(
+IN ULONG Processor
+);
+
+VOID
+Cbus2DisableMyInterrupts( ULONG );
+
+VOID
+HalpSpuriousInterrupt(VOID);
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+CbusRebootHandler( VOID );
+
+VOID
+Cbus2InitializeApic(
+IN ULONG Processor
+);
+
+VOID
+Cbus2CheckBusRanges(VOID);
+
+ULONG
+Cbus2MapBusNumberToBridgeIndex(
+ULONG RootBusNumber
+);
+
+VOID
+Cbus2SetupPrivateVectors(VOID);
+
+VOID
+Cbus2InitializePlatform(VOID);
+
+VOID
+Cbus2InitializeCPU(
+IN ULONG Processor
+);
+
+VOID
+Cbus2InitOtherBuses(VOID);
+
+VOID
+Cbus2ParseRRD(
+IN PEXT_ID_INFO Table,
+IN OUT PULONG Count
+);
+
+VOID
+Cbus2InitializeDeviceIntrs(
+IN ULONG Processor
+);
+
+UCHAR
+Cbus2CheckForPeleSystem(
+VOID
+);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, Cbus2SetupPrivateVectors)
+#pragma alloc_text(INIT, Cbus2BootCPU)
+#pragma alloc_text(INIT, Cbus2InitializePlatform)
+#pragma alloc_text(INIT, Cbus2InitializeCBC)
+#pragma alloc_text(INIT, Cbus2InitializeApic)
+#pragma alloc_text(INIT, Cbus2InitializeCPU)
+#pragma alloc_text(INIT, Cbus2InitOtherBuses)
+#pragma alloc_text(INIT, Cbus2ParseRRD)
+#pragma alloc_text(INIT, Cbus2InitializeDeviceIntrs)
+#pragma alloc_text(INIT, Cbus2InitInterruptPolarity)
+#endif
+
+VOID
+Cbus2DisableMyInterrupts(ULONG);
+
+extern ADDRESS_USAGE HalpCbusMemoryHole;
+extern ULONG CbusMemoryHoleIndex;
+extern ADDRESS_USAGE HalpCbusMemoryResource;
+extern ULONG CbusMemoryResourceIndex;
+
+extern MEMORY_ALLOCATION_DESCRIPTOR HalpMemory[];
+extern ULONG HalpMemoryIndex;
+
+extern RRD_CONFIGURATION_T CbusJumpers;
+
+extern ULONG CbusRedirVector;
+extern ULONG CbusRebootVector;
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+
+VOID
+CbusPreparePhase0Interrupts(
+IN ULONG,
+IN ULONG,
+IN PVOID
+);
+
+ULONG
+Cbus2GetInterruptVector(
+IN PBUS_HANDLER BusHandler,
+IN PBUS_HANDLER RootHandler,
+IN ULONG BusInterruptLevel,
+IN ULONG BusInterruptVector,
+OUT PKIRQL Irql,
+OUT PKAFFINITY Affinity
+);
+
+ULONG Cbus2BridgesFound;
+PCSR Cbus2BridgeCSR[CBUS_MAX_BRIDGES];
+UCHAR Cbus2PeleSystemFound;
+
+PCSR Cbus2IdentityCSR;
+
+PHYSICAL_ADDRESS Cbus2BridgeCSRPaddr[CBUS_MAX_BRIDGES];
+ULONG Cbus2BridgeId[CBUS_MAX_BRIDGES];
+ULONG Cbus2IrqPolarity[CBUS_MAX_BRIDGES];
+ULONG Cbus2BridgePCIBusNumber[CBUS_MAX_BRIDGES];
+ULONG Cbus2BridgeOverride;
+
+ULONG Cbus2InterruptController;
+
+ULONG Cbus2FixLevelInterrupts;
+ULONG Cbus2CheckSpuriousClock;
+ULONG Cbus2EnableBroadcast;
+ULONG Cbus2ClockVector;
+ULONG Cbus2EoiToHwmap;
+UCHAR Cbus2InterruptPolarity[MAXIMUM_IDTVECTOR + 1];
+PULONG Cbus2TimeStamp0;
+
+extern PULONG CbusTimeStamp;
+extern PULONG CbusVectorToEoi[MAXIMUM_IDTVECTOR + 1];
+extern ULONG CbusVectorToHwmap[MAXIMUM_IDTVECTOR + 1];
+
+//
+// Created for HalRequestIpi streamlining when operating in CBC mode -
+// otherwise the ipi address could always have been gotten via CbusCSR[].
+//
+PULONG Cbus2SendIPI[MAX_CBUS_ELEMENTS];
+PULONG Cbus2Poke8042;
+
+KSPIN_LOCK Cbus2NMILock;
+
+//
+// for Cbus2, the CBC interrupt hardware supports all 256 interrupt
+// priorities, and unlike the APIC, doesn't disable receipt of interrupts
+// at granularities of 16-deep buckets. instead the CBC uses the whole byte,
+// instead of 4 bits like the APIC, giving us a granularity of 1. This
+// fine granularity results in us having more available priorities than
+// both NT's 32 IRQL levels _AND_ the total number of EISA irq lines.
+// This distinction is critical because it allows us to associate a unique
+// vector AND PRIORITY to every single interrupt.
+//
+
+
+//
+// our interrupt prioritization picture from lowest priority
+// to highest priority) thus looks as follows:
+//
+// APC: 0x1F (lowest priority)
+// DPC: 0x2F
+// Lowest Priority EISA: 0x30
+// Highest Priority EISA: 0x4F
+//
+// unused vectors: 0x50->0x60
+//
+// Lowest Priority CBC: 0x61
+// Highest Priority CBC: 0xE9
+// EISA Profile: 0xEB
+// EISA Clock: 0xEC
+// Hal Private Reboot IPI: 0xED
+// IPI Broadcasting: 0xEE->FC
+// IPI: 0xFD
+// Power: 0xFE
+// High: 0xFE (highest priority)
+// Spurious: 0xFF (highest priority)
+//
+//
+
+#define CBUS2_PROFILE_TASKPRI 0xEB
+#define CBUS2_CLOCK_TASKPRI 0xEC
+
+//
+// all interrupts from this vector up can be enabled by just setting up
+// the calling processor's interrupt configuration register in his CBC.
+//
+
+#define CBUS2_REBOOT_TASKPRI 0xED
+#define CBUS2_REDIR_IPI 0xEE
+#define CBUS2_ALTERNATE_IPI 0xEF
+
+//
+// It's OK if the redirection IPI shares a vector assignment with the
+// broadcast_low IPI - because only one of them will be used in a given
+// system - the redirection IPI will only be used if we are using APICs to
+// communicate; the broadcast_low IPI will only be used if we are using
+// CBCs to communicate - we will never use both in the same system.
+//
+#define CBUS2_BROADCAST_TASKPRI_LOW 0xEE // only used by Cbus2 CBC
+#define CBUS2_BROADCAST_TASKPRI_HIGH 0xFC // only used by Cbus2 CBC
+
+#define CBUS2_IPI_TASKPRI 0xFD
+
+#define CBUS2_POWER_TASKPRI 0xFE
+
+//
+// we don't really care what this value is for the CBC, but the APIC
+// spec seems to imply that this must be hardcoded at 0xff for future
+// compatibility.
+//
+#define CBUS2_SPURIOUS_TASKPRI 0xFF
+
+#define LOWEST_DEVICE_TASKPRI 0x30
+#define LOWEST_CBC_TASKPRI 0x61
+#define HIGHEST_DEVICE_TASKPRI (CBUS2_PROFILE_TASKPRI - 1) // 0xEA
+
+//
+// declare an EISA_IRQ2PRI just to flesh out arrays that will be indexed by
+// irq line. the EISA_IRQ2PRI should never actually be used
+//
+
+#define EISA_IRQ2PRI HIGHEST_DEVICE_TASKPRI
+
+#define EISA_IRQ1PRI (LOWEST_DEVICE_TASKPRI + 0xE * CBUS_MAX_BRIDGES)
+#define EISA_IRQ3PRI (LOWEST_DEVICE_TASKPRI + 0xC * CBUS_MAX_BRIDGES)
+#define EISA_IRQ4PRI (LOWEST_DEVICE_TASKPRI + 0xB * CBUS_MAX_BRIDGES)
+#define EISA_IRQ5PRI (LOWEST_DEVICE_TASKPRI + 0xA * CBUS_MAX_BRIDGES)
+#define EISA_IRQ6PRI (LOWEST_DEVICE_TASKPRI + 0x9 * CBUS_MAX_BRIDGES)
+#define EISA_IRQ7PRI (LOWEST_DEVICE_TASKPRI + 0x8 * CBUS_MAX_BRIDGES)
+#define EISA_IRQ9PRI (LOWEST_DEVICE_TASKPRI + 0x6 * CBUS_MAX_BRIDGES)
+#define EISA_IRQAPRI (LOWEST_DEVICE_TASKPRI + 0x5 * CBUS_MAX_BRIDGES)
+#define EISA_IRQBPRI (LOWEST_DEVICE_TASKPRI + 0x4 * CBUS_MAX_BRIDGES)
+#define EISA_IRQCPRI (LOWEST_DEVICE_TASKPRI + 0x3 * CBUS_MAX_BRIDGES)
+#define EISA_IRQDPRI (LOWEST_DEVICE_TASKPRI + 0x2 * CBUS_MAX_BRIDGES)
+#define EISA_IRQEPRI (LOWEST_DEVICE_TASKPRI + 0x1 * CBUS_MAX_BRIDGES)
+#define EISA_IRQFPRI (LOWEST_DEVICE_TASKPRI)
+
+#define EISA_IRQ0PRI2 (LOWEST_DEVICE_TASKPRI + 0xF * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ1PRI2 (LOWEST_DEVICE_TASKPRI + 0xE * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ2PRI2 (LOWEST_DEVICE_TASKPRI + 0xD * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ3PRI2 (LOWEST_DEVICE_TASKPRI + 0xC * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ4PRI2 (LOWEST_DEVICE_TASKPRI + 0xB * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ5PRI2 (LOWEST_DEVICE_TASKPRI + 0xA * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ6PRI2 (LOWEST_DEVICE_TASKPRI + 0x9 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ7PRI2 (LOWEST_DEVICE_TASKPRI + 0x8 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ8PRI2 (LOWEST_DEVICE_TASKPRI + 0x7 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQ9PRI2 (LOWEST_DEVICE_TASKPRI + 0x6 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQAPRI2 (LOWEST_DEVICE_TASKPRI + 0x5 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQBPRI2 (LOWEST_DEVICE_TASKPRI + 0x4 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQCPRI2 (LOWEST_DEVICE_TASKPRI + 0x3 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQDPRI2 (LOWEST_DEVICE_TASKPRI + 0x2 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQEPRI2 (LOWEST_DEVICE_TASKPRI + 0x1 * CBUS_MAX_BRIDGES + 1)
+#define EISA_IRQFPRI2 (LOWEST_DEVICE_TASKPRI + 1)
+
+//
+// you would think EISA_IRQ0PRI would be equivalent to
+// (LOWEST_DEVICE_TASKPRI + 0x1 * CBUS_MAX_BRIDGES - 1).
+// however irq0 is the system clock and is instead set to CLOCK2_TASKPRI.
+//
+// EISA_IRQ8PRI (irq8) is the profile interrupt, and is also
+// special-cased in a similar fashion.
+//
+
+#define EISA_IRQ0PRI CBUS2_CLOCK_TASKPRI
+#define EISA_IRQ8PRI CBUS2_PROFILE_TASKPRI
+
+#define UNUSED_PRI HIGHEST_DEVICE_TASKPRI
+
+//
+// 186 priorities (0xE9-0x30+1) are available for device hardware.
+// Vectors and IRQLs are given out in HalGetInterruptVector(). Since
+// drivers can be dynamically linked in at any time, leave
+// space so that they can be given roughly the same priorities as in a
+// PC-environment. ie: IRQL(EISA irq0) > IRQL(EISA irq15), and so on,
+// in order to mimic the standard Microsoft uniprocessor HAL.
+//
+// 23 distinct IRQL levels are left for us (by the kernel) to give to
+// various hardware devices. Multiple drivers will be allowed to share
+// any given IRQL level, although they will be given different VECTORS.
+//
+// All native Cbus2 I/O will be given priorities higher than that
+// of any EISA device. This is because Cbus2 drivers will generally
+// be written by Corollary, and thus guaranteed to have short ISRs, fully
+// utilizing the DPC mechanism.
+//
+// The high 8 IRQL levels are reserved for native Cbus2 drivers.
+// the 16 hardware interrupts for each Cbus2 CBC will be given IRQL
+// priority on a "lower local irq line gets higher priority IRQL" basis.
+//
+// The low 15 IRQLs are for EISA devices, with
+// EISA irql == EISA irq + LOWEST_DEVICE_TASKPRI.
+// EISA irq lines on each bus are assigned identical IRQLs.
+// irq2 (slave 8259), irq0 (clock) and irq8 (profile) are
+// included in these calculations despite the fact that irq2 can't happen,
+// and irq0/irq8 are assigned special (higher) priorities above.
+// They are included because multiple I/O buses are a feature of
+// Cbus2, and the irq0/irq8 of the second I/O bus could be wired
+// up to devices other than 8254 or RTC clocks.
+//
+
+#define EISA_IRQLS 15
+
+#define EISA_LOW_IRQL (DISPATCH_LEVEL + 1)
+#define EISA_HIGH_IRQL (EISA_LOW_IRQL + EISA_IRQLS - 1)
+#define CBC_HIGH_IRQL (PROFILE_LEVEL - 1)
+
+//
+// Limit to 9 I/O CBCs for now: 154 (0xe9 - 0x50 + 1) vectors are available
+// after the dual EISAs and kernel vectors are assigned. Divide this up
+// amongst 16 hardware interrupt map entries per CBC, and 9 is what you get.
+// Note that to allow more than 9 active I/O CBCs, they cannot all
+// be using all their interrupt lines, since there are not enough IDT
+// entries to give them all unique vectors.
+//
+// This limitation should never be a problem, as it is generally
+// unlikely that more than a few interrupt lines per Cbus2 native I/O CBC will
+// be used.
+//
+#define NCBC_BUCKETS 9
+
+//
+// each pair of adjacent Cbus2 CBC irqlines on all CBCs will be mapped
+// to the same IRQL. ie: CBC 0..n will have IRQL 27 assigned for hardware
+// interrupt map entries 0 & 1 on these CBCs. This is because after EISA
+// Irql assignments, there are only 8 Irql levels left, and 16
+// CBC hardware interrupt lines can request vectors and levels.
+//
+#define CBC_IRQL_GROUPING 2 // each pair of lines shares an Irql
+
+#define HIGHEST_CBC_TASKPRI HIGHEST_DEVICE_TASKPRI // 0xEA
+
+#if (HIGH_LEVEL + 1 != 32)
+Cause error to get attention:
+Cbus2IrqlToVector[] must be built and indexed properly
+#endif
+
+#if DBG
+#define MAX_ELEMENT_CSRS 15
+
+#if (CBUS2_BROADCAST_TASKPRI_HIGH - CBUS2_BROADCAST_TASKPRI_LOW + 1 != MAX_ELEMENT_CSRS)
+cause error to get attention - above task priority assignment must
+leave a broadcast priority for each potential Cbus2 processor in the system.
+this set of priorities MUST be higher than CLOCK2, _AND_ less than IPI,
+so that IPI_IRQL/IPI_TASKPRI will be sufficient to block any of the
+broadcast priorities.
+#endif
+#endif
+
+//
+// since each Irql will hold CBUS_MAX_BRIDGES lines at that priority, ensure
+// that the Cbus2 Irql array masks off all lines at a given Irql priority...
+//
+#define MAX_EISA_PRIORITY(eisa_taskpri) (eisa_taskpri + CBUS_MAX_BRIDGES - 1)
+
+#define MAX_CBC_PRIORITY(cbc_taskpri) \
+ (cbc_taskpri + CBC_IRQL_GROUPING * NCBC_BUCKETS - 1)
+
+ULONG Cbus2IrqlToVector[HIGH_LEVEL + 1 ] = {
+
+ LOW_TASKPRI,
+ APC_TASKPRI,
+ DPC_TASKPRI,
+ MAX_EISA_PRIORITY(EISA_IRQFPRI),
+
+ MAX_EISA_PRIORITY(EISA_IRQEPRI),
+ MAX_EISA_PRIORITY(EISA_IRQDPRI),
+ MAX_EISA_PRIORITY(EISA_IRQCPRI),
+ MAX_EISA_PRIORITY(EISA_IRQBPRI),
+
+ MAX_EISA_PRIORITY(EISA_IRQAPRI),
+ MAX_EISA_PRIORITY(EISA_IRQ9PRI),
+ EISA_IRQ8PRI2, // used on second bridge only
+ MAX_EISA_PRIORITY(EISA_IRQ7PRI),
+
+ MAX_EISA_PRIORITY(EISA_IRQ6PRI),
+ MAX_EISA_PRIORITY(EISA_IRQ5PRI),
+ MAX_EISA_PRIORITY(EISA_IRQ4PRI),
+ MAX_EISA_PRIORITY(EISA_IRQ3PRI),
+
+ EISA_IRQ2PRI2, // used on second bridge only
+ MAX_EISA_PRIORITY(EISA_IRQ1PRI),
+ EISA_IRQ0PRI2, // used on second bridge only
+ HIGHEST_DEVICE_TASKPRI - 7 * CBC_IRQL_GROUPING * NCBC_BUCKETS,
+
+ HIGHEST_DEVICE_TASKPRI - 6 * CBC_IRQL_GROUPING * NCBC_BUCKETS,
+ HIGHEST_DEVICE_TASKPRI - 5 * CBC_IRQL_GROUPING * NCBC_BUCKETS,
+ HIGHEST_DEVICE_TASKPRI - 4 * CBC_IRQL_GROUPING * NCBC_BUCKETS,
+ HIGHEST_DEVICE_TASKPRI - 3 * CBC_IRQL_GROUPING * NCBC_BUCKETS,
+
+ HIGHEST_DEVICE_TASKPRI - 2 * CBC_IRQL_GROUPING * NCBC_BUCKETS,
+ HIGHEST_DEVICE_TASKPRI - CBC_IRQL_GROUPING * NCBC_BUCKETS,
+ HIGHEST_DEVICE_TASKPRI,
+ CBUS2_PROFILE_TASKPRI,
+
+ CBUS2_CLOCK_TASKPRI,
+ CBUS2_IPI_TASKPRI,
+ CBUS2_POWER_TASKPRI,
+ HIGH_TASKPRI,
+};
+
+//
+// A table converting software interrupt Irqls to Cbus2-specific offsets
+// within a given CSR space. Note that all task priorities are shifted
+// by the Cbus2 register width (64 bits) to create the correct hardware
+// offset to poke to cause the interrupt. This table is declared here to
+// optimize the assembly software interrupt request lookup, and is filled
+// in as part of InitializePlatform.
+//
+
+#define CBUS2_REGISTER_SHIFT 3
+
+//
+// Although the IrqlToAddr table is really used only to speed up software
+// interrupt dispatching, it is filled in for all possible IRQLs.
+//
+ULONG Cbus2IrqlToCbus2Addr[HIGH_LEVEL + 1];
+
+#if (MAX_EISA_PRIORITY(EISA_IRQ1PRI) >= \
+ HIGHEST_DEVICE_TASKPRI - 8 * CBC_IRQL_GROUPING * NCBC_BUCKETS)
+Cause error to get attention: Cbus2 & EISA vectors must not overlap
+#endif
+
+
+#define EISA_IRQLINES 16
+
+typedef struct _cbus2_irqline_t {
+ ULONG Vector;
+ KIRQL Irql;
+} CBUS2_IRQLINE_T, *PCBUS2_IRQLINE;
+
+//
+// map EISA irqline to Cbus2 programmable vectors & IRQL levels...
+//
+
+CBUS2_IRQLINE_T Cbus2EISAIrqlines[CBUS_MAX_BRIDGES][EISA_IRQLINES] =
+{
+ EISA_IRQ0PRI, CLOCK2_LEVEL,
+ EISA_IRQ1PRI, EISA_LOW_IRQL+0xE, // Irql 11
+ EISA_IRQ2PRI, PROFILE_LEVEL -1,
+ EISA_IRQ3PRI, EISA_LOW_IRQL+0xC, // Irql F
+
+ EISA_IRQ4PRI, EISA_LOW_IRQL+0xB,
+ EISA_IRQ5PRI, EISA_LOW_IRQL+0xA,
+ EISA_IRQ6PRI, EISA_LOW_IRQL+0x9,
+ EISA_IRQ7PRI, EISA_LOW_IRQL+0x8, // Irql B
+
+ EISA_IRQ8PRI, PROFILE_LEVEL,
+ EISA_IRQ9PRI, EISA_LOW_IRQL+6,
+ EISA_IRQAPRI, EISA_LOW_IRQL+5,
+ EISA_IRQBPRI, EISA_LOW_IRQL+4, // Irql 7
+
+ EISA_IRQCPRI, EISA_LOW_IRQL+3,
+ EISA_IRQDPRI, EISA_LOW_IRQL+2,
+ EISA_IRQEPRI, EISA_LOW_IRQL+1,
+ EISA_IRQFPRI, EISA_LOW_IRQL, // Irql 3
+
+ EISA_IRQ0PRI2, EISA_LOW_IRQL+0xF, // Irql 13
+ EISA_IRQ1PRI2, EISA_LOW_IRQL+0xE,
+ EISA_IRQ2PRI2, EISA_LOW_IRQL+0xD,
+ EISA_IRQ3PRI2, EISA_LOW_IRQL+0xC, // Irql F
+
+ EISA_IRQ4PRI2, EISA_LOW_IRQL+0xB,
+ EISA_IRQ5PRI2, EISA_LOW_IRQL+0xA,
+ EISA_IRQ6PRI2, EISA_LOW_IRQL+0x9,
+ EISA_IRQ7PRI2, EISA_LOW_IRQL+0x8, // Irql B
+
+ EISA_IRQ8PRI2, EISA_LOW_IRQL+7,
+ EISA_IRQ9PRI2, EISA_LOW_IRQL+6,
+ EISA_IRQAPRI2, EISA_LOW_IRQL+5,
+ EISA_IRQBPRI2, EISA_LOW_IRQL+4, // Irql 7
+
+ EISA_IRQCPRI2, EISA_LOW_IRQL+3,
+ EISA_IRQDPRI2, EISA_LOW_IRQL+2,
+ EISA_IRQEPRI2, EISA_LOW_IRQL+1,
+ EISA_IRQFPRI2, EISA_LOW_IRQL // Irql 3
+};
+
+//
+// map Cbus2 hardware interrupt irqlines
+// to Cbus2 programmable vectors & IRQL levels...
+//
+
+CBUS2_IRQLINE_T Cbus2CBCIrqlines[REV1_HWINTR_MAP_ENTRIES] =
+{
+ HIGHEST_CBC_TASKPRI - NCBC_BUCKETS + 1, CBC_HIGH_IRQL,
+ HIGHEST_CBC_TASKPRI - 2 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL,
+ HIGHEST_CBC_TASKPRI - 3 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 1,
+ HIGHEST_CBC_TASKPRI - 4 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 1,
+
+ HIGHEST_CBC_TASKPRI - 5 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 2,
+ HIGHEST_CBC_TASKPRI - 6 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 2,
+ HIGHEST_CBC_TASKPRI - 7 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 3,
+ HIGHEST_CBC_TASKPRI - 8 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 3,
+
+ HIGHEST_CBC_TASKPRI - 9 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 4,
+ HIGHEST_CBC_TASKPRI -10 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 4,
+ HIGHEST_CBC_TASKPRI -11 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 5,
+ HIGHEST_CBC_TASKPRI -12 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 5,
+
+ HIGHEST_CBC_TASKPRI -13 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 6,
+ HIGHEST_CBC_TASKPRI -14 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 6,
+ HIGHEST_CBC_TASKPRI -15 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 7,
+ HIGHEST_CBC_TASKPRI -16 * NCBC_BUCKETS + 1, CBC_HIGH_IRQL - 7,
+};
+
+CCHAR HalpFindFirstSetRight[256] = {
+ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+
+VOID
+HalpClockInterruptPx( VOID );
+
+NTSTATUS
+HalpNoAdjustResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpNoAssignSlotResources (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpProfileInterruptPx( VOID );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG
+Cbus2GetCbusData(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+Cbus2SetCbusData(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// defines for resetting the keyboard controller used
+// in Cbus2ResetAllOtherProcessors().
+//
+#define RESET 0xfe
+#define KEYBPORT (PUCHAR )0x64
+
+#define BRIDGE0 0
+#define IRQ0 0
+#define IRQ8 8
+
+extern ULONG ProfileVector;
+extern ULONG CbusClockVector;
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+//
+//
+// Cbus2 switch table entry routines begin here
+//
+//
+
+
+/*++
+
+Routine Description:
+
+ This routine is called only once from HalInitProcessor() at Phase 0
+ by the boot cpu. All other cpus are still in reset.
+
+ software(APC, DPC, wake) and IPI vectors have already been initialized
+ and enabled.
+
+ all we're doing here is setting up some software structures for two
+ EISA interrupts (clock and profile) so they can be enabled later.
+
+ The bus handler data structures are not initialized until Phase 1,
+ so HalGetInterruptVector() may not be called before Phase1.
+
+ Hence we cannot pass a valid BusHandler parameter to the Tie code.
+ That's ok, since it doesn't currently use it.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2SetupPrivateVectors(VOID)
+{
+ PVOID OpaqueClock;
+ PVOID OpaqueProfile;
+
+ //
+ // we are defaulting to the EISA (or MCA) bridge 0
+ // for all of these interrupts which need enabling during Phase 0.
+ //
+
+ //
+ // unfortunately, we had hardcode the vectors onto bridge 0 - this // is because there is no legitimate bus handler structure to pass
+ // around at this time during startup.
+ //
+ if (Cbus2InterruptController == ELEMENT_HAS_CBC) {
+
+ OpaqueClock = Cbus2LinkVector((PBUS_HANDLER)BRIDGE0,
+ CbusClockVector, IRQ0);
+ OpaqueProfile = Cbus2LinkVector((PBUS_HANDLER)BRIDGE0,
+ ProfileVector, IRQ8);
+ }
+ else {
+ ASSERT (Cbus2InterruptController == ELEMENT_HAS_APIC);
+
+ OpaqueClock = CbusApicLinkVector((PBUS_HANDLER)BRIDGE0,
+ CbusClockVector, IRQ0);
+
+ OpaqueProfile = CbusApicLinkVector((PBUS_HANDLER)BRIDGE0,
+ ProfileVector, IRQ8);
+ }
+
+ CbusPreparePhase0Interrupts(CbusClockVector, IRQ0, OpaqueClock);
+ CbusPreparePhase0Interrupts(ProfileVector, IRQ8, OpaqueProfile);
+}
+
+
+/*++
+
+Routine Description:
+
+ This function calculates the stall execution, and initializes the
+ HAL-specific hardware device (CLOCK & PROFILE) interrupts for the
+ Corollary Cbus1 architecture.
+
+Arguments:
+
+ Processor - Supplies a logical processor number to initialize
+
+Return Value:
+
+ VOID
+
+--*/
+
+VOID
+Cbus2InitializeInterrupts(
+IN ULONG Processor
+)
+{
+ //
+ // Cbus2: stall uses the RTC irq8 to figure it out (needed in phase0).
+ // the clock uses the irq0 (needed in phase0)
+ // the perfcounter uses RTC irq8 (not needed till all cpus boot)
+ //
+ // Cbus1: stall uses the APIC to figure it out (needed in phase0).
+ // the clock uses the APIC (needed in phase0)
+ // the perfcounter uses irq0 (not needed till all cpus boot)
+ // the profile uses RTC irq8 (not needed till all cpus boot)
+ //
+
+ if (Processor == 0) {
+ //
+ // we must be at Phase0 of system initialization. we need to
+ // assign vectors for interrupts needed during Phase0.
+ // currently the 8254 clock and the RTC CMOS interrupts are
+ // needed during Phase0.
+ //
+
+ Cbus2ClockVector = CbusIrqlToVector[CLOCK2_LEVEL];
+ Cbus2SetupPrivateVectors();
+ }
+
+ Cbus2InitializeStall(Processor);
+
+ //
+ // Call the hardware backend handler to generate an
+ // interrupt every 10 milliseconds to be used as the system timer.
+ //
+
+ Cbus2InitializeClock();
+
+ //
+ // Set up and enable the irq0 performance counter and irq8 profile
+ // interrupts. Also enable the APIC clocks. This also registers
+ // the resources being used by these interrupts so other subsystems
+ // know the HAL has reserved them.
+ //
+
+ Cbus2InitializeDeviceIntrs(Processor);
+
+ //
+ // APC, DPC and IPI have already been initialized and enabled
+ // as part of HalInitializeProcessor.
+ //
+}
+
+/*++
+
+Routine Description:
+
+ Determine if the supplied vector belongs to an EISA device - if so,
+ then the corresponding bridge's CBC hardware interrupt map entry
+ will need to be modified to enable the line, so return FALSE here.
+
+ Otherwise, just enable this processor's interrupt configuration register
+ for the supplied vector and return TRUE immediately. note that for
+ non-device (software) interrupts, generally no CbusVectorTable[] entries
+ have been set up.
+
+Arguments:
+
+ Vector - Supplies a vector number to enable
+
+Return Value:
+
+ TRUE if the vector was enabled, FALSE if not.
+
+--*/
+BOOLEAN
+Cbus2EnableNonDeviceInterrupt(
+IN ULONG Vector
+)
+{
+ PCSR csr;
+
+ //
+ // if pure software interrupt, setting the calling processor's
+ // CBC entry to accept the interrupt is sufficient.
+ //
+ if (Cbus2InterruptController == ELEMENT_HAS_APIC) {
+ //
+ // If pure software interrupt, no action needed.
+ // Note both APIC timer interrupts and IPIs are
+ // treated as "software" interrupts. The EOI
+ // address still needs to be set up here.
+ //
+ if (Vector != CBUS2_SPURIOUS_TASKPRI)
+ CbusVectorToEoi[Vector] = CbusApicVectorToEoi(Vector);
+
+ if (Vector < LOWEST_DEVICE_TASKPRI || Vector > CBUS2_CLOCK_TASKPRI) {
+ return TRUE;
+ }
+
+ //
+ // indicate that Enable_Device_Interrupt will need to be run
+ // in order to enable this vector, as it associated with an I/O
+ // bus device which will need enabling within a locked critical
+ // section.
+ //
+
+ return FALSE;
+ }
+
+ //
+ // the spurious vector doesn't need any interrupt configuration mucking
+ //
+ if (Vector == CBUS2_SPURIOUS_TASKPRI) {
+ return TRUE;
+ }
+
+ csr = (PCSR)KeGetPcr()->HalReserved[PCR_CSR];
+
+ if (Vector < LOWEST_DEVICE_TASKPRI) {
+ csr->InterruptConfiguration[Vector].csr_register =
+ HW_IMODE_ALLINGROUP;
+
+ return TRUE;
+ }
+
+ //
+ // if just IPI, setting the calling processor's
+ // CBC entry to accept the interrupt is sufficient.
+ //
+
+ if (Vector >= CBUS2_REBOOT_TASKPRI && Vector <= CBUS2_IPI_TASKPRI) {
+ csr->InterruptConfiguration[Vector].csr_register =
+ HW_IMODE_ALLINGROUP;
+ return TRUE;
+ }
+
+ //
+ // indicate that EnableDeviceInterrupt will need to be run
+ // in order to enable this vector, as it is associated with an I/O
+ // bus device which will need enabling within a locked critical
+ // section.
+ //
+
+ return FALSE;
+}
+
+
+/*++
+
+Routine Description:
+
+ Enable the specified interrupt for the calling processor.
+ Note that the caller holds the HAL's CbusVectorLock at CLOCK_LEVEL
+ on entry.
+
+Arguments:
+
+ Vector - Supplies a vector number to enable
+
+ HardwarePtr - Supplies a CSR address on some bridge or native Cbus2 I/O
+ card which will be generating the specified interrupt vector.
+
+ FirstAttach - TRUE if this is the first processor to enable the
+ specified vector
+
+ BusNumber - the bus number of the particular bustype.
+
+ Irqline - the irqline on the particular CBC that will be generating this
+ vector
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2EnableDeviceInterrupt(
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG FirstAttach,
+IN USHORT BusNumber,
+IN USHORT Irqline
+)
+{
+ PHWINTRMAP hwentry; // CBC entry generating the intr
+ PCSR io_csr; // CBC entry generating the intr
+ PCSR csr;
+ ULONG IrqPolarity;
+ ULONG BusBridge;
+ BOOLEAN LowestInGroup;
+ BOOLEAN LevelTriggered;
+
+ //
+ // All interrupts are lowest-in-group. However,
+ // clocks, profiling & IPIs must stay ALL-IN-GROUP.
+ //
+
+ switch (Vector) {
+
+ case CBUS2_CLOCK_TASKPRI:
+ case CBUS2_PROFILE_TASKPRI:
+ case CBUS2_POWER_TASKPRI:
+ LowestInGroup = FALSE;
+ break;
+
+ default:
+ //
+ // Only enable CBC LIG arbitration if we have more than
+ // one processor. This is an optimization for speed.
+ //
+ if (CbusProcessors > 1) {
+ LowestInGroup = TRUE;
+ }
+ else {
+ LowestInGroup = FALSE;
+ }
+ break;
+ }
+
+ //
+ // if we are enabling an Irqline on an SPP, then decrement
+ // the Irqline first. we artificially set the interrupt range
+ // to 1-4 from 0-3. there was generic HAL code that did not
+ // allow for allocation of 0.
+ //
+ BusBridge = Cbus2MapBusNumberToBridgeIndex(BusNumber);
+ if (BusBridge) {
+ Irqline--;
+ }
+
+ //
+ // if this is the _first_ processor to actually enable this
+ // interrupt, then we'll need to know what kind of interrupt it is.
+ //
+ if (Vector >= LOWEST_CBC_TASKPRI && Vector <= HIGHEST_CBC_TASKPRI) {
+
+ ASSERT ((Vector >= EISA_IRQ1PRI + CBUS_MAX_BRIDGES) &&
+ Vector != EISA_IRQ0PRI &&
+ Vector != EISA_IRQ8PRI);
+ //
+ // default for Cbus2 I/O cards is edge
+ // triggered (ie rising edge CBC).
+ //
+ LevelTriggered = FALSE;
+ }
+ else {
+ ASSERT ((Vector >= EISA_IRQFPRI &&
+ Vector < EISA_IRQ1PRI + CBUS_MAX_BRIDGES) ||
+ Vector == EISA_IRQ0PRI ||
+ Vector == EISA_IRQ8PRI);
+ //
+ // must be an EISA interrupt, so
+ // get the irq polarity for the specified bus...
+ //
+ ASSERT (Irqline < EISA_IRQLINES);
+
+ IrqPolarity=Cbus2IrqPolarity[BusBridge];
+
+ //
+ // Mark the caller's interrupt as falling
+ // (level) or rising (edge) triggered, based
+ // on the ELCR register we read earlier.
+ //
+ if (((IrqPolarity >> Irqline)) & 0x1) {
+ //
+ // if level triggered, we must program
+ // the CBC as falling edge.
+ //
+ LevelTriggered = TRUE;
+ }
+ else {
+ //
+ // if edge triggered, we must program
+ // the CBC as rising edge.
+ //
+ LevelTriggered = FALSE;
+ }
+ }
+
+ if (Cbus2InterruptController == ELEMENT_HAS_APIC) {
+ //
+ // The EOI address is set up here.
+ //
+ CbusVectorToEoi[Vector] = CbusApicVectorToEoi(Vector);
+
+ CbusEnableApicInterrupt(BusNumber, Vector, HardwarePtr,
+ FirstAttach, LowestInGroup, LevelTriggered);
+ return;
+ }
+
+ //
+ // Record the interrupt polarity so that the CBUS_EOI macro
+ // can more easily determine if the level-triggered hardware
+ // workaround for CBC-2 is required.
+ //
+ if (LevelTriggered == TRUE) {
+ Cbus2InterruptPolarity[Vector]=CBUS2_LEVEL_TRIGGERED_INTERRUPT;
+ }
+ else {
+ Cbus2InterruptPolarity[Vector] = CBUS2_EDGE_TRIGGERED_INTERRUPT;
+ }
+
+ //
+ // Set up the processor side of the interrupt initialization.
+ // this needs to be done for ALL interrupts (ie: software,
+ // IPI, etc, as well as for real hardware devices).
+ // note that this must precede the I/O side of the initialization
+ // because an interrupt could be pending at initialization time
+ // (especially with a level-triggered interrupt) and the broadcast
+ // could occur before the processor side is set up.
+ // this would cause the interrupt to be missed with no way to EOI.
+ //
+ csr = (PCSR)KeGetPcr()->HalReserved[PCR_CSR];
+
+ //
+ // before allowing LIG interrupts, check to see that
+ // RRD has configured the system for LIG's. CBC-1 and
+ // CBC-2 did not support LIG.
+ //
+ if (LowestInGroup == TRUE) {
+ //
+ // allow OEMs to disable LIG from their ROMs...
+ // if they do this, each normally LIG device interrupt
+ // will go only to the first processor to enable it.
+ //
+ if (CbusGlobal.Cbus2Features & CBUS_ENABLED_LIG) {
+ csr->InterruptConfiguration[Vector].csr_register =
+ HW_IMODE_LIG;
+ }
+ else if (FirstAttach) {
+ csr->InterruptConfiguration[Vector].csr_register =
+ HW_IMODE_ALLINGROUP;
+ }
+ }
+ else {
+ csr->InterruptConfiguration[Vector].csr_register =
+ HW_IMODE_ALLINGROUP;
+ }
+
+ if (FirstAttach) {
+
+ //
+ // initialize the generating bridge or Cbus2 native card's CBC
+ // that will be generating this interrupt.
+ //
+ io_csr = (PCSR)HardwarePtr;
+ hwentry = &io_csr->HardwareInterruptMap[Irqline];
+
+ //
+ // Set up the EOI address now that we know which
+ // bridge's CBC will need it.
+ //
+ CbusVectorToEoi[Vector] = (PULONG)
+ &io_csr->HardwareInterruptMapEoi[Irqline];
+
+ //
+ // let the generating CBC know in a single dword access...
+ //
+
+ if (LevelTriggered == TRUE) {
+ Cbus2EoiToHwmap =
+ (int)Cbus2BridgeCSR[BRIDGE0]->HardwareInterruptMapEoi -
+ (int)Cbus2BridgeCSR[BRIDGE0]->HardwareInterruptMap;
+ CbusVectorToHwmap[Vector] = (HW_LEVEL_LOW | Vector);
+ hwentry->csr_register = (HW_LEVEL_LOW | Vector);
+ }
+ else {
+ CbusVectorToHwmap[Vector] = (HW_EDGE_RISING | Vector);
+ hwentry->csr_register = (HW_EDGE_RISING | Vector);
+ }
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Disable the specified interrupt so it can not occur on the calling
+ processor upon return from this routine. Note that the caller holds
+ the HAL's CbusVectorLock at CLOCK_LEVEL on entry.
+
+Arguments:
+
+ Vector - Supplies a vector number to disable
+
+ HardwarePtr - Supplies a hardware interrupt map entry address on
+ the CBC of the bridge whose Vector is specified
+
+ LastDetach - TRUE if this is the last processor to detach from the
+ specified vector
+
+ Irqline - the irqline this vector is coming in on
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2DisableInterrupt(
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG LastDetach,
+IN USHORT BusNumber,
+IN USHORT Irqline
+)
+{
+ PHWINTRMAP hwentry; // CBC entry generating the intr
+ PCSR csr;
+
+ if (Cbus2InterruptController == ELEMENT_HAS_APIC) {
+ CbusDisableApicInterrupt(BusNumber, Vector, HardwarePtr,
+ LastDetach);
+ return;
+ }
+
+ //
+ // Only the vector matters to us, irql is irrelevant.
+ // tell the world that _this processor_ is no longer
+ // participating in receipt of this interrupt.
+ //
+
+ csr = (PCSR)(KeGetPcr()->HalReserved[PCR_CSR]);
+ csr->InterruptConfiguration[Vector].csr_register = HW_IMODE_DISABLED;
+
+ //
+ // No need to actually reach out to the specific I/O CBC, but
+ // if this is the last CPU to detach, turn off the
+ // I/O CBC entry which generates the specified interrupt.
+ // (this is cleaner from a hardware perspective).
+ //
+
+ if (LastDetach) {
+ hwentry = (PHWINTRMAP)HardwarePtr;
+
+ if (Vector >= LOWEST_DEVICE_TASKPRI &&
+ Vector < CBUS2_BROADCAST_TASKPRI_LOW)
+ hwentry->csr_register = HW_MODE_DISABLED;
+ }
+}
+
+
+
+
+/*++
+
+Routine Description:
+
+ Remove reset from the specified processor, allowing him to boot,
+ beginning execution at the specified start address.
+
+Arguments:
+
+ Processor - Supplies a logical processor number to boot
+
+ StartAddress - Supplies a start address containing real-mode code
+ for the processor to execute.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2BootCPU (
+IN ULONG Processor,
+IN ULONG StartAddress
+)
+{
+ PULONG ResetAddress;
+
+ //
+ // For Cbus2, the only hardware dependency when booting
+ // additional processors is to put the real-mode starting
+ // CS/EIP in 0x467 (the warm reset vector), and clear reset
+ // on the specified CPU. The start address has already been
+ // set up, so here just remove reset.
+ //
+
+ UNREFERENCED_PARAMETER( StartAddress );
+
+ ResetAddress = (PULONG)((PUCHAR)CbusCSR[Processor].csr +
+ CbusGlobal.smp_creset);
+
+ *ResetAddress = CbusGlobal.smp_creset_val;
+}
+
+/*++
+
+Routine Description:
+
+ Overlay the irql-to-vector mappings with the Cbus2
+ vector maps. Initialize the broadcast IPI address and the
+ "Irql-To-Cbus2-Hardware-Address" translation table.
+
+ Also read the EISA interrupt edge/level specifications for
+ later use when enabling various EISA interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2InitializePlatform(VOID)
+{
+ ULONG Index;
+ LONG Irql;
+ ULONG LowerVector;
+ ULONG Vector;
+ ULONG i;
+ extern ULONG CbusVectorToIrql[MAXIMUM_IDTVECTOR + 1];
+
+ //
+ // pick up the the EISA interrupt edge/level requests
+ //
+
+ Cbus2InitInterruptPolarity();
+
+ //
+ // overlay the irql-to-vector mappings with the Cbus2 layout
+ //
+
+ RtlMoveMemory( (PVOID)CbusIrqlToVector,
+ (PVOID)Cbus2IrqlToVector,
+ (HIGH_LEVEL + 1) * sizeof (ULONG));
+
+ for (Index = 0; Index < HIGH_LEVEL + 1; Index++) {
+#ifdef CBC_REV1
+ Cbus2IrqlToCbus2Addr[Index] =
+ (Cbus2IrqlToVector[Index] << CBUS2_REGISTER_SHIFT) +
+ FIELD_OFFSET(CSR_T, InterruptRequest);
+#else
+ Cbus2IrqlToCbus2Addr[Index] =
+ (ULONG)(Cbus2IdentityCSR->InterruptRequest) +
+ (Cbus2IrqlToVector[Index] << CBUS2_REGISTER_SHIFT);
+#endif
+ }
+
+ CbusRedirVector = CBUS2_REDIR_IPI;
+ CbusRebootVector = CBUS2_REBOOT_TASKPRI;
+
+ //
+ // build the "vector-to-irql" mappings here for fast
+ // translation when accepting an interrupt. this is
+ // better than continually keeping fs:PcIrql updated,
+ // as it allows us to remove instructions from KfRaiseIrql
+ // and KfLowerIrql, the hot paths. Although this is done
+ // for each interrupt as it is individually enabled, this
+ // must also be done here for Cbus2 since multiple vectors
+ // can be grouped into a shared irql - this isn't done in
+ // Cbus1 because there isn't the concept of supporting multiple
+ // different kinds of I/O busses simultaneously.
+ //
+ for (Irql = HIGH_LEVEL; Irql > 0; Irql--) {
+ Vector = Cbus2IrqlToVector[Irql];
+ LowerVector = Cbus2IrqlToVector[Irql - 1];
+ for (i = Vector; i > LowerVector; i--) {
+ CbusVectorToIrql[i] = Irql;
+ }
+ }
+
+ //
+ // The PCI bus number of the default C-bus II PCI bus bridge
+ // must be 0. At initialization time, the additional bus
+ // bridges should be set to 0xFF. they will be properly
+ // initialized in Cbus2InitiailizeOtherPCIBus().
+ //
+ for (Index = 1; Index < Cbus2BridgesFound; Index++) {
+ Cbus2BridgePCIBusNumber[Index] = 0xFF;
+ }
+ Cbus2BridgePCIBusNumber[0] = 0;
+
+ //
+ // Check if this is a PELE platform.
+ // If so, it uses a different interrupt routing
+ // algorithm for the 2nd bus.
+ //
+ Cbus2PeleSystemFound = Cbus2CheckForPeleSystem();
+}
+
+/*++
+
+Routine Description:
+
+ Initialize this processor's CSR, interrupts, spurious interrupts & IPI
+ vector, using the CBC (not the APIC) for interrupt control.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2InitializeCBC(
+IN ULONG Processor
+)
+{
+ PCSR csr;
+ PCSR Broadcast;
+ ULONG Index, ThisElement, Vector;
+
+ ASSERT (Cbus2InterruptController == ELEMENT_HAS_CBC);
+ //
+ // Map this CPU's CSR stuff into his local
+ // address space for fast access.
+ //
+ csr = (PCSR)CbusCSR[Processor].csr;
+
+ //
+ // save the interrupt address for this processor for
+ // streamlining the interrupt code
+ //
+ Cbus2SendIPI[Processor] =
+ (PULONG)&(csr->InterruptRequest[CBUS2_IPI_TASKPRI]);
+
+ //
+ // map in the task priority register and start off at
+ // IRQL 0 - we are still protected by cli.
+ //
+#ifdef CBC_REV1
+ (PTASKPRI) KeGetPcr()->HalReserved[PCR_TASKPRI] = &csr->TaskPriority;
+ csr->TaskPriority.csr_register = 0;
+#else
+ (PTASKPRI) KeGetPcr()->HalReserved[PCR_TASKPRI] =
+ &Cbus2IdentityCSR->TaskPriority;
+ Cbus2IdentityCSR->TaskPriority.csr_register = 0;
+#endif
+
+ //
+ // Create the spurious interrupt IDT entry for this processor
+ //
+ KiSetHandlerAddressToIDT(CBUS2_SPURIOUS_TASKPRI, HalpSpuriousInterrupt);
+
+ //
+ // initialize the spurious vector for the CBC
+ // to generate when it detects inconsistencies.
+ //
+ csr->SpuriousVector.csr_register = CBUS2_SPURIOUS_TASKPRI;
+
+ HalEnableSystemInterrupt(CBUS2_SPURIOUS_TASKPRI, HIGH_LEVEL, Latched);
+
+ //
+ // generate NMIs (trap 2) when we get error interrupts. enabled
+ // faults already generate NMI traps by default.
+ //
+ csr->ErrorVector.LowDword = 2;
+ csr->InterruptControl.LowDword = CbusGlobal.InterruptControlMask;
+ csr->FaultControl.LowDword = CbusGlobal.FaultControlMask;
+
+ ThisElement = Processor;
+ Broadcast = (PCSR)CbusBroadcastCSR;
+
+ //
+ // This processor participates in all broadcast IPIs
+ // except for ones sent by this processor.
+ //
+ Vector = CBUS2_BROADCAST_TASKPRI_LOW;
+
+ for (Index = 0; Index < MAX_ELEMENT_CSRS; Index++, Vector++) {
+
+ if (Index == ThisElement) {
+
+ //
+ // Map this element's broadcast interrupt entry
+ // to streamline the IPI sending code, because
+ // this is not done easily by the hardware.
+ //
+
+ (ULONG)KeGetPcr()->HalReserved[PCR_BROADCAST] =
+ (ULONG)&Broadcast->InterruptRequest[Vector];
+ if (Cbus2EnableBroadcast == 0) {
+ KiSetHandlerAddressToIDT(Vector,HalpIpiHandler);
+ HalEnableSystemInterrupt(Vector,
+ IPI_LEVEL, Latched);
+ }
+ }
+ else {
+ if (Cbus2EnableBroadcast) {
+ KiSetHandlerAddressToIDT(Vector,HalpIpiHandler);
+ HalEnableSystemInterrupt(Vector,
+ IPI_LEVEL, Latched);
+ }
+ }
+ }
+
+ //
+ // Also initialize the directed IPI entry for this processor.
+ //
+ KiSetHandlerAddressToIDT(CBUS2_IPI_TASKPRI, HalpIpiHandler);
+ HalEnableSystemInterrupt(CBUS2_IPI_TASKPRI, IPI_LEVEL, Latched);
+
+ //
+ // Create an interrupt gate so processors can
+ // be stopped cleanly prior to rebooting the system.
+ //
+ KiSetHandlerAddressToIDT(CBUS2_REBOOT_TASKPRI,
+ CbusRebootHandler);
+ HalEnableSystemInterrupt(CBUS2_REBOOT_TASKPRI,
+ IPI_LEVEL, Latched);
+}
+
+/*++
+
+Routine Description:
+
+ Initialize all the I/O Apics in the system. This includes I/O APICs
+ on the EISA bridges, as well as any that may exist on native Cbus2
+ I/O boards.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2InitializeApic(
+IN ULONG Processor
+)
+{
+ ULONG BridgeIndex;
+ ULONG WindowBaseAddress;
+ ULONG WindowBaseAddressShifted;
+ ULONG WindowOffsetAddress;
+ ULONG CsrPhysicalAddress;
+ WINDOWRELOC_T RegisterValue;
+ PCSR csr;
+ PCBUS2_ELEMENT Cbus2Element;
+ ULONG original_bridge;
+ ULONG BridgeId;
+
+ for (BridgeIndex = 0; BridgeIndex < Cbus2BridgesFound; BridgeIndex++) {
+ //
+ // since each EISA bridge will have the I/O APIC at the
+ // same physical address, we must make each one unique so
+ // references are guaranteed to get to the desired one.
+ // this is done by mapping them into each bridge's window 0
+ // relocation register, and thus onto the PCBusWindow0.
+ //
+ csr = (PCSR)Cbus2BridgeCSR[BridgeIndex];
+ CsrPhysicalAddress = Cbus2BridgeCSRPaddr[BridgeIndex].LowPart;
+ BridgeId = Cbus2BridgeId[BridgeIndex];
+
+ //
+ // save the original value for restoral after our I/O.
+ // repoint our I/O references to the desired bus bridge number.
+ //
+ original_bridge = csr->BusBridgeSelection.csr_register;
+ csr->BusBridgeSelection.csr_register =
+ ((original_bridge & ~MAX_ELEMENT_CSRS) | BridgeId);
+
+ //
+ // this field must be set to the high 9 bits of the desired
+ // address.
+ //
+ WindowBaseAddressShifted = ((ULONG)CBUS2_IO_APIC_LOCATION >> 23);
+ WindowBaseAddress = (WindowBaseAddressShifted << 23);
+ WindowOffsetAddress = (ULONG)CBUS2_IO_APIC_LOCATION-WindowBaseAddress;
+
+ RegisterValue.csr_register = csr->BridgeWindow0.csr_register;
+ RegisterValue.ra.WindowBase = WindowBaseAddressShifted;
+ csr->BridgeWindow0.csr_register = RegisterValue.csr_register;
+
+ Cbus2Element = (PCBUS2_ELEMENT)
+ (CsrPhysicalAddress - CBUS_CSR_OFFSET);
+
+ CbusInitializeIOApic(Processor,
+ (PVOID)((ULONG)&Cbus2Element->PCBusWindow0 + WindowOffsetAddress),
+ CBUS2_REDIR_IPI,
+ CBUS2_REBOOT_TASKPRI,
+ Cbus2IrqPolarity[BridgeIndex]);
+
+ //
+ // restore our default bridge references to what they were
+ // when we started...
+ //
+ csr->BusBridgeSelection.csr_register = original_bridge;
+ }
+
+ //
+ // NOTE:
+ // add above for native Cbus2 cards using APICs based on cbdriver.c
+ // this will also involve changes to the CbusInitializeIOApic code.
+ //
+}
+
+/*++
+
+Routine Description:
+
+ Initialize this processor's CSR, interrupts, spurious interrupts & IPI
+ vector. This routine is also responsible for setting the initial IRQL
+ value for this processor to 0 - this is so the first call to KfRaiseIrql
+ from the kernel will return a level 0 as the "previous level". note that
+ lowering the task priority to irql 0 is harmless at this point because
+ we are protected by cli.
+
+Arguments:
+
+ Processor - Supplies a logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2InitializeCPU(
+IN ULONG Processor
+)
+{
+ PCSR csr;
+ ULONG cbc_config;
+
+ //
+ // Disable all of this processor's incoming interrupts _AND_
+ // any generated by his local CBC (otherwise they could go to
+ // any processor). This has to be done regardless of whether
+ // APIC or CBC mode is being used.
+ //
+ Cbus2DisableMyInterrupts(Processor);
+
+ //
+ // Setup the interrupt controller as specified by RRD -
+ // currently we support either CBC or APIC...
+ //
+
+ if (Cbus2InterruptController == ELEMENT_HAS_CBC) {
+ Cbus2InitializeCBC(Processor);
+ }
+
+ else if (Cbus2InterruptController == ELEMENT_HAS_APIC) {
+ CbusInitializeLocalApic(Processor, CBUS2_LOCAL_APIC_LOCATION,
+ CBUS2_SPURIOUS_TASKPRI);
+
+ //
+ // Only the boot processor initializes all the I/O APICs
+ // on all the EISA bridges and native Cbus2 cards.
+ //
+
+ if (Processor == 0) {
+ Cbus2InitializeApic(Processor);
+ }
+ else {
+ KiSetHandlerAddressToIDT(CBUS2_REBOOT_TASKPRI,
+ CbusRebootHandler);
+ HalEnableSystemInterrupt(CBUS2_REBOOT_TASKPRI,
+ IPI_LEVEL, Latched);
+ }
+ }
+ else {
+ FatalError(MSG_OBSOLETE_PIC);
+ }
+
+ //
+ // Set up a pointer to the global system timer for all of the
+ // processors. We directly access this from our low-level
+ // assembly code.
+ //
+ // Since we are setting this in global C-bus address space
+ // by using the broadcast mechanism, all the processors
+ // can provide a uniform synchronized view via
+ // KeQueryPerformanceCounter.
+ //
+
+ if (Processor == 0) {
+ KeInitializeSpinLock(&Cbus2NMILock);
+
+ csr = (PCSR)CbusCSR[Processor].csr;
+
+ Cbus2TimeStamp0 = &csr->SystemTimer.LowDword;
+#ifdef CBC_REV1
+ CbusTimeStamp =
+ &((PCSR)CbusBroadcastCSR)->SystemTimer.LowDword;
+#else
+ CbusTimeStamp =
+ &((PCSR)Cbus2IdentityCSR)->SystemTimer.LowDword;
+#endif
+
+ if (CbusGlobal.Cbus2Features & CBUS_ENABLED_PW) {
+
+#if DBG
+ DbgPrint("Enabling posted writes\n");
+#endif
+
+ //
+ // if the posted-writes bit is enabled, then
+ // allow EISA I/O cycles to use posted writes.
+ //
+ // call a function here so the compiler won't use byte
+ // enables here - we must force a dword access.
+ //
+ cbc_config = Cbus2ReadCSR(&csr->CbcConfiguration.LowDword);
+ Cbus2WriteCSR(&csr->CbcConfiguration.LowDword,
+ cbc_config & ~CBC_DISABLE_PW);
+ }
+
+ //
+ // C-bus II hardware work-around that is causing less
+ // than optimal code in the CBUS_EOI macro.
+ //
+ if ((CbusGlobal.Cbus2Features &
+ CBUS_DISABLE_LEVEL_TRIGGERED_INT_FIX) == 0) {
+ Cbus2FixLevelInterrupts = 1;
+ }
+
+ //
+ // C-bus II hardware work-around for spurious interrupts
+ // on IRQ0 when edge-triggered interrupts are EOI'd
+ // and the interrupt is high. work-around consists of
+ // detecting spurious clock interrupts in Cbus2ClockInterrupt()
+ // and Cbus2ClockInterruptPx().
+ //
+ if ((CbusGlobal.Cbus2Features &
+ CBUS_DISABLE_SPURIOUS_CLOCK_CHECK) == 0) {
+ Cbus2CheckSpuriousClock = 1;
+ }
+
+ //
+ // C-bus II hardware work-around that prevents Cbus2RequestIpi()
+ // from using the CSR broadcast space for sending IPIs.
+ //
+ if ((CbusGlobal.Cbus2Features & CBUS_ENABLE_BROADCAST) == 1) {
+ Cbus2EnableBroadcast = 1;
+ }
+ }
+}
+
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ HalGetInterruptVector() must maintain a "vector to interrupt"
+ mapping so when the interrupt is enabled later via
+ HalEnableSystemInterrupt(), something intelligent can be done -
+ ie: which CBC's hardware interrupt maps to enable!
+ this applies both to EISA bridge CBCs and Cbus2 native I/O CBC's.
+
+ Note that HalEnableSystemInterrupt() will be CALLED by
+ EACH processor wishing to participate in the interrupt receipt.
+
+ Do not detect collisions here because interrupts are allowed to be
+ shared at a higher level - the ke\i386\intobj.c will take care of
+ the sharing. Just make sure that for any given irq line, only one
+ vector is generated, regardless of how many drivers may try to share
+ the line.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+ULONG
+Cbus2MapVector(
+IN PBUS_HANDLER RootHandler,
+IN ULONG BusInterruptLevel,
+IN ULONG BusInterruptVector,
+OUT PKIRQL Irql
+)
+{
+ ULONG SystemVector;
+ ULONG Index;
+
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ if (RootHandler->ConfigurationType == CbusConfiguration) {
+ //
+ // Each CBC interrupt line on each board
+ // gets a different interrupt vector, ie: irq3 on CBC 1
+ // gets a different vector from irq3 on CBC2.
+ //
+ SystemVector = Cbus2CBCIrqlines[BusInterruptLevel].Vector +
+ Cbus2MapBusNumberToBridgeIndex(RootHandler->BusNumber);
+
+ //
+ // Group each pair of CBC irqs into a single IRQL.
+ //
+ *Irql = Cbus2CBCIrqlines[BusInterruptLevel].Irql;
+ }
+ else {
+
+ //
+ // Must be EISA, ISA, PCI or MCA...
+ //
+ // For Cbus2, CBUS_MAX_BRIDGES(==2) entries have been allocated per
+ // NT IRQL level, with each irq line getting its own _vector_.
+ // However, the same irq on each EISA bus shares the same NT IRQL
+ // level, since not enough IRQLs are provided to make them
+ // unique also.
+ //
+
+ //
+ // note that EISA bus 0 gets the lower vector and EISA bus 1 gets
+ // the higher vector in each vector pair. this fact is relied
+ // upon by Cbus2EnableDeviceInterrupt().
+ //
+ Index = Cbus2MapBusNumberToBridgeIndex(RootHandler->BusNumber);
+ SystemVector = Cbus2EISAIrqlines[Index][BusInterruptLevel].Vector;
+
+ *Irql = Cbus2EISAIrqlines[Index][BusInterruptLevel].Irql;
+ }
+
+ return SystemVector;
+}
+
+
+/*++
+
+Routine Description:
+
+ "Link" a given vector to the passed BusNumber/irqline, returning
+ a "handle" that can be used to reference it later for operations
+ that must access the hardware (ie: Enable & DisableInterrupt).
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ Vector - Supplies the system interrupt vector corresponding to the
+ specified BusNumber/Irqline.
+
+ BusNumber - Supplies the bus number for the device.
+
+ Irqline - Supplies the IRQ line of the specified interrupt
+
+Return Value:
+
+ A hardware-specific pointer (actually a CSR hardware interrupt map address)
+ that is interpreted only by the Cbus2 backend.
+
+--*/
+PVOID
+Cbus2LinkVector(
+IN PBUS_HANDLER RootHandler,
+IN ULONG Vector,
+IN ULONG Irqline
+)
+{
+ PCSR csr;
+ PVOID Opaque;
+ extern PVOID CbusCBCtoCSR(ULONG);
+
+ if (Cbus2InterruptController == ELEMENT_HAS_APIC) {
+ Opaque = CbusApicLinkVector(RootHandler, Vector, Irqline);
+ return Opaque;
+ }
+
+ if (RootHandler && RootHandler->ConfigurationType == CbusConfiguration) {
+ //
+ // map the CBC hardware interrupt map on the Cbus2 native CBC
+ // that the hardware is attached to. note that this is
+ // purely a physical location issue; the access both to and from
+ // the driver's hardware is fully symmetric for ALL processors.
+ //
+ csr = (PCSR) CbusCBCtoCSR(
+ Cbus2MapBusNumberToBridgeIndex(RootHandler->BusNumber));
+ }
+ else {
+
+ //
+ // For any EISA interrupts, just point the caller at the
+ // corresponding bridge entry.
+ //
+ // Note also that this section of code is called by
+ // Cbus2SetupPrivateVectors() to set up CBC
+ // mappings at Phase0 for interrupts that must be enabled
+ // during Phase0. At that point in startup, the bus
+ // enumeration structures don't exist, so we default to
+ // EISA bridge 0 for any requests at that point in time.
+ //
+
+ if (!RootHandler)
+ csr = (PCSR)Cbus2BridgeCSR[BRIDGE0];
+ else
+ csr = (PCSR)Cbus2BridgeCSR[
+ Cbus2MapBusNumberToBridgeIndex(RootHandler->BusNumber)];
+ }
+
+ return (PVOID)csr;
+}
+
+//
+//
+// internal Cbus2 support routines begin here
+//
+//
+//
+
+/*++
+
+Routine Description:
+
+ by default, disable all of the calling processor's
+ interrupt configuration registers(ICR) so he will take no interrupts.
+ also disable all interrupts originating from his CBC, so
+ no other processor will get interrupts from any devices
+ attached to this CBC.
+
+ as each interrupt is enabled, it will need to be enabled
+ at this CBC, and also in each receiving processors' ICR.
+
+ all EISA bridges have had their interrupts disabled already.
+ as each interrupt is enabled, it will need to be enabled
+ at the bridge, and also on each processor participating
+ in the reception. this needs to be done for both APIC and CBC
+ modes.
+
+Arguments:
+
+ Processor - Supplies the caller's logical processor number whose
+ interrupts will be disabled
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2DisableMyInterrupts(
+IN ULONG Processor
+)
+{
+ ULONG Vector;
+ PCSR csr;
+
+ csr = (PCSR)KeGetPcr()->HalReserved[PCR_CSR];
+
+ for (Vector = 0; Vector < INTR_CONFIG_ENTRIES; Vector++) {
+ csr->InterruptConfiguration[Vector].csr_register =
+ HW_IMODE_DISABLED;
+ }
+
+ //
+ // In the midst of setting up the EISA element CBCs or
+ // processor CBCs (for those with native Cbus2 devices attached),
+ // a device interrupt that was pending in a bridge's
+ // 8259 ISRs may be lost. None should be fatal, even an
+ // 8042 keystroke, since the keyboard driver should do a flush
+ // on open, and thus recover in the same way the standard
+ // uniprocessor NT HAL does when it initializes 8259s.
+ //
+ // the hardware interrupt map entries for this processor's
+ // CBC are disabled by RRD prior to booting each processor,
+ // so it doesn't need to be done here.
+ //
+}
+
+/*++
+
+Routine Description:
+
+ Allocate an interrupt vector for a Cbus2 native device.
+
+Arguments:
+
+ BusHandler - Supplies the parent (ie: Internal) pointer
+
+ RootHandler - Supplies the bus (ie: Cbus2) for the device. For Cbus2
+ native I/O devices, the bus number is actually the CBC
+ number index in the CbusIoElements[] table.
+
+ BusInterruptLevel - Supplies the IRQ line of the specified interrupt
+
+ BusInterruptVector - Unused
+
+ Irql - Returns the IRQL associated with this interrupt request
+
+ Affinity - Returns the mask of processors participating in receipt
+ of this interrupt
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the
+ specified BusNumber/BusInterruptLevel.
+
+--*/
+ULONG
+Cbus2GetInterruptVector(
+IN PBUS_HANDLER BusHandler,
+IN PBUS_HANDLER RootHandler,
+IN ULONG BusInterruptLevel,
+IN ULONG BusInterruptVector,
+OUT PKIRQL Irql,
+OUT PKAFFINITY Affinity
+)
+{
+
+ extern ULONG CbusIoElementIndex;
+
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+#if 0
+ //
+ // can't do this because we don't include ntddk.h
+ //
+ ASSERT (RootHandler->InterfaceType == Cbus);
+#endif
+
+ if (BusInterruptLevel >= REV1_HWINTR_MAP_ENTRIES) {
+
+ //
+ // Illegal BusInterruptVector - do not connect.
+ //
+
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here...
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+/*++
+
+Routine Description:
+
+ Convert a PCI interrupt pin to an interrupt line.
+ Note that this work has already been done in
+ Cbus2HierarchicalPciBusSearch().
+
+Arguments:
+
+ BusHandler - Supplies the parent (ie: Internal) pointer
+
+ RootHandler - Supplies the bus for the device
+
+ SlotNumber - Slot number of request
+
+ PciData - PCI configuration data
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2PCIPin2CB2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+{
+}
+
+/*++
+
+Routine Description:
+
+ Convert a PCI interrupt line to an interrupt pin.
+ Note that this work has already been done in
+ Cbus2HierarchicalPciBusSearch().
+
+Arguments:
+
+ BusHandler - Supplies the parent (ie: Internal) pointer
+
+ RootHandler - Supplies the bus for the device
+
+ SlotNumber - Slot number of request
+
+ PciNewData - New PCI configuration data
+
+ PciOldData - Old PCI configuration data
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2PCICB2Line2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+{
+}
+
+/*++
+
+Routine Description:
+
+ Returns an interrupt range for the given PciSlot.
+
+Arguments:
+
+ BusHandler - Supplies the parent (ie: Internal) pointer
+
+ RootHandler - Supplies the bus for the device
+
+ PciSlot - Slot number of request
+
+ Interrupt - Pointer to returned Interrupt structure
+
+Return Value:
+
+ None.
+
+--*/
+NTSTATUS
+Cbus2GetFixedPCICB2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
+
+VOID
+Cbus2InitOtherBuses(VOID)
+{
+ PBUS_HANDLER Bus;
+ ULONG i;
+ extern ULONG CBCIndex;
+
+ //
+ // For each Cbus2 CBC present, add a handler
+ //
+ for (i=0; i < CBCIndex; i++) {
+ Bus = HalpAllocateBusHandler (
+ CBus, // Interface type
+ CbusConfiguration, // Has this configuration space
+ i, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ 0 // sizeof bus specific buffer
+ ); //(should be sizeof CBUS_IO_ELEMENTS_T
+
+ //
+ // Add Cbus configuration space
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) Cbus2GetCbusData;
+ Bus->SetBusData = (PGETSETBUSDATA) Cbus2SetCbusData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) Cbus2GetInterruptVector;
+
+#if 0
+ //
+ // NOT CODED YET: BusSpecific data is a pointer to the info
+ // (if possible this structure should be the bus specific info)
+ //
+ Bus->BusData = (PVOID) &CbusIoElements[i];
+ Bus->AdjustResourceList
+ Bus->AssignSlotResources
+#endif
+ Bus->AdjustResourceList = HalpNoAdjustResourceList;
+ Bus->AssignSlotResources = HalpNoAssignSlotResources;
+
+ }
+}
+
+
+/*++
+
+Routine Description:
+
+ Check for a supported multiprocessor interrupt controller - currently
+ this means CBC or APIC only.
+
+ Check for Cbus2 I/O bridges and disable their incoming interrupts
+ here. This cannot be done in HalInitializeProcessor() because generally
+ the I/O bridge will not have a CPU on it.
+
+Arguments:
+
+ Table - Supplies a pointer to the RRD extended ID information table
+
+ Count - Supplies a pointer to the number of valid entries in the
+ RRD extended ID information table
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2ParseRRD(
+IN PEXT_ID_INFO Table,
+IN OUT PULONG Count
+)
+{
+ ULONG Index;
+ PEXT_ID_INFO Idp;
+ PCSR csr;
+ UCHAR control_register;
+ ULONG original_bridge;
+ PCBUS2_ELEMENT Cbus2Element;
+ WINDOWRELOC_T RegisterValue;
+ PCHAR BusMemoryWindow0;
+ PCHAR BusMemoryWindow1;
+ extern VOID CbusDisable8259s(USHORT);
+
+ for (Idp = Table, Index = 0; Index < *Count; Index++, Idp++) {
+
+ //
+ // map the identity range of the CSR space so each CPU
+ // can access his own CSR without knowing his slot id.
+ // this is useful because the task priority (and other
+ // registers) can now be referenced at the same physical
+ // address regardless of which processor you're currently
+ // executing on. if you couldn't reference it at the same
+ // physical address (regardless of processor), then you
+ // would need to pushfd/cli/popfd around capturing the
+ // current task priority address and setting it. otherwise
+ // you could be context switched in between, and you'd
+ // corrupt the initial processor's task priority!!!
+ //
+ if (Idp->id == CbusGlobal.broadcast_id) {
+ //
+ // unfortunately, the size and offset of the identity
+ // map is hardcoded in. we really should get RRD to
+ // tell us this offset.
+ //
+ Cbus2Element = (PCBUS2_ELEMENT)
+ (Idp->pel_start - CBUS_CSR_OFFSET);
+
+ Cbus2IdentityCSR = HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)(Cbus2Element->IdentityMappedCsr),
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ (ULONG)Cbus2Element->IdentityMappedCsr,
+ Idp->pel_size));
+ continue;
+ }
+
+ if (Idp->id == LAST_EXT_ID)
+ break;
+
+ // check only processor elements...
+
+ if (Idp->pm == 0)
+ continue;
+
+ //
+ // at least the base bridge must have a
+ // distributed interrupt chip (because
+ // any CPUs without them will be disabled).
+ //
+ if (Idp->id != CbusGlobal.bootid)
+ continue;
+
+ //
+ // check for CBC first, since if types of interrupt
+ // controllers are marked present, we will default to
+ // the CBC.
+ //
+ if (Idp->pel_features & ELEMENT_HAS_CBC) {
+ Cbus2InterruptController = ELEMENT_HAS_CBC;
+ continue;
+ }
+
+ if (Idp->pel_features & ELEMENT_HAS_APIC) {
+ Cbus2InterruptController = ELEMENT_HAS_APIC;
+ //
+ // patch the ipi vector to one compatible with
+ // the cbusapic.asm code.
+ //
+ Cbus2IrqlToVector[IPI_LEVEL] = CBUS2_ALTERNATE_IPI;
+ continue;
+ }
+ }
+
+ //
+ // there must be at least an APIC or a CBC for us to use
+ //
+ if ((Cbus2InterruptController &
+ (ELEMENT_HAS_APIC | ELEMENT_HAS_CBC)) == 0)
+ FatalError(MSG_OBSOLETE_PIC);
+
+ for (Idp = Table, Index = 0; Index < *Count; Index++, Idp++) {
+
+ if ((Idp->pel_features & ELEMENT_BRIDGE) == 0) {
+ continue;
+ }
+
+ csr = HalpMapPhysicalMemoryWriteThrough (
+ (PVOID)Idp->pel_start,
+ (ULONG)ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ Idp->pel_start, Idp->pel_size));
+
+ //
+ // to go from 8259 to CBC (or APIC) mode for interrupt handling,
+ //
+ // a) disable PC compatible interrupts, ie: stop each
+ // bridge CBC from asking its 8259 to satisfy INTA
+ // pulses to the CPU.
+ // b) mask off ALL 8259 interrupt input lines EXCEPT
+ // for irq0. since clock interrupts are not external
+ // in the EISA chipset, the bridge 8259 must enable
+ // them even when the CBC is enabled. putting the
+ // 8259 in passthrough mode (ie: the 8259 irq0 input
+ // will just be wired straight through) WILL NOT
+ // allow the 8259 to actually talk to the CPU; it
+ // just allows the interrupt to be seen by the CBC.
+ // the CBC is responsible for all the CPU interrupt
+ // handshaking.
+ // c) enable each participating element's (ie: CPUs only)
+ // interrupt configuration register for the vector
+ // the HAL has programmed irq0 to actually generate.
+ // d) initialize the hardware interrupt map for the irq0
+ // entry.
+ //
+ // IT IS CRITICAL THAT THE ABOVE STEPS HAPPEN IN THE
+ // ORDER OUTLINED, OTHERWISE YOU MAY SEE SPURIOUS
+ // INTERRUPTS.
+ //
+
+ //
+ // now process this I/O bridge:
+ //
+ // currently assumes that all bridges will be of the same
+ // flavor. if this element is a bridge, map it systemwide
+ // and disable all incoming interrupts on this bridge.
+ // any extra bridges beyond our configuration maximum
+ // are just disabled, and not used by NT.
+ //
+
+ if (Cbus2BridgesFound < CBUS_MAX_BRIDGES) {
+ Cbus2BridgeCSR[Cbus2BridgesFound] = csr;
+ Cbus2BridgeId[Cbus2BridgesFound] = Idp->id;
+ Cbus2BridgeCSRPaddr[Cbus2BridgesFound].HighPart = 0;
+ Cbus2BridgeCSRPaddr[Cbus2BridgesFound].LowPart =
+ Idp->pel_start;
+ if ((Idp->id != CBUS2_DEFAULT_BRIDGE_ID) &&
+ (csr->IoTypeInformation.LowDword != CBUS2_ELEMENT_TYPE_RAS)) {
+ //
+ // Use PC Bus Window 0 and 1 of the SPP
+ // bus bridge for memory space allocation
+ // of PCI devices on the SPP bus.
+ //
+ Cbus2Element = (PCBUS2_ELEMENT)((PCHAR) Idp->pel_start -
+ CBUS_CSR_OFFSET);
+ if (Cbus2InterruptController == ELEMENT_HAS_CBC) {
+ BusMemoryWindow0 = Cbus2Element->PCBusWindow0;
+ RegisterValue.csr_register =
+ csr->BridgeWindow0.csr_register;
+ RegisterValue.ra.WindowBase =
+ (ULONG)BusMemoryWindow0 >>
+ CBUS2_WINDOW_REGISTER_SHIFT;
+ csr->BridgeWindow0.csr_register =
+ RegisterValue.csr_register;
+ }
+ BusMemoryWindow1 = Cbus2Element->PCBusWindow1;
+ RegisterValue.csr_register =
+ csr->BridgeWindow1.csr_register;
+ RegisterValue.ra.WindowBase =
+ (ULONG)BusMemoryWindow1 >>
+ CBUS2_WINDOW_REGISTER_SHIFT;
+ csr->BridgeWindow1.csr_register =
+ RegisterValue.csr_register;
+
+ //
+ // Set Memory hole register of each additional
+ // bus bridge.
+ //
+ csr->PcBusMemoryHoles0.LowDword=CBUS2_NO_MEMORY_HOLES;
+ csr->PcBusMemoryHoles1.LowDword=CBUS2_NO_MEMORY_HOLES1;
+ csr->PcBusMemoryHoles2.LowDword=CBUS2_NO_MEMORY_HOLES2;
+
+ //
+ // Turn LED of SPP bus bridge on.
+ //
+ csr->LED.LowDword = CBUS2_LED_ON;
+ }
+ if (csr->IoTypeInformation.LowDword!=CBUS2_ELEMENT_TYPE_RAS)
+ Cbus2BridgesFound++;
+ }
+
+ if (Idp->pel_features & ELEMENT_HAS_8259) {
+
+ //
+ // disable all inputs in the 8259 IMRs except for the
+ // irq0. and explicitly force these masks onto the
+ // 8259s.
+ //
+ // if profiling is disabled, we will disable it in
+ // the interrupt configuration registers, but still
+ // we must leave the 8259 irq0 enabled. not to worry,
+ // the processor will not see irq0 interrupts.
+ // this way, if profiling is re-enabled later, we
+ // only need to change the interrupt configuration
+ // registers, and bingo, we provide the desired effect.
+ //
+
+ //
+ // save the original value for restoral after our read.
+ // repoint our I/O references to the desired bus
+ // bridge number.
+ //
+ original_bridge = csr->BusBridgeSelection.csr_register;
+ csr->BusBridgeSelection.csr_register =
+ ((original_bridge & ~MAX_ELEMENT_CSRS) | Idp->id);
+
+ control_register =
+ READ_PORT_UCHAR((PUCHAR)CbusGlobal.Control8259Mode);
+ WRITE_PORT_UCHAR((PUCHAR)CbusGlobal.Control8259Mode,
+ (UCHAR)(control_register | (UCHAR)CbusGlobal.Control8259ModeValue));
+
+#ifdef MCA
+ CbusDisable8259s(0xFFFF);
+#else
+ CbusDisable8259s(0xFFFE);
+#endif
+
+ //
+ // restore our default bridge references to what they
+ // were when we started...
+ //
+ csr->BusBridgeSelection.csr_register = original_bridge;
+ }
+
+ //
+ // In the midst of setting up the EISA element CBCs or
+ // processor CBCs (for those with Cbus2 native devices), a
+ // device interrupt that was pending in a bridge's 8259 ISRs
+ // may be lost. None should be fatal, even an
+ // 8042 keystroke, since the keyboard driver does a flush
+ // on open, and will, thus recover in the same way the standard
+ // uniprocessor NT HAL does when it initializes 8259s.
+ //
+ // If RRD instructed us to operate in APIC mode, then we want
+ // all the hardware interrupt map registers disabled as well.
+ // so this code works for both CBC and APIC modes.
+ //
+ // the hardware interrupt map entries for this processor's
+ // CBC are disabled by RRD prior to booting each processor,
+ // so it doesn't need to be done here.
+ //
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Called to put all the other processors in reset prior to reboot.
+ In order to safely put the other processors in reset, an IPI is
+ sent to the other processors to force them to write-invalidate
+ their L1 cache and halt. The calling processor will wait 5 seconds
+ for the IPI to take affect.
+
+ Once accomplished, the calling processor then clears all hardware
+ interrupt maps on the default bridge. The interrupt controller
+ is reset back to the 8259s. The keyboard controller is then
+ reset and ThisProcessor spins awaiting the reboot.
+
+ This routine can be called at any IRQL and can be called
+ whilst cli'd at interrupt time.
+
+Arguments:
+
+ ThisProcessor - Supplies the caller's logical processor number
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2ResetAllOtherProcessors(
+IN ULONG ThisProcessor
+)
+{
+ PHWINTRMAP hwentry;
+ PCSR io_csr;
+ ULONG Index;
+ ULONG Irq;
+ PCSR csr;
+ UCHAR control_register;
+
+ //
+ // repoint our I/O references to the default bus bridge
+ // don't bother saving and restoring the current bridge
+ // selection since we're about to reboot anyway.
+ //
+ csr = (PCSR)CbusCSR[ThisProcessor].csr;
+ csr->BusBridgeSelection.csr_register = Cbus2BridgeId[0];
+
+ control_register = READ_PORT_UCHAR((PUCHAR)CbusGlobal.Control8259Mode);
+
+ //
+ // we need to protect ourselves from interrupts as the
+ // CBC will be disabled with our next write and the 8259s
+ // will be in control...
+ //
+ _asm {
+ cli
+ }
+
+ //
+ // IPI the additional processors to get them to flush
+ // their internal caches and halt. this will be more
+ // conducive for the subsequent reset.
+ //
+ for (Index = 0; Index < CbusProcessors; Index++) {
+ if (Index == ThisProcessor)
+ continue;
+ csr = (PCSR)CbusCSR[Index].csr;
+ Cbus2WriteCSR((PULONG)
+ &(csr->InterruptRequest[CBUS2_REBOOT_TASKPRI]), 1);
+ }
+
+ //
+ // Delay 5 seconds to give the additional processors
+ // a chance to get the previous IPI.
+ //
+ KeStallExecutionProcessor(5000000);
+
+ //
+ // Disable all the bridge hardware interrupt maps.
+ // This will disable all EISA IRQ interrupts.
+ //
+ for (Index = 0; Index < Cbus2BridgesFound; Index++) {
+ io_csr = (PCSR)Cbus2BridgeCSR[Index];
+ for (Irq = 0; Irq <= EISA_IRQLS; Irq++) {
+ hwentry = &io_csr->HardwareInterruptMap[Irq];
+ hwentry->csr_register = 0;
+ }
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)CbusGlobal.Control8259Mode,
+ (UCHAR)(control_register & ~(UCHAR)CbusGlobal.Control8259ModeValue));
+
+ //
+ // reset the keyboard controller.
+ //
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+loop:
+ goto loop;
+}
+
+/*++
+
+Routine Description:
+
+ This function initializes the HAL-specific hardware device
+ (CLOCK & PROFILE) interrupts for the Corollary Cbus2 architecture.
+
+Arguments:
+
+ none.
+
+Return Value:
+
+ VOID
+
+--*/
+VOID
+Cbus2InitializeDeviceIntrs(
+IN ULONG Processor
+)
+{
+ PCSR csr;
+ ULONG TimeStamp;
+ extern VOID Cbus2ClockInterrupt(VOID);
+ extern VOID Cbus2ClockInterruptPx(VOID);
+
+ //
+ // here we initialize & enable all the device interrupts.
+ // this routine is called from HalInitSystem.
+ //
+ // each processor needs to call KiSetHandlerAddressToIDT()
+ // and HalEnableSystemInterrupt() for himself.
+ //
+
+ if (Processor == 0) {
+
+ //
+ // Support the HAL's exported interface to the rest of the
+ // system for the IDT configuration. This routine will
+ // also set up the IDT entry and enable the actual interrupt.
+ //
+ // Only one processor needs to do this, especially since
+ // the additional processors are vectoring elsewhere for speed.
+ //
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ IRQ0, // Bus interrupt level
+ CbusClockVector, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ Cbus2ClockInterrupt, // ISR
+ Latched);
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ IRQ8, // Bus interrupt level
+ ProfileVector, // System IDT
+ PROFILE_LEVEL, // System Irql
+ HalpProfileInterrupt, // ISR
+ Latched);
+
+ }
+ else {
+ //
+ // if the spurious clock check is enabled, then
+ // synchronize this CPU's SystemTimer by capturing CPU0's.
+ //
+ if (Cbus2CheckSpuriousClock) {
+ csr = (PCSR)CbusCSR[Processor].csr;
+ TimeStamp = Cbus2ReadCSR(Cbus2TimeStamp0);
+ Cbus2WriteCSR(&csr->SystemTimer.LowDword, TimeStamp);
+ }
+
+ KiSetHandlerAddressToIDT(CbusClockVector,Cbus2ClockInterruptPx);
+ HalEnableSystemInterrupt(CbusClockVector, CLOCK2_LEVEL, Latched);
+
+ KiSetHandlerAddressToIDT(ProfileVector, HalpProfileInterruptPx);
+ HalEnableSystemInterrupt(ProfileVector, PROFILE_LEVEL, Latched);
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Translate a Root BusNumber to a C-bus II bridge index.
+
+Arguments:
+
+ Root BusNumber - Supplies the child bus.
+
+Return Value:
+
+ Index - The C-bus II bridge index.
+
+--*/
+ULONG
+Cbus2MapBusNumberToBridgeIndex(
+ULONG RootBusNumber
+)
+{
+ ULONG Index;
+
+ for (Index = Cbus2BridgesFound - 1; Index >= 0; Index--) {
+ if (RootBusNumber >= Cbus2BridgePCIBusNumber[Index])
+ break;
+ }
+
+ return Index;
+}
+
+/*++
+
+Routine Description:
+
+ Translate a bridge ID to an index.
+
+Arguments:
+
+ BridgeId - Supplies the bridge ID.
+
+Return Value:
+
+ Index - The C-bus II bridge index.
+
+--*/
+ULONG
+Cbus2MapBridgeIdToIndex(
+ULONG BridgeId
+)
+{
+ ULONG Index;
+
+ for (Index = Cbus2BridgesFound - 1; Index >= 0; Index--) {
+ if (BridgeId == Cbus2BridgeId[Index])
+ break;
+ }
+
+ return Index;
+}
+
+/*++
+
+Routine Description:
+
+ Check the passed pRange list for qualifying ranges that
+ can be mapped into C-bus space.
+
+Arguments:
+
+ pRange - Supplies the range list.
+
+ Base - Supplies the base of the C-bus II remappable range.
+
+ Limit - Supplies the limit of the C-bus II remappable range.
+
+ SystemBase - Supplies the SystemBase for the translation.
+
+Return Value:
+
+ Number of new ranges added.
+
+--*/
+ULONG
+Cbus2CheckRange(
+PSUPPORTED_RANGE pRange,
+ULONG Base,
+ULONG Limit,
+PCHAR SystemBase
+)
+{
+ ULONG NewRanges = 0;
+
+ for (; pRange; pRange = pRange->Next) {
+ //
+ // Check if in the range by checking for stradlers and fully
+ // contained Base/Limit pairs.
+ //
+ if ((pRange->Base <= Base && pRange->Limit >= Base) ||
+ (pRange->Base >= Base && pRange->Base <= Limit)) {
+
+ //
+ // Check for a base stradler.
+ //
+ if (pRange->Base < Base) {
+ HalpAddRange (
+ pRange,
+ pRange->SystemAddressSpace,
+ pRange->SystemBase,
+ Base,
+ pRange->Limit
+ );
+ pRange->Limit = Base - 1;
+ pRange = pRange->Next;
+ //
+ // Should still be sorted, but bump the count.
+ //
+ NewRanges++;
+ }
+
+ //
+ // Check for a limit stradler.
+ //
+ if (pRange->Limit > Limit) {
+ HalpAddRange (
+ pRange,
+ pRange->SystemAddressSpace,
+ pRange->SystemBase,
+ Limit + 1,
+ pRange->Limit
+ );
+ pRange->Limit = Limit;
+ //
+ // Should still be sorted, but bump the count.
+ //
+ NewRanges++;
+ }
+
+ //
+ // Set SystemBase for the qualifying pRange.
+ // Make sure that SystemAddressSpace is set to 0.
+ //
+ pRange->SystemBase = (ULONG)SystemBase;
+ pRange->SystemAddressSpace = 0;
+ }
+ }
+
+ return NewRanges;
+}
+
+/*++
+
+Routine Description:
+
+ Check the passed pRange list for limits that
+ exceed that new limit. If so, lower the limit.
+
+Arguments:
+
+ pRange - Supplies the range list.
+
+ NewLimit - Supplies the new limit for the given range list.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2LowerLimit(
+PSUPPORTED_RANGE pRange,
+ULONG NewLimit
+)
+{
+ for (; pRange; pRange = pRange->Next) {
+ if (pRange->Limit > NewLimit)
+ pRange->Limit = NewLimit;
+ //
+ // Check if the extent is no longer valid.
+ //
+ if (pRange->Base > pRange->Limit) {
+ pRange->Base = 0;
+ pRange->Limit = 0;
+ }
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Set the range for this pRange to the passed base and limit.
+
+Arguments:
+
+ pRange - Supplies the range list.
+
+ NewBase - Supplies the new base for the given range list.
+
+ NewLimit - Supplies the new limit for the given range list.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2SetRange(
+PSUPPORTED_RANGE pRange,
+LONGLONG NewBase,
+LONGLONG NewLimit
+)
+{
+ pRange->Base = NewBase;
+ pRange->Limit = NewLimit;
+ pRange->Next = 0;
+}
+
+/*++
+
+Routine Description:
+
+ Called once, from HalReportResourceUsage(), to check all the
+ Ranges in all the PBUS_HANDLERs. note that it is currently
+ assumed that HalpInitializePciBus() is the last in the chain to
+ add and configure buses. if this condition changes, then the
+ calling of this routine will need to be adjusted.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2CheckBusRanges(VOID)
+{
+ PBUS_HANDLER Bus;
+ PSUPPORTED_RANGES BusAddresses;
+ ULONG InterfaceType;
+ ULONG BridgeIndex;
+ ULONG BusNumber;
+
+ //
+ // Check all the buses (InterfaceType, BusNumber) pairs ...
+ //
+ for (InterfaceType=0; InterfaceType<MaximumInterfaceType; InterfaceType++) {
+ for (BusNumber = 0; ; BusNumber++) {
+ if ((Bus = HaliHandlerForBus (InterfaceType, BusNumber)) == NULL) {
+ break;
+ }
+ if (Bus->InterfaceType != PCIBus)
+ break;
+ BusAddresses = Bus->BusAddresses;
+ if (BusAddresses) {
+ //
+ // Get the root bus, or C-bus II bridge index.
+ // The SystemBase will be either:
+ //
+ // IO - offset 0x3c10000 into the CSR space
+ // Memory - offset 0x0 into the CSR space
+ //
+ BridgeIndex = Cbus2MapBusNumberToBridgeIndex(Bus->BusNumber);
+
+ //
+ // For compatibility with non-Microsoft maintained
+ // device drivers, don't translate bus 0 addresses.
+ //
+ if (BridgeIndex == 0) {
+ //
+ // ensure that the limit of any memory range
+ // on the primary bus bridge is below the
+ // CSR space.
+ //
+ Cbus2LowerLimit(&BusAddresses->PrefetchMemory,
+ CbusGlobal.cbusio - 1);
+ Cbus2LowerLimit(&BusAddresses->Memory,
+ CbusGlobal.cbusio - 1);
+ continue;
+ }
+ }
+ }
+ }
+}
+
+
+/*++
+
+Routine Description:
+
+ Called once, from HalReportResourceUsage(), to check all the
+ Ranges in all the PBUS_HANDLERs. note that it is currently
+ assumed that HalpInitializePciBus() is the last in the chain to
+ add and configure buses. if this condition changes, then the
+ calling of this routine will need to be adjusted.
+
+Arguments:
+
+ Bus - Bus Handler to check.
+
+ BridgeIndex - Logical bridge index.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2AdjustSPPBusRange(
+PBUS_HANDLER Bus,
+UCHAR BridgeIndex,
+UCHAR RootPciBus
+)
+{
+ PSUPPORTED_RANGES BusAddresses;
+ PHYSICAL_ADDRESS CsrPhysicalAddress;
+ PCBUS2_ELEMENT Cbus2Element;
+ PCHAR IOSystemBase;
+ LONGLONG MemorySystemBase;
+ ULONG MemorySystemLimit;
+
+ if (!(BusAddresses = Bus->BusAddresses))
+ return;
+ //
+ // check if the range of the IO bus address is within
+ // CBUS2_IO_BASE_ADDRESS & CBUS2_IO_LIMIT. if so,
+ // add IOSystemBase to uniquely target the I/O to the
+ // SPP bus bridge.
+ //
+ CsrPhysicalAddress = Cbus2BridgeCSRPaddr[BridgeIndex];
+ Cbus2Element = (PCBUS2_ELEMENT)
+ ((PCHAR)CsrPhysicalAddress.LowPart - CBUS_CSR_OFFSET);
+ IOSystemBase = Cbus2Element->PCBusIO;
+ BusAddresses->NoIO += Cbus2CheckRange(&BusAddresses->IO,
+ CBUS2_IO_BASE_ADDRESS, CBUS2_IO_LIMIT, IOSystemBase);
+ if (RootPciBus) {
+ if (Cbus2InterruptController == ELEMENT_HAS_CBC) {
+ MemorySystemBase = (ULONGLONG)
+ ((ULONG)Cbus2Element->PCBusWindow0);
+ MemorySystemLimit = ((ULONG)Cbus2Element->PCBusWindow0 +
+ (sizeof (Cbus2Element->PCBusWindow0) * 2) - 1);
+ }
+ else {
+ MemorySystemBase = (ULONGLONG)
+ ((ULONG)Cbus2Element->PCBusWindow1);
+ MemorySystemLimit = ((ULONG)Cbus2Element->PCBusWindow1 +
+ sizeof (Cbus2Element->PCBusWindow1) - 1);
+ }
+ Cbus2SetRange(&BusAddresses->PrefetchMemory,
+ MemorySystemBase, MemorySystemLimit);
+ Cbus2SetRange(&BusAddresses->Memory,
+ MemorySystemBase, MemorySystemLimit);
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Called once, from CbusEstablishMaps(), to find the holes in the
+ C-bus memory space that is not useable for device allocation.
+ These ranges are entered into a table and this table is then used:
+
+ 1. to remove the hole ranges from the memory descriptor table as
+ passed in from the BIOS E820 function (see comment in HalpAddMem()).
+
+ 2. to add to the resource list used by the C-bus HAL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2AddMemoryHoles(VOID)
+{
+ PCSR csr;
+ ULONG Index;
+ ULONG Start;
+ ULONG TLM;
+
+ //
+ // HalpMemory[] lists all the valid memory ranges reported by RRD.
+ // use AddMemoryHole() and AddMemoryResource() to remove gaps
+ // between these memory ranges.
+ //
+ for (Index = 0; Index < HalpMemoryIndex - 1; Index++) {
+
+ Start = PAGES_TO_BYTES(HalpMemory[Index].BasePage +
+ HalpMemory[Index].PageCount),
+ AddMemoryHole(Start,
+ PAGES_TO_BYTES(HalpMemory[Index+1].BasePage) - Start);
+ AddMemoryResource(Start,
+ PAGES_TO_BYTES(HalpMemory[Index+1].BasePage) - Start);
+
+ }
+
+ //
+ // the final memory gap is from the end of the last memory range
+ // through the TLM register. the TLM register marks the start
+ // of resource allocatable memory. the TLM register is in units
+ // of 256MB where 0 indicates 256MB.
+ //
+ csr = (PCSR)Cbus2BridgeCSR[BRIDGE0];
+ TLM = (Cbus2ReadCSR(&csr->TLM.LowDword) + 1) * 256 * 1024 * 1024;
+ Start = PAGES_TO_BYTES(HalpMemory[Index].BasePage +
+ HalpMemory[Index].PageCount);
+ if (TLM - Start) {
+ AddMemoryHole(Start, TLM - Start);
+ AddMemoryResource(Start, TLM - Start);
+ }
+}
+
+//
+// Mask for valid bits of edge/level control register (ELCR) in 82357 ISP:
+// ie: ensure irqlines 0, 1, 2, 8 and 13 are always marked edge, as the
+// I/O register will not have them set correctly. All other bits in the
+// I/O register will be valid without us having to poke them.
+//
+// If this is a microchannel machine, then we don't use the mask.
+//
+#define ELCR_MASK 0xDEF8
+
+#define PIC1_ELCR_PORT (PUCHAR)0x4D0 // ISP edge/level control regs
+#define PIC2_ELCR_PORT (PUCHAR)0x4D1
+
+/*++
+
+Routine Description:
+
+ Called once to read the EISA interrupt configuration registers.
+ This will tell us which interrupt lines are level-triggered and
+ which are edge-triggered. Note that irqlines 0, 1, 2, 8 and 13
+ are not valid in the 4D0/4D1 registers and are defaulted to edge.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The interrupt line polarity of all the EISA irqlines on all the EISA
+ buses in the system.
+
+--*/
+VOID
+Cbus2InitInterruptPolarity(
+VOID
+)
+{
+ ULONG InterruptLines;
+ ULONG BridgeIndex;
+ ULONG original_bridge;
+ ULONG BridgeId;
+ PCSR csr;
+
+ for (BridgeIndex = 0; BridgeIndex < Cbus2BridgesFound; BridgeIndex++) {
+ InterruptLines = 0;
+
+ //
+ // Read the edge-level control register (ELCR) so we'll know how
+ // to mark each driver's interrupt line (ie: edge or level
+ // triggered) in the CBC or APIC I/O unit redirection table
+ // entry.
+ //
+
+ BridgeId = Cbus2BridgeId[BridgeIndex];
+ csr = Cbus2BridgeCSR[BridgeIndex];
+
+ //
+ // save the original value for restoral after our read.
+ // repoint our I/O references to the desired bus bridge number.
+ //
+ original_bridge = csr->BusBridgeSelection.csr_register;
+ csr->BusBridgeSelection.csr_register =
+ ((original_bridge & ~MAX_ELEMENT_CSRS) | BridgeId);
+
+ //
+ // read the ELCR register from the correct bus bridge
+ //
+ InterruptLines = ( ((ULONG)READ_PORT_UCHAR(PIC2_ELCR_PORT) << 8) |
+ ((ULONG)READ_PORT_UCHAR(PIC1_ELCR_PORT)) );
+
+ //
+ // restore our default bridge references to what they were
+ // when we started...
+ //
+ csr->BusBridgeSelection.csr_register = original_bridge;
+
+ //
+ // Explicitly mark irqlines 0, 1, 2, 8 and 13 as edge,
+ // unless the system is a microchannel system.
+ // Leave all other irqlines at their current register values.
+ //
+
+#ifndef MCA
+ InterruptLines &= ELCR_MASK;
+#endif
+
+ Cbus2IrqPolarity[BridgeIndex] = InterruptLines;
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Call HalpPCISynchronizeType1() from ixpcibus.c for proper
+ configuration space synchronization and then adjust the
+ bridge selection csr to point to the desired bus.
+
+Arguments:
+
+ BusHandler - BusHandler for PCI configuration read/write
+
+ Slot - Desired slot.
+
+ Irql - Pointer to hold previous Irql.
+
+ PciCfg1 - Type 1 configuration access.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2PCISynchronize(
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+)
+{
+ PCSR csr = Cbus2IdentityCSR;
+ ULONG BusNumber;
+ ULONG BridgeId;
+
+ HalpPCISynchronizeType1 (BusHandler, Slot, Irql, PciCfg1);
+ BusNumber = BusHandler->BusNumber;
+ if (Cbus2BridgeOverride) {
+ BusNumber = Cbus2BridgeOverride;
+ Cbus2BridgeOverride = 0;
+ }
+ BridgeId = Cbus2BridgeId[Cbus2MapBusNumberToBridgeIndex(BusNumber)];
+ csr->BusBridgeSelection.csr_register = BridgeId;
+}
+
+/*++
+
+Routine Description:
+
+ Restore the bridge selection csr to bus bridge 0 and
+ then call HalpPCIReleaseSynchronzationType1() in ixpcibus.c
+ to release the PCI configuration synchronization.
+
+Arguments:
+
+ BusHandler - BusHandler for PCI configuration read/write
+
+ Irql - Pointer that holds Irql to restore to.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2PCIReleaseSynchronization(
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+)
+{
+ PCSR csr = Cbus2IdentityCSR;
+
+ csr->BusBridgeSelection.csr_register = 0;
+ HalpPCIReleaseSynchronzationType1 (BusHandler, Irql);
+}
+
+/*++
+
+Routine Description:
+
+ Read the PCI configuration for the designated PPB.
+ Update the bus fields for this bridge device.
+
+Arguments:
+
+ BusNumber - Bus Number of Bridge device.
+
+ Device - Device Number of Bridge device.
+
+ Function - Function of Bridge device.
+
+ PrimaryBus - set Primary bus to this value.
+
+ SecondaryBus - set Secondary bus to this value.
+
+ SubordinateBus - set Subordinate bus to this value.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2SetPPBBridgeBuses(
+ULONG BusNumber,
+PCI_SLOT_NUMBER Slot,
+ULONG Function,
+ULONG PrimaryBus,
+ULONG SecondaryBus,
+ULONG SubordinateBus
+)
+{
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ BusHandler = HalpHandlerForBus (PCIBus, BusNumber);
+ SlotNumber.u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ SlotNumber.u.bits.FunctionNumber = Function;
+ SlotNumber.u.bits.Reserved = 0;
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData,
+ 0, PCI_COMMON_HDR_LENGTH);
+ PciData->u.type1.PrimaryBus = (UCHAR)PrimaryBus;
+ PciData->u.type1.SecondaryBus = (UCHAR)SecondaryBus;
+ PciData->u.type1.SubordinateBus = (UCHAR)SubordinateBus;
+ HalpWritePCIConfig (BusHandler, SlotNumber, PciData,
+ 0, PCI_COMMON_HDR_LENGTH);
+}
+
+/*++
+
+Routine Description:
+
+ Read the PCI configuration for the designated host bridge.
+ Update the bus fields for this bridge device.
+
+Arguments:
+
+ BusNumber - Bus Number of Bridge device.
+
+ Device - Device Number of Bridge device.
+
+ Function - Function of Bridge device.
+
+ PrimaryBus - set Primary bus to this value.
+
+ SubordinateBus - set Subordinate bus to this value.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2SetHostBridgeBuses(
+ULONG BusNumber,
+ULONG Device,
+ULONG Function,
+ULONG PrimaryBus,
+ULONG SubordinateBus
+)
+{
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PCBUS2_HOST_BRIDGE_CONFIG PciData;
+ UCHAR iBuffer[sizeof (CBUS2_HOST_BRIDGE_CONFIG)];
+ ULONG BusOverride = 0;
+ static ULONG FirstTry = 1;
+
+ PciData = (PCBUS2_HOST_BRIDGE_CONFIG) iBuffer;
+ BusHandler = HalpHandlerForBus (PCIBus, BusNumber);
+ SlotNumber.u.bits.DeviceNumber = Device;
+ SlotNumber.u.bits.FunctionNumber = Function;
+ SlotNumber.u.bits.Reserved = 0;
+retry:
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData,
+ 0, sizeof (CBUS2_HOST_BRIDGE_CONFIG));
+ if (PciData->VendorID == PCI_INVALID_VENDORID && FirstTry) {
+ FirstTry = 0;
+ BusHandler->BusNumber = 0;
+ Cbus2BridgeOverride = BusNumber;
+ BusOverride = BusNumber;
+ goto retry;
+ }
+ PciData->BusNumber = (UCHAR)PrimaryBus;
+ PciData->SubordinateBusNumber = (UCHAR)SubordinateBus;
+ Cbus2BridgeOverride = BusOverride;
+ HalpWritePCIConfig (BusHandler, SlotNumber, PciData,
+ 0, sizeof (CBUS2_HOST_BRIDGE_CONFIG));
+ BusHandler->BusNumber = BusNumber;
+}
+
+UCHAR Cbus2SPPInterruptRoute[] = {
+ 1, 4, 3, 2,
+ 2, 1, 4, 3,
+ 3, 2, 1, 4,
+ 4, 3, 2, 1
+};
+
+UCHAR Cbus2SPPInterruptRouteForPele[] = {
+ 10, 10, 10, 10,
+ 11, 11, 11, 11,
+ 12, 12, 12, 12,
+ 13, 13, 13, 13
+};
+
+/*++
+
+Routine Description:
+
+ Route the interrupt for the given device and interrupt pin
+ for the secondary peer pci bridge.
+
+Arguments:
+
+ Device - Device number for the device to route.
+
+ InterruptPin - Interrupt Pin requested
+
+Return Value:
+
+ Resulting routed interrupt line.
+
+--*/
+UCHAR
+Cbus2RouteSPPInterrupt(
+ULONG Device,
+UCHAR InterruptPin
+)
+{
+ if (Device == 0 || InterruptPin == 0) {
+ return 0;
+ }
+ if (Cbus2PeleSystemFound) {
+ return Cbus2SPPInterruptRouteForPele[
+ ((InterruptPin - 1) * 4) + ((Device - 1) % 4)];
+ }
+ else {
+ return Cbus2SPPInterruptRoute[
+ ((InterruptPin - 1) * 4) + ((Device - 1) % 4)];
+ }
+}
+
+UCHAR Cbus2PPBInterruptRoute[] = {
+ 1, 2, 3, 4,
+ 2, 3, 4, 1,
+ 3, 4, 1, 2,
+ 4, 1, 2, 3,
+};
+
+/*++
+
+Routine Description:
+
+ Route the interrupt for the given device and interrupt pin
+ for a PCI-to-PCI bridge.
+
+Arguments:
+
+ BusNumber - Bus number for this device.
+
+ Device - Device number for the device to route.
+
+ InterruptPin - Current Interrupt Pin request.
+
+Return Value:
+
+ Resulting routed interrupt line.
+
+--*/
+ULONG
+Cbus2RoutePPBInterrupt(
+ULONG BusNumber,
+ULONG Device,
+UCHAR InterruptPin
+)
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ while (TRUE) {
+ Bus = HaliHandlerForBus(PCIBus, BusNumber);
+ if (Bus->ParentHandler->InterfaceType == Internal ||
+ Device == 0 || InterruptPin == 0) {
+ break;
+ }
+ InterruptPin = Cbus2PPBInterruptRoute[
+ ((Device % 4) * 4) + (InterruptPin - 1)];
+ BusNumber = Bus->ParentHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+ Device = BusData->CommonData.ParentSlot.u.bits.DeviceNumber;
+ }
+
+ return (Device << 8) | InterruptPin;
+}
+
+/*++
+
+Routine Description:
+
+ Add an additional PCI bus to the registry.
+
+Arguments:
+
+ PCIRegInfo - Global registry information.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2AddPciBusToRegistry(
+PPCI_REGISTRY_INFO PCIRegInfo
+)
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hBus;
+ NTSTATUS status;
+ UCHAR buf2[150];
+ PCONFIGURATION_COMPONENT Component;
+ PCM_FULL_RESOURCE_DESCRIPTOR Description;
+ ACCESS_MASK DesiredAccess;
+ PBUS_HANDLER Bus;
+ ULONG mnum;
+ ULONG d;
+
+ mnum = 0;
+ //
+ // Add another PCI bus in the registry.
+ //
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key.
+ //
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buf2, L"%s\\%d",
+ rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buf2);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL);
+ status = ZwOpenKey( &hBus, DesiredAccess,
+ &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+ // already exists, next
+ ZwClose (hBus);
+ mnum += 1;
+ }
+ ZwCreateKey (&hBus,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+ //
+ // Add needed registry values for this
+ // MultifunctionAdapter entry.
+ //
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (hBus,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Description = (PCM_FULL_RESOURCE_DESCRIPTOR) buf2;
+ Description->InterfaceType = PCIBus;
+ Description->BusNumber = (ULONG)PCIRegInfo->NoBuses;
+ Description->PartialResourceList.Version = 0;
+ Description->PartialResourceList.Revision = 0;
+ Description->PartialResourceList.Count = 0;
+ ZwSetValueKey (hBus,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Description,
+ sizeof (*Description)
+ );
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buf2;
+ RtlZeroMemory (Component, sizeof (*Component));
+
+ //
+ // Setting the Component structure values using the
+ // structure doesn't match the PCI bus 0 setting.
+ // Set the values by hand to match what ntloader did
+ // for bus 0. Proper code would be:
+ //
+ // Component->AffinityMask = 0xffffffff;
+ //
+ buf2[12] = 0xff;
+ buf2[13] = 0xff;
+ buf2[14] = 0xff;
+ buf2[15] = 0xff;
+ ZwSetValueKey (hBus,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ 16
+ );
+ ZwClose (hBus);
+}
+
+/*++
+
+Routine Description:
+
+ Search the given PCI bus for device and PPB devices.
+ As devices are found, route any needed interrupts pins.
+ As PPB devices are found, recursively descend to the lower bus.
+
+Arguments:
+
+ BridgeIndex - Logical index of C-bus II bridge.
+
+ PCIRegInfo - Global registry information.
+
+ BusNumber - Bus Number to begin search from.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2HierarchicalPciBusSearch(
+UCHAR BridgeIndex,
+PPCI_REGISTRY_INFO PCIRegInfo,
+ULONG BusNumber
+)
+{
+ PBUS_HANDLER ParentBus;
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ CONFIGBRIDGE CB;
+ PSUPPORTED_RANGES ParentBusAddresses;
+ PSUPPORTED_RANGES ChildBusAddresses;
+ LONGLONG IOLimit;
+ LONGLONG MemoryLimit;
+ LONGLONG PrefetchMemoryLimit;
+ ULONG Device;
+ ULONG Function;
+ ULONG SecondaryBus;
+ UCHAR InterruptPin;
+ ULONG Retval;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNumber);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ //
+ // Set resource limits for PCI-to-PCI bridges found.
+ // Each is allowed 25% of the amount available on the parent.
+ //
+ ParentBus = CB.BusHandler;
+ ParentBusAddresses = ParentBus->BusAddresses;
+ IOLimit = ((ParentBusAddresses->IO.Limit -
+ ParentBusAddresses->IO.Base) + 1) >> 2;
+ MemoryLimit = ((ParentBusAddresses->Memory.Limit -
+ ParentBusAddresses->Memory.Base) + 1) >> 2;
+ PrefetchMemoryLimit = ((ParentBusAddresses->PrefetchMemory.Limit -
+ ParentBusAddresses->PrefetchMemory.Base) + 1) >> 2;
+
+ //
+ // Seach all the devices of this bus.
+ //
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+ CB.SlotNumber.u.bits.DeviceNumber = Device;
+
+ for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
+ CB.SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read PCI configuration information
+ //
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ Retval = Cbus2RoutePPBInterrupt(BusNumber, Device,
+ CB.PciData->u.type0.InterruptPin);
+ InterruptPin = (UCHAR)(Retval & 0xff);
+ Retval >>= 8;
+ CB.PciData->u.type0.InterruptLine =
+ Cbus2RouteSPPInterrupt(Retval, InterruptPin);
+ CB.PciData->LatencyTimer = CBUS2_PCI_LATENCY_TIMER;
+ HalpWritePCIConfig (CB.BusHandler, CB.SlotNumber,
+ CB.PciData, 0, PCI_COMMON_HDR_LENGTH);
+ continue;
+ }
+
+ CB.PciData->Command |=
+ PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_SERR;
+
+ //
+ // Found a PCI-PCI bridge.
+ // Set up its parent child relationships.
+ //
+ ChildBus = HalpAllocateAndInitPciBusHandler (
+ PCIRegInfo->HardwareMechanism & 0xf,
+ PCIRegInfo->NoBuses, FALSE);
+
+ PCIConfigHandler.Synchronize = Cbus2PCISynchronize;
+ PCIConfigHandler.ReleaseSynchronzation =
+ Cbus2PCIReleaseSynchronization;
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ ChildBus->GetInterruptVector =
+ (PGETINTERRUPTVECTOR) Cbus2GetInterruptVector;
+ ChildBusData->CommonData.Pin2Line =
+ (PciPin2Line) Cbus2PCIPin2CB2Line;
+ ChildBusData->CommonData.Line2Pin =
+ (PciLine2Pin) Cbus2PCICB2Line2Pin;
+ ChildBusData->GetIrqRange = Cbus2GetFixedPCICB2Line;
+
+ //
+ // Assign I/O, Memory and Prefetch resources
+ // for this PPB.
+ //
+ // First reduce the parent bus ranges.
+ //
+ Cbus2SetRange(&ParentBusAddresses->IO,
+ ParentBusAddresses->IO.Base,
+ ParentBusAddresses->IO.Limit - IOLimit);
+ Cbus2SetRange(&ParentBusAddresses->Memory,
+ ParentBusAddresses->Memory.Base,
+ ParentBusAddresses->Memory.Limit - MemoryLimit);
+ Cbus2SetRange(&ParentBusAddresses->PrefetchMemory,
+ ParentBusAddresses->PrefetchMemory.Base,
+ ParentBusAddresses->PrefetchMemory.Limit -
+ PrefetchMemoryLimit);
+ //
+ // Next, set the ranges in the config space of the PPB.
+ //
+ CB.PciData->u.type1.IOBase = PCI_IO_TO_CFG(
+ ParentBusAddresses->IO.Limit + 1);
+ CB.PciData->u.type1.IOLimit = PCI_IO_TO_CFG(
+ ParentBusAddresses->IO.Limit + IOLimit);
+ CB.PciData->u.type1.MemoryBase = PCI_MEMORY_TO_CFG(
+ ParentBusAddresses->Memory.Limit + 1);
+ CB.PciData->u.type1.MemoryLimit = PCI_MEMORY_TO_CFG(
+ ParentBusAddresses->Memory.Limit + MemoryLimit);
+ CB.PciData->u.type1.PrefetchBase = PCI_PREFETCH_TO_CFG(
+ ParentBusAddresses->PrefetchMemory.Limit + 1);
+ CB.PciData->u.type1.PrefetchLimit = PCI_PREFETCH_TO_CFG(
+ ParentBusAddresses->PrefetchMemory.Limit +
+ PrefetchMemoryLimit);
+ //
+ // Lastly, set the ranges in the child bus handler.
+ // Some of this code tracks HalpGetPciBridgeConfig().
+ //
+ ChildBusAddresses = ChildBus->BusAddresses;
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, ParentBus);
+ ChildBusData->ParentBus = (UCHAR) ParentBus->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+ Cbus2SetRange(&ChildBusAddresses->IO,
+ ParentBusAddresses->IO.Limit + 1,
+ ParentBusAddresses->IO.Limit + IOLimit);
+ Cbus2SetRange(&ChildBusAddresses->Memory,
+ ParentBusAddresses->Memory.Limit + 1,
+ ParentBusAddresses->Memory.Limit + MemoryLimit);
+ Cbus2SetRange(&ChildBusAddresses->PrefetchMemory,
+ ParentBusAddresses->PrefetchMemory.Limit + 1,
+ ParentBusAddresses->PrefetchMemory.Limit +
+ PrefetchMemoryLimit);
+
+ //
+ // Update the configuration space.
+ //
+ HalpWritePCIConfig (CB.BusHandler, CB.SlotNumber,
+ CB.PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Adjust appropriate ranges.
+ //
+ Cbus2AdjustSPPBusRange(ChildBus, BridgeIndex, 0);
+
+ //
+ // Set the bus numbers for this bridge.
+ //
+ Cbus2SetPPBBridgeBuses((UCHAR)BusNumber, CB.SlotNumber, 0,
+ (UCHAR)BusNumber, (UCHAR)PCIRegInfo->NoBuses, 0xff);
+ //
+ // Add an additional PCI bus to the registry.
+ //
+ Cbus2AddPciBusToRegistry(PCIRegInfo);
+ SecondaryBus = PCIRegInfo->NoBuses;
+ PCIRegInfo->NoBuses++;
+ Cbus2HierarchicalPciBusSearch(BridgeIndex, PCIRegInfo,
+ SecondaryBus);
+ Cbus2SetPPBBridgeBuses((UCHAR)BusNumber, CB.SlotNumber, 0,
+ (UCHAR)BusNumber, (UCHAR)SecondaryBus,
+ (UCHAR)(PCIRegInfo->NoBuses - 1));
+ }
+ }
+}
+
+/*++
+
+Routine Description:
+
+ If an additional C-bus bridge is present in the system,
+ perform a hierarchical scan of the bus, set up the interrupt
+ routing for all the devices on the bus and allocate and initialize
+ the bus handlers for the buses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+Cbus2InitializeOtherPciBus(
+VOID
+)
+{
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer[sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ volatile PPCI_REGISTRY_INFO PCIRegInfo;
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+ PCONFIGURATION_COMPONENT Component;
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+ UCHAR BridgeIndex;
+ ULONG i, junk;
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+ //
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize each additional C-bus II PCI bus bridge
+ //
+ for (BridgeIndex = 1; BridgeIndex < Cbus2BridgesFound; BridgeIndex++) {
+ //
+ // Record the PCI Bus number for additional
+ // C-bus II PCI bus bridges.
+ //
+ Cbus2BridgePCIBusNumber[BridgeIndex] =
+ (ULONG)PCIRegInfo->NoBuses;
+
+ //
+ // Initialize IRQ Polarity table for additional
+ // C-bus II PCI bus bridges.
+ //
+ Cbus2IrqPolarity[BridgeIndex] = 0xffff;
+
+ Bus = HalpAllocateAndInitPciBusHandler (
+ PCIRegInfo->HardwareMechanism & 0xf,
+ (ULONG)PCIRegInfo->NoBuses, FALSE);
+
+ PCIConfigHandler.Synchronize = Cbus2PCISynchronize;
+ PCIConfigHandler.ReleaseSynchronzation =
+ Cbus2PCIReleaseSynchronization;
+
+ Bus->GetInterruptVector =
+ (PGETINTERRUPTVECTOR) Cbus2GetInterruptVector;
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+ BusData->CommonData.Pin2Line =
+ (PciPin2Line) Cbus2PCIPin2CB2Line;
+ BusData->CommonData.Line2Pin =
+ (PciLine2Pin) Cbus2PCICB2Line2Pin;
+ BusData->GetIrqRange = Cbus2GetFixedPCICB2Line;
+ Cbus2AdjustSPPBusRange(Bus, BridgeIndex, 1);
+
+ //
+ // Set the bus numbers for this bridge.
+ //
+ Cbus2SetHostBridgeBuses((ULONG)PCIRegInfo->NoBuses, 0, 0,
+ (ULONG)PCIRegInfo->NoBuses, 0xff);
+
+ //
+ // Add an additional PCI bus to the registry.
+ //
+ Cbus2AddPciBusToRegistry(PCIRegInfo);
+
+ PCIRegInfo->NoBuses++;
+
+ //
+ // Search the PCI bus on this bus bridge determining
+ // the hierarchy.
+ //
+ Cbus2HierarchicalPciBusSearch(BridgeIndex, PCIRegInfo,
+ (ULONG)(PCIRegInfo->NoBuses - 1));
+
+ //
+ // Set the bus numbers for this bridge.
+ //
+ Cbus2SetHostBridgeBuses(Cbus2BridgePCIBusNumber[BridgeIndex],
+ 0, 0, Cbus2BridgePCIBusNumber[BridgeIndex],
+ (ULONG)PCIRegInfo->NoBuses - 1);
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Check if this C-bus II system is a PELE system.
+ If it is a PELE system, it will use a different interrupt
+ routing algorithm than other C-bus II platforms.
+
+ The identification is done by checking the system board's EISA ID
+ which is at I/O addresses 0xc80 - 0xc83:
+
+ 1. Write FFh to 0C80h
+ 2. Read 0C80h
+ If the contents of 0xc80 equals 0xff, discontinue the
+ identification process -- the system board does not
+ have a readable ID. If the contents of 0xc80 does not
+ equal 0xff and the most significant bit is a zero,
+ the system board supports a readable ID that can be read
+ at 0xc80 - 0xc83.
+
+ PELE's ID is "FUJC071", so each byte of the System board ID is as follows:
+
+ 1st byte(0xc80) is 0x1a.
+ 2nd byte(0xc81) is 0xaa.
+ 3rd byte(0xc82) is 0xc0.
+ 4th byte(0xc83) is 0x71.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Boolean whether a PELE system was found.
+
+--*/
+UCHAR
+Cbus2CheckForPeleSystem(
+VOID
+)
+{
+ WRITE_PORT_UCHAR((PUCHAR)0xc80, (UCHAR)0xff);
+ if (READ_PORT_UCHAR((PUCHAR)0xc80) != (UCHAR)0x1a)
+ return FALSE;
+ if (READ_PORT_UCHAR((PUCHAR)0xc81) != (UCHAR)0xaa)
+ return FALSE;
+ if (READ_PORT_UCHAR((PUCHAR)0xc82) != (UCHAR)0xc0)
+ return FALSE;
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbus2.h b/private/ntos/nthals/halcbus/i386/cbus2.h
new file mode 100644
index 000000000..543d9f1e6
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus2.h
@@ -0,0 +1,397 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus2.h
+
+Abstract:
+
+ Cbus2 hardware architecture definitions for the
+ Corollary C-bus II multiprocessor HAL modules.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _CBUS2_
+#define _CBUS2_
+
+//
+// General notes:
+//
+// - ALL reserved fields must be zero filled on writes to
+// ensure future compatibility.
+//
+// - general CSR register length is 64 bits.
+//
+//
+
+
+
+typedef struct _csr_register_t {
+
+ ULONG LowDword; // 32 bit field
+ ULONG HighDword; // 32 bit field
+
+} CSR_REGISTER_T, *PCSR_REG;
+
+
+
+
+typedef union _elementid_t {
+ struct {
+ ULONG ElementID : 4;
+ ULONG Reserved0 : 28;
+ ULONG Reserved1 : 32;
+ } ra;
+ CSR_REGISTER_T rb;
+} ELEMENTID_T, *PELEMENTID;
+
+
+
+
+typedef union _spurious_t {
+ struct {
+ ULONG Vector : 8;
+ ULONG Reserved0 : 24;
+ ULONG Reserved1 : 32;
+ } ra;
+ CSR_REGISTER_T rb;
+} SPURIOUS_T;
+
+
+typedef union _windowreloc_t {
+ struct {
+ ULONG WindowBase : 9;
+ ULONG Reserved0 : 23;
+ ULONG Reserved1 : 32;
+ } ra;
+ CSR_REGISTER_T rb;
+} WINDOWRELOC_T;
+
+
+
+
+
+//
+// The hardware interrupt map table (16 entries) is indexed by irq.
+// Lower numerical irq lines will receive higher interrupt (IRQL) priority.
+//
+// Each CBC has its own hardware interrupt map registers . note that
+// each processor gets his own CBC, but it need only be used in this
+// mode if there is an I/O card attached to its CBC. each EISA bridge
+// will have a CBC, which is used to access any devices on that EISA bus.
+//
+typedef union _hwintrmap_t {
+ struct {
+ ULONG Vector : 8;
+ ULONG Mode : 3;
+ ULONG Reserved0 : 21;
+ ULONG Reserved1 : 32;
+ } ra;
+ CSR_REGISTER_T rb;
+} HWINTRMAP_T, *PHWINTRMAP;
+
+/*
+ * interrupt trigger conditions
+ */
+#define HW_MODE_DISABLED 0x0
+#define HW_EDGE_RISING 0x100 /* ie: ISA card interrupts */
+#define HW_EDGE_FALLING 0x200
+#define HW_LEVEL_HIGH 0x500
+#define HW_LEVEL_LOW 0x600
+
+/*
+ * CBC rev 1 value for the number of hardware interrupt map entries
+ */
+#define REV1_HWINTR_MAP_ENTRIES 0x10
+
+/*
+ * max growth for the number of hardware interrupt map entries
+ */
+#define HWINTR_MAP_ENTRIES 0x20
+
+
+//
+// 256 intrconfig registers for vectors 0 to 255. this determines how
+// a given processor will react to each of these vectors. each processor
+// has his own intrconfig table in his element space.
+//
+typedef union _intrconfig_t {
+ struct {
+ ULONG Imode : 2;
+ ULONG Reserved0 : 30;
+ ULONG Reserved1 : 32;
+ } ra;
+ CSR_REGISTER_T rb;
+} INTRCONFIG_T, *PINTRCONFIG;
+
+#define HW_IMODE_DISABLED 0x0
+#define HW_IMODE_ALLINGROUP 0x1
+#define HW_IMODE_LIG 0x2
+#define INTR_CONFIG_ENTRIES 0x100
+
+#define CBUS2_LEVEL_TRIGGERED_INTERRUPT 1
+#define CBUS2_EDGE_TRIGGERED_INTERRUPT 2
+
+
+//
+// 256 interrupt request registers for vectors 0 to 255.
+// parallel to the interrupt config register set above.
+// This is used to send the corresponding interrupt vector.
+// which processor gets it is determined by which element's
+// address space you write to.
+//
+// The irq field should always be set when accessed by software.
+// only hardware LIG arbitration will clear it.
+//
+typedef union _intrreq_t {
+ struct {
+ ULONG Irq : 1;
+ ULONG Reserved0 : 31;
+ ULONG Reserved1 : 32;
+ } ra;
+ CSR_REGISTER_T rb;
+} INTRREQ_T, *PINTRREQ;
+
+
+//
+// the Cbus2 task priority register bit layout and
+// minimum/maximum values are defined in cbus.h, as
+// they need to be shared with the symmetric Cbus1.
+//
+
+//
+// bit 7 of the CBC configuration register must be turned off to enable
+// posted writes for EISA I/O cycles.
+//
+#define CBC_DISABLE_PW 0x80
+
+
+//
+// Offsets of various registers within the processor CSR space.
+//
+typedef struct _csr {
+ CSR_REGISTER_T ElementTypeInformation; // 0x0000
+ CSR_REGISTER_T IoTypeInformation; // 0x0008
+ CSR_REGISTER_T ProcessorReset; // 0x0010
+ CSR_REGISTER_T DirectedNmi; // 0x0018
+ CSR_REGISTER_T LED; // 0x0020
+
+ CHAR pad0[0x90 - 0x20 - sizeof (CSR_REGISTER_T)];
+
+ CSR_REGISTER_T PcBusMemoryHoles0; // 0x0090
+ CSR_REGISTER_T PcBusMemoryHoles1; // 0x0098
+ CSR_REGISTER_T PcBusMemoryHoles2; // 0x00A0
+ CSR_REGISTER_T TLM; // 0x00A8
+
+ CHAR pad00[0x100 - 0xA8 - sizeof (CSR_REGISTER_T)];
+
+ ELEMENTID_T BusBridgeSelection; // 0x0100
+
+ WINDOWRELOC_T BridgeWindow0; // 0x0108
+ WINDOWRELOC_T BridgeWindow1; // 0x0110
+
+ CHAR pad1[0x200 - 0x110 - sizeof (WINDOWRELOC_T)];
+
+ TASKPRI_T TaskPriority; // 0x0200
+
+ CSR_REGISTER_T pad2; // 0x208
+ CSR_REGISTER_T FaultControl; // 0x210
+ CSR_REGISTER_T FaultIndication; // 0x218
+ CSR_REGISTER_T InterruptControl; // 0x220
+ CSR_REGISTER_T ErrorVector; // 0x228
+ CSR_REGISTER_T InterruptIndication; // 0x230
+ CSR_REGISTER_T PendingPriority; // 0x238
+
+ SPURIOUS_T SpuriousVector; // 0x0240
+
+ CHAR pad3[0x600 - 0x240 - sizeof (CSR_REGISTER_T)];
+
+ HWINTRMAP_T HardwareInterruptMap[HWINTR_MAP_ENTRIES]; // 0x0600
+ CSR_REGISTER_T HardwareInterruptMapEoi[HWINTR_MAP_ENTRIES]; // 0x0700
+ INTRCONFIG_T InterruptConfiguration[INTR_CONFIG_ENTRIES]; // 0x0800
+ INTRREQ_T InterruptRequest[INTR_CONFIG_ENTRIES]; // 0x1000
+
+ CHAR pad4[0x2000 - 0x1000 -
+ INTR_CONFIG_ENTRIES * sizeof (INTRREQ_T)];
+
+ CSR_REGISTER_T SystemTimer; // 0x2000
+
+ CHAR pad5[0x2140 - 0x2000 - sizeof(CSR_REGISTER_T)];
+
+ CSR_REGISTER_T EccError; // 0x2140
+
+ CHAR pad6[0x3000 - 0x2140 - sizeof(CSR_REGISTER_T)];
+
+ CSR_REGISTER_T EccClear; // 0x3000
+ CSR_REGISTER_T EccSyndrome; // 0x3008
+ CSR_REGISTER_T EccWriteAddress; // 0x3010
+ CSR_REGISTER_T EccReadAddress; // 0x3018
+
+ CHAR pad7[0x8000 - 0x3018 - sizeof(CSR_REGISTER_T)];
+
+ CSR_REGISTER_T CbcConfiguration; // 0x8000
+} CSR_T, *PCSR;
+
+//
+// Offsets of various registers within the memory board CSR space.
+//
+typedef struct _memcsr {
+ CHAR pad0[0x10];
+ CSR_REGISTER_T MemoryFaultStatus; // 0x0010
+ CHAR pad1[0x3020 - 0x10 - sizeof (CSR_REGISTER_T)];
+ CSR_REGISTER_T MemoryEccReadAddress; // 0x3020
+ CSR_REGISTER_T MemoryEccWriteAddress; // 0x3028
+ CSR_REGISTER_T MemoryEccClear; // 0x3028
+ CSR_REGISTER_T MemoryEccSyndrome; // 0x3030
+} MEMCSR_T, *PMEMCSR;
+
+//
+// Interrupt Indication register bit that a fault occurred. This applies
+// to the processor CSR.
+//
+#define CBUS2_FAULT_DETECTED 0x2
+
+//
+// Fault Indication register bits for errors this processor's CSR has latched.
+//
+#define CBUS2_BUS_DATA_UNCORRECTABLE 0x2
+#define CBUS2_BUS_ADDRESS_UNCORRECTABLE 0x10
+
+//
+// Fault Status register bit for errors latched by this memory board's CSR.
+//
+#define CBUS2_MEMORY_FAULT_DETECTED 0x80
+
+//
+// RRD will provide an entry for every Cbus2 element. To avoid
+// using an exorbitant number of PTEs, this entry will specify
+// only the CSR space within each Cbus2 element's space. And only
+// a subset of that, as well, usually on the order of 4 pages.
+// Code wishing to access other portions of the cbus_element
+// space will need to subtract down from the RRD-specified CSR
+// address and map according to their particular needs.
+//
+#define MAX_CSR_BYTES 0x10000
+
+#define csr_register rb.LowDword
+
+//
+// The full layout of a cbus2 element space:
+//
+// Note that only the Csr offset/size is passed up by RRD, and
+// mapped by the HAL. before referencing any other fields, the
+// caller must first set up appropriate PDE/PTE entries.
+//
+typedef struct _cbus2element {
+ CHAR PCBusRAM [16 * 1024 * 1024];
+ CHAR PCBusWindow0 [8 * 1024 * 1024];
+ CHAR PCBusWindow1 [8 * 1024 * 1024];
+ CHAR DeviceReserved [28 * 1024 * 1024];
+ CHAR ControlIO [0x10000];
+ CHAR PCBusIO [0x10000];
+ CHAR Csr [MAX_CSR_BYTES];
+ CHAR IdentityMappedCsr [MAX_CSR_BYTES];
+ CHAR Reserved [0x1C0000];
+ CHAR Ram [0x100000];
+ CHAR Prom [0x100000];
+} CBUS2_ELEMENT, *PCBUS2_ELEMENT;
+
+//
+// offset of CSR within any element's I/O space.
+//
+#define CBUS_CSR_OFFSET 0x3C20000
+
+//
+// id of the default C-bus II bridge
+//
+#define CBUS2_DEFAULT_BRIDGE_ID 0
+
+//
+// reserved element types
+//
+#define CBUS2_ELEMENT_TYPE_RAS 0x50
+
+//
+// Shift for PC Bus Window CSRs
+//
+#define CBUS2_WINDOW_REGISTER_SHIFT 23
+
+//
+// PC Bus memory hole defines to designate all memory
+// holes go to system memory.
+//
+#define CBUS2_NO_MEMORY_HOLES 0x3f;
+#define CBUS2_NO_MEMORY_HOLES1 0xff;
+#define CBUS2_NO_MEMORY_HOLES2 0xffff;
+
+//
+// turn the LED on or off.
+//
+#define CBUS2_LED_OFF 0
+#define CBUS2_LED_ON 1
+
+//
+//
+// Physical address of the Cbus2 local APIC
+//
+#define CBUS2_LOCAL_APIC_LOCATION (PVOID)0xFEE00000
+
+//
+// Physical address of the Cbus2 I/O APIC
+//
+#define CBUS2_IO_APIC_LOCATION (PVOID)0xFEC00000
+
+//
+// Programmed I/O translation ranges
+//
+#define CBUS2_IO_BASE_ADDRESS 0x0000
+#define CBUS2_IO_LIMIT 0xFFFF
+
+//
+// PCI macros used to fill in the configuration space of a PPB
+//
+#define PCI_IO_TO_CFG(x) ((UCHAR)(((x) & 0xF000) >> 8))
+#define PCI_MEMORY_TO_CFG(x) ((USHORT)(((x) & 0xFFF00000) >> 16))
+#define PCI_PREFETCH_TO_CFG(x) ((USHORT)(((x) & 0xFFF00000) >> 16))
+
+#define CBUS2_PCI_LATENCY_TIMER 0x60
+
+typedef struct _cbus2_host_bridge_config {
+ USHORT VendorID; // (ro) 0x0000
+ USHORT DeviceID; // (ro) 0x0002
+ USHORT Command; // Device control 0x0004
+ USHORT Status; // 0x0006
+ UCHAR RevisionID; // (ro) 0x0008
+ UCHAR ProgIf; // (ro) 0x0009
+ UCHAR SubClass; // (ro) 0x000A
+ UCHAR BaseClass; // (ro) 0x000B
+ UCHAR CacheLineSize; // (ro+) 0x000C
+ UCHAR LatencyTimer; // (ro+) 0x000D
+ UCHAR HeaderType; // (ro) 0x000E
+ UCHAR BIST; // Built in self test 0x000F
+
+ UCHAR pad1[0x4A - 0XF - sizeof (UCHAR)];
+ UCHAR BusNumber; // 0x004A
+ UCHAR SubordinateBusNumber; // 0x004B
+ UCHAR pad2[0x70 - 0X4B - sizeof (UCHAR)];
+ UCHAR ErrorCommand; // 0x0070
+ UCHAR ErrorStatus; // 0x0071
+ UCHAR MasterCommand; // 0x0072
+ UCHAR pad3;
+ UCHAR DiagnosticMode; // 0x0074
+ UCHAR pad4[0xFF - 0x74 - sizeof (UCHAR)];
+} CBUS2_HOST_BRIDGE_CONFIG, *PCBUS2_HOST_BRIDGE_CONFIG;
+
+#endif // _CBUS2_
diff --git a/private/ntos/nthals/halcbus/i386/cbus2cbc.asm b/private/ntos/nthals/halcbus/i386/cbus2cbc.asm
new file mode 100644
index 000000000..a69cc8c39
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus2cbc.asm
@@ -0,0 +1,283 @@
+ title "Software Interrupts"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+;Module Name:
+;
+; cbuscbc.asm
+;
+;Abstract:
+;
+; This module implements the Corollary Cbus2 HAL routines to deal
+; with the Corollary CBC distributed interrupt controller chip.
+;
+; This includes the_sending_ of software and IPI interrupts in Windows NT.
+; The receipt of these interrupts is handled elsewhere.
+;
+; Note: The routines in this module are jmp'ed to directly from
+; their common Hal counterparts.
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include cbus.inc
+
+;
+; Some definitions needed for accessing the Corollary CBC...
+;
+
+INTS_ENABLED equ 200 ; X86 EFLAGS bit definition
+
+ .list
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; Cbus2RequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to issue a software interrupt to the
+; calling processor. Since this is all done in hardware, the
+; code to implement this is trivial. Our hardware supports
+; sending the interrupt to lowest-in-group processors, which
+; would be useful for a good number of DPCs, for example, but
+; the kernel doesn't currently tell us which kinds of software
+; interrupts need to go to the caller versus which can go to
+; any processor.
+;
+; Arguments:
+;
+; (esp+4) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+;
+; equates for accessing arguments
+;
+
+KsiRequestIrql equ byte ptr [esp+4]
+
+cPublicProc _Cbus2RequestSoftwareInterrupt ,1
+
+ xor ecx, ecx ; (faster than movzx)
+ mov cl, KsiRequestIrql ; to get the irql
+
+ mov eax, [_Cbus2IrqlToCbus2Addr+4*ecx] ; get h/w CSR offset
+ifdef CBC_REV1
+ pushfd
+ cli
+ add eax, PCR[PcHal.PcrCSR] ; get h/w CSR base
+
+ mov dword ptr [eax], 1 ; send the interrupt
+ popfd
+else
+ mov dword ptr [eax], 1 ; send the interrupt
+endif
+
+ stdRET _Cbus2RequestSoftwareInterrupt
+stdENDP _Cbus2RequestSoftwareInterrupt
+
+ page ,132
+ subttl "Cbus2RequestIpi"
+;++
+;
+; VOID
+; Cbus2RequestIpi(
+; IN ULONG Mask
+; );
+;
+; Routine Description:
+;
+; Requests an interprocessor interrupt.
+;
+; This is generally not an easy thing in Cbus2 hardware...
+;
+; a) Interrupting everyone incl yourself: EASY IN HARDWARE
+;
+; b) Interrupting everyone but yourself: DIFFICULT IN HARDWARE,
+; MADE EASY BY SOFTWARE
+;
+; c) Interrupting a random processor subset: DIFFICULT IN HARDWARE,
+; NOT EASY FOR SOFTWARE EITHER,
+; RESULTS IN LOOPING BELOW
+;
+;
+; To deal with case b), a set of MAX_CBUS_ELEMENTS interrupts have
+; been allocated for IPI vectors. Each processor participates in ALL of them
+; EXCEPT one. So for any processor to issue a global broadcast to all
+; the others, he just sends the IPI vector which he isn't participating in.
+;
+; To support case c) using the case b) model would result in too many
+; vectors being allocated, so instead we loop here in software to do it.
+;
+; Arguments:
+;
+; Mask - Mask of processors to be interrupted
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _Cbus2RequestIpi ,1
+ mov edx, [esp+4] ; get requested recipients
+
+ cmp [_Cbus2EnableBroadcast], 1
+ jne short somesubset
+
+ cmp edx, PCR[PcHal.PcrAllOthers] ; broadcast to everyone else?
+ jne short somesubset ; no, some subset of processors
+
+ mov edx, PCR[PcHal.PcrBroadcast] ; get h/w addr of all others
+ mov dword ptr [edx], 1 ; interrupt them all
+
+ stdRET _Cbus2RequestIpi
+
+ ;
+ ; somewhat unwieldy to structure the code this way, but
+ ; it avoids the expensive bsr/bsf. to avoid a 64K array
+ ; of processor numbers, do it in two separate passes,
+ ; first do processors 0 through 7, and then processors 8
+ ; through 0xF.
+ ;
+
+ align 4
+somesubset:
+
+ or dl, dl ; any processors 0..7 ?
+ jz highcpus ; no, check processors 8..F
+
+ align 4
+@@:
+ movzx ecx, dl ; set up working copy
+ mov cl, _HalpFindFirstSetRight[ecx] ; get processor number
+
+ mov eax, 1
+ shl eax, cl
+ xor edx, eax ; clear bit in requested mask
+
+ ; get correct IPI address
+ mov ecx, dword ptr [_Cbus2SendIPI + ecx * 4]
+
+ mov dword ptr [ecx], 1 ; send this processor the IPI
+
+ or dl, dl ; any more processors 0..7 ?
+ jnz short @b ; get next 0..7 processor
+
+ align 4
+highcpus:
+ or dh, dh ; any processors 8..F?
+ jz alldone ; no, all done
+ shr edx, 8 ; check high processors in dl
+
+ align 4
+@@:
+ movzx ecx, dl ; set up working copy
+ mov cl, _HalpFindFirstSetRight[ecx] ; get (processor number - 8)
+
+ mov eax, 1
+ shl eax, cl
+ xor edx, eax ; clear bit in requested mask
+
+ add ecx, 8 ; in second set of processors
+
+ ; get correct IPI address
+ mov ecx, [_Cbus2SendIPI + ecx * 4 ]
+
+ mov dword ptr [ecx], 1 ; send this processor the IPI
+
+ or dl, dl ; any more processors 0..7 ?
+ jnz short @b ; get next 0..7 processor
+
+ align 4
+alldone:
+
+ stdRET _Cbus2RequestIpi
+stdENDP _Cbus2RequestIpi
+
+;
+; ULONG
+; Cbus2ReadCSR(
+; ULONG CsrAddress
+; )
+;
+; Routine Description:
+;
+; Read the specified register in the CSR space. This routine is
+; coded in assembly because the register must be read/written 32
+; bits at a time, and we don't want the compiler "optimizing" our
+; accesses into byte-enabled operations which the hardware won't
+; understand.
+;
+; Arguments:
+; (esp+4) = Address of the CSR register
+;
+; Returns:
+; Value of the register.
+;
+;--
+cPublicProc _Cbus2ReadCSR ,1
+ mov ecx, [esp + 4] ; CSR register address
+ mov eax, dword ptr [ecx] ; return CSR register contents
+ stdRET _Cbus2ReadCSR
+stdENDP _Cbus2ReadCSR
+
+;++
+;
+; VOID
+; Cbus2WriteCSR(
+; ULONG CsrAddress
+; )
+;
+; Routine Description:
+;
+; Write the specified register in the CSR space. This routine is
+; coded in assembly because the register must be read/written 32
+; bits at a time, and we don't want the compiler "optimizing" our
+; accesses into byte-enabled operations which the hardware won't
+; understand.
+;
+; Arguments:
+; (esp+4) = Address of the CSR register
+; (esp+8) = Contents to write to the specified register
+;
+;--
+cPublicProc _Cbus2WriteCSR ,2
+
+ mov ecx, [esp + 4] ; CSR register address
+ mov eax, [esp + 8] ; new contents
+ mov [ecx], eax ; set the new value
+
+ stdRET _Cbus2WriteCSR
+
+stdENDP _Cbus2WriteCSR
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halcbus/i386/cbus2ecc.c b/private/ntos/nthals/halcbus/i386/cbus2ecc.c
new file mode 100644
index 000000000..f19655623
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus2ecc.c
@@ -0,0 +1,475 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus2ecc.c
+
+Abstract:
+
+ This module implements the Corollary Cbus2 ECC specific functions for
+ the Hardware Architecture Layer (HAL) for Windows NT.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cbusrrd.h" // HAL <-> RRD interface definitions
+#include "cbus_nt.h" // C-bus NT-specific implementation stuff
+#include "cbus.h" // needed for cbus2.h inclusion
+#include "cbus2.h" // C-bus II specific stuff
+#include "bugcodes.h"
+#include "stdio.h"
+#include "cbusnls.h"
+
+ULONG
+Cbus2ReadCSR(PULONG);
+
+VOID
+Cbus2WriteCSR(PULONG, ULONG);
+
+VOID
+CbusHardwareFailure(
+IN PUCHAR HardwareMessage
+);
+
+extern KSPIN_LOCK Cbus2NMILock;
+extern ULONG CbusBootedProcessors;
+extern ULONG Cbus2BridgesFound;
+extern PCSR Cbus2BridgeCSR[CBUS_MAX_BRIDGES];
+ULONG Cbus2NMIHandler;
+
+//
+// defines for the Cbus2 ECC syndrome
+//
+#define MULTIBIT 3
+#define DOUBLEBIT 2
+#define SINGLEBIT 1
+#define NOECCERROR 0x7f
+
+//
+// defines for the Cbus2 ECC error register
+//
+typedef struct _extmear_t {
+ ULONG Syndrome:8;
+ ULONG reserved:24;
+} EXTMEAR_T, *PEXTMEAR;
+
+UCHAR cbus2_edac_syndrome[] = {
+
+NOECCERROR,/* 00 */ SINGLEBIT, /* 01 */ SINGLEBIT, /* 02 */ MULTIBIT, /* 03 */
+SINGLEBIT, /* 04 */ MULTIBIT, /* 05 */ MULTIBIT, /* 06 */ MULTIBIT, /* 07 */
+SINGLEBIT, /* 08 */ MULTIBIT, /* 09 */ MULTIBIT, /* 0A */ SINGLEBIT, /* 0B */
+MULTIBIT, /* 0C */ MULTIBIT, /* 0D */ SINGLEBIT, /* 0E */ MULTIBIT, /* 0F */
+SINGLEBIT, /* 10 */ MULTIBIT, /* 11 */ MULTIBIT, /* 12 */ SINGLEBIT, /* 13 */
+MULTIBIT, /* 14 */ SINGLEBIT, /* 15 */ SINGLEBIT, /* 16 */ MULTIBIT, /* 17 */
+MULTIBIT, /* 18 */ SINGLEBIT, /* 19 */ SINGLEBIT, /* 1A */ MULTIBIT, /* 1B */
+SINGLEBIT, /* 1C */ MULTIBIT, /* 1D */ MULTIBIT, /* 1E */ MULTIBIT, /* 1F */
+SINGLEBIT, /* 20 */ MULTIBIT, /* 21 */ MULTIBIT, /* 22 */ SINGLEBIT, /* 23 */
+MULTIBIT, /* 24 */ SINGLEBIT, /* 25 */ SINGLEBIT, /* 26 */ MULTIBIT, /* 27 */
+MULTIBIT, /* 28 */ SINGLEBIT, /* 29 */ SINGLEBIT, /* 2A */ MULTIBIT, /* 2B */
+SINGLEBIT, /* 2C */ MULTIBIT, /* 2D */ MULTIBIT, /* 2E */ MULTIBIT, /* 2F */
+MULTIBIT, /* 30 */ SINGLEBIT, /* 31 */ MULTIBIT, /* 32 */ MULTIBIT, /* 33 */
+SINGLEBIT, /* 34 */ MULTIBIT, /* 35 */ MULTIBIT, /* 36 */ MULTIBIT, /* 37 */
+MULTIBIT, /* 38 */ MULTIBIT, /* 39 */ MULTIBIT, /* 3A */ MULTIBIT, /* 3B */
+MULTIBIT, /* 3C */ MULTIBIT, /* 3D */ MULTIBIT, /* 3E */ MULTIBIT, /* 3F */
+SINGLEBIT, /* 40 */ MULTIBIT, /* 41 */ MULTIBIT, /* 42 */ MULTIBIT, /* 43 */
+MULTIBIT, /* 44 */ MULTIBIT, /* 45 */ MULTIBIT, /* 46 */ MULTIBIT, /* 47 */
+MULTIBIT, /* 48 */ MULTIBIT, /* 49 */ SINGLEBIT, /* 4A */ MULTIBIT, /* 4B */
+MULTIBIT, /* 4C */ MULTIBIT, /* 4D */ MULTIBIT, /* 4E */ SINGLEBIT, /* 4F */
+MULTIBIT, /* 50 */ MULTIBIT, /* 51 */ SINGLEBIT, /* 52 */ MULTIBIT, /* 53 */
+SINGLEBIT, /* 54 */ MULTIBIT, /* 55 */ MULTIBIT, /* 56 */ SINGLEBIT, /* 57 */
+SINGLEBIT, /* 58 */ MULTIBIT, /* 59 */ MULTIBIT, /* 5A */ SINGLEBIT, /* 5B */
+MULTIBIT, /* 5C */ SINGLEBIT, /* 5D */ MULTIBIT, /* 5E */ MULTIBIT, /* 5F */
+MULTIBIT, /* 60 */ MULTIBIT, /* 61 */ SINGLEBIT, /* 62 */ MULTIBIT, /* 63 */
+SINGLEBIT, /* 64 */ MULTIBIT, /* 65 */ MULTIBIT, /* 66 */ SINGLEBIT, /* 67 */
+SINGLEBIT, /* 68 */ MULTIBIT, /* 69 */ MULTIBIT, /* 6A */ SINGLEBIT, /* 6B */
+MULTIBIT, /* 6C */ SINGLEBIT, /* 6D */ MULTIBIT, /* 6E */ MULTIBIT, /* 6F */
+SINGLEBIT, /* 70 */ MULTIBIT, /* 71 */ MULTIBIT, /* 72 */ MULTIBIT, /* 73 */
+MULTIBIT, /* 74 */ SINGLEBIT, /* 75 */ MULTIBIT, /* 76 */ MULTIBIT, /* 77 */
+MULTIBIT, /* 78 */ MULTIBIT, /* 79 */ MULTIBIT, /* 7A */ MULTIBIT, /* 7B */
+MULTIBIT, /* 7C */ MULTIBIT, /* 7D */ MULTIBIT, /* 7E */ MULTIBIT, /* 7F */
+SINGLEBIT, /* 80 */ MULTIBIT, /* 81 */ MULTIBIT, /* 82 */ MULTIBIT, /* 83 */
+MULTIBIT, /* 84 */ MULTIBIT, /* 85 */ MULTIBIT, /* 86 */ MULTIBIT, /* 87 */
+MULTIBIT, /* 88 */ MULTIBIT, /* 89 */ SINGLEBIT, /* 8A */ MULTIBIT, /* 8B */
+MULTIBIT, /* 8C */ MULTIBIT, /* 8D */ MULTIBIT, /* 8E */ SINGLEBIT, /* 8F */
+MULTIBIT, /* 90 */ MULTIBIT, /* 91 */ SINGLEBIT, /* 92 */ MULTIBIT, /* 93 */
+SINGLEBIT, /* 94 */ MULTIBIT, /* 95 */ MULTIBIT, /* 96 */ SINGLEBIT, /* 97 */
+SINGLEBIT, /* 98 */ MULTIBIT, /* 99 */ MULTIBIT, /* 9A */ SINGLEBIT, /* 9B */
+MULTIBIT, /* 9C */ SINGLEBIT, /* 9D */ MULTIBIT, /* 9E */ MULTIBIT, /* 9F */
+MULTIBIT, /* A0 */ MULTIBIT, /* A1 */ SINGLEBIT, /* A2 */ MULTIBIT, /* A3 */
+SINGLEBIT, /* A4 */ MULTIBIT, /* A5 */ MULTIBIT, /* A6 */ SINGLEBIT, /* A7 */
+SINGLEBIT, /* A8 */ MULTIBIT, /* A9 */ MULTIBIT, /* AA */ SINGLEBIT, /* AB */
+MULTIBIT, /* AC */ SINGLEBIT, /* AD */ MULTIBIT, /* AE */ MULTIBIT, /* AF */
+SINGLEBIT, /* B0 */ MULTIBIT, /* B1 */ MULTIBIT, /* B2 */ MULTIBIT, /* B3 */
+MULTIBIT, /* B4 */ SINGLEBIT, /* B5 */ MULTIBIT, /* B6 */ MULTIBIT, /* B7 */
+MULTIBIT, /* B8 */ MULTIBIT, /* B9 */ MULTIBIT, /* BA */ MULTIBIT, /* BB */
+MULTIBIT, /* BC */ MULTIBIT, /* BD */ MULTIBIT, /* BE */ MULTIBIT, /* BF */
+MULTIBIT, /* C0 */ MULTIBIT, /* C1 */ MULTIBIT, /* C2 */ MULTIBIT, /* C3 */
+MULTIBIT, /* C4 */ MULTIBIT, /* C5 */ MULTIBIT, /* C6 */ MULTIBIT, /* C7 */
+MULTIBIT, /* C8 */ MULTIBIT, /* C9 */ MULTIBIT, /* CA */ SINGLEBIT, /* CB */
+MULTIBIT, /* CC */ MULTIBIT, /* CD */ SINGLEBIT, /* CE */ MULTIBIT, /* CF */
+MULTIBIT, /* D0 */ MULTIBIT, /* D1 */ MULTIBIT, /* D2 */ SINGLEBIT, /* D3 */
+MULTIBIT, /* D4 */ SINGLEBIT, /* D5 */ SINGLEBIT, /* D6 */ MULTIBIT, /* D7 */
+MULTIBIT, /* D8 */ SINGLEBIT, /* D9 */ SINGLEBIT, /* DA */ MULTIBIT, /* DB */
+SINGLEBIT, /* DC */ MULTIBIT, /* DD */ MULTIBIT, /* DE */ MULTIBIT, /* DF */
+MULTIBIT, /* E0 */ MULTIBIT, /* E1 */ MULTIBIT, /* E2 */ SINGLEBIT, /* E3 */
+MULTIBIT, /* E4 */ SINGLEBIT, /* E5 */ SINGLEBIT, /* E6 */ MULTIBIT, /* E7 */
+MULTIBIT, /* E8 */ SINGLEBIT, /* E9 */ SINGLEBIT, /* EA */ MULTIBIT, /* EB */
+SINGLEBIT, /* EC */ MULTIBIT, /* ED */ MULTIBIT, /* EE */ MULTIBIT, /* EF */
+MULTIBIT, /* F0 */ SINGLEBIT, /* F1 */ MULTIBIT, /* F2 */ MULTIBIT, /* F3 */
+SINGLEBIT, /* F4 */ MULTIBIT, /* F5 */ MULTIBIT, /* F6 */ MULTIBIT, /* F7 */
+MULTIBIT, /* F8 */ MULTIBIT, /* F9 */ MULTIBIT, /* FA */ MULTIBIT, /* FB */
+MULTIBIT, /* FC */ MULTIBIT, /* FD */ MULTIBIT, /* FE */ MULTIBIT, /* FF */
+
+};
+
+#if DBG
+#define NMI_BUTTON_PRESSED() 0
+#else
+#define NMI_BUTTON_PRESSED() 0
+#endif
+
+NTSTATUS
+Cbus2ResolveNMI(
+ IN PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ This function determines the cause of the NMI so that the user can
+ replace any offending SIMMs.
+
+Arguments:
+
+ NmiInfo - pointer to the NMI information structure
+
+Return Value:
+
+ Returns the byte address which caused the NMI, 0 if indeterminate
+
+--*/
+{
+ PCSR csr;
+ UCHAR syndrome;
+ UCHAR memsyndrome;
+ UCHAR EccError;
+ ULONG Processor;
+ ULONG InterruptIndication;
+ ULONG FaultIndication;
+ ULONG ErrorType;
+ PMEMCSR memcsr;
+ PMEMORY_CARD pm;
+ ULONG board;
+ UCHAR NmiMessage[80];
+ PHYSICAL_ADDRESS FaultAddress;
+ BOOLEAN founderror = FALSE;
+ ULONG original_bridge;
+ ULONG BridgeId;
+ ULONG BusNumber;
+ extern ULONG Cbus2BridgeId[];
+ extern PCSR Cbus2BridgeCSR[];
+ extern NTSTATUS DefaultHalHandleNMI( IN OUT PVOID);
+ extern VOID CbusClearEISANMI(VOID);
+
+ if (NMI_BUTTON_PRESSED()) {
+
+ //
+ // NMI button was pressed, so go to the debugger
+ //
+
+ _asm {
+ int 3
+ }
+
+ //
+ // Clear the NMI in hardware so the system can continue
+ //
+ // assume that bridge 0 needs the clear in this case.
+ // save the original value for restoral after the clear.
+ // repoint our I/O references to the default bus bridge number.
+ //
+ BusNumber =0;
+
+ BridgeId = Cbus2BridgeId[BusNumber];
+ csr = Cbus2BridgeCSR[BusNumber];
+
+ original_bridge = csr->BusBridgeSelection.csr_register;
+ csr->BusBridgeSelection.csr_register =
+ ((original_bridge & ~MAX_ELEMENT_CSRS) | BridgeId);
+
+
+ CbusClearEISANMI();
+
+ //
+ // restore our default bridge references to what they
+ // were when we started...
+ //
+ csr->BusBridgeSelection.csr_register = original_bridge;
+
+ return STATUS_SUCCESS; // ignore this NMI
+ }
+
+ if (CbusGlobal.nonstdecc)
+ return DefaultHalHandleNMI(NmiInfo);
+
+ //
+ // All Cbus2 faults will generate an NMI on all the processors.
+ // An EISA NMI will also go to all CPUs. Only directed NMIs
+ // (sent by software) can go to less than all the processors.
+ //
+ // only one processor may proceed beyond this point,
+ // so first get the Cbus HAL's NMI lock.
+ //
+
+ KiAcquireSpinLock(&Cbus2NMILock);
+
+ if (Cbus2NMIHandler) {
+ KiReleaseSpinLock(&Cbus2NMILock);
+ //
+ // another processor is handling it, so just spin forever
+ //
+ while (1)
+ ;
+ }
+
+ Cbus2NMIHandler = 1;
+
+ KiReleaseSpinLock(&Cbus2NMILock);
+
+ //
+ // Now display all the CSRs of:
+ // a) all the processors and
+ // b) all the memory boards and
+ // c) all the I/O bridges
+ //
+
+ //
+ // print out a leading newline so if he's running a checked
+ // build, he'll be able to see the whole line. otherwise,
+ // the kernel debugger CTS/SEND/etc. serial line status will
+ // overwrite the first NMI line from our processor loop below.
+ //
+ HalDisplayString (MSG_NEWLINE);
+
+ //
+ // first go through the processors. there is no need to disable
+ // ecc to safely take the system down because we will not iret,
+ // (which is needed to re-enable NMI).
+ //
+ for (Processor = 0; Processor < CbusBootedProcessors; Processor++) {
+ csr = CbusCSR[Processor].csr;
+
+ InterruptIndication = csr->InterruptIndication.LowDword;
+
+ //
+ // if the interrupt indication is not set, then it's not
+ // a Cbus2 NMI, so it must be something from EISA. we'll
+ // handle EISA NMI detection last.
+ //
+ if ((InterruptIndication & CBUS2_FAULT_DETECTED) == 0) {
+ sprintf(NmiMessage, MSG_NMI_ECC0, Processor);
+ HalDisplayString (NmiMessage);
+ continue;
+ }
+
+ founderror = TRUE;
+ FaultIndication = (csr->FaultIndication.LowDword & 0xFF);
+
+ if ((FaultIndication & (CBUS2_BUS_DATA_UNCORRECTABLE | CBUS2_BUS_ADDRESS_UNCORRECTABLE)) == 0) {
+ //
+ // it is a Cbus2 NMI, but we cannot determine the
+ // address. at least display the fault indication
+ // register so we can see what type of error it was.
+ //
+ sprintf(NmiMessage, MSG_NMI_ECC1, Processor,
+ FaultIndication & CbusGlobal.FaultControlMask);
+ HalDisplayString (NmiMessage);
+ continue;
+ }
+
+ FaultAddress.LowPart = 0;
+ FaultAddress.HighPart = 0;
+
+ //
+ // EccError contains the quadword index of which quadword
+ // in the cache line is bad. since words in a cacheline
+ // are not always transferred in order, we must print this
+ // value as well as the address of the cacheline. the
+ // transfer order is deterministic based on the specific
+ // addresses, but not all addresses are read in the same order.
+ //
+ EccError = ((UCHAR)csr->EccError.LowDword & 0x03);
+
+ syndrome = ((UCHAR)csr->EccSyndrome.LowDword & 0xFF);
+
+ //
+ // check if this memory board generated the ecc error
+ //
+
+ ErrorType = cbus2_edac_syndrome[syndrome];
+
+ ASSERT (ErrorType != NOECCERROR && ErrorType != SINGLEBIT);
+
+ //
+ // the error is latched in this processor's DPX registers.
+ // now we need to figure out which register is correct, since
+ // the error could have happened in the memory or on the bus.
+ //
+
+ //
+ // display the values this processor has latched.
+ //
+ FaultAddress.HighPart = csr->EccWriteAddress.LowDword;
+ FaultAddress.LowPart = csr->EccReadAddress.LowDword;
+
+ sprintf(NmiMessage, MSG_NMI_ECC2,
+ Processor,
+ FaultAddress.HighPart,
+ FaultAddress.LowPart,
+ EccError,
+ FaultIndication & CbusGlobal.FaultControlMask);
+
+ HalDisplayString (NmiMessage);
+ }
+
+ //
+ // next go through the memory boards...
+ //
+
+ pm = CbusMemoryBoards;
+ for (board = 0; board < CbusMemoryBoardIndex; board++, pm++) {
+
+ memcsr = (PMEMCSR)pm->regmap;
+
+ if ((memcsr->MemoryFaultStatus.LowDword & CBUS2_MEMORY_FAULT_DETECTED) == 0) {
+ sprintf(NmiMessage, MSG_NMI_ECC3, board);
+ HalDisplayString (NmiMessage);
+ continue;
+ }
+
+ founderror = TRUE;
+
+ //
+ // this board contains an error
+ //
+ memsyndrome = ((UCHAR)memcsr->MemoryEccSyndrome.LowDword & 0xFF);
+ ErrorType = cbus2_edac_syndrome[memsyndrome];
+
+ ASSERT (ErrorType != NOECCERROR && ErrorType != SINGLEBIT);
+
+ FaultAddress.HighPart = memcsr->MemoryEccWriteAddress.LowDword;
+ FaultAddress.LowPart = memcsr->MemoryEccReadAddress.LowDword;
+
+ sprintf(NmiMessage, MSG_NMI_ECC4,
+ board,
+ FaultAddress.HighPart,
+ FaultAddress.LowPart);
+
+ HalDisplayString (NmiMessage);
+ }
+
+ //
+ // lastly, go through the I/O bridges...
+ //
+ for (BusNumber = 0; BusNumber < Cbus2BridgesFound; BusNumber++) {
+ csr = Cbus2BridgeCSR[BusNumber];
+
+ InterruptIndication = csr->InterruptIndication.LowDword;
+
+ //
+ // if the interrupt indication is not set, then it's not
+ // a Cbus2 NMI, so it must be something from EISA. we'll
+ // handle EISA NMI detection last.
+ //
+ if ((InterruptIndication & CBUS2_FAULT_DETECTED) == 0) {
+ sprintf(NmiMessage, MSG_NMI_ECC5, BusNumber);
+ HalDisplayString (NmiMessage);
+ continue;
+ }
+
+ founderror = TRUE;
+ FaultIndication = (csr->FaultIndication.LowDword & 0xFF);
+
+ if ((FaultIndication & (CBUS2_BUS_DATA_UNCORRECTABLE | CBUS2_BUS_ADDRESS_UNCORRECTABLE)) == 0) {
+ //
+ // it is a Cbus2 NMI, but we cannot determine the
+ // address. at least display the fault indication
+ // register so we can see what type of error it was.
+ //
+ sprintf(NmiMessage, MSG_NMI_ECC6, BusNumber,
+ FaultIndication & CbusGlobal.FaultControlMask);
+ HalDisplayString (NmiMessage);
+ continue;
+ }
+
+ FaultAddress.LowPart = 0;
+ FaultAddress.HighPart = 0;
+
+ //
+ // EccError contains the quadword index of which quadword
+ // in the cache line is bad. since words in a cacheline
+ // are not always transferred in order, we must print this
+ // value as well as the address of the cacheline. the
+ // transfer order is deterministic based on the specific
+ // addresses, but not all addresses are read in the same order.
+ //
+ EccError = ((UCHAR)csr->EccError.LowDword & 0x03);
+
+ syndrome = ((UCHAR)csr->EccSyndrome.LowDword & 0xFF);
+
+ //
+ // check if this memory board generated the ecc error
+ //
+
+ ErrorType = cbus2_edac_syndrome[syndrome];
+
+ ASSERT (ErrorType != NOECCERROR && ErrorType != SINGLEBIT);
+
+ //
+ // the error is latched in this processor's DPX registers.
+ // now we need to figure out which register is correct, since
+ // the error could have happened in the memory or on the bus.
+ //
+
+ //
+ // display the values this processor has latched.
+ //
+ FaultAddress.HighPart = csr->EccWriteAddress.LowDword;
+ FaultAddress.LowPart = csr->EccReadAddress.LowDword;
+
+ sprintf(NmiMessage, MSG_NMI_ECC7,
+ BusNumber,
+ FaultAddress.HighPart,
+ FaultAddress.LowPart,
+ EccError,
+ FaultIndication & CbusGlobal.FaultControlMask);
+
+ HalDisplayString (NmiMessage);
+ }
+
+ if (founderror == TRUE) {
+ //
+ // this call will not return
+ //
+ CbusHardwareFailure (MSG_NMI_ECC8);
+ }
+
+ //
+ // No errors were found in Cbus RAM, so check for EISA errors
+ //
+
+ DefaultHalHandleNMI(NmiInfo);
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbus_nt.h b/private/ntos/nthals/halcbus/i386/cbus_nt.h
new file mode 100644
index 000000000..258e391de
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus_nt.h
@@ -0,0 +1,226 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus_nt.h
+
+Abstract:
+
+ Windows NT-specific definitions for the Corollary C-bus I & II
+ MP HAL modules. The global definitions needed for the
+ Windows NT HAL reside here. Hardware architecture-specific
+ definitions are in their respective modules.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _CBUS_NT_H
+#define _CBUS_NT_H
+
+//
+// WARNING: Changes to the CBUS_MAX_BRIDGES definition below may involve
+// detailed changes to the source code which allocates interrupt vectors.
+// Make sure you know what you are doing if you change this.
+//
+
+#define CBUS_MAX_BRIDGES 2
+
+extern ULONG CbusProcessors;
+
+extern PVOID CbusBroadcastCSR;
+
+//
+// Map IRQL level to a hardware task priority vector. Note
+// that since many drivers may share the same IRQL, yet have
+// different hardware interrupt vectors. Thus, the CbusIrqlToVector[]
+// array will always contain the highest priority (== highest numerically)
+// vector for a given IRQL index. This way, CbusIrqlToVector[] can provide
+// fast lookups for KfRaiseIrql(), KfLowerIrql(), etc.
+//
+extern ULONG CbusIrqlToVector[HIGH_LEVEL + 1];
+
+//
+// The first 0x30 IDT entries are reserved as follows:
+// 0 -- 0xf for Intel processor traps
+// 0x10 -- 0x2f for Intel reserved
+// 0x20 -- 0x2f for Microsoft (system call entry point, profiling, etc)
+//
+// APC is the lowest priority interrupt actually sent & masked, and Microsoft
+// has reserved vector 0x1F for it. DPC has been reserved vector 0x2F by
+// Microsoft.
+//
+// All other task priorities and interrupt request registers cannot
+// include the low 0x30 IDT entries. Vectors and task priorities are
+// synonymous to the Corollary hardware. Cbus1 & Cbus2 share
+// the LOW, APC, DPC and HIGH task priorities. Other priorities generally
+// differ depending on whether the CBC or the APIC is being used. This
+// is because the CBC allows byte priority granularity, but the APIC only
+// prioritizes in buckets of 16 priorities. The individual hardware modules
+// contain the exact architecture layout and issues.
+//
+
+#define LOW_TASKPRI 0x00 // lowest priority
+#define APC_TASKPRI 0x1F
+#define DPC_TASKPRI 0x2F
+#define HIGH_TASKPRI 0xFF // highest priority
+
+//
+// Define the PCR HalReserved[] entries being used by the Corollary HAL.
+//
+// WARNING! THIS MUST MATCH cbus.inc !!!
+//
+
+//
+// element is the logical processor number (0..n)
+//
+
+#define PCR_PROCESSOR 0
+
+//
+// bit is the logical processor bit number (0x1, 0x2, 0x4, 0x8, 0x10, etc)
+//
+
+#define PCR_BIT 1
+
+//
+// PCR_CSR maps the per-processor area that RRD has informed us about:
+// for Cbus2, this CPUS's csr base pointer
+// for Cbus1, this CPUS's memory-mapped Cbus I/O space
+
+#define PCR_CSR 2
+
+//
+// Cbus2 CBC & Cbus1 APIC taskpri reg address
+// Cbus1 taskpri didn't need to be in PCR
+// since we have mapped the APIC at the same
+// PHYSICAL address for all processors, but
+// doing it this way achieves more commonality
+// between the code for the two platforms.
+// For CBC Rev2, we will use the identity mapped
+// CSR and completely get rid of this field.
+//
+
+#define PCR_TASKPRI 3
+
+//
+// CBC global broadcast hardware address - provides a way for any
+// processor to interrupt everyone but himself. This entry is not used
+// by the APIC code, as the APIC supports this completely in hardware.
+//
+
+#define PCR_BROADCAST 4
+
+//
+// Bitfield mask of all the other processors in the system but the caller
+//
+#define PCR_ALL_OTHERS 5
+
+//
+// Address of this processor's LED ON register
+//
+#define PCR_LED_ON 6
+
+//
+// Address of this processor's LED OFF register
+//
+#define PCR_LED_OFF 7
+
+//
+// This PCR field will be used by all CPUs other than CPU 0 to find out
+// when to call the KeUpdateRunTime() routine. This routine (KeUpdateRunTime)
+// is called at the maximum supported rate as reported by KeSetTimeIncrement.
+//
+#define TICK_OFFSET 8
+
+//
+// Definitions of supported Corollary C-bus platforms
+//
+#define COROLLARY_CBUS1 1 // Corollary C-bus 1 system
+#define COROLLARY_CBUS2 2 // Corollary C-bus 2 system
+
+//
+// Definitions of the switch table for multiple Corollary C-bus platforms.
+// The structure of this is defined by the layout of the Windows NT HAL.
+// The first three entries are captured in variables as well (for speed)
+// since they are dereferenced frequently throughout the life of the system.
+//
+// WARNING! This structure must match the one in cbus.inc !!!
+//
+typedef struct _CBUS_NTHAL {
+
+ VOID (*HalRequestInterrupt)( IN ULONG);
+
+ VOID (*HalRequestSoftwareInterrupt)( IN KIRQL);
+
+ LARGE_INTEGER (*HalQueryPerformanceCounter)(IN OUT PLARGE_INTEGER);
+
+ VOID (*BootCPU)( IN ULONG processor, IN ULONG);
+
+
+ VOID (*InitializePlatform)(VOID);
+
+ VOID (*InitializeCPU)(ULONG);
+
+ BOOLEAN (*EnableNonDeviceInterrupt)(ULONG);
+
+ VOID (*EnableDeviceInterrupt)(ULONG, PVOID, ULONG, USHORT, USHORT);
+
+
+ VOID (*DisableInterrupt)(ULONG, PVOID, ULONG, USHORT, USHORT);
+
+ PVOID (*LinkVector)(PBUS_HANDLER, ULONG, ULONG);
+
+ ULONG (*MapVector)(PBUS_HANDLER, ULONG, ULONG, PKIRQL);
+
+ VOID (*ParseRRD)(IN OUT PEXT_ID_INFO, IN OUT PULONG);
+
+
+ NTSTATUS (*ResolveNMI)(IN PVOID);
+
+ VOID (*HalInitializeInterrupts)(IN ULONG);
+
+ VOID (*ResetAllOtherProcessors)(IN ULONG);
+
+ VOID (*InitOtherBuses)(VOID);
+
+
+ ULONG (*HalSetTimeIncrement)(IN ULONG);
+
+ VOID (*CheckBusRanges)(VOID);
+
+ VOID (*AddMemoryHoles)(VOID);
+
+ VOID (*InitializeOtherPciBus)(VOID);
+
+} CBUS_NTHAL, *PCBUS_NTHAL;
+
+extern PCBUS_NTHAL CbusBackend;
+
+//
+// software categories for each possible I/O interrupt
+//
+
+#define SW_BINDTOBOOT 0x0
+#define SW_LIG 0x1
+#define SW_GOTOALL 0x2
+#define SW_DISABLED 0x3
+
+//
+// software categories for interrupt vectors when detaching
+//
+
+#define LAST_CPU_DETACH 0x0
+#define NOT_LAST_CPU_DETACH 0x1
+
+#endif // _CBUS_NT_H
diff --git a/private/ntos/nthals/halcbus/i386/cbus_sw.c b/private/ntos/nthals/halcbus/i386/cbus_sw.c
new file mode 100644
index 000000000..bd674c11a
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbus_sw.c
@@ -0,0 +1,191 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus_sw.c
+
+Abstract:
+
+ This module defines the switch table for various C-bus platform
+ architectures under Windows NT. During initialization, the
+ Corollary HAL will revector all hardware-specific actions
+ through the switch table declared here.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cbus_nt.h" // C-bus NT-specific implementation stuff
+#include "cbusrrd.h" // HAL <-> RRD interface definitions
+
+BOOLEAN
+CbusMPMachine(VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, CbusMPMachine)
+#endif
+
+extern VOID Cbus2RequestIpi ( IN ULONG Mask);
+extern VOID Cbus2RequestSoftwareInterrupt (KIRQL);
+extern VOID Cbus2BootCPU (ULONG, ULONG);
+extern VOID Cbus2InitializePlatform ( VOID);
+extern VOID Cbus2InitializeCPU ( ULONG);
+extern BOOLEAN Cbus2EnableNonDeviceInterrupt(ULONG);
+extern VOID Cbus2EnableDeviceInterrupt(ULONG, PVOID, ULONG, USHORT, USHORT);
+extern VOID Cbus2DisableInterrupt(ULONG, PVOID, ULONG, USHORT, USHORT);
+extern PVOID Cbus2LinkVector(PBUS_HANDLER, ULONG, ULONG);
+extern ULONG Cbus2MapVector(PBUS_HANDLER, ULONG, ULONG, PKIRQL);
+extern VOID Cbus2ParseRRD(IN PVOID, IN OUT PULONG);
+extern NTSTATUS Cbus2ResolveNMI(PVOID);
+extern VOID Cbus2InitializeInterrupts(ULONG);
+extern LARGE_INTEGER Cbus2QueryPerformanceCounter(IN OUT PLARGE_INTEGER);
+extern VOID Cbus2ResetAllOtherProcessors(ULONG);
+extern VOID Cbus2InitOtherBuses(VOID);
+extern ULONG Cbus2SetTimeIncrement(ULONG);
+extern VOID Cbus2CheckBusRanges(VOID);
+extern VOID Cbus2AddMemoryHoles(VOID);
+extern VOID Cbus2InitializeOtherPciBus(VOID);
+
+extern VOID CbusRequestApicIpi ( IN ULONG Mask);
+extern VOID CbusRequestApicSoftwareInterrupt ( IN KIRQL Rirql);
+extern VOID Cbus1BootCPU ( IN ULONG, IN ULONG);
+extern VOID Cbus1InitializePlatform ( VOID);
+extern VOID Cbus1InitializeCPU ( ULONG);
+extern BOOLEAN Cbus1EnableNonDeviceInterrupt(IN ULONG);
+extern VOID Cbus1EnableDeviceInterrupt(ULONG, PVOID, ULONG, USHORT, USHORT);
+extern VOID Cbus1DisableInterrupt(ULONG, PVOID, ULONG, USHORT, USHORT);
+
+
+extern VOID Cbus1ParseRRD(IN PVOID, IN OUT PULONG);
+
+extern PVOID Cbus1LinkVector(PBUS_HANDLER, ULONG, ULONG);
+
+extern ULONG Cbus1MapVector(PBUS_HANDLER, ULONG, ULONG, PKIRQL);
+
+extern NTSTATUS Cbus1ResolveNMI(PVOID);
+
+extern VOID Cbus1InitializeInterrupts(ULONG);
+extern LARGE_INTEGER Cbus1QueryPerformanceCounter(PLARGE_INTEGER);
+extern VOID Cbus1ResetAllOtherProcessors(ULONG);
+extern ULONG Cbus1SetTimeIncrement(ULONG);
+
+typedef VOID (*VOID_FUNCTION)(VOID);
+
+CBUS_NTHAL cbus2_nthal = {
+ Cbus2RequestIpi,
+ Cbus2RequestSoftwareInterrupt,
+ Cbus2QueryPerformanceCounter,
+ Cbus2BootCPU,
+
+ Cbus2InitializePlatform,
+ Cbus2InitializeCPU,
+ Cbus2EnableNonDeviceInterrupt,
+ Cbus2EnableDeviceInterrupt,
+
+ Cbus2DisableInterrupt,
+ Cbus2LinkVector,
+ Cbus2MapVector,
+ Cbus2ParseRRD,
+
+ Cbus2ResolveNMI,
+ Cbus2InitializeInterrupts,
+ Cbus2ResetAllOtherProcessors,
+ Cbus2InitOtherBuses,
+
+ Cbus2SetTimeIncrement,
+ Cbus2CheckBusRanges,
+ Cbus2AddMemoryHoles,
+ Cbus2InitializeOtherPciBus,
+};
+
+CBUS_NTHAL cbus1_nthal = {
+ CbusRequestApicIpi,
+ CbusRequestApicSoftwareInterrupt,
+ Cbus1QueryPerformanceCounter,
+ Cbus1BootCPU,
+
+ Cbus1InitializePlatform,
+ Cbus1InitializeCPU,
+ Cbus1EnableNonDeviceInterrupt,
+ Cbus1EnableDeviceInterrupt,
+
+ Cbus1DisableInterrupt,
+ Cbus1LinkVector,
+ Cbus1MapVector,
+ Cbus1ParseRRD,
+
+ Cbus1ResolveNMI,
+ Cbus1InitializeInterrupts,
+ Cbus1ResetAllOtherProcessors,
+ (VOID_FUNCTION)0,
+
+ Cbus1SetTimeIncrement,
+ (VOID_FUNCTION)0,
+ (VOID_FUNCTION)0,
+ (VOID_FUNCTION)0
+};
+
+PCBUS_NTHAL CbusBackend;
+
+BOOLEAN
+CbusMPMachine(VOID)
+/*++
+
+ Routine Description:
+
+ recognize which type of C-bus multiprocessor system it is:
+
+ C-bus I Symmetric XM
+ C-bus II:
+
+ Use CbusGlobal to determine which type of machine this is.
+ note the ordering of the platform recognition is important for future
+ expansion.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if this Corollary MP machine is supported by this MP HAL.
+ FALSE if not.
+
+--*/
+{
+ ULONG machine;
+
+ machine = CbusGlobal.machine_type;
+
+ if (machine & MACHINE_CBUS2) {
+
+ if ((CbusGlobal.supported_environments & WINDOWS_NT_R2) == 0)
+ return FALSE;
+
+ CbusBackend = &cbus2_nthal;
+ return TRUE;
+ }
+
+ if (machine & MACHINE_CBUS1_XM) {
+
+ if ((CbusGlobal.supported_environments & (WINDOWS_NT|WINDOWS_NT_R2)) == 0)
+ return FALSE;
+
+ CbusBackend = &cbus1_nthal;
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbusapic.asm b/private/ntos/nthals/halcbus/i386/cbusapic.asm
new file mode 100644
index 000000000..c71a43b68
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusapic.asm
@@ -0,0 +1,715 @@
+ title "Software Interrupts"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+;Module Name:
+;
+; cbusapic.asm
+;
+;Abstract:
+;
+; This module implements the low-level Corollary Cbus HAL routines to deal
+; with the Intel APIC distributed interrupt controller.
+;
+; This includes the_sending_ of software and IPI interrupts in Windows NT.
+; The receipt of these interrupts is handled elsewhere.
+;
+; Note: The routines in this module are jmp'ed to directly from
+; their common Hal counterparts.
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include cbus.inc
+
+ EXTRNP _CbusApicRedirectionInterrupt,0
+
+;
+; APIC register offsets...
+;
+APIC_IRR_OFFSET equ 0100h ; offset of APIC IRR registers
+APIC_APC_IRR equ 0103h ; offset of APIC APC IRR register
+APIC_DPC_IRR equ 0105h ; offset of APIC DPC IRR register
+APIC_ICR_OFFSET equ 0300h ; offset of APIC intr cmd register
+APIC_ICR_DEST_OFFSET equ 0310h ; offset of APIC intr cmd dest register
+
+;
+; APIC register bitfield definitions...
+;
+APIC_DEASSERT_RESET equ 000500h ; sending a DEASSERT-RESET command
+APIC_LOGICAL_MODE equ 000800h ; sending an APIC-LOGICAL interrupt
+APIC_ICR_BUSY equ 001000h ; APIC intr command reg is busy
+APIC_TRIGGER_LEVEL equ 008000h ; generate a level interrupt
+APIC_INTR_DISABLED equ 010000h ; disable this redirection entry
+APIC_SELFINTR equ 040000h ; APIC's self-interrupt code
+APIC_ALLINCLSELF equ 080000h ; sending a DEASSERT-RESET command
+
+APIC_FULL_DRESET equ (APIC_ALLINCLSELF or APIC_TRIGGER_LEVEL or APIC_LOGICAL_MODE or APIC_DEASSERT_RESET)
+
+;
+; the IOAPIC_REGISTERS_T register access template...
+;
+RegisterSelect equ 0h ; this APIC's register select
+WindowRegister equ 010h ; this APIC's window register
+
+;
+; left shift needed to convert processor_bit to Intel APIC ID - this applies
+; to the logical destination ID and redirection entry registers only.
+;
+APIC_BIT_TO_ID equ 24 ; also in cbus1.h
+
+;
+; macro to wait for the delivery status register to become idle
+;
+APIC_WAIT macro apicreg
+ local a
+
+ align 4
+a:
+ test dword ptr [apicreg + APIC_ICR_OFFSET], APIC_ICR_BUSY
+ jnz short a
+
+endm
+
+IOAPIC_READ macro ioapic, offset, answer
+ ;
+ ; 'ioapic' must point at the I/O APIC
+ ; 'offset' is the offset to peek
+ ; 'answer' is the peeked return value
+ ;
+ mov dword ptr RegisterSelect[ioapic], offset
+
+ mov answer, dword ptr WindowRegister[ioapic]
+endm
+
+
+IOAPIC_WRITE macro ioapic, offset, value
+ ;
+ ; 'ioapic' must point at the I/O APIC
+ ; 'offset' is the offset to poke
+ ; 'value' is the value to poke
+ ;
+ mov dword ptr RegisterSelect[ioapic], offset
+
+ mov dword ptr WindowRegister[ioapic], value
+endm
+
+ .list
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; CbusApicArbsync ( VOID )
+;
+; Routine Description:
+;
+; Broadcast an ALL-INCLUDING-SELF interrupt with deassert, reset &
+; physical mode set. This routine is called after each APIC assigns
+; itself a unique ID that can be used in APIC bus arbitration and
+; priority arbitration. This syncs up the picture that each APIC
+; has with the new ID that has just been added.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _CbusApicArbsync ,0
+
+ ; get the base of APIC space, so we can then access
+ ; the addr of hardware interrupt command register below
+
+ mov ecx, [_CbusLocalApic]
+
+ ;
+ ; disable interrupts so that polling the register and
+ ; poking it becomes an atomic operation (for this processor),
+ ; as specified in the Intel 82489DX specification.
+ ; this is needed since interrupt service routines must
+ ; be allowed to send IPIs (for example, DPCs, etc).
+ ;
+
+ pushfd
+ cli
+
+ ; wait for the delivery status register to become idle
+
+ APIC_WAIT ecx
+
+ ;
+ ; it is ILLEGAL to use the "destination shorthand" mode of the APIC
+ ; for this command - we must set up the whole 64 bit register).
+ ; both destination and vector are DONT_CARE for this request.
+ ;
+ ; no recipients (probably a don't care), but must be written
+ ; _before_ the command is sent...
+
+ mov dword ptr [ecx + APIC_ICR_DEST_OFFSET], 0
+
+ ;
+ ; now we can send the full deassert-reset command
+ ;
+
+ mov dword ptr [ecx + APIC_ICR_OFFSET], APIC_FULL_DRESET
+
+ popfd
+
+ stdRET _CbusApicArbsync
+stdENDP _CbusApicArbsync
+
+INIT ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; CbusRequestApicSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to issue a software interrupt to the
+; calling processor. Since this is all done in hardware, the
+; code to implement this is trivial. Our hardware supports
+; sending the interrupt to lowest-in-group processors, which
+; would be useful for a good number of DPCs, for example, but
+; the kernel doesn't currently tell us which kinds of software
+; interrupts need to go to the caller versus which can go to
+; any processor.
+;
+; Arguments:
+;
+; (esp+4) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+;
+; equates for accessing arguments
+;
+
+KsiRequestIrql equ byte ptr [esp+4]
+;
+
+cPublicProc _CbusRequestApicSoftwareInterrupt ,1
+
+ xor ecx, ecx ; faster than movzx
+ mov cl, KsiRequestIrql ; to get irql
+
+ ;
+ ; disable interrupts so that polling the register and
+ ; poking it becomes an atomic operation (for this processor),
+ ; as specified in the Intel 82489DX specification.
+ ; this is needed since interrupt service routines must
+ ; be allowed to send IPIs (for example, DPCs, etc).
+ ;
+
+ pushfd
+ cli
+
+ ;
+ ; notice the CbusIrqlToVector[] indexing below -- it means
+ ; that only pre-defined software interrupts can be sent,
+ ; NOT any "int xx" command on demand.
+ ;
+ mov eax, [_CbusIrqlToVector+4*ecx] ; get vector to issue
+
+ ;
+ ; if this function is ever changed so that we are
+ ; allowed to interrupt a different processor than
+ ; the caller, we will not be able to use the APIC
+ ; shorthand method below to address them, and we will
+ ; have to change the selfintr mode we use to issue.
+ ; HalRequestApicIpi() already does these types of things, btw.
+ ;
+
+ or eax, APIC_SELFINTR
+
+ ; get the base of APIC space, so we can then access
+ ; the addr of hardware interrupt command register below
+
+ mov ecx, [_CbusLocalApic]
+
+ ; wait for the delivery status register to become idle
+
+ APIC_WAIT ecx
+
+ ;
+ ; since we are just interrupting ourself, we can use
+ ; the "destination shorthand" mode of the APIC and
+ ; just set up the single 32-bit write, instead of doing
+ ; the whole 64 bit register). So,
+ ;
+ ; the APIC icr.destination = DONT_CARE
+ ; the APIC icr.vector = IPI_TASKPRI
+ ; the APIC icr.destination_shorthand = 01 (SELF);
+ ;
+
+ mov [ecx + APIC_ICR_OFFSET], eax
+
+ ;
+ ; The interrupt must be pending before returning
+ ; wait for the delivery status register to become idle.
+ ; the delivery status register being idle just means that
+ ; this local APIC has sent the interrupt message out on the
+ ; APIC bus (it has to do this even for self interrupts!).
+ ;
+ ; but waiting for delivery status to be idle is NOT ENOUGH !!!
+ ; you must also wait for the IRR bit to be set. this means
+ ; this APIC's local unit has accepted the interrupt and the
+ ; CPU has not yet sent the APIC an EOI.
+ ;
+
+ APIC_WAIT ecx
+
+ popfd
+
+ stdRET _CbusRequestApicSoftwareInterrupt
+
+stdENDP _CbusRequestApicSoftwareInterrupt
+
+
+ page ,132
+ subttl "CbusRequestApicIpi"
+;++
+;
+; VOID
+; CbusRequestApicIpi(
+; IN ULONG Mask
+; );
+;
+; Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+; for Windows NT, we use full distributed
+; interrupt capability, and, thus, we will IGNORE the sswi address
+; that RRD passes us and prioritize IPI as we see fit, given the
+; other devices configured into the system.
+;
+; Arguments:
+;
+; Mask - Mask of processors to be interrupted
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _CbusRequestApicIpi ,1
+ mov eax, [_CbusIpiVector]
+
+ mov edx, [esp+4] ; get requested recipients
+
+ ;
+ ; translate logical processor mask into the high byte of edx,
+ ; since this is the only portion of the logical destination register
+ ; that future APICs will use to compare with.
+ ;
+ shl edx, APIC_BIT_TO_ID
+
+ ; get the base of APIC space, so we can then access
+ ; the addr of hardware interrupt command register below
+
+ mov ecx, [_CbusLocalApic]
+
+ ;
+ ; disable interrupts so that polling the register and
+ ; poking it becomes an atomic operation (for this processor),
+ ; as specified in the Intel 82489DX specification.
+ ; this is needed since interrupt service routines must
+ ; be allowed to send IPIs (for example, DPCs, etc).
+ ;
+
+ pushfd
+ cli
+
+ ; wait for the delivery status register to become idle
+
+ APIC_WAIT ecx
+
+ ; use APIC logical mode to pop randomly-specified sets of processors
+ ; we cannot use "destination shorthand" mode for this;
+ ; we must write the whole 64 bit register. ie:
+ ;
+ ; The APIC icr.destination = processor_mask
+ ; The APIC icr.vector = IPI_TASKPRI
+ ; The APIC icr.destination_mode = 1 (LOGICAL);
+ ;
+ ; all other fields are zero.
+ ;
+ ; note that the high 32 bits of the interrupt command
+ ; register must be written _BEFORE_ the low 32 bits.
+ ;
+
+ ; specify the CPUs...
+ mov [ecx + APIC_ICR_DEST_OFFSET], edx
+
+ ; send the command...
+ or eax, APIC_LOGICAL_MODE ; set up mode & vector
+ mov dword ptr [ecx + APIC_ICR_OFFSET], eax
+
+ popfd
+
+ stdRET _CbusRequestApicIpi
+stdENDP _CbusRequestApicIpi
+
+
+;++
+;
+; ULONG
+; READ_IOAPIC_ULONG(
+; ULONG ApicNumber,
+; PULONG Port
+; )
+;
+; Routine Description:
+;
+; Read the specified offset of the specified I/O APIC.
+;
+;
+; Arguments:
+; (esp+4) = Logical Apic Number
+; (esp+8) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_IOAPIC_ULONG ,2
+
+ mov ecx, [esp + 4] ; Apic number to access
+ mov eax, [_CbusIOApic+4*ecx] ; point at the I/O APIC
+ mov edx, [esp + 8] ; offset to peek
+
+ IOAPIC_READ eax, edx, eax
+
+ stdRET _READ_IOAPIC_ULONG
+stdENDP _READ_IOAPIC_ULONG
+
+
+;++
+;
+; VOID
+; WRITE_IOAPIC_ULONG(
+; ULONG ApicNumber,
+; PULONG Port,
+; ULONG Value
+; )
+;
+; Routine Description:
+;
+; Write the specified offset with the specified value into
+; the calling processor's I/O APIC.
+;
+; Arguments:
+; (esp+4) = Logical Apic Number
+; (esp+8) = Port
+; (esp+c) = Value
+;
+;--
+cPublicProc _WRITE_IOAPIC_ULONG ,3
+
+ mov ecx, [esp + 4] ; Apic number to access
+ mov eax, [_CbusIOApic+4*ecx] ; point at the I/O APIC
+ mov edx, [esp + 8] ; offset to poke
+ mov ecx, [esp + 0ch] ; value for the poke
+
+ IOAPIC_WRITE eax, edx, ecx
+
+ stdRET _WRITE_IOAPIC_ULONG
+stdENDP _WRITE_IOAPIC_ULONG
+
+
+ page ,132
+ subttl "I/O APIC Update Interrupt"
+;++
+;
+; VOID
+; IOApicUpdate(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for an IPI interrupt generated
+; at a priority just below that of normal IPIs. Its function is to
+; poke the I/O APIC with the new masks that have been requested so
+; that an interrupt can be accepted or ignored on a given processor.
+;
+; The priorities of this and CbusAllocateVector() have been carefully
+; chosen so as to avoid deadlock.
+;
+; This routine is needed because each I/O APIC is only addressable from
+; its local CPU.
+;
+; since this routine is entered directly via an interrupt gate, interrupt
+; protection via cli is not necessary.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hiui_a, hiui_t
+
+cPublicProc _IOApicUpdate ,0
+
+ ;
+ ; Save machine state on trap frame
+ ;
+
+ ENTER_INTERRUPT hiui_a, hiui_t
+
+ ; keep it simple, just issue the EOI right now.
+ ; no changing of taskpri/irql is needed here.
+ ; Thus, the EOI serves as the HalEndSystemInterrupt.
+
+ mov eax, _CbusRedirVector
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ stdCall _CbusApicRedirectionInterrupt
+
+ ;
+ ; Call this directly instead of through INTERRUPT_EXIT
+ ; because the HalEndSystemInterrupt has already been done,
+ ; and must only be done ONCE per interrupt.
+ ;
+
+ cli
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _IOApicUpdate
+
+
+ page ,132
+ subttl "CbusApicRedirectionRequest"
+;++
+;
+; VOID
+; CbusApicRedirectionRequest(IN OUT PULONG spinaddress)
+; );
+;
+; Routine Description:
+;
+; Requests an interprocessor interrupt, at the HAL private CBUS1_REDIR_IPI
+; priority. this must be higher than any device priority to prevent
+; deadlocks. this routine always interrupts the processor that can
+; access the I/O unit of the APIC distributing the interrupts amongst
+; all the processors. we have currently wired that up to the boot
+; processor for Cbus1.
+;
+; the boot processor will receive the interrupt in the IOApicUpdate()
+; routine above.
+;
+; Arguments:
+;
+; spinaddress - the caller will spin until the dword pointed to by
+; this variable becomes zero. this insures that the
+; processor controlling the APIC has actually satisfied
+; our request.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _CbusApicRedirectionRequest ,1
+
+ ;
+ ; set the vector we're going to send
+ ;
+ mov edx, [_CbusRedirVector]
+
+ ; get the base of APIC space, so we can then access
+ ; the addr of hardware interrupt command register below
+
+ mov ecx, [_CbusLocalApic]
+
+ ; create the boot CPU ( 1 << 24) APIC ID in a portable manner...
+
+ mov eax, 1
+ shl eax, APIC_BIT_TO_ID
+
+ ;
+ ; disable interrupts so that polling the register and
+ ; poking it becomes an atomic operation (for this processor),
+ ; as specified in the Intel 82489DX specification.
+ ; this is needed since interrupt service routines must
+ ; be allowed to send IPIs (for example, DPCs, etc).
+ ;
+
+ pushfd
+ cli
+
+ ; wait for the delivery status register to become idle
+
+ APIC_WAIT ecx
+
+ ; can't use "destination shorthand" mode for this -
+ ; must write the whole 64 bit register. ie:
+ ;
+ ; The APIC icr.destination = processor_mask
+ ; The APIC icr.vector = IPI_TASKPRI
+ ; The APIC icr.destination_mode = 1 (LOGICAL);
+ ;
+ ; all other fields are zero.
+ ;
+ ; note that the destination word of the interrupt command
+ ; register must be written _BEFORE_ the command word.
+ ;
+
+ mov [ecx + APIC_ICR_DEST_OFFSET], eax
+
+ or edx, APIC_LOGICAL_MODE ; set up mode & vector
+
+ ; send the command...
+ mov dword ptr [ecx + APIC_ICR_OFFSET], edx
+
+ ; now wait for the processor controlling the APIC to finish our request
+ ; do this in assembly so the compiler won't optimize this incorrectly
+
+ mov eax, [esp+8] ; remember we pushed flags
+
+ align 4
+@@:
+ cmp dword ptr [eax], 0
+ jne @b
+
+ popfd
+
+ stdRET _CbusApicRedirectionRequest
+stdENDP _CbusApicRedirectionRequest
+
+ page ,132
+ subttl "Cbus1RebootRequest"
+;++
+;
+; VOID
+; Cbus1RebootRequest(IN ULONG Processor);
+;
+; Routine Description:
+;
+;
+; Arguments:
+;
+; Requests an interprocessor interrupt, at the HAL private CbusRebootVector.
+; This interrupt is always sent to the non-boot processors.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _Cbus1RebootRequest ,1
+ mov edx, 1
+ mov ecx, [_CbusProcessors] ; set mask for all processors
+ shl edx, cl
+ sub edx, 1
+
+ mov eax, 1
+ mov ecx, [esp+8] ; get the requesting processor
+ shl eax, cl
+ not eax
+ and edx, eax
+
+ mov eax, [_CbusRebootVector]
+
+ cmp edx, 0 ; check for uniprocessor case
+ je no_ipi_needed
+
+ ;
+ ; translate logical processor mask into the high byte of edx,
+ ; since this is the only portion of the logical destination register
+ ; that future APICs will use to compare with.
+ ;
+ shl edx, APIC_BIT_TO_ID
+
+ ; get the base of APIC space, so we can then access
+ ; the addr of hardware interrupt command register below
+
+ mov ecx, [_CbusLocalApic]
+
+ ;
+ ; disable interrupts so that polling the register and
+ ; poking it becomes an atomic operation (for this processor),
+ ; as specified in the Intel 82489DX specification.
+ ; this is needed since interrupt service routines must
+ ; be allowed to send IPIs (for example, DPCs, etc).
+ ;
+
+ pushfd
+ cli
+
+ ; wait for the delivery status register to become idle
+
+ APIC_WAIT ecx
+
+ ; use APIC logical mode to pop randomly-specified sets of processors
+ ; we cannot use "destination shorthand" mode for this;
+ ; we must write the whole 64 bit register. ie:
+ ;
+ ; The APIC icr.destination = processor_mask
+ ; The APIC icr.vector = IPI_TASKPRI
+ ; The APIC icr.destination_mode = 1 (LOGICAL);
+ ;
+ ; all other fields are zero.
+ ;
+ ; note that the high 32 bits of the interrupt command
+ ; register must be written _BEFORE_ the low 32 bits.
+ ;
+
+ ; specify the CPUs...
+ mov [ecx + APIC_ICR_DEST_OFFSET], edx
+
+ ; send the command...
+ or eax, APIC_LOGICAL_MODE ; set up mode & vector
+ mov dword ptr [ecx + APIC_ICR_OFFSET], eax
+
+ popfd
+
+no_ipi_needed:
+
+ stdRET _Cbus1RebootRequest
+stdENDP _Cbus1RebootRequest
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halcbus/i386/cbusapic.h b/private/ntos/nthals/halcbus/i386/cbusapic.h
new file mode 100644
index 000000000..ad3677e10
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusapic.h
@@ -0,0 +1,256 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbusapic.h
+
+Abstract:
+
+ Cbus APIC architecture definitions for the Corollary Cbus1
+ and Cbus2 multiprocessor HAL modules.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 05-Oct-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _CBUSAPIC_
+#define _CBUSAPIC_
+
+//
+//
+// THE APIC HARDWARE ARCHITECTURE DEFINITIONS
+//
+//
+
+#define LOCAL_APIC_ENABLE 0x100 // all APIC intrs now enabled
+
+#define APIC_INTR_UNMASKED 0x0 // this interrupt now enabled
+#define APIC_INTR_MASKED 0x1 // this interrupt now disabled
+
+#define APIC_INTR_FIXED 0x0 // this interrupt is tied to a CPU
+#define APIC_INTR_LIG 0x1 // this interrupt is lowest-in-group
+#define APIC_INTR_NMI 0x4 // this interrupt is an NMI
+
+#define APIC_EDGE 0x0 // this interrupt is edge-triggered
+#define APIC_LEVEL 0x1 // this interrupt is level-triggered
+#define APIC_LOGICAL_MODE 0x1 // only logical mode is being used
+
+#define APIC_ALL_PROCESSORS (ULONG)-1 // Destination format reg default
+
+//
+// left shift needed to convert processor_bit to Intel APIC ID.
+// this applies to the:
+//
+// I/O unit ID register
+// I/O unit ID redirection entry destination registers
+// local unit ID register
+// local unit logical destination register
+//
+
+#define APIC_BIT_TO_ID 24 // also in cbusapic.asm
+
+//
+// both LOCAL and I/O APICs must be on page-aligned boundaries
+// for the current HalpMapPhysicalMemory() calls to work.
+//
+
+//
+// The physical address of the local and I/O APICs are architecture
+// dependent, and therefore reside in cbus1.h & cbus2.h. The size
+// of the APIC is not architecture dependent, and thus is declared here.
+//
+
+#define LOCAL_APIC_SIZE 0x400
+#define IO_APIC_SIZE 0x11
+
+//
+// I/O APIC registers. note only register select & window register are
+// directly accessible in the address space. other I/O registers are
+// reached via these two registers, similar to the CMOS access method.
+//
+#define IO_APIC_REGSEL 0x00
+#define IO_APIC_WINREG 0x10
+
+#define IO_APIC_ID_OFFSET 0x00
+#define IO_APIC_VERSION 0x01
+#define IO_APIC_REDIRLO 0x10
+#define IO_APIC_REDIRHI 0x11
+
+//
+// Each I/O APIC has one redirection entry for each interrupt it handles.
+// note that since it is not directly accessible (instead the window register
+// must be used), consecutive entries are byte aligned, not 16 byte aligned.
+//
+typedef union _redirection_t {
+ struct {
+ ULONG Vector : 8;
+ ULONG Delivery_mode : 3;
+ ULONG Dest_mode : 1;
+ ULONG Delivery_status : 1; // read-only
+ ULONG Reserved0 : 1;
+ ULONG Remote_irr : 1;
+ ULONG Trigger : 1;
+ ULONG Mask : 1;
+ ULONG Reserved1 : 15;
+ ULONG Destination;
+ } ra;
+ struct {
+ ULONG dword1;
+ ULONG dword2;
+ } rb;
+} REDIRECTION_T;
+
+//
+// The Interrupt Command register format is used for IPIs, and is
+// here purely for reference. It is actually only used by cbusapic.asm,
+// which has its internal (identical) conception of this register.
+// No C code references this structure.
+//
+typedef struct _intrcommand_t {
+ ULONG vector : 8;
+ ULONG delivery_mode : 3;
+ ULONG dest_mode : 1;
+ ULONG delivery_status : 1; // read-only
+ ULONG reserved0 : 1;
+ ULONG level : 1;
+ ULONG trigger : 1;
+ ULONG remote_read_status : 2;
+ ULONG destination_shorthand : 2;
+ ULONG reserved1 : 12;
+ ULONG pad[3];
+ ULONG destination;
+} INTRCOMMAND_T, *PINTRCOMMAND;
+
+typedef struct _apic_registers_t {
+ UCHAR fill0[0x20];
+
+ ULONG LocalUnitID; // 0x20
+ UCHAR fill1[0x80 - 0x20 - sizeof(ULONG)];
+
+ TASKPRI_T ApicTaskPriority; // 0x80
+ UCHAR fill2[0xB0 - 0x80 - sizeof(TASKPRI_T)];
+
+ ULONG ApicEOI; // 0xB0
+ UCHAR fill3[0xD0 - 0xB0 - sizeof(ULONG)];
+
+ ULONG ApicLogicalDestination; // 0xD0
+ UCHAR fill4[0xE0 - 0xD0 - sizeof(ULONG)];
+
+ ULONG ApicDestinationFormat; // 0xE0
+ UCHAR fill5[0xF0 - 0xE0 - sizeof(ULONG)];
+
+ ULONG ApicSpuriousVector; // 0xF0
+ UCHAR fill6[0x300 - 0xF0 - sizeof(ULONG)];
+
+ INTRCOMMAND_T ApicICR; // 0x300
+ UCHAR fill7[0x360 - 0x300 - sizeof(INTRCOMMAND_T)];
+
+ REDIRECTION_T ApicLocalInt1; // 0x360
+ UCHAR fill8[0x4D0 - 0x360 - sizeof(REDIRECTION_T)];
+
+ //
+ // Note that APMode is also the PolarityPortLow register
+ //
+ UCHAR APMode; // 0x4D0
+ UCHAR PolarityPortHigh; // 0x4D1
+
+} APIC_REGISTERS_T, *PAPIC_REGISTERS;
+
+#define LOWEST_APIC_PRI 0x00
+#define LOWEST_APIC_DEVICE_PRI 0x40
+#define HIGHEST_APIC_PRI 0xF0
+
+//
+//
+// PURE SOFTWARE DEFINITIONS HERE
+//
+//
+
+//
+// this structure is used for communications between processors
+// when modifying the I/O APIC.
+//
+typedef struct _redirport_t {
+ ULONG Status;
+ ULONG ApicID;
+ ULONG BusNumber;
+ ULONG RedirectionAddress;
+ ULONG RedirectionCommand;
+ ULONG RedirectionDestination;
+} REDIR_PORT_T, *PREDIR_PORT_T;
+
+#define REDIR_ACTIVE_REQUEST 0x01
+#define REDIR_ENABLE_REQUEST 0x02
+#define REDIR_DISABLE_REQUEST 0x04
+#define REDIR_LASTDETACH_REQUEST 0x08
+#define REDIR_FIRSTATTACH_REQUEST 0x10
+
+
+//
+// declare APIC-related external functions
+//
+
+
+VOID
+CbusInitializeLocalApic(
+IN ULONG Processor,
+IN PVOID PhysicalApicLocation,
+IN ULONG SpuriousVector
+);
+
+
+VOID
+CbusInitializeIOApic(
+IN ULONG Processor,
+IN PVOID PhysicalApicLocation,
+IN ULONG RedirVector,
+IN ULONG RebootVector,
+IN ULONG IrqPolarity
+);
+
+VOID
+CbusEnableApicInterrupt(
+IN ULONG ApicBusNumber,
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG FirstAttach,
+IN BOOLEAN LowestInGroup,
+IN BOOLEAN LevelTriggered
+);
+
+VOID
+CbusDisableApicInterrupt(
+IN ULONG ApicBusNumber,
+IN ULONG Vector,
+IN PVOID HardwarePtr,
+IN ULONG LastDetach
+);
+
+PVOID
+CbusApicLinkVector(
+IN PBUS_HANDLER Bus,
+IN ULONG Vector,
+IN ULONG Irqline
+);
+
+VOID
+CbusApicBrandIOUnitID(
+IN ULONG Processor
+);
+
+//
+// end of APIC-related external function declarations
+//
+
+
+#endif // _CBUSAPIC_
diff --git a/private/ntos/nthals/halcbus/i386/cbusboot.asm b/private/ntos/nthals/halcbus/i386/cbusboot.asm
new file mode 100644
index 000000000..3e0770eef
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusboot.asm
@@ -0,0 +1,362 @@
+ title "MP primitives for the Corollary Cbus machines"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; cbusboot.asm
+;
+;Abstract:
+;
+; Corollary Start Next Processor assembly code
+;
+; This module along implements the code to start
+; off the additional processors in the Corollary machines.
+;
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+;Environment:
+; Kernel mode.
+;
+;
+;Revision History:
+;
+; Landy Wang (landy@corollary.com) 20-Oct-1992
+;
+; - slight modification to boot Corollary-architecture processors
+; to allow booting multiple hardware platforms
+;
+; - preserve interrupt state in eflags whilst booting other processors
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include cbus.inc
+
+ .list
+
+WarmResetVector equ 467h ; warm reset vector in ROM data segment
+
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_PB db ProcessorStateLength dup (?)
+PxParamBlock ends
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+
+
+cPublicProc _HalStartNextProcessor ,2
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.SPx_flag, eax
+
+ cmp _MpCount, eax
+ jbe snp_exit ; exit FALSE
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+ mov edi, _MpLowStub ; Copy RMStub to low memory
+ add edi, size PxParamBlock
+ rep movsb
+
+ lea edi, PxFrame.SPx_PB
+ mov esi, pProcessorState
+ mov ecx, ProcessorStateLength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+ stdCall _HalpBuildTiledCR3, <pProcessorState>
+
+ mov PxFrame.SPx_TiledCR3, eax
+ mov PxFrame.SPx_P0EBP, ebp
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _MpLowStub
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx ; patch realmode stub with
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
+
+ mov ebx, _MppIDT
+ add ebx, WarmResetVector
+
+ pushfd ; must preserve flags
+ cli
+ push dword ptr [ebx] ; Save current vector
+
+ mov edx, _MpLowStubPhysicalAddress
+ shl edx, 12 ; seg:0
+ add edx, size PxParamBlock
+ mov dword ptr [ebx], edx ; start Px here
+
+ mov ecx, pLoaderBlock ; lookup processor # we are
+ mov ecx, [ecx].LpbPrcb ; starting
+ movzx ecx, byte ptr [ecx].PbNumber
+
+ push edx ; start address (seg:off)
+ push ecx ; processor number
+
+ mov eax, _CbusBackend ; use hardware handler
+ call HalBootCPU[ eax ] ; to boot specified processor
+ ; callee pops the args
+
+ align 4
+Hsnp002:
+@@:
+ cmp PxFrame.SPx_flag, 0 ; wait for Px to get its
+ jz @b ; info
+
+ pop dword ptr [ebx] ; restore WarmResetVector
+ popfd ; must restore flags
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+
+ dec _MpCount ; one less
+ mov eax, 1 ; return TRUE
+
+snp_exit:
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ stdRET _HalStartNextProcessor
+
+stdENDP _HalStartNextProcessor
+
+
+_TEXT ends ; end 32 bit code
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1MB and accessible from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub ,0
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+stdENDP StartPx_RMStub
+
+
+_TEXT16 ends ; End 16 bit code
+
+_TEXT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+ align 16 ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+cPublicProc _StartPx_PMStub ,0
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+
+ ltr word ptr ds:[esi].SrTr ; load tss
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+
+ mov fs, word ptr ds:[edi].CsSegFs
+
+ mov gs, word ptr ds:[edi].CsSegGs
+
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with it's data
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ stdRET _StartPx_PMStub ; Set eip
+
+stdENDP _StartPx_PMStub
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbushal.c b/private/ntos/nthals/halcbus/i386/cbushal.c
new file mode 100644
index 000000000..c4e992ec5
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbushal.c
@@ -0,0 +1,482 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ cbushal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992:
+
+ - slight modifications for Corollary's symmetric interrupt enabling
+
+--*/
+
+#include "halp.h"
+#include "cbus_nt.h" // pick up APC_TASKPRI definition
+
+VOID
+HalpInitializeCoreIntrs(VOID);
+
+PUCHAR
+CbusFindString (
+IN PUCHAR Str,
+IN PUCHAR StartAddr,
+IN LONG Len
+);
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+CbusGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, HalpInitializeCoreIntrs)
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, CbusGetParameters)
+#endif
+
+ULONG HalpBusType;
+
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+
+ULONG
+CbusStringLength (
+IN PUCHAR Str
+);
+
+VOID
+HalpInitBusHandlers (VOID);
+
+VOID
+HalpInitOtherBuses (VOID);
+
+ULONG
+HalpInitMP(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpDispatchInterrupt( VOID );
+
+VOID
+HalpApcInterrupt( VOID );
+
+VOID
+HalpIpiHandler( VOID );
+
+VOID
+HalpInitializeTimeIncrement( VOID );
+
+VOID
+HalpRegisterInternalBusHandlers( VOID );
+
+extern ULONG CbusIpiVector;
+
+KSPIN_LOCK HalpSystemHardwareLock;
+
+
+/*++
+
+Routine Description:
+
+ This function initializes the HAL-specific "software" (APC, DPC)
+ and hardware (IPI, spurious) interrupts for the Corollary architectures.
+
+Arguments:
+
+ none.
+
+Return Value:
+
+ VOID
+
+--*/
+
+VOID
+HalpInitializeCoreIntrs(VOID
+)
+{
+ //
+ // Here we initialize all the core interrupts that need to
+ // work EARLY on in kernel startup. Device interrupts are
+ // not enabled until later (in HalInitSystem).
+ //
+ // Each processor needs to call KiSetHandlerAddressToIDT()
+ // and HalEnableSystemInterrupt() for himself. This is done
+ // as a by-product of the HAL IDT registration scheme.
+ //
+ // Even though race conditions can exist between processors as
+ // there is no interlocking when calling HalpRegisterVector()
+ // from HalpEnabledInterruptHandler(), this is not harmful in
+ // this particular case, as all processors will be writing the
+ // exact same values.
+ //
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ DPC_TASKPRI, // No real IRQ, so use this
+ DPC_TASKPRI, // System IDT
+ DISPATCH_LEVEL, // System Irql
+ HalpDispatchInterrupt, // ISR
+ Latched );
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ APC_TASKPRI, // No real IRQ, so use this
+ APC_TASKPRI, // System IDT
+ APC_LEVEL, // System Irql
+ HalpApcInterrupt, // ISR
+ Latched );
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Mark as device vector
+ CbusIpiVector, // No real IRQ, so use this
+ CbusIpiVector, // System IDT
+ IPI_LEVEL, // System Irql
+ HalpIpiHandler, // ISR
+ Latched );
+}
+
+
+BOOLEAN
+CbusGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This gets any parameters from the boot.ini invocation line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if initial breakpoint was requested, FALSE otherwise
+
+--*/
+{
+ PUCHAR Options;
+ ULONG OptionLength;
+ BOOLEAN InitialBreak = FALSE;
+ UCHAR IsBreak[] = "BREAK";
+
+ if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
+ Options = (PUCHAR)LoaderBlock->LoadOptions;
+ //
+ // Uppercase Only
+ //
+
+ //
+ // The number of processors to boot can be specified dynamically
+ // with the /NUMPROC=n, and this will be parsed by the Executive.
+ // so we don't need to bother with it here.
+ //
+
+ //
+ // Has the user asked for an initial BreakPoint (ie: /BREAK) ?
+ //
+
+ OptionLength = CbusStringLength (Options);
+ if (CbusFindString(IsBreak, Options, OptionLength))
+ InitialBreak = TRUE;
+ }
+ return InitialBreak;
+}
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ KIRQL CurrentIrql;
+ extern VOID HalpAddMem(IN PLOADER_PARAMETER_BLOCK);
+ PKPRCB pPRCB;
+ ULONG BuildType;
+
+ pPRCB = KeGetCurrentPrcb();
+
+ if (Phase == 0) {
+
+ if (CbusGetParameters (LoaderBlock)) {
+ DbgBreakPoint();
+ }
+
+ HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
+
+ //
+ // Verify Prcb version and build flags conform to
+ // this image
+ //
+
+ BuildType = 0;
+#if DBG
+ BuildType |= PRCB_BUILD_DEBUG;
+#endif
+#ifdef NT_UP
+ BuildType |= PRCB_BUILD_UNIPROCESSOR;
+#endif
+
+ if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ if (pPRCB->BuildType != BuildType) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 2, pPRCB->BuildType, BuildType, 0);
+ }
+
+ //
+ // Phase 0 initialization
+ // only called by P0
+ //
+
+ //
+ // Check to make sure the MCA HAL is not running on an ISA/EISA
+ // system, and vice-versa.
+ //
+#if MCA
+ if (HalpBusType != MACHINE_TYPE_MCA) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 3, HalpBusType, MACHINE_TYPE_MCA, 0);
+ }
+#else
+ if (HalpBusType == MACHINE_TYPE_MCA) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 3, HalpBusType, 0, 0);
+ }
+#endif
+
+ //
+ // Most HALs initialize their PICs at this point - we set up
+ // the Cbus PICs in HalInitializeProcessor() long ago...
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ KfRaiseIrql(CurrentIrql);
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Initialize CMOS
+ //
+
+ HalpInitializeCmos();
+
+
+ //
+ // Register the PC-compatible base IO space used by hal
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ }
+
+ //
+ // Cbus1: stall uses the APIC to figure it out (needed in phase0).
+ // the clock uses the APIC (needed in phase0)
+ // the perfcounter uses RTC irq8 (not needed till all cpus boot)
+ //
+ // Cbus2: stall uses the RTC irq8 to figure it out (needed in phase0).
+ // the clock uses the irq0 (needed in phase0)
+ // the perfcounter uses RTC irq8 (not needed till all cpus boot)
+ //
+ //
+ // set up the stall execution and enable clock interrupts now.
+ // APC, DPC and IPI are already enabled.
+ //
+
+ (*CbusBackend->HalInitializeInterrupts)(0);
+
+ HalStopProfileInterrupt(0);
+
+ HalpInitializeDisplay();
+
+ //
+ // Initialize spinlock used by HalGetBusData hardware access routines
+ //
+
+ KeInitializeSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Any additional memory must be recovered BEFORE Phase0 ends
+ //
+ HalpAddMem(LoaderBlock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+ // This should probably create a memory descriptor which describes
+ // the DMA map buffers reserved by the HAL, and then add it back in
+ // to the LoaderBlock so the kernel can report the correct amount
+ // of memory in the machine.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ } else {
+
+ //
+ // Phase 1 initialization - run by all processors eventually,
+ // however processor 0 runs here to completion _BEFORE_ any
+ // other processors have been brought out of reset.
+ //
+ PKPCR pPCR = KeGetPcr();
+
+ //
+ // each processor sets up his own global vectors.
+ // we do this here for hardware device interrupts, and
+ // enable IPI & SW interrupts from HalInitializeProcessor.
+ //
+ // Note that for Cbus1, InitializeClock MUST be called after
+ // HalpInitializeStallExecution, because HalpInitializeStallExecution
+ // reprograms the timer.
+ //
+ // The boot processor has already done all this as part of Phase 0,
+ // but each additional processor is responsible for setting up his
+ // own hardware, so the additional processors each do it here...
+ //
+
+ if (pPCR->Prcb->Number == 0) {
+
+ HalpRegisterInternalBusHandlers ();
+
+ HalpInitOtherBuses ();
+ }
+ else {
+
+ (*CbusBackend->HalInitializeInterrupts)(pPCR->Prcb->Number);
+ }
+
+ //
+ // No need to enable irq13 for FP errors - all the Corollary
+ // architectures are 486 and above, so we will route FP errors
+ // through trap 0x10.
+ //
+
+ }
+
+ HalpInitMP (Phase, LoaderBlock);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbuslock.asm b/private/ntos/nthals/halcbus/i386/cbuslock.asm
new file mode 100644
index 000000000..0e8e3c546
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbuslock.asm
@@ -0,0 +1,512 @@
+if NT_INST
+
+else
+ TITLE "Spin Locks"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; cbuslock.asm
+;
+; Abstract:
+;
+; This module implements x86 spinlock functions for the Corollary
+; multiprocessor HAL. Including both a stripped-down RaiseIrql
+; and LowerIrql inline for the AcquireSpinLock & ReleaseSpinLock
+; routines for speed.
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 13 Dec 89
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ken Reneris (kenr) 22-Jan-1991
+;
+; Landy Wang (landy@corollary.com) 07 Feb 93
+; - Now that these routines have been moved to the domain of the HAL,
+; speed them up by coding raise/lower irql inline.
+;--
+
+ PAGE
+
+.486p
+
+
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include hal386.inc
+include mac386.inc
+include i386\cbus.inc
+
+ EXTRNP KfRaiseIrql,1,,FASTCALL
+ EXTRNP KfLowerIrql,1,,FASTCALL
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ PAGE
+ SUBTTL "Acquire Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfAcquireSpinLock, 1
+cPublicFpo 0,0
+
+ ;
+ ; Raise to DISPATCH_LEVEL inline
+ ;
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ mov edx, [eax] ; get old taskpri val
+
+ mov dword ptr [eax], DPC_TASKPRI ; set new hardware taskpri
+ifdef CBC_REV1
+ popfd
+endif
+
+ mov eax, [_CbusVectorToIrql+4*edx] ; convert old taskpri to irql
+
+ ;
+ ; Acquire the lock
+ ;
+
+ align 4
+sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
+ fstRET KfAcquireSpinLock
+
+ ;
+ ; Lock is owned, spin till it looks free, then go get it again.
+ ;
+
+ align 4
+sl20: SPIN_ON_SPINLOCK ecx,sl10
+
+fstENDP KfAcquireSpinLock
+
+ PAGE
+ SUBTTL "Acquire Synch Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired,
+; any spin should occur at OldIrql)
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+;
+; Disable interrupts
+;
+
+sls10: cli
+
+;
+; Try to obtain spinlock. Use non-lock operation first
+;
+ TEST_SPINLOCK ecx,<short sls20>
+ ACQUIRE_SPINLOCK ecx,<short sls20>
+
+
+;
+; Got the lock, raise to SYNCH_LEVEL
+;
+
+ ; this function should be optimized to perform the irql
+ ; operation inline.
+
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+;
+; Enable interrupts and return
+;
+
+ sti
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sls20: sti
+ SPIN_ON_SPINLOCK ecx,sls10
+
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+
+ movzx edx, dl
+ RELEASE_SPINLOCK ecx ; release it
+ mov ecx, [_CbusIrqlToVector+4*edx] ; convert irql to taskpri
+
+ ; Inline version of KeLowerIrql
+
+ifdef CBC_REV1
+ ;
+ ; we should be at DISPATCH_LEVEL on entry and therefore shouldn't
+ ; need scheduling protection, but add this anyway in case there
+ ; are places that call this routine that don't obey the rules...
+ ;
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get hardware taskpri addr
+
+ mov [eax], ecx ; set new hardware taskpri
+
+ ;
+ ; read back the new hardware taskpri to work around an APIC errata.
+ ; doing this read forces the write to the task priority above to get
+ ; flushed out of any write buffer it may be lying in. this is needed
+ ; to ensure that we get the interrupt immediately upon return, not
+ ; just at some point in the (distant) future. this is needed because
+ ; NT counts on this in various portions of the code, for example
+ ; in KeConnectInterrupt(), where the rescheduling DPC must arrive
+ ; within 12 assembly instructions after lowering IRQL.
+ ;
+ mov ecx, [eax] ; issue dummy read as per above
+ifdef CBC_REV1
+ popfd
+endif
+
+ fstRET KfReleaseSpinLock
+
+fstENDP KfReleaseSpinLock
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ ;
+ ; code KfRaiseIrql/KfLowerIrql inline for speed
+ ;
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov edx, PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ mov eax, [edx] ; save old taskpri val
+
+ mov [edx], APC_TASKPRI ; set new hardware taskpri
+
+ifdef CBC_REV1
+ popfd
+endif
+ mov eax, [_CbusVectorToIrql+4*eax] ; convert old taskpri to irql
+
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,1
+ push ecx ; save mutex address
+ push eax ; save entry irql
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax ; restore entry irql
+ pop ecx ; restore mutex address
+
+cPublicFpo 0,0
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al ; tell caller his entry irql
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+
+;
+; Try to acquire
+;
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam25 ; Yes, abort
+
+cPublicFpo 0,1
+
+ ;
+ ; code KfRaiseIrql/KfLowerIrql inline for speed
+ ;
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get h/w taskpri addr
+
+ mov edx, [eax] ; get old taskpri val
+
+ mov [eax], APC_TASKPRI ; set new hardware taskpri
+
+ifdef CBC_REV1
+ popfd
+endif
+
+ push edx ; Save old task priority
+
+ mov eax, 1 ; Value to compare against
+ mov edx, 0 ; Value to set
+
+ lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire
+ jnz short tam20 ; got it?
+
+cPublicFpo 0,0
+ pop edx ; (edx) = old task priority
+ mov edx, [_CbusVectorToIrql+4*edx] ; convert old taskpri to irql
+
+ mov eax, 1 ; return TRUE
+ mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql
+ fstRet ExTryToAcquireFastMutex
+
+tam20:
+ pop edx ; (edx) = old task priority
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get hardware taskpri addr
+
+ mov [eax], edx ; set new hardware taskpri
+
+ ;
+ ; we must re-read the task priority register because this read
+ ; forces the write above to be flushed out of the write buffers.
+ ; otherwise the write above can get stuck and result in a pending
+ ; interrupt not being immediately delivered. in situations like
+ ; KeConnectInterrupt, the interrupt must be delivered in less than
+ ; 12 assembly instructions (the processor sends himself a rescheduling
+ ; DPC and has to execute it to switch to another CPU before continuing)
+ ; or corruption will result. because he thinks he has switched
+ ; processors and he really hasn't. and having the interrupt come in
+ ; after the 12 assembly instructions is _TOO LATE_!!!
+ ;
+ mov ecx, [eax] ; ensure it's lowered
+ifdef CBC_REV1
+ popfd
+endif
+
+tam25: xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz short rfm06 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+rfm06:
+
+ ;
+ ; code KfLowerIrql inline for speed
+ ;
+
+ movzx ecx, cl
+ mov ecx, [_CbusIrqlToVector+4*ecx] ; convert irql to taskpri
+
+ifdef CBC_REV1
+ pushfd
+ cli
+endif
+ mov eax, PCR[PcHal.PcrTaskpri] ; get hardware taskpri addr
+
+ mov [eax], ecx ; set new hardware taskpri
+
+ ;
+ ; we must re-read the task priority register because this read
+ ; forces the write above to be flushed out of the write buffers.
+ ; otherwise the write above can get stuck and result in a pending
+ ; interrupt not being immediately delivered. in situations like
+ ; KeConnectInterrupt, the interrupt must be delivered in less than
+ ; 12 assembly instructions (the processor sends himself a rescheduling
+ ; DPC and has to execute it to switch to another CPU before continuing)
+ ; or corruption will result. because he thinks he has switched
+ ; processors and he really hasn't. and having the interrupt come in
+ ; after the 12 assembly instructions is _TOO LATE_!!!
+ ;
+ mov ecx, [eax] ; ensure it's lowered
+ifdef CBC_REV1
+ popfd
+endif
+
+ fstRET ExReleaseFastMutex
+
+fstENDP ExReleaseFastMutex
+
+_TEXT ends
+ENDIF ; NT_INST
+
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbusmem.c b/private/ntos/nthals/halcbus/i386/cbusmem.c
new file mode 100644
index 000000000..f7ecf9266
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusmem.c
@@ -0,0 +1,294 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbus_mem.c
+
+Abstract:
+
+ This module implements the handling of additional memory
+ ranges to be freed to the MM subcomponent for the Corollary MP
+ architectures under Windows NT.
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cbusrrd.h"
+
+VOID
+CbusMemoryFree(
+IN ULONG Address,
+IN ULONG Size
+);
+
+VOID
+HalpAddMem (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, CbusMemoryFree)
+#pragma alloc_text(INIT, HalpAddMem)
+#endif
+
+#define MAX_MEMORY_RANGES 16
+
+ULONG HalpMemoryIndex;
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpMemory [MAX_MEMORY_RANGES];
+
+extern EXT_CFG_OVERRIDE_T CbusGlobal;
+extern ADDRESS_USAGE HalpCbusMemoryHole;
+extern ULONG CbusMemoryHoleIndex;
+
+#define SIXTEEN_MB (BYTES_TO_PAGES(16 * 1024 * 1024))
+
+VOID
+CbusMemoryFree(
+IN ULONG Address,
+IN ULONG Size
+)
+/*++
+
+Routine Description:
+
+ Add the specified memory range to our list of memory ranges to
+ give to MM later. Called each time we find a memory card during startup,
+ also called on Cbus1 systems when we add a jumpered range (between 8 and
+ 16MB). ranges are jumpered via EISA config when the user has added a
+ dual-ported RAM card and wants to configure it into the middle of memory
+ (not including 640K-1MB, which is jumpered for free) somewhere.
+
+Arguments:
+
+ Address - Supplies a start physical address in bytes of memory to free
+
+ Size - Supplies a length in bytes spanned by this range
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ ULONG Page;
+ ULONG Index;
+ ULONG Index2;
+
+ //
+ // add the card provided we have space.
+ //
+ if (HalpMemoryIndex >= MAX_MEMORY_RANGES)
+ return;
+
+ Page = BYTES_TO_PAGES(Address);
+ for (Index = 0; Index < HalpMemoryIndex; Index++) {
+ if (Page < HalpMemory[Index].BasePage) {
+ for (Index2 = HalpMemoryIndex+1; Index2 > Index; Index2--) {
+ HalpMemory[Index2] = HalpMemory[Index2 - 1];
+ }
+ break;
+ }
+ }
+
+ Descriptor = &HalpMemory[Index];
+ Descriptor->MemoryType = MemoryFree;
+ Descriptor->BasePage = Page;
+ Descriptor->PageCount = BYTES_TO_PAGES(Size);
+ HalpMemoryIndex++;
+}
+
+
+VOID
+HalpAddMem (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function adds any general-purpose memory (not found by
+ ntldr) to the memory descriptor lists for usage by the MM subcomponent.
+ Kernel mode only. Called from HalInitSystem() at Phase0 since
+ this must all happen before MmInitSystem happens at Phase0.
+
+
+Arguments:
+
+ LoaderBlock data structure to add the memory to. Note that when
+ adding memory, no attempt is made to sort new entries numerically
+ into the list.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NewMd;
+ ULONG Index;
+
+ //
+ // first, scan the existing memory list checking for an entries
+ // memory holes added to this table via the BIOS E820 function.
+ // using the E820 memory function was the only way to have the
+ // uniprocessor HAL not use the 3GB - 4GB range (CSR space),
+ // and other memory memory holes, for PCI devices. however,
+ // using the E820 memory function to pass reserved ranges has the
+ // side-effect of causing NT to allocate page tables and page
+ // file size calculations based on the inclusion of these reserved
+ // memory ranges. so, the E820 memory function will continue
+ // to set this range, but the C-bus HAL will look for these reserved
+ // memory ranges and delete it before the page tables are allocated.
+ // note that these reserved memory ranges have been recorded in
+ // HalpCbusMemoryHole and passed to the NT kernel as resources
+ // reserved by the C-bus HAL.
+ //
+ NewMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NewMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NewMd, MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ for (Index = 0; Index < CbusMemoryHoleIndex; Index++) {
+ if (Descriptor->BasePage == BYTES_TO_PAGES(HalpCbusMemoryHole.Element[Index].Start)) {
+ NewMd = &Descriptor->ListEntry;
+ RemoveEntryList(NewMd);
+ break;
+ }
+ }
+
+ NewMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // next, scan the existing memory list for memory above 16MB.
+ // if we find any, then we are running on a new BIOS
+ // which has already told the NT loader about all the memory in
+ // the system, so don't free it again now...
+ //
+ NewMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NewMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NewMd, MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if (Descriptor->BasePage + Descriptor->PageCount > SIXTEEN_MB) {
+ //
+ // our BIOS gave NT loader the memory already, so
+ // we can just bail right now...
+ //
+ return;
+ }
+
+ NewMd = Descriptor->ListEntry.Flink;
+ }
+
+ Descriptor = HalpMemory;
+
+ for (Index = 0; Index < HalpMemoryIndex; Index++, Descriptor++) {
+
+ NewMd = &Descriptor->ListEntry;
+
+ //
+ // any memory below 16MB has already been reported by the BIOS,
+ // so trim the request. this is because requests can arrive in
+ // the flavor of a memory board with 64MB (or more) on one board!
+ //
+ // note that Cbus1 "hole" memory is always reclaimed at the
+ // doubly-mapped address in high memory, never in low memory.
+ //
+
+ if (Descriptor->BasePage + Descriptor->PageCount <= SIXTEEN_MB) {
+ continue;
+ }
+
+ if (Descriptor->BasePage < SIXTEEN_MB) {
+ Descriptor->PageCount -= (SIXTEEN_MB-Descriptor->BasePage);
+ Descriptor->BasePage = SIXTEEN_MB;
+ }
+
+ InsertHeadList(&LoaderBlock->MemoryDescriptorListHead, NewMd);
+
+ }
+}
+
+#if 0
+
+VOID
+CbusMemoryThread()
+{
+ //
+ // Loop looking for work to do
+ //
+
+ do {
+
+ //
+ // Wait until something is put in the queue. By specifying
+ // a wait mode of UserMode, the thread's kernel stack is
+ // swappable
+ //
+
+ Entry = KeRemoveQueue(&ExWorkerQueue[QueueType], WaitMode,
+ NULL);
+
+ WorkItem = CONTAINING_RECORD(Entry, WORK_QUEUE_ITEM, List);
+
+ //
+ // Execute the specified routine.
+ //
+
+ } while (1);
+}
+
+BOOLEAN
+CbusCreateMemoryThread()
+{
+ HANDLE Thread;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+
+ //
+ // Create our memory scrubbing thread
+ //
+
+ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
+
+ Status = PsCreateSystemThread(&Thread,
+ THREAD_ALL_ACCESS,
+ &ObjectAttributes,
+ 0L,
+ NULL,
+ CbusMemoryThread,
+ (PVOID)CriticalWorkQueue);
+
+ if (!NT_SUCCESS(Status)) {
+ return FALSE;
+ }
+
+ ExCriticalWorkerThreads++;
+ ZwClose(Thread);
+
+ return True;
+}
+#endif
diff --git a/private/ntos/nthals/halcbus/i386/cbusmisc.asm b/private/ntos/nthals/halcbus/i386/cbusmisc.asm
new file mode 100644
index 000000000..4223fcf3c
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusmisc.asm
@@ -0,0 +1,406 @@
+
+ title "miscellaneous MP primitives for the Corollary MP machines"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+;Module Name:
+;
+; cbusmisc.asm
+;
+;Abstract:
+;
+; This module contains miscellaneous MP primitives for the
+; Corollary MP machines.
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+;
+;Revision History:
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include cbus.inc
+
+;
+; enable the Pentium internal cache to its full capability
+;
+CR0_INTERNAL_ON equ (not (CR0_NW or CR0_CD))
+CR0_INTERNAL_OFF equ (CR0_NW or CR0_CD)
+
+ .list
+
+INIT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; i486cacheon
+;
+; Routine Description:
+;
+; This function enables the calling processor's internal cache.
+; Executed by each processor (via HalInitializeProcessor) in the
+; Corollary Cbus1 and Cbus2 architectures.
+;
+; Note: This must be run before HalpInitializeStallExecution().
+;
+; Return Value:
+; none.
+;
+;--
+
+cPublicProc _i486cacheon ,0
+
+ pushfd
+ cli
+
+ ; Enable the 486 processor internal cache if it wasn't already.
+
+ mov eax, cr0 ; get real cr0
+ test eax, CR0_INTERNAL_OFF ; see if CPU cache on already
+ jz short @f ; no op if it is
+
+ ; hard code the WBINVD instruction to flush internal cache.
+ ; this would cause an opcode trap on 386, but we will ship
+ ; only 486 (Cbus1) and Pentium (Cbus2).
+
+ db 00fh ; ESCAPE
+ db 009h ; write-back invalidate
+
+ and eax, CR0_INTERNAL_ON ; enable CPU internal cache
+ jmp @f ; flush queues
+@@:
+ mov cr0, eax ; put cr0 back
+ popfd
+
+ stdRET _i486cacheon
+stdENDP _i486cacheon
+
+;++
+;
+; VOID
+; i486cacheoff
+;
+; Routine Description:
+;
+; This function disables the calling processor's internal cache.
+; Executed by each processor (via HalInitializeProcessor) in the
+; Corollary Cbus1 and Cbus2 architectures.
+;
+; Note: This must be run before HalpInitializeStallExecution().
+;
+; Return Value:
+; none.
+;
+;--
+
+cPublicProc _i486cacheoff ,0
+
+ pushfd
+ cli
+
+ ; Disable the 486 processor internal cache if it wasn't already.
+
+ mov eax, cr0 ; get real cr0
+ test eax, CR0_INTERNAL_OFF ; see if CPU cache on already
+ jnz short @f ; no op if it is
+
+ ; hard code the WBINVD instruction to flush internal cache.
+ ; this would cause an opcode trap on 386, but we will ship
+ ; only 486 (Cbus1) and Pentium (Cbus2).
+
+ db 00fh ; ESCAPE
+ db 009h ; write-back invalidate
+
+ or eax, CR0_INTERNAL_OFF ; disable CPU internal cache
+ jmp @f ; flush queues
+@@:
+ mov cr0, eax ; put cr0 back
+ popfd
+
+ stdRET _i486cacheoff
+stdENDP _i486cacheoff
+
+;++
+;
+; VOID
+; CbusDefaultStall (VOID)
+;
+; Routine Description:
+;
+; This routine initializes the calling processor's stall execution to
+; a reasonable value until we later give it a real value in HalInitSystem.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _CbusDefaultStall ,0
+ mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
+ stdRET _CbusDefaultStall
+stdENDP _CbusDefaultStall
+
+INIT ends ; end 32 bit init code
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "KeQueryPerformanceCounter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+
+cPublicProc _KeQueryPerformanceCounter ,1
+
+ jmp dword ptr [_CbusQueryPerformanceCounter]
+
+stdENDP _KeQueryPerformanceCounter
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processor's counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to the count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+
+ ;
+ ; Calibration is already handled by the Cbus HAL for both Cbus1
+ ; and Cbus2.
+ ;
+
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+ page ,132
+ subttl "CbusRebootHandler"
+;++
+;
+; VOID
+; CbusRebootHandler(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for an IPI interrupt generated
+; at a priority just below that of normal IPIs. Its function is to
+; force all additional processors to flush their internal cache and halt.
+; This puts the processors in a more conducive state for system reset.
+;
+; This routine is run only by the non-boot processors.
+;
+; Since this routine is entered directly via an interrupt gate, interrupt
+; protection via cli is not necessary.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hirs_a, hirs_t
+
+cPublicProc _CbusRebootHandler ,0
+
+ ;
+ ; Save machine state on trap frame
+ ;
+
+ ENTER_INTERRUPT hirs_a, hirs_t
+
+ ; keep it simple, just issue the EOI right now.
+ ; no changing of taskpri/irql is needed here.
+ ; Thus, the EOI serves as the HalEndSystemInterrupt.
+
+ mov eax, _CbusRebootVector
+ CBUS_EOI eax, ecx ; destroy eax & ecx
+
+ mov eax, dword ptr PCR[PcHal.PcrNumber]
+
+ ; the boot processor will take care of the reboot from this point on.
+ ; however, ensure that our internal cache is flushed and halt.
+
+ db 00fh ; ESCAPE
+ db 009h ; write-back invalidate
+ hlt
+
+ ;
+ ; we should never reach this point, but if we do, just return our
+ ; processor number (loaded above).
+ ;
+ stdRET _CbusRebootHandler
+stdENDP _CbusRebootHandler
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+
+cPublicProc _KeStallExecutionProcessor ,1
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ ; loop count for the processor
+ mul ecx ; (eax) = desired loop count
+
+if DBG
+
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short @f
+ int 3
+
+ align 4
+@@: cmp eax,0
+ jnz short @f
+ int 3
+@@:
+endif
+ALIGN 16
+ jmp kese05
+
+ALIGN 16
+kese05:
+ sub eax, 1 ; (eax) = (eax) - 1
+ jnz short kese05
+
+ align 4
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initializes the system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick in
+; 100ns units.
+;
+; Return Value:
+;
+; The *REAL* time increment set - this can be different from what he
+; requested due to hardware limitations.
+;--
+
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, _CbusBackend ; use hardware handler
+ jmp HalSetTimeIncrement[ eax ] ; JMP to set the interval
+ ; counter
+stdENDP _HalSetTimeIncrement
+
+_TEXT ends ; end 32 bit code
+
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbusnls.h b/private/ntos/nthals/halcbus/i386/cbusnls.h
new file mode 100644
index 000000000..2a23ee011
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusnls.h
@@ -0,0 +1,41 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ cbusnls.h
+
+Abstract:
+
+ Strings which are used in the HAL
+
+ English
+
+--*/
+
+
+#define MSG_OBSOLETE "HAL: CBUS HAL.DLL cannot be run on an out-of-date Corollary machine.\n"
+#define MSG_RRD_ERROR "HAL: RRD entry too short\n"
+#define MSG_OBSOLETE_PIC "HAL: No advanced interrupt controller on boot CPU\nUse default Windows NT HAL instead\n"
+#define MSG_OBSOLETE_PROC "WARNING: %d early C-bus I CPU board(s) disabled\n"
+
+#define MSG_ARBITRATE_ID_ERR "CbusIDtoCSR failure\n"
+#define MSG_ARBITRATE_FAILED "Cbus1 CPU arbitration failed"
+
+#define MSG_NMI_ECC0 "NMI: Processor %d interrupt indication is 0\n"
+#define MSG_NMI_ECC1 "NMI: Processor %d fault indication=%x\n"
+#define MSG_NMI_ECC2 "NMI: Processor %d address=0x%x%x, quadword=%x, fault indication=%x\n"
+
+#define MSG_NMI_ECC3 "NMI: Memory board %d fault status is 0\n"
+#define MSG_NMI_ECC4 "NMI: Memory board %d address=0x%x%x\n"
+
+#define MSG_NMI_ECC5 "NMI: I/O Bus bridge %d interrupt indication is 0\n"
+#define MSG_NMI_ECC6 "NMI: I/O Bus bridge %d fault indication=%x\n"
+#define MSG_NMI_ECC7 "NMI: I/O Bus bridge %d address=0x%x%x, quadword=%x, fault indication=%x\n"
+
+#define MSG_NMI_ECC8 "Fatal double-bit NMI"
+
+#define MSG_CBUS1NMI_ECC "NMI: double-bit ecc error address=0x%x%x\n"
+
+#define MSG_NEWLINE "\n"
diff --git a/private/ntos/nthals/halcbus/i386/cbusnmi.c b/private/ntos/nthals/halcbus/i386/cbusnmi.c
new file mode 100644
index 000000000..9ecbaaa7a
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusnmi.c
@@ -0,0 +1,204 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ cbusnmi.c
+
+Abstract:
+
+ Provides standard x86 NMI handler
+
+Author:
+
+ kenr
+
+Revision History:
+
+ Landy Wang (landy@corollary.com) 10-Oct-1992
+
+ - hook HalHandleNMI() so it can call the Corollary
+ backend platform-specific handlers.
+
+Revision History:
+
+--*/
+#ifndef _NTOS_
+#include "nthal.h"
+#endif
+#include "halp.h"
+#include "cbus_nt.h" // C-bus NT-specific implementation stuff
+#include "bugcodes.h"
+#include "stdio.h"
+#include "cbusnls.h"
+
+VOID
+HalHandleNMI(
+ IN OUT PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ Called DURING an NMI. The system will BugCheck when an NMI occurs.
+ This function can return the proper bugcheck code, bugcheck itself,
+ or return success which will cause the system to iret from the nmi.
+
+ This function is called during an NMI - no system services are available.
+ In addition, you don't want to touch any spinlock which is normally
+ used since we may have been interrupted while owning it, etc, etc...
+
+Warnings:
+
+ Do NOT:
+ Make any system calls
+ Attempt to acquire any spinlock used by any code outside the NMI handler
+ Change the interrupt state. Do not execute any IRET inside this code
+
+ Passing data to non-NMI code must be done using manual interlocked
+ functions. (xchg instructions).
+
+Arguments:
+
+ NmiInfo - Pointer to NMI information structure (TBD)
+ - NULL means no NMI information structure was passed
+
+Return Value:
+
+ STATUS_SUCCESS if NMI was handled and system should continue,
+ BugCheck code if not.
+
+--*/
+{
+ CbusBackend->ResolveNMI(NmiInfo);
+}
+
+
+#define SYSTEM_CONTROL_PORT_A 0x92
+#define SYSTEM_CONTROL_PORT_B 0x61
+#define EISA_EXTENDED_NMI_STATUS 0x461
+
+UCHAR EisaNMIMsg[] = MSG_NMI_EISA_IOCHKERR;
+
+
+VOID
+DefaultHalHandleNMI(
+ IN OUT PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ Called DURING an NMI. The system will BugCheck when an NMI occurs.
+ This function can return the proper bugcheck code, bugcheck itself,
+ or return success which will cause the system to iret from the nmi.
+
+ This function is called during an NMI - no system services are available.
+ In addition, you don't want to touch any spinlock which is normally
+ used since we may have been interrupted while owning it, etc, etc...
+
+Warnings:
+
+ Do NOT:
+ Make any system calls
+ Attempt to acquire any spinlock used by any code outside the NMI handler
+ Change the interrupt state. Do not execute any IRET inside this code
+
+ Passing data to non-NMI code must be done using manual interlocked
+ functions. (xchg instructions).
+
+Arguments:
+
+ NmiInfo - Pointer to NMI information structure (TBD)
+ - NULL means no NMI information structure was passed
+
+Return Value:
+
+ STATUS_SUCCESS if NMI was handled and system should continue,
+ BugCheck code if not.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ UCHAR c;
+ ULONG port, i;
+
+ HalDisplayString (MSG_HARDWARE_ERROR1);
+ HalDisplayString (MSG_HARDWARE_ERROR2);
+ StatusByte = READ_PORT_UCHAR((PUCHAR) SYSTEM_CONTROL_PORT_B);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_PARITY);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_CHANNEL_CHECK);
+ }
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR((PUCHAR) EISA_EXTENDED_NMI_STATUS);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_FAIL_SAFE);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_BUS_TIMEOUT);
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString (MSG_NMI_SOFTWARE_NMI);
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 1; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ c = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ for (i=0; EisaNMIMsg[i]; i++) {
+ if (EisaNMIMsg[i] == '%') {
+ EisaNMIMsg[i] = c;
+ break;
+ }
+ }
+ HalDisplayString (EisaNMIMsg);
+
+ }
+ }
+ }
+ }
+
+ HalDisplayString (MSG_HALT);
+ KeEnterKernelDebugger();
+}
+
+VOID
+CbusHardwareFailure(
+ IN PUCHAR HardwareMessage
+ )
+{
+ HalDisplayString (MSG_HARDWARE_ERROR1);
+ HalDisplayString (MSG_HARDWARE_ERROR2);
+ HalDisplayString (HardwareMessage);
+ HalDisplayString (MSG_HALT);
+ KeEnterKernelDebugger();
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbusproc.c b/private/ntos/nthals/halcbus/i386/cbusproc.c
new file mode 100644
index 000000000..199d2cc8f
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusproc.c
@@ -0,0 +1,427 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbusproc.c
+
+Abstract:
+
+ Corollary Start Next Processor C code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for the
+ Corollary MP architectures.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+ - slight modifications for Corollary architecture in HalInitMP().
+
+
+--*/
+
+#include "halp.h"
+#include "cbus_nt.h" // C-bus NT-specific implementation definitions
+
+#ifndef MCA
+UCHAR HalName[] = "Corollary C-bus Architecture MP HAL Version 3.4.0";
+#else
+UCHAR HalName[] = "Corollary C-bus MicroChannel Architecture MP HAL Version 3.4.0";
+#endif
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ );
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+StartPx_PMStub(
+ VOID
+ );
+
+VOID CbusCheckBusRanges(
+ VOID
+ );
+
+VOID CbusInitializeOtherPciBus(
+ VOID
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#pragma alloc_text(INIT,HalpFreeTiledCR3)
+#pragma alloc_text(INIT,HalpMapCR3)
+#pragma alloc_text(INIT,HalpBuildTiledCR3)
+#endif
+
+
+#define LOW_MEMORY 0x000100000
+#define MAX_PT 8
+
+ULONG MpCount; // zero based. 0 = 1, 1 = 2, ...
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR MppIDT; // pointer to physical memory 0:0
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ extern ULONG CbusProcessors;
+
+ if (Phase == 0) {
+
+ MpCount = CbusProcessors-1;
+
+ if (!MpCount) {
+ return TRUE;
+ }
+
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress)
+ return TRUE;
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+
+ }
+ return TRUE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registry is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+ //
+ // Check for and initialize other PCI buses.
+ //
+ CbusInitializeOtherPciBus ();
+
+ //
+ // Check all buses and determine SystemBase for all ranges
+ // within all buses.
+ //
+ CbusCheckBusRanges ();
+}
+
+VOID
+HalpInitOtherBuses (VOID)
+{
+ if (CbusBackend->InitOtherBuses)
+ (*CbusBackend->InitOtherBuses);
+}
+
+
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+
+
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halcbus/i386/cbusprof.asm b/private/ntos/nthals/halcbus/i386/cbusprof.asm
new file mode 100644
index 000000000..4b445df95
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusprof.asm
@@ -0,0 +1,193 @@
+ title "profile interrupt handler for the Corollary MP machines"
+;++
+;
+;Copyright (c) 1992, 1993, 1994 Corollary Inc
+;
+;Module Name:
+;
+; cbusprof.asm
+;
+;Abstract:
+;
+; This module contains the profile interrupt handler for the
+; non-boot processors in the Corollary MP machines. This is
+; only needed because only one processor should ack the CMOS
+; for each profile interrupt.
+;
+;Author:
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+;
+;Revision History:
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include cbus.inc
+
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ifdef CBC_REV1
+ EXTRNP _Cbus2RequestSoftwareInterrupt,1
+endif
+
+ .list
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+ page ,132
+ subttl "System Profile Interrupt for Additional Processors"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; This routine is only entered by the non-boot processors.
+;
+; The CMOS will be acked by the boot processor (only one CPU can
+; do this - which one is arbitrary, but it must only be ONE!).
+;
+; This function thus, just raises system Irql to PROFILE_LEVEL
+; and transfers control to the standard system routine to process
+; any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = PROFILE_LEVEL
+;
+;--
+ ENTER_DR_ASSIST Hpx_a, Hpx_t
+
+cPublicProc _HalpProfileInterruptPx ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT Hpx_a, Hpx_t
+
+ ;
+ ; (esp) - base of trap frame
+ ;
+
+ push _ProfileVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,_ProfileVector,esp>
+
+ ;
+ ; if this is C-bus II, modify the vector so the interrupt
+ ; will not be EOI'd.
+ ;
+ cmp _Cbus2BridgesFound, 0
+ je short cbus1
+ mov eax, [_CbusClockVector]
+ mov [esp+4], eax
+cbus1:
+
+ ;
+ ; The boot processor has already cleared (or is about to clear)
+ ; the interrupt flag on the RTC, so we don't do that here.
+ ;
+
+ jmp _HalpProfileInterrupt2ndEntry@0
+
+stdENDP _HalpProfileInterruptPx
+
+
+ page ,132
+ subttl "System Clock Interrupt for Additional Processors"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by CLOCK.
+; This routine is entered only by additional (non-boot) processors, so it
+; must NOT update the performance counter or update the system time.
+;
+; instead, it just dismisses the interrupt, raises system Irql to
+; CLOCK2_LEVEL and transfers control to the standard system routine
+; to update the execution time of the current thread and process.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateRunTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hcix_a, Hcix_t
+
+cPublicProc _CbusClockInterruptPx ,0
+
+ ;
+ ; Save machine state in trap frame
+ ; (esp) - base of trap frame
+ ;
+
+ ENTER_INTERRUPT Hcix_a, Hcix_t
+
+ifdef CBC_REV1
+ ;
+ ; because we can miss an interrupt due to a hardware bug in the
+ ; CBC rev 1 silicon, send ourselves an IPI on every clock.
+ ; since we don't know when we've missed one, this will ensure
+ ; we don't cause lock timeouts if nothing else!
+ ;
+
+ stdCall _Cbus2RequestSoftwareInterrupt, <IPI_LEVEL>
+endif
+
+ ;
+ ; Dismiss interrupt and raise irq level to clock2 level
+ ;
+
+ push _CbusClockVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL, _CbusClockVector, esp>
+
+ ; Spurious interrupts on Corollary hardware are
+ ; directed to a different interrupt gate, so no need
+ ; to check return value above.
+
+ POKE_LEDS eax, edx
+
+ mov eax, dword ptr [_CbusTimeStamp]
+ mov dword ptr [eax], 0
+
+ ;
+ ; (esp) = OldIrql
+ ; (esp+4) = Vector
+ ; (esp+8) = base of trap frame
+ ;
+ ; (ebp) = base of trap frame for KeUpdateRunTime, this was set
+ ; up by the ENTER_INTERRUPT macro above
+
+ stdCall _KeUpdateRunTime,<dword ptr [esp]>
+
+ INTERRUPT_EXIT
+
+stdENDP _CbusClockInterruptPx
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/halcbus/i386/cbusrrd.h b/private/ntos/nthals/halcbus/i386/cbusrrd.h
new file mode 100644
index 000000000..e29a89cfd
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/cbusrrd.h
@@ -0,0 +1,299 @@
+/*++
+
+Copyright (c) 1992, 1993, 1994 Corollary Inc.
+
+Module Name:
+
+ cbusrrd.h
+
+Abstract:
+
+ Definitions for the Corollary C-bus II MP hardware architecture
+ interface with the Rom Resident Diagnostic
+
+Author:
+
+ Landy Wang (landy@corollary.com) 26-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _CBUS_RRD_H
+#define _CBUS_RRD_H
+
+//
+// Processor Types - counting number
+///
+#define PT_NO_PROCESSOR 0x0
+#define PT_386 0x1
+#define PT_486 0x2
+#define PT_PENTIUM 0x3
+
+//
+// Processor Attributes - counting number
+///
+#define PA_CACHE_OFF 0x0
+#define PA_CACHE_ON 0x1
+
+//
+// I/O Function - counting number
+//
+#define IOF_NO_IO 0x0
+#define IOF_CBUS1_SIO 0x1
+#define IOF_CBUS1_SCSI 0x2
+#define IOF_REACH_IO 0x3
+#define IOF_ISA_BRIDGE 0x4
+#define IOF_EISA_BRIDGE 0x5
+#define IOF_HODGE 0x6
+#define IOF_MEDIDATA 0x7
+#define IOF_INVALID_ENTRY 0x8 // use to denote whole entry is invalid,
+ // note that pm must equal zero as well.
+#define IOF_MEMORY 0x9
+
+//
+// Bit fields of pel_features, independent of whether pm indicates it
+// has an attached processor or not.
+//
+#define ELEMENT_SIO 0x00001 // SIO present
+#define ELEMENT_SCSI 0x00002 // SCSI present
+#define ELEMENT_IOBUS 0x00004 // IO bus is accessible
+#define ELEMENT_BRIDGE 0x00008 // IO bus Bridge
+#define ELEMENT_HAS_8259 0x00010 // local 8259s present
+#define ELEMENT_HAS_CBC 0x00020 // local Corollary CBC
+#define ELEMENT_HAS_APIC 0x00040 // local Intel APIC
+#define ELEMENT_WITH_IO 0x00080 // some extra I/O device here
+ // this could be SCSI, SIO, etc
+#define ELEMENT_RRD_RESERVED 0x20000 // Old RRDs used this
+
+// Due to backwards compatibility, the check for an I/O
+// device is somewhat awkward.
+
+#define ELEMENT_HAS_IO (ELEMENT_SIO | ELEMENT_SCSI | ELEMENT_WITH_IO)
+
+//
+// Bit fields of machine types
+//
+#define MACHINE_CBUS1 0x1 // Original C-bus 1
+#define MACHINE_CBUS1_XM 0x2 // XM C-bus 1
+#define MACHINE_CBUS2 0x4 // C-bus 2
+
+//
+// Bit fields of supported environment types - each bit signifies that
+// the specified operating system release is supported in full multiprocessor
+// mode. Note that since the Cbus2 hardware changed, and initial hardware
+// wasn't available until Q2 1994, Cbus2 RRDs will _NEVER_ set the
+// 0x4 bit, and will instead set the 0x10 bit. This will have the effect
+// of Cbus2 being supported in MP mode by NT release 3.5 and up. Cbus1
+// will be supported in MP mode by all NT releases (3.1 and up).
+//
+#define SCO_UNIX 0x01
+#define USL_UNIX 0x02
+#define WINDOWS_NT 0x04 // release 3.1 and up (July 1993)
+#define NOVELL 0x08
+#define OS2 0x10
+#define WINDOWS_NT_R2 0x20 // release 3.5 and up (June 1994)
+
+//
+// address of configuration passed
+//
+#define RRD_RAM 0xE0000
+
+//
+// extended structures passed by RRD ROMs to various kernels
+// for the Corollary smp architectures
+//
+// layout of information passed to the kernels:
+// The exact format of the configuration structures is hard
+// coded in info.s (rrd). The layout is designed such that
+// the ROM version need not be in sync with the kernel version.
+//
+// checkword: ULONG
+// - extended configuration list must be terminated
+// with EXT_CFG_END (0)
+// length: ULONG
+// - length is for structure body only; does not include
+// either the checkword or length word
+//
+// structure body: format determined by checkword
+//
+//
+
+typedef struct _ext_cfg_header {
+
+ ULONG ext_cfg_checkword;
+ ULONG ext_cfg_length;
+
+} EXT_CFG_HEADER_T, *PEXT_CFG_HEADER;
+
+//
+// slot parameter structure (overrides any matching previous entry,
+// but is usually used in conjunction with the ext_cfg_override)
+// in processor_configuration or ext_memory_board.
+//
+// checkword is EXT_ID_INFO
+//
+// each structure is 16 bytes wide, and any number
+// of these structures can be presented by the ROM.
+// the kernel will keep reading them until either:
+//
+// a) an entry with id == 0x7f (this is treated as the list delimiter)
+// OR
+// b) the kernel's internal tables fill up. at which point, only
+// the entries read thus far will be used and the rest ignored.
+//
+#define EXT_ID_INFO 0x01badcab
+typedef struct _ext_id_info {
+
+ ULONG id:7;
+
+ //
+ // pm == 1 indicates CPU, pm == 0 indicates non-CPU (ie: memory or I/O)
+ //
+ ULONG pm:1;
+
+ ULONG proc_type:4;
+ ULONG proc_attr:4;
+
+ //
+ // io_function != 0 indicates I/O,
+ // io_function == 0 or 9 indicates memory
+ //
+ ULONG io_function:8;
+
+ //
+ // io_attr can pertain to an I/O card or memory card
+ //
+ ULONG io_attr:8;
+
+ //
+ // pel_start & pel_size can pertain to a CPU card,
+ // I/O card or memory card
+ //
+ ULONG pel_start;
+ ULONG pel_size;
+
+ ULONG pel_features;
+
+ //
+ // below two fields can pertain to an I/O card or memory card
+ //
+ ULONG io_start;
+ ULONG io_size;
+
+} EXT_ID_INFO_T, *PEXT_ID_INFO;
+
+#define LAST_EXT_ID 0x7f // delimit the extended ID list
+
+extern ULONG cbus_valid_ids;
+extern EXT_ID_INFO_T cbusext_id_info[];
+
+//
+// configuration parameter override structure
+//
+// checkword is EXT_CFG_OVERRIDE.
+// can be any length up to the kernel limit. this
+// is a SYSTEMWIDE configuration override structure.
+//
+#define EXT_CFG_OVERRIDE 0xdeedcafe
+
+typedef struct _ext_cfg_override {
+ ULONG baseram;
+ ULONG memory_ceiling;
+ ULONG resetvec;
+ ULONG cbusio; // base of global Cbus I/O space
+
+ UCHAR bootid;
+ UCHAR useholes;
+ UCHAR rrdarb;
+ UCHAR nonstdecc;
+ ULONG smp_creset;
+ ULONG smp_creset_val;
+ ULONG smp_sreset;
+
+ ULONG smp_sreset_val;
+
+ //
+ // piggyback various fields which have meaning only in Cbus2 with
+ // fields which only have meaning in Cbus1. these should really be
+ // unions...
+ //
+
+ ULONG smp_contend;
+#define InterruptControlMask smp_contend
+
+ ULONG smp_contend_val;
+#define FaultControlMask smp_contend_val
+
+#define CBUS_ENABLED_PW 0x01
+#define CBUS_ENABLED_LIG 0x02
+#define CBUS_DISABLE_LEVEL_TRIGGERED_INT_FIX 0x04
+#define CBUS_DISABLE_SPURIOUS_CLOCK_CHECK 0x08
+#define CBUS_ENABLE_BROADCAST 0x10
+
+ //
+ // if rrdarb is set (will only happen on Cbus1 machines),
+ // then use setida as the address to set CPU IDs.
+ // if rrdarb is not set _AND_ it's a Cbus2 machine,
+ // then if setida has bit 0 set, then enable
+ // posted-writes for EISA I/O cycles.
+ //
+ ULONG smp_setida;
+#define Cbus2Features smp_setida
+
+ ULONG smp_setida_val;
+#define Control8259Mode smp_setida_val
+
+ ULONG smp_cswi;
+#define Control8259ModeValue smp_cswi
+
+ ULONG smp_cswi_val;
+ ULONG smp_sswi;
+
+ ULONG smp_sswi_val;
+ ULONG smp_cnmi;
+ ULONG smp_cnmi_val;
+ ULONG smp_snmi;
+
+ ULONG smp_snmi_val;
+ ULONG smp_sled;
+ ULONG smp_sled_val;
+ ULONG smp_cled;
+
+ ULONG smp_cled_val;
+ ULONG machine_type;
+ ULONG supported_environments;
+ ULONG broadcast_id;
+
+} EXT_CFG_OVERRIDE_T, *PEXT_CFG_OVERRIDE;
+
+extern EXT_CFG_OVERRIDE_T CbusGlobal;
+
+#define EXT_CFG_END 0
+
+//
+// this is the original structure passed from RRD to UNIX for the
+// Corollary multiprocessor architecture. The only fields we are
+// still interested in is the jumper settings - all other fields
+// are now obtained from the extended configuration tables. hence
+// the structure below contains only a subset of the original structure.
+//
+
+#define ATMB 16
+#define MB(x) ((x) * 1024 * 1024)
+
+typedef struct _rrd_configuration {
+
+ ULONG checkword; // must be 0xdeadbeef
+ UCHAR mem[64]; // each 1 signifies a real MB
+ UCHAR jmp[ATMB]; // each 1 signifies jumpered MB
+
+} RRD_CONFIGURATION_T, *PRRD_CONFIGURATION;
+
+#define JUMPER_SIZE (sizeof (RRD_CONFIGURATION_T))
+
+#endif // _CBUS_RRD_H
diff --git a/private/ntos/nthals/halcbus/i386/halp.h b/private/ntos/nthals/halcbus/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halcbus/i386/ix8259.inc b/private/ntos/nthals/halcbus/i386/ix8259.inc
new file mode 100644
index 000000000..1546408d1
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halcbus/i386/ixbeep.asm b/private/ntos/nthals/halcbus/i386/ixbeep.asm
new file mode 100644
index 000000000..eb2723e1c
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halcbus/i386/ixbusdat.c b/private/ntos/nthals/halcbus/i386/ixbusdat.c
new file mode 100644
index 000000000..38ff4f515
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixcmos.asm b/private/ntos/nthals/halcbus/i386/ixcmos.asm
new file mode 100644
index 000000000..7c472d779
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halcbus/i386/ixcmos.inc b/private/ntos/nthals/halcbus/i386/ixcmos.inc
new file mode 100644
index 000000000..14a90be8f
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halcbus/i386/ixdat.c b/private/ntos/nthals/halcbus/i386/ixdat.c
new file mode 100644
index 000000000..b35be0b4b
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixenvirv.c b/private/ntos/nthals/halcbus/i386/ixenvirv.c
new file mode 100644
index 000000000..998131ad7
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixfirm.c b/private/ntos/nthals/halcbus/i386/ixfirm.c
new file mode 100644
index 000000000..f4a62c8e6
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixhwsup.c b/private/ntos/nthals/halcbus/i386/ixhwsup.c
new file mode 100644
index 000000000..a38cb695a
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixidle.asm b/private/ntos/nthals/halcbus/i386/ixidle.asm
new file mode 100644
index 000000000..df0471dbc
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halcbus/i386/ixinfo.c b/private/ntos/nthals/halcbus/i386/ixinfo.c
new file mode 100644
index 000000000..4b2ca3f27
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixisa.h b/private/ntos/nthals/halcbus/i386/ixisa.h
new file mode 100644
index 000000000..851f7455d
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halcbus/i386/ixisabus.c b/private/ntos/nthals/halcbus/i386/ixisabus.c
new file mode 100644
index 000000000..69acc0d9b
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixisasup.c b/private/ntos/nthals/halcbus/i386/ixisasup.c
new file mode 100644
index 000000000..441740a6f
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixkdcom.c b/private/ntos/nthals/halcbus/i386/ixkdcom.c
new file mode 100644
index 000000000..a345dacea
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixkdcom.h b/private/ntos/nthals/halcbus/i386/ixkdcom.h
new file mode 100644
index 000000000..561f64cc0
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halcbus/i386/ixmca.h b/private/ntos/nthals/halcbus/i386/ixmca.h
new file mode 100644
index 000000000..ee6b0709d
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixmca.h
@@ -0,0 +1,5 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#include "halmca\i386\ixmca.h"
diff --git a/private/ntos/nthals/halcbus/i386/ixmcabus.c b/private/ntos/nthals/halcbus/i386/ixmcabus.c
new file mode 100644
index 000000000..a8d8f55e0
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixmcabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#include "halmca\i386\ixmcabus.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixmcasup.c b/private/ntos/nthals/halcbus/i386/ixmcasup.c
new file mode 100644
index 000000000..f3e648e63
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixmcasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#include "halmca\i386\ixmcasup.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixpcibrd.c b/private/ntos/nthals/halcbus/i386/ixpcibrd.c
new file mode 100644
index 000000000..158e19341
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixpcibrd.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixpcibus.c b/private/ntos/nthals/halcbus/i386/ixpcibus.c
new file mode 100644
index 000000000..9c799947b
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixpciint.c b/private/ntos/nthals/halcbus/i386/ixpciint.c
new file mode 100644
index 000000000..35160bc76
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixphwsup.c b/private/ntos/nthals/halcbus/i386/ixphwsup.c
new file mode 100644
index 000000000..90ef815af
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixprofil.asm b/private/ntos/nthals/halcbus/i386/ixprofil.asm
new file mode 100644
index 000000000..07ad0d885
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixprofil.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\ixprofil.asm
diff --git a/private/ntos/nthals/halcbus/i386/ixreboot.c b/private/ntos/nthals/halcbus/i386/ixreboot.c
new file mode 100644
index 000000000..a246dd95d
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixthunk.c b/private/ntos/nthals/halcbus/i386/ixthunk.c
new file mode 100644
index 000000000..01fe25363
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halcbus/i386/ixusage.c b/private/ntos/nthals/halcbus/i386/ixusage.c
new file mode 100644
index 000000000..524705910
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halcbus/i386/pcip.h b/private/ntos/nthals/halcbus/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/halcbus/i386/xxbiosa.asm b/private/ntos/nthals/halcbus/i386/xxbiosa.asm
new file mode 100644
index 000000000..2da2d0fd7
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halcbus/i386/xxbiosc.c b/private/ntos/nthals/halcbus/i386/xxbiosc.c
new file mode 100644
index 000000000..aa00832e9
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halcbus/i386/xxdisp.c b/private/ntos/nthals/halcbus/i386/xxdisp.c
new file mode 100644
index 000000000..451ee18e6
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halcbus/i386/xxflshbf.c b/private/ntos/nthals/halcbus/i386/xxflshbf.c
new file mode 100644
index 000000000..8a8646f63
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halcbus/i386/xxkdsup.c b/private/ntos/nthals/halcbus/i386/xxkdsup.c
new file mode 100644
index 000000000..2cad9cf92
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halcbus/i386/xxmemory.c b/private/ntos/nthals/halcbus/i386/xxmemory.c
new file mode 100644
index 000000000..a8c6f6f68
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halcbus/i386/xxstubs.c b/private/ntos/nthals/halcbus/i386/xxstubs.c
new file mode 100644
index 000000000..d0b4e936c
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halcbus/i386/xxtime.c b/private/ntos/nthals/halcbus/i386/xxtime.c
new file mode 100644
index 000000000..0767298a6
--- /dev/null
+++ b/private/ntos/nthals/halcbus/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halcbus/mca/makefile b/private/ntos/nthals/halcbus/mca/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halcbus/mca/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halcbus/mca/makefile.inc b/private/ntos/nthals/halcbus/mca/makefile.inc
new file mode 100644
index 000000000..e2bb55a56
--- /dev/null
+++ b/private/ntos/nthals/halcbus/mca/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: ..\..\hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) ..\..\hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halcbus/mca/sources b/private/ntos/nthals/halcbus/mca/sources
new file mode 100644
index 000000000..f160571e9
--- /dev/null
+++ b/private/ntos/nthals/halcbus/mca/sources
@@ -0,0 +1,116 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halcbusm
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=$(C_DEFINES) -DMCA
+ASM_DEFINES=$(ASM_DEFINES) -DMCA
+
+INCLUDES=..\..\..\inc;..\..\..\ke;..\..\;..;..\..\halmca\i386
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ..\i386\ixbeep.asm \
+ ..\i386\ixbusdat.c \
+ ..\i386\ixdat.c \
+ ..\i386\ixinfo.c \
+ ..\i386\ixisabus.c \
+ ..\i386\ixpcibus.c \
+ ..\i386\ixpciint.c \
+ ..\i386\ixpcibrd.c \
+ ..\i386\ixcmos.asm \
+ ..\i386\ixenvirv.c \
+ ..\i386\ixfirm.c \
+ ..\i386\ixhwsup.c \
+ ..\i386\ixidle.asm \
+ ..\i386\ixmcabus.c \
+ ..\i386\ixmcasup.c \
+ ..\i386\ixkdcom.c \
+ ..\i386\ixphwsup.c \
+ ..\i386\ixprofil.asm \
+ ..\i386\ixreboot.c \
+ ..\i386\ixthunk.c \
+ ..\i386\ixusage.c \
+ ..\i386\xxbiosa.asm \
+ ..\i386\xxbiosc.c \
+ ..\i386\xxdisp.c \
+ ..\i386\xxkdsup.c \
+ ..\i386\xxmemory.c \
+ ..\i386\xxstubs.c \
+ ..\i386\xxtime.c \
+ ..\i386\cbapic.c \
+ ..\i386\cbioacc.asm \
+ ..\i386\cb1stall.asm \
+ ..\i386\cb2stall.asm \
+ ..\i386\cbswint.asm \
+ ..\i386\cbsysint.asm \
+ ..\i386\cbmapint.c \
+ ..\i386\cbdriver.c \
+ ..\i386\cbusnmi.c \
+ ..\i386\cbusboot.asm \
+ ..\i386\cbuslock.asm \
+ ..\i386\cbusprof.asm \
+ ..\i386\cbusmisc.asm \
+ ..\i386\cbus2cbc.asm \
+ ..\i386\cbusapic.asm \
+ ..\i386\cbus2.c \
+ ..\i386\cbus1.c \
+ ..\i386\cbus1bt.asm \
+ ..\i386\cbus2ecc.c \
+ ..\i386\cbus.c \
+ ..\i386\cbus_sw.c \
+ ..\i386\cbusmem.c \
+ ..\i386\cbushal.c \
+ ..\i386\cbusproc.c
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halcbusm.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halcbus/rangesup.c b/private/ntos/nthals/halcbus/rangesup.c
new file mode 100644
index 000000000..d9d8db63f
--- /dev/null
+++ b/private/ntos/nthals/halcbus/rangesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\rangesup.c"
diff --git a/private/ntos/nthals/haldti/drivesup.c b/private/ntos/nthals/haldti/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haldti/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haldti/hal.rc b/private/ntos/nthals/haldti/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haldti/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haldti/hal.src b/private/ntos/nthals/haldti/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haldti/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haldti/makefile b/private/ntos/nthals/haldti/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haldti/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haldti/makefile.inc b/private/ntos/nthals/haldti/makefile.inc
new file mode 100644
index 000000000..2558bb59f
--- /dev/null
+++ b/private/ntos/nthals/haldti/makefile.inc
@@ -0,0 +1,6 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\haldti.lib
+ copy $** $@
+
diff --git a/private/ntos/nthals/haldti/mips/allstart.c b/private/ntos/nthals/haldti/mips/allstart.c
new file mode 100644
index 000000000..8d81b6eb8
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/allstart.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haldti/mips/dtidef.h b/private/ntos/nthals/haldti/mips/dtidef.h
new file mode 100644
index 000000000..e105e845f
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/dtidef.h
@@ -0,0 +1,147 @@
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jazzdef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 26-Nov-1990
+
+Revision History:
+
+--*/
+
+#ifndef _DTIDEF_
+#define _DTIDEF_
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+//#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+#define MAXIMUM_MAP_BUFFER_SIZE 0x80000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+//#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x80000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+//#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x80000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+//#define MAXIMUM_ISA_MAP_REGISTER 16
+#define MAXIMUM_ISA_MAP_REGISTER 64
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_ISA_PHYSICAL_ADDRESS 0x01000000
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//typedef volatile struct _OLD_TRANSLATION_ENTRY {
+// ULONG PageFrame;
+// ULONG Fill;
+//} OLD_TRANSLATION_ENTRY, *POLD_TRANSLATION_ENTRY;
+//
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define physical base addresses for system mapping.
+//
+
+#define EISA_CONTROL_PHYSICAL_BASE 0x10000000 // physical base of EISA control
+#define EISA_MEMORY_PHYSICAL_BASE 0x00000000 // physical base of EISA memory
+
+////
+//// Define the size of the DMA translation table.
+////
+//#define DMA_TRANSLATION_LIMIT 0x100 // translation table limit
+
+//
+// Define EISA NMI interrupt level.
+//
+
+#define EISA_NMI_LEVEL 6
+
+//
+// Define the minimum and maximum system time increment values in 100ns units.
+//
+// N.B. these values are as close to exact values as possible given the input
+// clock of 1.19318167 hz (14.31818 / 12)
+//
+
+#define MAXIMUM_INCREMENT (99968) // Time increment in 100ns units - Approx 10 ms
+#define MINIMUM_INCREMENT (10032) // Time increment in 100ns units - Approx 1 ms
+
+//
+// Define clock constants and clock levels.
+//
+
+#define AT_BUS_OSC 14318180 // 14.31818 MHz Crystal
+#define CLOCK_LEVEL 32 // Interval clock level
+
+#if defined(R3000)
+
+#define EISA_DEVICE_LEVEL 8 // EISA bus interrupt level
+
+#endif
+
+#if defined(R4000)
+
+#define EISA_DEVICE_LEVEL 5 // EISA bus interrupt level
+
+#endif
+
+#define CLOCK2_LEVEL CLOCK_LEVEL //
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define EISA_VECTORS 32
+
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+#endif // _DTIDEF_
diff --git a/private/ntos/nthals/haldti/mips/halp.h b/private/ntos/nthals/haldti/mips/halp.h
new file mode 100644
index 000000000..e600988b0
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/halp.h
@@ -0,0 +1,179 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "dtidef.h"
+#include "hal.h"
+#include "jxhalp.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define function prototypes.
+//
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ );
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpPurgeSecondaryCachePage (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ );
+
+VOID HalpProgramIntervalTimer(
+ IN ULONG IntervalCount
+ );
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG1_BASE)) ? TRUE : FALSE)
+
+//
+// Define external references.
+//
+
+extern PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern BOOLEAN LessThan16Mb;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/haldti/mips/j4cache.s b/private/ntos/nthals/haldti/mips/j4cache.s
new file mode 100644
index 000000000..fe657e353
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/j4cache.s
@@ -0,0 +1,1026 @@
+#if defined(R4000)
+
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30: j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,ZpA1(sp) // get old color value
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
+
+ SBTTL("Purge Secondary Cache Page")
+//++
+//
+// VOID
+// HalpPurgeSecondaryCachePage (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (invalidates) the specified range of addresses
+// from the secondary write through cache on an Evolution RISC PC.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the page that is purged
+// from the secondary cache.
+//
+// Length (a1) - Supplies the length to purge from the secondary cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeSecondaryCachePage)
+
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+
+//
+// Purge data from the primary data cache and the secondary cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ subu t6,t4,1 // compute block size minus one
+ and t7,a0,t6 // compute offset in block
+ addu a1,a1,t6 // round up to next block
+ addu a1,a1,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a1,a1,t6 // truncate length to even number
+ beq zero,a1,30f // if eq, no blocks to purge
+ and t8,a0,t6 // compute starting virtual address
+ addu t9,t8,a1 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate primary cache block
+ lw zero,0x0(t8) // invalidate secondary cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeSecondaryCachePage
+
+#endif
diff --git a/private/ntos/nthals/haldti/mips/j4flshbf.s b/private/ntos/nthals/haldti/mips/j4flshbf.s
new file mode 100644
index 000000000..ff3a32f78
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/j4flshbf.s
@@ -0,0 +1,61 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/haldti/mips/j4flshio.c b/private/ntos/nthals/haldti/mips/j4flshio.c
new file mode 100644
index 000000000..14a757965
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/j4flshio.c
@@ -0,0 +1,264 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+extern PVOID SecondaryCachePurgeBaseAddress;
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, export or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then export the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ // If this is a read operation involving a DMA device, then purge the
+ // secondary write through cache by performing read operations in the
+ // appropriate range of SecondaryCachePurgeBaseAddress
+
+ if (ReadOperation != FALSE && DmaOperation != FALSE) {
+
+ volatile ULONG i;
+ volatile ULONG j;
+ ULONG PurgeOffset;
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ PurgeOffset = ((((*PageFrame)<<12) | (Source&0xfff)) & 0x7fff0);
+
+ HalpPurgeSecondaryCachePage((PVOID)((ULONG)SecondaryCachePurgeBaseAddress + PurgeOffset),CacheSegment);
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/haldti/mips/j4prof.c b/private/ntos/nthals/haldti/mips/j4prof.c
new file mode 100644
index 000000000..5c858c382
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/j4prof.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter;
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter;
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ HalpPerformanceCounter.QuadPart = 0;
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Sourve - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/haldti/mips/jxbeep.c b/private/ntos/nthals/haldti/mips/jxbeep.c
new file mode 100644
index 000000000..cb04082f4
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxbeep.c
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = (AT_BUS_OSC/12) / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeLowerIrql(oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/haldti/mips/jxdisp.c b/private/ntos/nthals/haldti/mips/jxdisp.c
new file mode 100644
index 000000000..3225a0a4f
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxdisp.c
@@ -0,0 +1,246 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ Andre Vachon (andreva) 09-May-1992
+ David N. Cutler (davec) 27-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "stdio.h"
+#include "string.h"
+
+#define CSI (CHAR)0x9b
+
+extern ULONG IoSpaceAlreadyMapped;
+
+static CHAR DisplayInitializationString[] = {CSI,'3','7',';','4','4','m',CSI,'2','J',0};
+static CHAR CarriageReturnString[] = {13,0};
+
+static ULONG HalOwnsDisplay = FALSE;
+static ULONG DisplayFile;
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ArcClose(DisplayFile);
+ HalOwnsDisplay = FALSE;
+
+ HalpResetDisplayParameters = ResetDisplayParameters;
+
+ return;
+}
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Count;
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ HalpMapIoSpace();
+ HalpInitializeX86DisplayAdapter();
+ IoSpaceAlreadyMapped = TRUE;
+ }
+
+ if (HalOwnsDisplay==FALSE) {
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+ ArcOpen(ArcGetEnvironmentVariable("ConsoleOut"),ArcOpenWriteOnly,&DisplayFile);
+ ArcWrite(DisplayFile,DisplayInitializationString,strlen(DisplayInitializationString),&Count);
+ HalOwnsDisplay=TRUE;
+ }
+
+ ArcWrite(DisplayFile,String,strlen(String),&Count);
+ ArcWrite(DisplayFile,CarriageReturnString,strlen(CarriageReturnString),&Count);
+ return;
+
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_DISPLAY_STATUS *DisplayStatus;
+
+ //
+ // Get the display parameter values and return.
+ //
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Make firmware call to get the display's current status
+ //
+
+ DisplayStatus = ArcGetDisplayStatus(DisplayFile);
+
+ *WidthInCharacters = DisplayStatus->CursorMaxXPosition;
+ *HeightInLines = DisplayStatus->CursorMaxYPosition;
+ *CursorColumn = DisplayStatus->CursorXPosition;
+ *CursorRow = DisplayStatus->CursorYPosition;
+
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHAR SetCursorPositionString[20];
+ ULONG Count;
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Build ANSI sequence to set the cursor position.
+ //
+
+ sprintf(SetCursorPositionString,"%c%d;%dH",CSI,CursorRow,CursorColumn);
+ ArcWrite(DisplayFile,SetCursorPositionString,strlen(SetCursorPositionString),&Count);
+
+ return;
+}
diff --git a/private/ntos/nthals/haldti/mips/jxebsup.c b/private/ntos/nthals/haldti/mips/jxebsup.c
new file mode 100644
index 000000000..eb764f0fd
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxebsup.c
@@ -0,0 +1,2376 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "dtidef.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+extern PVOID HalpEisaControlBase;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice,
+ IN ULONG noncachedAddress
+ );
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and updated to
+ show actual number allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ UCHAR channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+ ULONG maximumLength;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!eisaSystem &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = (UCHAR)(DeviceDescriptor->DmaChannel & 0x03);
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ if (!HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ )) {
+ }
+
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch (channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (eisaSystem) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ adapterObject->MasterDevice = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+ ULONG noncachedAddress;
+ ULONG partialLength;
+ ULONG temp;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) & 0x03ffffff;
+
+ //
+ // If the buffer is contigous and does not cross a 64 K bountry then
+ // just extend the buffer. The 64 K bountry restriction does not apply
+ // to Eisa systems.
+ //
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ } else {
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1) ||
+ (*pageFrame & ~0x0f) != (*(pageFrame + 1) & ~0x0f)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+ }
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL &&
+ !( ((*pageFrame<<PAGE_SHIFT) & 0x03ffffff) >= HalpMapBufferPhysicalAddress.LowPart &&
+ ((*pageFrame<<PAGE_SHIFT) & 0x03ffffff) < (HalpMapBufferPhysicalAddress.LowPart + HalpMapBufferSize))) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+
+// Make IoMapTransfer() assume that all transfers are above 16 MB and have
+// to be mapped through the map buffer.
+
+// if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+// }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+// HalpCopyBufferMap(
+// Mdl,
+// translationEntry + index,
+// CurrentVa,
+// *Length,
+// WriteToDevice,
+// noncachedAddress
+// );
+
+ temp = transferLength;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= *Length ) {
+
+ noncachedAddress = KSEG1_BASE | ((*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa));
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = *Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ noncachedAddress = KSEG1_BASE | ((*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa));
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ }
+
+ transferLength = temp;
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+ ULONG logicalAddress;
+ ULONG noncachedAddress;
+
+ ULONG PagesAbove16MB;
+ ULONG PagesBelow16MB;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL ||
+ ( ((*pageFrame<<PAGE_SHIFT) & 0x03ffffff) >= HalpMapBufferPhysicalAddress.LowPart &&
+ ((*pageFrame<<PAGE_SHIFT) & 0x03ffffff) < (HalpMapBufferPhysicalAddress.LowPart + HalpMapBufferSize))) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ }
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ PagesBelow16MB = 0;
+ PagesAbove16MB = 0;
+
+ while( transferLength <= Length ){
+
+// Make IoFlushAdapterBuffers assume that all transfers are above 16MB
+// and have to be mapped through the map buffer.
+
+// if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ PagesAbove16MB++;
+
+// }
+//
+// else {
+//
+// PagesBelow16MB++;
+//
+// }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+// Make IoFlushAdapterBuffer assume that all transfers are above 16MB and
+// have to be mapped through the map buffer.
+
+// if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ if (partialLength) {
+
+// if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ PagesAbove16MB++;
+
+// }
+//
+// else {
+//
+// PagesBelow16MB++;
+//
+// }
+ }
+
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+// //
+// // Initialize the EISA NMI interrupt.
+// //
+//
+//
+// PCR->InterruptRoutine[EISA_NMI_LEVEL] = HalHandleNMI;
+//
+// //
+// // Clear the Eisa NMI disable bit. This bit is the high order of the
+// // NMI enable register.
+// //
+//
+// DataByte = 0;
+// //
+// // TEMPTEMP Disable the NMI because this is causing machines in the build
+// // lab to fail.
+// //
+// DataByte = 0x80;
+//
+// WRITE_REGISTER_UCHAR(
+// &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+// DataByte
+// );
+
+ //
+ // Initialize the EISA interrupt dispatcher for ArcStation I/O interrupts.
+ //
+
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second level
+ interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PULONG dispatchCode;
+ PKINTERRUPT interruptObject;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue;
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector =
+ READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector != 0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset = interruptVector + EISA_VECTORS;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ //
+ // The interrupt vector for CLOCK2_LEVEL is directly connected by the HAL.
+ // If the interrupt is on CLOCK2_LEVEL then vector to the address stored
+ // in the PCR. Otherwise, bypass the thunk code in the interrupt object
+ // whose address is stored in the PCR.
+ //
+
+ if (PCRInOffset == CLOCK2_LEVEL) {
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])
+ (PCR->InterruptRoutine[PCRInOffset]);
+
+ } else {
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+ }
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ } else {
+
+ //
+ // This interrupt is on the second interrupt controller
+ //
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ PCRInOffset = interruptVector + 8 + EISA_VECTORS;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ }
+ }
+ }
+}
diff --git a/private/ntos/nthals/haldti/mips/jxenvirv.c b/private/ntos/nthals/haldti/mips/jxenvirv.c
new file mode 100644
index 000000000..3d69ac268
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxenvirv.c
@@ -0,0 +1,98 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "string.h"
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+ CHAR *Value;
+
+ Value = ArcGetEnvironmentVariable(Variable);
+ if (Value==NULL)
+ return(ENOENT);
+ if (strlen(Value)>Length)
+ return(ENOENT);
+ strcpy(Buffer,Value);
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+ return(ArcSetEnvironmentVariable(Variable,Value));
+}
diff --git a/private/ntos/nthals/haldti/mips/jxhalp.h b/private/ntos/nthals/haldti/mips/jxhalp.h
new file mode 100644
index 000000000..42d5cdf9a
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxhalp.h
@@ -0,0 +1,105 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/haldti/mips/jxhwsup.c b/private/ntos/nthals/haldti/mips/jxhwsup.c
new file mode 100644
index 000000000..b36595764
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxhwsup.c
@@ -0,0 +1,2024 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+extern BOOLEAN LessThan16Mb;
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+extern PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ BOOLEAN eisaSystem;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+
+ // On an R4000 system, this space should be mapped with caches
+ // disabled to avoid having to perform page exports on IO writes
+ // and page purges on IO reads.
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disabled.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!eisaSystem &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1 ) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+extern PVOID SecondaryCachePurgeBaseAddress;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice,
+ IN ULONG noncachedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+ ULONG *p;
+ ULONG *q;
+ UCHAR *m;
+ UCHAR *n;
+ ULONG i;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, (PCCHAR)noncachedAddress, Length);
+
+// if ( ((ULONG)mapAddress & 0x03)==0 &&
+// ((ULONG)noncachedAddress & 0x03)==0 &&
+// (Length & 0x03)==0 ) {
+// p = (ULONG *)mapAddress;
+// q = (ULONG *)noncachedAddress;
+// for(i=0;i<Length;i+=4)
+// *(p++) = *(q++);
+// }
+// else {
+//
+// KdPrint(("HalpCopyBufferMap() : Unaligned copy\n"));
+//
+// m = (UCHAR *)mapAddress;
+// n = (UCHAR *)noncachedAddress;
+// for(i=0;i<Length;i++)
+// *(m++) = *(n++);
+// }
+
+ } else {
+
+ RtlMoveMemory( (PCCHAR)noncachedAddress, mapAddress, Length);
+
+// if ( ((ULONG)mapAddress & 0x03)==0 &&
+// ((ULONG)noncachedAddress & 0x03)==0 &&
+// (Length & 0x03)==0 ) {
+// q = (ULONG *)mapAddress;
+// p = (ULONG *)noncachedAddress;
+// for(i=0;i<Length;i+=4)
+// *(p++) = *(q++);
+// }
+// else {
+//
+// KdPrint(("HalpCopyBufferMap() : Unaligned copy\n"));
+//
+// n = (UCHAR *)mapAddress;
+// m = (UCHAR *)noncachedAddress;
+// for(i=0;i<Length;i++)
+// *(m++) = *(n++);
+// }
+
+ }
+
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ UCHAR SavedNeedsMapRegisters;
+ ULONG SavedMapRegistersPerChannel;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMapRegistersPerChannel = AdapterObject->MapRegistersPerChannel;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG)mapRegisterBase & ~NO_SCATTER_GATHER);
+ LogicalAddress->HighPart = 0;
+ LogicalAddress->LowPart = translationEntry->PhysicalAddress;
+ virtualAddress = (PVOID)(0xa0000000 | LogicalAddress->LowPart);
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+
+ return(virtualAddress);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+ UCHAR SavedNeedsMapRegisters;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ if (MasterAdapterObject != NULL) {
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = (LogicalAddress.LowPart - HalpMapBufferPhysicalAddress.LowPart) >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+
+ }
+
+ return;
+
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != Internal) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Jazz only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+}
+
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ return 0;
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ return HalpCreateEisaStructures();
+
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
diff --git a/private/ntos/nthals/haldti/mips/jxmapio.c b/private/ntos/nthals/haldti/mips/jxmapio.c
new file mode 100644
index 000000000..48fc44aa8
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxmapio.c
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+#define REAL_TIME_CLOCK_ADDRESS 0x71
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase;
+PVOID HalpRealTimeClockBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ // For ARCStation I, Eisa I/O Space can be accessed through KSEG1.
+ // So, HalpEisaControlBase can be computed by ORing the base address
+ // of KSEG1 with the base physical address of EISA I/O space.
+ // HalpRealTimeClockBase can be computed in a similar manner.
+
+ HalpEisaControlBase = (PVOID)(KSEG1_BASE | EISA_CONTROL_PHYSICAL_BASE);
+
+ HalpEisaMemoryBase = (PVOID)(KSEG1_BASE | EISA_MEMORY_PHYSICAL_BASE);
+
+ HalpRealTimeClockBase = (PVOID)(KSEG1_BASE | EISA_CONTROL_PHYSICAL_BASE | REAL_TIME_CLOCK_ADDRESS);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haldti/mips/jxport.c b/private/ntos/nthals/haldti/mips/jxport.c
new file mode 100644
index 000000000..afc9c4dca
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxport.c
@@ -0,0 +1,773 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+// Assume COM1 for the kernel debugger.
+
+#define SERIAL_PORT_ADDRESS 0x3f8
+
+#define SP_READ ((PSP_READ_REGISTERS)(KSEG1_BASE | EISA_CONTROL_PHYSICAL_BASE | SERIAL_PORT_ADDRESS))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(KSEG1_BASE | EISA_CONTROL_PHYSICAL_BASE | SERIAL_PORT_ADDRESS))
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 6;
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 1843200.
+ //
+
+ BaudClock = 1843200;
+
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ KdComPortInUse=(PUCHAR)(SERIAL_PORT_ADDRESS);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff));
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
+
+
diff --git a/private/ntos/nthals/haldti/mips/jxreturn.c b/private/ntos/nthals/haldti/mips/jxreturn.c
new file mode 100644
index 000000000..3ca52b325
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxreturn.c
@@ -0,0 +1,89 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+ ArcReboot();
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/haldti/mips/jxsysint.c b/private/ntos/nthals/haldti/mips/jxsysint.c
new file mode 100644
index 000000000..af60aded5
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxsysint.c
@@ -0,0 +1,252 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This functionr returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ *Affinity = 1;
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != Internal) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+
+ }
+
+ //
+ // Jazz only has one I/O bus which is an EISA, so the bus number and the
+ // bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/haldti/mips/jxtime.c b/private/ntos/nthals/haldti/mips/jxtime.c
new file mode 100644
index 000000000..25c825f89
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxtime.c
@@ -0,0 +1,278 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+#define BCDToBinary(D) (10 * (((D) & 0xf0) >>4 ) + ((D) & 0x0f))
+#define BinaryToBCD(B) ((((B) & 0xff) / 10) << 4 ) | (((B) & 0xff) % 10)
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_YEAR));
+ if (TimeFields->Year < 1992)
+ TimeFields->Year += 100;
+ TimeFields->Month = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MONTH));
+ TimeFields->Day = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_MONTH));
+ TimeFields->Weekday = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_WEEK)) - 1;
+ TimeFields->Hour = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_HOUR));
+ TimeFields->Minute = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MINUTE));
+ TimeFields->Second = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_SECOND));
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN HalSetRealTimeClock (IN PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DayLightSavingsEnable = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(BinaryToBCD(TimeFields->Year - 1900)));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)BinaryToBCD(TimeFields->Month));
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)BinaryToBCD(TimeFields->Day));
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(BinaryToBCD(TimeFields->Weekday + 1)));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)BinaryToBCD(TimeFields->Hour));
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)BinaryToBCD(TimeFields->Minute));
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)BinaryToBCD(TimeFields->Second));
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/haldti/mips/jxusage.c b/private/ntos/nthals/haldti/mips/jxusage.c
new file mode 100644
index 000000000..0c1d01efc
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/jxusage.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/haldti/mips/x4clock.s b/private/ntos/nthals/haldti/mips/x4clock.s
new file mode 100644
index 000000000..9b20f0e03
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/x4clock.s
@@ -0,0 +1,210 @@
+#if defined(R4000)
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // Get current time increment
+ jal KeUpdateSystemTime // update system time
+ lw t0,HalpNextTimeIncrement // Get NextTimeIncrement
+ sw t0,HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+ lw a0,HalpNextIntervalCount // Get Next Interval Count. If 0, then no change required
+ beq zero,a0,5f // See if time increment is to be changed
+ jal HalpProgramIntervalTimer // Program timer with new interval count value
+ lw t0,HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ sw t0,HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+ sw zero,HalpNextIntervalCount // Set HalpNextIntervalCount to 0
+5:
+ lw t0,KdDebuggerEnabled // check if debugger enabled
+ lbu t0,0(t0) //
+ beq zero,t0,10f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,10f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+10: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ la t1,HalpPerformanceCounter // get performance counter address
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ j KeProfileInterrupt // process profile entries
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+#endif
diff --git a/private/ntos/nthals/haldti/mips/x86bios.c b/private/ntos/nthals/haldti/mips/x86bios.c
new file mode 100644
index 000000000..c31a8baf5
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/x86bios.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+typedef struct FIRMWARE_INT_ARGUMENTS {
+ ULONG pEAX;
+ ULONG pEBX;
+ ULONG pECX;
+ ULONG pEDX;
+ ULONG pESI;
+ ULONG pEDI;
+ ULONG pEBP;
+ USHORT pES;
+ USHORT pDS;
+ USHORT pFlags;
+} FIRMWARE_INT_ARGUMENTS, *PFIRMWARE_INT_ARGUMENTS;
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+ULONG HalpUseFirmwareX86Emulator = FALSE;
+
+typedef
+VOID
+(*PVENDOR_EXECUTE_INT) (
+ IN USHORT Type,
+ IN PFIRMWARE_INT_ARGUMENTS Context
+ );
+
+PVENDOR_EXECUTE_INT VendorX86ExecuteInt;
+
+VOID HalpInitializeX86DisplayAdapter()
+
+{
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = (PSYSTEM_PARAMETER_BLOCK)(0x80001000);
+
+ //
+ // If EISA I/O Ports or EISA Memory could not be mapped, then leave the
+ // X86 BIOS Emulator disabled.
+ //
+
+ if (HalpEisaControlBase == NULL || HalpEisaMemoryBase == NULL) {
+
+// DbgPrint("X86 BIOS Emulator Disabled\n");
+
+ return;
+ }
+
+ //
+ // If Firmware level X86 Bios Emulator exists, then use that instead of the
+ // one built into the HAL.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength/4) >= 34) {
+
+ VendorX86ExecuteInt =
+ *(PVENDOR_EXECUTE_INT *)((ULONG)(SystemParameterBlock->VendorVector) + 34*4);
+
+ if (VendorX86ExecuteInt != NULL) {
+ HalpX86BiosInitialized = TRUE;
+ HalpUseFirmwareX86Emulator = TRUE;
+ HalpEnableInt10Calls = TRUE;
+
+// DbgPrint("Firmware X86 BIOS Emulator Enabled\n");
+// DbgPrint("INT 10 Calls Enabled\n");
+
+ return;
+ }
+ }
+
+// DbgPrint("HAL X86 BIOS Emulator Enabled\n");
+
+ x86BiosInitializeBios(HalpEisaControlBase, HalpEisaMemoryBase);
+
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the Display Adapter by executing the Display Adapters
+ // initialization code in its BIOS. The standard for PC video adapters is for
+ // the BIOS to reside at 0xC000:0000 on the ISA bus.
+ //
+
+// DbgPrint("X86BiosInitializeAdapter(0xc0000)\n");
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+
+// DbgPrint("INT 10 Calls Disabled\n");
+
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+// DbgPrint("INT 10 Calls Enabled\n");
+}
+
+VOID HalpResetX86DisplayAdapter()
+
+{
+ XM86_CONTEXT Context;
+
+ //
+ // Make INT 10 call to initialize 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ FIRMWARE_INT_ARGUMENTS Arguments;
+ XM86_CONTEXT Context;
+
+
+ //
+ // If the X86 BIOS Emulator has not been initialized then fail all INT calls.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return(FALSE);
+ }
+
+ //
+ // If the Video Adapter initialization failed, then we can not make INT 10 calls.
+ //
+
+ if (BiosCommand == 0x10 && HalpEnableInt10Calls == FALSE) {
+ return(FALSE);
+ }
+
+// DbgPrint("HalCallBios(%02X,%04X,%04X,%04X,%04X,%04X,%04X,%04X)\n",BiosCommand,*Eax,*Ebx,*Ecx,*Edx,*Esi,*Edi,*Ebp);
+
+ if (HalpUseFirmwareX86Emulator == TRUE) {
+
+ //
+ // Make private vector call to the emulator in the firmware.
+ //
+
+ Arguments.pEAX = *Eax;
+ Arguments.pEBX = *Ebx;
+ Arguments.pECX = *Ecx;
+ Arguments.pEDX = *Edx;
+ Arguments.pESI = *Esi;
+ Arguments.pEDI = *Edi;
+ Arguments.pEBP = *Ebp;
+ Arguments.pES = 0;
+ Arguments.pDS = 0;
+ Arguments.pFlags = 0;
+
+ VendorX86ExecuteInt((USHORT)BiosCommand,&Arguments);
+
+ *Eax = Arguments.pEAX;
+ *Ebx = Arguments.pEBX;
+ *Ecx = Arguments.pECX;
+ *Edx = Arguments.pEDX;
+ *Esi = Arguments.pESI;
+ *Edi = Arguments.pEDI;
+ *Ebp = Arguments.pEBP;
+
+ }
+ else {
+
+ //
+ // Make call to emulator build into HAL
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+
+ }
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haldti/mips/x86bios.h b/private/ntos/nthals/haldti/mips/x86bios.h
new file mode 100644
index 000000000..c52a96fea
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/x86bios.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the haltyne directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\haltyne\mips\x86bios.h"
diff --git a/private/ntos/nthals/haldti/mips/x86lator.c b/private/ntos/nthals/haldti/mips/x86lator.c
new file mode 100644
index 000000000..b1e36cb72
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/x86lator.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the haltyne directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\haltyne\mips\x86lator.c"
diff --git a/private/ntos/nthals/haldti/mips/xxcalstl.c b/private/ntos/nthals/haldti/mips/xxcalstl.c
new file mode 100644
index 000000000..d30177228
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/xxcalstl.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Start the system clock to interrupt at the MAXIMUM_INCREMENT interval.
+ //
+ // N.B. MAXIMUM_INCREMENT is in 100ns units.
+ //
+
+ HalSetTimeIncrement(MAXIMUM_INCREMENT);
+ HalpProgramIntervalTimer(HalpNextIntervalCount);
+ HalpEnableEisaInterrupt(CLOCK2_LEVEL,Latched); /* Enable Timer1,Counter0 interrupt */
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (PCR->StallScaleFactor <= 0) {
+ PCR->StallScaleFactor = 1;
+ }
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+// //
+// // Acknowledge the clock interrupt.
+// //
+//
+//#if defined(JAZZ)
+//
+// READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+//
+//#endif
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/haldti/mips/xxclock.c b/private/ntos/nthals/haldti/mips/xxclock.c
new file mode 100644
index 000000000..27a981d7b
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/xxclock.c
@@ -0,0 +1,171 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define clock count and time table.
+//
+
+typedef struct _COUNT_ENTRY {
+ ULONG Count;
+ ULONG Time;
+} COUNT_ENTRY, *PCOUNT_ENTRY;
+
+COUNT_ENTRY TimeTable[] = {
+ {1197, 10032},
+ {2394, 20064},
+ {3591, 30096},
+ {4767, 39952},
+ {5964, 49984},
+ {7161, 60016},
+ {8358, 70048},
+ {9555, 80080},
+ {10731, 89936},
+ {11928, 99968}
+ };
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG IntervalCount
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+Arguments:
+
+ IntervalCount - Supplies cound value to be placed in the timer/counter.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+
+ //
+ // Set the system clock timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ controlBase = HalpEisaControlBase;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)IntervalCount);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(IntervalCount >> 8));
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // The new clock count value is selected from a precomputed table of
+ // count/time pairs. The values in the table were selected for their
+ // accuracy and closeness to the values of 1ms, 2ms, 3ms, etc. to 10ms.
+ //
+ // N.B. The NT executive guarantees that this function will never
+ // be called with the desired incrment less than the minimum
+ // increment or greater than the maximum increment.
+ //
+
+ for (Index = 0; Index < sizeof(TimeTable) / sizeof(COUNT_ENTRY); Index += 1) {
+ if (DesiredIncrement <= TimeTable[Index].Time) {
+ break;
+ }
+ }
+
+ if (DesiredIncrement < TimeTable[Index].Time) {
+ Index -= 1;
+ }
+
+ HalpNextIntervalCount = TimeTable[Index].Count;
+ HalpNewTimeIncrement = TimeTable[Index].Time;
+ KeLowerIrql(OldIrql);
+ return TimeTable[Index].Time;
+}
diff --git a/private/ntos/nthals/haldti/mips/xxidle.s b/private/ntos/nthals/haldti/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/haldti/mips/xxinithl.c b/private/ntos/nthals/haldti/mips/xxinithl.c
new file mode 100644
index 000000000..d55d826f1
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/xxinithl.c
@@ -0,0 +1,269 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+BOOLEAN LessThan16Mb;
+PVOID SecondaryCachePurgeBaseAddress = (PVOID)(0x80f00000);
+ULONG IoSpaceAlreadyMapped = FALSE;
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ Prcb = KeGetCurrentPrcb();
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+ LessThan16Mb = TRUE;
+
+ SecondaryCachePurgeBaseAddress = NULL;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+// To purge the secondary cache on an ArcStation I, a valid Firmware Permanent
+// region must be found that starts on a 512 KB boundry and is at least
+// 512 KB long. The secondary cache is purged by reading from the appropriate
+// range of this 512 KB region for the page being purged.
+
+ if (Descriptor->MemoryType == LoaderFirmwarePermanent &&
+ (Descriptor->BasePage % 128)==0 &&
+ Descriptor->PageCount>=128) {
+
+ SecondaryCachePurgeBaseAddress = (PVOID)(KSEG0_BASE | (Descriptor->BasePage*4096));
+
+ Descriptor->BasePage+=128;
+ Descriptor->PageCount-=128;
+
+ }
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ if (SecondaryCachePurgeBaseAddress==NULL) {
+ HalDisplayString("ERROR : A valid Firmware Permanent area does not exist\n");
+ KeBugCheck(PHASE0_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_ISA_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, FALSE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ //
+ // Initialize interrupts.
+ //
+
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ HalpMapIoSpace();
+ HalpInitializeX86DisplayAdapter();
+ IoSpaceAlreadyMapped = TRUE;
+ }
+
+ HalpCreateDmaStructures();
+ HalpCalibrateStall();
+ return TRUE;
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion ()
+{
+
+}
diff --git a/private/ntos/nthals/haldti/mips/xxinitnt.c b/private/ntos/nthals/haldti/mips/xxinitnt.c
new file mode 100644
index 000000000..9053b05e9
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/xxinitnt.c
@@ -0,0 +1,158 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+#if defined(R4000)
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+#endif
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Connect the clock interrupt to the stall interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Connect the R4000 count/compare interrupt to the early interrupt
+ // routine.
+ //
+
+#if defined(R4000)
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+#endif
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haldti/mips/xxmemory.c b/private/ntos/nthals/haldti/mips/xxmemory.c
new file mode 100644
index 000000000..30ed99db8
--- /dev/null
+++ b/private/ntos/nthals/haldti/mips/xxmemory.c
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow tha HAL to map physical memory
+
+Author:
+
+ Jeff McLeman (DEC) 11-June-1992
+
+Environment:
+
+ Phase 0 initialization only
+
+--*/
+
+#include "halp.h"
+
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The pyhsical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+// if ((Descriptor->MemoryType == LoaderFree ||
+// Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+// (Descriptor->BasePage) &&
+// (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+// (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+ if ((Descriptor->MemoryType == MemoryFirmwarePermanent) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset <= MaxPageAddress)) {
+
+ PhysicalAddress =
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) << PAGE_SHIFT;
+
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // orgial block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+ return PhysicalAddress;
+}
diff --git a/private/ntos/nthals/haldti/sources b/private/ntos/nthals/haldti/sources
new file mode 100644
index 000000000..8573a033a
--- /dev/null
+++ b/private/ntos/nthals/haldti/sources
@@ -0,0 +1,84 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haldti
+TARGETPATH=\nt\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\x86new;..\..\inc
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\jxbeep.c \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxmemory.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halduomp/drivesup.c b/private/ntos/nthals/halduomp/drivesup.c
new file mode 100644
index 000000000..8247c7928
--- /dev/null
+++ b/private/ntos/nthals/halduomp/drivesup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halduomp/hal.rc b/private/ntos/nthals/halduomp/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halduomp/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halduomp/hal.src b/private/ntos/nthals/halduomp/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halduomp/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halduomp/makefile b/private/ntos/nthals/halduomp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halduomp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halduomp/makefile.inc b/private/ntos/nthals/halduomp/makefile.inc
new file mode 100644
index 000000000..6ef17781f
--- /dev/null
+++ b/private/ntos/nthals/halduomp/makefile.inc
@@ -0,0 +1,57 @@
+mips\allstart.c: ..\halfxs\mips\allstart.c
+
+mips\cacherr.s: ..\halfxs\mips\cacherr.s
+
+mips\jxbeep.c: ..\halfxs\mips\jxbeep.c
+
+mips\jxdmadsp.s: ..\halfxs\mips\jxdmadsp.s
+
+mips\jxenvirv.c: ..\halfxs\mips\jxenvirv.c
+
+mips\j4flshbf.s: ..\halfxs\mips\j4flshbf.s
+
+mips\j4flshio.c: ..\halfxs\mips\j4flshio.c
+
+mips\jxdisp.c: ..\halfxs\mips\jxdisp.c
+
+mips\jxebsup.c: ..\halfxs\mips\jxebsup.c
+
+mips\jxhwsup.c: ..\halfxs\mips\jxhwsup.c
+
+mips\jxmapio.c: ..\halfxs\mips\jxmapio.c
+
+mips\jxmaptb.c: ..\halfxs\mips\jxmaptb.c
+
+mips\jxport.c: ..\halfxs\mips\jxport.c
+
+mips\j4cache.s: ..\halfxs\mips\j4cache.s
+
+mips\j4prof.c: ..\halfxs\mips\j4prof.c
+
+mips\jxreturn.c: ..\halfxs\mips\jxreturn.c
+
+mips\jxsysint.c: ..\halfxs\mips\jxsysint.c
+
+mips\jxtime.c: ..\halfxs\mips\jxtime.c
+
+mips\jxusage.c: ..\halfxs\mips\jxusage.c
+
+mips\x4clock.s: ..\halfxs\mips\x4clock.s
+
+mips\xxcalstl.c: ..\halfxs\mips\xxcalstl.c
+
+mips\xxinitnt.c: ..\halfxs\mips\xxinitnt.c
+
+mips\xxinithl.c: ..\halfxs\mips\xxinithl.c
+
+mips\xxipiint.s: ..\halfxs\mips\xxipiint.s
+
+mips\x4tb.s: ..\halfxs\mips\x4tb.s
+
+mips\x86bios.c: ..\halfxs\mips\x86bios.c
+
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halduomp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halduomp/mips/allstart.c b/private/ntos/nthals/halduomp/mips/allstart.c
new file mode 100644
index 000000000..26556a5c7
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/allstart.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\allstart.c"
diff --git a/private/ntos/nthals/halduomp/mips/cacherr.s b/private/ntos/nthals/halduomp/mips/cacherr.s
new file mode 100644
index 000000000..0b3cdf5ce
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/cacherr.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\cacherr.s"
diff --git a/private/ntos/nthals/halduomp/mips/halp.h b/private/ntos/nthals/halduomp/mips/halp.h
new file mode 100644
index 000000000..2f89bf746
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/halp.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\halp.h"
diff --git a/private/ntos/nthals/halduomp/mips/j4cache.s b/private/ntos/nthals/halduomp/mips/j4cache.s
new file mode 100644
index 000000000..0f17e43bf
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/j4cache.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4cache.s"
diff --git a/private/ntos/nthals/halduomp/mips/j4flshbf.s b/private/ntos/nthals/halduomp/mips/j4flshbf.s
new file mode 100644
index 000000000..04012b70b
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/j4flshbf.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshbf.s"
diff --git a/private/ntos/nthals/halduomp/mips/j4flshio.c b/private/ntos/nthals/halduomp/mips/j4flshio.c
new file mode 100644
index 000000000..d608140c2
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/j4flshio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshio.c"
diff --git a/private/ntos/nthals/halduomp/mips/j4prof.c b/private/ntos/nthals/halduomp/mips/j4prof.c
new file mode 100644
index 000000000..dd8c2b7c9
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/j4prof.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4prof.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxbeep.c b/private/ntos/nthals/halduomp/mips/jxbeep.c
new file mode 100644
index 000000000..173ea259e
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxbeep.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxbeep.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxdisp.c b/private/ntos/nthals/halduomp/mips/jxdisp.c
new file mode 100644
index 000000000..9daf3d16e
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxdisp.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdisp.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxdmadsp.s b/private/ntos/nthals/halduomp/mips/jxdmadsp.s
new file mode 100644
index 000000000..370edd47f
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxdmadsp.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdmadsp.s"
diff --git a/private/ntos/nthals/halduomp/mips/jxebsup.c b/private/ntos/nthals/halduomp/mips/jxebsup.c
new file mode 100644
index 000000000..c0f0b6b37
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxebsup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxebsup.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxenvirv.c b/private/ntos/nthals/halduomp/mips/jxenvirv.c
new file mode 100644
index 000000000..398a656e7
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxenvirv.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxenvirv.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxhalp.h b/private/ntos/nthals/halduomp/mips/jxhalp.h
new file mode 100644
index 000000000..4e39adf70
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxhalp.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxhalp.h"
diff --git a/private/ntos/nthals/halduomp/mips/jxhwsup.c b/private/ntos/nthals/halduomp/mips/jxhwsup.c
new file mode 100644
index 000000000..be474375a
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxhwsup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxhwsup.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxmapio.c b/private/ntos/nthals/halduomp/mips/jxmapio.c
new file mode 100644
index 000000000..879f96410
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxmapio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmapio.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxmaptb.c b/private/ntos/nthals/halduomp/mips/jxmaptb.c
new file mode 100644
index 000000000..9262bc775
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxmaptb.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmaptb.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxport.c b/private/ntos/nthals/halduomp/mips/jxport.c
new file mode 100644
index 000000000..26e310528
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxport.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxport.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxreturn.c b/private/ntos/nthals/halduomp/mips/jxreturn.c
new file mode 100644
index 000000000..8ff827bf7
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxreturn.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxreturn.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxsysint.c b/private/ntos/nthals/halduomp/mips/jxsysint.c
new file mode 100644
index 000000000..528753dda
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxsysint.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxsysint.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxtime.c b/private/ntos/nthals/halduomp/mips/jxtime.c
new file mode 100644
index 000000000..996be9c3c
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxtime.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxtime.c"
diff --git a/private/ntos/nthals/halduomp/mips/jxusage.c b/private/ntos/nthals/halduomp/mips/jxusage.c
new file mode 100644
index 000000000..e4d8e2f52
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/jxusage.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxusage.c"
diff --git a/private/ntos/nthals/halduomp/mips/x4clock.s b/private/ntos/nthals/halduomp/mips/x4clock.s
new file mode 100644
index 000000000..ce9c3a190
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/x4clock.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4clock.s"
diff --git a/private/ntos/nthals/halduomp/mips/x4tb.s b/private/ntos/nthals/halduomp/mips/x4tb.s
new file mode 100644
index 000000000..be37d6677
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/x4tb.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4tb.s"
diff --git a/private/ntos/nthals/halduomp/mips/x86bios.c b/private/ntos/nthals/halduomp/mips/x86bios.c
new file mode 100644
index 000000000..89aea8d14
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/x86bios.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x86bios.c"
diff --git a/private/ntos/nthals/halduomp/mips/xxcalstl.c b/private/ntos/nthals/halduomp/mips/xxcalstl.c
new file mode 100644
index 000000000..eabb7db1d
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/xxcalstl.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxcalstl.c"
diff --git a/private/ntos/nthals/halduomp/mips/xxclock.c b/private/ntos/nthals/halduomp/mips/xxclock.c
new file mode 100644
index 000000000..c7ec77df5
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/xxclock.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxclock.c"
diff --git a/private/ntos/nthals/halduomp/mips/xxidle.s b/private/ntos/nthals/halduomp/mips/xxidle.s
new file mode 100644
index 000000000..faf3163a9
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/xxidle.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxidle.s"
diff --git a/private/ntos/nthals/halduomp/mips/xxinithl.c b/private/ntos/nthals/halduomp/mips/xxinithl.c
new file mode 100644
index 000000000..3a49aaf9c
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/xxinithl.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinithl.c"
diff --git a/private/ntos/nthals/halduomp/mips/xxinitnt.c b/private/ntos/nthals/halduomp/mips/xxinitnt.c
new file mode 100644
index 000000000..2b57adb0d
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/xxinitnt.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinitnt.c"
diff --git a/private/ntos/nthals/halduomp/mips/xxipiint.s b/private/ntos/nthals/halduomp/mips/xxipiint.s
new file mode 100644
index 000000000..266246f51
--- /dev/null
+++ b/private/ntos/nthals/halduomp/mips/xxipiint.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxipiint.s"
diff --git a/private/ntos/nthals/halduomp/sources b/private/ntos/nthals/halduomp/sources
new file mode 100644
index 000000000..7adda85a4
--- /dev/null
+++ b/private/ntos/nthals/halduomp/sources
@@ -0,0 +1,92 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halduomp
+TARGETPATH=\nt\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_DUO_
+
+INCLUDES=..\x86new;..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILE0=$(SOURCES)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/haleagle/hal.rc b/private/ntos/nthals/haleagle/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haleagle/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haleagle/makefile b/private/ntos/nthals/haleagle/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haleagle/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haleagle/ppc/ctrlops.c b/private/ntos/nthals/haleagle/ppc/ctrlops.c
new file mode 100644
index 000000000..f921d2ed6
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/ctrlops.c
@@ -0,0 +1,471 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ ctrlops.c
+
+Abstract:
+
+ This module implements the code to emulate call, retunr, and various
+ control operations.
+
+Author:
+
+ David N. Cutler (davec) 10-Nov-1994
+
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Scott Geranen 5-Mar-1996 Added hooks for System BIOS emulation
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+#include "sysbios.h"
+
+VOID
+XmCallOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a call opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Target;
+ ULONG Source;
+
+ //
+ // Save the target address, push the current segment, if required, and
+ // push the current IP, set the destination segment, if required, and
+ // set the new IP.
+ //
+
+ Target = P->DstValue.Long;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if ((P->CurrentOpcode == 0x9a) || (P->FunctionIndex != X86_CALL_OP)) {
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+ P->SegmentRegister[CS] = P->DstSegment;
+
+ } else {
+ XmPushStack(P, P->Eip);
+ }
+
+ P->Eip = Target;
+ XmTraceJumps(P);
+ return;
+}
+
+VOID
+XmEnterOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an enter opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Allocate;
+ ULONG Frame;
+ ULONG Number;
+
+ //
+ // set the number of bytes to allocate on the stack and the number
+ // of nesting levels.
+ //
+
+ Allocate = P->SrcValue.Long;
+ Number = P->DstValue.Long;
+
+ //
+ // Set the data type and save the frame pointer on the stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ XmPushStack(P, P->Gpr[EBP].Exx);
+ Frame = P->Gpr[ESP].Exx;
+
+ } else {
+ P->DataType = WORD_DATA;
+ XmPushStack(P, P->Gpr[BP].Xx);
+ Frame = P->Gpr[SP].Xx;
+ }
+
+ //
+ // Save the current stack pointer and push parameters on the stack.
+ //
+
+ if (Number != 0) {
+
+ //
+ // If the level number is not one, then raise an exception.
+ //
+ // N.B. Level numbers greater than one are not supported.
+ //
+
+ if (Number != 1) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_LEVEL_NUMBER);
+ }
+
+ XmPushStack(P, Frame);
+ }
+
+ //
+ // Allocate local storage on stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->Gpr[EBP].Exx = Frame;
+ P->Gpr[ESP].Exx = P->Gpr[ESP].Exx - Allocate;
+
+ } else {
+ P->Gpr[BP].Xx = (USHORT)Frame;
+ P->Gpr[SP].Xx = (USHORT)(P->Gpr[SP].Xx - Allocate);
+ }
+
+ return;
+}
+
+VOID
+XmHltOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a hlt opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Halt instructions are not supported by the emulator.
+ //
+
+ longjmp(&P->JumpBuffer[0], XM_HALT_INSTRUCTION);
+ return;
+}
+
+VOID
+XmIntOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an int opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Number;
+ PULONG Vector;
+
+ //
+ // If the int instruction is an int 3, then set the interrupt vector
+ // to 3. Otherwise, if the int instruction is an into, then set the
+ // vector to 4 if OF is set. use the source interrupt vector.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if (P->CurrentOpcode == 0xcc) {
+ Number = 3;
+
+ } else if (P->CurrentOpcode == 0xce) {
+ if (P->Eflags.OF == 0) {
+ return;
+ }
+
+ Number = 4;
+
+ } else {
+ Number = P->SrcValue.Byte;
+ }
+
+ //
+ // If the vector number is 0x42, then nop the interrupt. This is the
+ // standard EGA video driver entry point in a PC's motherboard BIOS
+ // for which there is no code.
+ //
+
+#if !defined(_PURE_EMULATION_)
+
+ if (Number == 0x42) {
+ return;
+ }
+
+#endif
+
+ //
+ // Try to emulate a system BIOS call first.
+ //
+ if (!HalpEmulateSystemBios(P, Number)) {
+
+ //
+ // Either it isn't a BIOS call or it isn't supported.
+ // Emulate the x86 stream instead. Note that this
+ // doesn't support chained handlers.
+
+ //
+ // Push the current flags, code segment, and EIP on the stack.
+ //
+
+ XmPushStack(P, P->AllFlags);
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+
+ //
+ // Set the new coded segment and IP from the specified interrupt
+ // vector.
+ //
+
+ Vector = (PULONG)(P->TranslateAddress)(0, 0);
+ P->SegmentRegister[CS] = (USHORT)(Vector[Number] >> 16);
+ P->Eip = (USHORT)(Vector[Number] & 0xffff);
+ XmTraceJumps(P);
+ }
+
+ return;
+}
+
+VOID
+XmIretOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an iret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type and restore the return address, code segment,
+ // and flags.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ P->AllFlags = XmPopStack(P);
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
+
+VOID
+XmLeaveOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a leave opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type, restore the stack pointer, and restore the frame
+ // pointer.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ P->Gpr[ESP].Exx = P->Gpr[EBP].Exx;
+ P->Gpr[EBP].Exx = XmPopStack(P);
+
+ } else {
+ P->DataType = WORD_DATA;
+ P->Gpr[SP].Xx = P->Gpr[BP].Xx;
+ P->Gpr[BP].Xx = (USHORT)XmPopStack(P);
+ }
+
+ return;
+}
+
+VOID
+XmRetOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a ret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Adjust;
+
+ //
+ // Compute the number of bytes that are to be removed from the stack
+ // after having removed the return address and optionally the new CS
+ // segment value.
+ //
+
+ if ((P->CurrentOpcode & 0x1) == 0) {
+ Adjust = XmGetWordImmediate(P);
+
+ } else {
+ Adjust = 0;
+ }
+
+ //
+ // Remove the return address from the stack and set the new IP.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+
+ //
+ // If the current opcode is a far return, then remove the new CS segment
+ // value from the stack.
+ //
+
+ if ((P->CurrentOpcode & 0x8) != 0) {
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ }
+
+ //
+ // Remove the specified number of bytes from the stack.
+ //
+
+ P->Gpr[ESP].Exx += Adjust;
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/fwnvr.c b/private/ntos/nthals/haleagle/ppc/fwnvr.c
new file mode 100644
index 000000000..859d0aef9
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/fwnvr.c
@@ -0,0 +1,1745 @@
+/*
+***********************************************************************
+** NVRAM
+***********************************************************************
+*/
+#define _NOT_HALNVR_
+
+#ifdef _HALNVR_
+#include "halp.h"
+#else
+#include "fwp.h"
+#endif /* _HALNVR_ */
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+#include "fwnvr.h"
+
+/*
+***********************************************************************
+** internal type definitions
+***********************************************************************
+*/
+typedef struct _nvrregs {
+ UCHAR reserved_0[0x74];
+ UCHAR addl; /* low half of address register */
+ UCHAR addh; /* high half of address register */
+ UCHAR polodata; /* NVRAM Data Port on Polo */
+ UCHAR sfdata; /* NVRAM Data Port on Sandalfoot */
+ UCHAR reserved_1[0x800-0x78];
+ UCHAR bb_data; /* NVRAM Data Port on BigBend (0x800) */
+ UCHAR reserved_2[0x400-1];
+ UCHAR bb_addl; /* NVRAM Lo Index Port on BigBend (0xC00) */
+ UCHAR bb_addh; /* NVRAM Hi Index Port on BigBend (0xC01) */
+
+ } NVRREGS, *PNVRREGS;
+
+typedef struct _nvr_object {
+ struct _nvr_object *self;
+ NVR_SYSTEM_TYPE systype;
+ HEADER* bhead;
+ HEADER* lhead;
+ UCHAR bend[NVSIZE*2];
+ UCHAR lend[NVSIZE*2];
+ } NVR_OBJECT, *PNVR_OBJECT;
+
+typedef NVRAM_MAP *PNVRAM_MAP;
+
+/*
+***********************************************************************
+** private macros, defines, and externs
+***********************************************************************
+*/
+extern PVOID HalpIoControlBase;
+#define NVRAM_VIRTUAL_BASE ((PUCHAR)HalpIoControlBase)
+
+#define _ppc_shortswap(_x) (((_x<<8)&0xff00)|((_x>>8)&0x00ff))
+
+#define _ppc_longswap(_x)\
+(((_x<<24)&0xff000000)|((_x<<8)&0x00ff0000)|\
+((_x>>8)&0x0000ff00)|((_x>>24)&0x000000ff))
+
+#define _toupr_(_c) (((_c >= 'a') && (_c <= 'z')) ? (_c - 'a' + 'A') : _c)
+
+#define MAXNVRFETCH NVSIZE*2
+
+/*
+***********************************************************************
+** prototypes of private methods
+** (prototypes of public methods are defined in fwnvr.h)
+***********************************************************************
+*/
+
+VOID nvr_clear_nvram(PNVR_OBJECT);
+UCHAR nvr_read(NVR_SYSTEM_TYPE, ULONG);
+VOID nvr_write(NVR_SYSTEM_TYPE, ULONG,UCHAR);
+PNVR_OBJECT nvr_create_object(NVR_SYSTEM_TYPE);
+PNVR_OBJECT nvr_alloc(ULONG);
+VOID nvr_free(PVOID);
+VOID nvr_default_nvram(PNVR_OBJECT);
+VOID nvr_read_nvram(PNVR_OBJECT);
+VOID nvr_write_Header(PNVR_OBJECT);
+VOID nvr_swap_Header(HEADER*, HEADER*);
+VOID nvr_headb2l(PNVR_OBJECT);
+VOID nvr_headl2b(PNVR_OBJECT);
+ULONG nvr_computecrc(ULONG, UCHAR);
+USHORT nvr_calc1crc(PNVR_OBJECT);
+USHORT nvr_calc2crc(PNVR_OBJECT);
+VOID nvr_read_GEArea(PNVR_OBJECT);
+VOID nvr_read_OSArea(PNVR_OBJECT);
+VOID nvr_read_CFArea(PNVR_OBJECT);
+VOID nvr_write_GEArea(PNVR_OBJECT);
+VOID nvr_write_OSArea(PNVR_OBJECT);
+VOID nvr_write_CFArea(PNVR_OBJECT);
+
+/*
+***********************************************************************
+** prototypes of private debug methods are defined below
+***********************************************************************
+*/
+//#undef KDB
+#ifdef KDB
+VOID nvr_display_object(PNVR_OBJECT);
+VOID nvr_display_lemap(PNVR_OBJECT);
+VOID nvr_display_bemap(PNVR_OBJECT);
+VOID nvr_test_setvar(VOID);
+#endif /* KDB */
+
+/*
+***********************************************************************
+** private data items - not visible to public clients
+***********************************************************************
+*/
+
+UCHAR _currentstring[MAXIMUM_ENVIRONMENT_VALUE];
+UCHAR _currentfetch[MAXNVRFETCH];
+
+#ifndef _HALNVR_
+NVR_OBJECT nvrobj;
+#endif /* _HALNVR_ */
+
+PNVR_OBJECT pnvrobj = 0;
+
+/*
+***********************************************************************
+** methods
+***********************************************************************
+*/
+
+/***********************************************************************/
+PNVR_OBJECT nvr_alloc(ULONG size)
+{
+ PNVR_OBJECT p;
+
+ p = (PNVR_OBJECT)0;
+
+#ifdef _HALNVR_
+ /* use HAL memory allocation here */
+ p = ExAllocatePool(NonPagedPool, size);
+ return(p);
+#else
+ /* use ARC FW memory allocation here */
+ p = &nvrobj;
+ return(p);
+#endif /* _HALNVR_ */
+}
+
+/***********************************************************************/
+VOID nvr_free(PVOID p)
+{
+ if (p == (PVOID)NULL)
+ return;
+
+#ifdef _HALNVR_
+ /* use HAL memory deallocation here */
+ ExFreePool(p);
+#endif /* _HALNVR_ */
+
+ return;
+}
+
+/***********************************************************************/
+UCHAR nvr_read(NVR_SYSTEM_TYPE st, ULONG addr)
+{
+ UCHAR uc;
+ UCHAR hi_index, lo_index;
+ PNVRREGS nvp = (PNVRREGS)NVRAM_VIRTUAL_BASE;
+ lo_index = (UCHAR)(addr & 0xff);
+ hi_index = (UCHAR)((addr >> 8) & 0x1f);
+ switch (st) {
+ case nvr_systype_bigbend:
+ WRITE_REGISTER_UCHAR(&nvp->bb_addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->bb_addh, hi_index);
+ break;
+ default:
+ WRITE_REGISTER_UCHAR(&nvp->addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->addh, hi_index);
+ break;
+ }
+#ifndef _HALNVR_
+ Eieio();
+#endif /* _HALNVR_ */
+
+ switch (st) {
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ uc = READ_REGISTER_UCHAR(&nvp->sfdata);
+ break;
+ case nvr_systype_bigbend:
+ uc = READ_REGISTER_UCHAR(&nvp->bb_data);
+ break;
+ case nvr_systype_polo:
+ case nvr_systype_woodfield:
+ uc = READ_REGISTER_UCHAR(&nvp->polodata);
+ break;
+ default:
+ uc = 0;
+ break;
+ }
+
+ return(uc);
+}
+
+/***********************************************************************/
+VOID nvr_write(NVR_SYSTEM_TYPE st, ULONG addr, UCHAR data)
+{
+ UCHAR hi_index, lo_index;
+ PNVRREGS nvp = (PNVRREGS)NVRAM_VIRTUAL_BASE;
+
+ lo_index = (UCHAR)(addr & 0xff);
+ hi_index = (UCHAR)((addr >> 8) & 0x1f);
+ switch (st) {
+ case nvr_systype_bigbend:
+ WRITE_REGISTER_UCHAR(&nvp->bb_addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->bb_addh, hi_index);
+ break;
+ default:
+ WRITE_REGISTER_UCHAR(&nvp->addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->addh, hi_index);
+ break;
+ }
+#ifndef _HALNVR_
+ Eieio();
+#endif /* _HALNVR_ */
+
+ switch (st) {
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ WRITE_REGISTER_UCHAR(&nvp->sfdata, data);
+ break;
+ case nvr_systype_bigbend:
+ WRITE_REGISTER_UCHAR(&nvp->bb_data, data);
+ break;
+ case nvr_systype_polo:
+ case nvr_systype_woodfield:
+ WRITE_REGISTER_UCHAR(&nvp->polodata, data);
+ break;
+ default:
+ break;
+ }
+
+#ifndef _HALNVR_
+ Eieio();
+#endif /* _HALNVR_ */
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_swap_Header(HEADER* dest, HEADER* src)
+{
+ ULONG i;
+ PUCHAR cp;
+
+ /* validate pointers */
+ if ((dest == NULL) || (src == NULL))
+ return;
+
+ dest->Size = _ppc_shortswap(src->Size);
+ dest->Version = src->Version;
+ dest->Revision = src->Revision;
+ dest->Crc1 = _ppc_shortswap(src->Crc1);
+ dest->Crc2 = _ppc_shortswap(src->Crc2);
+ dest->LastOS = src->LastOS;
+ dest->Endian = src->Endian;
+ dest->OSAreaUsage = src->OSAreaUsage;
+ dest->PMMode = src->PMMode;
+
+ /* convert NVRRESTART_BLOCK structure of Header */
+ dest->ResumeBlock.CheckSum = _ppc_longswap(src->ResumeBlock.CheckSum);
+ dest->ResumeBlock.BootStatus = _ppc_longswap(src->ResumeBlock.BootStatus);
+ dest->ResumeBlock.ResumeAddr =
+ (VOID *) _ppc_longswap((ULONG)src->ResumeBlock.ResumeAddr);
+ dest->ResumeBlock.SaveAreaAddr =
+ (VOID *) _ppc_longswap((ULONG)src->ResumeBlock.SaveAreaAddr);
+ dest->ResumeBlock.SaveAreaLength =
+ _ppc_longswap((ULONG)src->ResumeBlock.SaveAreaLength);
+ dest->ResumeBlock.HibResumeImageRBA =
+ _ppc_longswap((ULONG)src->ResumeBlock.HibResumeImageRBA);
+ dest->ResumeBlock.HibResumeImageRBACount =
+ _ppc_longswap((ULONG)src->ResumeBlock.HibResumeImageRBACount);
+ dest->ResumeBlock.Reserved =
+ _ppc_longswap((ULONG)src->ResumeBlock.Reserved);
+
+ /* convert SECURITY structure */
+ dest->Security.BootErrCnt =
+ _ppc_longswap(src->Security.BootErrCnt);
+ dest->Security.ConfigErrCnt =
+ _ppc_longswap(src->Security.ConfigErrCnt);
+ dest->Security.BootErrorDT[0] =
+ _ppc_longswap(src->Security.BootErrorDT[0]);
+ dest->Security.BootErrorDT[1] =
+ _ppc_longswap(src->Security.BootErrorDT[1]);
+ dest->Security.ConfigErrorDT[0] =
+ _ppc_longswap(src->Security.ConfigErrorDT[0]);
+ dest->Security.ConfigErrorDT[1] =
+ _ppc_longswap(src->Security.ConfigErrorDT[1]);
+ dest->Security.BootCorrectDT[0] =
+ _ppc_longswap(src->Security.BootCorrectDT[0]);
+ dest->Security.BootCorrectDT[1] =
+ _ppc_longswap(src->Security.BootCorrectDT[1]);
+ dest->Security.ConfigCorrectDT[0] =
+ _ppc_longswap(src->Security.ConfigCorrectDT[0]);
+ dest->Security.ConfigCorrectDT[1] =
+ _ppc_longswap(src->Security.ConfigCorrectDT[1]);
+ dest->Security.BootSetDT[0] =
+ _ppc_longswap(src->Security.BootSetDT[0]);
+ dest->Security.BootSetDT[1] =
+ _ppc_longswap(src->Security.BootSetDT[1]);
+ dest->Security.ConfigSetDT[0] =
+ _ppc_longswap(src->Security.ConfigSetDT[0]);
+ dest->Security.ConfigSetDT[1] =
+ _ppc_longswap(src->Security.ConfigSetDT[1]);
+ for (i = 0; i < 16; i++)
+ dest->Security.Serial[i] = src->Security.Serial[i];
+
+ /* convert ERROR_LOG 0 and ERROR_LOG 1 structure */
+ for (i = 0; i < 40; i++) {
+ dest->ErrorLog[0].ErrorLogEntry[i] = src->ErrorLog[0].ErrorLogEntry[i];
+ dest->ErrorLog[1].ErrorLogEntry[i] = src->ErrorLog[1].ErrorLogEntry[i];
+ }
+
+ /* convert remainder of Header */
+ dest->GEAddress = (VOID *) _ppc_longswap((ULONG)src->GEAddress);
+ dest->GELength = _ppc_longswap(src->GELength);
+ dest->GELastWriteDT[0] = _ppc_longswap(src->GELastWriteDT[0]);
+ dest->GELastWriteDT[1] = _ppc_longswap(src->GELastWriteDT[1]);
+
+ dest->ConfigAddress =
+ (VOID *)_ppc_longswap((ULONG)src->ConfigAddress);
+ dest->ConfigLength = _ppc_longswap(src->ConfigLength);
+ dest->ConfigLastWriteDT[0] =
+ _ppc_longswap(src->ConfigLastWriteDT[0]);
+ dest->ConfigLastWriteDT[1] =
+ _ppc_longswap(src->ConfigLastWriteDT[1]);
+ dest->ConfigCount = _ppc_longswap(src->ConfigCount);
+
+ dest->OSAreaAddress =
+ (VOID *)_ppc_longswap((ULONG)src->OSAreaAddress);
+ dest->OSAreaLength = _ppc_longswap(src->OSAreaLength);
+ dest->OSAreaLastWriteDT[0] =
+ _ppc_longswap(src->OSAreaLastWriteDT[0]);
+ dest->OSAreaLastWriteDT[1] =
+ _ppc_longswap(src->OSAreaLastWriteDT[1]);
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_headb2l(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER *dest;
+ HEADER *src;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ dest = (HEADER*)p->lend;
+ src = (HEADER*)p->bend;
+
+ nvr_swap_Header(dest, src);
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_headl2b(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER *dest;
+ HEADER *src;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ dest = (HEADER*)p->bend;
+ src = (HEADER*)p->lend;
+
+ nvr_swap_Header(dest, src);
+
+ return;
+}
+
+/*
+***********************************************************************
+** the following attempts to protect operation from faulty
+** intitialization of NVRAM by early versions of the machine FW
+***********************************************************************
+*/
+#define GEASIZE (NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER))
+VOID nvr_default_nvram(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER* bethp;
+
+#ifdef KDB
+DbgPrint("************** nvr_default_nvram: entry\n");
+#endif /* KDB */
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* clear the chip memory */
+ nvr_clear_nvram(p);
+
+ cp = (PUCHAR)p->bend;
+ bethp = (HEADER *) cp;
+ /* clear internal header */
+ for (i = 0; i < sizeof(HEADER); i++)
+ *cp++ = 0;
+
+ /* clear internal data areas */
+ for (i = 0; i < (NVSIZE*2); i++)
+ p->bend[i] = p->lend[i] = 0;
+
+ /* initialize size according to what we know about type */
+ if (p->systype == nvr_systype_polo)
+ bethp->Size = _ppc_shortswap((USHORT)8);
+ else if (p->systype == nvr_systype_woodfield)
+ bethp->Size = _ppc_shortswap((USHORT)8);
+ else
+ bethp->Size = _ppc_shortswap((USHORT)4);
+ bethp->Endian = 'B';
+
+ /* init the header to default values */
+ if (_ppc_shortswap((USHORT)bethp->Size) == 8) {
+ /* size of NVRAM is 8k */
+ if (_ppc_longswap((ULONG)bethp->GEAddress) == 0) {
+ bethp->GEAddress = (VOID *)_ppc_longswap((ULONG)sizeof(HEADER));
+ bethp->GELength = _ppc_longswap((ULONG)GEASIZE+NVSIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->OSAreaAddress) == 0) {
+ bethp->OSAreaAddress =
+ (VOID *)_ppc_longswap((ULONG)((NVSIZE*2)-(CONFSIZE+OSAREASIZE)));
+ bethp->OSAreaLength =
+ _ppc_longswap((ULONG)OSAREASIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->ConfigAddress) == 0) {
+ bethp->ConfigAddress = (VOID *)_ppc_longswap((ULONG)(NVSIZE*2));
+ bethp->ConfigLength = _ppc_longswap((ULONG)0);
+ }
+ }
+ else {
+ /* size is assumed to be 4k */
+ if (_ppc_longswap((ULONG)bethp->GEAddress) == 0) {
+ bethp->GEAddress = (VOID *)_ppc_longswap((ULONG)sizeof(HEADER));
+ bethp->GELength = _ppc_longswap((ULONG)GEASIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->OSAreaAddress) == 0) {
+ bethp->OSAreaAddress =
+ (VOID *)_ppc_longswap((ULONG)(NVSIZE-(CONFSIZE+OSAREASIZE)));
+ bethp->OSAreaLength =
+ _ppc_longswap((ULONG)OSAREASIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->ConfigAddress) == 0) {
+ bethp->ConfigAddress = (VOID *)_ppc_longswap((ULONG)NVSIZE);
+ bethp->ConfigLength = _ppc_longswap((ULONG)0);
+ }
+ }
+
+ /* transfer data to little endian (internal) side */
+ nvr_headb2l(p);
+
+ /* write the default header to chip memory */
+ nvr_write_Header(p);
+
+#ifdef KDB
+DbgPrint("************** nvr_default_nvram: exit\n");
+#endif /* KDB */
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_nvram(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER* hp;
+ USHORT us;
+ USHORT tmp;
+
+#ifdef KDB
+ DbgPrint("enter nvr_read_nvram\n");
+#endif /* KDB */
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* read data from the NVRAM chip */
+ hp = p->bhead;
+ cp = (PUCHAR)p->bend;
+ for (i = 0; i < sizeof(HEADER); i++)
+ *cp++ = nvr_read(p->systype,i);
+
+#ifdef KDB
+DbgPrint("IMMEDIATELY AFTER READ HEADER - NO DATA AREAS READ\n");
+nvr_display_bemap(p);
+#endif /* KDB */
+
+ if ((hp->Endian != 'B') && (hp->Endian != 'L')) {
+#ifdef KDB
+DbgPrint("BAD ENDIAN\n");
+#endif /* KDB */
+ nvr_default_nvram(p);
+ return;
+ }
+
+ /* convert big endian to little endian */
+ nvr_headb2l(p);
+
+ /* read in data areas */
+ nvr_read_GEArea(p);
+ nvr_read_OSArea(p);
+ nvr_read_CFArea(p);
+
+#ifdef KDB
+DbgPrint("After Areas\n");
+#endif /* KDB */
+
+ /* check valid checksum 1 */
+ us = _ppc_shortswap(hp->Crc1);
+ tmp = nvr_calc1crc(p);
+ if (tmp != us) {
+#ifdef KDB
+ DbgPrint("BADCRC1 nvr_read_nvram: orgcrc1: 0x%08x calccrc1: 0x%08x\n",
+ (int)us, (int)tmp);
+#endif /* KDB */
+ nvr_default_nvram(p);
+ return;
+ }
+
+#ifdef KDB
+DbgPrint("After CRC1\n");
+#endif /* KDB */
+
+#if 0 // Don't let a bad CRC #2 bother us
+ /* check valid checksum 2 */
+ us = _ppc_shortswap(hp->Crc2);
+ tmp = nvr_calc2crc(p);
+ if (tmp != us) {
+#ifdef KDB
+ DbgPrint("BADCRC2 nvr_read_nvram: orgcrc2: 0x%08x calccrc2: 0x%08x\n",
+ (int)us, (int)tmp);
+#endif /* KDB */
+ nvr_default_nvram(p);
+ return;
+ }
+
+#ifdef KDB
+DbgPrint("After CRC2\n");
+#endif /* KDB */
+#endif
+
+#ifdef KDB
+DbgPrint("exit nvr_read_nvram: SUCCESS\n");
+#endif /* KDB */
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_Header(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ USHORT us;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* convert little endian to big endian */
+ nvr_headl2b(p);
+
+ us = nvr_calc1crc(p);
+ p->bhead->Crc1 = _ppc_shortswap(us);
+ us = nvr_calc2crc(p);
+ p->bhead->Crc2 = _ppc_shortswap(us);
+
+ /* spit out data */
+ cp = (PUCHAR)p->bend;
+ for (i = 0; i < sizeof(HEADER); i++)
+ nvr_write(p->systype, i, *cp++);
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_GEArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR lp;
+ PUCHAR bp;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* suck up global environment data */
+ /* and place it in both little and big endian sides */
+ offset = (ULONG)p->lhead->GEAddress;
+ lp = (PUCHAR)((ULONG)p->lhead + offset);
+ bp = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->GELength; i++, bp++, lp++) {
+ *bp = *lp = nvr_read(p->systype, offset + i);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_OSArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR lp;
+ PUCHAR bp;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* suck up OS specific data */
+ /* and place it in both little and big endian sides */
+ offset = (ULONG)p->lhead->OSAreaAddress;
+ lp = (PUCHAR)((ULONG)p->lhead + offset);
+ bp = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->OSAreaLength; i++, bp++, lp++) {
+ *bp = *lp = nvr_read(p->systype, offset + i);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_CFArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR lp;
+ PUCHAR bp;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* suck up configuration data */
+ offset = (ULONG) p->lhead->ConfigAddress;
+ lp = (PUCHAR)((ULONG)p->lhead + offset);
+ bp = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->ConfigLength; i++) {
+ bp[i] = lp[i] = nvr_read(p->systype, (offset + i));
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_GEArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR dest;
+ PUCHAR src;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->GEAddress;
+ src = (PUCHAR)((ULONG)p->lhead + offset);
+ dest = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->GELength; i++, dest++, src++)
+ *dest = *src;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p);
+
+ /* spit out global environment data */
+ src = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->GELength; i++, src++) {
+ nvr_write(p->systype, (i + offset), *src);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_OSArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ ULONG offset;
+ PUCHAR src;
+ PUCHAR dest;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG) p->lhead->OSAreaAddress;
+ src = (PUCHAR)((ULONG)p->lhead + offset);
+ dest = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->OSAreaLength; i++, dest++, src++)
+ *dest = *src;
+
+ /* spit out OS specific data */
+ /* header not needed - no crc for OS Area in Header */
+ src = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->OSAreaLength; i++, src++) {
+ nvr_write(p->systype, (i + offset), *src);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_CFArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR dest;
+ PUCHAR src;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->ConfigAddress;
+ dest = (PUCHAR)((ULONG)p->bhead + offset - 1);
+ src = (PUCHAR)((ULONG)p->lhead + offset - 1);
+ for (i = 0; i < p->lhead->ConfigLength; i++, dest--, src--)
+ *dest = *src;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p);
+
+ /* spit out configuration data */
+ src = (PUCHAR)((ULONG)p->bhead + offset - 1);
+ for (i = 1; i <= p->lhead->ConfigLength; i++, src--) {
+ nvr_write(p->systype, (i + offset), *src);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+PNVR_OBJECT nvr_create_object(NVR_SYSTEM_TYPE systemtype)
+{
+ ULONG i;
+ PUCHAR cp;
+ UCHAR pid;
+
+ pnvrobj = nvr_alloc(sizeof(NVR_OBJECT));
+
+ if (pnvrobj) {
+ /* success */
+ /* zero out input area */
+ for (i = 0, cp = (PUCHAR)pnvrobj; i < sizeof(NVR_OBJECT); i++, cp++)
+ *cp = 0;
+
+ /* initialize internal elements */
+ pnvrobj->self = pnvrobj;
+ pnvrobj->bhead = (HEADER *) pnvrobj->bend;
+ pnvrobj->lhead = (HEADER *) pnvrobj->lend;
+
+ switch (systemtype) {
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ pnvrobj->systype = nvr_systype_sandalfoot;
+ break;
+ case nvr_systype_bigbend:
+ pnvrobj->systype = nvr_systype_bigbend;
+ break;
+ case nvr_systype_polo:
+ pnvrobj->systype = nvr_systype_polo;
+ break;
+ case nvr_systype_woodfield:
+ pnvrobj->systype = nvr_systype_woodfield;
+ break;
+ default:
+ pnvrobj->systype = nvr_systype_unknown;
+ break;
+ }
+ }
+
+ return(pnvrobj);
+}
+
+/***********************************************************************/
+VOID nvr_delete_object()
+{
+ PNVR_OBJECT p = pnvrobj;
+
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ p->self = (PNVR_OBJECT)0;
+
+ (void)nvr_free(p);
+
+ pnvrobj = (PNVR_OBJECT)0;
+
+ return;
+}
+
+/***********************************************************************/
+STATUS_TYPE nvr_initialize_object(NVR_SYSTEM_TYPE systemtype)
+{
+ HEADER* hp;
+
+#ifdef KDB
+ DbgPrint("enter nvr_initialize_object\n");
+#endif /* KDB */
+
+ if (pnvrobj)
+ return(stat_exist);
+
+ /* create object or get static address */
+ if (!(pnvrobj = nvr_create_object(systemtype)))
+ return(stat_error);
+
+ /* read the header from NVRAM and convert to little endian */
+ nvr_read_nvram(pnvrobj);
+
+ return(stat_ok);
+}
+
+/***********************************************************************/
+VOID nvr_clear_nvram(PNVR_OBJECT p)
+{
+ ULONG i;
+ ULONG len;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ len = NVSIZE;
+ switch (p->systype) {
+ case nvr_systype_polo:
+ case nvr_systype_woodfield:
+ len *= 2;
+ break;
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ break;
+ case nvr_systype_delmar:
+ default:
+ break;
+ }
+
+ for (i = 0; i < len; i++) {
+ nvr_write(p->systype,i,0);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_destroy()
+{
+ NVR_SYSTEM_TYPE st;
+
+ /* validate pointer */
+ if ((pnvrobj == NULL) || (pnvrobj != pnvrobj->self))
+ return;
+
+ st = pnvrobj->systype;
+
+ nvr_delete_object();
+ nvr_initialize_object(st);
+ nvr_clear_nvram(pnvrobj);
+ nvr_delete_object();
+
+ nvr_initialize_object(st);
+
+#ifdef KDB
+ nvr_display_object(pnvrobj);
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+#endif /* KDB */
+
+ return;
+}
+
+/*
+***********************************************************************
+** Computation of CRCs must be done consistent with the approach
+** taken by the Firmware (Dakota or Open FW). The algorithm for the
+** following CRC routines (i.e., nvr_computecrc, nvr_calc1crc,
+** nvr_calc2crc were obtained from the ESW group that develops
+** Dakota FW
+**
+** If Dakota changes, then these routines may have to change also.
+**
+** 07.21.94
+***********************************************************************
+*/
+
+#define rol(x,y) ( ( ((x)<<(y)) | ((x)>>(16 - (y))) ) & 0x0FFFF)
+#define ror(x,y) ( ( ((x)>>(y)) | ((x)<<(16 - (y))) ) & 0x0FFFF)
+
+ULONG nvr_computecrc(ULONG oldcrc, UCHAR data)
+{
+ ULONG pd, crc;
+
+ pd = ((oldcrc>>8) ^ data) << 8;
+
+ crc = 0xFF00 & (oldcrc << 8);
+ crc |= pd >> 8;
+ crc ^= rol(pd,4) & 0xF00F;
+ crc ^= ror(pd,3) & 0x1FE0;
+ crc ^= pd & 0xF000;
+ crc ^= ror(pd,7) & 0x01E0;
+ return crc;
+}
+
+USHORT nvr_calc1crc(PNVR_OBJECT p)
+{
+ ULONG ul;
+ ULONG i;
+ PUCHAR cp;
+ ULONG len1;
+ ULONG len2;
+ USHORT us;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return(0);
+
+ ul = 0x0ffff;
+
+ // do not include current Crc1/Crc2 in checksum
+ len1 = (sizeof(p->bhead->Size) +
+ sizeof(p->bhead->Version) +
+ sizeof(p->bhead->Revision));
+ len2 = (ULONG) p->lhead->OSAreaAddress;
+
+
+ // calculate the area before Crc1/Crc2 in the header
+ for (cp = (PUCHAR)p->bhead, i = 0; i < len1; i++)
+ ul = nvr_computecrc(ul, cp[i]);
+
+ // advance to calculate the area after Crc1, Crc2, and LastOS
+ // to include the region up to the OSArea
+ i += (sizeof(p->bhead->Crc1) + sizeof(p->bhead->Crc2)) + 1;
+ for (i = i; i < len2; i++)
+ ul = nvr_computecrc(ul, cp[i]);
+
+ us = (USHORT)(ul & 0x0ffff);
+
+ return(us);
+}
+
+USHORT nvr_calc2crc(PNVR_OBJECT p)
+{
+ ULONG ul;
+ PUCHAR cp;
+ PUCHAR end;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return 0;
+
+ ul = 0x0ffff;
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress);
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) - 1));
+ for (; cp < end; cp++)
+ ul = nvr_computecrc(ul, *cp);
+
+ return((USHORT)(ul & 0x0ffff));
+}
+
+/*
+***********************************************************************
+** Computation of CRCs must be done consistent with the approach
+** taken by the Firmware (Dakota or Open FW). The algorithm for the
+** above CRC routines (i.e., nvr_computecrc, nvr_calc1crc,
+** nvr_calc2crc were obtained from the ESW group that develops
+** Dakota FW
+**
+** 07.21.94
+***********************************************************************
+*/
+
+/*
+***********************************************************************
+** ----------- Methods Public to the higher layers of SW -------------
+** The methods below operate on the little endian section of the
+** data structure internal to this file. Little endian is the internal
+** (volatile RAM) representation of the NVRAM contents. All access to
+** NVRAM data (variables, etc) are performed on this internal
+** representation. When necessary, the internal representation is
+** downloaded back to NVRAM.
+***********************************************************************
+*/
+
+VOID nvr_print_object()
+{
+#ifdef KDB
+ nvr_display_object(pnvrobj);
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+#endif /* KDB */
+ return;
+}
+
+STATUS_TYPE nvr_find_OS_variable(PUCHAR var, PULONG ni, PULONG vi)
+{
+ PUCHAR lvar;
+ PUCHAR cp;
+ ULONG i;
+ PNVRAM_MAP little_nvrmap;
+
+ if (*var == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ little_nvrmap = (PNVRAM_MAP)pnvrobj->lend;
+
+ i = 0;
+ while (TRUE) {
+ lvar = var;
+ *ni = i;
+ cp = (PUCHAR)((ULONG)little_nvrmap +
+ (ULONG)(little_nvrmap->Header.OSAreaAddress));
+
+ /* does the variable we want start at this index? */
+ while (i < little_nvrmap->Header.OSAreaLength) {
+ /* break if mismatch */
+ if (_toupr_(cp[i]) != _toupr_(*lvar))
+ break;
+ lvar++;
+ i++;
+ }
+
+ /* if we're at the end of OSArea and var has a match */
+ if ((*lvar == 0) && (cp[i] == '=')) {
+ *vi = ++i;
+ return(stat_ok);
+ }
+
+ /* no match - set index to start of the next variable */
+ if (i >= little_nvrmap->Header.OSAreaLength)
+ return(stat_error);
+ while (cp[i++] != 0) {
+ if (i >= little_nvrmap->Header.OSAreaLength)
+ return(stat_error);
+ }
+ }
+}
+
+STATUS_TYPE nvr_find_GE_variable(PUCHAR var, PULONG ni, PULONG vi)
+{
+ PUCHAR lvar;
+ PUCHAR cp;
+ ULONG i;
+ HEADER* lhp;
+
+ if (*var == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+
+ i = 0;
+ while (TRUE) {
+ lvar = var;
+ *ni = i;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)(lhp->GEAddress));
+
+ /* does the variable we want start at this index? */
+ while (i < lhp->GELength) {
+ /* break if mismatch */
+ if (_toupr_(cp[i]) != _toupr_(*lvar))
+ break;
+ lvar++;
+ i++;
+ }
+
+ /* if we're at the end of GEArea and var has a match */
+ if ((*lvar == 0) && (cp[i] == '=')) {
+ *vi = ++i;
+ return(stat_ok);
+ }
+
+ /* no match - set index to start of the next variable */
+ if (i >= lhp->GELength)
+ return(stat_error);
+ while (cp[i++] != 0) {
+ if (i >= lhp->GELength)
+ return(stat_error);
+ }
+ }
+}
+
+PUCHAR nvr_get_OS_variable(PUCHAR vname)
+{
+ ULONG ni;
+ ULONG vi;
+ ULONG i;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return((PUCHAR)NULL);
+
+ if (nvr_find_OS_variable(vname, &ni, &vi) != stat_ok)
+ return((PUCHAR)NULL);
+
+ little_nvrmap = (PNVRAM_MAP)pnvrobj->lend;
+
+ for (i = 0; i < MAXIMUM_ENVIRONMENT_VALUE - 1; i++) {
+ if (little_nvrmap->OSArea[vi] == 0)
+ break;
+ _currentstring[i] = little_nvrmap->OSArea[vi++];
+ }
+ _currentstring[i] = 0;
+
+ return(_currentstring);
+}
+
+PUCHAR nvr_get_GE_variable(PUCHAR vname)
+{
+ ULONG ni;
+ ULONG vi;
+ ULONG i;
+ PUCHAR cp;
+ HEADER* lhp;
+
+ if (!pnvrobj)
+ return((PUCHAR)NULL);
+
+ if (nvr_find_GE_variable(vname, &ni, &vi) != stat_ok)
+ return((PUCHAR)NULL);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress);
+
+ for (i = 0; i < MAXIMUM_ENVIRONMENT_VALUE - 1; i++) {
+ if (cp[vi] == 0) {
+ break;
+ }
+ _currentstring[i] = cp[vi++];
+ }
+ _currentstring[i] = 0;
+
+#ifdef KDB
+DbgPrint("get_GE vname: '%s' value: '%s'\n", vname, _currentstring);
+#endif /* KDB */
+
+ return(_currentstring);
+}
+
+STATUS_TYPE nvr_set_OS_variable(PUCHAR vname, PUCHAR value)
+{
+ ULONG nameindex;
+ ULONG valueindex;
+ ULONG eos;
+ PUCHAR str;
+ ULONG count;
+ CHAR c;
+ PUCHAR aptr;
+ HEADER* lhp;
+
+ if ((vname == 0) || (value == 0))
+ return(stat_error);
+
+ if (*vname == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+
+#ifdef KDB
+DbgPrint("OS vname: '%s' value: '%s'\n", vname, value);
+#endif /* KDB */
+
+ /* initialize pointer to OS area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->OSAreaAddress);
+
+ // find the end of the used OS space by looking for
+ // the first non-null character from the top
+ eos = lhp->OSAreaLength - 1;
+ while (aptr[--eos] == 0) {
+ if (eos == 0)
+ break;
+ }
+
+ // position eos to the first new character, unless
+ // environment space is empty
+ if (eos != 0)
+ eos += 2;
+
+ // find out if the variable already has a value
+ count = lhp->OSAreaLength - eos;
+ if (nvr_find_OS_variable(vname, &nameindex, &valueindex) == stat_ok) {
+ // count free space
+ // start with the free area at the top and add
+ // the old nameindex value
+ for (str = &(aptr[valueindex]); *str != 0; str++)
+ count++;
+
+ // if free area is not large enough to handle new value return error
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+
+ // pack strings
+ // first move valueindex to the end of the value
+ while (aptr[valueindex++] != 0)
+ ;
+
+ // now move everything to where the variable starts
+ // covering up the old name/value pair
+ while (valueindex < eos) {
+ c = aptr[valueindex++];
+ aptr[nameindex++] = c;
+ }
+
+ // adjust new top of environment
+ eos = nameindex;
+
+ // zero to the end of OS area
+ while (nameindex < lhp->OSAreaLength)
+ aptr[nameindex++] = 0;
+ }
+ else {
+ // variable is new
+ // if free area is not large enough to handle new value return error
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+ }
+
+ /* if value is null, we have removed the variable */
+ if (*value) {
+ // insert new name, converting to upper case.
+ while (*vname != 0) {
+ aptr[eos++] = _toupr_(*vname);
+ vname++;
+ }
+ aptr[eos++] = '=';
+
+ // insert new value
+ while (*value != 0) {
+ aptr[eos++] = *value;
+ value++;
+ }
+ }
+
+ nvr_write_OSArea(pnvrobj);
+
+ return(stat_ok);
+}
+
+STATUS_TYPE nvr_set_GE_variable(PUCHAR vname, PUCHAR value)
+{
+ ULONG nameindex;
+ ULONG valueindex;
+ ULONG toe;
+ PUCHAR str;
+ ULONG count;
+ CHAR c;
+ PUCHAR aptr;
+ HEADER* lhp;
+
+ if (vname == 0)
+ return(stat_error);
+
+ if (*vname == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+
+#ifdef KDB
+DbgPrint("set_GE vname: '%s' value: '%s'\n", vname, value);
+#endif /* KDB */
+
+ /* initialize pointer to OS area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress);
+
+ /* find the top of the used environment space by looking for */
+ /* the first non-null character from the top */
+ toe = lhp->GELength - 1;
+
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress);
+ while (aptr[--toe] == 0) {
+ if (toe == 0)
+ break;
+ }
+
+ /* adjust toe to the first new character, unless */
+ /* environment space is empty */
+ if (toe != 0)
+ toe += 2;
+
+ /* find out if the variable already has a value */
+ count = lhp->GELength - toe;
+ if (nvr_find_GE_variable(vname, &nameindex, &valueindex) == stat_ok) {
+ /* count free space */
+ /* start with the free area at the top and add */
+ /* the old nameindex value */
+ for (str = &(aptr[valueindex]); *str != 0; str++)
+ count++;
+
+ /* if free area is not large enough to handle new value return error */
+ if (value) {
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+ }
+
+ /* pack strings */
+ /* first move valueindex to the end of the value */
+ while (aptr[valueindex++] != 0)
+ ;
+
+ /* now move everything to where the variable starts */
+ /* covering up the old name/value pair */
+ while (valueindex < toe) {
+ c = aptr[valueindex++];
+ aptr[nameindex++] = c;
+ }
+
+ /* adjust new top of environment */
+ toe = nameindex;
+
+ /* zero to the end of GE area */
+ while (nameindex < lhp->GELength)
+ aptr[nameindex++] = 0;
+ }
+ else {
+ /* variable is new */
+ /* if free area is not large enough to handle new value return error */
+ if (value) {
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+ }
+ }
+
+ /* if value is null or is a pointer to a 0 */
+ /* the variable has been removed */
+ if ((value) && (*value)) {
+ /* insert new name, converting to upper case */
+ while (*vname != 0) {
+ aptr[toe] = _toupr_(*vname);
+ vname++;
+ toe++;
+ }
+ aptr[toe++] = '=';
+
+ /* insert new value */
+ while (*value != 0) {
+ aptr[toe] = *value;
+ value++;
+ toe++;
+ }
+ }
+
+ nvr_write_GEArea(pnvrobj);
+
+ return(stat_ok);
+}
+
+PUCHAR nvr_fetch_GE()
+{
+ ULONG i;
+ ULONG toe;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return NULL;
+
+ little_nvrmap = (NVRAM_MAP *)pnvrobj->lend;
+
+ // initialize hold buffer to zeros
+ for (i = 0; i < little_nvrmap->Header.GELength; i++)
+ _currentfetch[i] = 0;
+
+ // find the top of the used environment space by looking for
+ // the first non-null character from the top
+ toe = little_nvrmap->Header.GELength - 1;
+ while ((little_nvrmap->GEArea[--toe]) == 0) {
+ if (toe == 0)
+ break;
+ }
+
+ // toe contains last index of GE
+ if (toe == 0)
+ return(_currentfetch);
+
+ // copy from GE to hold buffer
+ for (i = 0; ((i <= toe) && (i < MAXNVRFETCH)); i++)
+ _currentfetch[i] = little_nvrmap->GEArea[i];
+
+ return(_currentfetch);
+}
+
+PUCHAR nvr_fetch_OS()
+{
+ ULONG i;
+ ULONG toe;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return NULL;
+
+ little_nvrmap = (NVRAM_MAP *)pnvrobj->lend;
+
+ // initialize the hold buffer to zeros
+ for (i = 0; i < little_nvrmap->Header.OSAreaLength; i++)
+ _currentfetch[i] = 0;
+
+ // find the top of the used environment space by looking for
+ // the first non-null character from the top
+ toe = little_nvrmap->Header.OSAreaLength - 1;
+ while ((little_nvrmap->OSArea[--toe]) == 0) {
+ if (toe == 0)
+ break;
+ }
+
+ // toe contains last index of OS
+ if (toe == 0)
+ return(_currentfetch);
+
+ // copy from OS to hold buffer
+ for (i = 0; ((i <= toe) && (i < MAXNVRFETCH)); i++)
+ _currentfetch[i] = little_nvrmap->OSArea[i];
+
+ return(_currentfetch);
+}
+
+PUCHAR nvr_fetch_CF()
+{
+ ULONG i;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return NULL;
+
+ little_nvrmap = (NVRAM_MAP *)pnvrobj->lend;
+
+ /* initialize the hold buffer to zeros */
+ for (i = 0; i < MAXNVRFETCH; i++)
+ _currentfetch[i] = 0;
+
+ /* copy from Config to hold buffer */
+ for (i = 0; i < little_nvrmap->Header.ConfigLength; i++)
+ _currentfetch[i] = little_nvrmap->ConfigArea[i];
+
+ return(_currentfetch);
+}
+
+/*
+***********************************************************************
+** ----------- Methods Public to the higher layers of SW -------------
+** The methods above operate on the little endian section of the
+** data structure internal to this file. Little endian is the internal
+** (volatile RAM) representation of the NVRAM contents. All access to
+** NVRAM data (variables, etc) are performed on this internal
+** representation. When necessary, the internal representation is
+** downloaded back to NVRAM.
+***********************************************************************
+*/
+
+#ifdef KDB
+/*
+***********************************************************************
+** The methods below are used in development and debug.
+***********************************************************************
+*/
+
+VOID nvr_display_object(PNVR_OBJECT p)
+{
+ PUCHAR cp;
+ int len;
+ UCHAR tmp;
+ PNVRAM_MAP mp;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ DbgPrint(" ---- ---- INTERNAL DISPLAY ---- ----\n\r");
+ DbgPrint(" Object Addr: 0x%08lx\n\r",(ULONG)p->self);
+ switch (p->systype) {
+ case nvr_systype_powerstack:
+ DbgPrint(" System Type: PowerStack\n\r");
+ break;
+ case nvr_systype_sandalfoot:
+ DbgPrint(" System Type: Sandalfoot\n\r");
+ break;
+ case nvr_systype_polo:
+ DbgPrint(" System Type: Polo\n\r");
+ break;
+ case nvr_systype_woodfield:
+ DbgPrint(" System Type: Woodfield\n\r");
+ break;
+ case nvr_systype_delmar:
+ DbgPrint(" System Type: Delmar\n\r");
+ break;
+ default:
+ DbgPrint(" System Type: Unknown\n\r");
+ break;
+ }
+ DbgPrint(" BE Header addr: 0x%08lx\n\r",(ULONG)p->bhead);
+ DbgPrint(" BE Map addr: 0x%08lx\n\r",(ULONG)p->bend);
+ DbgPrint(" LE Header addr: 0x%08lx\n\r",(ULONG)p->lhead);
+ DbgPrint(" LE Map addr: 0x%08lx\n\r",(ULONG)p->lend);
+ DbgPrint(" ---- ---- INTERNAL DISPLAY ---- ----\n\r");
+
+ return;
+}
+
+VOID nvr_display_lemap(PNVR_OBJECT p)
+{
+ PUCHAR cp;
+ PUCHAR max;
+ UCHAR tmp;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ DbgPrint(" -------- ---- ---- ---- ---- LITTLE DISPLAY\n\r");
+ DbgPrint(" NVR Size: 0x%04xK (%dK)", (int)p->lhead->Size,
+ (int)p->lhead->Size);
+ DbgPrint(" Version: 0x%02x Revision: 0x%02x\n\r",
+ (int)p->lhead->Version, (int)p->lhead->Revision);
+ DbgPrint(" Crc1: 0x%04x Crc2: 0x%04x\n\r",
+ (int)p->lhead->Crc1, (int)p->lhead->Crc2);
+ DbgPrint(" NVR Endian: '%c'\n\r",p->lhead->Endian);
+
+ tmp = p->lhead->Security.Serial[15];
+ p->lhead->Security.Serial[15] = 0;
+ DbgPrint(" NVR Serial: '%s'\n\r",p->lhead->Security.Serial);
+ p->lhead->Security.Serial[15] = tmp;
+
+ DbgPrint(" GEAddress: 0x%08lx GELength: 0x%08lx\n\r",
+ (ULONG)p->lhead->GEAddress, (ULONG)p->lhead->GELength);
+ cp = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->GEAddress);
+ max = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->GEAddress +
+ (ULONG)p->lhead->GELength);
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" OSAreaAddress: 0x%08lx OSAreaLength: 0x%08lx\n\r",
+ (ULONG)p->lhead->OSAreaAddress, (ULONG)p->lhead->OSAreaLength);
+ cp = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->OSAreaAddress);
+ max = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->OSAreaAddress +
+ (ULONG)p->lhead->OSAreaLength);
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" ConfigAddress: 0x%08lx ConfigLength: 0x%08lx Count: 0x%08lx\n\r",
+ (ULONG)p->lhead->ConfigAddress, (ULONG)p->lhead->ConfigLength,
+ (ULONG)p->lhead->ConfigCount);
+ DbgPrint(" -------- ---- ---- ---- ---- LITTLE DISPLAY\n\r");
+
+ return;
+}
+
+VOID nvr_display_bemap(PNVR_OBJECT p)
+{
+ PUCHAR cp;
+ PUCHAR max;
+ UCHAR tmp;
+ PNVRAM_MAP mp;
+ HEADER* hp;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ mp = p->bend;
+ hp = p->bhead;
+
+ DbgPrint(" ---- ---- BIG DISPLAY ---- ----\n\r");
+ DbgPrint(" NVR Size: 0x%04xK (%dK)", (int)mp->Header.Size,
+ (int)mp->Header.Size);
+ DbgPrint(" Version: 0x%02x Revision: 0x%02x\n\r",
+ (int)mp->Header.Version, (int)mp->Header.Revision);
+ DbgPrint(" Crc1: 0x%04x Crc2: 0x%04x\n\r",
+ (int)mp->Header.Crc1, (int)mp->Header.Crc2);
+ DbgPrint(" NVR Endian: '%c'\n\r",mp->Header.Endian);
+
+ tmp = mp->Header.Security.Serial[15];
+ mp->Header.Security.Serial[15] = 0;
+ DbgPrint(" NVR Serial: '%s'\n\r",mp->Header.Security.Serial);
+ mp->Header.Security.Serial[15] = tmp;
+
+ DbgPrint(" GEAddress: 0x%08lx GELength: 0x%08lx\n\r",
+ (ULONG)hp->GEAddress, (ULONG)hp->GELength);
+ cp = (PUCHAR)((ULONG)hp + _ppc_longswap((ULONG)hp->GEAddress));
+ max = (PUCHAR)((ULONG)cp + _ppc_longswap((ULONG)hp->GELength));
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" OSAreaAddress: 0x%08lx OSAreaLength: 0x%08lx\n\r",
+ (ULONG)hp->OSAreaAddress, (ULONG)hp->OSAreaLength);
+ cp = (PUCHAR)((ULONG)hp + _ppc_longswap((ULONG)hp->OSAreaAddress));
+ max = (PUCHAR)((ULONG)cp + _ppc_longswap((ULONG)hp->OSAreaLength));
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" ConfigAddress: 0x%08lx ConfigLength: 0x%08lx Count: 0x%08lx\n\r",
+ (ULONG)hp->ConfigAddress, (ULONG)hp->ConfigLength,
+ (ULONG)hp->ConfigCount);
+ DbgPrint(" ---- ---- BIG DISPLAY ---- ----\n\r");
+
+ return;
+}
+
+VOID nvr_test_setvar(VOID)
+{
+ DbgPrint("\n\r");
+ DbgPrint("--------- VARIABLE SET TEST\n\r");
+ nvr_display_lemap(pnvrobj);
+ DbgPrint("---------\n\r");
+
+ (VOID)nvr_set_GE_variable("GESLUG0","this is it");
+ (VOID)nvr_set_GE_variable("GESLUG1","NO: this is it");
+ (VOID)nvr_set_GE_variable("GESLUG2","I beg your pardon! This is it");
+
+ (VOID)nvr_set_OS_variable("OSSLUG0","multi(0)scsi(0)");
+ (VOID)nvr_set_OS_variable("OSSLUG1","multi(0)scsi(1)");
+ (VOID)nvr_set_OS_variable("OSSLUG2",
+ "multi(0)scsi(0)disk(6)rdisk(0)partition(1)");
+ nvr_display_lemap(pnvrobj);
+
+ DbgPrint("--------- VARIABLE SET TEST\n\r");
+
+ return;
+}
+
+VOID nvr_test_object(NVR_SYSTEM_TYPE systemtype)
+{
+ PUCHAR cp;
+
+ nvr_initialize_object(systemtype);
+
+ nvr_display_object(pnvrobj);
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+
+/***************************
+ cp = nvr_get_GE_variable("SYSTEMPARTITION");
+ if (cp) {
+ if (*cp == 0)
+ DbgPrint("nvr_test_object: SYSTEMPARTITION=-value zero-\n",cp);
+ else
+ DbgPrint("nvr_test_object: SYSTEMPARTITION='%s'\n",cp);
+ }
+ else
+ DbgPrint("nvr_test_object: SYSTEMPARTITION=-pointer NULL-\n");
+
+ cp = nvr_get_GE_variable("DOG000111");
+ if (cp) {
+ if (*cp == 0)
+ DbgPrint("nvr_test_object: DOG000111=-value zero-\n",cp);
+ else
+ DbgPrint("nvr_test_object: DOG000111='%s'\n",cp);
+ }
+ else
+ DbgPrint("nvr_test_object: DOG000111=-pointer NULL-\n");
+
+ DbgBreakPoint();
+ nvr_test_setvar();
+ DbgBreakPoint();
+***************************/
+
+/***************************
+ DbgPrint("--------- CLEARING NVRAM\n");
+ if (!(pnvrobj = nvr_create_object(systemtype)))
+ return;
+ nvr_clear_nvram(pnvrobj);
+ nvr_delete_object();
+ DbgPrint("--------- CLEARED NVRAM\n");
+ DbgBreakPoint();
+***************************/
+
+/***************************
+ DbgPrint("--------- REREAD NVRAM \n\r");
+ DbgPrint("---------\n");
+ DbgPrint("---------\n");
+ nvr_initialize_object(systemtype);
+ DbgPrint("nvr_calc1crc: 0x%08x\n",(int)nvr_calc1crc(pnvrobj));
+ DbgPrint("nvr_calc2crc: 0x%08x\n",(int)nvr_calc2crc(pnvrobj));
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+ DbgPrint("--- SETTING VARS\n");
+ (VOID)nvr_set_GE_variable("GESLUG0","this is it");
+ (VOID)nvr_set_GE_variable("GESLUG1"," -------- this is it --------");
+ (VOID)nvr_set_OS_variable("OSSLUG0","multi(0)scsi(0)");
+ (VOID)nvr_set_OS_variable("OSSLUG1","multi(1)scsi(1)");
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+ (VOID)nvr_set_GE_variable("GESLUG0","");
+ nvr_display_lemap(pnvrobj);
+
+ DbgPrint("---------\n");
+ DbgPrint("---------\n");
+ DbgPrint("--------- REREAD NVRAM \n\r");
+ DbgBreakPoint();
+
+***************************/
+
+ return;
+}
+#endif /* KDB */
diff --git a/private/ntos/nthals/haleagle/ppc/fwnvr.h b/private/ntos/nthals/haleagle/ppc/fwnvr.h
new file mode 100644
index 000000000..568d83f95
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/fwnvr.h
@@ -0,0 +1,37 @@
+#ifndef _FWNVR_H
+#define _FWNVR_H
+
+typedef enum _nvr_system_type {
+ nvr_systype_null = 0x00,
+ nvr_systype_unknown = 0x01,
+ nvr_systype_sandalfoot = 0x02,
+ nvr_systype_polo = 0x04,
+ nvr_systype_woodfield = 0x08,
+ nvr_systype_delmar = 0x10,
+ nvr_systype_bigbend = 0x20,
+ nvr_systype_powerstack = 0x40,
+ nvr_systype_last = 0x80
+ } NVR_SYSTEM_TYPE;
+
+STATUS_TYPE nvr_initialize_object(NVR_SYSTEM_TYPE);
+VOID nvr_delete_object(VOID);
+VOID nvr_destroy(VOID);
+STATUS_TYPE nvr_find_GE_variable(PUCHAR,PULONG,PULONG);
+STATUS_TYPE nvr_set_GE_variable(PUCHAR,PUCHAR);
+STATUS_TYPE nvr_find_OS_variable(PUCHAR,PULONG,PULONG);
+STATUS_TYPE nvr_set_OS_variable(PUCHAR,PUCHAR);
+
+PUCHAR nvr_get_GE_variable(PUCHAR);
+PUCHAR nvr_get_OS_variable(PUCHAR);
+PUCHAR nvr_fetch_GE(VOID);
+PUCHAR nvr_fetch_OS(VOID);
+PUCHAR nvr_fetch_CF(VOID);
+
+#ifdef KDB
+VOID nvr_print_object(VOID);
+VOID nvr_test_object(NVR_SYSTEM_TYPE);
+#endif /* KDB */
+
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+
+#endif /* _FWNVR_H */
diff --git a/private/ntos/nthals/haleagle/ppc/fwstatus.h b/private/ntos/nthals/haleagle/ppc/fwstatus.h
new file mode 100644
index 000000000..fd09e6363
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/fwstatus.h
@@ -0,0 +1,17 @@
+#ifndef _FWSTATUS_H_
+#define _FWSTATUS_H_
+
+typedef enum _status_type {
+ stat_ok = 0,
+ stat_warning = 1,
+ stat_exist = 2,
+ stat_error = 3,
+ stat_badptr = 4,
+ stat_notexist = 5,
+ stat_noentry = 6,
+ stat_checksum = 7,
+ stat_badlength = 8,
+ stat_last = 0x40
+ } STATUS_TYPE;
+
+#endif /* _FWSTATUS_H_ */
diff --git a/private/ntos/nthals/haleagle/ppc/halp.h b/private/ntos/nthals/haleagle/ppc/halp.h
new file mode 100644
index 000000000..ad74517ac
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/halp.h
@@ -0,0 +1,239 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added PPC specific includes
+ Changed paramaters to HalpProfileInterrupt
+ Added function prototype for HalpWriteCompareRegisterAndClear()
+ Added include for ppcdef.h
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "hal.h"
+
+#include "ppcdef.h"
+#include "pxhalp.h"
+
+#ifndef _HALI_
+#include "..\inc\hali.h"
+#endif
+
+
+
+
+//
+// Resource usage information
+//
+
+#define MAXIMUM_IDTVECTOR 255
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+
+#define HalpGetProcessorVersion() KeGetPvr()
+
+#define HalpEnableInterrupts() _enable()
+#define HalpDisableInterrupts() _disable()
+
+#define KeFlushWriteBuffer() __builtin_eieio()
+
+//
+// Bus handlers
+//
+
+
+PBUS_HANDLER HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN BUS_DATA_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpAllocateConfigSpace HalpAllocateBusHandler
+
+#define SPRANGEPOOL NonPagedPool // for now, until crashdump is fixed
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG,
+ ULONG
+ );
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ );
+
+VOID
+HalpHandleIoError (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ );
+
+BOOLEAN
+HalpHandleProfileInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ );
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KAFFINITY HalpIsaBusAffinity;
+extern ULONG HalpProfileCount;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+
+#define IRQ_VALID 0x01
+#define IRQ_PREFERRED 0x02
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/haleagle/ppc/mk48tdc.h b/private/ntos/nthals/haleagle/ppc/mk48tdc.h
new file mode 100644
index 000000000..c98179731
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/mk48tdc.h
@@ -0,0 +1,68 @@
+/*++
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ mk48tdc.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the realtime clock on the Comet (PowerPC 603/604) platform.
+
+ This module was taken from the jazzrtc.h file and renamed.
+
+Original Author:
+
+ David N. Cutler (davec) 3-May-1991
+
+Revision History:
+
+Who When What
+--- -------- -----------------------------------------------
+dgh 07/13/94 Redefined the TODC registers for the MK48T18 chip.
+dgh 07/22/94 Update file name in header comment.
+dgh 08/03/94 Redefined virtual address of RTC and NVRAM.
+dgh 08/08/94 Don't use virtual addresses for RTC and NVRAM, use
+ offsets instead. Actual virtual address will be in
+ the HalpNvramBaseAddr variable.
+kjr 10/18/94 Changes to support Revision B Comet motherboard.
+ Remove HalpNvramBaseAddr and use new NVRAM address
+ and data port.
+
+--*/
+
+#ifndef _MK48TDC
+#define _MK48TDC
+
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x74];
+ UCHAR NvramIndexLo; // Offset 0x74
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+
+//
+// Define Realtime Clock register numbers
+// for the MK48T18 TODC Chip.
+//
+#define TODC_CONTROL 0 // TODC Control Register
+#define TODC_SECOND 1 // second of minute [0..59]
+#define TODC_MINUTE 2 // minute of hour [0..59]
+#define TODC_HOUR 3 // hour of day [0..23]
+#define TODC_DAY_OF_WEEK 4 // day of week [1..7]
+#define TODC_DAY_OF_MONTH 5 // day of month [1..31]
+#define TODC_MONTH 6 // month of year [1..12]
+#define TODC_YEAR 7 // year [00..99]
+
+
+//
+// Comet NVRAM/RTC Mapping
+//
+#define TODC_OFFSET 0x9ff8 // offset of RTC
+#define NVR_OFFSET 0x8000 // offset of NVRAM
+
+
+#endif // MK48TDC
diff --git a/private/ntos/nthals/haleagle/ppc/mk48time.c b/private/ntos/nthals/haleagle/ppc/mk48time.c
new file mode 100644
index 000000000..fe0ccf00d
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/mk48time.c
@@ -0,0 +1,431 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ mk48time.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system using the MK48T18 Clock Chip.
+
+Original Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Who When What
+--- -------- -----------------------------------------------
+dgh 07/20/94 Created from pxtime.c and modified for MK48T18 chip.
+dgh 07/22/94 Fixed typo of HalpReadRawClockRegister.
+dgh 07/29/94 Don't run the day-of-week value through the BCD
+ conversion when reading the clock. Also mask it
+ to 3-bits.
+dgh 08/08/94 Compute RTC location from HalpNvramBaseAddr and the
+ RTC offset.
+dgh 08/09/94 HalQueryRealTimeClock: Forgot to restart the clock
+ after reading it.
+kjr 10/18/94 Changes for Revision B Comet Mother Board. Remove
+ HalpNvramBaseAddr and use new NVRAM address and data
+ port.
+
+--*/
+
+#include "halp.h"
+#include "mk48tdc.h"
+#include "eisa.h"
+
+#define WRITE 0x80 // Stop update while writing control bit
+#define READ 0x40 // Stop updating while reading control bit
+#define STOP 0x80 // Clock is stopped bit
+
+extern PVOID HalpIoControlBase;
+#define RTC_BASE (TODC_OFFSET)
+#define NVRAM ((PNVRAM_CONTROL) HalpIoControlBase)
+
+//***************************************************************************
+// Time of Day Clock registers for the MK48T18 chip can be viewed as an
+// array of bytes (UCHARs) where:
+//
+// Address of Real Time Clock Register bitmap of registers
+// -----------------------------------------------------------------------
+// TODC_OFFSET + 0: clock control/calibration reg. [W R S - - - - -]
+// TODC_OFFSET + 1: seconds register (00-59) [P - - - - - - -]
+// TODC_OFFSET + 2: minutes register (00-59) [0 - - - - - - -]
+// TODC_OFFSET + 3: hours register (00-23) [0 0 - - - - - -]
+// TODC_OFFSET + 4: day-of-week register (01-07) [0 F 0 0 0 - - -]
+// TODC_OFFSET + 5: day-of-month register (01-31) [0 0 - - - - - -]
+// TODC_OFFSET + 6: month register (01-12) [0 0 0 - - - - -]
+// TODC_OFFSET + 7: year register (00-99) [- - - - - - - -]
+// W=write, R=read, S=sign, P=stop
+// F=frequency test.
+//
+// NOTE: Values in the TODC registers are in BCD format
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClockMk (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+ // NOTE: It isn't possible to test this clock chip to determine if
+ // the battery is still running or not. So we check the STOP
+ // bit and if set, then we return FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ DataByte = HalpReadRawClockRegister(TODC_SECOND);
+ if (!(DataByte & STOP)) {
+
+ //
+ // Clock is running.
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ } while (DataByte & WRITE);
+
+ //
+ // First stop the clock from being updated while we read it.
+ //
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte |= READ;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(TODC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(TODC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(TODC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(TODC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(TODC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(TODC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(TODC_SECOND);
+ TimeFields->Milliseconds = 0;
+
+ //
+ // Now restart the clock
+ //
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte &= ~READ;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClockMk (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+ // NOTE: We can't determine if the battery is running or not on
+ // this clock chip. So, instead we check the STOP bit and
+ // if set, then we treat this as the same condition and
+ // return FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(TODC_SECOND);
+ if (!(DataByte & STOP)) {
+
+ //
+ // Clock is running.
+ // Set the realtime clock to stop updating while we set
+ // the time.
+ //
+
+
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte |= WRITE;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if (TimeFields->Year > 1999)
+ HalpWriteClockRegister(TODC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ else
+ HalpWriteClockRegister(TODC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+
+ HalpWriteClockRegister(TODC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(TODC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(TODC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(TODC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(TODC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(TODC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to resume updating the time.
+ //
+
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte &= ~WRITE;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Read the specified Register from the Real Time Clock.
+ //
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexLo, (RTC_BASE + Register) & 0xFF);
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexHi, (RTC_BASE + Register) >> 8);
+ return(READ_REGISTER_UCHAR (&NVRAM->NvramData));
+}
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+
+ BcdValue = HalpReadRawClockRegister(Register);
+ //
+ // If this is NOT the day-of-week register, then
+ // convert from BCD. If it is day-of-week, then
+ // mask off to 3-bits.
+ //
+ if (Register != TODC_DAY_OF_WEEK)
+ {
+ BcdValue = ((BcdValue >> 4) & 0xf) * 10 + (BcdValue & 0xf);
+ }
+ else
+ BcdValue &= 0x07;
+
+ return BcdValue;
+}
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // Write the realtime clock register value.
+ //
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexLo, (RTC_BASE + Register) & 0xFF);
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexHi, (RTC_BASE + Register) >> 8);
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramData, Value);
+}
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+ The value is first converted to BCD format before being written to
+ the clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+ //
+ // First ensure that the value is in range 0 - 99
+ //
+ BcdValue = (((Value % 100) / 10) << 4) | (Value % 10);
+ HalpWriteRawClockRegister(Register, BcdValue);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pcibios.c b/private/ntos/nthals/haleagle/ppc/pcibios.c
new file mode 100644
index 000000000..a922c00e3
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pcibios.c
@@ -0,0 +1,1056 @@
+/*++
+
+
+Copyright (C) 1996 Motorola Inc.
+
+Module Name:
+
+ pcibios.c
+
+Abstract:
+
+ Emulate PCI BIOS functions.
+
+ Note that the HAL bus functions (HalGetBusData, etc.) are not
+ available at this phase of initialization, all of the work has
+ to be done here.
+
+Author:
+
+ Scott Geranen
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+
+#include "emulate.h"
+#include "pcibios.h"
+
+UCHAR SBReadConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+USHORT SBReadConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+ULONG SBReadConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+VOID SBWriteConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN UCHAR Data
+ );
+
+VOID SBWriteConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN USHORT Data
+ );
+
+VOID SBWriteConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN ULONG Data
+ );
+
+//
+// Last PCI bus in the system.
+//
+extern UCHAR HalpLastPciBus;
+
+//
+// Mapped I/O space.
+//
+#define CONFIG_ADDR (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress)
+#define CONFIG_DATA (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData)
+
+
+BOOLEAN
+HalpEmulatePciBios(
+ IN OUT PRXM_CONTEXT P
+ )
+/*++
+
+Routine Description:
+
+ This function emulates the PCI BIOS Specification, revision 2.1. The
+ specification is available from the PCI Special Interest Group.
+
+ This function assumes that it is being called during phase 0 initialization.
+ The PCI bus functions are not available at this point, e.g. HalGetBusData.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ TRUE (PCI BIOS was emulated)
+
+--*/
+{
+#if DBG
+ VOID TestPciBios(int flag);
+
+ TestPciBios(0);
+#endif
+
+ switch (P->Gpr[EAX].Xl) {
+
+ case PCIBIOS_PCI_BIOS_PRESENT: // Installation Check
+
+ KdPrint(("PCI_BIOS_PRESENT\n"));
+
+ P->Gpr[EDX].Exx = 0x20494350; // "PCI "
+
+ P->Gpr[EAX].Xh = 0x00; // 00 == BIOS present
+ P->Gpr[EAX].Xl = 0x11; // PCI Hardware Characteristics (mech #1)
+
+ P->Gpr[EBX].Xh = 0x02; // PCI Interface Level Major Version
+ P->Gpr[EBX].Xl = 0x10; // PCI Interface Level (BCD)
+
+ P->Gpr[ECX].Xl = HalpLastPciBus; // Last PCI bus number
+
+ P->Eflags.CF = 0; // reset == PCI BIOS present
+
+ break;
+
+ case PCIBIOS_FIND_PCI_DEVICE:
+ {
+ USHORT DevID = P->Gpr[ECX].Xx;
+ USHORT VenID = P->Gpr[EDX].Xx;
+ USHORT DevIndex = P->Gpr[ESI].Xx;
+
+ UCHAR Bus, Device, Function, Header, NumFunctions;
+ BOOLEAN Found = FALSE;
+
+ KdPrint(("Looking for instance %d of 0x%X, 0x%X\n", DevIndex, DevID, VenID));
+
+ if (VenID == 0xFFFF) {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_VENDOR_ID;
+ P->Eflags.CF = 1; // set == error
+
+ } else {
+
+ for (Bus = 0; Bus <= HalpLastPciBus; Bus++) {
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+
+ if (SBReadConfigWord(Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) {
+
+ continue; // no device here
+
+ }
+
+ Header = SBReadConfigByte(
+ Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType));
+
+ NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1;
+
+ for (Function = 0; Function < NumFunctions; Function++) {
+
+ if (SBReadConfigWord(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == VenID) {
+
+ if (SBReadConfigWord(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID)) == DevID) {
+
+ Found = (DevIndex == 0);
+ DevIndex--;
+ }
+ }
+ if (Found) break; // function
+ }
+ if (Found) break; // device
+ }
+ if (Found) break; // bus
+ }
+
+ if (Found) {
+
+ KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function));
+
+ P->Gpr[EBX].Xh = Bus;
+ P->Gpr[EBX].Xl = (Device << 3) + Function;
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+
+ P->Eflags.CF = 0; // clear == success
+
+ } else {
+
+ KdPrint(("Not found\n"));
+
+ P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND;
+
+ P->Eflags.CF = 1; // set == error
+ }
+
+ }
+ }
+ break;
+
+
+ case PCIBIOS_FIND_PCI_CLASS_CODE:
+ {
+ ULONG ClassCode = (P->Gpr[ECX].Exx) << 8; // see comments below
+ USHORT DevIndex = P->Gpr[ESI].Xx;
+
+ UCHAR Bus, Device, Function, Header, NumFunctions;
+ BOOLEAN Found = FALSE;
+
+ KdPrint(("Looking for class instance %d of 0x%X\n", DevIndex, P->Gpr[ECX].Exx));
+
+ for (Bus = 0; Bus <= HalpLastPciBus; Bus++) {
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+
+ if (SBReadConfigWord(Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) {
+
+ continue; // no device here
+
+ }
+
+ Header = SBReadConfigByte(
+ Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType));
+
+ NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1;
+
+ for (Function = 0; Function < NumFunctions; Function++) {
+
+ //
+ // The class code bytes are in the same Dword as
+ // the revision id:
+ //
+ // Byte
+ // 3 2 1 0
+ // +-------------------+--------+
+ // | class code | Rev id |
+ // +-------------------+--------+
+ //
+ // Read the Dword and mask off the revision id.
+ // The class code we are looking for has been
+ // shifted up already above.
+ //
+ if ((SBReadConfigDword(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID))
+ & 0xFFFFFF00) == ClassCode) {
+
+ Found = (DevIndex == 0);
+ DevIndex--;
+ }
+ if (Found) break; // function
+ }
+ if (Found) break; // device
+ }
+ if (Found) break; // bus
+ }
+
+ if (Found) {
+
+ KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function));
+
+ P->Gpr[EBX].Xh = Bus;
+ P->Gpr[EBX].Xl = (Device << 3) + Function;
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+
+ P->Eflags.CF = 0; // clear == success
+
+ } else {
+
+ KdPrint(("Not found\n"));
+
+ P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND;
+
+ P->Eflags.CF = 1; // set == error
+ }
+ }
+ break;
+
+ case PCIBIOS_READ_CONFIG_BYTE:
+
+ KdPrint(("read byte %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Xl = SBReadConfigByte(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xl));
+
+ break;
+
+ case PCIBIOS_READ_CONFIG_WORD:
+
+ KdPrint(("read word %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 1) == 0) {
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Xx = SBReadConfigWord(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xx));
+
+ break;
+
+ case PCIBIOS_READ_CONFIG_DWORD:
+
+ KdPrint(("read Dword %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 3) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Exx = SBReadConfigDword(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Exx));
+
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_BYTE:
+
+ KdPrint(("Write byte 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Xl, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigByte( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Xl); // Value
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_WORD:
+
+ KdPrint(("Write word 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Xx, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 1) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigWord( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Xx); // Value
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_DWORD:
+
+ KdPrint(("Write Dword 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Exx, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 3) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigDword( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Exx); // Value
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ break;
+
+ case PCIBIOS_GENERATE_SPECIAL_CYCLE:
+ {
+ PCI_TYPE1_CFG_BITS Addr;
+
+ KdPrint(("Generate Special cycle %d, 0x%X\n",
+ P->Gpr[EBX].Xh, // Bus
+ P->Gpr[ECX].Exx)); // Value
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = P->Gpr[EBX].Xh;
+ Addr.u.bits.DeviceNumber = 0x1f;
+ Addr.u.bits.FunctionNumber = 7;
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_ULONG (CONFIG_DATA, P->Gpr[EDX].Exx);
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+ }
+
+ break;
+
+
+ case PCIBIOS_GET_IRQ_ROUTING_OPTIONS: // not supported
+ case PCIBIOS_SET_IRQ_ROUTING_OPTIONS: // not supported
+ default:
+
+ KdPrint(("PCI BIOS: function %x not supported\n", P->Gpr[EAX].Xl));
+
+ P->Gpr[EAX].Xh = PCIBIOS_FUNC_NOT_SUPPORTED;
+
+ P->Eflags.CF = 1; // set == error
+
+ break;
+ }
+
+ return TRUE;
+}
+
+UCHAR
+SBReadConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ ULONG ByteInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ ByteInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ return READ_PORT_UCHAR ((PUCHAR)CONFIG_DATA + ByteInRegister);
+}
+
+USHORT
+SBReadConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ ULONG WordInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ WordInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ return READ_PORT_USHORT ((PUCHAR)CONFIG_DATA + WordInRegister);
+}
+
+ULONG
+SBReadConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ return READ_PORT_ULONG (CONFIG_DATA);
+}
+
+VOID
+SBWriteConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN UCHAR Data
+ )
+{
+ ULONG ByteInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ ByteInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_UCHAR ((PUCHAR)CONFIG_DATA + ByteInRegister, Data);
+}
+
+VOID
+SBWriteConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN USHORT Data
+ )
+{
+ ULONG WordInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ WordInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_USHORT ((PUCHAR)CONFIG_DATA + WordInRegister, Data);
+}
+
+VOID
+SBWriteConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN ULONG Data
+ )
+{
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_ULONG (CONFIG_DATA, Data);
+}
+
+
+#if DBG
+
+// Modify this code to match your particular HW configuration
+//
+// Use the debugger to force flag to 1.
+
+VOID
+initregs(PRXM_CONTEXT P)
+{
+ P->Gpr[EAX].Exx = 0x1234B100;
+ P->Gpr[EBX].Exx = 0x23456789;
+ P->Gpr[ECX].Exx = 0x3456789A;
+ P->Gpr[EDX].Exx = 0x456789AB;
+ P->Gpr[ESP].Exx = 0x87654321;
+ P->Gpr[EBP].Exx = 0x98765432;
+ P->Gpr[ESI].Exx = 0xA9876543;
+ P->Gpr[EDI].Exx = 0xBA987654;
+
+ P->Eflags.CF = 1;
+}
+
+VOID
+dumpregs(PRXM_CONTEXT P)
+{
+ DbgPrint("Carry = %d\n", P->Eflags.CF);
+
+ DbgPrint("EAX = %X, EBX = %X, ECX = %X, EDX = %X\n",
+ P->Gpr[EAX], P->Gpr[EBX], P->Gpr[ECX], P->Gpr[EDX]);
+
+ DbgPrint("ESP = %X, EBP = %X, ESI = %X, EDI = %X\n",
+ P->Gpr[ESP], P->Gpr[EBP], P->Gpr[ESI], P->Gpr[EDI]);
+}
+
+
+VOID
+TestPciBios(int flag)
+{
+int i;
+XM_CONTEXT Context;
+PRXM_CONTEXT P = &Context;
+
+ if (flag == 0) return;
+
+ DbgBreakPoint();
+ initregs(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ P->Gpr[EAX].Xl = 1; // bios present
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0xffff;
+ P->Gpr[EDX].Xx = 0xffff;
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x0453;
+ P->Gpr[EDX].Xx = 0x8086;
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x0002;
+ P->Gpr[EDX].Xx = 0x1011; // DEC ethernet
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x7278;
+ P->Gpr[EDX].Xx = 0x9004; // adaptec
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x1234;
+ P->Gpr[EDX].Xx = 0x5678;
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x030000; // vga
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x020000; // ethernet
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x010000; // scsi
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0xABCDEF; // not found
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 6; // generate special cycle
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EDX].Exx = 0x00000002; // x86 specific
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xE; // get irq routing
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xF; // set irq routing
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 1; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xB; // write byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xC; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3F; // bad register
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xC; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ P->Gpr[ECX].Xx = 0xFFFF;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xD; // write Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3F; // bad register
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xD; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ P->Gpr[ECX].Exx = 0xFFFFFFFF;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ DbgPrint("All done!\n");
+ DbgBreakPoint();
+}
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/pcibios.h b/private/ntos/nthals/haleagle/ppc/pcibios.h
new file mode 100644
index 000000000..2e47f6b23
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pcibios.h
@@ -0,0 +1,58 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1996 Motorola Inc.
+
+Module Name:
+
+ pcibios.h
+
+Abstract:
+
+ This module contains the private header file for the PCI bios
+ emulation.
+
+Author:
+
+ Scott Geranen (3-4-96)
+
+Revision History:
+
+--*/
+
+#ifndef _PCIBIOS_
+#define _PCIBIOS_
+
+
+BOOLEAN HalpEmulatePciBios(
+ IN OUT PRXM_CONTEXT P
+ );
+
+//
+// PCI BIOS v2.1 functions
+//
+#define PCIBIOS_PCI_FUNCTION_ID 0xB1
+#define PCIBIOS_PCI_BIOS_PRESENT 0x01
+#define PCIBIOS_FIND_PCI_DEVICE 0x02
+#define PCIBIOS_FIND_PCI_CLASS_CODE 0x03
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
+#define PCIBIOS_READ_CONFIG_BYTE 0x08
+#define PCIBIOS_READ_CONFIG_WORD 0x09
+#define PCIBIOS_READ_CONFIG_DWORD 0x0A
+#define PCIBIOS_WRITE_CONFIG_BYTE 0x0B
+#define PCIBIOS_WRITE_CONFIG_WORD 0x0C
+#define PCIBIOS_WRITE_CONFIG_DWORD 0x0D
+#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0x0E
+#define PCIBIOS_SET_IRQ_ROUTING_OPTIONS 0x0F
+
+//
+// PCI BIOS v2.1 status codes:
+//
+#define PCIBIOS_SUCCESSFUL 0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
+#define PCIBIOS_BAD_VENDOR_ID 0x83
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
+#define PCIBIOS_SET_FAILED 0x88
+#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+
+#endif // _PCIBIOS_
diff --git a/private/ntos/nthals/haleagle/ppc/pcip.h b/private/ntos/nthals/haleagle/ppc/pcip.h
new file mode 100644
index 000000000..3aa4853ca
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pcip.h
@@ -0,0 +1,186 @@
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/prepnvr.h b/private/ntos/nthals/haleagle/ppc/prepnvr.h
new file mode 100644
index 000000000..93c8c09bc
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/prepnvr.h
@@ -0,0 +1,134 @@
+/* Structure map for NVRAM on PowerPC Reference Platform */
+
+/* Revision 1 changes (8/25/94):
+ - Power Management (RESTART_BLOCK struct)
+ - Normal added to PM_MODE
+ - OSIRQMask (HEADER struct) */
+
+/* All fields are either character/byte strings which are valid either
+endian or they are big-endian numbers.
+
+There are a number of Date and Time fields which are in RTC format,
+big-endian. These are stored in UT (GMT).
+
+For enum's: if given in hex then they are bit significant, i.e. only
+one bit is on for each enum.
+*/
+
+#ifndef _NVRAM_
+#define _NVRAM_
+
+#define NVSIZE 4096 /* size of NVRAM */
+#define OSAREASIZE 512 /* size of OSArea space */
+#define CONFSIZE 1024 /* guess at size of Configuration space */
+
+typedef struct _SECURITY {
+ unsigned long BootErrCnt; /* Count of boot password errors */
+ unsigned long ConfigErrCnt; /* Count of config password errors */
+ unsigned long BootErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long ConfigErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long BootCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long ConfigCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long BootSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned long ConfigSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned char Serial[16]; /* Box serial number */
+ } SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ WPOS2 = 4,
+ WPAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ Netware = 8,
+ USL = 9,
+ Low_End_Client = 10,
+ SCO = 11
+ } OS_ID;
+
+typedef struct _ERROR_LOG {
+ unsigned char ErrorLogEntry[40]; /* To be architected */
+ } ERROR_LOG;
+
+/*---Revision 1: Change the following struct:---*/
+typedef struct _RESUME_BLOCK {
+ /* Hibernation Resume Device will be an
+ environment variable */
+ unsigned long CheckSum; /* Checksum of RESUME_BLOCK */
+ volatile unsigned long BootStatus;
+
+ void * ResumeAddr; /* For Suspend Resume */
+ void * SaveAreaAddr; /* For Suspend Resume */
+ unsigned long SaveAreaLength; /* For Suspend Resume */
+
+ unsigned long HibResumeImageRBA; /* RBA (512B blocks) of compressed OS
+ memory image to be loaded by FW
+ on Resume from hibernation */
+ unsigned long HibResumeImageRBACount; /* Size of image in 512B blocks*/
+ unsigned long Reserved;
+ } RESUME_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+ } OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80, /* Part of state is in memory */
+ Hibernate = 0x40, /* Nothing in memory - state saved elsewhere */
+/* Revision 1: Normal added (actually was already here) */
+ Normal = 0x00 /* No power management in effect */
+ } PMMode;
+
+typedef struct _HEADER {
+ unsigned short Size; /* NVRAM size in K(1024) */
+ unsigned char Version; /* Structure map different */
+ unsigned char Revision; /* Structure map the same -
+ may be new values in old fields
+ in other words old code still works */
+ unsigned short Crc1; /* check sum from beginning of nvram to OSArea */
+ unsigned short Crc2; /* check sum of config */
+ unsigned char LastOS; /* OS_ID */
+ unsigned char Endian; /* B if big endian, L if little endian */
+ unsigned char OSAreaUsage; /* OSAREA_USAGE */
+ unsigned char PMMode; /* Shutdown mode */
+ RESUME_BLOCK ResumeBlock;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+/* Global Environment information */
+ void * GEAddress;
+ unsigned long GELength;
+ /* Date&Time from RTC of last change to Global Environment */
+ unsigned long GELastWriteDT[2];
+
+/* Configuration information */
+ void * ConfigAddress;
+ unsigned long ConfigLength;
+ /* Date&Time from RTC of last change to Configuration */
+ unsigned long ConfigLastWriteDT[2];
+ unsigned long ConfigCount; /* Count of entries in Configuration */
+
+/* OS dependent temp area */
+ void * OSAreaAddress;
+ unsigned long OSAreaLength;
+ /* Date&Time from RTC of last change to OSAreaArea */
+ unsigned long OSAreaLastWriteDT[2];
+
+/* Revision 1: add this mask - function tbd */
+ /*unsigned short OSIRQMask; OS to FW IRQ Mask - "I've used this one" */
+ } HEADER;
+
+
+/* Here is the whole map of the NVRAM */
+typedef struct _NVRAM_MAP {
+ HEADER Header;
+ unsigned char GEArea[NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER)];
+ unsigned char OSArea[OSAREASIZE];
+ unsigned char ConfigArea[CONFSIZE];
+ } NVRAM_MAP;
+
+#endif /* ndef _NVRAM_ */
diff --git a/private/ntos/nthals/haleagle/ppc/pxbeep.c b/private/ntos/nthals/haleagle/ppc/pxbeep.c
new file mode 100644
index 000000000..2ac4b543c
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxbeep.c
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a Power PC
+ system.
+
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpIoControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxbusdat.c b/private/ntos/nthals/haleagle/ppc/pxbusdat.c
new file mode 100644
index 000000000..ef7f3462b
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxbusdat.c
@@ -0,0 +1,210 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxbusdat.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+ //
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+
+ return Bus;
+}
+
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxcache.s b/private/ntos/nthals/haleagle/ppc/pxcache.s
new file mode 100644
index 000000000..a8c393646
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxcache.s
@@ -0,0 +1,208 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxcache.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 27-Dec-93 plj Added 603 support.
+// 13-Mar-94 plj Fixed problem introduced during switch to PAS;
+// added 604 support.
+// 07-Oct-94 saj Check for length=0 in Range functions
+//--
+
+#include "kxppc.h"
+#include "halppc.h"
+
+ .extern HalpIoControlBase
+
+// NOTE: The 603's "I-Cache Flash Invalidate" and the 604's
+// "I-Cache Invalidate All" basically perform the same function
+// although the usage is slightly different. In the 603 case,
+// ICFI must be cleared under program control after it is set.
+// In the 604 the bit clears automatically.
+
+ .set HID0_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set HID0, 1008 // SPR # for HID0
+ .set BLOCK_SIZE, 32
+ .set BLOCK_LOG2, 5 // Should be == log2(BLOCK_SIZE)
+ .set BASE, 0x80000000 // base addr of valid cacheable region
+
+//++
+//
+// Routine Description:
+//
+// The D-Cache is flushed by loading 1 byte per cache line from a
+// valid address range, then flushing that address range.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+ mfsprg r.5, 1 // Get PCR->FirstLevelDcacheSize
+ lwz r.4, PcFirstLevelDcacheSize(r.5)
+
+ LWI (r.3, BASE) // Get a valid virtual address
+ srwi r.4, r.4, BLOCK_LOG2 // Convert to # cache lines
+//
+// Load r.4 cache lines starting from virtual address in r.3
+//
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.12)
+ sync // ensure ALL previous stores completed
+ subi r.6, r.3, BLOCK_SIZE // bias addr for pre-index
+FillLoop:
+ lbzu r.0, BLOCK_SIZE(r.6) // Read memory to force cache fill
+ bdnz FillLoop // into cache
+ ENABLE_INTERRUPTS(r.10)
+
+ mtctr r.4
+FlushRange:
+ dcbf r.0, r.3 // flush block
+ addi r.3, r.3, BLOCK_SIZE // bump address
+ bdnz FlushRange
+
+ LEAF_EXIT(HalSweepDcache)
+
+
+
+
+
+//++
+//
+// Routine Description:
+//
+// The I-Cache is flushed by toggling the Icache flash invalidate bit
+// in HID0. Invalidation is all that is necessary. Flushing to main
+// memory is not needed since the Icache can never be dirty.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+ LWI (r.3, BASE)
+
+FlashInvalidateIcache:
+ mfspr r.3, HID0
+ ori r.4, r.3, HID0_ICFI // Cache Flash Invalidate
+ isync
+ mtspr HID0, r.4 // Flash invalidate I-Cache
+ mtspr HID0, r.3 // re-enable (not needed on 604)
+
+ LEAF_EXIT(HalSweepIcache)
+
+//
+// Routine Description:
+//
+// The D-Cache is flushed by issuing a data cache block flush (DCBF)
+// instruction for each data block in the range.
+//
+// Arguments:
+//
+// r.3 - Starting address
+// r.4 - Length
+//
+// Return Value:
+//
+// None.
+//
+//
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+ andi. r.5, r.3, BLOCK_SIZE-1 // Get block offset of Start Addr
+ or. r.4, r.4, r.4 // Check for Length == 0
+ addi r.4, r.4, BLOCK_SIZE-1 // bump Length by BLOCK_SIZE-1
+ add r.4, r.4, r.5
+ srwi r.4, r.4, BLOCK_LOG2 // Compute # of cache blocks to flush
+ mtctr r.4
+ bne+ FlushRange // Branch if Length != 0
+
+ LEAF_EXIT(HalSweepDcacheRange)
+
+
+
+//
+// Routine Description:
+//
+// The I-Cache is flushed by issuing a Instruction Cache Block
+// Invalidate (ICBI) instruction for each data block in the range.
+// If the range is large, the entire Icache can be invalidated by
+// branching to FlashInvalidateIcache.
+//
+// Arguments:
+//
+// r.3 - Starting address
+// r.4 - Length
+//
+// Return Value:
+//
+// None.
+//
+//
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+ andi. r.5, r.3, BLOCK_SIZE-1 // Get block offset of Start Addr
+ or. r.4, r.4, r.4 // Check for Length == 0
+ addi r.4, r.4, BLOCK_SIZE-1 // bump Length by BLOCK_SIZE-1
+ add r.4, r.4, r.5
+ srwi r.4, r.4, BLOCK_LOG2 // Compute # of cache blocks to flush
+ beqlr- // return if Length == 0
+ mtctr r.4
+
+#if 0
+//
+// Possible speedup: If Length is fairly large (e.g. greater than 1/2
+// of the cache size), we will flash invalidate the entire cache, else
+// only sweep the desired range.
+//
+ li r.5, 16384/BLOCK_SIZE // # Icache lines on 604
+ cmpwi r.6, 3 // possible values are 3 or 4
+ bgt Threshold // Branch if 604
+ li r.5, 8192/BLOCK_SIZE // # Icache lines on 603
+Threshold:
+ srwi r.5, r.5, 1 // r.5 = IcacheLines/2
+ cmpl 0,0, r.4, r.5
+ bgt FlashInvalidateIcache
+#endif
+
+InvalidateIcache:
+ icbi 0, r.3 // invalidate block in I-cache
+ addi r.3, r.3, BLOCK_SIZE // bump address by BLOCK_SIZE
+ bdnz InvalidateIcache
+
+ LEAF_EXIT(HalSweepIcacheRange)
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxcalstl.c b/private/ntos/nthals/haleagle/ppc/pxcalstl.c
new file mode 100644
index 000000000..bc8044575
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxcalstl.c
@@ -0,0 +1,184 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service for a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jim Wooldridge
+ Steve Johns (Motorola)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxsystyp.h"
+
+//
+// KeQueryPerformanceCounter & KeStallExecutionProcessor are called
+// before Phase 0 initialization, so initialize it to a reasonable value.
+//
+ULONG HalpPerformanceFrequency = 80000000/16;
+extern ULONG HalpClockCount;
+extern ULONG HalpFullTickClockCount;
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+
+#endif
+
+
+
+ULONG
+HalpCalibrateTBPStack(
+ VOID
+ );
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{ int i;
+ ULARGE_INTEGER BigNumber;
+ ULONG Variance;
+ ULONG BusSpeed;
+ static ULONG BusSpeeds [] = {
+ 25000000,
+ 33333333,
+ 40000000,
+ 41875000,
+ 50000000,
+ 55833333,
+ 60000000,
+ 66000000,
+ 66666666,
+ 67000000,
+ 75000000,
+ 80000000,
+ 83333333,
+ 83750000,
+ 90000000,
+ 99000000,
+ 100000000,
+ 111666666,
+ 120000000,
+ 132000000,
+ 133333332,
+ 134000000,
+ 150000000,
+ 160000000,
+ 166666666,
+ 167500000
+ };
+
+
+
+ //
+ // Set initial scale factor
+ //
+
+ PCR->StallScaleFactor = 1;
+
+ //
+ // Compute the clock frequency of the Time Base & Decrementer
+ //
+ // It's possible for reads from the CMOS RTC to return odd results.
+ // For this reason, We can use a do-while loop, to ensure the calibration
+ // function is called at least once and is returning a reasonable value.
+ //
+
+ do {
+ switch( HalpSystemType ) {
+
+ case MOTOROLA_POWERSTACK:
+ HalpPerformanceFrequency = HalpCalibrateTBPStack();
+ break;
+
+ default:
+ case MOTOROLA_BIG_BEND:
+ HalpPerformanceFrequency = HalpCalibrateTB();
+ break;
+ }
+ } while( HalpPerformanceFrequency < 1000000 );
+
+ //
+ // CPU bus runs at 4 times the DECREMENTER frequency
+ //
+ BusSpeed = HalpPerformanceFrequency * 4;
+
+ //
+ // Choose the bus speed which is closest to calculated value.
+ // If the bus speed is not "close enough", then it may be
+ // a new speed which we don't know about. For this case
+ // we will leave the Performance Frequency alone.
+ //
+ for (i=0; i< (sizeof(BusSpeeds)/sizeof(ULONG)); i++) {
+ //
+ // We are going to allow for a 0.1% variation
+ // in calibrated frequency of the system bus clock.
+ // Calculate the variance as 1/2048 the frequency.
+ //
+ Variance = BusSpeeds[i] >> 11;
+ if ((BusSpeeds[i] - Variance < BusSpeed) &&
+ (BusSpeeds[i] + Variance > BusSpeed)) {
+ HalpPerformanceFrequency = BusSpeeds[i] / 4;
+ break;
+ }
+ }
+
+ //
+ // Initialize the system clock variables
+ //
+ HalpClockCount = (HalpPerformanceFrequency * (MAXIMUM_INCREMENT/10000)) / 1000;
+ HalpFullTickClockCount = HalpClockCount;
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxcirrus.h b/private/ntos/nthals/haleagle/ppc/pxcirrus.h
new file mode 100644
index 000000000..5ec9916ba
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxcirrus.h
@@ -0,0 +1,238 @@
+/*
+ * pxcirrus.h
+ *
+ * Defines for cirrus HAL support
+ */
+
+#define CIRRUS_VIDEO_MEMORY_BASE 0xc0000000
+#define CIRRUS_VENDOR_ID 0x1013
+#define CIRRUS_COMMAND_MASK 0x03
+
+#define CIRRUS_TEXT_MEM 0xb8000
+#define CIRRUS_FONT_MEM 0xa0000
+
+
+#define WRITE_CIRRUS_UCHAR(port,data) \
+ *(volatile unsigned char *) \
+ ((ULONG)HalpIoControlBase+(port))=(UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_CIRRUS_VRAM(port,data) \
+ *((PUCHAR)((ULONG) HalpVideoMemoryBase + (port))) = (UCHAR) (data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_CIRRUS_USHORT(port,data) \
+ *(volatile unsigned short*) \
+ ((ULONG)HalpIoControlBase+(port))=(USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_CIRRUS_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define READ_CIRRUS_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define setreg(port,index,data) \
+ WRITE_CIRRUS_UCHAR(port,index), \
+ WRITE_CIRRUS_UCHAR(port+1,data)
+
+#define outportb(port,data) \
+ WRITE_CIRRUS_UCHAR(port,data)
+
+#define outp(port,data) outportb(port,data)
+
+#define inp(port) \
+ READ_CIRRUS_UCHAR(port)
+
+#define INSTATUS_1 (PVOID) ((ULONG)((int)HalpIoControlBase + (int)0x03DA))
+
+//
+// Attributes Registers
+//
+
+static unsigned char attr3[] =
+{
+ 0x00, // AR0-ARF: Attribute Controller
+ 0x01, // Palette Registers
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x14,
+ 0x07,
+ 0x38,
+ 0x39,
+ 0x3a,
+ 0x3b,
+ 0x3c,
+ 0x3d,
+ 0x3e,
+ 0x3f,
+ 0x0c, // AR10: Attribute Controller Mode
+ // Blink Enable
+ // Line Graphics Enable
+ 0x00, // AR11: Overscan (Border) color
+ 0x0f, // AR12: Color Plane Enable
+ // All planes enabled
+ 0x08, // AR13: Pixel Panning
+ 0x00 // AR14: Color Select
+};
+
+//
+// CRT control
+//
+
+static unsigned char crtc3[] =
+{
+ 0x5f, // CR0: Horizontal Total
+ 0x4f, // CR1: Horizontal Display End
+ 0x50, // CR2: Start Horizontal Blinking
+ 0x82, // CR3: End Horizontal Blanking
+ 0x55, // CR4: Start Horizontal Retrace Pulse
+ 0x81, // CR5: End Horizontal Retrace Pulse
+ 0xbf, // CR6: Vertical Total
+ 0x1f, // CR7: Overflow
+ 0x00, // CR8: Row Scan
+ 0x4f, // CR9: Character Cell Height (16)
+ 0x0d, // CRa: Text Cursor Start Register
+ 0x0e, // CRb: Text Cursor End Register
+ 0x00, // CRc: Screen Start High
+ 0x00, // CRd: Screen Start Low
+ 0x00, // CRe: Text Cursor Location High
+ 0x00, // CRf: Text Cursor Location Low
+ 0x9c, // CR10: Vertical Sync Start
+ 0xae, // CR11: Vertical Sync End
+ 0x8f, // CR12: Vertical Display End
+ 0x28, // CR13: Offset
+ 0x1f, // CR14: Underline Row Scanline
+ 0x96, // CR15: Vertical Blank Start
+ 0xb9, // CR16: Vertical Blank End
+ 0xa3, // CR17: Mode Control
+ 0xff, // CR18: Line Compare
+ 0x00, // CR19: Interlace End
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+
+//
+// Graphics Registers
+//
+
+static unsigned char graph3[] =
+{
+ 0x00, // GR0: Set/Reset Register
+ 0x00, // GR1: Set/Reset Enable Register
+ 0x00, // GR2: Color Compare
+ 0x00, // GR3: Data Rotate Register
+ 0x00, // GR4: Read Map Select Register
+ 0x10, // GR5: Mode Register (Odd/Even On)
+
+ 0x0e, // GR6: Miscellaneous Register
+ // Memory Map b800:0
+ // Chain Odd Maps to Even
+ 0x00, // GR7: Color Don't Care register
+ 0xff // GR8: Bit Mask Register
+};
+
+//
+// Sequencer Registers
+//
+
+static unsigned char seq3[] =
+{
+ 0x03, // SR0: Reset Register
+ // Asynchronous and Synchronous reset
+ 0x00, // SR1: Clocking Mode
+ 0x03, // SR2: Plane Mask Register
+ // Map 0 and 1 Enable
+ 0x00, // SR3: Character Map Select Register
+ 0x02, // SR4: Memory Mode
+ // Extended Memory
+};
+
+//
+// Extended Sequencer Registers
+//
+
+static unsigned char eseq3[] =
+{
+ 0x02,0x0f, // Enable Writing Pixel Extension
+ 0x06,0x12, // Unlock All Extensions
+ 0x07,0x00, // Extended Sequencer Mode (From Meeting)
+ 0x08,0x40, // EEPROM control register
+
+//
+// The Cirrus book says that all of the scratch pad registers
+// are "reserved for the Cirrus Logic BIOS" so it would be proper to
+// leave all of them alone.
+//
+
+// 0x09,0x68, // Scratch Pad 0 register
+// 0x0a,0x32, // Scratch Pad 1 register
+ 0x0b,0x4a, // VCLK 0 Numerator Register
+ 0x0c,0x5b, // VCLK 1 Numerator Register
+ 0x0d,0x42, // VCLK 2 Numerator Register
+ 0x0e,0x6e, // VCLK 3 Numerator Register
+ 0x0f,0x1d, // DRAM control
+ 0x10,0x00, // Graphics Cursor X Position
+ 0x11,0x00, // Graphics Cursor Y Position
+ 0x12,0x00, // Graphics Cursor Attributes
+ 0x13,0x00, // Graphics Pattern Address Offset Register
+// 0x14,0x00, // Scratch Pad Register 2
+// 0x15,0x02, // Scratch Pad Register 3
+ 0x16,0x71, // Performance Tuning
+ 0x17,0x31, // Configuration Readback and Extended Control
+ 0x18,0x00, // Signature Generator Control
+ 0x19,0x01, // Signature Register Result Low-Byte
+ 0x1a,0x00, // Signature Generator Result High-Byte
+ 0x1b,0x2b, // VCLK Denominator and Post-Scalar Value
+ 0x1c,0x2f,
+ 0x1d,0x1f,
+ 0x1e,0x2a,
+ 0x1f,0x1c, // MCLK Select Register
+ 0xff // End of list.
+};
+
+//
+// Extended CRTC Registers
+//
+
+static unsigned char ecrtc3[] =
+{
+ 0x19,0x00, // CR19: Inerlace End
+ 0x1a,0x00, // CR1a: Miscellaneous
+ 0x1b,0x00, // CR1b: Extended Display Controlls
+ 0x1d,0x00, // Overlay Extended Control
+ 0xff // End of list.
+};
+
+//
+// Extended Graphics Registers
+//
+
+static unsigned char egraph3[] =
+{
+ 0x9,0x00, // GR9: Offset Register 0
+ 0xa,0x00, // GRa: Offset Register 1
+ 0xb,0x00, // GRb: Graphics Controller Mode Extnsions
+ 0xc,0xff, // GRc: Color Key Compare
+ 0xd,0x00, // GRd: Color Key Compare Mask
+ 0x10,0x00, // GR10: Background Color Byte 1
+ 0x11,0x00, // GR11: Foreground Color Byte 1
+ 0xff
+};
+
+//
+// Extended Attribute Registers
+//
+
+static unsigned char eattr3[] =
+{
+ 0xff
+};
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxclksup.s b/private/ntos/nthals/haleagle/ppc/pxclksup.s
new file mode 100644
index 000000000..140c8fbee
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxclksup.s
@@ -0,0 +1,145 @@
+/***********************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+ File Name:
+ PXCLKSUP.S
+
+ Globals:
+ none
+
+ Functions:
+ HalpUpdateDecrementer
+ KeQueryPerformanceCounter
+
+ History:
+ 11-Feb-1994 Steve Johns
+ Original Version
+ 23-Jun-1994 Steve Johns (sjohns@pets.sps.mot.com)
+ Fixed HalpZeroPerformanceCounter. Was writing to RTCU & RTCL.
+ Writes should go to SPR 20 & 21.
+ 11-Sep-1995 Steve Johns
+ Removed 601 specific code
+ Removed 603 workaround, since we don't support < 603 v3.2
+***********************************************************************/
+
+#include <halppc.h>
+#define ERRATA603 FALSE
+
+
+ LEAF_ENTRY(HalpSetDecrementer)
+
+ mtdec r.3 // Set the DECREMENTER
+
+ LEAF_EXIT(HalpSetDecrementer)
+
+
+
+ LEAF_ENTRY(HalpUpdateDecrementer)
+
+//
+// Read the DECREMENTER to get the interrupt latency and bias Count by
+// that amount. Otherwise, the latencies would accumulate and the time
+// of day would run slow.
+//
+ mfdec r.7 // Read the DECREMENTER
+ add r.4,r.3,r.7 // + Count
+//
+// We expect that the DECREMENTER should be near 0xFFFFFFxx, so R4 should
+// be less than r.3. If not, we don't want to cause an excessively long
+// clock tick, so just ignore the latency and use Count.
+//
+ cmpl 0,0,r.4,r.3
+ ble SetDecr
+ mr r.4,r.3
+SetDecr:
+
+ mtdec r.4 // Write to the DECREMENTER
+#if ERRATA603
+ isync
+#endif
+
+// Undocumented return value: the latency in servicing this interrupt
+ neg r.3,r.7
+
+
+ LEAF_EXIT(HalpUpdateDecrementer)
+
+
+
+ .extern HalpPerformanceFrequency
+
+
+/***********************************************************************
+ Synopsis:
+ ULARGE_INTEGER KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
+
+ Purpose:
+ Supplies a 64-bit realtime counter for use in evaluating performance
+ of routines.
+
+ Returns:
+ This routine returns current 64-bit performance counter and,
+ optionally, the frequency of the Performance Counter.
+
+ Global Variables Referenced:
+ HalpPerformanceFrequency
+
+***********************************************************************/
+
+//
+// Register Definitions
+//
+ .set RetPtr, r.3
+ .set Freq, r.4
+ .set TimerLo, r.6
+ .set TimerHi, r.7
+ .set Temp, r.8
+
+
+ LEAF_ENTRY(KeQueryPerformanceCounter)
+
+
+ cmpli 0,0,Freq,0 // Was PerformanceFrequency passed ?
+ beq ReadTB
+
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp) // PerformanceFrequency.LowPart =
+ stw Temp,0(Freq) // HalpPerformanceFrequency;
+ li Temp,0 // PerformanceFrequency.HighPart = 0;
+ stw Temp,4(Freq)
+
+ReadTB:
+ mftbu TimerHi // Read the TB registers coherently
+ mftb TimerLo
+#if ERRATA603
+ mftb TimerLo
+ mftb TimerLo
+ mftb TimerLo
+#endif
+ mftbu Temp
+ cmpl 0,0,Temp,TimerHi
+ bne- ReadTB
+
+ stw TimerLo,0(RetPtr)
+ stw TimerHi,4(RetPtr)
+
+ LEAF_EXIT(KeQueryPerformanceCounter)
+
+
+
+ .set TB, 284
+ .set TBU, 285
+
+ LEAF_ENTRY(HalpZeroPerformanceCounter)
+
+ li r.3, 0
+ mtspr TB,r.3
+ mtspr TBU,r.3
+
+ LEAF_EXIT(HalpZeroPerformanceCounter)
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxclock.c b/private/ntos/nthals/haleagle/ppc/pxclock.c
new file mode 100644
index 000000000..a621530d3
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxclock.c
@@ -0,0 +1,243 @@
+
+/*****************************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ PXCLOCK.C
+
+Abstract:
+
+ This module contains the system clock interrupt handler.
+ The DECREMENTER is used to implement the system clock. The
+ handler resets the DECREMENTER to SYSTEM_TIME (accounting
+ for interrupt latency), and updates the system time.
+
+
+Author:
+
+ Steve Johns 10-Feb-1994
+
+Revision History:
+// 09-Jun-95 Steve Johns
+// - Removed 1 level of buffering of time increment to match
+// buffering of DECREMENTER counts.
+******************************************************************************/
+
+#include "halp.h"
+
+extern ULONG HalpPerformanceFrequency;
+
+BOOLEAN
+KdPollBreakIn (
+ VOID
+ );
+
+ULONG HalpClockCount;
+ULONG HalpFullTickClockCount;
+ULONG HalpUpdateDecrementer();
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+BOOLEAN
+HalpHandleDecrementerInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processor 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpClockCount);
+
+ //
+ // Call the kernel to update system time
+ //
+
+ KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
+
+ //
+ // If tick rate has changed, then tell the kernel about it
+ //
+
+ HalpCurrentTimeIncrement = HalpNewTimeIncrement;
+
+ //
+ // Lower Irql to original value and enable interrupts
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ HalpEnableInterrupts();
+
+ if ( KdDebuggerEnabled && KdPollBreakIn() ) {
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ }
+
+ return (TRUE);
+}
+
+#if !defined(NT_UP)
+VOID
+HalpHandleDecrementerInterrupt1(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processors other than 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpFullTickClockCount);
+
+ //
+ // Call the kernel to update run time for this thread and process.
+ //
+
+ KeUpdateRunTime(TrapFrame);
+
+ //
+ // Lower Irql to original value
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ return;
+}
+#endif
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // HalpPerformanceFrequence is the number of times the decrementer
+ // ticks in 1 second. MINIMUM_INCREMENT is the number of 100 is the
+ // number of 100ns units in 1 ms.
+ // Therefore, DesiredIncrement/MINUMUM_INCREMENT is the number of
+ // ms desired. This multiplied by the number of decrementer ticks
+ // in 1 second, divided by 1000 gives the number of ticks in the
+ // desired number of milliseconds. This value will go into the
+ // decrementer.
+ //
+
+ HalpClockCount = (HalpPerformanceFrequency *
+ (DesiredIncrement/MINIMUM_INCREMENT)) / 1000;
+
+ //
+ // Calculate the number of 100ns units to report to the kernel every
+ // time the decrementer fires with this new period. Note, for small
+ // values of DesiredIncrement (min being 10000, ie 1ms), truncation
+ // in the above may result in a small decrement in the 5th decimal
+ // place. As we are effectively dealing with a 4 digit number, eg
+ // 10000 becomes 9999.something, we really can't do any better than
+ // the following.
+ //
+
+ HalpNewTimeIncrement = DesiredIncrement/MINIMUM_INCREMENT * MINIMUM_INCREMENT;
+
+ KeLowerIrql(OldIrql);
+ return HalpNewTimeIncrement;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxdat.c b/private/ntos/nthals/haleagle/ppc/pxdat.c
new file mode 100644
index 000000000..cb05bec92
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxdat.c
@@ -0,0 +1,110 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x000, 0x10, // SIO DMA
+ 0x0C0, 0x20, // SIO DMA
+ 0x080, 0x20, // SIO DMA
+ 0x400, 0x40, // SIO DMA
+ 0x480, 0x10, // SIO DMA
+ 0x4C0, 0x10, // SIO DMA
+ 0x4D6, 0x2, // SIO DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+ 0x4D0, 0x2, // PIC edge/level
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+
+ 0x074, 0x4, // NVRAM
+
+ 0x0F0, 0x10, // coprocessor ports
+
+// 0x800, 0x1, // Big Bend NVRAM data port
+ 0x81C, 0x1, // Eagle external configuration register
+ 0x850, 0x1, // Eagle external configuration register
+// 0xC00, 0x2, // Big Bend NVRAM index ports
+ 0xCF8, 0x8, // PCI CONFIG_ADDRESS & CONFIG_DATA
+
+ 0,0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+
+//
+// From ixpcibrd.c
+//
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
diff --git a/private/ntos/nthals/haleagle/ppc/pxdisp.c b/private/ntos/nthals/haleagle/ppc/pxdisp.c
new file mode 100644
index 000000000..d86393105
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxdisp.c
@@ -0,0 +1,2211 @@
+/*++
+Copyright (c) 1994 International Business Machines Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Eagle-Based PowerPC system using an S3, Weitek P9000, Cirrus
+ CL-GD5434 video adapter, or most any video card with an option ROM.
+
+Author:
+
+ Jim Wooldridge Sept 1994 - Ported to PowerPC Initial Version
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jess Botts S3 support in text mode Oct-1993
+ Lee Nolan Added Weitek P9000 support Feb-1994
+ Mike Haskell Added Weitek P9100 support Oct-1994
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "string.h"
+#include "pxcirrus.h"
+#include "pxpcisup.h"
+
+//=============================================================================
+//
+// IBMBJB added include to get text mode values for the Brooktree 485 DAC's
+// palette registers, removed definition of HDAL and added address
+// definitions for PowerPC
+
+#include "txtpalet.h"
+
+#if defined(_PPC_)
+
+# define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
+# define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
+
+#endif
+
+//PHYSICAL ADDRESS of WEITEK P9000 video ram
+#define P9_VIDEO_MEMORY_BASE 0xC1200000
+
+//PHYSICAL ADDRESS of WEITEK P9100 video ram
+#define P91_VIDEO_MEMORY_BASE 0xC1800000
+
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+
+#define ROWS 25
+#define COLS 80
+#define TAB_SIZE 4
+#define ONE_LINE (COLS*2)
+#define TWENTY_FOUR_LINES (ROWS-1)* ONE_LINE
+#define TWENTY_FIVE_LINES ROWS * ONE_LINE
+#define TEXT_ATTR 0x1F
+
+//
+// Define forward referenced procedure prototypes.
+//
+VOID HalpDisplayINT10Setup (VOID);
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character );
+
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+VOID
+HalpScrollS3(
+ IN UCHAR line
+ );
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP9 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+ScreenOn (
+ VOID
+ );
+
+VOID
+ScreenOff (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP9 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterP9(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ );
+
+
+
+
+VOID
+HalpDisplayCharacterCirrus (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterCirrus (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcCirrusSetup (
+ VOID
+ );
+
+VOID HalpScrollCirrus (
+ IN UCHAR line
+ );
+
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+static void updattr(IN int rg,IN unsigned char val);
+static void set_ext_regs(IN int reg,IN unsigned char *p);
+static void clear_text(VOID);
+static void load8x16(VOID);
+static void load_ramdac();
+
+
+//
+//
+//
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+typedef
+VOID
+(*PHALP_SCROLL_SCREEN) (
+ UCHAR
+ );
+
+
+typedef
+VOID
+(*PHALP_OUTPUT_CHARACTER) (
+ UCHAR
+ );
+
+
+//
+// Define static data.
+//
+BOOLEAN HalpDisplayOwnedByHal;
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters = NULL;
+
+volatile PUCHAR HalpVideoMemoryBase = (PUCHAR)0;
+
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+PHALP_OUTPUT_CHARACTER HalpOutputCharacter = NULL;
+PHALP_SCROLL_SCREEN HalpScrollScreen = NULL;
+
+
+//
+// Define OEM font variables.
+//
+
+USHORT HalpBytesPerRow;
+USHORT HalpCharacterHeight;
+USHORT HalpCharacterWidth;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+ULONG HalpColumn;
+ULONG HalpRow;
+USHORT HalpHorizontalResolution;
+USHORT HalpVerticalResolution;
+USHORT HalpScreenStart = 0;
+
+
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+POEM_FONT_FILE_HEADER HalpFontHeader;
+
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ //LONG SlotNumber = 0;
+ //LONG ChipID = -1;
+
+
+
+
+
+ //
+ // For the Weitek P9000, set the address of the font file header.
+ // Display variables are computed later in HalpDisplayPpcP9Setup.
+ //
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+
+
+ //
+ // Read the Registry entry to find out which video adapter the system
+ // is configured for. This code depends on the OSLoader to put the
+ // correct value in the Registry.
+ //
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ while (ConfigurationEntry != NULL) {
+
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterS3;
+ HalpScrollScreen = HalpScrollS3;
+
+
+
+ if (ConfigurationEntry->ComponentEntry.Identifier[0] == 'C' &&
+ ConfigurationEntry->ComponentEntry.Identifier[1] == 'L' &&
+ ConfigurationEntry->ComponentEntry.Identifier[2] == '5' &&
+ ConfigurationEntry->ComponentEntry.Identifier[3] == '4') {
+ HalpDisplayControllerSetup = HalpDisplayPpcCirrusSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterCirrus;
+ HalpScrollScreen = HalpScrollCirrus;
+ break;
+ }
+ if (HalpInitializeX86DisplayAdapter(LoaderBlock)) {
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterINT10;
+ HalpScrollScreen = HalpScrollINT10;
+ break;
+ }
+
+ if (ConfigurationEntry->ComponentEntry.Identifier[0] == 'S' &&
+ ConfigurationEntry->ComponentEntry.Identifier[1] == '3') {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ break;
+ }
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9000")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP9Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP9;
+ break;
+ }
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP91;
+ break;
+ }
+
+ break;
+
+ } // end While
+
+
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+ HalpDisplayControllerSetup();
+ }
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Record the routine to reset display to text mode.
+ //
+ HalpResetDisplayParameters = ResetDisplayParameters;
+
+ //
+ // Set HAL ownership of the display to FALSE.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the S3 display controller chip.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// Routine Description:
+//
+// This is the initialization routine for S3 86C911. This routine initializes
+// the S3 86C911 chip in the sequence of VGA BIOS for AT.
+//
+ ULONG DataLong;
+ USHORT i,j;
+ UCHAR DataByte;
+ UCHAR Index;
+// PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+
+
+ if (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ // Enable Video Subsystem
+ // According to chapter 5.4.2 regular VGA setup sequence
+
+ //=========================================================================
+ //
+ // IBMBJB changed from writing 0x10 and then 0x08 to writing 0x18
+ // because the second write will wipe out the first one, the
+ // second write was originally done after the write to Setup_OP
+ //
+ // WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
+ // WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
+
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x18);
+
+ //=========================================================================
+
+ // Subsystem Enable = 0x10;
+ WRITE_S3_UCHAR(Setup_OP, 0x01);
+
+ WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ WRITE_S3_UCHAR(Seq_Data, 0x21);
+
+ //=========================================================================
+ //
+ // IBMBJB removed this section because it is not currently used, this
+ // was left commented out instead of deleting it in case we use
+ // a monochrome monitor in the future
+ //
+ // // Check monitor type to decide index address (currently not use)
+ // DataByte = READ_S3_UCHAR(MiscOutR);
+ // ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+ //
+ // if (ColorMonitor) {
+ // Index_3x4 = (PVOID)S3_3D4_Index;
+ // Data_3x5 = (PVOID)S3_3D5_Data;
+ // } else {
+ // Index_3x4 = (PVOID)Mono_3B4;
+ // Data_3x5 = (PVOID)Mono_3B5;
+ // }
+ //
+ //=========================================================================
+
+ //
+ // -- Initialization Process Begin --
+ // According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
+ // to set the default values to VGA +3 mode.
+ //
+ WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // For ATI card(0x63) we may want to change the frequence
+ WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // Sequencer Register
+ for (Index = 1; Index < 5; Index++) {
+ WRITE_S3_UCHAR(Seq_Index, Index);
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
+ }
+
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+ WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte = DataByte & 0x7f;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // CRTC controller CR0 - CR18
+ for (Index = 0; Index < 25; Index++) {
+ WRITE_S3_UCHAR(S3_3D4_Index, Index);
+ WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
+ }
+
+ // attribute write
+ // program palettes and mode register
+ for (Index = 0; Index < 21; Index++) {
+ WaitForVSync();
+
+ DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
+ WRITE_S3_UCHAR(Attr_Index,Index);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
+ }
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ // graphics controller
+ for (Index = 0; Index < 9; Index++) {
+ WRITE_S3_UCHAR(GC_Index, Index);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
+ }
+
+ // turn off the text mode cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
+
+ // Unlock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
+
+ // Unlock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
+
+ // Disable enhanced mode
+ WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
+
+ // Turn off H/W Graphic Cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, SC5);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ //=========================================================================
+ //
+ // IBMBJB S3 errata sheet says that CR40 can not be read correctly after
+ // power up until it has been written to, suggested workaround is
+ // to use the power on default (0xA4) Since the intent of the
+ // existing code was to reset bit 0, 0xA4 will be used to reset
+ // the bit. The other bits that are reset select the desired
+ // default configuration.
+ //
+ // If this register is written by the firmware then this fix is
+ // unneccessary. If future modifications of the firmware were to
+ // remove all writes to this register then this fix would have to
+ // be added here. This is being added now to protect this code
+ // from possible firmware changes.
+ //
+ // // Disable enhanced mode registers access
+ // WRITE_S3_UCHAR(S3_3D4_Index, SC0);
+ // DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ // DataByte &= 0xfe;
+ // DataByte ^= 0x0;
+ //
+ // WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+ //
+
+ WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
+
+ //=========================================================================
+
+ // Set Misc 1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xc7;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0x80;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R2 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Set S3R4 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xec;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ //=========================================================================
+ //
+ // IBMBJB added this section to eliminate the DAC hardware cursor, this
+ // is done before setting registers 0x50 - 0x62 to default states
+ // so that R55's default state will not be undone.
+ //
+ // this sequence zeros the 2 least signifigant bits in command
+ // register 2 on the DAC
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
+ DataByte = READ_S3_UCHAR( S3_3D5_Data );
+ DataByte &= 0xfc;
+ DataByte |= 0x02;
+ WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
+
+ DataByte = READ_S3_UCHAR( DAC_Data );
+ DataByte &= 0xfc; // zero CR21,20 in DAC command
+ WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
+
+ //=========================================================================
+ //
+ // IBMBJB Added code to configure for 18 bit color mode and reload the
+ // palette registers because the firmware configures for 24 bit
+ // color. If this is done when the system driver initializes for
+ // graphics mode then the text mode colors can not be changed
+ // properly.
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
+
+ DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
+ DataByte &= 0xfd; // register 0 to select 6 bit
+ WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
+
+ // IBMBJB added write to SDAC PLL control register to make sure CLK0
+ // is correct if we have to reinitialize after graphics mode
+ // initialization, this does not bother the 928/Bt485 card
+ // because the Bt485 DAC looks very much like the SDAC
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
+ WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
+
+ for( i = 0, j = 0; i < 256; ++i ) // load all color registers
+ {
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
+ // state because some of them are set by the firmware and are
+ // not correct for our use
+ //
+ // NOTE: there are some writes to the DAC registers in code that
+ // executes later that depend on R55[1:0] being 00B, if the
+ // default state of R55 is changed make sure that these bits
+ // are not changed
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
+#ifdef SAM_256
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x40 );
+#else
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+#endif
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ // IBMBJB changed value written from 0 to 1 for an S3 864 based card to
+ // clear up bad display caused by 864->SDAC FIFO underrun
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ //=========================================================================
+ //
+ // IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
+ // transfer problem in parallel and continuous addressing modes
+ // Note: side effect of setting bit 7 was a garbled firmware screen after
+ // shutdown.
+
+ // Set SR65 bits 7 and 6
+ WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte |= 0x40;
+// DataByte |= 0xc0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Lock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Lock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+ WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
+
+ WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
+
+ WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data,0x00);
+
+ WRITE_S3_UCHAR(GC_Index,0x06);
+ WRITE_S3_UCHAR(GC_Data,0x04);
+
+ WRITE_S3_UCHAR(GC_Index,0x04);
+ WRITE_S3_UCHAR(GC_Data,0x02);
+
+ MemBase = 0xA0000;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 16; j++) {
+ WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
+ MemBase++;
+ }
+ // 32 bytes each character font
+ for (j = 16; j < 32; j++) {
+ WRITE_S3_VRAM(MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_S3_UCHAR(DAC_Mask, 0xff);
+
+ // select plane 0, 1
+ WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
+
+ // access to planes 0, 1.
+ WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x04);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x06);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
+
+ //
+ // Set screen into blue
+ //
+ for (DataLong = 0xB8000;
+ DataLong < 0xB8000+TWENTY_FIVE_LINES;
+ DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, ' ');
+ WRITE_S3_VRAM(DataLong+1, TEXT_ATTR);
+ }
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplayPpcS3Setup() */
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, flush the TB, and map the display
+ // frame buffer into the address space of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+
+ //
+ // The display has been put in graphics mode, and we need to
+ // reset it to text mode before we can display any text on it.
+ //
+
+ if (HalpResetDisplayParameters) {
+ HalpDisplayOwnedByHal = HalpResetDisplayParameters(COLS, ROWS);
+ HalpScreenStart = 0; // used by Cirrus scroll
+ HalpColumn = 0;
+ HalpRow = 0;
+ }
+
+ if (!HalpDisplayOwnedByHal && HalpDisplayControllerSetup != NULL) {
+ HalpDisplayControllerSetup();
+ }
+
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+
+ //
+ // Lower IRQL to its previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+
+VOID
+HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+
+ //=========================================================================
+ //
+ // TAB processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= COLS ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollScreen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacter(' ');
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= COLS) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+ HalpOutputCharacter(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+
+
+
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < COLS) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+} /* end of HalpOutputCharacterS3() */
+
+
+
+VOID
+HalpScrollS3(IN UCHAR line)
+{
+UCHAR i, DataByte;
+ULONG target;
+
+ for (i = 0; i < line; i ++) {
+ //=======================================================================
+ //
+ // wait for vertical sync to make scroll smooth
+
+ WaitForVSync();
+
+ //=======================================================================
+
+ for (target = 0xB8000;
+ target < 0xB8000+TWENTY_FOUR_LINES;
+ target += 2) {
+ DataByte = READ_S3_VRAM(target+ONE_LINE);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+ for (target = 0xB8000+TWENTY_FOUR_LINES;
+ target < 0xB8000+TWENTY_FIVE_LINES;
+ target += 2) {
+ WRITE_S3_VRAM(target, ' ' );
+ }
+ }
+}
+
+VOID
+WaitForVSync (VOID)
+{
+ UCHAR DataByte;
+ BOOLEAN test;
+
+ //
+ // Determine 3Dx or 3Bx
+ //
+
+ DataByte = READ_S3_UCHAR(MiscOutR);
+ ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+
+ // Unlock S3 ( S3R8 )
+ // UnLockS3();
+
+ //
+ // Test Chip ID = '81h' ?
+ //
+
+ // For standard VGA text mode this action is not necessary.
+ // WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ // if ((DataByte = READ_S3_UCHAR(S3_3D5_Data)) == 0x81) {
+ //
+ // Wait For Verttical Retrace
+ //
+
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x08 ? FALSE : TRUE;
+ }
+
+ // Wait for H/V blanking
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x01 ? TRUE : FALSE;
+ }
+ // }
+
+ // Lock S3 ( S3R8 )
+ // LockS3();
+
+ return;
+} /* end of WaitForVsync() */
+
+VOID ScreenOn(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte & 0xdf;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+VOID ScreenOff(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte | 0x20;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Weitek P9000 display contoller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ // For now I'll leave the P9000 in the same state that the firmware
+ // left it in. This should be 640x480.
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ if (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P9_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+ //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ //HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+} //end of HalpDisplayPpcP9Setup
+
+VOID
+HalpDisplayCharacterP9 (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P9_VIDEO_MEMORY_BASE,
+ // (PVOID)(P9_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // Scroll up one line
+ Destination = HalpVideoMemoryBase;
+ Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpVideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP9((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP9(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG tmp;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacterP9('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+ // Move the font bits around so the characters look right.
+ tmp = (FontValue >> 3) & 0x11111111; //bits 7 and 3 to the right 3
+ tmp |= (FontValue >> 1) & 0x22222222; //bits 6 and 2 to the right 1
+ tmp |= (FontValue << 1) & 0x44444444; //bits 5 and 1 to the left 1
+ tmp |= (FontValue << 3) & 0x88888888; //bits 4 and 0 to the left 3
+ FontValue = tmp;
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0)
+ *Destination = 0xFF; //Make this pixel white
+
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Weitek P9100 display contoller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ // For now I'll leave the P9100 in the same state that the firmware
+ // left it in. This should be 640x480.
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ if (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P91_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+ //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ //HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+} //end of HalpDisplayPpcP91Setup
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P91_VIDEO_MEMORY_BASE,
+ // (PVOID)(P91_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // Scroll up one line
+ Destination = HalpVideoMemoryBase;
+ Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpVideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP91((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG tmp;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacterP91('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0)
+ *Destination = 0xFF; //Make this pixel white
+
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+//
+// Cirrus Device Driver
+//
+
+// Routine Description:
+//
+// This routine displays a character at the current x and y positions in
+// the frame buffer. If a newline is encounter, then the frame buffer is
+// scrolled. If characters extend below the end of line, then they are not
+// displayed.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+
+VOID
+HalpDisplayCharacterCirrus (
+ IN UCHAR Character
+ )
+{
+
+//
+// If the character is a newline, then scroll the screen up, blank the
+// bottom line, and reset the x position.
+//
+
+ if (Character == '\n')
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+
+//
+// added tab processing
+//
+
+ else if ( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if ( HalpColumn >= COLS ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column
+ // of next line
+
+ if ( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollScreen( 1 );
+ else ++HalpRow;
+ }
+ }
+ else if (Character == '\r')
+ {
+ HalpColumn = 0;
+ }
+ else if (Character == 0x7f)
+ { // DEL character
+ if (HalpColumn != 0)
+ {
+ HalpColumn -= 1;
+ HalpOutputCharacterCirrus(' ');
+ HalpColumn -= 1;
+ }
+ else // do nothing
+ ;
+ }
+ else if (Character >= 0x20)
+ {
+ // Auto wrap for 80 columns
+ // per line
+ if (HalpColumn >= COLS)
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+ HalpOutputCharacterCirrus(Character);
+ }
+ // skip the nonprintable character
+}
+
+
+//
+//
+// Routine Description:
+//
+// This routine insert a set of pixels into the display at the current x
+// cursor position. If the x cursor position is at the end of the line,
+// then no pixels are inserted in the display.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+
+
+VOID
+HalpOutputCharacterCirrus (
+ IN UCHAR AsciiChar
+ )
+{
+ PUCHAR Destination;
+ ULONG I;
+
+//
+// If the current x cursor position is within the current line, then insert
+// the specified pixels into the last line of the text area and update the
+// x cursor position.
+//
+
+ if (HalpColumn < COLS)
+ {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ Destination = (PUCHAR)(CIRRUS_TEXT_MEM + I + HalpScreenStart);
+ WRITE_CIRRUS_VRAM(Destination, AsciiChar);
+ HalpColumn += 1;
+ }
+}
+
+
+//
+// Routine Description:
+//
+// This routine initializes the Cirrus CL-GD5430 graphics controller chip
+//
+
+static void updattr(IN int rg,IN unsigned char val)
+{
+ inp(0x3da);
+ outportb(0x3c0,rg);
+ outportb(0x3c0,val);
+ outportb(0x3c0,((unsigned char)(rg | 0x20)));
+}
+
+
+static void set_ext_regs(IN int reg,IN unsigned char *p)
+{
+ unsigned char index, data;
+
+ while (*p != 0xff)
+ {
+ index= *p++;
+ data= *p++;
+ setreg(reg,index,data);
+ }
+}
+
+
+VOID
+HalpDisplayPpcCirrusSetup (
+ VOID
+ )
+{
+ int i;
+
+
+
+ if(HalpVideoMemoryBase == NULL) {
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+//
+// Assert synchronous reset while setting the clock mode
+//
+
+ setreg(0x3c4,0,1); // assert synchronous reset
+
+ outportb(0x3c2,0x67);
+
+ for ( i = 0; i < 21; i++ ) updattr(i,attr3[i]);
+
+ setreg(0x3d4,0x11,0x20);
+ for ( i = 0; i < 32; i++ ) setreg(0x3d4,i,crtc3[i]);
+
+ for ( i = 0x00;i < 9; i++ ) setreg(0x3ce,i,graph3[i]);
+
+ for ( i = 0; i < 5; i++ ) setreg(0x3c4,i,seq3[i]);
+
+ set_ext_regs (0x3c4,eseq3);
+ set_ext_regs (0x3d4,ecrtc3);
+ set_ext_regs (0x3ce,egraph3);
+ set_ext_regs (0x3c0,eattr3);
+
+//
+// Reset Hidden color register
+//
+
+ inp(0x3c6);
+ inp(0x3c6);
+ inp(0x3c6);
+ inp(0x3c6);
+ outp(0x3c6,0x00);
+
+//
+// Load 8x16 font
+//
+
+ load8x16();
+
+//
+// Load color palette
+//
+
+ load_ramdac();
+
+ outportb(0x3c6,0xff);
+
+//
+// Screen blank
+//
+
+ clear_text();
+
+//
+// Initialize the current display column, row, and ownership values.
+//
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayOwnedByHal = TRUE;
+ HalpScreenStart = 0;
+}
+
+VOID HalpScrollCirrus(
+ IN UCHAR line
+ )
+{ ULONG LogicalTarget, PhysicalTarget;
+ int i;
+
+ for (i=0; i < line; i++) {
+
+ HalpScreenStart = HalpScreenStart + ONE_LINE;
+ setreg(0x3d4,0xC, (UCHAR) (HalpScreenStart >> 9));
+ setreg(0x3d4,0xD, (UCHAR) ((HalpScreenStart >> 1) & 0xFF));
+
+ for (LogicalTarget = TWENTY_FOUR_LINES;
+ LogicalTarget < TWENTY_FIVE_LINES;
+ LogicalTarget += 2) {
+ PhysicalTarget = LogicalTarget + HalpScreenStart + CIRRUS_TEXT_MEM;
+ WRITE_CIRRUS_VRAM(PhysicalTarget, ' ' );
+ WRITE_CIRRUS_VRAM(PhysicalTarget+1, TEXT_ATTR );
+ }
+ }
+}
+
+static void clear_text(VOID)
+{
+ unsigned long p;
+
+//
+// fill plane 0 and 1 with 0x20 and 0x1f
+//
+
+ for (p = CIRRUS_TEXT_MEM;
+ p < CIRRUS_TEXT_MEM+TWENTY_FIVE_LINES;
+ p += 2)
+ {
+ WRITE_CIRRUS_VRAM(p, ' ');
+ WRITE_CIRRUS_VRAM(p+1, TEXT_ATTR);
+ }
+}
+
+static void load8x16(VOID)
+{
+ int i, j;
+ PUCHAR address;
+
+//
+// load 8x16 font into plane 2
+//
+
+ setreg(0x3c4,0x04,(seq3[4] | 0x04));
+
+//
+// disable video and enable all to cpu to enable maximum video
+// memory access
+//
+
+ setreg(0x3c4,0x01,seq3[1] | 0x20);
+ setreg(0x3c4,2,4);
+
+ setreg(0x3ce,0x05,graph3[5] & 0xef);
+ setreg(0x3ce,0x06,0x05);
+
+
+//
+// fill plane 2 with 8x16 font
+
+ address = (void *) (CIRRUS_FONT_MEM);
+ for ( i = 0; i < 256; i++ )
+ {
+ for ( j = 0; j < 16; j++ )
+ {
+ WRITE_CIRRUS_VRAM(address,VGAFont8x16[i*16+j]);
+ address++;
+ }
+
+ for ( j = 16; j < 32; j++ )
+ {
+ WRITE_CIRRUS_VRAM(address,0);
+ address++;
+ }
+ }
+
+ setreg(0x3c4,0x01,seq3[1]);
+ setreg(0x3c4,0x04,seq3[4]);
+ setreg(0x3c4,2,seq3[2]);
+
+ setreg(0x3ce,0x06,graph3[6]);
+ setreg(0x3ce,0x05,graph3[5]);
+}
+
+
+static void load_ramdac()
+{
+ int ix,j;
+
+ for ( ix = 0,j = 0; j <= 0x0FF ; ix = ix+3,j++ )
+ {
+ outp(0x3c8,(unsigned char)j); // write ramdac index
+ outp(0x3c9,TextPalette[ix]); // write red
+ outp(0x3c9,TextPalette[ix+1]); // write green
+ outp(0x3c9,TextPalette[ix+2]); // write blue
+ }
+}
+
+
+
+
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 2 << 8; // AH = 2
+ Ebx = 0; // BH = page number
+ Edx = (HalpRow << 8) + HalpColumn;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
+ Ebx = 0;
+ Ecx = 1;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ HalpColumn += 1;
+
+}
+
+
+VOID HalpScrollINT10 (
+ IN UCHAR LinesToScroll)
+
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 6 << 8; // AH = 6 (scroll up)
+ Eax |= LinesToScroll; // AL = lines to scroll
+ Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
+ Ecx = 0; // CH,CL = upper left
+ Edx = ((ROWS-1) << 8) + COLS - 1; // DH,DL = lower right
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+VOID HalpDisplayINT10Setup (VOID)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ //
+ // Reset the display to mode 3
+ //
+ Eax = 0x0003; // Function 0, Mode 3
+ Ebx = Ecx = Edx = Esi = Edi = Ebp = 0;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Set cursor to (0,0)
+ //
+ Eax = 0x02 << 8; // AH = 2
+ Ebx = 0; // BH = page Number
+ Edx = 0; // DH = row DL = column
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Make screen white on blue by scrolling entire screen
+ //
+ Eax = 0x06 << 8; // AH = 6 AL = 0
+ Ebx = TEXT_ATTR << 8; // BH = attribute
+ Ecx = 0; // (x,y) upper left
+ Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
+ Edx += HalpScrollLine/2;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxds1385.c b/private/ntos/nthals/haleagle/ppc/pxds1385.c
new file mode 100644
index 000000000..b1a48ae12
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxds1385.c
@@ -0,0 +1,386 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Change real time clock mapping to port 71.
+ Code assumes the DS1385S chip is compatible with existing
+ PC/AT type RTC's. The only known exception to PC/AT
+ compatibility on S-FOOT is the use of ports 810 and 812.
+ These ports provide password security for the RTC's NVRAM,
+ and are currently unused in this port since this address space
+ is available from kernel mode only in NT.
+
+ Steve Johns (sjohns@pets.sps.mot.com)
+ Changed to support years > 1999
+
+--*/
+
+#include "halp.h"
+#include "pxds1585.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClockDs (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClockDs (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if (TimeFields->Year > 1999)
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ else
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData);
+}
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+ can be configured to do this,... but as a quick fix I am doing it
+ here. (plj)
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+
+ BcdValue = HalpReadRawClockRegister(Register);
+ return (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
+}
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the SIO NMI is always enabled.
+ //
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData, Value);
+ return;
+}
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+ BcdValue = ((Value / 10) << 4) | (Value % 10);
+ HalpWriteRawClockRegister(Register, BcdValue);
+ return;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxds1585.h b/private/ntos/nthals/haleagle/ppc/pxds1585.h
new file mode 100644
index 000000000..cee3e7fd5
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxds1585.h
@@ -0,0 +1,106 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxds1585.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+
+
+
+typedef struct _RTC_CONTROL {
+ UCHAR Reserved0[0x71];
+ UCHAR RtcData; // Offset 0x71
+} RTC_CONTROL, *PRTC_CONTROL;
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x74];
+ UCHAR NvramIndexLo; // Offset 0x74
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_BATTERY_BACKED_UP_RAM 14 // battery backed up RAM [0..49]
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxenviro.c b/private/ntos/nthals/haleagle/ppc/pxenviro.c
new file mode 100644
index 000000000..3248fbbf1
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxenviro.c
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxenviro.c
+
+Abstract:
+
+ This module implements the interface to the HAL get and set
+ environment variable routines for a Power PC system.
+
+
+Author:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+#include "fwnvr.h"
+
+// This is initialized in pxsystyp during phase 0 init.
+NVR_SYSTEM_TYPE nvr_system_type = nvr_systype_unknown;
+
+KSPIN_LOCK NVRAM_Spinlock;
+
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+
+{
+
+KIRQL Irql;
+PUCHAR tmpbuffer;
+
+
+ //
+ // Check input parameters
+ //
+ if (Variable == NULL ||
+ *Variable == 0 ||
+ Length < 1 ||
+ Buffer == NULL)
+ return(ENOENT);
+
+ //
+ // Grab control of NVRAM
+ //
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql);
+
+ (VOID)nvr_initialize_object(nvr_system_type);
+
+ if ((tmpbuffer = nvr_get_GE_variable(Variable)) == NULL) {
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOENT);
+ }
+
+ //
+ // Copy the environment variable's value to Buffer
+ //
+
+ do {
+ *Buffer = *tmpbuffer++;
+ if (*Buffer++ == 0) {
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ESUCCESS);
+ }
+ } while (--Length);
+
+ //
+ // Truncate the returned string. The buffer was too short.
+ //
+ *--Buffer = 0;
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOMEM);
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+
+{
+ ARC_STATUS ReturnValue;
+ KIRQL Irql;
+
+
+
+ if (Value == NULL) return(ENOENT);
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql); // Grab control of NVRAM
+
+ (VOID)nvr_initialize_object(nvr_system_type);
+
+ ReturnValue = nvr_set_GE_variable(Variable,Value);
+
+ nvr_delete_object(); // free object created by nvr_init_object
+
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+
+ return(ReturnValue);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxflshbf.s b/private/ntos/nthals/haleagle/ppc/pxflshbf.s
new file mode 100644
index 000000000..dd7244b39
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxflshbf.s
@@ -0,0 +1,186 @@
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxflshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a Power PC
+// system.
+//
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+//
+// Used PowerPC eieio instruction to flush writes
+//
+//--
+
+#include "kxppc.h"
+ .extern HalpIoControlBase
+ .set ISA, r.7
+
+
+// SBTTL("Flush Write Buffer")
+//
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+//
+// It is required that the results of all stores to memory and I/O registers,
+// performed in "critical sections" just prior to calling KeFlushWriteBuffer,
+// be seen by other processors and mechanisms before returning from this
+// routine (KeFlushWriteBuffer). All write-posting queues, both processor and
+// external hardware, must be flushed so that their data are seen by other
+// processors and controllers on both the PCI and ISA busses.
+//
+
+//
+// The Eagle will initiate flushing it's write posting queue on either
+// an EIEIO or a SYNC. However, an EIEIO is a NOP on a 603, so we use
+// a LOAD from ISA I/O space to get the same effect.
+//
+
+
+ eieio //
+ lwz r.4,[toc]HalpIoControlBase(r.toc)
+ lwz r.4,0(r.4)
+ lbz r.4, 0x21(r.4)
+
+//
+// Lastly, theFlush write buffers on the processor! To do this, we must use the
+// "sync" instruction. The EIEIO instruction does NOT provide the required
+// synchronization with external hardware and controllers.
+//
+
+ sync
+
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+ LEAF_ENTRY(HalpPatch_KeFlushWriteBuffer)
+
+ mflr r.8 // Save LR
+ bl Here
+Here: mflr r.9
+ mtlr r.8 // Restore LR
+
+ addi r.3, r.9, ..HalpFlushWriteBuffer603-Here
+ addi r.4, r.9, ..HalpFlushWriteBuffer604-Here
+
+ mfpvr r.0 // Distinguish 603/603e from 604/604e
+ andis. r.0, r.0, 0x0002
+ beq PatchTOC
+ mr r.4, r.3
+PatchTOC:
+ lwz r.7, [toc]KeFlushWriteBuffer(r.toc)
+ stw r.4, 0(r.7)
+ dcbf r.0, r.7 // Flush it from the L1 cache
+
+ LEAF_EXIT(HalpPatch_KeFlushWriteBuffer)
+
+
+ LEAF_ENTRY(HalpFlushWriteBuffer603)
+ lwz r.4,[toc]HalpIoControlBase(r.toc)
+ lwz r.4,0(r.4)
+ lbz r.4, 0x21(r.4)
+ sync
+ LEAF_EXIT(HalpFlushWriteBuffer603)
+
+
+
+ LEAF_ENTRY(HalpFlushWriteBuffer604)
+ eieio // Initiate flushing the Eagle write-post buffers
+ sync // Wait for the flushing to complete
+ LEAF_EXIT(HalpFlushWriteBuffer604)
+
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpSynchronizeExecution()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSynchronizeExecution)
+
+ sync // synchronize
+
+ LEAF_EXIT(HalpSynchronizeExecution)
+
+
+//
+//++
+//
+// VOID
+// HalpSetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+// HashedPageTableSize is unused because we ASSUME that the HPT is 64K
+//
+
+ LEAF_ENTRY(HalpSetSDR1)
+
+ mtsdr1 r.3
+
+ LEAF_EXIT(HalpSetSDR1)
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxflshio.c b/private/ntos/nthals/haleagle/ppc/pxflshio.c
new file mode 100644
index 000000000..e13615ec9
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxflshio.c
@@ -0,0 +1,128 @@
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ psflshio.c
+
+Abstract:
+
+ This module implements miscellaneous PowerPC HAL functions.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.ibm.com)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 1;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // check for 601, it has a combined I and D cache that bus snoops
+ //
+ //
+
+ if ((HalpGetProcessorVersion() >> 16) != 1) {
+
+ //
+ // If the I/O operation is not a DMA operation,
+ // and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+ // WARNING: HalSweepDcache is NOT MP-coherent, so calling it like
+ // this makes this HAL UP-only!
+ //
+
+ if (((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ }
+ return;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxhalp.h b/private/ntos/nthals/haleagle/ppc/pxhalp.h
new file mode 100644
index 000000000..66bbf8e46
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxhalp.h
@@ -0,0 +1,253 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ pxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ PowerPC specific interfaces, defines and structures.
+
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added externs for HalpInterruptBase,HalpPciConfigBase
+ Added extern for HalpIoControlBase
+ Added prototype for HalpHandleDecrementerInterrupt (was in halp.h)
+ changed adapter object structure to be compatible with the intel HAL
+
+--*/
+
+#ifndef _PXHALP_
+#define _PXHALP_
+
+
+//
+// Define global data used to locate the IO control space, the interrupt
+// acknowlege, and the Pci config base.
+//
+
+extern PVOID HalpIoControlBase;
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpInterruptBase;
+extern PVOID HalpPciConfigBase;
+extern PVOID HalpErrorAddressRegister;
+extern PVOID HalpPciIsaBridgeConfigBase;
+
+//
+// Define adapter object structure.
+//
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IsaBusMaster;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters
+ );
+
+BOOLEAN
+HalpCreateSioStructures(
+ VOID
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpFieldExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleDecrementerInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ );
+
+ULONG
+HalpUpdateDecrementer(
+ ULONG
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace(
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace(
+ VOID
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+PVOID
+KePhase0MapIo(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+PVOID
+KePhase0DeleteIoMap(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+ULONG
+HalpCalibrateTB(
+ VOID
+ );
+
+VOID
+HalpZeroPerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ );
+
+#endif // _PXHALP_
diff --git a/private/ntos/nthals/haleagle/ppc/pxhwsup.c b/private/ntos/nthals/haleagle/ppc/pxhwsup.c
new file mode 100644
index 000000000..dd0d1ea39
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxhwsup.c
@@ -0,0 +1,2199 @@
+/*++
+
+Copyright (C) 1990-1995 Microsoft Corporation
+
+Copyright (C) 1994,1995 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC Port
+ Remove support for internal bus and devices
+ Changed HalFreeCommonBuffer to support S-FOOT address inversion
+ Added PCI, PCMCIA, and ISA bus support
+ Removed support for internal DMA controller
+ Change HalTranslateBusAddress to support S-FOOTS memory map
+ Deleted HalpReadEisaBus - this code was specific to EISA buses
+ Changed IoMapTransfer to support S-FOOT address inversion
+ Added support for guaranteed contigous common buffers
+
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+#include <pxmemctl.h>
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// Define map buffer variables
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Amount
+ );
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Allocate the actual buffer.
+ //
+
+
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+
+
+
+ //
+ // Memory space inverion
+ //
+
+
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (!AdapterObject->IsaBusMaster) {
+ LogicalAddress->LowPart |= IO_CONTROL_PHYSICAL_BASE;
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. If not all of
+ the registers could be allocated this field is updated to show how
+ many were.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+ return;
+
+}
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: PCI, Isa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != PCIBus &&
+ DeviceDescription->InterfaceType != PCMCIABus) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateIsaAdapter( DeviceDescription,
+ NumberOfMapRegisters);
+ return(adapterObject);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == NULL) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->IsaBusMaster = FALSE;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+
+ ULONG pageOffset;
+ ULONG index;
+ ULONG transferLength;
+ PULONG pageFrame;
+ ULONG logicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ BOOLEAN useBuffer;
+ PHYSICAL_ADDRESS returnAddress;
+
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) | IO_CONTROL_PHYSICAL_BASE;
+
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ //
+ // do the memory inversion on the logical address
+ //
+
+ logicalAddress = ( translationEntry->PhysicalAddress + pageOffset)
+ | IO_CONTROL_PHYSICAL_BASE;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // ISA masters require memory to be at less than 16 MB.
+ // always use map buffers for ISA busmasters
+ //
+
+ if (((logicalAddress+transferLength) & ~IO_CONTROL_PHYSICAL_BASE)
+ >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset | IO_CONTROL_PHYSICAL_BASE;
+
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ if (AdapterObject != NULL) {
+ if (AdapterObject->IsaBusMaster == TRUE) {
+ returnAddress.LowPart = logicalAddress & ~IO_CONTROL_PHYSICAL_BASE;
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ } else {
+
+
+ HalpIsaMapTransfer(
+ AdapterObject,
+ logicalAddress,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a PPC Machine Check interrupt occurs.
+ It print the appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Unused
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ int i;
+
+ //
+ // raise irql to machine check level
+ //
+
+ KeRaiseIrql(MACHINE_CHECK_LEVEL,&OldIrql);
+
+ //
+ // Let the world know what happened.
+ //
+ HalDisplayString("\n *** Machine Check Exception ***\n");
+
+ //
+ // check memory controller machine check sources
+ //
+
+ HalpHandleMemoryError();
+
+ //
+ // check Bus NMI sources
+ //
+
+ HalpHandleIoError();
+
+ //
+ // Bug check - after stalling to allow
+ // any information printed on the screen
+ // by the Memory and IO Handlers to be read.
+ //
+ for (i=0; i<12; i++) {
+ HalDisplayString(".");
+ KeStallExecutionProcessor(1000000);
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ KeLowerIrql(OldIrql);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the required map buffers.
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+{
+
+ PVOID virtualAddress;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ HalpMapBufferPhysicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS;
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ HalpMapBufferSize,
+ HalpMapBufferPhysicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ return FALSE;
+
+ }
+
+ HalpMapBufferPhysicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return TRUE;
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry and that a 64K physical boundary is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress ||
+ (((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this boundary.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxidle.c b/private/ntos/nthals/haleagle/ppc/pxidle.c
new file mode 100644
index 000000000..038902d85
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxidle.c
@@ -0,0 +1,65 @@
+/*++
+TITLE("Processor Idle")
+
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ pxidle.c
+
+abstract:
+
+ This module implements system platform dependent power management
+ support.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+
+
+VOID
+HalProcessorIdle(
+ VOID
+ )
+
+/*++
+
+ Routine Description:
+
+ This function is called when the current processor is idle with
+ interrupts disabled. There is no thread active and there are no
+ DPCs to process. Therefore, power can be switched to a standby
+ mode until the the next interrupt occurs on the current processor.
+
+ N.B. This routine is entered with EE in MSR clear. This routine
+ must do any power management enabling necessary, set the EE
+ bit in MSR, then either return or wait for an interrupt.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+
+--*/
+
+{
+ extern VOID HalpProcessorIdle(VOID);
+ HalpProcessorIdle();
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxinfo.c b/private/ntos/nthals/haleagle/ppc/pxinfo.c
new file mode 100644
index 000000000..0ec6698b9
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxinfo.c
@@ -0,0 +1,97 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ pxinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+
+#include "halp.h"
+
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+ union {
+ HAL_POWER_INFORMATION PowerInf;
+ HAL_PROCESSOR_SPEED_INFORMATION ProcessorInf;
+ } U;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxinithl.c b/private/ntos/nthals/haleagle/ppc/pxinithl.c
new file mode 100644
index 000000000..28233a420
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxinithl.c
@@ -0,0 +1,396 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInitializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+
+--*/
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxsystyp.h"
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPciConfigSize;
+
+ULONG
+HalpSizeL2Cache(
+ VOID
+ );
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+VOID
+HalpCopyROMs(
+ VOID
+ );
+
+
+VOID HalpPatch_KeFlushWriteBuffer(VOID);
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+ULONG L2_Cache_Size;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+VOID
+HalpEnableEagleSettings(
+ VOID
+ );
+
+VOID
+HalpCheckHardwareRevisionLevels(
+ VOID
+ );
+
+VOID
+HalpDumpHardwareState(
+ VOID
+ );
+
+VOID
+HalpEnableL2Cache(
+ VOID
+ );
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ extern KSPIN_LOCK NVRAM_Spinlock;
+ PKPRCB Prcb;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ if (Prcb->Number == 0)
+ HalpSetSystemType( LoaderBlock );
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ //
+ // Get access to I/O space, check if I/O space has already been
+ // mapped by debbuger initialization.
+ //
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+ //
+ // Initialize the display adapter. Must be done early
+ // so KeBugCheck() will be able to display
+ //
+ if (!HalpInitializeDisplay(LoaderBlock))
+ return FALSE;
+
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Initialize Spinlock for NVRAM
+ //
+
+ KeInitializeSpinLock( &NVRAM_Spinlock );
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_MP_PPC_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#endif
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // Calibrate execution stall
+ //
+ HalpCalibrateStall();
+
+ //
+ // Patch KeFlushWriteBuffer to the optimum code sequence
+ //
+ HalpPatch_KeFlushWriteBuffer();
+
+ //
+ // Size the L2 cache
+ //
+ L2_Cache_Size = HalpSizeL2Cache();
+ PCR->SecondLevelIcacheSize = L2_Cache_Size << 10;
+ PCR->SecondLevelDcacheSize = L2_Cache_Size << 10;
+
+ //
+ // Compute size of PCI Configuration Space mapping
+ //
+ HalpPciConfigSize = PAGE_SIZE * ((1 << (HalpPciMaxSlots-2)) + 1);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+
+ }
+
+
+ //
+ // InitializeInterrupts
+ //
+
+ if (!HalpInitializeInterrupts())
+ return FALSE;
+
+ //
+ // return success
+ //
+ return TRUE;
+
+
+ } else {
+
+ if (Phase != 1)
+ return(FALSE);
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+
+ HalpRegisterInternalBusHandlers ();
+
+
+ if (!HalpAllocateMapBuffer()) {
+ return FALSE;
+ }
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+
+ if (!HalpMapIoSpace()) {
+ return FALSE;
+ }
+
+
+ if (!HalpCreateSioStructures()) {
+ return FALSE;
+ }
+
+ HalpCheckHardwareRevisionLevels();
+ HalpEnableL2Cache();
+ HalpEnableEagleSettings();
+ HalpDumpHardwareState();
+ HalpCopyROMs();
+
+ return TRUE;
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized. In order to access the PCR from this
+ routine, use the PCRsprg1 macro, not the PCR macro.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG IcacheSize, DcacheSize;
+ ULONG CacheBlockAlignment;
+
+ switch (HalpGetProcessorVersion() >> 16) {
+
+ case 1: // 601
+ IcacheSize = 32*1024;
+ DcacheSize = 32*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 3: // 603
+ IcacheSize = 8*1024;
+ DcacheSize = 8*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 6: // 603e
+ case 7: // 603ev
+ case 4: // 604
+ IcacheSize = 16*1024;
+ DcacheSize = 16*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 9: // 604+
+ IcacheSize = 32*1024;
+ DcacheSize = 32*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ default:
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+
+
+ PCRsprg1->FirstLevelIcacheSize = IcacheSize;
+ PCRsprg1->FirstLevelDcacheSize = DcacheSize;
+ PCRsprg1->DcacheAlignment = CacheBlockAlignment;
+ PCRsprg1->IcacheAlignment = CacheBlockAlignment;
+
+
+ return;
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxintsup.s b/private/ntos/nthals/haleagle/ppc/pxintsup.s
new file mode 100644
index 000000000..1472ea053
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxintsup.s
@@ -0,0 +1,290 @@
+// TITLE("Enable and Disable Processor Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxintsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to mask and unmask
+// interrupts on a PowerPC system.
+//
+// Author:
+//
+// Steve Johns
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 30-Dec-93 plj Added 603 support.
+// 7-Mar-95 Steve Johns Added HalpUpdate8259 for use in PXIRQL.C
+// 13-Mar-95 Steve Johns Assembly version of KeRaiseIrql
+//
+//--
+#include "halppc.h"
+
+
+
+
+
+
+ .extern HalpIoControlBase
+ .extern Halp8259MaskTable
+
+ .set NewIrql, r.3
+ .set OldIrql, r.4
+ .set Index, r.4
+ .set ISA_Base, r.5
+ .set MaskTable, r.6
+ .set MasterMask, r.8
+ .set SlaveMask, r.9
+ .set PCR, r.10
+ .set MSR, r.11
+ .set CLOCK2_LEVEL, 28
+
+#define KE_FLUSH_WRITE_BUFFERS() \
+ sync ;\
+ lbz r.0, 0x21(ISA_Base)
+
+
+//
+// VOID HalpUpdate8259(KIRQL NewIrql)
+//
+
+ LEAF_ENTRY(HalpUpdate8259)
+
+
+ //
+ // Get pointers to Halp8259MaskTable & ISA I/O space
+ //
+
+ lwz MaskTable,[toc]Halp8259MaskTable(r.toc)
+ add Index, NewIrql, NewIrql // Halp8259MaskTable is table of USHORTS
+
+ lwz ISA_Base,[toc]HalpIoControlBase(r.toc)
+ lwz ISA_Base,0(ISA_Base)
+
+ //
+ // MasterMask = Halp8259MaskTable[NewIrql];
+ //
+ lhzx MasterMask,Index,MaskTable
+
+ //
+ // SlaveMask = MasterMask >> 8;
+ //
+ srwi SlaveMask, MasterMask, 8
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt1ControlPort1),
+ // (UCHAR) MasterMask);
+ //
+ stb MasterMask, 0x21(ISA_Base)
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt2ControlPort1),
+ // (UCHAR) SlaveMask);
+ //
+ stb SlaveMask, 0xA1(ISA_Base)
+
+
+ //
+ // Make sure Eagle write buffers are flushed
+ //
+
+ KE_FLUSH_WRITE_BUFFERS()
+
+
+ LEAF_EXIT (HalpUpdate8259)
+
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql ( KIRQL NewIrql, OUT PKIRQL OldIrql)
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and
+// returns the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that receives the old
+// IRQL value.
+//
+// NOTE: This assembly routine has been measured to be 25% faster than
+// its "C" equivalent.
+
+ LEAF_ENTRY (KeRaiseIrql)
+
+ mfsprg PCR,1 // Get ptr to the PCR
+
+ cmpwi NewIrql, DISPATCH_LEVEL
+ mfmsr MSR
+
+ //
+ // *OldIrql = PCR->CurrentIrql;
+ //
+ lbz r0,PcCurrentIrql(PCR)
+ stb r0, 0(OldIrql)
+
+
+ //
+ // If this is a software-to-software transition,
+ // then don't change hardware interrupt state.
+ //
+ // if (NewIrql <= DISPATCH_LEVEL)
+ // goto RaiseSoftwareToSoftwareIrql;
+ //
+ ble RaiseSoftwareToSoftware
+
+ cmpli cr1, 0, NewIrql, CLOCK2_LEVEL
+
+
+ //
+ // MSR[EE] = 0;
+ //
+ rlwinm r.0,MSR,0,~MASK_SPR(MSR_EE,1)
+ mtmsr r.0
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+
+ //
+ // if (NewIrql >= CLOCK2_LEVEL) {
+ // goto RaiseSoftwareToSoftware;
+ // }
+ //
+
+ bge 1,RaiseSoftwareToSoftware
+
+
+
+
+
+ //
+ // Get pointers to Halp8259MaskTable & ISA I/O space
+ //
+
+ lwz MaskTable,[toc]Halp8259MaskTable(r.toc)
+ add Index, NewIrql, NewIrql // Halp8259MaskTable is table of USHORTS
+
+ lwz ISA_Base,[toc]HalpIoControlBase(r.toc)
+ lwz ISA_Base,0(ISA_Base)
+
+ //
+ // MasterMask = Halp8259MaskTable[NewIrql];
+ //
+ lhzx MasterMask,Index,MaskTable
+
+ //
+ // SlaveMask = MasterMask >> 8;
+ //
+ srwi SlaveMask, MasterMask, 8
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt1ControlPort1),
+ // (UCHAR) MasterMask);
+ //
+ stb MasterMask, 0x21(ISA_Base)
+
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt2ControlPort1),
+ // (UCHAR) SlaveMask);
+ //
+ stb SlaveMask, 0xA1(ISA_Base)
+
+
+ //
+ // Make sure Eagle write buffers are flushed.
+ //
+
+ KE_FLUSH_WRITE_BUFFERS()
+
+ //
+ // PCR->CurrentIrql = NewIrql;
+ //
+ stb NewIrql, PcCurrentIrql(PCR)
+
+
+ //
+ // MSR[EE] = 1;
+ //
+ ori MSR,MSR,MASK_SPR(MSR_EE,1)
+ mtmsr MSR
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ blr
+
+
+
+RaiseSoftwareToSoftware:
+ //
+ // PCR->CurrentIrql = NewIrql;
+ //
+ stb NewIrql, PcCurrentIrql(PCR)
+
+ LEAF_EXIT (KeRaiseIrql)
+
+
+
+//
+// VOID HalpResetIrqlAfterInterrupt(KIRQL NewIrql)
+//
+// Routine Description:
+//
+// This function disables external interrupts, lowers the current
+// IRQL to the specified value and returns with interrupts disabled.
+//
+// This routine is called instead of KeLowerIrql to return IRQL to
+// its level prior to being raised due to an external interrupt.
+//
+// We know current IRQL is > DISPATCH_LEVEL
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+
+// {
+// HalpDisableInterrupts();
+// PCR->CurrentIrql = NewIrql;
+// if (NewIrql < CLOCK2_LEVEL)
+// HalpUpdate8259(NewIrql);
+// }
+
+
+ LEAF_ENTRY (HalpResetIrqlAfterInterrupt)
+
+ mfmsr MSR
+ cmpwi NewIrql, CLOCK2_LEVEL
+ mfsprg PCR,1 // Get ptr to the PCR
+
+ //
+ // MSR[EE] = 0;
+ //
+ rlwinm MSR,MSR,0,~MASK_SPR(MSR_EE,1)
+ mtmsr MSR
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+
+ stb NewIrql,PcCurrentIrql(PCR)
+ blt+ ..HalpUpdate8259
+
+ LEAF_EXIT (HalpResetIrqlAfterInterrupt)
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxirql.c b/private/ntos/nthals/haleagle/ppc/pxirql.c
new file mode 100644
index 000000000..2fecf0219
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxirql.c
@@ -0,0 +1,261 @@
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// PXIRQL.C
+//
+// Abstract:
+//
+// This module implements the code necessary to lower and raise the current
+// Interrupt Request Level (IRQL).
+//
+//
+// Author:
+//
+// Jim Wooldridge (IBM)
+// Steve Johns (Motorola)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 22-Feb-94 Steve Johns (Motorola)
+// KeRaiseIrql - Disabled interrupts at PIC if IRQL >= DEVICE_LEVEL
+// KeLowerIrql - Enabled interrupts at PIC if IRQL < DEVICE_LEVEL
+// 15-Apr-94 Jim Wooldridge
+// Added irql interrupt mask table and expanded irql range from (0-8)
+// to (0-31).
+//
+//--
+
+#include "halp.h"
+
+//
+// Initialize the 8259 IRQL mask table
+//
+
+USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level
+ 0x0000, // irql1 APC
+ 0x0000, // irql2 Dispatch
+ 0x0000, // irql3
+ 0x0000, // irql4
+ 0x0000, // irql5
+ 0x0000, // irql6
+ 0x0000, // irql7
+ 0x0000, // irql8
+ 0x0000, // irql9
+ 0x0000, // irql10
+ 0x0080, // irql11 parallel
+ 0x00C0, // irql12 floppy
+ 0x00E0, // irql13 parallel
+ 0x00F0, // irql14 com 1
+ 0x00F8, // irql15 com 2
+ 0x80F8, // irql16 pci slot
+ 0xC0F8, // irql17 isa slot
+ 0xE0F8, // irql18 scsi
+ 0xF0F8, // irql19 mouse
+ 0xF8F8, // irql20 isa slot
+ 0xFCF8, // irql21 audio
+ 0xFEF8, // irql22 isa slot
+ 0xFFF8, // irql23 rtc
+ 0xFFF8, // irql24 cascade
+ 0xFFFA, // irql25 kb
+ 0xFFFB, // irql26 timer 1
+ 0xFFFB, // irql27 PROFILE_LEVEL
+ 0xFFFF, // irql28 CLOCK LEVEL
+ 0xFFFF, // irql29 IPI_LEVEL
+ 0xFFFF, // irql30 POWER_LEVEL
+ 0xFFFF // irql31 HIGH_LEVEL
+ };
+
+
+
+VOID
+KiDispatchSoftwareInterrupt(
+ VOID
+ );
+
+VOID
+HalpUpdate8259(
+ KIRQL NewIrql
+ );
+
+
+//
+// VOID
+// KeLowerIrql (
+// KIRQL NewIrql
+// )
+//
+// Routine Description:
+//
+// This function lowers the current IRQL to the specified value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+VOID
+KeLowerIrql(
+ KIRQL NewIrql
+ )
+
+{ KIRQL OldIrql;
+
+
+ OldIrql = PCR->CurrentIrql;
+
+ //
+ // If this is a software-to-software transition don't change hardware
+ // interrupt state
+ //
+
+ if (OldIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If old IRQL is < CLOCK2_LEVEL then interrupt are enabled
+ // in the MSR but the 8259 mask must be updated. If not, then
+ // interrupts need to be enabled, however the 8259 does not need to
+ // be updated.
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+ HalpUpdate8259(NewIrql);
+ HalpEnableInterrupts();
+ }
+ } else {
+ PCR->CurrentIrql = NewIrql;
+ }
+
+ //
+ // check for DPC's
+
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt)
+ KiDispatchSoftwareInterrupt();
+
+}
+
+#if 0 // This code has been re-written in assembly. See PXINTSUP.C
+//
+// VOID
+// HalpResetIrqlAfterInterrupt(
+// KIRQL TargetIrql
+// )
+//
+// Routine Description:
+//
+// This function disables external interrupts, lowers the current
+// IRQL to the specified value and returns with interrupts disabled.
+//
+// This routine is called instead of KeLowerIrql to return IRQL to
+// its level prior to being raised due to an external interrupt.
+//
+// We know current IRQL is > DISPATCH_LEVEL
+//
+// Arguments:
+//
+// TargetIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ )
+
+{
+
+ PUCHAR PIC_Address;
+ USHORT PIC_Mask;
+
+
+ HalpDisableInterrupts();
+ PCR->CurrentIrql = TargetIrql;
+
+ //
+ // If TargetIrql < CLOCK2_LEVEL, then the 8259 mask must be updated.
+ //
+
+ if (TargetIrql < CLOCK2_LEVEL) {
+ HalpUpdate8259(TargetIrql);
+ }
+}
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql (
+// KIRQL NewIrql,
+// PKIRQL OldIrql
+// )
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that receives the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+
+{
+ //
+ // If this is a software-to-software transition, don't change hardware
+ // interrupt state
+ //
+
+ if (NewIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If new IRQL is >= CLOCK2_LEVEL, disable interrupts in the MSR but
+ // don't touch the 8259's. Otherwise, leave interrupts enabled and
+ // update the 8259's.
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+ HalpUpdate8259(NewIrql);
+ HalpEnableInterrupts();
+ }
+
+ } else {
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ }
+}
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/pxisabus.c b/private/ntos/nthals/haleagle/ppc/pxisabus.c
new file mode 100644
index 000000000..0c0c03faf
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxisabus.c
@@ -0,0 +1,130 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
+#endif
+
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ //
+ // irq2 shows up on irq9
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ BusInterruptVector = 9;
+ }
+
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxl2.s b/private/ntos/nthals/haleagle/ppc/pxl2.s
new file mode 100644
index 000000000..045e29257
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxl2.s
@@ -0,0 +1,551 @@
+//
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// PXL2.S
+//
+// Abstract:
+//
+// This module implements the routines to size & enable the L2 cache
+// on an Eagle based system.
+//
+// Author:
+//
+// Steve Johns (sjohns@pets.sps.mot.com)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 11-Aug-94 saj Added Eagle L2 cache support for Big Bend.
+// 23-Nov-94 saj Added input parameter specifying write-back or write-thru
+// 01-Dec-94 saj Removed all hardware workarounds
+// Enable L2 Parity error checking (Eagle register 0xC4)
+// 08-Mar-95 saj Added input parameter EagleAC
+// 21-Aug-95 v-matth Steve's sizing functionality is walking on the
+// page file database if we have 128Mb of RAM. I'm
+// going to change it to save off main memory before
+// we do our writes to main memory, then restore those
+// values before we exit.
+// 01-Sep-95 saj Check if L2 is already enabled. If so, just exit.
+// Otherwise, size L2 and exit with L2 disabled. Don't read
+// DBATs, since can't be read reliably on 603e.
+//
+
+#include "kxppc.h"
+#include "halppc.h"
+
+ .extern HalpIoControlBase
+
+ .set HID0, 1008
+//
+// Eagle register A8 fields:
+//
+ .set CF_WRITE_THRU, 0x0001 // Write-through
+ .set CF_WRITE_BACK, 0x0002 // Write-back
+ .set CF_L2_MP, 0x0003 // Bits 1..0 (LE bit order)
+
+//
+// Eagle register AC fields:
+//
+ .set L2_EN, 0x40000000
+ .set L2_UPDATE_EN, 0x80000000
+ .set CF_FLUSH_L2, 0x10000000
+ .set CF_INV_MODE, 0x00001000
+//
+// L2 cache sizes:
+//
+ .set CF_L2_SIZE, 0x0030 // Bits 5..4 (LE bit order)
+ .set L2_1M, 0x0020
+ .set L2_512K, 0x0010
+ .set L2_256K, 0x0000
+ .set L2_LINE_SIZE, 32
+//
+// Local parameters
+//
+ .set CacheSize, r.3 // Return value
+ .set Pattern, r.3
+ .set Offset, r.5
+ .set EagleA8, r.6
+ .set EagleAC, r.7
+ .set L2off, r.8 // Eagle register A8 for L2 disabled
+ .set Restore, r.9
+ .set ISA, r.10 // Pointer to ISA I/O space
+ .set Virtual, r.11
+
+ .set Pattern0, 0x77777777 // Patterns for L2 cache sizing
+ .set Pattern1, 0x11111111
+ .set Pattern2, 0x22222222
+ .set Pattern3, 0X33333333
+ .set Pattern4, 0x44444444
+
+ .set VIRTUAL, 0xFFC00000 // Virtual address for L2 sizing
+ .set PHYSICAL, 0x00C00000 // Physical mem. used for L2 sizing
+ .set BAT_REG, 1 // BAT register to use for L2 sizing
+
+//***********************************************************************
+//
+// Synopsis:
+// ULONG HalpSizeL2(VOID)
+//
+// Purpose:
+// Sizes and enables the Eagle L2 cache.
+//
+// Returns:
+// Size of L2 cache or zero if not installed.
+// Valid sizes are 256, 512, and 1024.
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+
+
+ LEAF_ENTRY(HalpSizeL2)
+
+//
+// Lock the I-cache so instruction fetching doesn't impact the L2 cache
+// while we are sizing it. With the I-cache locked, instruction fetches will
+// not bursted in, so the L2 will not respond to those cycles.
+//
+ mfspr r.0, HID0
+ ori r.0, r.0, 0x2000 // Lock the Icache
+ mtspr HID0, r.0
+
+
+
+//
+// Get ptr to Eagle I/O (ISA bus)
+//
+ lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA,0(ISA)
+
+ LWI (EagleA8, 0x800000A8) // Processor Interface Configuration 1
+ addi EagleAC, EagleA8, 4 // Processor Interface Configuration 2
+
+//
+// Return if L2 cache is already enabled.
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ andis. r.4, r.0, (L2_EN >> 16) // Test L2_EN
+ beq Init_BAT
+
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ lwz r.4, 0xCFC(ISA)
+ andi. r.4, r.4, CF_L2_MP // Test CF_L2_MP
+ beq Init_BAT
+
+ andi. r.0, r.0, CF_L2_SIZE // Isolate L2 size field
+ cmpi 0,0,r.0, 0x30 // Reserved ?
+ li CacheSize, 0
+ beq L2_Exit
+
+ li CacheSize, 256
+ cmpi 0,0,r.0, L2_256K
+ beq L2_Exit
+
+ li CacheSize, 512
+ cmpi 0,0,r.0, L2_512K
+ beq L2_Exit
+
+ li CacheSize, 1024
+ b L2_Exit
+
+
+//
+// Initialize a BAT register to map the memory at PHYSICAL to VIRTUAL.
+// The sizing algorithm depends on the block of memory being marked WRITE-THRU.
+//
+Init_BAT:
+ LWI (Virtual, VIRTUAL)
+ LWI (r.0, PHYSICAL + 0x5A) // WIMG = 1011; PP = 10
+ mtdbatl BAT_REG, r.0
+ ori r.0, Virtual, 0x003F // BL = 2MB; Vs = Vp = 1
+ mtdbatu BAT_REG, r.0
+
+ isync
+
+
+
+//
+// Save the 4 test locations.
+//
+ lis Offset, 4 // Offset = 256K
+
+ lwz Pattern,[toc].LRDATA(rtoc) // Pattern <- address of .LRDATA
+ lwz r.0, 0 (Virtual)
+ stw r.0, 0 (Pattern) // Save Memory[ 0K];
+ dcbf r.0, Virtual
+
+ lwzux r.0, Virtual, Offset
+ dcbf r.0, Virtual
+ stw r0, 4(Pattern) // Save Memory[256K];
+
+ lwzux r.0, Virtual, Offset
+ mr r.9, Virtual // r.9 = Virtual + 512K
+ dcbf r.0, Virtual
+ stw r0, 8(Pattern) // Save Memory[512K];
+
+ lwzux r.0, Virtual, Offset
+ dcbf r.0, Virtual
+ stw r0,12(Pattern) // Save Memory[768K];
+ LWI (Virtual, VIRTUAL)
+
+
+//
+// Set the L2 cache to Write-Through
+//
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ lwz L2off, 0xCFC(ISA)
+ rlwinm L2off, L2off,0,~CF_L2_MP
+ ori r.0, L2off, CF_WRITE_THRU
+ stw r.0, 0xCFC(ISA)
+ sync
+
+//
+// Enable the L2 cache for 1 MB
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ rlwinm r.0, r.0, 0, ~CF_L2_SIZE
+ ori r.0, r.0, L2_1M
+ oris r.0, r.0, ((L2_EN+L2_UPDATE_EN) >> 16)
+ stw r.0, 0xCFC(ISA)
+ sync
+ sync
+
+//
+// Load the 4 test locations into the L2 cache.
+//
+ lwzx r.0, r.9, Offset // 768 KB
+ lwz r.0, 0(r.9) // 512 KB
+ lwzx r.0, Virtual, Offset // 256 KB
+ lwz r.0, 0 (Virtual) // 0 KB
+
+
+//
+// Store different patterns to the 4 test locations. This should cause
+// values to be stored in the L2 cache and memory.
+//
+ LWI (Pattern, Pattern4) // L2_Cache[768K] = Pattern4;
+ stwx Pattern, r.9, Offset
+
+ LWI (Pattern, Pattern3) // L2_Cache[512K] = Pattern3;
+ stw Pattern, 0 (r.9)
+
+ LWI (Pattern, Pattern2) // L2_Cache[256K] = Pattern2;
+ stwx Pattern, Virtual, Offset
+
+ LWI (Pattern, Pattern1) // L2_Cache[ 0K] = Pattern1;
+ stw Pattern, 0 (Virtual)
+
+//
+// Disable the L2 cache. The tags are NOT invalidated. No L2 snoop
+// operations or data updates are performed.
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ rlwinm r.0, r.0, 0, ~(L2_EN+L2_UPDATE_EN)
+ stw r.0, 0xCFC(ISA)
+ sync
+
+//
+// Store PATTERN0 to our 4 test locations. Only L1 and main memory will be
+// written since the L2 cache has been disabled. This allows us to distinguish
+// patterns in the L2 from main memory.
+//
+
+ LWI (Pattern, Pattern0) // L2_Cache[768K] = Pattern0;
+ stwx Pattern, r.9, Offset
+ stw Pattern, 0 (r.9) // L2_Cache[512K] = Pattern0;
+ stwx Pattern, Virtual,Offset // L2_Cache[256K] = Pattern0;
+ stw Pattern, 0 (Virtual) // L2_Cache[ 0K] = Pattern0;
+
+//
+// Load 8 locations (for an 8-way L1 cache) 4096 bytes apart in order to flush
+// the test locations from the L1. We can't use DCBF since that would flush
+// the L2 also.
+//
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ LWI (Virtual, VIRTUAL)
+
+//
+// Re-enable the L2 cache
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ oris r.0, r.0, ((L2_EN + L2_UPDATE_EN) >> 16)
+ stw r.0, 0xCFC(ISA)
+ sync
+
+ lwz Pattern, 0(Virtual) // Read test location @ 0 KB
+ lwzx r.0, Virtual, Offset // Read test location @ 256 KB
+ rlwimi Pattern, r.0, 0, 8, 15
+ lwz r.0, 0 (r.9) // Read test location @ 512 KB
+ rlwimi Pattern, r.0, 0, 16, 23
+ lwzx r.0, r.9, Offset // Read test location @ 768 KB
+ rlwimi Pattern, r.0, 0, 24, 31
+
+//
+// Test the pattern from L2 to determine it's size
+//
+
+ LWI (r.0, 0x11777777)
+ cmpl 0,0, Pattern, r.0
+ beq Set_256K
+
+ LWI (r.0, 0x11227777)
+ cmpl 0,0, Pattern, r.0
+ beq Set_512K
+
+ LWI (r.0, 0x11223344)
+ cmpl 0,0, Pattern, r.0
+ beq Set_1M
+
+// LWI (r.0, 0x77777777)
+// cmpl 0,0, Pattern, r.0
+// bne InvalidPattern
+
+ li CacheSize, 0
+ b DisableCache
+
+
+//
+// Unexpected pattern. Return it for display.
+//
+InvalidPattern:
+// mr CacheSize, Pattern // Not needed if CacheSize == Pattern
+ b DisableCache
+
+
+
+Set_256K:
+ li CacheSize, 256
+ li r.4, L2_256K
+ b SetCacheSize
+
+Set_512K:
+ li CacheSize, 512
+ li r.4, L2_512K
+ b SetCacheSize
+
+Set_1M:
+ li CacheSize, 1024
+ li r.4, L2_1M
+
+//
+// r.3 = cache size in KB
+// r.4 = cache size field to be inserted into Eagle register AC.
+//
+SetCacheSize:
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.9, 0xCFC(ISA)
+ rlwimi r.9, r.4, 0, CF_L2_SIZE // Insert CF_L2_SIZE field
+ stw r.9, 0xCFC(ISA)
+ sync
+
+//
+// Eagle 2.1 BUG:
+// Write-back works OK
+// Write-thru walks thru addresses but does not invalidate them.
+// Don't need to flush for write-thru anyway!!!!
+//
+// NOTE: If changing from WRITE-BACK to WRITE-THROUGH, you must flush
+// beforehand because castouts are not supported in write-through.
+// If the L2 has dirty data, then switching to write-through, the
+// dirty data won't get flushed (cast out) to main memory.
+//
+ rlwinm r.4, r.9, 0, 1,31 // Clear L2_UPDATE_EN (lock L2)
+ stw r.4, 0xCFC(ISA)
+ oris r.0, r.4, (CF_FLUSH_L2 >> 16) // Toggle CF_FLUSH_L2
+ sync
+ stw r.0, 0xCFC(ISA)
+ sync
+ stw r.4, 0xCFC(ISA)
+//
+// Flush the L2 by walking through memory (2x L2 size)
+//
+ rlwinm r.0, CacheSize, 10-5+1, 0, 31 // L2Size * (1024 / LINE_SIZE) * 2
+ mtctr r.0
+ subi r.4, Virtual, L2_LINE_SIZE
+FlushLoop:
+ lwzu r.0, L2_LINE_SIZE (r.4)
+ bdnz FlushLoop
+
+//
+// Disable the L2 cache
+//
+DisableCache:
+ sync
+ lwz r.9, 0xCFC(ISA)
+ rlwinm r.9, r.9, 0, ~(L2_EN+L2_UPDATE_EN)
+ stw r.9, 0xCFC(ISA)
+ sync
+
+
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ stw L2off, 0xCFC(ISA) // Disable the L2 cache
+ sync
+
+//
+// Restore the original contents of the test locations
+//
+ lwz Restore,[toc].LRDATA(rtoc)
+ lwz r0, 0(Restore) // Restore test location 0
+ stw r0, 0(Virtual)
+
+ lwz r0, 4(Restore) // Restore test location 1
+ stwux r0, Virtual, Offset
+
+ lwz r0, 8(Restore) // Restore test location 2
+ stwux r0, Virtual, Offset
+
+ lwz r0,12(Restore) // Restore test location 3
+ stwx r0, Virtual, Offset
+
+ li r.0, 0 // Invalidate the BAT we used
+ mtdbatu BAT_REG, r.0
+ mtdbatl BAT_REG, r.0
+L2_Exit:
+ mfspr r.0, HID0
+ rlwinm r.0, r.0, 0, ~0x2000 // Unlock the Icache
+ mtspr HID0, r.0
+
+ LEAF_EXIT(HalpSizeL2)
+
+
+
+
+//***********************************************************************
+//
+// Synopsis:
+// VOID HalpFlushAndDisableL2(VOID)
+//
+// Purpose:
+// If the L2 is enabled and in WRITE-BACK mode, the L2 is flushed.
+// In either mode, the L2 is invalidated, and upon exit, the L2 is
+// left disabled.
+//
+// Returns:
+// nothing
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+ LEAF_ENTRY(HalpFlushAndDisableL2)
+
+ mfsprg r.12, 1 // Get PCR->SecondLevelDcacheSize
+ lwz r.0, PcSecondLevelDcacheSize (r.12)
+ srwi. r.0, r.0, 5 // # lines in L2
+ beqlr-
+ mtctr r.0
+
+
+ lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA,0(ISA)
+
+ LWI (EagleA8, 0x800000A8) // Processor Interface Configuration 1
+ addi EagleAC, EagleA8, 4 // Processor Interface Configuration 2
+
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.5, 0xCFC(ISA)
+ andis. r.0, r.5, (L2_EN >> 16) // Disable the L2 (L2_EN = 0)
+ beqlr
+
+ mfspr r.9, HID0 // Lock the Icache
+ ori r.0, r.9, 0x2000
+ mtspr HID0, r.0
+ isync
+
+ stw EagleA8, 0xCF8(ISA) // Check CF_L2_MP
+ sync
+ lwz r.4, 0xCFC(ISA)
+ andi. r.0, r.4, CF_L2_MP
+ beq FlushExit // Return if L2 is disabled
+
+
+ cmpwi r.0, CF_WRITE_THRU // Is L2 in write-through mode ?
+ beq InvalidateL2 // Yes, then flush is not necessary
+
+//
+// Flush the L2 contents to main memory
+//
+ stw EagleAC, 0xCF8(ISA) // Clear L2_UPDATE_EN (lock L2)
+ rlwinm r.0, r.5, 0, 1,31
+ oris r.0, r.0, (CF_FLUSH_L2 >> 16) // Toggle CF_FLUSH_L2
+ stw r.0, 0xCFC(ISA)
+ sync
+ stw r.5, 0xCFC(ISA)
+
+
+InvalidateL2:
+ stw EagleAC, 0xCF8(ISA) // Clear L2_UPDATE_EN (lock L2)
+ sync
+ rlwinm r.5, r.5, 0, 2,0 // Clear L2_EN (disable the L2 cache)
+ ori r.0, r.5, CF_INV_MODE // Set L2 to invalidate mode
+ stw r.0, 0xCFC(ISA)
+ sync
+
+//
+// Invalidate the L2 by walking thru memory
+//
+ LWI (r.12, 0x80000000-L2_LINE_SIZE)
+Invalidate:
+ lwzu r.0, L2_LINE_SIZE (r.12)// Read from L2 cache
+ bdnz Invalidate
+
+
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ rlwinm r.4, r.4, 0, ~CF_L2_MP // Clear CF_L2_MP
+ stw r.4, 0xCFC(ISA)
+
+FlushExit:
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ rlwinm r.5, r.5, 0, 2,31 // Clear L2_EN & L2_UPDATE_EN
+ stw r.5, 0xCFC(ISA) // Clear CF_INV_MODE
+
+
+ mtspr HID0, r.9 // Unlock the Icache
+
+ LEAF_EXIT(HalpFlushAndDisableL2)
+
+
+.LRDATA:
+// loc 0 - Holds memory at 0K
+ .ualong 0x0
+// loc 4 - Holds memory at 256K
+ .ualong 0x0
+// loc 8 - Holds memory at 512K
+ .ualong 0x0
+// loc 12 - Holds memory at 1024K
+ .ualong 0x0
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxmapio.c b/private/ntos/nthals/haleagle/ppc/pxmapio.c
new file mode 100644
index 000000000..edf50cc91
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmapio.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a POWER PC
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Map interrupt acknowledge base address
+ Map SIO config base address
+ Remove RTC map - S-FOOT mapsthe RTC into the ISA I/O space
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+//
+// Define global data used to locate the IO control space and the PCI config
+// space.
+//
+
+PVOID HalpInterruptBase;
+PVOID HalpPciConfigBase;
+PVOID HalpErrorAddressRegister;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O, planar control, and bus configuration
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map bus/bridge I/O control space
+ //
+
+ if (!HalpMapIoControlSpace())
+ return FALSE;
+
+ //
+ // Map Planar I/O control space
+ //
+
+ if (!HalpMapPlanarSpace())
+ return FALSE;
+
+ //
+ // Map Bus configuration space
+ //
+
+ if (!HalpMapBusConfigSpace())
+ return FALSE;
+
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxmemctl.c b/private/ntos/nthals/haleagle/ppc/pxmemctl.c
new file mode 100644
index 000000000..9a844710b
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmemctl.c
@@ -0,0 +1,1643 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+ Steve Johns (sjohns@pets.sps.mot.com)
+
+Revision History:
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+#include "pci.h"
+#include "pcip.h"
+#include "arccodes.h"
+#include "pxsystyp.h"
+#include <string.h>
+
+
+ULONG PciInterruptRoutingOther = 15;
+
+VOID HalDisplayString(PUCHAR String);
+ULONG HalpGetHID0(VOID);
+VOID HalpSetHID0(ULONG Value);
+BOOLEAN HalpStrCmp();
+VOID HalpEnableL2Cache(VOID);
+ULONG HalpSizeL2Cache(VOID);
+extern ULONG HalpSizeL2(VOID);
+extern ULONG L2_Cache_Size;
+extern VOID HalpFlushAndDisableL2(VOID);
+extern HalpPciConfigSize;
+BOOLEAN HalpInitPlanar(VOID);
+BOOLEAN HalpMapPlanarSpace(VOID);
+VOID HalpEnableEagleSettings(VOID);
+VOID HalpEnable_HID0_Settings(ULONG);
+VOID HalpCheckHardwareRevisionLevels(VOID);
+VOID HalpDumpHardwareState(VOID);
+
+#define EAGLECHIPID 0x0001
+
+#define BUF_LEN 120
+#define NEGATECHAR '~'
+
+#define EagleIndexRegister ((PULONG) (((PUCHAR) HalpIoControlBase) + 0xcf8))
+#define EagleDataRegister ((((PUCHAR) HalpIoControlBase) + 0xcfc))
+
+#define HalpReadEagleUlong(Port) \
+ (*EagleIndexRegister = (Port), __builtin_eieio(), *((PULONG) EagleDataRegister))
+
+#define HalpWriteEagleUlong(Port, Value) \
+ (*EagleIndexRegister = (Port), *((PULONG) EagleDataRegister) = (Value), __builtin_sync())
+
+#define HalpReadEagleUshort(Port) \
+ (*EagleIndexRegister = (Port&~3), __builtin_eieio(), *((PUSHORT)(EagleDataRegister+(Port&0x2))))
+
+#define HalpWriteEagleUshort(Port, Value) \
+ (*EagleIndexRegister = (Port&~3), *((PUSHORT)(EagleDataRegister+(Port&0x2))) = (Value), __builtin_sync())
+
+#define HalpWriteEagleUchar(Port, Value) \
+ (*EagleIndexRegister = (Port&~3), *((PUCHAR)(EagleDataRegister+(Port&0x3))) = (Value), __builtin_sync())
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpStrCmp)
+#pragma alloc_text(INIT,HalpEnableL2Cache)
+#pragma alloc_text(INIT,HalpInitPlanar)
+#pragma alloc_text(INIT,HalpMapPlanarSpace)
+#pragma alloc_text(INIT,HalpEnableEagleSettings)
+#pragma alloc_text(INIT,HalpEnable_HID0_Settings)
+#pragma alloc_text(INIT,HalpCheckHardwareRevisionLevels)
+#pragma alloc_text(INIT,HalpSizeL2Cache)
+#endif
+
+
+UCHAR HalpReadEagleUchar(ULONG Port)
+{ UCHAR c;
+ *EagleIndexRegister = Port & ~3;
+ __builtin_eieio();
+ c = *((PUCHAR)(EagleDataRegister+(Port&0x3)));
+ return (c);
+}
+
+
+// Eagle rev 2.1 reads Config register 0xC0 bit 4 into bit 3 instead.
+// Writes to bit 4 are OK.
+UCHAR HalpReadEagleC0(ULONG Port)
+{ UCHAR c;
+
+ c = HalpReadEagleUchar(0x800000C0);
+ c |= ((c & 0x08) << 1);
+ return (c);
+}
+
+
+
+typedef UCHAR (*PHALP_READ_EAGLE) (ULONG Port);
+PHALP_READ_EAGLE HalpReadEagleRegC0;
+
+
+#define HalpDisplayHex32(Num, Buf) HalpDisplayHex( 32, Num, Buf)
+#define HalpDisplayHex16(Num, Buf) HalpDisplayHex( 16, Num, Buf)
+#define HalpDisplayHex8(Num, Buf) HalpDisplayHex( 8, Num, Buf)
+
+VOID HalpDisplayHex(
+ ULONG NoBits,
+ ULONG Number,
+ IN PUCHAR Buffer
+)
+{ int Bits;
+
+ for (Bits=NoBits-4; Bits >= 0; Bits -=4) {
+ *Buffer++ = (UCHAR) ((((Number >> Bits) & 0xF) > 9) ?
+ ((Number >> Bits) & 0xF) - 10 + 'A' :
+ ((Number >> Bits) & 0xF) + '0');
+ }
+ *Buffer++ = '.';
+ *Buffer++ = '\n';
+ *Buffer++ = '\0';
+
+}
+
+
+UCHAR HalpUpperCase(UCHAR c)
+{
+ if (c >= 'a' && c <= 'z')
+ c -= 'a'-'A';
+ return c;
+}
+
+
+//
+// Routine Description:
+//
+// This routine is a helper routine for parameter parsing. It compares
+// String1 to String2.
+//
+// Return Value
+//
+// TRUE if strings match; otherwise FALSE
+// MatchLen - the number of characters correctly matched.
+//
+
+// #define HalpStrCmp(String1, String2) ( strcmp(String1, String2) == 0)
+BOOLEAN HalpStrCmp( char *String0, char *String1 )
+{
+char *tmp0, *tmp1;
+
+ tmp0 = String0;
+ tmp1 = String1;
+ while( (*tmp0 = toupper( *tmp0 )) && (*tmp1 = toupper( *tmp1 )) )
+ {
+ tmp0++; tmp1++;
+ }
+ return( strcmp(String0, String1) == 0 );
+}
+
+typedef struct tagEAGLEA8 {
+ union {
+ struct {
+ ULONG CF_L2_MP : 2;
+ ULONG SPECULATIVE_PCI : 1;
+ ULONG CF_APARK : 1;
+ ULONG CF_LOOP_SNOOP : 1;
+ ULONG LITTLE_ENDIAN : 1;
+ ULONG STORE_GATHERING : 1;
+ ULONG NO_PORTS_REG : 1;
+ ULONG Reserved1 : 1;
+ ULONG CF_DPARK : 1;
+ ULONG TEA_EN : 1;
+ ULONG MCP_EN : 1;
+ ULONG FLASH_WR_EN : 1;
+ ULONG CF_LBA_EN : 1;
+ ULONG Reserved2 : 1;
+ ULONG CF_MP_ID : 1;
+ ULONG ADDRESS_MAP : 1;
+ ULONG PROC_TYPE : 2;
+ ULONG DISCONTIGOUS_IO : 1;
+ ULONG ROM_CS : 1;
+ ULONG CF_CACHE_1G : 1;
+ ULONG CF_BREAD_WS : 2;
+ ULONG CF_CBA_MASK : 8;
+ } EagleA8;
+
+ ULONG AsUlong;
+ } u;
+} EAGLEA8;
+
+typedef struct tagEAGLEAC {
+ union {
+ struct {
+ ULONG CF_WDATA : 1;
+ ULONG CF_DOE : 1;
+ ULONG CF_APHASE : 2;
+ ULONG CF_L2_SIZE : 2;
+ ULONG CF_TOE_WIDTH : 1;
+ ULONG CF_FAST_CASTOUT : 1;
+ ULONG CF_BURST_RATE : 1;
+ ULONG CF_L2_HIT_DELAY : 2;
+ ULONG reserved1 : 1;
+ ULONG CF_INV_MODE : 1;
+ ULONG CF_HOLD : 1;
+ ULONG CF_ADDR_ONLY : 1;
+ ULONG reserved2 : 1;
+ ULONG CF_HIT_HIGH : 1;
+ ULONG CF_MOD_HIGH : 1;
+ ULONG CF_SNOOP_WS : 2;
+ ULONG CF_WMODE : 2;
+ ULONG CF_DATA_RAM_TYP : 2;
+ ULONG CF_FAST_L2_MODE : 1;
+ ULONG CF_BYTE_DECODE : 1;
+ ULONG reserved3 : 2;
+ ULONG CF_FLUSH_L2 : 1;
+ ULONG reserved4 : 1;
+ ULONG L2_ENABLE : 1;
+ ULONG L2_UPDATE_EN : 1;
+ } EagleAC;
+
+ ULONG AsUlong;
+ } u;
+} EAGLEAC;
+
+
+
+typedef struct tagEAGLEC0 {
+ union {
+ struct {
+ UCHAR LOCAL_BUS : 1;
+ UCHAR PCI_MASTER_ABORT : 1;
+ UCHAR MEM_READ_PARITY : 1;
+ UCHAR Reserved : 1;
+ UCHAR MASTER_PERR : 1;
+ UCHAR MEM_SELECT_ERROR : 1;
+ UCHAR SLAVE_PERR : 1;
+ UCHAR PCI_TARGET_ABORT : 1;
+ } EagleC0;
+
+ UCHAR AsUchar;
+ } u;
+} EAGLEC0;
+
+
+typedef enum {
+ MPC601 = 1,
+ MPC603 = 3,
+ MPC603e = 6,
+ MPC604 = 4,
+ MPC604e = 9
+} CPU_TYPE;
+
+
+// Parity Enable for memory interface
+#define PCKEN 0x10000
+// Machine Check Enable
+#define MCP_EN 0x800
+// Memory Read Parity Enable
+#define MRPE 0x04
+
+typedef enum {
+ WriteThrough,
+ WriteBack
+} L2MODE;
+
+// Oem Output Display function filter noise if OEM or quite
+
+VOID OemDisplayString(PUCHAR String)
+{
+UCHAR CharBuffer[BUF_LEN];
+
+ if(HalGetEnvironmentVariable("HALREPORT",sizeof(CharBuffer),&CharBuffer[0]) == ESUCCESS) {
+ if(HalpStrCmp("YES", CharBuffer)) {
+ HalDisplayString(String);
+ }
+ } else {
+ if(HalGetEnvironmentVariable("MOT-OEM-ID",sizeof(CharBuffer),&CharBuffer[0]) != ESUCCESS) {
+ HalDisplayString(String);
+ }
+ }
+}
+
+char *
+MyStrtok (
+ char * string,
+ const char * control
+ )
+{
+ unsigned char *str;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+
+ static char *nextoken;
+
+ /* Clear control map */
+ for (count = 0; count < 32; count++)
+ map[count] = 0;
+
+ /* Set bits in delimiter table */
+ do {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ } while (*ctrl++);
+
+ /* Initialize str. If string is NULL, set str to the saved
+ * pointer (i.e., continue breaking tokens out of the string
+ * from the last strtok call) */
+ if (string)
+ str = string;
+ else
+ str = nextoken;
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets str to point to the terminal
+ * null (*str == '\0') */
+ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
+ str++;
+
+ string = str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *str ; str++ )
+ if ( map[*str >> 3] & (1 << (*str & 7)) ) {
+ *str++ = '\0';
+ break;
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+ nextoken = str;
+
+ /* Determine if a token has been found. */
+ if ( string == str )
+ return NULL;
+ else
+ return string;
+}
+
+
+VOID HalpEnableL2Cache()
+{ EAGLEAC EagleRegAC;
+ EAGLEA8 EagleRegA8;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ BOOLEAN SynchronousSRAMs, Negate;
+ UCHAR EagleRevision;
+ L2MODE Mode;
+ int i;
+ UCHAR CharBuffer[BUF_LEN], *Value, c1, c2;
+ UCHAR L2_Parameter[BUF_LEN];
+
+ long BridgeChipId;
+
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+
+ //
+ // For non-EAGLE chips, firmware has already enabled the L2 cache.
+ // No further action is necessary, return.
+ //
+ if (BridgeChipId != EAGLECHIPID)
+ return;
+
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+
+ //
+ // Set some fields in Eagle Register 0xA8
+ //
+ EagleRegA8.u.AsUlong = HalpReadEagleUlong(0x800000A8);
+ EagleRegA8.u.EagleA8.TEA_EN = 1; // Enable TEA
+
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 0; // works for 601 & 604
+ switch (CpuType) {
+ case MPC601:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 0;
+ break;
+
+ case MPC603:
+ case MPC603e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 2;
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 1; // assumes DRTRY mode !!!
+ break;
+
+ case MPC604:
+ case MPC604e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 3;
+ break;
+ }
+
+ //
+ // Set the default L2 cache timing.
+ // The timing will be platform dependent.
+ // If the L2 is already on (via firmware), just return.
+ //
+
+ EagleRegAC.u.AsUlong = HalpReadEagleUlong(0x800000AC);
+ if (EagleRegAC.u.EagleAC.L2_ENABLE)
+ return;
+
+ EagleRegAC.u.EagleAC.CF_WMODE = 3;
+ EagleRegAC.u.EagleAC.CF_MOD_HIGH = 1;
+ EagleRegAC.u.EagleAC.CF_ADDR_ONLY = 1;
+ EagleRegAC.u.EagleAC.CF_APHASE = 1;
+ EagleRegAC.u.EagleAC.CF_DOE = 1;
+ EagleRegAC.u.EagleAC.CF_WDATA = 1;
+ EagleRegAC.u.EagleAC.L2_UPDATE_EN = 1;
+ EagleRegAC.u.EagleAC.L2_ENABLE = 1;
+
+
+ switch (HalpSystemType) {
+ case MOTOROLA_BIG_BEND:
+ case MOTOROLA_POWERSTACK:
+ default:
+ SynchronousSRAMs = TRUE;
+ break;
+ }
+
+ if (SynchronousSRAMs) {
+ EagleRegAC.u.EagleAC.CF_DATA_RAM_TYP = 0;
+ EagleRegAC.u.EagleAC.CF_HOLD = 0;
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 0;
+ } else {
+ EagleRegAC.u.EagleAC.CF_HOLD = 1;
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 1;
+ if (EagleRevision == 0x21)
+ EagleRegAC.u.EagleAC.CF_DOE = 0;
+ }
+
+ //
+ // Set up the default L2 cache mode.
+ // Default to WRITE-THROUGH prior to Eagle 2.4, else WRITE-BACK
+ //
+ Mode = WriteThrough;
+ if (EagleRevision >= 0x24) {
+ Mode = WriteBack;
+ EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 1;
+ EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x3f;
+ }
+
+ if (HalpSystemType == MOTOROLA_BIG_BEND) {
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = 3;
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = 1;
+ EagleRegAC.u.EagleAC.CF_TOE_WIDTH = 1;
+
+ } else {
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = 2;
+ EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 1;
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = 2;
+ }
+
+ //
+ // There are IBM 604 parts (Revision 3.3 and earlier) that cannot burst
+ // at the fastest rate in WRITE-BACK mode.
+ //
+ if ((Mode == WriteBack) && (CpuType == MPC604) && (CpuRevision < 0x0304))
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 1; // -2-2-2
+
+
+ //
+ // Parse the environment variable "L2"
+ //
+
+ if (HalGetEnvironmentVariable("L2", BUF_LEN, &CharBuffer[0]) == ESUCCESS) {
+
+ // Copy L2 environment variable
+ i = 0;
+ while (L2_Parameter[i] = CharBuffer[i]) {
+ i++;
+ }
+
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") )
+ {
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ } else
+ Negate = FALSE;
+
+ // Check for L2 = "OFF"
+ if (HalpStrCmp( "OFF", Value ))
+ {
+ OemDisplayString("HAL: L2 cache is disabled via environment variable L2\n");
+ HalpFlushAndDisableL2();
+ PCR->SecondLevelDcacheSize = PCR->SecondLevelIcacheSize = 0;
+ return;
+ }
+ // Check for WriteBack
+ else if ( HalpStrCmp( "WB", Value ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+ Mode = WriteBack;
+ EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 1;
+ EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x3f;
+ }
+ // Check for WriteThrough
+ else if ( HalpStrCmp( "WT", Value ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+ Mode = WriteThrough;
+ EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 0;
+ EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x00;
+ }
+ else if (SynchronousSRAMs && HalpStrCmp("FAST_CASTOUT", Value)) {
+ if (Negate) {
+ EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 0;
+ } else
+ EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 1;
+ }
+ else if ( HalpStrCmp( "FAST_MODE", Value ) ) {
+ if (Negate) {
+ EagleRegAC.u.EagleAC.CF_FAST_L2_MODE = 0;
+ } else
+ EagleRegAC.u.EagleAC.CF_FAST_L2_MODE = 1;
+ }
+ // Check for cache timings
+ else if ( ( HalpStrCmp( "3-1-1-1", Value ) ) ||
+ ( HalpStrCmp( "4-1-1-1", Value ) ) ||
+ ( HalpStrCmp( "5-1-1-1", Value ) ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = *Value - '2';
+// HIT_DELAY is where it samples HIT if =1, then 3-1-1-1 is fastest.
+// CF_DOE_DELAY adds 1 more delay to # cycles, but doesn't change where
+// HIT is sampled. If 66MHz or greater, then DOE_DELAY should be set.
+// same thing with WRITE_DELAY.
+
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = *Value - '2';
+ if( SynchronousSRAMs ) // Asynchronous SRAMs can't do -1-1-1
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 0;
+ }
+ else if ( ( HalpStrCmp( "3-2-2-2", Value ) ) ||
+ ( HalpStrCmp( "4-2-2-2", Value ) ) ||
+ ( HalpStrCmp( "5-2-2-2", Value ) ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = *Value - '2';
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = *Value - '2';
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 1;
+ } else {
+
+ParseError: HalDisplayString("HAL: Error in L2 environment variable: ");
+ HalDisplayString(L2_Parameter);
+ HalDisplayString("\n illegal parameter begins here ");
+ for (i = 0; i < Value - CharBuffer; i++)
+ HalDisplayString("\304");
+ HalDisplayString("^\n");
+ break;
+ }
+
+ } // End for
+ } // End If
+
+
+ //
+ // Enable L2 cache
+ //
+ OemDisplayString("HAL: L2 cache is ");
+
+ if (L2_Cache_Size == 0) {
+ OemDisplayString("not installed.\n");
+ return;
+ }
+
+ if (Mode == WriteThrough)
+ EagleRegA8.u.EagleA8.CF_L2_MP = 1;
+ else
+ EagleRegA8.u.EagleA8.CF_L2_MP = 2;
+
+ HalpWriteEagleUlong(0x800000A8, EagleRegA8.u.AsUlong);
+ HalpWriteEagleUlong(0x800000AC, EagleRegAC.u.AsUlong);
+
+ switch (L2_Cache_Size) {
+
+ case 256:
+ OemDisplayString("256 KB");
+ break;
+
+ case 512:
+ OemDisplayString("512 KB");
+ break;
+
+ case 1024:
+ OemDisplayString("1 MB");
+ break;
+
+ default:
+ OemDisplayString("an invalid configuration. Pattern = ");
+ HalpDisplayHex32(L2_Cache_Size, CharBuffer);
+ OemDisplayString(CharBuffer);
+ PCR->SecondLevelDcacheSize = PCR->SecondLevelDcacheSize = 0;
+ return;
+ }
+
+ //
+ // Display cache mode and timing
+ //
+ if (Mode == WriteBack)
+ OemDisplayString(" (write-back ");
+ else
+ OemDisplayString(" (write-through ");
+
+ CharBuffer[0] = (UCHAR) EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY + '2';
+ CharBuffer[1] = '\0';
+ OemDisplayString(CharBuffer);
+ if (EagleRegAC.u.EagleAC.CF_BURST_RATE)
+ OemDisplayString("-2-2-2)\n");
+ else
+ OemDisplayString("-1-1-1)\n");
+
+ return;
+}
+
+
+
+ULONG HalpSizeL2Cache()
+{ EAGLEAC EagleRegAC;
+ EAGLEA8 EagleRegA8;
+ CPU_TYPE CpuType;
+
+ long BridgeChipId;
+
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+
+ //
+ // For non-EAGLE chips, firmware has set up the L2 cache size in
+ // the config block and NT Kernel has copied this info into PCR
+ // structure. So, no work needs to be done, retrieve the size from PCR
+ //
+ if (BridgeChipId != EAGLECHIPID)
+ return( (PCR->SecondLevelIcacheSize >> 10) );
+
+ //
+ // Set some fields in Eagle Register 0xA8
+ //
+ EagleRegA8.u.AsUlong = HalpReadEagleUlong(0x800000A8);
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ switch (CpuType) {
+
+ case MPC603:
+ case MPC603e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 2;
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 1;
+ break;
+
+ case MPC604:
+ case MPC604e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 3;
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 0;
+ break;
+
+ default:
+ return 0; // This HAL doesn't work with this processor
+ }
+
+ HalpWriteEagleUlong(0x800000A8, EagleRegA8.u.AsUlong);
+
+ EagleRegAC.u.AsUlong = HalpReadEagleUlong(0x800000AC);
+ EagleRegAC.u.EagleAC.CF_MOD_HIGH = 1;
+ HalpWriteEagleUlong(0x800000AC, EagleRegAC.u.AsUlong);
+
+ return ( HalpSizeL2());
+}
+
+
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{ ULONG j;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision, c;
+ UCHAR CharBuffer[20], i;
+
+ long BridgeChipId;
+
+ switch (HalpSystemType) {
+
+ case MOTOROLA_BIG_BEND:
+ HalDisplayString("\nHAL: Motorola Big Bend System");
+ break;
+
+ case MOTOROLA_POWERSTACK:
+// HalDisplayString("\nHAL: Motorola PowerStack System");
+ break;
+
+ case SYSTEM_UNKNOWN:
+ default:
+ HalDisplayString("\nHAL: WARNING : UNKNOWN SYSTEM TYPE\n");
+ break;
+
+ }
+
+ OemDisplayString("\nHAL: Version 2.37 5/24/96.");
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+
+ OemDisplayString("\nHAL: Processor is a 60");
+ i = 0;
+ switch (CpuType) {
+ case MPC601:
+ case MPC603:
+ case MPC604:
+ CharBuffer[i++] = (UCHAR)(CpuType) + '0';
+ break;
+
+ case MPC603e:
+ CharBuffer[i++] = '3';
+ CharBuffer[i++] = 'e';
+ break;
+
+ case MPC604e:
+ CharBuffer[i++] = '4';
+ CharBuffer[i++] = 'e';
+ break;
+
+ default:
+ CharBuffer[i++] = '?';
+ break;
+ }
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ OemDisplayString(" revision ");
+ i = 0;
+ c = (UCHAR)((CpuRevision >> 8) & 0xf);
+ CharBuffer[i++] = c + '0';
+ CharBuffer[i++] = '.';
+ if (c = (UCHAR)((CpuRevision >> 4) & 0xf))
+ CharBuffer[i++] = c + '0';
+ c = (UCHAR)(CpuRevision & 0xf);
+ if (CpuType == MPC604 && c == 0) { // 604 v3.01
+ CharBuffer[i++] = '0';
+ CharBuffer[i++] = '1';
+ } else {
+ CharBuffer[i++] = c + '0';
+ }
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+
+ if (BridgeChipId == EAGLECHIPID)
+ OemDisplayString("\nHAL: Eagle Revision");
+ else
+ OemDisplayString("\nHAL: Bridge Chip Revision");
+
+ i = 0;
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+ CharBuffer[i++] = ' ';
+ CharBuffer[i++] = (UCHAR) (EagleRevision >> 4) + '0';
+ CharBuffer[i++] = '.';
+ CharBuffer[i++] = (UCHAR) (EagleRevision & 0x0F) + '0';
+ CharBuffer[i++] = '\n';
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ return TRUE;
+}
+
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+
+}
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map the PCI config space.
+ //
+
+ physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE;
+ HalpPciConfigBase = MmMapIoSpace(physicalAddress, HalpPciConfigSize, FALSE);
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+ UCHAR TextAddress[11];
+ USHORT EagleRegister, Byte;
+
+ EagleRegister = HalpReadEagleUshort(0x80000006);
+ if (EagleRegister & 0x8100)
+ HalDisplayString("\nEAGLE Status Register: PARITY Error Detected.");
+ if (EagleRegister & 0x4000)
+ HalDisplayString("\nEAGLE Status Register: SERR asserted.");
+
+// MOTKJR 08/22/95 - Don't check for the following bit.
+// It is always set when NT scans the slots on the PCI bus.
+// if (EagleRegister & 0x2000)
+// HalDisplayString("\nEAGLE Status Register: Transaction terminated with master-abort.");
+
+ if (EagleRegister & 0x1000)
+ HalDisplayString("\nEAGLE Status Register: Transaction terminated by target-abort while master.");
+ if (EagleRegister & 0x0800)
+ HalDisplayString("\nEAGLE Status Register: Transaction terminated by target-abort while slave.");
+
+ //
+ // Check Memory Error Detection Register 2
+ //
+ StatusByte = HalpReadEagleUchar(0x800000C5);
+
+ if (StatusByte & 0x10) {
+ HalDisplayString ("\nEAGLE Error Detection Register 2: L2 Parity Error Detected");
+ }
+
+ if (StatusByte & 0x80) {
+ // HalDisplayString ("\nEAGLE Error Detection Register 2: Invalid Error Address");
+#if DBG
+ //
+ // We have had a catastrophic hardware malfunction.
+ // Dump the state of the Eagle and HID 0 registers.
+ //
+ HalDisplayString("\n");
+ HalpDumpHardwareState();
+#endif
+ return;
+ }
+
+ //
+ // Read the error address register first
+ //
+ ErrorAddress = HalpReadEagleUlong(0x800000C8);
+ //
+ // Convert error address to HEX characters
+ //
+ HalpDisplayHex32(ErrorAddress, TextAddress);
+ TextAddress[ 8] = '.';
+ TextAddress[ 9] = '\0';
+ TextAddress[10] = '\0';
+
+
+ //
+ // Check Memory Error Detection Register 1
+ //
+
+ StatusByte = HalpReadEagleUchar(0x800000C1);
+
+ if (StatusByte & 0x08) {
+ HalDisplayString("\nEAGLE: PCI initiated Cycle.");
+ } else {
+ HalDisplayString("\nEAGLE: CPU initiated Cycle.");
+ }
+
+ if (StatusByte & 0xC0) {
+ HalDisplayString ("\nEAGLE: PCI ");
+ if (StatusByte & 0x80)
+ HalDisplayString ("SERR");
+ else
+ HalDisplayString ("target PERR");
+ HalDisplayString (" signaled at address ");
+ HalDisplayString (TextAddress);
+ }
+
+ if (StatusByte & 0x24) {
+ HalDisplayString ("\nEAGLE: Memory ");
+ if (StatusByte & 0x20)
+ HalDisplayString ("Select");
+ else
+ HalDisplayString ("Read Parity");
+ HalDisplayString (" error at address ");
+ HalDisplayString (TextAddress);
+ }
+
+#if DBG
+ //
+ // We have had a catastrophic hardware malfunction.
+ // Dump the state of the Eagle and HID 0 registers.
+ //
+ HalDisplayString("\n");
+ HalpDumpHardwareState();
+#endif
+}
+
+
+VOID HalpEnableEagleSettings(VOID)
+{
+ ULONG EagleRegister, UseFirmwareSettings;
+ volatile ULONG FakeVectorFetch;
+ USHORT CpuRevision;
+ EAGLEC0 ErrorEnable1;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision;
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ BOOLEAN Negate;
+
+ long BridgeChipId;
+
+#define SetEagleUcharC0( Clear, Val ) \
+ SetEagleReg(Clear, 0x800000C0, Val, HalpReadEagleRegC0, HalpWriteEagleUchar);
+
+#define SetEagleUchar( Clear, Offset, Val ) \
+ SetEagleReg(Clear, Offset, Val, HalpReadEagleUchar, HalpWriteEagleUchar);
+
+#define SetEagleUshort( Clear, Offset, Val ) \
+ SetEagleReg(Clear, Offset, Val, HalpReadEagleUshort, HalpWriteEagleUshort);
+
+#define SetEagleUlong( Clear, Offset, Val ) \
+ SetEagleReg(Clear, Offset, Val, HalpReadEagleUlong, HalpWriteEagleUlong);
+
+#define SetEagleReg( Clear, Offset, Val, GetReg, SetReg) \
+{ \
+ if (Clear) { \
+ SetReg(Offset, GetReg(Offset) & ~Val); \
+ } else { \
+ SetReg(Offset, GetReg(Offset) | Val); \
+ } \
+}
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+ UseFirmwareSettings = FALSE;
+
+ //
+ // Adjust default settings for any known chip bugs or anomalies here.
+ // Eagle revision 2.1 has funny bits in Register C0.
+ //
+
+ //
+ // If the bridge chip is not Eagle then set the revision number to 0x24
+ // Currently the sister chip grackle is the only one supported by this
+ // code and it is equivalent to Eagle revision 0x24
+ //
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+ if (BridgeChipId != EAGLECHIPID)
+ EagleRevision = 0x24;
+
+
+ if (EagleRevision == 0x21)
+ HalpReadEagleRegC0 = HalpReadEagleC0;
+ else
+ HalpReadEagleRegC0 = HalpReadEagleUchar;
+
+
+ //
+ // Set Address and Data Park bits in Eagle.
+ // These particular bits are not "parity" related.
+ //
+ HalpWriteEagleUlong(0x800000A8, HalpReadEagleUlong(0x800000A8) | 0x208);
+
+ //
+ // Setup and initialize the default EAGLE Parity Checking.
+ // This default is platform dependent.
+ //
+
+ switch (HalpSystemType) {
+ case MOTOROLA_POWERSTACK:
+ //
+ // PowerStack Systems will initialize EAGLE Parity Checking
+ // settings at the Boot ROM or ARC Firmware level. Use these
+ // EAGLE settings if they are present, otherwise use defaults.
+ //
+ UseFirmwareSettings = ((HalpReadEagleUlong(0x800000F0) & PCKEN) &&
+ (HalpReadEagleRegC0(0x800000C0) & MRPE));
+ if (UseFirmwareSettings)
+ break;
+
+ HalpWriteEagleUchar(0x800000C4, 0x10); // Enable L2 Parity Checking.
+ // fall-through to default
+
+ default:
+
+ //
+ // Enable parity checking in Eagle chip
+ //
+ ErrorEnable1.u.AsUchar = 0;
+ ErrorEnable1.u.EagleC0.PCI_TARGET_ABORT = 1;
+ ErrorEnable1.u.EagleC0.MEM_SELECT_ERROR = 1;
+ ErrorEnable1.u.EagleC0.MEM_READ_PARITY = 1;
+ HalpWriteEagleUchar(0x800000C0, ErrorEnable1.u.AsUchar);
+
+ if (EagleRevision >= 0x22) {
+ //
+ // NT must be loaded with the PCKEN bit enabled. Check PCKEN to make
+ // sure it is enabled. If it is not enabled, then don't enable parity
+ // checking since parity errors will be found all over memory.
+ //
+ EagleRegister = HalpReadEagleUlong(0x800000F0);
+ if (EagleRegister & PCKEN) {
+
+ //
+ // Enable parity checking in Eagle chip
+ //
+ ErrorEnable1.u.EagleC0.LOCAL_BUS = 1;
+ HalpWriteEagleUchar(0x800000C0, ErrorEnable1.u.AsUchar);
+
+ //
+ // Enable SERR checking in the Command register.
+ //
+ EagleRegister = HalpReadEagleUshort(0x80000004);
+ HalpWriteEagleUshort(0x80000004, (USHORT)(EagleRegister | 0x100)); // SERR only.
+
+ //
+ // Conditionally enable Machine Check in the Eagle.
+ // Systems with IBM 604 revision 3.2 & 3.3 parts have problems
+ // with parity. Motorola parts are OK. It would be great if we
+ // could tell them apart (one from the other), but we can't. So,
+ // don't enable internal Cache parity on this (or earlier) parts.
+ //
+ if ((CpuType != MPC604) || (CpuRevision >= 0x0304)) {
+ EagleRegister = HalpReadEagleUlong(0x800000A8);
+ HalpWriteEagleUlong(0x800000A8, EagleRegister | MCP_EN);
+ }
+ }
+ }
+ }
+
+
+ //
+ // The environment variable "EAGLESETTINGS" is defined as:
+ // Matching a string serves to enable that feature while a tilde (~)
+ // immediately before the parameter string indicates that it is to be disabled.
+ //
+
+ if ( HalGetEnvironmentVariable("EAGLESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) {
+
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, ":;,") ) {
+
+ Negate = FALSE;
+
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ }
+
+ if (HalpStrCmp("MCP_EN", Value) || HalpStrCmp("MCP", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, MCP_EN );
+
+ } else if (HalpStrCmp("TEA_EN", Value) || HalpStrCmp("TEA", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x400 );
+
+ } else if (HalpStrCmp("DPARK", Value) || HalpStrCmp("CF_DPARK", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x200 );
+
+ } else if (HalpStrCmp("GATHERING", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x040 );
+
+ } else if (HalpStrCmp("CF_LOOP_SNOOP", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x010 );
+
+ } else if (HalpStrCmp("APARK", Value) || HalpStrCmp("CF_APARK", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x008 );
+
+ } else if (HalpStrCmp("SPECULATIVE", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x004 );
+
+ } else if (HalpStrCmp("L2_PARITY", Value) || HalpStrCmp("L2", Value)) {
+ SetEagleUchar( Negate, 0x800000C4, 0x10 );
+
+ } else if (HalpStrCmp("PCKEN", Value)) {
+ SetEagleUlong( Negate, 0x800000F0, PCKEN );
+
+ } else if (HalpStrCmp("SERR", Value)) {
+ SetEagleUshort( Negate, 0x80000004, 0x100 );
+
+ } else if (HalpStrCmp("RX_SERR_EN", Value) || HalpStrCmp("RX_SERR", Value)) {
+ SetEagleUchar( Negate, 0x800000BA, 0x20 );
+
+ } else if (HalpStrCmp("TARGET_ABORT", Value)) {
+ SetEagleUcharC0( Negate, 0x80 );
+
+ } else if (HalpStrCmp("SLAVE_PERR", Value)) {
+ SetEagleUcharC0( Negate, 0x40 );
+ SetEagleUshort( Negate, 0x80000004, 0x040 );
+
+ } else if (HalpStrCmp("SELECT_ERROR", Value) || HalpStrCmp("SELECT", Value)) {
+ SetEagleUcharC0( Negate, 0x20 );
+
+ } else if (HalpStrCmp("MASTER_PERR", Value)) {
+ SetEagleUcharC0( Negate, 0x10 );
+ SetEagleUshort( Negate, 0x80000004, 0x040 );
+
+ } else if (HalpStrCmp("DRAM", Value) || HalpStrCmp("READ", Value) || HalpStrCmp("MEMORY", Value)) {
+ SetEagleUcharC0( Negate, MRPE );
+
+ } else if (HalpStrCmp("MASTER_ABORT", Value)) {
+ SetEagleUcharC0( Negate, 0x02 );
+
+ } else if (HalpStrCmp("LOCAL_ERROR", Value) || HalpStrCmp("LOCAL", Value)) {
+ SetEagleUcharC0( Negate, 0x01 );
+
+ //
+ // Enabling (or disabling) EAGLE parity by listing
+ // all of the individual bits was too complicated.
+ // For simplicity, we will define one pseudo-bit
+ // called "PARITY". This will set (or clear) all
+ // of the individual parity bits for EAGLE platforms.
+ //
+ } else if (HalpStrCmp("PARITY", Value)) {
+ // Conditionally turn on L2 checking.
+ if (HalpSystemType == MOTOROLA_POWERSTACK) {
+ SetEagleReg( Negate, 0x800000C4, 0x10, HalpReadEagleUchar, HalpWriteEagleUchar );
+ }
+
+ // Set or Clear the PCKEN bit.
+ SetEagleReg( Negate, 0x800000F0, PCKEN, HalpReadEagleUlong, HalpWriteEagleUlong );
+
+ // Set or Clear parity checking in Eagle chip
+ SetEagleUcharC0( Negate, 0xA5 );
+
+ // Set or Clear the SERR bit in the Command register.
+ SetEagleReg( Negate, 0x80000004, 0x100, HalpReadEagleUshort, HalpWriteEagleUshort );
+
+ // Set or Clear the MCP_EN last.
+ SetEagleReg( Negate, 0x800000A8, MCP_EN, HalpReadEagleUlong, HalpWriteEagleUlong );
+
+ } else if (HalpStrCmp("CF_ADDR_ONLY_DISABLE", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x4000);
+ } else if (HalpStrCmp("CF_BURST_RATE", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0100);
+ } else if (HalpStrCmp("CF_FAST_CASTOUT", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0080);
+ } else if (HalpStrCmp("CF_TOE_WIDTH", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0040);
+ } else if (HalpStrCmp("CF_DOE", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0002);
+ } else if (HalpStrCmp("CF_WDATA", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0001);
+
+ } else {
+ HalDisplayString( "HAL: Error in EAGLESETTINGS environment variable: ");
+ HalDisplayString(CharBuffer);
+ HalDisplayString("^\n");
+ }
+ } // End for
+ } // End If
+
+ //
+ // Initialize the PowerPC HID0 register here,
+ // before we clear the detection bits in the EAGLE.
+ // Otherwise we can miss the MCP pin signal transition.
+ //
+ HalpEnable_HID0_Settings(UseFirmwareSettings);
+
+ //
+ // Clear any detection bits that may have been set while enabling L2 cache.
+ // The Eagle does not clear the MCP_ signal until it sees a fetch from
+ // the Machine Check vector. So, we must simulate a vector fetch.
+ //
+ FakeVectorFetch = *((volatile PULONG)(0x80000200)); // Clear the EAGLE MCP_ signal if it is set.
+ HalpWriteEagleUchar(0x800000C1, 0xFF); // Clear Error Detection Register 1.
+ HalpWriteEagleUchar(0x800000C5, 0xFF); // Clear Error Detection Register 2.
+ EagleRegister = HalpReadEagleUshort(0x80000006); // Get any Un-documented Status bits.
+ HalpWriteEagleUshort(0x80000006, 0xF900 | (USHORT)(EagleRegister)); // Clear Status Register Bits.
+ FakeVectorFetch = *((volatile PULONG)(0x80000200)); // Clear the EAGLE MCP_ signal if it is set.
+
+ //
+ // Print this message last to confirm everything is working.
+ //
+
+}
+
+VOID HalpEnable_HID0_Settings(ULONG UseDefaultsHidSettings)
+{
+ ULONG EagleRegister;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision;
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ ULONG HidEnable, HidDisable, CurrentHID0;
+ BOOLEAN Negate;
+
+ long BridgeChipId;
+
+#define HID0_MCP (0x80000000)
+#define HID0_CACHE (0x40000000)
+#define HID0_ADDRESS (0x20000000)
+#define HID0_DATA (0x10000000)
+#define HID0_PAR (0x01000000)
+#define HID0_DPM (0x00100000)
+#define HID0_ILOCK (0x00002000)
+#define HID0_DLOCK (0x00001000)
+#define HID0_FBIOB (0x00000010)
+#define HID0_BHT (0x00000004)
+
+#define SetCPUMask( Disable, Val ) \
+{ \
+ if (Disable) \
+ HidDisable |= Val; \
+ else \
+ HidEnable |= Val; \
+}
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+
+ //
+ // If the bridge chip is not Eagle then set the revision number to 0x24
+ // Currently the sister chip grackle is the only one supported by this
+ // code and it is equivalent to Eagle revision 0x24
+ //
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+ if (BridgeChipId != EAGLECHIPID)
+ EagleRevision = 0x24;
+
+
+ HidEnable = 0;
+ HidDisable = 0;
+ CurrentHID0 = HalpGetHID0();
+
+ switch (CpuType) {
+ case MPC603e:
+ if (CpuRevision <= 0x102) {
+ //
+ // Disable Dynamic Power Management on 603e revisions 1.1 & 1.2
+ // 603e revisions 1.1 and 1.2 have errata w.r.t DPM.
+ //
+ CurrentHID0 &= ~HID0_DPM;
+ break;
+ }
+ // else fall through to 603
+
+ case MPC603:
+ //
+ // Enable Dynamic Power Management
+ //
+ CurrentHID0 |= HID0_DPM;
+ }
+
+ //
+ // Set the default CPU Parity Checking.
+ // This default is platform dependent.
+ //
+
+ switch (HalpSystemType) {
+ case MOTOROLA_POWERSTACK:
+ //
+ // PowerStack Systems will initialize HID0 Parity Checking
+ // settings at the Boot ROM or ARC Firmware level. Use these
+ // HID0 settings if they are present, otherwise use defaults.
+ //
+ if (UseDefaultsHidSettings) {
+ // Just enable the Machine Check Pin.
+ // Hopefully, everything else has been setup.
+ CurrentHID0 |= (HID0_MCP);
+ break;
+ }
+ // fall-through to default
+
+ default:
+ CurrentHID0 &= ~(HID0_MCP | HID0_DATA | HID0_CACHE | HID0_ADDRESS);
+
+ //
+ // Systems with IBM 604 revision 3.3 & 3.2 parts have problems with
+ // L1 parity checking. Motorola parts are OK, but we can't tell
+ // Motorola parts from IBM. So, don't enable L1 cache parity checking
+ // on 604 v3.3 or v3.2 parts.
+ switch (CpuType) {
+ case MPC604:
+ if (CpuRevision == 0x303 || CpuRevision == 0x302)
+ break;
+ // else fall through and enable Cache Parity
+ case MPC604e:
+ CurrentHID0 |= (HID0_CACHE);
+ // fall through
+ default:
+ break;
+ }
+
+ //
+ // Set up the default Parity Checking. No checking prior to Eagle 2.2.
+ // NT must be loaded with the PCKEN bit enabled. Check PCKEN to make
+ // sure it is enabled. If it is not enabled, then don't enable parity
+ // checking since parity errors will be found all over memory.
+ //
+
+ EagleRegister = HalpReadEagleUlong(0x800000F0);
+ if ((EagleRevision >= 0x22) && (EagleRegister & PCKEN)) {
+ //
+ // Systems with IBM 604 revision 3.3 parts have problems with
+ // parity generation. Motorola parts are OK. It would be great
+ // if we could tell them apart (one from the other), but we can't.
+ // So don't enable data parity checking on this (or earlier) parts.
+ //
+ if ((CpuType != MPC604) || (CpuRevision >= 0x0304))
+ CurrentHID0 |= (HID0_MCP | HID0_DATA);
+ }
+ break;
+ }
+
+ //
+ // The environment variable "HID0SETTINGS" is defined either as:
+ // "CACHE", "ADDRESS", "DATA", "MCP", "DPM" with either blank or semi-colon
+ // characters used as separators. Matching a string serves to enable
+ // that feature while a tilde (~) immediately before the parameter
+ // string indicates that it is to be disabled.
+ //
+
+ if (HalGetEnvironmentVariable("HID0SETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) {
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, ":;,") ) {
+
+ Negate = FALSE;
+
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ }
+
+ if (HalpStrCmp("MCP", Value)) {
+ SetCPUMask(Negate, HID0_MCP);
+ } else if (HalpStrCmp("ADDRESS", Value)) {
+ SetCPUMask(Negate, HID0_ADDRESS);
+ } else if (HalpStrCmp("DATA", Value)) {
+ SetCPUMask(Negate, HID0_DATA);
+ } else if (HalpStrCmp("PAR", Value)) {
+ SetCPUMask(Negate, HID0_PAR);
+ } else if (HalpStrCmp("ILOCK", Value)) {
+ SetCPUMask(Negate, HID0_ILOCK);
+ } else if (HalpStrCmp("DLOCK", Value)) {
+ SetCPUMask(Negate, HID0_DLOCK);
+ } else {
+ switch (CpuType) {
+ case MPC604:
+ case MPC604e:
+ if (HalpStrCmp("BHT", Value)) {
+ SetCPUMask(Negate, HID0_BHT);
+ continue;
+ }
+ if (HalpStrCmp("CACHE", Value)) {
+ SetCPUMask(Negate, HID0_CACHE);
+ continue;
+ }
+ break;
+
+ case MPC603:
+ case MPC603e:
+ if (HalpStrCmp("DPM", Value)) {
+ SetCPUMask(Negate, HID0_DPM);
+ continue;
+ }
+ if (HalpStrCmp("FBIOB", Value)) {
+ SetCPUMask(Negate, HID0_FBIOB);
+ continue;
+ }
+ break;
+
+
+ } // End switch
+
+ HalDisplayString("HAL: Error in HID0SETTINGS environment variable: ");
+ HalDisplayString(CharBuffer);
+ HalDisplayString("\n");
+ } // End else
+
+ } // End for
+ } // End if
+
+ //
+ // Check for inconsistencies in HID0SETTINGS
+ //
+ if (HidEnable & HidDisable) {
+ HalDisplayString("HAL: Inconsistent settings in HID0SETTINGS environment variable.\n");
+ HalDisplayString(" Disable setting will override enable setting.\n");
+ //
+ // Enforce DISABLE override ENABLE
+ //
+ HidEnable &= ~HidDisable;
+ }
+
+ //
+ // Disable and Enable the bits in the HID0 register.
+ //
+ CurrentHID0 &= ~HidDisable; // Disable bits first.
+ HalpSetHID0(CurrentHID0);
+
+ CurrentHID0 |= HidEnable; // Enable Bits last.
+ HalpSetHID0(CurrentHID0);
+
+ //
+ // Print this message last to confirm everything is working.
+ //
+
+}
+
+
+VOID HalpCheckHardwareRevisionLevels(VOID)
+{
+ ULONG EagleRegister, i;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision;
+ ARC_STATUS Status;
+ UCHAR Buffer[10];
+
+ long BridgeChipId;
+
+ i = HalpGetProcessorVersion();
+ CpuType = (CPU_TYPE)(i >> 16);
+ CpuRevision = (USHORT)(i & 0xFFFF);
+
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+ //
+ // Minimum hardware requirements:
+ // Eagle: v2.1 or greater
+ // 603 or 604: v3.2 or greater
+ // 603e or 604e: any CPU revision
+ //
+
+ //
+ // If the bridge chip is not Eagle then set the revision number to 0x24
+ // Currently the sister chip grackle is the only one supported by this
+ // code and it is equivalent to Eagle revision 0x24
+ //
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+ if (BridgeChipId != EAGLECHIPID)
+ EagleRevision = 0x24;
+
+
+ if (EagleRevision >= 0x21) {
+ switch (CpuType) {
+ case MPC603:
+ case MPC604:
+ if (CpuRevision >= 0x0302)
+ return;
+ else
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ // If the environment variable BOOTOLDHARDWARE exists (value is
+ // a don't care), then try to boot anyway.
+ Status = HalGetEnvironmentVariable("BOOTOLDHARDWARE", 5, Buffer);
+ if (Status == ESUCCESS || Status == ENOMEM)
+ return;
+
+ HalDisplayString("\nHAL: Unsupported CPU and/or EAGLE revision level. Set the\n");
+ HalDisplayString(" environment variable BOOTOLDHARDWARE to any value to boot anyway.");
+
+ //
+ // Bug check - after stalling to allow
+ // any information printed on the screen
+ // to be read and seen by the user.
+ //
+ HalDisplayString("\n");
+ for (i=0; i<12; i++) {
+ HalDisplayString(".");
+ KeStallExecutionProcessor(1000000);
+ }
+
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+}
+
+
+
+VOID HalpDumpHardwareState(VOID)
+{ ULONG EagleRegister, HID0;
+ UCHAR CharBuffer[12];
+
+#if DBG
+
+ if ( HalGetEnvironmentVariable("DBG_HAL", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) {
+
+ EagleRegister = HalpReadEagleUshort(0x80000004);
+ HalDisplayString("HAL: Eagle register 04 = 0x");
+ HalpDisplayHex16(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUshort(0x80000006);
+ HalDisplayString("HAL: Eagle register 06 = 0x");
+ HalpDisplayHex16(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUlong(0x800000A8);
+ HalDisplayString("HAL: Eagle register A8 = 0x");
+ HalpDisplayHex32(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUlong(0x800000AC);
+ HalDisplayString("HAL: Eagle register AC = 0x");
+ HalpDisplayHex32(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C0);
+ HalDisplayString("HAL: Eagle register C0 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C1);
+ HalDisplayString("HAL: Eagle register C1 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C3);
+ HalDisplayString("HAL: Eagle register C3 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C4);
+ HalDisplayString("HAL: Eagle register C4 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C5);
+ HalDisplayString("HAL: Eagle register C5 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C7);
+ HalDisplayString("HAL: Eagle register C7 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUlong(0x800000C8);
+ HalDisplayString("HAL: Eagle register C8 = 0x");
+ HalpDisplayHex32(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ HID0 = HalpGetHID0();
+ HalDisplayString("HAL: PowerPC Register HID0 = 0x");
+ HalpDisplayHex32(HID0, CharBuffer );
+ HalDisplayString(CharBuffer);
+ }
+
+#endif
+
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxmemctl.h b/private/ntos/nthals/haleagle/ppc/pxmemctl.h
new file mode 100644
index 000000000..25f180ea6
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmemctl.h
@@ -0,0 +1,45 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Masters systems.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define physical base addresses of planar
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+
+typedef struct _PLANAR_CONTROL {
+ UCHAR Reserved[0xcf8];
+
+ ULONG ConfigAddress; // 0xcf8
+ ULONG ConfigData; // 0xcfc
+
+} PLANAR_CONTROL, *PPLANAR_CONTROL;
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxmisc.s b/private/ntos/nthals/haleagle/ppc/pxmisc.s
new file mode 100644
index 000000000..8e3b58ac7
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmisc.s
@@ -0,0 +1,183 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxmisc.s
+//
+// Abstract:
+//
+// This module implements miscellaneous routines on the PowerPC.
+//
+// Author:
+//
+// Steve Johns (sjohns@pets.sps.mot.com) August 1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+
+#include "kxppc.h"
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+ LEAF_ENTRY(HalpGetHID0)
+
+ mfspr r.3, HID0
+
+ LEAF_EXIT(HalpGetHID0)
+
+
+
+
+ LEAF_ENTRY(HalpSetHID0)
+
+ mtspr HID0, r.3
+
+ LEAF_EXIT(HalpSetHID0)
+
+
+
+
+// ULONG HalpDivide (
+// IN ULARGE_INTEGER Dividend,
+// IN ULONG Divisor)
+//
+// Routine Description:
+//
+// This function divides an unsigned large integer by an unsigned long
+// and returns the resultant quotient.
+//
+// N.B. It is assumed that no overflow will occur.
+//
+// Arguments:
+//
+// Dividend (r.3, r.4) - Supplies the dividend value.
+// (High-order bits in r.4, low-order bits in r.3)
+//
+// Divisor (r.5) - Supplies the divisor value.
+//
+// Return Value:
+//
+// The ULONG quotient is returned as the function value.
+//
+//--
+
+
+
+ .set Quotient, r.3
+ .set DividendLo, r.3
+ .set DividendHi, r.4
+ .set Divisor, r.5
+ .set Q1, r.11
+ .set N, r.12
+ .set Q0, N // Use of N & Q0 don't overlap
+
+ LEAF_ENTRY(HalpDivide)
+
+
+ cmplw DividendHi,Divisor
+ bge overflow // catch overflow or division by 0
+ cmplwi DividendHi,0 // test high part for 0
+ bne Divide64Bits
+
+// High 32 bits of Dividend == 0, so use 32 bit division.
+ divwu Quotient,DividendLo,Divisor // Quotient = Dividend/Divisor
+ blr
+
+Divide64Bits:
+
+
+// Normalize: Shift divisor and dividend left to get rid of leading zeroes
+// in the divisor. Since DividendHi < Divisor, only zeroes are shifted out
+// of the dividend.
+ cntlzw N,Divisor // number of bits to shift (N)
+ slw Divisor,Divisor,N // shift divisor
+ slw DividendHi,DividendHi,N // shift upper part of dividend
+ mr r.8, DividendLo // Save unshifted DividendLo
+ slw DividendLo,DividendLo,N // shift lower part of dividend
+ subfic N,N,32 // 32-N
+ srw N,r.8,N // leftmost N bits of DividendLo, slid right
+ or DividendHi,DividendHi,N // and inserted into low end of DividendHi
+
+// Estimate high-order halfword of quotient. If the dividend is
+// A0 A1 A2 A3 and the divisor is B0 B1 (where each Ai or Bi is a halfword),
+// then the estimate is A0 A1 0000 divided by B0 0000, or A0 A1 divided by B0.
+// (DividendHi holds A0 A1, DividendLo holds A2 A3, and Divisor holds B0 B1.)
+// The estimate may be too high because it does not account for B1; in rare
+// cases, the estimate will not even fit in a halfword. High estimates are
+// corrected for later.
+ srwi r.8,Divisor,16 // r.8 <- B0
+ divwu Q0,DividendHi,r.8 // Q0 <- floor([A0 A1]/B0)
+// Subtract partial quotient times divisor from dividend: If Q0 is the quotient
+// computed above, this means that Q0 0000 times B0 B1 is subtracted from
+// A0 A1 A2 A3. We compute Q0 times B0 B1 and then shift the two-word
+// product left 16 bits.
+ mullw r.9,Q0,Divisor // low word of Q0 times B0 B1
+ mulhwu r.10,Q0,Divisor // high word of Q0 times B0 B1
+ slwi r.10,r.10,16 // shift high word left 16 bits
+ inslwi r.10,r.9,16,16 // move 16 bits from left of low word
+ // to right of high word
+ slwi r.9,r.9,16 // shift low word left 16 bits
+ subfc DividendLo,r.9,DividendLo // low word of difference
+ subfe DividendHi,r.10,DividendHi // high word of difference
+// If the estimate for Q0 was too high, the difference will be negative.
+// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 0000 to A0 A1 A2 A3
+// and decrement Q0 by one to correct for the overestimate.
+ cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
+ bge Q0_okay // no correction needed
+ inslwi r.10,Divisor,16,16 // high word of B0 B1 0000 (= 0000 B0)
+ slwi r.9,Divisor,16 // low word of B0 B1 0000 (= B1 0000)
+adjust_Q0:
+ addc DividendLo,DividendLo,r.9 // add B0 B1 0000 to A0 A1 A2 A3 (low)
+ adde DividendHi,DividendHi,r.10 // add B0 B1 0000 to A0 A1 A2 A3 (high)
+ cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
+ addi Q0,Q0,-1 // decrement Q0
+ blt adjust_Q0 // if A0 A1 A2 A3 still negative, repeat
+Q0_okay:
+// Estimate low-order halfword of quotient. A0 is necessarily 0000 at this
+// point, so if the remaining part of the dividend is A0 A1 A2 A3 then the
+// estimate is A1 A2 0000 divided by B0 0000, or A1 A2 divided by B0.
+// (DividendHi holds A0 A1, DividendLo holds A2 A3, and r.8 holds B0.)
+ slwi r.9,DividendHi,16 // r.9 <- A1 0000
+ inslwi r.9,DividendLo,16,16 // r.9 <- A1 A2
+ divwu Q1,r.9,r.8 // Q1 <- floor([A1 A2]/B0)
+// Subtract partial quotient times divisor from remaining part of dividend:
+// If Q1 is the quotient computed above, this means
+// that Q1 times B0 B1 is subtracted from A0 A1 A2 A3. We compute
+ mullw r.9,Q1,Divisor // low word of Q1 times B0 B1
+ mulhwu r.10,Q1,Divisor // high word of Q1 times B0 B1
+ subfc DividendLo,r.9,DividendLo // low word of difference
+ subfe DividendHi,r.10,DividendHi // high word of difference
+// If the estimate for Q1 was too high, the difference will be negative.
+// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 to A0 A1 A2 A3
+// and decrement Q1 by one to correct for the overestimate.
+ cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
+ bge Q1_okay // no correction needed
+adjust_Q1:
+ addc DividendLo,DividendLo,Divisor // add B0 B1 to A0 A1 A2 A3 (low)
+ addze DividendHi,DividendHi // add B0 B1 to A0 A1 A2 A3 (high)
+ cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
+ addi Q1,Q1,-1 // decrement Q1
+ blt adjust_Q1 // if A0 A1 A2 A3 still negative, repeat
+Q1_okay:
+ slwi Quotient,Q0,16 // Quotient <- Q0 A1
+ or Quotient,Quotient,Q1
+ blr
+
+
+// The error cases:
+overflow:
+ li Quotient, 0 // return(0);
+ LEAF_EXIT(HalpDivide)
+
+
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcibrd.c b/private/ntos/nthals/haleagle/ppc/pxpcibrd.c
new file mode 100644
index 000000000..91ef86864
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcibrd.c
@@ -0,0 +1,544 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ PCI to PCI bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child relationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured PCI bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses relationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limited to
+ // 256 bytes on every 1K aligned boundary within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+ return FALSE;
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ buses supports. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control register.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contemplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reserved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcibus.c b/private/ntos/nthals/haleagle/ppc/pxpcibus.c
new file mode 100644
index 000000000..a7f1f4b4f
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcibus.c
@@ -0,0 +1,2289 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpcibus.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+extern ULONG HalpPciMaxSlots;
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+#if 0
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+#endif
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ // direct Method.
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ // indirect Method.
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ //
+ // Allow access all 32 devices per bus.
+ //
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if 0
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if 0
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ //DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+#define ATIBUG 1
+#if ATIBUG
+ USHORT VendorId;
+ LONG Len;
+#endif
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+#if ATIBUG
+//
+// Temporary Hack (MOTKJR) - We have discovered a problem between the ATI
+// Video Driver and the NCR 810/825 SCSI parts. The NCR chip has hardware
+// registers in Configuration Space above 0x40 which have a side effect that
+// a read from these registers is destructive to its contents. If a SCSI
+// operation is active when these registers are read, the NCR device will
+// abort the operation and further I/O is impossible. Therefore, we will
+// not allow anyone to read from Offset 0x40 to 0xFF for any PCI slot that
+// has an NCR vendor ID number. Care must be taken to check for requests
+// which overlap both the PCI Common Header and the Device Dependent area.
+//
+#define NCR_VENDOR_ID 0x1000
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &VendorId, 0x0, sizeof(VendorId),
+ PCIConfigHandler.ConfigRead);
+
+ if ((VendorId == NCR_VENDOR_ID) && (Offset + Length > PCI_COMMON_HDR_LENGTH)) {
+ Len = PCI_COMMON_HDR_LENGTH - Offset;
+ if (Len < 0)
+ Len = 0;
+ RtlFillMemory ((PVOID)((PUCHAR)Buffer+Len), Length-Len, (UCHAR) -1);
+ if (Offset >= PCI_COMMON_HDR_LENGTH)
+ return;
+ Length = Len;
+ }
+#endif
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.bits.DeviceNumber)
+ + 0x100 * Slot.u.bits.FunctionNumber;
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ if ((PciCfg1->u.bits.BusNumber = BusHandler->BusNumber) == 0) {
+
+ // This hack is to maintain device number compatibility
+ // on bus 0 with the Type1 functions. We do this so that
+ // the installed base maintains the same "slot" numbering.
+ // The notable issue is with network interfaces where the
+ // slot number is stored in the registry at install time.
+ // It was judged too subtle and too painful to have everyone
+ // reinstall networking if they added a bridged device to
+ // their system.
+
+ int MappedDev;
+ ULONG Offset;
+ #define PRESHIFT 8 // Make invalid slot numbers to map to dev 9.
+ // Dev 9 is inaccessible from the eagle.
+
+ // Get the offset from the Type1 (direct mapping) offset table.
+ // If the device number isn't "valid", use an offset that won't
+ // actually end up selecting any device.
+
+ Offset = (Slot.u.bits.DeviceNumber < HalpPciMaxSlots) ?
+ HalpPciConfigSlot[Slot.u.bits.DeviceNumber] : (1 << PRESHIFT);
+
+ // Determine the device number accessed by the "offset".
+ // If bit 11 is set, MappedDev = 11; bit 12, MappedDev = 12;...
+
+ Offset >>= PRESHIFT;
+ MappedDev = PRESHIFT - 1;
+
+ do {
+ MappedDev++;
+ Offset >>= 1;
+
+ } while (Offset);
+
+ // The eagle docs say to set the device number field to 10
+ // for PCI device 31.
+
+ PciCfg1->u.bits.DeviceNumber = (MappedDev == 31) ? 10 : MappedDev;
+
+ } else {
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ }
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_UCHAR ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i,*Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_USHORT ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + (USHORT) i,*((PUSHORT)Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData,*((PULONG)Buffer));
+ return sizeof(ULONG);
+}
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+//*BJ* PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ *BaseAddress[RomIndex] &= ~0x7ff;
+
+ //
+ // Rom Base Address resource is not enabled, as the ROM code cannot
+ // be executed on a risk box, and the algorithm below interprets
+ // the card's Rom Base Address requirements incorrectly
+ //
+
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ m = 0;
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m |= PCI_ENABLE_IO_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ m |= PCI_ENABLE_MEMORY_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Set addresses, but do not turn on decodes
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (!(*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) &&
+ (Is64BitBaseAddress(*BaseAddress[j]))) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ // enable IO & Memory decodes (use HalSetBusData since valid settings now set)
+
+ // Set Bus master bit on for win95 compatability
+ m |= PCI_ENABLE_BUS_MASTER;
+
+ PciData->Command |= (USHORT) m;
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/pxpciint.c b/private/ntos/nthals/haleagle/ppc/pxpciint.c
new file mode 100644
index 000000000..36c139b3f
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpciint.c
@@ -0,0 +1,221 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+
+--*/
+{
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+}
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == 0) {
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcisup.c b/private/ntos/nthals/haleagle/ppc/pxpcisup.c
new file mode 100644
index 000000000..272a16022
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcisup.c
@@ -0,0 +1,235 @@
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxpcisup.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ T. White -- Added dword I/O to allow GXT150P to work correctly
+
+Special Note:
+
+ Please make sure that the dword I/O mechanisms are carried
+ forward for any box which is to support the GXT150P graphics
+ adapter. The GXT150P graphics adapter runs in any PowerPC
+ machine with a standard PCI bus connector.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+
+extern PVOID HalpPciConfigBase;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpPhase0SetPciDataByOffset)
+#pragma alloc_text(INIT,HalpPhase0GetPciDataByOffset)
+#endif
+
+ULONG HalpPciConfigSlot[] = { 0x0800,
+ 0x1000,
+ 0x2000,
+ 0x4000,
+ 0x8000,
+ 0x10000,
+ 0x20000,
+ 0x40000,
+ 0x80000
+ };
+
+ULONG HalpPciMaxSlots = sizeof(HalpPciConfigSlot)/sizeof(ULONG);
+ULONG HalpPciConfigSize;
+
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+ This is a sandalfoot memory map implementation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ UNREFERENCED_PARAMETER(BusNumber);
+
+ return ((ULONG) ((PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[SlotNumber]));
+
+}
+
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ to = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ to += Offset;
+ from = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)to & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ from = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ from += Offset;
+ to = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)from & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcisup.h b/private/ntos/nthals/haleagle/ppc/pxpcisup.h
new file mode 100644
index 000000000..a598de5e5
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcisup.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxpcisup.h
+
+Abstract:
+
+ The module provides the PCI bus interfaces for PowerPC systems.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+extern ULONG HalpPciConfigSlot[];
+extern ULONG HalpPciMaxSlots;
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+
+#define PCI_MEMORY_BASE 0xC0000000
+
+
+
+typedef struct {
+ USHORT VendorID;
+ USHORT DeviceID;
+ USHORT Command;
+ USHORT Status;
+ UCHAR RevisionID;
+ UCHAR ClassCode[3];
+ UCHAR CacheLineSize;
+ UCHAR LatencyTimer;
+ UCHAR HeaderType;
+ UCHAR BIST;
+ ULONG BaseAddress1;
+ ULONG BaseAddress2;
+ ULONG BaseAddress3;
+ ULONG BaseAddress4;
+ ULONG BaseAddress5;
+ ULONG BaseAddress6;
+ ULONG reserved1;
+ ULONG reserved2;
+ ULONG ROMbase;
+} *PCI_CONFIG;
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxport.c b/private/ntos/nthals/haleagle/ppc/pxport.c
new file mode 100644
index 000000000..6c91f4b59
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxport.c
@@ -0,0 +1,849 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Chuck Bauman 02-Jun-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+ Steve Johns (sjohns@pets.sps.mot.com)
+ - added support for multple baud rates, alternate COM port
+ - implemented KdPortSave & KdPortRestore
+
+--*/
+
+#include "halp.h"
+#include "ppcserp.h"
+
+#include <pxmemctl.h>
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+ULONG KdCurrentBaudRate= 19200;
+ULONG KdCurrentComPort = COM1_PORT;
+ULONG HalpSavedBaudRate;
+ULONG HalpSavedComPort;
+
+extern PVOID HalpIoControlBase;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 6;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameters - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+
+/*
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+
+*/
+
+ //
+ // Map I/O space if it has not already been mapped.
+ //
+
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE,
+ 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+
+ //
+ // Set COM parameters
+ //
+ if (DebugParameters != NULL) {
+ if (DebugParameters->BaudRate == 0)
+ KdCurrentBaudRate = 19200; // default baud rate
+ else
+ KdCurrentBaudRate = DebugParameters->BaudRate;
+
+ if (DebugParameters->CommunicationPort > 2)
+ return (FALSE);
+ KdCurrentComPort = COM1_PORT; // default COM port
+ if (DebugParameters->CommunicationPort == 1)
+ KdCurrentComPort = COM1_PORT;
+ if (DebugParameters->CommunicationPort == 2)
+ KdCurrentComPort = COM2_PORT;
+
+ }
+
+ HalpBaudRateDivisor = (UCHAR) ((1843200/16) / KdCurrentBaudRate);
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+
+
+ KdComPortInUse=(PUCHAR)KdCurrentComPort;
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to requested rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+
+ Status = HalpGetByte(Input, FALSE);
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ PSP_MODEM_STATUS LsrByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = (PSP_MODEM_STATUS) READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+DEBUG_PARAMETERS ComParams;
+
+ if (HalpSavedComPort != KdCurrentComPort ||
+ HalpSavedBaudRate != KdCurrentBaudRate) {
+ if (HalpSavedComPort == COM2_PORT)
+ ComParams.CommunicationPort = 2;
+ else
+ ComParams.CommunicationPort = 1;
+ ComParams.BaudRate = HalpSavedBaudRate;
+ KdPortInitialize(&ComParams, NULL, TRUE);
+ }
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpSavedBaudRate = KdCurrentBaudRate;
+ HalpSavedComPort = KdCurrentComPort;
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Supplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxpower.s b/private/ntos/nthals/haleagle/ppc/pxpower.s
new file mode 100644
index 000000000..e02d56689
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpower.s
@@ -0,0 +1,67 @@
+//++
+//
+// Copyright (c) 1993-1995 IBM Corporation
+//
+// Copyright (c) 1994, 1995 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxpower.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Steve Johns - Motorola
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 12-Sep-94 saj Wrote it
+// 25-Oct-94 saj Enable interrupts if 604
+// Set DOZE bit in HID0 before POW in MSR
+// 25-Sep-95 kjr Added 603ev support.
+//--
+
+#include "kxppc.h"
+
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+
+ LEAF_ENTRY(HalpProcessorIdle)
+
+ mfmsr r.4 // Read MSR
+ ori r.4, r.4, 0x8000 // Enable External/Decrementer interrupts
+
+ mfpvr r.0 // Read PVR
+ rlwinm r.0, r.0, 16, 15, 31
+ cmpwi r.0, 3 // Is it a 603?
+ beq EnableDoze
+ cmpwi r.0, 6 // Is it a 603e?
+ beq EnableDoze
+ cmpwi r.0, 7 // Is it a 603ev?
+ beq EnableDoze
+
+ b EnableInterrupts // If not, just enable interrupts
+
+EnableDoze:
+ mfspr r.3, HID0 // Set Doze mode in HID0 (bit 8)
+ oris r.3, r.3, 0x0080
+ mtspr HID0, r.3
+ sync
+
+ oris r.4, r.4, 0x0004 // Set POW in MSR (bit 13)
+
+EnableInterrupts:
+ mtmsr r.4
+ isync
+
+ LEAF_EXIT(HalpProcessorIdle)
diff --git a/private/ntos/nthals/haleagle/ppc/pxproc.c b/private/ntos/nthals/haleagle/ppc/pxproc.c
new file mode 100644
index 000000000..5ec201f37
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxproc.c
@@ -0,0 +1,212 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PowerPC HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+extern VOID HalpInitializePciBus (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return FALSE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If there is more than one restart block then this is a multi-
+ // processor system.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ Number = 0;
+ while (NextRestartBlock != NULL) {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Ppc, sizeof(PPC_RESTART_STATE));
+
+ //
+ // Set processor start address.
+ //
+
+ NextRestartBlock->u.Ppc.Iar = ProcessorState->ContextFrame.Iar;
+
+ //
+ // PowerPC linkage conventions pass parameters in registers
+ // r.3 thru r.10. Set all of them to allow as much flexibility
+ // to the kernel as possible.
+ //
+
+ NextRestartBlock->u.Ppc.IntR3 = ProcessorState->ContextFrame.Gpr3;
+ NextRestartBlock->u.Ppc.IntR4 = ProcessorState->ContextFrame.Gpr4;
+ NextRestartBlock->u.Ppc.IntR5 = ProcessorState->ContextFrame.Gpr5;
+ NextRestartBlock->u.Ppc.IntR6 = ProcessorState->ContextFrame.Gpr6;
+ NextRestartBlock->u.Ppc.IntR7 = ProcessorState->ContextFrame.Gpr7;
+ NextRestartBlock->u.Ppc.IntR8 = ProcessorState->ContextFrame.Gpr8;
+ NextRestartBlock->u.Ppc.IntR9 = ProcessorState->ContextFrame.Gpr9;
+ NextRestartBlock->u.Ppc.IntR10 = ProcessorState->ContextFrame.Gpr10;
+
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number++;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ interfacetype = Internal;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ interfacetype = Isa;
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+#ifdef POWER_MANAGEMENT
+ HalInitSystemPhase2();
+#endif
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxprof.c b/private/ntos/nthals/haleagle/ppc/pxprof.c
new file mode 100644
index 000000000..fdd31e5f1
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxprof.c
@@ -0,0 +1,268 @@
+
+/*****************************************************************************
+
+Copyright (c) 1993 Motorola Inc.
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ PXPROF.C
+
+Abstract:
+
+ This implements the HAL profile functions:
+
+ HalSetProfileInterval
+ HalStartProfileInterrupt
+ HalStopProfileInterrupt
+ HalCalibratePerformanceCounter
+ HalpProfileInterrupt
+
+
+Author:
+
+ Steve Johns 11-Feb-1994
+
+Revision History:
+ Changed from using the DECREMENTER to 8254 Timer 1 10-Feb-94
+
+******************************************************************************/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+
+#define TIMER ((PEISA_CONTROL)HalpIoControlBase)
+#define TIMER0_COMMAND (COMMAND_8254_COUNTER0 + COMMAND_8254_RW_16BIT + COMMAND_8254_MODE2)
+
+ULONG HalpMaxProfileInterval = 540000; // 54 ms maximum
+ULONG HalpMinProfileInterval = 10000; // 1 ms minimum
+ULONG HalpProfileCount;
+BOOLEAN HalpProfilingActive = FALSE;
+ULONG HalpProfileInts = 0;
+
+
+VOID HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine unmasks IRQ0 at the master interrupt controller,
+ enabling the profile interrupt.
+
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding
+ the profile lock.
+
+Arguments:
+
+ ProfileSource
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = TRUE;
+ //
+ // Unmasks IRQ 0 (Timer 1)
+ //
+ HalEnableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL, Latched);
+ }
+
+}
+
+
+
+
+
+
+ULONG HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval, rounded to the nearest 100ns units.
+
+--*/
+
+{
+ ULONG ActualInterval;
+ LARGE_INTEGER BigNumber;
+
+ //
+ // Clamp the requested profile interval between the minimum and
+ // maximum supported values.
+ //
+ if (Interval < HalpMinProfileInterval)
+ Interval = HalpMinProfileInterval;
+ else
+ if (Interval > HalpMaxProfileInterval)
+ Interval = HalpMaxProfileInterval;
+ //
+ // Compute Timer 1 counts for requested interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(Interval, TIMER_CLOCK_IN);
+
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber, 10000000, NULL);
+ HalpProfileCount = BigNumber.LowPart;
+
+ //
+ // Program Timer 1 to Mode 2 & program the timer count register.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount >> 8));
+ //
+ // Compute actual interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(HalpProfileCount, 10000000);
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber,TIMER_CLOCK_IN, NULL);
+ ActualInterval = BigNumber.LowPart;
+
+ return (ActualInterval);
+}
+
+
+
+
+BOOLEAN HalpHandleProfileInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+
+ if (HalpProfilingActive)
+ KeProfileInterrupt(TrapFrame);
+
+ return (TRUE);
+}
+
+
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine masks IRQ 0 (Timer 1) at the interrupt controller, thereby
+ stopping profile interrupts.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ ProfileSource
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = FALSE;
+
+ //
+ // Program Timer 1 to Mode 2 & program the LSB of the timer.
+ // That should keep it from interrupting in case IRQ0 accidently
+ // gets enabled.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+
+
+ //
+ // Mask IRQ 0 (Timer 1)
+ //
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+ }
+
+}
+
+
+
+
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Zero the Time Base registers
+ //
+
+ HalpZeroPerformanceCounter();
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxreset.s b/private/ntos/nthals/haleagle/ppc/pxreset.s
new file mode 100644
index 000000000..ad4bfb697
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxreset.s
@@ -0,0 +1,240 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxreset.s
+//
+// Abstract:
+//
+// This module implements the routine HalpPowerPcReset, which can be
+// used to return the PowerPC to Big Endian with cache flushed and
+// branches to the rom based machine reset handler.
+//
+// Author:
+//
+// Steve Johns Sept-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 3/21/95 saj Fixed HID0 getting trashed.
+//--
+
+#include "kxppc.h"
+ .new_section .text,"crx5"
+
+ .extern HalpIoControlBase
+ .extern HalpSystemType
+
+ .set ISA, r.1
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_EE,1) | MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+ .set HID0_DCE, 0x4000 // 603 Data Cache Enable
+ .set HID0_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set HID0_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set HID0_DCFI, 0x0400 // D-Cache Flash Invalidate
+
+
+ LEAF_ENTRY(HalpPowerPcReset)
+
+
+ lwz r.3,[toc]HalpSystemType(r.toc) // Get system type for later use.
+ lwz r.3, 0(r.3)
+
+ LWI (r.4, 0xfff00100) // Address of ROM reset vector
+ mfspr r.5, HID0
+
+ LWI (r.7, 0x80000000) // I/O space for physical mode
+
+ lwz ISA,[toc]HalpIoControlBase(r.toc)
+ lwz ISA,0(ISA) // Get base address of ISA I/O space
+
+
+ LWI (r.12, 0x800000A8) // Index to Eagle register 0xA8
+ stw r.12, 0xCF8(ISA)
+ sync
+ lwz r.6, 0xCFC(ISA)
+ rlwinm r.6, r.6, 0, 0, 29 // Disable L2 cache
+ rlwinm r.6, r.6, 0, 21, 19 // Disable Machine Checks from Eagle
+ stw r.6, 0xCFC(ISA) // Disable the L2 cache
+ rlwinm r.6, r.6, 0, 27, 25 // Clear LE_MODE of Eagle register A8
+
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1)
+ isync
+ mtmsr r.8 // disable interrupts
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ bl here // get current address
+here:
+ mflr r.9 // (r.9) = &here
+ addi r.9, r.9, BigEndian-here
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.5 contains HID0 present value.
+// r.6 contains Eagle register A8 value for switching to Big Endian
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the physical address of "BigEndian"
+
+
+
+// Disable D-Cache and Data address translation, flush I-Cache
+// and disable interrupts.
+
+ mr r.10, r.5
+ ori r.5,r.5,HID0_DCE+HID0_ICE+HID0_ICFI+HID0_DCFI // Invalidate caches
+ rlwinm r.10, r.10, 0, ~HID0_DCE// turn off D-cache
+ rlwinm r.10, r.10, 0, ~HID0_ICE// turn off I-cache
+ sync
+ mtspr HID0, r.5 // Flash invalidate both caches
+ mtspr HID0, r.10 // Disable both caches
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1)
+ isync
+ mtmsr r.8 // disable data address translation,
+ // disable interrupts.
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+// We will use a MTMSR instruction to switch to big-endian, untranslated,
+// interrupts disabled at the same time. We use an RFI to effect the
+// branch to the reset vector (0xFFF00100).
+
+ li r.8, MASK_SPR(MSR_IP,1)
+ ori r.8, r.8, MASK_SPR(MSR_ME,1)
+ mtsrr1 r.8 // state = Machine Check Enabled
+ mtsrr0 r.9 // RFI to BigEndian
+
+
+ //
+ // Try to issue a hard reset. If this fails, the fall
+ // thru and continue to manually return to firmware.
+ //
+
+ cmpwi r.3, 0 // Skip port 92 reset for BigBend. *BJ*
+ beq NoPort92
+
+ li r.9, 0xFF // All ones
+ stb r.9, 0x92(r.7) // Reset the System
+ eieio
+ lwz r.9, 0x21(r.7) // Flush the Eagle write buffers
+ sync
+ sync
+ sync
+ sync
+
+ //
+ // Continue returning to firmware...
+ //
+
+
+NoPort92:
+
+
+ stw r.12, 0xCF8(r.7)
+ sync
+ stw r.6, 0xCFC(r.7) // switch PCI bus to big-endian (Eagle)
+ li r.6, 0
+ sync
+ rfi
+
+
+ .align 5
+
+//
+// When the assembler mode is Big-Endian, instructions are stored in the .OBJ
+// in a different order. To be safe, we will place instructions in groups of
+// fours, where the execution order within a group is not important.
+BigEndian:
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+
+//
+// Return the processor as close as possible to the reset state
+//
+ mtibatl 0, r.6 // Invalidate BAT registers
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+
+ mtsr 0, r.6 // Zero the Segment Registers
+ mtsr 1, r.6
+ mtsr 2, r.6
+ mtsr 3, r.6
+ mtsr 4, r.6
+ mtsr 5, r.6
+ mtsr 6, r.6
+ mtsr 7, r.6
+ mtsr 8, r.6
+ mtsr 9, r.6
+ mtsr 10, r.6
+ mtsr 11, r.6
+ mtsr 12, r.6
+ mtsr 13, r.6
+ mtsr 14, r.6
+ mtsr 15, r.6
+
+ mtsprg 0,r.6 // Should get cleared in the firmware
+ mtsprg 1,r.6 // (used for branch table)
+ mtsprg 2,r.6
+ mtsprg 3,r.6
+
+ li r.9,-1 // DECREMENTER = 0xFFFFFFFF
+ mtdec r.9
+ li r.9, 128 // # TLBs on a 604 (603 has 32)
+ mtsrr0 r.4 // rfi target = 0xfff00100
+
+ li r.7, 0
+ mtctr r.9
+ nop
+ nop
+
+Invalidate_TLB:
+ tlbie r.7 // Invalidate Instruction & Data TLBs
+ nop
+ nop
+ nop
+
+ addi r.7, r.7, 4096 // next TLB
+ nop
+ nop
+ nop
+
+ bdnz Invalidate_TLB
+ nop
+ nop
+ nop
+
+ rfi // go to machine reset handler
+ rfi
+ rfi
+ rfi
+
+ LEAF_EXIT(HalpPowerPcReset)
diff --git a/private/ntos/nthals/haleagle/ppc/pxreturn.c b/private/ntos/nthals/haleagle/ppc/pxreturn.c
new file mode 100644
index 000000000..2638d8e6a
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxreturn.c
@@ -0,0 +1,133 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Keyboard mapping code was ported to PPC.
+ This function is currently a stub since our firmware is big endian
+
+--*/
+#include "halp.h"
+#include "pxsystyp.h"
+
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KBD_DATA_PORT 0x60
+#define KBD_COMMAND_PORT 0x64
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT))
+
+VOID
+HalpPowerPcReset(
+ VOID
+ );
+
+VOID HalpFlushAndDisableL2(VOID);
+
+
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+ HalpDisableInterrupts();
+ if (HalpSystemType == MOTOROLA_BIG_BEND)
+ HalpFlushAndDisableL2();
+ HalpPowerPcReset(); // does not return
+
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxs3.h b/private/ntos/nthals/haleagle/ppc/pxs3.h
new file mode 100644
index 000000000..96f669688
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxs3.h
@@ -0,0 +1,760 @@
+/*++
+
+Copyright (c) 1992 ACER Labs Inc.
+
+Module Name:
+
+ pxs3.h
+
+Abstract:
+
+ This header file defines the S3 86C911 GUI accelerator registers.
+
+Author:
+
+ Version 1.0 Kevin Chen 2-Apr-1992
+ Version 2.0 Andrew Chou Nov-24-1992
+ Version 3.0 Jess Botts Oct-06-1993 Power PC Initial Version
+
+--*/
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+UCHAR DAC_Table[64] = {
+ // DAC for mode 3
+ 0,16, 4,20, 1,17, 5,21,
+ 32,48,36,52,33,49,37,53,
+ 8,24,12,28, 9,25,13,29,
+ 40,56,44,60,41,57,45,61,
+ 2,18, 6,22, 3,19, 7,23,
+ 34,50,38,54,35,51,39,55,
+ 10,26,14,30,11,27,15,31,
+ 42,58,46,62,43,59,47,63
+ };
+
+UCHAR DAC_Color[4] = {0x00, 0x2a, 0x15, 0x3f};
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+extern PVOID HalpIoControlBase;
+
+//
+// Define S3 register I/O Macros
+//
+
+//=============================================================================
+//
+// IBMBJB Changed the semicolons separating statements in the write macros to
+// commas so that if the macro is used as the only statement in a loop
+// all of the statements in the macro will be part of the loop.
+//
+// Commas were used instead of putting braces around the statements
+// because if the macro is used in the true part of a conditional the
+// braces will cause the compiler to generate a syntax error.
+
+#define WRITE_S3_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_S3_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_S3_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_S3_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//=============================================================================
+
+#define DISPLAY_BITS_PER_PIXEL 8 // display bits per pixel
+#define NUMBER_OF_COLORS 256 // number of colors
+
+#define CURSOR_WIDTH 64 // width of hardware cursor
+#define CURSOR_HEIGHT 64 // height of hardware cursor
+#define CURSOR_BITS_PER_PIXEL 2 // hardware cursor bits per pixel
+
+//
+// S3 86C911 GUI, accelerator Video Controller Definitions.
+//
+// Define video register format.
+//
+#define PosID_LO 0x100 // R/W
+#define PosID_HI 0x101 // R/W
+#define Setup_OP 0x102 // R/W
+#define Chck_Ind 0x105 // R
+#define Mono_3B4 0x3B4 // R/W
+#define Mono_3B5 0x3B5 // R/W
+#define MDA_Mode 0x3B8 // W
+#define HGC_SLPEN 0x3B9 // R/W
+#define Stat1_MonoIn 0x3BA // R
+#define FC_MonoW 0x3BA // W
+#define HGC_CLPEN 0x3BB // W
+#define HGC_Config 0x3BF // W
+#define Attr_Index 0x3C0 // R/W
+#define Attr_Data 0x3C0 // R/W
+#define Stat0_In 0x3C2 // R
+#define MiscOutW 0x3C2 // W
+#define VSub_EnB 0x3C3 // R/W
+#define Seq_Index 0x3C4 // R/W
+#define Seq_Data 0x3C5 // R/W
+#define DAC_Mask 0x3C6 // R/W
+#define DAC_RIndex 0x3C7 // W
+#define DAC_Status 0x3C7 // W
+#define DAC_WIndex 0x3C8 // R/W
+#define DAC_Data 0x3C9 // R/W
+#define FC_Read 0x3CA // R
+#define MiscOutR 0x3CC // R
+#define GC_Index 0x3CE // R/W
+#define GC_Data 0x3CF // R/W
+#define S3_3D4_Index 0x3D4 // R/W
+#define S3_3D5_Data 0x3D5 // R/W
+
+#define CGA_Mode 0x3D8 // W
+#define CGA_Color 0x3D9 // W
+#define Stat1_In 0x3DA // R
+#define FC_Write 0x3DA // W
+#define CLPEN 0x3DB
+#define SLPEN 0x3DC
+
+//
+// Define Enhanced registers for S3_86C911
+//
+
+#define SUBSYS_STAT 0x42E8 // R
+#define SUBSYS_CNTL 0x42E8 // W
+#define SUBSYS_ENB 0x46E8 // R/W
+#define ADVFUNC_CNTL 0x4AE8 // W
+#define CUR_Y 0x82E8 // R/W
+#define CUR_X 0x86E8 // R/W
+#define DESTY 0x8AE8 // W
+#define AXIAL_STEP 0x8AE8 // W
+#define DESTX 0x8EE8 // W
+#define DIAG_STEP 0x8EE8 // W
+#define ERR_TERM 0x92E8 // R
+#define MAJ_AXIS_PCNT 0x96E8 // W
+#define RWIDTH 0x96E8 // W
+#define GP_STAT 0x9AE8 // R
+#define DRAW_CMD 0x9AE8 // W
+#define SHORT_STROKE 0x9EE8 // W
+#define BKGD_COLOR 0xA2E8 // W
+#define FRGD_COLOR 0xA6E8 // W
+#define WRITE_MASK 0xAAE8 // W
+#define READ_MASK 0xAEE8 // W
+#define BKGD_MIX 0xB6E8 // W
+#define FRGD_MIX 0xBAE8 // W
+#define MULTIFUNC_CNTL 0xBEE8 // W
+#define RHEIGHT 0xBEE8 // W
+#define PIX_TRANS 0xE2E8 // W
+
+
+//
+// Define Attribute Controller Indexes : ( out 3C0, Index )
+//
+
+#define PALETTE0 0
+#define PALETTE1 1
+#define PALETTE2 2
+#define PALETTE3 3
+#define PALETTE4 4
+#define PALETTE5 5
+#define PALETTE6 6
+#define PALETTE7 7
+#define PALETTE8 8
+#define PALETTE9 9
+#define PALETTE10 10
+#define PALETTE11 11
+#define PALETTE12 12
+#define PALETTE13 13
+#define PALETTE14 14
+#define PALETTE15 15
+#define ATTR_MODE_CTRL 16
+#define BORDER_COLOR 17
+#define COLOR_PLANE_ENABLE 18
+#define HORI_PIXEL_PANNING 19
+#define PIXEL_PADDING 20
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Define Graphics Controller Index ( out 3CE, Index )
+//
+
+#define SET_RESET 0
+#define ENABLE_SET_RESET 1
+#define COLOR_COMPARE 2
+#define DATA_ROTATE 3
+#define READ_PLANE_SELECT 4
+#define GRAPHICS_CTRL_MODE 5
+#define MEMORY_MAP_MODE 6
+#define COLOR_DONT_CARE 7
+#define BIT_MASK 8
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA S3 Indexes
+//
+#define S3R0 0x30
+#define S3R1 0x31
+#define S3R2 0x32
+#define S3R3 0x33
+#define S3R4 0x34
+#define S3R5 0x35
+#define S3R6 0x36
+#define S3R7 0x37
+#define S3R8 0x38
+#define S3R9 0x39
+#define S3R0A 0x3A
+#define S3R0B 0x3B
+#define S3R0C 0x3C
+#define SC0 0x40
+#define SC2 0x42
+#define SC3 0x43
+#define SC5 0x45
+
+//
+// Define System Control Indexes
+//
+#define SYS_CNFG 64
+#define SOFT_STATUS 65
+#define MODE_CTRL 66
+#define EXT_MODE 67
+#define HGC_MODE 69
+#define HGC_ORGX0 70
+#define HGC_ORGX1 71
+#define HGC_ORGY0 72
+#define HGC_ORGY1 73
+#define HGC_YSTART0 76
+#define HGC_YSTART1 77
+#define HGC_DISPX 78
+#define HGC_DISPY 79
+
+#define ENABLE_HARDWARE_CURSOR 1
+#define DISABLE_HARDWARE_CURSOR 0
+
+//
+// define advanced function control register structure
+//
+#define RES_640x480 0
+#define RES_1024x768 1
+#define RES_800x600 1
+
+#define ENABLE_VGA 6
+#define ENABLE_ENHANCED 7
+
+//
+// define draw command register values
+//
+#define NOP_COMMAND 0x0
+#define DRAW_LINE_COMMAND 0x2000
+#define RECTANGLE_FILL_COMMAND 0x4000
+#define BITBLT_COMMAND 0xc000
+#define BYTE_SWAP 0x1000
+#define NO_BYTE_SWAP 0x0
+#define SIXTEEN_BIT_BUS 0x0200
+#define EIGHT_BIT_BUS 0x0
+#define WAIT 0x0100
+#define NO_WAIT 0x0
+#define R0 0x0
+#define R45 0x20
+#define R90 0x40
+#define R135 0x60
+#define R180 0x80
+#define R225 0xa0
+#define R270 0xc0
+#define R315 0xe0
+#define XMAJ 0x0
+#define YMAJ 0x40
+#define XPositive 0x20
+#define YPositive 0x80
+#define XNegative 0x0
+#define YNegative 0x0
+
+#define DRAW_YES 0x10
+#define DRAW_NO 0x0
+#define RADIAL 8
+#define XY_BASE 0
+#define LAST_PIXEL_OFF 4
+#define LAST_PIXEL_ON 0
+#define MULTIPLE_PIXEL 2
+#define SINGLE_PIXEL 0
+#define DRAW_READ 0
+#define DRAW_WRITE 1
+
+#define SSV_DRAW 0x1000
+#define SSV_MOVE 0x0
+
+#define OneEmpty 0x80
+#define TwoEmpty 0x40
+#define ThreeEmpty 0x20
+#define FourEmpty 0x10
+#define FiveEmpty 0x8
+#define SixEmpty 0x4
+#define SevenEmpty 0x2
+#define EightEmpty 0x1
+
+#define BACKGROUND_COLOR 0
+#define FOREGROUND_COLOR 0x20
+#define CPU_DATA 0x40
+#define DISPLAY_MEMORTY 0x60
+#define NOT_SCREEN 0
+#define LOGICAL_ZERO 1
+#define LOGICAL_ONE 2
+#define LEAVE_ALONE 3
+#define NOT_NEW 4
+#define SCREEN_XOR_NEW 5
+#define NOT_SCREEN_XOR_NEW 6
+#define OVERPAINT 7 //( NEW )
+#define NOT_SCREEN_OR_NOT_NEW 8
+#define SCREEN_OR_NOT_NEW 9
+#define NOT_SCREEN_OR_NEW 10
+#define SCREEN_OR_NEW 11
+#define SCREEN_AND_NEW 12
+#define NOT_SCREEN_AND_NEW 13
+#define SCREEN_AND_NOT_NEW 14
+#define NOT_SCREEN_AND_NOT_NEW 15
+
+#define BEE8_1H 1
+#define BEE8_2H 2
+#define BEE8_3H 3
+#define BEE8_4H 4
+#define BEE8_0H 0
+#define L_CLIP 0x1000
+#define R_CLIP 0x2000
+#define B_CLIP 0x3000
+#define T_CLIP 0x4000
+
+#define DATA_EXTENSION 0xa000 // 10100000B
+#define CPU_EXT 0x80
+#define DISPLAY_EXT 0xc0
+#define NO_EXTENSION 0x0
+#define PACK_DATA 0x4
+#define NO_PACK_DATA 0x0
+#define SET_THIS_BIT_TO_ZERO 0;
+
+//
+// Define bits per pixel codes.
+//
+#define ONE_BIT_PER_PIXEL 0 // 1-bit per pixel
+#define TWO_BITS_PER_PIXEL 1 // 2-bits per pixel
+#define FOUR_BITS_PER_PIXEL 2 // 4-bits per pixel
+#define EIGHT_BITS_PER_PIXEL 3 // 8-bits per pixel
+
+//
+// Define address step value.
+//
+#define ADDRESS_STEP_INCREMENT 1 // vram transfer address increment
+
+//
+// Define cross hair thickness values.
+//
+#define ONE_PIXEL_THICK 0x0 // one pixel in thickness
+#define THREE_PIXELS_THICK 0x1 // three pixels in thickness
+#define FIVE_PIXELS_THICK 0x2 // five pixels in thickness
+#define SEVEN_PIXELS_THICK 0x3 // seven pixels in thickness
+
+//
+// Define multiplexer control values.
+//
+#define ONE_TO_ONE 0x0 // 1:1 multiplexing
+#define FOUR_TO_ONE 0x1 // 4:1 multiplexing
+#define FIVE_TO_ONE 0x2 // 5:1 multiplexing
+
+//
+// Define cursor origin values.
+//
+
+#define CURSOR_X_ORIGIN (((2*HORIZONAL_SYNC_VALUE)+BACK_PORCH_VALUE)*4-36)
+#define CURSOR_Y_ORIGIN ((VERTICAL_BLANK_VALUE/2)+24)
+
+ULONG HotspotX, HotspotY;
+
+// Extended VGA BIOS
+#define SUPER_VGA_SUPPORT 4FH
+#define RET_EXT_VGA_INFO 00H
+#define RET_EXT_VGA_MODE_INFO 01H
+#define SET_EXT_VGA_MODE 02H
+#define QUERY_CUR_EXT_VGA_MODE 03H
+
+#define SAVE_RESTORE_FUNCTION 04H
+// Function 04.0 Query Save/Restore Buffer Size
+#define GET_SAVE_BUFFER_SIZE 00H
+// Function 04.1 Save Extended Video state
+#define SAVE_STATE 01H
+// Function 04.2 Restore Extended VGA state
+#define RESTORE_STATE 02H
+
+#define WINDOWS_CONTROL 05H
+// Function 05.0 Set Window Control
+#define SELECT_PAGE_TO_BE_MAPPED 00H
+// fUNCTION 05.1 Get Window Control Setting
+#define GET_PAGE_MAPPED 01H
+
+#define SET_RESET_DUAL_DISPLAY_MODE FFH
+
+BOOLEAN ColorMonitor;
+PVOID S3_3x4, S3_3x5;
+UCHAR VideoParam[62] = {
+// Mode +3 480 Lines
+// External Registers 3C3, 3C2
+0x01,0x67,
+
+//=============================================================================
+//
+// IBMBJB changed value at offset 17 (5th number on second line) from 0x8e
+// to 0xae to disable the vertical retrace interrupt
+
+// CRT Controller Registers 3D4, 3D5
+0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,
+// 0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+ 0x00,0x00,0x00,0x9c,0xae,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+
+//=============================================================================
+
+// Sequencer Registers 3C4, 3C5
+// 0x01,0x01,0x03,0x00,0x02,
+0x01,0x20,0x03,0x00,0x02,
+
+// Graphic Control Registers
+0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff,
+
+// Attribute Controller Registers
+0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,
+0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00};
+
+
+UCHAR VGAFont8x16[4096] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00
+0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7E,0xFF,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // 8
+0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, // 9
+0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, // a
+0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, // 10
+0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, // 4
+0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 20
+0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // 1
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x18,0x18,0x7C,0xC6,0xC2,0x7C,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 30
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // b
+0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // 40
+0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 50
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // d
+0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, // f
+
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 60
+0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00, // 7
+0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // a
+0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 70
+0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, // 80
+0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, // 7
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // d
+0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // 90
+0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 8
+0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, // b
+0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, // f
+
+0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a0
+0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 1
+0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // 4
+0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 5
+0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, // b
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, // c
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // b0
+0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // 1
+0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // a
+0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // f
+
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c0
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // c
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // e
+0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d0
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 2
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // a
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // c
+0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // d
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // e
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, // e0
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00, // 1
+0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, // f0
+0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, // 3
+0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, // b
+0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // f
+ };
diff --git a/private/ntos/nthals/haleagle/ppc/pxsiosup.c b/private/ntos/nthals/haleagle/ppc/pxsiosup.c
new file mode 100644
index 000000000..1cd1c9789
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsiosup.c
@@ -0,0 +1,1761 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsiosup.c
+
+Abstract:
+
+ The module provides the PCI ISA bridge support.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "pxsystyp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "bugcodes.h"
+
+
+#define SioId 0x04848086 // UMC 8886
+
+PVOID HalpPciIsaBridgeConfigBase;
+extern USHORT Halp8259MaskTable[];
+extern PADAPTER_OBJECT MasterAdapterObject;
+VOID HalpUpdate8259(KIRQL Irql);
+
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+//
+// Declare the interrupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interrupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interrupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+//
+// Map the interrupt controllers priority scheme to NT IRQL values.
+// The SIO prioritizes IRQs as follows:
+// IRQ0, IRQ1, IRQ8 ... IRQ15, IRQ3, IRQ4 ... IRQ7.
+//
+// NOTE: The following table must be coordinated with the entries
+// in Halp8259MaskTable in PXIRQL.C
+//
+KIRQL VectorToIrql[16] = {
+// IRQL Vector
+// ---- ------
+ 26, // 0
+ 25, // 1
+ 24, // 2
+ 15, // 3
+ 14, // 4
+ 13, // 5
+ 12, // 6
+ 11, // 7
+ 23, // 8
+ 22, // 9
+ 21, // 10
+ 20, // 11
+ 19, // 12
+ 18, // 13
+ 17, // 14
+ 16 }; // 15
+
+KIRQL HalpTranslateVectorToIrql(
+ IN ULONG Vector
+ )
+{ // It is assumed that the caller has checked that Vector is valid (0..15)
+ return VectorToIrql[Vector];
+}
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+
+//
+// Define Isa bus interrupt affinity.
+//
+
+KAFFINITY HalpIsaBusAffinity;
+
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask registers
+// and level\edge control registers.
+//
+
+USHORT HalpSioInterruptLevel = 0x0000; // Default to edge-sensitive
+
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{ UCHAR DataByte;
+ ULONG Vector;
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second initialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+
+ //
+ // Mask all 8259 interrupts (except the Slave input)
+ //
+
+ for (Vector=0; Vector<= HIGHEST_8259_VECTOR; Vector++) {
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+ HalpEnableSioInterrupt(SLAVE_IRQL_LEVEL + DEVICE_VECTORS, Latched);
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt;
+
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initialized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+
+ //
+ // Enable the clock interrupt
+ //
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine is entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ UCHAR Irql;
+
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // check for nmi interrupt before we raise irql since we would raise to a
+ // bogus level
+ //
+
+ if (interruptVector == 0xFF) {
+
+ HalpHandleMachineCheck(NULL, NULL);
+ }
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (interruptVector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+#if DBG
+ //DbgPrint("A spurious interrupt occurred. \n");
+ HalpSpuriousInterruptCount++;
+#endif
+ return(0);
+
+ }
+ }
+
+ if (interruptVector > HIGHEST_8259_VECTOR) {
+#if DBG
+ DbgPrint("A bogus interrupt (0x%02x) occurred. \n", interruptVector);
+ HalpBogusInterruptCount++;
+#endif
+ return (0);
+ }
+
+ //
+ // Translate vector to IRQL and raise IRQL
+ //
+
+ Irql = HalpTranslateVectorToIrql(interruptVector);
+ KeRaiseIrql( Irql, &OldIrql);
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Lower IRQL but disable external interrupts.
+ // Return to caller with interrupts disabled.
+ //
+
+
+ HalpResetIrqlAfterInterrupt(OldIrql);
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{ USHORT MaskBit, i;
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+ Vector -= DEVICE_VECTORS;
+
+ if (Vector <= HIGHEST_8259_VECTOR) {
+ //
+ // Generate 8259 mask
+ //
+ MaskBit = (USHORT) (1 << Vector);
+
+ //
+ // Set the mask bit in Halp8259MaskTable
+ //
+ for (i = 0; i <= 31; i++) {
+ Halp8259MaskTable[i] |= MaskBit;
+ }
+
+ // Write new mask values to 8259s
+ HalpUpdate8259(PCR->CurrentIrql);
+ }
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{ USHORT MaskBit, Irql, i;
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+ Vector -= DEVICE_VECTORS;
+
+ if (Vector <= HIGHEST_8259_VECTOR) {
+ //
+ // Generate 8259 mask
+ //
+ MaskBit = (USHORT) ~(1 << Vector);
+
+
+ //
+ // Force interrupts to be latched (edge-triggered) if Big Bend
+ //
+ if(HalpSystemType == MOTOROLA_BIG_BEND)
+ InterruptMode = Latched;
+
+ //
+ // Set the level/edge control register.
+ //
+ if (InterruptMode == LevelSensitive) {
+ HalpSioInterruptLevel |= ~MaskBit;
+ } else {
+ HalpSioInterruptLevel &= MaskBit;
+ }
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ (UCHAR) (HalpSioInterruptLevel >> 8)
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ (UCHAR) HalpSioInterruptLevel
+ );
+ }
+
+
+ //
+ // Clear mask bit in Halp8259MaskTable
+ //
+ Irql = VectorToIrql[Vector];
+ for (i = 0; i < Irql; i++) {
+ Halp8259MaskTable[i] &= MaskBit;
+ }
+
+ // Write new mask values to 8259s
+ HalpUpdate8259(PCR->CurrentIrql);
+ }
+}
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is significantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialize the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transferred.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still to be transferred.
+
+--*/
+
+{
+ ULONG count=0;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxsiosup.h b/private/ntos/nthals/haleagle/ppc/pxsiosup.h
new file mode 100644
index 000000000..6b94bdc51
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsiosup.h
@@ -0,0 +1,221 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x8]; // Offset 0x58
+ UCHAR PciIrq0RouteControl; // Offset 0x60
+ UCHAR PciIrq1RouteControl; // Offset 0x61
+ UCHAR PciIrq2RouteControl; // Offset 0x62
+ UCHAR PciIrq3RouteControl; // Offset 0x63
+ UCHAR Reserved5[0x1C]; // Offset 0x64
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+#define HIGHEST_8259_VECTOR 15
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+
+
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/haleagle/ppc/pxstall.s b/private/ntos/nthals/haleagle/ppc/pxstall.s
new file mode 100644
index 000000000..fd3555c0d
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxstall.s
@@ -0,0 +1,326 @@
+//#***********************************************************************
+//
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Copyright 1993 International Buisness Machines Corporation.
+// All Rights Reserved.
+//
+// This file contains copyrighted material. Use of this file is
+// restricted by the provisions of a Motorola/IBM Joint Software
+// License Agreement.
+//
+// File Name:
+// PXSTALL.S
+//
+// Functions:
+// KeStallExecutionProcessor
+// HalpCalibrateStall
+//
+// History:
+// 21-Sep-1993 Steve Johns
+// Original Version
+// 24-Dec-1993 Peter Johnston
+// Adapted to 601 HAL in an attempt to avoid having different
+// versions if at all possible. Original was designed for both
+// 601 and 603 but had some 601 difficulties.
+// 17-Jan-1994 Steve Johns
+// Changed to treat 601 vs PowerPC time base differences more
+// transparently.
+// 11-Sep-1995 Steve Johns
+// Removed 601 specific ocde
+// Removed 603 workaround, since we don't support < 603 v3.2
+//
+//#***********************************************************************
+
+
+
+#include "halppc.h"
+
+#define ERRATA603 FALSE
+#define CMOS_INDEX 0x70
+#define CMOS_DATA 0x71
+#define RTC_SECOND 0x80
+
+
+ .extern HalpPerformanceFrequency
+ .extern HalpIoControlBase
+ .extern ..HalpDivide
+
+//
+// Register Definitions
+//
+ .set Microsecs, r.3
+ .set TimerLo , r.6
+ .set TimerHi , r.7
+ .set EndTimerLo, r.3
+ .set EndTimerHi, r.4
+ .set Temp , r.8
+ .set Temp2 , r.9
+ .set IO_Base , r.10
+
+//#***********************************************************************
+//
+// Synopsis:
+// VOID KeStallExecutionProcessor(
+// ULONG Microseconds)
+//
+// Purpose:
+// This function stalls the execution at least the specified number
+// of microseconds, but not substantially longer.
+//
+// Returns:
+// Nothing.
+//
+// Global Variables Referenced:
+// HalpPerformanceFrequency
+//#***********************************************************************
+
+ SPECIAL_ENTRY(KeStallExecutionProcessor)
+ mflr r.0 // Save Link Register
+ PROLOGUE_END(KeStallExecutionProcessor)
+
+ cmpli 0,0,Microsecs,0 // if (Microseconds == 0)
+ beqlr- // return;
+
+//
+// Read START time
+//
+ bl ..HalpReadTB // ReadPerformanceCounter();
+
+//
+// Get PerformanceCounter frequency
+//
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp)
+//
+// Compute: (Microseconds * PerformanceFrequency) / 1,000,000
+//
+ mulhwu. EndTimerHi,Microsecs,Temp
+ mullw EndTimerLo,Microsecs,Temp
+ LWI (r.5, 1000000)
+ bl ..HalpDivide
+
+//
+// Account for software overhead
+//
+ .set Overhead, 30
+ cmpwi r.3, Overhead
+ ble SkipOverhead
+ addi r.3, r.3, -Overhead // Reduce delay
+SkipOverhead:
+
+//
+// Add delay to start time
+//
+ addc EndTimerLo, TimerLo, r.3
+ addze EndTimerHi, TimerHi
+
+
+
+//
+// while (ReadPerformanceCounter() < EndTimer);
+//
+StallLoop:
+ bl ..HalpReadTB // Read Time Base
+ cmpl 0,0,TimerHi,EndTimerHi // Is TimerHi >= EndTimerHi ?
+ blt- StallLoop // No
+ bgt+ StallExit // Yes
+ cmpl 0,0,TimerLo,EndTimerLo // Is TimerLo >= EndTimerLo ?
+ blt StallLoop // Branch if not
+
+StallExit:
+ mtlr r.0 // Restore Link Register
+
+ SPECIAL_EXIT(KeStallExecutionProcessor)
+
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for PowerPC
+// architectures (not the 601).
+//
+ LEAF_ENTRY (HalpReadTB)
+
+ mftbu TimerHi // Read the TB registers coherently
+ mftb TimerLo
+#if ERRATA603
+ mftb TimerLo
+ mftb TimerLo
+ mftb TimerLo
+#endif
+ mftbu Temp
+ cmpl 0,0,Temp,TimerHi
+ bne- ..HalpReadTB
+
+ LEAF_EXIT (HalpReadTB)
+
+
+
+//
+// Returns the number of performance counter ticks/second.
+//
+// The DECREMENTER is clocked at the same rate as the PowerPC Time Base (TB)
+// and the POWER RTC. The POWER RTC is supposed to be clocked at 7.8125 MHz,
+// but on early prototypes of the Sandalfoot platform, this is not true).
+// In either case, to keep the calibration routine simple and generic, we
+// will determine the DECREMENTER clock rate by counting ticks for exactly
+// 1 second (as measured against the CMOS RealTimeClock). We then use that
+// value in the KeStallExecutionProcessor() and KeQueryPerformanceCounter()
+//
+
+ LEAF_ENTRY(HalpCalibrateTB)
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+
+
+WaitForTick1:
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.3,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2:
+ li r.4,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ LEAF_EXIT(HalpCalibrateTB)
+
+
+
+ LEAF_ENTRY(HalpCalibrateTBPStack)
+
+#define NVRAM_INDEX_LO 0x74
+#define NVRAM_INDEX_HI 0x75
+#define NVRAM_DATA 0x77
+#define RTC_OFFSET 0x1ff8
+#define RTC_CONTROL 0x0
+#define RTC_SECONDS 0x1
+#define WRITE 0x80
+#define READ 0x40
+
+#define SYNCHRONIZE \
+ sync; \
+ sync; \
+ sync
+
+#define READ_RTC_REG(reg, reg_num_lo, reg_num_hi) \
+ stb reg_num_lo,NVRAM_INDEX_LO(r10); \
+ stb reg_num_hi,NVRAM_INDEX_HI(r10); \
+ SYNCHRONIZE; \
+ lbz reg,NVRAM_DATA(r10)
+
+#define WRITE_RTC_REG(reg, reg_num_lo, reg_num_hi) \
+ stb reg_num_lo,NVRAM_INDEX_LO(r10); \
+ stb reg_num_hi,NVRAM_INDEX_HI(r10); \
+ SYNCHRONIZE; \
+ stb reg,NVRAM_DATA(r10); \
+ SYNCHRONIZE
+
+// Here are the steps to getting the Seconds register out of the CMOS RTC
+// A. Stop the RTC
+// 1. Read control reg
+// 2. Set READ bit
+// 3. write control reg
+//
+// B. Read Seconds
+//
+// C. Restart the RTC
+// 1. Read control reg
+// 2. Clear READ bit
+// 3. write control reg
+
+#define GET_SECONDS(reg) \
+ READ_RTC_REG(r9, r7, r8); \
+ ori r9,r9,READ; \
+ WRITE_RTC_REG(r9, r7, r8); \
+ \
+ READ_RTC_REG(reg, r5, r6); \
+ \
+ READ_RTC_REG(r9, r7, r8); \
+ andi. r9,r9,~READ; \
+ WRITE_RTC_REG(r9, r7, r8)
+
+ // Get base address of ISA I/O space
+ // so we can talk to the CMOS RTC
+ lwz r10,[toc]HalpIoControlBase(r.toc)
+ lwz r10,0(r10)
+
+ // Set up some offsets into the Real
+ // Time Clock...
+ li r5,RTC_OFFSET+RTC_SECONDS // r5 <- Seconds register offset
+ rlwinm r6,r5,32-8,24,31 // r6 <- Shift > 8 and mask 0xff
+ li r7,RTC_OFFSET+RTC_CONTROL // r7 <- Control register Offset
+ rlwinm r8,r7,32-8,24,31 // r8 <- Shift > 8 and mask 0xff
+
+WaitForRTC.Ps:
+ READ_RTC_REG(r3, r7, r8) // Read Control register
+ andi. r3,r3,WRITE // Is it being written to?
+ bne WaitForRTC.Ps // If so, loop again
+ GET_SECONDS(r3) // Get RTC seconds register
+
+WaitForTick0.Ps:
+ READ_RTC_REG(r4, r7, r8) // Read Control register
+ andi. r4,r4,WRITE // Is it being written to?
+ bne WaitForTick0.Ps // If so, loop again
+ GET_SECONDS(r4) // Get RTC seconds register
+ cmpw r4,r3 // Loop until it changes
+ beq WaitForTick0.Ps
+
+
+WaitForTick1.Ps:
+ READ_RTC_REG(r3, r7, r8) // Read Control register
+ andi. r3,r3,WRITE // Is it being written to?
+ bne WaitForTick1.Ps // If so, loop again
+ GET_SECONDS(r3) // Get RTC seconds register
+ cmpw r3,r4 // Loop until it changes
+ beq WaitForTick1.Ps
+
+ li r4,-1 // Start the decrementer at max. count
+ mtdec r4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2.Ps:
+ READ_RTC_REG(r4, r7, r8) // Read Control register
+ andi. r4,r4,WRITE // Is it being written to?
+ bne WaitForTick2.Ps // If so, loop again
+ GET_SECONDS(r4) // Get RTC seconds register
+ cmpw r4,r3 // Loop until it changes
+ beq WaitForTick2.Ps
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ LEAF_EXIT(HalpCalibrateTBPStack)
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxsysbus.c b/private/ntos/nthals/haleagle/ppc/pxsysbus.c
new file mode 100644
index 000000000..cb3e6c720
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsysbus.c
@@ -0,0 +1,204 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - IBM
+ - ported to PowerPC
+ 9/26/95 Steve Johns - Motorola
+ - use BusInterruptLevel instead of BusInterruptVector
+
+
+--*/
+
+#include "halp.h"
+
+#include "eisa.h"
+#include "pxmemctl.h"
+#include "pxsiosup.h"
+#include "pxsystyp.h"
+
+KIRQL HalpTranslateVectorToIrql(IN ULONG Vector);
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+
+ if (BusInterruptLevel > HIGHEST_8259_VECTOR) {
+ //
+ // Invalid BusInterruptLevel, so return Affinity of 0x0000;
+ //
+ *Affinity = 0;
+ return(DEVICE_VECTORS);
+
+ } else {
+
+ *Affinity = 1;
+
+ //
+ // Translate BusInterruptLevel to IRQL
+ //
+ *Irql = HalpTranslateVectorToIrql(BusInterruptLevel);
+
+ //
+ // The vector is equal to the specified bus level + DEVICE_VECTORS.
+ //
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxsysint.c b/private/ntos/nthals/haleagle/ppc/pxsysint.c
new file mode 100644
index 000000000..b02a11ca7
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsysint.c
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrupt.
+ //
+
+ if (Vector >= DEVICE_VECTORS && Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= DEVICE_VECTORS && Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpEnableSioInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxsystyp.c b/private/ntos/nthals/haleagle/ppc/pxsystyp.c
new file mode 100644
index 000000000..a35666f81
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsystyp.c
@@ -0,0 +1,96 @@
+//++
+//
+// Copyright (c) 1994, 1995 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxsystyp.c
+//
+// Abstract:
+//
+// Add a global variable to indicate which system implementation we are
+// running on. Called early in phase 0 init.
+//
+// Author:
+//
+// Bill Jones 12/94
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+
+#include "halp.h"
+#include "fwstatus.h"
+#include "arc.h"
+#include "pxsystyp.h"
+#include "fwnvr.h"
+
+SYSTEM_TYPE HalpSystemType = SYSTEM_UNKNOWN;
+extern NVR_SYSTEM_TYPE nvr_system_type;
+
+extern ULONG HalpPciConfigSlot[];
+ULONG HalpPciPowerStack[] = { 0x0800,
+ 0x1000,
+ 0x2000,
+ 0x4000,
+ 0x10000,
+ 0x20000,
+ 0x40000,
+ 0x80000,
+ 0x8000
+ };
+
+BOOLEAN
+HalpSetSystemType( PLOADER_PARAMETER_BLOCK LoaderBlock );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpSetSystemType)
+#endif
+
+BOOLEAN
+HalpSetSystemType( PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ &MatchKey);
+
+ if (ConfigurationEntry != NULL) {
+
+
+#if DBG
+ //DbgPrint("HAL: System configuration = %s\n",ConfigurationEntry->ComponentEntry.Identifier);
+#endif
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"MOTOROLA-Big Bend")) {
+ HalpSystemType = MOTOROLA_BIG_BEND;
+ nvr_system_type = nvr_systype_bigbend;
+
+ } else {
+ //
+ // Assume it is a PowerStack or OEM'ed PowerStack
+ //
+ //
+ HalpSystemType = MOTOROLA_POWERSTACK;
+ nvr_system_type = nvr_systype_powerstack;
+ //
+ // Change PCI addresses for Blackhawk
+ // to support other PCI video boards.
+ //
+ memcpy(HalpPciConfigSlot, HalpPciPowerStack, sizeof(HalpPciPowerStack));
+
+ }
+ }
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxsystyp.h b/private/ntos/nthals/haleagle/ppc/pxsystyp.h
new file mode 100644
index 000000000..f58fdcbf5
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsystyp.h
@@ -0,0 +1,44 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994, 1995 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxsystyp.h
+//
+// Abstract:
+//
+// Add a global variable to indicate which system implementation we are
+// running on. Called early in phase 0 init.
+//
+// Author:
+//
+// Bill Jones 12/94
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+
+
+BOOLEAN
+HalpSetSystemType( PLOADER_PARAMETER_BLOCK LoaderBlock );
+
+
+
+typedef enum {
+ MOTOROLA_BIG_BEND = 0,
+ MOTOROLA_POWERSTACK,
+ SYSTEM_UNKNOWN = 255
+} SYSTEM_TYPE;
+
+
+extern SYSTEM_TYPE HalpSystemType;
diff --git a/private/ntos/nthals/haleagle/ppc/pxtime.c b/private/ntos/nthals/haleagle/ppc/pxtime.c
new file mode 100644
index 000000000..7d18eb667
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxtime.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#include "halp.h"
+#include "pxsystyp.h"
+
+BOOLEAN
+HalQueryRealTimeClockMk (
+ OUT PTIME_FIELDS TimeFields
+ );
+BOOLEAN
+HalSetRealTimeClockMk (
+ OUT PTIME_FIELDS TimeFields
+ );
+BOOLEAN
+HalQueryRealTimeClockDs (
+ OUT PTIME_FIELDS TimeFields
+ );
+BOOLEAN
+HalSetRealTimeClockDs (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ switch (HalpSystemType) {
+
+ break;
+
+ case MOTOROLA_POWERSTACK:
+ return HalQueryRealTimeClockMk(TimeFields);
+ break;
+
+ case SYSTEM_UNKNOWN:
+ case MOTOROLA_BIG_BEND:
+ default:
+ return HalQueryRealTimeClockDs(TimeFields);
+ break;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ switch (HalpSystemType) {
+
+ break;
+
+ case MOTOROLA_POWERSTACK:
+ return HalSetRealTimeClockMk(TimeFields);
+ break;
+
+ case SYSTEM_UNKNOWN:
+ case MOTOROLA_BIG_BEND:
+ default:
+ return HalSetRealTimeClockDs(TimeFields);
+ break;
+ }
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxusage.c b/private/ntos/nthals/haleagle/ppc/pxusage.c
new file mode 100644
index 000000000..4a9fbf1f3
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxusage.c
@@ -0,0 +1,503 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+
+ KeInitializeInterrupt( Interrupt,
+ ServiceRoutine,
+ ServiceContext,
+ SpinLock,
+ Vector,
+ Irql,
+ SynchronizeIrql,
+ InterruptMode,
+ ShareVector,
+ ProcessorNumber,
+ FloatingSave
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ if (!KeConnectInterrupt( Interrupt )) {
+
+ return(FALSE);
+ }
+
+ HalpRegisterVector (ReportFlags, BusVector, Vector, Irql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ return(TRUE);
+
+
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList=NULL, pTPartList=NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+
+ for(i=0; i < DEVICE_VECTORS; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ ASSERT(pRPartList != NULL);
+ ASSERT(pTPartList != NULL);
+
+ if(pRPartList) pRPartList->Count++;
+ if(pTPartList) pTPartList->Count++;
+
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/sysbios.c b/private/ntos/nthals/haleagle/ppc/sysbios.c
new file mode 100644
index 000000000..9aa6dc90c
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/sysbios.c
@@ -0,0 +1,73 @@
+/*++
+
+
+Copyright (C) 1996 Motorola Inc.
+
+Module Name:
+
+ sysbios.c
+
+Abstract:
+
+ Emulate System BIOS functions.
+
+Author:
+
+ Scott Geranen
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "emulate.h"
+#include "sysbios.h"
+#include "pcibios.h"
+
+BOOLEAN
+HalpEmulateSystemBios(
+ IN OUT PRXM_CONTEXT P,
+ IN ULONG Number
+ )
+/*++
+
+Routine Description:
+
+ This function emulates a system BIOS. However, this is really
+ intended to support video bios functions, not all system BIOS
+ functions are implemented.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+ Number - interrupt number used to enter
+
+Return Value:
+
+ TRUE = the function was emulated
+ FALSE = the function was not emulated
+
+--*/
+{
+ switch (Number) {
+ case 0x1A:
+ if (P->Gpr[EAX].Xh == PCIBIOS_PCI_FUNCTION_ID) {
+ return HalpEmulatePciBios(P);
+ }
+
+ //
+ // Fall into the default case.
+ //
+
+ default:
+ return FALSE; // not supported
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/sysbios.h b/private/ntos/nthals/haleagle/ppc/sysbios.h
new file mode 100644
index 000000000..6119bc2d0
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/sysbios.h
@@ -0,0 +1,31 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1996 Motorola Inc.
+
+Module Name:
+
+ sysbios.h
+
+Abstract:
+
+ This module contains the private header file for the system BIOS
+ emulation.
+
+Author:
+
+ Scott Geranen (3-4-96)
+
+Revision History:
+
+--*/
+
+#ifndef _SYSBIOS_
+#define _SYSBIOS_
+
+BOOLEAN
+HalpEmulateSystemBios(
+ IN OUT PRXM_CONTEXT P,
+ IN ULONG Number
+ );
+
+#endif // _SYSBIOS_
diff --git a/private/ntos/nthals/haleagle/ppc/txtpalet.h b/private/ntos/nthals/haleagle/ppc/txtpalet.h
new file mode 100644
index 000000000..307464362
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/txtpalet.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+
+txtpalet.h
+
+ Author: Jess Botts
+
+ This file contains the text mode palette. Most of the entries are 0
+ because they are not used. The first 8 entries are used for all
+ background colors and normal intensity foregound colors. Background
+ colors are displayed at normal intensity only. The 8 entries that
+ begin at the 56th entry are used for high intensity foreground colors.
+
+ Each entry consists of 3 values, 1 for each color gun.
+
+******************************************************************************/
+
+UCHAR
+ TextPalette[] =
+ { /*
+ Line
+ R G B R G B R G B R G B Index
+ */
+
+// all background colors and normal intensity foregound colors
+
+ 0, 0, 0, 0, 0, 32, 0, 32, 0, 0, 32, 32, // 0
+ 32, 0, 0, 32, 0, 32, 32, 32, 0, 32, 32, 32,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+// high intensity foreground colors
+
+ 16, 16, 16, 0, 0, 63, 0, 63, 0, 0, 63, 63, // 56
+ 63, 0, 0, 63, 0, 63, 63, 63, 0, 63, 63, 63,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+/*****************************************************************************/
diff --git a/private/ntos/nthals/haleagle/ppc/x86bios.c b/private/ntos/nthals/haleagle/ppc/x86bios.c
new file mode 100644
index 000000000..1002fae70
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/x86bios.c
@@ -0,0 +1,1156 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 9/26/95 Steve Johns - Motorola
+ - Don't scan last PCI slot if PowerStack
+ - Don't execute PCI ROM if BaseClass indicates not video
+
+ 3/29/96 Scott Geranen - Motorola
+ - call PCI BIOS with bus/dev/func arguments
+--*/
+
+
+#define USE_BIOS_EMULATOR
+
+
+
+#include "halp.h"
+#include "xm86.h"
+#include "x86new.h"
+#include "pxpcisup.h"
+#include "pxsystyp.h"
+#include "pci.h"
+
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPciConfigSize;
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+PVOID HalpIoMemoryBase = NULL;
+PUCHAR HalpRomBase = NULL;
+
+UCHAR HalpVideoBus; // Used as arguments to the PCI BIOS
+UCHAR HalpVideoDevice; // init function. Set HalpInitX86Emulator,
+UCHAR HalpVideoFunction; // used by HalpInitializeX86DisplayAdapter.
+
+UCHAR HalpLastPciBus; // Set by scanning the configuration data and
+ // used by PCI BIOS eumulation code.
+
+//
+// The MPC105 and the IBM27-82660 map the device number to the AD
+// line differently. This value is used to compensate for the
+// difference. Any HAL #including this file should set this value
+// appropriately. Note that this value is subtracted from the
+// computed AD line.
+//
+#ifndef PCI_DEVICE_NUMBER_OFFSET
+#define PCI_DEVICE_NUMBER_OFFSET 0 // default value for eagle
+#endif
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (64*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+
+BOOLEAN HalpInitX86Emulator(
+ VOID)
+
+{
+ULONG ROM_size = 0;
+PHYSICAL_ADDRESS PhysAddr;
+USHORT Cmd, VendorID;
+ULONG Slot, EndSlot;
+PVOID HalpVideoConfigBase;
+PUCHAR ROM_Ptr, ROM_Shadow;
+ULONG i;
+UCHAR BaseClass;
+
+
+ PhysAddr.HighPart = 0x00000000;
+
+ EndSlot = HalpPciMaxSlots;
+ if (HalpSystemType == MOTOROLA_POWERSTACK)
+ EndSlot--;
+
+ //
+ // Scan PCI slots for video BIOS ROMs, except 2 PCI "slots" on motherboard
+ //
+ for (Slot = 2; Slot < EndSlot; Slot++) {
+
+ //
+ // Create a mapping to PCI configuration space
+ //
+ if( HalpPciConfigBase == NULL) {
+
+ HalpPciConfigBase = KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+
+
+ if (HalpPciConfigBase == NULL) {
+ DbgPrint("\nCan't create mapping to PCI Configuration Space\n");
+ return FALSE;
+ }
+ }
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot]);
+
+ //
+ // Read Vendor ID and check if slot is empty
+ //
+ VendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ if (VendorID == 0xFFFF)
+ continue; // Slot is empty; go to next slot
+
+ //
+ // If Base Class does not indicate video, go to next slot
+ //
+ BaseClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ if (BaseClass != 0 && BaseClass != 3)
+ continue;
+
+
+ //
+ // Get size of ROM
+ //
+ WRITE_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase, 0xFFFFFFFF);
+ ROM_size = READ_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase);
+
+ if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
+
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Set Expansion ROM Base Address & enable ROM
+ //
+ PhysAddr.LowPart = 0x000C0000 | 1;
+ WRITE_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase, PhysAddr.LowPart);
+
+
+
+ //
+ // Enable Memory & I/O spaces in command register
+ //
+ Cmd = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command);
+ WRITE_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command, Cmd | 3);
+
+ //
+ // Delete the mapping to PCI config space
+ //
+ HalpPciConfigBase = HalpVideoConfigBase = NULL;
+ KePhase0DeleteIoMap( PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+
+ //
+ // Create a mapping to the PCI memory space
+ //
+ HalpIoMemoryBase = KePhase0MapIo(PCI_MEMORY_BASE, ROM_size);
+
+ if (HalpIoMemoryBase == NULL) {
+ DbgPrint("\nCan't create mapping to PCI memory space\n");
+ return FALSE;
+ }
+
+ //
+ // Look for PCI option video ROM signature
+ //
+ HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+
+
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // Sometimes option ROM and video RAM can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ }
+
+ //
+ // Setup the PCI location for calling the BIOS init code.
+ // "Slot" needs to be translated into the device number
+ // suitable for CF8/CFC config accesses. In this case,
+ // if bit 11 set, dev = 11, etc.
+ //
+ HalpVideoBus = 0;
+ HalpVideoFunction = 0;
+
+ i = HalpPciConfigSlot[Slot] >> 1;
+ HalpVideoDevice = 0;
+
+ while (i) {
+ HalpVideoDevice++;
+ i >>= 1;
+ }
+
+ HalpVideoDevice -= PCI_DEVICE_NUMBER_OFFSET;
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+
+ //
+ // Delete mapping to PCI memory space
+ //
+ HalpIoMemoryBase = NULL;
+ KePhase0DeleteIoMap(PCI_MEMORY_BASE, HalpPciConfigSize);
+
+ //
+ // Restore PCI command register
+ //
+ HalpPciConfigBase = KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+
+ if (HalpPciConfigBase == NULL) {
+ DbgPrint("\nCan't create mapping to PCI Configuration Space\n");
+ return FALSE;
+ }
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot]);
+ WRITE_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command, Cmd);
+
+
+ } // end of if clause
+ } // end of for loop
+
+
+ //
+ // Delete mapping to PCI config space
+ //
+ if (HalpPciConfigBase) {
+ HalpPciConfigBase = NULL;
+ KePhase0DeleteIoMap(PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+ }
+
+
+ //
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+ if (HalpIoMemoryBase == NULL) {
+ HalpIoMemoryBase = KePhase0MapIo(PCI_MEMORY_BASE, ROM_size);
+ }
+
+
+ if (HalpIoMemoryBase == NULL) {
+ return FALSE;
+ } else {
+ //
+ // Look for ISA option video ROM signature
+ //
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ }
+ return TRUE;
+ }
+
+ //
+ // No video option ROM was found. Delete mapping to PCI memory space.
+ //
+ KePhase0DeleteIoMap(PCI_MEMORY_BASE, ROM_size);
+
+
+ return FALSE;
+ }
+}
+
+
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
+ &Context,
+ HalpIoControlBase,
+ HalpIoMemoryBase) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ LoaderBlock for access to the number of PCI buses
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ ULONG MatchKey;
+ PCM_PARTIAL_RESOURCE_LIST Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial;
+ XM86_CONTEXT State;
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (!HalpInitX86Emulator())
+ return FALSE;
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Get the number of PCI buses for the PCI BIOS functions
+ //
+
+ //
+ // Find the PCI info in the config data.
+ //
+ HalpLastPciBus = 0;
+ MatchKey = 0;
+ while ((ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ AdapterClass, MultiFunctionAdapter, &MatchKey)) != NULL) {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"PCI")) {
+
+ Descriptor = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+
+ PCIRegInfo = (PPCI_REGISTRY_INFO)&Descriptor->PartialDescriptors[1];
+
+ HalpLastPciBus = PCIRegInfo->NoBuses - 1;
+
+ break;
+ }
+
+ MatchKey++;
+ }
+
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ State.Eax = (HalpVideoBus << 8) |
+ (HalpVideoDevice << 3) |
+ HalpVideoFunction;
+
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+
+ if (x86BiosInitializeAdapter(0xc0000, &State, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ HalpEnableInt10Calls = TRUE;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+#endif
+
+ return;
+}
+
+
+//
+// This code came from ..\..\x86new\x86bios.c
+//
+#define LOW_MEMORY_SIZE 0x800
+extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+extern ULONG x86BiosScratchMemory;
+extern ULONG x86BiosIoMemory;
+extern ULONG x86BiosIoSpace;
+
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(HalpRomBase + Offset);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+
+ // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
+ return (PVOID)NULL;
+}
+
+
+VOID HalpCopyROMs(VOID)
+{
+ULONG i;
+PUCHAR ROM_Shadow;
+
+ if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
+ HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
+ for (i=0; i<ROM_Length; i++) {
+ *ROM_Shadow++ = ROM_Buffer[i];
+ }
+ }
+}
+
+
+/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
+
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space and the
+// base address of I/O memory space.
+//
+
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+//
+// Hardware Configuration Mechanism #1 emulation.
+//
+// The eagle does not distinguish between CF8 and CFC on reads.
+// At least one BIOS we know of writes/reads CF8 to see if HW
+// mechanism 1 is implemented.
+//
+ULONG x86CF8Shadow;
+
+//
+// Hardware Configuration Mechanism #2 emulation.
+//
+static struct {
+ UCHAR CSE;
+ UCHAR Forward;
+} x86ConfigMechanism2 = { 0, 0};
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Convert mechanism #2 config accesses to mechanism #1.
+ //
+ if (((PortNumber & 0xF000) == 0xC000) &&
+ ((x86ConfigMechanism2.CSE & 0xF0) != 0)) {
+
+ WRITE_REGISTER_ULONG(x86BiosIoSpace + 0xCF8,
+ (1 << 31) | // Enable
+ (x86ConfigMechanism2.Forward << 16) | // Bus
+ ((((PortNumber & 0x0F00) >> 8) + 11) << 11) | // Dev
+ (((x86ConfigMechanism2.CSE & 0x0E) >> 1) << 8) | // Function
+ (PortNumber & 0x00FC) // Register
+ );
+
+ PortNumber = 0xCFC + (PortNumber & 3); // convert to config data port
+ // and let code below do the rest
+ }
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ if (DataType == BYTE_DATA) {
+ //
+ // Emulate config mechanism #2
+ //
+ if (PortNumber == 0xCF8) {
+ Result = x86ConfigMechanism2.CSE;
+ } else if (PortNumber == 0xCFA) {
+ Result = x86ConfigMechanism2.Forward;
+ } else {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+ }
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ //
+ // Watch out for reads from CF8, the eagle will generate a config
+ // cycle rather than returning the contents of the CONFIG_ADDR reg.
+ //
+ if (PortNumber == 0xCF8) {
+
+ Result = x86CF8Shadow;
+
+ } else {
+
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Convert mechanism #2 config accesses to mechanism #1.
+ //
+ if (((PortNumber & 0xF000) == 0xC000) &&
+ ((x86ConfigMechanism2.CSE & 0xF0) != 0)) {
+
+ WRITE_REGISTER_ULONG(x86BiosIoSpace + 0xCF8,
+ (1 << 31) | // Enable
+ (x86ConfigMechanism2.Forward << 16) | // Bus
+ ((((PortNumber & 0x0F00) >> 8) + 11) << 11) | // Dev
+ (((x86ConfigMechanism2.CSE & 0x0E) >> 1) << 8) | // Function
+ (PortNumber & 0x00FC) // Register
+ );
+
+ PortNumber = 0xCFC + (PortNumber & 3); // convert to config data port
+ // and let code below do the rest
+ }
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ if (DataType == BYTE_DATA) {
+ //
+ // Emulate config mechanism #2
+ //
+ if (PortNumber == 0xCF8) {
+ x86ConfigMechanism2.CSE = (UCHAR)Value;
+ } else if (PortNumber == 0xCFA) {
+ x86ConfigMechanism2.Forward = (UCHAR)Value;
+ } else {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+ }
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+
+ //
+ // Shadow writes to CF8.
+ //
+ if (PortNumber == 0xCF8) {
+ x86CF8Shadow = Value;
+ }
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
diff --git a/private/ntos/nthals/haleagle/sources b/private/ntos/nthals/haleagle/sources
new file mode 100644
index 000000000..858f3bce6
--- /dev/null
+++ b/private/ntos/nthals/haleagle/sources
@@ -0,0 +1,97 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ Motorola Eagle based systems.
+
+
+
+Author:
+
+ Bill Jones - 12/15/94
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haleagle
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+!IF $(PPC)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_HALNVR_
+
+INCLUDES=..\x86new;..\..\inc;
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\fwnvr.c \
+ ppc\mk48time.c \
+ ppc\pxbeep.c \
+ ppc\pxbusdat.c \
+ ppc\pxcache.s \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxclock.c \
+ ppc\pxdat.c \
+ ppc\pxdisp.c \
+ ppc\pxds1385.c \
+ ppc\pxenviro.c \
+ ppc\pxflshbf.s \
+ ppc\pxflshio.c \
+ ppc\pxhwsup.c \
+ ppc\pxidle.c \
+ ppc\pxinfo.c \
+ ppc\pxinithl.c \
+ ppc\pxintsup.s \
+ ppc\pxirql.c \
+ ppc\pxisabus.c \
+ ppc\pxl2.s \
+ ppc\pxmapio.c \
+ ppc\pxmemctl.c \
+ ppc\pxmisc.s \
+ ppc\pxpcibrd.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxpcisup.c \
+ ppc\pxport.c \
+ ppc\pxpower.s \
+ ppc\pxproc.c \
+ ppc\pxprof.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxsiosup.c \
+ ppc\pxstall.s \
+ ppc\pxsysbus.c \
+ ppc\pxsysint.c \
+ ppc\pxsystyp.c \
+ ppc\pxtime.c \
+ ppc\pxusage.c \
+ ppc\x86bios.c \
+ ppc\ctrlops.c \
+ ppc\sysbios.c \
+ ppc\pcibios.c
+
+DLLDEF=obj\*\hal.def
+
diff --git a/private/ntos/nthals/haleb164/alpha/28f008sa.c b/private/ntos/nthals/haleb164/alpha/28f008sa.c
new file mode 100644
index 000000000..2865a2061
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/28f008sa.c
@@ -0,0 +1 @@
+#include "../halalpha/28f008sa.c"
diff --git a/private/ntos/nthals/haleb164/alpha/29f040.c b/private/ntos/nthals/haleb164/alpha/29f040.c
new file mode 100644
index 000000000..2c2b423af
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/29f040.c
@@ -0,0 +1 @@
+#include "../halalpha/29f040.c"
diff --git a/private/ntos/nthals/haleb164/alpha/adjust.c b/private/ntos/nthals/haleb164/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/allstart.c b/private/ntos/nthals/haleb164/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/apecs.c b/private/ntos/nthals/haleb164/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/apecserr.c b/private/ntos/nthals/haleb164/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/apecsio.s b/private/ntos/nthals/haleb164/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/bios.c b/private/ntos/nthals/haleb164/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/busdata.c b/private/ntos/nthals/haleb164/alpha/busdata.c
new file mode 100644
index 000000000..cc2a153c1
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/busdata.c
@@ -0,0 +1,125 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/haleb164/alpha/cache.c b/private/ntos/nthals/haleb164/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/cia.c b/private/ntos/nthals/haleb164/alpha/cia.c
new file mode 100644
index 000000000..7948bfe16
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/cia.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cia.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ciaaddr.c b/private/ntos/nthals/haleb164/alpha/ciaaddr.c
new file mode 100644
index 000000000..b85818ac0
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ciaaddr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaaddr.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ciaerr.c b/private/ntos/nthals/haleb164/alpha/ciaerr.c
new file mode 100644
index 000000000..bfb9efc93
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ciaerr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaerr.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ciaio.s b/private/ntos/nthals/haleb164/alpha/ciaio.s
new file mode 100644
index 000000000..16202a7e1
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ciaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaio.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ciamapio.c b/private/ntos/nthals/haleb164/alpha/ciamapio.c
new file mode 100644
index 000000000..3e9f7a9c1
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ciamapio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciamapio.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/cmos8k.c b/private/ntos/nthals/haleb164/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/devintr.s b/private/ntos/nthals/haleb164/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/eb164.h b/private/ntos/nthals/haleb164/alpha/eb164.h
new file mode 100644
index 000000000..52a434698
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/eb164.h
@@ -0,0 +1,133 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ eb164.h
+
+Abstract:
+
+ This file contains definitions specific to the EB164 platform.
+
+Author:
+
+ Joe Notarangelo 06-Sep-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _EB164H_
+#define _EB164H_
+
+//
+// Include definitions for the components that make up EB164.
+//
+
+#include "axp21164.h" // 21164 (EV5) microprocessor definitions
+#include "cia.h" // CIA controller definitions
+
+//
+// define the supported system types
+//
+
+typedef enum _PLATFORM_TYPES {
+ UnknownPlatform = 0,
+ EB66 = 1,
+ EB66Plus = 2,
+ EB64Plus = 3,
+ AlphaPC64 = 4,
+ EB164 = 5,
+ AlphaPC164 = 6
+} PLATFORM_TYPES, *PPLATFORM_TYPES;
+//
+// Define number of PCI, ISA, and combo slots
+//
+
+#define NUMBER_ISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 4
+#define NUMBER_COMBO_SLOTS 1
+
+//
+// PCI bus address values:
+//
+
+#define PCI_MAX_LOCAL_DEVICE (PCI_MAX_DEVICES - 1)
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+#define PCI_MAX_INTERRUPT (0x11)
+
+//
+// Define numbers and names of cpus.
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0)
+
+//
+// Define default processor frequency.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (250)
+
+//
+// Define EB164-specific routines that are really macros for performance.
+//
+
+#define HalpAcknowledgeEisaInterrupt(x) INTERRUPT_ACKNOWLEDGE(x)
+
+//
+// Define the per-processor data structures allocated in the PCR.
+//
+
+typedef struct _EB164_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+ } EB164_PCR, *PEB164_PCR;
+
+#define HAL_PCR ( (PEB164_PCR)(&(PCR->HalReserved)) )
+
+//
+// Define the locations of the interrupt mask registers.
+//
+
+#define INTERRUPT_MASK0_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + 0x804)
+#define INTERRUPT_MASK1_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + 0x805)
+#define INTERRUPT_MASK2_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + 0x806)
+
+//
+// Define the location of the flash environment block
+//
+
+#define NVRAM_ENVIRONMENT_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_MEMORY_PHYSICAL) + 0xf0000)
+
+#define CIA_MCR_QVA ((ULONG)HAL_MAKE_QVA(CIA_MEMORY_CSRS_PHYSICAL))
+
+//
+// Define EB164 SIO dispatch
+//
+BOOLEAN
+HalpEB164SioDispatch(
+ PKINTERRUPT Interrupt,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+typedef BOOLEAN (*PEB164_SECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT Interrupt,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+#endif //_EB164H_
+
diff --git a/private/ntos/nthals/haleb164/alpha/eb164err.c b/private/ntos/nthals/haleb164/alpha/eb164err.c
new file mode 100644
index 000000000..d305a0704
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/eb164err.c
@@ -0,0 +1,122 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ eb164err.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the EB164 platform.
+
+Author:
+
+ Joe Notarangelo 06-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eb164.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+VOID
+HalpErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for an EB164 machine check interrupt
+ The function calls HalpCiaReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // Report the error and crash the system
+ //
+
+ HalpCiaReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+
+
+ return; // never
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ //
+ // All machine check handling is determined by the CIA
+ //
+
+ return(HalpCiaMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ));
+}
diff --git a/private/ntos/nthals/haleb164/alpha/eb164io.s b/private/ntos/nthals/haleb164/alpha/eb164io.s
new file mode 100644
index 000000000..74e586ff2
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/eb164io.s
@@ -0,0 +1,139 @@
+
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ eb164io.s
+
+Abstract:
+
+ This module implements flashrom I/O access routines for EB164.
+
+Author:
+
+ Chao Chen 14-Sep-1994
+ Joe Notarangelo 14-Sep-1994
+ Jeff Wiedermeier 14-Sep-1994
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "halalpha.h"
+
+#define EB164_FLASH_BASE -0x37a9 // negative of 0xc857
+#define CIA_SPARSE_IO_SVA -0x37a8 // negative of 0xc858
+#define IO_BIT_SHIFT 5
+
+
+//++
+//
+// UCHAR
+// EB164_READ_FLASH_BYTE(
+// ULONG Offset
+// )
+//
+// Routine Description:
+//
+// Read a byte of data from the flash rom at the specified offset.
+//
+// Arguments:
+//
+// Offset (a0) - Supplies a byte offset from the base of the flash rom.
+//
+// Return Value:
+//
+// (v0) Returns the byte of data read from the flash rom.
+//
+//--
+
+ LEAF_ENTRY(EB164_READ_FLASH_BYTE)
+
+ and a0, 3, t2 // save byte lane to read
+
+ srl a0, 19,t1 // get bank select to lsb
+ and t1, 1, t1 // mask it
+ lda t3, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t3, 28, t3 // 0xffff fc85 8000 0000
+ lda t4, 0x800(zero) // get port number for bank sel
+ sll t4, IO_BIT_SHIFT, t4 // put it in place
+ or t3, t4, t3 // and merge it
+ stl t1, 0(t3) // write the bank select
+ mb
+
+ lda t0, EB164_FLASH_BASE(zero) // 0xffff ffff ffff c857
+ sll t0, 4, t0 // 0xffff ffff fffc 8570
+ lda t0, 0xf(t0) // 0xffff ffff fffc 857f
+ sll t0, 24, t0 // 0xffff fc85 7f00 0000
+
+ sll a0, IO_BIT_SHIFT, a0 // shift offset to sparse space
+ bis t0, a0, t0 // merge offset and base
+
+ ldl v0, 0(t0) // read flash rom
+ extbl v0, t2, v0 // extract byte from appropriate lane
+
+ ret zero, (ra) // return
+
+ .end EB164_READ_FLASH_BYTE
+
+//++
+//
+// VOID
+// EB164_WRITE_FLASH_BYTE(
+// ULONG Offset,
+// UCHAR Data
+// )
+//
+// Routine Description:
+//
+// Write a byte of data to the flash rom at the specified offset.
+//
+// Arguments:
+//
+// Offset (a0) - Supplies a byte offset from the base of the flash rom.
+//
+// Data (a1) - Supplies the data to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EB164_WRITE_FLASH_BYTE)
+
+ and a0, 3, t2 // save byte lane to read
+
+ srl a0, 19,t1 // get bank select to lsb
+ and t1, 1, t1 // mask it
+ lda t3, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t3, 28, t3 // 0xffff fc85 8000 0000
+ lda t4, 0x800(zero) // get port number for bank sel
+ sll t4, IO_BIT_SHIFT, t4 // put it in place
+ or t3, t4, t3 // and merge it
+ stl t1, 0(t3) // write the bank select
+ mb
+
+ lda t0, EB164_FLASH_BASE(zero) // 0xffff ffff ffff c857
+ sll t0, 4, t0 // 0xffff ffff fffc 8570
+ lda t0, 0xf(t0) // 0xffff ffff fffc 857f
+ sll t0, 24, t0 // 0xffff fc85 7f00 0000
+
+ sll a0, IO_BIT_SHIFT, a0 // shift offset to sparse space
+ bis t0, a0, t0 // merge offset and base
+
+ insbl a1, t2, a1 // put data into correct lane
+ stl a1, 0(t0) // write the flash rom
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EB164_WRITE_FLASH_BYTE
+
diff --git a/private/ntos/nthals/haleb164/alpha/ebinitnt.c b/private/ntos/nthals/haleb164/alpha/ebinitnt.c
new file mode 100644
index 000000000..c7ba7e0fc
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ebinitnt.c
@@ -0,0 +1,677 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an EB164 system.
+
+Author:
+
+ Joe Notarangelo 06-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "eb164.h"
+#include "iousage.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// PLATFORM_TYPE enumeration so that the HAL can be used on
+// similar systems with run-time differences
+//
+PLATFORM_TYPES PlatformType = UnknownPlatform;
+
+
+//
+// Irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - interval clock
+// irql 6 - not used
+// irql 7 - error, mchk, nmi, performance counters
+//
+//
+
+//
+// The hardware interrupt pins are used as follows for EB164
+//
+// IRQ0 = CIA_INT
+// IRQ1 = SYS_INT (PCI and ESC interrupts)
+// IRQ2 = Interval Clock
+// IRQ3 = Error Interrupts
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// External references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Function prototypes.
+//
+
+BOOLEAN
+HalpInitializeEB164Interrupts (
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpErrorInterrupt(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an EB164 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern ULONG HalpCiaErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+ extern ULONG HalpHaltInterrupt();
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize EB164 interrupts.
+ //
+
+ HalpInitializeEB164Interrupts();
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = (PKINTERRUPT_ROUTINE)HalpCiaErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] = (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = (PKINTERRUPT_ROUTINE)HalpErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_CRD_VECTOR] = (PKINTERRUPT_ROUTINE)Halp21164CorrectedErrorInterrupt;
+
+ HalpStart21164Interrupts();
+
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+ CIA_REVISION CiaRevision; // kmc - used to figure out if this is a PC164
+
+ //
+ // Since we have a flash device mapped in PCI memory space, but its
+ // HAL driver is pretending to be a cmos8k driver - override the
+ // HalpCMOSRamBase value set in HalpMapIoSpace (ciamapio.c) with the
+ // correct QVA to reach the environment block in the flash through
+ // the SIO.
+ //
+ HalpCMOSRamBase = (PVOID)NVRAM_ENVIRONMENT_QVA;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Determine the system type, if there's a REV 3 CIA
+ // then it's an AlphaPC164, otherwiser it's an EB164
+ //
+ CiaRevision.all =
+ READ_CIA_REGISTER(&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision);
+
+ PlatformType = EB164;
+ if (CiaRevision.CiaRev == CIA_REVISION_3) {
+ PlatformType = AlphaPC164;
+ }
+
+#ifdef HALDBG
+ DbgPrint("LOOK AT THIS ONE\r\n");
+ DumpCia(CiaGeneralRegisters |
+ CiaErrorRegisters |
+ CiaScatterGatherRegisters);
+#endif
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the PCI parity checking.
+ //
+
+ PciParityChecking = (BOOLEAN)(HalDisablePCIParityChecking == 0);
+
+ HalpInitializeCiaMachineChecks(ReportCorrectables = TRUE,
+ PciParityChecking);
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to EB164 and the call should be
+// ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(CIA_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "eb164";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV5_UNCORRECTABLE processorFrame;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
+
+//
+//jnfix - this variable is needed because the clock interrupt handler
+// - in intsup.s was made to be familiar with ev4prof.c, unfortunate
+// - since we don't use ev4prof.c, so for now this is a hack, later
+// - we will either fix intsup.s or create a new intsup.s that does
+// - not have this hack
+//
+
+ULONG HalpNumberOfTicksReload;
+
diff --git a/private/ntos/nthals/haleb164/alpha/ebintsup.c b/private/ntos/nthals/haleb164/alpha/ebintsup.c
new file mode 100644
index 000000000..2637ac814
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ebintsup.c
@@ -0,0 +1,626 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for EB164 systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Chao Chen (DEC) 06-Sept-1994
+ Adapted from Avanti module for EB164.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "eb164.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+
+extern PLATFORM_TYPES PlatformType;
+//
+// Declare the interrupt masks.
+//
+
+UCHAR IntMask0, IntMask1, IntMask2;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following functions handle the PCI interrupts.
+//
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitializeEB164Interrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for ISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the ISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the ISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ switch (PlatformType) {
+ case EB164:
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB164PCIPinToLineTable;
+ break;
+ case AlphaPC164:
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB164PCIPinToLineTable;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize the SIO's PICs for ISA interrupts.
+ //
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB164 comes from a Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the EB164 PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Clear all interrupt masks.
+ // Enable the SIO interrupt in the mask.
+ //
+
+ IntMask0 = 0x10;
+ IntMask1 = 0x00;
+ IntMask2 = 0x00;
+
+ //
+ // Disable interrupts except for SIO.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA, ~IntMask0);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA, ~IntMask1);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA, ~IntMask2);
+
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ if (Vector >= 0 && Vector <= 7) {
+
+ IntMask0 &= (UCHAR)~(1 << Vector);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA, ~IntMask0);
+
+ } else if (Vector >= 8 && Vector <= 0xf) {
+
+ IntMask1 &= (UCHAR)~(1 << (Vector - 8));
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA, ~IntMask1);
+
+ } else if (Vector == 0x10) {
+
+ IntMask2 = 0x00;
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA, ~IntMask2);
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: bad vector!\n");
+#endif
+
+ }
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for EB164 PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to one,
+ // to ensable that PCI interrupt.
+ //
+
+ if (Vector >= 0 && Vector <= 7) {
+
+ IntMask0 |= (UCHAR) (1 << Vector);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA, ~IntMask0);
+
+ } else if (Vector >= 8 && Vector <= 0xf) {
+
+ IntMask1 |= (UCHAR) (1 << (Vector - 8));
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA, ~IntMask1);
+
+ } else if (Vector == 0x10) {
+
+ IntMask2 = 0x01;
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA, ~IntMask2);
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpEnablePciInterrupt: bad vector!\n");
+#endif
+
+ }
+}
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ ULONG IdtIndex;
+ ULONG IntNumber;
+ PKINTERRUPT InterruptObject;
+ UCHAR PCIVector;
+
+ //
+ // Read in the 1st interrupt register.
+ //
+
+ PCIVector = READ_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA) & IntMask0;
+
+ //
+ // Did ISA interrupt occur?
+ //
+
+ if (PCIVector & 0x10) {
+
+ //
+ // ISA interrupt. Call HalpSioDispatch.
+ //
+
+ return ( HalpEB164SioDispatch( Interrupt, NULL, TrapFrame ) );
+
+
+ }
+
+ //
+ // Which PCI interrupt occurred?
+ //
+
+ IdtIndex = PCI_MAX_INTERRUPT + 1;
+
+ if (PCIVector) {
+
+ for (IntNumber = 0; IntNumber < 8; IntNumber++) {
+
+ if (PCIVector & 0x01) {
+ IdtIndex = IntNumber;
+ break;
+ } else {
+ PCIVector = PCIVector >> 1;
+ }
+
+ }
+
+ } else {
+
+ PCIVector = READ_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA) & IntMask1;
+
+ if (PCIVector) {
+
+ for (IntNumber = 0; IntNumber < 8; IntNumber++) {
+
+ if (PCIVector & 0x01) {
+ IdtIndex = IntNumber + 8;
+ break;
+ } else {
+ PCIVector = PCIVector >> 1;
+ }
+
+ }
+
+ } else {
+
+ PCIVector = READ_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA) & IntMask2;
+
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PCIVector & 0x01) {
+ IdtIndex = IntNumber + 16;
+ break;
+ } else {
+ PCIVector = PCIVector >> 1;
+ }
+ }
+ }
+
+ }
+
+ //
+ // If no PCI interrupt is enabled and asserted then this is a passive
+ // release.
+ //
+
+ if( IdtIndex > PCI_MAX_INTERRUPT ){
+
+#if HALDBG
+
+ DbgPrint( "HalpDeviceDispatch: PCI Passive Release.\n" );
+
+#endif //HALDBG
+
+ return FALSE;
+
+ }
+
+ IdtIndex += PCI_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ return( ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame) );
+
+}
diff --git a/private/ntos/nthals/haleb164/alpha/ebsgdma.c b/private/ntos/nthals/haleb164/alpha/ebsgdma.c
new file mode 100644
index 000000000..e2d35353d
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ebsgdma.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
diff --git a/private/ntos/nthals/haleb164/alpha/ebsysint.c b/private/ntos/nthals/haleb164/alpha/ebsysint.c
new file mode 100644
index 000000000..a597a13b9
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ebsysint.c
@@ -0,0 +1,425 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ebsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the EB164 system.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eb164.h"
+
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnablePciInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus ISA_VECTORS.
+ // N.B.: this encoding technique uses the notion of defining a
+ // base interrupt vector in the space defined by the constant,
+ // ISA_VECTORS, which may or may not differ from EISA_VECTORS or
+ // PCI_VECTORS.
+ //
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR
+ //
+ // N.B. The BusInterruptLevel is one-based while the vectors
+ // themselves are zero-based. The BusInterruptLevel must be
+ // one-based because if scsiport sees a zero vector then it
+ // will believe the interrupt is not connected. So in PCI
+ // configuration we have made the interrupt vector correspond
+ // to the slot and interrupt pin.
+ //
+
+ return( (BusInterruptLevel - 1) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on EB164 systems.
+ //
+
+#if defined(HALDBG)
+
+ DbgPrint("EBSYSINT: InterfaceType (%x) not supported on EB164\n",
+ InterfaceType);
+
+#endif
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an EB164 because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/haleb164/alpha/eisasup.c b/private/ntos/nthals/haleb164/alpha/eisasup.c
new file mode 100644
index 000000000..1b52e85e7
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/eisasup.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
diff --git a/private/ntos/nthals/haleb164/alpha/environ.c b/private/ntos/nthals/haleb164/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ev5cache.c b/private/ntos/nthals/haleb164/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ev5int.c b/private/ntos/nthals/haleb164/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ev5ints.s b/private/ntos/nthals/haleb164/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ev5mchk.c b/private/ntos/nthals/haleb164/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ev5mem.s b/private/ntos/nthals/haleb164/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ev5prof.c b/private/ntos/nthals/haleb164/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/flash8k.c b/private/ntos/nthals/haleb164/alpha/flash8k.c
new file mode 100644
index 000000000..4d59fc2f7
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/flash8k.c
@@ -0,0 +1 @@
+#include "../halalpha/flash8k.c"
diff --git a/private/ntos/nthals/haleb164/alpha/flashdrv.c b/private/ntos/nthals/haleb164/alpha/flashdrv.c
new file mode 100644
index 000000000..20b91fc59
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/flashdrv.c
@@ -0,0 +1,23 @@
+#include "halp.h"
+#include "flash8k.h"
+
+//
+// Flash Drivers
+//
+// extern declarations of each known flash driver's Initialize() funcion
+// are needed here for addition into the list of known drivers.
+//
+// FlashDriverList is an array of driver Initialize() functions used to
+// identify the flash device present in the system. The last entry
+// in FlashDriverList must be NULL.
+//
+extern PFLASH_DRIVER I28F008SA_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F080_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F040_Initialize(PUCHAR);
+
+PFLASH_DRIVER (*FlashDriverList[])(PUCHAR) = {
+ I28F008SA_Initialize,
+ Am29F080_Initialize,
+ Am29F040_Initialize,
+ NULL};
+
diff --git a/private/ntos/nthals/haleb164/alpha/fwreturn.c b/private/ntos/nthals/haleb164/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/haldebug.c b/private/ntos/nthals/haleb164/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/halpal.s b/private/ntos/nthals/haleb164/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/haltsup.s b/private/ntos/nthals/haleb164/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/idle.s b/private/ntos/nthals/haleb164/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/info.c b/private/ntos/nthals/haleb164/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/inithal.c b/private/ntos/nthals/haleb164/alpha/inithal.c
new file mode 100644
index 000000000..c9a9e2076
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/inithal.c
@@ -0,0 +1,1059 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inithal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+ 24-Sep-1993 Joe Notarangelo
+ Restructured to make this module platform-independent.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+PERROR_FRAME PUncorrectableError;
+
+//
+// external
+//
+
+ULONG HalDisablePCIParityChecking = 0xffffffff;
+
+//
+// Define HAL spinlocks.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Mask of all of the processors that are currently active.
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// Mapping of the logical processor numbers to the physical processors.
+//
+
+ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ULONG AlreadySet = 0;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ;
+
+ULONGLONG HalpContiguousPhysicalMemorySize;
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ );
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ );
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Perform initialization for the primary processor.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+ if (Phase == 0) {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+ HalpDumpMemoryDescriptors( LoaderBlock );
+
+#endif //HALDBG
+ //
+ // Get the memory Size.
+ //
+ HalpContiguousPhysicalMemorySize = HalpGetContiguousMemorySize(
+ LoaderBlock );
+
+
+ //
+ // Set second level cache size
+ // NOTE: Although we set the PCR with the right cache size this
+ // could be overridden by setting the Registry key
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
+ // \Control\Session Manager
+ // \Memory Management\SecondLevelDataCache.
+ //
+ //
+ //
+ // If the secondlevel cache size is 0 or 512KB then it is
+ // possible that the firmware is an old one. In which case
+ // we determine the cache size here. If the value is anything
+ // other than these then it is a new firmware and probably
+ // reporting the correct cache size hence use this value.
+ //
+
+ if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 ||
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){
+ PCR->SecondLevelCacheSize = HalpGetBCacheSize(
+ HalpContiguousPhysicalMemorySize
+ );
+ } else {
+ PCR->SecondLevelCacheSize =
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize;
+ }
+
+
+ //
+ // Initialize HAL spinlocks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpInitializeCia( LoaderBlock );
+
+ HalpSetTimeIncrement();
+ HalpMapIoSpace();
+ HalpCreateDmaStructures(LoaderBlock);
+ HalpEstablishErrorHandler();
+ HalpInitializeDisplay(LoaderBlock);
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+ HalpInitializeInterrupts();
+ HalpVerifyPrcbVersion();
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+ //
+ // Initialize the logical to physical processor mapping
+ // for the primary processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[0] = HAL_PRIMARY_PROCESSOR;
+
+ return TRUE;
+
+ } else {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpInitializeClockInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Allocate memory for the uncorrectable frame
+ //
+
+ HalpAllocateUncorrectableFrame();
+
+ //
+ // Initialize the Buffer for Uncorrectable Error.
+ //
+
+ HalpInitializeUncorrectableErrorFrame();
+
+ return TRUE;
+
+ }
+ }
+
+ //
+ // Perform necessary processor-specific initialization for
+ // secondary processors. Phase is ignored as this will be called
+ // only once on each secondary processor.
+ //
+
+ HalpMapIoSpace();
+ HalpInitializeInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors |= 1 << Prcb->Number;
+
+#if HALDBG
+
+ DbgPrint( "Secondary %d is alive\n", Prcb->Number );
+
+#endif //HALDBG
+
+ return TRUE;
+}
+
+
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called after the Phase1 Machine Dependent initialization.
+ It must be called only after Phase1 machine dependent initialization.
+ This function allocates the necessary amountof memory for storing the
+ uncorrectable error frame. This function makes a call to a machine
+ dependent function 'HalpGetMachineDependentErrorFrameSizes' for
+ getting the size of the Processor Specific and System Specific error
+ frame size. The machine dependent code will
+ know the size of these frames after the machine depedant Phase1
+ initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG RawProcessorFrameSize;
+ ULONG RawSystemFrameSize;
+ ULONG EntireErrorFrameSize;
+
+ //
+ // First get the machine dependent error frame sizes.
+ //
+ HalpGetMachineDependentErrorFrameSizes(
+ &RawProcessorFrameSize,
+ &RawSystemFrameSize);
+
+ //
+ // Compute the total size of the error frame
+ //
+ EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize +
+ RawSystemFrameSize;
+
+ //
+ // Allocate space to store the error frame.
+ // Not sure if it is OK to use ExAllocatePool at this instant.
+ // We will give this a try if it doesn't work What do we do??!!
+ //
+
+ PUncorrectableError = ExAllocatePool(NonPagedPool,
+ EntireErrorFrameSize);
+ if(PUncorrectableError == NULL) {
+ return;
+ }
+
+ PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize;
+
+ //
+ // if the size is not equal to zero then set the RawInformation pointers
+ // to point to the right place. If not set the pointer to NULL and set
+ // size to 0.
+ //
+
+ //
+ // make Raw processor info to point right after the error frame.
+ //
+ if(RawProcessorFrameSize) {
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ (PVOID)((PUCHAR)PUncorrectableError + sizeof(ERROR_FRAME) );
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ RawProcessorFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ 0;
+ }
+ if(RawSystemFrameSize){
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame.
+ RawProcessorInformation + RawProcessorFrameSize);
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ RawSystemFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ 0;
+ }
+}
+
+
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+)
+/*++
+
+Routine Description:
+
+ Collects the Processor Information and fills in the buffer.
+
+Arguments:
+
+ pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which
+ the processor information will be filled in.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+
+ pProcessorInfo->ProcessorType = PCR->ProcessorType;
+ pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision;
+
+ Prcb = PCR->Prcb;
+ pProcessorInfo->LogicalProcessorNumber = Prcb->Number;
+ pProcessorInfo->PhysicalProcessorNumber =
+ HalpLogicalToPhysicalProcessor[Prcb->Number];
+ return;
+}
+
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ ULONG LogicalNumber;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PhysicalNumber;
+ PKPRCB Prcb;
+
+#if !defined(NT_UP)
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ LogicalNumber = 0;
+ PhysicalNumber = 0;
+ do {
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){
+
+ PhysicalNumber += 1;
+
+ } else {
+
+ //
+ // Check if this processor has already been started.
+ // If it has not then start it now.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){
+
+ RtlZeroMemory( &NextRestartBlock->u.Alpha,
+ sizeof(ALPHA_RESTART_STATE));
+ NextRestartBlock->u.Alpha.IntA0 =
+ ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Alpha.IntSp =
+ ProcessorState->ContextFrame.IntSp;
+ NextRestartBlock->u.Alpha.ReiRestartAddress =
+ (ULONG)ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)LogicalNumber;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Ensure that the logical to physical mapping has been
+ // established for this processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ }
+
+ LogicalNumber += 1;
+ PhysicalNumber += 1;
+ }
+
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+
+ } while (NextRestartBlock != NULL);
+
+#endif // !defined(NT_UP)
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the HAL matches the kernel. If there
+ is a mismatch the HAL bugchecks the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PKPRCB Prcb;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+
+}
+
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PWSTR NameString;
+
+ //
+ // Quick out
+ //
+
+ if (AlreadySet) {
+ return;
+ }
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+ HalDisablePCIParityChecking = Component->Flags.ConsoleOut;
+ AlreadySet = TRUE;
+#if HALDBG
+ DbgPrint("ARC tree sets PCI parity checking to %s\n",
+ HalDisablePCIParityChecking ? "OFF" : "ON");
+#endif
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return (ULONG) ((Count2 - Count1)*(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the processor counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+#if DBG
+ DbgPrint(
+ "Frequency = %d\nMegaHertz = %d\n",
+ HalpClockFrequency,
+ HalpClockMegaHertz
+ );
+#endif
+
+}
+
+
+
+
+#if 0
+VOID
+HalpGatherPerformanceParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
diff --git a/private/ntos/nthals/haleb164/alpha/intsup.s b/private/ntos/nthals/haleb164/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/haleb164/alpha/ioproc.c b/private/ntos/nthals/haleb164/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/iousage.c b/private/ntos/nthals/haleb164/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/machdep.h b/private/ntos/nthals/haleb164/alpha/machdep.h
new file mode 100644
index 000000000..8dec64c29
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include EB164 platform-specific definitions.
+//
+
+#include "eb164.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/haleb164/alpha/memory.c b/private/ntos/nthals/haleb164/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/nvenv.c b/private/ntos/nthals/haleb164/alpha/nvenv.c
new file mode 100644
index 000000000..ba5a5c8f7
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/nvenv.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvenv.c"
diff --git a/private/ntos/nthals/haleb164/alpha/nvram.c b/private/ntos/nthals/haleb164/alpha/nvram.c
new file mode 100644
index 000000000..879c41c68
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/nvram.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvram.c"
diff --git a/private/ntos/nthals/haleb164/alpha/pcibus.c b/private/ntos/nthals/haleb164/alpha/pcibus.c
new file mode 100644
index 000000000..3ce95ed54
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pcibus.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+ Steve Brooks 30-Jun-1994
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+#if HALDBG
+
+ DbgPrint( "PCI Config Access: Bus = %d, Device = %d, Type = %d\n",
+ BusNumber, Slot.u.bits.DeviceNumber, ConfigType );
+
+#endif //HALDBG
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Note that HalpValidPCISlot has already done bounds checking
+ // on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+
+ //
+ // Encoding of the configuration addresses differs between
+ // passes of the CIA. Use the pre-determined global HalpCiaRevision
+ // to decide which encoding to use.
+ //
+
+ if( HalpCiaRevision == CIA_REVISION_1 ){
+
+ //
+ // CIA Pass 1
+ //
+
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+
+ } else {
+
+ //
+ // CIA Pass 2 or later.
+ //
+
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+
+ }
+
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+ } else {
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/haleb164/alpha/pcisio.c b/private/ntos/nthals/haleb164/alpha/pcisio.c
new file mode 100644
index 000000000..43ff9900a
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pcisio.c
@@ -0,0 +1,493 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pic8259.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI SIO
+ programmable interrupt controller.
+
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Import save area for SIO interrupt mask registers.
+//
+
+UCHAR HalpSioInterrupt1Mask;
+UCHAR HalpSioInterrupt2Mask;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+
+VOID
+HalpInitializeSioInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 8259 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ return;
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO bus specified SIO bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2, it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+ }
+
+ }
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO bus specified SIO bus interrupt.
+Arguments:
+
+ Vector - Supplies the vector of the SIO interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalpEB164SioDispatch(
+ PKINTERRUPT Interrupt,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to an interrupt object that
+ describes the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+ TrapFrame - Supplies a pointer to the interrupt trap frame.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR ISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ //ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase);
+ ISAVector = (UCHAR)INTERRUPT_ACKNOWLEDGE(ServiceContext);
+
+
+ if ((ISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return FALSE; // ecrfix - now returns a value
+
+ }
+
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = ISAVector + ISA_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PEB164_SECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (ISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+}
+
+
diff --git a/private/ntos/nthals/haleb164/alpha/pcisup.c b/private/ntos/nthals/haleb164/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/pcrtc.c b/private/ntos/nthals/haleb164/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/pcserial.c b/private/ntos/nthals/haleb164/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/pcspeakr.c b/private/ntos/nthals/haleb164/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/perfcntr.c b/private/ntos/nthals/haleb164/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/haleb164/alpha/pintolin.h b/private/ntos/nthals/haleb164/alpha/pintolin.h
new file mode 100644
index 000000000..80530bcd1
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/pintolin.h
@@ -0,0 +1,182 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+ Chao Chen 6-Sept 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for EB164.
+//
+// EB164 PCI interrupts are mapped to arbitrary interrupt numbers
+// in the table below. The values are a 1-1 map of the bit numbers
+// in the EB164 PCI interrupt register that are connected to PCI
+// devices. N.B.: there are two other interrupts in this register,
+// but they are not connected to I/O devices, so they're not
+// represented in the table.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_MIKASA.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG EB164PCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x03, 0x08, 0x0c, 0x10 }, // Virtual Slot 5 = PCI_AD[16] PCI Slot 2
+ { 0x01, 0x06, 0x0a, 0x0e }, // Virtual Slot 6 = PCI_AD[17] PCI Slot 0
+ { 0x02, 0x07, 0x0b, 0x0f }, // Virtual Slot 7 = PCI_AD[18] PCI Slot 1
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] PCI/ISA Bridge
+ { 0x04, 0x09, 0x0d, 0x11 }, // Virtual Slot 9 = PCI_AD[20] PCI Slot 3
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 11 = PCI_AD[22]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 12 = PCI_AD[23]
+};
+
+ULONG AlphaPC164PCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x03, 0x0a, 0x0e, 0x12 }, // Virtual Slot 5 = PCI_AD[16] PCI Slot 2
+ { 0x01, 0x08, 0x0c, 0x10 }, // Virtual Slot 6 = PCI_AD[17] PCI Slot 0
+ { 0x02, 0x09, 0x0d, 0x11 }, // Virtual Slot 7 = PCI_AD[18] PCI Slot 1
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] PCI/ISA Bridge
+ { 0x04, 0x0b, 0x0f, 0x13 }, // Virtual Slot 9 = PCI_AD[20] PCI Slot 3
+ { 0x07, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] USB
+ { 0x06, 0xff, 0xff, 0xff }, // Virtual Slot 11 = PCI_AD[22] IDE
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 12 = PCI_AD[23]
+};
+
diff --git a/private/ntos/nthals/haleb164/alpha/vga.c b/private/ntos/nthals/haleb164/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/haleb164/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/haleb164/drivesup.c b/private/ntos/nthals/haleb164/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haleb164/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haleb164/hal.rc b/private/ntos/nthals/haleb164/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haleb164/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haleb164/hal.src b/private/ntos/nthals/haleb164/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haleb164/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haleb164/makefile b/private/ntos/nthals/haleb164/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haleb164/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haleb164/makefile.inc b/private/ntos/nthals/haleb164/makefile.inc
new file mode 100644
index 000000000..07b5f7b33
--- /dev/null
+++ b/private/ntos/nthals/haleb164/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ cl /EP hal.src -DALPHA=1 $(C_DEFINES) > obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\haleb164.lib
+ copy $** $@
diff --git a/private/ntos/nthals/haleb164/sources b/private/ntos/nthals/haleb164/sources
new file mode 100644
index 000000000..d969ce3d6
--- /dev/null
+++ b/private/ntos/nthals/haleb164/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haleb164
+TARGETPATH=\nt\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DTAGGED_NVRAM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\28f008sa.c \
+ alpha\29f040.c \
+ alpha\adjust.c \
+ alpha\allstart.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cia.c \
+ alpha\ciaaddr.c \
+ alpha\ciaerr.c \
+ alpha\ciaio.s \
+ alpha\ciamapio.c \
+ alpha\devintr.s \
+ alpha\ev5cache.c \
+ alpha\ev5int.c \
+ alpha\ev5mchk.c \
+ alpha\ev5mem.s \
+ alpha\ev5ints.s \
+ alpha\ev5prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\haltsup.s \
+ alpha\info.s \
+ alpha\idle.s \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\nvenv.c \
+ alpha\nvram.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\pcibus.c \
+ alpha\pcisup.c \
+ alpha\busdata.c \
+ alpha\eb164err.c \
+ alpha\ebinitnt.c \
+ alpha\ebintsup.c \
+ alpha\ebsysint.c \
+ alpha\flash8k.c \
+ alpha\flashdrv.c \
+ alpha\pcisio.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/haleb64p/alpha/28f008sa.c b/private/ntos/nthals/haleb64p/alpha/28f008sa.c
new file mode 100644
index 000000000..2865a2061
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/28f008sa.c
@@ -0,0 +1 @@
+#include "../halalpha/28f008sa.c"
diff --git a/private/ntos/nthals/haleb64p/alpha/29f040.c b/private/ntos/nthals/haleb64p/alpha/29f040.c
new file mode 100644
index 000000000..2c2b423af
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/29f040.c
@@ -0,0 +1 @@
+#include "../halalpha/29f040.c"
diff --git a/private/ntos/nthals/haleb64p/alpha/addrsup.c b/private/ntos/nthals/haleb64p/alpha/addrsup.c
new file mode 100644
index 000000000..a7b3d0eb8
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/addrsup.c
@@ -0,0 +1,595 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the EB64+ system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen (Digital) 30-Jun-1994
+ Added code to check the new PCI Memory MAp address range which is
+ impacted by the EPEC HAXR1.
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "eb64pdef.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the originating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on EB64+ are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+//jnfix - HAE support here
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+ //
+ // IMPORTANT:
+ //
+ // MAX PCI sparse is PCI_MAX_SPARSE_MEMORY_ADDRESS
+ // MAX PCI dense is PCI_MAX_DENSE_MEMORY_ADDRESS
+ //
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ // Note that ISA bus devices can also request this space.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_DENSE_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ if ((PA.QuadPart >= APECS_COMANCHE_BASE_PHYSICAL)
+ &&
+ (PA.QuadPart < APECS_PCI_DENSE_BASE_PHYSICAL)
+ ) {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For EB64+ we have only 2 bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
+
diff --git a/private/ntos/nthals/haleb64p/alpha/adjust.c b/private/ntos/nthals/haleb64p/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/allstart.c b/private/ntos/nthals/haleb64p/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/alphaio.s b/private/ntos/nthals/haleb64p/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/apecs.c b/private/ntos/nthals/haleb64p/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/apecserr.c b/private/ntos/nthals/haleb64p/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/apecsio.s b/private/ntos/nthals/haleb64p/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/bios.c b/private/ntos/nthals/haleb64p/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/busdata.c b/private/ntos/nthals/haleb64p/alpha/busdata.c
new file mode 100644
index 000000000..cc2a153c1
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/busdata.c
@@ -0,0 +1,125 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/haleb64p/alpha/cache.c b/private/ntos/nthals/haleb64p/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/chipset.h b/private/ntos/nthals/haleb64p/alpha/chipset.h
new file mode 100644
index 000000000..0a72ef8cb
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/chipset.h
@@ -0,0 +1 @@
+#include "apecs.h"
diff --git a/private/ntos/nthals/haleb64p/alpha/cmos8k.c b/private/ntos/nthals/haleb64p/alpha/cmos8k.c
new file mode 100644
index 000000000..6253ecab6
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/cmos8k.c
@@ -0,0 +1,5 @@
+#define HalpWriteNVRamBuffer HalpCmos8kWriteNVRamBuffer
+#define HalpReadNVRamBuffer HalpCmos8kReadNVRamBuffer
+#define HalpCopyNVRamBuffer HalpCmos8kCopyNVRamBuffer
+#include "..\..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/eb64pdef.h b/private/ntos/nthals/haleb64p/alpha/eb64pdef.h
new file mode 100644
index 000000000..f34f6e28a
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/eb64pdef.h
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ eb64pdef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ EB64+ and AlphaPC64 modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+ Jeff Wiedemeier [DEC] December 1994
+
+ Adapted for AlphaPC64 from eb64pdef.h
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Added defines so both passes of the EB64Plus modules can be supported.
+
+--*/
+
+#ifndef _EB64PDEF_H_
+#define _EB64PDEF_H_
+
+#include "alpharef.h"
+#include "axp21064.h"
+#include "apecs.h"
+#include "isaaddr.h"
+
+#define NUMBER_ISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 4
+
+// Highest Virtual local PCI Slot is 9 == IDSEL PCI_AD[20]
+
+#define PCI_MAX_LOCAL_DEVICE (PCI_MAX_DEVICES - 1)
+
+// Highest PCI interrupt vector is in ISA Vector Space
+
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+#define ALPHAPC64_INTERRUPT_MASK0_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + 0x804)
+#define ALPHAPC64_INTERRUPT_MASK1_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + 0x805)
+#define ALPHAPC64_INTERRUPT_MASK2_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + 0x806)
+#define ALPHAPC64_SIO_INTERRUPT_MASK 0x10
+
+#define EB64P_INTERRUPT_MASK0_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + 0x26)
+#define EB64P_INTERRUPT_MASK1_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + 0x27)
+#define EB64P_INTERRUPT_MASK2_QVA NULL
+#define EB64P_SIO_INTERRUPT_MASK 0x20
+
+extern PVOID INTERRUPT_MASK0_QVA;
+extern PVOID INTERRUPT_MASK1_QVA;
+extern PVOID INTERRUPT_MASK2_QVA;
+extern ULONG SIO_INTERRUPT_MASK;
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV4 processor.
+//
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+typedef struct _EB64P_PCR {
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} EB64P_PCR, *PEB64P_PCR;
+
+#define HAL_PCR ( (PEB64P_PCR)(&(PCR->HalReserved)) )
+
+#define PCI_SPARSE_IO_BASE_QVA \
+ ((ULONG)(HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL)))
+
+#define PCI_SPARSE_MEMORY_BASE_QVA \
+ ((ULONG)(HAL_MAKE_QVA(APECS_PCI_MEMORY_BASE_PHYSICAL)))
+
+//
+// PCI-E/ISA Bridge chip configuration space base is at physical address
+// 0x1e0000000. The equivalent QVA is:
+// ((0x1e0000000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+// N.B.: The PCI configuration space address is what we're really referring
+// to, here; both symbols are useful.
+//
+
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+
+#define PCI_CONFIGURATION_BASE_QVA ((ULONG)APECS_PCI_CONFIG_BASE_QVA)
+#define PCI_BRIDGE_CONFIGURATION_BASE_QVA ((ULONG)APECS_PCI_CONFIG_BASE_QVA)
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device
+
+#define PCI_ISA_BRIDGE_HEADER_OFFSET_P2 (0x00080000 >> IO_BIT_SHIFT) // AD[18]
+#define PCI_ISA_BRIDGE_HEADER_OFFSET_P1 (0x01000000 >> IO_BIT_SHIFT) // AD[18]
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+//
+// Define primary (and only) CPU on an EB64+ system
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0)
+
+//
+// Define the default processor frequency to be used before the actual
+// processor frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (275)
+
+//
+// Define the location of the flash environment block
+//
+
+#define ALPHAPC64_ENVIRONMENT_QVA \
+ ((ULONG)HAL_MAKE_QVA(APECS_PCI_MEMORY_BASE_PHYSICAL) + 0xf0000)
+
+extern BOOLEAN SystemIsAlphaPC64;
+
+#endif // _EB64PDEF_H_
diff --git a/private/ntos/nthals/haleb64p/alpha/ebenv.c b/private/ntos/nthals/haleb64p/alpha/ebenv.c
new file mode 100644
index 000000000..310daed3e
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebenv.c
@@ -0,0 +1,61 @@
+#include "halp.h"
+#include "arccodes.h"
+
+extern BOOLEAN SystemIsAlphaPC64;
+
+ARC_STATUS
+HalpFlash8kReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpFlash8kWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCmos8kReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCmos8kWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ )
+{
+ if (SystemIsAlphaPC64)
+ return HalpFlash8kReadNVRamBuffer(DataPtr, NvRamPtr, Length);
+
+ return HalpCmos8kReadNVRamBuffer(DataPtr, NvRamPtr, Length);
+}
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ )
+{
+ if (SystemIsAlphaPC64)
+ return HalpFlash8kWriteNVRamBuffer(NvRamPtr, DataPtr, Length);
+
+ return HalpCmos8kWriteNVRamBuffer(NvRamPtr, DataPtr, Length);
+}
+
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ebinitnt.c b/private/ntos/nthals/haleb64p/alpha/ebinitnt.c
new file mode 100644
index 000000000..e47d067a4
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebinitnt.c
@@ -0,0 +1,880 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an EB64+ system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Dick Bissen [DEC] 30-Jun-1994
+
+ Added code to support new PCI memory configuration.
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Added code to support both passes of the EB64Plus modules.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "eb64pdef.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "flash8k.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+//
+//
+BOOLEAN SystemIsAlphaPC64;
+PVOID INTERRUPT_MASK0_QVA;
+PVOID INTERRUPT_MASK1_QVA;
+PVOID INTERRUPT_MASK2_QVA;
+ULONG SIO_INTERRUPT_MASK;
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for EB64+
+//
+// IRQ_H[0] = PIC
+// IRQ_H[1] = Clock
+// IRQ_H[2] = NMI
+// IRQ_H[3] = unused
+// IRQ_H[4] = unused
+// IRQ_H[5] = unused
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// These globals make available the specifics of the Eb64 platform
+// we're running in.
+//
+
+BOOLEAN SioCStep;
+
+//
+// This is the PCI Sparse Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself.
+//
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+ADDRESS_USAGE
+EB64pPCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
+ 0,0
+ }
+};
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpClearInterrupts(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize the PCI/ISA interrupt controller.
+ //
+
+ HalpInitializePCIInterrupts();
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ HalpEnable21064HardwareInterrupt(Irq = 0,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt(Irq = 1,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt(Irq = 2,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for EV4 is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize error handling for APECS.
+ //
+
+ HalpInitializeMachineChecks ( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG PciBridgeHeaderOffset;
+ ULONG SioRevision;
+
+ if ( Phase == 0 ) {
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ HalpFlashDriver = HalpInitializeFlashDriver((PCHAR)ALPHAPC64_ENVIRONMENT_QVA);
+ if (HalpFlashDriver != NULL) {
+ //
+ // The flash device was found, so we must be running on an
+ // AlphaPC64
+ //
+ SystemIsAlphaPC64 = TRUE;
+ HalpCMOSRamBase = (PVOID)ALPHAPC64_ENVIRONMENT_QVA;
+ INTERRUPT_MASK0_QVA = ALPHAPC64_INTERRUPT_MASK0_QVA;
+ INTERRUPT_MASK1_QVA = ALPHAPC64_INTERRUPT_MASK1_QVA;
+ INTERRUPT_MASK2_QVA = ALPHAPC64_INTERRUPT_MASK2_QVA;
+ SIO_INTERRUPT_MASK = ALPHAPC64_SIO_INTERRUPT_MASK;
+ } else {
+ SystemIsAlphaPC64 = FALSE;
+ INTERRUPT_MASK0_QVA = EB64P_INTERRUPT_MASK0_QVA;
+ INTERRUPT_MASK1_QVA = EB64P_INTERRUPT_MASK1_QVA;
+ INTERRUPT_MASK2_QVA = EB64P_INTERRUPT_MASK2_QVA;
+ SIO_INTERRUPT_MASK = EB64P_SIO_INTERRUPT_MASK;
+ }
+
+#ifdef HALDBG
+ DbgPrint("HalpInitializeMachineDependent: SystemIsAlphaPC64 is %x\n",
+ SystemIsAlphaPC64);
+ DbgPrint("HalpInitializeMachineDependent: HalpCMOSRamBase is %x\n",
+ HalpCMOSRamBase);
+ DbgPrint("HalpInitializeMachineDependent: INTERRUPT_MASK0_QVA is %x\n",
+ INTERRUPT_MASK0_QVA);
+ DbgPrint("HalpInitializeMachineDependent: INTERRUPT_MASK1_QVA is %x\n",
+ INTERRUPT_MASK1_QVA);
+ DbgPrint("HalpInitializeMachineDependent: INTERRUPT_MASK2_QVA is %x\n",
+ INTERRUPT_MASK2_QVA);
+ DbgPrint("HalpInitializeMachineDependent: SIO_INTERRUPT_MASK is %x\n",
+ SIO_INTERRUPT_MASK);
+#endif
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish the error handler, to reflect the parity checking
+ //
+
+ HalpEstablishErrorHandler();
+
+ PciBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET_P2;
+
+ SioRevision = READ_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA |
+ PciBridgeHeaderOffset |
+ PCI_REVISION),
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ SioCStep = (SioRevision == 0x3 ? TRUE : FALSE);
+
+#ifdef HALDBG
+ DbgPrint("HalpInitializeMachineDependent: SioCStep is %x\n",SioCStep);
+#endif
+
+ HalpInitializeHAERegisters();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize the profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the EPIC/APECS chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // Set HAXR1 to 0, which means no address extension
+ //
+
+ WRITE_EPIC_REGISTER (&((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0);
+
+ //
+ // We set HAXR2 to MB. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. HAXR2 Not used in address translation
+ // 64K to 16MB VALID. HAXR2 is used in the address translation
+ //
+
+ WRITE_EPIC_REGISTER ( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0);
+
+ //
+ // Report that the apecs mapping to the Io subsystem
+ //
+
+ HalpRegisterAddressUsage (&EB64pPCIMemorySpace);
+
+}
+
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the EPIC/APECS chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0 );
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0 );
+
+ return;
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(APECS_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "eb64p";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV4_UNCORRECTABLE processorFrame;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/haleb64p/alpha/ebintr.s b/private/ntos/nthals/haleb64p/alpha/ebintr.s
new file mode 100644
index 000000000..5c02c3304
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebintr.s
@@ -0,0 +1,75 @@
+// TITLE("PCI/ISA Interrupt Handler")
+//++
+//
+// Copyright (c) 1994 Digital Equipment Corporation
+//
+// Module Name:
+//
+// ebintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for EB64+
+//
+// During Phase 0 initialization, the appropriate platform-dependent handler
+// is connected.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 07-Feb-1994 Eric Rehm
+// Make this module platform-dependent.
+//--
+
+#include "halalpha.h"
+
+ SBTTL("PCI Bus Interrupt Handler")
+//++
+//
+// VOID
+// HalpPCIInterruptHandler
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on the I/O
+// bus. The function is responsible for calling HalpPCIDispatch to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpPCIDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// EISA interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPCIInterruptHandler)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpPCIDispatch // ecrfix - dispatch the interrupt to the dual 8259s.
+
+ ret zero, (ra) // will never get here
+
+ .end HalpPCIInterruptHandler
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ebintsup.c b/private/ntos/nthals/haleb64p/alpha/ebintsup.c
new file mode 100644
index 000000000..645753cf1
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebintsup.c
@@ -0,0 +1,569 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for EB64+ systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "eb64pdef.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Global to control interrupt handling for EB64+
+//
+
+UCHAR IntMask0, IntMask1, IntMask2;
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// Declare the interupt handler for the PCI and ISA bus.
+//
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ ISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = (PVOID)HalpPCIDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, DEVICE_LEVEL, LevelSensitive);
+
+ if (SystemIsAlphaPC64)
+ (PVOID) HalpPCIPinToLineTable = (PVOID) AlphaPC64PCIPinToLineTable;
+ else
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB64PPCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize the SIO Interrupt Controller
+ //
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the PCI and ISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the ISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpPCIDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, PCI_LEVEL, PCI_LEVEL, PCI_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the ISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR PciVector, IntNumber;
+ ULONG PCRInOffset = 0xffff;
+ KPCR *pcr;
+
+ //
+ // Read in the 1st interrupt register.
+ //
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK0_QVA) & IntMask0;
+
+ //
+ // Was it an ISA (SIO) interrupt?
+ //
+ if (PciVector & SIO_INTERRUPT_MASK) {
+ //
+ // ISA interrupt - call HalpSioDispatch().
+ //
+ return HalpSioDispatch();
+ }
+
+ //
+ // Which PCI interrupt was it?
+ //
+ if (PciVector) {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ } else {
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK1_QVA) & IntMask1;
+
+ if (PciVector) {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber + 8;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ } else if (INTERRUPT_MASK2_QVA != NULL) {
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK2_QVA) & IntMask2;
+
+ if (PciVector)
+ PCRInOffset = 0x10;
+ }
+ }
+
+ if (PCRInOffset == 0xffff) {
+ return FALSE;
+ }
+
+ PCRInOffset += PCI_VECTORS;
+ PCRInOffset++;
+ return ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset], TrapFrame);
+}
+
+
+VOID
+HalpDisablePCIInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the PCI bus specified PCI bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector.
+ //
+
+ Vector -= PCI_VECTORS;
+ Vector--;
+
+ //
+ // Clear the corresponding bit in the appropriate interrupt mask
+ // shadow and write it out to the interrupt mask.
+ //
+ if (Vector >= 0 && Vector <= 7) {
+ IntMask0 &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ } else if (Vector >= 8 && Vector <= 0xf) {
+ IntMask1 &= (UCHAR) ~(1 << (Vector - 8));
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ } else if ((Vector == 0x10) && (INTERRUPT_MASK2_QVA != NULL)) {
+ IntMask2 = 0;
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ } else {
+#ifdef HALDBG
+ DbgPrint("HalpDisablePCIInterrupt: bad vector\n");
+#endif // HALDBG
+ }
+}
+
+
+VOID
+HalpEnablePCIInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector.
+ //
+
+ Vector -= PCI_VECTORS;
+ Vector--;
+
+ //
+ // Set the corresponding bit in the appropriate interrupt mask
+ // shadow and write it out to the interrupt mask.
+ //
+ if (Vector >= 0 && Vector <= 7) {
+ IntMask0 |= (UCHAR) (1 << Vector);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ } else if (Vector >= 8 && Vector <= 0xf) {
+ IntMask1 |= (UCHAR) (1 << (Vector - 8));
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ } else if ((Vector == 0x10) && (INTERRUPT_MASK2_QVA != NULL)) {
+ IntMask2 = 1;
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ } else {
+#ifdef HALDBG
+ DbgPrint("HalpEnablePCIInterrupt: bad vector\n");
+#endif // HALDBG
+ }
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Sio machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the PCI device interrupt mask.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Initialize the shadow copies of the interrupt masks to enable only
+ // the SIO interrupt.
+ //
+
+ IntMask0 = (UCHAR)SIO_INTERRUPT_MASK;
+ IntMask1 = 0;
+ IntMask2 = 0;
+
+ //
+ // Write the masks.
+ //
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ if (INTERRUPT_MASK2_QVA != NULL) {
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ }
+}
diff --git a/private/ntos/nthals/haleb64p/alpha/ebmapio.c b/private/ntos/nthals/haleb64p/alpha/ebmapio.c
new file mode 100644
index 000000000..01005960a
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebmapio.c
@@ -0,0 +1,147 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the EB64+ system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eb64pdef.h"
+
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for an EB64+
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( APECS_PCI_IO_BASE_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( APECS_PCI_INTACK_BASE_PHYSICAL );
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/haleb64p/alpha/ebsgdma.c b/private/ntos/nthals/haleb64p/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ebsysint.c b/private/ntos/nthals/haleb64p/alpha/ebsysint.c
new file mode 100644
index 000000000..8efd3a4b2
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ebsysint.c
@@ -0,0 +1,422 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a EV4
+ based system.
+
+ Originally taken from JENSEN hal code.
+
+Author:
+
+ Wim Colgate 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Added code to support EB64+ pass 2 modules.
+
+--*/
+
+#include "halp.h"
+#include "eb64pdef.h"
+#include "axp21064.h"
+
+
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL) {
+ HalpDisablePCIInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( Vector );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( Vector );
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt. It must be latched.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt. PCI interrupts must be LevelSensitve.
+ // (PCI Spec. 2.2.6)
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL &&
+ InterruptMode == LevelSensitive) {
+ HalpEnablePCIInterrupt( Vector );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors (serial or keyboard/mouse) then perform
+ // 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( Vector, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( Vector, Irql );
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = PCI_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR.
+ //
+
+ return((BusInterruptLevel) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported onEB64P systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ This routine performs no function on anEB64P because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/haleb64p/alpha/eisasup.c b/private/ntos/nthals/haleb64p/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/environ.c b/private/ntos/nthals/haleb64p/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ev4cache.c b/private/ntos/nthals/haleb64p/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ev4int.c b/private/ntos/nthals/haleb64p/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ev4ints.s b/private/ntos/nthals/haleb64p/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ev4mchk.c b/private/ntos/nthals/haleb64p/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ev4mem.s b/private/ntos/nthals/haleb64p/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ev4prof.c b/private/ntos/nthals/haleb64p/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/flash8k.c b/private/ntos/nthals/haleb64p/alpha/flash8k.c
new file mode 100644
index 000000000..cfe6f38a2
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/flash8k.c
@@ -0,0 +1,5 @@
+#define HalpWriteNVRamBuffer HalpFlash8kWriteNVRamBuffer
+#define HalpReadNVRamBuffer HalpFlash8kReadNVRamBuffer
+#define HalpCopyNVRamBuffer HalpFlash8kCopyNVRamBuffer
+#include "..\..\halalpha\flash8k.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/flashdrv.c b/private/ntos/nthals/haleb64p/alpha/flashdrv.c
new file mode 100644
index 000000000..20b91fc59
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/flashdrv.c
@@ -0,0 +1,23 @@
+#include "halp.h"
+#include "flash8k.h"
+
+//
+// Flash Drivers
+//
+// extern declarations of each known flash driver's Initialize() funcion
+// are needed here for addition into the list of known drivers.
+//
+// FlashDriverList is an array of driver Initialize() functions used to
+// identify the flash device present in the system. The last entry
+// in FlashDriverList must be NULL.
+//
+extern PFLASH_DRIVER I28F008SA_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F080_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F040_Initialize(PUCHAR);
+
+PFLASH_DRIVER (*FlashDriverList[])(PUCHAR) = {
+ I28F008SA_Initialize,
+ Am29F080_Initialize,
+ Am29F040_Initialize,
+ NULL};
+
diff --git a/private/ntos/nthals/haleb64p/alpha/fwreturn.c b/private/ntos/nthals/haleb64p/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/haldebug.c b/private/ntos/nthals/haleb64p/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/halpal.s b/private/ntos/nthals/haleb64p/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/idle.s b/private/ntos/nthals/haleb64p/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/info.c b/private/ntos/nthals/haleb64p/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/inithal.c b/private/ntos/nthals/haleb64p/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/intsup.s b/private/ntos/nthals/haleb64p/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/ioproc.c b/private/ntos/nthals/haleb64p/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/iousage.c b/private/ntos/nthals/haleb64p/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/machdep.h b/private/ntos/nthals/haleb64p/alpha/machdep.h
new file mode 100644
index 000000000..29dbbeb76
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include platform-specific definitions.
+//
+
+#include "eb64pdef.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/haleb64p/alpha/memory.c b/private/ntos/nthals/haleb64p/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pcibus.c b/private/ntos/nthals/haleb64p/alpha/pcibus.c
new file mode 100644
index 000000000..1aa4f9428
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pcibus.c
@@ -0,0 +1,111 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Added code to support both passes of the EB64Plus modules.
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+//
+// This identifies the APECS revision.
+//
+
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24, which, in APECS
+ // pass 1, are wired to IDSEL pins. In pass 2, the format of a type
+ // 0 cycle is the same as the format of a type 1. Note that
+ // HalpValidPCISlot has already done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if DBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ } else {
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if DBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pcisio.c b/private/ntos/nthals/haleb64p/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pcisup.c b/private/ntos/nthals/haleb64p/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pcrtc.c b/private/ntos/nthals/haleb64p/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pcserial.c b/private/ntos/nthals/haleb64p/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pcspeakr.c b/private/ntos/nthals/haleb64p/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/perfcntr.c b/private/ntos/nthals/haleb64p/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/haleb64p/alpha/pintolin.h b/private/ntos/nthals/haleb64p/alpha/pintolin.h
new file mode 100644
index 000000000..70c9d7983
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/pintolin.h
@@ -0,0 +1,179 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Table.
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen [DEC] 13-Sep-1994
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// On Cabriolet, the interrupt vector is the Interrupt Request Register bit
+// representing the interrupt + 1. The value also represents the interrupt
+// mask register bit since the mask register and the request register have
+// the same format.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+//
+// Interrupt Vector Table Mapping for eb64p
+//
+// eb64p PCI interrupts are mapped to ISA IRQs in the table below.
+//
+// Limit init table to 14 entries, which is MAX_PCI_LOCAL_DEVICES_AVANTI.
+// We won't ever try to set an InterruptLine register of a slot greater
+// than Virtual slot 13 = PCI_AD[24].
+//
+
+ULONG AlphaPC64PCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x3, 0x8, 0xc, 0x10 }, // Virtual Slot 5 = PCI_AD[16] Slot #2
+ { 0x1, 0x6, 0xa, 0xe }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+ { 0x2, 0x7, 0xb, 0xf }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+ { 0x5, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x4, 0x9, 0xd, 0x11 } // Virtual Slot 9 = PCI_AD[20] Slot #3
+};
+
+ULONG EB64PPCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x8, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] SCSI
+ { 0x1, 0x3, 0x5, 0xa }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+ { 0x2, 0x4, 0x9, 0xb }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+ { 0x6, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x7, 0xff, 0xff, 0xff } // Virtual Slot 9 = PCI_AD[20] Tulip
+};
diff --git a/private/ntos/nthals/haleb64p/alpha/vga.c b/private/ntos/nthals/haleb64p/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/haleb64p/drivesup.c b/private/ntos/nthals/haleb64p/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haleb64p/hal.rc b/private/ntos/nthals/haleb64p/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haleb64p/hal.src b/private/ntos/nthals/haleb64p/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haleb64p/makefile b/private/ntos/nthals/haleb64p/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haleb64p/makefile.inc b/private/ntos/nthals/haleb64p/makefile.inc
new file mode 100644
index 000000000..98c1275cf
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ cl /EP hal.src -DALPHA=1 $(C_DEFINES) > obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\haleb64p.lib
+ copy $** $@
diff --git a/private/ntos/nthals/haleb64p/sources b/private/ntos/nthals/haleb64p/sources
new file mode 100644
index 000000000..e345aa0d7
--- /dev/null
+++ b/private/ntos/nthals/haleb64p/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haleb64p
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DAPECS
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\28f008sa.c \
+ alpha\29f040.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\apecs.c \
+ alpha\apecserr.c \
+ alpha\apecsio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cmos8k.c \
+ alpha\ebenv.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mchk.c \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\flash8k.c \
+ alpha\flashdrv.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\ebinitnt.c \
+ alpha\ebintsup.c \
+ alpha\ebmapio.c \
+ alpha\ebsysint.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/haleb66/alpha/28f008sa.c b/private/ntos/nthals/haleb66/alpha/28f008sa.c
new file mode 100644
index 000000000..2865a2061
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/28f008sa.c
@@ -0,0 +1 @@
+#include "../halalpha/28f008sa.c"
diff --git a/private/ntos/nthals/haleb66/alpha/29f040.c b/private/ntos/nthals/haleb66/alpha/29f040.c
new file mode 100644
index 000000000..2c2b423af
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/29f040.c
@@ -0,0 +1 @@
+#include "../halalpha/29f040.c"
diff --git a/private/ntos/nthals/haleb66/alpha/addrsup.c b/private/ntos/nthals/haleb66/alpha/addrsup.c
new file mode 100644
index 000000000..a3db00941
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/addrsup.c
@@ -0,0 +1,636 @@
+/*++
+
+Copyright (c) 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the EB66 system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "eb66def.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+#ifndef AXP_FIRMWARE
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+#endif
+
+#ifdef AXP_FIRMWARE
+//
+// Place the appropriate functions in the discardable text section.
+//
+
+//
+// Local function prototypes
+//
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ );
+
+#pragma alloc_text(DISTEXT, HalpTranslateSystemBusAddress)
+#pragma alloc_text(DISTEXT, HalCreateQva)
+#pragma alloc_text(DISTEXT, HalDereferenceQva)
+
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on EB66 are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+//jnfix - HAE support here
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // IMPORTANT: For now we have set HAE set to zero.
+ //
+ // MAX PCI sparse memory for us is PCI_MAX_SPARSE_MEMORY_ADDRESS=128MB-1
+ // MAX PCI dense memory for us is PCI_MAX_DENSE_MEMORY_ADDRESS=2.5GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = LCA4_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciIoPhysical();
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI sparse memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = LCA4_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciIoPhysical();
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Dense space is not supported on Pass 1 LCA4s.
+ //
+
+ if( HalpLca4Revision() == Lca4Pass1 ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return FALSE;
+
+ }
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciDensePhysical();
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ //
+ // If the physical address is not in dense space then perform the
+ // QVA shuffle.
+ //
+ // N.B. - Dense space is not supported for Lca4Pass1.
+ //
+
+ if( (HalpLca4Revision() == Lca4Pass1) ||
+ (PA.QuadPart < (LONGLONG)HalpLca4PciDensePhysical()) ){
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For EB66 we have only 2 bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/haleb66/alpha/adjust.c b/private/ntos/nthals/haleb66/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/allstart.c b/private/ntos/nthals/haleb66/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/alphaio.s b/private/ntos/nthals/haleb66/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/bios.c b/private/ntos/nthals/haleb66/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/busdata.c b/private/ntos/nthals/haleb66/alpha/busdata.c
new file mode 100644
index 000000000..020194bb6
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/busdata.c
@@ -0,0 +1,127 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eb66def.h"
+
+//
+// External Function Prototypes
+//
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/haleb66/alpha/cache.c b/private/ntos/nthals/haleb66/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/chipset.h b/private/ntos/nthals/haleb66/alpha/chipset.h
new file mode 100644
index 000000000..b5d5b44c3
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/chipset.h
@@ -0,0 +1 @@
+#include "lca4.h"
diff --git a/private/ntos/nthals/haleb66/alpha/cmos8k.c b/private/ntos/nthals/haleb66/alpha/cmos8k.c
new file mode 100644
index 000000000..6253ecab6
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/cmos8k.c
@@ -0,0 +1,5 @@
+#define HalpWriteNVRamBuffer HalpCmos8kWriteNVRamBuffer
+#define HalpReadNVRamBuffer HalpCmos8kReadNVRamBuffer
+#define HalpCopyNVRamBuffer HalpCmos8kCopyNVRamBuffer
+#include "..\..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/eb66def.h b/private/ntos/nthals/haleb66/alpha/eb66def.h
new file mode 100644
index 000000000..58b623bb2
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/eb66def.h
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ eb66def.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ EB66p modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+ Ken Curewitz [DEC] December 1994
+
+ Adapted for EB66p from eb66def.h
+
+--*/
+
+#ifndef _EB66PDEF_
+#define _EB66PDEF_
+
+#include "alpharef.h"
+#include "lca4.h"
+#include "isaaddr.h"
+
+#define NUMBER_ISA_SLOTS 4
+#define NUMBER_PCI_SLOTS 4
+
+//
+// QVA definitions for base addresses on the PCI
+//
+#define PCI_SPARSE_IO_BASE_QVA \
+ ((ULONG)(HAL_MAKE_QVA(LCA4_PASS2_PCI_IO_BASE_PHYSICAL)))
+
+#define PCI_SPARSE_MEMORY_BASE_QVA \
+ ((ULONG)(HAL_MAKE_QVA(LCA4_PCI_MEMORY_BASE_PHYSICAL)))
+
+//
+// Highest Virtual local PCI Slot
+//
+// On the EB66 we can only probe for 13 devices
+//
+#define PCI_MAX_LOCAL_DEVICE 13
+
+//
+// Highest PCI interrupt vector is in PCI vector space
+//
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+#define EB66P_INTERRUPT_MASK0_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(LCA4_PASS2_PCI_IO_BASE_PHYSICAL) + 0x804)
+#define EB66P_INTERRUPT_MASK1_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(LCA4_PASS2_PCI_IO_BASE_PHYSICAL) + 0x805)
+#define EB66P_INTERRUPT_MASK2_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(LCA4_PASS2_PCI_IO_BASE_PHYSICAL) + 0x806)
+#define EB66P_SIO_INTERRUPT_MASK 0x10
+
+#define EB66_INTERRUPT_MASK0_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(LCA4_PASS2_PCI_IO_BASE_PHYSICAL) + 0x26)
+#define EB66_INTERRUPT_MASK1_QVA \
+ ((PUCHAR)HAL_MAKE_QVA(LCA4_PASS2_PCI_IO_BASE_PHYSICAL) + 0x27)
+#define EB66_INTERRUPT_MASK2_QVA NULL
+#define EB66_SIO_INTERRUPT_MASK 0x20
+
+extern PVOID INTERRUPT_MASK0_QVA;
+extern PVOID INTERRUPT_MASK1_QVA;
+extern PVOID INTERRUPT_MASK2_QVA;
+extern ULONG SIO_INTERRUPT_MASK;
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (233)
+
+//
+// Define the location of the flash environment block
+//
+
+extern BOOLEAN SystemIsEB66P;
+
+#define EB66P_ENVIRONMENT_QVA \
+ ((ULONG)HAL_MAKE_QVA(LCA4_PCI_MEMORY_BASE_PHYSICAL) + 0xf0000)
+
+#endif // _EB66PDEF_
+
diff --git a/private/ntos/nthals/haleb66/alpha/ebenv.c b/private/ntos/nthals/haleb66/alpha/ebenv.c
new file mode 100644
index 000000000..b28e0ade4
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebenv.c
@@ -0,0 +1,61 @@
+#include "halp.h"
+#include "arccodes.h"
+
+extern BOOLEAN SystemIsEB66P;
+
+ARC_STATUS
+HalpFlash8kReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpFlash8kWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCmos8kReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCmos8kWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamPtr,
+ IN ULONG Length
+ )
+{
+ if (SystemIsEB66P)
+ return HalpFlash8kReadNVRamBuffer(DataPtr, NvRamPtr, Length);
+
+ return HalpCmos8kReadNVRamBuffer(DataPtr, NvRamPtr, Length);
+}
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamPtr,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ )
+{
+ if (SystemIsEB66P)
+ return HalpFlash8kWriteNVRamBuffer(NvRamPtr, DataPtr, Length);
+
+ return HalpCmos8kWriteNVRamBuffer(NvRamPtr, DataPtr, Length);
+}
+
+
+
diff --git a/private/ntos/nthals/haleb66/alpha/ebinitnt.c b/private/ntos/nthals/haleb66/alpha/ebinitnt.c
new file mode 100644
index 000000000..8e58f6527
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebinitnt.c
@@ -0,0 +1,784 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a Low Cost Alpha
+ (LCA) system. Contains the VLSI 82C106, the 82357 and an EISA bus.
+
+ Orignally taken from the JENSEN hal code.
+
+Author:
+
+ Wim Colgate (DEC) 26-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Correct the IRQ assignments for the EB66 pass2 module. Daytona will not
+ be supported on EB66 pass1 modules.
+
+ Eric Rehm (DEC) 7-Jan-1994
+ Intialize PCI Bus information during Phase 1 init.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "eb66def.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "flash8k.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+//
+//
+//
+BOOLEAN SystemIsEB66P;
+PVOID INTERRUPT_MASK0_QVA;
+PVOID INTERRUPT_MASK1_QVA;
+PVOID INTERRUPT_MASK2_QVA;
+ULONG SIO_INTERRUPT_MASK;
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low (All devices except)
+// irql 4 - device high (the serial lines)
+// irql 5 - clock
+// irql 6 - real time
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11 keyboard/mouse
+// 4 serial 12 errors
+// 5 clock 13 parallel
+// 6 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// clock
+// serial
+// parallel
+// keyboard/mouse
+// pic
+
+//
+// This is the HalpIrqlMask for LCA based machines:
+// The LCA interrupt pins:
+//
+// eirq 0 NMI
+// eirq 1 PIC - 82357 interrupts
+// eirq 2 Clock
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+ADDRESS_USAGE
+EB66PCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
+ 0,0
+ }
+};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpClearInterrupts(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize the EISA and PCI interrupt controllers.
+ //
+
+ HalpInitializePCIInterrupts();
+
+ //
+ // Initialize the 21066 interrupts.
+ //
+ // N.B. - The 21066 uses the 21064 core and so the 21066 HAL
+ // uses 21064 interrupt enable/disable routines.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ HalpEnable21064HardwareInterrupt( Irq = 0,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an LCA
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For LCA, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for LCA is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Clear any error conditions currently pending.
+ //jnfix - report correctables one day
+
+ HalpClearAllErrors( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ HalpFlashDriver = HalpInitializeFlashDriver(EB66P_ENVIRONMENT_QVA);
+ if (HalpFlashDriver != NULL) {
+ //
+ // The flash device was found, so we must be running on an
+ // EB66P
+ //
+ SystemIsEB66P = TRUE;
+ HalpCMOSRamBase = EB66P_ENVIRONMENT_QVA;
+ INTERRUPT_MASK0_QVA = EB66P_INTERRUPT_MASK0_QVA;
+ INTERRUPT_MASK1_QVA = EB66P_INTERRUPT_MASK1_QVA;
+ INTERRUPT_MASK2_QVA = EB66P_INTERRUPT_MASK2_QVA;
+ SIO_INTERRUPT_MASK = EB66P_SIO_INTERRUPT_MASK;
+ } else {
+ SystemIsEB66P = FALSE;
+ INTERRUPT_MASK0_QVA = EB66_INTERRUPT_MASK0_QVA;
+ INTERRUPT_MASK1_QVA = EB66_INTERRUPT_MASK1_QVA;
+ INTERRUPT_MASK2_QVA = EB66_INTERRUPT_MASK2_QVA;
+ SIO_INTERRUPT_MASK = EB66_SIO_INTERRUPT_MASK;
+ }
+
+ HalpRegisterAddressUsage (&EB66PCIMemorySpace);
+
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI Bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize the profiler.
+ //
+
+ HalpInitializeProfiler();
+
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+
+}
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ // WRITE_REGISTER_ULONG( EPIC_HAXR1_QVA, 0 );
+ // WRITE_REGISTER_ULONG( EPIC_HAXR2_QVA, 0);
+ return;
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_LCA_UNCORRECTABLE);
+ *RawSystemInfoSize = 0;
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "EB66";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_LCA_UNCORRECTABLE processorFrame;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/haleb66/alpha/ebintr.s b/private/ntos/nthals/haleb66/alpha/ebintr.s
new file mode 100644
index 000000000..7730a21ec
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebintr.s
@@ -0,0 +1,123 @@
+// TITLE("PCI/ISA Interrupt Handler")
+//++
+//
+// Copyright (c) 1994 Digital Equipment Corporation
+//
+// Module Name:
+//
+// ebintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for Mustang & EB66
+//
+// During Phase 0 initialization, the appropriate platform-dependent handler
+// is connected.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 07-Feb-1994 Eric Rehm
+// Make this module platform-dependent.
+//--
+
+#include "halalpha.h"
+
+ SBTTL("EB66 PCI Interrupt Handler")
+//++
+//
+// VOID
+// HalpPCIInterruptHandlerEB66
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on a PCI
+// bus. The function is responsible for calling HalpPCIDispatch to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpPCIDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// PCI interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPCIInterruptHandlerEB66)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpPCIDispatchEB66 // dispatch the interrupt
+
+ ret zero, (ra) // will never get here
+
+ .end HalpPCIInterruptHandlerEB66
+
+
+
+ SBTTL("Mustang PCI Interrupt Handler")
+//++
+//
+// VOID
+// HalpPCIInterruptHandlerMustang
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on a PCI
+// bus. The function is responsible for calling HalpPCIDispatch to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpPCIDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// PCI interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPCIInterruptHandlerMustang)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpPCIDispatchMustang // dispatch the interrupt
+
+ ret zero, (ra) // will never get here
+
+ .end HalpPCIInterruptHandlerMustang
+
+
+
+
diff --git a/private/ntos/nthals/haleb66/alpha/ebintsup.c b/private/ntos/nthals/haleb66/alpha/ebintsup.c
new file mode 100644
index 000000000..ed4ddbeea
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebintsup.c
@@ -0,0 +1,612 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for EB66/Mustang systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Removed all support of the EB66 pass1 module from the code.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "eb66def.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Global to control interrupt handling for EB64+
+//
+
+UCHAR IntMask0, IntMask1, IntMask2;
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following functions is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+ UCHAR *SystemType;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = (PVOID)HalpPCIDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, DEVICE_LEVEL, LevelSensitive);
+
+ if (SystemIsEB66P)
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB66PPCIPinToLineTable;
+ else
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB66PCIPinToLineTable;
+
+ //
+ // Raise the IRQL while the PCI interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(PCI_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize SIO Programmable Interrupt Contoller
+ //
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the PCI and ISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the ISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpPCIDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, PCI_LEVEL, PCI_LEVEL, PCI_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the ISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR PciVector, IntNumber;
+ ULONG PCRInOffset = 0xffff;
+ KPCR *pcr;
+
+ //
+ // Read in the 1st interrupt register.
+ //
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK0_QVA) & IntMask0;
+
+ //
+ // Was it an ISA (SIO) interrupt?
+ //
+ if (PciVector & SIO_INTERRUPT_MASK) {
+ //
+ // ISA interrupt - call HalpSioDispatch().
+ //
+ return HalpSioDispatch();
+ }
+
+ //
+ // Which PCI interrupt was it?
+ //
+ if (PciVector) {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ } else {
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK1_QVA) & IntMask1;
+
+ if (PciVector) {
+ for(IntNumber = 0; IntNumber < 8; IntNumber++) {
+ if (PciVector & 1) {
+ PCRInOffset = IntNumber + 8;
+ break;
+ }
+ PciVector >>= 1;
+ }
+ } else if (INTERRUPT_MASK2_QVA != NULL) {
+ PciVector = READ_PORT_UCHAR(INTERRUPT_MASK2_QVA) & IntMask2;
+
+ if (PciVector)
+ PCRInOffset = 0x10;
+ }
+ }
+
+ if (PCRInOffset == 0xffff) {
+ return FALSE;
+ }
+
+ PCRInOffset += PCI_VECTORS;
+ PCRInOffset++;
+ return ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset], TrapFrame);
+}
+
+
+VOID
+HalpDisablePCIInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the PCI bus specified PCI bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector.
+ //
+
+ Vector -= PCI_VECTORS;
+ Vector--;
+
+ //
+ // Clear the corresponding bit in the appropriate interrupt mask
+ // shadow and write it out to the interrupt mask.
+ //
+ if (Vector >= 0 && Vector <= 7) {
+ IntMask0 &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ } else if (Vector >= 8 && Vector <= 0xf) {
+ IntMask1 &= (UCHAR) ~(1 << (Vector - 8));
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ } else if ((Vector == 0x10) && (INTERRUPT_MASK2_QVA != NULL)) {
+ IntMask2 = 0;
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ } else {
+#ifdef HALDBG
+ DbgPrint("HalpDisablePCIInterrupt: bad vector\n");
+#endif // HALDBG
+ }
+}
+
+
+VOID
+HalpEnablePCIInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector.
+ //
+
+ Vector -= PCI_VECTORS;
+ Vector--;
+
+ //
+ // Set the corresponding bit in the appropriate interrupt mask
+ // shadow and write it out to the interrupt mask.
+ //
+ if (Vector >= 0 && Vector <= 7) {
+ IntMask0 |= (UCHAR) (1 << Vector);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ } else if (Vector >= 8 && Vector <= 0xf) {
+ IntMask1 |= (UCHAR) (1 << (Vector - 8));
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ } else if ((Vector == 0x10) && (INTERRUPT_MASK2_QVA != NULL)) {
+ IntMask2 = 1;
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ } else {
+#ifdef HALDBG
+ DbgPrint("HalpEnablePCIInterrupt: bad vector\n");
+#endif // HALDBG
+ }
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Isa machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ return( InterruptVector );
+
+}
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the PCI device interrupt mask.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Initialize the shadow copies of the interrupt masks to enable only
+ // the SIO interrupt.
+ //
+
+ IntMask0 = (UCHAR)SIO_INTERRUPT_MASK;
+ IntMask1 = 0;
+ IntMask2 = 0;
+
+ //
+ // Write the masks.
+ //
+ WRITE_PORT_UCHAR(INTERRUPT_MASK0_QVA, ~IntMask0);
+ WRITE_PORT_UCHAR(INTERRUPT_MASK1_QVA, ~IntMask1);
+ if (INTERRUPT_MASK2_QVA != NULL) {
+ WRITE_PORT_UCHAR(INTERRUPT_MASK2_QVA, ~IntMask2);
+ }
+}
diff --git a/private/ntos/nthals/haleb66/alpha/ebmapio.c b/private/ntos/nthals/haleb66/alpha/ebmapio.c
new file mode 100644
index 000000000..e779d23a6
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebmapio.c
@@ -0,0 +1,158 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This maps I/O addresses used by the HAL on Low Cost Alpha (LCA) machines.
+
+Author:
+
+ Wim Colgate (DEC) 26-Oct-1993
+ Originally taken from the Jensen hal code.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eb66def.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a LCA based
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map the address spaces on the LCA4.
+ //
+
+ HalpLca4MapAddressSpaces();
+
+ //
+ // Map base addresses into QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( HalpLca4PciIoPhysical() );
+
+ HalpEisaControlBase = PciIoSpaceBase;;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( HalpLca4PciIntAckPhysical() );
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Map the address spaces on the LCA4.
+ //
+
+ HalpLca4MapAddressSpaces();
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)(HAL_MAKE_QVA(HalpLca4PciIoPhysical())) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/haleb66/alpha/ebsgdma.c b/private/ntos/nthals/haleb66/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ebsysint.c b/private/ntos/nthals/haleb66/alpha/ebsysint.c
new file mode 100644
index 000000000..4d9e69a36
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ebsysint.c
@@ -0,0 +1,424 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Low Cost Alpha (LCA)
+ based system.
+
+ Originally taken from JENSEN hal code.
+
+Author:
+
+ Wim Colgate 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Removed all support of the EB66 pass1 module from the code.
+
+--*/
+
+#include "halp.h"
+#include "eb66def.h"
+#include "axp21064.h"
+
+
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+extern BOOLEAN bMustang;
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL) {
+ HalpDisablePCIInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors (serial and keyboard/mouse for LCA) then disable the
+ // interrupt.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( Vector );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( Vector );
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt. It must be latched.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt. PCI interrupts must be LevelSensitve.
+ // (PCI Spec. 2.2.6)
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL &&
+ InterruptMode == LevelSensitive) {
+ HalpEnablePCIInterrupt( Vector );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors (serial or keyboard/mouse) then perform
+ // 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( Vector, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( Vector, Irql );
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = PCI_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR.
+ //
+
+ return((BusInterruptLevel) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on EB66/Mustang systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ This routine performs no function on an EB66/Mustang because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/haleb66/alpha/eisasup.c b/private/ntos/nthals/haleb66/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/environ.c b/private/ntos/nthals/haleb66/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ev4cache.c b/private/ntos/nthals/haleb66/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ev4int.c b/private/ntos/nthals/haleb66/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ev4ints.s b/private/ntos/nthals/haleb66/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ev4mem.s b/private/ntos/nthals/haleb66/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ev4parit.c b/private/ntos/nthals/haleb66/alpha/ev4parit.c
new file mode 100644
index 000000000..74c6d0d00
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ev4parit.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4parit.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ev4prof.c b/private/ntos/nthals/haleb66/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/flash8k.c b/private/ntos/nthals/haleb66/alpha/flash8k.c
new file mode 100644
index 000000000..cfe6f38a2
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/flash8k.c
@@ -0,0 +1,5 @@
+#define HalpWriteNVRamBuffer HalpFlash8kWriteNVRamBuffer
+#define HalpReadNVRamBuffer HalpFlash8kReadNVRamBuffer
+#define HalpCopyNVRamBuffer HalpFlash8kCopyNVRamBuffer
+#include "..\..\halalpha\flash8k.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/flashdrv.c b/private/ntos/nthals/haleb66/alpha/flashdrv.c
new file mode 100644
index 000000000..20b91fc59
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/flashdrv.c
@@ -0,0 +1,23 @@
+#include "halp.h"
+#include "flash8k.h"
+
+//
+// Flash Drivers
+//
+// extern declarations of each known flash driver's Initialize() funcion
+// are needed here for addition into the list of known drivers.
+//
+// FlashDriverList is an array of driver Initialize() functions used to
+// identify the flash device present in the system. The last entry
+// in FlashDriverList must be NULL.
+//
+extern PFLASH_DRIVER I28F008SA_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F080_Initialize(PUCHAR);
+extern PFLASH_DRIVER Am29F040_Initialize(PUCHAR);
+
+PFLASH_DRIVER (*FlashDriverList[])(PUCHAR) = {
+ I28F008SA_Initialize,
+ Am29F080_Initialize,
+ Am29F040_Initialize,
+ NULL};
+
diff --git a/private/ntos/nthals/haleb66/alpha/fwreturn.c b/private/ntos/nthals/haleb66/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/haldebug.c b/private/ntos/nthals/haleb66/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/halpal.s b/private/ntos/nthals/haleb66/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/idle.s b/private/ntos/nthals/haleb66/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/info.c b/private/ntos/nthals/haleb66/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/inithal.c b/private/ntos/nthals/haleb66/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/intsup.s b/private/ntos/nthals/haleb66/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/ioproc.c b/private/ntos/nthals/haleb66/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/iousage.c b/private/ntos/nthals/haleb66/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/lca4.c b/private/ntos/nthals/haleb66/alpha/lca4.c
new file mode 100644
index 000000000..6c2a74470
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/lca4.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lca4.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/lca4err.c b/private/ntos/nthals/haleb66/alpha/lca4err.c
new file mode 100644
index 000000000..29b38623e
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/lca4err.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lca4err.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/lcaioacc.s b/private/ntos/nthals/haleb66/alpha/lcaioacc.s
new file mode 100644
index 000000000..02bcd070c
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/lcaioacc.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lcaioacc.s"
+
diff --git a/private/ntos/nthals/haleb66/alpha/machdep.h b/private/ntos/nthals/haleb66/alpha/machdep.h
new file mode 100644
index 000000000..364425c7f
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/machdep.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include EB66 platform-specific definitions.
+//
+
+#include "lca4.h"
+#include "eb66def.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/haleb66/alpha/memory.c b/private/ntos/nthals/haleb66/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/mustdef.h b/private/ntos/nthals/haleb66/alpha/mustdef.h
new file mode 100644
index 000000000..7269aeb05
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/mustdef.h
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mustdef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Mustang/EB66 modules.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Revision History:
+
+
+--*/
+
+#ifndef _MUSTDEF_
+#define _MUSTDEF_
+
+#include "alpharef.h"
+#include "lca4.h"
+#include "isaaddr.h"
+
+#define NUMBER_ISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 2
+
+// Highest Virtual local PCI Slot - Max of EB66 (9) and Mustang (7)
+
+#define PCI_MAX_LOCAL_DEVICE 9
+
+// Highest PCI interrupt vector is in PCI vector space
+
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+#define PCI_INTERRUPT_READ_QVA ((PUCHAR)HAL_MAKE_QVA(HalpLca4PciIoPhysical()) + 0x26)
+#define PCI_INTERRUPT_MASK_QVA ((PUCHAR)HAL_MAKE_QVA(HalpLca4PciIoPhysical()) + 0x26)
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (166)
+
+#endif // _MUSTDEF_
diff --git a/private/ntos/nthals/haleb66/alpha/pcibus.c b/private/ntos/nthals/haleb66/alpha/pcibus.c
new file mode 100644
index 000000000..ea5a1717d
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pcibus.c
@@ -0,0 +1,128 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+extern ULONG PCIMaxBus;
+
+//
+// Local function prototypes
+//
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber
+ );
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ );
+
+#ifdef AXP_FIRMWARE
+
+//
+// Put these functions in the discardable text section.
+//
+
+#pragma alloc_text(DISTEXT, HalpPCIConfigCycleType )
+#pragma alloc_text(DISTEXT, HalpPCIConfigAddr )
+
+#endif //AXP_FIRMWARE
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0)
+ {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24, which are wired to IDSEL pins.
+ // Note that HalpValidPCISlot has already done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) LCA4_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if DBG
+ DbgPrint("Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ else
+ {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) LCA4_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if DBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/haleb66/alpha/pcisio.c b/private/ntos/nthals/haleb66/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/pcisup.c b/private/ntos/nthals/haleb66/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/pcrtc.c b/private/ntos/nthals/haleb66/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/pcserial.c b/private/ntos/nthals/haleb66/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/pcspeakr.c b/private/ntos/nthals/haleb66/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/perfcntr.c b/private/ntos/nthals/haleb66/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/haleb66/alpha/pintolin.h b/private/ntos/nthals/haleb66/alpha/pintolin.h
new file mode 100644
index 000000000..e6af4110c
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/pintolin.h
@@ -0,0 +1,192 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Table
+ for EB66 and Mustang.
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston (Digital) 23-June-1994
+ Extracted these tables from ebintsup.c for EB66.
+
+ Anonymous (Digital) date uncertain
+ Combined tables for EB66 and Mustang to go with combined
+ ebintsup.c
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Removed all support of the EB66 pass1 module from the code.
+
+--*/
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang and EB66, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber + 11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for EB66
+//
+// You can limit init table to MAX_PCI_LOCAL_DEVICES entries.
+// The highest virtual slot between EB66 and Mustang is 9, so
+// MAX_PCI_LOCAL_DEVICE is defined as 9 in the platform dependent
+// header file (MUSTDEF.H). HalpValidPCISlot assures us that
+// we won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 9 = PCI_AD[20].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG EB66PCIPinToLineTable[][4]=
+{
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x8, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] SCSI
+ { 0x1, 0x3, 0x5, 0xa }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+ { 0x2, 0x4, 0x9, 0xb }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+ { 0x6, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x7, 0xff, 0xff, 0xff } // Virtual Slot 9 = PCI_AD[20] Tulip
+};
+
+//
+// Interrupt Vector Table Mapping for EB66p
+//
+
+ULONG EB66PPCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0x1, 0x6, 0xa, 0xe }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+ { 0x2, 0x7, 0xb, 0xf }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x3, 0x8, 0xc, 0x10 }, // Virtual Slot 9 = PCI_AD[20] Slot #2
+ { 0x4, 0x9, 0xd, 0x11 } // Virtual Slot 10 = PCI_AD[21] Slot #3
+};
diff --git a/private/ntos/nthals/haleb66/alpha/vga.c b/private/ntos/nthals/haleb66/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/haleb66/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/haleb66/drivesup.c b/private/ntos/nthals/haleb66/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haleb66/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haleb66/hal.rc b/private/ntos/nthals/haleb66/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haleb66/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haleb66/hal.src b/private/ntos/nthals/haleb66/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haleb66/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haleb66/makefile b/private/ntos/nthals/haleb66/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haleb66/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haleb66/makefile.inc b/private/ntos/nthals/haleb66/makefile.inc
new file mode 100644
index 000000000..e16589271
--- /dev/null
+++ b/private/ntos/nthals/haleb66/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ cl /EP hal.src -DALPHA=1 $(C_DEFINES) > obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\haleb66.lib
+ copy $** $@
diff --git a/private/ntos/nthals/haleb66/sources b/private/ntos/nthals/haleb66/sources
new file mode 100644
index 000000000..1cc389bfc
--- /dev/null
+++ b/private/ntos/nthals/haleb66/sources
@@ -0,0 +1,106 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haleb66
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3
+C_DEFINES=-DEV4 -DLCA4
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\28f008sa.c \
+ alpha\29f040.c \
+ alpha\adjust.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cmos8k.c \
+ alpha\ebenv.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\fwreturn.c \
+ alpha\flash8k.c \
+ alpha\flashdrv.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\lca4.c \
+ alpha\lca4err.c \
+ alpha\lcaioacc.s \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\ebinitnt.c \
+ alpha\ebmapio.c \
+ alpha\ebsysint.c \
+ alpha\ebintsup.c \
+ alpha\pcibus.c \
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halfire/hal.rc b/private/ntos/nthals/halfire/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halfire/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halfire/makefile b/private/ntos/nthals/halfire/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halfire/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halfire/makefile.inc b/private/ntos/nthals/halfire/makefile.inc
new file mode 100644
index 000000000..c0a760ce7
--- /dev/null
+++ b/private/ntos/nthals/halfire/makefile.inc
@@ -0,0 +1,22 @@
+ppc\phvrsion.c: $(FIREPOWER_SOURCES)
+
+!IFDEF DDKBUILDENV
+
+!IFDEF VERBOSE
+
+$(TARGETPATH)\$(DESTINATION_DIR)\hal.lib: FRC $(TARGETPATH)\$(DESTINATION_DIR)\halfire.lib
+ copy $** $@
+
+!ELSE
+
+$(TARGETPATH)\$(DESTINATION_DIR)\hal.lib: $(TARGETPATH)\$(DESTINATION_DIR)\halfire.lib
+ copy $** $@
+
+!ENDIF
+
+FRC:
+ echo ======================= environment vars ==========================
+ set
+ echo ======================= environment vars ==========================
+
+!ENDIF
diff --git a/private/ntos/nthals/halfire/ppc/ctrlops.c b/private/ntos/nthals/halfire/ppc/ctrlops.c
new file mode 100644
index 000000000..f921d2ed6
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/ctrlops.c
@@ -0,0 +1,471 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ ctrlops.c
+
+Abstract:
+
+ This module implements the code to emulate call, retunr, and various
+ control operations.
+
+Author:
+
+ David N. Cutler (davec) 10-Nov-1994
+
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Scott Geranen 5-Mar-1996 Added hooks for System BIOS emulation
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+#include "sysbios.h"
+
+VOID
+XmCallOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a call opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Target;
+ ULONG Source;
+
+ //
+ // Save the target address, push the current segment, if required, and
+ // push the current IP, set the destination segment, if required, and
+ // set the new IP.
+ //
+
+ Target = P->DstValue.Long;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if ((P->CurrentOpcode == 0x9a) || (P->FunctionIndex != X86_CALL_OP)) {
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+ P->SegmentRegister[CS] = P->DstSegment;
+
+ } else {
+ XmPushStack(P, P->Eip);
+ }
+
+ P->Eip = Target;
+ XmTraceJumps(P);
+ return;
+}
+
+VOID
+XmEnterOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an enter opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Allocate;
+ ULONG Frame;
+ ULONG Number;
+
+ //
+ // set the number of bytes to allocate on the stack and the number
+ // of nesting levels.
+ //
+
+ Allocate = P->SrcValue.Long;
+ Number = P->DstValue.Long;
+
+ //
+ // Set the data type and save the frame pointer on the stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ XmPushStack(P, P->Gpr[EBP].Exx);
+ Frame = P->Gpr[ESP].Exx;
+
+ } else {
+ P->DataType = WORD_DATA;
+ XmPushStack(P, P->Gpr[BP].Xx);
+ Frame = P->Gpr[SP].Xx;
+ }
+
+ //
+ // Save the current stack pointer and push parameters on the stack.
+ //
+
+ if (Number != 0) {
+
+ //
+ // If the level number is not one, then raise an exception.
+ //
+ // N.B. Level numbers greater than one are not supported.
+ //
+
+ if (Number != 1) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_LEVEL_NUMBER);
+ }
+
+ XmPushStack(P, Frame);
+ }
+
+ //
+ // Allocate local storage on stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->Gpr[EBP].Exx = Frame;
+ P->Gpr[ESP].Exx = P->Gpr[ESP].Exx - Allocate;
+
+ } else {
+ P->Gpr[BP].Xx = (USHORT)Frame;
+ P->Gpr[SP].Xx = (USHORT)(P->Gpr[SP].Xx - Allocate);
+ }
+
+ return;
+}
+
+VOID
+XmHltOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a hlt opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Halt instructions are not supported by the emulator.
+ //
+
+ longjmp(&P->JumpBuffer[0], XM_HALT_INSTRUCTION);
+ return;
+}
+
+VOID
+XmIntOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an int opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Number;
+ PULONG Vector;
+
+ //
+ // If the int instruction is an int 3, then set the interrupt vector
+ // to 3. Otherwise, if the int instruction is an into, then set the
+ // vector to 4 if OF is set. use the source interrupt vector.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if (P->CurrentOpcode == 0xcc) {
+ Number = 3;
+
+ } else if (P->CurrentOpcode == 0xce) {
+ if (P->Eflags.OF == 0) {
+ return;
+ }
+
+ Number = 4;
+
+ } else {
+ Number = P->SrcValue.Byte;
+ }
+
+ //
+ // If the vector number is 0x42, then nop the interrupt. This is the
+ // standard EGA video driver entry point in a PC's motherboard BIOS
+ // for which there is no code.
+ //
+
+#if !defined(_PURE_EMULATION_)
+
+ if (Number == 0x42) {
+ return;
+ }
+
+#endif
+
+ //
+ // Try to emulate a system BIOS call first.
+ //
+ if (!HalpEmulateSystemBios(P, Number)) {
+
+ //
+ // Either it isn't a BIOS call or it isn't supported.
+ // Emulate the x86 stream instead. Note that this
+ // doesn't support chained handlers.
+
+ //
+ // Push the current flags, code segment, and EIP on the stack.
+ //
+
+ XmPushStack(P, P->AllFlags);
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+
+ //
+ // Set the new coded segment and IP from the specified interrupt
+ // vector.
+ //
+
+ Vector = (PULONG)(P->TranslateAddress)(0, 0);
+ P->SegmentRegister[CS] = (USHORT)(Vector[Number] >> 16);
+ P->Eip = (USHORT)(Vector[Number] & 0xffff);
+ XmTraceJumps(P);
+ }
+
+ return;
+}
+
+VOID
+XmIretOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an iret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type and restore the return address, code segment,
+ // and flags.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ P->AllFlags = XmPopStack(P);
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
+
+VOID
+XmLeaveOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a leave opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type, restore the stack pointer, and restore the frame
+ // pointer.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ P->Gpr[ESP].Exx = P->Gpr[EBP].Exx;
+ P->Gpr[EBP].Exx = XmPopStack(P);
+
+ } else {
+ P->DataType = WORD_DATA;
+ P->Gpr[SP].Xx = P->Gpr[BP].Xx;
+ P->Gpr[BP].Xx = (USHORT)XmPopStack(P);
+ }
+
+ return;
+}
+
+VOID
+XmRetOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a ret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Adjust;
+
+ //
+ // Compute the number of bytes that are to be removed from the stack
+ // after having removed the return address and optionally the new CS
+ // segment value.
+ //
+
+ if ((P->CurrentOpcode & 0x1) == 0) {
+ Adjust = XmGetWordImmediate(P);
+
+ } else {
+ Adjust = 0;
+ }
+
+ //
+ // Remove the return address from the stack and set the new IP.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+
+ //
+ // If the current opcode is a far return, then remove the new CS segment
+ // value from the stack.
+ //
+
+ if ((P->CurrentOpcode & 0x8) != 0) {
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ }
+
+ //
+ // Remove the specified number of bytes from the stack.
+ //
+
+ P->Gpr[ESP].Exx += Adjust;
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/fp82091.c b/private/ntos/nthals/halfire/ppc/fp82091.c
new file mode 100644
index 000000000..b9b353158
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fp82091.c
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1994 FirePower Systems, Inc.
+
+Module Name:
+
+ fp82091.c
+
+Abstract:
+
+ The module provides the Intel AIP (82091AA) support for Power PC.
+
+Author:
+
+
+Revision History:
+
+
+
+--*/
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fp82091.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/16 20:45:10 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "fpreg.h"
+#include "fpio.h"
+#include "fp82091.h"
+
+
+
+BOOLEAN
+HalpInitIntelAIP (
+ VOID
+ )
+
+
+{
+
+ //
+ // AIP configuration
+ //
+
+ rIndexAIP1 = AIPCFG1;
+ rTargetAIP1 = CLOCK_POWERED_ON |
+ PRIMARY_ADDRESS_CONFIG |
+ SOFTWARE_MOTHERBOARD;
+ FireSyncRegister();
+
+ rIndexAIP1 = AIPCFG2;
+ //
+ // Active High Mode is ISA-Compatible
+ //
+ rTargetAIP1 = IRQ3_ACTIVE_HIGH |
+ IRQ4_ACTIVE_HIGH |
+ IRQ5_ACTIVE_HIGH |
+ IRQ6_ACTIVE_HIGH |
+ IRQ7_ACTIVE_HIGH;
+ FireSyncRegister();
+
+ rIndexAIP1 = FCFG1;
+ rTargetAIP1 = FDC_ENABLE |
+ PRIMARY_FDC_ADDRESS |
+ TWO_DISK_DRIVES;
+ FireSyncRegister();
+
+ rIndexAIP1 = FCFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset
+ FireSyncRegister();
+
+
+ rIndexAIP1 = PCFG1;
+ rTargetAIP1 = PP_ENABLE |
+ PP_ADDRESS_SELECT_2 | // Parallel Port1 (3BC-3BE)
+ PP_IRQ7 |
+ PP_FIFO_THRSEL_8;
+ FireSyncRegister();
+
+ rIndexAIP1 = PCFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset
+ FireSyncRegister();
+
+ rIndexAIP1 = SACFG1;
+ rTargetAIP1 = PORTA_ENABLE |
+ PORTA_ADDRESS_SELECT_0 | // Serial Port1 (3F8-3FF
+ PORTA_IRQ4;
+ FireSyncRegister();
+
+ rIndexAIP1 = SACFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset, no test mode
+ FireSyncRegister();
+
+ rIndexAIP1 = SBCFG1;
+ rTargetAIP1 = PORTB_ENABLE |
+ PORTB_ADDRESS_SELECT_1 | // Serial Port2 (2F8-2FF)
+ PORTB_IRQ3;
+ FireSyncRegister();
+
+ rIndexAIP1 = SACFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset, no test mode
+ FireSyncRegister();
+
+ rIndexAIP1 = IDECFG;
+ rTargetAIP1 = IDE_INTERFACE_ENABLE; // IDE interface enable
+ FireSyncRegister();
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/fp82091.h b/private/ntos/nthals/halfire/ppc/fp82091.h
new file mode 100644
index 000000000..5fed59a86
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fp82091.h
@@ -0,0 +1,426 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1994 FirePower Systems, Inc.
+
+Module Name:
+
+ pxaipsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the
+ AIP (Intel 82091AA) Advanced Integrated Peripheral chip.
+
+Author:
+
+
+Revision History:
+
+
+--*/
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fp82091.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/05/14 02:32:08 $
+ * $Locker: $
+ */
+
+// AIP configuration registers
+
+
+//
+// Index register select
+//
+
+#define AIPID 0x00 // Product Identification
+#define AIPREV 0x01 // Revision Identification
+#define AIPCFG1 0x02 // AIP Configuration 1
+#define AIPCFG2 0x03 // AIP Configuration 2
+#define FCFG1 0x10 // FDC Configuration
+#define FCFG2 0x11 // FDC Power Management and
+ /* Status */
+#define PCFG1 0x20 // Parallel Port Configuration
+#define PCFG2 0x21 // Parallel Port Power Management
+ /* and Status */
+#define SACFG1 0x30 // Serial Port A Configuration
+#define SACFG2 0x31 // Serail Port A Power Management
+ /* and Status */
+#define SBCFG1 0x40 // Serial Port B Configuration
+#define SBCFG2 0x41 // Serial Port B Power Management
+ /* and Status */
+#define IDECFG 0x50 // IDE Configuration
+
+/*+++
+
+ AIPID: RO
+ 7-0 Product Identification Number
+
+
+ AIPREV: RO
+ 7-4 Step Number
+ 3-0 Dash Number
+
+ AIPCFG1: R/W
+ 7 Not Used
+ 6 Supply Voltage (RO)
+ 0: 5.0V
+ 1: 3.3V
+ 4-5 Configuration Mode Select (R/W)
+ 0x00 Software Motherboard
+ 0x01 Software Add-in
+ 0x10 Extended Hardware
+ 0x11 Basic Hardware
+ 3 Configuration Address Select (RO)
+ 0: Secondary Address
+ 1: Primary Address
+ 2-1 Reserved
+ 0 Clock Off (R/W)
+ 0: AIP powered on
+ 1: AIP powered off
+
+ AIPCFG2: R/W
+ 7 IRQ7 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 6 IRQ6 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 5 IRQ5 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 4 IRQ4 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 3 IRQ3 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 2-0 Reserved
+
+ FCFG1: R/W
+ 7 Floppy Disk Drive Quantity (R/W)
+ 0: Two
+ 1: Four
+ 6-2 Reserved
+ 1 FDC Address Select (R/W)
+ 0: Primary (3F0-3F7)
+ 1: Secondary (370-377)
+ 0 FDC Enable (R/W)
+ 0: Disable
+ 1: Enable
+
+ FCFG2: R/W
+ 7-4 Reserved
+ 3 FDC Auto Powerdown Enable (R/W)
+ 0: Disable
+ 1: Enable, 0: Disable
+ 2 FDC Reset (R/W)
+ 0: No FDC Module Reset
+ 1: Reset FDC Module, 0: No FDC Module Reset
+ 1 FDC Idle Status (RO)
+ 0: Active
+ 1: Idle, 0: Active
+ 0 FDC Direct Powerdown Control (R/W)
+ 0: Not in Direct Powerdown
+ 1: Powerdown, 0: Not in Direct Powerdown
+
+ PCFG1: R/W
+ 7 PP FIFO Threshold Select (R/W)
+ 0: 8 (forward and reverse)
+ 1: 1 (forward), 15(reverse)
+ 6-5 PP Hardware Mode Select (R/W)
+ 00: ISA-Compatible (read), ISA-Compatible (write)
+ 01: PS/2-Compatible (read), PS/2-Compatible (write)
+ 10: EPP (read) , EPP (write)
+ 11: ECP (read), Reserved (do not write)
+ 4 Reserved
+ 3 PP Interrupt Select (R/W)
+ 0: IRQ5
+ 1: IRQ7
+ 2-1 PP Address Select (R/W)
+ 00: 378-37F
+ 01: 278-27F
+ 10: 3BC-3BE
+ 11: Reserved
+ 0 PP Enable (R/W)
+ 0: Disable
+ 1: Enable
+ PCFG2: R/W
+ 7-6 Reserved
+ 5 PP FIFO Error Status (RO)
+ 0: No Underrun or Overrun
+ 1: Underrun or Overrun
+ 4 Reserved
+ 3 PP Auto Powerdown Enable (R/W)
+ 0: Disable
+ 1: Enable
+ 2 PP Reset (R/W)
+ 0: Inactive
+ 1: Active
+ 1 PP Idle Status (RO)
+ 0: Avtive
+ 1: Idle
+ 0 PP Port Direct Powerdown (R/W)
+ 0: Disabled
+ 1: Enabled
+
+ SACFG1: R/W
+ 7 MIDI Clock Enable for Serial Port A (R/W)
+ 0: 1.8642 MHz Clock
+ 1: 2MHz Clock
+ 6-5 Reserved
+ 4 Serial Port A IRQ Select (R/W)
+ 0: IRQ3
+ 1: IRQ4
+ 3-1 Serial Port A Address Select (R/W)
+ 000: 3F8-3FF
+ 001: 2F8-2FF
+ 010: 220-227
+ 011: 228-22F
+ 100: 238-23F
+ 101: 2E8-2EF
+ 110: 338-33F
+ 111: 3E8-3EF
+ 0 Serial Port A Enable (R/W)
+ 0: Disable
+ 1: Enable
+
+ SACFG2: R/W
+ 0: to Disable
+ 1: to Enable
+ -------------------------------------------------------------
+ 7-5 Reserved
+ 4 Serial Port A Test Mode (R/W)
+ 3 Serial Port A Auto Powerdown Enable (R/W)
+ 2 Serial Port A Reset (R/W)
+ 1 Serial Port A Idle Status (RO)
+ 0 Serial Port A Direct Powerdown Control (R/W)
+
+
+ SBCFG1: R/W
+ -------------------------------------------------------------
+ 7 MIDI Clock Enable for Serial Port B (R/W)
+ 0: 1.8642 MHz Clock
+ 1: 2MHz Clock
+ 6-5 Reserved
+ 4 Serial Port B IRQ Select (R/W)
+ 0: IRQ3
+ 1: IRQ4
+ 3-1 Serial Port B Address Select (R/W)
+ 000: 3F8-3FF
+ 001: 2F8-2FF
+ 010: 220-227
+ 011: 228-22F
+ 100: 238-23F
+ 101: 2E8-2EF
+ 110: 338-33F
+ 111: 3E8-3EF
+ 0 Serial Port B Enable (R/W)
+ 0: Disable
+ 1: Enable
+
+ SBCFG2: R/W
+ -------------------------------------------------------------
+ 7-5 Reserved
+ 4 Serial Port B Test Mode (R/W)
+ 0: Disable
+ 1: Enable
+ 3 Serial Port B Auto Powerdown Enable (R/W)
+ 0: Disable
+ 1: Enable
+ 2 Serial Port B Reset (R/W)
+ 0: Reset Inactive
+ 1: Reset Active
+ 1 Serial Port B Idle Status (RO)
+ 0: Active
+ 1: Idle
+ 0 Serial Port B Direct Powerdown Control (R/W)
+ 0: Disable
+ 1: Enable
+
+ IDECFG: R/W
+ 7-3 Reserved
+ 2 IDE Dual Interface Select (R/W)
+ 1: Primary and Secondary Address Selected
+ 0: Dual Interface Disabled
+ 1 IDE Address Select (R/W)
+ 0: Primary (1F0-1F7,3F6,3F7)
+ 1: Secondary (170-17F,376,377)
+ 0 IDE Interface Enable (R/W)
+ 0: Disable
+ 1: Enable, 0: Disable
+
+---*/
+
+
+//
+// Data register values
+//
+
+//
+// AIPCFG1
+//
+
+#define CLOCK_POWERED_ON 0x00
+#define CLOCK_POWERED_OFF 0x01
+#define PRIMARY_ADDRESS_CONFIG 0x00
+#define SECONDARY_ADDRESS_CONFIG 0x08
+#define SOFTWARE_MOTHERBOARD 0x00
+#define SOFTWARE_ADDIN 0x10
+#define EXTENDED_HARDWARE 0x20
+#define BASIC_HARDWARE 0x30
+#define SUPPLY_VOLTAGE_33V 0x40
+
+//
+// AIPCFG2
+//
+
+#define IRQ3_ACTIVE_LOW 0x08
+#define IRQ3_ACTIVE_HIGH 0x00
+#define IRQ4_ACTIVE_LOW 0x10
+#define IRQ4_ACTIVE_HIGH 0x00
+#define IRQ5_ACTIVE_LOW 0x20
+#define IRQ5_ACTIVE_HIGH 0x00
+#define IRQ6_ACTIVE_LOW 0x40
+#define IRQ6_ACTIVE_HIGH 0x00
+#define IRQ7_ACTIVE_LOW 0x80
+#define IRQ7_ACTIVE_HIGH 0x00
+#define AIPCFG2_MASK 0xF8
+
+//
+// FCFG1
+//
+
+#define FDC_ENABLE 0x01
+#define PRIMARY_FDC_ADDRESS 0x00
+#define SECONDARY_FDC_ADDRESS 0x02
+#define TWO_DISK_DRIVES 0x00
+#define FOUR_DISK_DRIVES 0x80
+#define FCFG1_MASK 0x83
+
+//
+// FCFG2
+//
+
+#define FDC_DIRECT_POWERDOWN 0x01
+#define FDC_IDLE 0x02 /* read-only */
+#define RESET_FDC_MODULE 0x04
+#define FDC_AUTO_POWERDOWN_ENABLE 0x08
+#define FCFG2_MASK 0x0F
+
+//
+// PCFG1
+//
+
+#define PP_ENABLE 0x01
+#define PP_ADDRESS_SELECT_0 0x00 /* 378-37F */
+#define PP_ADDRESS_SELECT_1 0x02 /* 278-27F */
+#define PP_ADDRESS_SELECT_2 0x04 /* 3BC-3BE */
+#define PP_IRQ7 0x08
+#define PP_IRQ5 0x00
+#define PP_HWMODE_ISA_COMPAT 0x00
+#define PP_HWMODE_PS2_COMPAT 0x20
+#define PP_HWMODE_EPP 0x40
+#define PP_HWMODE_ECP 0x60 /* read-only */
+#define PP_FIFO_THRSEL_1 0x80
+#define PP_FIFO_THRSEL_8 0x00
+#define PCFG1_MASK 0xEF
+
+
+//
+// PCFG2
+//
+
+#define PP_DIRECT_POWERDOWN 0x01
+#define PP_IDLE 0x02 /* read-only */
+#define PP_RESET 0x04
+#define PP_AUTO_POWERDOWN_ENABLE 0x08
+#define PP_FIFO_UNDERRUN_OR_OVERRUN 0x20
+#define PCFG2_MASK 0x2F
+
+//
+// SACFG1
+//
+
+#define PORTA_ENABLE 0x01
+#define PORTA_ADDRESS_SELECT_0 0x00 /* 3F8-3FF */
+#define PORTA_ADDRESS_SELECT_1 0x02 /* 2F8-2FF */
+#define PORTA_ADDRESS_SELECT_2 0x04 /* 220-227 */
+#define PORTA_ADDRESS_SELECT_3 0x06 /* 228-22F */
+#define PORTA_ADDRESS_SELECT_4 0x08 /* 238-23F */
+#define PORTA_ADDRESS_SELECT_5 0x0A /* 2E8-2EF */
+#define PORTA_ADDRESS_SELECT_6 0x0C /* 338-33F */
+#define PORTA_ADDRESS_SELECT_7 0x0D /* 3E8-3EF */
+#define PORTA_IRQ4 0x10
+#define PORTA_IRQ3 0x00
+#define PORTA_MIDI_CLOCK_2000KHZ 0x80
+#define PORTA_MIDI_CLOCK_1846KHZ 0x00
+#define SACFG1_MASK 0x9F
+
+
+//
+// SACFG2
+//
+
+#define PORTA_DIRECT_POWERDOWN 0x01
+#define PORTA_IDLE 0x02 /* read-only */
+#define PORTA_RESET 0x04
+#define PORTA_AUTO_POWERDOWN_ENABLE 0x08
+#define PORTA_TEST_MODE_ENABLE 0x10
+#define SACFG2_MASK 0x1F
+
+//
+// SBCFG1
+//
+
+#define PORTB_ENABLE 0x01
+#define PORTB_ADDRESS_SELECT_0 0x00 /* 3F8-3FF */
+#define PORTB_ADDRESS_SELECT_1 0x02 /* 2F8-2FF */
+#define PORTB_ADDRESS_SELECT_2 0x04 /* 220-227 */
+#define PORTB_ADDRESS_SELECT_3 0x06 /* 228-22F */
+#define PORTB_ADDRESS_SELECT_4 0x08 /* 238-23F */
+#define PORTB_ADDRESS_SELECT_5 0x0A /* 2E8-2EF */
+#define PORTB_ADDRESS_SELECT_6 0x0C /* 338-33F */
+#define PORTB_ADDRESS_SELECT_7 0x0D /* 3E8-3EF */
+#define PORTB_IRQ4 0x10
+#define PORTB_IRQ3 0x00
+#define PORTB_MIDI_CLOCK_2000KHZ 0x80
+#define PORTB_MIDI_CLOCK_1846KHZ 0x00
+#define SBCFG1_MASK 0x9F
+
+
+//
+// SBCFG2
+//
+
+#define PORTB_DIRECT_POWERDOWN 0x01
+#define PORTB_IDLE 0x02 /* read-only */
+#define PORTB_RESET 0x04
+#define PORTB_AUTO_POWERDOWN_ENABLE 0x08
+#define PORTB_TEST_MODE_ENABLE 0x10
+#define SBCFG2_MASK 0x1F
+
+//
+// IDECFG
+//
+
+#define IDE_INTERFACE_ENABLE 0x01
+#define PRIMARY_IDE_ADDRESS 0x00
+#define SECONDARY_IDE_ADDRESS 0x02
+#define IDE_DUAL_INTERFACE 0x04
+#define IDECFG_MASK 0x07
+
+
+typedef struct _INTEL_AIP_CONTROL {
+ UCHAR Reserved1[0x22];
+ UCHAR AIPConfigIndexRegister; // Offset 0x22
+ UCHAR AIPConfigTargetRegister; // Offset 0x23
+// UCHAR Reserved1[0x26E];
+// UCHAR AIPConfigIndexRegister; // Offset 0x26E
+// UCHAR AIPConfigTargetRegister; // Offset 0x26F
+} INTEL_AIP_CONTROL, *PINTEL_AIP_CONTROL;
+
diff --git a/private/ntos/nthals/halfire/ppc/fparch.h b/private/ntos/nthals/halfire/ppc/fparch.h
new file mode 100644
index 000000000..99c9685fd
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fparch.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1995. FirePower Systems, Inc.
+ * (Do Not Distribute without permission)
+ *
+ * $RCSfile: fparch.h $
+ * $Revision: 1.4 $
+ * $Date: 1996/01/11 07:05:05 $
+ * $Locker: $
+ *
+ */
+
+#ifndef _FPARCH_H
+#define _FPARCH_H
+//
+// These names are not sacrosanct, and should be revised upon input from Susan,
+// Jim, and anyone else interested.
+//
+enum scope_use {
+ ENG,
+ MFG,
+ TEST,
+ CUST
+ };
+
+enum rel_state {
+ GENERAL,
+ OFFICIAL,
+ TESTING,
+ CONTROLLED,
+ LAB
+ };
+
+
+typedef struct _TheBigRev {
+ CHAR Org[80]; // originating organization, ( i.e.
+ // who built it )
+ enum scope_use Scope; // release status from the releasing org
+ CHAR BuildDate[16]; // time of year, date, day, hour, min,
+ CHAR BuildTime[16]; // time of year, date, day, hour, min,
+ // sec it was built
+ UCHAR Major; // the Major revision of this item
+ UCHAR Minor; // Minor rev of this item:
+ enum rel_state State; // the release status of this item
+} RelInfo;
+
+#endif // _FPARCH_H
diff --git a/private/ntos/nthals/halfire/ppc/fpbat.c b/private/ntos/nthals/halfire/ppc/fpbat.c
new file mode 100644
index 000000000..cdebbf049
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbat.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbat.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:32:13 $
+ * $Locker: $
+ */
+
+/*++
+
+Module Name:
+
+fpbat.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
+ video adapter.
+
+Author:
+
+ Roger Lanser February 1995
+ Bill Rees May 1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Roger Lanser 02-23-95: Added FirePower Video and INT10, nuc'd others
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+#include "fpbat.h"
+#include "arccodes.h"
+#include "phsystem.h"
+#include "pxmemctl.h"
+#include "fpdcc.h"
+#include "fpcpu.h"
+#include "fpdebug.h"
+#include "phsystem.h"
+#include "x86bios.h"
+#include "pxpcisup.h"
+
+#define MAX_DBATS 4
+
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalpInitializeVRAM)
+#if DBG
+#pragma alloc_text(INIT, HalpDisplayBatForVRAM)
+#endif
+#endif
+
+extern ULONG TmpVramBase;
+extern ULONG TmpDbatNum;
+extern ULONG TmpDbatVal;
+extern BOOLEAN HalpDisplayOwnedByHal; // make sure is false: [breeze:1/27/95]
+
+
+extern PUCHAR HalpVideoMemoryBase;
+extern ULONG HalpVideoMemorySize;
+extern BOOLEAN HalpDisplayTypeUnknown;
+
+#define MEM1MB 0x00100000
+#define MEM2MB 0x00200000
+#define MEM4MB 0x00400000
+
+//
+// Define OEM font variables.
+//
+
+
+
+/*++
+
+Routine Description: PVOID HalpMarkDbatForVRAM ()
+
+ This function Marks the VRAM DBAT cacheable and if it's on an
+ mp system marks the DBAT with the memory coherence attribute
+ according to the architecture manual.
+
+Arguments:
+
+ VramBase - The base of VRAM to map.
+
+ VramSize - The size of VRAM to map (output).
+
+Return Value:
+
+ Mapped virtual address.
+
+--*/
+
+VOID
+HalpMarkDbatForVRAM (
+ IN PVOID /* PHYSICAL_ADDRESS */ VramBase,
+ IN OUT PULONG VramSize
+ )
+{
+ ULONG i, low, hi;
+ //
+ // find the bat register used for the display memory and make
+ // it cacheable
+ //
+ for (i = 0; i < MAX_DBATS; i++) {
+ low = HalpGetLowerDBAT(i);
+ if ((low & 0xfffe0000) == (ULONG) VramBase) {
+ //
+ // Turn cache bit on.
+ //
+ hi = HalpGetUpperDBAT(i);
+ hi &= 0xfffe0000; // Clear BL, Vs, Vp bit
+ low &= 0xffffff87; // Clear W, I, M, & G bits -
+ // assuming PP is set to 10
+ switch (*VramSize) {
+ case MEM1MB:
+ hi |= 0x1f; // Set 1MB block size with Vs & Vp bits on
+ break;
+ case MEM2MB:
+ hi |= 0x3f; // Set 2MB block size with Vs & Vp bits on
+ break;
+ case MEM4MB:
+ default:
+ hi |= 0x7f; // Set 4MB block size with Vs & Vp bits on
+ break;
+ }
+
+ //
+ // Gives us a flag to turn off cached VRAM during debug
+ // sessions. Makes the display more trust worthy.
+ //
+ HDBG(DBG_DISPNOCACHE, low |= CACHE_INHIBIT;);
+
+ //
+ // Flag to turn on MEMORY COHERENCE, i.e. make it a global
+ // attribute so the processor will through the proper signals
+ // onto the bus to allow other cpus to snoop and act on it.
+ //
+ HDBG(DBG_DISPMEMCOHERE, low |= MEMORY_COHRNCY;);
+ HalpSetUpperDBAT(i, hi);
+ if ((SystemType == SYS_POWERTOP) || (SystemType == SYS_POWERSLICE)
+ || (SystemType == SYS_POWERSERVE)) {
+ low |= MEMORY_COHRNCY;
+ }
+ HalpSetLowerDBAT(i, low);
+ break;
+ }
+ }
+
+}
+/*++
+
+Routine Description: PVOID HalpInitializeVRAM ()
+
+ This function maps the VRAM DBAT and marks it cacheable.
+
+Arguments:
+
+ VramBase - The base of VRAM to map.
+
+ VramSize - The size of VRAM to map (output).
+
+Return Value:
+
+ Mapped virtual address.
+
+--*/
+
+PVOID
+HalpInitializeVRAM (
+ IN PVOID /* PHYSICAL_ADDRESS */ VramBase,
+ IN OUT PULONG VramSize,
+ OUT PULONG VramWidth
+ )
+{
+ PVOID va = NULL;
+ ULONG hi, low, detect_reg;
+ LONG i;
+
+ switch (SystemType) {
+ case SYS_POWERPRO:
+ /*
+ * Read VRAM presence detect register SIMM01
+ */
+ detect_reg = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase)+0x0890);
+ if ((detect_reg & 0xf0) == 0xf0 ) {
+ *VramSize = MEM1MB;
+ *VramWidth = VRAM_32BIT;
+ } else {
+ *VramSize = MEM2MB;
+ *VramWidth = VRAM_64BIT;
+ }
+ break;
+ case SYS_POWERTOP:
+ /*
+ * Read VRAM presence detect register SIMM23
+ */
+ detect_reg = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase)+0x08C0);
+ //
+ // if either of the vram simms in slot 2 or 3 appears missing ( i.e.
+ // reports it's nibble is an 'f' ), set the vram size to 2 meg.
+ //
+ if (((detect_reg & 0xf0) == 0xf0) || ((detect_reg & 0x0f) == 0x0f)) {
+ *VramSize = MEM2MB;
+ *VramWidth = VRAM_64BIT;
+ } else {
+ *VramSize = MEM4MB;
+ *VramWidth = VRAM_128BIT;
+ }
+ break;
+ case SYS_POWERSERVE:
+ case SYS_UNKNOWN:
+ default:
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ break;
+ }
+
+ //
+ // Map a BAT.
+ //
+
+ va = KePhase0MapIo(VramBase, *VramSize);
+
+ if (!va) {
+ //
+ // Bad news, the map failed. Look for the DBAT that has the
+ // memory space mapping and use it.
+ //
+ for (i = 0; i < MAX_DBATS; i++) {
+ low = HalpGetLowerDBAT(i);
+ if (IO_MEMORY_PHYSICAL_BASE == (low &= 0xfffe0000)) {
+ low |= IO_MEMORY_PHYSICAL_BASE;
+ HalpSetLowerDBAT(i, low);
+ hi = HalpGetUpperDBAT(i);
+ va = (PVOID)(hi & 0xfffe0000); // Get va
+ break;
+ }
+ }
+ //
+ // Give up...
+ //
+ if (!va) {
+ return va;
+ }
+ }
+
+ //
+ // find the bat register used for the display memory and make
+ // it cacheable
+ //
+ for (i = 0; i < MAX_DBATS; i++) {
+ low = HalpGetLowerDBAT(i);
+ if ((low & 0xfffe0000) == (ULONG) VramBase) {
+ //
+ // Turn cache bit on.
+ //
+ hi = HalpGetUpperDBAT(i);
+ hi &= 0xfffe0000; // Clear BL, Vs, Vp bit
+ low &= 0xffffff87; // Clear W, I, M, & G bits -
+ // assuming PP is set to 10
+ switch (*VramSize) {
+ case MEM1MB:
+ hi |= 0x1f; // Set 1MB block size with Vs & Vp bits on
+ break;
+ case MEM2MB:
+ hi |= 0x3f; // Set 2MB block size with Vs & Vp bits on
+ break;
+ case MEM4MB:
+ default:
+ hi |= 0x7f; // Set 4MB block size with Vs & Vp bits on
+ break;
+ }
+
+ //
+ // Gives us a flag to turn off cached VRAM during debug
+ // sessions. Makes the display more trust worthy.
+ //
+ // HDBG(DBG_DISPNOCACHE, low |= CACHE_INHIBIT;);
+
+ //
+ // Flag to turn on MEMORY COHERENCE, i.e. make it a global
+ // attribute so the processor will through the proper signals
+ // onto the bus to allow other cpus to snoop and act on it.
+ //
+ // HDBG(DBG_DISPMEMCOHERE, low |= MEMORY_COHRNCY;);
+ HalpSetUpperDBAT(i, hi);
+ if ( SystemDescription[SystemType].Flags & SYS_MPFOREAL) {
+ low |= MEMORY_COHRNCY;
+ }
+ HalpSetLowerDBAT(i, low);
+ break;
+ }
+ }
+ return va;
+}
+
+#if DBG
+/*++
+
+ Routine Description: VOID HalpDisplayBatForVRAM ()
+
+ This function displays the VRAM BAT.
+
+Arguments:
+
+
+Return Value:
+
+ none
+
+--*/
+
+VOID
+HalpDisplayBatForVRAM (
+ void
+ )
+{
+ ULONG hi, low;
+ LONG i;
+
+ //
+ // Look for the DBAT mapped to the VRAM
+ //
+ for (i = 0; i < 4; i++) {
+ low = HalpGetLowerDBAT(i);
+ if ((low & 0xfffe0000) == (ULONG)DISPLAY_MEMORY_BASE) {
+ hi = HalpGetUpperDBAT(i);
+ HalpDebugPrint("HalpDisplayBatForVRAM: (%d): U(0x%08x) L(0x%08x)\n", i, hi, low);
+ break;
+ }
+ }
+}
+#endif // DBG
diff --git a/private/ntos/nthals/halfire/ppc/fpbat.h b/private/ntos/nthals/halfire/ppc/fpbat.h
new file mode 100644
index 000000000..bb9266092
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbat.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbat.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/11 07:05:18 $
+ * $Locker: $
+ */
+
+#ifndef _FPBAT_H
+#define _FPBAT_H
+
+PVOID HalpInitializeVRAM ( PVOID , PULONG, PULONG );
+
+#if DBG
+VOID HalpDisplayBatForVRAM ( void );
+#endif
+
+#endif // _FPBAT_H
diff --git a/private/ntos/nthals/halfire/ppc/fpbt445.c b/private/ntos/nthals/halfire/ppc/fpbt445.c
new file mode 100644
index 000000000..514a81778
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbt445.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbt445.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/05/14 02:32:18 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the display controller chip
+ * known as the DCC. This chip control's vram setup and works in conjunction
+ * with the ram dac which, in this case is a Brooktree Bt485.
+ *
+ */
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpDcc.h"
+#include "fpBt445.h"
+
+VOID
+HalpSetupBt445(
+ ULONG Mode,
+ ULONG VramWidth
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the display hardware for 640x480 in preparation
+ for HalDisplayString(). This means that either we are booting up or
+ dealing with the blue screen of death. We should really change this to
+ a higher resolution ASAP. [ged]
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG i;
+ ULONG modeIndex;
+
+
+ //
+ // BT445 Mask value
+ //
+ // The order of entries must match btTab
+ //
+ UCHAR btMask[30][3] = {
+ {6,0x05,0x3f},
+ {6,0x06,0xcf},
+ {6,0x07,0x00},
+ {2,0x06,0x7f},
+ {6,0x0a,0xbb},
+ {6,0x0d,0x00},
+ {5,0x00,0x00},
+ {5,0x08,0x00},
+ {5,0x10,0x00},
+ {6,0x09,0x00},
+ {6,0x01,0xdf},
+ {6,0x02,0xbf},
+ {5,0x1a,0x0f},
+ {5,0x22,0x03},
+ {6,0x0f,0x00},
+ {6,0x03,0x3f},
+ {6,0x0b,0x3f},
+ {5,0x01,0x00},
+ {5,0x09,0x00},
+ {5,0x11,0x00},
+ {2,0x05,0x00},
+ {2,0x04,0x00},
+ {5,0x18,0x00},
+ {5,0x19,0x00},
+ {5,0x1b,0x0f},
+ {5,0x20,0x00},
+ {5,0x21,0x00},
+ {5,0x23,0x03},
+ {6,0x0e,0x00},
+ {6,0x08,0x1c}
+ };
+
+ // BT445 Address register
+ // address (index)
+ // register
+ // 2 = BT445 Group 0 Register
+ // 5 = BT445 Config Register
+ // 6 = BT445 Group 1 Register
+ // value
+ typedef struct {
+ UCHAR reg;
+ UCHAR addr;
+ UCHAR value;
+ } BTTAB; // [rdl:01.03.95]
+
+ // [rdl:01.03.95]
+ BTTAB btTab[3 /* 32/64/128 bit vram */][2 /* mode 0 or 15 */][30] = {
+ // 32 bit VRAM width
+ {
+ // Mode 0 - 640X480 8 bit 72Hz
+ {
+ {6,0x05,0x2c},
+ {6,0x06,0x84},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x00},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x40},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x03},
+ {6,0x0b,0x03},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ },
+
+ // Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {6,0x05,0x37},
+ {6,0x06,0x45},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x00},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x40},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x03},
+ {6,0x0b,0x03},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ }
+ },
+ // 64 bit VRAM width
+ {
+ // Mode 0 - 640X480 8 bit 72Hz
+ {
+ {6,0x05,0x2c},
+ {6,0x06,0x84},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ },
+
+ // Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {6,0x05,0x37},
+ {6,0x06,0x45},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ }
+ },
+ // 128 bit VRAM width
+ {
+ // Mode 0 - 640X480 8 bit 72Hz
+ {
+ {6,0x05,0x2c},
+ {6,0x06,0x84},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ },
+
+ // Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {6,0x05,0x37},
+ {6,0x06,0x45},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ }
+ }
+ };
+
+
+
+ //
+ // Setup the RAMDAC (Bt445)
+ //
+ // go table driven [rdl:01.03.95]
+ //
+ modeIndex = (Mode) ? 1 : 0; // if not mode 0, then make it mode 15.
+ for (i = 0; i < sizeof(btTab[0][0])/sizeof(BTTAB); i++) {
+ BTTAB tab = btTab[VramWidth][modeIndex][i];
+ UCHAR value = tab.value;
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + BT445_ADDRESS, tab.addr);
+ FireSyncRegister();
+
+ if (tab.reg == btMask[i][0] && tab.addr == btMask[i][1]) {
+ if (btMask[i][2]) {
+ value = READ_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + BT445_ADDRESS + tab.reg);
+ value &= ~btMask[i][2];
+ value |= btMask[i][2] & tab.value;
+ }
+ } else {
+ //
+ // btMask is out of order with respect to btTab
+ //
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + BT445_ADDRESS + tab.reg, value);
+ FireSyncRegister();
+ }
+
+ //
+ // ...and program the color lookup table with "NT" colors
+ // starting pixel address for loading RGB values:
+ //
+ rRamDacAddr = 0;
+ FireSyncRegister();
+
+ //
+ // load the red, green, and blue data for pixel 0:
+ //
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+
+ //
+ // load the red, green, and blue data for pixel 1: ( this gives NT
+ // the characteristice BLUE screen for booting )
+ //
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0xff;
+ FireSyncRegister();
+
+ for (i=2; i<=0xff; i++) {
+ /* A grey ramp with entry 255 white */
+ rDacPrimeLut = (UCHAR) i;
+ rDacPrimeLut = (UCHAR) i;
+ rDacPrimeLut = (UCHAR) i;
+ FireSyncRegister();
+ }
+
+ return;
+} // Init Vram
+
+ULONG
+HalpSetPixelColorMap( ULONG Color, ULONG Pixel )
+{
+ UCHAR Red, Green, Blue, Control;
+ //
+ // set the display to red while in phase 0:
+ //
+ rRamDacAddr = (UCHAR) ( Pixel & 0x000000ff);
+ FireSyncRegister();
+
+ Control = (UCHAR) ( ( Color >> 24 ) & 0x000000ff );
+ Red = (UCHAR) ( ( Color >> 16 ) & 0x000000ff );
+ Green = (UCHAR) ( ( Color >> 8 ) & 0x000000ff );
+ Blue = (UCHAR) ( Color & 0x000000ff );
+ //
+ // load the red, green, and blue data for pixel 1:
+ // ( this is the normal NT BLUE boot screen )
+ //
+ rDacPrimeLut = Red; // set this pixel to no red ...
+ FireSyncRegister();
+ rDacPrimeLut = Green; // set this pixel to no green ...
+ FireSyncRegister();
+ rDacPrimeLut = Blue; // set this pixel to max blue.
+ FireSyncRegister();
+ return(0);
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/fpbt445.h b/private/ntos/nthals/halfire/ppc/fpbt445.h
new file mode 100644
index 000000000..3b2d721f6
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbt445.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbt445.h $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:05:32 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the BrookTree Bt445 RamDac.
+ *
+ */
+
+#ifndef FPBT445_H
+#define FPBT445_H
+/*
+** The Bt445 organizes it's registers into a complex index based arrangement.
+** The final data registers are actually accessed via some control bits which
+** show up memory mapped. However, since each control address can access
+** several registers, the register desired must be specified through the Bt445
+** index register. For example, if you want to read the ID value of the chip,
+** you must write the id register value ( 0x00 ) to the Bt445 address ( index ).
+** Then you must read the address that corresponds to control register 2.
+**
+*/
+
+//
+// defines for access to control register 0 ( c bits = 000 )
+// Use rRamDacAddr to access the Bt445 address register
+//
+#define BT_Address 0x00 // index register into the Bt445.
+
+//
+// defines for access to control register 1 ( c bits = 001 )
+// Use rDacPrimeLut to access the primary color palette register
+// NOTE: This register requires MODULO 3 loading and reading
+//
+
+
+//
+// defines for access to control register 2 ( c bits = 010 )
+// use rRamDacCntl to access
+//
+#define DAC_ID_REG 0x00 //
+#define DAC_REVISION_REG 0x01
+#define DAC_READ_ENABLE 0x04
+#define DAC_BLINK_ENABLE 0x05
+#define DAC_COMMAND_REG0 0x06
+#define DAC_TEST_REG0 0x07
+
+//
+// defines for access to control register 3 ( c bits = 011 )
+// use rDacOvlayLut to access the overlay color palette
+// NOTE: This register requires MODULO 3 loading and reading
+//
+
+
+//
+// defines for access to control register 5 ( c bits = 101 )
+// use rDacPixelBit to access the rgb pixel layout register
+//
+#define RED_MSB_POSITION 0x00
+#define RED_WIDTH_CNTL 0x01
+#define RED_DISPLAY_ENBL 0x02
+#define RED_BLINK_ENBL 0x03
+
+#define GREEN_MSB_POSITION 0x08
+#define GREEN_WIDTH_CNTL 0x09
+#define GREEN_DISPLAY_ENBL 0x0A
+#define GREEN_BLINK_ENBL 0x0B
+
+#define BLUE_MSB_POSITION 0x10
+#define BLUE_WIDTH_CNTL 0x11
+#define BLUE_DISPLAY_ENBL 0x12
+#define BLUE_BLINK_ENBL 0x13
+
+#define OVRLY_MSB_POSITION 0x18
+#define OVRLY_WIDTH_CNTL 0x19
+#define OVRLY_DISPLAY_ENBL 0x1A
+#define OVRLY_BLINK_ENBL 0x1B
+
+#define CURSOR_MSB_POSITION 0x20
+#define CURSOR_WIDTH_CNTL 0x21
+#define CURSOR_DISPLAY_ENBL 0x22
+#define CURSOR_BLINK_ENBL 0x23
+
+
+
+//
+// defines for access to control register 6 ( c bits = 110 )
+// use rDacPixelClks to access
+//
+#define TEST_REG1 0x00
+#define COMMAND_REG1 0x01
+#define DIGI_OUT_CNTL 0x02
+#define VIDCLK_CYCLE 0x03
+#define PIXEL_PLL_RATE0 0x05
+#define PIXEL_PLL_RATE1 0x06
+#define PLL_CONTROL 0x07
+#define PIXEL_LOAD_CNTL 0x08
+#define PIXEL_PORT_START 0x09
+#define PIXEL_FORMAT_CNTL 0x0A
+#define MPX_RATE_REG 0x0B
+#define SIG_ANLYS_REG 0x0C
+#define PIXEL_DEPTH_CNTL 0x0D
+#define PALETTE_BYPASS_POS 0x0E
+#define PALETTE_BYPASS_WIDTH 0x0F
+
+//
+// defines for access to control register 7 ( c bits = 111 )
+// use rRamDacCursor to access the cursor color register
+// NOTE: This register requires MODULO 3 loading and reading
+//
+#define CURSOR_CLR0 0x00
+#define CURSOR_CLR1 0x01
+#define CURSOR_CLR2 0x02
+#define CURSOR_CLR3 0x03
+
+/*
+**
+**.................... Bit Field Definitions........................
+**
+*/
+
+//
+// Command Register 0 bit masks:
+//
+#define USE_PALETTE 0x40 // use color palette not overlay color 0
+//
+// These defines cover TWO bits: bit positions 4 and 5
+//
+#define BLINK_16ON_48OFF 0x00
+#define BLINK_16ON_16OFF 0x10
+#define BLINK_32ON_32OFF 0x20
+#define BLINK_64ON_64OFF 0x30
+#define ENBL_OVRLY0_BLINK 0x04
+#define ENBL_OVRLY1_BLINK 0x08
+#define ENBL_OVRLY0_DSPLY 0x02
+#define ENBL_OVRLY1_DSPLY 0x01
+
+//
+// COMMAND_REG1: Bit fields
+//
+#define ENABLE_GREEN_SYNC 0x80 // generate sync on the IOG output
+#define IRE75_PEDESTAL 0x40 // generate a blank pedestal of 7.5 IRE
+#define NORMAL_POWER_OP 0x00 // normal operations ( i.e. no pwr dwn )
+#define PWR_OFF_DACS 0x08 // Turn off DACs. functionally still ops
+#define DAC_RAM_OFF 0x10 // Dac and Ram off: no functions out
+#define DAC_RAM_CLKS_OFF 0x18 // turn off clocks too
+#define RIGHT_JSTFY_PIXBITS 0x04 // right justify pixels and zero extend
+#define ENABLE_SIG_ANLYS 0x02 // turn on SAR
+#define RESET_PIPE_DEPTH 0x01
+
+// Pixel Timing Register: Field definitions:
+//
+
+/*
+** Pixel Format Control Fields ( PIXEL_FORMAT_CNTL register )
+**
+*/
+#define UNPACK_LSB_FIRST 0x80
+#define ENABLE_CURSOR 0x20
+#define ENABLE_CURSOR_COLOR0 0x10
+#define ENABLE_OVERLAY 0x08
+#define USE_COLOR_PALETTE 0x00
+#define BYPASS_COLOR_PALETTE 0x01
+#define USE_INPUT_PIXEL_FIELD 0x02
+
+/*
+** Pixel PLL Rate Register 0
+*/
+
+//
+// Prototype Declarations
+//
+
+VOID HalpSetupBt445( ULONG, ULONG );
+ULONG HalpSetPixelColorMap( ULONG Color, ULONG Pixel );
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpcpu.h b/private/ntos/nthals/halfire/ppc/fpcpu.h
new file mode 100644
index 000000000..9a18fbdaa
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpcpu.h
@@ -0,0 +1,179 @@
+
+/*
+ * Copyright (c) 1995. FirePower Systems, Inc.
+ * (Do Not Distribute without permission)
+ *
+ * $RCSfile: fpcpu.h $
+ * $Revision: 1.8 $
+ * $Date: 1996/05/14 02:32:23 $
+ * $Locker: $
+ *
+ */
+
+#ifndef FPCPU_h
+#define FPCPU_h
+
+//
+// These defines setup access to the power pc chip itself. Reliance upon the
+// defines will isolate code from power pc chip variations and ease migration
+// to new cpus
+//
+
+
+
+//
+// Since the documentation refers to the bit positions of the cpu fields in
+// IBM relative format, handle the conversion of IBM bit position to shift
+// arguments
+//
+#define WORD(x) (( 1 ) << ( 31 - x ))
+
+
+/*
+************************************************************************
+**
+** Machine State Register
+**
+************************************************************************
+*/
+//
+// pull a bit out of the MSR: this is based on IBM bit ordering as shown in
+// the powerpc books ( 0 == MSB )
+//
+
+// #define MSR(x) ( ( HalpReadMsr() >> ( 31 - x ) ) & 0x01 )
+#define MSR(x) ( ( __builtin_get_msr() >> ( 31 - x ) ) & 0x01 )
+
+#define POW 13 // Power Management Enable
+#define TGPR 14 // Temporary GPR remapping
+#define ILE 15 // Exception Little-endian mode
+#define EE 16 // External interrupt enable
+#define PR 17 // Privilege Level
+#define FP 18 // Floating Point Enable
+#define ME 19 // Machine Check Enable
+#define FE0 20 // Floating Point Exception mode 0
+#define SE 21 // single step trace enable
+#define BE 22 // Branch Trace Enable
+#define FE1 23 // floating point exception mode 1
+#define IP 25 // Exception Prefix ( exception vector is 0xff... ?
+#define IR 26 // Instruction Address Translation
+#define DR 27 // Data Address Translation
+#define RI 30 // Recoverable Exception
+#define LE 31 // Endian bit (little or big )
+
+//
+// setup Flags to go along with the MSR bits
+//
+#define ENABLE_PWR_MGMT WORD( POW )
+#define ENABLE_GPR_REMAP WORD( TGPR )
+#define EXCEPTION_LE WORD( ILE )
+#define ENABLE_EXTERNAL_INTS WORD( EE )
+#define EXEC_AT_USER_LEVEL WORD( PR )
+#define FLOAT_PT_AVAIL WORD( FP )
+#define ENABLE_MACHINE_CHK WORD( ME )
+#define FLOAT_EXCPT_MODE0 WORD( FE0 )
+#define ENABLE_SGL_STP_TRCE WORD( SE )
+#define ENABLE_BRNCH_TRCE WORD( BE )
+#define FLOAT_EXCPT_MODE1 WORD( FE1 )
+#define EXCPT_PREFX_0xFFF WORD( IP )
+#define ENABLE_INSTR_TRANS WORD( IR )
+#define ENABLE_DATA_TRANS WORD( DR )
+#define EXCPTION_IS_RECOVBL WORD( RI )
+#define RUN_LITTLE_ENDIAN WORD( LE )
+
+
+/*
+************************************************************************
+**
+** Processor Version Register
+**
+************************************************************************
+*/
+#define CPU_VERSION ( ( ( HalpReadProcessorRev ) & 0xffff0000 ) >> 16 )
+#define CPU_REVISION ( ( ( HalpReadProcessorRev ) & 0x0000ffff ) )
+
+
+/*
+************************************************************************
+**
+** Block Address Translation registers
+**
+************************************************************************
+*/
+//
+// Here are defines for the UPPER 32 bit bat register:
+//
+#define PAGE_INDEX_BITS 0xfffe0000
+#define BLK_EFF_PI(x) ( x & PAGE_INDEX_BITS )
+
+#define A_128K_BLOCK_SIZE 0x00000000
+#define A_256K_BLOCK_SIZE 0x00000004
+#define A_512K_BLOCK_SIZE 0x0000000c
+#define A_1MEG_BLOCK_SIZE 0x0000001c
+#define A_2MEG_BLOCK_SIZE 0x0000003c
+#define A_4MEG_BLOCK_SIZE 0x0000007c
+#define A_8MEG_BLOCK_SIZE 0x000000fc
+#define A_16MB_BLOCK_SIZE 0x000001fc
+#define A_32MB_BLOCK_SIZE 0x000003fc
+#define A_64MB_BLOCK_SIZE 0x000007fc
+#define A_128M_BLOCK_SIZE 0x00000ffc
+#define A_256M_BLOCK_SIZE 0x00001ffc
+
+#define SUPERVISOR_ONLY 0x00000002
+#define USER_ACCESS_VALID 0x00000001
+
+//
+// The Lower BAT Register
+//
+#define BLOCK_REAL_PAGE_NUMBER(x) ( (x >> 8) & REAL_BITS)
+
+//
+// WIMG: VIMVENDERS BITS:
+//
+#define WRITE_THROUGH 0x00000040
+#define CACHE_INHIBIT 0x00000020
+#define MEMORY_COHRNCY 0x00000010
+#define GUARDED_BLOCK 0x00000008 // for IBAT use only....
+
+#define PAGE_RW_ACCESS 0x00000002
+#define PAGE_RO_ACCESS 0x00000001
+#define PAGE_UNAVAILBL 0x00000000
+
+
+/*
+************************************************************************
+**
+** Hardware Implementation Register 0 ( HID0 )
+**
+************************************************************************
+*/
+
+#define EMCP 0 // Enable Machine Check Pin
+#define EBA 2 // Enable Bus Address Parity Checking
+#define EBD 3 // Enable Bus Data Parity Checking
+#define SBCLK 4 // selct bus clock for test clock pin
+#define EICE 5 // Enable ISE outputs: pipeline tracking support
+#define ECLK 6 // Enable external test clock pin
+#define PAR 7 // Disable precharge of ARTRY_L and shared signals
+#define DOZE 8 // Doze mode: pll, time base, and snooping active
+#define NAP 9 // Nap Mode: pll and time base active
+#define SLEEP 10 // Sleep mode: no external clock required
+#define DPM 11 // Enable Dynamic power management
+#define RISEG 12 // Reserved for test
+#define ICE 16 // Instruction cache enable
+#define DCE 17 // Data cache enable
+#define ILOCK 18 // lock instruction cache
+#define DLOCK 19 // lock data cache
+#define ICFI 20 // instruction cache flash invalidate
+#define DCI 21 // Data cache flash invalidate
+#define FBIOB 27 // Force branch indirect on bus
+#define NOOPTI 31 // No-op touch instructions
+
+#define ENABLE_ICACHE WORD( ICE )
+#define ENABLE_DCACHE WORD( DCE )
+#define LOCK_ICACHE WORD( ILOCK )
+#define LOCK_DCACHE WORD( DLOCK )
+#define INVLIDAT_ICACHE WORD( ICFI )
+#define INVLIDAT_DCACHE WORD( DCI )
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpcpu.s b/private/ntos/nthals/halfire/ppc/fpcpu.s
new file mode 100644
index 000000000..c052c9787
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpcpu.s
@@ -0,0 +1,387 @@
+//++
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxsystem.s
+//
+// Abstract:
+//
+// This module implements the routines to handle system functions:
+// Provides system specific info.
+// Currently provides processor version type
+//
+// Author:
+// breeze@firepower.com
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpcpu.s $
+ * $Revision: 1.12 $
+ * $Date: 1996/01/11 07:05:51 $
+ * $Locker: $
+ */
+
+#include "kxppc.h"
+#include "fpcpu.h"
+
+ .set BatValue, r.3
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// None
+//
+//
+// Return Value:
+// Processor Version register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpReadProcessorRev)
+ mfpvr r.3 // get processor version
+ LEAF_EXIT(HalpReadProcessorRev)
+
+
+
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// None
+//
+//
+// Return Value:
+// Machine State register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpGetStack)
+ or r3, r1, r1 // get stack value
+ LEAF_EXIT(HalpGetStack)
+
+
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// None
+//
+//
+// Return Value:
+// Machine State register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpReadMSR)
+ mfmsr r.3 // get processor version
+ LEAF_EXIT(HalpReadMSR)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadIbatUpper(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper instruction BAT value
+ for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+*****************************************************************************/
+
+ .set BatNumber, r.3
+
+ LEAF_ENTRY(HalpReadIbatUpper)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUI0
+ mfibatu BatNumber,0
+ b ExitUI
+NotUI0:
+ cmpli 0,0,BatNumber,1
+ bne NotUI1
+ mfibatu BatNumber,1
+ b ExitUI
+NotUI1:
+ cmpli 0,0,BatNumber,2
+ bne NotUI2
+ mfibatu BatNumber,2
+ b ExitUI
+NotUI2:
+ mfibatu BatNumber,3 // OK, it's three by default
+
+ExitUI:
+
+ LEAF_EXIT(HalpReadIbatUpper)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadIbatLower(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower instruction BAT value for given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpReadIbatLower)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLI0
+ mfibatl BatNumber,0
+ b ExitLI
+NotLI0:
+ cmpli 0,0,BatNumber,1
+ bne NotLI1
+ mfibatl BatNumber,1
+ b ExitLI
+NotLI1:
+ cmpli 0,0,BatNumber,2
+ bne NotLI2
+ mfibatl BatNumber,2
+ b ExitLI
+NotLI2:
+ mfibatl BatNumber,3 // OK, it's three by default
+
+ExitLI:
+
+ LEAF_EXIT(HalpReadIbatLower)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadDbatUpper(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpReadDbatUpper)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUD0
+ mfdbatu BatNumber,0
+ b ExitUD
+NotUD0:
+ cmpli 0,0,BatNumber,1
+ bne NotUD1
+ mfdbatu BatNumber,1
+ b ExitUD
+NotUD1:
+ cmpli 0,0,BatNumber,2
+ bne NotUD2
+ mfdbatu BatNumber,2
+ b ExitUD
+NotUD2:
+ mfdbatu BatNumber,3 // OK, it's three by default
+
+ExitUD:
+
+ LEAF_EXIT(HalpReadDbatUpper)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadDbatLower(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpReadDbatLower)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLD0
+ mfdbatl BatNumber,0
+ b ExitLD
+NotLD0:
+ cmpli 0,0,BatNumber,1
+ bne NotLD1
+ mfdbatl BatNumber,1
+ b ExitLD
+NotLD1:
+ cmpli 0,0,BatNumber,2
+ bne NotLD2
+ mfdbatl BatNumber,2
+ b ExitLD
+NotLD2:
+ mfdbatl BatNumber,3 // OK, it's three by default
+
+ExitLD:
+
+ LEAF_EXIT(HalpReadDbatLower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT3.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+
+ LEAF_ENTRY(HalpSetDbat3Lower)
+
+ mtdbatl 3,BatValue
+
+ LEAF_EXIT(HalpSetDbat3Lower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpSetDbat2Lower)
+
+ mtdbatl 2,BatValue
+
+ LEAF_EXIT(HalpSetDbat2Lower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpSetDbat1Lower)
+
+ mtdbatl 1,BatValue
+
+ LEAF_EXIT(HalpSetDbat1Lower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpSetDbat0Lower)
+
+ mtdbatl 0,BatValue
+
+ LEAF_EXIT(HalpSetDbat0Lower)
+
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpGetInstructionTimes()
+
+ Purpose:
+ run a 1024 instructions measure how long the cpu needs to
+ execute them ( measured by time base value which is 1/4 bus speed )
+
+ Algorithm:
+ string together 8 instructions so that they are dependent on their
+ preceding neighbor and loop through this set of 8 instructions 128
+ times. Compare the lower time base register's value before and after
+ this instruction run.
+
+ To guarentee correct timing, this routine waits for the lower time base
+ register to 'flip' to the new value and then start running the test
+ instructions. The run is done three times to make sure the entire
+ sequence is in L1 cache.
+
+ The Time Base runs at 1/4 bus speed so the number of instructions
+ that the cpu executes for a given amount of time is measured as
+ the amount of time required to run 1024 instructions. If the time
+ base changes by 256 'ticks' then the cpu is running at bus speed.
+
+ Returns: the incremental change in the time base lower register
+
+*****************************************************************************/
+
+ //.set LOOPCOUNT, 0x400 // 8 * real loop count (8 * 0x80 ).
+ .set LOOPCOUNT, 0x780 // 8 * real loop count (8 * 0x80 ).
+ LEAF_ENTRY(HalpGetInstructionTimes)
+
+ sync
+ andi. r10,r9,0 // zero r10: holds the current loop count
+ andi. r8,r9,0 // zero r8: holds the do again flag.
+ andi. r7,r9,0 // zero r7: execution time within each loop through
+ andi. r3,r9,0 // zero r3: maintain summation of execution times
+ andi. r9,r9,0 // zero r9: holds the current loop count
+ sync
+START: mftb r6 // save off the starting value of lower time
+ // base register
+CHECK: mftb r5 // check the time base again and see if it's just
+ // changed....
+ cmp 0,0,r5,r6
+ beq CHECK // wait for a new time period to start...
+
+ //
+ // Run through some single cycle instructions. In order to defeat
+ // the double issue pipes of the ppc, create a dependency between
+ // an instruction and the preceding instruction. This will more
+ // accurately reflect the amount of time the cpu uses to execute
+ // an instruction in a stream relative to the bus frequency.
+ //
+TIMES: addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+
+ cmpi 0,0,r9,LOOPCOUNT
+ bne TIMES // bc 4,2,TIMES
+ mftb r6 // save off ending value of lower time base register
+ sync
+ andi. r9,r9,0 // zero r9: in preparation for another pass
+ addi r8,r8,1 // increment the flag
+ cmpli 0,0,r8,2 // compare the flag to '2'. Ensure the last pass
+ // through is fully out of L1 cache.
+ blt START // to make sure we're in cache, branch back.
+ subf r3,r5,r6 // subtract r5 from r6 and store in r3 and return.
+
+ LEAF_EXIT(HalpGetInstructionTimes)
diff --git a/private/ntos/nthals/halfire/ppc/fpdcc.c b/private/ntos/nthals/halfire/ppc/fpdcc.c
new file mode 100644
index 000000000..33b5a175b
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpdcc.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpdcc.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/01/11 07:06:05 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the display controller chip
+ * known as the DCC. This chip control's vram setup and works in conjunction
+ * with the ram dac which, in this case is a Brooktree Bt485.
+ *
+ */
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpDcc.h"
+#include "fpbt445.h"
+
+VOID
+HalpSetupDCC(
+ ULONG Mode,
+ ULONG VramWidth
+ );
+/*++
+
+Routine Description: VOID HalpSetupDCC()
+
+ This routine initializes the display hardware for 640x480 in preparation
+ for HalDisplayString(). This means that either we are booting up or
+ dealing with the blue screen of death. We should really change this to
+ a higher resolution ASAP. [ged]
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpSetupDCC(
+ ULONG Mode,
+ ULONG VramWidth
+ )
+{
+ LONG modeIndex;
+ LONG i;
+
+ //
+ // DCC Config A
+ //
+ UCHAR configA[NUMBER_OF_VRAM_WIDTH_TYPES] = {
+ A_1to1_64BitDac | HSYNC_ENABLE | VSYNC_ENABLE | CSYNC_ENABLE,
+ A_1to1_64BitDac | HSYNC_ENABLE | VSYNC_ENABLE | CSYNC_ENABLE,
+ A_2to1_64BitDac | HSYNC_ENABLE | VSYNC_ENABLE | CSYNC_ENABLE
+ };
+
+ // [rdl:01.03.95]
+ typedef struct {
+ UCHAR reg;
+ UCHAR value;
+ } DCCTAB;
+
+ // [rdl:01.03.95]
+ DCCTAB DCCtab[3 /* 32/64/128 bit vram */][2 /* mode 0 or 15 */][13] = {
+ // 32 bit VRAM width
+ {
+ // [0] Mode 0 - 640X480 8 bit 72Hz
+ {
+ {HZNTL_COUNT_L,0xcf},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x07},
+ {VERT_COUNT_H,0x02},
+ {HZNTL_SYNC_STOP,0x09},
+ {HZNTL_BLK_STP_L,0x29},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0xc9},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x02},
+ {VERT_BLK_STOP,0x1e},
+ {VERT_DTA_STP_L,0xfe},
+ {VERT_DTA_STP_H,0x01}
+ },
+ // [1] Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {HZNTL_COUNT_L,0x4f},
+ {HZNTL_COUNT_H,0x01},
+ {VERT_COUNT_L,0x25},
+ {VERT_COUNT_H,0x03},
+ {HZNTL_SYNC_STOP,0x21},
+ {HZNTL_BLK_STP_L,0x49},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0x49},
+ {HZNTL_DTA_STP_H,0x01},
+ {VERT_SYNC_STOP,0x05},
+ {VERT_BLK_STOP,0x22},
+ {VERT_DTA_STP_L,0x22},
+ {VERT_DTA_STP_H,0x03},
+ }
+ },
+ // 64 bit VRAM width
+ {
+ // [0] Mode 0 - 640X480 8 bit 72Hz
+ {
+ {HZNTL_COUNT_L,0x67},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x07},
+ {VERT_COUNT_H,0x02},
+ {HZNTL_SYNC_STOP,0x04},
+ {HZNTL_BLK_STP_L,0x14},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0x64},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x02},
+ {VERT_BLK_STOP,0x1e},
+ {VERT_DTA_STP_L,0xfe},
+ {VERT_DTA_STP_H,0x01}
+ },
+ // [1] Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {HZNTL_COUNT_L,0xa7},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x25},
+ {VERT_COUNT_H,0x03},
+ {HZNTL_SYNC_STOP,0x10},
+ {HZNTL_BLK_STP_L,0x24},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0xa4},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x05},
+ {VERT_BLK_STOP,0x22},
+ {VERT_DTA_STP_L,0x22},
+ {VERT_DTA_STP_H,0x03},
+ }
+ },
+ // 128 bit VRAM width
+ {
+ // [0] Mode 0 - 640X480 8 bit 72Hz
+ {
+ {HZNTL_COUNT_L,0x67},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x07},
+ {VERT_COUNT_H,0x02},
+ {HZNTL_SYNC_STOP,0x04},
+ {HZNTL_BLK_STP_L,0x14},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0x64},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x02},
+ {VERT_BLK_STOP,0x1e},
+ {VERT_DTA_STP_L,0xfe},
+ {VERT_DTA_STP_H,0x01}
+ },
+ // [1] Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {HZNTL_COUNT_L,0xa7},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x25},
+ {VERT_COUNT_H,0x03},
+ {HZNTL_SYNC_STOP,0x10},
+ {HZNTL_BLK_STP_L,0x24},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0xa4},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x05},
+ {VERT_BLK_STOP,0x22},
+ {VERT_DTA_STP_L,0x22},
+ {VERT_DTA_STP_H,0x03},
+ }
+ }
+ };
+
+
+ //
+ // Disable all counters and state machines before we go messing around.
+ //
+ rDccIndex = dccConfigB;
+ FireSyncRegister();
+ rDccData = DCC_HALT_CLK;
+ FireSyncRegister();
+
+ HalpSetupBt445(Mode, VramWidth);
+
+ //
+ // Setup the DCC
+ //
+ rDccIndex = dccIntReg;
+ FireSyncRegister();
+ rDccData = 0x00; // Clear the interrupt bit ( bit 0 )
+ FireSyncRegister();
+
+ rDccIndex = dccTimingA;
+ FireSyncRegister();
+ rDccData = 0x07; // delay syncs by 7 DispClk cycles
+ FireSyncRegister();
+
+ rDccIndex = dccConfigA;
+ FireSyncRegister();
+ rDccData = configA[VramWidth];
+ FireSyncRegister();
+
+#define DCC_STORE(reg,val) { \
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + DCC_INDEX, reg); \
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + DCC_DATA, val); \
+}
+
+ // go table driven [rdl:01.03.95]
+ modeIndex = (Mode) ? 1 : 0; // if not mode 0, then make it mode 15.
+ for (i = 0; i < sizeof(DCCtab[0][0])/sizeof(DCCTAB); i++) {
+ DCCTAB tab = DCCtab[VramWidth][modeIndex][i];
+ DCC_STORE(tab.reg, tab.value);
+ }
+
+ rDccIndex = dccConfigB; // Turn on counters, *DO LAST*
+ FireSyncRegister();
+ rDccData = 0x00;
+ FireSyncRegister();
+
+ return;
+} // HalpSetupDCC
diff --git a/private/ntos/nthals/halfire/ppc/fpdcc.h b/private/ntos/nthals/halfire/ppc/fpdcc.h
new file mode 100644
index 000000000..09a27bc11
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpdcc.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * (Do Not Distribute without permission)
+ *
+ * $RCSfile: fpdcc.h $
+ * $Revision: 1.11 $
+ * $Date: 1996/01/11 07:06:16 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the display controller chip
+ * known as the DCC. This chip control's vram setup and works in conjunction
+ * with the ram dac which, in this case is a Brooktree Bt445.
+ *
+ */
+
+#ifndef FPDCC_H
+#define FPDCC_H
+
+//
+// Prototype declarations for routines in fpDcc.c
+
+
+// The dcc registers are not memory mapped but are indexed map through the
+// dcc Index register. To access any dcc specific register, write the register
+// value to the index register and either read or write data through the data
+// register. See fpio.h for the macros to write to these registers
+//
+// register and address offset
+//-----------------------------
+//
+#define dccIndex DCC_INDEX
+
+#define dccID 0x00 // ID register
+#define dccMonId 0x01 // Monitor and Panel ID
+#define dccGpioA 0x02 // General Purpose I/O register A
+#define dccIntReg 0x03 // Interrupt Status
+#define dccPLL 0x04 // PLL Interface Register
+#define dccTimingA 0x05 // Timing Register A
+#define dccConfigA 0x06 // Configuration Register A
+#define dccConfigB 0x07 // Configuration Register B
+#define dccHCntLow 0x08 // Hoizontal Count Low
+#define dccHCntHigh 0x09 // Hoizontal Count High
+#define dccVCntLow 0x0A // Vertical Count Low
+#define dccVCntHigh 0x0B // Vertical Count High
+#define dccHSyncStop 0x0C // Hoizontal Sync Stop
+#define dccHBlankStopLow 0x0D // Horizontal Blank Stop low
+#define dccHBlankStopHigh 0x0E // Horizontal Blank Stop High
+#define dccHDataStopLow 0x0F // Horizontal Data Stop Low
+#define dccHDataStopHigh 0x10 // Horizontal Data Stop High
+#define dccVSyncStop 0x11 // Vertical Sync Stop
+#define dccVBlankStop 0x12 // Vertical Blank Stop
+#define dccVDataStopLow 0x13 // Vertical Data Stop Low
+#define dccVDataStopHigh 0x14 // Vertical Data Stop High
+#define dccCSynicStartLow 0x15 // Composite Sync Start Low
+#define dccCSyncStartHigh 0x16 // Composite Sync Start High
+#define dccLineStart 0x17 // Line Start
+#define dccLineStop 0x18 // Line Stop
+#define dccFrameStart 0x19 // Frame Start
+#define dccFrameStop 0x1a // Frame Stop
+#define dccIntTriggerLow 0x1B // Interrupt Trigger Low
+#define dccIntTriggerHigh 0x1C // Interrupt Trigger High
+#define dccTimingB 0x1D // Timing Register B
+#define dccGpioB 0x1E // General Purpose I/O register B
+
+//
+// 0x1E - 0x3F reserved;
+//
+
+//
+// Inidividual bit mappings for register use:
+
+#define INT_BIT 0x01 // LSB of Interrupt Register: dccIntReg
+
+#define PLL_CLK 0x01 // PLL clock bit in Pll Interface: dccPLL
+#define PLL_DATA 0x02 // Data Bit for the PLL port.
+#define PLL_WnotR 0x04 // this bit activates the Pll data driver.
+
+#define HV_SYNC_DELAY 0x0f
+#define CSYNC_DELAY 0xf0
+
+//
+// Configuration Register A
+//
+#define HSYNC_ENABLE 0x01 // enable Horizontal Sync pulse
+#define VSYNC_ENABLE 0x02 // enable Vertical Sync pulse
+#define CSYNC_ENABLE 0x04 // enable Composite Sync pulse
+#define FRAME_ENABLE 0x08 // enable Frame pulse
+#define LINE_ENABLE 0x10 // enable Line pulse
+
+#define A_1to1_32BitDac 0x00 // 1:1 mux mode, frequency = DispClk
+#define AB_2to1_32BitDac 0x20 // 2:1 mux mode, frequency = 1/2DispClk
+#define A_1to1_64BitDac 0x80 // 1:1 mux, 64 bit Data width, f=DispClk
+#define A_2to1_32BitDac 0xA0 // 2:1 mux, 32 bit width, f=1/2(DispClk)
+#define A_2to1_64BitDac 0xC0 // 2:1 mux, 64 bit width, f=1/2(DispClk)
+#define A_4to1_32BitDac 0xE0 // 4:1 mux, 32 bit width, f=1/4(DispClk)
+
+//
+// Configuration Register B
+//
+#define HSYNC_ACTV_HIGH 0x01 // Active High state for Horizontal Sync
+#define VSYNC_ACTV_HIGH 0x02 // Active High state for Vertical Sync
+#define CSYNC_ACTV_HIGH 0x04 // Active High state for Composite Sync
+#define FRAME_ACTV_HIGH 0x08 // Active High state for Frame Pulse
+#define LINE_ACTV_HIGH 0x10 // Active High state for Line Pulse
+#define BLANK_ACTV_HIGH 0x20 // Active High state for Blanking Pulse
+#define DCC_HALT_CLK 0x80 // Disables and Resets all counters and state
+ // machines. Xbus interface is still active.
+
+// DCC Definitions
+#define INT_STATUS 0x03
+#define PLL_INTERFACE 0x04
+#define TIMING_A 0x05
+#define CONFIG_A 0x06
+#define CONFIG_B 0x07
+#define HZNTL_COUNT_L 0x08
+#define HZNTL_COUNT_H 0x09
+#define VERT_COUNT_L 0x0a
+#define VERT_COUNT_H 0x0b
+#define HZNTL_SYNC_STOP 0x0c
+#define HZNTL_BLK_STP_L 0x0d
+#define HZNTL_BLK_STP_H 0x0e
+#define HZNTL_DTA_STP_L 0x0f
+#define HZNTL_DTA_STP_H 0x10
+#define VERT_SYNC_STOP 0x11
+#define VERT_BLK_STOP 0x12
+#define VERT_DTA_STP_L 0x13
+#define VERT_DTA_STP_H 0x14
+#define GPIO_B 0x1e
+
+
+//
+// VRAM width list.
+//
+
+typedef enum _DCC_VRAM_WIDTH {
+ VRAM_32BIT = 0,
+ VRAM_64BIT,
+ VRAM_128BIT,
+ NUMBER_OF_VRAM_WIDTH_TYPES
+} DCC_VRAM_WIDTH;
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpdebug.h b/private/ntos/nthals/halfire/ppc/fpdebug.h
new file mode 100644
index 000000000..b39899b86
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpdebug.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpdebug.h $
+ * $Revision: 1.30 $
+ * $Date: 1996/01/11 07:06:23 $
+ * $Locker: $
+ */
+
+#ifndef _FPDEBUG_H
+#define _FPDEBUG_H
+
+#include "fpdcc.h" // to cover the led writing macro.....
+
+//
+// This file provides an interface that allows individual debug printfs
+// to be turned on and off in the HAL based on an environment variable.
+// It also provides a means for turning on/off debug functionality
+// (like auto stopping at a break point).
+//
+
+//
+// Externs for global variables stuffed at run-time
+// Default values are provided in sources files
+//
+#if defined(HALDEBUG_ON)
+extern int HalpDebugValue;
+#endif
+
+//
+// Macros used in C code to access the debug funcationality
+//
+
+//
+// Since DBG is always defined ( at least as of 2/6/95 ), must change the test
+// to look at the value of DBG
+//
+// #if !defined(DBG)
+// #if DBG != 1
+#if !defined(HALDEBUG_ON)
+#define HDBG(_value, _str)
+#define RDBG(_value, _str)
+#else
+#define DBGSET(_value) ((_value)&(HalpDebugValue))
+
+#define HDBG(_value, _str) \
+ { \
+ if (DBGSET(_value)) { \
+ _str; \
+ } \
+ }
+
+#endif
+
+//
+// Defines used in the C code for each of the values,
+// so someone can tell what bits to turn on.
+//
+// Note: behavioral changes are at the top portion of the word and
+// simple informational ones are at the bottom portion of the word.
+//
+#define DBG_GENERAL 0x00000001
+#define DBG_EXTERNAL 0x00000002
+#define DBG_INTERNAL 0x00000004
+#define DBG_INTERRUPTS 0x00000008
+#define DBG_DUMPTREE 0x00000010
+#define DBG_IPI 0x00000020
+#define DBG_DBAT 0x00000040
+#define DBG_REGISTRY 0x00000080
+#define DBG_DMA 0x00000100
+#define DBG_ISA 0x00000200
+#define DBG_MPINTS 0x00000400
+#define DBG_PCI 0x00000800
+#define DBG_DISPLAY 0x00001000
+#define DBG_I2C 0x00002000
+#define DBG_TIME 0x00004000
+
+#define DBG_BUS 0x04000000
+#define DBG_DISPMEMCOHERE 0x08000000
+#define DBG_DISPNOCACHE 0x10000000
+#define DBG_COLORS 0x20000000
+#define DBG_BREAK 0x40000000
+#define DBG_PROC1DBG 0x80000000
+
+#define PRNTGENRL(_str) HDBG(DBG_GENERAL, _str)
+#define PRNTINTR(_str) HDBG(DBG_INTERRUPTS, _str)
+#define PRNTPCI(_str) HDBG(DBG_PCI, _str)
+#define PRNTREE(_str) HDBG(DBG_DUMPTREE, _str)
+#define PRNTDISP(_str) HDBG(DBG_DISPLAY, _str)
+#define PRNTI2C(_str) HDBG(DBG_I2C, _str)
+#define PRNTTIME(_str) HDBG(DBG_TIME, _str)
+
+
+//
+// Assert macro definitions for the HAL - Checked/Debug Builds only
+//
+#if defined(HALDEBUG_ON)
+#define _assert_begin(_exp) \
+ ULONG holdit,ee,CpuId; \
+ ee = MSR(EE); \
+ HalpDisableInterrupts(); \
+ rScratchPad2 = 0xdeadbeef; \
+ FireSyncRegister(); \
+ CpuId = GetCpuId(); \
+ holdit = RInterruptMask(CpuId); \
+ RInterruptMask(CpuId) = 0x0; \
+ WaitForRInterruptMask(CpuId); \
+ HalpDebugPrint("HAssertion Failure at line %d in file %s\n", \
+ __LINE__, __FILE__); \
+ HalpDebugPrint("HAssertion: " #_exp "\n");
+
+
+#define _assert_end \
+ HalpDebugPrint("Calling Debugger\n"); \
+ DbgBreakPoint(); \
+ RInterruptMask(CpuId) = holdit; \
+ if (ee) { \
+ HalpEnableInterrupts(); \
+ } \
+
+#define HASSERT(_exp) \
+ if (!(_exp)) { \
+ _assert_begin(_exp); \
+ _assert_end; \
+ }
+
+
+#define HASSERTMSG(_exp, _msg) \
+ if (!(_exp)) { \
+ _assert_begin(_exp); \
+ HalpDebugPrint("HAssertion Message: %s\n", _msg); \
+ _assert_end; \
+ }
+
+#define HASSERTEXEC(_exp, _exec) \
+ if (!(_exp)) { \
+ _assert_begin(_exp); \
+ { \
+ _exec; \
+ } \
+ _assert_end; \
+ }
+
+
+#define SET_LEDS(DATA) \
+ rDccIndex = dccGpioA; \
+ FireSyncRegister(); \
+ rDccData = DATA; \
+ FireSyncRegister();
+
+#define GET_LEDS(DATA) \
+ rDccIndex = dccGpioA; \
+ FireSyncRegister(); \
+ DATA = rDccData;
+
+#define TURN_ON(x,y) \
+ GET_LEDS(x); \
+ SET_LEDS((x | 0xf0 ) & ~(x));
+
+#else // Free/Non-Debug Builds
+
+#define HASSERT(_exp)
+#define HASSERTEXEC(_exp, _msg)
+#define HASSERTMSG(_exp, _exec)
+#define SET_LEDS(DATA)
+#define GET_LEDS(DATA)
+#define TURN_ON(x,y)
+#endif // HALDEBUG_ON
+
+#endif // _FPDEBUG_H
diff --git a/private/ntos/nthals/halfire/ppc/fpds1385.c b/private/ntos/nthals/halfire/ppc/fpds1385.c
new file mode 100644
index 000000000..06cac0749
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpds1385.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpds1385.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/05/20 22:35:57 $
+ * $Locker: $
+ *
+ * fpds1385.c: set of routines to init, and maintain the DS1385
+ *
+ */
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpreg.h"
+#include "fpio.h" // pick up the io space register access macros
+#include "fpds1385.h" // defines specific to the dallas 1385
+
+#define DS1385_BAILOUT_COUNT 10
+
+UCHAR OriginalA; // storage location for rtc data in control reg a
+UCHAR OriginalB; // storage location for rtc data in control reg b
+BOOLEAN RtcBinaryMode = FALSE;
+ // Flag to indicate if RTC is programmed in BINHEX or
+ // BCD format
+
+BOOLEAN RtcFailure = FALSE;
+ // Flag to indicate if the RTC was read correctly
+BOOLEAN NvramFailure = FALSE;
+ // Flag to indicate if the NVRAM was read correctly
+ULONG TotalDs1385Failures = 0;
+ // Keep track of failures to read the DS1385
+/*
+ * HalpInitFireRTC:
+ *
+ * Make sure the dallas 1385 chip is correctly setup. This means that
+ * all the configuration bits are in place. If the chip is not correctly
+ * setup, save the time off, fix the bits, recalculate the time if needed,
+ * and restore the time. Particularly, if the "DataMode" or "24/12 hour"
+ * bits are changed the time will need to be recalculated.
+ */
+BOOLEAN
+HalpInitFirePowerRTC( VOID )
+{
+ TIME_FIELDS TimeFields;
+ UCHAR tval;
+ BOOLEAN Status = FALSE;
+ UCHAR ds1385Data;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpInitFirePowerRTC: begin \n"););
+ if ( !(HalQueryRealTimeClock( &TimeFields )) ) {
+ HalDisplayString("Not sure RTC is initted \n");
+ }
+
+ //
+ // Make sure the time is valid before worrying about any of the bits.
+ //
+ ds1385Data = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+ if ( ds1385Data & RTC_VRT ) {
+
+ //
+ // Verify that the DataMode is BCD
+ // the time style is 24 hour,
+ // that Daylight Savings is NOT enabled,
+ // that the square wave output is enabled.
+ //
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+ OriginalB = tval;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: register b is %x \n",
+ OriginalB););
+
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ RTC_24_HR |
+ //
+ // for consistency with firmware, setup the RTC
+ // to maintain the time in BCD format rather
+ // than binary
+ //
+ // RTC_BIN_MODE |
+ RTC_SQWE|
+ RTC_UIE |
+ RTC_PIE);
+
+ RtcBinaryMode = FALSE;
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERA);
+ OriginalA = tval;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: register a is %x\n",
+ OriginalA););
+
+ //
+ // Ensure the Oscillator is running and updating, not either
+ // stopped or counting but not updating.
+ //
+ if ((tval & ( RTC_DV1 | RTC_DV2 | RTC_DV0 )) != RTC_DV1 ) {
+ tval = RTC_DV1;
+ }
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERA, (UCHAR)(tval | RTC_4096_HZ));
+
+ //
+ // Clear the interrupt flag bits
+ //
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERC);
+
+ //
+ // Finally, restore the time: HalSetRealTimeClock will take
+ // care of any BCD=BIN conversion necessary.
+ //
+ if ( HalSetRealTimeClock ( &TimeFields)) {
+ Status=TRUE;
+ }
+
+ } else {
+
+ HalDisplayString("RTC Time is invalid: battery is dead?\n");
+ }
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: end \n"););
+ return(Status);
+}
+
+
+//
+// write a byte to the specified DS1385 register.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the write
+// Finally, release the spinlock.
+//
+VOID
+HalpDS1385WriteReg(UCHAR reg, UCHAR value)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; after writing the DS1385 regiser, we
+ // read it back 3 times - if
+ // one of the three values compares with the value written, we are
+ // done. If we do not get a comparison, throw all three values away and
+ // try the write
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ // Write the register
+ rIndexRTC = reg;
+ FireSyncRegister();
+ rDataRTC = value;
+ // make sure access to the chip is complete before releasing
+ // the spin lock
+ FireSyncRegister();
+
+ // Read it three times
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data0 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data1 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data2 = rDataRTC;
+
+ if ((data0 == value) || (data1 == value) || (data2 == value)) {
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ RtcFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+}
+
+//
+// read a byte from the specified DS1385 register.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the read
+// Finally, release the spinlock.
+//
+UCHAR
+HalpDS1385ReadReg(UCHAR reg)
+{
+ KIRQL OldIrql;
+ UCHAR result = 0xff;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; read the DS1385 register 3 times - if
+ // one of the three values compares with either of the other two, return
+ // it. If we do not get a comparison, throw all three values away and try
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data0 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data1 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data2 = rDataRTC;
+
+ if ((data0 == data1) || (data0 == data2)) {
+ result = data0;
+ break;
+ }
+ if (data1 == data2) {
+ result = data1;
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ RtcFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+ return result;
+}
+
+//
+// write a byte to the specified address in the DS1385 NVRAM.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the write
+// Finally, release the spinlock.
+//
+VOID
+HalpDS1385WriteNVRAM(USHORT addr, UCHAR value)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; after writing the DS1385 regiser, we
+ // read it back 3 times - if
+ // one of the three values compares with the value written, we are
+ // done. If we do not get a comparison, throw all three values away and
+ // try the write
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ // Write the register
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ rNvramData = value;
+ // make sure access to the chip is complete before releasing
+ // the spin lock
+ FireSyncRegister();
+
+ // Read the register three times
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data0 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data1 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data2 = rNvramData;
+
+ if ((data0 == value) || (data1 == value) || (data2 == value)) {
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ NvramFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+}
+
+
+//
+// read a byte from the specified address in the DS1385 NVRAM.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the read
+// Finally, release the spinlock.
+//
+UCHAR
+HalpDS1385ReadNVRAM(USHORT addr)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ UCHAR result = 0xff;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; read the DS1385 register 3 times - if
+ // one of the three values compares with either of the other two, return
+ // it. If we do not get a comparison, throw all three values away and try
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data0 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data1 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data2 = rNvramData;
+
+ if ((data0 == data1) || (data0 == data2)) {
+ result = data0;
+ break;
+ }
+ if (data1 == data2) {
+ result = data1;
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ NvramFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+ return result;
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/fpds1385.h b/private/ntos/nthals/halfire/ppc/fpds1385.h
new file mode 100644
index 000000000..6c41e0e63
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpds1385.h
@@ -0,0 +1,213 @@
+/*
+** fpds1385.h header file definitions for the dallas 1385 chip.
+** This chip is functionally equivalent to the 1387.
+**
+**
+** 1385 features:
+** counts seconds, miniutes, hours, days, day of the week, date, month
+** and year with leap year compensation
+**
+** Binary or BCD representation of time, calendar, and alarm
+**
+** 12 or 24 hour clock with AM and PM in 12 hour mode
+**
+** daylight savings time op[tino
+**
+** selectable between motorola and intel bus timing
+**
+** programmable square wave output
+**
+** bus compatible interrupt signals ( ~IRQ )
+**
+** three interrupts are separately software maskable and testable:
+** time of day alarm ( once/second to once/day )
+** periodic rates from 122 uA to 500 ms
+** end of clock update cycle
+**
+** 4k X 8 NVRAM ( nonvolatile over 10 years ).
+**
+**
+** note: this file created with tab stops of 8 spaces
+** c.f. Dallas data book for 1992-1993, pp 6-129, 6-147
+*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpds1385.h $
+ * $Revision: 1.8 $
+ * $Date: 1996/05/14 02:32:34 $
+ * $Locker: $
+ */
+
+
+#ifndef FPDS1385
+#define FPDS1385
+
+typedef struct _RTC_CONTROL {
+ UCHAR Reserved0[0x71];
+ UCHAR RtcData; // Offset 0x71
+} RTC_CONTROL, *PRTC_CONTROL;
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x72];
+ UCHAR NvramIndexLo; // Offset 0x72
+ UCHAR Reserved1[2];
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_BATTERY_BACKED_UP_RAM 14 // battery backed up RAM [0..49]
+
+
+/*
+ ***********************************************************************
+**
+** The registers used for the indexing:
+**
+*/
+
+//
+// time....
+//
+#define SECONDS 0x00
+#define MINUTES 0x02
+#define HOURS 0x04
+
+//
+// calendar....
+//
+#define DAY_O_WEEK 0x06
+#define DAY_O_MONTH 0x07
+#define MONTH 0x08
+#define YEAR 0x09
+
+//
+// and the alarm bits
+//
+#define ALARM_secs 0x01
+#define ALARM_mins 0x03
+#define ALARM_hrs 0x05
+
+//
+// registers
+//
+#define RegA 0x0A
+#define RegB 0x0B
+#define RegC 0x0C
+#define RegD 0x0D
+
+/*
+ ***********************************************************************
+**
+** Register BIT definitions
+**
+*/
+
+//
+// Register A
+//
+#define RTC_UIP 0x80
+#define RTC_DV2 0x40
+#define RTC_DV1 0x20
+#define RTC_DV0 0x10
+
+//
+// these defines spec a set of 4 bits at a time. Each set defines an output
+// frequency
+//
+// Period in ms Frequency in hz
+#define RTC_DC__ 0x00 // no output wave
+#define A_0256_HZ 0x01 // 3.90625 256 dup
+#define A_0128_HZ 0x02 // 7.8125 128 dup
+#define RTC_8192_HZ 0x03 // .122070 8192
+#define RTC_4096_HZ 0x04 // .244141 4096
+#define RTC_2048_HZ 0x05 // .488281 2048
+#define RTC_1024_HZ 0x06 // .9765625 1024
+#define RTC_0512_HZ 0x07 // 1.953125 512
+#define RTC_0256_HZ 0x08 // 3.90625 256
+#define RTC_0128_HZ 0x09 // 7.8125 128
+#define RTC_0064_HZ 0x0A // 15.625 64
+#define RTC_0032_HZ 0x0B // 31.25 32
+#define RTC_0016_HZ 0x0C // 62.5 16
+#define RTC_0008_HZ 0x0D // 125 8
+#define RTC_0004_HZ 0x0E // 250 4
+#define RTC_0002_HZ 0x0F // 500 2
+
+
+//
+// Register B
+//
+#define RTC_SET 0x80 // set bit: 0=> allow update, 1=> block update
+#define RTC_PIE 0x40 // periodic interrupt enable
+#define RTC_AIE 0x20 // alarm interrupt enable
+#define RTC_UIE 0x10 // update ended interrupt enable
+#define RTC_SQWE 0x08 // sqaure wave enable
+#define RTC_BIN_MODE 0x04 // data mode set to Binary ( Not Coded Decimal )
+#define RTC_24_HR 0x02 // 24 or 12 hour mode
+#define RTC_DSE 0x01 // daylight savings enable
+
+//
+// Register C ( bits [3:0] are reserved by dallas, read as 0 )
+//
+
+#define RTC_IRQF 0x80 // interrupt request flag
+#define RTC_PF 0x40 // periodic interrupt flag
+#define RTC_AF 0x20 // alarm interrupt flag
+#define RTC_UF 0x10 // update endend interrupt flag
+
+
+//
+// Register D: ( only bit 7 is defined at present )
+//
+
+#define RTC_VRT 0x80 // valid ram and time
+
+
+//
+// the ds1385 chip requires multiple accesses to read or write
+// information. To make sure tose accesses are done atomically,
+// the following spinlock must be held. It is initialized in
+// pxinithl.c
+extern KSPIN_LOCK HalpDS1385Lock;
+//
+// Reading and Writing the time to the RTC takes several accesses
+// to the chip to synchronize those actions, the following spin
+// lock must be held. Using the chip's spin lock above is not
+// necessary because accesses to the chip's registers can be
+// intermixed with the chip's nvram. This lock is initialized in
+// pxinithl.c
+extern KSPIN_LOCK HalpRTCLock;
+/*
+**
+** PROTOTYPE declarations for the c-code
+**
+*/
+
+BOOLEAN HalpInitFirePowerRTC( VOID );
+
+VOID HalpDS1385WriteReg(UCHAR reg, UCHAR value);
+UCHAR HalpDS1385ReadReg(UCHAR reg);
+VOID HalpDS1385WriteNVRAM(USHORT addr, UCHAR value);
+UCHAR HalpDS1385ReadNVRAM(USHORT addr);
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpi2c.c b/private/ntos/nthals/halfire/ppc/fpi2c.c
new file mode 100644
index 000000000..d352d93f0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpi2c.c
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpi2c.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/03/05 02:15:54 $
+ * $Locker: $
+ */
+/* fpi2c.c - FirePower I2C (I squared C) */
+#include "halp.h"
+#include "phsystem.h"
+#include "pxmemctl.h"
+#include "fpdebug.h"
+#include "fpio.h"
+#include "phsystem.h"
+#include "fpi2csup.h"
+#include "pxpcisup.h"
+#include "fpcpu.h"
+
+extern VOID
+HalpSetValueKeyString(HANDLE key, PCHAR nameBuffer, PCHAR dataBuffer);
+
+/* defines */
+
+#define I2CBUS_TIMEOUT 1000
+#define I2CBUS_MAXROMSIZE 0x80
+#define I2CBUS_CONTROLLER 0x8E0
+#define I2C8584S0 0x8E0
+#define I2C8584S1 0x8E1
+#define rI2C8584S0 _IOREG( I2CBUS_CONTROLLER )
+#define rI2C8584S1 _IOREG( I2CBUS_CONTROLLER + 1)
+
+#define SLAVE_ADDRESS_WRITE(address) (UCHAR)(0xa0|(address << 1))
+#define SLAVE_ADDRESS_READ(address) (UCHAR)(0xa1|(address << 1))
+
+/* control register S1 */
+#define S1_PIN 0x80
+#define S1_ES0 0x40
+#define S1_ES1 0x20
+#define S1_ES2 0x10
+#define S1_ENI 0x08
+#define S1_STA 0x04
+#define S1_STO 0x02
+#define S1_ACK 0x01
+
+/* status register S1 */
+#define S1_STS 0x20
+#define S1_BER 0x10
+#define S1_LRB 0x08
+#define S1_AAS 0x04
+#define S1_LAB 0x02
+#define S1_BB 0x01
+
+// Interrupt Info from the IIC
+struct PAIRS IntPairTable[MAXIMUM_PCI_SLOTS];
+extern UCHAR PciDevicePrimaryInts[];
+
+extern ULONG CpuClockMultiplier;
+extern ULONG ProcessorBusFrequency;
+
+/* prototypes */
+static VOID Write8584S0(UCHAR byte);
+static VOID Write8584S1(UCHAR byte);
+
+static UCHAR Read8584S0(VOID);
+static UCHAR Read8583S1(VOID);
+
+/* HAL does not initialize I2C. Firmware does it
+BOOLEAN
+HalpInitializeI2C()
+{
+}
+*/
+
+static VOID i2c_delay(VOID)
+{
+ UCHAR byte;
+// KeStallExecutionProcessor(1000); /* 1000 us */
+ // Chip Select Signal must be changed.
+ byte = 0x00;
+ WRITE_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + 0x80, byte);
+}
+
+static VOID Write8584S0(UCHAR byte)
+{
+ WRITE_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S0, byte);
+ i2c_delay();
+}
+
+static VOID Write8584S1(UCHAR byte)
+{
+ WRITE_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S1, byte);
+ i2c_delay();
+}
+
+static UCHAR Read8584S0(VOID)
+{
+ UCHAR byte;
+ byte = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S0);
+ i2c_delay();
+ return byte;
+}
+
+static UCHAR Read8584S1(VOID)
+{
+ UCHAR byte;
+ byte = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S1);
+ i2c_delay();
+ return byte;
+}
+
+BOOLEAN I2CWaitForPin(VOID)
+{
+ UCHAR byte;
+ int timeout = I2CBUS_TIMEOUT;
+
+ //PRNTI2C(HalpDebugPrint("I2CWaitForPin starts...\n"));
+
+ while (timeout-- > 0) {
+ if (((byte = Read8584S1()) & S1_PIN) == 0x00) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOLEAN I2CWaitForAck(VOID)
+{
+ UCHAR byte;
+ int timeout = I2CBUS_TIMEOUT;
+
+ //PRNTI2C(HalpDebugPrint("I2CWaitForAck starts...\n"));
+ while (timeout-- > 0) {
+ if (((byte = Read8584S1()) & S1_PIN) == 0x00) {
+ break;
+ }
+ }
+ if (timeout <= 0) return FALSE;
+ if (byte & S1_LRB) return FALSE;
+ else return TRUE;
+}
+
+BOOLEAN I2CWaitWhileBusBusy(VOID)
+{
+ int timeout = I2CBUS_TIMEOUT;
+ UCHAR byte;
+
+ //PRNTI2C(HalpDebugPrint("I2CWaitWhileBusBusy starts...\n"));
+ while (timeout-- > 0) {
+ if (((byte = Read8584S1()) & S1_BB) != 0x00)
+ break;
+ }
+ if (timeout <= 0) return FALSE;
+ return TRUE;
+}
+
+VOID I2CStart(VOID)
+{
+ Write8584S1(0xc5);
+}
+
+VOID I2CRestart(VOID)
+{
+ Write8584S1(0x45);
+}
+
+VOID I2CPutByte(UCHAR byte)
+{
+ Write8584S0(byte);
+}
+
+VOID I2CDummyRead(VOID)
+{
+ UCHAR dummy;
+ dummy = Read8584S0();
+}
+
+UCHAR I2CGetByte(VOID)
+{
+ return Read8584S0();
+}
+
+VOID I2CStop(VOID)
+{
+ Write8584S1(0xc3);
+}
+
+VOID I2CNotAck(VOID)
+{
+ Write8584S1(0x40);
+}
+
+BOOLEAN HalpI2CPutByte(UCHAR address, UCHAR index, UCHAR byte)
+{
+ BOOLEAN bResult;
+
+ bResult = I2CWaitWhileBusBusy();
+ if (bResult == FALSE) return FALSE;
+
+ I2CPutByte(SLAVE_ADDRESS_WRITE(address)); // to write slave address and index
+ I2CStart();
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ //KeStallExecutionProcessor(10000); /* 10 ms */
+ return FALSE;
+ }
+
+ I2CPutByte(index);
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ //KeStallExecutionProcessor(10000); /* 10 ms */
+ return FALSE;
+ }
+ I2CPutByte(byte);
+ I2CWaitForPin();
+ I2CStop();
+ KeStallExecutionProcessor(10000); /* 10 ms */
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetByte(UCHAR address, UCHAR index, PUCHAR buf)
+{
+ BOOLEAN bResult;
+
+ bResult = I2CWaitWhileBusBusy();
+ if (bResult == FALSE) return FALSE;
+
+ I2CPutByte(SLAVE_ADDRESS_WRITE(address)); // to write slave address and index
+ I2CStart();
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ I2CDummyRead();
+ return FALSE;
+ }
+
+ I2CPutByte(index);
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ I2CDummyRead();
+ return FALSE;
+ }
+
+ I2CRestart();
+ I2CPutByte(SLAVE_ADDRESS_READ(address)); // to read
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ I2CDummyRead();
+ return FALSE;
+ }
+
+ I2CDummyRead();
+ I2CWaitForPin();
+ I2CNotAck();
+ *buf = I2CGetByte();
+ I2CWaitForPin();
+ I2CStop();
+ I2CDummyRead();
+ return TRUE;
+}
+
+VOID
+HalpDumpI2CEEPROM(VOID)
+{
+ UCHAR address = 0;
+ UCHAR i;
+ static UCHAR uc;
+ BOOLEAN bResult;
+
+ PRNTI2C(DbgPrint("HalpDumpI2CEEPROM starts...&I2C8584S0=0x%x &I2C8584S1=0x%x\n",
+ ((PUCHAR)HalpIoControlBase) + I2C8584S0,
+ ((PUCHAR)HalpIoControlBase) + I2C8584S1));
+ PRNTI2C(DbgPrint("--- I2C address 0 -----------------------------\n"));
+ PRNTI2C(DbgPrint("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"));
+ PRNTI2C(DbgPrint("-----------------------------------------------\n"));
+
+ for (i = 0; i < 128; i++) {
+ bResult = HalpI2CGetByte(address, i, &uc);
+ if (bResult == FALSE) {
+ PRNTI2C(DbgPrint("HalpI2CGetByte(%d) failed.\n", i));
+ } else {
+ PRNTI2C(DbgPrint("%02x", uc));
+ }
+ if ((i%16) == 15) {
+ PRNTI2C(DbgPrint("\n"));
+ } else {
+ PRNTI2C(DbgPrint(" "));
+ }
+ }
+
+ PRNTI2C(DbgPrint("--- I2C address 1 -----------------------------\n"));
+ PRNTI2C(DbgPrint("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"));
+ PRNTI2C(DbgPrint("-----------------------------------------------\n"));
+
+ address = 1;
+ for (i = 0; i < 128; i++) {
+ bResult = HalpI2CGetByte(address, i, &uc);
+ if (bResult == FALSE) {
+ PRNTI2C(DbgPrint("HalpI2CGetByte(%d) failed.\n", i));
+ } else {
+ PRNTI2C(DbgPrint("%02x", uc));
+ }
+ if ((i%16) == 15) {
+ PRNTI2C(DbgPrint("\n"));
+ } else {
+ PRNTI2C(DbgPrint(" "));
+ }
+ }
+}
+
+BOOLEAN HalpGetI2CSignature(PULONG pSignature)
+{
+ ULONG ul;
+ PUCHAR p = (PUCHAR)&ul;
+ UCHAR address = 0;
+ UCHAR index = 0;
+
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index, p);
+
+ *pSignature = ul;
+ return TRUE;
+}
+
+BOOLEAN HalpGetI2CItemDescriptor(PUCHAR p)
+{
+ UCHAR address = 0;
+ UCHAR index = sizeof(META);
+
+ PRNTI2C(HalpDebugPrint("index=%d 0x%x ", index, index));
+
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ *p = 0x00;
+
+ return TRUE;
+}
+
+BOOLEAN HalpGetI2CBoardRev(PUCHAR p)
+{
+ UCHAR address = 0;
+ UCHAR index = sizeof(META) + 2*sizeof(UCHAR);
+
+
+ PRNTI2C(HalpDebugPrint("index=%d 0x%x ", index, index));
+
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ *p = 0x00;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetUshort(UCHAR address, UCHAR index, PUSHORT pus)
+{
+ BOOLEAN bResult = FALSE;
+ PUCHAR p = (PUCHAR)pus;
+
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetUlong(UCHAR address, UCHAR index, PULONG pul)
+{
+ BOOLEAN bResult = FALSE;
+ PUCHAR p = (PUCHAR)pul;
+
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index, p);
+ if (bResult == FALSE) return FALSE;
+ return TRUE;
+}
+
+// OR together the sturcture types for this IIC address and return it as a
+// flag. NOTA BENA: we intercept known non-IIC platforms and return a special
+// cased result.
+ULONG FindDataTypes(UCHAR address, SYSTEM_TYPE System)
+{
+ int index = 0;
+ ULONG datatype;
+ ULONG FoundTypes = 0;
+ UCHAR offset;
+ BOOLEAN bResult = FALSE;
+
+ // The ES and MX (non-IIC) platforms are special cased
+ if ((System == SYS_POWERTOP) || (System == SYS_POWERPRO)) {
+ if (address == 0) {
+ FoundTypes = SYS_DATA;
+ }
+ return FoundTypes;
+ }
+
+ while (index < I2CBUS_MAXROMSIZE) {
+ bResult = HalpI2CGetUlong(address, (UCHAR)index, &datatype);
+ if ((bResult == FALSE) || (datatype == EMPTY_DATA)) {
+ break;
+ }
+ FoundTypes |= datatype;
+ HalpI2CGetByte(address, (UCHAR)(index+sizeof(ULONG)), &offset);
+ if (offset == 0) {
+ break;
+ }
+ index += offset;
+ }
+
+ return FoundTypes;
+}
+
+UCHAR I2CFindIndexOf(UCHAR address, ULONG datatype_wanted)
+{
+ int index = 0;
+ ULONG datatype;
+ UCHAR offset;
+ BOOLEAN bResult = FALSE;
+
+ while (index < I2CBUS_MAXROMSIZE) {
+ bResult = HalpI2CGetUlong(address, (UCHAR)index, &datatype);
+ if (bResult == FALSE) {
+ //DbgPrint("FindIndexOf failed\n");
+ return 0;
+ }
+ //DbgPrint("I2CFindIndexOf: address=%d datatype_wanted=0x%08x index=0x%02x datatype=0x%08x\n", address, datatype_wanted, index, datatype);
+ if (datatype == datatype_wanted) return index;
+ if (datatype == EMPTY_DATA) return 0;
+
+ HalpI2CGetByte(address, (UCHAR)(index+sizeof(ULONG)), &offset);
+ if (offset == 0) return 0;
+ index += offset;
+ }
+ //DbgPrint("FindIndexOf could not find key (0x%08x).\n", datatype_wanted);
+ return 0;
+}
+
+BOOLEAN HalpDoesI2CExist(UCHAR address)
+{
+ ULONG ul;
+ UCHAR index = 5;
+ BOOLEAN bResult = FALSE;
+
+#if DBG
+{
+ static BOOLEAN firsttime = TRUE;
+ if (firsttime) {
+ HalpDumpI2CEEPROM();
+ firsttime = FALSE;
+ }
+}
+#endif
+ bResult = HalpI2CGetUlong(address, index, &ul);
+ if (bResult == FALSE) return FALSE;
+
+ if (ul == CURRENT_SIGNATURE) return TRUE;
+ return FALSE;
+}
+
+BOOLEAN HalpI2CGetSystem(SYSTEM_TYPE *psystemtype)
+{
+ UCHAR address = 0;
+ UCHAR index;
+ UCHAR system;
+
+ PRNTI2C(DbgPrint("HalpI2CGetSystem starts...\n"));
+ if (HalpDoesI2CExist(address) == FALSE) {
+ PRNTI2C(DbgPrint("HalpDoesI2CExist returned FALSE.\n"));
+ *psystemtype = SYS_UNKNOWN;
+ return FALSE;
+ }
+ if ((index = I2CFindIndexOf(address, SYS_DATA)) == 0) {
+ *psystemtype = SYS_UNKNOWN;
+ return FALSE;
+ }
+ index += sizeof(ULONG) + sizeof(UCHAR);
+ HalpI2CGetByte(address, index, &system);
+ if (system == LX_SYSTEM) {
+ *psystemtype = SYS_POWERSLICE;
+ return TRUE;
+ }
+ if (system == MX_SYSTEM) {
+ *psystemtype = SYS_POWERTOP;
+ return TRUE;
+ }
+ if (system == TX_SYSTEM) {
+ *psystemtype = SYS_POWERSERVE;
+ return TRUE;
+ }
+ if (system == TX_PROTO) {
+ *psystemtype = SYS_POWERSERVE;
+ return TRUE;
+ }
+
+ // We found a system type so we need to return TRUE; since we do not
+ // recognize it, make it unknown.
+ *psystemtype = SYS_UNKNOWN;
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetBoard(UCHAR address, BOARD *pb)
+{
+ UCHAR index;
+ UCHAR uc;
+ USHORT us;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, BOARD_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartType[0] = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartType[1] = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartRev[0] = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartRev[1] = uc;
+ index++;
+
+ HalpI2CGetUlong(address, index, &ul);
+ pb->BoardNumber = ul;
+ index += 4;
+
+ HalpI2CGetUshort(address, index, &us);
+ pb->Version = us;
+ index += 2;
+
+ {
+ int i;
+ for (i = 0; i < 8; i++) {
+ HalpI2CGetByte(address, index, &uc);
+ pb->SerialNumber[i] = uc;
+ index++;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetProcessor(UCHAR address, PROCESSOR *p)
+{
+ UCHAR index;
+ UCHAR uc;
+
+ if ((index = I2CFindIndexOf(address, CPU_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->Total = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->BusFrequency = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->TenXFactor = uc;
+ index++;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetCache(UCHAR address, CACHE *p)
+{
+ UCHAR index;
+ UCHAR uc;
+ USHORT us;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, CACHE_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->MaxSets = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->Bytes2Line = uc;
+ index++;
+
+ HalpI2CGetUshort(address, index, &us);
+ p->Lines2Set = us;
+ index += 2;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->SramBanks = uc;
+ index++;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->Performance = ul;
+ index += 4;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->MaxSize = ul;
+ index += 4;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->Properties = ul;
+ index += 4;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetDRAM(UCHAR address, MEMORY *p)
+{
+ UCHAR index;
+ UCHAR uc;
+ USHORT us;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, DRAM_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->BaseAddress = ul;
+ index += 4;
+
+ HalpI2CGetUshort(address, index, &us);
+ p->MaxBankSize = us;
+ index += 2;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->MaxNumBanks = uc;
+ index ++;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetBus(UCHAR address, BUS *p)
+{
+ UCHAR index;
+ UCHAR uc;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, BUS_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->NumIoBus = uc;
+ index++;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->ConfigAddr = ul;
+ index += 4;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetIntsTotal(UCHAR address, UCHAR *p)
+{
+ UCHAR index;
+ UCHAR uc;
+
+ if ((index = I2CFindIndexOf(address, INT_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ *p = uc;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetIntsAPair(UCHAR address, UCHAR i, struct PAIRS *p)
+{
+ UCHAR index;
+ UCHAR uc;
+
+ if ((index = I2CFindIndexOf(address, INT_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ index += sizeof(UCHAR) + i * (sizeof(UCHAR)*2);
+
+ HalpI2CGetByte(address, index, &uc);
+ p->Int = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->SlotNumber = uc;
+ index++;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetInterrupt()
+{
+ UCHAR address = 0; // Id of the MLB I2c
+ UCHAR size;
+ UCHAR entry;
+ struct PAIRS *IntPairs = &IntPairTable[0];
+ UCHAR slot;
+
+ // Does the MLB I2C exist?
+ if (HalpDoesI2CExist(address) == FALSE) {
+ return FALSE;
+ }
+
+ // Is there an interrupt structure on the MLB?
+ if (HalpI2CGetIntsTotal(address, &size) == FALSE) {
+ return FALSE;
+ }
+
+ // Initialize the interrupt pairs table
+ for (entry = 0; entry < MAXIMUM_PCI_SLOTS; entry++) {
+ IntPairTable[entry].Int = INVALID_INT;
+ IntPairTable[entry].SlotNumber = INVALID_SLOTNUMBER;
+ }
+
+ // Now fill up the IntPair table from the IIC upto MaxSize entries;
+ // should size > MaxSize be an error?
+ if (size > MAXIMUM_PCI_SLOTS) size = MAXIMUM_PCI_SLOTS;
+ if (size == 0) return FALSE;
+
+ for (entry = 0; entry < size; entry++) {
+ if (HalpI2CGetIntsAPair(address, entry, IntPairs) == FALSE) {
+ return FALSE;
+ }
+ IntPairs++;
+ }
+
+ for (entry = 0; entry < size; entry++) {
+ slot = IntPairTable[entry].SlotNumber;
+ if (slot < MAXIMUM_PCI_SLOTS) {
+ PciDevicePrimaryInts[slot] = IntPairTable[entry].Int;
+ }
+ }
+
+ return TRUE;
+}
+
+// Fill in the registry info for the IIC at the passed in address.
+// NOTE BENA: we intercept non-IIC platforms and special case the data.
+BOOLEAN HalpFillUpRegistryForIIC(HANDLE key, UCHAR address, SYSTEM_TYPE System)
+{
+ BOOLEAN bStatus;
+ BOARD board;
+ PROCESSOR cpu;
+ MEMORY memory;
+ BUS bus;
+ UCHAR numInts;
+ struct PAIRS DefaultPair[4];
+ BOOLEAN NonIIC = FALSE;
+ CCHAR buffer[64];
+
+ // Set up default values for all of the structures to assist in filling
+ // out the registry for non-IIC platforms
+ board.PartType[0] = 'N';
+ board.PartType[1] = 'A';
+ board.PartRev[0] = 'N';
+ board.PartRev[1] = 'A';
+ board.BoardNumber = 0;
+ board.Version = 0;
+ board.SerialNumber[0] = '-';
+ board.SerialNumber[1] = '-';
+ board.SerialNumber[2] = ' ';
+ board.SerialNumber[3] = 'N';
+ board.SerialNumber[4] = 'A';
+ board.SerialNumber[5] = ' ';
+ board.SerialNumber[6] = '-';
+ board.SerialNumber[7] = '-';
+
+ cpu.Total = (UCHAR)HalpProcessorCount();
+ cpu.TenXFactor = (UCHAR)CpuClockMultiplier;
+ cpu.BusFrequency = (UCHAR)(ProcessorBusFrequency/1000000);
+
+ memory.BaseAddress = 0x0;
+ memory.MaxBankSize = 0x40;
+ memory.MaxNumBanks = (System == SYS_POWERPRO)?2:4;
+
+ bus.NumIoBus = 1;
+ bus.ConfigAddr = 0x80800800;
+
+ numInts = 4;
+
+ DefaultPair[0].Int = 25;
+ DefaultPair[0].SlotNumber = 1;
+ DefaultPair[1].Int = 22;
+ DefaultPair[1].SlotNumber = 2;
+ DefaultPair[2].Int = 23;
+ DefaultPair[2].SlotNumber = 3;
+ DefaultPair[3].Int = 26;
+ DefaultPair[3].SlotNumber = 4;
+
+ // The ES and MX (non-IIC) platforms are special cased
+ if ((System == SYS_POWERTOP) || (System == SYS_POWERPRO)) {
+ NonIIC = TRUE;
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetBoard(address, &board) == TRUE)) {
+ sprintf(buffer, "%c%c", board.PartType[0], board.PartType[1]);
+ HalpSetValueKeyString(key, "Board - Part Type", buffer);
+ sprintf(buffer, "%c%c", board.PartRev[0], board.PartRev[1]);
+ HalpSetValueKeyString(key, "Board - Part Rev", buffer);
+ sprintf(buffer, "%x", board.BoardNumber);
+ HalpSetValueKeyString(key, "Board - Number", buffer);
+ sprintf(buffer, "%x", board.Version);
+ HalpSetValueKeyString(key, "Board - Version", buffer);
+ sprintf(buffer, "%c%c%c%c%c%c%c%c",
+ board.SerialNumber[0], board.SerialNumber[1],
+ board.SerialNumber[2], board.SerialNumber[3],
+ board.SerialNumber[4], board.SerialNumber[5],
+ board.SerialNumber[6], board.SerialNumber[7]);
+ HalpSetValueKeyString(key, "Board - Serial Number", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetProcessor(address, &cpu) == TRUE)) {
+ sprintf(buffer, "%d", cpu.Total);
+ HalpSetValueKeyString(key, "CPU - Total Number of CPUs", buffer);
+ sprintf(buffer, "%d", cpu.BusFrequency);
+ if ((cpu.BusFrequency == 66) || (cpu.BusFrequency == 33)) {
+ sprintf(buffer, "%d.%d", cpu.BusFrequency, cpu.BusFrequency);
+ }
+ else {
+ sprintf(buffer, "%d", cpu.BusFrequency);
+ }
+ HalpSetValueKeyString(key, "CPU - Bus Frequency", buffer);
+ sprintf(buffer, "%d", cpu.TenXFactor);
+ HalpSetValueKeyString(key, "CPU - 10 Times Factor", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetDRAM(address, &memory) == TRUE)) {
+ sprintf(buffer, "0x%08x", memory.BaseAddress);
+ HalpSetValueKeyString(key, "Memory - Base Address", buffer);
+ sprintf(buffer, "0x%08x", memory.MaxBankSize);
+ HalpSetValueKeyString(key, "Memory - Max Bank Size", buffer);
+ sprintf(buffer, "%d", memory.MaxNumBanks);
+ HalpSetValueKeyString(key, "Memory - Max # of Banks", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetBus(address, &bus) == TRUE)) {
+ sprintf(buffer, "%d", bus.NumIoBus);
+ HalpSetValueKeyString(key, "Bus - Number of Buses", buffer);
+ sprintf(buffer, "0x%08x", bus.ConfigAddr);
+ HalpSetValueKeyString(key, "Bus - Configration Address", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetIntsTotal(address, &numInts) == TRUE)) {
+ char keyName[32];
+ UCHAR i = 0;
+ struct PAIRS *pair;
+
+ sprintf(buffer, "%d", numInts);
+ HalpSetValueKeyString(key,
+ "Ints - Number of Primary PCI Interrupts", buffer);
+
+ while (numInts-- > 0) {
+ sprintf(keyName, "Ints - Primary PCI Entry %d", i);
+ if (NonIIC == TRUE) {
+ pair = &DefaultPair[i];
+ }
+ else {
+ pair = &DefaultPair[0];
+ }
+ bStatus = HalpI2CGetIntsAPair(address, i++, pair);
+ if ((NonIIC == FALSE) && (bStatus == FALSE)) break;
+ sprintf(buffer, "Vector#%d Slot#%d", pair->Int, pair->SlotNumber);
+ HalpSetValueKeyString(key, keyName, buffer);
+ }
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpCreateNode(CCHAR * pszNodeName, UCHAR address, HANDLE * phNode)
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ HANDLE hNode;
+ ULONG disposition;
+ STRING strNodeName;
+ UNICODE_STRING ucNodeName;
+
+ *phNode = NULL;
+
+ RtlInitString (&strNodeName, pszNodeName);
+ status = RtlAnsiStringToUnicodeString(
+ &ucNodeName,
+ &strNodeName,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("Could not create unicode strings: (0x%x) \n",
+ status));
+ return FALSE;
+ }
+
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &ucNodeName,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(&hNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("Did not create key: (0x%x) \n", status););
+ RtlFreeUnicodeString(&ucNodeName);
+ return FALSE;
+ }
+
+ *phNode = hNode;
+ RtlFreeUnicodeString(&ucNodeName);
+ return TRUE;
+}
+
+BOOLEAN
+HalpSetUpRegistryForI2C(SYSTEM_TYPE System)
+{
+ HANDLE hNode;
+ BOOLEAN bStatus = FALSE;
+#if defined(HALDEBUG_ON)
+ BOOLEAN SystemTypeFound = FALSE;
+#endif
+ UCHAR address;
+ ULONG StructureTypes;
+
+ CCHAR szCPU[256];
+ CCHAR szMEM[256];
+ CCHAR szSystem[] = "\\Registry\\Machine\\Hardware\\Powerized\\System";
+ CHAR CpuCardLabel[] =
+ "\\Registry\\Machine\\Hardware\\Powerized\\Cpu Card";
+ SHORT CpuCardNo = 0;
+ CHAR MemCardLabel[] =
+ "\\Registry\\Machine\\Hardware\\Powerized\\Memory Card";
+ SHORT MemCardNo = 0;
+
+ address = 0;
+ // Loop through all possible IIC addresses
+ while (address < 16) {
+ // Since all of the structure type flags are mutually exclusive
+ // bits, we can lump together into one mask.
+ StructureTypes = FindDataTypes(address, System);
+
+ // Determine what identifying structures are present and create
+ // nodes corresponding to them.
+ // - an IIC with a SYS_DATA structure is a System board; there must
+ // be ONE and only ONE system board on a system
+ // - an IIC with a CPU_DATA structure and no SYS_DATA structure is
+ // a Cpu Card; there may be multiple Cpu Cards in a system.
+ // - an IIC with a MEM_DATA structure and no CPU or SYS_DATA structure
+ // is a Memory Card; there may be multiple Memory Cards in a system
+ if ((StructureTypes & SYS_DATA) != 0) {
+ bStatus = HalpCreateNode(szSystem, address, &hNode);
+ if (hNode != NULL) {
+ HalpFillUpRegistryForIIC(hNode, address, System);
+ ZwClose(hNode);
+ }
+#if defined(HALDEBUG_ON)
+ SystemTypeFound = TRUE;
+#endif
+ }
+ else if ((StructureTypes & CPU_DATA) != 0) {
+ sprintf(szCPU, "%s %d", CpuCardLabel, CpuCardNo);
+ bStatus = HalpCreateNode(szCPU, address, &hNode);
+ if (hNode != NULL) {
+ HalpFillUpRegistryForIIC(hNode, address, System);
+ ZwClose(hNode);
+ CpuCardNo++;
+ }
+ }
+ else if ((StructureTypes &
+ (DRAM_DATA|SRAM_DATA|VRAM_DATA|EDORAM_DATA) ) != 0) {
+ sprintf(szMEM, "%s %d", MemCardLabel, MemCardNo);
+ bStatus = HalpCreateNode(szMEM, address, &hNode);
+ if (hNode != NULL) {
+ HalpFillUpRegistryForIIC(hNode, address, System);
+ ZwClose(hNode);
+ MemCardNo++;
+ }
+ }
+ address++;
+ }
+#if defined(HALDEBUG_ON)
+ if (SystemTypeFound == FALSE) {
+ HalpDebugPrint ("HalpSetUpRegistryForI2C: no MLB IIC found.\n");
+ }
+#endif
+
+ return bStatus;
+}
+
+/* end of fpi2c.c */
diff --git a/private/ntos/nthals/halfire/ppc/fpi2c.h b/private/ntos/nthals/halfire/ppc/fpi2c.h
new file mode 100644
index 000000000..e3c5e1a18
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpi2c.h
@@ -0,0 +1,39 @@
+/* fpi2c.h */
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpi2c.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/02/06 02:20:28 $
+ * $Locker: $
+ *
+/*
+ system board ROM data (I2C address 0x00)
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 0x00: 26 59 41 31 10 26 59 41 31 ?? ?? 02 01 80 00 00 Meta
+ 0x10: 00 04 00 00 20 42 41 41 44 00 93 73 00 03 01 00 Board
+ 0x20: 04 01 00
+ 0x30: 01 00 00 00 10 01 00 System
+ 0x40: 08 00 00 00 10 00 00 00 00 08 00 04 Memory
+ 0x50: 40 00 00 00 10 01 08 80 80 Bus
+ 0x60: 80 00 00 00 00 05 26 04 25 01 23 03 22 02 21 05 Ints
+
+ * typical CPU card ROM data for LX (I2C address 0x01)
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 0x00: 26 59 41 31 10 26 59 41 31 ?? ?? 02 01 80 00 00 Meta
+ 0x10: 00 04 00 00 20 42 41 41 44 00 03 75 00 03 01 09 Board
+ 0x20: 00 01 00
+ 0x30: 02 00 00 00 10 02 42 14 Processor
+ 0x40: 04 00 00 00 00 02 20 00 20 02 11 31 00 00 00 00 Cache
+ 0x50: 08 00 00 00 00 00
+
+ */
+
+extern BOOLEAN HalpI2CGetSystem(SYSTEM_TYPE *psystemtype);
+extern BOOLEAN HalpSetUpRegistryForI2C(SYSTEM_TYPE System);
+extern BOOLEAN HalpDoesI2CExist(UCHAR address);
+extern BOOLEAN HalpI2CGetInterrupt();
+
+/* end of fpi2c.h */
+
diff --git a/private/ntos/nthals/halfire/ppc/fpi2csup.h b/private/ntos/nthals/halfire/ppc/fpi2csup.h
new file mode 100644
index 000000000..861821621
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpi2csup.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpi2csup.h $
+ * $Revision: 1.6 $
+ * $Date: 1996/02/19 23:54:29 $
+ * $Locker: $
+ */
+#ifndef FPI2CSUP_H
+#define FPI2CSUP_H
+// C4103 : "used #pragma pack to change alignment"
+//#pragma warning(disable:4103) // disable C4103 warning
+//#pragma pack(1)
+
+/* This is an implementation according to 1.5 specification */
+/*
+ *
+ * Each data structure has in common a STRUCT_HEADER which holds clues
+ * about the 'DataType' of the structure and it's 'OffSet'. The data
+ * type tells software what data is in the structure hence how to
+ * interpret the data. The OffSet indicates how far to the next
+ * data structure, or, if the value is 0, whether there is another data
+ * structure. return to index
+ *
+ */
+
+#define EMPTY_DATA 0x00000000 // indicates there is no data.
+#define SYS_DATA 0x00000001 // general system registers
+#define CPU_DATA 0x00000002 // processor
+#define CACHE_DATA 0x00000004 // cache control
+#define DRAM_DATA 0x00000008 // memory control
+#define SRAM_DATA 0x00000010 // memory control
+#define VRAM_DATA 0x00000020 // memory control
+#define EDORAM_DATA 0x00000040 // memory control
+#define INT_DATA 0x00000080 // int control, not initialization.
+#define BUS_DATA 0x00000400 // I O control, mainly configuration and
+// initialization.
+#define DMA_DATA 0x00000100
+#define DISPLAY_DATA 0x00000200
+// mogawa
+#define BOARD_DATA 0x40000000
+#define META_DATA 0x80000000
+
+#define STRUCT_HEADER \
+ULONG DataType; UCHAR OffSet
+ // The type of data contained in the structure
+ // The Offset to the next data structure, relative
+ // the beginning of this structure. Typically, it's
+ // value is set as the length of the structure, but
+ // is set to zero if no more structures exist.
+
+/*
+ *
+ *
+ * Meta data effectively describes the structure of the IIC rom data.
+ * The size of the total rom is given, along with pointers to the beginning of
+ * the other data areas. Finally, there is a major/minor version numbering
+ * system to provide some means of evaluating what data the rom contains.
+ * return to index
+ *
+ */
+#define CURRENT_META_REV 0x0103 // this is in the form of: USHORT 0x0101
+#define CURRENT_SIGNATURE 0x31415926 // numbers of PI: e is (27182818) next
+
+
+typedef struct _Meta_ {
+ STRUCT_HEADER;
+ ULONG Signature;
+ USHORT ChkSum; // a sum of byte pairs (USHORT) in little endian
+ // order.
+ USHORT Revision;
+ UCHAR Size; // in bytes, the size of the entire rom.
+} META;
+
+
+/*
+ *
+ * Manufacturing's part number is built out of four pieces: a two letter
+ * description of the item ( BA for board assembly ), a five digit part
+ * designator, a two digit board version, and a two letter board turn
+ * identifier ( as in AA, AB, AC, AD ... ).
+ *
+ * E.G. BA-007393-01-AD is an LX series Board Assembly (BA) whose board
+ * variation is 01, and board revision is "AD."
+ *
+ */
+
+#define BOARD_REV_MASK 0x000000ff // the manufacturing number's rev bits
+#define BOARD_PART_MSK 0xffffff00 // the 6 digits used as the part number
+ // ( 4 digits actually )
+/*
+ *
+ *
+ * The general board data contains data fields common to all boards. A version
+ * to correlate this structure with the meta data structure, along with
+ * the type of board, cpu or mlu, the board system, lx or tx, the board family
+ * as in PREP, CHRP or something else, return to index
+ *
+ */
+
+typedef struct _Board_ {
+ STRUCT_HEADER;
+ UCHAR PartType[2]; // Currently a two ascii value 'B''A' that stands
+ // for Board Assembly.
+ UCHAR PartRev[2]; // Colloquially the Board Rev. E.G. Mx has this as
+ // 'A''D' for the Rev AD board.
+ ULONG BoardNumber; // Board ID consists of two parts: Rev fields
+ // which are the least two significant nibbles,
+ // and Part Number field which is the 6 most
+ // nificant nibbles. The digits are stored
+ // in "BCD" format as in one decimal digit per
+ // nibble, in little endian order.
+
+ USHORT Version; // major/minor versioning value of this board.
+ UCHAR SerialNumber[8]; // board serial number. Format TBD....
+} BOARD;
+
+
+
+/*
+ * :
+ * System data structure: Mainly a catch all for data needed but not readily
+ * associated with any one hardware function. for instance, we use it here to
+ * say whether the system is TX, LX, MX or whatever. return * to index
+ *
+ */
+
+#define DEV_SYS 0x0000
+#define LX_SYSTEM 0x0001
+#define MX_SYSTEM 0x0002
+#define TX_SYSTEM 0x0003
+#define TX_PROTO 0x0004
+
+typedef struct _SYSTEM_ {
+ STRUCT_HEADER;
+ USHORT type; // what kind of system is this: This is a value field
+ // rather than a bit map....
+} SYSTEM;
+
+/*
+ * For the board specific information, there is a specific structure. This
+ * allows for varying data requirements of different boards such as a changing
+ * sense of where some registers may sit.
+ *
+ */
+
+typedef struct _Processor_ {
+ STRUCT_HEADER;
+ UCHAR Total; // total number of cpus on this board.
+ UCHAR BusFrequency; // frequency of the bus serving the cpu(s)
+ UCHAR TenXFactor; // 10 times the bus frequency multiplier for the cpu.
+ // This allows fractional multipliers as in 3/2
+ // (becomes 15) or 5/2 ( becomes 25 ).
+} PROCESSOR;
+
+
+#define LOOKASIDE_L2 0x00000001 // this cache is a look aside cache
+#define INLINE_L2 0x00000002 // this cache is an inline cache
+#define PIPELINED_L2 0x00010000 // pipelined cache
+
+typedef struct _Cache_ {
+ STRUCT_HEADER;
+ UCHAR MaxSets; // Maximum number of "sets" available for this cache.
+ // direct mapped, then there is only 1.
+ UCHAR Bytes2Line; // line size in bytes: i.e. number of bytes per set.
+ USHORT Lines2Set; // number of lines per set.
+ UCHAR SramBanks; // # of memory banks: indicates both cache
+ // size and max set associativity.
+ ULONG Performance; // 3-1-1-1, 2-1-1-1 or some other cycle latency.
+ // the data is stored in BCD format.
+ ULONG MaxSize; // size of cache in bytes.
+ ULONG Properties; // properties of the cache's behavior: pipelined
+ // or not, lookaside or not...
+} CACHE;
+
+typedef struct _Memory_Device_ {
+ STRUCT_HEADER;
+ ULONG BaseAddress; // the base physical address for this memory.
+ USHORT MaxBankSize; // Maximum size of banks in Megabytes
+ UCHAR MaxNumBanks; // Maximum number of memory banks on this board;
+} MEMORY;
+
+
+/*
+ *
+ *
+ * Describe any busses on the system. Current plans account only
+ * for the pci bus but will expand to allow for complete bus typing.
+ * return to index
+ *
+ */
+typedef struct _BUS_ {
+ STRUCT_HEADER;
+ UCHAR NumIoBus; // number of io busses on main logic board.
+ ULONG ConfigAddr; // the location of the config space. Zero
+ // means there is no config space. This value
+ // points to the first device's address, and is
+ // assumed to be device 0.
+} BUS;
+
+
+/*
+ *
+ * The INT structure describes some set of interrupts on the system that
+ * software needs knowledge of. In this case software needs to know what
+ * pci config addresses map to what interrupts.
+ * In a later implementation, this should fully describe the system's
+ * interrupt space. return to index
+ *
+ */
+struct PAIRS {
+ UCHAR Int;
+ UCHAR SlotNumber;
+};
+
+typedef struct _INTS_ {
+ STRUCT_HEADER;
+ UCHAR Total; // how many interrupts are we talking about here?
+ struct PAIRS Pairs[0]; // pairs of numbers in the form: int, slot number:
+ // for ints on config addresses on a secondary
+ // bus, the slot number will be greater than 10
+ // where the more significant nibble describes
+ // bus number as seen from a low to high descending
+ // bus probe.
+
+} INTS;
+
+//#pragma warning(enable:4103) // disable C4103 warning
+//#pragma pack
+
+#endif // FPI2CSUP_H
diff --git a/private/ntos/nthals/halfire/ppc/fpints.c b/private/ntos/nthals/halfire/ppc/fpints.c
new file mode 100644
index 000000000..e69c09813
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpints.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpints.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/07/13 01:15:58 $
+ * $Locker: $
+ */
+
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Module Name:
+//
+// FPINTS.C
+//
+// Abstract:
+//
+// This module implements the arrays required to handle interrupt
+// priorities including generation of the arrays, and anything else
+// that is hardware specific interrupt oriented. This is not intended,
+// in it's original incarnation, to be an OS policy file, merely a hw one.
+//
+// The theory of ops is given a set of interrupts ordered by priority,
+// that is for any occurance of an interrupt, only those interrupts pre-
+// ceding it in the list may now occur. So, if int 5 is the highest
+// priority then when it occurrs, no other interrupt will be visible. Any
+// lesser interrupt may be interruptable by an int 5. And so on.
+//
+// Author:
+//
+// Bill Rees ( FirePOWER )
+// Sol Kavy ( FirePOWER )
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 16-Jul-95 Created
+//
+//--
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fppci.h"
+#include "pxpcisup.h"
+extern ULONG atoi(PCHAR);
+
+#define MAX_IRQL_NUM 32
+#define MAX_VECTORS 32
+
+//
+// Note: this is declared poorly in pxsiosup.c and should be
+// moved to PCR.
+//
+extern ULONG registeredInts[];
+
+//
+// This array spec's which interrupts go with which devices
+// on the host-pci bus ( bus 0, i.e. primary bus ).
+// NOTE: 0xff => no device interrupt provided.
+//
+UCHAR PciDevicePrimaryInts[MAXIMUM_PCI_SLOTS];
+
+/*
+ * Given an IRQL, provide a register mask that sets allowable interrupts
+ * and blocks all ints that are set at "lower" priority.
+ *
+ * This array is automatically generated from the Vector2Irql array by the
+ * HalpSetIntPriorityMask() call in fpints.c. For each entry in the V2I array
+ * that sits at an IRQL or above, it's interrupt bit is or'd into the Irql2Mask
+ * value. For example, at irql 0, almost every entry in the V2I array has an
+ * irql greater than 0 ( except for the reserved interrupts ) so the mask value
+ * in the Irql2Mask array has nearly every bit turned on. Conversely, at IRQL
+ * 24, only a few interrupts have irql values above 21 ( ints 0, 1, 22, 23,
+ * 28, 29, 30, 31 )
+ *
+ */
+ULONG Irql2Mask[MAX_IRQL_NUM];
+
+/*
+ * This array matches an IRQL to an Interrupt Vector. Since the array is
+ * indexed by interrupt vector, there can be a many interrupts to single IRQL
+ * mapping allowing interrupts to share IRQL settings. IRQLs determine
+ * relative operational order such that any code operating at any irql, will
+ * block code from a lower priority from occuring and in turn this same code
+ * can be interrupted by code trying to run at a higher priority.
+ *
+ * So this array becomes a prioritization of interrupts, determining which
+ * interrupts will block each other or not block each other. In this case,
+ * a higher number means higher priority hence blocking more interrupts.
+ *
+ * explanation on how this array is used is above the Irql2Mask[] declaration.
+ *
+ */
+ULONG Vector2Irql[MAX_VECTORS] = {
+ 26, // int 0 (Timer) is IRQL 26 so it blocks most other interrupts:
+ 25, // int 1 (KEYBD) blocks all other ISA devices except RTC.
+
+ 24, // int 2 is the cascade bit so all interrupts on the cascaded
+ // interrupt controller ( 8259 ) are higher priority than the
+ // rest of the interrupts on the master interrupt controller.
+
+ 15, // int 3 (COM2) is on the master but after the slave ints, so it
+ // blocks only those ints left on the master chip.
+
+ 14, // int 4 (COM1) is lower priority than com 2.
+ 13, // int 5 Display:
+ 12, // int 6 Floppy:
+ 11, // int 7 Parallel:
+ 23, // int 8 (RTC): First int on Slave: only ints 0,1,2 are higher pri.
+ 22, // int 9:
+ 21, // int 10 (AUDIO).
+ 20, // int 11:
+ 19, // int 12 Mouse int. Lower than keyboard.
+ 18, // int 13 old scsi
+ 17, // int 14 old enet:
+ 16, // int 15:
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // int 20 |
+ 00, // int 21 |
+ 00, // int 22 |
+ 00, // int 23 - PCI interrupts configured dynamically from the I2C
+ 00, // int 24 |
+ 00, // int 25 |
+ 00, // int 26 |
+ 00, // reserved: hence lowest priority
+ 28, // int 28(CPU) Set CPU Bus error IRQL to IPI_LEVEL
+ 28, // int 29(PCI) Set PCI Bus error IRQL to IPI_LEVEL
+ 28, // int 30(MEM/VID) Set MEMORY error IRQL to IPI_LEVEL
+ 29 // int 31(IPI) this is the cpu message level: > clock
+};
+
+ULONG LX_Vector2Irql[MAX_VECTORS] = {
+ 26, // int 0 (Timer) is IRQL 26 so it blocks most other interrupts:
+ 25, // int 1 (KEYBD) blocks all other ISA devices except RTC.
+
+ 24, // int 2 is the cascade bit so all interrupts on the cascaded
+ // interrupt controller ( 8259 ) are higher priority than the
+ // rest of the interrupts on the master interrupt controller.
+
+ 15, // int 3 (COM2) is on the master but after the slave ints, so it
+ // blocks only those ints left on the master chip.
+
+ 14, // int 4 (COM1) is lower priority than com 2.
+ 13, // int 5 Display:
+ 12, // int 6 Floppy:
+ 11, // int 7 Parallel:
+ 23, // int 8 (RTC): First int on Slave: only ints 0,1,2 are higher pri.
+ 22, // int 9:
+ 21, // int 10 (AUDIO).
+ 20, // int 11:
+ 19, // int 12 Mouse int. Lower than keyboard.
+ 18, // int 13 old scsi
+ 17, // int 14 old enet:
+ 16, // int 15:
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 23, // int 20 LX: rsrvd ; TX: PCI slot 3
+ 22, // int 21 LX: IDE A ; TX: PCI slot 2
+ 21, // int 22 LX: IDE A ; TX: PCI slot 1
+ 20, // int 23 pci slot 3 IRQL
+ 19, // int 24 pci slot 2 IRQL
+ 18, // int 25 pci slot 1 IRQL scsi
+ 17, // int 26 pci slot 0 IRQL network
+ 00, // reserved: hence lowest priority
+ 28, // int 28(CPU) Set CPU Bus error IRQL to IPI_LEVEL
+ 28, // int 29(PCI) Set PCI Bus error IRQL to IPI_LEVEL
+ 28, // int 30(MEM/VID) Set MEMORY error IRQL to IPI_LEVEL
+ 29 // int 31(IPI) this is the cpu message level: > clock
+};
+
+// TX_PROTO & LX_PROTO: must reorder the IRQL table
+VOID HalpInitializeVector2Irql(VOID)
+{
+ ULONG irql = 17; // Start the PCI interrupts at irql 17
+ UCHAR slot;
+ UCHAR intNum;
+
+ for (slot = 1; slot < MAXIMUM_PCI_SLOTS; slot++) {
+ intNum = PciDevicePrimaryInts[slot];
+ if ((intNum != INVALID_INT) && (intNum < MAX_VECTORS)) {
+ Vector2Irql[intNum] = irql;
+ irql++;
+ }
+ }
+}
+
+HalpSetIntPriorityMask(VOID)
+{
+ ULONG irql, vec, Value=0;
+
+ //
+ // for each irql, search the Vector2Irql array and generate
+ // a mask suitable for writing to the mask register to block
+ // interrupts at the given irql.
+ //
+ for (irql = 0; irql < MAX_IRQL_NUM; irql++) {
+ Irql2Mask[irql] = 0;
+ for (vec = 0; vec < MAX_VECTORS; vec++) {
+ //
+ // Turn on bits for interrupts that are still allowed.
+ //
+ if (Vector2Irql[vec] > irql) {
+ Irql2Mask[irql] |= (1 << vec);
+ }
+ }
+ }
+ PRNTINTR(HalpDebugPrint("HalpSetIntPriorityMask: Irql2Mask: 0x%x\n",
+ &Irql2Mask[0]));
+ return(1);
+}
+
+
+//
+// THis array gives the processor affinity for the given interrupt
+// vector. Then NT will handle the interrupt on that processor.
+//
+
+ULONG Vector2Affinity[MAX_VECTORS];
+
+
+//
+/*++
+
+Routine Description: void HalpInitProcAffinity ()
+ This function sets the processor affinity for the given interrupt
+ in the Vector2Affinity array. If the values are wrong, cpu 0 is
+ set.
+
+Arguments:
+
+ pProcnInts - pointer to the PROCNINTS nvram variable.
+ numProc - number of processors in the system.
+
+
+Return Value:
+
+ void
+
+--*/
+
+void
+HalpInitProcAffinity(PCHAR pProcnInts, ULONG NumProc)
+{
+ ULONG vec,proc;
+ CHAR delim = ';';
+
+ if ( NumProc == 1 ) {
+ for(vec=0; vec < MAX_VECTORS; vec++) {
+ Vector2Affinity[vec] = 1; // cpu 0 always
+ }
+ HDBG(DBG_MPINTS,
+ HalpDebugPrint("Affinity set to 1 for all vectors\n"););
+ return;
+ }
+ HDBG(DBG_MPINTS,HalpDebugPrint("vector affinity\n"););
+ // multiprocessor but no PROCNINTS given
+ // distribute on all processors round robin fashion
+ if ( pProcnInts == 0 ) {
+ for(vec=0; vec < MAX_VECTORS; vec++) {
+ Vector2Affinity[vec] = 1 << (vec%NumProc); // next cpu gets next vec
+ HDBG(DBG_MPINTS,
+ HalpDebugPrint("%6d %6d\n",vec,Vector2Affinity[vec]););
+ }
+ return;
+ }
+ // otherwise go with the env variable PROCNINTS in pProcnInts
+ for(vec=0; vec < MAX_VECTORS; vec++) {
+ if ( *pProcnInts == 0 || *pProcnInts == delim )
+ proc = 0;
+ else
+ proc = atoi(pProcnInts);
+ if ( proc >= NumProc )
+ proc = (proc % NumProc);
+ Vector2Affinity[vec] = 1 << proc;
+ while(*pProcnInts && *pProcnInts != ';')
+ pProcnInts++; // skip current affinity
+ if (*pProcnInts == ';')
+ pProcnInts++; // skip delimiter
+ HDBG(DBG_MPINTS,
+ HalpDebugPrint("%6d %6d\n",vec,Vector2Affinity[vec]););
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/fpio.h b/private/ntos/nthals/halfire/ppc/fpio.h
new file mode 100644
index 000000000..e06763e14
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpio.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpio.h $
+ * $Revision: 1.9 $
+ * $Date: 1996/01/11 07:06:50 $
+ * $Locker: $
+ *
+ * This file contains references to registers in I/O space only. That is any
+ * access to the ISA or PCI space ( or any future additions ) are contained in
+ * this file. Access to device registers that do not lie in I/O space should
+ * be defined in the file fpreg.h
+ *
+ */
+
+#ifndef FPIO_H
+#define FPIO_H
+
+//
+// Define macros for handling accesses to io-space:
+//
+
+// HalpIoControlBase is extern'd in pxhalp.h which is included by halp.h
+
+#define _IOBASE ((PUCHAR)HalpIoControlBase)
+#define _IOREG(_OFFSET) (*(volatile UCHAR * const)((_IOBASE + (_OFFSET))))
+#define _IOADDR(_OFFSET) ((_IOBASE + (_OFFSET)))
+
+#define _PCIOBASE ((PUCHAR)HalpPciConfigBase)
+#define _PCIOREG(_OFFSET) (*(volatile UCHAR * const)((_PCIOBASE + (_OFFSET))))
+#define _PCIOADDR(_OFFSET) ((_PCIOBASE + (_OFFSET)))
+
+//
+// The Physical IO Space for generation one machines starts at 0x8000_0000.
+// All IO external devices in either ISA space or PCI space live within
+// this domain. This also includes the on-board ethernet and scsi drivers,
+// the ISA bus interrupt controllers, display control.
+//
+
+//
+// PCI Configuration Space:
+//
+//
+// device cpu relative Address Config space address
+// ------ -------------------- ----------------
+//
+// 82378 ( SIO ) 0x8080_0800 - 0x8080_08ff 0x80_0800 - 0x80_08ff
+// scsi (79c974) 0x8080_1000 - 0x8080_10ff 0x80_1000 - 0x80_10ff
+// pci slot A 0x8080_2000 - 0x8080_20ff 0x80_2000 - 0x80_20ff
+// pci slot B 0x8080_4000 - 0x8080_40ff 0x80_4000 - 0x80_40ff
+// enet (79c974) 0x8080_8000 - 0x8080_80ff 0x80_8000 - 0x80_80ff
+
+#define RPciConfig(Slot,Offset) \
+ (*(volatile ULONG * const)(_PCIOBASE + (HalpPciConfigSlot[Slot] + Offset)) )
+
+#define RPciVendor(Slot) \
+ (*(volatile ULONG * const)(_PCIOBASE + (UCHAR)(HalpPciConfigSlot[Slot])) )
+
+#define RPciVendorId(Slot) \
+ (*(volatile ULONG * const) (_PCIOBASE + (HalpPciConfigSlot[Slot])) )
+ //(*(volatile ULONG * const) (_PCIOBASE + (0x800 << Slot) ) )
+
+//
+// I/O Device Addresses
+//
+
+// Device Registers IO Space Cpu Space
+// ---------------- -------- ---------
+//
+// Dma 1 registers, control 0x0000 - 0x000f 0x8000_0000 - _000f
+
+// 8259 interrupt 1 control 0x0020 0x8000_0020
+// 8259 interrupt 1 mask 0x0021 0x8000_0021
+#define MasterIntPort0 0x0020
+#define MasterIntPort1 0x0021
+
+//
+// AIP Primary xbus index 0x0022
+// AIP Primary Xbus target 0x0023
+// AIP Secondary Xbus
+// target 0x0024
+// AIP Secondary xbus
+// index 0x0025
+//
+#define AIP_PRIMARY_XBUS_INDEX 0x0022
+#define AIP_PRIMARY_XBUS_TARGET 0x0023
+#define AIP_SECONDARY_XBUS_INDEX 0x0024
+#define AIP_SECONDARY_XBUS_TARGET 0x0025
+
+
+
+// keyboard cs, Reset 0x0060
+// ( xbus irq 12 )
+// nmi status and control 0x0061
+// keyboard cs 0x0062
+// keyboard cs 0x0064
+// keyboard cs 0x0066
+
+/*
+** *******************************************
+**
+** Dallas 1385 Real Time Clock : System macros
+** dallas specific macros are in pxds1585.h
+*/
+// RTC address 0x0070
+// RTC read/writ 0x0071
+// NVRAM addr strobe 0 0x0072
+// NVRAM addr strobe 1 0x0075
+// NVRAM Read/Write 0x0077
+// RTC and NVRAM 0x0070 - 0077
+
+#define RTC_INDEX 0x0070 // index register
+#define RTC_DATA 0x0071 // data register
+#define NVRAM_ADDR0 0x0072 // address strobe 0
+#define NVRAM_ADDR1 0x0075 // address strobe 1
+#define NVRAM_RW 0x0077 // read write nvram?
+
+
+// Timer 0x0078 - 007f
+// DMA Page Registers 0x0080 - 0090
+// Port 92 Register 0x0080 - 0092
+// DMA Page Registers 0x0094 - 009f
+
+// 8259 interrupt 2 control 0x00A0 0x8000_00A0
+// 8259 interrupt 2 mask 0x00A1 0x8000_00A1
+#define SlaveIntPort0 0x00A0
+#define SlaveIntPort1 0x00A1
+
+// DMA 2 registers and
+// control 0x00c0 - 00df
+
+
+// AIP Configuration
+// Registers 0x026e - 026f
+// ( primary addr block )
+#define AIP_PRIMARY_CONFIG_INDEX_REG 0x026e
+#define AIP_PRIMARY_CNFG_DATA_REG 0x026f
+
+
+// Parallel Port 3 0x0278 - 027d
+// serial port2 0x02f8 - 02ff
+// secondary floppy
+// controller 0x0370 - 0377
+// parallel port 2 0x0378 - 037d
+
+
+// AIP Configuraiton Registers 0x0398 - 0399
+// ( secondary addr blck )
+#define AIP_SECOND_CONFIG_INDEX_REG 0x0398
+#define AIP_SECOND_CNFG_DATA_REG 0x0399
+
+
+// parallel port 1 0x03bc - 03bf
+// pcmcia config registers 0x03e0 - 03e3
+// primary floppy controller 0x03f0 - 03f7
+// serial port 1 0x03f8 - 03ff
+// dma 1 extended
+// mode regsiter 0x040b
+// dma scatter/gather
+// command status 0x0410 - 041f
+// dma scatter/gather
+// Dscrptr ( channel 0-3 ) 0x0420 - 042f
+// dma scatter/gather
+// Dscrptr ( channel 5-7 ) 0x0434 - 043f
+// dma high page registers 0x0481 - 0483
+// dma high page registers 0x0487
+// dma high page registers 0x0489
+// dma high page registers 0x048a - 048b
+// dma 2 extended mode
+// register 0x04d6
+// business audio control,
+// status, data registers 0x0830 - 0833
+
+
+// video asic registers 0x0840 - 0841
+#define DCC_INDEX 0x0840
+#define DCC_DATA 0x0841
+
+
+// bt445 ramdac registers 0x0860 - 086f
+#define BT445_ADDRESS 0x0860
+#define ADDRESS_REGISTER 0x0860 // same as the BT445_ADDR
+#define PRIMARY_PALETTE 0x0861 // Primary Color Palette address
+#define CHIP_CONTROL 0x0862 // function control register
+#define OVERLAY_PALETTE 0x0863 // Overlay Color Palette
+#define RGB_PIXEL_CONFIG 0x0865 // RGB configuration and control
+#define TIMING_PIXEL_CONFIG 0x0866 // pixel timing, configuration, control
+#define CURSOR_COLOR 0x0867 // cursor color
+
+// dram simm presence
+// detect register 0x0880
+// vram simm presence
+// detect register 0x0890
+// epxansion presence
+// detect register 0x08a0
+//
+
+//
+// Defines for Register Access:
+//
+#define rIndexRTC _IOREG( RTC_INDEX )
+#define rDataRTC _IOREG( RTC_DATA )
+#define rNvramData _IOREG( NVRAM_RW )
+#define rNvramAddr0 _IOREG( NVRAM_ADDR0 )
+#define rNvramAddr1 _IOREG( NVRAM_ADDR1 )
+#define rMasterIntPort0 _IOREG( MasterIntPort0 )
+#define rMasterIntPort1 _IOREG( MasterIntPort1 )
+#define rSlaveIntPort0 _IOREG( SlaveIntPort0 )
+#define rSlaveIntPort1 _IOREG( SlaveIntPort1 )
+
+#define rIndexAIP1 _IOREG( AIP_PRIMARY_XBUS_INDEX )
+#define rTargetAIP1 _IOREG( AIP_PRIMARY_XBUS_TARGET )
+#define rIndexAIP2 _IOREG( AIP_SECONDARY_XBUS_INDEX )
+#define rTargetAIP2 _IOREG( AIP_SECONDARY_XBUS_TARGET )
+
+
+#define rDccIndex _IOREG( DCC_INDEX )
+#define rDccData _IOREG( DCC_DATA )
+
+#define rRamDacAddr _IOREG( BT445_ADDRESS )
+#define rDacPrimeLut _IOREG( PRIMARY_PALETTE )
+#define rRamDacCntl _IOREG( CHIP_CONTROL )
+#define rDacOvlayLut _IOREG( OVERLAY_PALETTE )
+#define rDacPixelBit _IOREG( RGB_PIXEL_CONFIG )
+#define rDacPixelClks _IOREG( TIMING_PIXEL_CONFIG )
+#define rRamDacCursor _IOREG( CURSOR_COLOR )
+
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fplibc.c b/private/ntos/nthals/halfire/ppc/fplibc.c
new file mode 100644
index 000000000..b3461e904
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fplibc.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fplibc.c $
+ * $Revision: 1.3 $
+ * $Date: 1996/04/30 23:25:53 $
+ * $Locker: $
+ */
+
+/*
+ * This file contains libc support routines that the kernel/hal do
+ * not include but that the HAL wants to use, so we have created
+ * our own.
+ */
+
+#include "fpproto.h"
+
+int
+atoi(char *s)
+{
+ int temp = 0, base = 10;
+
+ if (*s == '0') {
+ ++s;
+ if (*s == 'x') {
+ ++s;
+ base = 16;
+ } else {
+ base = 8;
+ }
+ }
+ while (*s) {
+ switch (*s) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ temp = (temp * base) + (*s++ - '0');
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ temp = (temp * base) + (*s++ - 'a' + 10);
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ temp = (temp * base) + (*s++ - 'A' + 10);
+ break;
+ default:
+ return (temp);
+ }
+ }
+ return (temp);
+}
+
+char *
+FpStrtok (
+ char * string,
+ const char * control
+ )
+{
+ unsigned char *str;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+
+ static char *nextoken;
+
+ /* Clear control map */
+ for (count = 0; count < 32; count++) {
+ map[count] = 0;
+ }
+
+ /* Set bits in delimiter table */
+ do {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ } while (*ctrl++);
+
+ /* Initialize str. If string is NULL, set str to the saved
+ * pointer (i.e., continue breaking tokens out of the string
+ * from the last strtok call) */
+ if (string) {
+ str = string;
+ }else {
+ str = nextoken;
+ }
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets str to point to the terminal
+ * null (*str == '\0') */
+ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) {
+ str++;
+ }
+
+ string = str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *str ; str++ ) {
+ if ( map[*str >> 3] & (1 << (*str & 7)) ) {
+ *str++ = '\0';
+ break;
+ }
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+ nextoken = str;
+
+ /* Determine if a token has been found. */
+ if ( string == str ) {
+ return '\0';
+ } else {
+ return string;
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/fpnvram.h b/private/ntos/nthals/halfire/ppc/fpnvram.h
new file mode 100644
index 000000000..a4a0c03b4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpnvram.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpnvram.h $
+ * $Revision: 1.4 $
+ * $Date: 1996/01/11 07:07:03 $
+ * $Locker: $
+ */
+#ifndef _PREPNVRM_H
+#define _PREPNVRM_H
+//
+// This header describes the NVRAM definition for PREP
+//
+typedef struct _SECURITY {
+ ULONG BootErrCnt; // Count of boot password errors
+ ULONG ConfigErrCnt; // Count of config password errors
+ ULONG BootErrorDT[2]; // Date&Time from RTC of last error in pw
+ ULONG ConfigErrorDT[2]; // Date&Time from RTC of last error in pw
+ ULONG BootCorrectDT[2]; // Date&Time from RTC of last correct pw
+ ULONG ConfigCorrectDT[2]; // Date&Time from RTC of last correct pw
+ ULONG BootSetDT[2]; // Date&Time from RTC of last set of pw
+ ULONG ConfigSetDT[2]; // Date&Time from RTC of last set of pw
+ UCHAR Serial[16]; // Box serial Number
+} SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ MKOS2 = 4,
+ MKAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ MK = 12
+} OS_ID;
+
+typedef struct _ERROR_LOG {
+ UCHAR ErrorLogEntry[40];
+} ERROR_LOG;
+
+typedef enum _NVRAM_BOOT_STATUS {
+ BootStarted = 0x001,
+ BootFinished = 0x002,
+ RestartStarted = 0x004,
+ RestartFinished = 0x008,
+ PowerFailStarted = 0x010,
+ PowerFailFinished = 0x020,
+ ProcessorReady = 0x040,
+ ProcessorRunning = 0x080,
+ ProcessorStart = 0x100
+} NVRAM_BOOT_STATUS;
+
+typedef struct _NVRAM_RESTART_BLOCK {
+ USHORT Version;
+ USHORT Revision;
+ ULONG ResumeReserved[2];
+ volatile ULONG BootStatus;
+ ULONG CheckSum;
+ void * RestartAddress;
+ void * SaveAreaAddr;
+ ULONG SaveAreaLength;
+} NVRAM_RESTART_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+} OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80,
+ Normal = 0x00
+} PMMode;
+
+typedef struct _HEADER {
+ USHORT Size; // NVRAM size in K
+ UCHAR Version; // Structure map different
+ UCHAR Revision; // Structure map same - may be new values in old fields
+ USHORT Crc1;
+ USHORT Crc2;
+ UCHAR LastOS; // OS_ID
+ UCHAR Endian; // B if big endian, L if little endian
+ UCHAR OSAreaUsage;
+ UCHAR PMMode; // Power Management shutdown mode
+ NVRAM_RESTART_BLOCK Restart;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+ PVOID GEAddress;
+ ULONG GELength;
+ ULONG GELastWriteDT[2]; // Date&Time from RTC of last change to Global
+
+ PVOID ConfigAddress;
+ ULONG ConfigLength;
+ ULONG ConfigLastWriteDT[2]; // Date&Time from RTC of last change to Config
+ ULONG ConfigCount; // Count of entries in Configuration
+
+ PVOID OSAreaAddress;
+ ULONG OSAreaLength;
+ ULONG OSAreaLastWriteDT[2]; // Date&Time from RTC of last change to Var
+
+} HEADER, *PHEADER;
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fppci.h b/private/ntos/nthals/halfire/ppc/fppci.h
new file mode 100644
index 000000000..f11095fb4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fppci.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fppci.h $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/25 01:11:27 $
+ * $Locker: $
+ *
+ * Herein are the definitions used to interact with PCI based devices. The
+ * information is specific to the PCI spec as interpreted by FirePOWER and
+ * not specific to the hardware ( or at the least minimally relavent to hw).
+ *
+ * Please look in FPIO.H for system specific information relevant to the IO
+ * system such as memory maps or register read/write specifics.
+ *
+ */
+
+#ifndef FPPCI_H
+#define FPPCI_H
+
+#ifdef HALDEBUG_ON
+#define PRINTBRIDGE(x) \
+ if ( HalpDebugValue&DBG_PCI ) { \
+ PULONG j; \
+ ULONG i; \
+ HalpDebugPrint("\nVendor: 0x%x, Dev: 0x%x, Cmd: 0x%x, Stat: 0x%x\n",\
+ x->VendorID, x->DeviceID, x->Command, x->Status); \
+ HalpDebugPrint("PrimaryBus: 0x%02x, SecondaryBus: 0x%02x", \
+ x->u.type1.PrimaryBus, \
+ x->u.type1.SecondaryBus); \
+ HalpDebugPrint(" SubBus: 0x%02x, IOBase: 0x%02x, IOLimit:0x%02x\n", \
+ x->u.type1.SubordinateBus,\
+ x->u.type1.IOBase, \
+ x->u.type1.IOLimit); \
+ HalpDebugPrint("Secnd Status: 0x%04x, MemBase 0x%04x, MemLimit 0x%04x",\
+ x->u.type1.SecondaryStatus, x->u.type1.MemoryBase, \
+ x->u.type1.MemoryLimit ); \
+ HalpDebugPrint(" IntLine: 0x%02x, IntPin: 0x%02x, BrdgeCntl: 0x%04x\n",\
+ x->u.type1.InterruptLine, x->u.type1.InterruptPin, \
+ x->u.type1.BridgeControl); \
+ j=(PULONG)x; \
+ for(i=0; i<(PCI_COMMON_HDR_LENGTH/4); j+=4, i+=4){ \
+ HalpDebugPrint("%s 0x%08x, 0x%08x, 0x%08x, 0x%08x \n", \
+ TBS, *j, *(j+1), *(j+2), *(j+3) ); \
+ } \
+ }
+#else
+#define PRINTBRIDGE(x)
+#endif //haldebug_on
+
+//
+// Hardware Specific Defines for FirePOWER:
+//
+#define TYPE1_ACCESS 0x1 // configuration space access is of Standard type 1
+#define TYPE2_ACCESS 0x2 // configuration space access is of Standard type 2
+#define BRIDGED_ACCESS 0x3 // FirePOWER specific access: modified type 1.
+
+/*
+ * PCI Register config read/write macros: dependent on defines
+ * in FPIO.H which must be included in the c file before this
+ * file is included ( not included here to avoid multiple
+ * includes of the file in any io specific file).
+ *
+ */
+
+//
+// type - what type of data access: uchar, ushort, or ulong:
+// (UCHAR) bus - what pci bus ( up to 256 )
+// (UCHAR) Device - Which physical board: = physical slot. ( max of 32 )
+// (UCHAR) Fn - Which function on the board ( Max of 8 )
+// (UCHAR) Offset - The offset into the config header ( one of 64 words )
+//
+
+#define SLOT(DEV, FN ) (ULONG) ((ULONG)( (DEV & 0x1f) << 11 ) | \
+ (ULONG)( (FN & 0x07) << 8 ) )
+#define CONFIG(BUSNUM, DEV, FN, OFFSET ) \
+ (ULONG)( BUSNUM << 16 ) | SLOT(DEV, FN) | (ULONG)( OFFSET & 0xfc)
+
+#define RPciBusConfig(TYPE, BUSNUM, DEV, FN, OFFSET ) \
+ (*(volatile type * const) (_PCIOBASE + \
+ (ULONG)( CONFIG(BUSNUM, DEV, FN, OFFSET) ) ) )
+// (*(volatile type * const) (_PCIOBASE + (ULONG)( (0x800 << Slot) ) ) )
+//(*(volatile ULONG * const)(_PCIOBASE + (HalpPciConfigSlot[Slot] + Offset)))
+
+/*
+ * Pci Configuration Header Defines:
+ * These defines are in conjunction with what's in ntos\inc\pci.h.
+ *
+ */
+
+//
+// Major Classes ( also called BaseClasses ) of devices.....
+//
+#define PRE_REV2_CLASS 0x00
+#define MASS_STORAGE_CLASS 0x01
+#define NETWORK_CTLR_CLASS 0x02
+#define DISPLAY_CTLR_CLASS 0x03
+#define MULTIMEDIA_CLASS 0x04
+#define MEMORY_CTLR_CLASS 0x05
+#define BRIDGE_CLASS 0x06
+
+//
+// SubClasses and Programming interfaces....
+//
+
+// REV2 CLASS
+//
+#define NON_VGA_SUBCLASS 0x00
+#define NON_VGA_PROGIF 0x00
+#define VGA_SUB_CLASS 0x01
+#define VGA_PROGIF 0x01
+
+// Mass Storage Classes
+//
+#define SCSI_SUBCLASS 0x00
+#define SCSI_PROGIF 0x00
+#define IDE_SUBCLASS 0x01
+#define IDE_PROGIF 0x00
+#define FLOPPY_SUBCLASS 0x02
+#define FLOPPY_PROGIF 0x00
+#define IPI_SUBCLASS 0x03
+#define IPI_PROGIF 0x00
+#define OTHER_SUBCLASS 0x80
+#define OTHER_PROGIF 0x00
+
+// Network Controller Classes
+//
+#define ENET_SUBCLASS 0x00
+#define ENET_PROGIF 0x00
+#define TKNRING_SUBCLASS 0x01
+#define TKNRING_PROGIF 0x00
+#define FDDI_SUBCLASS 0x02
+#define FDDI_PROGIF 0x00
+#define OTHR_NTWK_SUBCLASS 0x80
+#define OTHR_PROGIF 0x00
+
+// Display Controller Classes
+//
+#define VGA_SUBCLASS 0x00
+#define VGA_CTLR_PROGIF 0x00
+#define XGA_SUBCLASS 0x01
+#define XGA_PROGIF 0x00
+#define OTHR_DSPLY_SUBCLASS 0x80
+#define OTHR_DISPLY_PROGIF 0x00
+
+// Multimedia Device Classes
+//
+#define VIDEO_SUBCLASS 0x00
+#define VIDEO_PROGIF 0x00
+#define AUDIO_SUBCLASS 0x01
+#define AUDIO_PROGIF 0x00
+#define OTHR_MLTIMDIA_SUBCLASS 0x80
+#define OTHR_MLTIMDIA_PROGIF 0x00
+
+// Memory Controller Classes
+//
+#define RAM_SUBCLASS 0x00
+#define RAM_PROGIF 0x00
+#define FLASH_SUBCLASS 0x01
+#define FLASH_PROGIF 0x00
+#define OTHR_MEM_SUBCLASS 0x80
+#define OTHR_MEM_PROGIF 0x00
+
+// Bridge Device Classes
+//
+#define HOST_PCI_SUBCLASS 0x00
+#define HOST_PCI_PROGIF 0x00
+#define PCI_ISA_SUBCLASS 0x01
+#define PCI_ISA_PROGIF 0x00
+#define PCI_EISA_SUBCLASS 0x02
+#define PCI_EISA_PROGIF 0x00
+#define PCI_MCHANL_SUBCLASS 0x03
+#define PCI_MCHANL_PROGIF 0x00
+#define PCI_PCI_SUBCLASS 0x04
+#define PCI_PCI_PROGIF 0x00
+#define PCI_PCMCIA_SUBCLASS 0x05
+#define PCI_PCMCIA_PROGIF 0x00
+#define OTHER_BRIDGE_SUBCLASS 0x80
+#define OTHER_BRIDGE_PROGIF 0x00
+
+#define VENDOR_DIGITAL 0x1011
+#define DEVICE_21050 0x1
+#define PCI_ISA_IO_PHYSICAL_BASE 0x80000000
+#define PCI_IO_PHYSICAL_BASE 0x81000000
+#define PCI_IO_ADDRESS 0x00000001
+#define PCI_MEMORY_ADDRESS 0x00000000
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fppcisup.c b/private/ntos/nthals/halfire/ppc/fppcisup.c
new file mode 100644
index 000000000..379c03ef0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fppcisup.c
@@ -0,0 +1,1101 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fppcisup.c $
+ * $Revision: 1.33 $
+ * $Date: 1996/07/02 02:26:11 $
+ * $Locker: $
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arccodes.h>
+#include "fpdebug.h"
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fppci.h"
+#include "fppcisup.h"
+
+#define DEC_BRIDGE_CHIP (0x1011) // Dec Bridge Chip VendorID
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+extern UCHAR PciDevicePrimaryInts[];
+PUCHAR ClassNames[] = {
+ "Pre rev 2.0 ",
+ "Mass Storage",
+ "Network",
+ "Display",
+ "MultiMedia",
+ "Memory",
+ "Bridge",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown"
+ };
+
+//
+// scan the bus depth first, then pop back out and catch all the siblings
+// on the way back.
+//
+ULONG
+HalpScanPciBus( ULONG HwType, ULONG BusNo, PBUS_HANDLER ParentBus )
+{
+ ULONG devs, fns, Stat=0, ValidDevs=0,BusDepth=0, BusLimits;
+ PUCHAR Buffer;
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG *PciData;
+ PBUS_HANDLER CurrentBus, ChildBus;
+ PFPHAL_BUSNODE FpBusData;
+ ULONG slot;
+ char buf[128];
+
+ //
+ // Added by Keith Son to support peer level bridge.
+ //
+ ULONG Bus_Current_Number, Bus_Next_Number, Bus_Child_Number=0;
+
+
+ HDBG(DBG_GENERAL, HalpDebugPrint("HalpScanPciBus: 0x%x, 0x%0x, 0x%08x\n",
+ HwType, BusNo, ParentBus ););
+
+ // ENGINEERING DEVELOPMENT: allow optional toggle of Bridge mode
+ // in the IO ASIC.
+ if (HalGetEnvironmentVariable("BRIDGEMODE", sizeof(buf), buf)
+ == ESUCCESS) {
+ if (_stricmp(buf, "true") == 0) {
+ PRNTPCI(HalpDebugPrint(
+ "HalpScanPciBus: BRIDGEMODE enabled\n"));
+ rTscControl |= 0x20000000;
+ rPIOPendingCount |= 0x80;
+ FireSyncRegister();
+ }
+ else {
+ PRNTPCI(HalpDebugPrint(
+ "HalpScanPciBus: BRIDGEMODE disabled\n"));
+ rTscControl &= ~0x20000000;
+ rPIOPendingCount &= ~0x80;
+ FireSyncRegister();
+ }
+ }
+
+ //
+ // Added by Keith Son.
+ // This variable is needed to keep track of the number of buses in the
+ // system.
+ //
+ Bus_Next_Number = BusNo;
+
+
+
+ if ((CurrentBus = HalpAllocateAndInitPciBusHandler(HwType, BusNo, TRUE))
+ == (PBUS_HANDLER) NULL ) {
+ HalpDebugPrint("\nHalpInitIoBuses: DID NOT ALLOCATE BUS HANDLER: \n");
+ return 1; // add in status on return later...
+ }
+
+ FpBusData = (PFPHAL_BUSNODE)CurrentBus->BusData;
+
+ if (ParentBus) {
+ //
+ // Setup bus defaults for heirarchical buses.
+ //
+ Bus_Current_Number = BusNo;
+ FpBusData->Bus.MaxDevice = PCI_MAX_DEVICES;
+ BusLimits = PCI_MAX_DEVICES;
+ FpBusData->Bus.ParentBus = (UCHAR) ParentBus->BusNumber;
+
+ slot = FpBusData->Bus.CommonData.ParentSlot.u.bits.DeviceNumber;
+ if (slot > MAXIMUM_PCI_SLOTS) {
+ HalpDebugPrint("HalpScanPciBus: child %d ILLEGAL PARENT SLOT %d\n",
+ BusNo, slot);
+ return 1; // add in status on return later...
+ }
+ // It doesn't matter if the BusInt is an INVALID_INT here
+ FpBusData->BusInt = PciDevicePrimaryInts[slot];
+ FpBusData->BusMax = (UCHAR)BusNo;
+ FpBusData->Bus.CommonData.ParentSlot.u.AsULONG =
+ ((PFPHAL_BUSNODE)ParentBus->BusData)->SlotNumber.u.AsULONG;
+ FpBusData->SlotNumber.u.AsULONG =
+ ((PFPHAL_BUSNODE)ParentBus->BusData)->SlotNumber.u.AsULONG;
+
+
+
+ if (!(FpBusData->Bus.CommonData.ParentSlot.u.AsULONG)) {
+ PRNTPCI(
+ HalpDebugPrint("HalpScanPciBus: Child (0x%x): no ParentSlot\n",
+ BusNo));
+ FpBusData->Bus.CommonData.ParentSlot.u.AsULONG = 0xffffffff;
+
+
+ }
+ } else {
+ //
+ // This must be the host-pci bus handler, so setup the supported
+ // interrupts this bus will support...
+ //
+ BusLimits = MAXIMUM_PCI_SLOTS;
+ FpBusData->MemBase = 0;
+ FpBusData->MemTop = 0xffffffff;
+ FpBusData->IoBase = 0;
+ FpBusData->IoTop = 0xffffffff;
+ FpBusData->Bus.CommonData.ParentSlot.u.AsULONG = 0xffffffff;
+ //
+ // Keith Son.
+ // Added to support peer bridge. Keeping track the number of bridge in the scan process.
+ //
+ Bus_Current_Number = BusNo;
+
+
+
+ }
+ //
+ // setup general data areas for use...
+ //
+ Buffer = ExAllocatePool (PagedPool, 1024);
+ PciData = (PPCI_COMMON_CONFIG) Buffer;
+ FpBusData->ValidDevs = 0xffffffff; // init valid dev structure
+
+ HDBG(DBG_BREAK,DbgBreakPoint(););
+
+ //
+ // Now scan this bus for contents...
+ //
+ SlotNumber.u.AsULONG = 0; // init structure to a known value..
+ for (devs =0; devs < BusLimits; devs++) {
+ SlotNumber.u.bits.DeviceNumber = devs;
+ PRNTPCI(HalpDebugPrint("%s%x devs; %x",TBS,CurrentBus->BusNumber,devs));
+
+ for (fns =0; fns <PCI_MAX_FUNCTION; fns++) {
+ HDBG(DBG_PCI, HalpDebugPrint(" fns = %x \n",fns ););
+ SlotNumber.u.bits.FunctionNumber = fns;
+
+ HalpReadPCIConfig(
+ CurrentBus, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+
+ PRNTPCI(HalpDebugPrint("\tSlot %x: Vendor: 0x%x, Device: 0x%x\n",
+ SlotNumber.u.AsULONG, PciData->VendorID, PciData->DeviceID));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ){
+ //
+ // checking for invalid device status, and if
+ // there is no device on this slot then turn off
+ // the valid bit and break out of this loop
+ //
+ FpBusData->ValidDevs &= ~(1 << devs);
+ PRNTPCI(HalpDebugPrint("\t\tValidDevs now set to: 0x%08x\n",
+ FpBusData->ValidDevs) );
+ break;
+ }
+
+ PRNTPCI(HalpDebugPrint("\t\tDev is class type %s(%x)\n",
+ ClassNames[PciData->BaseClass], PciData->BaseClass));
+
+ //
+ // Check if this device is a bridge chip. Add in checking for
+ // what Type of bridge chip it is and tailor the configuration
+ // appropriately.
+ //
+ if (PciData->BaseClass == 0x6) {
+ //
+ // Set this bridge's primary bus number and pass it into
+ // the configuration routine. The config routine will set
+ // up the secondary bus fields and other required fields,
+ // write the config data out to the bridge, and return.
+ //
+ FpBusData->SlotNumber.u.AsULONG = SlotNumber.u.AsULONG;
+ //
+ // Keith Son.
+ // Needed to pass the bus no. to the next level of bridge.
+ //
+ PciData->u.type1.PrimaryBus = (UCHAR) Bus_Next_Number;
+
+
+
+ switch (PciData->SubClass) {
+ case HOST_PCI_SUBCLASS: Stat =0;
+ break;
+
+ case PCI_PCI_SUBCLASS:
+ Stat = HalpInitPciBridgeConfig( BusNo,
+ PciData,
+ CurrentBus);
+ break;
+
+ case PCI_PCMCIA_SUBCLASS:
+ Stat = HalpConfigurePcmciaBridge(BusNo);
+ break;
+ default:
+ break;
+ };
+
+ //
+ // Now setup a bus and scan the secondary bus on this
+ // bridge chip. If it also contains a bridge, recurse.
+ // When we come back out, need to make sure the subordinate
+ // bus fields are setup correctly.
+ //
+ if (Stat) {
+ //
+ // If the bridge was successfully initted, then
+ // descend through the bridge and scan it's bus
+ //
+ FpBusData->BusLevel++;
+ HDBG(DBG_PCI, HalpDebugPrint("-------- Bus %x ---------\n",
+ FpBusData->BusLevel););
+
+
+ //
+ // Keith Son.
+ // Keep updating the maximun bus variable and the value for the recursive scan.
+ //
+ if (Bus_Next_Number > FpBusData->BusMax)
+ FpBusData->BusMax = (UCHAR)Bus_Next_Number;
+
+ //
+ // Keith Son.
+ // Bus_Next_Number is the place holder for counting number of buses.
+ //
+
+ Bus_Next_Number = HalpScanPciBus( BRIDGED_ACCESS,
+ FpBusData->BusMax+1,
+ CurrentBus);
+
+
+ HDBG(DBG_PCI, HalpDebugPrint("-------- Bus_Next_Number %x ---------\n",
+ Bus_Next_Number););
+
+ //
+ // Keith Son.
+ // Update the secondary bus value after scanning the sub-bus.
+ // This is very important because bridge controller only forward acces based on
+ // the secondary and Subordinate.
+ //
+ PRINTBRIDGE(PciData);
+ PciData->u.type1.SecondaryBus = (UCHAR)Bus_Next_Number;
+ PciData->u.type1.SubordinateBus = (UCHAR)Bus_Next_Number;
+ // for now, prune on way back..
+
+ PRINTBRIDGE(PciData);
+
+ HalpWritePCIConfig (CurrentBus, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Keith Son.
+ //
+
+
+ ChildBus = HalpHandlerForBus(PCIBus, Bus_Next_Number );
+
+ if (ChildBus) {
+ PFPHAL_BUSNODE ChildData;
+ ChildData = (PFPHAL_BUSNODE)ChildBus->BusData;
+ ChildBus->ParentHandler = CurrentBus;
+ FpBusData->BusMax = ChildData->BusMax;
+/*
+#pragma NOTE("fixup memory/port assignments");
+should probably assign parent's fields first, then tell the child
+what range he can use.
+*/
+ //
+ // setup the memory and port limits for this bridge:
+ // since the bridge itself uses the limit registers to
+ // effectively pick the last page ( for port addresses )
+ // or last megabyte ( for memory ) rather than the last
+ // byte, we need to reflect that by translating the
+ // page ( or megabyte ) count to a byte count: hence the
+ // shift left and 'or' in of 'f's.
+ //
+ ChildData->MemBase =
+ (ULONG)PciData->u.type1.MemoryBase<<16;
+ ChildData->MemTop =
+ (ULONG)(PciData->u.type1.MemoryLimit<<16 | 0xfffff);
+
+ ChildData->IoBase = (ULONG)PciData->u.type1.IOBase<<8;
+ ChildData->IoTop =
+ (ULONG)PciData->u.type1.IOLimit << 8 | 0xfff;
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("ChildData->MemBase=%x MemTop=%x IoBase=%x IoTop=%x\n",
+ ChildData->MemBase, ChildData->MemTop, ChildData->IoBase, ChildData->IoTop););
+
+
+ //
+ // Skim the memory from the parents list..
+ //
+ FpBusData->MemTop = ChildData->MemBase -1;
+ FpBusData->IoTop = ChildData->IoBase -1;
+
+ //
+ // Remind the child what slot he uses on the parent's
+ // bus. This allows someone, given the child's bus,
+ // to not only grab it's parent's bus handler but to
+ // know where the child bus is so memory and io address
+ // assignments can be dynamically altered.
+ //
+ ChildData->Bus.CommonData.ParentSlot =
+ FpBusData->SlotNumber;
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("FpBusData->SlotNumber %x\n", FpBusData->SlotNumber););
+
+
+ //FpBusData->Bus.CommonData.ParentSlot;
+ }else{
+ HalpDebugPrint("Could Not find handler for bus %x\n",
+ BusNo+1);
+ }
+
+ //clear out any pending ints due to child bus scanning...
+ //
+ rPCIBusErrorCause = 0xffffffff;
+ FireSyncRegister();
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("--------------------------\n"););
+ } else {
+ HDBG(DBG_PCI,
+ HalpDebugPrint(" Don't go into bridge\n"););
+ }
+ }
+
+ if (PciData->BaseClass != 0x6) {
+ //
+ // this is not a bridge card so go ahead and fix the interrupt
+ // value for this device:
+ //
+ if ( CurrentBus->BusNumber != 0 ) {
+ PciData->u.type0.InterruptLine=(UCHAR)FpBusData->BusInt;
+ HalpWritePCIConfig(CurrentBus, // bus type
+ SlotNumber, // "Slot"
+ PciData, // data buffer,
+ 0, // Offset,
+ PCI_COMMON_HDR_LENGTH); // read first 64 bytes..
+
+ //
+ // Read it back in and make sure it is valid.
+ //
+ HalpReadPCIConfig(CurrentBus, // bus type
+ SlotNumber, // "Slot"
+ PciData, // data buffer,
+ 0, // Offset,
+ PCI_COMMON_HDR_LENGTH); // read first 64 bytes..
+
+ if ( PciData->u.type0.InterruptLine != FpBusData->BusInt ){
+ HalpDebugPrint("HalpScanPciBus: Line=%x, BusInt=%x\n",
+ PciData->u.type0.InterruptLine, FpBusData->BusInt );
+ }
+ }
+ }
+ if ( !(PciData->HeaderType & PCI_MULTIFUNCTION) ) {
+ //
+ // get out of here...
+ //
+ break;
+ }
+ } // .....for fns loop
+ } // .....for devs loop
+
+ ExFreePool(Buffer);
+
+ //
+ // Keith Son.
+ // Keep track the highest bus in the system.
+ //
+
+ return (Bus_Next_Number);
+}
+
+VOID HalpPCISynchronizeBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Now block interruptions and make this transaction appear
+ // atomic with respect to any one else trying to access this
+ // bus and device (especially any other cpu ).
+ //
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+ //
+ // Initialize PciCfg1
+ //
+
+ //
+ // The Bus Number must share the 8 bits with a bit of config address
+ // space. Namely, the physical address to access config space requires
+ // 9 bits. This means that only buses whose numbers are less than 128
+ // are available which shouldn't be a problem.
+ //
+ PciCfg1->u.AsULONG = 0;
+ //
+ // Limit bus totals to less than 128 buses:
+ PciCfg1->u.bits.BusNumber = ( (0x7f) & BusHandler->BusNumber);
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PRNTPCI(HalpDebugPrint("HalpPCISynchronizeBridged: u.AsULONG: 0x%08x",
+ PciCfg1->u.AsULONG));
+
+ //
+ // add in base offset of pci config space's virtual address:
+ //
+ PciCfg1->u.AsULONG += (ULONG) HalpPciConfigBase;
+
+ //
+ // Setup the config space address for access...
+ //
+ RInterruptMask(GetCpuId()) &= ~(PCI_ERROR_INT); // block pci error ints.
+ WaitForRInterruptMask(GetCpuId());
+
+ PRNTPCI(HalpDebugPrint(" ->u.AsULONG: 0x%08x\n", PciCfg1->u.AsULONG));
+
+}
+
+VOID HalpPCIReleaseSynchronzationBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ //rPCIStatus = 0xffff; // clear out any latent interrutps at bus
+ rPCIBusErrorCause = 0xffffffff; //clear out ints at the pending register...
+ FireSyncRegister();
+
+ RInterruptPending(GetCpuId()) |= PCI_ERROR_INT; // clear any pending ints.
+ RInterruptMask(GetCpuId()) |= PCI_ERROR_INT; // turn pci ints back on.
+ WaitForRInterruptMask(GetCpuId());
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+ //HalSweepIcache();
+ HalSweepDcache();
+
+}
+
+
+ULONG
+HalpPCIReadUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ //PciCfg1->u.bits.Reserved1 = 0x1; // turn access into config cycle
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+
+ FireSyncRegister();
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ //PciCfg1->u.bits.Reserved1 = 0x1; // turn access into config cycle
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+
+ FireSyncRegister();
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system pci config cycles
+ // will now be type 1 cycles.
+ FireSyncRegister();
+
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system config cycles
+ // will now be type 0 cycles.
+ FireSyncRegister();
+
+ return sizeof (ULONG);
+}
+
+ULONG
+HalpPCIWriteUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+ FireSyncRegister();
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ //PciCfg1->u.bits.Reserved1 = 0x1; // turn access into config cycle
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+ FireSyncRegister();
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+ FireSyncRegister();
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (ULONG);
+}
+
+VOID
+HalpInitIoBuses (
+ VOID
+ )
+{
+ ULONG BusNum, HwType;
+
+ //
+ // Initialize bus handling structures for the primary PCI bus in
+ // the system. We know the bus is there if this system is a top
+ // or pro. When other buses are added, a peer pci for example,
+ // there will need to be a search done on the config tree to find
+ // the first available one, hopefully I can tell which one is the
+ // boot pci path.
+ //
+ BusNum = 0;
+ HwType = 1; // our system most closely resembles the Type1
+ // config access model.
+
+ if ( HalpScanPciBus( HwType, BusNum, (PBUS_HANDLER) NULL ) ) {
+// HalpDebugPrint("HalpInitIoBuses: ScanPciBus returned non-zero: \n");
+ }
+
+}
+
+/*--
+ Routine: HalpAdjustBridge( PBUS_HANDLER, PPCI_COMMON_CONFIG )
+
+ Description:
+
+ Given the child bus and a device on that bus, make sure
+ the bridge servicing the bus is adequately setup. This means
+ checking the memory and io base and limit registers, the command
+ and status registers.
+
+ ChildBus This is the bus on the child's side of the bridge. It
+ should hold the parent slot so the bridge may be found
+ and read from or written to.
+
+ PrivData Private Data to the device under resource control. This
+ provides the data to figure out how the bridge should be
+ adjusted.
+--*/
+
+ULONG
+HalpAdjustBridge(PBUS_HANDLER ChildBus,
+ PPCI_COMMON_CONFIG PrivData,
+ PCM_RESOURCE_LIST CmList
+ )
+{
+ PFPHAL_BUSNODE FpBusData;
+ ULONG BaseAddress=0, DCount, Range, TopAddr=0, i;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR TmpDescr;
+ ULONG PciCommandFlag=0;
+ PCI_COMMON_CONFIG Buffer, *BridgeData;
+
+ BridgeData = &Buffer;
+
+ //
+ // Pull out the resources that should describe the device under assignment.
+ //
+ TmpDescr = CmList->List[0].PartialResourceList.PartialDescriptors;
+ DCount = CmList->List[0].PartialResourceList.Count;
+
+ //
+ // Find the device's memory needs
+ //
+ for (i=0; i<DCount; i++, TmpDescr++ ) {
+ switch (TmpDescr->Type) {
+ case CmResourceTypeMaximum:
+ i = DCount;
+ break;
+ case CmResourceTypeMemory:
+ PciCommandFlag |= PCI_ENABLE_MEMORY_SPACE;
+ if (BaseAddress == 0 ) {
+ Range = TmpDescr->u.Memory.Length;
+ BaseAddress = TmpDescr->u.Memory.Start.LowPart;
+ TopAddr = BaseAddress + TmpDescr->u.Memory.Length;
+ }
+ if (BaseAddress > TmpDescr->u.Memory.Start.LowPart) {
+ //
+ // set baseaddress to new low address
+ BaseAddress = TmpDescr->u.Memory.Start.LowPart;
+ }
+
+ //
+ // check that the new descriptor's range lies within
+ // the current TopAddr.
+ //
+ if ( (TmpDescr->u.Memory.Start.LowPart +
+ TmpDescr->u.Memory.Length ) > TopAddr ) {
+ TopAddr = TmpDescr->u.Memory.Start.LowPart +
+ TmpDescr->u.Memory.Length;
+ }
+ break;
+
+ case CmResourceTypePort:
+ PciCommandFlag |= PCI_ENABLE_IO_SPACE;
+ break;
+ case CmResourceTypeDeviceSpecific:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeDma:
+ default:
+ break;
+ }
+ }
+
+
+ //
+ // now read the bridges base and limit registers and compare
+ // the devices memory needs with the bridge's abilities to
+ // properly decode and pass through the proper memory ranges
+ //
+ FpBusData = (PFPHAL_BUSNODE) ChildBus->BusData;
+ if (FpBusData->Bus.CommonData.ParentSlot.u.AsULONG) {
+ HalpReadPCIConfig(ChildBus->ParentHandler, // bus type
+ FpBusData->Bus.CommonData.ParentSlot,
+ BridgeData, // data buffer,
+ 0, // Offset,
+ PCI_COMMON_HDR_LENGTH); // read first 64 words..
+ }
+
+ //
+ // If the bridge does not sufficiently cover the devices needs,
+ // adjust the limits and make sure the command register is properly
+ // set.
+
+ //
+ // Now write out the bridge's new data if any has changed.
+ //
+ return 0;
+}
+
+/*--
+ Routine: HalpInitPciBridgeConfig( ULONG )
+
+ Description:
+ To perform enough initialization of the bridge to allow
+ configuration scanning along the secondary bus to proceed. Ideally
+ setup bridge's config registers with initial state that will be
+ "pruned" by a call to HalpSetPciBridgeConfig.
+
+--*/
+
+ULONG
+HalpInitPciBridgeConfig( IN ULONG PrimaryBusNo,
+ IN OUT PPCI_COMMON_CONFIG PciData,
+ IN OUT PBUS_HANDLER PrimaryBus )
+{
+ PCI_SLOT_NUMBER Slot;
+ PFPHAL_BUSNODE FpNode=(PFPHAL_BUSNODE)PrimaryBus->BusData;
+ PPCI_COMMON_CONFIG TmpPciData;
+ PUCHAR Buffer;
+ ULONG slotNum;
+ BOOLEAN DecBridgeChip = FALSE;
+ BOOLEAN BridgeReconfig = FALSE;
+ ULONG DeviceSpecificSize = 0;
+ ULONG ChipConfigReg = 0;
+ ULONG TimerConfigReg = 0;
+ char buf[128];
+#if HALDEBUG_ON
+ ULONG i;
+#endif
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitPciBridgeConfig: 0x%x, 0x%08x, 0x%08x\n",
+ PrimaryBusNo, PciData, PrimaryBus););
+ //
+ // Print out the incoming common config data...
+ PRINTBRIDGE(PciData);
+
+ // We have been passed the PciData for a bridge chip; before we go any
+ // further, determine if it is DEC bridge, because we need to do some
+ // fix-ups if it is.
+ if( PciData->VendorID == DEC_BRIDGE_CHIP) {
+ DecBridgeChip = TRUE;
+ DeviceSpecificSize = 8;
+ // On POWERSERVE (TX platform) we MUST disable write posting from
+ // the DEC bridge.
+ if (SystemType == SYS_POWERSERVE) {
+ BridgeReconfig = TRUE;
+ ChipConfigReg = 0x00000006;
+ }
+ // Check for NVRAM reconfig values
+ if (HalGetEnvironmentVariable("DECCHIPCONFIGREG", sizeof(buf), buf)
+ == ESUCCESS) {
+ BridgeReconfig = TRUE;
+ ChipConfigReg = atoi(buf);
+ }
+ if (HalGetEnvironmentVariable("DECTIMERCONFIGREG", sizeof(buf), buf)
+ == ESUCCESS) {
+ BridgeReconfig = TRUE;
+ TimerConfigReg = atoi(buf);
+ }
+ }
+
+ Buffer = ExAllocatePool (PagedPool, 1024);
+ TmpPciData = (PPCI_COMMON_CONFIG) Buffer;
+ TmpPciData->VendorID = 0xffff;
+ TmpPciData->u.type1.InterruptLine = 0xff;
+
+ Slot.u.AsULONG=FpNode->SlotNumber.u.AsULONG;
+
+#if HALDEBUG_ON
+ PRNTPCI(HalpDebugPrint("%s ", TBS));
+ for (i=0; i<DeviceSpecificSize - 4; i += 4) {
+ PRNTPCI(HalpDebugPrint("0x%08x, ", PciData->DeviceSpecific[i]));
+ }
+ PRNTPCI(HalpDebugPrint("0x%08x\n", PciData->DeviceSpecific[i]));
+#endif
+
+ //
+ // Enable commands in the command register address in first 64 bytes.
+ // For example, turn on bus mastering,
+ //
+ PciData->Command = PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+
+ //
+ // Keith Son.
+ // Please do not change the order of assignment.
+ // I am using the PrimaryBus variable as a passed in value.
+ // The value is the parent bus number.
+ //
+ PciData->u.type1.SecondaryBus = PciData->u.type1.PrimaryBus + 1;
+ PciData->u.type1.PrimaryBus = (UCHAR) PrimaryBusNo;
+ PciData->u.type1.SubordinateBus = 0xff; // for now, prune on way back..
+ PciData->u.type1.SecondaryStatus = 0xff;
+ PciData->Status = 0xff;
+ slotNum = Slot.u.bits.DeviceNumber;
+ if (slotNum > MAXIMUM_PCI_SLOTS) {
+ HalpDebugPrint("HalpInitPciBridgeConfig:");
+ HalpDebugPrint(" ILLEGAL SLOT NUMBER %d\n", slotNum);
+ return 0; // add in status on return later...
+ }
+ // This can be INVALID_INT
+ PciData->u.type1.InterruptLine = PciDevicePrimaryInts[slotNum];
+ PRNTPCI(HalpDebugPrint("slot=%x\n",
+ Slot.u.bits.DeviceNumber));
+
+
+ //
+ // Keith Son.
+ // Right now we are support four peer level.
+ // Split the resource even for peer level.
+ //
+ if ( PciData->u.type1.SecondaryBus == 4 )
+ {
+ PciData->u.type1.MemoryBase = 0x2000; // for now!!
+ PciData->u.type1.MemoryLimit= 0x2050; // for now!!
+ PciData->u.type1.IOBase = 0xa0; // for now!!
+ PciData->u.type1.IOLimit= 0xa0; // for now!!
+
+ }
+ else if ( PciData->u.type1.SecondaryBus ==3)
+ {
+ PciData->u.type1.MemoryBase = 0x2060; // for now!!
+ PciData->u.type1.MemoryLimit= 0x2bf0; // for now!!
+ PciData->u.type1.IOBase = 0xb0; // for now!!
+ PciData->u.type1.IOLimit= 0xb0; // for now!!
+
+ }
+
+
+ else if ( PciData->u.type1.SecondaryBus == 2)
+ {
+ PciData->u.type1.MemoryBase = 0x2c00; // for now!!
+ PciData->u.type1.MemoryLimit= 0x31f0; // for now!!
+ PciData->u.type1.IOBase = 0xe0; // for now!!
+ PciData->u.type1.IOLimit= 0xe0; // for now!!
+
+ }
+
+ else
+ {
+ PciData->u.type1.MemoryBase = 0x3200; // for now!!
+ PciData->u.type1.MemoryLimit= 0x3800; // for now!!
+ PciData->u.type1.IOBase = 0xc0; // for now!!
+ PciData->u.type1.IOLimit= 0xc0; // for now!!
+
+ }
+
+
+ //PciData->Command = 0; // this disables everything?!
+ PciData->u.type1.BridgeControl = 0; // this disables bridge activity!
+
+ //
+ // Print out the modified common config data...
+ PRINTBRIDGE(PciData);
+
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ KeStallExecutionProcessor(100); // wait for 100 microseconds
+
+ PciData->u.type1.BridgeControl = 0x0000;
+
+ //
+ // Write out new config parameters, and read back in to do some sanity
+ // checking....
+ //
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ if ((DecBridgeChip == TRUE) && (BridgeReconfig == TRUE)) {
+ PULONG ptr;
+ // Re-program the DEC device specific registers
+ HalpReadPCIConfig (PrimaryBus, Slot, TmpPciData, 0,
+ PCI_COMMON_HDR_LENGTH+DeviceSpecificSize);
+ ptr = (PULONG)&PciData->DeviceSpecific[0];
+ *ptr++ = ChipConfigReg;
+ *ptr = TimerConfigReg;
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0,
+ PCI_COMMON_HDR_LENGTH+DeviceSpecificSize);
+ }
+
+ HalpReadPCIConfig (PrimaryBus, Slot, TmpPciData, 0,
+ PCI_COMMON_HDR_LENGTH+DeviceSpecificSize);
+ if ( TmpPciData->u.type1.SecondaryBus != PciData->u.type1.SecondaryBus ){
+ HalpDebugPrint("HalpInitPciBridgeConfig: Read no matchee Write!!\n");
+ }
+ //
+ // Print out the New common config data...
+ PRINTBRIDGE(TmpPciData);
+#if HALDEBUG_ON
+ PRNTPCI(HalpDebugPrint("%s ", TBS));
+ for (i=0; i<DeviceSpecificSize - 4; i += 4) {
+ PRNTPCI(HalpDebugPrint("0x%08x, ", PciData->DeviceSpecific[i]));
+ }
+ PRNTPCI(HalpDebugPrint("0x%08x\n", PciData->DeviceSpecific[i]));
+#endif
+
+ ExFreePool(Buffer);
+
+ return 1;
+
+}
+
+ULONG
+HalpConfigurePcmciaBridge(ULONG ParentBusNo )
+{
+ PRNTGENRL(HalpDebugPrint("HalpConfigurePcmciaBridge: 0x%x\n",ParentBusNo));
+
+ return 0;
+}
+
+/*++
+ Routine: ULONG HalpGetPciInterruptSlot(PBUS_HANDlER , PCI_SLOT )
+
+ Description:
+
+ Given a bus ( bus handler ) and a slot on the bus, find the slot value
+ directly connected to a system interrupt ( I.E. a slot without an inter-
+ vening bridge ).
+
+ Return:
+ Returns a slot value disguised as a ULONG.
+
+--*/
+
+ULONG
+HalpGetPciInterruptSlot(PBUS_HANDLER BusHandler, PCI_SLOT_NUMBER PciSlot )
+{
+ PFPHAL_BUSNODE FpNode;
+ PBUS_HANDLER TmpBus=0;
+
+
+ FpNode = (PFPHAL_BUSNODE)BusHandler->BusData;
+ TmpBus = BusHandler;
+
+
+ //
+ // Keith Son.
+ // Rewrote this function to support peer level buses.
+ // Find the root bus and return the bridge slot on the root bus level.
+ //
+
+ PRNTPCI(HalpDebugPrint("parent busnumber = 0x%x, \n",FpNode->Bus.ParentBus));
+
+
+ PRNTPCI(HalpDebugPrint("BusHandler = 0x%x, slot = %x\n", BusHandler, PciSlot));
+
+
+ TmpBus = BusHandler->ParentHandler ;
+
+ PRNTPCI(HalpDebugPrint("BusNumber = 0x%x, \n",TmpBus->BusNumber));
+
+ PRNTPCI(HalpDebugPrint("aslong = 0x%x, \n",FpNode->Bus.CommonData.ParentSlot.u.AsULONG));
+
+
+ while( (TmpBus) && ( TmpBus->BusNumber != 0)) {
+ PRNTPCI(HalpDebugPrint("aslong = 0x%x, \n",FpNode->Bus.CommonData.ParentSlot.u.AsULONG));
+
+ FpNode = (PFPHAL_BUSNODE)TmpBus->BusData;
+ TmpBus = TmpBus->ParentHandler;
+
+ }
+
+ return (FpNode->SlotNumber.u.AsULONG);
+
+
+}
+
+/*++
+ Routine: HalpStatSlot()
+
+ Description:
+
+ Given a known device ( slot ), "stat" the slot to discover
+ particular information such as memory/io space requirements,
+ vendor/device ids, device types, etc.
+
+ Also, create a range description of this device to pass back
+ to the bus scan routine for inclusion into the bus resource
+ description.
+
+
+--*/
+
+ULONG
+HalpStatSlot(
+ IN PPCI_COMMON_CONFIG StatData,
+ IN PBUS_HANDLER ThisBus,
+ IN PCI_SLOT_NUMBER Slot,
+ OUT PSUPPORTED_RANGES pRanges
+ )
+{
+ PPCI_COMMON_CONFIG NewData;
+ PUCHAR Buffer;
+ ULONG Addr, Length, Limit, Index;
+
+ Buffer = ExAllocatePool (PagedPool, 1024);
+ NewData = (PPCI_COMMON_CONFIG) Buffer;
+ RtlCopyMemory((PVOID)NewData, (PVOID)StatData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // setup the NewData to probe memory and io space requirements for the
+ // device. Write those registers to all 'f's and read back resource needs.
+ //
+ for( Addr=0; Addr < PCI_TYPE0_ADDRESSES; Addr++ ) {
+ NewData->u.type0.BaseAddresses[Addr] = 0xffffffff;
+ }
+
+ NewData->u.type0.ROMBaseAddress = 0xffffffff & ~(PCI_ROMADDRESS_ENABLED);
+ NewData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+
+ HalpWritePCIConfig( ThisBus, Slot, NewData, 0, PCI_COMMON_HDR_LENGTH );
+ HalpReadPCIConfig( ThisBus, Slot, NewData, 0, PCI_COMMON_HDR_LENGTH );
+
+ for( Index=0; Index < PCI_TYPE0_ADDRESSES; Index++ ) {
+
+ Addr = NewData->u.type0.BaseAddresses[Index];
+ Length = ( Addr & ( ~(Addr & 0xfffffff0) << 1 ));
+ Limit = ( Addr & ( 0x80000000 | (~(Addr & 0xfffffff0) >> 1 )));
+
+ switch( Addr & 0x00000003 ) {
+
+ case PCI_IO_ADDRESS:
+ ThisBus->BusAddresses->NoIO++;
+ break;
+
+ default:
+ ThisBus->BusAddresses->NoMemory++;
+ break;
+ }
+ }
+
+
+ // HalpCreateRangeFromPciData();
+
+ //
+ // Restore the device to it's original settings.
+ //
+ HalpWritePCIConfig( ThisBus, Slot, StatData, 0, PCI_COMMON_HDR_LENGTH );
+
+ return 1;
+}
diff --git a/private/ntos/nthals/halfire/ppc/fppcisup.h b/private/ntos/nthals/halfire/ppc/fppcisup.h
new file mode 100644
index 000000000..fb15495ae
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fppcisup.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fppcisup.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/11 08:38:36 $
+ * $Locker: $
+ *
+ */
+
+#define TBS " "
+
+ULONG
+HalpStatSlot(
+ IN PPCI_COMMON_CONFIG StatData,
+ IN PBUS_HANDLER ThisBus,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ OUT PSUPPORTED_RANGES pRanges
+ );
+
+ULONG
+HalpAdjustBridge(
+ PBUS_HANDLER ChildBus,
+ PPCI_COMMON_CONFIG PrivData,
+ PCM_RESOURCE_LIST CmList
+ );
+
+ULONG
+HalpConfigurePcmciaBridge(
+ IN ULONG ParentBusNo
+ );
+
+ULONG
+HalpInitPciBridgeConfig(
+ IN ULONG ParentBusNo,
+ IN OUT PPCI_COMMON_CONFIG,
+ IN OUT PBUS_HANDLER ParentBus
+ );
+
+VOID
+HalpInitIoBuses (
+ VOID
+ );
+
+VOID HalpPCISynchronizeBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpGetPciInterruptSlot(
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER PciSlot
+ );
+
+PCI_CONFIG_HANDLER PCIConfigHandlerBridged = {
+ HalpPCISynchronizeBridged,
+ HalpPCIReleaseSynchronzationBridged,
+ {
+ HalpPCIReadUlongBridged, // 0
+ HalpPCIReadUcharBridged, // 1
+ HalpPCIReadUshortBridged // 2
+ },
+ {
+ HalpPCIWriteUlongBridged, // 0
+ HalpPCIWriteUcharBridged, // 1
+ HalpPCIWriteUshortBridged // 2
+ }
+};
+
+
+typedef struct ABusInfo {
+ struct ABusInfo *ParentBus;
+ struct ABusInfo *ChildBus;
+ struct ABusInfo *PeerBus;
+ ULONG PeerCount;
+ ULONG ChildCount;
+} BUSINFO, PBUSINFO;
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+
+//
+// scan within a bus for devices, accumulating info. Keep track of
+// devices on current bus, how deep you are, who the parents are.
+//
+ULONG HalpScanPciBus(ULONG HwType, ULONG BusNo, PBUS_HANDLER ParentBus);
+
+
+//
+// Once a bus is fully known, then setup all the devs on the bus:
+//
+ULONG HalpInitPciBus(ULONG BusNo, PULONG ParentBus, PULONG CurrentBus);
+
diff --git a/private/ntos/nthals/halfire/ppc/fpproto.h b/private/ntos/nthals/halfire/ppc/fpproto.h
new file mode 100644
index 000000000..90f7ae0c2
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpproto.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpproto.h $
+ * $Revision: 1.1 $
+ * $Date: 1996/04/30 23:25:58 $
+ * $Locker: $
+ */
+
+
+#ifndef FPPROTO_H
+#define FPPROTO_H
+
+char * FpStrtok ( char * string, const char * control );
+
+#endif //FPPROTO_H
diff --git a/private/ntos/nthals/halfire/ppc/fpreg.h b/private/ntos/nthals/halfire/ppc/fpreg.h
new file mode 100644
index 000000000..70af4feb3
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpreg.h
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpreg.h $
+ * $Revision: 1.19 $
+ * $Date: 1996/05/14 02:32:57 $
+ * $Locker: $
+ */
+
+#ifndef FPREG_H
+#define FPREG_H
+
+#define MAX_SYSTEM_CPU_NUM 2
+//
+// This file contains all of the definitions for the FirePower Control
+// registers. C code needing to access these registers should include this
+// file. If future boards differ from these definitions, we should move
+// the contents of this file into a board specific file, but still
+// have c code include fpreg.h
+//
+
+//
+// This is a variable that when set contains the virtual address of
+// where the system registers were mapped
+//
+extern PVOID HalpSystemRegisterBase;
+
+//
+// Code to write to a safe place (generate external bus cycle to work
+// around the TSC bug).
+//
+extern ULONG SafePlace;
+#define WriteSafePlace() \
+ SafePlace = 0x0; \
+ HalSweepDcacheRange(&SafePlace, 8);
+
+//
+// The following routine should be called whenever the order of writes
+// to a control register needs to be guaranteed.
+//
+#define FireSyncRegister() \
+ __builtin_eieio() ;
+ // __builtin_sync();
+
+//
+// After all writes to the Tsc registers, the system needs to
+// generate an off chip write request.
+//
+#define FireTscSyncRegister() \
+ WriteSafePlace(); \
+ KeFlushWriteBuffer();
+
+//
+// The following macro handles the conversion from BigEndian to LittleEndian
+// This is current setup as a compile time handling but could easily be'
+// made dynamic.
+//
+// Note: The following is the proper definition for Endianess but
+// it causes the Motorola Compiler to go nuts.
+//
+// #ifdef BIGENDIAN
+// #define _BE 1
+// #else
+// #define _BE 0
+// #endif
+//
+// #define _ENDIAN(_X) ((int)(_X) + (int)((_BE)?0:4))
+#ifdef BIGENDIAN
+#define _ENDIAN(_X) ((ULONG)_X + 0)
+#else
+// the NT is running in little endian mode.
+// The following conversion macro can be used only with
+// the addresses at double word boundary and in ASIC.
+// It is not required for the memory accesses.
+#define _ENDIAN(_X) ((ULONG)_X + 4)
+#endif
+
+//
+// These defines provide the mapping to turn an offset into
+// a pointer to the 32 bit register.
+//
+
+#define _SYSBASE ((PUCHAR)HalpSystemRegisterBase)
+#define _REG(_OFFSET) (*(volatile ULONG * const)(_ENDIAN(_SYSBASE + (_OFFSET))))
+#define _ADDR(_OFFSET) (_ENDIAN(_SYSBASE + (_OFFSET)))
+
+//
+// Register definitions with appropriate bit field defintions below.
+// Defines are used because not all of the compilers can be trusted
+// to treat bit field definitions correctly for this architecture.
+//
+#define rInterruptRequest _REG( 0x000000 )
+#define rInterruptRequestSet _REG( 0x000008 )
+#define rInterruptMask0 _REG( 0x000100 )
+#define rInterruptMask1 _REG( 0x000108 )
+#define rInterruptMask2 _REG( 0x000110 )
+#define rInterruptMask3 _REG( 0x000118 )
+#define rInterruptPending0 _REG( 0x000200 )
+#define rInterruptPending1 _REG( 0x000208 )
+#define rInterruptPending2 _REG( 0x000210 )
+#define rInterruptPending3 _REG( 0x000218 )
+#define rCPUMessageInterrupt _REG( 0x000300 )
+#define rCPUMessageInterruptSet _REG( 0x000308 )
+#define rPCIBusErrorCause _REG( 0x000400 )
+#define rPCIBusErrorCauseSet _REG( 0x000408 )
+#define rPCIBusErrorAddressRegister _REG( 0x000410 )
+#define rCPUBusErrorCause _REG( 0x000800 )
+#define rCPUBusErrorCauseSet _REG( 0x000808 )
+#define rCPUBusErrorAddressRegister _REG( 0x000810 )
+#define rErrorStatus0 _REG( 0x001000 )
+#define rErrorStatus0Set _REG( 0x001008 )
+#define rErrorMask _REG( 0x001010 )
+#define rErrorAddr0 _REG( 0x001120 )
+#define rErrorAddr1 _REG( 0x001128 )
+#define rErrorAddr2 _REG( 0x001130 )
+#define rErrorAddr3 _REG( 0x001138 )
+#define rVidInt _REG( 0x001140 )
+#define rVidIntSet _REG( 0x001148 )
+#define rVidIntMask _REG( 0x001150 )
+#define rTscControl _REG( 0x100000 )
+#define rFbControl _REG( 0x100008 )
+#define rEsccControl _REG( 0x100010 )
+#define rEsccL2FLush _REG( 0x100018 )
+#define rScratchPad0 _REG( 0x100020 )
+#define rScratchPad1 _REG( 0x100028 )
+#define rScratchPad2 _REG( 0x100030 )
+#define rLowPowerControl _REG( 0x100080 )
+#define rRomControl _REG( 0x100100 )
+#define rTscStatus0 _REG( 0x100200 )
+#define rTscRevision _REG( 0x100300 )
+#define rMemBank0Config _REG( 0x100400 )
+#define rMemBank1Config _REG( 0x100408 )
+#define rMemBank2Config _REG( 0x100410 )
+#define rMemBank3Config _REG( 0x100418 )
+#define rMemBank4Config _REG( 0x100420 )
+#define rMemBank5Config _REG( 0x100428 )
+#define rMemBank6Config _REG( 0x100430 )
+#define rMemBank7Config _REG( 0x100438 )
+#define rMemDramTiming _REG( 0x100500 )
+#define rMemVramTiming _REG( 0x100508 )
+#define rMemRefresh _REG( 0x100510 )
+#define rVidControl _REG( 0x100518 )
+#define rVidPixelsPerLineLo _REG( 0x100520 )
+#define rVidPixelsPerLineHi _REG( 0x100528 )
+#define rIOControl _REG( 0x101000 )
+#define rPCIConfigType _REG( 0x101100 )
+#define rPIOPendingCount _REG( 0x101200 )
+#define rDMAPendingCount _REG( 0x101300 )
+#define rPCIVendorID _REG( 0x400100 )
+#define rPCIDeviceID _REG( 0x400108 )
+#define rPCICommand _REG( 0x400110 )
+#define rPCIStatus _REG( 0x400118 )
+#define rPCIRevisionID _REG( 0x400120 )
+#define rPCIClassCode _REG( 0x400128 )
+#define rPCIHeaderType _REG( 0x400140 )
+
+
+//
+// Addrs non-dereferenced register declarations
+//
+#define rInterruptMask _ADDR(0x000100)
+#define rInterruptPending _ADDR(0x000200)
+//#define memCpuMailBox _ENDIAN(0x80002F80)
+#define memCpuMailBox 0x80002F80
+//
+// Use the value of the last defines register
+//
+#define NBPG 4096
+#define roundup(_X, _Y) (((_X) + ((_Y)-1)) / (_Y))
+#define btorp(_X) (roundup((_X), NBPG) )
+#define REGISTER_PAGES (btorp(0x400140))
+
+
+//
+// Place Macros/Masks/Bit Definitions in this area for each of the
+// control registers.
+//
+
+// rInterruptRequest
+// rInterruptRequestSet
+
+// rInterruptMask0
+// rInterruptMask1
+// rInterruptMask2
+// rInterruptMask3
+
+#define RInterruptMask(_CPU) \
+ (*(volatile ULONG * const)(rInterruptMask + (ULONG)((_CPU) << 3)))
+ //(*(volatile ULONG * const)(rInterruptMask + ((_CPU) * 8)))
+
+#define RInterruptPending(_CPU) \
+ (*(volatile ULONG * const)(rInterruptPending + ((_CPU) * 8)))
+
+//
+// To guarantee that the Mask write is complete we must insure that:
+// a) the ordering does not change and b) the all pending reads are
+// complete before we continue. Since we are reading the address
+// we write, the processor will not re-order the read/write. We
+// must use a "sync" to guarantee that the EE bit is not set
+// until after the data from the read of RInterruptMask returns.
+//
+#define WaitForRInterruptMask(_CPU) \
+ { \
+ volatile ULONG dummyVar; \
+ FireSyncRegister(); \
+ dummyVar = RInterruptMask(_CPU);\
+ __builtin_sync(); \
+ }
+
+
+#define MemSetCpuAddr(_CPU) \
+ (*(volatile ULONG * const)( memCpuMailBox + ( (( _CPU ) * 8 ) + 0x4 )))
+
+#define MemStartCpu(_CPU) \
+ (*(volatile ULONG * const)( memCpuMailBox + (( _CPU ) * 8 )))
+
+#define ALL_INTS_OFF 0x00000000
+#define ALL_INTS_ON 0xffffffff
+
+#define CPU_MESSAGE_NUM 31
+#define MEMORY_ERROR_VIDEO_NUM 30
+#define PCI_ERROR_NUM 29
+#define CPU_BUS_ERROR_NUM 28
+#define SIO_NMI_NUM 27
+
+#define LX_PCI_SLOT_0_NUM 26
+#define LX_PCI_SLOT_1_NUM 25
+#define LX_PCI_SLOT_2_NUM 24
+#define LX_PCI_SLOT_3_NUM 23
+#define LX_PCI_IDE_INTA_NUM 22
+#define LX_PCI_IDE_INTB_NUM 21
+
+#define ENET_NUM 26
+#define SCSI_NUM 25
+#define PCI_SLOT_1_NUM 23
+#define PCI_SLOT_0_NUM 22
+#define SOFTWARE0_NUM 19
+#define SOFTWARE1_NUM 18
+#define SOFTWARE2_NUM 17
+#define SOFTWARE3_NUM 16
+#define ISA_PIND06_NUM 15
+#define ISA_PIND07_NUM 14
+#define MOUSE_NUM 12
+#define ISA_PIND04_NUM 11
+#define AUDIO_NUM 10
+#define ISA_PINB04_NUM 9
+#define RTC_NUM 8
+#define PARALLEL_NUM 7
+#define FLOPPY_NUM 6
+#define DISPLAY_NUM 5
+#define SERIAL1_NUM 4
+#define SERIAL2_NUM 3
+#define KEYBOARD_NUM 1
+#define TIMER_NUM 0
+
+#define NUM_2_INT(x) (1 << x )
+
+#define CPU_MESSAGE_INT NUM_2_INT( CPU_MESSAGE_NUM )
+#define MEMORY_ERROR_VIDEO_INT NUM_2_INT( MEMORY_ERROR_VIDEO_NUM )
+#define PCI_ERROR_INT NUM_2_INT( PCI_ERROR_NUM )
+#define CPU_BUS_ERROR_INT NUM_2_INT( CPU_BUS_ERROR_NUM )
+#define SIO_NMI_INT NUM_2_INT( SIO_NMI_NUM )
+
+#define LX_PCI_SLOT_0_INT NUM_2_INT( LX_PCI_SLOT_0_NUM )
+#define LX_PCI_SLOT_1_INT NUM_2_INT( LX_PCI_SLOT_1_NUM )
+#define LX_PCI_SLOT_2_INT NUM_2_INT( LX_PCI_SLOT_2_NUM )
+#define LX_PCI_SLOT_3_INT NUM_2_INT( LX_PCI_SLOT_3_NUM )
+#define LX_PCI_IDE_INTA_INT NUM_2_INT( LX_PCI_IDE_INTA_NUM )
+#define LX_PCI_IDE_INTB_INT NUM_2_INT( LX_PCI_IDE_INTB_NUM )
+
+#define ENET_INT NUM_2_INT( ENET_NUM )
+#define SCSI_INT NUM_2_INT( SCSI_NUM )
+#define PCI_SLOT_1_INT NUM_2_INT( PCI_SLOT_1_NUM )
+#define PCI_SLOT_0_INT NUM_2_INT( PCI_SLOT_0_NUM )
+#define SOFTWARE0_INT NUM_2_INT( SOFTWARE0_NUM )
+#define SOFTWARE1_INT NUM_2_INT( SOFTWARE1_NUM )
+#define SOFTWARE2_INT NUM_2_INT( SOFTWARE2_NUM )
+#define SOFTWARE3_INT NUM_2_INT( SOFTWARE3_NUM )
+#define ISA_PIND06_INT NUM_2_INT( ISA_PIND06_NUM )
+#define ISA_PIND07_INT NUM_2_INT( ISA_PIND07_NUM )
+#define MOUSE_INT NUM_2_INT( MOUSE_NUM )
+#define ISA_PIND04_INT NUM_2_INT( ISA_PIND04_NUM )
+#define AUDIO_INT NUM_2_INT( AUDIO_NUM )
+#define ISA_PINB04_INT NUM_2_INT( ISA_PINB04_NUM )
+#define RTC_INT NUM_2_INT( RTC_NUM )
+#define PARALLEL_INT NUM_2_INT( PARALLEL_NUM )
+#define FLOPPY_INT NUM_2_INT( FLOPPY_NUM )
+#define DISPLAY_INT NUM_2_INT( DISPLAY_NUM )
+#define SERIAL1_INT NUM_2_INT( SERIAL1_NUM )
+#define SERIAL2_INT NUM_2_INT( SERIAL2_NUM )
+#define KEYBOARD_INT NUM_2_INT( KEYBOARD_NUM )
+#define TIMER_INT NUM_2_INT( TIMER_NUM )
+
+
+#define ALL_BITS_CLEAR 0xffffffff
+#define ENABLE_EISA_MASK 0x0000ffff
+#define SET_INTS_CLEAR 0xffffffff
+#define EISA_INTS_ON 0xffff0000
+#define SCSI_EISA_INT 0x00002000
+
+
+
+// rInterruptPending0
+// rInterruptPending1
+// rInterruptPending2
+// rInterruptPending3
+// rCPUMessageInterrupt
+// rCPUMessageInterruptSet
+
+
+// rPCIBusErrorCause
+// rPCIBusErrorCauseSet
+#define PCI_ERROR_SIGNALED_SYS 0x00000001
+#define PCI_ERROR_DATA_PARITY 0x00000002
+#define PCI_ERROR_DEV_TIMEOUT 0x00000004
+#define PCI_ERROR_TARGET_ABORT 0x00000008
+
+// rPCIBusErrorAddressRegister
+// rCPUBusErrorCause
+#define CPU_ERROR_ILLEGAL_SAACC 0x00000001
+#define CPU_ERROR_ADDR_PARITY 0x00000002
+#define CPU_ERROR_DISCONTIG_ISA 0x00000004
+
+// rCPUBusErrorCauseSet
+// rCPUBusErrorAddressRegister
+// rErrorStatus0
+#define ERROR_ECC_CORRECTED 0x02000000
+#define ERROR_ECC_FAILED 0x04000000
+#define ERROR_ADDR_PARITY 0x08000000
+#define ERROR_DATA_PARITY 0x10000000
+#define ERROR_MEM_PARITY 0x20000000
+#define ERROR_INVALID_XACT 0x40000000
+
+// rErrorStatus0Set
+// rErrorMask
+#define ECC_CORRECTED 0x02000000
+#define ECC_FAILED 0x04000000
+#define ADDRESS_PARITY_ERROR 0x08000000
+#define DATA_PARITY_ERROR 0x10000000
+#define MEM_PARITY_ERROR 0x20000000
+#define INVALID_XACT 0x40000000
+
+// rErrorAddr0
+// rErrorAddr1
+// rErrorAddr2
+// rErrorAddr3
+// rVidInt
+// rVidIntSet
+// rVidIntMask
+// rTscControl
+#define L2_PRESENT 0x01000000
+#define MP_CONFIG 0x04000000
+#define ECC_ENABLE 0x08000000
+#define LITTLE_ENDIAN 0x10000000
+#define BRIDGE_MODE 0x20000000
+
+// rFbControl
+#define CPU_VRAM_SWAP_BYTES 0x01000000
+#define CPU_VRAM_ADDR_MUNGE 0x02000000
+#define CPU_INVERT_FB_ADDR_LSB 0x04000000
+#define PCI_VRAM_SWAP_BYTES 0x08000000
+#define PCI_VRAM_SWAP_ENABLES 0x10000000
+#define PCI_INVERT_FB_ADDR2 0x20000000
+
+// rEsccControl
+// rEsccL2FLush
+// rScratchPad0
+// rScratchPad1
+// rScratchPad2
+// rLowPowerControl
+// rRomControl
+// rTscStatus0
+#define ROM_BUSY 0x00000001
+#define WRQ_FULL 0x00000002
+#define I2Q_FULL 0x00000004
+#define WRQ_EMPTY 0x00000008
+#define I2Q_EMPTY 0x00000010
+//#define CPU_MASK 0x000000c0
+#define CPU_MASK 0xc0000000
+#define GetCpuId() ((rTscStatus0 & CPU_MASK) >> 30)
+
+// rTscRevision
+// rMemBank0Config
+// rMemBank1Config
+// rMemBank2Config
+// rMemBank3Config
+// rMemBank4Config
+// rMemBank5Config
+// rMemBank6Config
+// rMemBank7Config
+// rMemDramTiming
+// rMemVramTiming
+// rMemRefresh
+// rVidControl
+// rVidPixelsPerLineLo
+// rVidPixelsPerLineHi
+// rIOControl
+// rPCIConfigType
+#define PCI_TYPE1_CYCLE 0x00000001
+
+// rPIOPendingCount
+#define PENDING_COUNTMASK 0x0000007f
+#define PCI_BRIDGE_MODE 0x00000080
+
+// rDMAPendingCount
+// rPCIVendorID
+// rPCIDeviceID
+// rPCICommand
+// rPCIStatus
+#define PCI_DATA_PARITY_ERROR 0x00008000
+#define PCI_SIGNLD_SYSTEM_ERR 0x00004000
+#define PCI_RCVD_MASTER_ABORT 0x00002000
+#define PCI_RCVD_TARGET_ABORT 0x00001000
+#define PCI_SGNLD_TARGET_ABORT 0x00000800
+#define PCI_DATA_PARITY_DETECT 0x00000100
+
+// rPCIRevisionID
+// rPCIClassCode
+// rPCIHeaderType
+
+#endif // FPREG_H
diff --git a/private/ntos/nthals/halfire/ppc/fprgstry.c b/private/ntos/nthals/halfire/ppc/fprgstry.c
new file mode 100644
index 000000000..846ecb301
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fprgstry.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fprgstry.c $
+ * $Revision: 1.40 $
+ * $Date: 1996/05/14 02:33:02 $
+ * $Locker: $
+ */
+
+/* mogawa
+ * HalpInitializeRegistry fails if it is put in HalInitSystem().
+ * So I moved it in HalReportResourceUsage(VOID) in pxpro.c.
+ * Still L"\\Registry\\Machine\\Software\\FirePower" can not be used.
+ * L"\\Registry\\Machine\\Hardware\\FirePower" can be created successfully.
+ */
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+#include "phsystem.h"
+#include "stdio.h"
+#include "string.h"
+#include "fpdebug.h"
+#include "fparch.h"
+#include "fpi2c.h"
+#include "fpcpu.h"
+
+#define TBS " "
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+extern WCHAR rgzSystem[];
+extern WCHAR rgzSoftwareDescriptor[];
+extern WCHAR rgzFirePOWERNode[];
+extern WCHAR rgzCpuNode[];
+extern WCHAR rgzHalNode[];
+extern WCHAR rgzVeneerNode[];
+extern WCHAR rgzFirmwareNode[];
+extern NTSTATUS RtlCharToInteger ( PCSZ String, ULONG Base, PULONG Value );
+extern ULONG CpuClockMultiplier;
+extern ULONG ProcessorBusFrequency;
+extern ULONG TimeBaseCount;
+extern ULONG HalpPerformanceFrequency;
+
+
+BOOLEAN HalpInitializeRegistry (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+VOID HalpTranslateSystemSpecificData ( VOID );
+VOID HalpSetUpFirePowerRegistry(VOID);
+VOID HalpSetUpSystemBiosKeys( VOID );
+
+/* unfortunately the following data must be stored somewhere
+ * because it is not possible to get these data except when HalinitSystem.
+ * Registry does not exist when HalInitSystem.
+ */
+#define FIRMWARE_BUF_SIZE 64
+static char firmwareBuf[FIRMWARE_BUF_SIZE];
+static char veneerBuf[64];
+static ULONG FirstLevelIcacheSize;
+static ULONG FirstLevelDcacheSize;
+static ULONG SecondLevelCacheSize;
+
+VOID
+HalpTranslateSystemSpecificData ( VOID)
+{
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status = STATUS_SEVERITY_INFORMATIONAL;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ WCHAR wstr[8];
+ ULONG i, junk;
+ PPCI_REGISTRY_INFO PCIRegInfo = NULL;
+
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ //
+ // Search the hardware description looking for the cpu node:
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzCpuNode);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("HalpTranslateSystemSpecificData: ");
+ HalpDebugPrint("ZwOpenKey returned !NT_SUCCESS \n"));
+ return;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ //
+ // Now that we have a handler for the node, look for all instances of this
+ // type. I.E.: Instances are ordinally enumerated 0,1,...
+ //
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Cpu entries:
+ //
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("Out of CentralProcessor Entries \n"););
+ break;
+ }
+
+ //
+ // The first CPU entry has the CM_SYSTEM_GENERAL_DATA structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ //
+ // Set Desc to point to the classes at the proscribed offset. Since
+ // we're looking at a configuration_descriptor, all the data will be
+ // after the header, at the offset...
+ //
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR)
+ ((PUCHAR)ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ ((PUCHAR)Desc->PartialResourceList.PartialDescriptors);
+
+ while (PDesc->Type != CmResourceTypeDeviceSpecific) {
+ //PDesc+= (PCM_PARTIAL_RESOURCE_DESCRIPTOR)1;
+ PDesc += 1;
+ }
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+ ZwClose (hMFunc);
+}
+
+/*---------------------------------------------------------------------------*/
+VOID
+HalpSetValueKeyString(
+ HANDLE key,
+ PCHAR nameBuffer,
+ PCHAR dataBuffer
+ )
+{
+ UNICODE_STRING nameUnicodeString;
+ UNICODE_STRING dataUnicodeString;
+ ANSI_STRING nameString, dataString;
+ NTSTATUS status;
+ PCHAR junkPtr;
+
+ if (NULL == dataBuffer) return;
+
+ RtlInitString (&nameString,
+ nameBuffer
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &nameUnicodeString,
+ &nameString,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpSetValueKeyString: RtlAnsiStringToUnicodeString failed. '%s': (0x%x) \n", nameBuffer, status));
+ return;
+ }
+
+ dataString.MaximumLength = 256;
+ dataString.Buffer = dataBuffer;
+
+ junkPtr = memchr(
+ &dataString.Buffer[0],
+ 0x00,
+ dataString.MaximumLength
+ );
+
+ if (!junkPtr) {
+ dataString.Length = dataString.MaximumLength;
+ } else {
+ dataString.Length = junkPtr - &dataString.Buffer[0];
+ }
+
+ status = RtlAnsiStringToUnicodeString(
+ &dataUnicodeString,
+ &dataString,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ status = ZwSetValueKey(
+ key,
+ &nameUnicodeString,
+ 0,
+ REG_SZ,
+ dataUnicodeString.Buffer,
+ dataUnicodeString.Length + sizeof(wchar_t));
+
+ RtlFreeUnicodeString(&dataUnicodeString);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("ZwSetValueKey failed. (0x%x) \n", status));
+ }
+ }
+ RtlFreeUnicodeString(&nameUnicodeString);
+}
+
+
+/*---------------------------------------------------------------------------*/
+VOID
+HalpSetValueKeyMultiString(
+ HANDLE key,
+ PCHAR nameBuffer,
+ PCHAR dataBuffer
+ )
+{
+ UNICODE_STRING nameUnicodeString;
+ UNICODE_STRING dataUnicodeString;
+ ANSI_STRING nameString, dataString;
+ NTSTATUS status;
+ PCHAR junkPtr;
+
+ if (NULL == dataBuffer) return;
+
+ RtlInitString (&nameString,
+ nameBuffer
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &nameUnicodeString,
+ &nameString,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpSetValueKeyString: RtlAnsiStringToUnicodeString failed. '%s': (0x%x) \n", nameBuffer, status));
+ return;
+ }
+
+ dataString.MaximumLength = 256;
+ dataString.Buffer = dataBuffer;
+
+ junkPtr = memchr(
+ &dataString.Buffer[0],
+ 0x00,
+ dataString.MaximumLength
+ );
+
+ if (!junkPtr) {
+ dataString.Length = dataString.MaximumLength;
+ } else {
+ dataString.Length = junkPtr - &dataString.Buffer[0];
+ }
+
+ status = RtlAnsiStringToUnicodeString(
+ &dataUnicodeString,
+ &dataString,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ status = ZwSetValueKey(
+ key,
+ &nameUnicodeString,
+ 0,
+ REG_MULTI_SZ,
+ dataUnicodeString.Buffer,
+ dataUnicodeString.Length + sizeof(wchar_t));
+
+ RtlFreeUnicodeString(&dataUnicodeString);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("ZwSetValueKey failed. (0x%x) \n", status));
+ }
+ }
+ RtlFreeUnicodeString(&nameUnicodeString);
+}
+
+
+VOID
+HalpSetValueKeyUlong(
+ HANDLE key,
+ PCHAR str,
+ ULONG version
+ )
+{
+ CHAR buffer[16+1];
+
+ sprintf(buffer, "%08x", version);
+ HalpSetValueKeyString(key, str, buffer);
+}
+
+ULONG
+HalpVersionSystemInRegistry(SYSTEM_TYPE System, HANDLE key)
+{
+ ULONG TscRevision=0;
+ ULONG PciRevision=0;
+ ULONG ProcessorVersion, ProcessorRevision, ProcHertz;
+ PCHAR debugStr;
+ CCHAR buffer[256];
+ extern RelInfo ThisOne;
+ extern ULONG HalpVideoMemorySize; // pxdisp.c
+
+
+ switch(System) {
+
+ case SYS_POWERTOP :
+ case SYS_POWERSLICE:
+ case SYS_POWERSERVE:
+ TscRevision = (rTscRevision & 0xff000000) >> 24; // bits 7:0
+ PciRevision = (rPCIRevisionID & 0xff000000) >> 24; // bits 7:0
+
+ sprintf(buffer, "%d", TscRevision);
+ HalpSetValueKeyString(key, "TSC Revision", buffer);
+ sprintf(buffer, "%d", PciRevision);
+ HalpSetValueKeyString(key, "TIO Revision", buffer);
+ break;
+
+ case SYS_POWERPRO :
+ PciRevision = (rPCIRevisionID & 0xff000000) >> 24; // bits 7:0
+ sprintf(buffer, "%d", PciRevision);
+ HalpSetValueKeyString(key, "ESCC Revision", buffer);
+ break;
+
+ case SYS_UNKNOWN :
+ HalpDebugPrint("Unknown system type \n");
+ break;
+
+ default: // unknown stuff? should never get here
+ break;
+ }
+#if DBG==1
+ debugStr = "(DEBUG)";
+#else
+ debugStr = "";
+#endif
+ sprintf(buffer, "%d.%d %s %s, %s",
+ (ULONG)ThisOne.Major, (ULONG)ThisOne.Minor, debugStr,
+ ThisOne.BuildDate, ThisOne.BuildTime);
+
+ HalpSetValueKeyString(key, "HAL Version", buffer);
+
+ ProcessorVersion = HalpGetProcessorVersion();
+ ProcessorRevision = ProcessorVersion & 0x0000ffff;
+ ProcessorVersion = ProcessorVersion >> 16;
+
+ sprintf(buffer, "%d", 600+ProcessorVersion);
+ HalpSetValueKeyString(key, "Processor", buffer);
+ sprintf(buffer, "%d.%d", ProcessorRevision/256, ProcessorRevision%256);
+ HalpSetValueKeyString(key, "Processor Revision", buffer);
+
+ //
+ // Display the Model Number and our company name
+ //
+ ProcHertz = HalpGetCycleTime();
+ sprintf(buffer, "%d MHz", ProcHertz);
+ HalpSetValueKeyString(key, "Processor Clock Frequency", buffer);
+
+ //
+ // Display the Frequency Multiplier for the Cpu:
+ // two digits are enough. bug 5182
+ //
+ sprintf(buffer, "%d.%02d MHz",ProcessorBusFrequency/1000000,
+ (ProcessorBusFrequency -
+ ((ProcessorBusFrequency / 1000000) * 1000000))/ 10000);
+ HalpSetValueKeyString(key, "Processor Bus Frequency", buffer);
+
+ //
+ // Now figure out what the clock multiplier should look like
+ // in the registery:
+ //
+ if ((CpuClockMultiplier == 25) || (CpuClockMultiplier==15)) {
+ sprintf(buffer, "%d.5", CpuClockMultiplier/10);
+ } else {
+ sprintf(buffer, "%d", CpuClockMultiplier/10);
+ }
+ HalpSetValueKeyString(key, "Processor Clock Multiplier", buffer);
+
+ //
+ // For debug HALs, enable registry storage of timing calculations.
+ //
+ HDBG(DBG_TIME, sprintf(buffer, "%d",TimeBaseCount ));
+ HDBG(DBG_TIME,
+ HalpSetValueKeyString(key, "SYSTEM DEBUG: TimeBaseCount", buffer));
+ HDBG(DBG_TIME,sprintf(buffer, "%d",HalpPerformanceFrequency ));
+ HDBG(DBG_TIME,
+ HalpSetValueKeyString(key, "SYSTEM DEBUG: HalpPerformanceFrequency",
+ buffer));
+
+#if DBG==1
+ sprintf(buffer, "0x%08x",HalpDebugValue );
+ HalpSetValueKeyString(key, "DEBUG HALDEBUG", buffer);
+#endif
+
+ sprintf(buffer, "Powerized %s", SystemDescription[SystemType].SystemName);
+
+ HalpSetValueKeyString(key, "Hardware", buffer);
+ HalpSetValueKeyString(key, "IEEE 1275 Firmware Version", firmwareBuf);
+ HalpSetValueKeyString(key, "ARC Veneer Version", veneerBuf);
+ sprintf(buffer, "%dK bytes", FirstLevelIcacheSize/1024);
+ HalpSetValueKeyString(key, "First Level Icache Size", buffer);
+ sprintf(buffer, "%dK bytes", FirstLevelDcacheSize/1024);
+ HalpSetValueKeyString(key, "First Level Dcache Size", buffer);
+ sprintf(buffer, "%dK bytes per CPU", SecondLevelCacheSize/1024);
+ HalpSetValueKeyString(key, "Second Level Cache Size", buffer);
+
+ if (HalpVideoMemorySize < 0x100000) {
+ sprintf(buffer, "%dK bytes", HalpVideoMemorySize/1024);
+ } else {
+ sprintf(buffer, "%dM bytes", HalpVideoMemorySize/0x100000);
+ }
+ if ((System == SYS_POWERPRO) || (System == SYS_POWERTOP)) {
+ HalpSetValueKeyString(key, "MLU VRAM", buffer);
+ }
+ // ALL platforms fill in the registry information, even if they have
+ // no IIC
+ HalpSetUpRegistryForI2C(System);
+
+ return(1); // success, true, good, ...
+}
+
+NTSTATUS
+HalpCreateKey(HANDLE *pNode, PWCHAR rgzKey)
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ ULONG disposition;
+
+ RtlInitUnicodeString (&unicodeString,
+ rgzKey
+ );
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(pNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Did not create key: (0x%x) \n", status));
+ } else {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("Did create key: (0x%x) \n", status));
+ }
+ return status;
+}
+
+/* called from HalReportResourceUsage(VOID) in pxproc. */
+VOID
+HalpSetUpFirePowerRegistry(
+ VOID
+ )
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ HANDLE hNode;
+ ULONG disposition;
+
+ static CCHAR szFirePower[] =
+ "\\Registry\\Machine\\Hardware\\Powerized"; //mogawa
+ STRING strFirePower;
+ UNICODE_STRING ucFirePower;
+ //
+ // Open up the FirePOWER entry in the registry, create it if it's not there:
+ // Actually, just create it since create will default to open if the entry
+ // is already present.
+ //
+ RtlInitString (&strFirePower,
+ szFirePower
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &ucFirePower,
+ &strFirePower,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Could not create unicode strings: (0x%x) \n",
+ status));
+ return;
+ }
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &ucFirePower,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(&hNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Did not create key: (0x%x) \n", status););
+ RtlFreeUnicodeString(&ucFirePower);
+ return;
+ }
+ //ZwFlushKey(hNode);
+ HalpVersionSystemInRegistry(SystemType, hNode);
+ if (NULL != hNode) {
+ ZwClose (hNode);
+ }
+ RtlFreeUnicodeString(&ucFirePower);
+ HalpSetUpSystemBiosKeys();
+ return;
+}
+
+
+/* called from HalReportResourceUsage(VOID) in pxproc. */
+VOID
+HalpSetUpSystemBiosKeys(
+ VOID
+ )
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ HANDLE hNode;
+ CCHAR versionString[256];
+ PUCHAR pDateString = "";
+ ULONG disposition;
+ ULONG i;
+ BOOLEAN DateStringFound = FALSE;
+
+ static CCHAR szFirePower[] =
+ "\\Registry\\Machine\\Hardware\\Description\\System";
+ STRING strFirePower;
+ UNICODE_STRING ucFirePower;
+ //
+ // Open up the FirePOWER entry in the registry, create it if it's not there:
+ // Actually, just create it since create will default to open if the entry
+ // is already present.
+ //
+ RtlInitString (&strFirePower,
+ szFirePower
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &ucFirePower,
+ &strFirePower,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Could not create unicode strings: (0x%x) \n",
+ status));
+ return;
+ }
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &ucFirePower,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(&hNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Did not create key: (0x%x) \n", status););
+ RtlFreeUnicodeString(&ucFirePower);
+ return;
+ }
+ //ZwFlushKey(hNode);
+
+ // Seperate the version and date strings in the firmwareBuf identifier
+ // ASSUMES that the month is the first item of the date and it starts
+ // with an uppercase letter.
+ for (i=0; i < FIRMWARE_BUF_SIZE; i++) {
+ if (firmwareBuf[i] >= 'A' && firmwareBuf[i] <= 'Z') {
+ pDateString = &firmwareBuf[i];
+ versionString[i] = '\0';
+ DateStringFound = TRUE;
+ break;
+ }
+ versionString[i] = firmwareBuf[i];
+ }
+
+ HASSERT(DateStringFound);
+
+ HalpSetValueKeyString(hNode, "SystemBiosDate", pDateString);
+ HalpSetValueKeyString(hNode, "SystemBiosVersion", versionString);
+ HalpSetValueKeyString(hNode, "VideoBiosDate", "");
+ HalpSetValueKeyString(hNode, "VideoBiosVersion", "");
+ if (NULL != hNode) {
+ ZwClose (hNode);
+ }
+ RtlFreeUnicodeString(&ucFirePower);
+ return;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static VOID HalpAppendSprintf(
+ PCHAR buffer,
+ PCHAR format,
+ ...
+ )
+{
+ va_list arglist;
+ ULONG length;
+ UCHAR tempBuf[256];
+
+ va_start(arglist, format);
+ length = vsprintf(tempBuf, format, arglist);
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpAppendSprintf: tempBuf='%s'\n", tempBuf));
+ if (length) {
+ strcat(buffer, tempBuf);
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpAppendSprintf: vsprintf returned length=%n\n",
+ length));
+ }
+}
+
+static PCHAR
+gettoken(PCHAR token, PCHAR buf, CHAR delim)
+{
+ CHAR c;
+ while (c = *buf) {
+ if (c == delim) {
+ buf++;
+ break;
+ } else {
+ *token++ = c;
+ buf++;
+ }
+ }
+ *token = '\0';
+ return buf;
+}
+
+static VOID
+HalpSetVersionData( IN PCHAR VersionData
+ )
+{
+
+ while (*VersionData) {
+ enum {Firmware = 0, Veneer = 1, Nada};
+ ULONG type;
+ PCHAR typeStr[2] = {"Firmware", "Veneer"};
+ CHAR token[64];
+ PCHAR tok = VersionData;
+ PCHAR buffer;
+ CHAR buf[80];
+ buffer = (PCHAR)0; // to satisfy warnings
+
+ VersionData += strlen(VersionData)+1;
+
+ if (strstr(tok, typeStr[Firmware])) {
+ type = Firmware;
+ buffer = firmwareBuf;
+ buffer[0] = '\0';
+ } else {
+ if (strstr(tok, typeStr[Veneer])) {
+ type = Veneer;
+ buffer = veneerBuf;
+ buffer[0] = '\0';
+ } else {
+ type = Nada;
+ }
+ }
+ if (Nada == type) {
+ continue;
+ }
+ /* else */
+
+ if (*VersionData) {
+ LONG n;
+
+ tok = VersionData;
+ VersionData += strlen(VersionData)+1;
+ n = 0;
+ tok = gettoken(token, tok, ',');
+
+ while (*token) {
+ switch (n++) {
+ case 2:
+ strcpy(buf, token);
+ strcat(buf, "\0");
+ if (strlen(buf) < 7) {
+ HalpAppendSprintf(buffer, "%-7s", buf);
+ } else {
+ HalpAppendSprintf(buffer, "%s ", buf);
+ }
+ break;
+ case 3:
+ //
+ // Put date in Mmm dd yyyy format if in yyyy-mm-dd
+ // No unicode here :-).
+ // isdigit() causes too many link hassles.
+ // We CANNOT change the case of the first letter of the
+ // month without changing HalpSetUpSystemBiosKeys
+ //
+ if (type == Firmware && *token >= '0' && *token <= '9') {
+ PCHAR day;
+ PCHAR month;
+ PCHAR year;
+ PCHAR Mmm[12] = {
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec",
+ };
+
+ strcpy(buf, token);
+ if (day = strrchr(buf, '-')) {
+ *day++ = '\0';
+ if (month = strrchr(buf, '-')) {
+ ULONG i;
+ *month++ = '\0';
+ RtlCharToInteger(month, 10, &i);
+ if (i > 12 || i < 1) {
+ HalpAppendSprintf(buffer, "%s, ", token);
+ } else {
+ year = buf;
+ //
+ // Decrement the month by one to align with
+ // zero based nature of the Mmm array.
+ //
+ HalpAppendSprintf(buffer, "%s %s %s, ",
+ Mmm[i-1], day, year);
+ }
+ }
+ } else {
+ HalpAppendSprintf(buffer, "%s, ", token);
+ }
+ } else {
+ HalpAppendSprintf(buffer, "%s, ", token);
+ }
+ break;
+ case 4:
+ HalpAppendSprintf(buffer, "%s", token);
+ break;
+ } // end of switch......
+ tok = gettoken(token, tok, ',');
+
+ }
+ }
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpSetVersionData: %s\n", buffer);
+ );
+
+ } /* while */
+}
+
+/* called in HalInitSystem phase 1 in pxinithl.c */
+BOOLEAN
+HalpInitializeRegistry ( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ PCHAR versionData;
+ extern PCHAR HalpGetVersionData( IN PLOADER_PARAMETER_BLOCK );
+
+
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: FirstLevelDcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.FirstLevelDcacheSize));
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: FirstLevelIcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.FirstLevelDcacheSize));
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: SecondLevelDcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.SecondLevelDcacheSize));
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: SecondLevelIcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.SecondLevelIcacheSize));
+ FirstLevelIcacheSize = LoaderBlock->u.Ppc.FirstLevelIcacheSize;
+ FirstLevelDcacheSize = LoaderBlock->u.Ppc.FirstLevelDcacheSize;
+ SecondLevelCacheSize = LoaderBlock->u.Ppc.SecondLevelDcacheSize;
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ CacheClass,
+ PrimaryIcache,
+ &MatchKey);
+ if (ConfigurationEntry) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: PrimaryIcache Key=0x%08x\n",
+ ConfigurationEntry->ComponentEntry.Key););
+
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: KeFindConfigurationEntry PrimaryICache failed\n"));
+ }
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ CacheClass,
+ PrimaryDcache,
+ &MatchKey);
+
+ if (ConfigurationEntry) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: PrimaryDcache Key=0x%08x\n",
+ ConfigurationEntry->ComponentEntry.Key));
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: KeFindConfigurationEntry PrimaryDcache failed\n"););
+ }
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ CacheClass,
+ SecondaryCache,
+ &MatchKey);
+ if (ConfigurationEntry) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: SecondaryCache Key=0x%x\n",
+ ConfigurationEntry->ComponentEntry.Key));
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: KeFindConfigurationEntry SecondaryCache failed\n"));
+ }
+
+ if ( versionData = HalpGetVersionData(LoaderBlock) ) {
+ HalpSetVersionData(versionData);
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: HalpGetVersionData failed.\n"));
+ }
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halfire/ppc/halp.h b/private/ntos/nthals/halfire/ppc/halp.h
new file mode 100644
index 000000000..14862b25e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/halp.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: halp.h $
+ * $Revision: 1.20 $
+ * $Date: 1996/05/14 02:33:08 $
+ * $Locker: $
+ */
+
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added PPC specific includes
+ Changed paramaters to HalpProfileInterrupt
+ Added function prototype for HalpWriteCompareRegisterAndClear()
+ Added include for ppcdef.h
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+
+
+#include "ppcdef.h"
+
+#include "hal.h"
+#include "pxhalp.h"
+
+
+
+
+// Debug prints. see pxdisp.c
+#include <stdarg.h>
+
+VOID HalpDebugPrint( PCHAR Format, ... );
+VOID HalpForceDisplay( PCHAR Format, ... );
+
+//
+// Resource usage information
+//
+
+#define MAXIMUM_IDTVECTOR 255
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+#define HalpGetProcessorVersion() KeGetPvr()
+
+#define HalpEnableInterrupts() _enable()
+#define HalpDisableInterrupts() _disable()
+
+#define KeFlushWriteBuffer() __builtin_eieio()
+
+//
+// Bus handlers
+//
+
+
+PBUS_HANDLER HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN BUS_DATA_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpAllocateConfigSpace HalpAllocateBusHandler
+
+#define HalpHandlerForBus HaliHandlerForBus
+
+#define SPRANGEPOOL NonPagedPool // for now, until crashdump is fixed
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+
+BOOLEAN
+HalpCalibrateTimingValues (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ );
+
+VOID
+HalpHandleIoError (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ );
+
+BOOLEAN
+HalpHandleProfileInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitSuperIo(
+ VOID
+ );
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ );
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableLength,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ );
+
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KAFFINITY HalpIsaBusAffinity;
+extern ULONG HalpProfileCount;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+
+#define IRQ_VALID 0x01
+#define IRQ_PREFERRED 0x02
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halfire/ppc/pcibios.c b/private/ntos/nthals/halfire/ppc/pcibios.c
new file mode 100644
index 000000000..a6ec9a959
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pcibios.c
@@ -0,0 +1,1084 @@
+/*++
+
+
+Copyright (C) 1996 Motorola Inc.
+
+Module Name:
+
+ pcibios.c
+
+Abstract:
+
+ Emulate PCI BIOS functions.
+
+ Note that the HAL bus functions (HalGetBusData, etc.) are not
+ available at this phase of initialization, all of the work has
+ to be done here.
+
+Author:
+
+ Scott Geranen
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+
+#include "emulate.h"
+#include "pcibios.h"
+
+UCHAR SBReadConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+USHORT SBReadConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+ULONG SBReadConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+VOID SBWriteConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN UCHAR Data
+ );
+
+VOID SBWriteConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN USHORT Data
+ );
+
+VOID SBWriteConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN ULONG Data
+ );
+
+//
+// Last PCI bus in the system.
+//
+extern UCHAR HalpLastPciBus;
+
+//
+// Ports to be used to access config space.
+//
+#define CONFIG_ADDR_PORT (0x00000CF8)
+#define CONFIG_DATA_PORT (0x00000CFC)
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ );
+
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ );
+
+BOOLEAN
+HalpEmulatePciBios(
+ IN OUT PRXM_CONTEXT P
+ )
+/*++
+
+Routine Description:
+
+ This function emulates the PCI BIOS Specification, revision 2.1. The
+ specification is available from the PCI Special Interest Group.
+
+ This function assumes that it is being called during phase 0 initialization.
+ The PCI bus functions are not available at this point, e.g. HalGetBusData.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ TRUE (PCI BIOS was emulated)
+
+--*/
+{
+#if DBG
+ VOID TestPciBios(int flag);
+
+ TestPciBios(0);
+#endif
+
+ switch (P->Gpr[EAX].Xl) {
+
+ case PCIBIOS_PCI_BIOS_PRESENT: // Installation Check
+
+ KdPrint(("PCI_BIOS_PRESENT\n"));
+
+ P->Gpr[EDX].Exx = 0x20494350; // "PCI "
+
+ P->Gpr[EAX].Xh = 0x00; // 00 == BIOS present
+ P->Gpr[EAX].Xl = 0x11; // PCI Hardware Characteristics (mech #1)
+
+ P->Gpr[EBX].Xh = 0x02; // PCI Interface Level Major Version
+ P->Gpr[EBX].Xl = 0x10; // PCI Interface Level (BCD)
+
+ P->Gpr[ECX].Xl = HalpLastPciBus; // Last PCI bus number
+
+ P->Eflags.CF = 0; // reset == PCI BIOS present
+
+ break;
+
+ case PCIBIOS_FIND_PCI_DEVICE:
+ {
+ USHORT DevID = P->Gpr[ECX].Xx;
+ USHORT VenID = P->Gpr[EDX].Xx;
+ USHORT DevIndex = P->Gpr[ESI].Xx;
+
+ UCHAR Bus, Device, Function, Header, NumFunctions;
+ BOOLEAN Found = FALSE;
+
+ KdPrint(("Looking for instance %d of 0x%X, 0x%X\n", DevIndex, DevID, VenID));
+
+ if (VenID == 0xFFFF) {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_VENDOR_ID;
+ P->Eflags.CF = 1; // set == error
+
+ } else {
+
+ for (Bus = 0; Bus <= HalpLastPciBus; Bus++) {
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+
+ if (SBReadConfigWord(Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) {
+
+ continue; // no device here
+
+ }
+
+ Header = SBReadConfigByte(
+ Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType));
+
+ NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1;
+
+ for (Function = 0; Function < NumFunctions; Function++) {
+
+ if (SBReadConfigWord(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == VenID) {
+
+ if (SBReadConfigWord(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID)) == DevID) {
+
+ Found = (DevIndex == 0);
+ DevIndex--;
+ }
+ }
+ if (Found) break; // function
+ }
+ if (Found) break; // device
+ }
+ if (Found) break; // bus
+ }
+
+ if (Found) {
+
+ KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function));
+
+ P->Gpr[EBX].Xh = Bus;
+ P->Gpr[EBX].Xl = (Device << 3) + Function;
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+
+ P->Eflags.CF = 0; // clear == success
+
+ } else {
+
+ KdPrint(("Not found\n"));
+
+ P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND;
+
+ P->Eflags.CF = 1; // set == error
+ }
+
+ }
+ }
+ break;
+
+
+ case PCIBIOS_FIND_PCI_CLASS_CODE:
+ {
+ ULONG ClassCode = (P->Gpr[ECX].Exx) << 8; // see comments below
+ USHORT DevIndex = P->Gpr[ESI].Xx;
+
+ UCHAR Bus, Device, Function, Header, NumFunctions;
+ BOOLEAN Found = FALSE;
+
+ KdPrint(("Looking for class instance %d of 0x%X\n", DevIndex, P->Gpr[ECX].Exx));
+
+ for (Bus = 0; Bus <= HalpLastPciBus; Bus++) {
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+
+ if (SBReadConfigWord(Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) {
+
+ continue; // no device here
+
+ }
+
+ Header = SBReadConfigByte(
+ Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType));
+
+ NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1;
+
+ for (Function = 0; Function < NumFunctions; Function++) {
+
+ //
+ // The class code bytes are in the same Dword as
+ // the revision id:
+ //
+ // Byte
+ // 3 2 1 0
+ // +-------------------+--------+
+ // | class code | Rev id |
+ // +-------------------+--------+
+ //
+ // Read the Dword and mask off the revision id.
+ // The class code we are looking for has been
+ // shifted up already above.
+ //
+ if ((SBReadConfigDword(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID))
+ & 0xFFFFFF00) == ClassCode) {
+
+ Found = (DevIndex == 0);
+ DevIndex--;
+ }
+ if (Found) break; // function
+ }
+ if (Found) break; // device
+ }
+ if (Found) break; // bus
+ }
+
+ if (Found) {
+
+ KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function));
+
+ P->Gpr[EBX].Xh = Bus;
+ P->Gpr[EBX].Xl = (Device << 3) + Function;
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+
+ P->Eflags.CF = 0; // clear == success
+
+ } else {
+
+ KdPrint(("Not found\n"));
+
+ P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND;
+
+ P->Eflags.CF = 1; // set == error
+ }
+ }
+ break;
+
+ case PCIBIOS_READ_CONFIG_BYTE:
+
+ KdPrint(("read byte %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Xl = SBReadConfigByte(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xl));
+
+ break;
+
+ case PCIBIOS_READ_CONFIG_WORD:
+
+ KdPrint(("read word %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 1) == 0) {
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Xx = SBReadConfigWord(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xx));
+
+ break;
+
+ case PCIBIOS_READ_CONFIG_DWORD:
+
+ KdPrint(("read Dword %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 3) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Exx = SBReadConfigDword(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Exx));
+
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_BYTE:
+
+ KdPrint(("Write byte 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Xl, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigByte( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Xl); // Value
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_WORD:
+
+ KdPrint(("Write word 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Xx, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 1) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigWord( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Xx); // Value
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_DWORD:
+
+ KdPrint(("Write Dword 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Exx, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 3) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigDword( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Exx); // Value
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ break;
+
+ case PCIBIOS_GENERATE_SPECIAL_CYCLE:
+ {
+ PCI_TYPE1_CFG_BITS Addr;
+
+ KdPrint(("Generate Special cycle %d, 0x%X\n",
+ P->Gpr[EBX].Xh, // Bus
+ P->Gpr[ECX].Exx)); // Value
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = P->Gpr[EBX].Xh;
+ Addr.u.bits.DeviceNumber = 0x1f;
+ Addr.u.bits.FunctionNumber = 7;
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_DATA_PORT, P->Gpr[EDX].Exx);
+
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+ }
+
+ break;
+
+
+ case PCIBIOS_GET_IRQ_ROUTING_OPTIONS: // not supported
+ case PCIBIOS_SET_IRQ_ROUTING_OPTIONS: // not supported
+ default:
+
+ KdPrint(("PCI BIOS: function %x not supported\n", P->Gpr[EAX].Xl));
+
+ P->Gpr[EAX].Xh = PCIBIOS_FUNC_NOT_SUPPORTED;
+
+ P->Eflags.CF = 1; // set == error
+
+ break;
+ }
+
+ return TRUE;
+}
+
+UCHAR
+SBReadConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ ULONG ByteInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ ByteInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ return((UCHAR)x86BiosReadIoSpace (BYTE_DATA, (USHORT)(CONFIG_DATA_PORT + ByteInRegister)));
+
+}
+
+USHORT
+SBReadConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ ULONG WordInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ WordInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ return((USHORT)x86BiosReadIoSpace (WORD_DATA, (USHORT)(CONFIG_DATA_PORT + WordInRegister)));
+
+}
+
+ULONG
+SBReadConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ return(x86BiosReadIoSpace (LONG_DATA, (USHORT)CONFIG_DATA_PORT));
+
+}
+
+VOID
+SBWriteConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN UCHAR Data
+ )
+{
+ ULONG ByteInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ ByteInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+
+ x86BiosWriteIoSpace (
+ BYTE_DATA,
+ (USHORT)(CONFIG_DATA_PORT + ByteInRegister),
+ Data
+ );
+
+}
+
+VOID
+SBWriteConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN USHORT Data
+ )
+{
+ ULONG WordInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ WordInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+
+ x86BiosWriteIoSpace (
+ WORD_DATA,
+ (USHORT)(CONFIG_DATA_PORT + WordInRegister),
+ Data
+ );
+
+}
+
+VOID
+SBWriteConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN ULONG Data
+ )
+{
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+
+ x86BiosWriteIoSpace (
+ LONG_DATA,
+ CONFIG_DATA_PORT,
+ Data
+ );
+
+}
+
+
+#if DBG
+
+// Modify this code to match your particular HW configuration
+//
+// Use the debugger to force flag to 1.
+
+VOID
+initregs(PRXM_CONTEXT P)
+{
+ P->Gpr[EAX].Exx = 0x1234B100;
+ P->Gpr[EBX].Exx = 0x23456789;
+ P->Gpr[ECX].Exx = 0x3456789A;
+ P->Gpr[EDX].Exx = 0x456789AB;
+ P->Gpr[ESP].Exx = 0x87654321;
+ P->Gpr[EBP].Exx = 0x98765432;
+ P->Gpr[ESI].Exx = 0xA9876543;
+ P->Gpr[EDI].Exx = 0xBA987654;
+
+ P->Eflags.CF = 1;
+}
+
+VOID
+dumpregs(PRXM_CONTEXT P)
+{
+ DbgPrint("Carry = %d\n", P->Eflags.CF);
+
+ DbgPrint("EAX = %X, EBX = %X, ECX = %X, EDX = %X\n",
+ P->Gpr[EAX], P->Gpr[EBX], P->Gpr[ECX], P->Gpr[EDX]);
+
+ DbgPrint("ESP = %X, EBP = %X, ESI = %X, EDI = %X\n",
+ P->Gpr[ESP], P->Gpr[EBP], P->Gpr[ESI], P->Gpr[EDI]);
+}
+
+
+VOID
+TestPciBios(int flag)
+{
+int i;
+XM_CONTEXT Context;
+PRXM_CONTEXT P = &Context;
+
+ if (flag == 0) return;
+
+ DbgBreakPoint();
+ initregs(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ P->Gpr[EAX].Xl = 1; // bios present
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0xffff;
+ P->Gpr[EDX].Xx = 0xffff;
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x0453;
+ P->Gpr[EDX].Xx = 0x8086;
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x0002;
+ P->Gpr[EDX].Xx = 0x1011; // DEC ethernet
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x7278;
+ P->Gpr[EDX].Xx = 0x9004; // adaptec
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x1234;
+ P->Gpr[EDX].Xx = 0x5678;
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x030000; // vga
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x020000; // ethernet
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x010000; // scsi
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0xABCDEF; // not found
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 6; // generate special cycle
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EDX].Exx = 0x00000002; // x86 specific
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xE; // get irq routing
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xF; // set irq routing
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 1; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xB; // write byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xC; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3F; // bad register
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xC; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ P->Gpr[ECX].Xx = 0xFFFF;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xD; // write Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3F; // bad register
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xD; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ P->Gpr[ECX].Exx = 0xFFFFFFFF;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ DbgPrint("All done!\n");
+ DbgBreakPoint();
+}
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/pcibios.h b/private/ntos/nthals/halfire/ppc/pcibios.h
new file mode 100644
index 000000000..2e47f6b23
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pcibios.h
@@ -0,0 +1,58 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1996 Motorola Inc.
+
+Module Name:
+
+ pcibios.h
+
+Abstract:
+
+ This module contains the private header file for the PCI bios
+ emulation.
+
+Author:
+
+ Scott Geranen (3-4-96)
+
+Revision History:
+
+--*/
+
+#ifndef _PCIBIOS_
+#define _PCIBIOS_
+
+
+BOOLEAN HalpEmulatePciBios(
+ IN OUT PRXM_CONTEXT P
+ );
+
+//
+// PCI BIOS v2.1 functions
+//
+#define PCIBIOS_PCI_FUNCTION_ID 0xB1
+#define PCIBIOS_PCI_BIOS_PRESENT 0x01
+#define PCIBIOS_FIND_PCI_DEVICE 0x02
+#define PCIBIOS_FIND_PCI_CLASS_CODE 0x03
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
+#define PCIBIOS_READ_CONFIG_BYTE 0x08
+#define PCIBIOS_READ_CONFIG_WORD 0x09
+#define PCIBIOS_READ_CONFIG_DWORD 0x0A
+#define PCIBIOS_WRITE_CONFIG_BYTE 0x0B
+#define PCIBIOS_WRITE_CONFIG_WORD 0x0C
+#define PCIBIOS_WRITE_CONFIG_DWORD 0x0D
+#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0x0E
+#define PCIBIOS_SET_IRQ_ROUTING_OPTIONS 0x0F
+
+//
+// PCI BIOS v2.1 status codes:
+//
+#define PCIBIOS_SUCCESSFUL 0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
+#define PCIBIOS_BAD_VENDOR_ID 0x83
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
+#define PCIBIOS_SET_FAILED 0x88
+#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+
+#endif // _PCIBIOS_
diff --git a/private/ntos/nthals/halfire/ppc/pcip.h b/private/ntos/nthals/halfire/ppc/pcip.h
new file mode 100644
index 000000000..262a4393e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pcip.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pcip.h $
+ * $Revision: 1.17 $
+ * $Date: 1996/05/14 02:33:13 $
+ * $Locker: $
+ */
+
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqTable) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+typedef struct tagPCIPBUSDATA {
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqTable GetIrqTable;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ BOOLEAN LimitedIO;
+ UCHAR reserved;
+ UCHAR SwizzleIn[4];
+
+ ULONG IOBase;
+ ULONG IOLimit;
+ ULONG MemoryBase;
+ ULONG MemoryLimit;
+ ULONG PFMemoryBase;
+ ULONG PFMemoryLimit;
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+NTSTATUS
+HalpTranslatePCIBusAddress (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+
+
+
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+//
+// This is a "container" for pci private data that needs
+// to be known per bus and for the set of functions that
+// each bus uses to access data.
+// There is also a couple of extra pci private data needs
+// namely the configuration type of the config data accesses.
+//
+
+typedef struct _BUS_NODE {
+
+ //
+ // The standard bus data for pci buses
+ //
+ PCIPBUSDATA Bus;
+
+ //
+ // Some extra data not part of PCIPBUSDATA:
+ //
+ ULONG HwType; // What HW config access type to use.
+ PPCI_CONFIG_HANDLER ThisNode; // used to point to the "Node"
+ PCI_SLOT_NUMBER SlotNumber;
+ UCHAR BusOrder, BusLevel, BusMax;
+ ULONG BusInt; // bit map of allowable interrupts...
+ ULONG ValidDevs; // bit map of valid DEVICES on this bus.
+ ULONG MemBase, MemTop, IoBase, IoTop;
+
+ //
+ // set of bus specific functions to handle
+ // bus reading, writing, locking, unlocking.
+ //
+ PCI_CONFIG_HANDLER Node;
+
+} FPHAL_BUSNODE, *PFPHAL_BUSNODE;
+
+
diff --git a/private/ntos/nthals/halfire/ppc/phcalls.c b/private/ntos/nthals/halfire/ppc/phcalls.c
new file mode 100644
index 000000000..63dbfec4e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phcalls.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phcalls.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/01/11 07:08:05 $
+ * $Locker: $
+ */
+
+#include "nthal.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpdcc.h"
+#include "stdio.h"
+#include "string.h"
+#include "fparch.h"
+
+PUCHAR Types[] = {
+ "ArcSystem",
+ "CentralProcessor",
+ "FloatingPointProcessor",
+ "PrimaryIcache",
+ "PrimaryDcache",
+ "SecondaryIcache",
+ "SecondaryDcache",
+ "SecondaryCache",
+ "EisaAdapter",
+ "TcAdapter",
+ "ScsiAdapter",
+ "DtiAdapter",
+ "MultiFunctionAdapter",
+ "DiskController",
+ "TapeController",
+ "CdromController",
+ "WormController",
+ "SerialController",
+ "NetworkController",
+ "DisplayController",
+ "ParallelController",
+ "PointerController",
+ "KeyboardController",
+ "AudioController",
+ "OtherController",
+ "DiskPeripheral",
+ "FloppyDiskPeripheral",
+ "TapePeripheral",
+ "ModemPeripheral",
+ "MonitorPeripheral",
+ "PrinterPeripheral",
+ "PointerPeripheral",
+ "KeyboardPeripheral",
+ "TerminalPeripheral",
+ "OtherPeripheral",
+ "LinePeripheral",
+ "NetworkPeripheral",
+ "SystemMemory",
+ "MaximumType"
+};
+
+PUCHAR Classes[] = {
+ "SystemClass",
+ "ProcessorClass",
+ "CacheClass",
+ "AdapterClass",
+ "ControllerClass",
+ "PeripheralClass",
+ "MemoryClass",
+ "MaximumClass"
+};
+
+/*
+** PHalDumpTree
+**
+**
+**
+*/
+
+VOID
+PHalpDumpLoaderBlock (
+ PLOADER_PARAMETER_BLOCK lpb
+ )
+{
+ DbgPrint("\nlpb is %x\n",lpb);
+ DbgPrint("Kernel stack: %x \n",lpb->KernelStack);
+ DbgPrint("ArcBootDeviceName: %s \n",lpb->ArcBootDeviceName);
+ DbgPrint("ArcHalDeviceName: %s \n",lpb->ArcHalDeviceName);
+ DbgPrint("NtBootPathName: %s \n",lpb->NtBootPathName);
+ DbgPrint("NtHalPathName: %s \n",lpb->NtHalPathName);
+ DbgPrint("Loader Options : %s \n",lpb->LoadOptions);
+ DbgPrint("ArcDiskInformation: %x \n",lpb->ArcDiskInformation);
+ DbgPrint("\nPArcDiskinfo: %x \n",lpb->ArcDiskInformation);
+}
+
+VOID
+PHalpDumpConfigData (
+ PCONFIGURATION_COMPONENT_DATA ConfigurationNode,
+ PULONG depth
+ )
+{
+ PCONFIGURATION_COMPONENT_DATA current=NULL, next=NULL;
+
+ DbgPrint("\n======================================\n");
+ for (next = ConfigurationNode; next; next = next->Child) {
+ current = next;
+ DbgPrint("\nNode address = 0x%8.8x, Parent = 0x%8.8x, Sibling = 0x%8.8x, Child = 0x%8.8x\n", current, current->Parent, current->Sibling, current->Child);
+ DbgPrint("\tComponent Class %d, Type %d", current->ComponentEntry.Class, current->ComponentEntry.Type);
+ DbgPrint(", Identifier = '%s' (Length = %d)\n", current->ComponentEntry.Identifier, current->ComponentEntry.IdentifierLength);
+ DbgPrint("\n\tComponent Class %s, Type %s\n", Classes[current->ComponentEntry.Class], Types[current->ComponentEntry.Type]);
+ }
+
+ for ( ; current && !current->Sibling; current = current->Parent) ;
+
+ if (current) {
+ current = current->Sibling;
+ PHalpDumpConfigData(current, &*depth++);
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/phprods.c b/private/ntos/nthals/halfire/ppc/phprods.c
new file mode 100644
index 000000000..cc09923f2
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phprods.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phprods.c $
+ * $Revision: 1.66 $
+ * $Date: 1996/05/14 02:33:18 $
+ * $Locker: $
+ */
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "bugcodes.h"
+
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpcpu.h"
+#include <pci.h>
+#include "pcip.h"
+#include <arccodes.h> // for ESUCCESS
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+VOID HalpHandleDecrementerInterrupt1( PKINTERRUPT , PVOID , PVOID );
+
+HalState Dispatch;
+
+
+extern BOOLEAN HalpHandleMachineCheck(PKINTERRUPT, PVOID);
+extern KINTERRUPT HalpMachineCheckInterrupt;
+extern ULONG HalpSetIntPriorityMask( VOID );
+extern ULONG Irql2Mask[];
+
+KINTERRUPT HalpPciErrorInt;
+KINTERRUPT HalpBusErrorInt;
+KINTERRUPT HalpMemoryErrorInt;
+
+KINTERRUPT HalpHandleClockInterrruptOnOther;
+
+
+
+extern ULONG registeredInts[];
+
+extern VOID KiDispatchSoftwareInterrupt( VOID);
+extern BOOLEAN HalAcknowledgeIpi (VOID);
+ULONG HalpGetHighVector(ULONG);
+
+
+extern ULONG HalpSpuriousInterruptCount;
+extern UCHAR HalpSioInterrupt1Mask,HalpSioInterrupt2Mask;
+extern UCHAR HalpSioInterrupt1Level, HalpSioInterrupt2Level;
+extern ULONG Vector2Irql[];
+ULONG HalpSpuriousInts = 0;
+
+
+/*
+ * HalpHandleExternalInterrupt
+ *
+ * Description:
+ *
+ * This is the main external interrupt handler. It is called whenever
+ * an external interrupt occurs. It interfaces to the ASICs that
+ * cause the external interrupt and vectors to the corresponding
+ * interrupt handling routine.
+ *
+ * Issues:
+ *
+ * Not implemented Yet (sfk 8/26/95).
+ * The returnValue of the driver should be checked and if the driver
+ * did not handle the interrupt, we should consider clearing the interrupt
+ * and broadcasting an interrupt error message.
+ */
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ ULONG TmpSysVector;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ KIRQL OldIrql;
+ ULONG OldMask;
+ UCHAR Irql, i;
+ register UCHAR CpuId;
+
+ //
+ // Assert that interrupts are disabled (or just disable them for now)
+ //
+ HASSERT(!MSR(EE));
+
+ //
+ // Use a local variable for CPU.
+ //
+ CpuId = (UCHAR) GetCpuId();
+
+ //
+ // indicate are in interrupt handler...
+ //
+ SET_LEDS(0xf0 & ~(LED_1));
+
+ //
+ // Get the value out of the (ESCC/TIO) register
+ // Compute interrupt vector number.
+ //
+ TmpSysVector = RInterruptPending(CpuId);
+ if (TmpSysVector == 0) {
+ // For a spurious interrupt, simply return
+#if defined(HALDEBUG_ON)
+ HalpDebugPrint("HalpHandleExternalInterrupt: Spurious Interrupt");
+#endif
+ return FALSE;
+ }
+ //
+ // We must now find the highest priority interrupt to service.
+ // Since the Pending register is not ordered in correct
+ // priority order, we muse "find" the highest priority
+ // interrupt. Servicing a lower priority interrupt will cause us
+ // to nest too deeply on the interrupt stack and panic.
+ //
+ for (i = HIGH_LEVEL; i > DISPATCH_LEVEL; i--) {
+ if ((Irql2Mask[i] & TmpSysVector) != 0) {
+ break;
+ }
+ }
+ HASSERT(i >= PCR->CurrentIrql);
+ TmpSysVector &= Irql2Mask[i];
+
+ //
+ // Now find any single bit of the bits left.
+ //
+ interruptVector = (USHORT) HalpGetHighVector(TmpSysVector);
+
+ //
+ // Turns off ASIC Interrupts (ESCC/TIO).
+ // Need more protection than KeRaisIrql currently provides.
+ //
+ OldIrql = PCR->CurrentIrql;
+ Irql = (UCHAR) Vector2Irql[interruptVector];
+ HASSERT(Irql > i);
+ PCR->CurrentIrql = Irql;
+ OldMask = RInterruptMask(CpuId);
+
+ //
+ // Mask Handling has varied over time based on how well
+ // nesting works. The proper answer is to mask off all of the
+ // interrupts that are a lesser priority than the one
+ // we are currently handling. Using the same code as KeRaiseIrql
+ // does.
+ //
+ RInterruptMask(CpuId) = (Irql2Mask[Irql]&registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+ HASSERT((RInterruptMask(CpuId) & (1 << interruptVector)) == 0);
+
+ //
+ // Clear the interrupt out of the request register by writing a one
+ // for the handled interrupt.
+ //
+ rInterruptRequest = (1 << interruptVector);
+ FireSyncRegister();
+
+ //
+ // if the new IRQL level is lower than clock2_level, restore
+ // system interrupts to allow decrementer interrupts:
+ // Restoring the interrupt bit in the MSR here allows the
+ // debugger to break into this routine (or a driver ISR) if
+ // the system hangs
+ //
+ if (Irql < CLOCK2_LEVEL) {
+ HalpEnableInterrupts();
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+
+ //
+ // A small bit of hack logic. We need a way to make sure that a
+ // "valid" registration has occured for this interrupt. We compare
+ // the handler with the "known" Unexpected interrupt handler routine.
+ // Use location 255 to get it.
+ //
+ if (SioHandler == (PSECONDARY_DISPATCH) PCR->InterruptRoutine[255]) {
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpHandleExternalInterrupt: %d not registered\n",
+ interruptVector););
+ returnValue = FALSE;
+ } else {
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT, DispatchCode[0]);
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame);
+ }
+
+ //
+ // Now disable the PowerPC interrupts to provide protection
+ // for the exit portion of the interrupt handling.
+ //
+ HalpDisableInterrupts();
+
+ //
+ // indicate are exiting the interrupt handler...
+ //
+ SET_LEDS(0xf0 & ~(0x1));
+
+ //
+ // Now lower the IRQL
+ //
+ PCR->CurrentIrql = OldIrql;
+ RInterruptMask(CpuId) = OldMask;
+ WaitForRInterruptMask(CpuId);
+ HASSERT(RInterruptMask(CpuId) ==
+ (Irql2Mask[PCR->CurrentIrql] & registeredInts[CpuId]));
+ return(returnValue);
+}
+
+/*
+ * HalpHandleIpiInterrupt
+ *
+ * Clear the IPI and call the kernel's handler
+ */
+BOOLEAN
+HalpHandleIpiInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ if (HalAcknowledgeIpi()) {
+ KeIpiInterrupt(TrapFrame);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+int
+PHalpInterruptSetup( VOID )
+{
+ UCHAR DataByte,Isr;
+
+ HalpSetIntPriorityMask();
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ rMasterIntPort0 = DataByte;
+ rSlaveIntPort0 = DataByte;
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+ rMasterIntPort1 = DataByte;
+ FireSyncRegister();
+
+ DataByte = 0x08;
+ rSlaveIntPort1 = DataByte;
+ FireSyncRegister();
+
+ //
+ // The third initialization control word set the slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a number.
+ //
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+ rMasterIntPort1 = DataByte;
+ FireSyncRegister();
+
+ DataByte = SLAVE_IRQL_LEVEL;
+ rSlaveIntPort1 = DataByte;
+ FireSyncRegister();
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ //
+ // setup for auto end of interrupt mode in case of firepower
+ //
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
+
+
+ rMasterIntPort1 = DataByte;
+ rSlaveIntPort1 = DataByte;
+ FireSyncRegister();
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL);
+
+ rMasterIntPort1 = DataByte;
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ rSlaveIntPort1 = DataByte;
+
+// define priority specifically IRQ 7 is set to priority 15, while IRQ 0 is set
+// to 1. So, tell the SIO to affix the lowest priority to IRQ 7: 110 00 111
+// should do it: this sets the command to "set priority" and says IRQ 7 is
+// the lowest priority [ 111 ].
+
+ DataByte=0xc7;
+ rMasterIntPort0 = DataByte;
+ rSlaveIntPort0 = DataByte;
+
+// Read the IRR:
+ DataByte=0x0a;
+ rMasterIntPort0 = DataByte;
+ Isr = rMasterIntPort0;
+ HDBG(DBG_GENERAL, HalpDebugPrint("Master: IRR is %x .. ",Isr););
+
+// Read the ISR
+ DataByte=0x0b;
+ rMasterIntPort0 = DataByte;
+ Isr = rMasterIntPort0;
+ HDBG(DBG_GENERAL, HalpDebugPrint("ISR is %x .. \n",Isr););
+
+ //
+ // Set up the system error registers for use: Mask off Video ints, clear
+ // anything pending:
+ //
+
+ //
+ // Clear the PCI Bus error cause register and mask-enable pci error ints
+ //
+ rPCIBusErrorCauseSet = 0x0;
+ rPCIBusErrorCause = 0xffffffff;
+ FireSyncRegister();
+
+ //
+ // Clear the Memory Bus error cause register and mask-enable memory
+ // error ints. Note: (breeze 3/6/95 ) I removed the earlier comments.
+ //
+ rErrorStatus0Set = 0x0;
+ rErrorStatus0 = 0xffffffff;
+ rErrorMask =
+ (ECC_CORRECTED|ECC_FAILED|ADDRESS_PARITY_ERROR|DATA_PARITY_ERROR|
+ MEM_PARITY_ERROR|INVALID_XACT);
+
+ //
+ // IBM 604 Processors (revision 3.3) have parity problems. For these
+ // processors we unset DATA_PARITY to avoid dying from a false
+ // parity error. ES machines only used the Motorola processors
+ // so check for PowerTOP.
+ //
+ if ((SystemType == SYS_POWERTOP) && (ProcessorType == PPC_604)) {
+ if (HalpGetProcessorVersion() == 0x00040303) {
+ rErrorMask &= ~DATA_PARITY_ERROR;
+ }
+ }
+ FireSyncRegister();
+
+ //
+ // Clear the Video error register and disable video ints
+ //
+ rVidInt = 0xffffffff;
+ rVidIntMask = 0x00000000;
+ FireSyncRegister();
+
+ if (!HalpEnableInterruptHandler(&HalpPciErrorInt,
+ (PKSERVICE_ROUTINE) HalpMemoryHandler,
+ NULL,
+ NULL,
+ DEVICE_VECTORS + PCI_ERROR_NUM,
+ 28,
+ 28,
+ Latched,
+ FALSE,
+ 0, // Processor Number
+ FALSE,
+ InternalUsage,
+ DEVICE_VECTORS + PCI_ERROR_NUM)) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+ if (!HalpEnableInterruptHandler(&HalpBusErrorInt,
+ (PKSERVICE_ROUTINE) HalpMemoryHandler,
+ NULL,
+ NULL,
+ DEVICE_VECTORS + CPU_BUS_ERROR_NUM,
+ 28,
+ 28,
+ Latched,
+ FALSE,
+ 0, // Processor Number
+ FALSE,
+ InternalUsage,
+ DEVICE_VECTORS + CPU_BUS_ERROR_NUM)) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ if (SystemType == SYS_POWERPRO) {
+ if (!HalpEnableInterruptHandler(&HalpMemoryErrorInt,
+ (PKSERVICE_ROUTINE) HalpMemoryHandler,
+ NULL,
+ NULL,
+ DEVICE_VECTORS + MEMORY_ERROR_VIDEO_NUM,
+ 28,
+ 28,
+ Latched,
+ TRUE, // share with the video-in ISR...
+ // FALSE,
+ 0, // Processor Number
+ FALSE,
+ InternalUsage,
+ DEVICE_VECTORS +
+ MEMORY_ERROR_VIDEO_NUM)) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+ }
+
+ return(0);
+}
+
+
+
+//
+// Initialize interrupts on processors other than the main (boot) processor.
+//
+//
+ULONG
+HalpInitInts( ULONG ProcessorNumber )
+{
+
+ ULONG Mask;
+
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpInitInts: entered Cpu (%d)\n", ProcessorNumber));
+
+ //
+ // Make sure all the interrupts are masked off and any potential
+ // interrupts are cleared from the pending register. This is a percpu
+ // action and makes sure that this cpu starts off with a known
+ // interrupt state.
+ //
+ HalpDisableInterrupts();
+ RInterruptMask(GetCpuId()) = ALL_INTS_OFF;
+ WaitForRInterruptMask(GetCpuId());
+
+ //
+ // Connect the external interrupt handler first, then the other
+ // handlers for external events may be installed....
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector with the HAL
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+ //
+ // Connect the IPI interrupt handler directly to the CPU dispatch table
+ // without registering with the kernel. The IPI interrupt has
+ // already been registered with the HAL by CPU 0 in HalpCreateSioStructures
+ // so we don't need to do it again here.
+ //
+
+ PCR->InterruptRoutine[DEVICE_VECTORS + 31] =
+ (PKINTERRUPT_ROUTINE) HalpHandleIpiInterrupt;
+
+ //
+ // Now enable the IPI interrupt on this CPU; the HAL must do this
+ // directly since we did not register with the kernel.
+ // It should be alright to call this routine directly rather than
+ // HalEnableSystemInterrupt because interrupts are disabled.
+ //
+ HalpEnableSioInterrupt(DEVICE_VECTORS + 31, Latched);
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitInts: Enabled IPI handler \n"););
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ (CCHAR) ProcessorNumber,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt1;
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+ //
+ // Make sure the mask is set correctly at the mask register for this cpu:
+ //
+ Mask = RInterruptMask(GetCpuId());
+ if (Mask != CPU_MESSAGE_INT) {
+ HalpDebugPrint("HalpInitInts: no CPU_MESSAGE_INT\n");
+ }
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpInitInts: exit\n"););
+ return (0);
+}
+
+//
+// Some quick code for handling memory bus errors
+//
+BOOLEAN
+HalpMemoryHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ ULONG causeValue;
+
+ //
+ // Proper handling of Memory, CPU and PCI errors.
+ //
+ switch ((Interrupt->Vector - DEVICE_VECTORS)) {
+ case MEMORY_ERROR_VIDEO_NUM: {
+ ULONG addr;
+
+ //
+ // Read the register so that we can see it on a logic analyzer
+ //
+ causeValue = rErrorStatus0;
+
+ //
+ // check for valid video-in interrupt if on a powertop system. If
+ // there is a valid video-in interrupt AND no valid cause other than
+ // a memory int, then return false and let the video driver handle
+ // this.
+ // If there is a cause, then handle the memory error cause
+ // regardless of the video-in case:
+ //
+ if ( causeValue == 0x0 ) {
+ return FALSE; // return false in any case since no
+ // cause was found!!
+ }
+
+ //
+ // This is not a true error, just record it in the registry
+ // (recording in registry not implemented yet - sfk 2/20/95 - XXX)
+ //
+ // Don't bother checking for video-in interrupt here. If there is
+ // a video interrupt awaiting action, it should be picked up when
+ // the hal returns from interrupt since the uncleared int will be
+ // automatically re-asserted when cpu ints are re-enabled via the
+ // MSR(EE) action.
+ //
+ if (causeValue&ERROR_ECC_CORRECTED) {
+ ULONG rc;
+ ULONG count = 0, total = 0;
+ const PCHAR varname = "PARITY_ERROR";
+ CHAR buf[80];
+
+ rErrorStatus0 |= ERROR_ECC_CORRECTED;
+ FireSyncRegister();
+
+ //
+ // record the error count to NVRAM as:
+ // # errors this boot, # errors forever
+ //
+ MemoryParityErrorsThisBoot++;
+ MemoryParityErrorsForever++;
+ sprintf(buf, "%d,%d",
+ MemoryParityErrorsThisBoot,
+ MemoryParityErrorsForever
+ );
+ rc = HalSetEnvironmentVariable(MemoryParityErrorsVarName, buf);
+ if (ESUCCESS != rc) {
+ // what to do?
+ }
+ return TRUE;
+ }
+ //
+ // Now we panic: Make sure that in the process we don't fall
+ // into a loop of parity errors, so turn off memory parity errors,
+ // and the other errors as well:
+ //
+ rErrorMask &= ~(MEM_PARITY_ERROR |
+ INVALID_XACT
+ );
+
+ addr = (rErrorAddr0 & 0xff000000);
+ addr |= ((rErrorAddr1 & 0xff000000) >> 8);
+ addr |= ((rErrorAddr2 & 0xff000000) >> 16);
+ addr |= ((rErrorAddr3 & 0xff000000) >> 24);
+
+ //
+ // Show the user what happened before we die
+ //
+ HalpForceDisplay("MEMORY_ERROR cause(0x%08x) at 0x%08x\n",
+ causeValue&0xff000000, addr);
+
+ //
+ // Decode the cause into ascii strings for the user impatiently
+ // waiting for enlightenment from the dead machine: Before
+ // reincarnation, what major transgression did we commit?
+ //
+
+ if( causeValue&ERROR_DATA_PARITY) {
+ HalpForceDisplay("DATA PARITY");
+ }
+ if (causeValue&ERROR_MEM_PARITY) {
+ HalpForceDisplay(", MEMORY PARITY");
+ }
+ if (causeValue&ERROR_ECC_FAILED) {
+ HalpForceDisplay(", ECC FAILED");
+ }
+ if (causeValue&ERROR_INVALID_XACT) {
+ HalpForceDisplay(", Bad bus transaction: burst access to rom or io space?");
+ }
+ HalpForceDisplay("\n\n");
+
+ //
+ // Clear the Memory Error. Since we only want one error
+ // of each type (max.), we mask off the error we just
+ // received.
+ //
+ rErrorMask &= ~causeValue;
+ rErrorStatus0 = causeValue;
+ FireSyncRegister();
+ break;
+
+ }
+
+ case PCI_ERROR_NUM:
+ //
+ // Read the register so that we can see it on a logic analyzer
+ //
+ causeValue = rPCIBusErrorCause;
+
+ //
+ // This is not a true error, just record it in the registry
+ // (recording in registry not implemented yet - sfk 2/20/95 - XXX)
+ //
+ if (causeValue&PCI_ERROR_DEV_TIMEOUT) {
+ rPCIBusErrorCause = PCI_ERROR_DEV_TIMEOUT;
+ FireSyncRegister();
+ return TRUE;
+ }
+
+ // This also may not be a true error; we must check the Pci status
+ // registers
+ if( causeValue& PCI_ERROR_TARGET_ABORT) {
+ // Scan the Primary Pci status registers
+ ULONG devs;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ for (devs = 0; devs < MAXIMUM_PCI_SLOTS; devs++) {
+ HalGetBusData (
+ PCIConfiguration,
+ 0,
+ devs,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ continue;
+ }
+
+ if (PciData->Status & PCI_STATUS_SIGNALED_TARGET_ABORT) {
+ // We can ignore this one; clear the error bits
+ rPCIBusErrorCause = PCI_ERROR_TARGET_ABORT;
+ PciData->Status = PCI_STATUS_SIGNALED_TARGET_ABORT;
+ HalSetBusDataByOffset(
+ PCIConfiguration,
+ 0,
+ devs,
+ &PciData->Status,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ Status),
+ 1);
+ FireSyncRegister();
+ return TRUE;
+ }
+ }
+ }
+
+ //
+ // Show the user what happened before we die
+ //
+ HalpForceDisplay("\nPCI_ERROR cause(0x%08x) at 0x%08x\n",
+ causeValue, rPCIBusErrorAddressRegister);
+
+ if( causeValue& PCI_ERROR_SIGNALED_SYS) {
+ HalpForceDisplay("Address parity error on PCI bus\n");
+ }
+ if( causeValue& PCI_ERROR_DATA_PARITY) {
+ HalpForceDisplay("Data parity error on PCI bus\n");
+ }
+ if( causeValue& PCI_ERROR_DEV_TIMEOUT) {
+ HalpForceDisplay("Device Timeout: Master Aborted\n");
+ }
+ if( causeValue& PCI_ERROR_TARGET_ABORT) {
+ HalpForceDisplay("Target Aborted or Master experienced a fatal error\n");
+ }
+ HalpForceDisplay("\n\n");
+
+ //
+ // Clear the PCI Error
+ //
+ rPCIBusErrorCause = causeValue;
+ FireSyncRegister();
+ break;
+
+ case CPU_BUS_ERROR_NUM:
+ //
+ // Read the register so that we can see it on a logic analyzer
+ //
+ causeValue = rCPUBusErrorCause;
+
+ //
+ // Show the user what happened before we die
+ //
+ HalpForceDisplay("CPU_ERROR cause(0x%08x) at 0x%08x\n",
+ causeValue, rCPUBusErrorAddressRegister);
+
+ //
+ // Clear the Bus Error
+ //
+ rCPUBusErrorCause = causeValue;
+ FireSyncRegister();
+ break;
+
+ default:
+ //
+ // We should not be here, bug check because things are not sane
+ // if we got this far.
+ //
+ HalpForceDisplay("Unknown Bus Error (%d)\n",
+ (Interrupt->Vector - DEVICE_VECTORS));
+ break;
+
+ } // end of switch statement.....
+
+ //
+ // If we make it to here, we just stop the system (cold).
+ //
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ //
+ // This should never return but just in case
+ //
+ HalpDisableInterrupts();
+here:
+ goto here;
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/phsystem.h b/private/ntos/nthals/halfire/ppc/phsystem.h
new file mode 100644
index 000000000..03b211f40
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phsystem.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1995 Firepower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phsystem.h $
+ * $Revision: 1.28 $
+ * $Date: 1996/05/14 02:33:25 $
+ * $Locker: $
+ */
+
+#ifndef PHSYSTEM_H
+#define PHSYSTEM_H
+
+//
+// (sfk 11/3/94)
+// Should this be placed here or directly included?
+//
+#include "fpreg.h"
+#include "stdio.h"
+#include "ntverp.h"
+
+// defined 'special' address space for system memory [rdl:01.04.95]
+#define MEMORY_ADDRESS_SPACE 0
+#define IO_ADDRESS_SPACE 1
+#define SYSTEM_ADDRESS_SPACE 2
+
+BOOLEAN HalpInitializeDisplay1(PLOADER_PARAMETER_BLOCK);
+ULONG HalpInitInts( ULONG CpuNumber );
+VOID HalpInitPciBusEarly( PLOADER_PARAMETER_BLOCK );
+int PHalTriggerEvent( ULONG returndata );
+int PHalSetupGpio( ULONG LEDFLAGS );
+VOID PHalBlinkLeds( UCHAR LEDS, ULONG Rate, ULONG LEDFLAGS );
+int PHalpInterruptSetup( VOID );
+BOOLEAN PHalpHandleIpi( PKINTERRUPT , PVOID , PVOID );
+VOID PHalpDumpLoaderBlock ( PLOADER_PARAMETER_BLOCK );
+VOID PHalpDumpConfigData ( PCONFIGURATION_COMPONENT_DATA, PULONG );
+VOID PHalDumpTree ( PCONFIGURATION_COMPONENT_DATA );
+BOOLEAN PHalpEisaDispatch( PKINTERRUPT , PVOID , PVOID );
+int PH_HalVersion( VOID );
+ULONG HalpCheckString( PCHAR , PCHAR );
+ULONG HalpSetPixelColorMap( ULONG , ULONG );
+BOOLEAN HalpInitIntelAIP ( VOID );
+VOID PH_HalVersionInternal( VOID );
+VOID PH_HalVersionExternal( VOID );
+VOID HalpResetByKeyboard(VOID);
+VOID HalpSetupDCC(ULONG, ULONG);
+
+BOOLEAN HalpMemoryHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame);
+
+BOOLEAN HalpHandleExternalInterrupt( IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+ULONG HalpGetProcessorRev( VOID);
+
+// define the start address for system register space, apart
+// from eisa/pci specific registers
+//
+// PVOID HalpSysBase = (PVOID) 0xff000000;
+// PVOID HalpSysBase = (PVOID) 0x8000ff00;
+
+extern PVOID HalpSystemSpace;
+extern PVOID HalpIoControl;
+extern PVOID HalpVideMemoryBase;
+extern PVOID HalpSystemControlBase;
+extern BOOLEAN HalpInitializeRegistry (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+extern ULONG HalpGetCycleTime(VOID);
+extern ULONG HalpProcessorCount(VOID);
+extern ULONG HalpGetCycleTime(VOID);
+
+#define LED_0 0x01 // led 0
+#define LED_1 0x02 // led 1
+#define LED_2 0x04 // led 2
+#define LED_3 0x08 // led 3
+#define LED_EMIT 0xf0 // led direction bits in gpio register
+
+#define LED_ON 0xffffffff
+#define LED_OFF 0x00000000
+//#define DCC_INDX 0x840
+//#define DCC_DATA 0x841
+#define GPIOA 0x2
+// #define WAIT_TIME 0xf000000
+#define WAIT_TIME 0x800000
+
+typedef struct _DCC_CONTROL {
+ UCHAR space[0x840];
+ UCHAR DccIndxReg; // this should show up at address base + 840
+ UCHAR DccDataReg; // this should show up at address base + 841
+ UCHAR DccTestAddr; // this is for test purposes....
+} DCC_CONTROL, *P_DCC_CONTROL;
+
+typedef struct _Address_Map {
+ ULONG System;
+ ULONG IO;
+ ULONG General;
+} Address_Map, *PAddress_Map;
+
+
+typedef struct {
+ ULONG EntryCounter;
+ ULONG ExitCounter;
+ ULONG Flags; // keep track of where in the routine you are..
+ ULONG Isr;
+ ULONG TmpMask;
+ ULONG MasksDifferFlag;
+ ULONG SysInterruptVector;
+ ULONG Intbucket; // bit map each int type seen
+ ULONG CompareMask;
+ ULONG BusyCount;
+ ULONG Bloob;
+ ULONG LastCount;
+} HalState, *PHalState;
+
+//
+// System Descriptions:
+// Hold a description of the system for the hal to use
+// to determine what form it should take.
+
+//
+// Declare an enumerated type for asking which processor the
+// system is currently running on.
+//
+typedef struct {
+ ULONG Flags;
+ ULONG HashSize;
+ PCHAR ProcessorName;
+ PCHAR ProductNumber;
+} PROCESSOR_DESCRIPTION;
+
+//
+// Flags for defining the capabilities of the cpu,
+// and the enumerated labels for marking what
+// cpu we're on.
+//
+#define PROC_NOSUPP 0x00000000
+#define PROC_SUPP 0x00000001
+#define PROC_HASHTABLE 0x00000002
+#define PROC_MPCAPABLE 0x00000004
+
+typedef enum {
+ PPC_UNKNOWN = 0,
+ PPC_601 = 1,
+ PPC_602 = 2,
+ PPC_603 = 3,
+ PPC_604 = 4,
+ PPC_605 = 5,
+ PPC_606 = 6,
+ PPC_607 = 7,
+ PPC_608 = 8,
+ PPC_609 = 9,
+ nPROCESSOR_TYPE
+} PROCESSOR_TYPE;
+
+extern PROCESSOR_DESCRIPTION ProcessorDescription[];
+extern PROCESSOR_TYPE ProcessorType;
+
+//
+// System IDENT Values:
+//
+#define ESCC_IDENT 0x60730000 // chip only in pro
+#define TSC_IDENT 0x60370000 // chip only in top ( currently )
+
+
+//
+// Flags to label the capabilities of the system as a whole:
+//
+#define SYS_NOSUPP 0x00000000 // system is not supported by this hal.
+#define SYS_SUPP 0x00000001 // system is supported by this hal.
+#define SYS_MPCAPABLE 0x00000002 // system is able to support more than one cpu.
+#define SYS_MPFOREAL 0x00000004 // system is able to have more than one cpu.
+
+typedef enum {
+ SYS_UNKNOWN = 0,
+ SYS_POWERPRO = 1, // 0x60730000
+ SYS_POWERTOP = 2, // 0x60370000
+ SYS_POWERSERVE = 3, // 0x60370000 ???? don't know yet
+ SYS_POWERSLICE = 4,
+ nSYSTEM_TYPE
+} SYSTEM_TYPE ;
+
+typedef struct {
+ ULONG Flags;
+ PCHAR SystemName;
+} SYSTEM_DESCRIPTION, PSYSTEM_DESCRIPTION;
+
+typedef struct _HW_DESCRIPTION {
+ ULONG HwFlags;
+ ULONG Spare;
+}HARDWARE_DESCRIPTION;
+extern SYSTEM_DESCRIPTION SystemDescription[];
+extern SYSTEM_TYPE SystemType;
+extern VOID HalpInitIoBuses ( VOID );
+
+#define IRQ0 1
+
+extern ULONG PciDeviceIDs[4][256];
+extern ULONG PciClassInfo[4][256];
+
+
+//
+// these values show up in the lower byte of the interrupt word read out of
+// the system register...
+//
+#define VEC_Timer 0x0001
+#define VEC_Keyboard 0x0002
+#define VEC_Cascade 0x0004
+#define VEC_Serial2 0x0008
+#define VEC_Serial1 0x0010
+#define VEC_Display 0x0020
+#define VEC_Floppy 0x0040
+#define VEC_Parallel1 0x0080
+//
+// these values show up in the secondary next byte
+// of the SIO
+//
+#define VEC_RTC 0x0100
+#define VEC_Open9 0x0200
+#define VEC_Audio 0x0400
+#define VEC_PCI 0x0800
+#define VEC_Mouse 0x1000
+#define VEC_Scsi 0x2000
+#define VEC_Enet 0x4000
+#define VEC_Open15 0x8000
+
+#define HalPrint HalpDebugPrint
+#define HalpPrint HalpDebugPrint
+
+#define HalBreak(x)
+#define SEE_DEFINES A_DEFINES
+#define SET_STRING(x) #x
+
+//
+//Declare The BAT Support Routines [ged]
+//
+ULONG HalpGetUpperIBAT(ULONG);
+ULONG HalpGetLowerIBAT(ULONG);
+ULONG HalpGetUpperDBAT(ULONG);
+ULONG HalpGetLowerDBAT(ULONG);
+VOID HalpSetLowerDBAT1(ULONG);
+VOID HalpSetUpperDBAT1(ULONG);
+// Add more BAT Support Routines [rdl:01.03.95]
+VOID HalpSetUpperDBAT(ULONG,ULONG);
+VOID HalpSetLowerDBAT(ULONG,ULONG);
+
+//
+// Memory parity error variables
+//
+
+#define MemoryParityErrorsVarName "MEMORY_PARITY_ERRORS"
+extern ULONG MemoryParityErrorsThisBoot;
+extern ULONG MemoryParityErrorsForever;
+
+//
+// Useful macros for pragma message, ie. #pragma message(REVIEW "some text")
+//
+#define QUOTE(x) #x
+#define IQUOTE(x) QUOTE(x)
+#define REVIEW __FILE__ "(" IQUOTE(__LINE__) ") : REVIEW -> "
+
+
+#define NOTE(x) message(REVIEW IQUOTE(x) )
+
+#define PAUSE for(;;) { \
+ }
+
+
+#endif // PHSYSTEM_H
diff --git a/private/ntos/nthals/halfire/ppc/phsystem.s b/private/ntos/nthals/halfire/ppc/phsystem.s
new file mode 100644
index 000000000..b3ce390b9
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phsystem.s
@@ -0,0 +1,487 @@
+//++
+//
+// Copyright (c) 1994 FirePower Systems INC.
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxsystem.s
+//
+// Abstract:
+//
+// This module implements the routines to handle system functions:
+// Provides system specific info.
+// Currently provides processor version type
+//
+// Author:
+// breeze@firepower.com
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phsystem.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:08:26 $
+ * $Locker: $
+ */
+
+#include "kxppc.h"
+
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// HalProcessorRev, in r3
+//
+//
+// Return Value:
+// Processor Version register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpGetProcessorRev)
+ mfpvr r.3 // get processor version
+ LEAF_EXIT(HalpGetProcessorRev)
+
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetUpperIBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper instruction BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+******************************************************************************/
+
+ .set BatNumber, r.3
+
+ LEAF_ENTRY(HalpGetUpperIBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUI0
+ mfibatu BatNumber,0
+ b ExitUI
+NotUI0:
+ cmpli 0,0,BatNumber,1
+ bne NotUI1
+ mfibatu BatNumber,1
+ b ExitUI
+NotUI1:
+ cmpli 0,0,BatNumber,2
+ bne NotUI2
+ mfibatu BatNumber,2
+ b ExitUI
+NotUI2:
+ mfibatu BatNumber,3 // OK, it's three by default
+
+ExitUI:
+
+ LEAF_EXIT(HalpGetUpperIBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetLowerIBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower instruction BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+******************************************************************************/
+
+ LEAF_ENTRY(HalpGetLowerIBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLI0
+ mfibatl BatNumber,0
+ b ExitLI
+NotLI0:
+ cmpli 0,0,BatNumber,1
+ bne NotLI1
+ mfibatl BatNumber,1
+ b ExitLI
+NotLI1:
+ cmpli 0,0,BatNumber,2
+ bne NotLI2
+ mfibatl BatNumber,2
+ b ExitLI
+NotLI2:
+ mfibatl BatNumber,3 // OK, it's three by default
+
+ExitLI:
+
+ LEAF_EXIT(HalpGetLowerIBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetUpperDBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+******************************************************************************/
+
+ LEAF_ENTRY(HalpGetUpperDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUD0
+ mfdbatu BatNumber,0
+ b ExitUD
+NotUD0:
+ cmpli 0,0,BatNumber,1
+ bne NotUD1
+ mfdbatu BatNumber,1
+ b ExitUD
+NotUD1:
+ cmpli 0,0,BatNumber,2
+ bne NotUD2
+ mfdbatu BatNumber,2
+ b ExitUD
+NotUD2:
+ mfdbatu BatNumber,3 // OK, it's three by default
+
+ExitUD:
+
+ LEAF_EXIT(HalpGetUpperDBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetLowerDBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+******************************************************************************/
+
+ LEAF_ENTRY(HalpGetLowerDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLD0
+ mfdbatl BatNumber,0
+ b ExitLD
+NotLD0:
+ cmpli 0,0,BatNumber,1
+ bne NotLD1
+ mfdbatl BatNumber,1
+ b ExitLD
+NotLD1:
+ cmpli 0,0,BatNumber,2
+ bne NotLD2
+ mfdbatl BatNumber,2
+ b ExitLD
+NotLD2:
+ mfdbatl BatNumber,3 // OK, it's three by default
+
+ExitLD:
+
+ LEAF_EXIT(HalpGetLowerDBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpSetUpperDBAT(ULONG BatNumber) [rdl]
+
+ Purpose:
+ Stores the 32-bit upper data BAT value for a given <BatNumber>.
+
+ Returns:
+ N/A
+******************************************************************************/
+
+ .set BatValueToSet, r.4
+
+ LEAF_ENTRY(HalpSetUpperDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotSetUD0
+ mtdbatu 0,BatValueToSet
+ b ExitSetUD
+NotSetUD0:
+ cmpli 0,0,BatNumber,1
+ bne NotSetUD1
+ mtdbatu 1,BatValueToSet
+ b ExitSetUD
+NotSetUD1:
+ cmpli 0,0,BatNumber,2
+ bne NotSetUD2
+ mtdbatu 2,BatValueToSet
+ b ExitSetUD
+NotSetUD2:
+ mtdbatu 3,BatValueToSet // OK, it's three by default
+
+ExitSetUD:
+
+ LEAF_EXIT(HalpSetUpperDBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpSetLowerDBAT(ULONG BatNumber) [rdl]
+
+ Purpose:
+ Stores the 32-bit lower data BAT value for a given <BatNumber>.
+
+ Returns:
+ N/A
+******************************************************************************/
+
+ LEAF_ENTRY(HalpSetLowerDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotSetLD0
+ mtdbatl 0,BatValueToSet
+ b ExitSetLD
+NotSetLD0:
+ cmpli 0,0,BatNumber,1
+ bne NotSetLD1
+ mtdbatl 1,BatValueToSet
+ b ExitSetLD
+NotSetLD1:
+ cmpli 0,0,BatNumber,2
+ bne NotSetLD2
+ mtdbatl 2,BatValueToSet
+ b ExitSetLD
+NotSetLD2:
+ mtdbatl 3,BatValueToSet // OK, it's three by default
+
+ExitSetLD:
+
+ LEAF_EXIT(HalpSetLowerDBAT)
+
+/******************************************************************************
+ Synopsis:
+ VOID HalpSetLowerDBAT3(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT3.
+
+ Returns:
+ Nothing
+******************************************************************************/
+
+ .set BatValue, r.3
+
+ LEAF_ENTRY(HalpSetLowerDBAT3)
+
+ mtdbatl 3,BatValue
+
+ LEAF_EXIT(HalpSetLowerDBAT3)
+
+/******************************************************************************
+ Synopsis:
+ VOID HalpSetLowerDBAT1(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+******************************************************************************/
+
+ LEAF_ENTRY(HalpSetLowerDBAT1)
+
+ mtdbatl 1,BatValue
+
+ LEAF_EXIT(HalpSetLowerDBAT1)
+
+/******************************************************************************
+ Synopsis:
+ VOID HalpSetUpperDBAT1(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit upper data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+******************************************************************************/
+
+ LEAF_ENTRY(HalpSetUpperDBAT1)
+
+ mtdbatu 1,BatValue
+
+ LEAF_EXIT(HalpSetUpperDBAT1)
+
+/******************************************************************************
+
+ Synopsis:
+ VOID HalpDisableDCache()
+******************************************************************************/
+
+ LEAF_ENTRY(HalpDisableDCache)
+
+ .set HID0, 1008
+
+ mtspr HID0, r3
+
+ LEAF_EXIT(HalpDisableDCache)
+
+
+//++
+//
+// void
+// KiSetDbat
+//
+// Routine Description:
+//
+// Writes a set of values to DBAT n
+//
+// No validation of parameters is done. Protection is set for kernel
+// mode access only.
+//
+// Arguments:
+//
+// r.3 Number of DBAT
+// r.4 Physical address
+// r.5 Virtual Address
+// r.6 Length (in bytes)
+// r.7 Coherence Requirements (WIM)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY (KiSetDbat)
+
+ mfpvr r.9 // different format for
+ // 601 vs other 6xx processors
+ cmpwi cr.5, r.3, 1
+ cmpwi cr.6, r.3, 2
+ cmpwi cr.7, r.3, 3
+
+ rlwinm. r.10, r.9, 0, 0xfffe0000// Check for 601
+
+ // calculate mask (ie BSM) If we knew the number passed in was
+ // always a power of two we could just subtract 1 and shift right
+ // 17 bits. But to be sure we will use a slightly more complex
+ // algorithm than will always generate a correct mask.
+ //
+ // the mask is given by
+ //
+ // ( 1 << ( 32 - 17 - cntlzw(Length - 1) ) ) - 1
+ // == ( 1 << ( 15 - cntlzw(Length - 1) ) ) - 1
+
+ addi r.6, r.6, -1
+ oris r.6, r.6, 1 // ensure min length 128KB
+ ori r.6, r.6, 0xffff
+ cntlzw r.6, r.6
+ subfic r.6, r.6, 15
+ li r.10, 1
+ slw r.6, r.10, r.6
+ addi r.6, r.6, -1
+
+ beq cr.0, KiSetDbat601
+
+ // processor is not a 601.
+
+ rlwinm r.7, r.7, 3, 0x38 // position WIM (G = 0)
+ rlwinm r.6, r.6, 2, 0x1ffc // restrict BAT maximum (non 601)
+ // after left shifting by 2.
+ ori r.6, r.6, 0x2 // Valid (bit) in supervisor state only
+ ori r.7, r.7, 2 // PP = 0x2
+ or r.5, r.5, r.6 // = Virt addr | BL | Vs | Vp
+ or r.4, r.4, r.7 // = Phys addr | WIMG | 0 | PP
+
+ beq cr.5, KiSetDbat1
+ beq cr.6, KiSetDbat2
+ beq cr.7, KiSetDbat3
+
+KiSetDbat0:
+ mtdbatl 0, r.4
+ mtdbatu 0, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+KiSetDbat1:
+ mtdbatl 1, r.4
+ mtdbatu 1, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+KiSetDbat2:
+ mtdbatl 2, r.4
+ mtdbatu 2, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+KiSetDbat3:
+ mtdbatl 3, r.4
+ mtdbatu 3, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+ // 601 has different format BAT registers and actually only has
+ // one set unlike other PowerPC processors which have seperate
+ // Instruction and Data BATs. The 601 BAT registers are set
+ // with the mtibat[u|l] instructions.
+
+KiSetDbat601:
+
+ rlwinm r.7, r.7, 3, 0x70 // position WIMG (601 has no G bit)
+ rlwinm r.6, r.6, 0, 0x3f // restrict BAT maximum (601 = 8MB)
+ ori r.6, r.6, 0x40 // Valid bit
+ ori r.7, r.7, 4 // Ks = 0 | Ku = 1 | PP = 0b00
+ or r.4, r.4, r.6 // = Phys addr | Valid | BL
+ or r.5, r.5, r.7 // = Virt addr | WIM | Ks | Ku | PP
+
+ beq cr.5, KiSet601Bat1
+ beq cr.6, KiSet601Bat2
+ beq cr.7, KiSet601Bat3
+
+KiSet601Bat0:
+ mtibatl 0, r.4
+ mtibatu 0, r.5
+ ALTERNATE_EXIT(KiSet601Bat)
+
+KiSet601Bat1:
+ mtibatl 1, r.4
+ mtibatu 1, r.5
+ ALTERNATE_EXIT(KiSet601Bat)
+
+KiSet601Bat2:
+ mtibatl 2, r.4
+ mtibatu 2, r.5
+ ALTERNATE_EXIT(KiSet601Bat)
+
+KiSet601Bat3:
+ mtibatl 3, r.4
+ mtibatu 3, r.5
+
+ LEAF_EXIT(KiSetDbat)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetHighVector(ULONG IntValue)
+
+ Purpose:
+ Find the highest bit turned on and return the bit order
+
+ Returns:
+ Number of leading zeroes
+******************************************************************************/
+
+ .set IntValue, r.3
+
+ LEAF_ENTRY(HalpGetHighVector)
+
+ cntlzw IntValue, IntValue
+ subfic IntValue, IntValue, 0x1f
+
+ LEAF_EXIT(HalpGetHighVector)
diff --git a/private/ntos/nthals/halfire/ppc/phvrsion.c b/private/ntos/nthals/halfire/ppc/phvrsion.c
new file mode 100644
index 000000000..81f79d3b9
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phvrsion.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1995,1996 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phvrsion.c $
+ * $Revision: 1.47 $
+ * $Date: 1996/06/25 16:06:34 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fparch.h"
+#include "ntverp.h"
+#include "string.h"
+
+typedef CHAR Names[20];
+
+ LONG i=0;
+ Names ScopeList[] = {
+ "Engineering",
+ "Manufacturing",
+ "Testing",
+ "Customer",
+ };
+ Names RelList[] = {
+ "General",
+ "OfficiaL",
+ "Testing",
+ "Controlled",
+ "Lab use"
+ };
+
+//
+// to avoid cascading headers
+//
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlCharToInteger (
+ PCSZ String,
+ ULONG Base,
+ PULONG Value
+ );
+
+#define HAL_DISPLAY_DEFINES(a) \
+ if (state == 3) { \
+ HalDisplayString("\n"); \
+ state = 0; \
+ } \
+ HalDisplayString(" "); \
+ HalDisplayString(a); \
+ state++;
+
+#define ORG IQUOTE(BUILTBY)
+// #define REVIEW __FILE__ "(" IQUOTE(__LINE__) ") : REVIEW -> "
+
+ULONG
+HalpVersionSystem(
+ SYSTEM_TYPE
+) ;
+VOID
+HalpVersionExternal(
+ IN RelInfo *,
+ IN PLOADER_PARAMETER_BLOCK
+) ;
+PCHAR
+HalpGetVersionData(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+) ;
+VOID
+HalpDisplayVersionData(
+ IN PCHAR VersionData
+) ;
+BOOLEAN
+HalpSetRevs(
+ RelInfo *
+) ;
+
+// int HalpProcessorCount();
+
+#pragma alloc_text(INIT,HalpVersionSystem)
+#pragma alloc_text(INIT,HalpVersionExternal)
+#pragma alloc_text(INIT,HalpGetVersionData)
+#pragma alloc_text(INIT,HalpDisplayVersionData)
+#pragma alloc_text(INIT,HalpSetRevs)
+
+extern ULONG HalpGetCycleTime(VOID);
+extern ULONG HalpGetInstructionTimes( VOID );
+extern ULONG HalpPerformanceFrequency;
+
+
+#if DBG == 1
+VOID
+HalpVersionInternal( VOID )
+{
+
+ int state = 0;
+
+ HalpDebugPrint("\nWelcome to the %s (%s) Party\n",
+ SystemDescription[SystemType].SystemName,
+ ProcessorDescription[ProcessorType].ProcessorName);
+ HalpDebugPrint("HalpVersionInternal: Raw Processor Value (0x%x)\n",
+ HalpGetProcessorVersion());
+ HalpDebugPrint("Hal compiled on %s at %s with the following defines:\n",
+ __DATE__, __TIME__);
+
+ HalDisplayString("\n");
+ HalpDebugPrint(" Hal Build Base: %d \n",VER_PRODUCTBUILD);
+ HalpVersionSystem(SystemType);
+}
+#endif // DBG
+
+/*
+ * Routine Description: ULONG HalpVersionSystem(SYSTEM_TYPE System)
+ *
+ * Extract as much version information out of the mother board as possible:
+ *
+ */
+
+ULONG
+HalpVersionSystem(SYSTEM_TYPE System)
+{
+ ULONG TscVersion=0;
+ ULONG PciVersion=0;
+
+ TscVersion = rTscRevision;
+ PciVersion = rPCIRevisionID;
+
+ switch(System) {
+
+ case SYS_POWERSLICE:
+ HalpDebugPrint("TSC version: 0x%x \n", TscVersion );
+ break;
+
+ case SYS_POWERTOP : HalpDebugPrint("TSC version: 0x%x \n", TscVersion );
+ break;
+
+ case SYS_POWERPRO : HalpDebugPrint("Escc version: IS NOT DESIGNED IN!@!");
+ break;
+
+ case SYS_POWERSERVE : HalpDebugPrint("WHOOOAA pahdna, just what are you trying to pull here?\n");
+ break;
+
+ case SYS_UNKNOWN : HalpDebugPrint("Unknown system type \n");
+
+ default: // unknown stuff? should never get here
+ break;
+ }
+ HalpDebugPrint("\n===========================================================================\n");
+ HalpDebugPrint("PCI revision id: 0x%x \n", PciVersion );
+ HalpDebugPrint("TSC Control register: 0x%08x\n",rTscControl);
+ HalpDebugPrint("PioPending count: 0x%08x\n",rPIOPendingCount);
+ HalpDebugPrint("\n===========================================================================\n");
+
+ return(1); // success, true, good, ...
+}
+static PCHAR
+gettoken(PCHAR token, PCHAR buf, CHAR delim)
+{
+ CHAR c;
+ while (c = *buf) {
+ if (c == delim) {
+ buf++;
+ break;
+ } else {
+ *token++ = c;
+ buf++;
+ }
+ }
+ *token = '\0';
+ return buf;
+}
+
+VOID
+HalpDisplayVersionData( IN PCHAR VersionData )
+{
+
+ while (*VersionData) {
+ enum {Firmware = 0, Veneer = 1, Nada};
+ ULONG type;
+ PCHAR typeStr[2] = {"Firmware", "Veneer"};
+ CHAR token[64];
+ PCHAR tok = VersionData;
+ VersionData += strlen(VersionData)+1;
+
+ if (strstr(tok, typeStr[Firmware])) {
+ type = Firmware;
+ } else if (strstr(tok, typeStr[Veneer])) {
+ type = Veneer;
+ } else {
+ type = Nada;
+ }
+ if (Nada != type) {
+ CHAR buf[80];
+ strcpy(buf, typeStr[type]);
+ strcat(buf, ":");
+ if (strlen(buf) < 10) {
+ HalpDebugPrint("%-10s", buf);
+ } else {
+ HalpDebugPrint("%s: ", buf);
+ }
+ if (*VersionData) {
+ LONG n;
+
+ tok = VersionData;
+ VersionData += strlen(VersionData)+1;
+ n = 0;
+ tok = gettoken(token, tok, ',');
+ while (token[0]) {
+ switch (n++) {
+ case 2:
+ strcpy(buf, token);
+ strcat(buf, ",");
+ if (strlen(buf) < 7) {
+ HalpDebugPrint("%-7s", buf);
+ } else {
+ HalpDebugPrint("%s ", buf);
+ }
+ break;
+ case 3:
+ //
+ // Put date in Mmm dd yyyy format if in yyyy-mm-dd
+ // No unicode here :-).
+ // isdigit() causes too many link hassles.
+ //
+ if (type == Firmware && *token >= '0' && *token <= '9') {
+ PCHAR day;
+ PCHAR month;
+ PCHAR year;
+ PCHAR Mmm[12] = {
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec",
+ };
+
+ strcpy(buf, token);
+ if (day = strrchr(buf, '-')) {
+ *day++ = '\0';
+ if (month = strrchr(buf, '-')) {
+ ULONG i;
+ *month++ = '\0';
+ RtlCharToInteger(month, 10, &i);
+ if (i > 12 || i < 1) {
+ HalpDebugPrint("%s, ", token);
+ } else {
+ year = buf;
+ //
+ // Decrement the month by one to align with
+ // zero based nature of the Mmm array.
+ //
+ HalpDebugPrint("%s %s %s, ", Mmm[i-1], day, year);
+ }
+ }
+ } else {
+ HalpDebugPrint("%s, ", token);
+ }
+ } else {
+ HalpDebugPrint("%s, ", token);
+ }
+ break;
+ case 4:
+ HalpDebugPrint("%s", token);
+ break;
+ }
+ tok = gettoken(token, tok, ',');
+ }
+ HalpDebugPrint("\n");
+ }
+ }
+ }
+}
+
+PCHAR
+HalpGetVersionData( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCHAR versionData = NULL;
+
+ //
+ // Read the Registry entry to get the Firmware and Veneer version info.
+ //
+
+ if (LoaderBlock) {
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+
+ ConfigurationEntry = KeFindConfigurationEntry (
+ LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ NULL
+ );
+
+ if (ConfigurationEntry) {
+ if (ConfigurationEntry->ComponentEntry.ConfigurationDataLength) {
+ PCM_PARTIAL_RESOURCE_LIST List;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ LONG count;
+
+ List = (PCM_PARTIAL_RESOURCE_LIST) ConfigurationEntry->ConfigurationData;
+ Descriptor = List->PartialDescriptors;
+ for (count = List->Count; count > 0; count--) {
+ if (CmResourceTypeDeviceSpecific == Descriptor->Type) {
+ if (Descriptor->u.DeviceSpecificData.DataSize) {
+ //
+ // Finally, got the device specific data!
+ //
+
+ versionData = (PCHAR) Descriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return versionData;
+}
+
+VOID
+HalpVersionExternal( IN RelInfo *yahoo, IN PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCHAR versionData;
+ CHAR debugStr[50];
+ CHAR buf[BUFSIZ];
+
+
+ // --> Make it look like this <--
+ //
+ // FirePower (TM) Systems, Inc. Powerized (TM) MX4100/2
+ // Copyright (C) 1994-1996 FirePower Systems, Inc.
+ // All rights reserved.
+ //
+ // Firmware: 00.23, Apr 27 1995, 14:42:21
+ // Veneer: 1.0, May 13 1995, 18:59:56
+ // Hal: 0,0, May 16 1995, 18:00:42
+
+ //
+ // Display the Model Number and our company name
+ //
+ HalpDebugPrint("\nFirePower (TM) Systems, Inc. Powerized_%s\n",
+ SystemDescription[SystemType].SystemName);
+ HalpDebugPrint("Copyright (C) 1994-1996 FirePower Systems, Inc.\n");
+ HalpDebugPrint("All rights reserved.\n\n");
+
+ //
+ // Display Version Data from firmware/veneer
+ //
+
+ if ( versionData = HalpGetVersionData(LoaderBlock) ) {
+ HalpDisplayVersionData(versionData);
+ }
+
+ //
+ // Display HAL Version Data
+ //
+
+ sprintf(buf, "%d.%d,", yahoo->Major, yahoo->Minor);
+#if DBG
+#if HALFIRE_EVAL
+ sprintf(debugStr, "DEBUG %s", HALFIRE_EVAL);
+#else
+ strcpy(debugStr, "DEBUG");
+#endif
+#else
+#if HALFIRE_EVAL
+ sprintf(debugStr, "%s", HALFIRE_EVAL);
+#else
+ strcpy(debugStr, "");
+#endif
+#endif
+ if (strlen(buf) < 7) {
+ HalpDebugPrint("HAL: %-7s%s, %s %s\n\n", buf,
+ yahoo->BuildDate, yahoo->BuildTime, debugStr);
+ } else {
+ HalpDebugPrint("HAL: %s %s, %s %s\n\n", buf,
+ yahoo->BuildDate, yahoo->BuildTime, debugStr);
+ }
+}
+
+/*
+*/
+BOOLEAN
+HalpSetRevs( RelInfo *yahoo )
+{
+ CHAR *ads;
+ LONG i=0;
+
+ ads = ORG;
+ while( *ads ) {
+ yahoo->Org[i] = *ads++;
+ i++;
+ }
+ yahoo->Scope = ENG;
+ i=0;
+ ads=__DATE__;
+ while( *ads ) {
+ yahoo->BuildDate[i] = *ads++;
+ i++;
+ }
+ i=0;
+ ads=__TIME__;
+ while( *ads ) {
+ yahoo->BuildTime[i] = *ads++;
+ i++;
+ }
+ yahoo->Major = HAL_MAJOR;
+ yahoo->Minor = HAL_MINOR;
+ yahoo->State = LAB;
+ return TRUE;
+}
+
+#if DBG
+/*
+ * Routine Description: BOOLEAN HalpPrintRevs()
+ *
+ * args:
+ * RelInfo
+ */
+
+BOOLEAN
+HalpPrintRevs( RelInfo *yahoo )
+{
+
+ HalpDebugPrint("Hal version-[%x.%x] \n",yahoo->Major, yahoo->Minor);
+ HalpDebugPrint("%s: ", yahoo->Org );
+ HalpDebugPrint("%s: ", ScopeList[yahoo->Scope]);
+ HalpDebugPrint("%s: ",yahoo->BuildDate);
+ HalpDebugPrint("%s: ",yahoo->BuildTime);
+ HalpDebugPrint("%s: ", RelList[yahoo->State]);
+
+ return TRUE;
+}
+#endif // DBG
diff --git a/private/ntos/nthals/halfire/ppc/pxbeep.c b/private/ntos/nthals/halfire/ppc/pxbeep.c
new file mode 100644
index 000000000..201b01d11
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxbeep.c
@@ -0,0 +1,144 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a Power PC
+ system.
+
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxbeep.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:08:52 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpIoControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxbusdat.c b/private/ntos/nthals/halfire/ppc/pxbusdat.c
new file mode 100644
index 000000000..a72ecf450
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxbusdat.c
@@ -0,0 +1,207 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxbusdat.c $
+ * $Revision: 1.10 $
+ * $Date: 1996/05/14 02:33:37 $
+ * $Locker: $
+ */
+
+
+#include "halp.h"
+#include "fpdebug.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0);
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+ NTSTATUS status;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ status = HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if( !NT_SUCCESS(status) ) {
+ HalDisplayString("HalpAllocateBusHandler: unable to HaliRegister \n");
+ }
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL,
+ sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+
+ return Bus;
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxcache.s b/private/ntos/nthals/halfire/ppc/pxcache.s
new file mode 100644
index 000000000..5c20d501e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxcache.s
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxcache.s $
+ * $Revision: 1.12 $
+ * $Date: 1996/03/05 02:16:01 $
+ * $Locker: $
+ */
+
+//++
+//
+// Copyright (c) 1993, 1994, 1995 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxcache.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 27-Dec-93 plj Added 603 support.
+// 13-Mar-94 plj Fixed problem introduced during switch to pas,
+// added 604 support.
+// 18-Jan-95 plj Add 603+, 604+ and 620 support.
+//
+//--
+
+#include "kxppc.h"
+
+ .set HID0, 1008 // H/W Implementation Dependent reg 0
+
+//
+// Define various known processor types.
+//
+
+ .set PV601, 1 // 601
+ .set PV603, 3 // 603
+ .set PV603P, 6 // 603 plus
+ .set PV604, 4 // 604
+ .set PV604P, 9 // 604 plus
+ .set PV620, 20 // 620
+
+//
+// Note, in the following, the 603's "I-Cache Flash Invalidate"
+// and the 604's "I-Cache Invalidate All" basically perform the
+// same function although the usage is slightly different.
+// In the 603 case, ICFI must be cleared under program control
+// after it is set. In the 604 the bit clears automatically.
+// The 620's ICEFI behaves in the same way as the 604's ICIA.
+//
+
+ .set H0_603_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set H0_604_ICIA, 0x0800 // I-Cache Invalidate All
+ .set H0_620_ICEFI,0x0800 // I-Cache Edge Flash Invalidate
+
+//
+// Cache layout
+//
+// Processor | Size (bytes) | Line Size | Block Size | PVR Processor
+// | I-Cache | D-Cache | | | Version
+// ----------------------------------------------------------------------
+// 601 | 32KB Unified | 64 bytes | 32 bytes | 0x0001xxxx
+// 603 | 8KB | 8KB | 32 | 32 | 0x0003xxxx
+// 603+ | 16KB | 16KB | 32 | 32 | 0x0006xxxx
+// 604 | 16KB | 16KB | 32 | 32 | 0x0004xxxx
+// 604+ | 32KB | 32KB | 32 | 32 | 0x0009xxxx
+// 620 | 32KB | 32KB | 64 | 64 | 0x0014xxxx
+//
+
+ .set DCLSZ601, 64 // 601 cache line size
+ .set DCBSZ601, 32 // 601 cache block size
+ .set DCL601, 32 * 1024 / DCLSZ601 // 601 num cache lines
+ .set DCBSZL2601, 5 // 601 log2(block size)
+
+ .set DCBSZ603, 32 // 603 cache block size
+ .set DCB603, 8 * 1024 / DCBSZ603 // 603 num cache blocks
+ .set DCBSZL2603, 5 // 603 log2(block size)
+
+ .set DCB603P, 16 * 1024 / DCBSZ603 // 603+ num cache blocks
+
+ .set DCBSZ604, 32 // 604 cache block size
+ .set DCB604, 16 * 1024 / DCBSZ604 // 604 num cache blocks
+ .set DCBSZL2604, 5 // 604 log2(block size)
+
+ .set DCB604P, 32 * 1024 / DCBSZ604 // 604+ num cache blocks
+
+ .set DCBSZ620, 64 // 620 cache block size
+ .set DCB620, 32 * 1024 / DCBSZ620 // 620 num cache blocks
+ .set DCBSZL2620, 6 // 620 log2(block size)
+
+//
+// The following variables are declared locally so their addresses
+// will appear in the TOC. During initialization, we overwrite
+// the TOC entries with the entry points for the cache flushing
+// routines appropriate for the processor we are running on.
+//
+// It is done this way rather than filling in a table to reduce the
+// number of access required to get the address at runtime.
+// (This is known as "Data in TOC" which is not very much used in
+// NT at this time).
+//
+
+ .data
+ .globl HalpSweepDcache
+HalpSweepDcache: .long 0
+ .globl HalpSweepIcache
+HalpSweepIcache: .long 0
+ .globl HalpSweepDcacheRange
+HalpSweepDcacheRange: .long 0
+ .globl HalpSweepIcacheRange
+HalpSweepIcacheRange: .long 0
+
+//++
+//
+// Routine Description:
+//
+// HalpCacheSweepSetup
+//
+// This routine is called during HAL initialization. Its function
+// is to set the branch tables for cache flushing routines according
+// to the processor type.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(HalpCacheSweepSetup)
+
+ mfpvr r.3 // get processor type
+ rlwinm r.3, r.3, 16, 0xffff // remove version
+ cmpwi r.3, PV603P // binary search for the right code
+ lwz r.4, [toc].data(r.toc) // get address of local data section
+ bge hcss.high // jif 603+ or greater
+ cmpwi r.3, PV603
+ beq hcss.603 // jif 603
+ bgt hcss.604 // > 603, < 603+ must be 604
+
+//
+// processor is a 601
+//
+
+ lwz r.5, [toc]HalpSweepDcache601(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange601(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange601(r.toc)
+ mr r.6, r.5 // 601 icache use dcache routine
+ b hcss.done
+
+//
+// processor is a 603
+//
+
+hcss.603:
+
+ lwz r.5, [toc]HalpSweepDcache603(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603(r.toc)
+ b hcss.done
+
+//
+// processor is a 604
+//
+
+hcss.604:
+
+ lwz r.5, [toc]HalpSweepDcache604(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604(r.toc)
+ b hcss.done
+
+//
+// Processor type >= 603+, continue isolation of processor type.
+//
+
+hcss.high:
+
+ beq hcss.603p // jif 603 plus
+ cmpwi cr.0, r.3, PV604P
+ cmpwi cr.1, r.3, PV620
+ beq cr.0, hcss.604p // jif 604 plus
+ beq cr.1, hcss.620 // jif 620
+
+//
+// If we got here we are running on a processor whose cache characteristics
+// are not known. Return non-zero for error.
+//
+
+ li r.3, 1
+ blr
+
+//
+// processor is a 603 plus
+//
+
+hcss.603p:
+
+ lwz r.5, [toc]HalpSweepDcache603p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603p(r.toc)
+ b hcss.done
+
+//
+// processor is a 604 plus
+//
+
+hcss.604p:
+
+ lwz r.5, [toc]HalpSweepDcache604p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604p(r.toc)
+ b hcss.done
+
+//
+// processor is a 620
+//
+
+hcss.620:
+
+ lwz r.5, [toc]HalpSweepDcache620(r.toc)
+ lwz r.6, [toc]HalpSweepIcache620(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange620(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange620(r.toc)
+ b hcss.done
+
+
+hcss.done:
+
+//
+// r.5 thru r.9 contain the address of the function descriptors
+// for the routines we really want to use. Dereference them to
+// get at the entry point addresses.
+//
+ lwz r.5, 0(r.5)
+ lwz r.6, 0(r.6)
+ lwz r.7, 0(r.7)
+ lwz r.8, 0(r.8)
+
+//
+// Store the entry point addresses directly into the TOC.
+// This is so direct linkage from within the HAL to the
+// generic cache flushing routines can get to the desired
+// routines for this processor.
+//
+
+ stw r.5, [toc]HalpSweepDcache(r.toc)
+ stw r.6, [toc]HalpSweepIcache(r.toc)
+ stw r.7, [toc]HalpSweepDcacheRange(r.toc)
+ stw r.8, [toc]HalpSweepIcacheRange(r.toc)
+
+//
+// Modify the Function Descriptors for the generic routines to
+// point directly at the target routines so that linkage from
+// other executables (eg the kernel) will be direct rather
+// than via the generic routines.
+//
+
+ lwz r.3, [toc]HalSweepDcache(r.toc)
+ lwz r.4, [toc]HalSweepIcache(r.toc)
+ stw r.5, 0(r.3)
+ stw r.6, 0(r.4)
+ lwz r.3, [toc]HalSweepDcacheRange(r.toc)
+ lwz r.4, [toc]HalSweepIcacheRange(r.toc)
+ stw r.7, 0(r.3)
+ stw r.8, 0(r.4)
+
+ li r.3, 0 // return code = success
+
+ LEAF_EXIT(HalpCacheSweepSetup)
+
+//++
+//
+// Routines HalSweepDcache
+// HalSweepIcache
+// HalSweepDcacheRange
+// HalSweepIcacheRange
+//
+// are simply dispatch points for the appropriate routine for
+// the processor being used.
+//
+//--
+
+
+ LEAF_ENTRY(HalSweepDcache)
+
+ lwz r.12, [toc]HalpSweepDcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcache)
+
+
+
+ LEAF_ENTRY(HalSweepIcache)
+
+ lwz r.12, [toc]HalpSweepIcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcache)
+
+
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+ lwz r.12, [toc]HalpSweepDcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcacheRange)
+
+
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+ lwz r.12, [toc]HalpSweepIcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcacheRange)
+
+
+
+
+//++
+//
+// 601 Cache Flushing Routines
+//
+// The 601 has a unified instruction/data cache. For this reason
+// we need only two routines, one to sweep the entire cache and
+// another to sweep a given range.
+//
+//
+//
+//
+// HalpSweepDcache601
+//
+// Sweep the entire instruction/data cache. This is accomplished
+// by loading the cache with data corresponding to a known address
+// range and then ensuring that each block in the cache is not dirty.
+//
+// Note that the 601 line size is 64 bytes and its block size is 32
+// bytes. When we load any byte within a line, both blocks in that
+// line are loaded into the cache (if not already present). We must
+// clean each block individually.
+//
+// In an effort to maximize the possibilities that (a) the addressed
+// data is already in the cache and (b) there is some use in having
+// this data in the cache, we use the lower end of the hashed page
+// table as the data to be loaded and we use dcbst rather than dcbf
+// to force the block to memory (and leave it valid in the cache as
+// well).
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache601)
+
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ li r.4, DCL601 // size of cache in cache lines
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ601 // dec addr prior to inc
+hsd601.ld:
+ lbzu r.8, DCLSZ601(r.5)
+ bdnz hsd601.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ LEAF_EXIT(HalpSweepDcache601)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange601
+//
+// HalpSweepDcacheRange603
+//
+// HalpSweepDcacheRange603p
+//
+// HalpSweepDcacheRange604
+//
+// HalpSweepDcacheRange604p
+//
+// Force data in a given address range to memory.
+//
+// Because this routine works on a range of blocks and block size
+// is the same on 601, 603, 603+, 604 and 604+ we can use the same
+// code for each of them.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange601)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603p)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ601-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ601-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2601 // number of blocks
+ mtctr r.4
+ sync
+hsdr601.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ601 // bump address
+ bdnz hsdr601.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange601)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange601
+//
+// Due to the unified cache, this routine is meaningless on a 601.
+// The reason for flushing a range of instruction address is because
+// of code modification (eg breakpoints) in which case the nature
+// of the unified cache is that the *right* code is in the cache,
+// or because of a transfer of a code page in which case the unified
+// snooping cache will have done the right thing.
+//
+// Therefore this routine simply returns.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange601)
+
+ // return
+
+ LEAF_EXIT(HalpSweepIcacheRange601)
+
+//++
+//
+// 603, 603+ Cache Flushing Routines
+//
+// The 603 has seperate instruction and data caches of 8 KB each.
+// The 603+ has seperate instruction and data caches of 16 KB each.
+// Line size = Block size = 32 bytes.
+//
+// The mechanics of cache manipulation are the same for the 603 and
+// 603+.
+//
+//
+//
+// HalpSweepDcache603 HalpSweepDcache603p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// The 603 does not have a hashed page table so we can't use the
+// hashed page table as the data range. Instead use the start of
+// KSEG0.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache603p)
+
+ li r.4, DCB603P // size of 603+ cache in blocks
+ b hsd603
+
+ DUMMY_EXIT(HalpSweepDcache603p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache603)
+
+ li r.4, DCB603 // size of 603 cache in blocks
+hsd603:
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync // ensure ALL previous stores completed
+ LWI(r.3,0x80000000) // known usable virtual address
+ subi r.5, r.3, DCBSZ603 // dec addr prior to inc
+hsd603.ld:
+ lbzu r.8, DCBSZ603(r.5)
+ bdnz hsd603.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ mtctr r.4
+hsd603.fl:
+ dcbst 0, r.3 // ensure block is in memory
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsd603.fl
+
+ LEAF_EXIT(HalpSweepDcache603)
+
+
+
+
+//++
+//
+// HalpSweepIcache603 HalpSweepIcache603p
+//
+// Sweep the entire instruction cache. The instruction cache (by
+// definition) can never contain modified code (hence there are no
+// icbf or icbst instructions). Therefore what we really need to do
+// here is simply invalidate every block in the cache. This can be
+// done by toggling the Instruction Cache Flash Invalidate (ICFI) bit
+// in the 603's HID0 register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache603)
+
+ ALTERNATE_ENTRY(HalpSweepIcache603p)
+
+ mfspr r.3, HID0 // 603, use Instruction
+ ori r.4, r.3, H0_603_ICFI // Cache Flash Invalidate
+
+ isync
+ mtspr HID0, r.4 // invalidate I-Cache
+ mtspr HID0, r.3 // re-enable
+
+ LEAF_EXIT(HalpSweepIcache603)
+
+
+
+//++
+//
+// HalpSweepIcacheRange603 HalpSweepIcacheRange603p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Note that if this is going to take a long time we flash
+// invalidate the I cache instead. Currently I define a
+// "long time" as greater than 4096 bytes which amounts to
+// 128 trips thru this loop (which should run in 256 clocks).
+// This number was selected without bias or forethought from
+// thin air - plj. I chose this number because gut feel tells
+// me that it will cost me more than 256 clocks in cache misses
+// trying to get back to the function that requested the cache
+// flush in the first place.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange603p)
+
+ cmpwi r.4, 4096 // if range > 4096 bytes, flush
+ bgt- ..HalpSweepIcache603 // entire I cache
+
+ rlwinm r.5, r.3, 0, DCBSZ603-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ603-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2603 // number of blocks
+ mtctr r.4
+hsir603.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsir603.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange603)
+
+
+//++
+//
+// 604 Cache Flushing Routines
+//
+// The 604 has seperate instruction and data caches of 16 KB each.
+// The 604+ has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 32 bytes.
+//
+//
+//
+// HalpSweepDcache604 HalpSweepDcache604p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache604p)
+
+ li r.4, DCB604P // size of 604+ cache in blocks
+ b hsd604
+
+ DUMMY_EXIT(HalpSweepDcache604p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache604)
+
+ li r.4, DCB604 // size of cache in cache blocks
+hsd604:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync // ensure ALL previous stores completed
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ604 // dec addr prior to inc
+hsd604.ld:
+ lbzu r.8, DCBSZ604(r.5)
+ bdnz hsd604.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ LEAF_EXIT(HalpSweepDcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcache604 HalpSweepIcache604p
+//
+// Sweep the entire instruction cache. This routine is functionally
+// similar to the 603 version except that on the 604 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Invali-
+// sate All (ICIA) and it clears automatically after being set.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache604)
+
+ ALTERNATE_ENTRY(HalpSweepIcache604p)
+
+ mfspr r.3, HID0 // 604, use Instruction
+ ori r.3, r.3, H0_604_ICIA // Cache Invalidate All
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange604 HalpSweepIcacheRange604p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ604-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ604-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2604 // number of blocks
+ mtctr r.4
+hsir604.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ604 // bump address
+ bdnz hsir604.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange604)
+
+//++
+//
+// 620 Cache Flushing Routines
+//
+// The 620 has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 64 bytes.
+//
+//
+//
+// HalpSweepDcache620
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache620)
+
+ li r.4, DCB620 // size of cache in cache blocks
+hsd620:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ620 // dec addr prior to inc
+hsd620.ld:
+ lbzu r.8, DCBSZ620(r.5)
+ bdnz hsd620.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ LEAF_EXIT(HalpSweepDcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcache620
+//
+// Sweep the entire instruction cache. This routine is functionally
+// identical to the 604 version except that on the 620 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Edge
+// Flash Invalidate (ICEFI).
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache620)
+
+ mfspr r.3, HID0 // 620, use Instruction
+ ori r.3, r.3, H0_620_ICEFI // Cache Edge Flash Invalidate
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange620
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+hsir620.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsir620.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange620)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange620
+//
+// Force data in a given address range to memory.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+ sync
+hsdr620.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsdr620.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange620)
+
+
+//++
+//
+// HalpSweepPhysicalRangeInBothCaches
+//
+// Force data in a given PHYSICAL address range to memory and
+// invalidate from the block in the instruction cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .set PAGE_SHIFT, 12
+
+
+ LEAF_ENTRY(HalpSweepPhysicalRangeInBothCaches)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspribc
+hspribc:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspribc.real - hspribc
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspribc.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspribc.loop:
+ dcbst 0, r.4 // flush data block to memory
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspribc.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalRangeInBothCaches)
+
+//++
+//
+// HalpSweepPhysicalIcacheRange
+//
+// Invalidate a given PHYSICAL address range from the instruction
+// cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepPhysicalIcacheRange)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspir
+hspir:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspir.real - hspir
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+//
+// N.B. It may not be required that Data Relocation be disabled here.
+// I can't tell from my Arch spec if ICBI works on a Data or
+// Instruction address. I believe it is probably a Data
+// address even though it would be sensible for it to be an
+// instruction address,....
+//
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspir.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspir.loop:
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspir.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalIcacheRange)
diff --git a/private/ntos/nthals/halfire/ppc/pxcalstl.c b/private/ntos/nthals/halfire/ppc/pxcalstl.c
new file mode 100644
index 000000000..bc75249d0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxcalstl.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxcalstl.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/01/11 07:09:11 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service for a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jim Wooldridge
+ Steve Johns (Motorola)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+
+//
+// KeQueryPerformanceCounter & KeStallExecutionProcessor are called
+// before Phase 0 initialization, so initialize it to a reasonable value.
+//
+ULONG HalpPerformanceFrequency = 80000000/16;
+ULONG CpuFrequency;
+ULONG ProcessorBusFrequency;
+ULONG HalpGetCycleTime(VOID);
+extern ULONG CpuClockMultiplier;
+extern ULONG HalpClockCount;
+extern ULONG HalpFullTickClockCount;
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateTimingValues)
+
+#endif
+
+
+/*++
+
+Routine Description: BOOLEAN HalpCalibrateTimingValues ( VOID )
+
+ This function calibrates the stall execution HAL service.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalpCalibrateTimingValues (
+ VOID
+ )
+{
+ ULONG TmpCpuHertz;
+
+ //
+ // Set initial scale factor
+ //
+ PCR->StallScaleFactor = 1;
+
+ //
+ // Compute the clock frequency of the Time Base & Decrementer
+ //
+ HalpPerformanceFrequency = HalpCalibrateTB();
+ // HalpPerformanceFrequency = (HalpPerformanceFrequency / 1000) * 1000;
+
+ //
+ // Since the TimeBase ticks once for every four bus clock cycles, multiply
+ // the HalpPerformanceFrequency by 4. This is the bus speed in Hertz. Now
+ // apply the cpu chip clock multiplier calculated back in
+ // HalpInitializeProcessor and perform rounding converting to MegaHertz.
+ //
+ ProcessorBusFrequency = (4 * HalpPerformanceFrequency);
+
+ //
+ // Since the CpuClockMultiplier is really 10 times the true multiplier,
+ // add one more order of magnitude to the divisor when converting to
+ // megahertz
+ //
+ TmpCpuHertz = (CpuClockMultiplier * ProcessorBusFrequency)/1000000;
+ CpuFrequency = TmpCpuHertz/10;
+
+ //
+ // check to see if the sub megahertz residual of the frequency
+ // calculations are large enough to round up to the next megahertz.
+ //
+ if ((TmpCpuHertz - ((TmpCpuHertz/10)*10)) >= 5) {
+ CpuFrequency++; // round up to the next Megahertz.
+ }
+
+ //
+ // Initialize the system clock variable
+ //
+ HalpClockCount =
+ (HalpPerformanceFrequency * (MAXIMUM_INCREMENT/10000)) / 1000;
+ HalpFullTickClockCount = HalpClockCount;
+
+ return TRUE;
+}
+
+ULONG
+HalpGetCycleTime()
+{
+ HDBG(DBG_TIME,
+ HalpDebugPrint("HalpGetCycleTime: PerfFreq(%d), ClockCount(%d)\n",
+ HalpPerformanceFrequency, HalpClockCount););
+ return( CpuFrequency );
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxcirrus.h b/private/ntos/nthals/halfire/ppc/pxcirrus.h
new file mode 100644
index 000000000..32aee24df
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxcirrus.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxcirrus.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/11 07:09:18 $
+ * $Locker: $
+ */
+
+/*
+ * pxcirrus.h
+ *
+ * Defines for cirrus HAL support
+ */
+
+#define CIRRUS_VIDEO_MEMORY_BASE 0xc0000000
+#define CIRRUS_VENDOR_ID 0x1013
+#define CIRRUS_COMMAND_MASK 0x03
+
+#define CIRRUS_TEXT_MEM 0xb8000
+#define CIRRUS_FONT_MEM 0xa0000
+
+
+#define WRITE_CIRRUS_UCHAR(port,data) \
+ *(volatile unsigned char *) \
+ ((ULONG)HalpIoControlBase+(port))=(UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_CIRRUS_VRAM(port,data) \
+ *((PUCHAR)((ULONG) HalpVideoMemoryBase + (port))) = (UCHAR) (data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_CIRRUS_USHORT(port,data) \
+ *(volatile unsigned short*) \
+ ((ULONG)HalpIoControlBase+(port))=(USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_CIRRUS_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define READ_CIRRUS_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define setreg(port,index,data) \
+ WRITE_CIRRUS_UCHAR(port,index), \
+ WRITE_CIRRUS_UCHAR(port+1,data)
+
+#define outportb(port,data) \
+ WRITE_CIRRUS_UCHAR(port,data)
+
+#define outp(port,data) outportb(port,data)
+
+#define inp(port) \
+ READ_CIRRUS_UCHAR(port)
+
+#define INSTATUS_1 (PVOID) ((ULONG)((int)HalpIoControlBase + (int)0x03DA))
+
+
+
+
+//
+// Attributes Registers
+//
+
+static unsigned char attr3[] =
+{
+ 0x00, // AR0-ARF: Attribute Controller
+ 0x01, // Palette Registers
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x14,
+ 0x07,
+ 0x38,
+ 0x39,
+ 0x3a,
+ 0x3b,
+ 0x3c,
+ 0x3d,
+ 0x3e,
+ 0x3f,
+ 0x0c, // AR10: Attribute Controller Mode
+ // Blink Enable
+ // Line Graphics Enable
+ 0x00, // AR11: Overscan (Border) color
+ 0x0f, // AR12: Color Plane Enable
+ // All planes enabled
+ 0x08, // AR13: Pixel Panning
+ 0x00 // AR14: Color Select
+};
+
+//
+// CRT control
+//
+
+static unsigned char crtc3[] =
+{
+ 0x5f, // CR0: Horizontal Total
+ 0x4f, // CR1: Horizontal Display End
+ 0x50, // CR2: Start Horizontal Blinking
+ 0x82, // CR3: End Horizontal Blanking
+ 0x55, // CR4: Start Horizontal Retrace Pulse
+ 0x81, // CR5: End Horizontal Retrace Pulse
+ 0xbf, // CR6: Vertical Total
+ 0x1f, // CR7: Overflow
+ 0x00, // CR8: Row Scan
+ 0x4f, // CR9: Character Cell Height (16)
+ 0x0d, // CRa: Text Cursor Start Register
+ 0x0e, // CRb: Text Cursor End Register
+ 0x00, // CRc: Screen Start High
+ 0x00, // CRd: Screen Start Low
+ 0x00, // CRe: Text Cursor Location High
+ 0x00, // CRf: Text Cursor Location Low
+ 0x9c, // CR10: Vertical Sync Start
+ 0xae, // CR11: Vertical Sync End
+ 0x8f, // CR12: Vertical Display End
+ 0x28, // CR13: Offset
+ 0x1f, // CR14: Underline Row Scanline
+ 0x96, // CR15: Vertical Blank Start
+ 0xb9, // CR16: Vertical Blank End
+ 0xa3, // CR17: Mode Control
+ 0xff, // CR18: Line Compare
+ 0x00, // CR19: Interlace End
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+
+//
+// Graphics Registers
+//
+
+static unsigned char graph3[] =
+{
+ 0x00, // GR0: Set/Reset Register
+ 0x00, // GR1: Set/Reset Enable Register
+ 0x00, // GR2: Color Compare
+ 0x00, // GR3: Data Rotate Register
+ 0x00, // GR4: Read Map Select Register
+ 0x10, // GR5: Mode Register (Odd/Even On)
+
+ 0x0e, // GR6: Miscellaneous Register
+ // Memory Map b800:0
+ // Chain Odd Maps to Even
+ 0x00, // GR7: Color Don't Care register
+ 0xff // GR8: Bit Mask Register
+};
+
+//
+// Sequencer Registers
+//
+
+static unsigned char seq3[] =
+{
+ 0x03, // SR0: Reset Register
+ // Asynchronous and Synchronous reset
+ 0x00, // SR1: Clocking Mode
+ 0x03, // SR2: Plane Mask Register
+ // Map 0 and 1 Enable
+ 0x00, // SR3: Character Map Select Register
+ 0x02, // SR4: Memory Mode
+ // Extended Memory
+};
+
+//
+// Extended Sequencer Registers
+//
+
+static unsigned char eseq3[] =
+{
+ 0x6,0x12, // SR6: Unlock All Extensions
+ 0x7,0x00, // SR7: Extended Sequencer Mode
+ 0x8,0x40, // SR8: EEPROM Control
+// tsa 0x8,0x00, // SR8: EEPROM Control
+ 0xb,0x4a, // SRb: VCLK 0 Numerator Register
+ 0xc,0x5b, // SRc: VCLK 1 Numerator Register
+ 0xd,0x42, // SRd: VCLK 2 Numerator Register
+ 0xe,0x6e, // SRe: VCLK 3 Numerator Register
+//tsa x 0xe,0x7e, // SRe: VCLK 3 Numerator Register
+ 0xf,0x1d, // SRf: DRAM control
+ 0x12,0x00, // SR12: Cursor Attributes
+ 0x16,0x71, // SR16: Performance Tuning
+ 0x18,0x00, // SR18: Signature Generator Control
+ 0x1b,0x2b, // SR1b: VCLK Denominator and Post-Scalar
+ 0x1c,0x2f,
+ 0x1d,0x1f,
+ 0x1e,0x2a,
+//tsa x 0x1e,0x33,
+ 0x1f,0x1c,
+ 0xff
+};
+
+//
+// Extended CRTC Registers
+//
+
+static unsigned char ecrtc3[] =
+{
+ 0x19,0x00, // CR19: Inerlace End
+ 0x1a,0x00, // CR1a: Miscellaneous
+ 0x1b,0x00, // CR1b: Extended Display Controlls
+ 0xff
+};
+
+//
+// Extended Graphics Registers
+//
+
+static unsigned char egraph3[] =
+{
+ 0x9,0x00, // GR9: Offset Register 0
+ 0xa,0x00, // GRa: Offset Register 1
+ 0xb,0x00, // GRb: Graphics Controller Mode Extnsions
+ 0xc,0xff, // GRc: Color Key Compare
+ 0xd,0x00, // GRd: Color Key Compare Mask
+ 0x10,0x00, // GR10: Background Color Byte 1
+ 0x11,0x00, // GR11: Foreground Color Byte 1
+ 0xff
+};
+
+//
+// Extended Attribute Registers
+//
+
+static unsigned char eattr3[] =
+{
+ 0xff
+};
diff --git a/private/ntos/nthals/halfire/ppc/pxclksup.s b/private/ntos/nthals/halfire/ppc/pxclksup.s
new file mode 100644
index 000000000..2a3c37e99
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxclksup.s
@@ -0,0 +1,163 @@
+/***********************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+ File Name:
+ PXCLKSUP.S
+
+ Globals:
+ none
+
+ Functions:
+ HalpUpdateDecrementer
+ KeQueryPerformanceCounter
+
+ History:
+ 11-Feb-1994 Steve Johns
+ Original Version
+ 23-Jun-1994 Steve Johns (sjohns@pets.sps.mot.com)
+ Fixed HalpZeroPerformanceCounter. Was writing to RTCU & RTCL.
+ Writes should go to SPR 20 & 21.
+***********************************************************************/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxclksup.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:33:44 $
+ * $Locker: $
+ */
+
+#include <halppc.h>
+#define ERRATA603 TRUE
+
+
+
+
+ LEAF_ENTRY(HalpUpdateDecrementer)
+
+
+ mfpvr r.6 // Read Processor Version Register
+ rlwinm r.6,r.6,16,16,31
+ cmpli 0,0,r.6,1 // Is it an MPC601 ?
+ bne Not_601
+ rlwinm r.3,r.3,7,0,24 // Yes, Count *= 128
+Not_601:
+//
+// Read the DECREMENTER to get the interrupt latency and bias Count by
+// that amount. Otherwise, the latencies would accumulate and the time
+// of day would run slow.
+//
+ mfdec r.7 // Read the DECREMENTER
+ add r.4,r.3,r.7 // + Count
+//
+// We expect that the DECREMENTER should be near 0xFFFFFFxx, so R4 should
+// be less than r.3. If not, we don't want to cause an excessively long
+// clock tick, so just ignore the latency and use Count.
+//
+ cmpl 0,0,r.4,r.3
+ ble SetDecr
+ mr r.4,r.3
+SetDecr:
+
+ mtdec r.4 // Write to the DECREMENTER
+#if ERRATA603
+ isync
+#endif
+
+// Undocumented return value: the latency in servicing this interrupt
+ neg r.3,r.7
+
+
+ LEAF_EXIT(HalpUpdateDecrementer)
+
+
+
+ .extern HalpPerformanceFrequency
+ .extern ..HalpGetTimerRoutine
+
+
+/***********************************************************************
+ Synopsis:
+ ULARGE_INTEGER KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
+
+ Purpose:
+ Supplies a 64-bit realtime counter for use in evaluating performance
+ of routines.
+
+ Returns:
+ This routine returns current 64-bit performance counter and,
+ optionally, the frequency of the Performance Counter.
+
+ Global Variables Referenced:
+ HalpPerformanceFrequency
+
+***********************************************************************/
+
+//
+// Register Definitions
+//
+ .set RetPtr, r.3
+ .set Freq, r.4
+ .set TimerLo, r.6 // MUST be same as defined in PXSTALL.S
+ .set TimerHi, r.7 // MUST be same as defined in PXSTALL.S
+ .set Temp, r.8
+
+ .set RTCU, 4
+ .set RTCL, 5
+ .set TB, 284
+ .set TBU, 285
+
+
+ LEAF_ENTRY(KeQueryPerformanceCounter)
+
+ mflr r.0 // Save Link Register
+
+ cmpli 0,0,Freq,0 // Was PerformanceFrequency passed ?
+ beq GetCpuVersion
+
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp) // PerformanceFrequency.LowPart =
+ stw Temp,0(Freq) // HalpPerformanceFrequency;
+ li Temp,0 // PerformanceFrequency.HighPart = 0;
+ stw Temp,4(Freq)
+
+GetCpuVersion:
+ bl ..HalpGetTimerRoutine
+
+ bctrl // ReadPerformanceCounter();
+
+ stw TimerLo,0(RetPtr)
+ stw TimerHi,4(RetPtr)
+ mtlr r.0 // Restore Link Register
+
+ LEAF_EXIT(KeQueryPerformanceCounter)
+
+
+ LEAF_ENTRY(HalpZeroPerformanceCounter)
+
+
+ mfpvr r.4 // Read Processor Version Register
+ li r.3, 0
+ rlwinm r.4,r.4,16,16,31
+ cmpli 0,0,r.4,1 // Are we running on an MPC601 ?
+ beq ZeroRTC // Branch if yes
+
+ mtspr TB,r.3
+ mtspr TBU,r.3
+
+ blr
+
+ZeroRTC:
+ mtspr 20,r.3 // Zero the RTC registers
+ mtspr 21,r.3
+
+
+ LEAF_EXIT(HalpZeroPerformanceCounter)
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxclock.c b/private/ntos/nthals/halfire/ppc/pxclock.c
new file mode 100644
index 000000000..8d34efa28
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxclock.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxclock.c $
+ * $Revision: 1.19 $
+ * $Date: 1996/05/14 02:33:49 $
+ * $Locker: $
+ */
+
+/*****************************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ PXCLOCK.C
+
+Abstract:
+
+ This module contains the system clock interrupt handler.
+ The DECREMENTER is used to implement the system clock. The
+ handler resets the DECREMENTER to SYSTEM_TIME (accounting
+ for interrupt latency), and updates the system time.
+
+
+Author:
+
+ Steve Johns 10-Feb-1994
+
+Revision History:
+
+******************************************************************************/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpreg.h"
+#include "fpcpu.h"
+
+extern ULONG HalpPerformanceFrequency;
+extern ULONG Irql2Mask[];
+extern ULONG registeredInts[];
+
+BOOLEAN KdPollBreakIn (VOID);
+
+ULONG HalpClockCount;
+ULONG HalpFullTickClockCount;
+ULONG HalpUpdateDecrementer();
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNewTimeIncrement;
+
+// VOID KeUpdateRunTime(PVOID);
+
+/*++
+Routine Description:
+
+ Clock interrupt handler for processor 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+BOOLEAN
+HalpHandleDecrementerInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ KIRQL OldIrql;
+ static int recurse = FALSE;
+ ULONG CpuId;
+
+ HASSERT(!MSR(EE));
+
+ CpuId = GetCpuId();
+
+ //
+ // Raise irql via updating the PCR
+ //
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+ RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+ HalpUpdateDecrementer(HalpClockCount);
+
+ //
+ // Call the kernel to update system time
+ //
+ KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
+ HalpCurrentTimeIncrement = HalpNewTimeIncrement;
+
+ if (!recurse) {
+ //
+ // In some circumstances the KdPollBreakIn can
+ // take longer than a decrementer interrupt
+ // to complete. This is do to a conflict
+ // between DMA and PIO. For now, just avoid
+ // recursing into the debugger check.
+ //
+ recurse = TRUE;
+ if (KdDebuggerEnabled && KdPollBreakIn()) {
+ HalpEnableInterrupts();
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ HalpDisableInterrupts();
+ }
+ recurse = FALSE;
+ }
+
+ //
+ // Lower Irql to original value and enable interrupts
+ //
+ PCR->CurrentIrql = OldIrql;
+ RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+ return (TRUE);
+}
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processors other than 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+BOOLEAN
+HalpHandleDecrementerInterrupt1(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ KIRQL OldIrql;
+ ULONG CpuId;
+
+ HASSERT(!MSR(EE));
+
+ CpuId = GetCpuId();
+
+ //
+ // Raise irql via updating the PCR
+ //
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+ RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ //
+ // Reset DECREMENTER (no account for latency)
+ //
+ HalpUpdateDecrementer(HalpFullTickClockCount);
+
+ //
+ // Call the kernel to update run time for this thread and process.
+ //
+ KeUpdateRunTime(TrapFrame);
+
+ HDBG(DBG_PROC1DBG,
+ {
+ //
+ // Check for the debugger BreakIn only every minute or so.
+ // (decrementer is interms of ms so we multiple by 10,000
+ // on the order of a minute).
+ //
+ static Count = 0;
+ if (++Count > 10000) {
+ Count = 0;
+ if (KdDebuggerEnabled && KdPollBreakIn()) {
+ HalpEnableInterrupts();
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ HalpDisableInterrupts();
+ }
+ }
+ }
+ );
+
+ //
+ // Lower Irql to original value
+ //
+ PCR->CurrentIrql = OldIrql;
+ RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // HalpPerformanceFrequence is the number of times the decrementer
+ // ticks in 1 second. MINIMUM_INCREMENT is the number of 100 is the
+ // number of 100ns units in 1 ms.
+ // Therefore, DesiredIncrement/MINUMUM_INCREMENT is the number of
+ // ms desired. This multiplied by the number of decrementer ticks
+ // in 1 second, divided by 1000 gives the number of ticks in the
+ // desired number of milliseconds. This value will go into the
+ // decrementer.
+ //
+
+ NextIntervalCount = (HalpPerformanceFrequency *
+ (DesiredIncrement/MINIMUM_INCREMENT)) / 1000;
+
+ //
+ // Calculate the number of 100ns units to report to the kernel every
+ // time the decrementer fires with this new period. Note, for small
+ // values of DesiredIncrement (min being 10000, ie 1ms), truncation
+ // in the above may result in a small decrement in the 5th decimal
+ // place. As we are effectively dealing with a 4 digit number, eg
+ // 10000 becomes 9999.something, we really can't do any better than
+ // the following.
+ //
+
+ NewTimeIncrement = DesiredIncrement/MINIMUM_INCREMENT * MINIMUM_INCREMENT;
+ HalpClockCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxdat.c b/private/ntos/nthals/halfire/ppc/pxdat.c
new file mode 100644
index 000000000..6b220977a
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxdat.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxdat.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/05/14 02:33:54 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x000, 0x10, // SIO DMA
+ 0x0C0, 0x20, // SIO DMA
+ 0x080, 0x10, // SIO DMA
+ 0x400, 0x40, // SIO DMA
+ 0x480, 0x10, // SIO DMA
+ 0x4D6, 0x2, // SIO DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+
+ 0x074, 0x4, // NVRAM
+
+ 0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList = 0;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHALentry[] = L"\\Registry\\Machine\\Hardware\\ResourceMap\\Hardware Abstraction Layer\\Powerized HAL";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzSystem[] = L"\\Registry\\Machine\\Hardware\\Description\\System";
+WCHAR rgzSoftwareDescriptor[] = L"\\Registry\\Machine\\Software";
+WCHAR rgzFirePOWERNode[] = L"\\Registry\\Machine\\Software\\FirePOWER";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+WCHAR rgzCpuNode[] = L"Registry\\Machine\\Hardware\\Description\\System\\CentralProcessor";
+WCHAR rgzHalNode[] = L"\\HardwareAbstractionLayer";
+WCHAR rgzVeneerNode[] = L"\\Veneer";
+WCHAR rgzFirmwareNode[] = L"\\OpenFIRMWARE";
+
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
diff --git a/private/ntos/nthals/halfire/ppc/pxdisp.c b/private/ntos/nthals/halfire/ppc/pxdisp.c
new file mode 100644
index 000000000..aa06f64db
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxdisp.c
@@ -0,0 +1,2907 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxdisp.c $
+ * $Revision: 1.44 $
+ * $Date: 1996/07/02 04:58:11 $
+ * $Locker: $
+ */
+
+/*++
+
+ Copyright (c) 1994 International Business Machines Corporation
+
+ Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+ Module Name:
+
+ pxdisp.c
+
+ Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
+ video adapter.
+
+ Author:
+
+ Jim Wooldridge Sept 1994 - Ported to PowerPC Initial Version
+
+ Environment:
+
+ Kernel mode
+
+ Revision History:
+
+ Jess Botts S3 support in text mode Oct-1993
+ Lee Nolan Added Weitek P9000 support Feb-1994
+ Mike Haskell Added Weitek P9100 support Oct-1994
+ Roger Lanser 02-23-95: Added FirePower Video and INT10, nuc'd others
+
+ --*/
+
+#include "halp.h"
+#include "pxs3.h" // BUGBUG: generic output?
+#include "string.h"
+#include "fpbat.h"
+#include "arccodes.h"
+#include "phsystem.h"
+#include "pxmemctl.h"
+#include "fpdcc.h"
+#include "fpcpu.h"
+#include "fpdebug.h"
+#include "phsystem.h"
+#include "x86bios.h"
+#include "pxpcisup.h"
+#include "pxcirrus.h"
+
+#define MAX_DBATS 4
+
+// for test only
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlCharToInteger (
+ PCSZ String,
+ ULONG Base,
+ PULONG Value
+ );
+
+//=============================================================================
+//
+// IBMBJB added include to get text mode values for the Brooktree 485 DAC's
+// palette registers, removed definition of HDAL and added address
+// definitions for PowerPC
+
+#include "txtpalet.h"
+#include "pci.h"
+
+// PCI Vendor ID & Device ID
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000 0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100 0x9100
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_DEVICE_ID_S3_864_1 0x88c0
+#define PCI_DEVICE_ID_S3_864_2 0x88c1
+
+#if defined(_PPC_)
+
+#define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
+#define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
+
+#endif
+
+#define ROWS 25
+#define COLS 80
+#define TAB_SIZE 4
+#define ONE_LINE (80*2)
+#define TWENTY_FOUR_LINES 24*ONE_LINE
+#define TWENTY_FIVE_LINES 25*ONE_LINE
+#define TEXT_ATTR 0x1F
+
+//PHYSICAL ADDRESS of WEITEK P9100 video ram
+#define P91_VIDEO_MEMORY_BASE 0xC1800000
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+#if DBG
+extern VOID HalpDisplayBatForVRAM ( void );
+# define TRACE Trace
+#else
+# define TRACE
+#endif
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+//
+// Define forward referenced procedure prototypes.
+//
+BOOLEAN HalpDisplayINT10Setup (VOID);
+VOID HalpOutputCharacterINT10 (IN UCHAR Character );
+VOID HalpScrollINT10 (IN UCHAR line);
+VOID HalpDisplayCharacterVGA (IN UCHAR Character );
+VOID HalpDisplayCharacterVgaViaBios (IN UCHAR Character);
+VOID HalpOutputCharacterVgaViaBios (IN UCHAR AsciiChar);
+BOOLEAN HalpDisplaySetupVgaViaBios (VOID);
+
+
+BOOLEAN HalpDisplayPowerizedGrapicsSetup (ULONG);
+BOOLEAN HalpDisplayPowerizedGraphicsSetup (VOID);
+VOID HalpDisplayCharacterPowerizedGraphics (IN UCHAR Character);
+VOID HalpOutputCharacterPowerizedGraphics (IN PUCHAR Glyph);
+BOOLEAN HalpInitializeDisplay (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
+VOID HalpOutputCharacterS3 (IN UCHAR AsciiChar);
+BOOLEAN HalpDisplayPpcS3Setup (VOID);
+VOID HalpScrollS3(IN UCHAR line);
+BOOLEAN HalpDisplayPpcP91Setup (VOID);
+VOID HalpDisplayCharacterP91 (IN UCHAR Character);
+VOID HalpOutputCharacterP91(IN PUCHAR Glyph);
+BOOLEAN HalpDisplayPpcP91BlankScreen (VOID);
+VOID HalpDisplayCharacterCirrus(IN UCHAR Character);
+VOID HalpOutputCharacterCirrus(IN UCHAR AsciiChar);
+BOOLEAN HalpDisplayPpcCirrusSetup(VOID);
+VOID HalpScrollCirrus(IN UCHAR line);
+
+static void updattr(IN int rg,IN unsigned char val);
+static void set_ext_regs(IN int reg,IN unsigned char *p);
+static void clear_text(VOID);
+static void load8x16(VOID);
+static void load_ramdac();
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalpInitializeDisplay)
+#pragma alloc_text(INIT, HalpInitializeVRAM)
+#if DBG
+#pragma alloc_text(INIT, HalpDisplayBatForVRAM)
+#endif
+#endif
+
+#if !defined(NT_UP)
+ULONG HalpDisplayLock;
+#endif // !defined(NT_UP)
+
+
+typedef VOID (*PHALP_SCROLL_SCREEN) (UCHAR);
+typedef VOID (*PHALP_OUTPUT_CHARACTER) (UCHAR);
+typedef BOOLEAN (*PHALP_CONTROLLER_SETUP) (VOID);
+typedef VOID (*PHALP_DISPLAY_CHARACTER) (UCHAR);
+
+//
+// Define global data.
+//
+ULONG HalpVideoMemorySize = (ULONG)DISPLAY_MEMORY_SIZE;
+PUCHAR HalpVideoMemoryBase = (PUCHAR)NULL;
+
+//
+// Define static data.
+//
+
+static ULONG PowerizedGraphicsDisplayMode = 0; // default 640x480
+static PVOID HalpVideoConfigBase = NULL;
+static BOOLEAN HalpDisplayOwnedByHal = FALSE; // make sure is false: [breeze:1/27/95]
+static PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+static PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+static PHALP_OUTPUT_CHARACTER HalpOutputCharacter = NULL;
+static PHALP_SCROLL_SCREEN HalpScrollScreen = NULL;
+
+//
+// Define OEM font variables.
+//
+
+USHORT HalpBytesPerRow;
+USHORT HalpCharacterHeight;
+USHORT HalpCharacterWidth;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+ULONG HalpColumn;
+ULONG HalpRow;
+USHORT HalpHorizontalResolution;
+USHORT HalpVerticalResolution;
+USHORT HalpScreenStart = 0; // for cirrus
+
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+POEM_FONT_FILE_HEADER HalpFontHeader;
+
+extern ULONG HalpEnableInt10Calls;
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define DISPLAY_CLASS 0x03
+
+/*----------------------------------------------------------------------------*/
+#if DBG
+static VOID
+Trace(PCHAR Format, ...)
+
+{
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Length;
+ if (HalpDebugValue & DBG_DISPLAY) {
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+ DbgPrint(Buffer);
+ }
+}
+#endif
+/*----------------------------------------------------------------------------*/
+#define SEQ_CLKMODE_INDEX 0x01
+#define SEQ_MISC_INDEX 0x11
+#define SEQ_OUTPUT_CTL_INDEX 0x12 /* Vendor specific */
+
+VOID ScreenOn(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte & 0xdf;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+VOID ScreenOff(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte | 0x20;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define CRYSTAL_FREQUENCY (14318180 * 2)
+#define MIN_VCO_FREQUENCY 50000000
+#define MAX_NUMERATOR 130
+#define MAX_DENOMINATOR MIN(129, CRYSTAL_FREQUENCY / 400000)
+#define MIN_DENOMINATOR MAX(3, CRYSTAL_FREQUENCY / 2000000)
+
+#define CLOCK(x) WRITE_S3_UCHAR(MiscOutW, (UCHAR)(iotemp | (x)))
+#define C_DATA 0x0c
+#define C_CLK 0x04
+#define C_BOTH 0x08
+#define C_NONE 0x00
+
+long vclk_range[16] = {
+ 0, // should be MIN_VCO_FREQUENCY, but that causes problems.
+ 51000000,
+ 53200000,
+ 58500000,
+ 60700000,
+ 64400000,
+ 66800000,
+ 73500000,
+ 75600000,
+ 80900000,
+ 83200000,
+ 91500000,
+ 100000000,
+ 120000000,
+ 285000000,
+ 0,
+};
+/******************************************************************************
+ * Number theoretic function - GCD (Greatest Common Divisor)
+ *****************************************************************************/
+static long gcd(a, b)
+register long a, b;
+{
+ register long c = a % b;
+ while (c)
+ a = b, b = c, c = a % b;
+ return b;
+}
+/****************************************************************************
+ * calc_clock
+ *
+ * Usage: clock frequency [set]
+ * frequency is specified in MHz
+ *
+ ***************************************************************************/
+static long calc_clock(frequency, select)
+
+register long frequency; /* in Hz */
+int select;
+{
+ register long index;
+ long temp;
+ long min_m, min_n, min_diff;
+ long diff;
+
+ int clock_m;
+ int clock_n;
+ int clock_p;
+
+ min_diff = 0xFFFFFFF;
+ min_n = 1;
+ min_m = 1;
+
+ /* Calculate 18 bit clock value */
+
+ clock_p = 0;
+ if (frequency < MIN_VCO_FREQUENCY)
+ clock_p = 1;
+ if (frequency < MIN_VCO_FREQUENCY / 2)
+ clock_p = 2;
+ if (frequency < MIN_VCO_FREQUENCY / 4)
+ clock_p = 3;
+
+ frequency <<= clock_p;
+
+ for (clock_n = 4; clock_n <= MAX_NUMERATOR; clock_n++)
+ {
+ index = CRYSTAL_FREQUENCY / (frequency / clock_n);
+
+ if (index > MAX_DENOMINATOR)
+ index = MAX_DENOMINATOR;
+ if (index < MIN_DENOMINATOR)
+ index = MIN_DENOMINATOR;
+
+ for (clock_m = index - 3; clock_m < index + 4; clock_m++)
+ if (clock_m >= MIN_DENOMINATOR && clock_m <= MAX_DENOMINATOR)
+ {
+ diff = (CRYSTAL_FREQUENCY / clock_m) * clock_n - frequency;
+
+ if (diff < 0)
+ diff = -diff;
+
+ if (min_m * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_m &&
+ min_n * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_n)
+
+ if (diff > min_diff)
+ diff = min_diff;
+
+ if (diff <= min_diff)
+ {
+ min_diff = diff;
+ min_m = clock_m;
+ min_n = clock_n;
+ }
+ }
+ }
+
+ clock_m = min_m;
+ clock_n = min_n;
+
+ /* Calculate the index */
+
+ temp = (((CRYSTAL_FREQUENCY / 2) * clock_n) / clock_m) << 1;
+ for (index = 0; vclk_range[index + 1] < temp && index < 15; index++)
+ ;
+
+ /* Pack the clock value for the frequency snthesizer */
+
+ temp = (((long)clock_n - 3) << 11) + ((clock_m - 2) << 1)
+ + (clock_p << 8) + (index << 18) + ((long)select << 22);
+
+ return temp;
+
+}
+static VOID SetICD2061AClock(LONG clock_value) /* 7bits M, 7bits N, 2bits P */
+{
+ register long index;
+ register char iotemp;
+ int select;
+
+ select = (clock_value >> 22) & 3;
+
+ /* Shut off screen */
+ ScreenOff();
+
+ iotemp = READ_S3_UCHAR(MiscOutR);
+
+ /* Program the IC Designs 2061A frequency generator */
+
+ CLOCK(C_NONE);
+
+ /* Unlock sequence */
+
+ CLOCK(C_DATA);
+ for (index = 0; index < 6; index++)
+ {
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ }
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+
+ /* Program the 24 bit value into REG0 */
+
+ for (index = 0; index < 24; index++)
+ {
+ /* Clock in the next bit */
+ clock_value >>= 1;
+ if (clock_value & 1)
+ {
+ CLOCK(C_CLK);
+ CLOCK(C_NONE);
+ CLOCK(C_DATA);
+ CLOCK(C_BOTH);
+ }
+ else
+ {
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+ }
+ }
+
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ CLOCK(C_BOTH);
+
+ /* If necessary, reprogram other ICD2061A registers to defaults */
+
+ /* Select the CLOCK in the frequency synthesizer */
+
+ TRACE("select=%d\n", select);
+ CLOCK(C_NONE | select);
+
+ /* Turn screen back on */
+ ScreenOn();
+}
+
+static VOID EnableMemoryAndIO(PCI_CONFIG configBase)
+{
+ USHORT Cmd;
+ // Enable Memory & I/O spaces in command register. Firmware does not always set this.
+ Cmd = READ_REGISTER_USHORT(&configBase->Command);
+ //TRACE("Cmd=0x%x->", Cmd);
+ Cmd = Cmd | 3;
+ //TRACE("0x%x\n", Cmd);
+ WRITE_REGISTER_USHORT(&configBase->Command, Cmd);
+}
+
+static VOID MakeP9100VGA(PVOID pConfigBase)
+{
+ UCHAR DataByte;
+
+ //TRACE("MakeP9100VGA: starting\n");
+ /* Disable the P9000 and enable VGA.*/
+ /* unlocking the 5186/5286 registers */
+ WRITE_S3_UCHAR(Seq_Index, SEQ_MISC_INDEX);
+ DataByte = READ_S3_UCHAR(Seq_Data); /* Read misc register */
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+ WRITE_S3_UCHAR(Seq_Data, DataByte); /* Write back twice */
+ DataByte = READ_S3_UCHAR(Seq_Data); /* Read misc register again */
+ WRITE_S3_UCHAR(Seq_Data, DataByte & ~0x20); /* Clear bit 5 */
+
+ DataByte = READ_REGISTER_UCHAR(((PCHAR)pConfigBase)+65);
+ TRACE("HalpVideoConfigBase+65 DataByte=0x%02x->", DataByte);
+ DataByte = DataByte | 0x0e; // bit 1 VGA emulation
+ DataByte = 0xe2;
+ WRITE_REGISTER_UCHAR(((PCHAR)pConfigBase)+65, DataByte); // this makes display blank
+ DataByte = READ_REGISTER_UCHAR(((PCHAR)pConfigBase)+65);
+ TRACE("0x%02x\n", DataByte);
+
+ {
+ ULONG ul;
+ ULONG clock_numbers;
+
+ ul = 25175000;
+ clock_numbers = calc_clock(ul, 2);
+ SetICD2061AClock(clock_numbers);
+ }
+}
+
+static BOOLEAN
+WorkAroundBeforeInitBIOS()
+{
+ USHORT vendorID = 0;
+ USHORT deviceID = 0;
+ UCHAR revisionID = 0;
+ UCHAR Class;
+ UCHAR SubClass;
+ int i;
+ BOOLEAN Found = FALSE;
+
+ for (i = 1 /* skip SIO */; ((i < MAXIMUM_PCI_SLOTS) && (Found == FALSE)); i++) {
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[i]);
+
+ Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
+ if ((Class == DISPLAY_CLASS && (SubClass == 0)) ||
+ (Class == 0x00 && SubClass == 0x01)) { // pre-rev 2.0 display card
+
+ vendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ deviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
+ revisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
+ TRACE("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", vendorID, deviceID, revisionID);
+
+ if ((vendorID == PCI_VENDOR_ID_WEITEK) && (deviceID == PCI_DEVICE_ID_WEITEK_P9100)) { //viper Pro
+ EnableMemoryAndIO(HalpVideoConfigBase);
+ MakeP9100VGA(HalpVideoConfigBase); // let BIOS initialize chip
+ }
+ }
+ }
+ return Found;
+}
+
+/* firmware gives 'VGA' even when S3 card is in. */
+static BOOLEAN
+WorkAroundAfterInitBIOS()
+{
+ USHORT vendorID = 0;
+ USHORT deviceID = 0;
+ UCHAR revisionID = 0;
+ UCHAR Class;
+ UCHAR SubClass;
+ int i;
+ BOOLEAN Found = FALSE;
+
+ TRACE("WorkAroundAfterInitBIOS starting.\n");
+
+ for (i = 1; ((i < MAXIMUM_PCI_SLOTS) && (Found == FALSE)); i++) {
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[i]);
+
+ Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
+ TRACE("ClassID=0x%02x SubClass=0x%02x\n", Class, SubClass);
+
+ if ((Class == DISPLAY_CLASS && (SubClass == 0)) ||
+ (Class == 0x00 && SubClass == 0x01)) { // pre-rev 2.0 display card
+
+ vendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ deviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
+ revisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
+ TRACE("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", vendorID, deviceID, revisionID);
+
+ if (vendorID == PCI_VENDOR_ID_S3) {
+ EnableMemoryAndIO(HalpVideoConfigBase);
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterS3;
+ HalpScrollScreen = HalpScrollS3;
+ Found = TRUE;
+ }
+ }
+ }
+ return Found;
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpInitializeDisplay ()
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+ Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+ --*/
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ BOOLEAN Found = FALSE;
+ CHAR buf[BUFSIZ];
+ BOOLEAN bUseVGA = TRUE; // TRUE: scan SVGA cards. FALSE: ignore SVGA cards.
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // For the Weitek P9000, set the address of the font file header.
+ // Display variables are computed later in HalpDisplayPpcP9Setup.
+ //
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+
+ //
+ // Read the Registry entry to find out which video adapter the system
+ // is configured for. This code depends on the OSLoader to put the
+ // correct value in the Registry.
+ //
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (NULL == ConfigurationEntry) {
+ TRACE("ConfigurationEntry is NULL.\n");
+ return FALSE;
+ }
+
+ if (HalGetEnvironmentVariable("DISPLAY", sizeof(buf), buf) == ESUCCESS) {
+ TRACE("DISPLAY='%s'\n", buf);
+ bUseVGA = FALSE;
+ }
+ TRACE("HalpInitializeDisplay: ConfigurationEntry->ComponentEntry.Identifier='%s'\n", ConfigurationEntry->ComponentEntry.Identifier);
+
+ while ((TRUE == bUseVGA) && (FALSE == Found)) {
+ Found = WorkAroundBeforeInitBIOS();
+ if (TRUE == Found) break;
+
+ //
+ // Don't look for a PCI video adapter if the environment
+ // variable "DISPLAY" is defined.
+ //
+ if (HalpPciConfigBase) {
+ TRACE("HalpIoMemoryBase = 0x%08x\n", HalpIoMemoryBase);
+ TRACE("HalpPciConfigBase = 0x%08x\n", HalpPciConfigBase);
+ TRACE("HalpIoControlBase = 0x%08x\n", HalpIoControlBase);
+
+ if (HalpInitializeX86DisplayAdapter(LoaderBlock)) {
+ TRACE("HalpInitializeX86DisplayAdapter() succeeded.\n");
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterINT10;
+ HalpScrollScreen = HalpScrollINT10;
+ Found = TRUE;
+ } else {
+ TRACE("HalpInitializeX86DisplayAdapter() failed.\n");
+ }
+ }
+ if (TRUE == Found) break;
+
+ Found = WorkAroundAfterInitBIOS();
+ if (TRUE == Found) break;
+
+ if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP91;
+ Found = TRUE;
+ } else if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"S3")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterS3;
+ HalpScrollScreen = HalpScrollS3;
+ Found = TRUE;
+ } else {
+ // Unsupported VGA display identifier or probably Powerized Graphics.
+ bUseVGA = FALSE;
+ }
+ } /* while */
+
+ while (FALSE == Found) {
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"Powerized Graphics")) {
+ HalpDisplayControllerSetup = HalpDisplayPowerizedGraphicsSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterPowerizedGraphics;
+ //
+ // Set mode 15 which is 1024x768 60 Hz
+ //
+ PowerizedGraphicsDisplayMode = 15;
+ if (HalGetEnvironmentVariable("DISPLAY", sizeof(buf), buf) == ESUCCESS) {
+ if (!_stricmp(buf, "VGA")) {
+ //
+ // Just in case someone wants mode 0 (VGA)
+ //
+ PowerizedGraphicsDisplayMode = 0;
+ }
+ }
+ Found = TRUE;
+ } else if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"VGA")) {
+ //
+ // This is where the INT10 could go if the firmware were
+ // to be trusted.
+ // Just put the framebuffer in VGA mode for now.
+ //
+ HalpDisplayControllerSetup = HalpDisplayPowerizedGraphicsSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterPowerizedGraphics;
+ //
+ // Set mode 0 which is 640x480 60 Hz
+ //
+ PowerizedGraphicsDisplayMode = 0;
+ Found = TRUE;
+ } else {
+ HalDisplayString("can't happen\n");
+ return FALSE;
+ }
+ }
+ //===========end=IBMLAN===============================================
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+ return HalpDisplayControllerSetup();
+ }
+
+ return FALSE;
+}
+
+
+/*++
+
+ Routine Description: VOID HalAcquireDisplayOwnership ()
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+
+/*++
+
+ Routine Description: VOID HalDisplayString ()
+
+ This routine displays a character string on the display screen.
+
+ Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, flush the TB, and map the display
+ // frame buffer into the address space of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+ }
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+ KeLowerIrql(OldIrql);
+ return;
+
+} /* end of HalpDisplayString() */
+
+
+/*++
+
+ Routine Description: VOID HalQueryDisplayParameters ()
+
+ This routine return information about the display area and current
+ cursor position.
+
+ Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ *WidthInCharacters = HalpDisplayWidth; //IBMLAN
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+ return;
+}
+
+
+/*++
+
+ Routine Description: VOID HalSetDisplayParameters ()
+
+ This routine set the current cursor position on the display area.
+
+ Arguments:
+
+ CursorColumn - Supplies the new display column position.
+ CursorRow - Supplies a the new display row position.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ if (CursorColumn > HalpDisplayWidth) { //IBMLAN
+ CursorColumn = HalpDisplayWidth; //IBMLAN
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+ return;
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpDisplaySetupVgaViaBios ()
+
+ This routine initializes a vga controller via bios reset.
+ Arguments:
+ None.
+ Return Value:
+ None.
+
+ --*/
+
+BOOLEAN
+HalpDisplaySetupVgaViaBios (
+ VOID
+ )
+{
+ //
+ // Routine Description:
+ //
+ //
+
+ ULONG DataLong;
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Set screen into blue
+ //
+
+ for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, 0x20);
+ WRITE_S3_VRAM(DataLong+1, 0x1F);
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+}
+
+VOID
+WaitForVSync (VOID)
+{
+ UCHAR DataByte;
+ BOOLEAN test;
+
+ //
+ // Determine 3Dx or 3Bx
+ //
+
+ DataByte = READ_S3_UCHAR(MiscOutR);
+ ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+
+ // Unlock S3 ( S3R8 )
+ // UnLockS3();
+
+ //
+ // Test Chip ID = '81h' ?
+ //
+
+ // For standard VGA text mode this action is not necessary.
+ // WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ // if ((DataByte = READ_S3_UCHAR(S3_3D5_Data)) == 0x81) {
+ //
+ // Wait For Verttical Retrace
+ //
+
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x08 ? FALSE : TRUE;
+ }
+
+ // Wait for H/V blanking
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x01 ? TRUE : FALSE;
+ }
+ // }
+
+ // Lock S3 ( S3R8 )
+ // LockS3();
+
+ return;
+} /* end of WaitForVsync() */
+
+VOID
+Scroll_Screen(IN UCHAR line)
+{
+ UCHAR i, DataByte;
+ ULONG target;
+
+ for (i = 0; i < line; i ++) {
+ //=======================================================================
+ //
+ // IBMBJB added wait for vertical sync to make scroll smooth
+
+ WaitForVSync();
+
+ //=======================================================================
+
+ for (target = 0xB8000; target < 0xB8F00; target += 2) {
+ DataByte = READ_S3_VRAM(target+0xA0);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+ for (target = 0xB8F00; target < 0xB8FA0; target += 2) {
+ WRITE_S3_VRAM(target, 0x20 );
+ }
+ }
+}
+
+
+/*++
+ Routine Description: VOID HalpDisplayCharacterVgaViaBios ()
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpDisplayCharacterVgaViaBios (
+ IN UCHAR Character
+ )
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ Scroll_Screen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterVgaViaBios(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+ HalpOutputCharacterVgaViaBios(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+}
+
+/*++
+
+ Routine Description: VOID HalpOutputCharacterVgaViaBios ()
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpOutputCharacterVgaViaBios (
+ IN UCHAR AsciiChar
+ )
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < 80) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+}
+
+/*************************************************************************/
+/* Following code (to EOF) added for PowerPro HAL Display Support [ged]. */
+/*************************************************************************/
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ PVOID fontheader;
+
+ // Use font file from OS Loader
+ //
+ // During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from
+ // the OS Loader heap into pool.
+ //
+
+ fontheader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize );
+ if(fontheader == NULL ) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(fontheader, HalpFontHeader, HalpFontHeader->FileSize );
+ HalpFontHeader = (POEM_FONT_FILE_HEADER) fontheader;
+
+ return TRUE;
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpDisplayPowerizedGraphicsSetup ()
+
+ This routine initializes the FirePower 'Powerized Graphics' frame buffer.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+ --*/
+
+BOOLEAN
+HalpDisplayPowerizedGraphicsSetup (
+ VOID
+ )
+{
+ PULONG buffer;
+ ULONG limit, index;
+ static ULONG vramWidth; // mogawa BUG3449
+ static BOOLEAN onetime = TRUE;
+
+
+ /* NOTE: The following line remaps the virtual to physical mapping */
+ /* of DBAT3 to the physical address of PowerPro's frame */
+ /* buffer. This overrides the Kernel's mapping to PCI memory. */
+ /* If Motorola changes this, we need to revisit it! [ged] */
+ /* NOTE2: For speed, we may want to make this region cacheable. */
+
+ // Moved dbat mapping to init routines to remove it from normal code
+ // path [breeze-7.15.94]
+ //
+ // Moved mapping back here so various adapters can be supported,
+ // without getting the frame buffer init'd in the mainline init.
+ // [rlanser-02.06.95]
+
+
+ if (onetime) {
+
+ onetime = FALSE;
+
+ HalpVideoMemoryBase =
+ HalpInitializeVRAM( (PVOID)DISPLAY_MEMORY_BASE, &HalpVideoMemorySize, &vramWidth);
+
+ //
+ // Set FrameBuffer Control Register
+ //
+ // Use a mask value of 7
+ //
+
+ {
+ ULONG ul = rFbControl;
+ ul &= ~0x07000000;
+ ul |= 0x07000000 & (vramWidth ? 0x0 : 0x03000000);
+ rFbControl = ul;
+ FireSyncRegister();
+ }
+
+ if (!HalpVideoMemoryBase) {
+ HalpDebugPrint("HalpVideoMemoryBase did not map...%x,%x\n",
+ HalpVideoMemoryBase,HalpVideoMemorySize);
+ HDBG(DBG_BREAK, DbgBreakPoint(););
+ return FALSE;
+ }
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpVideoMemoryBase is: 0x%x\n",
+ HalpVideoMemoryBase););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpIoControlBase = 0x%x\n",
+ HalpIoControlBase););
+ }
+
+ if (15 == PowerizedGraphicsDisplayMode) {
+ HalpSetupDCC(15, vramWidth); // mode 15 - 1024x768 8 bit 60Hz
+ HalpHorizontalResolution = 1024;
+ HalpVerticalResolution = 768;
+ } else {
+ HalpSetupDCC(0, vramWidth); // mode 0 - 640x480 8 bit 60Hz
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+ }
+
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+ //
+ // Since we use a cached Video Controler sweep the video memory
+ // range.
+ //
+ HalSweepDcacheRange(HalpVideoMemoryBase, HalpVideoMemorySize);
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+
+} /* HalpDisplayPowerizedGraphicsSetup */
+
+
+/*++
+
+ Routine Description: VOID HalpDisplayCharacterPowerizedGraphics ()
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend beyond the end of line, they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpDisplayCharacterPowerizedGraphics (
+ IN UCHAR Character
+ )
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)PRO_VIDEO_MEMORY_BASE,
+ // (PVOID)(PRO_VIDEO_MEMORY_BASE + HalpScrollLine),
+ // HalpScrollLength);
+
+ // Scroll up one line
+ Destination = HalpVideoMemoryBase;
+ Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpVideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+ } else if( Character == '\t' ) { // tab?
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ // tab beyond end of screen?
+ if (HalpColumn >= HalpDisplayWidth) {
+ // next tab stop is 1st column of next line
+ HalpColumn = 0;
+
+ if( HalpRow >= (HalpDisplayText - 1) ) {
+ HalpDisplayCharacterPowerizedGraphics('\n');
+ } else {
+ HalpRow++;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn--;
+ HalpDisplayCharacterPowerizedGraphics(' ');
+ HalpColumn--;
+ }
+
+ } else if (Character >= 0x20) {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterPowerizedGraphics((PUCHAR)HalpFontHeader + \
+ HalpFontHeader->Map[Character].Offset);
+ } /* else skip the nonprintable character */
+
+ return;
+} /* HalpDisplayCharacterPowerizedGraphics */
+
+
+
+/*++
+
+ Routine Description: VOID HalpOutputCharacterPowerizedGraphics()
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpOutputCharacterPowerizedGraphics(
+ IN PUCHAR Glyph
+ )
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpDisplayCharacterPowerizedGraphics('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0) {
+ *Destination = 0xFF; //Make this pixel white
+ } else {
+ *Destination = 0x01; //Make this pixel blue
+ }
+ HalSweepDcacheRange(Destination, 1); // Push it out
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+
+ return;
+
+} /* HalpOutputCharacterPowerizedGraphics */
+
+
+///
+/// Debug
+///
+
+VOID
+HalpDebugPrint(
+
+ PCHAR Format,
+ ...
+ )
+
+{
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Length;
+
+ //
+ // Format the output into a buffer and then print it.
+ //
+
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+ if (HalpDisplayOwnedByHal) {
+ HalDisplayString(Buffer);
+ }
+ DbgPrint(Buffer);
+}
+
+VOID
+HalpForceDisplay(
+ PCHAR Format,
+ ...
+ )
+{
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Length;
+
+ //
+ // Format the output into a buffer and then display it.
+ //
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+ HalDisplayString(Buffer);
+}
+
+/*-----------------------------------------------------------------------------------------*/
+VOID
+HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ )
+
+/*++
+ Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollScreen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacter(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+ HalpOutputCharacter(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 2 << 8; // AH = 2
+ Ebx = 0; // BH = page number
+ Edx = (HalpRow << 8) + HalpColumn;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
+ Ebx = 0;
+ Ecx = 1;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ HalpColumn += 1;
+
+}
+
+
+VOID HalpScrollINT10 (
+ IN UCHAR LinesToScroll)
+
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 6 << 8; // AH = 6 (scroll up)
+ Eax |= LinesToScroll; // AL = lines to scroll
+ Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
+ Ecx = 0; // CH,CL = upper left
+ Edx = (24 << 8) + 79; // DH,DL = lower right
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+BOOLEAN HalpDisplayINT10Setup (VOID)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ //
+ // Set cursor to (0,0)
+ //
+ Eax = 0x02 << 8; // AH = 2
+ Ebx = 0; // BH = page Number
+ Edx = 0; // DH = row DL = column
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Make screen white on blue by scrolling entire screen
+ //
+ Eax = 0x06 << 8; // AH = 6 AL = 0
+ Ebx = TEXT_ATTR << 8; // BH = attribute
+ Ecx = 0; // (x,y) upper left
+ Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
+ Edx += HalpScrollLine/2;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ return TRUE;
+}
+/*------------------------------------------------------------------------*/
+
+BOOLEAN
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ This routine initializes the S3 display controller chip.
+ Arguments:
+ None.
+ Return Value:
+ TRUE if finished successfully
+
+ --*/
+{
+//
+// Routine Description:
+//
+// This is the initialization routine for S3 86C911. This routine initializes
+// the S3 86C911 chip in the sequence of VGA BIOS for AT.
+//
+ ULONG DataLong;
+ USHORT i,j;
+ UCHAR DataByte;
+ UCHAR Index;
+// PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+
+
+ if (HalpVideoMemoryBase == NULL) {
+ TRACE("HalpDisplayPpcS3Setup: calling KePhase0MapIo(S3_VIDEO_MEMORY_BASE,0x400000).\n");
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ // Enable Video Subsystem
+ // Accordint to chapter 5.4.2 regular VGA setup sequence
+ TRACE("HalpDisplayPpcS3Setup: starting.\n");
+
+ //=========================================================================
+ //
+ // IBMBJB changed from writing 0x10 and then 0x08 to writing 0x18
+ // because the second write will wipe out the first one, the
+ // second write was originally done after the write to Setup_OP
+ //
+ // WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
+ // WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
+
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x18);
+
+ //=========================================================================
+
+ TRACE(" Subsystem Enable = 0x10...\n");
+ WRITE_S3_UCHAR(Setup_OP, 0x01);
+
+
+ WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ WRITE_S3_UCHAR(Seq_Data, 0x21);
+
+ //=========================================================================
+ //
+ // IBMBJB removed this section because it is not currently used, this
+ // was left commented out instead of deleting it in case we use
+ // a monochrome monitor in the future
+ //
+ // // Check monitor type to decide index address (currently not use)
+ // DataByte = READ_S3_UCHAR(MiscOutR);
+ // ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+ //
+ // if (ColorMonitor) {
+ // Index_3x4 = (PVOID)S3_3D4_Index;
+ // Data_3x5 = (PVOID)S3_3D5_Data;
+ // } else {
+ // Index_3x4 = (PVOID)Mono_3B4;
+ // Data_3x5 = (PVOID)Mono_3B5;
+ // }
+ //
+ //=========================================================================
+
+ //
+ // -- Initialization Process Begin --
+ // According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
+ // to set the default values to VGA +3 mode.
+ //
+ WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // For ATI card(0x63) we may want to change the frequence
+ WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // Sequencer Register
+ for (Index = 1; Index < 5; Index++) {
+ WRITE_S3_UCHAR(Seq_Index, Index);
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
+ }
+
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+ WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte = DataByte & 0x7f;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // CRTC controller CR0 - CR18
+ for (Index = 0; Index < 25; Index++) {
+ WRITE_S3_UCHAR(S3_3D4_Index, Index);
+ WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
+ }
+
+ // attribute write
+ // program palettes and mode register
+ TRACE(" Program palettes ...\n");
+ for (Index = 0; Index < 21; Index++) {
+ WaitForVSync();
+
+ DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
+ WRITE_S3_UCHAR(Attr_Index,Index);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
+ }
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ // graphics controller
+ TRACE(" Graphics controller...\n");
+ for (Index = 0; Index < 9; Index++) {
+ WRITE_S3_UCHAR(GC_Index, Index);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
+ }
+
+ // turn off the text mode cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
+
+ // Unlock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
+
+ // Unlock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
+
+ // Disable enhanced mode
+ WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
+
+ // Turn off H/W Graphic Cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, SC5);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ //=========================================================================
+ //
+ // IBMBJB S3 errata sheet says that CR40 can not be read correctly after
+ // power up until it has been written to, suggested workaround is
+ // to use the power on default (0xA4) Since the intent of the
+ // existing code was to reset bit 0, 0xA4 will be used to reset
+ // the bit. The other bits that are reset select the desired
+ // default configuration.
+ //
+ // If this register is written by the firmware then this fix is
+ // unneccessary. If future modifications of the firmware were to
+ // remove all writes to this register then this fix would have to
+ // be added here. This is being added now to protect this code
+ // from possible firmware changes.
+ //
+ // // Disable enhanced mode registers access
+ // WRITE_S3_UCHAR(S3_3D4_Index, SC0);
+ // DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ // DataByte &= 0xfe;
+ // DataByte ^= 0x0;
+ //
+ // WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+ //
+
+ WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
+
+ //=========================================================================
+
+ // Set Misc 1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xc7;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0x80;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R2 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Set S3R4 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xec;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ //=========================================================================
+ //
+ // IBMBJB added this section to eliminate the DAC hardware cursor, this
+ // is done before setting registers 0x50 - 0x62 to default states
+ // so that R55's default state will not be undone.
+ //
+ // this sequence zeros the 2 least signifigant bits in command
+ // register 2 on the DAC
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
+ DataByte = READ_S3_UCHAR( S3_3D5_Data );
+ DataByte &= 0xfc;
+ DataByte |= 0x02;
+ WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
+
+ DataByte = READ_S3_UCHAR( DAC_Data );
+ DataByte &= 0xfc; // zero CR21,20 in DAC command
+ WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
+
+ //=========================================================================
+ //
+ // IBMBJB Added code to configure for 18 bit color mode and reload the
+ // palette registers because the firmware configures for 24 bit
+ // color. If this is done when the system driver initializes for
+ // graphics mode then the text mode colors can not be changed
+ // properly.
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
+
+ DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
+ DataByte &= 0xfd; // register 0 to select 6 bit
+ WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
+
+ // IBMBJB added write to SDAC PLL control register to make sure CLK0
+ // is correct if we have to reinitialize after graphics mode
+ // initialization, this does not bother the 928/Bt485 card
+ // because the Bt485 DAC looks very much like the SDAC
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
+ WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
+
+ for( i = 0, j = 0; i < 256; ++i ) // load all color registers
+ {
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
+ // state because some of them are set by the firmware and are
+ // not correct for our use
+ //
+ // NOTE: there are some writes to the DAC registers in code that
+ // executes later that depend on R55[1:0] being 00B, if the
+ // default state of R55 is changed make sure that these bits
+ // are not changed
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ // IBMBJB changed value written from 0 to 1 for an S3 864 based card to
+ // clear up bad display caused by 864->SDAC FIFO underrun
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ //=========================================================================
+ //
+ // IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
+ // transfer problem in parallel and continuous addressing modes
+ // Note: side effect of setting bit 7 was a garbled firmware screen after
+ // shutdown.
+
+ // Set SR65 bits 7 and 6
+ WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte |= 0x40;
+// DataByte |= 0xc0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Lock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Lock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+ TRACE(" Load Fonts into Plane2 ...\n");
+ WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
+
+ WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
+
+ WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data,0x00);
+
+ WRITE_S3_UCHAR(GC_Index,0x06);
+ WRITE_S3_UCHAR(GC_Data,0x04);
+
+ WRITE_S3_UCHAR(GC_Index,0x04);
+ WRITE_S3_UCHAR(GC_Data,0x02);
+
+ MemBase = 0xA0000;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 16; j++) {
+ WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
+ MemBase++;
+ }
+ // 32 bytes each character font
+ for (j = 16; j < 32; j++) {
+ WRITE_S3_VRAM(MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_S3_UCHAR(DAC_Mask, 0xff);
+
+ // select plane 0, 1
+ WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
+
+ // access to planes 0, 1.
+ WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x04);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x06);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
+
+ //
+ // Set screen into blue
+ //
+ TRACE(" Set Screen into Blue ...\n");
+ for (DataLong = 0xB8000;
+ DataLong < 0xB8000+TWENTY_FIVE_LINES;
+ DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, ' ');
+ WRITE_S3_VRAM(DataLong+1, TEXT_ATTR);
+ }
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+} /* end of HalpDisplayPpcS3Setup() */
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ )
+
+/*++
+
+ Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < 80) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+} /* end of HalpOutputCharacterS3() */
+
+
+
+VOID
+HalpScrollS3(IN UCHAR line)
+{
+ UCHAR i, DataByte;
+ ULONG target;
+
+ for (i = 0; i < line; i ++) {
+ //=======================================================================
+ //
+ // IBMBJB added wait for vertical sync to make scroll smooth
+
+ WaitForVSync();
+
+ //=======================================================================
+
+ for (target = 0xB8000;
+ target < 0xB8000+TWENTY_FOUR_LINES;
+ target += 2) {
+ DataByte = READ_S3_VRAM(target+ONE_LINE);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+ for (target = 0xB8000+TWENTY_FOUR_LINES;
+ target < 0xB8000+TWENTY_FIVE_LINES;
+ target += 2) {
+ WRITE_S3_VRAM(target, ' ' );
+ }
+ }
+}
+/*------------------------------------------------------------------------*/
+static PUCHAR HalpP91VideoMemoryBase = (PUCHAR)0;
+
+BOOLEAN
+HalpDisplayPpcP91Setup (
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine initializes the Weitek P9100 display contoller chip.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+ --*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ TRACE("HalpDisplayPpcP91Setup: starting...\n");
+ // For now I'll leave the P9100 in the same state that the firmware
+ // left it in. This should be 640x480.
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ if (HalpP91VideoMemoryBase == NULL) {
+
+ HalpP91VideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)P91_VIDEO_MEMORY_BASE,
+ 0x800000); // 8 MB
+ }
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+ //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ //HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpP91VideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ limit = 0x100000/sizeof(ULONG); // mogawa
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return TRUE;
+
+} //end of HalpDisplayPpcP91Setup
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ )
+/*++
+
+ Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ UCHAR DataByte;
+ DataByte = READ_REGISTER_UCHAR(((PCHAR)HalpVideoConfigBase)+65);
+ TRACE("Config[65]=0x%02x\n", DataByte);
+
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P91_VIDEO_MEMORY_BASE,
+ // (PVOID)(P91_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // Scroll up one line
+ Destination = HalpP91VideoMemoryBase;
+ Source = (PUCHAR) HalpP91VideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpP91VideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP91((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+ Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ //ULONG tmp;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacterP91('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpP91VideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0) {
+ *Destination = 0xFF; //Make this pixel white
+ HalSweepDcacheRange(Destination, 1); // Push it out
+ }
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+BOOLEAN
+HalpDisplayPpcP91BlankScreen (
+ VOID
+ )
+{
+ PULONG buffer;
+ ULONG limit, index;
+
+ if (HalpP91VideoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ buffer = (PULONG)HalpP91VideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ limit = 0x100000/sizeof(ULONG); // mogawa
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x00000000;
+ }
+ return TRUE;
+}
+
+
+/*------------------------------------------------------------------------*/
+//
+// Cirrus Device Driver
+//
+
+// Routine Description:
+//
+// This routine displays a character at the current x and y positions in
+// the frame buffer. If a newline is encounter, then the frame buffer is
+// scrolled. If characters extend below the end of line, then they are not
+// displayed.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+
+VOID
+HalpDisplayCharacterCirrus (
+ IN UCHAR Character
+ )
+{
+
+//
+// If the character is a newline, then scroll the screen up, blank the
+// bottom line, and reset the x position.
+//
+
+ if (Character == '\n')
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+
+//
+// added tab processing
+//
+
+ else if ( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if ( HalpColumn >= COLS ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column
+ // of next line
+
+ if ( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollScreen( 1 );
+ else ++HalpRow;
+ }
+ }
+ else if (Character == '\r')
+ {
+ HalpColumn = 0;
+ }
+ else if (Character == 0x7f)
+ { // DEL character
+ if (HalpColumn != 0)
+ {
+ HalpColumn -= 1;
+ HalpOutputCharacterCirrus(0);
+ HalpColumn -= 1;
+ }
+ else // do nothing
+ ;
+ }
+ else if (Character >= 0x20)
+ {
+ // Auto wrap for 80 columns
+ // per line
+ if (HalpColumn >= COLS)
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+ HalpOutputCharacterCirrus(Character);
+ }
+ // skip the nonprintable character
+}
+
+
+//
+//
+// Routine Description:
+//
+// This routine insert a set of pixels into the display at the current x
+// cursor position. If the x cursor position is at the end of the line,
+// then no pixels are inserted in the display.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+
+
+VOID
+HalpOutputCharacterCirrus (
+ IN UCHAR AsciiChar
+ )
+{
+ PUCHAR Destination;
+ ULONG I;
+
+//
+// If the current x cursor position is within the current line, then insert
+// the specified pixels into the last line of the text area and update the
+// x cursor position.
+//
+
+ if (HalpColumn < COLS)
+ {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ Destination = (PUCHAR)(CIRRUS_TEXT_MEM + I + HalpScreenStart);
+ WRITE_CIRRUS_VRAM(Destination, AsciiChar);
+ HalpColumn += 1;
+ }
+}
+
+
+//
+// Routine Description:
+//
+// This routine initializes the Cirrus CL-GD5430 graphics controller chip
+//
+
+static void updattr(IN int rg,IN unsigned char val)
+{
+ inp(0x3da);
+ outportb(0x3c0,rg);
+ outportb(0x3c0,val);
+ outportb(0x3c0,((unsigned char)(rg | 0x20)));
+}
+
+
+static void set_ext_regs(IN int reg,IN unsigned char *p)
+{
+ unsigned char index, data;
+
+ while (*p != 0xff)
+ {
+ index= *p++;
+ data= *p++;
+ setreg(reg,index,data);
+ }
+}
+
+
+BOOLEAN
+HalpDisplayPpcCirrusSetup (
+ VOID
+ )
+{
+ int i;
+
+ //DbgBreakPoint();
+ TRACE("HalpDisplayPpcCirrusSetup: starting.\n");
+ if (HalpVideoMemoryBase == NULL) {
+ TRACE("HalpDisplayPpcCirrusSetup: calling KePhase0MapIo(CIRRUS_VIDEO_MEMORY_BASE,0x400000).\n");
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)CIRRUS_VIDEO_MEMORY_BASE, 0x400000); // 4 MB
+ } else {
+ TRACE("HalpVideoMemoryBase=0x%08x\n", HalpVideoMemoryBase);
+ }
+
+//
+// Assert synchronous reset while setting the clock mode
+//
+
+ setreg(0x3c4,0,1); // assert synchronous reset
+
+ outportb(0x3c2,0x67);
+
+ for ( i = 0; i < 21; i++ ) updattr(i,attr3[i]);
+
+ setreg(0x3d4,0x11,0x20);
+ for ( i = 0; i < 32; i++ ) setreg(0x3d4,i,crtc3[i]);
+
+ for ( i = 0x00;i < 9; i++ ) setreg(0x3ce,i,graph3[i]);
+
+ for ( i = 0; i < 5; i++ ) setreg(0x3c4,i,seq3[i]);
+
+ set_ext_regs (0x3c4,eseq3);
+ set_ext_regs (0x3d4,ecrtc3);
+ set_ext_regs (0x3ce,egraph3);
+ set_ext_regs (0x3c0,eattr3);
+
+//
+// Load 8x16 font
+//
+
+ load8x16();
+
+//
+// Load color palette
+//
+
+ load_ramdac();
+
+ outportb(0x3c6,0xff);
+
+//
+// Reset Hidden color register
+//
+
+// inp(0x3c6);
+// inp(0x3c6);
+// inp(0x3c6);
+// inp(0x3c6);
+// outp(0x3c6,0x00);
+
+//
+// Screen blank
+//
+
+ clear_text();
+
+//
+// Initialize the current display column, row, and ownership values.
+//
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayOwnedByHal = TRUE;
+ HalpScreenStart = 0;
+ return TRUE;
+}
+
+VOID HalpScrollCirrus(
+ IN UCHAR line
+ )
+{
+ ULONG LogicalTarget, PhysicalTarget;
+ int i;
+
+ for (i=0; i < line; i++) {
+
+ HalpScreenStart = HalpScreenStart + ONE_LINE;
+ setreg(0x3d4,0xC, (UCHAR) (HalpScreenStart >> 9));
+ setreg(0x3d4,0xD, (UCHAR) ((HalpScreenStart >> 1) & 0xFF));
+
+ for (LogicalTarget = TWENTY_FOUR_LINES;
+ LogicalTarget < TWENTY_FIVE_LINES;
+ LogicalTarget += 2) {
+ PhysicalTarget = LogicalTarget + HalpScreenStart + CIRRUS_TEXT_MEM;
+ WRITE_CIRRUS_VRAM(PhysicalTarget, ' ' );
+ WRITE_CIRRUS_VRAM(PhysicalTarget+1, TEXT_ATTR );
+ }
+ }
+}
+
+static void clear_text(VOID)
+{
+ unsigned long p;
+
+//
+// fill plane 0 and 1 with 0x20 and 0x1f
+//
+
+ for (p = CIRRUS_TEXT_MEM;
+ p < CIRRUS_TEXT_MEM+TWENTY_FIVE_LINES;
+ p += 2)
+ {
+ WRITE_CIRRUS_VRAM(p, ' ');
+ WRITE_CIRRUS_VRAM(p+1, TEXT_ATTR);
+ }
+}
+
+static void load8x16(VOID)
+{
+ int i, j;
+ PUCHAR address;
+
+//
+// load 8x16 font into plane 2
+//
+
+ setreg(0x3c4,0x04,(seq3[4] | 0x04));
+
+//
+// disable video and enable all to cpu to enable maximum video
+// memory access
+//
+
+ setreg(0x3c4,0x01,seq3[1] | 0x20);
+ setreg(0x3c4,2,4);
+
+ setreg(0x3ce,0x05,graph3[5] & 0xef);
+ setreg(0x3ce,0x06,0x05);
+
+
+//
+// fill plane 2 with 8x16 font
+
+ address = (void *) (CIRRUS_FONT_MEM);
+ for ( i = 0; i < 256; i++ )
+ {
+ for ( j = 0; j < 16; j++ )
+ {
+ WRITE_CIRRUS_VRAM(address,VGAFont8x16[i*16+j]);
+ address++;
+ }
+
+ for ( j = 16; j < 32; j++ )
+ {
+ WRITE_CIRRUS_VRAM(address,0);
+ address++;
+ }
+ }
+
+ setreg(0x3c4,0x01,seq3[1]);
+ setreg(0x3c4,0x04,seq3[4]);
+ setreg(0x3c4,2,seq3[2]);
+
+ setreg(0x3ce,0x06,graph3[6]);
+ setreg(0x3ce,0x05,graph3[5]);
+}
+
+
+static void load_ramdac()
+{
+ int ix,j;
+
+ for ( ix = 0,j = 0; j <= 0x0FF ; ix = ix+3,j++ )
+ {
+ outp(0x3c8,(unsigned char)j); // write ramdac index
+ outp(0x3c9,TextPalette[ix]); // write red
+ outp(0x3c9,TextPalette[ix+1]); // write green
+ outp(0x3c9,TextPalette[ix+2]); // write blue
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxenviro.c b/private/ntos/nthals/halfire/ppc/pxenviro.c
new file mode 100644
index 000000000..55c3677b3
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxenviro.c
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxenviro.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/05/18 00:28:50 $
+ * $Locker: $
+ */
+
+/***********************************************************************
+
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+ File Name:
+ PXENVIRO.C
+
+ Purpose:
+ Provides the interface to the PowerPC ARC firmware.
+
+ Globals:
+ none
+
+ Functions:
+ ULONG HalGetEnvironmentVariable();
+ ULONG HalSetEnvironmentVariable();
+
+ History:
+ 27-Jul-1993 Steve Johns
+ Original version
+ 31-Jan-1994 Steve Johns
+ Added checksum logic
+ 08-Jul-1994 Steve Johns
+ Made Environment variable routines PReP compliant
+ 12-20-94
+ Heavly re-written by Sol Kavy at FirePower to
+ clean-up the code and properly suppor the Prep spec.
+
+
+NOTES:
+
+ The fields in the NVRAM structure follow Big-Endian byte ordering.
+
+ Each environment variable is stored as an zero-terminated ASCII string:
+
+ <name>=<value>,0
+
+***********************************************************************/
+
+
+#define USE_SPINLOCKS FALSE
+
+#include "halp.h"
+//#include "fpdebug.h"
+#include "arccodes.h"
+#include "eisa.h"
+#include "pxnvrsup.h"
+#include "fpnvram.h"
+
+USHORT HalpComputeCrc(VOID);
+
+//
+// Debug Define (first paramter is a place holder for future
+// level handling: 1 = Calls, 2 = Routine Info).
+//
+#define NDBG(_lvl, _print)
+
+PKSPIN_LOCK NVRAM_Spinlock;
+
+#define NVSIZE 4096
+
+//
+// Location of the NVRAM registers
+//
+// #include "phsystem.h"
+// extern PVOID HalpIoControlBase;
+#define NVRAM ((PNVRAM_CONTROL) (HalpIoControlBase))
+// #define NVRAM ((PNVRAM_CONTROL) 0xb1000000)
+
+//
+// Dummy pointer used to byte get offset information
+//
+PVOID NvramPtr=0;
+#define NVMAP ((PHEADER) NvramPtr)
+
+extern BOOLEAN NvramFailure;
+
+//
+// Use the routine from fpds1385.c to access the nvram chip. These
+// routines protect their accesses with the appropriate spin locks
+// to make sure the actions are atomic
+//
+
+USHORT
+HalpReadNvramUshort(USHORT Index)
+{
+ return (HalpDS1385ReadNVRAM(Index) << 8) +
+ HalpDS1385ReadNVRAM((USHORT)(Index+1));
+}
+
+
+ULONG
+HalpReadNvramUlong(USHORT Index)
+{
+ ULONG ReturnValue;
+
+ //
+ // Read Big-Endian ULONG value & convert to Little-Endian
+ //
+ ReturnValue = ((ULONG) HalpReadNvramUshort(Index) << 16) +
+ (ULONG) HalpReadNvramUshort((USHORT)(Index+2));
+
+ return ReturnValue;
+}
+
+VOID
+HalpWriteNvramUshort(USHORT Index,
+ USHORT Value)
+{
+ //
+ // Write USHORT value in Big-Endian
+ //
+ HalpDS1385WriteNVRAM(Index, (UCHAR) (Value >> 8));
+ HalpDS1385WriteNVRAM((USHORT)(Index+1),(UCHAR) Value);
+}
+
+
+VOID HalpWriteNvramUlong(
+ USHORT Index,
+ ULONG Value)
+{
+ //
+ // Write ULONG value in Big-Endian
+ //
+ HalpWriteNvramUshort(Index, (USHORT) (Value >> 16));
+ HalpWriteNvramUshort((USHORT)(Index+2),(USHORT) Value);
+}
+
+//
+// DumpNVRAM
+//
+// Description:
+// Used during bring-up to ensure that NVRAM is being handled
+// correctly. Nothing more than a bunch of DbgPrint of NVRAM
+//
+VOID
+DumpNVRAM()
+{
+ DbgPrint("HalpIoControlBase is at 0x%x\n", HalpIoControlBase);
+ DbgPrint("NVRAM is at 0x%x\n", NVRAM);
+ DbgPrint("NvramIndexLo is at 0x%x\n", &(NVRAM->NvramIndexLo));
+ DbgPrint("NvramIndexHi is at 0x%x\n", &(NVRAM->NvramIndexHi));
+ DbgPrint("NvramData is at 0x%x\n", &(NVRAM->NvramData));
+ DbgPrint("NVRAM USHORT Size(%d): %d\n",
+ (USHORT)&NVMAP->Size,
+ HalpReadNvramUshort((USHORT)&NVMAP->Size));
+ DbgPrint("NVRAM UCHAR Version(%d): %d\n",
+ (USHORT)&NVMAP->Version,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->Version));
+ DbgPrint("NVRAM UCHAR Revision(%d): %d\n",
+ (USHORT)&NVMAP->Revision,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->Revision));
+ DbgPrint("NVRAM USHORT Crc1(%d): 0x%x\n",
+ (USHORT)&NVMAP->Crc1,
+ HalpReadNvramUshort((USHORT)&NVMAP->Crc1));
+ DbgPrint("NVRAM USHORT Crc2(%d): 0x%x\n",
+ (USHORT)&NVMAP->Crc2,
+ HalpReadNvramUshort((USHORT)&NVMAP->Crc2));
+ DbgPrint("NVRAM UCHAR LastOS(%d): %d\n",
+ (USHORT)&NVMAP->LastOS,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->LastOS));
+ DbgPrint("NVRAM UCHAR Endian(%d): %d\n",
+ (USHORT)&NVMAP->Endian,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->Endian));
+ DbgPrint("NVRAM UCHAR OSAreaUsage(%d): %d\n",
+ (USHORT)&NVMAP->OSAreaUsage,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->OSAreaUsage));
+ DbgPrint("NVRAM UCHAR PMMode(%d): %d\n",
+ (USHORT)&NVMAP->PMMode,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->PMMode));
+ DbgPrint("NVRAM ULONG GEAddress(%d): %d\n",
+ (USHORT)&NVMAP->GEAddress,
+ HalpReadNvramUlong((USHORT)&NVMAP->GEAddress));
+ DbgPrint("NVRAM ULONG GELength(%d): %d\n",
+ (USHORT)&NVMAP->GELength,
+ HalpReadNvramUlong((USHORT)&NVMAP->GELength));
+ {
+ USHORT StartIndex, LastIndex, Index;
+ UCHAR NvramChar;
+ BOOLEAN LastNull = TRUE; // Assume it
+
+ DbgPrint("NVRAM Global Environment Area:\n");
+
+ StartIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress));
+ LastIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength));
+ LastIndex += StartIndex - 1;
+ for (Index = StartIndex; Index <= LastIndex; Index++) {
+ NvramChar = HalpDS1385ReadNVRAM(Index);
+ if (NvramChar == '\0') {
+ LastNull = TRUE;
+ } else {
+ if (LastNull == TRUE) {
+ DbgPrint("\n[%d]: ", Index);
+ }
+ DbgPrint("%c", NvramChar);
+ LastNull = FALSE;
+ }
+ }
+ DbgPrint("\n");
+ }
+
+ DbgPrint("Checking Our version of CRC");
+ DbgPrint("Compute CRC returns 0x%x\n", HalpComputeCrc());
+}
+
+UCHAR
+HalpGetEnvironmentInfo(
+ OPTIONAL PUSHORT TotalSize,
+ OPTIONAL PUSHORT FreeSize,
+ OPTIONAL PULONG pCrc)
+{
+ USHORT Index;
+ USHORT InUse, TotalLength;
+ UCHAR DataByte1, DataByte2;
+
+ NDBG(1, DbgPrint("HalpGetEnvironmentInfo: called\n"););
+
+ TotalLength = (USHORT) HalpReadNvramUlong((USHORT) &NVMAP->GELength);
+ if (TotalSize != NULL)
+ *TotalSize = TotalLength;
+
+ if (FreeSize != NULL) {
+ //
+ // Compute how much NVRAM is in use
+ //
+ InUse = 0;
+ Index = (USHORT)HalpReadNvramUlong ((USHORT) &NVMAP->GEAddress);
+ DataByte1 = HalpDS1385ReadNVRAM(Index++);
+ DataByte2 = DataByte1;
+ while (DataByte1 | DataByte2) {
+ DataByte1 = DataByte2;
+ DataByte2 = HalpDS1385ReadNVRAM(Index++);
+ InUse++;
+ }
+ *FreeSize = TotalLength - InUse;
+ }
+
+ if (pCrc != NULL) {
+ *pCrc = HalpReadNvramUshort((USHORT) &NVMAP->Crc1);
+ }
+ return(HalpDS1385ReadNVRAM((USHORT) &NVMAP->Version));
+}
+
+//
+// HalpAddByteCrc
+//
+// Description:
+// Use the X^16 + X^12 + X^5 + 1, Polynomial for CRC
+//
+// Input:
+// Stored in NVRAM
+//
+// Output:
+// New Crc Value
+//
+USHORT
+HalpAddByteCrc(USHORT CurrentCrc, USHORT Index)
+{
+ UCHAR Byte;
+ UCHAR CrcLo, CrcHi;
+ USHORT x,y,z;
+
+
+ Byte = HalpDS1385ReadNVRAM(Index);
+ CrcLo = CurrentCrc &0xff;
+ CrcHi = CurrentCrc >> 8;
+ x = (CrcLo << 8) | (CrcHi^Byte);
+ y = (CrcHi^Byte) << 8;
+ z = ((y >> 12) | (y << 4)) & 0xf00f;
+ x = x^z;
+ z = ((y << 13) | (y >> 3)) & 0x1fe0;
+ x = x^z;
+ z = y&0xf000;
+ x = x^z;
+ z = ((y<<9) | (y>>7)) & 0x1e0;
+ x = x^z;
+ return(x);
+}
+
+//
+// HalpComputeCrc
+//
+// Description:
+// Find the parts that are part of the crc and compute the
+// crc against them.
+//
+// Input:
+// Stored in NVRAM
+//
+// Output:
+//
+USHORT
+HalpComputeCrc(VOID)
+{
+ USHORT CurrentCrc = 0xffff;
+ USHORT Index, EndIndex;
+
+ //
+ // Loop through different parts computing CRC
+ // This is from Size to Revision inclusive
+ //
+ for (Index = 0; Index <= 3; Index++) {
+ CurrentCrc = HalpAddByteCrc(CurrentCrc, Index);
+ }
+
+ //
+ // Compute ending offset
+ //
+ EndIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->OSAreaAddress));
+
+ //
+ // Loop through second half
+ // This is from LastOS to OSArea (Note: 9 should be 8; however,
+ // IBM screwed up and we are all just going along with it).
+ //
+ for (Index = 9; Index < EndIndex; Index++) {
+ CurrentCrc = HalpAddByteCrc(CurrentCrc, Index);
+ }
+ return(CurrentCrc);
+}
+
+
+//
+// HalpUpdateCrc
+//
+// Description:
+// Compute the required Crc value and update the Header. This
+// code only updates crc1.
+//
+VOID
+HalpUpdateCrc()
+{
+ ULONG Crc;
+
+ NDBG(1, DbgPrint("HalpUpdateCrc: called\n"););
+ Crc = HalpComputeCrc();
+ HalpWriteNvramUshort((USHORT) &NVMAP->Crc1, (USHORT) Crc);
+}
+
+//
+// Returns the number of bytes removed
+//
+USHORT
+HalpCompressEnvironmentSpace(IN USHORT StartIndex)
+{
+ USHORT Index, BytesRemoved;
+ UCHAR PreviousChar, NvramChar;
+
+ Index = StartIndex+1;
+ while(HalpDS1385ReadNVRAM(Index++) != '=') {
+ /* Do Nothing */
+ }
+ while(HalpDS1385ReadNVRAM(Index++) != 0) {
+ /* Do Nothing */
+ }
+ BytesRemoved = Index - StartIndex; // Adjust amount of free space
+
+ NvramChar = 0;
+ //
+ // Copy subsequent variables
+ //
+ do {
+ PreviousChar = NvramChar;
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ HalpDS1385WriteNVRAM(StartIndex++, NvramChar);
+ } while (PreviousChar | NvramChar);
+
+ //
+ // Make sure unused NVRAM area is zeroed
+ //
+ for (Index=0; Index <BytesRemoved; Index++) {
+ if (Index+StartIndex >= NVSIZE) {
+ break;
+ }
+ HalpDS1385WriteNVRAM((USHORT)(Index+StartIndex), 0);
+ }
+ return(BytesRemoved);
+}
+
+//
+//HalpFindEnviroVar
+// Description:
+// Searches the NVRAM for an environment variable.
+//
+// Parameters:
+// Variable - ptr to the variable to search for.
+//
+// Return value:
+// The NVRAM index where the environment variable's VALUE is stored.
+// Returns 0 if the variable was not found.
+//
+// Assumes NVRAM_Spinlock has already been acquired by the caller.
+//
+USHORT
+HalpFindEnviroVar(IN CHAR *Variable)
+{
+ USHORT Index, StartIndex, LastIndex;
+ CHAR *VariablePtr, UserChar, NvramChar;
+
+ NDBG(1, DbgPrint("HalpFindEnviroVar: called for %s\n", Variable););
+
+ StartIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress));
+ LastIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength));
+ LastIndex += StartIndex - 1;
+
+
+ //
+ // Search the NVRAM for the variable.
+ //
+ VariablePtr = Variable;
+ for (Index = StartIndex ; Index <= LastIndex; ) {
+ //
+ // Get a character from the NVRAM
+ //
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ if (NvramChar == 0) {
+ break;
+ }
+
+ //
+ // Are we at the end of the variable name in both the
+ // input string and the NVRAM ?
+ // If so, then it is an exact match. Return the NVRAM index.
+ //
+ UserChar = *VariablePtr++;
+ if (UserChar == 0 && NvramChar == '=') {
+ NDBG(2, DbgPrint("HalpFindEnviroVar: found %s at %d\n",
+ Variable, Index););
+ return(Index);
+ }
+
+ //
+ // Convert variable to UPPER case
+ //
+ UserChar = (UserChar >= 'a' && UserChar <= 'z') ?
+ UserChar-0x20 : UserChar;
+
+ //
+ // Is there a match on this character ?
+ //
+
+ if (UserChar != NvramChar) {
+ //
+ // No, then skip over this variable in NVRAM and begin
+ // search again at start of variable NAME.
+ //
+ VariablePtr = Variable;
+ while (Index <= LastIndex) {
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ if (NvramChar == '=')
+ break;
+ }
+ while (Index <= LastIndex) {
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ if (NvramChar == 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // The variable was not found
+ //
+ NDBG(2, DbgPrint("HalpFindEnviroVar: %s not found\n", Variable););
+ return(0);
+}
+
+//
+// HalGetEnvironmentVariable
+//
+// Parameters:
+//
+// Variables:
+// Supplies a pointer to the zero-terminated, case ASCII string that contains
+// the name of the environment variable to be returned.
+// Length - Supplies the length of the buffer in bytes.
+// Buffer - Supplies a pointer to a buffer that receives the variable value.
+//
+// Return Value:
+// If the variable, the function returns the value ESUCCESS and its
+// value in Buffer. Otherwise, ENOENT is returned.
+//
+ULONG
+HalGetEnvironmentVariable(IN CHAR *Variable,
+ IN USHORT Length,
+ OUT CHAR *Buffer)
+{
+ USHORT Index;
+ static DumpNVRAMOnce = FALSE;
+ ULONG retVal = ENOENT
+
+
+ NDBG(1, DbgPrint("HalpGetEnvironmentVariable: called\n"););
+
+ //
+ // Check input parameters
+ //
+ if (!Variable) {
+ if (*Variable == 0 || Length < 1 || Buffer == NULL) {
+ NDBG(2, DbgPrint("HalpGetEnvironmentVariable: return ENOENT\n"););
+ return(retVal);
+ }
+ }
+
+ if (!DumpNVRAMOnce) {
+ NDBG(2, DumpNVRAM(););
+ DumpNVRAMOnce = TRUE;
+ }
+
+ //
+ // Grab control of NVRAM
+ //
+#if USE_SPINLOCKS
+ KIRQL Irql;
+ KeAcquireSpinLock(NVRAM_Spinlock, &Irql);
+#endif
+ NvramFailure = FALSE;
+
+ //
+ // Get NVRAM index of environment variable
+ //
+ Index = HalpFindEnviroVar(Variable);
+ if (Index == 0) {
+ //
+ // Environment variable was not found
+ //
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(retVal);
+ }
+
+ //
+ // Copy the environment variable's value to Buffer
+ //
+ do {
+ *Buffer = HalpDS1385ReadNVRAM(Index++);
+ if (*Buffer++ == 0) {
+ if (NvramFailure == TRUE) {
+ retVal = ENOMEM;
+ } else {
+ retVal = ESUCCESS;
+ }
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(retVal);
+ }
+ } while (--Length);
+
+ //
+ // Truncate the returned string. The buffer was too short.
+ //
+ *--Buffer = 0;
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(ENOMEM);
+}
+
+//
+// HalSetEnvironmentVariable
+//
+// Parameters:
+// Variable
+// Supplies a pointer to the zero-terminated ASCII string that contains
+// the name of the environment variable to be returned. The string is
+// converted to UPPER CASE.
+//
+// Value
+// Supplies a pointer to the zero-terminated string that contains the new
+// value of the environment variable.
+//
+// There are 4 cases:
+// 1) The environment variable is deleted if Value is a null string.
+// 2) The environment variable does not currently exist. It is appended
+// if there is enough NVRAM available.
+// 3) The environment variable already exists, and the new Value is
+// shorter than the old value.
+// 4) The environment variable already exists, and the new Value is longer than
+// the old value.
+//
+// In all cases the environment space will be compressed after
+// insertion/deletion.
+//
+ULONG
+HalSetEnvironmentVariable(
+ IN CHAR *Variable,
+ IN CHAR *Value)
+{
+ USHORT TotalSize, FreeSize, Index;
+ USHORT OldLength, NewLength;
+ USHORT StartIndex;
+ USHORT i;
+ USHORT NameLength, ValueLength;
+ CHAR *VariablePtr, *ValuePtr, Char;
+ ARC_STATUS ReturnValue;
+
+
+ NDBG(1, DbgPrint("HalSetEnvironmentVariable: called set %s to %s\n",
+ Variable, Value););
+
+ if (Value == NULL) {
+ NDBG(2, DbgPrint("HalSetEnvironmentVariable: returning ENOENT\n"););
+ return(ENOENT);
+ }
+
+ //
+ // Compute length of environment NAME
+ //
+ VariablePtr = Variable;
+ NameLength = 0;
+ while (*VariablePtr != 0) {
+ NameLength++;
+ VariablePtr++;
+ }
+
+ //
+ // Compute length of environment VALUE
+ //
+ ValuePtr = Value;
+ ValueLength = 0;
+ while (*ValuePtr != 0) {
+ ValueLength++;
+ ValuePtr++;
+ }
+#if USE_SPINLOCKS
+ KIRQL Irql;
+ KeAcquireSpinLock(NVRAM_Spinlock, &Irql); // Grab control of NVRAM
+#endif
+ NvramFailure = FALSE;
+
+ HalpGetEnvironmentInfo(&TotalSize, &FreeSize, NULL);
+
+
+ // Get index of environment variable
+ Index = HalpFindEnviroVar(Variable);
+
+ ReturnValue = ESUCCESS;
+ // Index to start of NAME
+ StartIndex = Index-NameLength-1;
+
+ // DELETE environment variable
+ if (ValueLength == 0) {
+ if (Index != 0) {
+ HalpCompressEnvironmentSpace(StartIndex);
+ }
+ } else {
+ // ADD or REPLACE environment variable
+ // Compute # bytes needed to store variable
+ NewLength = ValueLength + NameLength + 2;
+
+
+ // REPLACE environment variable.
+ // First we see if there is room. If so, delete the current
+ // variable & fall through to the code that ADDs a new variable.
+ if (Index != 0) {
+ // Compute current length of variable
+ OldLength = 0;
+ i = Index;
+ do {
+ OldLength++;
+ } while (HalpDS1385ReadNVRAM(i++) != 0);
+
+ // Is there room for the new variable ?
+ if (FreeSize-NewLength+OldLength >= 0)
+ FreeSize += HalpCompressEnvironmentSpace(StartIndex);
+ }
+ //
+ // ADD environment variable
+ //
+
+ if ((FreeSize-NewLength) >= 0) { // Room for new
+
+ Index = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress));
+ Index += (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength));
+ Index -= FreeSize;
+
+ //
+ // Write Variable NVRAM. Convert to UPPER case first.
+ //
+ while (*Variable != 0) {
+ Char = *Variable++;
+ //
+ // Convert Variable to UPPER case
+ //
+ Char = (Char >= 'a' && Char <= 'z') ? Char-0x20 : Char;
+ HalpDS1385WriteNVRAM(Index++,Char);
+ }
+
+ HalpDS1385WriteNVRAM(Index++,'='); // Write a "="
+
+ do {
+ // Write VALUE to NVRAM
+ HalpDS1385WriteNVRAM(Index++,*Value);
+ } while (*Value++ != 0);
+
+ ReturnValue = ESUCCESS;
+ }
+ }
+
+ //
+ // Update NVRAM checksum
+ //
+ HalpUpdateCrc();
+ if (NvramFailure == TRUE) {
+ ReturnValue = ENOMEM;
+ }
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(ReturnValue);
+}
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxflshbf.s b/private/ntos/nthals/halfire/ppc/pxflshbf.s
new file mode 100644
index 000000000..c4cdad4fd
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxflshbf.s
@@ -0,0 +1,159 @@
+#if defined(_PPC_)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxflshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a Power PC
+// system.
+//
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+//
+// Used PowerPC eieio instruction to flush writes
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxflshbf.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:34:14 $
+ * $Locker: $
+ */
+
+#include "kxppc.h"
+
+// SBTTL("Flush Write Buffer")
+//
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ eieio
+
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpSynchronizeExecution()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSynchronizeExecution)
+
+ sync // synchronize
+
+ LEAF_EXIT(HalpSynchronizeExecution)
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpGetProcessorVersion()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function gets the processor version of the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpGetProcessorVersion)
+
+ mfpvr r.3 // get processor version
+
+ LEAF_EXIT(HalpGetProcessorVersion)
+
+//
+//++
+//
+// VOID
+// SetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+
+ LEAF_ENTRY(SetSDR1)
+
+ subi r.4,r.4,1
+ rlwimi r.3,r.4,16,0x1ff
+ mtsdr1 r.3
+
+ LEAF_EXIT(SetSDR1)
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/pxflshio.c b/private/ntos/nthals/halfire/ppc/pxflshio.c
new file mode 100644
index 000000000..c73638505
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxflshio.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxflshio.c $
+ * $Revision: 1.11 $
+ * $Date: 1996/05/14 02:34:19 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ psflshio.c
+
+Abstract:
+
+ This module implements miscellaneous PowerPC HAL functions.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.ibm.com)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 1;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Length;
+ ULONG PartialLength;
+ ULONG Offset;
+ PULONG Page;
+ BOOLEAN DoDcache = FALSE;
+
+ //
+ // check for 601, it has a combined I and D cache that bus snoops
+ //
+ //
+
+ if ((HalpGetProcessorVersion() >> 16) != 1) {
+
+ Length = Mdl->ByteCount;
+
+ if ( !Length ) {
+ return;
+ }
+ //
+ // If the I/O operation is not a DMA operation,
+ // and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the data cache.
+ //
+ if (((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ DoDcache = TRUE;
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the range from the cache. Note it is not reasonable to sweep
+ // the entire cache on an MP system as "Flash Invalidate" doesn't
+ // broadcast the invalidate to other processors.
+ //
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+
+ Offset = Mdl->ByteOffset;
+ PartialLength = PAGE_SIZE - Offset;
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+
+ Page = (PULONG)(Mdl + 1);
+
+ if (DoDcache == TRUE) {
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ } else {
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ }
+ }
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxhalp.h b/private/ntos/nthals/halfire/ppc/pxhalp.h
new file mode 100644
index 000000000..ee880dedf
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxhalp.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxhalp.h $
+ * $Revision: 1.15 $
+ * $Date: 1996/05/15 00:06:21 $
+ * $Locker: $
+ */
+
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ PowerPC specific interfaces, defines and structures.
+
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added externs for HalpInterruptBase,HalpPciConfigBase
+ Added extern for HalpIoControlBase
+ Added prototype for HalpHandleDecrementerInterrupt (was in halp.h)
+ changed adapter object structure to be compatible with the intel HAL
+
+--*/
+
+#ifndef _PXHALP_
+#define _PXHALP_
+
+
+//
+// Define global data used to locate the IO control space, the interrupt
+// acknowlege, and the Pci config base.
+//
+
+extern PVOID HalpIoControlBase;
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpInterruptBase;
+extern PVOID HalpPciConfigBase;
+extern PVOID HalpErrorAddressRegister;
+extern PVOID HalpPciIsaBridgeConfigBase;
+
+//
+// prototype x86 emulator
+//
+
+extern BOOLEAN HalpInitX86Emulator(VOID);
+
+//
+// Define adapter object structure.
+//
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IsaBusMaster;
+ INTERFACE_TYPE InterfaceType; // spec what bus this adapter is on
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters
+ );
+
+BOOLEAN
+HalpCreateSioStructures(
+ VOID
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpFieldExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleDecrementerInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ );
+
+ULONG
+HalpUpdateDecrementer(
+ ULONG
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace(
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace(
+ VOID
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+PVOID
+KePhase0MapIo(
+ IN PVOID PhysicalMemoryBase,
+ IN ULONG MemorySize
+ );
+
+VOID
+KePhase0DeleteIoMap(
+ IN PVOID PhysicalMemoryBase,
+ IN ULONG MemorySize
+ );
+
+ULONG
+HalpCalibrateTB(
+ VOID
+ );
+
+VOID
+HalpZeroPerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ );
+
+VOID
+HalpLockDisplayString(
+ PVOID
+ );
+BOOLEAN
+HalpCacheSweepSetup(
+ VOID
+ );
+
+VOID
+HalpSweepPhysicalRangeInBothCaches(
+ ULONG Page,
+ ULONG Offset,
+ ULONG Length
+ );
+VOID
+HalpSweepPhysicalIcacheRange(
+ ULONG Page,
+ ULONG Offset,
+ ULONG Length
+ );
+#endif // _PXHALP_
diff --git a/private/ntos/nthals/halfire/ppc/pxhwsup.c b/private/ntos/nthals/halfire/ppc/pxhwsup.c
new file mode 100644
index 000000000..a96e4ff23
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxhwsup.c
@@ -0,0 +1,2212 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxhwsup.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/05/14 02:34:25 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC Port
+ Remove support for internal bus and devices
+ Changed HalFreeCommonBuffer to support S-FOOT address inversion
+ Added PCI, PCMCIA, and ISA bus support
+ Removed support for internal DMA controller
+ Change HalTranslateBusAddress to support S-FOOTS memory map
+ Deleted HalpReadEisaBus - this code was specific to EISA buses
+ Changed IoMapTransfer to support S-FOOT address inversion
+ Added support for guaranteed contigous common buffers
+
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+#include "phsystem.h"
+
+#include "pxmemctl.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// Define map buffer variables
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Amount
+ );
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+
+/*++
+
+Routine Description: NTSTATUS HalAllocateAdapterChannel()
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+ else
+ {
+ HalpPrint("KeInsertDeviceQueue: branch not taken \n");
+ }
+return(STATUS_SUCCESS);
+
+}
+
+/*++
+
+Routine Description: PVOID HalAllocateCommonBuffer()
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Allocate the actual buffer.
+ //
+
+
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+
+
+
+ //
+ // Memory space inverion
+ //
+
+
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (!AdapterObject->IsaBusMaster) {
+ LogicalAddress->LowPart |= IO_CONTROL_PHYSICAL_BASE;
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+/*++
+
+Routine Description: PVOID HalAllocateCrashDumpRegisters()
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. If not all of
+ the registers could be allocated this field is updated to show how
+ many were.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+/*++
+
+Routine Description: BOOLEAN HalFlushCommonBuffer()
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+{
+
+ return(TRUE);
+
+}
+
+/*++
+
+Routine Description: VOID HalFreeCommonBuffer()
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+{
+
+
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+ return;
+
+}
+
+/*++
+
+Routine Description: PADAPTER_OBJECT HalGetAdapter()
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: PCI, Isa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != PCIBus &&
+ DeviceDescription->InterfaceType != PCMCIABus) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateIsaAdapter( DeviceDescription,
+ NumberOfMapRegisters);
+ return(adapterObject);
+}
+
+
+/*++
+
+Routine Description: PADAPTER_OBJECT HalpAllocateAdapter()
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == NULL) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->IsaBusMaster = FALSE;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+/*++
+
+Routine Description: VOID IoFreeMapRegisters()
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+
+/*++
+
+Routine Description: VOID IoFreeAdapterChannel()
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+/*++
+
+Routine Description: PHYSICAL_ADDRESS IoMapTransfer()
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+
+ ULONG pageOffset;
+ ULONG index;
+ ULONG transferLength;
+ PULONG pageFrame;
+ ULONG logicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ BOOLEAN useBuffer;
+ PHYSICAL_ADDRESS returnAddress;
+
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) | IO_CONTROL_PHYSICAL_BASE;
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+// #pragma message(REVIEW "No Scatter Gather currently: Fix it soon?")
+// #pragma NOTE("No Scatter Gather currently: Fix it soon?")
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ //
+ // do the memory inversion on the logical address
+ //
+
+ logicalAddress = ( translationEntry->PhysicalAddress + pageOffset)
+ | IO_CONTROL_PHYSICAL_BASE;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // ISA masters require memory to be at less than 16 MB.
+ // always use map buffers for ISA busmasters
+ //
+
+ if (((logicalAddress+transferLength) & ~IO_CONTROL_PHYSICAL_BASE)
+ >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset | IO_CONTROL_PHYSICAL_BASE;
+
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ if (AdapterObject != NULL) {
+ if (AdapterObject->IsaBusMaster == TRUE) {
+ returnAddress.LowPart = logicalAddress & ~IO_CONTROL_PHYSICAL_BASE;
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ } else {
+
+
+ HalpIsaMapTransfer(
+ AdapterObject,
+ logicalAddress,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+
+ return(returnAddress);
+}
+
+
+/*++
+
+Routine Description: BOOLEAN IoFlushAdapterBuffers()
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: IO_ALLOCATION_ACTION HalpAllocationRoutine ()
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+/*++
+
+Routine Description: BOOLEAN HalpHandleMachineCheck()
+
+ This function is called when a PPC Machine Check interrupt occurs.
+ It print the appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Unused
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+{
+ KIRQL OldIrql;
+ //
+ // raise irql to machine check level
+ //
+
+ KeRaiseIrql(MACHINE_CHECK_LEVEL,&OldIrql);
+
+ //
+ // check memory controller machine check sources
+ //
+
+ // do not call this function now.
+ //
+ // HalpHandleMemoryError();
+ //
+ // check Bus NMI sources
+ //
+
+ HalpHandleIoError();
+
+ //
+ // Bug check
+ //
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ KeLowerIrql(OldIrql);
+
+ return(TRUE);
+}
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpAllocateMapBuffer()
+
+ This routine allocates the required map buffers.
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ )
+{
+
+ PVOID virtualAddress;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ HalpMapBufferPhysicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS;
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ HalpMapBufferSize,
+ HalpMapBufferPhysicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ return FALSE;
+
+ }
+
+ HalpMapBufferPhysicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: VOID HalpCopyBufferMap()
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+/*++
+
+Routine Description: BOOLEAN HalpGrowMapBuffers()
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ ULONG NumberOfPages;
+
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (ULONG) i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress ||
+ (((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxidaho.h b/private/ntos/nthals/halfire/ppc/pxidaho.h
new file mode 100644
index 000000000..19ba01f69
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxidaho.h
@@ -0,0 +1,149 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxidaho.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxidaho.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:10:40 $
+ * $Locker: $
+ */
+
+
+//
+// define structures for the idaho memory controller
+//
+
+
+
+typedef struct _IDAHO_CONTROL {
+ UCHAR Reserved1[0x808]; // Offset 0x000
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[7];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved9[0x1B];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR PciInterruptMap1; // Offset 0x839
+ UCHAR Reserved10[2];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR PciInterruptMap2; // Offset 0x83D
+ UCHAR AudioSupport; // Offset 0x83E
+ UCHAR Reserved11[0x14];
+ UCHAR Reserved12[0x2C];
+ UCHAR MemorySimmId1; // Offset 0x880
+ UCHAR Reserved13[3];
+ UCHAR MemorySimmId2; // Offset 0x884
+ UCHAR Reserved14[3];
+ UCHAR MemorySimmId3; // Offset 0x888
+ UCHAR Reserved15[3];
+ UCHAR MemorySimmId4; // Offset 0x88C
+ UCHAR Reserved16[0x46B];
+ ULONG ConfigAddress; // Offset 0xcf8
+ ULONG ConfigData; // Offset 0xcfc
+} IDAHO_CONTROL, *PIDAHO_CONTROL;
+
+typedef struct _IDAHO_CONFIG {
+
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1; // Offset 0x09
+ UCHAR SubclassCode; // Offset 0x0A
+ UCHAR ClassCode; // Offset 0x0B
+ UCHAR Reserved2; // Offset 0x0C
+ UCHAR Reserved3; // Offset 0x0D
+ UCHAR HeaderType; // Offset 0x0E
+ UCHAR BistControl; // Offset 0x0F
+ UCHAR Reserved4[0x2C];
+ UCHAR InterruptLine; // Offset 0x3C
+ UCHAR InterruptPin; // Offset 0x3D
+ UCHAR MinGnt; // Offset 0x3E
+ UCHAR MaxGnt; // Offset 0x3F
+ UCHAR BridgeNumber; // Offset 0x40
+ UCHAR SubordBusNumber; // Offset 0x41
+ UCHAR DisconnectCounter; // Offset 0x42
+ UCHAR ReservedAnger;
+ UCHAR SpecialCycleAddress[2]; // Offset 0x44
+ UCHAR Reserved5[0x3A];
+ UCHAR StartingAddress1; // Offset 0x80
+ UCHAR StartingAddress2; // Offset 0x81
+ UCHAR StartingAddress3; // Offset 0x82
+ UCHAR StartingAddress4; // Offset 0x83
+ UCHAR StartingAddress5; // Offset 0x84
+ UCHAR StartingAddress6; // Offset 0x85
+ UCHAR StartingAddress7; // Offset 0x86
+ UCHAR StartingAddress8; // Offset 0x87
+ UCHAR Reserved6[8];
+ UCHAR EndingAddress1; // Offset 0x90
+ UCHAR EndingAddress2; // Offset 0x91
+ UCHAR EndingAddress3; // Offset 0x92
+ UCHAR EndingAddress4; // Offset 0x93
+ UCHAR EndingAddress5; // Offset 0x94
+ UCHAR EndingAddress6; // Offset 0x95
+ UCHAR EndingAddress7; // Offset 0x96
+ UCHAR EndingAddress8; // Offset 0x97
+ UCHAR Reserved7[8];
+ UCHAR MemoryBankEnable; // Offset 0xA0
+ UCHAR MemoryTiming1; // Offset 0xA1
+ UCHAR MemoryTiming2; // Offset 0xA2
+ UCHAR Reserved8;
+ UCHAR SimmBank1; // Offset 0xA4
+ UCHAR SimmBank2; // Offset 0xA5
+ UCHAR SimmBank3; // Offset 0xA6
+ UCHAR SimmBank4; // Offset 0xA7
+ UCHAR Reserved9[9];
+ UCHAR L2CacheStatus; // Offset 0xB1
+ UCHAR Reserved10[2];
+ UCHAR RefreshCycle; // Offset 0xB4
+ UCHAR RefreshTimer; // Offset 0xB5
+ UCHAR WatchdogTimer; // Offset 0xB6
+ UCHAR BusTimer; // Offset 0xB7
+ UCHAR LocalBusTimer; // Offset 0xB8
+ UCHAR LocalBusIdleTimer; // Offset 0xB9
+ UCHAR Options1; // Offset 0xBA
+ UCHAR Options2; // Offset 0xBB
+ UCHAR Reserved11[4];
+ UCHAR EnableDetection1; // Offset 0xC0
+ UCHAR ErrorDetection1; // Offset 0xC1
+ UCHAR ErrorSimulation1; // Offset 0xC2
+ UCHAR CpuBusErrorStatus; // Offset 0xC3
+ UCHAR EnableDetection2; // Offset 0xC4
+ UCHAR ErrorDetection2; // Offset 0xC5
+ UCHAR ErrorSimulation2; // Offset 0xC6
+ UCHAR PciBusErrorStatus; // Offset 0xC7
+ UCHAR ErrorAddress[4]; // Offset 0xC8
+} IDAHO_CONFIG, *PIDAHO_CONFIG;
+
diff --git a/private/ntos/nthals/halfire/ppc/pxidle.c b/private/ntos/nthals/halfire/ppc/pxidle.c
new file mode 100644
index 000000000..51f1059ef
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxidle.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxidle.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/01/11 07:10:47 $
+ * $Locker: $
+ */
+
+/*++
+TITLE("Processor Idle")
+
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ pxidle.c
+
+abstract:
+
+ This module implements system platform dependent power management
+ support.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpcpu.h"
+ULONG HalpGetStack( VOID );
+extern ULONG registeredInts[];
+
+/*++
+
+ Routine Description: VOID HalProcessorIdle( VOID )
+
+
+ This function is called when the current processor is idle with
+ interrupts disabled. There is no thread active and there are no
+ DPCs to process. Therefore, power can be switched to a standby
+ mode until the the next interrupt occurs on the current processor.
+
+ N.B. This routine is entered with EE in MSR clear. This routine
+ must do any power management enabling necessary, set the EE
+ bit in MSR, then either return or wait for an interrupt.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+
+--*/
+
+VOID
+HalProcessorIdle(VOID)
+{
+ HASSERTMSG(PCR->CurrentIrql <= DISPATCH_LEVEL, "Wrong Dispatch Level");
+ HASSERT(RInterruptMask(GetCpuId()) == registeredInts[GetCpuId()]);
+
+ HalpEnableInterrupts();
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxinithl.c b/private/ntos/nthals/halfire/ppc/pxinithl.c
new file mode 100644
index 000000000..2166d81e4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxinithl.c
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxinithl.c $
+ * $Revision: 1.92 $
+ * $Date: 1996/05/14 02:34:31 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+ internal DMA contoller.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "halp.h"
+#include "pxmemctl.h"
+#include "fpproto.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpdcc.h"
+#include "fpds1385.h"
+#include "fpcpu.h"
+#include "arccodes.h"
+//#include "arc.h"
+#include "fpdebug.h"
+#include "fparch.h"
+#include "fpi2c.h"
+#include "pxpcisup.h"
+
+ULONG TmpVramBase;
+ULONG TmpDbatNum;
+ULONG TmpDbatVal;
+CHAR SysName[48];
+PCHAR SystemName="Unknown System";
+
+ULONG CpuClockMultiplier=0;
+ULONG MemoryParityErrorsThisBoot = 0;
+ULONG MemoryParityErrorsForever = 0;
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+extern ULONG HalpGetInstructionTimes( VOID );
+extern VOID HalpInitializeVector2Irql(VOID);
+extern UCHAR PciDevicePrimaryInts[];
+extern ULONG PciAllowedInts;
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+BOOLEAN
+HalpPhase0MapIo (
+ VOID
+ );
+
+BOOLEAN
+HalpPhase0MapPCIConfig (
+ VOID
+ );
+
+VOID
+HalpInitParityErrorLog (
+ VOID
+ );
+
+extern VOID HalpTranslateSystemSpecificData ( VOID );
+extern ULONG HalpPerformanceFrequency;
+extern BOOLEAN HalpSetRevs( RelInfo * );
+VOID HalpRestoreDBATs(VOID);
+VOID HalpSaveDBATs(VOID);
+#if defined(HALDEBUG_ON)
+VOID HalpDisplayBatForVRAM(void);
+VOID HalpGetDebugValue(VOID);
+extern BOOLEAN HalpPrintRevs( RelInfo * ); // from phvrsion.c
+extern VOID HalpVersionInternal( VOID ); // from phvrsion.c
+#endif
+extern VOID HalpVersionExternal( RelInfo *, PLOADER_PARAMETER_BLOCK ); // from phvrsion.c
+
+ULONG TimeBaseCount=0;
+
+
+//
+// This prototype taken from ntrtl.h.
+// Why not just include ntrtl.h? Well because I would need to include a dozen
+// other files too.
+//
+NTSYSAPI // ntddk ntifs
+NTSTATUS // ntddk ntifs
+NTAPI // ntddk ntifs
+RtlCharToInteger ( // ntddk ntifs
+ PCSZ String, // ntddk ntifs
+ ULONG Base, // ntddk ntifs
+ PULONG Value // ntddk ntifs
+ ); // ntddk ntifs
+
+
+RelInfo ThisOne;
+
+PROCESSOR_DESCRIPTION ProcessorDescription [nPROCESSOR_TYPE] = {
+ // Flags HashSize ProcessorName;
+ {PROC_NOSUPP, 0, "Unknown", "X"},
+ {PROC_SUPP, (64*1024), "601", "1"},
+ {PROC_NOSUPP, 0, "602", "2"},
+ {PROC_SUPP, 0, "603", "3"},
+ {PROC_SUPP |
+ PROC_HASHTABLE |
+ PROC_MPCAPABLE, (64*1024), "604", "4"},
+ {PROC_NOSUPP, 0, "605", "5"},
+ {PROC_SUPP, 0, "606", "3"},
+ {PROC_NOSUPP, 0, "607", "7"},
+ {PROC_NOSUPP, 0, "608", "8"},
+ {PROC_SUPP |
+ PROC_HASHTABLE |
+ PROC_MPCAPABLE, (64*1024), "609", "4"},
+};
+PROCESSOR_TYPE ProcessorType = PPC_UNKNOWN;
+
+SYSTEM_DESCRIPTION SystemDescription [] = {
+ {SYS_NOSUPP, "Unknown System Type"},
+ {SYS_SUPP, "ES"},
+ {SYS_SUPP|
+ SYS_MPCAPABLE, "MX"},
+ {SYS_SUPP|
+ SYS_MPCAPABLE, "TX"},
+ {SYS_SUPP|
+ SYS_MPCAPABLE, "LX"},
+};
+SYSTEM_TYPE SystemType = SYS_UNKNOWN;
+
+PVOID HalpSystemControlBase = NULL;
+PVOID HalpSystemRegisterBase = NULL;
+ULONG SafePlace;
+
+//
+// Define memory allocation structure.
+//
+typedef struct _AVR_MEMORY_DESCRIPTOR {
+ LIST_ENTRY *NextEntry;
+ LIST_ENTRY *PrevEntry;
+ MEMORY_DESCRIPTOR MemoryEntry;
+} AVR_MEMORY_DESCRIPTOR, *PAVR_MEMORY_DESCRIPTOR;
+
+CHAR *MemTypeList[] = {
+ "MemoryExceptionBlock",
+ "MemorySystemBlock",
+ "MemoryFree",
+ "MemoryBad",
+ "MemoryLoadedProgram",
+ "MemoryFirmwareTemporary",
+ "MemoryFirmwarePermanent",
+ "LoaderOsloaderHeap",
+ "LoaderOsloaderStack",
+ "LoaderSystemCode",
+ "LoaderHalCode",
+ "LoaderBootDriver",
+ "LoaderConsoleInDriver",
+ "LoaderConsoleOutDriver",
+ "LoaderStartupDpcStack",
+ "LoaderStartupKernelStack",
+ "LoaderStartupPanicStack",
+ "LoaderStartupPcrPage",
+ "LoaderStartupPdrPage",
+ "LoaderRegistryData",
+ "LoaderMemoryData",
+ "LoaderNlsData",
+ "LoaderSpecialMemory",
+ "LoaderMaximum"
+ };
+
+
+//
+// There are two variables that control debug printouts, HALDEBUG_ON,
+// and HALDEBUGVALUE. HALDEBUGVALUE is used to set a minimum level
+// of printing and debug behavior, and HALDEBUG_ON turns on the
+// environment variable. HALDEBUG_ON may be defined without HALPDEBUGVALUE,
+// but defining HALPDEBUGVALUE should require HALDEBUG_ON also be defined.
+//
+
+#if defined(HALDEBUG_ON)
+ //
+ // set the HalpDebugValue that determines what level of debug printout
+ // occurs. If one is defined on the cmd line, then 'or' it in with
+ // whatever is defined in the environment ( nvram ) area.
+ //
+# if defined(HALPDEBUGVALUE)
+int HalpDebugValue = HALPDEBUGVALUE;
+# else
+int HalpDebugValue = 0;
+# endif // HALPDEBUGVALUE
+#endif // HALPDEBUG_ON
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalpInitParityErrorLog)
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+PVOID HalpIoMemoryBase = (PVOID) 0;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpDS1385Lock;
+KSPIN_LOCK HalpRTCLock;
+
+
+/*++
+
+Routine Description: BOOLEAN HalInitSystem ()
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ SYSTEM_TYPE I2CSystemType;
+ UCHAR slot;
+ ULONG *TreeDepth = 0;
+ UCHAR CpuId;
+ KIRQL IrqlIn;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+ Prcb = PCR->Prcb;
+ IrqlIn = PCR->CurrentIrql;
+ SET_LEDS(0xf7);
+
+ //
+ // The following handles the initialization requirements for
+ // all processors greater than 1.
+ //
+
+ if (Prcb->Number > 0) {
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalInitSystem: Init of Cpu(%d)\n", GetCpuId()););
+
+ //
+ // Mask interrrupts, clear all of them and then
+ // enable interrupts.
+ //
+ HalpDisableInterrupts();
+ HalpInitInts(Prcb->Number);
+ HalpRestoreDBATs();
+ HalpEnableInterrupts();
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Cpu (%d) Interrupt Mask (0x%08x)\n",
+ GetCpuId(), RInterruptMask(GetCpuId())););
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalInitSystem: exit Cpu(%d)\n", GetCpuId()));
+
+ //
+ // Check the current irql level and make sure we exit at the same
+ // irql we entered with:
+ //
+ if( PCR->CurrentIrql >= IrqlIn ) {
+ KeLowerIrql(IrqlIn);
+ } else {
+ KIRQL dummyIrql;
+ KeRaiseIrql(IrqlIn, &dummyIrql);
+ }
+ return TRUE;
+ }
+
+ //
+ // Phase 0 initialization. (Main Processor Only).
+ //
+ ASSERT(Prcb->Number == 0);
+ if (Phase == 0) {
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey = 0;
+
+ HalpInitParityErrorLog();
+
+#if defined(HALDEBUG_ON)
+ //
+ // Get user defined debug variable and 'or' it into the
+ // compiled version of the debug variable.
+ //
+ HalpGetDebugValue();
+#endif
+
+ // moved this from after ConfigurationEntry because HalpGet
+ if (NULL == HalpIoControlBase) {
+ if (!HalpPhase0MapIo() || !HalpPhase0MapPCIConfig()) {
+ return FALSE;
+ }
+ }
+
+ // Initialize the Pci Primary Slot table to be invalid; this table
+ // is filled in on a per system basis.
+ for (slot = 0; slot < MAXIMUM_PCI_SLOTS; slot++) {
+ PciDevicePrimaryInts[slot] = INVALID_INT;
+ }
+
+ ConfigurationEntry =
+ KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ &MatchKey);
+
+ if (ConfigurationEntry) {
+ //
+ // If configuration entry is not null, then look at the
+ // identifier returned for this arc system name. If its the MP
+ // system, it means we really do have more than one cpu and
+ // will want to set a flag so VRAM is handled
+ // differently, and some extra checking is done.
+ //
+ SystemName = ConfigurationEntry->ComponentEntry.Identifier;
+
+ // Check if I2C is present
+ if (HalpI2CGetSystem(&I2CSystemType) == TRUE) {
+ SystemDescription[SystemType].Flags |= SYS_MPFOREAL;
+ // If I2C is present, determine if we are Slice or Serve
+ SystemType = I2CSystemType;
+ if ((SystemType != SYS_POWERSLICE) &&
+ (SystemType != SYS_POWERSERVE)) {
+ SystemType = SYS_UNKNOWN;
+ }
+ // An I2C is present, find the interrupt table. If there
+ // is no interrupt table, set SystemType back to SYS_UNKNOWN
+ // so that we may die now, since this is an unrecoverable
+ // error.
+ if (HalpI2CGetInterrupt() == FALSE) {
+ SystemType = SYS_UNKNOWN;
+ }
+ }
+ // If I2c is not present, must be either Pro or Top
+ else {
+ if (SystemType == SYS_POWERTOP) {
+ SystemDescription[SystemType].Flags |= SYS_MPFOREAL;
+ }
+ PciDevicePrimaryInts[1] = 0x19;
+ PciDevicePrimaryInts[2] = 0x16;
+ PciDevicePrimaryInts[3] = 0x17;
+ PciDevicePrimaryInts[4] = 0x1a;
+ PciAllowedInts = 0x06c00000;
+ }
+ } else {
+ HalpDebugPrint("ConfigurationEntry is null \n");
+ }
+
+ // Now compute the allowed interrupt mask
+ for (slot = 0; slot < MAXIMUM_PCI_SLOTS; slot++) {
+ if (PciDevicePrimaryInts[slot] != INVALID_INT) {
+ PciAllowedInts |= (1 << PciDevicePrimaryInts[slot]);
+ }
+ }
+ PciAllowedInts |= 0x40000000; // Add the MemErr bit
+
+ // If we are not a valid system type; die a horrible death
+ if (SystemType == SYS_UNKNOWN) {
+ HalpDebugPrint("HalInitSystem: Unknown SystemType\n");
+ DbgBreakPoint();
+ }
+
+ // Once we have the interrupt structure, we can initialize the IRQL
+ // values for the PIO slots.
+ HalpInitializeVector2Irql();
+
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalInitSystem: phase 0 init (processor 0)\n"););
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: HalpIoControlBase set: 0x%08x\n",
+ HalpIoControlBase););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: HalpSystemRegisterBase(0x%x)\n",
+ HalpSystemRegisterBase););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: rInterruptRequest(0x%x)\n",
+ _ADDR(0x0)););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: PciAllowedInts(0x%x)\n",
+ PciAllowedInts););
+
+ HalpInterruptBase =
+ (PULONG)HalpSystemRegisterBase + INTERRUPT_OFFSET;
+
+ //
+ // clear out all the crap from the system interrupt registers:
+ //
+ RInterruptMask(GetCpuId()) = 0x0;
+ WaitForRInterruptMask(GetCpuId());
+ rInterruptRequest = 0xffffffff;
+ FireSyncRegister();
+
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Init variables, spin locks, and the display adapter.
+ //
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ KeInitializeSpinLock(&HalpDS1385Lock);
+ KeInitializeSpinLock(&HalpRTCLock);
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // Initialize the display adapter.
+ //
+ if (!HalpInitializeDisplay(LoaderBlock)) {
+ HalpDebugPrint("HalInitSystem: did not init display\n");
+ return FALSE;
+ }
+
+ //
+ // set the background red for phase 0
+ //
+ HDBG(DBG_COLORS, HalpSetPixelColorMap( 0x00ff0000, 0x00000001 ););
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("Debug Value is 0x%x\n", HalpDebugValue););
+ HDBG(DBG_DUMPTREE,
+ PHalpDumpConfigData(LoaderBlock->ConfigurationRoot,
+ TreeDepth););
+ HDBG(DBG_DUMPTREE,
+ PHalpDumpLoaderBlock(LoaderBlock););
+
+ //
+ // Check if we should call a break point
+ //
+ HDBG(DBG_BREAK,
+ HalpDebugPrint("HalInitSystem: Calling Break Point\n"));
+ HDBG(DBG_BREAK, DbgBreakPoint());
+
+ //
+ // RTC: check that the RTC is working...
+ //
+ HDBG(DBG_GENERAL, HalpDebugPrint("Checking RTC ....\n"););
+ HalpInitFirePowerRTC();
+
+ //
+ // Calibrate execution stall
+ //
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Calibrating stall\n"););
+ HalpCalibrateTimingValues();
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: HalpPerformanceFrequency = %d\n",
+ HalpPerformanceFrequency););
+
+ //
+ // InitializeInterrupts
+ //
+ HDBG(DBG_GENERAL, HalpDebugPrint("HalInitSystem: Initting ints\n"););
+ if (!HalpInitializeInterrupts()) {
+ HalpDebugPrint("HalInitSystem: Did not init interrupts ");
+ return FALSE;
+ }
+
+ HDBG(DBG_GENERAL, HalpDisplayBatForVRAM(););
+ HalpSaveDBATs();
+ HDBG(DBG_GENERAL,
+ HalDisplayString("HalInitSystem: done with phase 0 \n"););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("System Name: %s \n", SystemName ););
+
+ } else {
+ //
+ // Phase 1 initialization.
+ //
+
+ //
+ // set the display to green while in phase 1:
+ //
+ HDBG(DBG_COLORS, HalpSetPixelColorMap(0x00009900, 0x00000001););
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: phase 1 init (processor 0)\n"););
+
+ HalpInitializeDisplay1(LoaderBlock );
+ HalpRegisterInternalBusHandlers ();
+ if (!HalpAllocateMapBuffer()) {
+ HalpDebugPrint("HalInitSystem: Did not allocate map buffer");
+ return FALSE;
+ }
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+ if (!HalpMapIoSpace()) {
+ HalpDebugPrint("HalInitSystem: Did not map io space");
+ return FALSE;
+ }
+
+
+ //
+ // Setup Io bus handlers ( really only setting up pci bus 0:
+ // the primary one). This needs to be done before the call
+ // to HalpCreateSioStructures so it can find the pci-e/isa
+ // bridge chip.
+ //
+ HalpInitIoBuses();
+
+
+ if (!HalpCreateSioStructures()) {
+ HalpDebugPrint("HalInitSystem: No sio structures created");
+ return FALSE;
+ }
+
+
+ //
+ // At this point, the interrupt handlers are installed so any
+ // interrupts pending are cleared...
+ //
+ if (!HalpInitIntelAIP()) {
+ HalpDebugPrint("HalInitSystem: AIP did not initialize\n");
+ return FALSE;
+ }
+
+ //
+ // Note: GetCpuId can not be called earlier
+ // because the registers are not mapped.
+ //
+ CpuId = (UCHAR) GetCpuId();
+ if (SystemType == SYS_POWERPRO) {
+ CpuId = 0;
+ }
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Cpu id is: %d\n", CpuId););
+
+ //
+ // Display HAL specific information
+ //
+ HalpSetRevs( &ThisOne );
+ HDBG(DBG_GENERAL, HalpPrintRevs( &ThisOne ););
+ HDBG(DBG_GENERAL, HalpVersionInternal(););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("CpuClockMultiplier = 0x%x ( %d ) \n",
+ CpuClockMultiplier, CpuClockMultiplier ));
+ HalpVersionExternal(&ThisOne, LoaderBlock);
+
+ //
+ // Before we exit, make sure any device interrupts are masked
+ // off, and all interrupts are cleared. DON'T FORGET: by this
+ // point, several interrupts have gone through a connect call,
+ // they may already exist in the mask. None of the devices are
+ // currently in this set but the cpu message interrupt. DON"T
+ // MESS WITH THE CPU MESSAGE INTERRUPT BIT!!
+ //
+ switch(SystemType) {
+ case SYS_POWERSLICE:
+ RInterruptMask(GetCpuId()) &= ~(ENABLE_EISA_MASK);
+ break;
+
+ case SYS_POWERSERVE:
+ // TX_PROTO: allowable PCI interrupts
+ RInterruptMask(GetCpuId()) &=
+ ~(ENABLE_EISA_MASK|0x06700000);
+ break;
+ case SYS_POWERTOP:
+ case SYS_POWERPRO:
+ RInterruptMask(GetCpuId()) &= ~(ENABLE_EISA_MASK|
+ SCSI_INT|
+ ENET_INT);
+ break;
+ default:
+ break;
+ };
+
+ WaitForRInterruptMask(GetCpuId());
+ rInterruptRequest = SET_INTS_CLEAR;
+ FireSyncRegister();
+
+ //HalpEnableInterrupts();
+ // Turn on interrupts, set the irql, and setup the system int masks:
+ //
+ KeLowerIrql(LOW_LEVEL);
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Cpu (%d) Interrupt Mask (0x%x)\n",
+ GetCpuId(), RInterruptMask(GetCpuId())));
+
+ //
+ // Make sure the display is now a blue background with
+ // White letters:
+ //
+ HDBG(DBG_COLORS, HalpSetPixelColorMap( 0x00ffffff, 0x000000ff ));
+ HDBG(DBG_COLORS, HalpSetPixelColorMap( 0x000000ff, 0x00000001 ));
+ HalpInitializeRegistry(LoaderBlock); // mogawa
+ HalpTranslateSystemSpecificData ();
+
+ HDBG(DBG_GENERAL, HalpDebugPrint("HalInitSystem: done phase 1\n"););
+ }
+
+ //
+ // Check the current irql level and make sure we exit at the same
+ // irql we entered with:
+ //
+ if( PCR->CurrentIrql >= IrqlIn ) {
+ KeLowerIrql(IrqlIn);
+ } else {
+ KIRQL dummyIrql;
+ KeRaiseIrql(IrqlIn, &dummyIrql);
+ }
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: VOID HalInitializeProcessor ()
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+{
+ PULONG pPCIBase;
+ BOOLEAN newMap;
+ ULONG IcacheSize, DcacheSize;
+ ULONG CacheBlockAlignment;
+
+ //
+ // Initialize the processor type (601, 603, 604, ...)
+ //
+ ProcessorType = (HalpGetProcessorVersion() >> 16);
+
+ //
+ // FireWorks ( FirePOWER and Firmworks ) veneer does not correctly set the
+ // processor cache size and alignment requirements in the loader parameter
+ // block so we forcibly replace the values that were copied from there
+ // into the PCR.
+ //
+ switch( ProcessorType ) {
+ case 1: // 601 processor
+ IcacheSize = 32 * 1024;
+ DcacheSize = 32 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ case 3: // 603 processor
+ IcacheSize = 8 * 1024;
+ DcacheSize = 8 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ case 6: // 603+ processor
+ case 4: // 604 processor
+ IcacheSize = 16 * 1024;
+ DcacheSize = 16 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ case 9: // 604+ processor
+ IcacheSize = 32 * 1024;
+ DcacheSize = 32 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ default:
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+ PCRsprg1->FirstLevelIcacheSize = IcacheSize;
+ PCRsprg1->FirstLevelDcacheSize = DcacheSize;
+ PCRsprg1->DcacheAlignment = CacheBlockAlignment;
+ PCRsprg1->IcacheAlignment = CacheBlockAlignment;
+
+ //
+ // Check what cpu we're on. Return now if this cpu is
+ // not the primary ( first ) cpu.
+ //
+ if (Number != 0) {
+ return; // Nothing to do here, just return
+ }
+
+ //
+ // Initialize the system type register (PowerPro vs PowerTop).
+ // Use the System Register Base address if mapped to access
+ // the control page of the system. If not, map a virtual
+ // address temporarily and unmap it when finished.
+ //
+ if (NULL == HalpIoControlBase) {
+ if (!HalpPhase0MapIo() || !HalpPhase0MapPCIConfig()) {
+ DbgPrint("HalInitializeProcessor: Failed to map dbats\n");
+ return;
+ }
+ }
+
+ if (HalpSystemRegisterBase) {
+ pPCIBase = (PULONG)((PUCHAR)HalpSystemRegisterBase +
+ (SYSTEM_PCI_CONFIG_BASE - SYSTEM_REGISTER_SPACE));
+ newMap = FALSE;
+ } else {
+
+ pPCIBase =
+ (PULONG)KePhase0MapIo((PVOID)SYSTEM_PCI_CONFIG_BASE, 0x1000);
+ newMap = TRUE;
+ }
+
+ if (pPCIBase) {
+ PULONG pDeviceId;
+ // for little endian reasons, add the 1 in.
+ pDeviceId = (PULONG)(pPCIBase + 0x42 + 0x01);
+ switch (*pDeviceId) {
+ case ESCC_IDENT:
+ SystemType = SYS_POWERPRO;
+ break;
+ case TSC_IDENT:
+ SystemType = SYS_POWERTOP;
+ break;
+ default:
+ SystemType = SYS_UNKNOWN;
+ break;
+ }
+ if (newMap) {
+ KePhase0DeleteIoMap((PVOID)SYSTEM_PCI_CONFIG_BASE, 0x1000);
+ }
+ } else {
+ SystemType = SYS_UNKNOWN;
+ }
+
+ //
+ // If this is the first processor, initialize the cache
+ // sweeping routines depending on type of processor.
+ //
+ if (HalpCacheSweepSetup()) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Calculate the cpu clock rate:
+ //
+
+ // Temporary fix until we understand the code
+ if (SystemType == SYS_POWERPRO) {
+ CpuClockMultiplier = 30; // fix it for the moment....
+ } else {
+ if ((SystemType == SYS_POWERSLICE) ||
+ (SystemType == SYS_POWERTOP) ||
+ (SystemType == SYS_POWERSERVE)) {
+ //
+ // The times recorded from HalpGetInstructionTimes range about
+ // 80 to 256.
+ // times: Multiplier:
+ // 85/6 3x BusClock
+ // 128 2x
+ // 170/1 1.5x
+ // 256 1x
+ //
+ // Since there can be a non integer multiple of bus clocks, will
+ // do all integer math at a multiple of 10 and remove the extra
+ // order of magnitude downstream when the value is used
+ //
+ TimeBaseCount = HalpGetInstructionTimes();
+ TimeBaseCount = HalpGetInstructionTimes();
+ CpuClockMultiplier = ((480 * 10) / (10 * (TimeBaseCount/10)));
+ if (CpuClockMultiplier > 50 ) {
+ CpuClockMultiplier = 50; // limit frequency multiples to 5.
+ }
+ }
+ }
+
+ return;
+}
+
+
+#define MAX_DBATS 4
+ULONG DBATUpper[MAX_DBATS];
+ULONG DBATLower[MAX_DBATS];
+
+VOID
+HalpRestoreDBATs()
+{
+ int i;
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpRestoreDBATs: entered\n"););
+ for (i = 0; i < MAX_DBATS; i++) {
+ HDBG(DBG_DBAT,
+ HalpDebugPrint("HalpRestoreDBATs: U(%d):Old(0x%08x) New(0x%08x)\n",
+ i, HalpGetUpperDBAT(i), DBATUpper[i]););
+ HDBG(DBG_DBAT,
+ HalpDebugPrint("HalpRestoreDBATs: L(%d):Old(0x%08x) New(0x%08x)\n",
+ i, HalpGetLowerDBAT(i), DBATLower[i]););
+ HalpSetUpperDBAT(i, DBATUpper[i]);
+ HalpSetLowerDBAT(i, DBATLower[i]);
+ }
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpRestoreDBATs: exit\n"););
+}
+
+
+VOID
+HalpSaveDBATs()
+{
+ int i;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpSaveDBATs: entered\n"););
+ for (i = 0; i < MAX_DBATS; i++) {
+ DBATUpper[i] = HalpGetUpperDBAT(i);
+ DBATLower[i] = HalpGetLowerDBAT(i);
+ HDBG(DBG_DBAT,
+ HalpDebugPrint("HalpSaveDBATs: (%d): U(0x%08x) L(0x%08x)\n",
+ i, DBATUpper[i], DBATLower[i]););
+ }
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpPhase0MapIo ()
+
+ This function forces a very special DBAT mapping for Phase0.
+ The kernel routine KePhase0DeleteIoMap has a nasty bug, so
+ just map three (the max) DBATS:
+
+ 1) system registers
+ 2) memory (to be reused for VRAM if no INT10 support)
+ 3) I/O control (change the size of its mapping)
+
+ The idea is to let the kernel map the three DBATs.
+ It sets the boundary to 8Mb and maps 8Mb starting at
+ virtual address 0xb0000000. Thus you get the following
+ virtual to physical mappings:
+
+ DBAT2 = 0xb0800000-0xb0ffffff -> 0xff000000-0xffffffff
+ DBAT3 = 0xb1000000-0xb17fffff -> 0x80000000-0x80ffffff
+
+ The I/O control size will be changed (by HalpPhase0MapPCIConfig())
+ to 16Mb so it maps 0x80000000 to 0x80ffffff which covers the PCI
+ config space.
+
+ The mapping of the frame buffer or memory space (for INT10)
+ is left to pxdisp.c which will use DBAT1.
+
+Arguments:
+
+
+Return Value:
+
+ TRUE if success, FALSE if failure
+
+--*/
+
+BOOLEAN
+HalpPhase0MapIo (
+ VOID
+ )
+{
+
+ //
+ // Get access to I/O space.
+ //
+ if (NULL == HalpIoControlBase) {
+ HalpIoControlBase =
+ (PVOID)KePhase0MapIo((PVOID)IO_CONTROL_PHYSICAL_BASE, 0x800000);
+ if (!HalpIoControlBase) {
+ DbgPrint("HalpPhase0MapIo: HalpIoControlBase map failed\n");
+ return FALSE;
+ }
+ }
+
+ //
+ // Get access to System Register space.
+ //
+ if (NULL == HalpSystemRegisterBase) {
+ HalpSystemRegisterBase =
+ (PVOID)KePhase0MapIo((PVOID)SYSTEM_REGISTER_SPACE, 0x800000);
+ if(HalpSystemRegisterBase) {
+ HalpInterruptBase =
+ (PULONG)HalpSystemRegisterBase + INTERRUPT_OFFSET;
+ HalpSystemControlBase =
+ (PULONG)HalpSystemRegisterBase + SYSTEM_CONTROL_OFFSET;
+ } else {
+ DbgPrint("HalpPhase0MapIo: HalpSystemRegisterBase map failed\n");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*++
+
+ Routine Description: BOOLEAN HalpPhase0MapPCIConfig ()
+
+ This function extends the map length of I/O Control
+ to include PCI Config space.
+
+Arguments:
+
+
+Return Value:
+
+ TRUE if success, FALSE if failure
+
+--*/
+
+BOOLEAN
+HalpPhase0MapPCIConfig (
+ VOID
+ )
+{
+ ULONG hi, low;
+ LONG i;
+
+
+ //
+ //
+ // Look for the I/O control space DBAT mapping.
+ //
+ for (i = 1; i < MAX_DBATS; i++) {
+ PVOID va = NULL;
+
+ low = HalpGetLowerDBAT(i);
+ if (IO_CONTROL_PHYSICAL_BASE == (low & 0xfffe0000)) {
+ hi = HalpGetUpperDBAT(i);
+ if ((PVOID)(hi & 0xfffe0000) == HalpIoControlBase) {
+ if (3 == i) {
+ //
+ // Change the size to 16Mb.
+ //
+ hi &= ~0x000001fc;
+ hi |= 0x000001fc;
+ HalpSetUpperDBAT(i, hi);
+ hi = HalpGetUpperDBAT(i);
+ if ((hi & 0x00001ffc) == 0x000001fc) {
+ HalpPciConfigBase = (PUCHAR)HalpIoControlBase +
+ ((ULONG)PCI_CONFIG_PHYSICAL_BASE -
+ (ULONG)IO_CONTROL_PHYSICAL_BASE);
+ } else {
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid size\n");
+ return FALSE;
+ }
+ } else {
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid DBAT\n");
+ }
+ } else {
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid virtual address\n");
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid physical address\n");
+ return FALSE;
+}
+
+
+#if defined(HALDEBUG_ON)
+VOID
+HalpGetDebugValue()
+{
+ CHAR buf[30];
+ int nvramValue;
+
+ //
+ // Get Debug Value from NVRAM and or with compiler version
+ //
+ if (HalGetEnvironmentVariable("HALDEBUG", sizeof(buf), buf) == ESUCCESS) {
+ nvramValue = atoi(buf);
+ HalpDebugValue |= nvramValue;
+ }
+}
+#endif
+
+//
+// Initialize the global variables for parity error count.
+//
+// The initial value for this boot is zero.
+// The initial value forever is read from NVRAM.
+//
+// The NVRAM values are stored in the env variable
+// "MEMORY_PARITY_ERRORS" as:
+// # errors this boot, # errors forever
+//
+//
+VOID
+HalpInitParityErrorLog (
+ VOID
+ )
+{
+ ULONG rc;
+ CHAR buf[80];
+
+ rc = HalGetEnvironmentVariable(MemoryParityErrorsVarName,
+ sizeof(buf), buf);
+ if (ESUCCESS == rc) {
+ PCHAR tok;
+ const PCHAR delimiters = ",; ";
+
+ if (buf && strlen(buf) && (tok = FpStrtok(buf, delimiters))) {
+ rc = RtlCharToInteger(tok, 0, &MemoryParityErrorsThisBoot);
+ if (STATUS_SUCCESS != rc) {
+ MemoryParityErrorsThisBoot = 0;
+ }
+ while ( tok = FpStrtok(NULL, delimiters) ) {
+ if (strlen(tok)) {
+ rc = RtlCharToInteger(tok, 10, &MemoryParityErrorsForever);
+ if (STATUS_SUCCESS != rc) {
+ MemoryParityErrorsForever = 0;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxintsup.s b/private/ntos/nthals/halfire/ppc/pxintsup.s
new file mode 100644
index 000000000..4daf671c9
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxintsup.s
@@ -0,0 +1,121 @@
+// TITLE("Enable and Disable Processor Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxintsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to enable and disable
+// interrupts on a PPC system.
+//
+// Author:
+//
+// Jim Wooldridge
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 30-Dec-93 plj Added 603 support.
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxintsup.s $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:11:07 $
+ * $Locker: $
+ */
+
+#include "halppc.h"
+
+//++
+//
+// Routine Description:
+//
+// Enables interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpEnableInterrupts)
+
+ mfmsr r.5
+ ori r.5,r.5,MASK_SPR(MSR_EE,1)
+ mtmsr r.5
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ LEAF_EXIT(HalpEnableInterrupts)
+
+
+//++
+
+//
+// Routine Description:
+//
+// Disables interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpDisableInterrupts)
+
+ mfmsr r.5
+ rlwinm r.5,r.5,0,~MASK_SPR(MSR_EE,1)
+ mtmsr r.5
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ LEAF_EXIT(HalpDisableInterrupts)
+
+
+//++
+
+//
+// Routine Description:
+//
+// Disables interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(KiGetPcr)
+
+ mfsprg r.3,1
+
+ LEAF_EXIT(KiGetPcr)
diff --git a/private/ntos/nthals/halfire/ppc/pxirql.c b/private/ntos/nthals/halfire/ppc/pxirql.c
new file mode 100644
index 000000000..773d892e4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxirql.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxirql.c $
+ * $Revision: 1.17 $
+ * $Date: 1996/01/11 07:11:13 $
+ * $Locker: $
+ */
+
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// PXIRQL.C
+//
+// Abstract:
+//
+// This module implements the code necessary to lower and raise the current
+// Interrupt Request Level (IRQL).
+//
+//
+// Author:
+//
+// Jim Wooldridge (IBM)
+// Steve Johns (Motorola)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 22-Feb-94 Steve Johns (Motorola)
+// KeRaiseIrql - Disabled interrupts at PIC if IRQL >= DEVICE_LEVEL
+// KeLowerIrql - Enabled interrupts at PIC if IRQL < DEVICE_LEVEL
+// 15-Apr-94 Jim Wooldridge
+// Added irql interrupt mask table and expanded irql range from (0-8)
+// to (0-31).
+//
+// TODO:
+// 1) Fix the forced mask assignments in the KeRaiseIrql and KeLowerIrql
+// routines
+//--
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "eisa.h"
+#include "phsystem.h"
+#include "fpcpu.h"
+
+
+VOID KiDispatchSoftwareInterrupt(VOID);
+
+//
+// Globals accessed.
+//
+extern ULONG registeredInts[];
+extern ULONG Irql2Mask[];
+
+//
+// VOID
+// KeLowerIrql (
+// KIRQL NewIrql
+// )
+//
+// Routine Description:
+//
+// This function lowers the current IRQL to the specified value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+VOID
+KeLowerIrql(KIRQL NewIrql)
+{
+ KIRQL OldIrql;
+ UCHAR CpuId;
+
+ //
+ // All accesses to the PCR should be guarded by disabling interrupts
+ // in the CPU (MSR register).
+ //
+ HalpDisableInterrupts();
+
+ CpuId = (UCHAR)GetCpuId();
+
+ //
+ // We should no be raising our Irql with lower.
+ //
+ HASSERTEXEC(NewIrql <= PCR->CurrentIrql,
+ HalpDebugPrint("KeLowerIrql: New (0x%x) Current(0x%x)\n",
+ NewIrql, PCR->CurrentIrql));
+
+ //
+ // Switch to the new Irql.
+ //
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // Now make the coresponding hardware mask changes.
+ //
+ RInterruptMask(CpuId) = (Irql2Mask[NewIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ if (NewIrql < CLOCK2_LEVEL) {
+
+ HalpEnableInterrupts();
+
+ //
+ // check for DPC's
+ //
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt) {
+ KiDispatchSoftwareInterrupt();
+ }
+ }
+}
+
+//
+// VOID KeRaiseIrql (KIRQL NewIrql, PKIRQL OldIrql)
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that recieves the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(IN KIRQL NewIrql, OUT PKIRQL OldIrql)
+{
+ UCHAR CpuId;
+
+ //
+ // All accesses to the PCR should be guarded by disabling interrupts
+ // in the CPU (MSR register).
+ //
+ HalpDisableInterrupts();
+
+ CpuId = (UCHAR)GetCpuId();
+
+ //
+ // We should not be raising to a lower level.
+ //
+ HASSERTEXEC(NewIrql >= PCR->CurrentIrql,
+ HalpDebugPrint("KeRaiseIrql: New (0x%x) Current(0x%x)\n",
+ NewIrql, PCR->CurrentIrql));
+
+ //
+ // Switch to the new Irql.
+ //
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // Now make the corresponding hardware mask changes.
+ //
+ RInterruptMask(CpuId) = (Irql2Mask[NewIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ if (NewIrql < CLOCK2_LEVEL) {
+ HalpEnableInterrupts();
+ }
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxisabus.c b/private/ntos/nthals/halfire/ppc/pxisabus.c
new file mode 100644
index 000000000..59c62c743
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxisabus.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxisabus.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/05/14 02:34:36 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+#define TBS " "
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
+#pragma alloc_text(PAGE,HalpAdjustResourceListLimits)
+#endif
+
+
+
+/*++
+
+Routine Description: ULONG HalpGetIsaInterruptVector()
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+
+ //
+ // irq2 shows up on irq9
+ //
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetIsaInterruptVector: 0x%x, 0x%x, 0x%x 0x%x \n",
+ BusInterruptLevel, BusInterruptVector, *Irql, *Affinity ););
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ BusInterruptVector = 9;
+ }
+
+ //
+ // Hack Hack:
+ //
+ // NOTE: NOTE:
+ // The Ethernet driver reports itself as an ISA device but with a
+ // PCI interrupt so need to fixup the interrupt if it looks correct
+ // for the pci bus vector:
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // There are 4 cases to check here:
+ // A) One of the entries ( BusIntLvl || BusIntVec ) is zero,
+ // B) Both of the entries are the same value,
+ // C) One of the entries is == 5 ( Which is the SPL for external
+ // devices on PowerPC NT )
+ // D) none of the above
+ //
+ switch(BusInterruptLevel) {
+ case 0:
+ if (BusInterruptVector) {
+ BusInterruptLevel = BusInterruptVector;
+ } else {
+ // they're both zero, so hope this is the profile int.
+ }
+ break;
+ case 5:
+ //
+ // In this case, BusInterruptLevel is probably indicating the
+ // system SPL for external ints, so assume the BusInterruptVector
+ // contains the real interrupt info
+ //
+
+ break;
+ default:
+ //
+ // Since BusInterruptLevel is nonzero and not equal to 5, then see
+ // if BusInterruptVector is zero or equal to 5. If it's neither,
+ // then print out the level and vector values and spin since this
+ // is a combination I've never seen before.
+ //
+ if( BusInterruptVector ) {
+ ULONG tmp;
+ if( BusInterruptVector == (BusInterruptLevel + 0x20) ) {
+
+ BusInterruptVector = BusInterruptLevel;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAInt: BusIntVec(0x%x) = BusIntLvl(0x%x) +0x20 \n",
+ BusInterruptVector, BusInterruptLevel ));
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAInt: ****** Please Fix Driver to use BusInterruptVector correctly \n"));
+// NOTE("Hack for audio driver to work")
+ }
+ if(( BusInterruptLevel != BusInterruptVector)
+ && ( BusInterruptVector != 5 )) {
+ HalpDebugPrint("Wierd BusIntVec & BusIntLvl (spin now)\n");
+ HalpDebugPrint(" BusIntLvl = 0x%x, BusIntVec = 0x%x\n",
+ BusInterruptLevel, BusInterruptVector );
+ for (;;) {
+ }
+ }
+ //
+ // Here, BusInterruptVector is known to be non-zero, = 5 or
+ // BusLevel. So, assume it's the 5 choice and swap it with
+ // level.
+ //
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("\t\tSwap BusIntLvl & BusIntVec %x, %x...\n",
+ BusInterruptLevel, BusInterruptVector););
+ tmp = BusInterruptLevel;
+ BusInterruptLevel = BusInterruptVector;
+ BusInterruptVector = tmp;
+ //
+ // Now, BusInterruptVector has the interesting value so the
+ // HalpGetSystemInterrupt can correctly key on
+ // BusInterruptVector.
+ //
+ } else {
+ //
+ // since BusInterruptVector is zero
+ //
+ BusInterruptVector = BusInterruptLevel;
+ }
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ UCHAR Irq[15], c;
+
+ for (c=0; c < 15; c++) {
+ Irq[c] = IRQ_VALID;
+ }
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpAdjustIsaResourceList: called\n"));
+
+ return HalpAdjustResourceListLimits (
+ BusHandler, RootHandler, pResourceList,
+ 0, 0xffffff, // Bus supports up to memory 0xFFFFFF
+ 0, 0, // No special range for prefetch
+ FALSE,
+ 0, 0xffff, // Bus supports up to I/O port 0xFFFF
+ Irq, 15, // Bus supports up to 15 IRQs
+ 0, 7 // Bus supports up to Dma channel 7
+ );
+}
+
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableSize,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ )
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList, OutCompleteList;
+ PIO_RESOURCE_LIST InResourceList, OutResourceList;
+ PIO_RESOURCE_DESCRIPTOR InDesc, OutDesc, HeadOutDesc;
+ BOOLEAN GotPFRange, FirstDescBuilt;
+ ULONG len, alt, cnt, i;
+ UCHAR LastIrqState, NewIrqState;
+ ULONG PFAddress, icnt, pcnt;
+
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpAdjustResourceListLimits: BusHandler=0x%08x, ResList=0x%08x\n",
+ BusHandler, pResourceList););
+
+ InCompleteList = *pResourceList;
+ len = InCompleteList->ListSize;
+ PFAddress =
+ MinimumPrefetchMemoryAddress || MaximumPrefetchMemoryAddress ? 1 : 0;
+ icnt = 0;
+ pcnt = 0;
+
+ //
+ // Worste case, add an extra interrupt descriptor for every different
+ // IRQ range present
+ //
+
+ LastIrqState = 0;
+ for (i=0; i < IrqTableSize; i++) {
+ if (IrqTable[i] != LastIrqState) {
+ icnt += 1;
+ LastIrqState = IrqTable[i];
+ }
+ }
+
+ //
+ // If LimitiedIOSupport, then the supported I/O ranges are
+ // limited to 256bytes on every 1K aligned boundry within the
+ // range specified. Worste case add an extra N descriptors for
+ // every I/O range passed.
+ //
+
+ if (LimitedIOSupport && MaximumPortAddress > MinimumPortAddress) {
+ pcnt = (MaximumPortAddress - MinimumPortAddress) / 1024;
+ }
+
+ //
+ // Scan input list - verify revision #'s, and increase len varible
+ // by amount output list may increase.
+ //
+
+ i = 0;
+ InResourceList = InCompleteList->List;
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+ if (InResourceList->Version != 1 || InResourceList->Revision < 1) {
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sVersion is not 1, or revision is < 1.\n",
+ TBS););
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ InDesc = InResourceList->Descriptors;
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+ switch (InDesc->Type) {
+ case CmResourceTypePort: i += pcnt; break;
+ case CmResourceTypeInterrupt: i += icnt; break;
+ case CmResourceTypeMemory: i += PFAddress; break;
+ case CmResourceTypeDma: break;
+ default:
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sINVALID PARAM ..InDesc->Type: 0x%x\n",
+ TBS,InDesc->Type););
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Next descriptor
+ InDesc++;
+ }
+
+ // Next Resource List
+ InResourceList = (PIO_RESOURCE_LIST) InDesc;
+ }
+ len += i * sizeof (IO_RESOURCE_DESCRIPTOR);
+
+ //
+ // Allocate output list
+ //
+
+ OutCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST)
+ ExAllocatePool (PagedPool, len);
+
+ if (!OutCompleteList) {
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sOutCompleteList is null ( No memory? ) \n",TBS););
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Walk each ResourceList and build output structure
+ //
+
+ InResourceList = InCompleteList->List;
+ *OutCompleteList = *InCompleteList;
+ OutResourceList = OutCompleteList->List;
+
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+ OutResourceList->Version = 1;
+ OutResourceList->Revision = 1;
+
+ InDesc = InResourceList->Descriptors;
+ OutDesc = OutResourceList->Descriptors;
+ HeadOutDesc = OutDesc;
+
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+
+ //
+ // Copy descriptor
+ //
+
+ *OutDesc = *InDesc;
+
+ //
+ // Limit desctiptor to be with the buses supported ranges
+ //
+
+ switch (OutDesc->Type) {
+ case CmResourceTypePort:
+ if (OutDesc->u.Port.MinimumAddress.QuadPart < MinimumPortAddress) {
+ OutDesc->u.Port.MinimumAddress.QuadPart = MinimumPortAddress;
+ }
+
+ if (OutDesc->u.Port.MaximumAddress.QuadPart > MaximumPortAddress) {
+ OutDesc->u.Port.MaximumAddress.QuadPart = MaximumPortAddress;
+ }
+
+ if (!LimitedIOSupport) {
+ break;
+ }
+
+ // In the case of LimitiedIOSupport the caller will only
+ // pass in 1K aligned values
+
+ FirstDescBuilt = FALSE;
+ for (i = MinimumPortAddress; i < MaximumPortAddress; i += 1024) {
+ if (InDesc->u.Port.MinimumAddress.QuadPart < i) {
+ OutDesc->u.Port.MinimumAddress.QuadPart = i;
+ }
+
+ if (InDesc->u.Port.MaximumAddress.QuadPart > i + 256) {
+ OutDesc->u.Port.MaximumAddress.QuadPart = i + 256;
+ }
+
+ if (OutDesc->u.Port.MinimumAddress.QuadPart <=
+ OutDesc->u.Port.MaximumAddress.QuadPart) {
+
+ //
+ // Valid I/O descriptor build, start another one.
+ //
+
+ FirstDescBuilt = TRUE;
+
+ OutDesc++;
+ *OutDesc = *InDesc;
+ OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
+ }
+ }
+
+ if (FirstDescBuilt) {
+ OutDesc--;
+ }
+ break;
+
+ case CmResourceTypeInterrupt:
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpAdjustResourceListLimits: new CmResourceTypeInterrupt \n"););
+
+ //
+ // Build a list of interrupt descriptors which are
+ // a subset of the IrqTable and the current descriptor
+ // passed in on the input list.
+ //
+
+ FirstDescBuilt = FALSE;
+ LastIrqState = 0;
+
+ for (i=0; i < IrqTableSize; i++) {
+ NewIrqState = IrqTable[i];
+
+ while (LastIrqState != NewIrqState) {
+ if (LastIrqState) {
+ OutDesc++; // done with last desc
+ LastIrqState = 0; // new state
+ continue;
+ }
+
+ //
+ // Start a new descriptor
+ //
+
+ *OutDesc = *InDesc;
+ OutDesc->u.Interrupt.MinimumVector = i;
+ if (NewIrqState & IRQ_PREFERRED) {
+ OutDesc->Option |= IO_RESOURCE_PREFERRED;
+ }
+
+ if (FirstDescBuilt) {
+ OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
+ }
+
+ LastIrqState = NewIrqState;
+ FirstDescBuilt = TRUE;
+ }
+
+ OutDesc->u.Interrupt.MaximumVector = i;
+ }
+
+ if (!LastIrqState) {
+ if (!FirstDescBuilt) {
+ OutDesc->u.Interrupt.MinimumVector =
+ IrqTableSize + 1;
+ } else {
+ OutDesc--;
+ }
+ }
+
+ break;
+
+ case CmResourceTypeMemory:
+ if (PFAddress && (OutDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) ) {
+ //
+ // There's a Prefetch range & this resource supports
+ // Prefetching. Build two descriptors - one for the
+ // supported Prefetch range as preferred, and the other
+ // normal memory range.
+ //
+
+ OutDesc->Option |= IO_RESOURCE_PREFERRED;
+
+ if (OutDesc->u.Memory.MinimumAddress.QuadPart < MinimumPrefetchMemoryAddress) {
+ OutDesc->u.Memory.MinimumAddress.QuadPart = MinimumPrefetchMemoryAddress;
+ }
+
+ if (OutDesc->u.Memory.MaximumAddress.QuadPart > MaximumPrefetchMemoryAddress) {
+ OutDesc->u.Memory.MaximumAddress.QuadPart = MaximumPrefetchMemoryAddress;
+ }
+
+ GotPFRange = FALSE;
+ if (OutDesc->u.Memory.MaximumAddress.QuadPart >=
+ OutDesc->u.Memory.MinimumAddress.QuadPart) {
+
+ //
+ // got a valid descriptor in the Prefetch range, keep it,
+ //
+
+ OutDesc++;
+ GotPFRange = TRUE;
+ }
+
+ *OutDesc = *InDesc;
+
+ if (GotPFRange) {
+ // next descriptor is an alternative
+ OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
+ }
+ }
+
+ //
+ // Fill in memory descriptor for range
+ //
+
+ if (OutDesc->u.Memory.MinimumAddress.QuadPart < MinimumMemoryAddress) {
+ OutDesc->u.Memory.MinimumAddress.QuadPart = MinimumMemoryAddress;
+ }
+
+ if (OutDesc->u.Memory.MaximumAddress.QuadPart > MaximumMemoryAddress) {
+ OutDesc->u.Memory.MaximumAddress.QuadPart = MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (OutDesc->u.Dma.MinimumChannel < MinimumDmaChannel) {
+ OutDesc->u.Dma.MinimumChannel = MinimumDmaChannel;
+ }
+
+ if (OutDesc->u.Dma.MaximumChannel > MaximumDmaChannel) {
+ OutDesc->u.Dma.MaximumChannel = MaximumDmaChannel;
+ }
+ break;
+
+#if DBG
+ default:
+ DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
+ break;
+#endif
+ }
+
+ //
+ // Next descriptor
+ //
+
+ InDesc++;
+ OutDesc++;
+ }
+
+ OutResourceList->Count = OutDesc - HeadOutDesc;
+
+ //
+ // Next Resource List
+ //
+
+ InResourceList = (PIO_RESOURCE_LIST) InDesc;
+ OutResourceList = (PIO_RESOURCE_LIST) OutDesc;
+ }
+
+ //
+ // Free input list, and return output list
+ //
+
+ ExFreePool (InCompleteList);
+
+ OutCompleteList->ListSize =
+ (ULONG) ((PUCHAR) OutResourceList - (PUCHAR) OutCompleteList);
+ *pResourceList = OutCompleteList;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxmapio.c b/private/ntos/nthals/halfire/ppc/pxmapio.c
new file mode 100644
index 000000000..383fa1c05
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmapio.c
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a POWER PC
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Map interrupt acknowledge base address
+ Map SIO config base address
+ Remove RTC map - S-FOOT mapsthe RTC into the ISA I/O space
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmapio.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:11:27 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+//
+// Define global data used to locate the IO control space and the PCI config
+// space.
+//
+
+PVOID HalpInterruptBase;
+PVOID HalpPciConfigBase;
+PVOID HalpErrorAddressRegister;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O, planar control, and bus configuration
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map bus/bridge I/O control space
+ //
+
+ if (!HalpMapIoControlSpace())
+ return FALSE;
+
+ //
+ // Map Planar I/O control space
+ //
+
+ if (!HalpMapPlanarSpace())
+ return FALSE;
+
+ //
+ // Map Bus configuration space
+ //
+
+ if (!HalpMapBusConfigSpace())
+ return FALSE;
+
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxmemctl.c b/private/ntos/nthals/halfire/ppc/pxmemctl.c
new file mode 100644
index 000000000..4dc541cad
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmemctl.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmemctl.c $
+ * $Revision: 1.16 $
+ * $Date: 1996/05/14 02:34:41 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "phsystem.h"
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+ return TRUE;
+}
+
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+
+
+ if ( HalpInterruptBase == NULL ) {
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ }
+
+ if ( HalpSystemControlBase == NULL ) {
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = SYSTEM_CONTROL_SPACE;
+ HalpSystemControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ }
+
+ //
+ // Map the error address register
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = ERROR_ADDRESS_REGISTER;
+ HalpErrorAddressRegister = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL || HalpErrorAddressRegister == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map the PCI config space.
+ //
+
+ physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE;
+ HalpPciConfigBase = MmMapIoSpace(physicalAddress,
+ PCI_CONFIG_SIZE,
+ FALSE);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map the PCI config space.
+ //
+
+ HalpPciConfigBase = (PUCHAR)KePhase0MapIo( (PVOID)PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Unmap the PCI config space and set HalpPciConfigBase to NULL.
+ //
+
+ KePhase0DeleteIoMap( (PVOID)PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+ HalpPciConfigBase = NULL;
+
+}
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxmemctl.h b/private/ntos/nthals/halfire/ppc/pxmemctl.h
new file mode 100644
index 000000000..691535694
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmemctl.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmemctl.h $
+ * $Revision: 1.10 $
+ * $Date: 1996/05/14 02:34:45 $
+ * $Locker: $
+ */
+
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Masters systems.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+#ifndef _PXMEMCTL_H
+#define _PXMEMCTL_H
+
+//
+// define physical base addresses of planar
+//
+#define SYSTEM_REGISTER_SPACE 0xff000000 // where the system registers
+ // live
+#define INTERRUPT_PHYSICAL_BASE 0xff000000 // sys interrupt register area
+#define SYSTEM_PCI_CONFIG_BASE 0xff400000 // sys pci config space
+#define ERROR_ADDRESS_REGISTER 0xff000400
+#define ERROR_STATUS_REGISTER 0xff001000
+#define SYSTEM_CONTROL_SPACE 0xff100000 // system control registers
+#define SYSTEM_CONTROL_SIZE 0x2000 // address range covered
+#define DISPLAY_MEMORY_BASE 0x70000000 // display memory start
+#define DISPLAY_MEMORY_SIZE 0x400000 // 4 MB for pro and top
+
+//
+// OFFSETS
+//
+#define INTERRUPT_OFFSET 0x000000 // offset from system base
+#define SYSTEM_CONTROL_OFFSET 0x100000 // offset from system base
+#define IO_MEMORY_PHYSICAL_BASE 0xC0000000 // physical base of IO memory
+
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+// used to be:
+// #define PCI_CONFIG_SIZE PAGE_SIZE * 9 // for FIREPOWER
+// #define PCI_CONFIG_SIZE PAGE_SIZE * 5 // for PPC
+#define PCI_CONFIG_SIZE 0x00800000
+
+#endif // _PXMEMCTL_H
diff --git a/private/ntos/nthals/halfire/ppc/pxmisc.s b/private/ntos/nthals/halfire/ppc/pxmisc.s
new file mode 100644
index 000000000..52ed5c5ec
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmisc.s
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmisc.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:11:46 $
+ * $Locker: $
+ */
+
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxmisc.s
+//
+// Abstract:
+//
+// This module implements miscellaneous routines on the PowerPC.
+//
+// Author:
+//
+// Steve Johns (sjohns@pets.sps.mot.com) August 1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+
+#include "kxppc.h"
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+ LEAF_ENTRY(HalpGetHID0)
+
+ mfspr r.3, HID0
+
+ LEAF_EXIT(HalpGetHID0)
+
+
+
+
+ LEAF_ENTRY(HalpSetHID0)
+
+ mtspr HID0, r.3
+
+ LEAF_EXIT(HalpSetHID0)
+
+
+ LEAF_ENTRY(HalpSetDecrementer)
+
+ mtdec r.3 // Set the DECREMENTER
+
+ LEAF_EXIT(HalpSetDecrementer)
+
+
+
+
+//
+// HalpLockDisplayString
+//
+// This routine implements a lock on the HalDisplayString function
+// to avoid garbling the display when more than one processor attempts
+// to display a string at the same time.
+//
+// r.3 is the address of the lock.
+//
+
+ LEAF_ENTRY(HalpLockDisplayString)
+
+ li r.5, 1
+ lis r.6, 0x99
+LkDis: lwarx r.4, 0, r.3
+ addic. r.6, r.6, -1
+ beq LkSync
+ cmpwi r.4, 0
+ bne- LkDis // jif lock already held
+ stwcx. r.5, 0, r.3 // attempt to take lock
+ sync
+ beqlr+ // return if all was good
+
+//
+// We lost the reserve, allow the other processor a chance to
+// win this argument.
+//
+
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ b LkDis
+
+LkSync:
+ stw r.5, 0(r.3) // Grab the lock anyway
+ LEAF_EXIT(HalpLockDisplayString)
+
+
+
+// ULONG HalpDivide (
+// IN ULARGE_INTEGER Dividend,
+// IN ULONG Divisor)
+//
+// Routine Description:
+//
+// This function divides an unsigned large integer by an unsigned long
+// and returns the resultant quotient and optionally the remainder.
+//
+// N.B. It is assumed that no overflow will occur.
+//
+// Arguments:
+//
+// Dividend (r.3, r.4) - Supplies the dividend value.
+// (High-order bits in r.4, low-order bits in r.3)
+//
+// Divisor (r.5) - Supplies the divisor value.
+//
+// Return Value:
+//
+// The ULONG quotient is returned as the function value.
+//
+//--
+
+
+
+ .set Quotient, r.3
+ .set DividendLo, r.3
+ .set DividendHi, r.4
+ .set Divisor, r.5
+ .set Q1, r.11
+ .set N, r.12
+ .set Q0, N // Use of N & Q0 don't overlap
+
+ LEAF_ENTRY(HalpDivide)
+
+
+ cmplw DividendHi,Divisor
+ bge overflow // catch overflow or division by 0
+ cmplwi DividendHi,0 // test high part for 0
+ bne Divide64Bits
+
+// High 32 bits of Dividend == 0, so use 32 bit division.
+ divwu DividendLo,DividendLo,Divisor // result <- dividend / divisor
+ blr
+
+Divide64Bits:
+
+// Normalize: Shift divisor and dividend left to get rid of leading zeroes
+// in the divisor. Since DividendHi < Divisor, only zeroes are shifted out
+// of the dividend.
+ cntlzw N,Divisor // number of bits to shift (N)
+ slw Divisor,Divisor,N // shift divisor
+ slw DividendHi,DividendHi,N // shift upper part of divisor
+ mr r.8, DividendLo // Save unshifted DividendLo
+ slw DividendLo,DividendLo,N // shift lower part of divisor
+ subfic N,N,32 // 32-N
+ srw N,r.8,N // leftmost N bits of DividendLo, slid right
+ or DividendHi,DividendHi,N // and inserted into low end of DividendHi
+
+// Estimate high-order halfword of quotient. If the dividend is
+// A0 A1 A2 A3 and the divisor is B0 B1 (where each Ai or Bi is a halfword),
+// then the estimate is A0 A1 0000 divided by B0 0000, or A0 A1 divided by B0.
+// (DividendHi holds A0 A1, DividendLo holds A2 A3, and Divisor holds B0 B1.)
+// The estimate may be too high because it does not account for B1; in rare
+// cases, the estimate will not even fit in a halfword. High estimates are
+// corrected for later.
+ srwi r.8,Divisor,16 // r.8 <- B0
+ divwu Q0,DividendHi,r.8 // Q0 <- floor([A0 A1]/B0)
+// Subtract partial quotient times divisor from dividend: If Q0 is the quotient
+// computed above, this means that Q0 0000 times B0 B1 is subtracted from
+// A0 A1 A2 A3. We compute Q0 times B0 B1 and then shift the two-word
+// product left 16 bits.
+ mullw r.9,Q0,Divisor // low word of Q0 times B0 B1
+ mulhwu r.10,Q0,Divisor // high word of Q0 times B0 B1
+ slwi r.10,r.10,16 // shift high word left 16 bits
+ inslwi r.10,r.9,16,16 // move 16 bits from left of low word
+ // to right of high word
+ slwi r.9,r.9,16 // shift low word left 16 bits
+ subfc DividendLo,r.9,DividendLo // low word of difference
+ subfe DividendHi,r.10,DividendHi // high word of difference
+// If the estimate for Q0 was too high, the difference will be negative.
+// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 0000 to A0 A1 A2 A3
+// and decrement Q0 by one to correct for the overestimate.
+ cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
+ bge Q0_okay // no correction needed
+ inslwi r.10,Divisor,16,16 // high word of B0 B1 0000 (= 0000 B0)
+ slwi r.9,Divisor,16 // low word of B0 B1 0000 (= B1 0000)
+adjust_Q0:
+ addc DividendLo,DividendLo,r.9 // add B0 B1 0000 to A0 A1 A2 A3 (low)
+ adde DividendHi,DividendHi,r.10 // add B0 B1 0000 to A0 A1 A2 A3 (high)
+ cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
+ addi Q0,Q0,-1 // decrement Q0
+ blt adjust_Q0 // if A0 A1 A2 A3 still negative, repeat
+Q0_okay:
+// Estimate low-order halfword of quotient. A0 is necessarily 0000 at this
+// point, so if the remaining part of the dividend is A0 A1 A2 A3 then the
+// estimate is A1 A2 0000 divided by B0 0000, or A1 A2 divided by B0.
+// (DividendHi holds A0 A1, DividendLo holds A2 A3, and r.8 holds B0.)
+ slwi r.9,DividendHi,16 // r.9 <- A1 0000
+ inslwi r.9,DividendLo,16,16 // r.9 <- A1 A2
+ divwu Q1,r.9,r.8 // Q1 <- floor([A1 A2]/B0)
+// Subtract partial quotient times divisor from remaining part of dividend:
+// If Q1 is the quotient computed above, this means
+// that Q1 times B0 B1 is subtracted from A0 A1 A2 A3. We compute
+ mullw r.9,Q1,Divisor // low word of Q1 times B0 B1
+ mulhwu r.10,Q1,Divisor // high word of Q1 times B0 B1
+ subfc DividendLo,r.9,DividendLo // low word of difference
+ subfe DividendHi,r.10,DividendHi // high word of difference
+// If the estimate for Q1 was too high, the difference will be negative.
+// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 to A0 A1 A2 A3
+// and decrement Q1 by one to correct for the overestimate.
+ cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
+ bge Q1_okay // no correction needed
+adjust_Q1:
+ addc DividendLo,DividendLo,Divisor // add B0 B1 to A0 A1 A2 A3 (low)
+ addze DividendHi,DividendHi // add B0 B1 to A0 A1 A2 A3 (high)
+ cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
+ addi Q1,Q1,-1 // decrement Q1
+ blt adjust_Q1 // if A0 A1 A2 A3 still negative, repeat
+Q1_okay:
+ slwi Quotient,Q0,16 // Quotient <- Q0 A1
+ or Quotient,Quotient,Q1
+ blr
+
+
+// The error cases:
+overflow:
+ li Quotient, 0 // return(0);
+ LEAF_EXIT(HalpDivide)
+
+
+
+
+// ULARGE_INTEGER HalpMultiply (
+// IN ULONG Multiplicand,
+// IN ULONG Multiplier)
+//
+// Routine Description:
+//
+// This function multiplies two ULONGS and returns a ULARGE_INTEGER product.
+//
+// N.B. It is assumed that no overflow will occur.
+//
+// Arguments:
+//
+// Multiplicand (r.4) - Supplies the multiplicand value.
+//
+// Multiplier (r.5) - Supplies the multiplier value.
+//
+// Return Value:
+//
+// The ULARGE_INTEGER product is returned as the function value.
+//
+
+ .set Multiplicand, r.4
+ .set Multiplier, r.5
+ .set Product, r.3
+
+
+ LEAF_ENTRY(HalpMultiply)
+
+ mullw r.0, Multiplicand, Multiplier // Calculate low 32 bits
+ stw r.0, 0(Product)
+ mulhwu r.0, Multiplicand, Multiplier // Calculate high 32 bits
+ stw r.0, 4(Product)
+
+ LEAF_EXIT(HalpMultiply)
+
diff --git a/private/ntos/nthals/halfire/ppc/pxnatsup.c b/private/ntos/nthals/halfire/ppc/pxnatsup.c
new file mode 100644
index 000000000..94452fcdc
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxnatsup.c
@@ -0,0 +1,90 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxnatsup.c
+
+Abstract:
+
+ The module provides the National SuperIO (PC87311) support for Power PC.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxnatsup.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:11:59 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "pxnatsup.h"
+
+
+
+BOOLEAN
+HalpInitSuperIo (
+ VOID
+ )
+
+
+{
+
+ //
+ // Initialize the National SuperIO chip
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FER_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ FER_PARALLEL_PORT_ENABLE |
+ FER_UART1_ENABLE |
+ FER_UART2_ENABLE |
+ FER_FDC_ENABLE |
+ FER_IDE);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FAR_ACCESS);
+
+ //
+ // LPT2 - irq5, uart1-com1, UART2-com2,
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x10);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ PTR_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x04);
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxnatsup.h b/private/ntos/nthals/halfire/ppc/pxnatsup.h
new file mode 100644
index 000000000..5c30c5a83
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxnatsup.h
@@ -0,0 +1,67 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxnatsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the
+ National (PC87311) SuperIO chip set.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxnatsup.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:12:05 $
+ * $Locker: $
+ */
+
+//
+// SuperIO configuration registers
+//
+
+//
+//index register select
+//
+
+#define FER_ACCESS 0x00
+#define FAR_ACCESS 0x01
+#define PTR_ACCESS 0x02
+
+//
+//FER register bit fields
+//
+
+#define FER_PARALLEL_PORT_ENABLE 0x01
+#define FER_UART1_ENABLE 0x02
+#define FER_UART2_ENABLE 0x04
+#define FER_FDC_ENABLE 0x08
+#define FER_FDD 0x10
+#define FER_FDC_MODE 0x20
+#define FER_IDE 0x30
+#define FER_IDE_MODE 0x40
+
+//
+// Lay the supio control registers onto the I/O control space
+//
+
+typedef struct _NAT_SUPERIO_CONTROL {
+ UCHAR Reserved1[0x398];
+ UCHAR SuperIoIndexRegister; // Offset 0x398
+ UCHAR SuperIoDataRegister; // Offset 0x399
+} NAT_SUPERIO_CONTROL, *PNAT_SUPERIO_CONTROL;
diff --git a/private/ntos/nthals/halfire/ppc/pxnvrsup.h b/private/ntos/nthals/halfire/ppc/pxnvrsup.h
new file mode 100644
index 000000000..d719b05b5
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxnvrsup.h
@@ -0,0 +1,35 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxnvrsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the NVRAM support
+ in a PowerPC System.
+
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxnvrsup.h $
+ * $Revision: 1.8 $
+ * $Date: 1996/05/14 02:34:50 $
+ * $Locker: $
+ */
+
+#include "fpds1385.h"
diff --git a/private/ntos/nthals/halfire/ppc/pxpcibus.c b/private/ntos/nthals/halfire/ppc/pxpcibus.c
new file mode 100644
index 000000000..dd578510f
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpcibus.c
@@ -0,0 +1,2327 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpcibus.c $
+ * $Revision: 1.32 $
+ * $Date: 1996/05/14 02:34:54 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+
+#include "pxidaho.h"
+
+#include "phsystem.h"
+#include "fpio.h"
+#include "stdio.h"
+#include "string.h"
+#include "fpdebug.h"
+
+#define TBS " "
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+extern ULONG HalpAdjustBridge(PBUS_HANDLER, PPCI_COMMON_CONFIG, PCM_RESOURCE_LIST );
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+extern PCI_CONFIG_HANDLER PCIConfigHandlerBridged;
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) HalpPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#endif
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PCI_REGISTRY_INFO FirePCIRegInfo;
+ PPCI_REGISTRY_INFO PCIRegInfo = NULL;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status = STATUS_SEVERITY_INFORMATIONAL;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+
+ //
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ HalDisplayString("HalpInitializePCIBus: ZwOpenKey returned !NT_SUCCESS \n");
+ return;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+ ZwClose (hMFunc);
+ break;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+
+ if(PCIRegInfo == NULL) {
+
+ //
+ // FirePower only has one PCI bus.
+ //
+ PCIRegInfo = &FirePCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism = 1;
+ }
+
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+ HalpDebugPrint("HalpInitializePCIBus: Setting HwType = 2 \n");
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+
+ //
+ // If handler not already built, do it now
+ //
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpDebugPrint("HalpInitializePciBus: Alloc PCI bus: 0x%0x\n",i);
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+
+#if DBG
+ HalpTestPci (0);
+#endif
+ //return;
+}
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpBusData;
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("HalpAllocAndInit: HwType=0x%x, BusNo=%x, TestAlloc=%x\n"
+ ,HwType, BusNo, TestAllocation););
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (FPHAL_BUSNODE) // FirePower hal bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+ if (!Bus) {
+ HalpDebugPrint("HalpAllocAndInit: No bus handler ...\n");
+ return (PBUS_HANDLER) NULL;
+ }
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("HalpAllocateAndInitPciBusHandler:@0x%08x \n", Bus->BusData););
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->TranslateBusAddress = (PTRANSLATEBUSADDRESS) HalpTranslatePCIBusAddress;
+
+ FpBusData = (PFPHAL_BUSNODE) Bus->BusData;
+ BusData = (PPCIPBUSDATA) &(FpBusData->Bus);
+ HDBG(DBG_PCI,
+ HalpDebugPrint("HalpAllocateAndInitPciBusHandler:@0x%08x \n", BusData););
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ FpBusData->HwType = HwType;
+
+ // set defaults
+ BusData->LimitedIO = FALSE;
+ BusData->IOLimit = 0x3F7FFFFF;
+ BusData->MemoryLimit = 0x3EFFFFFF;
+ BusData->GetIrqTable = (PciIrqTable) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&FpBusData->Bus.DeviceConfigured,
+ FpBusData->Bus.ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 0:
+ //
+ // This case allows the hal to initialize buses without setting
+ // any PCIConfigHandler. The confighandlers can then be setup
+ // elsewhere
+ //
+ HalpDebugPrint(" Case 0:...\n");
+ break;
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint(" Case 1:...\n"););
+ RtlCopyMemory ( &(FpBusData->Node),
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+ FpBusData->Bus.MaxDevice = MAXIMUM_PCI_SLOTS -1; // 0 based *BJ*
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory ( &(FpBusData->Node),
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ FpBusData->Bus.MaxDevice = MAXIMUM_PCI_SLOTS -1;
+
+ break;
+ case 3:
+ //
+ // Initialize this bus as a bridged bus: I.E. this pci bus goes
+ // through a bridge.
+ //
+
+ RtlCopyMemory ( &(FpBusData->Node),
+ &PCIConfigHandlerBridged,
+ sizeof (PCIConfigHandler));
+ FpBusData->Bus.MaxDevice = MAXIMUM_PCI_SLOTS -1; // 0 based *BJ*
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unknown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: ULONG HalpGetPCIData ()
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the starting location within config space for requested
+ data. It's an address relative to the start of the config header.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ ULONG Len;
+#if DBG != 0
+ ULONG i, bit;
+#endif
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line ((PBUS_HANDLER) BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+/*++
+
+Routine Description: ULONG HalpSetPCIData ()
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ ULONG Len;
+#if DBG != 0
+ ULONG cnt;
+#endif
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line ((PBUS_HANDLER) BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin ((PBUS_HANDLER) BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ HalpPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PFPHAL_BUSNODE FpNode;
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ //
+ // Pull the "methods" this bus uses to get and set
+ // data. It's now appended to the bus data
+ //
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ FpNode->Node.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PFPHAL_BUSNODE FpNode;
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ FpNode->Node.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ UCHAR HeaderType;
+ ULONG i;
+
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber > BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ i = Slot.u.bits.DeviceNumber;
+
+ if ( !((FpNode->ValidDevs) & ( 1 << i )) ) {
+ //
+ // check the valid devs bitmap and see if this slot
+ // is marked.
+ //
+ //PRNTPCI(HalpDebugPrint("HalpValidPCISlot: Invalid dev (0x%08x) @%x\n",
+ // FpNode->ValidDevs, i));
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &FpNode->Bus;
+ FpNode->Node.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+
+ i = RPciVendorId(0);
+
+ }
+ FpNode->Node.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+// PciCfg1->u.AsULONG = (PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[Slot.u.bits.DeviceNumber];
+ //
+ // The HalpPciConfigBase value just happens to satisfy the requirements of
+ // pci config space addressing: The word written out says this is a write
+ // enabling config space mapping on bus number 1.
+ //
+ // The value pulled out of HalpPciConfigSlot determines the device/function
+ // number and sets the register number ( which of the 32 config space words)
+ // to access
+ //
+ PciCfg1->u.AsULONG = (ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot.u.bits.DeviceNumber];
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber ?
+ Slot.u.bits.DeviceNumber + 10:
+ Slot.u.bits.DeviceNumber ;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_UCHAR ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + i,*Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_USHORT ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + (USHORT) i,*((PUSHORT)Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData,*((PULONG)Buffer));
+ return sizeof(ULONG);
+}
+
+/*++
+
+Routine Description: NTSTATUS HalpAssignPCISlotResources ()
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ PRNTPCI(HalpDebugPrint(
+ "HalpAssignPCISlotResources: BusHandler: 0x%x, Slot: 0x%x\n",
+ (ULONG)BusHandler, (ULONG)Slot ));
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+// PRNTPCI(DbgBreakPoint());
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ (sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2) +
+ PCI_COMMON_HDR_LENGTH * 3;
+ i *= 3;
+
+ //
+ // triple the calculated size just to make sure we don't run out of
+ // space.
+ //
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i -
+ PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i -
+ PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i -
+ PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ HalpDebugPrint("No such device found\n");
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ HalpDebugPrint("No such device of this type: %x \n",
+ PCI_CONFIG_TYPE(PciData));
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+//*BJ* PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and
+ // InterruptLine
+ //
+ BusData->CommonData.Pin2Line ( (PBUS_HANDLER) BusHandler,
+ RootHandler,
+ PciSlot,
+ PciData
+ );
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ } else {
+ PRNTINTR(HalpDebugPrint("%sDevice(%x,%x) has no interrupt resource\n",
+ TBS, Slot, BusNumber));
+ PRNTINTR(HalpDebugPrint("\t\tPciData: 0x%x\n",PciData));
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7ff;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+ PRNTPCI(HalpDebugPrint("PCI: BaseAddress[%d] = %08lx\n", j, i));
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ //
+ // check for hosed PCI configuration requirements:
+ //
+ if (length & ~m) {
+#if DBG
+ HalpPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ HalpPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+ PRNTPCI(HalpDebugPrint("FpNode: 0x%x ( %x:%x )\n",
+ FpNode, FpNode->MemBase,m));
+ if( FpNode->IoTop < m ) {
+ Descriptor->u.Port.MinimumAddress.LowPart =
+ FpNode->IoBase;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ FpNode->IoTop | 0xfff;
+ PRNTINTR(HalpDebugPrint("HalpAssignPciSlot........%x, %x\n",
+ Descriptor->u.Port.MinimumAddress.LowPart,
+ Descriptor->u.Port.MaximumAddress.LowPart));
+ }
+
+ } else {
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ PRNTPCI(HalpDebugPrint("FpNode: 0x%x ( %x:%x )\n",
+ FpNode, FpNode->MemBase,m));
+ if( FpNode->MemTop < m ) {
+ Descriptor->u.Memory.MinimumAddress.LowPart =
+ FpNode->MemBase;
+ Descriptor->u.Memory.MaximumAddress.LowPart =
+ FpNode->MemTop;
+ PRNTPCI(HalpDebugPrint("HalpAssignPciSlot....%x, %x\n",
+ FpNode->MemBase, FpNode->MemTop));
+ }
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ HalpDebugPrint("HalpAssignPCISlotResources: Failed IoAssignResources:%x\n",
+ status);
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin ((PBUS_HANDLER) BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ m = 0;
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m |= PCI_ENABLE_IO_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ m |= PCI_ENABLE_MEMORY_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Set addresses, but do not turn on decodes
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+ if (
+ !(*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) &&
+ Is64BitBaseAddress(*BaseAddress[j])
+ ) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ HalpPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO & Memory decodes (use HalSetBusData since valid settings now set)
+ //
+
+ // Set Bus master bit on for win95 compatibility
+ m |= PCI_ENABLE_BUS_MASTER;
+
+ PciData->Command |= (USHORT) m;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalpPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ HalpPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ HalpPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ HalpPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ HalpPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ HalpPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalpPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ HalpPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ HalpPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ HalpPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ HalpPrint ("\n%02x: ", j + 0x40);
+ }
+ HalpPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ HalpPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ HalpPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ HalpPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ HalpPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ HalpPrint ("\n\n");
+ }
+ }
+ }
+ }
+
+}
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/pxpciint.c b/private/ntos/nthals/halfire/ppc/pxpciint.c
new file mode 100644
index 000000000..960569d0e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpciint.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpciint.c $
+ * $Revision: 1.26 $
+ * $Date: 1996/05/15 00:06:27 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "phsystem.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+#include "fpdebug.h"
+
+ULONG PciAllowedInts = 0;
+
+#define PCI_DEVICE_VECTOR 0x10
+#define PCI_IO_ADDRESS_SPACE 0x81000000
+
+
+ULONG HalpGetPciIntVector( PBUS_HANDLER,
+ PBUS_HANDLER,
+ ULONG,
+ ULONG,
+ PKIRQL,
+ PKAFFINITY );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif
+
+
+/*
+ * HalpGetPciIntVector:
+ * This routine is a mirror ( but better ) version of HalpGetPCIIntOnISABus
+ *
+ */
+
+ULONG
+HalpGetPciIntVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ // since we can't see who's asking for an interrupt, must rely upon some
+ // known data: First, check to see if there is already one specified out
+ // among the pci devices: ( need to keep in mind some stubborn drivers
+ // that request several times for a particular interrupt i.e. scsi ).
+ //
+ // For now, to deal with a screwed up amd scsi driver, permanently map
+ // any requests for f ( as well as d which is what firmware sets this
+ // device to ) to 0x19, corresponding to the bit in our interrupt word.
+ //
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetPciIntVector: %x, %x \n",
+ BusInterruptLevel, BusInterruptVector ););
+
+#if defined(HALDEBUG_ON)
+ if (DBGSET(DBG_INTERRUPTS)) {
+ switch( BusInterruptVector ) {
+ case 0xd:
+ case 0xf:
+ HalpDebugPrint(" BusIntVec set to 0x%x \n",
+ BusInterruptVector);
+ break;
+ case 0xe:
+ HalpDebugPrint(" BusIntVec set to 0x%x \n",
+ BusInterruptVector);
+ break;
+ default:
+ HalpDebugPrint(" BusIntVec unchanged: \n");
+ break;
+ }
+ }
+#endif
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetPCIIntOnIsaBus: 0x%x, 0x%x, %x, %x, %x, %x \n",
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ *Irql,
+ *Affinity ););
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+ //
+ // Check that the requested interrupt is valid and return 0
+ // if the interrupt is not in the allowed set of interrupts.
+ if (((1 << BusInterruptVector) & PciAllowedInts) == 0) {
+ return 0;
+ }
+
+ //
+ //
+ // For FirePOWER, pci interrupts are not mapped onto the isa bus ( with the
+ // exception of the amd ethernet drive which will always believe it's isa )
+ // so for the moment map their "isa" int values so that they're picked up
+ // correctly by HalpGetSystem...
+ //
+ switch( BusInterruptVector ) {
+ case 0xa:
+ //
+ // For now, map this vector back down to ISA level since the
+ // audio driver is confused, thinking it's on the pci bus.
+ //
+ //BusInterruptVector = 0xa - PCI_DEVICE_VECTOR;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sVector is not PCI based vector: 0x%x\n",
+ " ", BusInterruptVector ););
+ break;
+ case 0xd:
+ case 0xf:
+ BusInterruptVector = 0xd +0xc ;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint(" BusIntVect set to 0x19 \n"););
+ break;
+ case 0xe:
+ BusInterruptVector = 0xe +0xc;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint(" BusIntVect set to 0x1a \n"););
+ break;
+ default:
+ break;
+ }
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sBusInterruptVector set to: 0x%x \n",
+ " ", BusInterruptVector););
+ //BusInterruptVector += PCI_DEVICE_VECTOR;
+ BusInterruptLevel = BusInterruptVector;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sBusIntVec set to 0x%x \n",
+ " ", BusInterruptVector););
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+/*++
+
+// Routine Description: VOID HalpPCIPin2ISALine ()
+//
+// This function maps the device's InterruptPin to an InterruptLine
+// value.
+//
+// On Sandalfoot and Polo machines PCI interrupts are statically routed
+// via slot number. This routine just returns and the static routing
+// is done in HalpGetIsaFixedPCIIrq
+//
+
+--*/
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+{
+
+
+}
+
+
+
+/*++
+ Routine Description: VOID HalpPCIISALine2Pin ()
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+
+--*/
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+{
+}
+
+
+/*++
+
+Routine Description: VOID HalpPCIISALine2Pin ()
+
+ Translate PCI bus address.
+ Verify the address is within the range of the bus.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+
+NTSTATUS
+HalpTranslatePCIBusAddress (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+{
+ BOOLEAN status;
+ PPCIPBUSDATA BusData;
+
+ if (BusAddress.HighPart) {
+ return FALSE;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ switch (*AddressSpace) {
+ case MEMORY_ADDRESS_SPACE:
+ //
+ // verify memory address is within PCI buses memory limits
+ //
+ status = BusAddress.LowPart >= BusData->MemoryBase &&
+ BusAddress.LowPart <= BusData->MemoryLimit;
+
+ if (!status) {
+ status = BusAddress.LowPart >= BusData->PFMemoryBase &&
+ BusAddress.LowPart <= BusData->PFMemoryLimit;
+ }
+
+ break;
+ //
+ // Everyone should be assumed IO space if not otherwise requested
+ //
+ default:
+ case IO_ADDRESS_SPACE:
+ //
+ // verify memory address is within PCI buses io limits
+ //
+ status = BusAddress.LowPart >= BusData->IOBase &&
+ BusAddress.LowPart <= BusData->IOLimit;
+ break;
+
+ case SYSTEM_ADDRESS_SPACE:
+// #pragma NOTE("SYSTEM_ADDRESS_SPACE, verify?")
+ status = BusAddress.LowPart < BusData->IOBase &&
+ BusAddress.LowPart >= 0;
+ break;
+
+ }
+
+ if (!status) {
+ return FALSE;
+ }
+
+ //
+ // Valid address for this bus - foreward it to the parent bus
+ //
+
+ return BusHandler->ParentHandler->TranslateBusAddress (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+}
+
+
+/*++
+Routine Description: NTSTATUS HalpAdjustPCIResourceList ()
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ UCHAR IrqTable[255];
+ PFPHAL_BUSNODE FpNode;
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ // BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus);
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+ // ======= Here's where thePCI interrupts are determined and set as a
+ // result of the call to HalpAdjustResourceListLimits
+
+ RtlZeroMemory(IrqTable, sizeof (IrqTable));
+ Status = BusData->GetIrqTable(BusHandler, RootHandler, PciSlot, IrqTable);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ return HalpAdjustResourceListLimits (
+ BusHandler, RootHandler, pResourceList,
+ BusData->MemoryBase, BusData->MemoryLimit,
+ BusData->PFMemoryBase, BusData->PFMemoryLimit,
+ BusData->LimitedIO,
+ BusData->IOBase, BusData->IOLimit,
+ IrqTable, 0xff,
+ 0, 0xffff // dma
+ );
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxpcisup.c b/private/ntos/nthals/halfire/ppc/pxpcisup.c
new file mode 100644
index 000000000..eecaa1e35
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpcisup.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpcisup.c $
+ * $Revision: 1.18 $
+ * $Date: 1996/05/14 02:35:00 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+#include "stdio.h"
+#include "fpdebug.h"
+#include "phsystem.h"
+
+extern PVOID HalpPciConfigBase;
+extern UCHAR PciDevicePrimaryInts[];
+extern ULONG HalpGetPciInterruptSlot( PBUS_HANDLER, PCI_SLOT_NUMBER );
+
+#define LX_PCI_INTERRUPT_ROUTING_SLOT0 25
+#define LX_PCI_INTERRUPT_ROUTING_SLOT1 22
+#define LX_PCI_INTERRUPT_ROUTING_SLOT2 23
+#define LX_PCI_INTERRUPT_ROUTING_SLOT3 26
+#define LX_PCI_INTERRUPT_ROUTING_IDEA 21
+#define LX_PCI_INTERRUPT_ROUTING_IDEB 20
+
+#define PCI_INTERRUPT_ROUTING_SLOT0 0x16 // phys dev# 2, logical 1
+#define PCI_INTERRUPT_ROUTING_SLOT1 0x17 // phys dev# 3, logical 2
+#define PCI_INTERRUPT_ROUTING_SCSI 0x19 // phys dev# 1, logical 3
+#define PCI_INTERRUPT_ROUTING_ETHERNET 0x1a // phys dev# 4, logical 4
+#define IRQ_INVALID 0x0 // goes with IRQ_VALID defines
+
+ULONG HalpPciConfigSlot[] = { 0x0800, // phys dev# 0: SIO chip
+ 0x1000, // phys dev# 1: mobo scsi
+ 0x2000, // phys dev# 2: peripheral plug in
+ 0x4000, // phys dev# 3: peripheral plug in
+ 0x8000 // phys dev# 4: mobo ethernet
+
+ ,0x10000, // IDE_IntA
+ 0x20000 // IDE_IntB
+
+ };
+
+
+
+/*++
+
+Routine Description: ULONG HalpTranslatePciSlotNumber ()
+
+ This routine translate a PCI slot number to a PCI device number.
+ This is a sandalfoot memory map implementation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ UNREFERENCED_PARAMETER(BusNumber);
+
+ return ((ULONG) ((PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[SlotNumber]));
+
+}
+
+
+
+/*++
+
+Routine Description: ULONG HalpPhase0SetPciDataByOffset ()
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+
+ if (SlotNumber < MAXIMUM_PCI_SLOTS) {
+
+ to = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ to += Offset;
+ from = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+
+/*++
+
+Routine Description: ULONG HalpPhase0GetPciDataByOffset ()
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+
+ if (SlotNumber < MAXIMUM_PCI_SLOTS) {
+
+ from = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ from += Offset;
+ to = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+ ULONG slot;
+ ULONG interrupt;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAFixedPCIIrq: %x, %x, %x, %x %x \n",
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH ));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // For Primary PCI slots, the interrupt corresponds to the primary
+ // slot number
+ if ( BusHandler->BusNumber == 0 ) {
+ slot = PciSlot.u.bits.DeviceNumber;
+ }
+ // For Secondary PCI slots, the interrupt corresponds to the slot
+ // number of the primary parent
+ else {
+ slot = HalpGetPciInterruptSlot(BusHandler, PciSlot );
+ }
+
+ // Search the interrupt table for the interrupt corresponding to the slot
+ if (slot < MAXIMUM_PCI_SLOTS) {
+ interrupt = PciDevicePrimaryInts[slot];
+ if (interrupt != INVALID_INT) {
+ IrqTable[interrupt] = IRQ_VALID;
+ } else {
+ return STATUS_UNSUCCESSFUL;
+ }
+ } else {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAFixedPCIIrq: index = 0x%x \n",
+ PciSlot.u.bits.DeviceNumber););
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxpcisup.h b/private/ntos/nthals/halfire/ppc/pxpcisup.h
new file mode 100644
index 000000000..6fd05f401
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpcisup.h
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxpcisup.h
+
+Abstract:
+
+ The module provides the PCI bus interfaces for PowerPC systems.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpcisup.h $
+ * $Revision: 1.10 $
+ * $Date: 1996/01/25 01:11:57 $
+ * $Locker: $
+ */
+
+extern ULONG HalpPciConfigSlot[];
+
+#include "phsystem.h"
+
+// The Maximum number of (Primary) PCI slots on a Firepower board
+#define MAXIMUM_PCI_SLOTS 7
+
+#define INVALID_INT 0xff
+#define INVALID_SLOTNUMBER 0xff
+
+
+typedef struct {
+ USHORT VendorID;
+ USHORT DeviceID;
+ USHORT Command;
+ USHORT Status;
+ UCHAR RevisionID;
+ UCHAR ClassCode[3];
+ UCHAR CacheLineSize;
+ UCHAR LatencyTimer;
+ UCHAR HeaderType;
+ UCHAR BIST;
+ ULONG BaseAddress1;
+ ULONG BaseAddress2;
+ ULONG BaseAddress3;
+ ULONG BaseAddress4;
+ ULONG BaseAddress5;
+ ULONG BaseAddress6;
+ ULONG reserved1;
+ ULONG reserved2;
+ ULONG ROMbase;
+} *PCI_CONFIG;
+
diff --git a/private/ntos/nthals/halfire/ppc/pxport.c b/private/ntos/nthals/halfire/ppc/pxport.c
new file mode 100644
index 000000000..4149cd107
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxport.c
@@ -0,0 +1,855 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxport.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/05/14 02:35:04 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Chuck Bauman 02-Jun-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+ Steve Johns (sjohns@pets.sps.mot.com)
+ - added support for multple baud rates, alternate COM port
+ - implemented KdPortSave & KdPortRestore
+
+--*/
+
+#include "halp.h"
+#include "ppcserp.h"
+#include "pxmemctl.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+ULONG KdCurrentBaudRate= 19200;
+
+extern BOOLEAN HalpPhase0MapIo( VOID );
+ULONG KdCurrentComPort;
+ULONG HalpSavedBaudRate;
+ULONG HalpSavedComPort;
+
+// HalpIoControlBase is extern'd in pxhalp.h which is included in halp.h
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 6;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+
+
+/*++
+
+Routine Description: ULONG HalpGetByte ()
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+
+/*++
+
+Routine Description: BOOLEAN KdPortInitialize ()
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameters - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+{
+
+ UCHAR DataByte;
+/*
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+
+*/
+
+ //
+ // Map I/O space if it has not already been mapped.
+ //
+
+ if (HalpIoControlBase == NULL) {
+ HalpPhase0MapIo();
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+
+ //
+ // Set COM parameters
+ //
+ if (DebugParameters != NULL) {
+ if (DebugParameters->BaudRate == 0)
+ KdCurrentBaudRate = 19200; // default baud rate
+ else
+ KdCurrentBaudRate = DebugParameters->BaudRate;
+
+ if (DebugParameters->CommunicationPort > 2)
+ return (FALSE);
+ KdCurrentComPort = COM1_PORT; // default COM port
+ if (DebugParameters->CommunicationPort == 1)
+ KdCurrentComPort = COM1_PORT;
+ if (DebugParameters->CommunicationPort == 2)
+ KdCurrentComPort = COM2_PORT;
+
+
+ }
+
+ HalpBaudRateDivisor = (UCHAR) ((1843200/16) / KdCurrentBaudRate);
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+
+
+ KdComPortInUse=(PUCHAR)KdCurrentComPort;
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to requested rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: ULONG KdPortGetByte ()
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+
+/*++
+
+Routine Description: ULONG KdPortPollByte ()
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+
+/*++
+
+Routine Description: VOID KdPortPutByte ()
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = (PSP_MODEM_STATUS) READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+
+/*++
+
+Routine Description: VOID KdPortRestore ()
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+KdPortRestore (
+ VOID
+ )
+{
+DEBUG_PARAMETERS ComParams;
+
+ if (HalpSavedComPort != KdCurrentComPort ||
+ HalpSavedBaudRate != KdCurrentBaudRate) {
+ ComParams.CommunicationPort = HalpSavedComPort;
+ ComParams.BaudRate = HalpSavedBaudRate;
+ KdPortInitialize(&ComParams, NULL, TRUE);
+ }
+}
+
+
+/*++
+
+Routine Description: VOID KdPortSave ()
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+KdPortSave (
+ VOID
+ )
+{
+
+ HalpSavedBaudRate = KdCurrentBaudRate;
+ HalpSavedComPort = KdCurrentComPort;
+ return;
+}
+
+
+/*++
+
+Routine Description: SP_LINE_STATUS KdReadLsr ()
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Supplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+
+
+/*++
+
+Routine Description: VOID HalpGetDivisorFromBaud()
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxproc.c b/private/ntos/nthals/halfire/ppc/pxproc.c
new file mode 100644
index 000000000..ca6d2e3f3
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxproc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxproc.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/06/25 02:46:32 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "stdio.h"
+#include "string.h"
+#include "stdlib.h"
+#include "arccodes.h"
+#include "fpreg.h"
+#include "phsystem.h"
+
+
+UCHAR HalName[] = "Powerized HAL";
+
+extern VOID HalpInitializePciBus (VOID);
+VOID HalpInitOtherBuses (VOID);
+ULONG HalpProcessorCount(VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+{
+ PRESTART_BLOCK pRB;
+ ULONG Number;
+ PKPRCB Prcb;
+ char buf[128];
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpStartNextProcessor: called\n"););
+
+
+ //
+ // Check if UNIPROCESSOR is set and ignore all other processors,
+ // this is done in a free HAL so that UP/MP performance measurements
+ // can be taken.
+ //
+ if (HalGetEnvironmentVariable("UNIPROCESSOR", sizeof(buf), buf)
+ == ESUCCESS) {
+ if (_stricmp(buf, "true") == 0) {
+ HalpDebugPrint("HalpStartNextProcessor: UNIPROCESSOR set\n");
+ return FALSE;
+ }
+ }
+
+ //
+ // If there is more than one restart block then this is a multi-
+ // processor system.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+ pRB = SYSTEM_BLOCK->RestartBlock;
+ Number = 0;
+ while (pRB != NULL) {
+ if ((pRB->BootStatus.ProcessorReady == TRUE) &&
+ (pRB->BootStatus.ProcessorStart == FALSE)) {
+
+ //
+ // Assert that we think this is an MP capable machine
+ //
+ if (!(SystemDescription[SystemType].Flags&SYS_MPCAPABLE) ||
+ !(ProcessorDescription[ProcessorType].Flags&PROC_MPCAPABLE)) {
+ HalpDebugPrint("HalStartNextProcessor: HAL/Veneer mismatch\n");
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ RtlZeroMemory(&pRB->u.Ppc, sizeof(PPC_RESTART_STATE));
+
+ //
+ // Set processor start address.
+ //
+ pRB->u.Ppc.Iar = ProcessorState->ContextFrame.Iar;
+ pRB->u.Ppc.Msr = ProcessorState->ContextFrame.Msr;
+
+ //
+ // PowerPC linkage conventions pass parameters in registers
+ // r.3 thru r.10. Set all of them to allow as much flexibility
+ // to the kernel as possible.
+ //
+ pRB->u.Ppc.IntR3 = ProcessorState->ContextFrame.Gpr3;
+ pRB->u.Ppc.IntR4 = ProcessorState->ContextFrame.Gpr4;
+ pRB->u.Ppc.IntR5 = ProcessorState->ContextFrame.Gpr5;
+ pRB->u.Ppc.IntR6 = ProcessorState->ContextFrame.Gpr6;
+ pRB->u.Ppc.IntR7 = ProcessorState->ContextFrame.Gpr7;
+ pRB->u.Ppc.IntR8 = ProcessorState->ContextFrame.Gpr8;
+ pRB->u.Ppc.IntR9 = ProcessorState->ContextFrame.Gpr9;
+ pRB->u.Ppc.IntR10 = ProcessorState->ContextFrame.Gpr10;
+
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = pRB;
+
+ //
+ // ARC interface is waiting for this bit to change
+ // so change it.
+ //
+ pRB->BootStatus.ProcessorStart = TRUE;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalStartNextProcessor: started Cpu (%d)\n",
+ Number););
+ return TRUE;
+ }
+ Number++;
+ pRB = pRB->NextRestartBlock;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted(VOID)
+{
+ PRESTART_BLOCK pRB;
+ ULONG NumCpu=0;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalAllProcessorsStarted: called\n"););
+
+ pRB = SYSTEM_BLOCK->RestartBlock;
+ while (pRB != NULL) {
+ if ((pRB->BootStatus.ProcessorReady == TRUE) &&
+ (pRB->BootStatus.ProcessorStart == FALSE))
+ HDBG(DBG_GENERAL,HalpDebugPrint(
+ "HalAllProcessorsStarted: NT disabled processor %d\n",NumCpu););
+ NumCpu++;
+ pRB = pRB->NextRestartBlock;
+ }
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalAllProcessorsStarted: return TRUE\n"););
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage(VOID)
+{
+ extern VOID HalpSetUpFirePowerRegistry(VOID);
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ interfacetype = Internal;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage(&UHalName, interfacetype);
+
+ interfacetype = Isa;
+ HalpReportResourceUsage (&UHalName, interfacetype);
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+ HalpInitializePciBus ();
+
+
+ HalpSetUpFirePowerRegistry(); // in fprgstry.c
+}
+
+ULONG
+HalpProcessorCount()
+{
+ PRESTART_BLOCK pRB;
+ static ULONG Count = 0;
+
+ if (Count)
+ return(Count);
+
+ pRB = SYSTEM_BLOCK->RestartBlock;
+ while (pRB != NULL) {
+ if ((pRB->BootStatus.ProcessorReady == TRUE) &&
+ (pRB->BootStatus.ProcessorStart == TRUE))
+ Count++;
+ pRB = pRB->NextRestartBlock;
+ }
+ return Count;
+}
+
+VOID
+HalpInitOtherBuses(VOID)
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxprof.c b/private/ntos/nthals/halfire/ppc/pxprof.c
new file mode 100644
index 000000000..ee3ed4532
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxprof.c
@@ -0,0 +1,277 @@
+
+/*****************************************************************************
+
+Copyright (c) 1993 Motorola Inc.
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ PXPROF.C
+
+Abstract:
+
+ This implements the HAL profile functions:
+
+ HalSetProfileInterval
+ HalStartProfileInterrupt
+ HalStopProfileInterrupt
+ HalCalibratePerformanceCounter
+ HalpProfileInterrupt
+
+
+Author:
+
+ Steve Johns 11-Feb-1994
+
+Revision History:
+ Changed from using the DECREMENTER to 8254 Timer 1 10-Feb-94
+
+******************************************************************************/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxprof.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:13:00 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+
+#define TIMER ((PEISA_CONTROL)HalpIoControlBase)
+#define TIMER0_COMMAND (COMMAND_8254_COUNTER0 + COMMAND_8254_RW_16BIT + COMMAND_8254_MODE2)
+
+ULONG HalpMaxProfileInterval = 540000; // 54 ms maximum
+ULONG HalpMinProfileInterval = 10000; // 1 ms minimum
+ULONG HalpProfileCount;
+BOOLEAN HalpProfilingActive = FALSE;
+ULONG HalpProfileInts = 0;
+
+
+VOID HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine unmasks IRQ0 at the master interrupt controller,
+ enabling the profile interrupt.
+
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding
+ the profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = TRUE;
+ //
+ // Unmasks IRQ 0 (Timer 1)
+ //
+ HalEnableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL, Latched);
+ }
+
+}
+
+
+
+
+
+
+ULONG HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval, rounded to the nearest 100ns units.
+
+--*/
+
+{
+ ULONG ActualInterval;
+ LARGE_INTEGER BigNumber;
+
+ //
+ // Clamp the requested profile interval between the minimum and
+ // maximum supported values.
+ //
+ if (Interval < HalpMinProfileInterval)
+ Interval = HalpMinProfileInterval;
+ else
+ if (Interval > HalpMaxProfileInterval)
+ Interval = HalpMaxProfileInterval;
+ //
+ // Compute Timer 1 counts for requested interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(Interval, TIMER_CLOCK_IN);
+
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber, 10000000, NULL);
+ HalpProfileCount = BigNumber.LowPart;
+
+ //
+ // Program Timer 1 to Mode 2 & program the timer count register.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount >> 8));
+ //
+ // Compute actual interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(HalpProfileCount, 10000000);
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber,TIMER_CLOCK_IN, NULL);
+ ActualInterval = BigNumber.LowPart;
+
+ return (ActualInterval);
+}
+
+
+
+
+BOOLEAN HalpHandleProfileInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+
+ if (HalpProfilingActive)
+ KeProfileInterrupt(TrapFrame);
+
+ return (TRUE);
+}
+
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+)
+
+/*++
+
+Routine Description:
+
+ This routine masks IRQ 0 (Timer 1) at the interrupt controller, thereby
+ stopping profile interrupts.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = FALSE;
+
+ //
+ // Program Timer 1 to Mode 2 & program the LSB of the timer.
+ // That should keep it from interrupting in case IRQ0 accidently
+ // gets enabled.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+
+
+ //
+ // Mask IRQ 0 (Timer 1)
+ //
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+ }
+
+}
+
+
+
+
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Zero the Time Base registers
+ //
+
+ HalpZeroPerformanceCounter();
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxreturn.c b/private/ntos/nthals/halfire/ppc/pxreturn.c
new file mode 100644
index 000000000..d9456cf41
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxreturn.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxreturn.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/05/14 02:35:12 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Keyboard mapping code was ported to PPC.
+ This function is currently a stub since our firmware is big endian
+
+--*/
+
+#include "halp.h"
+#include "phsystem.h"
+
+//
+// Define keyboard registers structure.
+//
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KEYBOARD_CONTROL_SPACE 0x80000000
+#define KBD_DATA_PORT 0x60
+#define KBD_COMMAND_PORT 0x64
+#define KBD_IBF_MASK 2 // input buffer full mask
+#define KBD_OBF_MASK 1 // Output buffer full mask
+
+#define KbdGetStatus() \
+ (READ_REGISTER_UCHAR(ControlSpace + KBD_COMMAND_PORT))
+#define KbdStoreCommand(Byte) \
+ WRITE_REGISTER_UCHAR(ControlSpace + KBD_COMMAND_PORT, Byte)
+#define KbdStoreData(Byte) \
+ WRITE_REGISTER_UCHAR(ControlSpace + KBD_DATA_PORT, Byte)
+#define KbdGetData() \
+ (READ_REGISTER_UCHAR(ControlSpace + KBD_DATA_PORT))
+
+#define KbdWriteSequence(_cmd, _data) { \
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { \
+ /* Do Nothing */ \
+ } \
+ KbdStoreCommand((_cmd)); \
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { \
+ /* Do Nothing */ \
+ } \
+ KbdStoreData((_data)); \
+}
+
+#define KbdReadSequence(_cmd, _pdata) { \
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { \
+ /* Do Nothing */ \
+ } \
+ KbdStoreCommand((_cmd)); \
+ while ((KbdGetStatus() & KBD_OBF_MASK) == 0) { \
+ /* Do Nothing */ \
+ } \
+ (*(_pdata)) = KbdGetData(); \
+}
+
+VOID
+HalpPowerPcReset(
+ VOID
+ );
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ //
+ // Disable Interrupts.
+ //
+ HalpDisableInterrupts();
+
+ //
+ // Perform an appropriate action for each request type
+ //
+ switch (Routine) {
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+ // Reset using 8042 keyboard command
+ HalpResetByKeyboard();
+
+ /* Fall Through to Hang */
+ case HalHaltRoutine:
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ /* Do Nothing */
+ }
+
+ default:
+ HalpDebugPrint("HalReturnToFirmware: invalid argument\n");
+ for (;;) {
+ /* Do Nothing */
+ }
+ }
+}
+
+VOID
+HalpResetByKeyboard( VOID )
+{
+ PHYSICAL_ADDRESS physicalAddress;
+ PUCHAR ControlSpace;
+ UCHAR data;
+
+
+ //
+ // First job is to map the Keyboard registers into a virtual
+ // address.
+ //
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = KEYBOARD_CONTROL_SPACE;
+ ControlSpace = (PUCHAR)MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ //
+ // Flush Keyboard Output Buffer (throw away data)
+ // Delay Loop (Wait for 8 milliseconds)
+ //
+ KeStallExecutionProcessor(8000);
+ while ((KbdGetStatus() & KBD_OBF_MASK) != 0) {
+ KbdGetData();
+ //
+ // Delay Loop (Wait for 8 milliseconds)
+ //
+ KeStallExecutionProcessor(8000);
+ };
+
+ //
+ // Disable auxillary device
+ //
+ KbdStoreCommand(0xa7);
+
+ //
+ // Disable Keyboard
+ //
+ KbdStoreCommand(0xad);
+
+ //
+ // Disable Chip Level Interrupts for Mouse and Keyboard
+ //
+ KbdReadSequence(0x20, &data);
+ data |= 0x30;
+ data &= 0xfc;
+ KbdWriteSequence(0x60, data);
+
+ //
+ // Request the reset
+ //
+ KbdWriteSequence(0xb8, 0x1e);
+ KbdWriteSequence(0xbd, 0x48);
+ KbdWriteSequence(0xbe, 0x1);
+ KbdWriteSequence(0xca, 0x1);
+
+ //
+ // Now wait forever for the reset to happen
+ //
+ for (;;) {
+ /* Do Nothing */
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxrtcsup.h b/private/ntos/nthals/halfire/ppc/pxrtcsup.h
new file mode 100644
index 000000000..bb8050454
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxrtcsup.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxrtcsup.h $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:35:17 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxrtcsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef PXRTCSUP_H
+#define PXRTCSUP_H
+
+#include "fpds1385.h"
+
+#endif // PXRTCSUP_H
diff --git a/private/ntos/nthals/halfire/ppc/pxs3.h b/private/ntos/nthals/halfire/ppc/pxs3.h
new file mode 100644
index 000000000..2b463c359
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxs3.h
@@ -0,0 +1,770 @@
+/*++
+
+Copyright (c) 1992 ACER Labs Inc.
+
+Module Name:
+
+ pxs3.h
+
+Abstract:
+
+ This header file defines the S3 86C911 GUI accelerator registers.
+
+Author:
+
+ Version 1.0 Kevin Chen 2-Apr-1992
+ Version 2.0 Andrew Chou Nov-24-1992
+ Version 3.0 Jess Botts Oct-06-1993 Power PC Initial Version
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxs3.h $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:13:27 $
+ * $Locker: $
+ */
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+UCHAR DAC_Table[64] = {
+ // DAC for mode 3
+ 0,16, 4,20, 1,17, 5,21,
+ 32,48,36,52,33,49,37,53,
+ 8,24,12,28, 9,25,13,29,
+ 40,56,44,60,41,57,45,61,
+ 2,18, 6,22, 3,19, 7,23,
+ 34,50,38,54,35,51,39,55,
+ 10,26,14,30,11,27,15,31,
+ 42,58,46,62,43,59,47,63
+ };
+
+UCHAR DAC_Color[4] = {0x00, 0x2a, 0x15, 0x3f};
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+// HalpIoControlBase is extern'd in pxhalp.h which is included by halp.h
+
+//
+// Define S3 register I/O Macros
+//
+
+//=============================================================================
+//
+// IBMBJB Changed the semicolons separating statements in the write macros to
+// commas so that if the macro is used as the only statement in a loop
+// all of the statements in the macro will be part of the loop.
+//
+// Commas were used instead of putting braces around the statements
+// because if the macro is used in the true part of a conditional the
+// braces will cause the compiler to generate a syntax error.
+
+#define WRITE_S3_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_S3_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_S3_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_S3_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//=============================================================================
+
+#define DISPLAY_BITS_PER_PIXEL 8 // display bits per pixel
+#define NUMBER_OF_COLORS 256 // number of colors
+
+#define CURSOR_WIDTH 64 // width of hardware cursor
+#define CURSOR_HEIGHT 64 // height of hardware cursor
+#define CURSOR_BITS_PER_PIXEL 2 // hardware cursor bits per pixel
+
+//
+// S3 86C911 GUI, accelerator Video Controller Definitions.
+//
+// Define video register format.
+//
+#define PosID_LO 0x100 // R/W
+#define PosID_HI 0x101 // R/W
+#define Setup_OP 0x102 // R/W
+#define Chck_Ind 0x105 // R
+#define Mono_3B4 0x3B4 // R/W
+#define Mono_3B5 0x3B5 // R/W
+#define MDA_Mode 0x3B8 // W
+#define HGC_SLPEN 0x3B9 // R/W
+#define Stat1_MonoIn 0x3BA // R
+#define FC_MonoW 0x3BA // W
+#define HGC_CLPEN 0x3BB // W
+#define HGC_Config 0x3BF // W
+#define Attr_Index 0x3C0 // R/W
+#define Attr_Data 0x3C0 // R/W
+#define Stat0_In 0x3C2 // R
+#define MiscOutW 0x3C2 // W
+#define VSub_EnB 0x3C3 // R/W
+#define Seq_Index 0x3C4 // R/W
+#define Seq_Data 0x3C5 // R/W
+#define DAC_Mask 0x3C6 // R/W
+#define DAC_RIndex 0x3C7 // W
+#define DAC_Status 0x3C7 // W
+#define DAC_WIndex 0x3C8 // R/W
+#define DAC_Data 0x3C9 // R/W
+#define FC_Read 0x3CA // R
+#define MiscOutR 0x3CC // R
+#define GC_Index 0x3CE // R/W
+#define GC_Data 0x3CF // R/W
+#define S3_3D4_Index 0x3D4 // R/W
+#define S3_3D5_Data 0x3D5 // R/W
+
+#define CGA_Mode 0x3D8 // W
+#define CGA_Color 0x3D9 // W
+#define Stat1_In 0x3DA // R
+#define FC_Write 0x3DA // W
+#define CLPEN 0x3DB
+#define SLPEN 0x3DC
+
+//
+// Define Enhanced registers for S3_86C911
+//
+
+#define SUBSYS_STAT 0x42E8 // R
+#define SUBSYS_CNTL 0x42E8 // W
+#define SUBSYS_ENB 0x46E8 // R/W
+#define ADVFUNC_CNTL 0x4AE8 // W
+#define CUR_Y 0x82E8 // R/W
+#define CUR_X 0x86E8 // R/W
+#define DESTY 0x8AE8 // W
+#define AXIAL_STEP 0x8AE8 // W
+#define DESTX 0x8EE8 // W
+#define DIAG_STEP 0x8EE8 // W
+#define ERR_TERM 0x92E8 // R
+#define MAJ_AXIS_PCNT 0x96E8 // W
+#define RWIDTH 0x96E8 // W
+#define GP_STAT 0x9AE8 // R
+#define DRAW_CMD 0x9AE8 // W
+#define SHORT_STROKE 0x9EE8 // W
+#define BKGD_COLOR 0xA2E8 // W
+#define FRGD_COLOR 0xA6E8 // W
+#define WRITE_MASK 0xAAE8 // W
+#define READ_MASK 0xAEE8 // W
+#define BKGD_MIX 0xB6E8 // W
+#define FRGD_MIX 0xBAE8 // W
+#define MULTIFUNC_CNTL 0xBEE8 // W
+#define RHEIGHT 0xBEE8 // W
+#define PIX_TRANS 0xE2E8 // W
+
+
+//
+// Define Attribute Controller Indexes : ( out 3C0, Index )
+//
+
+#define PALETTE0 0
+#define PALETTE1 1
+#define PALETTE2 2
+#define PALETTE3 3
+#define PALETTE4 4
+#define PALETTE5 5
+#define PALETTE6 6
+#define PALETTE7 7
+#define PALETTE8 8
+#define PALETTE9 9
+#define PALETTE10 10
+#define PALETTE11 11
+#define PALETTE12 12
+#define PALETTE13 13
+#define PALETTE14 14
+#define PALETTE15 15
+#define ATTR_MODE_CTRL 16
+#define BORDER_COLOR 17
+#define COLOR_PLANE_ENABLE 18
+#define HORI_PIXEL_PANNING 19
+#define PIXEL_PADDING 20
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Define Graphics Controller Index ( out 3CE, Index )
+//
+
+#define SET_RESET 0
+#define ENABLE_SET_RESET 1
+#define COLOR_COMPARE 2
+#define DATA_ROTATE 3
+#define READ_PLANE_SELECT 4
+#define GRAPHICS_CTRL_MODE 5
+#define MEMORY_MAP_MODE 6
+#define COLOR_DONT_CARE 7
+#define BIT_MASK 8
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA S3 Indexes
+//
+#define S3R0 0x30
+#define S3R1 0x31
+#define S3R2 0x32
+#define S3R3 0x33
+#define S3R4 0x34
+#define S3R5 0x35
+#define S3R6 0x36
+#define S3R7 0x37
+#define S3R8 0x38
+#define S3R9 0x39
+#define S3R0A 0x3A
+#define S3R0B 0x3B
+#define S3R0C 0x3C
+#define SC0 0x40
+#define SC2 0x42
+#define SC3 0x43
+#define SC5 0x45
+
+//
+// Define System Control Indexes
+//
+#define SYS_CNFG 64
+#define SOFT_STATUS 65
+#define MODE_CTRL 66
+#define EXT_MODE 67
+#define HGC_MODE 69
+#define HGC_ORGX0 70
+#define HGC_ORGX1 71
+#define HGC_ORGY0 72
+#define HGC_ORGY1 73
+#define HGC_YSTART0 76
+#define HGC_YSTART1 77
+#define HGC_DISPX 78
+#define HGC_DISPY 79
+
+#define ENABLE_HARDWARE_CURSOR 1
+#define DISABLE_HARDWARE_CURSOR 0
+
+//
+// define advanced function control register structure
+//
+#define RES_640x480 0
+#define RES_1024x768 1
+#define RES_800x600 1
+
+#define ENABLE_VGA 6
+#define ENABLE_ENHANCED 7
+
+//
+// define draw command register values
+//
+#define NOP_COMMAND 0x0
+#define DRAW_LINE_COMMAND 0x2000
+#define RECTANGLE_FILL_COMMAND 0x4000
+#define BITBLT_COMMAND 0xc000
+#define BYTE_SWAP 0x1000
+#define NO_BYTE_SWAP 0x0
+#define SIXTEEN_BIT_BUS 0x0200
+#define EIGHT_BIT_BUS 0x0
+#define WAIT 0x0100
+#define NO_WAIT 0x0
+#define R0 0x0
+#define R45 0x20
+#define R90 0x40
+#define R135 0x60
+#define R180 0x80
+#define R225 0xa0
+#define R270 0xc0
+#define R315 0xe0
+#define XMAJ 0x0
+#define YMAJ 0x40
+#define XPositive 0x20
+#define YPositive 0x80
+#define XNegative 0x0
+#define YNegative 0x0
+
+#define DRAW_YES 0x10
+#define DRAW_NO 0x0
+#define RADIAL 8
+#define XY_BASE 0
+#define LAST_PIXEL_OFF 4
+#define LAST_PIXEL_ON 0
+#define MULTIPLE_PIXEL 2
+#define SINGLE_PIXEL 0
+#define DRAW_READ 0
+#define DRAW_WRITE 1
+
+#define SSV_DRAW 0x1000
+#define SSV_MOVE 0x0
+
+#define OneEmpty 0x80
+#define TwoEmpty 0x40
+#define ThreeEmpty 0x20
+#define FourEmpty 0x10
+#define FiveEmpty 0x8
+#define SixEmpty 0x4
+#define SevenEmpty 0x2
+#define EightEmpty 0x1
+
+#define BACKGROUND_COLOR 0
+#define FOREGROUND_COLOR 0x20
+#define CPU_DATA 0x40
+#define DISPLAY_MEMORTY 0x60
+#define NOT_SCREEN 0
+#define LOGICAL_ZERO 1
+#define LOGICAL_ONE 2
+#define LEAVE_ALONE 3
+#define NOT_NEW 4
+#define SCREEN_XOR_NEW 5
+#define NOT_SCREEN_XOR_NEW 6
+#define OVERPAINT 7 //( NEW )
+#define NOT_SCREEN_OR_NOT_NEW 8
+#define SCREEN_OR_NOT_NEW 9
+#define NOT_SCREEN_OR_NEW 10
+#define SCREEN_OR_NEW 11
+#define SCREEN_AND_NEW 12
+#define NOT_SCREEN_AND_NEW 13
+#define SCREEN_AND_NOT_NEW 14
+#define NOT_SCREEN_AND_NOT_NEW 15
+
+#define BEE8_1H 1
+#define BEE8_2H 2
+#define BEE8_3H 3
+#define BEE8_4H 4
+#define BEE8_0H 0
+#define L_CLIP 0x1000
+#define R_CLIP 0x2000
+#define B_CLIP 0x3000
+#define T_CLIP 0x4000
+
+#define DATA_EXTENSION 0xa000 // 10100000B
+#define CPU_EXT 0x80
+#define DISPLAY_EXT 0xc0
+#define NO_EXTENSION 0x0
+#define PACK_DATA 0x4
+#define NO_PACK_DATA 0x0
+#define SET_THIS_BIT_TO_ZERO 0;
+
+//
+// Define bits per pixel codes.
+//
+#define ONE_BIT_PER_PIXEL 0 // 1-bit per pixel
+#define TWO_BITS_PER_PIXEL 1 // 2-bits per pixel
+#define FOUR_BITS_PER_PIXEL 2 // 4-bits per pixel
+#define EIGHT_BITS_PER_PIXEL 3 // 8-bits per pixel
+
+//
+// Define address step value.
+//
+#define ADDRESS_STEP_INCREMENT 1 // vram transfer address increment
+
+//
+// Define cross hair thickness values.
+//
+#define ONE_PIXEL_THICK 0x0 // one pixel in thickness
+#define THREE_PIXELS_THICK 0x1 // three pixels in thickness
+#define FIVE_PIXELS_THICK 0x2 // five pixels in thickness
+#define SEVEN_PIXELS_THICK 0x3 // seven pixels in thickness
+
+//
+// Define multiplexer control values.
+//
+#define ONE_TO_ONE 0x0 // 1:1 multiplexing
+#define FOUR_TO_ONE 0x1 // 4:1 multiplexing
+#define FIVE_TO_ONE 0x2 // 5:1 multiplexing
+
+//
+// Define cursor origin values.
+//
+
+#define CURSOR_X_ORIGIN (((2*HORIZONAL_SYNC_VALUE)+BACK_PORCH_VALUE)*4-36)
+#define CURSOR_Y_ORIGIN ((VERTICAL_BLANK_VALUE/2)+24)
+
+ULONG HotspotX, HotspotY;
+
+// Extended VGA BIOS
+#define SUPER_VGA_SUPPORT 4FH
+#define RET_EXT_VGA_INFO 00H
+#define RET_EXT_VGA_MODE_INFO 01H
+#define SET_EXT_VGA_MODE 02H
+#define QUERY_CUR_EXT_VGA_MODE 03H
+
+#define SAVE_RESTORE_FUNCTION 04H
+// Function 04.0 Query Save/Restore Buffer Size
+#define GET_SAVE_BUFFER_SIZE 00H
+// Function 04.1 Save Extended Video state
+#define SAVE_STATE 01H
+// Function 04.2 Restore Extended VGA state
+#define RESTORE_STATE 02H
+
+#define WINDOWS_CONTROL 05H
+// Function 05.0 Set Window Control
+#define SELECT_PAGE_TO_BE_MAPPED 00H
+// fUNCTION 05.1 Get Window Control Setting
+#define GET_PAGE_MAPPED 01H
+
+#define SET_RESET_DUAL_DISPLAY_MODE FFH
+
+BOOLEAN ColorMonitor;
+PVOID S3_3x4, S3_3x5;
+UCHAR VideoParam[62] = {
+// Mode +3 480 Lines
+// External Registers 3C3, 3C2
+0x01,0x67,
+
+//=============================================================================
+//
+// IBMBJB changed value at offset 17 (5th number on second line) from 0x8e
+// to 0xae to disable the vertical retrace interrupt
+
+// CRT Controller Registers 3D4, 3D5
+0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,
+// 0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+ 0x00,0x00,0x00,0x9c,0xae,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+
+//=============================================================================
+
+// Sequencer Registers 3C4, 3C5
+// 0x01,0x01,0x03,0x00,0x02,
+0x01,0x20,0x03,0x00,0x02,
+
+// Graphic Control Registers
+0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff,
+
+// Attribute Controller Registers
+0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,
+0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00};
+
+
+UCHAR VGAFont8x16[4096] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00
+0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7E,0xFF,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // 8
+0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, // 9
+0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, // a
+0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, // 10
+0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, // 4
+0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 20
+0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // 1
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x18,0x18,0x7C,0xC6,0xC2,0x7C,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 30
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // b
+0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // 40
+0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 50
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // d
+0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, // f
+
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 60
+0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00, // 7
+0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // a
+0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 70
+0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, // 80
+0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, // 7
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // d
+0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // 90
+0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 8
+0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, // b
+0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, // f
+
+0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a0
+0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 1
+0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // 4
+0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 5
+0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, // b
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, // c
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // b0
+0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // 1
+0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // a
+0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // f
+
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c0
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // c
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // e
+0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d0
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 2
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // a
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // c
+0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // d
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // e
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, // e0
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00, // 1
+0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, // f0
+0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, // 3
+0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, // b
+0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // f
+ };
diff --git a/private/ntos/nthals/halfire/ppc/pxsiosup.c b/private/ntos/nthals/halfire/ppc/pxsiosup.c
new file mode 100644
index 000000000..39f42166f
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsiosup.c
@@ -0,0 +1,1866 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsiosup.c $
+ * $Revision: 1.38 $
+ * $Date: 1996/05/14 02:35:22 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsiosup.c
+
+Abstract:
+
+ The module provides the PCI ISA bridge support.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "bugcodes.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpcpu.h"
+
+extern BOOLEAN HalpHandleIpiInterrupt(PKINTERRUPT, PVOID);
+
+//
+// TODO:
+// 1) Move to PCR
+// 2) Put on cache line boundaries for peformance (i.e. don't
+// cache thrash.
+//
+#define MAX_CPU 32
+ULONG registeredInts[MAX_CPU] = {0};
+
+
+#define TBS " "
+#define SioId 0x04848086
+#define AMD_ENET 0x20001022
+#define AMD_SCSI 0x20201022
+#define ESCId 0x04828086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern ULONG BugLvl;
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+//
+// Declare the interrupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interrupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interrupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+
+//
+// Define Isa bus interrupt affinity.
+//
+
+KAFFINITY HalpIsaBusAffinity;
+
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpInitializeInterrupts ()
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+{
+ ULONG Vector;
+
+ HDBG(DBG_BREAK,
+ HalpDebugPrint("HalpInitializeInterrupts: Calling Break\n"););
+ HDBG(DBG_BREAK, DbgBreakPoint(););
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+ HalpDisableInterrupts();
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpCreateSioStructures ()
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+{
+
+ UCHAR DataByte;
+
+ // We have no interrupt handlers setup; make sure interrupts are
+ // disabled. (No need to re-enable them)
+ HalpDisableInterrupts();
+ //
+ // Initialize the IPI for processor zero:
+ // Connect the IPI interrupt handler directly to the CPU dispatch table
+ // without registering with the kernel.
+ //
+ PCR->InterruptRoutine[DEVICE_VECTORS + 31] =
+ (PKINTERRUPT_ROUTINE) HalpHandleIpiInterrupt;
+
+ //
+ // register the interrupt vector with the HAL
+ //
+ HalpRegisterVector(InternalUsage,
+ DEVICE_VECTORS + 31,
+ DEVICE_VECTORS + 31,
+ HIGH_LEVEL);
+
+ //
+ // Now enable the IPI interrupt on this CPU; the HAL must do this
+ // directly since we did not register with the kernel.
+ // We cannot call HalEnableSystemInterrupt because the irql masks have
+ // not been set up. Interrupts are disabled anyway.
+ //
+ HalpEnableSioInterrupt(DEVICE_VECTORS + 31, Latched);
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt;
+ // PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ // HalpFieldExternalInterrupt;
+ // PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ // HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt;
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+ PHalpInterruptSetup();
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber, Tval, bleah;
+ ULONG ChipId=0, DevInt=0, EvInt=0, AChipId=0;
+ UCHAR PCIReg;
+ ULONG BufferLength;
+
+
+ //
+ // Save off the interrupt mask for this cpu and then block all interrupts
+ // from coming through while probing the PCI bus. Decrementer is still
+ // enabled.
+ //
+ Tval = RInterruptMask(GetCpuId());
+ RInterruptMask(GetCpuId()) = 0x0;
+ WaitForRInterruptMask(GetCpuId());
+ rInterruptRequest = 0xffffffff;
+ FireSyncRegister();
+
+ Found = FALSE;
+ SlotNumber = 0;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpInitPciIsaBridge:.......................\n"););
+ while (!Found && SlotNumber<MAXIMUM_PCI_SLOTS) {
+ BufferLength = HalGetBusData(PCIConfiguration, // bus type
+ 0, // bus number
+ SlotNumber, // "Slot"
+ (PULONG)&ChipId,
+ sizeof(ChipId));
+ switch( ChipId ) {
+ case SioId:
+ PRNTGENRL(HalpDebugPrint(
+ "HalpInitPciIsaBridge: Found the SIO chip...\n"));
+ Found = TRUE;
+ break;
+ // TX_PROTO: to make life interesting, use a different bridge chip
+ case ESCId:
+ PRNTGENRL(HalpDebugPrint(
+ "HalpInitPciIsaBridge: Found the ESC chip...\n"));
+ Found = TRUE;
+ break;
+ case AMD_ENET:
+ DevInt &= 0xffffff00;
+ DevInt |= 0x0000000e;
+ WRITE_REGISTER_ULONG( (
+ ((PUCHAR)HalpPciConfigBase
+ +(0x800 << SlotNumber)) + 0x3c ),
+ DevInt);
+ FireSyncRegister();
+ HalSweepDcache();
+ DevInt = READ_REGISTER_ULONG(
+ ((PUCHAR)HalpPciConfigBase +
+ (0x800 << SlotNumber)) + 0x3c );
+ PRNTINTR(HalpDebugPrint("%sFound Amd Enet: DevInt: 0x%x \n",
+ " ", DevInt ););
+ break;
+ case AMD_SCSI:
+ DevInt &= 0xffffff00;
+ DevInt |= 0x00000016;
+ WRITE_REGISTER_ULONG( (
+ ((PUCHAR)HalpPciConfigBase +
+ (0x800 << SlotNumber)) + 0x3c ),
+ DevInt);
+ FireSyncRegister();
+ HalSweepDcache();
+ DevInt = READ_REGISTER_ULONG(
+ ((PUCHAR)HalpPciConfigBase +
+ (0x800 << SlotNumber)) + 0x3c );
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sFound Amd scsi: DevInt: 0x%x \n",
+ TBS,DevInt ););
+ break;
+ default:
+ PRNTINTR(HalpDebugPrint("%sUnknown Device, ChipId = 0x%08x\n",
+ TBS, ChipId ));
+ break;
+ }
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Clear out any pci bus errors which occurred due to the probing of
+ // non-existent devices:
+ //
+ rPCIBusErrorCause = 0xffffffff;
+ bleah = rTscStatus0;
+ FireSyncRegister();
+
+ //
+ // Restore the mask as we found it on the way into this routine...
+ //
+ RInterruptMask(GetCpuId()) = Tval;
+ WaitForRInterruptMask(GetCpuId());
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("ChipId = %x, SLotNumber = %x \n",ChipId, SlotNumber););
+
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found) {
+ HalDisplayString("HalpInitPciIsaBridge: sio not found \n");
+ // return FALSE;
+ }
+
+
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalGetBusDataByOffset( \
+ PCIConfiguration, \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalSetBusDataByOffset( \
+ PCIConfiguration, \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ // READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+ // These must be BYTE reads and writes to avoid unintentionally writing
+ // other registers
+ PCIReg = READ_REGISTER_UCHAR(((PUCHAR)HalpPciConfigBase + (0x800)) + 0x40);
+
+ // Setup the PCI Control
+ PCIReg |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+ // WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+ WRITE_REGISTER_UCHAR((((PUCHAR)HalpPciConfigBase + (0x800)) + 0x40),
+ PCIReg);
+ //
+ // Disable Guaranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo()) {
+ HalDisplayString("Failed to init SuperIo\n");
+ return FALSE;
+ }
+
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpMapIoControlSpace ()
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+
+
+
+/*++
+
+Routine Description: VOID HalpDisableSioInterrupt()
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+{
+ UCHAR CpuId;
+
+ // Make sure we've been called with interrupts disabled....
+ //
+ HASSERT(!MSR(EE));
+
+ CpuId = (UCHAR)GetCpuId();
+
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ // Remember which interrupts have been turned on or off
+ //
+ registeredInts[CpuId] &= ~(1 << Vector);
+
+ // Change the Hardware mask to prevent the interrupt from
+ // occuring
+ //
+ RInterruptMask(CpuId) &= ~(1 << Vector);
+ WaitForRInterruptMask(CpuId);
+ if (Vector > 15) {
+
+ // Since this vector has no corollary with the SIO
+ // world, don't do any of the following stuff...
+ //
+ return;
+ }
+
+ if (Vector & 0x08) {
+
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+/*++
+
+Routine Description: VOID HalpIsaMapTransfer()
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+
+
+/*++
+
+Routine Description: VOID HalpEnableSioInterrupt()
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+{
+
+ ULONG CpuId = GetCpuId();
+
+ HASSERT(!MSR(EE));
+
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ // Make sure we're protected while we muck with the interrupt masks.
+ // since we asserted interrupts disabled on the way in, we can turn them
+ // off here and not worry about turning them on. If DbgPrint didn't
+ // turn ints off, we wouldn't have to worry about it.
+ //
+ // Remember which interrupts have been turned on or off
+ //
+ registeredInts[CpuId] |= (1 << Vector);
+
+ // Turn on the bit in the hardware to allow the interrupt
+ //
+ RInterruptMask(CpuId) |= (1 << Vector);
+ WaitForRInterruptMask(CpuId);
+
+ if (Vector > 0xf) {
+
+ // 15 is the effective MAX_DEV_VECTORS after the device vector
+ // offset is removed
+ //
+ return;
+
+ // Since this vector has no corollary with the SIO
+ // world, don't do any of the following stuff...
+ //
+ }
+ InterruptMode = Latched;
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+/*++
+
+Routine Description: PADAPTER_OBJECT HalpAllocateIsaAdapter()
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is significantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+// *NumberOfMapRegisters = numberOfMapRegisters;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialize the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+/*++
+
+Routine Description: ULONG HalReadDmaCounter()
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transferred.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still to be transferred.
+
+--*/
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+{
+ ULONG count=0;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxsiosup.h b/private/ntos/nthals/halfire/ppc/pxsiosup.h
new file mode 100644
index 000000000..beb486488
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsiosup.h
@@ -0,0 +1,231 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsiosup.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:13:41 $
+ * $Locker: $
+ */
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x8]; // Offset 0x58
+ UCHAR PciIrq0RouteControl; // Offset 0x60
+ UCHAR PciIrq1RouteControl; // Offset 0x61
+ UCHAR PciIrq2RouteControl; // Offset 0x62
+ UCHAR PciIrq3RouteControl; // Offset 0x63
+ UCHAR Reserved5[0x1C]; // Offset 0x64
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+#define HIGHEST_8259_VECTOR 15
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+
+
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/halfire/ppc/pxstall.s b/private/ntos/nthals/halfire/ppc/pxstall.s
new file mode 100644
index 000000000..d10f24ccb
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxstall.s
@@ -0,0 +1,390 @@
+//#***********************************************************************
+//
+//
+//
+//
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Copyright 1993 International Buisness Machines Corporation.
+// All Rights Reserved.
+//
+// This file contains copyrighted material. Use of this file is
+// restricted by the provisions of a Motorola/IBM Joint Software
+// License Agreement.
+//
+// File Name:
+// PXSTALL.S
+//
+// Functions:
+// KeStallExecutionProcessor
+// HalpCalibrateStall
+//
+// History:
+// 21-Sep-1993 Steve Johns
+// Original Version
+// 24-Dec-1993 Peter Johnston
+// Adapted to 601 HAL in an attempt to avoid having different
+// versions if at all possible. Original was designed for both
+// 601 and 603 but had some 601 difficulties.
+// 17-Jan-1994 Steve Johns
+// Changed to treat 601 vs PowerPC time base differences more
+// transparently.
+//
+//#***********************************************************************
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxstall.s $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:13:48 $
+ * $Locker: $
+ */
+
+
+#include "kxppc.h"
+
+#define ERRATA603 TRUE
+#define RTCU 4
+#define RTCL 5
+#define CMOS_INDEX 0x70
+#define CMOS_DATA 0x71
+#define RTC_SECOND 0x80
+
+
+ .extern HalpPerformanceFrequency
+ .extern HalpIoControlBase
+ .extern ..HalpDivide
+
+//
+// Register Definitions
+//
+ .set Microsecs, r.3
+ .set TimerLo , r.6 // MUST be same as defined in PXCLKSUP.S
+ .set TimerHi , r.7 // MUST be same as defined in PXCLKSUP.S
+ .set EndTimerLo, r.3
+ .set EndTimerHi, r.4
+ .set Temp , r.8
+ .set Temp2 , r.9
+ .set IO_Base , r.10
+
+//#***********************************************************************
+//
+// Synopsis:
+// VOID KeStallExecutionProcessor(
+// ULONG Microseconds)
+//
+// Purpose:
+// This function stalls the execution at least the specified number
+// of microseconds, but not substantially longer.
+//
+// Returns:
+// Nothing.
+//
+// Global Variables Referenced:
+// HalpPerformanceFrequency
+//#***********************************************************************
+
+ SPECIAL_ENTRY(KeStallExecutionProcessor)
+ mflr r.0 // Save Link Register
+ PROLOGUE_END(KeStallExecutionProcessor)
+
+ cmpli 0,0,Microsecs,0 // if (Microseconds == 0)
+ beqlr- // return;
+
+ bl ..HalpGetTimerRoutine // Get appropriate timer routine
+//
+// Read START time
+//
+ bctrl // ReadPerformanceCounter();
+
+//
+// Get PerformanceCounter frequency
+//
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp)
+//
+// Compute: (Microseconds * PerformanceFrequency) / 1,000,000
+//
+ mulhwu. EndTimerHi,Microsecs,Temp
+ mullw EndTimerLo,Microsecs,Temp
+
+
+
+ LWI (r.5, 1000000)
+ bl ..HalpDivide
+
+//
+// Account for software overhead
+//
+ .set Overhead, 30
+ cmpwi r.3, Overhead
+ ble SkipOverhead
+ addi r.3, r.3, -Overhead // Reduce delay
+SkipOverhead:
+
+//
+// Add delay to start time
+//
+ addc EndTimerLo, TimerLo, r.3
+ addze EndTimerHi, TimerHi
+
+
+
+//
+// while (ReadPerformanceCounter() < EndTimer);
+//
+StallLoop:
+ bctrl // ReadPerformanceCounter();
+ cmpl 0,0,TimerHi,EndTimerHi // Is TimerHi >= EndTimerHi ?
+ blt- StallLoop // No
+ bgt+ StallExit // Yes
+ cmpl 0,0,TimerLo,EndTimerLo // Is TimerLo >= EndTimerLo ?
+ blt StallLoop // Branch if not
+
+StallExit:
+ mtlr r.0 // Restore Link Register
+
+ SPECIAL_EXIT(KeStallExecutionProcessor)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for the 601 processor.
+// The 601 RTC counts discontinuously (1 is added to RTCU when the value in
+// RTCL passes 999,999,999). This routine converts the RTC count to a
+// continuous 64-bit count by calculating:
+//
+// ((RTC.HighPart * 1,000,000,000) + RTC.LowPart) / 128
+//
+//
+ LEAF_ENTRY (ReadRTC)
+
+ mfspr TimerHi,RTCU // Read the RTC registers coherently
+ mfspr TimerLo,RTCL
+ mfspr Temp,RTCU
+ cmpl 0,0,TimerHi,Temp
+ bne- ..ReadRTC
+
+ lis Temp,(1000000000 >> 16) // RTC.HighPart * 1,000,000
+ ori Temp,Temp,(1000000000 & 0xFFFF)
+ mullw Temp2,Temp,TimerHi
+ mulhwu Temp,Temp,TimerHi
+ addc TimerLo,Temp2,TimerLo // + RTC.LowPart
+ addze TimerHi,Temp
+//
+// Each tick increments the RTC by 128, so let's divide that out.
+//
+ mr Temp,TimerHi // Divide 64-bit value by 128
+ rlwinm TimerLo,TimerLo,32-7,7,31
+ rlwinm TimerHi,TimerHi,32-7,7,31
+ rlwimi TimerLo,Temp,32-7,0,6
+
+ LEAF_EXIT (ReadRTC)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for PowerPC
+// architectures (not the 601).
+//
+ LEAF_ENTRY (ReadTB)
+
+ mftbu TimerHi // Read the TB registers coherently
+ mftb TimerLo
+#if ERRATA603
+ mftb TimerLo
+ mftb TimerLo
+ mftb TimerLo
+#endif
+ mftbu Temp
+ cmpl 0,0,Temp,TimerHi
+ bne- ..ReadTB
+
+ LEAF_EXIT (ReadTB)
+
+
+//
+// Returns in the Count Register the entry point for the routine
+// that reads the appropriate Performance Counter (ReadRTC or ReadTB).
+//
+// Called from KeQueryPerformanceCounter and KeStallExecutionProcessor
+//
+ LEAF_ENTRY (HalpGetTimerRoutine)
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // Are we running on an MPC601 ?
+ lwz Temp,[toc]ReadTB(r.toc)
+ bne+ GetEntryPoint // Branch if not
+
+ lwz Temp,[toc]ReadRTC(r.toc)
+
+GetEntryPoint:
+ lwz Temp,0(Temp) // Get addr to ReadRTC or ReadTB
+ mtctr Temp
+
+ LEAF_EXIT (HalpGetTimerRoutine)
+
+
+
+
+
+//
+// Returns the number of performance counter ticks/second.
+//
+// The DECREMENTER is clocked at the same rate as the PowerPC Time Base (TB)
+// and the POWER RTC. The POWER RTC is supposed to be clocked at 7.8125 MHz,
+// but on early prototypes of the Sandalfoot platform, this is not true).
+// In either case, to keep the calibration routine simple and generic, we
+// will determine the DECREMENTER clock rate by counting ticks for exactly
+// 1 second (as measured against the CMOS RealTimeClock). We then use that
+// value in the KeStallExecutionProcessor() and KeQueryPerformanceCounter()
+//
+
+ LEAF_ENTRY(HalpCalibrateTB)
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+
+
+WaitForTick1:
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.3,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2:
+ li r.4,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // if (CPU != 601)
+ bnelr // return(r.3);
+//
+// On the 601, the DECREMENTER decrements every ns, so the 7 LSBs are
+// not implemented.
+//
+ rlwinm r.3,r.3,32-7,7,31 // Divide count by 128
+
+
+ LEAF_EXIT(HalpCalibrateTB)
+
+
+
+ LEAF_ENTRY(HalpCalibrateTBPStack)
+
+#define NVRAM_INDEX_LO 0x74
+#define NVRAM_INDEX_HI 0x75
+#define NVRAM_DATA 0x77
+#define RTC_OFFSET 0x1ff8
+#define RTC_CONTROL 0x0
+// *BJ* Fix later.
+#undef RTC_SECOND
+#define RTC_SECOND 0x1
+#define RTC_MINUTE 0x2
+
+#define SYNCHRONIZE \
+ lwz Temp,[toc]HalpIoControlBase(r.toc);\
+ stw Temp,[toc]HalpIoControlBase(r.toc);\
+ nop;\
+ sync
+
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+
+ li r.3,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.3,r.3,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.3,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.3,NVRAM_DATA(IO_Base) // Read CMOS data
+
+WaitForTick0.Ps:
+ li r.4,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.4,r.4,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.4,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.4,NVRAM_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick0.Ps
+
+
+WaitForTick1.Ps:
+ li r.3,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.3,r.3,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.3,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.3,NVRAM_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1.Ps
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2.Ps:
+ li r.4,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.4,r.4,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.4,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.4,NVRAM_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2.Ps
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // if (CPU != 601)
+ bnelr // return(r.3);
+//
+// On the 601, the DECREMENTER decrements every ns, so the 7 LSBs are
+// not implemented.
+//
+ rlwinm r.3,r.3,32-7,7,31 // Divide count by 128
+
+ LEAF_EXIT(HalpCalibrateTBPStack)
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxsysbus.c b/private/ntos/nthals/halfire/ppc/pxsysbus.c
new file mode 100644
index 000000000..651dae898
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsysbus.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsysbus.c $
+ * $Revision: 1.30 $
+ * $Date: 1996/07/13 01:16:01 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - ported to PowerPC
+
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arccodes.h>
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "eisa.h"
+#include "pxmemctl.h"
+
+extern ULONG Vector2Irql[];
+extern ULONG Vector2Affinity[];
+
+//
+// Which Ints on Processor 1?
+//
+BOOLEAN HalpGetAffinityCalled = FALSE;
+
+
+#define TBS " "
+
+void
+HalpGetAffinity();
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ TranslatedAddress->HighPart = BusAddress.HighPart;
+
+
+
+ //
+ // Determine the address based on whether the bus address
+ // is in I/O space, system space, or bus memory space.
+ //
+
+ switch (*AddressSpace) {
+ case MEMORY_ADDRESS_SPACE:
+ //
+ // The address is in memory space.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart +
+ PCI_MEMORY_PHYSICAL_BASE;
+ if (VER_PRODUCTBUILD > 1233) {
+ //
+ // Due to a change in NT defined spaces, our previous method
+ // of using AddressSpace to communicate a driver's mapping
+ // needs no longer will work. So, starting with Build 1297
+ // we need to make sure the display driver is not mapped into
+ // the PCI_MEMORY_PHYSICAL_BASE but into it's "natural"
+ // location.
+ //
+ // This is a temp fix and must be revisited so that we
+ // can more specifically detect the framebuffer based
+ // driver requirements and not affect other devices that
+ // may have a legitimate need for this address offset into
+ // a bus location.
+ //
+ if ((BusAddress.LowPart&0xf0000000)==(0x70000000)) {
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ }
+ }
+ break;
+ //
+ // Everyone should be assumed IO space if not otherwise requested
+ //
+ default:
+ case IO_ADDRESS_SPACE:
+ //
+ // The address is in I/O space.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart +
+ IO_CONTROL_PHYSICAL_BASE;
+ break;
+ case SYSTEM_ADDRESS_SPACE:
+ //
+ // The address is in system space.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ break;
+ }
+
+ *AddressSpace = 0;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+ //
+ // A carry occurred.
+ //
+ TranslatedAddress->HighPart += 1;
+
+ }
+
+ return(TRUE);
+}
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptLevel );
+
+ if (HalpGetAffinityCalled == FALSE) {
+ HalpGetAffinity();
+ HalpGetAffinityCalled = TRUE;
+ }
+
+ *Affinity = Vector2Affinity[BusInterruptVector];
+
+ HDBG(DBG_INTERRUPTS|DBG_MPINTS,
+ HalpDebugPrint("HalpGetSystemInterruptVector: %x, %x, %d, %x\n",
+ BusInterruptLevel, BusInterruptVector, *Irql, *Affinity););
+
+
+ *Irql = (UCHAR) Vector2Irql[BusInterruptVector]; // see define in ntdef.h
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+ BusInterruptLevel = BusInterruptVector;
+ HDBG(DBG_INTERRUPTS|DBG_MPINTS,
+ HalpDebugPrint( "%sint request: returning %x + %x = %x\n",
+ TBS, BusInterruptVector, DEVICE_VECTORS,
+ BusInterruptVector + DEVICE_VECTORS ););
+ return(BusInterruptVector + DEVICE_VECTORS);
+
+}
+
+//
+// HalpGetAffinity()
+//
+// This is a simple routine that gets a value from NVRAM to
+// overwrite the default value for where interrupts go.
+// This is mostly a hack for now.
+//
+void
+HalpGetAffinity()
+{
+ CHAR buf[256];
+ PKPRCB pPRCB;
+ ULONG count;
+ extern HalpInitProcAffinity(PCHAR,ULONG);
+
+ if ((count = HalpProcessorCount()) < 2) {
+ HalpInitProcAffinity((PCHAR)0,1);
+ return;
+ }
+
+ pPRCB = KeGetCurrentPrcb();
+ if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ HalpInitProcAffinity((PCHAR)0,1);
+ return;
+ }
+
+ if (HalGetEnvironmentVariable("UNIPROCESSOR", sizeof(buf), buf)
+ == ESUCCESS) {
+ if (_stricmp(buf, "true") == 0) {
+ HalpInitProcAffinity((PCHAR)0,1);
+ return;
+ }
+ }
+
+ // it is mulitprocessor system.
+ //
+ // Get PROCNINTS Value from NVRAM
+ //
+ if (HalGetEnvironmentVariable("PROCNINTS", sizeof(buf), buf)
+ == ESUCCESS) {
+ HalpInitProcAffinity(buf,count);
+ return;
+ } else {
+ HalpInitProcAffinity((PCHAR)0,count);
+ return;
+ }
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxsysint.c b/private/ntos/nthals/halfire/ppc/pxsysint.c
new file mode 100644
index 000000000..39ff55351
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsysint.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsysint.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/05/14 02:35:34 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+--*/
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fpdebug.h"
+
+
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrupt.
+ //
+
+ if (Vector >= DEVICE_VECTORS &&
+ //
+ // For FirePOWER, allowable external device interrupts spans 32 bits
+ // not the 16 of sandalfoot ( or SIO ) architecture. The 16 bit limits
+ // will be enforced in HalpDisableSioInterrupts. We'll do our normal
+ // system interrupt stuff there for now but should move the system
+ // register activity to here and leave the SIO disable routine to deal
+ // ONLY with the SIO stuff.
+ //
+ Vector < (DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR + 16) ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrupt and set the Level/Edge register.
+ //
+
+
+ if (Vector >= DEVICE_VECTORS &&
+ //
+ // For FirePOWER, allowable external device interrupts spans 32 bits
+ // not the 16 of sandalfoot ( or SIO ) architecture. The 16 bit limits
+ // will be enforced in HalpEnableSioInterrupts. We'll do our normal
+ // system interrupt stuff there for now but should move the system
+ // register activity to here and leave the SIO enable routine to deal
+ // ONLY with the SIO stuff.
+ //
+ Vector < (DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR + 16) ) {
+ HalpEnableSioInterrupt(Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+HalRequestIpi(IN ULONG Mask)
+{
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+ rCPUMessageInterruptSet = Mask;
+ FireSyncRegister();
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+{
+ //
+ // Use this call to clear the interrupt from the Req register
+ //
+ rCPUMessageInterrupt = (ULONG)(1 << GetCpuId());
+ FireSyncRegister();
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxtime.c b/private/ntos/nthals/halfire/ppc/pxtime.c
new file mode 100644
index 000000000..450b6856f
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxtime.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxtime.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/05/20 22:36:01 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Change real time clock mapping to port 71.
+ Code assumes the DS1385S chip is compatible with existing
+ PC/AT type RTC's. The only known exception to PC/AT
+ compatibility on S-FOOT is the use of ports 810 and 812.
+ These ports provide password security for the RTC's NVRAM,
+ and are currently unused in this port since this address space
+ is available from kernel mode only in NT.
+
+ Steve Johns (sjohns@pets.sps.mot.com)
+ Changed to support years > 1999
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "pxrtcsup.h"
+#include "fpreg.h"
+#include "fpio.h"
+#include "fpds1385.h"
+#include "eisa.h"
+
+
+extern BOOLEAN RtcBinaryMode;
+extern BOOLEAN RtcFailure;
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields)
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+ BOOLEAN retVal = FALSE;
+
+ //
+ // Acquire the RTC spin lock to synchronize the collection of
+ // accesses to the RTC
+ KeAcquireSpinLock(&HalpRTCLock, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+
+ //
+ // Make sure the time is valid before setting values:
+ //
+ if ((DataByte & RTC_VRT ) == RTC_VRT) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERA);
+ } while( (DataByte & RTC_UIP) == RTC_UIP);
+
+ //
+ // According to the chip spec, the only way to read the chip that
+ // is guarenteed to give a coherent time is to assert the SET bit;
+ // this essentially prevents the chip from updating the user visible
+ // copy of the time while we are reading it. Since the time will
+ // not update, there is the possiblity that we will loose a second.
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ (UCHAR)((DataByte & ~RTC_UIE) | RTC_SET));
+
+ // Reset the failure flag (see below)
+ RtcFailure = FALSE;
+
+ // Read the values
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday =
+ (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+
+ //
+ // Release the SET bit
+ //
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // We have a problem reading the RTC; see HalpDS1385ReadReg in
+ // fpds1385.c for a description. If we detect an
+ // error, that routine asserts RtcFailure. Use that value here.
+ //
+ retVal = !RtcFailure;
+ }
+
+ KeReleaseSpinLock(&HalpRTCLock, OldIrql);
+ return retVal;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+BOOLEAN
+HalSetRealTimeClock (IN PTIME_FIELDS TimeFields)
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+ BOOLEAN retVal = FALSE;
+
+ //
+ // Acquire the RTC spin lock to synchronize the collection of
+ // accesses to the RTC
+ KeAcquireSpinLock(&HalpRTCLock, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+
+ if (( DataByte & RTC_VRT ) == RTC_VRT) {
+ //
+ // Set the realtime clock control to set the time.
+ // RMW the control byte so we don't lose it's setup
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+
+ //
+ // set control parameters: leave daylight savings disabled
+ // since the control program needs to know and has no way of
+ // passing that info in to here.
+ //
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ (UCHAR)((DataByte & ~RTC_UIE) | RTC_SET));
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if ( TimeFields->Year > 1999 ) {
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ } else {
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+ }
+
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK,
+ (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Release the realtime clock control to update the time.
+ //
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB, DataByte);
+
+ retVal = TRUE;
+ }
+
+ KeReleaseSpinLock(&HalpRTCLock, OldIrql);
+ return retVal;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+ can be configured to do this,... but as a quick fix I am doing it
+ here. (plj)
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+UCHAR
+HalpReadClockRegister (UCHAR Register)
+{
+ UCHAR BcdValue;
+
+ BcdValue = HalpDS1385ReadReg(Register);
+
+ //
+ // If the data mode is BCD, calculate the return value as BCD:
+ //
+ if ( FALSE == RtcBinaryMode ) {
+ BcdValue = (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
+ }
+ return (BcdValue) ;
+}
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+{
+ UCHAR BcdValue;
+
+ if (TRUE == RtcBinaryMode) {
+ BcdValue = Value;
+ } else {
+ BcdValue = ((Value / 10) << 4) | (Value % 10);
+ }
+
+ //
+ // Now insert the value into the RTC register
+ //
+ HalpDS1385WriteReg(Register, BcdValue);
+
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxusage.c b/private/ntos/nthals/halfire/ppc/pxusage.c
new file mode 100644
index 000000000..75d3b0fd5
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxusage.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxusage.c $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:14:14 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpEnableInterruptHandler ()
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ )
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+
+ KeInitializeInterrupt( Interrupt,
+ ServiceRoutine,
+ ServiceContext,
+ SpinLock,
+ Vector,
+ Irql,
+ SynchronizeIrql,
+ InterruptMode,
+ ShareVector,
+ ProcessorNumber,
+ FloatingSave
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ if (!KeConnectInterrupt( Interrupt )) {
+ HalDisplayString("HalpEnableInterruptHandler: no connect \n");
+
+ return(FALSE);
+ }
+
+ HalpRegisterVector (ReportFlags, BusVector, Vector, Irql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ return(TRUE);
+
+
+}
+
+
+
+/*++
+
+Routine Description: VOID HalpRegisterVector ()
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+/*++
+
+Routine Description: VOID HalpGetResourceSortValue ()
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+/*++
+
+Routine Description: VOID HalpReportResourceUsage ()
+
+Arguments:
+
+Return Value:
+
+--*/
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList=NULL, pTPartList=NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+
+ for(i=0; i < DEVICE_VECTORS; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halfire/ppc/sysbios.c b/private/ntos/nthals/halfire/ppc/sysbios.c
new file mode 100644
index 000000000..9aa6dc90c
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/sysbios.c
@@ -0,0 +1,73 @@
+/*++
+
+
+Copyright (C) 1996 Motorola Inc.
+
+Module Name:
+
+ sysbios.c
+
+Abstract:
+
+ Emulate System BIOS functions.
+
+Author:
+
+ Scott Geranen
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "emulate.h"
+#include "sysbios.h"
+#include "pcibios.h"
+
+BOOLEAN
+HalpEmulateSystemBios(
+ IN OUT PRXM_CONTEXT P,
+ IN ULONG Number
+ )
+/*++
+
+Routine Description:
+
+ This function emulates a system BIOS. However, this is really
+ intended to support video bios functions, not all system BIOS
+ functions are implemented.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+ Number - interrupt number used to enter
+
+Return Value:
+
+ TRUE = the function was emulated
+ FALSE = the function was not emulated
+
+--*/
+{
+ switch (Number) {
+ case 0x1A:
+ if (P->Gpr[EAX].Xh == PCIBIOS_PCI_FUNCTION_ID) {
+ return HalpEmulatePciBios(P);
+ }
+
+ //
+ // Fall into the default case.
+ //
+
+ default:
+ return FALSE; // not supported
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/sysbios.h b/private/ntos/nthals/halfire/ppc/sysbios.h
new file mode 100644
index 000000000..6119bc2d0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/sysbios.h
@@ -0,0 +1,31 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1996 Motorola Inc.
+
+Module Name:
+
+ sysbios.h
+
+Abstract:
+
+ This module contains the private header file for the system BIOS
+ emulation.
+
+Author:
+
+ Scott Geranen (3-4-96)
+
+Revision History:
+
+--*/
+
+#ifndef _SYSBIOS_
+#define _SYSBIOS_
+
+BOOLEAN
+HalpEmulateSystemBios(
+ IN OUT PRXM_CONTEXT P,
+ IN ULONG Number
+ );
+
+#endif // _SYSBIOS_
diff --git a/private/ntos/nthals/halfire/ppc/txtpalet.h b/private/ntos/nthals/halfire/ppc/txtpalet.h
new file mode 100644
index 000000000..ffb5e97b1
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/txtpalet.h
@@ -0,0 +1,107 @@
+/******************************************************************************
+
+txtpalet.h
+
+ Author: Jess Botts
+
+ This file contains the text mode palette. Most of the entries are 0
+ because they are not used. The first 8 entries are used for all
+ background colors and normal intensity foregound colors. Background
+ colors are displayed at normal intensity only. The 8 entries that
+ begin at the 56th entry are used for high intensity foreground colors.
+
+ Each entry consists of 3 values, 1 for each color gun.
+
+******************************************************************************/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: txtpalet.h $
+ * $Revision: 1.4 $
+ * $Date: 1996/01/11 07:14:21 $
+ * $Locker: $
+ */
+
+UCHAR
+ TextPalette[] =
+ { /*
+ Line
+ R G B R G B R G B R G B Index
+ */
+
+// all background colors and normal intensity foregound colors
+
+ 0, 0, 0, 0, 0, 32, 0, 32, 0, 0, 32, 32, // 0
+ 32, 0, 0, 32, 0, 32, 32, 32, 0, 32, 32, 32,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+// high intensity foreground colors
+
+ 16, 16, 16, 0, 0, 63, 0, 63, 0, 0, 63, 63, // 56
+ 63, 0, 0, 63, 0, 63, 63, 63, 0, 63, 63, 63,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+/*****************************************************************************/
diff --git a/private/ntos/nthals/halfire/ppc/x86bios.c b/private/ntos/nthals/halfire/ppc/x86bios.c
new file mode 100644
index 000000000..3bb1a9686
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/x86bios.c
@@ -0,0 +1,1201 @@
+/*++
+
+Copyright (C) 1994,1995 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: x86bios.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/07/02 04:58:06 $
+ * $Locker: $
+ */
+
+
+
+
+
+#include "halp.h"
+#include "xm86.h"
+#include "x86new.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "fpdebug.h"
+#include "pci.h"
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+//PVOID HalpIoMemoryBase = NULL;
+PUCHAR HalpRomBase = NULL;
+
+UCHAR HalpVideoBus; // Used as arguments to the PCI BIOS
+UCHAR HalpVideoDevice; // init function. Set HalpInitX86Emulator,
+UCHAR HalpVideoFunction; // used by HalpInitializeX86DisplayAdapter.
+
+UCHAR HalpLastPciBus; // Set by scanning the configuration data and
+ // used by PCI BIOS eumulation code.
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (128*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+static VOID DumpPCIConfig(PVOID ConfigBaseAddress)
+{
+ USHORT VendorID, DeviceID, RevisionID;
+ ULONG addr;
+ ULONG TempReg32;
+
+ VendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)ConfigBaseAddress)->VendorID);
+ DeviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)ConfigBaseAddress)->DeviceID);
+ RevisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)ConfigBaseAddress)->RevisionID);
+ PRNTDISP(DbgPrint("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", VendorID, DeviceID, RevisionID));
+
+ TempReg32 = READ_REGISTER_ULONG((PULONG)&((PCI_CONFIG)ConfigBaseAddress)->Command);
+ PRNTDISP(DbgPrint("Status Command=0x%08x\n", TempReg32));
+
+ TempReg32 = READ_REGISTER_ULONG((PULONG)&((PCI_CONFIG)ConfigBaseAddress)->RevisionID);
+ PRNTDISP(DbgPrint("Revision ID=0x%08x\n", TempReg32));
+
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress1); PRNTDISP(DbgPrint("BaseAddress1=0x%08x\n", addr));
+
+
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress2); PRNTDISP(DbgPrint("BaseAddress2=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress3); PRNTDISP(DbgPrint("BaseAddress3=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress4); PRNTDISP(DbgPrint("BaseAddress4=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress5); PRNTDISP(DbgPrint("BaseAddress5=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress6); PRNTDISP(DbgPrint("BaseAddress6=0x%08x\n", addr));
+}
+
+
+
+BOOLEAN HalpInitX86Emulator(
+ VOID)
+
+{
+ BOOLEAN Found = FALSE;
+ ULONG ROM_size = 0;
+ PHYSICAL_ADDRESS PhysAddr;
+ USHORT Cmd, VendorID, Slot;
+ PVOID HalpVideoConfigBase;
+ PUCHAR ROM_Ptr;
+ ULONG i;
+ UCHAR Class;
+ UCHAR SubClass;
+ USHORT DeviceID = 0;
+ UCHAR RevisionID = 0;
+ ULONG mapSize = 0x800000;
+
+ PhysAddr.HighPart = 0x00000000;
+
+
+ //
+ // Scan PCI slots for video BIOS ROMs
+ //
+ for (Slot = 1; Slot < MAXIMUM_PCI_SLOTS; Slot++) {
+
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot]);
+
+ // Read Vendor ID and check if slot is empty
+ VendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ if (VendorID == 0xFFFF)
+ continue; // Slot is empty; go to next slot
+
+ DumpPCIConfig(HalpVideoConfigBase);
+
+ Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
+#define DISPLAY_CLASS 0x03
+ if ( !(Class == DISPLAY_CLASS && (SubClass == 0)) &&
+ !(Class == 0x00 && SubClass == 0x01))
+ continue;
+
+ DeviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
+ RevisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
+ //PRNTDISP(DbgPrint("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", VendorID, DeviceID, RevisionID));
+ //DbgBreakPoint();
+
+ // Get size of ROM
+ WRITE_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase, 0xFFFFFFFF);
+ ROM_size = READ_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase);
+
+
+ if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
+ ROM_size = ~(ROM_size & 0xFFFFFFFE) + 1;
+ PRNTDISP(DbgPrint("ROM_size=0x%08x\n", ROM_size));
+ ROM_size += 0xC0000;
+ // if (ROM_size < 0xE0000) ROM_size = 0xE0000; // Map to end of option ROM space
+
+ //
+ // Set Expansion ROM Base Address & enable ROM
+ //
+ PhysAddr.LowPart = 0x000C0000 | 1;
+ WRITE_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase, PhysAddr.LowPart);
+
+ //
+ // Enable Memory & I/O spaces in command register
+ //
+ Cmd = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command);
+ WRITE_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command, Cmd | 3);
+ PRNTDISP(DbgPrint("HalpVideoConfigBase=0x%08x Slot=%d Cmd=0x%08x ROM_size=0x%08x\n", HalpVideoConfigBase, Slot, Cmd, ROM_size));
+
+ //
+ // Create a mapping to the PCI memory space
+ //
+ if (NULL == HalpIoMemoryBase) {
+ HalpIoMemoryBase = KePhase0MapIo((PVOID)IO_MEMORY_PHYSICAL_BASE, mapSize /*ROM_size*/);
+
+ if (HalpIoMemoryBase == NULL) {
+ PRNTDISP(DbgPrint("\nCan't create mapping to PCI memory space\n"));
+ return FALSE;
+ }
+ }
+ //
+ // Look for PCI option video ROM signature
+ //
+ HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // Sometimes option ROM and video RAM can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ PRNTDISP(DbgPrint("ROM_Length=0x%08x\n", ROM_Length));
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ } else {
+ PRNTDISP(DbgPrint("ROM_Length=0x%08x is bigger than 0x%08x\n", ROM_Length, BUFFER_SIZE));
+ goto cleanup;
+ }
+
+ // Bus 0 because we do not yet support display cards behind a
+ // bridge
+
+ HalpVideoBus = 0;
+
+ // Function 0 because display cards are as of now single
+ // function devices.
+
+ HalpVideoFunction = 0;
+
+ HalpVideoDevice = (UCHAR)Slot;
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+ } // end of if clause
+ } // end of for loop
+
+ cleanup:
+ // mogawa for BUG 3400
+ if (HalpIoMemoryBase) {
+ HalpIoMemoryBase = (PVOID)0;
+ KePhase0DeleteIoMap((PVOID)IO_MEMORY_PHYSICAL_BASE,
+ mapSize/*ROM_size*/);
+ }
+ return FALSE;
+}
+
+
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
+ &Context,
+ HalpIoControlBase,
+ HalpIoMemoryBase) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+
+
+}
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ LoaderBlock for access to the number of PCI buses
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ ULONG MatchKey;
+ PCM_PARTIAL_RESOURCE_LIST Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial;
+ XM86_CONTEXT State;
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (!HalpInitX86Emulator())
+ return FALSE;
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Get the number of PCI buses for the PCI BIOS functions
+ //
+
+ //
+ // Find the PCI info in the config data.
+ //
+
+//JJJ
+#if 1
+
+ HalpLastPciBus = 0;
+ MatchKey = 0;
+
+#else
+
+ PRNTDISP(DbgPrint("about to find last PCI bus\n"));
+
+
+ while ((ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ AdapterClass, MultiFunctionAdapter, &MatchKey)) != NULL) {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"PCI")) {
+
+ Descriptor = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+
+ PCIRegInfo = (PPCI_REGISTRY_INFO)&Descriptor->PartialDescriptors[1];
+
+ HalpLastPciBus = PCIRegInfo->NoBuses - 1;
+
+ break;
+ }
+
+ MatchKey++;
+ }
+
+#endif
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ State.Eax = (HalpVideoBus << 8) |
+ (HalpVideoDevice << 3) |
+ HalpVideoFunction;
+
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+
+ if (x86BiosInitializeAdapter(0xc0000, &State, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ HalpEnableInt10Calls = TRUE;
+
+ return TRUE;
+}
+
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+
+ return;
+}
+
+
+//
+// This code came from ..\..\x86new\x86bios.c
+//
+#define LOW_MEMORY_SIZE 0x800
+extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+extern ULONG x86BiosScratchMemory;
+extern ULONG x86BiosIoMemory;
+extern ULONG x86BiosIoSpace;
+
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(HalpRomBase + Offset);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+
+ // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
+ return (PVOID)NULL;
+}
+
+
+VOID HalpCopyROMs(VOID)
+{
+ ULONG i;
+ PUCHAR ROM_Shadow;
+
+ if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
+ //DbgPrint("HalpCopyROMs: calling ExAllocatePool.\n");
+ HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
+ for (i=0; i<ROM_Length; i++) {
+ *ROM_Shadow++ = ROM_Buffer[i];
+ }
+ }
+}
+
+
+/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
+
+/*++
+
+ Copyright (c) 1994 Microsoft Corporation
+
+ Module Name:
+
+ x86bios.c
+
+ Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+ Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+ Environment:
+
+ Kernel mode only.
+
+ Revision History:
+
+ --*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space and the
+// base address of I/O memory space.
+//
+
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+
+//
+// contexst for PCI Config mechanism #1 [YS:042296]
+//
+
+//extern PVOID HalpPciConfigBase;
+//extern ULONG HalpPciConfigSlot[];
+
+#define BIT_ENABLE 1
+#define CONFIG_ADDR (0x00000CF8)
+#define CONFIG_DATA (0x00000CFC)
+
+typedef struct _PCI_CONFIG_ADDR {
+ union {
+ struct {
+ ULONG zeros:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG DeviceNumber:5;
+ ULONG BusNumber:8;
+ ULONG Reserved:7;
+ ULONG EnableMapping:1;
+ } bits;
+ ULONG AsULONG;
+ } u;
+} PCI_CONFIG_ADDR, *PPCI_CONFIG_ADDR ;
+
+// I wonder if it's OK to use a static to keep value for CONFIG_ADDRESS register or not.
+// May be needed to put this in XM_CONTEXT structure. [YS]
+
+static PCI_CONFIG_ADDR regConfigAddr;
+
+// end of contexst for PCI Config mechanism #1 [YS:042296]
+
+
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+ Routine Description:
+
+ This function reads from emulated I/O space.
+
+ Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+ Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+ --*/
+
+{
+
+ ULONG Result;
+
+ ULONG slotNumber ;
+ ULONG offset ;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ if (
+ ((PortNumber & 0xfffffffc) == CONFIG_DATA ) &&
+ (regConfigAddr.u.bits.EnableMapping == BIT_ENABLE )
+ ){
+ // This is read from PCI config register space so lets translate this
+ // to our memory mapped address for the corresponding register.
+
+ slotNumber = regConfigAddr.u.bits.DeviceNumber;
+
+ if (
+ (slotNumber < MAXIMUM_PCI_SLOTS) &&
+ !regConfigAddr.u.bits.BusNumber
+ ){
+
+ // Calc offset of register within individual slot config space
+ // taking into account that the PortNumber can refer to a byte
+ // within the 32 bit register starting at "CONFIG_DATA"
+
+ offset = (regConfigAddr.u.bits.RegisterNumber << 2) +
+ (PortNumber & 0x3);
+
+ u.Long = (PULONG)((ULONG)HalpPciConfigBase +
+ (ULONG)HalpPciConfigSlot[slotNumber] + offset);
+
+ PRNTDISP(
+ DbgPrint(
+ "RD: Port (0x%08x) Config Addr (0x%08x) register# (0x%08x) LONG: (0x%08x) type: (0x%08x)\n",
+ PortNumber,
+ regConfigAddr.u.AsULONG,
+ offset,
+ Result,
+ DataType
+ ));
+
+ } else {
+
+ // The config space read target is either out of our supported
+ // range of slots or on a bus that is not supported. Note we do
+ // not support display cards in any bus other that 0 (i.e a display
+ // card cannot reside behind a bridge).
+
+ return(0xffffffff);
+ }
+ } else if ((PortNumber & 0xfffffffc) == CONFIG_ADDR){
+
+ // This is a read to the register that would normally be the
+ // "CONFIG_ADDRESS" used in an Intel PC to hold the address in
+ // config space that will be accessed in a subsequent read/write to the
+ // the "CONFIG_DATA" register. So we simply return the value stored in
+ // our simulated version of thisregister.
+
+ return(regConfigAddr.u.AsULONG);
+
+ } else {
+
+ // Just a regular access so setup the standard address translation
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ // Lets do the actual read now...
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+
+ // PRNTDISP(DbgPrint("RD: Port (0x%08x) Result (0x%08x)\n", PortNumber, Result));
+
+ return Result;
+}
+
+
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+ Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+ Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+ ULONG slotNumber;
+ ULONG offset;
+ PULONG aPciConfigRegs;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ // PRNTDISP(DbgPrint("WRT: Port Number (0x%08x) DataType (0x%08x) Value (0x%08x)\n", PortNumber, DataType, Value));
+
+ //
+ // Compute port address and read port.
+ //
+
+ if (
+ ((PortNumber & 0xfffffffc) == CONFIG_DATA ) &&
+ (regConfigAddr.u.bits.EnableMapping == BIT_ENABLE )
+ ){
+ // This is read from PCI config register space so lets translate this
+ // to our memory mapped address for the corresponding register.
+
+ slotNumber = regConfigAddr.u.bits.DeviceNumber;
+
+ if (
+ (slotNumber < MAXIMUM_PCI_SLOTS) &&
+ !regConfigAddr.u.bits.BusNumber
+ ){
+
+ // Calc offset of register within individual slot config space
+ // taking into account that the PortNumber can refer to a byte
+ // within the 32 bit register starting at "CONFIG_DATA"
+
+ offset = (regConfigAddr.u.bits.RegisterNumber << 2) +
+ (PortNumber & 0x3);
+
+ u.Long = (PULONG)((ULONG)HalpPciConfigBase +
+ (ULONG)HalpPciConfigSlot[slotNumber] + offset);
+
+
+ PRNTDISP(DbgPrint(
+ "WRT: Port Number (0x%08x) DataType (0x%08x) Value (0x%08x) Offset (0x%08x)\n",
+ PortNumber,
+ DataType,
+ Value,
+ offset
+ ));
+
+ } else {
+ return;
+ }
+ } else {
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ if (DataType == BYTE_DATA) {
+
+ if ( PortNumber == 0x3C3 ) { // start of [YS:042296]
+
+ // CAUTION // This code is a hack for S3 Trio64 "Z" version
+ //
+ // Do NOT touch to the 0x03C3
+ //
+ // We know that some of the version of S3 Trio64,
+ // such as S3 Trio64 "Z" version (86C764X) or some of the Trio64V+,
+ // have bug on the new-wake-up register at 3C3.
+ // This register is not only WRITE ONLY, but WRITE ONCE.
+ // A second write is bad news.
+ // We are supposed to write this register with a 0x01 to wake up the chip.
+ // But writting it a second time will cose all sorts of problems,
+ // like hanging the system.
+ // So of cource, in order to display the firmware screen, FW has to
+ // write it once to open up the chip and get it going.
+ // If the VGA BIOS code tries to do it a second time in HAL, hang the system.
+ //
+ // Of cource, this hack is only for some version of S3 Trio64 chip.
+ // But we don't know which version of the chip have this problem.
+ //
+ // We know this port is also used by other vender.
+ // But "just ignore access to 0x3c3" will be OK for now, because:
+ // Weitek P9100 assigns this port as VGA enable register on Motherboard mode.
+ // Cirrus assigns this port as sleep address register for non-PCI bus, and
+ // this port is never accessible for PCI bus.
+ // So, I just ignore all byte write access to 0x3C3 ...
+
+ // PRNTDISP(DbgPrint("WRT: 3C3 access ignored\n"));
+
+
+ return;
+ } // end of [YS:042296]
+
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+
+ if ( PortNumber == CONFIG_ADDR ) {
+
+ // This is identified as the CONFIG_ADDRESS write phase of a
+ // standard PC style PCI configuration space access. This style
+ // of PCI configuration space access is referred to as
+ // "Configuratoin Mechanism #1" in the PCI spec. Rev. 2.1.
+ // What we do is store the CONFIG_ADDRESS as done below and
+ // when the CONFIG_DATA port is accessed we use the value stored
+ // below to figure out where is our PCI config space map we need to
+ // go to get, or put, the requested data.
+
+ regConfigAddr.u.AsULONG = Value;
+ } else {
+
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+ }
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+ Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+ Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+ Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+ Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+ Return Value:
+
+ The emulation completion status.
+
+ --*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+ Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+ Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+ Return Value:
+
+ The emulation completion status.
+
+ --*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/x86bios.h b/private/ntos/nthals/halfire/ppc/x86bios.h
new file mode 100644
index 000000000..fd5de89d4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/x86bios.h
@@ -0,0 +1,24 @@
+#ifndef _X86BIOS_H
+#define _X86BIOS_H
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: x86bios.h $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:14:34 $
+ * $Locker: $
+ */
+
+#include "xm86.h"
+
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+extern ULONG HalpEnableInt10Calls;
+
+#endif // _X86BIOS_H
diff --git a/private/ntos/nthals/halfire/sources b/private/ntos/nthals/halfire/sources
new file mode 100644
index 000000000..816dc199c
--- /dev/null
+++ b/private/ntos/nthals/halfire/sources
@@ -0,0 +1,235 @@
+#
+# Copyright (c) 1995,1996 FirePower Systems, Inc.
+#
+# $RCSfile: sources $
+# $Revision: 1.54 $
+# $Date: 1996/07/02 05:16:46 $
+# $Locker: $
+#
+#
+# Copyright (c) 1993 Microsoft Corporation
+#
+# Module Name:
+#
+# sources.
+#
+# Abstract:
+#
+# This file specifies the target component being built and the list of
+# sources files needed to build that component. Also specifies optional
+# compiler switches and libraries that are unique for the component being
+# built.
+#
+#
+#
+# Author:
+#
+# David N. Cutler (davec) 8-Apr-1993
+#
+# Revision Histoy:
+#
+# Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+#
+# NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+#
+#
+MAJORCOMP=ntos
+MINORCOMP=hal
+TARGETNAME=halfire
+TARGETTYPE=HAL
+HAL_MAJOR=3
+HAL_MINOR=00
+
+#
+# Make sure BASEDIR is set, and if it isn't set it to _NTDRIVE.
+# If _NTDRIVE is not set, then exit with error since the environment
+# does not match the expectations upon which this sources operates...
+#
+!IFNDEF BASEDIR
+! IFNDEF _NTDRIVE
+! ERROR neither BASEDIR nor _NTDRIVE is defined
+! ENDIF
+BASEDIR=$(_NTDRIVE)\NT
+!ENDIF
+
+#
+# COMMON DEFINES FOR ALL BUILD ENVIRONMENTS:
+#
+C_DEFINES= -DHAL_MAJOR=$(HAL_MAJOR) -DHAL_MINOR=$(HAL_MINOR) -DREORG
+
+#
+# Determine what style build environment this is: DDK style or ntos style....
+# Setup some library and include paths based on this evaluation.
+#
+!IFDEF DDKBUILDENV
+
+# If HALFIRE_EVAL is set, use the text in the HAL's blue screen
+# Otherwise, don't print anything out
+#
+EVAL=-DHALFIRE_EVAL=Beta
+
+!IF "$(DDKBUILDENV)" == "checked"
+C_DEFINES=$(C_DEFINES) -DHALDEBUG_ON
+!ENDIF
+
+INCLUDES=$(BASEDIR)\src\hal\inc;$(BASEDIR)\private\ntos\inc
+INCLUDES=$(BASEDIR)\src\hal\x86new;$(INCLUDES)
+LIBDIR=$(BASEDIR)
+C_DEFINES=$(C_DEFINES) -DPRINT_IT $(EVAL)
+TARGETPATH=$(BASEDIR)\lib
+TARGETLIBS=$(BASEDIR)\lib\*\$(DDKBUILDENV)\x86new.lib $(LIBDIR)\lib\*\$(DDKBUILDENV)\libc.lib
+DESTINATION_DIR=ppc\$(DDKBUILDENV)
+
+!ELSE
+
+#
+# Make sure this is an ntos environment since it did not pass the DDK env test...
+#
+! IF EXIST (..\..\..\ntos\nthals)
+
+INCLUDES=$(BASEDIR)\private\ntos\nthals\x86new;$(BASEDIR)\private\ntos\inc
+LIBDIR=$(BASEDIR)\public\sdk
+TARGETPATH=$(LIBDIR)\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\*\x86new.lib $(LIBDIR)\lib\*\libc.lib
+
+! IFDEF NTDEBUG
+C_DEFINES=$(C_DEFINES) -DHALDEBUG_ON
+! ENDIF
+
+! ELSE
+! ERROR BUILD ENVIRONMENT IS NOT RECOGNIZABLE!!
+! ENDIF
+
+!ENDIF # end of check for ddk or ntos build environment...
+
+
+# -DHALDEBUG_ON \
+# FirePower General Defines
+#
+# FIREPOWER_DAYTONA: General Changes for our platform
+# RES_640_480:
+# PROCESSOR604_22: sync inst. instead of eieio
+# HALDEBUG_ON: compile in HalpDebugPrintf support:
+# This routine performs debugprintfs
+# as well as debugprintfs.
+#
+# REMOVE THE FOLLOWING DEFINES FOR BUILDING AT MICROSOFT
+# HAL_SUPPORT_606: Provide HAL Support for 606 instead of kernel
+#
+C_DEFINES= $(C_DEFINES) \
+ -DFIREDATA \
+ -DFIREPOWER_DAYTONA
+
+#
+# FirePower Multi-Processor Specific Defines
+#
+# FIREPOWER_MP: Generic for the moment [10.30.94]
+# _MP_PPC: Kernel Define for MP Support
+#
+#
+C_DEFINES= $(C_DEFINES) \
+ -DFIREPOWER_MP \
+ -D_MP_PPC
+
+
+!IFNDEF BUILTBY
+C_DEFINES= $(C_DEFINES) -DBUILTBY=\"$(USERNAME)\"
+!ELSE
+C_DEFINES= $(C_DEFINES) -DBUILTBY=\"$(BUILTBY)\"
+!ENDIF
+
+#
+# announce to the user the set of variables used:
+#
+!IFDEF VERBOSE
+
+!MESSAGE
+!MESSAGE =================================================
+!MESSAGE BASEDIR: $(BASEDIR)
+!MESSAGE INCLUDES: $(INCLUDES)
+!MESSAGE TARGETPATH: $(TARGETPATH)
+!MESSAGE TARGETLIBS: $(TARGETLIBS)
+!MESSAGE C_DEFINES: $(C_DEFINES)
+!MESSAGE =================================================
+!MESSAGE
+
+!ENDIF
+
+SOURCES=
+
+HALPPC_SOURCES=hal.rc \
+ ..\drivesup.c \
+ ..\bushnd.c \
+ ppc\pxport.c \
+ ppc\pxinithl.c \
+ ppc\x86bios.c \
+ ppc\pxenviro.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxsiosup.c \
+ ppc\pxmemctl.c \
+ ppc\pxdisp.c \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxmapio.c \
+ ppc\pxsysint.c \
+ ppc\pxtime.c \
+ ppc\pxreturn.c \
+ ppc\pxintsup.s \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\pxflshio.c \
+ ppc\pxmisc.s \
+ ppc\pxpcisup.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(PPC)
+!IFNDEF DDKBUILDENV
+NTTARGETFILES=ppc\phvrsion.c
+!ELSE
+NTTARGETFILES=\
+ $(TARGETPATH)\$(DESTINATION_DIR)\halfire.lib \
+ $(TARGETPATH)\$(DESTINATION_DIR)\halfire.dll
+!ENDIF
+!ENDIF
+
+#
+# Sources required for the FirePower Machines
+#
+FIREPOWER_SOURCES=$(HALPPC_SOURCES)\
+ ppc\fpi2c.c \
+ ppc\fpcpu.s\
+ ppc\fp82091.c\
+ ppc\fpds1385.c\
+ ppc\fpdcc.c \
+ ppc\fpbat.c \
+ ppc\fppcisup.c \
+ ppc\fpBt445.c \
+ ppc\fplibc.c \
+ ppc\fprgstry.c \
+ ppc\fpints.c \
+ ppc\phprods.c\
+ ppc\phcalls.c\
+ ppc\phsystem.s \
+ ppc\ctrlops.c \
+ ppc\sysbios.c \
+ ppc\pcibios.c
+
+PPC_SOURCES=$(FIREPOWER_SOURCES) \
+ ppc\phvrsion.c
+
diff --git a/private/ntos/nthals/halflex/adjust.c b/private/ntos/nthals/halflex/adjust.c
new file mode 100644
index 000000000..c42bacc93
--- /dev/null
+++ b/private/ntos/nthals/halflex/adjust.c
@@ -0,0 +1,185 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+Copyright (c) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ adjust.c
+
+Abstract:
+
+ This module contains platform-independent slot resource adjust routines.
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#include "halp.h"
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpAdjustResourceListUpperLimits)
+#endif
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ )
+/*++
+
+Routine Description:
+
+ Adjust a pResource list with respect to the upper bounds supplied.
+ (A resource is changed only if it execceds the maximum.)
+
+Arguments:
+
+ pResouceList - Resource list to be checked.
+
+ MaximumPortAddress - Maximum I/O port allowed.
+
+ MaximumMemoryAddress - Maximum I/O memory address allowed.
+
+ MaximumInterruptVector - Maximum interrupt vector allowed.
+
+ MaximumDmaChannel - Maximum dma channel allowed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+
+ //
+ // Walk each ResourceList and shrink any values to system limits
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ //
+ // Make sure descriptor limits fall within the
+ // CompleteList->InterfaceType & CompleteList->BusNumber.
+ //
+ //
+
+ switch (Descriptor->Type) {
+ case CmResourceTypePort:
+ if (Descriptor->u.Port.MaximumAddress.QuadPart >
+ MaximumPortAddress.QuadPart) {
+
+ Descriptor->u.Port.MaximumAddress = MaximumPortAddress;
+ }
+
+ break;
+
+ case CmResourceTypeInterrupt:
+ if (Descriptor->u.Interrupt.MaximumVector >
+ MaximumInterruptVector ) {
+
+ Descriptor->u.Interrupt.MaximumVector =
+ MaximumInterruptVector;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+ if (Descriptor->u.Memory.MaximumAddress.QuadPart >
+ MaximumMemoryAddress.QuadPart) {
+
+ Descriptor->u.Memory.MaximumAddress =
+ MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (Descriptor->u.Dma.MaximumChannel >
+ MaximumDmaChannel ) {
+
+ Descriptor->u.Dma.MaximumChannel =
+ MaximumDmaChannel;
+ }
+ break;
+
+#if DBG
+ default:
+ DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
+ break;
+#endif
+ }
+
+ //
+ // Next descriptor
+ //
+ Descriptor++;
+ }
+
+ //
+ // Next Resource List
+ //
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+ }
+
+}
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts pResourceList to keep it in the bounds of ISA bus
+ resources.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ LARGE_INTEGER li64k, limem;
+
+ li64k.QuadPart = 0xffff;
+ limem.QuadPart = 0xffffff;
+
+ HalpAdjustResourceListUpperLimits (
+ pResourceList,
+ li64k, // Bus supports up to I/O port 0xFFFF
+ limem, // Bus supports up to memory 0xFFFFFF
+ 15, // Bus supports up to 15 IRQs
+ 7 // Bus supports up to Dma channel 7
+ );
+
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halflex/allstart.c b/private/ntos/nthals/halflex/allstart.c
new file mode 100644
index 000000000..8d81b6eb8
--- /dev/null
+++ b/private/ntos/nthals/halflex/allstart.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/alpha/addrsup.c b/private/ntos/nthals/halflex/alpha/addrsup.c
new file mode 100644
index 000000000..08174ae45
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/addrsup.c
@@ -0,0 +1,820 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the EB64+ system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen (Digital) 30-Jun-1994
+ Added code to check the new PCI Memory MAp address range which is
+ impacted by the EPEC HAXR1.
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+#define HAL_MAKE_LQVA(PA) (LONGLONG)HAL_MAKE_QVA(PA)
+#define HAL_MAKE_TA(PA,ByteOffset) (LONGLONG)(PA) + (LONGLONG)((ByteOffset) << IO_BIT_SHIFT)
+
+#define KERNEL_PCI_VGA_VIDEO_ROM (LONGLONG)(0x8000000000000000)
+#define USER_PCI_VGA_VIDEO_ROM (LONGLONG)(0x4000000000000000)
+
+PLATFORM_RANGE_LIST Apoc10Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Apoc20Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue0Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue1Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Apoc10Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_APOC1_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Apoc20Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Isa , 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Isa , 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_APOC2_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue0Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue1Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Isa , 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Isa , 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ ULONG i;
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ LONGLONG Offset;
+ PVOID va = 0; // note, this is used for a placeholder
+
+//BusAddress.HighPart = 0;
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+
+ //
+ // PCI Bus 0 is different than PCI Bus 1, but all other PCI busses are the same a PCI Bus 1
+ //
+
+ if (InterfaceType == PCIBus) {
+
+ switch (HalpMotherboardType) {
+ case TREBBIA13 :
+ if (BusNumber > 1) {
+ BusNumber = 1;
+ }
+ break;
+
+ case TREBBIA20 :
+ if (BusNumber == 0) {
+
+ //
+ // There are no resources in PCI Bus #0. It only contains the memory system and bridges.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+ break;
+
+ default :
+
+//DbgPrint(" Invalid Motherboard Type\n\r");
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ }
+
+ //
+ // If the VGA decodes are not enabled on the DEC PCI-PCI bridge associated with this
+ // memory range, then fail the translation.
+ //
+
+ if (!(HalpVgaDecodeBusNumber & (1<<BusNumber)) &&
+ BusAddress.QuadPart < (LONGLONG)0x0000000000100000 &&
+ (((ADDRESS_SPACE_TYPE)(*AddressSpace) == BusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserBusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == KernelPciDenseMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserPciDenseMemory) )) {
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Search the table for a valid mapping.
+ //
+
+ for(i=0;HalpRangeList[i].InterfaceType!=MaximumInterfaceType;i++) {
+
+ if (HalpRangeList[i].InterfaceType == InterfaceType &&
+ HalpRangeList[i].BusNumber == BusNumber &&
+ HalpRangeList[i].AddressType == (ADDRESS_SPACE_TYPE)(*AddressSpace) &&
+ BusAddress.QuadPart >= HalpRangeList[i].Base &&
+ BusAddress.QuadPart <= HalpRangeList[i].Limit ) {
+
+ TranslatedAddress->QuadPart = HalpRangeList[i].SystemBase;
+ *AddressSpace = HalpRangeList[i].SystemAddressSpace;
+
+ if (TranslatedAddress->QuadPart & KERNEL_PCI_VGA_VIDEO_ROM) {
+ TranslatedAddress->QuadPart &= ~KERNEL_PCI_VGA_VIDEO_ROM;
+ TranslatedAddress->QuadPart += (LONGLONG)HalpPlatformSpecificExtension->PciVideoExpansionRomAddress;
+ }
+
+ if (TranslatedAddress->QuadPart & USER_PCI_VGA_VIDEO_ROM) {
+ TranslatedAddress->QuadPart &= ~USER_PCI_VGA_VIDEO_ROM;
+ TranslatedAddress->QuadPart += (LONGLONG)(HalpPlatformSpecificExtension->PciVideoExpansionRomAddress << IO_BIT_SHIFT);
+ }
+
+ Offset = BusAddress.QuadPart - HalpRangeList[i].Base;
+ if (*AddressSpace == 0) {
+ Offset = Offset << IO_BIT_SHIFT;
+ }
+
+ TranslatedAddress->QuadPart += Offset;
+
+ if (*AddressSpace == 0) {
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ if (!HalpMiniTlbAllocateEntry(HalCreateQva(*TranslatedAddress,va),TranslatedAddress)) {
+
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+//DbgPrint(" Failed to allocate MiniTlb\n\r");
+
+ //
+ // A valid mapping was found, but the resources needed for the mapping could not be allocated.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ }
+ }
+
+ //
+ // If this is a UserPciDenseMemory mapping then let user call MmMapIoSpace()
+ //
+
+ if (*AddressSpace == 2) {
+ *AddressSpace = 0;
+ }
+
+//DbgPrint(" TranslatedAddress = %08x %08x AS=%d\n\r",TranslatedAddress->HighPart,TranslatedAddress->LowPart,*AddressSpace);
+
+ return(TRUE);
+ }
+ }
+
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+//DbgPrint(" Failed\n\r");
+
+ //
+ // A valid mapping was not found.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->QuadPart = 0;
+ return(FALSE);
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+ PVOID qva;
+ ULONG AddressSpace;
+
+ if (VA != 0) {
+
+ AddressSpace = PA.HighPart & 0x0f;
+
+ //
+ // See if the physical address is in cached memory space.
+ //
+
+ if (AddressSpace == 0 && PA.LowPart < 0x40000000) {
+
+ return(VA);
+ }
+
+ //
+ // See if the physical address is in PCI dense memory.
+ //
+
+ if (AddressSpace == ((HalpPciDenseBasePhysicalSuperPage >> 32) & 0x0f)) {
+
+ return(VA);
+ }
+
+ //
+ // See if the physical address is in non cached memory.
+ //
+
+ if (AddressSpace == ((HalpNoncachedDenseBasePhysicalSuperPage >> 32) & 0x0f) && PA.LowPart < 0x40000000) {
+
+ return(VA);
+ }
+ }
+
+ //
+ // Otherwise, the physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(RtlLargeIntegerShiftRight(PA, IO_BIT_SHIFT).LowPart & ~(DTI_QVA_SELECTORS));
+ qva = (PVOID)((ULONG)qva | DTI_QVA_ENABLE);
+
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ }
+
+ return(qva);
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+ //
+ // For EB64+ we have only 2 bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & DTI_QVA_SELECTORS) == DTI_QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/alphaio.s b/private/ntos/nthals/halflex/alpha/alphaio.s
new file mode 100644
index 000000000..f9d7471c6
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/alphaio.s
@@ -0,0 +1,1482 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alphaio.s
+
+
+Abstract:
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ 12-Jul-1994 - Eric Rehm - Added dense space I/O
+
+ 27-July-1994 - Sameer Dekate
+
+ Make a common file for all machines and optimize Read/Write
+ register buffer routines. Made a common routine with different
+ entry points for READ & WRITE_REGISTER_BUFFER routines
+
+--*/
+
+#include "halalpha.h"
+#include "apoc.h"
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+IoRa: .space 8 // space for return address
+IoS0: .space 8 // space for S0
+IoS1: .space 8 // space for S1
+IoS2: .space 8 // space for S2
+IoIrql: .space 8 // space for local variable
+IoFrameLength: //
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+#define EV4_IO(FastIoRoutine) \
+ ldq t0, HalpPciDenseBasePhysicalSuperPage; \
+ ldl t1, HalpIoArchitectureType; \
+ beq t1, FastIoRoutine; \
+ and a0, DTI_QVA_SELECTORS, t1; \
+ xor t1, DTI_QVA_ENABLE, t1; \
+ bne t1, FastIoRoutine; \
+ lda sp, -IoFrameLength(sp); \
+ stq ra, IoRa(sp); \
+ stq s0, IoS0(sp); \
+ stq s1, IoS1(sp); \
+ stq s2, IoS2(sp); \
+ or a0, a0, s0; \
+ or a1, a1, s1; \
+ or a2, a2, s2; \
+ or zero, HIGH_LEVEL, a0; \
+ addq sp, IoIrql, a1; \
+ bsr ra, KeRaiseIrql; \
+ or s0, s0, a0; \
+ bsr ra, HalpMiniTlbResolve; \
+ or v0, v0, a0; \
+ or s1, s1, a1; \
+ or s2, s2, a2; \
+ ldq t0, HalpPciDenseBasePhysicalSuperPage; \
+ bsr ra, FastIoRoutine; \
+ or v0, v0, s0; \
+ ldq a0, IoIrql(sp); \
+ and a0, 0xff, a0; \
+ bsr ra, KeLowerIrql; \
+ or s0, s0, v0; \
+ ldq s2, IoS2(sp); \
+ ldq s1, IoS1(sp); \
+ ldq s0, IoS0(sp); \
+ ldq ra, IoRa(sp); \
+ lda sp, IoFrameLength(sp); \
+ ret zero, (ra)
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+ ALTERNATE_ENTRY(READ_PORT_UCHAR)
+ EV4_IO(EV5_READ_PORT_UCHAR)
+ .end READ_REGISTER_UCHAR
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+ ALTERNATE_ENTRY(READ_PORT_USHORT)
+ EV4_IO(EV5_READ_PORT_USHORT)
+ .end READ_REGISTER_USHORT
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+ ALTERNATE_ENTRY(READ_PORT_ULONG)
+ EV4_IO(EV5_READ_PORT_ULONG)
+ .end READ_REGISTER_ULONG
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+ ALTERNATE_ENTRY(WRITE_PORT_UCHAR)
+ EV4_IO(EV5_WRITE_PORT_UCHAR)
+ .end WRITE_REGISTER_UCHAR
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+ ALTERNATE_ENTRY(WRITE_PORT_USHORT)
+ EV4_IO(EV5_WRITE_PORT_USHORT)
+ .end WRITE_REGISTER_USHORT
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+ ALTERNATE_ENTRY(WRITE_PORT_ULONG)
+ EV4_IO(EV5_WRITE_PORT_ULONG)
+ .end WRITE_REGISTER_ULONG
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+ EV4_IO(EV5_READ_PORT_BUFFER_UCHAR)
+ .end READ_PORT_BUFFER_UCHAR
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+ EV4_IO(EV5_READ_PORT_BUFFER_USHORT)
+ .end READ_PORT_BUFFER_USHORT
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+ EV4_IO(EV5_READ_PORT_BUFFER_ULONG)
+ .end READ_PORT_BUFFER_ULONG
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+ EV4_IO(EV5_WRITE_PORT_BUFFER_UCHAR)
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+ EV4_IO(EV5_WRITE_PORT_BUFFER_USHORT)
+ .end WRITE_PORT_BUFFER_USHORT
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+ EV4_IO(EV5_WRITE_PORT_BUFFER_ULONG)
+ .end WRITE_PORT_BUFFER_ULONG
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+ EV4_IO(EV5_READ_REGISTER_BUFFER_UCHAR)
+ .end READ_REGISTER_BUFFER_UCHAR
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_USHORT)
+ EV4_IO(EV5_READ_REGISTER_BUFFER_USHORT)
+ .end READ_REGISTER_BUFFER_USHORT
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+ EV4_IO(EV5_READ_REGISTER_BUFFER_ULONG)
+ .end READ_REGISTER_BUFFER_ULONG
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+ EV4_IO(EV5_WRITE_REGISTER_BUFFER_UCHAR)
+ .end WRITE_REGISTER_BUFFER_UCHAR
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+ EV4_IO(EV5_WRITE_REGISTER_BUFFER_USHORT)
+ .end WRITE_REGISTER_BUFFER_USHORT
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+ EV4_IO(EV5_WRITE_REGISTER_BUFFER_ULONG)
+ .end WRITE_REGISTER_BUFFER_ULONG
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ SBTTL( "Read I/O byte" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(EV5_READ_PORT_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ mb
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extbl v0, t3, v0 // get correct byte
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_UCHAR
+
+
+ SBTTL( "Read I/O word(16 bits)" )
+//++
+//
+// USHORT
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(EV5_READ_PORT_USHORT)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // get the longword
+ extwl v0,t3,v0 // get the correct word
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0,t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extwl v0, t3, v0 // get correct word
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_USHORT
+
+
+ SBTTL( "Read I/O longword(32 bits)" )
+//++
+//
+// ULONG
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(EV5_READ_PORT_ULONG)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // read the longword
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_ULONG
+
+ SBTTL( "Write I/O byte" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva,
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Writes a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(EV5_WRITE_PORT_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ insbl a1,t3,t4 // put the byte in the correct position
+ stl t4, (t0) // write the byte
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+ insbl a1, t3, t2 // put byte into position
+ bis t1, t2, t1 // merge byte in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write I/O word (16 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva,
+// IN USHORT Value
+// )
+//
+// Routine Description:
+//
+// Writes a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(EV5_WRITE_PORT_USHORT)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1,t3,t2 // put the word in the correct place
+ stl t2, (t0) // write the word
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, t2 // put word into position
+ bis t1, t2, t1 // merge in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write I/O longword (32 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(EV5_WRITE_PORT_ULONG)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ stl a1, (a0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_ULONG
+
+
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ bne a2, 2b // while count != 0
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ addl a1, 4, a1 // increment buffer
+ bne a2, 2b // while count != 0
+
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(EV5_READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(EV5_READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ zap a0, 0xf0, a0 // clear <63:32>
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(EV5_WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(EV5_WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(EV5_WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store to buffer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+//++
+//
+// VOID
+// HalpWriteAbsoluteUlong(
+// IN ULONG HighPart,
+// IN ULONG LowPart,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes Value to the processor address given in HighPart and LowPart.
+//
+// Arguments:
+//
+// HighPart(a0) - Upper 32 bits of address
+//
+// LowPart(a1) - Lower 32 bits of address
+//
+// Value(a2) - Value to write
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteAbsoluteUlong)
+ sll a0, 32, t0 // Shift Upper 32 bits of address into position
+ zap t0, 0x0f, t0 // Clear lower 32 bits of shifted address
+ zap a1, 0xf0, a1 // Clear upper 32 of lower part of address
+ or a1, t0, t0 // Build 64 bit address
+ stl a2, 0x0(t0) // Write value to address
+ mb // Memory Barrier
+ ret zero, (ra) // return
+ .end HalpWriteAbsoluteUlong
+
+//++
+//
+// ULONG
+// HalpReadAbsoluteUlong(
+// IN ULONG HighPart,
+// IN ULONG LowPart
+// )
+//
+// Routine Description:
+//
+// Reads a value from the processor address given in HighPart and LowPart.
+//
+// Arguments:
+//
+// HighPart(a0) - Upper 32 bits of address
+//
+// LowPart(a1) - Lower 32 bits of address
+//
+// Return Value:
+//
+// 32 bit value read from the processor address.
+//
+//--
+
+ LEAF_ENTRY(HalpReadAbsoluteUlong)
+ sll a0, 32, t0 // Shift Upper 32 bits of address into position
+ zap t0, 0x0f, t0 // Clear lower 32 bits of shifted address
+ zap a1, 0xf0, a1 // Clear upper 32 of lower part of address
+ or a1, t0, t0 // Build 64 bit address
+ mb // Memory Barrier
+ ldl v0, 0x0(t0) // Read value from address
+ ret zero, (ra) // return
+ .end HalpReadAbsoluteUlong
+
+
diff --git a/private/ntos/nthals/halflex/alpha/apoc.h b/private/ntos/nthals/halflex/alpha/apoc.h
new file mode 100644
index 000000000..85e3a8dc2
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/apoc.h
@@ -0,0 +1,167 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ apoc.h
+
+Abstract:
+
+ This file contains definitions specific to the Apocalypse (ALPHA EV5)
+ and Rogue (ALPHA EV4) processor modules.
+
+Author:
+
+ Michael D. Kinney 1-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#define DTI_QVA_ENABLE (0x80000000) // Identify VA as a QVA
+#define DTI_QVA_SELECTORS (0xc0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+//
+// Constant used by dense space I/O routines
+//
+
+#define APOC1_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000)
+#define APOC2_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfe00000000)
+#define ROGUE_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffc0100000000)
+
+//
+// Noncached Dense Memory address spaces.
+//
+
+#define APOC1_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000)
+#define APOC2_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000)
+#define ROGUE_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffc0100000000)
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( DTI_QVA_ENABLE | (ULONG)((PA) >> IO_BIT_SHIFT) & ~(DTI_QVA_SELECTORS) ) )
+
+
+
+//
+// Define physical address spaces for Apocalypse
+//
+
+#define TREB1_APOC1_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB1_APOC1_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define TREB1_APOC2_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB1_APOC2_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define TREB2_APOC1_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC1_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC1_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define TREB2_APOC2_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC2_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC2_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define APOC1_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0xfffffcfe00000000)
+#define APOC1_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0xfffffcfe00000000)
+#define APOC1_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0xfffffcff00000000)
+#define APOC1_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0b00000000)
+
+#define APOC2_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0xfffffcb800000000)
+#define APOC2_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0xfffffcb800000000)
+#define APOC2_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0xfffffcd800000000)
+#define APOC2_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0e00000000)
+#define APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0f00000000)
+
+#define APOC_DMA_CACHE_BASE_PHYSICAL ((ULONGLONG)0x0b007c0000)
+#define APOC_CACHE_FLUSH_BASE_PHYSICAL ((ULONGLONG)0x003fe00000)
+#define APOC_DMA_CACHE_SIZE 0x00040000
+#define APOC_CACHE_FLUSH_SIZE 0x00200000
+
+//
+// Define physical address spaces for Rogue
+//
+
+#define ROGUE_TRANSLATED_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+
+#define TREB1_ROGUE_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000)
+#define TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000)
+#define TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB1_ROGUE_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0100000000)
+
+#define TREB2_ROGUE_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000)
+#define TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000)
+#define TREB2_ROGUE_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000)
+#define TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000)
+#define TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0100000000)
+
+#define ROGUE_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0x0200000000)
+#define ROGUE_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0x03c0000000)
+#define ROGUE_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0100000000)
+#define ROGUE_DMA_CACHE_BASE_PHYSICAL ((ULONGLONG)0x01007c0000)
+#define ROGUE_CACHE_FLUSH_BASE_PHYSICAL ((ULONGLONG)0x003fc00000)
+#define ROGUE_DMA_CACHE_SIZE 0x00040000
+#define ROGUE_CACHE_FLUSH_SIZE 0x00400000
diff --git a/private/ntos/nthals/halflex/alpha/arcssup.c b/private/ntos/nthals/halflex/alpha/arcssup.c
new file mode 100644
index 000000000..6169f9c3b
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/arcssup.c
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ arcssup.c
+
+Abstract:
+
+ This module allocates resources before a call to the ARCS Firmware, and
+ frees those reources after the call returns.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+static KIRQL HalpArcsIrql;
+
+VOID
+HalpAllocateArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocated resources required before an ARCS Firmware call is made.
+ On an ALPHA system, this is a NULL function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+
+{
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ KeRaiseIrql(HIGH_LEVEL, &HalpArcsIrql);
+ HalpMiniTlbSaveState();
+ }
+}
+
+VOID
+HalpFreeArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the TLB entry that was reserved for the ARCS
+ Firmware call. On an ALPHA system, this is a NULL function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ HalpMiniTlbRestoreState();
+ KeLowerIrql(HalpArcsIrql);
+ }
+}
diff --git a/private/ntos/nthals/halflex/alpha/dtidef.h b/private/ntos/nthals/halflex/alpha/dtidef.h
new file mode 100644
index 000000000..2301a1556
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/dtidef.h
@@ -0,0 +1,149 @@
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dtidef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 26-Nov-1990
+
+Revision History:
+
+--*/
+
+#ifndef _DTIDEF_
+#define _DTIDEF_
+
+#include "uniflex.h"
+#include "apoc.h"
+#include "platform.h"
+
+//
+// Define the data structure returned by a private vector firmware function
+// that contains a set of system parameters.
+//
+
+typedef struct PLATFORM_SPECIFIC_EXTENSION {
+ UCHAR PciInterruptToIsaIrq[12];
+ ULONG PciVideoExpansionRomAddress;
+ PVOID AdvancedSetupInfo;
+} PLATFORM_SPECIFIC_EXTENSION;
+
+typedef struct TREB13SETUPINFO {
+ ULONG Reserved1:16;
+ ULONG Drive0Type:4;
+ ULONG Drive1Type:4;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq10:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq11:4;
+ ULONG Lpt1Irq:8;
+ ULONG Lpt2Irq:8;
+ ULONG Lpt3Irq:8;
+ ULONG SerialMousePort:8;
+ ULONG EnableAmd1:1;
+ ULONG EnableAmd2:1;
+ ULONG EnableX86Emulator:1;
+ ULONG Reserved2:5;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG Reserved3:7;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG Reserved4:6;
+ ULONG EnableDelays:1;
+ ULONG Reserved5:7;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved6:7;
+} TREB13SETUPINFO;
+
+typedef struct TREB20SETUPINFO {
+ ULONG Isa0Drive0Type:4;
+ ULONG Isa0Drive1Type:4;
+ ULONG Isa1Drive0Type:4;
+ ULONG Isa1Drive1Type:4;
+ ULONG SerialMousePort:8;
+ ULONG Isa0Lpt1Irq:8;
+ ULONG Isa0Lpt2Irq:8;
+ ULONG Isa0Lpt3Irq:8;
+ ULONG Isa1Lpt1Irq:8;
+ ULONG Isa1Lpt2Irq:8;
+ ULONG Isa1Lpt3Irq:8;
+ ULONG EnableNcr:1;
+ ULONG EnableX86Emulator:1;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG EnableDelays:1;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved1:1;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq4:4;
+ ULONG PciInterruptToIsaIrq5:4;
+ ULONG PciInterruptToIsaIrq6:4;
+ ULONG PciInterruptToIsaIrq7:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG NcrTermLow:1;
+ ULONG NcrTermHigh:1;
+ ULONG Reserved2:6;
+} TREB20SETUPINFO;
+
+//
+// Define the data structure used to describe all bus translations.
+//
+
+typedef struct PLATFORM_RANGE_LIST {
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ADDRESS_SPACE_TYPE AddressType;
+ ULONG SystemAddressSpace;
+ LONGLONG SystemBase;
+ LONGLONG Base;
+ LONGLONG Limit;
+} PLATFORM_RANGE_LIST, *PPLATFORM_RANGE_LIST;
+
+//
+// Define clock constants and clock levels.
+//
+
+#define UNIFLEX_CLOCK_LEVEL UNIFLEX_EISA_VECTORS+0 // Interval clock level is on ISA IRQ 0
+#define UNIFLEX_ISA_DEVICE_LEVEL 5 // ISA bus interrupt level
+#define UNIFLEX_EISA_DEVICE_LEVEL 5 // EISA bus interrupt level
+#define UNIFLEX_PCI_DEVICE_LEVEL 5 // PCI bus interrupt level
+#define UNIFLEX_CLOCK2_LEVEL UNIFLEX_CLOCK_LEVEL
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define UNIFLEX_ISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_ISA_VECTOR (15 + UNIFLEX_ISA_VECTORS)
+#define UNIFLEX_EISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_EISA_VECTOR (15 + UNIFLEX_EISA_VECTORS)
+#define UNIFLEX_ISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_ISA1_VECTOR (15 + UNIFLEX_ISA1_VECTORS)
+#define UNIFLEX_EISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_EISA1_VECTOR (15 + UNIFLEX_EISA1_VECTORS)
+#define UNIFLEX_PCI_VECTORS 100
+#define UNIFLEX_MAXIMUM_PCI_VECTOR (15 + UNIFLEX_PCI_VECTORS)
+
+#endif // _DTIDEF_
diff --git a/private/ntos/nthals/halflex/alpha/ev4int.c b/private/ntos/nthals/halflex/alpha/ev4int.c
new file mode 100644
index 000000000..7b64b42c8
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev4int.c
@@ -0,0 +1,955 @@
+/*++
+
+Copyright (C) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ ev4int.c
+
+Abstract:
+
+ This module implements the support routines to enable/disable DECchip
+ 21064-specific interrupts.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+VOID
+HalpUpdate21064PriorityTable(
+ VOID
+ );
+
+VOID
+HalpCachePcrValues(
+ VOID
+ );
+
+
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the data structures for the 21064
+ interrupt enable/disable routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ EV4Irq Irq;
+
+ //
+ // Initialize each entry in the Irq Status Table.
+ //
+
+ for( Irq=Irq0; Irq<MaximumIrq; Irq++ ){
+ HAL_21064_PCR->IrqStatusTable[Irq].Enabled = FALSE;
+ HAL_21064_PCR->IrqStatusTable[Irq].Irql = PASSIVE_LEVEL;
+ HAL_21064_PCR->IrqStatusTable[Irq].Vector = PASSIVE_VECTOR;
+ HAL_21064_PCR->IrqStatusTable[Irq].Priority = 0;
+ }
+
+ HalpUpdate21064PriorityTable();
+
+ //
+ // Write IrqlMask table entries for the Software Subtable.
+ //
+
+ Index = IRQLMASK_SFW_SUBTABLE_21064;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = APC_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = APC_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR;
+
+ //
+ // Write the IrqlMask table entries for the Performance Counter Subtable.
+ //
+
+ Index = IRQLMASK_PC_SUBTABLE_21064;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC0_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR;
+
+ return;
+
+}
+
+VOID
+HalpUpdate21064PriorityTable(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function updates the Irql Mask Table in the PCR of the current
+ processor. It is called whenever an interrupt is enabled or disabled.
+ The source of the data used to update the table is the global
+ IrqStatusTable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG InterruptMask;
+ EV4Irq Irq;
+ KIRQL Irql;
+ ULONG IrqlMaskIndex;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Cycle through each entry of the interrupt mask table for the
+ // hardware entries. For each entry, compute the highest priority
+ // entry that could be asserted for the mask entry and is enabled.
+ // The priority is determined first by Irql level, higher Irql
+ // indicates higher priority, and then, if there are multiple
+ // enabled, asserted interrupts of the same Irql, by a relative
+ // priority that was assigned by the caller when the interrupt
+ // was enabled.
+ //
+
+ for( InterruptMask=0;
+ InterruptMask < IRQLMASK_HDW_SUBTABLE_21064_ENTRIES;
+ InterruptMask++ ){
+
+ Vector = PASSIVE_VECTOR;
+ Irql = PASSIVE_LEVEL;
+ Priority = 0;
+
+ //
+ // Check if each Irq is asserted and enabled for this interrupt
+ // mask.
+ //
+
+ for( Irq=Irq0; Irq<MaximumIrq; Irq++ ){
+ ULONG IrqMask = 1 << Irq;
+
+ if( (IrqMask & InterruptMask) &&
+ (HAL_21064_PCR->IrqStatusTable[Irq].Enabled == TRUE) &&
+ (HAL_21064_PCR->IrqStatusTable[Irq].Irql >= Irql) ){
+
+ //
+ // If the new Irq has a higher Irql than the highest
+ // currently selected or has a higher relative priority
+ // then this is the Irq to be selected if this mask
+ // pattern is selected.
+ //
+
+ if( (HAL_21064_PCR->IrqStatusTable[Irq].Irql > Irql) ||
+ (HAL_21064_PCR->IrqStatusTable[Irq].Priority > Priority) ){
+
+ Irql = HAL_21064_PCR->IrqStatusTable[Irq].Irql;
+ Priority = HAL_21064_PCR->IrqStatusTable[Irq].Priority;
+ Vector = HAL_21064_PCR->IrqStatusTable[Irq].Vector;
+
+ }
+
+ }
+ }
+
+ IrqlMaskIndex = IRQLMASK_HDW_SUBTABLE_21064 + InterruptMask;
+ PCR->IrqlMask[IrqlMaskIndex].IrqlTableIndex = Irql;
+ PCR->IrqlMask[IrqlMaskIndex].IDTIndex = (USHORT)Vector;
+ }
+}
+
+VOID
+HalpDisable21064HardwareInterrupt(
+ IN ULONG Irq
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the interrupt connected to the specified Irq
+ pin on the 21064.
+
+Arguments:
+
+ Irq - Supplies the number of the Irq pin for the interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Irq ){
+
+ case Irq0:
+
+ IetEntry[IrqlIndex].Irq0Enable = 0;
+ break;
+
+ case Irq1:
+
+ IetEntry[IrqlIndex].Irq1Enable = 0;
+ break;
+
+ case Irq2:
+
+ IetEntry[IrqlIndex].Irq2Enable = 0;
+ break;
+
+ case Irq3:
+
+ IetEntry[IrqlIndex].Irq3Enable = 0;
+ break;
+
+ case Irq4:
+
+ IetEntry[IrqlIndex].Irq4Enable = 0;
+ break;
+
+ case Irq5:
+
+ IetEntry[IrqlIndex].Irq5Enable = 0;
+ break;
+
+
+ } //end switch( Irq )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Update the Irq status table and reflect the changes in the
+ // PCR IrqlMask table.
+ //
+
+ HAL_21064_PCR->IrqStatusTable[Irq].Enabled = FALSE;
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpDisable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the indicated software interrupt level.
+
+Arguments:
+
+ Irql - Supplies the software interrupt level to disable (APC_LEVEL or
+ DISPATCH_LEVEL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+
+ switch( Irql ){
+
+ //
+ // APC Interrupt level.
+ //
+
+ case APC_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].ApcEnable = 0;
+ break;
+
+ //
+ // DPC Interrupt level.
+ //
+
+ case DISPATCH_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].DispatchEnable = 0;
+ IetEntry[APC_LEVEL].DispatchEnable = 0;
+ break;
+
+ //
+ // Unrecognized software interrupt level.
+ //
+
+ default:
+
+ NOTHING;
+
+#if HALDBG
+
+ DbgPrint( "HalpDisable21064SoftwareInterrupt, Bad software level= %x\n",
+ Irql );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+VOID
+HalpDisable21064PerformanceInterrupt(
+ IN ULONG Vector
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the specified performance counter interrupt.
+
+Arguments:
+
+ Vector - Supplies the interrupt vector number of the performance counter
+ interrupt which is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 0;
+ break;
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 0;
+ break;
+
+
+ } //end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisable21064CorrectableInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the correctable read error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ IetEntry[IrqlIndex].CorrectableReadEnable = 0;
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpEnable21064HardwareInterrupt (
+ IN ULONG Irq,
+ IN KIRQL Irql,
+ IN ULONG Vector,
+ IN UCHAR Priority
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Irq - Supplies the IRQ pin number of the interrupt that is enabled.
+
+ Irql - Supplies the Irql of the interrupting source.
+
+ Vector - Supplies the interrupt vector for the enabled interrupt.
+
+ Priority - Supplies the relative priority of the interrupt in comparison
+ with other Irqs of the same Irql.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Irq ){
+
+ case Irq0:
+
+ IetEntry[IrqlIndex].Irq0Enable = 1;
+ break;
+
+ case Irq1:
+
+ IetEntry[IrqlIndex].Irq1Enable = 1;
+ break;
+
+ case Irq2:
+
+ IetEntry[IrqlIndex].Irq2Enable = 1;
+ break;
+
+ case Irq3:
+
+ IetEntry[IrqlIndex].Irq3Enable = 1;
+ break;
+
+ case Irq4:
+
+ IetEntry[IrqlIndex].Irq4Enable = 1;
+ break;
+
+ case Irq5:
+
+ IetEntry[IrqlIndex].Irq5Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Populate the interrupt status table and then update the Irql Mask
+ // table.
+ //
+
+ HAL_21064_PCR->IrqStatusTable[Irq].Enabled = TRUE;
+ HAL_21064_PCR->IrqStatusTable[Irq].Vector = Vector;
+ HAL_21064_PCR->IrqStatusTable[Irq].Irql = Irql;
+ HAL_21064_PCR->IrqStatusTable[Irq].Priority = Priority;
+
+ HalpUpdate21064PriorityTable();
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+VOID
+HalpEnable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This routine enables the indicated software interrupt level.
+
+Arguments:
+
+ Irql - Supplies the software interrupt level to enable (APC_LEVEL or
+ DISPATCH_LEVEL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+
+ switch( Irql ){
+
+ //
+ // APC Interrupt level.
+ //
+
+ case APC_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].ApcEnable = 1;
+ break;
+
+ //
+ // DPC Interrupt level.
+ //
+
+ case DISPATCH_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].DispatchEnable = 1;
+ IetEntry[APC_LEVEL].DispatchEnable = 1;
+ break;
+
+ //
+ // Unrecognized software interrupt level.
+ //
+
+ default:
+
+ NOTHING;
+
+#if HALDBG
+
+ DbgPrint( "HalpEnable21064SoftwareInterrupt, Bad software level= %x\n",
+ Irql );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpEnable21064PerformanceInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified performance counter interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the performance counter interrupt that is
+ enabled.
+
+ Irql - Supplies the Irql of the performance counter interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 1;
+ break;
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpEnable21064CorrectableInterrupt (
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the correctable read error interrupt.
+
+Arguments:
+
+ Irql - Supplies the Irql of the correctable read error interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ IetEntry[IrqlIndex].CorrectableReadEnable = 1;
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+ULONG
+HalpGet21064PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified performance counter interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ *Irql = PROFILE_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_SECONDARY_VECTOR;
+
+ } //end switch( BusInterruptLevel )
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/ev4ints.s b/private/ntos/nthals/halflex/alpha/ev4ints.s
new file mode 100644
index 000000000..08fdaadc0
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev4ints.s
@@ -0,0 +1,300 @@
+//++
+//
+// Copyright (C) 1994,1995 Microsoft Corporation
+//
+// Module Name:
+//
+// ev4ints.s
+//
+// Abstract:
+//
+// This module implements EV4-specific interrupt handlers.
+// (the performance counters)
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//
+//--
+#include "halalpha.h"
+
+#define PC0_SECONDARY_VECTOR 11
+#define PC1_SECONDARY_VECTOR 13
+#define PcProfileCount0 PcHalReserved+8
+#define PcProfileCount1 PcProfileCount0+4
+#define PcProfileCountReload0 PcProfileCount1+4
+#define PcProfileCountReload1 PcProfileCountReload0+4
+
+ .struct 0
+ .space 8 // reserved for alignment
+PrRa: .space 8 // space for return address
+PrFrameLength: //
+
+ SBTTL("Performance Counter 0 Interrupt")
+//++
+//
+// VOID
+// Halp21064PerformanceCounter0Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 0. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 0.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21064PerformanceCounter0Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount0(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload0(v0) // get the new tick count
+ stl t0, PcProfileCount0(v0) // reset the profile interval count
+
+ ldl a1, Halp21064ProfileSource0
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount0(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21064PerformanceCounter0Interrupt
+
+
+ SBTTL("Performance Counter 1 Interrupt")
+//++
+//
+// VOID
+// Halp21064PerformanceCounter1Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 1. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 1.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21064PerformanceCounter1Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount1(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload1(v0) // get the new tick count
+ stl t0, PcProfileCount1(v0) // reset the profile interval count
+
+ ldl a1, Halp21064ProfileSource1
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount1(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21064PerformanceCounter1Interrupt
+
+//++
+//
+// VOID
+// Halp21064WritePerformanceCounter(
+// IN ULONG PerformanceCounter,
+// IN BOOLEAN Enable,
+// IN ULONG MuxControl OPTIONAL,
+// IN ULONG EventCount OPTIONAL
+// )
+//
+// Routine Description:
+//
+// Write the specified microprocessor internal performance counter.
+//
+// Arguments:
+//
+// PerformanceCounter(a0) - Supplies the number of the performance counter
+// to write.
+//
+// Enable(a1) - Supplies a boolean that indicates if the performance
+// counter should be enabled or disabled.
+//
+// MuxControl(a2) - Supplies the mux control value which selects which
+// type of event to count when the counter is enabled.
+//
+// EventCount(a3) - Supplies the event interval when the counter is
+// enabled.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(Halp21064WritePerformanceCounter)
+
+ call_pal wrperfmon // write the counter
+
+ ret zero, (ra) // return
+
+ .end Halp21064WritePerformanceCounter
+
+//++
+//
+// VOID
+// Halp21064ClearLockRegister(
+// PVOID LockAddress
+// )
+//
+// Routine Description:
+//
+// This function is called on every interrupt to clear the lock bit.
+//
+// Arguments:
+//
+// ClearLockAddress(a0) - Address in which to perform the conditional store.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(Halp21064ClearLockRegister)
+
+ mb // Force all previous write off chip
+ stl_c zero, 0x0(a0) // Clear the lock register
+ mb // Force the write to clear the lock register off chip
+ ret zero, (ra) // return
+
+ .end Halp21064ClearLockRegister
+
+
diff --git a/private/ntos/nthals/halflex/alpha/ev4prof.c b/private/ntos/nthals/halflex/alpha/ev4prof.c
new file mode 100644
index 000000000..53dc896c6
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev4prof.c
@@ -0,0 +1,585 @@
+/*++
+
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ ev4prof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV4 core. This module is appropriate for all
+ machines based on microprocessors using the EV4 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+
+//
+// Define space in the HAL-reserved part of the PCR structure for each
+// performance counter's interval count
+//
+// Note that ev4ints.s depends on these positions in the PCR.
+//
+#define PCRProfileCount ((PULONG)(HAL_21064_PCR->ProfileCount.ProfileCount))
+#define PCRProfileCountReload ((PULONG)(&HAL_21064_PCR->ProfileCount.ProfileCountReload))
+
+
+//
+// Define the currently selected profile source for each counter
+//
+KPROFILE_SOURCE Halp21064ProfileSource0;
+KPROFILE_SOURCE Halp21064ProfileSource1;
+
+#define INTERVAL_DELTA (10)
+
+//
+// Define the mapping between possible profile sources and the
+// CPU-specific settings.
+//
+typedef struct _HALP_PROFILE_MAPPING {
+ BOOLEAN Supported;
+ ULONG MuxControl;
+ ULONG Counter;
+ ULONG EventCount;
+ ULONG NumberOfTicks;
+} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING;
+
+HALP_PROFILE_MAPPING Halp21064ProfileMapping[ProfileMaximum] =
+ {
+ {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4TotalIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4PipelineDry, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4LoadInstruction, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4PipelineFrozen, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4BranchInstructions, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4TotalNonIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4DcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4IcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4BranchMispredicts, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4StoreInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4FPInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4IntegerOperate, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4DualIssues, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4PalMode, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {FALSE, 0, 0, 0, 0},
+ {FALSE, 0, 0, 0, 0}
+ };
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+
+
+NTSTATUS
+Halp21064ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ Halp21064ProfileMapping[SourceInfo->Source].EventCount *
+ Halp21064ProfileMapping[SourceInfo->Source].NumberOfTicks;
+ if (SourceInfo->Source == ProfileTotalIssues) {
+ //
+ // Convert total issues/2 back into total issues
+ //
+ SourceInfo->Interval = SourceInfo->Interval * 2;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+Halp21064ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+VOID
+Halp21064InitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKINTERRUPT InterruptObject;
+ KIRQL Irql;
+ PKPRCB Prcb = PCR->Prcb;
+ ULONG Vector;
+
+ //
+ // Establish the profile interrupt as the interrupt handler for
+ // all performance counter interrupts.
+ //
+
+ PCR->InterruptRoutine[PC0_VECTOR] = Halp21064PerformanceCounter0Interrupt;
+ PCR->InterruptRoutine[PC1_VECTOR] = Halp21064PerformanceCounter1Interrupt;
+
+ return;
+
+}
+
+
+BOOLEAN
+Hal21064QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) {
+ return(FALSE);
+ }
+
+ return(Halp21064ProfileMapping[Source].Supported);
+}
+
+
+NTSTATUS
+Hal21064SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ ULONG FastTickPeriod;
+ ULONG SlowTickPeriod;
+ ULONG TickPeriod;
+ ULONGLONG CountEvents;
+ ULONG FastCountEvents;
+ ULONG SlowCountEvents;
+ ULONGLONG TempInterval;
+
+ if (!HalQueryProfileInterval(ProfileSource)) {
+ return(STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (ProfileSource == ProfileTime) {
+
+ //
+ // Convert the clock tick period (in 100ns units ) into
+ // a cycle count period
+ //
+
+ CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod;
+ } else if (ProfileSource == ProfileTotalIssues) {
+
+ //
+ // Convert the total issue events into the wonky
+ // total issues/2 form implemented by EV4.
+ //
+
+ CountEvents = (ULONGLONG)(*Interval / 2);
+ } else {
+ CountEvents = (ULONGLONG)*Interval;
+ }
+
+ if (Halp21064ProfileMapping[ProfileSource].Counter == Ev4PerformanceCounter1) {
+ FastCountEvents = Ev4CountEvents2xx8;
+ SlowCountEvents = Ev4CountEvents2xx12;
+ } else {
+ FastCountEvents = Ev4CountEvents2xx12;
+ SlowCountEvents = Ev4CountEvents2xx16;
+ }
+
+ //
+ // Limit the interval to the smallest interval we can time.
+ //
+ if (CountEvents < FastCountEvents) {
+ CountEvents = (ULONGLONG)FastCountEvents;
+ }
+
+ //
+ // Assume we will use the fast event count
+ //
+ Halp21064ProfileMapping[ProfileSource].EventCount = FastCountEvents;
+ Halp21064ProfileMapping[ProfileSource].NumberOfTicks =
+ (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents);
+
+ //
+ // See if we can successfully use the slower period. If the requested
+ // interval is greater than the slower tick period and the difference
+ // between the requested interval and the interval that we can deliver
+ // with the slower clock is acceptable, then use the slower clock.
+ // We define an acceptable difference as a difference of less than
+ // INTERVAL_DELTA of the requested interval.
+ //
+ if (CountEvents > SlowCountEvents) {
+ ULONG NewInterval;
+
+ NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) /
+ SlowCountEvents) * SlowCountEvents);
+ if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) {
+ Halp21064ProfileMapping[ProfileSource].EventCount = SlowCountEvents;
+ Halp21064ProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents;
+ }
+ }
+
+ *Interval = Halp21064ProfileMapping[ProfileSource].EventCount *
+ Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+
+ if (ProfileSource == ProfileTime) {
+ //
+ // Convert cycle count back into 100ns clock ticks
+ //
+ // Use 64-bit integer to prevent overflow.
+ //
+ TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod);
+ *Interval = (ULONG)(TempInterval / 100000);
+ } else if (ProfileSource == ProfileTotalIssues) {
+ //
+ // Convert issues/2 count back into issues
+ //
+ TempInterval = (ULONGLONG)(*Interval) * 2;
+ *Interval = (ULONG)TempInterval;
+ }
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+Hal21064SetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
+
+VOID
+Hal21064StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG MuxControl;
+ ULONG EventCount;
+
+ //
+ // Check input to see if we are turning on a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21064ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Set the performance counter within the processor to begin
+ // counting total cycles.
+ //
+ PerformanceCounter = Halp21064ProfileMapping[ProfileSource].Counter;
+ MuxControl = Halp21064ProfileMapping[ProfileSource].MuxControl;
+
+ if (PerformanceCounter == Ev4PerformanceCounter0) {
+
+ Halp21064ProfileSource0 = ProfileSource;
+ EventCount = (Halp21064ProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ?
+ Ev4EventCountHigh :
+ Ev4EventCountLow;
+ Halp21064WritePerformanceCounter( PerformanceCounter,
+ TRUE,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[0] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[0] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC0_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+
+ } else {
+
+ Halp21064ProfileSource1 = ProfileSource;
+ EventCount = (Halp21064ProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ?
+ Ev4EventCountLow :
+ Ev4EventCountHigh;
+ Halp21064WritePerformanceCounter( PerformanceCounter,
+ TRUE,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[1] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[1] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC1_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+ }
+
+ return;
+}
+
+
+VOID
+Hal21064StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG Vector;
+
+ //
+ // Check input to see if we are turning off a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21064ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Stop the performance counter from interrupting.
+ //
+
+ PerformanceCounter = Halp21064ProfileMapping[ProfileSource].Counter;
+ Halp21064WritePerformanceCounter( PerformanceCounter,
+ FALSE,
+ 0,
+ 0 );
+
+ //
+ // Disable the performance counter interrupt.
+ //
+ if (PerformanceCounter == Ev4PerformanceCounter0) {
+ HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+ } else {
+ HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+ }
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/ev5ints.s b/private/ntos/nthals/halflex/alpha/ev5ints.s
new file mode 100644
index 000000000..71319eb58
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev5ints.s
@@ -0,0 +1,397 @@
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// ev5ints.s
+//
+// Abstract:
+//
+// This module implements EV5-specific interrupt handlers.
+// (the performance counters)
+//
+// Author:
+//
+// John Vert (jvert) 15-Nov-1994
+// Steve Brooks 14-Feb-1994 (modified from ev4ints.s)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+#define PC0_SECONDARY_VECTOR 11
+#define PC1_SECONDARY_VECTOR 13
+#define PC2_SECONDARY_VECTOR 16 // SjBfix. This is actually PC3_VECTOR
+#define PcProfileCount0 PcHalReserved+20
+#define PcProfileCount1 PcProfileCount0+4
+#define PcProfileCount2 PcProfileCount1+4
+#define PcProfileCountReload0 PcProfileCount2+4
+#define PcProfileCountReload1 PcProfileCountReload0+4
+#define PcProfileCountReload2 PcProfileCountReload1+4
+
+ .struct 0
+ .space 8 // reserved for alignment
+PrRa: .space 8 // space for return address
+PrFrameLength: //
+
+ SBTTL("Performance Counter 0 Interrupt")
+//++
+//
+// VOID
+// Halp21164PerformanceCounter0Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 0. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 0.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21164PerformanceCounter0Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount0(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload0(v0) // get the new tick count
+ stl t0, PcProfileCount0(v0) // reset the profile interval count
+
+ ldl a1, Halp21164ProfileSource0
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount0(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21164PerformanceCounter0Interrupt
+
+
+ SBTTL("Performance Counter 1 Interrupt")
+//++
+//
+// VOID
+// Halp21164PerformanceCounter1Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 1. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 1.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21164PerformanceCounter1Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount1(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload1(v0) // get the new tick count
+ stl t0, PcProfileCount1(v0) // reset the profile interval count
+
+ ldl a1, Halp21164ProfileSource1
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount1(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21164PerformanceCounter1Interrupt
+
+ SBTTL("Performance Counter 2 Interrupt")
+//++
+//
+// VOID
+// Halp21164PerformanceCounter2Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 2. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 2.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21164PerformanceCounter2Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount2(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload2(v0) // get the new tick count
+ stl t0, PcProfileCount2(v0) // reset the profile interval count
+
+ ldl a1, Halp21164ProfileSource2
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount2(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC2_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21164PerformanceCounter2Interrupt
+
+//++
+//
+// ULONGLONG
+// HalpRead21164PerformanceCounter(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Read the processor performance counter register
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The current value of the performance counter register.
+//
+//--
+
+ LEAF_ENTRY(HalpRead21164PerformanceCounter)
+
+ bis zero, 1, a1 // indicate read operation
+ call_pal wrperfmon // read the performance counter
+
+ ret zero, (ra) // return to caller
+
+ .end HalpRead21164PerformanceCounter
+
+
+//++
+//
+// VOID
+// HalpWrite21164PerformanceCounter(
+// ULONGLONG PmCtr
+// ULONG CboxMux1
+// ULONG CboxMux2
+// )
+//
+// Routine Description:
+//
+// Write the processor performance counter register
+//
+// Arguments:
+//
+// PmCtr(a0) - value to be written to the performance counter
+// CboxMux1(a1) - value to be written to Cbox mux 1 select (optional)
+// CboxMux2(a2) - value to be written to Cbox mux 2 select (optional)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWrite21164PerformanceCounter)
+
+ bis zero, a2, a3 // move arguments up
+ bis zero, a1, a2 //
+ bis zero, zero, a1 // indicate write operation
+ call_pal wrperfmon // write the performance counter
+
+ ret zero, (ra)
+
+ .end HalpWrite21164PerformanceCounter
diff --git a/private/ntos/nthals/halflex/alpha/ev5prof.c b/private/ntos/nthals/halflex/alpha/ev5prof.c
new file mode 100644
index 000000000..625fba304
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev5prof.c
@@ -0,0 +1,747 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev5prof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV5 core. This module is appropriate for all
+ machines based on microprocessors using the EV5 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Steve Brooks 14-Feb-1995 (adapted from ev4prof.c)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21164.h"
+
+//
+// Default Number of Profile Clock Ticks per sample
+//
+
+ULONG Halp21164NumberOfTicks = 1;
+ULONG Halp21164NumberOfTicksReload;
+
+//
+// Define space in the HAL-reserved part of the PCR structure for each
+// performance counter's interval count
+//
+// Note that ev5ints.s depends on these positions in the PCR.
+//
+#define PCRProfileCount ((PULONG)(HAL_21164_PCR->ProfileCount.ProfileCount))
+#define PCRProfileCountReload ((PULONG)(&HAL_21164_PCR->ProfileCount.ProfileCountReload))
+
+
+//
+// Define the currently selected profile source for each counter
+//
+KPROFILE_SOURCE Halp21164ProfileSource0;
+KPROFILE_SOURCE Halp21164ProfileSource1;
+KPROFILE_SOURCE Halp21164ProfileSource2;
+
+#define INTERVAL_DELTA (10)
+
+//
+// Define the mapping between possible profile sources and the
+// CPU-specific settings.
+//
+typedef struct _HALP_PROFILE_MAPPING {
+ BOOLEAN Supported;
+ ULONG MuxControl;
+ ULONG Counter;
+ ULONG EventCount;
+ ULONG NumberOfTicks;
+} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING;
+
+HALP_PROFILE_MAPPING Halp21164ProfileMapping[ProfileMaximum] =
+{
+ {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5Instructions, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5PipeDry, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5LoadsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5AllFlowIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5NonIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DcacheLDMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5IcacheRFBMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5BRMispredicts, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5StoresIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5FPOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5IntOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DualIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5TripleIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5QuadIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5IcacheIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DcacheAccesses,Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5MBStallCycles, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5LDxLInstIssued,Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}
+};
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+VOID
+Halp21164UpdatePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN ULONG MuxControl,
+ IN ULONG EventCount
+ );
+
+
+NTSTATUS
+Halp21164ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ Halp21164ProfileMapping[SourceInfo->Source].EventCount *
+ Halp21164ProfileMapping[SourceInfo->Source].NumberOfTicks;
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+Halp21164ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+VOID
+Halp21164InitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Establish the profile interrupt as the interrupt handler for
+ // all performance counter interrupts.
+ //
+
+ PCR->InterruptRoutine[PC0_VECTOR] = Halp21164PerformanceCounter0Interrupt;
+ PCR->InterruptRoutine[PC1_VECTOR] = Halp21164PerformanceCounter1Interrupt;
+ PCR->InterruptRoutine[PC2_VECTOR] = Halp21164PerformanceCounter2Interrupt;
+
+ return;
+
+}
+
+
+BOOLEAN
+Hal21164QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) {
+ return(FALSE);
+ }
+
+ return(Halp21164ProfileMapping[Source].Supported);
+}
+
+
+NTSTATUS
+Hal21164SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ ULONG FastTickPeriod;
+ ULONG SlowTickPeriod;
+ ULONG TickPeriod;
+ ULONG FastCountEvents;
+ ULONG SlowCountEvents;
+ ULONGLONG CountEvents;
+ ULONGLONG TempInterval;
+
+ if (!HalQueryProfileInterval(ProfileSource)) {
+ return(STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (ProfileSource == ProfileTime) {
+
+ //
+ // Convert the clock tick period (in 100ns units ) into
+ // a cycle count period
+ //
+
+ CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod;
+ } else {
+ CountEvents = (ULONGLONG)*Interval;
+ }
+
+ FastCountEvents = Ev5CountEvents2xx8;
+ SlowCountEvents = Ev5CountEvents2xx16;
+
+ if (Halp21164ProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter0) {
+ FastCountEvents = Ev5CountEvents2xx16;
+ }
+ else if (Halp21164ProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter2) {
+ SlowCountEvents = Ev5CountEvents2xx14;
+ }
+
+ //
+ // Limit the interval to the smallest interval we can time.
+ //
+ if (CountEvents < FastCountEvents) {
+ CountEvents = (ULONGLONG)FastCountEvents;
+ }
+
+ //
+ // Assume we will use the fast event count
+ //
+ Halp21164ProfileMapping[ProfileSource].EventCount = FastCountEvents;
+ Halp21164ProfileMapping[ProfileSource].NumberOfTicks =
+ (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents);
+
+ //
+ // See if we can successfully use the slower period. If the requested
+ // interval is greater than the slower tick period and the difference
+ // between the requested interval and the interval that we can deliver
+ // with the slower clock is acceptable, then use the slower clock.
+ // We define an acceptable difference as a difference of less than
+ // INTERVAL_DELTA of the requested interval.
+ //
+ if (CountEvents > SlowCountEvents) {
+ ULONG NewInterval;
+
+ NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) /
+ SlowCountEvents) * SlowCountEvents);
+ if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) {
+ Halp21164ProfileMapping[ProfileSource].EventCount = SlowCountEvents;
+ Halp21164ProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents;
+ }
+ }
+
+ *Interval = Halp21164ProfileMapping[ProfileSource].EventCount *
+ Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ if (ProfileSource == ProfileTime) {
+ //
+ // Convert cycle count back into 100ns clock ticks
+ //
+ // Use 64-bit integer to prevent overflow.
+ //
+ TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod);
+ *Interval = (ULONG)(TempInterval / 100000);
+ }
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+Hal21164SetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
+
+VOID
+Hal21164StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG MuxControl;
+ ULONG EventCount;
+
+ //
+ // Check input to see if we are turning on a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21164ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Set the performance counter within the processor to begin
+ // counting total cycles.
+ //
+ PerformanceCounter = Halp21164ProfileMapping[ProfileSource].Counter;
+ MuxControl = Halp21164ProfileMapping[ProfileSource].MuxControl;
+
+ if (PerformanceCounter == Ev5PerformanceCounter0) {
+
+ EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx16) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ Halp21164ProfileSource0 = ProfileSource;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[0] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[0] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC0_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter1) {
+
+ EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx16) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ Halp21164ProfileSource1 = ProfileSource;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[1] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[1] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC1_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter2) {
+
+ EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx14) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ Halp21164ProfileSource2 = ProfileSource;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[2] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[2] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC2_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+ }
+
+ return;
+}
+
+
+VOID
+Hal21164StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG Vector;
+
+ //
+ // Check input to see if we are turning off a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21164ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Stop the performance counter from interrupting.
+ //
+
+ PerformanceCounter = Halp21164ProfileMapping[ProfileSource].Counter;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ 0,
+ Ev5CounterDisable );
+
+ //
+ // Disable the performance counter interrupt.
+ //
+ if (PerformanceCounter == Ev5PerformanceCounter0) {
+
+ HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter1) {
+
+ HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[1] = 0;
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter2) {
+
+ HalDisableSystemInterrupt( PC2_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[2] = 0;
+ }
+
+ return;
+}
+
+
+VOID
+Halp21164UpdatePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN ULONG MuxControl,
+ IN ULONG EventCount
+ )
+//++
+//
+// Routine Description:
+//
+// Write the specified microprocessor internal performance counter.
+//
+// Arguments:
+//
+// PerformanceCounter(a0) - Supplies the number of the performance counter
+// to write.
+//
+// MuxControl(a2) - Supplies the mux control value which selects which
+// type of event to count when the counter is enabled.
+//
+// EventCount(a3) - Supplies the event interval when the counter is
+// enabled.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+{
+ PMCTR_21164 PmCtr; // the performance counter register
+ ULONG CboxMux1 = 0; // CBOX select 1 mux value
+ ULONG CboxMux2 = 0; // CBOX select 2 mux value
+
+ PmCtr.all = HalpRead21164PerformanceCounter();
+
+ //
+ // Check for special values first:
+ //
+
+ if ( MuxControl >= Ev5PcSpecial ) {
+
+ switch( MuxControl ) {
+
+ //
+ // Count JsrRet Issued
+ //
+
+ case Ev5JsrRetIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+ PmCtr.Sel2 = Ev5PCMispredicts;
+ break;
+
+ //
+ // Count CondBr Issued
+ //
+
+ case Ev5CondBrIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+ PmCtr.Sel2 = Ev5BRMispredicts;
+ break;
+
+ //
+ // Count all flow change inst Issued
+ //
+
+ case Ev5AllFlowIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+
+ if ( (PmCtr.Sel2 == Ev5PCMispredicts) ||
+ (PmCtr.Sel2 == Ev5BRMispredicts)) {
+
+ PmCtr.Sel2 = Ev5LongStalls;
+
+ }
+ break;
+
+ //
+ // Must be an Scache counter. Select the appropriate counter
+ // in Sel1 or Sel2, and pass the CBOX mux value to WritePerfCounter
+ //
+
+ default:
+
+ if ( MuxControl <= Ev5ScSystemCmdReq ) {
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5CBOXInput1;
+ CboxMux1 = MuxControl - Ev5ScMux1;
+
+ } else if ( MuxControl <= Ev5ScSysReadReq ) {
+
+ PmCtr.Ctl2 = EventCount;
+ PmCtr.Sel2 = Ev5CBOXInput2;
+ CboxMux2 = MuxControl - Ev5ScMux2;
+
+ }
+
+ } // switch
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter0 ) {
+
+ PmCtr.Ctl0 = EventCount;
+ PmCtr.Sel0 = MuxControl;
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter1 ) {
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = MuxControl;
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter2 ) {
+
+ PmCtr.Ctl2 = EventCount;
+ PmCtr.Sel2 = MuxControl;
+
+ }
+
+ HalpWrite21164PerformanceCounter(PmCtr.all, CboxMux1, CboxMux2);
+}
diff --git a/private/ntos/nthals/halflex/alpha/evclock.s b/private/ntos/nthals/halflex/alpha/evclock.s
new file mode 100644
index 000000000..aaaf6cd27
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evclock.s
@@ -0,0 +1,119 @@
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// intsup.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 24-Sep-93 Joe Notarangelo
+// Make this module platform-independent.
+//--
+
+#include "halalpha.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// VOID
+// HalpClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the primary processor. The routine is responsible for acknowledging the
+// interrupt and calling the kernel to update the system time.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+CiRa: .space 8 // space for return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Call the kernel to update the system time.
+//
+ ldl a1, HalpCurrentTimeIncrement // Get current time increment
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateSystemTime
+ jsr ra, (t0) // call kernel
+
+ ldl t0, HalpNextTimeIncrement // Get next time increment
+ stl t0, HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+ ldl a0, HalpNextIntervalCount // Get next interval count. If 0, then no change required.
+ beq a0, 10f // See if time increment is to be changed
+ bsr ra, HalpProgramIntervalTimer // Program timer with new rate select
+ ldl t0, HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+ stl zero, HalpNextIntervalCount // Set HalpNextIntervalCount to 0
+
+//
+// Call to handle performance counter wrap.
+//
+10:
+ bsr ra, HalpCheckPerformanceCounter // check for perf. counter wrap
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ ldl t0, __imp_DbgBreakPointWithStatus
+ lda a0, DBG_STATUS_CONTROL_C
+ jsr ra, (t0) // send status to debugger
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpClockInterrupt
+
+
+
diff --git a/private/ntos/nthals/halflex/alpha/evxcache.c b/private/ntos/nthals/halflex/alpha/evxcache.c
new file mode 100644
index 000000000..12237a517
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evxcache.c
@@ -0,0 +1,823 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ev4cache.c
+
+Abstract:
+
+ This file contains the routines for managing the caches on machines
+ based on the DECchip 21064 microprocessor.
+
+ EV4 has primary I and D caches of 8KB each, both write-through.
+ Any systems based on EV4 are expected to have an external backup cache
+ which is write-back, but it is also coherent with all DMA operations. The
+ primary caches are shadowed by the backup, and on a write hit, the
+ primary data (but not instruction) cache is invalidated.
+ Consequently, the routines to flush,sweep,purge,etc the data
+ stream are nops on EV4, but the corresponding routines for the
+ Istream must ensure that we cannot hit in the primary I cache
+ after a DMA operation.
+
+ EV4 has a write buffer which contains 4 32-byte entries, which
+ must be flushable before DMA operations. The MB instruction is
+ used to accomplish this.
+
+ There is no coloring support on EV4, so Color operations are
+ null. Zero page is unsupported because it has no users. Copy
+ page is not special because we lack coloring.
+
+ We had to make a philosophical decision about what interfaces to
+ support in this file. (Almost) none of the interfaces defined in
+ the HAL spec are actually supported in either the i386 or MIPS
+ code. The i386 stream has almost no cache support at all. The
+ Mips stream has cache support, but most routines also refer to
+ coloring. Should we use the Spec'ed interfaces, or the Mips
+ interfaces? I have elected the Mips interfaces because they are
+ in use, and we are stealing much of the Mips code which expects
+ these interfaces. Besides, the only change we might make is to
+ remove the coloring arguments, but they may be used on Alpha
+ machines at some future date.
+
+Author:
+
+ Miche Baker-Harvey (miche) 29-May-1992
+
+Revision History:
+
+
+ 13-Jul-1992 Jeff McLeman (mcleman)
+ use HalpMb to do a memory barrier. Also, alter code and use super
+ pages to pass to rtl memory routines.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ use HalpImb to call pal.
+
+ 06-Jul-1992 Jeff McLeman (mcleman)
+ Move routine KeFlushDcache into this module.
+ Use only one memory barrier in the KeFlushWriteBuffer
+ routine. This is because the PAL for the EVx will
+ make sure the proper write ordering is done in PAL mode.
+
+--*/
+ // Include files
+
+#include "halp.h"
+
+
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ );
+
+//
+// Cache and write buffer flush functions.
+//
+
+
+VOID
+HalChangeColorPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+/*++
+
+Routine Description:
+
+ This function changes the color of a page if the old and new colors
+ do not match. DECchip 21064-based machines do not have page coloring, and
+ therefore, this function performs no operation.
+
+Arguments:
+
+ NewColor - Supplies the page aligned virtual address of the
+ new color of the page to change.
+
+ OldColor - Supplies the page aligned virtual address of the
+ old color of the page to change.
+
+ pageFrame - Supplies the page frame number of the page that
+ is changed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is flushed.
+ PageFrame - Supplies the page frame number of the page that
+ is flushed.
+
+ Length - Supplies the length of the region in the page that is
+ flushed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Address;
+ volatile ULONG i;
+ volatile ULONG j;
+
+ if (DmaOperation!=FALSE) {
+
+ HalpMb(); // force all previous writes off chip
+
+ Offset = Mdl->ByteOffset;
+ Length = Mdl->ByteCount;
+ PageFrame = (PULONG)(Mdl + 1);
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ if (Address & 0x2000) {
+ HalpWriteAbsoluteUlong(0xfffffce9,0x00000010,(Address >> 14) & 0xffff);
+ } else {
+ HalpWriteAbsoluteUlong(0xfffffce8,0x00000010,(Address >> 14) & 0xffff);
+ }
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x001fffff;
+ for(i=0;i<PAGE_SIZE;i+=0x40) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+ }
+
+ } else {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ HalpWriteAbsoluteUlong(0xfffffc03,0x40000004,((Address>>21)&0x1ff)<<8);
+ HalpWriteAbsoluteUlong(0xfffffc03,0x00000004,((Address>>13)&0xff)<<9);
+ HalpReadAbsoluteUlong(0xfffffc03,0x00000000);
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x0007ffff;
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+0x200000+Address+i);
+ }
+
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ } while(Length != 0);
+ }
+
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+
+ //
+ // If this is an EV4 or an EV45, then do an IMB
+ //
+
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+ }
+}
+
+VOID
+HalpCleanIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Address;
+ volatile ULONG i;
+ volatile ULONG j;
+
+// //
+// // If this is an EV4 or an EV45, then do nothing on the backend of DMA operations
+// //
+//
+// if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+// return;
+// }
+
+ if (DmaOperation!=FALSE) {
+
+ HalpMb(); // force all previous writes off chip
+
+ Offset = Mdl->ByteOffset;
+ Length = Mdl->ByteCount;
+ PageFrame = (PULONG)(Mdl + 1);
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ if (Address & 0x2000) {
+ HalpWriteAbsoluteUlong(0xfffffce9,0x00000010,(Address >> 14) & 0xffff);
+ } else {
+ HalpWriteAbsoluteUlong(0xfffffce8,0x00000010,(Address >> 14) & 0xffff);
+ }
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x001fffff;
+ for(i=0;i<PAGE_SIZE;i+=0x40) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+ }
+
+ } else {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ HalpWriteAbsoluteUlong(0xfffffc03,0x40000004,((Address>>21)&0x1ff)<<8);
+ HalpWriteAbsoluteUlong(0xfffffc03,0x00000004,((Address>>13)&0xff)<<9);
+ HalpReadAbsoluteUlong(0xfffffc03,0x00000000);
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x0007ffff;
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+0x200000+Address+i);
+ }
+
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ } while(Length != 0);
+ }
+
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+}
+
+
+VOID
+HalpGoodCleanIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Address;
+ volatile ULONG i;
+ volatile ULONG j;
+
+ if (DmaOperation!=FALSE) {
+
+ HalpMb(); // force all previous writes off chip
+
+ Offset = Mdl->ByteOffset;
+ Length = Mdl->ByteCount;
+ PageFrame = (PULONG)(Mdl + 1);
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ Address = ((*PageFrame << PAGE_SHIFT) + Offset) & 0x001fffc0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ Address = ((*PageFrame << PAGE_SHIFT) + Offset + 0x40) & 0x001fffc0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ Address = ((*PageFrame << PAGE_SHIFT) + CacheSegment - 1) & 0x001fffc0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+
+ } else {
+
+ Address = ((*PageFrame << PAGE_SHIFT) + Offset) & 0x000fffe0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ Address = ((*PageFrame << PAGE_SHIFT) + CacheSegment - 1) & 0x000fffe0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ } while(Length != 0);
+ }
+
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+}
+
+
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+Routine Description:
+
+ This function purges (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalPurgeIcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function purges (invalidates) up to a page fo data from the
+ instruction cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+}
+
+VOID
+HalSweepDcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire data cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepDcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the data
+ cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the data cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the data cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire instruction cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+ return;
+}
+
+VOID
+HalSweepIcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the
+ instruction cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the instruction cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the instruction cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+
+}
+
+VOID
+KeFlushWriteBuffer (
+ VOID
+ )
+
+{
+ //
+ // We flush the write buffer by doing a series of memory
+ // barrier operations. It still isn't clear if we need
+ // to do two/four of them to flush the buffer, or if one
+ // to order the writes is suffcient
+ //
+
+ HalpMb;
+ return;
+}
+
+VOID
+KeFlushDcache (
+ IN BOOLEAN AllProcessors,
+ IN PVOID BaseAddress OPTIONAL,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(BaseAddress);
+ UNREFERENCED_PARAMETER(Length);
+
+ HalFlushDcache(AllProcessors);
+ return;
+}
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sweep (index/writeback/invalidate) the data cache.
+ //
+
+ HalSweepDcache();
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+// if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+// return 0x40;
+// } else {
+// return 0x20;
+// }
+
+ //
+ // Checked builds will not run with an alignment other than 0x08. It generated assertions
+ // when buffers are not aligned correctly and this sometimes happens on the ALPHA builds.
+ // However, SCSI Tape device will not work unless the alignment value is correct. So,
+ // for right now SCSI Tape devices can not be used with a checked build.
+ //
+ // Free builds do not have the assertions for unaligned buffers, so we can set the
+ // alignment value to the systems actual cache line size. This means that SCSI Tape
+ // devices will work with a free build and a free HAL.
+ //
+
+#ifdef DEBUG
+ return 0x08;
+#else
+ return 0x40;
+#endif
+}
diff --git a/private/ntos/nthals/halflex/alpha/evxmem.s b/private/ntos/nthals/halflex/alpha/evxmem.s
new file mode 100644
index 000000000..532a67b6a
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evxmem.s
@@ -0,0 +1,231 @@
+// TITLE("EV4 Memory Operations")
+//++
+//
+// Copyright (C) 1994,1995 Digital Equipment Corporation
+//
+// Module Name:
+//
+// ev4mem.s
+//
+// Abstract:
+//
+// This module implements EV4 memory operations that require assembly
+// language.
+//
+// Environment:
+//
+// HAL, Kernel mode only.
+//
+//
+//
+//--
+
+#include "ksalpha.h"
+
+#define ZERO_BLOCK_SIZE (256)
+#define ZERO_LOOPS (PAGE_SIZE/ZERO_BLOCK_SIZE)
+
+//++
+//
+// VOID
+// HalEV4ZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalZeroPage)
+
+ ldl t0, HalpIoArchitectureType
+ beq t0, HalpEV5ZeroPage
+
+HalpEV4ZeroPage:
+
+ .set noreorder // hand scheduled
+
+//
+// Map the page via the 43-bit super-page on EV4.
+//
+
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll a2, PAGE_SHIFT, t1 // physical address of page
+
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+ ldil t2, ZERO_LOOPS // set count of loops to run
+
+ bis t0, t1, t0 // set super-page enable + physical
+ bis zero, zero, zero // for branch alignment
+
+//
+// Zero the page in a loop, zeroing 256 bytes per iteration. This number
+// was chosen to tradeoff loop overhead versus the overhead of fetching
+// Icache blocks.
+//
+
+10:
+ stq zero, 0x00(t0) //
+ subl t2, 1, t2 // decrement the loop count
+
+ stq zero, 0x08(t0) //
+ stt f31, 0x10(t0) //
+
+ stq zero, 0x18(t0) //
+ stt f31, 0x20(t0) //
+
+ stq zero, 0x28(t0) //
+ stt f31, 0x30(t0) //
+
+ stq zero, 0x38(t0) //
+ stt f31, 0x40(t0) //
+
+ stq zero, 0x48(t0) //
+ stt f31, 0x50(t0) //
+
+ stq zero, 0x58(t0) //
+ stt f31, 0x60(t0) //
+
+ stq zero, 0x68(t0) //
+ stt f31, 0x70(t0) //
+
+ stq zero, 0x78(t0) //
+ stt f31, 0x80(t0) //
+
+ stq zero, 0x88(t0) //
+ stt f31, 0x90(t0) //
+
+ stq zero, 0x98(t0) //
+ stt f31, 0xa0(t0) //
+
+ stq zero, 0xa8(t0) //
+ stt f31, 0xb0(t0) //
+
+ bis t0, zero, t1 // copy base register
+ stq zero, 0xb8(t0) //
+
+ stq zero, 0xc0(t0) //
+ stt f31, 0xc8(t0) //
+
+ stq zero, 0xd0(t0) //
+ stt f31, 0xd8(t0) //
+
+ stq zero, 0xe0(t0) //
+ lda t0, 0x100(t0) // increment to next block
+
+ stq zero, 0xe8(t1) //
+ stt f31, 0xf0(t1) //
+
+ stt f31, 0xf8(t1) // use stt for dual issue with bne
+ bne t2, 10b // while count > 0
+
+ ret zero, (ra) // return
+
+
+ .set reorder //
+
+HalpEV5ZeroPage:
+
+ .set noreorder // hand scheduled
+
+//
+// Map the page via the 43-bit super-page on EV5.
+//
+
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll a2, PAGE_SHIFT, t1 // physical address of page
+
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+ ldil t2, ZERO_LOOPS // set count of loops to run
+
+ bis t0, t1, t0 // set super-page enable + physical
+ br zero, 10f // start the zeroing
+
+//
+// Zero the page in a loop, zeroing 256 bytes per iteration. This number
+// was chosen to tradeoff loop overhead versus the overhead of fetching
+// Icache blocks.
+//
+
+ .align 4 // align as branch target
+10:
+ stq zero, 0x00(t0) //
+ subl t2, 1, t2 // decrement the loop count
+
+ stq zero, 0x08(t0) //
+ stq zero, 0x10(t0) //
+
+ stq zero, 0x18(t0) //
+ stq zero, 0x20(t0) //
+
+ stq zero, 0x28(t0) //
+ stq zero, 0x30(t0) //
+
+ stq zero, 0x38(t0) //
+ stq zero, 0x40(t0) //
+
+ stq zero, 0x48(t0) //
+ stq zero, 0x50(t0) //
+
+ stq zero, 0x58(t0) //
+ stq zero, 0x60(t0) //
+
+ stq zero, 0x68(t0) //
+ stq zero, 0x70(t0) //
+
+ stq zero, 0x78(t0) //
+ stq zero, 0x80(t0) //
+
+ stq zero, 0x88(t0) //
+ stq zero, 0x90(t0) //
+
+ stq zero, 0x98(t0) //
+ stq zero, 0xa0(t0) //
+
+ stq zero, 0xa8(t0) //
+ stq zero, 0xb0(t0) //
+
+ stq zero, 0xb8(t0) //
+ bis t0, zero, t1 // copy base register
+
+ stq zero, 0xc0(t0) //
+ stq zero, 0xc8(t0) //
+
+ stq zero, 0xd0(t0) //
+ stq zero, 0xd8(t0) //
+
+ stq zero, 0xe0(t0) //
+ lda t0, 0x100(t0) // increment to next block
+
+ stq zero, 0xe8(t1) //
+ stq zero, 0xf0(t1) //
+
+ stq zero, 0xf8(t1) // use stt for dual issue with bne
+ bne t2, 10b // while count > 0
+
+ ret zero, (ra) // return
+
+
+ .set reorder //
+
+ .end HalZeroPage
+
diff --git a/private/ntos/nthals/halflex/alpha/evxprof.c b/private/ntos/nthals/halflex/alpha/evxprof.c
new file mode 100644
index 000000000..4e296e5fc
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evxprof.c
@@ -0,0 +1,342 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ evxprof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV5 core. This module is appropriate for all
+ machines based on microprocessors using the EV5 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Michael D. Kinney 14-Aug-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+Hal21064QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+BOOLEAN
+Hal21164QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+Hal21064SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+NTSTATUS
+Hal21164SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+ULONG
+Hal21064SetProfileInterval (
+ IN ULONG Interval
+ );
+
+ULONG
+Hal21164SetProfileInterval (
+ IN ULONG Interval
+ );
+
+VOID
+Hal21064StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+VOID
+Hal21164StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+VOID
+Hal21064StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+VOID
+Hal21164StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Hal21164QueryProfileInterval(Source));
+ } else {
+ return(Hal21064QueryProfileInterval(Source));
+ }
+}
+
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Hal21164SetProfileSourceInterval(ProfileSource,Interval));
+ } else {
+ return(Hal21064SetProfileSourceInterval(ProfileSource,Interval));
+ }
+}
+
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Hal21164SetProfileInterval(Interval));
+ } else {
+ return(Hal21064SetProfileInterval(Interval));
+ }
+}
+
+
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Hal21164StartProfileInterrupt(ProfileSource);
+ } else {
+ Hal21064StartProfileInterrupt(ProfileSource);
+ }
+}
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Hal21164StopProfileInterrupt(ProfileSource);
+ } else {
+ Hal21064StopProfileInterrupt(ProfileSource);
+ }
+}
+
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Halp21164InitializeProfiler();
+ } else {
+ Halp21064InitializeProfiler();
+ }
+}
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Halp21164ProfileSourceInformation(Buffer,BufferLength,ReturnedLength));
+ } else {
+ return(Halp21064ProfileSourceInformation(Buffer,BufferLength,ReturnedLength));
+ }
+}
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Halp21164ProfileSourceInterval(Buffer,BufferLength));
+ } else {
+ return(Halp21064ProfileSourceInterval(Buffer,BufferLength));
+ }
+}
diff --git a/private/ntos/nthals/halflex/alpha/halpal.s b/private/ntos/nthals/halflex/alpha/halpal.s
new file mode 100644
index 000000000..d34a29084
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/halpal.s
@@ -0,0 +1,276 @@
+// TITLE("Alpha PAL funtions for HAL")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// halpal.s
+//
+// Abstract:
+//
+// This module implements routines to call PAL functions
+// from the Hal.
+//
+//
+// Author:
+//
+// Jeff McLeman (mcleman) 09-Jul-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 13-Jul-1992 Jeff McLeman (mcleman)
+// add HalpMb to functions.
+//
+// 14-Dec-1993 Joe Notarangelo
+// use new encoding to return to firmware: HalpReboot instead of
+// HalpHalt
+//--
+
+#include "halalpha.h"
+
+//++
+//
+// VOID
+// HalpReboot(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to reboot the Alpha processor.
+// This is used to restart the console firmware. (Note, MIPS does
+// not have a HALT instruction, so there had to be a mechanism to
+// restart the firware. Alpha merely reboots, which causes a jump
+// to firmware PAL, which restarts the firmware.)
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReboot)
+
+ REBOOT // call the PAL to reboot
+
+ .end HalpReboot
+
+//++
+//
+// VOID
+// HalpSwppal(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a SWPPAL
+// on the Alpha processor...
+//
+// Arguments:
+//
+// a0 The physical address to do the Swappal to.
+// a1 -- a5 Any other arguments to the PALcode.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSwppal)
+
+ SWPPAL // call the PAL to do a swap_pal
+
+ ret zero,(ra)
+
+ .end HalpSwppal
+
+
+//++
+//
+// VOID
+// HalpImb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue an Instruction
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpImb)
+
+ IMB // call the PAL to do an IMB
+
+ ret zero,(ra)
+
+ .end HalpImb
+
+
+//++
+//
+// VOID
+// HalpMb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a general
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpMb)
+
+ mb // memory barrier
+
+ ret zero, (ra)
+
+ .end HalpMb
+
+//++
+//
+// VOID
+// HalpCachePcrValues(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to cache values in the
+// PCR for faster access.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCachePcrValues)
+
+ CACHE_PCR_VALUES // call the palcode
+
+ ret zero,(ra)
+
+ .end HalpCachePcrValues
+//++
+//
+// ULONG
+// HalpRpcc(
+// )
+//
+// Routine Description:
+//
+// This function executes the RPCC (read processor cycle counter)
+// instruction.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The low-order 32 bits of the processor cycle counter is returned
+// as the function value.
+// N.B. At 125 MHz this counter wraps about every 30 seconds. It is
+// the caller's responsibility to deal with overflow or wraparound.
+//
+//--
+
+ LEAF_ENTRY(HalpRpcc)
+
+ rpcc v0 // get rpcc value
+ addl v0, zero, v0 // extend
+
+ ret zero, (ra) // return
+
+ .end HalpRpcc
+
+
+//++
+//
+// MCES
+// HalpReadMces(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Read the state of the MCES (Machine Check Error Summary)
+// internal processor register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// v0 - Current MCES value.
+//--
+
+ LEAF_ENTRY(HalpReadMces)
+
+ GET_MACHINE_CHECK_ERROR_SUMMARY // v0 = current value
+
+ ret zero, (ra) // return
+
+ .end HalpReadMces
+
+
+//++
+//
+// MCES
+// HalpWriteMces(
+// IN MCES Mces
+// )
+//
+// Routine Description:
+//
+// Update the current value of the MCES internal processor register.
+//
+// Arguments:
+//
+// Mces(a0) - Supplies the new value for the MCES register.
+//
+// Return Value:
+//
+// v0 - Previous MCES value.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteMces)
+
+ WRITE_MACHINE_CHECK_ERROR_SUMMARY // v0 = previous value
+
+ ret zero, (ra) // return
+
+ .end HalpWriteMces
diff --git a/private/ntos/nthals/halflex/alpha/info.c b/private/ntos/nthals/halflex/alpha/info.c
new file mode 100644
index 000000000..02e46848b
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/info.c
@@ -0,0 +1,128 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ info.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+#endif // _PNP_POWER_
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ The function returns system-wide information controlled by the HAL for a
+ variety of classes.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the space to store the data.
+
+ ReturnedLength - Supplies a count in bytes of the amount of data returned.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+ case HalProfileSourceInformation:
+ Status = HalpProfileSourceInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return(Status);
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+/*++
+
+Routine Description:
+
+ The function allows setting of various fields return by
+ HalQuerySystemInformation.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the data to be set.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ case HalProfileSourceInterval:
+ Status = HalpProfileSourceInterval (
+ Buffer,
+ BufferSize);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
diff --git a/private/ntos/nthals/halflex/alpha/initsys.c b/private/ntos/nthals/halflex/alpha/initsys.c
new file mode 100644
index 000000000..de6d38930
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/initsys.c
@@ -0,0 +1,579 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ initsys.c
+
+Abstract:
+
+ This module implements the platform specific portions of the
+ HAL initialization.
+
+Author:
+
+ Michael D. Kinney 3-May-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+//
+// Type Declarations
+//
+
+typedef
+VOID
+(*POPERATING_SYSTEM_STARTED) (
+ VOID
+ );
+
+//
+// Define global data used to determine the type of system I/O architecture to use.
+//
+
+ULONG HalpIoArchitectureType = UNKNOWN_PROCESSOR_MODULE;
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+ULONG IoSpaceAlreadyMapped = FALSE;
+ULONG HalpModuleChipSetRevision = MODULE_CHIP_SET_REVISION_UNKNOWN;
+BOOLEAN HalpModuleHardwareFlushing;
+UCHAR HalpSecondPciBridgeBusNumber = 2;
+ULONG HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+UCHAR *HalpInterruptLineToBit;
+UCHAR *HalpBitToInterruptLine;
+UCHAR *HalpInterruptLineToVirtualIsa;
+UCHAR *HalpVirtualIsaToInterruptLine;
+ULONGLONG HalpNoncachedDenseBasePhysicalSuperPage;
+ULONGLONG HalpPciDenseBasePhysicalSuperPage;
+ULONGLONG HalpPciConfig0BasePhysical;
+ULONGLONG HalpPciConfig1BasePhysical;
+ULONGLONG HalpIsaIoBasePhysical;
+ULONGLONG HalpIsa1IoBasePhysical;
+ULONGLONG HalpIsaMemoryBasePhysical;
+ULONGLONG HalpIsa1MemoryBasePhysical;
+ULONGLONG HalpPciIoBasePhysical;
+ULONGLONG HalpPci1IoBasePhysical;
+ULONGLONG HalpPciMemoryBasePhysical;
+ULONGLONG HalpPci1MemoryBasePhysical;
+PPLATFORM_RANGE_LIST HalpRangeList = NULL;
+ULONG HalpIntel82378BusNumber = 0;
+ULONG HalpIntel82378DeviceNumber = 0;
+ULONG HalpSecondIntel82378DeviceNumber = 0;
+ULONG HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ULONG HalpNonExistentPci1DeviceMask = 0;
+ULONG HalpNonExistentPci2DeviceMask = 0;
+ULONG HalpNumberOfIsaBusses;
+ULONG HalpVgaDecodeBusNumber;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpGetPlatformParameterBlock(
+ VOID
+ );
+
+ULONG FindIntel82378(ULONG Dec2105xBusNumber,ULONG Dec2105xDeviceNumber,ULONG BusNumber,ULONG IsaBusNumber)
+
+{
+ ULONG i;
+ ULONG MaxDevice;
+
+ if (BusNumber == 0) {
+ MaxDevice = PCI_MAX_LOCAL_DEVICE;
+ } else {
+ MaxDevice = 31;
+ }
+ for(i=0;i<=MaxDevice;i++) {
+
+ if (HalpPciLowLevelConfigRead(BusNumber,i,0,0) == 0x04848086) {
+ return(i);
+ }
+ }
+ return(0);
+ }
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the I/O Architecture Type from the Platform Parameter Block
+ retrieved from the firmware.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Device16;
+ ULONG Device17;
+
+ //
+ // If the I/O Architecture Type is already known, then just return.
+ //
+
+ if (HalpIoArchitectureType != UNKNOWN_PROCESSOR_MODULE) {
+ return;
+ }
+
+ //
+ // If the Platform Parameter Block has not been retrieved from the firmware,
+ // then do it now.
+ //
+
+ if (HalpPlatformParameterBlock == NULL) {
+ HalpGetPlatformParameterBlock();
+ }
+
+ //
+ // Check for the 21164(EV5) Apocolypse Module Type.
+ //
+
+ if (strcmp(HalpPlatformParameterBlock->ModuleName,"APOCALYPSE1.0")==0) {
+ HalpIoArchitectureType = EV5_PROCESSOR_MODULE;
+ }
+
+ //
+ // Check for the 21064(EV4) Rogue Module Type.
+ //
+
+ if (strcmp(HalpPlatformParameterBlock->ModuleName,"ROGUE2.0")==0) {
+ HalpIoArchitectureType = EV4_PROCESSOR_MODULE;
+ }
+
+ //
+ // If the I/O Architecture Type is still unknown then HALT.
+ //
+
+ if (HalpIoArchitectureType == UNKNOWN_PROCESSOR_MODULE) {
+ for(;;);
+ }
+
+ //
+ // Get the processor module's chip set revision.
+ //
+
+ HalpModuleChipSetRevision = HalpGetModuleChipSetRevision();
+
+ //
+ // Limit the chip set revision to the highest one allowed by this HAL.
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision > EV5_MAX_CHIP_SET_REVISION) {
+ HalpModuleChipSetRevision = EV5_MAX_CHIP_SET_REVISION;
+ }
+
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE && HalpModuleChipSetRevision > EV4_MAX_CHIP_SET_REVISION) {
+ HalpModuleChipSetRevision = EV4_MAX_CHIP_SET_REVISION;
+ }
+
+ //
+ // See if the module chip set supports hardware flushing.
+ //
+
+ HalpModuleHardwareFlushing = TRUE;
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ switch (HalpModuleChipSetRevision) {
+ case 0 : HalpModuleHardwareFlushing = FALSE;
+ break;
+ }
+ }
+
+ //
+ // Determine base physical address of Dense PCI Space and the PCI Configuration Spaces
+ //
+
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ HalpNoncachedDenseBasePhysicalSuperPage = ROGUE_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciDenseBasePhysicalSuperPage = ROGUE_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciConfig0BasePhysical = ROGUE_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = ROGUE_PCI_CONFIG1_BASE_PHYSICAL;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && (HalpModuleChipSetRevision==0 || HalpModuleChipSetRevision==1)) {
+ HalpNoncachedDenseBasePhysicalSuperPage = APOC1_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciDenseBasePhysicalSuperPage = APOC1_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciConfig0BasePhysical = APOC1_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = APOC1_PCI_CONFIG1_BASE_PHYSICAL;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision==2) {
+ HalpNoncachedDenseBasePhysicalSuperPage = APOC2_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciDenseBasePhysicalSuperPage = APOC2_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciConfig0BasePhysical = APOC2_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = APOC2_PCI_CONFIG1_BASE_PHYSICAL;
+ }
+
+ //
+ // Determine the motherboard type. Assume TREBBIA20 so we can do some config cycles.
+ //
+
+ HalpMotherboardType = TREBBIA20;
+
+ Device16 = HalpPciLowLevelConfigRead(0,0x10,0,0);
+ Device17 = HalpPciLowLevelConfigRead(0,0x11,0,0);
+
+ //
+ // Now assume motherboard type is unknown and check out values returned from config cycles.
+ //
+
+ HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+
+ if (Device16 == 0x00211011 && Device17 == 0x00211011) {
+ HalpMotherboardType = TREBBIA20;
+
+ //
+ // Find and initialize up to two Jubilee adapters.
+ //
+
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 1;
+ HalpIntel82378DeviceNumber = FindIntel82378(0,0x11,1,0);
+ HalpSecondPciBridgeBusNumber = (UCHAR)((HalpPciLowLevelConfigRead(0,0x10,0,0x18) >> 8) & 0xff);
+ HalpSecondIntel82378DeviceNumber = FindIntel82378(0,0x10,HalpSecondPciBridgeBusNumber,1);
+ if (HalpSecondIntel82378DeviceNumber != 0) {
+ HalpNumberOfIsaBusses = 2;
+ }
+ HalpVgaDecodeBusNumber = 0x00;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x01;
+ }
+ if (HalpPciLowLevelConfigRead(0,0x10,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ if (Device16 == 0x04848086 && Device17 == 0x00011011) {
+ HalpMotherboardType = TREBBIA13;
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 0;
+ HalpIntel82378DeviceNumber = 0x10;
+ HalpVgaDecodeBusNumber = 0x01;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ //
+ // If the Motherboard Type is unknown then HALT.
+ //
+
+ if (HalpMotherboardType == MOTHERBOARD_UNKNOWN) {
+ for(;;);
+ }
+
+ //
+ // Determine the PCI interrupt translation tables.
+ //
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpNonExistentPciDeviceMask = ~TREB13_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb13InterruptLineToBit;
+ HalpBitToInterruptLine = Treb13BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb13InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb13VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd1) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0d);
+ }
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd2) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0f);
+ }
+ }
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb20InterruptLineToBit;
+ HalpBitToInterruptLine = Treb20BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb20InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb20VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB20SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableNcr) {
+ HalpNonExistentPci2DeviceMask |= (1 << 0x07);
+ }
+ }
+ }
+
+ //
+ // Determine base physical address of thr ISA IO Address Space and the address translation table.
+ //
+
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_ROGUE_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_ROGUE_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ if (HalpModuleChipSetRevision == 0) {
+ HalpRangeList = Rogue0Trebbia13RangeList;
+ }
+ if (HalpModuleChipSetRevision == 1) {
+ HalpRangeList = Rogue1Trebbia13RangeList;
+ }
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_ROGUE_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_ROGUE_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL;
+ if (HalpModuleChipSetRevision == 0) {
+ HalpRangeList = Rogue0Trebbia20RangeList;
+ }
+ if (HalpModuleChipSetRevision == 1) {
+ HalpRangeList = Rogue1Trebbia20RangeList;
+ }
+ }
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && (HalpModuleChipSetRevision==0 || HalpModuleChipSetRevision==1)) {
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_APOC1_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_APOC1_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpRangeList = Apoc10Trebbia13RangeList;
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_APOC1_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_APOC1_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_APOC1_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_APOC1_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL;
+ HalpRangeList = Apoc10Trebbia20RangeList;
+ }
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision==2) {
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_APOC2_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_APOC2_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpRangeList = Apoc20Trebbia13RangeList;
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_APOC2_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_APOC2_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_APOC2_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_APOC2_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL;
+ HalpRangeList = Apoc20Trebbia20RangeList;
+ }
+ }
+
+
+ //
+ // If the address translation table is still NULL then HALT.
+ //
+
+ if (HalpRangeList == NULL) {
+ for(;;);
+ }
+}
+
+BOOLEAN
+HalpInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL).
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+
+{
+ POPERATING_SYSTEM_STARTED PrivateOperatingSystemStarted;
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PHYSICAL_ADDRESS CacheFlushPhysicalAddress;
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpGetIoArchitectureType();
+
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+
+ //
+ // Inform the firmware that an operating system has taken control of the system.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 50) {
+ PrivateOperatingSystemStarted = *(POPERATING_SYSTEM_STARTED *)((ULONG)(SystemParameterBlock->VendorVector) + 50*4);
+ if (PrivateOperatingSystemStarted != NULL) {
+ PrivateOperatingSystemStarted();
+ }
+ }
+ }
+
+ //
+ // Map all I/O Spaces used by the HAL
+ //
+
+ HalpMapIoSpace();
+ IoSpaceAlreadyMapped = TRUE;
+
+ HalpInitializeX86DisplayAdapter();
+
+ //
+ // Initialize Dma Cache Parameters
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ HalpMapBufferSize = APOC_DMA_CACHE_SIZE;
+ HalpMapBufferPhysicalAddress.QuadPart = APOC_DMA_CACHE_BASE_PHYSICAL;
+ } else {
+ HalpMapBufferSize = ROGUE_DMA_CACHE_SIZE;
+ HalpMapBufferPhysicalAddress.QuadPart = ROGUE_DMA_CACHE_BASE_PHYSICAL;
+ }
+
+ return TRUE;
+
+ } else {
+
+ UCHAR Message[80];
+
+ //
+ // Phase 1 initialization.
+ //
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalDisplayString("DeskStation Technology UniFlex/Raptor 3 Motherboard Rev. 1\n\r");
+ }
+
+ if (HalpMotherboardType == TREBBIA20) {
+ HalDisplayString("DeskStation Technology Raptor ReFlex Motherboard Rev. 2\n\r");
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ sprintf(Message,"DeskStation Technology ALPHA 21164 Processor Module Rev. %d\n\r",HalpModuleChipSetRevision);
+ } else {
+ sprintf(Message,"DeskStation Technology ALPHA 21064A Processor Module Rev. %d\n\r",HalpModuleChipSetRevision);
+ }
+ HalDisplayString(Message);
+
+ if (HalpModuleHardwareFlushing == TRUE) {
+ HalDisplayString("Hardware Flushing is Enabled\n\r");
+ } else {
+ HalDisplayString("Hardware Flushing is Disabled\n\r");
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Map Cache Flush Region.
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ CacheFlushPhysicalAddress.QuadPart = APOC_CACHE_FLUSH_BASE_PHYSICAL;
+ HalpCacheFlushBase = MmMapIoSpace(CacheFlushPhysicalAddress,APOC_CACHE_FLUSH_SIZE,TRUE);
+ } else {
+ CacheFlushPhysicalAddress.QuadPart = ROGUE_CACHE_FLUSH_BASE_PHYSICAL;
+ HalpCacheFlushBase = MmMapIoSpace(CacheFlushPhysicalAddress,ROGUE_CACHE_FLUSH_SIZE,TRUE);
+ }
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ HalpEnableEisaInterrupt(UNIFLEX_CLOCK2_LEVEL,Latched);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus ();
+ }
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/intsup.c b/private/ntos/nthals/halflex/alpha/intsup.c
new file mode 100644
index 000000000..7f5fa0f36
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/intsup.c
@@ -0,0 +1,393 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ intsup.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt for
+ platform specific vectors.
+
+Author:
+
+ Michael D. Kinney 14-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalpDisablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ } //end switch Vector
+
+ return;
+}
+
+
+BOOLEAN
+HalpEnablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ return Enabled;
+
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ if (InterfaceType == ProcessorInternal) {
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+ } else {
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+ }
+
+ } else if ( (InterfaceType==PCI_BUS && BusInterruptLevel>=0x0 && BusInterruptLevel<=0x0f) ||
+ (HalpMotherboardType==TREBBIA13 && InterfaceType==Isa && BusNumber==1) ) {
+
+ ULONG i;
+
+ for(i=0;i<12;i++) {
+ if (BusInterruptLevel == HalpPlatformSpecificExtension->PciInterruptToIsaIrq[i]) {
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel = HalpVirtualIsaInterruptToInterruptLine(i) - 0x10;
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+ }
+ }
+
+ //
+ // Unrecognized interrupt
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+ } else if (InterfaceType == PCIBus && BusInterruptLevel >= 0x10) {
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel -= 0x10;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR.
+ //
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+
+ } else if (InterfaceType == Isa) {
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_ISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_ISA1_VECTORS);
+ }
+ } else if (InterfaceType == Eisa) {
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_EISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_EISA1_VECTORS);
+ }
+
+ } else {
+
+ //
+ // Not an interface supported on EB64P systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ }
+}
+
+ULONG
+HalpGet21164PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified performance counter interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21164.
+ //
+
+ *Irql = PROFILE_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 2
+ //
+
+ case 2:
+
+ return PC2_SECONDARY_VECTOR;
+
+ } //end switch( BusInterruptLevel )
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/jxhalp.h b/private/ntos/nthals/halflex/alpha/jxhalp.h
new file mode 100644
index 000000000..84a06ca18
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/jxhalp.h
@@ -0,0 +1,404 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+typedef enum _ADDRESS_SPACE_TYPE{
+ BusMemory=0,
+ BusIo = 1,
+ UserBusMemory = 2,
+ UserBusIo = 3,
+ KernelPciDenseMemory = 4,
+ UserPciDenseMemory = 6,
+} ADDRESS_SPACE_TYPE, *PADDRESS_SPACE_TYPE;
+
+
+//
+// Define microprocessor-specific function prototypes and structures.
+//
+
+//
+// 21164 (EV4) processor family.
+//
+
+typedef struct _EV5ProfileCount {
+ ULONG ProfileCount[3];
+ ULONG ProfileCountReload[3];
+} EV5ProfileCount, *PEV5ProfileCount;
+
+//
+// 21064 (EV4) processor family.
+//
+
+typedef enum _EV4Irq{
+ Irq0 = 0,
+ Irq1 = 1,
+ Irq2 = 2,
+ Irq3 = 3,
+ Irq4 = 4,
+ Irq5 = 5,
+ MaximumIrq
+} EV4Irq, *PEV4Irq;
+
+typedef struct _EV4IrqStatus{
+ ULONG Vector;
+ BOOLEAN Enabled;
+ KIRQL Irql;
+ UCHAR Priority;
+} EV4IrqStatus, *PEV4IrqStatus;
+
+typedef struct _EV4ProfileCount {
+ ULONG ProfileCount[2];
+ ULONG ProfileCountReload[2];
+} EV4ProfileCount, *PEV4ProfileCount;
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ );
+
+VOID
+HalpDisable21064HardwareInterrupt(
+ IN ULONG Irq
+ );
+
+VOID
+HalpDisable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ );
+
+VOID
+HalpDisable21064PerformanceInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnable21064HardwareInterrupt(
+ IN ULONG Irq,
+ IN KIRQL Irql,
+ IN ULONG Vector,
+ IN UCHAR Priority
+ );
+
+VOID
+HalpEnable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ );
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ );
+
+VOID
+HalpEnable21064PerformanceInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql
+ );
+
+ULONG
+HalpGet21064PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+//
+// 21164 (EV5) processor family.
+//
+
+typedef struct _EB164_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+ } EB164_PCR, *PEB164_PCR;
+
+#define HAL_21164_PCR ( (PEB164_PCR)(&(PCR->HalReserved)) )
+
+//
+// 21064 (EV4) processor family.
+//
+
+typedef struct _EB64P_PCR {
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} EB64P_PCR, *PEB64P_PCR;
+
+#define HAL_21064_PCR ( (PEB64P_PCR)(&(PCR->HalReserved)) )
+
+//
+// Define used to determine if a page is within the DMA Cache range.
+//
+
+#define HALP_PAGE_IN_DMA_CACHE(Page) \
+ (Page >= (0x40000/2))
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+
+
+extern PVOID HalpCacheFlushBase;
+extern ULONG HalpClockFrequency;
+extern ULONG HalpClockMegaHertz;
+extern ULONG HalpIoArchitectureType;
+extern ULONG HalpModuleChipSetRevision;
+extern ULONG HalpMotherboardType;
+extern BOOLEAN HalpModuleHardwareFlushing;
+extern UCHAR *HalpInterruptLineToBit;
+extern UCHAR *HalpBitToInterruptLine;
+extern UCHAR *HalpInterruptLineToVirtualIsa;
+extern UCHAR *HalpVirtualIsaToInterruptLine;
+extern ULONGLONG HalpNoncachedDenseBasePhysicalSuperPage;
+extern ULONGLONG HalpPciDenseBasePhysicalSuperPage;
+extern ULONGLONG HalpPciConfig0BasePhysical;
+extern ULONGLONG HalpPciConfig1BasePhysical;
+extern ULONGLONG HalpIsaIoBasePhysical;
+extern ULONGLONG HalpIsa1IoBasePhysical;
+extern ULONGLONG HalpIsaMemoryBasePhysical;
+extern ULONGLONG HalpIsa1MemoryBasePhysical;
+extern ULONGLONG HalpPciIoBasePhysical;
+extern ULONGLONG HalpPci1IoBasePhysical;
+extern ULONGLONG HalpPciMemoryBasePhysical;
+extern ULONGLONG HalpPci1MemoryBasePhysical;
+extern PPLATFORM_RANGE_LIST HalpRangeList;
+extern UCHAR HalpSecondPciBridgeBusNumber;
+extern ULONG PCIMaxBus;
+extern ULONG HalpIntel82378BusNumber;
+extern ULONG HalpIntel82378DeviceNumber;
+extern ULONG HalpSecondIntel82378DeviceNumber;
+extern ULONG HalpNonExistentPciDeviceMask;
+extern ULONG HalpNonExistentPci1DeviceMask;
+extern ULONG HalpNonExistentPci2DeviceMask;
+
+extern PLATFORM_RANGE_LIST Apoc10Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Apoc10Trebbia20RangeList[];
+extern PLATFORM_RANGE_LIST Apoc20Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Apoc20Trebbia20RangeList[];
+extern PLATFORM_RANGE_LIST Rogue0Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Rogue1Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Rogue0Trebbia20RangeList[];
+extern PLATFORM_RANGE_LIST Rogue1Trebbia20RangeList[];
+
+extern UCHAR Treb13InterruptLineToBit[];
+extern UCHAR Treb13BitToInterruptLine[];
+extern UCHAR Treb13InterruptLineToVirtualIsa[];
+extern UCHAR Treb13VirtualIsaToInterruptLine[];
+extern UCHAR Treb20InterruptLineToBit[];
+extern UCHAR Treb20BitToInterruptLine[];
+extern UCHAR Treb20InterruptLineToVirtualIsa[];
+extern UCHAR Treb20VirtualIsaToInterruptLine[];
+extern ULONG HalpNumberOfIsaBusses;
+extern ULONG HalpVgaDecodeBusNumber;
+
+VOID
+HalpMb (
+ );
+
+VOID
+HalpImb (
+ );
+
+VOID
+HalpCachePcrValues (
+ );
+
+ULONG
+HalpRpcc (
+ );
+
+ULONG
+HalpReadAbsoluteUlong (
+ IN ULONG HighPart,
+ IN ULONG LowPart
+ );
+
+VOID
+HalpWriteAbsoluteUlong (
+ IN ULONG HighPart,
+ IN ULONG LowPart,
+ IN ULONG Value
+ );
+
+ULONG
+HalpGetModuleChipSetRevision(
+ VOID
+ );
+
+VOID
+HalpInitialize21164Interrupts(
+ VOID
+ );
+
+VOID
+HalpStart21164Interrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ );
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+VOID
+Halp21064InitializeProfiler(
+ VOID
+ );
+
+NTSTATUS
+Halp21064ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+Halp21064ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+VOID
+Halp21164InitializeProfiler(
+ VOID
+ );
+
+NTSTATUS
+Halp21164ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+Halp21164ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+ULONG
+HalpGet21164PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+ULONGLONG
+HalpRead21164PerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpWrite21164PerformanceCounter(
+ ULONGLONG PmCtr,
+ ULONG CBOXMux1,
+ ULONG CBOXMux2
+ );
+
+VOID
+Halp21064PerformanceCounter0Interrupt (
+ VOID
+ );
+
+VOID
+Halp21064PerformanceCounter1Interrupt (
+ VOID
+ );
+
+VOID
+Halp21164PerformanceCounter0Interrupt (
+ VOID
+ );
+
+VOID
+Halp21164PerformanceCounter1Interrupt (
+ VOID
+ );
+
+VOID
+Halp21164PerformanceCounter2Interrupt (
+ VOID
+ );
+
+VOID
+Halp21064WritePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN BOOLEAN Enable,
+ IN ULONG MuxControl OPTIONAL,
+ IN ULONG EventCount OPTIONAL
+ );
+
+VOID
+Halp21064ClearLockRegister(
+ PVOID LockAddress
+ );
+
+VOID
+HalpMiniTlbSaveState(
+ VOID
+ );
+
+VOID
+HalpMiniTlbRestoreState(
+ VOID
+ );
+
+ULONG
+HalpMiniTlbAllocateEntry(
+ PVOID Qva,
+ PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpCleanIoBuffers(
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ );
+
+ULONG HalpPciLowLevelConfigRead(
+ ULONG BusNumber,
+ ULONG DeviceNumber,
+ ULONG FunctionNumber,
+ ULONG Register
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halflex/alpha/jxmapio.c b/private/ntos/nthals/halflex/alpha/jxmapio.c
new file mode 100644
index 000000000..c46ebb8ee
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/jxmapio.c
@@ -0,0 +1,103 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase[MAX_EISA_BUSSES];
+PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES];
+PVOID HalpPciControlBase[MAX_PCI_BUSSES];
+PVOID HalpPciMemoryBase[MAX_PCI_BUSSES];
+PVOID HalpRealTimeClockBase;
+PVOID HalpCacheFlushBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ HalpEisaControlBase[0] = HAL_MAKE_QVA(HalpIsaIoBasePhysical);
+ HalpEisaControlBase[1] = HAL_MAKE_QVA(HalpIsa1IoBasePhysical);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ HalpRealTimeClockBase = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + 0x71);
+
+ //
+ // Map ISA Memory Space.
+ //
+
+ HalpEisaMemoryBase[0] = HAL_MAKE_QVA(HalpIsaMemoryBasePhysical);
+ HalpEisaMemoryBase[1] = HAL_MAKE_QVA(HalpIsa1MemoryBasePhysical);
+
+ //
+ // Map PCI control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ HalpPciControlBase[0] = HAL_MAKE_QVA(HalpPciIoBasePhysical);
+ HalpPciControlBase[1] = HAL_MAKE_QVA(HalpPci1IoBasePhysical);
+
+ //
+ // Map PCI Memory Space.
+ //
+
+ HalpPciMemoryBase[0] = HAL_MAKE_QVA(HalpPciMemoryBasePhysical);
+ HalpPciMemoryBase[1] = HAL_MAKE_QVA(HalpPci1MemoryBasePhysical);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/alpha/minitlb.c b/private/ntos/nthals/halflex/alpha/minitlb.c
new file mode 100644
index 000000000..0b29f5cd8
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/minitlb.c
@@ -0,0 +1,221 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ minitlb.c
+
+Abstract:
+
+ This module contains the support functions for the TLB that allows
+ access to the sparse address spaces.
+
+Author:
+
+ Michael D. Kinney 8-Aug-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define MINI_TLB_ATTRIBUTES_HIGH 0xfffffc03
+#define MINI_TLB_ATTRIBUTES_LOW 0xc0000004
+#define MINI_TLB_ENTRY_HIGH 0xfffffc03
+
+UCHAR HalpMiniTlbAttributesLookupTable[16] = {
+ 0, // ISA I/O Space 0x00000000 - 0x01ffffff
+ 0, // ISA Memory Space 0x00000000 - 0x01ffffff
+ 1, // PCI I/O Space 0x00000000 - 0x01ffffff
+ 1, // PCI Memory Space 0x00000000 - 0x01ffffff
+ 1, // PCI High Memory Space 0x40000000 - 0x41ffffff
+ 1, // PCI High Memory Space 0x42000000 - 0x43ffffff
+ 1, // PCI High Memory Space 0x44000000 - 0x45ffffff
+ 1, // PCI High Memory Space 0x46000000 - 0x47ffffff
+ 3, // PCI Config Type 0 Space Devices 0-13 0x00000000 - 0x01ffffff
+ 3, // PCI Config Type 0 Space Device 14 0x02000000 - 0x03ffffff
+ 3, // PCI Config Type 0 Space Device 15 0x04000000 - 0x05ffffff
+ 3, // PCI Config Type 0 Space Device 16 0x08000000 - 0x09ffffff
+ 3, // PCI Config Type 0 Space Device 17 0x10000000 - 0x11ffffff
+ 3, // PCI Config Type 0 Space Device 18 0x20000000 - 0x21ffffff
+ 3, // PCI Config Type 0 Space Device 19 0x40000000 - 0x41ffffff
+ 3 // PCI Config Type 1 Space 0x00000000 - 0x01ffffff
+ };
+
+UCHAR HalpMiniTlbEntryLookupTable[16] = {
+ 0x80, // ISA I/O Space 0x00000000 - 0x01ffffff
+ 0x00, // ISA Memory Space 0x00000000 - 0x01ffffff
+ 0x80, // PCI I/O Space 0x00000000 - 0x01ffffff
+ 0x00, // PCI Memory Space 0x00000000 - 0x01ffffff
+ 0x20, // PCI High Memory Space 0x40000000 - 0x41ffffff
+ 0x21, // PCI High Memory Space 0x42000000 - 0x43ffffff
+ 0x22, // PCI High Memory Space 0x44000000 - 0x45ffffff
+ 0x23, // PCI High Memory Space 0x46000000 - 0x47ffffff
+ 0x00, // PCI Config Type 0 Space Devices 0-13 0x00000000 - 0x01ffffff
+ 0x01, // PCI Config Type 0 Space Device 14 0x02000000 - 0x03ffffff
+ 0x02, // PCI Config Type 0 Space Device 15 0x04000000 - 0x05ffffff
+ 0x04, // PCI Config Type 0 Space Device 16 0x08000000 - 0x09ffffff
+ 0x08, // PCI Config Type 0 Space Device 17 0x10000000 - 0x11ffffff
+ 0x10, // PCI Config Type 0 Space Device 18 0x20000000 - 0x21ffffff
+ 0x20, // PCI Config Type 0 Space Device 19 0x40000000 - 0x41ffffff
+ 0x80 // PCI Config Type 1 Space 0x00000000 - 0x01ffffff
+ };
+
+ULONG HalpMiniTlbEntryAddressLow[4] = {
+ 0x1000000c, // Mini TLB Entry 0
+ 0x5000000c, // Mini TLB Entry 1
+ 0x9000000c, // Mini TLB Entry 2
+ 0xd000000c // Mini TLB Entry 3
+ };
+
+UCHAR HalpMiniTlbAttributes = 0x00;
+UCHAR HalpMiniTlbEntry[4] = {0x00,0x00,0x00,0x00};
+
+UCHAR HalpMiniTlbTag[4] = {0xff, 0xff, 0xff, 0xff};
+ULONG HalpMiniTlbIndex = 0;
+ULONG HalpMiniTlbEntries = 4;
+
+VOID
+HalpMiniTlbProgramEntry(
+ ULONG Index
+ )
+
+{
+ HalpMiniTlbAttributes &= (~(0x03 << (Index * 2)));
+ HalpMiniTlbAttributes |= (HalpMiniTlbAttributesLookupTable[HalpMiniTlbTag[Index]] << (Index * 2));
+ HalpMiniTlbEntry[Index] = HalpMiniTlbEntryLookupTable[HalpMiniTlbTag[Index]];
+ HalpWriteAbsoluteUlong(MINI_TLB_ATTRIBUTES_HIGH,MINI_TLB_ATTRIBUTES_LOW,((ULONG)HalpMiniTlbAttributes)<<8);
+ HalpWriteAbsoluteUlong(MINI_TLB_ENTRY_HIGH,HalpMiniTlbEntryAddressLow[Index],((ULONG)HalpMiniTlbEntry[Index])<<8);
+}
+
+VOID
+HalpMiniTlbSaveState(
+ VOID
+ )
+
+{
+}
+
+VOID
+HalpMiniTlbRestoreState(
+ VOID
+ )
+
+{
+ ULONG i;
+
+ for(i=0;i<4;i++) {
+ if (HalpMiniTlbTag[i]!=0xff) {
+ HalpMiniTlbProgramEntry(i);
+ }
+ }
+}
+
+ULONG
+HalpMiniTlbMatch(
+ PVOID Qva,
+ ULONG StartIndex
+ )
+
+{
+ ULONG Tag;
+ ULONG i;
+
+ Tag = ((ULONG)(Qva) >> 25) & 0x0f;
+ for(i=StartIndex;i<4 && HalpMiniTlbTag[i]!=Tag;i++);
+ return(i);
+}
+
+ULONG
+HalpMiniTlbAllocateEntry(
+ PVOID Qva,
+ PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ ULONG Index;
+
+ //
+ // Check for a tag match among the fixed TLB entries.
+ //
+
+ Index = HalpMiniTlbMatch(Qva,HalpMiniTlbEntries);
+
+ if (Index==4) {
+
+ //
+ // There was no match, so check for an available TLB entry.
+ //
+
+ if (HalpMiniTlbEntries<=1) {
+
+ //
+ // No TLB entries were available. Return NULL
+ //
+
+ return(FALSE);
+ }
+
+ //
+ // A TLB entry was available. Fill it in.
+ //
+
+ HalpMiniTlbEntries--;
+ Index = HalpMiniTlbEntries;
+ HalpMiniTlbTag[Index] = (UCHAR)(((ULONG)(Qva) >> 25) & 0x0f);
+ HalpMiniTlbProgramEntry(Index);
+
+ //
+ // Reset the random replacement index
+ //
+
+ HalpMiniTlbIndex = 0;
+ }
+
+ TranslatedAddress->QuadPart = ROGUE_TRANSLATED_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += (Index << 30) | (((ULONG)(Qva) & 0x01ffffff) << IO_BIT_SHIFT);
+ return(TRUE);
+}
+
+
+PVOID
+HalpMiniTlbResolve(
+ PVOID Qva
+ )
+
+{
+ ULONG Index;
+
+ //
+ // Check for a tag match among all the TLB entries
+ //
+
+ Index = HalpMiniTlbMatch(Qva,0);
+
+ if (Index==4) {
+
+ //
+ // There was no match, so replace one of the TLB entries
+ //
+
+ Index = HalpMiniTlbIndex;
+ HalpMiniTlbTag[Index] = (UCHAR)(((ULONG)(Qva) >> 25) & 0x0f);
+ HalpMiniTlbProgramEntry(Index);
+
+ //
+ // Point random replacement index at next available entry.
+ //
+
+ HalpMiniTlbIndex++;
+ if (HalpMiniTlbIndex >= HalpMiniTlbEntries) {
+ HalpMiniTlbIndex = 0;
+ }
+ }
+ return( (PVOID)(DTI_QVA_ENABLE | ((0x08 | Index) << 25) | ((ULONG)(Qva) & 0x01ffffff)) );
+}
diff --git a/private/ntos/nthals/halflex/alpha/pcisup.c b/private/ntos/nthals/halflex/alpha/pcisup.c
new file mode 100644
index 000000000..6d708835e
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/pcisup.c
@@ -0,0 +1,897 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ This module contains the routines that support PCI configuration cycles
+ and PCI interrupts.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define INVALID_PCI_CONFIGURATION_ADDRESS (0xffffff00)
+#define NO_PCI_DEVSEL_DATA_VALUE (0xffffffff)
+
+//
+// The following tables are used to map between PCI interrupt pins, PCI interrupt lines,
+// and virtual ISA interrupt indexes. The Uniflex architecture uses a 16 bit interrupt
+// controller for ISA interrupts and all PCI interrupts. An InterruptLine value of 0x20
+// is reserved for the ISA PIC. InterruptLine values between 0x10 and 0x20 are reserved
+// for PCI devices. InterruptLine values between 0x00 and 0x0f are reserved for ISA IRQs.
+//
+
+UCHAR Treb13InterruptLineToBit[0x11] = {7,2,3,1,4,5,6,9,10,11,16,16,16,16,15,14,0};
+UCHAR Treb13BitToInterruptLine[0x10] = {0x10,0x03,0x01,0x02,0x04,0x05,0x06,0x00,0x00,0x07,0x08,0x09,0x00,0x00,0x0f,0x0e};
+UCHAR Treb13InterruptLineToVirtualIsa[0x10] = {0,1,2,3,8,9,10,11,4,5,0,0,0,0,0,0};
+UCHAR Treb13VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0x18,0x19,0,0,0x14,0x15,0x16,0x17,0,0,0,0};
+
+UCHAR Treb20InterruptLineToBit[0x11] = {1,2,3,4,5,6,7,8,9,16,16,16,16,16,16,16,0};
+UCHAR Treb20BitToInterruptLine[0x10] = {0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00};
+UCHAR Treb20InterruptLineToVirtualIsa[0x11] = {0,1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,9};
+UCHAR Treb20VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x20,0,0,0,0,0,0};
+
+//
+// Interrupt mask for all active PCI interrupts including ISA Bus PICs
+//
+
+static volatile ULONG HalpPciInterruptMask;
+
+//
+// Interrupt mask for PCI interrupts that have been connected through device drivers.
+//
+
+static volatile ULONG HalpPciDeviceInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #0 PIC
+//
+
+static volatile ULONG HalpEisaInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #1 PIC
+//
+
+static volatile ULONG HalpEisa1InterruptMask;
+
+VOID
+HalpWritePciInterruptRegister(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the interrupt mask register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ HalpWriteAbsoluteUlong(0xfffffca8,0x00000010, (HalpPciInterruptMask & 0xff) << 8);
+ HalpWriteAbsoluteUlong(0xfffffc88,0x00000010, HalpPciInterruptMask & 0xff00);
+ } else {
+ HalpWriteAbsoluteUlong(0xfffffc03,0x2000000c, HalpPciInterruptMask & 0xff);
+ HalpWriteAbsoluteUlong(0xfffffc03,0x6000000c, HalpPciInterruptMask >> 8);
+ }
+ }
+
+ULONG
+HalpReadPciInterruptRegister(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the interrupt status register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The lower 16 bits contains the status of each interrupt line going to the PCI
+ interrupt controller.
+
+--*/
+
+ {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return ( ((HalpReadAbsoluteUlong(0xfffffca8,0x00000000)>>8)&0xff) |
+ (HalpReadAbsoluteUlong(0xfffffc88,0x00000000) & 0xff00) );
+ } else {
+ return ( (HalpReadAbsoluteUlong(0xfffffc03,0x2000000c) &0xff) |
+ ((HalpReadAbsoluteUlong(0xfffffc03,0x6000000c)<<8) & 0xff00) );
+ }
+ }
+
+ULONG
+HalpGetModuleChipSetRevision(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function identifies the chip set revision of the processor module installed in the
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The chip set revision.
+
+--*/
+
+{
+ ULONG Temp;
+ ULONG ReturnValue;
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Temp = HalpPciInterruptMask;
+ HalpPciInterruptMask = 0;
+ HalpWritePciInterruptRegister();
+ ReturnValue = (HalpReadPciInterruptRegister() >> 4) & 0x0f;
+ HalpPciInterruptMask = Temp;
+ HalpWritePciInterruptRegister();
+ }
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ ReturnValue = HalpReadAbsoluteUlong(0xfffffc03,0xe000000c);
+ ReturnValue = (ReturnValue & 0x0f) ^ ((ReturnValue >> 4) & 0x0f);
+ }
+ return(ReturnValue);
+}
+
+VOID
+HalpSetPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to set in the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask | (1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask | (1<<Bit);
+ HalpWritePciInterruptRegister();
+}
+
+VOID
+HalpClearPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function clears a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to clear from the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask & ~(1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask & ~(1<<Bit);
+ HalpWritePciInterruptRegister();
+}
+
+VOID
+HalpEnablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to enable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpSetPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+VOID
+HalpDisablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpClearPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+ULONG
+HalpVirtualIsaInterruptToInterruptLine (
+ IN ULONG Index
+ )
+
+/*++
+
+Routine Description:
+
+ This function maps a virtual ISA interrupt to a PCI interrupt line value.
+ This provides the ability to use an ISA device driver on a PCI device.
+
+Arguments:
+
+ Index - Index into a platform specific table that maps PCI interrupts to
+ virtual ISA interrupts.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return(HalpVirtualIsaToInterruptLine[Index]);
+}
+
+
+ULONG HalpClearLockCacheLineAddress[32];
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt dispatcher for all PCI interrupts.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ ULONG PciInterruptStatus;
+ PULONG dispatchCode;
+ PKINTERRUPT interruptObject;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue = FALSE;
+ ULONG i;
+
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ Halp21064ClearLockRegister(&(HalpClearLockCacheLineAddress[16]));
+ }
+
+ //
+ // Get the active interrupt bits
+ //
+
+ PciInterruptStatus = HalpReadPciInterruptRegister();
+
+ //
+ // See if this is the interrupt for ISA Bus #0 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisaInterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,0);
+
+ //
+ // If there really was an interrupt on ISA Bus #0, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // See if this is the interrupt for ISA Bus #1 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisa1InterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,1);
+
+ //
+ // If there really was an interrupt on ISA Bus #1, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // Only keep interrupt bits that have been connected by device drivers.
+ //
+
+ PciInterruptStatus &= HalpPciDeviceInterruptMask;
+
+ //
+ // Dispatch to the ISRs of interrupts that have been connected by device drivers.
+ //
+
+ for(i=0;i<16;i++) {
+ if (PciInterruptStatus & (1<<i)) {
+
+ PCRInOffset = UNIFLEX_PCI_VECTORS + HalpBitToInterruptLine[i];
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+ }
+ }
+
+ return(returnValue);
+}
+
+UCHAR HalpGetInterruptLine(ULONG BusNumber,ULONG DeviceNumber,ULONG InterruptPin)
+
+/*++
+
+Routine Description:
+
+ This routine maps a PCI interrupt described by the device's bus number, device number, and
+ interrupt pin into the interrupt line value that is stored in the PCI config header.
+
+Arguments:
+
+ BusNumber - PCI bus number of the device.
+
+ DeviceNumber - PCI device number of the device.
+
+ InterruptPin - PCI interrupt pin of the device (A=1,B=2,C=3,D=4).
+
+Return Value:
+
+ Returns the PCI Interrupt Line value for the PCI device.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ if (HalpMotherboardType == TREBBIA13) {
+
+ if (BusNumber > 1)
+ {
+ BusNumber = 1;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x010401 : InterruptLine = 0x10; break; // Bus 1, Device 4, Int A
+ case 0x010601 : InterruptLine = 0x11; break; // Bus 1, Device 6, Int A
+ case 0x010501 : InterruptLine = 0x12; break; // Bus 1, Device 5, Int A
+ case 0x010701 : InterruptLine = 0x13; break; // Bus 1, Device 7, Int A
+ case 0x010402 : InterruptLine = 0x17; break; // Bus 1, Device 4, Int B
+ case 0x010602 : InterruptLine = 0x14; break; // Bus 1, Device 6, Int B
+ case 0x010502 : InterruptLine = 0x14; break; // Bus 1, Device 5, Int B
+ case 0x010702 : InterruptLine = 0x17; break; // Bus 1, Device 7, Int B
+ case 0x010403 : InterruptLine = 0x18; break; // Bus 1, Device 4, Int C
+ case 0x010603 : InterruptLine = 0x15; break; // Bus 1, Device 6, Int C
+ case 0x010503 : InterruptLine = 0x15; break; // Bus 1, Device 5, Int C
+ case 0x010703 : InterruptLine = 0x18; break; // Bus 1, Device 7, Int C
+ case 0x010404 : InterruptLine = 0x19; break; // Bus 1, Device 4, Int D
+ case 0x010604 : InterruptLine = 0x16; break; // Bus 1, Device 6, Int D
+ case 0x010504 : InterruptLine = 0x16; break; // Bus 1, Device 5, Int D
+ case 0x010704 : InterruptLine = 0x19; break; // Bus 1, Device 7, Int D
+ case 0x000d01 : InterruptLine = 0x1e; break; // Bus 0, Device 13, Int A
+ case 0x000f01 : InterruptLine = 0x1f; break; // Bus 0, Device 15, Int A
+ case 0x001001 : InterruptLine = 0x20; break; // Bus 0, Device 16, Int A
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ if (HalpMotherboardType == TREBBIA20) {
+
+ if (BusNumber == 0) {
+ return(0xff);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x000401 : InterruptLine = 0x20; break;
+
+ case 0x000501 :
+ case 0x000603 :
+ case 0x000704 : InterruptLine = 0x10; break;
+
+ case 0x000502 :
+ case 0x000604 :
+ case 0x000701 : InterruptLine = 0x11; break;
+
+ case 0x000503 :
+ case 0x000601 :
+ case 0x000702 : InterruptLine = 0x12; break;
+
+ case 0x000504 :
+ case 0x000602 :
+ case 0x000703 : InterruptLine = 0x13; break;
+
+ case 0x010401 :
+ case 0x010504 :
+ case 0x010603 : InterruptLine = 0x14; break;
+
+ case 0x010402 :
+ case 0x010501 :
+ case 0x010604 : InterruptLine = 0x15; break;
+
+ case 0x010403 :
+ case 0x010502 :
+ case 0x010601 : InterruptLine = 0x16; break;
+
+ case 0x010404 :
+ case 0x010503 :
+ case 0x010602 : InterruptLine = 0x17; break;
+
+ case 0x010701 : InterruptLine = 0x18; break;
+
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ return(InterruptLine);
+}
+
+
+VOID
+HalpConnectInterruptDispatchers(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function connects the PCI interrupt dispatch routine and enables
+ ISA interrupts so they will generate processor interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ PCR->InterruptRoutine[22] = (PKINTERRUPT_ROUTINE)HalpPciDispatch;
+ } else {
+ PCR->InterruptRoutine[14] = (PKINTERRUPT_ROUTINE)HalpPciDispatch;
+ }
+
+//DbgPrint("Intel82378 : Bus=%d Device=%d\n\r",HalpIntel82378BusNumber,HalpIntel82378DeviceNumber);
+//DbgPrint("SecondIntel82378 : Bus=%d Device=%d\n\r",HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber);
+
+ InterruptLine = HalpGetInterruptLine(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,1);
+ HalpEisaInterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisaInterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+ InterruptLine = HalpGetInterruptLine(HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber,1);
+ HalpEisa1InterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisa1InterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+//DbgPrint("HalpEisaInterruptMask = %08x\n\r",HalpEisaInterruptMask);
+//DbgPrint("HalpEisa1InterruptMask = %08x\n\r",HalpEisa1InterruptMask);
+
+ //
+ // Enable ISA Interrupts on Apocolypse's PIC
+ //
+
+ HalpPciDeviceInterruptMask = 0x0000;
+ HalpPciInterruptMask = HalpEisaInterruptMask | HalpEisa1InterruptMask;
+ HalpWritePciInterruptRegister();
+}
+
+
+VOID
+HalpDisableAllInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables all external interrupt sources.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG i;
+
+ //
+ // Mask off all ISA Interrupts
+ //
+
+ for(i=0;i<HalpNumberOfIsaBusses;i++) {
+ WRITE_REGISTER_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase[i]+0x21),0xff);
+ WRITE_REGISTER_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase[i]+0xa1),0xff);
+ }
+
+ //
+ // Mask off all PCI Interrupts
+ //
+
+ HalpPciDeviceInterruptMask = 0x0000;
+ HalpPciInterruptMask = 0x0000;
+ HalpWritePciInterruptRegister();
+}
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (IN ULONG BusNumber)
+{
+ if (BusNumber == 0) {
+ return PciConfigType0;
+ } else if (BusNumber < PCIMaxBus) {
+ return PciConfigType1;
+ } else {
+ return PciConfigTypeInvalid;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusNumber);
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+
+ //
+ // See if this is a nonexistant device on PCI Bus 0
+ //
+
+ if ( (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPciDeviceMask ) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ pPciAddr->u.AsULONG = 1 << (3 + Slot.u.bits.DeviceNumber);
+ } else {
+ pPciAddr->u.AsULONG = 1 << (11 + Slot.u.bits.DeviceNumber);
+ }
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ pPciAddr->u.AsULONG &= 0x01ffffff;
+ pPciAddr->u.AsULONG += (ULONG)HAL_MAKE_QVA(HalpPciConfig0BasePhysical);
+ if (Slot.u.bits.DeviceNumber >= 14 && Slot.u.bits.DeviceNumber <= 19) {
+ pPciAddr->u.AsULONG += (Slot.u.bits.DeviceNumber-13) << 25;
+ }
+ }
+ } else {
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the First PCI-PCI Bridge
+ //
+
+ if (BusNumber == 1 && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci1DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the Second PCI-PCI Bridge
+ //
+
+ if (BusNumber == HalpSecondPciBridgeBusNumber && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci2DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+
+ pPciAddr->u.AsULONG = 0;
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ pPciAddr->u.AsULONG = (ULONG)HAL_MAKE_QVA(HalpPciConfig1BasePhysical);
+ }
+ pPciAddr->u.bits1.BusNumber = BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+ }
+
+ return;
+}
+
+ULONG READ_CONFIG_Ux(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType,
+ IN ULONG Offset
+ )
+
+{
+ switch(ConfigurationType) {
+ case PciConfigType0 :
+ return(HalpReadAbsoluteUlong((ULONG)(HalpPciConfig0BasePhysical >> 32),
+ (ULONG)HalpPciConfig0BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset));
+ case PciConfigType1 :
+ return(HalpReadAbsoluteUlong((ULONG)(HalpPciConfig1BasePhysical >> 32),
+ (ULONG)HalpPciConfig1BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset));
+ }
+ return(NO_PCI_DEVSEL_DATA_VALUE);
+}
+
+VOID WRITE_CONFIG_Ux(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType,
+ IN ULONG Offset,
+ IN ULONG Value
+ )
+
+{
+ switch(ConfigurationType) {
+ case PciConfigType0 :
+ HalpWriteAbsoluteUlong((ULONG)(HalpPciConfig0BasePhysical >> 32),
+ (ULONG)HalpPciConfig0BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset,
+ Value);
+ break;
+ case PciConfigType1 :
+ HalpWriteAbsoluteUlong((ULONG)(HalpPciConfig1BasePhysical >> 32),
+ (ULONG)HalpPciConfig1BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset,
+ Value);
+ break;
+ }
+}
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((UCHAR)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return((UCHAR)(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_BYTE_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03))));
+ } else {
+ return(READ_REGISTER_UCHAR(ConfigurationAddress));
+ }
+}
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((USHORT)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return((USHORT)(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_WORD_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03))));
+ } else {
+ return(READ_REGISTER_USHORT(ConfigurationAddress));
+ }
+}
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((ULONG)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_LONG_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ return(READ_REGISTER_ULONG(ConfigurationAddress));
+ }
+}
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_BYTE_LEN,(ULONG)ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ WRITE_REGISTER_UCHAR(ConfigurationAddress,ConfigurationData);
+ }
+ }
+}
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_WORD_LEN,(ULONG)ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ WRITE_REGISTER_USHORT(ConfigurationAddress,ConfigurationData);
+ }
+ }
+}
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_LONG_LEN,ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ WRITE_REGISTER_ULONG(ConfigurationAddress,ConfigurationData);
+ }
+ }
+}
+
+ULONG HalpPciLowLevelConfigRead(
+ ULONG BusNumber,
+ ULONG DeviceNumber,
+ ULONG FunctionNumber,
+ ULONG Register
+ )
+
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_CFG_CYCLE_BITS PciCfg;
+ ULONG ConfigurationCycleType;
+
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ HalpPCIConfigAddr(BusNumber,SlotNumber,&PciCfg);
+ ConfigurationCycleType = PciCfg.u.bits.Reserved1;
+ PciCfg.u.bits.Reserved1 = 0;
+ PciCfg.u.bits0.RegisterNumber = Register>>2;
+ return(READ_CONFIG_ULONG((PVOID)PciCfg.u.AsULONG,ConfigurationCycleType));
+}
diff --git a/private/ntos/nthals/halflex/alpha/perfcntr.c b/private/ntos/nthals/halflex/alpha/perfcntr.c
new file mode 100644
index 000000000..d9a0c4975
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/perfcntr.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ perfcntr.c
+
+Abstract:
+
+ This module implements the interfaces that access the system
+ performance counter and the calibrated stall. The functions implemented
+ in this module are suitable for uniprocessor systems only.
+
+Author:
+
+ Jeff McLeman (mcleman) 05-June-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+ Rod Gamache [DEC] 9-Mar-1993
+ Fix profile clock.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define and initialize the 64-bit count of total system cycles used
+// as the performance counter.
+//
+
+ULONGLONG HalpCycleCount = 0;
+
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Obtain the current value of the processor cycle counter and adjust
+ // the upper 32 bits if a roll-over occurred since the last time the
+ // Rpcc value was checked (at least oncce per clock interrupt). This
+ // code may be interrupted so we must fetch HalpRpccTimec atomically.
+ //
+
+ *(PULONGLONG)&LocalRpccTime = HalpCycleCount;
+ RpccValue = HalpRpcc();
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+ LocalRpccTime.LowPart = RpccValue;
+
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->LowPart = HalpClockFrequency;
+ Frequency->HighPart = 0;
+ }
+
+ //
+ // Return the current processor cycle counter as the function value.
+ //
+
+ return LocalRpccTime;
+}
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+//HalDisplayString("HalCalibratePerformanceCounter()\n\r");
+
+ //
+ // ****** Warning ******
+ //
+ // This is a stub routine. It should clear the current value of the
+ // performance counter. It is really only needed in an MP system where,
+ // close, but not exact synchronization of the performance counters
+ // are needed. See MIPS code in halfxs\mips\j4prof.c for a method of
+ // synchronizing.
+ //
+
+ return;
+}
+
+
+VOID
+HalpCheckPerformanceCounter(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called every system clock interrupt in order to
+ check for wrap of the performance counter. The function must handle
+ a wrap if it is detected.
+
+ N.B. - This function must be called at CLOCK_LEVEL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Update the low part of the performance counter directly from the
+ // rpcc count. Check for wrap of the rpcc count, if wrap has occurred
+ // then increment the high part of the performance counter.
+ //
+
+ LocalRpccTime.QuadPart = HalpCycleCount;
+ RpccValue = HalpRpcc();
+
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+
+ LocalRpccTime.LowPart = RpccValue;
+
+ HalpCycleCount = LocalRpccTime.QuadPart;
+
+ return;
+
+}
+
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG Microseconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalll execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ Microseconds - Supplies the number of microseconds to stall.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LONG StallCyclesRemaining; // signed value
+ ULONG PreviousRpcc, CurrentRpcc;
+
+ //
+ // Get the value of the RPCC as soon as we enter
+ //
+
+ PreviousRpcc = HalpRpcc();
+
+ //
+ // Compute the number of cycles to stall
+ //
+
+ StallCyclesRemaining = Microseconds * HalpClockMegaHertz;
+
+ //
+ // Wait while there are stall cycles remaining.
+ // The accuracy of this routine is limited by the
+ // length of this while loop.
+ //
+
+ while (StallCyclesRemaining > 0) {
+
+ CurrentRpcc = HalpRpcc();
+
+ //
+ // The subtraction always works because the Rpcc
+ // is a wrapping long-word. If it wraps, we still
+ // get the positive number we want.
+ //
+
+ StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc);
+
+ //
+ // remember this RPCC value
+ //
+
+ PreviousRpcc = CurrentRpcc;
+ }
+
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/portsup.c b/private/ntos/nthals/halflex/alpha/portsup.c
new file mode 100644
index 000000000..ec96fcebd
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/portsup.c
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ portsup.c
+
+Abstract:
+
+ This module implements the code that provides the resources required to
+ access the serial port that is used for the kernel debugger.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define SERIAL_PORT_COM1 0x3F8
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ );
+
+PUCHAR HalpAllocateKdPortResources(
+ OUT PVOID *SP_READ,
+ OUT PVOID *SP_WRITE
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the resources needed by the kernel debugger to
+ access a serial port. For an ALPHA processor, all I/O ports can be
+ accessed through super page addresses, so this function just maps the
+ serial port into the super page address range.
+
+Arguments:
+
+ SP_READ - Quasi virtual address to use for I/O read operations.
+
+ SP_WRITE - Quasi virtual address to use for I/O write operations.
+
+Return Value:
+
+ The bus relative address of the COM port being used as a kernel debugger.
+
+--*/
+
+{
+ HalpGetIoArchitectureType();
+
+ *SP_READ = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + SERIAL_PORT_COM1);
+ *SP_WRITE = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + SERIAL_PORT_COM1);
+
+ return((PUCHAR)(SERIAL_PORT_COM1));
+}
+
+VOID HalpFreeKdPortResources(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function deallocates the resources needed by the kernel debugger to
+ access a serial port. For an ALPHA processor, no resources were actually
+ allocated, so this is a NULL function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+}
diff --git a/private/ntos/nthals/halflex/alpha/xxidle.s b/private/ntos/nthals/halflex/alpha/xxidle.s
new file mode 100644
index 000000000..0d53d7aed
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/xxidle.s
@@ -0,0 +1,62 @@
+// TITLE("Processor Idle Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// idle.s
+//
+// Abstract:
+//
+// This module implements the HalProcessorIdle interface
+//
+// Author:
+//
+// John Vert (jvert) 11-May-1994
+//
+// Environment:
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with interrupts disabled. This routine
+// must do any power management enabling necessary, enable interrupts,
+// then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+ ENABLE_INTERRUPTS // no power management, just
+ // enable interrupts and return
+ ret zero, (ra)
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halflex/alpha/xxinitnt.c b/private/ntos/nthals/halflex/alpha/xxinitnt.c
new file mode 100644
index 000000000..45e0cb356
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/xxinitnt.c
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+UCHAR Halp21164IrqlTable[] = {00, // Irql 0
+ 01, // Irql 1
+ 02, // Irql 2
+ 20, // Irql 3
+ 21, // Irql 4
+ 22, // Irql 5
+ 23, // Irql 6
+ 31}; // Irql 7
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+#define DEFAULT_21164_PROCESSOR_FREQUENCY_MHZ 300;
+#define DEFAULT_21064_PROCESSOR_FREQUENCY_MHZ 275;
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_21064_PROCESSOR_FREQUENCY_MHZ;
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Mask sure that all processor interrupts are inactive by masking off all device
+ // interrupts in the system's Programable Interrupt Controllers.
+ //
+
+ HalpDisableAllInterrupts();
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL. They are
+ // also used by the routines that raise and lower IRQL.
+ //
+
+ for (Index = 0; Index < sizeof(Halp21164IrqlTable); Index++) {
+ PCR->IrqlTable[Index] = Halp21164IrqlTable[Index];
+ }
+ }
+
+ //
+ // Initialize HAL private data from the PCR. This must be done before
+ // HalpStallExecution is called. Compute integral megahertz first to
+ // avoid rounding errors due to imprecise cycle clock period values.
+ //
+
+ HalpClockMegaHertz = ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+ HalpClockFrequency = HalpClockMegaHertz * (1000 * 1000);
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Start the heartbeat timer
+ //
+
+ HalSetTimeIncrement(MAXIMUM_INCREMENT);
+ HalpProgramIntervalTimer(HalpNextIntervalCount);
+
+ //
+ // Initialize the PCI/ISA interrupt controller.
+ //
+
+ HalpCreateDmaStructures();
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ //
+ // Initialize the 21164 interrupts.
+ //
+
+ HalpCachePcrValues(0); // Enable all HW INTS on 21164
+
+ } else {
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ HalpEnable21064HardwareInterrupt(Irq = 2,
+// Irql = DEVICE_LEVEL,
+ Irql = UNIFLEX_PCI_DEVICE_LEVEL,
+// Vector = PIC_VECTOR,
+ Vector = 14,
+ Priority = 0 );
+
+ }
+
+ return TRUE;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/halflex/busdata.c b/private/ntos/nthals/halflex/busdata.c
new file mode 100644
index 000000000..7ae3a7987
--- /dev/null
+++ b/private/ntos/nthals/halflex/busdata.c
@@ -0,0 +1,175 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpIsaInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+ //
+ // Build Isa bus #1
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 1, // Internal bus #1
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+ //
+ // Build Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+ //
+ // Build Eisa bus #1
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ -1, // No config space
+ 1, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+}
+
+NTSTATUS
+HalpIsaInstallHandler(
+ IN PBUS_HANDLER Bus
+ )
+
+{
+ //
+ // Fill in ISA handlers
+ //
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halflex/bushnd.c b/private/ntos/nthals/halflex/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halflex/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halflex/drivesup.c b/private/ntos/nthals/halflex/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halflex/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halflex/hal.rc b/private/ntos/nthals/halflex/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halflex/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halflex/hal.src b/private/ntos/nthals/halflex/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halflex/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halflex/halp.h b/private/ntos/nthals/halflex/halp.h
new file mode 100644
index 000000000..b6cc7cfdd
--- /dev/null
+++ b/private/ntos/nthals/halflex/halp.h
@@ -0,0 +1,453 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "hal.h"
+#include "hali.h"
+#include "dtidef.h"
+#include "jxhalp.h"
+#include "string.h"
+
+
+#define __0K (ULONG)(0x0)
+#define __0MB (ULONG)(0x0)
+#define __0GB (ULONG)(0x0)
+#define __2K (ULONG)(0x800)
+#define __4K (ULONG)(0x1000)
+#define __8K (ULONG)(0x2000)
+#define __16K (ULONG)(0x4000)
+#define __32K (ULONG)(0x8000)
+#define __64K (ULONG)(0x10000)
+#define __128K (ULONG)(0x20000)
+#define __256K (ULONG)(0x40000)
+#define __512K (ULONG)(0x80000)
+#define __1MB (ULONG)(0x100000)
+#define __2MB (ULONG)(0x200000)
+#define __4MB (ULONG)(0x400000)
+#define __8MB (ULONG)(0x800000)
+#define __16MB (ULONG)(0x1000000)
+#define __32MB (ULONG)(0x2000000)
+#define __64MB (ULONG)(0x4000000)
+#define __128MB (ULONG)(0x8000000)
+#define __256MB (ULONG)(0x10000000)
+#define __512MB (ULONG)(0x20000000)
+#define __1GB (ULONG)(0x40000000)
+#define __2GB (ULONG)(0x80000000)
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ ULONG BusNumber;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpDisablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ );
+
+BOOLEAN
+HalpEnablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ ULONG BusNumber
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN ULONG BusNumber
+ );
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpInitializeX86DisplayAdapter (
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter (
+ VOID
+ );
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG IntervalCount
+ );
+
+VOID
+HalpConnectInterruptDispatchers(
+ VOID
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableAllInterrupts (
+ );
+
+ULONG
+HalpVirtualIsaInterruptToInterruptLine (
+ IN ULONG Index
+ );
+
+ULONG
+HalpReadPciData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ OUT PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpWritePciData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpAllocateArcsResources (
+ VOID
+ );
+
+VOID
+HalpFreeArcsResources (
+ VOID
+ );
+
+PUCHAR
+HalpAllocateKdPortResources(
+ PVOID *SP_READ,
+ PVOID *SP_WRITE
+ );
+
+VOID
+HalpFreeKdPortResources(
+ VOID
+ );
+
+//
+// Define Bus Handler support function prototypes.
+//
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ );
+
+//
+//
+//
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+//
+// Define PCI support function prototypes.
+//
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPCIBusHandler (
+ IN ULONG BusNo
+ );
+
+VOID
+HalpRegisterPCIInstallHandler(
+ IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
+);
+
+NTSTATUS
+HalpDefaultPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+VOID
+HalpDeterminePCIDevicesPresent(
+ IN PBUS_HANDLER Bus
+);
+
+BOOLEAN
+HalpInitializePCIInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnablePCIInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePCIInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpPCIInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+NTSTATUS
+HalpMachineSpecificPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+//
+// Define external references.
+//
+
+extern PVOID HalpEisaControlBase[MAX_EISA_BUSSES];
+extern PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES];
+extern PVOID HalpPciControlBase[MAX_PCI_BUSSES];
+extern PVOID HalpPciMemoryBase[MAX_PCI_BUSSES];
+extern PVOID HalpRealTimeClockBase;
+extern PLATFORM_PARAMETER_BLOCK *HalpPlatformParameterBlock;
+extern PLATFORM_SPECIFIC_EXTENSION *HalpPlatformSpecificExtension;
+
+extern PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halflex/ioproc.c b/private/ntos/nthals/halflex/ioproc.c
new file mode 100644
index 000000000..450f8e46d
--- /dev/null
+++ b/private/ntos/nthals/halflex/ioproc.c
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "DeskStation Technology UniFlex PCI/Eisa/Isa HAL";
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ switch (HalpBusType) {
+ case UNIFLEX_MACHINE_TYPE_ISA:
+ case UNIFLEX_MACHINE_TYPE_EISA: interfacetype = Isa; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halflex/iousage.c b/private/ntos/nthals/halflex/iousage.c
new file mode 100644
index 000000000..9b30da08e
--- /dev/null
+++ b/private/ntos/nthals/halflex/iousage.c
@@ -0,0 +1,515 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Define constants for system IDTs
+//
+
+#define MAXIMUM_IDTVECTOR 0xff
+#define MAXIMUM_PRIMARY_VECTOR 0xff
+#define PRIMARY_VECTOR_BASE 0x30 // 0-2f are x86 trap vectors
+
+//
+// From usage.c
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+#if 0
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+#endif //0
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS TempAddress;
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 3; pass++) {
+
+ switch(pass) {
+
+ case 0: {
+#if DBG
+DbgPrint("Device LIST...\n");
+#endif // DBG
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ break;
+ }
+
+ case 1: {
+#if DBG
+DbgPrint("Internal LIST...\n");
+#endif // DBG
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ break;
+ }
+
+ case 2: {
+#if DBG
+DbgPrint("PCI LIST...\n");
+#endif // DBG
+ //
+ // Third pass = build reousce lists for resources reported
+ // as PCI usage.
+ //
+
+ reporton = PCIUsage & ~IDTOwned;
+ interfacetype = PCIBus;
+ break;
+ }
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+#if DBG
+DbgPrint("Start=0x%x Lenght=0x%x\n", RPartialDesc.u.Memory.Start.LowPart, RPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TempAddress ); // aligned translated address
+
+ TPartialDesc.u.Memory.Start = TempAddress; // TPartialDesc is pack(4)
+
+#if DBG
+DbgPrint("TRANSLATED ADDRESS Start=0x%x Lenght=0x%x\n", TPartialDesc.u.Memory.Start.LowPart, TPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halflex/iousage.h b/private/ntos/nthals/halflex/iousage.h
new file mode 100644
index 000000000..a9153a982
--- /dev/null
+++ b/private/ntos/nthals/halflex/iousage.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+Copyright (c) 1992-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+
+--*/
+
+//
+// External Function Prototypes
+//
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+//
+// Resource usage information
+//
+
+#pragma pack(1)
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ ULONG Length;
+ } Element[];
+} ADDRESS_USAGE;
+#pragma pack()
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+#define PCIUsage 0x41 // Report usage on PCI bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
diff --git a/private/ntos/nthals/halflex/makefile b/private/ntos/nthals/halflex/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halflex/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halflex/makefile.inc b/private/ntos/nthals/halflex/makefile.inc
new file mode 100644
index 000000000..ad15f5255
--- /dev/null
+++ b/private/ntos/nthals/halflex/makefile.inc
@@ -0,0 +1,5 @@
+obj\*\hal.def: hal.src
+ cl /EP hal.src -D$(PROCESSOR_ARCHITECTIRE)=1 $(C_DEFINES) > obj\*\hal.def
+
+$(TARGETPATH)\*\$(DDKBUILDENV)\hal.lib: $(TARGETPATH)\*\$(DDKBUILDENV)\halflex.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halflex/mips/addrsup.c b/private/ntos/nthals/halflex/mips/addrsup.c
new file mode 100644
index 000000000..795e529a5
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/addrsup.c
@@ -0,0 +1,204 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+#define KERNEL_PCI_VGA_VIDEO_ROM (LONGLONG)(0x8000000000000000)
+
+PLATFORM_RANGE_LIST Gambit20Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 0, TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 0, TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 0, TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 0, TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 0, TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 0, TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0xffffffff },
+
+ { Eisa , 1, BusIo, 0, TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 0, TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 0, TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0xffffffff },
+ { PCIBus, 0, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { PCIBus, 1, BusIo, 0, TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Gambit20Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 0, TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 0, TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, BusIo, 0, TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 0, TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 0, TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 0, TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, BusIo, 0, TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 0, TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 0, TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 0, TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 0, TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { PCIBus, 1, BusIo, 0, TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 0, TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 0, TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ ULONG i;
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ LONGLONG Offset;
+ PVOID va = 0; // note, this is used for a placeholder
+
+//BusAddress.HighPart = 0;
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+
+ //
+ // PCI Bus 0 is different than PCI Bus 1, but all other PCI busses are the same a PCI Bus 1
+ //
+
+ if (InterfaceType == PCIBus) {
+
+ switch (HalpMotherboardType) {
+ case TREBBIA13 :
+ if (BusNumber > 1) {
+ BusNumber = 1;
+ }
+ break;
+
+ case TREBBIA20 :
+ if (BusNumber == 0) {
+
+ //
+ // There are no resources in PCI Bus #0. It only contains the memory system and bridges.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+ break;
+
+ default :
+
+//DbgPrint(" Invalid Motherboard Type\n\r");
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ }
+
+ //
+ // If the VGA decodes are not enabled on the DEC PCI-PCI bridge associated with this
+ // memory range, then fail the translation.
+ //
+
+ if (!(HalpVgaDecodeBusNumber & (1<<BusNumber)) &&
+ BusAddress.QuadPart < (LONGLONG)0x0000000000100000 &&
+ (((ADDRESS_SPACE_TYPE)(*AddressSpace) == BusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserBusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == KernelPciDenseMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserPciDenseMemory) )) {
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Search the table for a valid mapping.
+ //
+
+ for(i=0;HalpRangeList[i].InterfaceType!=MaximumInterfaceType;i++) {
+
+ if (HalpRangeList[i].InterfaceType == InterfaceType &&
+ HalpRangeList[i].BusNumber == BusNumber &&
+ HalpRangeList[i].AddressType == (ADDRESS_SPACE_TYPE)(*AddressSpace) &&
+ BusAddress.QuadPart >= HalpRangeList[i].Base &&
+ BusAddress.QuadPart <= HalpRangeList[i].Limit ) {
+
+ TranslatedAddress->QuadPart = HalpRangeList[i].SystemBase;
+ *AddressSpace = HalpRangeList[i].SystemAddressSpace;
+
+ if (TranslatedAddress->QuadPart & KERNEL_PCI_VGA_VIDEO_ROM) {
+ TranslatedAddress->QuadPart &= ~KERNEL_PCI_VGA_VIDEO_ROM;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ TranslatedAddress->QuadPart += (LONGLONG)HalpPlatformSpecificExtension->PciVideoExpansionRomAddress;
+ } else {
+ TranslatedAddress->QuadPart += (TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL + (LONGLONG)0xc0000);
+ }
+ }
+
+ Offset = BusAddress.QuadPart - HalpRangeList[i].Base;
+ TranslatedAddress->QuadPart += Offset;
+ return(TRUE);
+ }
+ }
+
+ //
+ // A valid mapping was not found.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->QuadPart = 0;
+ return(FALSE);
+}
diff --git a/private/ntos/nthals/halflex/mips/arcssup.c b/private/ntos/nthals/halflex/mips/arcssup.c
new file mode 100644
index 000000000..44d37edd3
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/arcssup.c
@@ -0,0 +1,144 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ arcssup.c
+
+Abstract:
+
+ This module allocates resources before a call to the ARCS Firmware, and
+ frees those reources after the call returns.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+typedef
+VOID
+(*PSET_VIRTUAL_BASE) (
+ IN ULONG Number,
+ IN PVOID Base
+ );
+
+
+VOID
+HalpArcsSetVirtualBase (
+ IN ULONG Number,
+ IN PVOID Base
+ )
+
+/*++
+
+Routine Description:
+
+ This routine makes a private call into the ARCS Firmware to provide the
+ firmware with parameters is need to perform I/O operations while NT is
+ active.
+
+Arguments:
+
+ Number : Address space type
+
+ Base : Kernel Virtual Address for the given address space type.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PSET_VIRTUAL_BASE PrivateSetVirtualBase;
+
+
+ //
+ // Call private vector function SetVirtualBase so that the firmware functions
+ // can perform I/O operations while NT is active. If SetVirtualBase does
+ // not exist, then print an error message out the debug port and halt the system.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 28) {
+
+ PrivateSetVirtualBase = *(PSET_VIRTUAL_BASE *)((ULONG)(SystemParameterBlock->VendorVector) + 28*4);
+ PrivateSetVirtualBase(Number,Base);
+
+ } else {
+
+ KdPrint(("HAL : SetVirtualBase does not exist. Halting\n"));
+ for(;;);
+
+ }
+
+}
+
+
+VOID
+HalpAllocateArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocated resources required before an ARCS Firmware call is made.
+ On a MIPS system, if any I/O operations are going to be performed by the
+ firmware routine, a TLB entry needs to be reserved for these I/O operations.
+ This routine reserves a single TLB entry and a 4 KB page out of the kernel
+ virtual address space. These parameters are passed to the firmware through
+ a private vector call.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+
+{
+ HalpArcsSetVirtualBase(6,(PVOID)(HalpAllocateTbEntry()));
+ HalpArcsSetVirtualBase(7,HalpFirmwareVirtualBase);
+}
+
+VOID
+HalpFreeArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the TLB entry that was reserved for the ARCS
+ Firmware call.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpFreeTbEntry();
+}
diff --git a/private/ntos/nthals/halflex/mips/dtidef.h b/private/ntos/nthals/halflex/mips/dtidef.h
new file mode 100644
index 000000000..5dcbd65c8
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/dtidef.h
@@ -0,0 +1,150 @@
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dtidef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 26-Nov-1990
+
+Revision History:
+
+--*/
+
+#ifndef _DTIDEF_
+#define _DTIDEF_
+
+#include "uniflex.h"
+#include "gambit.h"
+#include "platform.h"
+
+//
+// Define the data structure returned by a private vector firmware function
+// that contains a set of system parameters.
+//
+
+typedef struct PLATFORM_SPECIFIC_EXTENSION {
+ UCHAR PciInterruptToIsaIrq[12];
+ ULONG PciVideoExpansionRomAddress;
+ PVOID AdvancedSetupInfo;
+} PLATFORM_SPECIFIC_EXTENSION;
+
+typedef struct TREB13SETUPINFO {
+ ULONG Reserved1:16;
+ ULONG Drive0Type:4;
+ ULONG Drive1Type:4;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq10:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq11:4;
+ ULONG Lpt1Irq:8;
+ ULONG Lpt2Irq:8;
+ ULONG Lpt3Irq:8;
+ ULONG SerialMousePort:8;
+ ULONG EnableAmd1:1;
+ ULONG EnableAmd2:1;
+ ULONG EnableX86Emulator:1;
+ ULONG Reserved2:5;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG Reserved3:7;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG Reserved4:6;
+ ULONG EnableDelays:1;
+ ULONG Reserved5:7;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved6:7;
+} TREB13SETUPINFO;
+
+typedef struct TREB20SETUPINFO {
+ ULONG Isa0Drive0Type:4;
+ ULONG Isa0Drive1Type:4;
+ ULONG Isa1Drive0Type:4;
+ ULONG Isa1Drive1Type:4;
+ ULONG SerialMousePort:8;
+ ULONG Isa0Lpt1Irq:8;
+ ULONG Isa0Lpt2Irq:8;
+ ULONG Isa0Lpt3Irq:8;
+ ULONG Isa1Lpt1Irq:8;
+ ULONG Isa1Lpt2Irq:8;
+ ULONG Isa1Lpt3Irq:8;
+ ULONG EnableNcr:1;
+ ULONG EnableX86Emulator:1;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG EnableDelays:1;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved1:1;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq4:4;
+ ULONG PciInterruptToIsaIrq5:4;
+ ULONG PciInterruptToIsaIrq6:4;
+ ULONG PciInterruptToIsaIrq7:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG NcrTermLow:1;
+ ULONG NcrTermHigh:1;
+ ULONG Reserved2:6;
+} TREB20SETUPINFO;
+
+//
+// Define the data structure used to describe all bus translations.
+//
+
+typedef struct PLATFORM_RANGE_LIST {
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ADDRESS_SPACE_TYPE AddressType;
+ ULONG SystemAddressSpace;
+ LONGLONG SystemBase;
+ LONGLONG Base;
+ LONGLONG Limit;
+} PLATFORM_RANGE_LIST, *PPLATFORM_RANGE_LIST;
+
+//
+// Define clock constants and clock levels.
+//
+
+#define UNIFLEX_CLOCK_LEVEL UNIFLEX_EISA_VECTORS + 0 // Interval clock level is on ISA IRQ 0
+#define UNIFLEX_ISA_DEVICE_LEVEL 4 // ISA bus interrupt level
+#define UNIFLEX_EISA_DEVICE_LEVEL 4 // EISA bus interrupt level
+#define UNIFLEX_PCI_DEVICE_LEVEL 3 // PCI bus interrupt level
+#define UNIFLEX_CLOCK2_LEVEL UNIFLEX_CLOCK_LEVEL
+
+//
+// Define ISA, EISA and PCI device interrupt vectors.
+//
+
+#define UNIFLEX_ISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_ISA_VECTOR (15 + UNIFLEX_ISA_VECTORS)
+#define UNIFLEX_EISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_EISA_VECTOR (15 + UNIFLEX_EISA_VECTORS)
+#define UNIFLEX_ISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_ISA1_VECTOR (15 + UNIFLEX_ISA1_VECTORS)
+#define UNIFLEX_EISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_EISA1_VECTOR (15 + UNIFLEX_EISA1_VECTORS)
+#define UNIFLEX_PCI_VECTORS 100
+#define UNIFLEX_MAXIMUM_PCI_VECTOR (15 + UNIFLEX_PCI_VECTORS)
+
+
+#endif // _DTIDEF_
diff --git a/private/ntos/nthals/halflex/mips/flushio.c b/private/ntos/nthals/halflex/mips/flushio.c
new file mode 100644
index 000000000..985601ccc
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/flushio.c
@@ -0,0 +1,282 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ flushio.c
+
+Abstract:
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalpSweepSecondaryCache(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function invalidate all lines from all sets of the secondary write-through cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Force read to invalidate entire secondary cache
+ //
+
+ READ_REGISTER_ULONG(HalpSecondaryCacheResetBase);
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, export or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if (Length > PCR->FirstLevelDcacheSize) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ //
+ // Maintain Secondary Caches only on DMA Read Operations
+ //
+
+ if (HalpPlatformParameterBlock->External.UnifiedCache.Size>0 &&
+ ReadOperation!=FALSE &&
+ DmaOperation!=FALSE) {
+
+ //
+ // See if the transfer length is larger than the size of the secondary cache
+ //
+
+ if (Length > HalpPlatformParameterBlock->External.UnifiedCache.Size) {
+ //
+ // Do a fast invalidate of all tags in all sets of the secondary cache
+ //
+
+ HalpSweepSecondaryCache();
+ } else {
+
+ //
+ // Walk MDL and do hit/invalidate cycles on the secondary cache
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ HalpInvalidateSecondaryCachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+ }
+
+ } else {
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then export the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ if (HalpPlatformParameterBlock->External.UnifiedCache.Size>0) {
+ HalpInvalidateSecondaryCachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+
+ } while(Length != 0);
+ }
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halflex/mips/gambit.h b/private/ntos/nthals/halflex/mips/gambit.h
new file mode 100644
index 000000000..7356d16cd
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/gambit.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ gambit.h
+
+Abstract:
+
+ This file contains definitions specific to the Gambit (MIPS R4600)
+ processor module.
+
+Author:
+
+ Michael D. Kinney 31-Aug-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// Define physical base addresses for system mapping.
+//
+
+#define TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL (LONGLONG)0x200000000 // ISA I/O Base Address
+#define TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL (LONGLONG)0x000000000 // ISA Memory Base Address
+#define TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // ISA I/O Base Address
+#define TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // ISA Memory Base Address
+#define TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // PCI I/O Base Address
+#define TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // PCI Memory Base Address
+
+#define TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // ISA I/O Base Address
+#define TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // ISA Memory Base Address
+#define TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL (LONGLONG)0x200000000 // ISA I/O Base Address
+#define TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL (LONGLONG)0x000000000 // ISA Memory Base Address
+#define TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // PCI I/O Base Address
+#define TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // PCI Memory Base Address
+#define TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL (LONGLONG)0x200000000 // PCI I/O Base Address
+#define TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL (LONGLONG)0x000000000 // PCI Memory Base Address
+
+#define GAMBIT_PCI_CONFIG0_BASE_PHYSICAL (LONGLONG)0xb00000000 // PCI Config Type 0 Base Address
+#define GAMBIT_PCI_CONFIG1_BASE_PHYSICAL (LONGLONG)0xc00000000 // PCI Config Type 1 Base Address
+#define GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL (LONGLONG)0x500000000 // PCI Interrupt Register Base Address
+#define GAMBIT_SECONDARY_CACHE_RESET_BASE_PHYSICAL (LONGLONG)0x700000000 // Secondary Cache Reset Register Base Address
+#define GAMBIT_SECONDARY_CACHE_INVALIDATE_PHYSICAL_BASE (LONGLONG)0x600000000 // Secondary Cache Invalidate Base Address
+#define GAMBIT_PFN_SECONDARY_CACHE_INVALIDATE_PHYSICAL_BASE 0x00600000 // PFN version of Secondary Cache Invalidate Base Address
+#define GAMBIT_DMA_CACHE_BASE_PHYSICAL (LONGLONG)0x001c0000 // DMA Cache Base Address
+#define GAMBIT_DMA_CACHE_SIZE 0x00040000 // Size of DMA Cache in bytes - 256 KB
diff --git a/private/ntos/nthals/halflex/mips/info.c b/private/ntos/nthals/halflex/mips/info.c
new file mode 100644
index 000000000..f9abd9d6d
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/info.c
@@ -0,0 +1,116 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ info.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+#endif // _PNP_POWER_
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ The function returns system-wide information controlled by the HAL for a
+ variety of classes.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the space to store the data.
+
+ ReturnedLength - Supplies a count in bytes of the amount of data returned.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return(Status);
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+/*++
+
+Routine Description:
+
+ The function allows setting of various fields return by
+ HalQuerySystemInformation.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the data to be set.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
diff --git a/private/ntos/nthals/halflex/mips/initsys.c b/private/ntos/nthals/halflex/mips/initsys.c
new file mode 100644
index 000000000..e23d422c6
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/initsys.c
@@ -0,0 +1,405 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ initsys.c
+
+Abstract:
+
+ This module implements the platform specific potions of the
+ HAL initialization.
+
+Author:
+
+ Michael D. Kinney 3-May-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+//
+// The WINNT350 define is used to remove memory from the MDL passed in
+// from the loader block. This is required because Windows NT 3.50 had
+// some problems with holes in the MDL. This problem was fixed for
+// Windows NT 3.51.
+//
+
+//#define WINNT350
+
+ULONG HalpIoArchitectureType = UNKNOWN_PROCESSOR_MODULE;
+
+ULONG IoSpaceAlreadyMapped = FALSE;
+UCHAR HalpSecondPciBridgeBusNumber = 2;
+ULONG HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+UCHAR *HalpInterruptLineToBit;
+UCHAR *HalpBitToInterruptLine;
+UCHAR *HalpInterruptLineToVirtualIsa;
+UCHAR *HalpVirtualIsaToInterruptLine;
+ULONGLONG HalpPciConfig0BasePhysical;
+ULONGLONG HalpPciConfig1BasePhysical;
+ULONGLONG HalpIsaIoBasePhysical;
+ULONGLONG HalpIsa1IoBasePhysical;
+ULONGLONG HalpIsaMemoryBasePhysical;
+ULONGLONG HalpIsa1MemoryBasePhysical;
+ULONGLONG HalpPciIoBasePhysical;
+ULONGLONG HalpPci1IoBasePhysical;
+ULONGLONG HalpPciMemoryBasePhysical;
+ULONGLONG HalpPci1MemoryBasePhysical;
+PPLATFORM_RANGE_LIST HalpRangeList = NULL;
+ULONG HalpIntel82378BusNumber = 0;
+ULONG HalpIntel82378DeviceNumber = 0;
+ULONG HalpSecondIntel82378DeviceNumber = 0;
+ULONG HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ULONG HalpNonExistentPci1DeviceMask = 0;
+ULONG HalpNonExistentPci2DeviceMask = 0;
+ULONG HalpNumberOfIsaBusses;
+ULONG HalpVgaDecodeBusNumber;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpGetPlatformParameterBlock(
+ VOID
+ );
+
+ULONG FindIntel82378(ULONG Dec2105xBusNumber,ULONG Dec2105xDeviceNumber,ULONG BusNumber,ULONG IsaBusNumber)
+
+{
+ ULONG i;
+ ULONG MaxDevice;
+
+ if (BusNumber == 0) {
+ MaxDevice = PCI_MAX_LOCAL_DEVICE;
+ } else {
+ MaxDevice = 31;
+ }
+ for(i=0;i<=MaxDevice;i++) {
+ if (HalpPciLowLevelConfigRead(BusNumber,i,0,0) == 0x04848086) {
+ return(i);
+ }
+ }
+ return(0);
+ }
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the I/O Architecture Type from the Platform Parameter Block
+ retrieved from the firmware.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Device16;
+ ULONG Device17;
+
+ //
+ // If the I/O Architecture Type is already known, then just return.
+ //
+
+ if (HalpIoArchitectureType != UNKNOWN_PROCESSOR_MODULE) {
+ return;
+ }
+
+ //
+ // If the Platform Parameter Block has not been retrieved from the firmware,
+ // then do it now.
+ //
+
+ if (HalpPlatformParameterBlock == NULL) {
+ HalpGetPlatformParameterBlock();
+ }
+
+ //
+ // Check for the R4600 Gambit Module Type.
+ //
+
+ if (strcmp(HalpPlatformParameterBlock->ModuleName,"GAMBIT2.0")==0) {
+ HalpIoArchitectureType = R4600_PROCESSOR_MODULE;
+ }
+
+ //
+ // If the I/O Architecture Type is still unknown then HALT.
+ //
+
+ if (HalpIoArchitectureType == UNKNOWN_PROCESSOR_MODULE) {
+ for(;;);
+ }
+
+ HalpPciConfig0BasePhysical = GAMBIT_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = GAMBIT_PCI_CONFIG1_BASE_PHYSICAL;
+
+ //
+ // Determine the motherboard type. Assume TREBBIA20 so we can do some config cycles.
+ //
+
+ HalpMotherboardType = TREBBIA20;
+
+ Device16 = HalpPciLowLevelConfigRead(0,0x10,0,0);
+ Device17 = HalpPciLowLevelConfigRead(0,0x11,0,0);
+
+ //
+ // Now assume motherboard type is unknown and check out values returned from config cycles.
+ //
+
+ HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+
+ if (Device16 == 0x00211011 && Device17 == 0x00211011) {
+ HalpMotherboardType = TREBBIA20;
+
+ //
+ // Find and initialize up to two Jubilee adapters.
+ //
+
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 1;
+ HalpIntel82378DeviceNumber = FindIntel82378(0,0x11,1,0);
+ HalpSecondPciBridgeBusNumber = (UCHAR)((HalpPciLowLevelConfigRead(0,0x10,0,0x18) >> 8) & 0xff);
+ HalpSecondIntel82378DeviceNumber = FindIntel82378(0,0x10,HalpSecondPciBridgeBusNumber,1);
+ if (HalpSecondIntel82378DeviceNumber != 0) {
+ HalpNumberOfIsaBusses = 2;
+ }
+ HalpVgaDecodeBusNumber = 0x00;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x01;
+ }
+ if (HalpPciLowLevelConfigRead(0,0x10,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ if (Device16 == 0x04848086 && Device17 == 0x00011011) {
+ HalpMotherboardType = TREBBIA13;
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 0;
+ HalpIntel82378DeviceNumber = 0x10;
+ HalpVgaDecodeBusNumber = 0x01;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ //
+ // If the Motherboard Type is unknown then HALT.
+ //
+
+ if (HalpMotherboardType == MOTHERBOARD_UNKNOWN) {
+ for(;;);
+ }
+
+ //
+ // Determine the base physical addresses and PCI interrupt translation tables.
+ //
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpRangeList = Gambit20Trebbia13RangeList;
+ HalpNonExistentPciDeviceMask = ~TREB13_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb13InterruptLineToBit;
+ HalpBitToInterruptLine = Treb13BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb13InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb13VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd1) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0d);
+ }
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd2) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0f);
+ }
+ }
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL;
+ HalpRangeList = Gambit20Trebbia20RangeList;
+ HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb20InterruptLineToBit;
+ HalpBitToInterruptLine = Treb20BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb20InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb20VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB20SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableNcr) {
+ HalpNonExistentPci2DeviceMask |= (1 << 0x07);
+ }
+ }
+ }
+
+ //
+ // If the address translation table is still NULL then HALT.
+ //
+
+ if (HalpRangeList == NULL) {
+ for(;;);
+ }
+}
+
+BOOLEAN
+HalpInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL).
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+#ifdef WINNT350
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PLIST_ENTRY DeleteMd;
+#endif
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpGetIoArchitectureType();
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+#ifdef WINNT350
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+ //
+ // If Descriptor is >256 MB then remove it for NT 3.5.
+ // This problem was fixed in NT 3.51.
+ //
+
+ DeleteMd = NextMd;
+ NextMd = Descriptor->ListEntry.Flink;
+ if ((Descriptor->BasePage + Descriptor->PageCount) >= ((256*1024*1024)/4096)) {
+
+ //
+ // Delete Descriptor
+ //
+
+ RemoveEntryList(DeleteMd);
+ }
+
+ }
+#endif
+
+ //
+ // Initialize Dma Cache Parameters
+ //
+
+ HalpMapBufferSize = GAMBIT_DMA_CACHE_SIZE;
+ HalpMapBufferPhysicalAddress.QuadPart = GAMBIT_DMA_CACHE_BASE_PHYSICAL;
+
+ return TRUE;
+
+ } else {
+
+ UCHAR Message[80];
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpMapIoSpace();
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus ();
+
+ //
+ // Initialize the display adapter.
+ //
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ HalpInitializeX86DisplayAdapter();
+ IoSpaceAlreadyMapped = TRUE;
+ }
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalDisplayString("DeskStation Technology UniFlex/Raptor 3 Motherboard Rev. 1\n\r");
+ } else {
+ HalDisplayString("DeskStation Technology Raptor ReFlex Motherboard Rev. 2\n\r");
+ }
+
+ HalDisplayString("DeskStation Technology MIPS R4600 Processor Module\n\r");
+
+ HalpCreateDmaStructures();
+
+ HalpCalibrateStall();
+
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halflex/mips/intsup.c b/private/ntos/nthals/halflex/mips/intsup.c
new file mode 100644
index 000000000..9ef7a4e98
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/intsup.c
@@ -0,0 +1,240 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ intsup.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt for
+ platform specific vectors.
+
+Author:
+
+ Michael D. Kinney 14-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalpDisablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // There are no additional interrupts for MIPS processors
+ //
+
+ return;
+}
+
+
+BOOLEAN
+HalpEnablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ //
+ // There are no additional interrupts for MIPS processors
+ //
+
+ return FALSE;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ if ( (InterfaceType==PCI_BUS && BusInterruptLevel>=0x0 && BusInterruptLevel<=0x0f) ||
+ (HalpMotherboardType==TREBBIA13 && InterfaceType==Isa && BusNumber==1) ) {
+
+ ULONG i;
+
+ for(i=0;i<12;i++) {
+ if (BusInterruptLevel == HalpPlatformSpecificExtension->PciInterruptToIsaIrq[i]) {
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel = HalpVirtualIsaInterruptToInterruptLine(i) - 0x10;
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+ }
+ }
+
+ //
+ // Unrecognized interrupt
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+ } else if (InterfaceType == PCIBus && BusInterruptLevel >= 0x10) {
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel -= 0x10;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR.
+ //
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+
+ } else if (InterfaceType == Isa) {
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_ISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_ISA1_VECTORS);
+ }
+ } else if (InterfaceType == Eisa) {
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_EISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_EISA1_VECTORS);
+ }
+
+ } else {
+
+ //
+ // Not an interface supported on EB64P systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ }
+}
diff --git a/private/ntos/nthals/halflex/mips/j4cache.s b/private/ntos/nthals/halflex/mips/j4cache.s
new file mode 100644
index 000000000..d50bd2ba5
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/j4cache.s
@@ -0,0 +1,1091 @@
+#if defined(R4000)
+
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "gambit.h"
+
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30:
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,ZpA1(sp) // get old color value
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
+
+ SBTTL("Invalidate Secondary Cache Page")
+//++
+//
+// VOID
+// HalpInvalidateSecondaryCachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInvalidateSecondaryCachePage)
+
+ .set noreorder
+ .set noat
+
+ li t0,GAMBIT_PFN_SECONDARY_CACHE_INVALIDATE_PHYSICAL_BASE
+ or a1,a1,t0
+
+// lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ li v0,0x10 // uncached cache policy
+
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: sw zero,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpInvalidateSecondaryCachePage
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/j4flshbf.s b/private/ntos/nthals/halflex/mips/j4flshbf.s
new file mode 100644
index 000000000..ff3a32f78
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/j4flshbf.s
@@ -0,0 +1,61 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/j4prof.c b/private/ntos/nthals/halflex/mips/j4prof.c
new file mode 100644
index 000000000..14f92a196
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/j4prof.c
@@ -0,0 +1,290 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter;
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter;
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ HalpPerformanceCounter.QuadPart = 0;
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halflex/mips/jxhalp.h b/private/ntos/nthals/halflex/mips/jxhalp.h
new file mode 100644
index 000000000..83bcf38bd
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/jxhalp.h
@@ -0,0 +1,122 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+typedef enum _ADDRESS_SPACE_TYPE{
+ BusMemory=0,
+ BusIo = 1,
+ UserBusMemory = 2,
+ UserBusIo = 3,
+ KernelPciDenseMemory = 4,
+ UserPciDenseMemory = 6,
+} ADDRESS_SPACE_TYPE, *PADDRESS_SPACE_TYPE;
+
+extern PVOID HalpSecondaryCacheResetBase;
+extern PVOID HalpFirmwareVirtualBase;
+extern PVOID PciInterruptRegisterBase;
+
+extern ULONG HalpIoArchitectureType;
+extern ULONG HalpMotherboardType;
+extern UCHAR *HalpInterruptLineToBit;
+extern UCHAR *HalpBitToInterruptLine;
+extern UCHAR *HalpInterruptLineToVirtualIsa;
+extern UCHAR *HalpVirtualIsaToInterruptLine;
+extern ULONGLONG HalpPciConfig0BasePhysical;
+extern ULONGLONG HalpPciConfig1BasePhysical;
+extern ULONGLONG HalpIsaIoBasePhysical;
+extern ULONGLONG HalpIsa1IoBasePhysical;
+extern ULONGLONG HalpIsaMemoryBasePhysical;
+extern ULONGLONG HalpIsa1MemoryBasePhysical;
+extern ULONGLONG HalpPciIoBasePhysical;
+extern ULONGLONG HalpPci1IoBasePhysical;
+extern ULONGLONG HalpPciMemoryBasePhysical;
+extern ULONGLONG HalpPci1MemoryBasePhysical;
+extern PPLATFORM_RANGE_LIST HalpRangeList;
+extern UCHAR HalpSecondPciBridgeBusNumber;
+extern ULONG PCIMaxBus;
+extern ULONG HalpIntel82378BusNumber;
+extern ULONG HalpIntel82378DeviceNumber;
+extern ULONG HalpSecondIntel82378DeviceNumber;
+extern ULONG HalpNonExistentPciDeviceMask;
+extern ULONG HalpNonExistentPci1DeviceMask;
+extern ULONG HalpNonExistentPci2DeviceMask;
+
+extern PLATFORM_RANGE_LIST Gambit20Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Gambit20Trebbia20RangeList[];
+
+extern UCHAR Treb13InterruptLineToBit[];
+extern UCHAR Treb13BitToInterruptLine[];
+extern UCHAR Treb13InterruptLineToVirtualIsa[];
+extern UCHAR Treb13VirtualIsaToInterruptLine[];
+extern UCHAR Treb20InterruptLineToBit[];
+extern UCHAR Treb20BitToInterruptLine[];
+extern UCHAR Treb20InterruptLineToVirtualIsa[];
+extern UCHAR Treb20VirtualIsaToInterruptLine[];
+extern ULONG HalpNumberOfIsaBusses;
+extern ULONG HalpVgaDecodeBusNumber;
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+VOID
+HalpInvalidateSecondaryCachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+
+VOID
+HalpArcsSetVirtualBase (
+ IN ULONG Number,
+ IN PVOID Base
+ );
+
+ULONG HalpPciLowLevelConfigRead(
+ IN ULONG BusNumber,
+ IN ULONG DeviceNumber,
+ IN ULONG FunctionNumber,
+ IN ULONG Register
+ );
+
+//
+// There is not need for Memory Barriers on MIPS, so just define them away.
+//
+
+#define HalpMb()
+
+//
+// Define used to determine if a page is within the DMA Cache range.
+//
+
+#define HALP_PAGE_IN_DMA_CACHE(Page) \
+ (Page>=0x0001c0 && Page<0x000200)
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halflex/mips/jxmapio.c b/private/ntos/nthals/halflex/mips/jxmapio.c
new file mode 100644
index 000000000..f7c277ec4
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/jxmapio.c
@@ -0,0 +1,192 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase[MAX_EISA_BUSSES];
+PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES];
+PVOID HalpPciControlBase[MAX_PCI_BUSSES];
+PVOID HalpPciMemoryBase[MAX_PCI_BUSSES];
+PVOID HalpRealTimeClockBase;
+PVOID HalpFirmwareVirtualBase;
+PVOID PciInterruptRegisterBase;
+PVOID HalpSecondaryCacheResetBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.QuadPart = HalpIsaIoBasePhysical;
+ HalpEisaControlBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ if (HalpMotherboardType == TREBBIA20) {
+ physicalAddress.QuadPart = HalpIsa1IoBasePhysical;
+ HalpEisaControlBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+ }
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.QuadPart = HalpIsaIoBasePhysical + 0x71;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map ISA Memory Space.
+ //
+
+ physicalAddress.QuadPart = HalpIsaMemoryBasePhysical;
+ HalpEisaMemoryBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+
+ if (HalpMotherboardType == TREBBIA20) {
+ physicalAddress.QuadPart = HalpIsa1MemoryBasePhysical;
+ HalpEisaMemoryBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+ }
+
+ //
+ // Map PCI control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.QuadPart = HalpPciIoBasePhysical;
+ HalpPciControlBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map PCI Memory Space.
+ //
+
+ physicalAddress.QuadPart = HalpPciMemoryBasePhysical;
+ HalpPciMemoryBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+
+ if (HalpMotherboardType == TREBBIA20) {
+ physicalAddress.QuadPart = HalpPci1IoBasePhysical;
+ HalpPciControlBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ physicalAddress.QuadPart = HalpPci1MemoryBasePhysical;
+ HalpPciMemoryBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+ }
+
+ //
+ // Map PCI interrupt space.
+ //
+
+ physicalAddress.QuadPart = GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL;
+ PciInterruptRegisterBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map Secondary Cache Reset space.
+ //
+
+ physicalAddress.QuadPart = GAMBIT_SECONDARY_CACHE_RESET_BASE_PHYSICAL;
+ HalpSecondaryCacheResetBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase[0] == NULL) ||
+ (HalpRealTimeClockBase == NULL) ||
+ (HalpEisaMemoryBase[0] == NULL) ||
+ (HalpPciControlBase[0] == NULL) ||
+ (HalpPciMemoryBase[0] == NULL) ||
+ (HalpSecondaryCacheResetBase == NULL)) {
+ return FALSE;
+ }
+
+ //
+ // Map 1 page of EISA control space to generate a virtual address that the firmware can use.
+ //
+
+ physicalAddress.QuadPart = HalpIsaIoBasePhysical;
+ HalpFirmwareVirtualBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+// HalpArcsSetVirtualBase(0,HalpEisaControlBase[0]);
+// HalpArcsSetVirtualBase(1,HalpEisaMemoryBase[0]);
+// HalpArcsSetVirtualBase(4,HalpPciControlBase);
+// HalpArcsSetVirtualBase(5,HalpPciMemoryBase);
+
+ HalpArcsSetVirtualBase(7,HalpFirmwareVirtualBase);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/mips/pcisup.c b/private/ntos/nthals/halflex/mips/pcisup.c
new file mode 100644
index 000000000..117a85228
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/pcisup.c
@@ -0,0 +1,1008 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ This module contains the routines that support PCI configuration cycles and
+ PCI interrupts.
+
+Author:
+
+ Michael D. Kinney 2-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define SP_VIRTUAL_BASE 0xffffa000
+
+#define INVALID_PCI_CONFIGURATION_ADDRESS (0x00000000)
+#define NO_PCI_DEVSEL_DATA_VALUE (0xffffffff)
+
+//
+// The following tables are used to map between PCI interrupt pins, PCI interrupt lines,
+// and virtual ISA interrupt indexes. The Uniflex architecture uses a 16 bit interrupt
+// controller for ISA interrupts and all PCI interrupts.
+// InterruptLine values between 0x10 and 0x20 are reserved
+// for PCI devices. InterruptLine values between 0x00 and 0x10 are reserved for ISA IRQs.
+//
+
+UCHAR Treb13InterruptLineToBit[0x11] = {0,1,2,3,8,9,10,11,12,12,12,12,12,12,4,5,12};
+UCHAR Treb13BitToInterruptLine[12] = {0x00,0x01,0x02,0x03,0x0e,0x0f,0x00,0x00,0x04,0x05,0x06,0x07};
+UCHAR Treb13InterruptLineToVirtualIsa[0x11] = {0,1,2,3,8,9,10,11,0,0,0,0,0,0,0,0,0};
+UCHAR Treb13VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0,0,0,0,0x14,0x15,0x16,0x17,0,0,0,0};
+
+UCHAR Treb20InterruptLineToBit[0x11] = {3,1,2,8,9,10,0,5,11,12,12,12,12,12,12,12,12};
+UCHAR Treb20BitToInterruptLine[12] = {0x06,0x01,0x02,0x00,0x00,0x07,0x00,0x00,0x03,0x04,0x05,0x08};
+UCHAR Treb20InterruptLineToVirtualIsa[0x11] = {0,1,2,3,8,9,10,11,0,0,0,0,0,0,0,0,0};
+UCHAR Treb20VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0,0,0,0,0x14,0x15,0x16,0x17,0,0,0,0};
+
+//
+// Interrupt mask for all active PCI interrupts including ISA Bus PICs
+//
+
+static volatile ULONG HalpPciInterruptMask;
+
+//
+// Interrupt mask for PCI interrupts that have been connected through device drivers.
+//
+
+static volatile ULONG HalpPciDeviceInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #0 PIC
+//
+
+static volatile ULONG HalpEisaInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #1 PIC
+//
+
+static volatile ULONG HalpEisa1InterruptMask;
+
+PVOID HalpAllocateIoMapping(
+ LONGLONG BaseAddress
+ )
+
+{
+ ENTRYLO HalpPte[2];
+ ULONG KdPortEntry;
+
+ //
+ // Map the PCI Configuration register into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = (ULONG)(BaseAddress >> 12);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+ //
+ // Map the PCI Configuration register through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+
+ return((PVOID)(SP_VIRTUAL_BASE + (ULONG)(BaseAddress & 0xfff)));
+}
+
+VOID HalpFreeIoMapping(
+ VOID
+ )
+
+{
+ HalpFreeTbEntry();
+}
+
+VOID
+HalpWritePciInterruptMask (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the interrupt mask register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WRITE_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x00,HalpPciInterruptMask&0x0f);
+ WRITE_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x08,(HalpPciInterruptMask>>4)&0x0f);
+ WRITE_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x10,(HalpPciInterruptMask>>8)&0x0f);
+}
+
+ULONG
+HalpReadPciInterruptStatus (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the interrupt status register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The lower 12 bits contain the status of each interrupt line going to the PCI
+ interrupt controller.
+
+--*/
+
+{
+ return( (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x00)<<0) & 0x00f |
+ (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x08)<<4) & 0x030 |
+ (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x10)<<8) & 0xf00 );
+}
+
+ULONG
+HalpGetMemoryMode (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the status of the MemoryMode bit that is embedded within
+ the PCI interrupt controller. The status of this bit must be preserved on all
+ writes to the PCI interrupt mask register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return( (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x08) & 0x08) << 4 );
+}
+
+VOID
+HalpSetPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to set in the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Bit==6 || Bit==7 || Bit>=12) {
+ return;
+ }
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask | (1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask | (1<<Bit);
+ HalpWritePciInterruptMask();
+}
+
+VOID
+HalpClearPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function clears a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to clear from the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Bit==6 || Bit==7 || Bit>=12) {
+ return;
+ }
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask & ~(1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask & ~(1<<Bit);
+ HalpWritePciInterruptMask();
+}
+
+VOID
+HalpEnablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to enable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpSetPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+VOID
+HalpDisablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpClearPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+ULONG
+HalpVirtualIsaInterruptToInterruptLine (
+ IN ULONG Index
+ )
+
+/*++
+
+Routine Description:
+
+ This function maps a virtual ISA interrupt to a PCI interrupt line value.
+ This provides the ability to use an ISA device driver on a PCI device.
+
+Arguments:
+
+ Index - Index into a platform specific table that maps PCI interrupts to
+ virtual ISA interrupts.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return(HalpVirtualIsaToInterruptLine[Index]);
+}
+
+BOOLEAN
+HalpEisa0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt dispatcher for all ISA Bus #0 interrupts.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ return(HalpEisaDispatch(Interrupt,ServiceContext,0));
+}
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt dispatcher for all PCI interrupts.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ ULONG PciInterruptStatus;
+ PULONG dispatchCode;
+ PKINTERRUPT interruptObject;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue = FALSE;
+ ULONG i;
+
+ //
+ // Get the active interrupt bits
+ //
+
+ PciInterruptStatus = HalpReadPciInterruptStatus();
+
+ //
+ // See if this is the interrupt for ISA Bus #0 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisaInterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,0);
+
+ //
+ // If there really was an interrupt on ISA Bus #0, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // See if this is the interrupt for ISA Bus #1 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisa1InterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,1);
+
+ //
+ // If there really was an interrupt on ISA Bus #1, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // Only keep interrupt bits that have been connected by device drivers.
+ //
+
+ PciInterruptStatus &= HalpPciDeviceInterruptMask;
+
+ //
+ // Dispatch to the ISRs of interrupts that have been connected by device drivers.
+ //
+
+ for(i=0;i<12;i++) {
+ if (PciInterruptStatus & (1<<i)) {
+
+ PCRInOffset = UNIFLEX_PCI_VECTORS + HalpBitToInterruptLine[i];
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+ }
+ }
+
+ return(returnValue);
+}
+
+UCHAR HalpGetInterruptLine(ULONG BusNumber,ULONG DeviceNumber,ULONG InterruptPin)
+
+/*++
+
+Routine Description:
+
+ This routine maps a PCI interrupt described by the device's bus number, device number, and
+ interrupt pin into the interrupt line value that is stored in the PCI config header.
+
+Arguments:
+
+ BusNumber - PCI bus number of the device.
+
+ DeviceNumber - PCI device number of the device.
+
+ InterruptPin - PCI interrupt pin of the device (A=1,B=2,C=3,D=4).
+
+Return Value:
+
+ Returns the PCI Interrupt Line value for the PCI device.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ if (HalpMotherboardType == TREBBIA13) {
+
+ if (BusNumber > 1)
+ {
+ BusNumber = 1;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x010401 : InterruptLine = 0x10; break; // Bus 1, Device 4, Int A
+ case 0x010601 : InterruptLine = 0x11; break; // Bus 1, Device 6, Int A
+ case 0x010501 : InterruptLine = 0x12; break; // Bus 1, Device 5, Int A
+ case 0x010701 : InterruptLine = 0x13; break; // Bus 1, Device 7, Int A
+ case 0x010402 : InterruptLine = 0x17; break; // Bus 1, Device 4, Int B
+ case 0x010602 : InterruptLine = 0x14; break; // Bus 1, Device 6, Int B
+ case 0x010502 : InterruptLine = 0x14; break; // Bus 1, Device 5, Int B
+ case 0x010702 : InterruptLine = 0x17; break; // Bus 1, Device 7, Int B
+ case 0x010403 : InterruptLine = 0x15; break; // Bus 1, Device 4, Int C
+ case 0x010603 : InterruptLine = 0x15; break; // Bus 1, Device 6, Int C
+ case 0x010503 : InterruptLine = 0x15; break; // Bus 1, Device 5, Int C
+ case 0x010703 : InterruptLine = 0x15; break; // Bus 1, Device 7, Int C
+ case 0x010404 : InterruptLine = 0x16; break; // Bus 1, Device 4, Int D
+ case 0x010604 : InterruptLine = 0x16; break; // Bus 1, Device 6, Int D
+ case 0x010504 : InterruptLine = 0x16; break; // Bus 1, Device 5, Int D
+ case 0x010704 : InterruptLine = 0x16; break; // Bus 1, Device 7, Int D
+ case 0x000d01 : InterruptLine = 0x1e; break; // Bus 0, Device 13, Int A
+ case 0x000f01 : InterruptLine = 0x1f; break; // Bus 0, Device 15, Int A
+ case 0x001001 : InterruptLine = 0x20; break; // Bus 0, Device 16, Int A
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ if (HalpMotherboardType == TREBBIA20) {
+
+ if (BusNumber == 0) {
+ return(0xff);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x000401 : InterruptLine = 0x20; break;
+
+ case 0x000501 :
+ case 0x000603 :
+ case 0x000704 : InterruptLine = 0x10; break;
+
+ case 0x000502 :
+ case 0x000604 :
+ case 0x000701 : InterruptLine = 0x11; break;
+
+ case 0x000503 :
+ case 0x000601 :
+ case 0x000702 : InterruptLine = 0x12; break;
+
+ case 0x000504 :
+ case 0x000602 :
+ case 0x000703 : InterruptLine = 0x13; break;
+
+ case 0x010401 :
+ case 0x010504 :
+ case 0x010603 : InterruptLine = 0x14; break;
+
+ case 0x010402 :
+ case 0x010501 :
+ case 0x010604 : InterruptLine = 0x15; break;
+
+ case 0x010403 :
+ case 0x010502 :
+ case 0x010601 : InterruptLine = 0x16; break;
+
+ case 0x010404 :
+ case 0x010503 :
+ case 0x010602 : InterruptLine = 0x17; break;
+
+ case 0x010701 : InterruptLine = 0x18; break;
+
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ return(InterruptLine);
+}
+
+VOID
+HalpConnectInterruptDispatchers (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function connects the PCI interrupt dispatch routine and enables
+ ISA interrupts so they will generate processor interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ //
+ // Initialize the EISA interrupt dispatcher and the PCI interrupt dispatcher
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_PCI_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpPciDispatch;
+ PCR->InterruptRoutine[UNIFLEX_EISA_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpEisa0Dispatch;
+
+DbgPrint("Intel82378 : Bus=%d Device=%d\n\r",HalpIntel82378BusNumber,HalpIntel82378DeviceNumber);
+DbgPrint("SecondIntel82378 : Bus=%d Device=%d\n\r",HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber);
+
+ InterruptLine = HalpGetInterruptLine(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,1);
+ HalpEisaInterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisaInterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+ InterruptLine = HalpGetInterruptLine(HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber,1);
+ HalpEisa1InterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisa1InterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+DbgPrint("HalpEisaInterruptMask = %08x\n\r",HalpEisaInterruptMask);
+DbgPrint("HalpEisa1InterruptMask = %08x\n\r",HalpEisa1InterruptMask);
+
+ //
+ // Enable ISA Interrupts on Gambit's PIC
+ //
+
+ HalpPciInterruptMask = HalpGetMemoryMode();
+ HalpPciInterruptMask |= (HalpEisaInterruptMask | HalpEisa1InterruptMask);
+ HalpWritePciInterruptMask();
+}
+
+VOID
+HalpDisableAllInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables all external interrupt sources.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG VirtualAddress;
+
+ VirtualAddress = (ULONG)HalpAllocateIoMapping(HalpIsaIoBasePhysical);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0x21,0xff);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0xa1,0xff);
+ HalpFreeIoMapping();
+
+ if (HalpNumberOfIsaBusses > 1) {
+ VirtualAddress = (ULONG)HalpAllocateIoMapping(HalpIsa1IoBasePhysical);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0x21,0xff);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0xa1,0xff);
+ HalpFreeIoMapping();
+ }
+
+ VirtualAddress = (ULONG)HalpAllocateIoMapping(GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL);
+
+ HalpPciInterruptMask = ((READ_REGISTER_ULONG(VirtualAddress+0x08) & 0x08) << 4);
+ WRITE_REGISTER_ULONG(VirtualAddress+0x00,HalpPciInterruptMask&0x0f);
+ WRITE_REGISTER_ULONG(VirtualAddress+0x08,(HalpPciInterruptMask>>4)&0x0f);
+ WRITE_REGISTER_ULONG(VirtualAddress+0x10,(HalpPciInterruptMask>>8)&0x0f);
+ HalpFreeIoMapping();
+
+ HalpPciDeviceInterruptMask = 0x0000;
+}
+
+ULONG HalpPciConfigStructuresInitialized = FALSE;
+PVOID HalpPciConfig0BaseAddress[0x20];
+PVOID HalpPciConfig1BaseAddress[0x100];
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (IN ULONG BusNumber)
+{
+ if (BusNumber == 0) {
+ return PciConfigType0;
+ } else if (BusNumber < PCIMaxBus) {
+ return PciConfigType1;
+ } else {
+ return PciConfigTypeInvalid;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ //
+ // If the Configuration Base Address tables have not been initialized, then
+ // initialize them to NULL.
+ //
+
+ if (HalpPciConfigStructuresInitialized == FALSE) {
+
+ ULONG i;
+
+ for(i=0;i<0x20;HalpPciConfig0BaseAddress[i++]=NULL);
+ for(i=0;i<0xff;HalpPciConfig1BaseAddress[i++]=NULL);
+ HalpPciConfigStructuresInitialized = TRUE;
+ }
+
+ ConfigType = HalpPCIConfigCycleType(BusNumber);
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+
+ //
+ // See if this is a nonexistant device on PCI Bus 0
+ //
+
+ if ( (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPciDeviceMask ) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ if (HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] == NULL) {
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ physicalAddress.QuadPart = HalpPciConfig0BasePhysical;
+ physicalAddress.QuadPart += (1 << (11 + Slot.u.bits.DeviceNumber));
+ HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] = MmMapIoSpace(physicalAddress,0x800,FALSE);
+
+ //
+ // If the mapping failed, then the return value is INVALID_PCI_CONFIGURATION_ADDRESS.
+ // This will cause Config Reads to return 0xffffffff, and Config Writes to do nothing.
+ //
+
+ if (HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] == NULL) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ }
+ pPciAddr->u.AsULONG = (ULONG)HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber];
+ pPciAddr->u.AsULONG += ((Slot.u.bits.FunctionNumber & 0x07) << 8);
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if DBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ } else {
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the First PCI-PCI Bridge
+ //
+
+ if (BusNumber == 1 && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci1DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the Second PCI-PCI Bridge
+ //
+
+ if (BusNumber == HalpSecondPciBridgeBusNumber && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci2DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+
+ if (HalpPciConfig1BaseAddress[BusNumber] == NULL) {
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ physicalAddress.QuadPart = HalpPciConfig1BasePhysical;
+ physicalAddress.QuadPart += ((BusNumber & 0xff) << 16);
+ HalpPciConfig1BaseAddress[BusNumber] = MmMapIoSpace(physicalAddress,0x10000,FALSE);
+
+ //
+ // If the mapping failed, then the return value is INVALID_PCI_CONFIGURATION_ADDRESS.
+ // This will cause Config Reads to return 0xffffffff, and Config Writes to do nothing.
+ //
+
+ if (HalpPciConfig1BaseAddress[BusNumber] == NULL) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ }
+ pPciAddr->u.AsULONG = (ULONG)HalpPciConfig1BaseAddress[BusNumber];
+ pPciAddr->u.AsULONG += ((Slot.u.bits.DeviceNumber & 0x1f) << 11);
+ pPciAddr->u.AsULONG += ((Slot.u.bits.FunctionNumber & 0x07) << 8);
+ pPciAddr->u.bits0.Reserved1 = PciConfigType1;
+
+#if DBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((UCHAR)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ return(READ_REGISTER_UCHAR(ConfigurationAddress));
+}
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((USHORT)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ return(READ_REGISTER_USHORT(ConfigurationAddress));
+}
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((ULONG)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ return(READ_REGISTER_ULONG(ConfigurationAddress));
+}
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ WRITE_REGISTER_UCHAR(ConfigurationAddress,ConfigurationData);
+ }
+}
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ WRITE_REGISTER_USHORT(ConfigurationAddress,ConfigurationData);
+ }
+}
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ WRITE_REGISTER_ULONG(ConfigurationAddress,ConfigurationData);
+ }
+}
+
+LONGLONG HalpMapPciConfigBaseAddress(
+ IN ULONG BusNumber,
+ IN ULONG DeviceNumber,
+ IN ULONG FunctionNumber,
+ IN ULONG Register
+ )
+
+{
+ LONGLONG BaseAddress;
+
+ if (BusNumber == 0) {
+ BaseAddress = HalpPciConfig0BasePhysical +
+ (1 << (11+(DeviceNumber & 0x1f))) +
+ ((FunctionNumber & 0x07) << 8) +
+ Register;
+ } else {
+ BaseAddress = HalpPciConfig1BasePhysical +
+ ((BusNumber & 0xff) << 16) +
+ ((DeviceNumber & 0x1f) << 11) +
+ ((FunctionNumber & 0x07) << 8) +
+ Register;
+ }
+ return(BaseAddress);
+}
+
+ULONG HalpPciLowLevelConfigRead(
+ IN ULONG BusNumber,
+ IN ULONG DeviceNumber,
+ IN ULONG FunctionNumber,
+ IN ULONG Register
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the resources needed to perform a single PCI
+ configuration read cycle. The read data is returned. For a MIPS processor,
+ a single TLB entry is borrowed so that I/O reads and writes can be performed
+ to PCI configuration space.
+
+Return Value:
+
+ Data retuned by the PCI config cycle.
+
+--*/
+
+{
+ LONGLONG BaseAddress;
+ PVOID VirtualAddress;
+ ULONG ReturnValue;
+
+ BaseAddress = HalpMapPciConfigBaseAddress(BusNumber,DeviceNumber,FunctionNumber,Register&0xfc);
+ VirtualAddress = HalpAllocateIoMapping(BaseAddress);
+ ReturnValue = READ_REGISTER_ULONG(VirtualAddress);
+ HalpFreeIoMapping();
+ return(ReturnValue);
+}
+
+VOID HalpPostCard(UCHAR Value)
+
+{
+ LONGLONG BaseAddress;
+ PVOID VirtualAddress;
+
+ BaseAddress = HalpMapPciConfigBaseAddress(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,0,0x4f);
+ VirtualAddress = HalpAllocateIoMapping(BaseAddress);
+ WRITE_REGISTER_UCHAR(VirtualAddress,0xcf);
+ HalpFreeIoMapping();
+
+ VirtualAddress = HalpAllocateIoMapping(HalpIsaIoBasePhysical + 0x420);
+ Value = (Value & 0x7f) | (READ_REGISTER_UCHAR(VirtualAddress) & 0x80);
+ HalpFreeIoMapping();
+
+ VirtualAddress = HalpAllocateIoMapping(HalpIsaIoBasePhysical + 0xc00);
+ WRITE_REGISTER_UCHAR(VirtualAddress,Value);
+ HalpFreeIoMapping();
+
+ BaseAddress = HalpMapPciConfigBaseAddress(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,0,0x4f);
+ VirtualAddress = HalpAllocateIoMapping(BaseAddress);
+ WRITE_REGISTER_UCHAR(VirtualAddress,0x4f);
+ HalpFreeIoMapping();
+}
diff --git a/private/ntos/nthals/halflex/mips/portsup.c b/private/ntos/nthals/halflex/mips/portsup.c
new file mode 100644
index 000000000..9e0171440
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/portsup.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ portsup.c
+
+Abstract:
+
+ This module implements the code that provides the resources required to
+ access the serial port that is used for the kernel debugger.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+#define SP_VIRTUAL_BASE 0xffffa000
+#define SERIAL_PORT_COM1 0x3F8
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ );
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+
+PUCHAR HalpAllocateKdPortResources(
+ OUT PVOID *SP_READ,
+ OUT PVOID *SP_WRITE
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the resources needed by the kernel debugger to
+ access a serial port. For a MIPS processor, a single TLB entry is borrowed
+ so that I/O reads and writes can be performed to the serial port.
+
+Arguments:
+
+ SP_READ - Kernel virtual address to use for I/O read operations.
+
+ SP_WRITE - Kernel virtual address to use for I/O write operations.
+
+Return Value:
+
+ The bus relative address of the COM port being used as a kernel debugger.
+
+--*/
+
+{
+ ULONG KdPortEntry;
+
+ HalpGetIoArchitectureType();
+
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = (ULONG)(HalpIsaIoBasePhysical >> 12);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ *SP_READ = (PVOID)(SP_VIRTUAL_BASE + SERIAL_PORT_COM1);
+ *SP_WRITE = (PVOID)(SP_VIRTUAL_BASE + SERIAL_PORT_COM1);
+
+ return((PUCHAR)(SERIAL_PORT_COM1));
+}
+
+VOID HalpFreeKdPortResources(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function deallocates the resources needed by the kernel debugger to
+ access a serial port. For a MIPS processor, this simply frees the TLB entry
+ that was borrowed.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpFreeTbEntry();
+}
diff --git a/private/ntos/nthals/halflex/mips/x4clock.s b/private/ntos/nthals/halflex/mips/x4clock.s
new file mode 100644
index 000000000..0e8475007
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/x4clock.s
@@ -0,0 +1,210 @@
+#if defined(R4000)
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // Get current time increment
+ jal KeUpdateSystemTime // update system time
+ lw t0,HalpNextTimeIncrement // Get NextTimeIncrement
+ sw t0,HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+ lw a0,HalpNextIntervalCount // Get Next Interval Count. If 0, then no change required
+ beq zero,a0,5f // See if time increment is to be changed
+ jal HalpProgramIntervalTimer // Program timer with new interval count value
+ lw t0,HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ sw t0,HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+ sw zero,HalpNextIntervalCount // Set HalpNextIntervalCount to 0
+5:
+ lw t0,KdDebuggerEnabled // check if debugger enabled
+ lbu t0,0(t0) //
+ beq zero,t0,10f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,10f // if eq, no breakin requested
+ li a0, DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+10: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ la t1,HalpPerformanceCounter // get performance counter address
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ j KeProfileInterrupt // process profile entries
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/x4tb.s b/private/ntos/nthals/halflex/mips/x4tb.s
new file mode 100644
index 000000000..d399da2ac
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/x4tb.s
@@ -0,0 +1,109 @@
+#if defined(R4000)
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/xxcalstl.c b/private/ntos/nthals/halflex/mips/xxcalstl.c
new file mode 100644
index 000000000..e1ce0b6b0
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/xxcalstl.c
@@ -0,0 +1,253 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Start the system clock to interrupt at MAXIMUM_INCREMENT intervals.
+ //
+ // N.B. MAXIMUM_INCREMENT is in 100ns units.
+ //
+
+ HalSetTimeIncrement(MAXIMUM_INCREMENT);
+ HalpProgramIntervalTimer(HalpNextIntervalCount);
+ HalpEnableEisaInterrupt(UNIFLEX_CLOCK2_LEVEL,Latched); /* Enable Timer1,Counter0 interrupt */
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (PCR->StallScaleFactor <= 0) {
+ PCR->StallScaleFactor = 1;
+ }
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+ HalpWriteCompareRegisterAndClear(0);
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halflex/mips/xxidle.s b/private/ntos/nthals/halflex/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halflex/mips/xxinitnt.c b/private/ntos/nthals/halflex/mips/xxinitnt.c
new file mode 100644
index 000000000..b8b757141
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/xxinitnt.c
@@ -0,0 +1,159 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0x8f, // IRQL 0
+ 0x8e, // IRQL 1
+ 0x8c, // IRQL 2
+ 0x88, // IRQL 3
+ 0x80, // IRQL 4
+ 0x80, // IRQL 5
+ 0x80, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Mask sure that all processor interrupts are inactive by masking off all device
+ // interrupts in the system's Programable Interrupt Controllers.
+ //
+
+ HalpDisableAllInterrupts();
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Connect the clock interrupt to the stall interrupt routine.
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Connect the R4000 count/compare interrupt to the early interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/pcip.h b/private/ntos/nthals/halflex/pcip.h
new file mode 100644
index 000000000..2d8527914
--- /dev/null
+++ b/private/ntos/nthals/halflex/pcip.h
@@ -0,0 +1,138 @@
+/*++ BUILD Version: 0000 Increment this if a change has global effects
+
+Copyright (C) 1994,1995 Microsoft Corporation
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ pcip.h
+
+Abstract:
+
+ This header file defines the private PCI bus HAL interfaces and
+ data types.
+
+--*/
+//
+// Hal specific PCI bus structures
+//
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define PCI_MAX_BUSSES 256
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev)
+
+//
+// Define PCI configuration cycle types.
+//
+typedef enum _PCI_CONFIGURATION_TYPES {
+ PciConfigTypeInvalid = -1,
+ PciConfigType0 = 0,
+ PciConfigType1 = 1
+} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES;
+
+typedef struct _PCI_CFG_CYCLE_BITS {
+ union {
+ struct {
+ ULONG Reserved1:2;
+ ULONG Reserved2:30;
+ } bits; // Generic Config Cycle
+
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG Idsel:21;
+ } bits0; // Type0 Config Cycle
+
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG DeviceNumber:5;
+ ULONG BusNumber:8;
+ ULONG Reserved2:7;
+ ULONG Enable:1;
+ } bits1; // Type 1 Config Cycle
+
+ ULONG AsULONG;
+ } u;
+} PCI_CFG_CYCLE_BITS, *PPCI_CFG_CYCLE_BITS;
+
+//
+// Define PCI cycle/command types.
+//
+
+typedef enum _PCI_COMMAND_TYPES{
+ PciCommandInterruptAcknowledge = 0x0,
+ PciCommandSpecialCycle = 0x1,
+ PciCommandIoRead = 0x2,
+ PciCommandIoWrite = 0x3,
+ PciCommandMemoryRead = 0x6,
+ PciCommandMemoryWrite = 0x7,
+ PciCommandConfigurationRead = 0xa,
+ PciCommandConfigurationWrite = 0xb,
+ PciCommandMemoryReadMultiple = 0xc,
+ PciCommandDualAddressCycle = 0xd,
+ PciCommandMemoryReadLine = 0xe,
+ PciCommandMemoryWriteAndInvalidate = 0xf,
+ MaximumPciCommand
+} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES;
+
+//
+// PCI platform-specific functions
+//
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber
+ );
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ );
+
+
+//
+// Define PCI configuration cycle types.
+//
+
+typedef enum _PCI_TYPE0_CONFIG_TYPE {
+ PciConfigType0AsIdsel,
+ PciConfigType0AsDeviceNumber
+} PCI_TYPE0_CONFIG_TYPE, *PPCI_TYPE0_CONFIG_TYPE;
+
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // NT Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Common alpha hal specific data
+ //
+
+ PVOID ConfigBaseQva;
+ PCI_TYPE0_CONFIG_TYPE PciType0ConfigType;
+ BOOLEAN BusIsAcrossPPB;
+
+ RTL_BITMAP DevicePresent;
+ ULONG DevicePresentBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+
+ ULONG MaxDevice;
+
+ //
+ // Platform-specific storage
+ //
+
+ PVOID PlatformSpecificData;
+
+} PCIPBUSDATA, *PPCIPBUSDATA;
diff --git a/private/ntos/nthals/halflex/platform.h b/private/ntos/nthals/halflex/platform.h
new file mode 100644
index 000000000..b679d15a6
--- /dev/null
+++ b/private/ntos/nthals/halflex/platform.h
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ platform.h
+
+Abstract:
+
+ This file contains definitions specific to private vector calls into
+ the ARCSBIOS firmware.
+
+Author:
+
+ Michael D. Kinney 1-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#define MAX_PROCESSORS 32
+#define MAX_SYSTEM_INTERRUPTS 256
+#define MAX_SYSTEM_EXCEPTIONS 64
+#define MAX_INTERRUPTS_PER_BUS 32
+#define ARC_NAME_LENGTH 128
+#define IDENTIFIER_LENGTH 64
+#define MAX_SIMM_SOCKETS 32
+#define MAX_BUSSES 16
+#define NUMBEROFNVRAMSECTIONS 5
+
+typedef enum { ISA_BUS, EISA_BUS, VESA_BUS, PCI_BUS, PROCESSOR_BUS, MAXIMUM_BUS } BUS_TYPE;
+
+typedef enum { IO_SPACE, MEMORY_SPACE, CONFIGURATION_TYPE_0_SPACE, CONFIGURATION_TYPE_1_SPACE, MAX_ADDRESS_SPACE_TYPE } ADDRESS_SPACE_TYPE;
+
+typedef enum { EDGE, LEVEL} INTERRUPT_MODE;
+
+typedef enum {UnifiedCache,SplitCache,NoCache} CACHE_TYPE;
+
+typedef struct {
+ CHAR VendorId[8];
+ CHAR ProductId[8];
+ }
+ SYSTEMID;
+
+typedef struct CACHE_DESCRIPTION
+ {
+ ULONG NumberOfSets; // Number of associative sets
+ ULONG RefillSize; // Number of lines read per refill
+ ULONG LineSize; // Size of refill in bytes
+ ULONG Size; // Size of cache set in bytes
+ }
+ CACHE_DESCRIPTION;
+
+typedef struct SPLIT_CACHE_DESCRIPTION
+ {
+ CACHE_DESCRIPTION Instruction; // Configuration information on the insruction cache of a split cache
+ CACHE_DESCRIPTION Data; // Configuration information on the data cache of a split cache
+ }
+ SPLIT_CACHE_DESCRIPTION;
+
+typedef struct PROCESSOR_CACHE_DESCRIPTION
+ {
+ CACHE_TYPE CacheType; // Cache type(i.e. Split or Unified)
+ ULONG CoherentWithDma; // TRUE if cache is coherent with DMA reads and writes
+ union
+ {
+ CACHE_DESCRIPTION UnifiedCache; // Configuration information on a unified cache
+ SPLIT_CACHE_DESCRIPTION SplitCache; // Configuration information on a split cache
+ };
+ }
+ PROCESSOR_CACHE_DESCRIPTION;
+
+typedef struct PROCESSOR
+ {
+ UCHAR *CpuIdentifier; // Pointer to the CPU's identifier
+ UCHAR *FpuIdentifier; // Pointer to the FPU's identifier
+ UCHAR *CpuName; // Pointer to the CPU's print name
+ UCHAR RevisionName[IDENTIFIER_LENGTH]; // CPU's revision print name
+ ULONG InternalClockSpeed; // Internal clock speed in MHz
+ ULONG ExternalClockSpeed; // External clock speed in MHz
+ ULONG StallExecutionDelay; // Count used in calibrated 1 us delay loop
+ PROCESSOR_CACHE_DESCRIPTION FirstLevel; // Primary cache configuration information
+ PROCESSOR_CACHE_DESCRIPTION SecondLevel; // Secondary cache configuration information
+ PROCESSOR_CACHE_DESCRIPTION ThirdLevel; // Third level cache configuration information
+ }
+ PROCESSOR;
+
+typedef struct SIMM_SOCKET
+ {
+ UCHAR Name[IDENTIFIER_LENGTH]; // Print string for the socket's name
+ UCHAR Size[IDENTIFIER_LENGTH]; // Print string for the socket's size
+ }
+ SIMM_SOCKET;
+
+typedef struct SYSTEM_IO_BUS
+ {
+ BUS_TYPE BusType; // Type of bus(i.e. ISA, EISA, VESA, PCI)
+ ULONG BusNumber; // Bus number starting from 0
+ ULONG BusConfigurationError; // TRUE if the bus is not configured correctly
+ ULONG AlliasedBus; // TRUE if this bus is an allias of another bus
+ ULONG DmaCacheOffset; // Bus Physical Offset of Dma Cache
+ PHYSICAL_ADDRESS AddressSpace[MAX_ADDRESS_SPACE_TYPE]; // Processor physical address for each address space type
+ PVOID VirtualAddress[MAX_ADDRESS_SPACE_TYPE]; // Processor virtual address for each address space type
+ ULONG NumberOfPhysicalSlots; // Number of physical slots in bus
+ ULONG NumberOfVirtualSlots; // Number of virtual slots in bus
+ }
+ SYSTEM_IO_BUS;
+
+typedef struct PLATFORM_DEVICE_INFO
+ {
+ UCHAR FloppyDriveATypeInformation;
+ UCHAR FloppyDriveBTypeInformation;
+ UCHAR Lpt1IrqInformation;
+ UCHAR Lpt2IrqInformation;
+ UCHAR Lpt3IrqInformation;
+ UCHAR SerialMouseInformation;
+ UCHAR CheckEisaSlots;
+ UCHAR LoadEmbeddedScsiDrivers;
+ UCHAR LoadFlashScsiDrivers;
+ UCHAR LoadSoftScsiDrivers;
+ UCHAR EnableDelays;
+ UCHAR ResetDelay;
+ UCHAR DetectDelay;
+ UCHAR EnableIDEDriver;
+ UCHAR EnableX86Emulator;
+ }
+ PLATFORM_DEVICE_INFO;
+
+typedef struct {
+ ULONG StartOffset;
+ ULONG EndOffset;
+ ULONG CheckSumOffset;
+ }
+ NVRAMDETAILS;
+
+typedef struct PLATFORM_PARAMETER_BLOCK
+ {
+ SYSTEMID SystemId; // VendorID and ProductID for this platform
+ UCHAR ArchitectureName[16]; // String for the processor architecture(MIPS,ALPHA,X86,PPC)
+ UCHAR ModuleName[16]; // String used to identify the module(MOLDAU,TYNE,GAMBIT,ROGUE,COBRA)
+
+ USHORT ArcVersion; // Major Version of ARC Specification
+ USHORT ArcRevision; // Minor Revision of ARC Specification
+ ULONG FirmwareRevision; // ARCS BIOS Firmware Revision
+
+ ULONG MultiProcessorSystem; // TRUE if system is an MP system
+ ULONG NumberOfCpus; // Total number of CPUs in the system
+ PROCESSOR Processor[MAX_PROCESSORS]; // Configuration information on each processor
+ PROCESSOR_CACHE_DESCRIPTION External; // Configuration information on a shared external cache
+
+ ULONG MemorySize; // Main memory size in bytes
+ ULONG SimmConfigurationError; // TRUE if the SIMMs are not correctly configured
+ SIMM_SOCKET SimmSocket[MAX_SIMM_SOCKETS]; // Configuration information on SIMMs
+
+ ULONG DmaCacheError; // TRUE if the DMA cache did not pass the memory test
+ ULONG DmaCacheVirtualAddress; // Processor virtual address of the DMA cache
+ PHYSICAL_ADDRESS DmaCachePhysicalAddress; // Processor physical address of the DMA cache
+ ULONG DmaCacheSize; // Size of the DMA Cache in bytes
+ ULONG DmaAlignmentRequirement; // DMA Buffer Alignment requirement in bytes
+
+ SYSTEM_IO_BUS SystemIoBus[MAX_BUSSES]; // Configuration information on system busses
+
+ ULONG InterruptDispatchTable[MAX_SYSTEM_INTERRUPTS]; // Dispatch table for processor and bus interrupts
+ ULONG ExceptionDispatchTable[MAX_SYSTEM_EXCEPTIONS]; // Dispatch table for processor exceptions
+
+ ULONG FirmwareBaseAddress; // Memory address for the start of the firmware code/data
+ ULONG FirmwareSize; // Size of the firmware code/data section in bytes
+ ULONG HeapStart; // Memory address for the start of the firmware heap
+ ULONG HeapEnd; // Memory address for the end of the firmware heap
+ ULONG StackBaseAddress; // Memory address for the start of the firmware stack
+ ULONG StackSize; // Size of the firmware stack section in bytes
+ ULONG ImageLibraryBaseAddress; // Memory address for the start of the image library
+ ULONG ImageLibrarySize; // Size of the image library in bytes
+
+ UCHAR ConsoleOutAdapterName[ARC_NAME_LENGTH]; // ARC name for the console out device's adapter
+ UCHAR ConsoleOutName[ARC_NAME_LENGTH]; // ARC name for the console out device
+ UCHAR ProductIdentifier[IDENTIFIER_LENGTH]; // Product identifier string
+ UCHAR ProductName[IDENTIFIER_LENGTH]; // Product name string
+ UCHAR HelpAboutBoxString[IDENTIFIER_LENGTH]; // Help about box string
+
+ PLATFORM_DEVICE_INFO PlatformDeviceInfo; // System info on how to detect I/O devices
+
+ NVRAMDETAILS NVRAMDetails[NUMBEROFNVRAMSECTIONS]; // Describes organization of NVRAM.
+
+ PVOID PlatformSpecificExtension; // Platform Specific Extension
+ }
+ PLATFORM_PARAMETER_BLOCK;
+
diff --git a/private/ntos/nthals/halflex/sources b/private/ntos/nthals/halflex/sources
new file mode 100644
index 000000000..26c244e5d
--- /dev/null
+++ b/private/ntos/nthals/halflex/sources
@@ -0,0 +1,141 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halflex
+TARGETPATH=\nt\public\sdk\lib
+
+TARGETTYPE=HAL
+
+INCLUDES=..\x86new;..\inc;..\..\inc
+
+!IF $(MIPS)
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\*\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+MIPS_ENABLE_MIPS3=1
+MSC_WARNING_LEVEL=/W3
+
+!ENDIF
+
+!IF $(ALPHA)
+TARGETLIBS=\nt\public\sdk\lib\*\libcntpr.lib
+
+ALPHA_WARNING_LEVEL=-W3
+C_DEFINES=-DEV5 -DTAGGED_NVRAM
+NT_UP=1
+
+!ENDIF
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ adjust.c \
+ bushnd.c \
+ drivesup.c \
+ allstart.c \
+ busdata.c \
+ ioproc.c \
+ iousage.c \
+ xxbeep.c \
+ xxclock.c \
+ xxdisp.c \
+ xxebsup.c \
+ xxenvirv.c \
+ xxhwsup.c \
+ xxinithl.c \
+ xxpcisup.c \
+ xxport.c \
+ xxreturn.c \
+ xxsysint.c \
+ xxtime.c \
+ x86bios.c \
+ alpha\addrsup.c \
+ alpha\arcssup.c \
+ alpha\evxcache.c \
+ alpha\ev4prof.c \
+ alpha\ev5prof.c \
+ alpha\evxprof.c \
+ alpha\initsys.c \
+ alpha\intsup.c \
+ alpha\jxmapio.c \
+ alpha\minitlb.c \
+ alpha\pcisup.c \
+ alpha\perfcntr.c \
+ alpha\portsup.c \
+ alpha\xxinitnt.c \
+ alpha\alphaio.s \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev5ints.s \
+ alpha\evxmem.s \
+ alpha\halpal.s \
+ alpha\evclock.s \
+ alpha\info.c \
+ alpha\xxidle.s
+
+MIPS_SOURCES=hal.rc \
+ adjust.c \
+ bushnd.c \
+ drivesup.c \
+ allstart.c \
+ busdata.c \
+ ioproc.c \
+ iousage.c \
+ xxbeep.c \
+ xxclock.c \
+ xxdisp.c \
+ xxebsup.c \
+ xxenvirv.c \
+ xxhwsup.c \
+ xxinithl.c \
+ xxpcisup.c \
+ xxport.c \
+ xxreturn.c \
+ xxsysint.c \
+ xxtime.c \
+ x86bios.c \
+ mips\addrsup.c \
+ mips\arcssup.c \
+ mips\flushio.c \
+ mips\info.c \
+ mips\initsys.c \
+ mips\jxmapio.c \
+ mips\intsup.c \
+ mips\j4prof.c \
+ mips\pcisup.c \
+ mips\portsup.c \
+ mips\xxcalstl.c \
+ mips\xxinitnt.c \
+ mips\xxidle.s \
+ mips\x4tb.s \
+ mips\j4flshbf.s \
+ mips\j4cache.s \
+ mips\x4clock.s
+
+DLLDEF=obj\*\hal.def
+
+NTTARGETFILES=$(TARGETPATH)\*\hal.lib
diff --git a/private/ntos/nthals/halflex/uniflex.h b/private/ntos/nthals/halflex/uniflex.h
new file mode 100644
index 000000000..6a239d454
--- /dev/null
+++ b/private/ntos/nthals/halflex/uniflex.h
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ platform.h
+
+Abstract:
+
+ This file contains definitions specific to the UNIFLEX motherboard.
+
+Author:
+
+ Michael D. Kinney 1-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// Define the motherboard types
+//
+
+#define MOTHERBOARD_UNKNOWN 0
+#define TREBBIA13 1
+#define TREBBIA20 2
+
+//
+// Define the processor module types
+//
+
+#define EV5_PROCESSOR_MODULE 0
+#define EV4_PROCESSOR_MODULE 1
+#define R4600_PROCESSOR_MODULE 2
+#define UNKNOWN_PROCESSOR_MODULE 0xffffffff
+
+//
+// Define the module chip set revision constants
+//
+
+#define EV4_MAX_CHIP_SET_REVISION 1
+#define EV5_MAX_CHIP_SET_REVISION 2
+#define MODULE_CHIP_SET_REVISION_UNKNOWN 0xffffffff
+
+//
+// Define the bus types
+//
+
+#define UNIFLEX_MACHINE_TYPE_ISA 0
+#define UNIFLEX_MACHINE_TYPE_EISA 1
+
+#define MAX_EISA_BUSSES 2
+#define MAX_PCI_BUSSES 2
+#define MAX_DMA_CHANNELS_PER_EISA_BUS 8
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER (0x10000/PAGE_SIZE)
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+#define NULL_MAP_REGISTER_BASE (PVOID)(0xfffffffe)
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define the maximum and minimum time increment values in 100ns units.
+//
+// N.B. these values are as close to exact values as possible given the input
+// clock of 1.19318167 hz (14.31818 / 12)
+//
+
+#define MAXIMUM_INCREMENT (99968) // Time increment in 100ns units - Approx 10 ms
+#define MINIMUM_INCREMENT (10032) // Time increment in 100ns units - Approx 1 ms
+
+//
+// Define clock constants.
+//
+
+#define AT_BUS_OSC 14318180 // 14.31818 MHz Crystal
+
+//
+// Define UniFlex PCI Bus #0 motherboard device mask.
+//
+
+#define TREB13_MOTHERBOARD_PCI_DEVICE_MASK (ULONG)((1<<0x0d) | (1<<0x0f) | (1<<0x10) | (1<<0x11))
+#define TREB20_MOTHERBOARD_PCI_DEVICE_MASK (ULONG)((1<<0x10) | (1<<0x11))
+
+//
+// Highest Virtual local PCI Slot is 20 == IDSEL PCI_AD[31]
+//
+
+#define PCI_MAX_LOCAL_DEVICE 20
diff --git a/private/ntos/nthals/halflex/x86bios.c b/private/ntos/nthals/halflex/x86bios.c
new file mode 100644
index 000000000..7968bca21
--- /dev/null
+++ b/private/ntos/nthals/halflex/x86bios.c
@@ -0,0 +1,599 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// The X86 Emulator built into the HAL is suported on MIPS and PPC,
+// but not ALPHA. If this is an ALPHA system, then don't include the
+// code that uses the X86 emulator in the HAL. Instead, use the X86
+// emulator built in the Firmware if one is available.
+//
+
+#ifndef ALPHA
+#define ENABLE_HAL_X86_EMULATOR
+#endif
+
+typedef struct FIRMWARE_INT_ARGUMENTS {
+ ULONG pEAX;
+ ULONG pEBX;
+ ULONG pECX;
+ ULONG pEDX;
+ ULONG pESI;
+ ULONG pEDI;
+ ULONG pEBP;
+ USHORT pES;
+ USHORT pDS;
+ USHORT pFlags;
+} FIRMWARE_INT_ARGUMENTS, *PFIRMWARE_INT_ARGUMENTS;
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+extern ULONG x86BiosIoSpace;
+ULONG HalpPciConfigAddress;
+
+#endif
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+ULONG HalpUseFirmwareX86Emulator = FALSE;
+
+typedef
+VOID
+(*PVENDOR_EXECUTE_INT) (
+ IN USHORT Type,
+ IN PFIRMWARE_INT_ARGUMENTS Context
+ );
+
+PVENDOR_EXECUTE_INT VendorX86ExecuteInt;
+
+VOID HalpInitializeX86DisplayAdapter()
+
+/*++
+
+Routine Description:
+
+ This function performs the initialization required to use an X86 emulator.
+ If a firmware level X86 emulator is available, then that emulator will be used.
+ Otherwise, we will default to using the emulator built into the HAL if it is
+ available.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context;
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ ULONG PciLength;
+ ULONG PciBus;
+ ULONG PciDevice;
+ ULONG PciFunction;
+ ULONG PciVideoAdapterFound;
+
+ //
+ // If EISA I/O Ports or EISA Memory could not be mapped, then leave the
+ // X86 BIOS Emulator disabled.
+ //
+
+ if (HalpEisaControlBase[0] == NULL || HalpEisaMemoryBase[0] == NULL) {
+ return;
+ }
+
+ //
+ // If Firmware level X86 Bios Emulator exists, then use that instead of the
+ // one built into the HAL.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength/4) >= 34) {
+
+ VendorX86ExecuteInt =
+ *(PVENDOR_EXECUTE_INT *)((ULONG)(SystemParameterBlock->VendorVector) + 34*4);
+
+ if (VendorX86ExecuteInt != NULL) {
+ HalpX86BiosInitialized = TRUE;
+ HalpUseFirmwareX86Emulator = TRUE;
+ HalpEnableInt10Calls = TRUE;
+ return;
+ }
+ }
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+ //
+ // Attempt to initialize the Display Adapter by executing the Display Adapters
+ // initialization code in its BIOS. The standard for PC video adapters is for
+ // the BIOS to reside at 0xC000:0000 on the ISA bus.
+ //
+
+ PciVideoAdapterFound = FALSE;
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PciBus = 0;
+ do {
+ for(PciDevice=0;PciDevice < PCI_MAX_DEVICES;PciDevice++) {
+ PciFunction = 0;
+ do {
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = PciDevice;
+ SlotNumber.u.bits.FunctionNumber = PciFunction;
+
+ PciLength = HalGetBusData (
+ PCIConfiguration,
+ PciBus,
+ SlotNumber.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciLength==0) {
+ break;
+ }
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if ( (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01) ||
+ (PciData->BaseClass == 0x03 && PciData->SubClass == 0x00) ) {
+ PciVideoAdapterFound = TRUE;
+ break;
+ }
+ if (PciFunction == 0 && ((PciData->HeaderType & 0x80)==0)) {
+ break;
+ }
+ PciFunction++;
+ } while (PciFunction < PCI_MAX_FUNCTION);
+ if (PciLength==0 || PciVideoAdapterFound) {
+ break;
+ }
+ }
+ if (PciLength==0 || PciVideoAdapterFound) {
+ break;
+ }
+ PciBus++;
+ } while (PciLength!=0);
+
+ if (PciVideoAdapterFound) {
+ if (PciBus < HalpSecondPciBridgeBusNumber) {
+ x86BiosInitializeBios(HalpPciControlBase[0], HalpPciMemoryBase[0]);
+ } else {
+ x86BiosInitializeBios(HalpPciControlBase[1], HalpPciMemoryBase[1]);
+ }
+ Context.Eax = (PciBus<<8) | (PciDevice<<3) | PciFunction;
+ } else {
+ x86BiosInitializeBios(HalpEisaControlBase[0], HalpEisaMemoryBase[0]);
+ Context.Eax = 0;
+ }
+ HalpX86BiosInitialized = TRUE;
+
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Ebx = 0;
+ Context.Ebp = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+
+ if (x86BiosInitializeAdapter(0xc0000, &Context, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+#endif
+}
+
+VOID HalpResetX86DisplayAdapter()
+
+/*++
+
+Routine Description:
+
+ This function invokes the X86 emulator to initialize a text mode 80x25 display.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context;
+
+ //
+ // Make INT 10 call to initialize 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ FIRMWARE_INT_ARGUMENTS Arguments;
+ XM86_CONTEXT Context;
+
+ //
+ // If the X86 BIOS Emulator has not been initialized then fail all INT calls.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return(FALSE);
+ }
+
+ //
+ // If the Video Adapter initialization failed, then we can not make INT 10 calls.
+ //
+
+ if (BiosCommand == 0x10 && HalpEnableInt10Calls == FALSE) {
+ return(FALSE);
+ }
+
+ if (HalpUseFirmwareX86Emulator == TRUE) {
+
+ //
+ // Make private vector call to the emulator in the firmware.
+ //
+
+ Arguments.pEAX = *Eax;
+ Arguments.pEBX = *Ebx;
+ Arguments.pECX = *Ecx;
+ Arguments.pEDX = *Edx;
+ Arguments.pESI = *Esi;
+ Arguments.pEDI = *Edi;
+ Arguments.pEBP = *Ebp;
+ Arguments.pES = 0;
+ Arguments.pDS = 0;
+ Arguments.pFlags = 0;
+
+ HalpAllocateArcsResources();
+
+ VendorX86ExecuteInt((USHORT)BiosCommand,&Arguments);
+
+ HalpFreeArcsResources();
+
+ *Eax = Arguments.pEAX;
+ *Ebx = Arguments.pEBX;
+ *Ecx = Arguments.pECX;
+ *Edx = Arguments.pEDX;
+ *Esi = Arguments.pESI;
+ *Edi = Arguments.pEDI;
+ *Ebp = Arguments.pEBP;
+
+ }
+ else {
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+ //
+ // Make call to emulator build into HAL
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+
+#endif
+
+ }
+
+ return TRUE;
+}
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+ ULONG PciBusNumber;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ //
+ // If PortNumber is in ISA Motherboard space, then overide the base address of
+ // the IO space with ISA space, otherwise, use the base address passed in on
+ // initialization.
+ //
+
+ if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) {
+ u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber);
+ } else {
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+
+ //
+ // If PortNumber is attempting to access the PCI config registers defined for X86 systems,
+ // intercept them, and make the appropriate HAL call to get the PCI confoguration data.
+ //
+
+ if (PortNumber == 0xcf8) {
+ Result = HalpPciConfigAddress;
+ } else if (PortNumber == 0xcfc && (HalpPciConfigAddress & 0x80000000)) {
+ PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff;
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f;
+ SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07;
+ HalGetBusDataByOffset (PCIConfiguration,
+ PciBusNumber,
+ SlotNumber.u.AsULONG,
+ &Result,
+ HalpPciConfigAddress & 0xfc,
+ 4
+ );
+
+ } else {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PciBusNumber;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ //
+ // If PortNumber is in ISA Motherboard space, then overide the base address of
+ // the IO space with ISA space, otherwise, use the base address passed in on
+ // initialization.
+ //
+
+ if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) {
+ u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber);
+ } else {
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ if (DataType == BYTE_DATA) {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+
+ //
+ // If PortNumber is attempting to access the PCI config registers defined for X86 systems,
+ // intercept them, and make the appropriate HAL call to get the PCI confoguration data.
+ //
+
+ if (PortNumber == 0xcf8) {
+ HalpPciConfigAddress = Value;
+ } else if (PortNumber == 0xcfc) {
+ PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff;
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f;
+ SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07;
+ HalSetBusDataByOffset (PCIConfiguration,
+ PciBusNumber,
+ SlotNumber.u.AsULONG,
+ &Value,
+ HalpPciConfigAddress & 0xfc,
+ 4
+ );
+
+ } else {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+#endif
diff --git a/private/ntos/nthals/halflex/xxbeep.c b/private/ntos/nthals/halflex/xxbeep.c
new file mode 100644
index 000000000..b3beef50e
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxbeep.c
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase[0];
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = (AT_BUS_OSC/12) / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeLowerIrql(oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halflex/xxclock.c b/private/ntos/nthals/halflex/xxclock.c
new file mode 100644
index 000000000..3a05b3ac1
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxclock.c
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define clock count and time table.
+//
+
+typedef struct _COUNT_ENTRY {
+ ULONG Count;
+ ULONG Time;
+} COUNT_ENTRY, *PCOUNT_ENTRY;
+
+COUNT_ENTRY TimeTable[] = {
+ {1197, 10032},
+ {2394, 20064},
+ {3591, 30096},
+ {4767, 39952},
+ {5964, 49984},
+ {7161, 60016},
+ {8358, 70048},
+ {9555, 80080},
+ {10731, 89936},
+ {11928, 99968}
+ };
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG IntervalCount
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+Arguments:
+
+ IntervalCount - Supplies cound value to be placed in the timer/counter.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+
+ //
+ // Set the system clock timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ controlBase = HalpEisaControlBase[0];
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)IntervalCount);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(IntervalCount >> 8));
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // The new clock count value is selected from a precomputed table of
+ // count/time pairs. The values in the table were selected for their
+ // accuracy and closeness to the values of 1ms, 2ms, 3ms, etc. to 10ms.
+ //
+ // N.B. The NT executive guarantees that this function will never
+ // be called with the desired incrment less than the minimum
+ // increment or greater than the maximum increment.
+ //
+
+ for (Index = 0; Index < sizeof(TimeTable) / sizeof(COUNT_ENTRY); Index += 1) {
+ if (DesiredIncrement <= TimeTable[Index].Time) {
+ break;
+ }
+ }
+
+ if (DesiredIncrement < TimeTable[Index].Time) {
+ Index -= 1;
+ }
+
+ HalpNextIntervalCount = TimeTable[Index].Count;
+ HalpNewTimeIncrement = TimeTable[Index].Time;
+ KeLowerIrql(OldIrql);
+ return HalpNewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halflex/xxdisp.c b/private/ntos/nthals/halflex/xxdisp.c
new file mode 100644
index 000000000..2722c3223
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxdisp.c
@@ -0,0 +1,293 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ Andre Vachon (andreva) 09-May-1992
+ David N. Cutler (davec) 27-Apr-1991
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define CSI 0x9b
+#define MAX_DISPLAY_BUFFER 256
+
+int sprintf();
+
+extern ULONG IoSpaceAlreadyMapped;
+
+static UCHAR DisplayInitializationString[] = {CSI,'3','7',';','4','4','m',CSI,'2','J',0};
+static UCHAR CarriageReturnString[] = {10,13,0};
+
+static ULONG HalOwnsDisplay = FALSE;
+static ULONG DisplayFile;
+
+static UCHAR DisplayBuffer[MAX_DISPLAY_BUFFER];
+static ULONG DisplayBufferInitialized = FALSE;
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpAllocateArcsResources();
+ ArcClose(DisplayFile);
+ HalpFreeArcsResources();
+ HalOwnsDisplay = FALSE;
+ HalpResetDisplayParameters = ResetDisplayParameters;
+ return;
+}
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Count;
+ ULONG i;
+
+ if (DisplayBufferInitialized==FALSE) {
+ DisplayBufferInitialized = TRUE;
+ strcpy(DisplayBuffer,"");
+ }
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ if ((strlen(DisplayBuffer)+strlen(String)) < MAX_DISPLAY_BUFFER) {
+ strcat(DisplayBuffer,String);
+ }
+ return;
+ }
+
+ if (HalOwnsDisplay==FALSE) {
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+
+ HalpAllocateArcsResources();
+
+ ArcOpen(ArcGetEnvironmentVariable("ConsoleOut"),ArcOpenWriteOnly,&DisplayFile);
+ ArcWrite(DisplayFile,DisplayInitializationString,strlen(DisplayInitializationString),&Count);
+ if (strlen(DisplayBuffer)!=0) {
+
+ for(i=0;i<strlen(DisplayBuffer);i++) {
+ switch (DisplayBuffer[i]) {
+ case '\n' : ArcWrite(DisplayFile,CarriageReturnString,strlen(CarriageReturnString),&Count);
+ break;
+ default : ArcWrite(DisplayFile,&(DisplayBuffer[i]),1,&Count);
+ break;
+ }
+ }
+
+ strcpy(DisplayBuffer,"");
+ }
+
+ HalpFreeArcsResources();
+
+ HalOwnsDisplay=TRUE;
+
+ }
+
+ HalpAllocateArcsResources();
+
+ for(i=0;i<strlen(String);i++) {
+ switch (String[i]) {
+ case '\n' : ArcWrite(DisplayFile,CarriageReturnString,strlen(CarriageReturnString),&Count);
+ break;
+ default : ArcWrite(DisplayFile,&(String[i]),1,&Count);
+ break;
+ }
+ }
+
+ HalpFreeArcsResources();
+
+ return;
+}
+
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_DISPLAY_STATUS *DisplayStatus;
+
+ //
+ // Get the display parameter values and return.
+ //
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Make firmware call to get the display's current status
+ //
+
+ HalpAllocateArcsResources();
+
+ DisplayStatus = ArcGetDisplayStatus(DisplayFile);
+
+ HalpFreeArcsResources();
+
+ *WidthInCharacters = DisplayStatus->CursorMaxXPosition;
+ *HeightInLines = DisplayStatus->CursorMaxYPosition;
+ *CursorColumn = DisplayStatus->CursorXPosition;
+ *CursorRow = DisplayStatus->CursorYPosition;
+
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHAR SetCursorPositionString[20];
+ ULONG Count;
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Build ANSI sequence to set the cursor position.
+ //
+
+ sprintf(SetCursorPositionString,"%c%d;%dH",CSI,CursorRow,CursorColumn);
+
+ HalpAllocateArcsResources();
+
+ ArcWrite(DisplayFile,SetCursorPositionString,strlen(SetCursorPositionString),&Count);
+
+ HalpFreeArcsResources();
+
+ return;
+}
diff --git a/private/ntos/nthals/halflex/xxebsup.c b/private/ntos/nthals/halflex/xxebsup.c
new file mode 100644
index 000000000..203c21720
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxebsup.c
@@ -0,0 +1,2375 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[MAX_EISA_BUSSES][MAX_DMA_CHANNELS_PER_EISA_BUS];
+
+UCHAR HalpEisaInterrupt1Mask[MAX_EISA_BUSSES];
+UCHAR HalpEisaInterrupt2Mask[MAX_EISA_BUSSES];
+UCHAR HalpEisaInterrupt1Level[MAX_EISA_BUSSES];
+UCHAR HalpEisaInterrupt2Level[MAX_EISA_BUSSES];
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ );
+
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY translationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specified data between the user buffer and the
+ map register buffer. First, the user buffer is mapped, if need be then
+ the data is copied. Finally, the user buffer will be unmapped, if need be.
+
+Arguments:
+
+ Mdl - Pointer to the Mdl that describes the pages of memory that are
+ being read or written.
+
+ translationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the xfer.
+
+ CurrentVa - Current Virtual Address in the buffer described by the Mdl
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - A Boolean value that indicates whether this is a write
+ to the device from memory of vise-versa.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) translationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Flush all writes off chip
+ //
+
+ HalpMb();
+ HalpMb();
+
+ //
+ // Copy the data between the user buffer and the map buffer.
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory ( bufferAddress, mapAddress, Length);
+
+ }
+
+ //
+ // Flush all writes off chip
+ //
+
+ HalpMb();
+ HalpMb();
+}
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ BOOLEAN MappingRequired;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ MappingRequired = FALSE;
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+ MappingRequired = TRUE;
+ }
+
+ if (MappingRequired) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+ return(STATUS_SUCCESS);
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. This field is
+ updated with the number of registers allocated in the event that less
+ were available than requested.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ UCHAR channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+ ULONG maximumLength;
+
+ eisaSystem = HalpBusType == UNIFLEX_MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+
+ //
+ // If the device is an ISA device, then limit the number of map registers.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa) {
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+ }
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!eisaSystem &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = (UCHAR)(DeviceDescriptor->DmaChannel & 0x03);
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // If the device is a 32 bit bus mastering device, then set field in AdapterObject.
+ //
+
+ if (DeviceDescriptor->InterfaceType == PCIBus && DeviceDescriptor->Master) {
+ adapterObject->NeedsMapRegisters = FALSE;
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->BusNumber = DeviceDescriptor->BusNumber;
+
+ adapterObject->ChannelNumber = channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch (channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (eisaSystem) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ adapterObject->MasterDevice = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+VOID
+HalpMapTransferHelper(
+ IN PMDL Mdl,
+ IN PVOID CurrentVa,
+ IN ULONG TransferLength,
+ IN PULONG PageFrame,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ Helper routine for bus master transfers that cross a page
+ boundary. This routine is separated out from the IoMapTransfer
+ fast path in order to minimize the total instruction path
+ length taken for the common network case where the entire
+ buffer being mapped is contained within one page.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ TransferLength = Supplies the current transferLength
+
+ PageFrame - Supplies a pointer to the starting page frame of the transfer
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+Return Value:
+
+ None. *Length will be updated
+
+--*/
+
+{
+ do {
+ if (*PageFrame + 1 != *(PageFrame + 1)) {
+ break;
+ }
+ TransferLength += PAGE_SIZE;
+ PageFrame++;
+
+ } while ( TransferLength < *Length );
+
+
+ //
+ // Limit the Length to the maximum TransferLength.
+ //
+
+ if (TransferLength < *Length) {
+ *Length = TransferLength;
+ }
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset);
+
+ if (MapRegisterBase==NULL_MAP_REGISTER_BASE) {
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous
+ //
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ //
+ // Compute the starting address of the transfer
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If the transfer is not completely contained within
+ // a page, call the helper to compute the appropriate
+ // length.
+ //
+ if (transferLength < *Length) {
+ HalpMapTransferHelper(Mdl, CurrentVa, transferLength, pageFrame, Length);
+ }
+
+ return(returnAddress);
+ }
+
+ transferLength = *Length;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ //
+ // If *pageFrame is in the DMA Cache, then it was allocated by HalAllocateCommonBuffer(),
+ // and should not be mapped.
+ //
+
+ if (MapRegisterBase != NULL_MAP_REGISTER_BASE && !HALP_PAGE_IN_DMA_CACHE(*pageFrame)) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+
+ //
+ // Force IoMapTransfer() to use the map buffer.
+ //
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress + pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(Mdl,
+ translationEntry,
+ CurrentVa,
+ transferLength,
+ WriteToDevice);
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == UNIFLEX_MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == UNIFLEX_MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ BOOLEAN masterDevice;
+ PVOID OriginalCurrentVa;
+
+ OriginalCurrentVa = CurrentVa;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+#if defined(_ALPHA_)
+
+ HalpCleanIoBuffers(Mdl,!WriteToDevice,TRUE);
+// HalFlushIoBuffers(Mdl,!WriteToDevice,TRUE);
+
+#endif
+
+ if (MapRegisterBase==NULL_MAP_REGISTER_BASE) {
+ return(TRUE);
+ }
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ //
+ // If there are no map registers being used then just return TRUE.
+ // If *pageFrame is in the DMA Cache, then it was allocated by HalAllocateCommonBuffer(),
+ // and was not be mapped. So, just return TRUE.
+ //
+
+ if (MapRegisterBase == NULL_MAP_REGISTER_BASE || HALP_PAGE_IN_DMA_CACHE(*pageFrame)) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice);
+
+#if defined(_MIPS_)
+
+ //
+ // If this is a page read then flush the buffer from the primary data cache so
+ // it can be potentially read into the primary instruction cache.
+ //
+
+ if ( (Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+
+ ULONG transferLength;
+ ULONG partialLength;
+
+ if (Length > PCR->FirstLevelDcacheSize) {
+ HalSweepDcache();
+ } else {
+
+ CurrentVa = OriginalCurrentVa;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ HalFlushDcachePage(CurrentVa,*pageFrame,partialLength);
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ transferLength += partialLength;
+ pageFrame++;
+ }
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalFlushDcachePage(CurrentVa,*pageFrame,partialLength);
+ }
+ }
+ }
+
+#endif
+
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BusNumber;
+
+ if (Vector >= UNIFLEX_EISA_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA_VECTOR) {
+
+ BusNumber = 0;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA_VECTORS;
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA1_VECTOR) {
+
+ BusNumber = 1;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask[BusNumber] &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level[BusNumber] |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level[BusNumber] &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level[BusNumber]
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask[BusNumber] &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask[BusNumber]
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level[BusNumber] |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level[BusNumber] &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level[BusNumber]
+ );
+ }
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BusNumber;
+
+ if (Vector >= UNIFLEX_EISA_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA_VECTOR) {
+
+ BusNumber = 0;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA_VECTORS;
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA1_VECTOR) {
+
+ BusNumber = 1;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask[BusNumber] |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask[BusNumber] |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask[BusNumber]
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ ULONG BusNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask[BusNumber] = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask[BusNumber]
+ );
+
+ HalpEisaInterrupt2Mask[BusNumber] = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level[BusNumber] = 0;
+ HalpEisaInterrupt2Level[BusNumber] = 0;
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ HalpConnectInterruptDispatchers();
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN ULONG BusNumber
+ )
+
+{
+ volatile UCHAR LowerVector;
+ volatile UCHAR UpperVector;
+ volatile UCHAR UpperVector1;
+ volatile PULONG dispatchCode;
+ volatile PKINTERRUPT interruptObject;
+ volatile USHORT PCRInOffset;
+ volatile BOOLEAN returnValue = FALSE;
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ UpperVector = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0);
+
+ //
+ // See if there is a real interrupt on Interrupt Controller 2
+ //
+
+ if (UpperVector & 0x80) {
+
+ UpperVector = UpperVector & 0x07;
+
+ if (BusNumber == 0) {
+ PCRInOffset = UpperVector + 8 + UNIFLEX_EISA_VECTORS;
+ }
+ if (BusNumber == 1) {
+ PCRInOffset = UpperVector + 8 + UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ UpperVector1 = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0);
+
+ if ((UpperVector1 & 0x80) && (UpperVector1 & 0x07) == UpperVector) {
+
+ UCHAR DataByte;
+
+//DbgPrint("ERROR : Interrupt controller 2 stuck on ISA bus %d : UpperVector1 = %02x\n\r",BusNumber,UpperVector1);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0x70;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // Program the interrupt mask register for the upper PIC
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ //
+ // Program the interrupt edge/level register for the upper PIC
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level[BusNumber]
+ );
+ }
+
+ return(returnValue);
+ }
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ LowerVector = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0);
+
+ //
+ // See if there is a real interrupt on Interrupt Controller 1
+ //
+
+ if (LowerVector & 0x80) {
+
+ LowerVector = LowerVector & 0x07;
+
+ if (LowerVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ if (BusNumber == 0) {
+ PCRInOffset = LowerVector + UNIFLEX_EISA_VECTORS;
+ }
+ if (BusNumber == 1) {
+ PCRInOffset = LowerVector + UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ //
+ // The interrupt vector for CLOCK2_LEVEL is directly connected by the HAL.
+ // If the interrupt is on CLOCK2_LEVEL then vector to the address stored
+ // in the PCR. Otherwise, bypass the thunk code in the interrupt object
+ // whose address is stored in the PCR.
+ //
+
+ if (PCRInOffset == UNIFLEX_CLOCK2_LEVEL) {
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])
+ (PCR->InterruptRoutine[PCRInOffset]);
+
+ } else {
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+ }
+ }
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+ }
+
+ //
+ // Spurrious Interrupt. Return FALSE
+ //
+
+ return(returnValue);
+}
diff --git a/private/ntos/nthals/halflex/xxenvirv.c b/private/ntos/nthals/halflex/xxenvirv.c
new file mode 100644
index 000000000..1b81d4cad
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxenvirv.c
@@ -0,0 +1,106 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+ CHAR *Value;
+
+ HalpAllocateArcsResources();
+ Value = ArcGetEnvironmentVariable(Variable);
+ HalpFreeArcsResources();
+
+ if (Value==NULL)
+ return(ENOENT);
+ if (strlen(Value)>Length)
+ return(ENOENT);
+ strcpy(Buffer,Value);
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+ ARC_STATUS ReturnValue;
+
+ HalpAllocateArcsResources();
+ ReturnValue = ArcSetEnvironmentVariable(Variable,Value);
+ HalpFreeArcsResources();
+ return(ReturnValue);
+}
diff --git a/private/ntos/nthals/halflex/xxhwsup.c b/private/ntos/nthals/halflex/xxhwsup.c
new file mode 100644
index 000000000..06f2d77d3
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxhwsup.c
@@ -0,0 +1,1250 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ BOOLEAN eisaSystem;
+ PMDL MapBufferMdl;
+
+ eisaSystem = HalpBusType == UNIFLEX_MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(HalpMapBufferSize) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+
+ // On an R4000 system, this space should be mapped with caches
+ // disabled to avoid having to perform page exports on IO writes
+ // and page purges on IO reads.
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disabled.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ //
+ // Flush all references to the map buffer from the caches.
+ //
+
+ MapBufferMdl = MmCreateMdl(NULL,MapBufferVirtualAddress,HalpMapBufferSize);
+ MmBuildMdlForNonPagedPool(MapBufferMdl);
+ HalFlushIoBuffers(MapBufferMdl,TRUE,TRUE);
+ IoFreeMdl(MapBufferMdl);
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!eisaSystem &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough HalpMapBufferSize / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject,HalpMapBufferSize))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ KIRQL irql;
+ PTRANSLATION_ENTRY translationEntry;
+ UCHAR SavedNeedsMapRegisters;
+ ULONG SavedMapRegistersPerChannel;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMapRegistersPerChannel = AdapterObject->MapRegistersPerChannel;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG)mapRegisterBase & ~NO_SCATTER_GATHER);
+ LogicalAddress->HighPart = 0;
+ LogicalAddress->LowPart = translationEntry->PhysicalAddress;
+
+ if (CacheEnabled) {
+ virtualAddress = (PVOID)(KSEG0_BASE | LogicalAddress->LowPart);
+ } else {
+ virtualAddress = translationEntry->VirtualAddress;
+ }
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(virtualAddress);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+ return(TRUE);
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+ UCHAR SavedNeedsMapRegisters;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ if (MasterAdapterObject != NULL) {
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = (LogicalAddress.LowPart - HalpMapBufferPhysicalAddress.LowPart) >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+
+ }
+
+ return;
+
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL_MAP_REGISTER_BASE) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG i;
+ BOOLEAN ReturnValue;
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ for(i=0;i<HalpNumberOfIsaBusses;i++) {
+ ReturnValue = HalpCreateEisaStructures(i);
+ }
+
+ return(ReturnValue);
+}
+
diff --git a/private/ntos/nthals/halflex/xxinithl.c b/private/ntos/nthals/halflex/xxinithl.c
new file mode 100644
index 000000000..4c91ae959
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxinithl.c
@@ -0,0 +1,286 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Constants
+//
+
+ADDRESS_USAGE
+UniFlexPCIMainMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __0MB, __1GB, // Start=0MB; Length=1GB
+ 0,0
+ }
+};
+
+//ADDRESS_USAGE
+//UniFlexPCIReservedMemorySpace = {
+// NULL, CmResourceTypeMemory, PCIUsage,
+// {
+// __1GB + __128MB, __2GB + __1GB - __128MB, // Start=0MB; Length=1GB
+// 0,0
+// }
+//};
+
+//ADDRESS_USAGE
+//UniFlexPCIReservedIoSpace = {
+// NULL, CmResourceTypePort, PCIUsage,
+// {
+// __32MB, ~(__32MB) + 1, // Start=32MB; Length= 4GB - 32MB
+// 0,0
+// }
+//};
+
+//
+// Type Declarations
+//
+
+typedef
+VOID
+(*PGET_PLATFORM_PARAMETER_BLOCK) (
+ OUT PLATFORM_PARAMETER_BLOCK **PlatformParameterBlock
+ );
+
+//
+// Global Veriables
+//
+
+KAFFINITY HalpActiveProcessors;
+ULONG HalpBusType = UNIFLEX_MACHINE_TYPE_EISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+PLATFORM_PARAMETER_BLOCK *HalpPlatformParameterBlock = NULL;
+PLATFORM_SPECIFIC_EXTENSION *HalpPlatformSpecificExtension = NULL;
+
+
+VOID HalpGetPlatformParameterBlock(VOID)
+
+/*++
+
+Routine Description:
+
+ This function gets the PlatformParameterBlock data structure from the
+ firmware. If the PlatformParameterBlock is not available, then the
+ system is halted.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PGET_PLATFORM_PARAMETER_BLOCK PrivateGetPlatformParameterBlock;
+
+ //
+ // Get Platform Parameter Block from Firmware
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 37) {
+ PrivateGetPlatformParameterBlock = *(PGET_PLATFORM_PARAMETER_BLOCK *)((ULONG)(SystemParameterBlock->VendorVector) + 37*4);
+ PrivateGetPlatformParameterBlock(&HalpPlatformParameterBlock);
+ HalpPlatformSpecificExtension = (PLATFORM_SPECIFIC_EXTENSION *)(HalpPlatformParameterBlock->PlatformSpecificExtension);
+ } else {
+
+ //
+ // HALT system. No platform parameter block available.
+ //
+
+ for(;;);
+ }
+}
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ Prcb = KeGetCurrentPrcb();
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set the active processor affinity mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+ //
+ // Set the DMA I/O Coherency to not coherent. This means that the instruction
+ // cache is not coherent with DMA, and the data cache is not coherent with DMA
+ // on either reads or writes.
+ //
+
+ KeSetDmaIoCoherency(0);
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+
+ //
+ // Get Platform Parameter Block from Firmware
+ //
+
+ HalpGetPlatformParameterBlock();
+
+ //
+ // Do platform specific initialization.
+ //
+
+ HalpInitSystem(Phase,LoaderBlock);
+
+ //
+ // Initialize interrupts.
+ //
+
+ HalpInitializeInterrupts();
+
+ //
+ // Register HAL Reserved Address Spaces
+ //
+
+// HalpRegisterAddressUsage (&UniFlexPCIMainMemorySpace);
+// HalpRegisterAddressUsage (&UniFlexPCIReservedMemorySpace);
+// HalpRegisterAddressUsage (&UniFlexPCIReservedIoSpace);
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ //
+ // Do platform specific initialization.
+ //
+
+ HalpInitSystem(Phase,LoaderBlock);
+
+ return TRUE;
+ }
+}
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+VOID
+HalpVerifyPrcbVersion ()
+{
+
+}
+
+
+
diff --git a/private/ntos/nthals/halflex/xxpcisup.c b/private/ntos/nthals/halflex/xxpcisup.c
new file mode 100644
index 000000000..ebe41bd0d
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxpcisup.c
@@ -0,0 +1,2391 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ Platform-independent PCI bus routines
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+typedef ULONG (*FncConfigIO) (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef struct {
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} CONFIG_HANDLER, *PCONFIG_HANDLER;
+
+
+//
+// Define PCI slot validity
+//
+typedef enum _VALID_SLOT {
+ InvalidBus = 0,
+ InvalidSlot,
+ ValidSlot
+} VALID_SLOT;
+
+//
+// Local prototypes for routines supporting PCI bus handler routines
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+ULONG HalpPCIReadUlong (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUchar (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshort (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlong (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUchar (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshort (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpPCILine2PinNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+VOID
+HalpPCIPin2LineNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+#if DBG
+BOOLEAN
+HalpValidPCIAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PHYSICAL_ADDRESS BAddr,
+ IN ULONG Length,
+ IN ULONG AddressSpace
+ );
+#endif
+
+//
+// Local prototypes of functions that are not built for Alpha AXP firmware
+//
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+#if DBG
+VOID
+HalpTestPci (
+ ULONG
+ );
+#endif
+
+//
+// Pragmas to assign functions to different kinds of pages.
+//
+
+#if !defined(AXP_FIRMWARE)
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePCIBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPCIBusHandler)
+#pragma alloc_text(INIT,HalpRegisterPCIInstallHandler )
+#pragma alloc_text(INIT,HalpDefaultPCIInstallHandler )
+#pragma alloc_text(INIT,HalpDeterminePCIDevicesPresent )
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif // ALLOC_PRAGMA
+#endif // !defined(AXP_FIRMWARE)
+
+#ifdef AXP_FIRMWARE
+
+#define ExFreePool(PoolData)
+
+#pragma alloc_text(DISTEXT, HalpInitializePCIBus )
+#pragma alloc_text(DISTEXT, HalpAllocateAndInitPCIBusHandler)
+#pragma alloc_text(DISTEXT, HalpRegisterPCIInstallHandler )
+#pragma alloc_text(DISTEXT, HalpDefaultPCIInstallHandler )
+#pragma alloc_text(DISTEXT, HalpDeterminePCIDevicesPresent )
+#pragma alloc_text(DISTEXT, HalpGetPCIData )
+#pragma alloc_text(DISTEXT, HalpSetPCIData )
+#pragma alloc_text(DISTEXT, HalpReadPCIConfig )
+#pragma alloc_text(DISTEXT, HalpWritePCIConfig )
+#pragma alloc_text(DISTEXT, HalpValidPCISlot )
+#if DBG
+#pragma alloc_text(DISTEXT, HalpValidPCIAddr )
+#endif
+#pragma alloc_text(DISTEXT, HalpPCIConfig )
+#pragma alloc_text(DISTEXT, HalpPCIReadUchar )
+#pragma alloc_text(DISTEXT, HalpPCIReadUshort )
+#pragma alloc_text(DISTEXT, HalpPCIReadUlong )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUchar )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUshort )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUlong )
+#pragma alloc_text(DISTEXT, HalpAssignPCISlotResources)
+#pragma alloc_text(DISTEXT, HalpAdjustPCIResourceList)
+
+#endif // AXP_FIRMWARE
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+BOOLEAN PCIInitialized = FALSE;
+ULONG PCIMaxLocalDevice;
+ULONG PCIMaxDevice;
+ULONG PCIMaxBus;
+PINSTALL_BUS_HANDLER PCIInstallHandler = HalpDefaultPCIInstallHandler;
+
+CONFIG_HANDLER PCIConfigHandlers = {
+ {
+ HalpPCIReadUlong, // 0
+ HalpPCIReadUchar, // 1
+ HalpPCIReadUshort // 2
+ },
+ {
+ HalpPCIWriteUlong, // 0
+ HalpPCIWriteUchar, // 1
+ HalpPCIWriteUshort // 2
+ }
+};
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The function intializes global PCI bus state from the registry.
+
+ The Arc firmware is responsible for building configuration information
+ about the number of PCI buses on the system and nature (local vs. secondary
+ - across a PCI-PCI bridge) of the each bus. This state is held in
+ PCIRegInfo.
+
+ The maximum virtual slot number on the local (type 0 config cycle)
+ PCI bus is registered here, based on the machine dependent define
+ PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice.
+
+ The maximum number of virtual slots on a secondary bus is fixed by the
+ PCI Specification and is represented by PCI_MAX_DEVICES. This
+ state is held in PCIMaxDevice.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+
+#if !defined(AXP_FIRMWARE)
+
+ //
+ // x86 Hal's can query the registry, while on Alpha pltforms we cannot.
+ // So we let the ARC firmware actually configure the bus/bridges.
+ //
+
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ PCI_COMMON_CONFIG CommonConfig;
+ ULONG BusNumber;
+ ULONG ibus;
+ PBUS_HANDLER Bus0;
+
+ //
+ // Has the PCI bus already been initialized?
+ //
+
+ if (PCIInitialized) {
+ return;
+ }
+
+ //
+ // Intialize PCI configuration to the maximum configuration for starters.
+ //
+
+ PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+
+ //
+ // Unless there exists any PCI-to-PCI bridges, there will only be 1
+ // bus.
+ //
+
+ PCIMaxBus = 1;
+
+ //
+ // For each "local" PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+ // After we determine how many "remote" PCI buses are present, we will
+ // add them.
+ //
+
+ for (ibus = 0; ibus < PCIMaxBus; ibus++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HaliHandlerForBus (PCIBus, ibus)) {
+ HalpAllocateAndInitPCIBusHandler (ibus);
+ }
+ }
+ //
+ // Initialize the slot number struct.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+
+ //
+ // Loop through each device.
+ //
+
+ Bus0 = HaliHandlerForBus(PCIBus, 0);
+
+ for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++) {
+
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function.
+ //
+
+ for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++) {
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the device's configuration space.
+ //
+
+ HalpReadPCIConfig(Bus0,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH);
+
+ //
+ // No device exists at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+
+ //
+ // If this is the first function number, then break, because
+ // we know a priori there will not be any devices on the
+ // other function numbers.
+ //
+
+ if (FunctionNumber == 0) {
+ break;
+ }
+
+ //
+ // Check the next function number.
+ //
+
+ continue;
+ }
+
+ //
+ // A PCI-to-PCI bridge has been discovered.
+ //
+
+ if (CommonConfig.BaseClass == 0x06 &&
+ CommonConfig.SubClass == 0x04 &&
+ CommonConfig.ProgIf == 0x00) {
+
+ //
+ // Get the subordinate bus number (which is the highest
+ // numbered bus this bridge will forward to) and add 1.
+ //
+
+ BusNumber = CommonConfig.u.type1.SubordinateBus + 1;
+
+ //
+ // The maximum subordinate across the local bus is the
+ // maximum number of busses.
+ //
+
+ if (PCIMaxBus < BusNumber) {
+ PCIMaxBus = BusNumber;
+ }
+ }
+
+ //
+ // If this is not a multi-function device then break out now.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+ }
+ }
+
+ //
+ // For each additional PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions. If there are no additional
+ // PCI buses, (i.e., no PCI-PCI bridges were found), this loop
+ // will exit before a single iteration.
+ //
+
+ for (ibus = 1; ibus < PCIMaxBus; ibus++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HaliHandlerForBus (PCIBus, ibus)) {
+ HalpAllocateAndInitPCIBusHandler (ibus);
+ }
+ }
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PCIInitialized = TRUE;
+
+#if DBG
+ HalpTestPci (0);
+#endif
+
+#else
+
+ PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+ PCIMaxBus = PCI_MAX_BUSSES;
+
+ //
+ // Note:
+ // Firmware will allocate bus handlers during
+ // PCI configuration.
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PCIInitialized = TRUE;
+
+#endif // !AXP_FIRMWARE
+
+}
+
+PBUS_HANDLER
+HalpAllocateAndInitPCIBusHandler (
+ IN ULONG BusNo
+ )
+{
+ PBUS_HANDLER Bus;
+
+ HaliRegisterBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // Bus Number
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA), // sizeof bus specific buffer
+ PCIInstallHandler, // PCI install handler
+ &Bus); // Bushandler return
+
+ return Bus;
+}
+
+NTSTATUS
+HalpDefaultPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ )
+{
+ PPCIPBUSDATA BusData;
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2LineNop;
+ BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCILine2PinNop;
+
+
+ // set defaults
+ //
+ // ecrfix - if we knew more about the PCI bus at this
+ // point (e.g., local vs. across bridge, PCI config
+ // space base QVA, APECS vs. Sable T2/T4 vs. LCA4 vs. ??? config
+ // cycle type 0 mechanism), we could put this info into
+ // the "BusData" structure. The nice thing about this is
+ // that we could eliminate the platform-dependent module
+ // PCIBUS.C.
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES - 1; // not currently used anywhere
+
+#if !defined(AXP_FIRMWARE)
+ //
+ // Perform DevicePresent scan for this bus.
+ //
+
+ HalpDeterminePCIDevicesPresent(Bus);
+#endif // !AXP_FIRMWARE
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpRegisterPCIInstallHandler(
+ IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
+)
+/*++
+
+Routine Description:
+
+ The function register's a machine-specific PCI Install Handler.
+ This allows a specific platform to override the default PCI install
+ handler, DefaultPCIInstallHandler().
+
+Arguments:
+
+ MachineSpecificPCIInstallHandler - Function that provides machine
+ specific PCI Bus Handler setup.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+ PCIInstallHandler = MachineSpecificPCIInstallHandler;
+
+ return;
+}
+
+VOID
+HalpDeterminePCIDevicesPresent(
+ IN PBUS_HANDLER Bus
+)
+/*++
+
+Routine Description:
+
+ The function determines which PCI devices and functions are
+ present on a given PCI bus. An RTL_BITMAP vector in the bus handler's
+ PCI-specific BusData is updated to reflect the devices that actually
+ exist on this bus.
+
+ THIS COULD BE DONE IN FIRMWARE!
+
+Arguments:
+
+ Bus - BusHandler for the bus to be searched. This bus handler must
+ have already been allocated and initialized.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+ PCI_COMMON_CONFIG CommonConfig;
+ PCI_SLOT_NUMBER Slot;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ ULONG cnt;
+ RTL_BITMAP DevicePresent;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Formally disable DevicePresent checking for this bus.
+ //
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+ BusData->DevicePresent.Buffer = NULL;
+
+ //
+ // Initialize local copy of device present bitmap
+ // (Can't update bus handler data because we need to probe
+ // the bus in question.)
+ //
+
+ RtlInitializeBitMap (&DevicePresent,
+ BusData->DevicePresentBits, 256);
+
+ //
+ // For this bus, probe each possible slot. If no device
+ // is present than indicate that in the DevicePresent structure.
+ //
+
+ Slot.u.AsULONG = 0;
+
+ for( DeviceNumber=0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++ ){
+
+ Slot.u.bits.DeviceNumber = DeviceNumber;
+
+ for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+ {
+
+ Slot.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read only first ULONG of PCI config space, which
+ // contains the Vendor ID.
+ //
+ // (DevicePresent checking is *not* in effect yet
+ // for this bus.)
+ //
+
+ HalpReadPCIConfig(Bus,
+ Slot,
+ &CommonConfig,
+ 0,
+ sizeof(ULONG));
+
+ //
+ // See if a device & function is present. If so, set a bit.
+ //
+
+ if (CommonConfig.VendorID != PCI_INVALID_VENDORID) {
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&DevicePresent, cnt, 1);
+ }
+
+ } // end for( FunctionNumber=0; ...
+
+ } // end for( DeviceNumber=0; ...
+
+ //
+ // Update bus data now that we know what's present on the bus.
+ // (DevicePresent checking is now in effect yet for this bus.)
+ //
+
+ BusData->DevicePresent = DevicePresent;
+
+ return;
+
+}
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the PCI bus data for a device.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalGetBusData request.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
+
+
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalSetBusData request.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00 ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configation value changed\n");
+ DbgBreakPoint ();
+ }
+#endif // DBG
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
+
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpPCILine2PinNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+{
+ // line-pin mappings not needed on alpha machines
+ return ;
+}
+
+VOID
+HalpPCIPin2LineNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+{
+ // line-pin mappings not needed on alpha machines
+ return ;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+#if 0
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigRead);
+#endif // 0
+
+ //
+ // Read the slot, if it's valid.
+ // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
+ // or a null (zero) buffer if we have a non-existant bus.
+ //
+
+ switch (HalpValidPCISlot (BusHandler, Slot))
+ {
+
+ case ValidSlot:
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigRead);
+ break;
+
+ case InvalidSlot:
+
+ //
+ // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ break ;
+
+ case InvalidBus:
+
+ //
+ // Invalid Bus, return return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) 0);
+ break ;
+ }
+
+ return;
+
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+
+ if (HalpValidPCISlot (BusHandler, Slot) != ValidSlot) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigWrite);
+}
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ ULONG BusNumber;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER Slot2;
+ PCI_CONFIGURATION_TYPES PciConfigType;
+ UCHAR HeaderType;
+ ULONG i, bit;
+
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ //
+ // If the initial device probe has been completed and no device
+ // is present for this slot then simply return invalid slot.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+
+ if( ( (BusData->DevicePresent).Buffer != NULL) &&
+ !RtlCheckBit(&BusData->DevicePresent, bit) ) {
+
+#if HALDBG
+
+ DbgPrint( "Config access supressed for bus = %d, device = %d, function = %d\n",
+ BusNumber,
+ Slot.u.bits.DeviceNumber,
+ Slot.u.bits.FunctionNumber );
+
+#endif // HALDBG
+
+ return InvalidSlot;
+ }
+
+
+ //
+ // Get the config cycle type for the proposed bus.
+ // (PciConfigTypeInvalid indicates a non-existent bus.)
+ //
+
+ PciConfigType = HalpPCIConfigCycleType(BusNumber);
+
+ //
+ // The number of devices allowed on a local PCI bus may be different
+ // than that across a PCI-PCI bridge.
+ //
+
+ switch(PciConfigType) {
+ case PciConfigType0:
+
+ if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) {
+#if HALDBG
+ DbgPrint("Invalid local PCI Slot %x\n", Slot.u.bits.DeviceNumber);
+#endif
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigType1:
+
+ if (Slot.u.bits.DeviceNumber > PCIMaxDevice) {
+#if HALDBG
+ DbgPrint("Invalid remote PCI Slot %x\n", Slot.u.bits.DeviceNumber);
+#endif
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigTypeInvalid:
+
+#if HALDBG
+ DbgPrint("Invalid PCI Bus %x\n", BusNumber);
+#endif
+ return InvalidBus;
+ break;
+
+ }
+
+ //
+ // Check function number
+ //
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return ValidSlot;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return InvalidSlot;
+ }
+
+ return ValidSlot;
+}
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ PCI_CFG_CYCLE_BITS PciAddr;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ //
+ // Setup platform-dependent state for configuration space access
+ //
+
+ HalpPCIConfigAddr(BusNumber, Slot, &PciAddr);
+
+ //
+ // Synchronize with PCI config space
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ //
+ // Do the I/O to PCI configuration space
+ //
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (&PciAddr, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ //
+ // Release spinlock
+ //
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+
+ return;
+}
+
+ULONG
+HalpPCIReadUchar (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ //
+ // The configuration cycle type is extracted from bits[1:0] of PciCfg.
+ //
+ // Since an LCA4 register generates the configuration cycle type
+ // on the PCI bus, and because Offset bits[1:0] are used to
+ // generate the PCI byte enables (C/BE[3:0]), clear PciCfg bits [1:0]
+ // out before adding in Offset.
+ //
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *Buffer = READ_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshort (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *((PUSHORT) Buffer) = READ_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlong (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *((PULONG) Buffer) = READ_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUchar (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset), *Buffer,
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshort (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset), *((PUSHORT) Buffer),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlong (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset), *((PULONG) Buffer),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (ULONG);
+}
+
+#if DBG
+
+BOOLEAN
+HalpValidPCIAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PHYSICAL_ADDRESS BAddr,
+ IN ULONG Length,
+ IN ULONG AddressSpace)
+/*++
+
+Routine Description:
+
+ Checks to see that the begining and ending 64 bit PCI bus addresses
+ of the 32 bit range of length Length are supported on the system.
+
+Arguments:
+
+ BAddr - the 64 bit starting address
+
+ Length - a 32 bit length
+
+ AddressSpace - is this I/O (1) or memory space (0)
+
+Return Value:
+
+ TRUE or FALSE
+
+--*/
+{
+ PHYSICAL_ADDRESS EAddr, TBAddr, TEAddr;
+ LARGE_INTEGER LiILen;
+ ULONG inIoSpace, inIoSpace2;
+ BOOLEAN flag, flag2;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ //
+ // Translated address to system global setting and verify
+ // resource is available.
+ //
+ // Note that this code will need to be changed to support
+ // 64 bit PCI bus addresses.
+ //
+
+ LiILen.QuadPart = (ULONG)(Length - 1); // Inclusive length
+ EAddr.QuadPart = BAddr.QuadPart + LiILen.QuadPart;
+
+ inIoSpace = inIoSpace2 = AddressSpace;
+
+ flag = HalTranslateBusAddress ( PCIBus,
+ BusNumber,
+ BAddr,
+ &inIoSpace,
+ &TBAddr
+ );
+
+ flag2 = HalTranslateBusAddress (PCIBus,
+ BusNumber,
+ EAddr,
+ &inIoSpace2,
+ &TEAddr
+ );
+
+ if (flag == FALSE || flag2 == FALSE || inIoSpace != inIoSpace2) {
+
+ //
+ // HalAdjustResourceList should ensure that the returned range
+ // for the bus is within the bus limits and no translation
+ // within those limits should ever fail
+ //
+
+ DbgPrint ("HalpValidPCIAddr: Error return for HalTranslateBusAddress %x.%x:%x %x.%x:%x\n",
+ BAddr.HighPart, BAddr.LowPart, flag,
+ EAddr.HighPart, EAddr.LowPart, flag2);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine the firmwaire-assigned resources.
+ Calls IoReportResources to report/confirm them.
+ Returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ PCI_SLOT_NUMBER PciSlot;
+
+ PCM_RESOURCE_LIST CmRes;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc;
+ PHYSICAL_ADDRESS BAddr;
+ ULONG addr;
+ ULONG Command;
+ ULONG cnt, len;
+ BOOLEAN conflict;
+
+ ULONG i, j, m, length, holdvalue;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH * 2;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory - here we allocate
+ // a single chunk of memory and partition it into three pieces, pointed
+ // to by three separate pointers.
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CmRes = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read the PCI device configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID || // empty slot
+ PciData->VendorID == 0x00) { // non-existant bus
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the devices current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData->u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ PciData->u.type0.ROMBaseAddress &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Build an CM_RESOURCE_LIST for the PCI device to report resources
+ // to IoReportResourceUsage.
+ //
+ // This code does *not* use IoAssignoResources, as the PCI
+ // address space resources have been previously assigned by the ARC firmware
+ //
+
+ CmRes->Count = 1;
+ CmRes->List[0].InterfaceType = PCIBus;
+ CmRes->List[0].BusNumber = BusNumber;
+
+ CmRes->List[0].PartialResourceList.Count = 0;
+
+ //
+ // Set current CM_RESOURCE_LIST version and revision
+ //
+
+ CmRes->List[0].PartialResourceList.Version = 0;
+ CmRes->List[0].PartialResourceList.Revision = 0;
+
+ CmDesc = CmRes->List[0].PartialResourceList.PartialDescriptors;
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: Resource List V%d.%d for slot %x:\n",
+ CmRes->List[0].PartialResourceList.Version,
+ CmRes->List[0].PartialResourceList.Revision,
+ Slot);
+
+#endif
+
+ //
+ // Interrupt resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ CmDesc->Type = CmResourceTypeInterrupt;
+ CmDesc->ShareDisposition = CmResourceShareShared;
+ CmDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ CmDesc->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ CmDesc->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+
+#if DBG
+ DbgPrint (" INT Level %x, Vector %x\n",
+ CmDesc->u.Interrupt.Level, CmDesc->u.Interrupt.Vector );
+#endif
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDesc++;
+ }
+
+ //
+ // Add a memory or port resoruce for each PCI resource
+ // (Compute the ROM address as well. Just append it to the Base
+ // Address table.)
+ //
+
+ holdvalue = PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES];
+ PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES] =
+ PciData->u.type0.ROMBaseAddress & ~PCI_ADDRESS_IO_SPACE;
+
+ Command = PciOrigData->Command;
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ addr = i = PciData->u.type0.BaseAddresses[j];
+
+ //
+ // calculate the length necessary - note there is more complicated
+ // code in the x86 HAL that probably isn't necessary
+ //
+
+ length = ~(i & ~((i & 1) ? 3 : 15)) + 1;
+
+ //
+ // I/O space resource
+ //
+
+ if (addr & PCI_ADDRESS_IO_SPACE) {
+
+ CmDesc->Type = CmResourceTypePort;
+ CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDesc->Flags = CM_RESOURCE_PORT_IO;
+
+ BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~3;
+ BAddr.HighPart = 0;
+
+#if DBG
+ HalpValidPCIAddr(BusHandler, BAddr, length, 1); // I/O space
+#endif
+
+ CmDesc->u.Port.Start = BAddr;
+ CmDesc->u.Port.Length = length;
+ Command |= PCI_ENABLE_IO_SPACE;
+#if DBG
+ DbgPrint (" IO Start %x:%08x, Len %x\n",
+ CmDesc->u.Port.Start.HighPart, CmDesc->u.Port.Start.LowPart,
+ CmDesc->u.Port.Length );
+#endif
+ //
+ // Memory space resource
+ //
+
+ } else {
+
+ CmDesc->Type = CmResourceTypeMemory;
+ CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == PCI_TYPE0_ADDRESSES) {
+ // this is a ROM address
+ if ((PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) == 0) {
+ //
+ // Ignore expansion ROMs which are not enabled by
+ // the firmware/ROM BIOS.
+ //
+
+ continue;
+ }
+ CmDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ BAddr.LowPart = PciOrigData->u.type0.ROMBaseAddress &
+ ~PCI_ROMADDRESS_ENABLED;
+ BAddr.HighPart = 0;
+ } else {
+ // this is a memory space base address
+ CmDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~15;
+ BAddr.HighPart = 0;
+ }
+
+#if DBG
+ HalpValidPCIAddr(BusHandler, BAddr, length, 0); // Memory space
+#endif
+
+ CmDesc->u.Memory.Start = BAddr;
+ CmDesc->u.Memory.Length = length;
+ Command |= PCI_ENABLE_MEMORY_SPACE;
+#if DBG
+ DbgPrint (" MEM Start %x:%08x, Len %x\n",
+ CmDesc->u.Memory.Start.HighPart, CmDesc->u.Memory.Start.LowPart,
+ CmDesc->u.Memory.Length );
+#endif
+ }
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDesc++;
+
+ if (Is64BitBaseAddress(addr)) {
+ // skip upper half of 64 bit address since we
+ // only supports 32 bits PCI addresses for now.
+ j++;
+ }
+ }
+ }
+
+ //
+ // Setup the resource list.
+ // Count only the acquired resources.
+ //
+
+ *pAllocatedResources = CmRes;
+ cnt = CmRes->List[0].PartialResourceList.Count;
+ len = sizeof (CM_RESOURCE_LIST) +
+ cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)",
+ cnt, len, *pAllocatedResources);
+#endif
+
+ //
+ // Report the IO resource assignments
+ //
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ *pAllocatedResources, // DriverList
+ len, // DriverListSize
+ DeviceObject, // DeviceObject
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ *pAllocatedResources, // DeviceList
+ len, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ if (NT_SUCCESS(status) && conflict) {
+
+ //
+ // IopReportResourceUsage saw a conflict?
+ //
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n",
+ status);
+#endif
+ status = STATUS_CONFLICTING_ADDRESSES;
+ goto CleanUp;
+ }
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status);
+#endif
+ goto CleanUp;
+ }
+
+ //
+ // Restore orginial data, turning on the appropiate decodes
+ //
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: IoReportResourseUsage succeeded\n");
+#endif
+
+ // enable IO & Memory decodes
+
+ PciOrigData->Command |= (USHORT) Command;
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: PCI Config Space updated with Command = %x\n",
+ Command);
+#endif
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ i = 0;
+ if (*pAllocatedResources) {
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts a PCI pResourceList and forces it to match the
+ pre-configured values in PCI configuration space for this device.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER PciSlot;
+ PPCI_COMMON_CONFIG PciData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt, bcnt;
+ ULONG MemoryBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+
+ //
+ // Fix any requested resources for this device to be the
+ // value set in PCI configuration space for this device.
+ //
+
+ //
+ // Get PCI common configuration space for this slot
+ //
+
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber),
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Copy base addresses based on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ for (bcnt=0; bcnt < PCI_TYPE0_ADDRESSES; bcnt++) {
+ BaseAddress[bcnt] = &PciData->u.type0.BaseAddresses[bcnt];
+ }
+ BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = bcnt;
+ break;
+ case 1:
+ for (bcnt=0; bcnt < PCI_TYPE1_ADDRESSES; bcnt++) {
+ BaseAddress[bcnt] = &PciData->u.type1.BaseAddresses[bcnt];
+ }
+ BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = bcnt;
+ break;
+
+ default:
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Walk each ResourceList and confine resources
+ // to preconfigured settings.
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+ ResourceList->Version = 1;
+ ResourceList->Revision = 1;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+ Descriptor = ResourceList->Descriptors;
+
+ //
+ // For each alternative list, reset to review entire
+ // set of Base Address registers
+ //
+ // We assume that the order of resource descriptors for
+ // each alternative list matches the order of the
+ // PCI configuration space base address registers
+ //
+
+ bcnt = 0;
+
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ //
+ // Limit desctiptor to to preconfigured setting
+ // held in the InterruptLine register.
+ //
+
+ switch (Descriptor->Type) {
+ case CmResourceTypeInterrupt:
+
+ //
+ // Confine interrupt vector to preconfigured setting.
+ //
+
+ Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine;
+ break;
+
+ case CmResourceTypePort:
+
+ //
+ // Assure that requested descriptor is valid
+ //
+
+ if (bcnt > RomIndex) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Confine to preconfigured setting.
+ //
+
+ Descriptor->u.Port.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~0x3;
+
+ Descriptor->u.Port.MaximumAddress.QuadPart =
+ Descriptor->u.Port.MinimumAddress.QuadPart +
+ Descriptor->u.Port.Length - 1;
+
+#if HALDBG
+ DbgPrint("AdjustPCIResourceList\nPort: MinimumAddress set to %x\n",
+ Descriptor->u.Port.MinimumAddress.QuadPart);
+
+ DbgPrint(" MaximumAddress set to %x\n",
+ Descriptor->u.Port.MaximumAddress.QuadPart);
+#endif
+
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Assure that requested descriptor is valid
+ //
+
+ if (bcnt > RomIndex) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Confine to preconfigured setting.
+ //
+
+ MemoryBaseAddress = *BaseAddress[bcnt];
+
+ if (bcnt == RomIndex) {
+ Descriptor->u.Memory.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~PCI_ROMADDRESS_ENABLED;
+ } else {
+ Descriptor->u.Memory.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~0xF;
+ }
+
+ Descriptor->u.Memory.MaximumAddress.QuadPart =
+ Descriptor->u.Memory.MinimumAddress.QuadPart +
+ Descriptor->u.Memory.Length - 1;
+
+ if (Is64BitBaseAddress(MemoryBaseAddress)) {
+ // skip upper half of 64 bit address since we
+ // only supports 32 bits PCI addresses for now.
+ bcnt++;
+ }
+
+
+#if HALDBG
+ DbgPrint("AdjustPCIResourceList\nMemory: MinimumAddress set to %x\n",
+ Descriptor->u.Memory.MinimumAddress.QuadPart);
+
+ DbgPrint(" MaximumAddress set to %x\n",
+ Descriptor->u.Memory.MaximumAddress.QuadPart);
+#endif
+ break;
+
+ case CmResourceTypeDma:
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Next descriptor
+ //
+ Descriptor++;
+ }
+
+ //
+ // Next Resource List
+ //
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+ }
+ return STATUS_SUCCESS;
+}
+
+#define TEST_PCI 1
+
+#if DBG && TEST_PCI
+
+VOID HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < 32; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+
+ }
+ DbgBreakPoint();
+}
+
+#endif // DBG && TEST_PCI
diff --git a/private/ntos/nthals/halflex/xxport.c b/private/ntos/nthals/halflex/xxport.c
new file mode 100644
index 000000000..3d0770236
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxport.c
@@ -0,0 +1,769 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+PSP_READ_REGISTERS SP_READ;
+PSP_WRITE_REGISTERS SP_WRITE;
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 6;
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 1843200.
+ //
+
+ BaudClock = 1843200;
+
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ KdComPortInUse = HalpAllocateKdPortResources(&SP_READ,&SP_WRITE);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff));
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ HalpFreeKdPortResources();
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpFreeKdPortResources();
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpAllocateKdPortResources(&SP_READ,&SP_WRITE);
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
+
+
diff --git a/private/ntos/nthals/halflex/xxreturn.c b/private/ntos/nthals/halflex/xxreturn.c
new file mode 100644
index 000000000..bbd381e12
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxreturn.c
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ HalpAllocateArcsResources();
+ ArcReboot();
+
+ //
+ // Should never get here...
+ //
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halflex/xxsysint.c b/private/ntos/nthals/halflex/xxsysint.c
new file mode 100644
index 000000000..4f3e00a44
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxsysint.c
@@ -0,0 +1,217 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+ Michael D. Kinney 2-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= UNIFLEX_EISA_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA1_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= UNIFLEX_PCI_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_PCI_VECTOR) &&
+ Irql == UNIFLEX_PCI_DEVICE_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // Call platform specific routine
+ //
+
+ HalpDisablePlatformInterrupt(Vector,Irql);
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ BOOLEAN Enabled = FALSE;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= UNIFLEX_EISA_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ Enabled = TRUE;
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA1_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= UNIFLEX_PCI_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_PCI_VECTOR) &&
+ Irql == UNIFLEX_PCI_DEVICE_LEVEL) {
+ HalpEnablePciInterrupt(Vector);
+ Enabled = TRUE;
+ }
+
+ //
+ // Call platform specific routine
+ //
+
+ if (!Enabled) {
+ Enabled = HalpEnablePlatformInterrupt(Vector,Irql,InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halflex/xxtime.c b/private/ntos/nthals/halflex/xxtime.c
new file mode 100644
index 000000000..bddec03d2
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxtime.c
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+#define BCDToBinary(D) (10 * (((D) & 0xf0) >>4 ) + ((D) & 0x0f))
+#define BinaryToBCD(B) ((((B) & 0xff) / 10) << 4 ) | (((B) & 0xff) % 10)
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_YEAR));
+ if (TimeFields->Year < 1992)
+ TimeFields->Year += 100;
+ TimeFields->Month = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MONTH));
+ TimeFields->Day = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_MONTH));
+ TimeFields->Weekday = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_WEEK)) - 1;
+ TimeFields->Hour = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_HOUR));
+ TimeFields->Minute = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MINUTE));
+ TimeFields->Second = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_SECOND));
+ TimeFields->Milliseconds = 0;
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN HalSetRealTimeClock (IN PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DayLightSavingsEnable = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(BinaryToBCD(TimeFields->Year - 1900)));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)BinaryToBCD(TimeFields->Month));
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)BinaryToBCD(TimeFields->Day));
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(BinaryToBCD(TimeFields->Weekday + 1)));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)BinaryToBCD(TimeFields->Hour));
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)BinaryToBCD(TimeFields->Minute));
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)BinaryToBCD(TimeFields->Second));
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase[0])->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase[0])->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/drivesup.c b/private/ntos/nthals/halfxs/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halfxs/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halfxs/hal.rc b/private/ntos/nthals/halfxs/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halfxs/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halfxs/hal.src b/private/ntos/nthals/halfxs/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halfxs/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halfxs/makefile b/private/ntos/nthals/halfxs/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halfxs/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halfxs/makefile.inc b/private/ntos/nthals/halfxs/makefile.inc
new file mode 100644
index 000000000..325690537
--- /dev/null
+++ b/private/ntos/nthals/halfxs/makefile.inc
@@ -0,0 +1,9 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halfxs.lib
+ copy $** $@
+
+$(TARGETPATH)\mips\hal.dll: $(TARGETPATH)\mips\halfxs.dll
+ copy $** $@
+ binplace $(BINPLACE_FLAGS) $@
diff --git a/private/ntos/nthals/halfxs/mips/allstart.c b/private/ntos/nthals/halfxs/mips/allstart.c
new file mode 100644
index 000000000..91c96b5dd
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/allstart.c
@@ -0,0 +1,70 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ //
+ // If the number of processors in the host configuration is one,
+ // then connect EISA interrupts to that processor zero. Otherwise,
+ // connect EISA interrupts to processor one.
+ //
+
+ if (**((PULONG *)(&KeNumberProcessors)) == 1) {
+ return HalpCreateEisaStructures();
+
+ } else if (PCR->Number == 1) {
+ return HalpCreateEisaStructures();
+
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halfxs/mips/cacherr.s b/private/ntos/nthals/halfxs/mips/cacherr.s
new file mode 100644
index 000000000..6d31bb5e7
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/cacherr.s
@@ -0,0 +1,199 @@
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// N.B. All the code in this routine MUST run in KSEG1 and reference
+// data only in KSEG1 until which time as any cache errors have
+// been corrected.
+//
+// N.B. This routine is NOT COMPLETE. All cache errors result in a
+// soft reset.
+//
+// Author:
+//
+// David N. Cutler (davec) 29-Jun-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved integer register at - a3
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+
+ SBTTL("Cache Error Handling")
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1. If the error is a single bit ECC error in the second
+// level data cache or the error is in the primary instruction cache,
+// then the error is corrected and execution is continued. Otherwise,
+// a fatal system error has occured and control is transfered to the
+// soft reset vector.
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCacheErrorRoutine)
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw AT,0(k0) // save registers AT - a3
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+
+//
+// Get the current processor state and cache error register, and check
+// if the error can be corrected.
+//
+
+ mfc0 v0,psr // get current processor state
+ mfc0 v1,cacheerr // get cache error state
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+//
+// The following code is temporary and will be removed when full cache
+// error support is included.
+//
+// ****** temp ******
+//
+
+ b SoftReset // ****** all error soft rest
+
+//
+// If the EXL bit is set in the processor state, then the error is not
+// recoverable because the EXL bit may be erroneously set (errata) and
+// it cannot be determined whether is should or should not be set, e.g.,
+// the exact addresses ranges over which EXL might be correctly set are
+// not verifiable. Also, k0 and k1 are destroyed before they are saved
+// and are used by the exception handling code (there is no way to save
+// a register in noncached memory wihtout the use of a register).
+//
+
+ sll a0,v0,31 - PSR_EXL // shift EXL bit in sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// If the error occured on the SysAd bus, then the error is not correctable.
+//
+
+ sll a0,v1,31 - CACHEERR_EE // shift EE bit into sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// Determine whether the error is in the instruction or data cache.
+//
+
+ sll a0,v1,31 - CACHEERR_ER // shift ER bit into sign
+ bgez a0,IcacheError // if gez, instruction cache error
+
+//
+// The error occured in the data cache.
+//
+// If the error is a data error in the primary cache, then the error
+// is not correctable since the cache line dirty bit is included in
+// the parity calculation and therefore may be wrong.
+//
+
+DcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bgez a0,SoftReset // if gez, error in primary cache
+ b ExitError // exit error
+
+//
+// The error occured in the instruction cache.
+//
+// If the error occured in the secondary data cache, then the error is not
+// correctable since there is not secondary instruciton cache.
+//
+
+IcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bltz a0,SoftReset // if ltz, error in secondary cache
+
+//
+// The cache error has been corrected - restore register state and continue
+// execution.
+//
+
+ExitError: //
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw AT,0(k0) // restore registers AT - a3
+ lw v0,4(k0) //
+ lw v1,8(k0) //
+ lw a0,12(k0) //
+ lw a1,16(k0) //
+ lw a2,20(k0) //
+ eret //
+ .set at
+ .set reorder
+
+//
+// Cache error cannot be corrected - transfer control to soft reset vector.
+//
+
+SoftReset: //
+ la k0,SOFT_RESET_VECTOR // get address of soft reset vector
+ j k0 // perform a soft reset
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halfxs/mips/halp.h b/private/ntos/nthals/halfxs/mips/halp.h
new file mode 100644
index 000000000..d5e4c8143
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/halp.h
@@ -0,0 +1,192 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+
+#if defined(_DUO_)
+
+#include "duodma.h"
+#include "duodef.h"
+#include "duoint.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdma.h"
+#include "jazzdef.h"
+#include "jazzint.h"
+
+#endif
+
+#include "hal.h"
+#include "jxhalp.h"
+
+#if defined(USE_BIOS_EMULATOR)
+
+#include "xm86.h"
+#include "x86new.h"
+
+#endif
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern USHORT HalpBuiltinInterruptEnable;
+extern ULONG HalpCurrentTimeIncrement;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KAFFINITY HalpEisaBusAffinity;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halfxs/mips/j4cache.s b/private/ntos/nthals/halfxs/mips/j4cache.s
new file mode 100644
index 000000000..3b5c32aa9
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/j4cache.s
@@ -0,0 +1,1038 @@
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30: j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t1) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t1) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+#if defined(_DUO_)
+
+30: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,30b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+#if defined(_DUO_)
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halfxs/mips/j4flshbf.s b/private/ntos/nthals/halfxs/mips/j4flshbf.s
new file mode 100644
index 000000000..ff3a32f78
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/j4flshbf.s
@@ -0,0 +1,61 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halfxs/mips/j4flshio.c b/private/ntos/nthals/halfxs/mips/j4flshio.c
new file mode 100644
index 000000000..2bce6b387
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/j4flshio.c
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halfxs/mips/j4prof.c b/private/ntos/nthals/halfxs/mips/j4prof.c
new file mode 100644
index 000000000..beca8478b
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/j4prof.c
@@ -0,0 +1,318 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart = 0;
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxbeep.c b/private/ntos/nthals/halfxs/mips/jxbeep.c
new file mode 100644
index 000000000..104cb2712
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxbeep.c
@@ -0,0 +1,133 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxdisp.c b/private/ntos/nthals/halfxs/mips/jxdisp.c
new file mode 100644
index 000000000..98d9ea91c
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxdisp.c
@@ -0,0 +1,1718 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ Andre Vachon (andreva) 09-May-1992
+ David N. Cutler (davec) 27-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+#include "string.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayG364Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayVxlSetup (
+ VOID
+ );
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+#define G300_VIDEO_CONTROL ((PG300_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_CONTROL ((PG364_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_RESET ((PVIDEO_REGISTER)0x403fe000)
+
+//
+// Define memory access constants for VXL
+//
+
+#define VXL_VIDEO_MEMORY_BASE 0x40000000
+#define BT484_BASE ((PBT484_REGISTERS)0x403fd000)
+#define CLOCK_BASE ((PUCHAR)0x403fe000)
+#define JAGUAR_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+
+//
+// The three type of g364 boards we support
+//
+
+#define JAZZG364 1
+#define MIPSG364 2
+#define OLIVETTIG364 3
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayResetRegisterBase = 0;
+ULONG HalpDisplayVxlClockRegisterBase = 0;
+ULONG HalpDisplayVxlBt484RegisterBase = 0;
+ULONG HalpDisplayVxlJaguarRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpG364Type = 0;
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G300")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG300Setup;
+
+ HalpDisplayControlBase =
+ ((PJAZZ_G300_CONFIGURATION_DATA)
+ (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = JAZZG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Mips G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = MIPSG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "OLIVETTI_G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = OLIVETTIG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "VXL")) {
+
+ HalpDisplayControllerSetup = HalpDisplayVxlSetup;
+ HalpDisplayVxlBt484RegisterBase = 0x60100000;
+ HalpDisplayVxlClockRegisterBase = 0x60200000;
+ HalpDisplayVxlJaguarRegisterBase = 0x60300000;
+
+ } else {
+ HalpDisplayTypeUnknown = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ Child = ConfigurationEntry->Child;
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ Pte.PFN = VIDEO_MEMORY_BASE >> PAGE_SHIFT;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayVxlSetup) {
+
+ //
+ // If this is VXL then map a page for the
+ // brooktree base
+ // Clock base
+ // jaguar base
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlBt484RegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 2) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlClockRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlJaguarRegisterBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+
+
+ } else {
+
+ //
+ // If we have a G364, use the page before last to map the reset register.
+ //
+
+ if (HalpDisplayControllerSetup == HalpDisplayG364Setup) {
+ Pte.PFN = ((ULONG)HalpDisplayResetRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+ }
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G300B display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG BackPorch;
+ PULONG Buffer;
+ ULONG DataLong;
+ ULONG FrontPorch;
+ ULONG HalfLineTime;
+ ULONG HalfSync;
+ ULONG Index;
+ ULONG Limit;
+ ULONG MultiplierValue;
+ ULONG ScreenUnitRate;
+ ULONG VerticalBlank;
+ ULONG ShortDisplay;
+ ULONG TransferDelay;
+
+ //
+ // Disable the G300B display controller.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Initialize the G300B boot register value.
+ //
+
+ ScreenUnitRate =
+ (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ MultiplierValue = 125000 / (ScreenUnitRate / 4);
+ DataLong = 0;
+ ((PG300_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue;
+ ((PG300_VIDEO_BOOT)(&DataLong))->ClockSelect = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Boot.Long, DataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G300B operational values.
+ //
+
+ HalfSync =
+ (HalpMonitorConfigurationData.HorizontalSync * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->HorizonalSync.Long, HalfSync);
+
+ BackPorch =
+ (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / ScreenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BackPorch.Long, BackPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ HalfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineTime.Long, HalfLineTime * 2);
+ FrontPorch =
+ (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) / ScreenUnitRate;
+
+ ShortDisplay = HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ShortDisplay.Long, ShortDisplay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BroadPulse.Long,
+ HalfLineTime - FrontPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ VerticalBlank = (HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalBackPorch -
+ (HalpMonitorConfigurationData.VerticalSync * 2)) * 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalBlank.Long,
+ VerticalBlank);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineStart.Long, LINE_START_VALUE);
+ if (BackPorch < ShortDisplay) {
+ TransferDelay = BackPorch - 1;
+ } else {
+ TransferDelay = ShortDisplay - 1;
+ }
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->TransferDelay.Long, TransferDelay);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - TransferDelay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->PixelMask.Long, G300_PIXEL_MASK_VALUE);
+
+ //
+ // Initialize the G300B control parameters.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->SeparateSync = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G300_DELAY_SYNC_CYCLES;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BlankOutput = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->AddressStep = 2;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Set up the color map for two colors.
+ //
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[1], 0x900000);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpDisplayG364Setup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G364 display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG videoClock;
+ ULONG videoPeriod;
+ ULONG backPorch;
+ ULONG dataLong;
+ ULONG frontPorch;
+ ULONG halfLineTime;
+ ULONG halfSync;
+ PULONG buffer;
+ ULONG index;
+ ULONG limit;
+ ULONG multiplierValue;
+ ULONG screenUnitRate;
+ ULONG shortDisplay;
+ ULONG transferDelay;
+ ULONG verticalBlank;
+
+ //
+ // Reset the G364 display controller.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_RESET->Long,
+ 0);
+
+ //
+ // Initialize the G364 boot register value.
+ //
+
+ if (HalpG364Type == MIPSG364) {
+
+ videoClock = 5000000;
+
+ } else {
+
+ videoClock = 8000000;
+
+ }
+
+ videoPeriod = 1000000000 / (videoClock / 1000);
+
+ screenUnitRate = (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ multiplierValue = videoPeriod / (screenUnitRate / 4);
+ dataLong = 0;
+ ((PG364_VIDEO_BOOT)(&dataLong))->Multiplier = multiplierValue;
+ ((PG364_VIDEO_BOOT)(&dataLong))->ClockSelect = 1;
+ ((PG364_VIDEO_BOOT)(&dataLong))->MicroPort64Bits = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Boot.Long,
+ dataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G364 control parameters.
+ //
+
+ dataLong = 0;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DelaySync = G364_DELAY_SYNC_CYCLES;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->AddressStep = G364_ADDRESS_STEP_INCREMENT;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DisableCursor = 1;
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize the G364 control parameters for VDR1 with patch for HSync
+ // problem during the VBlank. The control register is set to 0xB03041
+ // according to the hardware specs. @msu, Olivetti, 5/14/92
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->VideoOnly = 1;
+
+ } else {
+
+ //
+ // Only set tesselated sync in non-olivetti G364 cards when
+ // vertical frontporch is set to 1
+ //
+
+ if (HalpMonitorConfigurationData.VerticalFrontPorch != 1) {
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->PlainSync = 1;
+ }
+
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Initialize the G364 operational values.
+ //
+
+ halfSync = (HalpMonitorConfigurationData.HorizontalSync * 1000) / screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->HorizontalSync.Long,
+ halfSync);
+
+ backPorch = (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / screenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BackPorch.Long,
+ backPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ halfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) /
+ screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineTime.Long,
+ halfLineTime * 2);
+
+ frontPorch = (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) /
+ screenUnitRate;
+
+ shortDisplay = halfLineTime - ((halfSync * 2) + backPorch + frontPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ShortDisplay.Long,
+ shortDisplay);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize Broad Pulse, Vertical PreEqualize and Vertical
+ // PostEqualize registers to work with Olivetti monitors.
+ // @msu, Olivetti, 5/14/92
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ 0x30);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ } else {
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ halfLineTime - frontPorch);
+
+ // NOTE: changed the order to simplify if statement .
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ HalpMonitorConfigurationData.VerticalFrontPorch * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ }
+
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ verticalBlank = (HalpMonitorConfigurationData.VerticalBackPorch - 1) * 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalBlank.Long,
+ verticalBlank);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineStart.Long,
+ LINE_START_VALUE);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Fixes for Olivetti monitors, @msu, Olivetti
+ //
+
+ transferDelay = 30; // @msu
+
+ } else {
+
+ if (backPorch < shortDisplay) {
+ transferDelay = backPorch - 1;
+ } else {
+ transferDelay = shortDisplay - 4;
+ }
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->TransferDelay.Long,
+ transferDelay);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - transferDelay);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->PixelMask.Long,
+ 0xFFFFFF);
+
+ //
+ // Enable video
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->EnableVideo = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Set up the color map for two colors.
+ // NOTE: this device is not RGB but BGR.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[1], 0x000090);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)VIDEO_MEMORY_BASE;
+ limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpDisplayVxlSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the JazzVxl Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ UCHAR DataChar;
+ UCHAR CmdReg0;
+ ULONG Status;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+
+
+ //
+ // Define clock value for the ICS part (pS)
+ //
+
+ LONG ClockResList[32] = { 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4,42918,40984,38760,36724,33523,31017,
+ 29197,27548,24882,23491,22482,21468,20509,19920,
+ 18692,18054,16722,15015,14773,14053,13040, 4};
+
+ JAGUAR_REG_INIT JagInitData;
+
+ LONG HorDisplayTime;
+ LONG HorResolutionDiv;
+ LONG RequestedClockPeriod;
+ LONG CurrentClockError;
+ LONG MinErrorValue;
+ USHORT MinErrorIndex;
+ LONG ShiftClockPeriod;
+
+ USHORT BoardTypeBt485;
+
+
+
+ //
+ // Determine if this is a Bt484 or Bt485 board. To do this write a 1 to command
+ // register bit 07 then write 01 to the address register 0. This will enable
+ // read/writes to command register 3 on a Bt485 but not on a Bt484. Clear
+ // Command register 3 then read it back. On a Bt485 the return value will be 0x00,
+ // on a Bt484 it will be 0x40.
+ //
+ // Get the value in command register 0, then set bit 07
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Command0.Byte);
+ DataChar |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,DataChar);
+
+ //
+ // Write 0x01 to the address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Clear command register 3
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,0x00);
+
+ //
+ // Read Command Register 3 back and compare
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Status.Byte);
+
+ if (DataChar != 0x00) {
+
+ //
+ // This is a Bt484
+ //
+
+ BoardTypeBt485 = 0;
+ JagInitData.Bt485Multiply = 0;
+
+ } else {
+
+ //
+ // This is a Bt485
+ //
+
+ BoardTypeBt485 = 1;
+ JagInitData.Bt485Multiply = 0;
+ }
+
+ //
+ // Calculate the requested clock frequency then find the closest match in the
+ // ICS clock frequency table. The requested clock frequency in picoseconds =
+ //
+ // Horizontal display time * 1000000
+ // ---------------------------------
+ // horizontal resolution
+ //
+ //
+
+ HorDisplayTime = HalpMonitorConfigurationData.HorizontalDisplayTime * 1000;
+ HorResolutionDiv = HalpMonitorConfigurationData.HorizontalResolution;
+ RequestedClockPeriod = HorDisplayTime / HorResolutionDiv;
+
+ //
+ // Check for a Bt485 frequency
+ //
+
+ if ((BoardTypeBt485 == 1) && (RequestedClockPeriod < ClockResList[30])) {
+ RequestedClockPeriod = RequestedClockPeriod * 2;
+ JagInitData.Bt485Multiply = 1;
+ }
+
+ MinErrorIndex = 0;
+
+ //
+ // Gaurentee a maximum starting error
+ //
+
+ MinErrorValue = RequestedClockPeriod + 1;
+ for (Index = 0; Index < 32; Index++) {
+
+ //
+ // Calculate the absolute value of clock error and find the
+ // closest match in the array of clock values
+ //
+
+ CurrentClockError = RequestedClockPeriod - ClockResList[Index];
+ if (CurrentClockError < 0) {
+ CurrentClockError *= -1;
+ }
+
+ if (CurrentClockError < MinErrorValue) {
+ MinErrorValue = CurrentClockError;
+ MinErrorIndex = (USHORT)Index;
+ }
+ }
+
+ //
+ // We now have a closest match in the clock array, now calculate the
+ // values for the Bt484/Bt485 register values
+ //
+
+ JagInitData.ClockFreq = (UCHAR)MinErrorIndex;
+ JagInitData.BitBltControl = 1;
+ JagInitData.TopOfScreen = 0;
+ JagInitData.XferLength = 0x200;
+ JagInitData.VerticalInterruptLine = 4;
+ JagInitData.HorizontalDisplay = HalpMonitorConfigurationData.HorizontalResolution;
+
+ //
+ // All jaguar timing values are based on the brooktree shift clock value which
+ // is the clock frequency divided by 4. (period * 4) If this is a Bt485 using
+ // its internal 2x clock multiplier than is is period * 2; (freq * 2 / 4)
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 2;
+ } else {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 4;
+ }
+
+ JagInitData.HorizontalBlank = (USHORT)(((HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod);
+
+ JagInitData.HorizontalBeginSync = (USHORT)((HalpMonitorConfigurationData.HorizontalFrontPorch * 1000)
+ / ShiftClockPeriod);
+
+ JagInitData.HorizontalEndSync = (USHORT)(((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod);
+
+ JagInitData.HorizontalLine = JagInitData.HorizontalBlank +
+ (HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ JagInitData.VerticalBlank = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalBeginSync = HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalEndSync = HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalSync;
+
+ JagInitData.VerticalLine = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalResolution;
+
+ //
+ // Start ICS Clock pll and stabilize.
+ //
+
+ WRITE_REGISTER_UCHAR(CLOCK_BASE,JagInitData.ClockFreq);
+
+ //
+ // Wait 10 uS for PLL clock to stabilize on the video board
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+
+ //
+ // Initialize Bt484 Command Register 0 to:
+ //
+ // 8 Bit DAC Resolution
+ //
+
+ CmdReg0 = 0;
+ ((PBT484_COMMAND0)(&CmdReg0))->DacResolution = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->GreenSyncEnable = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->SetupEnable = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Initialize Command Register 1 to:
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND1)(&DataChar))->BitsPerPixel = VXL_EIGHT_BITS_PER_PIXEL;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command1.Byte,DataChar);
+
+ //
+ // Initialize Command Register 2 to:
+ //
+ // SCLK Enabled
+ // TestMode disabled
+ // PortselMask Non Masked
+ // PCLK 1
+ // NonInterlaced
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND2)(&DataChar))->SclkDisable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->TestEnable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PortselMask = 1;
+ ((PBT484_COMMAND2)(&DataChar))->PclkSelect = 1;
+ ((PBT484_COMMAND2)(&DataChar))->InterlacedDisplay = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PaletteIndexing = CONTIGUOUS_PALETTE;
+ ((PBT484_COMMAND2)(&DataChar))->CursorMode = BT_CURSOR_WINDOWS;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command2.Byte,DataChar);
+
+ //
+ // if JagInitData.ClockFreq bit 8 is set then this is a Bt485 mode that requires
+ // the internal 2x clock multiplier to be enabled.
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+
+ //
+ // To access cmd register 3, first set bit CR17 in command register 0
+ //
+
+ CmdReg0 |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Write a 0x01 to Address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Write to cmd register 3 in the status register location. Cmd3 is initialized
+ // to turn on the 2x clock multiplier.
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND3)(&DataChar))->ClockMultiplier = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,DataChar);
+
+ //
+ // Allow 10 uS for the 2x multiplier to stabilize
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+ }
+
+ //
+ // Initialize Color Palette. Only init the first 2 entries
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+
+ //
+ // Entry 0 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 1 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x90);
+
+ //
+ // Initialize Cursor and Overscan color.
+ //
+ // Set address pointer base.
+ // Zero 4 entries.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColorWrAddress.Byte,0);
+ for (Index = 0; Index < 4*3; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColor.Byte,0);
+ }
+
+ //
+ // Initialize cursor RAM
+ //
+ // Set address pointer to base of ram.
+ // Clear both planes
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+ for (Index = 0; Index < 256; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorRam.Byte,0);
+ }
+
+ //
+ // Initialize cursor position registers--cursor off.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXHigh.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYHigh.Byte,0);
+
+ //
+ // Initialize pixel mask.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PixelMask.Byte,0xFF);
+
+ //
+ // Init Jaguar Registers
+ //
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->TopOfScreen.Short,
+ JagInitData.TopOfScreen);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBlank.Short,
+ JagInitData.HorizontalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBeginSync.Short,
+ JagInitData.HorizontalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalEndSync.Short,
+ JagInitData.HorizontalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalLine.Short,
+ JagInitData.HorizontalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBlank.Short,
+ JagInitData.VerticalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBeginSync.Short,
+ JagInitData.VerticalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalEndSync.Short,
+ JagInitData.VerticalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalLine.Short,
+ JagInitData.VerticalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->XferLength.Short,
+ JagInitData.XferLength);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalInterruptLine.Short,
+ JagInitData.VerticalInterruptLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalDisplay.Short,
+ JagInitData.HorizontalDisplay);
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->BitBltControl.Byte,
+ JagInitData.BitBltControl);
+
+ //
+ // Enable timing.
+ //
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->MonitorControl,MONITOR_TIMING_ENABLE);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VXL_VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte;
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_DUO_)
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ HalpResetX86DisplayAdapter();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+#if defined(_DUO_)
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ RtlMoveMemory((PVOID)VIDEO_MEMORY_BASE,
+ (PVOID)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination++ = (UCHAR)((FontValue >> 31) ^ 1);
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxdmadsp.s b/private/ntos/nthals/halfxs/mips/jxdmadsp.s
new file mode 100644
index 000000000..b057fdf95
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxdmadsp.s
@@ -0,0 +1,78 @@
+// TITLE("Jazz I/O Interrupt Dispatch")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// jxdmadsp.s
+//
+// Abstract:
+//
+// This module implements the code necessary to do the second level dispatch
+// for I/O interrupts on Jazz.
+//
+// Author:
+//
+// David N. Cutler (davec) 12-May-1990
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdef.h"
+
+#endif
+
+ SBTTL("Local Device First Level Dispatch")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt being generated
+// for a local device.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpDmaDispatch)
+
+#if defined(_DUO_)
+
+ lbu t0,DMA_VIRTUAL_BASE + 0x48 // get interrupt source vector
+
+#endif
+
+#if defined(_JAZZ_)
+
+ lbu t0,INTERRUPT_VIRTUAL_BASE + 0x0 // get interrupt source vector
+
+#endif
+
+ lw a0,KiPcr + PcInterruptRoutine + (DEVICE_VECTORS * 4)(t0) //
+ lw t1,InDispatchAddress - InDispatchCode(a0) // get dispatch address
+ subu a0,a0,InDispatchCode // compute address of interrupt object
+ j t1 // transfer control to interrupt routine
+
+ .end HalpDmaDispatch
diff --git a/private/ntos/nthals/halfxs/mips/jxebsup.c b/private/ntos/nthals/halfxs/mips/jxebsup.c
new file mode 100644
index 000000000..2f8149510
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxebsup.c
@@ -0,0 +1,1287 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+//
+// Define EISA bus interrupt affinity.
+//
+
+KAFFINITY HalpEisaBusAffinity;
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ KIRQL oldIrql;
+
+#if !defined(_DUO_)
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#else
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#endif
+
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] =
+ (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Set EISA bus interrupt affinity.
+ //
+
+ HalpEisaBusAffinity = PCR->SetMember;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+#if defined(_DUO_)
+
+ //
+ // Enable the EISA interrupts to the CPU.
+ //
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_EISA_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+
+#endif
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+#if defined(_DUO_)
+
+ PUSHORT Acknowledge = (PUSHORT)&DMA_CONTROL->EisaInterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_USHORT(Acknowledge);
+
+#else
+
+ PUCHAR Acknowledge = (PUCHAR)&DMA_CONTROL->InterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(Acknowledge);
+
+#endif
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+ if (interruptVector != 0x8000) {
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+ } else {
+ returnValue = HalHandleNMI(NULL, NULL);
+ }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT(Offset >= 0x100000);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxenvirv.c b/private/ntos/nthals/halfxs/mips/jxenvirv.c
new file mode 100644
index 000000000..a7b53a60e
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxenvirv.c
@@ -0,0 +1,664 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "jazznvr.h"
+#include "string.h"
+
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+KIRQL
+HalpMapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into a wired TB entry.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO NvramPte[2];
+
+ //
+ // Construct a pair of PTE's to map NVRAM.
+ //
+
+ NvramPte[0].X1 = 0;
+ NvramPte[0].PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
+ NvramPte[0].G = 0;
+ NvramPte[0].V = 1;
+ NvramPte[0].D = 1;
+ NvramPte[0].C = UNCACHED_POLICY;
+ NvramPte[1] = NvramPte[0];
+ NvramPte[1].PFN += 1;
+
+ //
+ // Raise IRQL to the highest level, allocate a TB entry, map NVRAM
+ // using the alocated entry, and return the previous IRQL.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0],
+ (PVOID)NVRAM_VIRTUAL_BASE,
+ HalpAllocateTbEntry());
+
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from a wired entry in
+ the TB.
+
+Arguments:
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the wired TB entry that was allocated to map NVRAM and lower
+ // IRQL to its previous level.
+ //
+
+ HalpFreeTbEntry();
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram();
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(OldIrql);
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram();
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(OldIrql);
+ return Status;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxhalp.h b/private/ntos/nthals/halfxs/mips/jxhalp.h
new file mode 100644
index 000000000..fffc5a760
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxhalp.h
@@ -0,0 +1,106 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halfxs/mips/jxhwsup.c b/private/ntos/nthals/halfxs/mips/jxhwsup.c
new file mode 100644
index 000000000..c53367cf7
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxhwsup.c
@@ -0,0 +1,2927 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCreateDmaStructures)
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpDmaChannelInterrupt;
+
+UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. ";
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+//
+// The following function is called when a DMA channel interrupt occurs.
+//
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[8];
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG Hint;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+
+ if (virtualAddress == NULL) {
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ Hint,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = Hint;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+ return;
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: Internal, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) {
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+ }
+
+ if (DeviceDescription->InterfaceType == Internal) {
+
+
+ //
+ // Return the adapter pointer for internal adapters.
+ //
+ // If this is a master controler such as the SONIC then return the
+ // last channel.
+ //
+
+ if (DeviceDescription->Master) {
+
+ //
+ // Create an adapter if necessary.
+ //
+
+ if (HalpInternalAdapters[7] == NULL) {
+
+ HalpInternalAdapters[7] = HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[7],
+ NULL
+ );
+
+ }
+
+ return(HalpInternalAdapters[7]);
+
+ }
+
+ //
+ // Make sure the DMA channel range is valid. Only use channels 0-6.
+ //
+
+ if (DeviceDescription->DmaChannel > 6) {
+
+ return(NULL);
+ }
+
+ //
+ // If necessary allocate an adapter; otherwise,
+ // just return the adapter for the requested channel.
+ //
+
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel] == NULL) {
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel] =
+ HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[DeviceDescription->DmaChannel],
+ NULL
+ );
+
+ }
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+ return(HalpInternalAdapters[DeviceDescription->DmaChannel]);
+ }
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != Eisa) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ return(TRUE);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // There is only one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+
+#if !defined(_DUO_)
+
+ if (DMA_CONTROL->RevisionLevel.Long < 2) {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ } else {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+ }
+#else
+
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+#endif
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+ ULONG Mode;
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter( 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if (AdapterBaseVa == NULL) {
+
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+ AdapterObject->PagePort = NULL;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+ ULONG MapRegisterSize;
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG1_BASE);
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationBase.Long,
+ HalpMapRegisterPhysicalBase
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationLimit.Long,
+ MapRegisterSize
+ );
+
+ //
+ // Initialize the DMA mode registers for the Floppy, SCSI and Sound.
+ // The initialization values come fomr the System Specification.
+ //
+
+#if defined(_JAZZ_)
+
+ Mode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_120NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_8BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[FLOPPY_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_A].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_B].Mode.Long,
+ (ULONG) Mode
+ );
+
+#endif
+
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ return AdapterObject;
+
+ return (PADAPTER_OBJECT) NULL;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ ULONG Hint;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize the DMA interrupt dispatcher for I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpDmaChannelInterrupt,
+ HalpDmaChannel,
+ (PVOID) NULL,
+ (PKSPIN_LOCK) NULL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpDmaChannelInterrupt );
+
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ PCR->InterruptRoutine[DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpDmaDispatch;
+ return TRUE;
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+
+ //
+ // Set the offset to point to the map register plus the offset.
+ //
+
+ Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+
+ //
+ // Invalidate the translation entry.
+ //
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long, 1);
+
+ if ( AdapterObject == NULL) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+
+ if (AdapterObject->PagePort == NULL) {
+
+ //
+ // Set the local DMA Registers.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Address.Long, Offset);
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long, *Length);
+
+ i = 0;
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 1;
+ ((PDMA_CHANNEL_ENABLE) &i)->TransferDirection =
+ WriteToDevice ? DMA_WRITE_OP : DMA_READ_OP;
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, i);
+
+
+ } else {
+
+ //
+ // Start the EISA DMA controller.
+ //
+
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+
+ ULONG i;
+ UCHAR DataByte;
+
+ if (AdapterObject == NULL) {
+
+ //
+ // This is a master adadapter so there is nothing to do.
+ //
+
+ return(TRUE);
+ }
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else {
+
+ //
+ // Clear on board DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ i = READ_REGISTER_USHORT(
+ &((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable
+ );
+ }
+
+ return(TRUE);
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ } else {
+
+ //
+ // Disable the DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ saveEnable = i;
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ //
+ // Read the transfer count.
+ //
+
+ count = READ_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long);
+
+ //
+ // Reset the Enable register.
+ //
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ saveEnable
+ );
+
+ }
+
+ return(count);
+}
+
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a DMA channel interrupt occurs.
+ These should never occur. Bugcheck is called if an error does occur.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+
+ ULONG DataWord;
+ ULONG Channel;
+ DMA_CHANNEL_ENABLE ChannelWord;
+
+#if defined(_JAZZ_)
+
+ //
+ // Read the DMA channel interrupt source register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long);
+
+ for (Channel = 0; Channel < 8; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << Channel))) {
+ continue;
+ }
+
+ DmaChannelMsg[18] = (CHAR) Channel + '0';
+
+ HalDisplayString(DmaChannelMsg);
+
+ *((PULONG) &ChannelWord) =
+ READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long);
+
+ if (ChannelWord.TerminalCount) {
+ HalDisplayString("Terminal count was reached.\n");
+ }
+
+ if (ChannelWord.MemoryError) {
+ HalDisplayString("A memory error was detected.\n");
+ }
+
+ if (ChannelWord.TranslationError) {
+ HalDisplayString("A translation error occured.\n");
+ }
+
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+#endif
+
+ return(TRUE);
+}
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ HalpMapRegisterPhysicalBase = PhysicalAddress;
+
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxmapio.c b/private/ntos/nthals/halfxs/mips/jxmapio.c
new file mode 100644
index 000000000..d61662620
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxmapio.c
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase;
+PVOID HalpRealTimeClockBase;
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.LowPart = RTCLOCK_PHYSICAL_BASE;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase == NULL) ||
+ (HalpRealTimeClockBase == NULL)) {
+ return FALSE;
+
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxmaptb.c b/private/ntos/nthals/halfxs/mips/jxmaptb.c
new file mode 100644
index 000000000..2b972a02d
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxmaptb.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmaptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for a MIPS R3000
+ or R4000 Jazz system. It also sets the instruction and data cache line
+ sizes for a MIPS R3000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapFixedTbEntries)
+
+#endif
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine loads the fixed TB entries that map the DMA control and
+ interrupt sources registers for a MIPS R3000 or R4000 Jazz system. It
+ also sets the instruction and data cache line sizes for a MIPS R3000
+ Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ ENTRYLO Pte[2];
+
+ //
+ // Map the DMA control and interrupt source register by loading fixed
+ // TB entry(s).
+ //
+
+ Pte[0].PFN = DMA_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+#if defined(R3000)
+
+ Pte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte[0].C = UNCACHED_POLICY;
+
+#endif
+
+ Pte[1].PFN = INTERRUPT_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[1].G = 1;
+ Pte[1].V = 1;
+ Pte[1].D = 1;
+
+#if defined(R3000)
+
+ Pte[1].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte[1].C = UNCACHED_POLICY;
+
+#endif
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+#if defined(R3000)
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[1],
+ (PVOID)INTERRUPT_VIRTUAL_BASE,
+ INTERRUPT_ENTRY);
+
+#endif
+
+ //
+ // Set the instruction and data cache line sizes.
+ //
+
+#if defined(R3000)
+
+ PCR->DcacheFillSize = 0x10;
+ PCR->DcacheAlignment = 0x10 - 1;
+ PCR->FirstLevelDcacheFillSize = 0x10;
+ PCR->FirstLevelIcacheFillSize = 0x20;
+
+#endif
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxport.c b/private/ntos/nthals/halfxs/mips/jxport.c
new file mode 100644
index 000000000..16c94aef1
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxport.c
@@ -0,0 +1,879 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)(SP_VIRTUAL_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SP_VIRTUAL_BASE))
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 0;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = SP_PHYSICAL_BASE >> PAGE_SHIFT;
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry and set the noncached bit in the PTE that will
+ // map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+ HalpPte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+#endif
+
+ KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG KdPortEntry;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+
+#endif
+
+ //
+ // Map the serial controller through a allocated TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxreturn.c b/private/ntos/nthals/halfxs/mips/jxreturn.c
new file mode 100644
index 000000000..5222e9994
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxreturn.c
@@ -0,0 +1,169 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+--*/
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO Pte[2];
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE;
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ //
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Map the keyboard controller
+ //
+
+ Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map keyboard controller using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreData(0);
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxsysint.c b/private/ntos/nthals/halfxs/mips/jxsysint.c
new file mode 100644
index 000000000..76194a5c5
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxsysint.c
@@ -0,0 +1,304 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // enable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector.
+ The system interrupt vector and IRQL are suitable for use in a
+ subsequent call to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ *Affinity = 1;
+ *Irql = (KIRQL)BusInterruptLevel;
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+
+ }
+
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // Set the EISA interrupt affinity.
+ //
+
+ *Affinity = HalpEisaBusAffinity;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+#if defined(_DUO_)
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long,
+ Mask);
+
+#endif
+
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxtime.c b/private/ntos/nthals/halfxs/mips/jxtime.c
new file mode 100644
index 000000000..34ee1a150
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxtime.c
@@ -0,0 +1,289 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ Register |= 0x80;
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ Register |= 0x80;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/jxusage.c b/private/ntos/nthals/halfxs/mips/jxusage.c
new file mode 100644
index 000000000..0c1d01efc
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/jxusage.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/x4clock.s b/private/ntos/nthals/halfxs/mips/x4clock.s
new file mode 100644
index 000000000..570f4a0a8
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/x4clock.s
@@ -0,0 +1,354 @@
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdef.h"
+
+#endif
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+
+#endif
+
+#if defined(_JAZZ_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
+
+#endif
+
+ .set reorder
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// The following code is a work around for a bug in the Fusion machines
+// where the clock interrupt is not dismissed by reading the acknowledge
+// register.
+//
+
+#if defined(_JAZZ_)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,cause // read the cause register
+ lw t1,HalpEisaControlBase // get EISA control base address
+ sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit
+ bgez t0,10f // if gez, no clock interrupt pending
+ li t2,0x2 // get NMI port enable bit
+ lb t3,0x70(t1) // save EISA NMI interrupt disable
+ lb t4,0x461(t1) // save EISA extended NMI status
+ sb zero,0x70(t1) // clear EISA NMI interrupt disable
+ sb t2,0x461(t1) // set EISA NMI port enable
+ sb zero,0x462(t1) // generate EISA NMI interrupt
+ sb zero,0x461(t1) // clear EISA extended NMI status
+ sb t2,0x461(t1) //
+ lb zero,0x461(t1) // synchronize clear operatin
+ sb t3,0x70(t1) // restore EISA NMI interupt disable
+ sb t4,0x461(t1) // restore EISA exteneed NMI status
+ lb zero,0x461(t1) // synchronize restore operation
+ .set at
+ .set reorder
+
+10: //
+
+#endif
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,30f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+
+ .set noreorder
+
+#if defined(_DUO_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count
+
+#endif
+
+#if defined(_JAZZ_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
+
+#endif
+
+ .set reorder
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1 //
+
+#else
+
+ j ra //
+
+#endif
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+#if defined(NT_UP)
+
+ la t1,HalpPerformanceCounter // get performance counter address
+
+#else
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+#endif
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halfxs/mips/x4tb.s b/private/ntos/nthals/halfxs/mips/x4tb.s
new file mode 100644
index 000000000..a997f57d9
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/x4tb.s
@@ -0,0 +1,115 @@
+#if defined(R4000)
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Author:
+//
+// David N. Cutler (davec) 29-Dec-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halfxs/mips/x86bios.c b/private/ntos/nthals/halfxs/mips/x86bios.c
new file mode 100644
index 000000000..0e53cb7e0
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/x86bios.c
@@ -0,0 +1,239 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (HalpEisaControlBase == NULL || HalpEisaMemoryBase == NULL) {
+ return;
+ }
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios((ULONG)HalpEisaControlBase, (ULONG)HalpEisaMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+#endif
+
+ return;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+#endif
+
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/xxcalstl.c b/private/ntos/nthals/halfxs/mips/xxcalstl.c
new file mode 100644
index 000000000..1d586ec3c
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/xxcalstl.c
@@ -0,0 +1,296 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt0;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the interval timer interrupt.
+ //
+
+#if defined(_DUO_)
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->TimerInterruptAcknowledge.Long);
+
+#else
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+
+#endif
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/xxclock.c b/private/ntos/nthals/halfxs/mips/xxclock.c
new file mode 100644
index 000000000..118b7ca19
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/xxclock.c
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ NextIntervalCount = DesiredIncrement / MINIMUM_INCREMENT;
+ NewTimeIncrement = NextIntervalCount * MINIMUM_INCREMENT;
+ HalpNextIntervalCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halfxs/mips/xxidle.s b/private/ntos/nthals/halfxs/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halfxs/mips/xxinithl.c b/private/ntos/nthals/halfxs/mips/xxinithl.c
new file mode 100644
index 000000000..78dc7c909
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/xxinithl.c
@@ -0,0 +1,547 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Define bug check information buffer and callback record.
+//
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG FailedAddress;
+ ULONG DiagnosticLow;
+ ULONG DiagnosticHigh;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ ULONG FailedAddress;
+ PKPRCB Prcb;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ PCR->DataBusError = HalpBusError;
+ PCR->InstructionBusError = HalpBusError;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_DUO_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#endif
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+ }
+
+ //
+ // Clear memory address error registers.
+ //
+
+#if defined(_DUO_)
+
+ FailedAddress = ((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+ FailedAddress = ((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+
+ //
+ // Initialize interrupts
+ //
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ HalpMapIoSpace();
+ HalpCalibrateStall();
+ HalpCreateDmaStructures();
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+ HalpInitializeX86DisplayAdapter();
+ return TRUE;
+ }
+ }
+}
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+#if defined(_DUO_)
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+ return;
+}
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG DiagnosticHigh;
+ ULONG DiagnosticLow;
+ ULONG FailedAddress;
+
+ //
+ // Bug check specifying the exception code, the virtual address, the
+ // failed memory address, and either the ECC diagnostic registers or
+ // the parity diagnostic registers depending on the platform.
+ //
+
+#if defined(_DUO_)
+
+ DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+ DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+ DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ FailedAddress,
+ DiagnosticLow,
+ DiagnosticHigh);
+
+ return FALSE;
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+#if defined(_DUO_)
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+#endif
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halfxs/mips/xxinitnt.c b/private/ntos/nthals/halfxs/mips/xxinitnt.c
new file mode 100644
index 000000000..dcaa2f814
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/xxinitnt.c
@@ -0,0 +1,295 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpCountInterrupt (
+ VOID
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+#pragma alloc_text(INIT, HalpCountInterrupt)
+
+#endif
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the count/compare interrupt service routine
+ early in the system initialization. Its only function is to field
+ and acknowledge count/compare interrupts during the system boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Jazz or Duo MIPS system.
+
+ N.B. This function is only called during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ USHORT DataShort;
+ ULONG DataLong;
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Clear interprocessor, timer, EISA, local device, and DMA interrupt
+ // enables.
+ //
+
+#if defined(_DUO_)
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ 0);
+
+#endif
+
+ //
+ // If processor 0 is being initialized, then clear all builtin device
+ // interrupt enables.
+ //
+
+ if (Prcb->Number == 0) {
+ HalpBuiltinInterruptEnable = 0;
+ }
+
+ //
+ // Disable individual device interrupts and make sure no device interrupts
+ // are pending.
+ //
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ 0);
+
+#if defined(_DUO_)
+
+ do {
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->LocalInterruptAcknowledge.Long) & 0x3ff;
+ } while (DataLong != 0);
+
+ //
+ // If processor 0 is being initialized, then enable device interrupts.
+ //
+
+ if (Prcb->Number == 0) {
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_DEVICE_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+ }
+
+#endif
+
+#if defined(_JAZZ_)
+
+ do {
+ DataShort = READ_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Source) & 0x3ff;
+ } while (DataShort != 0);
+
+#endif
+
+ //
+ // If processor 0 is being initialized, then connect the interval timer
+ // interrupt to the stall interrupt routine so the stall execution count
+ // can be computed during phase 1 initialization. Otherwise, connect the
+ // interval timer interrupt to the appropriate interrupt service routine
+ // and set stall execution count from the computation made on processor
+ // 0.
+ //
+
+ if (Prcb->Number == 0) {
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ } else {
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt1;
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+ }
+
+ //
+ // Initialize the interval timer to interrupt at the specified interval.
+ //
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptInterval.Long, CLOCK_INTERVAL);
+
+ //
+ // Enable the interval timer interrupt on the current processor.
+ //
+
+#if defined(_DUO_)
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_TIMER_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+
+#endif
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\comapre interrupt to the appropriate interrupt service routine.
+ //
+
+ if (Prcb->Number == 0) {
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ } else {
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+ }
+
+ //
+ // Connect the interprocessor interrupt service routine and enable
+ // interprocessor interrupts.
+ //
+
+#if defined(_DUO_)
+
+ PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt;
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_IP_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+
+#endif
+
+ //
+ // Reserve the local device interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= ((1 << DEVICE_LEVEL) | (1 << EISA_DEVICE_LEVEL));
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halfxs/mips/xxipiint.s b/private/ntos/nthals/halfxs/mips/xxipiint.s
new file mode 100644
index 000000000..8b6303be1
--- /dev/null
+++ b/private/ntos/nthals/halfxs/mips/xxipiint.s
@@ -0,0 +1,65 @@
+// TITLE("Interprocessor Interrupts")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// xxipiint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a MIPS R4000 Duo system.
+//
+// Author:
+//
+// David N. Cutler (davec) 29-May-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt.
+// Its function is to acknowledge the interrupt and transfer control to
+// the standard system routine to process interprocessor requrests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#if defined(_DUO_)
+
+ LEAF_ENTRY(HalpIpiInterrupt)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x60 // acknowledge IP interrupt
+ lw t1,__imp_KeIpiInterrupt // process interprocessor requests
+ j t1 //
+
+ .end HalpIpIInterrupt
+
+#endif
diff --git a/private/ntos/nthals/halfxs/sources b/private/ntos/nthals/halfxs/sources
new file mode 100644
index 000000000..de52dcf6f
--- /dev/null
+++ b/private/ntos/nthals/halfxs/sources
@@ -0,0 +1,91 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halfxs
+TARGETPATH=\nt\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_JAZZ_
+
+INCLUDES=..\x86new;..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib \
+ $(TARGETPATH)\mips\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halfxspc/drivesup.c b/private/ntos/nthals/halfxspc/drivesup.c
new file mode 100644
index 000000000..8247c7928
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/drivesup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halfxspc/hal.rc b/private/ntos/nthals/halfxspc/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halfxspc/hal.src b/private/ntos/nthals/halfxspc/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halfxspc/makefile b/private/ntos/nthals/halfxspc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halfxspc/makefile.inc b/private/ntos/nthals/halfxspc/makefile.inc
new file mode 100644
index 000000000..3a9067fdb
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/makefile.inc
@@ -0,0 +1,57 @@
+mips\allstart.c: ..\halfxs\mips\allstart.c
+
+mips\cacherr.s: ..\halfxs\mips\cacherr.s
+
+mips\jxbeep.c: ..\halfxs\mips\jxbeep.c
+
+mips\jxdmadsp.s: ..\halfxs\mips\jxdmadsp.s
+
+mips\jxenvirv.c: ..\halfxs\mips\jxenvirv.c
+
+mips\j4flshbf.s: ..\halfxs\mips\j4flshbf.s
+
+mips\j4flshio.c: ..\halfxs\mips\j4flshio.c
+
+mips\jxdisp.c: ..\halfxs\mips\jxdisp.c
+
+mips\jxebsup.c: ..\halfxs\mips\jxebsup.c
+
+mips\jxhwsup.c: ..\halfxs\mips\jxhwsup.c
+
+mips\jxmapio.c: ..\halfxs\mips\jxmapio.c
+
+mips\jxmaptb.c: ..\halfxs\mips\jxmaptb.c
+
+mips\jxport.c: ..\halfxs\mips\jxport.c
+
+mips\j4cache.s: ..\halfxs\mips\j4cache.s
+
+mips\j4prof.c: ..\halfxs\mips\j4prof.c
+
+mips\jxreturn.c: ..\halfxs\mips\jxreturn.c
+
+mips\jxsysint.c: ..\halfxs\mips\jxsysint.c
+
+mips\jxtime.c: ..\halfxs\mips\jxtime.c
+
+mips\jxusage.c: ..\halfxs\mips\jxusage.c
+
+mips\x4clock.s: ..\halfxs\mips\x4clock.s
+
+mips\xxcalstl.c: ..\halfxs\mips\xxcalstl.c
+
+mips\xxinitnt.c: ..\halfxs\mips\xxinitnt.c
+
+mips\xxinithl.c: ..\halfxs\mips\xxinithl.c
+
+mips\xxipiint.s: ..\halfxs\mips\xxipiint.s
+
+mips\x4tb.s: ..\halfxs\mips\x4tb.s
+
+mips\x86bios.c: ..\halfxs\mips\x86bios.c
+
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halfxspc.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halfxspc/mips/allstart.c b/private/ntos/nthals/halfxspc/mips/allstart.c
new file mode 100644
index 000000000..26556a5c7
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/allstart.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\allstart.c"
diff --git a/private/ntos/nthals/halfxspc/mips/cacherr.s b/private/ntos/nthals/halfxspc/mips/cacherr.s
new file mode 100644
index 000000000..0b3cdf5ce
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/cacherr.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\cacherr.s"
diff --git a/private/ntos/nthals/halfxspc/mips/halp.h b/private/ntos/nthals/halfxspc/mips/halp.h
new file mode 100644
index 000000000..2f89bf746
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/halp.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\halp.h"
diff --git a/private/ntos/nthals/halfxspc/mips/j4cache.s b/private/ntos/nthals/halfxspc/mips/j4cache.s
new file mode 100644
index 000000000..521782b32
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/j4cache.s
@@ -0,0 +1,13 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#define _MIPS_R4600
+
+#include "..\halfxs\mips\j4cache.s"
diff --git a/private/ntos/nthals/halfxspc/mips/j4flshbf.s b/private/ntos/nthals/halfxspc/mips/j4flshbf.s
new file mode 100644
index 000000000..04012b70b
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/j4flshbf.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshbf.s"
diff --git a/private/ntos/nthals/halfxspc/mips/j4flshio.c b/private/ntos/nthals/halfxspc/mips/j4flshio.c
new file mode 100644
index 000000000..d608140c2
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/j4flshio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshio.c"
diff --git a/private/ntos/nthals/halfxspc/mips/j4prof.c b/private/ntos/nthals/halfxspc/mips/j4prof.c
new file mode 100644
index 000000000..dd8c2b7c9
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/j4prof.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4prof.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxbeep.c b/private/ntos/nthals/halfxspc/mips/jxbeep.c
new file mode 100644
index 000000000..173ea259e
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxbeep.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxbeep.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxdisp.c b/private/ntos/nthals/halfxspc/mips/jxdisp.c
new file mode 100644
index 000000000..9daf3d16e
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxdisp.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdisp.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxdmadsp.s b/private/ntos/nthals/halfxspc/mips/jxdmadsp.s
new file mode 100644
index 000000000..370edd47f
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxdmadsp.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdmadsp.s"
diff --git a/private/ntos/nthals/halfxspc/mips/jxebsup.c b/private/ntos/nthals/halfxspc/mips/jxebsup.c
new file mode 100644
index 000000000..c0f0b6b37
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxebsup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxebsup.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxenvirv.c b/private/ntos/nthals/halfxspc/mips/jxenvirv.c
new file mode 100644
index 000000000..398a656e7
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxenvirv.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxenvirv.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxhalp.h b/private/ntos/nthals/halfxspc/mips/jxhalp.h
new file mode 100644
index 000000000..4e39adf70
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxhalp.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxhalp.h"
diff --git a/private/ntos/nthals/halfxspc/mips/jxhwsup.c b/private/ntos/nthals/halfxspc/mips/jxhwsup.c
new file mode 100644
index 000000000..be474375a
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxhwsup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxhwsup.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxmapio.c b/private/ntos/nthals/halfxspc/mips/jxmapio.c
new file mode 100644
index 000000000..879f96410
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxmapio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmapio.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxmaptb.c b/private/ntos/nthals/halfxspc/mips/jxmaptb.c
new file mode 100644
index 000000000..9262bc775
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxmaptb.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmaptb.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxport.c b/private/ntos/nthals/halfxspc/mips/jxport.c
new file mode 100644
index 000000000..26e310528
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxport.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxport.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxreturn.c b/private/ntos/nthals/halfxspc/mips/jxreturn.c
new file mode 100644
index 000000000..8ff827bf7
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxreturn.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxreturn.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxsysint.c b/private/ntos/nthals/halfxspc/mips/jxsysint.c
new file mode 100644
index 000000000..528753dda
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxsysint.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxsysint.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxtime.c b/private/ntos/nthals/halfxspc/mips/jxtime.c
new file mode 100644
index 000000000..996be9c3c
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxtime.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxtime.c"
diff --git a/private/ntos/nthals/halfxspc/mips/jxusage.c b/private/ntos/nthals/halfxspc/mips/jxusage.c
new file mode 100644
index 000000000..e4d8e2f52
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/jxusage.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxusage.c"
diff --git a/private/ntos/nthals/halfxspc/mips/x4clock.s b/private/ntos/nthals/halfxspc/mips/x4clock.s
new file mode 100644
index 000000000..ce9c3a190
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/x4clock.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4clock.s"
diff --git a/private/ntos/nthals/halfxspc/mips/x4tb.s b/private/ntos/nthals/halfxspc/mips/x4tb.s
new file mode 100644
index 000000000..be37d6677
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/x4tb.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4tb.s"
diff --git a/private/ntos/nthals/halfxspc/mips/x86bios.c b/private/ntos/nthals/halfxspc/mips/x86bios.c
new file mode 100644
index 000000000..89aea8d14
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/x86bios.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x86bios.c"
diff --git a/private/ntos/nthals/halfxspc/mips/xxcalstl.c b/private/ntos/nthals/halfxspc/mips/xxcalstl.c
new file mode 100644
index 000000000..eabb7db1d
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/xxcalstl.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxcalstl.c"
diff --git a/private/ntos/nthals/halfxspc/mips/xxclock.c b/private/ntos/nthals/halfxspc/mips/xxclock.c
new file mode 100644
index 000000000..c7ec77df5
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/xxclock.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxclock.c"
diff --git a/private/ntos/nthals/halfxspc/mips/xxidle.s b/private/ntos/nthals/halfxspc/mips/xxidle.s
new file mode 100644
index 000000000..faf3163a9
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/xxidle.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxidle.s"
diff --git a/private/ntos/nthals/halfxspc/mips/xxinithl.c b/private/ntos/nthals/halfxspc/mips/xxinithl.c
new file mode 100644
index 000000000..3a49aaf9c
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/xxinithl.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinithl.c"
diff --git a/private/ntos/nthals/halfxspc/mips/xxinitnt.c b/private/ntos/nthals/halfxspc/mips/xxinitnt.c
new file mode 100644
index 000000000..2b57adb0d
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/xxinitnt.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinitnt.c"
diff --git a/private/ntos/nthals/halfxspc/mips/xxipiint.s b/private/ntos/nthals/halfxspc/mips/xxipiint.s
new file mode 100644
index 000000000..266246f51
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/mips/xxipiint.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxipiint.s"
diff --git a/private/ntos/nthals/halfxspc/sources b/private/ntos/nthals/halfxspc/sources
new file mode 100644
index 000000000..4f7878e7d
--- /dev/null
+++ b/private/ntos/nthals/halfxspc/sources
@@ -0,0 +1,92 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halfxspc
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=$(C_DEFINES) -D_JAZZ_
+
+INCLUDES=..\x86new;..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILE0=$(SOURCES)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halgamma/alpha/addrsup.c b/private/ntos/nthals/halgamma/alpha/addrsup.c
new file mode 100644
index 000000000..1b7d444d7
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/addrsup.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the sable HAL directory
+//
+
+#include "..\halsable\alpha\addrsup.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/adjust.c b/private/ntos/nthals/halgamma/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/allstart.c b/private/ntos/nthals/halgamma/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/alphaio.s b/private/ntos/nthals/halgamma/alpha/alphaio.s
new file mode 100644
index 000000000..695e1edbf
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/alphaio.s
@@ -0,0 +1,1368 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alphaio.s
+
+
+Abstract:
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ 12-Jul-1994 - Eric Rehm - Added dense space I/O
+
+ 27-July-1994 - Sameer Dekate
+
+ Make a common file for all machines and optimize Read/Write
+ register buffer routines. Made a common routine with different
+ entry points for READ & WRITE_REGISTER_BUFFER routines
+
+--*/
+
+#include "chipset.h"
+#include "halalpha.h"
+
+// Superpage VA
+//
+// This value is used to define the base physical address from which
+// QVA's are defined.
+//
+// This value is specified as a negative number so that the value will
+// be sign extended when loaded into a register. If defined positive, the
+// assembler will prevent sign extension.
+//
+
+#define GAMMA_IO_SVA -0x3800 // negative of 0xc800
+
+
+ SBTTL( "Read I/O byte" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(READ_PORT_UCHAR)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ mb
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extbl v0, t3, v0 // get correct byte
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_UCHAR
+
+
+ SBTTL( "Read I/O word(16 bits)" )
+//++
+//
+// USHORT
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(READ_PORT_USHORT)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // get the longword
+ extwl v0,t3,v0 // get the correct word
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extwl v0, t3, v0 // get correct word
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_USHORT
+
+
+ SBTTL( "Read I/O longword(32 bits)" )
+//++
+//
+// ULONG
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(READ_PORT_ULONG)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // read the longword
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_ULONG
+
+ SBTTL( "Write I/O byte" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva,
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Writes a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ insbl a1,t3,t4 // put the byte in the correct position
+ stl t4, (t0) // write the byte
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+ insbl a1, t3, t2 // put byte into position
+ bis t1, t2, t1 // merge byte in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write I/O word (16 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva,
+// IN USHORT Value
+// )
+//
+// Routine Description:
+//
+// Writes a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1,t3,t2 // put the word in the correct place
+ stl t2, (t0) // write the word
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, t2 // put word into position
+ bis t1, t2, t1 // merge in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write I/O longword (32 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ stl a1, (a0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_ULONG
+
+
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // t4=ffff ffff ffff c800
+ sll t4, 28, t4 // t4=ffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // t4=ffff ffff ffff c800
+ sll t4, 28, t4 // t4=ffff f800 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, GAMMA_IO_SVA // t4=ffff ffff ffff c800
+ sll t4, 28, t4 // t4=ffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // t4=ffff ffff ffff c800
+ sll t4, 28, t4 // t4=ffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // t4=ffff ffff ffff c800
+ sll t4, 28, t4 // t4=ffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, GAMMA_IO_SVA // t4=ffff ffff ffff c800
+ sll t4, 28, t4 // t4=ffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ addl a1, 4, a1 // increment buffer
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ lda v0, -1(zero) // prestore 0xff in return arg
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ zap a0, 0xf0, a0 // clear <63:32>
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+//
+// Check whether access is to PCI 0 or PCI 1. QVA bits are set for
+// addresses in PCI 0
+//
+
+ ldiq t2, SABLE_PCI0_DENSE_MEMORY_QVA // load qva bits
+ and a0, t2, t2 // bits set in address ??
+
+ ldiq t0, PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE // default to PCI 0 SVA
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // load PCI 1 SVA
+
+ cmoveq t2, t1, t0 // if not PCI 0, use PCI 1 SVA
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store to buffer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
diff --git a/private/ntos/nthals/halgamma/alpha/bios.c b/private/ntos/nthals/halgamma/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/busdata.c b/private/ntos/nthals/halgamma/alpha/busdata.c
new file mode 100644
index 000000000..3d7bbf02c
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/busdata.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the sable HAL directory
+//
+
+#include "..\halsable\alpha\busdata.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/cache.c b/private/ntos/nthals/halgamma/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/chipset.h b/private/ntos/nthals/halgamma/alpha/chipset.h
new file mode 100644
index 000000000..9351c5dc7
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/chipset.h
@@ -0,0 +1 @@
+#include "gamma.h"
diff --git a/private/ntos/nthals/halgamma/alpha/ebsgdma.c b/private/ntos/nthals/halgamma/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/eeprom8k.c b/private/ntos/nthals/halgamma/alpha/eeprom8k.c
new file mode 100644
index 000000000..c03d04c0d
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/eeprom8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eeprom8k.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/eisasup.c b/private/ntos/nthals/halgamma/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/environ.c b/private/ntos/nthals/halgamma/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ev5cache.c b/private/ntos/nthals/halgamma/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ev5int.c b/private/ntos/nthals/halgamma/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ev5ints.s b/private/ntos/nthals/halgamma/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ev5mchk.c b/private/ntos/nthals/halgamma/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ev5mem.s b/private/ntos/nthals/halgamma/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ev5prof.c b/private/ntos/nthals/halgamma/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/fwreturn.c b/private/ntos/nthals/halgamma/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/gamma.h b/private/ntos/nthals/halgamma/alpha/gamma.h
new file mode 100644
index 000000000..ffb3c9d14
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gamma.h
@@ -0,0 +1,553 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ gamma.h
+
+Abstract:
+
+ This file defines the structures and definitions common to all
+ sable-based platforms.
+
+Author:
+
+ Joe Notarangelo 26-Oct-1993
+ Steve Jenness 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 28-Dec 1994 Steve Brooks
+ t2.h and rattler.h extracted from this file.
+
+--*/
+
+#ifndef _GAMMAH_
+#define _GAMMAH_
+
+#include "sableref.h" // Sable reference IO structure
+#include "lynxref.h" // Lynx interrupt structure
+#include "xioref.h" // XIO interrupt structure
+#if !defined(_LANGUAGE_ASSEMBLY)
+#include "errframe.h"
+#endif
+
+
+//
+// Constants used by dense space I/O routines
+//
+
+#define GAMMA_PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc83c0000000
+#define GAMMA_PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc8180000000
+
+#define PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE \
+ (GAMMA_PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE - SABLE_PCI0_DENSE_MEMORY_QVA)
+
+#define PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE \
+ (GAMMA_PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE - SABLE_PCI1_DENSE_MEMORY_QVA)
+
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+#include "rattler.h" // Rattler chipset definitions
+#include "t2.h" // T2 chipset definitions
+#include "icic.h" // ICIC definitions
+
+#define GAMMA_QVA_PHYSICAL_BASE ((ULONGLONG)0x8000000000)
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | \
+ (ULONG)( ((PA)-GAMMA_QVA_PHYSICAL_BASE) >> IO_BIT_SHIFT) ) )
+
+
+//
+// Define physical address spaces for GAMMA.
+//
+// PCI0 - 32bit PCI bus
+// PCI1 - 64bit PCI bus
+//
+
+#define GAMMA_PCI1_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x8180000000)
+#define GAMMA_PCI1_SPARSE_IO_PHYSICAL ((ULONGLONG)0x81C0000000)
+#define GAMMA_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x8200000000)
+#define GAMMA_PCI1_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x8300000000)
+
+#define GAMMA_PCI1_SPARSE_ISA_LEGACY_MEMORY_PHYSICAL ((ULONGLONG)0x8302000000)
+#define GAMMA_PCI1_SPARSE_ISA_LEGACY_IO_PHYSICAL ((ULONGLONG)0x8200000000)
+
+#define GAMMA_CBUS_CSRS_PHYSICAL ((ULONGLONG)0x8380000000)
+#define GAMMA_CPU0_CSRS_PHYSICAL ((ULONGLONG)0x8380000000)
+#define GAMMA_CPU1_CSRS_PHYSICAL ((ULONGLONG)0x8381000000)
+#define GAMMA_CPU2_CSRS_PHYSICAL ((ULONGLONG)0x8382000000)
+#define GAMMA_CPU3_CSRS_PHYSICAL ((ULONGLONG)0x8383000000)
+#define GAMMA_CPU0_SICR_PHYSICAL ((ULONGLONG)0x8380000320)
+#define GAMMA_CPU1_SICR_PHYSICAL ((ULONGLONG)0x8381000320)
+#define GAMMA_CPU2_SICR_PHYSICAL ((ULONGLONG)0x8382000320)
+#define GAMMA_CPU3_SICR_PHYSICAL ((ULONGLONG)0x8383000320)
+#define GAMMA_MEM0_CSRS_PHYSICAL ((ULONGLONG)0x8388000000)
+#define GAMMA_MEM1_CSRS_PHYSICAL ((ULONGLONG)0x8389000000)
+#define GAMMA_MEM2_CSRS_PHYSICAL ((ULONGLONG)0x838A000000)
+#define GAMMA_MEM3_CSRS_PHYSICAL ((ULONGLONG)0x838B000000)
+#define GAMMA_T2_CSRS_PHYSICAL ((ULONGLONG)0x838E000000)
+#define GAMMA_T4_CSRS_PHYSICAL ((ULONGLONG)0x838F000000)
+
+#define T2_CSRS_QVA (HAL_MAKE_QVA(GAMMA_T2_CSRS_PHYSICAL))
+#define T4_CSRS_QVA (HAL_MAKE_QVA(GAMMA_T4_CSRS_PHYSICAL))
+
+
+#define GAMMA_PCI0_CONFIGURATION_PHYSICAL ((ULONGLONG)0x8390000000)
+#define GAMMA_PCI1_CONFIGURATION_PHYSICAL ((ULONGLONG)0x8398000000)
+#define GAMMA_PCI0_SPARSE_IO_PHYSICAL ((ULONGLONG)0x83A0000000)
+#define GAMMA_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x83C0000000)
+
+//
+// Define the limits of User mode Sparse and dense space:
+// A special hack is applied to these values for Gamma, since these addresses
+// are 40 bits in length, and are therefore beyond the range of QVAs. Bit 36
+// is set in these constants, which will get shifted to bit 31 when a QVA is
+// formed. When the physical address is then generated by the access macros,
+// the high order bits will get set, forcing bit 39 to be set, causing a
+// noncached access to occur
+//
+#define GAMMA_USER_PCI1_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x8980000000)
+#define GAMMA_USER_PCI1_SPARSE_IO_PHYSICAL ((ULONGLONG)0x89c0000000)
+#define GAMMA_USER_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x8A00000000)
+#define GAMMA_USER_PCI0_SPARSE_MEMORY_END_PHYSICAL ((ULONGLONG)0x8b00000000)
+#define GAMMA_USER_PCI1_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x8b00000000)
+#define GAMMA_USER_PCI1_SPARSE_MEMORY_END_PHYSICAL ((ULONGLONG)0x8b80000000)
+#define GAMMA_USER_PCI0_SPARSE_IO_PHYSICAL ((ULONGLONG)0x8ba0000000)
+#define GAMMA_USER_PCI0_SPARSE_IO_END_PHYSICAL ((ULONGLONG)0x8bc0000000)
+#define GAMMA_USER_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x8bc0000000)
+
+#define GAMMA_EDGE_LEVEL_CSRS_PHYSICAL ((ULONGLONG)0x83A00004C0)
+#define GAMMA_INTERRUPT_CSRS_PHYSICAL ((ULONGLONG)0x83A000A640)
+#define XIO_INTERRUPT_CSRS_PHYSICAL ((ULONGLONG)0x81C000A640)
+
+//
+// For compatability, define the SABLE_* constants to refer to the GAMMA_*
+// constants. This allows gamma to share sources from the sable tree.
+//
+
+#define SABLE_PCI1_DENSE_MEMORY_PHYSICAL GAMMA_PCI1_DENSE_MEMORY_PHYSICAL
+#define SABLE_PCI1_SPARSE_IO_PHYSICAL GAMMA_PCI1_SPARSE_IO_PHYSICAL
+#define SABLE_PCI0_SPARSE_MEMORY_PHYSICAL GAMMA_PCI0_SPARSE_MEMORY_PHYSICAL
+#define SABLE_PCI1_SPARSE_MEMORY_PHYSICAL GAMMA_PCI1_SPARSE_MEMORY_PHYSICAL
+
+#define SABLE_USER_PCI1_DENSE_MEMORY_PHYSICAL GAMMA_USER_PCI1_DENSE_MEMORY_PHYSICAL
+#define SABLE_USER_PCI1_SPARSE_IO_PHYSICAL GAMMA_USER_PCI1_SPARSE_IO_PHYSICAL
+#define SABLE_USER_PCI0_SPARSE_MEMORY_PHYSICAL GAMMA_USER_PCI0_SPARSE_MEMORY_PHYSICAL
+#define SABLE_USER_PCI0_SPARSE_MEMORY_END_PHYSICAL GAMMA_USER_PCI0_SPARSE_MEMORY_END_PHYSICAL
+#define SABLE_USER_PCI1_SPARSE_MEMORY_PHYSICAL GAMMA_USER_PCI1_SPARSE_MEMORY_PHYSICAL
+#define SABLE_USER_PCI1_SPARSE_MEMORY_END_PHYSICAL GAMMA_USER_PCI1_SPARSE_MEMORY_END_PHYSICAL
+#define SABLE_USER_PCI0_SPARSE_IO_PHYSICAL GAMMA_USER_PCI0_SPARSE_IO_PHYSICAL
+#define SABLE_USER_PCI0_SPARSE_IO_END_PHYSICAL GAMMA_USER_PCI0_SPARSE_IO_END_PHYSICAL
+#define SABLE_USER_PCI0_DENSE_MEMORY_PHYSICAL GAMMA_USER_PCI0_DENSE_MEMORY_PHYSICAL
+
+#define SABLE_CBUS_CSRS_PHYSICAL GAMMA_CBUS_CSRS_PHYSICAL
+#define SABLE_CPU0_CSRS_PHYSICAL GAMMA_CPU0_CSRS_PHYSICAL
+#define SABLE_CPU1_CSRS_PHYSICAL GAMMA_CPU1_CSRS_PHYSICAL
+#define SABLE_CPU2_CSRS_PHYSICAL GAMMA_CPU2_CSRS_PHYSICAL
+#define SABLE_CPU3_CSRS_PHYSICAL GAMMA_CPU3_CSRS_PHYSICAL
+#define SABLE_CPU0_IPIR_PHYSICAL GAMMA_CPU0_SICR_PHYSICAL
+#define SABLE_CPU1_IPIR_PHYSICAL GAMMA_CPU1_SICR_PHYSICAL
+#define SABLE_CPU2_IPIR_PHYSICAL GAMMA_CPU2_SICR_PHYSICAL
+#define SABLE_CPU3_IPIR_PHYSICAL GAMMA_CPU3_SICR_PHYSICAL
+
+#define SABLE_PCI0_CONFIGURATION_PHYSICAL GAMMA_PCI0_CONFIGURATION_PHYSICAL
+#define SABLE_PCI1_CONFIGURATION_PHYSICAL GAMMA_PCI1_CONFIGURATION_PHYSICAL
+#define SABLE_PCI0_SPARSE_IO_PHYSICAL GAMMA_PCI0_SPARSE_IO_PHYSICAL
+#define SABLE_PCI0_DENSE_MEMORY_PHYSICAL GAMMA_PCI0_DENSE_MEMORY_PHYSICAL
+
+//
+// Define Interrupt Controller CSRs.
+//
+
+#define SABLE_EDGE_LEVEL_CSRS_QVA (HAL_MAKE_QVA(GAMMA_EDGE_LEVEL_CSRS_PHYSICAL))
+#define SABLE_INTERRUPT_CSRS_QVA (HAL_MAKE_QVA(GAMMA_INTERRUPT_CSRS_PHYSICAL))
+
+//
+// Define XIO interrupt controller CSRs.
+//
+
+#define XIO_INTERRUPT_CSRS_QVA (HAL_MAKE_QVA(XIO_INTERRUPT_CSRS_PHYSICAL))
+
+#define SABLE_PCI_CONFIG_BASE_QVA (HAL_MAKE_QVA(GAMMA_PCI0_CONFIGURATION_PHYSICAL))
+
+//
+// Gamma uses the Rattler chipset for the CBUS bridge. Define the Sable
+// CPU CSRS to be Rattler CPU Csrs.
+//
+#define SABLE_CPU_CSRS RATTLER_CPU_CSRS
+#define PSABLE_CPU_CSRS PRATTLER_CPU_CSRS
+
+
+//
+// Define CPU CSRs and masks.
+//
+
+#define SABLE_CPU0_CSRS_QVA (HAL_MAKE_QVA(GAMMA_CPU0_CSRS_PHYSICAL))
+#define SABLE_CPU1_CSRS_QVA (HAL_MAKE_QVA(GAMMA_CPU1_CSRS_PHYSICAL))
+#define SABLE_CPU2_CSRS_QVA (HAL_MAKE_QVA(GAMMA_CPU2_CSRS_PHYSICAL))
+#define SABLE_CPU3_CSRS_QVA (HAL_MAKE_QVA(GAMMA_CPU3_CSRS_PHYSICAL))
+#define GAMMA_MEM0_CSRS_QVA (HAL_MAKE_QVA(GAMMA_MEM0_CSRS_PHYSICAL))
+#define GAMMA_MEM1_CSRS_QVA (HAL_MAKE_QVA(GAMMA_MEM1_CSRS_PHYSICAL))
+#define GAMMA_MEM2_CSRS_QVA (HAL_MAKE_QVA(GAMMA_MEM2_CSRS_PHYSICAL))
+#define GAMMA_MEM3_CSRS_QVA (HAL_MAKE_QVA(GAMMA_MEM3_CSRS_PHYSICAL))
+
+#define GAMMA_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define GAMMA_SECONDARY_PROCESSOR ((ULONG)0x1)
+#define GAMMA_MAXIMUM_PROCESSOR ((ULONG)0x3)
+#define HAL_PRIMARY_PROCESSOR (GAMMA_PRIMARY_PROCESSOR)
+#define HAL_MAXIMUM_PROCESSOR (GAMMA_MAXIMUM_PROCESSOR)
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (275)
+
+enum {
+ NoError,
+ UncorrectableError,
+ CorrectableError
+} ErrorType;
+
+//
+// Define the memory module CSRs (from chapter 10 of the GAMMA CPU spec)
+//
+
+//
+// Error Summary register
+//
+
+typedef struct _GAMMA_ESREG_CSR1 {
+ union {
+ ULONG EVBCorrecectableError0: 3; // 0-2
+ ULONG Resrved1: 1; // 3
+ ULONG EVBFatalError0: 4; // 4-7
+ ULONG DTError0: 2; // 8-9
+ ULONG DTSummary0: 1; // 10
+ ULONG Reserved2: 1; // 11
+ ULONG IBParError0: 1; // 12
+ ULONG IBErrorInfo0: 2; // 13-14
+ ULONG IBSummary0: 1; // 15
+ ULONG CBError0: 8; // 16-23
+ ULONG CBSummary0: 1; // 24
+ ULONG CBCommand0: 1; // 25
+ ULONG Reserved3: 2; // 26-27
+ ULONG EVNoResponse0: 1; // 28
+ ULONG Reserved4: 3; // 29-31
+
+ ULONG EVBCorrecectableError1: 3; // 32-34
+ ULONG Resrved5: 1; // 35
+ ULONG EVBFatalError1: 4; // 36-39
+ ULONG DTError1: 2; // 40-41
+ ULONG DTSummary1: 1; // 42
+ ULONG Reserved6: 1; // 43
+ ULONG IBParError1: 1; // 44
+ ULONG IBErrorInfo1: 2; // 45-46
+ ULONG IBSummary1: 1; // 47
+ ULONG CBError1: 4; // 48-51
+ ULONG Reserved7: 4; // 52-55
+ ULONG CBSummary1: 1; // 56
+ ULONG CBCommand1: 1; // 57
+ ULONG Reserved8: 2; // 58-59
+ ULONG EVNoResponse1: 1; // 60
+ ULONG Reserved9: 3; // 61-63
+ };
+ ULONGLONG all;
+
+} GAMMA_ESREG_CSR1, *PGAMMA_ESREG_CSR1;
+
+typedef struct _GAMMA_EVBCR_CSR2 {
+ union {
+ ULONG EnableAddressCommandBusParityCheck0: 1; // 0
+ ULONG Reserved1: 3; // 1-3
+ ULONG EnableCorrectionErrorInterrupt0: 1; // 4
+ ULONG EnableECCCorrection0: 1; // 5
+ ULONG EnableRattlerECCCheck0: 1; // 6
+ ULONG Reserved2: 20; // 7-26
+ ULONG ForceFilledShared: 1; // 27
+ ULONG RmmStxcFillShared: 1; // 28
+ ULONG Reserved3: 3; // 29-31
+ ULONG EnableAddressCommandBusParityCheck1: 1; // 32
+ ULONG Reserved4: 4; // 33-35
+ ULONG EnableCorrectionErrorInterrupt1: 1; // 36
+ ULONG EnableECCCorrection1: 1; // 37
+ ULONG EnableRattlerECCCheck1: 1; // 38
+ ULONG DisableEV5ECCChecking1: 1; // 39
+ ULONG Reserved5: 24; // 40-63
+ };
+ ULONGLONG all;
+
+} GAMMA_EVBCR_CSR2, *PGAMMA_EVBCR_CSR2;
+
+
+typedef struct _GAMMA_EVBVEAR_CSR3 {
+ union {
+ ULONG EVBVictimErrorAddress0: 30; // 0-29
+ ULONG Reserved1: 2; // 30-31
+ ULONG EVBVictimErrorAddress1: 30; // 32-61
+ ULONG Reserved2: 2; // 62-63
+ };
+
+} GAMMA_EVBVEAR_CSR3, *PGAMMA_EVBVEAR_CSR3;
+
+typedef struct _GAMMA_EVBCER_CSR4 {
+ union {
+ ULONG CorrectableError0: 2; // 0-1
+ ULONG ReadDirty0: 1; // 2
+ ULONG MissedCorrectable0: 1; // 3
+ ULONG Reserved1: 4; // 4-7
+ ULONG ECCSyndrome0: 8; // 8-15
+ ULONG ECCSyndrome2: 8; // 16-23
+ ULONG Reserved2: 8; // 24-31
+
+ ULONG CorrectableError1: 2; // 32-33
+ ULONG ReadDirty1: 1; // 34
+ ULONG MissedCorrectable1: 1; // 35
+ ULONG Reserved3: 4; // 36-39
+ ULONG ECCSyndrome1: 8; // 40-47
+ ULONG ECCSyndrome3: 8; // 48-55
+ ULONG Reserved4: 8; // 56-63
+ };
+ ULONGLONG all;
+
+} GAMMA_EVBCER_CSR4, *PGAMMA_EVBCER_CSR4;
+
+typedef struct _GAMMA_EVBCEAR_CSR5 {
+ union {
+ ULONG EVBCorrectableErrorAddress0: 32; // 0-31
+ ULONG EVBCorrectableErrorAddress1: 32; // 32-63
+ };
+ ULONGLONG all;
+
+} GAMMA_EVBCEAR_CSR5, *PGAMMA_EVBCEAR_CSR5;
+
+typedef struct _GAMMA_EVBUER_CSR6 {
+ union {
+ ULONG UncorrectableError0: 2; // 0-1
+ ULONG ReadDirty0: 1; // 2
+ ULONG Reserved1: 1; // 3
+ ULONG ParityErrorOnAddressCommand0: 1; // 4
+ ULONG ParityErrorOnVictim0: 1; // 5
+ ULONG Reserved2: 2; // 6-7
+ ULONG ECCSyndrome0: 8; // 8-15
+ ULONG ECCSyndrome2: 8; // 16-23
+ ULONG Reserved3: 4; // 24-27
+ ULONG EVBCommand0: 4; // 28-31
+
+ ULONG UncorrectableError1: 2; // 32-33
+ ULONG ReadDirty1: 1; // 34
+ ULONG Reserved4: 1; // 35
+ ULONG ParityErrorOnAddressCommand1: 1; // 36
+ ULONG ParityErrorOnVictim1: 1; // 37
+ ULONG Reserved5: 2; // 38-39
+ ULONG ECCSyndrome1: 8; // 40-47
+ ULONG ECCSyndrome3: 8; // 48-55
+ ULONG Reserved6: 4; // 56-59
+ ULONG EVBCommand1: 4; // 60-63
+ };
+ ULONGLONG all;
+
+} GAMMA_EVBUER_CSR6, *PGAMMA_EVBUER_CSR6;
+
+typedef struct _GAMMA_EVBUEAR_CSR7 {
+ union {
+ ULONG EVBUncorrectableErrorAddress0: 32; // 0-31
+ ULONG EVBUncorrectableErrorAddress1: 32; // 32-63
+ };
+ ULONGLONG all;
+
+} GAMMA_EVBEUAR_CSR7, *PGAMMA_EVBUEAR_CSR7;
+
+
+typedef struct _GAMMA_CBER_CSR18 {
+ union {
+ ULONG UncorrectableReadError0: 1; // 0
+ ULONG Reserved1: 3; // 1-3
+ ULONG CAParity0ErrorL: 1; // 4
+ ULONG CAParity0ErrorH: 1; // 5
+ ULONG Reserved2: 2; // 6-7
+ ULONG ParityErrorWriteDataLW0: 1; // 8
+ ULONG ParityErrorWriteDataLW1: 1; // 9
+ ULONG ParityErrorWriteDataLW4: 1; // 10
+ ULONG ParityErrorWriteDataLW5: 1; // 11
+ ULONG Reserved3: 4; // 12-15
+ ULONG ParityErrorReadDataLW0: 1; // 16
+ ULONG ParityErrorReadDataLW1: 1; // 17
+ ULONG ParityErrorReadDataLW4: 1; // 18
+ ULONG ParityErrorReadDataLW5: 1; // 19
+ ULONG UnexpectedSharedResponse: 1; // 20
+ ULONG Reserved4: 3; // 21-23
+ ULONG CANotAcked: 1; // 24
+ ULONG Reserved5: 3; // 25-27
+ ULONG Data0NotAcked: 1; // 28
+ ULONG Data1NotAcked: 1; // 29
+ ULONG Reserved6: 2; // 30-31
+
+ ULONG UncorrectableReadError1: 1; // 32
+ ULONG Reserved7: 3; // 33-35
+ ULONG CAParity1ErrorL: 1; // 36
+ ULONG CAParity1ErrorH: 1; // 37
+ ULONG Reserved8: 2; // 38-39
+ ULONG ParityErrorWriteDataLW2: 1; // 40
+ ULONG ParityErrorWriteDataLW3: 1; // 41
+ ULONG ParityErrorWriteDataLW6: 1; // 42
+ ULONG ParityErrorWriteDataLW7: 1; // 43
+ ULONG Reserved9: 4; // 44-47
+ ULONG ParityErrorReadDataLW2: 1; // 48
+ ULONG ParityErrorReadDataLW3: 1; // 49
+ ULONG ParityErrorReadDataLW6: 1; // 50
+ ULONG ParityErrorReadDataLW7: 1; // 51
+ ULONG Reserved10: 12; // 52-63
+ };
+ ULONGLONG all;
+
+} GAMMA_CBER_CSR18, *PGAMMA_CBER_CSR18;
+
+typedef struct _GAMMA_CBEALR_CSR19 {
+ union {
+ ULONG CBusErrorLowAddress0: 32; // 0-31
+ ULONG CBusErrorLowAddress1: 32; // 32-63
+ };
+ ULONGLONG all;
+
+} GAMMA_CBEALR_CSR19, *PGAMMA_CBEALR_CSR19;
+
+typedef struct _GAMMA_CBEAHR_CSR20 {
+ union {
+ ULONG CBusErrorHighAddress0: 32; // 0-31
+ ULONG CBusErrorHighAddress1: 32; // 32-63
+ };
+ ULONGLONG all;
+
+} GAMMA_CBEAHR_CSR20, *PGAMMA_CBEAHR_CSR20;
+
+
+typedef struct _SGL_MEM_CSR0 {
+ union {
+ ULONG ErrorSummary1: 1; // 0
+ ULONG SyncError1: 1; // 1
+ ULONG CAParityError1: 1; // 2
+ ULONG CAMissedParityError1: 1; // 3
+ ULONG WriteParityError1: 1; // 4
+ ULONG MissedWriteParityError1: 1; // 5
+ ULONG Reserved1: 2; // 6-7
+
+ ULONG CAParityErrorLW0: 1; // 8
+ ULONG CAParityErrorLW2: 1; // 9
+ ULONG ParityErrorLW0: 1; // 10
+ ULONG ParityErrorLW2: 1; // 11
+ ULONG ParityErrorLW4: 1; // 12
+ ULONG ParityErrorLW6: 1; // 13
+ ULONG Reserved2: 2; // 14-15
+
+ ULONG EDCUncorrectable1: 1; // 16
+ ULONG EDCMissedUncorrectable1: 1; // 17
+ ULONG EDCCorrectable1: 1; // 18
+ ULONG EDCMissdedCorrectable1: 1; // 19
+ ULONG Reserved3: 12; // 20-31
+
+ ULONG ErrorSummary2: 1; // 32
+ ULONG SyncError2: 1; // 33
+ ULONG CAParityError2: 1; // 34
+ ULONG CAMissedParityError2: 1; // 35
+ ULONG WriteParityError2: 1; // 36
+ ULONG MissedWriteParityError2: 1; // 37
+ ULONG Reserved4: 2; // 38-39
+
+ ULONG CAParityErrorLW1: 1; // 40
+ ULONG CAParityErrorLW3: 1; // 41
+ ULONG ParityErrorLW1: 1; // 42
+ ULONG ParityErrorLW3: 1; // 43
+ ULONG ParityErrorLW5: 1; // 44
+ ULONG ParityErrorLW7: 1; // 45
+ ULONG Reserved5: 2; // 46-47
+
+ ULONG EDCUncorrectable2: 1; // 48
+ ULONG EDCMissedUncorrectable2: 1; // 49
+ ULONG EDCCorrectable2: 1; // 50
+ ULONG EDCMissdedCorrectable2: 1; // 51
+ ULONG Reserved6: 12; // 52-63
+ };
+ ULONGLONG all;
+
+} SGL_MEM_CSR0, *PSGL_MEM_CSR0;
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each Gamma processor.
+//
+// NOTE: If the IpirSva field is moved, the change must be reflected in
+// the routine HalpGammaIpiInterrupt
+//
+
+typedef struct _GAMMA_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONGLONG IpirSva; // Superpage Va of per-processor IPIR CSR
+ PVOID CpuCsrsQva; // Qva of per-cpu csrs
+ EV5ProfileCount ProfileCount; // Profile counter state
+} GAMMA_PCR, *PGAMMA_PCR;
+
+#define HAL_PCR ( (PGAMMA_PCR)(&(PCR->HalReserved)) )
+
+
+//
+// Define Miscellaneous Gamma routines.
+//
+
+VOID
+WRITE_CPU_REGISTER(
+ PVOID,
+ ULONGLONG
+ );
+
+ULONGLONG
+READ_CPU_REGISTER(
+ PVOID
+ );
+
+ULONGLONG
+READ_MEM_REGISTER(
+ PVOID
+ );
+
+BOOLEAN
+HalpGammaDispatch(
+ VOID
+ );
+
+VOID
+HalpGammaIpiInterrupt(
+ VOID
+ );
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_GAMMAH_
diff --git a/private/ntos/nthals/halgamma/alpha/gammaerr.c b/private/ntos/nthals/halgamma/alpha/gammaerr.c
new file mode 100644
index 000000000..b3fd0dfbc
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gammaerr.c
@@ -0,0 +1,2395 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ gammaerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Sable platform.
+
+Author:
+
+ Joe Notarangelo 15-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+//jnfix - this module current only deals with errors initiated by the
+//jnfix - T2, there is nothing completed for CPU Asic errors
+
+#include "halp.h"
+#include "gamma.h"
+#include "axp21164.h"
+#include "stdio.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+extern ULONG HalDisablePCIParityChecking;
+extern ULONG HalpMemorySlot[];
+extern ULONG HalpCPUSlot[];
+
+ULONG SlotToPhysicalCPU[4] = {3, 0, 1, 2};
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+ULONG
+HalpTranslateSyndromToECC(
+ PULONG Syndrome
+ );
+
+ULONG SGLCorrectedErrors = 0;
+
+//
+// PCI Config space access in progress. The READ_CONFIG_* routines
+// must set this value to the correct return address before performing
+// config space reads. The machine check handler will use this value for
+// the return address if a machine check is detected from a config
+// space read.
+//
+LONG HalpConfigIoAccess = 0; // Machine check return address
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpSableReportFatalError(
+ VOID
+ );
+
+#define MAX_ERROR_STRING 128
+
+
+VOID
+HalpInitializeMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for an APECS-based
+ system by clearing all pending errors in the COMANCHE and EPIC and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ T2_PERR1 Perr1;
+ T2_IOCSR Iocsr;
+
+ //
+ // Clear any pending CBUS errors.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1, Cerr1.all );
+
+ //
+ // Clear any pending PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ Perr1.ForceReadDataParityError64 = 0;
+ Perr1.ForceAddressParityError64 = 0;
+ Perr1.ForceWriteDataParityError64 = 0;
+ Perr1.DetectTargetAbort = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1, Perr1.all );
+
+ //
+ // Enable the errors we want to handle in the T2 via the Iocsr,
+ // must read-modify-write Iocsr as it contains values we want to
+ // preserve.
+ //
+
+ Iocsr.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr );
+
+ //
+ // Enable all of the hard error checking and error interrupts.
+ //
+
+ Iocsr.EnableTlbErrorCheck = 1;
+ Iocsr.EnableCxAckCheckForDma = 1;
+// Iocsr.EnableCommandOutOfSyncCheck = 1;
+ Iocsr.EnableCbusErrorInterrupt = 1;
+ Iocsr.EnableCbusParityCheck = 1;
+
+#if 0
+ //
+ // T3 Bug: There are 2 write buffers which can be used for PIO or
+ // PPC. By default they are initialized to PIO. However, using
+ // them for PIO causes T3 state machine errors. To work around this
+ // problem convert them to PPC buffers, instead. This decreases PIO
+ // performance.
+ //
+
+ if (Iocsr.T2RevisionNumber >= 4) {
+
+ Iocsr.EnablePpc1 = 1;
+ Iocsr.EnablePpc2 = 1;
+
+ }
+#endif // wkc - the SRM sets this now....
+
+ Iocsr.ForcePciRdpeDetect = 0;
+ Iocsr.ForcePciApeDetect = 0;
+ Iocsr.ForcePciWdpeDetect = 0;
+ Iocsr.EnablePciNmi = 1;
+ Iocsr.EnablePciDti = 1;
+ Iocsr.EnablePciSerr = 1;
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+
+ //
+ // Disable PCI Parity Checking
+ //
+
+ Iocsr.EnablePciPerr = 0;
+ Iocsr.EnablePciRdp = 0;
+ Iocsr.EnablePciAp = 0;
+ Iocsr.EnablePciWdp = 0;
+
+ } else {
+
+ Iocsr.EnablePciPerr = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciRdp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp = !HalDisablePCIParityChecking;
+
+ }
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr, Iocsr.all );
+
+ //
+ // Ascertain whether this is a Gamma or Lynx platform.
+ //
+
+ if( Iocsr.T2RevisionNumber >= 4 ){
+
+ HalpLynxPlatform = TRUE;
+
+ }
+
+ //
+ // Set the machine check enables within the EV5.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ } else {
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ {
+ //
+ // Clear any existing Rattler errors:
+ //
+
+ RATTLER_ESREG_CSR Esreg;
+ RATTLER_SIC_CSR Sicr;
+
+ Esreg.all =
+ READ_CPU_REGISTER(&((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg);
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg,
+ Esreg.all);
+
+
+ Sicr.all = 0;
+ Sicr.SystemEventClear = 1;
+ Sicr.SystemBusErrorInterruptClear0 = 1;
+ Sicr.SystemBusErrorInterruptClear1 = 1;
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr,
+ Sicr.all);
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // The next line *may* generate a machine check. This would happen
+ // if an XIO module is not present in the system. It should be safe
+ // to take machine checks now. Here goes nothing...
+ //
+
+ Iocsr.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr );
+
+ if( Iocsr.all != (ULONGLONG)-1 ){
+
+ HalpXioPresent = TRUE;
+
+ //
+ // Clear any pending CBUS errors.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1, Cerr1.all );
+
+ //
+ // Clear any pending PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1 );
+
+ Perr1.ForceReadDataParityError64 = 0;
+ Perr1.ForceAddressParityError64 = 0;
+ Perr1.ForceWriteDataParityError64 = 0;
+ Perr1.DetectTargetAbort = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1, Perr1.all );
+
+ Iocsr.EnableTlbErrorCheck = 1;
+ Iocsr.EnableCxAckCheckForDma = 1;
+// Iocsr.EnableCommandOutOfSyncCheck = 1;
+ Iocsr.EnableCbusErrorInterrupt = 1;
+ Iocsr.EnableCbusParityCheck = 1;
+
+ //
+ // T3 Bug: There are 2 write buffers which can be used for PIO or
+ // PPC. By default they are initialized to PIO. However, using
+ // them for PIO causes T3 state machine errors. To work around
+ // this problem convert them to PPC buffers, instead. This
+ // decreases PIO performance.
+ //
+
+ Iocsr.EnablePpc1 = 1;
+ Iocsr.EnablePpc2 = 1;
+
+ Iocsr.EnablePciStall = 0;
+ Iocsr.ForcePciRdpeDetect = 0;
+ Iocsr.ForcePciApeDetect = 0;
+ Iocsr.ForcePciWdpeDetect = 0;
+ Iocsr.EnablePciNmi = 1;
+ Iocsr.EnablePciDti = 1;
+ Iocsr.EnablePciSerr = 1;
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+
+ //
+ // Disable PCI Parity Checking
+ //
+
+ Iocsr.EnablePciRdp64 = 0;
+ Iocsr.EnablePciAp64 = 0;
+ Iocsr.EnablePciWdp64 = 0;
+ Iocsr.EnablePciPerr = 0;
+ Iocsr.EnablePciRdp = 0;
+ Iocsr.EnablePciAp = 0;
+ Iocsr.EnablePciWdp = 0;
+
+ } else {
+
+ Iocsr.EnablePciRdp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciPerr = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciRdp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp = !HalDisablePCIParityChecking;
+
+ }
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr,
+ Iocsr.all );
+
+ }
+
+#endif
+
+#if HALDBG
+ if (HalDisablePCIParityChecking == 0) {
+ DbgPrint("gammaerr: PCI Parity Checking ON\n");
+ } else if (HalDisablePCIParityChecking == 1) {
+ DbgPrint("gammaerr: PCI Parity Checking OFF\n");
+ } else {
+ DbgPrint("gammaerr: PCI Parity Checking OFF - not set by ARC yet\n");
+ }
+#endif
+
+ return;
+}
+
+VOID
+HalpGammaCorrectableInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for an Gamma Correctable errors.
+ This function does nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalpBuildGammaUncorrectableErrorFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when an uncorrectable error occurs.
+ This routine builds the global Sable Uncorrectable Error frame.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ //
+ // We will *try* to get the CPU module information that was active at the
+ // time of the machine check.
+ // We will *try* to get as much information about the system, the CPU
+ // modules and the memory modules at the time of the crash.
+ //
+ extern ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ //
+ // SABLE_CPU_CSRS is defined to be RATTLER_CPU_CSRS in gamma.h
+ //
+ extern PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+ extern KAFFINITY HalpActiveProcessors;
+
+ PSABLE_CPU_CSRS CpuCsrsQva;
+ PGAMMA_UNCORRECTABLE_FRAME gammauncorrerr = NULL;
+ PEXTENDED_ERROR PExtErr;
+ ULONG LogicalCpuNumber;
+ ULONG i = 0;
+ ULONG TotalNumberOfCpus = 0;
+ T2_IOCSR Iocsr;
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+
+ if(PUncorrectableError){
+ gammauncorrerr = (PGAMMA_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ if(gammauncorrerr){
+ //
+ // Get the Error registers from all the CPU modules.
+ // Although called CPU error this is sable specific and not CPU
+ // specific the CPU error itself will be logged in the EV4 error frame.
+ // HalpActiveProcessors is a mask of all processors that are active.
+ // 8 bits per byte to get the total number of bits in KAFFINITY
+ //
+ DbgPrint("gammaerr.c - HalpBuildGammaUncorrectableErrorFrame :\n");
+ for(i = 0 ; i < sizeof(KAFFINITY)*8 ; i++ ) {
+ if( (HalpActiveProcessors >> i) & 0x1UL) {
+ LogicalCpuNumber = i;
+ TotalNumberOfCpus++;
+ }
+ else
+ continue;
+
+ CpuCsrsQva = HalpSableCpuCsrs[LogicalCpuNumber];
+
+ DbgPrint("\tCurrent CPU Module's[LN#=%d] CSRS QVA = %08lx\n",
+ LogicalCpuNumber, CpuCsrsQva);
+ DbgPrint("\n\t CPU Module Error Log : \n");
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Esreg =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Esreg);
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuer =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Evbuer);
+
+ DbgPrint("\t\tEvbuer = %016Lx\n",
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuer);
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuear =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Evbuear);
+
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuear;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ DbgPrint("\t\tEvbuear = %016Lx\n",
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuear);
+
+ //
+ // If the Parity Error Bit (bit 5 and bit 37) is Set then
+ // read the victim address.
+ //
+
+ if(
+ ( gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuer
+ & ((ULONGLONG)1 << 5) ) ||
+ ( gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuer
+ & ((ULONGLONG)1 << 37) )
+ ){
+ gammauncorrerr->CpuError[LogicalCpuNumber].Vear =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Evbvear);
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid
+ = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Parity Error on Victim Address");
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_CACHE;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuear;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.CacheBoardNumber = LogicalCpuNumber;
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+
+ }
+ if(
+ ( gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuer
+ & ((ULONGLONG)1 << 4) ) ||
+ ( gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuer
+ & ((ULONGLONG)1 << 36) )
+ ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid
+ = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Parity Error on Address-Cmd Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_CACHE;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ gammauncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Evbuear;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.CacheBoardNumber = LogicalCpuNumber;
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+ }
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Dter =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Dter);
+ DbgPrint("\t\tDter = %016Lx\n",
+ gammauncorrerr->CpuError[LogicalCpuNumber].Dter);
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Cberr =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cber);
+ DbgPrint("\t\tCberr = %016Lx\n",
+ gammauncorrerr->CpuError[LogicalCpuNumber].Cberr);
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Cbeal =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbealr);
+ DbgPrint("\t\tCbeal = %016Lx\n",
+ gammauncorrerr->CpuError[LogicalCpuNumber].Cbeal);
+
+ gammauncorrerr->CpuError[LogicalCpuNumber].Cbeah =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbeahr);
+ DbgPrint("\t\tCbeah = %016Lx\n",
+ gammauncorrerr->CpuError[LogicalCpuNumber].Cbeah);
+
+
+ //
+ // Fill in some of the control registers in the configuration
+ // structures.
+ //
+ DbgPrint("\n\t CPU Module Configuration : \n");
+ gammauncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Creg =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Creg);
+ DbgPrint("\t\tCreg = %016Lx\n",
+ gammauncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Creg);
+
+ gammauncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Cbctl =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbcr);
+ DbgPrint("\t\tCbctl = %016Lx\n",
+ gammauncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Cbctl);
+
+ gammauncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Dtctr =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Dtctr);
+ DbgPrint("\t\tDtctr = %016Lx\n",
+ gammauncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Dtctr);
+
+ }
+
+ gammauncorrerr->Configuration.NumberOfCpus = TotalNumberOfCpus;
+ DbgPrint("\tTotalNumberOfCpus = %d\n", TotalNumberOfCpus);
+
+ //
+ // Since I dont know how to get how many memory modules
+ // are available and which slots they are in we will skip
+ // the memory error logging. When we do this we will also fill in
+ // the memory configuration details.
+ //
+
+ //
+ // Get T2 errors.
+ //
+ DbgPrint("\n\tT2 Error Log :\n");
+ gammauncorrerr->IoChipsetError.Cerr1 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ DbgPrint("\t\tCerr1 = %016Lx\n",
+ gammauncorrerr->IoChipsetError.Cerr1);
+
+ Perr1.all = gammauncorrerr->IoChipsetError.Perr1 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+ DbgPrint("\t\tPerr1 = %016Lx\n",
+ gammauncorrerr->IoChipsetError.Perr1);
+
+ gammauncorrerr->IoChipsetError.Cerr2 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr2 );
+ DbgPrint("\t\tCerr2 = %016Lx\n",
+ gammauncorrerr->IoChipsetError.Cerr2);
+
+ gammauncorrerr->IoChipsetError.Cerr3 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr3 );
+ DbgPrint("\t\tCerr3 = %016Lx\n",
+ gammauncorrerr->IoChipsetError.Cerr3);
+
+ Perr2.all = gammauncorrerr->IoChipsetError.Perr2 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr2 );
+ DbgPrint("\t\tPerr2 = %016Lx\n",
+ gammauncorrerr->IoChipsetError.Perr2);
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ Perr2.ErrorAddress;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ }
+
+
+
+ //
+ // T2 Configurations
+ //
+ DbgPrint("\n\tT2 Configuration :\n");
+ Iocsr.all = gammauncorrerr->Configuration.T2IoCsr =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr );
+ DbgPrint("\t\tIocsr = %016Lx\n",
+ gammauncorrerr->Configuration.T2IoCsr);
+
+ gammauncorrerr->Configuration.T2Revision = Iocsr.T2RevisionNumber;
+ DbgPrint("\t\tT2 Revision = %d\n",
+ gammauncorrerr->Configuration.T2Revision);
+
+
+ }
+
+ //
+ // Now fill in the Extended error information.
+ //
+ return;
+}
+
+
+VOID
+HalpGammaErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for an Gamma machine check interrupt
+ The function calls HalpSableReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+ RATTLER_ESREG_CSR Esreg;
+ RATTLER_SIC_CSR Sicr;
+
+ Esreg.all =
+ READ_CPU_REGISTER(&((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg);
+
+ if( TRUE ){ //Esreg.EvNoResponse1 == 1 ){
+
+ //
+ // Dismiss the CBUS timeout errors and return. Let the machine check
+ // handler handle the PCI fixup.
+ //
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg,
+ Esreg.all
+ );
+
+ Sicr.all = 0;
+ Sicr.SystemBusErrorInterruptClear0 = 1;
+ Sicr.SystemBusErrorInterruptClear1 = 1;
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr,
+ Sicr.all
+ );
+
+ //
+ // Read the SICR to force the write to complete. Otherwise the CPU
+ // can unwind from the interrupt before the wrattler completes
+ // the processing of the write, causing another interrupt to be
+ // taken. This read forces the write to fully complete before
+ // proceeding.
+ //
+ Sicr.all =
+ READ_CPU_REGISTER(&((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr);
+
+ return;
+ }
+
+ //
+ // Report the error and crash the system
+ //
+ HalpBuildGammaUncorrectableErrorFrame();
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Gamma: Uncorrectable Error interrupt from T2");
+ }
+
+
+ HalpSableReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+
+
+ return; // never
+}
+
+
+BOOLEAN
+HalpIsaLegacyMemoryAccess(
+ ULONGLONG PA
+ )
+/*++
+
+Routine Description:
+
+ Checks for ISA legacy memory access on PCI bus1
+
+Arguments:
+
+ PA Physical Address
+
+Return Value:
+
+ true/false
+
+--*/
+
+{
+
+ if ( PA >= GAMMA_PCI1_SPARSE_MEMORY_PHYSICAL &&
+ PA < GAMMA_PCI1_SPARSE_ISA_LEGACY_MEMORY_PHYSICAL) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+HalpIsaLegacyIOAccess(
+ ULONGLONG PA
+ )
+/*++
+
+Routine Description:
+
+ Checks for ISA legacy I/O access on PCI bus1
+
+ The rules are:
+
+ The first 4K of IO space is ISA legacy.
+ Each 1K after that, the first 256 bytes (of that 1K) is NOT ISA legacy, but
+ the other section (768 bytes) is.
+
+
+Arguments:
+
+ PA Physical Address
+
+Return Value:
+
+ true/false
+
+--*/
+
+{
+ ULONG LowOrder;
+
+ //
+ // First check the range...
+ //
+
+ if ( PA >= GAMMA_PCI1_SPARSE_IO_PHYSICAL &&
+ PA < GAMMA_PCI1_SPARSE_ISA_LEGACY_IO_PHYSICAL) {
+
+ //
+ // Whack off high order physical address bits and shift down
+ // by the IO bit shift
+ //
+
+ LowOrder = ((ULONG)(PA)) >> IO_BIT_SHIFT;
+
+ //
+ // Less than 4K?
+ //
+
+ if (LowOrder < 0x1000) {
+ return TRUE;
+ }
+
+ //
+ // Modulo 1K (0400)
+ //
+
+ LowOrder &= 0x3ff;
+
+ //
+ // first 256 bytes?
+ //
+
+ if (LowOrder < 0x100) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the APECS chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+ PLOGOUT_FRAME_21164 LogoutFrame;
+ ULONGLONG PA;
+ enum {
+ Pci0ConfigurationSpace,
+ Pci1ConfigurationSpace,
+ MemCsrSpace,
+ CPUCsrSpace,
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+ T4CsrSpace
+#endif
+ } AddressSpace;
+ PVOID TxCsrQva;
+ PALPHA_INSTRUCTION FaultingInstruction;
+
+ RATTLER_ESREG_CSR Esreg;
+ RATTLER_SIC_CSR Sicr;
+ CHAR ErrSpace[32];
+
+ //
+ // Check if there are any CBUS errors pending. Any of these errors
+ // are fatal.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+#if HALDBG
+ DbgPrint("HalpPlatformMachineCheck: T2 CERR1 = %Lx\n", Cerr1.all);
+#endif
+ sprintf(ErrSpace,"System Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = CBus;
+
+ goto FatalError;
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent ){
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1);
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+#if HALDBG
+ DbgPrint("HalpPlatformMachineCheck: T4 CERR1 = %Lx\n",
+ Cerr1.all);
+#endif
+
+ sprintf(ErrSpace,"System Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = CBus;
+ goto FatalError;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+#if HALDBG
+ DbgPrint("HalpPlatformMachineCheck: T2 PERR1 = %Lx\n", Perr1.all);
+#endif
+
+ sprintf(ErrSpace,"PCI Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = PCIBus;
+ goto FatalError;
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent ){
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1 );
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ||
+ (Perr1.PpcSizeError == 1) ||
+ (Perr1.WriteDataParityError64 == 1) ||
+ (Perr1.AddressParityError64 == 1) ||
+ (Perr1.ReadDataParityError64 == 1) ||
+ (Perr1.TargetAbort == 1) ){
+
+#if HALDBG
+ DbgPrint("HalpPlatformMachineCheck: T4 PERR1 = %Lx\n",
+ Perr1.all);
+#endif
+
+ sprintf(ErrSpace,"PCI Configuration");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = PCIBus;
+
+ goto FatalError;
+
+ }
+ }
+
+#endif
+
+ //
+ // Get a pointer to the EV5 machine check logout frame.
+ //
+
+ LogoutFrame =
+ (PLOGOUT_FRAME_21164)ExceptionRecord->ExceptionInformation[1];
+
+ //
+ // Get the physical address which caused the machine check.
+ //
+
+ PA = LogoutFrame->EiAddr.EiAddr << 4;
+
+ //
+ // We handle and dismiss 3 classes of machine checks:
+ //
+ // - Read accesses from PCI 0 configuration space
+ // - Read accesses from PCI 1 configuration space
+ // - Read accesses from T4 CSR space
+ //
+ // Any other type of machine check is fatal.
+ //
+ // The following set of conditionals check which address space the
+ // machine check occured in, to decide how to handle it.
+ //
+
+ if( (PA >= GAMMA_PCI0_CONFIGURATION_PHYSICAL) &&
+ (PA < GAMMA_PCI1_CONFIGURATION_PHYSICAL) ){
+
+ //
+ // The machine check occured in PCI 0 configuration space. Save
+ // the address space and a QVA to T2 CSR space, we'll need them
+ // below.
+ //
+
+ AddressSpace = Pci0ConfigurationSpace;
+ TxCsrQva = (PVOID)T2_CSRS_QVA;
+
+ } else if( (PA >= GAMMA_PCI1_CONFIGURATION_PHYSICAL) &&
+ (PA < GAMMA_PCI0_SPARSE_IO_PHYSICAL) ){
+
+ //
+ // The machine check occured in PCI 1 configuration space.
+ // Save the address space and a QVA to T2 CSR space, we'll
+ // need them below.
+ //
+
+ AddressSpace = Pci1ConfigurationSpace;
+ TxCsrQva = (PVOID)T4_CSRS_QVA;
+
+ } else if( (PA >= GAMMA_CPU0_CSRS_PHYSICAL) &&
+ (PA <= GAMMA_CPU3_SICR_PHYSICAL)) {
+
+ //
+ // The machine check occured within CPU CSR space. Save
+ // the addres space, w'll need it below.
+ //
+
+ AddressSpace = CPUCsrSpace;
+
+ } else if( (PA >= GAMMA_MEM0_CSRS_PHYSICAL) &&
+ (PA < GAMMA_T2_CSRS_PHYSICAL)) {
+
+ //
+ // The machine check occured within MEM CSR space. Save
+ // the addres space, w'll need it below.
+ //
+
+ AddressSpace = MemCsrSpace;
+
+ } else
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( (PA >= GAMMA_T4_CSRS_PHYSICAL) &&
+ (PA < GAMMA_PCI0_CONFIGURATION_PHYSICAL) ){
+
+ //
+ // The machine check occured within T4 CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = T4CsrSpace;
+
+ } else if (HalpIsaLegacyMemoryAccess(PA) ||
+ HalpIsaLegacyIOAccess(PA)) {
+
+#if HALDBG
+ if (HalpIsaLegacyMemoryAccess(PA)) {
+ DbgPrint("Isa Legacy Memory access on PCI1: PA: %Lx \n", PA);
+ } else if (HalpIsaLegacyIOAccess(PA)) {
+ DbgPrint("Isa Legacy I/O access on PCI1: PA: %Lx \n", PA);
+ }
+#endif
+ //
+ // Check for a master abort under within the first 1Mb of
+ // sparse space to fix broken drivers that sniff ISA legacy
+ // space on PCI slot 1 (which has no ISA address space...)
+ // This happens when a dorky driver was pokes around ISA legacy space
+ // on our second (peer) PCI bus -- which has no ISA legacy space.
+ // We attempt to silently return all ff's -- and look like there
+ // is non-responding ISA space...
+ //
+
+ Esreg.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg );
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg, Esreg.all );
+
+ Sicr.all = 0;
+ Sicr.SystemBusErrorInterruptClear0 = 1;
+ Sicr.SystemBusErrorInterruptClear1 = 1;
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr, Sicr.all );
+
+ //
+ // Read the SICR to force the write to complete. Otherwise the CPU
+ // can unwind from the machine check before the rattler completes
+ // the processing of the write. This read forces the write to
+ // fully complete before proceeding.
+ //
+
+ Sicr.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr );
+
+
+ //
+ // Our I/O access routines preload -1 into V0, so if we simply return,
+ // V0 should correctly be set to all ff's
+ //
+
+ return TRUE;
+
+ } else
+
+#endif
+
+ {
+ //
+ // Just based on the physical address, we have determined
+ // we cannot handle this machine check.
+ //
+
+ goto FatalError;
+
+ }
+
+ //
+ // The configuration space and T2 register access routines set
+ // HalpConfigIoAccess to point to the faulting instruction. If it
+ // is non-NULL update the exception frame to reflect the real
+ // address of the faulting instruction.
+ //
+
+ if( HalpConfigIoAccess != 0 ){
+
+ TrapFrame->Fir = (LONGLONG)HalpConfigIoAccess;
+
+ }
+
+ //
+ // Get a pointer to the faulting instruction. (It is possible
+ // that the exception address is actually an instruction or two
+ // beyond the instruction which actually caused the machine check.)
+ //
+
+ FaultingInstruction = (PALPHA_INSTRUCTION)TrapFrame->Fir;
+
+ //
+ // There are typically 2 MBs which follow the load which caused the
+ // machine check. The exception address could be one of them.
+ // If it is, advance the instruction pointer ahead of them.
+ //
+
+ while( (FaultingInstruction->Memory.Opcode == MEMSPC_OP) &&
+ (FaultingInstruction->Memory.MemDisp == MB_FUNC) ){
+
+ FaultingInstruction--;
+
+ }
+
+ //
+ // If the instruction uses v0 as Ra (i.e. v0 is the target register
+ // of the instruction) then this would typically indicate an T2 or
+ // configuration space access routine, and getting a machine check
+ // therein is acceptable. Otherwise, we took it someplace else, and
+ // it is fatal.
+ //
+
+ if( FaultingInstruction->Memory.Ra != V0_REG ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Perform address space-dependent handling.
+ //
+
+ switch( AddressSpace ){
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ case Pci1ConfigurationSpace:
+
+ //
+ // If no XIO module is present then we do not fix-up read accesses
+ // from PCI 1 configuration space. (This should never happen.)
+ //
+
+ if( !HalpXioPresent ){
+
+ goto FatalError;
+
+ }
+
+#endif
+
+ case Pci0ConfigurationSpace:
+
+ //
+ // Read the state of the T2/T4.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr1 );
+ Perr2.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr2 );
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Cerr1 );
+
+ //
+ // The T2/T4 responds differently when an error was received
+ // on type 0 and type 1 configuration cycles. For type 0 the
+ // T2/T4 detects and reports the device timeout. For type 1
+ // the PPB detects the timeout. Type 0 cycles error with
+ // the DeviceTimeout bit set. Type 1 cycles look just like
+ // NXM. Thus, the code below requires both checks.
+ //
+
+ if( (Perr1.DeviceTimeoutError != 1) &&
+ ((Perr1.all != 0) ||
+ (Cerr1.all != 0) ||
+ (Perr2.PciCommand != 0xA)) ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Clear any PCI or Cbus errors which may have been latched.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr1, Perr1.all );
+
+ break;
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ case T4CsrSpace:
+
+ //
+ // A read was performed from T4 CSR space when no XIO module was
+ // present. This was done, presumably, to detect the presence of
+ // the T4, and correspondingly, the XIO module. There is nothing
+ // special to do in this case, just fix-up the reference and
+ // dismiss the machine check.
+ //
+
+ break;
+
+#endif
+
+ case MemCsrSpace:
+ case CPUCsrSpace:
+
+ //
+ // A read was performed from the Mem CSR space when no memory module was
+ // present. This was done, presumably, to detect the presence of
+ // a memory board.
+ //
+
+ break;
+
+ }
+
+ //
+ // Dismiss the CBUS timeout errors and return. Let the machine
+ // check handler handle the PCI fixup.
+ //
+ // The Esreg.EVNoResponse bits get set on a PCI bus timeout. This
+ // generates an Error interrupt, which must be cleared in the Sicr.
+ // Clear the error bit here, dismissing the interrupt.
+ //
+
+ Esreg.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg );
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg, Esreg.all );
+
+ Sicr.all = 0;
+ Sicr.SystemBusErrorInterruptClear0 = 1;
+ Sicr.SystemBusErrorInterruptClear1 = 1;
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr, Sicr.all );
+
+ //
+ // Read the SICR to force the write to complete. Otherwise the CPU
+ // can unwind from the machine check before the rattler completes
+ // the processing of the write. This read forces the write to
+ // fully complete before proceeding.
+ //
+
+ Sicr.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr );
+
+ //
+ // Advance the instruction pointer.
+ //
+
+ TrapFrame->Fir += 4;
+
+ //
+ // Make it appear as if the load instruction read all ones.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)-1;
+
+ //
+ // Dismiss the machine check.
+ //
+
+ return TRUE;
+
+ //
+ // The system is not well and cannot continue reliable execution.
+ // Print some useful messages and return FALSE to indicate that the
+ // error was not handled.
+ //
+
+FatalError:
+ //
+ // Build the error frame. Later may be move it in front and use
+ // the field in the error frame rather than reading the error registers
+ // twice.
+ //
+
+ HalpBuildGammaUncorrectableErrorFrame();
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Gamma: Uncorrectable Error detected in %s", ErrSpace);
+ }
+
+
+ HalpSableReportFatalError();
+
+ return FALSE;
+
+}
+
+ULONG
+HalpTranslateSyndromToECC(
+ IN OUT PULONG Syndrome
+ )
+/*++
+
+Routine Description:
+
+ Translate the syndrome to a particular bit. If the syndrome indicates
+ a data bit, then return 0, if a check bit, then return 1.
+
+ In the place of the incoming syndrome, stuff the resulting bit.
+
+Arguments:
+
+ Syndrome Pointer to the syndrome
+
+Return Value:
+
+ 0 for data bit
+ 1 for check bit
+
+--*/
+{
+
+ static UCHAR SyndromeToECCTable[0xff] = {0, };
+ static BOOLEAN SyndromeToECCTableInitialized = FALSE;
+
+ ULONG Temp = *Syndrome;
+
+ //
+ // Initialize the table.
+ //
+
+ if (!SyndromeToECCTableInitialized) {
+ SyndromeToECCTableInitialized = TRUE;
+
+ //
+ // fill in the table
+ //
+
+ SyndromeToECCTable[0x1] = 0;
+ SyndromeToECCTable[0x2] = 1;
+ SyndromeToECCTable[0x4] = 2;
+ SyndromeToECCTable[0x8] = 3;
+ SyndromeToECCTable[0x10] = 4;
+ SyndromeToECCTable[0x20] = 5;
+ SyndromeToECCTable[0x40] = 6;
+
+ SyndromeToECCTable[0x4F] = 0;
+ SyndromeToECCTable[0x4A] = 1;
+ SyndromeToECCTable[0x52] = 2;
+ SyndromeToECCTable[0x54] = 3;
+ SyndromeToECCTable[0x57] = 4;
+ SyndromeToECCTable[0x58] = 5;
+ SyndromeToECCTable[0x5B] = 6;
+ SyndromeToECCTable[0x5D] = 7;
+ SyndromeToECCTable[0x23] = 8;
+ SyndromeToECCTable[0x25] = 9;
+ SyndromeToECCTable[0x26] = 10;
+ SyndromeToECCTable[0x29] = 11;
+ SyndromeToECCTable[0x2A] = 12;
+ SyndromeToECCTable[0x2C] = 13;
+ SyndromeToECCTable[0x31] = 14;
+ SyndromeToECCTable[0x34] = 15;
+ SyndromeToECCTable[0x0E] = 16;
+ SyndromeToECCTable[0x0B] = 17;
+ SyndromeToECCTable[0x13] = 18;
+ SyndromeToECCTable[0x15] = 19;
+ SyndromeToECCTable[0x16] = 20;
+ SyndromeToECCTable[0x19] = 21;
+ SyndromeToECCTable[0x1A] = 22;
+ SyndromeToECCTable[0x1C] = 23;
+ SyndromeToECCTable[0x62] = 24;
+ SyndromeToECCTable[0x64] = 25;
+ SyndromeToECCTable[0x67] = 26;
+ SyndromeToECCTable[0x68] = 27;
+ SyndromeToECCTable[0x6B] = 28;
+ SyndromeToECCTable[0x6D] = 29;
+ SyndromeToECCTable[0x70] = 30;
+ SyndromeToECCTable[0x75] = 31;
+ }
+
+ *Syndrome = SyndromeToECCTable[Temp];
+
+ if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 ||
+ Temp == 0x10 || Temp == 0x20 || Temp == 0x40) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+VOID
+HalpCPUCorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on a CPU
+ module -- the only thing this can be is a Bcache error. Populate the
+ correctable error frame.
+
+Arguments:
+
+ PhysicalSlot Physical CPU slot number
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ GAMMA_ESREG_CSR1 CSR1;
+ GAMMA_EVBCER_CSR4 CSR4;
+ ULONG CERBase;
+
+ //
+ // Get CPU's bcache CSRs
+ //
+
+ CERBase = HalpCPUSlot[PhysicalSlot];
+ CSR1.all = READ_CPU_REGISTER((PVOID)(CERBase | 0x1));
+ CSR4.all = READ_CPU_REGISTER((PVOID)(CERBase | 0x4));
+
+ //
+ // Set the bits, one by one
+ //
+
+ CorrPtr->Flags.AddressSpace = 1; // memory space
+ CorrPtr->Flags.PhysicalAddressValid = 0;
+ CorrPtr->Flags.ErrorBitMasksValid = 0;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.ProcessorInformationValid = 1;
+ CorrPtr->Flags.SystemInformationValid = 0;
+ CorrPtr->Flags.ServerManagementInformationValid = 0;
+ CorrPtr->Flags.MemoryErrorSource = 2; // processor cache
+
+ CorrPtr->Flags.ScrubError = 0; // ??
+ CorrPtr->Flags.LostCorrectable = CSR4.MissedCorrectable0 |
+ CSR4.MissedCorrectable1;
+
+
+ CorrPtr->Flags.LostAddressSpace = 0;
+ CorrPtr->Flags.LostMemoryErrorSource = 0;
+
+ CorrPtr->PhysicalAddress = 0;
+ CorrPtr->DataBitErrorMask = 0;
+ CorrPtr->CheckBitErrorMask = 0;
+
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheLevelValid = 0;
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheBoardValid = 0;
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheSimmValid = 0;
+
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.ProcessorType = 21064;
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.ProcessorRevision = 0;
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.PhysicalProcessorNumber =
+ SlotToPhysicalCPU[PhysicalSlot];
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.LogicalProcessorNumber = 0;
+ CorrPtr->ErrorInformation.CacheError.CacheLevel = 0;
+ CorrPtr->ErrorInformation.CacheError.CacheSimm = 0;
+ CorrPtr->ErrorInformation.CacheError.TransferType = 0;
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // wkc fix -- get info from the CER
+ //
+
+}
+
+
+VOID
+HalpMemoryCorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on a memory
+ module. Populate the correctable error frame.
+
+Arguments:
+
+ PhysicalSlot The physical slot of the falting board
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+ SGL_MEM_CSR0 CSR;
+ ULONG CSRBase;
+
+ //
+ // Get MEM modules base addr
+ //
+
+ CSRBase = HalpMemorySlot[PhysicalSlot];
+
+ CSR.all = READ_MEM_REGISTER((PVOID)CSRBase);
+
+ //
+ // Set the bits, one by one
+ //
+
+ CorrPtr->Flags.AddressSpace = 0; // ??
+ CorrPtr->Flags.PhysicalAddressValid = 0;
+ CorrPtr->Flags.ErrorBitMasksValid = 0;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+ CorrPtr->Flags.SystemInformationValid = 0;
+ CorrPtr->Flags.ServerManagementInformationValid = 0;
+ CorrPtr->Flags.MemoryErrorSource = 4; // processor memory
+
+ CorrPtr->PhysicalAddress = 0;
+ CorrPtr->DataBitErrorMask = 0;
+ CorrPtr->CheckBitErrorMask = 0;
+
+ CorrPtr->ErrorInformation.MemoryError.Flags.MemoryBoardValid = 0;
+ CorrPtr->ErrorInformation.MemoryError.Flags.MemorySimmValid = 0;
+
+ CorrPtr->ErrorInformation.MemoryError.MemoryBoard = PhysicalSlot;
+ CorrPtr->ErrorInformation.MemoryError.MemorySimm = 0;
+ CorrPtr->ErrorInformation.MemoryError.TransferType = 0;
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // wkc fix -- get info from the CSR
+ //
+
+}
+
+
+VOID
+HalpT2CorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on the CBus.
+ Populate the correctable error frame.
+
+Arguments:
+
+ Physical Slot
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // This should never be called, because there are no correctable T2 errors.
+ //
+
+}
+
+
+
+ULONG
+HalpCheckCPUForError(
+ IN OUT PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the CPU module CSR for BCACHE error.
+
+Arguments:
+
+ Slot The return value for the slot if an error is found
+
+Return Value:
+
+ Either CorrectableError or NoError
+
+--*/
+{
+
+ ULONG i;
+
+ GAMMA_EVBCER_CSR4 CSR4;
+ ULONG BaseCSRQVA;
+
+ //
+ // Run through the CPU modules looking for a correctable
+ // error.
+ //
+
+ for (i=0; i<4; i++) {
+
+ //
+ // If a cpu board is present, then use the QVA stored in that
+ // location -- if a CPU module is not present, then the value is 0.
+ //
+
+ if (HalpCPUSlot[i] != 0) {
+
+ BaseCSRQVA = HalpCPUSlot[i];
+
+ //
+ // Read the backup cache correctable error register (CSR1)
+ //
+
+ CSR4.all = READ_CPU_REGISTER((PVOID)(BaseCSRQVA | 0x4));
+
+ //
+ // Check the two correctable error bits -- if one at least one
+ // is set, then go off and build the frame and jump directly
+ // to the correctable error flow.
+ //
+
+ if (CSR4.MissedCorrectable0 ||
+ CSR4.MissedCorrectable1 ||
+ CSR4.CorrectableError0 ||
+ CSR4.CorrectableError1) {
+
+ *Slot = i;
+ return CorrectableError;
+ }
+ }
+ }
+
+ return NoError;
+}
+
+
+ULONG
+HalpCheckMEMForError(
+ PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the Memory module CSR for errors.
+
+Arguments:
+
+ Slot The return value for the slot if an error is found
+
+Return Value:
+
+ Either CorrectableError or NoError or UncorrectableError
+
+--*/
+{
+
+ SGL_MEM_CSR0 CSR;
+ ULONG i;
+ ULONG BaseCSRQVA;
+
+ //
+ // If we have fallen through the CPU correctable errors,
+ // check the Memory boards
+ //
+
+ for (i=0; i<4; i++) {
+
+ //
+ // If a memory board is present, then the value is the QVA of CSR0
+ // on that memory board. If not present, the value is 0.
+ //
+
+ if (HalpMemorySlot[i] != 0) {
+
+ BaseCSRQVA = HalpMemorySlot[i];
+
+ CSR.all = READ_MEM_REGISTER((PVOID)BaseCSRQVA);
+
+ //
+ // Sync Errors are NOT part of the summary registers (bogus
+ // if you ask me....), but check them first.
+ //
+
+ if (CSR.SyncError1 || CSR.SyncError2) {
+ *Slot = i;
+ return CorrectableError;
+ }
+
+ //
+ // The error summary bit indicates if ANY error bits are
+ // lit. If no error on this module, then skip to the next one.
+ //
+
+ if (CSR.ErrorSummary1 == 0 && CSR.ErrorSummary2 == 0) {
+ continue;
+ }
+
+ //
+ // Because one of the summary registers are set, then this memory
+ // module has indicated an error. Check the correctable bits. If
+ // any are set, then build a correctable error frame, otherwise,
+ // drop back 20 and punt.
+ //
+
+ *Slot = i;
+
+ if (CSR.EDCCorrectable1 || CSR.EDCCorrectable2 ||
+ CSR.EDCMissdedCorrectable1 || CSR.EDCMissdedCorrectable2) {
+
+ return CorrectableError;
+ } else {
+ return UncorrectableError;
+ }
+ }
+ }
+
+ return NoError;
+
+}
+
+
+ULONG
+HalpCheckT2ForError(
+ PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the System Host Chips for Errors.
+
+Arguments:
+
+ Slot The return value for the QVA of the T2 of an error is returned.
+
+Return Value:
+
+ Either CorrectableError or NoError or UncorrectableError
+
+--*/
+{
+ T2_CERR1 Cerr1;
+
+ *Slot = 0;
+
+ //
+ // Run through the T2 chips (OK, they may be T2, or T3 or T4...)
+ // and check for correctable errors
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+ return UncorrectableError;
+ }
+
+ //
+ // There are no uncorrectable CBus errors
+ //
+
+ return NoError;
+}
+
+
+VOID
+HalpSableErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an error interrupt from the
+ T2 on a Sable system. This function determines if the error is
+ fatal or recoverable and if recoverable performs the recovery and
+ error logging.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ static ERROR_FRAME Frame;
+
+ ULONG DetectedError;
+
+ ULONG Slot = 0;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+ PCORRECTABLE_ERROR CorrPtr;
+ PBOOLEAN ErrorlogBusy;
+ ERROR_FRAME TempFrame;
+
+ //
+ // Get the interrupt information
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Find out if a CPU module had any errors
+ //
+
+ DetectedError = HalpCheckCPUForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpCPUCorrectableError(Slot, CorrPtr);
+ goto CError;
+ }
+
+ //
+ // Find out if Memory module had any errors
+ //
+
+ DetectedError = HalpCheckMEMForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpMemoryCorrectableError(Slot, CorrPtr);
+ goto CError;
+ }
+
+
+ //
+ // Find out if the T2's had any errors
+ //
+
+ DetectedError = HalpCheckT2ForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpT2CorrectableError(Slot, CorrPtr);
+ goto CError;
+ } else {
+ return; // no error?
+ }
+
+CError:
+
+ //
+ // Build the rest of the error frame
+ //
+
+ SGLCorrectedErrors += 1;
+
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = SGLCorrectedErrors;
+ TempFrame.PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ // Then add our platform info...
+ //
+
+ if (!*ErrorlogBusy) {
+
+ // wkc fix....
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+ //
+ // Clear the error and return (wkcfix -- clear now? or in routines).
+ //
+
+ return;
+
+
+UCError: // wkcfix
+
+ //
+ // The interrupt indicates a fatal system error.
+ // Display information about the error and shutdown the machine.
+ //
+
+ HalpSableReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ 0 );
+}
+
+
+VOID
+HalpSableReportFatalError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error on
+ a Sable system. Currently, only the T2 error registers - CERR1 and PERR1
+ are used to interpret the error.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ ULONGLONG Cerr2;
+ ULONGLONG Cerr3;
+ UCHAR OutBuffer[MAX_ERROR_STRING];
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+ RATTLER_ESREG_CSR Esreg;
+ PCHAR parityErrString = NULL;
+ PEXTENDED_ERROR exterr;
+
+ //
+ // Begin the error output by acquiring ownership of the display
+ // and printing the dreaded banner.
+ //
+
+ if(PUncorrectableError) {
+ exterr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ parityErrString = PUncorrectableError->UncorrectableFrame.ErrorString;
+ }
+
+ HalAcquireDisplayOwnership(NULL);
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // Read both of the error registers. It is possible that more
+ // than one error was reported simulataneously.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ //
+ // Read all of the relevant error address registers.
+ //
+
+ Cerr2 = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr2 );
+ Cerr3 = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr3 );
+
+ Perr2.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr2 );
+
+ //
+ // Interpret any errors from CERR1.
+ //
+
+ sprintf( OutBuffer, "T2 CERR1 = 0x%Lx\n", Cerr1.all );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.UncorrectableReadError == 1 ){
+
+ sprintf( OutBuffer,
+ "Uncorrectable read error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.NoAcknowledgeError == 1 ){
+
+ sprintf( OutBuffer,
+ "No Acknowledgement Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.CommandAddressParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( OutBuffer,
+ "Command Address Parity Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.CaParityErrorLw3 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 3\n");
+ HalDisplayString( "C/A Parity Error on longword 3\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw2 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 2\n" );
+ HalDisplayString( "C/A Parity Error on longword 2\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw1 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 1\n");
+ HalDisplayString( "C/A Parity Error on longword 1\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw0 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 0\n" );
+ HalDisplayString( "C/A Parity Error on longword 0\n" );
+ }
+
+ }
+
+ if( Cerr1.MissedCommandAddressParity == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( parityErrString,
+ "Missed C/A Parity Error\n" );
+ HalDisplayString( "Missed C/A Parity Error\n" );
+ }
+
+ if( (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( OutBuffer,
+ "T2 detected Data Parity error, CBUS Address = 0x%Lx16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "T2 was %s on error transaction\n",
+ Cerr1.ResponderWriteDataParityError == 1 ? "responder" :
+ "commander" );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.DataParityErrorLw0 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 0\n" );
+ HalDisplayString( "Data Parity on longword 0\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw1 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 1\n" );
+ HalDisplayString( "Data Parity on longword 1\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw2 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 2\n");
+ HalDisplayString( "Data Parity on longword 2\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw3 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 3\n" );
+ HalDisplayString( "Data Parity on longword 3\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw4 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 4\n" );
+ HalDisplayString( "Data Parity on longword 4\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw5 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 5\n" );
+ HalDisplayString( "Data Parity on longword 5\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw6 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 6\n" );
+ HalDisplayString( "Data Parity on longword 6\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw7 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 7\n" );
+ HalDisplayString( "Data Parity on longword 7\n" );
+ }
+
+ } //(Cerr1.ResponderWriteDataParityError == 1) || ...
+
+
+ if( Cerr1.MissedRspWriteDataParityError == 1 ){
+ HalDisplayString( "Missed data parity error as responder\n" );
+ }
+
+ if( Cerr1.MissedReadDataParityError == 1 ){
+ HalDisplayString( "Missed data parity error as commander\n" );
+ }
+
+
+ if( Cerr1.CmdrWriteDataParityError == 1 ){
+
+ sprintf( OutBuffer,
+ "Commander Write Parity Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.BusSynchronizationError == 1 ){
+
+ sprintf( OutBuffer,
+ "Bus Synchronization Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.InvalidPfnError == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid PFN for scatter/gather, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Interpret any errors from T2 PERR1.
+ //
+
+ sprintf( OutBuffer, "PERR1 = 0x%Lx\n", Perr1.all );
+ HalDisplayString( OutBuffer );
+
+ if( Perr1.WriteDataParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (slave) detected write parity error\n");
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+ sprintf( OutBuffer,
+ "T2 (slave) detected write parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.AddressParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (slave) detected address parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+ sprintf( OutBuffer,
+ "T2 (slave) detected address parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ReadDataParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (master) detected read parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "T2 (master) detected read parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Participant asserted PERR#, parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "Participant asserted PERR#, parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Slave asserted SERR#, parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "Slave asserted SERR#, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.DeviceTimeoutError == 1 ){
+
+ sprintf( OutBuffer,
+ "Device timeout error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.DeviceTimeoutError == 1 ){
+
+ HalDisplayString( "PCI NMI asserted.\n" );
+
+ }
+
+ //
+ // Interpret RATTLER errors: (GAMMA Specific)
+ //
+
+ Esreg.all =
+ READ_CPU_REGISTER(&((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Esreg);
+
+ sprintf(OutBuffer, "ESREG = 0x%Lx\n", Esreg.all);
+ HalDisplayString( OutBuffer );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halgamma/alpha/gammaio.s b/private/ntos/nthals/halgamma/alpha/gammaio.s
new file mode 100644
index 000000000..d030f544e
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gammaio.s
@@ -0,0 +1,1046 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ gammaio.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Gamma system.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "gamma.h"
+#include "halalpha.h"
+
+
+// Superpage VA
+//
+// This value is used to define the base physical address from which
+// QVA's are defined.
+//
+// This value is specified as a negative number so that the value will
+// be sign extended when loaded into a register. If defined positive, the
+// assembler will prevent sign extension.
+//
+
+#define GAMMA_IO_SVA -0x3800 // negative of 0xc800
+
+.set noreorder
+
+
+ LEAF_ENTRY(WRITE_T2_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_CPU_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_MEM_REGISTER)
+
+/*++
+Routine Description:
+ Writes a T2 or a CPU CSR.
+
+Arguments:
+ a0 QVA of register to be written.
+ a1 Longword to be written.
+
+Return Value:
+ None.
+--*/
+
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+ stq a1, (t0) // write the quadword
+ mb // order the write
+ mb
+ ret zero, (ra)
+
+2:
+ BREAK_DEBUG_STOP // Bad Qva
+ ret zero, (ra)
+
+ .end WRITE_T2_REGISTER
+
+
+
+ LEAF_ENTRY(READ_T2_REGISTER)
+
+ ALTERNATE_ENTRY(READ_CPU_REGISTER)
+
+ ALTERNATE_ENTRY(READ_MEM_REGISTER)
+
+/*++
+
+Routine Description:
+ Read a T2 or CPU CSR.
+
+Arguments:
+ a0 QVA of register to be read.
+
+Return Value:
+ The quadword read from the register.
+
+--*/
+
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+//
+// Save Address of Config space access for the machine check handler:
+// (This isn't a config space access, but the exception handling is identical)
+//
+
+ lda t1, HalpConfigIoAccess
+ lda t4, CPUCsrRead // machine check return address
+ stl t4, 0(t1)
+ mb // commit the store before reading
+
+ DISABLE_INTERRUPTS // don't allow ints before Mcheck
+
+CPUCsrRead:
+
+ ldq v0, (t0) // read the register
+ mb // synchronize
+ mb //
+
+
+ stl zero, 0(t1) // Restore HalpConfigIoAccess
+
+ ENABLE_INTERRUPTS // Interrupts OK after Mcheck
+
+ ret zero, (ra)
+
+2:
+ BREAK_DEBUG_STOP // Bad Qva
+ ret zero, (ra)
+
+ .end READ_T2_REGISTER
+
+
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the QVA for the Configuration Cycle Type register within the
+// IOC.
+//
+
+// PASS 1 SABLE SUPPORT
+
+#define T2_HAE0_2_QVA (0xbc700008)
+#define T2_HAE02_CYCLETYPE_SHIFT 30
+#define T2_HAE02_CYCLETYPE_MASK 0xc0000000
+
+// PASS 2 SABLE SUPPORT
+
+#define T2_HAE03_CYCLETYPE_SHIFT 30
+#define T2_HAE03_CYCLETYPE_MASK 0xc0000000
+#define T2_HAE0_3_QVA (0xbc700012)
+#define T2_CONFIG_ADDR_QVA (0xbc800000)
+
+//
+// T4 Support:
+//
+
+#define T4_HAE0_3_QVA (0xbc780012)
+#define T4_CONFIG_ADDR_QVA (0xbcc00000)
+
+
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved ConfigurationAddress
+CfgA1: .space 8 // saved ConfigurationData
+CfgA2: .space 8 // padding for 16 byte alignment
+CfgFrameLength:
+
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 T2 the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 T2
+
+//
+// PASS 2 T2 or XIO access:
+// Cycle type are the only bits in HAE0_3 register
+//
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// Determine whether access is to T2 or T4 space:
+// Isolate the Base address bits: bit 22 indicates T4 space access
+//
+
+ ldil t0, T4_CONFIG_ADDR_QVA // check for QVA in T4 space
+ and t0, a0, t1 // isolate QVA base address
+
+ ldil a0, T2_HAE0_3_QVA // address of T2 space HAE0_3
+ xor t0, t1, t0 // T4 address space ? (bit 22 set)
+
+ ldil t1, T4_HAE0_3_QVA // load address of T4 HAE register
+ cmoveq t0, t1, a0 // if in T4 space, update a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type in position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual read
+
+//
+// PASS 1 T2
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1// put cycle type in position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte enables
+
+//
+// Save Address of Config space address for the machine check handler:
+//
+
+ lda t1, HalpConfigIoAccess
+ lda t4, CfgUcharRead // machine check return address
+ stl t4, 0(t1)
+ mb // commit the store before reading
+
+ DISABLE_INTERRUPTS // don't allow ints before Mcheck
+
+CfgUcharRead:
+
+ ldl v0, (t0) // read the longword
+ extbl v0, t3, v0 // return byte from requested lane
+ // also, consume loaded value
+ // to cause a pipeline stall
+ mb // Gamma requires MBs or the
+ mb // machine check may happen
+ // much later
+
+ stl zero, 0(t1) // Restore HalpConfigIoAccess
+
+ ENABLE_INTERRUPTS // Interrupts OK after Mcheck
+
+3: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 T2 the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 T2
+
+//
+// PASS 2 T2 or XIO access:
+// Merge the configuration cycle type into the HAE0_3 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// Determine whether access is to T2 or T4 space:
+// Isolate the Base address bits: bit 22 indicates T4 space access
+//
+
+ ldil t0, T4_CONFIG_ADDR_QVA // check for QVA in T4 space
+ and t0, a0, t1 // isolate QVA base address
+
+ ldil a0, T2_HAE0_3_QVA // address of HAE0_3
+ xor t0, t1, t0 // T4 address space ? (bit 22 set)
+
+ ldil t1, T4_HAE0_3_QVA // load address of T4 HAE register
+ cmoveq t0, t1, a0 // if in T4 space, update a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f
+
+//
+// Merge the configuration cycle type into the HAE0_3 register within
+// the T2.
+//
+
+1:
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t0) // write the configuration byte
+ mb // synchronize
+ mb // synchronize
+
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 T2 the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 T2
+
+//
+// PASS 2 T2 or XIO access:
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// Determine whether access is to T2 or T4 space:
+// Isolate the Base address bits: bit 22 indicates T4 space access
+//
+
+ ldil t0, T4_CONFIG_ADDR_QVA // check for QVA in T4 space
+ and t0, a0, t1 // isolate QVA base address
+
+ ldil a0, T2_HAE0_3_QVA // address of HAE0_3
+ xor t0, t1, t0 // T4 address space ? (bit 22 set)
+
+ ldil t1, T4_HAE0_3_QVA // load address of T4 HAE register
+ cmoveq t0, t1, a0 // if in T4 space, update a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual io
+
+//
+// Pass 1 T2
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+2:
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+//
+// Save Address of Config space address for the machine check handler:
+//
+ lda t1, HalpConfigIoAccess
+ lda t4, CfgShortRead // machine check return address
+ stl t4, 0(t1)
+ mb // commit the store before reading
+
+ DISABLE_INTERRUPTS // don't allow ints before Mcheck
+
+CfgShortRead:
+
+ ldl v0, (t0) // read the longword
+ extwl v0, t3, v0 // return word from requested lanes
+ // also, consume loaded value
+ // to cause a pipeline stall
+ mb // Gamma requires MBs or the
+ mb // machine check may happen
+ // much later
+
+ stl zero, 0(t1) // restore HalpConfigIoAccess
+
+ ENABLE_INTERRUPTS // Interrupts OK after Mcheck
+
+3:
+
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// USHORT ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 T2 the configuration
+// cycle type is in different registers
+//
+
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 T2
+
+//
+// PASS 2 T2 or XIO access:
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// Determine whether access is to T2 or T4 space:
+// Isolate the Base address bits: bit 22 indicates T4 space access
+//
+
+ ldil t0, T4_CONFIG_ADDR_QVA // check for QVA in T4 space
+ and t0, a0, t1 // isolate QVA base address
+
+ ldil a0, T2_HAE0_3_QVA // address of HAE0_3
+ xor t0, t1, t0 // T4 address space ? (bit 22 set)
+
+ ldil t1, T4_HAE0_3_QVA // load address of T4 HAE register
+ cmoveq t0, t1, a0 // if in T4 space, update a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual transfer
+
+
+//
+// Pass 1 T2
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1, t3, t4 // put data to appropriate lane
+ stl t4, (t0) // read the longword
+ mb // synchronize
+ mb // synchronize
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 T2 the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 T2
+
+//
+// PASS 2 T2 or XIO access:
+// Cycle type are the only bits in HAE0_3 register
+//
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// Determine whether access is to T2 or T4 space:
+// Isolate the Base address bits: bit 22 indicates T4 space access
+//
+
+ ldil t0, T4_CONFIG_ADDR_QVA // check for QVA in T4 space
+ and t0, a0, t1 // isolate QVA base address
+
+ ldil a0, T2_HAE0_3_QVA // address of HAE0_3
+ xor t0, t1, t0 // T4 address space ? (bit 22 set)
+
+ ldil t1, T4_HAE0_3_QVA // load address of T4 HAE register
+ cmoveq t0, t1, a0 // if in T4 space, update a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type in position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual read
+
+//
+// PASS 1 T2
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1// put cycle type in position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+2:
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+//
+// Save Address of Config space address for the machine check handler:
+//
+
+ lda t1, HalpConfigIoAccess
+ lda t4, CfgUlongRead // machine check return address
+ stl t4, 0(t1)
+ mb // commit the store before reading
+
+ DISABLE_INTERRUPTS // don't take interrupt before MCHK
+
+CfgUlongRead:
+
+ ldl v0, (t0) // read the longword
+ bis v0, zero, t4 // consume loaded value to cause
+ // a pipeline stall
+ mb // Gamma requires MBs or the
+ mb // machine check may happen
+ // much later
+
+ stl zero, 0(t1) // restore HalpConfigIoAccess
+
+ ENABLE_INTERRUPTS // Mcheck has occurred: allow ints
+
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 T2 the configuration
+// cycle type is in different registers
+//
+
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 T2
+
+//
+// PASS 2 T2 or XIO access:
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// Determine whether access is to T2 or T4 space:
+// Isolate the Base address bits: bit 22 indicates T4 space access
+//
+
+ ldil t0, T4_CONFIG_ADDR_QVA // check for QVA in T4 space
+ and t0, a0, t1 // isolate QVA base address
+
+ ldil a0, T2_HAE0_3_QVA // address of HAE0_3
+ xor t0, t1, t0 // T4 address space ? (bit 22 set)
+
+ ldil t1, T4_HAE0_3_QVA // load address of T4 HAE register
+ cmoveq t0, t1, a0 // if in T4 space, update a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual transfer
+
+
+//
+// Pass 1 T2
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, GAMMA_IO_SVA // 0xffff ffff ffff c800
+ sll t4, 28, t4 // 0xffff fc80 0000 0000
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // synchronize
+ mb // synchronize
+
+3: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
diff --git a/private/ntos/nthals/halgamma/alpha/gammartc.h b/private/ntos/nthals/halgamma/alpha/gammartc.h
new file mode 100644
index 000000000..4082975a5
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gammartc.h
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the sable HAL directory
+//
+
+#include "..\halsable\alpha\sablertc.h"
+
diff --git a/private/ntos/nthals/halgamma/alpha/gminitnt.c b/private/ntos/nthals/halgamma/alpha/gminitnt.c
new file mode 100644
index 000000000..b66c25240
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gminitnt.c
@@ -0,0 +1,1321 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ gminitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ a Sable system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+ Steve Jenness 28-Oct-1993 (Sable)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "gammartc.h"
+#include "gamma.h"
+#include "halpcsl.h"
+#include "pci.h"
+#include "pcip.h"
+#include "isaaddr.h"
+#include "eisa.h"
+#include "iousage.h"
+#include "axp21164.h"
+#include "siintsup.h"
+#include "lyintsup.h"
+#include "xiintsup.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+
+//
+// Don't change these values unless you know exactly what you are doing
+//
+#define HAE0_1_REGISTER_VALUE 0x0 // to address SPARSE PCI MEMORY
+#define HAE0_2_REGISTER_VALUE 0x0 // to address PCI IO space
+#define HAE0_3_REGISTER_VALUE 0x0 // For PCI config cycle type
+#define HAE0_4_REGISTER_VALUE 0x0 // to address DENCE PCI Memory
+
+ULONG HalpMemorySlot[4] = { (ULONG)GAMMA_MEM0_CSRS_QVA,
+ (ULONG)GAMMA_MEM1_CSRS_QVA,
+ (ULONG)GAMMA_MEM2_CSRS_QVA,
+ (ULONG)GAMMA_MEM3_CSRS_QVA };
+
+ULONG HalpCPUSlot[4] = { (ULONG)SABLE_CPU0_CSRS_QVA, // we overload SABLE
+ (ULONG)SABLE_CPU1_CSRS_QVA, // with GAMMA values
+ (ULONG)SABLE_CPU2_CSRS_QVA,
+ (ULONG)SABLE_CPU3_CSRS_QVA };
+
+//
+// Prototypes
+//
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ );
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpSenseCBusSlots(
+ VOID
+ );
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+// Block out 8Mb to 144MB
+//
+
+ADDRESS_USAGE
+SablePCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, (__32MB - __8MB), // Start=8MB; Length=24MB
+ 0,0
+ }
+};
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define global for saving the T2 Chipset's version
+//
+
+ULONG T2VersionNumber;
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+//
+// Is the external I/O module present?
+//
+
+BOOLEAN HalpXioPresent = FALSE;
+
+#endif
+
+//
+// Is this a Lynx platform?
+//
+
+BOOLEAN HalpLynxPlatform = FALSE;
+
+//
+// How many processors are ready to run?
+//
+
+ULONG HalpProcessors = 0;
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Sable
+//
+// IRQ_H[0] = Correctable Error
+// IRQ_H[1] = PCI0/Eisa0
+// IRQ_H[2] = Clock/IPI
+// IRQ_H[3] = PCI1/Eisa1 // This vector has been changed to shadow
+// // the IPI vector value
+//
+
+// smjfix - This comment doesn't match what is currently happening in the
+// code. Plus it isn't clear that EISA and ISA entries can
+// be split apart.
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+// smjfix - Why is this here? It is a compile time constant for the
+// platform. This is useful only if one HAL is being used
+// for multiple platforms and is being passed from the firmware
+// or detected.
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpClearInterrupts(
+ );
+
+//
+// The correctable interrupt handler:
+//
+VOID
+HalpGammaCorrectableInterrupt(
+ VOID
+ );
+
+//
+// The Machine check Interrupt handler:
+//
+VOID
+HalpGammaErrorInterrupt(
+ VOID
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Sable system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ RATTLER_CONFIG_CSR Config;
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ PKPRCB Prcb;
+ UCHAR Priority;
+ ULONG Vector;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize interrupt handling for the primary processor and
+ // any system-wide interrupt initialization.
+ //
+
+ if( Prcb->Number == GAMMA_PRIMARY_PROCESSOR ){
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC.
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+#if !defined(NT_UP)
+
+ //
+ // Connect the interprocessor interrupt handler.
+ //
+
+ PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = HalpGammaIpiInterrupt;
+
+#endif //NT_UP
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Initialize SIO interrupts.
+ //
+
+ if( HalpLynxPlatform ){
+
+ HalpInitializeLynxSioInterrupts();
+
+ } else {
+
+ HalpInitializeSableSioInterrupts();
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the XIO module is present, initialize the XIO interrupt
+ // controller, as well.
+ //
+
+ if( HalpXioPresent ){
+
+ HalpInitializeXioInterrupts();
+
+ }
+
+#endif
+
+ //
+ // Disable the HALT interrupts.
+ //
+
+ {
+ Config.all = READ_CPU_REGISTER(
+ &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg
+ );
+
+ Config.EnableSystemInterrupts = 0x09; // Enable Mchk & IPI
+
+ //
+ // If the XIO module is present, but there are less than 2
+ // processors in the system, then the primary processor must
+ // handle both SIO and XIO interrupts. Otherwise, the primary
+ // handles the SIO interrupts, and the secondary processor
+ // handles the XIO interrupts (if it is present).
+ //
+
+ Config.EnableIoInterrupts = 0x1; // Enable CIRQ<0>
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent && HalpProcessors < 2 ){
+
+ Config.EnableAlternateIoInts = 0x2; // Enable CIRQ<1>
+
+ } else {
+
+#endif
+
+ Config.EnableAlternateIoInts = 0x0; // Disable CIRQ<1>
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+ }
+#endif
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg,
+ Config.all
+ );
+
+ }
+
+ //
+ // Initialize the 21164 interrupts on the current processor
+ // before enabling the individual interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = HalpGammaDispatch;
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = HalpGammaCorrectableInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = HalpGammaErrorInterrupt;
+
+ //
+ // Allow the interrupts to occur:
+ //
+
+ HalpStart21164Interrupts();
+
+ return TRUE;
+
+ } //end if Prcb->Number == GAMMA_PRIMARY_PROCESSOR
+
+
+#if !defined(NT_UP)
+
+ //
+ // Initialize interrupts for the current, secondary processor.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ //
+ // Disable the HALT interrupts.
+ // Disable the Device and Machine check interrupts for secondaries:
+ //
+
+ {
+ Config.all = READ_CPU_REGISTER(
+ &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg
+ );
+
+ Config.EnableSystemInterrupts = 0x08; // Enable IPI only
+
+ //
+ // If the XIO module is present, and this is the secondary
+ // processor, enable XIO interrupts on this processor. Otherwise,
+ // disable all I/O interrupt.
+ //
+
+ Config.EnableIoInterrupts = 0x0; // Disable CIRQ<0>
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent && Prcb->Number == GAMMA_SECONDARY_PROCESSOR ){
+
+ Config.EnableAlternateIoInts = 0x2; // Enable CIRQ<1>
+
+ } else {
+
+#endif
+
+ Config.EnableAlternateIoInts = 0x0; // Disable CIRQ<1>
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+ }
+#endif
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg,
+ Config.all
+ );
+ }
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the XIO module is present and this is the secondary processor,
+ // enable XIO interrupts on the secondary processor.
+ //
+
+ if( HalpXioPresent && Prcb->Number == GAMMA_SECONDARY_PROCESSOR ){
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = HalpGammaDispatch;
+
+ }
+
+#endif
+
+ //
+ // Connect the clock and ipi interrupt handlers.
+ // jnfix - For now these are the only interrupts we will accept on
+ // jnfix - secondary processors. Later we will add PCI interrupts
+ // jnfix - and the error interrupts.
+ //
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpSecondaryClockInterrupt;
+ PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = HalpGammaIpiInterrupt;
+
+ //
+ // Allow the interrupts to occur:
+ //
+
+ HalpStart21164Interrupts();
+
+#endif //NT_UP
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function clears all pending interrupts on the Gamma.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ RATTLER_SIC_CSR Sicr; // system interrupt clear register
+
+ Sicr.all = 0;
+ Sicr.SystemBusErrorInterruptClear0 = 1; // (0)
+ Sicr.SystemBusErrorInterruptClear1 = 1; // (32)
+ Sicr.IntervalTimerInterrupt = 1; // (36)
+ Sicr.SystemEventClear = 1; // (40)
+ Sicr.NodeHaltInterruptClear = 1; // (44)
+ Sicr.InterprocessorInterruptClear = 1; // (48)
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr,
+ Sicr.all
+ );
+
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for Sable
+ via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+// smjfix - Where is this referenced?
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For Sable, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Sable is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize machine check handling for Sable.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Sable-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies the loader block passed in via the OsLoader.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+ PRESTART_BLOCK RestartBlock;
+ ULONGLONG Value;
+ T2_IOCSR Iocsr;
+
+ Prcb = PCR->Prcb;
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR) {
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Determine how many processors are ready to run. We use
+ // this information to decide whether to split SIO/XIO
+ // interrupts across two processors or not.
+ //
+
+#ifdef NT_UP
+
+ HalpProcessors = 1;
+
+#else
+
+ HalpProcessors = 0;
+
+ for( RestartBlock = SYSTEM_BLOCK->RestartBlock;
+ RestartBlock != NULL;
+ RestartBlock = RestartBlock->NextRestartBlock ){
+
+ if( RestartBlock->BootStatus.ProcessorReady ){
+
+ HalpProcessors++;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Initialize the performance counter.
+ //
+
+ HalCalibratePerformanceCounter( NULL );
+
+
+ //
+ // Parse the loader block - this sets global for PCI parity check
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish Error Handler to pick up PCI parity changes
+ //
+
+ HalpEstablishErrorHandler();
+
+ //
+ // Determine the T2 Chipset's Version Number. Save Version in Global.
+ //
+ // T2VersionNumber Pass
+ //
+ // 000 1
+ // 001 2
+ //
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T2_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+ T2VersionNumber = Iocsr.T2RevisionNumber;
+
+ HalpInitializeHAERegisters();
+
+ HalpSenseCBusSlots();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiling for the primary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ } else {
+
+ //
+ // Re-establish Error Handler to pick up PCI parity changes
+ //
+
+ HalpEstablishErrorHandler();
+
+
+ //
+ // Initialize profiling on this secondary processor.
+ //
+
+ HalpInitializeProfiler();
+
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR data;
+ RATTLER_SIC_CSR Sic;
+
+ //
+ // Acknowledge the clock interrupt in the real time clock.
+ // We don't need to do an ACK to the RTC since we're using the
+ // DS1459A RTC's square wave instead of periodic interrupt to
+ // generate the periodic clock. Each processor board has it's own
+ // periodic clock interrupt latch that needs to be cleared.
+ //
+ // This code is MP safe since the Sic is per-processor.
+
+ RtlZeroMemory( &Sic, sizeof(Sic) );
+
+ Sic.IntervalTimerInterrupt = 1;
+
+ WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)(SABLE_CPU0_CSRS_QVA))->Sicr,
+ *(PULONGLONG)&Sic );
+
+ return;
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+//
+//
+//
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the T2 chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // Set Hae0_1, Hae0_2, Hae0_3 and Hae0_4 registers
+ //
+ // IMPORTANT: IF YOU CHANGE THE VALUE OF THE HAE0_1 REGISTERS PLEASE
+ // REMEMBER YOU WILL NEED TO CHANGE:
+ //
+ // PCI_MAX_MEMORY_ADDRESS IN halalpha\sable.h
+ // SablePCIMemorySpace in this file to report holes
+ //
+
+ // SPARSE SPACE: Hae0_1
+ //
+ // We set Hae0_1 to 0MB. Which means we have the following
+ // PCI Sparse Memory addresses:
+ // 0 to 8MB VALID. Hae0_1 Not used in address translation
+ // 8 to 16MB Invalid.
+ // 16 to 32MB Invalid. Used for Isa DMA copy for above 16MB
+ // 32 to 128MB VALID. Hae0_1 used in address translation
+
+ //
+ // All invalid addresses are reported to be used by the hal.
+ // see SablePCIMemorySpace above.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1,
+ HAE0_1_REGISTER_VALUE );
+
+
+ // PCI IO SPACE: Hae0_2
+ //
+ // We set Hae0_2 to MB. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. Hae0_2 Not used in address translation
+ // 64K to 16MB VALID. Hae0_2 is used in the address translation
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2,
+ HAE0_2_REGISTER_VALUE );
+
+
+ if( T2VersionNumber != 0 ) {
+
+ // PCI CONFIG CYCLE TYPE: Hae0_3
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3,
+ HAE0_3_REGISTER_VALUE );
+
+ // PCI DENSE MEMORY: Hae0_4
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4,
+ HAE0_4_REGISTER_VALUE );
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the XIO module is present, initialize the T4's HAE
+ // registers.
+ //
+
+ if( HalpXioPresent ){
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_1,
+ HAE0_1_REGISTER_VALUE );
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_2,
+ HAE0_2_REGISTER_VALUE );
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_3,
+ HAE0_3_REGISTER_VALUE );
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_4,
+ HAE0_4_REGISTER_VALUE );
+
+ }
+
+#endif
+
+ //
+ // Report that the SPARSE SPACE mapping to the Io subsystem
+ //
+ HalpRegisterAddressUsage (&SablePCIMemorySpace);
+
+}
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1, 0 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2, 0 );
+
+ if( T2VersionNumber != 0) {
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3, 0 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4, 0 );
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpSenseCBusSlots(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function Probes the Cbus looking for slots that are filled.
+ are only 8 Cbus locations we can look at (4 memory, 4 CPU).
+
+ If we find a module, we will fill in the table at the
+ appropriate location -- if no module is found, then place a
+ zero there.
+
+Note:
+
+ This routine will machine check in an empty slot -- and is expected.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ ULONG i;
+ ULONG CSR;
+
+
+
+ for (i=0; i<4; i++) {
+ if (HalpMemorySlot[i] != 0) {
+ CSR = (ULONG)READ_MEM_REGISTER((PVOID)HalpMemorySlot[i]);
+ if (CSR == 0xffffffff) {
+ HalpMemorySlot[i] = 0;
+ }
+#if HALDBG
+ if (HalpMemorySlot[i] == 0) {
+ DbgPrint("Memory Slot %d is EMPTY\n", i);
+ } else {
+ DbgPrint("Memory Slot %d is POPULATED\n", i);
+ }
+#endif
+ }
+ }
+
+ for (i=0; i<4; i++) {
+ if (HalpCPUSlot[i] != 0) {
+ CSR = (ULONG)READ_CPU_REGISTER((PVOID)HalpCPUSlot[i]);
+ if (CSR == 0xffffffff) {
+ HalpCPUSlot[i] = 0;
+ }
+#if HALDBG
+ if (HalpCPUSlot[i] == 0) {
+ DbgPrint("CPU Slot %d is EMPTY\n", i);
+ } else {
+ DbgPrint("CPU Slot %d is POPULATED\n", i);
+ }
+#endif
+ }
+ }
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(GAMMA_UNCORRECTABLE_FRAME);
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Gamma";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halgamma/alpha/gmintr.s b/private/ntos/nthals/halgamma/alpha/gmintr.s
new file mode 100644
index 000000000..727187660
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gmintr.s
@@ -0,0 +1,99 @@
+// TITLE("Clock and Eisa Interrupt Handlers")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// gmintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for the
+// Gamma system.
+//
+// Author:
+//
+// Joe Notarangelo 29-Oct-1993
+// Steve Jenness 29-Oct-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halalpha.h"
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// VOID
+// HalpGammaIpiInterrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interprocessor
+// interrupt asserted on the current processor. This function is
+// responsible for acknowledging the interrupt and dispatching to
+// the kernel for processing.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpGammaIpiInterrupt)
+
+//
+// Acknowledge the IPI interrupt by clearing the RequestInterrupt bit
+// of the IPIR register for the current processor.
+//
+// N.B. - Clearing the RequestInterrupt bit of the IPIR is accomplished
+// by writing a zero to the register. This eliminates the need
+// to perform a read-modify-write operation but loses the state
+// of the RequestNodeHaltInterrupt bit. Currently, this is fine
+// because the RequestNodeHalt feature is not used. Were it to
+// be used in the future, then this short-cut would have to be
+// reconsidered.
+//
+// N.B. - The code to write a sable CPU register is inlined here for
+// performance.
+//
+// N.B. - The PcHalIpirSva value must reflect the location of the Ipir
+// pointer in the GAMMA_PCR structure, defined in gamma.h
+//
+
+//jnfix - define elsewhere
+#define PcHalIpirSva 0x08
+#define SicrIpiClear 0x1000000000000 // bit to write to clear IPI int
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldiq t0, SicrIpiClear // get clear bit
+ ldq v0, PcHalReserved + PcHalIpirSva(v0) // get per-processor
+ // CPU IPIR SVA
+ stq t0, (v0) // clear IPIR
+ mb // synchronize the write
+
+//
+// Call the kernel to processor the interprocessor request.
+//
+ ldl t0, __imp_KeIpiInterrupt
+ jmp zero, (t0) // call kernel to process
+
+//
+// Control is returned from KeIpiInterrupt to the caller.
+//
+
+ .end HalpGammaIpiInterrupt
+
diff --git a/private/ntos/nthals/halgamma/alpha/gmintsup.c b/private/ntos/nthals/halgamma/alpha/gmintsup.c
new file mode 100644
index 000000000..71e7096e5
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gmintsup.c
@@ -0,0 +1,217 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ gmintsup.c
+
+Abstract:
+
+ This module provides support for Gamma-specific interrupts.
+
+Author:
+
+ Steve Jenness 28-Oct-1993
+ Joe Notarangelo 28-Oct-1993
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "lyintsup.h"
+#include "siintsup.h"
+#include "xiintsup.h"
+
+BOOLEAN
+HalpGammaDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ The Sable/Gamma/Lynx system family have two sources of device
+ interrupts; the standard I/O module and the external I/O module.
+ Each I/O module generates interrupts on a seperate Cbus2 interrupt
+ line. The standard I/O module uses CIRQ<0>, and the external I/O
+ module uses CIRQ<1>. This routine calls the standard and external
+ I/O module dispatch routines as appropriate, based on the status
+ of the CIRQ<0:1> lines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Return a boolean, indicating whether the standard or external
+ I/O module interrupt dispatch routine handled the interrupt.
+
+--*/
+
+{
+ BOOLEAN ReturnValue;
+ RATTLER_SIC_CSR Sicr;
+
+ ReturnValue = FALSE;
+
+ //
+ // The SICR register contains two bits, which indicate the current
+ // status of the CIRQ<0> and CIRQ<1> lines.
+ //
+
+ Sicr.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr );
+
+ //
+ // If the standard I/O module is interrupting the processor, call
+ // the dispatch routine.
+ //
+
+ if( (Sicr.IOInterruptIRQ & 0x1) != 0 ){
+
+ if( HalpLynxPlatform ){
+
+ if( HalpLynxSioDispatch() ){
+
+ ReturnValue = TRUE;
+
+ }
+
+ } else {
+
+ if( HalpSableSioDispatch() ){
+
+ ReturnValue = TRUE;
+
+ }
+
+ }
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the external I/O module is interrupting the processor, call
+ // the dispatch routine.
+ //
+
+ if( (Sicr.IOInterruptIRQ & 0x2) != 0 ){
+
+ if( HalpXioDispatch() ){
+
+ ReturnValue = TRUE;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Return a value indicating whether either dispatch routine handled
+ // the device interrupt.
+ //
+
+ return ReturnValue;
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Gamma comes from the Dallas DS1287A real-time clock. Gamma
+ uses the Square Wave from the RTC and distributes it out of phase
+ to each of the processors. The acknowledgement of the interrupt is
+ done by clearing an interrupt latch on each processor board.
+
+ The interrupt generated directly by the RTC is not used and does not
+ need to be acknowledged.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRATTLER_CPU_CSRS CurrentCpuCsrs;
+ RATTLER_SIC_CSR Sic;
+
+
+ CurrentCpuCsrs = HAL_PCR->CpuCsrsQva;
+
+ //
+ // Acknowledge the interval timer interrupt on the current processor.
+ //
+
+ Sic.all = 0;
+ Sic.IntervalTimerInterrupt = 1;
+
+ WRITE_CPU_REGISTER( &CurrentCpuCsrs->Sicr,
+ *(PULONGLONG)&Sic );
+
+ return;
+}
+
+VOID
+HalpAcknowledgeIpiInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the interprocessor interrupt on the current processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PRATTLER_CPU_CSRS CurrentCpuCsrs;
+ RATTLER_IPIR_CSR Ipir;
+
+ CurrentCpuCsrs = HAL_PCR->CpuCsrsQva;
+
+ Ipir.all = 0;
+ Ipir.RequestInterrupt = 1;
+
+ //
+ // Acknowledge the interprocessor interrupt by clearing the
+ // RequestInterrupt bit of the IPIR register for the current processor.
+ //
+ // N.B. - Clearing the RequestInterrupt bit of the IPIR is accomplished
+ // by writing a zero to the register. This eliminates the need
+ // to perform a read-modify-write operation but loses the state
+ // of the RequestNodeHaltInterrupt bit. Currently, this is fine
+ // because the RequestNodeHalt feature is not used. Were it to
+ // be used in the future, then this short-cut would have to be
+ // reconsidered.
+ //
+
+ WRITE_CPU_REGISTER( &CurrentCpuCsrs->Iirr,
+ Ipir.all );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halgamma/alpha/gmmapio.c b/private/ntos/nthals/halgamma/alpha/gmmapio.c
new file mode 100644
index 000000000..6efb6abd0
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gmmapio.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the sable HAL directory
+//
+
+#include "..\halsable\alpha\sbmapio.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/gmsysint.c b/private/ntos/nthals/halgamma/alpha/gmsysint.c
new file mode 100644
index 000000000..5e29b8a1c
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/gmsysint.c
@@ -0,0 +1,471 @@
+// jnfix - This module needs PCI interrupt support
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ gminitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Gamma system.
+
+Author:
+
+ Joe Notarangelo 29-Oct-1993
+ Steve Jenness 29-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "gamma.h"
+#include "siintsup.h"
+#include "lyintsup.h"
+#include "xiintsup.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+extern ULONG HalpProcessors;
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire the system interrupt
+ // lock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21164.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21164)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21164)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ break;
+
+ //
+ // Performance counter 2 interrupt (internal to 21164)
+ //
+
+ case PC2_VECTOR:
+ case PC2_SECONDARY_VECTOR:
+
+ break;
+
+ default:
+
+ if( Irql == DEVICE_LEVEL ){
+
+ if( HalpLynxPlatform ){
+
+ HalpDisableLynxSioInterrupt( Vector );
+
+ } else {
+
+ HalpDisableSableSioInterrupt( Vector );
+
+ }
+ }
+
+ break;
+
+ }
+
+ //
+ // Release the system interrupt lock and restore the IRWL.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21164-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21164)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21164)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 2 (internal to 21164)
+ //
+
+ case PC2_VECTOR:
+ case PC2_SECONDARY_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ default:
+
+ if( HalpLynxPlatform ){
+
+ Enabled = HalpEnableLynxSioInterrupt( Vector, InterruptMode );
+
+ } else {
+
+ Enabled = HalpEnableSableSioInterrupt( Vector, InterruptMode );
+
+ }
+
+ break;
+
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+// We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ ULONG Vector;
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21164.
+ //
+
+ if( InterfaceType == ProcessorInternal ) {
+
+ Vector = HalpGet21164PerformanceVector( BusInterruptLevel, Irql );
+
+ if( Vector != 0 ){
+
+ //
+ // Success
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ }
+
+ }
+
+ //
+ // Handle Isa/Eisa bus and Internal devices.
+ //
+ // N.B. The bus interrupt level is the actual E/ISA signal name for
+ // option boards while the bus interrupt level is the actual
+ // interrupt vector number for internal devices. The interrupt
+ // vectors for internal devices are specified in the firmware
+ // configuration and are agreed upon between the firmware and this
+ // code.
+ //
+
+ if( (InterfaceType == Internal) ||
+ (InterfaceType == Isa) ||
+ (InterfaceType == PCIBus) ||
+ (InterfaceType == Eisa) ){
+
+ if( HalpLynxPlatform ){
+
+ return HalpGetLynxSioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ } else {
+
+ return HalpGetSableSioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ }
+
+ //
+ // Not an interface supported on Alpha systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ RATTLER_IPIR_CSR Ipir;
+ extern PRATTLER_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+
+ //
+ // Set up to request an interprocessor interrupt.
+ //
+
+ Ipir.all = 0;
+ Ipir.RequestInterrupt = 1;
+
+ //
+ // N.B. Gamma supports up to 4 processors only.
+ //
+ // N.B. A read-modify-write is not performed on the Ipir register
+ // which implies that the value of the request halt interrupt
+ // bit may be lost. Currently, this is not an important
+ // consideration because that feature is not being used.
+ // If later it is used than more consideration must be given
+ // to the possibility of losing the bit.
+ //
+
+ //
+ // The request mask is specified as a mask of the logical processors
+ // that must receive IPI requests. HalpSableCpuCsrs[] contains the
+ // CPU CSRs address for the logical processors.
+ //
+
+ //
+ // Request an IPI for processor 0 if requested.
+ //
+
+ if( Mask & HAL_CPU0_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU0]->Iirr), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 1 if requested.
+ //
+
+ if( Mask & HAL_CPU1_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU1]->Iirr), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 2 if requested.
+ //
+
+ if( Mask & HAL_CPU2_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU2]->Iirr), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 3 if requested.
+ //
+
+ if( Mask & HAL_CPU3_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU3]->Iirr), Ipir.all );
+
+ }
+
+
+
+
+ return;
+}
diff --git a/private/ntos/nthals/halgamma/alpha/haldebug.c b/private/ntos/nthals/halgamma/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/halpal.s b/private/ntos/nthals/halgamma/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halgamma/alpha/haltsup.s b/private/ntos/nthals/halgamma/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halgamma/alpha/icic.c b/private/ntos/nthals/halgamma/alpha/icic.c
new file mode 100644
index 000000000..83e584b63
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/icic.c
@@ -0,0 +1 @@
+#include "..\halsable\alpha\icic.c"
diff --git a/private/ntos/nthals/halgamma/alpha/idle.s b/private/ntos/nthals/halgamma/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halgamma/alpha/info.c b/private/ntos/nthals/halgamma/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/inithal.c b/private/ntos/nthals/halgamma/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/intsup.s b/private/ntos/nthals/halgamma/alpha/intsup.s
new file mode 100644
index 000000000..59352ced3
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "gammartc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halgamma/alpha/ioproc.c b/private/ntos/nthals/halgamma/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/iousage.c b/private/ntos/nthals/halgamma/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/lyintsup.c b/private/ntos/nthals/halgamma/alpha/lyintsup.c
new file mode 100644
index 000000000..28b7ffe13
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/lyintsup.c
@@ -0,0 +1 @@
+#include "..\halsable\alpha\lyintsup.c"
diff --git a/private/ntos/nthals/halgamma/alpha/machdep.h b/private/ntos/nthals/halgamma/alpha/machdep.h
new file mode 100644
index 000000000..adeda1dd4
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Gamma platform-specific definitions.
+//
+
+#include "gamma.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halgamma/alpha/memory.c b/private/ntos/nthals/halgamma/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/pcibus.c b/private/ntos/nthals/halgamma/alpha/pcibus.c
new file mode 100644
index 000000000..d272af9e9
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/pcibus.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the sable HAL directory
+//
+
+#include "..\halsable\alpha\pcibus.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/pcisup.c b/private/ntos/nthals/halgamma/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/pcrtc.c b/private/ntos/nthals/halgamma/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/pcserial.c b/private/ntos/nthals/halgamma/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/pcspeakr.c b/private/ntos/nthals/halgamma/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/perf8254.c b/private/ntos/nthals/halgamma/alpha/perf8254.c
new file mode 100644
index 000000000..5fade7e42
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/perf8254.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perf8254.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/rattler.h b/private/ntos/nthals/halgamma/alpha/rattler.h
new file mode 100644
index 000000000..c12b6e244
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/rattler.h
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ rattler.h
+
+Abstract:
+
+ This file defines the structures and definitions describing the
+ Rattler EV5 to CBUS bridge chip
+
+Author:
+
+ Steve Brooks 28-Dec 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RATTLERH_
+#define _RATTLERH_
+
+
+typedef struct _RATTLER_CPU_CSRS{
+ UCHAR Creg; // (0000) Configuration Register
+ UCHAR Esreg; // (0020) Error Summary Register
+ UCHAR Evbcr; // (0040) EVB Control Register
+ UCHAR Evbvear; // (0060) EVB Victim Error Address Register
+ UCHAR Evbcer; // (0080) EVB Correctable Error Register
+ UCHAR Evbcear; // (00a0) EVB Correctable error address register
+ UCHAR Evbuer; // (00c0) EVB Uncorrectable Error Register
+ UCHAR Evbuear; // (00e0) EVB Uncorrectable Error Address register
+ UCHAR Evresv; // (0100) EVB Reserver Register
+ UCHAR Dtctr; // (0120) Duptag Control register
+ UCHAR Dter; // (0140) Duptag error register
+ UCHAR Dttcr; // (0160) Duptag test control register
+ UCHAR Dttr; // (0180) Duptag test register
+ UCHAR Dtresv; // (01a0) Duptag reserve register
+ UCHAR Ibcsr; // (01c0) I-Bus control and status register
+ UCHAR Ibear; // (01e0) I-Bus error address register
+ UCHAR Acr; // (0200) Arbitration control register
+ UCHAR Cbcr; // (0220) Cobra-bus2 Control register
+ UCHAR Cber; // (0240) Cobra-bus2 Error register
+ UCHAR Cbealr; // (0260) Cobra-bus2 Error address low register
+ UCHAR Cbeahr; // (0280) Cobra-bus2 Error address high register
+ UCHAR Cbresv; // (02a0) Cobra-bus2 reserve register
+ UCHAR Alr; // (02c0) Address lock register
+ UCHAR Pmbr; // (02e0) Processor Mailbox register
+ UCHAR Iirr; // (0300) Interprocessor interrupt request register
+ UCHAR Sicr; // (0320) System interrupt clear register
+ UCHAR Mresv; // (0340) Miscellaneous reserve register
+ UCHAR Pmr1; // (0360) Performance Register 1
+ UCHAR Pmr2; // (0380) Performance Register 2
+ UCHAR Pmr3; // (03a0) Performance Register 3
+ UCHAR Pmr4; // (03c0) Performance Register 4
+ UCHAR Pmr5; // (03e0) Performance Register 5
+
+} RATTLER_CPU_CSRS, *PRATTLER_CPU_CSRS;
+
+//
+// Define the Rattler Configuration Register
+//
+
+typedef union _RATTLER_CONFIG_CSR{
+ struct{
+ ULONG RevisionNumber: 4; // (0-3)
+ ULONG Reserved0: 8; // (4-11)
+ ULONG EnableBusSizing0: 1; // (12)
+ ULONG Reserved1: 7; // (13-19)
+ ULONG EnableExchangeDly0: 1; // (20)
+ ULONG Reserved2: 3; // (21-23)
+ ULONG DisableIdleBcCsStall0: 1; // (24)
+ ULONG Enable4IdleBc0: 1; // (25)
+ ULONG AckMb0: 1; // (26)
+ ULONG AckSetDirty0: 1; // (27)
+ ULONG CacheSize0: 3; // (28-30)
+ ULONG Reserved3: 1; // (31)
+ ULONG RevisionNumber2: 4; // (32-35)
+ ULONG EnableSystemInterrupts: 4; // (36-39)
+ ULONG EnableIoInterrupts: 2; // (40-41)
+ ULONG EnableAlternateIoInts: 2; // (42-43)
+ ULONG EnableBusSizing1: 1; // (44)
+ ULONG Reserved4: 7; // (45-51)
+ ULONG EnableExchangeDly1: 1; // (52)
+ ULONG Reserved5: 3; // (53-55)
+ ULONG DisableIdleBcCsStall1: 1; // (56)
+ ULONG Enable4IdleBc1: 1; // (57)
+ ULONG AckMb1: 1; // (58)
+ ULONG AckSetDirty1: 1; // (59)
+ ULONG CacheSize1: 3; // (60-62)
+ ULONG Reserved6: 1; // (63)
+ };
+ ULONGLONG all;
+
+} RATTLER_CONFIG_CSR, *PRATTLER_CONFIG_CSR;
+
+//
+// Define the Rattler Error Summary register:
+//
+
+typedef union _RATTLER_ESREG_CSR{
+ struct{
+ ULONG EvbCorrErr0: 3; //
+ ULONG Reserved0: 1; //
+ ULONG EvbFatalErr0: 4; //
+ ULONG DtErr0: 2; //
+ ULONG DtSummary0: 1; //
+ ULONG Reserved1: 1; //
+ ULONG IbParErr0: 1; //
+ ULONG IbErrInfo0: 2; //
+ ULONG IbSummary0: 1; //
+ ULONG CbErr0: 8; //
+ ULONG CbSummary0: 1; //
+ ULONG CbCmdr0: 1; //
+ ULONG Reserved2: 2; //
+ ULONG EvNoResponse0: 1; //
+ ULONG Reserved3: 3; //
+ ULONG EvbCorrErr1: 3; //
+ ULONG EvbCorrErrInt1: 1; //
+ ULONG EvbFatalErr1: 4; //
+ ULONG DtErr1: 2; //
+ ULONG DtSummary1: 1; //
+ ULONG Reserved4: 1; //
+ ULONG IbParErr1: 1; //
+ ULONG IbErrInfo1: 2; //
+ ULONG IbSummary1: 1; //
+ ULONG CbErr1: 4; //
+ ULONG Reserved5: 4; //
+ ULONG CbSummary1: 1; //
+ ULONG CbCmdr1: 1; //
+ ULONG Reserved6: 2; //
+ ULONG EvNoResponse1: 1; //
+ ULONG EvSysFail: 1; //
+ ULONG Reserved7: 2; //
+ };
+ ULONGLONG all;
+
+} RATTLER_ESREG_CSR, *PRATTLER_ESREG_CSR;
+
+
+//
+// Define the Cobra-bus2 Control Register:
+//
+
+typedef union _RATTLER_CBCR_CSR{
+ struct{
+ ULONG EnableParityChecking0: 1; // Enable CBUS parity checking
+ ULONG DataWrongParity0: 1; // Force bad data parity on bus
+ ULONG CAWrongParity0: 1; // Force bad command/addr parity
+ ULONG Reserved0: 1; //
+ ULONG ForceShared: 1; // force shared bus status
+ ULONG Reserved1: 7; //
+ ULONG EnableCbusErrInt0: 1; // Enable Rattler error interrupt
+ ULONG Reserved2: 19; //
+ ULONG EnableParityChecking1: 1; // Rattler-D parity checking enable
+ ULONG DataWrongParity1: 1; // Force bad data parity (Rattler-D)
+ ULONG CAWrongParity1: 1; // bad command/addr parity (D)
+ ULONG Reserved3: 5; //
+ ULONG CommanderID: 3; // CPU Commander ID
+ ULONG Reserved4: 1; //
+ ULONG EnableCbusErrInt1: 1; // Enable Rattler-D error interrupt
+ ULONG Reserved5: 19; //
+ };
+ ULONGLONG all;
+
+} RATTLER_CBCR_CSR, *PRATTLER_CBCR_CSR;
+
+//
+// Define the Interprocessor Interrupt Request Register.
+//
+
+typedef union _RATTLER_IPIR_CSR{
+ struct{
+ ULONGLONG Reserved0: 44;
+ ULONGLONG RequestNodeHaltInterrupt: 1;
+ ULONGLONG Reserved1: 3;
+ ULONGLONG RequestInterrupt: 1;
+ ULONGLONG Reserved2: 15;
+ };
+ ULONGLONG all;
+} RATTLER_IPIR_CSR, *PRATTLER_IPIR_CSR;
+
+//
+// Define the System Interrupt Clear Register format.
+//
+
+typedef union _RATTLER_SIC_CSR{
+ struct{
+ ULONG SystemBusErrorInterruptClear0: 1; // (0)
+ ULONG Reserved0: 31; // (1-31)
+ ULONG SystemBusErrorInterruptClear1: 1; // (32)
+ ULONG Reserved1: 3; // (33-35)
+ ULONG IntervalTimerInterrupt: 1; // (36)
+ ULONG Reserved2: 3; // (37-39)
+ ULONG SystemEventClear: 1; // (40)
+ ULONG Reserved3: 3; // (41-43)
+ ULONG NodeHaltInterruptClear: 1; // (44)
+ ULONG Reserved4: 3; // (45-47)
+ ULONG InterprocessorInterruptClear: 1; // (48)
+ ULONG Reserved5: 3; // (49-51)
+ ULONG IOInterruptIRQ: 2; // (52-53)
+ ULONG Reserved6: 10; // (54-63)
+ };
+ ULONGLONG all;
+} RATTLER_SIC_CSR, *PRATTLER_SIC_CSR;
+
+#endif // _RATTLERH_
diff --git a/private/ntos/nthals/halgamma/alpha/siintsup.c b/private/ntos/nthals/halgamma/alpha/siintsup.c
new file mode 100644
index 000000000..7151c2d75
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/siintsup.c
@@ -0,0 +1 @@
+#include "..\halsable\alpha\siintsup.c"
diff --git a/private/ntos/nthals/halgamma/alpha/t2.c b/private/ntos/nthals/halgamma/alpha/t2.c
new file mode 100644
index 000000000..f333da400
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/t2.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\t2.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/vga.c b/private/ntos/nthals/halgamma/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halgamma/alpha/xiintsup.c b/private/ntos/nthals/halgamma/alpha/xiintsup.c
new file mode 100644
index 000000000..add543421
--- /dev/null
+++ b/private/ntos/nthals/halgamma/alpha/xiintsup.c
@@ -0,0 +1 @@
+#include "..\halsable\alpha\xiintsup.c"
diff --git a/private/ntos/nthals/halgamma/bushnd.c b/private/ntos/nthals/halgamma/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halgamma/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halgamma/dirs b/private/ntos/nthals/halgamma/dirs
new file mode 100644
index 000000000..a2a38f0fd
--- /dev/null
+++ b/private/ntos/nthals/halgamma/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up
+
+OPTIONAL_DIRS=mp
diff --git a/private/ntos/nthals/halgamma/drivesup.c b/private/ntos/nthals/halgamma/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halgamma/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halgamma/hal.rc b/private/ntos/nthals/halgamma/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halgamma/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halgamma/hal.src b/private/ntos/nthals/halgamma/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halgamma/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halgamma/mp/makefile b/private/ntos/nthals/halgamma/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halgamma/mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halgamma/mp/makefile.inc b/private/ntos/nthals/halgamma/mp/makefile.inc
new file mode 100644
index 000000000..6985ce07a
--- /dev/null
+++ b/private/ntos/nthals/halgamma/mp/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halsabmp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halgamma/mp/sources b/private/ntos/nthals/halgamma/mp/sources
new file mode 100644
index 000000000..d6e690e72
--- /dev/null
+++ b/private/ntos/nthals/halgamma/mp/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halgammp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DAXPSABLE -DRTC_SQE -DEISA_PLATFORM -DXIO_PASS2
+
+NT_UP=0
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha;..\..\halsable\alpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\alphaio.s \
+ ..\alpha\bios.c \
+ ..\alpha\cache.c \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\environ.c \
+ ..\alpha\ev5cache.c \
+ ..\alpha\ev5int.c \
+ ..\alpha\ev5mchk.c \
+ ..\alpha\ev5mem.s \
+ ..\alpha\ev5prof.c \
+ ..\alpha\ev5ints.s \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\icic.c \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\lyintsup.c \
+ ..\alpha\memory.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\siintsup.c \
+ ..\alpha\t2.c \
+ ..\alpha\vga.c \
+ ..\alpha\xiintsup.c \
+ ..\alpha\addrsup.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\gammaerr.c \
+ ..\alpha\gammaio.s \
+ ..\alpha\gminitnt.c \
+ ..\alpha\gmintr.s \
+ ..\alpha\gmintsup.c \
+ ..\alpha\gmmapio.c \
+ ..\alpha\gmsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halgamma/up/makefile b/private/ntos/nthals/halgamma/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halgamma/up/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halgamma/up/makefile.inc b/private/ntos/nthals/halgamma/up/makefile.inc
new file mode 100644
index 000000000..76942c78b
--- /dev/null
+++ b/private/ntos/nthals/halgamma/up/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halsabup.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halgamma/up/sources b/private/ntos/nthals/halgamma/up/sources
new file mode 100644
index 000000000..650b153c9
--- /dev/null
+++ b/private/ntos/nthals/halgamma/up/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halgamup
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DAXPSABLE -DRTC_SQE -DEISA_PLATFORM -DXIO_PASS2
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha;..\..\halsable\alpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\drivesup.c \
+ ..\bushnd.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\alphaio.s \
+ ..\alpha\bios.c \
+ ..\alpha\cache.c \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\environ.c \
+ ..\alpha\ev5cache.c \
+ ..\alpha\ev5int.c \
+ ..\alpha\ev5mchk.c \
+ ..\alpha\ev5mem.s \
+ ..\alpha\ev5prof.c \
+ ..\alpha\ev5ints.s \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\icic.c \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\lyintsup.c \
+ ..\alpha\memory.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\siintsup.c \
+ ..\alpha\t2.c \
+ ..\alpha\vga.c \
+ ..\alpha\xiintsup.c \
+ ..\alpha\addrsup.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\gammaerr.c \
+ ..\alpha\gammaio.s \
+ ..\alpha\gminitnt.c \
+ ..\alpha\gmintr.s \
+ ..\alpha\gmintsup.c \
+ ..\alpha\gmmapio.c \
+ ..\alpha\gmsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/hallego/alpha/addrsup.c b/private/ntos/nthals/hallego/alpha/addrsup.c
new file mode 100644
index 000000000..2a7deb1f6
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/addrsup.c
@@ -0,0 +1,590 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+ Gene Morgan (Digital) 11-Oct-1995
+ Initial LEGO version -- adapted from Avanti
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "legodef.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on Avanti are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAXR2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ // Note that ISA and EISA buses can also request this space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_DENSE_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ if( (PA.QuadPart >= APECS_COMANCHE_BASE_PHYSICAL)
+ && (PA.QuadPart < APECS_PCI_DENSE_BASE_PHYSICAL)
+ )
+ {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Lego we have only bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/hallego/alpha/adjust.c b/private/ntos/nthals/hallego/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/allstart.c b/private/ntos/nthals/hallego/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/alphaio.s b/private/ntos/nthals/hallego/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/apecs.c b/private/ntos/nthals/hallego/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/apecserr.c b/private/ntos/nthals/hallego/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/apecsio.s b/private/ntos/nthals/hallego/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/bios.c b/private/ntos/nthals/hallego/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/busdata.c b/private/ntos/nthals/hallego/alpha/busdata.c
new file mode 100644
index 000000000..b04915a0e
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/busdata.c
@@ -0,0 +1,129 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+
+ Initial version for Lego. Adapted from Avanti.
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/hallego/alpha/cache.c b/private/ntos/nthals/hallego/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/chipset.h b/private/ntos/nthals/hallego/alpha/chipset.h
new file mode 100644
index 000000000..0a72ef8cb
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/chipset.h
@@ -0,0 +1 @@
+#include "apecs.h"
diff --git a/private/ntos/nthals/hallego/alpha/cmos8k.c b/private/ntos/nthals/hallego/alpha/cmos8k.c
new file mode 100644
index 000000000..483709b57
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/cmos8k.c
@@ -0,0 +1,2 @@
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/ebsgdma.c b/private/ntos/nthals/hallego/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/eisasup.c b/private/ntos/nthals/hallego/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/ev4cache.c b/private/ntos/nthals/hallego/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/ev4int.c b/private/ntos/nthals/hallego/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/ev4ints.s b/private/ntos/nthals/hallego/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/ev4mchk.c b/private/ntos/nthals/hallego/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/ev4mem.s b/private/ntos/nthals/hallego/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/ev4prof.c b/private/ntos/nthals/hallego/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/fwreturn.c b/private/ntos/nthals/hallego/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/haldebug.c b/private/ntos/nthals/hallego/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/halpal.s b/private/ntos/nthals/hallego/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/idle.s b/private/ntos/nthals/hallego/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/info.c b/private/ntos/nthals/hallego/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/inithal.c b/private/ntos/nthals/hallego/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/intsup.s b/private/ntos/nthals/hallego/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/hallego/alpha/ioproc.c b/private/ntos/nthals/hallego/alpha/ioproc.c
new file mode 100644
index 000000000..14af7ad42
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/ioproc.c
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/hallego/alpha/iousage.c b/private/ntos/nthals/hallego/alpha/iousage.c
new file mode 100644
index 000000000..6ac8f6f4e
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/iousage.c
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/hallego/alpha/iousage.h b/private/ntos/nthals/hallego/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/hallego/alpha/legodef.h b/private/ntos/nthals/hallego/alpha/legodef.h
new file mode 100644
index 000000000..14213c792
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/legodef.h
@@ -0,0 +1,671 @@
+/*++
+
+Copyright (c) 1993,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ legodef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Lego modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+ Initial version for Lego. Adapted from Avanti.
+
+ Gene Morgan 15-Apr-1996
+ New Platform Name strings
+
+--*/
+
+#ifndef _LEGODEF_
+#define _LEGODEF_
+
+#include "alpharef.h"
+#include "apecs.h"
+#include "isaaddr.h"
+
+//****************************************************************
+// Lego family configurations
+// (PCI/ISA slots and backplane features).
+//
+// PCI "Virtual slot" concept comes from Microsoft's pci.h file.
+//
+//****************************************************************
+
+// Atacama -- Baby-AT form factor
+//
+#define NUMBER_ATACAMA_ISA_SLOTS 4
+#define NUMBER_ATACAMA_PCI_SLOTS 3 // 2 are 64-bit. NCR810 is in what would be 2nd slot
+
+//
+// Gobi -- 15 slot backplane
+//
+// Addition of one DECchip 21052 PPB yields 4 32-bit PCI slots (at cost of one 32-bit slot).
+// NCR810 is gone, too.
+//
+// Gobi PCI config
+// Slot function IDSEL int pin routing (mod 4)
+// ---- -------- ----- ----------------------
+// 20 PCI-PCI bridge 31 +3
+// 19 64-bit slot 30 +2
+// 18 64-bit slot 29 +1
+// 17 32-bit slot 28 +0
+//
+// 15 bridge 1 slot 31 +0
+// 14 bridge 1 slot 30 +1
+// 13 bridge 1 slot 29 +2
+// 12 bridge 1 slot 28 +3
+//
+// 7 ISA SIO 18 --
+//
+#define NUMBER_GOBI_ISA_SLOTS 5
+#define NUMBER_GOBI_PCI_SLOTS 7
+
+// Sahara -- 20 slot backplane
+//
+// Addition of another 21052...
+//
+#define NUMBER_SAHARA_ISA_SLOTS 7
+#define NUMBER_SAHARA_PCI_SLOTS 10
+
+// Generic -- use Sahara's values
+//
+// ??? Used ???
+//
+#define NUMBER_ISA_SLOTS (NUMBER_SAHARA_ISA_SLOTS)
+#define NUMBER_PCI_SLOTS (NUMBER_SAHARA_PCI_SLOTS)
+
+// Lowest virtual local PCI slot is 17 == IDSEL PCI_AD[28]
+// Highest Virtual local PCI Slot is 20 == IDSEL PCI_AD[31]
+// This gives the following slot layout:
+//
+// Virtual Device Physical Device/slot IDSEL
+// 17 1 28
+// 18 2 29
+// 19 3 30
+// 20 4 31
+//
+// Used for sizing Pin-to-Line table.
+//
+#define PCI_MIN_LOCAL_DEVICE 17 //[wem] not used
+#define PCI_MAX_LOCAL_DEVICE 20
+
+// LEGO Family Members -
+//
+// concatenate cpu and backplane type to get family type
+//
+
+#define CPU_UNKNOWN 0x0 // Can't tell what CPU
+#define CPU_LEGO_K2 0x1 // K2 CPU card
+
+#define BACKPLANE_UNKNOWN 0x0 // Can't determine backplane -- assume PICMIG-compliant
+#define BACKPLANE_ATACAMA 0x1
+#define BACKPLANE_GOBI 0x2
+#define BACKPLANE_SAHARA 0x3
+
+//
+// Backplane/CPU feature mask
+//
+
+#define LEGO_FEATURE_INT_ACCEL 0x01
+#define LEGO_FEATURE_SERVER_MGMT 0x02
+#define LEGO_FEATURE_WATCHDOG 0x04 // PSU (not in first rev of K2)
+#define LEGO_FEATURE_OCP_DISPLAY 0x08 // I2C bus and PCF8574s are present
+#define LEGO_FEATURE_PSU 0x10 // System has DMCC backplane with support
+ // for multiple power supplies
+
+#define LEGO_NUMBER_OF_FEATURES 5
+
+//
+// Server Management Conditions
+//
+
+#define LEGO_CONDITION_OVERTEMP 0x01
+#define LEGO_CONDITION_CPU_OVERTEMP 0x02
+#define LEGO_CONDITION_CPU_TEMPOK 0x04
+#define LEGO_CONDITION_BADFAN 0x08
+#define LEGO_CONDITION_CPU_BADFAN 0x10
+#define LEGO_CONDITION_POWER1_BAD 0x20
+#define LEGO_CONDITION_POWER2_BAD 0x40
+
+#define CONDITION_QUERY 0x10000 // force recheck of server management register
+
+#define LEGO_NUMBER_OF_CONDITIONS 7
+
+//
+// Define known Lego platform names.
+//
+
+#define PLATFORM_NAME_LEGO_K2 "LegoK2"
+#define PLATFORM_NAME_K2_ATA "LegoK2A" // Atacama
+#define PLATFORM_NAME_K2_GOBI "LegoK2G" // Gobi
+#define PLATFORM_NAME_K2_SAHA "LegoK2S" // Sahara
+#define PLATFORM_NAME_UNKNOWN "LegoUnk" // Unknown
+
+//
+// PCI Interrupt routing types
+//
+// PCI Interrupts in LEGO may be routed in one of three ways:
+// SIO - INTA .. INTD off the PCI bus routed through the SIO.
+// DIRECT - INTA .. INTD off the PCI bus routed to an interrupt
+// register.
+// FULL - INTA .. INTD from each primary or bridged slot (64 signals)
+// routed to one of four interrupt registers.
+//
+#define PCI_INTERRUPT_ROUTING_SIO 1
+#define PCI_INTERRUPT_ROUTING_FULL 2
+#define PCI_INTERRUPT_ROUTING_DIRECT 3
+
+
+//*******************************************************
+//
+// End Lego-specific configuration info
+//
+// Lego-specific register layouts and addresses
+// are at the end of this file.
+//
+//*******************************************************
+
+//[wem] same as avanti.h
+//
+#define PCI_SPARSE_IO_BASE_QVA ((ULONG)(HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL))) //[wem] LEGO-OK
+
+//
+// PCI-E/ISA Bridge chip configuration space base is at physical address
+// 0x1e0000000. The equivalent QVA is:
+// ((0x1e0000000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+// N.B.: The PCI configuration space address is what we're really referring
+// to, here; both symbols are useful.
+//
+
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+
+#define PCI_CONFIGURATION_BASE_QVA 0xaf000000
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device
+
+#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00070000 >> IO_BIT_SHIFT) // AD[18] //[wem] LEGO-OK
+
+//
+// PCI-ISA Bridge Non-Configuration control register offsets.
+// These offsets are in PCI I/O space and should be ored with
+// PCI_SPARSE_IO_BASE_QVA.
+//
+
+#define SIO_II_EDGE_LEVEL_CONTROL_1 (0x9a00 >> IO_BIT_SHIFT) //[wem] LEGO-OK
+#define SIO_II_EDGE_LEVEL_CONTROL_2 (0x9a20 >> IO_BIT_SHIFT)
+
+//
+// Register offsets for unique functions on Lego. Some of these are offsets
+// into ISA I/O space -- they cannot be reached via PCI I/O space.
+//
+
+// PCI offsets...
+//
+
+#define PCI_INDEX (0x04c0 >> IO_BIT_SHIFT) //[wem] 0x4DC0 for LEGO ?
+#define PCI_DATA (0x04e0 >> IO_BIT_SHIFT) //[wem] 0x4DE0 for LEGO ?
+
+//
+// PCI-ISA Bridge Configuration register offsets.
+//
+
+#define PCI_VENDOR_ID (0x0000 >> IO_BIT_SHIFT) //[wem] LEGO-OK
+#define PCI_DEVICE_ID (0x0040 >> IO_BIT_SHIFT)
+#define PCI_COMMAND (0x0080 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_STATUS (0x00c0 >> IO_BIT_SHIFT)
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+#define PCI_CONTROL (0x0800 >> IO_BIT_SHIFT)
+#define PCI_ARBITER_CONTROL (0x0820 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_A (0x09c0 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_B (0x09e0 >> IO_BIT_SHIFT)
+#define PIRQ0_ROUTE_CONTROL (0x0c00 >> IO_BIT_SHIFT)
+#define PIRQ1_ROUTE_CONTROL (0x0c20 >> IO_BIT_SHIFT)
+#define PIRQ2_ROUTE_CONTROL (0x0c40 >> IO_BIT_SHIFT)
+#define PIRQ3_ROUTE_CONTROL (0x0c60 >> IO_BIT_SHIFT)
+
+//
+// SIO-II value for setting edge/level operation in the control words.
+//
+
+#define IRQ0_LEVEL_SENSITIVE 0x01
+#define IRQ1_LEVEL_SENSITIVE 0x02
+#define IRQ2_LEVEL_SENSITIVE 0x04
+#define IRQ3_LEVEL_SENSITIVE 0x08
+#define IRQ4_LEVEL_SENSITIVE 0x10
+#define IRQ5_LEVEL_SENSITIVE 0x20
+#define IRQ6_LEVEL_SENSITIVE 0x40
+#define IRQ7_LEVEL_SENSITIVE 0x80
+#define IRQ8_LEVEL_SENSITIVE 0x01
+#define IRQ9_LEVEL_SENSITIVE 0x02
+#define IRQ10_LEVEL_SENSITIVE 0x04
+#define IRQ11_LEVEL_SENSITIVE 0x08
+#define IRQ12_LEVEL_SENSITIVE 0x10
+#define IRQ13_LEVEL_SENSITIVE 0x20
+#define IRQ14_LEVEL_SENSITIVE 0x40
+#define IRQ15_LEVEL_SENSITIVE 0x80
+
+//
+// Values for PIRQ route control settings.
+// see 82378 SIO spec, section 4.1.27
+//
+
+#define PIRQX_ROUTE_IRQ3 0x03
+#define PIRQX_ROUTE_IRQ4 0x04
+#define PIRQX_ROUTE_IRQ5 0x05
+#define PIRQX_ROUTE_IRQ6 0x06
+#define PIRQX_ROUTE_IRQ7 0x07
+#define PIRQX_ROUTE_IRQ9 0x09
+#define PIRQX_ROUTE_IRQ10 0x0a
+#define PIRQX_ROUTE_IRQ11 0x0b
+#define PIRQX_ROUTE_IRQ12 0x0c
+#define PIRQX_ROUTE_IRQ14 0x0d
+#define PIRQX_ROUTE_IRQ15 0x0f
+#define PIRQX_ROUTE_ENABLE 0x00
+#define PIRQX_ROUTE_DISABLE 0x80
+
+//
+// Define primary (and only) CPU on Lego system
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0)
+
+//
+// Define the default processor clock frequency used before the actual
+// value can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (233)
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+#if !defined (AXP_FIRMWARE)
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV4 processor.
+//
+typedef struct _LEGO_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} LEGO_PCR, *PLEGO_PCR;
+
+#endif
+
+#define HAL_PCR ( (PLEGO_PCR)(&(PCR->HalReserved)) )
+
+#endif
+
+//**************************************************
+//
+// The remainder of this file contain Lego-specific
+// definitions.
+//
+//**************************************************
+
+// The Lego server management data structure
+//
+// The server management register is at ISA address 506h.
+//
+// The SINT signals are routed to CPU IRQ5. Writing a 1 to an SINT
+// bit will clear the interrupt (an edge will reassert it). The temperature
+// sensors can clear and reassert themselves, the fan sensors are one-shots.
+//
+// The NMI signals are routed to CPU IRQ3. The bits cannot be cleared, only
+// masked.
+//
+// Note: PINT and MPINT bits are not in first rev of K2.
+//
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+typedef union _LEGO_SRV_MGMT{
+ struct {
+ USHORT CpuTempRestored : 1; // rw - SINT1
+ USHORT CpuTempFailure : 1; // rw - SINT2
+ USHORT EnclFanFailure : 1; // rw - SINT3
+ USHORT EnclTempFailureNmi : 1; // ro - SNMI1
+ USHORT CpuFanFailureNmi : 1; // ro - SNMI2
+ USHORT IntMask : 1; // rw - MSINT - set to mask SINT[1..3]
+ USHORT NmiMask : 1; // rw - MSNMI - set to mask SNMI[1..2]
+ USHORT PowerOff : 1; // rw - POFF - set to switch off power
+ USHORT PsuMask : 1; // rw - MPINT - set to mask PINT[2..1]
+ USHORT Psu1Failure : 1; // rw - PINT1 - PSU status change
+ USHORT Psu2Failure : 1; // rw - PINT2 - PSU status change
+ USHORT Reserved : 5; // ro/undefined
+ };
+ USHORT All;
+} LEGO_SRV_MGMT, *PLEGO_SRV_MGMT;
+
+// The Lego watchdog timer data structure
+// The watchdog timer register is at ISA address 504h.
+//
+// The WINT signal is routed to CPU IRQ5. The interrupt
+// is cleared by writing a 1 to WINT.
+//
+// Notes:
+// WMODE, T1CF, and T2CF can be written iff the watchdog is disabled.
+// The watchdog cannot be disabled if timer 2 running.
+// To disable the watchdog:
+// (WPHAS==0) ? WEN = 0 : WPHAS = 1, WEN = 0;
+// If timer two is allowed to expire, a system-wide reset occurs.
+// Write 1 to WPHAS, WINT to clear them.
+//
+typedef union _LEGO_WATCHDOG{
+ struct {
+ USHORT TimerOnePeriod : 3; // rw - T1CF[2:0]
+ USHORT TimerTwoPeriod : 3; // rw - T2CF[2:0]
+ USHORT Enabled : 1; // rw - WEN - set to enable timer
+ USHORT Mode : 1; // rw - WMODE - see WATCHDOG_MODE_*
+ USHORT Phase : 1; // rw - WPHAS - see WATCHDOG_PHASE_*
+ USHORT Interrupt : 1; // rw - WINT - timer one expired.
+ USHORT Reserved : 6; // ro/undefined
+ };
+ USHORT All;
+} LEGO_WATCHDOG, *PLEGO_WATCHDOG;
+
+// Watchdog phase - detect whether timer (phase) one or two is running.
+// Writing one to the phase bit will place timer in phase one.
+//
+#define WATCHDOG_PHASE_ONE 0
+#define WATCHDOG_PHASE_TWO 1
+
+// Watchdog mode - select whether to run in one-timer or two-timer mode
+//
+#define WATCHDOG_MODE_2TIMER 0
+#define WATCHDOG_MODE_1TIMER 1
+
+#define WATCHDOG_MODE_DISABLED 2
+
+// Timeout periods for timers 1 and 2
+//
+#define WATCHDOG_PERIOD_10MS 0
+#define WATCHDOG_PERIOD_100MS 1
+#define WATCHDOG_PERIOD_500MS 2
+#define WATCHDOG_PERIOD_1S 3
+#define WATCHDOG_PERIOD_8S 4
+#define WATCHDOG_PERIOD_60S 5
+#define WATCHDOG_PERIOD_300S 6
+#define WATCHDOG_PERIOD_1200S 7
+
+// Lego PCI Interrupt Support
+//
+// Define registers used for facilitating PCI interrupt processing:
+// Configuration register (LEGO_PCI_INT_CONFIG) - controls interrupt routing
+// Master Interrupt register (LEGO_PCI_INT_MASTER) - slot-level int and mask
+// Interrupt Registers 1-4 (LEGO_PCI_INT_REGISTER) - device-level int and mask
+// The interrupt registers may hold interrupt and mask signals for a single
+// primary slot, or for the four slots that may reside behind the bridge.
+//
+// The registers are all defined as 16-bit registers since LEGO's ISA bus
+// is limited to 16-bit reads and writes.
+//
+
+// Lego PCI Interrupt Support Configuration Register (ISA address 502h)
+// CFG - read-only field that identifies which primary slots hold bridges.
+// ADR - used to establish the base address of the 4 4-byte interrupt registers.
+//
+typedef union _LEGO_PCI_INT_CONFIG{
+ struct {
+ USHORT BackplaneConfig : 4; // ro - CFG[4:1] - see LEGO_CONFIG_*
+ USHORT IntRegisterBaseAddr : 12; // rw - ADR[15:4]
+ };
+ USHORT All;
+} LEGO_PCI_INT_CONFIG, *PLEGO_PCI_INT_CONFIG;
+
+// Configurations
+//
+// Value is a bitmask that indicates which primary slots are
+// bridges -- the rightmost bit is for device 1.
+//
+#define LEGO_CONFIG_ATACAMA 0x0 // b0000 - all primary slots are connectors
+#define LEGO_CONFIG_GOBI 0x1 // b0001 - primary slot one is a PPB
+#define LEGO_CONFIG_SAHARA 0x3 // b0011 - primary slots one and two are PPBs
+
+// Lego PCI Interrupt Support Master Register (ISA address 500h)
+//
+// INTE and INTF and reserved for on-board PCI functions. Their use
+// is not currently defined.
+//
+// OWN - controls who drives bits 13-15 on a read to the Interrupt Master Register
+// 0 (default) - backplane drives the bits on a read
+// 1 - cpu card drives the bits
+//
+typedef union _LEGO_PCI_INT_MASTER{
+ struct {
+ USHORT Interrupt : 4; // ro - INTA..INTD
+ USHORT InterruptRes : 2; // ro - INTE,F **reserved**
+ USHORT IntMask : 4; // rw - MINTA..MINTD
+ USHORT IntMaskRes : 2; // rw - MINTE,F **reserved**
+ USHORT IntOwner : 1; // rw - OWN
+ USHORT IntRegMaskEnable : 1; // rw - MSKEN
+ USHORT InterruptEnable : 1; // rw - PCIE
+ USHORT InterruptMode : 1; // rw - MODE
+ };
+ USHORT All;
+} LEGO_PCI_INT_MASTER, *PLEGO_PCI_INT_MASTER;
+
+#define INTA 0x1
+#define INTB 0x2
+#define INTC 0x4
+#define INTD 0x8
+
+#define SLOT1INTA (INTA)
+#define SLOT1INTB (INTB)
+#define SLOT1INTC (INTC)
+#define SLOT1INTD (INTD)
+#define SLOT2INTA (INTA<<4)
+#define SLOT2INTB (INTB<<4)
+#define SLOT2INTC (INTC<<4)
+#define SLOT2INTD (INTD<<4)
+#define SLOT3INTA (INTA<<8)
+#define SLOT3INTB (INTB<<8)
+#define SLOT3INTC (INTC<<8)
+#define SLOT3INTD (INTD<<8)
+#define SLOT4INTA (INTA<<12)
+#define SLOT4INTB (INTB<<12)
+#define SLOT4INTC (INTC<<12)
+#define SLOT4INTD (INTD<<12)
+
+// Lego PCI Interrupt Support -- Interrupt Register.
+//
+typedef union _LEGO_PCI_INT_REGISTER {
+ union {
+ struct {
+ USHORT Slot1IntA : 1; // ro - S1IA
+ USHORT Slot1IntB : 1; // ro - S1IB
+ USHORT Slot1IntC : 1; // ro - S1IC
+ USHORT Slot1IntD : 1; // ro - S1ID
+ USHORT Slot2IntA : 1; // ro - S2IA
+ USHORT Slot2IntB : 1; // ro - S2IB
+ USHORT Slot2IntC : 1; // ro - S2IC
+ USHORT Slot2IntD : 1; // ro - S2ID
+ USHORT Slot3IntA : 1; // ro - S3IA
+ USHORT Slot3IntB : 1; // ro - S3IB
+ USHORT Slot3IntC : 1; // ro - S3IC
+ USHORT Slot3IntD : 1; // ro - S3ID
+ USHORT Slot4IntA : 1; // ro - S4IA
+ USHORT Slot4IntB : 1; // ro - S4IB
+ USHORT Slot4IntC : 1; // ro - S4IC
+ USHORT Slot4IntD : 1; // ro - S4ID
+ } bridge;
+ struct {
+ USHORT IntA : 1; // ro - IA
+ USHORT IntB : 1; // ro - IB
+ USHORT IntC : 1; // ro - IC
+ USHORT IntD : 1; // ro - ID
+ USHORT Reserved : 12; // ro - reserved
+ } primary;
+ } slot;
+ USHORT All;
+} LEGO_PCI_INT_REGISTER, *PLEGO_PCI_INT_REGISTER;
+
+// Lego PCI Interrupt Support -- Interrupt Mask Register.
+//
+typedef union _LEGO_PCI_INT_MASK_REGISTER {
+ union {
+ struct {
+ USHORT Slot1MaskIntA : 1; // rw - MS1IA
+ USHORT Slot1MaskIntB : 1; // rw - MS1IB
+ USHORT Slot1MaskIntC : 1; // rw - MS1IC
+ USHORT Slot1MaskIntD : 1; // rw - MS1ID
+ USHORT Slot2MaskIntA : 1; // rw - MS2IA
+ USHORT Slot2MaskIntB : 1; // rw - MS2IB
+ USHORT Slot2MaskIntC : 1; // rw - MS2IC
+ USHORT Slot2MaskIntD : 1; // rw - MS2ID
+ USHORT Slot3MaskIntA : 1; // rw - MS3IA
+ USHORT Slot3MaskIntB : 1; // rw - MS3IB
+ USHORT Slot3MaskIntC : 1; // rw - MS3IC
+ USHORT Slot3MaskIntD : 1; // rw - MS3ID
+ USHORT Slot4MaskIntA : 1; // rw - MS4IA
+ USHORT Slot4MaskIntB : 1; // rw - MS4IB
+ USHORT Slot4MaskIntC : 1; // rw - MS4IC
+ USHORT Slot4MaskIntD : 1; // rw - MS4ID
+ } bridge;
+ struct {
+ USHORT MaskIntA : 1; // rw - MIA
+ USHORT MaskIntB : 1; // rw - MIB
+ USHORT MaskIntC : 1; // rw - MIC
+ USHORT MaskIntD : 1; // rw - MID
+ USHORT Reserved : 12; // ro - reserved
+ } primary;
+ } slot;
+ USHORT All;
+} LEGO_PCI_INT_MASK_REGISTER, *PLEGO_PCI_INT_MASK_REGISTER;
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+// Define "non-standard" primary interrupts for Lego/K2
+//
+#define PCI_VECTOR PRIMARY0_VECTOR // from alpharef.h
+#define SERVER_MGMT_VECTOR PRIMARY1_VECTOR
+
+#define SERVER_MGMT_VECTORS 80
+
+// server management conditions (via CPU IRQ5)
+//
+#define WATCHDOG_VECTOR (0 + SERVER_MGMT_VECTORS)
+#define SM_WARNING_VECTOR (1 + SERVER_MGMT_VECTORS)
+#define SM_PSU_FAILURE_VECTOR (2 + SERVER_MGMT_VECTORS)
+
+// NMI conditions (via CPU IRQ3)
+//
+#define SM_ERROR_VECTOR (5 + SERVER_MGMT_VECTORS)
+#define HALT_BUTTON_VECTOR (6 + SERVER_MGMT_VECTORS)
+
+#define MAXIMUM_SERVER_MGMT_VECTOR (7 + SERVER_MGMT_VECTORS)
+
+//
+// Define interrupt level for server management interrupts,
+// including watchdog timer.
+// Level should be high, but not as high as NMI
+// Using IPI_LEVEL, which is normally for interprocessor interrupts,
+//[wem] ??? IPI_LEVEL is between NMI and CLOCK levels -- is this OK ?
+//
+
+#define SERVER_MGMT_LEVEL IPI_LEVEL // from alpharef.h
+
+//
+// Highest PCI interrupt vector is in ISA Vector Space
+// Standard vectors are defined in alpharef.h
+//
+
+#define ISA_DEVICE_VECTORS (ISA_VECTORS)
+#define PCI_DEVICE_VECTORS (PCI_VECTORS)
+#define LEGO_MAXIMUM_PCI_VECTOR (PCI_VECTORS + 0x50) //[wem] 16 vectors wasted
+
+// Lego device port ISA offsets - 16-bit access only
+
+//
+// server management and watchdog timer control
+//
+
+#define SERVER_MANAGEMENT_REGISTER 0x506
+#define WATCHDOG_REGISTER 0x504
+
+//
+// PCI interrupt control registers
+//
+
+#define PCI_INTERRUPT_MASTER_REGISTER 0x500
+#define PCI_INTERRUPT_CONFIG_REGISTER 0x502
+
+//
+// Base address of interrupt and mask registers
+//
+// The actual base address is determined by reading the IntRegisterBaseAddr field
+// of the config register. This is presumably the value established by SROM. [wem] check this
+//
+
+#define PCI_INTERRUPT_BASE_REGISTER 0x510
+
+//
+// offsets from base address set in IntRegisterBaseAddr field of
+// PCI_INTERRUPT_CONFIG_REGISTER (set to PCI_INTERRUPT_BASE_REGISTER).
+//
+// NOTE: USHORT accesses can be made to these offsets, or ULONG accesses
+// can be made to the PCI_INTERRUPT_REGISTER_* offsets to read/write
+// the interrupt state and interrupt mask in a single access.
+//
+
+#define MAXIMUM_PCI_INTERRUPT_REGISTERS 4
+#define PCI_INTERRUPT_REGISTER_1 (0x00) // << IO_SHORT_OFFSET)
+#define PCI_INTMASK_REGISTER_1 (0x02)
+#define PCI_INTERRUPT_REGISTER_2 (0x04)
+#define PCI_INTMASK_REGISTER_2 (0x06)
+#define PCI_INTERRUPT_REGISTER_3 (0x08)
+#define PCI_INTMASK_REGISTER_3 (0x0a)
+#define PCI_INTERRUPT_REGISTER_4 (0x0c)
+#define PCI_INTMASK_REGISTER_4 (0x0e)
+
+//
+// PCI vector offsets. Interrupt vectors that originate from register
+// 1 start at 0x11 for bit position 0. So, when servicing an interrupt from
+// register 1, you must add 0x11 to the bit position to get the interrupt
+// vector. Likewise, if you have an interrupt vector, and you would like to
+// determine which interrupt register it resides in, you can use the vector
+// offsets to determine this. All vectors in interrupt register 1 are between
+// 0x11 and 0x20. All vectors in interrupt register 2 are between 0x21 and
+// 0x30, and so on. Subtracting the vector offset for a register from the
+// interrupt vector will give you the bit position of the vector. For example,
+// Vector 0x14 corresponds to bit 3 of interrupt register 1, Vector 0x27
+// corresponds to bit 6 of interrupt register 2, and so on.
+//
+//[wem] used?
+//
+
+#define REGISTER_1_VECTOR_OFFSET 0x00
+#define REGISTER_2_VECTOR_OFFSET 0x10
+#define REGISTER_3_VECTOR_OFFSET 0x20
+#define REGISTER_4_VECTOR_OFFSET 0x30
+
+//
+// I2C Interface -- via PCF8584
+//
+// The PCF8584 presents 2 ports:
+// Control Status Register, or CSR (ISA address 509h) -
+// Register Window (data port) (ISA address 508h) -
+//
+// I2C support is via pcd8584.h,.c
+//
+// I2C bus in Lego has a single device -- the OCP.
+//
+// OCP support is via pcf8574.c
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x508
+#define I2C_INTERFACE_CSR_PORT 0x509
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+
+#endif // _LEGODEF_
diff --git a/private/ntos/nthals/hallego/alpha/lginitnt.c b/private/ntos/nthals/hallego/alpha/lginitnt.c
new file mode 100644
index 000000000..205a87096
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/lginitnt.c
@@ -0,0 +1,1409 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+Copyright (c) 1994,1996 Digital Equipment Corporation
+
+
+Module Name:
+
+ lginitnt.c
+
+Abstract:
+
+ This module implements the platform-specific initialization for
+ a Lego system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+ Initial version for Lego. Adapted from Avanti and Mikasa.
+
+ Gene Morgan 15-Apr-1996
+ Error loggin/correction, OCP model/speed display,
+ screen display of server management features.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "legodef.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "arccodes.h"
+#include "pcf8574.h"
+#include "errframe.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//[wem]
+//[wem] *******************DEBUG*********************
+//[wem]
+
+#ifdef WEMDBG
+extern PVOID DBG_IOBASE;
+
+#define DBGPUTCHR(c) \
+ { UCHAR lsr; \
+ while (1) { \
+ lsr = READ_REGISTER_UCHAR ((PUCHAR)(((ULONG)DBG_IOBASE) | 0x3FD)); \
+ if ((lsr & 0x60) != 0) \
+ break; \
+ } \
+ WRITE_REGISTER_UCHAR ((PUCHAR)(((ULONG)DBG_IOBASE) | 0x3F8), c ); \
+ }
+#else
+
+#define DBGPUTCHR(c)
+
+#endif
+
+VOID
+DBGPUTNL(VOID);
+
+VOID
+DBGPUTHEXB(UCHAR Datum);
+
+VOID
+DBGPUTHEXL(ULONG Datum);
+
+VOID
+DBGPUTHEXP(PVOID Datum);
+
+VOID
+DBGPUTSTR(UCHAR *str);
+
+//[wem]
+//[wem] *******************DEBUG*********************
+//[wem]
+
+//
+// Product Naming data.
+//
+PCHAR HalpFamilyName = "DMCC"; //[wem] ??? real values needed
+PCHAR HalpProductName = "Alpha 21064A PICMG SBC";
+ULONG HalpProcessorNumber = 4;
+
+// Qvas for Server Management and Watchdog Timer functions
+//
+extern PVOID HalpLegoWatchdogQva;
+extern PVOID HalpLegoServerMgmtQva;
+
+//
+// Globals for conveying Cpu and Backplane type
+//
+BOOLEAN HalpLegoCpu;
+BOOLEAN HalpLegoBackplane;
+ULONG HalpLegoCpuType;
+ULONG HalpLegoBackplaneType;
+UCHAR HalpLegoFeatureMask;
+ULONG HalpLegoPciRoutingType;
+
+//
+// True if we are servicing watchdog
+//
+BOOLEAN HalpLegoServiceWatchdog;
+BOOLEAN HalpLegoWatchdogSingleMode;
+BOOLEAN LegoDebugWatchdogIsr;
+
+//
+// True if someone has "enabled" interrupts
+// for a particular server management event.
+//
+BOOLEAN HalpLegoDispatchWatchdog;
+BOOLEAN HalpLegoDispatchNmi;
+BOOLEAN HalpLegoDispatchInt;
+BOOLEAN HalpLegoDispatchPsu;
+BOOLEAN HalpLegoDispatchHalt;
+
+#define MAX_INIT_MSG (80)
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Lego/K2
+//
+// IRQ_H[0] = EPIC Error
+// IRQ_H[1] = PCI Interrupt (if PCI Interrupt controller enabled)
+// IRQ_H[2] = PIC (ISA Device interrupt)
+// IRQ_H[3] = NMI, Server management fatal errors, Halt button
+// IRQ_H[4] = Clock
+// IRQ_H[5] = Watchdog timer, Server Management warning conditions
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 064-127 PCI
+// 128-144 Server Management and Watchdog Timer
+// 144-255 unused, as are all other holes
+//
+//[wem] Here's what it is really like (as per alpharef.h and legodef.h)
+//
+// 000-019 Built-ins DEVICE_VECTORS - MAXIMUM_BUILTIN_VECTOR
+// 020-029 Platform-specific PRIMARY_VECTORS, PRIMARY0_VECTOR - PRIMARY9_VECTOR
+// 048-063 EISA & ISA ISA_VECTORS - MAXIMUM_ISA_VECTOR
+// 080-089 Server Mgmt and Watchdog Timer SERVER_MGMT_VECTORS - MAXIMUM_SERVER_MGMT_VECTORS
+// 100-164 PCI PCI_VECTORS - MAXIMUM_PCI_VECTOR
+// 165-255 unused, as are all other holes
+//
+//[wem] Here's what Lego uses for PCI
+//
+// 117-180 PCI (64h + 11h through 64h + 50h) Same size range, just shifted (16 vectors wasted).
+// PCI_VECTORS - LEGO_MAXIMUM_PCI_VECTOR
+// 181-255 unused, as are all other holes
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+extern ULONG HalpClockFrequency;
+extern ULONG HalpClockMegaHertz;
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpClearInterrupts(
+ );
+
+BOOLEAN
+HalpInitializeLegoInterrupts(
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ VOID
+ );
+
+VOID
+HalpDetermineMachineType(
+ VOID
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Lego/K2 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL private data from the PCR. This must be done before
+ // HalpStallExecution is called.
+ //
+
+ //
+ // Compute integral megahertz first to
+ // avoid rounding errors due to imprecise cycle clock period values.
+ //
+
+ HalpClockMegaHertz =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+ HalpClockFrequency = HalpClockMegaHertz * (1000 * 1000);
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+//jnfix, wkc - init the Eisa interrupts after the chip, don't init the
+// PIC here, fix halenablesysteminterrupt to init the pic
+// interrrupt, as in sable
+
+ //
+ // Initialize the PCI/ISA interrupt controller.
+ //
+
+ HalpInitializeLegoInterrupts();
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ HalpEnable21064HardwareInterrupt( Irq = 5,
+ Irql = SERVER_MGMT_LEVEL,
+ Vector = SERVER_MGMT_VECTOR,
+ Priority = 0 );
+
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+
+ if (HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_FULL) {
+
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = PCI_DEVICE_LEVEL,
+ Vector = PCI_VECTOR,
+ Priority = 0 );
+#if DBG
+ } else {
+ DbgPrint("Irq 1 disabled -- PCI interrupts via SIO\n");
+#endif
+ }
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LEGO_WATCHDOG WdRegister;
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // If desired, turn on the watchdog timer
+ //
+
+ if (HalpLegoServiceWatchdog) {
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ WdRegister.Enabled = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All);
+
+ }
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize error handling for APECS.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = TRUE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ CHAR MhzString[9];
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish the error handler, to reflect the parity checking
+ //
+ HalpEstablishErrorHandler();
+
+ HalpInitializeHAERegisters();
+
+ //
+ // Determine what flavor platform we are on
+ //
+ HalpDetermineMachineType();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+ HalpInitializeProfiler();
+
+ //
+ // Print out a cool-o message
+ //
+
+ sprintf(MsgBuffer,
+ "Digital Equipment Corporation %s %s\n",
+ HalpFamilyName,
+ HalpProductName);
+
+ HalDisplayString(MsgBuffer);
+
+ //
+ // Display system speed on the OCP
+ //
+
+ sprintf (MhzString, " 4A/%3d ", HalpClockMegaHertz);
+ HalpOcpInitDisplay();
+ HalpOcpPutSlidingString(MhzString,8);
+
+ //
+ // Register HAL name and I/O resources
+ //
+
+ HalpRegisterPlatformResources();
+
+ }
+
+ return;
+}
+
+
+
+VOID
+HalpRegisterPlatformResources(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+ UCHAR HalName[256];
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ sprintf(HalName,
+ "%s %s, %d Mhz, PCI/ISA HAL\n",
+ HalpFamilyName,
+ HalpProductName,
+ HalpClockMegaHertz );
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Report the apecs mapping to the Io subsystem
+ //
+ // This is the PCI Memory space that cannot be used by anyone
+ // and therefore the HAL says it is reserved for itself
+ //
+ //[wem] ??? check register resource for PCI memory ?
+ //
+
+ Resource.BusType = PCIBus;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeMemory;
+ Resource.Next = NULL;
+ Resource.u.Start = __8MB;
+ Resource.u.Length = __32MB - __8MB;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+//[wem] ??? What is this?
+// Resource.u.Start = SUPERIO_INDEX_PORT;
+// Resource.u.Length = SUPERIO_PORT_LENGTH;
+// HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaPort = 0x0;
+ Resource.u.DmaChannel = 0x4;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the EPIC/APECS chipset.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // We set HAXR1 to 0. This means no address extension
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0);
+
+ //
+ // We set HAXR2 to 0. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. HAXR2 Not used in address translation
+ // 64K to 16MB VALID. HAXR2 is used in the address translation
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0);
+
+#if 0
+#if DBG
+ DumpEpic();
+#endif // DBG
+#endif
+}
+
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the EPIC/APECS chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0 );
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0 );
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(APECS_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "LegoK2"; // 8 char max.
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocate an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ Called during machine dependent system initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV4_UNCORRECTABLE processorFrame;
+ APECS_UNCORRECTABLE_FRAME LegoUnCorrrectable; //[wem] used?
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
+
+
+VOID
+HalpDetermineMachineType(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Determine which Lego variant of backplane and cpu we're on
+ and set HalpLegoCpu, HalpLegoBackplane, HalpLegoCpuType,
+ and HalpLegoBackplaneType accordingly.
+
+Arguments:
+
+ None.
+
+Return value:
+
+ None.
+
+Notes:
+
+ [wem] ??? Missing - method of detecting OCP Display from HAL
+
+--*/
+{
+ PSYSTEM_ID SystemId;
+ PUCHAR ProductId;
+ LEGO_SRV_MGMT SmRegister;
+ LEGO_WATCHDOG WdRegister;
+ BOOLEAN PsuMask;
+ UCHAR temp;
+
+ //
+ // Get the ProductId, and see if it is one of the
+ // Lego strings.
+ //
+ // Product ID is only eight characters!
+ //
+
+ SystemId = ArcGetSystemId();
+
+ ProductId = &SystemId->ProductId[0];
+
+#if DBG
+ DbgPrint("ProductId: %s, product type: ",ProductId);
+#endif
+
+ if (strstr(ProductId,PLATFORM_NAME_K2_ATA)!=0) {
+
+#if DBG
+ DbgPrint("K2+Atacama");
+#endif
+
+ HalpLegoCpu = TRUE;
+ HalpLegoBackplane = TRUE;
+ HalpLegoCpuType = CPU_LEGO_K2;
+ HalpLegoBackplaneType = BACKPLANE_ATACAMA;
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL;
+
+ } else if (strstr(ProductId,PLATFORM_NAME_K2_GOBI)!=0) {
+
+#if DBG
+ DbgPrint("K2+Gobi");
+#endif
+
+ HalpLegoCpu = TRUE;
+ HalpLegoBackplane = TRUE;
+ HalpLegoCpuType = CPU_LEGO_K2;
+ HalpLegoBackplaneType = BACKPLANE_GOBI;
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL;
+
+ } else if (strstr(ProductId,PLATFORM_NAME_K2_SAHA)!=0) {
+
+#if DBG
+ DbgPrint("K2+Sahara");
+#endif
+
+ HalpLegoCpu = TRUE;
+ HalpLegoBackplane = TRUE;
+ HalpLegoCpuType = CPU_LEGO_K2;
+ HalpLegoBackplaneType = BACKPLANE_SAHARA;
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL;
+
+ } else if (strstr(ProductId,PLATFORM_NAME_LEGO_K2)!=0) {
+
+#if DBG
+ DbgPrint("K2+unknown backplane");
+#endif
+
+ HalpLegoCpu = TRUE;
+ HalpLegoBackplane = FALSE;
+ HalpLegoCpuType = CPU_LEGO_K2;
+ HalpLegoBackplaneType = BACKPLANE_UNKNOWN;
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO;
+
+ } else {
+
+#if DBG
+ DbgPrint("unknown cpu, unknown backplane");
+#endif
+ HalpLegoCpu = FALSE;
+ HalpLegoBackplane = FALSE;
+ HalpLegoCpuType = CPU_UNKNOWN;
+ HalpLegoBackplaneType = BACKPLANE_UNKNOWN;
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO;
+
+ }
+
+#if DBG
+ DbgPrint("\n");
+#endif
+
+ //
+ // Read environment variable to get PCI Interrupt Routing
+ //
+ // If environment variable is absent or unreadable, use
+ // default setting of PCI_INTERRUPT_ROUTING_SIO
+ //
+ {
+ ARC_STATUS Status;
+ CHAR Buffer[16];
+
+ Status = HalGetEnvironmentVariable ("LGPCII",16,Buffer);
+
+#if DBG
+ DbgPrint("Get LGPCII = %s\n",Buffer);
+#endif
+
+ if (Status==ESUCCESS) {
+
+ if (tolower(*Buffer) == 's') {
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO;
+ }
+ else if (tolower(*Buffer) == 'f') {
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL;
+ }
+ else if (tolower(*Buffer) == 'd') {
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_DIRECT;
+ }
+ else {
+ //
+ // Bad setting
+ //
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO;
+ }
+ }
+ else {
+ //
+ // No setting - use default
+ //
+ HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO;
+ }
+ }
+
+ HalDisplayString ("DMCC Interrupt Routing: ");
+
+ HalDisplayString ((HalpLegoPciRoutingType==PCI_INTERRUPT_ROUTING_SIO) ? "ISA PIRQs" :
+ (HalpLegoPciRoutingType==PCI_INTERRUPT_ROUTING_DIRECT) ? "Interrupt Registers" :
+ (HalpLegoPciRoutingType==PCI_INTERRUPT_ROUTING_FULL) ? "Interrupt Accelerator" : "Unknown!");
+
+ HalDisplayString ("\n");
+
+#if DBG
+ DbgPrint("\n");
+ DbgPrint("Interrupt Routing is via ");
+ DbgPrint((HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_SIO)
+ ? "SIO.\n\r" : "Interrupt accelerator.\n\r");
+#endif
+
+ // Setup feature mask
+ //
+ HalpLegoFeatureMask = 0;
+ if (HalpLegoCpu) {
+
+ // Is watchdog timer present?
+ //
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ if (WdRegister.All != 0xffff) {
+ HalpLegoFeatureMask |= LEGO_FEATURE_WATCHDOG;
+ }
+
+ // Is server management register present?
+ //
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ if (SmRegister.All != 0xffff) {
+ HalpLegoFeatureMask |= LEGO_FEATURE_SERVER_MGMT;
+
+ // Is multiple PSU support present?
+ // Write 0 then 1 into PSU mask bit, and read it
+ // back each time to see if setting sticks.
+ //
+ PsuMask = (SmRegister.PsuMask == 1); // save setting
+ SmRegister.PsuMask = 0; // clear mask
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+
+ if (SmRegister.PsuMask == 0) {
+ //
+ // mask bit is cleared
+ //
+ SmRegister.PsuMask = 1; // set mask
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+
+ if (SmRegister.PsuMask == 1) {
+ //
+ // mask bit is set. Feature is
+ // present, restore mask bit's original setting
+ //
+ HalpLegoFeatureMask |= LEGO_FEATURE_PSU;
+ SmRegister.PsuMask = (PsuMask) ? 1 : 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+ }
+ }
+ }
+ temp = HalpLegoFeatureMask;
+ if (temp != 0) {
+ HalDisplayString ("DMCC Platform Features: ");
+ if ((temp & LEGO_FEATURE_WATCHDOG) != 0) {
+ temp &= ~LEGO_FEATURE_WATCHDOG;
+ HalDisplayString ("Watchdog Timer");
+ HalDisplayString ((temp!=0)?", ":".");
+ }
+ if ((temp & LEGO_FEATURE_SERVER_MGMT) != 0) {
+ temp &= ~LEGO_FEATURE_SERVER_MGMT;
+ HalDisplayString ("Server Management");
+ HalDisplayString ((temp!=0)?", ":".");
+ }
+ if ((HalpLegoFeatureMask & LEGO_FEATURE_PSU) != 0) {
+ HalDisplayString ("Multiple PSU Support.");
+ }
+ HalDisplayString ("\n");
+ } else {
+ HalDisplayString("No LEGO Platform Features detected!\n");
+ }
+
+ if ((HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) != 0) {
+
+ //
+ // Read environment variable to get Watchdog Timer setting
+ //
+ // If environment variable is absent or unreadable, use
+ // default setting of NOT HalpLegoServiceWatchdog
+ //
+
+ {
+ ARC_STATUS Status;
+ CHAR Buffer[16];
+
+ Status = HalGetEnvironmentVariable ("LGWD",16,Buffer);
+
+ #if DBG
+ DbgPrint("Get LGWD = %s\n",Buffer);
+ #endif
+
+ if (Status==ESUCCESS) {
+
+ if (Buffer[0]=='0') {
+ HalpLegoServiceWatchdog = TRUE;
+ HalpLegoWatchdogSingleMode = FALSE;
+ }
+ else if (Buffer[0]=='1') {
+ HalpLegoServiceWatchdog = TRUE;
+ HalpLegoWatchdogSingleMode = TRUE;
+ }
+ else {
+ HalpLegoServiceWatchdog = FALSE;
+ }
+
+ //
+ // Check for special debug variable -- if set,
+ // don't service the watchdog in the clock ISR
+ //
+
+ Status = HalGetEnvironmentVariable ("LGWDD",16,Buffer);
+
+ if (Status==ESUCCESS) {
+ LegoDebugWatchdogIsr = TRUE;
+ }
+ else {
+ LegoDebugWatchdogIsr = FALSE;
+ }
+
+ }
+ else {
+ //
+ // No setting - use default
+ //
+
+ HalpLegoServiceWatchdog = FALSE;
+ HalpLegoWatchdogSingleMode = FALSE;
+ LegoDebugWatchdogIsr = FALSE;
+ }
+ }
+
+ HalDisplayString("DMCC Watchdog Timer is ");
+ if (HalpLegoServiceWatchdog) {
+ HalDisplayString("active ");
+ HalDisplayString((HalpLegoWatchdogSingleMode)
+ ? "(single timeout)."
+ : "(double timeout).");
+ }
+ else {
+ HalDisplayString("inactive.");
+ }
+ HalDisplayString("\n");
+ }
+ else {
+ HalpLegoServiceWatchdog = FALSE;
+ }
+ }
+}
diff --git a/private/ntos/nthals/hallego/alpha/lgintr.s b/private/ntos/nthals/hallego/alpha/lgintr.s
new file mode 100644
index 000000000..f9de5d6ef
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/lgintr.s
@@ -0,0 +1,121 @@
+// TITLE("Lego PCI/ServerMgmt Interrupt Handler")
+//++
+//
+// Copyright (c) 1994,1995 Digital Equipment Corporation
+//
+// Module Name:
+//
+// lgintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for Lego
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 29-Apr-1994 James Livingston
+// Adapt from Avanti ebintr.s for Mikasa
+//
+// 3-Nov-1995 Gene Morgan
+// Initial version for Lego. Adapt from Mikasa's mkintr.s,
+// add Server Management dispatch.
+//
+//--
+
+#include "halalpha.h"
+
+ SBTTL("Lego PCI Interrupt Handler")
+//++
+//
+// VOID
+// HalpPciInterruptHandler
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on the PCI I/O
+// bus. The function is responsible for calling HalpPciDispatch to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpPciDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// PCI interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPciInterruptHandler)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpPciDispatch // dispatch the interrupt to the PCI handler
+
+ ret zero, (ra) // will never get here
+
+ .end HalpPciInterruptHandler
+
+
+ SBTTL("Lego Server Management Interrupt Handler")
+//++
+//
+// VOID
+// HalpPciInterruptHandler
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on the
+// CPU IRQ pin allocated to Lego Server Management functions.
+// The function is responsible for calling HalpServerMgmtDispatch() to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpServerMgmtDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// Server Management interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpServerMgmtInterruptHandler)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpServerMgmtDispatch // dispatch the interrupt to the PCI handler
+
+ ret zero, (ra) // will never get here
+
+ .end HalpServerMgmtInterruptHandler
diff --git a/private/ntos/nthals/hallego/alpha/lgintsup.c b/private/ntos/nthals/hallego/alpha/lgintsup.c
new file mode 100644
index 000000000..2b2e73beb
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/lgintsup.c
@@ -0,0 +1,732 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992,1993,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ lgintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Lego systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ James Livingston (DEC) 30-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+ Gene Morgan (Digital) 25-Oct-1995
+ Initial version for Lego. Adapted from Mikasa's mkintsup.c.
+
+ Gene Morgan 15-Apr-1996
+ Service watchdog timer.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "legodef.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Server management and watchdog timer control
+//
+extern PVOID HalpLegoServerMgmtQva;
+extern PVOID HalpLegoWatchdogQva;
+
+extern BOOLEAN HalpLegoServiceWatchdog;
+extern BOOLEAN HalpLegoWatchdogSingleMode;
+extern BOOLEAN LegoDebugWatchdogIsr;
+
+extern BOOLEAN HalpLegoDispatchNmi;
+extern BOOLEAN HalpLegoDispatchHalt;
+
+//
+// Global to control whether halt button triggers breakpoint
+// 0 -> no breakpoint
+// !0 -> breakpoint when halt button is pressed
+//
+ULONG HalpHaltButtonBreak = 0;
+
+//
+// PCI Interrupt control
+//
+extern PVOID HalpLegoPciInterruptConfigQva;
+extern PVOID HalpLegoPciInterruptMasterQva;
+extern PVOID HalpLegoPciInterruptRegisterBaseQva;
+extern PVOID HalpLegoPciInterruptRegisterQva[];
+extern PVOID HalpLegoPciIntMaskRegisterQva[];
+
+//
+// Import globals declared in HalpMapIoSpace.
+//
+
+extern PVOID HalpServerControlQva;
+
+// Count NMI interrupts
+//
+ULONG NMIcount = 0;
+
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+KINTERRUPT HalpPciInterrupt;
+KINTERRUPT HalpServerMgmtInterrupt;
+
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// Declare the interrupt handler for the PCI bus. The interrupt dispatch
+// routine, HalpPciDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpPciInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Declare the interrupt handler for Server Management and Watchdog Timer
+// functions. The interrupt dispatch routine, HalpServermgmtDispatch, is
+// called from this handler.
+//
+
+BOOLEAN
+HalpServerMgmtInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Declare the interrupt handler for the EISA bus. The interrupt dispatch
+// routine, HalpEisaDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpInitializePciInterrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeServerMgmtInterrupts(
+ VOID
+ );
+
+
+//
+// External routines
+//
+
+BOOLEAN
+LegoServerMgmtDelayedShutdown(
+ ULONG DelaySeconds
+ );
+
+VOID
+LegoServerMgmtReportFatalError(
+ USHORT SmRegAll
+ );
+
+
+
+BOOLEAN
+HalpInitializeLegoInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the ISA interrupt controller; Lego's SIO-based interrupt controller is
+ compatible with Avanti and with the EISA interrupt contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive);
+
+ //
+ // Initialize the interrupt dispatchers for PCI & Server management interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpPciInterrupt,
+ HalpPciInterruptHandler,
+ (PVOID) HalpLegoPciInterruptMasterQva, // Service Context
+ (PKSPIN_LOCK)NULL,
+ PCI_VECTOR,
+ PCI_DEVICE_LEVEL,
+ PCI_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpPciInterrupt )) {
+ return(FALSE);
+ }
+
+ KeInitializeInterrupt( &HalpServerMgmtInterrupt,
+ HalpServerMgmtInterruptHandler,
+ (PVOID) HalpLegoServerMgmtQva, // Service Context is...
+ (PKSPIN_LOCK)NULL,
+ SERVER_MGMT_VECTOR,
+ SERVER_MGMT_LEVEL,
+ SERVER_MGMT_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpServerMgmtInterrupt )) {
+ return(FALSE);
+ }
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // We must initialize the SIO's PICs, for ISA interrupts.
+ //
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // There's no initialization required for the Lego PCI interrupt
+ // "controller," as it's the wiring of the hardware, rather than a
+ // PIC like the 82c59 that directs interrupts. We do set the IMR to
+ // zero to disable all interrupts, initially.
+ //
+
+ HalpInitializePciInterrupts();
+
+ //
+ // Setup server management interrupts.
+ // On return, server management interrupts will be unmasked,
+ // but secondary dispatch will not be performed unless appropriate
+ // boolean has been set due to enable call.
+ //
+
+ HalpInitializeServerMgmtInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register. Note that the other bits should be left as
+ // they are, according to the chip's documentation.
+ //
+ //[wem] ?? Avanti simply writes zero to NmiEnable -- OK
+
+ DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&DataByte))->NmiDisable = 0;
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte);
+
+#ifdef DBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n", DataByte);
+#endif
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ LEGO_SRV_MGMT SmRegister;
+ UCHAR NmiControl, NmiStatus;
+ BOOLEAN GotSerr, GotIochk, GotSmFan, GotSmTemp, GotHalt;
+
+ NMIcount++;
+
+#if DBG
+ if (NMIcount<5) {
+ DbgPrint("II<NMI><");
+ }
+ if (NMIcount % 100 == 0) {
+ DbgPrint("II<NMI><%08x><", NMIcount);
+ }
+#endif
+
+ GotSerr = GotIochk = GotSmFan = GotSmTemp = GotHalt = FALSE;
+
+ //
+ // Set the Eisa NMI disable bit. We do this to mask further NMI
+ // interrupts while we're servicing this one.
+ //
+ NmiControl = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 1;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl);
+
+#ifdef DBG
+ DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl);
+#endif
+
+ NmiStatus =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (NmiStatus & 0x80) {
+ GotSerr = TRUE;
+
+#ifdef DBG
+ DbgPrint("HalHandleNMI: Parity Check / Parity Error\n");
+ DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus);
+#endif
+ HalAcquireDisplayOwnership(NULL);
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return (TRUE);
+ }
+
+ if (NmiStatus & 0x40) {
+ GotIochk = TRUE;
+#ifdef DBG
+ DbgPrint("HalHandleNMI: Channel Check / IOCHK\n");
+ DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus);
+#endif
+ HalAcquireDisplayOwnership(NULL);
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return (TRUE);
+ }
+
+ // Read server management register
+ // Events that can be reported as NMI are:
+ // Enclosure temperature too high
+ // CPU Fan failure
+ //
+ // For now, generate a bugcheck.
+ // [wem] Future: perform secondary dispatch to give
+ // driver shot at reporting problem.
+ //
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+
+ GotSmFan = SmRegister.CpuFanFailureNmi == 1;
+ GotSmTemp = SmRegister.EnclTempFailureNmi == 1;
+
+ if (GotSmFan || GotSmTemp) {
+
+#ifdef DBG
+ DbgPrint("HalHandleNMI: Server management NMI\n");
+ DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus);
+ DbgPrint("HalHandleNMI: Server Management Status = 0x%x\n", SmRegister);
+#endif
+
+ //
+ // If secondary dispatch enabled, do it now.
+ //
+#if 0
+ if (HalpLegoDispatchNmi
+ && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SM_ERROR_VECTOR])(
+ PCR->InterruptRoutine[SM_ERROR_VECTOR],
+ TrapFrame)
+ ) {
+ return TRUE;
+ }
+#endif
+
+ //
+ // Build uncorrectable error frame and
+ // prepare for orderly shutdown
+ //
+ // The delayed shutdown depends on watchdog timer support
+ // A power off cannot be directly done since KeBugChk() turns
+ // off interrupts, so there's no way to get control back.
+ //
+ // WARNING: Pick a delay that allows a dump to complete.
+ //
+
+ LegoServerMgmtReportFatalError(SmRegister.All);
+ LegoServerMgmtDelayedShutdown(8); // Issue reset in 8 seconds
+
+ HalAcquireDisplayOwnership(NULL);
+
+ HalDisplayString ("NMI: Hardware Failure -- ");
+ HalDisplayString ((SmRegister.CpuFanFailureNmi==1) ? "CPU fan failed."
+ : "Enclosure termperature too high.");
+ HalDisplayString ("\nSystem Power Down will be attempted in 8 seconds...\n\n");
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return (TRUE);
+ }
+
+
+ //
+ // Halt button was hit.
+ //
+ // [wem] Perform second-level dispatch here too?
+ //
+ if (!GotSerr && !GotIochk && !GotSmFan && !GotSmTemp) {
+
+ //
+ // If secondary dispatch enabled, do it now.
+ //
+#if 0
+ if (HalpLegoDispatchHalt
+ && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[HALT_BUTTON_VECTOR])(
+ PCR->InterruptRoutine[HALT_BUTTON_VECTOR],
+ TrapFrame)
+ ) {
+ return TRUE;
+ }
+#endif
+
+ GotHalt = TRUE;
+ HalDisplayString ("NMI: Halt button pressed.\n");
+
+ if (HalpHaltButtonBreak) {
+ DbgBreakPoint();
+ }
+
+ return (TRUE);
+ }
+
+ //
+ // Clear and re-enable SERR# and IOCHK#, then re-enable NMI
+ //
+
+#ifdef DBG
+ DbgPrint("HalHandleNMI: Shouldn't get here!\n");
+#endif
+
+ if (GotSerr) {
+#ifdef DBG
+ DbgPrint("HalHandleNMI: Resetting SERR#; NMI count = %d\n", NMIcount);
+#endif
+ //
+ // Reset SERR# (and disable it), then re-enable it.
+ //
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04);
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0);
+ }
+
+ if (GotIochk) {
+#ifdef DBG
+ DbgPrint("HalHandleNMI: Resetting IOCHK#; NMI count = %d\n", NMIcount);
+#endif
+ //
+ // Reset IOCHK# (and disable it), then re-enable it.
+ //
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x08);
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0);
+ }
+
+ if (GotSmFan || GotSmTemp) {
+ //
+ // Reset Server management condition.
+ //
+ // Interrupt must be cleared or the NMI will continue
+ // to occur.
+ //
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ if (GotSmFan) {
+ SmRegister.CpuFanFailureNmi = 1;
+ }
+ else {
+ SmRegister.EnclTempFailureNmi = 1;
+ }
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+ }
+
+ //
+ // Clear the Eisa NMI disable bit. This re-enables NMI interrupts,
+ // now that we're done servicing this one.
+ //
+ NmiControl = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 0;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl);
+#ifdef DBG
+ DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl);
+#endif
+
+ return(TRUE);
+}
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Lego comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LEGO_WATCHDOG WdRegister;
+
+ static LEGO_WATCHDOG WdRegisterDbg;
+ static ULONG DbgWdCnt = 0;
+ static ULONG WdNextService = 0;
+ static BOOLEAN WdIntervalSet = FALSE;
+
+ //
+ // Make watchdog service interval a function of the timer period.
+ //
+
+#if 1
+ static ULONG WdServiceIntervals[8] = {1, 1, 5, 15, 100, 600, 3000, 20000};
+#else
+ static ULONG WdServiceIntervals[8] = {1, 1, 1, 1, 1, 1, 1, 1};
+#endif
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ //
+ // If we are to service the Watchdog Timer, do it here
+ //
+ // Setting Phase to one will restart the timer...
+ // [wem] this needs more work. For example, no need to touch it each clock tick!...
+ //
+
+ if (HalpLegoServiceWatchdog) {
+
+ if (WdNextService==0) {
+
+ //
+ // read register to get service interval
+ //
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ WdNextService = WdServiceIntervals[WdRegister.TimerOnePeriod];
+
+#if DBG
+ if (!WdIntervalSet) {
+ DbgPrint(" <Watchdog:%04x> ",WdRegister.All);
+ DbgPrint(" <WdInterval:%d> ",WdNextService);
+ WdRegisterDbg.All = WdRegister.All;
+ WdIntervalSet = TRUE;
+ }
+#endif
+ }
+
+ WdNextService--;
+
+ //
+ // If service interval falls to zero, read register to service timer
+ //
+
+ if (WdNextService==0) {
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+
+#if DBG
+
+ if (WdRegisterDbg.All != WdRegister.All) {
+ WdRegisterDbg.All = WdRegister.All;
+ DbgWdCnt = 0;
+ }
+
+ if (DbgWdCnt < 2) {
+ DbgPrint(" <Watchdog:%04x> ",WdRegister.All);
+ }
+
+ if ((DbgWdCnt % 10000)==0) {
+ DbgPrint(" <Watchdog:%04x> ",WdRegister.All);
+ DbgWdCnt = 1;
+ }
+
+ DbgWdCnt++;
+#endif
+
+ //
+ // Reset the timer. This is done by writing 1 then 0
+ // to the Watchdog register's Phase bit
+ //
+ // If LegoDebugWatchdogIsr is true, let watchdog timer expire.
+ // This will result in a watchdog interrupt or a system reset
+ // depending on the watchdog mode.
+ //
+
+ if (!LegoDebugWatchdogIsr) {
+#if 0
+ if (HalpLegoWatchdogSingleMode) {
+ WdRegister.Mode = WATCHDOG_MODE_1TIMER;
+ }
+#endif
+ WdRegister.Phase = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All);
+ WdRegister.Phase = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All);
+ }
+ }
+ }
+}
diff --git a/private/ntos/nthals/hallego/alpha/lgmapio.c b/private/ntos/nthals/hallego/alpha/lgmapio.c
new file mode 100644
index 000000000..02f14a08b
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/lgmapio.c
@@ -0,0 +1,232 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ lgmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Lego systems.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+
+ Initial version for Lego. Adapted from Avanti and Mikasa
+
+
+--*/
+
+#include "halp.h"
+#include "legodef.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+//
+// SIO's Int Ack Register (if it exists)
+//
+// Used when interrupt accelerator is active, and we
+// must not generate PCI Interrupt Acknowledge cycles
+// for ISA devices.
+//
+
+PVOID HalpSioIntAckQva;
+
+//
+// Server management and watchdog timer control
+//
+PVOID HalpLegoServerMgmtQva;
+PVOID HalpLegoWatchdogQva;
+
+//
+// PCI Interrupt control
+//
+PVOID HalpLegoPciInterruptConfigQva;
+PVOID HalpLegoPciInterruptMasterQva;
+PVOID HalpLegoPciInterruptRegisterBaseQva;
+PVOID HalpLegoPciInterruptRegisterQva[4];
+PVOID HalpLegoPciIntMaskRegisterQva[4];
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for Lego
+ system using the Quasi VA mechanism.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( APECS_PCI_IO_BASE_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+
+ //
+ // Interrupt Acknowledge ports
+ //
+
+ HalpEisaIntAckBase = HAL_MAKE_QVA( APECS_PCI_INTACK_BASE_PHYSICAL );
+ HalpSioIntAckQva = (PVOID)((ULONG)PciIoSpaceBase + 0x238);
+
+ //
+ // CMOS ram addresses encoded in nvram.c - kept for commonality
+ // in environ.c
+ //
+ //[wem] NOTE: halavant version of ebmapio.c sets HalpCMOSRamBase to (PVOID)0 ???
+ //
+
+ HalpCMOSRamBase = (PVOID) ((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ //
+ // Map Lego server management and watchog control registers
+ //
+
+ HalpLegoServerMgmtQva = (PVOID)((ULONG)PciIoSpaceBase | SERVER_MANAGEMENT_REGISTER);
+ HalpLegoWatchdogQva = (PVOID)((ULONG)PciIoSpaceBase | WATCHDOG_REGISTER);
+
+ //
+ // Map Lego PCI Interrupt control registers
+ //
+
+ HalpLegoPciInterruptConfigQva = (PVOID)((ULONG)PciIoSpaceBase | PCI_INTERRUPT_CONFIG_REGISTER);
+ HalpLegoPciInterruptMasterQva = (PVOID)((ULONG)PciIoSpaceBase | PCI_INTERRUPT_MASTER_REGISTER);
+ HalpLegoPciInterruptRegisterBaseQva = (PVOID)((ULONG)PciIoSpaceBase | PCI_INTERRUPT_BASE_REGISTER);
+
+ //
+ // Lego PCI interrupt state and interrupt mask registers
+ //
+ // NOTE: The InterruptRegister Qvas can be used to access the interrupt
+ // state (via USHORT), or the interrupt state and interrupt mask (via ULONG).
+ // The IntMaskRegister Qvas can only be used to access the interrupt
+ // mask (via USHORT).
+ //
+
+ HalpLegoPciIntMaskRegisterQva[0] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_1);
+ HalpLegoPciIntMaskRegisterQva[1] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_2);
+ HalpLegoPciIntMaskRegisterQva[2] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_3);
+ HalpLegoPciIntMaskRegisterQva[3] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_4);
+
+ HalpLegoPciInterruptRegisterQva[0] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_1);
+ HalpLegoPciInterruptRegisterQva[1] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_2);
+ HalpLegoPciInterruptRegisterQva[2] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_3);
+ HalpLegoPciInterruptRegisterQva[3] =
+ (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_4);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/hallego/alpha/lgsysint.c b/private/ntos/nthals/hallego/alpha/lgsysint.c
new file mode 100644
index 000000000..e735721bf
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/lgsysint.c
@@ -0,0 +1,679 @@
+/*++
+
+Copyright (c) 1993,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ lgsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Lego system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+ Initial version for Lego. Adapted from Avanti and Mikasa
+
+ Gene Morgan 15-Apr-1996
+ Remove debugging code.
+ Add error logging for server management events (e.g., fan and temp)
+
+
+--*/
+
+#include "halp.h"
+#include "legodef.h"
+#include "axp21064.h"
+
+
+
+extern ULONG HalpLegoPciRoutingType;
+extern BOOLEAN HalpServerMgmtLoggingEnabled;
+
+//
+// External function prototypes
+//
+
+ULONG
+HalpGet21064CorrectableVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+//
+// Local function prototypes
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableServerMgmtInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpEnableServerMgmtInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the
+ // Server Management interrupts, then disable the appropriate
+ // interrupt.
+ //
+ if (Vector >= SERVER_MGMT_VECTORS &&
+ Vector < MAXIMUM_SERVER_MGMT_VECTOR &&
+ Irql == SERVER_MGMT_LEVEL) {
+
+#if DBG
+ DbgPrint("Dm<%02x>",Vector);
+#endif
+ HalpDisableServerMgmtInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the
+ // ISA interrupts, then disable the ISA interrupt.
+ //
+ else if (Vector >= ISA_DEVICE_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+
+#if DBG
+ DbgPrint("Ds<%02x>",Vector);
+#endif
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the
+ // PCI interrupts, then disable the PCI interrupt.
+ //
+ else if (Vector >= PCI_DEVICE_VECTORS &&
+ Vector < LEGO_MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL) {
+
+#if DBG
+ DbgPrint("Dp<%02x>",Vector);
+#endif
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ else {
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+#if DBG
+ DbgPrint("Dc0<%02x>",Vector);
+#endif
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+#if DBG
+ DbgPrint("Dc1<%02x>",Vector);
+#endif
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Disable the correctable error interrupt.
+ //
+
+ {
+ EPIC_ECSR Ecsr;
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+ Ecsr.Dcei = 0x0;
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all );
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+
+ //
+ // Disable logging of server management errors as well
+ //
+
+ HalpServerMgmtLoggingEnabled = FALSE;
+
+ break;
+ }
+
+#if DBG
+ default:
+
+ //
+ // unrecognized
+ //
+
+ DbgPrint("D?<%02x>",Vector);
+#endif
+ } //end switch Vector
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt;
+ LevelSensitive or Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the
+ // Server Management interrupts, then enable the appropriate
+ // interrrupt.
+ //
+ if (Vector >= SERVER_MGMT_VECTORS &&
+ Vector < MAXIMUM_SERVER_MGMT_VECTOR &&
+ Irql == SERVER_MGMT_LEVEL) {
+
+#if DBG
+ DbgPrint("Em<%02x,%02x>",Vector,InterruptMode);
+#endif
+ HalpEnableServerMgmtInterrupt(Vector,InterruptMode);
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the
+ // ISA interrupts, then enable the ISA interrupt and
+ // set the Level/Edge register.
+ //
+ else if (Vector >= ISA_DEVICE_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+
+#if DBG
+ DbgPrint("Es<%02x,%02x>",Vector,InterruptMode);
+#endif
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the
+ // PCI interrupts, then enable the PCI interrupt.
+ //
+ else if (Vector >= PCI_DEVICE_VECTORS &&
+ Vector < LEGO_MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL) {
+
+#if DBG
+ DbgPrint("Ep<%02x,%02x>",Vector,InterruptMode);
+#endif
+ HalpEnablePciInterrupt(Vector, InterruptMode);
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+ else {
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+#if DBG
+ DbgPrint("Ec0<%02x,%02x>",Vector,Irql);
+#endif
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+#if DBG
+ DbgPrint("Ec1<%02x,%02x>",Vector,Irql);
+#endif
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Enable the correctable error interrupt.
+ //
+
+ {
+ EPIC_ECSR Ecsr;
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+ Ecsr.Dcei = 0x1;
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all );
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+
+ //
+ // Will log server management errors as well
+ //
+
+ HalpServerMgmtLoggingEnabled = TRUE;
+
+ Enabled = TRUE;
+ break;
+
+ }
+
+#if DBG
+ default:
+
+ //
+ // not enabled
+ //
+
+ DbgPrint("E?<%02x,%02x,%02x>",Vector,Irql,InterruptMode);
+#endif
+
+ } //end switch Vector
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+#if DBG
+ DbgPrint("GIV< l:%02x, v:%02x => ",
+ BusInterruptLevel,BusInterruptVector);
+#endif
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters and
+ // correctable errors in the 21064.
+ //
+
+ Vector = HalpGet21064PerformanceVector(BusInterruptLevel,Irql);
+
+ if (Vector != 0) {
+
+#if DBG
+ DbgPrint("PIperf: i:%02x, v:%02x >.", Vector, *Irql);
+#endif
+
+ return Vector; // Performance counter interrupt
+ }
+
+ Vector = HalpGet21064CorrectableVector( BusInterruptLevel,Irql);
+
+ if (Vector != 0) {
+
+#if DBG
+ DbgPrint("PIcorr: i:%02x, v:%02x >.", Vector, *Irql);
+#endif
+
+ return Vector; // Correctable error interrupt
+ }
+
+ // Check for unrecognized processor interrupt.
+ //
+ if (Vector == 0) {
+ *Irql = 0;
+ *Affinity = 0;
+ }
+
+#if DBG
+ DbgPrint("PI: i:00, v:00 >.");
+#endif
+ return Vector; // zero if unrecognized interrupt
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+ // Assume interrupt can be mapped to Lego System Management.
+ // [wem] ??? check this ?
+ //
+ *Irql = SERVER_MGMT_LEVEL;
+
+ // The vector is equal to the specified bus level plus
+ // SERVER_MGMT_VECTORS.
+ //
+#if DBG
+ DbgPrint("SM: i:%02x, v:%02x >.",
+ SERVER_MGMT_LEVEL,
+ BusInterruptLevel + SERVER_MGMT_VECTORS);
+#endif
+ return(BusInterruptLevel + SERVER_MGMT_VECTORS);
+
+ case PCIBus:
+
+ //[wem] if interrupt accelerator is enabled, direct
+ // PCI interrupts via the PCI_DEVICE_VECTORS
+ // Otherwise, fall into the ISA case...
+ //
+ if (HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_FULL) {
+
+ //
+ // All PCI devices coming in on same CPU IRQ pin
+ //
+ *Irql = PCI_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level
+ // plus the PCI Device Vector base
+ //
+#if DBG
+ DbgPrint("PCI: i:%02x, v:%02x >.",
+ PCI_DEVICE_LEVEL,
+ BusInterruptLevel + PCI_DEVICE_VECTORS);
+#endif
+ return((BusInterruptLevel) + PCI_DEVICE_VECTORS);
+
+#if DBG
+ } else {
+
+ //
+ // Fall into ISA interrupt handling code
+ //
+
+ DbgPrint("PCI*");
+#endif
+ }
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus
+ // the ISA_VECTOR. This is assuming that the ISA levels
+ // not assigned Interrupt Levels in the Beta programming
+ // guide are unused in the LCA system. Otherwise, need
+ // a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+ //
+
+#if DBG
+ DbgPrint("ISA: i:%02x, v:%02x >.",
+ ISA_DEVICE_LEVEL,
+ BusInterruptLevel + ISA_DEVICE_VECTORS);
+#endif
+ return(BusInterruptLevel + ISA_DEVICE_VECTORS);
+
+ case Eisa:
+
+ //[wem] Should never occur
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+ return(BusInterruptLevel + EISA_VECTORS);
+
+ default:
+
+ //
+ // Not an interface supported on Lego systems
+ //
+#if DBG
+ DbgPrint("LGSYSINT: InterfaceType (%d) not supported.\n",
+ InterfaceType);
+#endif
+#if DBG
+ DbgPrint("?: i:00, v:00 >.");
+#endif
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Avanti because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/hallego/alpha/machdep.h b/private/ntos/nthals/hallego/alpha/machdep.h
new file mode 100644
index 000000000..264be0ec2
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/machdep.h
@@ -0,0 +1,46 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+
+ Initial version for Lego. Adapted from Avanti.
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Lego platform-specific definitions.
+//
+
+#include "legodef.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/hallego/alpha/memory.c b/private/ntos/nthals/hallego/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/nvenv.c b/private/ntos/nthals/hallego/alpha/nvenv.c
new file mode 100644
index 000000000..ba5a5c8f7
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/nvenv.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvenv.c"
diff --git a/private/ntos/nthals/hallego/alpha/nvram.c b/private/ntos/nthals/hallego/alpha/nvram.c
new file mode 100644
index 000000000..879c41c68
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/nvram.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvram.c"
diff --git a/private/ntos/nthals/hallego/alpha/pcd8584.c b/private/ntos/nthals/hallego/alpha/pcd8584.c
new file mode 100644
index 000000000..981a3aca3
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcd8584.c
@@ -0,0 +1,653 @@
+/*++
+
+Copyright (c) 1994,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ pcd8584.c
+
+Abstract:
+
+ This module contains the routines that support operations
+ on the PCD8584 I2C bus controller.
+
+Author:
+
+ James Livingston [DEC] 13-Sep-1994
+
+Environment:
+
+ Alpha AXP ARC firmware
+
+Revision History:
+
+ Gene Morgan (Digital) 08-Nov-1995
+ Adapted for LEGO platforms from Mikasa
+
+ Gene Morgan 15-Apr-1996
+ Cleanup, fix OCP corruption problem.
+
+
+--*/
+
+#include <stdarg.h>
+#include "halp.h"
+#include "string.h"
+#include "arccodes.h"
+#include "pcd8584.h"
+
+extern PVOID HalpEisaControlBase;
+
+BOOLEAN PcdValid = FALSE;
+
+//
+// I2C data and csr ports.
+//
+ULONG I2cInterfaceCsrPort;
+ULONG I2cInterfaceDataPort;
+
+//
+// Data for testing internal registers in the PCD8584 I2C bus controller.
+//
+I2C_TEST_REG I2cTestReg[] = { "CSR", I2C_STATUS, 0x3d, 0xff,
+ "S0", I2C_DATA, 0x7f, I2C_S0,
+ "S2", I2C_DATA, 0x1f, I2C_S2,
+ "S3", I2C_DATA, 0xff, I2C_S3,
+ };
+
+//
+// External prototypes
+//
+
+static VOID
+FwStallExecution (
+ IN ULONG MicroSeconds
+ )
+{
+ HalpStallExecution(MicroSeconds);
+}
+
+//
+// Private function prototypes
+//
+
+VOID
+FwPcdWrite(
+ IN UCHAR Argument,
+ IN UCHAR Register
+ );
+
+UCHAR
+FwPcdRead(
+ IN UCHAR Register
+ );
+
+ARC_STATUS
+FwPcdStatusWaitWithTimeout(
+ BOOLEAN BusIdle,
+ BOOLEAN PendingInterrupt,
+ BOOLEAN AckByte,
+ ULONG Timeout
+ );
+
+//
+// Code begins.
+//
+
+ARC_STATUS
+FwPcdInit(
+ ULONG I2cCsrPort,
+ ULONG I2cDataPort
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the PCD8584 I2C controller for use in
+ writing to the LCD display on the Mikasa Operator Control Panel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS - Everything's ready to go.
+ ENODEV - Something's wrong.
+
+--*/
+
+{
+ UCHAR Datum;
+ UCHAR DataRead;
+ ARC_STATUS Status;
+ ULONG i;
+
+ //
+ // Set the csr and data port for I2C bus.
+ //
+ I2cInterfaceCsrPort = I2cCsrPort;
+ I2cInterfaceDataPort = I2cDataPort;
+
+#if 0 // Done by firmware -- don't do it again
+
+ //
+ // Write the PIN bit to "1", as Dave Baird discovered was a
+ // requirement some years back.
+ //
+ // This should turn off ESO
+ //
+ //[wem] ??? needed for Lego ?
+ //
+ FwPcdWrite(I2C_PIN, I2C_STATUS);
+ FwPcdWrite(I2C_PIN, I2C_STATUS);
+
+ //
+ // Initialize the PCD8584 with its own node address. A write
+ // to this register must be the first access to the device
+ // after a reset.
+ //
+ //[wem] OK for Lego.
+ //
+ Datum = (I2C_MASTER_NODE >> 1) & 0x7f;
+ FwPcdWrite(I2C_S0P, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also
+ FwPcdWrite(I2C_S0P, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also
+ FwPcdWrite(Datum, I2C_DATA);
+ FwPcdWrite(Datum, I2C_DATA);
+
+ //
+ // Define clock frequencies for the I2C bus. After this is done
+ // we should be able to write to a node on the bus.
+ //
+ //[wem] OK for Lego.
+ //
+ FwPcdWrite(I2C_S2, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also
+ FwPcdWrite(I2C_S2, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also
+ FwPcdWrite(I2C_CLOCK, I2C_DATA);
+ FwPcdWrite(I2C_CLOCK, I2C_DATA);
+
+ // jwlfix - this is to see what we can read from the PCD8584.
+ // We'll want to get rid of it when things start doing
+ // what we want. For now, it's a good verification that
+ // we're able to reach the device.
+ //
+ //[wem] If all the reads return 0xFF, assume no I2C bus is present (and return ENODEV)
+ //
+#if 0
+ for (i = 0; i < 4; i++) {
+ if (I2cTestReg[i].Setup != -1) {
+ FwPcdWrite(I2cTestReg[i].Setup, I2C_STATUS);
+ }
+ DataRead = FwPcdRead(I2cTestReg[i].Target);
+
+#ifdef DBG
+ DbgPrint("Pcd8584: register %s = 0x%2x\r\n", I2cTestReg[i].Name,
+ DataRead);
+#endif
+ if (DataRead != (UCHAR)0xFF) {
+ // Good.
+ PcdValid = TRUE;
+ }
+ }
+#else
+ PcdValid = TRUE;
+#endif
+
+ //
+ // Issue Stop command (twice)
+ //
+ //[wem] recommended for Lego.
+ //
+ FwPcdWrite(I2C_STOP, I2C_STATUS);
+ FwPcdWrite(I2C_STOP, I2C_STATUS);
+
+#if 0 //[wem] needed for Lego ?
+ //
+ // Now write communication initialization
+ // to the PCD8584 CSR (S1).
+ // This must be done only once, so we do it here.
+ //
+
+ FwPcdWrite(I2C_INIT, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN | I2C_ACKB also
+#endif
+#endif
+
+ PcdValid = TRUE;
+
+ return ((PcdValid) ? ESUCCESS : ENODEV);
+}
+
+
+VOID
+FwPcdWrite(
+ UCHAR Argument,
+ UCHAR Register
+ )
+/*++
+
+Routine Description:
+
+ This function writes a byte to one of the two EISA interface
+ registers of the PCD8584 I2C bus controller.
+
+Arguments:
+
+ Argument - The byte to be written.
+
+ Register - Selector for the EISA port to be written.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Offset = Register ? I2cInterfaceCsrPort : I2cInterfaceDataPort;
+
+ WRITE_PORT_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase | Offset), Argument);
+
+ return;
+}
+
+UCHAR
+FwPcdRead(
+ UCHAR Register
+ )
+/*++
+
+Routine Description:
+
+ This function reads a byte from one of the two EISA interface
+ registers of the PCD8584 I2C bus controller.
+
+Arguments:
+
+ Register - Selector for the EISA port to be read.
+
+Return Value:
+
+ Character supplied by the PCD8584.
+
+--*/
+
+{
+ ULONG Offset = Register ? I2cInterfaceCsrPort : I2cInterfaceDataPort;
+ UCHAR Datum;
+
+ Datum = READ_PORT_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase | Offset));
+
+ return Datum;
+}
+
+ARC_STATUS
+FwI2cWrite(
+ UCHAR Node,
+ UCHAR Datum
+ )
+/*++
+
+Routine Description:
+
+ This function sends a data byte to the specified node on the I2C bus.
+
+Arguments:
+
+ Node - The I2C address to which the data byte should go.
+
+ Datum - The data byte.
+
+Return Value:
+
+ ESUCCESS - The operation succeeded.
+ ENODEV - Something's wrong.
+
+--*/
+
+{
+ BOOLEAN BusIdle;
+ BOOLEAN PendingInterrupt;
+ BOOLEAN AckByte;
+ ARC_STATUS Status;
+ ULONG Timeout;
+ ULONG Count;
+
+#if 0
+ if (!PcdValid) return ENODEV;
+#endif
+
+ //
+ // Set timeout to 100ms.
+ //
+
+ Timeout = 100 * 1000;
+
+ //
+ // Mask off the low-order node number bit, then write the
+ // result to the PCD8584 DATA register.
+ //
+
+ Status = FwPcdStatusWaitWithTimeout( BusIdle = TRUE,
+ PendingInterrupt = FALSE,
+ AckByte = FALSE,
+ Timeout );
+ if( Status != ESUCCESS ){
+#if DBG
+ DbgPrint ("I2C: Timeout waiting for bus idle, status=%X\r\n",Status);
+#endif
+ return Status;
+ }
+
+ FwPcdWrite((Node & 0xfe) | I2C_WRITE_DIR, I2C_DATA);
+
+ //
+ // Now start up the PCD8584 communication with the specified node.
+ //
+ Count = 10;
+ while (1) {
+
+ FwPcdWrite(I2C_START, I2C_STATUS);
+
+ FwStallExecution(__1MSEC*1); // The device is picky about how quickly
+ // you may access it again.
+ // Wait for PIN to drop
+ //
+ //[wem] Lego repeated start inside loop -- is this OK ?
+ //[wem] Lego -- is 10ms long enough?
+ //
+ Status = FwPcdStatusWaitWithTimeout( BusIdle = FALSE,
+ PendingInterrupt = TRUE,
+ AckByte = FALSE,
+ 10 * 1000 );
+ if( Status == ESUCCESS){
+ break;
+ } else {
+ if (Count-- == 0) {
+#if DBG
+ DbgPrint ("I2C: Timeout during addr phase, status=%X\r\n",Status);
+#endif
+ return Status; // status from wait
+ }
+ }
+ }
+
+ //
+ // Write the desired datum onto the bus. We can do this lots of
+ // times, if we wish, without restarting the process. That'll be
+ // another direction of exploration, as time permits.
+ //
+
+
+ //[wem] Should check for LRB (lost arbitration) set before writing.
+ //[wem] If LRB set, then issue Stop.
+
+ FwPcdWrite(Datum, I2C_DATA);
+ FwPcdWrite(I2C_START, I2C_STATUS);
+
+ //
+ //[wem] Wait for PIN to drop
+ //
+
+ FwStallExecution(__1MSEC*1); // The device is picky about how quickly
+ // you may access it again.
+
+ Status = FwPcdStatusWaitWithTimeout( BusIdle = FALSE,
+ PendingInterrupt = TRUE,
+ AckByte = FALSE,
+ Timeout );
+ if( Status != ESUCCESS ){
+#if DBG
+ DbgPrint ("I2C: Timeout during data phase, status=%X\r\n",Status);
+#endif
+ return Status; // status from wait
+ }
+
+ //
+ // Finally, close down the communication with the target node.
+ //
+ //[wem] If LRB is still clear, it is safe to issue
+ //[wem] another data write. Otherwise, must issue Stop.
+
+ FwStallExecution(__1MSEC*1); // The device is picky about how quickly
+
+ Count = 10;
+ while (1) {
+
+ FwPcdWrite(I2C_STOP, I2C_STATUS);
+
+ FwStallExecution(__1MSEC*1); // The device is picky about how quickly
+ // you may access it again.
+
+ // Wait for PIN to drop
+ //
+ //[wem] Lego repeated start inside loop -- is this OK ?
+ //[wem] Lego -- is 10ms long enough?
+ //
+ Status = FwPcdStatusWaitWithTimeout( BusIdle = FALSE,
+ PendingInterrupt = TRUE,
+ AckByte = TRUE,
+ 10 * 1000 );
+ if( Status == ESUCCESS){
+ break;
+ } else {
+ if (Count-- == 0) {
+#if DBG
+ DbgPrint ("I2C: Timeout during stop, status=%X\r\n",Status);
+#endif
+ return Status; // status from wait
+ }
+ }
+ }
+
+ //
+ // And this writes just a single byte to the I2C bus; whew! We'd
+ // like to get smarter, when this works right.
+ //
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FwI2cRead(
+ IN UCHAR Node,
+ OUT PUCHAR ReadDatum
+ )
+/*++
+
+Routine Description:
+
+ This function receives a single data byte from a node on
+ the I2C bus.
+
+Arguments:
+
+ Node - The I2C address from which the data byte should come.
+
+Return Value:
+
+ The data byte.
+
+--*/
+
+{
+ ARC_STATUS Status;
+
+ *ReadDatum = 0;
+ Status = ESUCCESS;
+
+ if (!PcdValid) return ENODEV;
+
+// jwlfix - currently unused function, and probably incorrect.
+#if 0
+ I2C_STATUS_BITS I2cStatus;
+
+ //
+ // Mask off the low-order node number bit, then write the
+ // result to the PCD8584 DATA register.
+ //
+ do {
+ I2cStatus.All = FwPcdRead(I2C_STATUS);
+ } while (I2cStatus.NotBusBusy == 0);
+ FwPcdWrite((Node & 0xfe) | I2C_READ_DIR, I2C_DATA);
+
+ //
+ // Now start up the PCD8584 communication with the specified node.
+ //
+ do {
+ I2cStatus.All = FwPcdRead(I2C_STATUS);
+ } while (I2cStatus.NotBusBusy == 0);
+ FwPcdWrite(I2C_START, I2C_STATUS);
+
+ //
+ // Read the desired datum from the bus: first wait for PIN to
+ // clear, then NACK the transmission, since we're only reading
+ // the single byte; next, read a byte. That byte is the
+ // address we wrote into the data port, increased by one. Why?
+ // Dunno; that's just what happens, currently.
+ //
+ do {
+ I2cStatus.All = FwPcdRead(I2C_STATUS);
+ } while (I2cStatus.NotPendingInterrupt == 1);
+ FwPcdWrite(I2C_NACK, I2C_STATUS);
+ ReadDatum = FwPcdRead(I2C_DATA);
+ //
+ // Now we wait for PIN to clear, saying that we've received
+ // the byte acutally sent by the node, and then read that.
+ //
+ do {
+ I2cStatus.All = FwPcdRead(I2C_STATUS);
+ } while (I2cStatus.NotPendingInterrupt == 1);
+ ReadDatum = FwPcdRead(I2C_DATA);
+
+ //
+ // Finally, close down the communication with the target node.
+ //
+ FwPcdWrite(I2C_STOP, I2C_STATUS);
+#endif
+ return Status;
+}
+
+
+ARC_STATUS
+FwPcdStatusWaitWithTimeout (
+ BOOLEAN BusIdle,
+ BOOLEAN PendingInterrupt,
+ BOOLEAN AckByte,
+ ULONG Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for the desired I2C bus status state with a timeout value.
+
+ N.B. - This routine will only wait for one of the two states that
+ can be specified.
+
+Arguments:
+
+ BusIdle - Supplies a boolean that if true specifies that the
+ routine should wait for status to indicate that the bus is
+ not busy (NotBusBusy == 1).
+
+ PendingInterrupt - Supplies a boolean that if true specifies that
+ the routine should wait for status to indicate that
+ there is a pending interrupt (NotPendingInterrupt == 0).
+
+ AckByte - true indicates that the routine should wait for
+ status to indicate that status == PIN + ACKB
+
+ Timeout - Supplies the timeout value in microseconds.
+
+Return Value:
+
+ The status of the operation. ESUCCESS is returned if the specified
+ status is read on the bus before the timeout expires. EBUSY is
+ returned if the operation times out.
+
+Notes:
+
+ [wem] This routine should also check for lost arbitration.
+
+--*/
+
+{
+ LONG CyclesBeforeTimeout;
+ ULONG CycleCount;
+#if 0 //[wem] redundant?
+ extern ULONG HalpClockMegaHertz;
+#endif
+ ULONG ElapsedCycles;
+ I2C_STATUS_BITS I2cStatus;
+ ULONG PreviousCycleCount;
+ ARC_STATUS Status;
+ int MinLoopCnt;
+
+ //
+ // Compute Cycles to wait.
+ //
+
+ CyclesBeforeTimeout = Timeout * HalpClockMegaHertz;
+
+ //
+ // Capture initial time.
+ //
+
+ PreviousCycleCount = HalpRpcc();
+
+ //
+ // Continue the loop while waiting for the timeout. Assume timeout
+ // status.
+ //
+
+ Status = EBUSY;
+
+ while( CyclesBeforeTimeout > 0){
+
+ I2cStatus.All = FwPcdRead(I2C_STATUS);
+
+ //
+ // Check for bus not busy.
+ //
+
+ if( (BusIdle == TRUE) && (I2cStatus.NotBusBusy == 1) ){
+ Status = ESUCCESS;
+ break;
+ }
+
+ //
+ // Check for pending interrupt.
+ //
+ //[wem] AckByte case is to recognize successful
+ //[wem] stop command for Lego.
+ //
+
+ if (PendingInterrupt == TRUE) {
+ if (AckByte == TRUE) {
+ if (I2cStatus.NotPendingInterrupt == 1
+ && I2cStatus.NotBusBusy == 1) {
+ Status = ESUCCESS;
+ break;
+ }
+ } else {
+ if (I2cStatus.NotPendingInterrupt == 0) {
+ Status = ESUCCESS;
+ break;
+ }
+ }
+ }
+
+ //
+ // Update the number of cycles remaining before timeout.
+ //
+
+ CycleCount = HalpRpcc();
+ ElapsedCycles = CycleCount - PreviousCycleCount;
+ CyclesBeforeTimeout -= ElapsedCycles;
+ PreviousCycleCount = CycleCount;
+
+ }
+
+ return Status;
+
+}
diff --git a/private/ntos/nthals/hallego/alpha/pcd8584.h b/private/ntos/nthals/hallego/alpha/pcd8584.h
new file mode 100644
index 000000000..3344e42c5
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcd8584.h
@@ -0,0 +1,196 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pcd8584.h
+
+Abstract:
+
+ This module contains the definitions that support the PCD8584 I2C
+ bus controller.
+
+Author:
+
+ James Livingston [DEC] 13-Sep-1994
+
+Environment:
+
+ Alpha AXP ARC firmware
+
+Revision History:
+
+ Gene Morgan (Digital) 08-Nov-1995
+ Adapted for LEGO platforms from Mikasa
+
+--*/
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+//
+// jwlfix - These definitions are used in unused test code.
+//
+typedef struct _I2C_TEST_REG {
+ PUCHAR Name;
+ ULONG Target;
+ UCHAR Mask;
+ UCHAR Setup;
+} I2C_TEST_REG, *PI2C_TEST_REG;
+
+//
+// The following definitions are used to program the PCD8584 I2C bus
+// controller.
+//
+typedef union _I2C_CONTROL_BITS{
+ struct {
+ UCHAR AckEachByte: 1;
+ UCHAR SendStop: 1;
+ UCHAR SendStart: 1;
+ UCHAR ExtInterruptEnable: 1;
+ UCHAR Reserved: 2;
+ UCHAR EnableSerialOutput: 1;
+ UCHAR NotPendingInterrupt: 1;
+ };
+ UCHAR All;
+} I2C_CONTROL_BITS, *PI2C_CONTROL_BITS;
+
+typedef union _I2C_STATUS_BITS{
+ struct {
+ UCHAR NotBusBusy: 1;
+ UCHAR LostArbitration: 1;
+ UCHAR AddressedAsSlave: 1;
+ UCHAR Address0LastRBit: 1;
+ UCHAR BusError: 1;
+ UCHAR ExternalStop: 1;
+ UCHAR Reserved: 1;
+ UCHAR NotPendingInterrupt: 1;
+ };
+ UCHAR All;
+} I2C_STATUS_BITS, *PI2C_STATUS_BITS;
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
+
+#define __1MSEC 1000
+#define __HALF_MSEC 500
+#define __1USEC 1
+
+#define I2C_DATA 0
+#define I2C_STATUS 1
+#define I2C_MASTER_NODE 0xb6
+
+//[wem] It probably doesn't matter, but I2C_MASTER_NODE
+//[wem] should be in machine dependent file.
+//#define I2C_MASTER_NODE 0xaa //[wem] as per LEGO spec
+
+//
+// Control register bit definitions
+//
+#define I2C_S0 0x00 // Data register
+#define I2C_S0P 0x00 // Own address register
+#define I2C_S2 0x20 // Clock register
+#define I2C_S3 0x10 // Interrupt vector register
+
+//
+// Clock register SCL (data clocking) frequency bit definitions
+//
+#define I2C_SCL_90 0x00 // 90 KHz
+#define I2C_SCL_45 0x01 // 45 KHz
+#define I2C_SCL_11 0x02 // 11 KHz
+#define I2C_SCL_15 0x03 // 1.5 KHz
+
+//
+// Clock register input clock frequency bit definitions.
+//
+#define I2C_CLOCK_3 0x00 // 3 MHz
+#define I2C_CLOCK_443 0x10 // 4.3 MHz
+#define I2C_CLOCK_6 0x14 // 6 MHz
+#define I2C_CLOCK_8 0x18 // 8 MHz
+#define I2C_CLOCK_12 0x1c // 12 MHz
+
+//
+// I2C bus control byte bit definitions
+//
+#define I2C_ACKB 0x01 // Ack each byte sent
+#define I2C_STO 0x02 // Send stop condition
+#define I2C_STA 0x04 // Send start condition
+#define I2C_ENI 0x08 // Enable external interrupt
+#define I2C_ESO 0x40 // Enable serial output
+#define I2C_PIN 0x80 // Pending interrupt NOT
+
+//
+// Data direction (PCD8584 state) flags
+//
+#define I2C_WRITE_DIR 0x00
+#define I2C_READ_DIR 0x01
+#define I2C_IDLE 0x02
+#define I2C_S_WRITE 0x03
+#define I2C_S_READ 0x04
+#define I2C_SR_DONE 0x0a
+
+//
+// Setup condition constants for this implementation.
+//
+// Dave Baird's and Carey McMasters' choices:
+//#define I2C_CLOCK (I2C_SCL_90 | I2C_CLOCK_6)
+//
+// LEGO Settings [wem] ??? check this ?
+//
+// I2C_CLOCK should be in machine-dependent section,
+// unlike the bulk of this file.
+//
+//#define I2C_CLOCK (I2C_SCL_90 | I2C_CLOCK_12)
+//
+#define I2C_CLOCK (I2C_SCL_90 | I2C_CLOCK_8)
+
+//
+// jwlfix - These would need to be defined as bit-field assignments,
+// e.g.,
+//
+// I2C_STOP:
+// ---------
+// ((PI2C_CONTROL_BITS)&Datum)->AckEachByte = 1;
+// ((PI2C_CONTROL_BITS)&Datum)->SendStop = 1;
+// ((PI2C_CONTROL_BITS)&Datum)->EnableSerialOutput = 1;
+// ((PI2C_CONTROL_BITS)&Datum)->NotPendingInterrupt = 1;
+//
+// for stylistic consistency. We'll see if that's a better
+// way to do it after the function's running. I suppose it's
+// a matter of what the compiler generates, in each case.
+//
+#define I2C_STOP (I2C_S0 | I2C_ESO | I2C_ACKB | I2C_STO | I2C_PIN)
+#if 0 //[wem] set PIN for Lego.
+#define I2C_START (I2C_S0 | I2C_ESO | I2C_ACKB | I2C_STA)
+#else
+#define I2C_START (I2C_S0 | I2C_ESO | I2C_ACKB | I2C_STA | I2C_PIN)
+#endif
+#define I2C_INIT (I2C_S0 | I2C_ESO)
+#define I2C_NACK (I2C_S0 | I2C_ESO)
+#define I2C_ACK (I2C_S0 | I2C_ESO | I2C_ACKB)
+
+#define I2C_MASTER_TYPE 0
+#define I2C_LED_TYPE 1
+
+//
+// Function prototypes
+//
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+ARC_STATUS
+FwPcdInit(
+ ULONG I2cCsrPort,
+ ULONG I2cDataPort
+ );
+
+ARC_STATUS
+FwI2cWrite(
+ UCHAR Node,
+ UCHAR Datum
+ );
+
+ARC_STATUS
+FwI2cRead(
+ IN UCHAR Node,
+ OUT PUCHAR ReadDatum
+ );
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
diff --git a/private/ntos/nthals/hallego/alpha/pcf8574.c b/private/ntos/nthals/hallego/alpha/pcf8574.c
new file mode 100644
index 000000000..65f1f21ec
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcf8574.c
@@ -0,0 +1,336 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1994,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ pcf8574.c
+
+Abstract:
+
+ This module contains the routines that operate the 8-character
+ display on Lego's Operator Console Panel.
+
+ The OCP display is implemented via two PCF8574's, which
+ drive the LED display, select which character position will
+ be written, and select which character to write.
+
+ This module uses a subset of interface defined in ocplcd.c for
+ Mikasa and others. Lego uses a much simpler device, so some of
+ the functions defined for Mikasa are not needed.
+
+Author:
+
+ Gene Morgan (Digital)
+
+Environment:
+
+ Alpha AXP ARC firmware.
+
+Revision History:
+
+ Gene Morgan (Digital) 11-Nov-1995
+ Initial version
+
+ Gene Morgan 15-Apr-1996
+ Cleanup, add HalpOcpTestDisplay() and HalpOcpPutSlidingString()
+
+--*/
+
+#include "halp.h"
+#include "legodef.h"
+#include "arccodes.h"
+#include "pcf8574.h"
+#include "pcd8584.h"
+
+//
+// OcpValid -- Gate for access to OCP.
+// Init code will set to TRUE if OCP is reachable
+// If FALSE, OCP access routines become no-ops
+//
+
+BOOLEAN OcpValid = FALSE;
+
+ARC_STATUS
+HalpOcpInitDisplay(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the display and the PCF8574 control register.
+
+ This sequence must be completed before any characters
+ are written to the device.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS sts;
+
+ if (OcpValid) {
+
+ //[wem] Attempt to reach OCP device?
+ //[wem] Or let FwI2cWrite() fail?
+ //
+ //return ENODEV;
+
+ return ESUCCESS;
+ }
+
+ FwPcdInit(I2C_INTERFACE_CSR_PORT, I2C_INTERFACE_DATA_PORT);
+
+ //
+ // Issue a reset.
+ //
+
+#if 0 //[wem] not tested
+
+ sts = FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_INIT); // Turn on Reset, Chip Enable, and Read
+ if (sts != ESUCCESS) {
+ OcpValid = FALSE;
+ return sts;
+ }
+
+ sts = FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_INITCLR); // Clear Reset, leave Chip Enable asserted
+ if (sts != ESUCCESS) {
+ OcpValid = FALSE;
+ return sts;
+ }
+#endif
+
+ OcpValid = TRUE;
+
+ return ESUCCESS;
+}
+
+VOID
+HalpOcpTestDisplay(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Display text sequences to allow visual checkout
+ of OCP.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ UCHAR string[9] = " ";
+ int index, i, j, k;
+
+ for (index=0;index<100;index++) {
+ string[7] = 'A' + (index % 26);
+ HalpOcpPutString(string, 8, 0);
+ for (i=0;i<7;i++) {
+ string[i] = string[i+1];
+ }
+ }
+
+ for (i=0;i<32;i++) {
+
+ string[0] = '0' + (i / 10);
+ string[1] = '0' + (i % 10);
+ string[2] = ' ';
+ string[3] = ' ';
+ HalpOcpPutString(string, 4, 0);
+
+ HalpStallExecution(__1MSEC * 100);
+
+ for (j=0;j<8;j++) {
+ string[j] = (i*8)+j;
+ }
+
+ for (j=0;j<5;j++) {
+ HalpOcpPutString(string, 8, 0);
+ }
+
+ HalpStallExecution(__1MSEC * 100);
+ }
+}
+
+VOID
+HalpOcpClearDisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Clear the display of the Operator Control
+ Panel (OCP).
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+Notes:
+
+ (1) Turn on Reset, Chip Enable, and Write
+ (2) Clear Reset, leave Chip Enable asserted
+
+--*/
+{
+
+ if (!OcpValid) return;
+
+ FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_RESET);
+ FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_CLEAR);
+
+}
+
+VOID
+HalpOcpPutString(
+ IN PUCHAR String,
+ IN ULONG Count,
+ IN ULONG Start
+ )
+
+/*++
+
+Routine Description:
+
+ Prints a string to the Operator Control
+ Panel (OCP).
+
+Arguments:
+
+ String - An ASCII character string for display on the OCP.
+ Count - The number of characters in the argument string.
+ Start - Starting position on the OCP (0..7)
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PUCHAR ArgString = String;
+ ULONG CharCount, End;
+
+ if (!OcpValid) return;
+
+ //
+ // Limit the string to a maximum of OCP_SIZE characters.
+ //
+ End = (Start+Count > OCP_SIZE) ? OCP_SIZE : Start+Count;
+
+ for (CharCount = Start; CharCount < End; CharCount++) {
+ HalpOcpPutByte((UCHAR)CharCount, *ArgString++);
+ }
+ return;
+}
+
+VOID
+HalpOcpPutSlidingString(
+ IN PUCHAR String,
+ IN ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Prints a sliding string to the Operator Control
+ Panel (OCP).
+
+Arguments:
+
+ String - An ASCII character string for display on the OCP.
+ Count - The number of characters in the argument string.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DisplayString[OCP_SIZE];
+ int index, i;
+ int count = Count;
+
+ if (!OcpValid) return;
+
+ for (i=0;i<OCP_SIZE;i++)
+ DisplayString[i] = ' ';
+
+ for (index=0;index<count;index++) {
+ DisplayString[7] = String[index]; // move next char in from right
+ HalpOcpPutString(DisplayString, OCP_SIZE, 0);
+ for (i=0;i<(OCP_SIZE-1);i++) {
+ DisplayString[i] = DisplayString[i+1]; // slide right 7 chars 1 space to left
+ }
+ }
+
+ // Leaves last 8 characters of string in display...
+}
+
+VOID
+HalpOcpPutByte(
+ UCHAR Position,
+ UCHAR Datum
+ )
+/*++
+
+Routine Description:
+
+ This function sends a data byte in Datum to the high-order node
+ address of the OCP, its data port.
+
+ The byte will be displayed at the position indicated by Position.
+
+Arguments:
+
+ Position - The character position to write Datum.
+ Datum - The byte to be written to the OCP data port.
+
+Return Value:
+
+ None.
+
+Notes:
+
+ Assume that FPCE is set upon entry.
+
+--*/
+
+{
+ UCHAR Command;
+
+ if (!OcpValid) return;
+
+ Command = OCP_CMD_READY | OCP_FP_ADDRESS(Position);
+
+ FwI2cWrite(OCP_SLAVE_CONTROL, Command); // Assert address, ready to write
+ FwI2cWrite(OCP_SLAVE_DATA, Datum); // Load data byte in data port.
+ FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_ISSUE(Command)); // Clear FPCE
+ FwI2cWrite(OCP_SLAVE_CONTROL, Command); // Reassert FPCE
+
+ return;
+}
+
+/* end pcf8574.c */
diff --git a/private/ntos/nthals/hallego/alpha/pcf8574.h b/private/ntos/nthals/hallego/alpha/pcf8574.h
new file mode 100644
index 000000000..76b4b8ae6
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcf8574.h
@@ -0,0 +1,175 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1994,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ pcf8574.h
+
+Abstract:
+
+ This module contains the definitions for controlling Lego's
+ OCP display.
+
+ The OCP display is on the I2C bus and is implemented via two
+ PCF8574's, which drive the LED display, select which character
+ position will be written, and select which character to write.
+
+Author:
+
+ Gene Morgan (Digital)
+
+Environment:
+
+ Alpha AXP ARC firmware.
+
+Revision History:
+
+ Gene Morgan (Digital) 11-Nov-1995
+ Initial version
+
+ Gene Morgan 15-Apr-1996
+ Update function prototypes.
+
+--*/
+
+#ifndef _PCF8754_
+#define _PCF8754_
+
+
+// Lego OCP interface
+//
+// The interface is implemented via the I2C bus. Two PCF8574's
+// provide the two slave device registers that control Lego's
+// 8-character LED display. The two registers are Display
+// Address and Control, and Display Data.
+//
+/*--
+ Display Address and Control Register:
+
+ +-------+-------+-------+-------+----------------------+
+ | FPRST | RES | FPCE | FPWR | FPAD[3:0] |
+ +-------+-------+-------+-------+----------------------+
+ | | | | |
+ | reserved | | +-- Front Panel Address
+ | | | 0x8 -> char 0 (Left)
+ +-- Front Panel | | 0xF -> char 7 (Right)
+ Reset | +-- Front Panel Write
+ 1 -> reset | 0 -> write, 1 -> read
+ +-- Front Panel Chip Enable
+ 0 -> FPAD, FPWR, and data are valid
+
+ Current implementation always writes 1 to the reserved bit, and the
+ initialization sequence clears FPWR (i.e., set to read). It is not known
+ whether these actions are necessary.
+--*/
+// The Display Data register receives or delivers a single byte,
+// depending on the setting of FPWR.
+//
+
+//
+// OCP Slave addresses
+//
+
+#define OCP_SLAVE_CONTROL 0x40 // Display Address and Control register
+#define OCP_SLAVE_DATA 0x42 // Display Data register
+#define OCP_SIZE 8 // 8 character display
+
+//
+// OCP Display Address and Control definitions
+//
+
+#define OCP_FP_RESET 0x80 // FPRST -- Set to perform reset
+#define OCP_FP_RES 0x40 // RES -- Reserved, currently always set
+#define OCP_FP_ENABLE 0x20 // FPCE -- Clear to assert valid address and data
+#define OCP_FP_READ 0x10 // FPWR -- Set to perform read
+#define OCP_FP_ADDRESS(pos) ((UCHAR)(0x8 | (pos & 0x7)))
+ // FPAD3..FPAD0 -- Display character address
+//
+// OCP Command Settings
+//
+
+//
+// OCP_CMD_RESET issues a reset to the OCP (which clears the display)
+// OCP_CMD_CLEAR clears reset
+
+#define OCP_CMD_RESET ((UCHAR)(OCP_FP_RES | OCP_FP_RESET) | OCP_FP_ADDRESS(0))
+#define OCP_CMD_CLEAR ((UCHAR)(OCP_FP_RES) | OCP_FP_ADDRESS(0))
+
+//
+// OCP_CMD_READY is sent before data is issued
+// OCP_CMD_ISSUE indicates that the address and data for the transfer are valid
+//
+
+#define OCP_CMD_READY ((UCHAR)(OCP_FP_RES | OCP_FP_ENABLE))
+#define OCP_CMD_ISSUE(cmd) ((UCHAR)(cmd & ~OCP_FP_ENABLE))
+
+//
+// Init sequence -- not tested.
+//
+
+#define OCP_CMD_INIT ((UCHAR)(OCP_FP_RES | OCP_FP_RESET | OCP_FP_ENABLE))
+#define OCP_CMD_INITCLR ((UCHAR)(OCP_CMD_INIT & ~OCP_FP_RESET))
+
+//
+// Function prototypes.
+//
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+// FwOcpInitDisplay
+// Call once to set the OCP display to a known state
+// Returns:
+// ESUCCESS - Initialization was successful
+// ENODEV - OCP couldn't be reached
+//
+ARC_STATUS
+HalpOcpInitDisplay(
+ VOID
+ );
+
+// HalpOcpTestDisplay
+// Perfom visual test of OCP
+//
+VOID
+HalpOcpTestDisplay(
+ VOID
+ );
+
+// HalpOcpClearDisplay
+// Clear display
+VOID
+HalpOcpClearDisplay(
+ VOID
+ );
+
+// FwOcpPutString
+// Call to display a string on the OCP display.
+//
+VOID
+HalpOcpPutString(
+ IN PUCHAR String,
+ IN ULONG Count,
+ IN ULONG Start
+ );
+
+// HalpOcpPutSlidingString
+// Display a string on the OCP display.
+//
+VOID
+HalpOcpPutSlidingString(
+ IN PUCHAR String,
+ IN ULONG Count
+ );
+
+// FwOcpPutByte
+// Call to a display a single byte on the OCP display.
+VOID
+HalpOcpPutByte(
+ UCHAR Position,
+ UCHAR Datum
+ );
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
+
+#endif // _PCF8574_
diff --git a/private/ntos/nthals/hallego/alpha/pcibus.c b/private/ntos/nthals/hallego/alpha/pcibus.c
new file mode 100644
index 000000000..472054ee0
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcibus.c
@@ -0,0 +1,111 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Gene Morgan [Digital] 11-Oct-1995
+
+ Initial version for Lego. Adapted from Avanti.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+// Highest numbered bus detected during PCI configuration
+//
+extern ULONG PCIMaxBus;
+
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0)
+ {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24.
+ // In APECS pass 2, the format of a type 0 cycle is the same as the
+ // format of a type 1. Note that HalpValidPCISlot has already
+ // done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ else
+ {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if HALDBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/hallego/alpha/pciir.c b/private/ntos/nthals/hallego/alpha/pciir.c
new file mode 100644
index 000000000..d1e8fe7e9
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pciir.c
@@ -0,0 +1,646 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992,1993,1994,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ pciir.c
+
+Abstract:
+
+ The module provides the interrupt support for the Lego's PCI
+ interrupts.
+
+Author:
+
+ James Livingston 2-May-1994
+
+Revision History:
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+ Gene Morgan (Digital) 28-Oct-1995
+ Initial version for Lego. Adapted from Mikasa/Noritake.
+
+ Gene Morgan 15-Apr-1996
+ Fix PICMG-mode initialization.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define external function prototypes
+//
+
+UCHAR
+HalpAcknowledgePciInterrupt(
+ PVOID ServiceContext
+ );
+
+//
+// Import save area for PCI interrupt mask register.
+//
+USHORT HalpLegoPciInterruptMasterMask;
+
+// Cache current contents of interrupt mask registers
+//
+USHORT HalpLegoPciInterruptMask[4];
+
+//
+// PCI Interrupt control -- defined in I/O mapping module
+//
+extern PVOID HalpLegoPciInterruptConfigQva;
+extern PVOID HalpLegoPciInterruptMasterQva;
+extern PVOID HalpLegoPciInterruptRegisterBaseQva;
+extern PVOID HalpLegoPciInterruptRegisterQva[];
+extern PVOID HalpLegoPciIntMaskRegisterQva[];
+
+//
+// Globals for conveying Cpu and Backplane type
+//
+extern BOOLEAN HalpLegoCpu;
+extern BOOLEAN HalpLegoBackplane;
+extern ULONG HalpLegoCpuType;
+extern ULONG HalpLegoBackplaneType;
+extern UCHAR HalpLegoFeatureMask;
+extern ULONG HalpLegoPciRoutingType;
+
+VOID
+DbgDumpIntRegs(
+ VOID
+ )
+{
+#if DBG
+ LEGO_PCI_INT_MASTER MasterRegister;
+ USHORT MaskReg[4];
+ USHORT IntReg[4];
+ int i;
+
+ MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva);
+
+ MaskReg[0] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[0]);
+ MaskReg[1] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[1]);
+ MaskReg[2] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[2]);
+ MaskReg[3] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[3]);
+
+ IntReg[0] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[0]);
+ IntReg[1] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[1]);
+ IntReg[2] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[2]);
+ IntReg[3] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[3]);
+
+ DbgPrint ("\nMaster: %04X\n",MasterRegister.All);
+ DbgPrint (" Mask: %04X %04X %04X %04X\n", MaskReg[0], MaskReg[1], MaskReg[2], MaskReg[3]);
+ DbgPrint ("IntReg: %04X %04X %04X %04X\n", IntReg[0], IntReg[1], IntReg[2], IntReg[3]);
+#endif
+}
+
+
+VOID
+HalpInitializePciInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Lego PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LEGO_PCI_INT_CONFIG ConfigRegister;
+ LEGO_PCI_INT_MASTER MasterRegister;
+
+#if DBG
+ //
+ // Dump current contents of master and config interrupt registers
+ //
+ ConfigRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptConfigQva);
+ MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva);
+
+ DbgPrint("PCI-INTACC[config:%04x,master:%04x]\n",
+ ConfigRegister.All, MasterRegister.All);
+#endif
+
+
+ if (HalpLegoPciRoutingType != PCI_INTERRUPT_ROUTING_FULL) {
+
+ //
+ // disable interrupt accelerator and return
+ //
+
+ MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva); //[wem] added PEFT
+ MasterRegister.InterruptMode = 0; // MODE - select SIO routing
+ MasterRegister.InterruptEnable = 0; // valid iff MODE==0
+ MasterRegister.IntRegMaskEnable = 0;
+ MasterRegister.IntMask = 0;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva,
+ MasterRegister.All );
+
+ MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva);
+#if DBG
+ DbgPrint("PCI-INTACC[config:%04x,master:%04x]\n",
+ ConfigRegister.All, MasterRegister.All);
+#endif
+
+ MasterRegister.InterruptMode = 0; // MODE - select SIO routing
+ MasterRegister.InterruptEnable = 0; // valid iff MODE==0
+ MasterRegister.IntRegMaskEnable = 0;
+ MasterRegister.IntMask = 0;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva,
+ MasterRegister.All );
+
+#if DBG
+ MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva);
+
+ DbgPrint("PCI-INTACC[config:%04x,master:%04x]\n",
+ ConfigRegister.All, MasterRegister.All);
+#endif
+ return;
+ }
+
+ //
+ // Initialize the Lego PCI interrupts. There's a master
+ // interrupt and mask register, plus individual interrupt
+ // and mask registers for each physical slot.
+ //
+ // 1. Write base address of interrupt registers.
+ // 2. Write MODE, MSKEN, and MINT[D:A].
+ // 3. Set all mask bits to "disabled".
+ //
+
+ ConfigRegister.All = 0;
+ ConfigRegister.IntRegisterBaseAddr = PCI_INTERRUPT_BASE_REGISTER >> 4;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptConfigQva,
+ ConfigRegister.All );
+
+ //
+ // Set interrupt accelerator mode
+ // Mask interrupts until interrupt registers are setup.
+ //
+ // Note: The interrupt mask in the master register is always clear
+ //
+
+ MasterRegister.All = 0;
+ MasterRegister.InterruptMode = 1; // MODE
+ MasterRegister.InterruptEnable = 0; // valid iff MODE==0
+ MasterRegister.IntRegMaskEnable = 1; // valid iff MODE==1
+#if 0 //[wem] remove PEFT
+ MasterRegister.IntMask = HalpLegoPciInterruptMasterMask;
+#endif
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva,
+ MasterRegister.All );
+
+ //
+ // Turn on mask bits for each interrupt register
+ //
+
+ HalpLegoPciInterruptMask[0] = (USHORT)~0;
+ HalpLegoPciInterruptMask[1] = (USHORT)~0;
+ HalpLegoPciInterruptMask[2] = (USHORT)~0;
+ HalpLegoPciInterruptMask[3] = (USHORT)~0;
+
+ WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[0],
+ HalpLegoPciInterruptMask[0] );
+ WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[1],
+ HalpLegoPciInterruptMask[1] );
+ WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[2],
+ HalpLegoPciInterruptMask[2] );
+ WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[3],
+ HalpLegoPciInterruptMask[3] );
+
+ // Turn off mask bits in master interrupt register
+ //
+ MasterRegister.All = 0;
+ MasterRegister.InterruptMode = 1; // MODE
+ MasterRegister.InterruptEnable = 0; // valid iff MODE==0
+ MasterRegister.IntRegMaskEnable = 1; // valid iff MODE==1
+ MasterRegister.IntMask = (USHORT)~(INTA | INTB | INTC | INTD);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva,
+ MasterRegister.All );
+
+#if DBG
+ DbgDumpIntRegs();
+#endif
+
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt to disable.
+
+Return Value:
+
+ None.
+
+Notes:
+
+ The register contents are cached in HalpLegoPciInterruptMask
+ array. [wem] ??? Is this safe ?
+
+--*/
+
+{
+ ULONG RegSelect;
+ USHORT BitMask, NewMask;
+
+ // Remove offset to yield register and bit position.
+ //
+ Vector -= PCI_DEVICE_VECTORS;
+
+ // High order nibble of Vector selects the register, low order
+ // selects the bit.
+ //
+ RegSelect = (Vector >> 4) - 1;
+ BitMask = 1 << ((Vector & 0xf) - 1);
+
+ // Assume the current state of the interrupt mask register
+ // is in HalpLegoPciInterruptMask.
+ //
+ // Set bit indicated by Vector to disable interrupts
+ //
+ NewMask = HalpLegoPciInterruptMask[RegSelect] | BitMask;
+
+ // If changed, write new register contents
+ //
+ if (NewMask != HalpLegoPciInterruptMask[RegSelect]) {
+ HalpLegoPciInterruptMask[RegSelect] = NewMask;
+ WRITE_REGISTER_USHORT( (PUSHORT)
+ HalpLegoPciIntMaskRegisterQva[RegSelect],
+ HalpLegoPciInterruptMask[RegSelect] );
+ }
+
+#if DBG
+ DbgPrint("\nDisable PCI vector: %02X", Vector);
+ DbgDumpIntRegs();
+#endif
+
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt;
+ LevelSensitive or Latched (ignored for Lego PCI
+ interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG RegSelect;
+ USHORT BitMask, NewMask;
+
+ //
+ // Remove offset to yield register and bit position.
+ //
+
+ Vector -= PCI_DEVICE_VECTORS;
+
+ //
+ // High order nibble of Vector selects the register, low order
+ // selects the bit.
+ //
+
+ RegSelect = (Vector >> 4) - 1;
+ BitMask = 1 << ((Vector & 0xf) - 1);
+
+ //
+ // Assume the current state of the interrupt mask register
+ // is in HalpLegoPciInterruptMask.
+ //
+ // Clear bit indicated by Vector to enable interrupts.
+ //
+
+ NewMask = HalpLegoPciInterruptMask[RegSelect] & ~BitMask;
+
+ //
+ // If changed, write new register contents
+ //
+
+ if (NewMask != HalpLegoPciInterruptMask[RegSelect]) {
+ HalpLegoPciInterruptMask[RegSelect] = NewMask;
+ WRITE_REGISTER_USHORT( (PUSHORT)
+ HalpLegoPciIntMaskRegisterQva[RegSelect],
+ HalpLegoPciInterruptMask[RegSelect] );
+ }
+
+#if DBG
+ DbgPrint("\nEnable PCI vector: %02X", Vector);
+ DbgPrint("\n Old: %04X, New: %04X", HalpLegoPciInterruptMask[RegSelect], NewMask);
+ DbgDumpIntRegs();
+#endif
+
+}
+
+// Table for mapping from per-slot interrupt signal
+// to which slot to service.
+// Index is 4-bit value representing interrupt status for
+// <slot 4> <slot 3> <slot 2> <slot 1>
+// Current priority ordering is slot 1, 2, 3, 4
+// Index zero has no meaning, but it should do no harm.
+//
+//
+USHORT
+HighestPrioritySlot[16] = {
+// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f // value
+ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 // slot (based from zero)
+ };
+
+ULONG
+HighestPrioritySlotHits[4][16] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+UCHAR
+HighestPriorityLine (
+ LEGO_PCI_INT_MASTER MasterReg
+ )
+/*++
+
+Routine Description:
+
+ Policy routine for determining which PCI device to service next.
+
+Arguments:
+
+ MasterReg -- current Lego Master Interrupt register. Interrupt
+ field indicates which slots have pending interrupts.
+
+Return Value:
+
+ Value in range of 0..64, indicating which device should be serviced.
+
+--*/
+{
+ USHORT IntReg;
+
+ UCHAR Nib;
+ USHORT IrContents;
+ USHORT RegSelect, BitSelect;
+ int i;
+
+ RegSelect = HighestPrioritySlot[MasterReg.Interrupt];
+
+ // Read interrupt register for slot
+ //
+ IntReg = READ_REGISTER_USHORT( (PUSHORT)
+ HalpLegoPciInterruptRegisterQva[RegSelect]);
+
+ if (IntReg==0)
+ return 0xff;
+
+ // Find lowest numbered bit.
+ //
+ BitSelect = 0;
+ while (IntReg!=0) {
+ Nib = IntReg & 0xf;
+ if (Nib != 0) {
+ BitSelect += HighestPrioritySlot[Nib];
+ break;
+ }
+ IntReg = IntReg >> 4;
+ BitSelect += 4;
+ }
+
+
+#if DBG
+ if (HighestPrioritySlotHits[RegSelect][BitSelect]++ == 0) {
+ DbgPrint("\nSlot: %d, %d", RegSelect, BitSelect);
+ DbgDumpIntRegs();
+ }
+#endif
+
+ return ((RegSelect + 1) << 4) + (BitSelect + 1);
+
+}
+
+UCHAR
+HalpAcknowledgePciInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service - supplies
+ a QVA to Lego's Master PCI interrupt register.
+
+Return Value:
+
+
+ Return the value of the highest priority pending interrupt,
+ or 0xff if none.
+
+--*/
+{
+ LEGO_PCI_INT_MASTER MasterReg;
+ UCHAR InterruptVector;
+
+ UCHAR ISAVector = 0; //[wem] DEBUG - ack PCI int
+
+ static ULONG Count = 0;
+
+ //
+ // Check the master register to see which primary slot is
+ // requesting service (slot may be a PPB requesting service
+ // on behalf of one of its slots). Then check that slot's
+ // interrupt register.
+ //
+ // A set bit in the master or slot register indicates an active
+ // interrupt. Note that if the interrupt is masked, the bit will
+ // not be set. Also note that the code does not use the master
+ // register's mask bits unless all PCI interrupts need to be
+ // disabled at once.
+ //
+ // Scan is currently depth-first from slot 1 to slot 4. For
+ // each slot, INTA is serviced first and INTD serviced last.
+ //
+ // [wem] There's some interesting opportunities here.
+ // For example, it is possible to scan and detect how many
+ // waiting interrupts there are. It is also possible remember
+ // last vector and scan forward from that point (as in round
+ // robin), or to implement a fairness algorithm that incorporates
+ // priority.
+ //
+
+#if 0
+ //
+ //[wem] This requires an interrupt controller to respond to the
+ // interrupt acknowledge. The SIO has been programmed to not
+ // respond, so someone else has to do it (the interrupt accelerator?).
+ //
+
+ ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase);
+#endif
+
+ // Read master register.
+ //
+ MasterReg.All = READ_REGISTER_USHORT(
+ (PUSHORT) HalpLegoPciInterruptMasterQva);
+
+ if (MasterReg.Interrupt==0) {
+ return 0xff; // no interrupts
+ }
+
+ // Scan
+ //
+ InterruptVector = HighestPriorityLine (MasterReg);
+
+#if DBG
+ if (Count++ < 5 && ISAVector != 0xff) {
+ DbgPrint("<PCIACK:%02X:%02X>",ISAVector,InterruptVector);
+ }
+#endif
+
+ return( InterruptVector );
+}
+
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt having been generated
+ via the vector connected to the PCI device interrupt object. Its function
+ is to call the second-level interrupt dispatch routine.
+
+ This service routine could have been connected as follows, where the
+ ISR is the assembly wrapper that does the handoff to this function:
+
+ KeInitializeInterrupt( &Interrupt,
+ HalpPciInterruptHandler,
+ (PVOID) HalpPciIrQva,
+ (PKSPIN_LOCK)NULL,
+ PCI_VECTOR,
+ PCI_DEVICE_LEVEL,
+ PCI_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE);
+
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR PCIVector;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+
+ //[wem] DEBUG - count SIO dispatch entries
+ //
+ static long PciCount = 0;
+
+#if DBG //[wem]
+ PciCount++;
+ if (PciCount<5) {
+ DbgPrint("II<PCI><");
+ }
+ if (PciCount % 5000 == 0) {
+ DbgPrint("II<PCI><%08x><",PciCount);
+ }
+#endif
+
+ //
+ // Acknowledge interrupt and receive the returned interrupt vector.
+ // If we got 0xff back, there were no enabled interrupts, so we
+ // signal that with a FALSE return, immediately.
+ //
+
+ PCIVector = HalpAcknowledgePciInterrupt(ServiceContext);
+
+ if (PCIVector == 0xff) {
+
+#if DBG //[wem]
+ if (PciCount<5 || (PciCount % 5000) == 0) {
+ DbgPrint("ff>.");
+ }
+#endif
+ return( FALSE );
+ }
+
+ // Compute new vector based on PCI bus state
+ //
+ PCRInOffset = PCIVector + PCI_DEVICE_VECTORS;
+
+ // Re-dispatch via new vector
+ //
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset],
+ TrapFrame
+ );
+
+#if DBG //[wem]
+ if (PciCount<5 || (PciCount % 5000) == 0) {
+ DbgPrint("%02x>.",returnValue);
+ }
+#endif
+
+ return( returnValue );
+}
diff --git a/private/ntos/nthals/hallego/alpha/pcisio.c b/private/ntos/nthals/hallego/alpha/pcisio.c
new file mode 100644
index 000000000..91153d23c
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcisio.c
@@ -0,0 +1,587 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pic8259.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI SIO
+ programmable interrupt controller.
+
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+#if 0 //[wem] not yet
+extern PVOID HalpSioIntAckQva;
+extern ULONG HalpLegoPciRoutingType;
+#endif
+
+//
+// Import save area for SIO interrupt mask registers.
+//
+
+UCHAR HalpSioInterrupt1Mask;
+UCHAR HalpSioInterrupt2Mask;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+
+VOID
+HalpInitializeSioInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 8259 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ return;
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO bus specified SIO bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2, it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+ }
+
+ }
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO bus specified SIO bus interrupt.
+Arguments:
+
+ Vector - Supplies the vector of the SIO interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+UCHAR
+HalpAcknowledgeSioInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the Sio interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service - supplies
+ a QVA to Lego's Master PCI interrupt register.
+
+Return Value:
+
+
+ Return the value of the highest priority pending interrupt,
+ or 0xff if none.
+
+--*/
+{
+ UCHAR ISAVector;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+
+ //
+ // If PCI interrupts are being routed through the SIO, then
+ // a write to HalpEisaIntAckBase will generate a correct
+ // PCI Interrupt Acknowledge cycle for both PCI and ISA devices.
+ //
+ // If PCI interrupts are being routed through the interrupt
+ // accelerator, then the Interrupt Acknowledge cannot be issued
+ // on the PCI bus (since the SIO no longer has complete knowledge
+ // of interrupts). Instead, ISA interrupts must be acknowledged
+ // via a special port of the SIO, and PCI interrupts must be
+ // acknowledged via a PCI Interrupt Acknowledge (but that's another
+ // story).
+ //
+
+
+#if 0 //[wem] not yet
+ if (HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_FULL) {
+
+ //
+ // The interrupt accelerator is active. Issue the
+ // interrupt acknowledge directly to the SIO
+ //
+
+ ISAVector = READ_PORT_UCHAR(HalpSioIntAckQva);
+ }
+ else {
+
+ // The interrupt accelerator is in PICMG mode. All
+ // interrupts are going through the SIO, so a PCI
+ // interrupt acknowledge is safe.
+ //
+ ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase);
+ }
+#else
+
+ //
+ // Acknowledge the PCI/ISA interrupt via the SIO
+ //
+ // Note: This path is not used for PCI interrupts when
+ // interrupt accelerator is active.
+ //
+
+ ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase);
+
+#endif
+
+
+ if ((ISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return 0xFF; // ecrfix - now returns a value
+
+ }
+
+ }
+
+ return ISAVector & 0x0F;
+
+}
+
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to an interrupt object that
+ describes the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR ISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //[wem] DEBUG - count SIO dispatch entries
+ //
+ static long SioCount = 0;
+
+#if DBG
+ SioCount++;
+ if (SioCount<5) {
+ DbgPrint("II<SIO><");
+ }
+ if (SioCount % 1000 == 0) {
+ DbgPrint("II<SIO><%08x><",SioCount);
+ }
+#endif
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ ISAVector = HalpAcknowledgeSioInterrupt(NULL);
+
+ if (ISAVector==0xff)
+ return FALSE;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = ISAVector + ISA_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (ISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+#if DBG //[wem]
+ if (SioCount<5 || (SioCount % 1000)==0) {
+ DbgPrint("%02x>.", returnValue);
+ }
+#endif
+
+ return(returnValue);
+}
+
+
diff --git a/private/ntos/nthals/hallego/alpha/pcisup.c b/private/ntos/nthals/hallego/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/pcrtc.c b/private/ntos/nthals/hallego/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/pcserial.c b/private/ntos/nthals/hallego/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/pcspeakr.c b/private/ntos/nthals/hallego/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/perfcntr.c b/private/ntos/nthals/hallego/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/hallego/alpha/pintolin.h b/private/ntos/nthals/hallego/alpha/pintolin.h
new file mode 100644
index 000000000..86843acd3
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/pintolin.h
@@ -0,0 +1,273 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables for Lego
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Gene Morgan [Digital] 15-Apr-1996
+ Fix swapped PICMG-mode (ISA shared mode) lines -- affects
+ Gobi and Sahara bridged slots (first and third) if interrupts
+ in use.
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang, EB66, and Lego, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66 and Lego, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_DEVICE_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which //[wem] ???problem?
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31] //[wem] ???problem?
+// since PCI Config space is a sparse space, requiring a five-bit shift.) //[wem] ???problem?
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB# = 2, INTC# = 3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// be combined to appear on some combination of the four interrupt pins
+// that the bridge plugs into. On Lego platforms, that routing is dictated by
+// the PICMG specification.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[31]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for Lego
+//
+// You can limit init table to MAX_PCI_LOCAL_DEVICES entries.
+// The virtual slot range on lego is 17-20, so
+// MAX_PCI_LOCAL_DEVICE is defined as 20 in the platform dependent
+// header file (legodef.H). HalpValidPCISlot assures us that
+// we won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 20 = PCI_AD[31].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+//
+// Interrupt Vector Table Mapping for Lego
+//
+// Lego PCI interrupts are mapped to ISA IRQs in the table below.
+//
+// Limit init table to 20 entries, which is the
+// MAX_PCI_LOCAL_DEVICES for Lego.
+// We won't ever try to set an InterruptLine register of a slot
+// less than virtual slot 17 = PCI_AD[28]
+// or greater than Virtual slot 20 = PCI_AD[31].
+//
+
+#define SLOT_UNREACHABLE { 0xff, 0xff, 0xff, 0xff }
+
+#define SLOTS_UNREACHABLE_8 \
+ SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, \
+ SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE
+
+#define SLOTS_UNREACHABLE_12 \
+ SLOTS_UNREACHABLE_8, \
+ SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE
+
+
+#define SLOTS_UNREACHABLE_17 \
+ SLOTS_UNREACHABLE_12, \
+ SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, \
+ SLOT_UNREACHABLE
+
+#define PTL0 0xa
+#define PTL1 0xf
+#define PTL2 0x9
+#define PTL3 0xb
+
+// Pin to Line Table for primary (bus 0) slots
+// when PCI Interrupts routed through SIO
+//
+// **tested**
+//
+ULONG LegoPCIPinToLineTableIsa[][4]=
+{
+ SLOTS_UNREACHABLE_17, // Virtual Slots 0..16 = PCI_AD[11..27]
+ { PTL0, PTL1, PTL2, PTL3 }, // Virtual Slot 17 = PCI_AD[28] Slot #4
+ { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 18 = PCI_AD[29] Slot #3
+ { PTL2, PTL3, PTL0, PTL1 }, // Virtual Slot 19 = PCI_AD[30] Slot #2
+ { PTL1, PTL2, PTL3, PTL0 } // Virtual Slot 20 = PCI_AD[31] Slot #1
+};
+
+// Slot 2 is SCSI (NCR810) on Atacama.
+// Give it a dedicated SIO IRQ (as Avanti and friends do)
+//
+// **tested**
+//
+ULONG LegoPCIPinToLineTableIsaAtacama[][4]=
+{
+ SLOTS_UNREACHABLE_17, // Virtual Slots 0..16 = PCI_AD[11..27]
+ { PTL0, PTL1, PTL2, PTL3 }, // Virtual Slot 17 = PCI_AD[28] Slot #4
+ { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 18 = PCI_AD[29] Slot #3 -- SCSI
+ { PTL2, 0xff, 0xff, 0xff }, // Virtual Slot 19 = PCI_AD[30] Slot #2
+ { PTL1, PTL2, PTL3, PTL0 } // Virtual Slot 20 = PCI_AD[31] Slot #1
+};
+
+// Pin to Line Table for Bus 1 slots when PCI Interrupts
+// routed through SIO. Bus 1 is behind a PPB in primary slot 1.
+//
+ULONG LegoPCIPinToLineTableIsaBus1[][4]=
+{
+ SLOTS_UNREACHABLE_12, // Virtual Slots 0..11 = PCI_AD[11..27]
+ { PTL1, PTL2, PTL3, PTL0 }, // Virtual Slot 12 = PCI_AD[28] Slot #4
+ { PTL2, PTL3, PTL0, PTL1 }, // Virtual Slot 13 = PCI_AD[29] Slot #3
+ { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 14 = PCI_AD[30] Slot #2
+ { PTL0, PTL1, PTL2, PTL3 } // Virtual Slot 15 = PCI_AD[31] Slot #1
+};
+
+// Pin to Line Table for Bus 2 slots when PCI Interrupts
+// routed through SIO. Bus 2 is behind a PPB in primary slot 2.
+//
+ULONG LegoPCIPinToLineTableIsaBus2[][4]=
+{
+ SLOTS_UNREACHABLE_8, // Virtual Slots 0..7 = PCI_AD[11..27]
+ { PTL2, PTL3, PTL0, PTL1 }, // Virtual Slot 8 = PCI_AD[28] Slot #4
+ { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 9 = PCI_AD[29] Slot #3
+ { PTL0, PTL1, PTL2, PTL3 }, // Virtual Slot 10 = PCI_AD[30] Slot #2
+ { PTL1, PTL2, PTL3, PTL0 } // Virtual Slot 11 = PCI_AD[31] Slot #1
+};
+
+// Pin to Line Table for primary (bus 0) slots when Lego PCI Interrupt routing enabled
+//
+ULONG LegoPCIPinToLineTable[][4]=
+{
+ SLOTS_UNREACHABLE_17, // Virtual Slots 0..16 = PCI_AD[11..27]
+ { 0x41, 0x42, 0x43, 0x44 }, // Virtual Slot 17 = PCI_AD[28] Slot #4
+ { 0x31, 0x32, 0x33, 0x34 }, // Virtual Slot 18 = PCI_AD[29] Slot #3
+ { 0x21, 0x22, 0x23, 0x24 }, // Virtual Slot 19 = PCI_AD[30] Slot #2
+ { 0x11, 0x12, 0x13, 0x14 } // Virtual Slot 20 = PCI_AD[31] Slot #1
+};
+
+// Pin to Line Table for Bus 1 slots when Lego PCI Interrupt routing enabled
+// Bus 1 is behind a PPB in primary slot 1
+//
+ULONG LegoPCIPinToLineTableBus1[][4]=
+{
+ SLOTS_UNREACHABLE_12, // Virtual Slots 0..11 = PCI_AD[11..27]
+ { 0x1d, 0x1e, 0x1f, 0x20 }, // Virtual Slot 12 = PCI_AD[28] Slot #7 (Gobi) or #6 (Sahara)
+ { 0x19, 0x1a, 0x1b, 0x1c }, // Virtual Slot 13 = PCI_AD[29] Slot #6 or #5
+ { 0x15, 0x16, 0x17, 0x18 }, // Virtual Slot 14 = PCI_AD[30] Slot #5 or #4
+ { 0x11, 0x12, 0x13, 0x14 } // Virtual Slot 15 = PCI_AD[31] Slot #4 or #3
+};
+
+// Pin to Line Table for Bus 2 slots when Lego PCI Interrupt routing enabled
+// Bus 2 is behind a PPB in primary slot 2
+//
+ULONG LegoPCIPinToLineTableBus2[][4]=
+{
+ SLOTS_UNREACHABLE_8, // Virtual Slots 0..7 = PCI_AD[11..27]
+ { 0x2d, 0x2e, 0x2f, 0x30 }, // Virtual Slot 8 = PCI_AD[28] Slot #10
+ { 0x29, 0x2a, 0x2b, 0x2c }, // Virtual Slot 9 = PCI_AD[29] Slot #9
+ { 0x25, 0x26, 0x27, 0x28 }, // Virtual Slot 10 = PCI_AD[30] Slot #8
+ { 0x21, 0x22, 0x23, 0x24 } // Virtual Slot 11 = PCI_AD[31] Slot #7
+};
+
diff --git a/private/ntos/nthals/hallego/alpha/smerr.c b/private/ntos/nthals/hallego/alpha/smerr.c
new file mode 100644
index 000000000..993131568
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/smerr.c
@@ -0,0 +1,390 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1996 Digital Equipment Corporation
+
+Module Name:
+
+ smerr.c
+
+Abstract:
+
+ The module provides the error logging support for Lego's
+ Server Management and Watchdog timer functions.
+
+Author:
+
+ Gene Morgan (Digital) 17-Apr-1996
+
+Revision History:
+
+ Gene Morgan (Digital) 17-Apr-1996
+ Initial version.
+
+--*/
+
+#include "halp.h"
+#include "errframe.h"
+
+//
+// Context structure used interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+//
+// External variable UncorrectableError is declared in inithal.c.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Counter for correctable events
+//
+
+extern ULONG CorrectedMemoryReads;
+ULONG ServerMgmtEvents = 0;
+
+BOOLEAN HalpServerMgmtLoggingEnabled;
+
+//
+// External function prototypes
+//
+
+UCHAR
+HalpAcknowledgeServerMgmtInterrupt(
+ PVOID ServiceContext
+ );
+
+int
+sprintf( char *, const char *, ... );
+
+//
+// Local prototypes
+//
+
+VOID
+LegoServerMgmtReportWarningCondition(
+ BOOLEAN ReportWatchdog,
+ USHORT SmRegAll,
+ USHORT WdRegAll
+ );
+
+VOID
+LegoServerMgmtReportFatalError(
+ USHORT SmRegAll
+ );
+
+
+//
+// Local routines
+//
+
+VOID
+LegoServerMgmtReportWarningCondition(
+ BOOLEAN ReportWatchdog,
+ USHORT SmRegAll,
+ USHORT WdRegAll
+ )
+/*++
+
+Routine Description:
+
+ Report "correctable error" condition to error log.
+
+Arguments:
+
+ ReportWd -- reporting watchdog timer expiration
+ SmRegAll -- copy of server management register that is to be reported
+ (if ReportWd == FALSE)
+ WdRegAll -- copy of watchdog register that is to be reported
+ (if ReportWd == TRUE)
+
+Return Value:
+
+ None
+
+Notes:
+
+--*/
+{
+ LEGO_SRV_MGMT SmRegister;
+ LEGO_WATCHDOG WdRegister;
+
+ static ERROR_FRAME Frame; // Copy here for error logger's use
+
+ ERROR_FRAME TempFrame; // Build frame here
+ PCORRECTABLE_ERROR CorrPtr;
+ PEXTENDED_ERROR PExtended;
+
+ PBOOLEAN ErrorlogBusy;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+
+ //
+ // Copy provided register values
+ //
+
+ WdRegister.All = WdRegAll;
+ SmRegister.All = SmRegAll;
+
+ //
+ // Update the number of correctable errors.
+ //
+
+ CorrectedMemoryReads += 1; // sequence number for all correctable errors
+ ServerMgmtEvents += 1;
+
+
+ //
+ // If error logger not available, do not attempt
+ // to log an error.
+ //
+
+ if (!HalpServerMgmtLoggingEnabled) {
+ return;
+ }
+
+ //
+ // Init the error frame struct
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Fill in the error frame information.
+ //
+
+ TempFrame.Signature = ERROR_FRAME_SIGNATURE;
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = CorrectedMemoryReads;
+ TempFrame.PerformanceCounterValue = KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Fill in the specific error information
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ CorrPtr->Flags.SystemInformationValid = 1;
+ CorrPtr->Flags.AddressSpace = UNIDENTIFIED;
+ CorrPtr->Flags.MemoryErrorSource = UNIDENTIFIED;
+
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+
+ PExtended = &CorrPtr->ErrorInformation;
+
+ if (ReportWatchdog) {
+
+ //
+ // Unexpected watchdog timer expiration
+ //
+
+ PExtended->SystemError.Flags.WatchDogExpiredValid = 1;
+ PExtended->SystemError.WatchdogExpiration = WdRegister.All; // Watchdog timer expired
+
+ }
+ else {
+
+ //
+ // Server management warning condition
+ //
+
+ if (SmRegister.EnclFanFailure) {
+ PExtended->SystemError.Flags.FanNumberValid = 1;
+ PExtended->SystemError.FanNumber = 2; // Enclosure Fan died
+ }
+ else if (SmRegister.CpuTempFailure) {
+ PExtended->SystemError.Flags.TempSensorNumberValid = 1;
+ PExtended->SystemError.TempSensorNumber = 1; // CPU temp sensor alert
+ }
+ else if (SmRegister.CpuTempRestored) {
+ PExtended->SystemError.Flags.TempSensorNumberValid = 1;
+ PExtended->SystemError.TempSensorNumber = 101; // CPU temp sensor OK
+ }
+ else if (SmRegister.Psu1Failure) {
+ PExtended->SystemError.Flags.PowerSupplyNumberValid = 1;
+ PExtended->SystemError.PowerSupplyNumber = 1; // Power supply #1 dead
+ }
+ else if (SmRegister.Psu2Failure) {
+ PExtended->SystemError.Flags.PowerSupplyNumberValid = 1;
+ PExtended->SystemError.PowerSupplyNumber = 2; // Power supply #2 dead
+ }
+ else {
+
+ //
+ // Error didn't match any expected value -- leave extended error info flag on,
+ // leave all condition flags off.
+ //
+
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+
+#if HALDBG
+ DbgPrint("smerr: No Server Mgmt error to report!\n");
+
+#endif
+ }
+
+ }
+
+ //
+ // Correctable frame complete
+ //
+
+
+ //
+ // Get the interrupt object.
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Acquire spinlock for exclusive access to error frame.
+ //
+
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext + sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ //
+
+ if (!*ErrorlogBusy) {
+
+ //
+ // Set the raw system information.
+ //
+
+ CorrPtr->RawSystemInformationLength = 0;
+ CorrPtr->RawSystemInformation = NULL;
+
+ //
+ // Set the raw processor information. Disregard at the moment.
+ //
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // Set reporting processor information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+
+ //
+ // Copy the information that we need to log.
+ //
+
+ RtlCopyMemory(&Frame,
+ &TempFrame,
+ sizeof(ERROR_FRAME));
+
+ //
+ // Put frame into ISR service context.
+ //
+
+ *(PERROR_FRAME *)InterruptObject->ServiceContext = &Frame;
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+ // Chao claims it is not possible to reach this on a UP system.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext);
+}
+
+VOID
+LegoServerMgmtReportFatalError(
+ USHORT SmRegAll
+ )
+/*++
+
+Routine Description:
+
+ Report an uncorrectable error.
+
+Arguments:
+
+ SmRegAll -- copy of server management register that is to be reported
+
+Return Value:
+
+ None
+
+Notes:
+
+--*/
+{
+ LEGO_SRV_MGMT SmRegister;
+ PEXTENDED_ERROR PExtended;
+
+ SmRegister.All = SmRegAll;
+
+ //
+ // Load fields of uncorrectable error record
+ //
+
+ if (PUncorrectableError) {
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace = UNIDENTIFIED;
+ PUncorrectableError->UncorrectableFrame.Flags.MemoryErrorSource = UNIDENTIFIED;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid = 1;
+ PExtended = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+
+ if (SmRegister.CpuFanFailureNmi) {
+ PExtended->SystemError.Flags.FanNumberValid = 1;
+ PExtended->SystemError.FanNumber = 1; // CPU Fan
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "CPU fan failed.");
+ }
+ else if (SmRegister.EnclTempFailureNmi) {
+ PExtended->SystemError.Flags.TempSensorNumberValid = 1;
+ PExtended->SystemError.TempSensorNumber = 2; // Enclosure sensor
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Enclosure temperature too high for safe operation.");
+ }
+ else {
+ PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid = 0;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Unknown server management NMI failure."); // BUG!
+ }
+ }
+}
diff --git a/private/ntos/nthals/hallego/alpha/smir.c b/private/ntos/nthals/hallego/alpha/smir.c
new file mode 100644
index 000000000..3fe96ccff
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/smir.c
@@ -0,0 +1,722 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992,1993,1994,1995,1996 Digital Equipment Corporation
+
+Module Name:
+
+ smir.c
+
+Abstract:
+
+ The module provides the interrupt support for Lego's
+ Server Management and Watchdog timer functions.
+
+Author:
+
+ Gene Morgan (Digital) 3-Nov-1995
+
+Revision History:
+
+ Gene Morgan (Digital) 3-Nov-1995
+ Initial version for Lego. Adapted from Mikasa/Noritake.
+
+ Gene Morgan 15-Apr-1996
+ Service Watchdog Timer.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define external function prototypes
+//
+
+UCHAR
+HalpAcknowledgeServerMgmtInterrupt(
+ PVOID ServiceContext
+ );
+
+VOID
+LegoServerMgmtReportWarningCondition(
+ BOOLEAN ReportWatchdog,
+ USHORT SmRegAll,
+ USHORT WdRegAll
+ );
+
+BOOLEAN
+HalpLegoShutdownWatchdog(
+ VOID
+ );
+
+
+//
+// Save area for interrupt mask register.
+//
+USHORT HalpLegoServerMgmtInterruptMask;
+
+//
+// Server management and watchdog timer control.
+// defined/setup in lgmapio.c
+//
+extern PVOID HalpLegoServerMgmtQva;
+extern PVOID HalpLegoWatchdogQva;
+
+//
+// Globals for conveying Cpu and Backplane type
+//
+extern BOOLEAN HalpLegoCpu;
+extern BOOLEAN HalpLegoBackplane;
+extern ULONG HalpLegoCpuType;
+extern ULONG HalpLegoBackplaneType;
+extern UCHAR HalpLegoFeatureMask;
+extern BOOLEAN HalpLegoServiceWatchdog;
+
+//
+// Track whether error logger is available
+//
+extern BOOLEAN HalpServerMgmtLoggingEnabled;
+
+//
+// True if someone has "enabled" interrupts
+// for a particular server management event.
+//
+extern BOOLEAN HalpLegoDispatchWatchdog;
+extern BOOLEAN HalpLegoDispatchNmi;
+extern BOOLEAN HalpLegoDispatchInt;
+extern BOOLEAN HalpLegoDispatchPsu;
+extern BOOLEAN HalpLegoDispatchHalt;
+
+
+VOID
+HalpInitializeServerMgmtInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Lego
+ Server Management and Watchdog Timer functions
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+Notes:
+
+ Goal is to set the Server Management and Watchdog
+ functions to a known state.
+
+--*/
+{
+ LEGO_SRV_MGMT SmRegister;
+ LEGO_WATCHDOG WdRegister;
+
+ //
+ // Initial state is error logger is not available
+ //
+
+ HalpServerMgmtLoggingEnabled = FALSE;
+
+ //
+ // Assume watchdog is idle.
+ // There's no interrupt mask bit, so no work needs to be done here.
+ //
+
+ if (HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) {
+
+ //
+ // Do nothing until clock is started.
+ //
+
+ HalpLegoDispatchWatchdog = FALSE;
+
+ }
+
+ // Set the mask bits for all Server Management functions
+ // (i.e., block interrupts)
+ //
+ if (HalpLegoFeatureMask & LEGO_FEATURE_SERVER_MGMT) {
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.IntMask = 0;
+ SmRegister.NmiMask = 0;
+ SmRegister.PsuMask = 0; // not present on all platforms
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+
+ HalpLegoDispatchNmi = FALSE;
+ HalpLegoDispatchInt = FALSE;
+ HalpLegoDispatchPsu = FALSE;
+ HalpLegoDispatchHalt = FALSE;
+ }
+}
+
+
+VOID
+HalpDisableServerMgmtInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the Server Management
+ or Watchdog Timer interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt to disable.
+
+Return Value:
+
+ None.
+
+Notes:
+
+ An interrupt is masked by setting the appropriate mask bit to 1.
+ The halt button cannot be masked.
+
+--*/
+
+{
+ LEGO_SRV_MGMT SmRegister;
+ LEGO_WATCHDOG WdRegister;
+
+ // dispatch on vector to determine which interrupt mask to clear
+ //
+ switch (Vector) {
+
+ case WATCHDOG_VECTOR:
+ //
+ // Disable Watchdog timer interrupts (and the timer itself)
+ //
+ // If timer is running and timer 2 is active, timer 2
+ // must be stopped before the timer can be disabled.
+ //
+
+ HalpLegoShutdownWatchdog();
+
+ //
+ // Re-enable timer but stop performing secondary dispatch
+ //
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ WdRegister.Enabled = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All );
+
+ HalpLegoDispatchWatchdog = FALSE;
+ break;
+
+ case SM_WARNING_VECTOR:
+
+#if 0
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.IntMask = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+#endif
+
+ HalpLegoDispatchInt = FALSE;
+ break;
+
+ case SM_ERROR_VECTOR:
+
+#if 0
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.NmiMask = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+#endif
+
+ HalpLegoDispatchNmi = FALSE;
+ break;
+
+ case SM_PSU_FAILURE_VECTOR:
+
+#if 0
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.PsuMask = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+#endif
+
+ HalpLegoDispatchPsu = FALSE;
+ break;
+
+ case HALT_BUTTON_VECTOR:
+ //
+ // Halt button cannot be masked -- ignore
+ //
+
+ HalpLegoDispatchHalt = FALSE;
+ break;
+
+ default:
+ //
+ // Error - unrecognized vector
+ //
+ break;
+ }
+}
+
+
+VOID
+HalpEnableServerMgmtInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Server Management or
+ Watchdog Timer interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt to be enabled.
+
+ InterruptMode - Supplies the mode of the interrupt;
+ LevelSensitive or Latched //[wem] ??? check this ???
+
+Return Value:
+
+ None.
+
+Notes:
+
+ An interrupt is enabled by clearing the appropriate mask bit (i.e., set to 0).
+ The halt button cannot be masked.
+
+--*/
+
+{
+ LEGO_SRV_MGMT SmRegister;
+ LEGO_WATCHDOG WdRegister;
+
+ // dispatch on vector to determine which interrupt mask to clear
+ //
+ switch (Vector) {
+
+ case WATCHDOG_VECTOR:
+ //
+ // Enable Watchdog timer interrupts (and the timer itself)
+ // Assume all other aspects of the timer are correctly setup, but:
+ //
+ // If timer is already running and timer 2 is active, re-establish timer 1.
+ //
+
+ HalpLegoShutdownWatchdog();
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ WdRegister.Enabled = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All );
+
+ //
+ // Watchdog is enabled and Timer 1 is now running
+ //
+
+ HalpLegoDispatchWatchdog = TRUE;
+ break;
+
+ case SM_WARNING_VECTOR:
+
+#if 0
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.IntMask = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+#endif
+ HalpLegoDispatchInt = TRUE;
+ break;
+
+ case SM_ERROR_VECTOR:
+
+#if 0
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.NmiMask = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+#endif
+ HalpLegoDispatchNmi = TRUE;
+ break;
+
+ case SM_PSU_FAILURE_VECTOR:
+
+#if 0
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegister.PsuMask = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+#endif
+ HalpLegoDispatchPsu = TRUE;
+ break;
+
+ case HALT_BUTTON_VECTOR:
+
+ //
+ // Halt button cannot be masked.
+ //
+
+ HalpLegoDispatchHalt = TRUE;
+ break;
+
+ default:
+
+ //
+ // Error - unrecognized vector
+ //
+
+ break;
+ }
+
+}
+
+UCHAR
+HalpAcknowledgeServerMgmtInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the Server Management interrupt. Return vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service - supplies
+ a QVA to Lego's Server Management interrupt register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt,
+ or 0xff if none.
+
+--*/
+{
+ LEGO_SRV_MGMT SmRegister;
+ LEGO_WATCHDOG WdRegister;
+ UCHAR Vector;
+
+ //
+ // Check the watchdog and server management registers to see which
+ // event occurred.
+ //
+ // Read watchdog first since it is most probable cause of interrupt
+ //
+
+ //
+ // Value to return if no match
+ //
+
+ Vector = 0xFF;
+
+ //
+ // Check Watchdog register's interrupt bit.
+ //
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+
+#if DBG
+ DbgPrint(" <WdReg:%04x> ",WdRegister.All);
+#endif
+
+ if (WdRegister.Interrupt==1) {
+
+ Vector = (WATCHDOG_VECTOR - SERVER_MGMT_VECTORS);
+
+#if DBG
+ DbgPrint(" <WdReg:%04x> ",WdRegister.All);
+#endif
+
+ }
+ else {
+
+ //
+ // Check Server Management register bits
+ //
+
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+
+#if DBG
+ DbgPrint(" <SmReg:%04x> ",SmRegister.All);
+#endif
+
+ if (SmRegister.CpuTempFailure==1
+ || SmRegister.CpuTempRestored==1
+ || SmRegister.EnclFanFailure==1) {
+
+ Vector = (SM_WARNING_VECTOR - SERVER_MGMT_VECTORS);
+ }
+ else if (SmRegister.Psu1Failure==1
+ || SmRegister.Psu2Failure) {
+
+ Vector = (SM_PSU_FAILURE_VECTOR - SERVER_MGMT_VECTORS);
+ }
+ }
+
+ return Vector;
+}
+
+
+BOOLEAN
+HalpServerMgmtDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt having been generated
+ via the vector connected to the Server Management device interrupt object.
+ Its function is to call the second-level interrupt dispatch routine.
+
+ If the second level dispatch doesn't handle, then this routine will perform
+ default handling.
+
+ This service routine could have been connected as follows, where the
+ ISR is the assembly wrapper that does the handoff to this function:
+
+ KeInitializeInterrupt( &Interrupt,
+ HalpServerMgmtInterruptHandler,
+ (PVOID) HalpLegoServerMgmtInterruptQva,
+ (PKSPIN_LOCK)NULL,
+ SERVER_MGMT_VECTOR,
+ SERVER_MGMT_DEVICE_LEVEL,
+ SERVER_MGMT_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE);
+
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Server Management
+ interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+Notes:
+
+ Only the CPU IRQ5 interrupts come through here. Server management
+ NMIs are handled by HalpHandleNmi()
+
+--*/
+{
+ UCHAR SmVector;
+ BOOLEAN returnValue;
+ LEGO_SRV_MGMT SmRegister, SmRegisterLog;
+ LEGO_WATCHDOG WdRegister, WdRegisterLog;
+
+ BOOLEAN LogIt = FALSE;
+ BOOLEAN LogWatchdog = FALSE;
+
+ //
+ // [wem] DEBUG - count SM dispatch entries
+ //
+ static long IntCount = 0;
+
+#if DBG //[wem]
+ IntCount++;
+ if (IntCount<5) {
+ DbgPrint("II<SM><");
+ }
+ if (IntCount % 1000 == 0) {
+ DbgPrint("II<SM><%08x><", IntCount);
+ }
+#endif
+
+ //
+ // Acknowledge interrupt and receive the returned interrupt vector.
+ // If we got 0xff back, there were no enabled interrupts, so we
+ // signal that with a FALSE return, immediately.
+ //
+
+ SmVector = HalpAcknowledgeServerMgmtInterrupt(ServiceContext);
+
+#if DBG
+ DbgPrint("<SmVector:%04x> ",SmVector);
+#endif
+
+ if (SmVector == ((UCHAR)0xff)) {
+
+#if DBG //[wem]
+ if (IntCount<5 || (IntCount % 1000)==0) {
+ DbgPrint("ff>.");
+ }
+#endif
+ return( FALSE );
+ }
+
+ SmVector += SERVER_MGMT_VECTORS;
+
+#if DBG
+ DbgPrint("<SmVector:%04x> ",SmVector);
+#endif
+
+ switch (SmVector) {
+
+ case WATCHDOG_VECTOR:
+
+ if (HalpLegoDispatchWatchdog
+ && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SmVector])(
+ PCR->InterruptRoutine[SmVector],
+ TrapFrame)
+ ) {
+ return TRUE;
+ }
+
+ WdRegisterLog.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+
+#if DBG
+ DbgPrint("<WdReg:%04x> ",WdRegisterLog.All);
+#endif
+
+ if (HalpLegoServiceWatchdog) {
+
+ //
+ // Get control of the watchdog timer
+ //
+
+ HalpLegoShutdownWatchdog();
+
+ //
+ // Re-enable it
+ //
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ WdRegister.Enabled = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All);
+
+ returnValue = TRUE;
+ }
+ else {
+
+ //
+ // Dismiss the interrupt -- but system is on the way down!
+ //
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+ WdRegister.Interrupt = 1;
+ WdRegister.Enabled = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All );
+
+ //
+ // Interrupt not serviced
+ //
+
+ returnValue = FALSE;
+
+ }
+
+ LogIt = TRUE;
+ LogWatchdog = TRUE;
+
+ break;
+
+ case SM_WARNING_VECTOR:
+
+ if (HalpLegoDispatchInt
+ && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SmVector])(
+ PCR->InterruptRoutine[SmVector],
+ TrapFrame)
+ ) {
+ return TRUE;
+ }
+
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegisterLog.All = SmRegister.All;
+
+ // Handle any that were not handled by secondary dispatch
+ //
+ if (SmRegister.CpuTempRestored==1) {
+ HalDisplayString ("Server Management: CPU Temperature restored.\n");
+ }
+ if (SmRegister.CpuTempFailure==1) {
+ HalDisplayString ("Server Management: CPU Temperature warning.\n");
+ }
+ if (SmRegister.EnclFanFailure==1) {
+ HalDisplayString ("Server Management: System fan failure.\n");
+ }
+
+ // Any interrupts will be cleared
+ // Don't touch PSU interrupts
+ //
+ SmRegister.Psu1Failure = 0;
+ SmRegister.Psu2Failure = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+
+ LogIt = TRUE;
+ returnValue = TRUE;
+ break;
+
+ case SM_PSU_FAILURE_VECTOR:
+
+ if (HalpLegoDispatchPsu
+ && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SmVector])(
+ PCR->InterruptRoutine[SmVector],
+ TrapFrame)
+ ) {
+ return TRUE;
+ }
+
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
+ SmRegisterLog.All = SmRegister.All;
+
+ //
+ // Handle any that were not handled by secondary dispatch
+ //
+
+ if (SmRegister.Psu1Failure==1) {
+ HalDisplayString ("Server Management: PSU 1 has failed.\n");
+ }
+ if (SmRegister.Psu2Failure==1) {
+ HalDisplayString ("Server Management: PSU 2 has failed.\n");
+ }
+
+ // Any interrupts will be cleared
+ // Don't touch fan/temperature interrupts
+ //
+ SmRegister.CpuTempRestored = 0;
+ SmRegister.CpuTempFailure = 0;
+ SmRegister.EnclFanFailure = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
+
+ LogIt = TRUE;
+ returnValue = TRUE;
+
+ break;
+
+
+ default:
+ returnValue = FALSE; //[wem] Error -- bugcheck?
+ }
+
+#if DBG //[wem]
+ if (IntCount<5 || (IntCount % 1000)==0) {
+ DbgPrint("%02x>.", returnValue);
+ }
+#endif
+
+ //
+ // Post "correctable" error record to error log.
+ //
+
+ if (LogIt) {
+ LegoServerMgmtReportWarningCondition(LogWatchdog, SmRegisterLog.All,WdRegisterLog.All);
+ }
+
+ return( returnValue );
+}
diff --git a/private/ntos/nthals/hallego/alpha/smsup.c b/private/ntos/nthals/hallego/alpha/smsup.c
new file mode 100644
index 000000000..c84269e4e
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/smsup.c
@@ -0,0 +1,363 @@
+/*++
+
+Copyright (c) 1996 Digital Equipment Corporation
+
+Module Name:
+
+ smsup.c
+
+Abstract:
+
+ Server Management support
+
+Author:
+
+ Gene Morgan (Digital) 28-Apr-1996
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pcf8574.h"
+
+
+//
+// Local prototypes
+//
+
+BOOLEAN
+HalpLegoShutdownWatchdog(
+ VOID
+ );
+
+VOID
+HalpLegoInitWatchdog(
+ UCHAR WdMode,
+ UCHAR WdTimer1,
+ UCHAR WdTimer2,
+ BOOLEAN Enabled
+ );
+
+VOID
+HalpPowerOff(
+ VOID
+ );
+
+BOOLEAN
+LegoServerMgmtDelayedShutdown(
+ ULONG DelaySeconds
+ );
+
+
+//
+// Server management and watchdog timer control.
+// defined/setup in lgmapio.c
+//
+extern PVOID HalpLegoServerMgmtQva;
+extern PVOID HalpLegoWatchdogQva;
+
+//
+// Globals for conveying Cpu and Backplane type
+//
+extern BOOLEAN HalpLegoCpu;
+extern BOOLEAN HalpLegoBackplane;
+extern ULONG HalpLegoCpuType;
+extern ULONG HalpLegoBackplaneType;
+extern UCHAR HalpLegoFeatureMask;
+extern BOOLEAN HalpLegoServiceWatchdog;
+
+
+BOOLEAN
+HalpLegoShutdownWatchdog(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Shutdown the wtachdog timer.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if watchdog was successfully shut down, FALSE otherwise.
+
+Notes:
+
+ Algorithm works if watchdog is in stage one or two.
+
+ On TRUE return, Watchdog is ready to be enabled.
+ On FALSE return, watchdog is running, reset will eventually occur.
+
+--*/
+{
+ LEGO_WATCHDOG WdRegister;
+ ULONG Count;
+#if DBG
+ ULONG DbgCnt;
+
+ DbgCnt = 0;
+ DbgPrint(" <Wd:reset:");
+#endif
+
+ Count = 100; // Observations indicate that 2 cycles is sufficient. Still...
+
+ while (1) {
+
+ WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
+
+ if ((WdRegister.Enabled == 0) || (Count-- == 0)) {
+ break;
+ }
+
+ if (WdRegister.Phase == WATCHDOG_PHASE_ONE) {
+
+ WdRegister.Enabled = 0;
+ }
+ else {
+
+ WdRegister.Phase = 1; // should revert to phase 1
+ WdRegister.Enabled = 0;
+ }
+
+ WRITE_REGISTER_USHORT((PUSHORT)HalpLegoWatchdogQva,WdRegister.All);
+
+#if DBG
+ DbgCnt++;
+ if (DbgCnt>10) {
+ DbgPrint(">10> ");
+ break;
+ }
+#endif
+ }
+
+#if DBG
+ DbgPrint("%d> ",DbgCnt);
+#endif
+
+ //
+ // Return TRUE if count not exhausted
+ //
+ return (Count > 0);
+
+}
+
+
+VOID
+HalpLegoInitWatchdog(
+ UCHAR WdMode,
+ UCHAR WdTimer1,
+ UCHAR WdTimer2,
+ BOOLEAN Enabled
+ )
+/*++
+
+Routine Description:
+
+ Setup the Lego watchdog timer.
+
+Arguments:
+
+ WdMode, WdTimer1, WdTimer2 -- new parameters for watchdog timer
+ Enabled -- TRUE if timer should be started
+
+Return Value:
+
+ None.
+
+ ++*/
+{
+ LEGO_WATCHDOG WdRegister;
+
+ if (HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) {
+
+ //
+ // Disable watchdog in case it was running
+ //
+
+ HalpLegoShutdownWatchdog();
+ }
+
+ if (HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) {
+
+ //
+ // Set mode and timers, leave disabled for now
+ // HAL will enable the timer during its initialization
+ //
+
+ WdRegister.All = 0;
+ WdRegister.Mode = WdMode;
+ WdRegister.TimerOnePeriod = WdTimer1;
+ WdRegister.TimerTwoPeriod = WdTimer2;
+
+#if DBG
+ DbgPrint("Watchdog setting: %04x\n",WdRegister.All);
+#endif
+ WRITE_REGISTER_USHORT((PUSHORT)HalpLegoWatchdogQva,WdRegister.All);
+
+ if (Enabled) {
+ WdRegister.Enabled = 1;
+ WRITE_REGISTER_USHORT((PUSHORT)HalpLegoWatchdogQva,WdRegister.All);
+ }
+ }
+}
+
+
+VOID
+HalpPowerOff(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Shutdown the system (i.e., shutdown power supply)
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Doesn't return.
+
+Notes:
+
+ This will work iff the proper connections to the power supply exists.
+
+ ++*/
+{
+ LEGO_SRV_MGMT SmRegister;
+ UCHAR Buffer[2];
+ int i,j,k;
+
+ //
+ // Set the power off bit in the server management register
+ //
+ // [wem] ??? Currently it appears that toggling the bit 1->0 triggers
+ // the shutdown. Toggle it both ways just in case...
+
+ SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva);
+ SmRegister.PowerOff = 0;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva,SmRegister.All);
+ SmRegister.PowerOff = 1;
+ WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva,SmRegister.All);
+
+ //
+ // Wait forever if necessary
+ //
+
+ i=j=k=0;
+ HalpOcpPutString("SHUT:000", 8, 0);
+ Buffer[1] = '\0';
+
+ while (1) {
+
+ if (i == 10) {
+ i = 0;
+ if (j == 10) {
+ j = 0;
+ if (k == 10) {
+ k = 0;
+ }
+ HalpOcpPutString(((k & 1)==0)?"DOWN":"SHUT", 4, 0);
+ Buffer[0] = '0' + k;
+ HalpOcpPutString(Buffer, 1, 5);
+ k++;
+ }
+ Buffer[0] = '0' + j;
+ HalpOcpPutString(Buffer, 1, 6);
+ j++;
+ }
+ Buffer[0] = '0' + i;
+ HalpOcpPutString(Buffer, 1, 7);
+ i++;
+ }
+
+}
+
+BOOLEAN
+LegoServerMgmtDelayedShutdown(
+ ULONG DelaySeconds
+ )
+/*++
+
+Routine Description:
+
+ Schedule a powerdown.
+
+ Current algorithm:
+ 1. Shutdown watchdog.
+ 2. Init watchdog for requested delay and single-stage timeout
+ (since interrupts will be shut off
+ 3. Set boolean to indicate power-down in progress
+ 4. return TRUE if power-down will occur
+
+ When reset is performed, firmware will get control, rediscover
+ failure, and act accordingly.
+
+ Problem? will shutdown or KeBugCheck disable interrupts? May have to do
+ something else...
+
+Arguments:
+
+ DelaySeconds -- desired delay. Should match capabilities of watchdog.
+
+Return Value:
+
+ TRUE if reset successfully initiated
+
+Notes:
+
+--*/
+{
+ BOOLEAN WillShutdown;
+ UCHAR Period;
+ ULONG Count;
+
+ //
+ // If watchdog not present, bail out
+ //
+
+ if (!(HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG)) {
+ return FALSE;
+ }
+
+ //
+ // Shutdown watchdog, then set it up for the
+ // requested delay.
+ //
+
+ WillShutdown = HalpLegoShutdownWatchdog();
+
+ if (WillShutdown) {
+ if (DelaySeconds <= 1) {
+ Period = WATCHDOG_PERIOD_1S;
+ }
+ else if (DelaySeconds <= 8) {
+ Period = WATCHDOG_PERIOD_8S;
+ }
+ else if (DelaySeconds <= 60) {
+ Period = WATCHDOG_PERIOD_60S;
+ }
+ else if (DelaySeconds <= 300) {
+ Period = WATCHDOG_PERIOD_300S;
+ }
+ else if (DelaySeconds <= 1200) {
+ Period = WATCHDOG_PERIOD_1200S;
+ }
+
+ HalpLegoInitWatchdog(WATCHDOG_MODE_1TIMER,
+ Period,
+ Period,
+ TRUE);
+ }
+
+ return WillShutdown; // Power-off attempt failed!
+}
diff --git a/private/ntos/nthals/hallego/alpha/vga.c b/private/ntos/nthals/hallego/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/hallego/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/hallego/bushnd.c b/private/ntos/nthals/hallego/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/hallego/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/hallego/drivesup.c b/private/ntos/nthals/hallego/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/hallego/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/hallego/hal.aps b/private/ntos/nthals/hallego/hal.aps
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/private/ntos/nthals/hallego/hal.aps
diff --git a/private/ntos/nthals/hallego/hal.rc b/private/ntos/nthals/hallego/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/hallego/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/hallego/hal.src b/private/ntos/nthals/hallego/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/hallego/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/hallego/makefile b/private/ntos/nthals/hallego/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/hallego/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/hallego/makefile.inc b/private/ntos/nthals/hallego/makefile.inc
new file mode 100644
index 000000000..75668f3d2
--- /dev/null
+++ b/private/ntos/nthals/hallego/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\hallego.lib
+ copy $** $@
diff --git a/private/ntos/nthals/hallego/sources b/private/ntos/nthals/hallego/sources
new file mode 100644
index 000000000..fe9f99c01
--- /dev/null
+++ b/private/ntos/nthals/hallego/sources
@@ -0,0 +1,111 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=hallego
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3
+C_DEFINES=-DEV4 -DAPECS -DTAGGED_NVRAM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\apecs.c \
+ alpha\apecserr.c \
+ alpha\apecsio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cmos8k.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mchk.c \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\nvram.c \
+ alpha\nvenv.c \
+ alpha\pcibus.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\lginitnt.c \
+ alpha\lgintsup.c \
+ alpha\lgintr.s \
+ alpha\lgmapio.c \
+ alpha\lgsysint.c \
+ alpha\pciir.c \
+ alpha\smir.c \
+ alpha\smerr.c \
+ alpha\smsup.c \
+ alpha\pcf8574.c \
+ alpha\pcd8584.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/hallx3/alpha/addrsup.c b/private/ntos/nthals/hallx3/alpha/addrsup.c
new file mode 100644
index 000000000..5c6365c6e
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/addrsup.c
@@ -0,0 +1,587 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "lx3.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on Avanti are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAXR2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ // Note that ISA and EISA buses can also request this space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_DENSE_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ if( (PA.QuadPart >= APECS_COMANCHE_BASE_PHYSICAL)
+ && (PA.QuadPart < APECS_PCI_DENSE_BASE_PHYSICAL)
+ )
+ {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Avanti we have only bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/hallx3/alpha/adjust.c b/private/ntos/nthals/hallx3/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/allstart.c b/private/ntos/nthals/hallx3/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/alphaio.s b/private/ntos/nthals/hallx3/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/hallx3/alpha/am29f400.c b/private/ntos/nthals/hallx3/alpha/am29f400.c
new file mode 100644
index 000000000..cc5152b17
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/am29f400.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\am29f400.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/apecs.c b/private/ntos/nthals/hallx3/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/apecserr.c b/private/ntos/nthals/hallx3/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/apecsio.s b/private/ntos/nthals/hallx3/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/hallx3/alpha/bios.c b/private/ntos/nthals/hallx3/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/busdata.c b/private/ntos/nthals/hallx3/alpha/busdata.c
new file mode 100644
index 000000000..cc2a153c1
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/busdata.c
@@ -0,0 +1,125 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/hallx3/alpha/cache.c b/private/ntos/nthals/hallx3/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/chipset.h b/private/ntos/nthals/hallx3/alpha/chipset.h
new file mode 100644
index 000000000..0a72ef8cb
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/chipset.h
@@ -0,0 +1 @@
+#include "apecs.h"
diff --git a/private/ntos/nthals/hallx3/alpha/eisasup.c b/private/ntos/nthals/hallx3/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/environ.c b/private/ntos/nthals/hallx3/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ev4cache.c b/private/ntos/nthals/hallx3/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ev4int.c b/private/ntos/nthals/hallx3/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ev4ints.s b/private/ntos/nthals/hallx3/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ev4mchk.c b/private/ntos/nthals/hallx3/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ev4mem.s b/private/ntos/nthals/hallx3/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ev4prof.c b/private/ntos/nthals/hallx3/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/flash8k.c b/private/ntos/nthals/hallx3/alpha/flash8k.c
new file mode 100644
index 000000000..193b2b9fc
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/flash8k.c
@@ -0,0 +1,518 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ flash8k.c
+
+Abstract:
+
+ This module implements the flash-specific, device-independent routines
+ necessary to Read and Write the flash ROM containing the system environment
+ variables. The routines implemented here are:
+
+ HalpReadNVRamBuffer() - copy data from Flash into memory
+ HalpWriteNVRamBuffer() - write memory data to Flash
+ HalpCopyNVRamBuffer() - stubbed for compatibility with NVRAM
+
+Author:
+
+ Steve Brooks 5-Oct 93
+
+
+Revision History:
+
+ Wim Colgate 1-May-1995
+
+ Added LX3 specfic code for Bankset 8 mumbo-jumbo for the LX3 specific
+ 'Flash Bus'.
+
+
+--*/
+
+
+#include "halp.h"
+#include "pflash.h"
+#include "flash8k.h"
+
+#include "arccodes.h"
+
+//
+// To access the flash bus, one needs to enable the bankset 8 in
+// the APECS chipset.
+//
+
+#define BANKSET8_CONFIGURATION_REGISTER HAL_MAKE_QVA( 0x180000B00 )
+#define BANKSET8_ENABLE 0x1
+
+#define STALL_VALUE 16
+
+//
+// This variable tells us which bank of 8K 'nvram' are we using
+// The LX3 nvram is actually two separate 8K sections of the FLASH ROM.
+// One living at 0x4000, the other at 0x8000.
+//
+// This 'base' is not a QVA as in other platforms -- rather it is a base
+// index off of the FLASH ROM device (0-512K).
+
+extern ULONG Am29F400NVRAMBase;
+
+//
+// Variables:
+//
+// PFLASH_DRIVER HalpFlashDriver
+// Pointer to the device-specific flash driver.
+//
+
+PFLASH_DRIVER HalpFlashDriver = NULL;
+
+//
+// Flash Drivers
+//
+// Each platform which uses this module must define FlashDriverList as an
+// array of pointers to the initialize functions of any flash drivers for
+// which the flash device might be used for the environment in the system.
+//
+
+extern PFLASH_DRIVER (*FlashDriverList[])(ULONG);
+
+//
+// Local function prototypes.
+//
+
+ARC_STATUS
+HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamOffset,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamOffset,
+ IN PCHAR DataPtr,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length
+ );
+
+PFLASH_DRIVER
+HalpInitializeFlashDriver(
+ IN ULONG NvRamOffset
+ );
+
+#ifdef AXP_FIRMWARE
+
+#pragma alloc_text(DISTEXT, HalpReadNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpWriteNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpCopyNVRamBuffer )
+#pragma alloc_text(DISTEXT, HalpInitializeFlashDriver )
+
+#endif
+
+ARC_STATUS HalpReadNVRamBuffer (
+ OUT PCHAR DataPtr,
+ IN PCHAR NvRamOffset,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Reads data from the NVRam into main memory
+
+Arguments:
+
+ DataPtr - Pointer to memory location to receive data
+ NvRamOffset- NVRam offset to read data from
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+ ENODEV if no flash driver is loaded
+ E2BIG if we attempt to read beyond the end of the NVRAM location
+
+--*/
+{
+ ULONG CsrMask;
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("HalpReadNVRamBuffer(%08x, %08x, %d)\r\n",(ULONG)DataPtr,
+ NvRamOffset, Length);
+#endif
+
+ //
+ // If there is no flash driver, return an error.
+ //
+
+ if ((HalpFlashDriver == NULL) &&
+ ((HalpFlashDriver =
+ HalpInitializeFlashDriver((ULONG)NvRamOffset)) == NULL)) {
+
+ return ENODEV;
+ }
+
+ //
+ // Check to see if we will read beyond the bounds...
+ // (normalize offset - base + length)
+ //
+
+ if (NvRamOffset - Am29F400NVRAMBase + Length > (PUCHAR)NVRAM1_SECTOR_SIZE) {
+ return E2BIG;
+ }
+
+ //
+ // Adjust the offset by the NVRAM Base -- The NVRAM Offset is going
+ // to be 0-8K. The Base is where in the FLASH ROM the NVRAM is located.
+ // Since these routines are going to call the lower FLASH ROM routines,
+ // (which spans 0-512K), we need to adjust the NVRAM offset appropriately.
+ //
+
+ //
+ // Enable Bankset 8
+ //
+
+ CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER );
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER,
+ CsrMask | BANKSET8_ENABLE );
+
+ //
+ // Read from the flash.
+ //
+
+ HalpFlash8kSetReadMode(NvRamOffset);
+ while(Length--) {
+ *DataPtr = HalpFlash8kReadByte(NvRamOffset);
+ DataPtr++;
+ NvRamOffset++;
+ }
+
+ //
+ // Disable Bankset 8 (Restore original state)
+ //
+
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask );
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+HalpWriteNVRamBuffer (
+ IN PCHAR NvRamOffset,
+ IN PCHAR DataPtr,
+ IN ULONG Length )
+
+/*++
+
+Routine Description:
+
+ This routine Writes data from memory into the NVRam
+
+Arguments:
+
+ NvRamOffset- NVRam Offset to write data into
+ DataPtr - Pointer to memory location of data to be written
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ESUCCESS if the operation succeeds.
+ ENODEV if no flash driver is loaded
+ EIO if a device error was detected
+ E2BIG if we attempt to write beyond the end of the NVRAM location
+
+--*/
+{
+ ARC_STATUS ReturnStatus = ESUCCESS;
+ UCHAR NeedToErase = FALSE;
+ UCHAR Byte;
+ ULONG Index;
+ ULONG Offset;
+ ULONG CsrMask;
+ PUCHAR FlashBuffer;
+
+ ULONG SectorSize;
+ ULONG SectorBase;
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("HalpWriteNVRamBuffer(%08x, %08x, %d)\r\n", NvRamOffset,
+ (ULONG)DataPtr, Length);
+#endif
+
+ //
+ // If there is no flash driver, return an error.
+ //
+
+ if ((HalpFlashDriver == NULL) &&
+ ((HalpFlashDriver =
+ HalpInitializeFlashDriver((ULONG)NvRamOffset)) == NULL)) {
+
+ return ENODEV;
+ }
+
+ //
+ // Check to see if we will write beyond the bounds...
+ // (normalize offset - base + length)
+ //
+
+ if (NvRamOffset - Am29F400NVRAMBase + Length > (PUCHAR)NVRAM1_SECTOR_SIZE) {
+ return E2BIG;
+ }
+
+ //
+ // Enable Bankset 8
+ //
+
+ CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER );
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER,
+ CsrMask | BANKSET8_ENABLE );
+
+ //
+ // Read the whole bloody Physical NVRAM into a temporary buffer for
+ // comparisons
+ //
+
+ SectorBase = (ULONG)HalpFlash8kSectorAlign(NvRamOffset);
+ SectorSize = HalpFlash8kSectorSize(SectorBase);
+
+ FlashBuffer = ExAllocatePool(NonPagedPool, SectorSize);
+ if (FlashBuffer == NULL) {
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("HalpWriteNVRamBuffer: Could not allocate shadow\r\n");
+#endif
+ return ENOMEM;
+ }
+
+ ReturnStatus = HalpReadNVRamBuffer(FlashBuffer,
+ (PUCHAR)SectorBase,
+ SectorSize);
+
+ //
+ // Check to see if we can write the data as is. Since we're dealing with
+ // a flash ROM device, we can only program 1-->1 and 1-->0, but not 0-->1.
+ //
+
+ Offset = (ULONG)NvRamOffset;
+ for (Index = 0; (Index < Length) && !NeedToErase; Index++, Offset++) {
+
+ Byte = FlashBuffer[Offset - SectorBase];
+
+ if (!HalpFlash8kOverwriteCheck(Byte, (UCHAR)DataPtr[Index])) {
+ NeedToErase = TRUE;
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Need to erase flash because byte at %08x (%02x) ",
+ Offset, Byte);
+ DbgPrint("Cannot be written with %02x\r\n", (UCHAR)DataPtr[Index]);
+#endif
+
+ }
+
+ }
+
+ //
+ // We can either program directly, or we must erase first.
+ // split this path here.
+ //
+
+ if (!NeedToErase) {
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Don't need to erase -- simple overwrite\n");
+#endif
+ Offset = (ULONG)NvRamOffset;
+ for (Index = 0; Index < Length; Index++, Offset++) {
+
+ //
+ // if byte is the same - don't bother writing
+ //
+
+ Byte = FlashBuffer[Offset - SectorBase];
+
+ if (Byte != (UCHAR)DataPtr[Index]) {
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Writing %02x at %x\n", (UCHAR)DataPtr[Index], Offset);
+#endif
+ HalpStallExecution(STALL_VALUE);
+ ReturnStatus = HalpFlash8kWriteByte(Offset,DataPtr[Index]);
+ if (ReturnStatus != ESUCCESS) {
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Failed to write %02x (was %02x) at %x status %x (Retrying...)\n",
+ (UCHAR)DataPtr[Index], Byte, Offset, ReturnStatus);
+#endif
+ //
+ // Retry
+ //
+
+ Index--; Offset--;
+ }
+ }
+ }
+ } else {
+
+ //
+ // We need to erase the flash block in order to write some of the
+ // requested data.
+ //
+
+
+ //
+ // Merge our data with the existing FLASH ROM data.
+ //
+
+ for(Index = 0; Index < Length; Index++) {
+ FlashBuffer[(ULONG)NvRamOffset - SectorBase + Index] =
+ DataPtr[Index];
+ }
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Erasing sector\n");
+#endif
+
+ //
+ // Erase the sector
+ //
+
+ ReturnStatus = HalpFlash8kEraseSector(SectorBase);
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Returned from erase: %x\n", ReturnStatus);
+ DbgPrint("Writing %x bytes to %x\n", SectorSize, SectorBase);
+#endif
+
+ for (Index = 0; Index < SectorSize; Index++, Offset++) {
+
+ if (FlashBuffer[Index] != HalpFlashDriver->ErasedData) {
+
+ HalpStallExecution(STALL_VALUE);
+
+ ReturnStatus = HalpFlash8kWriteByte(SectorBase + Index,
+ FlashBuffer[Index]);
+ if (ReturnStatus != ESUCCESS) {
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("Failed to write %02x at %x status %x (Retrying...)\n",
+ (UCHAR)FlashBuffer[Index], SectorBase + Index, ReturnStatus);
+#endif
+ //
+ // Retry
+ //
+
+ Index--; Offset--;
+ }
+ }
+ }
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("\nReturned from write: %x\n", ReturnStatus);
+ DbgPrint("Wrote %x bytes\n", Index);
+#endif
+
+ }
+
+ //
+ // Disable Bankset 8 (Restore original state)
+ //
+
+ WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask );
+
+ HalpFlash8kSetReadMode(NvRamOffset);
+
+ ExFreePool(FlashBuffer);
+
+ return ReturnStatus;
+}
+
+//
+//
+//
+ARC_STATUS HalpCopyNVRamBuffer (
+ IN PCHAR NvDestPtr,
+ IN PCHAR NvSrcPtr,
+ IN ULONG Length )
+/*++
+
+Routine Description:
+
+ This routine is not supported.
+
+Arguments:
+
+ NvDestPtr- NVRam Offset to write data into
+ NvSrcPtr - NVRam Offset of data to copy
+ Length - Number of bytes of data to transfer
+
+Return Value:
+
+ ENODEV if no flash driver is loaded
+ EIO if a flash driver is loaded
+
+--*/
+
+{
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ DbgPrint("HalpCopyNVRamBuffer()\r\n");
+#endif
+
+ //
+ // If there is no flash driver, return an error.
+ //
+ if (HalpFlashDriver == NULL) {
+ return ENODEV;
+ }
+
+ return EIO;
+}
+
+PFLASH_DRIVER
+HalpInitializeFlashDriver(
+ IN ULONG NvRamOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine attempts to recognize the flash device present in the
+ system by calling each known flash driver's Initialize() function
+ with the address passed in. The Initialize() functions will each
+ return NULL if they do not recognize the flash device at the specified
+ address and a pointer to a FLASH_DRIVER structure if the device is
+ recognized. This routine looks until it either recognizes a flash device
+ or runs out of known flash devices.
+
+Arguments:
+
+ NvRamOffset - an Offset within the flash device
+
+Return Value:
+
+ A pointer to the FLASH_DRIVER structure of the driver which corresponds
+ to the flash device in the system. NULL if no known flash device was
+ recognized.
+
+--*/
+{
+ PFLASH_DRIVER FlashDriver = NULL;
+ ULONG DriverNumber;
+
+ for(DriverNumber=0; FlashDriverList[DriverNumber] != NULL; DriverNumber++) {
+ FlashDriver = FlashDriverList[DriverNumber](NvRamOffset);
+ if (FlashDriver != NULL) {
+ break;
+ }
+ }
+
+#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
+ if (FlashDriver == NULL) {
+ DbgPrint("ERROR: No flash device found at %08x\r\n", NvRamOffset);
+ }
+#endif
+
+ return FlashDriver;
+}
+
diff --git a/private/ntos/nthals/hallx3/alpha/flash8k.h b/private/ntos/nthals/hallx3/alpha/flash8k.h
new file mode 100644
index 000000000..7d9131baa
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/flash8k.h
@@ -0,0 +1,80 @@
+// flash8k.h
+
+#ifndef _FLASH8K_H_
+#define _FLASH8K_H_
+
+#include "halp.h"
+#include "arccodes.h"
+
+//
+// The value of HalpCMOSRamBase must be set at initialization
+//
+
+typedef enum _FLASH_OPERATIONS {
+ FlashByteWrite,
+ FlashEraseSector
+} FLASH_OPERATIONS, *PFLASH_OPERATIONS;
+
+typedef struct _FLASH_DRIVER {
+ PCHAR DeviceName;
+ ARC_STATUS (*SetReadModeFunction)(PUCHAR Offset);
+ ARC_STATUS (*WriteByteFunction)(PUCHAR Offset, UCHAR data);
+ ARC_STATUS (*EraseSectorFunction)(PUCHAR Offset);
+ PUCHAR (*SectorAlignFunction)(PUCHAR Offset);
+ UCHAR (*ReadByteFunction)(PUCHAR Offset);
+ BOOLEAN (*OverwriteCheckFunction)(UCHAR olddata, UCHAR newdata);
+ ULONG (*SectorSizeFunction)(PUCHAR Offset);
+ ULONG DeviceSize;
+ UCHAR ErasedData;
+} FLASH_DRIVER, *PFLASH_DRIVER;
+
+extern PFLASH_DRIVER HalpFlashDriver;
+
+//
+// The following macros define the HalpFlash8k*() functions in terms
+// of the FlashDriver variable. FlashDriver points to a structure
+// containing information about the currently active flash driver.
+// Information in the structure pointed to by FlashDriver includes
+// functions within the driver to perform all device-dependent operations.
+//
+
+#define HalpFlash8kSetReadMode(boffset) \
+ HalpFlashDriver->SetReadModeFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kReadByte(boffset) \
+ HalpFlashDriver->ReadByteFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kWriteByte(boffset, data) \
+ HalpFlashDriver->WriteByteFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)), ((data) & 0xff))
+
+#define HalpFlash8kOverwriteCheck(olddata, newdata) \
+ HalpFlashDriver->OverwriteCheckFunction( \
+ (olddata) & 0xff, (newdata) & 0xff)
+
+#define HalpFlash8kEraseSector(boffset) \
+ HalpFlashDriver->EraseSectorFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kSectorAlign(boffset) \
+ HalpFlashDriver->SectorAlignFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kSectorSize(boffset) \
+ HalpFlashDriver->SectorSizeFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)))
+
+#define HalpFlash8kCheckStatus(boffset, operation) \
+ HalpFlashDriver->CheckStatusFunction( \
+ (PUCHAR)((ULONG)(HalpCMOSRamBase) | \
+ (ULONG)(boffset)), (operation))
+
+#endif // _FLASH8K_H_
diff --git a/private/ntos/nthals/hallx3/alpha/flashbus.h b/private/ntos/nthals/hallx3/alpha/flashbus.h
new file mode 100644
index 000000000..2fceabad3
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/flashbus.h
@@ -0,0 +1,9 @@
+//
+// These are the defines that make up access to the FlashBus
+//
+
+#define FLASH_ACCESS_ADDR HAL_MAKE_QVA( 0x100000000 )
+#define FLASH_ADDR_SHIFT 8
+#define FLASH_WRITE_FLAG (0x80000000)
+
+#define CONFIG_ACCESS_ADDR HAL_MAKE_QVA( 0x100100000 )
diff --git a/private/ntos/nthals/hallx3/alpha/flashdrv.c b/private/ntos/nthals/hallx3/alpha/flashdrv.c
new file mode 100644
index 000000000..43638aa02
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/flashdrv.c
@@ -0,0 +1,19 @@
+#include "flash8k.h"
+
+//
+// Flash Drivers
+//
+// extern declarations of each known flash driver's Initialize() funcion
+// are needed here for addition into the list of known drivers.
+//
+// FlashDriverList is an array of driver Initialize() functions used to
+// identify the flash device present in the system. The last entry
+// in FlashDriverList must be NULL.
+//
+extern PFLASH_DRIVER Am29F400_Initialize(PUCHAR);
+
+PFLASH_DRIVER (*FlashDriverList[])(PUCHAR) = {
+ Am29F400_Initialize,
+ NULL};
+
+
diff --git a/private/ntos/nthals/hallx3/alpha/fwreturn.c b/private/ntos/nthals/hallx3/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/haldebug.c b/private/ntos/nthals/hallx3/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/halpal.s b/private/ntos/nthals/hallx3/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/hallx3/alpha/idle.s b/private/ntos/nthals/hallx3/alpha/idle.s
new file mode 100644
index 000000000..22dc3c2ee
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/idle.s
@@ -0,0 +1,187 @@
+// TITLE("Processor Idle Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// idle.s
+//
+// Abstract:
+//
+// This module implements the HalProcessorIdle interface
+//
+// Author:
+//
+// John Vert (jvert) 11-May-1994
+//
+// Environment:
+//
+// Revision History:
+//
+// Wim Colgate, 11-Nov-1995
+//
+// Modified stub routine to idle the processor on LX3.
+//
+//--
+#include "halalpha.h"
+#include "lx3.h"
+
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with interrupts disabled. This routine
+// must do any power management enabling necessary, enable interrupts,
+// then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+// Note:
+//
+// On LX3, the sequence of events should are:
+//
+// Write "idle" to processor
+// Flush Dcache
+// Enable Interrupts
+//
+// All of the above MUST be loaded into the Icache of the processor
+// once we write "idle" to the processor
+//
+// Once the processor is idle, we cannot get to the backup cache,
+// nor main memory. Once an interrupt occurs, the CPU reattaches via
+// hardware magic.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+ //
+ // Enable, then disable interrups to force the PALcode
+ // enable_interrupt routine into the Icache -- by executing it,
+ // then back to interrupts disabled.
+ //
+
+ ENABLE_INTERRUPTS
+
+#ifdef IDLE_PROCESSOR
+
+ //
+ // set up temps here - instead of in critical Icache area
+ // temps are a0-a5, t0-t7
+ //
+
+ lda a0, HalpInterruptReceived
+ bis zero, 1, t3
+ stl t3, 0(a0)
+
+ //
+ // set up t5 for superpage mode base address
+ //
+
+ ldiq t5, -0x4000 // 0xffff ffff ffff c000
+ sll t5, 28, t5 // 0xffff fc00 0000 0000
+
+ //
+ // set t7 for interrupt register to poll on
+ //
+
+ ldah t7, 0x1b(zero) // 0x0000 0000 1b00 0000
+ sll t7, 4, t7 // 0x0000 0001 b000 0000
+
+ bis t5, t7, t7 // 0xffff fc01 b000 0000
+
+ //
+ // set t6 for a 32K constant for Dcache flushing
+ //
+
+ ldil t6, 0x8000 // 0x0000 0000 0000 8000
+
+ //
+ // set a1 to be the 'bouncing' bit
+ //
+
+ bis zero, 1, a1
+
+ mb
+
+ DISABLE_INTERRUPTS
+
+ //
+ // Flush Dcache -- start at superpage address 0 and read 32K worth of
+ // data
+ //
+
+flush: ldl t1, 0(t5) // read data
+ addl t5, 0x20, t5 // increment location by 8 longwords
+ and t5, t6, t4 // check for 32K limit
+ bne t4, setspin // loop finished
+ br zero, flush // branch back
+
+ bne a1, touch1 // bounce ahead to touch1
+
+continue:
+
+ //
+ // clear a1 (aka the bouncing bit) so that we actually execite code
+ // now.
+
+ bis zero, zero, a1
+
+ //
+ // Power down the processor to 'idle speed', which is not
+ // completelty off. Duh.
+ //
+
+ ldil t0, CONFIG_REGISTER_SMALL // 0x0000 0000 0000 1001
+ sll t0, 20, t0 // 0x0000 0001 0010 0000
+
+ bis t0, t5, t0 // 0xffff fc01 0010 0000
+
+ ldil t2, CONFIG_SELECT_IDLE // load idle setting
+ stl t2, 0(t0) // set processor to idle
+
+ //
+ // Past this point, all instructions MUST be in the Icache
+ //
+
+ //
+ // Enable Interrupts
+ //
+
+setspin:
+ ENABLE_INTERRUPTS
+
+ //
+ // spin on the interrupt bit -- cleared by any interrupt routine
+ //
+
+spin: ldl t0, 0(a0) // load bit
+ bne t0, spin // spin on bit
+
+touch1: bne a1, continue // go all the way back
+
+#endif
+
+done: ret zero, (ra)
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/hallx3/alpha/info.c b/private/ntos/nthals/hallx3/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/inithal.c b/private/ntos/nthals/hallx3/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/intsup.s b/private/ntos/nthals/hallx3/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/hallx3/alpha/ioproc.c b/private/ntos/nthals/hallx3/alpha/ioproc.c
new file mode 100644
index 000000000..47c62196e
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/ioproc.c
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+extern UCHAR HalRegisteredName[];
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/hallx3/alpha/iousage.c b/private/ntos/nthals/hallx3/alpha/iousage.c
new file mode 100644
index 000000000..c3f2bbe99
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/iousage.c
@@ -0,0 +1,554 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Define constants for system IDTs
+//
+
+#define MAXIMUM_IDTVECTOR 0xff
+#define MAXIMUM_PRIMARY_VECTOR 0xff
+#define PRIMARY_VECTOR_BASE 0x30 // 0-2f are x86 trap vectors
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/ISA HAL";
+
+//
+// Array to remember hal's IDT usage
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+#if 0
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+#endif //0
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS TempAddress;
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 3; pass++) {
+
+ switch(pass) {
+
+ case 0: {
+#if DBG
+DbgPrint("Device LIST...\n");
+#endif // DBG
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ break;
+ }
+
+ case 1: {
+#if DBG
+DbgPrint("Internal LIST...\n");
+#endif // DBG
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ break;
+ }
+
+ case 2: {
+#if DBG
+DbgPrint("PCI LIST...\n");
+#endif // DBG
+ //
+ // Third pass = build reousce lists for resources reported
+ // as PCI usage.
+ //
+
+ reporton = PCIUsage & ~IDTOwned;
+ interfacetype = PCIBus;
+ break;
+ }
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+#if DBG
+DbgPrint("Start=0x%x Lenght=0x%x\n", RPartialDesc.u.Memory.Start.LowPart, RPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TempAddress ); // aligned translated address
+
+ TPartialDesc.u.Memory.Start = TempAddress; // TPartialDesc is pack(4)
+
+#if DBG
+DbgPrint("TRANSLATED ADDRESS Start=0x%x Lenght=0x%x\n", TPartialDesc.u.Memory.Start.LowPart, TPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/hallx3/alpha/iousage.h b/private/ntos/nthals/hallx3/alpha/iousage.h
new file mode 100644
index 000000000..cefab9095
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/iousage.h
@@ -0,0 +1,92 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992,1993 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Most pieces have be stolen from Microsofts halp.h
+
+--*/
+
+//
+// External Function Prototypes
+//
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ );
+
+//
+// Resource usage information
+//
+
+#pragma pack(1)
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ ULONG Length;
+ } Element[];
+} ADDRESS_USAGE;
+#pragma pack()
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+#define PCIUsage 0x41 // Report usage on PCI bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
diff --git a/private/ntos/nthals/hallx3/alpha/lx3.h b/private/ntos/nthals/hallx3/alpha/lx3.h
new file mode 100644
index 000000000..157c89bd3
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/lx3.h
@@ -0,0 +1,155 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ avantdef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Avanti modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+
+--*/
+
+#ifndef _LX3DEF_
+#define _LX3DEF_
+
+#include "alpharef.h"
+#include "apecs.h"
+#include "isaaddr.h"
+
+//
+// Highest Virtual local PCI Slot is 14 == IDSEL PCI_AD[25]
+//
+
+#define PCI_MAX_LOCAL_DEVICE 14
+
+//
+// Highest PCI interrupt vector is in ISA Vector Space
+//
+
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_ISA_VECTOR - ISA_VECTORS)
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV4 processor.
+//
+
+#if !defined (_LANGUAGE_ASSEMBLY) && !defined (AXP_FIRMWARE)
+
+typedef struct _AVANTI_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq];// Irq status table
+} AVANTI_PCR, *PAVANTI_PCR;
+
+//
+// Short form for PCR access
+//
+
+#define HAL_PCR ( (PAVANTI_PCR)(&(PCR->HalReserved)) )
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+//
+// define base of sparse I/O space
+//
+#define PCI_SPARSE_IO_BASE_QVA ((ULONG)(HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL)))
+
+//
+// PCI-E/ISA Bridge chip configuration space base is at physical address
+// 0x1.e000.0000. The equivalent QVA is:
+//
+// ((0x1.e000.0000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+// which equals 0xaf000000.
+//
+// NB: The PCI configuration space address is what we're really referring
+// to, here; both symbols are useful.
+//
+
+#define PCI_CONFIGURATION_BASE_QVA 0xaf000000
+#define PCI_BRIDGE_CONFIGURATION_BASE_QVA 0xaf000000
+
+//
+// ISA memory space base starts at 0x2.0000.0000.
+// The equivalent QVA is:
+//
+// ((0x2.0000.0000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+
+#define ISA_MEMORY_BASE_QVA 0xb0000000
+
+//
+// I/O space base starts at 0x3.0000.0000.
+// The equivalent QVA is:
+//
+// ((0x3.0000.0000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+
+#define IO_BASE_QVA 0xAE000000
+
+//
+// Define the PCI config cycle type
+//
+
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device
+
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+
+//
+// Define the location of the PCI/ISA bridge IDSEL: AD[18]
+//
+
+#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00070000 >> IO_BIT_SHIFT)
+
+
+//
+// Define primary (and only) CPU on an Avanti system
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0)
+
+//
+// Define the default processor clock frequency used before the actual
+// value can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (233)
+#define DEFAULT_PROCESSOR_CYCLE_COUNT (1000000/233)
+
+//
+// define configuration register
+// (see page 5-3) of the LX3 spec.
+//
+
+#define CONFIG_REGISTER_PHYS 0x100100000
+#define CONFIG_REGISTER_SMALL 0x1001
+
+#define CONFIG_SELECT_DISABLE_AUDIO 0x0
+#define CONFIG_SELECT_ENABLE_AUDIO 0x1
+#define CONFIG_SELECT_SELECT_AUDIO1_530 0x10
+#define CONFIG_SELECT_SELECT_AUDIO1_E80 0x11
+#define CONFIG_SELECT_SELECT_AUDIO2_F40 0x20
+#define CONFIG_SELECT_SELECT_AUDIO2_604 0x21
+#define CONFIG_SELECT_ECP_DMA_0 0x30
+#define CONFIG_SELECT_ECP_DMA_1 0x31
+#define CONFIG_SELECT_DISABLE_87303 0x40
+#define CONFIG_SELECT_ENABLE_87303 0x41
+#define CONFIG_SELECT_LIGHT_LED 0x60
+#define CONFIG_SELECT_UNLIGHT_LED 0x61
+#define CONFIG_SELECT_RESET_SYSTEM 0x71
+#define CONFIG_SELECT_IDLE 0x80
+
+#endif // _LX3DEF_
+
diff --git a/private/ntos/nthals/hallx3/alpha/lxinitnt.c b/private/ntos/nthals/hallx3/alpha/lxinitnt.c
new file mode 100644
index 000000000..8706dfb4a
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/lxinitnt.c
@@ -0,0 +1,900 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+
+Module Name:
+
+ lxinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Wim Colgate November, 1995
+ modified Joe's cruft for LX3 support.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "lx3.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+#if DBG
+VOID
+DumpEpic(
+ VOID
+ );
+#endif // DBG
+
+//
+// temporary
+//
+
+PVOID HalpCMOSRamBase = 0;
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpProductName = "255";
+PCHAR HalpFamilyName = "AlphaStation";
+ULONG HalpProcessorNumber = 4;
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Avanti
+//
+// IRQ_H[0] = EPIC Error
+// IRQ_H[1] = unused
+// IRQ_H[2] = PIC
+// IRQ_H[3] = NMI
+// IRQ_H[4] = Clock
+// IRQ_H[5] = Halt
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+ADDRESS_USAGE
+AvantiPCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
+ 0,0
+ }
+};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ );
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpClearInterrupts(
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+//jnfix, wkc - init the Eisa interrupts after the chip, don't init the
+// PIC here, fix halenablesysteminterrupt to init the pic
+// interrrupt, as in sable
+
+ //
+ // Initialize the PCI/ISA interrupt controller.
+ //
+
+ HalpInitializePCIInterrupts();
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize error handling for APECS.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeHalName(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Thsi routine intializes the visible HAL name.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ UCHAR MsgBuffer[256];
+
+ sprintf(MsgBuffer,
+ "%s %s, %d Mhz, PCI/ISA HAL\n",
+ HalpFamilyName,
+ HalpProductName,
+ HalpClockMegaHertz );
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( MsgBuffer );
+
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ UCHAR MsgBuffer[256];
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish the error handler, to reflect the parity checking
+ //
+
+ HalpEstablishErrorHandler();
+
+ //
+ // Set the HAE registers
+ //
+
+ HalpInitializeHAERegisters();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus( LoaderBlock );
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+
+ //
+ // Print out a cool-o message
+ //
+
+ sprintf(MsgBuffer,
+ "Digital Equipment Corporation %s %s\n",
+ HalpFamilyName,
+ HalpProductName);
+
+ HalDisplayString(MsgBuffer);
+
+ //
+ // Initialize HAL name
+ //
+
+ HalpInitializeHalName();
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the EPIC/APECS chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // We set HAXR1 to 0. This means no address extension
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0);
+
+ //
+ // We set HAXR2 to 0. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. HAXR2 Not used in address translation
+ // 64K to 16MB VALID. HAXR2 is used in the address translation
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0);
+
+ //
+ // Report that the apecs mapping to the Io subsystem
+ //
+
+ HalpRegisterAddressUsage (&AvantiPCIMemorySpace);
+
+#if DBG
+ DumpEpic();
+#endif // DBG
+}
+
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the EPIC/APECS chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0 );
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0 );
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ FwExtSysInfo.SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+ sprintf(SystemInfo->SystemType,"lx3");
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(APECS_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV4_UNCORRECTABLE processorFrame;
+ APECS_UNCORRECTABLE_FRAME AvantiUnCorrrectable;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/hallx3/alpha/lxintsup.c b/private/ntos/nthals/hallx3/alpha/lxintsup.c
new file mode 100644
index 000000000..f9a535832
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/lxintsup.c
@@ -0,0 +1,396 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ lxintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for LX3
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Rewritten from ebintsup.c to lx3intsup.
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "lx3.h"
+#include "pcrtc.h"
+
+
+extern BOOLEAN SioCStep;
+
+#ifdef IDLE_PROCESSOR
+ULONG HalpInterruptReceived;
+BOOLEAN
+PreHalpSioDispatch(
+ VOID
+ );
+#endif
+
+//
+// Declare the interrupt handler for the PCI and ISA bus.
+//
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for ISA & PCI operations
+ and connects the intermediate interrupt dispatcher.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+#ifdef IDLE_PROCESSOR
+ PCR->InterruptRoutine[PIC_VECTOR] = PreHalpSioDispatch;
+#else
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch;
+#endif
+ HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive);
+
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+
+ //
+ // Initialize the PCI-ISA bridge interrupt controller
+ //
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+#ifdef IDLE_PROCESSOR
+ //
+ // Clear interrupt flag
+ //
+
+ HalpInterruptReceived = 0;
+#endif
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Sio machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+#ifdef IDLE_PROCESSOR
+ //
+ // Clear interrupt flag
+ //
+
+ HalpInterruptReceived = 0;
+#endif
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ return( InterruptVector );
+
+}
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+#ifdef IDLE_PROCESSOR
+ //
+ // Clear interrupt flag
+ //
+
+ HalpInterruptReceived = 0;
+#endif
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+#ifdef IDLE_PROCESSOR
+BOOLEAN
+PreHalpSioDispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt by clearing the interrupt flag, then
+ dispatch to the real PCI/SIO interrupt handler
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Clear interrupt flag
+ //
+
+ HalpInterruptReceived = 0;
+
+ return HalpSioDispatch();
+
+}
+#endif
+
diff --git a/private/ntos/nthals/hallx3/alpha/lxmapio.c b/private/ntos/nthals/hallx3/alpha/lxmapio.c
new file mode 100644
index 000000000..4ecab50a2
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/lxmapio.c
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ lxmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Wim Colgate 27-April-1995
+
+ Renamed for LX3.
+
+
+--*/
+
+#include "halp.h"
+#include "lx3.h"
+#include "pflash.h"
+
+
+//
+// Define global data used to locate the EISA control space.
+//
+// The reason these names seem strange, is because they are legacy names.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for an Avanti
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( APECS_PCI_IO_BASE_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( APECS_PCI_INTACK_BASE_PHYSICAL );
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ //
+ // Set the base offset of the NVRAM location inside the FLASH ROM
+ //
+
+ HalpCMOSRamBase = (PVOID)NVRAM1_BASE;
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/hallx3/alpha/lxsgdma.c b/private/ntos/nthals/hallx3/alpha/lxsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/lxsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/lxsysint.c b/private/ntos/nthals/hallx3/alpha/lxsysint.c
new file mode 100644
index 000000000..48a092204
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/lxsysint.c
@@ -0,0 +1,394 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "lx3.h"
+#include "axp21064.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR
+ //
+
+ return((BusInterruptLevel) + ISA_VECTORS);
+
+ break;
+
+
+
+ default:
+
+ //
+ // Not an interface supported on EB66/Mustang systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Avanti because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/hallx3/alpha/machdep.h b/private/ntos/nthals/hallx3/alpha/machdep.h
new file mode 100644
index 000000000..542953086
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/machdep.h
@@ -0,0 +1,44 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Avanti platform-specific definitions.
+//
+
+#include "lx3.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+extern ULONG Am29F400NVRAMBase;
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/hallx3/alpha/memory.c b/private/ntos/nthals/hallx3/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/nvenv.c b/private/ntos/nthals/hallx3/alpha/nvenv.c
new file mode 100644
index 000000000..8a8dfdeb5
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/nvenv.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\nvenv.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/nvram.c b/private/ntos/nthals/hallx3/alpha/nvram.c
new file mode 100644
index 000000000..6fd93ab46
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/nvram.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\nvram.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/pcibus.c b/private/ntos/nthals/hallx3/alpha/pcibus.c
new file mode 100644
index 000000000..9b5c260ea
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pcibus.c
@@ -0,0 +1,108 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+//
+// This references a boolean variable that identifies the APECS revision.
+//
+
+extern ULONG PCIMaxBus;
+
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0)
+ {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24, which, in APECS
+ // pass 1, are wired to IDSEL pins. In pass 2, the format of a type
+ // 0 cycle is the same as the format of a type 1. Note that
+ // HalpValidPCISlot has already done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ else
+ {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if HALDBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/hallx3/alpha/pcisio.c b/private/ntos/nthals/hallx3/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/pcisup.c b/private/ntos/nthals/hallx3/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/pcrtc.c b/private/ntos/nthals/hallx3/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/pcserial.c b/private/ntos/nthals/hallx3/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/pcspeakr.c b/private/ntos/nthals/hallx3/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/perfcntr.c b/private/ntos/nthals/hallx3/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/hallx3/alpha/pflash.c b/private/ntos/nthals/hallx3/alpha/pflash.c
new file mode 100644
index 000000000..870902f60
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pflash.c
@@ -0,0 +1,91 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ pflash.c
+
+Abstract:
+
+ This module contains the platform dependent code to access the AMD
+ flash ROM part
+
+Author:
+
+ Wim Colgate, 5/23/95
+
+Environment:
+
+ Firmware/Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include <flash8k.h>
+#include "flashbus.h"
+#include "am29f400.h"
+
+
+VOID pWriteFlashByte(
+ IN ULONG FlashOffset,
+ IN UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This routine goes writes the flashbus using the hardware
+ specific access method.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+ Data - data to write
+
+Return Value:
+
+ The value of the flash at the given location.
+
+--*/
+{
+
+ WRITE_EPIC_REGISTER(FLASH_ACCESS_ADDR,
+ (FlashOffset << FLASH_ADDR_SHIFT) | Data
+ | FLASH_WRITE_FLAG);
+}
+
+
+UCHAR pReadFlashByte(
+ IN ULONG FlashOffset
+ )
+/*++
+
+Routine Description:
+
+ This routine goes out and reads the flashbus using the hardware
+ specific access method.
+
+Arguments:
+
+ FlashOffset - offset within the flash ROM.
+
+Return Value:
+
+ The value of the flash at the given location.
+
+--*/
+{
+ ULONG ReturnVal;
+
+
+ WRITE_EPIC_REGISTER(FLASH_ACCESS_ADDR,
+ (FlashOffset << FLASH_ADDR_SHIFT));
+
+ ReturnVal = READ_EPIC_REGISTER(FLASH_ACCESS_ADDR);
+
+ return (UCHAR)ReturnVal;
+}
diff --git a/private/ntos/nthals/hallx3/alpha/pflash.h b/private/ntos/nthals/hallx3/alpha/pflash.h
new file mode 100644
index 000000000..3704e27d7
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/pflash.h
@@ -0,0 +1,31 @@
+//
+// The AMD is a full megabyte broken into the following sectors:
+//
+// 0x00000 .. 0x03fff -- > SROM (not writable)
+// 0x04000 .. 0x05fff -- > First 8K 'nvram'
+// 0x06000 .. 0x07fff -- > Second 8K 'nvram'
+// 0x08000 .. 0x0ffff -- > DROM (not writable)
+// 0x10000 .. 0x1ffff -- > First 64K of ARC firmware
+// 0x20000 .. 0x2ffff -- > Second 64K of ARC firmware
+// 0x30000 .. 0x3ffff -- > Third 64K of ARC firmware
+// 0x40000 .. 0x4ffff -- > Fourth 64K of ARC firmware
+// 0x50000 .. 0x5ffff -- > Fifth 64K of ARC firmware
+// 0x60000 .. 0x6ffff -- > Sixth 64K of ARC firmware
+// 0x70000 .. 0x7ffff -- > Seventh 64K of ARC firmware
+
+//
+// Name the blocks
+//
+
+#include "am29f400.h"
+
+#define SROM_BASE SECTOR_1_BASE
+#define NVRAM1_BASE SECTOR_2_BASE
+#define NVRAM2_BASE SECTOR_3_BASE
+#define DROM_BASE SECTOR_4_BASE
+#define ARC_BASE SECTOR_5_BASE
+
+#define SROM_SECTOR_SIZE (SECTOR_2_BASE - SECTOR_1_BASE)
+#define NVRAM1_SECTOR_SIZE (SECTOR_3_BASE - SECTOR_2_BASE)
+#define NVRAM2_SECTOR_SIZE (SECTOR_4_BASE - SECTOR_3_BASE)
+#define DROM_SECTOR_SIZE (SECTOR_5_BASE - SECTOR_4_BASE)
diff --git a/private/ntos/nthals/hallx3/alpha/vga.c b/private/ntos/nthals/hallx3/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/hallx3/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/hallx3/drivesup.c b/private/ntos/nthals/hallx3/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/hallx3/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/hallx3/hal.rc b/private/ntos/nthals/hallx3/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/hallx3/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/hallx3/hal.src b/private/ntos/nthals/hallx3/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/hallx3/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/hallx3/makefile b/private/ntos/nthals/hallx3/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/hallx3/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/hallx3/makefile.inc b/private/ntos/nthals/hallx3/makefile.inc
new file mode 100644
index 000000000..0f5a8b41c
--- /dev/null
+++ b/private/ntos/nthals/hallx3/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halavant.lib
+ copy $** $@
diff --git a/private/ntos/nthals/hallx3/sources b/private/ntos/nthals/hallx3/sources
new file mode 100644
index 000000000..1e4040c2a
--- /dev/null
+++ b/private/ntos/nthals/hallx3/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=hallx3
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DTAGGED_NVRAM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=.;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\am29f400.c \
+ alpha\apecs.c \
+ alpha\apecserr.c \
+ alpha\apecsio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\lxsgdma.c \
+ alpha\eisasup.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mchk.c \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\flash8k.c \
+ alpha\flashdrv.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\pflash.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\lxinitnt.c \
+ alpha\lxintsup.c \
+ alpha\lxmapio.c \
+ alpha\lxsysint.c \
+ alpha\nvenv.c \
+ alpha\nvram.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halmca/drivesup.c b/private/ntos/nthals/halmca/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halmca/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halmca/hal.rc b/private/ntos/nthals/halmca/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halmca/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halmca/hal.src b/private/ntos/nthals/halmca/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halmca/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halmca/i386/halnls.h b/private/ntos/nthals/halmca/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/halmca/i386/halp.h b/private/ntos/nthals/halmca/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halmca/i386/ix8259.inc b/private/ntos/nthals/halmca/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halmca/i386/ixbeep.asm b/private/ntos/nthals/halmca/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halmca/i386/ixbusdat.c b/private/ntos/nthals/halmca/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halmca/i386/ixclock.asm b/private/ntos/nthals/halmca/i386/ixclock.asm
new file mode 100644
index 000000000..fa1155436
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixclock.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixclock.asm
diff --git a/private/ntos/nthals/halmca/i386/ixcmos.asm b/private/ntos/nthals/halmca/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halmca/i386/ixcmos.inc b/private/ntos/nthals/halmca/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halmca/i386/ixdat.c b/private/ntos/nthals/halmca/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halmca/i386/ixenvirv.c b/private/ntos/nthals/halmca/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halmca/i386/ixfirm.c b/private/ntos/nthals/halmca/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halmca/i386/ixhwsup.c b/private/ntos/nthals/halmca/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halmca/i386/ixidle.asm b/private/ntos/nthals/halmca/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halmca/i386/ixinfo.c b/private/ntos/nthals/halmca/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halmca/i386/ixipi.asm b/private/ntos/nthals/halmca/i386/ixipi.asm
new file mode 100644
index 000000000..17eea3bf1
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixipi.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixipi.asm
diff --git a/private/ntos/nthals/halmca/i386/ixisa.h b/private/ntos/nthals/halmca/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halmca/i386/ixisabus.c b/private/ntos/nthals/halmca/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halmca/i386/ixisasup.c b/private/ntos/nthals/halmca/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halmca/i386/ixkdcom.c b/private/ntos/nthals/halmca/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halmca/i386/ixkdcom.h b/private/ntos/nthals/halmca/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halmca/i386/ixmca.h b/private/ntos/nthals/halmca/i386/ixmca.h
new file mode 100644
index 000000000..e96b1064e
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixmca.h
@@ -0,0 +1,113 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ imhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ MCA specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _IXMCA_
+#define _IXMCA_
+
+#include "mca.h"
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_MCA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ DMA_EXTENDED_MODE ExtendedModeFlags;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN Dma32BitAddresses;
+} ADAPTER_OBJECT;
+
+
+#endif // _IXMCA_
diff --git a/private/ntos/nthals/halmca/i386/ixmcabus.c b/private/ntos/nthals/halmca/i386/ixmcabus.c
new file mode 100644
index 000000000..82cc981cd
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixmcabus.c
@@ -0,0 +1,117 @@
+/*++
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixmcabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+extern KSPIN_LOCK HalpSystemHardwareLock;
+
+ULONG
+HalpGetPosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG DOffset,
+ IN ULONG Length
+ )
+{
+ ULONG DataLength = 0;
+ ULONG Offset = 0;
+ ULONG Index = 0;
+ PUCHAR DataBuffer = Buffer;
+ PVOID McaRegisterBase = 0;
+ PUCHAR PosBase;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS BusAddress;
+ BOOLEAN Status;
+ ULONG AddressSpace;
+
+
+ if (DOffset != 0) {
+ // bugbug: should support this
+ return 0;
+ }
+
+ //
+ // Translate the Mca Base port for this MCA bus
+ //
+
+ BusAddress.LowPart = (ULONG) McaRegisterBase;
+ BusAddress.HighPart = 0;
+ AddressSpace = 1; // I/O space
+ Status = BusHandler->TranslateBusAddress(
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ &AddressSpace, // I/O Space
+ &BusAddress);
+
+ if (Status == FALSE || AddressSpace != 1) {
+ return 0;
+ }
+
+ McaRegisterBase = (PVOID) BusAddress.LowPart;
+
+ PosBase = (PUCHAR) &((PMCA_CONTROL) McaRegisterBase)->Pos;
+
+ Irql = KfAcquireSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Place the specified adapter into setup mode.
+ //
+
+ WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
+ (UCHAR) ( MCA_ADAPTER_SETUP_ON | SlotNumber ));
+
+ while (DataLength < Length && DataLength < 6) {
+ DataBuffer[DataLength] = READ_PORT_UCHAR( PosBase + DataLength );
+ DataLength++;
+ }
+
+ while (DataLength < Length) {
+
+ WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
+ PosBase)->SubaddressExtensionLsb, (UCHAR) Index);
+
+ WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
+ PosBase)->SubaddressExtensionMsb, (UCHAR) (Index >> 8));
+
+ DataBuffer[Index + 6] = READ_PORT_UCHAR(
+ (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData2);
+
+ DataLength++;
+
+ if (DataLength < Length) {
+ Offset = DataLength + ((Length - DataLength) / 2);
+ DataBuffer[Offset] = READ_PORT_UCHAR(
+ (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData3);
+ DataLength++;
+ Index++;
+ }
+ }
+
+ //
+ // Disable adapter setup.
+ //
+
+ WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
+ (UCHAR) ( MCA_ADAPTER_SETUP_OFF ));
+
+
+ KfReleaseSpinLock( &HalpSystemHardwareLock, Irql );
+ return DataLength;
+}
diff --git a/private/ntos/nthals/halmca/i386/ixmcasup.c b/private/ntos/nthals/halmca/i386/ixmcasup.c
new file mode 100644
index 000000000..6e5f3f105
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixmcasup.c
@@ -0,0 +1,1344 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixmcasup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Modified for MCA support - Bill Parry (o-billp) 22-Jul-1991
+
+--*/
+
+#define MCA 1
+#include "halp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalGetAdapter)
+#endif
+
+//
+// The HalpNewAdapter event is used to serialize allocations
+// of new adapter objects, additions to the HalpMCAAdapter
+// array, and some global values (MasterAdapterObject) and some
+// adapter fields modified by HalpGrowMapBuffers.
+// (AdapterObject->NumberOfMapRegisters is assumed not to be
+// growable while this even is held)
+//
+// Note: We don't really need our own an event object for this.
+//
+
+#define HalpNewAdapter HalpBusDatabaseEvent
+extern KEVENT HalpNewAdapter;
+
+
+//
+// Define save area for MCA adapter objects. Allocate 1 extra slot for
+// bus masters (MAX_DMA_CHANNEL_NUMBER is zero-based).
+//
+
+PADAPTER_OBJECT HalpMCAAdapter[MAX_MCA_DMA_CHANNEL_NUMBER + 1 + 1];
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Input the number of registers requests and output
+ the number allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for MCA systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adpater object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+
+ PAGED_CODE();
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->Dma32BitAddresses ||
+ DeviceDescriptor->InterfaceType == PCIBus)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(DeviceDescriptor->MaximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_MCA_MAP_REGISTER ?
+ MAXIMUM_MCA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master and does scatter/gather then it only
+ // needs one map register.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ channelNumber = DeviceDescriptor->DmaChannel;
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) {
+
+ adapterObject = HalpMCAAdapter[ channelNumber];
+
+ } else {
+
+ //
+ // Serialize before allocating a new adapter
+ //
+
+ KeWaitForSingleObject (
+ &HalpNewAdapter,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+
+ //
+ // Determine if a new adapter object has already been allocated.
+ // If so use it, otherwise allocate a new adapter object
+ //
+
+ if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) {
+
+ adapterObject = HalpMCAAdapter[ channelNumber];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ //
+ // bugbug- need to pass in MCA base address instead of 0.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ (PVOID) 0,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+ KeSetEvent (&HalpNewAdapter, 0, FALSE);
+ return(NULL);
+ }
+
+ if (!DeviceDescriptor->Master) {
+ HalpMCAAdapter[channelNumber] = adapterObject;
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_MCA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ DeviceDescriptor->MaximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ KeSetEvent (&HalpNewAdapter, 0, FALSE);
+
+ }
+
+ adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // set up channel number.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ //
+ // initialize MCA Extended DMA Mode flags.
+ //
+
+ *((PUCHAR) &adapterObject->ExtendedModeFlags) = 0;
+
+ //
+ // set up auto-initialize if necessary.
+ //
+
+ if ( DeviceDescriptor->AutoInitialize) {
+
+ adapterObject->ExtendedModeFlags.AutoInitialize = 1;
+
+ }
+
+ //
+ // set up PIO address if necessary.
+ //
+
+ if ( DeviceDescriptor->DmaPort) {
+
+ adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_USE_PIO;
+ adapterObject->DmaPortAddress = (USHORT) DeviceDescriptor->DmaPort;
+
+ } else {
+
+ adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_NO_PIO;
+ }
+
+ //
+ // indicate data transfer operation for DMA.
+ //
+
+ adapterObject->ExtendedModeFlags.DmaOpcode = DMA_EXT_DATA_XFER;
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_8_BIT;
+ break;
+
+ case Width16Bits:
+ adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_16_BIT;
+ break;
+
+ case Width32Bits:
+ //
+ // If it's a master, it doesn't need DmaWidth filled in
+ //
+
+ if (!DeviceDescriptor->Master) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ } // switch
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+ } // if
+
+ return(adapterObject);
+}
+
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PTRANSLATION_ENTRY translationEntry;
+ PMCA_DMA_CONTROLLER dmaControl;
+ UCHAR channelNumber;
+ KIRQL Irql;
+ KIRQL Irql2;
+ ULONG pageOffset;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how must of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous then just extend the buffer.
+ //
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+ if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed, or device is bus master, then there
+ // is no more work to do so return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // grab the spinlock for the Microchannel system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Raise to high level. On systems with ABIOS disks
+ // the ABIOS can reprogram the DMA from its interrupt. Raising to high
+ // prevents the ABIOS from running while the DMA controller is being
+ // maniulated. Note this will not work on MP systems, however there are
+ // no know MP systems with non-SCSI ABIOS disks.
+ //
+
+ Irql2 = KfRaiseIrql(HIGH_LEVEL);
+
+ //
+ // Set up the Microchannel system DMA controller
+ //
+
+ dmaControl = (PMCA_DMA_CONTROLLER)
+ &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
+ ExtendedDmaBasePort[0];
+ channelNumber = AdapterObject->ChannelNumber;
+
+ //
+ // set the mask bit
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( SET_MASK_BIT | channelNumber));
+
+ //
+ // set mode register
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_MODE | channelNumber));
+
+ //
+ // Set up for read or write, appropriately
+ //
+
+ if ( WriteToDevice) {
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) (*((PUCHAR) &AdapterObject->
+ ExtendedModeFlags)
+ | (UCHAR) DMA_MODE_READ));
+
+ } else {
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( *((PUCHAR) &AdapterObject->
+ ExtendedModeFlags)
+ | DMA_MODE_WRITE));
+ }
+
+ //
+ // if there is a DMA Programmed I/O address, set it up
+ //
+
+ if ( AdapterObject->ExtendedModeFlags.ProgrammedIo) {
+
+ //
+ // set up I/O base address
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_IO_ADDRESS | channelNumber));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) AdapterObject->DmaPortAddress);
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( AdapterObject->DmaPortAddress >> 8));
+
+ }
+
+ //
+ // set the DMA transfer count
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_TRANSFER_COUNT | channelNumber));
+
+ //
+ // adjust transfer count for 16-bit transfers as required.
+ //
+
+ if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) {
+
+ //
+ // Round up on odd byte transfers and divide by 2.
+ //
+
+ transferLength++;
+ transferLength >>= 1;
+ }
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( transferLength - 1));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( ( transferLength - 1) >> 8));
+
+ //
+ // set the DMA transfer start address
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_MEMORY_ADDRESS | channelNumber));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) logicalAddress);
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) (logicalAddress >> 8));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) (logicalAddress >> 16));
+
+ //
+ // clear the mask bit
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( CLEAR_MASK_BIT | channelNumber));
+
+ KfLowerIrql(Irql2);
+
+ //
+ // release the spinlock for the Microchannel system DMA controller
+ //
+
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adpater object buffers.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PMCA_DMA_CONTROLLER dmaControl;
+ KIRQL Irql;
+ KIRQL Irql2;
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device then stop the DMA controller be flushing
+ // the data.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // grab the spinlock for the Microchannel system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Raise to high level. On systems with ABIOS disks
+ // the ABIOS can reprogram the DMA from its interrupt. Raising to high
+ // prevents the ABIOS from running while the DMA controller is being
+ // maniulated. Note this will not work on MP systems, however there are
+ // no know MP systems with non-SCSI ABIOS disks.
+ //
+
+ Irql2 = KfRaiseIrql(HIGH_LEVEL);
+
+ //
+ // Set up the Microchannel system DMA controller
+ //
+
+ dmaControl = (PMCA_DMA_CONTROLLER)
+ &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
+ ExtendedDmaBasePort[0];
+ //
+ // clear the mask bit
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( SET_MASK_BIT | AdapterObject->ChannelNumber));
+
+ //
+ // release the spinlock for the Microchannel system DMA controller
+ //
+
+ KfLowerIrql(Irql2);
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ }
+
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear the index of used buffers.
+ //
+
+ if (translationEntry) {
+
+ translationEntry->Index = 0;
+ }
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ PMCA_DMA_CONTROLLER dmaControl;
+ UCHAR channelNumber;
+ KIRQL Irql;
+ KIRQL Irql2;
+
+ //
+ // grab the spinlock for the Microchannel system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Raise to high level. On systems with ABIOS disks
+ // the ABIOS can reprogram the DMA from its interrupt. Raising to high
+ // prevents the ABIOS from running while the DMA controller is being
+ // maniulated. Note this will not work on MP systems, however there are
+ // no know MP systems with non-SCSI ABIOS disks.
+ //
+
+ Irql2 = KfRaiseIrql(HIGH_LEVEL);
+
+ //
+ // Set up the Microchannel system DMA controller
+ //
+
+ dmaControl = (PMCA_DMA_CONTROLLER)
+ &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
+ ExtendedDmaBasePort[0];
+ channelNumber = AdapterObject->ChannelNumber;
+
+ count = 0XFFFF00;
+
+ //
+ // Loop until the high byte matches.
+ //
+
+ do {
+
+ high = count;
+
+ //
+ // read the DMA transfer count
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( READ_TRANSFER_COUNT | channelNumber));
+
+ count = READ_PORT_UCHAR( &dmaControl->DmaFunctionData);
+
+ count |= READ_PORT_UCHAR( &dmaControl->DmaFunctionData) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // adjust transfer count for 16-bit transfers as required.
+ //
+
+ if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) {
+ count <<= 1;
+ }
+
+
+ KfLowerIrql(Irql2);
+
+ //
+ // release the spinlock for the Microchannel system DMA controller
+ //
+
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ return(count);
+}
diff --git a/private/ntos/nthals/halmca/i386/ixnmi.c b/private/ntos/nthals/halmca/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/halmca/i386/ixpcibrd.c b/private/ntos/nthals/halmca/i386/ixpcibrd.c
new file mode 100644
index 000000000..02fd82821
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixpcibrd.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/halmca/i386/ixpcibus.c b/private/ntos/nthals/halmca/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/halmca/i386/ixpciint.c b/private/ntos/nthals/halmca/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/halmca/i386/ixphwsup.c b/private/ntos/nthals/halmca/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halmca/i386/ixproc.c b/private/ntos/nthals/halmca/i386/ixproc.c
new file mode 100644
index 000000000..fdb962b05
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixproc.c
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixsproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PC Compatible MicroChannel HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitOtherBuses (VOID);
+VOID HalpInitializePciBus (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ // do nothing
+ return TRUE;
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2();
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+VOID
+HalpMcaQueueDpc (
+ VOID
+ )
+{
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halmca/i386/ixprofil.asm b/private/ntos/nthals/halmca/i386/ixprofil.asm
new file mode 100644
index 000000000..c33b273ae
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixprofil.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixprofil.asm
diff --git a/private/ntos/nthals/halmca/i386/ixreboot.c b/private/ntos/nthals/halmca/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halmca/i386/ixstall.asm b/private/ntos/nthals/halmca/i386/ixstall.asm
new file mode 100644
index 000000000..115c6c9c1
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixstall.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixstall.asm
diff --git a/private/ntos/nthals/halmca/i386/ixswint.asm b/private/ntos/nthals/halmca/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixswint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixswint.asm
diff --git a/private/ntos/nthals/halmca/i386/ixsysbus.c b/private/ntos/nthals/halmca/i386/ixsysbus.c
new file mode 100644
index 000000000..b4776da76
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixsysbus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixsysbus.c"
diff --git a/private/ntos/nthals/halmca/i386/ixthunk.c b/private/ntos/nthals/halmca/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halmca/i386/ixusage.c b/private/ntos/nthals/halmca/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halmca/i386/mcirql.asm b/private/ntos/nthals/halmca/i386/mcirql.asm
new file mode 100644
index 000000000..02d355cd4
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/mcirql.asm
@@ -0,0 +1,1121 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixirql.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the 8259 PIC.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; John Vert (jvert) 27-Nov-1991
+; Moved from kernel into HAL
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ extrn _HalpApcInterrupt:near
+ extrn _HalpDispatchInterrupt:near
+ extrn _KiUnexpectedInterrupt:near
+ extrn _HalpBusType:DWORD
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+
+;
+; Initialization control words equates for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW2_SET_PRIORITY equ 0c0H
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+
+;
+; Interrupt flag bit maks for EFLAGS
+;
+
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; PICsInitializationString - Master PIC initialization command string
+;
+
+PS2PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+ align 4
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 11111111100000000000000000000000B ; irql 4
+ dd 11111111110000000000000000000000B ; irql 5
+ dd 11111111111000000000000000000000B ; irql 6
+ dd 11111111111100000000000000000000B ; irql 7
+ dd 11111111111110000000000000000000B ; irql 8
+ dd 11111111111111000000000000000000B ; irql 9
+ dd 11111111111111100000000000000000B ; irql 10
+ dd 11111111111111110000000000000000B ; irql 11
+ dd 11111111111111111000000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111110000000000000B ; irql 14
+ dd 11111111111111111111000000000000B ; irql 15
+ dd 11111111111111111111100000000000B ; irql 16
+ dd 11111111111111111111110000000000B ; irql 17
+ dd 11111111111111111111111000000000B ; irql 18
+ dd 11111111111111111111111000000000B ; irql 19
+ dd 11111111111111111111111010000000B ; irql 20
+ dd 11111111111111111111111011000000B ; irql 21
+ dd 11111111111111111111111011100000B ; irql 22
+ dd 11111111111111111111111011110000B ; irql 23
+ dd 11111111111111111111111011111000B ; irql 24
+ dd 11111111111111111111111011111000B ; irql 25
+ dd 11111111111111111111111011111010B ; irql 26
+ dd 11111111111111111111111111111010B ; irql 27
+ dd 11111111111111111111111111111011B ; irql 28
+ dd 11111111111111111111111111111011B ; irql 29
+ dd 11111111111111111111111111111011B ; irql 30
+ dd 11111111111111111111111111111011B ; irql 31
+
+ align 4
+;
+; The following tables define the addresses of software interrupt routers
+;
+
+;
+; Use this table if there is NO machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt ; irql 2
+
+;
+; Use this table if there is a machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable2
+SWInterruptHandlerTable2 label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt2ndEntry ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt2ndEntry ; irql 2
+
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,0
+
+ movzx ecx, cl ; 32bit extend NewIrql
+ mov al, PCR[PcIrql] ; get current irql
+
+if DBG
+ cmp al,cl ; old > new?
+ jbe short Kri99 ; no, we're OK
+ movzx ecx, cl
+ movzx eax, al
+ push ecx ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr PCR[PcIrql],0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL > ; never return
+Kri99:
+endif
+ cmp cl,DISPATCH_LEVEL ; software level?
+ jbe short kri10 ; Skip setting 8259 masks
+
+ mov edx, eax ; Save OldIrql
+
+ pushfd
+ cli ; disable interrupt
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+ popfd
+
+ mov eax, edx ; (al) = OldIrql
+ fstRET KfRaiseIrql
+
+align 4
+kri10:
+;
+; Note it is very important that we set the old irql AFTER we raised to
+; the new irql. Otherwise, if there is an interrupt comes in between and
+; the OldIrql is not a local variable, the caller will get wrong OldIrql.
+; The bottom line is the raising irql and returning old irql has to be
+; atomic to the caller.
+;
+ mov PCR[PcIrql], cl
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short Krid99 ; yes, go bugcheck
+endif
+
+ stdRET _KeRaiseIrqlToDpcLevel
+
+if DBG
+cPublicFpo 0,1
+Krid99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+ stdRET _KeRaiseIrqlToDpcLevel
+endif
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+cPublicFpo 0, 0
+ pushfd
+ cli ; disable interrupt
+ mov eax, KiI8259MaskTable[SYNCH_LEVEL*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+ mov al, PCR[PcIrql] ; (al) = Old irql
+ mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql
+
+ popfd
+
+if DBG
+ cmp al, SYNCH_LEVEL
+ ja short Kris99
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+ stdRET _KeRaiseIrqlToSynchLevel
+
+if DBG
+cPublicFpo 0,1
+Kris99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+ stdRET _KeRaiseIrqlToSynchLevel
+endif
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+ page ,132
+ subttl "Lower irql"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; On a UP system, HalEndSystenInterrupt is treated as a
+; LowerIrql.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+cPublicFastCall KfLowerIrql ,1
+cPublicFpo 0,1
+
+ pushfd ; save caller's eflags
+ movzx ecx, cl ; zero extend irql
+
+if DBG
+ cmp cl,PCR[PcIrql]
+ ja short Kli99
+endif
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ cli
+ jbe short kli02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+kli02:
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja Kli10 ; yes, go simulate interrupt
+
+kil03: popfd ; restore flags, including ints
+cPublicFpo 1,0
+ fstRET KfLowerIrql
+
+if DBG
+cPublicFpo 1,3
+Kli99:
+ push ecx ; new irql for debugging
+ push PCR[PcIrql] ; old irql for debugging
+ mov byte ptr PCR[PcIrql],HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+endif
+
+;
+; When we come to Kli10, (eax) = soft interrupt index
+;
+; Note Do NOT:
+;
+; popfd
+; jmp SWInterruptHandlerTable[eax*4]
+;
+; We want to make sure interrupts are off after entering SWInterrupt
+; Handler.
+;
+
+align 4
+cPublicFpo 1,1
+Kli10: call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ popfd ; restore flags, including ints
+cPublicFpo 1,0
+ fstRET KfLowerIrql ; cRetURN
+
+fstENDP KfLowerIrql
+
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfAcquireSpinLock,1
+cPublicFpo 0,0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifndef NT_UP
+asl10: ACQUIRE_SPINLOCK ecx,<short asl20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short asl99 ; yes, go bugcheck
+endif
+ fstRET KfAcquireSpinLock
+
+ifndef NT_UP
+asl20: SPIN_ON_SPINLOCK ecx,<short asl10>
+endif
+
+if DBG
+cPublicFpo 2, 1
+asl99:
+ push ecx ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfAcquireSpinLock
+fstENDP KfAcquireSpinLock
+
+
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock,
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired.
+; Any spin should occur at OldIrql; however, since this is a UP hal
+; we don't have the code for it)
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to SYNCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+ push ecx
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; Raise to SYNCH_LEVEL
+ pop ecx
+
+ifndef NT_UP
+asls10: ACQUIRE_SPINLOCK ecx,<short asls20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, SYNCH_LEVEL ; old > new?
+ ja short asls99 ; yes, go bugcheck
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+ifndef NT_UP
+asls20: SPIN_ON_SPINLOCK ecx,<short asls10>
+endif
+
+if DBG
+cPublicFpo 2, 1
+asls99:
+ push ecx ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we use the SpinLock.
+;
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,1
+ pushfd
+
+ifndef NT_UP
+ RELEASE_SPINLOCK ecx ; release it
+endif
+ movzx ecx, dl ; (ecx) = NewIrql
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ cli
+ jbe short rsl02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+rsl02:
+ mov PCR[PcIrql], cl
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja short rsl20 ; yes, go simulate interrupt
+
+ popfd
+ fstRet KfReleaseSpinLock ; all done
+
+align 4
+rsl20: call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ popfd ; restore flags, including ints
+cPublicFpo 2,0
+ fstRET KfReleaseSpinLock ; all done
+
+fstENDP KfReleaseSpinLock
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ push ecx ; Save FastMutex
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; Raise to APC_LEVEL
+ pop ecx ; (ecx) = FastMutex
+
+cPublicFpo 0,0
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,2
+ push ecx ; Save FastMutex
+ push eax ; Save OldIrql
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax
+ pop ecx
+
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al ; (al) = OldIrql
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,1
+
+;
+; Try to acquire - but needs to support 386s.
+; *** Warning: This code is NOT MP safe ***
+; But, we know that this hal really only runs on UP machines
+;
+
+ push ecx ; Save FAST_MUTEX
+
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ pop edx ; (edx) = FAST_MUTEX
+
+cPublicFpo 0,0
+
+ cli
+ cmp dword ptr [edx].FmCount, 1 ; Busy?
+ jne short tam20 ; Yes, abort
+
+ mov dword ptr [edx].FmCount, 0 ; acquire count
+ sti
+
+ mov byte ptr [edx].FmOldIrql, al
+ mov eax, 1 ; return TRUE
+ fstRet ExTryToAcquireFastMutex
+
+tam20: sti
+ mov ecx, eax ; (cl) = OldIrql
+ fstCall KfLowerIrql ; resture OldIrql
+ xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz @KfLowerIrql@4 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+ jmp @KfLowerIrql@4
+
+fstENDP ExReleaseFastMutex
+
+
+
+
+;++
+;
+; VOID
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+12 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HeiNewIrql equ [esp + 4]
+
+cPublicProc _HalEndSystemInterrupt ,2
+cPublicFpo 2, 0
+
+ movzx ecx, byte ptr HeiNewIrql; get new irql value
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ jbe short Hei02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+Hei02:
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja short Hei10 ; yes, go simulate interrupt
+
+ stdRET _HalEndSystemInterrupt ; cRetURN
+
+; When we come to Hei10, (eax) = soft interrupt index
+
+Hei10: add esp, 12 ; esp = trap frame
+ jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+
+stdENDP _HalEndSystemInterrupt
+
+;++
+;
+; VOID
+; HalpEndSoftwareInterrupt
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL from software interrupt
+; level to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HesNewIrql equ [esp + 4]
+
+cPublicProc _HalpEndSoftwareInterrupt ,1
+cPublicFpo 1, 0
+
+ movzx ecx, byte ptr HesNewIrql; get new irql value
+
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ jbe short Hes02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+Hes02:
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja short Hes10 ; yes, go simulate interrupt
+
+ stdRET _HalpEndSoftwareInterrupt ; cRetURN
+
+; When we come to Hes10, (eax) = soft interrupt index
+
+Hes10: add esp, 8
+ jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT
+
+ ; to the appropriate handler
+stdENDP _HalpEndSoftwareInterrupt
+
+
+ page ,132
+ subttl "Get current irql"
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+cPublicFpo 0, 0
+ movzx eax, word ptr PCR[PcIrql] ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+cPublicFpo 0, 0
+
+ ;
+ ; Raising to HIGH_LEVEL disables interrupts for the microchannel HAL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine sends the 8259 PIC initialization commands and
+; masks all the interrupts on 8259s.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+
+ push esi ; save caller's esi
+ cli ; disable interrupt
+ lea esi, PICsInitializationString
+
+ test _HalpBusType, MACHINE_TYPE_MCA
+ jz short Hip00
+
+; Is this a PS2 or PS700 series machine?
+
+ in al, 07fh ; get PD700 ID byte
+ and al, 0F0h ; Mask high nibble
+ cmp al, 0A0h ; Is the ID Ax?
+ jz short Hip00
+ cmp al, 090h ; Or an 9X?
+ jz short Hip00 ; Yes, it's a 700
+
+ lea esi, PS2PICsInitializationString
+Hip00:
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ mov al, 0FFH ; mask all 8259 irqs
+ out dx,al ; write mask to PIC
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+ pop esi ; restore caller's esi
+ sti ; enable interrupt
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halmca/i386/mcsysint.asm b/private/ntos/nthals/halmca/i386/mcsysint.asm
new file mode 100644
index 000000000..f00b5c6e7
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/mcsysint.asm
@@ -0,0 +1,385 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixsysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts.
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include callconv.inc
+ .list
+
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeBugCheck,1,IMPORT
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; Macros to Read/Write/Reset CMOS to initialize RTC
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+align dword
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irq 0
+ dd offset FLAT:HalpDismissNormal ; irq 1
+ dd offset FLAT:HalpDismissNormal ; irq 2
+ dd offset FLAT:HalpDismissNormal ; irq 3
+ dd offset FLAT:HalpDismissNormal ; irq 4
+ dd offset FLAT:HalpDismissNormal ; irq 5
+ dd offset FLAT:HalpDismissNormal ; irq 6
+ dd offset FLAT:HalpDismissIrq07 ; irq 7
+ dd offset FLAT:HalpDismissNormal ; irq 8
+ dd offset FLAT:HalpDismissNormal ; irq 9
+ dd offset FLAT:HalpDismissNormal ; irq A
+ dd offset FLAT:HalpDismissNormal ; irq B
+ dd offset FLAT:HalpDismissNormal ; irq C
+ dd offset FLAT:HalpDismissNormal ; irq D
+ dd offset FLAT:HalpDismissNormal ; irq E
+ dd offset FLAT:HalpDismissIrq0f ; irq F
+ dd offset FLAT:HalpDismissNormal ; irq 10
+ dd offset FLAT:HalpDismissNormal ; irq 11
+ dd offset FLAT:HalpDismissNormal ; irq 12
+ dd offset FLAT:HalpDismissNormal ; irq 13
+ dd offset FLAT:HalpDismissNormal ; irq 14
+ dd offset FLAT:HalpDismissNormal ; irq 15
+ dd offset FLAT:HalpDismissNormal ; irq 16
+ dd offset FLAT:HalpDismissNormal ; irq 17
+ dd offset FLAT:HalpDismissNormal ; irq 18
+ dd offset FLAT:HalpDismissNormal ; irq 19
+ dd offset FLAT:HalpDismissNormal ; irq 1A
+ dd offset FLAT:HalpDismissNormal ; irq 1B
+ dd offset FLAT:HalpDismissNormal ; irq 1C
+ dd offset FLAT:HalpDismissNormal ; irq 1D
+ dd offset FLAT:HalpDismissNormal ; irq 1E
+ dd offset FLAT:HalpDismissNormal ; irq 1F
+ dd offset FLAT:HalpDismissNormal ; irq 20
+ dd offset FLAT:HalpDismissNormal ; irq 21
+ dd offset FLAT:HalpDismissNormal ; irq 22
+ dd offset FLAT:HalpDismissNormal ; irq 23
+
+_DATA ENDS
+
+_TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+; On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
+; This is fine since the irql is being raise to mask it off.
+; HalEndSystemInterrupt is simply a LowerIrql request.
+;
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+cPublicFpo 3, 0
+ movzx ebx,HbsiVector ; (ebx) = System Vector
+ sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ #
+if DBG
+ cmp ebx, 23h
+ jbe hbsi00
+ int 3
+hbsi00:
+
+endif
+ jmp HalpSpecialDismissTable[ebx*4]
+
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ mov eax,0 ; return FALSE
+; sti
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+; sti
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissNormal:
+;
+; Store OldIrql
+;
+ mov eax, HbsiOldIrql
+ movzx ecx, word ptr PCR[PcIrql]
+ mov byte ptr [eax], cl
+
+;
+; Raise IRQL to requested level
+;
+ movzx eax, HbsiIrql ; (eax) = irql
+ ; (ebx) = IRQ #
+
+ mov PCR[PcIrql], al ; set new Irql
+
+
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, PCR[PcIDR] ; mask disabled irqs
+ SET_8259_MASK ; send mask to 8259s
+
+;
+; Dismiss interrupt. Current interrupt is already masked off.
+;
+ mov eax, ebx ; (eax) = IRQ #
+ cmp eax, 8 ; EOI to master or slave?
+
+ jae short Hbsi100 ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short Hbsi200 ; IO delay - This is not enough for 486
+
+Hbsi100:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+Hbsi200:
+ PIC1DELAY ; *MUST* wait for 8259 before sti
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt ,2
+cPublicFpo 2, 0
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or PCR[PcIDR], edx
+ xor eax, eax
+
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt ,3
+cPublicFpo 3, 0
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc hes_error
+ cmp ecx, CLOCK2_LEVEL
+ jnc hes_error
+
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ cli
+ and PCR[PcIDR], eax
+
+;
+; Get the PIC masks for the current Irql
+;
+ movzx eax, byte ptr PCR[PcIrql]
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+hes_error:
+if DBG
+ int 3
+endif
+ xor eax, eax ; FALSE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT$01 ENDS
+
+ END
diff --git a/private/ntos/nthals/halmca/i386/pcip.h b/private/ntos/nthals/halmca/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/halmca/i386/xxbiosa.asm b/private/ntos/nthals/halmca/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halmca/i386/xxbiosc.c b/private/ntos/nthals/halmca/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halmca/i386/xxdisp.c b/private/ntos/nthals/halmca/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halmca/i386/xxflshbf.c b/private/ntos/nthals/halmca/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halmca/i386/xxhal.c b/private/ntos/nthals/halmca/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxhal.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxhal.c"
diff --git a/private/ntos/nthals/halmca/i386/xxioacc.asm b/private/ntos/nthals/halmca/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halmca/i386/xxkdsup.c b/private/ntos/nthals/halmca/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halmca/i386/xxmemory.c b/private/ntos/nthals/halmca/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halmca/i386/xxstubs.c b/private/ntos/nthals/halmca/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halmca/i386/xxtime.c b/private/ntos/nthals/halmca/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halmca/makefile b/private/ntos/nthals/halmca/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmca/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halmca/makefile.inc b/private/ntos/nthals/halmca/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halmca/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halmca/sources b/private/ntos/nthals/halmca/sources
new file mode 100644
index 000000000..0760716a7
--- /dev/null
+++ b/private/ntos/nthals/halmca/sources
@@ -0,0 +1,100 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halmca
+TARGETPATH=\nt\public\sdk\lib
+
+HALTYPE=MCA
+
+!IF $(386)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixdat.c \
+ i386\ixinfo.c \
+ i386\ixisabus.c \
+ i386\ixpcibus.c \
+ i386\ixpciint.c \
+ i386\ixpcibrd.c \
+ i386\ixsysbus.c \
+ i386\ixclock.asm \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixipi.asm \
+ i386\mcirql.asm \
+ i386\ixkdcom.c \
+ i386\ixmcabus.c \
+ i386\ixmcasup.c \
+ i386\ixnmi.c \
+ i386\ixphwsup.c \
+ i386\ixprofil.asm \
+ i386\ixproc.c \
+ i386\ixreboot.c \
+ i386\ixstall.asm \
+ i386\ixswint.asm \
+ i386\mcsysint.asm \
+ i386\ixthunk.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxhal.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halmca.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halmikas/alpha/addrsup.c b/private/ntos/nthals/halmikas/alpha/addrsup.c
new file mode 100644
index 000000000..adc788329
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/addrsup.c
@@ -0,0 +1,576 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Mikasa system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston (Digital) 29-Apr-1994
+ Adapted this file for Mikasa
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "mikasa.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call HalCreateQva to
+ build a Quasi Virtual Address and return that to the caller. We then
+ set AddressSpace to a 1, so that the caller will not call MmMapIoSpace.
+ The Caller will use the low 32 bits of the physical address we return
+ as the VA. (Which we built a QVA in).
+
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The buses available on Mikasa are EISA and PCI.
+ // We support any translations for ISA devices as well,
+ // since they can plug into EISA slots just fine.
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system; return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case Eisa:
+
+ //
+ // Eisa is the same as PCI, with respect to kernel mode
+ // sparse and dense space memory support, i.e., its a full 32 bit space,
+ // supports dense memory access.
+ //
+
+ case PCIBus: {
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI/EISA address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI/EISA kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI/EISA memory space
+ //
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus, Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will explicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG)HalCreateQva(*TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Eisa:
+
+ //
+ // Eisa is the same as ISA, with respect to kernel mode
+ // sparse I/O space support, i.e., it is a 16 bit sparse
+ // space.
+ //
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will explicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG)HalCreateQva(*TranslatedAddress,va);
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ } // case UserBusMemory
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ } // case UserBusIo
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ // Note that ISA and EISA buses can also request this space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = APECS_PCI_DENSE_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ } // case UserPciDenseMemory
+
+ default: {
+
+ //
+ // Unsupported address space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ } // default
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ if ((PA.QuadPart >= APECS_COMANCHE_BASE_PHYSICAL)
+ &&(PA.QuadPart < APECS_PCI_DENSE_BASE_PHYSICAL)) {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+ } else {
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, so return the VA as the QVA
+ //
+
+ return(VA);
+}
+
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+ //
+ // For Mikasa we have support three bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support PCI Dense space: check to see if it's really
+ // a QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+ break;
+
+ default:
+
+ return NULL;
+ }
+}
diff --git a/private/ntos/nthals/halmikas/alpha/adjust.c b/private/ntos/nthals/halmikas/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/allstart.c b/private/ntos/nthals/halmikas/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/alphaio.s b/private/ntos/nthals/halmikas/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/apecs.c b/private/ntos/nthals/halmikas/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/apecserr.c b/private/ntos/nthals/halmikas/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/apecsio.s b/private/ntos/nthals/halmikas/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/bios.c b/private/ntos/nthals/halmikas/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/busdata.c b/private/ntos/nthals/halmikas/alpha/busdata.c
new file mode 100644
index 000000000..af95247cd
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/busdata.c
@@ -0,0 +1,138 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halmikas/alpha/cache.c b/private/ntos/nthals/halmikas/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/chipset.h b/private/ntos/nthals/halmikas/alpha/chipset.h
new file mode 100644
index 000000000..0a72ef8cb
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/chipset.h
@@ -0,0 +1 @@
+#include "apecs.h"
diff --git a/private/ntos/nthals/halmikas/alpha/cmos8k.c b/private/ntos/nthals/halmikas/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ebsgdma.c b/private/ntos/nthals/halmikas/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/eisasup.c b/private/ntos/nthals/halmikas/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/environ.c b/private/ntos/nthals/halmikas/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ev4cache.c b/private/ntos/nthals/halmikas/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ev4int.c b/private/ntos/nthals/halmikas/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ev4ints.s b/private/ntos/nthals/halmikas/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ev4mchk.c b/private/ntos/nthals/halmikas/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ev4mem.s b/private/ntos/nthals/halmikas/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ev4prof.c b/private/ntos/nthals/halmikas/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/fwreturn.c b/private/ntos/nthals/halmikas/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/haldebug.c b/private/ntos/nthals/halmikas/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/halpal.s b/private/ntos/nthals/halmikas/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/idle.s b/private/ntos/nthals/halmikas/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/info.c b/private/ntos/nthals/halmikas/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/inithal.c b/private/ntos/nthals/halmikas/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/intsup.s b/private/ntos/nthals/halmikas/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halmikas/alpha/ioproc.c b/private/ntos/nthals/halmikas/alpha/ioproc.c
new file mode 100644
index 000000000..d4bd5b0b2
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/ioproc.c
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halmikas/alpha/iousage.c b/private/ntos/nthals/halmikas/alpha/iousage.c
new file mode 100644
index 000000000..ba57097d8
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/iousage.c
@@ -0,0 +1,648 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/halmikas/alpha/iousage.h b/private/ntos/nthals/halmikas/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/halmikas/alpha/machdep.h b/private/ntos/nthals/halmikas/alpha/machdep.h
new file mode 100644
index 000000000..51b1c8dbe
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Mikasa platform-specific definitions.
+//
+
+#include "mikasa.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halmikas/alpha/memory.c b/private/ntos/nthals/halmikas/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/mikasa.h b/private/ntos/nthals/halmikas/alpha/mikasa.h
new file mode 100644
index 000000000..76526030b
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/mikasa.h
@@ -0,0 +1,722 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mikasa.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Mikasa modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+#ifndef _MIKASA_
+#define _MIKASA_
+
+#include "alpharef.h"
+#include "apecs.h"
+#include "isaaddr.h"
+
+#define NUMBER_MIKASA_EISA_SLOTS 7
+#define NUMBER_MIKASA_PCI_SLOTS 3
+#define NUMBER_MIKASA_COMBO_SLOTS 1
+
+#define NUMBER_NORITAKE_EISA_SLOTS 2
+#define NUMBER_NORITAKE_PCI_SLOTS 7
+
+// Highest local PCI virtual slot number is 13 == IDSEL PCI_AD[24]
+
+#define PCI_MAX_LOCAL_DEVICE 13
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+#if !defined (AXP_FIRMWARE)
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV4 processor.
+//
+
+typedef struct _MIKASA_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} MIKASA_PCR, *PMIKASA_PCR;
+#endif
+
+//
+// Define the Mikasa server management data structure.
+//
+
+typedef union _MIKASA_SRV{
+ struct {
+ UCHAR FlashRomEnable : 1; // rw
+ UCHAR DcPowerDisable : 1; // rw
+ UCHAR HaltIncoming : 1; // ro
+ UCHAR TempFail : 1; // ro
+ UCHAR DcOk1 : 1; // ro
+ UCHAR DcOk2 : 1; // ro
+ UCHAR Fan1Fault : 1; // ro
+ UCHAR Fan2Fault : 1; // ro
+ };
+ UCHAR All;
+} MIKASA_SRV, *PMIKASA_SRV;
+
+//
+// Define the Mikasa interrupt mask register. This is how we enable
+// and disable individual PCI interrupts. Actually, it's here more
+// for reference, since the interrupt enable/disable is done with a
+// computational algorithm.
+//
+
+typedef union _MIKASA_IMR{
+ struct {
+ ULONG Slot0IntA : 1;
+ ULONG Slot0IntB : 1;
+ ULONG Slot0IntC : 1;
+ ULONG Slot0IntD : 1;
+ ULONG Slot1IntA : 1;
+ ULONG Slot1IntB : 1;
+ ULONG Slot1IntC : 1;
+ ULONG Slot1IntD : 1;
+ ULONG Slot2IntA : 1;
+ ULONG Slot2IntB : 1;
+ ULONG Slot2IntC : 1;
+ ULONG Slot2IntD : 1;
+ ULONG Ncr810Scsi : 1;
+ ULONG PwrInt : 1;
+ ULONG TempWarn : 1;
+ ULONG Reserved : 17;
+ };
+ ULONG All;
+} MIKASA_IMR, *PMIKASA_IMR;
+
+//
+// Define the Noritake server management data structure.
+//
+
+typedef union _NORITAKE_SRV{
+ struct {
+ UCHAR FlashRomEnable : 1; // rw
+ UCHAR DcPowerDisable : 1; // rw
+ UCHAR Reserved1: 2;
+ UCHAR HaltIncoming : 1; // ro
+ UCHAR FlashReady: 1; // ro
+ UCHAR Reserved2: 1;
+ UCHAR EmbeddedVGAStatus: 1; // rw
+ };
+ UCHAR All;
+} NORITAKE_SRV, *PNORITAKE_SRV;
+
+//
+// Define the Noritake interrupt mask registers. This is how we enable
+// and disable individual PCI interrupts. Actually, it's here more
+// for reference, since the interrupt enable/disable is done with a
+// computational algorithm.
+//
+
+//
+// Note: Slots 0 through 2 are on PCI bus 0, and slots 3 through 6 are
+// on PCI bus 1.
+//
+
+typedef union _NORITAKE_IMR1{
+ struct {
+ ULONG SumIr2And3 : 1;
+ ULONG QLogic: 1;
+ ULONG Slot0IntA : 1;
+ ULONG Slot0IntB : 1;
+ ULONG Slot1IntA : 1;
+ ULONG Slot1IntB : 1;
+ ULONG Slot2IntA : 1;
+ ULONG Slot2IntB : 1;
+ ULONG Slot3IntA : 1;
+ ULONG Slot3IntB : 1;
+ ULONG Slot4IntA : 1;
+ ULONG Slot4IntB : 1;
+ ULONG Slot5IntA : 1;
+ ULONG Slot5IntB : 1;
+ ULONG Slot6IntA : 1;
+ ULONG Slot6IntB : 1;
+ ULONG Reserved : 16;
+ };
+ ULONG ALL;
+} NORITAKE_IMR1, *PNORITAKE_IMR1;
+
+typedef union _NORITAKE_IMR2{
+ struct {
+ ULONG SumUnmaskedIr2 : 1;
+ ULONG SecondaryPCIBusInt : 1;
+ ULONG Slot0IntC : 1;
+ ULONG Slot0IntD : 1;
+ ULONG Slot1IntC : 1;
+ ULONG Slot1IntD : 1;
+ ULONG Slot2IntC : 1;
+ ULONG Slot2IntD : 1;
+ ULONG Slot3IntC : 1;
+ ULONG Slot3IntD : 1;
+ ULONG Slot4IntC : 1;
+ ULONG Slot4IntD : 1;
+ ULONG Slot5IntC : 1;
+ ULONG Slot5IntD : 1;
+ ULONG Slot6IntC : 1;
+ ULONG Slot6IntD : 1;
+ ULONG Reserved : 16;
+ };
+ ULONG ALL;
+} NORITAKE_IMR2, *PNORITAKE_IMR2;
+
+typedef union _NORITAKE_IMR3{
+ struct {
+ ULONG Reserved1 : 2;
+ ULONG Power2Int : 1;
+ ULONG Power1Int : 1;
+ ULONG TempFail : 1;
+ ULONG TempWarn : 1;
+ ULONG Fan2Fail : 1;
+ ULONG Fan1Fail : 1;
+ ULONG Reserved2 : 24;
+ };
+ ULONG ALL;
+} NORITAKE_IMR3, *PNORITAKE_IMR3;
+
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#define HAL_PCR ( (PMIKASA_PCR)(&(PCR->HalReserved)) )
+
+#define PCI_VECTOR PRIMARY0_VECTOR // from alpharef.h
+#define PCI_MAX_INTERRUPT_VECTOR MAXIMUM_PCI_VECTOR // from alpharef.h
+
+#define PCI_SPARSE_IO_BASE_QVA ((ULONG)(HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL)))
+
+//
+// The combined Vendor ID, Device ID for the PCEB of the PCI/EISA bridge
+// chip set.
+//
+#define INTEL_PCI_EISA_BRIDGE_ID 0x04828086
+
+//
+// PCI-EISA Bridge chip configuration space base is at physical address
+// 0x1e0000000. The equivalent QVA is:
+// (0x1e0000000 >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+// N.B.: The PCI configuration space address is what we're really referring
+// to, here.
+//
+
+#define PCI_CONFIGURATION_BASE_QVA 0xaf000000
+
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device
+
+#define PCI_EISA_BRIDGE_HEADER_OFFSET (0x00070000 >> IO_BIT_SHIFT) // AD[18]
+
+//
+// PCI-EISA Bridge Non-Configuration control register offsets. These should
+// be simply ored with PCI_SPARSE_IO_BASE_QVA; they match what's in the
+// Intel handbook for the 82374EB (ESC).
+//
+#define ESC_EDGE_LEVEL_CONTROL_1 0x4d0
+#define ESC_EDGE_LEVEL_CONTROL_2 0x4d1
+#define ESC_CMOS_ISA_PORT 0x800
+
+//
+// BIOS timer address port. This value is stuffed into PCEB configuration
+// space at PCEB/ESC cofiguration.
+//
+#define BIOS_TIMER_PORT 0x78
+
+//
+// Mikasa-unique registers, accessed via PCI_SPARSE_IO_BASE_QVA, via the
+// same protocol as above. Locations of these are intermixed with
+// ESC-specific and ordinary ISA registers in this space. N.B.: the
+// term "port" is used for compatibility with PC industry terminology.
+// We know Alphas don't have I/O instructions, nor ports, as such.
+//
+#define COMBO_CHIP_CONFIG_INDEX_PORT 0x398
+#define COMBO_CHIP_CONFIG_DATA_PORT 0x399
+
+//
+// Define I2C constants
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x530
+#define I2C_INTERFACE_CSR_PORT 0x531
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+//
+// This is the same for both Noritake and Mikasa
+//
+
+#define SERVER_MANAGEMENT_REGISTER 0x532
+
+//
+// Noritake interrupt and interrupt mask register offsets.
+//
+
+#define PCI_INTERRUPT_BASE_ADDRESS 0x540
+#define PCI_INTERRUPT_REGISTER_1 0x542
+#define PCI_INTERRUPT_REGISTER_2 0x544
+#define PCI_INTERRUPT_REGISTER_3 0x546
+#define PCI_INTERRUPT_MASK_REGISTER_1 0x54A
+#define PCI_INTERRUPT_MASK_REGISTER_2 0x54C
+#define PCI_INTERRUPT_MASK_REGISTER_3 0x54E
+
+//
+// Noritake PCI vector offsets. Interrupt vectors that originate from register
+// 1 start at 0x11 for bit position 0. So, when servicing an interrupt from
+// register 1, you must add 0x11 to the bit position to get the interrupt
+// vector. Likewise, if you have an interrupt vector, and you would like to
+// determine which interrupt register it resides in, you can use the vector
+// offsets to determine this. All vectors in interrupt register 1 are between
+// 0x11 and 0x20. All vectors in interrupt register 2 are between 0x21 and
+// 0x30. All vectors in interrupt register 3 are between 0x31 and 0x38.
+// Subtracting the vector offset for a register from the interrupt vector will
+// give you the bit position of the vector. For example, Vector 0x14
+// corresponds to bit 3 of interrupt register 1, Vector 0x27 corresponds to bit
+// 6 of interrupt register 2, and so on.
+//
+
+#define REGISTER_1_VECTOR_OFFSET 0x11
+#define REGISTER_2_VECTOR_OFFSET 0x21
+#define REGISTER_3_VECTOR_OFFSET 0x31
+
+
+//
+// Mikasa interrupt and interrupt mask register offsets.
+//
+
+#define PCI_INTERRUPT_REGISTER 0x534
+#define PCI_INTERRUPT_MASK_REGISTER 0x536
+
+//
+// Define the index and data ports for the NS Super IO (87312) chip.
+//
+
+#define SUPERIO_INDEX_PORT 0x398
+#define SUPERIO_DATA_PORT 0x399
+#define SUPERIO_PORT_LENGTH 0x2
+
+//
+// PCI Sparse I/O space offsets for unique functions on the ESC. They are
+// used as the offsets above.
+//
+
+#define ESC_CONFIG_ADDRESS 0x22
+#define ESC_CONFIG_DATA 0x23
+
+//
+// ESC configuration register index addresses. The protocol is:
+// write the configuration register address (one of the following)
+// into ESC_CONTROL_INDEX, then write the data into ESC_CONTROL_DATA.
+//
+#define ESC_INDEX_ESC_ID 0x02 // write 0xf to enable
+#define ESC_INDEX_REVISION_ID 0x08 // ro
+#define ESC_INDEX_MODE_SELECT 0x40 // rw
+#define ESC_INDEX_BIOS_CHIP_SELECT_A 0x42 // rw
+#define ESC_INDEX_BIOS_CHIP_SELECT_B 0x43 // rw
+#define ESC_INDEX_BCLK_CLOCK_DIVISOR 0x4d // rw
+#define ESC_INDEX_PERIPHERAL_CHIP_SELECT_A 0x4e // rw
+#define ESC_INDEX_PERIPHERAL_CHIP_SELECT_B 0x4f // rw
+#define ESC_INDEX_EISA_ID_BYTE_1 0x50 // rw
+#define ESC_INDEX_EISA_ID_BYTE_2 0x51 // rw
+#define ESC_INDEX_EISA_ID_BYTE_3 0x52 // rw
+#define ESC_INDEX_EISA_ID_BYTE_4 0x53 // rw
+#define ESC_INDEX_SG_RELOCATE_BASE 0x57 // rw
+#define ESC_INDEX_PIRQ0_ROUTE_CONTROL 0x60 // rw
+#define ESC_INDEX_PIRQ1_ROUTE_CONTROL 0x61 // rw
+#define ESC_INDEX_PIRQ2_ROUTE_CONTROL 0x62 // rw
+#define ESC_INDEX_PIRQ3_ROUTE_CONTROL 0x63 // rw
+#define ESC_INDEX_GPCS0_BASE_LOW 0x64 // rw
+#define ESC_INDEX_GPCS0_BASE_HIGH 0x65 // rw
+#define ESC_INDEX_GPCS0_MASK 0x66 // rw
+#define ESC_INDEX_GPCS1_BASE_LOW 0x68 // rw
+#define ESC_INDEX_GPCS1_BASE_HIGH 0x69 // rw
+#define ESC_INDEX_GPCS1_MASK 0x6a // rw
+#define ESC_INDEX_GPCS2_BASE_LOW 0x6c // rw
+#define ESC_INDEX_GPCS2_BASE_HIGH 0x6d // rw
+#define ESC_INDEX_GPCS2_MASK 0x6e // rw
+#define ESC_INDEX_GP_XBUS_CONTROL 0x6f // rw
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+typedef union _ESC_MODESEL{
+ struct {
+ UCHAR EisaMasterSupport: 2;
+ UCHAR Reserved1: 1;
+ UCHAR SystemErrorEnable : 1;
+ UCHAR EscSelect : 1;
+ UCHAR CramPageEnable : 1;
+ UCHAR MreqPirqEnable : 1;
+ UCHAR Reserved2: 2;
+ };
+ UCHAR All;
+}ESC_MODESEL, *PESC_MODESEL;
+
+#define MS_4_EISA_MASTERS 0x00
+#define MS_6_EISA_MASTERS 0x01
+#define MS_7_EISA_MASTERS 0x02
+#define MS_8_EISA_MASTERS 0x03
+#define MS_RESERVED_MASK 0x84
+
+#define BIOSCSA_RESERVED_MASK 0xc0
+#define BIOSCSB_RESERVED_MASK 0xf0
+
+#define GPXBC_RESERVED_MASK 0xf8
+
+typedef union _ESC_CLKDIV{
+ struct {
+ UCHAR ClockDivisor: 3;
+ UCHAR Reserved1: 1;
+ UCHAR MouseInterruptEnable : 1;
+ UCHAR CoprocessorError : 1;
+ UCHAR Reserved2: 2;
+ };
+ UCHAR All;
+}ESC_CLKDIV, *PESC_CLKDIV;
+
+#define CLKDIV_33MHZ_EISA 0x00
+#define CLKDIV_25MHZ_EISA 0x01
+#define CLKDIV_RESERVED_MASK 0xc8
+
+typedef union _ESC_PCSA{
+ struct {
+ UCHAR RtcDecode: 1;
+ UCHAR KeyboardControllerDecode: 1;
+ UCHAR FloppyDiskSecondaryDecode : 1;
+ UCHAR FloppyDiskPrimaryDecode : 1;
+ UCHAR IdeDecode : 1;
+ UCHAR FloppyIdeSpaceSecondary : 1;
+ UCHAR Reserved : 2;
+ };
+ UCHAR All;
+}ESC_PCSA, *PESC_PCSA;
+
+#define PCSA_RESERVED_MASK 0xc0
+
+typedef union _ESC_PCSB{
+ struct {
+ UCHAR SerialPortADecode: 2;
+ UCHAR SerialPortBDecode: 2;
+ UCHAR ParallelPortDecode : 2;
+ UCHAR Port92Decode : 1;
+ UCHAR CramDecode : 1;
+ };
+ UCHAR All;
+}ESC_PCSB, *PESC_PCSB;
+
+#define PCSB_DECODE_DISABLE 0x3
+
+typedef union _ESC_PIRQ{
+ struct {
+ UCHAR IrqxRoutingBits: 7;
+ UCHAR RoutePciInterrupts: 1;
+ };
+ UCHAR All;
+}ESC_PIRQ, *PESC_PIRQ;
+
+#define PIRQ_DISABLE_ROUTING 0x01
+#define PIRQ_ENABLE_ROUTING 0x00
+
+typedef union _ESC_GPXBC{
+ struct {
+ UCHAR EnableGpcs0: 1;
+ UCHAR EnableGpcs1: 1;
+ UCHAR EnableGpcs2: 1;
+ UCHAR Reserved: 5;
+ };
+ UCHAR All;
+}ESC_GPXBC, *PESC_GPXBC;
+
+#endif // !_LANGUAGE_ASSEMBLY
+
+//
+// PCI-EISA Bridge Configuration register offsets. These should be
+// simply ored with PCI_CONFIGURATION_BASE_QVA; they match what's
+// in the Intel handbook for the 82375EB (PCEB).
+//
+#define PCI_VENDOR_ID 0x00 // ro
+#define PCI_DEVICE_ID 0x02 // ro
+#define PCI_COMMAND 0x04 // rw
+#define PCI_DEVICE_STATUS 0x06 // ro, rw clear
+#define PCI_REVISION 0x08 // ro
+#define PCI_MASTER_LATENCY_TIMER 0x0d // rw
+#define PCI_CONTROL 0x40 // rw
+#define PCI_ARBITER_CONTROL 0x41 // rw
+#define PCI_ARBITER_PRIORITY_CONTROL 0x42 // rw
+#define PCI_MEMCS_CONTROL 0x44 // rw
+#define PCI_MEMCS_BOTTOM_OF_HOLE 0x45 // rw
+#define PCI_MEMCS_TOP_OF_HOLE 0x46 // rw
+#define PCI_MEMCS_TOP_OF_MEMORY 0x47 // rw
+#define PCI_EISA_ADDRESS_DECODE_CONTROL_1 0x48 // rw
+#define PCI_ISA_IO_RECOVERY_TIME_CONTROL 0x4c // rw
+#define PCI_MEMCS_ATTRIBUTE_REGISTER_1 0x54 // rw
+#define PCI_MEMCS_ATTRIBUTE_REGISTER_2 0x55 // rw
+#define PCI_MEMCS_ATTRIBUTE_REGISTER_3 0x56 // rw
+#define PCI_DECODE_CONTROL 0x58 // rw
+#define PCI_EISA_ADDRESS_DECODE_CONTROL_2 0x5a // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGIONS_ATTR 0x5c // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION1_REGISTER 0x60 // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION2_REGISTER 0x64 // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION3_REGISTER 0x68 // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION4_REGISTER 0x6c // rw
+#define PCI_EISA_TO_PCI_IO_REGION1_REGISTER 0x70 // rw
+#define PCI_EISA_TO_PCI_IO_REGION2_REGISTER 0x74 // rw
+#define PCI_EISA_TO_PCI_IO_REGION3_REGISTER 0x78 // rw
+#define PCI_EISA_TO_PCI_IO_REGION4_REGISTER 0x7c // rw
+#define PCI_BIOS_TIMER_BASE_ADDRESS 0x80 // rw
+#define PCI_EISA_LATENCY_TIMER_CONTROL_REGISTER 0x84 // rw
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+//
+// Structure definitions of registers in PCEB PCI configuration space.
+// fields marked "Not supported" are Intel placeholders, apparently.
+//
+
+typedef union _PCEB_PCICMD{
+ struct {
+ USHORT IoSpaceEnable : 1;
+ USHORT MemorySpaceEnable : 1;
+ USHORT BusMasterEnable : 1;
+ USHORT SpecialCycleEnable: 1; // Not supported
+ USHORT MemoryWriteInvalidateEnable : 1; // Not supported
+ USHORT VgaPaletteSnoop : 1; // Not supported
+ USHORT ParityErrorEnable : 1;
+ USHORT WaitStateControl : 1; // Not supported
+ USHORT SerreEnable : 1; // Not supported
+ USHORT Reserved : 7;
+ };
+ USHORT All;
+} PCEB_PCICMD, *PPCEB_PCICMD;
+
+typedef union _PCEB_PCISTS{
+ struct {
+ USHORT Reserved : 9;
+ USHORT DevselTiming: 2; // ro
+ USHORT SignaledTargetAbort : 1; // Not supported
+ USHORT ReceivedTargetAbort: 1; // r/wc
+ USHORT MasterAbort : 1; // r/wc
+ USHORT Serrs : 1; // Not supported
+ USHORT ParityError: 1; // r/wc
+ };
+ USHORT All;
+} PCEB_PCISTS, *PPCEB_PCISTS;
+
+typedef union _PCEB_MLT{
+ struct {
+ UCHAR Reserved : 3;
+ UCHAR LatencyTimerCount: 5;
+ };
+ UCHAR All;
+} PCEB_MLT, *PPCEB_MLT;
+
+typedef union _PCEB_PCICON{
+ struct {
+ UCHAR Reserved1 : 2;
+ UCHAR PciPostedWriteBuffersEnable: 1;
+ UCHAR SubtractDecodeSamplePoint: 2;
+ UCHAR InterruptAcknowledgeEnable: 1;
+ UCHAR EisaToPciLineBuffersEnable: 1;
+ UCHAR Reserved2 : 1;
+ };
+ UCHAR All;
+} PCEB_PCICON, *PPCEB_PCICON;
+
+#define PCICON_SDSP_SLOW 0x00
+#define PCICON_SDSP_TYPICAL 0x01
+#define PCICON_SDSP_FAST 0x02
+
+typedef union _PCEB_ARBCON{
+ struct {
+ UCHAR GuaranteedAccessTimeEnable : 1;
+ UCHAR BusLockEnable: 1;
+ UCHAR CpuBusParkEnable: 1;
+ UCHAR MasterRetryTimer: 2;
+ UCHAR Reserved : 2;
+ UCHAR AutoPereqControlEnable: 1;
+ };
+ UCHAR All;
+} PCEB_ARBCON, *PPCEB_ARBCON;
+
+#define ARBCON_RETRY_TIMER_DISABLE 0x00
+#define ARBCON_16_PCICLKS_UNMASK 0x01
+#define ARBCON_32_PCICLKS_UNMASK 0x02
+#define ARBCON_64_PCICLKS_UNMASK 0x03
+
+typedef union _PCEB_ARBPRI{
+ struct {
+ UCHAR Bank0FixedPriorityMode : 1;
+ UCHAR Bank1FixedPriorityMode: 1;
+ UCHAR Bank2FixedPriorityMode: 2;
+ UCHAR Bank0RotateEnable: 1;
+ UCHAR Bank1RotateEnable: 1;
+ UCHAR Bank2RotateEnable: 1;
+ UCHAR Bank3RotateEnable: 1;
+ };
+ UCHAR All;
+} PCEB_ARBPRI, *PPCEB_ARBPRI;
+
+#define ARBPRI_BANK0_BANK3_BANK1 0x00
+#define ARBPRI_BANK3_BANK1_BANK0 0x10
+#define ARBPRI_BANK1_BANK0_BANK3 0x01
+
+typedef union _PCEB_MCSCON{
+ struct {
+ UCHAR ReadEnable512To640 : 1;
+ UCHAR WriteEnable512To640: 1;
+ UCHAR ReadEnableUpper64K: 1;
+ UCHAR WriteEnableUpper64K: 1;
+ UCHAR MemcsMasterEnable: 1;
+ UCHAR Reserved: 3;
+ };
+ UCHAR All;
+} PCEB_MCSCON, *PPCEB_MCSCON;
+
+typedef union _PCEB_EADC1{
+ struct {
+ USHORT Block0To512 : 1;
+ USHORT Block512To640: 1;
+ USHORT Block640To768: 1;
+ USHORT Reserved: 5;
+ USHORT Block768To784: 1;
+ USHORT Block784To800: 1;
+ USHORT Block800To816: 1;
+ USHORT Block816To832: 1;
+ USHORT Block832To848: 1;
+ USHORT Block848To864: 1;
+ USHORT Block864To880: 1;
+ USHORT Block880To896: 1;
+ };
+ UCHAR All;
+} PCEB_EADC1, *PPCEB_EADC1;
+
+typedef union _PCEB_IORT{
+ struct {
+ UCHAR RecoveryTimes16Bit : 2;
+ UCHAR RecoveryEnable16Bit: 1;
+ UCHAR RecoveryTimes8Bit : 3;
+ UCHAR RecoveryEnable8Bit: 1;
+ UCHAR Reserved: 1;
+ };
+ UCHAR All;
+} PCEB_IORT, *PPCEB_IORT;
+
+#define IORT_16BIT_1BCLK 0x01
+#define IORT_16BIT_2BCLKS 0x02
+#define IORT_16BIT_3BCLKS 0x03
+#define IORT_16BIT_4BCLKS 0x00
+
+#define IORT_8BIT_1BCLK 0x01
+#define IORT_8BIT_2BCLKS 0x02
+#define IORT_8BIT_3BCLKS 0x03
+#define IORT_8BIT_4BCLKS 0x04
+#define IORT_8BIT_5BCLKS 0x05
+#define IORT_8BIT_6BCLKS 0x06
+#define IORT_8BIT_7BCLKS 0x07
+#define IORT_8BIT_8BCLKS 0x00
+
+typedef union _PCEB_PDCON{
+ struct {
+ UCHAR PciDecodeMode : 1;
+ UCHAR Reserved1: 3;
+ UCHAR DecodeControlIde : 1;
+ UCHAR DecodeControl8259 : 1;
+ UCHAR Reserved2: 2;
+ };
+ UCHAR All;
+} PCEB_PDCON, *PPCEB_PDCON;
+
+#define SUBTRACTIVE_DECODE 0x00
+#define NEGATIVE_DECODE 0x01
+
+typedef struct _PCEB_EPMRA{
+ struct {
+ UCHAR Region1Attribute : 1;
+ UCHAR Region2Attribute : 1;
+ UCHAR Region3Attribute : 1;
+ UCHAR Region4Attribute : 1;
+ UCHAR Reserved: 4;
+ };
+ UCHAR All;
+} PCEB_EPMRA, *PPCEB_EPMRA;
+
+#define REGION_BUFFERED 0x01
+
+typedef struct _PCEB_MEMREGN{
+ USHORT BaseAddress;
+ USHORT LimitAddress;
+} PCEB_MEMREGN, *PPCEB_MEMREGN;
+
+typedef union _PCEB_IOREGN{
+ struct {
+ ULONG Reserved1: 2;
+ ULONG BaseAddress : 14;
+ ULONG Reserved2: 2;
+ ULONG LimitAddress : 14;
+ };
+ ULONG All;
+} PCEB_IOREGN, *PPCEB_IOREGN;
+
+typedef union _PCEB_BTMR{
+ struct {
+ USHORT BiosTimerEnable: 1;
+ USHORT Reserved: 1;
+ USHORT BaseAddress2thru15 : 14;
+ };
+ USHORT All;
+} PCEB_BTMR, *PPCEB_BTMR;
+
+#endif
+
+//
+// ESC value for setting edge/level operation in the control words.
+//
+#define IRQ0_LEVEL_SENSITIVE 0x01
+#define IRQ1_LEVEL_SENSITIVE 0x02
+#define IRQ2_LEVEL_SENSITIVE 0x04
+#define IRQ3_LEVEL_SENSITIVE 0x08
+#define IRQ4_LEVEL_SENSITIVE 0x10
+#define IRQ5_LEVEL_SENSITIVE 0x20
+#define IRQ6_LEVEL_SENSITIVE 0x40
+#define IRQ7_LEVEL_SENSITIVE 0x80
+#define IRQ8_LEVEL_SENSITIVE 0x01
+#define IRQ9_LEVEL_SENSITIVE 0x02
+#define IRQ10_LEVEL_SENSITIVE 0x04
+#define IRQ11_LEVEL_SENSITIVE 0x08
+#define IRQ12_LEVEL_SENSITIVE 0x10
+#define IRQ13_LEVEL_SENSITIVE 0x20
+#define IRQ14_LEVEL_SENSITIVE 0x40
+#define IRQ15_LEVEL_SENSITIVE 0x80
+
+//
+// Define primary (and only) CPU on an Mikasa system
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0)
+
+//
+// Define the default processor clock frequency used before the actual
+// value can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (200)
+
+#endif // _MIKASA_
diff --git a/private/ntos/nthals/halmikas/alpha/mkinitnt.c b/private/ntos/nthals/halmikas/alpha/mkinitnt.c
new file mode 100644
index 000000000..15f77ecd2
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/mkinitnt.c
@@ -0,0 +1,1031 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an Mikasa system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+ Balakumar Nagarajan (Digital) 9-Mar-1996
+ Added Errorlogging support.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "mikasa.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+#if DBG
+VOID
+DumpEpic(
+ VOID
+ );
+#endif // DBG
+
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpFamilyName = "AlphaServer";
+PCHAR HalpProductName = "1000";
+ULONG HalpProcessorNumber = 4;
+
+#define MAX_INIT_MSG (80)
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Mikasa
+//
+// IRQ_H[0] = EPIC Error
+// IRQ_H[1] = EISA Interrupt (PIC)
+// IRQ_H[2] = PCI Interrupt
+// IRQ_H[3] = Reserved
+// IRQ_H[4] = Clock
+// IRQ_H[5] = NMI (includes Halt)
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+//ADDRESS_USAGE
+//MikasaPCIMemorySpace = {
+// NULL, CmResourceTypeMemory, PCIUsage,
+// {
+// __8MB, ( __32MB - __8MB ), // Start=8MB; Length=24MB
+// 0,0
+// }
+//};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// Determines if the platform is a Noritake.
+//
+
+BOOLEAN HalpNoritakePlatform;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpClearInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeMikasaAndNoritakeInterrupts(
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ );
+
+VOID
+HalpDetermineMachineType(
+ VOID
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+// jwlfix - Does the following apply to me on Mikasa?
+//
+//jnfix, wkc - init the Eisa interrupts after the chip, don't init the
+// PIC here, fix halenablesysteminterrupt to init the pic
+// interrrupt, as in sable
+
+ //
+ // Initialize EISA, PCI and NMI interrupts.
+ //
+
+ HalpInitializeMikasaAndNoritakeInterrupts();
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+ HalpEnable21064HardwareInterrupt( Irq = 5,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = PCI_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize error handling for APECS.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish the error handler, to reflect the parity checking
+ //
+
+ HalpEstablishErrorHandler();
+
+ //
+ // Set up the hardware address extension registers.
+ //
+
+ HalpInitializeHAERegisters();
+
+ //
+ // Determine whether we are on a Noritake or a Mikasa platform.
+ //
+
+ HalpDetermineMachineType();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Print a message with version number.
+ //
+
+ sprintf( MsgBuffer,
+ "Digital Equipment Corporation %s %s %d/%d\n",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+ HalDisplayString( MsgBuffer );
+
+ //
+ // Register the name of the HAL.
+ //
+
+ sprintf( MsgBuffer,
+ "%s %s %d/%d PCI/EISA HAL",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+ HalpRegisterPlatformResources( MsgBuffer );
+
+ }
+
+ return;
+
+}
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Eisa);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ Resource.u.Start = SUPERIO_INDEX_PORT;
+ Resource.u.Length = SUPERIO_PORT_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaChannel = 0x4;
+ Resource.u.DmaPort = 0x0;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the EPIC/APECS chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // Set HAXR1 and HAXR2 registers
+ //
+ // We set HAXR1 to 0. This means HAXR1 has no effect.
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0);
+
+ //
+ // We set HAXR2 to 0. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. HAXR2 Not used in address translation
+ // 64K to 16MB VALID. HAXR2 is used in the address translation
+ //
+
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0);
+
+ //
+ // Report that the apecs mapping to the Io subsystem
+ //
+// HalpRegisterAddressUsage (&MikasaPCIMemorySpace);
+
+#if DBG
+ DumpEpic();
+#endif // DBG
+}
+
+
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the EPIC chip to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0 );
+ WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0 );
+}
+
+
+VOID
+HalpDetermineMachineType(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine will determine whether the platform we are running on is a
+ Noritake or a Mikasa, and set HalpNoritakePlatform accordingly.
+
+Arguments:
+
+ None.
+
+Return value:
+
+ None.
+
+--*/
+{
+
+ PSYSTEM_ID SystemId;
+
+ //
+ // Get the ProductId, and see if it contains "Nori".
+ // (The ProductId could be "1Nori" or "10Nori".)
+ //
+
+ SystemId = ArcGetSystemId();
+
+ if( strstr( &SystemId->ProductId[0], "Nori" ) != 0 ) {
+
+ HalpNoritakePlatform = TRUE;
+
+ } else {
+
+ HalpNoritakePlatform = FALSE;
+
+ }
+
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(APECS_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Mikasa";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/halmikas/alpha/mkintr.s b/private/ntos/nthals/halmikas/alpha/mkintr.s
new file mode 100644
index 000000000..56857340e
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/mkintr.s
@@ -0,0 +1,115 @@
+// TITLE("PCI/EISA Interrupt Handler")
+//++
+//
+// Copyright (c) 1994 Digital Equipment Corporation
+//
+// Module Name:
+//
+// mkintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for Mikasa
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 29-Apr-1994 James Livingston
+// Adapt from Avanti ebintr.s for Mikasa
+//
+//--
+
+#include "halalpha.h"
+
+ SBTTL("Mikasa Interrupt Handler")
+//++
+//
+// VOID
+// HalpEisaInterruptHandler
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on the EISA I/O
+// bus. The function is responsible for calling HalpEisaDispatch to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpEisaDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// EISA interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpEisaInterruptHandler)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpEisaDispatch // dispatch the interrupt to the dual 8259s.
+
+ ret zero, (ra) // will never get here
+
+ .end HalpEisaInterruptHandler
+
+//++
+//
+// VOID
+// HalpPciInterruptHandler
+// IN PKINTERRUPT Interrupt,
+// IN PVOID ServiceContext
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt on the PCI I/O
+// bus. The function is responsible for calling HalpPciDispatch to
+// appropriately dispatch the interrupt.
+//
+// N.B. This function exists only to capture the trap frame and forward
+// the interrupt to HalpPciDispatch.
+//
+// Arguments:
+//
+// Interrupt (a0) - Supplies a pointer to the interrupt object.
+//
+// ServiceContext (a1) - Supplies a pointer to the service context for
+// EISA interrupts.
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPciInterruptHandler)
+
+ bis fp, zero, a2 // capture trap frame as argument
+ br zero, HalpPciDispatch // dispatch the interrupt to the PCI handler
+
+ ret zero, (ra) // will never get here
+
+ .end HalpPciInterruptHandler
+
diff --git a/private/ntos/nthals/halmikas/alpha/mkintsup.c b/private/ntos/nthals/halmikas/alpha/mkintsup.c
new file mode 100644
index 000000000..1edc6cead
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/mkintsup.c
@@ -0,0 +1,827 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Mikasa systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ James Livingston (DEC) 30-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "mikasa.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Import globals declared in HalpMapIoSpace.
+//
+
+extern PVOID HalpServerControlQva;
+
+extern PVOID HalpMikasaPciIrQva;
+extern PVOID HalpMikasaPciImrQva;
+
+extern PVOID HalpNoritakePciIr1Qva;
+extern PVOID HalpNoritakePciIr2Qva;
+extern PVOID HalpNoritakePciIr3Qva;
+extern PVOID HalpNoritakePciImr1Qva;
+extern PVOID HalpNoritakePciImr2Qva;
+extern PVOID HalpNoritakePciImr3Qva;
+
+//
+// Import global from PCI interrupt management functions.
+//
+extern USHORT HalpMikasaPciInterruptMask;
+
+extern USHORT HalpNoritakePciInterrupt1Mask;
+extern USHORT HalpNoritakePciInterrupt2Mask;
+extern USHORT HalpNoritakePciInterrupt3Mask;
+
+//
+// Define reference to platform identifier
+//
+
+extern BOOLEAN HalpNoritakePlatform;
+
+//
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+
+KINTERRUPT HalpPciInterrupt;
+KINTERRUPT HalpEisaInterrupt;
+
+//
+// Declare the interrupt handler for the PCI bus. The interrupt dispatch
+// routine, HalpPciDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpPciInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Declare the interrupt handler for the EISA bus. The interrupt dispatch
+// routine, HalpEisaDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+ULONG NMIcount = 0;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// PCI initialization routines
+//
+
+VOID
+HalpInitializeMikasaPciInterrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeNoritakePciInterrupts(
+ VOID
+ );
+
+
+BOOLEAN
+HalpInitializeMikasaAndNoritakeInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the EISA interrupt controller; the Mikasa and Noritake ESC interrupt
+ controllers are compatible with the EISA interrupt contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Initialize the interrupt dispatchers for PCI & EISA I/O interrupts.
+ //
+
+ if( HalpNoritakePlatform ) {
+
+ KeInitializeInterrupt( &HalpPciInterrupt,
+ HalpPciInterruptHandler,
+ (PVOID) HalpNoritakePciIr1Qva, // Service Context
+ (PKSPIN_LOCK)NULL,
+ PCI_VECTOR,
+ PCI_DEVICE_LEVEL,
+ PCI_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ } else {
+
+ KeInitializeInterrupt( &HalpPciInterrupt,
+ HalpPciInterruptHandler,
+ (PVOID) HalpMikasaPciIrQva, // Service Context
+ (PKSPIN_LOCK)NULL,
+ PCI_VECTOR,
+ PCI_DEVICE_LEVEL,
+ PCI_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ }
+
+ if (!KeConnectInterrupt( &HalpPciInterrupt )) {
+ return(FALSE);
+ }
+
+ KeInitializeInterrupt( &HalpEisaInterrupt,
+ HalpEisaInterruptHandler,
+ (PVOID) HalpEisaIntAckBase, // Service Context is...
+ (PKSPIN_LOCK)NULL,
+ PIC_VECTOR,
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpEisaInterrupt )) {
+
+ return(FALSE);
+ }
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // There's no initialization required for the Mikasa PCI interrupt
+ // "controller," as it's the wiring of the hardware, rather than a
+ // PIC like the 82c59 that directs interrupts. We do set the IMR to
+ // zero to disable all interrupts, initially.
+ //
+ // The Noritake requires a separate routine to setup the 3 interrupt
+ // mask registers correctly.
+ //
+
+ if( HalpNoritakePlatform ) {
+
+ HalpInitializeNoritakePciInterrupts();
+
+ } else {
+
+ HalpInitializeMikasaPciInterrupts();
+
+ }
+
+ //
+ // We must initialize the ESC's PICs, for EISA interrupts.
+ //
+
+ HalpInitializeEisaInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register. Note that the other bits should be left as
+ // they are, according to the chip's documentation.
+ //
+
+ DataByte = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&DataByte))->NmiDisable = 0;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte);
+#ifdef HALDBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", DataByte);
+#endif
+
+}
+
+// jwlfix - I'll have to make this do something useful, since the console
+// halt button on Mikasa is connected to this interrupt. To start,
+// it will be a useful way to see if the interrupt gets connected.
+// The simple path is to check the server management register to
+// see if the "halt" button has been pressed on the operator's
+// console, and then initiate a hardware reset. On the other hand,
+// a server might not want to be halted so readily as that.
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+ UCHAR Datum;
+
+ NMIcount++;
+
+ //
+ // Set the Eisa NMI disable bit. We do this to mask further NMI
+ // interrupts while we're servicing this one.
+ //
+ Datum = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&Datum))->NmiDisable = 1;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum);
+#ifdef HALDBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum);
+#endif
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Parity Check / Parity Error\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+#else
+ //
+ // jwlfix - For the present, we're commenting out an NMI parity
+ // error bugcheck, until investigation into its causes
+ // yields a better solution.
+ //
+ // HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ // KeBugCheck(NMI_HARDWARE_FAILURE);
+ // return (TRUE);
+#endif
+ }
+
+ Datum = READ_REGISTER_UCHAR((PUCHAR)HalpServerControlQva );
+ if (((PMIKASA_SRV)(&Datum))->HaltIncoming == 0 ||
+ ((PMIKASA_SRV)(&Datum))->TempFail == 1 ||
+ ((PMIKASA_SRV)(&Datum))->Fan1Fault == 0 ||
+ ((PMIKASA_SRV)(&Datum))->Fan2Fault == 0) {
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Server management NMI\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+ DbgPrint("HalHandleNMI: Server Management Byte = 0x%x\r\n", Datum);
+#else
+ //
+ // jwlfix - All the above conditions are for handling server
+ // management features. Implementing more than simple
+ // dismissal waits upon definition of desired behavior
+ // by platform designers or Microsoft Windows NT
+ // requirements for server behavior.
+#endif
+ }
+
+ if (StatusByte & 0x40) {
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Channel Check / IOCHK\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+#else
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return (TRUE);
+#endif
+ }
+
+#if 0
+ // jwlfix - This code can be added in later, as we have need
+ // for it. It's good to have it here, for when it
+ // might be of use.
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+ // jwlfix - The following doesn't work, at this moment; it's
+ // likey the 12-bit shift, which should be a 5-bit
+ // shift on Mikasa.
+ //
+
+ BusAddress.HighPart = 0;
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++)
+ {
+ BusAddress.LowPart = (EisaPort << 12) + 0xC80;
+
+ Status = HalTranslateBusAddress(Eisa, // InterfaceType
+ 0, // BusNumber
+ BusAddress,
+ &AddressSpace, // 1=I/O address space
+ &TranslatedAddress); // QVA
+ if (Status == FALSE)
+ {
+ UCHAR pbuf[80];
+ sprintf(pbuf,
+ "Unable to translate bus address %x for EISA slot %d\n",
+ BusAddress.LowPart, EisaPort);
+ HalDisplayString(pbuf);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+
+ port = TranslatedAddress.LowPart;
+
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if its
+ // IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ }
+ }
+#ifdef HALDBG
+ // Reset extended NMI interrupts (for debugging purposes only).
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02);
+#endif
+#endif
+
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Resetting PERR#; NMI count = %d\r\n", NMIcount);
+#endif
+
+ //
+ // Reset PERR# and disable it.
+ //
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04);
+
+ //
+ // now enable it again.
+ //
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0);
+
+ //
+ // Clear the Eisa NMI disable bit. This re-enables NMI interrupts,
+ // now that we're done servicing this one.
+ //
+ Datum = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&Datum))->NmiDisable = 0;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum);
+#ifdef HALDBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum);
+#endif
+
+ return(TRUE);
+}
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ return( InterruptVector );
+
+}
+
+
+UCHAR
+HalpAcknowledgeMikasaPciInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the Mikasa PCI interrupt register QVA.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector = 0;
+ USHORT IrContents;
+ int i;
+
+ //
+ // Find the first zero bit in the register, starting from the highest
+ // order bit. This implies a priority ordering that makes a certain
+ // amount of sense, in that bits 14 and 13 indicate temperature and
+ // power faults, while bit 12 is the Ncr53c810. Note that it's
+ // necessary to add one to the bit number to make the interrupt
+ // vector, a unit-origin value in the pin-to-line table. We do
+ // this by starting i at 16 and ending it at 1; that means zero
+ // is a non-enabled interrupt indication.
+ //
+
+ //
+ // First, get and complement the interrupt register, so that the
+ // pending interrupts will be the "1" bits. Then mask with the
+ // enabled mask, HalpMikasaPciInterruptMask;
+ //
+
+ IrContents = ~(0xffff & READ_REGISTER_USHORT( (PUSHORT)ServiceContext ));
+ IrContents &= HalpMikasaPciInterruptMask;
+
+ for (i = 16; i >= 1; i-- ) {
+ if ( IrContents & 0x8000 ) {
+ InterruptVector = i;
+ break;
+ } else {
+ IrContents <<= 1;
+ }
+ }
+ return( InterruptVector );
+
+}
+
+
+UCHAR
+HalpAcknowledgeNoritakePciInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the Noritake PCI interrupt register 1 QVA.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector = 0;
+ USHORT IrContents;
+ int i;
+
+ //
+ // Interrupt1 register contains the sum of all interrupts of Interrupt2
+ // and Interrupt3 registers in bit 0. The rest of the register contains
+ // the A and B interrupts of the 7 PCI slots. Interrupt2 register
+ // contains the sum of all of the unmasked interrupts of Interrupt 2 in bit
+ // 0. Bit 1 is asserted when any secondary PCI bus interrupt is asserted
+ // (including those in interrupt register 1) and the posted write buffers
+ // in the PPB have been flushed. The rest of the register contians the C
+ // and D interrupts of all of the slots. Interrupt3 register contains some
+ // safety and reliability interrupts. Please see mikasa.h for the
+ // definitions of which interrupt is at which bit in the register.
+ //
+ // Each bit in the registers corresponds to an interrupt vector (which
+ // will later have PCI_VECTORS added to it.) This vector can be obtained
+ // by adding the vector offset for that register to the bit position.
+ // These offsets are also defined in mikasa.h.
+ //
+ // All registers are "reverse-logic" (active low), where a 0 means that an
+ // interrupt is waiting. That is why we must complement the contents of
+ // the register before we mask with HalpNoritakePciInterruptXMask.
+ //
+
+ //
+ // First, get and complement the first interrupt register, so that the
+ // pending interrupts will be the "1" bits. Then mask with the
+ // enabled mask, HalpNoritakePciInterrupt1Mask;
+ //
+
+ IrContents =
+ ~(0xffff & READ_REGISTER_USHORT((PUSHORT)HalpNoritakePciIr1Qva));
+ IrContents &= HalpNoritakePciInterrupt1Mask;
+
+ //
+ // Position bit 1 as the lowest bit. We will start checking here - this
+ // is the first "real" interrupt.
+ //
+
+ IrContents >>= 1;
+
+ for( i = 1; i < 16; i++ ) {
+ if( IrContents & 0x1 ) {
+ InterruptVector = i + REGISTER_1_VECTOR_OFFSET;
+ break;
+ }
+ IrContents >>= 1;
+ }
+
+
+ if( InterruptVector == 0 ) {
+
+ //
+ // We didn't find any interrupts in interrupt register 1.
+ // Check interrupt register 2.
+ //
+
+ IrContents =
+ ~(0xffff & READ_REGISTER_USHORT((PUSHORT)HalpNoritakePciIr2Qva));
+ IrContents &= HalpNoritakePciInterrupt2Mask;
+
+ //
+ // Position bit 2 in the lowest bit. We will start checking here -
+ // this is the first "real" interrupt.
+ //
+
+ IrContents >>= 2;
+
+ for( i = 2; i < 16; i++ ) {
+ if( IrContents & 0x1 ) {
+ InterruptVector = i + REGISTER_2_VECTOR_OFFSET;
+ break;
+ }
+ IrContents >>= 1;
+ }
+
+ if( InterruptVector == 0 ) {
+
+ //
+ // We didn't find any interrupts in interrupt register 2.
+ // Check Interrupt Register 3.
+ //
+
+ IrContents = ~(0xffff &
+ READ_REGISTER_USHORT((PUSHORT)HalpNoritakePciIr3Qva));
+ IrContents &= HalpNoritakePciInterrupt3Mask;
+
+ //
+ // Position bit 2 in the lowest bit. We will start checking here -
+ // this is the first "real" interrupt.
+ //
+
+ IrContents >>= 2;
+
+ for( i = 2; i < 6; i++ ) {
+ if( IrContents & 0x1 ) {
+ InterruptVector = i + REGISTER_3_VECTOR_OFFSET;
+ break;
+ }
+ IrContents >>= 1;
+ }
+
+ }
+
+ }
+
+ return( InterruptVector );
+
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Mikasa comes from a Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
diff --git a/private/ntos/nthals/halmikas/alpha/mkmapio.c b/private/ntos/nthals/halmikas/alpha/mkmapio.c
new file mode 100644
index 000000000..15b243fad
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/mkmapio.c
@@ -0,0 +1,219 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Mikasa system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+#include "halp.h"
+#include "mikasa.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+PVOID HalpServerControlQva;
+
+PVOID HalpMikasaPciIrQva;
+PVOID HalpMikasaPciImrQva;
+
+PVOID HalpNoritakePciIr1Qva;
+PVOID HalpNoritakePciIr2Qva;
+PVOID HalpNoritakePciIr3Qva;
+PVOID HalpNoritakePciImr1Qva;
+PVOID HalpNoritakePciImr2Qva;
+PVOID HalpNoritakePciImr3Qva;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a Mikasa system using
+ the Quasi VA mechanism.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( APECS_PCI_IO_BASE_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( APECS_PCI_INTACK_BASE_PHYSICAL );
+
+ //
+ // Set up the Mikasa interrupt registers.
+ //
+ // Map PCI interrupt and interrupt mask registers. The former register
+ // receives the interrupt state of each individual pin in each PCI slot,
+ // the state of the NCR 53C810 interrupt, and two server management
+ // interrupts' states. The PCI interrupt mask register can mask each
+ // of the interrupts in the IR.
+ //
+
+ HalpMikasaPciIrQva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER);
+ HalpMikasaPciImrQva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER);
+
+ //
+ // Set up the Noritake interrupt registers.
+ //
+ // Map the PCI interrupt and interrupt mask registers for Noritake.
+ // There are three interrupt registers, and three mask registers.
+ // The exact contents are described in mikasa.h.
+ //
+ // The Base Address Register of the interrupt registers is set up in SROM.
+ // We can change this if we choose.
+ //
+
+ HalpNoritakePciIr1Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_1);
+ HalpNoritakePciImr1Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_1);
+
+ HalpNoritakePciIr2Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_2);
+ HalpNoritakePciImr2Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_2);
+
+ HalpNoritakePciIr3Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_3);
+ HalpNoritakePciImr3Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_3);
+
+
+ //
+ // Map the Mikasa server management register. This single byte register
+ // contains the bits that enable control of the high-availability options
+ // on Mikasa. This is at the same location in the Noritake, but it has a
+ // slightly different content.
+ //
+
+ HalpServerControlQva = (PVOID)((ULONG)PciIoSpaceBase
+ + SERVER_MANAGEMENT_REGISTER);
+ //
+ // Map CMOS RAM address.
+ //
+
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + ESC_CMOS_ISA_PORT);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halmikas/alpha/mksysint.c b/private/ntos/nthals/halmikas/alpha/mksysint.c
new file mode 100644
index 000000000..4e47402cc
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/mksysint.c
@@ -0,0 +1,551 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkinitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Mikasa system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+#include "halp.h"
+#include "mikasa.h"
+#include "axp21064.h"
+
+//
+// Function prototype
+//
+VOID
+HalpDisableMikasaPciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableNoritakePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableMikasaPciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpEnableNoritakePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+extern USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define reference to platform identifier
+//
+
+extern BOOLEAN HalpNoritakePlatform;
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL) {
+
+ if( HalpNoritakePlatform ) {
+
+ HalpDisableNoritakePciInterrupt(Vector);
+
+ } else {
+
+ HalpDisableMikasaPciInterrupt(Vector);
+
+ }
+
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Disable the correctable error interrupt.
+ //
+
+ {
+ EPIC_ECSR Ecsr;
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+ Ecsr.Dcei = 0x0;
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all );
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ break;
+
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == PCI_DEVICE_LEVEL) {
+
+ if( HalpNoritakePlatform ) {
+
+ HalpEnableNoritakePciInterrupt( Vector, InterruptMode );
+
+ } else {
+
+ HalpEnableMikasaPciInterrupt( Vector, InterruptMode );
+
+ }
+
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Enable the correctable error interrupt.
+ //
+
+ {
+ EPIC_ECSR Ecsr;
+
+ Ecsr.all = READ_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister );
+
+ Ecsr.Dcei = 0x1;
+
+ WRITE_EPIC_REGISTER(
+ &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister,
+ Ecsr.all );
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ }
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+jwlfix - How does the above apply to PCI when it's done as in Mikasa? I've
+ made the assumption the the same is true, but that must be checked.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else if ((Vector = HalpGet21064CorrectableVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Correctable error interrupt was sucessfully recognized.
+ //
+
+ *Affinity = 1;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same processor pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus ISA_VECTORS.
+ // N.B.: this encoding technique uses the notion of defining a
+ // base interrupt vector in the space defined by the constant,
+ // ISA_VECTORS, which may or may not differ from EISA_VECTORS or
+ // PCI_VECTORS.
+ //
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same processor pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same processor pin
+ //
+
+ *Irql = PCI_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR
+ //
+
+ return((BusInterruptLevel) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on Mikasa systems.
+ //
+#if defined(HALDBG)
+ DbgPrint("MKSYSINT: InterfaceType (%d) not supported on Mikasa\r\n",
+ InterfaceType);
+#endif
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Mikasa because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/halmikas/alpha/pcibus.c b/private/ntos/nthals/halmikas/alpha/pcibus.c
new file mode 100644
index 000000000..8ad83dfe8
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pcibus.c
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 29-Apr-1994 James Livingston
+ Adapted from Avanti module for Mikasa.
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+//
+// Reference variable that defines largest PCI bus number.
+//
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0) {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Note that HalpValidPCISlot has already done bounds checking
+ // on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n",
+ pPciAddr->u.AsULONG);
+#endif // DBG
+
+ } else {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if HALDBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halmikas/alpha/pciesc.c b/private/ntos/nthals/halmikas/alpha/pciesc.c
new file mode 100644
index 000000000..49142ea83
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pciesc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pciesc.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/pciir.c b/private/ntos/nthals/halmikas/alpha/pciir.c
new file mode 100644
index 000000000..4fe907622
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pciir.c
@@ -0,0 +1,499 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pciir.c
+
+Abstract:
+
+ The module provides the interrupt support for the Mikasa's PCI
+ interrupts.
+
+Author:
+
+ James Livingston 2-May-1994
+
+Revision History:
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define external function prototypes
+//
+
+UCHAR
+HalpAcknowledgeMikasaPciInterrupt(
+ PVOID ServiceContext
+ );
+
+UCHAR
+HalpAcknowledgeNoritakePciInterrupt(
+ PVOID ServiceContext
+ );
+
+//
+// Import save area for PCI interrupt mask register.
+//
+
+USHORT HalpMikasaPciInterruptMask;
+
+USHORT HalpNoritakePciInterrupt1Mask;
+USHORT HalpNoritakePciInterrupt2Mask;
+USHORT HalpNoritakePciInterrupt3Mask;
+
+//
+// Reference for globals defined in I/O mapping module.
+//
+extern PVOID HalpMikasaPciIrQva;
+extern PVOID HalpMikasaPciImrQva;
+
+extern PVOID HalpNoritakePciIr1Qva;
+extern PVOID HalpNoritakePciIr2Qva;
+extern PVOID HalpNoritakePciIr3Qva;
+extern PVOID HalpNoritakePciImr1Qva;
+extern PVOID HalpNoritakePciImr2Qva;
+extern PVOID HalpNoritakePciImr3Qva;
+
+//
+// Define reference to platform identifier
+//
+
+extern BOOLEAN HalpNoritakePlatform;
+
+
+VOID
+HalpInitializeMikasaPciInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Mikasa PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Initialize the Mikasa PCI interrupts. There is a single interrupt mask
+ // that permits individual interrupts to be enabled or disabled by
+ // setting the appropriate bit in the interrupt mask register. We
+ // initialize them all to "disabled".
+ //
+
+ HalpMikasaPciInterruptMask = 0;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpMikasaPciImrQva,
+ HalpMikasaPciInterruptMask );
+
+}
+
+
+VOID
+HalpInitializeNoritakePciInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Noritake PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Initialize the Noritake PCI interrupts. There are three interrupt masks
+ // that permit individual interrupts to be enabled or disabled by
+ // setting the appropriate bit in the interrupt mask register. We
+ // initialize them all to "disabled", except for the SUM bits. (Bit 0
+ // in IR1, and bits 0 and 1 in IR2.)
+ //
+
+ HalpNoritakePciInterrupt1Mask = 0x1;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr1Qva,
+ HalpNoritakePciInterrupt1Mask );
+
+ HalpNoritakePciInterrupt2Mask = 0x3;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr2Qva,
+ HalpNoritakePciInterrupt2Mask );
+
+ HalpNoritakePciInterrupt3Mask = 0x0;
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr3Qva,
+ HalpNoritakePciInterrupt3Mask );
+
+}
+
+
+VOID
+HalpDisableMikasaPciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0, offset by one.
+ //
+
+ Vector -= PCI_VECTORS + 1;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ HalpMikasaPciInterruptMask =
+ READ_REGISTER_USHORT( (PUSHORT)HalpMikasaPciImrQva );
+ HalpMikasaPciInterruptMask &= (USHORT) ~(1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpMikasaPciImrQva,
+ HalpMikasaPciInterruptMask );
+
+}
+
+
+VOID
+HalpDisableNoritakePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // First we must determine which interrupt register the interrupt is in.
+ // In each case, subtract the register offset to get the bit position in
+ // the interrupt register. Then, get the current state of the interrupt
+ // mask register. Finally, set the bit corresponding to the adjusted value
+ // of Vector to zero, to disable that PCI interrupt.
+ //
+
+ if( Vector >= REGISTER_2_VECTOR_OFFSET ) {
+
+ if( Vector >= REGISTER_3_VECTOR_OFFSET ) {
+
+ //
+ // The interrupt is in Interrupt Register 3.
+ //
+
+ Vector -= REGISTER_3_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt3Mask = READ_REGISTER_USHORT(
+ (PUSHORT)HalpNoritakePciImr3Qva );
+ HalpNoritakePciInterrupt3Mask &= (USHORT) ~(1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr3Qva,
+ HalpNoritakePciInterrupt3Mask );
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 2.
+ //
+
+ Vector -= REGISTER_2_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt2Mask = READ_REGISTER_USHORT(
+ (PUSHORT)HalpNoritakePciImr2Qva );
+ HalpNoritakePciInterrupt2Mask &= (USHORT) ~(1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr2Qva,
+ HalpNoritakePciInterrupt2Mask );
+
+ }
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 1.
+ //
+
+ Vector -= REGISTER_1_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt1Mask =
+ READ_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr1Qva );
+ HalpNoritakePciInterrupt1Mask &= (USHORT) ~(1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr1Qva,
+ HalpNoritakePciInterrupt1Mask );
+
+ }
+
+}
+
+
+VOID
+HalpEnableMikasaPciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Mikasa PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0, offset by one.
+ //
+
+ Vector -= PCI_VECTORS + 1;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to one,
+ // to enable that PCI interrupt.
+ //
+
+ HalpMikasaPciInterruptMask =
+ READ_REGISTER_USHORT( (PUSHORT)HalpMikasaPciImrQva );
+ HalpMikasaPciInterruptMask |= (USHORT) (1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpMikasaPciImrQva,
+ HalpMikasaPciInterruptMask );
+
+}
+
+
+VOID
+HalpEnableNoritakePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Mikasa PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // First we must determine which interrupt register the interrupt is in.
+ // In each case, subtract the register offset to get the bit position in
+ // the interrupt register. Then, get the current state of the interrupt
+ // mask register. Finally, set the bit corresponding to the adjusted value
+ // of Vector to one, to enable that PCI interrupt.
+ //
+
+ if( Vector >= REGISTER_2_VECTOR_OFFSET ) {
+
+ if( Vector >= REGISTER_3_VECTOR_OFFSET ) {
+
+ //
+ // The interrupt is in Interrupt Register 3.
+ //
+
+ Vector -= REGISTER_3_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt3Mask = READ_REGISTER_USHORT(
+ (PUSHORT)HalpNoritakePciImr3Qva );
+ HalpNoritakePciInterrupt3Mask |= (USHORT) (1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr3Qva,
+ HalpNoritakePciInterrupt3Mask );
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 2.
+ //
+
+ Vector -= REGISTER_2_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt2Mask = READ_REGISTER_USHORT(
+ (PUSHORT)HalpNoritakePciImr2Qva );
+ HalpNoritakePciInterrupt2Mask |= (USHORT) (1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr2Qva,
+ HalpNoritakePciInterrupt2Mask );
+
+ }
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 1.
+ //
+
+ Vector -= REGISTER_1_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt1Mask =
+ READ_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr1Qva );
+ HalpNoritakePciInterrupt1Mask |= (USHORT) (1 << Vector);
+ WRITE_REGISTER_USHORT( (PUSHORT)HalpNoritakePciImr1Qva,
+ HalpNoritakePciInterrupt1Mask );
+
+ }
+
+}
+
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt having been generated
+ via the vector connected to the PCI device interrupt object. Its function
+ is to call the second-level interrupt dispatch routine.
+
+ This service routine could have been connected as follows, where the
+ ISR is the assembly wrapper that does the handoff to this function:
+
+ KeInitializeInterrupt( &Interrupt,
+ HalpPciInterruptHandler,
+ (PVOID) HalpPciIrQva,
+ (PKSPIN_LOCK)NULL,
+ PCI_VECTOR,
+ PCI_DEVICE_LEVEL,
+ PCI_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE);
+
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR PCIVector;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+
+ //
+ // Acknowledge interrupt and receive the returned interrupt vector.
+ // If we got zero back, there were no enabled interrupts, so we
+ // signal that with a FALSE return, immediately.
+ //
+
+ if( HalpNoritakePlatform ) {
+
+ PCIVector = HalpAcknowledgeNoritakePciInterrupt(ServiceContext);
+
+ } else {
+
+ PCIVector = HalpAcknowledgeMikasaPciInterrupt(ServiceContext);
+
+ }
+
+ if (PCIVector == 0) {
+ return( FALSE );
+ }
+
+ PCRInOffset = PCIVector + PCI_VECTORS;
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset],
+ TrapFrame
+ );
+
+ return( returnValue );
+}
diff --git a/private/ntos/nthals/halmikas/alpha/pcisup.c b/private/ntos/nthals/halmikas/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/pcrtc.c b/private/ntos/nthals/halmikas/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/pcserial.c b/private/ntos/nthals/halmikas/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/pcspeakr.c b/private/ntos/nthals/halmikas/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/perfcntr.c b/private/ntos/nthals/halmikas/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halmikas/alpha/pintolin.h b/private/ntos/nthals/halmikas/alpha/pintolin.h
new file mode 100644
index 000000000..52dfcb23a
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/pintolin.h
@@ -0,0 +1,219 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Table
+ for Mikasa.
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston (Digital) 10-May-1994
+ Extracted Mikasa-specific table from the combined table
+ of pin-to-line assignments.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+//
+// This table represents the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// On platforms that use an interrupt register or registers instead of,
+// or in addition to cascaded 85c59s, the Interrupt Vector is one greater
+// than the Interrupt Request Register bit, because interrupt vectors
+// can't be zero, and bits in a register are numbered from zero. On
+// Mikasa, the Interrupt Vector also represents the Interrupt Mask
+// Register bit, since the arrangement of its bits is identical to
+// that of the Interrupt Read Register.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// (SlotNumber.DeviceNumber, InterruptPin) -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit + 1
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit + 1
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to:
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table for lookup function is initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (Slot.DeviceNumber + 11)
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]).
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#,
+// INTD#, per the PCI Spec. V2.0, Section 2.2.6. Devices having one
+// interrupt use INTA#; only multifunction devices use INTB#, INTC#,
+// INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which can have the values:
+//
+// INTA# = 1, INTB# = 2, INTC# = 3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots. Each function has its own PCI
+// configuration space, addressed by the SlotNumber.FunctionNumber field,
+// and will identify which interrput pin of the four it will use in its
+// own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts from "downstream" PCI
+// slots must somehow be combined to appear on some combination of the
+// four interrupt pins belonging to the bridge's slot.
+//
+// InterruptLine:
+// This PCI Configuration register is maintained by software, and holds
+// an offset into PCI interrupt vectors. Whenever HalGetBusData or
+// HalGetBusDataByOffset is called, HalpPCIPinToLine() computes the
+// correct InterruptLine register value by using the mapping in
+// HalpPCIPinToLineTable.
+//
+// InterruptRequestRegisterBit:
+// In the table, 0xff is used to mark an invalid cell; this cell cannot
+// be used to produce an interrupt request register bit.
+//
+// InterruptMaskRegisterBit:
+// On Mikasa, the pin-to-line table may also be used to write the
+// InterruptMaskRegister, via
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used, should we be accessing a multifunction device.)
+// Virtual slot 0 represents the device with IDSEL = AD[11], and so on.
+//
+//
+// Interrupt Vector Table Mapping for Mikasa.
+//
+// Mikasa PCI interrupts are mapped to interrupt vectors in the table
+// below. The values are a 1-1 map of the bit numbers in the Mikasa
+// PCI interrupt register that are connected to PCI devices.
+//
+// N.B.: there are two other interrupts in the Mikasa IRR/IMR, but they
+// are not connected to I/O devices, and have no associated PCI virtual
+// slot, so they're not represented in the table. Entries in the table
+// are interrupt vector values for the device having the given virtual
+// slot and pin number.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_MIKASA.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+
+PULONG HalpPCIPinToLineTable;
+
+ULONG MikasaPCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xd, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] ESC
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0x1, 0x2, 0x3, 0x4 }, // Virtual Slot 11 = PCI_AD[22] Slot #0
+ { 0x5, 0x6, 0x7, 0x8 }, // Virtual Slot 12 = PCI_AD[23] Slot #1
+ { 0x9, 0xa, 0xb, 0xc } // Virtual Slot 13 = PCI_AD[24] Slot #2
+};
+
+
+//
+// Limit init table to 14 entries, which is the MAX_PCI_LOCAL_DEVICES_MIKASA.
+// (It is same for Noritake.)
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24] on bus 0.
+//
+// Noritake PCI interrupts will be no lower than 0x11 so that they are disjoint
+// from EISA levels.
+//
+
+ULONG NoritakePCIPinToLineTable0[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] PCEB
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] PCI-PCI Bridge
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0x13, 0x14, 0x23, 0x24 }, // Virtual Slot 11 = PCI_AD[22] Slot 0
+ { 0x15, 0x16, 0x25, 0x26 }, // Virtual Slot 12 = PCI_AD[23] Slot 1
+ { 0x17, 0x18, 0x27, 0x28 } // Virtual Slot 13 = PCI_AD[24] Slot 2
+};
+
+
+ULONG NoritakePCIPinToLineTable1[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0x12, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[16] QLogic
+ { 0x19, 0x1a, 0x29, 0x2a }, // Virtual Slot 1 = PCI_AD[17] Slot 3
+ { 0x1b, 0x1c, 0x2b, 0x2c }, // Virtual Slot 2 = PCI_AD[18] Slot 4
+ { 0x1d, 0x1e, 0x2d, 0x2e }, // Virtual Slot 3 = PCI_AD[19] Slot 5
+ { 0x1f, 0x20, 0x2f, 0x30 } // Virtual Slot 4 = PCI_AD[20] Slot 6
+};
diff --git a/private/ntos/nthals/halmikas/alpha/vga.c b/private/ntos/nthals/halmikas/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halmikas/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halmikas/drivesup.c b/private/ntos/nthals/halmikas/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halmikas/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halmikas/hal.rc b/private/ntos/nthals/halmikas/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halmikas/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halmikas/hal.src b/private/ntos/nthals/halmikas/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halmikas/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halmikas/makefile b/private/ntos/nthals/halmikas/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmikas/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halmikas/makefile.inc b/private/ntos/nthals/halmikas/makefile.inc
new file mode 100644
index 000000000..3b2c2be8e
--- /dev/null
+++ b/private/ntos/nthals/halmikas/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halmikas.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halmikas/sources b/private/ntos/nthals/halmikas/sources
new file mode 100644
index 000000000..16af3ab0b
--- /dev/null
+++ b/private/ntos/nthals/halmikas/sources
@@ -0,0 +1,105 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halmikas
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DAPECS -DEISA_PLATFORM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\apecs.c \
+ alpha\apecserr.c \
+ alpha\apecsio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mchk.c \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\iousage.c \
+ alpha\ioproc.c \
+ alpha\memory.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\mkinitnt.c \
+ alpha\mkintr.s \
+ alpha\mkintsup.c \
+ alpha\mkmapio.c \
+ alpha\mksysint.c \
+ alpha\cmos8k.c \
+ alpha\pcisup.c \
+ alpha\pciir.c \
+ alpha\pciesc.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halmps/bushnd.c b/private/ntos/nthals/halmps/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halmps/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halmps/dirs b/private/ntos/nthals/halmps/dirs
new file mode 100644
index 000000000..3da411e04
--- /dev/null
+++ b/private/ntos/nthals/halmps/dirs
@@ -0,0 +1,22 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up mp mpmca
diff --git a/private/ntos/nthals/halmps/drivesup.c b/private/ntos/nthals/halmps/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halmps/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halmps/hal.rc b/private/ntos/nthals/halmps/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halmps/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halmps/i386/apic.inc b/private/ntos/nthals/halmps/i386/apic.inc
new file mode 100644
index 000000000..8d7dd5ade
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/apic.inc
@@ -0,0 +1,283 @@
+;/*
+;++
+;
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+;
+; Module Name:
+;
+; apic.inc
+;
+; Abstract:
+;
+; This module contains the definitions used by HAL to manipulate
+; APIC interrupt controller and APIC-specific constants.
+;
+; WARNING: This file is included by both ASM and C files.
+;
+; Author:
+;
+; Hugh Bynum and Ron Mosgrove Aug-1992
+;
+;--
+if 0 ; Begin C only code */
+
+typedef volatile ULONG *PVULONG;
+
+
+//
+// APIC Version Register (both IO Unit and Local Units)
+//
+
+struct ApicVersion {
+ UCHAR Version; // either 0.x or 1.x
+ UCHAR Reserved1;
+ UCHAR MaxRedirEntries; // Number of INTIs on unit
+ UCHAR Reserved2;
+};
+
+//
+// IO Unit definition
+//
+
+struct ApicIoUnit {
+ volatile ULONG RegisterSelect; // Write register number to access register
+ volatile ULONG Reserved1[3];
+ volatile ULONG RegisterWindow; // Data read/written here
+};
+
+//
+// APIC defines for C code
+// BE SURE TO CHANGE THESE VALUES IN BOTH TABLES!
+//
+
+#define IO_REGISTER_SELECT 0x00000000 //
+#define IO_REGISTER_WINDOW 0x00000010 //
+
+#define IO_ID_REGISTER 0x00000000
+#define IO_VERS_REGISTER 0x00000001
+#define IO_ARB_ID_REGISTER 0x00000002
+#define IO_REDIR_00_LOW 0x00000010
+#define IO_REDIR_00_HIGH 0x00000011
+
+#define IO_MAX_REDIR_MASK 0x00FF0000
+#define IO_VERSION_MASK 0x000000FF
+
+#define LU_ID_REGISTER 0x00000020 //
+#define LU_VERS_REGISTER 0x00000030 //
+#define LU_TPR 0x00000080 //
+#define LU_APR 0x00000090 //
+#define LU_PPR 0x000000A0 //
+#define LU_EOI 0x000000B0 //
+#define LU_REMOTE_REGISTER 0x000000C0 //
+
+#define LU_LOGICAL_DEST 0x000000D0 //
+#define LU_LOGICAL_DEST_MASK 0xFF000000
+
+#define LU_DEST_FORMAT 0x000000E0 //
+#define LU_DEST_FORMAT_MASK 0xF0000000
+#define LU_DEST_FORMAT_FLAT 0xFFFFFFFF
+
+#define LU_SPURIOUS_VECTOR 0x000000F0 //
+#define LU_FAULT_VECTOR 0x00000370 //
+#define LU_UNIT_ENABLED 0x00000100
+#define LU_UNIT_DISABLED 0x00000000
+
+#define LU_ISR_0 0x00000100 //
+#define LU_TMR_0 0x00000180 //
+#define LU_IRR_0 0x00000200 //
+#define LU_ERROR_STATUS 0x00000280 //
+#define LU_INT_CMD_LOW 0x00000300 //
+#define LU_INT_CMD_HIGH 0x00000310 //
+#define LU_TIMER_VECTOR 0x00000320 //
+#define LU_PERF_VECTOR 0x00000340
+#define LU_INT_VECTOR_0 0x00000350 // TEMPORARY - do not use
+#define LU_INT_VECTOR_1 0x00000360 // TEMPORARY - do not use
+#define LU_INITIAL_COUNT 0x00000380 //
+#define LU_CURRENT_COUNT 0x00000390 //
+#define LU_DIVIDER_CONFIG 0x000003E0 //
+
+#define APIC_ID_MASK 0x0F000000
+#define APIC_ID_SHIFT 24
+
+#define INT_VECTOR_MASK 0x000000FF
+#define RESERVED_HIGH_INT 0x000000F8
+#define DELIVERY_MODE_MASK 0x00000700
+#define DELIVER_FIXED 0x00000000
+#define DELIVER_LOW_PRIORITY 0x00000100
+#define DELIVER_SMI 0x00000200
+#define DELIVER_REMOTE_READ 0x00000300
+#define DELIVER_NMI 0x00000400
+#define DELIVER_INIT 0x00000500
+#define DELIVER_STARTUP 0x00000600
+#define DELIVER_EXTINT 0x00000700
+#define PHYSICAL_DESTINATION 0x00000000
+#define LOGICAL_DESTINATION 0x00000800
+#define DELIVERY_PENDING 0x00001000
+#define ACTIVE_LOW 0x00002000
+#define ACTIVE_HIGH 0x00000000
+#define REMOTE_IRR 0x00004000
+#define LEVEL_TRIGGERED 0x00008000
+#define EDGE_TRIGGERED 0x00000000
+#define INTERRUPT_MASKED 0x00010000
+#define INTERRUPT_MOT_MASKED 0x00000000
+#define PERIODIC_TIMER 0x00020000
+
+#define ICR_LEVEL_ASSERTED 0x00004000
+#define ICR_LEVEL_DEASSERTED 0x00000000
+#define ICR_RR_STATUS_MASK 0x00030000
+#define ICR_RR_INVALID 0x00000000
+#define ICR_RR_IN_PROGRESS 0x00010000
+#define ICR_RR_VALID 0x00020000
+#define ICR_SHORTHAND_MASK 0x000C0000
+#define ICR_USE_DEST_FIELD 0x00000000
+#define ICR_SELF 0x00040000
+#define ICR_ALL_INCL_SELF 0x00080000
+#define ICR_ALL_EXCL_SELF 0x000C0000
+
+//
+// Special ICR request to reset a remote processor
+//
+#define LU_RESET_ASSERT ( DELIVER_INIT | LEVEL_TRIGGERED | ICR_LEVEL_ASSERTED | \
+ ICR_USE_DEST_FIELD | PHYSICAL_DESTINATION)
+#define LU_RESET_DEASSERT ( DELIVER_INIT | LEVEL_TRIGGERED | ICR_LEVEL_DEASSERTED | \
+ ICR_USE_DEST_FIELD | PHYSICAL_DESTINATION)
+//
+// Special ICR request to reset a remote processor
+//
+#define LU_INIT_DEASSERT (DELIVER_INIT | LEVEL_TRIGGERED | \
+ ICR_ALL_INCL_SELF | ICR_LEVEL_DEASSERTED )
+//
+// Startup ICR Requset - OR in the VV value needed
+//
+#define LU_STARTUP_IPI ( DELIVER_STARTUP | ICR_USE_DEST_FIELD | \
+ PHYSICAL_DESTINATION)
+
+#define DESTINATION_MASK 0xFF000000
+#define DESTINATION_SHIFT 24
+//
+// APIC IO unit redirection table, interrupt destination field: this field
+// is 32 bits for the 82489DX APIC; future APIC implementations will put the
+// destination field in the upper 8 bits of the entry, not the full 32 bits
+//
+#define DESTINATION_CPU_0 (ULONG) (1 << DESTINATION_SHIFT)
+#define DESTINATION_ALL_CPUS (ULONG) (0xff << DESTINATION_SHIFT)
+
+/*
+endif
+
+; APIC defines for assembly code
+; BE SURE TO CHANGE THESE VALUES IN BOTH TABLES!
+;
+
+IO_REGISTER_SELECT equ 00000000H ;
+IO_REGISTER_WINDOW equ 00000010H ;
+
+IO_ID_REGISTER equ 00000000H ;
+IO_VERS_REGISTER equ 00000001H ;
+IO_ARB_ID_REGISTER equ 00000002H ;
+IO_REDIR_00_LOW equ 00000010H ;
+IO_REDIR_00_HIGH equ 00000011H ;
+
+IO_MAX_REDIR_MASK equ 00FF0000H ;
+IO_VERSION_MASK equ 000000FFH ;
+
+LU_ID_REGISTER equ 00000020H ;
+LU_VERS_REGISTER equ 00000030H ;
+LU_TPR equ 00000080H ;
+LU_APR equ 00000090H ;
+LU_PPR equ 000000A0H ;
+LU_EOI equ 000000B0H ;
+LU_REMOTE_REGISTER equ 000000C0H ;
+
+LU_LOGICAL_DEST equ 000000D0H ;
+LU_LOGICAL_DEST_MASK equ 0FF000000H ;
+
+LU_DEST_FORMAT equ 000000E0H ;
+LU_DEST_FORMAT_MASK equ 0F0000000H ;
+LU_DEST_FORMAT_FLAT equ 0FFFFFFFFH ;
+
+LU_SPURIOUS_VECTOR equ 000000F0H ;
+LU_FAULT_VECTOR equ 00000370H ;
+LU_UNIT_ENABLED equ 00000100H ;
+LU_UNIT_DISABLED equ 00000000H ;
+
+LU_ISR_0 equ 00000100H ;
+LU_TMR_0 equ 00000180H ;
+LU_IRR_0 equ 00000200H ;
+LU_ERROR_STATUS equ 00000280H ;
+LU_INT_CMD_LOW equ 00000300H ;
+LU_INT_CMD_HIGH equ 00000310H ;
+LU_TIMER_VECTOR equ 00000320H ;
+LU_INT_VECTOR_0 equ 00000350H ; TEMPORARY - do not use
+LU_INT_VECTOR_1 equ 00000360H ; TEMPORARY - do not use
+LU_INITIAL_COUNT equ 00000380H ;
+LU_CURRENT_COUNT equ 00000390H ;
+
+LU_DIVIDER_CONFIG equ 000003E0H ;
+LU_DIVIDE_BY_1 equ 0000000BH ;
+LU_DIVIDE_BY_2 equ 00000000H ;
+LU_DIVIDE_BY_4 equ 00000001H ;
+LU_DIVIDE_BY_8 equ 00000002H ;
+LU_DIVIDE_BY_16 equ 00000003H ;
+LU_DIVIDE_BY_32 equ 00000008H ;
+LU_DIVIDE_BY_64 equ 00000009H ;
+LU_DIVIDE_BY_128 equ 0000000AH ;
+
+APIC_ID_MASK equ 0F000000H ;
+APIC_ID_SHIFT equ 24 ;
+
+INT_VECTOR_MASK equ 000000FFH ;
+RESERVED_HIGH_INT equ 000000F8H ;
+DELIVERY_MODE_MASK equ 00000700H ;
+DELIVER_FIXED equ 00000000H ;
+DELIVER_LOW_PRIORITY equ 00000100H ;
+DELIVER_SMI equ 00000200H ;
+DELIVER_REMOTE_READ equ 00000300H ;
+DELIVER_NMI equ 00000400H ;
+DELIVER_INIT equ 00000500H ;
+DELIVER_STARTUP equ 00000600H ;
+DELIVER_EXTINT equ 00000700H ;
+PHYSICAL_DESTINATION equ 00000000H ;
+LOGICAL_DESTINATION equ 00000800H ;
+DELIVERY_PENDING equ 00001000H ;
+ACTIVE_LOW equ 00002000H ;
+ACTIVE_HIGH equ 00000000H ;
+REMOTE_IRR equ 00004000H ;
+LEVEL_TRIGGERED equ 00008000H ;
+EDGE_TRIGGERED equ 00000000H ;
+INTERRUPT_MASKED equ 00010000H ;
+INTERRUPT_MOT_MASKED equ 00000000H ;
+PERIODIC_TIMER equ 00020000H ;
+
+ICR_LEVEL_ASSERTED equ 00004000H ;
+ICR_LEVEL_DEASSERTED equ 00000000H ;
+ICR_RR_STATUS_MASK equ 00030000H ;
+ICR_RR_INVALID equ 00000000H ;
+ICR_RR_IN_PROGRESS equ 00010000H ;
+ICR_RR_VALID equ 00020000H ;
+ICR_SHORTHAND_MASK equ 000C0000H ;
+ICR_USE_DEST_FIELD equ 00000000H ;
+ICR_SELF equ 00040000H ;
+ICR_ALL_INCL_SELF equ 00080000H ;
+ICR_ALL_EXCL_SELF equ 000C0000H ;
+
+DESTINATION_MASK equ 0FF000000H ;
+DESTINATION_SHIFT equ 24 ; shift count for dest. mask
+;
+; APIC IO unit redirection table, interrupt destination field: this field
+; is 32 bits for the 82489DX APIC; future APIC implementations will put the
+; destination field in the upper 8 bits of the entry, not the full 32 bits
+;
+DESTINATION_CPU_0 equ 1 SHL DESTINATION_SHIFT
+DESTINATION_ALL_CPUS equ 0FFH SHL DESTINATION_SHIFT
+
+;*/
diff --git a/private/ntos/nthals/halmps/i386/halnls.h b/private/ntos/nthals/halmps/i386/halnls.h
new file mode 100644
index 000000000..93d6e2968
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/halmps/i386/halp.h b/private/ntos/nthals/halmps/i386/halp.h
new file mode 100644
index 000000000..a9e4b7542
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/halp.h
@@ -0,0 +1,15 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\halp.h"
+
+// #define NT_35 1 // build hal for NT 3.5
+
+#ifdef NT_35
+#undef ALLOC_PRAGMA
+#undef MmLockPagableCodeSection(a)
+#undef MmUnlockPagableImageSection(a)
+#define MmLockPagableCodeSection(a) NULL
+#define MmUnlockPagableImageSection(a)
+#endif
diff --git a/private/ntos/nthals/halmps/i386/ix8259.inc b/private/ntos/nthals/halmps/i386/ix8259.inc
new file mode 100644
index 000000000..978078dce
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halmps/i386/ixaddr.c b/private/ntos/nthals/halmps/i386/ixaddr.c
new file mode 100644
index 000000000..9c9491d45
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixaddr.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixaddr.c"
diff --git a/private/ntos/nthals/halmps/i386/ixbeep.asm b/private/ntos/nthals/halmps/i386/ixbeep.asm
new file mode 100644
index 000000000..abc3b19aa
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halmps/i386/ixbusdat.c b/private/ntos/nthals/halmps/i386/ixbusdat.c
new file mode 100644
index 000000000..3a3847088
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halmps/i386/ixcmos.asm b/private/ntos/nthals/halmps/i386/ixcmos.asm
new file mode 100644
index 000000000..593bbc153
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halmps/i386/ixcmos.inc b/private/ntos/nthals/halmps/i386/ixcmos.inc
new file mode 100644
index 000000000..7dc545361
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halmps/i386/ixdat.c b/private/ntos/nthals/halmps/i386/ixdat.c
new file mode 100644
index 000000000..4fecf2c05
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halmps/i386/ixenvirv.c b/private/ntos/nthals/halmps/i386/ixenvirv.c
new file mode 100644
index 000000000..9c3105723
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halmps/i386/ixfirm.c b/private/ntos/nthals/halmps/i386/ixfirm.c
new file mode 100644
index 000000000..e5f5224a1
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halmps/i386/ixhwsup.c b/private/ntos/nthals/halmps/i386/ixhwsup.c
new file mode 100644
index 000000000..8f0f81536
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halmps/i386/ixidle.asm b/private/ntos/nthals/halmps/i386/ixidle.asm
new file mode 100644
index 000000000..afdd2bc82
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halmps/i386/ixinfo.c b/private/ntos/nthals/halmps/i386/ixinfo.c
new file mode 100644
index 000000000..d2ec5c2a7
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halmps/i386/ixisa.h b/private/ntos/nthals/halmps/i386/ixisa.h
new file mode 100644
index 000000000..db3e40a6c
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halmps/i386/ixisabus.c b/private/ntos/nthals/halmps/i386/ixisabus.c
new file mode 100644
index 000000000..9ec02b377
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixisabus.c
@@ -0,0 +1,6 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+//
+
+#include "..\..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halmps/i386/ixisasup.c b/private/ntos/nthals/halmps/i386/ixisasup.c
new file mode 100644
index 000000000..bc3621c8b
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixisasup.c
@@ -0,0 +1,7 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#ifndef MCA
+#include "..\..\halx86\i386\ixisasup.c"
+#endif
diff --git a/private/ntos/nthals/halmps/i386/ixkdcom.c b/private/ntos/nthals/halmps/i386/ixkdcom.c
new file mode 100644
index 000000000..87ab015af
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halmps/i386/ixkdcom.h b/private/ntos/nthals/halmps/i386/ixkdcom.h
new file mode 100644
index 000000000..a028acfb9
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halmps/i386/ixmca.c b/private/ntos/nthals/halmps/i386/ixmca.c
new file mode 100644
index 000000000..9da2bc023
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixmca.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixmca.c"
diff --git a/private/ntos/nthals/halmps/i386/ixmca.h b/private/ntos/nthals/halmps/i386/ixmca.h
new file mode 100644
index 000000000..f49d38933
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixmca.h
@@ -0,0 +1,6 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#include "..\..\halmca\i386\ixmca.h"
+
diff --git a/private/ntos/nthals/halmps/i386/ixmcaa.asm b/private/ntos/nthals/halmps/i386/ixmcaa.asm
new file mode 100644
index 000000000..8dedd8e01
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixmcaa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\ixmcaa.asm
diff --git a/private/ntos/nthals/halmps/i386/ixmcabus.c b/private/ntos/nthals/halmps/i386/ixmcabus.c
new file mode 100644
index 000000000..686ac927b
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixmcabus.c
@@ -0,0 +1,8 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#ifdef MCA
+#include "..\..\halmca\i386\ixmcabus.c"
+#endif
+
diff --git a/private/ntos/nthals/halmps/i386/ixmcasup.c b/private/ntos/nthals/halmps/i386/ixmcasup.c
new file mode 100644
index 000000000..e968a400d
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixmcasup.c
@@ -0,0 +1,8 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#ifdef MCA
+#include "..\..\halmca\i386\ixmcasup.c"
+#endif
+
diff --git a/private/ntos/nthals/halmps/i386/ixnmi.c b/private/ntos/nthals/halmps/i386/ixnmi.c
new file mode 100644
index 000000000..4947c8856
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/halmps/i386/ixpcibrd.c b/private/ntos/nthals/halmps/i386/ixpcibrd.c
new file mode 100644
index 000000000..48dacf825
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixpcibrd.c
@@ -0,0 +1,7 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#define SUBCLASSPCI 1
+
+#include "..\..\halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/halmps/i386/ixpcibus.c b/private/ntos/nthals/halmps/i386/ixpcibus.c
new file mode 100644
index 000000000..9249cc699
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixpcibus.c
@@ -0,0 +1,7 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#define SUBCLASSPCI 1
+
+#include "..\..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/halmps/i386/ixpciint.c b/private/ntos/nthals/halmps/i386/ixpciint.c
new file mode 100644
index 000000000..b51766a59
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixpciint.c
@@ -0,0 +1,7 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#define SUBCLASSPCI 1
+
+#include "..\..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/halmps/i386/ixphwsup.c b/private/ntos/nthals/halmps/i386/ixphwsup.c
new file mode 100644
index 000000000..171ac1524
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halmps/i386/ixreboot.c b/private/ntos/nthals/halmps/i386/ixreboot.c
new file mode 100644
index 000000000..bbf8a5932
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halmps/i386/ixthunk.c b/private/ntos/nthals/halmps/i386/ixthunk.c
new file mode 100644
index 000000000..b35e01061
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halmps/i386/ixusage.c b/private/ntos/nthals/halmps/i386/ixusage.c
new file mode 100644
index 000000000..9e24322d8
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halmps/i386/mpaddr.c b/private/ntos/nthals/halmps/i386/mpaddr.c
new file mode 100644
index 000000000..69692592a
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpaddr.c
@@ -0,0 +1,812 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+All rights reserved
+
+Module Name:
+
+ mpaddr.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+*/
+
+#include "halp.h"
+#include "apic.inc"
+#include "pcmp_nt.inc"
+
+#if DEBUGGING
+#include "stdio.h"
+#endif
+
+#define STATIC // functions used internal to this module
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+extern struct HalpMpInfo HalpMpInfoTable;
+extern USHORT HalpIoCompatibleRangeList0[];
+extern USHORT HalpIoCompatibleRangeList1[];
+extern BOOLEAN HalpPciLockSettings;
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+// --------------------------------------------------------------------
+
+BOOLEAN
+HalpMPSBusId2NtBusId (
+ IN UCHAR ApicBusId,
+ OUT PPCMPBUSTRANS *ppBusType,
+ OUT PULONG BusNo
+ );
+
+VOID
+HalpInitBusAddressMapInfo (
+ VOID
+ );
+
+STATIC PSUPPORTED_RANGES
+HalpBuildBusAddressMap (
+ IN UCHAR MpsBusId
+ );
+
+PBUS_HANDLER
+HalpLookupCreateHandlerForBus (
+ IN PPCMPBUSTRANS pBusType,
+ IN ULONG BusNo
+ );
+
+NTSTATUS
+HalpMpsAddEisaBus (
+ PBUS_HANDLER Bus
+ );
+
+NTSTATUS
+HalpMpsAddPciBus (
+ PBUS_HANDLER Bus
+ );
+
+VOID
+HalpInheritBusAddressMapInfo (
+ VOID
+ );
+
+VOID
+HalpMPSPCIChildren (
+ VOID
+ );
+
+STATIC PSUPPORTED_RANGES
+HalpMergeRangesFromParent (
+ PSUPPORTED_RANGES CurrentList,
+ UCHAR MpsBusId
+ );
+
+
+#if DEBUGGING
+VOID
+HalpDisplayBusInformation (
+ PBUS_HANDLER Bus
+ );
+#endif
+
+//
+// Internal prototypes
+//
+
+struct {
+ ULONG Offset;
+ UCHAR MpsType;
+} HalpMpsRangeList[] = {
+ FIELD_OFFSET (SUPPORTED_RANGES, IO), MPS_ADDRESS_MAP_IO,
+ FIELD_OFFSET (SUPPORTED_RANGES, Memory), MPS_ADDRESS_MAP_MEMORY,
+ FIELD_OFFSET (SUPPORTED_RANGES, PrefetchMemory),MPS_ADDRESS_MAP_PREFETCH_MEMORY,
+ FIELD_OFFSET (SUPPORTED_RANGES, Dma), MPS_ADDRESS_MAP_UNDEFINED,
+ 0, MPS_ADDRESS_MAP_UNDEFINED
+ };
+
+#define RANGE_LIST(a,i) ((PSUPPORTED_RANGE) ((PUCHAR) a + HalpMpsRangeList[i].Offset))
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitBusAddressMapInfo)
+#pragma alloc_text(INIT,HalpBuildBusAddressMap)
+#pragma alloc_text(INIT,HalpInheritBusAddressMapInfo)
+#pragma alloc_text(INIT,HalpMergeRangesFromParent)
+#pragma alloc_text(INIT,HalpLookupCreateHandlerForBus)
+#pragma alloc_text(INIT,HalpMpsAddEisaBus)
+#pragma alloc_text(INIT,HalpMpsAddPciBus)
+#pragma alloc_text(PAGE,HalpAllocateNewRangeList)
+#pragma alloc_text(PAGE,HalpFreeRangeList)
+#endif
+
+
+VOID
+HalpInitBusAddressMapInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Reads MPS bus addressing mapping table, and builds/replaces the
+ supported address range mapping for the given bus.
+
+ Note there's a little slop in this function as it doesn't reclaim
+ memory allocated before this function is called, which it replaces
+ pointers too.
+
+--*/
+{
+ ULONG BusNo;
+ PPCMPBUSTRANS pBusType;
+ PMPS_EXTENTRY ExtTable2, ExtTable;
+ PBUS_HANDLER Handler;
+ PSUPPORTED_RANGES Addresses;
+ ULONG i;
+ BOOLEAN Processed;
+
+ //
+ // Check for any address mapping information for the buses
+ //
+ // Note: We assume that if any MPS bus address map information
+ // is found for a bus, that the MPS bios will supply all the
+ // valid IO, Memory, and prefetch memory addresses for that BUS.
+ // The bios can not supply some address tyeps for a given bus
+ // without supplying them all.
+ //
+
+ ExtTable = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) {
+
+ //
+ // Is this an address map entry?
+ //
+
+ if (ExtTable->Type == EXTTYPE_BUS_ADDRESS_MAP) {
+
+ //
+ // See if this bus has already been processed
+ //
+
+ Processed = FALSE;
+ ExtTable2 = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable2 < ExtTable) {
+ if (ExtTable2->Type == EXTTYPE_BUS_ADDRESS_MAP &&
+ ExtTable2->u.AddressMap.BusId == ExtTable->u.AddressMap.BusId) {
+ Processed = TRUE;
+ break;
+ }
+ ExtTable2 = (PMPS_EXTENTRY) (((PUCHAR) ExtTable2) + ExtTable2->Length);
+ }
+
+ //
+ // Determine the NT bus this map info is for
+ //
+
+ if (!Processed &&
+ HalpMPSBusId2NtBusId (ExtTable->u.AddressMap.BusId, &pBusType, &BusNo)) {
+
+ //
+ // Lookup the bushander for the bus
+ //
+
+ Handler = HalpLookupCreateHandlerForBus (pBusType, BusNo);
+
+ if (Handler) {
+
+ //
+ // NOTE: Until we get better kernel PnP support, for now
+ // limit the ability of the system to move already BIOS
+ // initialized devices. This is needed because the exteneded
+ // express BIOS can't give the OS any breathing space when
+ // it hands bus supported ranges, and there's currently not
+ // an interface to the kernel to obtain current PCI device
+ // settings. (fixed in the future.)
+ //
+
+ HalpPciLockSettings = TRUE;
+
+ //
+ // Build BusAddress Map for this MPS bus
+ //
+
+ Addresses = HalpBuildBusAddressMap (ExtTable->u.AddressMap.BusId);
+
+ //
+ // Consoladate ranges
+ //
+
+ HalpConsolidateRanges (Addresses);
+
+ //
+ // Use current ranges for any undefined MPS ranges
+ //
+
+ for (i=0; HalpMpsRangeList[i].Offset; i++) {
+ if (HalpMpsRangeList[i].MpsType == MPS_ADDRESS_MAP_UNDEFINED) {
+ *RANGE_LIST(Addresses,i) = *RANGE_LIST(Handler->BusAddresses, i);
+ }
+ }
+
+ //
+ // Set bus'es support addresses
+ //
+
+ Handler->BusAddresses = Addresses;
+
+ } else {
+
+ DBGMSG ("HAL: Initialize BUS address map - bus not an registered NT bus\n");
+
+ }
+ }
+ }
+
+ ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length);
+ }
+}
+
+
+STATIC PSUPPORTED_RANGES
+HalpBuildBusAddressMap (
+ IN UCHAR MpsBusId
+ )
+/*++
+
+Routine Description:
+
+ Builds a SUPPORT_RANGES list for the supplied Mps Bus Id, by
+ MPS bus addressing mapping descriptors.
+
+ Note this function does not include any information contained
+ in the MPS bus hierarchy descriptors.
+
+Arguments:
+
+ MpsBusId - mps bus id of bus to build address map for.
+
+Return:
+
+ The bus'es supported ranges as defined by the MPS bus
+ address mapping descriptors
+
+--*/
+{
+ PMPS_EXTENTRY ExtTable;
+ PSUPPORTED_RANGES Addresses;
+ PSUPPORTED_RANGE HRange, Range;
+ ULONG i, j, k;
+ ULONG Base, Limit, AddressSpace;
+ PUSHORT CompatibleList;
+
+ Addresses = HalpAllocateNewRangeList();
+
+ ExtTable = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) {
+
+ //
+ // Is this an address map entry for the proper bus?
+ //
+
+ if (ExtTable->Type == EXTTYPE_BUS_ADDRESS_MAP &&
+ ExtTable->u.AddressMap.BusId == MpsBusId) {
+
+ //
+ // Find range type
+ //
+
+ for (i=0; HalpMpsRangeList[i].Offset; i++) {
+ if (HalpMpsRangeList[i].MpsType == ExtTable->u.AddressMap.Type) {
+ HRange = RANGE_LIST(Addresses, i);
+ break;
+ }
+ }
+
+ AddressSpace = HalpMpsRangeList[i].MpsType == MPS_ADDRESS_MAP_IO ? 1 : 0;
+ if (HalpMpsRangeList[i].Offset) {
+ HalpAddRange (
+ HRange,
+ AddressSpace,
+ 0, // SystemBase
+ ExtTable->u.AddressMap.Base,
+ ExtTable->u.AddressMap.Base + ExtTable->u.AddressMap.Length - 1
+ );
+
+ } else {
+
+ DBGMSG ("HALMPS: Unkown address range type in MPS table\n");
+
+ }
+ }
+
+ ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length);
+ }
+
+ //
+ // See if the BIOS wants to modify the buses supported addresses with
+ // some pre-defined default information. (yes, another case where the
+ // bios wants to be lazy.)
+ //
+
+ ExtTable = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) {
+
+ //
+ // Is this an CompatibleMap entry for the proper bus?
+ //
+
+ if (ExtTable->Type == EXTTYPE_BUS_COMPATIBLE_MAP &&
+ ExtTable->u.CompatibleMap.BusId == MpsBusId) {
+
+ //
+ // All currently defined default tables are for IO ranges,
+ // we'll use that assumption here.
+ //
+
+ i = 0;
+ ASSERT (HalpMpsRangeList[i].MpsType == MPS_ADDRESS_MAP_IO);
+ HRange = RANGE_LIST(Addresses, i);
+ AddressSpace = 1;
+
+ CompatibleList = NULL;
+ switch (ExtTable->u.CompatibleMap.List) {
+ case 0: CompatibleList = HalpIoCompatibleRangeList0; break;
+ case 1: CompatibleList = HalpIoCompatibleRangeList1; break;
+ default: DBGMSG ("HAL: Unknown compatible range list\n"); break;
+ }
+
+ for (j=0; j < 0x10; j++) {
+ for (k=0; CompatibleList[k]; k += 2) {
+ Base = (j << 12) | CompatibleList[k];
+ Limit = (j << 12) | CompatibleList[k+1];
+
+ if (ExtTable->u.CompatibleMap.Modifier) {
+
+ HalpRemoveRange (HRange, Base, Limit);
+
+ } else {
+
+ HalpAddRange (HRange, AddressSpace, 0, Base, Limit);
+
+ }
+ }
+ }
+
+ }
+ ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length);
+ }
+
+ return Addresses;
+}
+
+NTSTATUS
+HalpAddEisaBus (
+ PBUS_HANDLER Bus
+ )
+/*++
+
+Routine Description:
+
+ Adds another EISA bus handler to the system.
+ Note: this is used for ISA buses as well - they are added as eisa
+ buses, then cloned into isa bus handlers
+
+--*/
+{
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0xFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 1;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+HalpAddPciBus (
+ PBUS_HANDLER Bus
+ )
+{
+ //
+ // The firmware should have informed NT how many PCI buses
+ // there where at NtDetect time
+ //
+
+ DBGMSG ("HAL: BIOS problem. PCI bus must be report via IS_PCI_PRESENT bios call\n");
+ return STATUS_UNSUCCESSFUL;
+}
+
+PBUS_HANDLER
+HalpLookupCreateHandlerForBus (
+ IN PPCMPBUSTRANS pBusType,
+ IN ULONG BusNo
+ )
+{
+ NTSTATUS Status;
+ PBUS_HANDLER Handler;
+
+ Handler = HaliHandlerForBus (pBusType->NtType, BusNo);
+
+ if (!Handler && pBusType->NewInstance) {
+
+ //
+ // This bus does not exist, but we know how to add it.
+ //
+
+ Status = HalRegisterBusHandler (
+ pBusType->NtType,
+ pBusType->NtConfig,
+ BusNo,
+ Internal, // parent bus
+ 0,
+ pBusType->BusExtensionSize,
+ pBusType->NewInstance,
+ &Handler
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ Handler = NULL;
+ }
+ }
+
+ return Handler;
+}
+
+
+
+VOID
+HalpInheritBusAddressMapInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Reads MPS bus hierarchy descriptors and inherits any implied bus
+ address mapping information.
+
+ Note there's a little slop in this function as it doesn't reclaim
+ memory allocated before this function is called, which it replaces
+ pointers too.
+
+--*/
+{
+ ULONG BusNo, i, j;
+ PPCMPBUSTRANS pBusType;
+ PMPS_EXTENTRY ExtTable;
+ PBUS_HANDLER Bus, Bus2;
+ PSUPPORTED_RANGES Addresses;
+ PUCHAR p;
+
+ //
+ // Search for any bus hierarchy descriptors and inherit supported address
+ // ranges accordingly.
+ //
+
+ ExtTable = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) {
+
+ //
+ // Is this a bus hierarchy descriptor?
+ //
+
+ if (ExtTable->Type == EXTTYPE_BUS_HIERARCHY) {
+
+ //
+ // Determine the NT bus
+ //
+
+ if (HalpMPSBusId2NtBusId (ExtTable->u.BusHierarchy.BusId, &pBusType, &BusNo)) {
+
+ Bus = HalpLookupCreateHandlerForBus (pBusType, BusNo);
+
+ if (Bus) {
+ //
+ // Get ranges from parent
+ //
+
+ Addresses = HalpMergeRangesFromParent (
+ Bus->BusAddresses,
+ ExtTable->u.BusHierarchy.ParentBusId
+ );
+
+ //
+ // Set bus'es support addresses
+ //
+
+ Bus->BusAddresses = HalpConsolidateRanges (Addresses);
+
+ } else {
+
+ DBGMSG ("HAL: Inherit BUS address map - bus not an registered NT bus\n");
+ }
+
+ } else {
+
+ DBGMSG ("HAL: Inherit BUS address map - unkown MPS bus type\n");
+ }
+ }
+
+ ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length);
+ }
+
+ //
+ // Clone EISA bus ranges to matching ISA buses
+ //
+
+ BusNo = 0;
+ for (; ;) {
+ Bus = HaliHandlerForBus(Eisa, BusNo);
+ Bus2 = HaliHandlerForBus(Isa , BusNo);
+
+ if (!Bus) {
+ break;
+ }
+
+ if (!Bus2) {
+ //
+ // Matching ISA bus didn't exist, create it
+ //
+
+ HalRegisterBusHandler (
+ Isa,
+ ConfigurationSpaceUndefined,
+ BusNo,
+ Eisa, // parent bus
+ BusNo,
+ 0,
+ NULL,
+ &Bus2
+ );
+
+ Bus2->GetBusData = HalpNoBusData;
+ Bus2->TranslateBusAddress = HalpTranslateIsaBusAddress;
+ }
+
+ //
+ // Copy its parent bus ranges
+ //
+
+ Addresses = HalpCopyRanges (Bus->BusAddresses);
+
+ //
+ // Pull out memory ranges above the isa 24 bit supported ranges
+ //
+
+ HalpRemoveRange (
+ &Addresses->Memory,
+ 0x1000000,
+ 0x7FFFFFFFFFFFFFFF
+ );
+
+ HalpRemoveRange (
+ &Addresses->PrefetchMemory,
+ 0x1000000,
+ 0x7FFFFFFFFFFFFFFF
+ );
+
+ Bus2->BusAddresses = HalpConsolidateRanges (Addresses);
+ BusNo += 1;
+ }
+
+ //
+ // Inherit any implied interrupt routing from parent PCI buses
+ //
+
+ HalpMPSPCIChildren ();
+
+#if DBG
+ HalpDisplayAllBusRanges ();
+#endif
+}
+
+STATIC PSUPPORTED_RANGES
+HalpMergeRangesFromParent (
+ IN PSUPPORTED_RANGES CurrentList,
+ IN UCHAR MpsBusId
+ )
+/*++
+Routine Description:
+
+ Shrinks this CurrentList to include only the ranges also
+ supported by the supplied MPS bus id.
+
+
+Arguments:
+
+ CurrentList - Current supported range list
+ MpsBusId - mps bus id of bus to merge with
+
+Return:
+
+ The bus'es supported ranges as defined by the orignal list,
+ shrunk by all parents buses supported ranges as defined by
+ the MPS hierarchy descriptors
+
+--*/
+{
+ ULONG BusNo;
+ PPCMPBUSTRANS pBusType;
+ PMPS_EXTENTRY ExtTable;
+ PBUS_HANDLER Bus;
+ PSUPPORTED_RANGES NewList, MergeList, MpsBusList;
+ BOOLEAN FoundParentBus;
+ ULONG i;
+
+ FoundParentBus = FALSE;
+ MergeList = NULL;
+ MpsBusList = NULL;
+
+ //
+ // Determine the NT bus
+ //
+
+ if (HalpMPSBusId2NtBusId (MpsBusId, &pBusType, &BusNo)) {
+
+ //
+ // Lookup the bushander for the bus
+ //
+
+ Bus = HaliHandlerForBus (pBusType->NtType, BusNo);
+ if (Bus) {
+ MergeList = Bus->BusAddresses;
+ }
+ }
+
+ //
+ // If NT bus not found, use supported range list from MPS bus
+ // address map descriptors
+ //
+
+ if (!MergeList) {
+ MpsBusList = HalpBuildBusAddressMap(MpsBusId);
+ MergeList = MpsBusList;
+ }
+
+ //
+ // If no list to merge with use CurrentList
+ //
+
+ if (!MergeList) {
+ return CurrentList;
+ }
+
+
+ if (!CurrentList) {
+
+ //
+ // If no CurrentList, then nothing to merge with
+ //
+
+ NewList = HalpCopyRanges (MergeList);
+
+ } else {
+
+ //
+ // Merge lists together and build a new list
+ //
+
+ NewList = HalpMergeRanges (
+ CurrentList,
+ MergeList
+ );
+
+ //
+ // MPS doesn't define DMA ranges, so we don't
+ // merge those down.. Add valid DMA ranges back
+ //
+
+ HalpAddRangeList (&NewList->Dma, &CurrentList->Dma);
+ }
+
+
+ //
+ // See if bus has parent bus listed in the bus hierarchy descriptors
+ //
+
+ ExtTable = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) {
+
+ if (ExtTable->Type == EXTTYPE_BUS_HIERARCHY &&
+ ExtTable->u.BusHierarchy.BusId == MpsBusId) {
+
+ //
+ // BIOS can only list one parent per bus
+ //
+
+ ASSERT (FoundParentBus == FALSE);
+ FoundParentBus = TRUE;
+
+ //
+ // Merge current list with parent's supported range list
+ //
+
+ CurrentList = NewList;
+ NewList = HalpMergeRangesFromParent (
+ CurrentList,
+ ExtTable->u.BusHierarchy.ParentBusId
+ );
+
+ //
+ // Free old list
+ //
+
+ HalpFreeRangeList (CurrentList);
+ }
+
+ ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length);
+ }
+
+ //
+ // Clean up
+ //
+
+ if (MpsBusList) {
+ HalpFreeRangeList (MpsBusList);
+ }
+
+ return NewList;
+}
diff --git a/private/ntos/nthals/halmps/i386/mpclock.asm b/private/ntos/nthals/halmps/i386/mpclock.asm
new file mode 100644
index 000000000..33bc37430
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpclock.asm
@@ -0,0 +1,1000 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+;
+; Module Name:
+;
+; mpclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ron Mosgrove (Intel) Aug 1993
+; Modified to support PC+MP Systems
+;--
+
+.586p
+ .xlist
+include hal386.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\pcmp_nt.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _HalSetProfileInterval ,1
+
+ EXTRNP _HalpSetInitialClockRate,0
+
+ EXTRNP _HalpMcaQueueDpc, 0
+
+ extrn _HalpRtcTimeIncrements:DWORD
+ extrn _HalpGlobal8259Mask:WORD
+ extrn _HalpMpInfoTable:DWORD
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+CMOS_STATUS_BUSY EQU 80H ; Time update in progress
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+;
+; RegisterAInitByte sets 8Hz clock rate, used during init to set up
+; KeStallExecutionProcessor, etc. (See RegASystemClockByte below.)
+;
+
+RegisterAInitByte EQU 00101101B ; RT/CMOS Register 'A' init byte
+ ; 32.768KHz Base divider rate
+ ; 8Hz int rate, period = 125.0ms
+PeriodInMicroSecond EQU 125000 ;
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; There is a "C" version of this structure in MPCLOCKC.C
+;
+
+TimeStrucSize EQU 20
+
+RtcTimeIncStruc struc
+ RTCRegisterA dd 0 ;The RTC register A value for this rate
+ RateIn100ns dd 0 ;This rate in multiples of 100ns
+ RateAdjustmentNs dd 0 ;Error Correction (in ns)
+ RateAdjustmentCnt dd 0 ;Error Correction (as a fraction of 256)
+ IpiRate dd 0 ;IPI Rate Count (as a fraction of 256)
+RtcTimeIncStruc ends
+
+ifdef DBGSSF
+DebugSSFStruc struc
+ SSFCount1 dd 0
+ SSFCount2 dd 0
+ SSFRdtsc1 dd 0
+ SSFRdtsc2 dd 0
+ SSFRdtsc3 dd 0
+
+ SSFRna1 dd 0
+ SSFRna2 dd 0
+ SSFRna3 dd 0
+
+DebugSSFStruc ends
+
+ public HalpDbgSSF
+HalpDbgSSF db (size DebugSSFStruc) * 10 dup (0)
+
+endif
+
+ ALIGN dword
+
+ public RTCClockFreq
+ public RegisterAClockValue
+
+RTCClockFreq dd 156250
+RegisterAClockValue dd 00101010B ; default interval = 15.6250 ms
+
+MINIMUM_STALL_FACTOR EQU 10H ; Reasonable Minimum
+
+ public HalpP0StallFactor
+HalpP0StallFactor dd MINIMUM_STALL_FACTOR
+ public HalpInitStallComputedCount
+HalpInitStallComputedCount dd 0
+ public HalpInitStallLoopCount
+HalpInitStallLoopCount dd 0
+
+ ALIGN dword
+;
+; Clock Rate Adjustment Counter. This counter is used to keep a tally of
+; adjustments needed to be applied to the RTC rate as passed to the
+; kernel.
+;
+
+ public _HalpCurrentRTCRegisterA, _HalpCurrentClockRateIn100ns
+ public _HalpCurrentClockRateAdjustment, _HalpCurrentIpiRate
+ public _HalpIpiRateCounter, _HalpNextRate, _HalpPendingRate
+ public _HalpRateAdjustment
+_HalpCurrentRTCRegisterA dd 0
+_HalpCurrentClockRateIn100ns dd 0
+_HalpCurrentClockRateAdjustment dd 0
+_HalpCurrentIpiRate dd 0
+_HalpIpiRateCounter dd 0
+_HalpNextRate dd 0
+_HalpPendingRate dd 0
+_HalpRateAdjustment dd 0
+
+
+;
+; Inti value for the RTC
+;
+ public _HalpRTCApic, _HalpRTCInti
+_HalpRTCApic dd 0
+_HalpRTCInti dd 0
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+; This is no longer used here but ixbeep needs it declared.
+;
+ public _Halp8254Lock
+
+_Halp8254Lock dd 0
+
+;
+; Flag to tell clock routine when P0 can Ipi Other processors
+;
+
+ public _HalpIpiClock
+_HalpIpiClock dd 0
+
+ public _HalpClockWork, _HalpClockSetMSRate, _HalpClockMcaQueueDpc
+_HalpClockWork label dword
+ _HalpClockSetMSRate db 0
+ _HalpClockMcaQueueDpc db 0
+ _bReserved1 db 0
+ _bReserved2 db 0
+
+_DATA ends
+
+
+INIT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using RTC to generate an
+; interrupt at every 15.6250 ms interval at APIC_CLOCK_VECTOR
+;
+; See the definition of RegisterAClockValue if clock rate needs to be
+; changed.
+;
+; This routine assumes it runs during Phase 0 on P0.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock ,0
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+ stdCall _HalpSetInitialClockRate
+
+;
+; Set the interrupt rate to what is actually needed
+;
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov eax, _HalpCurrentRTCRegisterA
+ shl ax, 8
+ mov al, 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ popfd ; restore caller's eflag
+
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+ page ,132
+ subttl "Scale Apic Timer"
+;++
+;
+; VOID
+; HalpScaleTimers (
+; IN VOID
+; )
+;
+; Routine Description:
+;
+; Determines the frequency of the APIC timer. This routine is run
+; during initialization
+;
+;
+;--
+
+cPublicProc _HalpScaleTimers ,0
+ push ebx
+ push esi
+ push edi
+
+;
+; Don't let anyone in until we've finished here
+;
+ stdCall _HalpAcquireCmosSpinLock
+
+;
+; Protect us from interrupts
+;
+ pushfd
+ cli
+
+;
+; First set up the Local Apic Counter
+;
+; The following code assumes the CPU clock will never
+; exceed 4Ghz. For the short term this is probably OK
+;
+
+;
+; Configure the APIC timer
+;
+
+APIC_TIMER_DISABLED equ (INTERRUPT_MASKED OR PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
+TIMER_ROUNDING equ 10000
+
+
+ mov dword ptr APIC[LU_TIMER_VECTOR], APIC_TIMER_DISABLED
+ mov dword ptr APIC[LU_DIVIDER_CONFIG], LU_DIVIDE_BY_1
+
+;
+; We're going to do this twice & take the second results
+;
+ mov esi, 2
+hst10:
+
+;
+; Make sure the write has occurred
+;
+ mov eax, dword ptr APIC[LU_DIVIDER_CONFIG]
+
+;
+; We don't care what the actual time is we are only interested
+; in seeing the UIP transition. We are garenteed a 1 sec interval
+; if we wait for the UIP bit to complete an entire cycle.
+
+;
+; We also don't much care which direction the transition we use is
+; as long as we wait for the same transition to read the APIC clock.
+; Just because it is most likely that when we begin the UIP bit will
+; be clear, we'll use the transition from !UIP to UIP.
+;
+
+;
+; Wait for the UIP bit to be cleared, this is our starting state
+;
+
+@@:
+ mov al, 0Ah ; Specify register A
+ CMOS_READ ; (al) = CMOS register A
+ test al, CMOS_STATUS_BUSY ; Is time update in progress?
+ jnz short @b ; if z, no, wait some more
+
+;
+; Wait for the UIP bit to get set
+;
+
+@@:
+ mov al, 0Ah ; Specify register A
+ CMOS_READ ; (al) = CMOS register A
+ test al, CMOS_STATUS_BUSY ; Is time update in progress?
+ jz short @b ; if z, no, wait some more
+
+;
+; At this point we found the UIP bit set, now set the initial
+; count. Once we write this register its value is copied to the
+; current count register and countdown starts or continues from
+; there
+;
+
+ xor eax, eax
+ cpuid ; fence
+
+
+ mov ecx, MsrTSC ; MSR of RDTSC
+ xor edx, edx
+ mov eax, edx
+ mov dword ptr APIC[LU_INITIAL_COUNT], 0FFFFFFFFH
+ wrmsr ; Clear TSC count
+
+;
+; Wait for the UIP bit to be cleared again
+;
+
+@@:
+ mov al, 0Ah ; Specify register A
+ CMOS_READ ; (al) = CMOS register A
+ test al, CMOS_STATUS_BUSY ; Is time update in progress?
+ jnz short @b ; if z, no, wait some more
+
+;
+; Wait for the UIP bit to get set
+;
+
+@@:
+ mov al, 0Ah ; Specify register A
+ CMOS_READ ; (al) = CMOS register A
+ test al, CMOS_STATUS_BUSY ; Is time update in progress?
+ jz short @b ; if z, no, wait some more
+
+;
+; The cycle is complete, we found the UIP bit set. Now read
+; the counters and compute the frequency. The frequency is
+; just the ticks counted which is the initial value minus
+; the current value.
+;
+
+ xor eax, eax
+ cpuid ; fence
+
+ rdtsc
+ mov ecx, dword ptr APIC[LU_CURRENT_COUNT]
+
+ dec esi ; if this is the first time
+ jnz hst10 ; around, go loop
+
+ mov PCR[PcHal.TSCHz], eax
+
+ mov eax, 0FFFFFFFFH
+ sub eax, ecx
+
+;
+; Round the Apic Timer Freq
+;
+
+ xor edx, edx ; (edx:eax) = dividend
+
+ mov ecx, TIMER_ROUNDING
+ div ecx ; now edx has remainder
+
+ cmp edx, TIMER_ROUNDING / 2
+ jle @f ; if less don't round
+ inc eax ; else round up
+@@:
+
+;
+; Multiply by the Rounding factor to get the rounded Freq
+;
+ mov ecx, TIMER_ROUNDING
+ xor edx, edx
+ mul ecx
+
+ mov dword ptr PCR[PcHal.ApicClockFreqHz], eax
+
+;
+; Round TSC freq
+;
+
+ mov eax, PCR[PcHal.TSCHz]
+ xor edx, edx
+
+ mov ecx, TIMER_ROUNDING
+ div ecx ; now edx has remainder
+
+ cmp edx, TIMER_ROUNDING / 2
+ jle @f ; if less don't round
+ inc eax ; else round up
+@@:
+ mov ecx, TIMER_ROUNDING
+ xor edx, edx
+ mul ecx
+
+ mov PCR[PcHal.TSCHz], eax
+
+;
+; Convert TSC to microseconds
+;
+
+ xor edx, edx
+ mov ecx, 1000000
+ div ecx ; Convert to microseconds
+
+ xor ecx, ecx
+ cmp ecx, edx ; any remainder?
+ adc eax, ecx ; Yes, add one
+
+ mov PCR[PcStallScaleFactor], eax
+
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Return Value is the timer frequency
+;
+
+ mov eax, dword ptr PCR[PcHal.ApicClockFreqHz]
+ mov PCR[PcHal.ProfileCountDown], eax
+
+;
+; Set the interrupt rate in the chip.
+;
+
+ mov dword ptr APIC[LU_INITIAL_COUNT], eax
+
+ popfd
+
+ pop edi
+ pop esi
+ pop ebx
+
+ stdRET _HalpScaleTimers
+stdENDP _HalpScaleTimers
+
+
+INIT ends
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 12]
+
+cPublicProc _KeStallExecutionProcessor ,1
+
+ push ebx
+ push edi
+
+;
+; Issue a CPUID to implement a "fence"
+;
+ xor eax, eax
+fence1: cpuid
+
+
+;
+; Get current TSC
+;
+
+ rdtsc
+
+ mov ebx, eax
+ mov edi, edx
+
+;
+; Determine ending TSC
+;
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ mul ecx
+
+ add ebx, eax
+ adc edi, edx
+
+;
+; Wait for ending TSC
+;
+
+kese10: rdtsc
+ cmp edi, edx
+ ja short kese10
+ jc short kese20
+ cmp ebx, eax
+ ja short kese10
+
+kese20: pop edi
+ pop ebx
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+
+cPublicProc _HalpRemoveFences
+ mov word ptr fence1, 0c98bh
+ stdRET _HalpRemoveFences
+stdENDP _HalpRemoveFences
+
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+
+APIC_ICR_CLOCK equ (DELIVER_FIXED OR ICR_ALL_EXCL_SELF OR APIC_CLOCK_VECTOR)
+
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+; dismiss interrupt and raise Irql
+;
+
+ push APIC_CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,APIC_CLOCK_VECTOR,esp>
+
+;
+; This is the RTC interrupt, so we have to clear the
+; interrupt flag on the RTC.
+;
+ stdCall _HalpAcquireCmosSpinLock
+
+;
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ mov eax, _HalpCurrentClockRateIn100ns
+ xor ebx, ebx
+
+ ;
+ ; Adjust the tick count as needed
+ ;
+
+ mov ecx, _HalpCurrentClockRateAdjustment
+ add byte ptr _HalpRateAdjustment, cl
+ adc eax, ebx
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; eax = time increment of this tick
+; ebx = 0
+;
+
+;
+; With an APIC Based System we will force a clock interrupt to all other
+; processors. This is not really an IPI in the NT sense of the word, it
+; uses the Local Apic to generate interrupts to other CPU's.
+;
+
+ifdef NT_UP
+
+ ; UP implemention, we don't care about IPI's here
+
+else ; ! NT_UP
+
+ ;
+ ; See if we need to IPI anyone, this happens only at the
+ ; Lowest supported frequency (ie the value KeSetTimeIncrement
+ ; is called with. We have a IPI Rate based upon the current
+ ; clock rate relative to the lowest clock rate.
+ ;
+
+ mov ecx, _HalpIpiRateCounter
+ add ecx, _HalpCurrentIpiRate
+ cmp ch, bl
+ mov byte ptr _HalpIpiRateCounter, cl
+ jz short HalpDontSendClockIpi ; No, Skip it
+
+ ;
+ ; Don't send vectors onto the APIC bus until at least one other
+ ; processor comes on line. Vectors placed on the bus will hang
+ ; around until someone picks them up.
+ ;
+
+ cmp _HalpIpiClock, ebx
+ je short HalpDontSendClockIpi
+
+ ;
+ ; At least one other processor is alive, send clock pulse to all
+ ; other processors
+ ;
+
+ ; We use a destination shorthand and therefore only needs to
+ ; write the lower 32 bits of the ICR.
+
+
+ pushfd
+ cli
+
+;
+; Now issue the Clock IPI Command by writing to the Memory Mapped Register
+;
+
+ STALL_WHILE_APIC_BUSY
+ mov dword ptr APIC[LU_INT_CMD_LOW], APIC_ICR_CLOCK
+
+ popfd
+
+HalpDontSendClockIpi:
+
+endif ; NT_UP
+;
+; Check for any more work
+;
+ cmp _HalpClockWork, ebx ; Any clock interrupt work desired?
+ jz _KeUpdateSystemTime@0 ; No, process tick
+
+ cmp _HalpClockMcaQueueDpc, bl
+ je short CheckTimerRate
+
+ mov _HalpClockMcaQueueDpc, bl
+
+;
+; Queue MCA Dpc
+;
+
+ push eax
+ stdCall _HalpMcaQueueDpc ; Queue MCA Dpc
+ pop eax
+
+CheckTimerRate:
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; ebp = trap frame
+; eax = time increment of this tick
+; ebx = 0
+;
+ cmp _HalpClockSetMSRate, bl ; New clock rate desired?
+ jz _KeUpdateSystemTime@0 ; No, process tick
+
+
+;
+; Time of clock frequency is being changed. See if we have changed rates
+; since the last tick
+;
+ cmp _HalpPendingRate, ebx ; Was a new rate set durning last
+ jnz short SetUpForNextTick ; tick? Yes, go update globals
+
+ProgramTimerRate:
+
+; (eax) = time increment for current tick
+
+;
+; A new clock rate needs to be set. Setting the rate here will
+; cause the tick after the next tick to be at the new rate.
+; (the next tick is already in progress and will occur at the same
+; rate as this tick)
+;
+ push eax
+
+ stdCall _HalpAcquireCmosSpinLock
+
+ mov eax, _HalpNextRate
+ mov _HalpPendingRate, eax ; pending rate
+
+ dec eax
+ mov ecx, TimeStrucSize
+ xor edx, edx
+ mul ecx
+
+ mov eax, _HalpRtcTimeIncrements[eax].RTCRegisterA
+ mov _HalpCurrentRTCRegisterA, eax
+
+ shl ax, 8 ; (ah) = (al)
+ mov al, 0AH ; Register A
+ CMOS_WRITE ; Set it
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ pop eax
+ jmp _KeUpdateSystemTime@0 ; dispatch this tick
+
+SetUpForNextTick:
+
+;
+; The next tick will occur at the rate which was programmed during the last
+; tick. Update globals for new rate which starts with the next tick.
+;
+; We will get here if there is a request for a rate change. There could
+; been two requests. That is why we are conmparing the Pending with the
+; NextRate.
+;
+; (eax) = time increment for current tick
+;
+ push eax
+
+ mov eax, _HalpPendingRate
+
+ dec eax
+ mov ecx, TimeStrucSize
+ xor edx, edx
+ mul ecx
+
+ mov ebx, _HalpRtcTimeIncrements[eax].RateIn100ns
+ mov ecx, _HalpRtcTimeIncrements[eax].RateAdjustmentCnt
+ mov edx, _HalpRtcTimeIncrements[eax].IpiRate
+ mov _HalpCurrentClockRateIn100ns, ebx
+ mov _HalpCurrentClockRateAdjustment, ecx
+ mov _HalpCurrentIpiRate, edx
+
+ mov ebx, _HalpPendingRate
+ mov _HalpPendingRate, 0 ; no longer pending, clear it
+
+ pop eax
+
+ cmp ebx, _HalpNextRate ; new rate == NextRate?
+ jne ProgramTimerRate ; no, go set new pending rate
+
+ mov _HalpClockSetMSRate, 0 ; all done setting new rate
+ jmp _KeUpdateSystemTime@0 ; dispatch this tick
+
+
+stdENDP _HalpClockInterrupt
+
+ page ,132
+ subttl "System Clock Interrupt - Non BSP"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by
+; CLOCK2. Its function is to dismiss the interrupt, raise system Irql
+; to CLOCK2_LEVEL, transfer control to the standard system routine to
+; the execution time of the current thread and process.
+;
+; This routine is executed on all processors other than P0
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+
+ ENTER_DR_ASSIST HPn_a, HPn_t
+
+cPublicProc _HalpClockInterruptPn ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT HPn_a, HPn_t
+
+;
+; (esp) - base of trap frame
+;
+; dismiss interrupt and raise Irql
+;
+
+ push APIC_CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,APIC_CLOCK_VECTOR,esp>
+
+ ;
+ ; All processors will update RunTime for current thread
+ ;
+
+ sti
+ ; TOS const PreviousIrql
+ stdCall _KeUpdateRunTime,<dword ptr [esp]>
+
+ INTERRUPT_EXIT ; lower irql to old value, iret
+
+ ;
+ ; We don't return here
+ ;
+
+stdENDP _HalpClockInterruptPn
+
+
+ page ,132
+ subttl "System Clock Interrupt - Stub"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by
+; CLOCK2. Its function is to interrupt and return.
+;
+; This routine is executed on P0 During Phase 0
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+APIC_ICR_CLOCK equ (DELIVER_FIXED OR ICR_ALL_EXCL_SELF OR APIC_CLOCK_VECTOR)
+
+ ENTER_DR_ASSIST HStub_a, HStub_t
+
+cPublicProc _HalpClockInterruptStub ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT HStub_a, HStub_t
+
+;
+; (esp) - base of trap frame
+;
+
+
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+
+Hpi10: test al, 80h
+ jz short Hpi15
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ jmp short Hpi10
+Hpi15:
+
+ mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
+
+ ;
+ ; Do interrupt exit processing without EOI
+ ;
+
+ SPURIOUS_INTERRUPT_EXIT
+
+ ;
+ ; We don't return here
+ ;
+
+stdENDP _HalpClockInterruptStub
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halmps/i386/mpclockc.c b/private/ntos/nthals/halmps/i386/mpclockc.c
new file mode 100644
index 000000000..5a45903e9
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpclockc.c
@@ -0,0 +1,167 @@
+/*++
+
+Module Name:
+
+ mpclockc.c
+
+Abstract:
+
+Author:
+
+ Ron Mosgrove - Intel
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+struct RtcTimeIncStruc {
+ ULONG RTCRegisterA; // The RTC register A value for this rate
+ ULONG RateIn100ns; // This rate in multiples of 100ns
+ ULONG RateAdjustmentNs; // Error Correction (in ns)
+ ULONG RateAdjustmentCnt; // Error Correction (as a fraction of 256)
+ ULONG IpiRate; // IPI Rate Count (as a fraction of 256)
+};
+
+//
+// The adjustment is expressed in terms of a fraction of 256 so that
+// the ISR can easily determine when a 100ns slice needs to be added
+// to the count passed to the kernel without any expensive operations
+//
+// Using 256 as a base means that anytime the count becomes greater
+// than 256 the time slice must be incremented, the overflow can then
+// be cleared by AND'ing the value with 0xff
+//
+
+#define AVAILABLE_INCREMENTS 5
+
+#define MINIMUM_INCREMENT 9765
+#define MAXIMUM_INCREMENT 156250
+
+struct RtcTimeIncStruc HalpRtcTimeIncrements[AVAILABLE_INCREMENTS] = {
+ {0x026, 9765, 62, 160, /* 5/8 of 256 */ 16},
+ {0x027, 19531, 25, 64, /* 1/4 of 256 */ 32},
+ {0x028, 39062, 50, 128, /* 1/2 of 256 */ 64},
+ {0x029, 78125, 0, 0, 128},
+ {0x02a, 156250, 0, 0, 256}
+};
+
+ULONG HalpMinClockRate = MINIMUM_INCREMENT;
+ULONG HalpMaxClockRate = MAXIMUM_INCREMENT;
+
+extern ULONG HalpCurrentRTCRegisterA;
+extern ULONG HalpCurrentClockRateIn100ns;
+extern ULONG HalpCurrentClockRateAdjustment;
+extern ULONG HalpCurrentIpiRate;
+extern ULONG HalpNextRate;
+extern ULONG HalpClockWork;
+extern BOOLEAN HalpClockSetMSRate;
+
+
+VOID
+HalpSetInitialClockRate (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpSetInitialClockRate)
+#endif
+
+
+VOID
+HalpSetInitialClockRate (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the initial clock interrupt rate
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG Rate;
+
+ Rate = AVAILABLE_INCREMENTS-1;
+
+ HalpCurrentClockRateIn100ns = HalpRtcTimeIncrements[Rate].RateIn100ns;
+ HalpCurrentClockRateAdjustment = HalpRtcTimeIncrements[Rate].RateAdjustmentCnt;
+ HalpCurrentRTCRegisterA = HalpRtcTimeIncrements[Rate].RTCRegisterA;
+ HalpCurrentIpiRate = HalpRtcTimeIncrements[Rate].IpiRate;
+ HalpClockWork = 0;
+
+ KeSetTimeIncrement(HalpMaxClockRate, HalpMinClockRate);
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG i;
+ KIRQL OldIrql;
+
+ //
+ // Set the new clock interrupt parameters, return the new time increment value.
+ //
+
+
+ for (i=1; i < AVAILABLE_INCREMENTS - 1; i++) {
+ if (HalpRtcTimeIncrements[i].RateIn100ns > DesiredIncrement) {
+ i = i - 1;
+ break;
+ }
+ }
+
+ OldIrql = KfRaiseIrql(HIGH_LEVEL);
+
+ HalpNextRate = i + 1;
+ HalpClockSetMSRate = TRUE;
+
+ KfLowerIrql (OldIrql);
+
+ return (HalpRtcTimeIncrements[i].RateIn100ns);
+}
diff --git a/private/ntos/nthals/halmps/i386/mpconfig.asm b/private/ntos/nthals/halmps/i386/mpconfig.asm
new file mode 100644
index 000000000..b5b8d608d
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpconfig.asm
@@ -0,0 +1,530 @@
+ title "PC+MP configuration table processing"
+
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 Intel Corporation
+;All rights reserved
+;
+;INTEL CORPORATION PROPRIETARY INFORMATION
+;
+;This software is supplied to Microsoft under the terms
+;of a license agreement with Intel Corporation and may not be
+;copied nor disclosed except in accordance with the terms
+;of that agreement.
+;
+;
+;Module Name:
+;
+; mpconfig.asm
+;
+;Abstract:
+;
+; Build the default PC+MP configuration tables defined in the PC+MP
+; specification. This file contains no code. It statically builds the
+; default PC+MP configurations in data. C code declaring structures to
+; use these tables must use the "pack(1)" pragma to ensure they are byte
+; aligned.
+;
+;
+;Author:
+;
+; Rajesh Shah (Intel) Oct 1993
+;
+;Revision History:
+;
+;--
+.386p
+
+include i386\pcmp.inc
+include i386\apic.inc
+
+;
+; Entry size in bytes for Bus entries, Io Apic entries, Io Apic interrupt
+; input entries and Local Apic interrupt input entries in the PC+MP table.
+;
+COMMON_ENTRY_SIZE equ 08H
+;
+; Default values for Processor entries in the PC+MP table.
+;
+DEFAULT_NUM_CPUS equ 02H
+PROC_ENTRY_SIZE equ 14H
+CPU_i486 equ 0421H
+CPU_FEATURES equ 01H ; On-chip FPU
+
+;
+; Default Apic Version values.
+;
+VERSION_82489DX equ 01H ; 8 bit APIC version register value.
+VERSION_INTEGRATED equ 11H ; 8 bit APIC version register value.
+
+;
+; Default values for Bus entries in the PC+MP table
+;
+BUS_ID_0 equ 0H
+BUS_INTI_POLARITY equ 0H
+BUS_INTI_LEVEL equ 0H
+
+; Macros to emit the 6 byte bus type string. The string is not
+; NULL terminated. If the Bus string consists of less than 6
+; characters, it is padded with space characters(ASCII 20h).
+
+BUS_TYPE_EISA macro
+ db "EISA "
+endm
+
+BUS_TYPE_ISA macro
+ db "ISA "
+endm
+
+BUS_TYPE_PCI macro
+ db "PCI "
+endm
+
+BUS_TYPE_MCA macro
+ db "MCA "
+endm
+
+;
+; Macros to build the different parts of the PC+MP table. See pcmp.inc
+; for the layout of the table and its entries.
+
+; Macro to build the HEADER part of the PC+MP table.
+; It takes a parameter (NumOfEntries) that specifies the total number of
+; data entries in the table. Processor entries are 20(decimal) bytes long,
+; all other entry types are 8 bytes long. All default configurations have
+; 2 processors. The table length is computed based on the NumOfEntries
+; parameter.
+;
+Header macro NumEntries
+ dd PCMP_SIGNATURE ;; ASCII "PCMP"
+ dw ( (DEFAULT_NUM_CPUS * PROC_ENTRY_SIZE) \
+ + ((NumEntries - DEFAULT_NUM_CPUS) * COMMON_ENTRY_SIZE)\
+ + HEADER_SIZE ) ;; Total table length
+ db 1 ;; PC+MP spec. revision
+ db 0 ;; Checksum
+ db 8 dup (0) ;; OEM Id
+ db 12 dup (0) ;; OEM Product Id
+ dd 0 ;; OEM table pointer
+ dw 0 ;; OEM table size
+ dw NumOfEntries ;; Number of entries in DATA portion
+ dd LU_BASE_ADDRESS ;; Default Loacal Apic address
+ dd 0 ;; Reserved (Not Used)
+endm ;;Header
+
+;
+; Macro to build Processor entries of the PC+MP table
+;
+; Parameter ApicVersion specifes the Apic version (82489DX or integrated)
+; Parameter IsBsp is used in the CPU Flags field, and specifies if this
+; processor is the BSP processor
+;
+Processor macro LocalApicId, ApicVersion, IsBspCpu
+ db ENTRY_PROCESSOR ;; Processor entry type
+ db LocalApicId ;; ID of Loacal Apic unit.
+ db ApicVersion ;; Must agree with IO Apic Version
+ db CPU_ENABLED OR IsBspCpu ;; CpuFlags
+ dd CPU_i486 ;; Default CPU type
+ dd CPU_FEATURES ;; Default CPU features
+ db 8 dup (0) ;; Reserved
+endm ;Processor
+
+;
+; Macro to build Bus entries of the PC+MP table
+;
+Bus macro BusId, BusString
+ db ENTRY_BUS ;; Bus entry type
+ db BusId ;; ID of this bus
+ BusString ;; This parameter is a macro that
+ ;; emits the 6 byte bus type string.
+endm ;Bus
+
+;
+; Macro to build Io Apic entries of the PC+MP table
+; Parameter IoApicVersion specifes the Apic version (82489DX or integrated)
+; All default configurations have a single IO Apic.
+;
+IoApic macro IoApicVersion
+ db ENTRY_IOAPIC ;; IO APIC entry type
+ db IOUNIT_APIC_ID ;; Default Io Apic ID
+ db IoApicVersion ;; Must agree with Local APIC ver.
+ db IO_APIC_ENABLED ;; enable the IO APIC by default,
+ dd IO_BASE_ADDRESS ;; Default physical address of 1st
+ ;; IO APIC.
+endm ;IoApic
+
+;
+; Macro to build Io Apic interrupt input entries of the PC+MP table
+; Since all default configurations have a single IO Apic, all the IO Apic
+; interrput input entries are built for the default IO Apic. For all default
+; configurations, the interrupt source bus is assumed to have a bus ID 0.
+;
+IoApicInti macro IntType,SourceBusIrq,ApicInti
+ db ENTRY_INTI ;; IO Apic interrupt input entry type
+ db IntType ;; NMI,SMI,ExtINT or INTR
+ dw BUS_INTI_POLARITY OR BUS_INTI_LEVEL ;; Default polarity and level
+ db BUS_ID_0 ;; Bus Id on which interrupt arrives
+ db SourceBusIrq ;; Bus relative IRQ at which
+ ;; interrupt arrives
+ db IOUNIT_APIC_ID ;; Apic Id of destination IO Apic
+ db ApicInti ;; Io Apic Interrupt input pin
+ ;; number this interrupt goes to
+endm ;IoApicInti
+
+;
+; Macro to build Io Apic interrupt input entries of the PC+MP table
+; Since all default configurations have a single IO Apic, all the IO Apic
+; interrput input entries are built for the default IO Apic. For all default
+; configurations, the interrupt source bus is assumed to have a bus ID 0.
+;
+ApicInti macro IntType,SourceBusId,SourceBusIrq,AInti
+ db ENTRY_INTI ;; IO Apic interrupt input entry type
+ db IntType ;; NMI,SMI,ExtINT or INTR
+ dw BUS_INTI_POLARITY OR BUS_INTI_LEVEL ;; Default polarity and level
+ db SourceBusId ;; Bus Id on which interrupt arrives
+ db SourceBusIrq ;; Bus relative IRQ at which
+ ;; interrupt arrives
+ db IOUNIT_APIC_ID ;; Apic Id of destination IO Apic
+ db AInti ;; Io Apic Interrupt input pin
+ ;; number this interrupt goes to
+endm ;ApicInti
+
+;
+; Macro to build Local Apic interruptinput entries of the PC+MP table
+;
+Linti macro IntType,SourceBusId,SourceBusIrq,LocalApicId,ApicInti
+ db ENTRY_LINTI ;; Local Apic Interrupt Input
+ db IntType ;; NMI,SMI,ExtINT or INTR.
+ dw BUS_INTI_POLARITY OR BUS_INTI_LEVEL ;; Polarity and level
+ db SourceBusId ;; Bus Id on which interrupt arrives
+ db SourceBusIrq ;; Bus relative IRQ at which
+ ;; interrupt arrives
+ db LocalApicId ;; Apic Id of destination Local Apic
+ db ApicInti ;; Local Apic Interrupt input pin
+ ;; number this interrupt goes to
+endm ;Linti
+
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+
+; The PC+MP table consists of a fixed size HEADER and a variable
+; number of DATA entries. The order of the DATA entries is as
+; follows:
+;
+; 1) Processor entries (20 decimal bytes long). The Boot Strap
+; Processor (BSP) entry must be the first entry.
+; 2) Bus entries (8 bytes long).
+; 3) IO Apic entries (8 bytes long).
+; 4) IO Apic interrupt input entries (8 bytes long).
+; 5) Local Apic interrupt input entries (8 bytes long).
+;
+; All interrupting devices are connected to Bus ID 0 in the
+; default configurations.
+;
+; Any C code using these tables must use the pack(1) pragma.
+
+;
+; PC+MP default configuration 1: ISA bus, 82489DX Apic.
+;
+ public _PcMpDefaultConfig1
+_PcMpDefaultConfig1 label byte
+
+ ; Create table HEADER.
+ Header 14h
+
+ ; Create processor entries
+ Processor 0, VERSION_82489DX, BSP_CPU
+ Processor 1, VERSION_82489DX, 0
+
+ ; Create bus entries
+ Bus 0, BUS_TYPE_ISA
+
+ ; Create IO Apic entries.
+ IoApic VERSION_82489DX
+
+ ; Create IO Apic interrupt input entries.
+ IoApicInti INT_TYPE_INTR,1,1 ; IO APIC IRQ 1, INTIN 1
+ IoApicInti INT_TYPE_INTR,0,2 ; IO APIC IRQ 0, INTIN 2
+ IoApicInti INT_TYPE_INTR,3,3 ; IO APIC IRQ 3, INTIN 3
+ IoApicInti INT_TYPE_INTR,4,4 ; IO APIC IRQ 4, INTIN 4
+ IoApicInti INT_TYPE_INTR,5,5 ; IO APIC IRQ 5, INTIN 5
+ IoApicInti INT_TYPE_INTR,6,6 ; IO APIC IRQ 6, INTIN 6
+ IoApicInti INT_TYPE_INTR,7,7 ; IO APIC IRQ 7, INTIN 7
+ IoApicInti INT_TYPE_INTR,8,8 ; IO APIC IRQ 8, INTIN 8
+ IoApicInti INT_TYPE_INTR,9,9 ; IO APIC IRQ 9, INTIN 9
+ IoApicInti INT_TYPE_INTR,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ IoApicInti INT_TYPE_INTR,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ IoApicInti INT_TYPE_INTR,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ IoApicInti INT_TYPE_INTR,0dH,0dH ; IO APIC IRQ 13, INTIN 13
+ IoApicInti INT_TYPE_INTR,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ IoApicInti INT_TYPE_INTR,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+ ; Create Local Apic interrupt input entries.
+ Linti INT_TYPE_NMI,0,2,0,1 ; IRQ 2,LocalApicId 0,Linti 1
+
+;
+; PC+MP default configuration 2: EISA bus, 82489DX Apic.
+;
+ public _PcMpDefaultConfig2
+_PcMpDefaultConfig2 label byte
+
+ ; Create table HEADER.
+ Header 14h
+
+ ; Create processor entries
+
+ Processor 0H, VERSION_82489DX, BSP_CPU
+ Processor 01H, VERSION_82489DX, 0
+
+ ; Create bus entries
+ Bus 0, BUS_TYPE_EISA
+
+ ; Create IO Apic entries.
+ IoApic VERSION_82489DX
+
+ ; Create IO Apic interrupt input entries.
+ ; In configuration 2, the 8259 PIC fields the timer and DMA interrupts.
+ ; The PIC is connected to interrupt input pin 0 of the IO Apic, so this
+ ; IO Apic interrupt pin can get 2 different interrupts.
+
+ IoApicInti INT_TYPE_EXTINT,0,0 ; IO APIC IRQ 0, INTIN 0
+ IoApicInti INT_TYPE_EXTINT,0dh,0 ; IO APIC IRQ 13, INTIN 0
+ IoApicInti INT_TYPE_INTR,1,1 ; IO APIC IRQ 1, INTIN 1
+
+ ; In this configuration, NMI comes through IO Apic interrupt
+ ; input pin 2. In all other configurations, NMI comes through
+ ; the Local Apic interrupt input LINTIN1
+
+ IoApicInti INT_TYPE_NMI,2,2 ; IO APIC IRQ 2, INTIN 2
+
+ IoApicInti INT_TYPE_INTR,3,3 ; IO APIC IRQ 3, INTIN 3
+ IoApicInti INT_TYPE_INTR,4,4 ; IO APIC IRQ 4, INTIN 4
+ IoApicInti INT_TYPE_INTR,5,5 ; IO APIC IRQ 5, INTIN 5
+ IoApicInti INT_TYPE_INTR,6,6 ; IO APIC IRQ 6, INTIN 6
+ IoApicInti INT_TYPE_INTR,7,7 ; IO APIC IRQ 7, INTIN 7
+ IoApicInti INT_TYPE_INTR,8,8 ; IO APIC IRQ 8, INTIN 8
+ IoApicInti INT_TYPE_INTR,9,9 ; IO APIC IRQ 9, INTIN 9
+ IoApicInti INT_TYPE_INTR,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ IoApicInti INT_TYPE_INTR,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ IoApicInti INT_TYPE_INTR,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ IoApicInti INT_TYPE_INTR,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ IoApicInti INT_TYPE_INTR,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+;
+; PC+MP default configuration 3: EISA bus, 82489DX Apic, timer(Inti2)
+;
+ public _PcMpDefaultConfig3
+_PcMpDefaultConfig3 label byte
+
+ ; Create table HEADER.
+ Header 14h
+
+ ; Create processor entries
+ Processor 0H, VERSION_82489DX, BSP_CPU
+ Processor 01H, VERSION_82489DX, 0
+
+ ; Create bus entries
+ Bus 0, BUS_TYPE_EISA
+
+ ; Create IO Apic entries.
+ IoApic VERSION_82489DX
+
+ ; Create IO Apic interrupt input entries.
+ IoApicInti INT_TYPE_INTR,1,1 ; IO APIC IRQ 1, INTIN 1
+ IoApicInti INT_TYPE_INTR,0,2 ; IO APIC IRQ 0, INTIN 2
+ IoApicInti INT_TYPE_INTR,3,3 ; IO APIC IRQ 3, INTIN 3
+ IoApicInti INT_TYPE_INTR,4,4 ; IO APIC IRQ 4, INTIN 4
+ IoApicInti INT_TYPE_INTR,5,5 ; IO APIC IRQ 5, INTIN 5
+ IoApicInti INT_TYPE_INTR,6,6 ; IO APIC IRQ 6, INTIN 6
+ IoApicInti INT_TYPE_INTR,7,7 ; IO APIC IRQ 7, INTIN 7
+ IoApicInti INT_TYPE_INTR,8,8 ; IO APIC IRQ 8, INTIN 8
+ IoApicInti INT_TYPE_INTR,9,9 ; IO APIC IRQ 9, INTIN 9
+ IoApicInti INT_TYPE_INTR,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ IoApicInti INT_TYPE_INTR,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ IoApicInti INT_TYPE_INTR,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ IoApicInti INT_TYPE_INTR,0dH,0dH ; IO APIC IRQ 13, INTIN 13
+ IoApicInti INT_TYPE_INTR,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ IoApicInti INT_TYPE_INTR,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+ ; Create Local Apic interrupt input entries.
+ Linti INT_TYPE_NMI,0,2,0,1 ; IRQ 2,LocalApicId 0,Linti 1
+
+;
+; PC+MP default configuration 4: MCA bus, 82489DX Apic.
+;
+ public _PcMpDefaultConfig4
+_PcMpDefaultConfig4 label byte
+
+ ; Create table HEADER.
+ Header 14h
+
+ ; Create processor entries
+ Processor 0H, VERSION_82489DX, BSP_CPU
+ Processor 01H, VERSION_82489DX, 0
+
+ ; Create bus entries
+ Bus 0, BUS_TYPE_MCA
+
+ ; Create IO Apic entries.
+ IoApic VERSION_82489DX
+
+ ; Create IO Apic interrupt input entries.
+ IoApicInti INT_TYPE_INTR,1,1 ; IO APIC IRQ 1, INTIN 1
+ IoApicInti INT_TYPE_INTR,0,2 ; IO APIC IRQ 0, INTIN 2
+ IoApicInti INT_TYPE_INTR,3,3 ; IO APIC IRQ 3, INTIN 3
+ IoApicInti INT_TYPE_INTR,4,4 ; IO APIC IRQ 4, INTIN 4
+ IoApicInti INT_TYPE_INTR,5,5 ; IO APIC IRQ 5, INTIN 5
+ IoApicInti INT_TYPE_INTR,6,6 ; IO APIC IRQ 6, INTIN 6
+ IoApicInti INT_TYPE_INTR,7,7 ; IO APIC IRQ 7, INTIN 7
+ IoApicInti INT_TYPE_INTR,8,8 ; IO APIC IRQ 8, INTIN 8
+ IoApicInti INT_TYPE_INTR,9,9 ; IO APIC IRQ 9, INTIN 9
+ IoApicInti INT_TYPE_INTR,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ IoApicInti INT_TYPE_INTR,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ IoApicInti INT_TYPE_INTR,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ IoApicInti INT_TYPE_INTR,0dH,0dH ; IO APIC IRQ 13, INTIN 13
+ IoApicInti INT_TYPE_INTR,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ IoApicInti INT_TYPE_INTR,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+ ; Create Local Apic interrupt input entries.
+ Linti INT_TYPE_NMI,0,2,0,1 ; IRQ 2,LocalApicId 0,Linti 1
+
+;
+; PC+MP default configuration 5: ISA & PCI bus, Integrated Local Apic
+;
+ public _PcMpDefaultConfig5
+_PcMpDefaultConfig5 label byte
+
+ ; Create table HEADER.
+ Header 15h
+
+ ; Create processor entries
+ Processor 0H, VERSION_INTEGRATED, BSP_CPU
+ Processor 01H, VERSION_INTEGRATED, 0
+
+ ; Create bus entries
+ Bus 1, BUS_TYPE_ISA
+ Bus 0, BUS_TYPE_PCI
+
+ ; Create IO Apic entries.
+ IoApic VERSION_INTEGRATED
+
+ ; Create IO Apic interrupt input entries.
+ ApicInti INT_TYPE_INTR,1,1,1 ; IO APIC IRQ 1, INTIN 1
+ ApicInti INT_TYPE_INTR,1,0,2 ; IO APIC IRQ 0, INTIN 2
+ ApicInti INT_TYPE_INTR,1,3,3 ; IO APIC IRQ 3, INTIN 3
+ ApicInti INT_TYPE_INTR,1,4,4 ; IO APIC IRQ 4, INTIN 4
+ ApicInti INT_TYPE_INTR,1,5,5 ; IO APIC IRQ 5, INTIN 5
+ ApicInti INT_TYPE_INTR,1,6,6 ; IO APIC IRQ 6, INTIN 6
+ ApicInti INT_TYPE_INTR,1,7,7 ; IO APIC IRQ 7, INTIN 7
+ ApicInti INT_TYPE_INTR,1,8,8 ; IO APIC IRQ 8, INTIN 8
+ ApicInti INT_TYPE_INTR,1,9,9 ; IO APIC IRQ 9, INTIN 9
+ ApicInti INT_TYPE_INTR,1,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ ApicInti INT_TYPE_INTR,1,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ ApicInti INT_TYPE_INTR,1,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ ApicInti INT_TYPE_INTR,1,0dH,0dH ; IO APIC IRQ 13, INTIN 13
+ ApicInti INT_TYPE_INTR,1,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ ApicInti INT_TYPE_INTR,1,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+ ; Create Local Apic interrupt input entries.
+ Linti INT_TYPE_NMI,1,2,0,1 ; IRQ 2,LocalApicId 0,Linti 1
+
+;
+; PC+MP default configuration 6 EISA & PCI bus, Integrated Local Apic
+;
+ public _PcMpDefaultConfig6
+_PcMpDefaultConfig6 label byte
+
+ ; Create table HEADER.
+ Header 15h
+
+ ; Create processor entries
+ Processor 0H, VERSION_INTEGRATED, BSP_CPU
+ Processor 1H, VERSION_INTEGRATED, 0
+
+ ; Create bus entries
+ Bus 1, BUS_TYPE_EISA
+ Bus 0, BUS_TYPE_PCI
+
+ ; Create IO Apic entries.
+ IoApic VERSION_INTEGRATED
+
+ ; Create IO Apic interrupt input entries.
+ ApicInti INT_TYPE_INTR,1,1,1 ; IO APIC IRQ 1, INTIN 1
+ ApicInti INT_TYPE_INTR,1,0,2 ; IO APIC IRQ 0, INTIN 2
+ ApicInti INT_TYPE_INTR,1,3,3 ; IO APIC IRQ 3, INTIN 3
+ ApicInti INT_TYPE_INTR,1,4,4 ; IO APIC IRQ 4, INTIN 4
+ ApicInti INT_TYPE_INTR,1,5,5 ; IO APIC IRQ 5, INTIN 5
+ ApicInti INT_TYPE_INTR,1,6,6 ; IO APIC IRQ 6, INTIN 6
+ ApicInti INT_TYPE_INTR,1,7,7 ; IO APIC IRQ 7, INTIN 7
+ ApicInti INT_TYPE_INTR,1,8,8 ; IO APIC IRQ 8, INTIN 8
+ ApicInti INT_TYPE_INTR,1,9,9 ; IO APIC IRQ 9, INTIN 9
+ ApicInti INT_TYPE_INTR,1,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ ApicInti INT_TYPE_INTR,1,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ ApicInti INT_TYPE_INTR,1,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ ApicInti INT_TYPE_INTR,1,0dH,0dH ; IO APIC IRQ 13, INTIN 13
+ ApicInti INT_TYPE_INTR,1,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ ApicInti INT_TYPE_INTR,1,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+ ; Create Local Apic interrupt input entries.
+ Linti INT_TYPE_NMI,1,2,0,1 ; IRQ 2,LocalApicId 0,Linti 1
+
+
+;
+; PC+MP default configuration 7: MCA & PCI bus, Integrated Local Apic
+;
+ public _PcMpDefaultConfig7
+_PcMpDefaultConfig7 label byte
+
+ ; Create table HEADER.
+ Header 15h
+
+ ; Create processor entries
+ Processor 0H, VERSION_INTEGRATED, BSP_CPU
+ Processor 01H, VERSION_INTEGRATED, 0
+
+ ; Create bus entries
+ Bus 1, BUS_TYPE_MCA
+ Bus 0, BUS_TYPE_PCI
+
+ ; Create IO Apic entries.
+ IoApic VERSION_INTEGRATED
+
+ ; Create IO Apic interrupt input entries.
+ ApicInti INT_TYPE_INTR,1,1,1 ; IO APIC IRQ 1, INTIN 1
+ ApicInti INT_TYPE_INTR,1,0,2 ; IO APIC IRQ 0, INTIN 2
+ ApicInti INT_TYPE_INTR,1,3,3 ; IO APIC IRQ 3, INTIN 3
+ ApicInti INT_TYPE_INTR,1,4,4 ; IO APIC IRQ 4, INTIN 4
+ ApicInti INT_TYPE_INTR,1,5,5 ; IO APIC IRQ 5, INTIN 5
+ ApicInti INT_TYPE_INTR,1,6,6 ; IO APIC IRQ 6, INTIN 6
+ ApicInti INT_TYPE_INTR,1,7,7 ; IO APIC IRQ 7, INTIN 7
+ ApicInti INT_TYPE_INTR,1,8,8 ; IO APIC IRQ 8, INTIN 8
+ ApicInti INT_TYPE_INTR,1,9,9 ; IO APIC IRQ 9, INTIN 9
+ ApicInti INT_TYPE_INTR,1,0ah,0ah ; IO APIC IRQ 10, INTIN 10
+ ApicInti INT_TYPE_INTR,1,0bh,0bh ; IO APIC IRQ 11, INTIN 11
+ ApicInti INT_TYPE_INTR,1,0ch,0ch ; IO APIC IRQ 12, INTIN 12
+ ApicInti INT_TYPE_INTR,1,0dH,0dH ; IO APIC IRQ 13, INTIN 13
+ ApicInti INT_TYPE_INTR,1,0eH,0eH ; IO APIC IRQ 14, INTIN 14
+ ApicInti INT_TYPE_INTR,1,0fH,0fH ; IO APIC IRQ 15, INTIN 15
+
+ ; Create Local Apic interrupt input entries.
+ Linti INT_TYPE_NMI,1,2,0,1 ; IRQ 2,LocalApicId 0,Linti 1
+
+
+ ;
+ ; Pointers to the default configuration tables
+ ;
+ public _PcMpDefaultTablePtrs
+
+ ; Array of pointers to the default configurations.
+_PcMpDefaultTablePtrs label byte
+ dd offset _PcMpDefaultConfig1 ; Pointer to Default Config 1
+ dd offset _PcMpDefaultConfig2 ; Pointer to Default Config 2
+ dd offset _PcMpDefaultConfig3 ; Pointer to Default Config 3
+ dd offset _PcMpDefaultConfig4 ; Pointer to Default Config 4
+ dd offset _PcMpDefaultConfig5 ; Pointer to Default Config 5
+ dd offset _PcMpDefaultConfig6 ; Pointer to Default Config 6
+ dd offset _PcMpDefaultConfig7 ; Pointer to Default Config 7
+
+INIT ENDS
+
+end
diff --git a/private/ntos/nthals/halmps/i386/mpdat.c b/private/ntos/nthals/halmps/i386/mpdat.c
new file mode 100644
index 000000000..f4c47ca99
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpdat.c
@@ -0,0 +1,280 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "apic.inc"
+#include "pcmp_nt.inc"
+#include "pci.h"
+#include "pcip.h"
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+#ifndef MCA
+ 0x000, 0x10, // ISA DMA
+ 0x0C0, 0x10, // ISA DMA
+#else
+ 0x000, 0x20, // MCA DMA
+ 0x0C0, 0x20, // MCA DMA
+#endif
+ 0x080, 0x10, // DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ 0x048, 0x4, // Timer2, Failsafe
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+#ifdef MCA
+ 0x074, 0x3, // Extended CMOS
+
+ 0x090, 0x2, // Arbritration Control Port, Card Select Feedback
+ 0x093, 0x2, // Reserved, System board setup
+ 0x096, 0x2, // POS channel select
+#endif
+ 0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x0D0, 0x10, // DMA
+ 0x400, 0x10, // DMA
+ 0x480, 0x10, // DMA
+ 0x4C2, 0xE, // DMA
+ 0x4D4, 0x2C, // DMA
+
+ 0x461, 0x2, // Extended NMI
+ 0x464, 0x2, // Last Eisa Bus Muster granted
+
+ 0x4D0, 0x2, // edge/level control registers
+
+ 0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+ADDRESS_USAGE HalpImcrIoSpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ 0x022, 0x02, // ICMR ports
+ 0, 0
+ }
+};
+
+ADDRESS_USAGE HalpApicUsage = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ 0, 0x400, // Local apic
+ 0, 0x400, // IO Apic 0
+ 0, 0x400, // IO Apic 1
+ 0, 0x400, // IO Apic 2
+ 0, 0x400, // IO Apic 3
+ 0, 0x400, // IO Apic 4
+ 0, 0x400, // IO Apic 5
+ 0, 0x400, // IO Apic 6
+ 0, 0x400, // IO Apic 7 MAX_PCMP_IOAPICS
+ 0, 0,
+ }
+};
+
+//
+// From usage.c
+//
+
+WCHAR HalpSzSystem[] = L"\\Registry\\Machine\\Hardware\\Description\\System";
+WCHAR HalpSzSerialNumber[] = L"Serial Number";
+
+ADDRESS_USAGE *HalpAddressUsageList;
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR+1];
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+//
+// From ixpcibrd.c
+//
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+//
+// From ixinfo.c
+//
+
+WCHAR rgzSuspendCallbackName[] = L"\\Callback\\SuspendHibernateSystem";
+
+//
+// Strings used for boot.ini options
+// from mphal.c
+//
+
+UCHAR HalpSzBreak[] = "BREAK";
+UCHAR HalpSzOneCpu[] = "ONECPU";
+UCHAR HalpSzPciLock[] = "PCILOCK";
+UCHAR HalpGenuineIntel[]= "GenuineIntel";
+UCHAR HalpSzClockLevel[]= "CLKLVL";
+
+
+//
+// From ixcmos.asm
+//
+
+UCHAR HalpSerialLen;
+UCHAR HalpSerialNumber[31];
+
+//
+// From mpaddr.c
+//
+
+USHORT HalpIoCompatibleRangeList0[] = {
+ 0x0100, 0x03ff, 0x0500, 0x07FF, 0x0900, 0x0BFF, 0x0D00, 0x0FFF,
+ 0, 0
+ };
+
+USHORT HalpIoCompatibleRangeList1[] = {
+ 0x03B0, 0x03BB, 0x03C0, 0x03DF, 0x07B0, 0x07BB, 0x07C0, 0x07DF,
+ 0x0BB0, 0x0BBB, 0x0BC0, 0x0BDF, 0x0FB0, 0x0FBB, 0x0FC0, 0x0FDF,
+ 0, 0
+ };
+
+
+//
+// Copy of floating structure
+// from detection code
+//
+
+struct FloatPtrStruct HalpFloatStruct;
+UCHAR rgzNoMpsTable[] = "HAL: No MPS Table Found\n";
+UCHAR rgzNoApic[] = "HAL: No IO APIC Found\n";
+UCHAR rgzBadApicVersion[] = "HAL: Bad APIC Version\n";
+UCHAR rgzApicNotVerified[] = "HAL: APIC not verified\n";
+UCHAR rgzMPPTRCheck[] = "HAL: MP_PTR invalid checksum\n";
+UCHAR rgzNoMPTable[] = "HAL: MPS MP structure not found\n";
+UCHAR rgzMPSBadSig[] = "HAL: MPS table invalid signature\n";
+UCHAR rgzMPSBadCheck[] = "HAL: MPS table invalid checksum\n";
+UCHAR rgzBadDefault[] = "HAL: MPS default configuration unknown\n";
+UCHAR rgzBadHal[] = "\n\n" \
+ "HAL: This HAL.DLL requires an MPS version 1.1 system\n" \
+ "Replace HAL.DLL with the correct hal for this system\n" \
+ "The system is halting";
+UCHAR rgzRTCNotFound[] = "HAL: No RTC device interrupt\n";
+
+
+//
+// Table to translate PCMP BusType to NT INTERFACE_TYPEs
+// All Eisa, Isa, VL buses are squashed onto one space
+// from mpsys.c
+//
+
+NTSTATUS
+HalpAddEisaBus (
+ PBUS_HANDLER Bus
+ );
+
+NTSTATUS
+HalpAddPciBus (
+ PBUS_HANDLER Bus
+ );
+
+
+PCMPBUSTRANS HalpTypeTranslation[] = {
+ // "INTERN", can't be interface_type internal
+ "CBUS ", FALSE, CFG_EDGE, CBus, NULL, 0, 0,
+ "CBUSII", FALSE, CFG_EDGE, CBus, NULL, 0, 0,
+ "EISA ", FALSE, CFG_EDGE, Eisa, HalpAddEisaBus, EisaConfiguration, 0,
+ "ISA ", FALSE, CFG_EDGE, Eisa, HalpAddEisaBus, EisaConfiguration, 0,
+ "MCA ", FALSE, CFG_MB_LEVEL, MicroChannel, NULL, 0, 0,
+ "MPI ", FALSE, CFG_EDGE, MPIBus, NULL, 0, 0,
+ "MPSA ", FALSE, CFG_EDGE, MPSABus, NULL, 0, 0,
+ "NUBUS ", FALSE, CFG_EDGE, NuBus, NULL, 0, 0,
+ "PCI ", TRUE, CFG_MB_LEVEL, PCIBus, HalpAddPciBus, PCIConfiguration, sizeof (PCIPBUSDATA),
+ "PCMCIA", FALSE, CFG_EDGE, PCMCIABus, NULL, 0, 0,
+ "TC ", FALSE, CFG_EDGE, TurboChannel, NULL, 0, 0,
+ "VL ", FALSE, CFG_EDGE, Eisa, HalpAddEisaBus, EisaConfiguration, 0,
+ "VME ", FALSE, CFG_EDGE, VMEBus, NULL, 0, 0,
+ NULL, FALSE, CFG_EDGE, MaximumInterfaceType, NULL, 0, 0
+ } ;
+
+UCHAR HalpInitLevel [4][4] = {
+ // must-be must-be
+ // edge level edge level
+ { CFG_EDGE, CFG_LEVEL, CFG_MB_EDGE, CFG_MB_LEVEL }, // 00 - bus def
+ { CFG_MB_EDGE, CFG_MB_EDGE, CFG_MB_EDGE, CFG_ERR_MB_LEVEL }, // 01 - edge
+ { CFG_ERR_EDGE, CFG_ERR_LEVEL, CFG_ERR_MB_EDGE, CFG_ERR_MB_LEVEL }, // 10 - undefined
+ { CFG_MB_LEVEL, CFG_MB_LEVEL, CFG_ERR_MB_EDGE, CFG_MB_LEVEL } // 11 - level
+};
+
+BOOLEAN HalpELCRChecked;
+
+//
+// From ixmca.c
+//
+UCHAR MsgMCEPending[] = MSG_MCE_PENDING;
+WCHAR rgzSessionManager[] = L"Session Manager";
+WCHAR rgzEnableMCE[] = L"EnableMCE";
+WCHAR rgzEnableMCA[] = L"EnableMCA";
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+ULONG HalpFeatureBits;
+
+
+UCHAR HalpDevPolarity [4][2] = {
+ //
+ // Edge Level
+ { CFG_HIGH, CFG_LOW }, // 00 - bus def
+ { CFG_HIGH, CFG_HIGH }, // 01 - high
+ { CFG_HIGH, CFG_LOW }, // 10 - undefined
+ { CFG_LOW, CFG_LOW } // 11 - low
+};
+
+
+UCHAR HalpDevLevel [2][4] = {
+ // must-be must-be
+ // edge level edge level
+ { CFG_EDGE, CFG_EDGE, CFG_EDGE, CFG_ERR_LEVEL }, // 0 - edge
+ { CFG_LEVEL, CFG_LEVEL, CFG_ERR_EDGE, CFG_LEVEL } // 1 - level
+};
diff --git a/private/ntos/nthals/halmps/i386/mpdebug.c b/private/ntos/nthals/halmps/i386/mpdebug.c
new file mode 100644
index 000000000..f630fcee6
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpdebug.c
@@ -0,0 +1,683 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Intel Corporation
+All rights reserved
+
+INTEL CORPORATION PROPRIETARY INFORMATION
+
+This software is supplied to Microsoft under the terms
+of a license agreement with Intel Corporation and may not be
+copied nor disclosed except in accordance with the terms
+of that agreement.
+
+Module Name:
+
+ mpdebug.c
+
+Abstract:
+
+ This module has some useful modules for debug aid.
+
+Author:
+
+ Ron Mosgrove (Intel) - Aug 1993.
+
+Environment:
+
+ Kernel mode or from textmode setup.
+
+Revision History:
+
+--*/
+
+#ifndef _NTOS_
+#include "halp.h"
+#endif
+
+#include "apic.inc"
+#include "pcmp_nt.inc"
+#include "stdio.h"
+
+#define PCMP_TABLE_PTR_BASE 0x09f000
+#define PCMP_TABLE_PTR_OFFSET 0x00000c00
+
+// Create dummy PC+MP table at physical address 400K
+#define PCMP_TEST_TABLE 0x64000
+#define TEST_FLOAT_PTR 0x7d000
+
+extern struct PcMpTable *PcMpTablePtr, *PcMpDefaultTablePtrs[];
+//extern struct HalpMpInfo *HalpMpInfoPtr;
+
+CHAR Cbuf[120];
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+UCHAR
+ComputeCheckSum(
+ IN PUCHAR SourcePtr,
+ IN USHORT NumOfBytes
+ );
+
+#ifdef OLD_DEBUG
+extern struct PcMpConfigTable *PcMpTablePtr;
+#endif
+
+#ifdef DEBUGGING
+
+ULONG HalpUseDbgPrint = 0;
+
+void
+HalpDisplayString(
+ IN PVOID String
+ )
+{
+ if (!HalpUseDbgPrint) {
+ HalDisplayString(String);
+ } else {
+ DbgPrint(String);
+ }
+}
+
+
+void
+HalpDisplayItemBuf(
+ IN UCHAR Length,
+ IN PUCHAR Buffer,
+ IN PVOID Name
+ )
+{
+ ULONG i;
+ CHAR TmpBuf[80];
+
+ sprintf(TmpBuf, " %s -", Name);
+ HalpDisplayString(TmpBuf);
+ for (i=0; i< Length; i++) {
+ sprintf(TmpBuf, " 0x%x", Buffer[i]);
+ HalpDisplayString(TmpBuf);
+ }
+ HalpDisplayString("\n");
+}
+
+void
+HalpDisplayULItemBuf(
+ IN UCHAR Length,
+ IN PULONG Buffer,
+ IN PVOID Name
+ )
+{
+ ULONG i;
+ CHAR TmpBuf[80];
+
+ sprintf(TmpBuf, " %s -", Name);
+ HalpDisplayString(TmpBuf);
+ for (i=0; i< Length; i++) {
+ sprintf(TmpBuf, " 0x%lx", Buffer[i]);
+ HalpDisplayString(TmpBuf);
+ }
+ HalpDisplayString("\n");
+}
+
+void
+HalpDisplayItem(
+ IN ULONG Item,
+ IN PVOID ItemStr
+ )
+{
+ CHAR TmpBuf[80];
+
+ sprintf(TmpBuf, " %s - 0x%x\n", ItemStr, Item);
+ HalpDisplayString(TmpBuf);
+}
+
+VOID
+HalpDisplayBIOSSysCfg(
+ IN struct SystemConfigTable *SysCfgPtr
+ )
+{
+ HalpDisplayString("BIOS System Configuration Table\n");
+ HalpDisplayItem(SysCfgPtr->ModelType, "ModelType");
+ HalpDisplayItem(SysCfgPtr->SubModelType, "SubModelType");
+ HalpDisplayItem(SysCfgPtr->BIOSRevision, "BIOSRevision");
+ HalpDisplayItemBuf(3,SysCfgPtr->FeatureInfoByte,"FeatureInfoByte");
+ HalpDisplayItem(SysCfgPtr->MpFeatureInfoByte1, "MpFeatureInfoByte1");
+ HalpDisplayItem(SysCfgPtr->MpFeatureInfoByte2, "MpFeatureInfoByte2");
+}
+
+VOID
+HalpDisplayLocalUnit(
+ )
+{
+ ULONG Data;
+ PKPCR pPCR;
+
+ pPCR = KeGetPcr();
+
+ sprintf(Cbuf, "\nLocal Apic for P%d\n", pPCR->Prcb->Number);
+ HalpDisplayString(Cbuf);
+
+#define DisplayLuReg(Reg, RegStr) Data = *((PVULONG) (LOCALAPIC+Reg)); \
+ HalpDisplayItem(Data , RegStr);
+
+
+ DisplayLuReg( LU_ID_REGISTER , "LU_ID_REGISTER" );
+ DisplayLuReg( LU_VERS_REGISTER, "LU_VERS_REGISTER" );
+ DisplayLuReg( LU_TPR, "LU_TPR");
+ DisplayLuReg( LU_APR, "LU_APR");
+ DisplayLuReg( LU_PPR, "LU_PPR");
+ DisplayLuReg( LU_EOI, "LU_EOI");
+ DisplayLuReg( LU_REMOTE_REGISTER, "LU_REMOTE_REGISTER");
+ DisplayLuReg( LU_LOGICAL_DEST, "LU_LOGICAL_DEST");
+
+ DisplayLuReg( LU_DEST_FORMAT, "LU_DEST_FORMAT");
+
+ DisplayLuReg( LU_SPURIOUS_VECTOR , "LU_SPURIOUS_VECTOR" );
+
+ DisplayLuReg( LU_ISR_0, "LU_ISR_0");
+ DisplayLuReg( LU_TMR_0, "LU_TMR_0");
+ DisplayLuReg( LU_IRR_0, "LU_IRR_0");
+ DisplayLuReg( LU_ERROR_STATUS, "LU_ERROR_STATUS");
+ DisplayLuReg( LU_INT_CMD_LOW, "LU_INT_CMD_LOW");
+ DisplayLuReg( LU_INT_CMD_HIGH, "LU_INT_CMD_HIGH");
+ DisplayLuReg( LU_TIMER_VECTOR, "LU_TIMER_VECTOR");
+ DisplayLuReg( LU_INT_VECTOR_0, "LU_INT_VECTOR_0");
+ DisplayLuReg( LU_INT_VECTOR_1, "LU_INT_VECTOR_1");
+ DisplayLuReg( LU_INITIAL_COUNT, "LU_INITIAL_COUNT");
+ DisplayLuReg( LU_CURRENT_COUNT, "LU_CURRENT_COUNT");
+
+ DisplayLuReg( LU_DIVIDER_CONFIG, "LU_DIVIDER_CONFIG");
+ HalpDisplayString("\n");
+
+}
+
+VOID
+HalpDisplayIoUnit(
+ )
+/*++
+
+Routine Description:
+
+ Verify that an IO Unit exists at the specified address
+
+ Arguments:
+
+ BaseAddress - Address of the IO Unit to test.
+
+ Return Value:
+ BOOLEAN - TRUE if a IO Unit was found at the passed address
+ - FALSE otherwise
+
+--*/
+
+{
+#if 0
+ struct ApicIoUnit *IoUnitPtr;
+ ULONG Data,i,j;
+ PKPCR pPCR;
+
+ pPCR = KeGetPcr();
+
+ //
+ // The documented detection mechanism is to write all zeros to
+ // the Version register. Then read it back. The IO Unit exists if the
+ // same result is read both times and the Version is valid.
+ //
+
+
+
+ for (j=0; j<HalpMpInfoPtr->IOApicCount; j++) {
+ IoUnitPtr = (struct ApicIoUnit *) HalpMpInfoPtr->IoApicBase[j];
+
+ sprintf(Cbuf,"\nIoApic %d at Vaddr 0x%x\n",j,(ULONG) IoUnitPtr);
+ HalpDisplayString(Cbuf);
+
+ IoUnitPtr->RegisterSelect = IO_ID_REGISTER;
+ HalpDisplayItem(IoUnitPtr->RegisterWindow, "IO_ID_REGISTER");
+
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ HalpDisplayItem(IoUnitPtr->RegisterWindow, "IO_VERS_REGISTER");
+
+ for (i=0; i<16; i++) {
+
+ IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW+(i*2);
+ Data = IoUnitPtr->RegisterWindow;
+ sprintf(Cbuf, " Redir [0x%x] - 0x%x, ", i, Data);
+ HalpDisplayString(Cbuf);
+
+ IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW+(i*2)+1;
+ Data = IoUnitPtr->RegisterWindow;
+ sprintf(Cbuf, "0x%x\n", Data);
+ HalpDisplayString(Cbuf);
+
+ } // for each Redirection entry
+ } // for all Io Apics
+
+#endif
+}
+
+void
+HalpDisplayConfigTable ()
+/*+++
+ Debug routine to display the PC+MP config table
+--*/
+{
+ struct PcMpTable *MpPtr = PcMpTablePtr;
+ PPCMPPROCESSOR ProcPtr;
+ ULONG EntriesInTable = MpPtr->NumOfEntries;
+ union PL {
+ USHORT us;
+ POLARITYANDLEVEL PnL;
+ };
+
+ HalpDisplayString("PcMp Configuration Table\n");
+
+ HalpDisplayItem(MpPtr->Signature, "Signature");
+ HalpDisplayItem(MpPtr->TableLength, "TableLength");
+ HalpDisplayItem(MpPtr->Revision, "Revision");
+ HalpDisplayItem(MpPtr->Checksum, "Checksum");
+
+ HalpDisplayItemBuf(sizeof(MpPtr->OemId),
+ MpPtr->OemId,"OemId");
+ HalpDisplayItemBuf(sizeof(MpPtr->OemProductId),
+ MpPtr->OemProductId,"OemProductId");
+
+ HalpDisplayItem((ULONG) MpPtr->OemTablePtr, "OemTablePtr");
+ HalpDisplayItem(MpPtr->OemTableSize, "OemTableSize");
+ HalpDisplayItem(MpPtr->NumOfEntries, "NumOfEntries");
+ HalpDisplayItem((ULONG) MpPtr->LocalApicAddress, "LocalApicAddress");
+ HalpDisplayItem(MpPtr->Reserved, "Reserved");
+
+ ProcPtr = (PPCMPPROCESSOR) ((PUCHAR) MpPtr + HEADER_SIZE);
+
+
+ while (EntriesInTable) {
+ EntriesInTable--;
+ switch ( ProcPtr->EntryType ) {
+ case ENTRY_PROCESSOR: {
+ union xxx {
+ ULONG ul;
+ CPUIDENTIFIER CpuId;
+ } u;
+
+ sprintf (Cbuf, "Proc..: ApicId %x, Apic ver %x, Flags %x\n",
+ ProcPtr->LocalApicId,
+ ProcPtr->LocalApicVersion,
+ ProcPtr->CpuFlags
+ );
+ HalpDisplayString (Cbuf);
+ ProcPtr++;
+ break;
+ }
+
+ case ENTRY_BUS: {
+ PPCMPBUS BusPtr = (PPCMPBUS) ProcPtr;
+
+ sprintf (Cbuf, "Bus...: id %02x, type '%.6s'\n",
+ BusPtr->BusId, BusPtr->BusType);
+
+ HalpDisplayString (Cbuf);
+ BusPtr++;
+ ProcPtr = (PPCMPPROCESSOR) BusPtr;
+ break;
+ }
+
+ case ENTRY_IOAPIC: {
+ PPCMPIOAPIC IoApPtr = (PPCMPIOAPIC) ProcPtr;
+
+ sprintf (Cbuf, "IoApic: id %02x, ver %x, Flags %x, Address %x\n",
+ IoApPtr->IoApicId,
+ IoApPtr->IoApicVersion,
+ IoApPtr->IoApicFlag,
+ (ULONG) IoApPtr->IoApicAddress
+ );
+ HalpDisplayString (Cbuf);
+
+ IoApPtr++;
+ ProcPtr = (PPCMPPROCESSOR) IoApPtr;
+ break;
+ }
+
+ case ENTRY_INTI: {
+ PPCMPINTI IntiPtr = (PPCMPINTI) ProcPtr;
+ union PL u;
+
+ u.PnL = IntiPtr->Signal;
+
+ sprintf (Cbuf, "Inti..: t%x, s%x, SInt %x-%x, Inti %x-%x\n",
+ IntiPtr->IntType,
+ u.us,
+ IntiPtr->SourceBusId,
+ IntiPtr->SourceBusIrq,
+ IntiPtr->IoApicId,
+ IntiPtr->IoApicInti
+ );
+ HalpDisplayString (Cbuf);
+
+ IntiPtr++;
+ ProcPtr = (PPCMPPROCESSOR) IntiPtr;
+ break;
+ }
+
+ case ENTRY_LINTI: {
+ PPCMPLINTI LIntiPtr = (PPCMPLINTI) ProcPtr;
+ union PL u;
+
+ u.PnL = LIntiPtr->Signal;
+
+ sprintf (Cbuf, "Linti.: t%x, s%x, SInt %x-%x, Linti %x-%x\n",
+ LIntiPtr->IntType,
+ u.us,
+ LIntiPtr->SourceBusId,
+ LIntiPtr->SourceBusIrq,
+ LIntiPtr->DestLocalApicId,
+ LIntiPtr->DestLocalApicInti
+ );
+ HalpDisplayString (Cbuf);
+
+ LIntiPtr++;
+ ProcPtr = (PPCMPPROCESSOR) LIntiPtr;
+ break;
+ }
+
+ default: {
+ HalpDisplayItem(ProcPtr->EntryType, "Unknown Type");
+ return;
+ }
+ }
+ }
+}
+
+void
+HalpDisplayExtConfigTable ()
+{
+ PMPS_EXTENTRY ExtTable;
+ extern struct HalpMpInfo HalpMpInfoTable;
+
+
+ ExtTable = HalpMpInfoTable.ExtensionTable;
+ while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) {
+ switch (ExtTable->Type) {
+
+ case EXTTYPE_BUS_ADDRESS_MAP:
+ sprintf (Cbuf, "BusMap: id %02x, t%x Base %08x Len %08x\n",
+ ExtTable->u.AddressMap.BusId,
+ ExtTable->u.AddressMap.Type,
+ (ULONG) ExtTable->u.AddressMap.Base,
+ (ULONG) ExtTable->u.AddressMap.Length
+ );
+ HalpDisplayString (Cbuf);
+ break;
+
+ case EXTTYPE_BUS_HIERARCHY:
+ sprintf (Cbuf, "BusHie: id %02x, Parent:%x sd:%x\n",
+ ExtTable->u.BusHierarchy.BusId,
+ ExtTable->u.BusHierarchy.ParentBusId,
+ ExtTable->u.BusHierarchy.SubtractiveDecode
+ );
+ HalpDisplayString (Cbuf);
+ break;
+
+ case EXTTYPE_BUS_COMPATIBLE_MAP:
+ sprintf (Cbuf, "ComBus: id %02x %c List %x\n",
+ ExtTable->u.CompatibleMap.BusId,
+ ExtTable->u.CompatibleMap.Modifier ? '-' : '+',
+ ExtTable->u.CompatibleMap.List
+ );
+ HalpDisplayString (Cbuf);
+ break;
+
+ case EXTTYPE_PERSISTENT_STORE:
+ sprintf (Cbuf, "PreSTR: Address %08x Len %08x\n",
+ (ULONG) ExtTable->u.PersistentStore.Address,
+ (ULONG) ExtTable->u.PersistentStore.Length
+ );
+ HalpDisplayString (Cbuf);
+ break;
+
+ default:
+ HalpDisplayItem(ExtTable->Type, "Unknown Type");
+ break;
+ }
+
+
+ ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length);
+ }
+
+}
+
+
+void
+HalpDisplayMpInfo()
+{
+#if 0
+ struct HalpMpInfo *MpPtr = HalpMpInfoPtr;
+
+ HalpDisplayString("\nHAL: Private Mp Info\n");
+
+ HalpDisplayItem(MpPtr->ApicVersion, "ApicVersion");
+ HalpDisplayItem(MpPtr->ProcessorCount, "ProcessorCount");
+ HalpDisplayItem(MpPtr->BusCount, "BusCount");
+ HalpDisplayItem(MpPtr->IOApicCount, "IOApicCount");
+ HalpDisplayItem(MpPtr->IntiCount, "IntiCount");
+ HalpDisplayItem(MpPtr->LintiCount, "LintiCount");
+ HalpDisplayItem(MpPtr->IMCRPresent, "IMCRPresent");
+
+ HalpDisplayULItemBuf(4,(PULONG) MpPtr->IoApicBase,"IoApicBase");
+ HalpDisplayString("\n");
+ HalpDisplayConfigTable();
+
+#endif
+}
+
+
+#ifdef OLD_DEBUG
+
+BOOLEAN
+HalpVerifyLocalUnit(
+ IN UCHAR ApicID
+ )
+/*++
+
+Routine Description:
+
+ Verify that a Local Apic has the specified Apic Id.
+
+ Arguments:
+
+ ApicId - Id to verify.
+
+ Return Value:
+ BOOLEAN - TRUE if found
+ - FALSE otherwise
+
+--*/
+
+{
+ union ApicUnion Temp;
+
+ //
+ // The remote read command must be:
+ //
+ // Vector - Bits 4-9 of the Version register
+ // Destination Mode - Physical
+ // Trigger Mode - Edge
+ // Delivery Mode - Remote Read
+ // Destination Shorthand - Destination Field
+ //
+
+#define LU_READ_REMOTE_VERSION ( (LU_VERS_REGISTER >> 4) | \
+ DELIVER_REMOTE_READ | \
+ ICR_USE_DEST_FIELD)
+
+#define DEFAULT_DELAY 100
+
+ PVULONG LuDestAddress = (PVULONG) (LOCALAPIC + LU_INT_CMD_HIGH);
+ PVULONG LuICR = (PVULONG) (LOCALAPIC + LU_INT_CMD_LOW);
+ PVULONG LuRemoteReg = (PVULONG) (LOCALAPIC + LU_REMOTE_REGISTER);
+ ULONG RemoteReadStatus;
+ ULONG DelayCount = DEFAULT_DELAY;
+
+ //
+ // First make sure we can get to the Apic Bus
+ //
+
+ while ( ( DelayCount-- ) && ( *LuICR & DELIVERY_PENDING ) );
+
+ if (DelayCount == 0) {
+ //
+ // We're toast, can't gain access to the APIC Bus
+ //
+ return (FALSE);
+ }
+
+ //
+ // Set the Address of the APIC we're looking for
+ //
+
+ *LuDestAddress = (ApicID << DESTINATION_SHIFT);
+
+ //
+ // Issue the request
+ //
+
+ *LuICR = LU_READ_REMOTE_VERSION;
+
+ //
+ // Reset the Delay so we can get out of here just in case...
+ //
+
+ DelayCount = DEFAULT_DELAY;
+
+ while (DelayCount--) {
+
+ RemoteReadStatus = *LuICR & ICR_RR_STATUS_MASK;
+
+ if ( RemoteReadStatus == ICR_RR_INVALID) {
+ //
+ // No One responded, device timed out
+ //
+ return (FALSE);
+ }
+
+ if ( RemoteReadStatus == ICR_RR_VALID) {
+ //
+ // Someone is there and the Remote Register is valid
+ //
+ Temp.Raw = *LuRemoteReg;
+
+ //
+ // Do what we can to verify the Version
+ //
+
+ if (Temp.Ver.Version > 0x1f) {
+ //
+ // Only known devices are 0.x and 1.x
+ //
+ return (FALSE);
+ }
+
+ return (TRUE);
+
+ } // RemoteRead Successfull
+
+ } // While DelayCount
+
+ //
+ // No One responded, and the device did not time out
+ // This should never happen
+ //
+
+ return (FALSE);
+}
+
+#endif // OLD_DEBUG
+
+VOID
+CreateBIOSTables(
+ VOID)
+/*++
+
+Routine Description:
+ This routine is used to test the PC+MP detect code in the HAL.
+ It creates the PC+MP structures that are really created by the
+ BIOS. Since we presently do not have a BIOS that builds a PC+MP
+ table, we need this for now.
+
+Arguments:
+ None.
+
+ Return Value:
+ None.
+
+--*/
+
+{
+ PUCHAR TempPtr, BytePtr;
+ UCHAR CheckSum;
+ PULONG TraversePtr;
+ USHORT BytesToCopy;
+
+ HalpDisplayString("CreateBIOSTables : Entered\n");
+ // First, copy default PC+MP configuration 2 table at physical
+ // address PCMP_TEST_TABLE
+ TempPtr = (PUCHAR) HalpMapPhysicalMemory(
+ (PVOID) PCMP_TEST_TABLE, 1);
+
+ BytesToCopy = (PcMpDefaultTablePtrs[1])->TableLength;
+ RtlMoveMemory(TempPtr, (PUCHAR)PcMpDefaultTablePtrs[1],
+ BytesToCopy);
+
+ // Populate the checksum entry for the table.
+ CheckSum = ComputeCheckSum(TempPtr, BytesToCopy);
+
+ sprintf(Cbuf, "CreateBIOSTables: PC+MP table computed checksum = %x\n",
+ CheckSum);
+ HalpDisplayString(Cbuf);
+
+ CheckSum = ~CheckSum + 1;
+ ((struct PcMpTable *)TempPtr)->Checksum = CheckSum;
+
+ sprintf(Cbuf, "CreateBIOSTables: PC+MP table written checksum = %x\n",
+ CheckSum);
+ HalpDisplayString(Cbuf);
+
+
+ // Now create the floating pointer structure for the table.
+
+ TraversePtr = (PULONG) HalpMapPhysicalMemory( (PVOID) TEST_FLOAT_PTR, 1);
+ TempPtr = (PUCHAR) TraversePtr;
+
+ *TraversePtr++ = MP_PTR_SIGNATURE;
+ *TraversePtr++ = PCMP_TEST_TABLE;
+ BytePtr = (PUCHAR)TraversePtr;
+ *BytePtr++ = 1; // Length in number of 16 byte paragraphs
+ *BytePtr++ = 1; // Spec Rev.
+ *BytePtr++ = 0; // CheckSum
+ *BytePtr++ = 0; // Reserved
+ TraversePtr = (PULONG)BytePtr;
+ *TraversePtr = 0; // Reserved
+
+ CheckSum = ComputeCheckSum(TempPtr,16);
+
+ sprintf(Cbuf, "CreateBIOSTables: FLOAT_PTR computed checksum = %x\n",
+ CheckSum);
+ HalpDisplayString(Cbuf);
+
+ CheckSum = ~CheckSum + 1;
+
+ sprintf(Cbuf, "CreateBIOSTables: FLOAT_PTR written checksum = %x\n",
+ CheckSum);
+ HalpDisplayString(Cbuf);
+
+ ((struct PcMpTableLocator *)TempPtr)->TableChecksum = CheckSum;
+
+ HalpDisplayString("CreateBIOSTables : Done\n");
+
+}
+
+#endif // DEBUGGING
diff --git a/private/ntos/nthals/halmps/i386/mpdetect.c b/private/ntos/nthals/halmps/i386/mpdetect.c
new file mode 100644
index 000000000..e787c718d
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpdetect.c
@@ -0,0 +1,522 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Intel Corporation
+All rights reserved
+
+INTEL CORPORATION PROPRIETARY INFORMATION
+
+This software is supplied to Microsoft under the terms
+of a license agreement with Intel Corporation and may not be
+copied nor disclosed except in accordance with the terms
+of that agreement.
+
+Module Name:
+
+ mpdetect.c
+
+Abstract:
+
+ This module detects an MPS system.
+
+Author:
+
+ Ron Mosgrove (Intel) - Aug 1993.
+
+Environment:
+
+ Kernel mode or from textmode setup.
+
+Revision History:
+ Rajesh Shah (Intel) - Oct 1993. Added support for MPS table.
+
+--*/
+
+#ifndef _NTOS_
+#include "halp.h"
+#endif
+
+#ifdef SETUP
+#define FAILMSG(a)
+#else
+#define FAILMSG(a) HalDisplayString(a)
+extern UCHAR rgzNoMpsTable[];
+extern UCHAR rgzNoApic[];
+extern UCHAR rgzBadApicVersion[];
+extern UCHAR rgzApicNotVerified[];
+extern UCHAR rgzMPPTRCheck[];
+extern UCHAR rgzNoMPTable[];
+extern UCHAR rgzMPSBadSig[];
+extern UCHAR rgzMPSBadCheck[];
+extern UCHAR rgzBadDefault[];
+#endif
+
+
+// Include the code that actually detect a MPS system
+#include "pcmpdtct.c"
+
+
+BOOLEAN
+HalpVerifyIOUnit (
+ IN PUCHAR BaseAddress
+ );
+
+VOID
+HalpInitMpInfo (
+ IN struct PcMpTable *MpTablePtr
+ );
+
+ULONG
+DetectMPS (
+ OUT PBOOLEAN IsConfiguredMp
+ );
+
+ULONG
+DetectUPMPS (
+ OUT PBOOLEAN IsConfiguredMp
+ );
+
+extern struct PcMpTable *GetPcMpTable( VOID );
+
+ULONG UserSpecifiedNoIoApic = 0;
+
+struct HalpMpInfo HalpMpInfoTable;
+struct PcMpTable HalpPcMpTable;
+
+struct PcMpTable *PcMpTablePtr;
+
+PVOID
+HalpMapPhysicalMemoryWriteThrough(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+#ifndef SETUP
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpVerifyIOUnit)
+#pragma alloc_text(INIT,HalpInitMpInfo)
+#pragma alloc_text(INIT,DetectMPS)
+#pragma alloc_text(INIT,DetectUPMPS)
+#endif // ALLOC_PRAGMA
+
+extern struct PcMpTable *PcMpDefaultTablePtrs[];
+
+PVOID
+HalpRemapVirtualAddress (
+ IN PVOID VirtualAddress,
+ IN PVOID PhysicalAddress,
+ IN BOOLEAN WriteThrough
+ );
+
+#endif // SETUP
+
+
+BOOLEAN
+HalpVerifyIOUnit(
+ IN PUCHAR BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ Verify that an IO Unit exists at the specified address
+
+ Arguments:
+
+ BaseAddress - Virtual address of the IO Unit to test.
+
+ Return Value:
+ BOOLEAN - TRUE if a IO Unit was found at the passed address
+ - FALSE otherwise
+
+--*/
+
+{
+ union ApicUnion {
+ ULONG Raw;
+ struct ApicVersion Ver;
+ } Temp1, Temp2;
+
+ struct ApicIoUnit *IoUnitPtr = (struct ApicIoUnit *) BaseAddress;
+
+ //
+ // The documented detection mechanism is to write all zeros to
+ // the Version register. Then read it back. The IO Unit exists if the
+ // same result is read both times and the Version is valid.
+ //
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ IoUnitPtr->RegisterWindow = 0;
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ Temp1.Raw = IoUnitPtr->RegisterWindow;
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ IoUnitPtr->RegisterWindow = 0;
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ Temp2.Raw = IoUnitPtr->RegisterWindow;
+
+ if ((Temp1.Ver.Version != Temp2.Ver.Version) ||
+ (Temp1.Ver.MaxRedirEntries != Temp2.Ver.MaxRedirEntries)) {
+ //
+ // No IO Unit There
+ //
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+VOID
+HalpInitMpInfo (
+ IN struct PcMpTable *MpTablePtr
+ )
+
+/*++
+Routine Description:
+ This routine initializes a HAL specific data structure that is
+ used by the HAL to simplify access to MP information.
+
+Arguments:
+ MpTablePtr: Pointer to the MPS table.
+
+ Return Value:
+ Pointer to the HAL MP information table.
+
+*/
+{
+ PUCHAR TraversePtr;
+ UCHAR CheckSum;
+
+ // Walk the MPS table. The HAL MP information structure has
+ // pointers to the first entry for each entry type in the MPS
+ // table. Set these pointers.
+
+ TraversePtr = (PUCHAR) MpTablePtr + HEADER_SIZE;
+
+ HalpMpInfoTable.ProcessorEntryPtr = (PPCMPPROCESSOR) TraversePtr;
+
+ HalpMpInfoTable.ApicVersion =
+ (ULONG) (HalpMpInfoTable.ProcessorEntryPtr[0].LocalApicVersion & 0xf0);
+
+ while(((PPCMPPROCESSOR)(TraversePtr))->EntryType == ENTRY_PROCESSOR) {
+ if(((PPCMPPROCESSOR)(TraversePtr))->CpuFlags & CPU_ENABLED) {
+ HalpMpInfoTable.ProcessorCount += 1;
+ }
+ TraversePtr += sizeof(PCMPPROCESSOR);
+ }
+
+ HalpMpInfoTable.BusEntryPtr = (PPCMPBUS) TraversePtr;
+ while(((PPCMPBUS)(TraversePtr))->EntryType == ENTRY_BUS) {
+ HalpMpInfoTable.BusCount += 1;
+ TraversePtr += sizeof(PCMPBUS);
+ }
+
+ HalpMpInfoTable.IoApicEntryPtr = (PPCMPIOAPIC) TraversePtr;
+ while(((PPCMPIOAPIC)(TraversePtr))->EntryType == ENTRY_IOAPIC) {
+ if(((PPCMPIOAPIC)(TraversePtr))->IoApicFlag & IO_APIC_ENABLED) {
+ HalpMpInfoTable.IOApicCount += 1;
+ }
+ TraversePtr += sizeof(PCMPIOAPIC);
+ }
+
+ if (UserSpecifiedNoIoApic) {
+ HalpMpInfoTable.IOApicCount = 0;
+ }
+
+ HalpMpInfoTable.IntiEntryPtr = (PPCMPINTI) TraversePtr;
+ while(((PPCMPINTI)(TraversePtr))->EntryType == ENTRY_INTI) {
+ HalpMpInfoTable.IntiCount += 1;
+ TraversePtr += sizeof(PCMPINTI);
+ }
+
+ HalpMpInfoTable.LintiEntryPtr = (PPCMPLINTI) TraversePtr;
+ while(((PPCMPLINTI)(TraversePtr))->EntryType == ENTRY_LINTI) {
+ HalpMpInfoTable.LintiCount += 1;
+ TraversePtr += sizeof(PCMPLINTI);
+ }
+
+ //
+ // Check for Extension table defined
+ //
+
+ if (MpTablePtr->ExtTableLength &&
+ MpTablePtr->TableLength + MpTablePtr->ExtTableLength < 8192) {
+
+ CheckSum = ComputeCheckSum(
+ (PUCHAR) MpTablePtr + MpTablePtr->TableLength,
+ MpTablePtr->ExtTableLength
+ );
+
+ CheckSum += MpTablePtr->ExtTableChecksum;
+
+ if (CheckSum != 0) {
+ DBGMSG("HALMPS: InitMpInfo: Extension table checksum error\n");
+
+ } else {
+ HalpMpInfoTable.ExtensionTable = (PMPS_EXTENTRY)
+ (((PUCHAR) MpTablePtr) + MpTablePtr->TableLength);
+
+ HalpMpInfoTable.EndOfExtensionTable = (PMPS_EXTENTRY)
+ (((PUCHAR) MpTablePtr) + MpTablePtr->TableLength +
+ MpTablePtr->ExtTableLength);
+ }
+ }
+
+ return;
+}
+
+
+ULONG
+DetectMPS(
+ OUT PBOOLEAN IsConfiguredMp
+)
+
+/*++
+
+Routine Description:
+
+ This function is called from HalInitializeProcessors to determine
+ if this is an appropriate system to run the MPS hal on.
+
+ The recommended detection mechanism is:
+
+ if ( MPS information does not exist )
+ then
+ System is not MPS compliant. Return false.
+
+ In MP table:
+ if ( number IO APICs < 1 )
+ then
+ Not a MPS System - return false
+
+ if ( # CPUs = 1 )
+ then
+ Found a Single Processor MPS System
+ else
+ Found a MP MPS System
+
+
+ A side effect of this routine is the mapping of the IO UNits and
+ Local unit virtual addresses.
+
+ Return TRUE
+
+
+ Arguments:
+
+ IsConfiguredMp - TRUE if this machine is a MP instance of the MPS spec, else FALSE.
+
+ Return Value:
+ 0 - if not a MPS
+ 1 - if MPS
+
+*/
+{
+
+ UCHAR ApicVersion, i;
+ PUCHAR LocalApic;
+ PPCMPIOAPIC IoEntryPtr;
+
+ //
+ // Initialize MpInfo table
+ //
+
+ RtlZeroMemory (&HalpMpInfoTable, sizeof HalpMpInfoTable);
+
+ //
+ // Set the return Values to the default
+ //
+
+ *IsConfiguredMp = FALSE;
+
+ //
+ // See if there is a MP Table
+ //
+
+#if 1
+ if ((PcMpTablePtr = GetPcMpTable()) == NULL) {
+ FAILMSG (rgzNoMpsTable);
+ return(FALSE);
+ }
+#else
+ //********
+ //******** HACK! To make down level 1.0 machine work
+ //********
+
+ if ((PcMpTablePtr = MPS10_GetPcMpTable()) == NULL) {
+ FAILMSG (rgzNoMpsTable);
+ return(FALSE);
+ }
+#endif
+
+#ifdef SETUP
+ // During setup, if we detected a default MPS configuration, we have
+ // no more checking to do.
+ if (PcMpTablePtr == (struct PcMpTable *) DEFAULT_MPS_INDICATOR) {
+ *IsConfiguredMp = TRUE;
+ return(TRUE);
+ }
+#endif // SETUP
+
+#if DEBUGGING
+ HalpDisplayConfigTable();
+#endif
+
+ // We have a MPS table. Initialize a HAL specific MP information
+ // structure that gets information from the MPS table.
+
+ HalpInitMpInfo(PcMpTablePtr);
+
+
+ // Verify the information in the MPS table as best as we can.
+
+ if (HalpMpInfoTable.IOApicCount == 0) {
+ //
+ // Someone Has a MP Table and no IO Units -- Weird
+ // We have to assume the BIOS knew what it was doing
+ // when it built the table. so ..
+ //
+ FAILMSG (rgzNoApic);
+ return (FALSE);
+ }
+
+ //
+ // It's a MPS System. It could be a UP System though.
+ //
+
+#ifdef SETUP
+ //
+ // If this is a MPS (MPS) compliant system, but has only 1 processor,
+ // for now we want to install a standard UP kernel and HAL.
+ //
+
+ if (HalpMpInfoTable.ProcessorCount <= 1) {
+ return FALSE;
+ }
+#endif
+
+ if (HalpMpInfoTable.ProcessorCount > 1) {
+ *IsConfiguredMp = TRUE;
+ }
+
+ HalpMpInfoTable.LocalApicBase = (ULONG) PcMpTablePtr->LocalApicAddress;
+ LocalApic = (PUCHAR) HalpMapPhysicalMemoryWriteThrough(
+ (PVOID) HalpMpInfoTable.LocalApicBase,1);
+
+#ifndef SETUP
+ HalpRemapVirtualAddress (
+ (PVOID) LOCALAPIC,
+ (PVOID) HalpMpInfoTable.LocalApicBase,
+ TRUE
+ );
+#endif
+
+ ApicVersion = (UCHAR) *(LocalApic + LU_VERS_REGISTER);
+
+ if (ApicVersion > 0x1f) {
+ //
+ // Only known Apics are 82489dx with version 0.x and
+ // Embedded Apics with version 1.x (where x is don't care)
+ //
+ // Return of 0xFF? Can't have an MPS system without a Local Unit.
+ //
+
+#ifdef DEBUGGING
+ sprintf(Cbuf, "HALMPS: apic version %x, read from %x\n",
+ ApicVersion, LocalApic + LU_VERS_REGISTER);
+
+ HalDisplayString(Cbuf);
+#endif
+
+ FAILMSG (rgzBadApicVersion);
+ return (FALSE);
+ }
+
+#ifdef SETUP
+ //
+ // MP MPS table, and the local APIC ID looked OK.
+ //
+
+ return TRUE;
+#endif //SETUP
+
+
+#ifdef DEBUGGING
+ if ((ApicVersion & 0xf0) == 0) {
+ if (HalpMpInfoTable.ApicVersion != APIC_82489DX)
+ HalDisplayString("HAL:Invalid Local Apic version in MP table\n");
+ else {
+ sprintf(Cbuf, "HAL: DetectMPS: Found 82489DX Local APIC (Ver 0x%x) at 0x%lx\n",
+ ApicVersion, LocalApic);
+ HalDisplayString(Cbuf);
+ }
+ } else {
+ sprintf(Cbuf, "HAL: DetectMPS: Found Embedded Local APIC (Ver 0x%x) at 0x%lx\n",
+ ApicVersion, LocalApic);
+ HalDisplayString(Cbuf);
+
+ }
+#endif // DEBUGGING
+
+ IoEntryPtr = HalpMpInfoTable.IoApicEntryPtr;
+
+ for(i=0; i < HalpMpInfoTable.IOApicCount; i++, IoEntryPtr++)
+ {
+ if (IoEntryPtr->IoApicFlag & IO_APIC_ENABLED) {
+ //
+ // Verify the existance of the IO Units
+ //
+
+ HalpMpInfoTable.IoApicPhys[i] = (ULONG) IoEntryPtr->IoApicAddress;
+ HalpMpInfoTable.IoApicBase[i] = (PULONG)
+ HalpMapPhysicalMemoryWriteThrough(
+ (PVOID)(IoEntryPtr->IoApicAddress), 1);
+
+ //
+ // Verify the existance of the IO Unit
+ //
+ if (!(HalpVerifyIOUnit((PUCHAR)HalpMpInfoTable.IoApicBase[i]))) {
+ FAILMSG (rgzApicNotVerified);
+ return (FALSE);
+ }
+ }
+ }
+
+ DBGMSG("HAL: DetectMPS: MPS system found - Returning TRUE\n");
+ return(TRUE);
+}
+
+
+ULONG
+DetectUPMPS(
+ OUT PBOOLEAN IsConfiguredMp
+)
+/*++
+
+Routine Description:
+
+ This function is called by setup after DetectMPS has returned
+ false. During setup time DetectMPS will return false, if the
+ machine is an MPS system, but only has one processor. This
+ function is used to detect such a machine at setup time.
+
+ Arguments:
+
+ IsConfiguredMp - FALSE
+
+ Return Value:
+ 0 - if not a UP MPS
+ 1 - if UP MPS
+
+--*/
+{
+ *IsConfiguredMp = FALSE;
+
+ // we assume the caller has already called DetectMPS, and the
+ // MPS table has already been parsed.
+
+ return (HalpMpInfoTable.ProcessorCount == 1 ? TRUE : FALSE);
+}
diff --git a/private/ntos/nthals/halmps/i386/mphal.c b/private/ntos/nthals/halmps/i386/mphal.c
new file mode 100644
index 000000000..72359e72e
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mphal.c
@@ -0,0 +1,683 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Intel Corporation
+All rights reserved
+
+INTEL CORPORATION PROPRIETARY INFORMATION
+
+This software is supplied to Microsoft under the terms
+of a license agreement with Intel Corporation and may not be
+copied nor disclosed except in accordance with the terms
+of that agreement.
+
+Module Name:
+
+ mphal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ PC+MP system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Ron Mosgrove (Intel) - Modified to support the PC+MP Spec
+
+*/
+
+#include "halp.h"
+#include "pcmp_nt.inc"
+#include "string.h"
+#include "stdlib.h"
+#include "stdio.h"
+
+ULONG HalpBusType;
+extern ULONG HalpRTCApic, HalpRTCInti;
+
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern ADDRESS_USAGE HalpImcrIoSpace;
+extern struct HalpMpInfo HalpMpInfoTable;
+extern UCHAR rgzRTCNotFound[];
+extern UCHAR HalpVectorToINTI[];
+extern UCHAR HalpGenuineIntel[];
+
+VOID
+HalpInitMP(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+KSPIN_LOCK HalpSystemHardwareLock;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpClockInterruptPn(
+ VOID
+ );
+
+VOID
+HalpClockInterruptStub(
+ VOID
+ );
+
+ULONG
+HalpScaleTimers(
+ VOID
+ );
+
+VOID
+HalpApicRebootService(
+ VOID
+ );
+
+VOID
+HalpBroadcastCallService(
+ VOID
+ );
+
+VOID
+HalpDispatchInterrupt(
+ VOID
+ );
+
+VOID
+HalpApcInterrupt(
+ VOID
+ );
+
+VOID
+HalpIpiHandler(
+ VOID
+ );
+
+VOID
+HalpInitializeIOUnits (
+ VOID
+ );
+
+VOID
+HalpInitIntiInfo (
+ VOID
+ );
+
+VOID
+HalpInti2ApicInti (
+ ULONG Inti,
+ PULONG Apic,
+ PULONG ApicInti
+ );
+
+VOID
+HalpGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+ULONG
+HalpGetFeatureBits (
+ VOID
+ );
+
+
+#ifdef DEBUGGING
+extern void HalpDisplayLocalUnit(void);
+extern void HalpDisplayConfigTable(void);
+extern void HalpDisplayExtConfigTable(void);
+#endif // DEBUGGING
+
+
+BOOLEAN HalpClockMode = Latched;
+extern BOOLEAN HalpPciLockSettings;
+extern UCHAR HalpVectorToIRQL[];
+extern ULONG HalpDontStartProcessors;
+extern UCHAR HalpSzOneCpu[];
+extern UCHAR HalpSzNoIoApic[];
+extern UCHAR HalpSzBreak[];
+extern UCHAR HalpSzPciLock[];
+extern UCHAR HalpSzClockLevel[];
+
+ULONG UserSpecifiedCpuCount = 0;
+KSPIN_LOCK HalpAccountingLock;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetParameters)
+#pragma alloc_text(INIT,HalInitSystem)
+#pragma alloc_text(INIT,HalpGetFeatureBits)
+#endif // ALLOC_PRAGMA
+
+#ifndef NT_UP
+KIRQL
+FASTCALL
+KeAcquireSpinLockRaiseToSynchMCE(
+ IN PKSPIN_LOCK SpinLock
+ );
+
+KIRQL
+FASTCALL
+KeAcquireSpinLockRaiseToSynch (
+ IN PKSPIN_LOCK SpinLock
+ );
+#endif
+
+
+
+VOID
+HalpGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This gets any parameters from the boot.ini invocation line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PCHAR Options;
+
+ if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
+
+ Options = LoaderBlock->LoadOptions;
+
+ //
+ // Has the user set the debug flag?
+ //
+ //
+ // Has the user requested a particular number of CPU's?
+ //
+
+ if (strstr(Options, HalpSzOneCpu)) {
+ HalpDontStartProcessors++;
+ }
+
+ //
+ // Check if PCI settings are locked down
+ //
+
+ if (strstr(Options, HalpSzPciLock)) {
+ HalpPciLockSettings = TRUE;
+ }
+
+ //
+ // Check if CLKLVL setting
+ //
+
+ if (strstr(Options, HalpSzClockLevel)) {
+ HalpClockMode = LevelSensitive;
+ }
+
+ //
+ // Has the user asked for an initial BreakPoint?
+ //
+
+ if (strstr(Options, HalpSzBreak)) {
+ DbgBreakPoint();
+ }
+ }
+
+ return ;
+}
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PKPRCB pPRCB;
+ PKPCR pPCR;
+ BOOLEAN Found;
+ ULONG RTCInti;
+
+#ifdef DEBUGGING
+extern ULONG HalpUseDbgPrint;
+#endif // DEBUGGING
+
+ pPRCB = KeGetCurrentPrcb();
+
+ if (Phase == 0) {
+
+
+ HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
+ HalpGetParameters (LoaderBlock);
+
+ //
+ // Verify Prcb version and build flags conform to
+ // this image
+ //
+
+#if DBG
+ if (!(pPRCB->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL,
+ 2, pPRCB->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (pPRCB->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
+ }
+#endif
+ if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ KeInitializeSpinLock(&HalpAccountingLock);
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+#ifndef NT_35
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HalpSetSystemInformation;
+#endif
+ //
+ // Phase 0 initialization only called by P0
+ //
+
+#ifdef DEBUGGING
+ HalpUseDbgPrint++;
+ HalpDisplayLocalUnit();
+ HalpDisplayConfigTable();
+ HalpDisplayExtConfigTable();
+#endif // DEBUGGING
+
+ //
+ // Register PC style IO space used by hal
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ }
+
+ if (HalpMpInfoTable.IMCRPresent) {
+ HalpRegisterAddressUsage (&HalpImcrIoSpace);
+ }
+
+ //
+ // initialize the APIC IO unit, this could be a NOP if none exist
+ //
+
+ HalpInitIntiInfo ();
+
+ HalpInitializeIOUnits();
+
+ HalpInitializePICs();
+
+ //
+ // Initialize CMOS
+ //
+
+ HalpInitializeCmos();
+
+ //
+ // Find the RTC interrupt.
+ //
+
+ Found = HalpGetPcMpInterruptDesc (
+ DEFAULT_PC_BUS,
+ 0,
+ 8, // looking for RTC on ISA-Irq8
+ &RTCInti
+ );
+
+ if (!Found) {
+ HalDisplayString (rgzRTCNotFound);
+ return FALSE;
+ }
+
+ HalpInti2ApicInti (RTCInti, &HalpRTCApic, &HalpRTCInti);
+
+ //
+ // Initialize timers
+ //
+
+ HalpScaleTimers();
+
+ //
+ // Initialize the reboot handler
+ //
+
+ HalpSetInternalVector(APIC_REBOOT_VECTOR, HalpApicRebootService);
+ HalpSetInternalVector(APIC_GENERIC_VECTOR, HalpBroadcastCallService);
+
+ //
+ // Initialize the clock for the processor that keeps
+ // the system time. This uses a stub ISR until Phase 1
+ //
+
+ KiSetHandlerAddressToIDT(APIC_CLOCK_VECTOR, HalpClockInterruptStub );
+
+ HalpVectorToINTI[APIC_CLOCK_VECTOR] = (UCHAR) RTCInti;
+ HalEnableSystemInterrupt(APIC_CLOCK_VECTOR, CLOCK2_LEVEL, HalpClockMode);
+
+ HalpInitializeClock();
+
+ HalpRegisterVector (
+ DeviceUsage,
+ 8, // Clock is on ISA IRQ 8
+ APIC_CLOCK_VECTOR,
+ HalpVectorToIRQL [APIC_CLOCK_VECTOR >> 4]
+ );
+
+ //
+ // Register NMI vector
+ //
+
+ HalpRegisterVector (
+ InternalUsage,
+ NMI_VECTOR,
+ NMI_VECTOR,
+ HIGH_LEVEL
+ );
+
+
+ //
+ // Register spurious IDTs as in use
+ //
+
+ HalpRegisterVector (
+ InternalUsage,
+ APIC_SPURIOUS_VECTOR,
+ APIC_SPURIOUS_VECTOR,
+ HIGH_LEVEL
+ );
+
+
+ //
+ // Initialize the profile interrupt vector.
+ //
+
+ KeSetProfileIrql(HIGH_LEVEL);
+ HalStopProfileInterrupt(0);
+ HalpSetInternalVector(APIC_PROFILE_VECTOR, HalpProfileInterrupt);
+
+ //
+ // Set performance interrupt vector
+ //
+
+ HalpSetInternalVector(APIC_PERF_VECTOR, HalpPerfInterrupt);
+
+ //
+ // Initialize the IPI, APC and DPC handlers
+ //
+
+ HalpSetInternalVector(DPC_VECTOR, HalpDispatchInterrupt);
+ HalpSetInternalVector(APC_VECTOR, HalpApcInterrupt);
+ HalpSetInternalVector(APIC_IPI_VECTOR, HalpIpiHandler);
+
+ HalpInitializeDisplay();
+
+ //
+ // Initialize spinlock used by HalGetBusData hardware access routines
+ //
+
+ KeInitializeSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
+ Descriptor->MemoryType != LoaderSpecialMemory &&
+ Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ break;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ } else {
+
+ //
+ // Phase 1 initialization
+ //
+
+ pPCR = KeGetPcr();
+
+ if (pPCR->Number == 0) {
+
+ HalpRegisterInternalBusHandlers ();
+
+ //
+ // Initialize the clock for the processor
+ // that keeps the system time.
+ //
+
+ KiSetHandlerAddressToIDT(APIC_CLOCK_VECTOR, HalpClockInterrupt );
+
+ //
+ // Set initial feature bits
+ //
+
+ HalpFeatureBits = HalpGetFeatureBits();
+
+ } else {
+ //
+ // Initialization needed only on non BSP processors
+ //
+
+ HalpScaleTimers();
+
+ //
+ // Initialize the clock for all other processors
+ //
+
+ KiSetHandlerAddressToIDT(APIC_CLOCK_VECTOR, HalpClockInterruptPn );
+
+ //
+ // Reduce feature bits to be a subset
+ //
+
+ HalpFeatureBits &= HalpGetFeatureBits();
+
+ }
+
+ //
+ // Enable system NMIs on Pn
+ //
+
+ HalpEnableNMI ();
+ }
+
+ HalpInitMP (Phase, LoaderBlock);
+ return TRUE;
+}
+
+ULONG
+HalpGetFeatureBits (
+ VOID
+ )
+{
+ UCHAR Buffer[50];
+ ULONG Junk, ProcessorStepping, ProcessorFeatures, Bits;
+ PULONG p1, p2;
+ PUCHAR OrgRoutineAddress;
+ PUCHAR MCERoutineAddress;
+ ULONG newop;
+ PKPRCB Prcb;
+
+
+ Bits = 0;
+
+ Prcb = KeGetCurrentPrcb();
+
+ if (!Prcb->CpuID) {
+ return Bits;
+ }
+
+ //
+ // Determine the processor type
+ //
+
+ HalpCpuID (0, &Junk, (PULONG) Buffer+0, (PULONG) Buffer+2, (PULONG) Buffer+1);
+ Buffer[12] = 0;
+
+ //
+ // If this is an Intel processor, determine whichNT compatible
+ // features are present
+ //
+
+ if (strcmp (Buffer, HalpGenuineIntel) == 0) {
+
+ HalpCpuID (1, &ProcessorStepping, &Junk, &Junk, &ProcessorFeatures);
+
+ //
+ // Check Intel feature bits for HAL features needed
+ //
+
+ if (Prcb->CpuType == 6) {
+ Bits |= HAL_PERF_EVENTS;
+ }
+
+ if (Prcb->CpuType < 6) {
+ Bits |= HAL_NO_SPECULATION;
+ }
+ if (ProcessorFeatures & CPUID_MCA_MASK) {
+ Bits |= HAL_MCA_PRESENT;
+ }
+
+ if (ProcessorFeatures & CPUID_MCE_MASK) {
+ Bits |= HAL_MCE_PRESENT;
+ }
+
+#ifndef NT_UP
+
+ //
+ // Check if IFU errata workaround is required
+ //
+
+ if (Prcb->Number == 0 && (Bits & HAL_MCA_PRESENT) &&
+ ((ProcessorStepping & 0x700) == 0x600) &&
+ ((ProcessorStepping & 0xF0) == 0x10) &&
+ ((ProcessorStepping & 0xF) <= 0x7) ) {
+
+ //
+ // If the stepping is 617 or earlier, provide software workaround
+ //
+
+ p1 = (PULONG) (KeAcquireSpinLockRaiseToSynch);
+ p2 = (PULONG) (KeAcquireSpinLockRaiseToSynchMCE);
+ newop = (ULONG) p2 - (ULONG) p1 - 2; // compute offset
+ ASSERT (newop < 0x7f); // verify within range
+ newop = 0xeb | (newop << 8); // short-jmp
+
+ *(p1) = newop; // patch it
+ }
+#endif
+ }
+
+ return Bits;
+}
diff --git a/private/ntos/nthals/halmps/i386/mpinfo.c b/private/ntos/nthals/halmps/i386/mpinfo.c
new file mode 100644
index 000000000..80f56e5d8
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpinfo.c
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "pcmp_nt.inc"
+
+
+extern ULONG HalpPerfInterruptHandler;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HalpSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+
+ switch (InformationClass) {
+ case HalProfileSourceInterruptHandler:
+
+ //
+ // Set ISR handler for PerfVector
+ //
+
+ if (!(HalpFeatureBits & HAL_PERF_EVENTS) || HalpPerfInterruptHandler) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ HalpPerfInterruptHandler = *((PULONG) Buffer);
+ return STATUS_SUCCESS;
+ }
+
+
+ return HaliSetSystemInformation (InformationClass, BufferSize, Buffer);
+}
diff --git a/private/ntos/nthals/halmps/i386/mpipi.asm b/private/ntos/nthals/halmps/i386/mpipi.asm
new file mode 100644
index 000000000..5b7ba47d9
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpipi.asm
@@ -0,0 +1,1044 @@
+
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 Intel Corporation
+;All rights reserved
+;
+;INTEL CORPORATION PROPRIETARY INFORMATION
+;
+;This software is supplied to Microsoft under the terms
+;of a license agreement with Intel Corporation and may not be
+;copied nor disclosed except in accordance with the terms
+;of that agreement.
+;
+;
+;Module Name:
+;
+; mpipi.asm
+;
+;Abstract:
+;
+; PC+MP IPI code.
+; Provides the HAL support for Interprocessor Interrupts and Processor
+; initialization for PC+MP Systems
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+; Ron Mosgrove (Intel) Aug 1993
+; Modified for PC+MP Systems
+;--
+.386p
+ .xlist
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include callconv.inc ; calling convention macros
+include i386\pcmp_nt.inc
+
+
+ EXTRNP Kei386EoiHelper,0,IMPORT
+
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalDisplayString,1
+ EXTRNP HalpAcquireHighLevelLock,1,,FASTCALL
+ EXTRNP HalpReleaseHighLevelLock,2,,FASTCALL
+ EXTRNP _DetectMPS,1
+
+ EXTRNP _HalpInitializeLocalUnit,0
+ EXTRNP _HalpResetThisProcessor,0
+if DBG OR DEBUGGING
+ EXTRNP _DbgBreakPoint,0,IMPORT
+endif
+ extrn _HalpDefaultInterruptAffinity:DWORD
+ extrn _HalpActiveProcessors:DWORD
+
+ extrn _HalpGlobal8259Mask:WORD
+ extrn _HalpPICINTToVector:BYTE
+ extrn _rgzBadHal:BYTE
+
+
+I386_80387_BUSY_PORT equ 0f0h
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ ALIGN dword
+
+ public _HalpProcessorPCR
+_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
+
+;
+; The following symbols are used by the Local Apic Error handler.
+;
+LogApicErrors equ 1
+if LogApicErrors
+
+ public _HalpLocalApicErrorLock
+ public _HalpLocalApicErrorCount
+ public _HalpApicErrorLog
+
+APIC_ERROR_LOG_SIZE equ 128 ; Must be 2^n see usage below
+
+ ALIGN dword
+
+_HalpApicErrorLog dw APIC_ERROR_LOG_SIZE dup(0)
+_HalpLocalApicErrorLock dd 0
+_HalpLocalApicErrorCount dd 0
+
+ ;
+ ; Bit:
+ ;
+ ; 0 - Send checksum error
+ ; 1 - Recieve checksum error
+ ; 2 - Send accept error
+ ; 3 - Receive accept error
+ ; 4 - reserved
+ ; 5 - Send illegal vector
+ ; 6 - Receive illegal vector
+ ; 7 - illegal register address
+ ; 8-31 - reserved
+ ;
+
+
+endif ; LogApicErrors
+
+ public HalpBroadcastLock, HalpBroadcastTargets
+ public HalpBroadcastFunction, HalpBroadcastContext
+HalpBroadcastLock dd 0
+HalpBroadcastFunction dd 0
+HalpBroadcastContext dd 0
+HalpBroadcastTargets dd 0
+
+ ALIGN dword
+;
+; The _PicExtintIntiHandlers and the _PicNopIntiHandlers tables are
+; used by the enable and disable system interrupt routines to determine
+; the EXTINT interrupt handler to install.
+;
+ public _PicExtintIntiHandlers
+_PicExtintIntiHandlers label dword
+ dd PicInterruptHandlerInti0 ; Inti 0 - PIC 1
+ dd PicInterruptHandlerInti1 ; Inti 1 - PIC 1
+ dd PicInterruptHandlerInti2 ; Inti 2 - PIC 1
+ dd PicInterruptHandlerInti3 ; Inti 3 - PIC 1
+ dd PicInterruptHandlerInti4 ; Inti 4 - PIC 1
+ dd PicInterruptHandlerInti5 ; Inti 5 - PIC 1
+ dd PicInterruptHandlerInti6 ; Inti 6 - PIC 1
+ dd PicInterruptHandlerInti7 ; Inti 7 - PIC 1
+ dd PicInterruptHandlerInti8 ; Inti 8 - PIC 2
+ dd PicInterruptHandlerInti9 ; Inti 9 - PIC 2
+ dd PicInterruptHandlerIntiA ; Inti 10 - PIC 2
+ dd PicInterruptHandlerIntiB ; Inti 11 - PIC 2
+ dd PicInterruptHandlerIntiC ; Inti 12 - PIC 2
+ dd PicInterruptHandlerIntiD ; Inti 13 - PIC 2
+ dd PicInterruptHandlerIntiE ; Inti 14 - PIC 2
+ dd PicInterruptHandlerIntiF ; Inti 15 - PIC 2
+
+ public _PicNopIntiHandlers
+_PicNopIntiHandlers label dword
+ dd PicNopHandlerInti0 ; Inti 0 - PIC 1
+ dd PicNopHandlerInti1 ; Inti 1 - PIC 1
+ dd PicNopHandlerInti2 ; Inti 2 - PIC 1
+ dd PicNopHandlerInti3 ; Inti 3 - PIC 1
+ dd PicNopHandlerInti4 ; Inti 4 - PIC 1
+ dd PicNopHandlerInti5 ; Inti 5 - PIC 1
+ dd PicNopHandlerInti6 ; Inti 6 - PIC 1
+ dd PicNopHandlerInti7 ; Inti 7 - PIC 1
+ dd CommonPic2NopHandler ; Inti 8 - PIC 2
+ dd CommonPic2NopHandler ; Inti 9 - PIC 2
+ dd CommonPic2NopHandler ; Inti 10 - PIC 2
+ dd CommonPic2NopHandler ; Inti 11 - PIC 2
+ dd CommonPic2NopHandler ; Inti 12 - PIC 2
+ dd PicNopHandlerIntiD ; Inti 13 - PIC 2
+ dd CommonPic2NopHandler ; Inti 14 - PIC 2
+ dd CommonPic2NopHandler ; Inti 15 - PIC 2
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . Enable IPI interrupt (makes sense for P1, P2, ...).
+; . Save Processor Number in PCR.
+; . if (P0)
+; . determine if the system is a PC+MP,
+; . if not a PC+MP System Halt;
+; . Enable IPI's on CPU.
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor ,1
+
+ mov PCR[PcIDR], 0FFFFFFFFH ; mark all INTs as disabled
+
+ movzx eax, byte ptr [esp+4]
+ mov PCR[PcHal.PcrNumber], al ; Save processor # in PCR
+
+ mov ecx, PCR[PcSelfPcr] ; Flat address of this PCR
+ mov _HalpProcessorPCR[eax*4], ecx ; Save it away
+
+ mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
+
+
+ ;
+ ; set bit in interrupt affinity mask for this processor
+ ;
+ lock bts _HalpDefaultInterruptAffinity, eax
+ lock bts _HalpActiveProcessors, eax
+
+ ;
+ ; Most of the following code is only needed on P0
+ ;
+ or eax, eax
+ jnz PnInitCode ; Not P0 skip a lot
+
+ ; Run on P0 only
+
+ ;
+ ; Determine if the system we are on is an PC+MP
+ ;
+ ; DetectMPS has a parameter we don't currently use. It's a boolean
+ ; which is set to TRUE if the system we're on is a MP system. Remember,
+ ; we could have a UP PC+MP system.
+ ;
+ ; The DetectMPS routine also allocates Virtual Addresses for all of
+ ; the APIC's in the system (it needs to access the devices anyway so ...)
+ ;
+
+ sub esp, 4
+ stdCall _DetectMPS <esp> ; Are we running on an PC+MP
+ add esp,4
+
+ cmp eax, 0 ; Yes (nonZero) or
+ je NotPcMp ; No (Zero)
+
+; stdCall _HalDisplayString, <offset HalSignonString>
+
+ mov ax, 0FFFFH ; mask all PIC interrupts
+ mov _HalpGlobal8259Mask, ax ; save the mask
+ SET_8259_MASK
+
+ ;
+ ; Other P0 initialization would go here
+ ;
+ jmp CommonInitCode
+
+PnInitCode:
+ ;
+ ; Pn initialization goes here
+ ;
+
+CommonInitCode:
+
+ stdCall _HalInitApicInterruptHandlers
+
+ ;
+ ; initialize the APIC local unit for this Processor
+ ;
+
+ stdCall _HalpInitializeLocalUnit
+
+ stdRET _HalInitializeProcessor
+
+NotPcMp:
+ stdCall _HalDisplayString, <offset _rgzBadHal>
+ hlt
+
+stdENDP _HalInitializeProcessor
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+
+;++
+;
+; VOID
+; HalInitApicInterruptHandlers(
+; );
+;
+;Routine Description:
+;
+; This routine installs the interrupt vector in the IDT for the APIC
+; spurious interrupt.
+;
+;Arguments:
+;
+; None.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitApicInterruptHandlers ,0
+ enter 8,0 ; setup ebp, reserve 8 bytes of stack
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov edx, [ebp-6] ; (edx)->IDT
+
+ mov ecx, PIC1_SPURIOUS_VECTOR ; Spurious Vector
+ mov eax, offset FLAT:PicSpuriousService37
+ mov word ptr [edx+8*ecx], ax ; Lower half of handler addr
+ mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*ecx+6], ax
+
+ mov ecx, APIC_SPURIOUS_VECTOR ; Apic Spurious Vector
+ mov eax, offset FLAT:_HalpApicSpuriousService
+ mov word ptr [edx+8*ecx], ax ; Lower half of handler addr
+ mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*ecx+6], ax
+
+ leave
+ stdRET _HalInitApicInterruptHandlers
+stdENDP _HalInitApicInterruptHandlers
+
+cPublicProc PicSpuriousService37 ,0
+ iretd
+stdENDP PicSpuriousService37
+
+;++
+;
+; VOID
+; HalpApicRebootService(
+; );
+;
+;Routine Description:
+;
+; This is the ISR that handles Reboot events
+;
+;--
+
+ ENTER_DR_ASSIST HReboot_a, HReboot_t
+cPublicProc _HalpApicRebootService ,0
+ ENTER_INTERRUPT HReboot_a, HReboot_t ; (ebp) -> Trap frame
+
+ mov eax, APIC_REBOOT_VECTOR
+
+ mov ecx, dword ptr APIC[LU_TPR] ; get the old TPR
+ push ecx ; save it
+ mov dword ptr APIC[LU_TPR], eax ; set the TPR
+ APICFIX edx
+
+ ;
+ ; EOI the local APIC, warm reset does not reset the 82489 APIC
+ ; so if we don't EOI here we'll never see an interrupt after
+ ; the reboot.
+ ;
+
+ mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
+
+ stdCall _HalpResetThisProcessor
+
+ ;
+ ; We should never get here, but just in case someone is stepping
+ ; through this
+ ;
+
+ pop eax
+ mov dword ptr APIC[LU_TPR], eax ; reset the TPR
+ APICFIX edx
+
+ ;
+ ; Do interrupt exit processing without EOI
+ ;
+
+ SPURIOUS_INTERRUPT_EXIT
+
+stdENDP _HalpApicRebootService
+
+;++
+;
+; VOID
+; HalpGenericCallService(
+; );
+;
+; Routine Description:
+; This is the ISR that handles the GenericCall interrupt
+;
+;--
+ ENTER_DR_ASSIST HGeneric_a, HGeneric_t
+cPublicProc _HalpBroadcastCallService ,0
+ ENTER_INTERRUPT HGeneric_a, HGeneric_t ; (ebp) -> Trap frame
+;
+; (esp) - base of trap frame
+;
+; dismiss interrupt and raise Irql
+;
+ push APIC_GENERIC_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL-1,APIC_GENERIC_VECTOR,esp>
+
+ call _HalpPollForBroadcast
+
+ INTERRUPT_EXIT ; lower irql to old value, iret
+
+stdENDP _HalpBroadcastCallService
+
+;++
+;
+; VOID
+; HalpGenericCall(
+; IN VOID (*WorkerFunction)(VOID),
+; IN ULONG Context,
+; IN KAFFINITY TargetProcessors
+; );
+;
+; Routine Description:
+; Causes the WorkerFunction to be called on the specified target
+; processors. The WorkerFunction is called at CLOCK2_LEVEL-1
+; (Must be below IPI_LEVEL in order to prevent system deadlocks).
+;
+; Enviroment:
+; Must be called with interrupts enabled.
+; Must be called with IRQL = CLOCK2_LEVEL-1
+;--
+
+cPublicProc _HalpGenericCall,3
+cPublicFpo 3, 0
+
+GENERIC_IPI equ (DELIVER_FIXED OR LOGICAL_DESTINATION OR ICR_USE_DEST_FIELD OR APIC_GENERIC_VECTOR)
+
+@@: call _HalpPollForBroadcast
+ test HalpBroadcastLock, 1 ; Is broadcast busy?
+ jnz short @b ; Yes, wait
+
+ lock bts HalpBroadcastLock, 0 ; Try to get lock
+ jc short @b ; didn't get it, loop
+
+hgc30: mov ecx, [esp+4]
+ mov edx, [esp+8]
+ mov eax, [esp+12]
+ mov HalpBroadcastFunction, ecx
+ mov HalpBroadcastContext, edx
+ mov HalpBroadcastTargets, eax
+
+ or eax, eax ; (eax) = Targets
+ jz short gc90
+
+ shl eax, DESTINATION_SHIFT
+
+ cli
+ STALL_WHILE_APIC_BUSY
+
+ ;
+ ; Set the destination address, (eax) = Processor bitmask
+ ;
+
+ mov dword ptr APIC[LU_INT_CMD_HIGH], eax
+ APICFIX edx
+
+ ;
+ ; Now issue the command by writing to the Memory Mapped Register
+ ;
+
+ mov dword ptr APIC[LU_INT_CMD_LOW], GENERIC_IPI
+
+;
+; Why do we need to wait again???
+;
+
+ STALL_WHILE_APIC_BUSY
+ sti
+
+;
+; Wait for all processors to call broadcast function
+;
+
+@@: call _HalpPollForBroadcast
+ cmp HalpBroadcastTargets, 0
+ jnz short @b
+
+gc90: mov HalpBroadcastLock, 0 ; Release BroadcastLock
+ stdRET _HalpGenericCall
+
+stdENDP _HalpGenericCall
+
+;++
+;
+; VOID
+; _HalpPollForBroadcast (
+; VOID
+; );
+;
+; Routine Description:
+;
+; IRQL = CLOCK2_LEVEL-1
+;--
+cPublicProc _HalpPollForBroadcast, 0
+cPublicFpo 0, 0
+ mov eax, PCR[PcSetMember]
+ test HalpBroadcastTargets, eax
+ jz short pb90
+
+ mov ecx, HalpBroadcastFunction ; Pickup broadcast function
+ push HalpBroadcastContext
+
+ not eax ; Remove our bit from destionations
+ lock and HalpBroadcastTargets, eax
+
+ call ecx
+
+pb90: stdRET _HalpPollForBroadcast
+
+stdENDP _HalpPollForBroadcast
+
+;++
+;
+; ULONG
+; FASTCALL
+; HalpWaitForPending (
+; ULONG Count (ecx)
+; PULONG LuICR (edx)
+; );
+;
+; Routine Description:
+;
+; Waits for DELIVERY_PENDING to clear and returns remaining iteration count
+;--
+cPublicFastCall HalpWaitForPending, 2
+cPublicFpo 0, 0
+
+wfp10: test dword ptr [edx], DELIVERY_PENDING
+ jz short wfp20
+
+ dec ecx
+ jnz short wfp10
+
+wfp20: mov eax, ecx
+ fstRet HalpWaitForPending
+
+fstENDP HalpWaitForPending
+
+
+;++
+;
+; VOID
+; HalpLocalApicErrorService(
+; );
+;
+;Routine Description:
+;
+; This routine fields Local APIC error Events
+;
+;--
+
+ ENTER_DR_ASSIST HApicErr_a, HApicErr_t
+
+cPublicProc _HalpLocalApicErrorService ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT HApicErr_a, HApicErr_t ; (ebp) -> Trap frame
+
+if LogApicErrors
+
+ lea ecx, _HalpLocalApicErrorLock
+ fstCall HalpAcquireHighLevelLock
+ push eax
+
+ mov eax, _HalpLocalApicErrorCount
+ inc _HalpLocalApicErrorCount
+
+ lea ecx, _HalpApicErrorLog
+
+ and eax, APIC_ERROR_LOG_SIZE-1
+ shl eax, 1
+ add ecx, eax
+
+endif ; LogApicErrors
+
+ mov dword ptr APIC[LU_EOI], 0 ; local unit EOI
+ APICFIX eax
+
+ ;
+ ; The Apic EDS (Rev 4.0) says you have to write before you read
+ ; this doesn't work. The write clears the status bits.
+ ; But P6 works as according to the EDS!
+ ;
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbCpuType, 6
+ jc short lae10
+ mov dword ptr APIC[LU_ERROR_STATUS], 0
+
+lae10:
+ mov eax, dword ptr APIC[LU_ERROR_STATUS] ; read error status
+
+
+ ; Find out what kind of error it is and update the appropriate count.
+
+if LogApicErrors
+; out 80h, al
+ mov byte ptr [ecx], al
+ inc ecx
+ mov al, byte ptr PCR[PcHal.PcrNumber]
+ mov byte ptr [ecx], al
+
+ lea ecx, _HalpLocalApicErrorLock
+ pop edx
+ fstCall HalpReleaseHighLevelLock
+
+endif ; LogApicErrors
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+stdENDP _HalpLocalApicErrorService
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+;Return Value:
+;
+; None.
+;
+;--
+APIC_IPI equ (DELIVER_FIXED OR LOGICAL_DESTINATION OR ICR_USE_DEST_FIELD OR APIC_IPI_VECTOR)
+
+cPublicProc _HalRequestIpi ,1
+cPublicFpo 1, 0
+
+ mov eax, [esp+4] ; (eax) = Processor bitmask
+ shl eax, DESTINATION_SHIFT
+
+;
+; With an APIC we'll IPI everyone needed at the same time.
+; This assumes that:
+; (mask passed in) == (APIC logical destination mask) Since we've programmed
+; the APIC Local Units to use the Processor ID as the Logical ID's this IS true
+;
+
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+
+ STALL_WHILE_APIC_BUSY
+;
+; Set the destination address, (eax) = Processor bitmask
+;
+
+ mov dword ptr APIC[LU_INT_CMD_HIGH], eax
+ APICFIX edx
+
+;
+; Now issue the command by writing to the Memory Mapped Register
+;
+
+ mov dword ptr APIC[LU_INT_CMD_LOW], APIC_IPI
+
+;
+; Wait for the delivery to happen
+; KenR why is there a wait here????
+;
+ STALL_WHILE_APIC_BUSY
+
+ popfd
+ stdRET _HalRequestIpi
+
+stdENDP _HalRequestIpi
+
+ page ,132
+ subttl "PC+MP IPI Interrupt Handler"
+;++
+;
+; VOID
+; HalpIpiHandler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by inter
+; processor communication.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hipi_a, Hipi_t
+
+cPublicProc _HalpIpiHandler ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+ push APIC_IPI_VECTOR ; Vector
+ sub esp, 4 ; space for OldIrql
+;
+; We now dismiss the interprocessor interrupt and call its handler
+;
+
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,APIC_IPI_VECTOR,esp>
+
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+;
+; Do interrupt exit processing
+;
+
+ INTERRUPT_EXIT ; will return to caller
+
+stdENDP _HalpIpiHandler
+
+;++
+;
+; VOID
+; HalpApicSpuriousService(
+; );
+;
+;Routine Description:
+;
+; A place for spurious interrupts to end up.
+;
+;--
+cPublicProc _HalpApicSpuriousService,0
+ iretd
+stdENDP _HalpApicSpuriousService
+
+
+;++
+;
+; VOID
+; _PicInterruptHandlerIntiXX(
+; );
+;
+;Routine Description:
+;
+; These handlers receive interrupts from the PIC and reissues them via
+; a vector at the proper priority level. This is used to provide a symetric
+; interrupt distribution on a non symetric system.
+;
+; The PIC interrupts will normally only be received (in the PC+MP Hal) via an
+; interrupt input from on either the IO Unit or the Local unit which has been
+; programed as EXTINT. EXTINT interrupts are received outside of the APIC
+; priority structure (the PIC provides the vector). We use the APIC ICR to
+; generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are directed to a single processor, currently P0.
+; There is no good reason why they can't be directed to another processor.
+;
+; Since one processor must absorb the overhead of redistributing PIC interrupts
+; the interrupt handling on a system using EXTINT interrupts is not symetric.
+;
+;--
+
+ ENTER_DR_ASSIST Hcpic_a, Hcpic_t
+
+cPublicProc PicHandler ,0
+
+PicInterruptHandlerInti0:
+ push 0
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti1:
+ push 1
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti2:
+ push 2
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti3:
+ push 3
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti4:
+ push 4
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti5:
+ push 5
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti6:
+ push 6
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti7:
+;
+; Check to see if this is a spurious interrupt
+;
+ push eax
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ pop eax
+ jz short pic7_spurious ;
+
+ push 7
+ jmp short CommonPicHandler
+
+picf_spurious:
+ mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al
+ pop eax
+pic7_spurious:
+ iretd ; ignore PIC
+
+PicInterruptHandlerInti8:
+ push 8
+ jmp short CommonPicHandler
+
+PicInterruptHandlerInti9:
+ push 9
+ jmp short CommonPicHandler
+
+PicInterruptHandlerIntiA:
+ push 10
+ jmp short CommonPicHandler
+
+PicInterruptHandlerIntiB:
+ push 11
+ jmp short CommonPicHandler
+
+PicInterruptHandlerIntiC:
+ push 12
+ jmp short CommonPicHandler
+
+PicInterruptHandlerIntiD:
+ push 13
+ push eax
+ xor eax, eax
+ out I386_80387_BUSY_PORT, al
+ pop eax
+ jmp short CommonPicHandler
+
+PicInterruptHandlerIntiE:
+ push 14
+ jmp short CommonPicHandler
+
+PicInterruptHandlerIntiF:
+ push eax
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jz short picf_spurious ; Go eoi PIC1 & Ignore PIC2
+
+ pop eax
+ push 15
+ jmp short CommonPicHandler
+
+CommonPicHandler:
+ ENTER_INTERRUPT Hcpic_a, Hcpic_t,PassDwordParm ; (ebp) -> Trap frame
+
+;
+; Need to determine if we have a level interrupt and if so don't EOI it
+; It should be EOI'd by end system interrupt
+;
+
+ cmp bl, 8 ; Pic or Slave Pic
+ jae short cph20
+
+ mov al, bl
+ or al, OCW2_SPECIFIC_EOI ; specific eoi
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short cph30
+
+cph20:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+cph30:
+ mov al, _HalpPICINTToVector[ebx] ; Get vector for PIC interrupt
+ or al, al ; Is vector known?
+ jz short cph90 ; No, don't dispatch it
+
+;
+; Now gain exclusive access to the ICR
+;
+
+ STALL_WHILE_APIC_BUSY
+
+ cmp bl, 8
+ je short HandleClockInti
+
+;
+; Write the IPI Command to the Memory Mapped Register
+;
+
+ mov dword ptr APIC[LU_INT_CMD_HIGH], DESTINATION_ALL_CPUS
+ APICFIX edx
+ mov dword ptr APIC[LU_INT_CMD_LOW], eax
+ jmp short cph90
+
+
+HandleClockInti:
+;
+; Write the IPI Command to the Memory Mapped Register
+;
+
+ mov dword ptr APIC[LU_INT_CMD_LOW], (DELIVER_FIXED OR ICR_SELF OR APIC_CLOCK_VECTOR)
+
+
+cph90: APICFIX edx
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP PicHandler
+
+
+;++
+;
+; VOID
+; _PicXXNopHandler(
+; );
+;
+;Routine Description:
+;
+; These handlers are designed to be installed on a system to field any PIC
+; interrupts when there are not supposed to be any delivered.
+;
+; In the Debug case this routine increments an error count EOI's the PIC and
+; returns. Normally the increment is not performed.
+;--
+
+
+
+cPublicProc PicNopHandler ,0
+
+PicNopHandlerInti0:
+ push eax ; Save Scratch Registers
+ mov al, 0
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti1:
+ push eax ; Save Scratch Registers
+ mov al, 1
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti2:
+ push eax ; Save Scratch Registers
+ mov al, 2
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti3:
+ push eax ; Save Scratch Registers
+ mov al, 3
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti4:
+ push eax ; Save Scratch Registers
+ mov al, 4
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti5:
+ push eax ; Save Scratch Registers
+ mov al, 5
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti6:
+ push eax ; Save Scratch Registers
+ mov al, 6
+ jmp short CommonPic1NopHandler
+
+PicNopHandlerInti7:
+ push eax ; Save Scratch Registers
+ mov al, 7
+
+CommonPic1NopHandler:
+ ;
+ ; Need to determine if we have a level interrupt and if so don't EOI it
+ ; It should be EOI'd by end system interrupt
+ ;
+
+ or al, OCW2_SPECIFIC_EOI ; specific eoi
+ out PIC1_PORT0, al ; dismiss the interrupt
+ pop eax ; Restore Scratch registers
+ iretd
+
+PicNopHandlerIntiD:
+ push eax
+ xor eax, eax
+ out I386_80387_BUSY_PORT, al
+ pop eax
+
+CommonPic2NopHandler:
+ push eax
+
+;
+; Need to determine if we have a level interrupt and if so don't EOI it
+; It should be EOI'd by end system interrupt
+;
+
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ pop eax
+ iretd
+
+stdENDP PicNopHandler
+
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halmps/i386/mpirql.asm b/private/ntos/nthals/halmps/i386/mpirql.asm
new file mode 100644
index 000000000..18f0b3986
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpirql.asm
@@ -0,0 +1,517 @@
+
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+;
+; Module Name:
+;
+; mpirql.asm
+;
+; Abstract:
+;
+; This module implements the mechanism for raising and lowering IRQL
+; and dispatching software interrupts for PC+MP compatible systems
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ron Mosgrove (Intel) Sept 1993
+; Modified for PC+MP
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include mac386.inc
+include i386\apic.inc
+include i386\pcmp_nt.inc
+include i386\kimacro.inc
+ .list
+
+ EXTRNP _KeBugCheck,1,IMPORT
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ align dword
+
+;
+; Global8259Mask is used to avoid reading the PIC to get the current
+; interrupt mask; format is the same as for SET_8259_MASK, i.e.,
+; bits 7:0 -> PIC1, 15:8 -> PIC2
+;
+ public _HalpGlobal8259Mask
+_HalpGlobal8259Mask dw 0
+
+;
+; IOunitRedirectionTable is the memory image of the redirection table to be
+; loaded into APIC I/O unit 0 at initialization. there is one 64-bit entry
+; per interrupt input to the I/O unit. the edge/level trigger mode bit will
+; be set dynamically when the table is actually loaded. the mask bit is set
+; initially, and reset by EnableSystemInterrupt.
+;
+
+;
+; _HalpIRQLtoTPR maps IRQL to an APIC TPR register value
+;
+ align dword
+ public _HalpIRQLtoTPR
+_HalpIRQLtoTPR label byte
+ db ZERO_VECTOR ; IRQL 0
+ db APC_VECTOR ; IRQL 1
+ db DPC_VECTOR ; IRQL 2
+ db DPC_VECTOR ; IRQL 3
+ db DEVICE_LEVEL1 ; IRQL 4
+ db DEVICE_LEVEL2 ; IRQL 5
+ db DEVICE_LEVEL3 ; IRQL 6
+ db DEVICE_LEVEL4 ; IRQL 7
+ db DEVICE_LEVEL5 ; IRQL 8
+ db DEVICE_LEVEL6 ; IRQL 9
+ db DEVICE_LEVEL7 ; IRQL 10
+ db DEVICE_LEVEL7 ; IRQL 11
+ db DEVICE_LEVEL7 ; IRQL 12
+ db DEVICE_LEVEL7 ; IRQL 13
+ db DEVICE_LEVEL7 ; IRQL 14
+ db DEVICE_LEVEL7 ; IRQL 15
+ db DEVICE_LEVEL7 ; IRQL 16
+ db DEVICE_LEVEL7 ; IRQL 17
+ db DEVICE_LEVEL7 ; IRQL 18
+ db DEVICE_LEVEL7 ; IRQL 19
+ db DEVICE_LEVEL7 ; IRQL 20
+ db DEVICE_LEVEL7 ; IRQL 21
+ db DEVICE_LEVEL7 ; IRQL 22
+ db DEVICE_LEVEL7 ; IRQL 23
+ db DEVICE_LEVEL7 ; IRQL 24
+ db DEVICE_LEVEL7 ; IRQL 25
+ db DEVICE_LEVEL7 ; IRQL 26
+ db APIC_GENERIC_VECTOR ; IRQL 27
+ db APIC_CLOCK_VECTOR ; IRQL 28
+ db APIC_IPI_VECTOR ; IRQL 29
+ db POWERFAIL_VECTOR ; IRQL 30
+ db NMI_VECTOR ; IRQL 31
+
+;
+; VECTOR_MAP_ENTRY macro generates sparse table required for APIC vectors
+;
+
+VECTOR_MAP_ENTRY macro vector_number, apic_inti
+ current_entry = $ - _HalpVectorToINTI
+ entry_count = vector_number - current_entry
+ REPT entry_count
+ db 0FFh
+ ENDM
+ db apic_inti
+
+ endm
+
+;
+; _HalpVectorToINTI maps interrupt vector to EISA interrupt level
+; (APIC INTI input);
+; NOTE: this table must ordered by ascending vector numbers
+; also note that there is no entry for unused INTI13.
+;
+
+ align dword
+ public _HalpVectorToINTI
+_HalpVectorToINTI label byte
+ VECTOR_MAP_ENTRY NMI_VECTOR, 0FFH
+; VECTOR_MAP_ENTRY 0FFH, 0FFH ; End of Table
+
+;
+; _HalpVectorToIRQL maps interrupt vector to NT IRQLs
+; NOTE: this table must ordered by ascending vector numbers
+;
+
+VECTORTOIRQL_ENTRY macro vector_number, apic_inti
+ current_entry = $ - _HalpVectorToIRQL
+ priority_number = vector_number/16
+ entry_count = priority_number - current_entry
+ REPT entry_count
+ db 0FFh
+ ENDM
+ db apic_inti
+
+ endm
+
+ align dword
+ public _HalpVectorToIRQL
+_HalpVectorToIRQL label byte
+ VECTORTOIRQL_ENTRY ZERO_VECTOR, 00 ; placeholder
+ VECTORTOIRQL_ENTRY APC_VECTOR, 01 ; APC
+ VECTORTOIRQL_ENTRY DPC_VECTOR, 02 ; DPC
+ VECTORTOIRQL_ENTRY APIC_GENERIC_VECTOR, 27 ;
+ VECTORTOIRQL_ENTRY APIC_CLOCK_VECTOR, 28 ; System Clock
+ VECTORTOIRQL_ENTRY APIC_IPI_VECTOR, 29
+ VECTORTOIRQL_ENTRY POWERFAIL_VECTOR, 30
+
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+;++
+;
+; VOID
+; KIRQL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,0
+
+ xor edx, edx
+ mov dl, cl ; (edx) = New Irql
+
+ mov eax, dword ptr APIC[LU_TPR] ; (eax) = Old Priority (Vector)
+
+ xor ecx, ecx
+ mov cl, byte ptr _HalpIRQLtoTPR[edx] ; get TPR value for IRQL
+
+ mov dword ptr APIC[LU_TPR], ecx ; Write New Priority to the TPR
+
+;
+; get IRQL for Old Priority, and return it
+;
+ shr eax, 4
+ movzx eax, _HalpVectorToIRQL[eax] ; (al) = OldIrql
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov edx, dword ptr APIC[LU_TPR] ; (ecx) = Old Priority (Vector)
+ mov dword ptr APIC[LU_TPR], DPC_VECTOR ; Write New Priority to the TPR
+ shr edx, 4
+ movzx eax, _HalpVectorToIRQL[edx] ; (al) = OldIrql
+ stdRET _KeRaiseIrqlToDpcLevel
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSyncLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+cPublicFpo 0, 0
+
+ mov edx, dword ptr APIC[LU_TPR] ; (ecx) = Old Priority (Vector)
+ mov dword ptr APIC[LU_TPR], APIC_SYNCH_VECTOR ; Write New Priority to the TPR
+
+ shr edx, 4
+ movzx eax, _HalpVectorToIRQL[edx] ; (al) = OldIrql
+ stdRET _KeRaiseIrqlToSynchLevel
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+ page ,132
+ subttl "Lower irql"
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; equates for accessing arguments
+;
+
+cPublicFastCall KfLowerIrql ,1
+cPublicFpo 0,0
+
+ xor eax, eax
+ mov al, cl ; get new irql value
+
+if DBG
+;
+; Make sure we are not lowering to ABOVE current level
+;
+
+ mov ecx, dword ptr APIC[LU_TPR] ; (ebx) = Old Priority (Vector)
+ shr ecx, 4
+ movzx ecx, _HalpVectorToIRQL[ecx] ; get IRQL for Old Priority
+ cmp al, cl
+ jbe short KliDbg
+ push ecx ; new irql for debugging
+ push eax ; old irql for debugging
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
+KliDbg:
+endif
+ xor ecx, ecx ; Avoid a partial stall
+ mov cl, _HalpIRQLtoTPR[eax] ; get TPR value corresponding to IRQL
+ mov dword ptr APIC[LU_TPR], ecx
+
+;
+; We have to ensure that the requested priority is set before
+; we return. The caller is counting on it.
+;
+ mov eax, dword ptr APIC[LU_TPR]
+
+if DBG
+ cmp ecx, eax ; Verify IRQL read back is same as
+ je short @f ; set value
+ int 3
+@@:
+endif
+ fstRET KfLowerIrql
+fstENDP KfLowerIrql
+
+ page ,132
+ subttl "Get current irql"
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+
+ mov eax, dword ptr APIC[LU_TPR] ; (eax) = Old Priority (Vector)
+ shr eax, 4
+ movzx eax, _HalpVectorToIRQL[eax] ; get IRQL for Old Priority
+ stdRET _KeGetCurrentIrql
+
+stdENDP _KeGetCurrentIrql
+
+
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+
+ ;
+ ; Raising to HIGH_LEVEL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+_TEXT ends
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;
+; PIC initialization command strings - first word is port to write to,
+; followed by bytes of Initialization Control Words (ICWs) and Operation
+; Control Words (OCWs). Last string is zero-terminated.
+;
+
+PICsInitializationString label byte
+;
+; Master PIC initialization commands
+;
+ dw PIC1_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 + \
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+PIC1InitMask db 0FFh ; OCW1 - mask all inputs
+;
+; Slave PIC initialization commands
+;
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 + \
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+PIC2InitMask db 0FFh ; OCW1 - mask all inputs
+ dw 0 ; end of string
+
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine initializes the interrupt structures for the 8259A PIC.
+;
+; Context:
+;
+; This procedure is executed by CPU 0 during Phase 0 initialization.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+
+ push esi ; save caller's esi
+ cli ; disable interrupt
+
+ lea esi, PICsInitializationString
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ outsb ; output OCW1 (mask register)
+ IODelay
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+ mov al, PIC2InitMask ; save the initial mask in
+ shl ax, 8 ; mask in global variable
+ mov al, PIC1InitMask
+ mov _HalpGlobal8259Mask, ax
+
+ pop esi ; restore caller's esi
+ sti ; enable interrupt
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+INIT ends
+ end
diff --git a/private/ntos/nthals/halmps/i386/mppciint.c b/private/ntos/nthals/halmps/i386/mppciint.c
new file mode 100644
index 000000000..0802fcd96
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mppciint.c
@@ -0,0 +1,529 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pcmp_nt.inc"
+
+volatile ULONG PCIType2Stall;
+extern struct HalpMpInfo HalpMpInfoTable;
+extern BOOLEAN HalpHackNoPciMotion;
+extern BOOLEAN HalpDoingCrashDump;
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG InterruptLevel,
+ IN ULONG InterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+VOID
+HalpPCIPin2MPSLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIMPSLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetFixedPCIMPSLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+PSUPPORTED_RANGES
+HalpAllocateNewRangeList (
+ VOID
+ );
+
+VOID
+HalpFreeRangeList (
+ PSUPPORTED_RANGES Ranges
+ );
+
+VOID
+HalpMPSPCIChildren (
+ VOID
+ );
+
+ULONG
+HalpGetPCIBridgedInterruptVector (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG InterruptLevel,
+ IN ULONG InterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpSubclassPCISupport)
+#pragma alloc_text(INIT,HalpMPSPCIChildren)
+#pragma alloc_text(PAGE,HalpGetFixedPCIMPSLine)
+#pragma alloc_text(PAGE,HalpGetPCIBridgedInterruptVector)
+#endif
+
+
+//
+// Turn PCI pin to inti via the MPS spec
+// (note: pin must be non-zero)
+//
+
+#define PCIPin2Int(Slot,Pin) (Slot.u.bits.DeviceNumber << 2) | (Pin-1);
+
+
+
+VOID
+HalpSubclassPCISupport (
+ PBUS_HANDLER Handler,
+ ULONG HwType
+ )
+{
+ ULONG d, i, MaxDeviceFound;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+
+ BusData = (PPCIPBUSDATA) Handler->BusData;
+ SlotNumber.u.bits.Reserved = 0;
+ MaxDeviceFound = 0;
+
+#ifdef P6_WORKAROUNDS
+ BusData->MaxDevice = 0x10;
+#endif
+
+ //
+ // Find any PCI bus which has MPS inti information, and provide
+ // MPS handlers for dealing with it.
+ //
+ // Note: we assume that any PCI bus with any MPS information
+ // is totally defined. (Ie, it's not possible to connect some PCI
+ // interrupts on a given PCI bus via the MPS table without connecting
+ // them all).
+ //
+ // Note2: we assume that PCI buses are listed in the MPS table in
+ // the same order the BUS declares them. (Ie, the first listed
+ // PCI bus in the MPS table is assumed to match physical PCI bus 0, etc).
+ //
+ //
+
+ for (d=0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ i = PCIPin2Int (SlotNumber, 1);
+ if (HalpGetPcMpInterruptDesc(PCIBus, Handler->BusNumber, i, &i)) {
+ MaxDeviceFound = d;
+ }
+ }
+
+ if (MaxDeviceFound) {
+ //
+ // There are Inti mapping for interrupts on this PCI bus
+ // Change handlers for this bus to MPS versions
+ //
+
+ Handler->GetInterruptVector = HalpGetSystemInterruptVector;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2MPSLine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIMPSLine2Pin;
+ BusData->GetIrqRange = HalpGetFixedPCIMPSLine;
+
+ if (BusData->MaxDevice < MaxDeviceFound) {
+ BusData->MaxDevice = MaxDeviceFound;
+ }
+
+ } else {
+
+ //
+ // Not all PCI machines are eisa machine, since the PCI interrupts
+ // aren't coming into IoApics go check the Eisa ELCR for broken
+ // behaviour.
+ //
+
+ HalpCheckELCR ();
+
+
+ }
+}
+
+
+VOID
+HalpMPSPCIChildren (
+ VOID
+ )
+/*++
+
+ Any PCI buses which don't have declared interrupt mappings and
+ are children of parent buses that have MPS interrupt mappings
+ need to inherit interrupts from parents via PCI barbar pole
+ algorithm
+
+--*/
+{
+ PBUS_HANDLER Handler, Parent;
+ PPCIPBUSDATA BusData, ParentData;
+ ULONG b, cnt, i, id;
+ PCI_SLOT_NUMBER SlotNumber;
+ struct {
+ union {
+ UCHAR map[4];
+ ULONG all;
+ } u;
+ } Interrupt, Hold;
+
+ //
+ // Lookup each PCI bus in the system
+ //
+
+ for (b=0; Handler = HaliHandlerForBus(PCIBus, b); b++) {
+
+ BusData = (PPCIPBUSDATA) Handler->BusData;
+
+ if (BusData->CommonData.Pin2Line == (PciPin2Line) HalpPCIPin2MPSLine) {
+
+ //
+ // This bus already has mappings
+ //
+
+ continue;
+ }
+
+
+ //
+ // Check if any parent has PCI MPS interrupt mappings
+ //
+
+ Interrupt.u.map[0] = 1;
+ Interrupt.u.map[1] = 2;
+ Interrupt.u.map[2] = 3;
+ Interrupt.u.map[3] = 4;
+
+ Parent = Handler;
+ SlotNumber = BusData->CommonData.ParentSlot;
+
+ while (Parent = Parent->ParentHandler) {
+
+ if (Parent->InterfaceType != PCIBus) {
+ break;
+ }
+
+ //
+ // Check if parent has MPS interrupt mappings
+ //
+
+ ParentData = (PPCIPBUSDATA) Parent->BusData;
+ if (ParentData->CommonData.Pin2Line == (PciPin2Line) HalpPCIPin2MPSLine) {
+
+ //
+ // This parent has MPS interrupt mappings. Set the device
+ // to get its InterruptLine values from the buses SwizzleIn table
+ //
+
+ Handler->GetInterruptVector = HalpGetPCIBridgedInterruptVector;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIMPSLine2Pin;
+
+ for (i=0; i < 4; i++) {
+ id = PCIPin2Int (SlotNumber, Interrupt.u.map[i]);
+ BusData->SwizzleIn[i] = (UCHAR) id;
+ }
+ break;
+ }
+
+ //
+ // Apply interrupt mapping
+ //
+
+ i = SlotNumber.u.bits.DeviceNumber;
+ Hold.u.map[0] = Interrupt.u.map[(i + 0) & 3];
+ Hold.u.map[1] = Interrupt.u.map[(i + 1) & 3];
+ Hold.u.map[2] = Interrupt.u.map[(i + 2) & 3];
+ Hold.u.map[3] = Interrupt.u.map[(i + 3) & 3];
+ Interrupt.u.all = Hold.u.all;
+
+ SlotNumber = ParentData->CommonData.ParentSlot;
+ }
+
+ }
+}
+
+
+VOID
+HalpPCIPin2MPSLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+--*/
+{
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ PciData->u.type0.InterruptLine = (UCHAR)
+ PCIPin2Int (SlotNumber, PciData->u.type0.InterruptPin);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) & 3;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i];
+}
+
+
+VOID
+HalpPCIMPSLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+--*/
+{
+ //
+ // PCI interrupts described in the MPS table are directly
+ // connected to APIC Inti pins.
+ // Do nothing...
+ //
+}
+
+ULONG
+HalpGetPCIBridgedInterruptVector (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG InterruptLevel,
+ IN ULONG InterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ //
+ // Get parent's translation
+ //
+
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ BusHandler->ParentHandler,
+ InterruptLevel,
+ InterruptVector,
+ Irql,
+ Affinity
+ );
+
+}
+
+
+
+NTSTATUS
+HalpGetFixedPCIMPSLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpPCIType2TruelyBogus (
+ ULONG Context
+ )
+/*++
+
+ This is a piece of work.
+
+ Type 2 of the PCI configuration space is bad. Bad as in to
+ access it one needs to block out 4K of I/O space.
+
+ Video cards are bad. The only decode the bits in an I/O address
+ they feel like. Which means one can't block out a 4K range
+ or these video cards don't work.
+
+ Combinding all these bad things onto an MP machine is even
+ more (sic) bad. The I/O ports can't be mapped out unless
+ all processors stop accessing I/O space.
+
+ Allowing access to device specific PCI control space during
+ an interrupt isn't bad, (although accessing it on every interrupt
+ is stupid) but this cause the added grief that all processors
+ need to obtained at above all device interrupts.
+
+ And... naturally we have an MP machine with a wired down
+ bad video controller, stuck in the bad Type 2 configuration
+ space (when we told everyone about type 1!). So the "fix"
+ is to HALT ALL processors for the duration of reading/writing
+ ANY part of PCI configuration space such that we can be sure
+ no processor is touching the 4k I/O ports which get mapped out
+ of existance when type2 accesses occur.
+
+ ----
+
+ While I'm flaming. Hooking PCI interrupts ontop of ISA interrupts
+ in a machine which has the potential to have 240+ interrupts
+ sources (read APIC) is bad ... and stupid.
+
+--*/
+{
+ // oh - let's just wait here and not pay attention to that other processor
+ // guy whom is punching holes into the I/O space
+ while (PCIType2Stall == Context) {
+ HalpPollForBroadcast ();
+ }
+}
+
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL OldIrql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ *OldIrql = KfRaiseIrql (CLOCK2_LEVEL-1);
+ KiAcquireSpinLock (SpinLock);
+
+ //
+ // Interrupt all other processors and have them wait until the
+ // barrier is cleared. (HalpGenericCall waits until the target
+ // processors have been interrupted before returning)
+ //
+
+ HalpGenericCall (
+ HalpPCIType2TruelyBogus,
+ PCIType2Stall,
+ HalpActiveProcessors & ~KeGetCurrentPrcb()->SetMember
+ );
+ } else {
+ *OldIrql = HIGH_LEVEL;
+ }
+}
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ PCIType2Stall++; // clear barrier
+ KiReleaseSpinLock (SpinLock);
+ KfLowerIrql (Irql);
+ }
+}
diff --git a/private/ntos/nthals/halmps/i386/mpprofil.asm b/private/ntos/nthals/halmps/i386/mpprofil.asm
new file mode 100644
index 000000000..1905f416e
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpprofil.asm
@@ -0,0 +1,466 @@
+
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; mpprofile.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to initialize,
+; field and process the profile interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+;--
+
+.586p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+;include i386\ix8259.inc
+;include i386\ixcmos.inc
+include i386\apic.inc
+include i386\pcmp_nt.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+
+;
+; APIC Timer Constants
+;
+
+APIC_TIMER_DISABLED equ (INTERRUPT_MASKED OR PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
+APIC_TIMER_ENABLED equ (PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
+
+;
+; number of 100ns intervals in one second
+;
+Num100nsIntervalsPerSec equ 10000000
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ ALIGN dword
+
+public HalpProfileRunning, _HalpPerfInterruptHandler
+HalpProfileRunning dd 0
+_HalpPerfInterruptHandler dd 0
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+;++
+;
+; HalStartProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is set the interrupt rate to the value that's been set
+; by the KeSetProfileInterval routine. Then enable the APIC Timer interrupt.
+;
+; This function gets called on every processor so the hal can enable
+; a profile interrupt on each processor.
+;
+
+;--
+
+cPublicProc _HalStartProfileInterrupt ,1
+
+;
+; Set the interrupt rate to what is actually needed.
+;
+
+ mov eax, PCR[PcHal.ProfileCountDown]
+ mov dword ptr APIC[LU_INITIAL_COUNT], eax
+
+ mov HalpProfileRunning, 1 ; Indicate profiling
+;
+; Set the Local APIC Timer to interrupt Periodically at APIC_PROFILE_VECTOR
+;
+
+ mov dword ptr APIC[LU_TIMER_VECTOR], APIC_TIMER_ENABLED
+
+ stdRET _HalStartProfileInterrupt
+
+stdENDP _HalStartProfileInterrupt
+
+;++
+;
+; HalStopProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+;--
+
+cPublicProc _HalStopProfileInterrupt ,1
+
+;
+; Turn off profiling
+;
+
+ mov HalpProfileRunning, 0 ; Indicate profiling is off
+ mov dword ptr APIC[LU_TIMER_VECTOR], APIC_TIMER_DISABLED
+ stdRET _HalStopProfileInterrupt
+
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; Arguments:
+;
+; (TOS+4) - Interval in 100ns unit.
+; (MINIMUM is 1221 or 122.1 uS) see ke\profobj.c
+;
+; Return Value:
+;
+; Interval actually used
+;
+;--
+
+cPublicProc _HalSetProfileInterval ,1
+
+ mov ecx, [esp+4] ; ecx = interval in 100ns unit
+ and ecx, 7FFFFFFFh ; Remove sign bit.
+
+ ;
+ ; The only possible error is if we will cause a divide overflow
+ ; this can happen only if the (frequency * request count) is
+ ; greater than 2^32* Num100nsIntervalsPerSec.
+ ;
+ ; To protect against that we just ensure that the request count
+ ; is less than (or equal to) Num100nsIntervalsPerSec
+ ;
+ cmp ecx, Num100nsIntervalsPerSec
+ jle @f
+ mov ecx, Num100nsIntervalsPerSec
+@@:
+
+ ;
+ ; Save the interval we're using to return
+ ;
+ push ecx
+
+ ;
+ ; Compute the countdown value
+ ;
+ ; let
+ ; R == caller's requested 100ns interval count
+ ; F == APIC Counter Freguency (hz)
+ ; N == Number of 100ns Intervals per sec
+ ;
+ ; then
+ ; count = (R*F)/N
+ ;
+ ; Get the previously computed APIC counter Freq
+ ; for this processor
+ ;
+
+ mov eax, PCR[PcHal.ApicClockFreqHz]
+
+ ;
+ ; eax <= F and ecx <= R
+ ;
+
+ ;
+ ; Compute (request count) * (ApicClockFreqHz) == (R*F)
+ ;
+
+ xor edx, edx
+ mul ecx
+
+ ;
+ ; edx:eax contains 64Bits of (R*F)
+ ;
+
+ mov ecx, Num100nsIntervalsPerSec
+ div ecx
+
+ ;
+ ; Compute (R*F) / Num100nsIntervalsPerSec == (R*F)/N
+ ;
+
+ mov PCR[PcHal.ProfileCountDown], eax ; Save the Computed Count Down
+ mov edx, dword ptr APIC[LU_CURRENT_COUNT]
+
+ ;
+ ; Set the interrupt rate in the chip.
+ ;
+
+ mov dword ptr APIC[LU_INITIAL_COUNT], eax
+
+ pop eax ; Return Actual Interval Used
+
+ stdRET _HalSetProfileInterval
+
+stdENDP _HalSetProfileInterval
+
+ page ,132
+ subttl "System Profile Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; HAL_PROFILE_LEVEL and transfer control to
+; the standard system routine to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = HAL_PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpi_a, Hpi_t
+
+cPublicProc _HalpProfileInterrupt ,0
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpi_a, Hpi_t
+
+;
+; (esp) - base of trap frame
+;
+
+ push APIC_PROFILE_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <HAL_PROFILE_LEVEL,APIC_PROFILE_VECTOR,esp>
+
+ cmp HalpProfileRunning, 0 ; Profiling?
+ je @f ; if not just exit
+
+ stdCall _KeProfileInterrupt,<ebp> ; (ebp) = TrapFrame address
+
+@@:
+ INTERRUPT_EXIT
+
+stdENDP _HalpProfileInterrupt
+
+
+ subttl "System Perf Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a perf interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; HAL_PROFILE_LEVEL and transfer control to
+; the standard system routine to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = HAL_PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpf_a, Hpf_t
+
+cPublicProc _HalpPerfInterrupt ,0
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpf_a, Hpf_t
+
+;
+; (esp) - base of trap frame
+;
+
+ push APIC_PERF_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <HAL_PROFILE_LEVEL,APIC_PERF_VECTOR,esp>
+
+;
+; Invoke perf interrupt handler
+;
+
+ mov ecx, ebp ; param1 = trap frame
+ mov eax, _HalpPerfInterruptHandler
+ or eax, eax
+ jz short hpf20
+
+ call eax
+
+hpf10: INTERRUPT_EXIT
+
+hpf20:
+if DBG
+ int 3
+endif
+ jmp short hpf10
+
+stdENDP _HalpPerfInterrupt
+
+
+
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+4] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter ,1
+
+ mov ecx, KqpcFrequency
+ or ecx, ecx
+ je short kpc10
+
+ mov eax, PCR[PcHal.TSCHz]
+ mov dword ptr [ecx], eax
+ mov dword ptr [ecx+4], 0
+
+kpc10:
+ rdtsc
+ stdRET _KeQueryPerformanceCounter
+
+stdENDP _KeQueryPerformanceCounter
+
+
+_TEXT ends
+
+INIT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ push esi
+ push edi
+ push ebx
+
+ mov esi, [esp+16] ; pointer to Number
+
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts
+
+ xor eax, eax
+
+ lock dec dword ptr [esi] ; count down
+@@: cmp dword ptr [esi], 0 ; wait for all processors to signal
+ jnz short @b
+
+ cpuid ; fence
+
+ mov ecx, MsrTSC ; MSR of time stamp counter
+ xor eax, eax
+ xor edx, edx
+ wrmsr ; clear time stamp counter
+
+ popfd ; restore interrupt flag
+ pop ebx
+ pop edi
+ pop esi
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+INIT ends
+
+ end
diff --git a/private/ntos/nthals/halmps/i386/mpspin.asm b/private/ntos/nthals/halmps/i386/mpspin.asm
new file mode 100644
index 000000000..e43c41f75
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpspin.asm
@@ -0,0 +1,547 @@
+if NT_INST
+
+else
+ TITLE "Spin Locks"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spinlock.asm
+;
+; Abstract:
+;
+; This module implements x86 spinlock functions for the PC+MP
+; HAL.
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 13 Dec 89
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ron Mosgrove (o-RonMo) Dec 93 - modified for PC+MP Hal
+;--
+
+ PAGE
+
+.486p
+
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include hal386.inc
+include mac386.inc
+include i386\apic.inc
+include i386\pcmp_nt.inc
+
+ EXTRNP KfRaiseIrql, 1,,FASTCALL
+ EXTRNP KfLowerIrql, 1,,FASTCALL
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+ extrn _HalpVectorToIRQL:byte
+ extrn _HalpIRQLtoTPR:byte
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+ LOCK_CMPXCHG equ cmpxchg
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+ LOCK_CMPXCHG equ lock cmpxchg
+endif
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ PAGE
+ SUBTTL "Acquire Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql (TOS+8) - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KfAcquireSpinLock ,1
+cPublicFpo 0,0
+
+ mov edx, dword ptr APIC[LU_TPR] ; (ecx) = Old Priority (Vector)
+ mov dword ptr APIC[LU_TPR], DPC_VECTOR ; Write New Priority to the TPR
+
+ shr edx, 4
+ movzx eax, _HalpVectorToIRQL[edx] ; (al) = OldIrql
+
+ifndef NT_UP
+
+;
+; Attempt to assert the lock
+;
+
+sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
+ fstRET KfAcquireSpinLock
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+ align dword
+
+sl20: SPIN_ON_SPINLOCK ecx,sl10
+endif
+
+
+ fstRET KfAcquireSpinLock
+fstENDP KfAcquireSpinLock
+
+
+ PAGE
+ SUBTTL "Acquire Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired,
+; and any spin occurs at OldIrql)
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql (TOS+8) - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+ mov edx, dword ptr APIC[LU_TPR] ; (ecx) = Old Priority (Vector)
+ mov eax, edx
+ shr eax, 4
+ movzx eax, _HalpVectorToIRQL[eax] ; (al) = OldIrql
+
+ifdef NT_UP
+ mov dword ptr APIC[LU_TPR], APIC_SYNCH_VECTOR ; Write New Priority to the TPR
+ fstRET KeAcquireSpinLockRaiseToSynch
+else
+
+;
+; Test lock
+;
+ TEST_SPINLOCK ecx,<short sls30>
+
+;
+; Raise irql
+;
+
+sls10: mov dword ptr APIC[LU_TPR], APIC_SYNCH_VECTOR
+
+;
+; Attempt to assert the lock
+;
+
+ ACQUIRE_SPINLOCK ecx,<short sls20>
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+;
+; Lock is owned, spin till it looks free, then go get it
+;
+
+ align dword
+sls20: mov dword ptr APIC[LU_TPR], edx
+
+ align dword
+sls30: SPIN_ON_SPINLOCK ecx,sls10
+endif
+
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+
+ifndef NT_UP
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynchMCE (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function performs the same function as KeAcquireSpinLockRaiseToSynch
+; but provides a work around for an IFU errata for Pentium Pro processors
+; prior to stepping 619.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql (TOS+8) - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynchMCE,1
+cPublicFpo 0,0
+
+ mov edx, dword ptr APIC[LU_TPR] ; (ecx) = Old Priority (Vector)
+ mov eax, edx
+ shr eax, 4
+ movzx eax, _HalpVectorToIRQL[eax] ; (al) = OldIrql
+
+;
+; Test lock
+;
+; TEST_SPINLOCK ecx,<short slm30> ; NOTE - Macro expanded below:
+
+ test dword ptr [ecx], 1
+ nop ; On a P6 prior to stepping B1 (619), we
+ nop ; need these 5 NOPs to ensure that we
+ nop ; do not take a machine check exception.
+ nop ; The cost is just 1.5 clocks as the P6
+ nop ; just tosses the NOPs.
+ jnz short slm30
+
+
+;
+; Raise irql
+;
+
+slm10: mov dword ptr APIC[LU_TPR], APIC_SYNCH_VECTOR
+
+;
+; Attempt to assert the lock
+;
+
+ ACQUIRE_SPINLOCK ecx,<short slm20>
+ fstRET KeAcquireSpinLockRaiseToSynchMCE
+
+;
+; Lock is owned, spin till it looks free, then go get it
+;
+
+ align dword
+slm20: mov dword ptr APIC[LU_TPR], edx
+
+ align dword
+slm30: SPIN_ON_SPINLOCK ecx,slm10
+
+fstENDP KeAcquireSpinLockRaiseToSynchMCE
+endif
+
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; FASTCALL
+; KeReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+ xor eax, eax
+ mov al, dl ; (eax) = new irql value
+
+ifndef NT_UP
+ RELEASE_SPINLOCK ecx ; release spinlock
+endif
+
+ xor ecx, ecx
+ mov cl, _HalpIRQLtoTPR[eax] ; get TPR value corresponding to IRQL
+ mov dword ptr APIC[LU_TPR], ecx
+
+;
+; We have to ensure that the requested priority is set before
+; we return. The caller is counting on it.
+;
+ mov eax, dword ptr APIC[LU_TPR]
+if DBG
+ cmp ecx, eax ; Verify IRQL read back is same as
+ je short @f ; set value
+ int 3
+@@:
+endif
+ fstRET KfReleaseSpinLock
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; Routine Description:
+;
+; Acquires a spinlock with interrupts disabled
+;
+; Arguments:
+;
+; SpinLock
+;
+; Return Value:
+;
+;--
+
+cPublicFastCall HalpAcquireHighLevelLock ,1
+ pushfd
+ pop eax
+
+ahll10: cli
+ ACQUIRE_SPINLOCK ecx, ahll20
+ fstRET HalpAcquireHighLevelLock
+
+ahll20:
+ push eax
+ popfd
+
+ SPIN_ON_SPINLOCK ecx, <ahll10>
+
+fstENDP HalpAcquireHighLevelLock
+
+
+;++
+;
+; Routine Description:
+;
+; Release spinlock
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+;--
+
+cPublicFastCall HalpReleaseHighLevelLock ,2
+
+ RELEASE_SPINLOCK ecx
+ push edx
+ popfd
+ fstRET HalpReleaseHighLevelLock
+
+fstENDP HalpReleaseHighLevelLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,0
+ mov eax, dword ptr APIC[LU_TPR] ; (eax) = Old Priority (Vector)
+ mov dword ptr APIC[LU_TPR], APC_VECTOR ; Write New Priority to the TPR
+
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,2
+ push ecx
+ push eax
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax ; (al) = OldTpr
+ pop ecx ; (ecx) = FAST_MUTEX
+
+cPublicFpo 0,0
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+cPublicFpo 0,0
+ xor eax, eax
+ mov al, byte ptr [ecx].FmOldIrql ; (eax) = OldTpr
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ js short rfm05 ; if < 0, set event
+ jnz short rfm10 ; if != 0, don't set event
+
+cPublicFpo 0,1
+rfm05: add ecx, FmEvent
+ push eax ; save new tpr
+ stdCall _KeSetEventBoostPriority, <ecx, 0>
+ pop eax ; restore tpr
+
+cPublicFpo 0,0
+rfm10: mov dword ptr APIC[LU_TPR], eax
+ mov ecx, dword ptr APIC[LU_TPR]
+if DBG
+ cmp eax, ecx ; Verify TPR is what was
+ je short @f ; written
+ int 3
+@@:
+endif
+ fstRet ExReleaseFastMutex
+
+fstENDP ExReleaseFastMutex
+
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+
+;
+; Try to acquire
+;
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam25 ; Yes, abort
+
+ mov eax, dword ptr APIC[LU_TPR] ; (eax) = Old Priority (Vector)
+ mov dword ptr APIC[LU_TPR], APC_VECTOR ; Write New Priority to the TPR
+
+cPublicFpo 0,1
+ push eax ; Save Old TPR
+
+ mov edx, 0 ; Value to set
+ mov eax, 1 ; Value to compare against
+ LOCK_CMPXCHG dword ptr [ecx].FmCount, edx ; Attempt to acquire
+ jnz short tam20 ; got it?
+
+cPublicFpo 0,0
+ pop edx ; (edx) = Old TPR
+ mov eax, 1 ; return TRUE
+ mov byte ptr [ecx].FmOldIrql, dl ; Store Old TPR
+ fstRet ExTryToAcquireFastMutex
+
+tam20: pop ecx ; (ecx) = Old TPR
+ mov dword ptr APIC[LU_TPR], ecx
+ mov eax, dword ptr APIC[LU_TPR]
+
+if DBG
+ cmp ecx, eax ; Verify TPR is what was
+ je short @f ; written
+ int 3
+@@:
+endif
+
+tam25: xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+
+
+_TEXT ends
+
+ENDIF ; NT_INST
+
+ end
diff --git a/private/ntos/nthals/halmps/i386/mpsproc.c b/private/ntos/nthals/halmps/i386/mpsproc.c
new file mode 100644
index 000000000..e15e8f767
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpsproc.c
@@ -0,0 +1,1117 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Intel Corporation
+All rights reserved
+
+INTEL CORPORATION PROPRIETARY INFORMATION
+
+This software is supplied to Microsoft under the terms
+of a license agreement with Intel Corporation and may not be
+copied nor disclosed except in accordance with the terms
+of that agreement.
+
+Module Name:
+
+ mpsproc.c
+
+Abstract:
+
+ PC+MP Start Next Processor c code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ PC+MP System
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Ron Mosgrove (Intel) - Modified to support the PC+MP
+
+--*/
+
+#include "halp.h"
+#include "pcmp_nt.inc"
+#include "apic.inc"
+#include "stdio.h"
+
+#ifdef DEBUGGING
+
+void
+HalpDisplayString(
+ IN PVOID String
+ );
+
+#endif // DEBUGGING
+
+#if !defined(NT_UP)
+ #if !defined(MCA)
+ UCHAR HalName[] = "MPS 1.4 - APIC platform";
+ #else
+ UCHAR HalName[] = "MPS 1.4 MCA - APIC platform";
+ #endif
+#else
+ #if !defined(MCA)
+ UCHAR HalName[] = "UP MPS 1.4 - APIC platform";
+ #else
+ UCHAR HalName[] = "UP MPS 1.4 MCA - APIC platform";
+ #endif
+#endif
+
+
+#if !defined(NT_UP)
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+VOID
+StartPx_PMStub (
+ VOID
+ );
+
+ULONG
+HalpStartProcessor (
+ IN PVOID InitCodePhysAddr,
+ IN ULONG ProcessorNumber
+ );
+#endif
+
+VOID
+HalpSet8259Mask(
+ IN USHORT Mask
+ );
+
+VOID
+HalpBiosDisplayReset (
+ VOID
+ );
+
+VOID
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpInheritBusAddressMapInfo (
+ VOID
+ );
+
+VOID
+HalpInitBusAddressMapInfo (
+ VOID
+ );
+
+VOID
+HalpResetThisProcessor (
+ VOID
+ );
+
+VOID
+HalpApicRebootService(
+ VOID
+ );
+
+VOID
+HalpRemoveFences (
+ VOID
+ );
+
+extern VOID (*HalpRebootNow)(VOID);
+
+
+volatile ULONG HalpProcessorsNotHalted = 0;
+
+#define LOW_MEMORY 0x000100000
+
+//
+// From hal386.inc
+//
+
+#define IDT_NMI_VECTOR 2
+#define D_INT032 0x8E00
+#define KGDT_R0_CODE 0x8
+
+//
+// Defines to let us diddle the CMOS clock and the keyboard
+//
+
+#define CMOS_CTRL (PUCHAR )0x70
+#define CMOS_DATA (PUCHAR )0x71
+
+
+#define MAX_PT 8
+#define RESET 0xfe
+#define KEYBPORT (PUCHAR )0x64
+
+extern USHORT HalpGlobal8259Mask;
+extern PKPCR HalpProcessorPCR[];
+extern struct HalpMpInfo HalpMpInfoTable;
+
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR Halp1stPhysicalPageVaddr; // pointer to physical memory 0:0
+PUSHORT MppProcessorAvail; // pointer to processavail flag
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+ULONG HalpDontStartProcessors = 0;
+
+extern ULONG HalpIpiClock;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#if !defined(NT_UP)
+#pragma alloc_text(INIT,HalpBuildTiledCR3)
+#pragma alloc_text(INIT,HalpMapCR3)
+#pragma alloc_text(INIT,HalpFreeTiledCR3)
+#pragma alloc_text(INIT,HalpStartProcessor)
+#endif
+#endif
+
+
+
+VOID
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ None.
+
+--*/
+{
+ PKPCR pPCR;
+
+
+ pPCR = KeGetPcr();
+
+ //
+ // Increment a count of the number of processors
+ // running NT, This could be different from the
+ // number of enabled processors, if one or more
+ // of the processor failed to start.
+ //
+ if (Phase == 1)
+ HalpMpInfoTable.NtProcessors++;
+#ifdef DEBUGGING
+ sprintf(Cbuf, "HalpInitMP: Number of Processors = 0x%x\n",
+ HalpMpInfoTable.NtProcessors);
+
+ HalpDisplayString(Cbuf);
+#endif
+
+ if (Phase == 0) {
+
+#if defined(NT_UP)
+
+ //
+ // On UP build - done
+ //
+
+ return ;
+#endif
+
+ //
+ // Map the 1st Physical page of memory
+ //
+ Halp1stPhysicalPageVaddr = HalpMapPhysicalMemory (0, 1);
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress) {
+ //
+ // Can't get memory
+ //
+
+#if DBG
+ DbgPrint("HAL: can't allocate memory to start processors\n");
+#endif
+ return;
+ }
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+
+ } else {
+
+ //
+ // Phase 1 for another processor
+ //
+ if (pPCR->Prcb->Number != 0) {
+ HalpIpiClock = 0xff;
+ }
+ }
+}
+
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ if (KeGetPcr()->Number == 0) {
+
+ if (HalpFeatureBits & HAL_PERF_EVENTS) {
+
+ //
+ // Enable local perf events on each processor
+ //
+
+ HalpGenericCall (
+ HalpEnablePerfInterupt,
+ (ULONG) NULL,
+ HalpActiveProcessors
+ );
+
+ }
+
+ if (HalpFeatureBits & HAL_NO_SPECULATION) {
+
+ //
+ // Processor doesn't perform speculative execeution,
+ // remove fences in critical code paths
+ //
+
+ HalpRemoveFences ();
+ }
+ }
+
+ return TRUE;
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+ INTERFACE_TYPE interfacetype;
+
+ //
+ // Initialize phase 2
+ //
+
+ HalInitSystemPhase2 ();
+
+ //
+ // Set type
+ //
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+ default: interfacetype = Internal; break;
+ }
+
+ //
+ // Report HALs resource usage
+ //
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Turn on MCA support if present
+ //
+
+ HalpMcaInit();
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+ //
+ // Update supported address info with MPS bus address map
+ //
+
+ HalpInitBusAddressMapInfo ();
+
+ //
+ // Inherit any bus address mappings from MPS hierarchy descriptors
+ //
+
+ HalpInheritBusAddressMapInfo ();
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This procedure is called by the HalpReboot routine. It is called in
+ response to a system reset request.
+
+ This routine generates a reboot request via the APIC's ICR.
+
+ This routine will NOT return.
+
+--*/
+{
+ ULONG j;
+ PKIDTENTRY IdtPtr;
+ PKPRCB Prcb;
+
+#ifndef NT_UP
+ HalpProcessorsNotHalted = HalpMpInfoTable.NtProcessors;
+#else
+ //
+ // Only this processor needs to be halted
+ //
+ HalpProcessorsNotHalted = 1;
+#endif
+
+ //
+ // Set all processors NMI handlers
+ //
+
+ for (j = 0; j < HalpMpInfoTable.NtProcessors; ++j) {
+ IdtPtr = HalpProcessorPCR[j]->IDT;
+ IdtPtr[IDT_NMI_VECTOR].Offset = LOWWORD(HalpApicRebootService);
+ IdtPtr[IDT_NMI_VECTOR].ExtendedOffset = HIGHWORD(HalpApicRebootService);
+ IdtPtr[IDT_NMI_VECTOR].Selector = KGDT_R0_CODE;
+ IdtPtr[IDT_NMI_VECTOR].Access = D_INT032;
+ }
+
+ if (HalpProcessorsNotHalted > 1) {
+
+ //
+ // Wait for the ICR to become free
+ //
+
+ if (HalpWaitForPending (0xFFFF, pLocalApic + LU_INT_CMD_LOW/4)) {
+
+ //
+ // For P54c or better processors, reboot by sending all processors
+ // NMIs. For pentiums we send interrupts, since there are some
+ // pentium MP machines where the NMIs method does not work.
+ //
+ // The NMI method is better.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ j = Prcb->CpuType << 16 | (Prcb->CpuStep & 0xff00);
+ if (j > 0x50100) {
+
+ //
+ // Get other processors attention with an NMI
+ //
+
+ pLocalApic[LU_INT_CMD_LOW/4] = (ICR_ALL_EXCL_SELF | DELIVER_NMI);
+
+ //
+ // Wait 5ms and see if any processors took the NMI. If not,
+ // go do it the old way.
+ //
+
+ KeStallExecutionProcessor(5000);
+ if (HalpProcessorsNotHalted != HalpMpInfoTable.NtProcessors) {
+
+ //
+ // Reboot local
+ //
+
+ HalpApicRebootService();
+ }
+ }
+
+ //
+ // Signal other processors which also may be waiting to
+ // reboot the machine, that it's time to go
+ //
+
+ HalpRebootNow = HalpResetThisProcessor;
+
+ //
+ // Send a reboot interrupt
+ //
+
+ pLocalApic[LU_INT_CMD_LOW/4] = (ICR_ALL_INCL_SELF | APIC_REBOOT_VECTOR);
+
+ //
+ // we're done - set TPR to zero so the reboot interrupt will happen
+ //
+
+ pLocalApic[LU_TPR/4] = 0;
+ _asm sti ;
+ for (; ;) ;
+ }
+ }
+
+
+ //
+ // Reset the old fashion way
+ //
+
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+}
+
+VOID
+HalpResetThisProcessor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This procedure is called by the HalpReboot routine.
+ It is called in response to a system reset request.
+
+ This routine is called by the reboot ISR (linked to
+ APIC_REBOOT_VECTOR). The HalpResetAllProcessors
+ generates the reboot request via the APIC's ICR.
+
+ The function of this routine is to perform any processor
+ specific shutdown code needed and then reset the system
+ (on the BSP==P0 only).
+
+ This routine will NOT return.
+
+--*/
+{
+ PUSHORT Magic;
+ ULONG ThisProcessor = 0;
+ ULONG i, j, max, RedirEntry;
+ ULONG AllProcessorsHalted;
+ struct ApicIoUnit *IoUnitPtr;
+
+ ThisProcessor = KeGetPcr()->Prcb->Number;
+
+ //
+ // Do whatever is needed to this processor to restore
+ // system to a bootable state
+ //
+
+ pLocalApic[LU_TPR/4] = 0xff;
+ pLocalApic[LU_TIMER_VECTOR/4] =
+ (APIC_SPURIOUS_VECTOR |PERIODIC_TIMER | INTERRUPT_MASKED);
+ pLocalApic[LU_INT_VECTOR_0/4] =
+ (APIC_SPURIOUS_VECTOR | INTERRUPT_MASKED);
+ pLocalApic[LU_INT_VECTOR_1/4] =
+ ( LEVEL_TRIGGERED | ACTIVE_HIGH | DELIVER_NMI |
+ INTERRUPT_MASKED | NMI_VECTOR);
+ if (HalpMpInfoTable.ApicVersion != APIC_82489DX) {
+ pLocalApic[LU_FAULT_VECTOR/4] =
+ APIC_FAULT_VECTOR | INTERRUPT_MASKED;
+ }
+
+ if (ThisProcessor == 0) {
+ _asm {
+ lock dec HalpProcessorsNotHalted
+ }
+ //
+ // we are running on the BSP, wait for everyone to
+ // complete the re-initialization code above
+ //
+ AllProcessorsHalted = 0;
+ while(!AllProcessorsHalted) {
+ _asm {
+ lock and HalpProcessorsNotHalted,0xffffffff
+ jnz EveryOneNotDone
+ inc AllProcessorsHalted
+EveryOneNotDone:
+ } // asm block
+ } // NOT AllProcessorsHalted
+
+ KeStallExecutionProcessor(100);
+ //
+ // Write the Shutdown reason code, so the BIOS knows
+ // this is a reboot
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x0f); // CMOS Addr 0f
+
+ WRITE_PORT_UCHAR(CMOS_DATA, 0x00); // Reason Code Reset
+
+ Magic = HalpMapPhysicalMemory(0, 1);
+ Magic[0x472 / sizeof(USHORT)] = 0x1234; // warm boot
+
+ //
+ // If required, disable APIC mode
+ //
+
+ if (HalpMpInfoTable.IMCRPresent)
+ {
+ _asm {
+ mov al, ImcrPort
+ out ImcrRegPortAddr, al
+ }
+
+ KeStallExecutionProcessor(100);
+ _asm {
+ mov al, ImcrDisableApic
+ out ImcrDataPortAddr, al
+ }
+ }
+
+ KeStallExecutionProcessor(100);
+
+ for (j=0; j<HalpMpInfoTable.IOApicCount; j++) {
+ IoUnitPtr = (struct ApicIoUnit *) HalpMpInfoTable.IoApicBase[j];
+
+ //
+ // Disable all interrupts on IO Unit
+ //
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ max = ((IoUnitPtr->RegisterWindow >> 16) & 0xff) * 2;
+ for (i=0; i <= max; i += 2) {
+ IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW + i;
+ IoUnitPtr->RegisterWindow |= INT_VECTOR_MASK | INTERRUPT_MASKED;
+
+ //
+ // Clear any set Remote IRR bits by programming the entry to
+ // edge and then back to level. Otherwise there will be
+ // no further interrupts from this source.
+ //
+
+ IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW + i;
+ RedirEntry = IoUnitPtr->RegisterWindow;
+ if ( (RedirEntry & LEVEL_TRIGGERED) && (RedirEntry & REMOTE_IRR)) {
+ RedirEntry &= ~LEVEL_TRIGGERED;
+ IoUnitPtr->RegisterWindow = RedirEntry;
+ RedirEntry = IoUnitPtr->RegisterWindow;
+ RedirEntry |= LEVEL_TRIGGERED;
+ IoUnitPtr->RegisterWindow = RedirEntry;
+ }
+ }
+ } // for all Io Apics
+
+ //
+ // Disable the Local Apic
+ //
+ pLocalApic[LU_SPURIOUS_VECTOR/4] =
+ (APIC_SPURIOUS_VECTOR | LU_UNIT_DISABLED);
+
+
+ KeStallExecutionProcessor(100);
+
+ _asm {
+ cli
+ };
+
+ //
+ // Enable Pic interrupts
+ //
+ HalpGlobal8259Mask = 0;
+ HalpSet8259Mask ((USHORT) HalpGlobal8259Mask);
+
+ KeStallExecutionProcessor(1000);
+
+ //
+ // Finally, reset the system through
+ // the keyboard controller
+ //
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+
+ } else {
+ //
+ // We're running on a processor other than the BSP
+ //
+
+ //
+ // Disable the Local Apic
+ //
+
+ pLocalApic[LU_SPURIOUS_VECTOR/4] =
+ (APIC_SPURIOUS_VECTOR | LU_UNIT_DISABLED);
+
+ KeStallExecutionProcessor(100);
+
+ //
+ // Now we are done, tell the BSP
+ //
+
+ _asm {
+ lock dec HalpProcessorsNotHalted
+ }
+ } // Not BSP
+
+
+ //
+ // Everyone stops here until reset
+ //
+ _asm {
+ cli
+StayHalted:
+ hlt
+ jmp StayHalted
+ }
+}
+
+#if !defined(NT_UP)
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode.
+ In order to move the processor from real-mode to protected
+ mode with flat addressing the segment which loads CR0 needs
+ to have it's linear address mapped to machine the phyiscal
+ location of the segment for said instruction so the
+ processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory.
+ In addition, other flat addresses are tiled to match the
+ current running flat address for the new state. Once the
+ processor is in flat mode, we move to a NT tiled page which
+ can then load up the remaining processors state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page
+ directory. Used to build a tiled page directory with
+ real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped
+ to, if passed as a NULL then the physical
+ address of the passed virtual address
+ is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress =
+ (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory
+ was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+ULONG
+HalpStartProcessor (
+ IN PVOID InitCodePhysAddr,
+ IN ULONG ProcessorNumber
+ )
+/*++
+
+Routine Description:
+
+ Actually Start the Processor in question. This routine
+ assumes the init code is setup and ready to run. The real
+ mode init code must begin on a page boundry.
+
+ NOTE: This assumes the BSP is entry 0 in the MP table.
+
+ This routine cannot fail.
+
+Arguments:
+ InitCodePhysAddr - execution address of init code
+
+Return Value:
+ 0 - Something prevented us from issuing the reset.
+
+ n - Processor's PCMP Local APICID + 1
+--*/
+{
+ PPCMPPROCESSOR ApPtr ;
+ UCHAR ApicID;
+ PVULONG LuDestAddress = (PVULONG) (LOCALAPIC + LU_INT_CMD_HIGH);
+ PVULONG LuICR = (PVULONG) (LOCALAPIC + LU_INT_CMD_LOW);
+#define DEFAULT_DELAY 100
+ ULONG DelayCount = DEFAULT_DELAY;
+ ULONG ICRCommand,i;
+
+ ASSERT((((ULONG) InitCodePhysAddr) & 0xfff00fff) == 0);
+
+ //
+ // Get the MP Table entry for this processor
+ //
+ ApicID = 0xff;
+ ApPtr = HalpMpInfoTable.ProcessorEntryPtr;
+
+ if (ProcessorNumber >= HalpMpInfoTable.ProcessorCount) {
+ return(0);
+ }
+
+ while ((ProcessorNumber) && (ApPtr->EntryType == ENTRY_PROCESSOR)) {
+ if (ApPtr->CpuFlags & CPU_ENABLED) {
+ --ProcessorNumber;
+ }
+ ++ApPtr;
+ }
+
+ // Find the first remaining enabled processor.
+ while(ApPtr->EntryType == ENTRY_PROCESSOR) {
+ if ((ApPtr->CpuFlags & CPU_ENABLED) &&
+ !(ApPtr->CpuFlags & BSP_CPU)) {
+ ApicID = (UCHAR) ApPtr->LocalApicId;
+ break;
+ }
+ ++ApPtr;
+ }
+
+ if (ApicID == 0xff) {
+#ifdef DEBUGGING
+ HalpDisplayString("HAL: HalpStartProcessor: No Processor Available\n");
+#endif
+ return 0;
+ }
+
+ if (HalpDontStartProcessors)
+ return ApicID+1;
+
+ //
+ // Make sure we can get to the Apic Bus
+ //
+
+ KeStallExecutionProcessor(200);
+ if (HalpWaitForPending (DEFAULT_DELAY, LuICR) == 0) {
+ //
+ // We couldn't find a processor to start
+ //
+#ifdef DEBUGGING
+ HalpDisplayString("HAL: HalpStartProcessor: can't access APIC Bus\n");
+#endif
+ return 0;
+ }
+
+ // For a P54 C/CM system, it is possible that the BSP is the P54CM and the
+ // P54C is the Application processor. The P54C needs an INIT (reset)
+ // to restart, so we issue a reset regardless of whether we a 82489DX
+ // or an integrated APIC.
+
+ //
+ // This system is based on the original 82489DX's.
+ // These devices do not support the Startup IPI's.
+ // The mechanism used is the ASSERT/DEASSERT INIT
+ // feature of the local APIC. This resets the
+ // processor.
+ //
+
+#ifdef DEBUGGING
+ sprintf(Cbuf, "HAL: HalpStartProcessor: Reset IPI to ApicId %d (0x%x)\n",
+ ApicID,((ULONG) ApicID) << DESTINATION_SHIFT );
+ HalpDisplayString(Cbuf);
+#endif
+
+ //
+ // We use a Physical Destination
+ //
+
+ *LuDestAddress = ((ULONG) ApicID) << DESTINATION_SHIFT;
+
+ //
+ // Now Assert reset and drop it
+ //
+
+ *LuICR = LU_RESET_ASSERT;
+ KeStallExecutionProcessor(10);
+ *LuICR = LU_RESET_DEASSERT;
+ KeStallExecutionProcessor(200);
+
+ if (HalpMpInfoTable.ApicVersion == APIC_82489DX) {
+ return ApicID+1;
+ }
+
+ //
+ // Set the Startup Address as a vector and combine with the
+ // ICR bits
+ //
+ ICRCommand = (((ULONG) InitCodePhysAddr & 0x000ff000) >> 12)
+ | LU_STARTUP_IPI;
+
+#ifdef DEBUGGING
+ sprintf(Cbuf, "HAL: HalpStartProcessor: Startup IPI (0x%x) to ApicId %d (0x%x)\n",
+ ICRCommand, ApicID, ((ULONG) ApicID) << DESTINATION_SHIFT );
+ HalpDisplayString(Cbuf);
+#endif
+
+ //
+ // Set the Address of the APIC again, this may not be needed
+ // but it can't hurt.
+ //
+ *LuDestAddress = (ApicID << DESTINATION_SHIFT);
+ //
+ // Issue the request
+ //
+ *LuICR = ICRCommand;
+ KeStallExecutionProcessor(200);
+
+ //
+ // Repeat the Startup IPI. This is because the second processor may
+ // have been issued an INIT request. This is generated by some BIOSs.
+ //
+ // On older processors (286) BIOS's use a mechanism called triple
+ // fault reset to transition from protected mode to real mode.
+ // This mechanism causes the processor to generate a shutdown cycle.
+ // The shutdown is typically issued by the BIOS building an invalid
+ // IDT and then generating an interrupt. Newer processors have an
+ // INIT line that the chipset jerks when it sees a shutdown cycle
+ // issued by the processor. The Phoenix BIOS, for example, has
+ // integrated support for triple fault reset as part of their POST
+ // (Power On Self Test) code.
+ //
+ // When the P54CM powers on it is held in a tight microcode loop
+ // waiting for a Startup IPI to be issued and queuing other requests.
+ // When the POST code executes the triple fault reset test the INIT
+ // cycle is queued by the processor. Later, when a Startup IPI is
+ // issued to the CM, the CM starts and immediately gets a INIT cycle.
+ // The effect from a software standpoint is that the processor is
+ // never started.
+ //
+ // The work around implemented here is to issue two Startup IPI's.
+ // The first allows the INIT to be processed and the second performs
+ // the actual startup.
+ //
+
+ //
+ // Make sure we can get to the Apic Bus
+ //
+
+
+ if (HalpWaitForPending (DEFAULT_DELAY, LuICR) == 0) {
+ //
+ // We're toast, can't gain access to the APIC Bus
+ //
+#ifdef DEBUGGING
+ HalpDisplayString("HAL: HalpStartProcessor: can't access APIC Bus\n");
+#endif
+ return 0;
+ }
+
+ //
+ // Allow Time for any Init request to be processed
+ //
+ KeStallExecutionProcessor(100);
+
+ //
+ // Set the Address of the APIC again, this may not be needed
+ // but it can't hurt.
+ //
+ *LuDestAddress = (ApicID << DESTINATION_SHIFT);
+ //
+ // Issue the request
+ //
+ *LuICR = ICRCommand;
+
+ KeStallExecutionProcessor(200);
+ return ApicID+1;
+}
+#endif // !NT_UP
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halmps/i386/mpsproca.asm b/private/ntos/nthals/halmps/i386/mpsproca.asm
new file mode 100644
index 000000000..86890a7ef
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpsproca.asm
@@ -0,0 +1,558 @@
+ title "MP primitives for MP+AT Systems"
+
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 Intel Corporation
+;All rights reserved
+;
+;INTEL CORPORATION PROPRIETARY INFORMATION
+;
+;This software is supplied to Microsoft under the terms
+;of a license agreement with Intel Corporation and may not be
+;copied nor disclosed except in accordance with the terms
+;of that agreement.
+;
+;
+;Module Name:
+;
+; mpsproca.asm
+;
+;Abstract:
+;
+; PC+MP Start Next Processor assemble code
+;
+; This module along with mpspro.c implement the code to start
+; processors on MP+AT Systems.
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+;Revision History:
+;
+; Ron Mosgrove (Intel) - Modified to support PC+MP Systems
+;
+;--
+
+
+
+.386p
+ .xlist
+include i386\ixcmos.inc
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\pcmp_nt.inc
+ .list
+
+ifndef NT_UP
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+ EXTRNP _HalpStartProcessor,2
+endif
+
+ EXTRNP _HalpAcquireCmosSpinLock
+ EXTRNP _HalpReleaseCmosSpinLock
+
+ EXTRNP _HalDisplayString,1
+
+ extrn _Halp1stPhysicalPageVaddr:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+; SPx_Jmp_Inst db ? ; e9 == jmp rel16
+; SPx_Jmp_Offset dw ? ; 16 bit relative offset
+; SPx_Filler db ? ; word alignment
+ SPx_Jmp_Inst dd ?
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_PB db ProcessorStateLength dup (?)
+PxParamBlock ends
+
+WarmResetVector equ 467h ; warm reset vector in ROM data segment
+
+SHOWDOTS equ 0
+
+if DEBUGGING OR SHOWDOTS
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ ALIGN dword
+HalTimeOutFail db 'HAL: Next CPU Timed Out', cr, lf, 0
+HalDots db '.', 0
+HalEndDots db cr, lf, 0
+
+_DATA ends
+endif
+
+
+INIT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists or if the processor fails to
+; start, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; In order to use the Startup IPI the real mode startup code must be
+; page aligned. The MpLowStubPhysicalAddress has always been page
+; aligned but because the PxParamBlock was placed first in this
+; segment the real mode code has been something other than page aligned.
+; This has been changed by making the first entry in the PxParamBlock
+; a jump instruction to the real mode startup code.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+LWarmResetVector equ [ebp - size PxParamBlock - 4]
+LStatusCode equ [ebp - size PxParamBlock - 8]
+LCmosValue equ [ebp - size PxParamBlock - 12]
+
+
+cPublicProc _HalStartNextProcessor ,2
+ifdef NT_UP
+ xor eax, eax ; up build of hal, no processors to
+ stdRET _HalStartNextProcessor ; start
+else
+ push ebp ; save ebp
+ mov ebp, esp ; Save Frame
+ sub esp, size PxParamBlock + 12 ; Make room for local vars
+
+ push esi ; Save required registers
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov LStatusCode, eax
+
+ mov PxFrame.SPx_flag, eax ; Initialize the MP Completion flag
+
+ ;
+ ; Build a jmp to the start of the Real mode startup code
+ ;
+ ; This is needed because the Local APIC implementations
+ ; use a Startup IPI that must be Page aligned. The allocation
+ ; code int MP_INIT ensures that this is page aligned. The
+ ; original code was written to place the parameter block first.
+ ; By adding a jump instruction to the start of the parameter block
+ ; we can run either way.
+ ;
+
+
+ mov eax, size PxParamBlock - 3 ; Jump destination relative to
+ ; next instruction
+ shl eax, 8 ; Need room for jmp instruction
+ mov al,0e9h
+ mov dword ptr PxFrame.SPx_Jmp_Inst, eax
+
+; mov byte ptr PxFrame.SPx_Jmp_Inst, 0e9h ; e9 == jmp rel16
+; mov eax, size PxParamBlock - 3 ; Jump destination relative to next instruction
+; mov word ptr PxFrame.SPx_Jmp_Offset, ax
+
+
+ ;
+ ; Copy RMStub to low memory
+ ;
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+
+ mov edi, _MpLowStub ; Destination was allocated by MpInit
+ add edi, size PxParamBlock ; Parameter Block is placed first
+ rep movsb
+
+ ;
+ ; Copy Processor state into the stack based Parameter Block
+ ;
+ lea edi, PxFrame.SPx_PB ; Destination on stack
+ mov esi, pProcessorState ; Input parameter address
+ mov ecx, ProcessorStateLength ; Structure length
+ rep movsb
+
+ ;
+ ; Build a CR3 for the starting processor
+ ;
+ stdCall _HalpBuildTiledCR3, <pProcessorState>
+
+ ;
+ ; Save the special registers
+ ;
+ mov PxFrame.SPx_TiledCR3, eax ; Newly contructed CR3
+ mov PxFrame.SPx_P0EBP, ebp ; Stack pointer
+
+ ;
+ ; Now the parameter block has been completed, copy it to low memory
+ ;
+ mov ecx, size PxParamBlock ; Structure length
+ lea esi, PxFrame ; Parameter Block is placed first
+ mov edi, _MpLowStub ; Destination Address
+ rep movsb
+
+ ;
+ ; Now we need to create a pointer allowing the Real Mode code to
+ ; Branch to the Protected mode code
+ ;
+ mov eax, _MpLowStub ; low memory Address
+ add eax, size PxParamBlock ; Move past the Parameter block
+
+ ;
+ ; In order to get to the label we need to compute the label offset relative
+ ; to the start of the routine and then use this as a offset from the start of
+ ; the routine ( MpLowStub + (size PxParamBlock)) in low memory.
+ ;
+ ; The following code creates a pointer to (RMStub - StartPx_RMStub)
+ ; which can then be used to access code locations via code labels directly.
+ ; Since the [eax.Label] results in the address (eax + Label) loading eax
+ ; with the pointer created above results in (RMStub - StartPx_RMStub + Label).
+ ;
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+
+ ;
+ ; Patch the real mode code with a valid long jump address, first CS then offset
+ ;
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub
+
+ ;
+ ; Set the BIOS warm reset vector to our routine in Low Memory
+ ;
+ mov ebx, _Halp1stPhysicalPageVaddr
+ add ebx, WarmResetVector
+
+ cli
+
+ mov eax, [ebx] ; Get current vector
+ mov LWarmResetVector, eax ; Save it
+
+ ;
+ ; Actually build the vector (Seg:Offset)
+ ;
+ mov eax, _MpLowStubPhysicalAddress
+ shl eax, 12 ; seg:0
+ mov dword ptr [ebx], eax ; start Px at Seg:0
+
+ ;
+ ; Tell BIOS to Jump Via The Vector we gave it
+ ; By setting the Reset Code in CMOS
+ ;
+
+ stdCall _HalpAcquireCmosSpinLock
+ mov al, 0fh
+ CMOS_READ
+ mov LCmosValue, eax
+
+ mov eax, 0a0fh
+ CMOS_WRITE
+ stdCall _HalpReleaseCmosSpinLock
+
+ ;
+ ; Start the processor
+ ;
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+
+ stdCall _HalpStartProcessor < _MpLowStubPhysicalAddress, eax >
+ or eax, eax
+ jnz short WaitTilPnOnline
+
+ ;
+ ; Zero Return Value means couldn't kick start the processor
+ ; so there's no point in waiting for it.
+ ;
+
+ jmp NotWaitingOnProcessor
+
+WaitTilPnOnline:
+ dec eax ; Local APIC ID
+
+ mov ecx, pLoaderBlock
+ mov ecx, [ecx].LpbPrcb ; get new processors PRCB
+ mov [ecx].PbHalReserved.PrcbPCMPApicId, al
+
+ ;
+ ; We can't proceed until the started processor gives us the OK
+ ;
+
+ mov ecx, 01fffffH
+
+WaitAbit:
+ cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's
+ jne short ProcessorStarted ; info
+
+if DEBUGGING OR SHOWDOTS
+ cmp cx, 0
+ jne SkipTheDot
+ push ecx
+ push eax
+ stdCall _HalDisplayString, <offset HalDots>
+ pop eax
+ pop ecx
+
+SkipTheDot:
+endif
+
+ dec ecx
+ cmp ecx, 0
+ jne short WaitAbit
+
+if DEBUGGING OR SHOWDOTS
+ stdCall _HalDisplayString, <offset HalEndDots>
+ stdCall _HalDisplayString, <offset HalTimeOutFail>
+endif
+ jmp short NotWaitingOnProcessor
+
+ProcessorStarted:
+ mov LStatusCode, 1 ; Return TRUE
+
+if DEBUGGING OR SHOWDOTS
+ stdCall _HalDisplayString, <offset HalEndDots>
+endif
+
+NotWaitingOnProcessor:
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+ mov eax, LWarmResetVector
+ mov [ebx], eax ; Restore reset vector
+
+ stdCall _HalpAcquireCmosSpinLock
+ mov eax, LCmosValue ; Restore the Cmos setting
+ shl eax, 8
+ mov al, 0fh
+ CMOS_WRITE
+ stdCall _HalpReleaseCmosSpinLock
+
+ mov eax, LStatusCode
+ sti
+
+snp_exit:
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ stdRET _HalStartNextProcessor
+endif
+
+stdENDP _HalStartNextProcessor
+
+ifndef NT_UP
+
+INIT ends ; end 32 bit code
+
+_INIT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub ,0
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+
+ nop ; Fill - Ensure 13 non-page split
+ nop ; accesses before CR3 load
+ nop ; (P6 errata #11 stepping B0)
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+stdENDP StartPx_RMStub
+
+
+_INIT16 ends ; End 16 bit code
+
+INIT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+ align dword ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+cPublicProc _StartPx_PMStub ,0
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with it's data
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ stdRET _StartPx_PMStub
+
+stdENDP _StartPx_PMStub
+
+endif ; !NT_UP
+
+
+INIT ends ; end 32 bit code
+
+
+ end
diff --git a/private/ntos/nthals/halmps/i386/mpswint.asm b/private/ntos/nthals/halmps/i386/mpswint.asm
new file mode 100644
index 000000000..ecdf27925
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpswint.asm
@@ -0,0 +1,332 @@
+
+ title "Software Interrupts"
+;++
+;
+; Copyright (c) 1992 Microsoft Corporation
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+; Module Name:
+;
+; mpswint.asm
+;
+; Abstract:
+;
+; This module implements the software interrupt handlers for
+; APIC-based PC+MP multiprocessor systems.
+;
+; Author:
+;
+; John Vert (jvert) 2-Jan-1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ron Mosgrove (Intel) - Modified for PC+MP systems
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\apic.inc
+include i386\pcmp_nt.inc
+include i386\kimacro.inc
+ .list
+
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+
+ extrn _HalpIRQLtoTPR:byte
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Request Software Interrupt"
+;++
+;
+; VOID
+; FASTCALL
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to request a software interrupt of
+; the system.
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; equates for accessing arguments
+;
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+cPublicFpo 0,0
+
+ cmp cl, PCR[PcHal.ShortDpc]
+ je short rsi10
+
+ xor eax, eax
+ mov al, cl ; get irql
+
+;
+; In an APIC based system the TPR is the Vector
+;
+
+ xor ecx, ecx
+ mov cl, _HalpIRQLtoTPR[eax] ; get Vector for IRQL
+
+;
+; Build the ICR Command - Fixed Delivery to Self, Vector == al
+;
+
+ or ecx, (DELIVER_FIXED OR ICR_SELF)
+
+;
+; Make sure the ICR is available
+;
+
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+ STALL_WHILE_APIC_BUSY
+
+;
+; Now write the command to the Memory Mapped Register
+;
+
+ mov dword ptr APIC[LU_INT_CMD_LOW], ecx
+
+;
+; We have to wait for the request to be delivered.
+; If we don't wait here, then we will return to the caller
+; before the request has been issued.
+;
+ STALL_WHILE_APIC_BUSY
+
+ popfd ; restore original interrupt mode
+ fstRET HalRequestSoftwareInterrupt
+
+;
+; Requesting a DPC interrupt when ShortDpc is set. Just set the
+; DpcPending flag - whomever set ShortDpc will check the flag
+; at the proper time
+;
+
+rsi10: mov PCR[PcHal.DpcPending], 1
+ fstRET HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+ page ,132
+ subttl "Clear Software Interrupt"
+
+;++
+;
+; VOID
+; HalClearSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to clear a possible pending software interrupt.
+; Support for this function is optional, and allows the kernel to
+; reduce the number of spurious software interrupts it receives/
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalClearSoftwareInterrupt ,1
+ fstRET HalClearSoftwareInterrupt
+fstENDP HalClearSoftwareInterrupt
+
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+cPublicProc _HalpDispatchInterrupt ,0
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+
+ mov eax, DPC_VECTOR
+
+ mov esi, dword ptr APIC[LU_TPR] ; get the old TPR
+ mov dword ptr APIC[LU_TPR], eax ; set the TPR
+
+ sti ; and allow interrupts
+
+ APICFIX edx
+
+ mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
+ APICFIX edx
+
+ ;
+ ; Go do Dispatch Interrupt processing
+ ;
+
+di10: stdCall _KiDispatchInterrupt
+
+ cli
+ mov dword ptr APIC[LU_TPR], esi ; reset the TPR
+
+;
+; We have to ensure that the requested priority is set before
+; we return. The caller is counting on it.
+;
+ mov ecx, dword ptr APIC[LU_TPR]
+ CHECKTPR ecx, esi
+
+ ;
+ ; Do interrupt exit processing without EOI
+ ;
+
+ SPURIOUS_INTERRUPT_EXIT
+stdENDP _HalpDispatchInterrupt
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+;
+; Save machine state in trap frame
+;
+
+cPublicProc _HalpApcInterrupt ,0
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hapc_a, hapc_t
+
+
+ mov eax, APC_VECTOR
+
+ mov ecx, dword ptr APIC[LU_TPR] ; get the old TPR
+ push ecx ; save it
+ mov dword ptr APIC[LU_TPR], eax ; set the TPR
+
+ sti ; and allow interrupts
+
+ APICFIX edx
+
+ mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
+ APICFIX edx
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ ; call APC deliver routine
+ ; Previous mode
+ ; Null exception frame
+ ; Trap frame
+
+ stdCall _KiDeliverApc, <eax, 0,ebp>
+
+ pop eax
+
+ cli
+ mov dword ptr APIC[LU_TPR], eax ; reset the TPR
+
+;
+; We have to ensure that the requested priority is set before
+; we return. The caller is counting on it.
+;
+ mov ecx, dword ptr APIC[LU_TPR]
+ CHECKTPR ecx, eax
+
+ ;
+ ; Do interrupt exit processing without EOI
+ ;
+
+ SPURIOUS_INTERRUPT_EXIT
+
+stdENDP _HalpApcInterrupt
+
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halmps/i386/mpsys.c b/private/ntos/nthals/halmps/i386/mpsys.c
new file mode 100644
index 000000000..3be108d15
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpsys.c
@@ -0,0 +1,1682 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Intel Corporation
+All rights reserved
+
+INTEL CORPORATION PROPRIETARY INFORMATION
+
+This software is supplied to Microsoft under the terms
+of a license agreement with Intel Corporation and may not be
+copied nor disclosed except in accordance with the terms
+of that agreement.
+
+Module Name:
+
+ mpsys.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ PC+MP system.
+
+Author:
+
+ Ron Mosgrove (Intel)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+*/
+
+#include "halp.h"
+#include "apic.inc"
+#include "pcmp_nt.inc"
+
+#define STATIC // functions used internal to this module
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+extern struct HalpMpInfo HalpMpInfoTable;
+
+#define MAX_INTI (120) // Max interrupt inputs from APICs supported
+#define MAX_SOURCE_IRQS (120) // Max differenet source interrupts supported
+
+//
+// Counters used to determine the number of interrupt enables that
+// require the Local APIC Lint0 Extint enabled
+//
+
+UCHAR Halp8259Counts[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+extern BOOLEAN HalpELCRChecked;
+extern USHORT HalpGlobal8259Mask;
+extern UCHAR HalpVectorToINTI[];
+extern UCHAR HalpInitLevel[4][4];
+extern UCHAR HalpDevPolarity[4][2];
+extern UCHAR HalpDevLevel[2][4];
+
+//
+// Initialized from MPS table
+//
+
+typedef struct _INTI_INFO {
+ UCHAR Type:4;
+ UCHAR Level:2;
+ UCHAR Polarity:2;
+ UCHAR Destinations;
+} INTI_INFO, *PINTI_INFO;
+
+INTI_INFO HalpIntiInfo[MAX_INTI];
+ULONG HalpSourceIrqIds[MAX_SOURCE_IRQS];
+UCHAR HalpSourceIrqMapping[MAX_SOURCE_IRQS];
+UCHAR HalpMaxApicInti[MAX_IOAPICS];
+
+extern PCMPBUSTRANS HalpTypeTranslation[];
+
+
+extern ADDRESS_USAGE HalpApicUsage;
+
+#define BusIrq2Id(bus,no,irq) \
+ ((bus << 16) | (no << 8) | irq)
+
+VOID
+HalpApicSpuriousService(
+ VOID
+ );
+
+VOID
+HalpLocalApicErrorService(
+ VOID
+ );
+
+VOID
+HalpInitializeIOUnits (
+ VOID
+ );
+
+VOID
+HalpInitializeLocalUnit (
+ VOID
+ );
+
+VOID
+HalpInitIntiInfo (
+ VOID
+ );
+
+VOID
+HalpMpsPCIPhysicalWorkaround (
+ VOID
+ );
+
+STATIC UCHAR
+HalpPcMpIoApicById (
+ IN UCHAR IoApicId
+ );
+
+STATIC UCHAR
+HalpGetPcMpIntiType (
+ IN UCHAR InterruptInput
+ );
+
+STATIC VOID
+HalpSetRedirEntry (
+ IN UCHAR InterruptInput,
+ IN ULONG Entry,
+ IN ULONG Destination
+ );
+
+STATIC VOID
+HalpGetRedirEntry (
+ IN UCHAR InterruptInput,
+ IN PULONG Entry,
+ IN PULONG Destination
+ );
+
+BOOLEAN
+HalpMPSBusId2NtBusId (
+ IN UCHAR ApicBusId,
+ OUT PPCMPBUSTRANS *ppBusType,
+ OUT PULONG BusNo
+ );
+
+VOID
+HalpInti2ApicInti (
+ ULONG InterruptInput,
+ PULONG ApicNo,
+ PULONG ApicInti
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializeIOUnits)
+#pragma alloc_text(INIT,HalpInitializeLocalUnit)
+#pragma alloc_text(INIT,HalpEnableNMI)
+#pragma alloc_text(INIT,HalpEnablePerfInterupt)
+#pragma alloc_text(INIT,HalpInitIntiInfo)
+#pragma alloc_text(INIT,HalpMPSBusId2NtBusId)
+#pragma alloc_text(INIT,HalpMpsPCIPhysicalWorkaround)
+#pragma alloc_text(INIT,HalpInti2ApicInti)
+#pragma alloc_text(INIT,HalpCheckELCR)
+#pragma alloc_text(PAGELK,HalpGetPcMpInterruptDesc)
+#endif
+
+
+VOID
+HalpInitIntiInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called at initialization time before any interrupts
+ are connected. It reads the PC+MP Inti table and builds internal
+ information needed to route each Inti.
+
+Return Value:
+
+ The following structures are filled in:
+ HalpIntiInfo
+ HalpSourceIrqIds
+ HalpSourceIrqMapping
+ HalpISAIqpToVector
+
+--*/
+{
+ ULONG ApicNo, BusNo, InterruptInput, IdIndex;
+ PPCMPINTI pInti;
+ PPCMPIOAPIC pIoApic;
+ PPCMPPROCESSOR pProc;
+ PPCMPBUSTRANS pBusType;
+ ULONG i, id;
+ UCHAR Level, Polarity;
+
+ //
+ // Clear IntiInfo table
+ //
+
+ for (i=0; i < MAX_INTI; i++) {
+ HalpIntiInfo[i].Type = 0xf;
+ HalpIntiInfo[i].Level = 0;
+ HalpIntiInfo[i].Polarity = 0;
+ }
+
+ //
+ // Check for MPS bios work-around
+ //
+
+ HalpMpsPCIPhysicalWorkaround();
+
+ //
+ // Initialize HalpMaxApicInti table
+ //
+
+ for (pInti = HalpMpInfoTable.IntiEntryPtr;
+ pInti->EntryType == ENTRY_INTI;
+ pInti++) {
+
+
+ //
+ // Which IoApic number is this?
+ //
+
+ for (pIoApic = HalpMpInfoTable.IoApicEntryPtr, ApicNo = 0;
+ pIoApic->EntryType == ENTRY_IOAPIC;
+ pIoApic++, ApicNo++) {
+
+ if ( (pInti->IoApicId == pIoApic->IoApicId) ||
+ (pInti->IoApicId == 0xff) ) {
+ break;
+ }
+ }
+
+ if ( (pInti->IoApicId != pIoApic->IoApicId) &&
+ (pInti->IoApicId != 0xff) ) {
+ DBGMSG ("PCMP table corrupt - IoApic not found for Inti\n");
+ continue;
+ }
+
+ if (!(pIoApic->IoApicFlag & IO_APIC_ENABLED)) {
+ DBGMSG ("PCMP IoApic for Inti is disabled\n");
+ continue;
+ }
+
+ //
+ // Make sure we are below the max # of IOApic which
+ // are supported
+ //
+
+ ASSERT (ApicNo < MAX_IOAPICS);
+
+ //
+ // Track Max Inti line per IOApic
+ //
+
+ if (pInti->IoApicInti >= HalpMaxApicInti[ApicNo]) {
+ HalpMaxApicInti[ApicNo] = pInti->IoApicInti+1;
+ }
+ }
+
+ //
+ // Make sure there aren't more Inti lines then we can support
+ //
+
+ InterruptInput = 0;
+ for (i=0; i < MAX_IOAPICS; i++) {
+ InterruptInput += HalpMaxApicInti[i];
+ }
+ ASSERT (InterruptInput < MAX_INTI);
+
+ //
+ // Look at each Inti and record it's type in it's
+ // corrisponding array entry
+ //
+
+ IdIndex = 0;
+ for (pInti = HalpMpInfoTable.IntiEntryPtr;
+ pInti->EntryType == ENTRY_INTI;
+ pInti++) {
+
+ //
+ // Which IoApic number is this?
+ //
+
+ for (pIoApic = HalpMpInfoTable.IoApicEntryPtr, ApicNo = 0;
+ pIoApic->EntryType == ENTRY_IOAPIC;
+ pIoApic++, ApicNo++) {
+
+ if ( (pInti->IoApicId == pIoApic->IoApicId) ||
+ (pInti->IoApicId == 0xff) ) {
+ break;
+ }
+ }
+
+ if (!(pIoApic->IoApicFlag & IO_APIC_ENABLED)) {
+ continue;
+ }
+
+ //
+ // Determine the NT bus this INTI is on
+ //
+
+ if (!HalpMPSBusId2NtBusId (pInti->SourceBusId, &pBusType, &BusNo)) {
+ DBGMSG ("HAL: Initialize INTI - unkown MPS bus type\n");
+ continue;
+ }
+
+ //
+ // Calulcate InterruptInput value for this APIC Inti
+ //
+
+ InterruptInput = pInti->IoApicInti;
+ for (i = 0; i < ApicNo; i++) {
+ InterruptInput += HalpMaxApicInti[i];
+ }
+
+ //
+ // Get IntiInfo for this vector.
+ //
+
+ Polarity = (UCHAR) pInti->Signal.Polarity;
+ Level = HalpInitLevel[pInti->Signal.Level][pBusType->Level];
+
+ //
+ // Verify Level & Polarity mappings made sense
+ //
+
+ ASSERT (pBusType->NtType == MicroChannel || !(Level & CFG_ERROR));
+ Level &= ~CFG_ERROR;
+
+#if DBG
+ if (HalpIntiInfo[InterruptInput].Type != 0xf) {
+ //
+ // Multiple irqs are connected to the Inti line. Make
+ // sure Type, Level, and Polarity are all the same.
+ //
+
+ ASSERT (HalpIntiInfo[InterruptInput].Type == pInti->IntType);
+ ASSERT (HalpIntiInfo[InterruptInput].Level == Level);
+ ASSERT (HalpIntiInfo[InterruptInput].Polarity == Polarity);
+ }
+#endif
+ //
+ // Remember this Inti's configuration info
+ //
+
+ HalpIntiInfo[InterruptInput].Type = pInti->IntType;
+ HalpIntiInfo[InterruptInput].Level = Level;
+ HalpIntiInfo[InterruptInput].Polarity = Polarity;
+
+ //
+ // Get IRQs encoding for translations
+ //
+
+ ASSERT (pBusType->NtType < 16);
+ ASSERT (BusNo < 256);
+ id = BusIrq2Id(pBusType->NtType, BusNo, pInti->SourceBusIrq);
+
+ //
+ // Addinti mapping to translation table, do it now
+ //
+
+ HalpSourceIrqIds[IdIndex] = id;
+ HalpSourceIrqMapping[IdIndex] = (UCHAR) InterruptInput;
+ IdIndex++;
+
+ //
+ // Lots of source IRQs are supported; however, the PC+MP table
+ // allows for an aribtrary number even beyond the APIC limit.
+ //
+
+ if (IdIndex >= MAX_SOURCE_IRQS) {
+ DBGMSG ("MAX_SOURCE_IRQS exceeded\n");
+ break;
+ }
+
+ }
+
+ //
+ // Fill in the boot processors PCMP Apic ID.
+ //
+
+ pProc = HalpMpInfoTable.ProcessorEntryPtr;
+ for (i=0; i < HalpMpInfoTable.ProcessorCount; i++, pProc++) {
+ if (pProc->CpuFlags & BSP_CPU) {
+ ((PHALPRCB)KeGetCurrentPrcb()->HalReserved)->PCMPApicID = pProc->LocalApicId;
+ }
+ }
+
+ //
+ // If this is an EISA machine check the ELCR
+ //
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ HalpCheckELCR ();
+ }
+}
+
+BOOLEAN
+HalpMPSBusId2NtBusId (
+ IN UCHAR MPSBusId,
+ OUT PPCMPBUSTRANS *ppBusType,
+ OUT PULONG BusNo
+ )
+/*++
+
+Routine Description:
+
+ Lookup MPS Table BusId into PCMPBUSTRANS (NtType) and instance #.
+
+Arguments:
+
+ MPSBusId - Bus ID # in MPS table
+ ppBusType - Returned pointer to PPCMPBUSTRANS for this bus type
+ BusNo - Returned instance # of given bus
+
+Return Value:
+
+ TRUE if MPSBusId was cross referenced into an NT id.
+
+--*/
+{
+ PPCMPBUS pBus, piBus;
+ PPCMPBUSTRANS pBusType;
+
+ //
+ // What Bus is this?
+ //
+
+ for (pBus = HalpMpInfoTable.BusEntryPtr;
+ pBus->EntryType == ENTRY_BUS;
+ pBus++) {
+
+ if (MPSBusId == pBus->BusId) {
+ break;
+ }
+ }
+
+ if (MPSBusId != pBus->BusId) {
+ DBGMSG ("PCMP table corrupt - Bus not found for Inti\n");
+ return FALSE;
+ }
+
+ //
+ // What InterfaceType is this Bus?
+ //
+
+ for (pBusType = HalpTypeTranslation;
+ pBusType->NtType != MaximumInterfaceType;
+ pBusType++) {
+
+ if (pBus->BusType[0] == pBusType->PcMpType[0] &&
+ pBus->BusType[1] == pBusType->PcMpType[1] &&
+ pBus->BusType[2] == pBusType->PcMpType[2] &&
+ pBus->BusType[3] == pBusType->PcMpType[3] &&
+ pBus->BusType[4] == pBusType->PcMpType[4] &&
+ pBus->BusType[5] == pBusType->PcMpType[5]) {
+ break;
+ }
+ }
+
+ //
+ // Which instance of this BusType?
+ //
+
+ if (!pBusType->PhysicalInstance) {
+ for (piBus = HalpMpInfoTable.BusEntryPtr, *BusNo = 0;
+ piBus < pBus;
+ piBus++) {
+
+ if (pBus->BusType[0] == piBus->BusType[0] &&
+ pBus->BusType[1] == piBus->BusType[1] &&
+ pBus->BusType[2] == piBus->BusType[2] &&
+ pBus->BusType[3] == piBus->BusType[3] &&
+ pBus->BusType[4] == piBus->BusType[4] &&
+ pBus->BusType[5] == piBus->BusType[5]) {
+ *BusNo += 1;
+ }
+ }
+ } else {
+ *BusNo = pBus->BusId;
+ }
+
+ if (pBusType->NtType == MaximumInterfaceType) {
+ return FALSE;
+ }
+
+ *ppBusType = pBusType;
+ return TRUE;
+}
+
+VOID
+HalpMpsPCIPhysicalWorkaround (
+ VOID
+ )
+{
+ PPCMPBUS pBus;
+ PPCMPBUSTRANS pBusType;
+
+ //
+ // The MPS specification has a subtle comment that PCI bus IDs are
+ // suppose to match their physical PCI bus number. Many BIOSes don't
+ // do this, so unless there's a PCI bus #0 listed in the MPS table
+ // assume that the BIOS is broken
+ //
+
+ //
+ // Find the PCI interface type
+ //
+
+ for (pBusType = HalpTypeTranslation;
+ pBusType->NtType != MaximumInterfaceType;
+ pBusType++) {
+
+ if (pBusType->PcMpType[0] == 'P' &&
+ pBusType->PcMpType[1] == 'C' &&
+ pBusType->PcMpType[2] == 'I' &&
+ pBusType->PcMpType[3] == ' ' &&
+ pBusType->PcMpType[4] == ' ' &&
+ pBusType->PcMpType[5] == ' ' ) {
+ break;
+ }
+ }
+
+ //
+ // Find the bus with ID == 0
+ //
+
+ pBus = HalpMpInfoTable.BusEntryPtr;
+ while (pBus->EntryType == ENTRY_BUS) {
+
+ if (pBus->BusId == 0) {
+
+ //
+ // If it's a PCI bus, assume physical bus IDs
+ //
+
+ if (pBus->BusType[0] != 'P' ||
+ pBus->BusType[1] != 'C' ||
+ pBus->BusType[2] != 'I' ||
+ pBus->BusType[3] != ' ' ||
+ pBus->BusType[4] != ' ' ||
+ pBus->BusType[5] != ' ' ) {
+
+ //
+ // Change default behaviour of PCI type
+ // from physical to virtual
+ //
+
+ pBusType->PhysicalInstance = FALSE;
+ }
+
+ break;
+ }
+
+ pBus += 1;
+ }
+}
+
+
+VOID
+HalpCheckELCR (
+ VOID
+ )
+{
+ USHORT elcr;
+ ULONG IsaIrq, Inti;
+
+ if (HalpELCRChecked) {
+ return ;
+ }
+
+ HalpELCRChecked = TRUE;
+
+
+ //
+ // It turns out interrupts which are fed through the ELCR before
+ // going to the IOAPIC get inverted. So... here we *assume*
+ // the polarity of any ELCR level vector not declared in the MPS linti
+ // table as being active_high instead of what they should be (which
+ // is active_low). Any system which correctly delivers these vectors
+ // to an IOAPIC will need to declared the correct polarity in the
+ // MPS table.
+ //
+
+ elcr = READ_PORT_UCHAR ((PUCHAR) 0x4d1) << 8 | READ_PORT_UCHAR((PUCHAR) 0x4d0);
+ if (elcr == 0xffff) {
+ return ;
+ }
+
+ for (IsaIrq = 0; elcr; IsaIrq++, elcr >>= 1) {
+ if (!(elcr & 1)) {
+ continue;
+ }
+
+ if (HalpGetPcMpInterruptDesc (Eisa, 0, IsaIrq, &Inti)) {
+
+ //
+ // If the MPS passed Polarity for this Inti
+ // is "bus default" change it to be "active high".
+ //
+
+ if (HalpIntiInfo[Inti].Polarity == 0) {
+ HalpIntiInfo[Inti].Polarity = 1;
+ }
+ }
+ }
+}
+
+VOID
+HalpInti2ApicInti (
+ ULONG InterruptInput,
+ PULONG ApicNo,
+ PULONG ApicInti
+ )
+/*++
+
+Routine Description:
+
+ Convert InterruptInput to ApicNo & ApicInti
+
+Arguments:
+
+ InterruptInput - internal value for interrupt
+
+ ApicNo - Apic InterruptInput is on
+ ApicInti - Apic Inti line InterruptInput is on
+
+Return Value:
+
+--*/
+{
+ ULONG IoUnit;
+
+ for (IoUnit=0; IoUnit < MAX_IOAPICS; IoUnit++) {
+ if (InterruptInput+1 <= HalpMaxApicInti[IoUnit]) {
+ break;
+ }
+ InterruptInput -= HalpMaxApicInti[IoUnit];
+ }
+
+ ASSERT (IoUnit < MAX_IOAPICS);
+
+ *ApicNo = IoUnit;
+ *ApicInti = InterruptInput;
+}
+
+
+
+BOOLEAN
+HalpGetPcMpInterruptDesc (
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ OUT PULONG PcMpInti
+ )
+/*++
+
+Routine Description:
+
+ This procedure gets a "Inti" describing the requested interrupt
+
+Arguments:
+
+ BusType - The Bus type as known to the IO subsystem
+
+ BusNumber - The number of the Bus we care for
+
+ BusInterruptLevel - IRQ on the Bus
+
+Return Value:
+
+ TRUE if PcMpInti found; otherwise FALSE.
+
+ PcMpInti - A number that describes the interrupt to the HAL.
+
+--*/
+{
+ ULONG i, id;
+
+ if (BusType < 16 && BusNumber < 256 && BusInterruptLevel < 256) {
+
+ //
+ // get unique BusType,BusNumber,BusInterrupt ID
+ //
+
+ id = BusIrq2Id(BusType, BusNumber, BusInterruptLevel);
+
+ //
+ // Search for ID of Bus Irq mapping, and return the corrisponding
+ // InterruptLine.
+ //
+
+ for (i=0; i < MAX_SOURCE_IRQS; i++) {
+ if (HalpSourceIrqIds[i] == id) {
+ *PcMpInti = HalpSourceIrqMapping[i];
+ return TRUE;
+ }
+ }
+ }
+
+ //
+ // Not found or search out of range
+ //
+
+ return FALSE;
+}
+
+
+STATIC VOID
+HalpSetRedirEntry (
+ IN UCHAR InterruptInput,
+ IN ULONG Entry,
+ IN ULONG Destination
+ )
+/*++
+
+Routine Description:
+
+ This procedure sets a IO Unit Redirection Table Entry
+
+Arguments:
+
+ IoUnit - The IO Unit to modify (zero Based)
+
+ InterruptInput - The input line we're interested in
+
+ Entry - the lower 32 bits of the redir table
+
+ Destination - the upper 32 bits on the entry
+
+Return Value:
+
+ None.
+
+--*/
+{
+ struct ApicIoUnit *IoUnitPtr;
+ ULONG RedirRegister;
+ UCHAR IoUnit;
+
+ for (IoUnit=0; IoUnit < MAX_IOAPICS; IoUnit++) {
+ if (InterruptInput+1 <= HalpMaxApicInti[IoUnit]) {
+ break;
+ }
+ InterruptInput -= HalpMaxApicInti[IoUnit];
+ }
+
+ ASSERT (IoUnit < MAX_IOAPICS);
+
+ IoUnitPtr = (struct ApicIoUnit *) HalpMpInfoTable.IoApicBase[IoUnit];
+
+ RedirRegister = InterruptInput*2 + IO_REDIR_00_LOW;
+
+ IoUnitPtr->RegisterSelect = RedirRegister+1;
+ IoUnitPtr->RegisterWindow = Destination;
+ IoUnitPtr->RegisterSelect = RedirRegister;
+ IoUnitPtr->RegisterWindow = Entry;
+
+}
+
+STATIC VOID
+HalpGetRedirEntry (
+ IN UCHAR InterruptInput,
+ IN PULONG Entry,
+ IN PULONG Destination
+ )
+/*++
+
+Routine Description:
+
+ This procedure sets a IO Unit Redirection Table Entry
+
+Arguments:
+
+ IoUnit - The IO Unit to modify (zero Based)
+
+ InterruptInput - The input line we're interested in
+
+ Entry - the lower 32 bits of the redir table
+
+ Destination - the upper 32 bits on the entry
+
+Return Value:
+
+ None.
+
+--*/
+{
+ struct ApicIoUnit *IoUnitPtr;
+ ULONG RedirRegister;
+ UCHAR IoUnit;
+
+ for (IoUnit=0; IoUnit < MAX_IOAPICS; IoUnit++) {
+ if (InterruptInput+1 <= HalpMaxApicInti[IoUnit]) {
+ break;
+ }
+ InterruptInput -= HalpMaxApicInti[IoUnit];
+ }
+
+ ASSERT (IoUnit < MAX_IOAPICS);
+
+ IoUnitPtr = (struct ApicIoUnit *) HalpMpInfoTable.IoApicBase[IoUnit];
+
+ RedirRegister = InterruptInput*2 + IO_REDIR_00_LOW;
+
+ IoUnitPtr->RegisterSelect = RedirRegister+1;
+ *Destination = IoUnitPtr->RegisterWindow;
+
+ IoUnitPtr->RegisterSelect = RedirRegister;
+ *Entry = IoUnitPtr->RegisterWindow;
+
+}
+
+
+STATIC VOID
+HalpEnableRedirEntry(
+ IN UCHAR InterruptInput,
+ IN ULONG Entry,
+ IN UCHAR Cpu
+ )
+/*++
+
+Routine Description:
+
+ This procedure enables an interrupt via IO Unit
+ Redirection Table Entry
+
+Arguments:
+
+ InterruptInput - The input line we're interested in
+
+ Entry - the lower 32 bits of the redir table
+
+ Destination - the upper 32 bits of the entry
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Destination;
+
+ //
+ // bump Enable Count for this INTI
+ //
+
+ HalpIntiInfo[InterruptInput].Destinations |= (1 << Cpu);
+ Destination = HalpIntiInfo[InterruptInput].Destinations;
+ Destination = (Destination << DESTINATION_SHIFT);
+
+ HalpSetRedirEntry (
+ InterruptInput,
+ Entry,
+ Destination
+ );
+
+}
+
+STATIC VOID
+HalpDisableRedirEntry(
+ IN UCHAR InterruptInput,
+ IN UCHAR Cpu
+ )
+/*++
+
+Routine Description:
+
+ This procedure disables a IO Unit Redirection Table Entry
+ by setting the mask bit in the Redir Entry.
+
+Arguments:
+
+ InterruptInput - The input line we're interested in
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Entry;
+ ULONG Destination;
+
+ //
+ // Turn of the Destination bit for this Cpu
+ //
+ HalpIntiInfo[InterruptInput].Destinations &= ~(1 << Cpu);
+
+ //
+ // Get the old entry, the only thing we want is the Entry field
+ //
+
+ HalpGetRedirEntry (
+ InterruptInput,
+ &Entry,
+ &Destination
+ );
+
+ //
+ // Only perform the disable if we've transitioned to zero enables
+ //
+ if ( HalpIntiInfo[InterruptInput].Destinations == 0) {
+ //
+ // Disable the interrupt if no Cpu has it enabled
+ //
+ Entry |= INTERRUPT_MASKED;
+
+ } else {
+ //
+ // Create the new destination field sans this Cpu
+ //
+ Destination = HalpIntiInfo[InterruptInput].Destinations;
+ Destination = (Destination << DESTINATION_SHIFT);
+ }
+
+ HalpSetRedirEntry (
+ InterruptInput,
+ Entry,
+ Destination
+ );
+}
+
+VOID
+HalpSet8259Mask (
+ IN USHORT Mask
+ )
+/*++
+
+Routine Description:
+
+ This procedure sets the 8259 Mask to the value passed in
+
+Arguments:
+
+ Mask - The mask bits to set
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _asm {
+ mov ax, Mask
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ }
+}
+
+#define PIC1_BASE 0x30
+
+STATIC VOID
+SetPicInterruptHandler(
+ IN UCHAR InterruptInput
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sets a handler for a PIC inti
+
+Arguments:
+
+ InterruptInput - The input line we're interested in
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ extern VOID (*PicExtintIntiHandlers[])(VOID);
+
+ VOID (*Hp)(VOID) = PicExtintIntiHandlers[InterruptInput];
+
+ KiSetHandlerAddressToIDT(PIC1_BASE + InterruptInput, Hp);
+}
+
+STATIC VOID
+ResetPicInterruptHandler(
+ IN UCHAR InterruptInput
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sets a handler for a PIC inti to a NOP handler
+
+Arguments:
+
+ InterruptInput - The input line we're interested in
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ extern VOID (*PicNopIntiHandlers[])(VOID);
+
+ VOID (*Hp)(VOID) = PicNopIntiHandlers[InterruptInput];
+
+ KiSetHandlerAddressToIDT(PIC1_BASE + InterruptInput, Hp);
+}
+
+STATIC VOID
+HalpEnablePicInti (
+ IN UCHAR InterruptInput
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure enables a PIC interrupt
+
+Arguments:
+
+ InterruptInput - The input line we're interested in
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT PicMask;
+
+ ASSERT(InterruptInput < 16);
+
+ //
+ // bump Enable Count for this INTI
+ //
+ Halp8259Counts[InterruptInput]++;
+
+ //
+ // Only actually perform the enable if we've transitioned
+ // from zero to one enables
+ //
+ if ( Halp8259Counts[InterruptInput] == 1) {
+
+ //
+ // Set the Interrupt Handler for PIC inti, this is
+ // the routine that fields the EXTINT vector and issues
+ // an APIC vector
+ //
+
+ SetPicInterruptHandler(InterruptInput);
+
+ PicMask = HalpGlobal8259Mask;
+ PicMask &= (USHORT) ~(1 << InterruptInput);
+ if (InterruptInput > 7)
+ PicMask &= (USHORT) ~(1 << PIC_SLAVE_IRQ);
+
+ HalpGlobal8259Mask = PicMask;
+ HalpSet8259Mask ((USHORT) PicMask);
+
+ }
+}
+
+STATIC VOID
+HalpDisablePicInti(
+ IN UCHAR InterruptInput
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure enables a PIC interrupt
+
+Arguments:
+
+ InterruptInput - The input line we're interested in
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT PicMask;
+
+ //
+ // decrement Enable Count for this INTI
+ //
+
+ Halp8259Counts[InterruptInput]--;
+
+ //
+ // Only disable if we have zero enables
+ //
+ if ( Halp8259Counts[InterruptInput] == 0) {
+
+ //
+ // Disable the Interrupt Handler for PIC inti
+ //
+
+ ResetPicInterruptHandler(InterruptInput);
+
+ PicMask = HalpGlobal8259Mask;
+ PicMask |= (1 << InterruptInput);
+ if (InterruptInput > 7) {
+ //
+ // This inti is on the slave, see if any other
+ // inti's are enabled. If none are then disable the
+ // slave
+ //
+ if ((PicMask & 0xff00) == 0xff00)
+ //
+ // All inti's on the slave are disabled
+ //
+ PicMask |= PIC_SLAVE_IRQ;
+ }
+
+ HalpSet8259Mask ((USHORT) PicMask);
+ HalpGlobal8259Mask = PicMask;
+
+ }
+}
+
+BOOLEAN
+HalEnableSystemInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure enables a system interrupt
+
+ Some early implementations using the 82489DX only allow a processor
+ to access the IO Unit on it's own 82489DX. Since we use a single IO
+ Unit (P0's) to distribute all interrupts, we have a problem when Pn
+ wants to enable an interrupt on these type of systems.
+
+ In order to get around this problem we can take advantage of the fact
+ that the kernel calls Enable/Disable on each processor which has a bit
+ set in the Affinity mask for the interrupt. Since we have only one IO
+ Unit in use and that Unit is addressable from P0 only, we must set the
+ P0 affinity bit for all interrupts. We can then ignore Enable/Disable
+ requests from processors other than P0 since we will always get called
+ for P0.
+
+ The right way to do this assuming a single IO Unit accessable to all
+ processors, would be to use global counters to determine if the
+ interrupt has not been enabled on the IO Unit. Then enable the IO Unit
+ when we transition from no processors to one processor that have the
+ interrupt enabled.
+
+Arguments:
+
+ Vector - vector of the interrupt to be enabled
+
+ Irql - interrupt level of the interrupt to be enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPCR pPCR;
+ UCHAR InterruptInput, ThisCpu, DevLevel;
+ ULONG Entry;
+ ULONG OldLevel;
+ INTI_INFO Inti;
+
+ Vector &= 0xff;
+ Irql &= 0xff;
+
+ if ( (InterruptInput = HalpVectorToINTI[Vector]) == 0xff ) {
+ //
+ // There is no external device associated with this interrupt
+ //
+
+ return(FALSE);
+ }
+
+ Inti = HalpIntiInfo[InterruptInput];
+
+ DevLevel = HalpDevLevel
+ [InterruptMode == LevelSensitive ? CFG_LEVEL : CFG_EDGE]
+ [Inti.Level];
+
+ if (DevLevel & CFG_ERROR) {
+ DBGMSG ("HAL: Warning device interrupt mode overridden\n");
+ }
+
+ //
+ // Block interrupts & synchronize until we're done
+ //
+
+ OldLevel = HalpAcquireHighLevelLock (&HalpAccountingLock);
+
+ pPCR = KeGetPcr();
+ ThisCpu = pPCR->Prcb->Number;
+
+ switch (Inti.Type) {
+
+ case INT_TYPE_INTR: {
+ //
+ // enable the interrupt in the I/O unit redirection table
+ //
+ switch (Vector) {
+ case APIC_CLOCK_VECTOR:
+ ASSERT(ThisCpu == 0);
+ Entry = APIC_CLOCK_VECTOR | DELIVER_FIXED | LOGICAL_DESTINATION;
+ break;
+ case NMI_VECTOR:
+ ASSERT (1);
+ return FALSE;
+ default:
+ Entry = Vector | DELIVER_LOW_PRIORITY | LOGICAL_DESTINATION;
+ break;
+ } // switch (Vector)
+
+ Entry |= CFG_TYPE(DevLevel) == CFG_EDGE ? EDGE_TRIGGERED : LEVEL_TRIGGERED;
+ Entry |= HalpDevPolarity[Inti.Polarity][CFG_TYPE(DevLevel)] ==
+ CFG_LOW ? ACTIVE_LOW : ACTIVE_HIGH;
+
+ HalpEnableRedirEntry (
+ InterruptInput,
+ Entry,
+ (UCHAR) ThisCpu
+ );
+
+ break;
+
+ } // case INT_TYPE_INTR:
+
+ case INT_TYPE_EXTINT: {
+ //
+ // This is an interrupt that uses the IO APIC to route PIC
+ // events. In this case the IO unit has to be enabled and
+ // the PIC must be enabled.
+ //
+
+ HalpEnableRedirEntry (
+ 0, // WARNING: kenr - assuming 0
+ DELIVER_EXTINT | LOGICAL_DESTINATION,
+ (UCHAR) ThisCpu
+ );
+ HalpEnablePicInti(InterruptInput);
+ break;
+ } // case INT_TYPE_EXTINT
+
+ default:
+ DBGMSG ("HalEnableSystemInterrupt: Unkown Inti Type\n");
+ break;
+ } // switch (IntiType)
+
+ HalpReleaseHighLevelLock (&HalpAccountingLock, OldLevel);
+ return TRUE;
+}
+
+
+VOID
+HalDisableSystemInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+
+Routine Description:
+
+ Disables a system interrupt.
+
+ Some early implementations using the 82489DX only allow a processor
+ to access the IO Unit on it's own 82489DX. Since we use a single IO
+ Unit (P0's) to distribute all interrupts, we have a problem when Pn
+ wants to enable an interrupt on these type of systems.
+
+ In order to get around this problem we can take advantage of the fact
+ that the kernel calls Enable/Disable on each processor which has a bit
+ set in the Affinity mask for the interrupt. Since we have only one IO
+ Unit in use and that Unit is addressable from P0 only, we must set the
+ P0 affinity bit for all interrupts. We can then ignore Enable/Disable
+ requests from processors other than P0 since we will always get called
+ for P0.
+
+ The right way to do this assuming a single IO Unit accessable to all
+ processors, would be to use global counters to determine if the
+ interrupt has not been enabled on the IO Unit. Then enable the IO Unit
+ when we transition from no processors to one processor that have the
+ interrupt enabled.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt to be disabled
+
+ Irql - Supplies the interrupt level of the interrupt to be disabled
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPCR pPCR;
+ UCHAR InterruptInput;
+ UCHAR ThisCpu;
+ ULONG OldLevel;
+
+ Vector &= 0xff;
+ Irql &= 0xff;
+
+ if ( (InterruptInput = HalpVectorToINTI[Vector]) == 0xff ) {
+ //
+ // There is no external device associated with this interrupt
+ //
+ return;
+ }
+
+ //
+ // Block interrupts & synchronize until we're done
+ //
+
+ OldLevel = HalpAcquireHighLevelLock (&HalpAccountingLock);
+
+ pPCR = KeGetPcr();
+ ThisCpu = pPCR->Prcb->Number;
+
+ switch (HalpIntiInfo[InterruptInput].Type) {
+
+ case INT_TYPE_INTR: {
+ //
+ // enable the interrupt in the I/O unit redirection table
+ //
+
+ HalpDisableRedirEntry( InterruptInput, ThisCpu );
+ break;
+
+ } // case INT_TYPE_INTR:
+
+ case INT_TYPE_EXTINT: {
+ //
+ // This is an interrupt that uses the IO APIC to route PIC
+ // events. In this case the IO unit has to be enabled and
+ // the PIC must be enabled.
+ //
+ //
+ // WARNING: The PIC is assumed to be routed only through
+ // IoApic[0]Inti[0]
+ //
+
+ HalpDisablePicInti(InterruptInput);
+ break;
+ }
+
+ default:
+ DBGMSG ("HalDisableSystemInterrupt: Unkown Inti Type\n");
+ break;
+
+ }
+
+
+ HalpReleaseHighLevelLock (&HalpAccountingLock, OldLevel);
+ return;
+
+}
+
+VOID
+HalpInitializeIOUnits (
+ VOID
+ )
+/*
+
+ Routine Description:
+
+ This routine initializes the IO APIC. It only programs the APIC ID Register.
+
+ HalEnableSystemInterrupt programs the Redirection table.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None.
+
+*/
+
+{
+ ULONG IoApicId;
+ struct ApicIoUnit *IoUnitPtr;
+ ULONG i, j, max;
+
+ for(i=0; i < HalpMpInfoTable.IOApicCount; i++) {
+
+ IoUnitPtr = (struct ApicIoUnit *) HalpMpInfoTable.IoApicBase[i];
+ //
+ // write the I/O unit APIC-ID - Since we are using the Processor
+ // Numbers for the local unit ID's we need to set the IO unit
+ // to a high (out of Processor Number range) value.
+ //
+ IoUnitPtr->RegisterSelect = IO_ID_REGISTER;
+ IoApicId = (ULONG) HalpMpInfoTable.IoApicEntryPtr[i].IoApicId;
+ IoUnitPtr->RegisterWindow = (IoApicId << APIC_ID_SHIFT);
+
+ //
+ // mask all vectors on the ioapic
+ //
+
+ IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
+ max = ((IoUnitPtr->RegisterWindow >> 16) & 0xff) * 2;
+ for (j=0; j <= max; j += 2) {
+ IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW + j;
+ IoUnitPtr->RegisterWindow |= INT_VECTOR_MASK | INTERRUPT_MASKED;
+ }
+ }
+
+ //
+ // Add resources consumed by APICs
+ //
+
+ ASSERT (MAX_IOAPICS == 8); // if this changes, fix HalpApicUsage
+ HalpApicUsage.Element[0].Start = HalpMpInfoTable.LocalApicBase;
+ for (i=0; i < HalpMpInfoTable.IOApicCount; i++) {
+ HalpApicUsage.Element[i+1].Start = (ULONG) HalpMpInfoTable.IoApicPhys[i];
+ }
+
+ HalpApicUsage.Element[i+1].Start = 0;
+ HalpApicUsage.Element[i+1].Length = 0;
+ HalpRegisterAddressUsage (&HalpApicUsage);
+}
+
+VOID
+HalpEnableNMI (
+ VOID
+ )
+/*
+
+ Routine Description:
+
+ Enable & connect NMI sources for the calling processor.
+
+*/
+{
+ PKPCR pPCR;
+ UCHAR InterruptInput;
+ UCHAR ThisCpu;
+ UCHAR LocalApicId;
+ PPCMPLINTI pEntry;
+ ULONG OldLevel;
+
+ OldLevel = HalpAcquireHighLevelLock (&HalpAccountingLock);
+
+ pPCR = KeGetPcr();
+ ThisCpu = pPCR->Prcb->Number;
+
+ //
+ // Enable local processor NMI source
+ //
+
+ LocalApicId = ((PHALPRCB)pPCR->Prcb->HalReserved)->PCMPApicID;
+
+ for (pEntry = HalpMpInfoTable.LintiEntryPtr;
+ pEntry->EntryType == ENTRY_LINTI;
+ pEntry++) {
+
+ if ( ( (pEntry->DestLocalApicId == LocalApicId) ||
+ (pEntry->DestLocalApicId == 0xff)) &&
+ (pEntry->IntType == INT_TYPE_NMI) ) {
+
+ //
+ // Found local NMI source, enable it
+ //
+
+ if (pEntry->DestLocalApicInti == 0) {
+ pLocalApic[LU_INT_VECTOR_0/4] = ( LEVEL_TRIGGERED |
+ ACTIVE_HIGH | DELIVER_NMI | NMI_VECTOR);
+ } else {
+ pLocalApic[LU_INT_VECTOR_1/4] = ( LEVEL_TRIGGERED |
+ ACTIVE_HIGH | DELIVER_NMI | NMI_VECTOR);
+ }
+ }
+ }
+
+ //
+ // Enable any NMI sources found on IOAPICs
+ //
+
+ for (InterruptInput=0; InterruptInput < MAX_INTI; InterruptInput++) {
+ if (HalpIntiInfo[InterruptInput].Type == INT_TYPE_NMI) {
+ HalpEnableRedirEntry (
+ InterruptInput,
+ NMI_VECTOR | DELIVER_NMI | LOGICAL_DESTINATION | LEVEL_TRIGGERED,
+ (UCHAR) ThisCpu
+ );
+ }
+ }
+
+ HalpReleaseHighLevelLock (&HalpAccountingLock, OldLevel);
+}
+
+VOID
+HalpEnablePerfInterupt (
+ ULONG Context
+ )
+{
+ //
+ // Enable local processor perf interrupt source
+ //
+
+ pLocalApic[LU_PERF_VECTOR/4] = (LEVEL_TRIGGERED | APIC_PERF_VECTOR |
+ DELIVER_FIXED | ACTIVE_LOW);
+}
+
+
+
+
+VOID
+HalpInitializeLocalUnit (
+ VOID
+ )
+/*
+
+ Routine Description:
+
+
+ This routine initializes the interrupt structures for the local unit
+ of the APIC. This procedure is called by HalInitializeProcessor and
+ is executed by each CPU.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None.
+
+*/
+{
+ PKPCR pPCR;
+ ULONG SavedFlags, LogicalId;
+
+ _asm {
+ pushfd
+ pop SavedFlags
+ cli
+ }
+
+ pPCR = KeGetPcr();
+
+ if (pPCR->Prcb->Number ==0) {
+ //
+ // enable APIC mode
+ //
+ // PC+MP Spec has a port defined (IMCR - Interrupt Mode Control
+ // Port) That is used to enable APIC mode. The APIC could already
+ // be enabled, but per the spec this is safe.
+ //
+
+ if (HalpMpInfoTable.IMCRPresent)
+ {
+ _asm {
+ mov al, ImcrPort
+ out ImcrRegPortAddr, al
+
+ mov al, ImcrEnableApic
+ out ImcrDataPortAddr, al
+ }
+ }
+ }
+
+
+ //
+ // Program the TPR to mask all events
+ //
+ pLocalApic[LU_TPR/4] = 0xff;
+
+ pLocalApic[LU_DEST_FORMAT/4] = LU_DEST_FORMAT_FLAT; // write dest format register
+
+ //
+ // We need to set the logical APIC ID, we use the CPU number for logical id
+ // so there is no translation needed for OS addressing of CPUs
+ //
+
+ LogicalId = (ULONG) (1 << pPCR->Prcb->Number);
+
+ //
+ // At this point the Logical ID is a bit map of the processor number
+ // the actual ID is the upper byte of the logical destination register
+ // Note that this is not strictly true of 82489's. The 82489 has 32 bits
+ // available for the logical ID, but since we want software compatability
+ // between the two types of APICs we'll only use the upper byte.
+ //
+ // Shift the mask into the ID field and write it.
+ //
+ LogicalId = (ULONG) (LogicalId << DESTINATION_SHIFT);
+ pLocalApic[LU_LOGICAL_DEST/4] = LogicalId;
+
+ //
+ // Initilize spurious interrupt handling
+ //
+ KiSetHandlerAddressToIDT(APIC_SPURIOUS_VECTOR, HalpApicSpuriousService);
+ pLocalApic[LU_SPURIOUS_VECTOR/4] = (APIC_SPURIOUS_VECTOR | LU_UNIT_ENABLED);
+
+ if (HalpMpInfoTable.ApicVersion != APIC_82489DX) {
+ //
+ // Initilize Local Apic Fault handling
+ //
+ KiSetHandlerAddressToIDT(APIC_FAULT_VECTOR, HalpLocalApicErrorService);
+ pLocalApic[LU_FAULT_VECTOR/4] = APIC_FAULT_VECTOR;
+ }
+
+ //
+ // Disable APIC Timer Vector, will be enabled later if needed
+ // We have to program a valid vector otherwise we get an APIC
+ // error.
+ //
+ pLocalApic[LU_TIMER_VECTOR/4] = (APIC_PROFILE_VECTOR |PERIODIC_TIMER | INTERRUPT_MASKED);
+
+ //
+ // Disable APIC PERF Vector, will be enabled later if needed.
+ // We have to program a valid vector otherwise we get an APIC
+ // error.
+ //
+ pLocalApic[LU_PERF_VECTOR/4] = (APIC_PERF_VECTOR | INTERRUPT_MASKED);
+
+ //
+ // Disable LINT0, if we were in Virtual Wire mode then this will
+ // have been enabled on the BSP, it may be enabled later by the
+ // EnableSystemInterrupt code
+ //
+ pLocalApic[LU_INT_VECTOR_0/4] = (APIC_SPURIOUS_VECTOR | INTERRUPT_MASKED);
+
+ //
+ // Program NMI Handling, it will be enabled on P0 only
+ // RLM Enable System Interrupt should do this
+ //
+
+ pLocalApic[LU_INT_VECTOR_1/4] = ( LEVEL_TRIGGERED | ACTIVE_HIGH | DELIVER_NMI |
+ INTERRUPT_MASKED | ACTIVE_HIGH | NMI_VECTOR);
+
+ //
+ // Synchronize Apic IDs - InitDeassertCommand is sent to all APIC
+ // local units to force synchronization of arbitration-IDs with APIC-IDs.
+ //
+ // NOTE: we don't have to worry about synchronizing access to the ICR
+ // at this point.
+ //
+
+ pLocalApic[LU_INT_CMD_LOW/4] = (DELIVER_INIT | LEVEL_TRIGGERED |
+ ICR_ALL_INCL_SELF | ICR_LEVEL_DEASSERTED);
+
+ //
+ // we're done - set TPR to a high value and return
+ //
+ pLocalApic[LU_TPR/4] = ZERO_VECTOR;
+
+ _asm {
+ push SavedFlags
+ popfd
+ }
+}
diff --git a/private/ntos/nthals/halmps/i386/mpsysbus.c b/private/ntos/nthals/halmps/i386/mpsysbus.c
new file mode 100644
index 000000000..df69d79dd
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpsysbus.c
@@ -0,0 +1,341 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ mpsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "apic.inc"
+#include "pcmp_nt.inc"
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG InterruptLevel,
+ IN ULONG InterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+extern UCHAR HalpVectorToIRQL[];
+extern UCHAR HalpIRQLtoTPR[];
+extern UCHAR HalpVectorToINTI[];
+extern KSPIN_LOCK HalpAccountingLock;
+
+UCHAR HalpINTItoVector[16*4];
+UCHAR HalpPICINTToVector[16];
+ULONG HalpDefaultInterruptAffinity;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpSetInternalVector)
+#pragma alloc_text(PAGELK,HalpGetSystemInterruptVector)
+#endif
+
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN status;
+ PSUPPORTED_RANGE pRange;
+
+ status = FALSE;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ pRange = &BusHandler->BusAddresses->Memory;
+ while (!status && pRange) {
+ status = BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit;
+ pRange = pRange->Next;
+ }
+
+ pRange = &BusHandler->BusAddresses->PrefetchMemory;
+ while (!status && pRange) {
+ status = BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit;
+
+ pRange = pRange->Next;
+ }
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ pRange = &BusHandler->BusAddresses->IO;
+ while (!status && pRange) {
+ status = BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit;
+
+ pRange = pRange->Next;
+ }
+ break;
+
+ default:
+ status = FALSE;
+ break;
+ }
+
+ if (status) {
+ *TranslatedAddress = BusAddress;
+ } else {
+ _asm { nop }; // good for debugging
+ }
+
+ return status;
+}
+
+
+#define MAX_SYSTEM_IRQL 31
+#define MAX_FREE_IRQL 26
+#define MIN_FREE_IRQL 4
+#define MAX_FREE_VECTOR 0xbf
+#define MIN_FREE_VECTOR 0x51
+#define VECTOR_BASE 0x50
+#define MAX_VBUCKET 7
+
+#define AllocateVectorIn(index) \
+ vBucket[index]++; \
+ ASSERT (vBucket[index] < 16);
+
+#define GetVectorFrom(index) \
+ (ULONG) ( index*16 + VECTOR_BASE + vBucket[index] )
+ // note: device levels 50,60,70,80,90,A0,B0 are not allocatable
+
+#define GetIrqlFrom(index) (KIRQL) ( index + MIN_FREE_IRQL )
+
+UCHAR vBucket[MAX_VBUCKET];
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG InterruptLevel,
+ IN ULONG InterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL
+ corresponding to the specified bus interrupt level and/or
+ vector. The system interrupt vector and IRQL are suitable
+ for use in a subsequent call to KeInitializeInterrupt.
+
+Arguments:
+
+ InterruptLevel - Supplies the bus specific interrupt level.
+
+ InterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector, ApicInti;
+ ULONG Bucket, i, OldLevel;
+ BOOLEAN Found;
+ PVOID LockHandle;
+
+
+ UNREFERENCED_PARAMETER( InterruptVector );
+
+ //
+ // Find closest child bus to this handler
+ //
+
+ if (RootHandler != BusHandler) {
+ while (RootHandler->ParentHandler != BusHandler) {
+ RootHandler = RootHandler->ParentHandler;
+ }
+ }
+
+ //
+ // Find Interrupt's APIC Inti connection
+ //
+
+ Found = HalpGetPcMpInterruptDesc (
+ RootHandler->InterfaceType,
+ RootHandler->BusNumber,
+ InterruptLevel,
+ &ApicInti
+ );
+
+ if (!Found) {
+ return 0;
+ }
+
+ //
+ // On Symetric MP systems the interrupt affinity is all processors.
+ //
+
+ *Affinity = HalpDefaultInterruptAffinity;
+
+ //
+ // If device interrupt vector mapping is not already allocated,
+ // then do it now
+ //
+
+ if (!HalpINTItoVector[ApicInti]) {
+
+ //
+ // Vector is not allocated - synchronize and check again
+ //
+
+ LockHandle = MmLockPagableCodeSection (&HalpGetSystemInterruptVector);
+ OldLevel = HalpAcquireHighLevelLock (&HalpAccountingLock);
+ if (!HalpINTItoVector[ApicInti]) {
+
+ //
+ // Still not allocated, Dynamically allocate a vector
+ //
+
+ Bucket = MAX_VBUCKET-1;
+ for (i = MAX_VBUCKET-1; i; i--) {
+ if (vBucket[i-1] < vBucket[Bucket]) {
+ Bucket = i-1;
+ }
+ }
+
+ AllocateVectorIn (Bucket);
+ SystemVector = GetVectorFrom (Bucket);
+ *Irql = GetIrqlFrom (Bucket);
+
+ ASSERT(*Irql <= MAX_FREE_IRQL);
+ ASSERT(SystemVector <= MAX_FREE_VECTOR);
+ ASSERT(SystemVector >= MIN_FREE_VECTOR);
+ ASSERT((UCHAR) (HalpIRQLtoTPR[*Irql] & 0xf0) == (UCHAR) (SystemVector & 0xf0) );
+
+ HalpVectorToIRQL[SystemVector >> 4] = (UCHAR) *Irql;
+ HalpVectorToINTI[SystemVector] = (UCHAR) ApicInti;
+ HalpINTItoVector[ApicInti] = (UCHAR) SystemVector;
+
+ //
+ // If this assigned interrupt is connected to the machines PIC,
+ // then remember the PIC->SystemVector mapping.
+ //
+
+ if (RootHandler->BusNumber == 0 && InterruptLevel < 16 &&
+ RootHandler->InterfaceType == DEFAULT_PC_BUS) {
+ HalpPICINTToVector[InterruptLevel] = (UCHAR) SystemVector;
+ }
+
+ }
+
+ HalpReleaseHighLevelLock (&HalpAccountingLock, OldLevel);
+ MmUnlockPagableImageSection (LockHandle);
+ }
+
+ //
+ // Return this ApicInti's system vector & irql
+
+ SystemVector = HalpINTItoVector[ApicInti];
+ *Irql = HalpVectorToIRQL[SystemVector >> 4];
+
+ ASSERT(HalpVectorToINTI[SystemVector] == (UCHAR) ApicInti);
+ ASSERT(*Affinity);
+
+ return SystemVector;
+}
+
+VOID
+HalpSetInternalVector (
+ IN ULONG InternalVector,
+ IN VOID (*HalInterruptServiceRoutine)(VOID)
+ )
+/*++
+
+Routine Description:
+
+ Used at init time to set IDT vectors for internal use.
+
+--*/
+{
+ //
+ // Remember this vector so it's reported as Hal internal usage
+ //
+
+ HalpRegisterVector (
+ InternalUsage,
+ InternalVector,
+ InternalVector,
+ HalpVectorToIRQL[InternalVector >> 4]
+ );
+
+ //
+ // Connect the IDT
+ //
+
+ KiSetHandlerAddressToIDT(InternalVector, HalInterruptServiceRoutine);
+}
diff --git a/private/ntos/nthals/halmps/i386/mpsysint.asm b/private/ntos/nthals/halmps/i386/mpsysint.asm
new file mode 100644
index 000000000..e508f628a
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/mpsysint.asm
@@ -0,0 +1,244 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;Copyright (c) 1992 Intel Corporation
+;All rights reserved
+;
+;INTEL CORPORATION PROPRIETARY INFORMATION
+;
+;This software is supplied to Microsoft under the terms
+;of a license agreement with Intel Corporation and may not be
+;copied nor disclosed except in accordance with the terms
+;of that agreement.
+;
+;
+;Module Name:
+;
+; mpsysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to begin/end
+; system interrupts for a PC+MP implementation
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+; Ron Mosgrove (Intel) Aug 1993
+; Modified for PC+MP Systems
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\pcmp_nt.inc
+ .list
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+ extrn _HalpVectorToIRQL:byte
+ extrn _HalpIRQLtoTPR:byte
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "End System Interrupt"
+;++
+;
+; VOID
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+12 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HeiNewIrql equ [esp + 4]
+HeiVector equ [esp + 8]
+
+cPublicProc _HalEndSystemInterrupt ,2
+cPublicFpo 2, 0
+ xor ecx,ecx
+ mov cl, byte ptr HeiNewIrql ; get new IRQL
+ mov cl, _HalpIRQLtoTPR[ecx] ; get corresponding TPR value
+
+ mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
+ APICFIX edx
+
+ cmp cl, DPC_VECTOR ; Is new irql < DPC?
+ jc short es10 ; Yes, go check for pending DPC
+
+es05: mov dword ptr APIC[LU_TPR], ecx ; Vector == Priority
+
+;
+; We have to ensure that the requested priority is set before
+; we return. The caller is counting on it.
+;
+ mov edx, dword ptr APIC[LU_TPR]
+ CHECKTPR ecx, edx
+ stdRET _HalEndSystemInterrupt
+
+es10: cmp PCR[PcHal.DpcPending], 0 ; Is a DPC pending?
+ mov PCR[PcHal.ShortDpc], 0 ; Clear short dpc flag
+ jz short es05 ; No, eoi
+
+ mov dword ptr APIC[LU_TPR], DPC_VECTOR ; lower to DPC level
+ APICFIX edx
+
+ push ebx ; Save EBX (used by KiDispatchInterrupt)
+ push ecx ; Save OldIrql
+cPublicFpo 2, 2
+
+ sti
+
+es20: mov PCR[PcHal.DpcPending], 0 ; Clear pending flag
+
+ stdCall _KiDispatchInterrupt ; Dispatch interrupt
+
+ cli
+
+ pop ecx
+ pop ebx
+ jmp short es05
+
+stdENDP _HalEndSystemInterrupt
+
+
+;++
+;
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;Routine Description:
+;
+; This routine raises the IRQL to the level of the specified
+; interrupt vector. It is called by the hardware interrupt
+; handler before any other interrupt service routine code is
+; executed. The CPU interrupt flag is set on exit.
+;
+; On APIC-based systems we do not need to check for spurious
+; interrupts since they now have their own vector. We also
+; no longer need to check whether or not the incoming priority
+; is higher than the current priority that is guaranteed by
+; the priority mechanism of the APIC.
+;
+; SO
+;
+; All BeginSystemInterrupt needs to do is set the APIC TPR
+; appropriate for the IRQL, and return TRUE. Note that to
+; use the APIC ISR priority we are not going issue EOI until
+; EndSystemInterrupt is called.
+;
+; Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be
+; dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+; Return Value:
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+; This routine can not fail.
+;
+;--
+
+
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+cPublicFpo 3, 0
+
+ xor eax, eax
+ mov al, HbsiIrql ; (eax) = New Vector
+ mov al, _HalpIRQLtoTPR[eax] ; get corresponding TPR value
+
+ ;
+ ; Read the TPR for the Priority (Vector) in use,
+ ; and convert it to an IRQL
+ ;
+
+ mov ecx, dword ptr APIC[LU_TPR] ; Get the Priority
+ mov dword ptr APIC[LU_TPR], eax
+ APICFIX edx
+
+ mov eax, HbsiOldIrql ; return the current IRQL as OldIrql
+ shr ecx, 4
+ mov cl, byte ptr _HalpVectorToIRQL[ecx]
+
+ mov byte ptr [eax], cl
+ mov eax, 1 ; return TRUE
+ sti
+
+ ;
+ ; If OldIrql < DISPATCH_LEVEL and new irql >= DISPATCH_LEVEL (which
+ ; is assumed), then set
+ ;
+
+ cmp cl, DISPATCH_LEVEL
+ jnc short bs10
+
+if DBG
+ cmp PCR[PcHal.ShortDpc], 0
+ je short @f
+ int 3
+@@:
+endif
+ mov PCR[PcHal.ShortDpc], DISPATCH_LEVEL
+
+bs10:
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halmps/i386/pcip.h b/private/ntos/nthals/halmps/i386/pcip.h
new file mode 100644
index 000000000..0d5877d4a
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/pcip.h
@@ -0,0 +1,7 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#define SUBCLASSPCI 1
+
+#include "..\..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/halmps/i386/pcmp.inc b/private/ntos/nthals/halmps/i386/pcmp.inc
new file mode 100644
index 000000000..88b8b874d
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/pcmp.inc
@@ -0,0 +1,465 @@
+;/*
+;++
+;
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+;
+; Module Name:
+;
+; pcmp.inc
+;
+; Abstract:
+;
+; include file for PC+MP system.
+;
+; WARNING: This file is included by both ASM and C files.
+;
+; Author:
+;
+; Ron Mosgrove and Rajesh Shah (Intel) 30-July-1993
+;
+;--
+;
+
+if 0 ; Begin C only code */
+
+#pragma pack(1)
+
+//
+// IMCR (Interrupt Mode Control Register) access definitions
+//
+#define ImcrDisableApic 0x00
+#define ImcrEnableApic 0x01
+#define ImcrRegPortAddr 0x22
+#define ImcrDataPortAddr 0x23
+#define ImcrPort 0x70
+
+// Physical location where the Extended BIOS Data Area segment adress is stored
+#define EBDA_SEGMENT_PTR 0x40e
+#define BASE_MEM_PTR 0x413
+
+//
+// Default Physical addresses of the APICs in a PC+MP system
+//
+
+#define IO_BASE_ADDRESS 0xFEC00000 // Default address of
+ // 1st IO Apic
+#define LU_BASE_ADDRESS 0xFEE00000 // Default address
+ // of Local Apic
+//
+// The PC+MP configuration table Possible Entry Types
+//
+#define ENTRY_PROCESSOR 0
+#define ENTRY_BUS 1
+#define ENTRY_IOAPIC 2
+#define ENTRY_INTI 3
+#define ENTRY_LINTI 4
+
+#define HEADER_SIZE 0x2c
+
+// Number of default configurations for PC+MP version 1.1
+#define NUM_DEFAULT_CONFIGS 7
+
+//
+// Processor Entry definitions
+//
+
+typedef struct _CPUIDENTIFIER {
+ ULONG Stepping : 4;
+ ULONG Model : 4;
+ ULONG Family : 4;
+ ULONG Reserved : 20;
+} CPUIDENTIFIER, *PCPUIDENTIFIER;
+
+//
+// Bits used in the CpuFlags field of the Processor entry
+//
+#define CPU_DISABLED 0x0 // 1 Bit - CPU Disabled
+#define CPU_ENABLED 0x1 // 1 Bit - CPU Enabled
+#define BSP_CPU 0x2 // Bit #2 - CPU is BSP
+
+//
+// APIC Versions used by PC+MP systems - this is used in the
+// Processor entries and the IoApic Entries
+//
+#define APIC_INTEGRATED 0x10 // 8 Bits-Apic Version Register
+#define APIC_82489DX 0x0 // 8 Bits-Apic Version Register
+
+typedef struct _PcMpProcessorEntry {
+ UCHAR EntryType;
+ UCHAR LocalApicId;
+ UCHAR LocalApicVersion;
+ UCHAR CpuFlags;
+ CPUIDENTIFIER CpuIdentification; // CPU Identification
+ ULONG FeatureFlags;
+ UCHAR Reserved[8];
+} PCMPPROCESSOR , *PPCMPPROCESSOR;
+
+//
+// Bus Entry definitions
+//
+
+typedef struct _PcMpBusEntry {
+ UCHAR EntryType;
+ UCHAR BusId;
+ CHAR BusType[6];
+} PCMPBUS, *PPCMPBUS;
+
+//
+// Io Apic Entry definitions
+//
+// Valid IoApicFlag values
+//
+#define IO_APIC_ENABLED 0x1
+#define IO_APIC_DISABLED 0x0
+
+//
+// Default value for Io Apic ID.
+//
+#define IOUNIT_APIC_ID 0xE
+
+typedef struct _PcMpIoApicEntry {
+ UCHAR EntryType;
+ UCHAR IoApicId;
+ UCHAR IoApicVersion;
+ UCHAR IoApicFlag;
+ PVOID IoApicAddress;
+} PCMPIOAPIC, *PPCMPIOAPIC;
+
+//
+// Io Apic Entry definitions
+//
+// Interrupt Types Possible in the PC+MP Table
+// valid for both local and Io Apics
+//
+#define INT_TYPE_INTR 0x0
+#define INT_TYPE_NMI 0x1
+#define INT_TYPE_SMI 0x2
+#define INT_TYPE_EXTINT 0x3
+
+//
+// Bits that define the Interrupt logically
+//
+typedef struct _PolarityAndLevel {
+ USHORT Polarity : 2;
+ USHORT Level : 2;
+ USHORT Reserved : 12;
+} POLARITYANDLEVEL, *PPOLARITYANDLEVEL;
+
+typedef struct _PcMpApicIntiEntry {
+ UCHAR EntryType;
+ UCHAR IntType;
+ POLARITYANDLEVEL Signal;
+ UCHAR SourceBusId;
+ UCHAR SourceBusIrq;
+ UCHAR IoApicId;
+ UCHAR IoApicInti;
+} PCMPINTI, *PPCMPINTI;
+
+//
+// Local Apic Interrupt Entry definitions
+//
+typedef struct _PcMpLintiEntry {
+ UCHAR EntryType;
+ UCHAR IntType;
+ POLARITYANDLEVEL Signal;
+ UCHAR SourceBusId;
+ UCHAR SourceBusIrq;
+ UCHAR DestLocalApicId;
+ UCHAR DestLocalApicInti;
+} PCMPLINTI, *PPCMPLINTI;
+
+//
+// The PC+MP table definition
+//
+
+struct PcMpTable {
+ //
+ // PC+MP config table HEADER part (HEADER_SIZE bytes long)
+ //
+
+ ULONG Signature; // Must contain "P","C","M","P"
+ USHORT TableLength; // Length including the header
+ UCHAR Revision; // Rev 1.0 == 1
+ UCHAR Checksum; // Entire table including checksum byte
+ CHAR OemId[8]; // OEM defined
+ CHAR OemProductId[12]; // OEM defined
+ PVOID OemTablePtr; // OEM specific data
+ USHORT OemTableSize; // length in bytes of the OEM table
+ USHORT NumOfEntries; // Number of entries in the data portion
+ PVOID LocalApicAddress; // Physical address of Local units
+ USHORT ExtTableLength; // Extension table size
+ UCHAR ExtTableChecksum; // Complete checksum including extension table
+ UCHAR Reserved; // Not Used
+};
+
+//
+// PC+MP Signature used to verify the PC+MP table
+// as valid
+//
+// "P"=50H,"C"=43H,"M"=4dH,"P"=50H
+//
+#define PCMP_SIGNATURE 0x504d4350
+
+//
+// PC+MP Signature used to identify the floating pointer
+// structure (in extended BIOS data segment) that contains
+// a pointer to the PC+MP table.
+//
+// "_"=5fH, "M"=4dH, "P"=50H, "_"=5fH
+//
+#define MP_PTR_SIGNATURE 0x5f504d5f
+
+//
+// This is the floating pointer structure
+//
+
+// For PC+MP version 1.0
+struct PcMpTableLocator {
+ ULONG MpPtrSignature; // Must be "_MP_" (0x5f504d5f)
+ PUCHAR TablePtr; // ptr to the PC+MP Table
+ UCHAR MpTableLength; // Floating pointer structure length
+ UCHAR TableRevision; // Rev 1.0 == 1
+ UCHAR TableChecksum; // Checksum of PcMpTableLocator
+ UCHAR Pad;
+ ULONG Reserved;
+};
+
+
+struct FloatPtrStruct {
+ ULONG MpPtrSignature; // Must be "_MP_" (0x5f504d5f)
+ PUCHAR TablePtr; // ptr to the PC+MP Table
+ UCHAR MpTableLength; // Floating pointer structure length
+ UCHAR TableRevision; // Rev 1.0 == 1
+ UCHAR TableChecksum; // Checksum of PcMpTableLocator
+ UCHAR MpFeatureInfoByte1; // MP feature info. byte 1
+ UCHAR MpFeatureInfoByte2; // MP feature info. byte 2
+ UCHAR Pad;
+ USHORT Reserved;
+};
+
+
+//
+// Extension table definitions
+//
+
+#define EXTTYPE_BUS_ADDRESS_MAP 128
+#define EXTTYPE_BUS_HIERARCHY 129
+#define EXTTYPE_BUS_COMPATIBLE_MAP 130
+#define EXTTYPE_PERSISTENT_STORE 131
+
+typedef struct {
+ UCHAR Type;
+ UCHAR Length;
+ union {
+ struct {
+ UCHAR BusId;
+ UCHAR Type;
+ LONGLONG Base;
+ LONGLONG Length;
+ } AddressMap;
+
+ struct {
+ UCHAR BusId;
+ UCHAR SubtractiveDecode:1;
+ UCHAR ParentBusId;
+ } BusHierarchy;
+
+ struct {
+ LONGLONG Address;
+ LONGLONG Length;
+ } PersistentStore;
+
+ struct {
+ UCHAR BusId;
+ UCHAR Modifier:1;
+ UCHAR Reserved:7;
+ ULONG List;
+ } CompatibleMap;
+
+ } u;
+} MPS_EXTENTRY, *PMPS_EXTENTRY;
+
+
+#define MPS_ADDRESS_MAP_IO 0
+#define MPS_ADDRESS_MAP_MEMORY 1
+#define MPS_ADDRESS_MAP_PREFETCH_MEMORY 2
+#define MPS_ADDRESS_MAP_UNDEFINED 9
+
+//
+// The System configuration table as used by a PC_MP system
+//
+//
+// The offset is relative to the BIOS starting at f0000H
+//
+#define PTR_OFFSET 0x0000e6f5
+#define BIOS_BASE 0x000f0000
+
+#define PCMP_IMPLEMENTED 0x01 // In MpFeatureInfoByte1
+#define PCMP_CONFIG_MASK 0x0e // In MpFeatureInfoByte1
+#define IMCR_MASK 0x80 // In MpFeatureInfoByte2
+
+struct SystemConfigTable {
+ UCHAR Reserved[PTR_OFFSET];
+ USHORT NumOfBytes; // Table can be variable length.
+ UCHAR ModelType; // AT=0xfc, unknown board=0xff
+ UCHAR SubModelType;
+ UCHAR BIOSRevision; // First release = 0x0
+ UCHAR FeatureInfoByte[3]; // Standard AT features
+ UCHAR MpFeatureInfoByte1; // MP feature info. byte 1
+ UCHAR MpFeatureInfoByte2; // MP feature info. byte 2
+} ;
+
+#pragma pack()
+
+/*
+endif
+
+;
+; IMCR (Interrupt Mode Control Register) access definitions
+;
+
+ImcrDisableApic equ 00H
+ImcrEnableApic equ 01H
+ImcrRegPortAddr equ 22H
+ImcrDataPortAddr equ 23H
+ImcrPort equ 70H
+
+;
+; Default Physical addresses of the APICs in a PC+MP system
+;
+
+IO_BASE_ADDRESS equ 0FEC00000H ; Default address of
+ ; 1st IO Apic
+LU_BASE_ADDRESS equ 0FEE00000H ; Default address
+ ; of Local Apic
+
+;
+; MP Configuration Table - Built by an MP BIOS for OS Support
+
+;
+; PC+MP Signature used to identify the floating pointer
+; structure (in extended BIOS data segment) that contains
+; a pointer to the PC+MP table.
+;
+; "_"=5fH, "M"=4dH, "P"=50H, "_"=5fH
+;
+MP_PTR_SIGNATURE equ 5f504d5fH
+
+;
+; PC+MP Signature used to verify the PC+MP table
+; as valid
+;
+; "P"=50H,"C"=43H,"M"=4dH,"P"=50H
+;
+PCMP_SIGNATURE equ 504d4350H
+
+;
+; The PC+MP configuration table Possible Entry Types
+;
+ENTRY_PROCESSOR equ 0H
+ENTRY_BUS equ 1H
+ENTRY_IOAPIC equ 2H
+ENTRY_INTI equ 3H
+ENTRY_LINTI equ 4H
+
+;
+; Bits used in the CpuFlags field of the Processor entry
+;
+CPU_ENABLED equ 01H
+CPU_DISABLED equ 00H
+BSP_CPU equ 02H
+
+;
+; Interrupt Types Possible in the PC+MP Table
+;
+INT_TYPE_INTR equ 0H
+INT_TYPE_NMI equ 01H
+INT_TYPE_SMI equ 02H
+INT_TYPE_EXTINT equ 03H
+
+;
+; APIC Versions used by PC+MP systems - this is used in the
+; Processor entries and the IoApic Entries
+;
+APIC_INTEGRATED equ 10H
+APIC_82489DX equ 00H
+
+
+;
+; Macros used in table definitions
+;
+HEADER_SIZE equ 2CH
+
+; Number of default configurations for PC+MP version 1.1
+NUM_DEFAULT_CONFIGS equ 7
+
+;
+; Io Apic Entry definitions
+;
+IO_APIC_ENABLED equ 01H
+IO_APIC_DISABLED equ 00H
+
+;
+; Default value for Io Apic ID.
+;
+IOUNIT_APIC_ID equ 0EH ; ID of the IO Unit
+
+PcMpTable struc
+ ; HEADER portion of the PC+MP config table
+ ;
+ Signature db 4 dup (0) ; Must be "P","C","M","P"
+ TableLength dw 0 ; Length in bytes of table
+ Revision db 0 ; Table revision #
+ Checksum db 0 ; Table checksum
+ OemId db 8 dup (0) ; OemId string
+ OemProductId db 12 dup (0) ; Oem product id
+ OemTablePtr dd 0 ; Ptr to OEM table
+ OemTableSize dw 0 ; Size of OEM table
+ NumOfEntries dw 0 ; # of entries in table
+
+PcMpTable ends
+
+;
+; Bios Constants. The offset is relative to the BIOS starting at
+; f0000H.
+;
+
+PTR_OFFSET equ 0e6f5H
+BIOS_BASE equ 0f0000H
+PCMP_IMPLEMENTED equ 01H
+PCMP_CONFIG_MASK equ 0eH
+IMCR_MASK equ 80H
+
+PcMpTableLocator struc
+ MpPtrSignature dd 0 ; Must be "_MP_" (0x5f504d5f)
+ TablePtr dd 0
+ MpTableLength db 0
+ TableRevision db 0
+ TableChecksum db 0
+ Pad db 0
+ Reserved dd 0
+PcMpTableLocator ends
+
+SystemConfigTable struc
+
+ db PTR_OFFSET dup (0) ;Skip to 0e6f5
+NumOfBytes db 2 ; Table Length
+ModelType db 0 ; AT=0fc, unknown=0ff
+SubModelType db 0
+BIOSRevision db 0 ; 00=first release
+FeatureInfoByte db 3 dup (0) ; AT features
+MpFeatureInfoByte1 db 0 ; MP feature info. byte 1
+MpFeatureInfoByte2 db 0 ; MP feature info. byte 2
+
+SystemConfigTable ends
+
+; */
diff --git a/private/ntos/nthals/halmps/i386/pcmp_nt.inc b/private/ntos/nthals/halmps/i386/pcmp_nt.inc
new file mode 100644
index 000000000..46c96cdc7
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/pcmp_nt.inc
@@ -0,0 +1,560 @@
+;/*
+;++
+;
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+;
+; Module Name:
+;
+; pcmp_nt.inc
+;
+; Abstract:
+;
+; include file for PC+MP system.
+;
+; WARNING: This file is included by both ASM and C files.
+;
+; Author:
+;
+; Ron Mosgrove (Intel) 30-July-1993
+;
+;--
+;
+
+if 0 ; Begin C only code */
+
+#include "pcmp.inc"
+
+//#define DEBUGGING 1
+
+#ifdef DEBUGGING
+extern CHAR Cbuf[];
+#endif
+
+//
+// To allow the user to specify command line options to the HAL.
+//
+#define USER_SETABLE_OPTIONS
+// #define BUILD_FOR_OLD_IDW
+
+//
+// Default BusType
+//
+
+#ifndef MCA
+#define DEFAULT_PC_BUS Eisa
+#else
+#define DEFAULT_PC_BUS MicroChannel
+#endif
+
+
+//
+// Well known virtual address of local processor apic
+//
+
+#define LOCALAPIC 0xfffe0000
+#define pLocalApic ((volatile PULONG) LOCALAPIC)
+
+//
+// Additional CpuFlags Bits used by NT in PC+MP Table
+//
+#define CPU_NT_STARTED 0x40 // CPU Has Been Started
+#define CPU_NT_RUNNING 0x80 // CPU is Runing NT
+#define MAX_PROCESSORS 8
+#define MAX_IOAPICS 8
+
+//
+// This OS specific structure holds useful MP information. This information
+// is obtained from the PC+MP table and stored here for convenience.
+//
+typedef struct HalpMpInfo {
+ ULONG ApicVersion; // 82489Dx or Not
+ ULONG ProcessorCount; // Number of Enabled Processors
+ ULONG NtProcessors; // Number of Running Processors
+ ULONG BusCount; // Number of buses in system
+ ULONG IOApicCount; // Number of Io Apics in system
+ ULONG IntiCount; // Number of Io Apic interrupt input entries
+ ULONG LintiCount; // Number of Local Apic interrupt input entries
+ ULONG IMCRPresent; // Indicates if the IMCR is present
+ ULONG LocalApicBase; // Base of local APIC
+ PULONG IoApicBase[MAX_IOAPICS]; // The virtual addresses of the IoApics
+ ULONG IoApicPhys[MAX_IOAPICS]; // The physical addresses of the IoApics
+
+// only good during initialization...
+ PPCMPPROCESSOR ProcessorEntryPtr; // Ptr to 1st PC+MP processor entry
+ PPCMPBUS BusEntryPtr; // Ptr to 1st PC+MP bus entry
+ PPCMPIOAPIC IoApicEntryPtr; // Ptr to 1st PC+MP IoApic entry
+ PPCMPINTI IntiEntryPtr; // Ptr to 1st PC+MP Inti entry
+ PPCMPLINTI LintiEntryPtr; // Ptr to 1st PC+MP Linti entry
+ PMPS_EXTENTRY ExtensionTable; // Ptr to 1st extension table entry
+ PMPS_EXTENTRY EndOfExtensionTable;
+} ;
+
+typedef struct {
+ PUCHAR PcMpType;
+ BOOLEAN PhysicalInstance;
+ UCHAR Level;
+ INTERFACE_TYPE NtType;
+ PINSTALL_BUS_HANDLER NewInstance;
+ BUS_DATA_TYPE NtConfig;
+ ULONG BusExtensionSize;
+} PCMPBUSTRANS, *PPCMPBUSTRANS;
+
+#define CFG_MUST_BE 0x02
+#define CFG_ERROR 0x80
+
+#define CFG_HIGH 0x01
+#define CFG_LOW 0x00
+
+#define CFG_EDGE 0x00
+#define CFG_LEVEL 0x01
+#define CFG_MB_EDGE (CFG_MUST_BE | CFG_EDGE)
+#define CFG_MB_LEVEL (CFG_MUST_BE | CFG_LEVEL)
+#define CFG_ERR_EDGE (CFG_ERROR | CFG_EDGE)
+#define CFG_ERR_LEVEL (CFG_ERROR | CFG_LEVEL)
+#define CFG_ERR_MB_EDGE (CFG_ERROR | CFG_MUST_BE | CFG_EDGE)
+#define CFG_ERR_MB_LEVEL (CFG_ERROR | CFG_MUST_BE | CFG_LEVEL)
+
+#define CFG_TYPE(a) (a & 1)
+
+
+//
+// The kernel leaves some space (64 byte) of the PCR for the HAL to use
+// as it needs. Currently this space is used for some efficiency in
+// some of the MP specific code and is highly implementation-dependent.
+//
+
+typedef struct {
+ UCHAR PCMPApicID;
+ UCHAR na[3];
+} HALPRCB, *PHALPRCB;
+
+
+//
+// interrupt vector definitions for C
+//
+
+#define ZERO_VECTOR 0x00 // IRQL 00 placeholder
+#define APIC_SPURIOUS_VECTOR 0x1f // IRQL Spurious handler
+#define APC_VECTOR 0x3D // IRQL 01 APC
+#define DPC_VECTOR 0x41 // IRQL 02 DPC
+#define APIC_REBOOT_VECTOR 0x50 // IRQL Vector used to reboot
+#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 broadcast function call
+#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 APIC INTI0 - CLOCK2_LEVEL
+#define APIC_SYNCH_VECTOR 0xD1 // IRQL 28 IPI_LEVEL-1
+#define APIC_IPI_VECTOR 0xE1 // IRQL 29 APIC IPI
+
+#define APIC_FAULT_VECTOR 0xE3 //
+#define POWERFAIL_VECTOR 0xEF // IRQL 30 reserved. not used
+
+#define APIC_PROFILE_VECTOR 0xFD // IRQL 31
+#define APIC_PERF_VECTOR 0xFE // IRQL 31
+#define NMI_VECTOR 0xFF // IRQL 31
+
+//
+// 8259/ISP interrupt controller register addresses
+//
+
+#define PIC1_PORT0 0x20
+#define PIC1_PORT1 0x21
+#ifndef PIC2_PORT0
+#define PIC2_PORT0 0xA0
+#define PIC2_PORT1 0xA1
+#endif
+#define PIC_SLAVE_IRQ 2
+
+
+#define PIC1_ELCR_PORT 0x04D0 // ISP edge/level control registers
+#define PIC2_ELCR_PORT 0x04D1
+
+#define PIC1_SPURIOUS_VECTOR 0x37
+
+//
+// Defines for HalpFeatureBits
+//
+
+extern ULONG HalpFeatureBits;
+
+//
+//
+//
+
+ULONG FASTCALL HalpAcquireHighLevelLock(PKSPIN_LOCK);
+VOID FASTCALL HalpReleaseHighLevelLock(PKSPIN_LOCK, ULONG);
+extern KSPIN_LOCK HalpAccountingLock;
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Prototypes
+//
+
+BOOLEAN
+HalpGetPcMpInterruptDesc (
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ OUT PULONG PcMpInti
+ );
+
+VOID
+HalpCheckELCR (
+ VOID
+ );
+
+VOID
+HalpSetInternalVector (
+ IN ULONG InternalVector,
+ IN VOID (*HalInterruptSerivceRoutine)(VOID)
+ );
+
+VOID
+HalpGenericCall (
+ VOID (*Fnc)(ULONG),
+ ULONG Context,
+ KAFFINITY Processors
+ );
+
+VOID
+HalpPollForBroadcast (
+ VOID
+ );
+
+ULONG
+FASTCALL
+HalpWaitForPending (
+ IN ULONG Count,
+ IN volatile ULONG *LuICR
+ );
+
+VOID
+HalpPerfInterrupt(
+ VOID
+ );
+
+VOID
+HalpEnablePerfInterupt (
+ ULONG Context
+ );
+
+VOID
+HalpEnableNMI (
+ VOID
+ );
+
+NTSTATUS
+HalpSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ );
+
+/*
+endif
+;
+; Begin assembly part of the definitions
+;
+
+include i386\pcmp.inc
+
+;
+; Well known virtual address of local processor apic
+;
+
+LOCALAPIC equ 0fffe0000h
+APIC equ ds:[LOCALAPIC]
+
+DEBUGGING equ 0
+
+
+if DEBUGGING
+IRQL_METRICS equ 0
+endif
+;
+; To allow the user to specify command line options to the HAL.
+;
+USER_SETABLE_OPTIONS equ 1
+
+;
+; This OS specific structure holds useful MP information. This information
+; is obtained from the PC+MP table and stored here for convenience.
+;
+
+HalpMpInfo struc
+ ApicVersion dd 0 ; 82489Dx or Not
+ ProcessorCount dd 0 ; Number of Enabled Processors
+ NtProcessors dd 0 ; Number of Running Processors
+ BusCount dd 0 ; Number of buses in system
+ IOApicCount dd 0 ; Number of Io Apics in system
+ IntiCount dd 0 ; Num of Io Apic interrupt inputs
+ LintiCount dd 0 ; Num of Local Apic interrupt inputs
+ IMCRPresent dd 0 ; Indicates if the IMCR is present
+ LocalApicBase dd 0 ; Base of local apic
+ IoApicBase dd 8 dup (0) ; The virtual addresses of the IoApics
+ IoApicPhys dd 8 dup (0) ; The physical addresses of the IoApics
+ ProcessorEntryPtr dd 0 ; Ptr to 1st PC+MP processor entry
+ BusEntryPtr dd 0 ; Ptr to 1st PC+MP bus entry
+ IoApicEntryPtr dd 0 ; Ptr to 1st PC+MP IoApic entry
+ IntiEntryPtr dd 0 ; Ptr to 1st PC+MP Inti entry
+ LintiEntryPtr dd 0 ; Ptr to 1st PC+MP Linti entry
+ ExtensionTable dd 0 ; Ptr to 1st extension table entry
+ EndExtensionTable dd 0 ; Ptr to 1st extension table entry
+HalpMpInfo ends
+
+
+;
+; interrupt vector definitions for assembler
+;
+
+ZERO_VECTOR equ 000h ; IRQL 00 placeholder
+APIC_SPURIOUS_VECTOR equ 01fh ; Vector used for spurious handler
+APC_VECTOR equ 03Dh ; IRQL 01 APC
+DPC_VECTOR equ 041h ; IRQL 02 DPC
+APIC_REBOOT_VECTOR equ 050h ; Vector used to reboot
+DEVICE_LEVEL1 equ 051h
+DEVICE_LEVEL2 equ 061h
+DEVICE_LEVEL3 equ 071h
+DEVICE_LEVEL4 equ 081h
+DEVICE_LEVEL5 equ 091h
+DEVICE_LEVEL6 equ 0A1h
+DEVICE_LEVEL7 equ 0B1h
+APIC_GENERIC_VECTOR equ 0C1h ; IRQL 27 broadcast function call
+APIC_CLOCK_VECTOR equ 0D1h ; IRQL 28 APIC INTI0 - CLOCK2_LEVEL
+APIC_SYNCH_VECTOR equ 0D1h ; IRQL 28 IPI_LEVEL-1
+APIC_IPI_VECTOR equ 0E1h ; IRQL 29 APIC IPI
+
+APIC_FAULT_VECTOR equ 0E3h ;
+POWERFAIL_VECTOR equ 0EFh ; IRQL 30 reserved
+
+APIC_PROFILE_VECTOR equ 0FDh ; IRQL 27
+APIC_PERF_VECTOR equ 0FEh ; IRQL 27
+NMI_VECTOR equ 0FFh ; IRQL 31
+
+HAL_PROFILE_LEVEL equ HIGH_LEVEL
+
+;
+; 8259/ISP interrupt controller register addresses
+;
+
+PIC1_PORT0 equ 020H
+PIC1_PORT1 equ 021H
+PIC2_PORT0 equ 0A0H
+PIC2_PORT1 equ 0A1H
+
+PIC1_ELCR_PORT equ 04D0H ; ISP edge/level control registers
+PIC2_ELCR_PORT equ 04D1H
+
+;
+; Initialization control words for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_AUTO_EOI equ 002H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+PIC_CLOCK_VECTOR equ 30H
+PIC_DMA_VECTOR equ 3DH
+PIC1_SPURIOUS_VECTOR equ 37H
+PIC2_SPURIOUS_VECTOR equ 3FH
+
+;
+; Operation control words for the PICs
+;
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW3_READ_ISR equ 0BH
+OCW3_READ_IRR equ 0AH
+OCW3_READ_POLLED equ 0CH
+
+;
+; A couple of definitions that shouldn't change on a Compatible
+;
+
+TimerPicInti equ 0
+DmaPic2Inti equ 5
+SlavePicInti equ 2
+DmaPicInti equ 13 ; DMA input relative to 0
+
+cr equ 0ah
+lf equ 0dh
+
+;
+; The kernel leaves some space (64 byte) of the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation-dependent.
+;
+
+
+PcrE struc
+ PcrNumber db 0 ; Processor's number
+ ShortDpc db 0 ; Short circut dpc interrupt
+ DpcPending db 0 ; Dpc interrupt pending
+
+ db 0 ; force dword alignment
+ ;
+ ; The next three dwords are used to manipulate the APIC counter
+ ;
+
+ ApicClockFreqHz dd 0 ; Counter Freq in Hertz
+ ApicClockFreqKhz dd 0 ; Counter Freq in Khertz (rounded)
+ ProfileCountDown dd 0 ; Current Countdown Interval
+
+ TSCHz dd 0 ; Time stamp counter hertz low
+
+
+ ; PerfCounterLow dd 0 ; PerProcessor Counter
+ ; PerfCounterHigh dd 0 ;
+ ; ProfileCountLast dd 0
+
+PcrE ends
+
+PrcbE struc
+ PrcbPCMPApicID db 0 ; Processor's PCMP ApicID
+ db 3 dup (0) ; force dword alignment
+PrcbE ends
+
+
+MsrTSC equ 10h
+
+;++
+;
+; STALL_WHILE_APIC_BUSY
+;
+; Wait for the APIC DELIVERY_PENDING bit to be clear
+;
+;--
+
+STALL_WHILE_APIC_BUSY macro
+ local a, b
+if 0
+
+ push eax
+ mov eax, 5000h
+
+a: test dword ptr APIC[LU_INT_CMD_LOW],DELIVERY_PENDING
+ jz short b
+
+ dec eax
+ jnz short a
+
+ int 3
+ jmp short a
+
+b: pop eax
+
+else
+
+a: test dword ptr APIC[LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz short a
+
+endif
+endm
+
+;++
+;
+; APICFIX
+;
+; Macro Description:
+;
+; For internal testing use
+;
+; Arguments:
+;
+; None
+;
+;--
+
+APICFIX macro reg1
+ ; inc dword ptr PCR[PcKernel] ; Count # of times patched
+endm
+
+;++
+;
+; CHECKTPR
+;
+; Macro Description:
+;
+; For internal testing use
+;
+; Arguments:
+;
+; None
+;
+;--
+
+CHECKTPR macro reg1, reg2
+if DBG
+ cmp reg1, reg2
+ je short @f
+ int 3
+@@:
+endif
+endm
+
+;++
+;
+; IODELAY
+;
+; Macro Description:
+;
+; This macro delays the CPU just a little so the PIC has time to settle
+; between IO port accesses. Current mechanism is to read an APIC local
+; unit register (eax is saved). Note that PUSHF/POPF is worth 10 clocks.
+;
+; Arguments:
+;
+; None
+;
+;--
+
+IODELAY macro
+ pushf
+ popf
+ jmp $+2
+endm
+
+;++
+;
+; SET_8259_MASK
+;
+; Macro Description:
+;
+; This macro sets the 8259 PIC interrupt mask register with the mask
+; passed from eax register. Bits 7:0 are the mask for the master PIC
+; and bits 15:8 are the mask for the slave PIC.
+;
+; Arguments:
+;
+; (eax) = mask for setting 8259 PIC interrupt mask register
+;
+;--
+
+SET_8259_MASK macro
+
+ out PIC1_PORT1, al ; set master 8259 mask
+ shr eax, 8 ; shift slave 8259 mask to al
+ out PIC2_PORT1, al ; set slave 8259 mask
+endm
+
+;*/
diff --git a/private/ntos/nthals/halmps/i386/pcmpdtct.c b/private/ntos/nthals/halmps/i386/pcmpdtct.c
new file mode 100644
index 000000000..0bee1ebae
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/pcmpdtct.c
@@ -0,0 +1,581 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Intel Corporation
+All rights reserved
+
+INTEL CORPORATION PROPRIETARY INFORMATION
+
+This software is supplied to Microsoft under the terms
+of a license agreement with Intel Corporation and may not be
+copied nor disclosed except in accordance with the terms
+of that agreement.
+
+Module Name:
+
+ pcmpdtct.c
+
+Abstract:
+
+ This module detects an MPS system.
+
+Author:
+
+ Ron Mosgrove (Intel) - Aug 1993.
+
+Environment:
+
+ Kernel mode or from textmode setup.
+
+Revision History:
+ Rajesh Shah (Intel) - Oct 1993. Added support for MPS table.
+
+--*/
+
+#ifndef _NTOS_
+#include "halp.h"
+#endif
+
+#include "apic.inc"
+#include "pcmp_nt.inc"
+#include "stdio.h"
+
+#if DEBUGGING
+CHAR Cbuf[120];
+VOID HalpDisplayConfigTable(VOID);
+VOID HalpDisplayExtConfigTable(VOID);
+VOID HalpDisplayBIOSSysCfg(struct SystemConfigTable *);
+#define DBGMSG(a) HalDisplayString(a)
+#else
+#define DBGMSG(a)
+#endif
+
+//
+// The floating pointer structure defined by the MPS spec can reside
+// anywhere in BIOS extended data area. These defines are used to search for
+// the floating structure starting from physical address 639K(9f000+c00)
+//
+#define PCMP_TABLE_PTR_BASE 0x09f000
+#define PCMP_TABLE_PTR_OFFSET 0x00000c00
+
+extern struct HalpMpInfo HalpMpInfoTable;
+
+
+UCHAR
+ComputeCheckSum(
+ IN PUCHAR SourcePtr,
+ IN USHORT NumOfBytes
+ );
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+struct FloatPtrStruct *
+SearchFloatPtr (
+ ULONG PhysicalAddress,
+ ULONG ByteSize
+ );
+
+struct FloatPtrStruct *
+PcMpGetFloatingPtr (
+ VOID
+ );
+
+
+struct PcMpTable *
+GetPcMpTable (
+ VOID
+ );
+
+
+struct PcMpTable *
+MPS10_GetPcMpTablePtr (
+ VOID
+ );
+
+struct PcMpTable *
+MPS10_GetPcMpTable (
+ VOID
+ );
+
+
+struct PcMpTable *
+GetDefaultConfig (
+ IN ULONG Config
+ );
+
+#ifdef SETUP
+
+//
+// A dummy pointer to a default MPS table. For setup, we can conserve
+// space by not building default tables in our data area.
+#define DEFAULT_MPS_INDICATOR 0xfefefefe
+
+#endif //SETUP
+
+#ifndef SETUP
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,SearchFloatPtr)
+#pragma alloc_text(INIT,PcMpGetFloatingPtr)
+#pragma alloc_text(INIT,ComputeCheckSum)
+#pragma alloc_text(INIT,GetPcMpTable)
+#pragma alloc_text(INIT,MPS10_GetPcMpTablePtr)
+#pragma alloc_text(INIT,MPS10_GetPcMpTable)
+#pragma alloc_text(INIT,GetDefaultConfig)
+#endif // ALLOC_PRAGMA
+
+extern struct PcMpTable *PcMpDefaultTablePtrs[];
+#endif // ndef SETUP
+
+
+struct FloatPtrStruct *
+SearchFloatPtr(
+ ULONG PhysicalAddress,
+ ULONG ByteSize
+ )
+{
+ // Search for the MPS floating pointer structure starting from the
+ // physical address given.
+
+ USHORT Index, ParagraphLength;
+ UCHAR CheckSum;
+ ULONG VirtualAddress;
+ BOOLEAN CheckSumError;
+
+#ifdef DEBUGGING
+ sprintf(Cbuf, "SearchFloatPtr: Will search at physical address 0x%lx\n",
+ PhysicalAddress);
+ HalDisplayString(Cbuf);
+#endif // DEBUGGING
+
+ // Get the virtual address corresponding to the physical address
+ VirtualAddress = (ULONG) HalpMapPhysicalMemory( (PVOID) PhysicalAddress,
+ ((ByteSize/PAGE_SIZE) + 1) );
+
+ if ( (PVOID) VirtualAddress == NULL) {
+ DBGMSG ("SearchFloatPtr: Cannot map Physical address\n");
+ return (NULL);
+ }
+
+ // The MPS spec says that the floating pointer structure MUST be
+ // aligned at 16 byte boundaries. We can use this fact to search for
+ // the structure only at those boundaries. Assume that the input physical
+ // address to start search from is 16 byte aligned.
+
+ CheckSumError = FALSE;
+ for(Index = 0; Index < (ByteSize/sizeof(struct FloatPtrStruct)); ++Index) {
+ if ( (*((PULONG)VirtualAddress) ) == MP_PTR_SIGNATURE) {
+
+ ParagraphLength =
+ ((struct FloatPtrStruct *)VirtualAddress)->MpTableLength;
+ // Detected the floating structure signature. Check if the
+ // floating pointer structure checksum is valid.
+ CheckSum = ComputeCheckSum((PUCHAR)VirtualAddress,
+ (USHORT) (ParagraphLength*16) );
+ if (CheckSum != 0 ) {
+ CheckSumError = TRUE;
+ DBGMSG ("SearchFloatPtr: Valid MP_PTR signature, invalid checksum\n");
+
+ // Invalid structure. Continue searching.
+ VirtualAddress += sizeof(struct FloatPtrStruct);
+ continue;
+ }
+
+ // We have a valid floating pointer structure.
+ // Return a pointer to it.
+
+ DBGMSG ("SearchFloatPtr: Found structure\n");
+ return((struct FloatPtrStruct *) VirtualAddress);
+
+ }
+ VirtualAddress += sizeof(struct FloatPtrStruct);
+ }
+
+ if (CheckSumError) {
+ FAILMSG (rgzMPPTRCheck);
+ }
+
+ return(NULL);
+}
+
+
+struct FloatPtrStruct *
+PcMpGetFloatingPtr(
+ VOID)
+{
+ ULONG EbdaSegmentPtr, BaseMemPtr;
+ ULONG EbdaPhysicalAdd = 0, ByteLength, BaseMemKb = 0;
+ struct FloatPtrStruct *FloatPtr = NULL;
+
+ // Search for the floating pointer structure in the order specified in
+ // MPS spec version 1.1.
+
+ // First, search for it in the first kilobyte in the Extended BIOS Data
+ // Area. The EBDA segment address is available at physical address 40:0E
+
+ EbdaSegmentPtr = (ULONG) HalpMapPhysicalMemory( (PVOID) 0, 1);
+ EbdaSegmentPtr += EBDA_SEGMENT_PTR;
+ EbdaPhysicalAdd = *((PUSHORT)EbdaSegmentPtr);
+ EbdaPhysicalAdd = EbdaPhysicalAdd << 4;
+
+ if (EbdaPhysicalAdd != 0)
+ FloatPtr = SearchFloatPtr(EbdaPhysicalAdd, 1024);
+
+ if (FloatPtr == NULL) {
+
+ // Did not find it in EBDA.
+ // Look for it in the last KB of system memory.
+
+ BaseMemPtr = (ULONG) HalpMapPhysicalMemory( (PVOID) 0, 1);
+ BaseMemPtr += BASE_MEM_PTR;
+ BaseMemKb = *((PUSHORT)BaseMemPtr);
+
+ FloatPtr = SearchFloatPtr(BaseMemKb*1024, 1024);
+
+ if (FloatPtr == NULL) {
+
+ // Finally, look for the floating Pointer Structure at physical
+ // address F0000H to FFFFFH
+
+ ByteLength = 0xfffff - 0xf0000;
+
+ FloatPtr = SearchFloatPtr(0xf0000, ByteLength);
+ }
+ }
+
+ // At this point, we have a pointer to the MPS floating structure.
+
+ return(FloatPtr);
+}
+
+
+struct PcMpTable *
+MPS10_GetPcMpTablePtr(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Gets the Address of the MPS configuration table built by BIOS.
+ This routine looks for the floating pointer structure defined
+ in the MPS spec. This structure points to the MPS configuration
+ table built by an MP BIOS. The floating pointer structure can be
+ located anywhere in the extended BIOS data area(physical address range
+ 639K to 640K), and must be aligned on a 16 byte boundary.
+
+ Arguments:
+ None
+
+ Return Value:
+ struct PcMpTable * - Virtual address pointer to the PcMpTable, if
+ it exists, NULL otherwise
+
+--*/
+
+{
+ PUCHAR TempPtr;
+ ULONG LinearPtr;
+ UCHAR CheckSum;
+ struct PcMpTableLocator *PcMpPtrPtr;
+ PULONG TraversePtr;
+ USHORT ParagraphLength;
+ int i;
+
+ // Map the physical address of the BIOS extended data area to a virtual
+ // address we can use.
+ TempPtr = (PUCHAR) HalpMapPhysicalMemory(
+ (PVOID) PCMP_TABLE_PTR_BASE, 1);
+ TraversePtr = (PULONG)((PUCHAR) TempPtr + PCMP_TABLE_PTR_OFFSET);
+
+ // Look at 16 byte boundaries for the floating pointer structure
+ // The structure is identified by its signature, and verified by its
+ // checksum.
+ for (i=0; i < (1024/16); ++i)
+ {
+ if (*(TraversePtr) == MP_PTR_SIGNATURE)
+ {
+ // Got a valid signature.
+ PcMpPtrPtr = (struct PcMpTableLocator *)TraversePtr;
+
+ // Length in 16 byte paragraphs of the floating structure.
+ // Normally, this should be set to 1 by the BIOS.
+ ParagraphLength = PcMpPtrPtr->MpTableLength;
+
+ // Check if the floating pointer structure is valid.
+ CheckSum = ComputeCheckSum((PUCHAR)PcMpPtrPtr,
+ (USHORT) (ParagraphLength*16));
+ if (CheckSum != 0 ) {
+ FAILMSG (rgzMPPTRCheck);
+ // Invalid structure. Continue searching.
+ TraversePtr += 4;
+ continue;
+ }
+
+ // We have a valid floating pointer structure.
+ // The value stored in the structure is a physical address of the
+ // MPS table built by BIOS. Get the corresponding virtual
+ // address.
+
+ TempPtr = HalpMapPhysicalMemory(PcMpPtrPtr->TablePtr,2);
+ if (TempPtr == NULL) {
+ DBGMSG ("HAL: Cannot map BIOS created MPS table\n");
+ return (NULL);
+ }
+
+ // Return the virtual address pointer to the MPS table.
+ return((struct PcMpTable *) TempPtr);
+
+ }
+ TraversePtr += 4;
+ }
+
+ return(NULL);
+}
+
+
+UCHAR
+ComputeCheckSum (
+ IN PUCHAR SourcePtr,
+ IN USHORT NumOfBytes
+ )
+/*++
+
+Routine Description:
+ This routine computes a checksum for NumOfBytes bytes, starting
+ from SourcePtr. It is used to validate the tables built by BIOS.
+
+Arguments:
+ SourcePtr : Starting virtual address to compute checksum.
+ NumOfBytes: Number of bytes to compute the checksum of.
+
+ Return Value:
+ The checksum value.
+
+*/
+{
+ UCHAR Result = 0;
+ USHORT Count;
+
+ for(Count=0; Count < NumOfBytes; ++Count)
+ Result += *SourcePtr++;
+
+ return(Result);
+}
+
+
+struct PcMpTable *
+MPS10_GetPcMpTable (
+ VOID
+ )
+/*++
+Routine Description:
+ Detects an MPS 1.0 system only.
+
+Arguments:
+ None.
+
+Return Value:
+ Pointer to an MPS table.
+--*/
+{
+ struct SystemConfigTable *SystemConfigPtr;
+
+ UCHAR DefaultConfig, CheckSum;
+ struct PcMpTable *MpTablePtr;
+ UCHAR MpFeatureInfoByte1 = 0, MpFeatureInfoByte2 = 0;
+
+ // Get the virtual address of the system configuration table.
+ SystemConfigPtr = (struct SystemConfigTable *)
+ HalpMapPhysicalMemory((PVOID) BIOS_BASE, 16);
+
+ if (SystemConfigPtr == NULL) {
+ DBGMSG ("GetPcMpTable: Cannot map system configuration table\n");
+ return(NULL);
+ }
+
+ // HalpDisplayBIOSSysCfg(SystemConfigPtr);
+
+ // The system configuration table built by BIOS has 2 MP feature
+ // information bytes.
+
+ MpFeatureInfoByte1 = SystemConfigPtr->MpFeatureInfoByte1;
+ MpFeatureInfoByte2 = SystemConfigPtr->MpFeatureInfoByte2;
+
+ // The second MP feature information byte tells us whether the system
+ // has an IMCR(Interrupt Mode Control Register). We use this information
+ // in the HAL, so we store this information in the OS specific private
+ // area.
+
+ if ((MpFeatureInfoByte2 & IMCR_MASK) == 0)
+ HalpMpInfoTable.IMCRPresent = 0;
+ else
+ HalpMpInfoTable.IMCRPresent = 1;
+
+ // MP feature byte 1 indicates if the system is MPS compliant
+ if (! (MpFeatureInfoByte1 & PCMP_IMPLEMENTED)) {
+ // The MP feature information byte indicates that this
+ // system is not MPS compliant.
+ FAILMSG (rgzNoMpsTable);
+ return(NULL);
+ }
+
+ // The system is MPS compliant. MP feature byte 2 indicates if the
+ // system is a default configuration or not.
+ DefaultConfig = (MpFeatureInfoByte1 & PCMP_CONFIG_MASK) >> 1;
+
+ if (DefaultConfig) {
+ return GetDefaultConfig(DefaultConfig);
+ }
+
+ // DefaultConfig == 0. This means that the BIOS has built a MP
+ // config table for us. The BIOS will also build a floating pointer
+ // structure that points to the MP config table. This floating pointer
+ // structure resides in the BIOS extended data area.
+ MpTablePtr = MPS10_GetPcMpTablePtr();
+
+ if (MpTablePtr == NULL) {
+ FAILMSG (rgzNoMPTable); // Could not find BIOS created MPS table
+ return(NULL);
+ }
+
+ // We have a pointer to the MP config table. Check if the table is valid.
+
+ if ((MpTablePtr->Signature != PCMP_SIGNATURE) ||
+ (MpTablePtr->TableLength < sizeof(struct PcMpTable)) ) {
+ FAILMSG(rgzMPSBadSig);
+ return(NULL);
+ }
+
+ CheckSum = ComputeCheckSum((PUCHAR)MpTablePtr, MpTablePtr->TableLength);
+ if (CheckSum != 0) {
+ FAILMSG(rgzMPSBadCheck);
+ return(NULL);
+ }
+
+ return MpTablePtr;
+}
+
+
+struct PcMpTable *
+GetPcMpTable(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+ This routine gets the MP table for a MPS compliant system.
+ For a MPS compliant system, either the BIOS builds an MP table, or
+ it indicates that the system is one of the default configurations
+ defined in the MPS spec. The MP feature information bytes in the BIOS
+ system configuration table indicate whether the system is one of the
+ default systems, or has a BIOS created MP table. For a default system
+ configuration, this routine uses a statically built default table.
+ This routine copies the MPS table into private system memory, and
+ returns a pointer to this table.
+
+Arguments:
+ None.
+
+ Return Value:
+ Pointer to the private copy of the MP table that has been copied in
+ system memory.
+
+*/
+{
+
+ struct FloatPtrStruct *FloatingPtr;
+ UCHAR CheckSum;
+ struct PcMpTable *MpTablePtr;
+ UCHAR MpFeatureInfoByte1 = 0, MpFeatureInfoByte2 = 0;
+ PUCHAR TempPtr;
+
+ FloatingPtr = PcMpGetFloatingPtr();
+
+ if (FloatingPtr == NULL) {
+ FAILMSG (rgzNoMPTable);
+ return(NULL);
+ }
+
+ // The floating structure has 2 MP feature information bytes.
+
+ MpFeatureInfoByte1 = FloatingPtr->MpFeatureInfoByte1;
+ MpFeatureInfoByte2 = FloatingPtr->MpFeatureInfoByte2;
+
+ // The second MP feature information byte tells us whether the system
+ // has an IMCR(Interrupt Mode Control Register). We use this information
+ // in the HAL, so we store this information in the OS specific private
+ // area.
+
+ if ((MpFeatureInfoByte2 & IMCR_MASK) == 0)
+ HalpMpInfoTable.IMCRPresent = 0;
+ else
+ HalpMpInfoTable.IMCRPresent = 1;
+
+ if (MpFeatureInfoByte1 != 0) {
+ // The system configuration is one of the default
+ // configurations defined in the MPS spec. Find out which
+ // default configuration it is and get a pointer to the
+ // corresponding default table.
+
+ return GetDefaultConfig(MpFeatureInfoByte1);
+ }
+
+
+ // MpFeatureInfoByte1 == 0. This means that the BIOS has built a MP
+ // config table for us. The address of the OEM created table is in
+ // the MPS floating structure.
+
+ TempPtr = HalpMapPhysicalMemory(FloatingPtr->TablePtr,2);
+
+ if (TempPtr == NULL) {
+ DBGMSG ("HAL: Cannot map OEM MPS table\n");
+ return (NULL);
+ }
+
+ MpTablePtr = (struct PcMpTable *)TempPtr;
+
+ // We have a pointer to the MP config table. Check if the table is valid.
+
+ if ((MpTablePtr->Signature != PCMP_SIGNATURE) ||
+ (MpTablePtr->TableLength < sizeof(struct PcMpTable)) ) {
+ FAILMSG (rgzMPSBadSig);
+ return(NULL);
+ }
+
+ CheckSum = ComputeCheckSum((PUCHAR)MpTablePtr, MpTablePtr->TableLength);
+ if (CheckSum != 0) {
+ FAILMSG (rgzMPSBadCheck);
+ return(NULL);
+ }
+
+ return MpTablePtr;
+}
+
+
+struct PcMpTable *
+GetDefaultConfig (
+ IN ULONG Config
+ )
+{
+ Config -= 1;
+
+ if (Config >= NUM_DEFAULT_CONFIGS) {
+ FAILMSG (rgzBadDefault);
+ return NULL;
+ }
+
+#ifdef DEBUGGING
+ HalDisplayString ("HALMPS: Using default table\n");
+#endif
+
+#ifdef SETUP
+ return((struct PcMpTable *) DEFAULT_MPS_INDICATOR);
+#else
+ return PcMpDefaultTablePtrs[Config];
+#endif // SETUP
+}
diff --git a/private/ntos/nthals/halmps/i386/sources b/private/ntos/nthals/halmps/i386/sources
new file mode 100644
index 000000000..01ee5b046
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/sources
@@ -0,0 +1,55 @@
+i386_SOURCES=..\hal.rc \
+ ..\drivesup.c \
+ ..\bushnd.c \
+ ..\rangesup.c \
+ ..\i386\ixbeep.asm \
+ ..\i386\ixbusdat.c \
+ ..\i386\ixcmos.asm \
+ ..\i386\ixenvirv.c \
+ ..\i386\ixfirm.c \
+ ..\i386\ixhwsup.c \
+ ..\i386\ixidle.asm \
+ ..\i386\ixinfo.c \
+ ..\i386\ixisabus.c \
+ ..\i386\ixisasup.c \
+ ..\i386\ixkdcom.c \
+ ..\i386\ixmca.c \
+ ..\i386\ixmcaa.asm \
+ ..\i386\ixmcasup.c \
+ ..\i386\ixmcabus.c \
+ ..\i386\ixpcibus.c \
+ ..\i386\ixpciint.c \
+ ..\i386\ixpcibrd.c \
+ ..\i386\ixphwsup.c \
+ ..\i386\ixreboot.c \
+ ..\i386\ixthunk.c \
+ ..\i386\ixusage.c \
+ ..\i386\xxbiosa.asm \
+ ..\i386\xxbiosc.c \
+ ..\i386\xxdisp.c \
+ ..\i386\xxioacc.asm \
+ ..\i386\xxkdsup.c \
+ ..\i386\xxmemory.c \
+ ..\i386\xxstubs.c \
+ ..\i386\xxtime.c \
+ ..\i386\mpaddr.c \
+ ..\i386\mpclock.asm \
+ ..\i386\mpipi.asm \
+ ..\i386\mpirql.asm \
+ ..\i386\mpinfo.c \
+ ..\i386\mpsproca.asm \
+ ..\i386\mpsproc.c \
+ ..\i386\mpswint.asm \
+ ..\i386\mpsysint.asm \
+ ..\i386\mpsysbus.c \
+ ..\i386\mpconfig.asm \
+ ..\i386\mphal.c \
+ ..\i386\mpprofil.asm \
+ ..\i386\mppciint.c \
+ ..\i386\mpdetect.c \
+ ..\i386\mpdebug.c \
+ ..\i386\mpspin.asm \
+ ..\i386\mpclockc.c \
+ ..\i386\mpdat.c \
+ ..\i386\ixnmi.c \
+ ..\i386\mpsys.c
diff --git a/private/ntos/nthals/halmps/i386/xxbiosa.asm b/private/ntos/nthals/halmps/i386/xxbiosa.asm
new file mode 100644
index 000000000..af9de2a09
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halmps/i386/xxbiosc.c b/private/ntos/nthals/halmps/i386/xxbiosc.c
new file mode 100644
index 000000000..48f2b32d8
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halmps/i386/xxdisp.c b/private/ntos/nthals/halmps/i386/xxdisp.c
new file mode 100644
index 000000000..8b7b072f2
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halmps/i386/xxflshbf.c b/private/ntos/nthals/halmps/i386/xxflshbf.c
new file mode 100644
index 000000000..860e0a332
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halmps/i386/xxioacc.asm b/private/ntos/nthals/halmps/i386/xxioacc.asm
new file mode 100644
index 000000000..c963c91d6
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halmps/i386/xxkdsup.c b/private/ntos/nthals/halmps/i386/xxkdsup.c
new file mode 100644
index 000000000..2d9149247
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halmps/i386/xxmemory.c b/private/ntos/nthals/halmps/i386/xxmemory.c
new file mode 100644
index 000000000..e476095d5
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halmps/i386/xxstubs.c b/private/ntos/nthals/halmps/i386/xxstubs.c
new file mode 100644
index 000000000..3a69390bd
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halmps/i386/xxtime.c b/private/ntos/nthals/halmps/i386/xxtime.c
new file mode 100644
index 000000000..7a78dd38d
--- /dev/null
+++ b/private/ntos/nthals/halmps/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halmps/mp/makefile b/private/ntos/nthals/halmps/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmps/mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halmps/mp/makefile.inc b/private/ntos/nthals/halmps/mp/makefile.inc
new file mode 100644
index 000000000..e2bb55a56
--- /dev/null
+++ b/private/ntos/nthals/halmps/mp/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: ..\..\hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) ..\..\hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halmps/mp/sources b/private/ntos/nthals/halmps/mp/sources
new file mode 100644
index 000000000..d42aed030
--- /dev/null
+++ b/private/ntos/nthals/halmps/mp/sources
@@ -0,0 +1,56 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halmps
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\..\inc;..\..\..\ke;..\..;..;..\i386
+
+SOURCES=
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halmps.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halmps/mpmca/makefile b/private/ntos/nthals/halmps/mpmca/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmps/mpmca/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halmps/mpmca/makefile.inc b/private/ntos/nthals/halmps/mpmca/makefile.inc
new file mode 100644
index 000000000..e2bb55a56
--- /dev/null
+++ b/private/ntos/nthals/halmps/mpmca/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: ..\..\hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) ..\..\hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halmps/mpmca/sources b/private/ntos/nthals/halmps/mpmca/sources
new file mode 100644
index 000000000..ac4d74030
--- /dev/null
+++ b/private/ntos/nthals/halmps/mpmca/sources
@@ -0,0 +1,57 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halmpsm
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+HALTYPE=MCA
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\..\inc;..\..\..\ke;..\..;..;..\i386
+
+SOURCES=
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halmpsm.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halmps/rangesup.c b/private/ntos/nthals/halmps/rangesup.c
new file mode 100644
index 000000000..d9d8db63f
--- /dev/null
+++ b/private/ntos/nthals/halmps/rangesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\rangesup.c"
diff --git a/private/ntos/nthals/halmps/up/makefile b/private/ntos/nthals/halmps/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmps/up/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halmps/up/makefile.inc b/private/ntos/nthals/halmps/up/makefile.inc
new file mode 100644
index 000000000..e2bb55a56
--- /dev/null
+++ b/private/ntos/nthals/halmps/up/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: ..\..\hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) ..\..\hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halmps/up/sources b/private/ntos/nthals/halmps/up/sources
new file mode 100644
index 000000000..c6638c998
--- /dev/null
+++ b/private/ntos/nthals/halmps/up/sources
@@ -0,0 +1,55 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halapic
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\..\inc;..\..\..\ke;..\..;..;..\i386
+
+SOURCES=
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halapic.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halmps/upmca/makefile b/private/ntos/nthals/halmps/upmca/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmps/upmca/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halmps/upmca/makefile.inc b/private/ntos/nthals/halmps/upmca/makefile.inc
new file mode 100644
index 000000000..e2bb55a56
--- /dev/null
+++ b/private/ntos/nthals/halmps/upmca/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: ..\..\hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) ..\..\hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halmps/upmca/sources b/private/ntos/nthals/halmps/upmca/sources
new file mode 100644
index 000000000..197492336
--- /dev/null
+++ b/private/ntos/nthals/halmps/upmca/sources
@@ -0,0 +1,56 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halapicm
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+HALTYPE=MCA
+
+!IF $(386)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\..\inc;..\..\..\ke;..\..;..;..\i386
+
+SOURCES=
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halapicm.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halncr/drivesup.c b/private/ntos/nthals/halncr/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halncr/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halncr/hal.rc b/private/ntos/nthals/halncr/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halncr/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halncr/hal.src b/private/ntos/nthals/halncr/hal.src
new file mode 100644
index 000000000..fd1f28579
--- /dev/null
+++ b/private/ntos/nthals/halncr/hal.src
@@ -0,0 +1,20 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
+
+//
+// New APIs for NCR enhancements
+//
+
+ HalCatBusAvailable
+ HalCatBusIo
+ HalCatBusReset
+ HalPowerOffSystem
+ HalGetSUSErrorLogEntry
+ HalSetWatchDogPeriod
+ HalBumpWatchDogCount
+ HalSetStatusChangeInterruptState
diff --git a/private/ntos/nthals/halncr/i386/halnls.h b/private/ntos/nthals/halncr/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/halncr/i386/halp.h b/private/ntos/nthals/halncr/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halncr/i386/ix8259.inc b/private/ntos/nthals/halncr/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halncr/i386/ixbeep.asm b/private/ntos/nthals/halncr/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halncr/i386/ixbusdat.c b/private/ntos/nthals/halncr/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halncr/i386/ixcmos.asm b/private/ntos/nthals/halncr/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halncr/i386/ixcmos.inc b/private/ntos/nthals/halncr/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halncr/i386/ixdat.c b/private/ntos/nthals/halncr/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halncr/i386/ixenvirv.c b/private/ntos/nthals/halncr/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halncr/i386/ixhwsup.c b/private/ntos/nthals/halncr/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halncr/i386/ixidle.asm b/private/ntos/nthals/halncr/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halncr/i386/ixinfo.c b/private/ntos/nthals/halncr/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halncr/i386/ixisa.h b/private/ntos/nthals/halncr/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halncr/i386/ixisabus.c b/private/ntos/nthals/halncr/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halncr/i386/ixisasup.c b/private/ntos/nthals/halncr/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halncr/i386/ixkdcom.c b/private/ntos/nthals/halncr/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halncr/i386/ixkdcom.h b/private/ntos/nthals/halncr/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halncr/i386/ixmca.h b/private/ntos/nthals/halncr/i386/ixmca.h
new file mode 100644
index 000000000..f401e096e
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixmca.h
@@ -0,0 +1,5 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#include "..\halmca\i386\ixmca.h"
diff --git a/private/ntos/nthals/halncr/i386/ixmcabus.c b/private/ntos/nthals/halncr/i386/ixmcabus.c
new file mode 100644
index 000000000..8ef2ef197
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixmcabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halmca\i386\ixmcabus.c"
diff --git a/private/ntos/nthals/halncr/i386/ixmcasup.c b/private/ntos/nthals/halncr/i386/ixmcasup.c
new file mode 100644
index 000000000..625d7e412
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixmcasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halmca
+// This is a cpp style symbolic link
+
+#include "..\halmca\i386\ixmcasup.c"
diff --git a/private/ntos/nthals/halncr/i386/ixnmi.c b/private/ntos/nthals/halncr/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/halncr/i386/ixpcibrd.c b/private/ntos/nthals/halncr/i386/ixpcibrd.c
new file mode 100644
index 000000000..02fd82821
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixpcibrd.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/halncr/i386/ixpcibus.c b/private/ntos/nthals/halncr/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/halncr/i386/ixpciint.c b/private/ntos/nthals/halncr/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/halncr/i386/ixphwsup.c b/private/ntos/nthals/halncr/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halncr/i386/ixprofil.asm b/private/ntos/nthals/halncr/i386/ixprofil.asm
new file mode 100644
index 000000000..c33b273ae
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixprofil.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixprofil.asm
diff --git a/private/ntos/nthals/halncr/i386/ixstall.asm b/private/ntos/nthals/halncr/i386/ixstall.asm
new file mode 100644
index 000000000..4e33c55fb
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixstall.asm
@@ -0,0 +1,481 @@
+
+ title "Stall Execution Support"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixstall.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Landy Wang (corollary!landy) 04-Dec-92
+; Created this module by moving routines from ixclock.asm to here.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ncr.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+RTCIRQ EQU 8 ; IRQ number for RTC interrupt
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+;
+; RegisterAInitByte sets 8Hz clock rate, used during init to set up
+; KeStallExecutionProcessor, etc. (See RegASystemClockByte below.)
+;
+
+RegisterAInitByte EQU 00101101B ; RT/CMOS Register 'A' init byte
+ ; 32.768KHz Base divider rate
+ ; 8Hz int rate, period = 125.0ms
+PeriodInMicroSecond EQU 125000 ;
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+HalpP0BugBugStallCount dd 0
+
+_DATA ends
+
+INIT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; HalpInitializeStallExecution (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+; Note:
+;
+; Current implementation assumes that all the processors share
+; the same Real Time Clock. So, the dispatcher database lock is
+; acquired before entering this routine to guarantee only one
+; processor can access the routine.
+;
+;--
+
+KiseInterruptCount equ [ebp-12] ; local variable
+
+cPublicProc _HalpInitializeStallExecution ,1
+
+ifndef NT_UP
+;;
+;; This function currently doesn't work from any processor but the
+;; boot processor - for now stub out the others
+;;
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbNumber, 0
+ je @f
+
+ mov eax, HalpP0BugBugStallCount
+ mov PCR[PcStallScaleFactor], eax
+ stdRET _HalpInitializeStallExecution
+@@:
+endif
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 12 bytes for local use
+ sub esp, 12
+
+ pushfd ; save caller's eflag
+
+;
+; Initialize Real Time Clock to interrupt us for every 125ms at
+; IRQ 8.
+;
+
+ cli ; make sure interrupts are disabled
+
+;
+; Get and save current 8259 masks
+;
+
+ xor eax,eax
+
+;
+; Assume there is no third and fourth PICs
+;
+; Get interrupt Mask on PIC2
+;
+
+ in al,PIC2_PORT1
+ shl eax, 8
+
+;
+; Get interrupt Mask on PIC1
+;
+
+ in al,PIC1_PORT1
+ push eax ; save the masks
+ mov eax, NOT (( 1 SHL PIC_SLAVE_IRQ) + (1 SHL RTCIRQ))
+ ; Mask all the irqs except irq 2 and 8
+ SET_IRQ_MASK ; Set 8259's int mask register
+
+;
+; Since RTC interrupt will come from IRQ 8, we need to
+; Save original irq 8 descriptor and set the descriptor to point to
+; our own handler.
+;
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov ecx, [ebp-6] ; (ecx)->IDT
+
+ mov eax, (RTCIRQ+PRIMARY_VECTOR_BASE)
+
+ shl eax, 3 ; 8 bytes per IDT entry
+ add ecx, eax ; now at the correct IDT RTC entry
+
+ push dword ptr [ecx] ; (TOS) = original desc of IRQ 8
+ push dword ptr [ecx + 4] ; each descriptor has 8 bytes
+
+ ;
+ ; Pushing the appropriate entry address now (instead of
+ ; the IDT start address later) to make the pop at the end simpler.
+ ;
+ push ecx ; (TOS) -> &IDT[HalProfileVector]
+
+ mov eax, offset FLAT:RealTimeClockHandler
+
+ mov word ptr [ecx], ax ; Lower half of handler addr
+ mov word ptr [ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [ecx+4], D_INT032 ; 386 interrupt gate
+
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [ecx+6], ax
+
+ mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ mov dword ptr [KiseInterruptCount], 0
+
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Now enable the interrupt and start the counter
+; (As a matter of fact, only IRQ8 can come through.)
+;
+ xor eax, eax ; (eax) = 0, initialize loopcount
+ALIGN 16
+ sti
+ jmp kise10
+
+ALIGN 16
+kise10:
+ sub eax, 1 ; increment the loopcount
+ jnz short kise10
+
+if DBG
+;
+; Counter overflowed
+;
+
+ stdCall _DbgBreakPoint
+endif
+ jmp short kise10
+
+;
+; Our RealTimeClock interrupt handler. The control comes here through
+; irq 8.
+; Note: we discard first real time clock interrupt and compute the
+; permicrosecond loopcount on receiving of the second real time
+; interrupt. This is because the first interrupt is generated
+; based on the previous real time tick interval.
+;
+
+RealTimeClockHandler:
+
+ inc dword ptr KiseInterruptCount ; increment interrupt count
+ cmp dword ptr KiseInterruptCount,1 ; Is this the first interrupt?
+ jnz short kise25 ; no, its the second go process it
+ pop eax ; get rid of original ret addr
+ push offset FLAT:kise10 ; set new return addr
+
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+;
+; Dismiss the interrupt.
+;
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ xor eax, eax ; reset loop counter
+
+ iretd
+
+kise25:
+
+;
+; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount
+;
+
+if DBG
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint
+
+endif
+ ; never return
+;
+; ** End temporay code
+;
+
+kise30:
+ neg eax
+ xor edx, edx ; (edx:eax) = divident
+ mov ecx, PeriodInMicroSecond; (ecx) = time spent in the loop
+ div ecx ; (eax) = loop count per microsecond
+ cmp edx, 0 ; Is remainder =0?
+ jz short kise40 ; yes, go kise40
+ inc eax ; increment loopcount by 1
+kise40:
+ mov PCR[PcStallScaleFactor], eax
+ mov HalpP0BugBugStallCount, eax
+
+;
+; Reset return address to kexit
+;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+ mov eax, (HIGHEST_LEVEL_FOR_8259 - RTCIRQ)
+
+;
+; Shutdown periodic interrupt
+;
+ stdCall _HalpAcquireCmosSpinLock
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_DISABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending interrupt
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Dismiss the interrupt.
+;
+ mov eax, RTCIRQ
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+ iretd
+
+kexit: ; Interrupts are disabled
+ pop ecx ; (ecx) -> &IDT[HalProfileVector]
+ pop [ecx+4] ; restore higher half of RTC desc
+ pop [ecx] ; restore lower half of RTC desc
+
+ pop eax ; (eax) = origianl 8259 int masks
+ SET_IRQ_MASK
+
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+ stdRET _HalpInitializeStallExecution
+
+stdENDP _HalpInitializeStallExecution
+
+INIT ends
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+
+cPublicProc _KeStallExecutionProcessor ,1
+cPublicFpo 1, 0
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ ; loop count for the processor
+ mul ecx ; (eax) = desired loop count
+
+if DBG
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short @f
+ int 3
+
+@@: cmp eax,0
+ jnz short @f
+ int 3
+@@:
+endif
+ALIGN 16
+ jmp kese05
+
+ALIGN 16
+kese05: sub eax, 1 ; (eax) = (eax) - 1
+ jnz short kese05
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halncr/i386/ixswint.asm b/private/ntos/nthals/halncr/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixswint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixswint.asm
diff --git a/private/ntos/nthals/halncr/i386/ixsysbus.c b/private/ntos/nthals/halncr/i386/ixsysbus.c
new file mode 100644
index 000000000..b4776da76
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixsysbus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixsysbus.c"
diff --git a/private/ntos/nthals/halncr/i386/ixthunk.c b/private/ntos/nthals/halncr/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halncr/i386/ixusage.c b/private/ntos/nthals/halncr/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halncr/i386/ncr.h b/private/ntos/nthals/halncr/i386/ncr.h
new file mode 100644
index 000000000..2963c59fc
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncr.h
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncr.h
+
+Author:
+
+Abstract:
+
+ System Load Equates for NCR multiprocessing hardware based on Voyager
+ architecture.
+
+++*/
+
+
+#define NCR_VERSION_NUMBER 35001
+
+#define NCR_MAX_NUMBER_PROCESSORS 16
+#define NCR_MAX_NUMBER_DYADIC_PROCESSORS 8
+#define NCR_MAX_NUMBER_QUAD_PROCESSORS 16
+#define NCR_CPI_VECTOR_BASE 0x60
+#define NCR_QIC_CPI_VECTOR_BASE 0x70
+#define NCR_QIC_SPURIOUS_VECTOR 0x50
+#define NCR_IPI_LEVEL_CPI 0
+#define NCR_CLOCK_LEVEL_CPI 2
+#define NCR_SYSTEM_INTERRUPT 8
+#define NCR_SINGLE_BIT_ERROR 0xF
+
+#define NCR_SMCA_9 1
+#define NCR_SMCA_11_3 3
+#define NCR_SMCA_12_4 4
+#define NCR_SMCA_13_5 5
+#define NCR_SMCA_14_6 6
+#define NCR_SMCA_15_7 7
+
+//
+// CPU flags
+//
+
+#define CPU_DYADIC 0x1
+#define CPU_QUAD 0x2
+#define CPU_EXTENDED 0x4
+
+
+typedef struct ProcessorPrivateData {
+ unsigned long MyProcessorFlags;
+ unsigned long MyLogicalMask;
+ unsigned long MyLogicalNumber;
+ unsigned long MyPICsIrql;
+ unsigned long MyAcquireCount;
+ unsigned long MyLockColl;
+ unsigned long MySpinCount;
+ unsigned long MySpinTSCLowDWord;
+ unsigned long MySpinTSCHighDWord;
+ unsigned long MyHighestSpinCount;
+ unsigned long MyHighestLock;
+ unsigned long MyHighestAddress;
+ unsigned long MyClaimedIRQs;
+ unsigned long MyClaimedIRQsCount;
+} *PProcessorPrivateData;
+
+/*
+ * Values for NCRPlatform
+ */
+#define NCR3450 0x35333433
+#define NCR3550 0x30353834
+#define NCR3360 0x33333630
+
+
+
+
+/*
+ * This structure is used to Send QIC Cross Processor Interrupts (CPI)
+ */
+
+typedef struct _QIC_IPI {
+ struct _QIC_LEVEL {
+ ULONG Ipi;
+ ULONG Filler[7];
+ } QIC_LEVEL[8];
+} QIC_IPI, *PQIC_IPI;
+
+
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint a
+#else
+#define DBGMSG(a)
+#endif
diff --git a/private/ntos/nthals/halncr/i386/ncr.inc b/private/ntos/nthals/halncr/i386/ncr.inc
new file mode 100644
index 000000000..59d181e9f
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncr.inc
@@ -0,0 +1,453 @@
+;
+; Copyright (c) 1992 NCR Corporation
+;
+; Module Name:
+;
+; ncr.inc
+;
+; Abstract:
+;
+; This module contains the equates for defining the system memory
+; map for NCR Multiprocessor systems using the Voyager architecture
+; (3450/3550)
+;
+; Author:
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+;
+; Maximum number of processors include boot processor and non-boot processors
+
+NCR_MAX_NUMBER_PROCESSORS equ 16
+NCR_MAX_NUMBER_DYADIC_PROCESSORS equ 8
+NCR_MAX_NUMBER_QUAD_PROCESSORS equ 16
+
+;
+;
+
+NCR_CPI_VECTOR_BASE equ 60H
+NCR_QIC_CPI_VECTOR_BASE equ 70H
+NCR_SECONDARY_VECTOR_BASE equ 40H
+NCR_QIC_SPURIOUS_VECTOR equ 50H
+NCR_IPI_LEVEL_CPI equ 0 ; cpi used for ipi
+NCR_CLOCK_LEVEL_CPI equ 2 ; cpi used for clock broadcast
+NCR_SYSTEM_INTERRUPT equ 8 ; system interrupt
+NCR_SINGLE_BIT_ERROR equ 0FH ; single bit error
+NCR_STARTUP_CPI equ 2 ; cpi used to start nonboot procs
+NCR_STARTUP_VECTOR_VIC equ (NCR_STARTUP_CPI+NCR_CPI_VECTOR_BASE) * 4
+NCR_STARTUP_VECTOR_QIC equ (NCR_STARTUP_CPI+NCR_QIC_CPI_VECTOR_BASE) * 4
+
+;
+; CPU flags
+;
+
+CPU_DYADIC equ 01h
+CPU_QUAD equ 02h
+CPU_EXTENDED equ 04h
+
+
+;
+; Define Voyager Configuration and Test (CAT) register set
+;
+
+CAT_BASE_ADDRESS equ 0F800h ; configuration register base
+CAT_ID_SELECT_PORT equ 97h ; ASIC select register
+
+_CAT_REGISTERS struc
+ cat_CatIdReg db ? ; Offset 0x00
+ cat_AsicInformationReg db ? ; Offset 0x01
+ cat_ControlReg db ? ; Offset 0x02
+ cat_DataPort1 db ? ; Offset 0x03
+ cat_ConfigurationReg db ? ; Offset 0x04
+ cat_Reserved0 db ?
+ cat_SubAddressRegLsb db ? ; Offset 0x06
+ cat_SubAddressRegMsb db ? ; Offset 0x07
+ cat_DataPort2 db ? ; Offset 0x08
+ cat_DataPort3 db ? ; Offset 0x09
+ cat_PDataRead db ? ; Offset 0x0a
+ cat_Reserved1 db 3 dup(?)
+ cat_JtagCommandReg db ? ; Offset 0x0e
+ cat_StatusReg db ? ; Offset 0x0f
+_CAT_REGISTERS ends
+
+
+MCADDR_CAT_ID equ 0C0h
+
+CAT_READ macro reg
+ mov dx, CAT_BASE_ADDRESS+cat_&reg
+ in al, dx
+ endm
+
+CAT_WRITE macro reg, dbyte
+ ifnb <dbyte>
+ mov al, dbyte
+ endif
+ mov dx, CAT_BASE_ADDRESS+cat_&reg
+ out dx, al
+ endm
+
+
+;++
+;
+; SET_IRQ_MASK
+;
+; Macro Description:
+;
+; This macro sets 8259 interrupt mask register with the mask
+; passed from eax register.
+;
+; Note: Currently, only two 8259s are support. As a result,
+; only ax contains valid mask.
+;
+; Arguments:
+;
+; (eax) = mask for setting 8259 interrupt mask register
+;
+;--
+
+
+QIC_IRQ_ENABLE_MASK equ 0fah ; Mask for enabling the disabling interrupts on Qic
+
+
+SET_IRQ_MASK macro
+local a,b,c ; define local labels
+
+;
+; Turn off P5 counters
+;
+; push eax
+; mov ecx,011h
+; db 0fh,32h
+; push eax
+; and eax,0fe3ffe3fh
+; mov edx,0
+; db 0fh,30h
+; pop eax
+;
+; mov edx, eax
+; pop eax
+; push edx
+
+ mov edx, PCR[PcHal.PcrMyProcessorFlags]
+ test edx, CPU_QUAD
+ jnz short b
+
+ out PIC1_PORT1, al ; set master 8259 mask
+ shr eax, 8 ; shift slave 8259 mask to al
+ out PIC2_PORT1, al ; set slave 8259 mask
+
+ jmp short c
+
+b:
+ test edx, CPU_EXTENDED
+ jz short a
+
+ out PIC1_PORT1, al ; set master 8259 mask
+ ror eax,8 ; set slave pic mask
+ out PIC2_PORT1, al ; set slave 8259 mask
+ rol eax,8 ; restore eax for Qic operation
+a:
+ or al,QIC_IRQ_ENABLE_MASK
+ QIC_WRITE QicMask1
+
+c:
+;
+; Turn counters back on
+;
+; pop eax
+; mov ecx,011h
+; mov edx,0
+; db 0fh,30h
+;
+endm
+
+
+
+;
+; Define Voyager Interrupt Controller (VIC) register set
+;
+
+VIC_BASE_ADDRESS equ 0FC00h ; base address for VIC registers
+QIC_BASE_ADDRESS equ 0FC70h ; base address for QIC registers
+
+
+_VIC_REGISTERS struc
+ vic_CpiLevel0Reg db ? ; Offset 0x00
+ vic_CpiLevel1Reg db ? ; Offset 0x01
+ vic_Reserved0 db 6 dup (?)
+ vic_CpiLevel2Reg db ? ; Offset 0x08
+ vic_CpiLevel3Reg db ? ; Offset 0x09
+ vic_Reserved1 db 6 dup (?)
+ vic_CpiLevel4Reg db ? ; Offset 0x10
+ vic_CpiLevel5Reg db ? ; Offset 0x11
+ vic_Reserved2 db 6 dup (?)
+ vic_CpiLevel6Reg db ? ; Offset 0x18
+ vic_CpiLevel7Reg db ? ; Offset 0x19
+ vic_Reserved3 db 6 dup (?)
+ vic_ActivityReg db ? ; Offset 0x20
+ vic_ProcessorIdReg db ? ; Offset 0x21
+ vic_Reserved4 db 6 dup (?)
+ vic_ProcessorAliveReg db ? ; Offset 0x28
+ vic_ProcessorWhoAmIReg db ? ; Offset 0x29
+ vic_Reserved5 db 6 dup (?)
+ vic_FakeInterruptRegLsb db ? ; Offset 0x30
+ vic_FakeInterruptRegMsb db ? ; Offset 0x31
+ vic_Reserved6 db 6 dup (?)
+ vic_ClaimRegLsb db ? ; Offset 0x38
+ vic_ClaimRegMsb db ? ; Offset 0x39
+ vic_Reserved9 db 6 dup (?)
+ vic_SpareInterruptReg db ? ; Offset 0x40
+ vic_CpiVectorBaseReg db ? ; Offset 0x41
+ vic_Reserved10 db 6 dup (?)
+ vic_ExtMasterVectorBaseReg db ? ; Offset 0x48
+ vic_ExtSlaveVectorBaseReg db ? ; Offset 0x49
+ vic_Reserved11 db 6 dup (?)
+ vic_AddressOffsetReg db ? ; Offset 0x50
+ vic_ParityErrorReg db ? ; Offset 0x51
+ vic_Reserved12 db 6 dup (?)
+ vic_AsicConfigurationReg db ? ; Offset 0x58
+ vic_RevisionLevelReg db ? ; Offset 0x59
+ vic_Reserved13 db 6 dup (?)
+ vic_RedirectIrqReg0 db ? ; Offset 0x60
+ vic_RedirectIrqReg1 db ? ; Offset 0x61
+_VIC_REGISTERS ends
+
+
+_QIC_REGISTERS struc
+ qic_Configuration db ? ; Offset 0x00
+ qic_ProcessorId db ? ; Offset 0x01
+ qic_ExtendedProcessorSelect db ? ; Offset 0x02
+ qic_SpuriousVectorReg db ? ; Offset 0x03
+ qic_Reserved1 db 4 dup (?)
+ qic_PerformanceTimerVector db ? ; Offset 0x08
+ qic_VicCpiVectorBaseReg db ? ; Offset 0x09
+ qic_QuadCpiVectorBaseReg db ? ; Offset 0x0a
+ qic_LocalMemoryErrorVectorReg db ? ; Offset 0x0b
+ qic_Reserved2 db 4 dup (?)
+ qic_QicMask0 db ? ; Offset 0x10
+ qic_QicMask1 db ? ; Offset 0x11
+ qic_QicIrrReg0 db ? ; Offset 0x12
+ qic_QicIrrReg1 db ? ; Offset 0x13
+ qic_Reserved3 db 4 dup (?)
+ qic_ProcessorWhoAmIReg db ? ; Offset 0x18
+ qic_Reserved4 db 1 dup (?)
+ qic_Clear0Reg db ? ; Offset 0x1a
+ qic_Clear1Reg db ? ; Offset 0x1b
+ qic_Reserved5 db 4 dup (?)
+ qic_PerformanceTimerInitialCount db ? ; Offset 0x20
+ qic_PerformanceTimerCurrentCount db ? ; Offset 0x22
+ qic_Reserved6 db 45 dup (?)
+ qic_QuadCpi0StatusReg db ? ; Offset 0x50
+ qic_Reserved7 db 7 dup (?)
+ qic_QuadCpi1StatusReg db ? ; Offset 0x58
+ qic_Reserved8 db 7 dup (?)
+ qic_QuadCpi2StatusReg db ? ; Offset 0x60
+ qic_Reserved9 db 7 dup (?)
+ qic_QuadCpi3StatusReg db ? ; Offset 0x68
+ qic_Reserved10 db 7 dup (?)
+ qic_QuadCpi4StatusReg db ? ; Offset 0x70
+ qic_Reserved11 db 7 dup (?)
+ qic_QuadCpi5StatusReg db ? ; Offset 0x78
+ qic_Reserved12 db 7 dup (?)
+ qic_QuadCpi6StatusReg db ? ; Offset 0x80
+ qic_Reserved13 db 7 dup (?)
+ qic_QuadCpi7StatusReg db ? ; Offset 0x88
+_QIC_REGISTERS ends
+
+
+
+
+
+;
+; Processor Identification register definition
+;
+
+ProcessorIdNumber equ 07h
+ProcessorIdSelect equ 08h
+
+;
+; Cross Processor Interrupt Base Vector register definition
+;
+
+InterruptType equ 008h ; 0 = cpi, 1 = system int or
+CpiBaseVectorMask equ 0F0h ; single bit error
+
+
+;
+; Read/Write VIC macro definitions
+;
+
+VIC_READ macro reg
+ mov dx, VIC_BASE_ADDRESS+vic_&reg
+ in al, dx
+ endm
+
+VIC_WRITE macro reg, dbyte
+ ifnb <dbyte>
+ mov al, dbyte
+ endif
+ mov dx, VIC_BASE_ADDRESS+vic_&reg
+ out dx, al
+ endm
+
+
+;
+; Read the who_am_i register. If this is a Dyadic then clear carry flag and return who_am_i
+; if this is a Quad then set carry flag and translate who_am_i
+;
+
+
+WHO_AM_I macro
+local a,b
+ mov dx, VIC_BASE_ADDRESS+vic_ProcessorWhoAmIReg
+ in al,dx
+ movzx eax, al
+ mov dl,al
+ and edx,0c0h ; check for quad processor
+ cmp edx,0c0h
+ jne short a
+
+;
+; this is a Quad
+;
+
+ mov dl,al
+ and edx,0fh ; this must change for 32 way currently ccvv is left
+ push ecx
+
+ mov eax,1h
+ mov ecx,edx
+ shr ecx,2h ; get shift for processor bit
+ shl eax,cl ; now put processor bit in right position
+ mov ecx,edx ; now lets adjust for processor slot
+ and ecx,3h ; now isolate voyager slot number
+ shl ecx,2h ; 1 slot is 4 processors
+ shl eax,cl ; now mask is corrent
+
+ pop ecx
+ stc
+ jmp short b
+a:
+;
+; this is a Dyadic
+;
+ push ebx
+ push ecx
+ stdCall _NCRTranslateCMOSMask, <eax>
+ pop ecx
+ pop ebx
+
+ clc
+b:
+ endm
+
+
+
+
+;
+; Translate the Processors logical mask into a VIC hardware mask for sending CPIs
+; to processors on Dyadic boards
+;
+
+
+TRANSLATE_LOGICAL_TO_VIC macro
+local loop,almost,done
+ push ebx ; save registers
+
+ xor ebx,ebx ; set logical processor number to zero
+ dec ebx ; dec logical so we and inc right away
+ xor edx,edx ; clear VIC mask
+ align dword
+loop:
+ inc ebx ; logical processor number
+ shr eax,1 ; shift logical mask into carry
+ jz short almost ; if logical mask zero we are almost done
+ jnb short loop ; if this processor mask not set check next
+ or edx,dword ptr _NCRLogicalNumberToPhysicalMask[ebx*4] ; or in the VIC mask for this processor
+
+ jmp short loop
+almost:
+ jnb short done ; if logical bit not set we are done
+ or edx,dword ptr _NCRLogicalNumberToPhysicalMask[ebx*4] ; or in the VIC mask for this processor
+done:
+ mov eax,edx ; put VIC mask into eax for return value
+
+ pop ebx ; restore registers
+ endm
+
+
+
+
+PROCESSOR_SLOT macro
+ bsf eax,eax
+ shr eax,2
+ endm
+
+
+;
+; Read/Write QIC macro definitions
+;
+
+QIC_READ macro reg
+ mov dx, QIC_BASE_ADDRESS+qic_&reg
+ in al, dx
+ endm
+
+QIC_WRITE macro reg, dbyte
+ ifnb <dbyte>
+ mov al, dbyte
+ endif
+ mov dx, QIC_BASE_ADDRESS+qic_&reg
+ out dx, al
+ endm
+
+
+
+;; Constants
+
+TRUE equ 1
+FALSE equ 0
+
+
+;
+; the kernel reserved space for us in our pcr. this structure defines
+; that space. it MUST coincide with the corresponding 'C' structure.
+;
+
+PcrE struc
+ PcrMyProcessorFlags dd 0 ; Processor Flags that Indicate type of processor
+ PcrMyLogicalMask dd 0 ; logical processor mask
+ PcrMyLogicalNumber dd 0 ; logical processor number
+ PcrMyPICsIrql dd 0 ; last Irql written to PICs
+ PcrMyAcquireCount dd 0
+ PcrMyLockColl dd 0
+ PcrMySpinCount dd 0
+
+ PcrMySpinTSCLowDWord dd 0
+ PcrMySpinTSCHighDWord dd 0
+
+
+ PcrMyHighestSpinCount dd 0
+ PcrMyHighestLock dd 0
+ PcrMyHighestAddress dd 0
+ PcrMyClaimedIRQs dd 0
+ PcrMyClaimedIRQsCount dd 0
+PcrE ends
+
+;
+; Values for NCRPlatform
+;
+NCR3450 equ 35333433H
+NCR3550 equ 30353834H
+NCR3360 equ 33333630H
+
+;
+; functions to turn on and off the performance counters
+;
+
diff --git a/private/ntos/nthals/halncr/i386/ncrarb.h b/private/ntos/nthals/halncr/i386/ncrarb.h
new file mode 100644
index 000000000..85929330a
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrarb.h
@@ -0,0 +1,157 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncrarb.h
+
+Author:
+
+Abstract:
+
+ System equates for dealing with the NCR Arbiter ASIC.
+
+++*/
+
+#ifndef _NCRARB_
+#define _NCRARB_
+
+
+/* Level 4 Arbiter ASIC ID */
+#define SBA_ID_L4 0xC1
+
+/* Arbiter Register Addresses and their bit definitions */
+
+#define SBA_Dev_Id 0x00
+#define SBA_Dev_Info 0x01
+#define SBA_CAT_Cntl1 0x02
+#define SBA_Extended_Reg_Data 0x03
+#define SBA_Extended_Reg_Addr 0x06
+
+#define SBA_Intr_Stat1 0x08
+# define SBA_Proto_Err_A 0x80
+# define SBA_Proto_Err_B 0x40
+# define SBA_Toe_A 0x20
+# define SBA_Toe_B 0x10
+# define SBA_Elatchd_A 0x08
+# define SBA_Elatchd_B 0x04
+# define SBA_Par_Int_A 0x02
+# define SBA_Par_Int_B 0x01
+
+#define SBA_Intr_Stat2 0x09
+# define SBA_Reserved 0x80
+# define SBA_Sw_Nmi 0x40
+# define SBA_Error_Int 0x20
+# define SBA_Power_Fail 0x10
+# define SBA_Exp_Cougar_Nmi 0x08
+# define SBA_Exp_Mc_Toe 0x04
+# define SBA_Cougar_Nmi 0x02
+# define SBA_Mc_Toe 0x01
+
+#define SBA_SysInt_Enables 0x0A
+# define SBA_Toe_S 0x80
+# define SBA_Par_Int_S 0x40
+# define SBA_Err_Int_S 0x20
+# define SBA_Power_Fail_S 0x10
+# define SBA_Exp_Cougar_Nmi_S 0x08
+# define SBA_Exp_Mc_Toe_S 0x04
+# define SBA_Cougar_Nmi_S 0x02
+# define SBA_Mc_Toe_S 0x01
+
+#define SBA_GNMI_Enables 0x0B
+# define SBA_Toe_G 0x80
+# define SBA_Par_Int_G 0x40
+# define SBA_Err_Int_G 0x20
+# define SBA_Power_Fail_G 0x10
+# define SBA_Exp_Cougar_Nmi_G 0x08
+# define SBA_Exp_Mc_Toe_G 0x04
+# define SBA_Cougar_Nmi_G 0x02
+# define SBA_Mc_Toe_G 0x01
+
+#define SBA_Control 0x0C
+
+#define SBA_Intr_Clear 0x0D
+# define SBA_Err_Int_Clr 0x10
+# define SBA_Par_Clr_A 0x08
+# define SBA_Par_Clr_B 0x04
+# define SBA_Err_Clr_A 0x02
+# define SBA_Err_Clr_B 0x01
+
+#define SBA_Misc 0x0E
+
+#define SBA_CAT_Cntl2 0x0F
+# define SBA_Reset_Not_Compl 0x80
+# define SBA_Cat_Inst_Perr 0x08
+
+/* Extended Registers; Accessed via SBA_Extended_Reg_Data &
+** SBA_Extended_Reg_Data above
+*/
+
+#define SBA_Size_Subaddress 0x08
+
+#define SBA_Ext_Err0_BusA 0x00
+#define SBA_Ext_Err1_BusA 0x01
+#define SBA_Ext_Err2_BusA 0x02
+# define SBA_ErrParInt 0x20
+#define SBA_Ext_Err3_BusA 0x03
+
+#define SBA_Ext_Err4_BusB 0x04
+#define SBA_Ext_Err5_BusB 0x05
+#define SBA_Ext_Err6_BusB 0x06
+#define SBA_Ext_Err7_BusB 0x07
+
+
+
+
+/* Valuable Arbiter error information to be captured when SYS_INT or
+** G_NMI occurs.
+*/
+typedef struct SBA_INFO {
+ UCHAR Flag; /* for state of information in struct */
+ union {
+ CAT_REGISTERS CatRegs;
+ struct {
+ UCHAR Dummy0;
+ UCHAR Dummy1;
+ UCHAR Dummy2;
+ UCHAR Dummy3;
+ UCHAR Dummy4;
+ UCHAR Dummy5;
+ UCHAR Dummy6;
+ UCHAR Dummy7;
+ UCHAR InterruptStatus1;
+ UCHAR InterruptStatus2;
+ UCHAR SysIntEnables;
+ UCHAR GlobalNmiEnables;
+ UCHAR ArbControl;
+ UCHAR InterruptClear;
+ UCHAR Misc;
+ UCHAR DummyF;
+ } ArbRegisters;
+ } CatRegisters;
+ UCHAR ExtError0BusA; /* for PAR_INT */
+ UCHAR ExtError1BusA; /* for PAR_INT */
+ UCHAR ExtError2BusA; /* for ERROR_L */
+ UCHAR ExtError3BusA; /* for ERROR_L */
+ UCHAR ExtError4BusB; /* for PAR_INT */
+ UCHAR ExtError5BusB; /* for PAR_INT */
+ UCHAR ExtError6BusB; /* for ERROR_L */
+ UCHAR ExtError7BusB; /* for ERROR_L */
+} SBA_INFO, *PSBA_INFO;
+
+/* defines for union referencing */
+#define Intr_Stat1 CatRegisters.ArbRegisters.InterruptStatus1
+#define Intr_Stat2 CatRegisters.ArbRegisters.InterruptStatus2
+#define SysIntEnables CatRegisters.ArbRegisters.SysIntEnables
+#define GNMIEnables CatRegisters.ArbRegisters.GlobalNmiEnables
+#define ArbControl CatRegisters.ArbRegisters.ArbControl
+#define InterruptClear CatRegisters.ArbRegisters.InterruptClear
+#define Misc CatRegisters.ArbRegisters.Misc
+
+
+#endif // _NCRARB_
+
+
+
diff --git a/private/ntos/nthals/halncr/i386/ncrcat.c b/private/ntos/nthals/halncr/i386/ncrcat.c
new file mode 100644
index 000000000..c0680ee4a
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrcat.c
@@ -0,0 +1,3223 @@
+/*++
+
+Copyright (c) 1993 NCR Corporation
+
+Module Name:
+
+ ncrcat.c
+
+Abstract:
+
+ Provides the interface to the NCR CAT bus.
+
+Author:
+
+ Rick Ulmer (rick.ulmer@columbiasc.ncr.com) 29-Jul-1993
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "ncr.h"
+#include "ncrcat.h"
+#include "ncrcatp.h"
+#include "ncrpsi.h"
+#include "ncrarb.h"
+
+
+VOID HalpAcquireCatBusSpinLock();
+VOID HalpReleaseCatBusSpinLock();
+
+
+
+PMODULE NCRCatModuleList = NULL;
+PMODULE NCRCatModule = NULL;
+USHORT NCRCatBasePort;
+USHORT NCRCatCommandPort;
+USHORT NCRCatDataPort;
+SHORT NCRMinModuleAddress = 0;
+SHORT NCRMaxModuleAddress = PSI;
+
+//
+// Used to signal HalReturnToFirmware to powerdown instead of reboot
+//
+BOOLEAN NCRPowerOffSystem = FALSE;
+
+
+
+extern ULONG NCRLarcEnabledPages[]; // LARC size by Voyager slot
+
+
+/*
+ * Function prototypes
+ */
+
+
+PMODULE
+NCRCatModulePresent(
+ IN UCHAR ModuleAddress
+ );
+
+
+UCHAR
+NCRCatSubModulePresent(
+ );
+
+
+PUCHAR
+NCRCatReadModuleData(
+ );
+
+
+VOID
+NCRCatExtractSetupInformation(
+ PUCHAR EEpromData
+ );
+
+
+VOID
+NCRCatDefaultSetupInformation(
+ );
+
+
+PMODULE
+NCRCatSelect(
+ UCHAR ModuleAddress
+ );
+
+
+PASIC
+NCRCatGetAsic(
+ UCHAR AsicId
+ );
+
+
+LONG
+NCRCatConnect(
+ );
+
+
+LONG
+NCRCatDisconnect(
+ );
+
+
+VOID
+NCRCatRestoreState(
+ );
+
+
+LONG
+NCRCatAutoIncrement(
+ PASIC Asic
+ );
+
+
+LONG
+NCRCatNoAutoIncrement(
+ PASIC Asic
+ );
+
+
+LONG
+NCRCatSubaddressSetup(
+ PASIC Asic,
+ USHORT Subaddress
+ );
+
+
+LONG
+NCRCatRegisterIo(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ );
+
+
+LONG
+NCRCatSubaddressIo(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ );
+
+
+LONG
+NCRCatRead(
+ PASIC Asic,
+ UCHAR RegisterNumber,
+ PUCHAR Buffer
+ );
+
+
+LONG
+NCRCatWrite(
+ PASIC Asic,
+ UCHAR RegisterNumber,
+ PUCHAR Data
+ );
+
+
+LONG
+NCRCatSubaddressRead(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ );
+
+
+LONG
+NCRCatWriteComplete(
+ PASIC Asic,
+ USHORT Address,
+ UCHAR Expected
+ );
+
+
+LONG
+NCRCatSubaddressWrite(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ );
+
+
+UCHAR
+NCRCatInstruction(
+ UCHAR RegisterNumber,
+ UCHAR Operation
+ );
+
+
+LONG
+NCRCatSendInstruction(
+ PASIC Asic,
+ UCHAR Instruction
+ );
+
+
+VOID
+NCRCatBuildHeader(
+ PUCHAR Header,
+ SHORT HeaderBytes,
+ SHORT LargestRegister,
+ SHORT SmallestRegister
+ );
+
+
+LONG
+NCRCatSendData(
+ PASIC Aisc,
+ PUCHAR Data,
+ LONG InternalRegister,
+ LONG ExternalSpecial
+ );
+
+
+VOID
+NCRCatInsertData(
+ PUCHAR String,
+ SHORT StartBit,
+ PUCHAR Data,
+ SHORT NumberOfBits
+ );
+
+
+VOID
+NCRCatExtractData(
+ PUCHAR String,
+ SHORT StartBit,
+ PUCHAR Data,
+ SHORT NumberOfBits
+ );
+
+
+LONG
+NCRCatShiftOutData(
+ PUCHAR Data,
+ SHORT DataBytes,
+ SHORT HeaderBytes,
+ SHORT PadBits
+ );
+
+
+LONG
+NCRCatGetData(
+ PASIC Asic,
+ PUCHAR Data,
+ LONG InternalRegister
+ );
+
+
+LONG
+NCRCatIoLpb(
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ );
+
+
+
+VOID
+NCRCatModuleName (
+ LONG Module,
+ PUNICODE_STRING ModuleName
+ );
+
+
+VOID
+NCRCatAsicName (
+ LONG Module,
+ LONG Asic,
+ PUNICODE_STRING AsicName
+ );
+
+
+
+/*
+ * End of function prototypes.
+ */
+
+
+BOOLEAN
+HalCatBusAvailable (
+ )
+
+/*++
+
+Routine Description:
+ Check to see if the Cat Bus is available on this system. If no modules
+ are found then the Cat Bus is not available.
+
+Arguments:
+ None.
+
+Return Value:
+ TRUE - Cat Bus is available.
+
+ FALSE - Cat Bus is not available
+
+--*/
+
+{
+ if (NCRCatModuleList) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+
+
+LONG
+HalCatBusIo (
+ IN PCAT_CONTROL CatControl,
+ IN OUT PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+ CatControl -
+
+ Buffer -
+
+Return Value:
+
+--*/
+
+{
+LONG status;
+#ifdef CATDEBUG
+ULONG i;
+PUCHAR pos;
+#endif // CATDEBUG
+
+/*
+ * Get the Cat bus lock.
+ */
+
+HalpAcquireCatBusSpinLock();
+
+/*
+ * Perform the Cat bus function
+ */
+
+status = HalpCatBusIo(CatControl,Buffer);
+
+/*
+ * Release the Cat Bus lock.
+ */
+
+HalpReleaseCatBusSpinLock();
+
+#ifdef CATDEBUG
+DBGMSG(("HalCatBusIo: Module 0x%x, Asic 0x%x, Address 0x%x\n", CatControl->Module, CatControl->Asic, CatControl->Address));
+
+if (status == CATNOERR) {
+ if ((CatControl->Command == READ_REGISTER) || (CatControl->Command == READ_SUBADDR))
+ {
+ DBGMSG(("\tRead Data: "));
+ pos = Buffer;
+ for ( i = 0; i < CatControl->NumberOfBytes; i++ )
+ {
+ DBGMSG(("0x%2x ", *pos++));
+ }
+ DBGMSG(("\n"));
+ }
+ else
+ {
+ DBGMSG(("\tWrote Data: "));
+ pos = Buffer;
+ for ( i = 0; i < CatControl->NumberOfBytes; i++ )
+ {
+ DBGMSG(("0x%2x ", *pos++));
+ }
+ DBGMSG(("\n"));
+ }
+ } else {
+ DBGMSG(("HalCatBusIo Error: Status = 0x%x\n", status));
+ }
+#endif // CATDEBUG
+
+
+return status;
+}
+
+
+VOID
+HalCatBusReset (
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ NCRCatRestoreState();
+}
+
+
+
+LONG
+HalpCatBusIo (
+ IN PCAT_CONTROL CatControl,
+ IN OUT PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PASIC asic;
+ LONG status;
+
+/*
+ * Special processing required since LPB is not on the CAT bus.
+ */
+
+ if (CatControl->Module == CAT_LPB_MODULE) {
+ status = NCRCatIoLpb(CatControl, Buffer);
+ return (status);
+ }
+
+/*RMU add code here to detect if the CAT bus has been reset.... */
+
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)DESELECT);
+
+ if ((NCRCatSelect(CatControl->Module)) == NULL)
+ status = CATNOMOD;
+ else if ((asic = NCRCatGetAsic(CatControl->Asic)) == NULL)
+ status = CATNOASIC;
+ else {
+ switch(CatControl->Command) {
+ case READ_REGISTER:
+ case WRITE_REGISTER:
+
+
+ status = NCRCatRegisterIo(asic, CatControl, Buffer);
+ break;
+
+ case READ_SUBADDR:
+ case WRITE_SUBADDR:
+ status = NCRCatSubaddressIo(asic, CatControl, Buffer);
+ break;
+ default:
+ status = CATINVAL;
+ break;
+ }
+ }
+
+/*
+ * UNIX guys took this out because of problems, so we will too.
+ *
+ if (status == CATIO) {
+ NCRCatRestoreState();
+ } else {
+*/
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+/*
+ }
+*/
+
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)DESELECT);
+ return (status);
+}
+
+VOID
+HalpInitializeCatBusDriver (
+ )
+
+/*++
+
+Routine Description:
+ Read the ASIC information for each module from the subaddress space
+ of the CAT_I ASIC (EEPROM).
+
+Arguments:
+ None
+
+Return Value:
+ None
+
+--*/
+
+{
+ PMODULE *module_p;
+ UCHAR module_address, number_submodule, *data;
+ CAT_CONTROL cat_control;
+ UCHAR cat_data;
+
+/*
+ * Get the Command and Data Port address
+ */
+
+ NCRCatBasePort = (USHORT)(READ_PORT_UCHAR((PUCHAR)BASE_PORT) << 8);
+ NCRCatCommandPort = NCRCatBasePort + COMMAND_OFFSET;
+ NCRCatDataPort = NCRCatBasePort + DATA_OFFSET;
+
+
+/*
+ * For each module that is present, build a data structure for the
+ * module and each of its ASICs.
+ */
+
+
+ for (module_p = &NCRCatModuleList, module_address = (UCHAR)NCRMinModuleAddress;
+ module_address <= (UCHAR)NCRMaxModuleAddress; module_address++) {
+
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)DESELECT);
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)module_address);
+
+
+ if (((NCRCatModule = *module_p = NCRCatModulePresent(module_address))) == NULL) {
+ continue;
+ }
+
+/*
+ * For 16way there way be submodules in addition to modules; if a
+ * submodule is present but the eeprom image is bad, just continue.
+ * This should never happen since firmware has already checked it.
+ */
+
+ if ((number_submodule = NCRCatSubModulePresent()) > 0) {
+
+ PMODULE parent_module;
+ UCHAR submodule_data, submodule;
+ LONG status;
+
+ parent_module = NCRCatModule;
+
+ for (NCRCatModule = NCRCatModule->SubModules, submodule = 1; NCRCatModule != NULL;
+ NCRCatModule = NCRCatModule->Next, submodule++) {
+
+ /*
+ * Select the submodule by reading the SUBMODSELECT register
+ * (register 8). The most significant bit (bit 7) is the hold
+ * bit and should always be set to zero; bits 2-6 should not be
+ * altered; bits 0-1 will contain the submod that is to be
+ * selected. An ASIC structure for the CAT_I was allocated by
+ * NCRCatModulePresent().
+ */
+
+ cat_control.Module = NCRCatModule->ModuleAddress;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = READ_REGISTER;
+ cat_control.Address = SUBMODSELECT;
+ cat_control.NumberOfBytes = 1;
+
+ status = NCRCatRegisterIo(NCRCatModule->Asic, &cat_control,
+ (PUCHAR)&submodule_data);
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (status)
+ continue;
+
+ submodule_data = (submodule_data & 0x7C) | submodule;
+
+ cat_control.Module = NCRCatModule->ModuleAddress;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.Address = SUBMODSELECT;
+ cat_control.NumberOfBytes = 1;
+
+ status = NCRCatRegisterIo(NCRCatModule->Asic, &cat_control,
+ (PUCHAR)&submodule_data);
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (status)
+ continue;
+
+ if ((data = NCRCatReadModuleData()) != NULL)
+ NCRCatExtractSetupInformation(data);
+ }
+ NCRCatModule = parent_module;
+ } else {
+ if ((data = NCRCatReadModuleData()) == NULL) {
+ NCRCatDefaultSetupInformation();
+ } else {
+ NCRCatExtractSetupInformation(data);
+ }
+ }
+ module_p = &NCRCatModule->Next;
+ }
+
+ *module_p = NULL;
+
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)DESELECT);
+
+
+//
+// Lets steer all hardware failures to NMI and not SYSINT
+// after this setup SYSINT should not occur.
+//
+
+ cat_control.Module = PRIMARYMC;
+ cat_control.Asic = PMC_ARB;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.Address = SBA_SysInt_Enables;
+ cat_control.NumberOfBytes = 1;
+
+ cat_data = 0x0; // Disable all SYS_INT interrupts
+
+ HalCatBusIo(&cat_control, &cat_data);
+
+ cat_control.Address = SBA_GNMI_Enables;
+ cat_control.NumberOfBytes = 1;
+
+ cat_data = 0xff; // Enable all G_NMI interrupts
+
+ HalCatBusIo(&cat_control, &cat_data);
+}
+
+
+PMODULE
+NCRCatModulePresent(
+ IN UCHAR ModuleAddress
+ )
+
+/*++
+
+Routine Description:
+ Determine if the module is present.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PMODULE module;
+ UCHAR input;
+
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)ModuleAddress);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)IRCYC);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)HEADER);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)0xAA);
+ input = READ_PORT_UCHAR((PUCHAR)NCRCatDataPort);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (input != HEADER) {
+ return (NULL);
+ }
+
+/*
+ * If the module is present, allocate a data structure and
+ * assign the default values so we can later do a read.
+ */
+
+ if ((module = (PMODULE)ExAllocatePool(NonPagedPool,sizeof(MODULE))) != NULL) {
+ RtlZeroMemory((PVOID)module,sizeof(MODULE));
+ module->ModuleAddress = ModuleAddress;
+ module->EEpromSize = EEPROM_SIZE;
+ module->ScanPathConnected = FALSE;
+ }
+ return (module);
+}
+
+
+UCHAR
+NCRCatSubModulePresent(
+ )
+
+/*++
+
+Routine Description:
+ Determine if the module has submodules for 16way.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ PMODULE submodule, *submodule_p;
+ CAT_CONTROL cat_control;
+ UCHAR number_submodules, submodule_present;
+ LONG status, i;
+
+ /*
+ * Submodules are unique to the processor boards.
+ */
+
+ if( !((NCRCatModule->ModuleAddress >= PROCESSOR0 &&
+ NCRCatModule->ModuleAddress <= PROCESSOR3) ||
+ (NCRCatModule->ModuleAddress >= PROCESSOR4 &&
+ NCRCatModule->ModuleAddress <= PROCESSOR7)) )
+ return(0);
+
+ /*
+ * Allocate and define an ASIC data structure for the CAT_I so we can
+ * do our first read.
+ */
+
+ if (NCRCatModule->Asic == NULL) {
+ if (!(NCRCatModule->Asic =
+ (PASIC)ExAllocatePool(NonPagedPool,sizeof(ASIC)))) {
+ return(0);
+ }
+ RtlZeroMemory((PVOID)NCRCatModule->Asic, sizeof(ASIC));
+ NCRCatModule->Asic->AsicId = CAT_I;
+ NCRCatModule->Asic->SubaddressSpace = SUBADDR_HI;
+ }
+ /*
+ * Read the SUBMODPRESENT register (register 9) of CAT_I to determine
+ * if there are any submodules present. If there are, allocate a
+ * module_t structure for each.
+ */
+
+ cat_control.Module = NCRCatModule->ModuleAddress;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = READ_REGISTER;
+ cat_control.Address = SUBMODPRESENT;
+ cat_control.NumberOfBytes = 1;
+
+ status = NCRCatRegisterIo(NCRCatModule->Asic, &cat_control, (PUCHAR)&number_submodules);
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (status)
+ return(0);
+
+ /*
+ * The two least significant bits of the SUBMODPRESENT register contain the
+ * number of submodules. These bits are active low.
+ * muoe941414 - jtt - 4/28/94
+ * These bits actually tell which submodules are present (each one
+ * representing a submodule). Submodpres is a bit place indicator
+ * of what modules are present (there is always a base board - 1 in
+ * lowest position).
+ */
+
+ number_submodules = ~(number_submodules | 0xFC);
+
+ if(number_submodules)
+ submodule_present = (number_submodules << BASE_BOARD_SHIFT) | BASE_BOARD_PRESENT;
+ else
+ submodule_present = 0;
+
+ /*
+ * For each submodule, allocate a submodule structure and fill in
+ * default values for the eeprom read.
+ */
+
+ submodule_p = &(NCRCatModule->SubModules);
+ for (i = 1; number_submodules != 0, i <= MAXSUBMOD; i++) {
+ /*
+ * muoe941414 - jtt - 4/28/94
+ * check first if submodule is present (corresponding bit set in
+ * submodpres string
+ */
+
+ if (!(submodule_present & (1 << (i - 1))))
+ continue;
+ if ((*submodule_p = submodule = (PMODULE)ExAllocatePool(NonPagedPool,sizeof(MODULE))) != NULL) {
+ /*
+ * The submodule address is kept in the three most significant bits of
+ * the module address.
+ */
+ RtlZeroMemory((PVOID)submodule, sizeof(MODULE));
+ submodule->ModuleAddress = ((i << 5) | NCRCatModule->ModuleAddress);
+ submodule->EEpromSize = EEPROM_SIZE;
+ submodule->ScanPathConnected = FALSE;
+ submodule_p = &submodule->Next;
+
+ /*
+ * Allocate a ASIC structure for CAT_I for each submodule; we will need
+ * it to select the submodle when we return to catinit_L5().
+ */
+ if (!(submodule->Asic = (PASIC)ExAllocatePool(NonPagedPool,sizeof(ASIC)))) {
+ ExFreePool((PVOID)submodule);
+ *submodule_p = NULL;
+ return(i - 1);
+ }
+ RtlZeroMemory((PVOID)submodule->Asic, sizeof(ASIC));
+ submodule->Asic->AsicId = CAT_I;
+ submodule->Asic->SubaddressSpace = SUBADDR_HI;
+ }
+ }
+ *submodule_p = NULL;
+ return(number_submodules);
+}
+
+
+
+PUCHAR
+NCRCatReadModuleData(
+ )
+
+/*++
+
+Routine Description:
+ Read the module data from the EEPROM and checksum it. If the checksum
+ fails for any reason, a NULL pointer is returned. If the checksum is
+ correct a pointer to the EEPROM data is returned.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ CAT_CONTROL cat_control;
+ PASIC asic;
+ USHORT xsum_end;
+ USHORT xsum;
+ PUSHORT data;
+ USHORT i;
+ USHORT size_of_eeprom;
+ LONG status;
+
+/*
+ * Allocate and define an ASIC data structure for the CAT_I so we can do our first read.
+ * If it is a processor board, the CAT_I will have been allocated by NCRCatSubModulePresent.
+ * If an error occurs, do not free the Asic structure since we may or may not have creatd it and
+ * it will be needed by NCRCatDefaultSetup if we fail.
+ */
+
+ if (NCRCatModule->Asic == NULL) {
+ if (!(asic = NCRCatModule->Asic = (PASIC)ExAllocatePool(NonPagedPool,sizeof(ASIC)))) {
+ return (NULL);
+ }
+ RtlZeroMemory((PVOID)asic, sizeof(ASIC));
+
+ asic->AsicId = CAT_I;
+ asic->SubaddressSpace = SUBADDR_HI;
+ } else {
+ asic = NCRCatModule->Asic;
+ }
+
+/*
+ * Read the checksum offset from the EEPROM and make sure it looks valid.
+ */
+
+ cat_control.Module = NCRCatModule->ModuleAddress;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = XSUM_END_OFFSET;
+ cat_control.NumberOfBytes = 2;
+
+ status = NCRCatSubaddressIo(asic,&cat_control,(PUCHAR)&xsum_end);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (status) {
+ return (NULL);
+ }
+
+ cat_control.Module = NCRCatModule->ModuleAddress;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = EEPROM_SIZE_OFFSET;
+ cat_control.NumberOfBytes = 2;
+
+ status = NCRCatSubaddressIo(asic,&cat_control,(PUCHAR)&size_of_eeprom);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (status) {
+ return (NULL);
+ }
+
+ if ((xsum_end < sizeof(MODULE_HEADER)) || (xsum_end > size_of_eeprom)) {
+ return (NULL);
+ }
+
+/*
+ * Allocate a buffer for the data and read it from the EEPROM
+ */
+
+ if ((data = (PUSHORT) ExAllocatePool(NonPagedPool, (ULONG)xsum_end)) == NULL) {
+ return (NULL);
+ }
+
+ RtlZeroMemory((PVOID)data,(ULONG)xsum_end);
+
+ cat_control.Address = EEPROM_DATA_START;
+ cat_control.NumberOfBytes = xsum_end;
+
+ status = NCRCatSubaddressIo(asic, &cat_control, (PUCHAR)data);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ if (status) {
+ ExFreePool((PVOID)data);
+ return (NULL);
+ }
+
+
+/*
+ * Checksum the data to make sure it is valid.
+ */
+
+ for (i = 0, xsum = 0; i < (USHORT)(xsum_end / 2); i++)
+ xsum += *((PUSHORT)(data +i));
+
+ if (xsum != 0) {
+ ExFreePool((PVOID)data);
+ return (NULL);
+ }
+
+/*
+ * Return the EEPROM data. Also, as a side effect, the NCRCatModule->asic field
+ * is left pointing to the ASIC data structure that was allocated.
+ */
+ return ((PUCHAR)data);
+
+}
+
+
+
+VOID
+NCRCatExtractSetupInformation(
+ PUCHAR EEpromData
+ )
+
+/*++
+
+Routine Description:
+ Extract the setup information from the data read from the EEPROM.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PASIC asic, *asic_pointer;
+ PMODULE_HEADER module_header;
+ PSCAN_PATH_TABLE scan_path_table;
+ PASIC_DATA_TABLE asic_data_table;
+ PJTAG_TABLE jtag_table;
+ USHORT asic_number, scan_path_offset;
+ LONG i;
+
+ module_header = (PMODULE_HEADER)EEpromData;
+ NCRCatModule->EEpromSize = module_header->EEpromSize;
+ NCRCatModule->NumberOfAsics = module_header->NumberOfAsics;
+
+
+ for (asic_number = 0, asic = NCRCatModule->Asic, scan_path_offset = module_header->ScanPathOffset;
+ asic_number < module_header->NumberOfAsics; asic_number++, scan_path_offset +=
+ sizeof(SCAN_PATH_TABLE), asic_pointer = &asic->Next, asic = NULL) {
+
+/*
+ * On the first pass, we have an asic that was allocated when the
+ * data block was read from the EEPROM.
+ */
+
+ if (asic == NULL) {
+ if (!(asic = *asic_pointer = ExAllocatePool(NonPagedPool,sizeof(ASIC)))) {
+ ExFreePool((PVOID)EEpromData);
+ return;
+ }
+ RtlZeroMemory((PVOID)asic, sizeof(ASIC));
+ }
+
+
+ asic->AsicLocation = (UCHAR)asic_number;
+
+/*
+ * Set up a pointer to the new scan path table
+ */
+
+ scan_path_table = (PSCAN_PATH_TABLE)(EEpromData + scan_path_offset);
+ asic->AsicId = scan_path_table->AsicId;
+
+/*
+ * Set up a pointer to the asic_data_table
+ */
+
+ asic_data_table = (PASIC_DATA_TABLE)(EEpromData + scan_path_table->AsicDataOffset);
+ for (i = 0; i < 4; i++) {
+ asic->JtagId[i] = asic_data_table->JtagId[i];
+ }
+ asic->SubaddressSpace = ((1 << asic_data_table->SubaddressBits) - 1);
+
+
+/*
+ * Set up a pointer to the jtab_table
+ */
+
+ jtag_table = (PJTAG_TABLE)(EEpromData + asic_data_table->JtagOffset);
+ asic->InstructionRegisterLength = jtag_table->InstructionRegisterLength;
+ asic->BitLocation = (USHORT)NCRCatModule->InstructionBits;
+ NCRCatModule->InstructionBits += asic->InstructionRegisterLength;
+
+ if (asic->InstructionRegisterLength > NCRCatModule->LargestRegister) {
+ NCRCatModule->LargestRegister = asic->InstructionRegisterLength;
+ }
+
+ if (asic->InstructionRegisterLength < NCRCatModule->SmallestRegister ||
+ NCRCatModule->SmallestRegister == 0) {
+ NCRCatModule->SmallestRegister = asic->InstructionRegisterLength;
+ }
+ }
+ asic_pointer = NULL;
+
+ ExFreePool((PVOID)EEpromData);
+}
+
+VOID
+NCRCatDefaultSetupInformation(
+ )
+
+/*++
+
+Routine Description:
+ Assign defaults to the module if the EEPROM checksum is not correct.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PASIC asic, *asic_pointer;
+ USHORT i;
+
+ switch (NCRCatModule->ModuleAddress) {
+ case PROCESSOR0:
+ case PROCESSOR1:
+ case PROCESSOR2:
+ case PROCESSOR3:
+ case PROCESSOR4:
+ case PROCESSOR5:
+ case PROCESSOR6:
+ case PROCESSOR7:
+ NCRCatModule->EEpromSize = EEPROM_SIZE;
+ NCRCatModule->NumberOfAsics = 1;
+ break;
+
+ case MEMORY0:
+ case MEMORY1:
+ NCRCatModule->EEpromSize = EEPROM_SIZE;
+ NCRCatModule->NumberOfAsics = 7;
+ break;
+
+ case PRIMARYMC:
+ NCRCatModule->EEpromSize = EEPROM_SIZE;
+ NCRCatModule->NumberOfAsics = 9;
+ break;
+
+ case SECONDARYMC:
+ NCRCatModule->EEpromSize = EEPROM_SIZE;
+ NCRCatModule->NumberOfAsics = 7;
+ break;
+
+ case PSI:
+ NCRCatModule->EEpromSize = PSI_EEPROM_SIZE;
+ NCRCatModule->NumberOfAsics = 1;
+ break;
+
+ default:
+ NCRCatModule->EEpromSize = EEPROM_SIZE;
+ NCRCatModule->NumberOfAsics = 1;
+ break;
+ }
+
+ NCRCatModule->InstructionBits = NCRCatModule->NumberOfAsics * CHAR_SIZE;
+ NCRCatModule->LargestRegister = 8;
+ NCRCatModule->SmallestRegister = 8;
+ NCRCatModule->SubModules = NULL;
+
+ for (i = 0, asic = NCRCatModule->Asic,asic_pointer = &NCRCatModule->Asic;
+ i < NCRCatModule->NumberOfAsics; i++) {
+
+ if (*asic_pointer == NULL) {
+ if (!(asic = *asic_pointer = ExAllocatePool(NonPagedPool,sizeof(ASIC)))) {
+ return;
+ }
+ }
+
+ RtlZeroMemory((PVOID)asic,sizeof(ASIC));
+
+ asic->AsicId = (UCHAR)i;
+ asic->AsicLocation = (UCHAR)i;
+ asic->BitLocation = (UCHAR)(i * CHAR_SIZE);
+ asic->InstructionRegisterLength = 8;
+ asic->SubaddressSpace = SUBADDR_HI;
+ asic_pointer = &asic->Next;
+ }
+}
+
+PMODULE
+NCRCatSelect(
+ UCHAR ModuleAddress
+ )
+
+/*++
+
+Routine Description:
+ This function is used to select a module. If the module address matches the
+ address passed in, a pointer to the module structure is returned. Otherwise,
+ NULL is returned.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PMODULE module, submodule;
+ CAT_CONTROL cat_control;
+ UCHAR module_address, submodule_address, data;
+ LONG status;
+
+
+ /*
+ * Extract the real module and submodule addresses.
+ * If any of the three most significant bits of the module
+ * address are set, we have a submodule.
+ */
+
+ submodule_address = ModuleAddress;
+ module_address = ModuleAddress & 0x1f;
+
+ for (module = NCRCatModuleList; module != NULL; module = module->Next) {
+ if (module->ModuleAddress != module_address)
+ continue;
+
+//
+// Select the module
+//
+ WRITE_PORT_UCHAR((PUCHAR)SELECT_PORT, (UCHAR)module_address);
+
+ /*
+ * muoe941245 - jtt - 5/10/94
+ * If it is a submodule, "catmodule" is not set which
+ * can cause problems in the following catregio(),
+ * especially if it is NULL.
+ */
+ NCRCatModule = module;
+
+ if (submodule_address == module_address)
+ return(module);
+
+ /*
+ * Must be looking for a submodule (16way). Select the
+ * submodule by writing the submodule address in the
+ * two least significant bits of the CAT_I;
+ */
+ for (submodule = module->SubModules; submodule != NULL;
+ submodule = submodule->Next) {
+ if (submodule->ModuleAddress != submodule_address)
+ continue;
+ cat_control.Module = submodule->ModuleAddress;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.Address = SUBMODSELECT;
+ cat_control.NumberOfBytes = 1;
+
+ data = submodule->ModuleAddress >> 5;
+ status = NCRCatRegisterIo(submodule->Asic, &cat_control, (PUCHAR)&data);
+
+ if (!status) {
+ NCRCatModule = submodule;
+ } else {
+ NCRCatModule = NULL;
+ }
+ return(NCRCatModule);
+ }
+ /*
+ * Should not have to deselect here. The next operation will send a DESELECT.
+ */
+ break;
+ }
+ NCRCatModule = NULL;
+ return (NULL);
+}
+
+PASIC
+NCRCatGetAsic(
+ UCHAR AsicId
+ )
+
+/*++
+
+Routine Description:
+ Tries to match the AsicId with an AsicId in the current selected module.
+ If there is no match, NULL is returned.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PASIC asic;
+
+ for (asic = NCRCatModule->Asic; asic != NULL; asic = asic->Next) {
+ if (asic->AsicId == AsicId) {
+ return (asic);
+ }
+ }
+
+ return (NULL);
+}
+
+
+LONG
+NCRCatConnect(
+ )
+
+/*++
+
+Routine Description:
+ Called to connect the CAT_I with all of the other ASICs on the module.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PASIC asic;
+ UCHAR value;
+ LONG status;
+
+ if (NCRCatModule->ScanPathConnected == TRUE) {
+ return (CATNOERR);
+ }
+
+ if (!(asic = NCRCatGetAsic(CAT_I))) {
+ return (CATIO);
+ }
+
+ if (status = NCRCatRead(asic, SCANPATH, &value)) {
+ return (status);
+ }
+
+ value |= CONNECT_ASICS;
+
+ if (status = NCRCatWrite(asic, SCANPATH, &value)) {
+ return (status);
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+
+ NCRCatModule->ScanPathConnected = TRUE;
+
+ return (CATNOERR);
+}
+
+
+
+LONG
+NCRCatDisconnect(
+ )
+
+/*++
+
+Routine Description:
+ Called to disconnect the CAT_I from all the ASICs on the module.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PASIC asic;
+ UCHAR value;
+ LONG status;
+
+ if (NCRCatModule->ScanPathConnected == FALSE) {
+ return (CATNOERR);
+ }
+
+ if (!(asic = NCRCatGetAsic(CAT_I))) {
+ return (CATIO);
+ }
+
+ if (status = NCRCatRead(asic, SCANPATH, &value)) {
+ return (status);
+ }
+
+ value &= DISCONNECT_ASIC;
+
+ if (status = NCRCatWrite(asic, SCANPATH, &value)) {
+ return (status);
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+
+ NCRCatModule->ScanPathConnected = FALSE;
+ return (CATNOERR);
+}
+
+
+VOID
+NCRCatRestoreState(
+ )
+
+/*++
+
+Routine Description:
+ This function is called when an I/O error has occured. The best thing to do
+ is to do a blind disconnect and hope this fixes the problem.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR instruction;
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)IRCYC); // Instruct the module
+ instruction = NCRCatInstruction(SCANPATH, WRITE_CONFIG);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)instruction);
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)DRCYC);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)RESET_STATE);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+
+ NCRCatModule->ScanPathConnected = FALSE;
+}
+
+
+LONG
+NCRCatAutoIncrement(
+ PASIC Asic
+ )
+
+/*++
+
+Routine Description:
+ When reading/writing from/to the subaddress space of an ASIC, the catautoinc bit
+ can be set so that registers 6 & 7 are incremented by the hardware after each
+ read/write from/to register 3.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR newvalue;
+ UCHAR oldvalue;
+ LONG status;
+
+ if (status = NCRCatRead(Asic, AUTO_INC_REG, &oldvalue)) {
+ return (status);
+ }
+
+ if ((newvalue = (oldvalue | AUTO_INC)) != oldvalue) {
+ status = NCRCatWrite(Asic, AUTO_INC_REG, &newvalue);
+ }
+
+ return status;
+}
+
+LONG
+NCRCatNoAutoIncrement(
+ PASIC Asic
+ )
+
+/*++
+
+Routine Description:
+ This function is used to reset the auto increment bit for subaddress reads/writes.
+ This allows reads/writes from/to the subaddress space via register 3 with out
+ incrementing registers 6 & 7.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR newvalue;
+ UCHAR oldvalue;
+ LONG status;
+
+ if (status = NCRCatRead(Asic, AUTO_INC_REG, &oldvalue)) {
+ return (status);
+ }
+
+ if ((newvalue = (oldvalue & NO_AUTO_INC)) != oldvalue) {
+ status = NCRCatWrite(Asic, AUTO_INC_REG, &newvalue);
+ }
+
+ return (status);
+}
+
+
+
+LONG
+NCRCatSubaddressSetup(
+ PASIC Asic,
+ USHORT Subaddress
+ )
+
+/*++
+
+Routine Description:
+ Sets up register 6 & 7 for a subaddress read. Note: If the subaddres space
+ requires 8 bits or less for addressing, register 7 may be user defined. If
+ there is no subaddress space registers 6 & 7 may be user defined.
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LONG status;
+ UCHAR address;
+
+ if (Asic->SubaddressSpace == (USHORT)SUBADDR_ZERO) {
+ return (CATIO);
+ }
+
+/*
+ * Set up register 6 with the low byte of the sub address
+ */
+ address = (UCHAR)(Subaddress & 0xff);
+ if (status = NCRCatWrite(Asic, SUBADDRLO, &address)) {
+ return (status);
+ }
+
+/*
+ * Set up register 7 with the high byte of the sub address
+ */
+
+ if (Asic->SubaddressSpace > SUBADDR_LO) {
+ address = (UCHAR)(Subaddress >> CHAR_SIZE);
+ status = NCRCatWrite(Asic, SUBADDRHI, &address);
+ }
+ return (status);
+}
+
+
+
+LONG
+NCRCatRegisterIo(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+ The function is used to read/write from/to any number of register of an ASIC.
+ If a read is being performed, the buffer is assumed to be large enough to
+ hold the data that is being read.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR register_number;
+ PUCHAR buffer;
+ USHORT number_bytes;
+ LONG status;
+
+ if ((USHORT)(CatControl->Address + CatControl->NumberOfBytes) > (USHORT)MAXNUMREG) {
+ return (CATFAULT);
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+
+ if (Asic->AsicId == CAT_I) {
+ if (status = NCRCatDisconnect()) {
+ return (status);
+ }
+ } else {
+ if (status = NCRCatConnect()) {
+ return (status);
+ }
+ }
+
+ if (CatControl->Command == READ_REGISTER) {
+ for (register_number = (UCHAR)CatControl->Address, number_bytes = CatControl->NumberOfBytes,
+ buffer = Buffer; number_bytes > 0;
+ register_number++, number_bytes--, buffer++) {
+
+ if (status = NCRCatRead(Asic, register_number, buffer)) {
+ return (status);
+ }
+ }
+ } else { /* CatControl->Command == WRITE_REGISTER */
+
+ for (register_number = (UCHAR)CatControl->Address, number_bytes = CatControl->NumberOfBytes,
+ buffer = Buffer; number_bytes > 0;
+ register_number++, number_bytes--, buffer++) {
+
+ if (status = NCRCatWrite(Asic, register_number, buffer)) {
+ return (status);
+ }
+ }
+ }
+
+ if (Asic->AsicId != CAT_I) {
+ status = NCRCatDisconnect();
+ }
+
+ return (status);
+}
+
+
+
+
+LONG
+NCRCatSubaddressIo(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+ This function is used to read/write from/to the subaddress space of an ASIC.
+ If a read is being performed, the buffer is assumed to be large enough to hold
+ the data that is being read.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LONG status;
+
+ if ((ULONG)(CatControl->Address + CatControl->NumberOfBytes - 1) > Asic->SubaddressSpace) {
+ return (CATFAULT);
+ }
+
+ if ((CatControl->Module >= PROCESSOR0 && CatControl->Module <= PROCESSOR3 ||
+ CatControl->Module >= PROCESSOR4 && CatControl->Module <= PROCESSOR7) &&
+ ((ULONG)(CatControl->Address + CatControl->NumberOfBytes) >
+ (ULONG)NCRCatModule->EEpromSize)) {
+ return (CATACCESS);
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+
+ if (Asic->AsicId == CAT_I) {
+ if (status = NCRCatDisconnect())
+ return (status);
+ } else { /* Asic->AsicId != CAT_I */
+ if (status = NCRCatConnect())
+ return (status);
+ }
+
+ if (CatControl->Command == READ_SUBADDR) {
+ if (status = NCRCatSubaddressRead(Asic, CatControl, Buffer))
+ return (status);
+ } else {
+ if (status = NCRCatSubaddressWrite(Asic, CatControl, Buffer))
+ return (status);
+ }
+ if (Asic->AsicId != CAT_I)
+ status = NCRCatDisconnect();
+
+ return (status);
+}
+
+
+LONG
+NCRCatRead(
+ PASIC Asic,
+ UCHAR RegisterNumber,
+ PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+ Function used to read one register from one asic at a time.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LONG status;
+ LONG internal_register = TRUE;
+ UCHAR instruction;
+
+ instruction = NCRCatInstruction(RegisterNumber, READ_CONFIG);
+
+ if (status = NCRCatSendInstruction(Asic, instruction))
+ return (status);
+
+ if (RegisterNumber > SUBADDRHI)
+ internal_register = FALSE;
+
+ if (status = NCRCatGetData(Asic, Buffer, internal_register))
+ return (status);
+
+ return (status);
+}
+
+
+
+LONG
+NCRCatWrite(
+ PASIC Asic,
+ UCHAR RegisterNumber,
+ PUCHAR Data
+ )
+
+/*++
+
+Routine Description:
+ Function used to write to one register of one ASIC at a time. It
+ is assumed that the CatSelect call has already been used to select
+ the desired module.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LONG status;
+ LONG internal_register = TRUE;
+ LONG external_special = FALSE;
+ UCHAR instruction;
+
+ instruction = NCRCatInstruction(RegisterNumber, WRITE_CONFIG);
+
+ if (status = NCRCatSendInstruction(Asic, instruction))
+ return (status);
+
+ if (RegisterNumber > SUBADDRHI) {
+ internal_register = FALSE;
+ if (RegisterNumber < MAXNUMREG) {
+ external_special = TRUE;
+ }
+ }
+
+ if (status = NCRCatSendData(Asic, Data, internal_register, external_special))
+ return (status);
+
+ return (status);
+}
+
+
+
+LONG
+NCRCatSubaddressRead(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+ Function used to read data from the subaddress space. If the CAT_I subaddress
+ space is being read (EEPROM), extra RUN cycles are required for the read.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR instruction;
+ PUCHAR buffer;
+ USHORT number_bytes;
+ LONG status;
+
+ if (CatControl->NumberOfBytes > 1) {
+ if (status = NCRCatAutoIncrement(Asic))
+ return (status);
+ }
+
+ if (status = NCRCatSubaddressSetup(Asic, CatControl->Address)) {
+ return (status);
+ }
+
+ instruction = NCRCatInstruction(SUBADDRDATA, READ_CONFIG);
+
+ if (status = NCRCatSendInstruction(Asic, instruction)) {
+ return (status);
+ }
+
+ for (number_bytes = CatControl->NumberOfBytes, buffer = Buffer; number_bytes > 0;
+ number_bytes--, buffer++) {
+
+ if (status = NCRCatGetData(Asic, buffer, FALSE))
+ break;
+ }
+ return (status);
+}
+
+
+LONG
+NCRCatWriteComplete(
+ PASIC Asic,
+ USHORT Address,
+ UCHAR Expected
+ )
+
+/*++
+
+Routine Description:
+ Function used to determine if a write to the subaddress space of the CAT_I (EEPROM) has been
+ completed. The write is complete when the data read matches what was written. The data that
+ is read should be the one's complement of the data written until the write completes.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR data;
+ LONG status;
+ ULONG i, j;
+ UCHAR instruction;
+
+ if (status = NCRCatNoAutoIncrement(Asic))
+ return (status);
+
+ if (status = NCRCatSubaddressSetup(Asic, Address))
+ return (status);
+
+ for (i = 0; i < MAXREADS; i++) {
+ for ( j = 0; j < WRITEDELAY; j++)
+ KeStallExecutionProcessor((ULONG)10);
+
+/* Old code
+ if (status = NCRCatRead(Asic, SUBADDRDATA, &data))
+ return(status);
+*/
+ instruction = NCRCatInstruction(SUBADDRDATA, READ_CONFIG);
+
+ if (status = NCRCatSendInstruction(Asic,instruction))
+ return(status);
+
+ if (status = NCRCatGetData(Asic, &data, FALSE))
+ return(status);
+
+ if (data == Expected)
+ return (CATNOERR);
+ }
+ return (CATIO);
+}
+
+
+
+LONG
+NCRCatSubaddressWrite(
+ PASIC Asic,
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+ Function that writes to the subaddress space of an ASIC.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ USHORT subaddress;
+ USHORT remaining_bytes;
+ USHORT number_bytes;
+ USHORT i;
+ UCHAR instruction;
+ PUCHAR buffer;
+ LONG status;
+
+/*
+ * The CAT_I subaddress space (EEPROM) may be written one byte at
+ * time. However, the EEPROM waits for 20 microsec before starting
+ * the write. If an additional byte of data is received before the
+ * 20 microsec timeout, the EEPROM waits for yet another byte of data.
+ * This contiues until the 64 byte EEPROM buffer is filled or a timeout
+ * occures. At that point the data is written to the EEPROM.
+ */
+
+ if ((CatControl->Asic == CAT_I) && (CatControl->Address < NCRCatModule->EEpromSize)) {
+/*
+ * Write the data up to a page & then wait for the EEPROM write to complete.
+ */
+
+ for (subaddress = CatControl->Address, remaining_bytes = CatControl->NumberOfBytes,
+ buffer = Buffer; remaining_bytes > 0; subaddress += number_bytes,
+ remaining_bytes -= number_bytes) {
+
+ number_bytes = EEPROMPAGESIZE - (USHORT)(subaddress % EEPROMPAGESIZE);
+
+ if (number_bytes > remaining_bytes)
+ number_bytes = remaining_bytes;
+
+ if (status = NCRCatAutoIncrement(Asic))
+ return (status);
+
+ if (status = NCRCatSubaddressSetup(Asic, subaddress))
+ return (status);
+
+ instruction = NCRCatInstruction(SUBADDRDATA, WRITE_CONFIG);
+
+ if (status = NCRCatSendInstruction(Asic, instruction))
+ return (status);
+
+/*
+ * When writing to the EEPROM, error checking must be delayed until
+ * the the end of the block write. This is due to the amount of
+ * time it take to send data over the CAT bus and the EEPROM
+ * timeout.
+ */
+ for (i = 0; i < number_bytes; i++) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)DRCYC);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)*buffer++);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+ }
+
+/*
+ * If the read starts in the PSI EEPROM and continues into the
+ * the subaddress space past the EEPROM the data compare must
+ * stop. Writing to this area toggles bits so the data that is
+ * written may not match what is read later.
+ */
+
+ if ((ULONG)(subaddress + number_bytes - 1) < (ULONG)NCRCatModule->EEpromSize) {
+/*
+ * Read the last byte and compare it with last byte written.
+ * The data should be the one's complement of the data written
+ * until the write completes.
+ */
+ if (status = NCRCatWriteComplete(Asic, (USHORT)(subaddress + number_bytes - 1),
+ *(buffer - 1))) {
+
+ return (status);
+ }
+
+ }
+
+ }
+
+
+ } else { /* ((Aisc != CAT_I) || (CatControl->Address >= NCRCatControl->EEpromSize)) */
+
+ if (status = NCRCatAutoIncrement(Asic))
+ return (status);
+
+ if (status = NCRCatSubaddressSetup(Asic, CatControl->Address))
+ return (status);
+
+ instruction = NCRCatInstruction(SUBADDRDATA, WRITE_CONFIG);
+
+ if (status = NCRCatSendInstruction(Asic, instruction))
+ return (status);
+
+ for (number_bytes = CatControl->NumberOfBytes, buffer = Buffer; number_bytes > 0;
+ number_bytes--, buffer++) {
+
+ if (status = NCRCatSendData(Asic, buffer, FALSE, FALSE))
+ return (status);
+ }
+ }
+ return (CATNOERR);
+}
+
+
+
+UCHAR
+NCRCatInstruction(
+ UCHAR RegisterNumber,
+ UCHAR Operation
+ )
+
+/*++
+
+Routine Description:
+ Function builds an instruction by determing the parity bit needed for
+ even parity and puting this value in bit 7 and zero in bit 6. The
+ register number is placed in bits 2-5 and the operation (read/write)
+ value in bits 0 and 1.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR parity;
+
+/*
+ * Parity is the parity of the register number + 1 (READ_REGISTER
+ * and WRITE_REGISTER always add '1' to the number of bits == 1)
+ */
+
+ parity = (UCHAR)(1 + (RegisterNumber & 0x01) +
+ ((UCHAR)(RegisterNumber & 0x02) >> 1) +
+ ((UCHAR)(RegisterNumber & 0x04) >> 2) +
+ ((UCHAR)(RegisterNumber & 0x08) >> 3)) % 2;
+
+ return (((parity << 7) | (RegisterNumber << 2) | Operation));
+}
+
+
+LONG
+NCRCatSendInstruction(
+ PASIC Asic,
+ UCHAR Instruction
+ )
+
+/*++
+
+Routine Description:
+ Function inserts an instruction inside of a string to be shifted
+ out of the NCRCatDataPort so that all of the ASICs execept the one we are
+ instructing will be placed in bypass mode. If the scan path has not been
+ connected, then we can only talk to the CAT_I. In this case, we have very
+ little work to do.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR instruction_sequence[MAX_SCAN_PATH];
+ UCHAR header_sequence[MAX_REG_SIZE];
+ SHORT i;
+ SHORT instruction_bytes;
+ SHORT header_bytes;
+ SHORT pad_bits;
+ LONG status = CATNOERR;
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)IRCYC);
+
+ if (NCRCatModule->ScanPathConnected == FALSE) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)HEADER);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)Instruction);
+
+ if ((READ_PORT_UCHAR((PUCHAR)NCRCatDataPort)) != HEADER)
+ status = CATIO;
+
+ return (status);
+ }
+
+ instruction_bytes = NCRCatModule->InstructionBits / CHAR_SIZE;
+
+ if (pad_bits = NCRCatModule->InstructionBits % CHAR_SIZE) {
+ pad_bits = CHAR_SIZE - pad_bits;
+ instruction_bytes++;
+ }
+
+ header_bytes = NCRCatModule->LargestRegister / CHAR_SIZE;
+
+ if (NCRCatModule->LargestRegister % CHAR_SIZE)
+ header_bytes++;
+
+ for (i = 0; i < (instruction_bytes + header_bytes); i++) {
+ *(instruction_sequence + i) = 0xff;
+ }
+
+ NCRCatBuildHeader(header_sequence, header_bytes, NCRCatModule->LargestRegister,
+ NCRCatModule->SmallestRegister);
+
+ NCRCatInsertData(instruction_sequence, NCRCatModule->InstructionBits, header_sequence,
+ (SHORT)(header_bytes * CHAR_SIZE));
+
+ NCRCatInsertData(instruction_sequence, Asic->BitLocation, &Instruction,
+ Asic->InstructionRegisterLength);
+
+ status = NCRCatShiftOutData(instruction_sequence, instruction_bytes, header_bytes, pad_bits);
+
+ return (status);
+}
+
+VOID
+NCRCatBuildHeader(
+ PUCHAR Header,
+ SHORT HeaderBytes,
+ SHORT LargestRegister,
+ SHORT SmallestRegister
+ )
+
+/*++
+
+Routine Description:
+ Function builds a header to be placed out on the CAT bus. It is used
+ to make sure that a register did not unexpectedly go into bypass.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SHORT one_bits;
+ SHORT i;
+ PUCHAR last_byte;
+
+ if (SmallestRegister == 1)
+ one_bits = 1;
+ else
+ one_bits = (USHORT)(SmallestRegister - 1) % CHAR_SIZE;
+
+ for (i = 0; i < HeaderBytes; i++)
+ *(Header+i) = 0;
+
+ for (i = one_bits, last_byte = (PUCHAR)(Header + (HeaderBytes - 1)); i > 0; i--)
+ *last_byte = ((*last_byte) << 1) + 1;
+}
+
+
+LONG
+NCRCatSendData(
+ PASIC Asic,
+ PUCHAR Data,
+ LONG InternalRegister,
+ LONG ExternalRegister
+ )
+
+/*++
+
+Routine Description:
+ Function generates a sequence to be shifted out of the NCRCatDataPort
+ so that the data is send to the desired ASIC and an one is shifted to all
+ of the other ASICs (they are in bypass mode).
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ UCHAR data_sequence[MAX_SCAN_PATH];
+ UCHAR header_sequence[MAX_REG_SIZE];
+ SHORT i;
+ SHORT data_bytes;
+ SHORT header_bytes;
+ SHORT pad_bits;
+ SHORT header_location;
+ LONG status = CATNOERR;
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)DRCYC);
+
+ if (NCRCatModule->ScanPathConnected == FALSE) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)HEADER);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)*Data);
+
+ if (READ_PORT_UCHAR((PUCHAR)NCRCatDataPort) != HEADER)
+ status = CATIO;
+
+ if (InternalRegister == FALSE) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+
+ if (ExternalRegister == TRUE) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)END);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+ }
+ }
+ return (status);
+ }
+
+ data_bytes = (SHORT)((NCRCatModule->NumberOfAsics - 1) + Asic->InstructionRegisterLength) /
+ (SHORT)CHAR_SIZE;
+
+ if (pad_bits = (SHORT)((NCRCatModule->NumberOfAsics - 1) +
+ Asic->InstructionRegisterLength) % (SHORT)CHAR_SIZE) {
+
+ pad_bits = CHAR_SIZE - pad_bits;
+ data_bytes++;
+ }
+
+ header_bytes = (SHORT)(Asic->InstructionRegisterLength / CHAR_SIZE);
+
+ if ((SHORT)(Asic->InstructionRegisterLength % CHAR_SIZE))
+ header_bytes++;
+
+ NCRCatBuildHeader(header_sequence, header_bytes, Asic->InstructionRegisterLength, 1);
+
+ for (i = 0; i < (data_bytes + header_bytes); i++)
+ *(data_sequence + i) = 0xff;
+
+
+ header_location = (NCRCatModule->NumberOfAsics - 1) + Asic->InstructionRegisterLength;
+
+ NCRCatInsertData(data_sequence, header_location, header_sequence, (SHORT)(header_bytes * CHAR_SIZE));
+ NCRCatInsertData(data_sequence, Asic->AsicLocation, Data, Asic->InstructionRegisterLength);
+
+ status = NCRCatShiftOutData(data_sequence, data_bytes, header_bytes, pad_bits );
+
+ return (status);
+}
+
+
+VOID
+NCRCatInsertData(
+ PUCHAR String,
+ SHORT StartBit,
+ PUCHAR Data,
+ SHORT NumberOfBits
+ )
+
+/*++
+
+Routine Description:
+ Given a string, the function places the data inside of the string
+ starting a bit location string_bit. The most significant byte will
+ be placed in the first 8 bits starting at string_bit location. If
+ the data does not fall on a byte boundry, the data should be placed
+ in the high order bits. The low order bits should be padded with 1's.
+ The first byte of the string is considered the most significant byte
+ and should be the last byte shifted out.
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SHORT data_bits; // running count of data bits placed in the string
+ SHORT data_bits_remaining; // data bits remaining in current char
+ SHORT string_bits_needed; // string bits needed to fill current char
+ SHORT bits_in_string; // bits inserted in the string during current operation
+ PUCHAR tmp_string;
+ PUCHAR tmp_data;
+
+ for (data_bits = 0, tmp_string = String + (StartBit / CHAR_SIZE), tmp_data = Data;
+ NumberOfBits > 0; data_bits += bits_in_string, StartBit += bits_in_string,
+ NumberOfBits -= bits_in_string ) {
+
+ data_bits_remaining = CHAR_SIZE - (data_bits % CHAR_SIZE);
+ string_bits_needed = CHAR_SIZE - (StartBit % CHAR_SIZE);
+
+ if (data_bits_remaining == CHAR_SIZE && string_bits_needed == CHAR_SIZE) {
+ *tmp_string++ = *tmp_data++;
+ bits_in_string = CHAR_SIZE;
+
+ } else if (data_bits_remaining == CHAR_SIZE) { /* string_bits_needed != CHAR */
+ *tmp_string++ &= (UCHAR)((0xff << string_bits_needed ) |
+ (*tmp_data >> (CHAR_SIZE - string_bits_needed)));
+ bits_in_string = string_bits_needed;
+
+ } else if (string_bits_needed == CHAR_SIZE) { /* data_bits_remaining != CHAR_SIZE */
+
+ *tmp_string &= (0xff >> data_bits_remaining) |
+ (*tmp_data++ << (CHAR_SIZE - data_bits_remaining));
+ bits_in_string = data_bits_remaining;
+
+ } else {
+ /*RMU this is an error case... */
+ }
+ }
+}
+
+
+
+VOID
+NCRCatExtractData(
+ PUCHAR String,
+ SHORT StartBit,
+ PUCHAR Data,
+ SHORT NumberOfBits
+ )
+
+/*++
+
+Routine Description:
+ Function extract NumberBits of data from the string and places them in
+ the string Data.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SHORT data_bits; // running count of data bits in the data string
+ SHORT data_bits_needed; // data bits needed from to fill current char
+ SHORT string_bits_remaining; // string bits remaining in current char
+ SHORT bits_extracted; // bits extracted from the string with last operation
+ PUCHAR tmp_string;
+ PUCHAR tmp_data;
+
+ for (data_bits = 0, tmp_data = Data, (tmp_string = String + (StartBit / CHAR_SIZE));
+ NumberOfBits > 0; data_bits += bits_extracted, StartBit += bits_extracted,
+ NumberOfBits -= bits_extracted ) {
+
+ data_bits_needed = CHAR_SIZE - (data_bits % CHAR_SIZE);
+ string_bits_remaining = CHAR_SIZE - (StartBit % CHAR_SIZE);
+
+ if (string_bits_remaining == CHAR_SIZE && data_bits_needed == CHAR_SIZE) {
+ *tmp_data++ = *tmp_string;
+ bits_extracted = CHAR_SIZE;
+ }
+ else if (string_bits_remaining == CHAR_SIZE) { /* data_bits_needed != CHAR_SIZE */
+ *tmp_data++ |= *tmp_string >> (CHAR_SIZE - data_bits_needed);
+ bits_extracted = data_bits_needed;
+ }
+ else if (data_bits_needed == CHAR_SIZE) { /* string_bits_remaining != CHAR_SIZE */
+ *tmp_data |= *tmp_string++ << (CHAR_SIZE - string_bits_remaining);
+ bits_extracted = string_bits_remaining;
+ }
+ else {
+ /*RMU this is an error case ASSERT? */
+ }
+ }
+}
+
+
+LONG
+NCRCatShiftOutData(
+ PUCHAR Data,
+ SHORT DataBytes,
+ SHORT HeaderBytes,
+ SHORT PadBits
+ )
+
+/*++
+
+Routine Description:
+ Function shifts out data starting with the last byte in the
+ data string (header is shifted out first). Also checks to make sure
+ the header shifted out matches the header shifted back in.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SHORT i;
+ SHORT start_bit;
+ UCHAR input = 0;
+ UCHAR header = 0;
+
+ for (i = DataBytes + HeaderBytes - 1; i >= HeaderBytes; i--) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)*(Data + i));
+ }
+
+ for (i = HeaderBytes - 1; i >= 0; i--, header = 0) { /* check the header */
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)*(Data + i));
+
+ input = READ_PORT_UCHAR((PUCHAR)NCRCatDataPort);
+ start_bit = ((DataBytes + i) * CHAR_SIZE) - PadBits;
+ NCRCatExtractData(Data, start_bit, &header, CHAR_SIZE);
+
+ if (input != header)
+ return (CATIO);
+ }
+ return (CATNOERR);
+}
+
+
+
+LONG
+NCRCatGetData(
+ PASIC Asic,
+ PUCHAR Data,
+ LONG InternalRegister
+ )
+
+/*++
+
+Routine Description:
+ Functions writes 0xAA in the NCRCatDataPort to be shifted out. Then
+ the results of the shift are read from the NCRCatDataPort and placed in the
+ string "string". This loop continues until the requested data has been
+ placed in the string "string". Then the requested data is extracted from
+ the string "string" and placed in the "Data" string.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SHORT i;
+ SHORT string_bits;
+ SHORT string_bytes;
+ SHORT trailer_bytes;
+ SHORT pad_bits;
+ UCHAR string[MAX_SCAN_PATH];
+ UCHAR trailer[MAX_REG_SIZE];
+ UCHAR input;
+ LONG status = CATNOERR;
+
+ if (NCRCatModule->ScanPathConnected == FALSE) {
+
+/*
+ * For external register and subaddress space, use the RUN command
+ * to generate extra clock cycles for data access.
+ */
+ if (InternalRegister == FALSE) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)RUN);
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)DRCYC);
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)HEADER);
+ *Data = READ_PORT_UCHAR((PUCHAR)NCRCatDataPort);
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)0xAA);
+
+ if (READ_PORT_UCHAR((PUCHAR)NCRCatDataPort) != HEADER)
+ status = CATIO;
+
+ return (status);
+ }
+
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatCommandPort, (UCHAR)DRCYC);
+
+ string_bits = NCRCatModule->NumberOfAsics - 1 + Asic->InstructionRegisterLength;
+ string_bytes = string_bits / CHAR_SIZE;
+
+ if (pad_bits = string_bits % CHAR_SIZE) {
+ pad_bits = CHAR_SIZE - pad_bits;
+ string_bytes++;
+ }
+
+ trailer_bytes = Asic->InstructionRegisterLength / CHAR_SIZE;
+
+ if (Asic->InstructionRegisterLength % CHAR_SIZE)
+ trailer_bytes++;
+
+ NCRCatBuildHeader((PUCHAR)(trailer), trailer_bytes, Asic->InstructionRegisterLength, 1);
+
+/*
+ * Shift out the trailer while data is being shifted into the string.
+ */
+ for (i = trailer_bytes - 1; i >= 0; i--) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)*(trailer + i));
+ *(string + string_bytes + i) = READ_PORT_UCHAR((PUCHAR)NCRCatDataPort);
+ }
+
+/*
+ * Shift out 0xAA until the trailer is shifted back into the string
+ */
+ for (i = string_bytes - 1; i >= 0; i--) {
+ WRITE_PORT_UCHAR((PUCHAR)NCRCatDataPort, (UCHAR)0xAA);
+ *(string + i) = READ_PORT_UCHAR((PUCHAR)NCRCatDataPort);
+ }
+
+ *Data = 0;
+ NCRCatExtractData(string, (SHORT)(pad_bits + (trailer_bytes * CHAR_SIZE) +
+ Asic->AsicLocation), Data, Asic->InstructionRegisterLength);
+
+ for (i = 0; i < trailer_bytes; i++) {
+ input = 0;
+ NCRCatExtractData(string, (SHORT)(pad_bits + (CHAR_SIZE * i)), &input, CHAR_SIZE);
+
+ if (*(trailer + i) != input) {
+ status = CATIO;
+ break;
+ }
+ }
+ return (status);
+}
+
+
+
+LONG
+NCRCatIoLpb(
+ PCAT_CONTROL CatControl,
+ PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+ The following code is for accessing the LPB EEprom image. Since the LPB
+ is not on the cat bus, we must map in this area before accessing it in
+ physical memory.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return (CATNOERR);
+}
+
+
+
+
+VOID
+NCRCatModuleName (
+ LONG Module,
+ PUNICODE_STRING ModuleName
+ )
+
+/*++
+
+Routine Description:
+ Given a module ID return the module name.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ NTSTATUS status;
+
+ switch (Module) {
+
+ case PROCESSOR0:
+ status = RtlAppendUnicodeToString(ModuleName, L"Processor 0");
+ break;
+
+ case PROCESSOR1:
+ status = RtlAppendUnicodeToString(ModuleName, L"Processor 1");
+ break;
+
+ case PROCESSOR2:
+ status = RtlAppendUnicodeToString(ModuleName, L"Processor 2");
+ break;
+
+ case PROCESSOR3:
+ status = RtlAppendUnicodeToString(ModuleName, L"Processor 3");
+ break;
+
+ case MEMORY0:
+ status = RtlAppendUnicodeToString(ModuleName, L"Memory 0");
+ break;
+
+ case MEMORY1:
+ status = RtlAppendUnicodeToString(ModuleName, L"Memory 1");
+ break;
+
+ case PRIMARYMC:
+ status = RtlAppendUnicodeToString(ModuleName, L"PrimaryMicroChannel");
+ break;
+
+ case SECONDARYMC:
+ status = RtlAppendUnicodeToString(ModuleName, L"SecondaryMicroChannel");
+ break;
+
+ case PSI:
+ status = RtlAppendUnicodeToString(ModuleName, L"PowerSupplyInterface");
+ break;
+
+ case CAT_LPB_MODULE:
+ status = RtlAppendUnicodeToString(ModuleName, L"LocalPeripheralBoard");
+ break;
+
+ default:
+ status = RtlIntegerToUnicodeString(Module, 16, ModuleName);
+ break;
+ }
+}
+
+
+
+
+PWSTR ProcessorAsicNames[16] = {
+ L"CAT_I",
+ L"A_PBC",
+ L"B_PBC",
+ L"3",
+ L"4",
+ L"5",
+ L"6",
+ L"CPU_CATI7",
+ L"8",
+ L"CPU_Config2",
+ L"A",
+ L"CPU_Config4",
+ L"CPU_Config5",
+ L"CPU_Config6",
+ L"CPU_Config7",
+ L"PBC_Status"
+ };
+
+
+
+
+PWSTR MemoryAsicNames[7] = {
+ L"CAT_I",
+ L"MMC1",
+ L"MMA1",
+ L"MMD1_0",
+ L"MMD1_1",
+ L"MMD1_2",
+ L"MMD1_3"
+ };
+
+
+
+PWSTR PMCAsicNames[9] = {
+ L"CAT_I",
+ L"PMC_MCADDR",
+ L"PMC_DMA",
+ L"PMC_DS1",
+ L"PMC_DS0",
+ L"PMC_VIC",
+ L"PMC_ARB",
+ L"PMC_DS2",
+ L"PMC_DS3",
+ };
+
+
+
+
+PWSTR SMCAsicNames[9] = {
+ L"CAT_I",
+ L"PMC_MCADDR",
+ L"PMC_DMA",
+ L"PMC_DS1",
+ L"PMC_DS0",
+ L"5",
+ L"6",
+ L"PMC_DS2",
+ L"PMC_DS3",
+ };
+
+
+
+
+
+VOID
+NCRCatAsicName (
+ LONG Module,
+ LONG Asic,
+ PUNICODE_STRING AsicName
+ )
+
+/*++
+
+Routine Description:
+ Given a Module ID and an Asic ID return the Asic name.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ NTSTATUS status;
+
+ switch (Module) {
+ case PROCESSOR0:
+ case PROCESSOR1:
+ case PROCESSOR2:
+ case PROCESSOR3:
+ if (Asic > PBC_Status) {
+ status = RtlIntegerToUnicodeString(Asic,
+ 16, AsicName);
+ } else {
+ status = RtlAppendUnicodeToString( AsicName,
+ ProcessorAsicNames[Asic]);
+ }
+ break;
+
+ case MEMORY0:
+ case MEMORY1:
+ if (Asic > MMD1_3) {
+ status = RtlIntegerToUnicodeString(Asic,
+ 16, AsicName);
+ } else {
+ status = RtlAppendUnicodeToString( AsicName,
+ MemoryAsicNames[Asic]);
+ }
+ break;
+
+ case PSI:
+ switch (Asic) {
+ case CAT_I:
+ status = RtlAppendUnicodeToString( AsicName,
+ L"CAT_I");
+ break;
+
+ default:
+ status = RtlIntegerToUnicodeString(Asic,
+ 16, AsicName);
+ break;
+ }
+
+ break;
+
+ case PRIMARYMC:
+ if (Asic > PMC_DS3) {
+ status = RtlIntegerToUnicodeString(Asic,
+ 16, AsicName);
+ } else {
+ status = RtlAppendUnicodeToString( AsicName,
+ PMCAsicNames[Asic]);
+ }
+ break;
+
+ case SECONDARYMC:
+ if (Asic > SMC_DS3) {
+ status = RtlIntegerToUnicodeString(Asic,
+ 16, AsicName);
+ } else {
+ status = RtlAppendUnicodeToString( AsicName,
+ SMCAsicNames[Asic]);
+ }
+
+ break;
+
+
+ default:
+ status = RtlIntegerToUnicodeString(Asic, 16, AsicName);
+ break;
+ }
+
+
+
+}
+
+
+
+VOID
+HalpCatReportModuleAsics (
+ PUNICODE_STRING UnicodeModule,
+ PMODULE Module
+ )
+
+/*++
+
+Routine Description:
+ Place information about module Asics into the registry.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PASIC asic;
+
+ UNICODE_STRING unicode_asics;
+ OBJECT_ATTRIBUTES asics_attributes;
+ WCHAR asics_buffer[256];
+
+ UNICODE_STRING unicode_asic;
+ OBJECT_ATTRIBUTES asic_attributes;
+ WCHAR asic_buffer[256];
+
+ UNICODE_STRING unicode_asic_id;
+
+ UNICODE_STRING unicode_name;
+ WCHAR name_buffer[256];
+
+ HANDLE asics_handle;
+ HANDLE asic_handle;
+
+ NTSTATUS status;
+ ULONG tmp;
+
+/* Asics */
+
+ unicode_asics.Length = 0;
+ unicode_asics.MaximumLength=256;
+ unicode_asics.Buffer = asics_buffer;
+ RtlZeroMemory(unicode_asics.Buffer,unicode_asics.MaximumLength);
+
+ RtlCopyUnicodeString(&unicode_asics,UnicodeModule);
+ status = RtlAppendUnicodeToString(&unicode_asics,L"\\Asics");
+
+ InitializeObjectAttributes( &asics_attributes, &unicode_asics,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&asics_handle, KEY_READ | KEY_WRITE, &asics_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+
+ for (asic = Module->Asic; asic != NULL; asic = asic->Next) {
+
+/* Asic directory */
+
+ unicode_asic.Length = 0;
+ unicode_asic.MaximumLength=256;
+ unicode_asic.Buffer = asic_buffer;
+ RtlZeroMemory(unicode_asic.Buffer,unicode_asic.MaximumLength);
+
+ RtlCopyUnicodeString(&unicode_asic,&unicode_asics);
+ status = RtlAppendUnicodeToString(&unicode_asic,L"\\");
+
+ unicode_name.Length = 0;
+ unicode_name.MaximumLength=256;
+ unicode_name.Buffer = name_buffer;
+
+ NCRCatAsicName(Module->ModuleAddress, asic->AsicId, &unicode_name);
+
+ status = RtlAppendUnicodeStringToString(&unicode_asic,&unicode_name);
+
+ InitializeObjectAttributes( &asic_attributes, &unicode_asic,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&asic_handle, KEY_READ | KEY_WRITE, &asic_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+
+
+// Asic ID
+
+ RtlInitUnicodeString(&unicode_asic_id,L"ID");
+ tmp = asic->AsicId;
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+// Asic JtagId
+
+ RtlInitUnicodeString(&unicode_asic_id,L"JtagID");
+ tmp = *((PULONG)(&(asic->JtagId[0])));
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+// Asic Type
+ RtlInitUnicodeString(&unicode_asic_id,L"Type");
+ tmp = asic->AsicType;
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// Asic Location
+ RtlInitUnicodeString(&unicode_asic_id,L"Location");
+ tmp = asic->AsicLocation;
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ RtlInitUnicodeString(&unicode_asic_id,L"InstructionRegisterLength");
+ tmp = asic->InstructionRegisterLength;
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ RtlInitUnicodeString(&unicode_asic_id,L"BitLocation");
+ tmp = asic->BitLocation;
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ RtlInitUnicodeString(&unicode_asic_id,L"SubaddressSpace");
+ tmp = asic->SubaddressSpace;
+ status = ZwSetValueKey(asic_handle, &unicode_asic_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ status = ZwClose(asic_handle);
+ }
+
+ status = ZwClose(asics_handle);
+}
+
+
+
+
+VOID
+HalpCatReportModuleSubModules (
+ PUNICODE_STRING UnicodeModule,
+ PMODULE Module
+ )
+
+/*++
+
+Routine Description:
+ Place information about system modules into the registry.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PMODULE module;
+
+ UNICODE_STRING unicode_submodules;
+ OBJECT_ATTRIBUTES submodules_attributes;
+ WCHAR submodules_buffer[256];
+
+ UNICODE_STRING unicode_module;
+ OBJECT_ATTRIBUTES module_attributes;
+ WCHAR module_buffer[256];
+
+ UNICODE_STRING unicode_module_id;
+
+ UNICODE_STRING unicode_name;
+ WCHAR name_buffer[256];
+
+ HANDLE submodules_handle;
+ HANDLE module_handle;
+
+ NTSTATUS status;
+ ULONG tmp;
+
+
+ unicode_submodules.Length = 0;
+ unicode_submodules.MaximumLength=256;
+ unicode_submodules.Buffer = submodules_buffer;
+ RtlZeroMemory(unicode_submodules.Buffer,unicode_submodules.MaximumLength);
+
+ RtlCopyUnicodeString(&unicode_submodules,UnicodeModule);
+ status = RtlAppendUnicodeToString(&unicode_submodules,L"\\SubModules");
+
+ InitializeObjectAttributes( &submodules_attributes, &unicode_submodules,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&submodules_handle, KEY_READ | KEY_WRITE, &submodules_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+
+ for (module = Module->SubModules; module != NULL; module = module->Next) {
+
+/* Module directory */
+
+ unicode_module.Length = 0;
+ unicode_module.MaximumLength=256;
+ unicode_module.Buffer = module_buffer;
+ RtlZeroMemory(unicode_module.Buffer,unicode_module.MaximumLength);
+
+ RtlCopyUnicodeString(&unicode_module,&unicode_submodules);
+ status = RtlAppendUnicodeToString(&unicode_module,L"\\");
+
+ unicode_name.Length = 0;
+ unicode_name.MaximumLength=256;
+ unicode_name.Buffer = name_buffer;
+
+ NCRCatModuleName(module->ModuleAddress,&unicode_name);
+
+ status = RtlAppendUnicodeStringToString(&unicode_module,&unicode_name);
+
+ InitializeObjectAttributes( &module_attributes, &unicode_module,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&module_handle, KEY_READ | KEY_WRITE, &module_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+/* Module ID */
+
+ RtlInitUnicodeString(&unicode_module_id,L"ID");
+ tmp = module->ModuleAddress;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// EEProm size
+ RtlInitUnicodeString(&unicode_module_id,L"EEpromSize");
+ tmp = module->EEpromSize;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// Number of Asics
+ RtlInitUnicodeString(&unicode_module_id,L"NumberOfAsics");
+ tmp = module->NumberOfAsics;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// InstructionBits
+ RtlInitUnicodeString(&unicode_module_id,L"InstructionBits");
+ tmp = module->InstructionBits;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// LargestRegister
+ RtlInitUnicodeString(&unicode_module_id,L"LargestRegister");
+ tmp = module->LargestRegister;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// Smallest Register
+ RtlInitUnicodeString(&unicode_module_id,L"SmallestRegister");
+ tmp = module->SmallestRegister;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ if (module->SubModules) {
+ HalpCatReportModuleSubModules(&unicode_module,module);
+ }
+
+ if (module->Asic) {
+ HalpCatReportModuleAsics(&unicode_module,module);
+ }
+
+ status = ZwClose(module_handle);
+ }
+ status = ZwClose(submodules_handle);
+}
+
+
+
+
+
+VOID
+HalpCatReportSystemModules (
+ )
+
+/*++
+
+Routine Description:
+ Place information about system modules into the registry.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PMODULE module;
+ PASIC asic;
+
+ PWSTR catbus_path = L"\\Registry\\Machine\\Hardware\\DeviceMap\\CatBus";
+ PWSTR modules_path = L"\\Registry\\Machine\\Hardware\\DeviceMap\\CatBus\\Modules";
+
+
+ UNICODE_STRING unicode_catbus;
+ OBJECT_ATTRIBUTES catbus_attributes;
+ UNICODE_STRING unicode_catbus_id;
+
+ UNICODE_STRING unicode_modules;
+ OBJECT_ATTRIBUTES modules_attributes;
+
+ UNICODE_STRING unicode_module;
+ OBJECT_ATTRIBUTES module_attributes;
+ WCHAR module_buffer[256];
+
+ UNICODE_STRING unicode_module_id;
+
+ UNICODE_STRING unicode_name;
+ WCHAR name_buffer[256];
+
+ HANDLE catbus_handle;
+ HANDLE modules_handle;
+ HANDLE module_handle;
+
+ NTSTATUS status;
+ ULONG tmp;
+
+
+/*
+ * CatBus
+ */
+ RtlInitUnicodeString(&unicode_catbus,catbus_path);
+
+ InitializeObjectAttributes( &catbus_attributes, &unicode_catbus,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&catbus_handle, KEY_READ | KEY_WRITE, &catbus_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+// NCR Hal Version Number
+ RtlInitUnicodeString(&unicode_catbus_id,L"HalVersion");
+ tmp = NCR_VERSION_NUMBER;
+ status = ZwSetValueKey(catbus_handle, &unicode_catbus_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+/*
+ * Modules
+ */
+ RtlInitUnicodeString(&unicode_modules,modules_path);
+
+ InitializeObjectAttributes( &modules_attributes, &unicode_modules,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&modules_handle, KEY_READ | KEY_WRITE, &modules_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+
+ for (module = NCRCatModuleList; module != NULL; module = module->Next) {
+
+/* Module directory */
+
+ unicode_module.Length = 0;
+ unicode_module.MaximumLength=256;
+ unicode_module.Buffer = module_buffer;
+ RtlZeroMemory(unicode_module.Buffer,unicode_module.MaximumLength);
+
+ RtlCopyUnicodeString(&unicode_module,&unicode_modules);
+ status = RtlAppendUnicodeToString(&unicode_module,L"\\");
+
+ unicode_name.Length = 0;
+ unicode_name.MaximumLength=256;
+ unicode_name.Buffer = name_buffer;
+
+ NCRCatModuleName(module->ModuleAddress,&unicode_name);
+
+ status = RtlAppendUnicodeStringToString(&unicode_module,&unicode_name);
+
+ InitializeObjectAttributes( &module_attributes, &unicode_module,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&module_handle, KEY_READ | KEY_WRITE, &module_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+/* Module ID */
+
+ RtlInitUnicodeString(&unicode_module_id,L"ID");
+ tmp = module->ModuleAddress;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// EEProm size
+ RtlInitUnicodeString(&unicode_module_id,L"EEpromSize");
+ tmp = module->EEpromSize;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// Number of Asics
+ RtlInitUnicodeString(&unicode_module_id,L"NumberOfAsics");
+ tmp = module->NumberOfAsics;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// InstructionBits
+ RtlInitUnicodeString(&unicode_module_id,L"InstructionBits");
+ tmp = module->InstructionBits;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// LargestRegister
+ RtlInitUnicodeString(&unicode_module_id,L"LargestRegister");
+ tmp = module->LargestRegister;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+// Smallest Register
+ RtlInitUnicodeString(&unicode_module_id,L"SmallestRegister");
+ tmp = module->SmallestRegister;
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ if (module->SubModules) {
+ //
+ // This is a Quad board
+ //
+ // Larc size
+ //
+ RtlInitUnicodeString(&unicode_module_id,L"LARCPages");
+ tmp = NCRLarcEnabledPages[module->ModuleAddress&0xf];
+ status = ZwSetValueKey(module_handle, &unicode_module_id, 0, REG_DWORD, &tmp, sizeof(ULONG));
+
+ HalpCatReportModuleSubModules(&unicode_module,module);
+ }
+
+ if (module->Asic) {
+ HalpCatReportModuleAsics(&unicode_module,module);
+ }
+
+ status = ZwClose(module_handle);
+ }
+ status = ZwClose(modules_handle);
+ status = ZwClose(catbus_handle);
+
+
+}
+
+
+
+VOID
+HalpCatPowerOffSystem (
+ )
+
+/*++
+
+Routine Description:
+ Sends command to PSI to shut off the power to the system.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+
+
+ cat_control.Module = PSI;
+ cat_control.Asic = CAT_I;
+
+//
+// check position of Front panel switch to see if we need to enable it
+// if the switch is in the off position then enable it
+//
+
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = PSI_General_Ps_Status_L5;
+ cat_control.NumberOfBytes = 1;
+
+ HalCatBusIo(&cat_control, &data);
+
+ if (!(data & PSI_PowerSwitch_On)) {
+ cat_control.Command = WRITE_SUBADDR;
+ cat_control.Address = PSI_General_Ps_Status_L5;
+ cat_control.NumberOfBytes = 1;
+
+ data = PSI_Enable_FrontSwitch;
+
+ HalCatBusIo(&cat_control, &data);
+ }
+
+ cat_control.Command = WRITE_SUBADDR;
+ cat_control.Address = PSI_General_Ps_Status_L5;
+ cat_control.NumberOfBytes = 1;
+
+ data = PSI_Set_AlarmEnable;
+
+ HalCatBusIo(&cat_control, &data);
+
+ //
+ // Power down the machine
+ //
+
+ data = PSI_SoftwarePowerDown1;
+
+ HalCatBusIo(&cat_control, &data);
+
+ return;
+}
+
+
+VOID
+HalPowerOffSystem (
+ BOOLEAN PowerOffSystem
+ )
+
+/*++
+
+Routine Description:
+ Set a flag so HalReturnToFirmware will poweroff instead of reboot.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ NCRPowerOffSystem = PowerOffSystem;
+}
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halncr/i386/ncrcat.h b/private/ntos/nthals/halncr/i386/ncrcat.h
new file mode 100644
index 000000000..73df6d7aa
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrcat.h
@@ -0,0 +1,308 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncrcat.h
+
+Author:
+
+Abstract:
+
+ System equates for dealing with the NCR Cat Bus.
+
+++*/
+
+#ifndef _NCRCAT_
+#define _NCRCAT_
+
+/*
+ * Cat bus driver error codes
+ */
+
+#define CATNOERR 0
+#define CATIO 1 /* I/O error */
+#define CATFAULT 2 /* Bad address */
+#define CATACCESS 3 /* Permission denied */
+#define CATINVAL 4 /* Invalid argument */
+#define CATNOMOD 5 /* Module not found */
+#define CATNOASIC 6 /* Asic not found */
+
+
+/*
+ * CAT Bus Driver Commands
+ */
+
+
+#define READ_REGISTER 1 /* Read a register */
+#define WRITE_REGISTER 2 /* Write a register */
+#define READ_SUBADDR 3 /* Read from the subaddress area */
+#define WRITE_SUBADDR 4 /* Write to the subaddress area */
+
+
+/*
+ * Modules and ASICs for the Level 5
+ */
+
+#define PROCESSOR0 0x10 /* Processor Module 0 */
+#define PROCESSOR1 0x11 /* Processor Module 1 */
+#define PROCESSOR2 0x12 /* Processor Module 2 */
+#define PROCESSOR3 0x13 /* Processor Module 3 */
+#define NoModule0 0x1b /* No Module address */
+#define PROCESSOR4 0x1c /* Processor Module 4 */
+#define PROCESSOR5 0x1d /* Processor Module 5 */
+#define PROCESSOR6 0x1e /* Processor Module 6 */
+#define PROCESSOR7 0x1f /* Processor Module 7 */
+#define QUAD_BBID 1
+#define QUAD_LL2_AID 2
+#define QUAD_LL2_BID 3
+#define QUAD_BB0 (QUAD_BBID<<5|PROCESSOR0)
+#define QUAD_BB1 (QUAD_BBID<<5|PROCESSOR1)
+#define QUAD_BB2 (QUAD_BBID<<5|PROCESSOR2)
+#define QUAD_BB3 (QUAD_BBID<<5|PROCESSOR3)
+#define QUAD_BB4 (QUAD_BBID<<5|PROCESSOR4)
+#define QUAD_BB5 (QUAD_BBID<<5|PROCESSOR5)
+#define QUAD_BB6 (QUAD_BBID<<5|PROCESSOR6)
+#define QUAD_BB7 (QUAD_BBID<<5|PROCESSOR7)
+#define QUAD_LL2_A0 (QUAD_LL2_AID<<5|PROCESSOR0)
+#define QUAD_LL2_A1 (QUAD_LL2_AID<<5|PROCESSOR1)
+#define QUAD_LL2_A2 (QUAD_LL2_AID<<5|PROCESSOR2)
+#define QUAD_LL2_A3 (QUAD_LL2_AID<<5|PROCESSOR3)
+#define QUAD_LL2_A4 (QUAD_LL2_AID<<5|PROCESSOR4)
+#define QUAD_LL2_A5 (QUAD_LL2_AID<<5|PROCESSOR5)
+#define QUAD_LL2_A6 (QUAD_LL2_AID<<5|PROCESSOR6)
+#define QUAD_LL2_A7 (QUAD_LL2_AID<<5|PROCESSOR7)
+#define QUAD_LL2_B0 (QUAD_LL2_BID<<5|PROCESSOR0)
+#define QUAD_LL2_B1 (QUAD_LL2_BID<<5|PROCESSOR1)
+#define QUAD_LL2_B2 (QUAD_LL2_BID<<5|PROCESSOR2)
+#define QUAD_LL2_B3 (QUAD_LL2_BID<<5|PROCESSOR3)
+#define QUAD_LL2_B4 (QUAD_LL2_BID<<5|PROCESSOR4)
+#define QUAD_LL2_B5 (QUAD_LL2_BID<<5|PROCESSOR5)
+#define QUAD_LL2_B6 (QUAD_LL2_BID<<5|PROCESSOR6)
+#define QUAD_LL2_B7 (QUAD_LL2_BID<<5|PROCESSOR7)
+#define CATbaseModule(id) ((id)&0x1f)
+#define CATsubModule(id) ((id)>>5)
+
+#define MEMORY0 0x14 /* Memory Module 0 */
+#define MEMORY1 0x15 /* Memory Module 1 */
+#define PRIMARYMC 0x18 /* Primary Micro Channel */
+#define SECONDARYMC 0x19 /* Secondary Micro Channel */
+#define PSI 0x1A /* Power Supply Interface Module */
+#define CAT_LPB_MODULE 0x00 /* Local Peripheral Board - non CAT */
+
+#define CAT_I 0x00 /* Configure and Test Interface ASIC; Always */
+ /* ASIC 0 on every module */
+
+#define NUM_PROCESSOR_CARDS 4
+#define NUM_MEMORY_CARDS 2
+#define NUM_MC_SLOTS 8
+#define NUM_MC_BUSES 2
+
+
+
+/*
+ * CAT_I is the only ASIC on the Processor Module
+ */
+
+/*
+ * ASIC IDs for the Memory Module
+ */
+
+#define MMC1 1 /* Magellan Memory Controller 1 ASIC */
+#define MMA1 2 /* Magellan Memory Address 1 ASIC */
+#define MMD1_0 3 /* Magellan Memeory Data 1 Slice 0 */
+#define MMD1_1 4 /* Magellan Memeory Data 1 Slice 1 */
+#define MMD1_2 5 /* Magellan Memeory Data 1 Slice 2 */
+#define MMD1_3 6 /* Magellan Memeory Data 1 Slice 3 */
+
+/*
+ * ASIC IDs for the Primary Micro Channel
+ */
+
+#define PMC_MCADDR 1 /* Micro Channel Address/Controller */
+#define PMC_DMA 2 /* DMA Controller */
+#define PMC_DS1 3 /* Memory Controller Data Slice 1 */
+#define PMC_DS0 4 /* Memory Controller Data Slice 0 */
+#define PMC_VIC 5 /* Voyager Interrupt Controller ASIC */
+#define PMC_ARB 6 /* Dual System Bus Arbiter ASIC */
+#define PMC_DS2 7 /* Memory Controller Data Slice 2 */
+#define PMC_DS3 8 /* Memory Controller Data Slice 3 */
+
+/*
+ * ASIC IDs for the Secondary Micro Channel
+ */
+
+/*
+ * SMC ASIC ID's listed in scan path order
+ */
+
+#define SMC_MCADDR 1 /* Micro Channel Address/Controller */
+#define SMC_DS1 3 /* Memory Controller Data Slice 1 */
+#define SMC_DS0 4 /* Memory Controller Data Slice 0 */
+#define SMC_DMA 2 /* DMA Controller */
+#define SMC_DS2 7 /* Memory Controller Data Slice 2 */
+#define SMC_DS3 8 /* Memory Controller Data Slice 3 */
+
+
+
+
+/*
+ * common CATI registers
+ */
+
+typedef struct _CAT_REGISTERS {
+ UCHAR Config0; /* CAT id */
+ UCHAR Config1; /* CAT device info */
+ UCHAR Control2; /* CAT control bits */
+ UCHAR Config3; /* subaddress read/write */
+ UCHAR Config4; /* user defined configuration */
+ UCHAR Config5; /* user defined configuration */
+ UCHAR SubAddress6; /* low byte */
+ UCHAR SubAddress7; /* high byte */
+ UCHAR Config8; /* user defined configuration */
+ UCHAR Config9; /* user defined configuration */
+ UCHAR ConfigA; /* user defined configuration */
+ UCHAR ConfigB; /* user defined configuration */
+ UCHAR ConfigC; /* user defined configuration */
+ UCHAR ConfigD; /* user defined configuration */
+ UCHAR ConfigE; /* user defined configuration */
+ UCHAR StatusF; /* CAT status bits */
+} CAT_REGISTERS, *PCAT_REGISTERS;
+
+
+/*
+ * Processor Asic
+ */
+
+#define PBC_Status 0x0F
+
+/* ASIC ID's for the Processor Module */
+#define A_PBC 1
+#define B_PBC 2
+
+/* ASIC ID's for the Quad Baseboard (QBB) */
+#define QDATA1 1
+#define QDATA0 2
+#define QABC 3
+
+/* ASIC ID's for the Large Level 2 Cache Submodule (LL2) */
+#define QCC0 4
+#define QCC1 5
+#define QCD0 6
+#define QCD1 7
+
+/*
+ * Micro Channel I/F Address/Contrlo (MCADDR) ASICs
+ */
+
+#define MCADDR 0xC0
+
+/*
+ * Micro Channel Interface Data Slice (MCDATA) ASICs; One for each System Bus
+ */
+
+#define MCDATA_A 0xC4 /* MCDATA for bus A */
+#define MCDATA_B 0xC5 /* MCDATA for bus B */
+
+/*
+ * System Bus Arbiter (SBA) ASIC
+ */
+
+#define SBA 0xC1
+
+/*
+ * Voyager Interrupt Controller (VIC) ASIC
+ */
+
+#define VIC 0xC8
+
+/*
+ * DMA Controller (DMA) ASIC
+ */
+
+#define DMA 0xC9
+
+/*
+ * COUGAR ASIC
+ */
+
+#define COUGAR 0xE0
+
+/*
+ * LPB EEPROM Address
+ */
+
+#define LPB_EEPROM_ADDRESS 0xFFF5E000 /* LPB EEPROM */
+
+
+
+
+typedef struct _CAT_CONTROL {
+ UCHAR Module; // Module ID
+ UCHAR Asic; // ASIC ID
+ UCHAR Command; // CAT bus driver command
+ USHORT Address; // Register or Sub address
+ USHORT NumberOfBytes; // Number of bytes to read/write
+} CAT_CONTROL, *PCAT_CONTROL;
+
+
+
+//
+// Micro Channel slot information
+//
+
+#define NUM_POS_REGISTERS 8
+#define POS_Setup 0x96
+#define POS_Slot0 0x78 /* select slot 0 */
+
+//
+// POS Space Definitions
+//
+
+#define POS_0 0x100
+#define POS_1 0x101
+#define POS_2 0x102
+#define POS_3 0x103
+#define POS_4 0x104
+#define POS_5 0x105
+#define POS_6 0x106
+#define POS_7 0x107
+
+
+/*
+ * Cat bus driver function prototypes.
+ */
+
+BOOLEAN
+HalCatBusAvailable (
+ );
+
+LONG
+HalCatBusIo (
+ IN PCAT_CONTROL CatControl,
+ IN OUT PUCHAR Buffer
+ );
+
+
+VOID
+HalCatBusReset (
+ );
+
+
+
+LONG
+HalpCatBusIo (
+ IN PCAT_CONTROL CatControl,
+ IN OUT PUCHAR Buffer
+ );
+
+
+VOID
+HalPowerOffSystem (
+ IN BOOLEAN PowerOffSystem
+ );
+
+
+#endif // _NCRCAT_
diff --git a/private/ntos/nthals/halncr/i386/ncrcatlk.asm b/private/ntos/nthals/halncr/i386/ncrcatlk.asm
new file mode 100644
index 000000000..b720a4142
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrcatlk.asm
@@ -0,0 +1,120 @@
+ title "CAT Bus Lock Routines"
+;++
+;
+; Module Name:
+;
+; ncrcatlk.asm
+;
+; Abstract:
+;
+; Procedures necessary to lock CAT bus.
+;
+; Author:
+;
+; Rick Ulmer (rick.ulmer@columbiasc.ncr.com) 29 Apr 1993
+;
+; Revision History:
+;
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include mac386.inc
+ .list
+
+ extrn _HalpCatBusLock:DWORD
+
+_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
+;
+; Hold the value of the eflags register before a CAT bus spinlock is
+; acquired (used in HalpAcquire/ReleaseCatBusSpinLock().
+;
+_HalpCatBusFlags dd 0
+
+_DATA ends
+
+ subttl "HalpAcquireCatBusSpinLock"
+_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; Routine Description:
+;
+; Acquires a spinlock to access the CAT bus. The CAT bus is
+; accessed at different irql levels, so to be safe, we 'cli'.
+; We could replace that to raise irql to PROFILE_LEVEL, but that's
+; a lot of code.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; Interrupt is disabled.
+; Irql level not affected.
+; Flags saved in _HalpCatBusLockFlags.
+;--
+
+cPublicProc _HalpAcquireCatBusSpinLock ,0
+ push eax
+
+ align 4
+HArsl01:
+ pushfd
+ cli
+ lea eax, _HalpCatBusLock
+ ACQUIRE_SPINLOCK eax, HArsl90
+ pop _HalpCatBusFlags ; save flags for release S.L.
+ pop eax
+ stdRET _HalpAcquireCatBusSpinLock
+
+ align 4
+HArsl90:
+ popfd
+ SPIN_ON_SPINLOCK eax, <HArsl01>
+
+stdENDP _HalpAcquireCatBusSpinLock
+
+
+ subttl "HalpReleaseCatBusSpinLock"
+;++
+;
+; Routine Description:
+;
+; Release spinlock, and restore flags to the state it was before
+; acquiring the spinlock.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; Interrupts restored to their state before acquiring spinlock.
+; Irql level not affected.
+;
+;--
+
+cPublicProc _HalpReleaseCatBusSpinLock ,0
+ push eax
+ ;
+ ; restore eflags as it was before acquiring spinlock. Put it on
+ ; stack before releasing spinlock (so other cpus cannot overwrite
+ ; it with their own eflags).
+ ;
+ push _HalpCatBusFlags ; old eflags on stack.
+ lea eax, _HalpCatBusLock
+ RELEASE_SPINLOCK eax
+ popfd ; restore eflags.
+ pop eax
+ stdRET _HalpReleaseCatBusSpinLock
+stdENDP _HalpReleaseCatBusSpinLock
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halncr/i386/ncrcatp.h b/private/ntos/nthals/halncr/i386/ncrcatp.h
new file mode 100644
index 000000000..44f2caffa
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrcatp.h
@@ -0,0 +1,232 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncrcat.h
+
+Author:
+
+Abstract:
+
+ System equates for dealing with the NCR Cat Bus.
+
+++*/
+
+#ifndef _NCRCATP_
+#define _NCRCATP_
+
+/*
+ * Ports
+ */
+
+#define MAX_REG_SIZE 0x04 /* Maximum instruction register size */
+#define MAX_SCAN_PATH 0x100 /* Maximum size of a scan path */
+
+#define SUBADDR_ZERO 0x00 /* No sub address space */
+#define SUBADDR_LO 0xff /* 256 byte sub address space */
+#define SUBADDR_HI 0xffff /* 64K sub address space */
+#define MAXSUBADDR 0xffff /* Maximum sub address space */
+#define PSI_EEPROM_SIZE 0x8000 /* Size of the PSI EEPROM */
+#define EEPROM_SIZE 0x2000 /* Default size of the EEPROM */
+#define MAXNUMREG 0x10 /* Maximum number of registers in an ASIC */
+
+/* Ports */
+#define SELECT_PORT 0x97 /* port value to select module */
+#define BASE_PORT 0x98 /* contains base address */
+#define DATA_OFFSET 0x0D /* base addr + DATA_OFFSET => data port */
+#define COMMAND_OFFSET 0x0E /* base addr + COMMAND_OFFSET => command port */
+
+#define RESET 0x00 /* Reset the CAT bus w/o updating */
+#define DESELECT 0xFF /* Deselect the CAT bus */
+
+/* Valid CAT controller commands */
+#define IRCYC 0x01 /* start instruction register cycle */
+#define DRCYC 0x02 /* start data register cycle */
+#define RUN 0x0F /* move to execute state */
+#define END 0x80 /* end operation */
+#define HOLD 0x90 /* hold in idle state */
+#define STEP 0xE0 /* single step an "intest" vector */
+#define CLEMSON 0xFF /* return cat controller to CLEMSON mode */
+
+/* Supported ASIC Commands */
+#define READ_CONFIG 0x01 /* read config register */
+#define WRITE_CONFIG 0x02 /* write config register */
+#define BYPASS 0xFF /* place asic in bypass mode */
+
+/* Defines for CAT_I control */
+#define AUTO_INC 0x04 /* OR w/ reg 2 for auto increment */
+#define NO_AUTO_INC 0xFB /* AND w/ reg 2 for no auto increment */
+#define CONNECT_ASICS 0x01 /* OR w/ reg 5 value to connect scan path */
+#define DISCONNECT_ASIC 0xFE /* AND w/ reg 5 value to disconnect scan path */
+#define RESET_STATE 0x00 /* Used to blindly disconnect the scan path */
+
+/* Defines for special registers */
+#define ASIC_ID_REG 0x00 /* Reg which contains the ASIC ID; Level 4 */
+#define ASIC_TYPE_REG 0x01 /* Reg which contains ASIC type; Level 4*/
+#define AUTO_INC_REG 0x02 /* Reg which contains auto increment bit */
+#define SUBADDRDATA 0x03 /* Reg w/ data for subaddr read/write */
+#define SCANPATH 0x05 /* Reg which contains scan path bit; Level 5 */
+#define SUBADDRLO 0x06 /* Reg w/ low byte for subaddr read/write */
+#define SUBADDRHI 0x07 /* Reg w/ high byte for subaddr read/write */
+#define SUBMODSELECT 0x08 /* Reg which contains submodule select bits */
+#define SUBMODPRESENT 0x09 /* Reg which contains submodule present bits */
+
+#define MAXSUBMOD 0x3 /* max # of submodules, BB counts as one */
+#define BASE_BOARD_SHIFT 0x1 /* shift required to or in presence of BB */
+#define BASE_BOARD_PRESENT 0x1 /* signifies presence of BB */
+
+#define HEADER 0x7F /* Header to check hw is setup correctly */
+#define DEFAULT_INST 0x01 /* The default CAT_I instruction is xxxxxx01 */
+#define CHAR_SIZE 0x08 /* Number of bits in a "char" */
+#define EEPROMPAGESIZE 0x40 /* Number of bytes in a EEPROM page */
+#define MAXREADS 0x10 /* Max EEPROM reads to varify write */
+#define WRITEDELAY 0x250 /* Number of tenmicrosec delays for write to */
+
+
+
+typedef struct _ASIC {
+ UCHAR AsicType; // ASIC type
+ UCHAR AsicId; // ASIC ID
+ UCHAR JtagId[4]; // JTAG ID
+ UCHAR AsicLocation; // Location within scan path, start with 0
+ USHORT BitLocation; // Location with bit stream, start with 0
+ UCHAR InstructionRegisterLength; // Instruction register length
+ USHORT SubaddressSpace; // Amount of sub address space
+ struct _ASIC *Next; // Next ASIC in linked list
+} ASIC, *PASIC;
+
+
+
+
+
+typedef struct _MODULE {
+ UCHAR ModuleAddress; // Module address
+ USHORT EEpromSize; // Size of the EEPROM
+ USHORT NumberOfAsics; // Number of ASICs
+ USHORT InstructionBits; // Instruction bits in the scan path
+ USHORT LargestRegister; // Largest register in the scan path
+ USHORT SmallestRegister; // Smallest register in the scan path
+ USHORT ScanPathConnected; // Scan path connected
+ PASIC Asic; // First ASIC in scan path, always a CAT_I
+ struct _MODULE *SubModules; // Submodule pointer
+ struct _MODULE *Next; // Next module in linked list
+} MODULE, *PMODULE;
+
+
+
+
+/*
+ * eeprom data structure
+ */
+
+/*
+ * Module Header
+ */
+
+#pragma pack(1)
+typedef struct _MODULE_HEADER {
+ UCHAR ModuleId[4]; // maybe unionize
+ UCHAR VersionId; // version id
+ UCHAR ConfigId; // configuration id
+ USHORT BoundryId; // boundary scan id
+ USHORT EEpromSize; // size of EEPROM
+ UCHAR Assembly[11]; // assembly #
+ UCHAR AssemblyRevision; // assembly revision
+ UCHAR Tracer[4]; // tracer number
+ USHORT AssemblyCheckSum; // assembly check sum
+ USHORT PowerConsumption; // power requirements
+ USHORT NumberOfAsics; // number of asics
+ USHORT MinBistTime; // min. bist time
+ USHORT ErrorLogOffset; // error log offset
+ USHORT ScanPathOffset; // scan path table offset
+ USHORT CctOffset; // cct offset
+ USHORT LogLength; // length of error log
+ USHORT CheckSumEnd; // offset to end of cksum
+ UCHAR Reserved[4]; // reserved
+ UCHAR StartingSentinal; // starting sentinal
+ UCHAR PartNumber[13]; // prom part number
+ UCHAR Version[10]; // version number
+ UCHAR Signature[8]; // signature
+ USHORT EEpromCheckSum; // eeprom checksum
+ ULONG DataStampOffset; // date stamp offset
+ UCHAR EndingSentinal; // ending sentinal
+} MODULE_HEADER, *PMODULE_HEADER;
+
+#pragma pack()
+
+#define EEPROM_DATA_START 0x00
+#define EEPROM_SIZE_OFFSET 0x08
+#define XSUM_END_OFFSET 0x2A
+
+
+/*
+ * Scan Path Table
+ */
+
+
+#pragma pack(1)
+typedef struct _SCAN_PATH_TABLE {
+ UCHAR AsicId; // ASIC ID
+ UCHAR BypassFlag; // Bypass Flag
+ USHORT AsicDataOffset; // ASIC data table
+ USHORT ConfigDataOffset; // config tbl ptr
+} SCAN_PATH_TABLE, *PSCAN_PATH_TABLE;
+
+#pragma pack()
+
+/*
+ * JTAG Table
+ */
+
+#pragma pack(1)
+typedef struct _JTAG_TABLE {
+ UCHAR IdCode[4]; // IDCODE
+ UCHAR RunBist[4]; // RUNBIST
+ UCHAR InTest[4]; // INTEST
+ UCHAR SamplePreload[4]; // SAMPLE/PRELOAD
+ UCHAR InstructionRegisterLength; // IR length
+} JTAG_TABLE, *PJTAG_TABLE;
+#pragma pack()
+
+/*
+ * Asic Information Table
+ */
+
+#pragma pack(1)
+typedef struct _ASIC_DATA_TABLE {
+ UCHAR JtagId[4]; // JTAG ID
+ USHORT LengthBsr; // BSR length
+ USHORT LengthBistRegister; // BIST register length
+ ULONG BistClockLength; // BIST clock length
+ USHORT SubaddressBits; // # bits in subaddress
+ USHORT SeedBits; // BIST seed length
+ USHORT SignatureBits; // BIST signature length
+ USHORT JtagOffset; // JTAG tbl ptr
+} ASIC_DATA_TABLE, *PASIC_DATA_TABLE;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct _MODULE_ID {
+ UCHAR ModuleName[5]; // MODULE IDENTIFIER
+} MODULE_ID, *PMODULE_ID;
+#pragma pack()
+
+
+VOID
+HalpInitializeCatBusDriver (
+ );
+
+VOID
+HalpCatReportSystemModules (
+ );
+
+
+VOID
+HalpCatPowerOffSystem (
+ );
+
+
+#endif // _NCRCATP
diff --git a/private/ntos/nthals/halncr/i386/ncrclock.asm b/private/ntos/nthals/halncr/i386/ncrclock.asm
new file mode 100644
index 000000000..da69aee8a
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrclock.asm
@@ -0,0 +1,724 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ncrclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT. It works on UP and SystemPro.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\ixcmos.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ncr.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ EXTRNP _HalQicRequestIpi,2
+ extrn _NCRActiveProcessorLogicalMask:DWORD
+ extrn _NCRLogicalNumberToPhysicalMask:DWORD
+ extrn _HalpSystemHardwareLock:DWORD
+ extrn _NCRLogicalDyadicProcessorMask:DWORD
+ extrn _NCRLogicalQuadProcessorMask:DWORD
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193000
+
+;
+; ==== Values used for System Clock ====
+;
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec.
+;
+;
+; The best fit value closest to 10ms (but not below) is 10.0144012689ms:
+; ROLLOVER_COUNT 11949
+; TIME_INCREMENT 100144
+; Calculated error is -.0109472 s/day
+;
+; The best fit value closest to 15ms (but not above) is 14.9952019ms:
+; ROLLOVER_COUNT 17892
+; TIME_INCREMENT 149952
+; Calculated error is -.0109472 s/day
+;
+; On 486 class machines or better we use a 10ms tick, on 386
+; class machines we use a 15ms tick
+;
+
+ROLLOVER_COUNT EQU 11949
+TIME_INCREMENT EQU 100144
+
+_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
+
+ public _HalpIpiClock
+_HalpIpiClock dd 0 ; Processors to IPI clock pulse to
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+
+_Halp8254Lock dd 0
+
+ public HalpPerfCounterLow
+ public HalpPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpPerfCounterInit dd 0
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0
+;
+; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalpInitializeClock ,0
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov ecx, ROLLOVER_COUNT
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+
+;
+; Fill in PCR value with TIME_INCREMENT
+;
+ mov edx, TIME_INCREMENT
+ stdCall _KeSetTimeIncrement, <edx, edx>
+
+ mov HalpPerfCounterInit, 1 ; Indicate performance counter
+ ; has been initialized.
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter ,1
+
+ push ebx
+ push esi
+
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before 8254
+; initialization has occured. Reading garbage off the 8254 is not reasonable.
+;
+ cmp HalpPerfCounterInit, 0
+ jne Kqpc01 ; ok, perf counter has been initialized
+
+;
+; Initialization hasn't occured yet, so just return zeroes.
+;
+ mov eax, 0
+ mov edx, 0
+ jmp Kqpc20
+
+Kqpc01:
+Kqpc11: pushfd
+ cli
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+; NOTE:
+; Need to watch for Px reading the 'CounterLow', P0 updates both
+; then Px finishes reading 'CounterHigh' [getting the wrong value].
+; After reading both, make sure that 'CounterLow' didn't change.
+; If it did, read it again. This way, we won't have to use a spinlock.
+;
+
+@@:
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+ cmp ebx, HalpPerfCounterLow ;
+ jne @b
+;
+; Fetch the current counter value from the hardware
+;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+ jmp $+2
+
+
+;
+; Fetch the base value again.
+;
+
+@@:
+ mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+
+ cmp eax, HalpPerfCounterLow
+ jne @b
+
+;
+; Compare the two reads of Performance counter. If they are different,
+; simply returns the new Performance counter. Otherwise, we add the hardware
+; count to the performance counter to form the final result.
+;
+
+ cmp eax, ebx
+ jne short Kqpc20
+ cmp edx, esi
+ jne short Kqpc20
+ neg ecx ; PIT counts down from 0h
+ add ecx, ROLLOVER_COUNT
+ add eax, ecx
+ adc edx, 0 ; [edx:eax] = Final result
+
+;
+; Return the counter
+;
+
+Kqpc20:
+ ; return value is in edx:eax
+
+;
+; Return the freq. if caller wants it.
+;
+
+ or dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc99 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc99:
+ pop esi ; restore esi and ebx
+ pop ebx
+ stdRET _KeQueryPerformanceCounter
+
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc11>
+
+stdENDP _KeQueryPerformanceCounter
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine resets the performance counter value for the current
+; processor to zero. The reset is done such that the resulting value
+; is closely synchronized with other processors in the configuration.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ mov eax, [esp+4] ; ponter to Number
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ ;
+ ; Nothing to calibrate on a NCR MP machine...
+ ;
+
+ popfd ; restore interrupt flag
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; dismiss interrupt and raise Irql
+;
+
+ cmp byte ptr PCR[PcIrql], CLOCK2_LEVEL
+ jae SpuriousClock
+
+ push NCR_CPI_VECTOR_BASE ; SEE NOTE BELOW!
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,CLOCK_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz SpuriousClock2
+
+; turn off the interrupt via system control port b - since HalMakeBeep also
+; accesses system control port b (speaker control) and uses the 8254 spin lock,
+; we will too
+
+Hci11: pushfd
+ cli
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax,Hci99
+
+ in al, 61h
+ jmp $+2
+ or al, 80h
+ out 61h, al
+ jmp $+2
+
+ align dword
+@@:
+ lea ebx, _Halp8254Lock
+ RELEASE_SPINLOCK ebx
+ popfd
+
+;
+; Both IPI's and Clock interrupts are processed at the same priority
+; level by the hardware. NT needs IPI priorities to be higher then
+; the Clock interrupt (irq 0) - we handle this by EOI-ing the clock
+; interrupt before calling the kernel so IPI interrupts can still
+; arrive. If another clock interrupt comes in, it will be ignored.
+;
+; The kernel will also call HalEndSystemInterrupt to dismiss the clock
+; interrupt. The vector passed to the kernel is one which will not cause
+; the hardware to be EOIed
+;
+
+; end of interrupt & restore irql
+ ; (oldirq) Don't lower
+ ; Vector to EOI
+
+ stdCall _HalEndSystemInterrupt, <CLOCK2_LEVEL,CLOCK_VECTOR>
+
+
+;
+; Update performance counter
+;
+ProcessClock:
+;
+; (esp) = OldIrql
+; (esp+4) = Bogus Vector
+; (esp+8) = base of trap frame
+; (ebp) = pointer to trap frame
+;
+
+ add HalpPerfCounterLow, ROLLOVER_COUNT ; update performace counter
+ adc HalpPerfCounterHigh, dword ptr 0
+
+ ;
+ ; Broadcast clock CPI to all other processors on the system
+ ;
+
+ mov eax, PCR[PcHal].PcrMyLogicalMask
+ not eax
+ and eax, _NCRActiveProcessorLogicalMask
+ jz SkipQuad
+ mov _HalpIpiClock, eax ; Indicate which processors are getting clock interrupt
+
+ push eax
+ and eax,_NCRLogicalDyadicProcessorMask ; see which processors are dyadics
+ jz short SkipDyadic
+
+ TRANSLATE_LOGICAL_TO_VIC
+ VIC_WRITE CpiLevel2Reg, al ; Broadcast interrupt to all other active CPUs
+
+SkipDyadic:
+ pop eax ; restore Active processor mask
+ and eax,_NCRLogicalQuadProcessorMask ; see which processors are quad
+ jz short SkipQuad
+
+ stdCall _HalQicRequestIpi, <eax, NCR_CLOCK_LEVEL_CPI>
+
+SkipQuad:
+
+
+ align dword
+@@:
+ cmp PCR[PcHal].PcrMyLogicalNumber, 0 ; P0 calls UpdateSystemTime
+ je short _HalpUpdateSystemTime
+
+ stdCall _KeUpdateRunTime,<dword ptr [esp]> ; else, UpdateRunTime
+
+ INTERRUPT_EXIT
+
+ public _HalpUpdateSystemTime
+_HalpUpdateSystemTime:
+ mov eax, TIME_INCREMENT
+ jmp _KeUpdateSystemTime@0
+
+
+SpuriousClock:
+
+;
+; A spurious interrupt to a clock interrupt can occur because we either
+; haven't raised our mask, or because we are multiplexing the clock vector's
+; IRQ with NT's IPI vector IRQ.
+;
+
+ push CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <IPI_LEVEL,CLOCK_VECTOR,esp>
+
+ ; if it's spurious here, then
+ or eax, eax ; the interrupt was masked and the HW
+ jz SpuriousClock3 ; will take care of re-routing it
+;
+; We recieved a clock tick while while our irql was >= clock_level and
+; below ipi_level. The clock tick can't be processed until we get below
+; clock_level, and we can't raise above ipi_level to mask it off so we
+; eat the clock interrupt and use the soft-emulation (PcIRR) to process a
+; clock tick later
+;
+
+; turn off the interrupt via system control port b - since HalMakeBeep also
+; accesses system control port b (speaker control) and uses the 8254 spin lock,
+; we will too
+
+Hci21: pushfd
+ cli
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax,Hci198
+
+ in al, 61h
+ jmp $+2
+ or al, 80h
+ out 61h, al
+ jmp $+2
+
+ align dword
+@@:
+ lea ebx, _Halp8254Lock
+ RELEASE_SPINLOCK ebx
+ popfd
+
+;;;;
+;;;; BUGBUG - Setting the bit to delay processing of the clock interrupt
+;;;; causes the machine to stop under moderate stress - can't even get
+;;;; get into the debugger. By removing the delayed processing, the
+;;;; problem seems to have gone away - I don't know why. At some point
+;;;; this needs to be fixed.
+;;;;
+;;;; NOTE - check delayed processing of CPIs from within HalBeginSystem
+;;;; Interrupt. Perhaps this is causing the problem (with the broadcast
+;;;; clock cpi)
+;;;;
+;;;;; BUGBUG: Hardcoded value
+
+ or dword ptr PCR[PcIRR], 1 shl 4
+
+ INTERRUPT_EXIT ; EOI this vector
+
+SpuriousClock2:
+if DBG
+ int 3 ; Should never get here
+endif
+
+SpuriousClock3:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+Hci99: popfd
+ SPIN_ON_SPINLOCK eax,<Hci11>
+
+Hci198: popfd
+ SPIN_ON_SPINLOCK eax,<Hci21>
+
+stdENDP _HalpClockInterrupt
+
+
+ page ,132
+ subttl "Emulate System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of an a delayed clock interrupt.
+; The clock has already been EOI-ed, so this function simply setups
+; a frame and jumps into the normal clocktick code without touching
+; the clock device or interrupt hardware.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;--
+
+ ENTER_DR_ASSIST Heci_a, Heci_t
+
+ align dword
+ public _NCREmulateClockTick
+_NCREmulateClockTick proc
+
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT Heci_a, Heci_t
+
+ push NCR_CPI_VECTOR_BASE ; BOGUS vector to prevent EOI
+ push PCR[PcIrql] ; save previous IRQL
+ mov byte ptr PCR[PcIrql], CLOCK2_LEVEL; set new irql
+ sti
+ jmp ProcessClock ; Join ClockInterrupt code
+
+_NCREmulateClockTick endp
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, TIME_INCREMENT
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halncr/i386/ncrdetct.c b/private/ntos/nthals/halncr/i386/ncrdetct.c
new file mode 100644
index 000000000..f61f96fb1
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrdetct.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ncrdetct.c"
diff --git a/private/ntos/nthals/halncr/i386/ncrhwsup.c b/private/ntos/nthals/halncr/i386/ncrhwsup.c
new file mode 100644
index 000000000..89e36b2e7
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrhwsup.c
@@ -0,0 +1,170 @@
+
+/*++
+
+Copyright (c) 1992 NCR - MSBU
+
+Module Name:
+
+ ncrhwsup.c
+
+Abstract:
+
+
+Author:
+
+ Richard Barton (o-richb) 11-Mar-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "ncr.h"
+#include "ncrcat.h"
+#include "ncrpsi.h"
+
+extern ULONG NCRActiveProcessorCount;
+
+ULONG NCRSysIntCount;
+ULONG NCRSingleBitCount;
+
+ULONG NCRLockedExchangeAndAdd(PULONG, ULONG);
+
+
+VOID
+NCRHandleSysInt (TrapFramePtr, ExceptionRecordPtr)
+IN PKTRAP_FRAME TrapFramePtr;
+IN PVOID ExceptionRecordPtr;
+/*++
+
+Routine Description:
+ Handles the NCR hardware generated System Interrupt
+
+Arguments:
+
+Return Value:
+ none.
+
+--*/
+{
+
+ DbgBreakPoint();
+ return ;
+
+#if 0
+ ULONG i;
+
+ i = NCRLockedExchangeAndAdd(&NCRSysIntCount, 1);
+ if (i != 0) {
+ for (i = 100000;
+ ((NCRSysIntCount != NCRActiveProcessorCount) &&
+ (i > 0)); --i) ;
+ KiIpiServiceRoutine(TrapFramePtr, ExceptionRecordPtr);
+ return;
+ }
+
+ DbgPrint("NCRHandleSysInt");
+ DbgBreakPoint();
+
+ NCRSysIntCount = 0;
+#endif
+}
+
+
+VOID
+NCRHandleSingleBitError (TrapFramePtr, ExceptionRecordPtr)
+IN PKTRAP_FRAME TrapFramePtr;
+IN PVOID ExceptionRecordPtr;
+/*++
+
+Routine Description:
+ Handles the NCR hardware generated Single Bit Error Interrupt and a
+ Status Change
+
+Arguments:
+
+Return Value:
+ none.
+
+--*/
+{
+ CAT_CONTROL cat_control;
+ PSI_INFORMATION psi_information;
+
+ cat_control.Module = PSI;
+ cat_control.Asic = CAT_I;
+
+//
+// Lets get the CatBus spin lock because the status change interrupt is a broadcast
+// interrupt that goes to all CPU's
+//
+
+ HalpAcquireCatBusSpinLock();
+
+//
+// read status registers from PSI. This will tell us if a status change interrupt occured.
+//
+ cat_control.Command = READ_REGISTER;
+ cat_control.Address = 0;
+ cat_control.NumberOfBytes = sizeof(CAT_REGISTERS);
+ HalpCatBusIo(&cat_control,(PUCHAR)&(psi_information.CatRegisters.CatRegs));
+
+ if (psi_information.INTERRUPT_STATUS) {
+
+ //
+ // A status change interrupt has occured. Lets go read detailed status information so
+ // the interrupt will be cleared.
+ //
+
+ //
+ // read power supply mask registers
+ //
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = PSI_Pwr_Supply_Status_L5;
+ cat_control.NumberOfBytes = 8;
+ HalpCatBusIo(&cat_control,(PUCHAR)&(psi_information.PowerSupplyStatus));
+ //
+ // read disk power registers
+ //
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = PSI_DiskStatus_L5;
+ cat_control.NumberOfBytes = 16;
+ HalpCatBusIo(&cat_control,(PUCHAR)&(psi_information.DiskPowerStatus[0]));
+ //
+ // read DVM registers
+ //
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = PSI_Dvm_Select_L5;
+ cat_control.NumberOfBytes = 1;
+ HalpCatBusIo(&cat_control,(PUCHAR)&(psi_information.DvmSelect));
+
+ cat_control.Command = READ_SUBADDR;
+ cat_control.Address = DVM_DBASE;
+ cat_control.NumberOfBytes = 4;
+ HalpCatBusIo(&cat_control,(PUCHAR)&(psi_information.DvmData0));
+
+ } else {
+
+ //
+ // This path means another CPU has handled the status change.
+ //
+ // NOTE: If single bit error reporting were enabled then this path could also
+ // mean a single bit error occured.
+ //
+
+ }
+
+ //
+ // Release the CatBus spin lock.
+ //
+
+ HalpReleaseCatBusSpinLock();
+
+ if (psi_information.INTERRUPT_STATUS) {
+ DBGMSG(("A Status Change Interrupt was received: 0x%x\n",psi_information.INTERRUPT_STATUS));
+ }
+}
diff --git a/private/ntos/nthals/halncr/i386/ncrintr.asm b/private/ntos/nthals/halncr/i386/ncrintr.asm
new file mode 100644
index 000000000..f5c9c6899
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrintr.asm
@@ -0,0 +1,823 @@
+ title "NCR Specific Interrupt Handlers"
+;++
+;
+; Copyright (c) 1992 NCR - MSBU
+;
+; Module Name:
+;
+; ncrintr.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process
+; interrupts specific to the NCR - MSBU platforms.
+;
+; Author:
+;
+; Richard R. Barton (o-richb) 11 Mar 1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ncr.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _NCRHandleSysInt,2
+ EXTRNP _NCRHandleSingleBitError,2
+ EXTRNP _NCRHandleQicSpuriousInt,2
+ EXTRNP _HalpProfileInterrupt2ndEntry
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _HalQicRequestIpi,2
+ extrn _HalpUpdateSystemTime:near
+ extrn _NCRLogicalNumberToPhysicalMask:DWORD
+ extrn _HalpIpiClock:DWORD
+ extrn _NCRActiveProcessorLogicalMask:DWORD
+ extrn _NCRPlatform:DWORD
+ extrn _NCRStatusChangeInterruptEnabled:DWORD
+ extrn _NCRLogicalDyadicProcessorMask:DWORD
+ extrn _NCRLogicalQuadProcessorMask:DWORD
+
+
+_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
+ public _NCRIpiProfile
+_NCRIpiProfile dd 0
+_DATA ends
+
+
+_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Broadcast Clock Handler"
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives the clock interrupt for processors
+; that did not handle the interrupt from the rtc.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRClockBroadcast_a, NCRClockBroadcast_t
+
+cPublicProc _NCRClockBroadcastHandler,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRClockBroadcast_a, NCRClockBroadcast_t
+
+ mov eax, PCR[PcHal.PcrMyProcessorFlags]
+ test eax, CPU_DYADIC
+ jz short DoQuad
+
+;
+; get slave ISR value and check to see if this is really a SMCA IRQ10
+; if it is then go handle that interrupt and exit
+;
+ ; NOTE: NCR needs to test the following fix. By not using interrupt
+ ; 10 on the secondary MCA bus this following work-around is nop-ed.
+
+
+ in al, PIC2_PORT0
+ test al, 00000100B
+ jnz HandleIrq10
+
+; (esp) - base of trap frame
+;
+ push NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI
+ sub esp, 4 ; placeholder for OldIrql
+
+;; stdCall _HalBeginSystemInterrupt,<CLOCK2_LEVEL,NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI,esp>
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI,esp>
+ jmp short NoQuad
+
+DoQuad:
+
+ push NCR_QIC_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI
+ sub esp, 4 ; placeholder for OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,NCR_QIC_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI,esp>
+
+NoQuad:
+
+ or al,al ; check for spurious interrupt
+ jz SpuriousClockBroadcast
+
+ mov esi, PCR[PcHal.PcrMyLogicalNumber]
+ lock btr _HalpIpiClock, esi ; reset our clock tick bit
+ jnc short bch_30 ; if it wasn't set, then don't updatetime
+
+ or esi, esi ; is this P0?
+ jz ClockBroadcastP0 ; Yes, then UpdateSystemTime
+
+;
+; (esp) = OldIrql
+; (esp+4) = vector
+;
+ stdCall _KeUpdateRunTime, <dword ptr [esp]>
+ align dword
+bch_30:
+ bt _NCRIpiProfile, esi ; Profile broadcast pending?
+ jc short ProfileBroadcast ; Yes, go do it
+
+ INTERRUPT_EXIT ; All done
+
+ align dword
+ProfileBroadcast:
+ lock btr _NCRIpiProfile, esi ; clear our bit
+ jmp _HalpProfileInterrupt2ndEntry@0
+
+SpuriousClockBroadcast:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+HandleIrq10:
+ int NCR_SECONDARY_VECTOR_BASE + 10
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+bch_35:
+;
+; P0 also has a profile interrupt pending. For simpilicty just
+; send ourselves another interrupt to handle the profile interrupt
+;
+
+ mov eax, PCR[PcHal.PcrMyProcessorFlags]
+ test eax, CPU_DYADIC
+ jz short DoQuad0
+
+ mov eax,dword ptr _NCRLogicalNumberToPhysicalMask[0]
+ VIC_WRITE CpiLevel2Reg, al ; Send ourselves another broadcast
+ jmp _HalpUpdateSystemTime ; Go update system time
+
+DoQuad0:
+
+ xor eax,eax
+ stdCall _HalQicRequestIpi, <eax, NCR_CLOCK_LEVEL_CPI>
+ jmp _HalpUpdateSystemTime ; Go update system time
+
+ align dword
+ClockBroadcastP0:
+;
+; P0 has a clock interrupt broadcast to it
+;
+ test _NCRIpiProfile, 1 ; Profile broadcast pending?
+ jnz short bch_35
+ jmp _HalpUpdateSystemTime ; Go update system time
+
+stdENDP _NCRClockBroadcastHandler
+
+
+ page ,132
+ subttl "NCR Profile Handler"
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives the profile interrupt and
+; broadcasts it to all other processors
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRProfile_a, NCRProfile_t
+
+ align dword
+ public _NCRProfileHandler
+_NCRProfileHandler proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRProfile_a, NCRProfile_t
+
+;
+; (esp) - base of trap frame
+;
+ push PROFILE_VECTOR
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,PROFILE_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz SpuriousProfile
+
+;
+; Broadcast profile interrupt to all other processors
+;
+
+ mov eax, _NCRActiveProcessorLogicalMask ; all processors
+ xor eax, PCR[PcHal.PcrMyLogicalMask] ; less current one
+ or _NCRIpiProfile, eax ; set their bits
+
+ push eax
+ and eax,_NCRLogicalDyadicProcessorMask ; see which processors are dyadics
+ jz short SkipDyadic
+
+ TRANSLATE_LOGICAL_TO_VIC
+ VIC_WRITE CpiLevel2Reg, al
+SkipDyadic:
+ pop eax ; restore Active processor mask
+ and eax,_NCRLogicalQuadProcessorMask ; see which processors are quad
+ jz short SkipQuad
+
+ stdCall _HalQicRequestIpi, <eax, NCR_CLOCK_LEVEL_CPI>
+
+SkipQuad:
+
+
+;
+; This is the RTC interrupt, so we have to clear the
+; interrupt flag on the RTC.
+;
+ stdCall _HalpAcquireCmosSpinLock
+
+;
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+ jmp _HalpProfileInterrupt2ndEntry@0
+
+SpuriousProfile:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRProfileHandler endp
+
+
+ page ,132
+ subttl "System Interrupt Handler"
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives the hardware generated system interrupt.
+;
+; Due to a VIC errata, this handler can also be invoked on a CPI 0 (IPI)
+; that was simultaneous with a system interrupt or a single bit error
+; (except on 3360, where only a simultaneous system interrupt can cause
+; this condition). The proper way to handle this condition is as follows:
+;
+; 3360: handle system interrupt first (since we know we had one) and
+; perform IPI processing if the error was non-fatal
+;
+; 3450/3550: since we don't necessarily have a sysint and since sysint
+; processing requires CAT accesses (time consuming), should process
+; potential IPI first. If there wasn't one, then should perform
+; sysint processing (else exit - if there is a sysint it will
+; come back in).
+;
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRSysInt_a, NCRSysInt_t
+
+ align dword
+ public _NCRSysIntHandler
+_NCRSysIntHandler proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRSysInt_a, NCRSysInt_t
+
+;
+; (esp) - base of trap frame
+;
+
+; NOTE: since the 3360 currently does not use the sysint, will not perform
+; the processing as identified above. Will need to when (if) it is used.
+
+
+; see if there is an IPI to process first
+
+ int NCR_CPI_VECTOR_BASE + NCR_IPI_LEVEL_CPI
+
+
+; should only perform system interrupt processing (below) if there was not
+; an valid IPI (processed above) - TO BE ADDED LATER, IF DESIRED
+
+
+ push NCR_CPI_VECTOR_BASE + NCR_SYSTEM_INTERRUPT
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <HIGH_LEVEL,NCR_CPI_VECTOR_BASE + NCR_SYSTEM_INTERRUPT,esp>
+
+ or al,al ; check for spurious interrupt
+ jz SpuriousSysInt
+
+
+;
+; NOTE: On 3450 and greater machines a sysint should never occur. This is because
+; the Arbiter ASIC has been configured to send all hardware failures to the NMI vector
+; and not sysints. This configuration code is located in ncrsus.c in the function
+; HalpInitializeSUSInterface. The only way we can take this code path is if a
+; IPI 0 and status change/single bit error occured at the same time. So we will
+; process the ipi now and let the status change/single bit error handler process its
+; interrupt.
+;
+
+
+ mov eax, _NCRPlatform ; get Platform so we can check for 3360
+ cmp eax, NCR3360
+ jne short SkipSysInt ; if system is 3450 and greater then skip sys handler
+ ; because we cannot get a sysint. This condition is
+ ; caused by a a IPI0 and a Status change.
+
+;
+; (esp) = OldIrql
+; (esp+4) = vector
+;
+
+ stdCall _NCRHandleSysInt, <ebp, 0>
+
+SkipSysInt:
+
+ INTERRUPT_EXIT ; will return to caller, no DebugCheck
+
+SpuriousSysInt:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRSysIntHandler endp
+
+
+
+ page ,132
+ subttl "Qic Spurious Handler"
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives the spurious interrupts from the Qic.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRQicSpurInt_a, NCRQicSpurInt_t
+
+ align dword
+ public _NCRQicSpuriousHandler
+_NCRQicSpuriousHandler proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRQicSpurInt_a, NCRQicSpurInt_t
+
+;
+; (esp) - base of trap frame
+;
+
+ push NCR_QIC_SPURIOUS_VECTOR
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <HIGH_LEVEL,NCR_QIC_SPURIOUS_VECTOR,esp>
+
+ or al,al ; check for spurious interrupt
+ jz SpuriousQicSpurInt
+
+;
+; (esp) = OldIrql
+; (esp+4) = vector
+;
+
+ stdCall _NCRHandleQicSpuriousInt, <ebp, 0>
+
+
+ INTERRUPT_EXIT ; will return to caller, no DebugCheck
+
+SpuriousQicSpurInt:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRQicSpuriousHandler endp
+
+
+ page ,132
+ subttl "VIC Errata Handler"
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata1_a, NCRVICErrata1_t
+
+ align dword
+ public _NCRVICErrataHandler1
+_NCRVICErrataHandler1 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata1_a, NCRVICErrata1_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 00000010B
+ jz short SpuriousVICErrata1
+ int NCR_SECONDARY_VECTOR_BASE + 9
+SpuriousVICErrata1:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler1 endp
+
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata3_a, NCRVICErrata3_t
+
+ align dword
+ public _NCRVICErrataHandler3
+_NCRVICErrataHandler3 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata3_a, NCRVICErrata3_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 00001000B
+ jnz short SMCA_11
+ int NCR_SECONDARY_VECTOR_BASE + 3
+ jmp short SMCA_3
+SMCA_11:
+ int NCR_SECONDARY_VECTOR_BASE + 11
+SMCA_3:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler3 endp
+
+
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata4_a, NCRVICErrata4_t
+
+ align dword
+ public _NCRVICErrataHandler4
+_NCRVICErrataHandler4 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata4_a, NCRVICErrata4_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 00010000B
+ jnz short SMCA_12
+ int NCR_SECONDARY_VECTOR_BASE + 4
+ jmp short SMCA_4
+SMCA_12:
+ int NCR_SECONDARY_VECTOR_BASE + 12
+SMCA_4:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler4 endp
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata5_a, NCRVICErrata5_t
+
+ align dword
+ public _NCRVICErrataHandler5
+_NCRVICErrataHandler5 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata5_a, NCRVICErrata5_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 00100000B
+ jnz short SMCA_13
+ int NCR_SECONDARY_VECTOR_BASE + 5
+ jmp short SMCA_5
+SMCA_13:
+ int NCR_SECONDARY_VECTOR_BASE + 13
+SMCA_5:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler5 endp
+
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata6_a, NCRVICErrata6_t
+
+ align dword
+ public _NCRVICErrataHandler6
+_NCRVICErrataHandler6 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata6_a, NCRVICErrata6_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 01000000B
+ jnz short SMCA_14
+ int NCR_SECONDARY_VECTOR_BASE + 6
+ jmp short SMCA_6
+SMCA_14:
+ int NCR_SECONDARY_VECTOR_BASE + 14
+SMCA_6:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler6 endp
+
+
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata7_a, NCRVICErrata7_t
+
+ align dword
+ public _NCRVICErrataHandler7
+_NCRVICErrataHandler7 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata7_a, NCRVICErrata7_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 10000000B
+ jnz short SMCA_15
+ int NCR_SECONDARY_VECTOR_BASE + 7
+ jmp short SMCA_7
+SMCA_15:
+ int NCR_SECONDARY_VECTOR_BASE + 15
+SMCA_7:
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler7 endp
+
+
+;++
+;
+; Routine Description:
+;
+; This interrupt handler receives a SMCA interrupt whos vector
+; has been replace with a vector in the CPI range.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+;--
+
+ ENTER_DR_ASSIST NCRVICErrata15_a, NCRVICErrata15_t
+
+ align dword
+ public _NCRVICErrataHandler15
+_NCRVICErrataHandler15 proc
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT NCRVICErrata15_a, NCRVICErrata15_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; get slave ISR value
+;
+ in al, PIC2_PORT0
+ test al, 10000000B
+ jnz short SMCA_15b
+
+;
+; This is a Single Bit Error or a Status Change
+;
+ test _NCRStatusChangeInterruptEnabled,1 ; send interrupt to a device driver?
+ jnz short ToDeviceDriver
+;
+; (esp) - base of trap frame
+;
+ push NCR_CPI_VECTOR_BASE + NCR_SINGLE_BIT_ERROR
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <HIGH_LEVEL,NCR_CPI_VECTOR_BASE + NCR_SINGLE_BIT_ERROR,esp>
+ or al,al ; check for spurious interrupt
+ jz SpuriousSingleBit
+;
+; (esp) = OldIrql
+; (esp+4) = vector
+;
+
+ stdCall _NCRHandleSingleBitError, <ebp, 0>
+ INTERRUPT_EXIT ; will return to caller, no DebugCheck
+
+SpuriousSingleBit:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+
+ToDeviceDriver:
+ int PRIMARY_VECTOR_BASE + 027H ; call status change interrupt at vector 57
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+SMCA_15b:
+ int NCR_SECONDARY_VECTOR_BASE + 15
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_NCRVICErrataHandler15 endp
+
+
+
+_TEXT ends
+ end
+
+
diff --git a/private/ntos/nthals/halncr/i386/ncrioacc.asm b/private/ntos/nthals/halncr/i386/ncrioacc.asm
new file mode 100644
index 000000000..8929e56ad
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrioacc.asm
@@ -0,0 +1,730 @@
+ title "ix ioaccess"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ncrioacc.asm
+;
+; Abstract:
+;
+; Procedures to correctly touch I/O registers.
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 16 May 1990
+; Rick Ulmer (rick.ulmer@columbiasc.ncr.com) 1 March 1994
+;
+; Environment:
+;
+; User or Kernel, although privledge (IOPL) may be required.
+;
+; Revision History:
+;
+; RMU - Added support for SMC for NCR 35xx systems.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+ .list
+
+
+ extrn _NCRSegmentIoRegister:DWORD
+
+
+
+
+_TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; I/O port space read and write functions.
+;
+; These have to be actual functions on the 386, because we need
+; to use assembler, but cannot return a value if we inline it.
+;
+; This set of functions manipulates I/O registers in PORT space.
+; (Uses x86 in and out instructions)
+;
+; WARNING: Port addresses must always be in the range 0 to 64K, because
+; that's the range the hardware understands.
+;
+;--
+
+;++
+;
+; UCHAR
+; READ_PORT_UCHAR(
+; PUCHAR Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_UCHAR ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+
+ test edx, 00010000h ; test for secondary access
+ jnz short ReadUcharSmca
+;
+; PMCA access
+;
+ in al,dx
+ stdRET _READ_PORT_UCHAR
+
+
+ReadUcharSmca:
+;
+; SMCA access
+;
+ mov ecx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ecx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ in al,dx
+;
+ mov BYTE PTR[ecx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+
+ stdRET _READ_PORT_UCHAR
+
+stdENDP _READ_PORT_UCHAR
+
+
+
+;++
+;
+; USHORT
+; READ_PORT_USHORT(
+; PUSHORT Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_USHORT ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short ReadUshortSmca
+;
+; PMCA access
+;
+ in ax,dx
+ stdRET _READ_PORT_USHORT
+
+ReadUshortSmca:
+;
+; SMCA access
+;
+ mov ecx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ecx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ in ax,dx
+;
+ mov BYTE PTR[ecx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ stdRET _READ_PORT_USHORT
+
+stdENDP _READ_PORT_USHORT
+
+
+
+;++
+;
+; ULONG
+; READ_PORT_ULONG(
+; PULONG Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_ULONG ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short ReadUlongSmca
+;
+; PMCA access
+;
+ in eax,dx
+ stdRET _READ_PORT_ULONG
+
+
+ReadUlongSmca:
+;
+; SMCA access
+;
+ mov ecx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ecx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ in eax,dx
+;
+ mov BYTE PTR[ecx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ stdRET _READ_PORT_ULONG
+
+stdENDP _READ_PORT_ULONG
+
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_UCHAR(
+; PUCHAR Port,
+; PUCHAR Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_UCHAR ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short ReadBufferUcharSmca
+;
+; PMCA access
+;
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep insb
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_UCHAR
+
+ReadBufferUcharSmca:
+;
+; SMCA access
+;
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ push ebx ; save ebx
+ mov ebx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ebx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ rep insb
+;
+ mov BYTE PTR[ebx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ pop ebx ; restore ebx
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_UCHAR
+
+stdENDP _READ_PORT_BUFFER_UCHAR
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_USHORT(
+; PUSHORT Port,
+; PUSHORT Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_USHORT ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short ReadBufferUshortSmca
+;
+; PMCA access
+;
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep insw
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_USHORT
+
+ReadBufferUshortSmca:
+;
+; SMCA access
+;
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ push ebx ; save ebx
+ mov ebx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ebx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ rep insw
+;
+ mov BYTE PTR[ebx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ pop ebx ; restore ebx
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_USHORT
+
+stdENDP _READ_PORT_BUFFER_USHORT
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_ULONG(
+; PULONG Port,
+; PULONG Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_ULONG ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short ReadBufferUlongSmca
+;
+; PMCA access
+;
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep insd
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_ULONG
+
+ReadBufferUlongSmca:
+;
+; SMCA access
+;
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ push ebx ; save ebx
+ mov ebx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ebx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ rep insd
+;
+ mov BYTE PTR[ebx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ pop ebx ; restore ebx
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_ULONG
+
+stdENDP _READ_PORT_BUFFER_ULONG
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_UCHAR(
+; PUCHAR Port,
+; UCHAR Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_UCHAR ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short WriteUcharSmca
+;
+; PMCA access
+;
+ mov al,[esp+8] ; (al) = Value
+ out dx,al
+ stdRET _WRITE_PORT_UCHAR
+
+WriteUcharSmca:
+;
+; SMCA access
+;
+ mov ecx,_NCRSegmentIoRegister ; get segment register
+ mov al,[esp+8] ; (al) = Value
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ecx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ out dx,al
+;
+ mov BYTE PTR[ecx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ stdRET _WRITE_PORT_UCHAR
+
+stdENDP _WRITE_PORT_UCHAR
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_USHORT(
+; PUSHORT Port,
+; USHORT Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_USHORT ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short WriteUshortSmca
+;
+; PMCA access
+;
+ mov eax,[esp+8] ; (ax) = Value
+ out dx,ax
+ stdRET _WRITE_PORT_USHORT
+
+
+WriteUshortSmca:
+;
+; SMCA access
+;
+ mov ecx,_NCRSegmentIoRegister ; get segment register
+ mov eax,[esp+8] ; (ax) = Value
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ecx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ out dx,ax
+;
+ mov BYTE PTR[ecx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ stdRET _WRITE_PORT_USHORT
+
+stdENDP _WRITE_PORT_USHORT
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_ULONG(
+; PULONG Port,
+; ULONG Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_ULONG ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short WriteUlongSmca
+;
+; PMCA access
+;
+ mov eax,[esp+8] ; (eax) = Value
+ out dx,eax
+ stdRET _WRITE_PORT_ULONG
+
+
+WriteUlongSmca:
+;
+; SMCA access
+;
+ mov ecx,_NCRSegmentIoRegister ; get segment register
+ mov eax,[esp+8] ; (eax) = Value
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ecx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ out dx,eax
+;
+ mov BYTE PTR[ecx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ stdRET _WRITE_PORT_ULONG
+
+stdENDP _WRITE_PORT_ULONG
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_UCHAR(
+; PUCHAR Port,
+; PUCHAR Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_UCHAR ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short WriteBufferUcharSmca
+;
+; PMCA access
+;
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep outsb
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_UCHAR
+
+WriteBufferUcharSmca:
+;
+; SMCA access
+;
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ push ebx ; save ebx
+ mov ebx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ebx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ rep outsb
+;
+ mov BYTE PTR[ebx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ pop ebx ; restore ebx
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_UCHAR
+
+stdENDP _WRITE_PORT_BUFFER_UCHAR
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_USHORT(
+; PUSHORT Port,
+; PUSHORT Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_USHORT ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short WriteBufferUshortSmca
+;
+; PMCA access
+;
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep outsw
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_USHORT
+
+
+WriteBufferUshortSmca:
+;
+; SMCA access
+;
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ push ebx ; save ebx
+ mov ebx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ebx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ rep outsw
+;
+ mov BYTE PTR[ebx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ pop ebx ; restore ebx
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_USHORT
+
+stdENDP _WRITE_PORT_BUFFER_USHORT
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_ULONG(
+; PULONG Port,
+; PULONG Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_ULONG ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ ; port = ??srpppph
+ ; sr = segment register
+ ; pppp = port
+ test edx, 00010000h ; test for secondary access
+ jnz short WriteBufferUlongSmca
+;
+; PMCA access
+;
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep outsd
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_ULONG
+
+
+WriteBufferUlongSmca:
+;
+; SMCA access
+;
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ push ebx ; save ebx
+ mov ebx,_NCRSegmentIoRegister ; get segment register
+ ror edx, 8 ; get segreg as byte in dh
+ pushfd
+ cli ; disable interrupts
+ mov BYTE PTR[ebx], dh ; set segment register
+ rol edx, 8 ; restore port
+;
+ rep outsd
+;
+ mov BYTE PTR[ebx], 0 ; clear segment register back to zero
+ popfd ; enable interrupt
+ pop ebx ; restore ebx
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_ULONG
+
+stdENDP _WRITE_PORT_BUFFER_ULONG
+
+
+_TEXT$00 ends
+
+ end
diff --git a/private/ntos/nthals/halncr/i386/ncripi.asm b/private/ntos/nthals/halncr/i386/ncripi.asm
new file mode 100644
index 000000000..ebbea00d8
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncripi.asm
@@ -0,0 +1,362 @@
+
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1992 NCR Corporation
+;
+;Module Name:
+;
+; ncripi.asm
+;
+;Abstract:
+;
+; Provides the HAL support for Interprocessor Interrupts.
+;
+;Author:
+;
+; Richard Barton (o-richb) 24-Jan-1992
+;
+;Revision History:
+;
+;--
+.386p
+ .xlist
+include i386\kimacro.inc
+include callconv.inc ; calling convention macros
+include hal386.inc
+include i386\ncr.inc
+include i386\ix8259.inc
+
+
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP _KeRaiseIrql,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _NCRClearQicIpi,1
+ extrn _NCRLogicalNumberToPhysicalMask:DWORD
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+
+;++
+;
+; VOID
+; NCR3360EnableNmiButtoni(
+; VOID
+; );
+;
+;Routine Description:
+;
+; Programs the recessed button on the 3360 to generate an NMI.
+;
+; 3360 SPECIFIC CODE ONLY !!!!!
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to interrupt
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+;
+; in NMI handler, if you are interested in making sure button was source of
+; NMI, check bit 6 (of 0 thru 7) of IO port 0xf820. If 0, button was pressed,
+; 1 means NMI came from somewhere else.
+;
+; Also, in NMI interrupt handler, if NMI came fo...
+
+
+cPublicProc _NCR3360EnableNmiButton, 0
+
+ mov ah, 41h ; start with processor ASIC 0 (FRED ASIC)
+ mov cx, 2 ; loop through 2 processor cards
+
+PollAsics:
+ mov al, ah ; get ASIC select data
+ out 97h, al ; select ASIC through CAT Access port
+ mov dx, 0f800h ; read CAT ID
+ in al, dx ;
+ cmp al, 0ffh ; 0xff means no processor card is present
+ je @f
+
+ ; setup processor ASICs for g_nmi
+
+ mov dx, 0f80dh ; turn on GNMI in FRED ASIC
+ in al, dx
+ or al, 1
+ out dx, al
+
+@@:
+ add ah, 20h ; go to next processor card
+
+ loop PollAsics ; loop 'til done
+
+
+ mov al, 0c1h ; select arbiter ASIC
+ out 97h, al
+
+ mov dx, 0f80bh ; enable EXP_FALCON_NMI (pushbutton NMI)
+ in al, dx
+ or al, 8
+ out dx, al
+
+ mov al, 0ffh ; take CAT subsystem out of setup
+ out 97h, al
+
+
+ mov dx, 0f823h ; enable pushbutton NMI by disabling, then
+ in al, dx ; reenable
+ and al, 11011111b ; disable by setting MEM_DIS_L to 0
+ out dx, al
+ or al, 00100000b ; enable by setting MEM_DIS_L to 0
+ out dx, al
+
+ stdRET _NCR3360EnableNmiButton
+stdENDP _NCR3360EnableNmiButton
+
+
+
+;++
+;
+; VOID
+; HalVicRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt using the VIC
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to interrupt
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalVicRequestIpi ,1
+ mov eax, dword ptr 4[esp]
+ TRANSLATE_LOGICAL_TO_VIC
+ VIC_WRITE CpiLevel0Reg, al
+ stdRET _HalVicRequestIpi
+stdENDP _HalVicRequestIpi
+
+
+ page ,132
+ subttl "80387 Irq13 Interrupt Handler"
+
+;++
+;
+; VOID
+; HalpIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; When the 80387 detects an error, it raises its error line. This
+; was supposed to be routed directly to the 386 to cause a trap 16
+; (which would actually occur when the 386 encountered the next FP
+; instruction).
+;
+; However, the ISA design routes the error line to IRQ13 on the
+; slave 8259. So an interrupt will be generated whenever the 387
+; discovers an error.
+;
+; This routine handles that interrupt and passes control to the kernel
+; coprocessor error handler.
+;
+; Arguments:
+;
+; None.
+; Interrupt is disabled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hi13_a, Hi13_t
+
+cPublicProc _HalpIrq13Handler ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
+
+;
+; HalBeginSystemInterrupt will save previous IRQL
+;
+ cli
+ push 13 + PRIMARY_VECTOR_BASE
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <I386_80387_IRQL,13 + PRIMARY_VECTOR_BASE,esp>
+
+ or al,al ; check for spurious interrupt
+ jz SpuriousIrq13
+
+ stdCall _KiCoprocessorError ; call CoprocessorError handler
+
+;
+; Clear the busy latch so that the 386 doesn't mistakenly think
+; that the 387 is still busy.
+;
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+ INTERRUPT_EXIT ; will return to caller
+
+SpuriousIrq13:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpIrq13Handler
+
+
+ page ,132
+ subttl "Interprocessor Interrupt Handler"
+
+;++
+;
+; VOID
+; NCRVicIPIHandler (
+; );
+;
+; Routine Description:
+;
+; This routine handles an incoming cross-processor interrupt.
+;
+; Arguments:
+;
+; None.
+; Interrupt is disabled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Ipi_a, Ipi_t
+
+cPublicProc _NCRVicIPIHandler,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Ipi_a, Ipi_t ; (ebp) -> Trap frame
+
+;
+; HalBeginSystemInterrupt will save previous IRQL
+;
+
+ push NCR_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <IPI_LEVEL,NCR_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI,esp>
+
+ or al,al ; check for spurious interrupt
+ jz short SpuriousIpi
+
+; Pass TrapFrame to Ipi service rtn
+; Pass Null ExceptionFrame
+
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+; BUGBUG shielint ignore returncode
+
+NCRIpiisDone:
+ INTERRUPT_EXIT ; will return to caller
+
+ align 4
+SpuriousIpi:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _NCRVicIPIHandler
+
+
+;++
+;
+; VOID
+; NCRQicIPIHandler (
+; );
+;
+; Routine Description:
+;
+; This routine handles an incoming cross-processor interrupt for the Quad Processor.
+;
+; Arguments:
+;
+; None.
+; Interrupt is disabled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST QicIpi_a, QicIpi_t
+
+cPublicProc _NCRQicIPIHandler,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT QicIpi_a, QicIpi_t ; (ebp) -> Trap frame
+
+;
+; HalBeginSystemInterrupt will save previous IRQL
+;
+
+ push NCR_QIC_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI
+ sub esp, 4 ; placeholder for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <IPI_LEVEL,NCR_QIC_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI,esp>
+
+ or al,al ; check for spurious interrupt
+ jz short SpuriousQicIpi
+
+; Pass TrapFrame to Ipi service rtn
+; Pass Null ExceptionFrame
+
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+; BUGBUG shielint ignore returncode
+
+NCRQicIpiisDone:
+ INTERRUPT_EXIT ; will return to caller
+
+ align 4
+SpuriousQicIpi:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _NCRQicIPIHandler
+
+
+
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halncr/i386/ncrirql.asm b/private/ntos/nthals/halncr/i386/ncrirql.asm
new file mode 100644
index 000000000..c30cdf910
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrirql.asm
@@ -0,0 +1,1223 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1992 NCR Corporation
+;
+; Module Name:
+;
+; ncrirql.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the 8259 PIC.
+;
+; Author:
+;
+; Richard Barton (o-richb) 24-Jan-1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.486p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include i386\ncr.inc
+include mac386.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ extrn _HalpApcInterrupt:NEAR
+ extrn _HalpDispatchInterrupt:NEAR
+ extrn _KiUnexpectedInterrupt:NEAR
+ extrn _NCREmulateClockTick:NEAR
+ extrn _HalpBusType:DWORD
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+;
+; Initialization control words equates for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW2_SET_PRIORITY equ 0c0H
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+
+;
+; Interrupt flag bit maks for EFLAGS
+;
+
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; PICsInitializationString - Master PIC initialization command string
+;
+
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+ align 4
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0 low
+ dd 00000000000000000000000000000000B ; irql 1 apc
+ dd 00000000000000000000000000000000B ; irql 2 dpc
+ dd 00000000000000000000000000000000B ; irql 3 .
+ dd 11111111100000000000000000000000B ; irql 4 .
+ dd 11111111110000000000000000000000B ; irql 5 .
+ dd 11111111111000000000000000000000B ; irql 6 .
+ dd 11111111111100000000000000000000B ; irql 7 .
+ dd 11111111111110000000000000000000B ; irql 8 .
+ dd 11111111111111000000000000000000B ; irql 9 .
+ dd 11111111111111100000000000000000B ; irql 10 .
+ dd 11111111111111110000000000000000B ; irql 11 .\
+ dd 11111111111111111000000000000000B ; irql 12 . irql
+ dd 11111111111111111100000000000000B ; irql 13 . device
+ dd 11111111111111111110000000000000B ; irql 14 . range
+ dd 11111111111111111111000000000000B ; irql 15 ./
+ dd 11111111111111111111100000000000B ; irql 16 .
+ dd 11111111111111111111110000000000B ; irql 17 .
+ dd 11111111111111111111111000000000B ; irql 18 .
+ dd 11111111111111111111111000000000B ; irql 19 .
+ dd 11111111111111111111111010000000B ; irql 20 .
+ dd 11111111111111111111111011000000B ; irql 21 .
+ dd 11111111111111111111111011100000B ; irql 22 .
+ dd 11111111111111111111111011110000B ; irql 23 .
+ dd 11111111111111111111111011111000B ; irql 24 .
+ dd 11111111111111111111111011111000B ; irql 25 .
+ dd 11111111111111111111111011111010B ; irql 26 .
+ dd 11111111111111111111111111111110B ; irql 27 profile/clock
+; ^ bubug- change to a 0 (see below)
+ dd 11111111111111111111111111111110B ; irql 28 clock
+ dd 11111111111111111111111111111111B ; irql 29 ipi
+ dd 11111111111111111111111111111111B ; irql 30 power
+ dd 11111111111111111111111111111111B ; irql 31 high
+; | | |
+; | | +- NT IPI vector &
+; | | clock interrupt
+; | | multiplexed here.
+; | | raised to ipi level
+; | |
+; | +--- CPI Clock broadcasts
+; | here. raise to clock
+; | level.
+; |
+; +--- RTC for NT Profile vector
+; raised to profile level
+
+;
+; Warning - I moved the CPI Clock to below profile for now.
+;
+
+
+;
+; This table is used to mask all pending interrupts below a given Irql
+; out of the IRR
+;
+ align 4
+
+FindHigherIrqlMask label dword
+ dd 11111111111111111111111111111111B ; irql 0
+ dd 11111111111111111111111111111100B ; irql 1 (APC)
+ dd 11111111111111111111111111111000B ; irql 2 (DISPATCH)
+ dd 11111111111111111111111111110000B ; irql 3
+ dd 00000111111111111111111111110000B ; irql 4
+ dd 00000011111111111111111111110000B ; irql 5
+ dd 00000001111111111111111111110000B ; irql 6
+ dd 00000000111111111111111111110000B ; irql 7
+ dd 00000000011111111111111111110000B ; irql 8
+ dd 00000000001111111111111111110000B ; irql 9
+ dd 00000000000111111111111111110000B ; irql 10
+ dd 00000000000011111111111111110000B ; irql 11
+ dd 00000000000001111111111111110000B ; irql 12
+ dd 00000000000000111111111111110000B ; irql 13
+ dd 00000000000000011111111111110000B ; irql 14
+ dd 00000000000000001111111111110000B ; irql 15
+ dd 00000000000000000111111111110000B ; irql 16
+ dd 00000000000000000011111111110000B ; irql 17
+ dd 00000000000000000001111111110000B ; irql 18
+ dd 00000000000000000001111111110000B ; irql 19
+ dd 00000000000000000001011111110000B ; irql 20
+ dd 00000000000000000001001111110000B ; irql 20
+ dd 00000000000000000001000111110000B ; irql 22
+ dd 00000000000000000001000011110000B ; irql 23
+ dd 00000000000000000001000001110000B ; irql 24
+ dd 00000000000000000001000001110000B ; irql 25
+ dd 00000000000000000001000001010000B ; irql 26
+ dd 00000000000000000000000000010000B ; irql 27 profile/clock
+; ^ Warning - change to a 1 (see above)
+ dd 00000000000000000000000000000000B ; irql 28 clock
+ dd 00000000000000000000000000000000B ; irql 29 ipi
+ dd 00000000000000000000000000000000B ; irql 30 power
+ dd 00000000000000000000000000000000B ; irql 31 high
+; | | |
+; | | +- We only emulate clock
+; | | interrupts here, not IPIs.
+; | | So this is set to clock
+; | | level
+; | |
+; | +--- CPI Clock broadcasts
+; | here. raise to clock
+; | level
+; |
+; +--- RTC for NT Profile vector
+; raised to profile level
+
+ align 4
+;
+; The following tables define the addresses of software interrupt routers
+;
+
+;
+; Use this table if there is NO machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:_NCREmulateClockTick ; 8259 irq#0
+ dd offset FLAT:HalpHardwareInterrupt01 ; 8259 irq#1
+ dd offset FLAT:HalpHardwareInterrupt02 ; 8259 irq#2
+ dd offset FLAT:HalpHardwareInterrupt03 ; 8259 irq#3
+ dd offset FLAT:HalpHardwareInterrupt04 ; 8259 irq#4
+ dd offset FLAT:HalpHardwareInterrupt05 ; 8259 irq#5
+ dd offset FLAT:HalpHardwareInterrupt06 ; 8259 irq#6
+ dd offset FLAT:HalpHardwareInterrupt07 ; 8259 irq#7
+ dd offset FLAT:HalpHardwareInterrupt08 ; 8259 irq#8
+ dd offset FLAT:HalpHardwareInterrupt09 ; 8259 irq#9
+ dd offset FLAT:HalpHardwareInterrupt10 ; 8259 irq#10
+ dd offset FLAT:HalpHardwareInterrupt11 ; 8259 irq#11
+ dd offset FLAT:HalpHardwareInterrupt12 ; 8259 irq#12
+ dd offset FLAT:HalpHardwareInterrupt13 ; 8259 irq#13
+ dd offset FLAT:HalpHardwareInterrupt14 ; 8259 irq#14
+ dd offset FLAT:HalpHardwareInterrupt15 ; 8259 irq#15
+
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+ db 3 ; SWIRR=8, so highest pending SW irql= 3
+ db 3 ; SWIRR=9, so highest pending SW irql= 3
+ db 3 ; SWIRR=A, so highest pending SW irql= 3
+ db 3 ; SWIRR=B, so highest pending SW irql= 3
+ db 3 ; SWIRR=C, so highest pending SW irql= 3
+ db 3 ; SWIRR=D, so highest pending SW irql= 3
+ db 3 ; SWIRR=E, so highest pending SW irql= 3
+ db 3 ; SWIRR=F, so highest pending SW irql= 3
+
+ db 4 ; SWIRR=10, so highest pending SW irql= 4
+ db 4 ; SWIRR=11, so highest pending SW irql= 4
+ db 4 ; SWIRR=12, so highest pending SW irql= 4
+ db 4 ; SWIRR=13, so highest pending SW irql= 4
+ db 4 ; SWIRR=14, so highest pending SW irql= 4
+ db 4 ; SWIRR=15, so highest pending SW irql= 4
+ db 4 ; SWIRR=16, so highest pending SW irql= 4
+ db 4 ; SWIRR=17, so highest pending SW irql= 4
+ db 4 ; SWIRR=18, so highest pending SW irql= 4
+ db 4 ; SWIRR=19, so highest pending SW irql= 4
+ db 4 ; SWIRR=1A, so highest pending SW irql= 4
+ db 4 ; SWIRR=1B, so highest pending SW irql= 4
+ db 4 ; SWIRR=1C, so highest pending SW irql= 4
+ db 4 ; SWIRR=1D, so highest pending SW irql= 4
+ db 4 ; SWIRR=1E, so highest pending SW irql= 4
+ db 4 ; SWIRR=1F, so highest pending SW irql= 4
+
+
+
+; public SWInterruptLookUpTable, FindFirstSetBit
+;FindFirstSetBit label byte
+; db 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+; db 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+;
+;
+; public AcquireBufferPosition, SpinLockRecord
+;
+;AcquireBufferPosition dd 0
+;SpinLockRecord dd 4096 dup (0)
+
+
+ifdef IRQL_METRICS
+
+ public HalRaiseIrqlCount
+ public HalLowerIrqlCount
+ public HalQuickLowerIrqlCount
+ public HalApcSoftwareIntCount
+ public HalDpcSoftwareIntCount
+ public HalHardwareIntCount
+ public HalPostponedIntCount
+ public Hal8259MaskCount
+
+HalRaiseIrqlCount dd 0
+HalLowerIrqlCount dd 0
+HalQuickLowerIrqlCount dd 0
+HalApcSoftwareIntCount dd 0
+HalDpcSoftwareIntCount dd 0
+HalHardwareIntCount dd 0
+HalPostponedIntCount dd 0
+Hal8259MaskCount dd 0
+
+endif
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfRaiseIrql ,1
+cPublicFpo 0,0
+ mov al, PCR[PcIrql] ; get current irql
+ mov PCR[PcIrql], cl
+
+ifdef IRQL_METRICS
+ lock inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, cl ; old > new?
+ ja short Kri99 ; yes, go bugcheck
+
+ fstRET KfRaiseIrql
+
+cPublicFpo 2,2
+Kri99:
+ push eax ; put new irql where we can find it
+ push ecx ; put old irql where we can find it
+ mov byte ptr PCR[PcIrql],0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+
+;++
+;
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short Krid99 ; yes, go bugcheck
+
+ stdRET _KeRaiseIrqlToDpcLevel
+
+cPublicFpo 0,1
+Krid99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ stdRET _KeRaiseIrqlToDpcLevel
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+cPublicFpo 0, 0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, SYNCH_LEVEL ; old > new?
+ ja short Kris99 ; yes, go bugcheck
+
+ stdRET _KeRaiseIrqlToSynchLevel
+
+cPublicFpo 0,1
+Kris99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ stdRET _KeRaiseIrqlToSynchLevel
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+ page ,132
+ subttl "Lower irql"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; On a UP system, HalEndSystenInterrupt is treated as a
+; LowerIrql.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall KfLowerIrql ,1
+cPublicFpo 0,1
+ pushfd ; save caller's eflags
+ movzx ecx, cl ; (ecx) = NewIrql
+
+ifdef IRQL_METRICS
+ lock inc HalLowerIrqlCount
+endif
+
+if DBG
+ cmp cl,PCR[PcIrql]
+ ja KliBug
+endif
+ cli
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+ jz KliSWInterruptsDone
+
+cPublicFpo 0,1
+ push ecx ; Save NewIrql
+
+KliDoSWInterrupt:
+ bsr ecx, edx ; find highest priority interrupt.
+ ; (ecx) is bit position
+;
+; lower to irql level we are emulating
+;
+ mov PCR[PcIrql], ecx
+ cmp ecx, PCR[PcHal.PcrMyPICsIrql]
+ jae short Kli50
+
+ mov PCR[PcHal.PcrMyPICsIrql], ecx
+ mov eax, KiI8259MaskTable[ecx*4]
+ or eax, PCR[PcIDR]
+ SET_IRQ_MASK
+
+Kli50:
+ mov eax, 1
+ shl eax, cl
+ xor PCR[PcIRR], eax ; clear bit in IRR
+
+ call SWInterruptHandlerTable[ecx*4]
+
+;
+; When the trap handler returns, we will end up here
+;
+
+ mov ecx, [esp] ; Restore NewIrql
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ jnz KliDoSWInterrupt ; get next pending interrupt
+
+ add esp, 4
+cPublicFpo 0,0
+
+KliSWInterruptsDone:
+ mov PCR[PcIrql], ecx ; save NewIrql
+ cmp ecx, PCR[PcHal.PcrMyPICsIrql]
+ jb KliLowerPICMasks ; really lower the masks
+ popfd
+ fstRET KfLowerIrql
+
+KliLowerPICMasks:
+;
+; really lower each PICs mask
+;
+ mov PCR[PcHal.PcrMyPICsIrql], ecx
+ mov eax, KiI8259MaskTable[ecx*4]
+ or eax, PCR[PcIDR]
+ SET_IRQ_MASK
+
+ popfd
+ fstRET KfLowerIrql
+
+if DBG
+cPublicFpo 1,3
+KliBug:
+ push ecx ; new irql for debugging
+ push PCR[PcIrql] ; old irql for debugging
+ mov byte ptr PCR[PcIrql],HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+endif
+fstENDP KfLowerIrql
+
+cPublicProc _HalpEndSoftwareInterrupt,1
+cPublicFpo 1,0
+ mov ecx, [esp+4]
+ fstCall KfLowerIrql
+ stdRet _HalpEndSoftwareInterrupt
+stdENDP _HalpEndSoftwareInterrupt
+
+ page ,132
+ subttl "Get current irql"
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+cPublicFpo 0,0
+ xor eax,eax
+ mov al, byte ptr PCR[PcIrql] ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfAcquireSpinLock,1
+cPublicFpo 0,0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short asl99 ; yes, go bugcheck
+endif
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+
+sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
+ fstRET KfAcquireSpinLock
+
+ public KfAcquireSpinLockSpinning
+KfAcquireSpinLockSpinning: ; label for profiling
+
+align 4
+sl20: SPIN_ON_SPINLOCK ecx,<short sl10>
+
+if DBG
+cPublicFpo 2, 1
+asl99:
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfAcquireSpinLock
+fstENDP KfAcquireSpinLock
+
+ PAGE
+ SUBTTL "Acquire Synch Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired,
+; any spin should occur at OldIrql)
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+;
+; Disable interrupts
+;
+
+sls10: cli
+
+;
+; Try to obtain spinlock. Use non-lock operation first
+;
+ TEST_SPINLOCK ecx,<short sls20>
+ ACQUIRE_SPINLOCK ecx,<short sls20>
+
+
+;
+; Got the lock, raise to SYNCH_LEVEL
+;
+
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+;
+; Enable interrupts and return
+;
+
+ sti
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sls20: sti
+ SPIN_ON_SPINLOCK ecx,sls10
+
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+
+ RELEASE_SPINLOCK ecx ; release it
+
+ mov ecx, edx ; (ecx) = NewIrql
+ jmp @KfLowerIrql@4
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ push ecx ; Push FAST_MUTEX addr
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql
+
+ pop ecx ; (ecx) = Fast Mutex
+
+cPublicFpo 0,0
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,1
+ push ecx
+ push eax
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax
+ pop ecx
+
+cPublicFpo 0,0
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+
+;
+; Try to acquire
+;
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam25 ; Yes, abort
+
+cPublicFpo 0,1
+ push ecx ; Push FAST_MUTEX
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ mov ecx, [esp] ; Restore FAST_MUTEX
+ mov [esp], eax ; Save OldIrql
+
+ mov eax, 1 ; Value to compare against
+ mov edx, 0 ; Value to set
+ lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire
+ jnz short tam20 ; got it?
+
+cPublicFpo 0,0
+ pop edx ; (edx) = OldIrql
+ mov eax, 1 ; return TRUE
+ mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql
+ fstRet ExTryToAcquireFastMutex
+
+tam20: pop ecx ; (ecx) = OldIrql
+ fstCall KfLowerIrql ; restore OldIrql
+tam25: xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz @KfLowerIrql@4 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+ jmp @KfLowerIrql@4
+
+
+fstENDP ExReleaseFastMutex
+
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+cPublicFpo 0,0
+
+ ;
+ ; Mask interrupts off at PIC
+ ; (raising to high_level does not work on lazy irql implementation)
+ ;
+ mov eax, KiI8259MaskTable[HIGH_LEVEL*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_IRQ_MASK ; set 8259 masks
+
+ mov byte ptr PCR[PcIrql], HIGH_LEVEL ; set new irql
+
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+
+
+ page ,132
+ subttl "Postponed Hardware Interrupt Dispatcher"
+;++
+;
+; VOID
+; HalpHardwareInterruptNN (
+; VOID
+; );
+;
+; Routine Description:
+;
+; These routines branch through the IDT to simulate the appropriate
+; hardware interrupt. They use the "INT nn" instruction to do this.
+;
+; Arguments:
+;
+; None.
+;
+; Returns:
+;
+; None.
+;
+; Environment:
+;
+; IRET frame is on the stack
+;
+;--
+cPublicProc _HalpHardwareInterruptTable
+cPublicFpo 0,0
+
+ public HalpHardwareInterrupt00
+HalpHardwareInterrupt00 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 0
+ ret
+
+ public HalpHardwareInterrupt01
+HalpHardwareInterrupt01 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 1
+ ret
+
+ public HalpHardwareInterrupt02
+HalpHardwareInterrupt02 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 2
+ ret
+
+ public HalpHardwareInterrupt03
+HalpHardwareInterrupt03 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 3
+ ret
+
+ public HalpHardwareInterrupt04
+HalpHardwareInterrupt04 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 4
+ ret
+
+ public HalpHardwareInterrupt05
+HalpHardwareInterrupt05 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 5
+ ret
+
+ public HalpHardwareInterrupt06
+HalpHardwareInterrupt06 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 6
+ ret
+
+ public HalpHardwareInterrupt07
+HalpHardwareInterrupt07 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 7
+ ret
+
+ public HalpHardwareInterrupt08
+HalpHardwareInterrupt08 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 8
+ ret
+
+ public HalpHardwareInterrupt09
+HalpHardwareInterrupt09 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 9
+ ret
+
+ public HalpHardwareInterrupt10
+HalpHardwareInterrupt10 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 10
+ ret
+
+ public HalpHardwareInterrupt11
+HalpHardwareInterrupt11 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 11
+ ret
+
+ public HalpHardwareInterrupt12
+HalpHardwareInterrupt12 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 12
+ ret
+
+ public HalpHardwareInterrupt13
+HalpHardwareInterrupt13 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 13
+ ret
+
+ public HalpHardwareInterrupt14
+HalpHardwareInterrupt14 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 14
+ ret
+
+ public HalpHardwareInterrupt15
+HalpHardwareInterrupt15 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 15
+ ret
+stdENDP _HalpHardwareInterruptTable
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine sends the 8259 PIC initialization commands and
+; masks all the interrupts on 8259s.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+
+ push esi ; save caller's esi
+ cli ; disable interrupt
+ lea esi, PICsInitializationString
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ mov al, 0FFH ; mask all 8259 irqs
+ out dx,al ; write mask to PIC
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+
+ pop esi ; restore caller's esi
+ sti ; enable interrupt
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halncr/i386/ncrlarc.c b/private/ntos/nthals/halncr/i386/ncrlarc.c
new file mode 100644
index 000000000..e486fcdbc
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrlarc.c
@@ -0,0 +1,392 @@
+/*++
+
+Copyright (c) 1992 NCR Corporation
+
+Module Name:
+
+ ncrlarc.c
+
+Abstract:
+
+
+Author:
+
+ Rick Ulmer
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+//#include "halp.h"
+#include "ki.h"
+#include "stdio.h"
+#include "ncr.h"
+#include "ncrcat.h"
+#include "ncrsus.h"
+
+extern PPROCESSOR_BOARD_INFO SUSBoardInfo;
+extern ULONG NCRLogicalDyadicProcessorMask;
+extern ULONG NCRLogicalQuadProcessorMask;
+extern ULONG NCRLogicalNumberToPhysicalMask[];
+extern ULONG NCRExistingQuadProcessorMask;
+extern ULONG NCRActiveProcessorMask;
+
+extern ULONG NCRLarcPageMask;
+
+#define PASS_LARC_TEST 1
+#define LARC_TEST 2
+#define LARC_BANK0 4
+#define LARC_BANK1 8
+#define LARC_8MB 0x80
+#define LARC_2MB 0x40
+#define LARC_PAGES 8
+#define LARC_TIMEOUT 40000 // This is what the UNIX Guys use.
+
+
+ULONG NCRLarcEnabledPages[8] = {0}; // LARC size by Voyager slot
+
+
+PCHAR
+NCRUnicodeToAnsi(
+ IN PUNICODE_STRING UnicodeString,
+ OUT PCHAR AnsiBuffer,
+ IN ULONG MaxAnsiLength
+ )
+{
+ PCHAR Dst;
+ PWSTR Src;
+ ULONG Length;
+
+ Length = UnicodeString->Length / sizeof( WCHAR );
+ if (Length >= MaxAnsiLength) {
+ Length = MaxAnsiLength - 1;
+ }
+ Src = UnicodeString->Buffer;
+ Dst = AnsiBuffer;
+ while (Length--) {
+ *Dst++ = (UCHAR)*Src++;
+ }
+ *Dst = '\0';
+ return AnsiBuffer;
+}
+
+
+
+VOID
+HalpInitializeLarc (
+ )
+/*++
+
+Routine Description:
+ Initialize any Larc's that may exist on any Quad processor boards
+
+Arguments:
+ none.
+
+Return Value:
+ none.
+
+--*/
+
+{
+ PLIST_ENTRY ModuleListHead;
+ PLIST_ENTRY Next;
+ PLDR_DATA_TABLE_ENTRY DataTableEntry;
+ CHAR Buffer[256];
+ UCHAR AnsiBuffer[ 32 ];
+ ULONG i;
+ PHYSICAL_ADDRESS kernel_physical;
+ ULONG base;
+ UCHAR addr[2];
+ CAT_CONTROL cat_control;
+ LONG status;
+ UCHAR data;
+ UCHAR enable;
+ BOOLEAN larc_found = FALSE;
+ ULONG timeout_count;
+ LONG pages, page, banks;
+
+ DBGMSG(("HalpInitializeLarc: KeLoaderBlock = 0x%x\n",KeLoaderBlock));
+
+ //
+ // Dump the loaded module list
+ //
+
+ if (KeLoaderBlock != NULL) {
+ ModuleListHead = &KeLoaderBlock->LoadOrderListHead;
+
+ } else {
+ DBGMSG(("HalpInitializeLarc: KeLoaderBlock is NULL returning...\n"));
+ return;
+ }
+
+ Next = ModuleListHead->Flink;
+
+ if (Next != NULL) {
+
+ i = 0;
+
+ DBGMSG(("HalpInitializeLarc: ModuleListHead = 0x%x\n", ModuleListHead));
+
+ DBGMSG(("HalpInitializeLarc: Next = 0x%x\n", Next));
+ while (Next != ModuleListHead) {
+
+ DataTableEntry = CONTAINING_RECORD(Next,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ sprintf (Buffer, "HalpInitializeLarc: Name: %s Base: 0x%x\n",
+ NCRUnicodeToAnsi(&DataTableEntry->BaseDllName,AnsiBuffer,sizeof(AnsiBuffer)),
+ DataTableEntry->DllBase
+ );
+
+ DBGMSG((Buffer));
+
+ if (strncmp(AnsiBuffer,"ntoskrnl",8) == 0) {
+ kernel_physical = MmGetPhysicalAddress(DataTableEntry->DllBase);
+
+ DBGMSG(("HalpInitializeLarc: Found kernel at Virtual address 0x%x and Physical Address 0x%x\n",
+ DataTableEntry->DllBase,
+ kernel_physical.LowPart));
+ break;
+ }
+
+ if (i++ == 30) {
+ DBGMSG(("HalpInitializeLarc: ModuleList too long breaking out\n"));
+ break;
+ }
+ Next = Next->Flink;
+ DBGMSG(("HalpInitializeLarc: Next = 0x%x\n", Next));
+ }
+ }
+
+ base = 0xffc00000 & kernel_physical.LowPart; // round down to 4MB boundary
+
+ addr[0] = base >> 24;
+ addr[1] = base >> 16;
+
+//
+// Lets check for larc info
+//
+
+ DBGMSG(("HalpInitializeLarc: Lets look to Quad boards and larc\n"));
+
+ for (i = 0; i < SUSBoardInfo->NumberOfBoards; i++ ) {
+ if (SUSBoardInfo->QuadData[i].Type != QUAD) {
+ continue;
+ }
+ switch (SUSBoardInfo->QuadData[i].Slot) {
+ case 1:
+ cat_control.Module = QUAD_BB0;
+ break;
+ case 2:
+ cat_control.Module = QUAD_BB1;
+ break;
+ case 3:
+ cat_control.Module = QUAD_BB2;
+ break;
+ case 4:
+ cat_control.Module = QUAD_BB3;
+ break;
+ }
+ cat_control.Asic = QABC;
+
+ //
+ // get LARC bank info
+ //
+
+ cat_control.Command = READ_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x3;
+ status = HalCatBusIo(&cat_control, &enable);
+
+ if (((enable & (LARC_BANK0|LARC_BANK1)) == 0) || (status != CATNOERR)) {
+ //
+ // no LARC on this board
+ //
+ continue;
+ }
+
+ larc_found = TRUE;
+
+ DBGMSG(("HalpInitializeLarc: Found LARC in Slot %d, with Self_test Reg = 0x%x\n",
+ SUSBoardInfo->QuadData[i].Slot,
+ enable));
+ //
+ // Disable all 4MB pages
+ //
+
+
+ data = 0;
+ cat_control.Command = WRITE_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x0;
+ status = HalCatBusIo(&cat_control, &data);
+
+ //
+ // Set new LARC base
+ //
+
+ cat_control.NumberOfBytes = 2;
+ cat_control.Address = 0x1;
+ status = HalCatBusIo(&cat_control, addr);
+
+ //
+ // now lets test the LARC
+ //
+
+ enable |= LARC_TEST; // Run LARC test
+
+ cat_control.Command = WRITE_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x3;
+ status = HalCatBusIo(&cat_control, &enable);
+ }
+
+
+ if (!larc_found) {
+ return;
+ }
+
+ //
+ // lets wait for all LARC test to complete
+ //
+
+ DBGMSG(("HalpInitializeLarc: Now waiting for LARC self-test to complete.\n"));
+
+ for (i = 0; i < SUSBoardInfo->NumberOfBoards; i++ ) {
+ if (SUSBoardInfo->QuadData[i].Type != QUAD) {
+ continue;
+ }
+ switch (SUSBoardInfo->QuadData[i].Slot) {
+ case 1:
+ cat_control.Module = QUAD_BB0;
+ break;
+ case 2:
+ cat_control.Module = QUAD_BB1;
+ break;
+ case 3:
+ cat_control.Module = QUAD_BB2;
+ break;
+ case 4:
+ cat_control.Module = QUAD_BB3;
+ break;
+ }
+ cat_control.Asic = QABC;
+
+ cat_control.Command = READ_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x3;
+ timeout_count = 0;
+
+ do {
+ status = HalCatBusIo(&cat_control, &enable);
+ if (status != CATNOERR) {
+ return;
+ }
+ if ((enable & (LARC_BANK0|LARC_BANK1)) == 0) {
+ break; // no LARC on this QUAD board
+ }
+ } while ((enable & LARC_TEST) && (++timeout_count < LARC_TIMEOUT));
+ DBGMSG(("HalpInitializeLarc: LARC in slot %d, complete: enable = 0x%x, timeout_count =%d\n",
+ SUSBoardInfo->QuadData[i].Slot, enable, timeout_count));
+ }
+ DBGMSG(("HalpInitializeLarc: All LARCS test complete.....\n"));
+
+
+
+ //
+ // Lets enable the LARCS
+ //
+
+ DBGMSG(("HalpInitializeLarc: Now Enabling LARC pages\n"));
+
+ for (i = 0; i < SUSBoardInfo->NumberOfBoards; i++ ) {
+ if (SUSBoardInfo->QuadData[i].Type != QUAD) {
+ continue;
+ }
+ switch (SUSBoardInfo->QuadData[i].Slot) {
+ case 1:
+ cat_control.Module = QUAD_BB0;
+ break;
+ case 2:
+ cat_control.Module = QUAD_BB1;
+ break;
+ case 3:
+ cat_control.Module = QUAD_BB2;
+ break;
+ case 4:
+ cat_control.Module = QUAD_BB3;
+ break;
+ }
+ cat_control.Asic = QABC;
+
+ cat_control.Command = READ_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x3;
+ status = HalCatBusIo(&cat_control, &enable);
+
+ if (((enable & (LARC_BANK0|LARC_BANK1)) == 0) || (status != CATNOERR)) {
+ //
+ // no LARC on this board
+ //
+ continue;
+ }
+
+ if ((enable & PASS_LARC_TEST) == 0) {
+ //
+ // this LARC did not pass self-test
+ //
+ continue;
+ }
+
+
+ if (enable & LARC_BANK0) {
+ banks = 1;
+ } else {
+ banks = 0;
+ }
+
+ if (enable & LARC_BANK1) {
+ banks += 1;
+ }
+
+ if (enable & LARC_8MB) {
+ pages = 4 * banks;
+ } else {
+ pages = banks;
+ }
+
+ cat_control.Command = READ_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x0;
+ status = HalCatBusIo(&cat_control, &enable);
+
+ DBGMSG(("HalpInitializeLarc: banks = %d, pages = %d\n",banks, pages));
+
+ NCRLarcEnabledPages[SUSBoardInfo->QuadData[i].Slot-1] = pages;
+
+ for (page = 1; pages > 0; page <<= 1, pages--) {
+ enable |= page;
+ }
+
+ enable &= NCRLarcPageMask; // now apply enable mask
+
+ cat_control.Command = WRITE_SUBADDR;
+
+ DBGMSG(("HalpInitializeLarc: Slot %d, enable Mask = 0x%x\n",
+ SUSBoardInfo->QuadData[i].Slot,
+ enable));
+
+ status = HalCatBusIo(&cat_control, &enable);
+ }
+
+ DBGMSG(("HalpInitializeLarc: Done\n"));
+}
+
+
+
diff --git a/private/ntos/nthals/halncr/i386/ncrlock.asm b/private/ntos/nthals/halncr/i386/ncrlock.asm
new file mode 100644
index 000000000..9ee3b35bd
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrlock.asm
@@ -0,0 +1,103 @@
+
+ title "NCR Lock Routines"
+;++
+;
+; Copyright (c) 1992 NCR - MSBU
+;
+; Module Name:
+;
+; ncrlock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to perform atomic
+; operations specific to the NCR - MSBU platforms.
+;
+; Author:
+;
+; Richard R. Barton (o-richb) 20 Mar 1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;
+;--
+
+.386p
+include callconv.inc ; calling convention macros
+ .xlist
+
+_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Locked Or"
+;++
+;
+; Routine Description:
+;
+; This function atomically ors the second argument with the given
+; pointer to an unsigned long.
+;
+; Arguments:
+;
+; Pointer to unsigned long.
+;
+; Thing to or it with.
+;
+; Return Value:
+;
+; None
+;
+;--
+
+cPublicProc _NCRLockedOr ,2
+
+ mov ecx, 1*4[esp]
+ mov eax, 2*4[esp]
+
+ lock or [ecx], eax
+
+ stdRET _NCRLockedOr
+
+stdENDP _NCRLockedOr
+
+
+ page ,132
+ subttl "Locked Exchange and Add"
+;++
+;
+; Routine Description:
+;
+; This function atomically adds the second argument with the given
+; pointer to an unsigned long.
+;
+; Arguments:
+;
+; Pointer to unsigned long.
+;
+; Thing to add it with.
+;
+; Return Value:
+;
+; Return value is previous value pointed to by 2nd argument
+;
+;--
+
+cPublicProc _NCRLockedExchangeAndAdd ,2
+
+ mov ecx, 1*4[esp]
+ mov eax, 2*4[esp]
+
+; lock xadd [ecx], eax
+ db 0F0H, 0FH, 0C1H, 01H
+
+ stdRET _NCRLockedExchangeAndAdd
+
+stdENDP _NCRLockedExchangeAndAdd
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halncr/i386/ncrmcabs.c b/private/ntos/nthals/halncr/i386/ncrmcabs.c
new file mode 100644
index 000000000..9d37fc7f6
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrmcabs.c
@@ -0,0 +1,243 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ncrmcabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+ULONG
+HalpGetMCAInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetSMCAInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetMCAInterruptVector)
+#endif
+
+
+ULONG
+HalpGetMCAInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
+ // up on IRQ 9.
+ //
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+
+ // RMU
+ BusInterruptVector = BusInterruptLevel;
+
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+ULONG
+HalpGetSMCAInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
+ // up on IRQ 9.
+ //
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+
+ // RMU
+ BusInterruptVector = BusInterruptLevel + 0x10;
+
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+BOOLEAN
+HalpTranslateSMCBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a SMC bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ if (BusAddress.HighPart != 0) {
+ // Unsupported range
+ return (FALSE);
+ }
+
+ switch (*AddressSpace) {
+ case 0: // MEMORY space
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+ break;
+ case 1: // IO space
+ TranslatedAddress->LowPart = BusAddress.LowPart | 0x00010000;
+ TranslatedAddress->HighPart = 0;
+ break;
+ default: // UNKOWN address space
+ return FALSE;
+ }
+
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halncr/i386/ncrmem.h b/private/ntos/nthals/halncr/i386/ncrmem.h
new file mode 100644
index 000000000..aec0a83b6
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrmem.h
@@ -0,0 +1,494 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncrmem.h
+
+Author:
+
+Abstract:
+
+ System equates for dealing with the NCR Memory boads.
+
+++*/
+
+#ifndef _NCRMEM_
+#define _NCRMEM_
+
+
+/*
+ * Memory module
+ */
+
+#define NUM_MEMORY_CARDS_L5 2
+#define NUM_MMC_PER_CARD 1
+#define NUM_MMA_PER_CARD 1
+#define NUM_MMD_PER_CARD 4
+
+#define NUM_POSSIBLE_SIMMS 48
+#define EDC_FIELD (32+7)
+#define INTERLEAVES_PER_BOARD 2
+#define MAX_BANKS 2
+
+
+/* defines for union referencing */
+
+#define CONFIG0 CatRegisters.CatRegs.Config0
+#define CONFIG1 CatRegisters.CatRegs.Config1
+#define CONTROL2 CatRegisters.CatRegs.Control2
+#define CONFIG3 CatRegisters.CatRegs.Config3
+#define CONFIG4 CatRegisters.CatRegs.Config4
+#define CONFIG5 CatRegisters.CatRegs.Config5
+#define SUBADDRESS6 CatRegisters.CatRegs.SubAddress6
+#define SUBADDRESS7 CatRegisters.CatRegs.SubAddress7
+#define CONFIG8 CatRegisters.CatRegs.Config8
+#define CONFIG9 CatRegisters.CatRegs.Config9
+#define CONFIGA CatRegisters.CatRegs.ConfigA
+#define CONFIGB CatRegisters.CatRegs.ConfigB
+#define CONFIGC CatRegisters.CatRegs.ConfigC
+#define CONFIGD CatRegisters.CatRegs.ConfigD
+#define CONFIGE CatRegisters.CatRegs.ConfigE
+#define StatusF CatRegisters.CatRegs.StatusF
+
+
+
+/*
+ *
+ * Description : Config registers for the Magellan Memory Address 1 ASIC.
+ */
+
+/* Main CAT registers */
+#define MMA1_Config 0x00
+# define MMA1_128bit 0x01
+# define MMA1_I0TwoBanks 0x10
+# define MMA1_I1TwoBanks 0x20
+#define MMA1_ParityTest 0x01
+# define MMA1_ParB3 0x80
+# define MMA1_ParB2 0x40
+# define MMA1_ParB1 0x20
+# define MMA1_ParB0 0x10
+# define MMA1_ParA3 0x08
+# define MMA1_ParA2 0x04
+# define MMA1_ParA1 0x02
+# define MMA1_ParA0 0x01
+
+#define MMA1_Byte_A_Error 0x0d /* Byte in Error Register */
+#define MMA1_Byte_B_Error 0x0e /* Byte in Error Register */
+# define MMA1_Prty_Byte3 0x08 /* Parity error in byte 3 */
+# define MMA1_Prty_Byte2 0x04 /* Parity error in byte 2 */
+# define MMA1_Prty_Byte1 0x02 /* Parity error in byte 1 */
+# define MMA1_Prty_Byte0 0x01 /* Parity error in byte 0 */
+
+#define MMA1_Subport_Data 0x03
+#define MMA1_Subport_Addr 0x06
+
+/* addr0 decodes MMA */
+#define MEM 0x02
+#define MOP 0x01
+#define ADDR_MASK 0xfffffff8 /* lowest 3 bits are not valid */
+#define BYTE0 0x01
+#define BYTE1 0x02
+#define BYTE2 0x04
+#define BYTE3 0x08
+
+#define BANK1 0x10 /* bit 4 of interleave error address */
+
+/* macros */
+#define MEM_BIT(_x) ( (((_x) & MEM) == MEM) ? 0x1 : 0x0 )
+#define MOP_BIT(_x) ( (((_x) & MOP) == MOP) ? 0x1 : 0x0 )
+
+/* Subaddress CAT Extension registers */
+#define MMA1_Sub_Start 0x00 /* First sub address extension regs */
+#define MMA1_Sub_Size 32 /* The number of subaddress extension regs */
+#define MMA1_BusB_Sub_Start 0x10 /* First Bus B register */
+#define MMA1_Bus_Sub_Size 0x0C /* Size of Bus specific registers */
+#define MMA1_Interleave_0_Start 0x0D /* First Byte of Interleave 0 */
+#define MMA1_Interleave_1_Start 0x1C /* First Byte of Interleave 1 */
+#define MMA1_Interleave_Size 0x04 /* Size of Interleave registers */
+//
+// (ts) 2/24/95 Changes for Disco Memory Support
+//
+
+#define DMAC1_Sub_Start (MMA1_Sub_Start+MMA_SubAddress)
+#define DMAC1_BusB_Sub_Start (MMA1_BusB_Sub_Start+MMA_SubAddress)
+#define DMAC1_Interleave_0_Start (MMA1_Interleave_0_Start+MMA_SubAddress)
+#define DMAC1_Interleave_1_Start (MMA1_Interleave_Size+MMA_SubAddress)
+/* For the DMAC1 the MMA1 direct address registers are at 0x40 - 0x4f
+ * For the DMAC1 the MMA1 subaddress registers are at 0x20 - 0x3f
+ */
+
+#define MMA_Direct 0x40
+#define MMA_SubAddress 0x20
+
+
+typedef struct _MMA1_INFO {
+ ULONG JtagId;
+ UCHAR Flag;
+ union {
+ CAT_REGISTERS CatRegs;
+ struct {
+ UCHAR Dummy0;
+ UCHAR ParityTest;
+ UCHAR Dummy2;
+ UCHAR Dummy3;
+ UCHAR InterleaveLA0;
+ UCHAR InterleaveLA1;
+ UCHAR Dummy6;
+ UCHAR IoStartAddress;
+ UCHAR Dummy8;
+ UCHAR IoEndAddress;
+ UCHAR I1StartAddress;
+ UCHAR DummyB;
+ UCHAR I1EndAddress;
+ UCHAR ErrorByteA;
+ UCHAR ErrorByteB;
+ UCHAR DummyF;
+ } MmaRegisters;
+ } CatRegisters;
+ UCHAR LastBusAAddressError0; /* for PAR_INT diagnosis */
+ UCHAR LastBusAAddressError1; /* for PAR_INT diagnosis */
+ UCHAR LastBusAAddressError2; /* for PAR_INT diagnosis */
+ UCHAR LastBusAAddressError3; /* for PAR_INT diagnosis */
+
+ UCHAR GoodBusAAddressError0; /* for PAR_INT diagnosis */
+ UCHAR GoodBusAAddressError1; /* for PAR_INT diagnosis */
+ UCHAR GoodBusAAddressError2; /* for PAR_INT diagnosis */
+ UCHAR GoodBusAAddressError3; /* for PAR_INT diagnosis */
+
+ UCHAR BusAErrorAddress0; /* for ERROR_L diagnosis */
+ UCHAR BusAErrorAddress1; /* for ERROR_L diagnosis */
+ UCHAR BusAErrorAddress2; /* for ERROR_L diagnosis */
+ UCHAR BusAErrorAddress3; /* for ERROR_L diagnosis */
+
+ UCHAR Interleave0Error0;
+ UCHAR Interleave0Error1;
+ UCHAR Interleave0Error2;
+ UCHAR Interleave0Error3;
+
+ UCHAR LastBusBAddressError0; /* for PAR_INT diagnosis */
+ UCHAR LastBusBAddressError1; /* for PAR_INT diagnosis */
+ UCHAR LastBusBAddressError2; /* for PAR_INT diagnosis */
+ UCHAR LastBusBAddressError3; /* for PAR_INT diagnosis */
+
+ UCHAR GoodBusBAddressError0; /* for PAR_INT diagnosis */
+ UCHAR GoodBusBAddressError1; /* for PAR_INT diagnosis */
+ UCHAR GoodBusBAddressError2; /* for PAR_INT diagnosis */
+ UCHAR GoodBusBAddressError3; /* for PAR_INT diagnosis */
+
+ UCHAR BusBErrorAddress0; /* for ERROR_L diagnosis */
+ UCHAR BusBErrorAddress1; /* for ERROR_L diagnosis */
+ UCHAR BusBErrorAddress2; /* for ERROR_L diagnosis */
+ UCHAR BusBErrorAddress3; /* for ERROR_L diagnosis */
+
+ UCHAR Interleave1Error0;
+ UCHAR Interleave1Error1;
+ UCHAR Interleave1Error2;
+ UCHAR Interleave1Error3;
+
+ UCHAR FirstError[2]; /* new for DMAC1 */
+ UCHAR SecondError[2]; /* new for DMAC1 */
+ UCHAR DisconnectGroups[2]; /* new for DMAC1 */
+ UCHAR BusyIndication[2]; /* new for DMAC1 */
+
+} MMA1_INFO, *PMMA1_INFO;
+
+
+/* defines for union referencing */
+#define BYTE_ERROR_A CatRegisters.MmaRegisters.ErrorByteA
+#define BYTE_ERROR_B CatRegisters.MmaRegisters.ErrorByteB
+
+
+
+/*
+ *
+ * Description : Config registers for the Magellan Memory Data 1 ASIC.
+ *
+ */
+
+
+/* Main CAT registers */
+
+#define MMC1_Subport_Data 0x03
+#define MMC1_Subport_Addr 0x06
+
+#define MMC1_Parity_Status_A 0x00
+#define MMC1_Parity_Status_B 0x10
+# define MMC1_Addr_Parity_Err 0x02
+# define MMC1_Data_Parity_Err 0x01
+
+#define MMC1_Config1 0x08
+# define MMC1_SBErr_DetectDisable 0x04
+# define MMC1_LBEDIS_DetectDisable 0x40
+
+/* Subaddress space */
+#define MMC1_Inter_0_Status 0x09
+#define MMC1_Inter_1_Status 0x19
+# define MMC1_Clear_Interleave 0x01
+
+#define MMC1_Interleave_0_Info_0 0x0A
+#define MMC1_Interleave_1_Info_0 0x1A
+# define MMC1_BusA_Cpu0 0x01
+# define MMC1_BusA_Cpu1 0x02
+# define MMC1_BusA_Cpu2 0x04
+# define MMC1_BusA_Cpu3 0x08
+# define MMC1_BusB_Cpu0 0x10
+# define MMC1_BusB_Cpu1 0x20
+# define MMC1_BusB_Cpu2 0x40
+# define MMC1_BusB_Cpu3 0x80
+
+#define MMC1_Interleave_0_Info_1 0x0B
+#define MMC1_Interleave_1_Info_1 0x1B
+
+
+#define MMC1_Intr0_Single_Bit_Status 0x0D
+#define MMC1_Intr1_Single_Bit_Status 0x1D
+# define MMC1_SBerr 0x01
+# define MMC1_SB_LPE_0 0x02
+# define MMC1_SB_LPE_1 0x04
+# define MMC1_SB_LPE_2 0x08
+# define MMC1_SB_ErrInt 0x40
+# define MMC1_ErrStore 0x80
+
+#define MMC1_Intr0_Single_Bit_Info_0 0x0E
+#define MMC1_Intr0_Single_Bit_Info_1 0x0F
+#define MMC1_Intr1_Single_Bit_Info_0 0x1E
+#define MMC1_Intr1_Single_Bit_Info_1 0x1F
+
+
+/* Subaddress CAT Extension registers */
+#define MMC1_Sub_Start 0x00 /* First sub address extension regs */
+#define MMC1_Sub_Size 32 /* The number of subaddress extension regs */
+#define MMC1_BusB_Sub_Start 0x10 /* First sub address for Bus B */
+#define MMC1_Bus_Sub_Size 0x09 /* Size of sub address for Bus */
+#define MMC1_Interleave_0_Start 0x09 /* First sub address for Interleave 0 */
+#define MMC1_Interleave_1_Start 0x19 /* First sub address for Interleave 1 */
+#define MMC1_Interleave_Size 0x07 /* Size of interleave space */
+
+/* Error interrupt status MMC */
+#define MBIT 0x01
+#define MOWN 0x02
+#define ILV_LOCK 0x04
+#define LBE 0x40
+#define LPE_MASK 0x38
+#define LPE_SHIFT 3
+#define ERR_STORE 0x80
+
+#define LPE_BITS(_x) ( (int)((_x) & LPE_MASK) >> LPE_SHIFT )
+/* Interrupt info 0 */
+#define SB_ID_MASK 0xf0
+#define SB_ID_SHIFT 4
+#define SA_ID_MASK 0x0f
+
+/* Interrupt info 1 */
+#define LST8 0x01
+#define LST8_SHIFT 8
+#define SA_MID 0x02
+#define SB_MID 0x04
+#define E_AP256 0x08
+#define E_BOP_MASK 0xf0
+
+/* error status */
+#define CO_ERR 0x10
+#define CO_DPE 0x08
+#define LK_LPE 0x04
+
+#define ERROR_L_MASK (CO_ERR | CO_DPE | LK_LPE | MOWN | MBIT)
+
+/* last_control_X0 decodes MMC */
+#define MID 0x10
+#define ID_MASK 0x0f
+#define MACK_MASK 0x60
+#define MACK_SHIFT 5
+
+/* last_control_X1 decodes MMC */
+#define LOCKG 0x80
+#define LOCKL 0x40
+#define MIC 0x20
+#define AP256 0x10
+#define BOP_MASK 0x0f
+
+/* macros */
+#define MIC_BIT(_x) ( (((_x) & MIC) == MIC) ? 0x1 : 0x0 )
+#define MACK_BITS(_x) ( (int)((_x) & MACK_MASK) >> MACK_SHIFT )
+
+typedef struct _MMC1_INFO {
+ ULONG JtagId;
+ UCHAR Flag;
+ union {
+ CAT_REGISTERS CatRegs;
+ struct {
+ UCHAR Dummy0;
+ UCHAR Dummy1;
+ UCHAR Dummy2;
+ UCHAR Dummy3;
+ UCHAR Dummy4;
+ UCHAR Dummy5;
+ UCHAR Dummy6;
+ UCHAR Dummy7;
+ UCHAR Mode1;
+ UCHAR ActiveProcessors;
+ UCHAR Mode2;
+ UCHAR RefreshCount;
+ UCHAR RASActiveCount;
+ UCHAR DummyD;
+ UCHAR DummyE;
+ UCHAR DummyF;
+ } MmcRegisters;
+ } CatRegisters;
+ UCHAR ParityInterruptAStatus; /* MEM module detectd parity */
+ UCHAR LastControlA0; /* for PAR_INT diagnosis */
+ UCHAR LastControlA1; /* for PAR_INT diagnosis */
+ UCHAR GoodControlA0; /* for PAR_INT diagnosis */
+ UCHAR GoodControlA1; /* for PAR_INT diagnosis */
+ UCHAR ErrorAStatus; /* MEM module generated ERROR_L */
+ UCHAR ErrorA0; /* for ERROR_L diagnosis */
+ UCHAR ErrorA1; /* for ERROR_L diagnosis */
+ UCHAR ErrorAId; /* MIC timeout ERROR_L */
+ UCHAR Interleave0Status;
+ UCHAR Interleave0Info0;
+ UCHAR Interleave0Info1;
+ UCHAR Interleave0Lst;
+ UCHAR SingleInterruptI0Status;
+ UCHAR SingleInterruptI00;
+ UCHAR SingleInterruptI01;
+ UCHAR ParityInterruptBStatus; /* MEM module detectd parity */
+ UCHAR LastControlB0; /* for PAR_INT diagnosis */
+ UCHAR LastControlB1; /* for PAR_INT diagnosis */
+ UCHAR GoodControlB0; /* for PAR_INT diagnosis */
+ UCHAR GoodControlB1; /* for PAR_INT diagnosis */
+ UCHAR ErrorBStatus; /* MEM module generated ERROR_L */
+ UCHAR ErrorB0; /* for ERROR_L diagnosis */
+ UCHAR ErrorB1; /* for ERROR_L diagnosis */
+ UCHAR ErrorBId; /* MIC timeout ERROR_L */
+ UCHAR Interleave1Status;
+ UCHAR Interleave1Info0;
+ UCHAR Interleave1Info1;
+ UCHAR Interleave1Lst;
+ UCHAR SingleInterruptI1Status;
+ UCHAR SingleInterruptI10;
+ UCHAR SingleInterruptI11;
+//
+// (ts) 2/24/95 Changes for Disco Memory Support
+//
+ UCHAR FirstError[2]; /* new for DMAC1 */
+ UCHAR SecondError[2]; /* new for DMAC1 */
+ UCHAR DisconnectGroups[2]; /* new for DMAC1 */
+ UCHAR BusyIndication[2]; /* new for DMAC1 */
+} MMC1_INFO, *PMMC1_INFO;
+
+
+/*
+ * Description : Config registers for the Magellan Memory Data 1 ASIC.
+ *
+ */
+
+
+/* Main CAT registers */
+
+#define MMD1_TestMode 0x04
+# define MMD1_OddPar 0x20 /* gen parity error */
+
+#define MMD1_Interleave0_Error 0x3 /* Interleave error register */
+# define MMD1_Intro_Line0_Sbe 0x08 /* single bit error */
+# define MMD1_Intro_Line0_Mbe 0x04 /* multiple-bit error */
+# define MMD1_Intro_Line1_Sbe 0x02 /* single bit error */
+# define MMD1_Intro_Line1_Mbe 0x01 /* multiple-bit error */
+
+#define MMD1_Interleave1_Error 0x8 /* Interleave error register */
+# define MMD1_Intr1_Line0_Sbe 0x08 /* single bit error */
+# define MMD1_Intr1_Line0_Mbe 0x04 /* multiple-bit error */
+# define MMD1_Intr1_Line1_Sbe 0x02 /* single bit error */
+# define MMD1_Intr1_Line1_Mbe 0x01 /* multiple-bit error */
+
+#define ECCERROR 0x20
+#define DATAPERR 0x02
+#define PERR_BITS 0x03
+
+#define MERR_ML1 0x08
+#define SERR_ML1 0x04
+#define MERR_ML0 0x02
+#define SERR_ML0 0x01
+
+#define MMD1_ECC_DIAG 0x05 /* ECC Diagnostic register */
+
+#define MMD1_Syn_Diag_0 0x09 /* ECC Syndrome register */
+#define MMD1_Syn_Diag_1 0x0a /* ECC Syndrome register */
+#define MMD1_Syn_Diag_2 0x0b /* ECC Syndrome register */
+#define MMD1_Syn_Diag_3 0x0c /* ECC Syndrome register */
+# define MMD1_CHK_MASK 0x7f /* check bit mask */
+
+#define MMD1_Bus_B_Parity 0x0d /* bus B Parity error */
+#define MMD1_Bus_A_Parity 0x0e /* bus A Parity error */
+# define MMD1_High_Byte 0x02 /* bus parity on high byte */
+# define MMD1_Low_Byte 0x01 /* bus parity on low byte */
+
+#define MMD1_STATUS 0x0f
+# define MMD1_Cat_Stuff 0x09 /* cat bus stuff dont change */
+# define MMD1_EDC_Error 0x20 /* EDC error captured */
+# define MMD1_Data_Parity_Error 0x01 /* Data parity error captured */
+
+
+typedef struct _MMD1_INFO {
+ UCHAR Flag;
+ union {
+ CAT_REGISTERS CatRegs;
+ struct {
+ UCHAR Dummy0;
+ UCHAR Dummy1;
+ UCHAR Dummy2;
+ UCHAR I0EccStatus;
+ UCHAR TestMode;
+ UCHAR ECCDiag;
+ UCHAR Dummy6;
+ UCHAR Dummy7;
+ UCHAR I1EccStatus;
+ UCHAR SyndromeI0ML0;
+ UCHAR SyndromeI0ML1;
+ UCHAR SyndromeI1ML0;
+ UCHAR SyndromeI1ML1;
+ UCHAR ParityAStatus;
+ UCHAR ParityBStatus;
+ UCHAR Status;
+ } MmdRegisters;
+ } CatRegisters;
+} MMD1_INFO, *PMMD1_INFO;
+
+/* defines for union referencing */
+#define INTERLEAVE0_ERROR CatRegisters.MmdRegisters.I0ECCStatus
+#define INTERLEAVE1_ERROR CatRegisters.MmdRegisters.I1ECCStatus
+#define SYN_DIAG_0 CatRegisters.MmdRegisters.SyndromeI0Ml0
+#define SYN_DIAG_1 CatRegisters.MmdRegisters.SyndromeI0Ml1
+#define SYN_DIAG_2 CatRegisters.MmdRegisters.SyndromeI1Ml0
+#define SYN_DIAG_3 CatRegisters.MmdRegisters.SyndromeI1Ml1
+#define BUS_A_PARITY CatRegisters.MmdRegisters.ParityAStatus
+#define BUS_B_PARITY CatRegisters.MmdRegisters.ParityBStatus
+#define MMDSTATUS CatRegisters.MmdRegisters.Status
+
+
+
+typedef struct _FRU_LOCATION {
+ UCHAR BusType;
+ UCHAR BusNumber;
+ UCHAR BusSlotNumber;
+} FRU_LOCATION, *PFRU_LOCATION;
+
+
+
+typedef struct _MEMORY_CARD_INFO {
+ ULONG FruAsic;
+ ULONG FruSimm;
+ ULONG AsicConfidenceLevel;
+ ULONG SimmConfidenceLevel;
+ FRU_LOCATION Location;
+ MMC1_INFO Mmc1Info;
+ MMA1_INFO Mma1Info;
+ MMD1_INFO Mmd1Info[NUM_MMD_PER_CARD];
+} MEMORY_CARD_INFO, *PMEMORY_CARD_INFO;
+
+
+
+
+#endif // _NCRMEM_
diff --git a/private/ntos/nthals/halncr/i386/ncrmp.c b/private/ntos/nthals/halncr/i386/ncrmp.c
new file mode 100644
index 000000000..0c41cbb59
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrmp.c
@@ -0,0 +1,2443 @@
+/*++
+
+Copyright (c) 1992 NCR Corporation
+
+Module Name:
+
+ ncrmp.c
+
+Abstract:
+
+
+Author:
+
+ Richard Barton (o-richb) 24-Jan-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "ixkdcom.h"
+#include "ncr.h"
+#include "stdio.h"
+#include "ncrnls.h"
+#include "ncrcat.h"
+#include "ncrcatp.h"
+#include "ncrsus.h"
+#include "ncrmem.h"
+
+UCHAR HalName[] = "NCR 3x series MP HAL";
+
+ADDRESS_USAGE HalpNCRIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0xF800, 0x100, // IO space reserved for CAT
+ 0xFC00, 0x100, // IO space reserved for VIC
+ 0x97, 0x2, // IO space for 3450 and up CAT SELECT/BASE port
+ 0,0
+ }
+};
+
+ULONG NCRDebug = 0x2;
+ // 0x01 - none
+ // 0x02 - stop on memory edits
+ // 0x04 - enable nmi button on 3360
+ // 0x08 - enable boot on 3550
+ // 0x10 - disable reprogram of QCC and QABC Asics for cache ownership
+ // 0x20 - Enable LARCs
+
+
+ULONG NCRProcessorsToBringup = 0xFFFF;
+ULONG NCRExistingProcessorMask = 0x00;
+ULONG NCRExistingDyadicProcessorMask = 0x00;
+ULONG NCRExistingQuadProcessorMask = 0x00;
+ULONG NCRExtendedProcessorMask = 0x00;
+ULONG NCRExtendedProcessor0Mask = 0x00;
+ULONG NCRExtendedProcessor1Mask = 0x00;
+ULONG NCRActiveProcessorMask = 0x00;
+ULONG NCRActiveProcessorLogicalMask = 0x00;
+ULONG NCRActiveProcessorCount = 0;
+ULONG NCRMaxProcessorCount = NCR_MAX_NUMBER_QUAD_PROCESSORS;
+ULONG LimitMemory = 0;
+
+ULONG NCRNeverClaimIRQs = 0xffffffff; // we start out claiming none
+
+#if 0
+
+//
+// BUGBUG - (shielint) This is requested by Ncr.
+// For now don't let cpus claim any IRQ by setting the flag to -1.
+// NCR/ATT will revisit this problem after NT4.0 release.
+//
+
+ULONG DefaultNeverClaimIRQs = 1 // lets don't claim the timer interrupt
+
+#else
+
+ULONG DefaultNeverClaimIRQs = 0xffffffff; // lets don't claim the timer interrupt
+
+#endif
+
+ULONG NCRMaxIRQsToClaim = 0;
+ULONG NCRGlobalClaimedIRQs = 0;
+
+ULONG NCRLogicalNumberToPhysicalMask[NCR_MAX_NUMBER_PROCESSORS] = {0};
+
+ULONG NCRProcessorIDR[NCR_MAX_NUMBER_PROCESSORS];
+
+ULONG NCRLarcPageMask = 0x1; // only one page by default (4 Meg)
+
+#ifdef DBG
+ULONG NCRProcessorClaimedIRQs[NCR_MAX_NUMBER_PROCESSORS] = {0};
+ULONG NCRClaimCount = 0;
+ULONG NCRStolenCount = 0;
+ULONG NCRUnclaimCount = 0;
+#endif
+
+ULONG NCRLogicalDyadicProcessorMask = 0x00;
+ULONG NCRLogicalQuadProcessorMask = 0x00;
+
+UCHAR NCRSlotExtended0ToVIC[4] = {0, 5, 2, 7};
+UCHAR NCRSlotExtended1ToVIC[4] = {1, 4, 3, 6};
+
+extern ULONG NCRPlatform;
+
+ULONG NCRStatusChangeInterruptEnabled = 0;
+
+extern ULONG HalpDefaultInterruptAffinity;
+
+extern ULONG NCRLarcEnabledPages[]; // LARC size by Voyager slot
+
+/*
+ * Struct used to report secondary MC information to the
+ * Registery
+ */
+
+typedef struct _SMC_RESOURCES {
+ CM_FULL_RESOURCE_DESCRIPTOR ConfigurationData;
+ CM_MCA_POS_DATA PosData[10];
+ } SMC_RESOURCES, *PSMC_RESOURCES;
+
+
+/*
+ * Global variables used for acessing Secondary Microchannel
+ *
+ */
+
+
+ULONG NCRSegmentIoAddress = 0xffe00000;
+PUCHAR NCRSegmentIoRegister = NULL;
+
+/*
+ * Spin lock used to lock the CAT Bus. HalpAcquireCatBusSpinLock and
+ * HalpReleaseCatBusSpinLock use this lock.
+ */
+
+KSPIN_LOCK HalpCatBusLock;
+
+
+typedef struct {
+ ULONG StartingByte;
+ ULONG Pages;
+} NCRClickMapEntry;
+#define ClickMapEntryCount 16
+#define NoExtraDescriptors 16
+
+ULONG NCRAddedDescriptorCount;
+MEMORY_ALLOCATION_DESCRIPTOR NCRAdditionalMemoryDescriptors[NoExtraDescriptors];
+
+
+PVOID NonbootStartupPhysicalPtr;
+PUCHAR NonbootStartupVirtualPtr;
+PUCHAR PageZeroVirtualPtr;
+
+VOID NCRVicIPIHandler(VOID);
+VOID NCRQicIPIHandler(VOID);
+VOID NCRClockBroadcastHandler(VOID);
+
+VOID __cdecl NCRVICErrataHandler1();
+VOID __cdecl NCRVICErrataHandler3();
+VOID __cdecl NCRVICErrataHandler4();
+VOID __cdecl NCRVICErrataHandler5();
+VOID __cdecl NCRVICErrataHandler6();
+VOID __cdecl NCRVICErrataHandler7();
+VOID __cdecl NCRVICErrataHandler15();
+
+VOID __cdecl NCRProfileHandler();
+VOID __cdecl NCRSysIntHandler();
+VOID __cdecl NCRQicSpuriousHandler();
+
+PUCHAR NCRDeterminePlatform(PBOOLEAN);
+VOID NCRFixMemory(PLOADER_PARAMETER_BLOCK);
+VOID NCRLimitMemory(PLOADER_PARAMETER_BLOCK);
+VOID NCRVerifyMemoryRange (ULONG, ULONG, PLOADER_PARAMETER_BLOCK);
+//VOID NCRAdjustMemoryDescriptor(PMEMORY_ALLOCATION_DESCRIPTOR,
+// NCRClickMapEntry *);
+VOID NCRSetupDiagnosticProcessor(PLOADER_PARAMETER_BLOCK);
+
+VOID NCRLockedOr(PULONG, ULONG);
+VOID NCRParseLoaderOptions (PUCHAR Options);
+BOOLEAN NCRGetValue (PUCHAR Options, PUCHAR String, PULONG Value);
+ULONG HalpGetCmosData (ULONG SourceLocation, ULONG SourceAddress,
+ PUCHAR Buffer, ULONG Length);
+
+VOID HalpDisableSingleBitErrorDET();
+VOID HalpInitializeSMCInterface();
+VOID HalpCatReportSMC();
+
+VOID HalEnableStatusChangeInterrupt (
+ IN ULONG
+ );
+
+BOOLEAN
+HalpTranslateSMCBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetMCAInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetSMCAInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+ULONG
+HalpNCRGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+HalpGetPosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+#define HalpAdjustMCAResourceList HalpAdjustEisaResourceList;
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+VOID HalpInitOtherBuses (VOID);
+
+ULONG NCRTranslateCMOSMask(ULONG);
+ULONG NCRTranslateToCMOSMask(ULONG);
+VOID NCRFindExtendedProcessors();
+VOID NCRMapIpiAddresses();
+
+VOID NCRAdjustDynamicClaims();
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#pragma alloc_text(INIT,NCRFixMemory)
+#pragma alloc_text(INIT,NCRLimitMemory)
+//#pragma alloc_text(INIT,NCRAdjustMemoryDescriptor)
+#pragma alloc_text(INIT,NCRVerifyMemoryRange)
+#pragma alloc_text(INIT,NCRSetupDiagnosticProcessor)
+#pragma alloc_text(INIT,NCRParseLoaderOptions)
+#pragma alloc_text(INIT,NCRGetValue)
+#pragma alloc_text(INIT,HalpFreeTiledCR3)
+#pragma alloc_text(INIT,HalpMapCR3)
+#pragma alloc_text(INIT,HalpBuildTiledCR3)
+#pragma alloc_text(INIT,HalpInitializeCatBusDriver)
+#pragma alloc_text(INIT,HalpDisableSingleBitErrorDET)
+#pragma alloc_text(INIT,HalpInitializeSUSInterface)
+#pragma alloc_text(INIT,HalpInitializeSMCInterface)
+#pragma alloc_text(INIT,HalpCatReportSystemModules)
+#pragma alloc_text(INIT,HalpCatReportSMC)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ PKPCR pPCR;
+ UCHAR Buffer[64];
+ UCHAR id;
+ PUCHAR PlatformStringPtr;
+ ULONG MyLogicalNumber;
+ ULONG MyLogicalMask;
+ BOOLEAN ConfiguredMp;
+ ULONG trans;
+ CAT_CONTROL cat_control;
+
+ pPCR = KeGetPcr();
+ MyLogicalNumber =
+ ((PProcessorPrivateData)pPCR->HalReserved)->MyLogicalNumber;
+
+ if (Phase == 0) {
+
+ //
+ // Register NCR machine IO space, so drivers don't try to
+ // use it
+ //
+
+ HalpRegisterAddressUsage (&HalpNCRIoSpace);
+
+ NCRParseLoaderOptions (LoaderBlock->LoadOptions);
+
+ /*
+ * only the boot processor sees phase zero.
+ */
+ if ((PlatformStringPtr = NCRDeterminePlatform(&ConfiguredMp)) == NULL) {
+ sprintf(Buffer, MSG_UNKOWN_NCR_PLATFORM, NCRPlatform);
+ HalDisplayString(Buffer);
+
+ /*
+ may not want to continue here, but for now let's
+ go on, assuming a UP machine
+ */
+
+ NCRExistingProcessorMask = 0x1;
+
+ } else {
+ sprintf(Buffer, MSG_NCR_PLATFORM, PlatformStringPtr);
+ HalDisplayString(Buffer);
+
+ HalpGetCmosData(1, 0x88A, (PUCHAR)&NCRExistingProcessorMask, 4);
+
+ trans = NCRTranslateCMOSMask(NCRExistingProcessorMask);
+ NCRExtendedProcessorMask = 0x0;
+
+ DBGMSG(("HalpInitMP: CMOS NCRExistingProcessorMask = 0x%x, translated = 0x%x\n",
+ NCRExistingProcessorMask,
+ trans));
+
+ NCRExistingProcessorMask = trans;
+
+
+ // additional stuff only if MSBU machine
+
+ if (NCRPlatform != NCR3360) {
+
+ KeInitializeSpinLock(&HalpCatBusLock);
+
+ /*
+ * This is to allow tweeking the memory descriptors.
+ */
+
+ NCRFixMemory(LoaderBlock);
+
+ /*
+ * This is to determine whether we ought to save COM1
+ * for the diagnostic processors use.
+ */
+ NCRSetupDiagnosticProcessor(LoaderBlock);
+
+ }
+
+ if (NCRPlatform == NCR3360) {
+ id = 1;
+ HalpSetCmosData(1, 0x41E, &id, 1);
+
+ if (NCRDebug & 0x04) {
+ NCR3360EnableNmiButton();
+ }
+ }
+
+ }
+
+
+
+ if (LimitMemory) {
+ NCRLimitMemory (LoaderBlock);
+ }
+
+ PageZeroVirtualPtr = HalpMapPhysicalMemory(0, 1);
+
+ if ((NCRExistingProcessorMask ^ NCRActiveProcessorMask) != 0) {
+ /*
+ * there are non-boot processors to bring up...
+ *
+ * allocate some space to put the non-boot processors
+ * startup code.
+ */
+ NonbootStartupPhysicalPtr =
+ (PVOID)HalpAllocPhysicalMemory(LoaderBlock,
+ (1*1024*1024),
+ 1, FALSE);
+ NonbootStartupVirtualPtr =
+ (PUCHAR)HalpMapPhysicalMemory(NonbootStartupPhysicalPtr,
+ 1);
+ }
+
+ if (NCRPlatform != NCR3360) {
+
+ HalpInitializeSUSInterface();
+
+ DBGMSG(("HalpInitMP: End of Phase 0, NCRExistingProcessorMask = 0x%x, NCRActiveProcessorMask = 0x%x\n",
+ NCRExistingProcessorMask,
+ NCRActiveProcessorMask));
+
+ NCRMapIpiAddresses(); // Map all QIC Ipi address
+ NCRFindIpiAddress(0); // lookup processor 0 Ipi address
+
+#ifdef NEVER
+ DBGMSG(("HalpInitMP: Lets break into the debug..\n"));
+ _asm {
+ int 3
+ }
+#endif // NEVER
+
+ } else {
+ NCRExistingDyadicProcessorMask = NCRExistingProcessorMask;
+ }
+
+
+
+ } else {
+ // Phase 1...
+
+ DBGMSG(("HalpInitMP: Start Phase %d for Proc %d\n", Phase, MyLogicalNumber));
+
+
+ /*
+ * set up idt for cpis
+ */
+ HalpEnableInterruptHandler (
+ InternalUsage, // Report as device vector
+ NCR_CPI_VECTOR_BASE + NCR_IPI_LEVEL_CPI,
+ NCR_CPI_VECTOR_BASE + NCR_IPI_LEVEL_CPI, // IDT
+ IPI_LEVEL, // System Irql
+ NCRVicIPIHandler, // ISR
+ LevelSensitive );
+
+
+ NCRSetHandlerAddressToIDT((NCR_QIC_CPI_VECTOR_BASE +
+ NCR_IPI_LEVEL_CPI),
+ NCRQicIPIHandler);
+
+
+ /*
+ * put the broadcast clock handler at the
+ * same irql as the clock. that way enabling
+ * the clock enables the broadcast.
+ */
+ HalpEnableInterruptHandler (
+ InternalUsage, // Report as device vector
+ NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI,
+ NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI, // IDT
+ CLOCK2_LEVEL, // System Irql
+ NCRClockBroadcastHandler, // ISR
+ LevelSensitive );
+
+ NCRSetHandlerAddressToIDT((NCR_QIC_CPI_VECTOR_BASE +
+ NCR_CLOCK_LEVEL_CPI),
+ NCRClockBroadcastHandler);
+
+ KiSetHandlerAddressToIDT(PROFILE_VECTOR,
+ NCRProfileHandler);
+
+ /*
+ * Set up handlers for sysints
+ */
+
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SYSTEM_INTERRUPT),
+ NCRSysIntHandler);
+
+ HalEnableSystemInterrupt((NCR_CPI_VECTOR_BASE +
+ NCR_SYSTEM_INTERRUPT),
+ (HIGH_LEVEL -
+ (NCR_SYSTEM_INTERRUPT & 0x7)),
+ LevelSensitive);
+
+ // due to a VIC errata, may get a bad vector (offset
+ // by 8) for a CPI when a sysint or sbe is active.
+ // Only CPIs 0 (NCR_IPI_LEVEL_CPI) and 2
+ // (NCR_CLOCK_LEVEL_CPI) are currently are used. Thus,
+ // need to handle CPIs 0/2 at CPI vectors 8/10 as
+ // well. Since CPI 10 is not used for anything else,
+ // it can be set identical to CPI 2. However, CPI 8
+ // is used by sysint. Thus, the handler for CPI 8
+ // needs to handle this case
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_CLOCK_LEVEL_CPI + 8),
+ NCRClockBroadcastHandler);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_9),
+ NCRVICErrataHandler1);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_9 + 8),
+ NCRVICErrataHandler1);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_11_3),
+ NCRVICErrataHandler3);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_11_3 + 8),
+ NCRVICErrataHandler3);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_12_4),
+ NCRVICErrataHandler4);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_12_4 + 8),
+ NCRVICErrataHandler4);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_13_5),
+ NCRVICErrataHandler5);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_13_5 + 8),
+ NCRVICErrataHandler5);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_14_6),
+ NCRVICErrataHandler6);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_14_6 + 8),
+ NCRVICErrataHandler6);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_15_7),
+ NCRVICErrataHandler7);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_15_7 + 8),
+ NCRVICErrataHandler15);
+
+ //
+ // Lets go ahead an enable the interrupt for single bit/status change.
+ // The following HalEnableSystemInterrupt call will enable the interrupt
+ // that will be serviced by NCRVICErrataHandler15. The reason we enable
+ // interrupt level 7 is because the single bit/status interrupt is on vector
+ // CPI+f and is a level 7 interrupt.
+ //
+
+ if (NCRPlatform != NCR3360) {
+
+ // This code was removed since enabled this vector
+ // also enables 0x37. (Microchanel IRQ 7). If there
+ // is a device connected to IRQ 7 which has an interrupt
+ // asserted, it could start sending interrupts as soon
+ // as ncr_single_bit_error is enabled - which is before
+ // the corrisponding driver could be loaded.
+
+ HalEnableSystemInterrupt((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_15_7),
+ (HIGH_LEVEL -
+ (NCR_SMCA_15_7 & 0x7)),
+ LevelSensitive);
+
+ }
+
+
+ //
+ // If this is a processor on the Quad board then we need to handle the
+ // Qic Spurious interrupt
+ //
+
+
+ MyLogicalMask = 0x1 << MyLogicalNumber;
+
+ if (MyLogicalMask & NCRLogicalQuadProcessorMask) {
+ NCRSetHandlerAddressToIDT(NCR_QIC_SPURIOUS_VECTOR, NCRQicSpuriousHandler);
+ }
+
+ if (MyLogicalNumber != 0) {
+ /*
+ * not the boot processor
+ */
+ HalpInitializeStallExecution((CCHAR)MyLogicalNumber);
+
+ /*
+ * Allow clock interrupts on all processors
+ */
+ HalEnableSystemInterrupt(CLOCK_VECTOR,
+ CLOCK2_LEVEL, LevelSensitive);
+
+ /*
+ * Allow profile interrupt on all processors
+ */
+ HalEnableSystemInterrupt(PROFILE_VECTOR,
+ PROFILE_LEVEL, LevelSensitive);
+
+ }
+
+ NCRLockedOr(&NCRActiveProcessorLogicalMask,
+ ((PProcessorPrivateData)pPCR->HalReserved)->MyLogicalMask);
+ }
+
+ return(TRUE);
+}
+
+NCRSetHandlerAddressToIDT (
+ IN ULONG IdtEntry,
+ IN VOID (*Handler)(VOID)
+ )
+{
+
+
+ HalpRegisterVector (InternalUsage, IdtEntry, IdtEntry, (HIGH_LEVEL - (IdtEntry & 0x7)));
+ KiSetHandlerAddressToIDT (IdtEntry, Handler);
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ MicroChannel // NCR's are MCA machines
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now online, check for any PCI buses to support
+ //
+
+ HalpInitializePciBus ();
+
+ if (NCRPlatform != NCR3360) {
+ HalpCatReportSystemModules();
+ if (NCRSegmentIoRegister != NULL) {
+ HalpCatReportSMC();
+ }
+ }
+}
+
+
+
+VOID
+NCRFixMemory (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Consult the firmware click map to determine what the memory
+ really looks like. Fix up the memory descriptors as necessary.
+
+ Note this function only adds memory which is in the clickmap
+ to NTs memory descriptors.
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG BPage, EPage, Temp;
+ PVOID ClickMapPage;
+ NCRClickMapEntry *BaseOfClickMap;
+ NCRClickMapEntry *ClickMapEntryPtr;
+ MEMORY_ALLOCATION_DESCRIPTOR TempDesc;
+
+ /*
+ * First get the physical address of the firmware's click map.
+ */
+ HalpGetCmosData(1, 0xA23, (PUCHAR)&BaseOfClickMap, 4);
+ if (BaseOfClickMap == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: No click map?!\n");
+#endif
+ return;
+ }
+
+ /*
+ * Now get a virtual address for the firmware's click map.
+ */
+ ClickMapPage = (PVOID)((ULONG)BaseOfClickMap & ~(PAGE_SIZE - 1));
+ ClickMapPage = HalpMapPhysicalMemory(ClickMapPage, 2);
+ if (ClickMapPage == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: Can't map in click map?!\n");
+#endif
+ return;
+ }
+
+ ClickMapEntryPtr = (NCRClickMapEntry *)((ULONG)ClickMapPage +
+ ((ULONG)BaseOfClickMap & (PAGE_SIZE - 1)));
+ BaseOfClickMap = ClickMapEntryPtr;
+
+
+ /*
+ * Run the firmware's click map and verify NT has some type of
+ * descriptor for all memory in the click map.
+ */
+
+ // The hal allocates various memory by just removing it from the memory
+ // map, we can't add that memory back in.
+
+ // make bogus descriptor for 0-16M
+ TempDesc.MemoryType = -1;
+ TempDesc.BasePage = 0;
+ TempDesc.PageCount = 0x1000;
+ InsertHeadList(&LoaderBlock->MemoryDescriptorListHead, &TempDesc.ListEntry);
+
+ for (ClickMapEntryPtr = BaseOfClickMap;
+ ((ClickMapEntryPtr < &BaseOfClickMap[ClickMapEntryCount]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+
+ BPage = ClickMapEntryPtr->StartingByte >> PAGE_SHIFT;
+ EPage = BPage + ClickMapEntryPtr->Pages;
+
+ NCRVerifyMemoryRange (BPage, EPage, LoaderBlock);
+ }
+
+ RemoveEntryList(&TempDesc.ListEntry);
+
+ /*
+ * Clear the mapping to the scratchpad. Not all of it is
+ * reinitialized on a warm reset and the data may get corrupted.
+ * We mapped in two pages.
+ */
+ Temp = (ULONG)MiGetPteAddress(ClickMapPage);
+ *(PULONG)Temp = 0;
+ *((PULONG)Temp+1) = 0;
+ /*
+ * Flush the TLB.
+ */
+ _asm {
+ mov eax, cr3
+ mov cr3, eax
+ }
+}
+
+VOID NCRVerifyMemoryRange (
+ IN ULONG StartPage,
+ IN ULONG EndPage,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Ensure there is an NT descriptor for this memory range. Any
+ part of the range which does not have a descriptor is added
+ as available memory.
+
+Arguments:
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG sp, ep;
+ PLIST_ENTRY NextListEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR Desc;
+
+ if (StartPage == EndPage) {
+ return ;
+ }
+
+ for (NextListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ NextListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ NextListEntry = NextListEntry->Flink) {
+
+ //
+ // Check each descriptor to see if it intersects with the range
+ // in question
+ //
+
+ Desc = CONTAINING_RECORD(NextListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ sp = Desc->BasePage;
+ ep = sp + Desc->PageCount;
+
+ if (sp < StartPage) {
+ if (ep > StartPage && ep < EndPage) {
+ // bump target area past this descriptor
+ StartPage = ep;
+ }
+
+ if (ep > EndPage) {
+ //
+ // Target area is contained totally within this
+ // descriptor. This range is fully accounted for.
+ //
+
+ StartPage = EndPage;
+ }
+
+ } else {
+ // sp >= StartPage
+
+ if (sp < EndPage) {
+ if (ep < EndPage) {
+ //
+ // This descriptor is totally within the target area -
+ // check the area on either side of this desctipor
+ //
+
+ NCRVerifyMemoryRange (StartPage, sp, LoaderBlock);
+ StartPage = ep;
+
+ } else {
+ // bump begining page of this descriptor
+ EndPage = sp;
+ }
+ }
+ }
+
+ //
+ // Anything left of target area?
+ //
+
+ if (StartPage == EndPage) {
+ return ;
+ }
+ } // next descrtiptor
+
+ //
+ // The range StartPage - EndPage is a missing range from NTs descriptor
+ // list. Add it as available memory.
+ //
+
+ if (NCRAddedDescriptorCount == NoExtraDescriptors) {
+ return ;
+ }
+
+ Desc = &NCRAdditionalMemoryDescriptors[NCRAddedDescriptorCount];
+ NCRAddedDescriptorCount += 1;
+
+ Desc->MemoryType = MemoryFree;
+ Desc->BasePage = StartPage;
+ Desc->PageCount = EndPage - StartPage;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &Desc->ListEntry);
+}
+
+
+
+#if 0
+VOID
+NCRFixMemory(LoaderBlockPtr)
+PLOADER_PARAMETER_BLOCK LoaderBlockPtr;
+/*++
+
+Routine Description:
+ Consult the firmware click map to determine what the memory
+ really looks like. Fix up the memory descriptors as necessary.
+
+ Note that we may remove memory descriptors due to the clickmap
+ disagreeing. However, we will only add memory descriptors to
+ the end as necessary. Therefore, in theory, it is possible to
+ have unused memory. But not likely.
+
+ New descriptors may be added due to holes in physical
+ memory caused by memory mapped adapters.
+ This means that firmware is expected to give the
+ loader (via BIOS int 15 function 88) the amount of contiguous
+ extended memory with the lowest addresses.
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG MaxDescriptorPage;
+ ULONG Temp;
+ ULONG StartingPage;
+ PLIST_ENTRY NextListEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptorPtr;
+ PMEMORY_ALLOCATION_DESCRIPTOR HighestMemoryDescriptor;
+ PMEMORY_ALLOCATION_DESCRIPTOR NextFreeMemoryDescriptor;
+ PVOID ClickMapPage;
+ NCRClickMapEntry *BaseOfClickMap;
+ NCRClickMapEntry *ClickMapEntryPtr;
+
+ /*
+ * First get the physical address of the firmware's click map.
+ */
+ HalpGetCmosData(1, 0xA23, (PUCHAR)&BaseOfClickMap, 4);
+ if (BaseOfClickMap == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: No click map?!\n");
+#endif
+ return;
+ }
+
+ /*
+ * Now get a virtual address for the firmware's click map.
+ */
+ ClickMapPage = (PVOID)((ULONG)BaseOfClickMap & ~(PAGE_SIZE - 1));
+ ClickMapPage = HalpMapPhysicalMemory(ClickMapPage, 2);
+ if (ClickMapPage == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: Can't map in click map?!\n");
+#endif
+ return;
+ }
+ ClickMapEntryPtr = (NCRClickMapEntry *)((ULONG)ClickMapPage +
+ ((ULONG)BaseOfClickMap & (PAGE_SIZE - 1)));
+ BaseOfClickMap = ClickMapEntryPtr;
+
+ /*
+ * the firmware guys say that contiguous memory
+ * will always be coalesced into one clickmap
+ * entry. we "trust but verify."
+ */
+ for (; ((ClickMapEntryPtr <
+ &BaseOfClickMap[ClickMapEntryCount-1]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+ Temp = ClickMapEntryPtr->StartingByte +
+ (ClickMapEntryPtr->Pages << PAGE_SHIFT);
+ while (((ClickMapEntryPtr+1)->Pages != 0) &&
+ ((ClickMapEntryPtr+1)->StartingByte <= Temp)) {
+ /*
+ * this should never happen...but if it does
+ * it's easily fixed
+ */
+ NCRClickMapEntry *NextClickMapEntryPtr;
+
+ DBGMSG(("NCRFixMemory: Fixing clickmap!?!\n"));
+
+ NextClickMapEntryPtr = ClickMapEntryPtr + 1;
+ /*
+ * note that this ending byte address is used
+ * to determine whether we iterate again.
+ */
+ Temp = NextClickMapEntryPtr->StartingByte +
+ (NextClickMapEntryPtr->Pages << PAGE_SHIFT);
+
+ if (Temp <= ClickMapEntryPtr->StartingByte) {
+ /*
+ * Whoa!!! this ain't so easy to fix.
+ * I'm not interested in sorting right now.
+ */
+ DbgBreakPoint();
+ }
+
+ /*
+ * here again, in theory, if the planets are really
+ * off their courses we could decrease the page
+ * count
+ */
+ ClickMapEntryPtr->Pages =
+ (Temp - ClickMapEntryPtr->StartingByte) >>
+ PAGE_SHIFT;
+
+ /*
+ * we just removed an entry...shift all subsequent
+ * entries down
+ */
+ for (++NextClickMapEntryPtr;
+ (NextClickMapEntryPtr <
+ &BaseOfClickMap[ClickMapEntryCount]);
+ ++NextClickMapEntryPtr) {
+ (NextClickMapEntryPtr-1)->StartingByte =
+ NextClickMapEntryPtr->StartingByte;
+ (NextClickMapEntryPtr-1)->Pages =
+ NextClickMapEntryPtr->Pages;
+ if (NextClickMapEntryPtr->Pages == 0) {
+ /*
+ * we just copied the sentinel
+ */
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * go through all the memory descriptor entries...
+ */
+ HighestMemoryDescriptor = NULL;
+ NextListEntry = LoaderBlockPtr->MemoryDescriptorListHead.Flink;
+ while (NextListEntry != &LoaderBlockPtr->MemoryDescriptorListHead) {
+ MemoryDescriptorPtr =
+ CONTAINING_RECORD(NextListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /*
+ * find clickmap entry that contains this memory descriptor
+ */
+ for (ClickMapEntryPtr = BaseOfClickMap;
+ ((ClickMapEntryPtr <
+ &BaseOfClickMap[ClickMapEntryCount]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+ StartingPage = ClickMapEntryPtr->StartingByte >>
+ PAGE_SHIFT;
+ Temp = StartingPage + ClickMapEntryPtr->Pages;
+ MaxDescriptorPage = MemoryDescriptorPtr->BasePage +
+ MemoryDescriptorPtr->PageCount;
+
+ if ((MemoryDescriptorPtr->BasePage >= StartingPage) &&
+ (MemoryDescriptorPtr->BasePage < Temp)) {
+ /*
+ * this memory descriptor starts in this
+ * clickmap entry...
+ */
+ if (MaxDescriptorPage > Temp) {
+ /*
+ * and goes beyond
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ ClickMapEntryPtr);
+ }
+ break;
+ }
+ if ((MaxDescriptorPage > StartingPage) &&
+ (MaxDescriptorPage <= Temp)) {
+ /*
+ * this memory descriptor ends in this
+ * clickmap entry...
+ */
+ if (MemoryDescriptorPtr->BasePage <
+ StartingPage) {
+ /*
+ * but starts before
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ ClickMapEntryPtr);
+ }
+ break;
+ }
+ if ((MemoryDescriptorPtr->BasePage < StartingPage) &&
+ (MaxDescriptorPage > Temp)) {
+ /*
+ * this memory descriptor is a superset of
+ * this clickmap entry
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ ClickMapEntryPtr);
+ break;
+ }
+ }
+
+ /*
+ * question...it's possible with the adjustments we did above
+ * to have a memory descriptor with zero pages. should we
+ * remove it too? i've seen other memory descriptors with
+ * zero pages. for now we don't remove them.
+ *
+ * Also the ClickMap doesn't contain any memory for regions
+ * between 640-1M, but the memory descriptor may. we leave
+ * those memory descriptors alone.
+ */
+ if ((ClickMapEntryPtr >= &BaseOfClickMap[ClickMapEntryCount] ||
+ ClickMapEntryPtr->Pages == 0) &&
+ (MemoryDescriptorPtr->BasePage < 0x9f ||
+ MemoryDescriptorPtr->BasePage+MemoryDescriptorPtr->PageCount > 0x100) ) {
+
+ /*
+ * no part of this memory descriptor was found to be
+ * contained within any clickmap entry...remove it
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ NULL);
+ /*
+ * a memory descriptor was removed. it's probably
+ * safest to just start over
+ */
+ NextListEntry =
+ LoaderBlockPtr->MemoryDescriptorListHead.Flink;
+ continue;
+ }
+
+ /*
+ * remember the entry for the memory range with the highest
+ * address
+ */
+ if ((HighestMemoryDescriptor == NULL) ||
+ (HighestMemoryDescriptor->BasePage <
+ MemoryDescriptorPtr->BasePage)) {
+ HighestMemoryDescriptor = MemoryDescriptorPtr;
+ }
+
+ NextListEntry = NextListEntry->Flink;
+ }
+
+ /*
+ * We depend on NextListEntry being the list head later.
+ */
+
+ MaxDescriptorPage = HighestMemoryDescriptor->BasePage +
+ HighestMemoryDescriptor->PageCount;
+
+ NextFreeMemoryDescriptor = NCRAdditionalMemoryDescriptors;
+ /*
+ * Go through firmware's click map and find the entry that contains
+ * the highest memory descriptor.
+ */
+ for (ClickMapEntryPtr = BaseOfClickMap;
+ ((ClickMapEntryPtr < &BaseOfClickMap[ClickMapEntryCount]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+ StartingPage = ClickMapEntryPtr->StartingByte >> PAGE_SHIFT;
+ Temp = StartingPage + ClickMapEntryPtr->Pages;
+ if (MaxDescriptorPage >= Temp) {
+ continue;
+ }
+
+ /*
+ * The click map has memory above the highest memory
+ * descriptor.
+ *
+ * We always add a new memory descriptor to the list.
+ */
+
+ NextFreeMemoryDescriptor->MemoryType = MemoryFree;
+ NextFreeMemoryDescriptor->BasePage = StartingPage;
+ NextFreeMemoryDescriptor->PageCount =
+ ClickMapEntryPtr->Pages;
+ if (MaxDescriptorPage > NextFreeMemoryDescriptor->BasePage) {
+ /*
+ * another descriptor already contains part of this
+ * clickmap entry...adjust the new descriptor so
+ * that it excludes the already accounted for memory.
+ * note that we should get into this condition
+ * at most once.
+ */
+ NextFreeMemoryDescriptor->PageCount -=
+ MaxDescriptorPage -
+ NextFreeMemoryDescriptor->BasePage;
+ NextFreeMemoryDescriptor->BasePage = MaxDescriptorPage;
+ }
+ InsertTailList(NextListEntry,
+ &NextFreeMemoryDescriptor->ListEntry);
+
+ /*
+ * This is the new highest memory descriptor.
+ */
+ HighestMemoryDescriptor = NextFreeMemoryDescriptor;
+ MaxDescriptorPage = HighestMemoryDescriptor->BasePage +
+ HighestMemoryDescriptor->PageCount;
+
+ /*
+ * We can never run out since the maximum was
+ * declared.
+ */
+ ++NextFreeMemoryDescriptor;
+ }
+
+ /*
+ * Clear the mapping to the scratchpad. Not all of it is
+ * reinitialized on a warm reset and the data may get corrupted.
+ * We mapped in two pages.
+ */
+ Temp = (ULONG)MiGetPteAddress(ClickMapPage);
+ *(PULONG)Temp = 0;
+ *((PULONG)Temp+1) = 0;
+ /*
+ * Flush the TLB.
+ */
+ _asm {
+ mov eax, cr3
+ mov cr3, eax
+ }
+}
+
+VOID
+NCRAdjustMemoryDescriptor(MemoryDescriptorPtr, ClickMapEntryPtr)
+PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptorPtr;
+NCRClickMapEntry *ClickMapEntryPtr;
+/*++
+
+Routine Description:
+ Make the memory descriptor fit into the clickmap entry
+
+Arguments:
+ Pointer to the memory descriptor
+
+ Pointer to the clickmap entry
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG Temp;
+ UCHAR Buffer[64];
+
+#if DBG
+ if ((NCRDebug & 0x2) &&
+ (MemoryDescriptorPtr->MemoryType != LoaderFree) &&
+ (MemoryDescriptorPtr->MemoryType != LoaderLoadedProgram) &&
+ (MemoryDescriptorPtr->MemoryType != MemoryFirmwareTemporary) &&
+ (MemoryDescriptorPtr->MemoryType != MemoryFirmwarePermanent) &&
+ (MemoryDescriptorPtr->MemoryType != LoaderOsloaderStack)) {
+ /*
+ * looks like it's already been allocated to
+ * to something other than available
+ */
+ DbgBreakPoint();
+ }
+#endif
+
+ sprintf(Buffer,
+ "MD: Type: %d; BasePage: 0x%08X; PageCount: 0x%X\n",
+ MemoryDescriptorPtr->MemoryType,
+ MemoryDescriptorPtr->BasePage,
+ MemoryDescriptorPtr->PageCount);
+ DBGMSG((Buffer));
+
+ if (ClickMapEntryPtr == NULL) {
+ /*
+ * remove the entry from the list
+ */
+ RemoveEntryList(&MemoryDescriptorPtr->ListEntry);
+ return;
+ }
+
+ sprintf(Buffer,
+ "CM: StartingByte: 0x%08X; Pages: 0x%X\n",
+ ClickMapEntryPtr->StartingByte,
+ ClickMapEntryPtr->Pages);
+ DBGMSG((Buffer));
+
+ Temp = ClickMapEntryPtr->StartingByte >> PAGE_SHIFT;
+ if (MemoryDescriptorPtr->BasePage < Temp) {
+ /*
+ * the memory descriptor starts before the clickmap
+ * entry.
+ */
+ MemoryDescriptorPtr->PageCount -=
+ Temp - MemoryDescriptorPtr->BasePage;
+ MemoryDescriptorPtr->BasePage = Temp;
+ }
+
+ Temp += ClickMapEntryPtr->Pages;
+ if ((MemoryDescriptorPtr->BasePage +
+ MemoryDescriptorPtr->PageCount) > Temp) {
+ /*
+ * the memory descriptor ends after the clickmap
+ * entry.
+ */
+ MemoryDescriptorPtr->PageCount =
+ Temp - MemoryDescriptorPtr->BasePage;
+ }
+}
+
+#endif
+
+VOID
+NCRLimitMemory(LoaderBlockPtr)
+PLOADER_PARAMETER_BLOCK LoaderBlockPtr;
+/*++
+
+Routine Description:
+ For performance work the machine can be booted to only
+ use some of the memory in the machine with the /MAXMEM setting.
+
+ Here we will go through the memory list and remove and free memory
+ above the LimitMemory address
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG LimitPage;
+ PLIST_ENTRY NextListEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemDesc;
+
+ //
+ // Calculate highest page address
+ //
+
+ LimitPage = LimitMemory * 1024 * 1024 / PAGE_SIZE;
+
+ //
+ // Walk memory descritpor list looking for any pages above LimitPage
+ //
+
+ NextListEntry = LoaderBlockPtr->MemoryDescriptorListHead.Flink;
+ while (NextListEntry != &LoaderBlockPtr->MemoryDescriptorListHead) {
+ MemDesc = CONTAINING_RECORD(NextListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ NextListEntry = NextListEntry->Flink;
+
+ if (MemDesc->BasePage + MemDesc->PageCount > LimitPage) {
+ //
+ // For memory descriptor which extends above LimitPage
+ // Either remove the memory descriptor from the system, or
+ // shrink it.
+ //
+
+ if (MemDesc->MemoryType != MemoryFree) {
+ DBGMSG(("NCRLimitMemory: non free memory region not freed"));
+ continue;
+ }
+
+ if (MemDesc->BasePage > LimitPage) {
+ RemoveEntryList(&MemDesc->ListEntry);
+ } else {
+ MemDesc->PageCount = MemDesc->BasePage + MemDesc->PageCount - LimitPage;
+ }
+ }
+ }
+}
+
+
+VOID
+NCRSetupDiagnosticProcessor(LoaderBlockPtr)
+PLOADER_PARAMETER_BLOCK LoaderBlockPtr;
+/*++
+
+Routine Description:
+ Determine whether the diagnostic processor is using COM1. If so,
+ make sure that the serial driver leaves COM1 alone.
+
+ Note that the interface used will have to be changed to use
+ the registry when the serial driver makes the switch.
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ extern PUCHAR KdComPortInUse;
+
+ UCHAR FirmwareFlags;
+
+ HalpGetCmosData(1, 0x7803, (PUCHAR)&FirmwareFlags, 1);
+ if ((FirmwareFlags & 0x80) == 0) {
+ /*
+ * Kernel debug not set.
+ */
+ return;
+ }
+
+ if (KdComPortInUse == (PUCHAR)COM1_PORT) {
+ /*
+ * The debugger is using COM1.
+ */
+ return;
+ }
+
+ HalDisplayString(MSG_DIAG_ENABLED);
+ UNREFERENCED_PARAMETER(LoaderBlockPtr);
+}
+
+VOID
+NCRParseLoaderOptions (PUCHAR Options)
+{
+ ULONG l;
+
+ if (Options == NULL)
+ return;
+
+ NCRGetValue (Options, "NCRDEBUG", &NCRDebug);
+
+ NCRGetValue (Options, "MAXMEM", &LimitMemory);
+
+ if (NCRGetValue (Options, "PROCESSORS", &l)) {
+ if (l >= 1 && l <= NCR_MAX_NUMBER_QUAD_PROCESSORS)
+ NCRMaxProcessorCount = l;
+ }
+
+ if (NCRGetValue (Options, "NEVERCLAIM", &l)) {
+ DefaultNeverClaimIRQs = l;
+ }
+
+ if (NCRGetValue (Options, "LARCPAGEMASK", &l)) {
+ NCRLarcPageMask = l;
+ }
+}
+
+
+BOOLEAN
+NCRGetValue (PUCHAR Options, PUCHAR String, PULONG Value)
+{
+ PUCHAR p, s, t;
+
+ // strstr (Options, String);
+ for (p=Options; *p; p++) {
+ for (s=String, t=p; *t == *s; s++, t++) {
+ if (*s == 0)
+ break;
+ }
+
+ if (*s == 0)
+ break;
+ }
+
+ if (*p == 0) {
+ return FALSE;
+ }
+
+
+ for (p += strlen (String); *p && (*p < '0' || *p > '9'); p++) ;
+
+ // atol (p)
+ for (*Value = 0L; *p >= '0' && *p <= '9'; p++) {
+ *Value = *Value * 10 + *p - '0';
+ }
+
+ return TRUE;
+}
+
+
+
+#define MAX_PT 8
+
+extern StartPx_PMStub();
+
+
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) NonbootStartupPhysicalPtr,
+ NonbootStartupPhysicalPtr,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+
+
+
+ULONG
+HalpNCRGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ SystemVector = BusInterruptVector + PRIMARY_VECTOR_BASE;
+
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = (KIRQL)(HIGHEST_LEVEL_FOR_8259 - BusInterruptLevel);
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+
+ return SystemVector;
+}
+
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ PBUS_HANDLER InternalBus;
+ PBUS_HANDLER McaBus;
+ PBUS_HANDLER Bus;
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ LONG status;
+
+
+ if (NCRPlatform != NCR3360) {
+ HalpInitializeCatBusDriver();
+ HalpDisableSingleBitErrorDET();
+ HalpInitializeSMCInterface();
+ NCRFindExtendedProcessors();
+ if ((NCRDebug & 0x20) == 1) {
+ HalpInitializeLarc();
+ }
+
+
+//
+// Turn off cache ownership it NCRDebug bit is set and you only have one Quad board installed
+// in slot 1
+//
+
+ if ((NCRDebug & 0x10) && (NCRExistingProcessorMask == 0xf)) {
+
+ DBGMSG(("HalpInitOtherBuses: Changing QCC Asic on Quad\n"));
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC0 A0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC0 B0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC1 A0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC1 B0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+
+ cat_control.Module = QUAD_BB0;
+ cat_control.Asic = QABC;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0xb;
+ status = HalCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QABC Nbus Config read 0x%x\n", data));
+
+ data |= 0x10;
+
+ cat_control.Module = QUAD_BB0;
+ cat_control.Asic = QABC;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0xb;
+ status = HalCatBusIo(&cat_control,&data);
+ }
+
+
+ InternalBus = HalpHandlerForBus( Internal, 0);
+ InternalBus->GetInterruptVector = HalpNCRGetSystemInterruptVector;
+
+ //
+ // Change MCA bus #0
+ //
+
+ McaBus = HalpHandlerForBus( MicroChannel, 0);
+ McaBus->GetInterruptVector = HalpGetMCAInterruptVector;
+
+
+ //
+ // Build MCA bus #1 if present
+ //
+
+ if (NCRSegmentIoRegister != NULL) {
+ Bus = HalpAllocateBusHandler (MicroChannel, Pos, 1, Internal, 0, 0);
+ Bus->GetBusData = HalpGetPosData;
+ Bus->GetInterruptVector = HalpGetSMCAInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSMCBusAddress;
+ Bus->AdjustResourceList = HalpAdjustMCAResourceList;
+ }
+ }
+}
+
+
+
+VOID
+HalpDisableSingleBitErrorDET (
+
+ )
+/*++
+
+Routine Description:
+ Disable Single Bit Error Reporting
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ LONG status;
+
+//
+// Disable single bit error interrupt MMC on memory board 0
+//
+
+ cat_control.Module = MEMORY0;
+ cat_control.Asic = MMC1;
+
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = READ_REGISTER;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ if (status == CATNOERR) {
+//
+// disable reporting via mem_error_int
+// correction still enabled
+//
+ data |= MMC1_SBErr_DetectDisable;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = WRITE_REGISTER;
+ HalpCatBusIo(&cat_control,&data);
+ }
+
+
+//
+// Disable single bit error interrupt MMC on memory board 1
+//
+
+ cat_control.Module = MEMORY1;
+ cat_control.Asic = MMC1;
+
+
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = READ_REGISTER;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ if (status == CATNOERR) {
+//
+// disable reporting via mem_error_int
+// correction still enabled
+//
+ data |= MMC1_SBErr_DetectDisable;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = WRITE_REGISTER;
+ HalpCatBusIo(&cat_control,&data);
+ }
+
+}
+
+
+VOID
+HalpInitializeSMCInterface (
+
+ )
+/*++
+
+Routine Description:
+ Check for SMC board and it present setup segment register.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ LONG status;
+ PHYSICAL_ADDRESS physical_address;
+ PUCHAR mapped_segment_address;
+
+ cat_control.Module = SECONDARYMC;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ if (status != CATNOMOD) {
+
+/*
+ * SMC is installed in this unit
+ */
+ DBGMSG(("HalpInitializeSMCInterface: SMC has been detected...\n"));
+
+ physical_address.HighPart = 0;
+ physical_address.LowPart = NCRSegmentIoAddress;
+
+ mapped_segment_address = (PUCHAR) MmMapIoSpace(physical_address, sizeof(UCHAR), FALSE);
+
+ if (mapped_segment_address != NULL) {
+ NCRSegmentIoRegister = mapped_segment_address;
+ }
+
+/*RMU temp fix for arb control register on DMA asic. */
+
+ WRITE_PORT_UCHAR((PUCHAR)0x10090, (UCHAR)0x8f);
+ }
+}
+
+
+
+
+
+
+VOID
+HalpCatReportSMC (
+ )
+
+/*++
+
+Routine Description:
+ Place information about system modules into the registry.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PMODULE module;
+ PASIC asic;
+
+ PWSTR smc_path = L"\\Registry\\Machine\\Hardware\\DESCRIPTION\\System\\MultifunctionAdapter\\1";
+
+
+ UNICODE_STRING unicode_smc;
+ OBJECT_ATTRIBUTES smc_attributes;
+ HANDLE smc_handle;
+
+
+ UNICODE_STRING unicode_name;
+
+ UNICODE_STRING unicode_mca;
+
+ NTSTATUS status;
+ ULONG tmp;
+
+ CONFIGURATION_COMPONENT component;
+
+ ULONG ConfigurationDataLength;
+ SMC_RESOURCES SmcConfig;
+ int i;
+
+
+/*
+ *
+ */
+ RtlInitUnicodeString(&unicode_smc,smc_path);
+
+ InitializeObjectAttributes( &smc_attributes, &unicode_smc,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&smc_handle, KEY_READ | KEY_WRITE, &smc_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+
+
+ RtlInitUnicodeString(&unicode_name,L"Component Information");
+ RtlZeroMemory (&component, sizeof(CONFIGURATION_COMPONENT));
+ component.AffinityMask = 0xffffffff;
+
+ status = ZwSetValueKey(
+ smc_handle,
+ &unicode_name,
+ 0,
+ REG_BINARY,
+ &component.Flags,
+ FIELD_OFFSET(CONFIGURATION_COMPONENT, ConfigurationDataLength) -
+ FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)
+ );
+
+
+ RtlInitUnicodeString(&unicode_name,L"Configuration Data");
+ RtlZeroMemory (&SmcConfig, sizeof(SMC_RESOURCES));
+
+ ConfigurationDataLength = sizeof(SMC_RESOURCES);
+
+ //
+ // Set up InterfaceType and BusNumber for the component.
+ //
+
+ SmcConfig.ConfigurationData.InterfaceType = MicroChannel;
+ SmcConfig.ConfigurationData.BusNumber = 1;
+ SmcConfig.ConfigurationData.PartialResourceList.Count = 1;
+
+ SmcConfig.ConfigurationData.PartialResourceList.PartialDescriptors[0].Type =
+ CmResourceTypeDeviceSpecific;
+
+ SmcConfig.ConfigurationData.PartialResourceList.PartialDescriptors[0].ShareDisposition =
+ CmResourceShareUndetermined;
+
+ SmcConfig.ConfigurationData.PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
+ sizeof(CM_MCA_POS_DATA)*10;
+
+ for (i = 0; i < 8; i++) {
+ HalGetBusData(Pos, 1, i, &SmcConfig.PosData[i], sizeof(CM_MCA_POS_DATA));
+ }
+
+
+ //
+ // Write the newly constructed configuration data to the hardware registry
+ //
+
+ status = ZwSetValueKey(
+ smc_handle,
+ &unicode_name,
+ 0,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ &SmcConfig,
+ ConfigurationDataLength
+ );
+
+
+
+ RtlInitUnicodeString(&unicode_name,L"Identifier");
+ RtlInitUnicodeString(&unicode_mca,L"MCA");
+ status = ZwSetValueKey(smc_handle, &unicode_name, 0, REG_SZ,
+ unicode_mca.Buffer,
+ unicode_mca.Length + sizeof(UNICODE_NULL));
+
+ status = ZwClose(smc_handle);
+
+}
+
+
+
+
+VOID
+HalSetStatusChangeInterruptState(
+ ULONG State
+ )
+
+/*++
+
+Routine Description:
+ This HAL function will enable or disable the revectoring of the
+ Status Change Interrupt to vector 57.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ if (State) {
+ NCRStatusChangeInterruptEnabled = 0x1;
+ } else {
+ NCRStatusChangeInterruptEnabled = 0x0;
+ }
+
+}
+
+
+
+
+ULONG
+NCRTranslateCMOSMask(
+ ULONG CmosMask
+ )
+
+/*++
+
+Routine Description:
+ This function translates the CMOS processor Mask into what we want to use.
+ This function must change for 32 way
+
+ CMOS format is: each nibble contains all processors 0 in the system where each bit
+ position denotes the processor slot. Therefore a system with
+ one Quad board has a mask of (0x1111), 2 Quad boards has a
+ mask of (0x3333), 3 Quad boards has a mask of (0x7777), and
+ 4 Quad boards has a mask of (0xffff).
+
+ Our format is: each nibble contains all processors on one Quad board where each
+ bit position denotes the processor on one board. Therefore a
+ system with one Quad board has a mask of (0x000f), 2 Quad boards
+ has a mask of (0x00ff), 3 Quad boards has a mask of (0x0ffff), and
+ 4 Quad boards has a mask of (xffff);
+
+Arguments:
+
+Return Value:
+ The Processor Mask that the Hal wants to use for bringing up the system.
+
+
+--*/
+
+{
+ ULONG working_mask = CmosMask;
+ ULONG existing_mask = 0x0;
+ int i, j;
+
+ // loop thru each processor number
+
+ for (i = 0; i < 4; i++ ) {
+
+ // loop thru each processor slot
+
+ for (j = 0; j < 4; j++) {
+ if (working_mask & 0x1) {
+ existing_mask |= ((1 << i) << (j<<2));
+ }
+ working_mask >>= 1;
+ }
+ }
+
+ return existing_mask;
+}
+
+
+ULONG
+NCRTranslateToCMOSMask(
+ ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+ Do the oppsite of NCRTranslateCMOSMask()
+
+Arguments:
+
+Return Value:
+ The Processor Mask that CMOS uses.
+
+
+--*/
+
+{
+ ULONG working_mask = Mask;
+ ULONG cmos_mask = 0x0;
+ int i;
+
+ for (i = 0; i < 4; i++ ) {
+
+ if (working_mask & 1) {
+ cmos_mask |= (0x1 << i);
+ }
+
+ if (working_mask & 2) {
+ cmos_mask |= (0x10 << i);
+ }
+ working_mask >>= 4;
+ }
+ return cmos_mask;
+}
+
+
+VOID
+NCRFindExtendedProcessors(
+ )
+/*++
+
+Routine Description:
+ Loop over the CAT bus and find all extended processors
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ UCHAR qabc_ext;
+ LONG status;
+ UCHAR module;
+ int slot;
+
+
+ for(slot = 0; slot < 4; slot++) {
+
+ switch (slot) {
+ case 0:
+ module = QUAD_BB0;
+ break;
+ case 1:
+ module = QUAD_BB1;
+ break;
+ case 2:
+ module = QUAD_BB2;
+ break;
+ case 3:
+ module = QUAD_BB3;
+ break;
+ }
+ cat_control.Module = module;
+ cat_control.Asic = QABC;
+ cat_control.Command = READ_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x8;
+ status = HalpCatBusIo(&cat_control,&qabc_ext);
+
+ if (status == CATNOERR) {
+// NCRExtendedProcessor0Mask |= (qabc_ext & 0xf) << (qabc_ext << 2);
+ NCRExtendedProcessor0Mask |= (qabc_ext & 0xf) << (slot << 2);
+ NCRExtendedProcessor1Mask |= (qabc_ext >> 4) << (slot << 2);
+ }
+ }
+ NCRExtendedProcessorMask = NCRExtendedProcessor0Mask | NCRExtendedProcessor1Mask;
+
+ DBGMSG(("NCRFindExtendedProcessors: Extended 0 = 0x%x, 1 = 0x%x\n",
+ NCRExtendedProcessor0Mask, NCRExtendedProcessor1Mask));
+}
+
+
+
+
+
+
+
+
+VOID
+NCRAdjustDynamicClaims(
+ )
+/*++
+
+Routine Description:
+ Determine how man interrupts a processor should claim. This is called when
+ processors are enabled and with interrups are enabled and disabled
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ ULONG processors = 0;
+ ULONG max_claimable_irqs = 0;
+ ULONG processor;
+ ULONG irq_count;
+ ULONG mask;
+
+ //
+ // Count the number of processors that can take device interrupts.
+ //
+
+ for (mask = HalpDefaultInterruptAffinity; mask != 0; mask >>= 1) {
+ if (mask & 0x1) {
+ processors++;
+ }
+ }
+
+ for (processor = 0; processor < NCRActiveProcessorCount; processor++) {
+
+ mask = NCRProcessorIDR[processor];
+ mask |= NCRNeverClaimIRQs; // do not count never claim IRQs
+
+ irq_count = 0;
+
+ for (mask = ~mask; (mask != 0); mask >>= 1) {
+ if (mask & 0x1) {
+ irq_count++;
+ }
+ }
+ if (irq_count > max_claimable_irqs) {
+ max_claimable_irqs = irq_count;
+ }
+ }
+
+ if ((max_claimable_irqs % processors) == 0) {
+ max_claimable_irqs /= processors;
+ } else {
+ max_claimable_irqs /= processors;
+ max_claimable_irqs++;
+ }
+ if (max_claimable_irqs == 0) {
+ max_claimable_irqs = 1;
+ }
+ NCRMaxIRQsToClaim = max_claimable_irqs;
+}
+
+
+#ifdef DBG
+
+
+VOID
+NCRConsoleDebug(
+ ULONG MsgNumber,
+ ULONG Data
+ )
+
+{
+ CHAR buffer[256];
+
+ switch (MsgNumber) {
+
+ case 1:
+ sprintf(buffer, "HalInitializeProcessor called for processor %d\n", Data);
+ HalDisplayString(buffer);
+ break;
+ case 2:
+ sprintf(buffer, "HalStartNextProcessor trying to wakeup 0x%x\n", Data);
+ HalDisplayString(buffer);
+ break;
+ case 3:
+ sprintf(buffer, "HalStartNextProcessor Processor is now awake\n", Data);
+ HalDisplayString(buffer);
+ break;
+
+
+
+ }
+}
+
+#endif
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halncr/i386/ncrnls.h b/private/ntos/nthals/halncr/i386/ncrnls.h
new file mode 100644
index 000000000..17d4646df
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrnls.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ ncrnls.h
+
+Abstract:
+
+ Strings which are used in the HAL
+
+ English
+
+--*/
+
+#define MSG_NCR_PLATFORM "NCR platform: %s\n"
+#define MSG_UNKOWN_NCR_PLATFORM "HAL: 0x%08X: Unrecognized NCR platform\n"
+#define MSG_HARDWARE_ERROR3 "Call your NCR hardware vendor for support\n\n"
+#define MSG_DIAG_ENABLED "Diagnostic processor using COM1\n"
+
+#define MSG_GLOBAL_NMI "Global NMI"
+#define MSG_SHUTDOWN_OCCURRED "Shutdown occurred"
+#define MSG_LOCAL_EXTERNAL_ERROR "Local extern error"
+#define MSG_SB_READ_DATA_PARITY_ERROR "SB Read Data Parity Error"
+#define MSG_SB_ERROR_L_TERMINATION "SB ERROR_L Termination"
+#define MSG_P5_INTERNAL_ERROR "P5 internal error"
+#define MSG_PROCESSOR_HALTED "Processor halted"
+
+#define MSG_SB_ADDRESS_PARITY_ERROR "SB Address parity error"
+#define MSG_SB_DATA_PARITY_ERROR "SB data parity error"
+#define MSG_SHUTDOWN_ERROR_INT_L "Shutdown ERR_INT_L"
+#define MSG_EXTERNAL_ERROR_INT_L "External error ERR_INT_L"
+#define MSG_P_IERR_L_ERROR_INT_L "P_IERR_L error ERR_INT_L"
+
+#define MSG_VDLC_DATA_ERROR "VDLC data error"
+#define MSG_LST_ERROR "LST error"
+#define MSG_BUS_A_DATA_PARITY_ERROR "Bus A data parity error"
+#define MSG_BUS_B_DATA_PARITY_ERROR "Bus B data parity error"
+#define MSG_LST_UNCORRECTABLE_ERROR "LST uncorrectable error"
+
+#define MSG_MC_MASTER_ERROR "MC master error"
+#define MSG_SA_MASTER_ERROR "SA master error"
+#define MSG_SB_MASTER_ERROR "SB master error"
+#define MSG_MC_TOE_ERROR "MC TOE error"
+#define MSG_ASYNC_ERROR "ASYNC error"
+#define MSG_SYNC_ERROR "SYNC error"
+#define MSG_REFRESH_ERROR "Refresh error"
+#define MSG_SXERROR_L "SxERROR_L error"
+
+#define MSG_FRED "FRED %x: Error Enables = %p Nmi Enables = %p\n"
+#define MSG_A_PARITY "PORT A address parity: %A BIOE = %s. Data parity %A MISC = %s\n"
+#define MSG_B_PARITY "PORT B address parity: %A BIOE = %s. Data parity %A MISC = %s\n"
+#define MSG_A_TOE "PORT A TOE address: %A ID/BOP = %s\n"
+#define MSG_B_TOE "PORT B TOE address: %A ID/BOP = %s\n"
+#define MSG_A_GOOD "%1Bus A good address: %A Status = %s\n"
+#define MSG_B_GOOD "%1Bus B good address: %A Status = %s\n"
+#define MSG_A_LAST "%1Bus A last address: %A\n"
+#define MSG_B_LAST "%1Bus B last address: %A\n"
+#define MSG_MC_ADDRESS "%1MC error address: %A Status = %s\n"
+#define MSG_MC_TIMEOUT "MC timeout error: Status = %s\n"
+#define MSG_MC_PARITY "%1MC address parity error. Status = %s\n"
diff --git a/private/ntos/nthals/halncr/i386/ncrnmi.c b/private/ntos/nthals/halncr/i386/ncrnmi.c
new file mode 100644
index 000000000..097142365
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrnmi.c
@@ -0,0 +1,422 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ncrnmi.c
+
+Abstract:
+
+ Provides ncr x86 NMI handler
+
+Author:
+
+ kenr
+
+Revision History:
+
+--*/
+#include "halp.h"
+#include "bugcodes.h"
+#include "ncr.h"
+#include "ncrnls.h"
+
+#define SYSTEM_CONTROL_PORT_A 0x92
+#define SYSTEM_CONTROL_PORT_B 0x61
+#define EISA_EXTENDED_NMI_STATUS 0x461
+
+extern ULONG NCRPlatform;
+
+VOID HalpDumpAsicPorts (UCHAR *p, ULONG arg, ...);
+VOID HalpDumpBitsField (UCHAR bits, char *BitMsgs[]);
+VOID HexSubPort (PUCHAR *o, ULONG l);
+VOID HalpDumpFred (UCHAR FredId);
+VOID HalpDumpVMC (UCHAR VMCId);
+VOID HalpDumpMCADDR (UCHAR MCADDRId);
+VOID HalpDumpArbiter (UCHAR ArbiterId);
+
+BOOLEAN HalpSUSSwNmi();
+
+ULONG NmiLock;
+UCHAR HexString[] = "0123456789ABCDEF";
+
+char *NmiStatusRegisterBits[] = {
+ MSG_GLOBAL_NMI, // 0
+ MSG_SHUTDOWN_OCCURRED, // 1
+ MSG_LOCAL_EXTERNAL_ERROR, // 2
+ MSG_SB_READ_DATA_PARITY_ERROR, // 3
+ MSG_SB_ERROR_L_TERMINATION, // 4
+ MSG_P5_INTERNAL_ERROR, // 5
+ NULL, // 6
+ MSG_PROCESSOR_HALTED // 7
+};
+
+char *ParityErrorIntStatusBits[] = {
+ MSG_SB_ADDRESS_PARITY_ERROR, // 0
+ MSG_SB_DATA_PARITY_ERROR, // 1
+ NULL, // 2
+ NULL, // 3
+ NULL, // 4
+ MSG_SHUTDOWN_ERROR_INT_L, // 5
+ MSG_EXTERNAL_ERROR_INT_L, // 6
+ MSG_P_IERR_L_ERROR_INT_L // 7
+};
+
+char *VMCErrorStatusZeroBits[] = {
+ MSG_VDLC_DATA_ERROR, // 0
+ MSG_LST_ERROR, // 1
+ MSG_BUS_A_DATA_PARITY_ERROR, // 2
+ MSG_BUS_B_DATA_PARITY_ERROR, // 3
+ MSG_LST_UNCORRECTABLE_ERROR, // 4
+ NULL, // 5
+ NULL, // 6
+ NULL // 7
+};
+
+char *SBErrorIntStatusBits[] = {
+ MSG_MC_MASTER_ERROR, // 0
+ MSG_SA_MASTER_ERROR, // 1
+ MSG_SA_MASTER_ERROR, // 2
+ MSG_MC_TOE_ERROR, // 3
+ MSG_ASYNC_ERROR, // 4
+ MSG_SYNC_ERROR, // 5
+ MSG_REFRESH_ERROR, // 6
+ MSG_SXERROR_L // 7
+};
+
+char *InterruptStatusOneBits[] = {
+ "PAR_INT_B", // 0
+ "PAR_INT_A", // 1
+ "ELATCHD_B", // 2
+ "ELATCHD_A", // 3
+ "TOE_B", // 4
+ "TOE_A", // 5
+ "PROTO_ERR_B", // 6
+ "PROTO_ERR_A" // 7
+};
+
+char *InterruptStatusTwoBits[] = {
+ "MC_TOE", // 0
+ "COUGAR_NMI", // 1
+ "EXP_MC_TOE", // 2
+ "EXP_COUGAR_NMI", // 3
+ "POWER_FAIL", // 4
+ "ERROR_INT", // 5
+ "SW_NMI", // 6
+ NULL // 7
+};
+
+VOID
+HalHandleNMI(
+ IN OUT PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ Called DURING an NMI. The system will BugCheck when an NMI occurs.
+ This function can return the proper bugcheck code, bugcheck itself,
+ or return success which will cause the system to iret from the nmi.
+
+ This function is called during an NMI - no system services are available.
+ In addition, you don't want to touch any spinlock which is normally
+ used since we may have been interrupted while owning it, etc, etc...
+
+Warnings:
+
+ Do NOT:
+ Make any system calls
+ Attempt to acquire any spinlock used by any code outside the NMI handler
+ Change the interrupt state. Do not execute any IRET inside this code
+
+ Passing data to non-NMI code must be done using manual interlocked
+ functions. (xchg instructions).
+
+Arguments:
+
+ NmiInfo - Pointer to NMI information structure (TBD)
+ - NULL means no NMI information structure was passed
+
+Return Value:
+
+ BugCheck code
+
+--*/
+{
+ UCHAR StatusByte;
+
+ _asm {
+nmi00:
+ lock bts NmiLock, 0
+ jnc nmilocked
+
+nmi10:
+ test NmiLock, 1
+ jnz short nmi10
+ jmp short nmi00
+nmilocked:
+ }
+
+ if (NmiLock & 2) {
+ // some other processor has already processed the Nmi and
+ // determined that the machine should crash - just stop
+ // this processor
+
+
+
+ NmiLock = 2; // free busy bit
+ KeEnterKernelDebugger ();
+ return;
+ }
+
+
+ if (NCRPlatform != NCR3360) {
+
+//
+// If is this is the Dump switch
+//
+ if (HalpSUSSwNmi() == TRUE) {
+ NmiLock = 2;
+ KeEnterKernelDebugger();
+ return;
+ }
+ }
+
+ HalDisplayString (MSG_HARDWARE_ERROR1);
+ HalDisplayString (MSG_HARDWARE_ERROR3);
+
+ StatusByte = READ_PORT_UCHAR((PUCHAR) SYSTEM_CONTROL_PORT_B);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_PARITY);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_CHANNEL_CHECK);
+ }
+
+ if (NCRPlatform == NCR3360) {
+ HalpDumpFred (0x41); // fred 1
+ HalpDumpFred (0x61); // fred 2
+
+ HalpDumpVMC (0x81); // memory 1
+ HalpDumpVMC (0x91); // memory 2
+
+ HalpDumpArbiter (0xC1); // arbiter
+ HalpDumpMCADDR (0xC0); // mcaddr
+ } else {
+//
+// For 3450 and 3550 let SUS go do FRU analysis and log the error to SUS
+// error log. After SUS logs the error the system will reboot and the
+// HwMon service will copy the SUS error log to the NT error log.
+//
+
+ HalDisplayString ("NMI: 345x/35xx SUS Logging Error\n");
+ HalpSUSLogError();
+ }
+
+ HalDisplayString (MSG_HALT);
+ NmiLock = 2;
+ KeEnterKernelDebugger ();
+}
+
+
+VOID HalpDumpFred (UCHAR FredId)
+{
+ UCHAR c;
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0x97, FredId);
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf801);
+ if (c & 0xf0 != 0x20) {
+ return ;
+ }
+
+ HalpDumpAsicPorts (MSG_FRED, FredId, 0xf808, 0xf80d);
+
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf809);
+ HalpDumpBitsField (c, NmiStatusRegisterBits);
+
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf80b);
+ HalpDumpBitsField (c, ParityErrorIntStatusBits);
+ HalDisplayString("\n");
+}
+
+VOID HalpDumpVMC (UCHAR VMCId)
+{
+ UCHAR c;
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0x97, VMCId);
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf800);
+ if (c != 0x81 && c != VMCId) {
+ return ;
+ }
+
+ HalpDumpAsicPorts ("VMC %x: S0 = %p S1 = %p S2 = %p BD/D = %p\n",
+ VMCId, 0xf804, 0xf808, 0xf809, 0xf80a);
+
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf80d);
+ HalpDumpBitsField (c, VMCErrorStatusZeroBits);
+
+ if (c & 0x04) {
+ HalpDumpAsicPorts (MSG_A_PARITY, 0x13, 0x14, 0x18, 0x19);
+ }
+
+ if (c & 0x08) {
+ HalpDumpAsicPorts (MSG_B_PARITY, 0x23, 0x24, 0x28, 0x29);
+ }
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0x97, 0xc1); // select arbiter
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf808);
+ WRITE_PORT_UCHAR ((PUCHAR) 0x97, VMCId);
+
+ if (c & 0x20) { // check for s_error
+ HalpDumpAsicPorts (MSG_A_TOE, 0x1d, 0x1e);
+
+ }
+
+ if (c & 0x10) { // check for s_error
+ HalpDumpAsicPorts (MSG_B_TOE, 0x2d, 0x2e);
+ }
+ HalDisplayString("\n");
+}
+
+VOID HalpDumpMCADDR (UCHAR MCADDRId)
+{
+ UCHAR c;
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0x97, MCADDRId);
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf800);
+ if (c != MCADDRId) {
+ return ;
+ }
+ WRITE_PORT_UCHAR ((PUCHAR) 0xF807, 0);
+
+ HalpDumpAsicPorts ("MCADDR: %x\n", MCADDRId);
+ HalpDumpAsicPorts (MSG_A_GOOD, 0x40, 0x43, 0x44);
+ HalpDumpAsicPorts (MSG_B_GOOD, 0x45, 0x48, 0x49);
+ HalpDumpAsicPorts (MSG_A_LAST, 0x4a, 0x4d);
+ HalpDumpAsicPorts (MSG_B_LAST, 0x4e, 0x51);
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0xF806, 0x55);
+ c = READ_PORT_UCHAR((PUCHAR) 0xF803);
+ HalpDumpBitsField (c, SBErrorIntStatusBits);
+ HalpDumpAsicPorts (MSG_MC_ADDRESS, 0x55, 0x5c, 0x5d);
+ // status bits decode as:
+ // 0x04 = 1 is memory, 0 is I/O
+
+ if (c & 0x08) {
+ HalpDumpAsicPorts (MSG_MC_TIMEOUT, 0x58);
+ }
+
+ HalpDumpAsicPorts (MSG_MC_PARITY, 0x5e, 0x5e);
+ HalDisplayString ("\n");
+}
+
+VOID HalpDumpArbiter (UCHAR ArbiterId)
+{
+ UCHAR c;
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0x97, ArbiterId);
+ c = READ_PORT_UCHAR ((PUCHAR) 0xf800);
+ if (c != ArbiterId) {
+ return ;
+ }
+
+ HalpDumpAsicPorts ("Aribter: %x\n", ArbiterId);
+
+ c = READ_PORT_UCHAR((PUCHAR) 0xF808);
+ HalpDumpBitsField (c, InterruptStatusOneBits);
+
+ c = READ_PORT_UCHAR((PUCHAR) 0xF809);
+ HalpDumpBitsField (c, InterruptStatusTwoBits);
+ HalDisplayString ("\n");
+}
+
+
+
+VOID HalpDumpBitsField (UCHAR bits, char *BitMsgs[])
+{
+ UCHAR i;
+
+ for (i=0; i < 8; i++) {
+ if (bits & 1 && BitMsgs[i]) {
+ HalDisplayString (" ");
+ HalDisplayString (BitMsgs[i]);
+ HalDisplayString ("\n");
+ }
+ bits >>= 1;
+ }
+}
+
+
+VOID HalpDumpAsicPorts (PUCHAR p, ULONG arg, ...)
+{
+ UCHAR c;
+ PUCHAR o;
+ UCHAR s[150];
+ PULONG stack;
+ ULONG l;
+
+ o = s;
+ stack = &arg;
+ while (*p) {
+ if (*p == '%') {
+ p++;
+ l = *(stack++);
+ switch (*(p++)) {
+
+ // truncate sting if bit-0 is not set
+ case '1':
+ WRITE_PORT_UCHAR ((PUCHAR) 0xF806, (UCHAR) l);
+ c = READ_PORT_UCHAR((PUCHAR) 0xF803);
+ if ((c & 1) == 0) {
+ return ;
+ }
+ break;
+
+ case 'p': // port value
+ c = READ_PORT_UCHAR((PUCHAR) l);
+ *(o++) = HexString[c >> 4];
+ *(o++) = HexString[c & 0xF];
+ break;
+
+ case 's': // sub-port value
+ HexSubPort (&o, l);
+ break;
+
+ case 'A': // address at
+ HexSubPort (&o, l); // sub-port
+ HexSubPort (&o, l-1);
+ HexSubPort (&o, l-2);
+ HexSubPort (&o, l-3);
+ break;
+
+ case 'x': // hex byte
+ *(o++) = HexString[l >> 4];
+ *(o++) = HexString[l & 0xF];
+ break;
+
+ default:
+ *(o++) = '?';
+ break;
+ }
+ } else {
+ *(o++) = *(p++);
+ }
+ }
+ *o = 0;
+ HalDisplayString (s);
+}
+
+VOID HexSubPort (PUCHAR *o, ULONG l)
+{
+ UCHAR c;
+
+ WRITE_PORT_UCHAR ((PUCHAR) 0xF806, (UCHAR) l);
+ c = READ_PORT_UCHAR((PUCHAR) 0xF803);
+
+ o[0][0] = HexString[c >> 4];
+ o[0][1] = HexString[c & 0xF];
+ *o += 2;
+}
diff --git a/private/ntos/nthals/halncr/i386/ncrpsi.h b/private/ntos/nthals/halncr/i386/ncrpsi.h
new file mode 100644
index 000000000..2bda2f117
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrpsi.h
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncrpsi.h
+
+Author:
+
+Abstract:
+
+ System equates for dealing with the NCR PSI boad.
+
+++*/
+
+#ifndef _NCRPSI_
+#define _NCRPSI_
+
+/*
+ * CAT_I is the only ASIC on the Power Supply Interface Module
+ */
+
+
+/* UNDEFINED STATUS BITS */
+
+#define PSI_Security_Switch_L5 0x01
+
+/* END UNDEFINED STATUS BITS */
+
+
+#define NUM_POWER_SUPPLIES_L5 5
+#define NUM_FANS_L5 8
+
+#define PSI_Interrupt_Status_L5 0x08
+
+ /* Read Values */
+
+#define PSI_DC_Failed0_L5 0x01
+#define PSI_PwrSupplyMon_L5 0x02
+#define PSI_Fault_L5 0x04
+#define PSI_TimerAlarm_L5 0x08
+#define PSI_DVM_Int_L5 0x20
+#define PSI_StatusChange_L5 0x80
+
+ /* Write Values */
+
+#define PSI_ClearFault_L5 0x00
+
+
+#define PSI_Status_Change_1_L5 0x09
+
+#define PSI_Temp2_L5 0x02
+#define PSI_Temp1_L5 0x04
+#define PSI_Diag_Stat_L5 0x40
+
+#define PSI_Status_Change_3_L5 0x0A
+#define PSI_Fan1_Failed_L5 0x01
+#define PSI_Fan2_Failed_L5 0x02
+#define PSI_Fan3_Failed_L5 0x04
+#define PSI_Fan4_Failed_L5 0x08
+#define PSI_Fan5_Failed_L5 0x10
+#define PSI_Fan6_Failed_L5 0x20
+#define PSI_Fan7_Failed_L5 0x40
+#define PSI_Fan8_Failed_L5 0x80
+
+#define PSI_Fault_Status_L5 0x0B
+#define PSI_VSB_OverCurrent_L5 0x01
+#define PSI_PMC_OverCurrent_L5 0x02
+#define PSI_SMC_OverCurrent_L5 0x04
+#define PSI_TempFault_L5 0x80
+
+#define PSI_TMS_Activity_L5 0x0C
+#define PSI_TMSX_0 0x01
+#define PSI_TMSX_1 0x02
+#define PSI_TMSX_2 0x04
+#define PSI_TMSX_3 0x08
+#define PSI_TMSX_4 0x10
+#define PSI_TMSX_5 0x20
+#define PSI_TMSX_MC 0x40
+#define PSI_TMSX_Spare 0x80
+
+#define PSI_General_XS1_L5 0x0D
+
+ /* Read Values */
+
+#define PSI_Red_Disk_LED_L5 0x01
+#define PSI_Grn_Disk_LED_L5 0x02
+#define PSI_Red_Stat_LED_L5 0x04
+#define PSI_Grn_Stat_LED_L5 0x08
+#define PSI_Diag_Stat_L5 0x40
+#define PSI_Q_Cold_Reset_L5 0x80
+
+/* Write Values */
+
+#define PSI_Red_Disk_LED_Off_L5 0x00
+#define PSI_Red_Disk_LED_On_L5 0x10
+#define PSI_Grn_Disk_LED_Off_L5 0x01
+#define PSI_Grn_Disk_LED_On_L5 0x11
+#define PSI_Red_Stat_LED_Off_L5 0x02
+#define PSI_Red_Stat_LED_On_L5 0x12
+#define PSI_Grn_Stat_LED_Off_L5 0x03
+#define PSI_Grn_Stat_LED_On_L5 0x13
+#define PSI_Diag_Stat_Off_L5 0x06
+#define PSI_Diag_Stat_On_L5 0x16
+#define PSI_Assert_Cold_Reset_L5 0x07
+#define PSI_Unassert_Cold_Reset_L5 0x17
+
+#define PSI_Sys_Status_L5 0x0E
+#define PSI_S_128_256_L5 0x04
+#define PSI_Test_L5 0x08
+#define PSI_Enable_Fault_L5 0x40
+#define PSI_Enable_HX_Off_L5 0x80
+
+
+#define PSI_Pwr_Supply_Status_L5 0x8000
+
+ /* read values */
+
+#define PSI_DC_Fail0 0x01
+#define PSI_AC_Fail0 0x02
+#define PSI_PSMon_INT 0x04
+#define PSI_PowerOff_Request 0x08
+#define PSI_HX_Off 0x10
+#define PSI_SecuritySwitch_On 0x20
+#define PSI_CmosBattery_Low 0x40
+#define PSI_CmosBattery_Fail 0x80
+
+ /* write values */
+
+#define PSI_Clear_PowerOff_Request 0x13
+#define PSI_Clear_HXOff_Request 0x14
+#define PSI_Clear_CmosBattery_Fail 0x17
+
+#define PSI_Pwr_Supply_Mask_L5 0x8001
+
+ /* read values */
+
+#define PSI_Redundant_Config 0x20
+
+ /* write values */
+
+#define PSI_PowerSupply1_Mask 0x10
+#define PSI_PowerSupply2_Mask 0x11
+#define PSI_PowerSupply3_Mask 0x12
+#define PSI_PowerSupply4_Mask 0x13
+#define PSI_PowerSupply5_Mask 0x14
+
+#define PSI_Pwr_Supply_Pres_L5 0x8002
+#define PSI_PowerSupply1_Present 0x01
+#define PSI_PowerSupply2_Present 0x02
+#define PSI_PowerSupply3_Present 0x04
+#define PSI_PowerSupply4_Present 0x08
+#define PSI_PowerSupply5_Present 0x10
+#define PSI_UPS_Present 0x20
+#define PSI_True 0x40
+#define PSI_PowerSupply_Failure 0x80
+
+#define PSI_Pwr_Supply_DCFail_L5 0x8003
+#define PSI_DcFail1 0x01
+#define PSI_DcFail2 0x02
+#define PSI_DcFail3 0x04
+#define PSI_DcFail4 0x08
+#define PSI_DcFail5 0x10
+#define PSI_DcChange 0x80
+
+#define PSI_Pwr_Supply_AcFail_L5 0x8004
+#define PSI_AcFail1 0x01
+#define PSI_AcFail2 0x02
+#define PSI_AcFail3 0x04
+#define PSI_AcFail4 0x08
+#define PSI_AcFail5 0x10
+#define PSI_AcChange 0x80
+
+#define PSI_Pwr_Supply_Fail_L5 0x8005
+#define PSI_PwrFail1 0x01
+#define PSI_PwrFail2 0x02
+#define PSI_PwrFail3 0x04
+#define PSI_PwrFail4 0x08
+#define PSI_PwrFail5 0x10
+#define PSI_PsChange 0x80
+
+#define PSI_Pwr_Supply_UpsFail_L5 0x8006
+#define PSI_UpsFail1 0x01
+#define PSI_UpsFail2 0x02
+#define PSI_UpsFail3 0x04
+#define PSI_UpsFail4 0x08
+#define PSI_UpsFail5 0x10
+#define PSI_UpsPresent 0x20
+#define PSI_UpsChargeLow 0x40
+#define PSI_UpsChange 0x80
+
+#define PSI_General_Ps_Status_L5 0x8007
+
+ /* read values */
+
+#define PSI_PowerSwitch_On 0x01
+#define PSI_PowerSwitch_Enabled 0x02
+#define PSI_Alarm_Enabled 0x08
+#define PSI_SecureSwitch_Enabled 0x10
+#define PSI_Cold_Reset 0x20
+#define PSI_Cold_Start 0x80
+
+ /* write values */
+
+#define PSI_SoftwarePowerDown0 0x00
+#define PSI_SoftwarePowerDown1 0x10
+#define PSI_Clear_AlarmEnable 0x01
+#define PSI_Set_AlarmEnable 0x11
+#define PSI_Disable_FrontSwitch 0x02
+#define PSI_Enable_FrontSwitch 0x12
+#define PSI_LPB_Reset 0x13
+#define PSI_SwClear_On 0x14
+#define PSI_Clear_ColdReset 0x05
+#define PSI_Set_ColdReset 0x15
+#define PSI_Clear_ColdStart0 0x07
+#define PSI_Clear_ColdStart1 0x17
+
+#define PSI_DiskGroupEnable_L5 0x8010
+#define PSI_DiskStatus_L5 0x8020
+#define PSI_DiskLatchInstalled_L5 0x8028
+#define PSI_Dvm_Select_L5 0x8030
+#define PSI_Dvm_Int_En_L5 0x80
+#define DVM_CONTROL (0x8030)
+#define DVM_DBASE (0x8038)
+#define DVM_SAMPLE (0x80)
+#define DVM_SAMPLE_TIME (5000000) // 500ms in 100ns ticks
+
+#define PSI_WDT_Command_Register_L5 0x804b
+
+ /* write values */
+
+#define PSI_Set_TDM_Bit 0x04
+
+typedef struct _PSI_INFORMATION {
+ union {
+ CAT_REGISTERS CatRegs;
+ struct {
+ UCHAR Dummy0;
+ UCHAR Dummy1;
+ UCHAR Dummy2;
+ UCHAR Dummy3;
+ UCHAR Dummy4;
+ UCHAR Dummy5;
+ UCHAR Dummy6;
+ UCHAR Dummy7;
+ UCHAR InterruptStatus;
+ UCHAR Status1;
+ UCHAR Status3;
+ UCHAR Fault;
+ UCHAR Tms;
+ UCHAR General1;
+ UCHAR SystemConfig;
+ UCHAR DummyF;
+ } PsiRegisters;
+ } CatRegisters;
+
+ /* Begin Subaddress space */
+
+ UCHAR PowerSupplyStatus; /* begin address 8000 */
+ UCHAR PowerSupplyMask;
+ UCHAR PowerSupplyPres;
+ UCHAR PowerSupplyDcFail;
+ UCHAR PowerSupplyAcFail;
+ UCHAR PowerSupplyPsFail;
+ UCHAR PowerSupplyUpsFail;
+ UCHAR GeneralPowerSupplyStatus;
+ UCHAR DiskPowerStatus[8]; /* begin address 8020 */
+ UCHAR DiskInstallStatus[8]; /* begin address 8028 */
+ UCHAR DvmSelect; /* begin address 8030 */
+ UCHAR DvmData0;
+ UCHAR DvmData1;
+ UCHAR DvmData2;
+ UCHAR DvmData3;
+
+} PSI_INFORMATION, *PPSI_INFORMATION;
+
+/* defines for union referencing */
+#define INTERRUPT_STATUS CatRegisters.PsiRegisters.InterruptStatus
+#define STATUS_CHANGE_1 CatRegisters.PsiRegisters.Status1
+#define STATUS_CHANGE_3 CatRegisters.PsiRegisters.Status3
+#define GENERAL_1 CatRegisters.PsiRegisters.General1
+#define FAULT_STATUS CatRegisters.PsiRegisters.Fault
+#define SYSTEM_CONFIG CatRegisters.PsiRegisters.SystemConfig
+
+#define PSI_SHUTDOWN 0 /* tells kernel power fail code to shutdown */
+#define PSI_POWERFAIL 1 /* tells kernel power fail code to powerfail */
+
+
+#endif // _NCRPSI_
diff --git a/private/ntos/nthals/halncr/i386/ncrqic.c b/private/ntos/nthals/halncr/i386/ncrqic.c
new file mode 100644
index 000000000..197acb3bd
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrqic.c
@@ -0,0 +1,329 @@
+/*++
+
+Copyright (c) 1992 NCR Corporation
+
+Module Name:
+
+ ncrqic.c
+
+Abstract:
+
+
+Author:
+
+ Rick Ulmer
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "ncr.h"
+#include "ncrsus.h"
+#include "stdio.h"
+
+PQIC_IPI IpiAddresses[NCR_MAX_NUMBER_QUAD_PROCESSORS];
+PQIC_IPI PhysicalIpiAddresses[NCR_MAX_NUMBER_QUAD_PROCESSORS];
+
+extern PPROCESSOR_BOARD_INFO SUSBoardInfo;
+extern ULONG NCRLogicalDyadicProcessorMask;
+extern ULONG NCRLogicalQuadProcessorMask;
+extern ULONG NCRLogicalNumberToPhysicalMask[];
+extern ULONG NCRExistingQuadProcessorMask;
+
+extern ULONG NCRActiveProcessorMask;
+
+ULONG NCRQicSpurCount = 0;
+
+
+VOID
+HalQicRequestIpi (
+ IN KAFFINITY Mask,
+ IN ULONG Level
+ );
+
+VOID
+HalRequestIpi (
+ IN KAFFINITY Mask
+ )
+/*++
+
+Routine Description:
+ Send Ipi's to processors
+
+Arguments:
+ Processors Mask;
+
+Return Value:
+ none.
+
+--*/
+
+{
+ if (Mask & NCRLogicalDyadicProcessorMask) {
+ HalVicRequestIpi(Mask & NCRLogicalDyadicProcessorMask);
+ }
+
+ if (Mask & NCRLogicalQuadProcessorMask) {
+ HalQicRequestIpi(Mask & NCRLogicalQuadProcessorMask, NCR_IPI_LEVEL_CPI);
+ }
+}
+
+
+VOID
+HalQicRequestIpi (
+ IN KAFFINITY Mask,
+ IN ULONG Level
+ )
+/*++
+
+Routine Description:
+ Send Ipi's to processors
+
+Arguments:
+ Processors Mask;
+
+Return Value:
+ none.
+
+--*/
+
+{
+ PKPCR pPCR;
+ ULONG my_logical_mask;
+
+ PQIC_IPI IpiAddress;
+ ULONG logical_mask;
+ ULONG cpu_id;
+
+
+ pPCR = KeGetPcr();
+ my_logical_mask = ((PProcessorPrivateData)pPCR->HalReserved)->MyLogicalMask;
+
+ logical_mask = Mask;
+
+ cpu_id = 0;
+
+ //
+ // See if we need to send the cpi two ourselves
+ //
+
+ if (my_logical_mask & logical_mask) {
+ WRITE_PORT_UCHAR((PUCHAR)(0xFCC0+(0x8*Level)),0x1);
+ logical_mask ^= my_logical_mask;
+ }
+
+
+ //
+ // Now send to all other processors
+ //
+
+ while (logical_mask) {
+ if (logical_mask & 0x01) {
+ IpiAddress = IpiAddresses[cpu_id];
+ IpiAddress->QIC_LEVEL[Level].Ipi = 1;
+ }
+ cpu_id++;
+ logical_mask >>= 1;
+ }
+}
+
+
+
+VOID
+HalQicStartupIpi (
+ ULONG ProcessorNumber
+ )
+/*++
+
+Routine Description:
+ Send Ipi's to processors
+
+Arguments:
+ Processors Mask;
+
+Return Value:
+ none.
+
+--*/
+
+{
+ register QIC_IPI *IpiAddress;
+
+ IpiAddress = PhysicalIpiAddresses[ProcessorNumber];
+ IpiAddress->QIC_LEVEL[2].Ipi = 1;
+}
+
+
+
+
+ULONG
+NCRClearQicIpi (
+ IN Level
+ )
+/*++
+
+Routine Description:
+ Send Ipi's to processors
+
+Arguments:
+ Processors Mask;
+
+Return Value:
+ none.
+
+--*/
+
+{
+ PKPCR pPCR;
+ ULONG my_logical_number;
+ register QIC_IPI *IpiAddress;
+
+
+ pPCR = KeGetPcr();
+ my_logical_number = ((PProcessorPrivateData)pPCR->HalReserved)->MyLogicalNumber;
+
+//
+// Clear the interrupt
+//
+
+ WRITE_PORT_UCHAR((PUCHAR)0xfc8b, (UCHAR) (0x1<<Level));
+
+// there is some window during bootup where we are hitting this code before
+// IpiAddresses is filled in
+
+ IpiAddress = IpiAddresses[my_logical_number];
+
+ return (IpiAddress->QIC_LEVEL[Level].Ipi);
+}
+
+
+
+VOID
+NCRFindIpiAddress (
+ ULONG ProcessorNumber
+ )
+
+{
+ ULONG physical_processor_number;
+ ULONG physical_mask;
+ ULONG mask;
+ ULONG i;
+
+ physical_mask = NCRLogicalNumberToPhysicalMask[ProcessorNumber];
+
+ physical_processor_number = 0;
+
+ for ( mask = 0x1; mask < (0x1 << NCR_MAX_NUMBER_PROCESSORS); mask <<= 1, physical_processor_number++) {
+ if (mask & physical_mask) {
+ break;
+ }
+ }
+ IpiAddresses[ProcessorNumber] = PhysicalIpiAddresses[physical_processor_number];
+}
+
+
+
+
+
+VOID
+NCRMapIpiAddresses (
+ )
+
+{
+ ULONG i;
+ PQUAD_DESCRIPTION quad_desc;
+ PCHAR cpiaddr[8] = {0};
+ ULONG cpipage[8] = {0};
+ ULONG modules;
+ ULONG slot;
+ ULONG cpu_offset;
+ ULONG proc_id;
+ ULONG physical_processor_number;
+ ULONG mask;
+
+ if (NCRExistingQuadProcessorMask == 0) {
+ return;
+ }
+
+ physical_processor_number = 0;
+
+ for ( mask = NCRExistingQuadProcessorMask; mask != 0; mask >>= 1, physical_processor_number++) {
+
+ if (!(mask & 1)) {
+ continue;
+ }
+
+ slot = (physical_processor_number / 4);
+ proc_id = physical_processor_number % 4;
+
+ DBGMSG(("NCRMapIpiAddress: Physical Proc 0x%x, slot = 0x%x, proc_id = 0x%x\n",
+ physical_processor_number, slot, proc_id));
+
+ modules = SUSBoardInfo->NumberOfBoards;
+ quad_desc = SUSBoardInfo->QuadData;
+
+ cpu_offset = proc_id * 0x100;
+
+ DBGMSG(("NCRMapIpiAddress: modules = %d\n",modules));
+
+ for ( i = 0; i < modules; quad_desc++, i++) {
+
+ DBGMSG(("NCRMapIpiAddress: quad_desc Type = 0x%x, slot = 0x%x\n",quad_desc->Type, quad_desc->Slot));
+
+ if ( quad_desc->Slot == (slot+1)) {
+ if (quad_desc->Type == QUAD ) {
+ if (cpipage[slot] == 0 ) {
+ cpipage[slot] = (ULONG) quad_desc->IpiBaseAddress & ~POFFMASK;
+ cpiaddr[slot] = HalpMapPhysicalMemory(cpipage[slot],1);
+ }
+ PhysicalIpiAddresses[physical_processor_number] =
+ cpiaddr[slot]+(cpu_offset+(quad_desc->IpiBaseAddress & POFFMASK));
+
+ DBGMSG(("NCRMapIpiAddress: Proc %d, Address = 0x%x\n",
+ physical_processor_number,
+ PhysicalIpiAddresses[physical_processor_number]));
+
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+VOID
+NCRHandleQicSpuriousInt (TrapFramePtr, ExceptionRecordPtr)
+IN PKTRAP_FRAME TrapFramePtr;
+IN PVOID ExceptionRecordPtr;
+/*++
+
+Routine Description:
+ Handles the NCR Qic Spurious interrupts
+
+Arguments:
+
+Return Value:
+ none.
+
+--*/
+{
+ UCHAR qic_irr0;
+ UCHAR qic_irr1;
+
+ NCRQicSpurCount++;
+
+#ifdef NEVER
+ qic_irr0 = READ_PORT_UCHAR(0xfc82);
+ qic_irr1 = READ_PORT_UCHAR(0xfc83);
+
+ DBGMSG(("NCRHandleQicSpurious: Count %d, QicIrr0 = 0x%x, QicIrr1 = 0x%x\n",
+ NCRQicSpurCount, qic_irr0, qic_irr1));
+#endif
+}
diff --git a/private/ntos/nthals/halncr/i386/ncrstart.asm b/private/ntos/nthals/halncr/i386/ncrstart.asm
new file mode 100644
index 000000000..e36fb91e9
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrstart.asm
@@ -0,0 +1,987 @@
+ title "Multiprocessor Startup"
+;++
+;
+;Copyright (c) 1992 NCR Corporation
+;
+;Module Name:
+;
+; ncrstart.asm
+;
+;Abstract:
+;
+; Provides the HAL support for starting processors.
+;
+;Author:
+;
+; Richard Barton (o-richb) 24-Jan-1992
+;
+;Revision History:
+;
+;--
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include i386\ix8259.inc
+include i386\ncr.inc
+
+
+ extrn _DbgPrint:PROC
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _NCRFindIpiAddress,1
+ EXTRNP _NCRClearQicIpi,1
+ EXTRNP _HalQicStartupIpi,1
+ EXTRNP _NCRTranslateCMOSMask,1
+ EXTRNP _NCRTranslateToCMOSMask,1
+ EXTRNP _NCRAdjustDynamicClaims,0
+if DBG
+ EXTRNP _NCRConsoleDebug,2
+endif
+ extrn _NCRProcessorsToBringup:DWORD
+ extrn _NCRExistingProcessorMask:DWORD
+ extrn _NCRExistingDyadicProcessorMask:DWORD
+ extrn _NCRExistingQuadProcessorMask:DWORD
+ extrn _NCRExtendedProcessorMask:DWORD
+ extrn _NCRExtendedProcessor0Mask:DWORD
+ extrn _NCRExtendedProcessor1Mask:DWORD
+ extrn _NCRLogicalDyadicProcessorMask:DWORD
+ extrn _NCRLogicalQuadProcessorMask:DWORD
+ extrn _NCRActiveProcessorMask:DWORD
+ extrn _NCRActiveProcessorCount:DWORD
+ extrn _NCRMaxProcessorCount:DWORD
+ extrn _NCRLogicalNumberToPhysicalMask:DWORD
+ extrn _NCRSlotExtended0ToVIC:BYTE
+ extrn _NCRSlotExtended1ToVIC:BYTE
+ extrn _NonbootStartupVirtualPtr:DWORD
+ extrn _NonbootStartupPhysicalPtr:DWORD
+ extrn _PageZeroVirtualPtr:DWORD
+ extrn _HalpDefaultInterruptAffinity:DWORD
+ extrn _HalpActiveProcessors:DWORD
+ extrn _NCRProcessorIDR:DWORD
+ extern _DefaultNeverClaimIRQs:DWORD
+ extern _NCRNeverClaimIRQs:DWORD
+
+ EXTRNP _HalpInitializePICs,0
+
+
+PxParamBlock struc
+ SPx_Mask dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_PB db processorstatelength dup (?)
+PxParamBlock ends
+
+ page ,132
+ subttl "Initialize boot processor"
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeRaise/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; This routine makes some VIC accesses assuming that it's running on
+; an NCR box. The real check won't happen until HalInitMP().
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalInitializeProcessor ,1
+
+;
+; Initialize IDR in PCR to allow irq 2 only.
+;
+
+ mov dword ptr PCR[PcIDR],0fffffffbh
+ mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
+ mov dword ptr PCR[PcHal.PcrMyClaimedIRQs], 0
+ mov dword ptr PCR[PcHal.PcrMyClaimedIRQsCount],0
+
+
+;
+; all processors execute this first section
+;
+; remember this processors logical number
+;
+
+ mov ecx, 4[esp]
+ mov PCR[PcHal.PcrMyLogicalNumber], ecx
+
+;
+; Set IDR table to same value as PcIDR
+;
+ mov _NCRProcessorIDR[ecx*4],0fffffffbh
+
+
+;RMU
+;if DBG
+; push ebx
+; push ecx
+; push edx
+; mov eax,1
+; stdCall _NCRConsoleDebug, <eax,ecx>
+; pop edx
+; pop ecx
+; pop ebx
+;endif
+;RMU
+
+
+ mov eax, 1
+ shl eax, cl
+ lock or _HalpActiveProcessors, eax
+
+if 0
+ ; begin - spinlock test code - kenr
+ push eax
+ push edx
+
+ mov eax, 1
+ shl eax, cl ; (eax) = pmask
+ shl eax, 16 ; mask into high word of dword
+
+ mov fs:PcHal.PcrCheckForBit, eax ; (pmask<<16)
+
+ or eax, 1 ; set low byte to 1
+ mov fs:PcHal.PcrSpinAcquireBits, eax ; (pmask<<16) | 1
+
+ not eax
+ and eax, 0ffff0000h
+ mov fs:PcHal.PcrSpinReleaseMask, eax ; ~(pmask<<16)
+
+
+ mov eax, ecx
+ inc eax ; handoff id
+ shl eax, 8
+ or eax, 1 ; (handoff << 8) | 1
+ mov fs:PcHal.PcrSpinId, eax
+
+
+ pop edx
+ pop eax
+ ; end - spinlock test code
+endif
+
+
+;
+; remember this processors physical mask
+;
+ WHO_AM_I
+ jb IAmQuad
+
+;
+; Processor init code for Dyadic
+;
+
+ lock or _NCRActiveProcessorMask, eax
+ lock inc _NCRActiveProcessorCount
+
+ mov edx, CPU_DYADIC
+ mov PCR[PcHal.PcrMyProcessorFlags],edx
+;
+; setup translation databases:
+;
+ mov edx, 1
+ shl edx, cl ; edx contains logical mask
+ mov PCR[PcHal.PcrMyLogicalMask], edx
+ lock or _NCRLogicalDyadicProcessorMask, edx
+ lock or _HalpDefaultInterruptAffinity, edx
+;
+; Get the real hardware VIC mask so we can send CPIs
+;
+ mov dx, VIC_BASE_ADDRESS+vic_ProcessorWhoAmIReg
+ xor eax,eax
+ in al,dx
+ mov _NCRLogicalNumberToPhysicalMask[ecx*4], eax
+
+;
+; make sure all processors can take interrupts (have this processor claim none)
+;
+ VIC_WRITE ClaimRegLsb, 0
+ VIC_WRITE ClaimRegMsb, 0
+
+ or ecx, ecx
+ jz InitBoot
+;
+; nonboot processor only stuff
+;
+ stdCall _HalpInitializePICs
+
+;
+; no need to send EOI for startup CPI since just initialized PICs above
+;
+
+;
+; make sure each processor can get IPI
+;
+ stdCall _HalEnableSystemInterrupt, <NCR_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI,IPI_LEVEL,0>
+
+ stdRET _HalInitializeProcessor
+;
+; boot processor only stuff
+;
+ align dword
+InitBoot:
+;
+; setup the cross-processor vector base
+;
+ mov eax, NCR_CPI_VECTOR_BASE
+ VIC_WRITE CpiVectorBaseReg
+;
+; temporary fix for VIC errata - true spurious primary MC interrupts (where
+; HW removes the request during INTA cycle) can result in a secondary MC based
+; vector being supplied by the VIC (with the ISR bit actually set, but no
+; real interrupt). Since currently no interrupts are routed through the
+; secondary MC vector space, will simply set the secondary MC vector space
+; equal to the primary vector space.
+;
+ mov eax, NCR_SECONDARY_VECTOR_BASE
+ VIC_WRITE ExtMasterVectorBaseReg
+ mov eax, NCR_SECONDARY_VECTOR_BASE+8
+ VIC_WRITE ExtSlaveVectorBaseReg
+
+ stdRET _HalInitializeProcessor
+;
+; Processor init code for Quad processor
+;
+
+IAmQuad:
+
+;
+; save logical processor number to hardware mask
+;
+
+ mov _NCRLogicalNumberToPhysicalMask[ecx*4], eax
+
+;
+; now lets see if we are extended or not
+;
+
+ mov edx,eax ; save process mask
+ PROCESSOR_SLOT ; get the process slot for this CPU
+ shl eax,2h ; calculate shift to isolate mask to one board
+ push ecx ; save ecx (contains logical processor number)
+ mov ecx,eax
+ mov eax,edx ; now get processor mask
+ shr eax,cl ; now isolate processor on this board
+ mov ecx,eax ; save processor by board mask
+
+ push edx ; save edx with processor mask
+ QIC_READ ExtendedProcessorSelect ; get the extended processor mask
+ pop edx
+
+ test eax,ecx ; test for extended processor 0
+ jnz short ExtendedProcessor0
+
+ shr eax,4h ; isolate extended processor 1 mask
+
+ test eax,ecx ; test for extended processor 1
+ jnz short ExtendedProcessor
+ pop ecx
+ mov eax,edx
+ mov edx, CPU_QUAD
+
+ jmp short NotExtended;
+
+ExtendedProcessor0:
+
+;
+; For Extended Processor 0 lets setup all other processors on the Quad Board
+;
+ xor ecx,ecx
+ push edx ; save who am I mask
+ align dword
+ExtendedLoop:
+
+ mov al,cl
+ or al,8
+ QIC_WRITE ProcessorId
+
+ mov al,0ffh
+ QIC_WRITE QicMask0
+
+ mov al,QIC_IRQ_ENABLE_MASK
+ QIC_WRITE QicMask1
+
+ xor al,al
+ QIC_WRITE ProcessorId
+
+ inc ecx
+ cmp ecx,4
+ jne short ExtendedLoop
+
+;
+; Qic setup
+;
+
+;
+; Disable propagation of SBE and SINT to non-extened processors
+;
+ QIC_READ Configuration
+ or al,7
+ QIC_WRITE Configuration
+
+ mov al, NCR_CPI_VECTOR_BASE
+ QIC_WRITE VicCpiVectorBaseReg
+
+ mov al, NCR_QIC_CPI_VECTOR_BASE
+ QIC_WRITE QuadCpiVectorBaseReg
+
+ mov al,0ffh
+ QIC_WRITE Clear1Reg
+
+ mov al,NCR_QIC_SPURIOUS_VECTOR
+ QIC_WRITE SpuriousVectorReg
+
+ pop edx ; restore the who am I mask
+
+ExtendedProcessor:
+ pop ecx
+ mov eax,edx
+ mov edx, CPU_QUAD
+ or edx, CPU_EXTENDED
+ push eax
+ mov eax, 1
+ shl eax, cl
+ lock or _HalpDefaultInterruptAffinity, eax
+ pop eax
+NotExtended:
+ mov PCR[PcHal.PcrMyProcessorFlags],edx
+;
+;
+ lock or _NCRActiveProcessorMask, eax
+ lock inc _NCRActiveProcessorCount
+
+ mov edx, 1
+ shl edx, cl ; edx contains logical mask
+ lock or _NCRLogicalQuadProcessorMask, edx
+ mov PCR[PcHal.PcrMyLogicalMask], edx
+
+
+;
+; make sure all processors can take interrupts (have this processor claim none)
+;
+ VIC_WRITE ClaimRegLsb, 0
+ VIC_WRITE ClaimRegMsb, 0
+
+ or ecx, ecx
+ jz QuadInitBoot
+
+ stdCall _NCRFindIpiAddress, <ecx> ; lookup IPI address so we can send and clear IPI's
+ stdCall _NCRClearQicIpi, <2> ; clear the startup IPI
+
+;
+; nonboot processor only stuff
+;
+ mov eax, PCR[PcHal.PcrMyProcessorFlags]
+ test eax,CPU_EXTENDED
+ jz short NoPic
+
+ stdCall _HalpInitializePICs
+
+NoPic:
+ stdRET _HalInitializeProcessor
+;
+; boot processor only stuff
+;
+ align dword
+QuadInitBoot:
+;
+; setup the cross-processor vector base
+;
+ mov eax, NCR_CPI_VECTOR_BASE
+ VIC_WRITE CpiVectorBaseReg
+
+;
+; temporary fix for VIC errata - true spurious primary MC interrupts (where
+; HW removes the request during INTA cycle) can result in a secondary MC based
+; vector being supplied by the VIC (with the ISR bit actually set, but no
+; real interrupt). Since currently no interrupts are routed through the
+; secondary MC vector space, will simply set the secondary MC vector space
+; equal to the primary vector space.
+;
+
+ mov eax, NCR_SECONDARY_VECTOR_BASE
+ VIC_WRITE ExtMasterVectorBaseReg
+ mov eax, NCR_SECONDARY_VECTOR_BASE+8
+ VIC_WRITE ExtSlaveVectorBaseReg
+
+;
+; Qic setup
+;
+
+ mov al, NCR_CPI_VECTOR_BASE
+ QIC_WRITE VicCpiVectorBaseReg
+
+ mov al, NCR_QIC_CPI_VECTOR_BASE
+ QIC_WRITE QuadCpiVectorBaseReg
+
+ mov al,0ffh
+ QIC_WRITE Clear1Reg
+
+ stdRET _HalInitializeProcessor
+stdENDP _HalInitializeProcessor
+
+
+
+ page ,132
+ subttl "Start non-boot processor"
+
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+;
+; we need to consult with firmware tables to determine which processors
+; are okay to start. note that we can not return false until there are
+; no processors left. so we stay here until we either start another
+; processor, there are no processors left to start, or all our attempts
+; to start another processor fail.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+
+cPublicProc _HalStartNextProcessor ,2
+;
+; note that we can screen processors two ways: we can limit the number
+; of processors to start or we can choose which physical processors we
+; will start. this is mainly for debugging and benchmarking purposes.
+;
+; how many processors are we going to allow
+;
+ mov ecx, _NCRActiveProcessorCount
+ cmp ecx, _NCRMaxProcessorCount
+ jae Done
+;
+; which processors are left
+;
+ mov eax, _NCRExistingProcessorMask
+ xor eax, _NCRActiveProcessorMask
+;
+; which processors are we going to allow
+;
+ and eax, _NCRProcessorsToBringup
+ jz Done
+
+ push ebp
+ mov ebp, esp
+
+ sub esp, size PxParamBlock
+
+ push esi
+ push edi
+ push ebx
+
+ push eax ; processors to choose from
+
+ mov esi, OFFSET FLAT:StartPx_RMStubE
+ mov ecx, esi
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ sub ecx, esi
+ mov edi, _NonbootStartupVirtualPtr
+ add edi, size PxParamBlock
+ rep movsb ; Copy RMStub to low memory
+
+ lea edi, PxFrame.SPx_PB
+ mov esi, pProcessorState
+ mov ecx, processorstatelength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+ stdCall _HalpBuildTiledCR3, <pProcessorState>
+
+ mov PxFrame.SPx_Mask, 0
+ mov PxFrame.SPx_TiledCR3, eax
+ mov PxFrame.SPx_P0EBP, ebp
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _NonbootStartupVirtualPtr
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx ; patch realmode stub with
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
+
+;
+; determine which one processor we are going to start. think i'll try
+; alternating buses.
+;
+
+ mov eax, dword ptr [esp] ; retrieve processors awaiting
+ bsf ecx, eax
+
+;
+; check to see if we are starting a dyadic or quad processor
+;
+ mov eax,1
+ shl eax,cl
+
+ test eax,_NCRExistingQuadProcessorMask
+ jnz StartQuadProcessor
+
+;
+; Startup code for a Dyadic processor
+;
+ mov ecx, eax ; now we only care about the startup mask
+;
+; fix the startee processors vector to allow it to receive the cpi
+;
+ mov ebx, _PageZeroVirtualPtr
+ add ebx, NCR_STARTUP_VECTOR_VIC
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+
+ mov eax, _NonbootStartupPhysicalPtr
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+;
+; enable the cpi for the startee processor (although unnecessary for 3360 -
+; it's left enabled by BIOS)
+;
+ push ebx
+ push ecx
+ stdCall _NCRTranslateToCMOSMask, <ecx>
+ bsf ecx, eax
+ mov al, cl
+ pop ecx
+ pop ebx
+ or al, ProcessorIdSelect
+ VIC_WRITE ProcessorIdReg ; assume startee's id
+ mov edx, ecx ; save processor number
+ mov eax, 1
+ mov ecx, NCR_STARTUP_CPI
+ shl eax, cl
+ not al
+ mov ecx, edx ; restore processor number
+ out PIC1_PORT1, al ; clear cpi's irq
+ VIC_WRITE ProcessorIdReg, 0 ; restore own id
+
+ mov eax,ecx ; get the startee mask
+;
+; interrupt the startee
+;
+ push ebx
+ push ecx
+ stdCall _NCRTranslateToCMOSMask, <eax>
+ VIC_WRITE CpiLevel2Reg
+ pop ecx
+ pop ebx
+
+ mov eax,ecx ; get the startee mask
+
+ jmp StarteeWakeNow
+;
+; Startup code for a Quad Processor
+;
+
+StartQuadProcessor:
+
+ test eax,_NCRExtendedProcessor0Mask
+ jnz short StarteeExtended
+
+ mov ebx, _PageZeroVirtualPtr
+ add ebx, NCR_STARTUP_VECTOR_QIC
+
+ jmp short SkipVicSetup
+StarteeExtended:
+;
+; fix the startee processors vector to allow it to receive the cpi
+;
+ mov ebx, _PageZeroVirtualPtr
+ add ebx, NCR_STARTUP_VECTOR_VIC
+
+SkipVicSetup:
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+
+ mov eax, _NonbootStartupPhysicalPtr
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+
+;
+; generate startee processors mask
+;
+ mov eax, 1
+ shl eax, cl ; mask of processor to start
+
+ test eax,_NCRExtendedProcessor0Mask
+ jz short StarteeNotExtended
+
+;
+; We are starting an Extended processor, we do this my using the VIC and not the QIC
+;
+
+;
+; This is extended processor 0
+;
+
+ PROCESSOR_SLOT
+ movzx eax, byte ptr _NCRSlotExtended0ToVIC[eax]
+
+;
+; enable the cpi for the startee processor (although unnecessary for 3360 -
+; it's left enabled by BIOS)
+;
+ push eax ; save the vic processor number
+
+ or al, ProcessorIdSelect
+ VIC_WRITE ProcessorIdReg ; assume startee's id
+ mov dl, cl ; save processor number
+ mov eax, 1
+ mov ecx, NCR_STARTUP_CPI
+ shl eax, cl
+ not al
+ mov cl, dl ; restore processor number
+ out PIC1_PORT1, al ; clear cpi's irq
+ VIC_WRITE ProcessorIdReg, 0 ; restore own id
+
+ pop eax
+ push ecx
+ mov ecx, eax
+;
+; generate startee processors mask
+;
+ mov eax, 1
+ shl eax, cl ; mask of VIC processor to start
+
+; interrupt the startee
+
+ VIC_WRITE CpiLevel2Reg
+ pop ecx
+
+ mov eax, 1
+ shl eax, cl ; mask of processor started
+
+ jmp short StarteeWakeNow
+
+StarteeNotExtended:
+
+ push ecx
+ stdCall _HalQicStartupIpi, <ecx>
+ pop ecx
+
+ mov eax, 1
+ shl eax, cl ; mask of processor started
+
+StarteeWakeNow:
+
+;RMU
+;if DBG
+; push eax
+; push ebx
+; push ecx
+; push edx
+; mov edx,2
+; stdCall _NCRConsoleDebug, <edx,eax>
+; pop edx
+; pop ecx
+; pop ebx
+; pop eax
+;endif
+;RMU
+
+
+;
+; wait for startee to say it's active. we should have a timeout on this
+; loop. however, what if the startee went off in the weeds and corrupted
+; something. if we timeout here we can't be sure what the other processor
+; is doing.
+;
+ align dword
+@@: cmp eax, PxFrame.SPx_Mask
+ jne @b
+
+
+;RMU
+;if DBG
+; push eax
+; push ebx
+; push ecx
+; push edx
+; mov edx,3
+; stdCall _NCRConsoleDebug, <edx,eax>
+; pop edx
+; pop ecx
+; pop ebx
+; pop eax
+;endif
+;RMU
+
+
+
+ pop dword ptr [ebx] ; restore vector
+ add esp, 1*4 ; pop saved mask
+
+ sti
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+
+;
+; tell 'em we started another one
+;
+ mov eax, 1
+ stdRET _HalStartNextProcessor
+
+
+;
+; All processors are online so now lets start the claiming process
+;
+
+ align dword
+Done:
+;
+; now that all CPU's are online we need to calculate how many interrupts
+; each CPU can claim
+;
+
+ stdCall _NCRAdjustDynamicClaims
+
+;
+; setting the never claim mask to correct value will start the claim process
+;
+
+ mov eax, _DefaultNeverClaimIRQs;
+ mov _NCRNeverClaimIRQs, eax
+
+ xor eax,eax
+ stdRET _HalStartNextProcessor
+
+
+stdENDP _HalStartNextProcessor
+
+
+_TEXT ENDS
+
+
+;
+; heavy-duty plagarism from systempro stuff follows:
+;
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+
+cPublicProc StartPx_RMStub ,0
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStubE equ $
+stdENDP StartPx_RMStub
+
+
+_TEXT16 ends ; End 16 bit code
+
+_TEXT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value: ; does not return - completes the loading of the processors_state
+;
+;--
+ align 16 ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+cPublicProc _StartPx_PMStub ,0
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+ ; eax, ebx, edx are still free
+
+ WHO_AM_I
+ mov [PxFrame.SPx_Mask], eax
+
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ stdRET _StartPx_PMStub ; Set eip
+
+stdENDP _StartPx_PMStub
+
+_TEXT ends ; end 32 bit code
+
+ END
diff --git a/private/ntos/nthals/halncr/i386/ncrstop.c b/private/ntos/nthals/halncr/i386/ncrstop.c
new file mode 100644
index 000000000..31172977b
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrstop.c
@@ -0,0 +1,219 @@
+/*++
+
+Copyright (c) 1992 NCR Corporation
+
+Module Name:
+
+ ncrstop.c
+
+Abstract:
+
+ Provides the interface to the firmware for x86.
+
+Author:
+
+ Richard R. Barton (o-richb) 04-Feb-1992
+
+Revision History:
+
+--*/
+#include "halp.h"
+#include "ncr.h"
+
+/*
+ * Some plagarism from ixreboot.c
+ */
+
+//
+// Defines to let us diddle the CMOS clock and the keyboard
+//
+
+#define CMOS_CTRL (PUCHAR )0x70
+#define CMOS_DATA (PUCHAR )0x71
+
+
+// below 2 defines are for 3450/3550 machines
+
+#define SHUT_DOWN 0x8F
+#define SHUT5 0x05
+
+#define RESET 0xfe
+#define KEYBPORT (PUCHAR )0x64
+
+extern ULONG NCRPlatform;
+
+extern BOOLEAN NCRPowerOffSystem;
+
+//
+// Private function prototypes
+//
+
+VOID
+HalpReboot (
+ VOID
+ );
+
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_ENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ Returns control to the firmware routine specified.
+
+ BUGBUG This can probably do useful things (like rebooting) for some
+ values of Routine.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ switch (Routine) {
+ case HalPowerDownRoutine:
+ if (NCRPlatform != NCR3360) {
+ HalpCatPowerOffSystem();
+ }
+
+ case HalHaltRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+
+ //
+ // Never returns
+ //
+
+ if ((NCRPlatform != NCR3360) && (NCRPowerOffSystem == TRUE)) {
+ HalpCatPowerOffSystem();
+ } else {
+ HalpVideoReboot();
+ HalpReboot();
+ }
+ break;
+ default:
+ DBGMSG(("HalReturnToFirmware called\n"));
+ DbgBreakPoint();
+ break;
+ }
+}
+
+
+VOID
+HalpReboot (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure resets the CMOS clock to the standard timer settings
+ so the bios will work, and then issues a reset command to the keyboard
+ to cause a warm boot.
+
+ It is very machine dependent, this implementation is intended for
+ PC-AT like machines.
+
+ This code copied from the "old debugger" sources.
+
+ N.B.
+
+ Will NOT return.
+
+--*/
+
+{
+ UCHAR Scratch;
+ PUSHORT Magic;
+
+ //
+ // By sticking 0x1234 at physical location 0x472, we can bypass the
+ // memory check after a reboot.
+ //
+
+ Magic = HalpMapPhysicalMemory(0, 1);
+ Magic[0x472 / sizeof(USHORT)] = 0x1234;
+
+ //
+ // Turn off interrupts
+ //
+
+ HalpAcquireCmosSpinLock();
+
+ _asm {
+ cli
+ }
+
+ //
+ // Reset the cmos clock to a standard value
+ // (We are setting the periodic interrupt control on the MC147818)
+ //
+
+ //
+ // Disable periodic interrupt
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x0b); // Set up for control reg B.
+ KeStallExecutionProcessor(1);
+
+ Scratch = READ_PORT_UCHAR(CMOS_DATA);
+ KeStallExecutionProcessor(1);
+
+ Scratch &= 0xbf; // Clear periodic interrupt enable
+
+ WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
+ KeStallExecutionProcessor(1);
+
+ //
+ // Set "standard" divider rate
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x0a); // Set up for control reg A.
+ KeStallExecutionProcessor(1);
+
+ Scratch = READ_PORT_UCHAR(CMOS_DATA);
+ KeStallExecutionProcessor(1);
+
+ Scratch &= 0xf0; // Clear rate setting
+ Scratch |= 6; // Set default rate and divider
+
+ WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
+ KeStallExecutionProcessor(1);
+
+ //
+ // Set a "neutral" cmos address to prevent weirdness
+ // (Why is this needed? Source this was copied from doesn't say)
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x15);
+ KeStallExecutionProcessor(1);
+
+ //
+ // for 3450/3550 machines - Set shutdown flag to reset
+ //
+
+ if ((NCRPlatform == NCR3450) || (NCRPlatform == NCR3550)) {
+ WRITE_PORT_UCHAR(CMOS_CTRL, SHUT_DOWN);
+ WRITE_PORT_UCHAR(CMOS_DATA, SHUT5);
+ }
+
+ //
+ // Send the reset command to the keyboard controller
+ //
+
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+
+ _asm {
+ hlt
+ }
+}
diff --git a/private/ntos/nthals/halncr/i386/ncrsus.c b/private/ntos/nthals/halncr/i386/ncrsus.c
new file mode 100644
index 000000000..b454cef24
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrsus.c
@@ -0,0 +1,678 @@
+/*++
+
+Copyright (c) 1993 NCR Corporation
+
+Module Name:
+
+ ncrsus.c
+
+Abstract:
+
+ Provides the interface to the NCR SUS.
+
+Author:
+
+ Rick Ulmer (rick.ulmer@columbiasc.ncr.com) 8-Sep-1993
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "ncr.h"
+#include "ncrcat.h"
+#include "ncrsus.h"
+#include "ncrarb.h"
+
+
+PNST_SUS_LOG SUSErrorLogHeader;
+PUCHAR SUSErrorLogData;
+PUCHAR CurrentSUSErrorEntryPosition;
+USHORT CurrentSUSErrorEntryBytesRemaining;
+
+
+PKERNEL_SUS_MAILBOX SUSMailbox;
+PPROCESSOR_BOARD_INFO SUSBoardInfo;
+PCPU_INFO SUSCpuInfo;
+
+extern ULONG NCRExistingProcessorMask;
+extern ULONG NCRExistingDyadicProcessorMask;
+extern ULONG NCRExistingQuadProcessorMask;
+
+ULONG HalpGetCmosData (ULONG SourceLocation, ULONG SourceAddress,
+ PUCHAR Buffer, ULONG Length);
+
+ULONG HalpSetCmosData (ULONG SourceLocation, ULONG SourceAddress,
+ PUCHAR Buffer, ULONG Length);
+
+
+BOOLEAN HalpCheckSUSLogSanity();
+
+VOID HalpWriteCheckSum(
+ PUCHAR CheckSumStart,
+ PUCHAR CheckSumEnd,
+ PUCHAR CheckSumLowByte,
+ PUCHAR CheckSumHighByte
+ );
+
+ULONG NCRTranslateCMOSMask(ULONG);
+
+
+
+VOID
+HalpInitializeSUSInterface (
+ )
+
+{
+ PHYSICAL_ADDRESS physical_log_address;
+ ULONG LowPart;
+ UCHAR data;
+ ULONG i;
+
+
+//
+// Get pointers to SUS Error Log
+//
+
+ SUSErrorLogHeader = NULL;
+ SUSErrorLogData = NULL;
+
+ LowPart = 0;
+
+ HalpGetCmosData(1,SUS_LOG_PTR,
+ (PUCHAR)&LowPart,NST_LOG_PTR_SIZE);
+
+ SUSErrorLogHeader = (PNST_SUS_LOG)HalpMapPhysicalMemory(LowPart,
+ COMPUTE_PAGES_SPANNED(LowPart,sizeof(NST_SUS_LOG)));
+
+
+ if (SUSErrorLogHeader != NULL) {
+
+ LowPart += SUSErrorLogHeader->PhysicalLogBegin;
+
+ SUSErrorLogData = (PUCHAR)HalpMapPhysicalMemory(LowPart,
+ COMPUTE_PAGES_SPANNED(LowPart,SUSErrorLogHeader->PhysicalLogEnd));
+
+
+ if (SUSErrorLogData == NULL) {
+ // MmUnmapIoSpace(SUSErrorLogHeader,sizeof(NST_SUS_LOG));
+ SUSErrorLogHeader = NULL;
+ }
+ }
+
+
+//
+// Make sure SUS error log is OK
+//
+/*RMU
+This is just during debug.......
+
+ if (SUSErrorLogHeader) {
+ SUSErrorLogHeader->FirstUnreadRecord = SUSErrorLogHeader->FirstValidRecord;
+ SUSErrorLogHeader->UnreadBytesInLog = SUSErrorLogHeader->ValidBytesInLog;
+ }
+*/
+
+
+ if (!HalpCheckSUSLogSanity()) {
+ DBGMSG(("SUS Error log is corrputed......................\n"));
+ SUSErrorLogHeader = NULL;
+ SUSErrorLogData = NULL;
+ }
+
+
+
+/*RMU debug phase */
+
+//
+// Get Pointer to SUS/Kernel mailbox
+//
+
+
+ LowPart = 0;
+
+ HalpGetCmosData(1,SUS_MAILBOX_PTR,
+ (PUCHAR)&LowPart,4);
+
+ SUSMailbox = (PKERNEL_SUS_MAILBOX)HalpMapPhysicalMemory(LowPart,
+ COMPUTE_PAGES_SPANNED(LowPart,sizeof(KERNEL_SUS_MAILBOX)));
+
+ SUSMailbox->OSMailboxVersion = FIRST_PASS_INTERFACE;
+ SUSMailbox->OSFlags = OS_KNOWS_SYSINT;
+
+
+//
+// Get Pointer to the SUS board info struct.
+//
+
+ LowPart = (ULONG)SUSMailbox->BoardData;
+
+ SUSBoardInfo = (PPROCESSOR_BOARD_INFO)HalpMapPhysicalMemory(LowPart,
+ COMPUTE_PAGES_SPANNED(LowPart,sizeof(PROCESSOR_BOARD_INFO)));
+
+ DBGMSG(("HalpInitializeSUSInterface: SUSMailbox = 0x%x\n", SUSMailbox));
+ DBGMSG(("HalpInitializeSUSInterface: SUSBoardInfo = 0x%x\n", SUSBoardInfo));
+
+
+//
+// Get Pointer to the SUS cpu info struct.
+//
+
+ LowPart = (ULONG)SUSMailbox->Cpu_Data;
+
+ SUSCpuInfo = (PCPU_INFO)HalpMapPhysicalMemory(LowPart,
+ COMPUTE_PAGES_SPANNED(LowPart,sizeof(CPU_INFO)));
+
+ DBGMSG(("HalpInitializeSUSInterface: SUSCpuInfo = 0x%x\n", SUSCpuInfo));
+
+
+//
+// Now lets go look for all the processor in the system and fill in
+// NCRExistingDyadicProcessorMask and NCRExistingQuadProcessorMask
+//
+
+
+ for (i = 0; i < SUSCpuInfo->NumberOfCpus; i++ ) {
+
+ data = SUSCpuInfo->CpuData[i].CPU_HardwareId;
+
+ if ((data & 0xc0) == 0xc0) {
+
+ //
+ // this is a Quad processor
+ //
+ // convert the who_am_i into the proper mask
+ //
+ // format:
+ //
+ // 1100ccss
+ //
+ // cc = processor bits
+ // ss = slot bits
+ //
+
+ NCRExistingQuadProcessorMask |= (1<<((data & 0xf)>>2))<<(((data&3)<<2));
+
+ } else {
+
+ //
+ // this is a Dyadic processor
+ //
+
+ NCRExistingDyadicProcessorMask |= NCRTranslateCMOSMask(data);
+ }
+ }
+
+
+ DBGMSG(("HalpInitializeSUSInterface: Dyadic Mask = 0x%x, Quad Mask = 0x%x\n",
+ NCRExistingDyadicProcessorMask, NCRExistingQuadProcessorMask));
+
+
+
+
+
+
+//
+// Set firmware to perform a cold reset and not take a dump.
+//
+
+ HalpGetCmosData(1,SUS_RESET_PTR,
+ (PUCHAR)&data,1);
+
+ data |= 0x01;
+
+ HalpSetCmosData(1,SUS_RESET_PTR,
+ (PUCHAR)&data,1);
+
+ HalpWriteCheckSum((PUCHAR)SUS_HIGH_AVAIL_XSUM_START,
+ (PUCHAR)SUS_HIGH_AVAIL_XSUM_END,
+ (PUCHAR)SUS_HIGH_AVAIL_XSUM_LOW,
+ (PUCHAR)SUS_HIGH_AVAIL_XSUM_HIGH);
+}
+
+
+
+
+
+
+VOID
+HalpSUSLogError (
+
+ )
+
+{
+//
+// This routine tells SUS to go do FRU analysis. After the FRU
+// analysis the system will reboot
+//
+
+ DBGMSG(("HalpSUSLogError has been called......\n"));
+
+ SUSMailbox->OSFlags |= OS_IN_PROGRESS;
+ SUSMailbox->MailboxOS = SYSINT_HANDSHAKE;
+
+
+//
+// Send interrupt from SP to DP
+//
+
+ WRITE_PORT_UCHAR((PUCHAR)0xf820,(UCHAR)0x11);
+}
+
+
+
+BOOLEAN
+HalpSUSSwNmi (
+
+ )
+
+{
+
+ DBGMSG(("HalpSUSSwNmi has been called......\n"));
+
+ if (SUSMailbox->MailboxSUS == DUMP_BUTTON_INTERRUPT) {
+
+ SUSMailbox->MailboxOS = NO_COMMAND;
+ SUSMailbox->OSFlags |= OS_IN_PROGRESS;
+ KeStallExecutionProcessor(1000000); // give DP a chance 1 sec
+
+ SUSMailbox->MailboxOS = IGNORE_DUMP_BUTTON;
+ SUSMailbox->OSFlags &= ~OS_IN_PROGRESS;
+
+ while (SUSMailbox->MailboxSUS == DUMP_BUTTON_INTERRUPT) {
+ KeStallExecutionProcessor(1);
+ };
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+
+
+
+
+
+
+BOOLEAN
+HalpCheckSUSLogSanity (
+ )
+
+
+{
+ USHORT bytes_in_log;
+ PSUS_ERROR_RECORD_HEADER SUS_header;
+
+ PUCHAR next_write_record;
+ PUCHAR logical_log_end;
+
+ if (SUSErrorLogHeader == NULL) {
+ return FALSE;
+ }
+
+ next_write_record = ADDRESS_OF(NEXT_WRITE_RECORD);
+ logical_log_end = ADDRESS_OF(LOGICAL_LOG_END);
+
+ if( (FIRST_VALID_RECORD >= PHYS_LOG_END) ||
+ (FIRST_UNREAD_RECORD > PHYS_LOG_END) ||
+ (LOGICAL_LOG_END > PHYS_LOG_END) ||
+ (NEXT_WRITE_RECORD > PHYS_LOG_END) ||
+ (VALID_BYTES_IN_LOG > PHYS_LOG_END) ||
+ (UNREAD_BYTES_IN_LOG > PHYS_LOG_END) ||
+ (UNREAD_BYTES_IN_LOG > VALID_BYTES_IN_LOG) ||
+ (VALID_BYTES_IN_LOG > LOGICAL_LOG_END) ) {
+ return FALSE;
+ }
+
+ if (VALID_BYTES_IN_LOG == 0)
+ return TRUE;
+
+
+ //
+ // Make sure the VALID_BYTES_IN_LOG is correct and that the log can be
+ // traversed starting with the FIRST_VALID_RECORD.
+ //
+
+ for (bytes_in_log = 0,
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)ADDRESS_OF(FIRST_VALID_RECORD);
+ bytes_in_log < VALID_BYTES_IN_LOG; ) {
+
+
+ if (SUS_header > (PSUS_ERROR_RECORD_HEADER)logical_log_end)
+ return FALSE;
+
+ if ((SUS_header == (PSUS_ERROR_RECORD_HEADER)logical_log_end))
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)SUSErrorLogData;
+
+ if (SUS_header->RecordLength <= 0)
+ return FALSE;
+
+ if ((bytes_in_log += SUS_header->RecordLength) > VALID_BYTES_IN_LOG)
+ return FALSE;
+
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)((ULONG)SUS_header +
+ (ULONG)SUS_header->RecordLength);
+ }
+
+ if( bytes_in_log != VALID_BYTES_IN_LOG )
+ return FALSE;
+
+
+ if (UNREAD_BYTES_IN_LOG == 0)
+ return TRUE;
+
+//
+// Make sure the UNREAD_BYTES_IN_LOG is correct and that the log can be
+// traversed starting with the FIRST_UNREAD_RECORD.
+//
+ for (bytes_in_log = 0,
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)ADDRESS_OF(FIRST_UNREAD_RECORD);
+ bytes_in_log < UNREAD_BYTES_IN_LOG; ) {
+
+ if (SUS_header > (PSUS_ERROR_RECORD_HEADER)logical_log_end)
+ return FALSE;
+
+ if ((SUS_header == (PSUS_ERROR_RECORD_HEADER)logical_log_end))
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)SUSErrorLogData;
+
+ if (SUS_header->RecordLength <= 0)
+ return FALSE;
+
+ if ((bytes_in_log += SUS_header->RecordLength) > UNREAD_BYTES_IN_LOG)
+ return FALSE;
+
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)((ULONG)SUS_header +
+ (ULONG)SUS_header->RecordLength);
+ }
+
+ if( bytes_in_log != UNREAD_BYTES_IN_LOG )
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+
+
+LONG
+HalGetSUSErrorLogEntry (
+ PUCHAR ErrorEntry
+ )
+
+{
+ PSUS_ERROR_RECORD_HEADER SUS_header;
+ USHORT entry_length;
+
+ if ((SUSErrorLogHeader == NULL) || (SUSErrorLogData == NULL)) {
+ return -1;
+ }
+
+ if (UNREAD_BYTES_IN_LOG) {
+
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)ADDRESS_OF(FIRST_UNREAD_RECORD);
+ entry_length = SUS_header->RecordLength;
+
+ if (entry_length > HAL_MAX_SUS_ENTRY_SIZE) {
+ entry_length = HAL_MAX_SUS_ENTRY_SIZE;
+ }
+
+ RtlMoveMemory(ErrorEntry,SUS_header,entry_length);
+
+ UNREAD_BYTES_IN_LOG -= SUS_header->RecordLength;
+ FIRST_UNREAD_RECORD += SUS_header->RecordLength;
+
+ if ((FIRST_UNREAD_RECORD == LOGICAL_LOG_END) &&
+ (UNREAD_BYTES_IN_LOG)) {
+
+ FIRST_UNREAD_RECORD = 0;
+ }
+
+ } else {
+ entry_length = 0;
+ }
+ return entry_length;
+}
+
+
+
+
+VOID
+HalSetWatchDogPeriod (
+ ULONG Period
+ )
+
+{
+ if (SUSMailbox) {
+ SUSMailbox->OSFlags |= UPDATING_WDPERIOD;
+ SUSMailbox->WatchDogPeriod = Period;
+ SUSMailbox->WatchDogCount = 0;
+ SUSMailbox->OSFlags &= ~UPDATING_WDPERIOD;
+ }
+}
+
+
+VOID
+HalBumpWatchDogCount (
+ )
+
+{
+ if (SUSMailbox) {
+ SUSMailbox->WatchDogCount++;
+ }
+}
+
+
+
+
+
+
+
+VOID
+HalpBeginSUSErrorEntry (
+ ULONG EntryType,
+ ULONG EntrySize
+ )
+
+{
+ USHORT record_length;
+ PSUS_ERROR_RECORD_HEADER SUS_header;
+
+ USHORT i;
+
+
+//
+// Make sure the log is in a good state.
+//
+
+ if (!HalpCheckSUSLogSanity()) {
+ CurrentSUSErrorEntryPosition = NULL;
+ CurrentSUSErrorEntryBytesRemaining = 0;
+ return;
+ }
+
+
+//
+// Make sure the Error Entry is valid
+//
+
+ if ((EntryType != NST_ErrorType) && (EntryType != ASCII_ErrorType)) {
+ return;
+ }
+
+
+ record_length = EntrySize + sizeof(SUS_ERROR_RECORD_HEADER);
+
+//
+// increate by 1 for the null terminator
+//
+ record_length++;
+
+
+//
+// is it too big to fit?
+//
+
+ if (record_length > PHYS_LOG_END)
+ return;
+
+ /* Check for fit before physical end of log */
+ /*
+ * if this record will NOT fit within physical end of log,
+ * it causes a wrap of the error log
+ * if the log is in a wrapped state, valid records at end of log will
+ * be lost
+ * Delete the valid bytes that are at the end of the log
+ * Point first valid to top of log
+ * if first unread will be lost in the wrap, unread records at the
+ * end of the log will be lost
+ * Delete the unread bytes that are at the end of the log
+ * Point first unread to top of log
+ * Set new logical end to where next record was to write
+ * Set next write record to the top of the log
+ */
+
+ if ((record_length + NEXT_WRITE_RECORD) > PHYS_LOG_END) {
+ if (FIRST_VALID_RECORD >= NEXT_WRITE_RECORD) {
+ VALID_BYTES_IN_LOG -= LOGICAL_LOG_END - FIRST_VALID_RECORD;
+ FIRST_VALID_RECORD = 0;
+ }
+ if (FIRST_UNREAD_RECORD >= NEXT_WRITE_RECORD) {
+ UNREAD_BYTES_IN_LOG -= LOGICAL_LOG_END - FIRST_UNREAD_RECORD;
+ FIRST_UNREAD_RECORD = 0;
+ }
+ LOGICAL_LOG_END = NEXT_WRITE_RECORD;
+ NEXT_WRITE_RECORD = 0;
+ }
+
+
+ /* Check for overwriting currently unread records */
+
+ while(UNREAD_BYTES_IN_LOG && (NEXT_WRITE_RECORD <= FIRST_UNREAD_RECORD) &&
+ ((record_length + NEXT_WRITE_RECORD) > FIRST_UNREAD_RECORD)) {
+
+ UNREAD_BYTES_IN_LOG -= RECORDLENGTH(ADDRESS_OF(FIRST_UNREAD_RECORD));
+ FIRST_UNREAD_RECORD += RECORDLENGTH(ADDRESS_OF(FIRST_UNREAD_RECORD));
+
+ if (FIRST_UNREAD_RECORD >= LOGICAL_LOG_END) {
+ FIRST_UNREAD_RECORD = 0;
+ }
+ }
+
+
+ /* Check for overwriting currently valid records */
+
+ while (VALID_BYTES_IN_LOG && (NEXT_WRITE_RECORD <= FIRST_VALID_RECORD)&&
+ ((record_length + NEXT_WRITE_RECORD) > FIRST_VALID_RECORD)) {
+
+ VALID_BYTES_IN_LOG -= RECORDLENGTH(ADDRESS_OF(FIRST_VALID_RECORD));
+ FIRST_VALID_RECORD += RECORDLENGTH(ADDRESS_OF(FIRST_VALID_RECORD));
+ if (FIRST_VALID_RECORD >= LOGICAL_LOG_END) {
+ FIRST_VALID_RECORD = 0;
+ LOGICAL_LOG_END = VALID_BYTES_IN_LOG;
+ }
+ }
+
+ UNREAD_BYTES_IN_LOG += record_length;
+ VALID_BYTES_IN_LOG += record_length;
+
+ SUS_header = (PSUS_ERROR_RECORD_HEADER)ADDRESS_OF(NEXT_WRITE_RECORD);
+
+ RtlZeroMemory((PVOID)SUS_header, (ULONG)record_length);
+
+ SUS_header->RecordType = EntryType;
+ SUS_header->RecordLength = record_length;
+
+ CurrentSUSErrorEntryPosition = (PUCHAR)ADDRESS_OF(NEXT_WRITE_RECORD) +
+ sizeof(SUS_ERROR_RECORD_HEADER);
+
+ CurrentSUSErrorEntryBytesRemaining = EntrySize;
+
+ /*
+ * Adjust all of the offsets to include the new record.
+ */
+
+ NEXT_WRITE_RECORD += record_length;
+
+ if (NEXT_WRITE_RECORD > LOGICAL_LOG_END)
+ LOGICAL_LOG_END = NEXT_WRITE_RECORD;
+}
+
+
+
+VOID
+HalpWriteToSUSErrorEntry (
+ PUCHAR EntryData
+ )
+
+{
+ USHORT entry_length;
+ USHORT i;
+ PUCHAR char_pointer;
+
+ if (CurrentSUSErrorEntryBytesRemaining == 0) {
+ return;
+ }
+
+ entry_length = 0;
+ char_pointer = EntryData;
+
+ while (*char_pointer) {
+ char_pointer++;
+ entry_length++;
+ }
+
+ if (entry_length == 0)
+ return;
+
+ if (entry_length > CurrentSUSErrorEntryBytesRemaining) {
+ entry_length = CurrentSUSErrorEntryBytesRemaining;
+ }
+
+
+//
+// Copy Entry segment into the Error Log
+//
+
+ RtlMoveMemory(CurrentSUSErrorEntryPosition,EntryData,entry_length);
+
+ CurrentSUSErrorEntryBytesRemaining -= entry_length;
+ CurrentSUSErrorEntryPosition += entry_length;
+}
+
+
+
+
+VOID HalpWriteCheckSum(
+ PUCHAR CheckSumStart,
+ PUCHAR CheckSumEnd,
+ PUCHAR CheckSumLowByte,
+ PUCHAR CheckSumHighByte
+ )
+
+
+
+{
+ USHORT check_sum = 0;
+ USHORT zero_sum;
+ PUCHAR address;
+ UCHAR data;
+
+
+ for (address = CheckSumStart; address <= CheckSumEnd; address++) {
+ HalpGetCmosData(1,(ULONG)address,
+ (PUCHAR)&data,1);
+ check_sum = check_sum + data;
+ }
+
+ zero_sum = 0 - check_sum;
+
+ HalpSetCmosData(1,SUS_HIGH_AVAIL_XSUM_LOW,
+ (PUCHAR)&zero_sum,2);
+}
+
+
+
+
diff --git a/private/ntos/nthals/halncr/i386/ncrsus.h b/private/ntos/nthals/halncr/i386/ncrsus.h
new file mode 100644
index 000000000..b9981cc7a
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrsus.h
@@ -0,0 +1,361 @@
+/*++
+
+Copyright (C) 1992 NCR Corporation
+
+
+Module Name:
+
+ ncrsus.h
+
+Author:
+
+Abstract:
+
+ System equates for dealing with the NCR SUS.
+
+++*/
+
+#ifndef _NCRSUS_
+#define _NCRSUS_
+
+
+#define SUS_LOG_PTR 0xA27 /* CMOS location where the SUS Error */
+ /* Log pointer is kept. */
+
+#define HAL_MAX_SUS_ENTRY_SIZE 0x2000 // Maximum Error Log entry size
+
+#pragma pack(1)
+
+typedef struct _NST_SUS_LOG {
+ USHORT PhysicalLogBegin; /* Offset from the header */
+ USHORT PhysicalLogEnd; /* Offset from the PhysicalLogBegin */
+ USHORT FirstValidRecord; /* Offset from the PhysicalLogBegin */
+ USHORT FirstUnreadRecord; /* Offset from the PhysicalLogBegin */
+ USHORT NextWriteRecord; /* Offset from the PhysicalLogBegin */
+ USHORT LogicalLogEnd; /* Offset from the PhysicalLogBegin */
+ USHORT ValidBytesInLog; /* Number of valid bytes in the log */
+ USHORT UnreadBytesInLog; /* Number of unread bytes in the log */
+} NST_SUS_LOG, *PNST_SUS_LOG;
+#pragma pack()
+
+
+#pragma pack(1)
+typedef struct _SUS_ERROR_RECORD_HEADER {
+ USHORT RecordType; /* Type of record */
+ USHORT RecordLength; /* Length of record in bytes */
+} SUS_ERROR_RECORD_HEADER, *PSUS_ERROR_RECORD_HEADER;
+#pragma pack()
+
+
+
+#define NST_ErrorType 0x01 /* Conforms to NST ASCII Format */
+#define ASCII_ErrorType 0x02 /* Non NST, but All ASCII (SUS Can Display) */
+
+#define LOGSIZE PHYS_LOG_END
+
+#define PHYS_LOG_BEGIN (SUSErrorLogHeader->PhysicalLogBegin)
+#define PHYS_LOG_END (SUSErrorLogHeader->PhysicalLogEnd)
+#define FIRST_VALID_RECORD (SUSErrorLogHeader->FirstValidRecord)
+#define FIRST_UNREAD_RECORD (SUSErrorLogHeader->FirstUnreadRecord)
+#define NEXT_WRITE_RECORD (SUSErrorLogHeader->NextWriteRecord)
+#define LOGICAL_LOG_END (SUSErrorLogHeader->LogicalLogEnd)
+#define VALID_BYTES_IN_LOG (SUSErrorLogHeader->ValidBytesInLog)
+#define UNREAD_BYTES_IN_LOG (SUSErrorLogHeader->UnreadBytesInLog)
+#define ADDRESS_OF(OFFSET) (SUSErrorLogData + OFFSET)
+#define RECORDLENGTH(ADDRESS) (((PSUS_ERROR_RECORD_HEADER)(ADDRESS))->RecordLength)
+
+
+#define NST_LOG_PTR_SIZE 4 /* error log ptr size in cmos */
+
+#define CBIOS_SEGMENT 0x40 /* start of bios data area */
+#define CBIOS_OFFSET 0x0E /* extended data segment offset */
+#define CBIOS_AREA ((CBIOSSEGMENT << 4) + CBIOSOFFSET)
+#define POST_NERROFF 0x17 /* offset for number of post errors */
+#define POST_LOGOFF 0x18 /* offset where error log begins */
+#define POST_SPECIFIC "%d%02d" /* post error log specific portion */
+#define POST_ERROR_ID 23 /* used in error log tag */
+#define POST_SPEC_SIZE 10 /* size of post specific portion */
+#define NONE_ID 02
+
+#define E_POSTDOS_TAGS 230000000
+#define E_NONE_TAGS 20000000
+
+#define POST_ERROR_TAG (E_POSTDOS_TAGS + POSTERRORID)
+#define NONE_ERROR_TAG (E_NONE_TAGS + NONEID)
+
+
+#define SUS_MAILBOX_PTR 0xb1a /* XCMOS location for the SUS/OS MAILBOX */
+
+
+#define SUS_RESET_PTR 0xa33 /* XCMOS location for the SUS reboot flag */
+#define SUS_HIGH_AVAIL_XSUM_START 0xa20
+#define SUS_HIGH_AVAIL_XSUM_END 0xb1d
+#define SUS_HIGH_AVAIL_XSUM_LOW 0xb1e
+#define SUS_HIGH_AVAIL_XSUM_HIGH 0xb1f
+
+
+#define NUMBER_OF_POS_REGS 8
+
+#pragma pack(1)
+typedef struct _MC_SLOT_INFORMATION{
+ UCHAR MCSlot;
+ UCHAR POSValues[NUMBER_OF_POS_REGS];
+} MC_SLOT_INFORMATION, *PMC_SLOT_INFORMATION;
+#pragma pack()
+
+#define NUMBER_OF_MC_BUSSES 2
+#define SLOTS_PER_MC_BUS 8
+#define MAX_CPUS 16 // 16 way CPU system
+
+/* Index to MC_SlotInfo[xMC_BUS][] */
+#define PMC_BUS 0
+#define SMC_BUS 1
+
+#define MAX_PROCESSOR_BOARDS 4 /* 4 processor slot system */
+#define MAX_CACHE_LEVELS 4 /* # of cache levels supported */
+#define MAX_SHARED_CPUS 4 /* # of CPUs that can share a LARC */
+
+/*
+ * Defines for BoardDescription
+ * structure
+ */
+
+/* Defines for Type */
+#define DYADIC_OR_MONADIC 0
+#define QUAD 1
+
+#define POFFMASK 0xfff // Mask for offset into page.
+
+
+/* Define for LocalMemoryStateBits */
+#define BANK_0_PRESENT 0x01
+#define BANK_0_FUNCTIONAL 0x02
+#define BANK_1_PRESENT 0x04
+#define BANK_1_FUNTIONAL 0x08
+
+/* type defines for CPU info */
+#define BASIC_CPU_INFO_TYPE 0
+#define CPU_INFO_VERSION_0 0
+
+/*
+ * Defines for ProcBoardInfo
+ * and QuadDescription structurs
+ */
+#define QUAD_BOARD_INFO_TYPE 0
+#define QUAD_BOARD_INFO_VERSION_0 0
+#define QUAD_DESCRIPTION_TYPE 1
+#define QUAD_DESCRIPTION_VERSION_0 0
+#define DYADIC_DESCRIPTION_TYPE 0
+#define DYADIC_DESCRIPTION_VERSION 0
+
+
+#pragma pack(1)
+typedef struct _QUAD_DESCRIPTION {
+ UCHAR Type;
+ UCHAR StructureVersion;
+ ULONG IpiBaseAddress;
+ ULONG LarcBankSize;
+ ULONG LocalMemoryStateBits;
+ UCHAR Slot;
+ } QUAD_DESCRIPTION, *PQUAD_DESCRIPTION;
+#pragma pack()
+
+
+#pragma pack(1)
+typedef struct _PROCESSOR_BOARD_INFO {
+ UCHAR Type;
+ UCHAR StructureVersion;
+ UCHAR NumberOfBoards;
+ QUAD_DESCRIPTION QuadData[MAX_PROCESSOR_BOARDS];
+ } PROCESSOR_BOARD_INFO, *PPROCESSOR_BOARD_INFO;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct _CACHE_DESCRIPTION {
+ UCHAR Level;
+ ULONG TotalSize;
+ USHORT LineSize;
+ UCHAR Associativity;
+ UCHAR CacheType;
+ UCHAR WriteType;
+ UCHAR NumberCpusSharedBy;
+ UCHAR SharedCpusHardware_Ids[MAX_SHARED_CPUS];
+ } CACHE_DESCRIPTION, *PCACHE_DESCRIPTION;
+#pragma pack()
+
+
+#pragma pack(1)
+typedef struct _CPU_DESCRIPTION {
+ UCHAR CPU_HardwareId;
+ PCHAR FRU_String;
+ UCHAR NumberOfCacheLevels;
+ CACHE_DESCRIPTION CacheLevelData[MAX_CACHE_LEVELS];
+ } CPU_DESCRIPTION, *PCPU_DESCRIPTION;
+#pragma pack()
+
+
+#pragma pack(1)
+typedef struct _CPU_INFO {
+ UCHAR Type;
+ UCHAR StructureVersion;
+ UCHAR NumberOfCpus;
+ CPU_DESCRIPTION CpuData[MAX_CPUS];
+ } CPU_INFO, *PCPU_INFO;
+#pragma pack()
+
+
+
+/*
+ * This structure will be used by SUS and the OS.
+ */
+
+
+#pragma pack(1)
+typedef struct _KERNEL_SUS_MAILBOX {
+ UCHAR MailboxSUS; /* Written to by SUS to give
+ commands/response to the OS */
+ UCHAR MailboxOS; /* Written to by the OS to give
+ commands/response to SUS */
+ UCHAR SUSMailboxVersion; /* Tells the OS which iteration of the
+ interface SUS supports */
+ UCHAR OSMailboxVersion; /* Tells SUS which iteration of the
+ interface the OS supports */
+ ULONG OSFlags; /* Flags set by the OS as info for
+ SUS */
+ ULONG SUSFlags; /* Flags set by SUS as info for OS */
+ ULONG WatchDogPeriod; /* Watchdog period (in seconds) which
+ the DP uses to see if the OS is
+ dead */
+ ULONG WatchDogCount; /* Updated by the OS on every tic. */
+ ULONG MemoryForSUSErrorLog; /* Flat 32 bit address which tells
+ SUS where to stuff the SUS error
+ log on a dump */
+ MC_SLOT_INFORMATION MCSlotInfo[NUMBER_OF_MC_BUSSES][SLOTS_PER_MC_BUS];
+ /* Storage for MCA POS data */
+ PPROCESSOR_BOARD_INFO BoardData;
+ PCPU_INFO Cpu_Data;
+ /* All new fields must be added from this point */
+} KERNEL_SUS_MAILBOX, *PKERNEL_SUS_MAILBOX;
+#pragma pack()
+
+/*
+ * Common defines for MailBox_SUS
+ */
+#define NO_COMMAND 0x00 /* Default state - indicates that no action/response has been written */
+/*
+ * Defines for start of day VERSION INFO the can be put in both MailBoxes.
+ */
+#define FIRST_PASS_INTERFACE 0x10
+
+/*
+ * SUS messages to the OS
+ */
+#define DUMP_BUTTON_INTERRUPT 0x01
+#define KERNEL_SUS_STRUCTURE_VALID 0x02
+/*
+ * SUS responses to OS messages
+ */
+#define SYSINT_COMPLETE 0x03
+
+/*
+ * OS responses to SUS messages
+ */
+#define IGNORE_DUMP_BUTTON 0x01
+#define TAKE_A_DUMP 0x02
+/*
+ * OS messages to SUS
+ */
+#define SYSINT_HANDSHAKE 0x03
+#define TAKE_MEMORY_DUMP 0x04
+#define SYSINT_WAS_RECOVERED 0x05
+
+/*
+ * Defines for Flags_OS
+ */
+#define OS_KNOWS_SYSINT 0x00000001
+#define OS_IN_PROGRESS 0x00000002
+#define UPDATING_WDPERIOD 0x00000004
+/*
+ * Defines for SUS_Flags
+ */
+#define SUS_BOOTING 0x00000001
+#define SUS_IN_PROGRESS 0x00000002
+/*
+ * Constant for delay util we give up looking for an OS
+ */
+#define SYSINT_HANDOFF_TIMEOUT (60*5*1000)
+
+/* defines for watchdog timer interface */
+#define WDMIN 5 /* 5 seconds is minimum WD period */
+#define WRITE_TIMEOUT 5 /* 5 milliseconds is max period update time */
+
+/*
+ * The following defines allocate the slots in the mailbox.
+ * THIS SOULD CHANGE TO THE STRUCTURE KERNEL_SUS_MAILBOX
+ */
+#define SUS_MBOX_SLOT 0
+#define KERNEL_MBOX_SLOT 1
+
+
+/* Size of copy used with MemoryFor_SUS_ErrorLog
+ */
+
+/* This is the interface from the OS to SUS. You can reverse this
+ * example to go the other way.
+ */
+
+/*
+
+Kernel SUS
+-------------------------------------------- ---------------------------------
+KernelSUSMailbox.MailboxOS = REQUEST_TASK_X
+Interrupt is sent to DP
+ KernelSUSMailbox.MailboxSUS = NO_COMMAND
+ KernelSUSMailbox.SUSFlags |= SUS_IN_PROGRESS
+
+Wait 5 Sec for KernelSUSMailbox.SUSFlags & DO TASK_X
+ SUS_IN_PROGRESS
+ KernelSUSMailbox.MailboxSUS = SYSINT_COMPLETE
+ KernelSUSMailbox.SUSFlags &= ~SUS_IN_PROGRESS
+
+Wait ? Sec for KernelSUSMailbox.MailboxSUS ==
+ TASK_X_COMPLETE
+KernelSUSMailbox.MailboxOS = NO_COMMAND
+
+ */
+
+
+
+
+
+LONG
+HalGetSUSErrorLogEntry (
+ PUCHAR ErrorEntry
+ );
+
+VOID
+HalSetWatchDogPeriod (
+ ULONG Period
+ );
+
+VOID
+HalBumpWatchDogCount (
+ );
+
+
+VOID
+HalpBeginSUSErrorEntry (
+ ULONG EntryType,
+ ULONG EntrySize
+ );
+
+VOID
+HalpWriteToSUSErrorEntry (
+ PUCHAR EntryData
+ );
+
+VOID
+HalpInitializeSUSInterface (
+ );
+
+#endif // _NCRSUS_
diff --git a/private/ntos/nthals/halncr/i386/ncrsyint.asm b/private/ntos/nthals/halncr/i386/ncrsyint.asm
new file mode 100644
index 000000000..2e2e811d4
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrsyint.asm
@@ -0,0 +1,711 @@
+;++
+;
+;Copyright (c) 1992 NCR Corporation
+;
+;Module Name:
+;
+; ncrsyint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts.
+;
+;Author:
+;
+; Richard Barton (o-richb) 24-Jan-1992
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.486p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ncr.inc
+ .list
+
+ EXTRNP KfLowerIrql,1,,FASTCALL
+ EXTRNP _NCRClearQicIpi,1
+ EXTRNP _HalQicRequestIpi,2
+ EXTRNP _NCRAdjustDynamicClaims,0
+ extrn KiI8259MaskTable:DWORD
+ extrn _NCRLogicalNumberToPhysicalMask:DWORD
+ extrn _NCRProcessorIDR:DWORD
+ extrn _NCRNeverClaimIRQs:DWORD
+ extrn _NCRMaxIRQsToClaim:DWORD
+ extrn _NCRGlobalClaimedIRQs:DWORD
+ifdef DBG
+ extrn _NCRProcessorClaimedIRQs:DWORD
+ extrn _NCRClaimCount:DWORD
+ extrn _NCRStolenCount:DWORD
+ extrn _NCRUnclaimCount:DWORD
+endif
+
+
+ifdef IRQL_METRICS
+ extrn HalPostponedIntCount:dword
+endif
+
+
+_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to determine whether the given interrupt is
+; spurious and to raise the irql to the given value.
+; It is called before the interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+; On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
+; This is fine since the irql is being raise to mask it off.
+; HalEndSystemInterrupt is simply a LowerIrql request.
+;
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt being handled
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt is real and Irql raised.
+;
+;--
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+cPublicFpo 3,0
+ movzx ebx,HbsiVector ; (eax) = System Vector
+ sub ebx, PRIMARY_VECTOR_BASE ; (eax) = 8259 IRQ #
+ cmp ebx, 1FH ; if greater then CPI
+ ja HalpNotSpurious
+
+;
+; we could be spurious at irq 7
+;
+ mov eax,ebx ; lets mask off whether it is
+ and eax,0fh ; secondary or primary
+ cmp eax, 7H
+ jne HbsiCheckIrq0F
+
+ align dword
+HbsiCheckIrq07:
+;
+; Check to see if this is a spurious interrupt at irq7
+;
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpNotSpurious ; No, so this is NOT a spurious int
+ xor eax, eax ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+ align dword
+HbsiCheckIrq0F:
+
+;
+; we could be spurious with irq F
+;
+ mov eax,ebx ; lets mask off whether it is
+ and eax,0fh ; secondary or primary
+ cmp eax, 0FH
+ jne HalpNotSpurious
+
+;
+; Check to see if this is a spurious interrupt at irq F
+;
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpNotSpurious ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ xor eax, eax ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+ align dword
+HalpNotSpurious:
+if DBG
+ cmp ebx, 4FH
+ jbe @f
+ int 3
+ align dword
+@@:
+
+endif
+;
+; Store OldIrql
+;
+ mov eax, HbsiOldIrql
+ mov cl, PCR[PcIrql]
+ mov [eax], cl
+
+;
+; Raise IRQL to requested level
+;
+ mov al, HbsiIrql ; (eax) = irql
+ ; (ebx) = IRQ #
+;
+; Now we check to make sure the Irql of this interrupt > current Irql.
+; If it is not, we dismiss it as spurious and set the appropriate bit
+; in the IRR so we can dispatch the interrupt when Irql is lowered
+;
+ cmp al, cl
+ jbe Hbsi300
+;
+; now check for a cpi.
+;
+
+ cmp ebx, NCR_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE ; check for VIC ipi
+ mov PCR[PcIrql], al ; set new Irql
+ jb CheckClaim
+
+ cmp ebx, NCR_QIC_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE ; check for QIC ipi
+ jb VicEOI
+
+ and ebx,7H ; only the mask of irq
+ stdCall _NCRClearQicIpi, <ebx>
+
+ jmp NCRCPIEOId
+
+VicEOI:
+ and bl, 7H ; only the mask of irq
+ mov al, bl
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+
+NCRCPIEOId:
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+
+;RMU
+;
+; Logic used to dynamicly claim device interrupts
+;
+
+CheckClaim:
+ mov ecx, ebx ; get vector
+
+;
+; Lets check for a status change interrupt because it is a broadcast interrupt
+; and is sent to all processors. In this case we skip the Claim logic completely.
+; If we try to claim this interrupt it will cause problems because it is valid for a
+; processor to get this interrupt while another processor has it claimed.
+;
+
+ cmp ecx, 027h ; status change interrupt is at vector PRIMARY_VECTOR_BASE + 027H
+ jz DontClaim ; done claim if equal
+
+;
+;
+;
+
+ and ecx, 0fh ; now is irql
+ mov eax, 1 ; build irq mask
+ shl eax, cl
+
+ test eax, _NCRNeverClaimIRQs ; see if we should never claim it irq
+ jnz DontClaim
+
+ mov ecx, _NCRGlobalClaimedIRQs
+ mov edx, PCR[PcHal.PcrMyClaimedIRQs]
+ and ecx, eax ; set if irq claimed globally
+ and edx, eax ; set if irq claimed privately
+
+ test edx, ecx ; if irq already claimed
+ jz AdjustClaim
+
+DontClaim:
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+
+AdjustClaim:
+ test edx, edx
+ not edx ; is it claimed privately?
+ jnz PrivateUnclaim ; yes, then clear claim
+
+ test ecx,ecx ; is it claimed by another?
+ jnz Unclaimed ; don't unclaim
+
+ mov ecx, PCR[PcHal.PcrMyClaimedIRQsCount] ; see if you have our fair share
+ cmp ecx, _NCRMaxIRQsToClaim ; of irqs claimed then handle if
+ jl ClaimForMe ; but don't claim
+
+HandleNoClaim:
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+
+ClaimForMe:
+
+ mov edx, eax
+ push ebx ; save vector
+ mov ebx, PCR[PcHal.PcrMyClaimedIRQs] ; our claimed irqs
+ or ebx, eax
+ mov eax, _NCRGlobalClaimedIRQs ; what global claim should be
+GlobalClaim:
+ test eax,edx ; this irq has been stolen
+ jnz IRQStolen ; by another processor
+ mov ecx,ebx
+ or ecx,eax
+lock cmpxchg _NCRGlobalClaimedIRQs, ecx
+ jne GlobalClaim
+
+ add esp,4 ; throw away saved vector we do
+ ; not need it
+;
+; Lets claim the interrupt now
+;
+ mov eax,ebx
+ mov PCR[PcHal.PcrMyClaimedIRQs],eax ; claim irq privately
+
+ VIC_WRITE ClaimRegLsb ; set VIC claim registers
+ shr eax,8
+ VIC_WRITE ClaimRegMsb
+ inc PCR[PcHal.PcrMyClaimedIRQsCount]
+
+ mov eax,PCR[PcHal.PcrMyClaimedIRQsCount]
+ VIC_WRITE ActivityReg
+
+ifdef DBG
+ mov ecx,PCR[PcNumber]
+ mov eax,PCR[PcHal.PcrMyClaimedIRQs]
+ mov _NCRProcessorClaimedIRQs[ecx*4], eax
+ inc _NCRClaimCount;
+endif
+
+; done claiming
+ClaimDone:
+
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+
+IRQStolen:
+
+ifdef DBG
+ inc _NCRStolenCount;
+endif
+
+ pop ebx ; restore vector
+ and ebx, 0fh ; clear high nibble due to SMC or Status Change vector
+ cmp ebx, 8 ; EOI to master or slave?
+ mov al, bl
+ jae short SHbsiEOIMaster ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short SHbsiMasterEOId
+
+SHbsiEOIMaster:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+SHbsiMasterEOId:
+
+ xor eax, eax ; return FALSE, spurious interrupt
+ stdRET _HalBeginSystemInterrupt
+
+ align dword
+Hbsi300:
+;
+; Raise Irql to prevent it from happening again
+;
+
+;
+; Get the PIC masks for Irql
+;
+ movzx eax, cl
+ mov PCR[PcHal.PcrMyPICsIrql], eax
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_IRQ_MASK
+;
+; if this isn't a CPI, EOI the interrupt to give the VIC a chance
+; to reroute it
+;
+ cmp ebx, NCR_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE ; EOI for CPI?
+ jae NCRPostponeCPI ; no need to EOI CPI
+;
+;RMU
+; Logic used to unclaim interrupts. This is done when drivers have disabled
+; an interrupt.
+;
+;
+ mov ecx, ebx ; get vector
+ and ecx, 0fh ; now is irql
+ mov eax, 1 ; build irq mask
+ shl eax, cl
+ mov edx, PCR[PcHal.PcrMyClaimedIRQs]
+ and edx, eax ; claiming fixed?
+ jz Unclaimed ; don't unclaim
+
+ mov ecx, PCR[PcHal.PcrMyClaimedIRQsCount] ; if we don't have our fair
+ cmp ecx, _NCRMaxIRQsToClaim ; share of irqs claimed then
+ jle Unclaimed ; don't unclaim
+
+ not edx ; clear irq bit
+ mov eax, _NCRGlobalClaimedIRQs ; what global claim should be
+GlobalUnclaim:
+ mov ecx, edx
+ and ecx, eax
+lock cmpxchg _NCRGlobalClaimedIRQs, ecx
+ jne GlobalUnclaim
+
+PrivateUnclaim:
+ mov eax, PCR[PcHal.PcrMyClaimedIRQs]
+ and eax, edx
+
+ mov PCR[PcHal.PcrMyClaimedIRQs],eax
+ VIC_WRITE ClaimRegLsb
+ shr eax,8
+ VIC_WRITE ClaimRegMsb
+ dec PCR[PcHal.PcrMyClaimedIRQsCount]
+
+ mov eax,PCR[PcHal.PcrMyClaimedIRQsCount]
+ VIC_WRITE ActivityReg
+
+ifdef DBG
+ mov ecx,PCR[PcNumber]
+ mov eax,PCR[PcHal.PcrMyClaimedIRQs]
+ mov _NCRProcessorClaimedIRQs[ecx*4], eax
+ inc _NCRUnclaimCount;
+endif
+
+;
+Unclaimed:
+
+ and ebx, 0fh ; clear high nibble due to SMC or Status Change vector
+ cmp ebx, 8 ; EOI to master or slave?
+ mov al, bl
+ jae short HbsiEOIMaster ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short HbsiMasterEOId
+
+HbsiEOIMaster:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+HbsiMasterEOId:
+
+ifdef IRQL_METRICS
+ lock inc HalPostponedIntCount
+endif
+
+ xor eax, eax ; return FALSE, spurious interrupt
+ stdRET _HalBeginSystemInterrupt
+
+ align dword
+NCRPostponeCPI:
+;
+; CPIs must be reissued since when we EOI them they're gone
+;
+
+ cmp ebx, NCR_QIC_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE ; check for QIC ipi
+ jb VicCPI
+
+ movzx ecx, bl
+ sub ecx, NCR_QIC_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE
+ and ecx, 7
+
+;
+; Clear the current CPI so we can reissue it again
+;
+
+ push ecx
+ stdCall _NCRClearQicIpi, <ecx>
+ pop ecx
+
+;
+; now reissue the same CPI... since our mask is raised and we've EOId
+; the other we'll get this one when we lower our masks
+;
+
+ mov eax, PCR[PcHal.PcrMyLogicalMask]
+ stdCall _HalQicRequestIpi,<eax,ecx>
+
+ jmp ReissuedCPIDone
+VicCPI:
+ movzx ecx, bl
+ sub ecx, NCR_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE
+ and ecx, 7
+ mov al, cl
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+
+;
+; now reissue the same CPI...since our mask is raised and we've EOId
+; the other we'll get this one when we lower our masks.
+;
+ shr ecx, 1 ; we're determining which VIC
+ lea edx, [ecx*8] ; offset corresponds to the
+ adc edx, VIC_BASE_ADDRESS ; given vector
+ mov eax, PCR[PcHal.PcrMyLogicalNumber]
+ mov eax, dword ptr _NCRLogicalNumberToPhysicalMask[eax*4]
+ out dx, al
+
+ReissuedCPIDone:
+
+ifdef IRQL_METRICS
+ lock inc HalPostponedIntCount
+endif
+
+ xor eax, eax ; return FALSE, spurious interrupt
+ stdRET _HalBeginSystemInterrupt
+
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;BOOLEAN
+;HalEndSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified interrupt vector and
+; to lower the irql to the given value.
+; It is called after the interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+;Arguments:
+;
+; Irql - Supplies the interrupt level of the interrupt to be dismissed
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+;Return Value:
+;
+; None.
+;
+;--
+HesiIrql equ [esp+4]
+HesiVector equ [esp+8]
+
+cPublicProc _HalEndSystemInterrupt ,2
+cPublicFpo 2,0
+ movzx eax, byte ptr HesiVector ; (eax) = System Vector
+ sub eax, PRIMARY_VECTOR_BASE ; (eax) = 8259 IRQ #
+if DBG
+ cmp eax, 4FH
+ jbe Hesi00
+ int 3
+ align dword
+Hesi00:
+
+endif
+
+;
+; Dismiss interrupt. Current interrupt is already masked off. note that
+; cpi's are eoi'ed at the beginning.
+;
+ cmp eax, NCR_CPI_VECTOR_BASE - PRIMARY_VECTOR_BASE ; EOI for CPI?
+ mov ecx, HesiIrql ; (cl) = NewIrql
+ jae short Hesi10 ; no need to EOI CPI
+ and eax, 0fh ; clear high nibble due to SMC or Status Change vector
+
+ cmp eax, 8 ; EOI to master or slave?
+
+ jae short Hesi100 ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+
+Hesi10:
+ fstCall KfLowerIrql ; (cl) = NewIrql
+ stdRet _HalEndSystemInterrupt
+
+Hesi100:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ fstCall KfLowerIrql ; (cl) = NewIrql
+ stdRet _HalEndSystemInterrupt
+
+stdENDP _HalEndSystemInterrupt
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalDisableSystemInterrupt ,2
+cPublicFpo 2,0
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ and ecx, 0FH ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or PCR[PcIDR], edx
+
+;
+; save IDR in table for use by NCRAdjustDynamicClaims
+;
+ mov eax,PCR[PcNumber]
+ or _NCRProcessorIDR[eax*4],edx
+;
+ xor eax, eax
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+
+ stdCall _NCRAdjustDynamicClaims
+
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalEnableSystemInterrupt ,3
+cPublicFpo 3,0
+
+ mov ecx, dword ptr [esp+4] ; (ecx) = Vector
+ and ecx, 0FH
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ cli
+ and PCR[PcIDR], eax
+;
+; save IDR in table for use by NCRAdjustDynamicClaims
+;
+ mov edx,PCR[PcNumber]
+ and _NCRProcessorIDR[edx*4],eax
+;
+; Get the PIC masks for Irql 0
+;
+ mov eax, KiI8259MaskTable[0]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_IRQ_MASK
+
+ sti
+
+ stdCall _NCRAdjustDynamicClaims
+
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halncr/i386/pcip.h b/private/ntos/nthals/halncr/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/halncr/i386/xxbiosa.asm b/private/ntos/nthals/halncr/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halncr/i386/xxbiosc.c b/private/ntos/nthals/halncr/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halncr/i386/xxdisp.c b/private/ntos/nthals/halncr/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halncr/i386/xxflshbf.c b/private/ntos/nthals/halncr/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halncr/i386/xxhal.c b/private/ntos/nthals/halncr/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxhal.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxhal.c"
diff --git a/private/ntos/nthals/halncr/i386/xxioacc.asm b/private/ntos/nthals/halncr/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halncr/i386/xxkdsup.c b/private/ntos/nthals/halncr/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halncr/i386/xxmemory.c b/private/ntos/nthals/halncr/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halncr/i386/xxstubs.c b/private/ntos/nthals/halncr/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halncr/i386/xxtime.c b/private/ntos/nthals/halncr/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halncr/makefile b/private/ntos/nthals/halncr/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halncr/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halncr/makefile.inc b/private/ntos/nthals/halncr/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halncr/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halncr/sources b/private/ntos/nthals/halncr/sources
new file mode 100644
index 000000000..34be96362
--- /dev/null
+++ b/private/ntos/nthals/halncr/sources
@@ -0,0 +1,110 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halncr
+TARGETPATH=\nt\public\sdk\lib
+
+HALTYPE=MCA
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixdat.c \
+ i386\ixisabus.c \
+ i386\ixinfo.c \
+ i386\ixpcibus.c \
+ i386\ixpciint.c \
+ i386\ixpcibrd.c \
+ i386\ixsysbus.c \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixidle.asm \
+ i386\ixhwsup.c \
+ i386\ixkdcom.c \
+ i386\ixphwsup.c \
+ i386\ixprofil.asm \
+ i386\ixmcabus.c \
+ i386\ixmcasup.c \
+ i386\ixstall.asm \
+ i386\ixswint.asm \
+ i386\ixthunk.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxhal.c \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c \
+ i386\ncrclock.asm \
+ i386\ncrdetct.c \
+ i386\ncrhwsup.c \
+ i386\ncrintr.asm \
+ i386\ncripi.asm \
+ i386\ncrirql.asm \
+ i386\ncrnmi.c \
+ i386\ncrlock.asm \
+ i386\ncrsyint.asm \
+ i386\ncrstart.asm \
+ i386\ncrstop.c \
+ i386\ncrmp.c \
+ i386\ncrcatlk.asm \
+ i386\ncrcat.c \
+ i386\ncrsus.c \
+ i386\ncrioacc.asm \
+ i386\ncrmcabs.c \
+ i386\ncrqic.c \
+ i386\ncrlarc.c
+
+
+DLLDEF=obj\*\hal.def
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halncr.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halnecmp/drivesup.c b/private/ntos/nthals/halnecmp/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halnecmp/hal.rc b/private/ntos/nthals/halnecmp/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halnecmp/hal.src b/private/ntos/nthals/halnecmp/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halnecmp/makefile b/private/ntos/nthals/halnecmp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halnecmp/makefile.inc b/private/ntos/nthals/halnecmp/makefile.inc
new file mode 100644
index 000000000..71614c3fb
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/makefile.inc
@@ -0,0 +1,53 @@
+mips\allstart.c: ..\halfxs\mips\allstart.c
+
+mips\cacherr.s: ..\halfxs\mips\cacherr.s
+
+mips\jxbeep.c: ..\halfxs\mips\jxbeep.c
+
+mips\jxdmadsp.s: ..\halfxs\mips\jxdmadsp.s
+
+mips\jxenvirv.c: ..\halfxs\mips\jxenvirv.c
+
+mips\j4flshbf.s: ..\halfxs\mips\j4flshbf.s
+
+mips\j4flshio.c: ..\halfxs\mips\j4flshio.c
+
+mips\jxhwsup.c: ..\halfxs\mips\jxhwsup.c
+
+mips\jxmapio.c: ..\halfxs\mips\jxmapio.c
+
+mips\jxmaptb.c: ..\halfxs\mips\jxmaptb.c
+
+mips\jxport.c: ..\halfxs\mips\jxport.c
+
+mips\j4cache.s: ..\halfxs\mips\j4cache.s
+
+mips\j4prof.c: ..\halfxs\mips\j4prof.c
+
+mips\jxreturn.c: ..\halfxs\mips\jxreturn.c
+
+mips\jxsysint.c: ..\halfxs\mips\jxsysint.c
+
+mips\jxtime.c: ..\halfxs\mips\jxtime.c
+
+mips\jxusage.c: ..\halfxs\mips\jxusage.c
+
+mips\x4clock.s: ..\halfxs\mips\x4clock.s
+
+mips\xxcalstl.c: ..\halfxs\mips\xxcalstl.c
+
+mips\xxinitnt.c: ..\halfxs\mips\xxinitnt.c
+
+mips\xxinithl.c: ..\halfxs\mips\xxinithl.c
+
+mips\xxipiint.s: ..\halfxs\mips\xxipiint.s
+
+mips\x4tb.s: ..\halfxs\mips\x4tb.s
+
+mips\x86bios.c: ..\halfxs\mips\x86bios.c
+
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halnecmp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halnecmp/mips/allstart.c b/private/ntos/nthals/halnecmp/mips/allstart.c
new file mode 100644
index 000000000..26556a5c7
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/allstart.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\allstart.c"
diff --git a/private/ntos/nthals/halnecmp/mips/cacherr.s b/private/ntos/nthals/halnecmp/mips/cacherr.s
new file mode 100644
index 000000000..0b3cdf5ce
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/cacherr.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\cacherr.s"
diff --git a/private/ntos/nthals/halnecmp/mips/cirrus.h b/private/ntos/nthals/halnecmp/mips/cirrus.h
new file mode 100644
index 000000000..2a6b1e4b8
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/cirrus.h
@@ -0,0 +1,294 @@
+#ident "@(#) NEC cirrus.h 1.1 94/10/29 03:39:40"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.7 94/02/03 18:58:17" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.6 94/01/28 11:50:02" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.4 93/10/29 12:25:02" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cirrus.h
+
+Abstract:
+
+ This module contains the definitions for the code that implements the
+ Cirrus Logic VGA 6410/6420/542x device driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Miniport Driver Interface
+ *
+ *
+ * #if defined(DBCS) && defined(_MIPS_)
+ * M002 1994.2.2 A. Kuriyama @ oa2
+ * - Bug fix
+ *
+ * Modify : Video Memory Physical Address
+ * #endif // DBCS && _MIPS_
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ * L002 1993.10.21 Kuroki
+ *
+ * - Warniing clear
+ *
+ *
+ */
+
+//
+// Change Ushort to Uchar, because R96 is mips machine.
+//
+
+
+//
+// Base address of VGA memory range. Also used as base address of VGA
+// memory when loading a font, which is done with the VGA mapped at A0000.
+//
+
+/* START L001 */
+
+#if defined(DBCS) && defined(_MIPS_)
+/* START M002 */
+// If LA_MASK value is 0xE, when you access SCSI Device, VGA device also responce.
+// So LA_MASK value change 0x1 to 0xE.
+#define LA_MASK 0xE
+/* END M002 */
+#endif // DBCS && _MIPS_
+#define MEM_VGA (LA_MASK << 20)
+#define MEM_VGA_SIZE 0x100000
+
+/* END L001 */
+
+//
+// Port definitions for filling the ACCSES_RANGES structure in the miniport
+// information, defines the range of I/O ports the VGA spans.
+// There is a break in the IO ports - a few ports are used for the parallel
+// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped
+// so all VGA ports are in one address range.
+//
+
+#define VGA_BASE_IO_PORT 0x000003B0
+#define VGA_START_BREAK_PORT 0x000003BB
+#define VGA_END_BREAK_PORT 0x000003C0
+#define VGA_MAX_IO_PORT 0x000003DF
+
+//
+// VGA port-related definitions.
+//
+
+//
+// VGA register definitions
+//
+ // ports in monochrome mode
+#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and
+#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode
+#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port
+ // in mono mode
+#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read
+ // port in mono mode
+#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO
+ // Register to read to reset
+ // Attribute Controller index/data
+#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and
+#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port
+ // for writes, but only Address is
+ // readable at 0x010
+#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is
+ // readable here
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write
+ // port
+#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read
+ // port
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the
+ // entire VGA subsystem
+#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and
+#define SEQ_DATA_PORT 0x0015 // Data registers
+#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg
+#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg,
+ // write-only
+#define DAC_STATE_PORT 0x0017 // DAC state (read/write),
+ // read-only
+#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg
+#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg
+#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port
+#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read
+ // port
+#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address
+#define GRAPH_DATA_PORT 0x001F // and Data registers
+
+ // ports in color mode
+#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and
+#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode
+#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port
+#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read
+ // port in color mode
+#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR
+ // Register to read to reset
+ // Attribute Controller index/data
+ // toggle in color mode
+
+//
+// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed
+// VGA registers.
+//
+
+#define CRTC_ADDRESS_MONO_OFFSET 0x04
+#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A
+#define ATT_ADDRESS_OFFSET 0x10
+#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12
+#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13
+#define SEQ_ADDRESS_OFFSET 0x14
+#define DAC_PIXEL_MASK_OFFSET 0x16
+#define DAC_STATE_OFFSET 0x17
+#define DAC_ADDRESS_WRITE_OFFSET 0x18
+#define GRAPH_ADDRESS_OFFSET 0x1E
+#define CRTC_ADDRESS_COLOR_OFFSET 0x24
+#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A
+
+// toggle in color mode
+//
+// VGA indexed register indexes.
+//
+
+// CL-GD542x specific registers:
+//
+#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts
+#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad
+#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register
+//
+#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start
+#define IND_CURSOR_END 0x0B // and End registers
+#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location
+#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers
+#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync
+ // End register, which has the bit
+ // that protects/unprotects CRTC
+ // index registers 0-7
+#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC
+#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC
+#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr
+#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr
+#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr
+#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr
+#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq
+#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer
+#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq
+#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in
+ // CRTC
+#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg
+ // in CRTC
+#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start
+ // synchronous reset
+#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end
+ // synchronous reset
+
+//
+// Values for Attribute Controller Index register to turn video off
+// and on, by setting bit 5 to 0 (off) or 1 (on).
+//
+
+#define VIDEO_DISABLE 0
+#define VIDEO_ENABLE 0x20
+
+// Masks to keep only the significant bits of the Graphics Controller and
+// Sequencer Address registers. Masking is necessary because some VGAs, such
+// as S3-based ones, don't return unused bits set to 0, and some SVGAs use
+// these bits if extensions are enabled.
+//
+
+#define GRAPH_ADDR_MASK 0x0F
+#define SEQ_ADDR_MASK 0x07
+
+//
+// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register.
+//
+
+#define CHAIN4_MASK 0x08
+
+//
+// Value written to the Read Map register when identifying the existence of
+// a VGA in VgaInitialize. This value must be different from the final test
+// value written to the Bit Mask in that routine.
+//
+
+#define READ_MAP_TEST_SETTING 0x03
+
+//
+// Default text mode setting for various registers, used to restore their
+// states if VGA detection fails after they've been modified.
+//
+
+#define MEMORY_MODE_TEXT_DEFAULT 0x02
+#define BIT_MASK_DEFAULT 0xFF
+#define READ_MAP_DEFAULT 0x00
+
+
+//
+// Palette-related info.
+//
+
+//
+// Highest valid DAC color register index.
+//
+
+#define VIDEO_MAX_COLOR_REGISTER 0xFF
+
+//
+// Indices for type of memory mapping; used in ModesVGA[], must match
+// MemoryMap[].
+//
+
+typedef enum _VIDEO_MEMORY_MAP {
+ MemMap_Mono,
+ MemMap_CGA,
+ MemMap_VGA
+} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP;
+
+//
+// For a mode, the type of banking supported. Controls the information
+// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking.
+//
+
+typedef enum _BANK_TYPE {
+ NoBanking = 0,
+ NormalBanking,
+ PlanarHCBanking
+} BANK_TYPE, *PBANK_TYPE;
+
+#define CL6410 0x0001
+#define CL6420 0x0002
+#define CL542x 0x0004
+
+// bitfields for the DisplayType
+#define crt 0x0001
+#define panel 0x0002
+#define simulscan 0x0004 // this means both, but is unused for now.
diff --git a/private/ntos/nthals/halnecmp/mips/cmdcnst.h b/private/ntos/nthals/halnecmp/mips/cmdcnst.h
new file mode 100644
index 000000000..ea2bba221
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/cmdcnst.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdcnst.h
+
+Abstract:
+
+ This is the command string interpreter definitions
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ This module is same file on Cirrus Minport Driver.
+
+Revision History:
+
+--*/
+
+//--------------------------------------------------------------------------
+// Definition of the set/clear mode command language.
+//
+// Each command is composed of a major portion and a minor portion.
+// The major portion of a command can be found in the most significant
+// nibble of a command byte, while the minor portion is in the least
+// significant portion of a command byte.
+//
+// maj minor Description
+// ---- ----- --------------------------------------------
+// 00 End of data
+//
+// 10 in and out type commands as described by flags
+// flags:
+//
+// xxxx
+// ||||
+// |||+-------- unused
+// ||+--------- 0/1 single/multiple values to output (in's are always
+// |+---------- 0/1 8/16 bit operation single)
+// +----------- 0/1 out/in instruction
+//
+// Outs
+// ----------------------------------------------
+// 0 reg:W val:B
+// 2 reg:W cnt:W val1:B val2:B...valN:B
+// 4 reg:W val:W
+// 6 reg:W cnt:W val1:W val2:W...valN:W
+//
+// Ins
+// ----------------------------------------------
+// 8 reg:W
+// a reg:W cnt:W
+// c reg:W
+// e reg:W cnt:W
+//
+// 20 Special purpose outs
+// 00 do indexed outs for seq, crtc, and gdc
+// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 01 do indexed outs for atc
+// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 02 do masked outs
+// indexreg:W andmask:B xormask:B
+//
+// F0 Nop
+//
+//---------------------------------------------------------------------------
+
+// some useful equates - major commands
+
+#define EOD 0x000 // end of data
+#define INOUT 0x010 // do ins or outs
+#define METAOUT 0x020 // do special types of outs
+#define NCMD 0x0f0 // Nop command
+
+
+// flags for INOUT major command
+
+//#define UNUSED 0x01 // reserved
+#define MULTI 0x02 // multiple or single outs
+#define BW 0x04 // byte/word size of operation
+#define IO 0x08 // out/in instruction
+
+// minor commands for metout
+
+#define INDXOUT 0x00 // do indexed outs
+#define ATCOUT 0x01 // do indexed outs for atc
+#define MASKOUT 0x02 // do masked outs using and-xor masks
+
+
+// composite inout type commands
+
+#define OB (INOUT) // output 8 bit value
+#define OBM (INOUT+MULTI) // output multiple bytes
+#define OW (INOUT+BW) // output single word value
+#define OWM (INOUT+BW+MULTI) // output multiple words
+
+#define IB (INOUT+IO) // input byte
+#define IBM (INOUT+IO+MULTI) // input multiple bytes
+#define IW (INOUT+IO+BW) // input word
+#define IWM (INOUT+IO+BW+MULTI) // input multiple words
diff --git a/private/ntos/nthals/halnecmp/mips/halp.h b/private/ntos/nthals/halnecmp/mips/halp.h
new file mode 100644
index 000000000..2f89bf746
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/halp.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\halp.h"
diff --git a/private/ntos/nthals/halnecmp/mips/j4cache.s b/private/ntos/nthals/halnecmp/mips/j4cache.s
new file mode 100644
index 000000000..0f17e43bf
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/j4cache.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4cache.s"
diff --git a/private/ntos/nthals/halnecmp/mips/j4flshbf.s b/private/ntos/nthals/halnecmp/mips/j4flshbf.s
new file mode 100644
index 000000000..04012b70b
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/j4flshbf.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshbf.s"
diff --git a/private/ntos/nthals/halnecmp/mips/j4flshio.c b/private/ntos/nthals/halnecmp/mips/j4flshio.c
new file mode 100644
index 000000000..d608140c2
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/j4flshio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshio.c"
diff --git a/private/ntos/nthals/halnecmp/mips/j4prof.c b/private/ntos/nthals/halnecmp/mips/j4prof.c
new file mode 100644
index 000000000..dd8c2b7c9
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/j4prof.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4prof.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxbeep.c b/private/ntos/nthals/halnecmp/mips/jxbeep.c
new file mode 100644
index 000000000..173ea259e
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxbeep.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxbeep.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxdisp.c b/private/ntos/nthals/halnecmp/mips/jxdisp.c
new file mode 100644
index 000000000..4c1a138a4
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxdisp.c
@@ -0,0 +1,2589 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.10 93/12/01 12:18:22" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.9 93/11/19 13:48:37" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.7 93/11/18 14:57:07" ) */
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+History:
+
+--*/
+
+/*
+ * M001 1993.10.28 A. Kuriyama@oa2
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Add : Initialize routine for Cirrus CL5428.
+ *
+ * Notes : HalpCirrusInterpretCmdStream() based on VgaInterpretCmdStream()
+ * in Cirrus Miniport Driver.
+ *
+ * M002 1993.11.10 M. Kusano
+ *
+ * - initialize bug fixed
+ *
+ * Add : Color palette initialize sequence.
+ *
+ * - scroll bug fixed
+ *
+ * Add : 32bit Move Memory routine.
+ *
+ * M003 1993.11.18 A. Kuriyama@oa2
+ *
+ * - Exchanged HalpMoveMemory32()
+ *
+ * Add : HalpMoveMemory32()
+ *
+ * M004 1993.11.18 M. Kusano
+ *
+ * - Modefy HalpMoveMemory32()
+ *
+ * Bug fix
+ *
+ *
+ * M005 1993.11.30 M.Kusano
+ *
+ * - Modefy Display Identifier
+ * Cirrus GD5428 -> necvdfrb
+ *
+ * #if defined(DBCS) && defined(_MIPS_)
+ *
+ * M006 1994.10.29 T.Samezima
+ *
+ * - Add display mode on vga
+ *
+ * #endif // DBCS && _MIPS_
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 in Miniport Driver
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ * M007 1994.11.25 A.Kuriyama
+ *
+ * - Bug fix for FW 1024x768(44Hz)
+ *
+ *
+ */
+
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+/* START M001 */
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+/* END M001 */
+#include "string.h"
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayG364Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayVxlSetup (
+ VOID
+ );
+
+/* START M001 */
+VOID
+HalpDisplayCirrusSetup (
+ VOID
+ );
+
+BOOLEAN
+HalpCirrusInterpretCmdStream (
+ PUSHORT pusCmdStream
+ );
+/* END M001 */
+
+/* START M002 */
+VOID
+Write_Dbg_Uchar(
+PUCHAR,
+UCHAR
+);
+/* END M002 */
+
+/* START M003 */
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+);
+/* END M003 */
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+#define G300_VIDEO_CONTROL ((PG300_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_CONTROL ((PG364_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_RESET ((PVIDEO_REGISTER)0x403fe000)
+
+//
+// Define memory access constants for VXL
+//
+
+#define VXL_VIDEO_MEMORY_BASE 0x40000000
+#define BT484_BASE ((PBT484_REGISTERS)0x403fd000)
+#define CLOCK_BASE ((PUCHAR)0x403fe000)
+#define JAGUAR_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+/* START M001 */
+#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+#define CIRRUS_OFFSET ((PUSHORT)0x3b0)
+/* END M001 */
+//
+// The three type of g364 boards we support
+//
+
+#define JAZZG364 1
+#define MIPSG364 2
+#define OLIVETTIG364 3
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayResetRegisterBase = 0;
+ULONG HalpDisplayVxlClockRegisterBase = 0;
+ULONG HalpDisplayVxlBt484RegisterBase = 0;
+ULONG HalpDisplayVxlJaguarRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpG364Type = 0;
+/* START M001 */
+LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0};
+/* END M001 */
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ENTRYLO SavedPte;
+ ULONG StartingPfn;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("HalpInitializeDisplay0\n");
+#endif
+ /* END M002 */
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("ConfigurationEntry Found\n");
+#endif
+ /* END M002 */
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G300")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG300Setup;
+
+ HalpDisplayControlBase =
+ ((PJAZZ_G300_CONFIGURATION_DATA)
+ (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = JAZZG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Mips G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = MIPSG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "OLIVETTI_G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = OLIVETTIG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "VXL")) {
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("VXL config found\n");
+#endif
+ /* END M002 */
+ HalpDisplayControllerSetup = HalpDisplayVxlSetup;
+ HalpDisplayVxlBt484RegisterBase = 0x60100000;
+ HalpDisplayVxlClockRegisterBase = 0x60200000;
+ HalpDisplayVxlJaguarRegisterBase = 0x60300000;
+
+ /* START M001 */
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "necvdfrb")) { /* M005 */
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("necvdfrb Config found\n"); /* M005 */
+#endif
+ /* END M002 */
+
+ HalpDisplayControllerSetup = HalpDisplayCirrusSetup;
+ HalpDisplayControlBase = 0x90000000;
+ /* END M001 */
+
+ } else {
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("DisplayTypeUnknown\n");
+#endif
+ /* END M002 */
+
+ HalpDisplayTypeUnknown = TRUE;
+ }
+
+ /* START M001 */
+ }
+ /* END M001 */
+ }
+ }
+ }
+ }
+
+ Child = ConfigurationEntry->Child;
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("parameters read start\n");
+#endif
+ /* END M002 */
+
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ /* START M002 */
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpScrollLine =
+ 1024 * HalpCharacterHeight;
+ }else{
+ /* END M002 */
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+
+ /* START M002 */
+ }
+ /* END M002 */
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ /* START M002 */
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpDisplayWidth =
+ 1024 / HalpCharacterWidth;
+
+ }else{
+ /* END M002 */
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+ /* START M002 */
+ }
+ /* END M002 */
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("Mem get \n");
+#endif
+ /* END M002 */
+
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ /* START M001 */
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = MEM_VGA;
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+ else {
+ /* END M001 */
+
+ Pte.PFN = VIDEO_MEMORY_BASE >> PAGE_SHIFT;
+
+ /* START M001 */
+ }
+ /* END M001 */
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayVxlSetup) {
+
+ //
+ // If this is VXL then map a page for the
+ // brooktree base
+ // Clock base
+ // jaguar base
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlBt484RegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 2) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlClockRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlJaguarRegisterBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+
+ } else {
+
+ //
+ // If we have a G364, use the page before last to map the reset register.
+ //
+
+ if (HalpDisplayControllerSetup == HalpDisplayG364Setup) {
+ Pte.PFN = ((ULONG)HalpDisplayResetRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+ }
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+
+ //
+ // Unmap video memory that was temporily mapped during initialization.
+ //
+
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+ KeFlushCurrentTb();
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G300B display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG BackPorch;
+ PULONG Buffer;
+ ULONG DataLong;
+ ULONG FrontPorch;
+ ULONG HalfLineTime;
+ ULONG HalfSync;
+ ULONG Index;
+ ULONG Limit;
+ ULONG MultiplierValue;
+ ULONG ScreenUnitRate;
+ ULONG VerticalBlank;
+ ULONG ShortDisplay;
+ ULONG TransferDelay;
+
+ //
+ // Disable the G300B display controller.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Initialize the G300B boot register value.
+ //
+
+ ScreenUnitRate =
+ (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ MultiplierValue = 125000 / (ScreenUnitRate / 4);
+ DataLong = 0;
+ ((PG300_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue;
+ ((PG300_VIDEO_BOOT)(&DataLong))->ClockSelect = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Boot.Long, DataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G300B operational values.
+ //
+
+ HalfSync =
+ (HalpMonitorConfigurationData.HorizontalSync * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->HorizonalSync.Long, HalfSync);
+
+ BackPorch =
+ (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / ScreenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BackPorch.Long, BackPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ HalfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineTime.Long, HalfLineTime * 2);
+ FrontPorch =
+ (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) / ScreenUnitRate;
+
+ ShortDisplay = HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ShortDisplay.Long, ShortDisplay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BroadPulse.Long,
+ HalfLineTime - FrontPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ VerticalBlank = (HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalBackPorch -
+ (HalpMonitorConfigurationData.VerticalSync * 2)) * 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalBlank.Long,
+ VerticalBlank);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineStart.Long, LINE_START_VALUE);
+ if (BackPorch < ShortDisplay) {
+ TransferDelay = BackPorch - 1;
+ } else {
+ TransferDelay = ShortDisplay - 1;
+ }
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->TransferDelay.Long, TransferDelay);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - TransferDelay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->PixelMask.Long, G300_PIXEL_MASK_VALUE);
+
+ //
+ // Initialize the G300B control parameters.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->SeparateSync = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G300_DELAY_SYNC_CYCLES;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BlankOutput = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->AddressStep = 2;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Set up the color map for two colors.
+ //
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[1], 0x900000);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpDisplayG364Setup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G364 display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG videoClock;
+ ULONG videoPeriod;
+ ULONG backPorch;
+ ULONG dataLong;
+ ULONG frontPorch;
+ ULONG halfLineTime;
+ ULONG halfSync;
+ PULONG buffer;
+ ULONG index;
+ ULONG limit;
+ ULONG multiplierValue;
+ ULONG screenUnitRate;
+ ULONG shortDisplay;
+ ULONG transferDelay;
+ ULONG verticalBlank;
+
+ //
+ // Reset the G364 display controller.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_RESET->Long,
+ 0);
+
+ //
+ // Initialize the G364 boot register value.
+ //
+
+ if (HalpG364Type == MIPSG364) {
+
+ videoClock = 5000000;
+
+ } else {
+
+ videoClock = 8000000;
+
+ }
+
+ videoPeriod = 1000000000 / (videoClock / 1000);
+
+ screenUnitRate = (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ multiplierValue = videoPeriod / (screenUnitRate / 4);
+ dataLong = 0;
+ ((PG364_VIDEO_BOOT)(&dataLong))->Multiplier = multiplierValue;
+ ((PG364_VIDEO_BOOT)(&dataLong))->ClockSelect = 1;
+ ((PG364_VIDEO_BOOT)(&dataLong))->MicroPort64Bits = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Boot.Long,
+ dataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G364 control parameters.
+ //
+
+ dataLong = 0;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DelaySync = G364_DELAY_SYNC_CYCLES;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->AddressStep = G364_ADDRESS_STEP_INCREMENT;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DisableCursor = 1;
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize the G364 control parameters for VDR1 with patch for HSync
+ // problem during the VBlank. The control register is set to 0xB03041
+ // according to the hardware specs. @msu, Olivetti, 5/14/92
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->VideoOnly = 1;
+
+ } else {
+
+ //
+ // Only set tesselated sync in non-olivetti G364 cards when
+ // vertical frontporch is set to 1
+ //
+
+ if (HalpMonitorConfigurationData.VerticalFrontPorch != 1) {
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->PlainSync = 1;
+ }
+
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Initialize the G364 operational values.
+ //
+
+ halfSync = (HalpMonitorConfigurationData.HorizontalSync * 1000) / screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->HorizontalSync.Long,
+ halfSync);
+
+ backPorch = (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / screenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BackPorch.Long,
+ backPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ halfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) /
+ screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineTime.Long,
+ halfLineTime * 2);
+
+ frontPorch = (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) /
+ screenUnitRate;
+
+ shortDisplay = halfLineTime - ((halfSync * 2) + backPorch + frontPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ShortDisplay.Long,
+ shortDisplay);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize Broad Pulse, Vertical PreEqualize and Vertical
+ // PostEqualize registers to work with Olivetti monitors.
+ // @msu, Olivetti, 5/14/92
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ 0x30);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ } else {
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ halfLineTime - frontPorch);
+
+ // NOTE: changed the order to simplify if statement .
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ HalpMonitorConfigurationData.VerticalFrontPorch * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ }
+
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ verticalBlank = (HalpMonitorConfigurationData.VerticalBackPorch - 1) * 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalBlank.Long,
+ verticalBlank);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineStart.Long,
+ LINE_START_VALUE);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Fixes for Olivetti monitors, @msu, Olivetti
+ //
+
+ transferDelay = 30; // @msu
+
+ } else {
+
+ if (backPorch < shortDisplay) {
+ transferDelay = backPorch - 1;
+ } else {
+ transferDelay = shortDisplay - 4;
+ }
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->TransferDelay.Long,
+ transferDelay);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - transferDelay);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->PixelMask.Long,
+ 0xFFFFFF);
+
+ //
+ // Enable video
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->EnableVideo = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Set up the color map for two colors.
+ // NOTE: this device is not RGB but BGR.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[1], 0x000090);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)VIDEO_MEMORY_BASE;
+ limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpDisplayVxlSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the JazzVxl Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ UCHAR DataChar;
+ UCHAR CmdReg0;
+ ULONG Status;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+
+
+ //
+ // Define clock value for the ICS part (pS)
+ //
+
+ LONG ClockResList[32] = { 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4,42918,40984,38760,36724,33523,31017,
+ 29197,27548,24882,23491,22482,21468,20509,19920,
+ 18692,18054,16722,15015,14773,14053,13040, 4};
+
+ JAGUAR_REG_INIT JagInitData;
+
+ LONG HorDisplayTime;
+ LONG HorResolutionDiv;
+ LONG RequestedClockPeriod;
+ LONG CurrentClockError;
+ LONG MinErrorValue;
+ USHORT MinErrorIndex;
+ LONG ShiftClockPeriod;
+
+ USHORT BoardTypeBt485;
+
+
+
+ //
+ // Determine if this is a Bt484 or Bt485 board. To do this write a 1 to command
+ // register bit 07 then write 01 to the address register 0. This will enable
+ // read/writes to command register 3 on a Bt485 but not on a Bt484. Clear
+ // Command register 3 then read it back. On a Bt485 the return value will be 0x00,
+ // on a Bt484 it will be 0x40.
+ //
+ // Get the value in command register 0, then set bit 07
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Command0.Byte);
+ DataChar |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,DataChar);
+
+ //
+ // Write 0x01 to the address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Clear command register 3
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,0x00);
+
+ //
+ // Read Command Register 3 back and compare
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Status.Byte);
+
+ if (DataChar != 0x00) {
+
+ //
+ // This is a Bt484
+ //
+
+ BoardTypeBt485 = 0;
+ JagInitData.Bt485Multiply = 0;
+
+ } else {
+
+ //
+ // This is a Bt485
+ //
+
+ BoardTypeBt485 = 1;
+ JagInitData.Bt485Multiply = 0;
+ }
+
+ //
+ // Calculate the requested clock frequency then find the closest match in the
+ // ICS clock frequency table. The requested clock frequency in picoseconds =
+ //
+ // Horizontal display time * 1000000
+ // ---------------------------------
+ // horizontal resolution
+ //
+ //
+
+ HorDisplayTime = HalpMonitorConfigurationData.HorizontalDisplayTime * 1000;
+ HorResolutionDiv = HalpMonitorConfigurationData.HorizontalResolution;
+ RequestedClockPeriod = HorDisplayTime / HorResolutionDiv;
+
+ //
+ // Check for a Bt485 frequency
+ //
+
+ if ((BoardTypeBt485 == 1) && (RequestedClockPeriod < ClockResList[30])) {
+ RequestedClockPeriod = RequestedClockPeriod * 2;
+ JagInitData.Bt485Multiply = 1;
+ }
+
+ MinErrorIndex = 0;
+
+ //
+ // Gaurentee a maximum starting error
+ //
+
+ MinErrorValue = RequestedClockPeriod + 1;
+ for (Index = 0; Index < 32; Index++) {
+
+ //
+ // Calculate the absolute value of clock error and find the
+ // closest match in the array of clock values
+ //
+
+ CurrentClockError = RequestedClockPeriod - ClockResList[Index];
+ if (CurrentClockError < 0) {
+ CurrentClockError *= -1;
+ }
+
+ if (CurrentClockError < MinErrorValue) {
+ MinErrorValue = CurrentClockError;
+ MinErrorIndex = (USHORT)Index;
+ }
+ }
+
+ //
+ // We now have a closest match in the clock array, now calculate the
+ // values for the Bt484/Bt485 register values
+ //
+
+ JagInitData.ClockFreq = (UCHAR)MinErrorIndex;
+ JagInitData.BitBltControl = 1;
+ JagInitData.TopOfScreen = 0;
+ JagInitData.XferLength = 0x200;
+ JagInitData.VerticalInterruptLine = 4;
+ JagInitData.HorizontalDisplay = HalpMonitorConfigurationData.HorizontalResolution;
+
+ //
+ // All jaguar timing values are based on the brooktree shift clock value which
+ // is the clock frequency divided by 4. (period * 4) If this is a Bt485 using
+ // its internal 2x clock multiplier than is is period * 2; (freq * 2 / 4)
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 2;
+ } else {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 4;
+ }
+
+ JagInitData.HorizontalBlank = (USHORT)(((HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod);
+
+ JagInitData.HorizontalBeginSync = (USHORT)((HalpMonitorConfigurationData.HorizontalFrontPorch * 1000)
+ / ShiftClockPeriod);
+
+ JagInitData.HorizontalEndSync = (USHORT)(((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod);
+
+ JagInitData.HorizontalLine = JagInitData.HorizontalBlank +
+ (HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ JagInitData.VerticalBlank = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalBeginSync = HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalEndSync = HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalSync;
+
+ JagInitData.VerticalLine = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalResolution;
+
+ //
+ // Start ICS Clock pll and stabilize.
+ //
+
+ WRITE_REGISTER_UCHAR(CLOCK_BASE,JagInitData.ClockFreq);
+
+ //
+ // Wait 10 uS for PLL clock to stabilize on the video board
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+
+ //
+ // Initialize Bt484 Command Register 0 to:
+ //
+ // 8 Bit DAC Resolution
+ //
+
+ CmdReg0 = 0;
+ ((PBT484_COMMAND0)(&CmdReg0))->DacResolution = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->GreenSyncEnable = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->SetupEnable = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Initialize Command Register 1 to:
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND1)(&DataChar))->BitsPerPixel = VXL_EIGHT_BITS_PER_PIXEL;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command1.Byte,DataChar);
+
+ //
+ // Initialize Command Register 2 to:
+ //
+ // SCLK Enabled
+ // TestMode disabled
+ // PortselMask Non Masked
+ // PCLK 1
+ // NonInterlaced
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND2)(&DataChar))->SclkDisable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->TestEnable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PortselMask = 1;
+ ((PBT484_COMMAND2)(&DataChar))->PclkSelect = 1;
+ ((PBT484_COMMAND2)(&DataChar))->InterlacedDisplay = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PaletteIndexing = CONTIGUOUS_PALETTE;
+ ((PBT484_COMMAND2)(&DataChar))->CursorMode = BT_CURSOR_WINDOWS;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command2.Byte,DataChar);
+
+ //
+ // if JagInitData.ClockFreq bit 8 is set then this is a Bt485 mode that requires
+ // the internal 2x clock multiplier to be enabled.
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+
+ //
+ // To access cmd register 3, first set bit CR17 in command register 0
+ //
+
+ CmdReg0 |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Write a 0x01 to Address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Write to cmd register 3 in the status register location. Cmd3 is initialized
+ // to turn on the 2x clock multiplier.
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND3)(&DataChar))->ClockMultiplier = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,DataChar);
+
+ //
+ // Allow 10 uS for the 2x multiplier to stabilize
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+ }
+
+ //
+ // Initialize Color Palette. Only init the first 2 entries
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+
+ //
+ // Entry 0 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 1 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x90);
+
+ //
+ // Initialize Cursor and Overscan color.
+ //
+ // Set address pointer base.
+ // Zero 4 entries.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColorWrAddress.Byte,0);
+ for (Index = 0; Index < 4*3; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColor.Byte,0);
+ }
+
+ //
+ // Initialize cursor RAM
+ //
+ // Set address pointer to base of ram.
+ // Clear both planes
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+ for (Index = 0; Index < 256; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorRam.Byte,0);
+ }
+
+ //
+ // Initialize cursor position registers--cursor off.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXHigh.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYHigh.Byte,0);
+
+ //
+ // Initialize pixel mask.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PixelMask.Byte,0xFF);
+
+ //
+ // Init Jaguar Registers
+ //
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->TopOfScreen.Short,
+ JagInitData.TopOfScreen);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBlank.Short,
+ JagInitData.HorizontalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBeginSync.Short,
+ JagInitData.HorizontalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalEndSync.Short,
+ JagInitData.HorizontalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalLine.Short,
+ JagInitData.HorizontalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBlank.Short,
+ JagInitData.VerticalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBeginSync.Short,
+ JagInitData.VerticalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalEndSync.Short,
+ JagInitData.VerticalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalLine.Short,
+ JagInitData.VerticalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->XferLength.Short,
+ JagInitData.XferLength);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalInterruptLine.Short,
+ JagInitData.VerticalInterruptLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalDisplay.Short,
+ JagInitData.HorizontalDisplay);
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->BitBltControl.Byte,
+ JagInitData.BitBltControl);
+
+ //
+ // Enable timing.
+ //
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->MonitorControl,MONITOR_TIMING_ENABLE);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VXL_VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+/* START M001 */
+VOID
+HalpDisplayCirrusSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Cirrus VGA display controlleer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG dac_address, dac_reg;
+
+#if defined(DBCS) && defined(_MIPS_)
+ // M006 vvv
+ ULONG verticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+ if( verticalFrequency < 66 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 72Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 800:
+ if( verticalFrequency < 58 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 56Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_56);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 66 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 72Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 1024:
+
+ // M007 start
+ if( verticalFrequency < 47 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 87Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if ( verticalFrequency < 65) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 70Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ // M007 end
+ break;
+ default:
+ return;
+ }
+ // M006 ^^^
+#else // defined(DBCS) && defined(_MIPS_)
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("640x480 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_640x480_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 800:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("800x600 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_800x600_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 1024:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("1024x768 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_1024x768_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ default:
+ return;
+ }
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("color set\n");
+#endif
+
+ dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT;
+ dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT;
+
+
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0);
+
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2));
+ /* END M002 */
+
+ //
+ // Set the video memory to address color one.
+ //
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+// Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+// HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+ /* START M002 */
+ Limit = (1024 *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+ /* END M002 */
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+BOOLEAN
+HalpCirrusInterpretCmdStream(
+ PUSHORT pusCmdStream
+ )
+
+/*++
+
+Routine Description:
+
+ Interprets the appropriate command array to set up VGA registers for the
+ requested mode. Typically used to set the VGA into a particular mode by
+ programming all of the registers
+
+Arguments:
+
+
+ pusCmdStream - array of commands to be interpreted.
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+Revision History:
+--*/
+
+
+
+{
+ ULONG ulCmd;
+ ULONG ulPort;
+ UCHAR jValue;
+ USHORT usValue;
+ ULONG culCount;
+ ULONG ulIndex;
+ ULONG ulBase;
+ if (pusCmdStream == NULL) {
+
+ return TRUE;
+ }
+
+ ulBase = (ULONG)CIRRUS_BASE+0x3b0;
+
+ //
+ // Now set the adapter to the desired mode.
+ //
+
+ while ((ulCmd = *pusCmdStream++) != EOD) {
+
+ //
+ // Determine major command type
+ //
+
+ switch (ulCmd & 0xF0) {
+
+ //
+ // Basic input/output command
+ //
+
+ case INOUT:
+
+ //
+ // Determine type of inout instruction
+ //
+
+ if (!(ulCmd & IO)) {
+
+ //
+ // Out instruction. Single or multiple outs?
+ //
+
+ if (!(ulCmd & MULTI)) {
+
+ //
+ // Single out. Byte or word out?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // Single byte out
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort),
+ jValue);
+ /* END M002 */
+
+
+ } else {
+
+ //
+ // Single word out
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff));
+ /* END M002 */
+
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8));
+ /* END M002 */
+
+
+ }
+
+ } else {
+
+ //
+ // Output a string of values
+ // Byte or word outs?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // String byte outs. Do in a loop; can't use
+ // VideoPortWritePortBufferUchar because the data
+ // is in USHORT form
+ //
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+
+ while (culCount--) {
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ jValue);
+ /* END M002 */
+
+
+ }
+
+ } else {
+
+ //
+ // String word outs
+ //
+
+ ulPort = *pusCmdStream++;
+ culCount = *pusCmdStream++;
+//
+// Buffering out is not use on the Miniport Driver for R96 machine.
+//
+
+ /* START L001 */
+
+ while(culCount--)
+ {
+ usValue = *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort), (UCHAR) (usValue & 0x00ff));
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort+1), (UCHAR) (usValue >> 8));
+ /* END M002 */
+
+ }
+
+ /* END L001 */
+ }
+ }
+
+ } else {
+
+ // In instruction
+ //
+ // Currently, string in instructions aren't supported; all
+ // in instructions are handled as single-byte ins
+ //
+ // Byte or word in?
+ //
+
+ if (!(ulCmd & BW)) {
+ //
+ // Single byte in
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+
+ } else {
+
+ //
+ // Single word in
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = READ_REGISTER_USHORT((PUSHORT)
+ (ulBase+ulPort));
+ }
+
+ }
+
+ break;
+
+ //
+ // Higher-level input/output commands
+ //
+
+ case METAOUT:
+
+ //
+ // Determine type of metaout command, based on minor
+ // command field
+ //
+ switch (ulCmd & 0x0F) {
+
+ //
+ // Indexed outs
+ //
+
+ case INDXOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ usValue = (USHORT) (ulIndex +
+ (((ULONG)(*pusCmdStream++)) << 8));
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff));
+ /* END M002 */
+
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8));
+ /* END M002 */
+
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // Masked out (read, AND, XOR, write)
+ //
+
+ case MASKOUT:
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+ jValue &= *pusCmdStream++;
+ jValue ^= *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulBase + ulPort,
+ jValue);
+ /* END M002 */
+
+ break;
+
+ //
+ // Attribute Controller out
+ //
+
+ case ATCOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ // Write Attribute Controller index
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ (UCHAR)ulIndex);
+ /* END M002 */
+
+
+ // Write Attribute Controller data
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort, jValue);
+ /* END M002 */
+
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // None of the above; error
+ //
+ default:
+
+ return FALSE;
+
+ }
+
+
+ break;
+
+ //
+ // NOP
+ //
+
+ case NCMD:
+
+ break;
+
+ //
+ // Unknown command; error
+ //
+
+ default:
+
+ return FALSE;
+
+ }
+
+ }
+
+ return TRUE;
+
+} // end HalpCirrusInterpretCmdStream()
+/* END M001 */
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte;
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("HalDisplayString\n");
+#endif
+ /* END M002 */
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_DUO_)
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ HalpResetX86DisplayAdapter();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+#if defined(_DUO_)
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ /* START M002 */
+ HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE,
+ (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+ /* END M002 */
+
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination++ = (UCHAR)((FontValue >> 31) ^ 1);
+ FontValue <<= 1;
+ }
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ Destination +=
+ (1024 - HalpCharacterWidth);
+ }else{
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+ }
+ HalpColumn += 1;
+ return;
+}
+
+/* START M002 */
+VOID
+Write_Dbg_Uchar(
+ PUCHAR Ioadress,
+UCHAR Moji
+)
+
+{
+#if defined (R96DBG)
+ DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji);
+#endif
+ WRITE_PORT_UCHAR(Ioadress,Moji);
+}
+/* END M002 */
+
+/* START M003 */
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+ )
+
+/*++
+ Routine Description:
+
+ This function moves blocks of memory.
+
+ Arguments:
+
+ Destination - Supplies a pointer to the destination address of
+ the move operation.
+
+ Source - Supplies a pointer to the source address of the move
+ operation.
+
+ Length - Supplies the length, in bytes, of the memory to be moved.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Remainder;
+ PUCHAR Dstend; /* M004 */
+ PUCHAR Srcend; /* M004 */
+
+ if ( (Source == Destination) || (Length == 0) ) { /* M004 */
+ return;
+ }
+
+ if ((Source < Destination)&((Source + Length) > Destination)) { /* M004 vvv */
+ if((Destination - Source) > 4){
+ Remainder = (UCHAR)(Length &0x03);
+ Length = Length / 4;
+ Dstend = Destination + Length - 4 ;
+ Srcend = Source + Length -4;
+
+ for (; Length > 0; Length--) {
+ *(PULONG)(Dstend) = *(PULONG)(Srcend);
+ Dstend -= 4;
+ Srcend -= 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+ for (; Length > 0; Length--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+
+ else {
+ if( (Source - Destination) > 4 ){
+ Remainder = (UCHAR)(Length &0x03);
+ Length = Length / 4;
+ for (; Length > 0; Length--) {
+ *(PULONG)(Destination) = *(PULONG)(Source);
+ Destination += 4;
+ Source += 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ return;
+ }
+
+ for (; Length > 0; Length--) {
+ *Destination = *Source;
+ Destination++;
+ Source++; /* M004 ^^^*/
+ }
+ }
+}
+
+/* END M003 */
diff --git a/private/ntos/nthals/halnecmp/mips/jxdmadsp.s b/private/ntos/nthals/halnecmp/mips/jxdmadsp.s
new file mode 100644
index 000000000..370edd47f
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxdmadsp.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdmadsp.s"
diff --git a/private/ntos/nthals/halnecmp/mips/jxebsup.c b/private/ntos/nthals/halnecmp/mips/jxebsup.c
new file mode 100644
index 000000000..a9978da60
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxebsup.c
@@ -0,0 +1,1344 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+
+Revision History:
+
+
+--*/
+
+/*
+ * #if defined(DBCS)
+ * M001 1994.9.29 T.Katoh @ oa2
+ * - Bug fix
+ *
+ * Modify : Check ISR for IR7 and IR15 before Calling Device Driver
+ * #endif //DBCS
+ */
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+//
+// Define EISA bus interrupt affinity.
+//
+
+KAFFINITY HalpEisaBusAffinity;
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ KIRQL oldIrql;
+
+#if !defined(_DUO_)
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#else
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#endif
+
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] =
+ (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Set EISA bus interrupt affinity.
+ //
+
+ HalpEisaBusAffinity = PCR->SetMember;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+#if defined(_DUO_)
+
+ //
+ // Enable the EISA interrupts to the CPU.
+ //
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_EISA_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+
+#endif
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+#if defined(_DUO_)
+
+ PUSHORT Acknowledge = (PUSHORT)&DMA_CONTROL->EisaInterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_USHORT(Acknowledge);
+
+#else
+
+ PUCHAR Acknowledge = (PUCHAR)&DMA_CONTROL->InterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(Acknowledge);
+
+#endif
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+ if (interruptVector != 0x8000) {
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+/* Start M001 */
+#if defined(DBCS)
+
+ // When INT OutPut Pin is Low Level, CPU Carry Out INTACK Cycle. Pic is
+ // behave as if IR7 is Occured. This is a spurious interrupt!!.
+ // So Check ISR. If ISR Not 0. It is Authentic Interrupt !!
+
+ if(interruptVector == 7 || interruptVector==15){
+
+ PVOID IsrPortAddr;
+ UCHAR IsrValue;
+
+#define OCW3_READ_ISR 0x0B
+#define OCW3_READ_IRR 0x0A
+
+ //
+ // Master or Slave ?
+ //
+ IsrPortAddr = (interruptVector == 7) ?
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0:
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0;
+
+ // SetUp to ISR Regsiter
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_ISR );
+ // Read ISR Register
+ IsrValue=READ_REGISTER_UCHAR( IsrPortAddr );
+ // Resume to IRR Register
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_IRR);
+
+ if(!IsrValue){
+ // This is a spurious interrupt!!. No Call Driver.
+ goto NocallDriver;
+ }
+ }
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+NocallDriver:
+
+#else //!DBCS
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+#endif //DBCS
+/* End M001 */
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+ } else {
+ returnValue = HalHandleNMI(NULL, NULL);
+ }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT(Offset >= 0x100000);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halnecmp/mips/jxenvirv.c b/private/ntos/nthals/halnecmp/mips/jxenvirv.c
new file mode 100644
index 000000000..398a656e7
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxenvirv.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxenvirv.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxhalp.h b/private/ntos/nthals/halnecmp/mips/jxhalp.h
new file mode 100644
index 000000000..4e39adf70
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxhalp.h
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxhalp.h"
diff --git a/private/ntos/nthals/halnecmp/mips/jxhwsup.c b/private/ntos/nthals/halnecmp/mips/jxhwsup.c
new file mode 100644
index 000000000..be474375a
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxhwsup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxhwsup.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxmapio.c b/private/ntos/nthals/halnecmp/mips/jxmapio.c
new file mode 100644
index 000000000..879f96410
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxmapio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmapio.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxmaptb.c b/private/ntos/nthals/halnecmp/mips/jxmaptb.c
new file mode 100644
index 000000000..9262bc775
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxmaptb.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmaptb.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxport.c b/private/ntos/nthals/halnecmp/mips/jxport.c
new file mode 100644
index 000000000..26e310528
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxport.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxport.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxreturn.c b/private/ntos/nthals/halnecmp/mips/jxreturn.c
new file mode 100644
index 000000000..8ff827bf7
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxreturn.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxreturn.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxsysint.c b/private/ntos/nthals/halnecmp/mips/jxsysint.c
new file mode 100644
index 000000000..528753dda
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxsysint.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxsysint.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxtime.c b/private/ntos/nthals/halnecmp/mips/jxtime.c
new file mode 100644
index 000000000..996be9c3c
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxtime.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxtime.c"
diff --git a/private/ntos/nthals/halnecmp/mips/jxusage.c b/private/ntos/nthals/halnecmp/mips/jxusage.c
new file mode 100644
index 000000000..e4d8e2f52
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/jxusage.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxusage.c"
diff --git a/private/ntos/nthals/halnecmp/mips/mode542x.h b/private/ntos/nthals/halnecmp/mips/mode542x.h
new file mode 100644
index 000000000..fe986776a
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/mode542x.h
@@ -0,0 +1,1302 @@
+#ident "@(#) NEC mode542x.h 1.3 94/11/04 15:39:44"
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Mode542x.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-542x driver.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// The next set of tables are for the CL542x
+// Note: all resolutions supported
+//
+
+//
+// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode
+
+ EOD
+};
+
+//
+// 800x600 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_800x600[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode
+
+ EOD
+};
+
+//
+// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_1024x768[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ EOD
+};
+
+//-----------------------------
+// standard VGA text modes here
+// 80x25 at 640x350
+//
+//-----------------------------
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (720x400 pixel resolution; 9x16 character cell.)
+//
+
+USHORT CL542x_80x25Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (640x350 pixel resolution; 8x14 character cell.)
+//
+
+USHORT CL542x_80x25_14_Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x.
+//
+
+USHORT CL542x_1280x1024[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_64k[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 4,
+ 0x0506, // Some BIOS's set Chain Odd maps bit
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#ifdef _X86_
+
+//
+// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x.
+//
+
+USHORT CL542x_800x600_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#else
+
+//
+// NOTE(DBCS) : Update 94/09/12 - NEC Corporation
+//
+// - Add mode set command string for NEC MIPS machine.
+//
+// - 640x480 256 color 72Hz
+// - 800x600 256 color 56 / 60Hz
+// - 1024x768 256 color 70 / 45Hz
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+//
+// For MIPS NEC machine only
+//
+
+//
+// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xE3,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F,
+ 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x420E,
+ 0x2B1B,0x2F1C,0x301D,0x1F1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h)
+//
+// - Set Mode Type is VESA compatible. (Old Miss match)
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99,
+ 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+
+// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match
+// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode.
+// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B,
+// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+// 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_56[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12,
+ 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x510E,
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B,
+ 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B,0x5B0C,0x450D,0x650E,
+
+#else
+
+ 0x4A0B,0x5B0C,0x450D,0x640E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x760E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x341E,
+
+#else
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x3B0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x1A1E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_70[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x6E0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x2A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for
+// CL 542x. (Interlaced)
+//
+
+USHORT CL542x_1024x768_256_87[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x550E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x361E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99,
+ 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83,
+ 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x84,
+ 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+#endif
diff --git a/private/ntos/nthals/halnecmp/mips/modeset.h b/private/ntos/nthals/halnecmp/mips/modeset.h
new file mode 100644
index 000000000..cb923876c
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/modeset.h
@@ -0,0 +1,85 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) modeset.h 1.3 93/10/29 12:25:59" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Modeset.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-6410 and CL-6420 driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Mode structure.
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ *
+ */
+
+#include "cmdcnst.h"
+
+//---------------------------------------------------------------------------
+//
+// The actual register values for the supported modes are in chipset-specific
+// include files:
+//
+// mode64xx.h has values for CL6410 and CL6420
+// mode542x.h has values for CL5422, CL5424, and CL5426
+//
+
+
+USHORT HalpCirrus_MODESET_1K_WIDE[] = {
+ OW, // stretch scans to 1k
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x8013,
+
+ EOD
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halnecmp/mips/x4clock.s b/private/ntos/nthals/halnecmp/mips/x4clock.s
new file mode 100644
index 000000000..ce9c3a190
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/x4clock.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4clock.s"
diff --git a/private/ntos/nthals/halnecmp/mips/x4tb.s b/private/ntos/nthals/halnecmp/mips/x4tb.s
new file mode 100644
index 000000000..be37d6677
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/x4tb.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4tb.s"
diff --git a/private/ntos/nthals/halnecmp/mips/x86bios.c b/private/ntos/nthals/halnecmp/mips/x86bios.c
new file mode 100644
index 000000000..89aea8d14
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/x86bios.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x86bios.c"
diff --git a/private/ntos/nthals/halnecmp/mips/xxcalstl.c b/private/ntos/nthals/halnecmp/mips/xxcalstl.c
new file mode 100644
index 000000000..eabb7db1d
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/xxcalstl.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxcalstl.c"
diff --git a/private/ntos/nthals/halnecmp/mips/xxclock.c b/private/ntos/nthals/halnecmp/mips/xxclock.c
new file mode 100644
index 000000000..c7ec77df5
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/xxclock.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxclock.c"
diff --git a/private/ntos/nthals/halnecmp/mips/xxidle.s b/private/ntos/nthals/halnecmp/mips/xxidle.s
new file mode 100644
index 000000000..faf3163a9
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/xxidle.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxidle.s"
diff --git a/private/ntos/nthals/halnecmp/mips/xxinithl.c b/private/ntos/nthals/halnecmp/mips/xxinithl.c
new file mode 100644
index 000000000..3a49aaf9c
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/xxinithl.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinithl.c"
diff --git a/private/ntos/nthals/halnecmp/mips/xxinitnt.c b/private/ntos/nthals/halnecmp/mips/xxinitnt.c
new file mode 100644
index 000000000..2b57adb0d
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/xxinitnt.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinitnt.c"
diff --git a/private/ntos/nthals/halnecmp/mips/xxipiint.s b/private/ntos/nthals/halnecmp/mips/xxipiint.s
new file mode 100644
index 000000000..266246f51
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/mips/xxipiint.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxipiint.s"
diff --git a/private/ntos/nthals/halnecmp/sources b/private/ntos/nthals/halnecmp/sources
new file mode 100644
index 000000000..d5d46a8e6
--- /dev/null
+++ b/private/ntos/nthals/halnecmp/sources
@@ -0,0 +1,91 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+ NT_UP must be 0, because x4clock.s (profile interrupt) must be
+ assembled for multi-processor.
+
+!ENDIF
+
+NT_UP=0
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halnecmp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_DUO_ -DDBCS
+
+INCLUDES=..\x86new;..\..\inc
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILE0=$(SOURCES)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halnonme/alpha/addrsup.c b/private/ntos/nthals/halnonme/alpha/addrsup.c
new file mode 100644
index 000000000..79f2c2c30
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/addrsup.c
@@ -0,0 +1,635 @@
+/*++
+
+Copyright (c) 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the EB66 system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "nondef.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+#ifndef AXP_FIRMWARE
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+#endif
+
+#ifdef AXP_FIRMWARE
+//
+// Place the appropriate functions in the discardable text section.
+//
+
+//
+// Local function prototypes
+//
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ );
+
+#pragma alloc_text(DISTEXT, HalpTranslateSystemBusAddress)
+#pragma alloc_text(DISTEXT, HalCreateQva)
+#pragma alloc_text(DISTEXT, HalDereferenceQva)
+
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on EB66 are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+//jnfix - HAE support here
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // IMPORTANT: For now we have set HAE set to zero.
+ //
+ // MAX PCI sparse memory for us is PCI_MAX_SPARSE_MEMORY_ADDRESS=128MB-1
+ // MAX PCI dense memory for us is PCI_MAX_DENSE_MEMORY_ADDRESS=2.5GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = LCA4_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciIoPhysical();
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI sparse memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = LCA4_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciIoPhysical();
+ TranslatedAddress->QuadPart += (BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Dense space is not supported on Pass 1 LCA4s.
+ //
+
+ if( HalpLca4Revision() == Lca4Pass1 ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return FALSE;
+
+ }
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciDensePhysical();
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ //
+ // If the physical address is not in dense space then perform the
+ // QVA shuffle.
+ //
+ // N.B. - Dense space is not supported for Lca4Pass1.
+ //
+
+ if( (HalpLca4Revision() == Lca4Pass1) ||
+ (PA.QuadPart < (LONGLONG)HalpLca4PciDensePhysical()) ){
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For EB66 we have only 2 bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halnonme/alpha/adjust.c b/private/ntos/nthals/halnonme/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/allstart.c b/private/ntos/nthals/halnonme/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/alphaio.s b/private/ntos/nthals/halnonme/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/bios.c b/private/ntos/nthals/halnonme/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/busdata.c b/private/ntos/nthals/halnonme/alpha/busdata.c
new file mode 100644
index 000000000..2b83a7820
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/busdata.c
@@ -0,0 +1,126 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "nondef.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halnonme/alpha/cache.c b/private/ntos/nthals/halnonme/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/chipset.h b/private/ntos/nthals/halnonme/alpha/chipset.h
new file mode 100644
index 000000000..b5d5b44c3
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/chipset.h
@@ -0,0 +1 @@
+#include "lca4.h"
diff --git a/private/ntos/nthals/halnonme/alpha/cmos8k.c b/private/ntos/nthals/halnonme/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ebinitnt.c b/private/ntos/nthals/halnonme/alpha/ebinitnt.c
new file mode 100644
index 000000000..619794e06
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ebinitnt.c
@@ -0,0 +1,762 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a Low Cost Alpha
+ (LCA) system. Contains the VLSI 82C106, the 82357 and an EISA bus.
+
+ Orignally taken from the JENSEN hal code.
+
+Author:
+
+ Wim Colgate (DEC) 26-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Eric Rehm (DEC) 7-Jan-1994
+ Intialize PCI Bus information during Phase 1 init.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "nondef.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low (All devices except)
+// irql 4 - device high (the serial lines)
+// irql 5 - clock
+// irql 6 - real time
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11 keyboard/mouse
+// 4 serial 12 errors
+// 5 clock 13 parallel
+// 6 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// clock
+// serial
+// parallel
+// keyboard/mouse
+// pic
+
+//
+// This is the HalpIrqlMask for LCA based machines:
+// The LCA interrupt pins:
+//
+// eirq 0 NMI
+// eirq 1 PIC - 82357 interrupts
+// eirq 2 Clock
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+ADDRESS_USAGE
+NonamePCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
+ 0,0
+ }
+};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpClearInterrupts(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize the EISA and PCI interrupt controllers.
+ //
+
+ HalpInitializePCIInterrupts();
+
+ //
+ // Initialize the 21066 interrupts.
+ //
+ // N.B. - The 21066 uses the 21064 core and so the 21066 HAL
+ // uses 21064 interrupt enable/disable routines.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+ HalpEnable21064HardwareInterrupt( Irq = 0,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an LCA
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For LCA, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for LCA is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Clear any error conditions currently pending.
+ //jnfix - report correctables one day
+
+ HalpClearAllErrors( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish the error handler, to reflect the parity checking
+ //
+
+ HalpEstablishErrorHandler();
+
+ HalpRegisterAddressUsage (&NonamePCIMemorySpace);
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI Bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize the profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+
+}
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ // WRITE_REGISTER_ULONG( EPIC_HAXR1_QVA, 0 );
+ // WRITE_REGISTER_ULONG( EPIC_HAXR2_QVA, 0);
+ return;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_LCA_UNCORRECTABLE);
+ *RawSystemInfoSize = 0;
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "NoName";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_LCA_UNCORRECTABLE processorFrame;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/halnonme/alpha/ebintsup.c b/private/ntos/nthals/halnonme/alpha/ebintsup.c
new file mode 100644
index 000000000..e30156852
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ebintsup.c
@@ -0,0 +1,448 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support Noname SBC system.
+
+Author:
+
+ Robin Alexander (DEC) 13-June-1994
+ Modified from existing Avanti code.
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "nondef.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+
+//
+// Declare the interrupt handler for the PCI and ISA bus.
+//
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ ISA interrupt controller; in the case of the SIO-II in Noname, the
+ integral interrupt controller is compatible with the EISA interrupt
+ contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG PciIsaBridgeHeaderOffset;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive);
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) NonamePCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // We must declare the right form for the APECS PCI/ISA bridge
+ // configuration space device selector for use in the initialization
+ // of the interrupts.
+ //
+
+ PciIsaBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET;
+
+
+
+ //
+ // Setup the Noname interrupt assignments for the C-Step SIO; this
+ // is done with registers that are internal to the SIO-II, PIRQ0,
+ // PIRQ1, PIRQ2, and PIRQ3. They're at offsets 0x60, 0x61, 0x62,
+ // and 0x63 of the SIO-II's configuration registers. The effect
+ // of these registers is to steer the PCI interrupts into the IRQx
+ // inputs of the SIO's internal cascaded 82C59 interrupt controllers.
+ // These controllers are then programmed in their usual fashion.
+ //
+ // Set up interrupts from PCI slots 0, 1, and 2, compatible with
+ // Noname pass 1 MLB, i.e., steer the interrupt from each PCI
+ // slot or device into the default IRQL from pass 1 Noname; enable
+ // the routings.
+ //
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ0_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ10 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ1_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ15 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ2_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ9 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ //
+ // Set up interrupt from SCSI (IRQ11), and enable the routing.
+ //
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ3_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ11 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ //
+ // Select "level" operation for PCI PIRQx interrupt lines, and
+ // "edge" for ISA devices, e.g., mouse at IRQL12. Default is "edge"
+ // so no mention means "edge".
+ //
+ WRITE_REGISTER_UCHAR((PCHAR)(PCI_SPARSE_IO_BASE_QVA
+ | SIO_II_EDGE_LEVEL_CONTROL_2),
+ IRQ11_LEVEL_SENSITIVE | IRQ10_LEVEL_SENSITIVE |
+ IRQ9_LEVEL_SENSITIVE | IRQ15_LEVEL_SENSITIVE);
+
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Sio machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ return( InterruptVector );
+
+}
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halnonme/alpha/ebmapio.c b/private/ntos/nthals/halnonme/alpha/ebmapio.c
new file mode 100644
index 000000000..6f6b67159
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ebmapio.c
@@ -0,0 +1,158 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This maps I/O addresses used by the HAL on Low Cost Alpha (LCA) machines.
+
+Author:
+
+ Wim Colgate (DEC) 26-Oct-1993
+ Originally taken from the Jensen hal code.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "nondef.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a LCA based
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map the address spaces on the LCA4.
+ //
+
+ HalpLca4MapAddressSpaces();
+
+ //
+ // Map base addresses into QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( HalpLca4PciIoPhysical() );
+
+ HalpEisaControlBase = PciIoSpaceBase;;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( HalpLca4PciIntAckPhysical() );
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Map the address spaces on the LCA4.
+ //
+
+ HalpLca4MapAddressSpaces();
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)(HAL_MAKE_QVA(HalpLca4PciIoPhysical())) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halnonme/alpha/ebsgdma.c b/private/ntos/nthals/halnonme/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ebsysint.c b/private/ntos/nthals/halnonme/alpha/ebsysint.c
new file mode 100644
index 000000000..05cd33299
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ebsysint.c
@@ -0,0 +1,390 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "nondef.h"
+#include "axp21064.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR
+ //
+
+ return((BusInterruptLevel) + ISA_VECTORS);
+
+ break;
+
+
+
+ default:
+
+ //
+ // Not an interface supported on EB66/Mustang systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Avanti because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halnonme/alpha/eisasup.c b/private/ntos/nthals/halnonme/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/environ.c b/private/ntos/nthals/halnonme/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ev4cache.c b/private/ntos/nthals/halnonme/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ev4int.c b/private/ntos/nthals/halnonme/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ev4ints.s b/private/ntos/nthals/halnonme/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ev4mem.s b/private/ntos/nthals/halnonme/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ev4parit.c b/private/ntos/nthals/halnonme/alpha/ev4parit.c
new file mode 100644
index 000000000..74c6d0d00
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ev4parit.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4parit.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ev4prof.c b/private/ntos/nthals/halnonme/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/fwreturn.c b/private/ntos/nthals/halnonme/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/haldebug.c b/private/ntos/nthals/halnonme/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/halpal.s b/private/ntos/nthals/halnonme/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/idle.s b/private/ntos/nthals/halnonme/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/info.c b/private/ntos/nthals/halnonme/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/inithal.c b/private/ntos/nthals/halnonme/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/intsup.s b/private/ntos/nthals/halnonme/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/ioproc.c b/private/ntos/nthals/halnonme/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/iousage.c b/private/ntos/nthals/halnonme/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/lca4.c b/private/ntos/nthals/halnonme/alpha/lca4.c
new file mode 100644
index 000000000..6c2a74470
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/lca4.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lca4.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/lca4err.c b/private/ntos/nthals/halnonme/alpha/lca4err.c
new file mode 100644
index 000000000..29b38623e
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/lca4err.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lca4err.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/lcaioacc.s b/private/ntos/nthals/halnonme/alpha/lcaioacc.s
new file mode 100644
index 000000000..02bcd070c
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/lcaioacc.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lcaioacc.s"
+
diff --git a/private/ntos/nthals/halnonme/alpha/machdep.h b/private/ntos/nthals/halnonme/alpha/machdep.h
new file mode 100644
index 000000000..59716f0e7
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/machdep.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include EB66 platform-specific definitions.
+//
+
+#include "lca4.h"
+#include "nondef.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halnonme/alpha/memory.c b/private/ntos/nthals/halnonme/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/nondef.h b/private/ntos/nthals/halnonme/alpha/nondef.h
new file mode 100644
index 000000000..ade96c9ea
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/nondef.h
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ nondef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Mustang/EB66 modules.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Revision History:
+
+
+--*/
+
+#ifndef _NONDEF_
+#define _NONDEF_
+
+#include "alpharef.h"
+#include "lca4.h"
+#include "isaaddr.h"
+
+#define NUMBER_ISA_SLOTS 5
+#define NUMBER_PCI_SLOTS 3
+
+// Highest Virtual local PCI Slot.
+// Changed RAA was 13 but this pushes the code over to b000000 i.e AD[24]
+
+#define PCI_MAX_LOCAL_DEVICE 12
+
+// Highest PCI interrupt vector is in PCI vector space
+
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+#define PCI_INTERRUPT_READ_QVA ((PUCHAR)HAL_MAKE_QVA(HalpLca4PciIoPhysical()) + 0x26)
+#define PCI_INTERRUPT_MASK_QVA ((PUCHAR)HAL_MAKE_QVA(HalpLca4PciIoPhysical()) + 0x26)
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (166)
+
+//
+// PCI-E/ISA Bridge chip configuration space base is at physical address
+// 0x1e0000000. The equivalent QVA is:
+// ((0x1e0000000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+#define PCI_CONFIGURATION_BASE_QVA 0xaf000000
+#define PCI_SPARSE_IO_BASE_QVA 0xae000000
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+
+#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00800000 >> IO_BIT_SHIFT) // AD[18]
+
+//#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00040000 >> IO_BIT_SHIFT) // AD[13]
+
+//
+// PCI-ISA Bridge Configuration register offsets.
+//
+#define PCI_VENDOR_ID (0x0000 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_ID (0x0040 >> IO_BIT_SHIFT)
+#define PCI_COMMAND (0x0080 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_STATUS (0x00c0 >> IO_BIT_SHIFT)
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+#define PCI_CONTROL (0x0800 >> IO_BIT_SHIFT)
+#define PCI_ARBITER_CONTROL (0x0820 >> IO_BIT_SHIFT)
+#define ISA_ADDR_DECODER_CONTROL (0x0900 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_A (0x09c0 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_B (0x09e0 >> IO_BIT_SHIFT)
+#define PIRQ0_ROUTE_CONTROL (0x0c00 >> IO_BIT_SHIFT)
+#define PIRQ1_ROUTE_CONTROL (0x0c20 >> IO_BIT_SHIFT)
+#define PIRQ2_ROUTE_CONTROL (0x0c40 >> IO_BIT_SHIFT)
+#define PIRQ3_ROUTE_CONTROL (0x0c60 >> IO_BIT_SHIFT)
+
+//
+// Values for enabling an IORQ route control setting.
+//
+#define PIRQX_ROUTE_IRQ3 0x03
+#define PIRQX_ROUTE_IRQ4 0x04
+#define PIRQX_ROUTE_IRQ5 0x05
+#define PIRQX_ROUTE_IRQ6 0x06
+#define PIRQX_ROUTE_IRQ7 0x07
+#define PIRQX_ROUTE_IRQ9 0x09
+#define PIRQX_ROUTE_IRQ10 0x0a
+#define PIRQX_ROUTE_IRQ11 0x0b
+#define PIRQX_ROUTE_IRQ12 0x0c
+#define PIRQX_ROUTE_IRQ14 0x0d
+#define PIRQX_ROUTE_IRQ15 0x0f
+#define PIRQX_ROUTE_ENABLE 0x00
+
+//
+// PCI-ISA Bridge Non-Configuration control register offsets.
+//
+#define SIO_II_EDGE_LEVEL_CONTROL_1 (0x9a00 >> IO_BIT_SHIFT)
+#define SIO_II_EDGE_LEVEL_CONTROL_2 (0x9a20 >> IO_BIT_SHIFT)
+
+//
+// SIO-II value for setting edge/level operation in the control words.
+//
+#define IRQ0_LEVEL_SENSITIVE 0x01
+#define IRQ1_LEVEL_SENSITIVE 0x02
+#define IRQ2_LEVEL_SENSITIVE 0x04
+#define IRQ3_LEVEL_SENSITIVE 0x08
+#define IRQ4_LEVEL_SENSITIVE 0x10
+#define IRQ5_LEVEL_SENSITIVE 0x20
+#define IRQ6_LEVEL_SENSITIVE 0x40
+#define IRQ7_LEVEL_SENSITIVE 0x80
+#define IRQ8_LEVEL_SENSITIVE 0x01
+#define IRQ9_LEVEL_SENSITIVE 0x02
+#define IRQ10_LEVEL_SENSITIVE 0x04
+#define IRQ11_LEVEL_SENSITIVE 0x08
+#define IRQ12_LEVEL_SENSITIVE 0x10
+#define IRQ13_LEVEL_SENSITIVE 0x20
+#define IRQ14_LEVEL_SENSITIVE 0x40
+#define IRQ15_LEVEL_SENSITIVE 0x80
+
+#define SIO_II_INIT_COMMAND_1 (0x0400 >> IO_BIT_SHIFT)
+#define SIO_II_INIT_COMMAND_2 (0x1400 >> IO_BIT_SHIFT)
+
+
+
+
+#endif // _NONDEF_
+
diff --git a/private/ntos/nthals/halnonme/alpha/pcibus.c b/private/ntos/nthals/halnonme/alpha/pcibus.c
new file mode 100644
index 000000000..6f9412abc
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pcibus.c
@@ -0,0 +1,127 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+extern ULONG PCIMaxBus;
+
+//
+// Local function prototypes
+//
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ );
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ );
+
+#ifdef AXP_FIRMWARE
+
+//
+// Put these functions in the discardable text section.
+//
+
+#pragma alloc_text(DISTEXT, HalpPCIConfigCycleType )
+#pragma alloc_text(DISTEXT, HalpPCIConfigAddr )
+
+#endif //AXP_FIRMWARE
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0)
+ {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24, which are wired to IDSEL pins.
+ // Note that HalpValidPCISlot has already done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) LCA4_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if DBG
+ DbgPrint("Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ else
+ {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) LCA4_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if DBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halnonme/alpha/pcisio.c b/private/ntos/nthals/halnonme/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/pcisup.c b/private/ntos/nthals/halnonme/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/pcrtc.c b/private/ntos/nthals/halnonme/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/pcserial.c b/private/ntos/nthals/halnonme/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/pcspeakr.c b/private/ntos/nthals/halnonme/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/perfcntr.c b/private/ntos/nthals/halnonme/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halnonme/alpha/pintolin.h b/private/ntos/nthals/halnonme/alpha/pintolin.h
new file mode 100644
index 000000000..038797bbc
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/pintolin.h
@@ -0,0 +1,175 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang and EB66, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for EB66
+//
+// You can limit init table to MAX_PCI_LOCAL_DEVICES entries.
+// The highest virtual slot between EB66 and Mustang is 9, so
+// MAX_PCI_LOCAL_DEVICE is defined as 9 in the platform dependent
+// header file (MUSTDEF.H). HalpValidPCISlot assures us that
+// we won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 9 = PCI_AD[20].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+//
+// Interrupt Vector Table Mapping for Avanti
+//
+// Avanti PCI interrupts are mapped to ISA IRQs in the table below.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_AVANTI.
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+
+ULONG NonamePCIPinToLineTable[][4]=
+{
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xb, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] SIO
+ { 0x9, 0xf, 0xa, 0x9 }, // Virtual Slot 8 = PCI_AD[19] Slot #2
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0xa, 0x9, 0xf, 0xa }, // Virtual Slot 11 = PCI_AD[22] Slot #0
+ { 0xf, 0xa, 0x9, 0xf }, // Virtual Slot 12 = PCI_AD[23] Slot #1
+};
diff --git a/private/ntos/nthals/halnonme/alpha/vga.c b/private/ntos/nthals/halnonme/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halnonme/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halnonme/drivesup.c b/private/ntos/nthals/halnonme/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halnonme/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halnonme/hal.rc b/private/ntos/nthals/halnonme/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halnonme/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halnonme/hal.src b/private/ntos/nthals/halnonme/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halnonme/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halnonme/makefile b/private/ntos/nthals/halnonme/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halnonme/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halnonme/makefile.inc b/private/ntos/nthals/halnonme/makefile.inc
new file mode 100644
index 000000000..904ba095b
--- /dev/null
+++ b/private/ntos/nthals/halnonme/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halnonme.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halnonme/sources b/private/ntos/nthals/halnonme/sources
new file mode 100644
index 000000000..251197fb3
--- /dev/null
+++ b/private/ntos/nthals/halnonme/sources
@@ -0,0 +1,101 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halnonme
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEB66 -DEV4 -DLCA4
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cmos8k.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\lca4.c \
+ alpha\lca4err.c \
+ alpha\lcaioacc.s \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\ebinitnt.c \
+ alpha\ebmapio.c \
+ alpha\ebsysint.c \
+ alpha\ebintsup.c \
+ alpha\pcibus.c \
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halntp/bushnd.c b/private/ntos/nthals/halntp/bushnd.c
new file mode 100644
index 000000000..79123b47d
--- /dev/null
+++ b/private/ntos/nthals/halntp/bushnd.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halntp/drivesup.c b/private/ntos/nthals/halntp/drivesup.c
new file mode 100644
index 000000000..8247c7928
--- /dev/null
+++ b/private/ntos/nthals/halntp/drivesup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halntp/hal.rc b/private/ntos/nthals/halntp/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halntp/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halntp/hal.src b/private/ntos/nthals/halntp/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halntp/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halntp/makefile b/private/ntos/nthals/halntp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halntp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halntp/makefile.inc b/private/ntos/nthals/halntp/makefile.inc
new file mode 100644
index 000000000..038fffeab
--- /dev/null
+++ b/private/ntos/nthals/halntp/makefile.inc
@@ -0,0 +1,5 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halntp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halntp/mips/allstart.c b/private/ntos/nthals/halntp/mips/allstart.c
new file mode 100644
index 000000000..f974ff056
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/allstart.c
@@ -0,0 +1,71 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ //
+ // If the number of processors in the host configuration is one,
+ // then connect EISA interrupts to processor zero. Otherwise,
+ // connect EISA interrupts to processor one.
+ //
+
+ if (**((PULONG *)(&KeNumberProcessors)) == 1) {
+ return TRUE;
+
+ } else if (PCR->Number == 1) {
+ return TRUE;
+
+ } else {
+ return TRUE;
+ }
+
+}
diff --git a/private/ntos/nthals/halntp/mips/cacherr.s b/private/ntos/nthals/halntp/mips/cacherr.s
new file mode 100644
index 000000000..d7c852445
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/cacherr.s
@@ -0,0 +1,196 @@
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// N.B. All the code in this routine MUST run in KSEG1 and reference
+// data only in KSEG1 until which time as any cache errors have
+// been corrected.
+//
+// N.B. This routine is NOT COMPLETE. All cache errors result in a
+// soft reset.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+
+#include "halmips.h"
+
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved integer register at - a3
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+
+ SBTTL("Cache Error Handling")
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1. If the error is a single bit ECC error in the second
+// level data cache or the error is in the primary instruction cache,
+// then the error is corrected and execution is continued. Otherwise,
+// a fatal system error has occured and control is transfered to the
+// soft reset vector.
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCacheErrorRoutine)
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw AT,0(k0) // save registers AT - a3
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+
+//
+// Get the current processor state and cache error register, and check
+// if the error can be corrected.
+//
+
+ mfc0 v0,psr // get current processor state
+ mfc0 v1,cacheerr // get cache error state
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+//
+// The following code is temporary and will be removed when full cache
+// error support is included.
+//
+// ****** temp ******
+//
+
+ b SoftReset // ****** all error soft rest
+
+//
+// If the EXL bit is set in the processor state, then the error is not
+// recoverable because the EXL bit may be erroneously set (errata) and
+// it cannot be determined whether is should or should not be set, e.g.,
+// the exact addresses ranges over which EXL might be correctly set are
+// not verifiable. Also, k0 and k1 are destroyed before they are saved
+// and are used by the exception handling code (there is no way to save
+// a register in noncached memory wihtout the use of a register).
+//
+
+ sll a0,v0,31 - PSR_EXL // shift EXL bit in sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// If the error occured on the SysAd bus, then the error is not correctable.
+//
+
+ sll a0,v1,31 - CACHEERR_EE // shift EE bit into sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// Determine whether the error is in the instruction or data cache.
+//
+
+ sll a0,v1,31 - CACHEERR_ER // shift ER bit into sign
+ bgez a0,IcacheError // if gez, instruction cache error
+
+//
+// The error occured in the data cache.
+//
+// If the error is a data error in the primary cache, then the error
+// is not correctable since the cache line dirty bit is included in
+// the parity calculation and therefore may be wrong.
+//
+
+DcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bgez a0,SoftReset // if gez, error in primary cache
+ b ExitError // exit error
+
+//
+// The error occured in the instruction cache.
+//
+// If the error occured in the secondary data cache, then the error is not
+// correctable since there is not secondary instruciton cache.
+//
+
+IcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bltz a0,SoftReset // if ltz, error in secondary cache
+
+//
+// The cache error has been corrected - restore register state and continue
+// execution.
+//
+
+ExitError: //
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw AT,0(k0) // restore registers AT - a3
+ lw v0,4(k0) //
+ lw v1,8(k0) //
+ lw a0,12(k0) //
+ lw a1,16(k0) //
+ lw a2,20(k0) //
+ eret //
+ .set at
+ .set reorder
+
+//
+// Cache error cannot be corrected - transfer control to soft reset vector.
+//
+
+SoftReset: //
+ la k0,SOFT_RESET_VECTOR // get address of soft reset vector
+ j k0 // perform a soft reset
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halntp/mips/faldef.h b/private/ntos/nthals/halntp/mips/faldef.h
new file mode 100644
index 000000000..1dfc81863
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/faldef.h
@@ -0,0 +1,1542 @@
+
+
+#ifndef _FALCONDEF_
+#define _FALCONDEF_
+
+//
+// Falcon Firmware Address Space
+//
+// Below is the memory map of the Falcon firmware as seen
+// from the processor.
+//
+// Processor View
+// Flash ROM
+// Physical Virtual
+// Address Address
+//
+// |------------------|
+// FFFFFFFF | falcon.exe | E307FFFF
+// FFFFF000 | | E307F000
+// |------------------|
+// | |
+// | |
+// | baseprom.exe |
+// | |
+// FFFF3200 | | E3073000
+// |------------------|
+// | falconbase.exe |
+// FFFF0000 | | E3070000
+// |------------------|
+// | |
+// | NVRAM / 64k |
+// FFFE0000 | | E3060000
+// |------------------|
+// | |
+// | |
+// | |
+// | |
+// | f4fw.exe |
+// | |
+// | |
+// FFF81000 | | E3001000
+// |------------------|
+// | |
+// | f4reset.exe |
+// FFF80000 | | E3000000
+// |------------------|
+//
+// Firmware General Information:
+//
+// Falcon.exe - This is the startup code, it holds the reset vector, where
+// the system wil go when a reset occurs. The reset condition is checked
+// for a Cold or Warm reset, or a NMI reset. This section of the prom inits
+// the TLB's and the keyoboard controller to check if the space bar key
+// is being pressed. If a key is being pressed, it signals a flash prom
+// update and will jump to falconbase.exe, if no key is pressed it jumps
+// to f4reset.exe.
+//
+// F4reset.exe - This is the startup code for the "Bootprom". This is the
+// code that will size and test minimal memory and init the system. The code
+// than jumps to f4fw.exe.
+//
+// F4fw.exe - This is the code that executes the selftests for the Falcon
+// system, inits the on board devices and detects boards on the PCI and EISA
+// bus. The code will init the ARC environment, set up the boot process, and
+// boot the system if autoboot is on, else it will to a prom prompt and wait
+// for the appropriate action.
+//
+// Falconbase.exe - This is the startup code for the baseprom. This code
+// tests minimal memory, copies the firmware code to memory that updates
+// the flash prom.
+//
+// Baseprom.exe - This code will setup all necessary devices to update the
+// flash prom, reset the system and reboot. The code reads the floppy drive
+// for a file called romsetup.exe, this file has the routines to read a
+// file from the floppy to update the flash prom. The flash prom is erased,
+// and the new code is programmed in the flash prom.
+//
+//
+// Falcon System (Physical) Address Space
+//
+// Below is the memory map of the Falcon system as seen from the
+// processor as well as from PCI. The map of PCI space is mostly
+// programmable, and what is shown below is how we intend to map
+// it.
+//
+// Processor View PCI View
+//
+// |------------------| |------------------|
+// FFFFFFFF | Flash ROM | FFFFFFFF | Flash Rom |
+// F0000000 | | F0000000 | |
+// |------------------| |------------------|
+// EFFFFFFF | EISA/ISA Control | EFFFFFFF | Currently UNUSED |
+// E0000000 | | | |
+// |------------------| | |
+// DFFFFFFF | ECache Control | | |
+// D0000000 | | | |
+// |------------------| | |
+// CFFFFFFF | PMP Control | | |
+// C0000000 | | C0000000 | |
+// |------------------| |------------------|
+// BFFFFFFF | | BFFFFFFF | |
+// | PCI I/O | | Physical Memory |
+// | | | |
+// A0000000 | |--| | 2GB |
+// |------------------| | | |
+// 9FFFFFFF | | | | |
+// | PCI Memory | | | |
+// | | | | |
+// 80000000 | |--| | |
+// |------------------| | | |
+// 7FFFFFFF | | | | |
+// | Physical Memory | | | |
+// | | | | |
+// | 2GB | | | |
+// | | | | |
+// | | | | |
+// | | | | |
+// | | | 40000000 | |
+// | | | |------------------|
+// | | | 3FFFFFFF | Currently UNUSED |
+// | | | 20000000 | |
+// | | | |------------------|
+// | | | 1FFFFFFF | PCI Memory & I/O |
+// | | | | |
+// | | | | 512MB - 2MB |
+// | | | | |
+// | | | 00200000 | |
+// | | | |------------------|
+// | | | 001FFFFF | EISA/ISA |
+// 0000000 | | |----------> 00000000 | Control & Memory |
+// |------------------| |------------------|
+//
+//
+// General Information:
+//
+// The 82374/82375 PCI/EISA chipset powers up by default forcing EISA/ISA
+// Control/Memory space to address 00000000, and with system BIOS at FFFF8000.
+// This allows Falcon to be able to fetch from the flash rom at reset,
+// and also reach the EISA/ISA control space PRIOR to a PCI config cycle.
+//
+// Since the 82374/82375 PCI/EISA chipset mandates the EISA/ISA control/memory
+// space at address 00000000, we must relocate physical memory as seen
+// from PCI so as not to conflict with that space. By setting the MSO
+// bit in the PMP PCICtrl register, physical memory will be relocated to
+// start at 40000000 as seen from PCI. Therefore any physical memory
+// address passed to the PCI card for DMA purposes MUST add 0x40000000
+// to the address to get a proper address as seen from PCI.
+//
+// As seen from the processor side, PCI Memory and PCI I/O space are
+// 512MB. An access from the processor side to either the PCI Memory
+// or PCI I/O space are translated to a PCI address as follows. First
+// the lower 28 bits (27..0) of the address are taken to form the lower
+// 28 bits of the PCI address. Then, depending on bit 28 of the address,
+// either NIB1 (bit 28 == 1) or NIB0 (bit 28 == 0) from PMP PCISpaceMap
+// is taken as the upper 4 bits (31..28) to form the PCI address. Since
+// there is only one set of NIB# for both PCI Memory and PCI I/O accesses,
+// the two PCI spaces as seen from the processor side will map to the SAME
+// 512MB space on PCI side. The EISA/ISA bridge does NOT allow us to remap
+// control/memory space to a base other than 0x00000000. The only way to access
+// EISA/ISA memory space is through the PCI Memory range as seen from the
+// processor (0x80000000-0x9FFFFFFF). Since an access through either the
+// PCI Memory or I/O space as seen from the processor is translated to a
+// PCI address via the NIB# registers, these registers must be set knowing
+// the EISA/ISA bridge is located at 0x00000000 in the PCI address space.
+// Therefore, we will set up NIB0 to be 0x0 and NIB1 to be 0x1. Thus, our
+// PCI Memory and I/O space is 512MB starting at PCI address 0x00000000.
+// The EISA/ISA bridge consumes 2MB minimum of memory space, and significantly
+// less than that in I/O space. Therefore we will allocate the lower 2MB of
+// the 512MB space to the EISA/ISA bridge, and remaining 510MB will be
+// allocated to the remainder of the PCI devices.
+//
+// The range defined as PMP Control space from 0xC0000000 - 0xCFFFFFFFF is
+// further broken down as follows. See the Falcon Programmers Specification
+// for more information.
+//
+// System Control Space 0xC0000000 - 0xC7FFFFFF
+// PCI Configuration Space 0xC8000800 - 0xC80008FF
+// PCI Special Cycle Space 0xCA000A00 - 0xCA000AFF
+// PCI Interrupt Ack Space 0xCC000C00 - 0xCC000CFF
+//
+//
+// Falcon System (Virtual) Address Space
+//
+// Here is a proposal for the layout of the virtual address space for the
+// firmware and HAL. Comments welcome...
+//
+// PMP Control 0xE0000000 - 0xE1FFFFFF (2 x 16MB pages)
+// Devices 0xE2000000 (includes all Sidewinder + SCSI/Enet)
+// PROM 0xE3000000
+// EISA I/O 0xE4000000
+// EISA Memory 0xE5000000 (16MB page)
+// PMP/PCI additional 0xE6000000 (PCI Config, Special Cycle, Interrupt Ack)
+// ECache Control 0xE7000000
+// DEC Graphics 0xE8000000 - 0xEFFFFFFF (Needs 128MB, aligned)
+// Available 0xF0000000 - 0xFEFFFFFF
+
+//
+// Define physical base addresses for system mapping.
+//
+
+#define PCI_MEMORY_PHYSICAL_BASE 0x80000000
+#define PCI_IO_PHYSICAL_BASE 0xA0000000
+#define EISA_MEMORY_PHYSICAL_BASE PCI_MEMORY_PHYSICAL_BASE
+#define EISA_IO_PHYSICAL_BASE PCI_IO_PHYSICAL_BASE
+
+#define PCI_IO_MAPPED_PHYSICAL_BASE 0xA1000000 // PCI io physical plus space used by PCI/EISA bridge
+#define PCI_IO_MAPPED_PHYSICAL_RANGE 0x2000 // 8k TLB entry; change this and change tlb in falcon.s
+#define VIDEO_MEMORY_PHYSICAL_BASE 0x88000000
+#define VIDEO_CONTROL_PHYSICAL_BASE 0xA8000000
+#define LBUF_BURST_ADDR_PHYISCAL_BASE 0xC8000800
+#define ECACHE_CONTROL_PHYSICAL_BASE 0xD0000000
+#define EISA_CONTROL_PHYSICAL_BASE 0xE0000000 // Special path to control space
+#define PCR_PHYSICAL_BASE 0x7ff000
+
+//
+// The following #defines are for the I/O devices that reside in
+// the Sidewinder I/O chip.
+//
+
+#define SIDEWINDER_PHYSICAL_BASE EISA_CONTROL_PHYSICAL_BASE
+#define DEVICE_PHYSICAL_BASE EISA_CONTROL_PHYSICAL_BASE
+#define RTCLOCK_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x71)
+#define KEYBOARD_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x60)
+#define MOUSE_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x60)
+#define FLOPPY_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x3F0)
+#define SERIAL0_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x3F8)
+#define SERIAL1_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x2F8)
+#define SERIAL_COM1_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x3F8)
+#define SERIAL_COM2_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x2F8)
+#define SERIAL_COM3_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x3E8)
+#define SERIAL_COM4_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x2E8)
+#define PARALLEL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x3BC)
+#define SOUND_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + 0x534) // Crystal CS4248
+
+#define PROM_PHYSICAL_BASE 0xFFF80000
+#define NVRAM_PHYSICAL_BASE 0xFFFE0000 // NVRAM is in Flash Rom
+
+//
+// Define virtual base addresses for system mapping.
+//
+// See above address map
+//
+
+#if defined(_FALCON_HAL_)
+
+#define PMP_CONTROL_VIRTUAL_BASE 0xFFFFC000 // used for permanent HAL mappings
+#define SYS_CONTROL_VIRTUAL_BASE 0xFFFF8000 // used for on-the-fly HAL mappings (NEED TO FIX)
+#define KEYBOARD_VIRTUAL_BASE PMP_CONTROL_VIRTUAL_BASE // used by HAL (soft reset)
+
+#else
+
+#define PMP_CONTROL_VIRTUAL_BASE 0xE0000000 // used by firmware
+#define KEYBOARD_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x60)
+
+#endif // _FALCON_HAL_
+
+#define PCI_VIRTUAL_BASE 0xE2000000
+#define NET_VIRTUAL_BASE 0xE2001000
+
+#define PROM_VIRTUAL_BASE 0xE3000000
+#define NVRAM_VIRTUAL_BASE 0xE3060000
+
+#if defined(_FALCON_HAL_)
+#define EISA_CONTROL_VIRTUAL_BASE 0x40200000
+#define EISA_MEMORY_VIRTUAL_BASE 0x40000000 // Align on 32MB boundary
+#else
+// A single TLB entry maps these
+#define EISA_CONTROL_VIRTUAL_BASE 0xE4000000
+#define EISA_MEMORY_VIRTUAL_BASE 0xE5000000
+#define EISA_EXTERNAL_IO_VIRTUAL_BASE 0xF0000000
+#define EISA_LATCH_VIRTUAL_BASE 0xF0100000
+#endif
+
+#define PCI_CONFIG_VIRTUAL_BASE 0xE6000000
+#define PCI_SPECIAL_VIRTUAL_BASE 0xE6002000
+#define PCI_INTERRUPT_VIRTUAL_BASE 0xE6004000
+
+#define ECACHE_CONTROL_VIRTUAL_BASE 0xE7000000
+
+#define VIDEO_MEMORY_VIRTUAL_BASE 0xE8000000
+#define VIDEO_CONTROL_VIRTUAL_BASE 0xE8000000 // For DEC chip, only need to map 1!
+
+#define LBUF_BURST_ADDR_VIRTUAL_BASE 0xF3000800
+
+#define SIDEWINDER_VIRTUAL_BASE EISA_CONTROL_VIRTUAL_BASE
+#define FLOPPY_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x3F0)
+#define RTC_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x71)
+#define COMPORT1_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x3F8)
+#define COMPORT2_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x2F8)
+#define PARALLEL_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x3BC)
+#define SIDEWINDER_NVRAM_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x71)
+#define SOUND_VIRTUAL_BASE (EISA_CONTROL_VIRTUAL_BASE + 0x534) // Crystal CS4248
+
+#define PCR_VIRTUAL_BASE KiPcr
+
+//
+// Define some macros to aid in computing replication bits.
+//
+
+#define REPLICATE_16(x) ((x) << 16 | (x)) // Replicate low 16 bits to high 16
+#define IO_ADDRESS_HI(x) ((x) >> 28) // Generate high 32 bits of IO address
+#define IO_ADDRESS_LO(x) (x) // Generate low 32 bits of IO address
+#define REG_OFFSET(x) (x & 0xFFF) // Generate low order 12 bits
+#define REG_OFFSET4(x) (x & 0xF) // Generate low order 4 bits
+
+//
+// Define system control space physical base addresses for
+// system mappings. Note that the file fxpmpsup.c contains
+// all of the register and address space mappings for the
+// PMP chip used in Falcon. Because the address map is different
+// between the first version and the second version of the chip,
+// it was deemed more desireable to be able to distinguish between
+// the two chip versions at runtime rather than at compile time.
+// This precluded the use of #defines except for GLOBAL_STATUS* for
+// obvious reasons. The extern's for all the arrays is at the
+// end of this file.
+//
+
+#define PMP_CONTROL_PHYSICAL_BASE 0xC0000000
+
+// Global Status is the one register in the same place on PMP v1/v2
+
+#define GLOBAL_STATUS PMP_CONTROL_VIRTUAL_BASE
+#define GLOBAL_STATUS_PHYSICAL_BASE PMP_CONTROL_PHYSICAL_BASE
+
+//
+// These next #defines needed for TLB table initialization in falcon.s. They are
+// also used to initialize the appropriate arrays in fxpmpsup.c
+//
+#define PCI_CONFIG_PHYSICAL_BASE_PMP_V1 0xC8000800
+#define PCI_CONFIG_PHYSICAL_BASE_PMP_V2 0xC4000400
+
+#define PCI_SPECIAL_PHYSICAL_BASE_PMP_V1 0xCA000A00
+#define PCI_SPECIAL_PHYSICAL_BASE_PMP_V2 0xC6000600
+
+#define PCI_INTERRUPT_PHYSICAL_BASE_PMP_V1 0xCC000C00
+#define PCI_INTERRUPT_PHYSICAL_BASE_PMP_V2 0xC2000200
+
+#ifdef FALCON
+#define PCI_CONFIG_SELECT_OFFSET 0xC000
+#define EXTERNAL_PMP_CONTROL_OFFSET 0xC004
+#define EXTERNAL_PMP_CONTROL_OFFSET2 0xC008
+#else // #ifdef FALCON
+#define PCI_CONFIG_SELECT_OFFSET 0xE000
+#define EXTERNAL_PMP_CONTROL_OFFSET 0xE004
+#define EXTERNAL_PMP_CONTROL_OFFSET2 0xE008
+#endif // #ifdef FALCON
+#define PCI_CONFIG_SEL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + PCI_CONFIG_SELECT_OFFSET)
+#define EXTERNAL_PMP_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE + EXTERNAL_PMP_CONTROL_OFFSET)
+
+#define SP_PHYSICAL_BASE SERIAL0_PHYSICAL_BASE
+
+//
+// External register vaddrs used by the PMP for
+// PCI config select and external controls
+//
+
+#define PCI_CONFIG_SELECT (EISA_CONTROL_VIRTUAL_BASE + PCI_CONFIG_SELECT_OFFSET)
+#define EXTERNAL_PMP_CONTROL (EISA_CONTROL_VIRTUAL_BASE + EXTERNAL_PMP_CONTROL_OFFSET)
+#define EXTERNAL_PMP_CONTROL_1 (EISA_CONTROL_VIRTUAL_BASE + EXTERNAL_PMP_CONTROL_OFFSET2)
+
+//
+// PMP interrupt registers vaddr
+//
+#define SYS_INT_VIRTUAL_BASE 0xFFFFC000
+//#define IO_INT_ACK_VIRTUAL_BASE (0xFFFFD000 + REG_OFFSET(IO_INT_ACK_PHYSICAL_BASE))
+
+//
+// Serial port virtual address
+//
+#define SP_VIRTUAL_BASE (0xFFFFA000 + 0x3F8)
+
+//
+// Define system time increment value
+//
+#define TIME_INCREMENT (10 * 1000 * 10)
+#define CLOCK_INTERVAL ( 11949 )
+#define CLOCK_INTERVAL_PMP_V2 (CLOCK_INTERVAL * 2)
+#define MINIMUM_INCREMENT ( 10032 )
+#define MAXIMUM_INCREMENT ( 99968 )
+
+//
+// Interrupt levels
+//
+// Note:
+// FALCON steers all interrupts onto IP2 in the
+// R4x00 referred to as FALCON_LEVEL. We install
+// the handlers in the IDT at the DUO/STRIKER levels
+// for completeness and compatibility.
+//
+#define FALCON_LEVEL 3
+#define DEVICE_LEVEL FALCON_LEVEL
+#define IO_DEVICE_LEVEL 4
+#define CLOCK_LEVEL 6
+#define CLOCK2_LEVEL CLOCK_LEVEL
+#define MEMORY_LEVEL 8
+#define PCI_LEVEL 9
+#define EISA_DEVICE_LEVEL 16
+
+
+//
+// Define device interrupt vectors as follows:
+//
+// Priority IRQ Source
+// -------- --- ------
+// 1 0 Interval Timer 1 (Counter 0)
+// 2 1 Keyboard
+// 3 2 internal to 82374
+// 11 3 Serial Port 2
+// 12 4 Serial Port 1
+// 13 5 Expansion Bus
+// 14 6 Floppy
+// 15 7 Parallel Port
+// 3 8 Real Time Clock
+// 4 9 Ethernet (on-board)
+// 5 10 SCSI (on-board)
+// 6 11 Graphics (on-board)
+// 7 12 PCI Expansion Bus
+// 8 13 EISA/ISA DMA
+// 9 14 Audio
+// 10 15 Modem
+//
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define EISA_VECTORS EISA_DEVICE_LEVEL
+#define DEVICE_VECTORS EISA_VECTORS
+
+#define IRQL0_VECTOR ( 0 + EISA_VECTORS)
+#define IRQL1_VECTOR ( 1 + EISA_VECTORS)
+#define IRQL2_VECTOR ( 2 + EISA_VECTORS)
+#define IRQL3_VECTOR ( 3 + EISA_VECTORS)
+#define IRQL4_VECTOR ( 4 + EISA_VECTORS)
+#define IRQL5_VECTOR ( 5 + EISA_VECTORS)
+#define IRQL6_VECTOR ( 6 + EISA_VECTORS)
+#define IRQL7_VECTOR ( 7 + EISA_VECTORS)
+#define IRQL8_VECTOR ( 8 + EISA_VECTORS)
+#define IRQL9_VECTOR ( 9 + EISA_VECTORS)
+#define IRQL10_VECTOR (10 + EISA_VECTORS)
+#define IRQL11_VECTOR (11 + EISA_VECTORS)
+#define IRQL12_VECTOR (12 + EISA_VECTORS)
+#define IRQL13_VECTOR (13 + EISA_VECTORS)
+#define IRQL14_VECTOR (14 + EISA_VECTORS)
+#define IRQL15_VECTOR (15 + EISA_VECTORS)
+
+#define MAXIMUM_EISA_VECTOR IRQL15_VECTOR
+
+#define INT_TIMER_VECTOR IRQL0_VECTOR
+#define KEYBOARD_VECTOR IRQL1_VECTOR
+#define MOUSE_VECTOR IRQL1_VECTOR
+#define SERIAL0_VECTOR IRQL4_VECTOR
+#define SERIAL1_VECTOR IRQL3_VECTOR
+#define FLOPPY_VECTOR IRQL6_VECTOR
+#define PARALLEL_VECTOR IRQL5_VECTOR
+#define RTC_VECTOR IRQL8_VECTOR
+#define NET_VECTOR IRQL9_VECTOR
+#define SCSI_VECTOR IRQL10_VECTOR
+#define VIDEO_VECTOR IRQL11_VECTOR
+#define SOUND_VECTOR IRQL14_VECTOR
+#define MODEM_VECTOR IRQL15_VECTOR
+
+//
+// Defines for vector returned from reading IO_INT_ACK
+//
+
+#define INT_TIMER_DEVICE ( INT_TIMER_VECTOR - IRQL0_VECTOR )
+#define KEYBOARD_DEVICE ( KEYBOARD_VECTOR - IRQL0_VECTOR )
+#define MOUSE_DEVICE ( MOUSE_VECTOR - IRQL0_VECTOR )
+#define SERIAL0_DEVICE ( SERIAL0_VECTOR - IRQL0_VECTOR )
+#define SERIAL1_DEVICE ( SERIAL1_VECTOR - IRQL0_VECTOR )
+#define FLOPPY_DEVICE ( FLOPPY_VECTOR - IRQL0_VECTOR )
+#define PARALLEL_DEVICE ( PARALLEL_VECTOR - IRQL0_VECTOR )
+#define RTC_DEVICE ( RTC_VECTOR - IRQL0_VECTOR )
+#define NET_DEVICE ( NET_VECTOR - IRQL0_VECTOR )
+#define SCSI_DEVICE ( SCSI_VECTOR - IRQL0_VECTOR )
+#define VIDEO_DEVICE ( VIDEO_VECTOR - IRQL0_VECTOR )
+#define SOUND_DEVICE ( SOUND_VECTOR - IRQL0_VECTOR )
+#define MODEM_DEVICE ( MODEM_VECTOR - IRQL0_VECTOR )
+
+//
+// Pre-allocated DMA channels for on-board devices
+//
+
+#define FLOPPY_CHANNEL 1
+#define SOUND_CHANNEL 1
+
+//
+// Define the clock speed in megahertz for the SCSI protocol chips.
+//
+
+#define NCR_SCSI_CLOCK_SPEED 33
+
+//
+// PROM entry point definitions.
+//
+// Define base address of prom entry vector and prom entry macro.
+//
+
+#define PROM_BASE PROM_VIRTUAL_BASE
+#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8))
+
+#define BASEPROM_VIRTUAL_BASE (PROM_VIRTUAL_BASE + 0x70000)
+#define FALPROM_VIRTUAL_BASE (PROM_VIRTUAL_BASE + 0x7f000)
+
+#define BASEPROM_BASE BASEPROM_VIRTUAL_BASE
+#define BASEPROM_ENTRY(x) (BASEPROM_BASE + ((x) * 8))
+
+
+//
+// Scatter/Gather definitions
+//
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// Define scatter/gather table structure.
+//
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ ULONG Address;
+ ULONG ByteCountAndEol;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#define DMA_TRANSLATION_LIMIT 0x1000
+#define DMA_REQUEST_LIMIT (DMA_TRANSLATION_LIMIT / 8)
+
+#define SCATTER_GATHER_EOL 0x80000000
+#define SCATTER_GATHER_COMMAND 0xC1
+
+//
+// Prom Address definitions
+//
+#define LINK_ADDRESS PROM_VIRTUAL_BASE // Falcon BootProm Link address
+#define BASELINK_ADDRESS (PROM_VIRTUAL_BASE + 0x70000) // Falcon BaseProm Link address
+#define FALLINK_ADDRESS (PROM_VIRTUAL_BASE + 0x7f000) // Falcon Prom Link address
+#define RESET_VECTOR 0xbfc00000 // R4k Reset Vector address
+
+#define SECONDARY_CACHE_SIZE (1 << 20)
+
+#define REPLICATE_MASK 0xf0000000 // Mask of bits 31:28 only
+#define PAGE_SIZE_256K 0x40000 // Page size = 256K
+#define PAGE_SIZE_1MB 0x100000 // Page size = 1MB
+#define PAGE_SIZE_16MB 0x1000000 // Page size = 16MB
+#define PAGE_SIZE_32MB 0x2000000 // Page size = 32MB
+
+
+//
+// Memory address definitions for sizing and
+// probing Falcon memory. The address space
+// has a total of 8 banks, with a possible 2
+// banks per physical memory slot locations.
+//
+
+#define MEMORY_TLB_ENTRY 0x20
+
+#define MEM0_PROBE_0 0xa0000000
+#define MEM0_PROBE_1 0xa0100000
+#define MEM0_PROBE_2 0xa0200000
+#define MEM0_PROBE_4 0xa0400000
+#define MEM0_PROBE_8 0xa0800000
+#define MEM0_PROBE_16 0xa1000000
+#define MEM0_PROBE_32 0xa2000000
+#define MEM0_PROBE_64 0xa4000000
+#define MEM0_PROBE_128 0xa8000000
+
+#define MEM1_PROBE_0 0xb0000000
+#define MEM1_PROBE_1 0xb0100000
+#define MEM1_PROBE_2 0xb0200000
+#define MEM1_PROBE_4 0xb0400000
+#define MEM1_PROBE_8 0xb0800000
+#define MEM1_PROBE_16 0xb1000000
+#define MEM1_PROBE_32 0xb2000000
+#define MEM1_PROBE_64 0xb4000000
+#define MEM1_PROBE_128 0xb8000000
+
+#define MEM2_PROBE_0 0x20000000
+#define MEM2_PROBE_1 0x20100000
+#define MEM2_PROBE_2 0x20200000
+#define MEM2_PROBE_4 0x20400000
+#define MEM2_PROBE_8 0x20800000
+#define MEM2_PROBE_16 0x21000000
+#define MEM2_PROBE_32 0x22000000
+#define MEM2_PROBE_64 0x24000000
+#define MEM2_PROBE_96 0x26000000
+#define MEM2_PROBE_128 0x28000000
+#define MEM2_PROBE_160 0x2a000000
+#define MEM2_PROBE_192 0x2c000000
+#define MEM2_PROBE_224 0x2e000000
+
+#define MEM3_PROBE_0 0x30000000
+#define MEM3_PROBE_1 0x30100000
+#define MEM3_PROBE_2 0x30200000
+#define MEM3_PROBE_4 0x30400000
+#define MEM3_PROBE_8 0x30800000
+#define MEM3_PROBE_16 0x31000000
+#define MEM3_PROBE_32 0x32000000
+#define MEM3_PROBE_64 0x34000000
+#define MEM3_PROBE_96 0x36000000
+#define MEM3_PROBE_128 0x38000000
+#define MEM3_PROBE_160 0x3a000000
+#define MEM3_PROBE_192 0x3c000000
+#define MEM3_PROBE_224 0x3e000000
+
+#define MEM4_PROBE_0 0x40000000
+
+#define MEM5_PROBE_0 0x50000000
+
+#define MEM6_PROBE_0 0x60000000
+
+#define MEM7_PROBE_0 0x70000000
+
+
+#define MEM_SIZE_BANK0 0xa0000150
+#define MEM_SIZE_BANK1 0xa0000154
+#define MEM_SIZE_BANK2 0xa0000158
+#define MEM_SIZE_BANK3 0xa000015c
+#define MEM_SIZE_BANK4 0xa0000160
+#define MEM_SIZE_BANK5 0xa0000164
+#define MEM_SIZE_BANK6 0xa0000168
+#define MEM_SIZE_BANK7 0xa000016c
+#define MEM_NUMBER_OF_BANKS 0xa0000170
+//
+// Because there could be holes in the memory subsystem, the address
+// range could be bigger than the actual size of memory in the system.
+// This needs to be known to be able to correctly scrub and test the
+// correct memory address space present in the system.
+//
+#define BANK0_MEMORY_RANGE 0xa0000060
+#define BANK1_MEMORY_RANGE 0xa0000064
+#define BANK2_MEMORY_RANGE 0xa0000068
+#define BANK3_MEMORY_RANGE 0xa000006c
+#define BANK4_MEMORY_RANGE 0xa0000070
+#define BANK5_MEMORY_RANGE 0xa0000074
+#define BANK6_MEMORY_RANGE 0xa0000078
+#define BANK7_MEMORY_RANGE 0xa000007c
+
+//
+// Because there could be holes in the system, the minimum increment
+// of memory is needed to be able to determine how much memory is
+// available at each address. Along with the hit memory pointers that
+// were found while probing the Falcon memory subsystem, the user
+// can construct where memory is accessible in the system.
+//
+#define BANK0_INCREMENT_VALUE 0xa00000e0
+#define BANK1_INCREMENT_VALUE 0xa00000e4
+#define BANK2_INCREMENT_VALUE 0xa00000e8
+#define BANK3_INCREMENT_VALUE 0xa00000ec
+#define BANK4_INCREMENT_VALUE 0xa00000f0
+#define BANK5_INCREMENT_VALUE 0xa00000f4
+#define BANK6_INCREMENT_VALUE 0xa00000f8
+#define BANK7_INCREMENT_VALUE 0xa00000fc
+
+//
+// Because there could be holes in the memory subsystem, the hit memory
+// pointers found during the probe of memory, are needed so the firmware
+// can construct the memory map where memory is accessible in the Falcon
+// system.
+//
+#define BANK0_HIT_POINTERS 0xa00001e0
+#define BANK1_HIT_POINTERS 0xa00001e4
+#define BANK2_HIT_POINTERS 0xa00001e8
+#define BANK3_HIT_POINTERS 0xa00001ec
+#define BANK4_HIT_POINTERS 0xa00001f0
+#define BANK5_HIT_POINTERS 0xa00001f4
+#define BANK6_HIT_POINTERS 0xa00001f8
+#define BANK7_HIT_POINTERS 0xa00001fc
+
+//
+// Defines used in the probe and test of the Falcon memory subsystem.
+//
+#define MEM_256MB 0x10000000
+#define MEM_128MB 0x08000000
+#define MEM_32MB 0x02000000
+#define MEM_16MB 0x01000000
+#define MEM_8MB 0x00800000
+#define MEM_4MB 0x00400000
+#define MEM_2MB 0x00200000
+#define MEM_1MB 0x00100000
+
+//
+// Defines used for probing memory
+//
+#define MEM_DATA0 0x0A0A0A0A
+#define MEM_DATA1 0x1B1B1B1B
+#define MEM_DATA2 0x2C2C2C2C
+#define MEM_DATA3 0x3D3D3D3D
+#define MEM_DATA4 0x4E4E4E4E
+#define MEM_DATA5 0x5F5F5F5F
+#define MEM_DATA6 0x69696969
+#define MEM_DATA7 0x7A7B7C7D
+
+//
+// Defines for the cache coherency test
+//
+#define EXCLUSIVE_PAGE_PHYSICAL_BASE 0x00200000
+#define SHARED_PAGE_PHYSICAL_BASE 0x00201000
+#define EXCLUSIVE_PAGE_VIRTUAL_BASE 0x00200000
+#define SHARED_PAGE_VIRTUAL_BASE 0x00201000
+
+//
+// FLASH definitions
+//
+#define SECTOR_SIZE_AM29F040 (64*1024)
+#define FLASH_UPDATE_SIZE 6*SECTOR_SIZE_AM29F040
+
+//
+// GetMachineId will return on of these values. The values are
+// 1 and 2 respectively because the macro used with the return
+// of this value is subtracted by one to make sure that zero
+// is not a valid ID number.
+//
+#define MACHINE_ID_PMP_V1 1
+#define MACHINE_ID_PMP_V2 2
+
+#define IS_PMP_V1 ( MACHINE_ID == MACHINE_ID_PMP_V1 )
+#define IS_PMP_V2 ( MACHINE_ID == MACHINE_ID_PMP_V2 )
+
+//
+// The next section provides macros for supporting multiple machine types.
+// This provides an infrastructure from assembly code for machine specific switch
+// statements as well as the ability to retrive machine specific addresses.
+//
+// For example, to do a machine specific switch statement, you could do the
+// following:
+//
+// SWITCH_MACHINE_ID
+//
+// CASE_PMP_V1:
+// assembly code for PMP V1 case...
+// j 90f
+// CASE_PMP_V2:
+// assembly code for PMP V2 case...
+// j 90f
+// 90:
+// continuation of assembly code...
+//
+// The macro MACHINE_SPECIFIC calls GetMachineId to return a unique machine id
+// for this machine type. This is used to index into the jump table at the end
+// of the machine. Be sure to add a jump to the end of each CASE to do accomplish the
+// same as a C break statement.
+//
+// NOTE: These macros .set noreorder, but DO NOT restore it to its original value
+// upon exit. The programmer assumes all responsibility when using this macro!
+//
+// The macro SWITCH_MACHINE_ID_VIRTUAL SHOULD be used once you have jumped to
+// virtual space. It removed the calls to InBootMode which use lots of registers.
+// If you use SWITCH_MACHINE_ID_VIRTUAL, only registers v0 and v1 are used.
+//
+
+#define SWITCH_MACHINE_ID \
+ .set noreorder; \
+ bal GetMachineId; \
+ nop; \
+ sub v0, 1; \
+ sll v1, v0, 2; \
+ lw v1, 80f(v1); \
+ nop; \
+ bal InBootMode; \
+ nop; \
+ beq v0,zero,GoJump; \
+ nop; \
+ li v0,FALLINK_ADDRESS; \
+ subu v1, v0; \
+ li v0,RESET_VECTOR; \
+ addu v1,v0; \
+GoJump: \
+ j v1; \
+ nop; \
+80: /* Case table */ \
+ .word 81f; \
+ .word 82f
+
+#define SWITCH_MACHINE_ID_VIRTUAL \
+ .set noreorder; \
+ move v1, ra; \
+ bal GetMachineId; \
+ nop; \
+ move ra, v1; \
+ sub v0, 1; \
+ sll v1, v0, 2; \
+ lw v1, 80f(v1); \
+ nop; \
+ j v1; \
+ nop; \
+80: /* Case table */ \
+ .word 81f; \
+ .word 82f
+
+#define CASE_PMP_V1 81
+#define CASE_PMP_V2 82
+#define END_SWITCH 73
+#define END_SWITCHf 73f
+
+#include <sidewind.h>
+#include <pcieisa.h>
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// This is the C version of the PMP macro. Note it only has 1 argument, and
+// returns the machine specific address from the array passed in.
+//
+
+#define PMP(x) (x[MACHINE_ID - 1])
+
+#define DPRINT(message) { UCHAR TmpBootFlags; \
+ PUCHAR pCmos = EISA_CONTROL_VIRTUAL_BASE+0x70; \
+ *pCmos = SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ TmpBootFlags = *(pCmos+1); \
+ *pCmos = 0; \
+ if ( TmpBootFlags & BOOT_FLAGS_DPRINTS ) _PrintMsg(message);\
+ }
+
+#define DPRINT32(value) { UCHAR TmpBootFlags; \
+ PUCHAR pCmos = EISA_CONTROL_VIRTUAL_BASE+0x70; \
+ *pCmos = SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ TmpBootFlags = *(pCmos+1); \
+ *pCmos = 0; \
+ if ( TmpBootFlags & BOOT_FLAGS_DPRINTS ) _Print32bitVal(value);\
+ }
+
+
+#else
+
+//
+// This PMP macro is ONLY used for assembler code. It effectively does what
+// the PMP macro above does, but has two arguments instead of one. The first
+// argument is the register to put the address into, the second is the actual
+// array name (which is identical to the #define name). For example, where a
+// piece of assembler currently does:
+//
+// li t1, GLOBAL_CTRL
+//
+// This would be changed to:
+//
+// PMP( t1, GLOBAL_CTRL)
+//
+// And this would yield the machine specific address for GLOBAL_CTRL in t1.
+//
+// NOTE: The reason this macro is wrapped in #ifdef _LANGUAGE_ASSEMBLY is to prevent
+// multiple #defines for PMP. This version of the PMP macro is defined for assembly,
+// the other version above is defined for C.
+//
+
+
+#define PMP(Reg, Array) \
+ .set noreorder; \
+ bal GetMachineId; \
+ nop; \
+ sub v0, 1; \
+ sll v0, 2; \
+ lw Reg, Array(v0); \
+ nop
+
+//
+// PMPv is used in places where we have gone virtual and can now use jal instead of bal.
+// With the current version of the compiler under Daytona, bal can only be used for targets
+// in the same file. The suffix 'v' loosely stands for virtual.
+//
+
+#define PMPv(Reg, Array) \
+ .set noreorder; \
+ jal GetMachineId; \
+ nop; \
+ sub v0, 1; \
+ sll v0, 2; \
+ lw Reg, Array(v0); \
+ nop
+
+//
+// Debug Print Macro
+//
+#define DPRINT(message) \
+ b 77f; \
+ nop; \
+88: .asciiz message; \
+ .align 2; \
+77: li v0, ESC_CMOS_RAM_ADDRESS; \
+ li v1, SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ sb v1, 0(v0); \
+ lbu v0, 1(v0); \
+ andi v0, BOOT_FLAGS_DPRINTS; \
+ beq v0, zero, 89f; \
+ nop; \
+ la a0, 88b; \
+ bal _PrintMsg; \
+ nop; \
+89:
+
+//
+// Debug Print Macro - ONLY print on processor A
+//
+#define DPRINT_A(message) \
+ b 77f; \
+ nop; \
+88: .asciiz message; \
+ .align 2; \
+77: li v0, ESC_CMOS_RAM_ADDRESS; \
+ li v1, SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ sb v1, 0(v0); \
+ lbu v0, 1(v0); \
+ andi v0, BOOT_FLAGS_DPRINTS; \
+ beq v0, zero, 89f; \
+ nop; \
+ PMP( v0, WHOAMI_REG); \
+ lw v0, 0(v0); \
+ bne v0, zero, 89f; \
+ nop; \
+ la a0, 88b; \
+ bal _PrintMsg; \
+ nop; \
+89:
+
+#define DPRINT32(register) \
+ move a0, register; \
+ li v0, ESC_CMOS_RAM_ADDRESS; \
+ li v1, SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ sb v1, 0(v0); \
+ lbu v0, 1(v0); \
+ andi v0, BOOT_FLAGS_DPRINTS; \
+ beq v0, zero, 89f; \
+ nop; \
+ bal _Print32bitVal; \
+ nop; \
+89:
+
+//
+// Just like DPRINT_A, DPRINT32_A will only print on processor A
+//
+#define DPRINT32_A(register) \
+ move a0, register; \
+ li v0, ESC_CMOS_RAM_ADDRESS; \
+ li v1, SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ sb v1, 0(v0); \
+ lbu v0, 1(v0); \
+ andi v0, BOOT_FLAGS_DPRINTS; \
+ beq v0, zero, 89f; \
+ nop; \
+ PMP( v0, WHOAMI_REG); \
+ lw v0, 0(v0); \
+ bne v0, zero, 89f; \
+ nop; \
+ bal _Print32bitVal; \
+ nop; \
+89:
+
+#define EPRINT(message) \
+ b 77f; \
+ nop; \
+88: .asciiz message; \
+ .align 2; \
+77: la a0, 88b; \
+ bal _PrintMsg; \
+ nop
+
+//
+// Debug Print Macro -- DPRINTv("message")
+//
+// DPRINTv is used in places where we have gone virtual, and can now use jal instead of bal.
+// With the current version of the compiler under Daytona, bal can only be used for targets
+// in the same file. The suffix 'v' loosley stands for virtual.
+//
+#define DPRINTv(message) \
+ b 77f; \
+ nop; \
+88: .asciiz message; \
+ .align 2; \
+77: li v0, ESC_CMOS_RAM_ADDRESS; \
+ li v1, SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ sb v1, 0(v0); \
+ lbu v0, 1(v0); \
+ andi v0, BOOT_FLAGS_DPRINTS; \
+ beq v0, zero, 89f; \
+ nop; \
+ la a0, 88b; \
+ jal _PrintMsg; \
+ nop; \
+89:
+
+#define DPRINT32v(register) \
+ move a0, register; \
+ li v0, ESC_CMOS_RAM_ADDRESS; \
+ li v1, SNVRAM_BOOT_FLAGS_OFFSET+RTC_BATTERY_BACKED_UP_RAM; \
+ sb v1, 0(v0); \
+ lbu v0, 1(v0); \
+ andi v0, BOOT_FLAGS_DPRINTS; \
+ beq v0, zero, 89f; \
+ nop; \
+ jal _Print32bitVal; \
+ nop; \
+89:
+
+
+//
+// ZERO_MEMORY Macro, used during memory scrub. Use this macro instead of
+// the function call ZeroMemory, because of the need to copy the code to
+// memory to scrub most of memory found except the top 512k. That 512k of
+// memory is used to run the scrub code and will be scrubbed last.
+//
+#define ZERO_MEMORY(A0Reg, A1Reg) \
+ move t0, A0Reg; \
+ move t1, A1Reg; \
+ addu t1, t0, t1; \
+ mtc1 zero, f2; \
+ mtc1 zero, f3; \
+55: addi t0, 8; \
+ bne t0, t1, 55b; \
+ sdc1 f2, -8(t0)
+
+//
+// Define a load double and store double macro, to use this instruction
+// during assemly programming. To use the defined Mips instructions,
+// the assembler forces these instructions into 2 single 32bit word
+// instructionns. Borrowed from Steve Chang.
+//
+#define LDX(r, b, offset) \
+ .word (0xDC000000 + (r << 16) + (b << 21) + ( 0x0000ffff & offset))
+
+#define SDX(r, b, offset) \
+ .word (0xFC000000 + (r << 16) + (b << 21) + (0x0000ffff & offset))
+
+#endif // _LANGUAGE_ASSEMBLY
+
+//
+// Define global data used for PMP addresses
+//
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// If INITIALIZE_MACHINE_DATA is defined, then all the data structures required to support
+// multiple machine types are declared, otherwise extern's are entered to point to these
+// declarations. The intent is that ONE file will defile INITIALIZE_MACHINE_DATA, and
+// currently that will be fxpmpsup.c in the FW/HAL. All other files will pick up extern
+// references to this data. Note, if you add any structures below, be sure to add an
+// extern reference for the structure as well on the other side of this #ifdef.
+//
+
+#ifdef INITIALIZE_MACHINE_DATA
+
+ULONG MACHINE_ID;
+ULONG WHICH_PROCESSOR;
+
+//
+// Physical and Virtual addresses for the PMP chip
+// used in Falcon. Each array represents a unique
+// register in the PMP chip, and each entry in the
+// array represents a different version of the chip.
+// This is done because the address map for the system
+// control registers was changed between the first
+// version and the second version to optimize the use
+// of TLB entries by the HAL which is allocated only
+// one entry pair on a permanent basis.
+//
+
+//
+// GlobalCtrl
+//
+ULONG GLOBAL_CTRL_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0004),
+ PMP_CONTROL_PHYSICAL_BASE + 0x4
+ };
+
+//
+// WhoAmI
+//
+ULONG WHOAMI_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0008),
+ PMP_CONTROL_PHYSICAL_BASE + 0x8
+ };
+
+//
+// ProcSync
+//
+ULONG PROC_SYNC_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x000C),
+ PMP_CONTROL_PHYSICAL_BASE + 0xC
+ };
+
+//
+// PciStatus
+//
+ULONG PCI_STATUS_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0040),
+ PMP_CONTROL_PHYSICAL_BASE + 0x400040
+ };
+
+//
+// PciCtrl
+//
+ULONG PCI_CTRL_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0044),
+ PMP_CONTROL_PHYSICAL_BASE + 0x400044
+ };
+
+//
+// PciErrAck
+//
+ULONG PCI_ERR_ACK_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0048),
+ PMP_CONTROL_PHYSICAL_BASE + 0x400048
+ };
+
+//
+// PciErrAddr
+//
+ULONG PCI_ERR_ADDR_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x004C),
+ PMP_CONTROL_PHYSICAL_BASE + 0x40004C
+ };
+
+//
+// PciRetry
+//
+ULONG PCI_RETRY_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0060),
+ PMP_CONTROL_PHYSICAL_BASE + 0x500050
+ };
+
+//
+// PciSpaceMap
+//
+ULONG PCI_SPACE_MAP_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0064),
+ PMP_CONTROL_PHYSICAL_BASE + 0x500054
+ };
+
+//
+// PciConfigAddr
+//
+ULONG PCI_CONFIG_ADDR_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0068),
+ PMP_CONTROL_PHYSICAL_BASE + 0x500058
+ };
+
+//
+// MemStatus
+//
+ULONG MEM_STATUS_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0080),
+ PMP_CONTROL_PHYSICAL_BASE + 0x600060
+ };
+
+//
+// MemCtrl
+//
+ULONG MEM_CTRL_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0084),
+ PMP_CONTROL_PHYSICAL_BASE + 0x600064
+ };
+
+//
+// MemErrAck
+//
+ULONG MEM_ERR_ACK_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0088),
+ PMP_CONTROL_PHYSICAL_BASE + 0x600068
+ };
+
+//
+// MemErrAddr
+//
+ULONG MEM_ERR_ADDR_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x008C),
+ PMP_CONTROL_PHYSICAL_BASE + 0x60006C
+ };
+
+//
+// MemCount
+//
+ULONG MEM_COUNT_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x00A0),
+ PMP_CONTROL_PHYSICAL_BASE + 0x700070
+ };
+
+//
+// MemTiming
+//
+ULONG MEM_TIMING_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x00a4),
+ PMP_CONTROL_PHYSICAL_BASE + 0x700074
+ };
+
+//
+// MemDiag
+//
+ULONG MEM_DIAG_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x00a8),
+ PMP_CONTROL_PHYSICAL_BASE + 0x700078
+ };
+
+//
+// IntStatus
+//
+ULONG INT_STATUS_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0100),
+ PMP_CONTROL_PHYSICAL_BASE + 0x300030
+ };
+
+//
+// IntCtrl
+//
+ULONG INT_CONTROL_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0104),
+ PMP_CONTROL_PHYSICAL_BASE + 0x300034
+ };
+
+//
+// IntSetCtrl
+//
+ULONG INT_SET_CTRL_PHYSICAL_BASE[] = {
+ 0,
+ PMP_CONTROL_PHYSICAL_BASE + 0x200028
+ };
+
+//
+// IntSetCtrl
+//
+ULONG INT_CLR_CTRL_PHYSICAL_BASE[] = {
+ 0,
+ PMP_CONTROL_PHYSICAL_BASE + 0x20002C
+ };
+
+//
+// IntCause
+//
+ULONG INT_CAUSE_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0108),
+ PMP_CONTROL_PHYSICAL_BASE + 0x200020
+ };
+
+//
+// IpIntGen
+//
+ULONG IP_INT_GEN_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0114),
+ PMP_CONTROL_PHYSICAL_BASE + 0x300038
+ };
+
+//
+// IpIntAck
+//
+ULONG IP_INT_ACK_PHYSICAL_BASE[] = {
+ PMP_CONTROL_PHYSICAL_BASE + REPLICATE_16(0x0118),
+ PMP_CONTROL_PHYSICAL_BASE + 0x200024
+ };
+
+//
+// Pci Configuration Space
+//
+ULONG PCI_CONFIG_PHYSICAL_BASE[] = {
+ PCI_CONFIG_PHYSICAL_BASE_PMP_V1,
+ PCI_CONFIG_PHYSICAL_BASE_PMP_V2
+ };
+
+//
+// Pci Special Cycle Space
+//
+ULONG PCI_SPECIAL_PHYSICAL_BASE[] = {
+ PCI_SPECIAL_PHYSICAL_BASE_PMP_V1,
+ PCI_SPECIAL_PHYSICAL_BASE_PMP_V2
+ };
+//
+// Pci Interrupt Acknowledge Space
+//
+ULONG PCI_INTERRUPT_PHYSICAL_BASE[] = {
+ PCI_INTERRUPT_PHYSICAL_BASE_PMP_V1,
+ PCI_INTERRUPT_PHYSICAL_BASE_PMP_V2
+ };
+//
+// IO Interrupt Acknowledge Space
+//
+ULONG IO_INT_ACK_PHYSICAL_BASE[] = {
+ PCI_INTERRUPT_PHYSICAL_BASE_PMP_V1,
+ PCI_INTERRUPT_PHYSICAL_BASE_PMP_V2
+ };
+
+//
+// Interrupt Acknowledge Space
+//
+ULONG INTERRUPT_PHYSICAL_BASE[] = {
+ PCI_INTERRUPT_PHYSICAL_BASE_PMP_V1,
+ PCI_INTERRUPT_PHYSICAL_BASE_PMP_V2
+ };
+
+#if !defined(_FALCON_HAL_)
+
+//
+// GlobalCtrl
+//
+ULONG GLOBAL_CTRL[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0004),
+ PMP_CONTROL_VIRTUAL_BASE + 0x4
+ };
+//
+// WhoAmI
+//
+ULONG WHOAMI_REG[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0008),
+ PMP_CONTROL_VIRTUAL_BASE + 0x8
+ };
+//
+// ProcSync
+//
+ULONG PROC_SYNC[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x000C),
+ PMP_CONTROL_VIRTUAL_BASE + 0xC
+ };
+//
+// PciStatus
+//
+ULONG PCI_STATUS[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0040),
+ PMP_CONTROL_VIRTUAL_BASE + 0x400040
+ };
+//
+// PciCtrl
+//
+ULONG PCI_CTRL[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0044),
+ PMP_CONTROL_VIRTUAL_BASE + 0x400044
+ };
+//
+// PciErrAck
+//
+ULONG PCI_ERR_ACK[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0048),
+ PMP_CONTROL_VIRTUAL_BASE + 0x400048
+ };
+//
+// PciErrAddr
+//
+ULONG PCI_ERR_ADDRESS[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x004C),
+ PMP_CONTROL_VIRTUAL_BASE + 0x40004C
+ };
+//
+// PciRetry
+//
+ULONG PCI_RETRY[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0060),
+ PMP_CONTROL_VIRTUAL_BASE + 0x500050
+ };
+//
+// PciSpaceMap
+//
+ULONG PCI_SPACE_MAP[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0064),
+ PMP_CONTROL_VIRTUAL_BASE + 0x500054
+ };
+//
+// PciConfigAddr
+//
+ULONG PCI_CONFIG_ADDRESS[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0068),
+ PMP_CONTROL_VIRTUAL_BASE + 0x500058
+ };
+//
+// MemStatus
+//
+ULONG MEM_STATUS[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0080),
+ PMP_CONTROL_VIRTUAL_BASE + 0x600060
+ };
+//
+// MemCtrl
+//
+ULONG MEM_CTRL[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0084),
+ PMP_CONTROL_VIRTUAL_BASE + 0x600064
+ };
+//
+// MemErrAck
+//
+ULONG MEM_ERR_ACK[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0088),
+ PMP_CONTROL_VIRTUAL_BASE + 0x600068
+ };
+//
+// MemErrAddr
+//
+ULONG MEM_ERR_ADDRESS[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x008C),
+ PMP_CONTROL_VIRTUAL_BASE + 0x60006C
+ };
+//
+// MemCount
+//
+ULONG MEM_COUNT[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x00A0),
+ PMP_CONTROL_VIRTUAL_BASE + 0x700070
+ };
+//
+// MemTiming
+//
+ULONG MEM_TIMING[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x00A4),
+ PMP_CONTROL_VIRTUAL_BASE + 0x700074
+ };
+//
+// MemDiag
+//
+ULONG MEM_DIAG[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x00A8),
+ PMP_CONTROL_VIRTUAL_BASE + 0x700078
+ };
+//
+// IntStatus
+//
+ULONG INT_STATUS[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0100),
+ PMP_CONTROL_VIRTUAL_BASE + 0x300030
+ };
+//
+// IntCtrl
+//
+ULONG INT_CTRL[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0104),
+ PMP_CONTROL_VIRTUAL_BASE + 0x300034
+ };
+//
+// IntSetCtrl
+//
+ULONG INT_SET_CTRL[] = {
+ 0,
+ PMP_CONTROL_VIRTUAL_BASE + 0x200028
+ };
+//
+// IntSetCtrl
+//
+ULONG INT_CLR_CTRL[] = {
+ 0,
+ PMP_CONTROL_VIRTUAL_BASE + 0x20002C
+ };
+//
+// IntCause
+//
+ULONG INT_CAUSE[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0108),
+ PMP_CONTROL_VIRTUAL_BASE + 0x200020
+ };
+//
+// IpIntGen
+//
+ULONG IP_INT_GEN[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0114),
+ PMP_CONTROL_VIRTUAL_BASE + 0x300038
+ };
+//
+// IpIntAck
+//
+ULONG IP_INT_ACK[] = {
+ PMP_CONTROL_VIRTUAL_BASE + REPLICATE_16(0x0118),
+ PMP_CONTROL_VIRTUAL_BASE + 0x200024
+ };
+//
+// Pci Configuration Space
+//
+ULONG PCI_CONFIG_SPACE[] = {
+ PCI_CONFIG_VIRTUAL_BASE + 0x800,
+ PCI_CONFIG_VIRTUAL_BASE + 0x400
+ };
+
+//
+// IO Interrupt Acknowledge Space
+//
+ULONG IO_INT_ACK[] = {
+ PCI_INTERRUPT_VIRTUAL_BASE + 0xC00,
+ PCI_INTERRUPT_VIRTUAL_BASE + 0x200
+ };
+
+#endif // !defined(_FALCON_HAL_)
+
+#else
+
+extern ULONG MACHINE_ID;
+
+extern ULONG GLOBAL_CTRL_PHYSICAL_BASE[];
+extern ULONG GLOBAL_CTRL[];
+extern ULONG WHOAMI_PHYSICAL_BASE[];
+extern ULONG WHOAMI_REG[];
+extern ULONG PROC_SYNC_PHYSICAL_BASE[];
+extern ULONG PROC_SYNC[];
+extern ULONG PCI_STATUS_PHYSICAL_BASE[];
+extern ULONG PCI_STATUS[];
+extern ULONG PCI_CTRL_PHYSICAL_BASE[];
+extern ULONG PCI_CTRL[];
+extern ULONG PCI_ERR_ACK_PHYSICAL_BASE[];
+extern ULONG PCI_ERR_ACK[];
+extern ULONG PCI_ERR_ADDR_PHYSICAL_BASE[];
+extern ULONG PCI_ERR_ADDRESS[];
+extern ULONG PCI_RETRY_PHYSICAL_BASE[];
+extern ULONG PCI_RETRY[];
+extern ULONG PCI_SPACE_MAP_PHYSICAL_BASE[];
+extern ULONG PCI_SPACE_MAP[];
+extern ULONG PCI_CONFIG_ADDR_PHYSICAL_BASE[];
+extern ULONG PCI_CONFIG_ADDRESS[];
+extern ULONG MEM_STATUS_PHYSICAL_BASE[];
+extern ULONG MEM_STATUS[];
+extern ULONG MEM_CTRL_PHYSICAL_BASE[];
+extern ULONG MEM_CTRL[];
+extern ULONG MEM_ERR_ACK_PHYSICAL_BASE[];
+extern ULONG MEM_ERR_ACK[];
+extern ULONG MEM_ERR_ADDR_PHYSICAL_BASE[];
+extern ULONG MEM_ERR_ADDRESS[];
+extern ULONG MEM_COUNT_PHYSICAL_BASE[];
+extern ULONG MEM_COUNT[];
+extern ULONG MEM_TIMING_PHYSICAL_BASE[];
+extern ULONG MEM_TIMING[];
+extern ULONG MEM_DIAG_PHYSICAL_BASE[];
+extern ULONG MEM_DIAG[];
+extern ULONG INT_STATUS_PHYSICAL_BASE[];
+extern ULONG INT_STATUS[];
+extern ULONG INT_CONTROL_PHYSICAL_BASE[];
+extern ULONG INT_CTRL[];
+extern ULONG INT_SET_CTRL_PHYSICAL_BASE[];
+extern ULONG INT_SET_CTRL[];
+extern ULONG INT_CLR_CTRL_PHYSICAL_BASE[];
+extern ULONG INT_CLR_CTRL[];
+extern ULONG INT_CAUSE_PHYSICAL_BASE[];
+extern ULONG INT_CAUSE[];
+extern ULONG IP_INT_GEN_PHYSICAL_BASE[];
+extern ULONG IP_INT_GEN[];
+extern ULONG IP_INT_ACK_PHYSICAL_BASE[];
+extern ULONG IP_INT_ACK[];
+extern ULONG PCI_CONFIG_PHYSICAL_BASE[];
+extern ULONG PCI_CONFIG_SPACE[];
+extern ULONG PCI_SPECIAL_PHYSICAL_BASE[];
+extern ULONG PCI_INTERRUPT_PHYSICAL_BASE[];
+extern ULONG IO_INT_ACK_PHYSICAL_BASE[];
+extern ULONG IO_INT_ACK[];
+extern ULONG INTERRUPT_PHYSICAL_BASE[];
+
+#endif // INITIALIZE_MACHINE_DATA
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _FALCONDEF_
diff --git a/private/ntos/nthals/halntp/mips/falnvram.h b/private/ntos/nthals/halntp/mips/falnvram.h
new file mode 100644
index 000000000..335d0c6a7
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/falnvram.h
@@ -0,0 +1,1075 @@
+/*++
+
+Copyright (c) 1994 NeTpower, Inc.
+
+Module Name:
+
+ falconnvram.h
+
+Abstract:
+
+ This module contains definitions and code (initially) for Falcon NVRAM support.
+ NVRAM is a generic term on Falcon as we have 3 sources of NVRAM (Flash, Sidewinder,
+ EISA Bridge).
+
+--*/
+
+#ifndef _FALCONNVRAM_
+#define _FALCONNVRAM_
+
+//
+// Define the private configuration packet structure, which contains a
+// configuration component as well as pointers to the component's parent,
+// peer, child, and configuration data.
+//
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+
+typedef struct _CONFIGURATION_PACKET {
+ CONFIGURATION_COMPONENT Component;
+ struct _CONFIGURATION_PACKET *Parent;
+ struct _CONFIGURATION_PACKET *Peer;
+ struct _CONFIGURATION_PACKET *Child;
+ PVOID ConfigurationData;
+} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET;
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ UCHAR Version;
+ UCHAR Revision;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+//
+// Defines for the non-volatile configuration tables.
+//
+
+#define NUMBER_OF_ENTRIES 40
+#define LENGTH_OF_IDENTIFIER (1024 - (40*16) - 8)
+#define LENGTH_OF_DATA 2048
+#define LENGTH_OF_ENVIRONMENT 1024
+#define LENGTH_OF_EISA_DATA 2044
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+
+//
+// Additional defines for the second configuration area
+//
+#define NUMBER_OF_ENTRIES2 40
+#define LENGTH_OF_IDENTIFIER2 (1024 - (40*16))
+#define LENGTH_OF_DATA2 1020
+
+//
+// Defines for the volatile configuration tables.
+//
+#define VOLATILE_NUMBER_OF_ENTRIES ( ( NUMBER_OF_ENTRIES + NUMBER_OF_ENTRIES2 ) * 2 )
+#define VOLATILE_LENGTH_OF_IDENTIFIER ( (LENGTH_OF_IDENTIFIER + LENGTH_OF_IDENTIFIER2) * 4 )
+#define VOLATILE_LENGTH_OF_DATA ( (LENGTH_OF_DATA + LENGTH_OF_DATA2) * 4 )
+
+//
+// The volatile configuration table structure.
+//
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[VOLATILE_NUMBER_OF_ENTRIES];
+ UCHAR Identifier[VOLATILE_LENGTH_OF_IDENTIFIER];
+ UCHAR Data[VOLATILE_LENGTH_OF_DATA];
+ UCHAR EisaData[LENGTH_OF_EISA_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+//
+// The non-volatile configuration table structure.
+//
+
+typedef struct _NV_CONFIGURATION {
+
+ //
+ // NOTE: HAL only maps 2 pages for NVRAM. If this grows beyond
+ // 2 pages, the HAL must be changed.
+ //
+ // First Page
+ //
+
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+ UCHAR Checksum1[4];
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT];
+ UCHAR Checksum2[4];
+
+ //
+ // Second Page
+ //
+
+ UCHAR EisaData[LENGTH_OF_EISA_DATA];
+ UCHAR Checksum3[4];
+
+ //
+ // Second configuration area
+ // must fit in 2048 bytes
+ //
+
+ COMPRESSED_CONFIGURATION_PACKET Packet2[NUMBER_OF_ENTRIES2]; // packets on page 2
+ UCHAR Identifier2[LENGTH_OF_IDENTIFIER2]; // identifiers on page 2
+ UCHAR Data2[LENGTH_OF_DATA2]; // data on page 2
+ UCHAR Checksum4[4]; // checksum on page 2
+
+ //
+ // Third page
+ //
+
+ // Ethernet Hardware Address goes in the next 8 bytes, do not use...
+ UCHAR EthernetHWAddress[8];
+ UCHAR FlashWriteCount[4];
+
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+#endif //_LANGUAGE_ASSEMBLY
+
+//
+// The non-volatile data structure contained in the Sidewinder NVRAM
+//
+
+#define SIDEWINDER_NVRAM_MAGIC_NUMBER 0xcafebabe
+#define SIDEWINDER_NVRAM_SIZE 242
+#define READ_SIDEWINDER_NVRAM 1
+#define WRITE_SIDEWINDER_NVRAM 2
+
+#define SNVRAM_MAGIC_OFFSET 0
+#define SNVRAM_FLASH_COUNT_OFFSET 4
+#define SNVRAM_NUM_PROCS_OFFSET 8
+#define SNVRAM_PROC_SPEED_OFFSET 9
+#define SNVRAM_PROC_1_TYPE_OFFSET 10
+#define SNVRAM_PROC_2_TYPE_OFFSET 11
+#define SNVRAM_MEMORY_TYPE_OFFSET 12
+#define SNVRAM_MEMORY_TIMING_OFFSET 13
+#define SNVRAM_ECACHE_PRESENT_OFFSET 17
+#define SNVRAM_MEMORY_TIMING_SET_OFFSET 18
+#define SNVRAM_EXTERNAL_SCSI_DEVICES 19
+#define SNVRAM_SERIAL_PORT_0 20
+#define SNVRAM_SERIAL_PORT_1 21
+#define SNVRAM_PIRQ 22
+#define SNVRAM_SYSAD_SPEED_OFFSET 26
+#define SNVRAM_SYSAD_DIVISOR_OFFSET 27
+#define SNVRAM_MEMORY_SIZE_OFFSET 28
+#define SNVRAM_MEMORY_BANKS_OFFSET 30
+#define SNVRAM_MEMORY_REFRESH_OFFSET 31
+#define SNVRAM_MEMORY_REFRESH_SET_OFFSET 35
+#define SNVRAM_PCACHE_LINESIZE_OFFSET 36
+#define SNVRAM_CHECKSUM_OFFSET 106
+#define SNVRAM_BOOT_FLAGS_OFFSET 113
+
+#define SNVRAM_FLAG_SET 0x94
+#define SNVRAM_PCACHE_DATA 0x1
+#define SNVRAM_PCACHE_INST 0x2
+
+#define BOOT_FLAGS_DPRINTS 0x1
+#define BOOT_FLAGS_SERIAL_OUTPUT 0x2
+#define BOOT_FLAGS_SLOW_TIMING 0x4
+#define BOOT_FLAGS_DISABLE_ECC 0x8
+#define BOOT_FLAGS_K0_EXCLUSIVE 0x10
+#define BOOT_FLAGS_NAKED_ORION 0x20
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Note, this structure has been defined such that the majority of the used fields
+// are in the first half of the RAM, thus the RAM select bit in the Sidewinder does
+// not need to be flipped to access this data. In addition, there are fields in the
+// first half AFTER the checksum. This means that these fields will NOT be a part
+// of the checksum calculation
+//
+
+typedef struct _SIDEWINDER_NV_CONFIGURATION {
+
+ UCHAR Magic[4]; // Magic number, tells if we are initialized
+ UCHAR FlashWriteCount[4]; // Number of times Flash has been written
+ UCHAR NumberOfProcessors; // Number of processors on last boot
+ UCHAR ProcessorSpeed; // Speed of processor
+ UCHAR ProcessorType[2]; // Processors MAY be different. Allows us to check
+ UCHAR MemoryType; // EDO vs. Non-EDO, Parity vs ECC SIMMs
+ UCHAR MemoryTiming[4]; // Last valid memory timing used
+ UCHAR ECachePresent; // Whether ECache was present on last boot
+ UCHAR MemoryTimingSetFlag; // A memory timing value has been entered
+ UCHAR ExternalScsiDevices; // Flag to enable/disable termination for external scsi devices
+ UCHAR SerialPort0; // What is serial port 0 configured as?
+ UCHAR SerialPort1; // What is serial port 1 configured as?
+ UCHAR PIRQ[4]; // PCI interrupt IRQ routing
+ UCHAR SysAdSpeed; // R4XXX SysAd speed
+ UCHAR SysAdDivisor; // R4XXX SysAd divisor
+ UCHAR MemorySize[2]; // Size of memory from last boot
+ UCHAR MemoryBanks; // Number of memory banks from last boot
+ UCHAR MemoryRefresh[4]; // Memory refresh - based on SysAd
+ UCHAR MemoryRefreshSetFlag; // Has memory refresh been set?
+ UCHAR PrimaryCacheLineSize; // Primary Cache line sizes
+
+ // Add new fields AFTER this comment, AND decrease Available by correct number of bytes
+
+ UCHAR Available[69];
+ UCHAR Checksum[4]; // Checksum for the NVRAM
+ UCHAR Temporary0; // Temporary variables that are NOT apart of the
+ UCHAR Temporary1; // calculated checksum
+ UCHAR Temporary2;
+ UCHAR BootFlags; // Boot flags - if this moves, fix hardcode in falcon.s
+
+ // *** End of FIRST half of NVRAM ***
+
+ UCHAR Available1[124]; // Available bytes in other half
+ UCHAR Checksum1[4]; // Checksum for second half of NVRAM
+
+ // *** End of SECOND half of NVRAM ***
+
+} SIDEWINDER_NV_CONFIGURATION, *PSIDEWINDER_NV_CONFIGURATION;
+
+#endif //_LANGUAGE_ASSEMBLY
+
+//
+// Non-volatile ram layout.
+//
+
+#define NVRAM_CONFIGURATION NVRAM_VIRTUAL_BASE
+#define NVRAM_SYSTEM_ID (NVRAM_VIRTUAL_BASE + 0x00002000)
+#endif // _FALCONNVRAM_
+
+#if defined(GENERATE_NVRAM_CODE) && !defined(GENERATED_NVRAM_CODE)
+#define GENERATED_NVRAM_CODE
+
+#include "pcieisa.h"
+#include "sidewind.h"
+
+//
+// To facilitate ease of sharing between the firmware and HAL, the code will exist
+// here (I know it is ugly). Then the files fxnvram.c will simply define this
+// define and include this file. When we get close to release, fxnvram.c will then
+// contain this code, and will be removed from here.
+//
+
+//
+// Falcon is using part of FLASH for NVRAM. Most of support exists in this file.
+// All reads will pass unaltered to the FLASH. All writes to FLASH will be trapped
+// and written to an in memory copy of Flash, then written out to the FLASH whenever
+// the configuration, checksum is changed.
+//
+
+#if !defined(_FALCON_HAL_)
+#define HalpFlashRamBase NVRAM_CONFIGURATION
+#endif
+
+#if defined(_FALCON_HAL_)
+extern BOOLEAN HalpDisplayOwnedByHal;
+#endif
+
+NV_CONFIGURATION MirrorNvram; // Close to 8k
+ULONG MirrorNvramValid = FALSE;
+ULONG DelayFlashWrite = FALSE;
+ULONG HaveFlash = 1;
+
+//
+// Routine prototypes.
+//
+
+VOID
+WRITE_NVRAM_UCHAR (
+ ULONG Address,
+ UCHAR Data
+ );
+
+UCHAR
+READ_NVRAM_UCHAR (
+ ULONG Address
+ );
+
+VOID
+WriteMirrorNvramToFlash(
+ VOID
+ );
+
+VOID
+AccessSidewinderNvram(
+ ULONG Type, // Read or Write
+ ULONG Offset, // Offset into SidewinderNvram
+ PUCHAR Data, // Pointer to Data;
+ ULONG Length // Length to read or write
+ )
+
+/*++
+
+Routine Description:
+
+ This is the routine to use if you want to read/write the Sidewinder NVRAM. Because
+ of the indexing involved, and having to toggle RAMSEL depending on which by you are
+ interested it, it is much easier to encapsulate this into its own routine.
+
+--*/
+
+{
+ PUCHAR pData = Data;
+ PUCHAR SIOIndex, SIOData, RAMIndex, RAMData;
+ ULONG Count, NvramOffset = Offset; // Offset for first byte
+ ULONG High128 = 0;
+ UCHAR RTCcontrol;
+
+ //
+ // Set initial RAMSEL to zero - don't assume last value...
+ //
+#if defined(_FALCON_HAL_)
+ SIOIndex = (PUCHAR)HalpEisaControlBase + 0x398;
+ SIOData = SIOIndex + 1;
+ RAMIndex = (PUCHAR)HalpEisaControlBase + 0x70;
+ RAMData = RAMIndex + 1;
+#else
+ SIOIndex = (PUCHAR)EISA_CONTROL_VIRTUAL_BASE + 0x398;
+ SIOData = SIOIndex + 1;
+ RAMIndex = ESC_CMOS_RAM_ADDRESS;
+ RAMData = ESC_CMOS_RAM_DATA;
+#endif
+
+ WRITE_REGISTER_UCHAR( SIOIndex, SUPERIO_KRR_INDEX );
+ RTCcontrol = READ_REGISTER_UCHAR( SIOData );
+
+ RTCcontrol &= ~SUPERIO_KRR_RAMU128B;
+
+ WRITE_REGISTER_UCHAR( SIOIndex, SUPERIO_KRR_INDEX );
+ WRITE_REGISTER_UCHAR( SIOData, RTCcontrol );
+ WRITE_REGISTER_UCHAR( SIOData, RTCcontrol );
+
+ NvramOffset += RTC_BATTERY_BACKED_UP_RAM;
+
+ for ( Count = 0; Count < Length; Count++ ) {
+ if ( !High128 && NvramOffset >= 128 ) {
+ RTCcontrol |= SUPERIO_KRR_RAMU128B;
+ WRITE_REGISTER_UCHAR( SIOIndex, SUPERIO_KRR_INDEX );
+ WRITE_REGISTER_UCHAR( SIOData, RTCcontrol );
+ WRITE_REGISTER_UCHAR( SIOData, RTCcontrol );
+ High128 = 1;
+ NvramOffset -= 128;
+ }
+
+ WRITE_REGISTER_UCHAR( RAMIndex, (UCHAR)NvramOffset++ );
+ if ( Type == READ_SIDEWINDER_NVRAM ) {
+ *pData++ = READ_REGISTER_UCHAR( RAMData );
+ } else {
+ WRITE_REGISTER_UCHAR( RAMData, *pData++ );
+ }
+ }
+
+ //
+ // Set RAMSEL back to first bank...
+ //
+ RTCcontrol &= ~SUPERIO_KRR_RAMU128B;
+
+ WRITE_REGISTER_UCHAR( SIOIndex, SUPERIO_KRR_INDEX );
+ WRITE_REGISTER_UCHAR( SIOData, RTCcontrol );
+ WRITE_REGISTER_UCHAR( SIOData, RTCcontrol );
+}
+
+BOOLEAN
+SidewinderNvramValid(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks to see if the Sidewinder NVRAM is valid
+
+--*/
+
+{
+ UCHAR MagicChars[4];
+ ULONG MagicNumber;
+
+ AccessSidewinderNvram( READ_SIDEWINDER_NVRAM, 0, &MagicChars[0], 4 );
+ MagicNumber = ( MagicChars[3] << 24 ) | ( MagicChars[2] << 16 ) |
+ ( MagicChars[1] << 8 ) | MagicChars[0];
+
+ if ( MagicNumber != SIDEWINDER_NVRAM_MAGIC_NUMBER ) {
+ return FALSE;
+ }
+ return TRUE;
+
+}
+
+VOID
+InitializeSidewinderNvram(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Sidewinder NVRAM.
+
+--*/
+
+{
+ UCHAR InitialSNvram[SIDEWINDER_NVRAM_SIZE];
+ PSIDEWINDER_NV_CONFIGURATION pInitialSNvram = (PSIDEWINDER_NV_CONFIGURATION)&InitialSNvram;
+ ULONG Count;
+
+ //
+ // Scrub NVRAM
+ //
+ for ( Count = 0; Count < SIDEWINDER_NVRAM_SIZE; Count++ ) {
+ InitialSNvram[Count] = 0x0;
+ }
+
+ //
+ // Initialize the magic number header
+ //
+
+ pInitialSNvram->Magic[0] = (UCHAR)SIDEWINDER_NVRAM_MAGIC_NUMBER;
+ pInitialSNvram->Magic[1] = (UCHAR)( SIDEWINDER_NVRAM_MAGIC_NUMBER >> 8 );
+ pInitialSNvram->Magic[2] = (UCHAR)( SIDEWINDER_NVRAM_MAGIC_NUMBER >> 16 );
+ pInitialSNvram->Magic[3] = (UCHAR)( SIDEWINDER_NVRAM_MAGIC_NUMBER >> 24 );
+
+ AccessSidewinderNvram( WRITE_SIDEWINDER_NVRAM, 0, (PUCHAR)pInitialSNvram, SIDEWINDER_NVRAM_SIZE );
+
+ // XXX Checksum!
+}
+
+VOID
+WRITE_NVRAM_UCHAR (
+ ULONG Address,
+ UCHAR Data
+ )
+{
+ PUCHAR pMirrorNvram, pFlash;
+ ULONG Counter;
+ //
+ // When this routine is called, first check to see if MirrorNvramValid is FALSE.
+ // If it is FALSE, this is the first time a write has been called since the last
+ // write to the FLASH. This means we must first READ the FLASH to set get a copy
+ // of the FLASH into MirrorNvram
+ //
+ // Then, any and all writes are done to MirrorNvram. Then in the key *Save* routines,
+ // MirrorNvram will be rewritten back out to FLASH, and MirrorNvramValid will be set
+ // to FALSE.
+ //
+
+ if ( ( (PUCHAR)Address < (PUCHAR)HalpFlashRamBase ) ||
+ (((PUCHAR)Address - (PUCHAR)HalpFlashRamBase) > sizeof(NV_CONFIGURATION)) ) {
+#if defined(_FALCON_HAL_)
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("WRITE_NVRAM_UCHAR - outside range of NVRAM\r\n");
+ }
+#else
+ FwPrint("WRITE_NVRAM_UCHAR - Address: 0x%x\r\n", Address);
+#endif
+ }
+ if ( !MirrorNvramValid ) {
+
+ pFlash = (PUCHAR)HalpFlashRamBase;
+
+ pMirrorNvram = (PUCHAR)&MirrorNvram;
+ for ( Counter = 0; Counter < sizeof(NV_CONFIGURATION); Counter++ ) {
+ *pMirrorNvram++ = *pFlash++;
+ }
+ MirrorNvramValid = TRUE;
+ }
+
+ pMirrorNvram = (PUCHAR)&MirrorNvram + ( (PUCHAR)Address - (PUCHAR)HalpFlashRamBase );
+
+ *pMirrorNvram = Data;
+}
+
+UCHAR
+READ_NVRAM_UCHAR (
+ ULONG Address
+ )
+{
+ PUCHAR pMirrorNvram;
+
+ //
+ // When this routine is called, first check to see if MirrorNvramValid is FALSE.
+ // If it is FALSE, return byte from FLASH, otherwise return byte from MirrorNvram.
+ //
+ // This routine should ONLY be used in loops calculating checksums in
+ // FwConfigurationSetChecksum()
+ // FwEnvironmentSetChecksum()
+ //
+
+ if ( ( (PUCHAR)Address < (PUCHAR)HalpFlashRamBase ) ||
+ (((PUCHAR)Address - (PUCHAR)HalpFlashRamBase) > sizeof(NV_CONFIGURATION)) ) {
+#if defined(_FALCON_HAL_)
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("READ_NVRAM_UCHAR - outside range of NVRAM\r\n");
+ }
+#else
+ FwPrint("READ_NVRAM_UCHAR - Address: 0x%x 0x%x 0x%x\r\n", Address, sizeof(NV_CONFIGURATION), HalpFlashRamBase);
+#endif
+ }
+ if ( !MirrorNvramValid ) {
+ return READ_REGISTER_UCHAR( Address );
+ }
+
+ pMirrorNvram = (PUCHAR)&MirrorNvram + ( (PUCHAR)Address - (PUCHAR)HalpFlashRamBase );
+
+ return(*pMirrorNvram);
+}
+
+VOID
+EnableFlashWrite(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the appropriate bits to enabling writing to the FLASH.
+
+ Note: This code is NOT specific to any particular FLASH part.
+
+--*/
+
+{
+ UCHAR Data;
+
+ //
+ // Enable BIOS Write
+ //
+
+#if defined(_FALCON_HAL_)
+
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[0], ESC_CONFIG_BIOS_CSB );
+ Data = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[1] );
+ Data |= ESC_BIOS_CSB_BIOSWREN;
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[1], Data );
+
+#else
+
+ WRITE_REGISTER_UCHAR( ESC_CONFIG_INDEX_ADDRESS, ESC_CONFIG_BIOS_CSB );
+ Data = READ_REGISTER_UCHAR( ESC_CONFIG_INDEX_DATA );
+ Data |= ESC_BIOS_CSB_BIOSWREN;
+ WRITE_REGISTER_UCHAR( ESC_CONFIG_INDEX_DATA, Data );
+
+#endif // _FALCON_HAL_
+
+
+}
+
+VOID
+DisableFlashWrite(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the appropriate bits to enabling writing to the FLASH.
+
+ Note: This code is NOT specific to any particular FLASH part.
+
+--*/
+
+{
+ UCHAR Data;
+
+ //
+ // Disable BIOS Write
+ //
+
+#if defined(_FALCON_HAL_)
+
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[0], ESC_CONFIG_BIOS_CSB );
+ Data = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[1] );
+ Data &= ~ESC_BIOS_CSB_BIOSWREN;
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[0], ESC_CONFIG_BIOS_CSB );
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Reserved1[1], Data );
+
+#else
+
+ WRITE_REGISTER_UCHAR( ESC_CONFIG_INDEX_ADDRESS, ESC_CONFIG_BIOS_CSB );
+ Data = READ_REGISTER_UCHAR( ESC_CONFIG_INDEX_DATA );
+ Data &= ~ESC_BIOS_CSB_BIOSWREN;
+ WRITE_REGISTER_UCHAR( ESC_CONFIG_INDEX_DATA, Data );
+
+#endif _FALCON_HAL_
+
+}
+
+BOOLEAN
+EraseFlashSector(
+ ULONG SectorAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will erase the specified sector in the FLASH.
+
+ Note: These algorithms are AM29F040 specific!
+
+Arguments:
+
+ SectorAddress - base address of the sector to erase
+
+Return Value:
+
+ TRUE/FALSE indicating successful erasure.
+
+--*/
+
+{
+ UCHAR Data;
+ ULONG Count;
+ BOOLEAN Status = TRUE;
+
+ if ( !HaveFlash ) return TRUE;
+
+ //
+ // Set approriate bits to enable FLASH write...
+ //
+ EnableFlashWrite();
+
+ //
+ // First perform the unlock sequence for the AM29F040
+ //
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xAA );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x2AAA, 0x55 );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0x80 );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xAA );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x2AAA, 0x55 );
+
+ // Send Erase Sector Command...
+ WRITE_REGISTER_UCHAR( SectorAddress, 0x30 );
+
+ //
+ // Wait for PROM to be erased.
+ //
+ for (Count = 0; Count < 6000; Count++) {
+#if defined(_FALCON_HAL_)
+ KeStallExecutionProcessor(1000);
+#else
+ FwStallExecution(1000);
+#endif // _FALCON_HAL_
+ Data = READ_REGISTER_UCHAR( SectorAddress );
+ if ((Data & 0x80) != 0 ) {
+ break;
+ }
+ }
+ if ((Data & 0x80) == 0 ) {
+#if defined(_FALCON_HAL_)
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("Unable to erase prom.\r\n");
+ }
+#else
+ FwPrint("Unable to erase prom.\r\n");
+#endif // _FALCON_HAL_
+ Status = FALSE;
+ }
+ DisableFlashWrite();
+
+ return Status;
+}
+
+VOID
+UpdateFlashWriteCount(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will update the Flash write count that exists in the Flash AND
+ Sidewinder NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG FlashWriteCount, SidewinderWriteCount;
+
+ PNV_CONFIGURATION Nvram = (PNV_CONFIGURATION)HalpFlashRamBase;
+ // XXX Fixup for HAL
+ PSIDEWINDER_NV_CONFIGURATION SNvram = (PSIDEWINDER_NV_CONFIGURATION)SIDEWINDER_NVRAM_VIRTUAL_BASE;
+
+ //
+ // Read count
+ //
+
+ FlashWriteCount = (ULONG)READ_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[0] ) |
+ (ULONG)READ_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[1] ) << 8 |
+ (ULONG)READ_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[2] ) << 16 |
+ (ULONG)READ_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[3] ) << 24 ;
+
+
+#if defined(_FALCON_HAL_)
+ if ( FlashWriteCount == 0 ) {
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("WARNING: FlashWriteCount == 0\r\n");
+ }
+ }
+
+ if ( FlashWriteCount > 95000 ) {
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("WARNING: Flash soon to EXCEED maximum writes\r\n");
+ }
+ }
+#else
+ if ( FlashWriteCount == 0 ) {
+ StatusDisplay("WARNING: FlashWriteCount == 0");
+ }
+
+ if ( FlashWriteCount > 95000 && FlashWriteCount <= 100000 ) {
+ StatusDisplay("WARNING: Flash soon to EXCEED maximum writes (%d)", FlashWriteCount);
+ } else if ( FlashWriteCount > 100000 ) {
+ StatusDisplay("WARNING: Flash write count corrupted (0x%x)", FlashWriteCount);
+ FlashWriteCount = 0;
+ }
+#endif // _FALCON_HAL_
+
+
+ if ( SidewinderNvramValid() == FALSE ) {
+ InitializeSidewinderNvram();
+ }
+
+ AccessSidewinderNvram( READ_SIDEWINDER_NVRAM, SNVRAM_FLASH_COUNT_OFFSET,
+ (PUCHAR)&SidewinderWriteCount, sizeof(SidewinderWriteCount) );
+
+ if ( SidewinderWriteCount > 10000 ) {
+#if !defined(_FALCON_HAL_)
+ StatusDisplay("WARNING: Sidewinder write count corrupted (0x%x)", SidewinderWriteCount);
+#endif
+ SidewinderWriteCount = 0;
+ }
+
+#if defined(_FALCON_HAL_)
+
+ if ( SidewinderWriteCount != FlashWriteCount ) {
+
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("WARNING: Sidewinder != Flash write count\r\n");
+ }
+
+ if ( FlashWriteCount != 0 ) {
+ SidewinderWriteCount = FlashWriteCount;
+ } else {
+ FlashWriteCount = SidewinderWriteCount;
+ }
+ }
+ FlashWriteCount++;
+ SidewinderWriteCount++;
+
+#else
+
+ if ( SidewinderWriteCount != FlashWriteCount ) {
+ StatusDisplay("WARNING: Sidewinder != Flash write counts 0x%x vs. 0x%x",
+ SidewinderWriteCount, FlashWriteCount);
+ if ( FlashWriteCount != 0 && FlashWriteCount != 0xFFFFFFFF ) {
+ SidewinderWriteCount = FlashWriteCount;
+ } else {
+ FlashWriteCount = SidewinderWriteCount;
+ }
+ }
+ FlashWriteCount++;
+ SidewinderWriteCount++;
+
+#endif // _FALCON_HAL_
+
+ //
+ // Write counts. First write count that resides in the FLASH using special macros.
+ // Then write count that resides in the Sidewinder NVRAM with regular macro.
+ //
+
+ WRITE_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[0], (UCHAR)FlashWriteCount);
+ WRITE_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[1], (UCHAR)(FlashWriteCount >> 8));
+ WRITE_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[2], (UCHAR)(FlashWriteCount >> 16));
+ WRITE_NVRAM_UCHAR( (ULONG) &Nvram->FlashWriteCount[3], (UCHAR)(FlashWriteCount >> 24));
+
+ AccessSidewinderNvram( WRITE_SIDEWINDER_NVRAM, SNVRAM_FLASH_COUNT_OFFSET,
+ (PUCHAR)&SidewinderWriteCount, sizeof(SidewinderWriteCount) );
+
+}
+
+BOOLEAN
+ProgramFlashSector(
+ ULONG SectorAddress,
+ ULONG SectorSize,
+ PUCHAR ImageAddress,
+ ULONG ImageSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will program the specified sector in the FLASH.
+
+ If the amount of data we are writing is LESS than the sector size,
+ then fill the rest of the sector in with ZERO.
+
+ Note: These algorithms are AM29F040 specific!
+
+Arguments:
+
+ SectorAddress - base address of the sector to be programmed
+ SectorSize - size of the physical sector
+ ImageAddress - base address of image to write to FLASH sector
+ ImageSize - size of image
+
+Return Value:
+
+ TRUE/FALSE indicating successful programming.
+
+--*/
+
+{
+ UCHAR Data;
+ PUCHAR pImage;
+ ULONG Count;
+ BOOLEAN Status = TRUE;
+
+ //
+ // Set approriate bits to enable FLASH write...
+ //
+ EnableFlashWrite();
+
+ pImage = (PUCHAR)ImageAddress;
+ for (Count = 0; Count < SectorSize; Count++) {
+
+ if ( HaveFlash ) {
+ //
+ // First perform the unlock sequence for the AM29F040
+ //
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xAA );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x2AAA, 0x55 );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xA0 );
+ }
+
+ WRITE_REGISTER_UCHAR( SectorAddress + Count, Count < ImageSize ? *pImage: 0 );
+
+ do {
+ Data = READ_REGISTER_UCHAR( SectorAddress + Count );
+ } while (Data != ( Count < ImageSize ? *pImage : 0 ) );
+ pImage++;
+ }
+
+ DisableFlashWrite();
+
+ pImage = (PUCHAR)ImageAddress;
+ for (Count = 0; Count < ImageSize; Count++) {
+
+ Data = READ_REGISTER_UCHAR( SectorAddress + Count );
+
+#if defined(_FALCON_HAL_)
+
+ if ( *pImage != Data ) {
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("..Error\r\n");
+ }
+ return FALSE;
+ }
+
+ if ((Count & 0x3FFF) == 0) {
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ // HalDisplayString(".");
+ }
+ }
+
+#else
+
+ if ( *pImage != Data ) {
+ FwPrint("..Error mismatch\r\n");
+ return FALSE;
+ }
+
+ if ((Count & 0x3FFF) == 0) {
+ // Don't need status...
+ // FwPrint(".");
+ }
+
+#endif // _FALCON_HAL_
+
+ pImage++;
+
+ }
+
+ return Status;
+}
+
+ULONG
+FlashOrPromICE(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine whether the system has a Flash or PromICE
+ plugged in.
+
+--*/
+
+{
+ PUCHAR SectorAddress = HalpFlashRamBase;
+ UCHAR Saved1, Saved2;
+ ULONG IsFlash;
+
+ //
+ // Set approriate bits to enable FLASH write...
+ //
+ EnableFlashWrite();
+
+ //
+ // Save characters in case this is NOT Flash
+ //
+ Saved1 = READ_REGISTER_UCHAR( SectorAddress + 0x5555 );
+ Saved2 = READ_REGISTER_UCHAR( SectorAddress + 0x2AAA );
+
+ //
+ // First perform the unlock sequence for the AM29F040
+ //
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xAA );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x2AAA, 0x55 );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0x90 );
+
+ if ( READ_REGISTER_UCHAR( SectorAddress ) != 0x01 &&
+ READ_REGISTER_UCHAR( SectorAddress + 1 ) != 0xA4 ) {
+ IsFlash = 0;
+ } else {
+ IsFlash = 1;
+ }
+
+ if ( !IsFlash ) {
+ //
+ // Restore trashed bytes...
+ //
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, Saved1 );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x2AAA, Saved2 );
+ } else {
+ //
+ // Put Flash back into normal mode
+ //
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xAA );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x2AAA, 0x55 );
+ WRITE_REGISTER_UCHAR( SectorAddress + 0x5555, 0xF0 );
+ }
+
+ DisableFlashWrite();
+
+ return( IsFlash );
+}
+
+VOID
+WriteMirrorNvramToFlash(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will write the mirrored NVRAM to the FLASH sector dedicated to
+ hold the non-volatile data. It will call generic FLASH routines that will be
+ used to alter the FLASH in other parts of the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if ( DelayFlashWrite == TRUE ) {
+ return;
+ }
+
+#if !defined(_FALCON_HAL_)
+ // For debug mostly...
+ StatusDisplay("Updating Flash...");
+#endif
+
+ //
+ // First determine whether we have a Flash or PromICE plugged in
+ //
+ HaveFlash = FlashOrPromICE();
+
+ //
+ // Update the Flash write count. Need to do this in order to have
+ // the MirrorNvram correctly setup before erasing the Flash nvram.
+ //
+ UpdateFlashWriteCount();
+
+ //
+ // We are now ready to copy the contents of MirrorNvram out to the Flash, and set
+ // the MirrorNvramValid to FALSE
+ //
+
+ if ( EraseFlashSector((ULONG)HalpFlashRamBase) == FALSE ) {
+
+ //
+ // Failed to erase, simply return, and do not reset MirrorNvramValid.
+ // We will just have to run out of the Mirror which is like NO changes
+ // were made.
+ //
+#if defined(_FALCON_HAL_)
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("ERROR: WriteMirrorNvramToFlash() failed to erase FLASH\n\r");
+ }
+#else
+ FwPrint("ERROR: WriteMirrorNvramToFlash() failed to erase FLASH\n\r");
+#endif
+ return;
+ }
+
+ if ( ProgramFlashSector( (ULONG)HalpFlashRamBase, SECTOR_SIZE_AM29F040,
+ (PUCHAR)&MirrorNvram, sizeof(NV_CONFIGURATION) ) == FALSE ) {
+#if defined(_FALCON_HAL_)
+ if ( HalpDisplayOwnedByHal == TRUE ) {
+ HalDisplayString("ERROR: WriteMirrorNvramToFlash() failed to program FLASH\n\r");
+ }
+#else
+ FwPrint("ERROR: WriteMirrorNvramToFlash() failed to program FLASH\n\r");
+#endif
+ return;
+ }
+
+ MirrorNvramValid = FALSE;
+#if !defined(_FALCON_HAL_)
+ StatusClear();
+#endif
+}
+
+#endif // GENERATE_NVRAM_CODE
+
diff --git a/private/ntos/nthals/halntp/mips/falreg.h b/private/ntos/nthals/halntp/mips/falreg.h
new file mode 100644
index 000000000..41403af48
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/falreg.h
@@ -0,0 +1,393 @@
+
+#ifndef _FALCONREG_
+#define _FALCONREG_
+
+#include <faldef.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// //
+// //
+// Define Register bit definitions //
+// //
+// //
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Global Status register bit definitions
+//
+// Global status MC bit (0 = 64 bits, 1 = 128 bits)
+//
+#define GLOBAL_STATUS_MC REPLICATE_16(0x0001) // defines memory configuration
+#define GLOBAL_STATUS_MP REPLICATE_16(0x0002) // 2nd processor present (Processor B)
+#define GLOBAL_STATUS_ECP REPLICATE_16(0x0004) // external cache present
+#define GLOBAL_STATUS_MASK REPLICATE_16(0x0007) // Global Status register bit mask
+
+#define GLOBAL_STATUS_REV_MASK REPLICATE_16(0xFF00) // revision id field
+#define GLOBAL_STATUS_REVID_0 REPLICATE_16(0x0000) // revision id for 1.0 chip
+#define GLOBAL_STATUS_REVID_2 REPLICATE_16(0x0200) // revision id for 2.0 chip
+#define GLOBAL_STATUS_REVID_3 REPLICATE_16(0x0300) // revision id for 3.0 chip
+
+//
+// Global Ctrl register bit definitions
+//
+#define GLOBAL_CTRL_BMA REPLICATE_16(0x0001) // BootMode Processor A
+#define GLOBAL_CTRL_BMB REPLICATE_16(0x0002) // BootMode Processor B
+#define GLOBAL_CTRL_PCR REPLICATE_16(0x0004) // PCI EISA/ISA bus device reset
+#define GLOBAL_CTRL_PBE REPLICATE_16(0x0008) // Release Processor B, full sys access
+#define GLOBAL_CTRL_PWC0 REPLICATE_16(0x0000) // PCI write coherency control - none
+ // No hardware I/O consistancy
+#define GLOBAL_CTRL_PWC1 REPLICATE_16(0x0010) // R4K caches inv on all PCI write
+ // transactions from devs on PCI bus
+#define GLOBAL_CTRL_PWC2 REPLICATE_16(0x0020) // R4k caches inv on all PCI write & inv
+ // transactions from devs on PCI bus
+#define GLOBAL_CTRL_PRI REPLICATE_16(0x0040) // PCI read & invalidate command
+#define GLOBAL_CTRL_ECE REPLICATE_16(0x0080) // External cache enable
+#define GLOBAL_CTRL_ECL REPLICATE_16(0x0300) // External Cache Line Size (see R4x00 config reg)
+#define GLOBAL_CTRL_ECL1 REPLICATE_16(0x0100) // E-Cache 32 byte line size
+#define GLOBAL_CTRL_ECL2 REPLICATE_16(0x0200) // E-Cache 64 byte line size
+#define GLOBAL_CTRL_SRE REPLICATE_16(0x0400) // Slow memory read enable
+#define GLOBAL_CTRL_SME REPLICATE_16(0x0800) // Slow miss enable
+#define GLOBAL_CTRL_MASK REPLICATE_16(0x00ff) // Global Ctrl bit mask
+#define GLOBAL_CTRL_MASK_PMP_V2 REPLICATE_16(0x03ff) // Global Ctrl bit mask
+
+//
+// WhoAmi register bit definitions
+//
+#define WHOAMI_PROC_A REPLICATE_16(0x0000) // Processor A initiates read
+#define WHOAMI_PROC_B REPLICATE_16(0x0001) // Processor B initiates read
+#define WHOAMI_REG_MASK WHOAMI_PROC_B // WhoAmI register bit mask
+
+//
+// PCI Status register bit definitions
+//
+#define PCI_STATUS_ME REPLICATE_16(0x0001) // PCI detected multiple errors
+#define PCI_STATUS_RSE REPLICATE_16(0x0002) // Recvd system error from PCI bus
+#define PCI_STATUS_RER REPLICATE_16(0x0004) // Recvd excess # of retries
+#define PCI_STATUS_IAE REPLICATE_16(0x0008) // Access error
+#define PCI_STATUS_MPE REPLICATE_16(0x0010) // Master parity error
+#define PCI_STATUS_RTA REPLICATE_16(0x0020) // Recvd target abort
+#define PCI_STATUS_RMA REPLICATE_16(0x0040) // Recvd master abort
+#define PCI_STATUS_CFG REPLICATE_16(0x0080) // Config write to PMP occurred
+#define PCI_STATUS_FER REPLICATE_16(0x0100) // Error occurred on first word of read
+#define PCI_STATUS_RW REPLICATE_16(0x0200) // R/W bit (0 = Write, 1 = Read)
+#define PCI_STATUS_CMD REPLICATE_16(0x1E00) // Pci command field
+#define PCI_STATUS_MASK REPLICATE_16(0x1fff) // PCI Status register bit mask
+#define PCI_STATUS_CMD_PMP_V2 REPLICATE_16(0x3C00) // Pci command field
+#define PCI_STATUS_MASK_PMP_V2 REPLICATE_16(0x3fff) // PCI Status register bit mask
+
+
+//
+// PCI Ctrl register bit definitions
+//
+#define PCI_CTRL_RPS0 REPLICATE_16(0x0000) // PCI read prefetch size = 8/16 bytes
+#define PCI_CTRL_RPS1 REPLICATE_16(0x0001) // PCI read prefetch size = 16/32 bytes
+#define PCI_CTRL_RPS2 REPLICATE_16(0x0002) // PCI read prefetch size = 24/48 bytes
+#define PCI_CTRL_RPS3 REPLICATE_16(0x0003) // PCI read prefetch size = 32/64 bytes
+#define PCI_CTRL_MSO REPLICATE_16(0x0004) // Set, adds 0x40000000 to sys mem addrs
+#define PCI_CTRL_FBP REPLICATE_16(0x0008) // Force bad parity on PCI bus
+#define PCI_CTRL_RAP REPLICATE_16(0x0010) // Report all parity errors on bus
+#define PCI_CTRL_ELR REPLICATE_16(0x0020) // Read/Write burst control
+#define PCI_CTRL_MASK REPLICATE_16(0x001f) // PCI Ctrl register bit mask
+#define PCI_CTRL_MASK_PMP_V2 REPLICATE_16(0x003f) // PCI Ctrl register bit mask
+
+
+
+//
+// PCI Err Ack register bit definitions
+//
+#define PCI_ERR_ACK_MASK PCI_STATUS_MASK // PCI err ack bit mask
+
+//
+// PCI Err Addr register bit definitions
+//
+#define PCI_ERR_ADDR_MASK_PMP_V2 0xffffffff // PCI err addr bit mask
+#define PCI_ERR_ADDR_RW_PMP_V2 0x00000000 // PCI err addr rw bit (!!removed!!)
+#define PCI_ERR_ADDR_RW 0x80000000 // PCI err addr rw bit
+#define PCI_ERR_ADDR_MASK 0x7fffffff // PCI err addr bit mask
+
+//
+// PCI Retry register bit definitions
+//
+#define PCI_RETRY_COUNT REPLICATE_16(0x00ff) // PCI retry count field
+#define PCI_RETRY_MASK REPLICATE_16(0x00ff) // PCI retry count bit mask
+
+//
+// PCI Space Map register bit definitions
+//
+#define PCI_SPACE_MAP_NIB0 REPLICATE_16(0x000f) // PCI bus addrs bit 28 is = 0
+#define PCI_SPACE_MAP_NIB1 REPLICATE_16(0x00f0) // PCI bus addrs bit 28 is = 1
+#define PCI_SPACE_MAP_MASK REPLICATE_16(0x00ff) // PCI Space Map bit mask
+
+//
+// PCI Config Addr register bit definitions
+//
+#define PCI_CONFIG_ADDR_TYPE0 0x00000000 // PCI local bus access
+#define PCI_CONFIG_ADDR_TYPE1 0x00000001 // PCI remote bus access
+#define PCI_CONFIG_ADDR_FUNCNUM 0x00000700 // PCI remote bus config mask
+#define PCI_CONFIG_ADDR_REMDEVNUM 0x0000f800 // PCI remote bus dev mask
+#define PCI_CONFIG_ADDR_REMBUSNUM 0x00ff0000 // PCI remote bus target mask
+#define PCI_CONFIG_ADDR_MASK 0x00ffff01 // PCI remote bus access
+
+//
+// PCI Config Select register bit definitions
+//
+#define PCI_CONFIG_DIS_ISA 0x00 // PCI-ISA disable configuration access
+#define PCI_CONFIG_SEL_ISA 0x01 // PCI-ISA select configuration access
+#define PCI_CONFIG_SEL_ENET 0x02 // PCI-ENET select configuration access
+#define PCI_CONFIG_SEL_SCSI 0x04 // PCI-SCSI select configuration access
+#define PCI_CONFIG_SEL_VID 0x08 // PCI-VID select configuration access
+#define PCI_CONFIG_SEL_SLOT0 0x10 // PCI-SLOT0 select configuration access
+#define PCI_CONFIG_SEL_SLOT1 0x20 // PCI-SLOT1 select configuration access
+#define PCI_CONFIG_SEL_SLOT2 0x40 // PCI-SLOT2 select configuration access
+#define PCI_CONFIG_SEL_PROC 0x80 // PCI-PROC select configuration access
+#define PCI_CONFIG_SEL_MASK 0xff // PCI select configuration access mask
+
+//
+// PCI Other Addr register bit definitions
+//
+#define PCI_OTHER_ADDR_MASK 0x00000000 // PCI Other Addr bit mask
+
+//
+// PCI Special register bit definitions
+//
+#define PCI_SPECIAL_MASK 0xffffffff // PCI Special bit mask
+
+//
+// MEM Status register bit definitions
+//
+#define MEM_STATUS_EUE 0x00000001 // UnCorrectable err on even hw memory
+#define MEM_STATUS_ECE 0x00000004 // Correctable err on even hw memory
+#define MEM_STATUS_OUE 0x00010000 // UnCorrectable err on odd hw memory
+#define MEM_STATUS_OCE 0x00040000 // Correctable err on odd hw memory
+#define MEM_STATUS_MUE REPLICATE_16(0x0002) // Multiple UnCorrectable errors
+#define MEM_STATUS_MCE REPLICATE_16(0x0008) // Multiple Correctable errors
+#define MEM_STATUS_FER REPLICATE_16(0x0010) // Error occurred on first word of read
+#define MEM_STATUS_ESYN 0x0000ff00 // Even HalfWord error Syndrome
+#define MEM_STATUS_OSYN 0xff000000 // ODD HalfWord error Syndrome
+#define MEM_STATUS_MASK REPLICATE_16(0xff1f) // Mem status register Mask
+
+//
+// MEM Ctrl register bit definitions
+//
+#define MEM_CTRL_CHKSEL0 REPLICATE_16(0x0000) // Diagnostic Mode
+#define MEM_CTRL_CHKSEL1 REPLICATE_16(0x0001) // ECC enable Mode
+#define MEM_CTRL_RCE REPLICATE_16(0x0004) // Report Correctable errors
+#define MEM_CTRL_RRC REPLICATE_16(0x0008) // Reset refresh counter
+#define MEM_CTRL_RD0 REPLICATE_16(0x0010) // Refresh disable sys addrs REPLICATE_16(0x00000000
+ // & sys addrs 0x40000000
+#define MEM_CTRL_RD1 REPLICATE_16(0x0020) // Refresh disable sys addrs 0x10000000
+ // & sys addrs 0x50000000
+#define MEM_CTRL_RD2 REPLICATE_16(0x0040) // Refresh disable sys addrs 0x20000000
+ // & sys addrs 0x60000000
+#define MEM_CTRL_RD3 REPLICATE_16(0x0080) // Refresh disable sys addrs 0x30000000
+ // & sys addrs 0x70000000
+#define MEM_CTRL_MASK REPLICATE_16(0x00ff) // Mem Control register mask
+
+//
+// MEM Err Ack register bit definitions
+//
+#define MEM_ERR_ACK_MASK MEM_STATUS_MASK // MEM err ack bit mask
+
+//
+// MEM Error Addr register bit definitions
+//
+#define MEM_ERR_ADDR_SRC 0x00000001 // Source of failed memory access
+#define MEM_ERR_ADDR_RW 0x80000000 // Access type failure
+#define MEM_ERR_ADDR_MASK 0x7ffffff8 // Sys address of last memory failure
+
+
+//
+// MEM Count register bit definitions
+//
+// XXX Check these with David B.
+#define MEM_COUNT_MASK 0xffffffff // MEM count bit mask
+#define MEM_COUNT_44MHZ_VALUE REPLICATE_16(0x02B0) // Memory refresh for 44MHz proc
+#define MEM_COUNT_50MHZ_VALUE REPLICATE_16(0x030D) // Memory refresh for 50MHz proc
+#define MEM_COUNT_67MHZ_VALUE REPLICATE_16(0x0411) // Memory refresh for 67MHz proc
+
+//
+// MEM Timing register bit definitions
+//
+#define MEM_TIMING_EDO REPLICATE_16(0x0001) // EDO Memory mode
+#define MEM_TIMING_RCW0 REPLICATE_16(0x0000) // Read CAS width of 3 Cycles
+#define MEM_TIMING_RCW1 REPLICATE_16(0x0002) // Read CAS width of 2 Cycles
+#define MEM_TIMING_RCW2 REPLICATE_16(0x0004) // Read CAS width of 1 Cycles
+#define MEM_TIMING_RCW3 REPLICATE_16(0x0006) // Illegal Read CAS width
+#define MEM_TIMING_WCW0 REPLICATE_16(0x0000) // Write CAS width of 3 Cycles
+#define MEM_TIMING_WCW1 REPLICATE_16(0x0008) // Write CAS width of 2 Cycles
+#define MEM_TIMING_WCW2 REPLICATE_16(0x0010) // Write CAS width of 1 Cycles
+#define MEM_TIMING_WCW3 REPLICATE_16(0x0018) // Illegal Write CAS width
+#define MEM_TIMING_RCA0 REPLICATE_16(0x0000) // RAS to column addrs duration 2 cycles
+#define MEM_TIMING_RCA1 REPLICATE_16(0x0020) // RAS to column addrs duration 1 cycle
+#define MEM_TIMING_RP0 REPLICATE_16(0x0000) // RAS precharge duration width 5 cycles
+#define MEM_TIMING_RP1 REPLICATE_16(0x0040) // RAS precharge duration width 4 cycles
+#define MEM_TIMING_RP2 REPLICATE_16(0x0080) // RAS precharge duration width 3 cycles
+#define MEM_TIMING_RP3 REPLICATE_16(0x00c0) // RAS precharge duration width 2 cycles
+#define MEM_TIMING_RAS0 REPLICATE_16(0x0000) // RAS refresh width x cycles
+#define MEM_TIMING_RAS1 REPLICATE_16(0x0100) // RAS refresh width x cycles
+#define MEM_TIMING_RAS2 REPLICATE_16(0x0200) // RAS refresh width x cycles
+#define MEM_TIMING_RAS3 REPLICATE_16(0x0300) // RAS refresh width x cycles
+#define MEM_TIMING_PEN REPLICATE_16(0x0400) // Parity SIMM Enable
+#define MEM_TIMING_MASK REPLICATE_16(0x07ff) // MEM Timing register bit mask
+
+
+//
+// MEM Diag register bit definitions
+//
+#define MEM_DIAG_EVENCHK 0x0000ff00 // Even check bits written to memory
+#define MEM_DIAG_ODDCHK 0xff000000 // Odd check bits written to memory
+#define MEM_DIAG_MASK REPLICATE_16(0xff00) // MEM Diag register bit mask
+
+//
+// INT Status register bit definitions
+//
+#define INT_STATUS_IOA REPLICATE_16(0x0001) // IO int pending for Processor A
+#define INT_STATUS_IOB REPLICATE_16(0x0002) // IO int pending for Processor B
+#define INT_STATUS_MA REPLICATE_16(0x0004) // Mem int pending for Processor A
+#define INT_STATUS_MB REPLICATE_16(0x0008) // Mem int pending for Processor B
+#define INT_STATUS_MNI REPLICATE_16(0x0010) // NMI int (from Mem controller) pending
+#define INT_STATUS_PA REPLICATE_16(0x0020) // PCI int pending for Processor A
+#define INT_STATUS_PB REPLICATE_16(0x0040) // PCI int pending for Processor B
+#define INT_STATUS_PNI REPLICATE_16(0x0080) // NMI int (from PCI controller pending)
+#define INT_STATUS_IPA REPLICATE_16(0x0100) // Interproc int pending for Processor A
+#define INT_STATUS_IPB REPLICATE_16(0x0200) // Interproc int pending for Processor B
+#define INT_STATUS_ITA REPLICATE_16(0x0400) // Interval Timer interrupt pending for Processor A
+#define INT_STATUS_ITB REPLICATE_16(0x0800) // Interval Timer interrupt pending for Processor B
+#define INT_STATUS_AMASK (INT_STATUS_IOA|INT_STATUS_MA|INT_STATUS_PA|INT_STATUS_IPA|INT_STATUS_ITA|INT_STATUS_MNI|INT_STATUS_PNI)
+#define INT_STATUS_BMASK (INT_STATUS_IOB|INT_STATUS_MB|INT_STATUS_PB|INT_STATUS_IPB|INT_STATUS_ITB|INT_STATUS_MNI|INT_STATUS_PNI)
+#define INT_STATUS_MASK REPLICATE_16(0x03ff) // Int Status bit mask
+#define INT_STATUS_MASK_PMP_V2 REPLICATE_16(0x0fff) // Int Status bit mask
+
+//
+// INT Ctrl register bit definitions
+//
+#define INT_CTRL_IOEA REPLICATE_16(0x0001) // I/O int enable for Processor A
+#define INT_CTRL_IOEB REPLICATE_16(0x0002) // I/O int enable for Processor B
+#define INT_CTRL_MIEA REPLICATE_16(0x0004) // Mem sys int enable for Processor A
+#define INT_CTRL_MIEB REPLICATE_16(0x0008) // Mem sys int enable for Processor B
+#define INT_CTRL_MNE REPLICATE_16(0x0010) // Mem sys NMI enable for Processor A&B
+#define INT_CTRL_PIEA REPLICATE_16(0x0020) // PCI sys int enable for Processor A
+#define INT_CTRL_PIEB REPLICATE_16(0x0040) // PCI sys int enable for Processor B
+#define INT_CTRL_PNE REPLICATE_16(0x0080) // PCI sys NMI enable for Processor A&B
+#define INT_CTRL_IPEA REPLICATE_16(0x0100) // Inter Proc int enable for Processor A
+#define INT_CTRL_IPEB REPLICATE_16(0x0200) // Inter Proc int enable for Processor B
+#define INT_CTRL_ITEA REPLICATE_16(0x0400) // Interval Timer interrupt enable for Processor A
+#define INT_CTRL_ITEB REPLICATE_16(0x0800) // Interval Timer interrupt enable for Processor B
+#define INT_CTRL_IED REPLICATE_16(0x2000) // Interrupt escalation disable
+#define INT_CTRL_SEC0 REPLICATE_16(0x0000) // Synchronous delivery of exceptions
+#define INT_CTRL_SEC1 REPLICATE_16(0x4000) // Asynchronous delivery of exceptions
+#define INT_CTRL_SEC2 REPLICATE_16(0x8000) // Asynchronous delivery of exceptions if
+ // error is not on first word (Narrow) or
+ // first doubleword (Wide)
+#define INT_CTRL_MASK REPLICATE_16(0xe3ff) // INT Ctrl register bit mask
+#define INT_CTRL_MASK_PMP_V2 REPLICATE_16(0xefff) // INT Ctrl register bit mask
+
+#define ENABLE_IP_INTERRUPTS (INT_CTRL_IPEA | INT_CTRL_IPEB) // Enable A&B IP interrupts
+
+//
+// INT Cause register bit definitions
+//
+#define INT_CAUSE_IO REPLICATE_16(0x0001) // I/O interrupt delivered
+#define INT_CAUSE_MEM REPLICATE_16(0x0002) // Mem system interrupt delivered
+#define INT_CAUSE_MNMI REPLICATE_16(0x0004) // Mem NMI system interrupt delivered
+#define INT_CAUSE_PCI REPLICATE_16(0x0008) // PCI system interrupt delivered
+#define INT_CAUSE_PNMI REPLICATE_16(0x0010) // PCI NMI system interrupt delivered
+#define INT_CAUSE_IPC REPLICATE_16(0x0020) // InterProcessor interrupt delivered
+#define INT_CAUSE_TIMER REPLICATE_16(0x0040) // Interval Timer interrupt delivered
+#define INT_CAUSE_MASK REPLICATE_16(0x003f) // INT Cause register bit mask
+#define INT_CAUSE_MASK_PMP_V2 REPLICATE_16(0x007f) // INT Cause register bit mask
+
+//
+// IP Int Gen register bit definitions
+//
+#define IP_INT_GEN_IPIA REPLICATE_16(0x0001) // Gen InterProc int to Processor A
+#define IP_INT_GEN_IPIB REPLICATE_16(0x0002) // Gen InterProc int to Processor B
+#define IP_INT_GEN_MASK REPLICATE_16(0x0003) // IP Int Gen register bit mask
+
+
+//
+// IP Int Ack register bit definitions
+//
+#define IP_INT_ACK_IP REPLICATE_16(0x0001) // InterProcessor A Int pending
+#define IP_INT_ACK_MASK REPLICATE_16(0x0001) // IP Int Ack register bit mask
+
+//
+// IO Int Ack register bit definitions
+//
+#define IO_INT_ACK_MASK 0xff // IO Int ack bit mask
+
+//
+// Line buffer burst registers bit definitions
+//
+
+#define LBUF_BURST_MAP_MASK 0xFFFFFFE0 // bits define address field 31:5
+ // where low-order five bits are
+ // always 0 (minimum 32 byte aligned)
+
+#define LBUF_BURST_CTRL_ADDR 0x0000000F // bits 35:32 of physical address for Wide mode systems only
+#define LBUF_BURST_CTRL_SIZE 0x000001F0 // burst window size, ranges from (0) 32 bytes to (0x10) 512 bytes
+#define LBUF_BURST_CTRL_R0E REPLICATE_16(0x0200) // Return 0's Enable
+#define LBUF_BURST_CTRL_EOM REPLICATE_16(0x0400) // Even/Odd Nibble ...
+#define LBUF_BURST_CTRL_CME REPLICATE_16(0x0800) // Copy Mode Enable
+#define LBUF_BURST_CTRL_AWE REPLICATE_16(0x1000) // Address field write enable
+#define LBUF_BURST_CTRL_CWE REPLICATE_16(0x2000) // Control fields write enable
+#define LBUF_BURST_CTRL_MASK 0x3E003FFF // Mask of all writeable/readable bits
+
+//
+// Line buffer address space definitions
+//
+#define LBUF_ADDRESS_BS0 0
+#define LBUF_ADDRESS_BS1 REPLICATE_16(0x0400)
+#define LBUF_ADDRESS_BI0 0
+#define LBUF_ADDRESS_BI1 REPLICATE_16(0x0200)
+#define LBUF_ADDRESS_ALIAS 22
+
+//
+// External Pmp V1 Control register bit definitions
+//
+#define EPC_ECACHE_RESET 0x01
+#define EPC_POWER_0 0x02
+#define EPC_ECC_SIMM_ENABLE 0x04 // Clear for Parity SIMM enable...
+#define EPC_AUI 0x08
+#define EPC_FLASH_POWER 0x10
+#define EPC_LED_0 0x20
+#define EPC_LED_1 0x40
+#define EPC_LED_2 0x80
+#define EPC_REG_MASK 0xFF
+
+//
+// External Pmp V2 Control register bit definitions - bucky register 0
+//
+#define EPC_ECACHE_RESET_PMP_V2 0x01
+//#define EPC_ECACHE_TAGCS 0x02
+#define EPC_SCSI_TERMINATION 0x02 // for board revision 02 and later, now used for scsi termination
+#define EPC_POWER 0x04
+#define EPC_WATCHDOG 0x08
+#define EPC_LED_PMP_V2 0x10
+#define EPC_THERM_CLK 0x20
+#define EPC_WDSEL 0x40
+#define EPC_BREAD 0x80
+
+//
+// External PMP V2 Control additional register bit definitions - bucky register 1
+//
+#define EPC1_THERM_DQ 0x40
+#define EPC1_THERM_RST 0x80
+#define EPC1_DESKTOP 0x08 // 1 == Desktop, 0 == Tower
+#define EPC1_BOARD_ID 0x07 // Board revision
+#define BOARD_REV_00 0x07 // Original MB
+#define BOARD_REV_01 0x06 // Second revision (see falcon.s)
+#define BOARD_REV_02 0x05 // Third Rev, to change scsi termination
+#define IS_DESKTOP ( (*(PUCHAR)EXTERNAL_PMP_CONTROL_1) & EPC1_DESKTOP )
+
+
+// Firmware definitions
+//
+#define SECONDARY_CACHE_INVALID 0x0
+#define TAGLO_SSTATE 0xA
+
+//
+// Firmware Memory definitions
+#define NUMBER_OF_MEMORY_BANKS 8
+
+#endif // _FALCONREG_
diff --git a/private/ntos/nthals/halntp/mips/fxbusdat.c b/private/ntos/nthals/halntp/mips/fxbusdat.c
new file mode 100644
index 000000000..9c6a2f7c8
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxbusdat.c
@@ -0,0 +1,202 @@
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// Prototype for system bus handlers
+//
+
+#ifdef POWER_MANAGEMENT
+NTSTATUS
+HalpHibernateHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+HalpResumeHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal bus #0
+ //
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+#ifdef POWER_MANAGEMENT
+ //
+ // Hibernate and resume the hal by getting notifications
+ // for when this bus is hibernated or resumed. Since it's
+ // the first bus to be added, it will be the last to hibernate
+ // and the first to resume
+ //
+
+ Bus->HibernateBus = HalpHibernateHal;
+ Bus->ResumeBus = HalpResumeHal;
+#endif
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = (ULONGLONG)0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+
+ //
+ // Build other bus(es)
+ //
+
+ HalpInitializePCIBus ();
+
+}
+
+
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = (ULONGLONG)PCI_MAX_MEMORY_ADDRESS;
+
+ if( InterfaceType == PCIBus ) {
+ Bus->BusAddresses->IO.Limit = (ULONGLONG)PCI_MAX_IO_ADDRESS;
+ } else {
+ Bus->BusAddresses->IO.Limit = 0xFFFF;
+ }
+
+ Bus->BusAddresses->IO.SystemAddressSpace = 1;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+ return Bus;
+}
+
+
diff --git a/private/ntos/nthals/halntp/mips/fxdat.c b/private/ntos/nthals/halntp/mips/fxdat.c
new file mode 100644
index 000000000..cc7978ba4
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxdat.c
@@ -0,0 +1,73 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ fxdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "halp.h"
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x000, 0x20, // DMA
+ 0x020, 0x2, // Interrupt Controller 1
+ 0x022, 0x2, // Configuration Address/Data
+ 0x040, 0x4, // Timer1
+ 0x048, 0x4, // Timer2
+ 0x061, 0x1, // NMI
+ 0x070, 0x2, // NMI
+ 0x080, 0x10, // DMA
+ 0x092, 0x1, // System Control Port
+ 0x0A0, 0x2, // Interrupt Controller 2
+ 0x0C0, 0x20, // DMA
+ 0x0D0, 0x10, // DMA
+ 0x400, 0x10, // DMA
+ 0x410, 0x30, // Scatter/Gather
+ 0x461, 0x2, // Extended NMI
+ 0x464, 0x2, // Last Eisa Bus Master granted
+ 0x480, 0x10, // DMA
+ 0x4C2, 0xE, // DMA
+ 0x4D4, 0x2C, // DMA
+ 0x4D0, 0x2, // Edge/Level Control registers
+ 0xE000, 0x10, // Bucky registers
+ 0, 0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
diff --git a/private/ntos/nthals/halntp/mips/fxdisp.c b/private/ntos/nthals/halntp/mips/fxdisp.c
new file mode 100644
index 000000000..3c77856d7
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxdisp.c
@@ -0,0 +1,1127 @@
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+Copyright (c) 1993, NeTpower, Inc. All rights reserved.
+
+Module Name:
+
+ fxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for the NeTpower FALCON architecture. It supports standard VGA.
+
+Author:
+
+ Mike Dove (mdove), 8-Oct-93
+ Charlie Chase (cdc) 14-Jun-94
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "vga.h"
+#include "string.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayVGASetup (
+ VOID
+ );
+
+//
+// The video cards that we support
+//
+
+#define PCI_VGA 0
+#define PCI_3D 1
+#define ISA_VGA 2
+
+#define IS_DISPLAY_VGA ( HalpDisplayType == PCI_VGA || HalpDisplayType == ISA_VGA )
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+ULONG VideoMemoryVirtualBase[] = {
+ 0xBEEFBABE, // PCI VGA
+ VIDEO_MEMORY_VIRTUAL_BASE, // reserved for 3-D graphics card
+ EISA_MEMORY_VIRTUAL_BASE // ISA VGA
+ };
+
+ULONG VideoMemoryPhysicalBase[] = {
+ 0xBEEFBABE, // PCI VGA
+ VIDEO_MEMORY_PHYSICAL_BASE, // reserved for 3-D graphics card
+ EISA_MEMORY_PHYSICAL_BASE, // ISA VGA
+ };
+
+ULONG ControlMemoryVirtualBase[] = {
+ 0xBABECAFE, // PCI VGA
+ VIDEO_MEMORY_VIRTUAL_BASE, // reserved for 3-D graphics card
+ EISA_CONTROL_VIRTUAL_BASE // ISA VGA
+ };
+
+ULONG ControlMemoryPhysicalBase[] = {
+ 0xBABECAFE, // PCI VGA
+ VIDEO_MEMORY_PHYSICAL_BASE, // reserved for 3-D graphics card
+ PCI_IO_PHYSICAL_BASE // ISA VGA
+ };
+
+ULONG VideoMemoryBase[] = {
+ 0xBEEFBABE + 0xB8000, // PCI VGA
+ VIDEO_MEMORY_VIRTUAL_BASE, // reserved for 3-D graphics card
+ EISA_MEMORY_VIRTUAL_BASE + 0xB8000, // ISA VGA
+ };
+
+//
+// The ISA S3 card simply needs a single PDE page.
+//
+
+ULONG PDEPages[] = {
+ 1, // PCI VGA
+ 5, // reserved for 3-D graphics card
+ 1, // ISA VGA
+ };
+
+#define MAX_PDE_PAGES 5
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte[MAX_PDE_PAGES];
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayResetRegisterBase = 0;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpDisplayType = 0;
+
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+
+//
+// Define macros for reading/writing VGA control and memory space.
+//
+
+#define VGA_CREAD ((volatile PVGA_READ_PORT) (ControlMemoryVirtualBase[HalpDisplayType]))
+
+#define VGA_CWRITE ((volatile PVGA_WRITE_PORT) (ControlMemoryVirtualBase[HalpDisplayType]))
+
+#define VGA_MEMORY ((volatile PUCHAR)(VideoMemoryVirtualBase[HalpDisplayType] + 0xB8000))
+
+#define VIDEO_MEMORY ((volatile PUCHAR)(VideoMemoryBase[HalpDisplayType]))
+
+#define FONT_MEMORY ((volatile PUCHAR)(VideoMemoryVirtualBase[HalpDisplayType] + 0xA0000))
+
+
+
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+ ULONG PDECount;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "S3" )) {
+
+ HalpDisplayType = ISA_VGA;
+ HalpDisplayControllerSetup = HalpDisplayVGASetup;
+ HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "CIRRUS" )) {
+
+ HalpDisplayType = ISA_VGA;
+ HalpDisplayControllerSetup = HalpDisplayVGASetup;
+ HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
+
+ } else {
+
+ //
+ // Unknown device
+ //
+
+ HalpDisplayType = ISA_VGA;
+ HalpDisplayControllerSetup = HalpDisplayVGASetup;
+ HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
+
+// return FALSE;
+
+ }
+
+ Child = ConfigurationEntry->Child;
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+#if 0
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+#else
+
+ //
+ // Assume VGA...
+ //
+
+ HalpDisplayText = 400 / HalpCharacterHeight;
+ HalpScrollLine = 160; // 80 characters + 80
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayWidth = 80;
+
+#endif
+
+
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+ Pte.C = UNCACHED_POLICY;
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte[PDECount] = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ }
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VideoMemoryVirtualBase[HalpDisplayType]
+ >> (PDI_SHIFT - PTI_SHIFT)));
+
+ Pte.PFN = ((VideoMemoryPhysicalBase[HalpDisplayType] & 0xF0000000) >> (PAGE_SHIFT - 4)) | (VideoMemoryPhysicalBase[HalpDisplayType] >> PAGE_SHIFT);
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+ Pte.C = UNCACHED_POLICY;
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ( PDEPages[HalpDisplayType] * (PAGE_SIZE / sizeof(ENTRYLO)) / 2); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ Pte.PFN = ((ControlMemoryPhysicalBase[HalpDisplayType] & 0xF0000000) >> (PAGE_SHIFT - 4)) | (ControlMemoryPhysicalBase[HalpDisplayType] >> PAGE_SHIFT);
+
+ for ( Index = 0; Index < 0x10; Index+=1 ) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpEisaMemoryBase = (PVOID)VideoMemoryVirtualBase[HalpDisplayType];
+ HalpEisaControlBase = (PVOID)ControlMemoryVirtualBase[HalpDisplayType];
+ HalpInitializeX86DisplayAdapter();
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA display controller chip on the ISA bus.
+
+ Initialized configuration is to be:
+ 640 x 480
+ 80 x 25 characters (with 8x16 font), or 80 x 50 (with 8x8 font)
+ 16 colors
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpDisplayVGASetup (
+ VOID
+ )
+
+{
+
+//
+// Initialize the ISA VGA card. This routine is generic VGA, and will attempt
+// NOT to take advantage of any specific VGA implementation. In order to have
+// cleaner code, the eventual goal will be to put the VGA in graphics mode, and
+// address it the same way as a frame buffer. In addition the font is passed
+// to us by the OS loader, thus that is taken care of.
+//
+// Note, that the register sets are loosely configured in order. The values
+// for these registers are taken from page 318 of the Programmers Guide to
+// the EGA and VGA cards.
+//
+
+ ULONG RegisterIndex, RGBIndex, IndexI, IndexJ;
+ ULONG DoS3 = 1;
+ UCHAR Byte;
+ PUCHAR FontData;
+ UCHAR Character;
+ volatile PUCHAR MemoryByte;
+
+ // S3 - Put video subsystem into setup mode, and enable it...
+ if ( DoS3 ) {
+ VGA_CWRITE->VideoSubsystemEnable = ENTER_SETUP_MODE;
+ VGA_CWRITE->SetupOptionSelect = VIDEO_SUBSYSTEM_ALIVE;
+ VGA_CWRITE->VideoSubsystemEnable = ENABLE_VIDEO_SUBSYSTEM;
+ // The rest of the code in this if statement is to properly
+ // re-initalize the S3 chip specifically when coming from
+ // graphics mode (bug check for example).
+
+ // This DISABLES the Enhanced Functions...
+ VGA_CWRITE->AdvancedFunctionControl = 0x2;
+
+ // Unlock the register sets that need modification...
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_1;
+ VGA_CWRITE->CRTCData = 0x48;
+
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_2;
+ VGA_CWRITE->CRTCData = 0xa0;
+
+ // Re-initialize the S3 to a sane mode...
+ VGA_CWRITE->CRTCAddress = S3_MEMORY_CONFIGURATION;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_BACKWARD_COMPATIBILITY_3;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_CRT_REGISTER_LOCK;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_MISCELLANEOUS_1;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_MODE_CONTROL;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_HARDWARE_GRAPHICS_CURSOR;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_EXTENDED_MEMORY_CONTROL_1;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_EXTENDED_MEMORY_CONTROL_2;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_LINEAR_ADDRESS_WINDOW_LOW;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ // DISABLES access to Enhanced registers...
+ VGA_CWRITE->CRTCAddress = S3_SYSTEM_CONFIGURATION;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ // Lock the register sets that were modified...
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_2;
+ VGA_CWRITE->CRTCData = 0x0;
+
+ VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_1;
+ VGA_CWRITE->CRTCData = 0x0;
+ }
+
+ // Do initial synchronus reset...
+ VGA_CWRITE->SequencerAddress = SEQ_RESET;
+ VGA_CWRITE->SequencerData = SYNCHRONUS_RESET;
+
+ // Set up initial configuration using the Miscellaneous Output Register
+ VGA_CWRITE->MiscOutput = INITIAL_CONFIG;
+
+ // Do synchronus reset...
+ VGA_CWRITE->SequencerAddress = SEQ_RESET;
+ VGA_CWRITE->SequencerData = SYNCHRONUS_RESET;
+
+ // Set up Sequencer registers. Run through the array of data stuffing
+ // the values into the VGA. After the Sequencer values have been stuffed,
+ // we will return the VGA to normal operation.
+ for ( RegisterIndex = SEQ_CLOCKING_MODE; RegisterIndex <= SEQ_MEMORY_MODE;
+ RegisterIndex++ ) {
+
+ VGA_CWRITE->SequencerAddress = (UCHAR)RegisterIndex;
+ VGA_CWRITE->SequencerData = SequencerSetup[RegisterIndex];
+
+ }
+
+ // Next setup the CRT Controller registers. The registers 0-7 might
+ // be write-protected if bit 7 of the Vertical Retrace End register is
+ // set. First we will clear that bit, then set all the registers.
+
+ VGA_CWRITE->CRTCAddress = CRT_VERTICAL_RETRACE_END;
+ Byte = VGA_CREAD->CRTCData;
+ Byte &= 0x7f;
+ VGA_CWRITE->CRTCData = Byte;
+
+ // Adjust Maximum Scan Lines based on the size of the font passed in
+ // by the OSLOADER...
+
+ CRTCSetup[CRT_MAXIMUM_SCAN_LINE] =
+ ( CRTCSetup[CRT_MAXIMUM_SCAN_LINE] & 0xe0 ) |
+ ( (UCHAR)(( HalpCharacterHeight - 1 ) & 0x1f) );
+
+ for ( RegisterIndex = CRT_HORIZONTAL_TOTAL;
+ RegisterIndex <= CRT_LINE_COMPARE; RegisterIndex++ ) {
+
+ VGA_CWRITE->CRTCAddress = (UCHAR)RegisterIndex;
+ VGA_CWRITE->CRTCData = CRTCSetup[RegisterIndex];
+
+ }
+
+ // Next setup the Graphics Controller registers. Straight from the
+ // table...
+
+ for ( RegisterIndex = GFX_SET_RESET; RegisterIndex <= GFX_BIT_MASK;
+ RegisterIndex++ ) {
+
+ VGA_CWRITE->GraphicsAddress = (UCHAR)RegisterIndex;
+ VGA_CWRITE->GraphicsData = GraphicsSetup[RegisterIndex];
+
+ }
+
+ // Next we need to setup the Attribute Controller registers. Instead
+ // of a separate Address and Data register, they are combined into a
+ // single register with its output directed by a two-state flip-flop.
+ // When the flip-flop is clear, the first write to the
+ // AttributeAddressAndData register is the index, and the second write
+ // is the data. In order to be sure the flip-flop is in a known state,
+ // we will clear it first by reading the InputStatus1 register...
+
+ for ( RegisterIndex = ATT_PALETTE_00; RegisterIndex <= ATT_COLOR_SELECT;
+ RegisterIndex++ ) {
+
+ Byte = VGA_CREAD->InputStatus1; // Reset flip-flop...
+ VGA_CWRITE->AttributeAddressAndData = (UCHAR)RegisterIndex;
+ KeStallExecutionProcessor(10);
+ VGA_CWRITE->AttributeAddressAndData = AttributeSetup[RegisterIndex];
+ KeStallExecutionProcessor(10);
+ VGA_CWRITE->AttributeAddressAndData = 0x20; // Return to normal mode
+
+ }
+
+ // Sequencer register setup, so return VGA to operation
+ VGA_CWRITE->SequencerAddress = SEQ_RESET;
+ VGA_CWRITE->SequencerData = NORMAL_OPERATION;
+
+ // Now that the Attribute and Color Palette registers are set up,
+ // now it is time to fill in the value into the Color registers.
+ // First initialize PEL Mask to FF as the BIOS would.
+
+ VGA_CWRITE->PELMask = 0xff;
+ VGA_CWRITE->PELAddressWriteMode = 0; // Set Index to 0...
+
+ for ( RegisterIndex = 0; RegisterIndex < 16; RegisterIndex++ ) {
+ for ( RGBIndex = 0; RGBIndex < 3; RGBIndex++ ) {
+
+ VGA_CWRITE->PELData = ColorValues[RegisterIndex][RGBIndex];
+
+ }
+ }
+
+ // Now we are ready to load the fonts into bit plane 2...
+
+ VGA_CWRITE->SequencerAddress = SEQ_MAP_MASK;
+ VGA_CWRITE->SequencerData = ENABLE_PLANE_2;
+
+ VGA_CWRITE->SequencerAddress = SEQ_MEMORY_MODE;
+ VGA_CWRITE->SequencerData = SEQUENTIAL_ADDRESSING | EXTENDED_MEMORY;
+
+ VGA_CWRITE->GraphicsAddress = GFX_MODE;
+ VGA_CWRITE->GraphicsData = WRITE_MODE_0;
+
+ VGA_CWRITE->GraphicsAddress = GFX_MISCELLANEOUS;
+ VGA_CWRITE->GraphicsData = MEMORY_MODE_1 | ALPHA_MODE;
+
+ MemoryByte = FONT_MEMORY;
+
+ // Use font provided by OSLOADER...
+ for ( IndexI = 0; IndexI < 256; IndexI++ ) {
+ if (( IndexI < HalpFontHeader->FirstCharacter) ||
+ ( IndexI > HalpFontHeader->LastCharacter )) {
+ Character = HalpFontHeader->DefaultCharacter;
+ } else {
+ Character = (UCHAR)IndexI;
+ }
+ Character -= HalpFontHeader->FirstCharacter;
+ FontData = ((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ // Assumption, HalpCharacterHeight <= 16...
+ for ( IndexJ = 0; IndexJ < HalpCharacterHeight; IndexJ++ ) {
+ *MemoryByte = *FontData++;
+ MemoryByte++;
+ }
+ for ( IndexJ = HalpCharacterHeight; IndexJ < 32; IndexJ++ ) {
+ *MemoryByte = 0;
+ MemoryByte++;
+ }
+ }
+
+
+ // Now reload the default values into the above 4 registers...
+
+ VGA_CWRITE->SequencerAddress = SEQ_MAP_MASK;
+ VGA_CWRITE->SequencerData = SequencerSetup[SEQ_MAP_MASK];
+
+ VGA_CWRITE->SequencerAddress = SEQ_MEMORY_MODE;
+ VGA_CWRITE->SequencerData = SequencerSetup[SEQ_MEMORY_MODE];
+
+ VGA_CWRITE->GraphicsAddress = GFX_MODE;
+ VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_MODE];
+
+ VGA_CWRITE->GraphicsAddress = GFX_MISCELLANEOUS;
+ VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_MISCELLANEOUS];
+
+// /**/VGA_CWRITE->GraphicsAddress = GFX_READ_MAP_SELECT;
+// /**/VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_READ_MAP_SELECT];
+
+ // Now set the screen to blue... For the attribute byte, the upper 4 bits
+ // are the background color, while the low 4 bits are the foreground
+ // color...
+
+ MemoryByte = VIDEO_MEMORY;
+ for ( IndexI = 0; IndexI < (80*(HalpDisplayText+2));
+ IndexI++ ) {
+ *MemoryByte++ = SPACE;
+ *MemoryByte++ = ( ( COLOR_BLUE << 4 ) | COLOR_INTENSE_WHITE );
+ }
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpClearScreenToBlue(
+ ULONG Lines
+ )
+{
+ PUCHAR MemoryByte;
+ ULONG IndexI;
+
+ MemoryByte = VIDEO_MEMORY;
+ for ( IndexI = 0; IndexI < (80*(HalpDisplayText+2));
+ IndexI++ ) {
+ *MemoryByte++ = SPACE;
+ if ( IndexI >= ( Lines * 80 ) ) {
+ *MemoryByte++ = ( ( COLOR_RED << 4 ) | COLOR_INTENSE_WHITE );
+ } else {
+ *MemoryByte++ = ( ( COLOR_RED << 4 ) | COLOR_INTENSE_CYAN );
+ }
+ }
+
+ HalpColumn = 0;
+ HalpRow = 0;
+
+}
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[MAX_PDE_PAGES];
+ ULONG PDECount;
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+ SavedPte[PDECount] = *((PENTRYLO)(PDE_BASE |
+ (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc)));
+ }
+ KeFlushCurrentTb();
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+ *((PENTRYLO)(PDE_BASE |
+ (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte[PDECount];
+ }
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+
+ HalpResetX86DisplayAdapter();
+
+ HalpClearScreenToBlue( 0 );
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
+ *((PENTRYLO)(PDE_BASE | (((VideoMemoryVirtualBase[HalpDisplayType] +
+ (PDECount*0x400000))
+ >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte[PDECount];
+ }
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine is a very slow memory move routine for the PG1280P.
+ This routine will hardly be used, but will be replaced with a hardware
+ depenedent scroll routine soon.
+
+--*/
+
+VOID
+SlowMoveMemory (
+ OUT PUCHAR Destination,
+ IN PUCHAR Source,
+ IN ULONG Count
+ )
+
+{
+ ULONG Index;
+
+ for ( Index = 0; Index < Count/4; Index++ ) {
+ *(PULONG)Destination = *(PULONG)Source;
+ Destination+=4;
+ Source+=4;
+ }
+}
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+{
+
+ PUCHAR Destination;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ // Scroll the screen one line
+
+#ifdef SCROLL
+ SlowMoveMemory((PVOID)VIDEO_MEMORY,
+ (PVOID)(VIDEO_MEMORY + HalpScrollLine),
+ HalpScrollLength);
+#endif
+
+ Destination = (PUCHAR)VIDEO_MEMORY + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 2) {
+ *Destination++ = 0x20;
+ Destination++; // Skip attribute byte...
+ }
+
+
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+// Character -= HalpFontHeader->FirstCharacter;
+// HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ HalpOutputCharacter(&Character);
+ }
+
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ )
+
+{
+
+ PUCHAR Destination;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(VIDEO_MEMORY + (HalpRow * HalpScrollLine) + (HalpColumn*2));
+ *Destination = *Glyph;
+
+ HalpColumn += 1;
+ return;
+}
+
+
+
+
diff --git a/private/ntos/nthals/halntp/mips/fxerrlog.c b/private/ntos/nthals/halntp/mips/fxerrlog.c
new file mode 100644
index 000000000..e97417264
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxerrlog.c
@@ -0,0 +1,1305 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ fxerrlog.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+--*/
+
+#include "halp.h"
+
+WCHAR rgzNeTpowerKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries";
+
+//
+// Registry paths and keys for
+// memory error logging
+//
+
+#define MEMORY_ERROR_LOG_KEY_MEMORY 0
+#define MEMORY_ERROR_LOG_KEY_CE 1
+#define MEMORY_ERROR_LOG_KEY_UE 2
+#define MEMORY_ERROR_LOG_KEY_MCE 3
+#define MEMORY_ERROR_LOG_KEY_MUE 4
+#define MEMORY_ERROR_LOG_KEY_MAX 5
+
+PWCHAR rgzMemoryErrorLogKeys[] = {
+
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Memory",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Memory\\CorrectableError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Memory\\UncorrectableError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Memory\\MultipleCorrError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Memory\\MultipleCorrError"
+
+ };
+
+#define MEMORY_ERROR_LOG_VALUEKEY_INDEX0 0
+#define MEMORY_ERROR_LOG_VALUEKEY_INDEX1 1
+#define MEMORY_ERROR_LOG_VALUEKEY_INDEX2 2
+#define MEMORY_ERROR_LOG_VALUEKEY_INDEX3 3
+#define MEMORY_ERROR_LOG_VALUEKEY_INDEX4 4
+#define MEMORY_ERROR_LOG_VALUEKEY_MAX 5
+
+PWCHAR rgzMemoryErrorLogValueKeys[] = {
+
+ L"TotalAccumulatedErrors",
+ L"TotalErrorsSinceLastReboot",
+ L"LastMemoryErrorAddressReg",
+ L"LastMemoryStatusReg",
+ L"LastMemoryDiagReg"
+
+ };
+
+ULONG HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_MAX];
+
+//
+// Registry paths and keys for
+// pci error logging
+//
+
+#define PCI_ERROR_LOG_KEY_PCI 0
+#define PCI_ERROR_LOG_KEY_RMA 1
+#define PCI_ERROR_LOG_KEY_MPE 2
+#define PCI_ERROR_LOG_KEY_RER 3
+#define PCI_ERROR_LOG_KEY_RTA 4
+#define PCI_ERROR_LOG_KEY_IAE 5
+#define PCI_ERROR_LOG_KEY_RSE 6
+#define PCI_ERROR_LOG_KEY_ME 7
+
+#define PCI_ERROR_LOG_KEY_MAX 8
+
+PWCHAR rgzPciErrorLogKeys[] = {
+
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\MasterAbortError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\ParityError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\ExcessiveRetryError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\TargetAbortError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\AccessError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\SystemError",
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Pci\\MultipleError"
+
+ };
+
+#define PCI_ERROR_LOG_VALUEKEY_INDEX0 0
+#define PCI_ERROR_LOG_VALUEKEY_INDEX1 1
+#define PCI_ERROR_LOG_VALUEKEY_INDEX2 2
+#define PCI_ERROR_LOG_VALUEKEY_INDEX3 3
+#define PCI_ERROR_LOG_VALUEKEY_INDEX4 4
+#define PCI_ERROR_LOG_VALUEKEY_MAX 5
+
+PWCHAR rgzPciErrorLogValueKeys[] = {
+
+ L"TotalAccumulatedErrors",
+ L"TotalErrorsSinceLastReboot",
+ L"LastPciErrorAddressReg",
+ L"LastPciStatusReg",
+ L"LastPciRetryReg"
+
+ };
+
+ULONG HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+ULONG HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_MAX];
+
+//
+// Registry paths and keys for
+// processor error logging
+//
+
+#define PROC_ERROR_LOG_KEY_MAX 1
+
+PWCHAR rgzProcErrorLogKeys[] = {
+
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\FASTseries\\Processor"
+
+ };
+
+#define PROC_ERROR_LOG_VALUEKEY_MAX 2
+
+PWCHAR rgzProcErrorLogValueKeys[] = {
+
+ L"TotalAccumulatedErrors",
+ L"TotalErrorsSinceLastReboot"
+
+ };
+
+ULONG HalpProcErrorLogVariable[PROC_ERROR_LOG_VALUEKEY_MAX];
+
+
+VOID
+HalpCreateLogKeys(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hErrKey;
+ NTSTATUS status;
+ ULONG disposition, i, j;
+
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+
+ //
+ // Now we can add subkeys to the registry at
+ //
+ // \\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\System\\*
+ //
+ // which will allow our bus and interrupt handlers
+ // to log errors as they occur. All of these keys
+ // have the REG_OPTION_NON_VOLATILE attribute so
+ // that the key and its values are preserved across
+ // reboots. If the keys already exist, then they
+ // are just opened and then closed without affecting
+ // their values.
+ //
+ // The subkeys created here are
+ //
+ // - FASTseries
+ // - Memory
+ // - Pci
+ // - Processor
+ //
+ // Refer to the individual bus and interrupt handlers
+ // for details about additional subkeys and values
+ // logged.
+ //
+
+ //
+ // FASTseries key
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzNeTpowerKey);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+
+ status = ZwCreateKey (&hErrKey,
+ KEY_WRITE,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition);
+
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ ZwClose(hErrKey);
+
+ //
+ // MEMORY:
+ //
+ // Create (or open) the registry
+ // keys used for error logging and
+ // get the values (if any) and save
+ // them in the appropriate variable
+ // that will be referenced by the
+ // bus and interrupt handlers.
+ //
+
+ for (i = 0; i < MEMORY_ERROR_LOG_KEY_MAX; i++) {
+
+ RtlInitUnicodeString(&unicodeString, rgzMemoryErrorLogKeys[i]);
+ InitializeObjectAttributes (&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = ZwCreateKey (&hErrKey,
+ KEY_WRITE,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition);
+
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ if (i) {
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (j = 0; j < MEMORY_ERROR_LOG_VALUEKEY_MAX; j++) {
+
+ RtlInitUnicodeString(&unicodeString, rgzMemoryErrorLogValueKeys[j]);
+ status = ZwQueryValueKey(hErrKey,
+ &unicodeString,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof(buffer),
+ &disposition);
+
+ //
+ // If we are not successful, then
+ // the value key must not exist so
+ // let's create and initialize it
+ // and then go to the next valuekey
+ //
+ // If the value key is the errors
+ // since last reboot, we should clear
+ // the registry value and start from
+ // 0.
+ //
+
+ if (!NT_SUCCESS(status) || (j == MEMORY_ERROR_LOG_VALUEKEY_INDEX1) ) {
+
+ switch (i) {
+
+ case MEMORY_ERROR_LOG_KEY_CE:
+
+ HalpMemoryCeLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpMemoryCeLogVariable[j],
+ sizeof(HalpMemoryCeLogVariable[j]));
+ break;
+
+ case MEMORY_ERROR_LOG_KEY_UE:
+
+ HalpMemoryUeLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpMemoryUeLogVariable[j],
+ sizeof(HalpMemoryUeLogVariable[j]));
+ break;
+
+ case MEMORY_ERROR_LOG_KEY_MCE:
+
+ HalpMemoryMceLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpMemoryMceLogVariable[j],
+ sizeof(HalpMemoryMceLogVariable[j]));
+ break;
+
+ case MEMORY_ERROR_LOG_KEY_MUE:
+
+ HalpMemoryMueLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpMemoryMueLogVariable[j],
+ sizeof(HalpMemoryMueLogVariable[j]));
+ break;
+
+ }
+
+ continue ;
+ }
+
+ //
+ // Otherwise, let's initialize the
+ // appropriate variable that the bus
+ // and interrupt handlers will reference
+ // and update
+ //
+
+ switch (i) {
+
+ case MEMORY_ERROR_LOG_KEY_CE:
+
+ HalpMemoryCeLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case MEMORY_ERROR_LOG_KEY_UE:
+
+ HalpMemoryUeLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case MEMORY_ERROR_LOG_KEY_MCE:
+
+ HalpMemoryMceLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case MEMORY_ERROR_LOG_KEY_MUE:
+
+ HalpMemoryMueLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ }
+
+ }
+
+ }
+
+ ZwClose(hErrKey);
+
+ }
+
+ //
+ // PCI:
+ //
+ // Create (or open) the registry
+ // keys used for error logging and
+ // get the values (if any) and save
+ // them in the appropriate variable
+ // that will be referenced by the
+ // bus and interrupt handlers.
+ //
+
+ for (i = 0; i < PCI_ERROR_LOG_KEY_MAX; i++) {
+
+ RtlInitUnicodeString(&unicodeString, rgzPciErrorLogKeys[i]);
+ InitializeObjectAttributes (&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = ZwCreateKey (&hErrKey,
+ KEY_WRITE,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition);
+
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ if (i) {
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (j = 0; j < PCI_ERROR_LOG_VALUEKEY_MAX; j++) {
+
+ RtlInitUnicodeString(&unicodeString, rgzPciErrorLogValueKeys[j]);
+ status = ZwQueryValueKey(hErrKey,
+ &unicodeString,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof(buffer),
+ &disposition);
+
+ //
+ // If we are not successful, then
+ // the value key must not exist so
+ // let's create and initialize it
+ // and then go to the next valuekey
+ //
+
+ if (!NT_SUCCESS(status) || (j == PCI_ERROR_LOG_VALUEKEY_INDEX1) ) {
+
+ switch(i) {
+
+ case PCI_ERROR_LOG_KEY_RMA:
+
+ HalpPciRmaLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciRmaLogVariable[j],
+ sizeof(HalpPciRmaLogVariable[j]));
+
+ break;
+
+ case PCI_ERROR_LOG_KEY_MPE:
+
+ HalpPciMpeLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciMpeLogVariable[j],
+ sizeof(HalpPciMpeLogVariable[j]));
+
+ break;
+
+ case PCI_ERROR_LOG_KEY_RER:
+
+ HalpPciRerLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciRerLogVariable[j],
+ sizeof(HalpPciRerLogVariable[j]));
+
+ break;
+
+ case PCI_ERROR_LOG_KEY_RTA:
+
+ HalpPciRtaLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciRtaLogVariable[j],
+ sizeof(HalpPciRtaLogVariable[j]));
+
+ break;
+
+ case PCI_ERROR_LOG_KEY_IAE:
+
+ HalpPciIaeLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciIaeLogVariable[j],
+ sizeof(HalpPciIaeLogVariable[j]));
+
+ break;
+
+ case PCI_ERROR_LOG_KEY_RSE:
+
+ HalpPciRseLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciRseLogVariable[j],
+ sizeof(HalpPciRseLogVariable[j]));
+
+ break;
+
+ case PCI_ERROR_LOG_KEY_ME:
+
+ HalpPciMeLogVariable[j] = 0;
+
+ ZwSetValueKey(hErrKey,
+ &unicodeString,
+ 0,
+ REG_DWORD,
+ &HalpPciMeLogVariable[j],
+ sizeof(HalpPciMeLogVariable[j]));
+
+ break;
+
+ }
+
+ continue ;
+ }
+
+ //
+ // Otherwise, let's initialize the
+ // appropriate variable that the bus
+ // and interrupt handlers will reference
+ // and update
+ //
+
+ switch (i) {
+
+ case PCI_ERROR_LOG_KEY_RMA:
+
+ HalpPciRmaLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case PCI_ERROR_LOG_KEY_MPE:
+
+ HalpPciMpeLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case PCI_ERROR_LOG_KEY_RER:
+
+ HalpPciRerLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case PCI_ERROR_LOG_KEY_RTA:
+
+ HalpPciRtaLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case PCI_ERROR_LOG_KEY_IAE:
+
+ HalpPciIaeLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case PCI_ERROR_LOG_KEY_RSE:
+
+ HalpPciRseLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ case PCI_ERROR_LOG_KEY_ME:
+
+ HalpPciMeLogVariable[j] = *((PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset));
+ break;
+
+ }
+
+ }
+
+ }
+
+ ZwClose(hErrKey);
+
+ }
+
+ //
+ // Processor keys
+ //
+
+ for (i = 0; i < PROC_ERROR_LOG_KEY_MAX; i++) {
+
+ RtlInitUnicodeString(&unicodeString, rgzProcErrorLogKeys[i]);
+ InitializeObjectAttributes (&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = ZwCreateKey (&hErrKey,
+ KEY_WRITE,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition);
+
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ ZwClose(hErrKey);
+
+ }
+
+}
+
+VOID
+HalpLogErrorInfo(
+ IN PCWSTR RegistryKey,
+ IN PCWSTR ValueName,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG Size
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc;
+ NTSTATUS status;
+
+ RtlInitUnicodeString(&unicodeString, RegistryKey);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = ZwOpenKey (&hMFunc,
+ KEY_WRITE,
+ &objectAttributes);
+
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ RtlInitUnicodeString(&unicodeString, ValueName);
+ ZwSetValueKey(hMFunc,
+ &unicodeString,
+ 0,
+ Type,
+ Data,
+ Size);
+
+ ZwClose(hMFunc);
+
+}
+
+BOOLEAN
+HalpDataBusErrorHandler (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the FASTseries bus error
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BadStatus, i;
+
+
+ //
+ // MEMORY:
+ // 1. Uncorrectable memory error
+ // 2. Multiple UE
+ // 3. Mutiple CE
+ //
+
+ BadStatus = READ_REGISTER_ULONG(HalpPmpMemStatus);
+
+ if ( BadStatus & MEM_STATUS_MUE ) {
+
+ //
+ // Read the address, status, and diag registers
+ // and update the appropriate variables
+ //
+
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_MUE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryMueLogVariable[i],
+ sizeof(HalpMemoryMueLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & (MEM_STATUS_EUE | MEM_STATUS_OUE) ) {
+
+ //
+ // Read the address, status, and diag registers
+ // and update the appropriate variables
+ //
+
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_UE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryUeLogVariable[i],
+ sizeof(HalpMemoryUeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & MEM_STATUS_MCE ) {
+
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_MCE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryMceLogVariable[i],
+ sizeof(HalpMemoryMceLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & (MEM_STATUS_ECE | MEM_STATUS_OCE) ) {
+
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_CE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryCeLogVariable[i],
+ sizeof(HalpMemoryCeLogVariable[i]));
+
+ }
+
+ }
+
+ //
+ // PCI:
+ // 1. Parity (SERR#)
+ // 2. Master Abort
+ // 3. Target Abort
+ // 4. Access Error
+ // 5. System Error
+ // 6. Retry Error
+ //
+
+ BadStatus = READ_REGISTER_ULONG(HalpPmpPciStatus);
+
+ if ( BadStatus & PCI_STATUS_ME) {
+
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_ME],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciMeLogVariable[i],
+ sizeof(HalpPciMeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RMA) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RMA],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRmaLogVariable[i],
+ sizeof(HalpPciRmaLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RSE) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RSE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRseLogVariable[i],
+ sizeof(HalpPciRseLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RER) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RER],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRerLogVariable[i],
+ sizeof(HalpPciRerLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_IAE) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_IAE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciIaeLogVariable[i],
+ sizeof(HalpPciIaeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_MPE) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_MPE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciMpeLogVariable[i],
+ sizeof(HalpPciMpeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RTA) {
+
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RTA],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRtaLogVariable[i],
+ sizeof(HalpPciRtaLogVariable[i]));
+
+ }
+
+ }
+
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ PhysicalAddress.HighPart,
+ PhysicalAddress.LowPart,
+ 0);
+
+ return FALSE;
+}
+
+/*++
+
+Routine Description:
+
+ This function handles PCI interrupts on a FASTseries.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalpPciInterrupt(
+ VOID
+ )
+
+{
+ ULONG BadStatus, i;
+
+ //
+ // PCI:
+ // 1. Parity (SERR#)
+ // 2. Master Abort
+ // 3. Target Abort
+ // 4. Access Error
+ // 5. System Error
+ // 6. Retry Error
+ //
+
+ BadStatus = READ_REGISTER_ULONG(HalpPmpPciStatus);
+
+ if ( BadStatus & PCI_STATUS_RMA) {
+
+ //
+ // Determine if this is expected (from
+ // pci config probe) or unexpected
+ //
+
+ if (HalpPciRmaConfigErrorOccurred == 0) {
+
+ //
+ // Clear the error source
+ //
+
+ READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ HalpPciRmaConfigErrorOccurred = 1;
+
+ } else {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRmaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RMA],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRmaLogVariable[i],
+ sizeof(HalpPciRmaLogVariable[i]));
+
+ }
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RSE) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRseLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RSE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRseLogVariable[i],
+ sizeof(HalpPciRseLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RER) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRerLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RER],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRerLogVariable[i],
+ sizeof(HalpPciRerLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_IAE) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciIaeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_IAE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciIaeLogVariable[i],
+ sizeof(HalpPciIaeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_MPE) {
+
+ //
+ // Read the address and status registers
+ // and update the appropriate variables
+ //
+
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciMpeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_MPE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciMpeLogVariable[i],
+ sizeof(HalpPciMpeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_RTA) {
+
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciRtaLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_RTA],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciRtaLogVariable[i],
+ sizeof(HalpPciRtaLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & PCI_STATUS_ME) {
+
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ HalpPciMeLogVariable[PCI_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ for (i = 0; i < PCI_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzPciErrorLogKeys[PCI_ERROR_LOG_KEY_ME],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpPciMeLogVariable[i],
+ sizeof(HalpPciMeLogVariable[i]));
+
+ }
+
+ }
+
+}
+
+/*++
+
+Routine Description:
+
+ This function handles Memory interrupts on a FASTseries.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalpMemoryInterrupt(
+ VOID
+ )
+
+{
+ ULONG BadStatus, i;
+
+
+ //
+ // MEMORY:
+ // 1. Uncorrectable memory error
+ // 2. Multiple UE
+ // 3. Mutiple CE
+ //
+
+ BadStatus = READ_REGISTER_ULONG(HalpPmpMemStatus);
+
+ if ( BadStatus & MEM_STATUS_MUE ) {
+
+ //
+ // Read the address, status, and diag registers
+ // and update the appropriate variables
+ //
+
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryMueLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_MUE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryMueLogVariable[i],
+ sizeof(HalpMemoryMueLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & (MEM_STATUS_EUE | MEM_STATUS_OUE) ) {
+
+ //
+ // Read the address, status, and diag registers
+ // and update the appropriate variables
+ //
+
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryUeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_UE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryUeLogVariable[i],
+ sizeof(HalpMemoryUeLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & MEM_STATUS_MCE ) {
+
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryMceLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_MCE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryMceLogVariable[i],
+ sizeof(HalpMemoryMceLogVariable[i]));
+
+ }
+
+ } else if ( BadStatus & (MEM_STATUS_ECE | MEM_STATUS_OCE) ) {
+
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX0]++;
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX1]++;
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX2] = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX3] = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ HalpMemoryCeLogVariable[MEMORY_ERROR_LOG_VALUEKEY_INDEX4] = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ for (i = 0; i < MEMORY_ERROR_LOG_VALUEKEY_MAX; i++) {
+
+ HalpLogErrorInfo(rgzMemoryErrorLogKeys[MEMORY_ERROR_LOG_KEY_CE],
+ rgzMemoryErrorLogValueKeys[i],
+ REG_DWORD,
+ &HalpMemoryCeLogVariable[i],
+ sizeof(HalpMemoryCeLogVariable[i]));
+
+ }
+
+ }
+
+}
+
diff --git a/private/ntos/nthals/halntp/mips/fxhalp.h b/private/ntos/nthals/halntp/mips/fxhalp.h
new file mode 100644
index 000000000..3dd6c6691
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxhalp.h
@@ -0,0 +1,146 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ fxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Falcon specific interfaces, defines and structures.
+
+
+--*/
+
+#ifndef _FXHALP_
+#define _FXHALP_
+
+
+//
+// Define global data used for EISA devices
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+extern UCHAR HalpEisaInterrupt1Mask;
+extern UCHAR HalpEisaInterrupt2Mask;
+extern UCHAR HalpEisaInterrupt1Level;
+extern UCHAR HalpEisaInterrupt2Level;
+
+//
+// Define global data used for PMP registers
+//
+
+extern PVOID HalpPmpIoIntAck;
+extern PVOID HalpPmpIntCause;
+extern PVOID HalpPmpIntStatus;
+extern PVOID HalpPmpIntStatusProcB;
+extern PVOID HalpPmpIntCtrl;
+extern PVOID HalpPmpIntCtrlProcB;
+extern PVOID HalpPmpIntSetCtrl;
+extern PVOID HalpPmpIntSetCtrlProcB;
+extern PVOID HalpPmpTimerIntAck;
+extern PVOID HalpPmpTimerIntAckProcB;
+extern PVOID HalpPmpIntClrCtrl;
+extern PVOID HalpPmpIntClrCtrlProcB;
+extern PVOID HalpPmpMemStatus;
+extern PVOID HalpPmpMemCtrl;
+extern PVOID HalpPmpMemErrAck;
+extern PVOID HalpPmpMemErrAddr;
+extern PVOID HalpPmpPciStatus;
+extern PVOID HalpPmpPciCtrl;
+extern PVOID HalpPmpPciErrAck;
+extern PVOID HalpPmpPciErrAddr;
+extern PVOID HalpPmpIpIntAck;
+extern PVOID HalpPmpIpIntAckProcB;
+extern PVOID HalpPmpIpIntGen;
+extern PVOID HalpPmpPciConfigSpace;
+extern PVOID HalpPmpPciConfigAddr;
+extern PVOID HalpPmpPciConfigSelect;
+extern PVOID HalpExtPmpControl;
+extern PVOID HalpFlashRamBase;
+extern PVOID HalpDmaBufferPool;
+extern PVOID HalpPmpMemDiag;
+extern PVOID HalpPmpPciRetry;
+
+extern ULONG MACHINE_ID;
+extern ULONG HalpPciMemoryOffset;
+extern ULONG HalpPmpProcessorBPresent;
+extern ULONG HalpPmpExternalCachePresent;
+extern ULONG HalpPmpHalFlushIoBuffer;
+extern ULONG HalpPmpRevision;
+
+extern ULONG HalpPmpMemErrAckValue;
+extern ULONG HalpPmpMemErrAddrValue;
+extern ULONG HalpPmpPciErrAckValue;
+extern ULONG HalpPmpPciErrAddrValue;
+extern ULONG HalpPciBusErrorOccurred;
+extern ULONG HalpPciRmaConfigErrorOccurred;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+ INTERFACE_TYPE InterfaceType;
+ BOOLEAN AutoInitialize;
+} ADAPTER_OBJECT;
+
+//
+// IDT structures
+//
+
+#define MAXIMUM_IDTVECTOR 0xFF
+#define PRIMARY_VECTOR_BASE 0x10
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusRelativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+#endif // _FXHALP_
diff --git a/private/ntos/nthals/halntp/mips/fxhwsup.c b/private/ntos/nthals/halntp/mips/fxhwsup.c
new file mode 100644
index 000000000..73b4bbf49
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxhwsup.c
@@ -0,0 +1,3078 @@
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// Globals used to keep track of the private buffer pool managed by the HAL.
+//
+
+#define HALP_CONTIGUOUS_BUFFER_POOL_SIZE (0x8000 * 8)
+
+ULONG HalpContiguousBufferCurrentBase = 0;
+ULONG HalpContiguousBufferMax = 0;
+
+
+//
+// The HAL supports the concept of map registers which provide scatter/gather
+// functionality for IO devices whether a device directly supports scatter/gather
+// or not. FALCON will use one master adapter object to manage the pool of
+// map registers that can be allocated in groups for transfers requiring
+// multiple contiguous pages. This pool of map registers will be managed using
+// a bitmap data structure and are only available to EISA/ISA devices
+// and not PCI devices. In general, this should not be a problem given that the
+// majority of PCI devices will be busmaster devices that already support scatter/gather
+// on-chip or on-board. In the circumstance where a PCI device wants to do
+// multi-page transfers but does not itself support scatter/gather, the HAL will
+// attempt to transfer the maximum amount of data that is physically contiguous
+// in the described user/device buffer (by interrogating the MDL passed to IoMapTransfer).
+// In the worst-case the device will have to transfer a page at a time which is better
+// than supporting buffered-io which is slower.
+//
+
+
+PADAPTER_OBJECT MasterAdapterObject;
+PADAPTER_OBJECT HalpPciAdapterObject;
+
+ULONG HalpPciMemoryOffset;
+
+UCHAR HalpDma1Status;
+UCHAR HalpDma2Status;
+
+//
+// Variable to save the contents of the
+// bus error registers upon an exception
+//
+
+ULONG HalpPmpMemErrAckValue;
+ULONG HalpPmpMemErrAddrValue;
+ULONG HalpPmpPciErrAckValue;
+ULONG HalpPmpPciErrAddrValue;
+
+//
+// Local storage of pointer to physical memory of
+// the start of the map buffer pool and how many
+// PAGE_SIZE buffers it contains
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+//
+// Forward declarations
+//
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+ULONG
+HalpGetContiguousBufferPoolSize (
+ VOID
+ );
+
+
+
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG Hint;
+
+
+ //
+ // For PCI devices we don't have to deal with
+ // map registers, but we do for EISA devices!
+ //
+
+ if (AdapterObject->InterfaceType == PCIBus) {
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue, &Wcb->WaitQueueEntry )) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext);
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ }
+
+ } else {
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue, &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ Hint = 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint);
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters);
+
+ MapRegisterNumber = -1;
+ }
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext);
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+
+ }
+
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+ PHYSICAL_ADDRESS physAddr;
+
+ //
+ // Determine how many map registers (pages)
+ // the CommonBuffer requires.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the buffer
+ //
+
+ if (CacheEnabled != FALSE) {
+
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+
+ if (Length > PAGE_SIZE) {
+
+ if ((HalpContiguousBufferCurrentBase + Length) <= HalpContiguousBufferMax) {
+
+ //
+ // This is an absolute hack but it is the only
+ // way I can get a contiguous buffer for those
+ // devices which insist on large buffers. Because
+ // we don't have an IO TLB we cannot guarantee
+ // contiguousness. Devices such as the Madge Token
+ // Ring and the 3DLabs Glint insist on having a large
+ // DMA buffer.
+ //
+
+ physAddr.HighPart = 0;
+ physAddr.LowPart = HalpContiguousBufferCurrentBase;
+ virtualAddress = MmMapIoSpace(physAddr, Length, FALSE);
+
+ if (virtualAddress != (PVOID)NULL) {
+
+ HalpContiguousBufferCurrentBase += (numberOfMapRegisters * PAGE_SIZE);
+
+ }
+
+ } else {
+
+ virtualAddress = (PVOID)NULL;
+
+ }
+
+ } else {
+
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+
+ }
+
+ }
+
+
+ if (virtualAddress == NULL) {
+
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine);
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+
+ if (Length > PAGE_SIZE) {
+
+ MmUnmapIoSpace(virtualAddress, Length);
+ HalpContiguousBufferCurrentBase -= (numberOfMapRegisters * PAGE_SIZE);
+
+ } else {
+
+ MmFreeNonCachedMemory(virtualAddress, Length);
+
+ }
+
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject( &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+
+ if (Length > PAGE_SIZE) {
+
+ MmUnmapIoSpace(virtualAddress, Length);
+ HalpContiguousBufferCurrentBase -= (numberOfMapRegisters * PAGE_SIZE);
+
+ } else {
+
+ MmFreeNonCachedMemory(virtualAddress, Length);
+
+ }
+
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL);
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller
+ // can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE);
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled);
+
+ return(NULL);
+
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+
+{
+
+ return(TRUE);
+
+}
+
+
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+
+
+ //
+ // We only need to free up map registers
+ // if this was not a PCI device
+ //
+
+ if (AdapterObject->InterfaceType == PCIBus) {
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+
+ ExFreePool(VirtualAddress);
+
+ } else {
+
+ if (Length < PAGE_SIZE) {
+
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+
+ } else {
+
+ MmUnmapIoSpace(VirtualAddress, Length);
+
+ }
+
+ }
+
+ } else {
+
+ //
+ // Devices which do not use auto-initialize
+ // CommonBuffer DMA can use the scatter/gather
+ // capabilities of the 82374 which we manage
+ // through map registers.
+ //
+
+ if (!AdapterObject->AutoInitialize) {
+
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters);
+
+ }
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(VirtualAddress);
+
+ } else {
+
+ if (Length < PAGE_SIZE) {
+
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+
+ } else {
+
+ MmUnmapIoSpace(VirtualAddress, Length);
+
+ }
+ }
+
+ }
+
+ return;
+
+}
+
+
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: PCI, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+ if (DeviceDescription->InterfaceType != Internal
+ && DeviceDescription->InterfaceType != PCIBus
+ && DeviceDescription->InterfaceType != Isa
+ && DeviceDescription->InterfaceType != Eisa) {
+
+ return(NULL);
+
+ }
+
+ //
+ // Set the maximum number of map registers if requested.
+ //
+
+ if (NumberOfMapRegisters != NULL) {
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+
+ }
+
+ if (DeviceDescription->InterfaceType == PCIBus) {
+
+ //
+ // Create a PCI adapter object.
+ //
+
+ if (HalpPciAdapterObject == NULL) {
+
+ adapterObject = HalpAllocateAdapter(0, NULL, NULL);
+ adapterObject->InterfaceType = DeviceDescription->InterfaceType;
+ adapterObject->MasterAdapter = NULL;
+ HalpPciAdapterObject = adapterObject;
+
+ } else {
+
+ adapterObject = HalpPciAdapterObject;
+
+ }
+
+ } else {
+
+ //
+ // Create an EISA adapter object.
+ //
+
+ adapterObject = HalpAllocateEisaAdapter(DeviceDescription);
+
+ if (adapterObject == NULL) {
+
+ return NULL;
+
+ } else {
+
+ if ( *NumberOfMapRegisters > (MasterAdapterObject->MapRegistersPerChannel / 4) ) {
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+ }
+
+ //
+ // Set auto-initialize mode according to device's descriptor
+ // so that we don't use scatter/gather for common buffer
+ // devices
+ //
+
+ adapterObject->AutoInitialize = DeviceDescription->AutoInitialize;
+
+ //
+ // !!! HACK !!!
+ //
+ // This may not be necessary but it
+ // doesn't hurt given that the only
+ // devices who use this mode are sound
+ // cards.
+ //
+
+ if (adapterObject->AutoInitialize) {
+
+ *NumberOfMapRegisters = 1;
+
+ }
+
+ }
+
+ return(adapterObject);
+}
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+{
+
+ //
+ // We must replicate bits 31:28 into
+ // bits 35:32 so that in a wide mode
+ // system, both system asics can see
+ // the upper nibble of the address.
+ //
+
+ TranslatedAddress->QuadPart = BusAddress.QuadPart;
+
+ if (*AddressSpace) {
+
+ //
+ // EISA IO Space
+ //
+ // Note : for the keyboard controller, we need to munge the
+ // low-order address to be word-aligned as opposed to
+ // the previous byte-aligned address used by MIPS
+ // machines such as JAZZ, STRIKER and DUO.
+ //
+
+ if ((BusAddress.LowPart == 0xE0000061) || (BusAddress.LowPart == 0xA0000061)) {
+
+ TranslatedAddress->LowPart = EISA_IO_PHYSICAL_BASE | 0x00000064;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ } else {
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | EISA_IO_PHYSICAL_BASE;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ }
+
+ } else {
+
+ //
+ // EISA Memory Space
+ //
+ // Note : for the keyboard controller, we need to munge the
+ // low-order address to be word-aligned as opposed to
+ // the previous byte-aligned address used by MIPS
+ // machines such as JAZZ, STRIKER and DUO.
+ //
+
+ if ((BusAddress.LowPart == 0xE0000061) || (BusAddress.LowPart == 0xA0000061)) {
+
+ TranslatedAddress->LowPart = EISA_IO_PHYSICAL_BASE | 0x00000064;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ } else {
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | EISA_MEMORY_PHYSICAL_BASE;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ }
+
+ }
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+}
+
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+
+ TranslatedAddress->QuadPart = BusAddress.QuadPart;
+
+ //
+ // We must replicate bits 31:28 into
+ // bits 35:32 so that in a wide mode
+ // system, both system asics can see
+ // the upper nibble of the address.
+ //
+
+
+ if (*AddressSpace) {
+
+ //
+ // EISA IO Space
+ //
+ // Note : for the keyboard controller, we need to munge the
+ // low-order address to be word-aligned as opposed to
+ // the previous byte-aligned address used by MIPS
+ // machines such as JAZZ, STRIKER and DUO.
+ //
+
+ if ((BusAddress.LowPart == 0xE0000061) || (BusAddress.LowPart == 0xA0000061)) {
+
+ TranslatedAddress->LowPart = EISA_IO_PHYSICAL_BASE | 0x00000064;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ } else {
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | EISA_IO_PHYSICAL_BASE;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ }
+
+ } else {
+
+ //
+ // EISA Memory Space
+ //
+ // Note : for the keyboard controller, we need to munge the
+ // low-order address to be word-aligned as opposed to
+ // the previous byte-aligned address used by MIPS
+ // machines such as JAZZ, STRIKER and DUO.
+ //
+
+ if ((BusAddress.LowPart == 0xE0000061) || (BusAddress.LowPart == 0xA0000061)) {
+
+ TranslatedAddress->LowPart = EISA_IO_PHYSICAL_BASE | 0x00000064;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ } else {
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | EISA_MEMORY_PHYSICAL_BASE;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ }
+
+ }
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+ }
+
+ return(FALSE);
+
+}
+
+BOOLEAN
+HalpTranslatePCIBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+
+ //
+ // We must replicate bits 31:28 into
+ // bits 35:32 so that in a wide mode
+ // system, both system asics can see
+ // the upper nibble of the address.
+ //
+
+ TranslatedAddress->QuadPart = BusAddress.QuadPart;
+
+ if (*AddressSpace) {
+
+ //
+ // PCI IO Space
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | PCI_IO_PHYSICAL_BASE;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ } else {
+
+ //
+ // PCI Memory Space
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | PCI_MEMORY_PHYSICAL_BASE;
+ TranslatedAddress->HighPart = TranslatedAddress->LowPart >> 28;
+
+ }
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+ }
+
+ return(FALSE);
+
+}
+
+
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel : 0 means PCI adapter or EISA adapter;
+ otherwise, its the master adapter
+
+ AdapterBaseVa : Base virtual address of the adapter itself.
+ If NULL, then assume master adapter object.
+
+ MapRegisterBase : unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter( DMA_TRANSLATION_LIMIT / sizeof(TRANSLATION_ENTRY), NULL, NULL);
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL);
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if ( AdapterBaseVa == NULL && MapRegistersPerChannel ) {
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject(KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject(AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose(Handle);
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+
+ AdapterObject->MapRegistersPerChannel = DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdapter then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL && MapRegistersPerChannel ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap(AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ (DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)));
+
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) (HalpMapRegisterPhysicalBase | KSEG1_BASE);
+
+
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+ return AdapterObject;
+
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ ULONG Hint;
+
+
+ //
+ // Do this only for non-PCI devices
+ //
+
+ if (AdapterObject->InterfaceType != PCIBus) {
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters, MapRegisterNumber, NumberOfMapRegisters);
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet, ADAPTER_OBJECT, AdapterQueue);
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request.
+ //
+
+ Hint = 0;
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, NumberOfMapRegisters, Hint);
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(MasterAdapter->MapRegisters, MapRegisterNumber, NumberOfMapRegisters);
+
+ MapRegisterNumber = -1;
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where it came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+ break;
+
+ }
+
+ //
+ // Release spin lock
+ //
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ //
+ // Adjust map register base address
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext);
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whose
+ // execution routine decallocates the adapter. In that case, if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters, MapRegisterNumber, AdapterObject->NumberOfMapRegisters);
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ }
+}
+
+
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // For PCI devices we don't need to deal with
+ // map registers. For EISA devices we do.
+ //
+
+ if (AdapterObject->InterfaceType == PCIBus) {
+
+ while( TRUE ) {
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If there were no waiting jobs, break out of loop.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // Get current WCB
+ //
+
+ Wcb = CONTAINING_RECORD( Packet, WAIT_CONTEXT_BLOCK, WaitQueueEntry);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext);
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ }
+
+ } else {
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests off the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters);
+
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet, WAIT_CONTEXT_BLOCK, WaitQueueEntry);
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ Hint = 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ Hint);
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters);
+
+ MapRegisterNumber = -1;
+
+ }
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext);
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ }
+
+ }
+
+}
+
+
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = (PTRANSLATION_ENTRY)MapRegisterBase;
+ ULONG SgtMemoryAddress;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG LogicalAddress;
+ ULONG EisaLogicalAddress;
+ ULONG TransferLength;
+ ULONG i;
+
+
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+ TransferLength = PAGE_SIZE - Offset;
+
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ //
+ // Calculate LogicalAddress
+ //
+
+ LogicalAddress = ((*PageFrameNumber << PAGE_SHIFT) + Offset) & 0x7FFFFFFF;
+ LogicalAddress += HalpPciMemoryOffset;
+
+
+ if ( AdapterObject == NULL || AdapterObject->InterfaceType == PCIBus) {
+
+ if (NumberOfPages > 1) {
+
+ //
+ // Determine how much of the buffer is
+ // physically contiguous (if a multiple-page transfer)
+ // and adjust *Length accordingly.
+ //
+
+ while( TransferLength < *Length ){
+
+ //
+ // If next page in mdl not adjacent
+ // to current page, break out of loop
+ //
+
+ if ((*PageFrameNumber + 1) != *(PageFrameNumber + 1))
+ break;
+
+ //
+ // Adjust TransferLength and
+ // mdl pointer
+ //
+
+ TransferLength += PAGE_SIZE;
+ PageFrameNumber++;
+
+ }
+
+ //
+ // Limit the TransferLength to the requested Length.
+ //
+
+ *Length = (TransferLength > *Length) ? *Length : TransferLength;
+
+ }
+
+ return(RtlConvertUlongToLargeInteger(LogicalAddress));
+
+ } else {
+
+ //
+ // Devices which do not use auto-initialize
+ // CommonBuffer DMA can use the scatter/gather
+ // capabilities of the 82374 which we manage
+ // through map registers.
+ //
+
+ if (!AdapterObject->AutoInitialize) {
+
+ EisaLogicalAddress = LogicalAddress;
+
+ //
+ // Setup Scatter/Gather Table in the 82374
+ // based on the length of the transfer
+ //
+ if (NumberOfPages > 1) {
+
+ //
+ // Setup first page as a special case where
+ // count is less than a page size.
+ //
+
+ DmaMapRegister->Address = (ULONG) EisaLogicalAddress;
+ DmaMapRegister->ByteCountAndEol = (ULONG) (TransferLength - 1);
+ DmaMapRegister++;
+ PageFrameNumber++;
+ EisaLogicalAddress = (*PageFrameNumber << PAGE_SHIFT) & 0x7FFFFFFF;
+ EisaLogicalAddress += HalpPciMemoryOffset;
+
+ //
+ // Setup transfers that are each a page size
+ // in length except for the last page which
+ // we will special case due to the EOL bit
+ // that we must set to signify the end of the
+ // scatter-gather list.
+ //
+
+ for (i = 1; i < (NumberOfPages-1); i++) {
+
+ DmaMapRegister->Address = (ULONG) EisaLogicalAddress;
+ DmaMapRegister->ByteCountAndEol = (ULONG) (PAGE_SIZE - 1);
+ TransferLength += PAGE_SIZE;
+ DmaMapRegister++;
+ PageFrameNumber++;
+ EisaLogicalAddress = (*PageFrameNumber << PAGE_SHIFT) & 0x7FFFFFFF;
+ EisaLogicalAddress += HalpPciMemoryOffset;
+
+ }
+
+ //
+ // Now setup last page including the EOL bit.
+ //
+
+ DmaMapRegister->Address = (ULONG) EisaLogicalAddress;
+ DmaMapRegister->ByteCountAndEol = (ULONG) (*Length - TransferLength - 1) | SCATTER_GATHER_EOL;
+ TransferLength += (*Length - TransferLength);
+
+ } else {
+
+ DmaMapRegister->Address = (ULONG) EisaLogicalAddress;
+ DmaMapRegister->ByteCountAndEol = (ULONG) (*Length - 1) | SCATTER_GATHER_EOL;
+ TransferLength = *Length;
+
+ }
+
+ //
+ // Limit the TransferLength to the requested Length.
+ //
+
+ *Length = (TransferLength > *Length) ? *Length : TransferLength;
+
+ //
+ // Calculate the start of the SGD Table for this
+ // particular transfer
+ //
+
+ SgtMemoryAddress = (ULONG)MapRegisterBase & ~KSEG1_BASE;
+ SgtMemoryAddress += HalpPciMemoryOffset;
+
+ //
+ // Start the EISA DMA controller.
+ //
+
+ HalpEisaMapTransfer( AdapterObject, SgtMemoryAddress, *Length, WriteToDevice);
+
+ return(RtlConvertUlongToLargeInteger(LogicalAddress));
+
+ } else {
+
+ //
+ // For CommonBuffer devices (i.e., auto-initialize mode
+ // which cannot be used in conjunction with the 82374's
+ // scatter/gather mode) we will attempt to transfer the
+ // largest quantity possible based on how contiguous the
+ // buffer is.
+ //
+
+ if (NumberOfPages > 1) {
+
+ //
+ // Determine how much of the buffer is
+ // physically contiguous (if a multiple-page transfer)
+ // and adjust TransferLength accordingly.
+ //
+
+ while( TransferLength < *Length ){
+
+ //
+ // If next page in mdl not adjacent
+ // to current page, or if it crosses
+ // a 64K boundary, break out of loop
+ //
+
+ if ( (*PageFrameNumber + 1) != *(PageFrameNumber + 1) )
+ break;
+
+ //
+ // Adjust TransferLength and
+ // mdl pointer
+ //
+
+ TransferLength += PAGE_SIZE;
+ PageFrameNumber++;
+
+ }
+
+ //
+ // Limit the TransferLength to the requested Length
+ // or less than the requested Length if pages were
+ // non-contiguous.
+ //
+
+ *Length = (TransferLength > *Length) ? *Length : TransferLength;
+
+ }
+
+ HalpEisaMapTransfer( AdapterObject, LogicalAddress, *Length, WriteToDevice);
+
+ return(RtlConvertUlongToLargeInteger(LogicalAddress));
+
+ }
+
+ }
+
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+{
+
+ UCHAR DataByte;
+
+ if (AdapterObject == NULL) {
+
+ //
+ // This is a master adapter so there is nothing to do.
+ //
+
+ return(TRUE);
+
+ }
+
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ HalpDma1Status = READ_REGISTER_UCHAR( &dmaControl->DmaStatus);
+
+ WRITE_REGISTER_UCHAR( &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ HalpDma2Status = READ_REGISTER_UCHAR( &dmaControl->DmaStatus);
+
+ WRITE_REGISTER_UCHAR( &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) );
+
+ }
+
+ return(TRUE);
+
+}
+
+
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+ULONG
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+{
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount);
+
+ count |= READ_PORT_UCHAR(&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount);
+
+ count |= READ_PORT_UCHAR(&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ return(count);
+
+}
+
+
+
+
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ //
+ // FALCON does not support an IO TLB! However,
+ // the 82374 does support Scatter/Gather so we
+ // will use it for all EISA/ISA devices that need
+ // to do multi-page transfers provided that they
+ // do not use auto-initialize mode which cannot be
+ // used with the 82374's scatter/gather engine. In
+ // the case of auto-initialize devices, we will allocate
+ // a 64K buffer pool from which we will allocate
+ // common buffers to ensure physical contiguous-ness.
+ // Otherwise, we would have to break up the auto-initialize
+ // transfers on page boundaries which does not work
+ // for devices like SoundBlaster, etc.
+ //
+ // In the case of PCI devices, we will break transfers
+ // up according to the physical contiguous-ness of the
+ // buffer. There are no auto-initialize limitations
+ // associated with PCI devices.
+ //
+
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT + HALP_CONTIGUOUS_BUFFER_POOL_SIZE;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 1.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Initialize internal data structure
+ // responsible for maintaining address,
+ // size, and buffer number information.
+ //
+
+ HalpMapRegisterPhysicalBase = PhysicalAddress;
+
+ //
+ // Initialize the HAL buffer pool variables
+ //
+
+ HalpContiguousBufferCurrentBase = HalpMapRegisterPhysicalBase + (2*PAGE_SIZE);
+ HalpContiguousBufferMax = HalpContiguousBufferCurrentBase + HALP_CONTIGUOUS_BUFFER_POOL_SIZE - 1;
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+ ULONG Hint;
+
+
+ if (0) {
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Set the number of map registers required.
+ //
+
+ *NumberOfMapRegisters = 16;
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ Hint = 0;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ Hint);
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters);
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(MasterAdapter->MapRegisters,
+ Hint,
+ *NumberOfMapRegisters);
+
+ MapRegisterNumber = Hint;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+
+ }
+
+}
+
+/*++
+
+Routine Description:
+
+ This routine gets the contiguous buffer pool size from a
+ firmware environment variable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+ULONG
+HalpGetContiguousBufferPoolSize(
+ VOID
+ )
+
+{
+ register int i;
+ ULONG bufferpoolSize;
+ UCHAR buffer[20];
+ ULONG status;
+
+ status = (ULONG)HalGetEnvironmentVariable ("BUFFER_POOL_SIZE", sizeof(buffer), &buffer[0]);
+
+ if (status)
+ return 0;
+
+ bufferpoolSize = 0;
+ for (i=0; i < 8; i++) {
+
+ if (buffer[i] >= '0' && buffer[i] <= '9')
+ bufferpoolSize = 16 * bufferpoolSize + buffer[i] - '0';
+ else if (buffer[i] >= 'A' && buffer[i] <= 'F')
+ bufferpoolSize = 16 * bufferpoolSize + buffer[i] - 'A';
+ else if (buffer[i] >= 'a' && buffer[i] <= 'f')
+ bufferpoolSize = 16 * bufferpoolSize + buffer[i] - 'a';
+
+ }
+
+ return bufferpoolSize;
+
+}
+
+
+
+
diff --git a/private/ntos/nthals/halntp/mips/fxinfo.c b/private/ntos/nthals/halntp/mips/fxinfo.c
new file mode 100644
index 000000000..7af7b025b
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxinfo.c
@@ -0,0 +1,94 @@
+
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+
+#include "halp.h"
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
diff --git a/private/ntos/nthals/halntp/mips/fxintr.s b/private/ntos/nthals/halntp/mips/fxintr.s
new file mode 100644
index 000000000..8d34bfbdc
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxintr.s
@@ -0,0 +1,141 @@
+
+// TITLE("Falcon Interrupt Dispatch")
+//++
+//
+// Copyright (c) 1994 NeTpower, Inc.
+//
+// Module Name:
+//
+// fxintr.s
+//
+// Abstract:
+//
+// This routine is the master interrupt handler
+// for all FALCON system interrupts.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+
+#include "halmips.h"
+#include "falreg.h"
+#include "faldef.h"
+
+
+ SBTTL("System Interrupt Dispatch")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of
+// any system interrupt controlled by the
+// FALCON PMP chip.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(HalpInterruptDispatch)
+
+ //
+ // Determine the interrupt source by
+ // interrogating the IntCause register
+ // which is per-processor based. The
+ // order of this code has an implied
+ // priority : IP, IT, IO, ECC, PCI
+ //
+
+ lw t0, HalpPmpIntCause
+ lw t0, 0(t0)
+
+ .set noreorder
+ .set noat
+
+ //
+ // NEW WAY: Take the the upper 16 bits of IntCause, combine it with
+ // the lower 16 bits in IntCause, and use those to pick which interrupt.
+ //
+ srl a0, t0, 16
+ or t0, t0, a0 // Note, an AND would give LCD
+
+#ifndef PMP_V2_TIMER_BUG_FIXED
+ //
+ // !!!BUG WORKAROUND!!!
+ // Assumes timer interrupt...
+ //
+ // Note, this can be removed ONCE all PMP V2 are replaced in the field
+ //
+ li a0, INT_CAUSE_IO
+ beql t0, zero, 4f
+ or t0, t0, a0
+
+4:
+#endif // PMP_V2_TIMER_BUG_FIXED
+
+ //
+ // Check if an Inter-Processor interrupt
+ //
+ andi a1, t0, (INT_CAUSE_IPC & 0xFFFF)
+ bnel a1, zero, 2f
+ addiu t5, zero, (IPI_LEVEL*4)
+
+ //
+ // Check if an Timer interrupt
+ //
+ andi a1, t0, (INT_CAUSE_TIMER & 0xFFFF)
+ bnel a1, zero, 2f
+ addiu t5, zero, (CLOCK2_LEVEL*4)
+
+ //
+ // Check if an IO device interrupt
+ //
+ andi a1, t0, (INT_CAUSE_IO & 0xFFFF)
+ bnel a1, zero, 2f
+ addiu t5, zero, (IO_DEVICE_LEVEL*4)
+
+ //
+ // Check if a Memory ECC error
+ //
+ andi a1, t0, (INT_CAUSE_MEM & 0xFFFF)
+ bnel a1, zero, 2f
+ addiu t5, zero, (MEMORY_LEVEL*4)
+
+ //
+ // Check if a PCI error
+ //
+ andi a1, t0, (INT_CAUSE_PCI & 0xFFFF)
+ bnel a1, zero, 2f
+ addiu t5, zero, (PCI_LEVEL*4)
+
+
+#ifndef PMP_V2_TIMER_BUG_FIXED
+
+ //
+ // !!BUG WORKAROUND!!!
+ // If we get here with no bits set, assume timer interrupt.
+ // PMP V3 fixes this.
+ //
+
+ addiu t5, zero, (CLOCK2_LEVEL*4)
+
+#endif // PMP_V2_TIMER_BUG_FIXED
+
+ .set at
+ .set reorder
+
+ //
+ // Transfer control to interrupt handler
+ //
+2:
+ lw a0, KiPcr + PcInterruptRoutine(t5)
+ j a0
+
+ .end HalpInterruptDispatch
diff --git a/private/ntos/nthals/halntp/mips/fxnvram.c b/private/ntos/nthals/halntp/mips/fxnvram.c
new file mode 100644
index 000000000..6df0fccd0
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxnvram.c
@@ -0,0 +1,30 @@
+
+/*++
+
+Copyright (c) 1994 NeTpower, Inc.
+
+Module Name:
+
+ fxnvram.c
+
+Abstract:
+
+ This routine contains the code needed to deal with the NVRAM structures on Falcon.
+ Note, Flash is being used for NVRAM as well as the NVRAM in the Sidewinder chip.
+ This is a file that should be shared between the firmware and HAL.
+
+--*/
+
+#include "halp.h"
+#include "pcieisa.h"
+
+#if defined(_FALCON_HAL_)
+
+#include "eisa.h"
+
+#endif // _FALCON_HAL_
+
+#define GENERATE_NVRAM_CODE
+#include "falnvram.h"
+
+
diff --git a/private/ntos/nthals/halntp/mips/fxpcibrd.c b/private/ntos/nthals/halntp/mips/fxpcibrd.c
new file mode 100644
index 000000000..139125528
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxpcibrd.c
@@ -0,0 +1,825 @@
+
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+
+extern UCHAR HalpPCIPinToLineTable[];
+extern UCHAR HalpPCIBusToPirqTable[];
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI brdige. Determine the PIRQ to bus number
+ // mappings and store them in the HalpPCIBusToPirqTable[].
+ //
+
+ for (i = CB.PciData->u.type1.SecondaryBus;
+ i <= CB.PciData->u.type1.SubordinateBus;
+ i++) {
+
+ HalpPCIBusToPirqTable[i] = HalpPCIPinToLineTable[d];
+
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // relationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+ DBGMSG("HAL: VGA mode enable in bridge\n");
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+ DBGMSG("HAL: ISA mode enable in bridge\n");
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = (ULONGLONG)0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+ return FALSE;
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+ HalpFreeRangeList (HRanges);
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ HalpConsolidateRanges (Bus->BusAddresses);
+
+ }
+}
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f;
+ NTSTATUS status;
+
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the firmware didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged.
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ //
+ // Get IRQ value from table since firmware
+ // did not initialize the bridge.
+ //
+
+ Current->PciData->u.type1.InterruptPin =
+ CB.PciData->u.type0.InterruptPin + (UCHAR)d % 4;
+
+ Current->PciData->u.type1.InterruptLine =
+ HalpPCIPinToLineTable[(CB.BusNo*8) + CB.SlotNumber.u.bits.DeviceNumber];
+ }
+ }
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0xD000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x0 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x0 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0 >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+
+
diff --git a/private/ntos/nthals/halntp/mips/fxpcibus.c b/private/ntos/nthals/halntp/mips/fxpcibus.c
new file mode 100644
index 000000000..76170e745
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxpcibus.c
@@ -0,0 +1,2595 @@
+
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ Platform-independent PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+typedef ULONG (*FncConfigIO) (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+//
+// Local prototypes
+//
+
+BOOLEAN
+HalpPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+ULONG HalpPCIReadUlong (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUchar (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshort (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlong (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUchar (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshort (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//
+// Pragmas to assign functions to different kinds of pages.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePCIBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+ULONG HalpPciBusErrorOccurred;
+ULONG HalpPciRmaConfigErrorOccurred;
+
+//
+// These structures are used to efficiently
+// generate the PCI configuration cycles by
+// executing the largest transaction size
+// possible for each cycle.
+//
+
+PCI_CONFIG_HANDLER PCIConfigHandler = {
+ {
+ HalpPCIReadUlong, // 0
+ HalpPCIReadUchar, // 1
+ HalpPCIReadUshort // 2
+ },
+ {
+ HalpPCIWriteUlong, // 0
+ HalpPCIWriteUchar, // 1
+ HalpPCIWriteUshort // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+//
+// This is the IDSEL decode table for Falcon. It is indexed
+// by the DeviceNumber assigned to a particular device according
+// to where it is located within the system. BusNumber 0 refers
+// to Local PCI Devices whereas BusNumbers 1, 2, and 3 refer to
+// Remote PCI Devices attached to PCI-PCI bridges installed in
+// slot 0, 1, and 2, respectively. The BusNumber, DeviceNumber,
+// and IDSEL mappings are described as follows:
+//
+// BusNumber DeviceNumber IDSEL Slot
+// --------- ------------ ----- ----
+//
+// 0 0 - 7 0x1 - 0x80 Internal
+// 1 8 - 15 0x10 0
+// 2 16 - 23 0x20 1
+// 3 24 - 31 0x40 2
+//
+// Note:
+// If you change anything in or about these tables, you MUST
+// also change HalpInitializeEisaInterrupts() which depends
+// on the structure and order of these tables.
+//
+
+UCHAR HalpPciConfigSelectDecodeTable[32] = {
+
+ // Bus Number 0
+ // Device Number : (0) (1) (2) (3) (4) (5) (6) (7)
+ // On-board Devices : ISA/EISA ENET SCSI Not Used SLOT0 SLOT1 Not Used FASTswitch
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+
+ // Bus Number 0
+ // Device Number : (8) (9) (10) (11) (12) (13) (14) (15)
+ // Remote Devices :
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ // Bus Number 0
+ // Device Number : (16) (17) (18) (19) (20) (21) (22) (23)
+ // Remote Devices :
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ // Bus Number 0
+ // Device Number : (24) (25) (26) (27) (28) (29) (30) (31)
+ // Remote Devices :
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+};
+
+//
+// The following table describes the interrupt level
+// assigned to a particular PCI device based on where
+// it is located within the system. The DeviceNumber
+// is used as an index into this table which contains
+// the IRQ level assigned to that device. Note that
+// Remote Devices will share an interrupt level based
+// on which bus/slot they are attached.
+//
+// This table is initialized with 0xFF for each device
+// until the correct PIRQs are read from the 82374/82375
+// chipset. The PIRQ values are programmed by the firmware
+// and are dynamically configurable through the ARC menu.
+//
+
+UCHAR HalpPCIPinToLineTable[32] = {
+
+ // Bus Number 0
+ // Device Number : (0) (1) (2) (3) (4) (5) (6) (7)
+ // On-board Devices : ISA/EISA ENET SCSI Not Used SLOT0 SLOT1 Not Used FASTswitch
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
+ // Bus Number 0
+ // Device Number : (8) (9) (10) (11) (12) (13) (14) (15)
+ // Remote Devices :
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
+ // Bus Number 0
+ // Device Number : (16) (17) (18) (19) (20) (21) (22) (23)
+ // Remote Devices :
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
+ // Bus Number 0
+ // Device Number : (24) (25) (26) (27) (28) (29) (30) (31)
+ // Remote Devices :
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+};
+
+UCHAR HalpPIRQTable[4];
+
+//
+// This table serves to map a PCI bus number to
+// one of the PIRQ lines from the 82375. This table
+// is filled in during Phase 0 initialization to
+// allow for dynamic reallocation of the interrupt
+// routing on PCI.
+//
+
+UCHAR HalpPCIBusToPirqTable[32] = {
+
+ //
+ // Bus Number 0 1 2 3 4 5 6 7
+ //
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ // Bus Number 8 9 10 11 12 13 14 15
+ //
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ // Bus Number 16 17 18 19 20 21 22 23
+ //
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ // Bus Number 24 25 26 27 28 29 30 31
+ //
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+};
+
+//
+// Registry stuff
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_PREFETCHABLE) == PCI_TYPE_64BIT))
+
+
+
+/*++
+
+Routine Description:
+
+ The function intializes global PCI bus state from the registry.
+
+ The Arc firmware is responsible for building configuration information
+ about the number of PCI buses on the system and nature (local vs. secondary
+ - across a PCI-PCI bridge) of the each bus. This state is held in
+ PCIRegInfo.
+
+ The maximum virtual slot number on the local (type 0 config cycle)
+ PCI bus is registered here, based on the machine dependent define
+ PCI_MAX_LOCAL_DEVICE.
+
+ The maximum number of virtual slots on a secondary bus is fixed by the
+ PCI Specification and is represented by PCI_MAX_DEVICES.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ )
+
+{
+
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ ULONG i, d, HwType, BusNo, f;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PBUS_HANDLER BusHandler;
+
+#if 0
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ ULONG junk;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ PWSTR p;
+ WCHAR wstr[8];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+#else
+
+ //
+ // We are forcing the number of PCI
+ // buses in the system to be > 1 to
+ // workaround a problem we are having
+ // wrt opening and reading the registry
+ // at this point during the Phase 1
+ // initialization. This seems to work
+ // regardless if there are one or more
+ // PCI buses in the system.
+ //
+
+ PCIRegInfo->NoBuses = PCI_MAX_BUS_NUMBER;
+ PCIRegInfo->HardwareMechanism = 2;
+
+#endif
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support (as indicated by the BIOS).
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Determine what PCI bus type we got
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // Allocate type2 and test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+ buffer[1] &= ~0x01; // turn off bit 0 register 0x54
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+}
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Bus data type
+ BusNo, // bus number
+ Internal, // parent bus
+ 0, // parent bus number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIInterruptVector;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->TranslateBusAddress = (PTRANSLATEBUSADDRESS) HalpTranslatePCIBusAddress;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPinToLine;
+
+ //
+ // Set defaults
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetPCIIrqRange;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+ BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+ BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = 0xf;
+
+ break;
+
+ default:
+ // unsupport type
+ break;
+ }
+
+ return Bus;
+
+}
+
+
+
+
+/*++
+
+Routine Description:
+
+ The function returns the PCI bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PPCIPBUSDATA BusData;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ //
+ // Check for non-existent bus
+ //
+
+ if (PciData->VendorID == 0) {
+ return 0; // Requested bus does not exist. Return no data.
+ }
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 2;
+ }
+
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ //
+ // Check for non-existent bus
+ //
+
+ if (PciData->VendorID == 0x00) {
+ Len = 0; // Requested bus does not exist. Return no data.
+ }
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+
+ }
+
+ }
+
+ return Len;
+}
+
+
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PPCIPBUSDATA BusData;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PciData->VendorID == 0x00) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00 ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ //
+ // no device, or header type unkown
+ //
+
+ return 0;
+ }
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ //BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+
+
+ //
+ // Read the slot, if it's valid.
+ // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
+ // or a null (zero) buffer if we have a non-existant bus.
+ //
+
+ switch (HalpValidPCISlot (BusHandler, Slot)) {
+
+ case ValidSlot:
+
+ //
+ // Issue PCI Config Read Cycle(s)
+ //
+
+ if (!HalpPCIConfig (BusHandler->BusNumber, Slot, (PUCHAR) Buffer, Offset, Length, PCIConfigHandler.ConfigRead)) {
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ }
+ break;
+
+ case InvalidSlot:
+
+ //
+ // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ break ;
+
+ case InvalidBus:
+
+ //
+ // Invalid Bus, return return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) 0);
+ break ;
+
+ }
+
+ return;
+
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+
+ if (HalpValidPCISlot (BusHandler, Slot) != ValidSlot) {
+
+ //
+ // Invalid SlotID do nothing
+ //
+
+ return ;
+ }
+
+ //
+ // Issue PCI Config Write Cycle(s)
+ //
+
+ HalpPCIConfig ( BusHandler->BusNumber,
+ Slot,
+ (PUCHAR)Buffer,
+ Offset,
+ Length,
+ PCIConfigHandler.ConfigWrite);
+
+}
+
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ //ULONG i, j;
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+#if 0
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+#endif
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ UCHAR HeaderType;
+ ULONG i;
+ PCI_CONFIGURATION_TYPES PciConfigType;
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Get the config cycle type for the proposed bus.
+ // (PciConfigTypeInvalid indicates a non-existent bus.)
+ //
+
+ PciConfigType = HalpPCIConfigCycleType(BusHandler->BusNumber, Slot);
+
+ //
+ // The number of devices allowed on a local PCI bus may be different
+ // than that across a PCI-PCI bridge.
+ //
+
+ switch(PciConfigType) {
+
+ case PciConfigType0:
+
+ if (Slot.u.bits.DeviceNumber > BusData->MaxDevice) {
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigType1:
+
+ if (Slot.u.bits.DeviceNumber > BusData->MaxDevice) {
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigTypeInvalid:
+ return InvalidBus;
+
+ break;
+
+ }
+
+ //
+ // Check function number
+ //
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return ValidSlot;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof(UCHAR) );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) {
+
+ //
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ //
+
+ return InvalidSlot;
+
+ }
+
+ return ValidSlot;
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+
+BOOLEAN
+HalpPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ PCI_CONFIG_ADDR PciConfigAddrData;
+ ULONG OldIntCtrl;
+ BOOLEAN ConfigOk;
+
+
+ ConfigOk = TRUE;
+
+ //
+ // Acquire Spin Lock
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ //
+ // Force PCI read errors to be asynchronous (interrupts)
+ // as opposed to synchronous (bus errors)
+ //
+
+ OldIntCtrl = READ_REGISTER_ULONG(HalpPmpIntCtrl);
+
+ if ( PCR->Prcb->Number == 0 ) {
+ WRITE_REGISTER_ULONG(HalpPmpIntCtrl, OldIntCtrl | INT_CTRL_SEC1 | INT_CTRL_PIEA);
+ } else {
+ WRITE_REGISTER_ULONG(HalpPmpIntCtrl, OldIntCtrl | INT_CTRL_SEC1 | INT_CTRL_PIEB);
+ }
+
+ //
+ // Program PciConfigAddr register
+ //
+
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = (BusNumber ? Slot.u.bits.DeviceNumber : 0);
+ PciConfigAddrData.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciConfigAddrData.Reserved1 = 0;
+ PciConfigAddrData.Reserved2 = 0;
+
+ WRITE_REGISTER_ULONG(HalpPmpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ //
+ // Select PCI device using PciConfigSelect
+ // (IDSEL) register which is software programmable
+ // versus having the hardware decode the DeviceNumber
+ // field of the Configuration Address
+ //
+
+ WRITE_REGISTER_UCHAR(HalpPmpPciConfigSelect, BusNumber ? 0 : HalpPciConfigSelectDecodeTable[Slot.u.bits.DeviceNumber]);
+
+ //
+ // Issue PCI Configuration Cycles
+ // efficiently using word, hword, and
+ // byte quantities based on the transfer
+ // length and the buffer offset.
+ //
+
+ while (Length) {
+
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (Buffer, Offset);
+
+ //
+ // Exit loop because we got a bus
+ // error during a PCI config cycle
+ //
+
+ if (!i) {
+
+ ConfigOk = FALSE;
+ break;
+
+ }
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+
+ }
+
+ //
+ // Deselect PCI device
+ //
+
+ WRITE_REGISTER_UCHAR(HalpPmpPciConfigSelect, 0);
+
+ //
+ // Restore interrupt register to treat read
+ // errors synchronously (as bus errors)
+ //
+
+ WRITE_REGISTER_ULONG(HalpPmpIntCtrl, OldIntCtrl);
+
+ //
+ // Release Spin Lock
+ //
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+
+ return ConfigOk;
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ )
+
+{
+
+
+ //
+ // Determine if Type0, Type1, or Invalid
+ //
+
+ if (BusNumber < 0 || BusNumber > PCI_MAX_BUS_NUMBER) {
+ return PciConfigTypeInvalid;
+ } else if (BusNumber) {
+ return PciConfigType1;
+ } else {
+ return PciConfigType0;
+ }
+
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+ULONG
+HalpPCIReadUchar (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ ULONG DataLength;
+
+
+
+ //
+ // Clear bus error flag which will be set
+ // by the interrupt handler in the event we
+ // get an interrupt caused by a master abort
+ //
+
+ HalpPciRmaConfigErrorOccurred = 0;
+
+ //
+ // Do PCI Configuration BYTE Read
+ //
+
+ *Buffer = READ_REGISTER_UCHAR ((PUCHAR) ((ULONG)HalpPmpPciConfigSpace + Offset));
+ DataLength = sizeof(UCHAR);
+
+ //
+ // If we ecountered a master target abort during the
+ // configuration read, then no device exists in that slot
+ //
+
+ if (HalpPciRmaConfigErrorOccurred == 1) {
+
+ *Buffer = 0xFF;
+ DataLength = 0;
+
+ }
+
+ //
+ // Now reset the bus error flag
+ // to -1 that way if a master abort
+ // occurs for some other reason than
+ // during a pci config probe, we will
+ // deal with it in the handler correctly.
+ //
+
+ HalpPciRmaConfigErrorOccurred = 2;
+
+ return DataLength;
+
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+ULONG
+HalpPCIReadUshort (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG DataLength;
+
+
+ //
+ // Clear bus error flag which will be set
+ // by the interrupt handler in the event we
+ // get an interrupt caused by a master abort
+ //
+
+ HalpPciRmaConfigErrorOccurred = 0;
+
+ //
+ // Do PCI Configuration HWORD Read
+ //
+
+ *((PUSHORT) Buffer) = READ_REGISTER_USHORT ((PUSHORT) ((ULONG)HalpPmpPciConfigSpace + Offset));
+ DataLength = sizeof(USHORT);
+
+ //
+ // If we ecountered a master target abort during the
+ // configuration read, then no device exists in that slot
+ //
+
+ if (HalpPciRmaConfigErrorOccurred == 1) {
+
+ *((PUSHORT) Buffer) = 0xFFFF;
+ DataLength = 0;
+
+ }
+
+ //
+ // Now reset the bus error flag
+ // to -1 that way if a master abort
+ // occurs for some other reason than
+ // during a pci config probe, we will
+ // deal with it in the handler correctly.
+ //
+
+ HalpPciRmaConfigErrorOccurred = 2;
+
+ return DataLength;
+
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+ULONG
+HalpPCIReadUlong (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ ULONG DataLength;
+
+
+ //
+ // Clear bus error flag which will be set
+ // by the interrupt handler in the event we
+ // get an interrupt caused by a master abort
+ //
+
+ HalpPciRmaConfigErrorOccurred = 0;
+
+ //
+ // Do PCI Configuration WORD Read
+ //
+
+ *((PULONG) Buffer) = READ_REGISTER_ULONG ((PULONG) ((ULONG)HalpPmpPciConfigSpace + Offset));
+ DataLength = sizeof(ULONG);
+
+ //
+ // If we ecountered a master target abort during the
+ // configuration read, then no device exists in that slot
+ //
+
+ if (HalpPciRmaConfigErrorOccurred == 1) {
+
+ *((PULONG) Buffer) = 0xFFFFFFFF;
+ DataLength = 0;
+
+ }
+
+ //
+ // Now reset the bus error flag
+ // to -1 that way if a master abort
+ // occurs for some other reason than
+ // during a pci config probe, we will
+ // deal with it in the handler correctly.
+ //
+
+ HalpPciRmaConfigErrorOccurred = 2;
+
+ return DataLength;
+
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+ULONG
+HalpPCIWriteUchar (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+
+ //
+ // Do PCI Configuration BYTE Write
+ //
+
+ WRITE_REGISTER_UCHAR ((PUCHAR) ((ULONG)HalpPmpPciConfigSpace + Offset), *Buffer);
+
+ return sizeof (UCHAR);
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+ULONG
+HalpPCIWriteUshort (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ //
+ // Do PCI Configuration BYTE Write
+ //
+
+ WRITE_REGISTER_USHORT ((PUSHORT) ((ULONG)HalpPmpPciConfigSpace + Offset), *((PUSHORT)Buffer));
+
+ return sizeof (USHORT);
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+ULONG
+HalpPCIWriteUlong (
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ //
+ // Do PCI Configuration BYTE Write
+ //
+
+ WRITE_REGISTER_ULONG ((PULONG) ((ULONG)HalpPmpPciConfigSpace + Offset), *((PULONG)Buffer));
+
+ return sizeof (ULONG);
+}
+
+
+
+/*++
+
+Routine Description:
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpPCIPinToLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+
+{
+
+ ULONG BusNumber;
+
+ BusNumber = (ULONG)BusHandler->BusNumber;
+
+
+ //
+ // Devices (or device functions) that don't use an interrupt pin must
+ // put a zero in this configuration register.
+ //
+
+ if (!PciData->u.type0.InterruptPin) {
+ return;
+ }
+
+ //
+ // On NeTpower machines, the values in this register correspond to
+ // IRQ numbers (0-15) of the standard 8259 interrupt controller contained
+ // in the 82374.
+ //
+
+ if (PciData->u.type0.InterruptLine != HalpPIRQTable[0] &&
+ PciData->u.type0.InterruptLine != HalpPIRQTable[1] &&
+ PciData->u.type0.InterruptLine != HalpPIRQTable[2] &&
+ PciData->u.type0.InterruptLine != HalpPIRQTable[3] )
+
+ PciData->u.type0.InterruptLine = ( (BusNumber)
+ ? HalpPCIBusToPirqTable[BusNumber]
+ : HalpPCIPinToLineTable[SlotNumber.u.bits.DeviceNumber] );
+
+}
+
+/*++
+
+Routine Description:
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpPCILineToPin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+
+{
+
+ ULONG BusNumber;
+
+ BusNumber = (ULONG)BusHandler->BusNumber;
+
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return;
+ }
+
+ if ( (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine) ||
+ (PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) ) {
+
+#if 0
+ //
+ // Change the Pin2Line table
+ //
+
+ if (BusNumber) {
+ HalpPCIBusToPirqTable [BusNumber] = PciNewData->u.type0.InterruptLine;
+ } else {
+ HalpPCIPinToLineTable [SlotNumber.u.bits.DeviceNumber] = PciNewData->u.type0.InterruptLine;
+ }
+
+ //
+ // Now re-program the PIRQ registers
+ //
+#endif
+
+ }
+
+}
+
+
+
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+
+{
+
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ //
+ // Enable Memory and IO space accesses
+ //
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources);
+
+ if (!NT_SUCCESS(status)) {
+
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ //BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ m = 0;
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m |= PCI_ENABLE_IO_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ m |= PCI_ENABLE_MEMORY_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // We will always enable the Memory, IO, and BusMaster functions
+ // of a PCI device because some drivers expect (and check) these
+ // bits to be enabled (usually by the firmware). In our case, the
+ // firmware does not properly configure all pci devices and so
+ // this hack is required to be backward compatible with older
+ // firmware. Future firmware should do the right thing ...
+ //
+ // We never enable the ROM decodes since, in theory, only the driver
+ // knows when it's safe to do that.
+ //
+
+ PciData->Command |= (USHORT) (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER);
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+
+}
+
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+
+--*/
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+ return Status;
+
+}
+
+
+NTSTATUS
+HalpGetPCIIrqRange (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+
+ return STATUS_SUCCESS;
+
+}
diff --git a/private/ntos/nthals/halntp/mips/fxpmpsup.c b/private/ntos/nthals/halntp/mips/fxpmpsup.c
new file mode 100644
index 000000000..eb6834480
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxpmpsup.c
@@ -0,0 +1,11 @@
+
+//
+// When INITIALIZE_MACHINE_DATA is defined, all the machine specific data structures are
+// declared. Otherwise, extern's to these data structures are inserted. This flag is
+// used in faldef.h which is where all the machine specific data structures live
+//
+
+#define INITIALIZE_MACHINE_DATA
+
+#include "halp.h"
+
diff --git a/private/ntos/nthals/halntp/mips/fxusage.c b/private/ntos/nthals/halntp/mips/fxusage.c
new file mode 100644
index 000000000..a8f556234
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/fxusage.c
@@ -0,0 +1,523 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixusage.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+--*/
+
+#include "halp.h"
+
+KAFFINITY HalpActiveProcessors;
+
+UCHAR HalName[] = "NeTpower FASTseries HAL";
+
+//
+// prototypes
+//
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects and registers those
+ IDT vectors used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ PCR->InterruptRoutine[SystemInterruptVector] = HalInterruptServiceRoutine;
+
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusRelativeVector = (UCHAR) BusInterruptVector;
+
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS address;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ //
+ //
+
+ //for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ // if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ // HalpIDTUsage[i].Flags = InternalUsage;
+ // HalpIDTUsage[i].BusRelativeVector = (UCHAR) i;
+ // }
+ //}
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusRelativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusRelativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &address ); // translated address
+
+ TPartialDesc.u.Memory.Start = address;
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Report IO space usage
+ // for HAL/system resources
+ //
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName,
+ PCIBus
+ );
+
+ //RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Now create the registry keys
+ // used to log errors if they
+ // do not already exist
+ //
+
+ HalpCreateLogKeys();
+
+}
+
diff --git a/private/ntos/nthals/halntp/mips/halp.h b/private/ntos/nthals/halntp/mips/halp.h
new file mode 100644
index 000000000..f38afdd20
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/halp.h
@@ -0,0 +1,538 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "falreg.h"
+#include "faldef.h"
+#include "hal.h"
+#include "fxhalp.h"
+#include "xm86.h"
+#include "x86new.h"
+#include "pci.h"
+#include "pcip.h"
+#include "hali.h"
+
+//
+// Temp definitions to thunk into supporting new bus extension format
+//
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpDataBusErrorHandler(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+VOID
+HalpCreateLogKeys(
+ VOID
+ );
+
+VOID
+HalpLogErrorInfo(
+ IN PCWSTR RegistryKey,
+ IN PCWSTR ValueName,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG Size
+ );
+
+VOID
+HalpInterruptDispatch (
+ VOID
+ );
+
+VOID
+HalpInterruptDispatch1 (
+ VOID
+ );
+
+VOID
+HalpIoInterruptDispatch (
+ VOID
+ );
+
+VOID
+HalpMemoryInterrupt (
+ VOID
+ );
+
+VOID
+HalpPciInterrupt (
+ VOID
+ );
+
+VOID
+HalpMapSysCtrlReg (
+ IN ULONG PhysAddrEvenPage,
+ IN ULONG PhysAddrOddPage,
+ IN ULONG VirtAddr
+ );
+
+VOID
+HalpUnMapSysCtrlReg (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+VOID
+HalpConfigureGpcsRegs(
+ IN PVOID ControlBase
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpSweepDcache(
+ IN ULONG ECachePresentFlag
+ );
+
+VOID
+HalpSweepIcache(
+ IN ULONG ECachePresentFlag
+ );
+
+VOID
+HalpClearScreenToBlue(
+ IN ULONG Lines
+ );
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeProcessorBInterrupts (
+ VOID
+ );
+
+VOID
+HalpCheckSystemTimer(
+ VOID
+ );
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslatePCIBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+NTSTATUS
+HalpGetPCIIrqRange (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslatePCIBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpPCIPinToLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern USHORT HalpBuiltinInterruptEnable;
+extern ULONG HalpCurrentTimeIncrement;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KAFFINITY HalpEisaBusAffinity;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halntp/mips/j4cache.s b/private/ntos/nthals/halntp/mips/j4cache.s
new file mode 100644
index 000000000..555a2c8c0
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/j4cache.s
@@ -0,0 +1,1804 @@
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D))
+#define ECACHE_PROTECTION_BITS ((1 << ENTRYLO_V) | (2 << ENTRYLO_C) | (1 << ENTRYLO_D))
+#define ECACHE_CONTROL_PHYSICAL_BASE 0xD0000000
+#define FLUSH_BASE_HACK FLUSH_BASE
+#define PMP_CONTROL_VIRTUAL_BASE 0xFFFFC000
+#define PMP_CONTROL_PHYSICAL_BASE 0xC0000000
+#define GLOBAL_CTRL_ECE 0x00800080
+
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ //
+ // Determine if the ECache is
+ // present (active) which means
+ // it is enabled.
+ //
+ la t0,HalpPmpExternalCachePresent
+ lw t0,0(t0)
+ beq t0,zero, noECacheFlushDcachePage
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ //
+ // Calculate the tlbapping values
+ // and determine which half of the
+ // tlb entry to use for the on-chip
+ // cache.
+ //
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,11f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+11: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,16f // if ne, second level cache present
+ move t4,v0 // set flush block size
+
+16:
+
+ //
+ // Now calculate the tlb mapping values
+ // for the ECache invalidate space and
+ // use the other "unused" tlb entry.
+ //
+ li t6, (ECACHE_CONTROL_PHYSICAL_BASE >> 2)
+ li t7, ((ECACHE_CONTROL_PHYSICAL_BASE >> PAGE_SHIFT) << ENTRYLO_PFN)
+ or t6, t6, t7
+ li t7, (((512*1024)-1) >> PAGE_SHIFT)
+ and t7, a1, t7
+ sll t7, t7, ENTRYLO_PFN
+ or t6, t6, t7
+ li t7, ECACHE_PROTECTION_BITS
+ or t6, t6, t7
+
+ move a3, zero
+ beql t1, zero, 17f
+ move t1, t6
+
+ move t2, t6
+ addiu a3, a3, 1
+ .set at
+ .set reorder
+
+//
+// Now we actually do the mapping
+// by directly writing the TLB
+//
+17:
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,31f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ //
+ // Now we use the mapped
+ // vaddr based on which half
+ // of the tlb entry we used
+ // for the ECache mapping.
+ //
+ move t6, t8
+ li t7, PAGE_SIZE
+ beql a3, zero, 21f
+ subu t6, t6, t7
+
+ addu t6, t6, t7
+
+//
+// Flush the primary data cache and
+// invalidate the external cache.
+//
+21: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ nop
+ sw zero,0(t6) // ECache line invalidate
+ addu t6,t6,t4 // compute next address
+ bne t8,t9,21b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ //
+ // Now we will mark the ECache page
+ // invalid before exiting ...
+ //
+31:
+ .set noreorder
+ .set noat
+
+#if 1
+
+ //mtc0 zero, entrylo0
+ //mtc0 zero, entrylo1
+ //nop
+
+#else
+ beq zero, a3, 22f
+ nop
+
+ mtc0 zero, entrylo1
+ b 23f
+ nop
+
+22:
+ mtc0 zero, entrylo0
+ nop
+
+23:
+
+#endif
+
+ //nop
+ //nop
+ //nop
+ //tlbwi
+ //nop
+ //nop
+ //nop
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// This section of code is only executed
+// if the processor is not an R4600/R4700 or
+// it is an R4600/R4700 but there is no ECache.
+//
+noECacheFlushDcachePage:
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ //
+ // Determine if the ECache is
+ // present (active) which means
+ // it is enabled.
+ //
+ la t0,HalpPmpExternalCachePresent
+ lw t0,0(t0)
+ beq t0,zero, noECachePurgeDcachePage
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ //
+ // Calculate the tlb mapping values
+ // and determine which half of the
+ // tlb entry to use for the on-chip
+ // cache.
+ //
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,11f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+11: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,16f // if ne, second level cache present
+ move t4,v0 // set purge block size
+
+ //
+ // Now calculate the tlb mapping values
+ // for the ECache invalidate space and
+ // use the other "unused" tlb entry.
+ //
+16:
+ li t6, (ECACHE_CONTROL_PHYSICAL_BASE >> 2)
+ li t7, ((ECACHE_CONTROL_PHYSICAL_BASE >> PAGE_SHIFT) << ENTRYLO_PFN)
+ or t6, t6, t7
+ li t7, (((512*1024)-1) >> PAGE_SHIFT)
+ and t7, a1, t7
+ sll t7, t7, ENTRYLO_PFN
+ or t6, t6, t7
+ li t7, ECACHE_PROTECTION_BITS
+ or t6, t6, t7
+
+ move a3, zero
+ beql t1, zero, 17f
+ move t1, t6
+
+ move t2, t6
+ addiu a3, a3, 1
+ .set at
+ .set reorder
+
+//
+// Now we actually do the mapping
+// by directly writing the TLB
+//
+17:
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,31f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ //
+ // Now we use the mapped
+ // vaddr based on which half
+ // of the tlb entry we used
+ // for the ECache mapping.
+ //
+ move t6, t8
+ li t7, PAGE_SIZE
+ beql a3, zero, 21f
+ subu t6, t6, t7
+
+ addu t6, t6, t7
+
+//
+// Purge the primary data cache and
+// invalidate the external cache.
+//
+21: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ nop
+ sw zero,0(t6) // ECache line invalidate
+ addu t6,t6,t4 // compute next address
+ bne t8,t9,21b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ //
+ // Now we will mark the ECache page
+ // invalid before exiting ...
+ //
+31:
+ .set noreorder
+ .set noat
+
+#if 1
+
+ //mtc0 zero, entrylo0
+ //mtc0 zero, entrylo1
+ //nop
+
+#else
+
+ beq zero, a3, 22f
+ nop
+
+ mtc0 zero, entrylo1
+ b 23f
+ nop
+
+22:
+ mtc0 zero, entrylo0
+ nop
+
+23:
+
+#endif
+
+ //nop
+ //nop
+ //nop
+ //tlbwi
+ //nop
+ //nop
+ //nop
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+
+//
+// This section of code is only executed
+// if the processor is not an R4600/R4700 or
+// it is an R4600/R4700 but there is no ECache.
+//
+noECachePurgeDcachePage:
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ //
+ // Determine if the ECache is
+ // present (active) which means
+ // it is enabled.
+ //
+ la t0,HalpPmpExternalCachePresent
+ lw t0,0(t0)
+ beq t0,zero, noECachePurgeIcachePage
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ //
+ // Calculate the tlb mapping values
+ // and determine which half of the
+ // tlb entry to use for the on-chip
+ // cache.
+ //
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,11f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+11: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,16f // if ne, second level cache present
+ move t4,v0 // set purge block size
+
+ //
+ // Now calculate the tlb mapping values
+ // for the ECache invalidate space and
+ // use the other "unused" tlb entry.
+ //
+16:
+
+ li t6, (ECACHE_CONTROL_PHYSICAL_BASE >> 2)
+ li t7, ((ECACHE_CONTROL_PHYSICAL_BASE >> PAGE_SHIFT) << ENTRYLO_PFN)
+ or t6, t6, t7
+ li t7, (((512*1024)-1) >> PAGE_SHIFT)
+ and t7, a1, t7
+ sll t7, t7, ENTRYLO_PFN
+ or t6, t6, t7
+ li t7, ECACHE_PROTECTION_BITS
+ or t6, t6, t7
+
+ move a3, zero
+ beql t1, zero, 17f
+ move t1, t6
+
+ move t2, t6
+ addiu a3, a3, 1
+ .set at
+ .set reorder
+
+//
+// Now we actually do the mapping
+// by directly writing the TLB
+//
+17:
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,31f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ //
+ // Now we use the mapped
+ // vaddr based on which half
+ // of the tlb entry we used
+ // for the ECache mapping.
+ //
+ move t6, t8
+ li t7, PAGE_SIZE
+ beql a3, zero, 21f
+ subu t6, t6, t7
+
+ addu t6, t6, t7
+
+//
+// Purge the primary instruction cache and
+// invalidate the external cache.
+//
+21: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ nop
+ sw zero,0(t6) // ECache line invalidate
+ addu t6,t6,t4 // compute next address
+ bne t8,t9,21b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ //
+ // Now we will mark the ECache page
+ // invalid before exiting ...
+ //
+31:
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// This section of code is only executed
+// if the processor is not an R4600/R4700 or
+// it is an R4600/R4700 but there is no ECache.
+//
+noECachePurgeIcachePage:
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// a0 contains the virtual address of the ECache invalidate
+// register (if enabled); otherwise, it is NULL.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ //
+ // Determine if ECache is active
+ //
+ .set noreorder
+ .set noat
+ beq a0, zero, noECacheSweepDcache
+ nop
+
+ //
+ // Get vaddr of ECache invalidate register
+ //
+ lw t2, HalpExtPmpControl
+ .set at
+ .set reorder
+
+//////////////////////////////////////////////////////////////////////////
+//
+// This section is executed only
+// if the sweep routine was called
+// via HalFlushIoBuffer()
+//
+//////////////////////////////////////////////////////////////////////////
+ECacheSweepDcache:
+
+ DISABLE_INTERRUPTS(t5)
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ //
+ // Determine if this is an R4600/R4700
+ // and if so then we need to deal
+ // with the two-way set associativity.
+ //
+ .set noreorder
+ .set noat
+ mfc0 t3, prid
+ nop
+ nop
+ nop
+ li t0, 2
+ srl t3, t3, 12
+ bne t3, t0, 60f
+ nop
+ .set at
+ .set reorder
+
+//
+// Sweep the primary data cache (R4600/R4700 only).
+//
+
+ .set noreorder
+ .set noat
+50: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+ bne a0,a1,50b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ //
+ // Invalidate the ECache
+ //
+ lb t1, 0(t2) // External PMP Control
+ ori t1, t1, 1
+ sb t1, 0(t2)
+ andi t1, t1, 0xFE
+ sb t1, 0(t2)
+ ori t1, t1, 1
+ sb t1, 0(t2)
+ lb zero, 0(t2) // External cache INVALIDATED
+
+ ENABLE_INTERRUPTS(t5)
+
+ j ra
+
+//
+// Sweep the primary data cache (except R4600/R4700).
+//
+ .set noreorder
+ .set noat
+60: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,60b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ //
+ // Invalidate the ECache
+ //
+ lb t1, 0(t2) // External PMP Control
+ ori t1, t1, 1
+ sb t1, 0(t2)
+ andi t1, t1, 0xFE
+ sb t1, 0(t2)
+ ori t1, t1, 1
+ sb t1, 0(t2)
+ lb zero, 0(t2) // External cache INVALIDATED
+
+ ENABLE_INTERRUPTS(t5)
+
+ j ra
+
+//////////////////////////////////////////////////////////////
+//
+// This section of code is executed
+// there is no ECache active ...
+//
+//////////////////////////////////////////////////////////////
+noECacheSweepDcache:
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ //
+ // Determine if this is an R4600/R4700
+ // and if so then we need to deal
+ // with the two-way set associativity.
+ //
+ .set noreorder
+ .set noat
+ mfc0 t3, prid
+ nop
+ nop
+ nop
+ li t0, 2
+ srl t3, t3, 12
+ bne t3, t0, 10f
+ nop
+ .set at
+ .set reorder
+
+//
+// Sweep the primary data cache (R4600/R4700 only).
+//
+
+ DISABLE_INTERRUPTS(t5)
+
+ .set noreorder
+ .set noat
+50: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+ bne a0,a1,50b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5)
+
+ j ra // return
+
+//
+// Sweep the primary data cache (except R4600/R4700).
+//
+
+10:
+ DISABLE_INTERRUPTS(t5)
+
+ .set noreorder
+ .set noat
+11: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,11b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,40f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache (except R4600/R4700).
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+40:
+ ENABLE_INTERRUPTS(t5)
+
+ j ra // return
+
+ .end HalpSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+ //
+ // Determine if this is an R4600/R4700
+ // and if so then we need to deal
+ // with the two-way set associativity.
+ //
+ .set noreorder
+ .set noat
+ mfc0 t1, prid
+ nop
+ nop
+ nop
+ li t2, 2
+ srl t1, t1, 12
+ bne t1, t2, 20f
+ nop
+ .set at
+ .set reorder
+
+//
+// Sweep the primary data cache (only R4600/R4700).
+//
+
+ DISABLE_INTERRUPTS(t5)
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ nop
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // do other set on Orion
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5)
+
+ j ra
+
+//
+// Sweep the primary data cache (except R4600/R4700).
+//
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// a0 contains the virtual address of the ECache invalidate
+// register (if enabled); otherwise, it is NULL.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ //
+ // Determine if ECache is active
+ //
+ .set noreorder
+ .set noat
+ beq a0, zero, noECacheSweepIcache
+ nop
+
+ //
+ // Get vaddr of ECache invalidate register
+ //
+ lw t2, HalpExtPmpControl
+ .set at
+ .set reorder
+
+//
+// Invalidate the External Cache
+//
+ECacheSweepIcache:
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lb t1, 4(t2)
+ ori t1, t1, 1
+ sb t1, 4(t2)
+ andi t1, t1, 0xFE
+ sb t1, 4(t2)
+ ori t1, t1, 1
+ sb t1, 4(t2)
+ lb zero, 4(t2) // ECache INVALIDATED
+
+
+ lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ //
+ // Determine if this is an R4600/R4700
+ // and if so then we need to deal
+ // with the two-way set associativity.
+ //
+ .set noreorder
+ .set noat
+ mfc0 t3, prid
+ nop
+ nop
+ nop
+ li t2, 2
+ srl t3, t3, 12
+ bne t3, t2, 60f
+ nop
+ .set at
+ .set reorder
+
+//
+// Sweep the primary instruction cache (R4600/R4700 only).
+//
+
+ .set noreorder
+ .set noat
+50: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+ bne a0,a1,50b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra
+
+//
+// Sweep the primary instruction cache (except R4600/R4700).
+//
+ .set noreorder
+ .set noat
+60: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,60b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5)
+
+ j ra
+
+//
+// No ECache section
+//
+noECacheSweepIcache:
+
+ //
+ // Determine if this is an R4600/R4700
+ // and if so then we need to deal
+ // with the two-way set associativity.
+ //
+ .set noreorder
+ .set noat
+ mfc0 t3, prid
+ nop
+ nop
+ nop
+ li t2, 2
+ srl t3, t3, 12
+ bne t3, t2, 60f
+ nop
+ .set at
+ .set reorder
+
+//
+// Sweep the primary instruction cache (R4600/R4700 only).
+//
+ lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+50: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+ bne a0,a1,50b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra
+
+//
+// Sweep the secondary instruction cache (except R4600/R4700).
+//
+60:
+ DISABLE_INTERRUPTS(t5)
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+//
+// Sweep the primary instruction cache (except R4600/R4700).
+//
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ .set noreorder
+ .set noat
+40: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,40b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5)
+
+ j ra // return
+
+ .end HalpSweepIcache
+
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+ //
+ // Determine if this is an R4600/R4700
+ // and if so then we need to deal
+ // with the two-way set associativity.
+ //
+ .set noreorder
+ .set noat
+ mfc0 t3, prid
+ nop
+ nop
+ nop
+ li t2, 2
+ srl t3, t3, 12
+ bne t3, t2, 20f
+ nop
+ .set at
+ .set reorder
+
+//
+// Sweep the primary instruction cache (only R4600/R4700)
+//
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ nop
+ cache INDEX_INVALIDATE_I,8192(a0) // do other set on Orion
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra
+
+//
+// Sweep the primary instruction cache (except R4600/R4700)
+//
+ .set noreorder
+ .set noat
+20: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,30b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halntp/mips/j4flshbf.s b/private/ntos/nthals/halntp/mips/j4flshbf.s
new file mode 100644
index 000000000..606cf3fe5
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/j4flshbf.s
@@ -0,0 +1,51 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// j4flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halntp/mips/j4flshio.c b/private/ntos/nthals/halntp/mips/j4flshio.c
new file mode 100644
index 000000000..dad2ed1c3
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/j4flshio.c
@@ -0,0 +1,610 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+
+--*/
+
+#include "halp.h"
+
+
+/*++
+
+Routine Description:
+
+ This routine is a wrapper for the HalpSweepIcache() routine
+ implemented in j4cache.s
+
+ It was necessary to implement this wrapper in order to allow
+ us to get a TLB mapping for the ECache invalidate register without
+ having to steal (hack) an R4x00 tlb entry from the kernel without
+ it knowing.
+
+ The wrapper is somewhat complicated in that depending on which
+ point in the initialization stages (Phase 0 or Phase 1) the sweep
+ routine is called, the tlb mapping must be gotten either through
+ an a call to KeFillFixedEntryTb() which uses a "wired" entry or
+ through MmMapIoSpace() which is the normal method for mapping
+ registers, buffers, etc.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalSweepDcache(
+ VOID
+ )
+
+{
+
+ ULONG Temp;
+ PVOID SavedAddress, BaseAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Determine who is the caller:
+ //
+ // - the HAL
+ // - the kernel
+ //
+
+ if (HalpPmpHalFlushIoBuffer) {
+
+ //
+ // There are 3 cases:
+ //
+ // case 1: before HalpMapIoSpace() is called
+ //
+ // case 2: after HalpMapIoSpace() is called
+ //
+ // case 3: before HalpMapFixedTbEntries() is called
+ //
+
+ if ((HalpExtPmpControl == (PVOID)NULL) && (HalpPmpExternalCachePresent == 1)) {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ BaseAddress = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+ HalpExtPmpControl = (PVOID)(((ULONG)BaseAddress) + 0x4);
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepDcache(1);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ MmUnmapIoSpace(BaseAddress, PAGE_SIZE);
+ HalpExtPmpControl = (PVOID)NULL;
+
+ } else if ((HalpPmpExternalCachePresent == 0) || (HalpPmpExternalCachePresent == 1)) {
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepDcache(HalpPmpExternalCachePresent);
+
+ } else {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ SavedAddress = HalpExtPmpControl;
+
+ HalpMapSysCtrlReg(GLOBAL_STATUS_PHYSICAL_BASE, PCI_CONFIG_SEL_PHYSICAL_BASE, 0xFFFF6000);
+
+ HalpExtPmpControl = (PVOID) (0xFFFF6000 + PAGE_SIZE + 0x4);
+
+ Temp = READ_REGISTER_ULONG(0xFFFF6000 + REG_OFFSET(PMP(GLOBAL_CTRL_PHYSICAL_BASE)));
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepDcache(Temp & GLOBAL_CTRL_ECE ? 1 : 0);
+
+ //
+ // Unap ECache invalidate register
+ //
+
+ HalpUnMapSysCtrlReg();
+
+ HalpExtPmpControl = SavedAddress;
+
+ }
+
+ } else {
+
+ //
+ // There are 3 cases:
+ //
+ // case 1: before HalpMapIoSpace() is called
+ //
+ // case 2: after HalpMapIoSpace() is called
+ //
+ // case 3: before HalpMapFixedTbEntries() is called
+ //
+
+ if ((HalpExtPmpControl == (PVOID)NULL) && (HalpPmpExternalCachePresent == 1)) {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ BaseAddress = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+ HalpExtPmpControl = (PVOID)(((ULONG)BaseAddress) + 0x4);
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepDcache(1);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ MmUnmapIoSpace(BaseAddress, PAGE_SIZE);
+ HalpExtPmpControl = (PVOID)NULL;
+
+ } else if ((HalpPmpExternalCachePresent == 1) || (HalpPmpExternalCachePresent == 0)) {
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepDcache(HalpPmpExternalCachePresent);
+
+ } else {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ SavedAddress = HalpExtPmpControl;
+
+ HalpMapSysCtrlReg(GLOBAL_STATUS_PHYSICAL_BASE, PCI_CONFIG_SEL_PHYSICAL_BASE, 0xFFFF6000);
+
+ HalpExtPmpControl = (PVOID) (0xFFFF6000 + PAGE_SIZE + 0x4);
+
+ Temp = READ_REGISTER_ULONG(0xFFFF6000 + REG_OFFSET(PMP(GLOBAL_CTRL_PHYSICAL_BASE)));
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepDcache(Temp & GLOBAL_CTRL_ECE ? 1 : 0);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ HalpUnMapSysCtrlReg();
+
+ HalpExtPmpControl = SavedAddress;
+
+ }
+
+ }
+
+}
+
+/*++
+
+Routine Description:
+
+ This routine is a wrapper for the HalpSweepIcache() routine
+ implemented in j4cache.s
+
+ It was necessary to implement this wrapper in order to allow
+ us to get a TLB mapping for the ECache invalidate register without
+ having to steal (hack) an R4x00 tlb entry from the kernel without
+ it knowing.
+
+ The wrapper is somewhat complicated in that depending on which
+ point in the initialization stages (Phase 0 or Phase 1) the sweep
+ routine is called, the tlb mapping must be gotten either through
+ an a call to KeFillFixedEntryTb() which uses a "wired" entry or
+ through MmMapIoSpace() which is the normal method for mapping
+ registers, buffers, etc.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalSweepIcache(
+ VOID
+ )
+
+{
+
+ ULONG Temp;
+ PVOID SavedAddress, BaseAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Determine who is the caller:
+ //
+ // - the HAL
+ // - the kernel
+ //
+
+ if (HalpPmpHalFlushIoBuffer) {
+
+ //
+ // There are 3 cases:
+ //
+ // case 1: before HalpMapIoSpace() is called
+ //
+ // case 2: after HalpMapIoSpace() is called
+ //
+ // case 3: before HalpMapFixedTbEntries() is called
+ //
+
+ if ((HalpExtPmpControl == (PVOID)NULL) && (HalpPmpExternalCachePresent == 1)) {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ BaseAddress = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+ HalpExtPmpControl = (PVOID)(((ULONG)BaseAddress) + 0x4);
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepIcache(1);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ MmUnmapIoSpace(BaseAddress, PAGE_SIZE);
+ HalpExtPmpControl = (PVOID)NULL;
+
+ } else if ((HalpPmpExternalCachePresent == 0) || (HalpPmpExternalCachePresent == 1)) {
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepIcache(HalpPmpExternalCachePresent);
+
+ } else {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ SavedAddress = HalpExtPmpControl;
+
+ HalpMapSysCtrlReg(GLOBAL_STATUS_PHYSICAL_BASE, PCI_CONFIG_SEL_PHYSICAL_BASE, 0xFFFF6000);
+
+ HalpExtPmpControl = (PVOID) (0xFFFF6000 + PAGE_SIZE + 0x4);
+
+ Temp = READ_REGISTER_ULONG(0xFFFF6000 + REG_OFFSET(PMP(GLOBAL_CTRL_PHYSICAL_BASE)));
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepIcache(Temp & GLOBAL_CTRL_ECE ? 1 : 0);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ HalpUnMapSysCtrlReg();
+
+ HalpExtPmpControl = SavedAddress;
+
+ }
+
+ } else {
+
+ //
+ // There are 3 cases:
+ //
+ // case 1: before HalpMapIoSpace() is called
+ //
+ // case 2: after HalpMapIoSpace() is called
+ //
+ // case 3: before HalpMapFixedTbEntries() is called
+ //
+
+ if ((HalpExtPmpControl == (PVOID)NULL) && (HalpPmpExternalCachePresent == 1)) {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ BaseAddress = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+ HalpExtPmpControl = (PVOID)(((ULONG)BaseAddress) + 0x4);
+
+ //
+ // Sweep Icache and ECache
+ //
+
+ HalpSweepIcache(1);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ MmUnmapIoSpace(BaseAddress, PAGE_SIZE);
+ HalpExtPmpControl = (PVOID)NULL;
+
+ } else if ((HalpPmpExternalCachePresent == 1) || (HalpPmpExternalCachePresent == 0)) {
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepIcache(HalpPmpExternalCachePresent);
+
+ } else {
+
+ //
+ // Map ECache invalidate register
+ //
+
+ SavedAddress = HalpExtPmpControl;
+
+ HalpMapSysCtrlReg(GLOBAL_STATUS_PHYSICAL_BASE, PCI_CONFIG_SEL_PHYSICAL_BASE, 0xFFFF6000);
+
+ HalpExtPmpControl = (PVOID) (0xFFFF6000 + PAGE_SIZE + 0x4);
+
+ Temp = READ_REGISTER_ULONG(0xFFFF6000 + REG_OFFSET(PMP(GLOBAL_CTRL_PHYSICAL_BASE)));
+
+ //
+ // Sweep caches
+ //
+
+ HalpSweepIcache(Temp & GLOBAL_CTRL_ECE ? 1 : 0);
+
+ //
+ // Unmap ECache invalidate register
+ //
+
+ HalpUnMapSysCtrlReg();
+
+ HalpExtPmpControl = SavedAddress;
+
+ }
+
+ }
+
+}
+
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+
+ HalpPmpHalFlushIoBuffer = 1;
+ HalSweepDcache();
+ HalpPmpHalFlushIoBuffer = 0;
+
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+
+ HalpPmpHalFlushIoBuffer = 1;
+ HalSweepIcache();
+ HalpPmpHalFlushIoBuffer = 0;
+
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halntp/mips/j4prof.c b/private/ntos/nthals/halntp/mips/j4prof.c
new file mode 100644
index 000000000..b7ef1e25f
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/j4prof.c
@@ -0,0 +1,316 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+
+ } while (*Number !=0);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart = 0;
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Provides the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halntp/mips/jxbeep.c b/private/ntos/nthals/halntp/mips/jxbeep.c
new file mode 100644
index 000000000..8ac9a0276
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxbeep.c
@@ -0,0 +1,143 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+
+ if ( HalpPmpRevision >= 3 ) {
+ //
+ // For PMP V3, we are NOT using speaker timer in ESC for speaker tone.
+ // Need to add code to generate via sound card.
+ //
+ Result = TRUE;
+ return Result;
+ }
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+
+ return Result;
+}
diff --git a/private/ntos/nthals/halntp/mips/jxebsup.c b/private/ntos/nthals/halntp/mips/jxebsup.c
new file mode 100644
index 000000000..6a151403a
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxebsup.c
@@ -0,0 +1,1387 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+
+//
+// external (defined in fxpcibus.c)
+//
+
+extern UCHAR HalpPCIPinToLineTable[];
+extern UCHAR HalpPIRQTable[];
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Declare the interupt structure and spinlock for the intermediate EISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpEisaInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask registers and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+//
+// Define EISA bus interrupt affinity.
+//
+
+#if defined(PROCESSOR_AFFINITY_PCR)
+
+KAFFINITY HalpEisaBusAffinity;
+
+#endif // PROCESSOR_AFFINITY_PCR
+
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa && DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ //
+ // We want to know the interface type
+ //
+
+ adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+/*++
+
+Routine Description:
+
+ This function initializes IO interrupts on a Falcon system.
+
+ This function is only called during phase 0 initialization.
+
+Arguments:
+
+ pointer to eisa control structure.
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalpInitializeEisaInterrupts (
+ IN PEISA_CONTROL controlBase
+ )
+
+{
+ UCHAR DataByte;
+ ULONG i;
+
+ //
+ // Set EISA bus interrupt affinity.
+ //
+
+#if defined(PROCESSOR_AFFINITY_PCR)
+ HalpEisaBusAffinity = PCR->SetMember;
+#endif // PROCESSOR_AFFINITY_PCR)
+
+ //
+ // Let's read the PIRQ* registers to obtain the dynamic
+ // mapping for PCI interrupts as set by the firmware
+ // in the 82374/82375. We will save the PIRQ mappings
+ // in the HalpPCIPinToLineTable[] which is used during
+ // PCI bus probing and device configuration.
+ //
+ // Warning: Do not change the section of code related
+ // to PIRQ mappings unless you thoroughly
+ // understand the HalpPCIPinToLineTable[] and
+ // the HalpPciConfigSelectDecodeTable[]. These
+ // tables correspond directly to the PciConfigSelect
+ // register inside the PMP asic and the PIRQ
+ // lines which deliver the interrupts for each
+ // PCI device.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_ID);
+ WRITE_REGISTER_UCHAR(&controlBase->Reserved1[1], ESC_CONFIG_IDEN_BYTE);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ0);
+ HalpPCIPinToLineTable[PCI_OBENET_DEVICE_NUMBER] = HalpPIRQTable[0] =
+ READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ1);
+ HalpPCIPinToLineTable[PCI_OBSCSI_DEVICE_NUMBER] = HalpPIRQTable[1] =
+ READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ3);
+ HalpPCIPinToLineTable[PCI_SLOT0_DEVICE_NUMBER] = HalpPIRQTable[2] =
+ READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ2);
+ HalpPCIPinToLineTable[PCI_SLOT1_DEVICE_NUMBER] = HalpPIRQTable[3] =
+ READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
+
+ //
+ // First lets mask off all interrupts to separate ourselves
+ // from the firmware to avoid spurious interrupts
+ //
+ HalpEisaInterrupt1Mask = (UCHAR)0xFF;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, HalpEisaInterrupt1Mask);
+
+ HalpEisaInterrupt2Mask = (UCHAR)0xFF;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, HalpEisaInterrupt2Mask);
+
+ //
+ // Set everything to edge before beginning the initialization
+ // sequence (per the 82374 errata)
+ //
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1EdgeLevel, 0);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2EdgeLevel, 0);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort0, DataByte);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort0, DataByte);
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, DataByte);
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, DataByte);
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, DataByte);
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, DataByte);
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, DataByte);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, DataByte);
+
+ //
+ // Enable the slave interrupt which connects the two cascaded
+ // interrupt controllers together.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, HalpEisaInterrupt1Mask);
+
+ HalpEisaInterrupt2Mask = (UCHAR)0xFF;
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, HalpEisaInterrupt2Mask);
+
+ //
+ // Program the level versus edge sensitivity of the interrupts.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1EdgeLevel, HalpEisaInterrupt1Level);
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2EdgeLevel, HalpEisaInterrupt2Level);
+
+ //
+ // Clear any specific interrupts
+ // left hanging around by the
+ // boot
+
+ for (i = 0; i < 8; i++) {
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort0, 0x20);
+
+ }
+
+ for (i = 0; i < 8; i++) {
+
+ WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort0, 0x20);
+
+ }
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Dma1BasePort.AllMask, 0x0F);
+ WRITE_REGISTER_UCHAR(&controlBase->Dma2BasePort.AllMask, 0x0E);
+
+ //
+ // We're done
+ //
+
+ return;
+
+}
+
+/*++
+
+Routine Description:
+
+ This function dispatches IO interrupts on a Falcon system.
+
+ It calls the device-specific interrupt handler (ISR).
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalpIoInterruptDispatch(
+ VOID
+ )
+
+{
+
+ UCHAR interruptVector;
+ UCHAR inService;
+ PKPRCB Prcb;
+ BOOLEAN Status;
+
+ //
+ // Read IoIntAck register to determine the interrupt source
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(HalpPmpIoIntAck);
+
+ //
+ // Determine if this is a bogus interrupt from the 8259
+ // by checking the corresponding InService bit. If it is
+ // real then we will deal with it normally; otherwise,
+ // we will just dismiss it straight away.
+ //
+
+ if (interruptVector == 0x07) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0, 0x0B);
+
+ inService = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ if (!(inService & 0x80)) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0, NONSPECIFIC_END_OF_INTERRUPT);
+
+ }
+
+ }
+
+ //
+ // Get the PRCB.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ Status = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[EISA_VECTORS + interruptVector])(
+ PCR->InterruptRoutine[EISA_VECTORS + interruptVector]
+ );
+
+ //
+ // Dismiss the interrupt in the 8259 interrupt controller.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+}
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ KIRQL Irql;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT(Offset >= 0x100000);
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ //
+ // Release adapter spin lock
+ //
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Devices which do not use auto-initialize
+ // CommonBuffer DMA can use the scatter/gather
+ // capabilities of the 82374 which we manage
+ // through map registers similar to how previous
+ // MIPS machines managed the IO TLB.
+ //
+
+ if (!AdapterObject->AutoInitialize) {
+
+ //
+ // 1. Setup Scatter/Gather Descriptor Table Pointer
+ // register according to which channel is being used.
+ // 2. Issue Scatter/Gather Start command.
+ //
+
+ switch (AdapterObject->ChannelNumber) {
+
+ case 0:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[16], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[0], SCATTER_GATHER_COMMAND);
+ break;
+
+ case 1:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[20], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[1], SCATTER_GATHER_COMMAND);
+ break;
+ case 2:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[24], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[2], SCATTER_GATHER_COMMAND);
+ break;
+
+ case 3:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[28], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[3], SCATTER_GATHER_COMMAND);
+ break;
+
+ }
+
+ } else {
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+ }
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Devices which do not use auto-initialize
+ // CommonBuffer DMA can use the scatter/gather
+ // capabilities of the 82374 which we manage
+ // through map registers.
+ //
+
+ if (!AdapterObject->AutoInitialize) {
+
+ //
+ // 1. Setup Scatter/Gather Descriptor Table Pointer
+ // register according to which channel is being used.
+ // 2. Issue Scatter/Gather Start command.
+ //
+
+ switch (AdapterObject->ChannelNumber) {
+
+ case 1:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[36], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[5], SCATTER_GATHER_COMMAND);
+ break;
+
+ case 2:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[40], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[6], SCATTER_GATHER_COMMAND);
+ break;
+
+ case 3:
+ WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[44], Offset);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[7], SCATTER_GATHER_COMMAND);
+ break;
+
+ }
+
+ } else {
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+ }
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+ //
+ // Release adapter spin lock
+ //
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+ //
+ // According to the 82374, the following interrupts
+ // MUST be edge-triggered: 0, 1, 2, 8, 13.
+ //
+
+ if ( (InterruptMode == LevelSensitive) && (Vector != 0) && (Vector != 0x5) ) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+ //
+ // According to the 82374, the following interrupts
+ // MUST be edge-triggered: 0, 1, 2, 8, 13.
+ //
+ // Warning: due to a firmware limitation (???) we must
+ // force the floppy interrupt (irq6) to be edge
+ // even though it will request level. There is no
+ // mechanism for communicating to a driver that
+ // its interrupt mode is different than requested.
+ // Hope this doesn't cause problems ...
+ //
+
+ if ( (InterruptMode == LevelSensitive) && (Vector >= 3) && (Vector != 6) ) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+VOID
+HalpConfigureGpcsRegs(
+ IN PVOID ControlBase
+ )
+
+{
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_ID);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], ESC_CONFIG_IDEN_BYTE);
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSHA0);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(PCI_CONFIG_SELECT_OFFSET >> 8));
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSLA0);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(PCI_CONFIG_SELECT_OFFSET & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSHA1);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET >> 8));
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSLA1);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSHA2);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET2 >> 8));
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSLA2);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET2 & 0xFF));
+
+}
diff --git a/private/ntos/nthals/halntp/mips/jxenvirv.c b/private/ntos/nthals/halntp/mips/jxenvirv.c
new file mode 100644
index 000000000..01822061a
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxenvirv.c
@@ -0,0 +1,679 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+#include "falnvram.h"
+#include "string.h"
+
+
+//
+// Define base address at which to map NVRAM.
+//
+
+PVOID HalpFlashRamBase;
+
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+//
+// prototypes
+//
+
+VOID
+WRITE_NVRAM_UCHAR (
+ ULONG Address,
+ UCHAR Data
+ );
+
+UCHAR
+READ_NVRAM_UCHAR (
+ ULONG Address
+ );
+
+VOID
+WriteMirrorNvramToFlash(
+ VOID
+ );
+
+
+
+VOID
+HalpMapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into I/O space.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Construct physical address
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(NVRAM_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(NVRAM_PHYSICAL_BASE);
+
+ //
+ // Map Flash RAM (as NVRAM)
+ //
+
+ HalpFlashRamBase = MmMapIoSpace(physicalAddress, SECTOR_SIZE_AM29F040, FALSE);
+ return;
+}
+
+VOID
+HalpUnmapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from I/O space.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ MmUnmapIoSpace(HalpFlashRamBase, SECTOR_SIZE_AM29F040);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)HalpFlashRamBase;
+
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ Checksum1 = ~Checksum1;
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)HalpFlashRamBase;
+
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_NVRAM_UCHAR( (ULONG) &Environment[Index]);
+ }
+
+ Checksum = ~Checksum;
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_NVRAM_UCHAR( (ULONG) &NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_NVRAM_UCHAR( (ULONG) &NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_NVRAM_UCHAR( (ULONG) &NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_NVRAM_UCHAR( (ULONG) &NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ WriteMirrorNvramToFlash();
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)HalpFlashRamBase)->Environment[0];
+
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ HalpMapNvram();
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)HalpFlashRamBase)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram();
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ HalpMapNvram();
+ Environment = &((PNV_CONFIGURATION)HalpFlashRamBase)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_NVRAM_UCHAR( (ULONG) &Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram();
+ return Status;
+}
diff --git a/private/ntos/nthals/halntp/mips/jxmapio.c b/private/ntos/nthals/halntp/mips/jxmapio.c
new file mode 100644
index 000000000..cb5f3b942
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxmapio.c
@@ -0,0 +1,264 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase;
+PVOID HalpRealTimeClockBase;
+
+PVOID HalpPmpIoIntAck;
+PVOID HalpPmpIntCause;
+PVOID HalpPmpIntStatus;
+PVOID HalpPmpIntStatusProcB;
+PVOID HalpPmpIntCtrl;
+PVOID HalpPmpIntCtrlProcB;
+PVOID HalpPmpIntSetCtrl;
+PVOID HalpPmpIntSetCtrlProcB;
+PVOID HalpPmpTimerIntAck;
+PVOID HalpPmpTimerIntAckProcB;
+PVOID HalpPmpIntClrCtrl;
+PVOID HalpPmpIntClrCtrlProcB;
+PVOID HalpPmpMemStatus;
+PVOID HalpPmpMemCtrl;
+PVOID HalpPmpMemErrAck;
+PVOID HalpPmpMemErrAddr;
+PVOID HalpPmpPciStatus;
+PVOID HalpPmpPciCtrl;
+PVOID HalpPmpPciErrAck;
+PVOID HalpPmpPciErrAddr;
+PVOID HalpPmpIpIntAck;
+PVOID HalpPmpIpIntAckProcB;
+PVOID HalpPmpIpIntGen;
+PVOID HalpPmpPciConfigSpace;
+PVOID HalpPmpPciConfigAddr;
+PVOID HalpPmpPciConfigSelect;
+PVOID HalpExtPmpControl = (PVOID)NULL;
+PVOID HalpPmpMemDiag;
+PVOID HalpPmpPciRetry;
+
+ULONG HalpPmpProcessorBPresent = 0;
+ULONG HalpPmpExternalCachePresent = (ULONG)0xFFFFFFFF;
+ULONG HalpPmpHalFlushIoBuffer = 0;
+ULONG HalpEcacheMappingFlag = 0;
+ULONG HalpPmpRevision = 0;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ PVOID VirtualAddressBase;
+
+ //
+ // On FALCON, the RealTimeClock is implemented using
+ // the National Semiconductor PC87323VF (SuperIO Sidewinder)
+ // chip which is connected to the Intel 82374 ESC at IO
+ // address 0x70 (index) and 0x71 (data). This is different
+ // from the DUO and STRIKER designs which use a similar part
+ // that is decoded by their respective asic chip sets into a
+ // different address space outside of EISA control. For FALCON
+ // the RTC is accessible through the EISA control space mapping
+ // so we avoid having to call MmMapIoSpace a second time.
+ //
+ // In addition, the PciConfigSelect register is also decoded
+ // by the 82374 through EISA control space.
+ //
+
+ //
+ // Unmap Eisa Control Space which uses
+ // one of the wired TLB entries
+ //
+
+ HalpUnMapSysCtrlReg();
+
+ //
+ // Map EISA control space including the RealTimeClock
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(EISA_CONTROL_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(EISA_CONTROL_PHYSICAL_BASE);
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress, PAGE_SIZE * 16, FALSE);
+
+ if (HalpEisaControlBase == (PVOID)NULL)
+ return FALSE;
+
+ HalpRealTimeClockBase = (PVOID) &((PEISA_CONTROL)HalpEisaControlBase)->Reserved16[0];
+
+ //
+ // Map 82374 bucky registers including the PciConfigSelect (IDSEL) and ExtPmpControl registers
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ physicalAddress.LowPart = IO_ADDRESS_LO(PCI_CONFIG_SEL_PHYSICAL_BASE);
+ HalpPmpPciConfigSelect = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (HalpPmpPciConfigSelect == (PVOID)NULL)
+ return FALSE;
+
+ HalpExtPmpControl = (PVOID)(((ULONG)HalpPmpPciConfigSelect) + 0x4);
+
+ //
+ // Map PCI Configuration Space
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PMP(PCI_CONFIG_PHYSICAL_BASE));
+ physicalAddress.LowPart = IO_ADDRESS_LO(PMP(PCI_CONFIG_PHYSICAL_BASE));
+ HalpPmpPciConfigSpace = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (HalpPmpPciConfigSpace == (PVOID)NULL)
+ return FALSE;
+
+ //
+ // The following series of mappings are due to how the
+ // system control space registers are organized inside the
+ // PMP chip. The first version of the chip had each register
+ // residing in a separate page due to Wide/Narrow addressing
+ // requirements. The second version of the chip was able to
+ // cluster 4 registers per page to improve the mapping requirements
+ // of the HAL.
+ //
+
+ //
+ // IntCtrl
+ // IpIntGen
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PMP(INT_STATUS_PHYSICAL_BASE));
+ physicalAddress.LowPart = IO_ADDRESS_LO(PMP(INT_STATUS_PHYSICAL_BASE));
+ VirtualAddressBase = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (VirtualAddressBase == (PVOID)NULL)
+ return FALSE;
+
+ HalpPmpIntStatus = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(INT_STATUS_PHYSICAL_BASE)));
+ HalpPmpIntStatusProcB = (PVOID)HalpPmpIntStatus;
+ HalpPmpIntCtrl = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(INT_CONTROL_PHYSICAL_BASE)));
+ HalpPmpIntCtrlProcB = (PVOID)HalpPmpIntCtrl;
+ HalpPmpIpIntGen = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(IP_INT_GEN_PHYSICAL_BASE)));
+
+ //
+ // MemStatus
+ // MemCtrl
+ // MemErrAck
+ // MemErrAddr
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PMP(MEM_STATUS_PHYSICAL_BASE));
+ physicalAddress.LowPart = IO_ADDRESS_LO(PMP(MEM_STATUS_PHYSICAL_BASE));
+ VirtualAddressBase = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (VirtualAddressBase == (PVOID)NULL)
+ return FALSE;
+
+ HalpPmpMemStatus = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(MEM_STATUS_PHYSICAL_BASE)));
+ HalpPmpMemCtrl = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(MEM_CTRL_PHYSICAL_BASE)));
+ HalpPmpMemErrAck = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(MEM_ERR_ACK_PHYSICAL_BASE)));
+ HalpPmpMemErrAddr = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(MEM_ERR_ADDR_PHYSICAL_BASE)));
+
+ //
+ // PciStatus
+ // PciCtrl
+ // PciErrAck
+ // PciErrAddr
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PMP(PCI_STATUS_PHYSICAL_BASE));
+ physicalAddress.LowPart = IO_ADDRESS_LO(PMP(PCI_STATUS_PHYSICAL_BASE));
+ VirtualAddressBase = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (VirtualAddressBase == (PVOID)NULL)
+ return FALSE;
+
+ HalpPmpPciStatus = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(PCI_STATUS_PHYSICAL_BASE)));
+ HalpPmpPciCtrl = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(PCI_CTRL_PHYSICAL_BASE)));
+ HalpPmpPciErrAck = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(PCI_ERR_ACK_PHYSICAL_BASE)));
+ HalpPmpPciErrAddr = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(PCI_ERR_ADDR_PHYSICAL_BASE)));
+
+ //
+ // PciRetry
+ // PciConfigAddr
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PMP(PCI_RETRY_PHYSICAL_BASE));
+ physicalAddress.LowPart = IO_ADDRESS_LO(PMP(PCI_RETRY_PHYSICAL_BASE));
+ VirtualAddressBase = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (VirtualAddressBase == (PVOID)NULL)
+ return FALSE;
+
+ HalpPmpPciRetry = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(PCI_RETRY_PHYSICAL_BASE)));
+ HalpPmpPciConfigAddr = (PVOID)(((ULONG)VirtualAddressBase) + REG_OFFSET4(PMP(PCI_CONFIG_ADDR_PHYSICAL_BASE)));
+
+ //
+ // MemDiag
+ //
+
+ physicalAddress.HighPart = IO_ADDRESS_HI(PMP(MEM_DIAG_PHYSICAL_BASE));
+ physicalAddress.LowPart = IO_ADDRESS_LO(PMP(MEM_DIAG_PHYSICAL_BASE));
+ HalpPmpMemDiag = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ if (HalpPmpMemDiag == (PVOID)NULL)
+ return FALSE;
+
+ //
+ // See ya!
+ //
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halntp/mips/jxmaptb.c b/private/ntos/nthals/halntp/mips/jxmaptb.c
new file mode 100644
index 000000000..b04f8cb9d
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxmaptb.c
@@ -0,0 +1,440 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxmaptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for a MIPS R3000
+ or R4000 Jazz system. It also sets the instruction and data cache line
+ sizes for a MIPS R3000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapFixedTbEntries)
+#pragma alloc_text(INIT, HalpMapSysCtrlReg)
+#pragma alloc_text(INIT, HalpUnMapSysCtrlReg)
+
+#endif
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine loads the fixed TB entries that map the DMA control and
+ interrupt sources registers for a MIPS R3000 or R4000 Jazz system. It
+ also sets the instruction and data cache line sizes for a MIPS R3000
+ Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ ENTRYLO Pte[2];
+ ULONG HalpFirmwarePrivateData;
+ ULONG Address;
+ ULONG Temp;
+ PKPRCB Prcb;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // The FALCON architecture's address map is different
+ // from those of STRIKER and DUO such that the system
+ // control space registers cannot be mapped into one
+ // page of memory for the following reasons:
+ //
+ // 1. The system control space registers in the first version
+ // of the PMP chip spans > 16MB of control address space,
+ // not including EISA/ISA control space. The second (final)
+ // version of the PMP chip will not require as much address
+ // space for the control registers, but the registers will
+ // still not be able to all fit in one physically contiguous
+ // page.
+ //
+ // This is due to the fact that each 32-bit register is actually
+ // implemented as two 16-bit registers to provide the necessary
+ // state and control signal information between the two PMP chips
+ // required by a Wide memory system architecture. There are two
+ // PMP chips in a Wide mode system versus one in a Narrow mode
+ // system.
+ //
+ // 2. There is currently no mechanism for specifying memory regions
+ // greater than 4K bytes per TLB entry. Although this is supported
+ // in the R4x00, NT does not provide a documented interface to the
+ // HAL for taking advantage of this functionality.
+ //
+ // 3. It would require multiple pages to span the system control space
+ // for either version of the PMP chip. The HAL is only allocated one
+ // permament TLB entry which can, at most, map two physical pages of
+ // 4K bytes each.
+ //
+ //
+ // Note:
+ //
+ // We need to replicate bits 31:28 into bits 35:32 so that in a Wide Falcon
+ // system both PMP chips know what address space is being accessed.
+ //
+
+
+ //
+ // The first thing we need to do is determine which version of the PMP
+ // chip we have. We do this by mapping the GlobalStatus register and
+ // interrogating its RevisionId field. This field is 0 in the first version
+ // of the PMP and 0x2 in the second (final) version. The GlobalStatus
+ // register is the only register whose address is the same in both versions
+ // of the PMP chip (by design).
+ //
+
+ Pte[0].PFN = ((GLOBAL_STATUS_PHYSICAL_BASE & 0xF0000000) >> (PAGE_SHIFT - 4)) | (GLOBAL_STATUS_PHYSICAL_BASE >> PAGE_SHIFT);
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+ Pte[0].C = UNCACHED_POLICY;
+
+ Pte[1].PFN = 0;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+ Pte[1].D = 0;
+ Pte[1].C = 0;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ //
+ // Read GlobalStatus and save the version number
+ // of the RevisionId field to distinguish between
+ // each revision of the PMP chip. Also save whether
+ // there is a second processor present.
+ //
+
+ Temp = READ_REGISTER_ULONG(PMP_CONTROL_VIRTUAL_BASE);
+
+ HalpPmpProcessorBPresent = ((Temp & GLOBAL_STATUS_MP) ? 1 : 0);
+
+ //
+ // The revision id field is 0 for the first version
+ // and 2 for the second version. We set them to 1 and
+ // 2, respectively, so that it can then be MACHINE_ID
+ // is used as an index into each register array as explained
+ // in fxpmpsup.c through the use of the PMP(x) macro
+ // defined in falcondef.h
+ //
+ // Note: There is now a version 3 of the PMP chip which we
+ // pretend is the same as version 2 since there were
+ // no register address changes that would force us to
+ // expand the register array indexed by the PMP(x) macro.
+ //
+ // We now define a Hal private variable that contains the actual
+ // revision of the PMP chips as this is used in some tests.
+ //
+
+ switch (Temp & GLOBAL_STATUS_REV_MASK) {
+
+ case GLOBAL_STATUS_REVID_0 :
+ MACHINE_ID = 1;
+ HalpPmpRevision = 1;
+ break;
+
+ case GLOBAL_STATUS_REVID_2 :
+ MACHINE_ID = 2;
+ HalpPmpRevision = 2;
+ break;
+
+ case GLOBAL_STATUS_REVID_3 :
+ MACHINE_ID = 2;
+ HalpPmpRevision = 3;
+ break;
+
+ }
+
+ //
+ // Do the locked down mappings now
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Set the ECache active/inactive flag
+ //
+
+ Temp = READ_REGISTER_ULONG(PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(GLOBAL_CTRL_PHYSICAL_BASE)));
+ HalpPmpExternalCachePresent = (Temp & GLOBAL_CTRL_ECE) ? 1 : 0;
+
+ //
+ // Before we map the PMP registers required during Phase 0 intialization,
+ // we will first read the PciConfigAddress register which will contain
+ // the actual offset that will be ORed with the address used by the device
+ // driver to write/read memory. This is only necessary for the first version
+ // of the PMP chip which contains a bug in how the PLL was instantiated.
+ //
+
+ Address = PMP(PCI_CONFIG_ADDR_PHYSICAL_BASE);
+
+ Pte[0].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+ Pte[0].C = UNCACHED_POLICY;
+
+ Pte[1].PFN = 0;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+ Pte[1].D = 0;
+ Pte[1].C = 0;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ HalpPmpPciConfigAddr = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(PCI_CONFIG_ADDR_PHYSICAL_BASE)));
+
+ //
+ // Set the PCI address space memory offset according
+ // to what is passed up by the firmware. This offset
+ // defines the memory address space organization as
+ // viewed by an IO device. This offset is defined by
+ // the upper 16 bits of the register.
+ //
+ // In addition, the lower 16 bits of the register will
+ // define the IRQ edge versus level modes required by
+ // the 82374's interrupt controller.
+ //
+
+ HalpFirmwarePrivateData = READ_REGISTER_ULONG(HalpPmpPciConfigAddr);
+ HalpPciMemoryOffset = HalpFirmwarePrivateData & 0xFFFF0000;
+
+ HalpEisaInterrupt1Level = (UCHAR) ( (HalpFirmwarePrivateData & 0xFF) ? (HalpFirmwarePrivateData & 0xFF) : 0xF8 );
+ HalpEisaInterrupt2Level = (UCHAR) ( (HalpFirmwarePrivateData & 0xFF00) ? ((HalpFirmwarePrivateData >> 8) & 0xFF) : 0xDB );
+
+ //
+ // Now we will map in Eisa Control Space and
+ // program the base address for the GPCS registers.
+ //
+
+ Address = EISA_CONTROL_PHYSICAL_BASE;
+
+ Pte[0].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+ Pte[0].C = UNCACHED_POLICY;
+
+ Address = PCI_CONFIG_SEL_PHYSICAL_BASE;
+
+ Pte[1].PFN = 0;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+ Pte[1].D = 0;
+ Pte[1].C = UNCACHED_POLICY;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ HalpConfigureGpcsRegs((PVOID)PMP_CONTROL_VIRTUAL_BASE);
+
+ //
+ // Now we will re-use the same TLB entry pair and map IntCtrl and IntStatus
+ // for Phase 0 initialization. At the end of Phase 0 we will map IntCause
+ // and IoIntAck before enabling interrupts. This should minimize the
+ // need to map control registers on-the-fly.
+ //
+ // Note that in the first version of the PMP chip, these two registers
+ // reside in separate physical pages, but in the second version of the chip
+ // they reside in the same physical page.
+ //
+
+ Address = PMP(INT_STATUS_PHYSICAL_BASE);
+
+ Pte[0].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+ Pte[0].C = UNCACHED_POLICY;
+
+ Address = PCI_CONFIG_SEL_PHYSICAL_BASE;
+
+ Pte[1].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);;
+ Pte[1].G = 1;
+ Pte[1].V = 1;
+ Pte[1].D = 1;
+ Pte[1].C = UNCACHED_POLICY;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ //
+ // Initialize register pointers with
+ // wired virtual addresses
+ //
+
+ HalpPmpIntStatus = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_STATUS_PHYSICAL_BASE)));
+ HalpPmpIntCtrl = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CONTROL_PHYSICAL_BASE)));
+ HalpExtPmpControl = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + PAGE_SIZE + 0x4);
+
+
+ } else {
+
+ //
+ // Both the IntStatus and IntCtrl registers are
+ // on different physical pages in the first version
+ // of the PMP, but are one the same physical page in
+ // subsequent versions.
+ //
+
+ Address = PMP(INT_STATUS_PHYSICAL_BASE);
+
+ Pte[0].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+ Pte[0].C = UNCACHED_POLICY;
+
+ Pte[1].PFN = 0;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+ Pte[1].D = 0;
+ Pte[1].C = UNCACHED_POLICY;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ //
+ // Initialize register pointers with
+ // wired virtual addresses
+ //
+
+ HalpPmpIntStatusProcB = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_STATUS_PHYSICAL_BASE)));
+ HalpPmpIntCtrlProcB = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CONTROL_PHYSICAL_BASE)));
+
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpMapSysCtrlReg (
+ IN ULONG PhysAddrEvenPage,
+ IN ULONG PhysAddrOddPage,
+ IN ULONG VirtAddr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine uses the wired entries of the R4x00 TLB to
+ map system control registers on-the-fly for FALCON since
+ the system control space spans multiple pages which we
+ cannot map at one time due to limitations imposed by NT.
+
+Arguments:
+
+ PhysAddrEvenPage 32 bit physical address
+ PhysAddrOddPage 32 bit physical address
+ VirtAddr 32 bit virtual address
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ULONG HalpEntry;
+ENTRYLO HalpPte[2];
+
+ //
+ // Map page(s)
+ //
+
+ HalpEntry = HalpAllocateTbEntry();
+
+ HalpPte[0].PFN = ((PhysAddrEvenPage & 0xF0000000) >> (PAGE_SHIFT - 4)) | (PhysAddrEvenPage >> PAGE_SHIFT);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = ((PhysAddrOddPage & 0xF0000000) >> (PAGE_SHIFT - 4)) | (PhysAddrOddPage >> PAGE_SHIFT);
+ HalpPte[1].G = 1;
+ HalpPte[1].V = PhysAddrOddPage ? 1 : 0;
+ HalpPte[1].D = 1;
+ HalpPte[1].C = UNCACHED_POLICY;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], (PVOID)VirtAddr, HalpEntry);
+
+}
+
+VOID
+HalpUnMapSysCtrlReg (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine uses the wired entries of the R4x00 TLB to
+ unmap system control registers on-the-fly for FALCON since
+ the system control space spans multiple pages which we
+ cannot map at one time due to limitations imposed by NT.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Unmap system control register
+ // by freeing the wired entry.
+ //
+
+ HalpFreeTbEntry();
+
+}
+
+
diff --git a/private/ntos/nthals/halntp/mips/jxport.c b/private/ntos/nthals/halntp/mips/jxport.c
new file mode 100644
index 000000000..5533be22c
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxport.c
@@ -0,0 +1,845 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "sidewind.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)(SP_VIRTUAL_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SP_VIRTUAL_BASE))
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 0;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ //
+ // Need to replicate bits 31:28 in 35:32
+ //
+ HalpPte[0].PFN = ( SP_PHYSICAL_BASE >> PAGE_SHIFT ) |
+ ( ( SP_PHYSICAL_BASE & 0xF0000000 ) >> ( PAGE_SHIFT - 4 ) );
+
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+ KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate.
+ //
+
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+ HalpFreeTbEntry();
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+ HalpFreeTbEntry();
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG KdPortEntry;
+
+ //
+ // Allocate the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+
+ //
+ // Map the serial controller through a allocated TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
+
diff --git a/private/ntos/nthals/halntp/mips/jxreturn.c b/private/ntos/nthals/halntp/mips/jxreturn.c
new file mode 100644
index 000000000..7af09a702
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxreturn.c
@@ -0,0 +1,130 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+A
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ through the keyboard controller (STRIKER and DUO). However, for
+ FALCON we will use the Port92 register in the 82374 to generate
+ a software reset (restart) through the ALT_RESET signal.
+
+ Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+
+ //
+ // Mask interrupts
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Do the right thing!
+ //
+
+ switch (Routine) {
+
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+
+ //
+ // Power down the system
+ //
+
+ {
+ ULONG EPCValue;
+ ULONG EPC = (ULONG)HalpEisaControlBase + EXTERNAL_PMP_CONTROL_OFFSET;
+
+ EPCValue = READ_REGISTER_ULONG( EPC );
+ EPCValue &= ~EPC_POWER;
+ WRITE_REGISTER_ULONG( EPC, EPCValue );
+ EPCValue |= EPC_POWER;
+ WRITE_REGISTER_ULONG( EPC, EPCValue );
+ }
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ //
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Enable Port92 register in 82374
+ //
+
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved1[0], 0x4F);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved1[1], 0x7F);
+
+ //
+ // Generate soft reset through ALT_RESET signal from 82374
+ //
+
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved2[2], 0);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved2[2], 0x01);
+
+ //
+ // Hang
+ //
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+
+ }
+
+}
diff --git a/private/ntos/nthals/halntp/mips/jxsysint.c b/private/ntos/nthals/halntp/mips/jxsysint.c
new file mode 100644
index 000000000..4a43aa2b4
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxsysint.c
@@ -0,0 +1,340 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ //
+ // If the vector number is within the range
+ // of the EISA interrupts controlled by the
+ // 82374, then disable the EISA interrrupt.
+ //
+
+ if ( (Vector >= EISA_VECTORS) && (Vector <= MAXIMUM_EISA_VECTOR) && (Irql == FALCON_LEVEL) ) {
+
+ HalpDisableEisaInterrupt(Vector);
+
+ }
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range
+ // of the EISA interrupts controlled by the
+ // 82374, then enable the EISA interrrupt.
+ //
+
+ if ( (Vector >= EISA_VECTORS) && (Vector <= MAXIMUM_EISA_VECTOR) && (Irql == FALCON_LEVEL) ) {
+
+ HalpEnableEisaInterrupt(Vector, InterruptMode);
+
+ }
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // Set affinity to base processor 0.
+ //
+
+ *Affinity = 1;
+
+ //
+ // return processor IRQL
+ //
+
+ *Irql = FALCON_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level.
+ //
+
+ return(BusInterruptVector);
+
+}
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // Set affinity according to how many
+ // processors we have. If an MP (two
+ // processor) system, direct IO interrupts
+ // to the second processor; otherwise,
+ // all interrupts go to the same processor.
+ //
+
+#ifdef IO_INTERRUPT_STEERING
+ if (HalpPmpProcessorBPresent) {
+
+ *Affinity = 2;
+
+ } else {
+
+ *Affinity = 1;
+
+ }
+#else
+ *Affinity = 1;
+#endif
+
+ //
+ // return processor IRQL
+ //
+
+ *Irql = FALCON_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+}
+
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // Set affinity according to how many
+ // processors we have. If an MP (two
+ // processor) system, direct IO interrupts
+ // to the second processor; otherwise,
+ // all interrupts go to the same processor.
+ //
+
+#ifdef IO_INTERRUPT_STEERING
+ if (HalpPmpProcessorBPresent) {
+
+ *Affinity = 2;
+
+ } else {
+
+ *Affinity = 1;
+
+ }
+#else
+ *Affinity = 1;
+#endif
+
+ //
+ // return processor IRQL
+ //
+
+ *Irql = FALCON_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+ // Be sure no upper bits set as Mask is ULONG
+ //
+ Mask &= 0xFFFF;
+ WRITE_REGISTER_ULONG(HalpPmpIpIntAck, (Mask << 16) | Mask);
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halntp/mips/jxtime.c b/private/ntos/nthals/halntp/mips/jxtime.c
new file mode 100644
index 000000000..ceb932ca2
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxtime.c
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ Register |= 0x80;
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ Register |= 0x80;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/halntp/mips/jxusage.c b/private/ntos/nthals/halntp/mips/jxusage.c
new file mode 100644
index 000000000..7913de37f
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/jxusage.c
@@ -0,0 +1,48 @@
+
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halntp/mips/modes.h b/private/ntos/nthals/halntp/mips/modes.h
new file mode 100644
index 000000000..c4b70eff6
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/modes.h
@@ -0,0 +1,182 @@
+/***************************************************************************
+ *
+ * Media Vision Professional Graphics Adapeter mode tables.
+ *
+ * Created:
+ * August 27, 1993 -by- Jeffrey Newman (NewCon)
+ *
+ * Copyright (c) Newman Consulting 1993
+ * Copyright (c) Media Vision 1993
+ ***************************************************************************/
+
+#include "hm.h"
+
+MVPG_MODE aMvpgModes[] = {
+ {
+ {"1280X1024X32bpp@60Hz"},
+ { sizeof(VIDEO_MODE_INFORMATION),
+ 0,
+ 1280,
+ 1024,
+ 2048 * 4,
+ 1,
+ 32,
+ 60,
+ 800,
+ 600,
+ 8,
+ 8,
+ 8,
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF,
+#if 1
+ 0,
+#else
+ VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
+#endif
+ 1280,
+ 1024
+ },
+ {
+ 253,
+ 333,
+ 269,
+ 291,
+ 1023,
+ 1066,
+ 1024,
+ 1029
+ },
+ {
+ 0x000f71a0 | (3 << 21),
+ 0x00183002
+ },
+ {
+ 0x06 | // Define byte lanes as RGB, from LSB to MSB.
+ G_MODE1280 | // Select 1280x1024 mode.
+ G_MASKVINTR | // Mask off the vertical retrace interrupt.
+ G_RST439 | // Stop resetting the BT439 chip.
+ G_SYNCPOL | // Sync polarity is active low.
+ G_WAIT3 | // Select 0 wait states.
+ G_NOSYNCGRN | // Disable sync on green channel.
+ HM_GFX_IRQ_SEL // Select vertical retrace IRQ.
+ },
+ {
+ 0xC0C0C0
+ }
+ },
+
+ {
+ {"1024X768X32bpp@60Hz"},
+ { sizeof(VIDEO_MODE_INFORMATION),
+ 1,
+ 1024,
+ 768,
+ 2048 * 4,
+ 1,
+ 32,
+ 60,
+ 800,
+ 600,
+ 8,
+ 8,
+ 8,
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF,
+#if 1
+ 0,
+#else
+ VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
+#endif
+ 1024,
+ 768
+ },
+ {
+ 253,
+ 330,
+ 268,
+ 294,
+ 768,
+ 805,
+ 770,
+ 776
+ },
+ {
+ 0x000f71a0 | (3 << 21),
+ 0x00068c0f
+ },
+ {
+ 0x06 | // Define byte lanes as RGB, from LSB to MSB.
+ G_MASKVINTR | // Mask off the vertical retrace interrupt.
+ G_RST439 | // Stop resetting the BT439 chip.
+ G_SYNCPOL | // Sync polarity is active low.
+ G_WAIT3 | // Select 0 wait states.
+ G_NOSYNCGRN | // Disable sync on green channel.
+ HM_GFX_IRQ_SEL // Select vertical retrace IRQ.
+ },
+ {
+ 0x404040
+ }
+ },
+
+ {
+ // This is a special debug mode that returns a 1024 mode
+ // to the display driver, but really sets the chip to 1280 mode.
+
+ {"1024X768X32bpp@70Hz"},
+ { sizeof(VIDEO_MODE_INFORMATION),
+ 2,
+ 1024,
+ 768,
+ 2048 * 4,
+ 1,
+ 32,
+ 70,
+ 800,
+ 600,
+ 8,
+ 8,
+ 8,
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF,
+#if 1
+ 0,
+#else
+ VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
+#endif
+ 1024,
+ 768
+ },
+ {
+ 253,
+ 333,
+ 269,
+ 291,
+ 1023,
+ 1066,
+ 1024,
+ 1029
+ },
+ {
+ 0x000f71a0 | (3 << 21),
+ 0x00183002
+ },
+ {
+ 0x06 | // Define byte lanes as RGB, from LSB to MSB.
+ G_MODE1280 | // Select 1280x1024 mode.
+ G_MASKVINTR | // Mask off the vertical retrace interrupt.
+ G_RST439 | // Stop resetting the BT439 chip.
+ G_SYNCPOL | // Sync polarity is active low.
+ G_WAIT3 | // Select 0 wait states.
+ G_NOSYNCGRN | // Disable sync on green channel.
+ HM_GFX_IRQ_SEL // Select vertical retrace IRQ.
+ },
+ {
+ 0xC0C0C0
+ }
+ }
+
+};
diff --git a/private/ntos/nthals/halntp/mips/pcieisa.h b/private/ntos/nthals/halntp/mips/pcieisa.h
new file mode 100644
index 000000000..46227b9e9
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/pcieisa.h
@@ -0,0 +1,326 @@
+/*++
+
+Copyright (c) 1993 NeTpower Incorporated
+
+Module Name:
+
+ pcieisa.h
+
+Abstract:
+
+ This module is the header file that describes virtual
+ register address used by the EISA System Component (ESC)
+ device (82374EB).
+
+
+Author:
+
+ Hector R. Briones (hector) 29-Nov-1993
+
+Revision History:
+
+--*/
+
+#ifndef _PCIEISA_
+#define _PCIEISA_
+
+#define ESC_DMA0_ADDRESS (EISA_CONTROL_VIRTUAL_BASE)
+#define ESC_DMA0_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0x1)
+#define ESC_DMA1_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0x2)
+#define ESC_DMA1_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0x3)
+#define ESC_DMA2_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0x4)
+#define ESC_DMA2_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0x5)
+#define ESC_DMA3_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0x6)
+#define ESC_DMA3_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0x7)
+
+#define ESC_DMA0_3_CMD (EISA_CONTROL_VIRTUAL_BASE + 0x8)
+#define ESC_DMA0_3_STATUS (EISA_CONTROL_VIRTUAL_BASE + 0x8)
+
+#define ESC_DMA0_3_REQ (EISA_CONTROL_VIRTUAL_BASE + 0x9)
+#define ESC_DMA0_3_MASKSB (EISA_CONTROL_VIRTUAL_BASE + 0xa)
+#define ESC_DMA0_3_MODE (EISA_CONTROL_VIRTUAL_BASE + 0xb)
+#define ESC_DMA0_3_CLRBP (EISA_CONTROL_VIRTUAL_BASE + 0xc)
+#define ESC_DMA0_3_MASTER_CLR (EISA_CONTROL_VIRTUAL_BASE + 0xd)
+#define ESC_DMA0_3_CLRMASK (EISA_CONTROL_VIRTUAL_BASE + 0xe)
+#define ESC_DMA0_3_ALLBITMASK (EISA_CONTROL_VIRTUAL_BASE + 0xf)
+
+#define ESC_INT_CONTROL1 (EISA_CONTROL_VIRTUAL_BASE + 0x20)
+#define ESC_INT_MASK1 (EISA_CONTROL_VIRTUAL_BASE + 0x21)
+
+#define ESC_TC1_COUNTER0 (EISA_CONTROL_VIRTUAL_BASE + 0x40)
+#define ESC_TC1_COUNTER1 (EISA_CONTROL_VIRTUAL_BASE + 0x41)
+#define ESC_TC1_COUNTER2 (EISA_CONTROL_VIRTUAL_BASE + 0x42)
+#define ESC_TC1_CONTROL (EISA_CONTROL_VIRTUAL_BASE + 0x43)
+#define ESC_TC1_RBCMD (EISA_CONTROL_VIRTUAL_BASE + 0x43)
+#define ESC_TC1_LATCH_CMD (EISA_CONTROL_VIRTUAL_BASE + 0x43)
+
+#define ESC_TC2_COUNTER0 (EISA_CONTROL_VIRTUAL_BASE + 0x48)
+#define ESC_TC2_COUNTER2 (EISA_CONTROL_VIRTUAL_BASE + 0x4a)
+#define ESC_TC2_CONTROL (EISA_CONTROL_VIRTUAL_BASE + 0x4b)
+#define ESC_TC2_RBCMD (EISA_CONTROL_VIRTUAL_BASE + 0x4b)
+#define ESC_TC2_LATCH_CMD (EISA_CONTROL_VIRTUAL_BASE + 0x4b)
+
+#define ESC_RST_UBUS_IRQ12 (EISA_CONTROL_VIRTUAL_BASE + 0x60)
+#define ESC_NMI_CONTROL_STATUS (EISA_CONTROL_VIRTUAL_BASE + 0x61)
+
+#define ESC_NMI_RTC (EISA_CONTROL_VIRTUAL_BASE + 0x70)
+#define ESC_CMOS_RAM_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0x70)
+#define ESC_CMOS_RAM_DATA (EISA_CONTROL_VIRTUAL_BASE + 0x71)
+
+#define ESC_BIOS_TIMER (EISA_CONTROL_VIRTUAL_BASE + 0x78)
+
+#define ESC_DMA0_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x87)
+#define ESC_DMA1_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x83)
+#define ESC_DMA2_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x81)
+#define ESC_DMA3_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x82)
+#define ESC_DMA5_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x8b)
+#define ESC_DMA6_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x89)
+#define ESC_DMA7_PAGE (EISA_CONTROL_VIRTUAL_BASE + 0x8a)
+
+#define ESC_DMA_LPAGE_REF (EISA_CONTROL_VIRTUAL_BASE + 0x8f)
+
+#define ESC_PORT_92 (EISA_CONTROL_VIRTUAL_BASE + 0x8f)
+
+#define ESC_INT_CONTROL2 (EISA_CONTROL_VIRTUAL_BASE + 0xa0)
+#define ESC_INT_MASK2 (EISA_CONTROL_VIRTUAL_BASE + 0xa1)
+
+#define ESC_DMA4_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0xc0)
+#define ESC_DMA4_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0xc2)
+#define ESC_DMA5_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0xc4)
+#define ESC_DMA5_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0xc6)
+#define ESC_DMA6_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0xc8)
+#define ESC_DMA6_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0xca)
+#define ESC_DMA7_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0xcc)
+#define ESC_DMA7_COUNTER (EISA_CONTROL_VIRTUAL_BASE + 0xce)
+
+#define ESC_DMA4_7_CMD (EISA_CONTROL_VIRTUAL_BASE + 0xd0)
+#define ESC_DMA4_7_STATUS (EISA_CONTROL_VIRTUAL_BASE + 0xd0)
+
+#define ESC_DMA4_7_REQ (EISA_CONTROL_VIRTUAL_BASE + 0xd2)
+#define ESC_DMA4_7_MASKSB (EISA_CONTROL_VIRTUAL_BASE + 0xd4)
+#define ESC_DMA4_7_MODE (EISA_CONTROL_VIRTUAL_BASE + 0xd6)
+#define ESC_DMA4_7_CLRBP (EISA_CONTROL_VIRTUAL_BASE + 0xd8)
+#define ESC_DMA4_7_MASTER_CLR (EISA_CONTROL_VIRTUAL_BASE + 0xda)
+#define ESC_DMA4_7_CLRMASK (EISA_CONTROL_VIRTUAL_BASE + 0xdc)
+#define ESC_DMA4_7_ALLBITMASK (EISA_CONTROL_VIRTUAL_BASE + 0xde)
+
+#define ESC_FLOP2_DOR (EISA_CONTROL_VIRTUAL_BASE + 0x372)
+#define ESC_FLOP1_DOR (EISA_CONTROL_VIRTUAL_BASE + 0x3f2)
+
+#define ESC_DMA_SGINT_STAT (EISA_CONTROL_VIRTUAL_BASE + 0x40a)
+
+#define ESC_DMA0_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x410)
+#define ESC_DMA1_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x411)
+#define ESC_DMA2_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x412)
+#define ESC_DMA3_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x413)
+#define ESC_DMA5_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x415)
+#define ESC_DMA6_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x416)
+#define ESC_DMA7_SGCMD (EISA_CONTROL_VIRTUAL_BASE + 0x417)
+
+#define ESC_DMA0_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x418)
+#define ESC_DMA1_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x419)
+#define ESC_DMA2_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x41a)
+#define ESC_DMA3_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x41b)
+#define ESC_DMA5_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x41d)
+#define ESC_DMA6_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x41e)
+#define ESC_DMA7_SGSTAT (EISA_CONTROL_VIRTUAL_BASE + 0x41f)
+
+#define ESC_DMA0_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x420)
+#define ESC_DMA1_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x424)
+#define ESC_DMA2_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x428)
+#define ESC_DMA3_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x42c)
+#define ESC_DMA5_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x434)
+#define ESC_DMA6_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x438)
+#define ESC_DMA7_SGDPTR (EISA_CONTROL_VIRTUAL_BASE + 0x43c)
+
+#define ESC_NMI_EXT (EISA_CONTROL_VIRTUAL_BASE + 0x461)
+#define ESC_SW_NMI (EISA_CONTROL_VIRTUAL_BASE + 0x462)
+
+#define ESC_DMA0_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x487)
+#define ESC_DMA1_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x483)
+#define ESC_DMA2_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x481)
+#define ESC_DMA3_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x482)
+#define ESC_DMA5_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x48b)
+#define ESC_DMA6_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x489)
+#define ESC_DMA7_HIPAGE (EISA_CONTROL_VIRTUAL_BASE + 0x48a)
+
+#define ESC_EDGE_LEVEL1 (EISA_CONTROL_VIRTUAL_BASE + 0x4d0)
+#define ESC_EDGE_LEVEL2 (EISA_CONTROL_VIRTUAL_BASE + 0x4d1)
+#define ESC_DMA_EXT_MODE (EISA_CONTROL_VIRTUAL_BASE + 0x4d6)
+
+//
+// Timer/Counter Control Word definitions
+//
+#define ESC_TC_CNTRLW_RB_CMD 0xc0 // Read Back command
+#define ESC_TC_CNTRLW_SC(x) (x<<6) // Select counter (0-2)
+#define ESC_TC_CNTRLW_SC2 0x80 // Select counter 2
+#define ESC_TC_CNTRLW_SC1 0x40 // Select counter 1
+#define ESC_TC_CNTRLW_SC0 0x00 // Select counter 0
+#define ESC_TC_CNTRLW_CLC 0x00 // Counter Latch command
+#define ESC_TC_CNTRLW_16B 0x30 // R/W LSB then MSB
+#define ESC_TC_CNTRLW_MSB 0x20 // R/W Most sig. byte (MSB)
+#define ESC_TC_CNTRLW_LSB 0x10 // R/W Least sig. byte (LSB)
+#define ESC_TC_CNTRLW_MODE(x) (x<<1) // Select mode (0-5)
+#define ESC_TC_CNTRLW_BCD 0x01 // Binary/BCD countdown type
+
+//
+// Timer/Counter Modes
+//
+#define ESC_TC_MODE_ITC 0 // Sel mode0 (int. on term count)
+#define ESC_TC_MODE_HROS 1 // Sel mode1 (hw retrig. 1 shot)
+#define ESC_TC_MODE_RGEN 2 // Sel mode2 (rate generator)
+#define ESC_TC_MODE_SQW 3 // Sel mode3 (square wave mode)
+#define ESC_TC_MODE_STS 4 // Sel mode4 (sw triggerable strobe)
+#define ESC_TC_MODE_HTS 5 // Sel mode5 (hw triggerable strobe)
+
+//
+// Timer/Counter Read Back Command register
+//
+#define ESC_TC_NOLATCH_STATUS 0x20 // Do not Latch status - selected cntrs
+#define ESC_TC_NOLATCH_CNTR 0x10 // Do not Latch count of selected cntrs
+#define ESC_TC_LATCH_CNTR 0x00 // Latch count of selected cntrs
+#define ESC_TC_LATCH_STATUS 0x00 // Latch status - selected cntrs
+#define ESC_TC_RBCMD_SEL_CNT2 0x08 // Read Back Cmd, select counter2
+#define ESC_TC_RBCMD_SEL_CNT1 0x04 // Read Back Cmd, select counter1
+#define ESC_TC_RBCMD_SEL_CNT0 0x02 // Read Back Cmd, select counter0
+
+//
+// With a divisor of 11930 (0x2e9a), counter0 will produces a square
+// wave with a period of 10ms. If clock frequency (1.193MHz) is divided
+// by the divisor(11930), it gives a result of 100. If the recipricol of
+// the result (100) is done, it equals 10ms.
+//
+#define NANOSECONDS 1
+#define MICROSECONDS ( 1000 * NANOSECONDS )
+#define MILLISECONDS ( 1000 * MICROSECONDS )
+#define SECONDS ( 1000 * MILLISECONDS )
+#define COUNTER_PERIOD ( 838 * NANOSECONDS )
+#define COUNTER_10MS ( ( ( 10 * MILLISECONDS ) / COUNTER_PERIOD ) )
+#define COUNTER_1MS ( ( ( 1 * MILLISECONDS ) / COUNTER_PERIOD ) )
+
+//
+// NMI Status and Control Register
+//
+#define ESC_NCS_T1C2_OUT 0x20 // Output of Timer 1, Counter 2
+#define ESC_NCS_SPEAKER_ENABLE 0x02 // Enable Speaker, used for Interval Timer PMP v2
+#define ESC_NCS_T1C2_ENABLE 0x01 // Enable Timer 1, Counter 2
+
+//
+// The ESC Configuration registers are accessed through
+// and indexing scheme. The Index address register is
+// located at I/O address 0x22 and the index data register
+// is located at I/O address 0x23. The register data
+// written into the index address register selects the
+// desired configuration register. Data for the selected
+// configuration register can be read from or written to,
+// by performing a read or write to the index data register.
+//
+#define ESC_CONFIG_INDEX_ADDRESS (EISA_CONTROL_VIRTUAL_BASE + 0x22)
+#define ESC_CONFIG_INDEX_DATA (EISA_CONTROL_VIRTUAL_BASE + 0x23)
+
+#define ESC_CONFIG_ID 0x2
+#define ESC_CONFIG_REVID 0x8
+#define ESC_CONFIG_MODE_SEL 0x40
+#define ESC_CONFIG_BIOS_CSA 0x42
+#define ESC_CONFIG_BIOS_CSB 0x43
+#define ESC_CONFIG_EISA_CLK_DIV 0x4d
+#define ESC_CONFIG_PERIPH_CSA 0x4e
+#define ESC_CONFIG_PERIPH_CSB 0x4f
+#define ESC_CONFIG_EISA_ID0 0x50
+#define ESC_CONFIG_EISA_ID1 0x51
+#define ESC_CONFIG_EISA_ID2 0x52
+#define ESC_CONFIG_EISA_ID3 0x53
+
+#define ESC_CONFIG_SGRBA 0x57
+
+#define ESC_CONFIG_PIRQ0 0x60
+#define ESC_CONFIG_PIRQ1 0x61
+#define ESC_CONFIG_PIRQ2 0x62
+#define ESC_CONFIG_PIRQ3 0x63
+
+#define ESC_CONFIG_GPCSLA0 0x64
+#define ESC_CONFIG_GPCSHA0 0x65
+#define ESC_CONFIG_GPCSMASK0 0x66
+#define ESC_CONFIG_GPCSLA1 0x68
+#define ESC_CONFIG_GPCSHA1 0x69
+#define ESC_CONFIG_GPCSMASK1 0x6a
+#define ESC_CONFIG_GPCSLA2 0x6c
+#define ESC_CONFIG_GPCSHA2 0x6d
+#define ESC_CONFIG_GPCSMASK2 0x6e
+
+#define ESC_CONFIG_GPXBC 0x6f
+
+#define ESC_CONFIG_TEST_CNTRL 0x88
+
+//
+// Bit definitions for ESC configuration registers.
+//
+#define ESC_CONFIG_IDEN_BYTE 0x0f // Enable access to config registers
+
+#define ESC_BIOS_CSA_LOWBIOS1 0x01 // Addrs range 0xfffe0000 - 0xfffe3fff
+#define ESC_BIOS_CSA_LOWBIOS2 0x02 // Addrs range 0xfffe4000 - 0xfffe7fff
+#define ESC_BIOS_CSA_LOWBIOS3 0x04 // Addrs range 0xfffe8000 - 0xfffebfff
+#define ESC_BIOS_CSA_LOWBIOS4 0x08 // Addrs range 0xfffec000 - 0xfffeffff
+#define ESC_BIOS_CSA_HIGHBIOS 0x10 // Addrs range 0xffff0000 - 0xffffffff
+#define ESC_BIOS_CSA_ENLBIOS 0x20 // Addrs range 0xfff80000 - 0xfffdffff
+#define ESC_BIOS_CSA_ALLBIOS 0x3f // 512Kbytes 0xfff80000 - 0xffffffff
+
+#define ESC_BIOS_CSB_BIOSWREN 0x08 // Bios Write Enable
+
+#define ESC_PCI_EISA_CLK_33MHZ 0x00 // PCI Clk div of 33MHz for BCLK 8.33Mhz
+#define ESC_PCI_EISA_CLK_25MHZ 0x01 // PCI Clk div of 25MHz for BLCK 8.33Mhz
+#define ESC_PCI_EISA_MOUSE_INT 0x10 // Mouse interrupt
+#define ESC_PCI_EISA_PROC_ERR 0x20 // Co-Processor Error
+
+#define ESC_PERIPH_CSA_RTC 0x01 // Decode for Real Time Clock
+#define ESC_PERIPH_CSA_KBD 0x02 // Decode for Keyboard Controller
+#define ESC_PERIPH_CSA_FDC1 0x04 // Decode for Floppy Disk Controller
+#define ESC_PERIPH_CSA_FDC2 0x08 // Decode for Floppy Disk Controller
+#define ESC_PERIPH_CSA_SECNDARY 0x20 // Decode for Secondary addrs space
+
+#define ESC_PERIPH_CSB_SERA1 0x00 // Decode for Serial PortA - COM1
+#define ESC_PERIPH_CSB_SERA2 0x01 // Decode for Serial PortA - COM2
+#define ESC_PERIPH_CSB_SERA_DIS 0x03 // Decode for Serial PortA Disable
+#define ESC_PERIPH_CSB_SERB1 0x00 // Decode for Serial PortB - COM1
+#define ESC_PERIPH_CSB_SERB2 0x04 // Decode for Serial PortB - COM2
+#define ESC_PERIPH_CSB_SERB_DIS 0x0c // Decode for Serial PortB Disable
+#define ESC_PERIPH_CSB_LPT1 0x00 // Decode for Parallel Port1
+#define ESC_PERIPH_CSB_LPT2 0x10 // Decode for Parallel Port2
+#define ESC_PERIPH_CSB_LPT3 0x20 // Decode for Parallel Port3
+#define ESC_PERIPH_CSB_LPT_DIS 0x30 // Decode for Parallel Port Disable
+#define ESC_PERIPH_CSB_PORT92 0x40 // Decode for Port 92
+#define ESC_PERIPH_CSB_CRAM 0x80 // Decode for Cram
+
+#define ESC_MODE_SEL_EISAMSUPP0 0x00 // 4 EISA Masters, 4 slots, 4 PCI IRQ's
+#define ESC_MODE_SEL_EISAMSUPP1 0x01 // 6 EISA Masters, 2 slots, 2 PCI IRQ's
+#define ESC_MODE_SEL_EISAMSUPP2 0x02 // 7 EISA Masters, 1 slots, 1 PCI IRQ's
+#define ESC_MODE_SEL_EISAMSUPP3 0x03 // 8 EISA Masters, 0 slots, 0 PCI IRQ's
+#define ESC_MODE_SEL_SERR_NMIEN 0x08 // SERR# generated NMI enable
+#define ESC_MODE_SEL_GEN_CS 0x10 // General Purpose Chip selects
+#define ESC_MODE_SEL_CONFIG_RAD 0x20 // Configuration Ram Address
+
+#define ESC_GPXBC_XBUSOE0 0x01 // XBUSOE# Generation for GPCS0
+#define ESC_GPXBC_XBUSOE1 0x02 // XBUSOE# Generation for GPCS1
+#define ESC_GPXBC_XBUSOE2 0x04 // XBUSOE# Generation for GPCS2
+
+//
+// IRQ defines for PCI/EISA - PCI/ISA bridge devices.
+//
+#define IO_IRQ0 0
+#define IO_IRQ1 1
+#define IO_IRQ2 2
+#define IO_IRQ3 3
+#define IO_IRQ4 4
+#define IO_IRQ5 5
+#define IO_IRQ6 6
+#define IO_IRQ7 7
+#define IO_IRQ8 8
+#define IO_IRQ9 9
+#define IO_IRQ10 10
+#define IO_IRQ11 11
+#define IO_IRQ12 12
+#define IO_IRQ13 13
+#define IO_IRQ14 14
+#define IO_IRQ15 15
+
+#endif // _PCIEISA_
diff --git a/private/ntos/nthals/halntp/mips/pcip.h b/private/ntos/nthals/halntp/mips/pcip.h
new file mode 100644
index 000000000..984475a2a
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/pcip.h
@@ -0,0 +1,140 @@
+//
+// Hal specific PCI bus structures
+//
+
+#define PCI_MAX_LOCAL_DEVICE 7
+#define PCI_MAX_BUS_NUMBER 31
+#define PCI_MAX_IO_ADDRESS 0x1FFFFFFF // (PCI_IO_PHYSICAL_BASE + 0x1FFFFFFF)
+#define PCI_MAX_MEMORY_ADDRESS 0x1FFFFFFF //(PCI_MEMORY_PHYSICAL_BASE + 0x1FFFFFFF)
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS PCI_MAX_MEMORY_ADDRESS
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MEMORY_PHYSICAL_BASE
+#define PCI_MAX_DENSE_MEMORY_ADDRESS PCI_MAX_MEMORY_ADDRESS
+#define PCI_MAX_INTERRUPT_VECTOR 0xF
+
+//
+// Values used to index both the
+// HalpPciConfigSelectDecodeTable[]
+// and HalpPCIPinToLineTable[].
+//
+
+#define PCI_ISA_DEVICE_NUMBER 0
+#define PCI_OBENET_DEVICE_NUMBER 1
+#define PCI_OBSCSI_DEVICE_NUMBER 2
+#define PCI_VID_DEVICE_NUMBER 3
+#define PCI_SLOT0_DEVICE_NUMBER 4
+#define PCI_SLOT1_DEVICE_NUMBER 5
+#define PCI_SLOT2_DEVICE_NUMBER 6
+#define PCI_PMP_DEVICE_NUMBER 7
+
+//
+// Define PCI slot validity
+//
+
+typedef enum _VALID_SLOT {
+ InvalidBus = 0,
+ InvalidSlot,
+ ValidSlot
+} VALID_SLOT;
+
+//
+// New data structures for Hal Bus Extender API
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+//
+// Macro used to determin if Type 0 or Type 1
+// device
+//
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+//
+// Define PciConfigAddr register structure
+//
+typedef struct _PCI_CONFIG_ADDR {
+ ULONG Type : 1;
+ ULONG Reserved2 : 7;
+ ULONG FunctionNumber : 3;
+ ULONG DeviceNumber : 5;
+ ULONG BusNumber : 8;
+ ULONG Reserved1 : 8;
+} PCI_CONFIG_ADDR, *PPCI_CONFIG_ADDR;
+
+//
+// Define PCI configuration cycle types.
+//
+typedef enum _PCI_CONFIGURATION_TYPES {
+ PciConfigTypeInvalid = -1,
+ PciConfigType0 = 0,
+ PciConfigType1 = 1
+} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES;
+
+//
+// Define PCI cycle/command types.
+//
+
+typedef enum _PCI_COMMAND_TYPES{
+ PciCommandInterruptAcknowledge = 0x0,
+ PciCommandSpecialCycle = 0x1,
+ PciCommandIoRead = 0x2,
+ PciCommandIoWrite = 0x3,
+ PciCommandMemoryRead = 0x6,
+ PciCommandMemoryWrite = 0x7,
+ PciCommandConfigurationRead = 0xa,
+ PciCommandConfigurationWrite = 0xb,
+ PciCommandMemoryReadMultiple = 0xc,
+ PciCommandDualAddressCycle = 0xd,
+ PciCommandMemoryReadLine = 0xe,
+ PciCommandMemoryWriteAndInvalidate = 0xf,
+ MaximumPciCommand
+} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES;
+
+
+//
+// PCI platform-specific functions
+//
+
diff --git a/private/ntos/nthals/halntp/mips/pmpsup.h b/private/ntos/nthals/halntp/mips/pmpsup.h
new file mode 100644
index 000000000..524d58615
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/pmpsup.h
@@ -0,0 +1,69 @@
+//
+// Define global data used for PMP addresses
+//
+
+extern ULONG GLOBAL_STATUS_PHYSICAL_BASE[];
+extern ULONG GLOBAL_STATUS[];
+extern ULONG GLOBAL_CONTROL_PHYSICAL_BASE[];
+extern ULONG GLOBAL_CONTROL[];
+extern ULONG WHOAMI_PHYSICAL_BASE[];
+extern ULONG WHOAMI_REG[];
+extern ULONG PROC_SYNC_PHYSICAL_BASE[];
+extern ULONG PROC_SYNC[];
+extern ULONG PCI_STATUS_PHYSICAL_BASE[];
+extern ULONG PCI_STATUS[];
+extern ULONG PCI_CONTROL_PHYSICAL_BASE[];
+extern ULONG PCI_CONTROL[];
+extern ULONG PCI_ERR_ACK_PHYSICAL_BASE[];
+extern ULONG PCI_ERR_ACK[];
+extern ULONG PCI_ERR_ADDR_PHYSICAL_BASE[];
+extern ULONG PCI_ERR_ADDRESS[];
+extern ULONG PCI_RETRY_PHYSICAL_BASE[];
+extern ULONG PCI_RETRY[];
+extern ULONG PCI_SPACE_MAP_PHYSICAL_BASE[];
+extern ULONG PCI_SPACE[];
+extern ULONG PCI_CONFIG_ADDR_PHYSICAL_BASE[];
+extern ULONG PCI_CONFIG_ADDRESS[];
+extern ULONG MEM_STATUS_PHYSICAL_BASE[];
+extern ULONG MEM_STATUS[];
+extern ULONG MEM_CONTROL_PHYSICAL_BASE[];
+extern ULONG MEM_CONTROL[];
+extern ULONG MEM_ERR_ACK_PHYSICAL_BASE[];
+extern ULONG MEM_ERR_ACK[];
+extern ULONG MEM_ERR_ADDR_PHYSICAL_BASE[];
+extern ULONG MEM_ERR_ADDRESS[];
+extern ULONG MEM_COUNT_PHYSICAL_BASE[];
+extern ULONG MEM_COUNT[];
+extern ULONG MEM_TIMING_PHYSICAL_BASE[];
+extern ULONG MEM_TIMING[];
+extern ULONG MEM_DIAG_PHYSICAL_BASE[];
+extern ULONG MEM_DIAG[];
+extern ULONG INT_STATUS_PHYSICAL_BASE[];
+extern ULONG INT_STATUS[];
+extern ULONG INT_CONTROL_PHYSICAL_BASE[];
+extern ULONG INT_CTRL[];
+extern ULONG INT_SET_CTRL_PHYSICAL_BASE[];
+extern ULONG INT_SET_CTRL[];
+extern ULONG INT_CLR_CTRL_PHYSICAL_BASE[];
+extern ULONG INT_CLR_CTRL[];
+extern ULONG INT_CAUSE_PHYSICAL_BASE[];
+extern ULONG INT_CAUSE[];
+extern ULONG IP_INT_GEN_PHYSICAL_BASE[];
+extern ULONG IP_INT_GEN[];
+extern ULONG IP_INT_ACK_PHYSICAL_BASE[];
+extern ULONG IP_INT_ACK[];
+extern ULONG PCI_CONFIG_PHYSICAL_BASE[];
+extern ULONG PCI_SPECIAL_PHYSICAL_BASE[];
+extern ULONG PCI_INTERRUPT_PHYSICAL_BASE[];
+extern ULONG IO_INT_ACK_PHYSICAL_BASE[];
+extern ULONG INTERRUPT_PHYSICAL_BASE[];
+
+
+//
+//
+//
+
+extern ULONG MACHINE_ID;
+
+#define FALCON_VERSION_NUMBER_1 0x1
+#define FALCON_VERSION_NUMBER_2 0x2
diff --git a/private/ntos/nthals/halntp/mips/sidewind.h b/private/ntos/nthals/halntp/mips/sidewind.h
new file mode 100644
index 000000000..be6a9ef34
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/sidewind.h
@@ -0,0 +1,447 @@
+/*++
+
+Copyright (c) 1993 NeTpower Incorporated
+
+Module Name:
+
+ sidewinder.h
+
+Abstract:
+
+ This module is the header file that describes hardware
+ structure for sections of the SideWinder device. The
+ contents of this device includes the realtime clock,
+ keyboard controller, serial ports, parallel port,
+ floppy controller and nvram.
+
+Author:
+
+ Hector R. Briones 15-Dec-93
+
+Revision History:
+
+--*/
+
+
+
+#ifndef _SIDEWINDER_
+#define _SIDEWINDER_
+
+
+//
+//------------REALTIME CLOCK - (RTC)-----------------------------------
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_BATTERY_BACKED_UP_RAM 14 // battery backed up RAM [0..49]
+
+#ifndef _LANGUAGE_ASSEMBLY
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+
+//
+//------------SERIAL PORTS - (DUAL UART's)----------------------
+//
+// Define serial port read registers structure.
+//
+
+typedef struct _SP_READ_REGISTERS {
+ UCHAR ReceiveBuffer;
+ UCHAR InterruptEnable;
+ UCHAR InterruptId;
+ UCHAR LineControl;
+ UCHAR ModemControl;
+ UCHAR LineStatus;
+ UCHAR ModemStatus;
+ UCHAR ScratchPad;
+} SP_READ_REGISTERS, *PSP_READ_REGISTERS;
+
+//
+// Define define serial port write registers structure.
+//
+
+typedef struct _SP_WRITE_REGISTERS {
+ UCHAR TransmitBuffer;
+ UCHAR InterruptEnable;
+ UCHAR FifoControl;
+ UCHAR LineControl;
+ UCHAR ModemControl;
+ UCHAR Reserved1;
+ UCHAR ModemStatus;
+ UCHAR ScratchPad;
+} SP_WRITE_REGISTERS, *PSP_WRITE_REGISTERS;
+
+//
+// Define serial port interrupt enable register structure.
+//
+
+typedef struct _SP_INTERRUPT_ENABLE {
+ UCHAR ReceiveEnable : 1;
+ UCHAR TransmitEnable : 1;
+ UCHAR LineStatusEnable : 1;
+ UCHAR ModemStatusEnable : 1;
+ UCHAR Reserved1 : 4;
+} SP_INTERRUPT_ENABLE, *PSP_INTERRUPT_ENABLE;
+
+//
+// Define serial port interrupt id register structure.
+//
+
+typedef struct _SP_INTERRUPT_ID {
+ UCHAR InterruptPending : 1;
+ UCHAR Identification : 3;
+ UCHAR Reserved1 : 2;
+ UCHAR FifoEnabled : 2;
+} SP_INTERRUPT_ID, *PSP_INTERRUPT_ID;
+
+//
+// Define serial port fifo control register structure.
+//
+
+typedef struct _SP_FIFO_CONTROL {
+ UCHAR FifoEnable : 1;
+ UCHAR ReceiveFifoReset : 1;
+ UCHAR TransmitFifoReset : 1;
+ UCHAR DmaModeSelect : 1;
+ UCHAR Reserved1 : 2;
+ UCHAR ReceiveFifoLevel : 2;
+} SP_FIFO_CONTROL, *PSP_FIFO_CONTROL;
+
+//
+// Define serial port line control register structure.
+//
+
+typedef struct _SP_LINE_CONTROL {
+ UCHAR CharacterSize : 2;
+ UCHAR StopBits : 1;
+ UCHAR ParityEnable : 1;
+ UCHAR EvenParity : 1;
+ UCHAR StickParity : 1;
+ UCHAR SetBreak : 1;
+ UCHAR DivisorLatch : 1;
+} SP_LINE_CONTROL, *PSP_LINE_CONTROL;
+
+#endif // _LANGUAGE_ASSEMBLY
+//
+// Line status register character size definitions.
+//
+
+#define FIVE_BITS 0x0 // five bits per character
+#define SIX_BITS 0x1 // six bits per character
+#define SEVEN_BITS 0x2 // seven bits per character
+#define EIGHT_BITS 0x3 // eight bits per character
+
+//
+// Line speed divisor definition.
+//
+
+#define BAUD_RATE_9600 12 // divisor for 9600 baud
+#define BAUD_RATE_19200 6 // divisor for 19200 baud
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Define serial port modem control register structure.
+//
+
+typedef struct _SP_MODEM_CONTROL {
+ UCHAR DataTerminalReady : 1;
+ UCHAR RequestToSend : 1;
+ UCHAR Reserved1 : 1;
+ UCHAR Interrupt : 1;
+ UCHAR loopBack : 1;
+ UCHAR Reserved2 : 3;
+} SP_MODEM_CONTROL, *PSP_MODEM_CONTROL;
+
+//
+// Define serial port line status register structure.
+//
+
+typedef struct _SP_LINE_STATUS {
+ UCHAR DataReady : 1;
+ UCHAR OverrunError : 1;
+ UCHAR ParityError : 1;
+ UCHAR FramingError : 1;
+ UCHAR BreakIndicator : 1;
+ UCHAR TransmitHoldingEmpty : 1;
+ UCHAR TransmitEmpty : 1;
+ UCHAR ReceiveFifoError : 1;
+} SP_LINE_STATUS, *PSP_LINE_STATUS;
+
+//
+// Define serial port modem status register structure.
+//
+
+typedef struct _SP_MODEM_STATUS {
+ UCHAR DeltaClearToSend : 1;
+ UCHAR DeltaDataSetReady : 1;
+ UCHAR TrailingRingIndicator : 1;
+ UCHAR DeltaReceiveDetect : 1;
+ UCHAR ClearToSend : 1;
+ UCHAR DataSetReady : 1;
+ UCHAR RingIndicator : 1;
+ UCHAR ReceiveDetect : 1;
+} SP_MODEM_STATUS, *PSP_MODEM_STATUS;
+
+//
+//-------------------SUPER IO control----------------------------
+//
+//
+// SIDEWINDER Index and Data Registers
+//
+typedef struct _SUPERIO_CONFIG_REGISTERS {
+ UCHAR Index;
+ UCHAR Data;
+} SUPERIO_CONFIG_REGISTERS, *PSUPERIO_CONFIG_REGISTERS;
+
+#endif // LANGUAGE_ASSEMBLY
+
+#define SUPERIO_INDEX_REG (SIDEWINDER_VIRTUAL_BASE + 0x398)
+#define SUPERIO_DATA_REG (SIDEWINDER_VIRTUAL_BASE + 0x399)
+
+//
+// SideWinder Configuration registers
+//
+#define SUPERIO_FER_INDEX 0x0
+#define SUPERIO_FAR_INDEX 0x1
+#define SUPERIO_PTR_INDEX 0x2
+#define SUPERIO_FCR_INDEX 0x3
+#define SUPERIO_PCR_INDEX 0x4
+
+#define SIO_INDEX_REG 0x398
+#define SIO_DATA_REG 0x399
+
+//
+// KRR register index and
+// bit definitions
+//
+#define SUPERIO_KRR_INDEX 0x05
+#define SUPERIO_KRR_KBCE 0x01
+#define SUPERIO_KRR_PAE 0x04
+#define SUPERIO_KRR_RTCTEST 0x10
+#define SUPERIO_KRR_RAMU128B 0x20
+#define SUPERIO_KRR_ADE 0x40
+#define SUPERIO_KRR_RTCE 0x08
+//
+// New register definitions in the latest spec
+// from NATIONAL - February 1994
+//
+#define SUPERIO_PMC_INDEX 0x06
+#define SUPERIO_TUPP_INDEX 0x07
+#define SUPERIO_SIOID_INDEX 0x08
+#define SUPERIO_ASIOC_INDEX 0x09
+#define SUPERIO_CS0R0_INDEX 0x0a
+#define SUPERIO_CS0R1_INDEX 0x0b
+#define SUPERIO_CS1R0_INDEX 0x0c
+#define SUPERIO_CS1R1_INDEX 0x0d
+
+//
+// Real-time clock (RTC) index
+// and data register definitions
+//
+
+#define RTC_INDEX_REG 0x70
+#define RTC_DATA_REG 0x71
+
+//
+// RTC register A index and
+// bit definitions
+//
+
+#define RTC_REGA_INDEX 0x0A
+#define RTC_REGA_UIP 0x80
+#define RTC_REGA_DV2 0x40
+#define RTC_REGA_DV1 0x20
+#define RTC_REGA_DV0 0x10
+#define RTC_REGA_RS3 0x08
+#define RTC_REGA_RS2 0x04
+#define RTC_REGA_RS1 0x02
+#define RTC_REGA_RS0 0x01
+
+//
+// RTC register B index and
+// bit definitions
+//
+
+#define RTC_REGB_INDEX 0x0B
+#define RTC_REGB_SET 0x80
+#define RTC_REGB_PIE 0x40
+#define RTC_REGB_AIE 0x20
+#define RTC_REGB_UIE 0x10
+#define RTC_REGB_SWE 0x08
+#define RTC_REGB_DM 0x04
+#define RTC_REGB_24_12 0x02
+#define RTC_REGB_DSE 0x01
+
+//
+// RTC register C index and
+// bit definitions
+//
+
+#define RTC_REGC_INDEX 0x0C
+#define RTC_REGC_IRQF 0x80
+#define RTC_REGC_PF 0x40
+#define RTC_REGB_AF 0x20
+#define RTC_REGB_UF 0x10
+
+//
+// RTC register D index and
+// bit definitions
+//
+
+#define RTC_REGD_INDEX 0x0D
+#define RTC_REGD_VRT 0x80
+
+
+//
+// SideWinder Function Enable Register (FER) bit definitions
+//
+#define SUPERIO_FER_LPT_EN 0x1
+#define SUPERIO_FER_UART1_EN 0x2
+#define SUPERIO_FER_UART2_EN 0x4
+#define SUPERIO_FER_FDC_EN 0x8
+#define SUPERIO_FER_ENABLEALL 0xf // Enable LPT, UART1, UART2 & FDC Primary address= 0x3F0-0x3F7
+
+//
+// SideWinder Function Address Register (FAR) bit definitions
+//
+#define SUPERIO_FAR_LPT1_ADDR 0x1 // LPT1 Address: 0x3BC - 0x3BE
+#define SUPERIO_FAR_LPT2_ADDR 0x0
+#define SUPERIO_FAR_LPT3_ADDR 0x2
+#define SUPERIO_FAR_UART_PRI_ADDR 0x10 // UART1 Address: 0x3F8-0x3FF/UART2 Address: 0x2F8-0x2FF
+#define SUPERIO_FAR_UART1_MASK 0x0C
+#define SUPERIO_FAR_UART1_COM1 0x00
+#define SUPERIO_FAR_UART1_COM2 0x04
+#define SUPERIO_FAR_UART1_COM3 0x08
+#define SUPERIO_FAR_UART1_COM4 0x0C
+#define SUPERIO_FAR_UART2_MASK 0x30
+#define SUPERIO_FAR_UART2_COM1 0x00
+#define SUPERIO_FAR_UART2_COM2 0x10
+#define SUPERIO_FAR_UART2_COM3 0x20
+#define SUPERIO_FAR_UART2_COM4 0x30
+#define SUPERIO_FAR_COM34_ADDR_MASK 0xC0
+
+//
+// Sidewinder Function Enable Register (PTR) bit definitions
+//
+#define SUPERIO_PTR_ENABLE_OSC 0x4
+
+
+//
+//---------------SERIAL PORT 1 -- (UART)-----------------------
+//
+// Define serial port register addresses
+//
+#define SP0_RECEIVEBUFFER COMPORT1_VIRTUAL_BASE
+#define SP0_TRANSMITBUFFER COMPORT1_VIRTUAL_BASE
+#define SP0_INTERRUPTENABLE (COMPORT1_VIRTUAL_BASE + 1)
+#define SP0_INTERRUPTID (COMPORT1_VIRTUAL_BASE + 2)
+#define SP0_FIFOCONTROL (COMPORT1_VIRTUAL_BASE + 2)
+#define SP0_LINECONTROL (COMPORT1_VIRTUAL_BASE + 3)
+#define SP0_MODEMCONTROL (COMPORT1_VIRTUAL_BASE + 4)
+#define SP0_LINESTATUS (COMPORT1_VIRTUAL_BASE + 5)
+#define SP0_MODEMSTATUS (COMPORT1_VIRTUAL_BASE + 6)
+#define SP0_SCRATCHPAD (COMPORT1_VIRTUAL_BASE + 7)
+#define SP0_DIVLATCHLSB (COMPORT1_VIRTUAL_BASE + 8)
+#define SP0_DIVLATCHMSB (COMPORT1_VIRTUAL_BASE + 9)
+
+
+//
+//---------------SERIAL PORT 2 -- (UART)-----------------------
+//
+// Define serial port register addresses
+//
+#define SP1_RECEIVEBUFFER COMPORT2_VIRTUAL_BASE
+#define SP1_TRANSMITBUFFER COMPORT2_VIRTUAL_BASE
+#define SP1_INTERRUPTENABLE (COMPORT2_VIRTUAL_BASE + 1)
+#define SP1_INTERRUPTID (COMPORT2_VIRTUAL_BASE + 2)
+#define SP1_FIFOCONTROL (COMPORT2_VIRTUAL_BASE + 2)
+#define SP1_LINECONTROL (COMPORT2_VIRTUAL_BASE + 3)
+#define SP1_MODEMCONTROL (COMPORT2_VIRTUAL_BASE + 4)
+#define SP1_LINESTATUS (COMPORT2_VIRTUAL_BASE + 5)
+#define SP1_MODEMSTATUS (COMPORT2_VIRTUAL_BASE + 6)
+#define SP1_SCRATCHPAD (COMPORT2_VIRTUAL_BASE + 7)
+#define SP1_DIVLATCHLSB COMPORT2_VIRTUAL_BASE
+#define SP1_DIVLATCHMSB (COMPORT2_VIRTUAL_BASE + 1)
+
+
+#define SP_LINECNTRL_DIVLAT_EN 0x80 // Divisor Latch bit
+
+#define SP_LINESTATUS_RXRDY 0x01 // Rx Ready (Rx Buffer full)
+#define SP_LINESTATUS_TXRDY 0x40 // Tx Ready (Tx buffer empty)
+
+#define SP_FIFOCNTRL_ENABLE 0x01 // Enable Rx and Tx Fifo
+#define SP_FIFOCNTRL_RXRST 0x02 // Rx Fifo reset
+#define SP_FIFOCNTRL_TXRST 0x04 // Tx Fifo reset
+
+#define SP_MODEMCNTRL_DTR 0x01 // DataTerminalReady
+#define SP_MODEMCNTRL_RTS 0x02 // RequestToSend
+
+
+//
+// Temporary defines (Don't know where to put them yet...)
+//
+#define ASCLF 0xa
+#define ASCCR 0xd
+#define ASCNUL 0x0
+
+#endif //_SIDEWINDER_
diff --git a/private/ntos/nthals/halntp/mips/vga.h b/private/ntos/nthals/halntp/mips/vga.h
new file mode 100644
index 000000000..38f4cda87
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/vga.h
@@ -0,0 +1,343 @@
+/*++
+
+Copyright (c) 1993, NeTpower, Inc. All rights reserved.
+
+Module Name:
+
+ vga.h
+
+Abstract:
+
+ Standard VGA support header file. Everything needed to initialize,
+ and talk to standard VGA cards on either the PICA or the ISA bus.
+
+ Reference: Programmers Guide to the EGA and VGA, Second Edition.
+ by Richard F. Ferraro. ISBN 0-201-57025-4, 1990.
+
+Author:
+
+ Mike Dove (mdove), 8-Oct-93
+
+--*/
+
+#ifndef _VGA_
+#define _VGA_
+
+//
+// Set up typedef's for the VGA ports. Depending on whether you are
+// reading or writing, some of the registers appear at different addresses.
+// Therefore, there are two typedef structures defined depending on
+// whether you are doing reads or writes... These registers start at
+// offset 0x3C0.
+//
+
+typedef volatile struct _VGA_READ_PORT {
+ /* 000 */ UCHAR None_0[0x102];
+ /* 102 */ UCHAR SetupOptionSelect; // S3 only...
+ /* 103 */ UCHAR None_1[0x2be];
+ /* 3C1 */ UCHAR AttributeAddressAndData;
+ /* 3C2 */ UCHAR InputStatus0;
+ /* 3C3 */ UCHAR None_2;
+ /* 3C4 */ UCHAR SequencerAddress;
+ /* 3C5 */ UCHAR SequencerData;
+ /* 3C6 */ UCHAR PELMask;
+ /* 3C7 */ UCHAR DACState;
+ /* 3C8 */ UCHAR PELAddressWriteMode;
+ /* 3C9 */ UCHAR PELData;
+ /* 3CA */ UCHAR FeatureControl;
+ /* 3CB */ UCHAR None_3;
+ /* 3CC */ UCHAR MiscOutput;
+ /* 3CD */ UCHAR None_4;
+ /* 3CE */ UCHAR GraphicsAddress;
+ /* 3CF */ UCHAR GraphicsData;
+ /* 3D0 */ UCHAR None_5[4];
+ /* 3D4 */ UCHAR CRTCAddress;
+ /* 3D5 */ UCHAR CRTCData;
+ /* 3D6 */ UCHAR None_6[4];
+ /* 3DA */ UCHAR InputStatus1;
+} VGA_READ_PORT, *PVGA_READ_PORT;
+
+typedef volatile struct _VGA_WRITE_PORT {
+ /* 000 */ UCHAR None_0[0x102];
+ /* 102 */ UCHAR SetupOptionSelect; // S3 only...
+ /* 103 */ UCHAR None_1[0x2bd];
+ /* 3C0 */ UCHAR AttributeAddressAndData;
+ /* 3C1 */ UCHAR None_2;
+ /* 3C2 */ UCHAR MiscOutput;
+ /* 3C3 */ UCHAR None_3;
+ /* 3C4 */ UCHAR SequencerAddress;
+ /* 3C5 */ UCHAR SequencerData;
+ /* 3C6 */ UCHAR PELMask;
+ /* 3C7 */ UCHAR PELAddressReadMode;
+ /* 3C8 */ UCHAR PELAddressWriteMode;
+ /* 3C9 */ UCHAR PELData;
+ /* 3CA */ UCHAR None_4[4];
+ /* 3CE */ UCHAR GraphicsAddress;
+ /* 3CF */ UCHAR GraphicsData;
+ /* 3D0 */ UCHAR None_5[4];
+ /* 3D4 */ UCHAR CRTCAddress;
+ /* 3D5 */ UCHAR CRTCData;
+ /* 3D6 */ UCHAR None_6[4];
+ /* 3DA */ UCHAR FeatureControl;
+ /* 3DB */ UCHAR None_7[0x3f0d];
+ /* 42E8 */ USHORT SubsystemControlRegister; // S3 only...
+ /* 42E9 */ UCHAR None_8[0x3fe];
+ /* 46E8 */ UCHAR VideoSubsystemEnable; // S3 only...
+ /* 46E9 */ UCHAR None_9[0x3ff];
+ /* 4AE8 */ USHORT AdvancedFunctionControl; // S3 only...
+
+} VGA_WRITE_PORT, *PVGA_WRITE_PORT;
+
+//
+// The following #defines represent the indexes used for the Address/Data
+// register sets. The data for the *Setup arrays was taken from pages 318-319
+// in the Programmers Guide to the EGA and VGA for video mode 3.
+//
+
+// Sequencer Registers
+
+#define SEQ_RESET 0
+#define SYNCHRONUS_RESET 0x01
+#define NORMAL_OPERATION 0x03
+#define SEQ_CLOCKING_MODE 1
+#define SEQ_MAP_MASK 2
+#define ENABLE_PLANE_2 0x04
+#define SEQ_CHARACTER_MAP_SELECT 3
+#define SEQ_MEMORY_MODE 4
+#define SEQUENTIAL_ADDRESSING 0x04
+#define EXTENDED_MEMORY 0x02
+
+static UCHAR SequencerSetup[] = {
+ 0x03, // Reset
+ 0x00, // Clocking Mode
+ 0x03, // Map Mask
+ 0x00, // Character Map Select
+ 0x02, // Memory Mode
+};
+
+
+// CRT Controller Registers
+
+#define CRT_HORIZONTAL_TOTAL 0
+#define CRT_HORIZONTAL_DISPLAY_END 1
+#define CRT_START_HORIZONTAL_BLANKING 2
+#define CRT_END_HORIZONTAL_BLANKING 3
+#define CRT_START_HORIZONTAL_RETRACE 4
+#define CRT_END_HORIZONTAL_RETRACE 5
+#define CRT_VERTICAL_TOTAL 6
+#define CRT_OVERFLOW 7
+#define CRT_PRESET_ROW_SCAN 8
+#define CRT_MAXIMUM_SCAN_LINE 9
+#define CRT_CURSOR_START 10
+#define CRT_CURSOR_END 11
+#define CRT_START_ADDRESS_HIGH 12
+#define CRT_START_ADDRESS_LOW 13
+#define CRT_CURSOR_LOCATION_HIGH 14
+#define CRT_CURSOR_LOCATION_LOW 15
+#define CRT_VERTICAL_RETRACE_START 16
+#define CRT_VERTICAL_RETRACE_END 17
+#define CRT_VERTICAL_DISPLAY_END 18
+#define CRT_OFFSET 19
+#define CRT_UNDERLINE_LOCATION 20
+#define CRT_START_VERTICAL_BLANK 21
+#define CRT_END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define CRT_LINE_COMPARE 24
+
+static UCHAR CRTCSetup[] = {
+ 0x5f, // Horizontal Total
+ 0x4f, // Horizontal Display End
+ 0x50, // Start Horizontal Blanking
+ 0x82, // End Horizontal Blanking
+ 0x55, // Start Horizontal Retrace
+ 0x81, // End Horizontal Retrace
+ 0xbf, // Vertical Total
+ 0x1f, // Overflow
+ 0x00, // Preset Row Scan
+ 0x4b, // Maximum Scan Line - Changes: 2T4 turned off, 12 row characters
+ 0x0e, // Cursor Start - Changes: 16 row characters, move cursor down
+ 0x0f, // Cursor End - Changes: 16 row characters, move cursor down
+ 0x00, // Start Address High
+ 0x00, // Start Address Low
+ 0x00, // Cursor Location High
+ 0x00, // Cursor Location Low - Changes: Start at 0
+ 0x9c, // Vertical Retrace Start
+ 0x8e, // Vertical Retrace End - also write protects CRT registers 0-7.
+ 0x8f, // Vertical Display End
+ 0x28, // Offset
+ 0x1f, // Underline Location
+ 0x96, // Start Vertical Blank
+ 0xb9, // End Vertical Blank
+ 0xa3, // Mode Control
+ 0xff, // Line Compare
+};
+
+// Graphics Registers
+
+#define GFX_SET_RESET 0
+#define GFX_ENABLE_SET_RESET 1
+#define GFX_COLOR_COMPARE 2
+#define GFX_DATA_ROTATE 3
+#define GFX_READ_MAP_SELECT 4
+#define GFX_MODE 5
+#define WRITE_MODE_0 0x00
+#define GFX_MISCELLANEOUS 6
+#define MEMORY_MODE_1 0x04
+#define ALPHA_MODE 0x00
+#define GFX_COLOR_DONT_CARE 7
+#define GFX_BIT_MASK 8
+
+static UCHAR GraphicsSetup[] = {
+ 0x00, // Set/Reset
+ 0x00, // Enable Set/Reset
+ 0x00, // Color Compare
+ 0x00, // Data Rotate
+ 0x00, // Read Map Select
+ 0x10, // Mode
+ 0x0e, // Miscellaneous
+ 0x00, // Color Don't Care
+ 0xff, // Bit Mask
+};
+
+// Attribute Registers
+
+#define ATT_PALETTE_00 0
+#define ATT_PALETTE_01 1
+#define ATT_PALETTE_02 2
+#define ATT_PALETTE_03 3
+#define ATT_PALETTE_04 4
+#define ATT_PALETTE_05 5
+#define ATT_PALETTE_06 6
+#define ATT_PALETTE_07 7
+#define ATT_PALETTE_08 8
+#define ATT_PALETTE_09 9
+#define ATT_PALETTE_10 10
+#define ATT_PALETTE_11 11
+#define ATT_PALETTE_12 12
+#define ATT_PALETTE_13 13
+#define ATT_PALETTE_14 14
+#define ATT_PALETTE_15 15
+#define ATT_MODE 16
+#define ATT_OVERSCAN_COLOR 17
+#define ATT_COLOR_PLANE_ENABLE 18
+#define ATT_HORIZONTAL_PIXEL_PANNING 19
+#define ATT_COLOR_SELECT 20
+
+static UCHAR AttributeSetup[] = {
+ 0x00, // Palette 00 Index - Black
+ 0x01, // Palette 01 Index - Red
+ 0x02, // Palette 02 Index - Green
+ 0x03, // Palette 03 Index - Yellow
+ 0x04, // Palette 04 Index - Blue
+ 0x05, // Palette 05 Index - Magenta
+ 0x06, // Palette 06 Index - Cyan
+ 0x07, // Palette 07 Index - White
+ 0x08, // Palette 08 Index - Intense Black (read Grey)
+ 0x09, // Palette 09 Index - Intense Red
+ 0x0a, // Palette 10 Index - Intense Green
+ 0x0b, // Palette 11 Index - Intense Yellow
+ 0x0c, // Palette 12 Index - Intense Blue
+ 0x0d, // Palette 13 Index - Intense Magenta
+ 0x0e, // Palette 14 Index - Intense Cyan
+ 0x0f, // Palette 15 Index - Intense White
+ 0x04, // Mode
+ 0x00, // Overscan Color
+ 0x0F, // Color Plane Enable
+ 0x08, // Horizontal Pixel Panning
+ 0x00, // Color Select
+};
+
+static UCHAR ColorValues[16][3] = {
+// Red Grn Blue
+ 00, 00, 00, // Black
+ 42, 00, 00, // Red
+ 00, 42, 00, // Green
+ 42, 21, 00, // Brown
+ 00, 00, 42, // Blue
+ 42, 00, 42, // Magenta
+ 00, 42, 42, // Cyan
+ 42, 42, 42, // White
+ 21, 21, 21, // Intense Black (read Grey)
+ 63, 21, 21, // Intense Red
+ 21, 63, 21, // Intense Green
+ 63, 63, 21, // Intense Brown
+ 21, 21, 63, // Intense Blue
+ 63, 21, 63, // Intense Magenta
+ 21, 63, 63, // Intense Cyan
+ 63, 63, 63, // Intense White
+};
+
+#define COLOR_BLACK 0
+#define COLOR_RED 1
+#define COLOR_GREEN 2
+#define COLOR_BROWN 3
+#define COLOR_BLUE 4
+#define COLOR_MAGENTA 5
+#define COLOR_CYAN 6
+#define COLOR_WHITE 7
+#define COLOR_GREY 8
+#define COLOR_INTENSE_RED 9
+#define COLOR_INTENSE_GREEN 10
+#define COLOR_INTENSE_BROWN 11
+#define COLOR_INTENSE_BLUE 12
+#define COLOR_INTENSE_MAGENTA 13
+#define COLOR_INTENSE_CYAN 14
+#define COLOR_INTENSE_WHITE 15
+
+// Other register bit definitions...
+
+// Miscellaneous Output Register
+#define IOA_COLOR 0x01
+#define ER_ENABLE 0x02
+#define CS_25MHZ 0x00
+#define CS_28MHZ 0x04
+#define CS_ENHANCED 0x06
+#define DVD_ENABLE 0x00
+#define PB_HIGH64K 0x20
+#define HSP_NEGATIVE 0x40
+#define VSP_POSITIVE 0x00
+#define VSP_NEGATIVE 0x80
+#define INITIAL_CONFIG ( IOA_COLOR \
+ | ER_ENABLE \
+ | CS_ENHANCED \
+ | DVD_ENABLE \
+ | PB_HIGH64K \
+ | HSP_NEGATIVE \
+ | VSP_POSITIVE \
+ )
+
+// S3 specific #defines
+
+#define ENTER_SETUP_MODE 0x10
+#define ENABLE_VIDEO_SUBSYSTEM 0x08
+#define VIDEO_SUBSYSTEM_ALIVE 0x01
+
+#define S3_CHIP_ID 0x30
+#define S3_MEMORY_CONFIGURATION 0x31
+#define S3_BACKWARD_COMPATIBILITY_1 0x32
+#define S3_BACKWARD_COMPATIBILITY_2 0x33
+#define S3_BACKWARD_COMPATIBILITY_3 0x34
+#define S3_CRT_REGISTER_LOCK 0x35
+#define S3_CONFIGURATION_1 0x36
+#define S3_CONFIGURATION_2 0x37
+#define S3_REGISTER_LOCK_1 0x38
+#define S3_REGISTER_LOCK_2 0x39
+#define S3_MISCELLANEOUS_1 0x3a
+#define S3_DATA_TRANSFER_EXECUTE 0x3b
+#define S3_INTERLACE_RETRACE_START 0x3c
+#define S3_SYSTEM_CONFIGURATION 0x40
+#define S3_MODE_CONTROL 0x42
+#define S3_EXTENDED_MODE 0x43
+#define S3_HARDWARE_GRAPHICS_CURSOR 0x45
+#define S3_EXTENDED_MEMORY_CONTROL_1 0x53
+#define S3_EXTENDED_MEMORY_CONTROL_2 0x54
+#define S3_LINEAR_ADDRESS_WINDOW_HIGH 0x59
+#define S3_LINEAR_ADDRESS_WINDOW_LOW 0x5A
+
+
+// Other #defines
+
+#define SPACE 0x20 // Ascii space
+
+#endif
+
diff --git a/private/ntos/nthals/halntp/mips/x4clock.s b/private/ntos/nthals/halntp/mips/x4clock.s
new file mode 100644
index 000000000..b40d0e102
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/x4clock.s
@@ -0,0 +1,338 @@
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+//--
+
+#include "halmips.h"
+#include "faldef.h"
+
+
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+
+ //
+ // Clear Timer interrupt by reading
+ // TimerIntAck register in PMP chip
+ // only if this is PMP_V3 or later.
+ // NOTE: There are NO PMP_V1 in existence,
+ // therefore only checking that PMP_V2
+ // or NOT PMP_V2.
+ //
+ la t0, HalpPmpRevision
+ lw t1, 0(t0)
+ li t2, 2
+ beq t1, t2, 2f
+ nop
+
+ lw t0, HalpPmpTimerIntAck
+ lw t0, 0(t0)
+
+2:
+
+ .set reorder
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20:
+
+ beq zero,t1,30f // if eq, not interval count change
+ sw zero,HalpNextIntervalCount // clear next interval count
+
+ .set noreorder
+
+ //
+ // Determine which version of
+ // the PMP we have so we can
+ // update the correct counter
+ // in the 82374.
+ //
+ // NOTE: Any machine with PMP_V2
+ // uses Counter 0. Any machine
+ // with PMP_V3 or better uses
+ // Counter 2.
+ //
+ la a0, HalpPmpRevision
+ lw a0, 0(a0)
+ li a1, 2
+ beq a0, a1, 3f
+ nop
+
+ //
+ // Set next interval count for
+ // Timer 1, Counter 2
+ //
+ lw a0, HalpEisaControlBase
+ li a2, 0xB6 // Counter2, r/w LSB then MSB, Mode 3
+ sb a2, 0x43(a0)
+ sb t1, 0x42(a0)
+ srl a1, t1, 8
+ b 4f
+ sb a1, 0x42(a0)
+
+3:
+ //
+ // Set next interval count for
+ // Timer 1, Counter 0
+ //
+ lw a0, HalpEisaControlBase
+ li a2, 0x36 // Counter0, r/w LSB then MSB, Mode 3
+ sb a2, 0x43(a0)
+ sb t1, 0x40(a0)
+ srl a1, t1, 8
+ sb a1, 0x40(a0)
+
+4:
+
+ .set reorder
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+ //
+ // clear Timer interrupt by reading
+ // TimerIntAck register in PMP chip
+ // only if this is not the first
+ // version of the PMP chip.
+ //
+ lw t0, HalpPmpTimerIntAckProcB
+ lw t0, 0(t0)
+
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1
+
+
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+
diff --git a/private/ntos/nthals/halntp/mips/x4tb.s b/private/ntos/nthals/halntp/mips/x4tb.s
new file mode 100644
index 000000000..6d01e3a1d
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/x4tb.s
@@ -0,0 +1,109 @@
+#if defined(R4000)
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpFreeTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halntp/mips/x86bios.c b/private/ntos/nthals/halntp/mips/x86bios.c
new file mode 100644
index 000000000..f91a4d6f7
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/x86bios.c
@@ -0,0 +1,260 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, HalpEisaControlBase, HalpEisaMemoryBase ) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+
+ //
+ // HACK ALERT!
+ //
+ // Some video BIOS touch hardware OTHER than the video card. In one case, the
+ // #9 S3 928 GXE card we are using, the video BIOS touches the speaker timer,
+ // and disables it when it is done. This is a bad assumption that you can rely
+ // on anything else in the system other than the card the BIOS is on.
+ //
+ // This routine will check the status of the speaker timer and reset it if needed.
+ //
+
+ HalpCheckSystemTimer();
+
+ return TRUE;
+}
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (HalpEisaControlBase == NULL || HalpEisaMemoryBase == NULL) {
+ return;
+ }
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpEisaControlBase, HalpEisaMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+ //
+ // The default ROM bios video modes turn the blinking underline cursor on which
+ // is extreemely annoying. Make an INT 10 call to set the cursor type. By setting
+ // the starting scan line for the cursor > the ending scan line for the cursor
+ // turns the cursor off.
+ //
+
+ Context.Eax = 0x0100; // Function 1, Mode 0
+ Context.Ebx = 0;
+ Context.Ecx = 0x1F1E; // Starting > Ending == Cursor Off
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+ return;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
diff --git a/private/ntos/nthals/halntp/mips/xxcalstl.c b/private/ntos/nthals/halntp/mips/xxcalstl.c
new file mode 100644
index 000000000..cb0f11db6
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/xxcalstl.c
@@ -0,0 +1,273 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+
+#include "halp.h"
+#include "stdio.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 1) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (TIME_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+#if HALDBG
+ if ( ( HalpStallStart == 0 ) || ( HalpStallEnd == 0 ) ) {
+ HalDisplayString("HAL: StallScaleFactor BAD!\r\n");
+ }
+#endif // HALDBG
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt0;
+ PCR->InterruptRoutine[IRQL0_VECTOR] = HalpClockInterrupt0;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the interval timer interrupt.
+ //
+
+ if (HalpPmpRevision >= 3) {
+
+ READ_REGISTER_ULONG(HalpPmpTimerIntAck);
+
+ }
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+ HalpWriteCompareRegisterAndClear(0);
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halntp/mips/xxclock.c b/private/ntos/nthals/halntp/mips/xxclock.c
new file mode 100644
index 000000000..916981bd4
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/xxclock.c
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// Define clock count and time table.
+//
+
+typedef struct _COUNT_ENTRY {
+ ULONG Count;
+ ULONG Time;
+} COUNT_ENTRY, *PCOUNT_ENTRY;
+
+//
+// Define coutner table entries.
+//
+
+COUNT_ENTRY TimeTable[] = {
+ {1197, 10032},
+ {2394, 20064},
+ {3591, 30096},
+ {4767, 39952},
+ {5964, 49984},
+ {7161, 60016},
+ {8358, 70048},
+ {9555, 80080},
+ {10731, 89936},
+ {11928, 99968}
+ };
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // The new clock count value is selected from a precomputed table of
+ // count/time pairs. The values in the table were selected for their
+ // accuracy and closeness to the values of 1ms, 2ms, 3ms, etc. to 10ms.
+ //
+ // N.B. The NT executive guarantees that this function will never
+ // be called with the desired increment less than the minimum
+ // increment or greater than the maximum increment.
+ //
+
+ for (Index = 0; Index < sizeof(TimeTable) / sizeof(COUNT_ENTRY); Index += 1) {
+ if (DesiredIncrement <= TimeTable[Index].Time) {
+ break;
+ }
+ }
+
+ if (DesiredIncrement < TimeTable[Index].Time) {
+ Index -= 1;
+ }
+
+ HalpNextIntervalCount = TimeTable[Index].Count;
+ HalpNewTimeIncrement = TimeTable[Index].Time;
+ KeLowerIrql(OldIrql);
+ return TimeTable[Index].Time;
+}
diff --git a/private/ntos/nthals/halntp/mips/xxidle.s b/private/ntos/nthals/halntp/mips/xxidle.s
new file mode 100644
index 000000000..b577c862d
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/xxidle.s
@@ -0,0 +1,75 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halntp/mips/xxinithl.c b/private/ntos/nthals/halntp/mips/xxinithl.c
new file mode 100644
index 000000000..130719c72
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/xxinithl.c
@@ -0,0 +1,774 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+
+--*/
+
+
+#include "halp.h"
+
+
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Define bug check information buffer and callback record.
+//
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG Info0;
+ ULONG Info1;
+ ULONG Info2;
+ ULONG Info3;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+extern int sprintf();
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ PCR->DataBusError = HalpDataBusErrorHandler;
+
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set synchronization IRQL to dispatch level.
+ //
+
+ KeSetSynchIrql(DISPATCH_LEVEL);
+ if (Prcb->Number == 0) {
+
+ //
+ // Processor A will NULL the following
+ // pointers prior to any HAL mappings
+ // being setup. This will allow us to
+ // simplify some checks in the system
+ // interrupt dispatcher due to the
+ // on-the-fly mapping mess ...
+ //
+
+ HalpPmpIoIntAck = (PVOID)NULL;
+ HalpPmpIntCause = (PVOID)NULL;
+ HalpPmpIntStatus = (PVOID)NULL;
+ HalpPmpIntCtrl = (PVOID)NULL;
+ HalpPmpIntSetCtrl = (PVOID)NULL;
+ HalpPmpTimerIntAck = (PVOID)NULL;
+ HalpPmpIntClrCtrl = (PVOID)NULL;
+ HalpPmpMemErrAck = (PVOID)NULL;
+ HalpPmpMemErrAddr = (PVOID)NULL;
+ HalpPmpPciErrAck = (PVOID)NULL;
+ HalpPmpPciErrAddr = (PVOID)NULL;
+ HalpPmpIpIntAck = (PVOID)NULL;
+ HalpPmpIpIntGen = (PVOID)NULL;
+ HalpPmpPciConfigSpace = (PVOID)NULL;
+ HalpPmpPciConfigAddr = (PVOID)NULL;
+ HalpPmpPciConfigSelect = (PVOID)NULL;
+
+ //
+ // These are the ProcessorB specific
+ // pointers
+ //
+
+ HalpPmpIntStatusProcB = (PVOID)NULL;
+ HalpPmpIntCtrlProcB = (PVOID)NULL;
+ HalpPmpIntSetCtrlProcB = (PVOID)NULL;
+ HalpPmpTimerIntAckProcB = (PVOID)NULL;
+ HalpPmpIntClrCtrlProcB = (PVOID)NULL;
+ HalpPmpIpIntAckProcB = (PVOID)NULL;
+
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+
+ //
+ // Register cascade vector
+ //
+
+ HalpRegisterVector (InternalUsage,
+ IRQL2_VECTOR,
+ IRQL2_VECTOR,
+ HIGH_LEVEL );
+
+ //
+ // Register base IO space used by HAL
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ HalpClearScreenToBlue( 5 );
+ HalDisplayString("\r\n Prepare to experience Ultimate Windows NT Performance...\r\n\r\n");
+ HalDisplayString(" NeTpower FASTseries\r\n\r\n\r\n\r\n");
+
+
+ //
+ // Allocate map register memory.
+ //
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+
+ //
+ // Initialize Processor A interrupts
+ //
+
+ HalpInitializeInterrupts();
+
+ } else {
+
+ //
+ // Initialize Processor B interrupts
+ //
+
+ HalpInitializeProcessorBInterrupts();
+
+ }
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ HalpMapIoSpace();
+ HalpCalibrateStall();
+
+ //
+ // Register bus handlers
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+
+ return TRUE;
+ }
+ }
+}
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory/pci error registers into a bug check
+ buffer and output some debug information to the screen. This routine
+ is registered during Phase 0 initialization using KeRegisterBugCheckCallback().
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PHALP_BUGCHECK_BUFFER DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+ ULONG BadStatus;
+ CHAR buf[256];
+
+
+ //
+ // MEMORY:
+ // 1. Uncorrectable memory error
+ // 2. Multiple UE
+ // 3. Mutiple CE
+ //
+
+ BadStatus = READ_REGISTER_ULONG(HalpPmpMemStatus);
+
+ if ( BadStatus & (MEM_STATUS_EUE | MEM_STATUS_OUE) ) {
+
+ //
+ // Read the address, status, and diag registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ DumpBuffer->Info2 = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "MEMORY_UNCORRECTABLE_ERROR: at %08X with status %08X and diagbits %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1,
+ DumpBuffer->Info2);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & MEM_STATUS_MUE ) {
+
+ //
+ // Read the address, status, and diag registers
+ // and output the information related to the multiple
+ // UE
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ DumpBuffer->Info2 = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ //
+ // This is an NMI which means we were called by the
+ // firmware and so we are dead and need to output
+ // some debug information.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "MEMORY_MULTIPLE_UNCORRECTABLE_ERROR: at %08X with status %08X and diagbits %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1,
+ DumpBuffer->Info2);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & MEM_STATUS_MCE ) {
+
+ //
+ // Read the address, status, and diag registers
+ // and output the information related to the multiple
+ // CE
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpMemErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpMemErrAck);
+ DumpBuffer->Info2 = READ_REGISTER_ULONG(HalpPmpMemDiag);
+
+ //
+ // This is an NMI which means we were called by the
+ // firmware and so we are dead and need to output
+ // some debug information.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "MEMORY_MULTIPLE_CORRECTABLE_ERROR: at %08X with status %08X and diagbits %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1,
+ DumpBuffer->Info2);
+
+ HalDisplayString(buf);
+
+ }
+
+ //
+ // PCI:
+ // 1. Parity (SERR#)
+ // 2. Master Abort
+ // 3. Target Abort
+ // 4. Access Error
+ // 5. System Error
+ // 6. Retry Error
+ //
+
+ BadStatus = READ_REGISTER_ULONG(HalpPmpPciStatus);
+
+ if ( BadStatus & PCI_STATUS_RMA) {
+
+ //
+ // Read the address and status registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_MASTER_ABORT_ERROR: at %08X with status %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & PCI_STATUS_RSE) {
+
+ //
+ // Read the address and status registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_SYSTEM_ERROR: at %08X with status %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & PCI_STATUS_RER) {
+
+ //
+ // Read the address, status, and retry registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+ DumpBuffer->Info2 = READ_REGISTER_ULONG(HalpPmpPciRetry);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_EXCESSIVE_RETRY_ERROR: at %08X with status %08X and retrycount %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1,
+ DumpBuffer->Info2);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & PCI_STATUS_IAE) {
+
+ //
+ // Read the address and status registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_EXCESSIVE_RETRY_ERROR: at %08X with status %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & PCI_STATUS_MPE) {
+
+ //
+ // Read the address and status registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_MASTER_PARITY_ERROR: at %08X with status %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & PCI_STATUS_RTA) {
+
+ //
+ // Read the address and status registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_TARGET_ABORT_ERROR: at %08X with status %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1);
+
+ HalDisplayString(buf);
+
+ } else if ( BadStatus & PCI_STATUS_ME) {
+
+ //
+ // Read the address and status registers
+ //
+
+ DumpBuffer->Info0 = READ_REGISTER_ULONG(HalpPmpPciErrAddr);
+ DumpBuffer->Info1 = READ_REGISTER_ULONG(HalpPmpPciErrAck);
+
+ //
+ // Output debug info to blue screen
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ sprintf(buf, "PCI_MULTIPLE_ERROR: at %08X with status %08X\n",
+ DumpBuffer->Info0,
+ DumpBuffer->Info1);
+
+ HalDisplayString(buf);
+
+ }
+
+ return;
+}
+
+
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halntp/mips/xxinitnt.c b/private/ntos/nthals/halntp/mips/xxinitnt.c
new file mode 100644
index 000000000..ebaee5f3d
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/xxinitnt.c
@@ -0,0 +1,929 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+#include "eisa.h"
+
+
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpCountInterrupt (
+ VOID
+ );
+
+VOID
+HalpInitializeEisaInterrupts (
+ IN PEISA_CONTROL controlBase
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+#pragma alloc_text(INIT, HalpCountInterrupt)
+
+
+#endif
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the count/compare interrupt service routine
+ early in the system initialization. Its only function is to field
+ and acknowledge count/compare interrupts during the system boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Jazz or Duo MIPS system.
+
+ N.B. This function is only called during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG DataLong;
+ ULONG Index;
+ PKPRCB Prcb;
+ ULONG Address;
+ ENTRYLO HalpPte[2];
+ TIMER_CONTROL timerControl;
+
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Disable all system level interrupts which
+ // includes all IO (PCI/EISA) device interrupts.
+ //
+
+ WRITE_REGISTER_ULONG(HalpPmpIntCtrl, 0);
+
+ //
+ // If processor 0 is being initialized, then clear all builtin device
+ // interrupt enables.
+ //
+
+ if (Prcb->Number == 0) {
+ HalpBuiltinInterruptEnable = 0;
+ }
+
+ //
+ // Read IntStatus
+ //
+
+ DataLong = READ_REGISTER_ULONG(HalpPmpIntStatus) & INT_STATUS_AMASK;
+
+ //
+ // If there are any pending interrupts to processor A,
+ // then read the *Ack registers to clear the offending
+ // condition. We will need to map registers on-the-fly
+ // here iff there are any pending interrupts to be serviced.
+ //
+
+ if (DataLong) {
+
+ do {
+
+ //
+ // Clear pending IO interrupts
+ //
+
+ if (DataLong & INT_STATUS_IOA) {
+
+ HalpMapSysCtrlReg(PMP(IO_INT_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IO_INT_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending IP interrupts
+ //
+
+ if (DataLong & INT_STATUS_IPA) {
+
+ HalpMapSysCtrlReg(PMP(IP_INT_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IP_INT_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending PCI interrupts
+ //
+
+ if (DataLong & (INT_STATUS_PA | INT_STATUS_PNI)) {
+
+ HalpMapSysCtrlReg(PMP(PCI_ERR_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(PCI_ERR_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending MCU interrupts
+ //
+
+ if (DataLong & (INT_STATUS_MA | INT_STATUS_MNI)) {
+
+ HalpMapSysCtrlReg(PMP(MEM_ERR_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(MEM_ERR_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending Timer interrupts
+ //
+
+ if (DataLong & INT_STATUS_ITA) {
+
+ HalpMapSysCtrlReg(PMP(INT_CLR_CTRL_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CLR_CTRL_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ } while ((READ_REGISTER_ULONG(HalpPmpIntStatus) & INT_STATUS_AMASK) != 0);
+
+ }
+
+ //
+ // For FALCON: all interrupts, except the R4x00 timer and
+ // software interrupts, come into the kernel at the same
+ // level due to the manner in which interrupts are delivered
+ // to the processor and controlled by the IP field in the
+ // R4x00 cause register.
+ //
+ // This means that we need a master interrupt handler whose
+ // job is to (1) determine the source of the interrupt and
+ // (2) invoke the correct interrupt handler to service the
+ // request.
+ //
+ // Instead of managing a separate data structure for interrupt
+ // vectors, we will still install all interupt handlers at their
+ // normal positions within the IDT, eventhough they will be not
+ // be directly invoked by the kernel but rather by the master
+ // interrupt handler named HalpInterruptDispatch. Please
+ // refere to the fxintr.s file for more details on how this scheme
+ // will work.
+ //
+
+ PCR->InterruptRoutine[FALCON_LEVEL] = HalpInterruptDispatch;
+
+ //
+ // Likewise, we need a similar routine for IO device interrupts
+ // to transfer control to the correct handler based on the IRQ
+ // vector returned by the 82374. This handler is the first level
+ // handler in the HAL for any IO interrupt, regardless of whether
+ // the interrupt is from a PCI device or an EISA/ISA device.
+ //
+
+ PCR->InterruptRoutine[IO_DEVICE_LEVEL] = HalpIoInterruptDispatch;
+
+ //
+ // We also need to install the Memory and PCI interrupt handlers
+ // that deal with errors such as parity and ECC, etc. These handlers
+ // are invoked by the master interrupt handler but are in the IDT
+ // for completeness. These same handlers should serve as the error
+ // handlers for bus errors (i.e., synchronous errors as opposed to
+ // asynchronous interrupts).
+ //
+
+ PCR->InterruptRoutine[MEMORY_LEVEL] = HalpMemoryInterrupt;
+ PCR->InterruptRoutine[PCI_LEVEL] = HalpPciInterrupt;
+
+ //
+ // Install IP interrupt routine in PCR structure.
+ //
+
+ PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt;
+
+ //
+ // If processor 0 is being initialized, then connect the interval timer
+ // interrupt to the stall interrupt routine so the stall execution count
+ // can be computed during phase 1 initialization. Otherwise, connect the
+ // interval timer interrupt to the appropriate interrupt service routine
+ // and set stall execution count from the computation made on processor
+ // 0.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+ PCR->InterruptRoutine[IRQL0_VECTOR] = HalpStallInterrupt;
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\comapre interrupt to the appropriate interrupt service routine.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ //
+ // Initialize the interval timer to interrupt at the specified interval.
+ //
+ // Note that for the first version of the PMP chip, the timer control
+ // and the interrupt signal will only be controllable through the 82374
+ // and visible through the standard IRQ* signals. However, in the second
+ // version of the PMP chip, the interrupt signal will actually be a
+ // separate interrupt signal not part of the IRQ architecture of the
+ // 82374. This signal will actually be delivered by Timer 1, Counter 2
+ // in the 82374 which is normally used to generate speaker tone(s).
+ // We can play this trick because this timer runs off the same clock as
+ // the normal system timer (Timer 1, Counter 0). The difference between
+ // the two timers are that the system timer is wired to IRQ0 permanently
+ // and is always enabled, while the speaker timer is not part of the
+ // IRQ architecture and must be enabled by software through port 0x61
+ // (NMI Status and Control Register).
+ //
+ //
+ // For the first version of the PMP chip, we actually need to initialize
+ // the cascaded interrupt controllers in the 82374 before we can enable
+ // interrupts for the interval timer (or any other IO device). This is
+ // because the interval timer circuitry is in the 82374 and is part of
+ // the standard IRQ* architecture. In the second version of the PMP chip,
+ // the timer interrupt is a separate signal and we can avoid having to
+ // initialize the 82374 interrupt controllers during this phase.
+ //
+
+ //
+ // Map the system timer control registers
+ // located in the 82374 through EISA control
+ // space using one of the wired entries in
+ // the TLB. We will relinquish this entry when
+ // HalpMapIoSpace() is called and maps Eisa
+ // control space using MmMapIoSpace().
+ //
+
+ HalpMapSysCtrlReg(EISA_CONTROL_PHYSICAL_BASE, 0, SYS_CONTROL_VIRTUAL_BASE);
+ HalpEisaControlBase = (PVOID)SYS_CONTROL_VIRTUAL_BASE;
+
+ //
+ // Initialize the interrupt controllers.
+ //
+
+ HalpInitializeEisaInterrupts((PEISA_CONTROL)HalpEisaControlBase);
+
+ //
+ // Initialize interval timer
+ //
+ // Timer 1, Counter 2, Mode 3 (Square Wave), Binary Countdown
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+
+ if ( HalpPmpRevision < 3 ) {
+ //
+ // PMP V2 uses Counter 0, IRQ0.
+ //
+
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Timer1, (UCHAR)CLOCK_INTERVAL);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Timer1, (UCHAR)(CLOCK_INTERVAL >> 8));
+
+ } else {
+ //
+ // PMP V3 and better uses Counter 2, ITIMER.
+ //
+
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->SpeakerTone, (UCHAR)CLOCK_INTERVAL);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->SpeakerTone, (UCHAR)(CLOCK_INTERVAL >> 8));
+
+ }
+
+ //
+ // Unmap wired entry for now
+ //
+
+ HalpUnMapSysCtrlReg();
+
+ //
+ // We enable IO and IP interrupts here for Processor A.
+ //
+
+ DataLong = READ_REGISTER_ULONG(HalpPmpIntCtrl);
+ WRITE_REGISTER_ULONG(HalpPmpIntCtrl, DataLong | (INT_CTRL_IOEA | INT_CTRL_IPEA) );
+
+ //
+ // Now we map the IntCause and IoIntAck registers
+ // before enabling any system or IO interrupts. This
+ // means we lose the IntCtrl and IntStatus mappings
+ // due to the HAL only being allocated one TLB entry
+ // on a permanent basis.
+ //
+
+ Address = PMP(INT_CAUSE_PHYSICAL_BASE);
+
+ HalpPte[0].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ Address = PMP(IO_INT_ACK_PHYSICAL_BASE);
+
+ HalpPte[1].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 1;
+ HalpPte[1].D = 1;
+ HalpPte[1].C = UNCACHED_POLICY;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ //
+ // Now we will NULL out the HalpPmpIntCtrl and
+ // HalpPmpIntStatus pointers to simplify the
+ // system interrupt dispatch routine which needs
+ // to check if an on-the-fly mapping is needed
+ // or not.
+ //
+
+ HalpPmpIntCtrl = NULL;
+ HalpPmpIntStatus = NULL;
+ HalpExtPmpControl = NULL;
+
+ //
+ // Initialize the register pointers with
+ // the fixed virtual addresses allocated
+ // to the HAL by the NT god. Hail Caesar!
+ //
+
+ HalpPmpIntCause = (PVOID)(PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CAUSE_PHYSICAL_BASE)));
+ HalpPmpIoIntAck = (PVOID)(PMP_CONTROL_VIRTUAL_BASE + PAGE_SIZE + REG_OFFSET(PMP(IO_INT_ACK_PHYSICAL_BASE)));
+
+ //
+ // Now we will map the Eisa Control Space
+ // in using an on-the-fly mapping until
+ // we map IO space using MmMapIoSpace()
+ // during Phase 1.
+ //
+
+ HalpMapSysCtrlReg(EISA_CONTROL_PHYSICAL_BASE, PCI_CONFIG_SEL_PHYSICAL_BASE, SYS_CONTROL_VIRTUAL_BASE);
+ HalpEisaControlBase = (PVOID)SYS_CONTROL_VIRTUAL_BASE;
+ HalpExtPmpControl = (PVOID)(SYS_CONTROL_VIRTUAL_BASE + PAGE_SIZE + 0x4);
+
+ //
+ // This is the second (or N) version of
+ // the PMP chip, so we can take advantage
+ // the clustering of some registers that was
+ // not supported in the original PMP prototype.
+ //
+
+ HalpPmpIpIntAck = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IP_INT_ACK_PHYSICAL_BASE)));
+ HalpPmpIntSetCtrl = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_SET_CTRL_PHYSICAL_BASE)));
+ HalpPmpIntClrCtrl = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CLR_CTRL_PHYSICAL_BASE)));
+ HalpPmpTimerIntAck = (PVOID) HalpPmpIntClrCtrl;
+
+ if ( HalpPmpRevision < 3 ) {
+ //
+ // PMP_V2 uses timer on IRQ0.
+ //
+
+ HalpEisaInterrupt1Mask &= (UCHAR) 0xFE;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort1, HalpEisaInterrupt1Mask);
+
+ } else {
+ //
+ // PMP_V3 and better uses interval timer.
+ //
+
+ //
+ // Enable the speaker source which we use
+ // as the interval timer
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->NmiStatus, 0x3);
+
+ //
+ // Enable Interval Timer interrupts for processor A only
+ //
+
+ WRITE_REGISTER_ULONG(HalpPmpIntSetCtrl, INT_CTRL_ITEA);
+
+ }
+
+ //
+ // Now enable Memory and PCI interrupts
+ // for error logging and handling on
+ // Processor B
+ //
+
+ //WRITE_REGISTER_ULONG(HalpPmpIntSetCtrl, INT_CTRL_MIEA | INT_CTRL_PIEA);
+
+ //
+ // Reserve FALCON_LEVEL interrupt vector for
+ // exclusive use by the HAL
+ //
+
+ PCR->ReservedVectors |= ( (1 << FALCON_LEVEL) | (1 << IO_DEVICE_LEVEL) );
+
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeProcessorBInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a FALCON system.
+
+ N.B. This function is only called during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG DataLong;
+ ULONG Index;
+ PKPRCB Prcb;
+ ULONG Address;
+ ENTRYLO HalpPte[2];
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Read IntStatus
+ //
+
+ DataLong = READ_REGISTER_ULONG(HalpPmpIntStatusProcB) & INT_STATUS_BMASK;
+
+ //
+ // If there are any pending interrupts to processor B,
+ // then read the *Ack registers to clear the offending
+ // condition. We will need to map registers on-the-fly
+ // here iff there are any pending interrupts to be serviced.
+ //
+
+ if (DataLong) {
+
+ do {
+
+ //
+ // Clear pending IO interrupts
+ //
+
+ if (DataLong & INT_STATUS_IOB) {
+
+ HalpMapSysCtrlReg(PMP(IO_INT_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IO_INT_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending IP interrupts
+ //
+
+ if (DataLong & INT_STATUS_IPB) {
+
+ HalpMapSysCtrlReg(PMP(IP_INT_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IP_INT_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending PCI interrupts
+ //
+
+ if (DataLong & (INT_STATUS_PB | INT_STATUS_PNI)) {
+
+ HalpMapSysCtrlReg(PMP(PCI_ERR_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(PCI_ERR_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending MCU interrupts
+ //
+
+ if (DataLong & (INT_STATUS_MB | INT_STATUS_MNI)) {
+
+ HalpMapSysCtrlReg(PMP(MEM_ERR_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(MEM_ERR_ACK_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ //
+ // Clear pending Timer interrupts
+ //
+
+ if (DataLong & INT_STATUS_ITB) {
+
+ HalpMapSysCtrlReg(PMP(INT_CLR_CTRL_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE);
+ READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CLR_CTRL_PHYSICAL_BASE)));
+ HalpUnMapSysCtrlReg();
+
+ }
+
+ } while ((READ_REGISTER_ULONG(HalpPmpIntStatusProcB) & INT_STATUS_BMASK) != 0);
+
+ }
+
+ //
+ // For FALCON: all interrupts, except the R4x00 timer and
+ // software interrupts, come into the kernel at the same
+ // level due to the manner in which interrupts are delivered
+ // to the processor and controlled by the IP field in the
+ // R4x00 cause register.
+ //
+ // This means that we need a master interrupt handler whose
+ // job is to (1) determine the source of the interrupt and
+ // (2) invoke the correct interrupt handler to service the
+ // request.
+ //
+ // Instead of managing a separate data structure for interrupt
+ // vectors, we will still install all interupt handlers at their
+ // normal positions within the IDT, eventhough they will be not
+ // be directly invoked by the kernel but rather by the master
+ // interrupt handler named HalpInterruptDispatch. Please
+ // refere to the fxintr.s file for more details on how this scheme
+ // will work.
+ //
+
+ PCR->InterruptRoutine[FALCON_LEVEL] = HalpInterruptDispatch;
+
+ //
+ // Likewise, we need a similar routine for IO device interrupts
+ // to transfer control to the correct handler based on the IRQ
+ // vector returned by the 82374. This handler is the first level
+ // handler in the HAL for any IO interrupt, regardless of whether
+ // the interrupt is from a PCI device or an EISA/ISA device.
+ //
+
+ PCR->InterruptRoutine[IO_DEVICE_LEVEL] = HalpIoInterruptDispatch;
+
+ //
+ // We also need to install the Memory and PCI interrupt handlers
+ // that deal with errors such as parity and ECC, etc. These handlers
+ // are invoked by the master interrupt handler but are in the IDT
+ // for completeness. These same handlers should serve as the error
+ // handlers for bus errors (i.e., synchronous errors as opposed to
+ // asynchronous interrupts).
+ //
+
+ PCR->InterruptRoutine[MEMORY_LEVEL] = HalpMemoryInterrupt;
+ PCR->InterruptRoutine[PCI_LEVEL] = HalpPciInterrupt;
+
+ //
+ // Install IP interrupt routine in PCR structure.
+ //
+
+ PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt1;
+
+ //
+ // Install interval timer interrupt vectors.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt1;
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\comapre interrupt to the appropriate interrupt service routine.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+ //
+ // We enable IP interrupts here for Processor B.
+ //
+
+ DataLong = READ_REGISTER_ULONG(HalpPmpIntCtrlProcB);
+
+ WRITE_REGISTER_ULONG(HalpPmpIntCtrlProcB, DataLong | INT_CTRL_IPEB );
+
+ //
+ // Now we map the IntCause and IoIntAck registers
+ // before enabling any system or IO interrupts. This
+ // means we lose the IntCtrl and IntStatus mappings
+ // due to the HAL only being allocated one TLB entry
+ // on a permanent basis.
+ //
+
+ Address = PMP(INT_CAUSE_PHYSICAL_BASE);
+
+ HalpPte[0].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ Address = PMP(IO_INT_ACK_PHYSICAL_BASE);
+
+ HalpPte[1].PFN = ((Address & 0xF0000000) >> (PAGE_SHIFT - 4)) | (Address >> PAGE_SHIFT);
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 1;
+ HalpPte[1].D = 1;
+ HalpPte[1].C = UNCACHED_POLICY;
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], (PVOID)PMP_CONTROL_VIRTUAL_BASE, DMA_ENTRY);
+
+ //
+ // Now we will NULL out the HalpPmpIntCtrlProcB and
+ // HalpPmpIntStatusProcB pointers. These pointers
+ // will eventually be re-initialized, by Processor A
+ // during Phase 1, to point to the MmMapIoSpace()
+ // mappings.
+ //
+
+ HalpPmpIntCtrlProcB = NULL;
+ HalpPmpIntStatusProcB = NULL;
+
+ //
+ // This is the second (or N) version of
+ // the PMP chip, so we can take advantage
+ // the clustering of some registers that was
+ // not supported in the original PMP prototype.
+ //
+
+ HalpPmpIpIntAckProcB = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IP_INT_ACK_PHYSICAL_BASE)));
+ HalpPmpIntSetCtrlProcB = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_SET_CTRL_PHYSICAL_BASE)));
+ HalpPmpIntClrCtrlProcB = (PVOID) (PMP_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CLR_CTRL_PHYSICAL_BASE)));
+ HalpPmpTimerIntAckProcB = (PVOID) HalpPmpIntClrCtrlProcB;
+
+ //
+ // Now enable Interval Timer interrupts for processor B
+ //
+
+ WRITE_REGISTER_ULONG(HalpPmpIntSetCtrlProcB, INT_CTRL_ITEB);
+
+ //
+ // Now enable Memory and PCI interrupts
+ // for error logging and handling on
+ // Processor B
+ //
+
+ //WRITE_REGISTER_ULONG(HalpPmpIntSetCtrl, INT_CTRL_MIEB | INT_CTRL_PIEB);
+
+ //
+ // Reserve FALCON_LEVEL interrupt vector for
+ // exclusive use by the HAL
+ //
+
+ PCR->ReservedVectors |= ( (1 << FALCON_LEVEL) | (1 << IO_DEVICE_LEVEL) );
+
+ return TRUE;
+
+}
+
+VOID
+HalpCheckSystemTimer(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This checks to see if the system timer is still enabled. Tunrs out that some
+ video BIOS code (notably #9 S3 928 GXE ISA), disable the speaker 2 data enable bit
+ in the nmistatus register, in addition to re-programming the rate of the counter.
+ They apparently do this to have the video BIOS generate a tone when the card is
+ being initialized. Since we use this timer as our system timer for PMP V3 and
+ up, this is a problem! #9 has been contacted!
+
+Arguments:
+
+ None.
+
+--*/
+
+{
+ UCHAR HackByte;
+ TIMER_CONTROL timerControl;
+
+ //
+ // Only an issue if we are using Timer 1, Counter 2 which we do on PMP V3 only.
+ //
+
+ if ( HalpPmpRevision >= 3 ) {
+
+ HackByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->NmiStatus);
+
+ //
+ // If Timer 1, Counter 2 Gate Enable AND/OR SPeaker Data Enable are CLEARED,
+ // then assume the last BIOS call hacked them, and re-program the timer.
+ //
+
+ if ( ( HackByte & 0x3 ) != 0x3 ) {
+
+ //
+ // PMP V3 and better uses Timer 1, Counter 2.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->SpeakerTone, (UCHAR)CLOCK_INTERVAL);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->SpeakerTone, (UCHAR)(CLOCK_INTERVAL >> 8));
+
+ //
+ // This BIOS call turned off the enable, therefore let's reprogram it!
+ //
+
+ HackByte |= 0x3;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->NmiStatus, HackByte);
+
+ }
+ }
+}
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halntp/mips/xxipiint.s b/private/ntos/nthals/halntp/mips/xxipiint.s
new file mode 100644
index 000000000..f5ef86203
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/xxipiint.s
@@ -0,0 +1,159 @@
+// TITLE("Interprocessor Interrupts")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// xxipiint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a MIPS R4000 Duo system.
+//
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "faldef.h"
+#include "falreg.h"
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt
+// to processor A only. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to process interprocessor
+// requests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+FyRa: .space 4 // saved return address
+FyFrameLength: // length of stack frame
+FyIntCtrlAddr: .space 4 // IntCtrl virtual address
+FyIntCtrl: .space 4 // IntCtrl value
+FyTemp1: .space 4 //
+FyTemp2: .space 4 //
+FyTemp3: .space 4 //
+
+ NESTED_ENTRY(HalpIpiInterrupt, FyFrameLength, zero)
+
+ subu sp,sp,FyFrameLength // allocate stack frame
+ sw ra,FyRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+ .set noat
+
+ //
+ // clear IP interrupt by reading
+ // IPIntAck register in PMP chip.
+ //
+ lw t0, HalpPmpIpIntAck
+ lw t0, 0(t0)
+
+ //
+ // Service kernel
+ //
+ lw t1,__imp_KeIpiInterrupt // process interprocessor requests
+ jal t1
+
+ .set at
+ .set reorder
+
+ //
+ // Restore Return Address register
+ //
+ lw ra,FyRa(sp) // get return address
+ addu sp,sp,FyFrameLength // deallocate stack frame
+
+ j ra
+
+ .end HalpIpiInterrupt
+
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt
+// to processor B only. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to process interprocessor
+// requests. This handler also serves to update the system time for processor
+// B.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+FxRa: .space 4 // saved return address
+FxFrameLength: // length of stack frame
+FxBFlag: .space 4 // flag for IP versus timer update
+FxTemp0: .space 4 //
+FxTemp1: .space 4 //
+FxTemp2: .space 4 //
+FxTemp3: .space 4 //
+
+ NESTED_ENTRY(HalpIpiInterrupt1, FxFrameLength, zero)
+
+ subu sp,sp,FxFrameLength // allocate stack frame
+ sw ra,FxRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+ .set noat
+
+ //
+ // clear IP interrupt by reading
+ // IPIntAck register in PMP chip.
+ //
+ lw t0, HalpPmpIpIntAckProcB
+ lw t0, 0(t0)
+
+ //
+ // Service IP
+ //
+ lw t1,__imp_KeIpiInterrupt // process interprocessor requests
+ jal t1
+
+ .set at
+ .set reorder
+
+ //
+ // Restore Return Address register
+ //
+ lw ra,FxRa(sp) // get return address
+ addu sp,sp,FxFrameLength // deallocate stack frame
+
+ j ra
+
+ .end HalpIpiInterrupt1
+
+
diff --git a/private/ntos/nthals/halntp/rangesup.c b/private/ntos/nthals/halntp/rangesup.c
new file mode 100644
index 000000000..3b3c1cb54
--- /dev/null
+++ b/private/ntos/nthals/halntp/rangesup.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\rangesup.c"
diff --git a/private/ntos/nthals/halntp/sources b/private/ntos/nthals/halntp/sources
new file mode 100644
index 000000000..8ebd0d3db
--- /dev/null
+++ b/private/ntos/nthals/halntp/sources
@@ -0,0 +1,105 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1993, NeTpower, Inc. All rights reserved.
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revisions:
+ Addition of Striker (NeTpower Series 100, 200, 300) changes. 1-Oct-93.
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halntp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_FALCON_HAL_
+
+INCLUDES=..\x86new;..\inc;..\..\inc;
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\fxerrlog.c \
+ mips\fxbusdat.c \
+ mips\fxdat.c \
+ mips\fxinfo.c \
+ mips\fxintr.s \
+ mips\fxnvram.c \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\fxdisp.c \
+ mips\jxebsup.c \
+ mips\fxhwsup.c \
+ mips\fxpmpsup.c \
+ mips\fxpcibus.c \
+ mips\fxpcibrd.c \
+ mips\fxusage.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\rangesup.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s \
+ mips\xxidle.s \
+ mips\xxclock.c \
+ mips\x86bios.c \
+ mips\allstart.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/haloli/drivesup.c b/private/ntos/nthals/haloli/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haloli/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haloli/hal.rc b/private/ntos/nthals/haloli/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haloli/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haloli/hal.src b/private/ntos/nthals/haloli/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haloli/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haloli/i386/halnls.h b/private/ntos/nthals/haloli/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/haloli/i386/halp.h b/private/ntos/nthals/haloli/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/haloli/i386/ix8259.inc b/private/ntos/nthals/haloli/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/haloli/i386/ixbeep.asm b/private/ntos/nthals/haloli/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/haloli/i386/ixbusdat.c b/private/ntos/nthals/haloli/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/haloli/i386/ixcmos.asm b/private/ntos/nthals/haloli/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/haloli/i386/ixcmos.inc b/private/ntos/nthals/haloli/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/haloli/i386/ixdat.c b/private/ntos/nthals/haloli/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/haloli/i386/ixenvirv.c b/private/ntos/nthals/haloli/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/haloli/i386/ixfirm.c b/private/ntos/nthals/haloli/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/haloli/i386/ixhwsup.c b/private/ntos/nthals/haloli/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/haloli/i386/ixidle.asm b/private/ntos/nthals/haloli/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/haloli/i386/ixinfo.c b/private/ntos/nthals/haloli/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/haloli/i386/ixisa.h b/private/ntos/nthals/haloli/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/haloli/i386/ixisabus.c b/private/ntos/nthals/haloli/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/haloli/i386/ixisasup.c b/private/ntos/nthals/haloli/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/haloli/i386/ixkdcom.c b/private/ntos/nthals/haloli/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/haloli/i386/ixkdcom.h b/private/ntos/nthals/haloli/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/haloli/i386/ixnmi.c b/private/ntos/nthals/haloli/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/haloli/i386/ixpcibus.c b/private/ntos/nthals/haloli/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/haloli/i386/ixpciint.c b/private/ntos/nthals/haloli/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/haloli/i386/ixphwsup.c b/private/ntos/nthals/haloli/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/haloli/i386/ixreboot.c b/private/ntos/nthals/haloli/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/haloli/i386/ixstall.asm b/private/ntos/nthals/haloli/i386/ixstall.asm
new file mode 100644
index 000000000..115c6c9c1
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixstall.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixstall.asm
diff --git a/private/ntos/nthals/haloli/i386/ixswint.asm b/private/ntos/nthals/haloli/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixswint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixswint.asm
diff --git a/private/ntos/nthals/haloli/i386/ixthunk.c b/private/ntos/nthals/haloli/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/haloli/i386/ixusage.c b/private/ntos/nthals/haloli/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/haloli/i386/oliclock.asm b/private/ntos/nthals/haloli/i386/oliclock.asm
new file mode 100644
index 000000000..58ce1a7ea
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliclock.asm
@@ -0,0 +1,1281 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; oliclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT. It works on UP and LSX5030.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+include i386\kimacro.inc
+include mac386.inc
+;LSX5030 start
+include i386\olimp.inc
+;LSX5030 end
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalRequestIpi,1
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ extrn _HalpProcessorPCR:DWORD
+ extrn _HalpSystemHardwareLock:DWORD
+ extrn _HalpFindFirstSetRight:BYTE
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193000
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+RTCIRQ EQU 8 ; IRQ number for RTC interrupt
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+;
+; RegisterAInitByte sets 8Hz clock rate, used during init to set up
+; KeStallExecutionProcessor, etc. (See RegASystemClockByte below.)
+;
+
+RegisterAInitByte EQU 00101101B ; RT/CMOS Register 'A' init byte
+ ; 32.768KHz Base divider rate
+ ; 8Hz int rate, period = 125.0ms
+PeriodInMicroSecond EQU 125000 ;
+
+CMOS_STATUS_BUSY EQU 80H ; Time update in progress
+RTC_OFFSET_SECOND EQU 0 ; second field of RTC memory
+RTC_OFFSET_MINUTE EQU 2 ; minute field of RTC memory
+RTC_OFFSET_HOUR EQU 4 ; hour field of RTC memory
+RTC_OFFSET_DAY_OF_WEEK EQU 6 ; day-of-week field of RTC memory
+RTC_OFFSET_DATE_OF_MONTH EQU 7 ; date-of-month field of RTC memory
+RTC_OFFSET_MONTH EQU 8 ; month field of RTC memory
+RTC_OFFSET_YEAR EQU 9 ; year field of RTC memory
+RTC_OFFSET_CENTURY EQU 32h ; Century field of RTC memory
+
+;
+; ==== Values used for System Clock ====
+;
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+; sec, the computation is:
+; RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+; = Interval * 0.1193
+; = Interval * 1193 / 10000
+;
+;
+; The default Interrupt interval is Interval = 15ms.
+;
+
+TIME_INCREMENT EQU 150000 ; 15ms
+ROLLOVER_COUNT EQU 15 * 1193
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+RegisterAProfileValue db 00101000B ; default interval = 3.90625 ms
+
+ProfileIntervalTable dd 1221 ; unit = 100 ns
+ dd 2441
+ dd 4883
+ dd 9766
+ dd 19531
+ dd 39063
+ dd 78125
+ dd 156250
+ dd 312500
+ dd 625000
+ dd 1250000
+ dd 2500000
+ dd 5000000
+ dd 5000000 OR 80000000H
+
+ProfileIntervalInitTable db 00100011B
+ db 00100100B
+ db 00100101B
+ db 00100110B
+ db 00100111B
+ db 00101000B
+ db 00101001B
+ db 00101010B
+ db 00101011B
+ db 00101100B
+ db 00101101B
+ db 00101110B
+ db 00101111B
+ db 00101111B
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+ifndef NT_UP
+ public _HalpIpiClock
+_HalpIpiClock dd 0 ; Processors to IPI clock pulse to
+endif
+
+;
+; Holds the value of the eflags register before a cmos spinlock is
+; acquired (used in HalpAcquire/ReleaseCmosSpinLock().
+;
+_HalpHardwareLockFlags dd 0
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+
+_Halp8254Lock dd 0
+
+;
+; PerfCounter value lock. locks access to the HalpPerfCounterLow/High vars.
+;
+
+_HalpPerfCounterLock dd 0
+
+
+HalpProfileInterval dd -1
+ public HalpPerfCounterLow
+ public HalpPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpProfilingStopped dd 1
+HalpPerfCounterInit dd 0
+ public HalpHackEsp
+HalpHackEsp dd 0
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0
+;
+; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock,0
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov ecx, ROLLOVER_COUNT
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+
+;
+; Fill in PCR value with TIME_INCREMENT
+;
+ mov edx, TIME_INCREMENT
+ stdCall _KeSetTimeIncrement, <edx, edx>
+
+ mov HalpPerfCounterInit, 1 ; Indicate performance counter
+ ; has been initialized.
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; HalpInitializeStallExecution (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+; Note:
+;
+; Current implementation assumes that all the processors share
+; the same Real Time Clock. So, the dispatcher database lock is
+; acquired before entering this routine to guarantee only one
+; processor can access the routine.
+;
+; NOTE:The routine is called for each cpu after the
+; 'KiDispatcherLock' is acquired in ke\kernlini.c!KiInitializeKernel
+; So, global variables used here are safe, but global resources
+; like RTC are not (must be spinlocked).
+;--
+
+KiseInterruptCount equ [ebp-12] ; local variable
+
+cPublicProc _HalpInitializeStallExecution,1
+
+
+; LSX5030 start
+;+++
+;
+; WARNING o-obruno Mar-3-92 This routine can't be used for Px, x>0.
+;
+; Since on the LSX5030 only processor 0 can receive RT clock interrupts,
+; the other processors would hang in this routine. In order to calculate
+; the right per microsecond loop count for each processor, the 8254 timer
+; has to be used (To Be Implemented). The processors can have different
+; clock rates, so such a loop count must be calculated for each processor.
+; Here, temporarily, it is assumed that all the processors run at the same
+; speed, so the loop count of the first processor is used by all the others
+; as well.
+
+
+; LSX5030 end
+
+ movzx ecx, byte ptr [esp+4] ; Current processor number
+ cmp ecx, 0 ; if proc number = 0, ie master
+ jz short kise ; if z, it's master, do regular processing
+ mov ecx, _HalpProcessorPCR[0] ; PCR for P0
+ mov eax, [ecx].PcStallScaleFactor; get P0 scale factor
+ mov fs:PcStallScaleFactor, eax ; Px scale factor.
+ stdRET _HalpInitializeStallExecution
+kise:
+
+;
+; End of Hack
+;
+;---
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 12 bytes for local use
+ sub esp, 12
+
+ pushfd ; save caller's eflag
+
+;
+; Initialize Real Time Clock to interrupt us for every 125ms at
+; IRQ 8.
+;
+
+ cli ; make sure interrupts are disabled
+
+;
+; Get and save current 8259 masks
+;
+
+ xor eax,eax
+
+;
+; Assume there is no third and fourth PICs
+;
+; Get interrupt Mask on PIC2
+;
+
+ in al,PIC2_PORT1
+ shl eax, 8
+
+;
+; Get interrupt Mask on PIC1
+;
+
+ in al,PIC1_PORT1
+ push eax ; save the masks
+ mov eax, NOT (( 1 SHL PIC_SLAVE_IRQ) + (1 SHL RTCIRQ))
+ ; Mask all the irqs except irq 2 and 8
+ SET_8259_MASK ; Set 8259's int mask register
+
+;
+; Since RTC interrupt will come from IRQ 8, we need to
+; Save original irq 8 descriptor and set the descriptor to point to
+; our own handler.
+;
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov edx, [ebp-6] ; (edx)->IDT
+
+ push dword ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)]
+ ; (TOS) = original desc of IRQ 8
+ push dword ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE) + 4]
+ ; each descriptor has 8 bytes
+ push edx ; (TOS) -> IDT
+ mov eax, offset FLAT:RealTimeClockHandler
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)], ax
+ ; Lower half of handler addr
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+2], KGDT_R0_CODE
+ ; set up selector
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+4], D_INT032
+ ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+6], ax
+ mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax,(REGISTER_B_ENABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ mov dword ptr [KiseInterruptCount], 0
+
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Now enable the interrupt and start the counter
+; (As a matter of fact, only IRQ8 can come through.)
+;
+
+ xor eax, eax ; (eax) = 0, initialize loopcount
+ sti
+kise10:
+ add eax, 1 ; increment the loopcount
+ jnz short kise10
+;
+; Counter overflowed
+;
+
+ stdCall _DbgBreakPoint
+
+;
+; Our RealTimeClock interrupt handler. The control comes here through
+; irq 8.
+; Note: we discard first real time clock interrupt and compute the
+; permicrosecond loopcount on receiving of the second real time
+; interrupt. This is because the first interrupt is generated
+; based on the previous real time tick interval.
+;
+
+RealTimeClockHandler:
+
+ inc dword ptr KiseInterruptCount ; increment interrupt count
+ cmp dword ptr KiseInterruptCount,1 ; Is this the first interrupt?
+ jnz short kise25 ; no, its the second go process it
+ pop eax ; get rid of original ret addr
+ push offset FLAT:kise10 ; set new return addr
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax,(REGISTER_B_ENABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ xor eax, eax ; reset loop counter
+
+ stdCall _HalpReleaseCmosSpinLock
+;
+; Dismiss the interrupt.
+;
+
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ iretd
+
+kise25:
+
+;
+; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount
+;
+
+ifdef DBG
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint
+
+endif
+ ; never return
+;
+; ** End temporay code
+;
+
+kise30:
+ xor edx, edx ; (edx:eax) = divident
+ mov ecx, PeriodInMicroSecond; (ecx) = time spent in the loop
+ div ecx ; (eax) = loop count per microsecond
+ cmp edx, 0 ; Is remainder =0?
+ jz short kise40 ; yes, go kise40
+ inc eax ; increment loopcount by 1
+kise40:
+ movzx ecx, byte ptr [ebp+8] ; Current processor number
+
+ mov fs:PcStallScaleFactor, eax
+;
+; Reset return address to kexit
+;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+ iretd
+
+kexit: ; Interrupts are disabled
+ pop edx ; (edx)->IDT
+ pop [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+4]
+ ; restore higher half of NMI desc
+ pop [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)]
+ ; restore lower half of NMI desc
+
+ pop eax ; (eax) = origianl 8259 int masks
+ SET_8259_MASK
+
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+ stdRET _HalpInitializeStallExecution
+
+stdENDP _HalpInitializeStallExecution
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+cPublicProc _KeStallExecutionProcessor,1
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+; DbgWrtP84 57h
+ mov eax, fs:PcStallScaleFactor ; get per microsecond
+
+ mul ecx ; (eax) = desired loop count
+
+ifdef DBG
+
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short kese
+ stdCall _DbgBreakPoint ; stop ...
+;; align 4
+kese: cmp eax,0
+ jnz short kese0
+ stdCall _DbgBreakPoint ; stop ...
+endif
+
+kese0:
+ sub eax, 1 ; (eax) = (eax) - 1
+ jnz short kese0
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+
+
+;++
+;
+; PROFILING AND PERFORMANCE COUNTER SUPPORT
+;
+;--
+
+;++
+;
+; HalStartProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the slowest thing we can get away with to the value
+; that's been KeSetProfileInterval
+;--
+
+cPublicProc _HalStartProfileInterrupt,1
+
+;
+; This function gets called on every processor so the hal can enable
+; a profile interrupt on each processor. The LSX5030 only support
+; profile on P0.
+;
+
+ cmp fs:PcHal.PcrNumber, 0
+ jnz short eip_exit
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+;
+; Mark profiling as active
+;
+
+ mov dword ptr HalpProfilingStopped, 0
+
+;
+; Set the interrupt rate to what is actually needed.
+;
+
+
+ mov al, RegisterAProfileValue
+ shl ax, 8
+ mov al, 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax,(REGISTER_B_ENABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH
+ ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+eip_exit:
+ stdRET _HalStartProfileInterrupt
+
+stdENDP _HalStartProfileInterrupt
+
+
+
+;++
+;
+; HalStopProfileInterrupt
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the high profiling rate to the slowest thing we
+; can get away with for PerformanceCounter rollover notification.
+;--
+
+cPublicProc _HalStopProfileInterrupt,1
+
+ cmp fs:PcHal.PcrNumber, 0
+ jnz short dip_exit
+
+
+;
+; Turn off profiling hit computation and profile interrupt
+;
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(REGISTER_B_DISABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH
+ ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending profiling interrupt
+ mov dword ptr HalpProfilingStopped, 1
+
+ stdCall _HalpReleaseCmosSpinLock
+dip_exit:
+ stdRET _HalStopProfileInterrupt
+
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; If profiling is active (KiProfilingStopped == 0) the actual
+; hardware interrupt rate will be set. Otherwise, a simple
+; rate validation computation is done.
+;
+; Arguments:
+;
+; (TOS+4) - Interval in 100ns unit.
+;
+; Return Value:
+;
+; Interval actually used by system.
+;
+; WARNING - This is HIGHLY machine specific code. Current code
+; works for UP machines and the LSX5030.
+;--
+
+cPublicProc _HalSetProfileInterval,1
+
+ mov edx, [esp+4] ; [edx] = interval in 100ns unit
+ and edx, 7FFFFFFFh ; Remove highest bit.
+ mov ecx, 0 ; index = 0
+Hspi00:
+ mov eax, ProfileIntervalTable[ecx * 4]
+ cmp edx, eax ; if request interval < suport interval
+ jbe short Hspi10 ; if be, find supported interval
+ inc ecx
+ jmp short Hspi00
+
+Hspi10:
+ and eax, 7FFFFFFFh ; remove highest bit from supported interval
+ push eax ; save interval value
+ mov al, ProfileIntervalInitTable[ecx]
+ mov RegisterAProfileValue, al
+ test dword ptr HalpProfilingStopped,-1
+ jnz Hspi90
+
+ stdCall _HalStartProfileInterrupt,<0> ; Re-start profile interrupt
+ ; with the new interval
+Hspi90: pop eax
+ stdRET _HalSetProfileInterval ; (eax) = return interval
+
+stdENDP _HalSetProfileInterval
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter,1
+
+ push ebx
+ push esi
+
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before 8254
+; initialization has occured. Reading garbage off the 8254 is not reasonable.
+;
+ cmp HalpPerfCounterInit, 0
+ jne Kqpc01 ; ok, perf counter has been initialized
+
+;
+; Initialization hasn't occured yet, so just return zeroes.
+;
+ mov eax, 0
+ mov edx, 0
+ jmp Kqpc20
+
+Kqpc01:
+Kqpc11: pushfd
+ cli
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+endif
+
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+; NOTE:
+; Need to watch for Px reading the 'CounterLow', P0 updates both
+; then Px finishes reading 'CounterHigh' [getting the wrong value].
+; After reading both, make sure that 'CounterLow' didn't change.
+; If it did, read it again. This way, we won't have to use a spinlock.
+;
+
+@@:
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+ cmp ebx, HalpPerfCounterLow ;
+ jne @b
+;
+; Fetch the current counter value from the hardware
+;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+endif
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+ jmp $+2
+
+
+;
+; Fetch the base value again.
+;
+
+@@:
+ mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+
+ cmp eax, HalpPerfCounterLow
+ jne @b
+
+;
+; Compare the two reads of Performance counter. If they are different,
+; simply returns the new Performance counter. Otherwise, we add the hardware
+; count to the performance counter to form the final result.
+;
+
+ cmp eax, ebx
+ jne short Kqpc20
+ cmp edx, esi
+ jne short Kqpc20
+ neg ecx ; PIT counts down from 0h
+ add ecx, ROLLOVER_COUNT
+ add eax, ecx
+ adc edx, 0 ; [edx:eax] = Final result
+
+;
+; Return the counter
+;
+
+Kqpc20:
+ ; return value is in edx:eax
+
+;
+; Return the freq. if caller wants it.
+;
+
+ or dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc99 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc99:
+ pop esi ; restore esi and ebx
+ pop ebx
+ stdRET _KeQueryPerformanceCounter
+
+ifndef NT_UP
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc11>
+endif
+
+stdENDP _KeQueryPerformanceCounter
+
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ mov eax, [esp+4] ; ponter to Number
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ ;
+ ; Nothing to calibrate on a OLI MP machine. There is only a single
+ ; 8254 device
+ ;
+
+ popfd ; restore interrupt flag
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; dismiss interrupt and raise Irql
+;
+
+Hci10:
+ push CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+
+; esp - OldIrql
+ stdCall _HalBeginSystemInterrupt,<CLOCK2_LEVEL,CLOCK_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; Update performance counter
+;
+
+ ;add HalpPerfCounterLow, ROLLOVER_COUNT ; update performace counter
+ ;adc HalpPerfCounterHigh, 0
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; (ebp) = address of trap frame
+;
+
+; LSX5030 start
+ ;mov eax, _HalpIpiClock ; Emulate clock ticks to any processors?
+ ;or eax, eax
+ ;jz Hci90
+
+;
+; On the SystemPro we know the processor which needs an emulated clock tick.
+; Just set that processors bit and IPI him
+;
+
+;@@:
+ ;movzx ecx, _HalpFindFirstSetRight[eax] ; lookup first processor
+ ;btr eax, ecx
+ ;mov ecx, _HalpProcessorPCR[ecx*4] ; PCR of processor
+ ;mov [ecx].PcHal.PcrIpiClockTick, 1 ; Set internal IPI event
+ ;or eax, eax ; any other processors?
+ ;jnz @b ; yes, loop
+
+ ;push _HalpIpiClock ; Processors to IPI
+ ;call _HalRequestIpi ; IPI the processor
+ ;add esp, 4
+
+;Hci90:
+;
+; On the LSX5030 every processor receives the timer 1 counter 0 interrupts,
+; since such a timer is present on each CPU. Only processor 0 updates the
+; system time. All the processors execute KeUpdateRunTime (which is called
+; by KeUpdateSystemTime) in order to update the runtime of the current
+; thread, update the runtime of the current thread's process, and
+; decrement the current thread's quantum.
+;
+
+ movzx eax, fs:PcHal.PcrNumber ; (eax)= Processor number
+ or eax, eax
+ jnz @f
+;
+; Processor 0 updates the performance counter
+;
+
+ add HalpPerfCounterLow, ROLLOVER_COUNT ; update performace counter
+ adc HalpPerfCounterHigh, 0
+
+ mov eax, TIME_INCREMENT
+ jmp _KeUpdateSystemTime@0 ; if P0, jump to _KeUpdateSystemTime
+
+@@:
+ stdCall _KeUpdateRunTime,<dword ptr [esp]> ; if Px, x>0, call _KeUpdateRunTime
+
+ INTERRUPT_EXIT
+; LSX5030 end
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_HalpClockInterrupt endp
+
+ page ,132
+ subttl "System Profile Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; PROFILE_LEVEL and transfer control to
+; the standard system routine to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpi_a, Hpi_t
+
+cPublicProc _HalpProfileInterrupt,0
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpi_a, Hpi_t
+
+
+;
+; This is the RTC interrupt, so we have to clear the
+; interrupt flag on the RTC.
+;
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+; NOTE: THIS IS MACHINE SPECIFIC
+; for MP machines that utilize one global RTC chip, and a subset of
+; the CPUs (here,P0 must be one of them) accept an interrupt from
+; the RTC, only one CPU needs to ACK the RTC (P0 in this scheme).
+;
+
+ifndef NT_UP
+ cmp fs:PcHal.PcrNumber, 0 ; Only P0 ack RTC.
+ jne Hpi10
+endif
+
+Hpil01:
+ cli
+ lea eax, _HalpSystemHardwareLock
+ ACQUIRE_SPINLOCK eax, Hpil90
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+if DBG
+Hpi00: test al, 80h
+ jz short Hpi05
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ jmp short Hpi00
+Hpi05:
+endif ; DBG
+
+ lea eax, _HalpSystemHardwareLock
+ RELEASE_SPINLOCK eax
+
+Hpi10:
+
+
+;
+; (esp) - base of trap frame
+;
+
+ push PROFILE_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+
+; esp - OldIrql
+
+ stdCall _HalBeginSystemInterrupt,<PROFILE_LEVEL,PROFILE_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hpi100
+;
+; (esp) = OldIrql
+; (esp+4) = H/W vector
+; (esp+8) = base of trap frame
+;
+
+;
+; Now check is any profiling stuff to do.
+;
+
+ cmp HalpProfilingStopped, dword ptr 1 ; Has profiling been stopped?
+ jz short Hpi90 ; if z, prof disenabled
+
+ stdCall _KeProfileInterrupt,<ebp>
+Hpi90: INTERRUPT_EXIT
+
+
+Hpi100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+Hpil90:
+;
+; Even though intr gets enabled here, we shouldn't get another
+; intr on this channel, because we didn't eoi the interrupt yet.
+;
+ sti
+ SPIN_ON_SPINLOCK eax, <Hpil01>
+
+stdENDP _HalpProfileInterrupt
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, TIME_INCREMENT
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+
+_TEXT ends
+ end
+
diff --git a/private/ntos/nthals/haloli/i386/olidtect.asm b/private/ntos/nthals/haloli/i386/olidtect.asm
new file mode 100644
index 000000000..736d71f70
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olidtect.asm
@@ -0,0 +1,98 @@
+;++
+;
+;Module Name:
+;
+; olidtect.c
+;
+;Abstract:
+;
+; This modules implements the machine type detection.
+;
+;Author:
+;
+;
+;
+;Environment:
+;
+; Kernel mode only.
+;
+;Revision History:
+;
+;--
+.386p
+
+ include callconv.inc
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; BOOLEAN
+; DetectOlivettiMp (
+; OUT PBOOLEAN IsConfiguredMp
+; );
+;
+; Routine Description:
+; Determines the type of system (specifically for eisa machines), by reading
+; the system board ID.
+;
+; Arguments:
+; IsConfiguredMp - If LSX5030/40/40E is detected, then this value is
+; set to TRUE if more than one CPU is found, else FALSE.
+; The effect is that on returning FALSE, the standard HAL
+; is used, whilst on returning TRUE, the LSX5030 HAL is used.
+;
+; Return Value:
+; TRUE (non-zero in eax): LSX5030/40/40E detected
+; FALSE (zero in eax): non-LSX5030 detected
+;
+;--
+cPublicProc _DetectOlivettiMp,1
+
+ ; 3 byte value is read from 0c80-0c82
+
+ mov edx, 0c80h
+ in al, dx
+ cmp al, 3dh ; Manufacturer Code - 1st byte
+ jne NotAnLSX5030
+ inc edx
+ in al, dx
+ cmp al, 89h ; Manufacturer Code - 2nd byte
+ jne NotAnLSX5030
+ inc edx
+ in al, dx
+ cmp al, 03h ; Product Number part 1
+ jne NotAnLSX5030
+ ;inc edx
+ ;in al, dx
+ ;and al, 0f8h ; 5-bit Product Number part 2
+ ;cmp al, 10h
+ ;jne NotAnLSX5030
+
+;
+; Detect Processor Type reading Product Number part 2
+; Mask out Id's different from Cxh and Dxh
+;
+ mov edx, 0c8bh
+ in al, dx
+ and al, 0e0h
+ cmp al, 0c0h
+ je AnLSX5030
+
+
+NotAnLSX5030:
+ mov eax, 0
+ stdRET _DetectOlivettiMp
+
+AnLSX5030:
+
+ mov edx, dword ptr [esp+4] ; get the address of IsConfiguredMp
+ mov byte ptr [edx], 1 ; *IsConfiguredMp = TRUE
+ mov eax, 1
+
+ stdRET _DetectOlivettiMp
+
+stdENDP _DetectOlivettiMp
+
+
+_TEXT ENDS
diff --git a/private/ntos/nthals/haloli/i386/oliipi.asm b/private/ntos/nthals/haloli/i386/oliipi.asm
new file mode 100644
index 000000000..2c2886242
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliipi.asm
@@ -0,0 +1,571 @@
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; oliipi.asm
+;
+;Abstract:
+;
+; SystemPro IPI code.
+; Provides the HAL support for Interprocessor Interrupts for hte
+; MP SystemPro implementation.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;--
+.386p
+ .xlist
+
+;
+; Include LSX5030 detection code
+;
+
+include i386\olidtect.asm
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include i386\ix8259.inc
+;LSX5030 start
+include i386\olimp.inc
+ EXTRNP _HalpInitializeProcessor,1
+ extrn _IdtIpiVector:DWORD
+ extrn KiI8259MaskTable:DWORD
+;LSX5030 end
+
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalpInitializePICs,0
+ EXTRNP _HalDisplayString,1
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalDisableSystemInterrupt,2
+ extrn _HalpActiveProcessors:DWORD
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;LSX5030 start
+
+;ifdef HALOLI_DBG
+
+; for debug only
+
+public DbgDelay
+DbgDelay dd 20000000
+
+;endif
+
+; IPI IRQL decoding array
+
+public PcrIpiIrql
+PcrIpiIrql db 15
+ db 11
+ db 10
+ db 13
+
+
+;LSX5030 end
+
+;
+; Processor Control Ports
+;
+
+ public ProcessorControlPort, _HalpProcessorPCR, _HalpInitializedProcessors
+ProcessorControlPort dw PCR_P0 ; P0 Processor Control Port
+ dw PCR_P1 ; P1 Processor Control Port
+ dw PCR_P2 ; P2 Processor Control Port
+ dw PCR_P3 ; P3 Processor Control Port
+
+_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
+
+_HalpInitializedProcessors dd 0
+
+;
+;InterruptVectorControl dw 0 ; P0 none for p0
+ ;dw ICP_P1 ; P1 Processor Control Port
+ ;dw ICP_P2 ; P2 Processor Control Port
+ ;dw ICP_P3 ; P3 Processor Control Port
+
+ public _HalpFindFirstSetRight
+_HalpFindFirstSetRight db 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+
+
+ public _SystemType
+_SystemType dd 0
+
+;LSX5030 start
+BadHalString db 'HAL: LSX5030 HAL.DLL cannot be run on non LSX5030', cr, lf
+ db ' Replace the hal.dll with the correct hal', cr, lf
+ db ' System is HALTING *********', 0
+;LSX5030 end
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . Enable IPI interrupt (makes sense for P1, P2, ...).
+; . Save Processor Number in PCR.
+; . if (P0)
+; . determine what kind of system is it,
+; . if (NotSysProCompatible) Halt;
+; . InitializePICs.
+; . if (P1)
+; . program VECTOR_PORT to accept IPI at IRQ13.
+; . Save ProcesserControlPort (PCR) to PCRegion, per processor.
+; . Enable PINTs on CPU.
+;
+;Arguments:
+;
+; eax: processor number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor,1
+
+;LSX5030 start
+
+ ;DBG_DISPLAY 0a0h
+
+ ; Initialize PcIDR in PCR to enable slave IRQ
+
+ mov fs:PcIDR, 0fffffffbh
+
+ movzx eax, byte ptr [esp+4] ; get processor number
+ mov fs:PcHal.PcrNumber, al ; Save processor # in PCR
+ lock bts _HalpActiveProcessors, eax
+ lock inc _HalpInitializedProcessors
+
+ mov ecx, fs:PcSelfPcr ; Flat address of this PCR
+ mov _HalpProcessorPCR[eax*4], ecx ; Save it away
+
+ or eax, eax
+ jnz hip20_Any ; jump if not P0
+
+
+ ; For P0 only, determine if this is an LSX5030 or not.
+
+ lea eax, _SystemType ; this just to honor the
+ ; DetectOlivettiMp call interface
+ stdCall _DetectOlivettiMp,<eax>
+ ;DBG_DISPLAY 0a1h
+ mov _SystemType, eax ; Remember system type
+ or eax, eax
+ jz _NotAnLSX5030 ; (SystemType == 0): Alien machine
+
+ ; P0
+
+ ; Initialized the stall scale factor to something other that 0,
+ ; just in case KeStallExecutionProcessor was called before
+ ; HalpInitializeStallExecution (when a DbgBreakPoint() is used
+ ; before HalpInitializeStallExecution() is called.
+ ;
+
+ mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
+
+ ; load eax with the processor #
+
+ movzx eax, byte ptr fs:PcHal.PcrNumber ; get processor # from PCR
+
+
+hip20_Any:
+
+ ; Note: at this point eax must contain the processor number
+
+ mov dx, word ptr ProcessorControlPort[eax*2]
+ in al, dx ; get PCR status
+ and al, not PINT ; clear IPI pending bit
+ or al, IPI_EN ; enable IPI's
+ out dx, al ; store the new PCR status
+
+ mov fs:PcHal.PcrControlPort, dx ; Save port value
+
+ movzx eax, byte ptr [esp+4] ; get processor number
+ or eax, eax
+ jz hip30_Any ; jump if P0
+
+ ; init PICs, interval timer, stall scale factor...
+
+ ;DBG_DISPLAY 0a2h
+
+ stdCall _HalpInitializeProcessor,<eax>
+
+ ;DBG_DISPLAY 0a3h
+
+hip30_Any:
+
+
+;LSX5030 end
+
+ stdRET _HalInitializeProcessor
+
+;LSX5030 start
+
+_NotAnLSX5030:
+ stdCall _HalDisplayString,<offset BadHalString>
+ hlt
+
+;LSX5030 end
+
+
+stdENDP _HalInitializeProcessor
+
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalRequestIpi,1
+
+ movzx ecx, byte ptr [esp+4] ; (eax) = Processor bitmask
+
+ifdef DBG
+ or ecx, ecx ; must ipi somebody
+ jz short ipibad
+
+ movzx eax, byte ptr fs:PcHal.PcrNumber
+ bt ecx, eax ; cannot ipi yourself
+ jc short ipibad
+endif
+
+@@:
+ movzx eax, _HalpFindFirstSetRight[ecx] ; lookup first processor to ipi
+ btr ecx, eax
+ mov dx, ProcessorControlPort[eax*2]
+ in al, dx ; (al) = original content of PCP
+ or al, PINT ; generate Ipi on target
+ out dx, al
+ or ecx, ecx ; ipi any other processors?
+ jnz @b ; yes, loop
+
+ stdRET _HalRequestIpi
+
+ifdef DBG
+ipibad: int 3
+ stdRET _HalRequestIpi
+endif
+
+stdENDP _HalRequestIpi
+
+
+ page ,132
+ subttl "LSX5030 Inter-Processor Interrupt Handler"
+
+;LSX5030 start
+
+;++
+;
+; VOID
+; HalpIpiHandler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by inter
+; processor communication.
+; The interrupt is dismissed.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hixx_a, Hixx_t
+
+cPublicProc _HalpIpiHandler,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hixx_a, Hixx_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+ mov eax, _IdtIpiVector
+ push eax ; Vector
+ sub esp, 4 ; space for OldIrql
+
+ ;DBG_DISPLAY 90h
+
+; Dismiss interrupt.
+;
+ mov dx, fs:PcHal.PcrControlPort
+
+ in al, dx
+
+;
+; Dismiss the interprocessor interrupt and call its handler
+;
+
+ and al, not PINT
+ out dx, al ; clear PINT
+
+
+ ;DBG_DISPLAY 91h
+
+ mov eax, _IdtIpiVector
+
+; esp - stack location of OldIrql
+; eax - vector
+; IPI_LEVEL - Irql
+
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,eax,esp>
+
+ ;DBG_DISPLAY 92h
+
+; Pass Null ExceptionFrame
+; Pass TrapFrame to Ipi service rtn
+ stdCall _KiIpiServiceRoutine ,<ebp,0>
+
+;
+; Do interrupt exit processing
+;
+ ;DBG_DISPLAY 9fh
+
+
+ INTERRUPT_EXIT ; will return to caller
+
+
+stdENDP _HalpIpiHandler
+
+
+ifdef HALOLI_DBG
+
+;++
+;
+; DbgDisplay (
+; IN UCHAR DisplayCode
+; )
+;
+; Description:
+;
+; This function writes 'DisplayCode' to the parallel port, where a LED
+; display can be plugged in to show such a code.
+; In order to allow the user to read the code on the LED display,
+; after writing, a delay is introduced.
+;
+; Arguments:
+; DisplayCode - Byte to write to the parallel port
+;
+; Return Value:
+; None.
+;
+;--
+
+public _DbgDisplay
+_DbgDisplay proc
+
+
+ push eax
+ push edx
+
+ ; signal something on the parallel port
+
+ mov dx, 378h
+ mov eax, [esp+12]
+ out dx, al
+
+ mov eax, DbgDelay
+
+@@:
+ dec eax
+ cmp eax, 0
+ jne @b
+ pop edx
+ pop eax
+
+
+ ret
+ _DbgDisplay endp
+
+endif ; HALOLI_DBG
+
+
+; ULONG
+; HalpGetIpiIrqNumber (
+; );
+;
+; Routine Description:
+;
+; This routine is entered during the phase 0 initialization of the
+; first processor. It determines the IRQ # for IPI's.
+; The IPI IRQ is stored in the PCR's by the LSX5030 configuration
+; utility.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The IPI IRQ# in eax.
+;
+;--
+
+cPublicProc _HalpGetIpiIrqNumber,0
+
+
+ mov dx, word ptr ProcessorControlPort ; get 1st CPU slot #
+ in al, dx ; get PCR content
+
+ ; determine which IRQ for IPI has been set by the user
+
+ shr eax, 2 ; bits 0,1 encode the IPI IRQ
+ and eax, 3 ; zero all the bits but 0,1
+ movzx ecx, byte ptr PcrIpiIrql[eax] ; decode the IRQ
+ push ecx
+
+ ; edit the 8259 mask table to unmask IPI's from IPI_LEVEL-1 down
+
+ mov edx, 1
+ shl edx, cl
+ not edx ; mask with IPI IRQ# bit set to
+ ; 0
+; mov eax, IPI_LEVEL
+; sub eax, ecx
+ lea eax, KiI8259MaskTable ; start from the beginning
+; lea eax, KiI8259MaskTable[eax*4] ; start from
+ ; IPI_LEVEL - IPI_IRQ#
+ mov ecx, IPI_LEVEL
+
+NextEntry:
+ and [eax], edx
+ add eax, 4
+ dec ecx ; loop for IPI IRQ# times
+ jnz NextEntry
+
+ pop eax ; return IPI IRQ#
+
+ stdRET _HalpGetIpiIrqNumber
+stdENDP _HalpGetIpiIrqNumber
+
+
+ page ,132
+ subttl "Irq13 Interrupt Handler"
+;++
+;
+; VOID
+; HalpIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by
+; coprocessor error,
+; This routine will lower irql to its original level, and finally invoke
+; coprocessor error handler. By doing this, the coprocessor
+; error will be handled at Irql 0 as it should be.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hi13_a, Hi13_t
+
+cPublicProc _HalpIrq13Handler,0
+
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+ push 13 + PRIMARY_VECTOR_BASE ; Vector
+ sub esp, 4 ; space for OldIrql
+;
+; Dismiss interrupt.
+
+; location for OldIrql
+; Vector
+; Irql
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,13+PRIMARY_VECTOR_BASE,esp>
+
+ stdCall _KiCoprocessorError ; call CoprocessorError handler
+
+;
+; Do interrupt exit processing
+;
+
+ INTERRUPT_EXIT ; will return to caller
+
+
+stdENDP _HalpIrq13Handler
+
+;LSX5030 end
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/haloli/i386/oliirql.asm b/private/ntos/nthals/haloli/i386/oliirql.asm
new file mode 100644
index 000000000..b18871e22
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliirql.asm
@@ -0,0 +1,669 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; oliirql.asm
+;
+; Abstract:
+;
+; SystemPro IRQL
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the 8259 PIC.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; John Vert (jvert) 27-Nov-1991
+; Moved from kernel into HAL
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+;LSX5030 start
+include i386\olimp.inc
+;LSX5030 end
+
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ extrn _HalpApcInterrupt:NEAR
+ extrn _HalpDispatchInterrupt:NEAR
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+; extrn _HalpSWNonPrimaryClockTick2ndEntry:NEAR
+ extrn _KiUnexpectedInterrupt:NEAR
+ extrn _HalpBusType:DWORD
+
+;
+; Initialization control words equates for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW2_SET_PRIORITY equ 0c0H
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+
+;
+; Interrupt flag bit maks for EFLAGS
+;
+
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+
+;
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; PICsInitializationString - Master PIC initialization command string
+;
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+PS2PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+
+ align 4
+
+;LSX5030 start
+
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 00000000000000000000000000000000B ; irql 4
+ dd 11111111110000000000000000000000B ; irql 5
+ dd 11111111111000000000000000000000B ; irql 6
+ dd 11111111111100000000000000000000B ; irql 7
+ dd 11111111111110000000000000000000B ; irql 8
+ dd 11111111111111000000000000000000B ; irql 9
+ dd 11111111111111100000000000000000B ; irql 10
+ dd 11111111111111110000000000000000B ; irql 11
+ dd 11111111111111111000000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111110000000000000B ; irql 14
+ dd 11111111111111111111000000000000B ; irql 15
+ dd 11111111111111111111100000000000B ; irql 16
+ dd 11111111111111111111110000000000B ; irql 17
+ dd 11111111111111111111111000000000B ; irql 18
+ dd 11111111111111111111111000000000B ; irql 19
+ dd 11111111111111111111111010000000B ; irql 20
+ dd 11111111111111111111111011000000B ; irql 21
+ dd 11111111111111111111111011100000B ; irql 22
+ dd 11111111111111111111111011110000B ; irql 23
+ dd 11111111111111111111111011111000B ; irql 24
+ dd 11111111111111111111111011111000B ; irql 25
+ dd 11111111111111111111111011111010B ; irql 26
+ dd 11111111111111111111111111111010B ; irql 27
+ dd 11111111111111111111111111111011B ; irql 28
+ dd 11111111111111111111111111111011B ; irql 29
+ dd 11111111111111111111111111111011B ; irql 30
+ dd 11111111111111111111111111111011B ; irql 31
+;LSX5030 end
+
+ align 4
+;
+; The following tables define the addresses of software interrupt routers
+;
+
+;
+; Use this table if there is NO machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt ; irql 2
+
+;
+; Use this table if there is a machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable2
+SWInterruptHandlerTable2 label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt2ndEntry ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt2ndEntry ; irql 2
+
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+; equates for accessing arguments
+; since eflags and iret addr are pushed into stack, all the arguments
+; offset by 8 bytes
+;
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,1
+
+ pushfd ; save caller's eflags
+
+ movzx eax, cl ; (eax) = NewIrql
+ mov cl, fs:PcIrql ; get current irql
+
+if DBG
+ cmp cl,al ; old > new?
+ jbe short Kri99 ; no, we're OK
+ push eax ; put new irql where we can find it
+ push ecx ; put old irql where we can find it
+ mov byte ptr fs:PcIrql,0 ; avoid recursive error
+ stdCall _KeBugCheck,<IRQL_NOT_GREATER_OR_EQUAL>
+Kri99:
+endif
+
+ cmp al,DISPATCH_LEVEL ; software level?
+ cli ; disable interrupt
+ mov fs:PcIrql, al ; set the new irql
+ jbe kri10 ; go skip setting 8259 hardware
+
+ mov eax, KiI8259MaskTable[eax*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+kri10: popfd ; restore flags (including interrupts)
+
+ mov al, cl ; return old irql
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+
+ mov ecx, DISPATCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+
+ mov ecx, SYNCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+ page ,132
+ subttl "Lower irql"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall KfLowerIrql,1
+
+ pushfd ; save caller's eflags
+ movzx ecx, cl ; (ecx) = new irql value
+
+if DBG
+ cmp cl,fs:PcIrql
+ jbe short Kli99
+ push ecx ; new irql for debugging
+ push fs:PcIrql ; old irql for debugging
+ mov byte ptr fs:PcIrql,HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck,<IRQL_NOT_LESS_OR_EQUAL>
+Kli99:
+endif
+
+ cmp byte ptr fs:PcIrql,DISPATCH_LEVEL ; Software level?
+ cli
+ jbe kli02 ; yes, go skip setting 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+kli02: mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja Kli10 ; yes, go simulate interrupt
+
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql
+
+; When we come to Kli10, (eax) = soft interrupt index
+
+Kli10:
+ call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+ popfd
+ fstRET KfLowerIrql
+
+fstENDP KfLowerIrql
+
+;++
+;
+; VOID
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HeiNewIrql equ [esp + 4]
+
+cPublicProc _HalEndSystemInterrupt,2
+
+ movzx ecx, byte ptr HeiNewIrql; get new irql value
+
+ cmp byte ptr fs:PcIrql, DISPATCH_LEVEL ; Software level?
+ jbe short Hei02 ; yes, go skip setting 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+;
+; Unlike KeLowerIrql, we don't check if the the irql is lowered to
+; below IPI level and enable interrupt for second processor. This is because
+; the correct interrupt flag is already stored in the TsEflags of Trap frame.
+;
+
+Hei02: mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja Hei10 ; yes, go simulate interrupt
+
+ stdRET _HalEndSystemInterrupt ; RETURN
+
+; When we come to Kli10, (eax) = soft interrupt index
+
+Hei10: add esp, 12
+ jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+stdENDP _HalEndSystemInterrupt
+
+;++
+;
+; VOID
+; HalpEndSoftwareInterrupt
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL from software interrupt
+; level to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalpEndSoftwareInterrupt,1
+cPublicFpo 1,0
+ mov ecx, [esp+4]
+ fstCall KfLowerIrql
+ stdRet _HalpEndSoftwareInterrupt
+stdENDP _HalpEndSoftwareInterrupt
+
+ page ,132
+ subttl "Get current irql"
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql,0
+ movzx eax,byte ptr fs:PcIrql ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+
+ ;
+ ; Raising to HIGH_LEVEL disables interrupts for the Oli-HAL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine sends the 8259 PIC initialization commands and
+; masks all the interrupts on 8259s.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs,0
+
+ push esi ; save caller's esi
+ cli ; disable interrupt
+ lea esi, PICsInitializationString
+
+Hip00:
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ mov al, 0FFH ; mask all 8259 irqs
+ out dx,al ; write mask to PIC
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+ pop esi ; restore caller's esi
+ sti ; enable interrupt
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/haloli/i386/olimapin.c b/private/ntos/nthals/haloli/i386/olimapin.c
new file mode 100644
index 000000000..60d80553f
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olimapin.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ olimapin.c
+
+Abstract:
+
+ This module implements the HAL HalGetInterruptVector routine
+ for an x86 system
+
+Author:
+
+ John Vert (jvert) 17-Jul-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Bruno Sartirana (o-obruno) 4-Aug-1992
+ Added static interrupts assignement to the CPUs for LSX5030.
+
+--*/
+
+#include "halp.h"
+
+extern ULONG HalpInitializedProcessors;
+BOOLEAN HalpPciLockSettings; // make it build
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+
+ if (BusAddress.HighPart != 0 || *AddressSpace > 1) {
+ return (FALSE);
+ }
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+
+ return(TRUE);
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ SystemVector = BusInterruptLevel + PRIMARY_VECTOR_BASE;
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ SystemVector > PRIMARY_VECTOR_BASE + HIGHEST_LEVEL_FOR_8259 ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = (KIRQL)(HIGHEST_LEVEL_FOR_8259 + PRIMARY_VECTOR_BASE - SystemVector);
+
+ //
+ // On LSX5030 any CPU can handle any interrupt.
+ //
+
+ *Affinity = 1 << BusInterruptLevel % HalpInitializedProcessors;
+ return SystemVector;
+}
+
diff --git a/private/ntos/nthals/haloli/i386/olimp.inc b/private/ntos/nthals/haloli/i386/olimp.inc
new file mode 100644
index 000000000..c75d8dca2
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olimp.inc
@@ -0,0 +1,166 @@
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; olimp.inc
+;
+; Abstract:
+;
+; LSX5030 MP include file
+;
+; Author:
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+;
+;--
+
+
+
+
+
+;*****************************
+; Olivetti LSX5030 defines
+;
+
+MAX_NUMBER_PROCESSORS_MASK equ 0fh ; Maximum number of processors
+ ; bitmask
+MAX_NUMBER_PROCESSORS equ 4 ; Maximum number of processors
+RESET_WO_EOI equ 00ah ; Reset with out EOI
+WarmResetVector equ 467h ; warm reset vector in ROM data segment
+
+
+; Multi-Processor Control and Configuration Registers I/O Locations:
+
+PCR_Px equ 0c6ah ; control register offset
+;LEV2_CACHE_REG equ 0c94h ; level 2 cache register offset
+
+P0_SLOT equ 00000h
+P1_SLOT equ 0c000h
+P2_SLOT equ 0d000h
+P3_SLOT equ 0e000h
+
+Px_SLOT_MASK equ 0f000h
+
+PCR_P0 equ P0_SLOT + PCR_Px
+PCR_P1 equ P1_SLOT + PCR_Px
+PCR_P2 equ P2_SLOT + PCR_Px
+PCR_P3 equ P3_SLOT + PCR_Px
+
+
+; WHO AM I Register
+
+PROC_ID_PORT equ 0c70h ; who am I
+
+
+; Multi-Processor Control Register Bit Definitions:
+
+IPI_EN equ 080h ; Inter-Processor Interrupt Enable bit
+PINT equ 040h ; Inter-Processor Interrupt bit
+IPI_IRQ10 equ 008h ; Inter-processor-interrupt vectors
+IPI_IRQ11 equ 004h
+IPI_IRQ13 equ 00ch
+IPI_IRQ15 equ 000h
+RESET equ 001h ; RESET processor bit (1-0 transition
+
+; Multi-Processor 2nd Level Cache Policy Registers Bit Definitions
+
+;LEV2_CACHE_ON equ 80h ; 2nd level cache enable bit
+
+
+;
+; The kernel leaves some space (64 byte) of the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation
+; dependant.
+;
+
+
+PcrE struc
+ PcrControlPort dw 0 ; Processor's control port
+ PcrNumber db 0 ; Processor's number
+PcrE ends
+
+
+cr equ 0ah
+lf equ 0dh
+
+
+
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT equ 70h ; command port for cmos
+CMOS_DATA_PORT equ 71h ; cmos data port
+
+CMOS_GET_MP_STATUS equ 36h ; offset for MP status
+
+;
+; Macros to Read/Write/Reset CMOS
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ macro
+ out CMOS_CONTROL_PORT, al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ in al, CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+endm
+
+;++
+;
+; DBG_DISPLAY DisplayCode
+;
+; Macro Description:
+;
+; This macro writes 'DisplayCode' to the parallel port, where a LED
+; display can be plugged in to show such a code.
+; In order to allow the user to read the code on the LED display,
+; after writing, a delay is introduced.
+;
+; Arguments:
+; DisplayCode - Byte to write to the parallel port
+;
+;
+;--
+
+DBG_DISPLAY macro DisplayCode
+
+ifdef HALOLI_DBG
+
+ push eax
+ push edx
+
+ ; signal something on the parallel port
+
+ mov dx, 378h
+ mov al, DisplayCode
+ out dx, al
+
+ mov eax, DbgDelay
+
+@@:
+ dec eax
+ cmp eax, 0
+ jne @b
+ pop edx
+ pop eax
+
+endif ; HALOLI_DBG
+
+ endm
+
+
+;*****************************
+; end of list
diff --git a/private/ntos/nthals/haloli/i386/oliproca.asm b/private/ntos/nthals/haloli/i386/oliproca.asm
new file mode 100644
index 000000000..6e72e8efe
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliproca.asm
@@ -0,0 +1,478 @@
+ title "MP primitives for Compaq SystemPro"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; oliproca.asm
+;
+;Abstract:
+;
+; SystemPro Start Next Processor assemble code
+;
+; This module along with mpspro.c implement the code to start
+; off the second processor on the Compaq SystemPro.
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;
+;Revision History:
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+;LSX5030 start
+include i386\ix8259.inc
+include i386\olimp.inc
+;LSX5030 end
+ .list
+
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+
+ extrn _MppIDT:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+ extrn ProcessorControlPort:WORD
+;LSX5030 start
+ extrn _CpuLeft:DWORD
+ extrn _NextCpuToStart:DWORD
+ extrn DbgDelay:DWORD
+;LSX5030 end
+
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_ControlPort dd ?
+ SPx_PB db processorstatelength dup (?)
+PxParamBlock ends
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+
+
+cPublicProc _HalStartNextProcessor ,2
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+ DBG_DISPLAY 0f0h
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.SPx_flag, eax
+
+ cmp _CpuLeft, eax
+ je snp_exit ; exit FALSE
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+ mov edi, _MpLowStub ; Copy RMStub to low memory
+ add edi, size PxParamBlock
+ rep movsb
+
+ lea edi, PxFrame.SPx_PB
+ mov esi, pProcessorState
+ mov ecx, processorstatelength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+
+ stdCall _HalpBuildTiledCR3,<pProcessorState>
+
+ mov PxFrame.SPx_TiledCR3, eax
+ mov PxFrame.SPx_P0EBP, ebp
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+ movzx edx, ProcessorControlPort[eax*2] ; Get processor's control port
+ mov PxFrame.SPx_ControlPort, edx ; Pass it along
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _MpLowStub
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx ; patch realmode stub with
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
+
+ mov ebx, _MppIDT
+ add ebx, WarmResetVector
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+
+ mov eax, _MpLowStubPhysicalAddress
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+
+;LSX5030 start
+ mov eax, _NextCpuToStart
+ mov dx, word ptr ProcessorControlPort[eax*2]
+ in al, dx
+ or al, RESET ; assert RESET
+ out dx, al
+ and al, not RESET ; the 1-0 transition of PCR
+ ; reset bit resets the
+ ; processor
+ out dx, al ; reset processor
+;LSX5030 end
+
+@@:
+ cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's
+ jz @b ; info
+
+ pop dword ptr [ebx] ; restore WarmResetVector
+
+ sti
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+
+;LSX5030 start
+ DBG_DISPLAY 0ffh
+
+ dec _CpuLeft ; one less
+ inc _NextCpuToStart ; next CPU # to start
+;LSX5030 end
+
+ mov eax, 1 ; return TRUE
+
+snp_exit:
+ DBG_DISPLAY 0feh
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ stdRET _HalStartNextProcessor
+
+_HalStartNextProcessor endp
+
+
+_TEXT ends ; end 32 bit code
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub,0
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+stdENDP StartPx_RMStub
+
+
+_TEXT16 ends ; End 16 bit code
+
+_TEXT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+ align 16 ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+ public _StartPx_PMStub
+_StartPx_PMStub proc
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+
+ ; eax, ebx, edx are still free
+
+;LSX5030 start
+ mov eax, _NextCpuToStart
+ mov dx, word ptr ProcessorControlPort[eax*2]
+ in al, dx ; Get register
+ and al, not IPI_EN ; disable PINTs for now
+ out dx, al
+ ;and dx, Px_SLOT_MASK ; get processor slot (olibus)
+ ;or dx, LEV2_CACHE_REG ; calculate address of the 2nd
+ ; level cache policy register
+ ; for this processor
+ ;in al, dx ; Get register
+ ;and al, not LEV2_CACHE_ON ; turn cache off
+ ;or al, LEV2_CACHE_ON ; turn cache on
+ ;out dx, al
+ ;and dx, Px_SLOT_MASK ; get processor slot (olibus)
+ ;or dx, SLOT_CONFIG_REG_0 ; calculate address of
+ ; configuration register 0 for
+ ; this processor
+ ;in al, dx ; get register
+ ;and al, not INTERNAL_CACHE_ON ; turn internal cache off
+ ;or al, INTERNAL_CACHE_ON ; turn processor's internal
+ ; cache on
+ ;out dx, al
+
+ ;DBG_DISPLAY 0b0h
+
+; sti
+
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with its data
+ ;DBG_DISPLAY 0bfh
+
+;LSX5030 end
+
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ ret ; Set eip
+
+_StartPx_PMStub endp
+
+;LSX5030 start
+;++
+;
+; ULONG
+; HalpGetNumberOfProcessors()
+;
+; Routine Description:
+;
+; This routine queries the CMOS to determine the number of processors
+; that can be started.
+; Also, it rearranges the ProcessorControlPort array to make it
+; non-sparse. This means that, eventually, ProcessorControlPort[n]
+; will contain the slot # of the processor n, where n=0,1,2,3.
+; For example, if the machine has two processors, one in slot 0 and
+; the other in slot 3, only the ProcessorControlPort array elements
+; #0 and #1 will be meaningful.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The number of available processors in register eax.
+;
+;--
+
+cPublicProc _HalpGetNumberOfProcessors,0
+
+
+ push ebx
+ push ecx
+ push edx
+ mov al, CMOS_GET_MP_STATUS
+ CMOS_READ
+ mov ch, al ; al[7-4] = CPU card present bits
+ ; al[3-0] = CPU diagnostics passed bits
+ shr al, 4 ; al[3-0] = CPU card present bits
+ mov cl, al ; ch[3-0] = CPU card diag passed bits
+ ; cl[3-0] = CPU card present bits
+ and cl, ch ; CPUs actually available (bit mapped)
+
+ mov edx, 1 ; there's always the CPU0, so skip it
+ mov eax, 1 ; logical processor #
+NextCPU:
+ bt ecx, edx
+ jnc IncLoopCounter
+ mov bx, word ptr ProcessorControlPort[edx*2] ; get address of
+ ; PCP #edx
+ mov word ptr ProcessorControlPort[eax*2], bx ; set PCP address
+ ; for processor #eax
+ inc eax
+IncLoopCounter:
+ inc edx
+ cmp edx, MAX_NUMBER_PROCESSORS
+ jl NextCPU
+
+ pop edx
+ pop ecx
+ pop ebx
+
+ stdRET _HalpGetNumberOfProcessors
+
+stdENDP _HalpGetNumberOfProcessors
+
+;LSX5030 end
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/haloli/i386/olisproc.c b/private/ntos/nthals/haloli/i386/olisproc.c
new file mode 100644
index 000000000..1de78859f
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olisproc.c
@@ -0,0 +1,581 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ olisproc.c
+
+Abstract:
+
+ SystemPro Start Next Processor c code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ MP Compaq SystemPro
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Bruno Sartirana (o-obruno) 3-Mar-92
+ Added support for the Olivetti LSX5030.
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "Olivetti LSX5030 MP Hal";
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+//LSX5030 start
+
+
+ULONG
+HalpGetIpiIrqNumber();
+
+VOID
+HalpIpiHandler(
+ VOID
+ );
+
+ULONG
+HalpGetNumberOfProcessors();
+
+
+#ifdef HALOLI_DBG
+
+VOID
+DbgDisplay(
+ IN UCHAR Code
+ );
+# define DBG_DISPLAY(x) DbgDisplay(x)
+#else
+# define DBG_DISPLAY(x)
+#endif
+
+
+
+/***
+ * Olivetti LSX5030 varialbles and constants
+ */
+
+
+
+ULONG IpiVector; // Inter-processor interrupt vector
+ULONG IdtIpiVector; // Inter-processor interrupt vector # in
+ // the IDT
+ULONG HalpCpuCount; // total number of CPU's available
+ULONG CpuLeft; // number of CPU's not started yet
+ULONG NextCpuToStart = 1; // next CPU logical # to start
+
+
+// LSX5030 end
+
+
+
+#define LOW_MEMORY 0x000100000
+#define MAX_PT 8
+
+extern VOID __cdecl StartPx_PMStub(VOID);
+
+
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR MppIDT; // pointer to physical memory 0:0
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ PKPCR pPCR;
+ KIRQL CurrentIrql;
+
+
+ pPCR = KeGetPcr();
+
+ if (Phase == 0) {
+
+ //
+ // Only Processor 0 runs the phase 0 initializtion code
+ //
+
+ //DBG_DISPLAY(0x00);
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+//LSX5030 start
+ IpiVector = HalpGetIpiIrqNumber();
+ IdtIpiVector = IpiVector + PRIMARY_VECTOR_BASE;
+
+ HalpCpuCount = HalpGetNumberOfProcessors();
+ CpuLeft = HalpCpuCount - 1;
+
+ if (CpuLeft == 0) {
+
+ //
+ // Only 1 CPU available
+ //
+
+ return TRUE;
+ }
+
+
+ //
+ // Register IPI handler
+ //
+
+ KiSetHandlerAddressToIDT(PRIMARY_VECTOR_BASE + IpiVector,
+ HalpIpiHandler);
+
+ //
+ // Enable inter-processor interrupts on CPU 0
+ //
+
+ HalEnableSystemInterrupt(PRIMARY_VECTOR_BASE + IpiVector,
+ IPI_LEVEL, 0);
+
+//LSX5030 end
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress)
+ return TRUE;
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+
+ } else {
+
+ //
+ // Phase 1
+ //
+
+ //DBG_DISPLAY(0x10);
+ //
+ // Check to see if this is not processor 0
+ //
+
+ if (pPCR->Prcb->Number != 0) {
+
+ //DBG_DISPLAY(0x11);
+ //
+ // It is not processor 0. Mask the PICs and start the clock.
+ //
+
+ //
+ // Mask the PICs to reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ CurrentIrql = KfRaiseIrql (CurrentIrql);
+
+
+ //
+ // Initialize the timer 1 counter 0
+ //
+
+ HalpInitializeClock();
+ //DBG_DISPLAY(0x12);
+
+ //
+ // Initialize the clock interrupt vector and enable the
+ // clock interrupt.
+ //
+
+ KiSetHandlerAddressToIDT(CLOCK_VECTOR, HalpClockInterrupt );
+ HalEnableSystemInterrupt(CLOCK_VECTOR, CLOCK2_LEVEL, Latched);
+ //DBG_DISPLAY(0x13);
+ }
+ }
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Eisa // The LSX5030 is an Eisa machine
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+}
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+
+
+VOID
+HalpInitializeProcessor (
+ IN UCHAR ProcessorNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the current CPU's PIC's and clock.
+
+Arguments:
+
+ ProcessorNumber: current processor
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL CurrentIrql;
+
+
+
+
+
+ //DBG_DISPLAY(0x70);
+
+// if (ProcessorNumber != '\0') {
+
+ //
+ // For processor 0 only initialize PICs and stall execution counter.
+ //
+
+ HalpInitializePICs();
+
+ //
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ //DBG_DISPLAY(0x71);
+
+ CurrentIrql = KeGetCurrentIrql();
+ //DBG_DISPLAY(0x72);
+
+ KeRaiseIrql(CurrentIrql, &CurrentIrql);
+ //DBG_DISPLAY(0x73);
+
+ //
+ // Note that HalpInitializeClock MUST be called after
+ // HalpInitializeStallExecution, because
+ // HalpInitializeStallExecution reprograms the timer.
+ //
+
+ HalpInitializeStallExecution(ProcessorNumber);
+ //DBG_DISPLAY(0x74);
+
+ // }
+
+ //
+ // Register IPI handler
+ //
+
+ KiSetHandlerAddressToIDT(PRIMARY_VECTOR_BASE + IpiVector , HalpIpiHandler);
+ //DBG_DISPLAY(0x75);
+
+ //
+ // Enable inter-processor interrupts on this CPU
+ //
+
+ HalEnableSystemInterrupt(PRIMARY_VECTOR_BASE + IpiVector,
+ (KIRQL) IPI_LEVEL,
+ (KINTERRUPT_MODE) 0);
+
+ //DBG_DISPLAY(0x76);
+
+
+ return;
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+}
+
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
+
+
+
diff --git a/private/ntos/nthals/haloli/i386/olisyint.asm b/private/ntos/nthals/haloli/i386/olisyint.asm
new file mode 100644
index 000000000..17476ff92
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olisyint.asm
@@ -0,0 +1,386 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; olisyint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts, for the MP systempro implementation
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+;LSX5030 start
+include i386\olimp.inc
+;LSX5030 end
+ .list
+
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeBugCheck,1,IMPORT
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; Macros to Read/Write/Reset CMOS to initialize RTC
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+align dword
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irq 0
+ dd offset FLAT:HalpDismissNormal ; irq 1
+ dd offset FLAT:HalpDismissNormal ; irq 2
+ dd offset FLAT:HalpDismissNormal ; irq 3
+ dd offset FLAT:HalpDismissNormal ; irq 4
+ dd offset FLAT:HalpDismissNormal ; irq 5
+ dd offset FLAT:HalpDismissNormal ; irq 6
+ dd offset FLAT:HalpDismissIrq07 ; irq 7
+ dd offset FLAT:HalpDismissNormal ; irq 8
+ dd offset FLAT:HalpDismissNormal ; irq 9
+ dd offset FLAT:HalpDismissNormal ; irq A
+ dd offset FLAT:HalpDismissNormal ; irq B
+ dd offset FLAT:HalpDismissNormal ; irq C
+ dd offset FLAT:HalpDismissNormal ; irq D
+ dd offset FLAT:HalpDismissNormal ; irq E
+ dd offset FLAT:HalpDismissIrq0f ; irq F
+ dd offset FLAT:HalpDismissNormal ; irq 10
+ dd offset FLAT:HalpDismissNormal ; irq 11
+ dd offset FLAT:HalpDismissNormal ; irq 12
+ dd offset FLAT:HalpDismissNormal ; irq 13
+ dd offset FLAT:HalpDismissNormal ; irq 14
+ dd offset FLAT:HalpDismissNormal ; irq 15
+ dd offset FLAT:HalpDismissNormal ; irq 16
+ dd offset FLAT:HalpDismissNormal ; irq 17
+ dd offset FLAT:HalpDismissNormal ; irq 18
+ dd offset FLAT:HalpDismissNormal ; irq 19
+ dd offset FLAT:HalpDismissNormal ; irq 1A
+ dd offset FLAT:HalpDismissNormal ; irq 1B
+ dd offset FLAT:HalpDismissNormal ; irq 1C
+ dd offset FLAT:HalpDismissNormal ; irq 1D
+ dd offset FLAT:HalpDismissNormal ; irq 1E
+ dd offset FLAT:HalpDismissNormal ; irq 1F
+ dd offset FLAT:HalpDismissNormal ; irq 20
+ dd offset FLAT:HalpDismissNormal ; irq 21
+ dd offset FLAT:HalpDismissNormal ; irq 22
+ dd offset FLAT:HalpDismissNormal ; irq 23
+
+_DATA ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt,3
+ movzx ebx,HbsiVector ; (ebx) = System Vector
+ sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ #
+
+ cmp ebx, 24h ; Interrupt in table?
+ jnc hbsi00 ; no go handle
+ jmp HalpSpecialDismissTable[ebx*4]
+
+hbsi00:
+;
+; Interrupt is out of range. There's no EOI here since it wouldn't
+; have been out of range if it occured on either interrupt controller
+; which is known about.
+;
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissNormal:
+;
+; Store OldIrql
+;
+ mov eax, HbsiOldIrql
+ movzx ecx, byte ptr fs:PcIrql
+ mov byte ptr [eax], cl
+
+;
+; Raise IRQL to requested level
+;
+ movzx eax, HbsiIrql ; (eax) = irql
+ ; (ebx) = IRQ #
+
+ mov fs:PcIrql, al ; set new Irql
+
+
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, fs:PcIDR ; mask disabled irqs
+ SET_8259_MASK ; send mask to 8259s
+
+;
+; Dismiss interrupt. Current interrupt is already masked off.
+;
+ mov eax, ebx ; (eax) = IRQ #
+ cmp eax, 8 ; EOI to master or slave?
+
+ jae short Hbsi100 ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short Hbsi200 ; IO delay
+
+Hbsi100:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+Hbsi200:
+ PIC1DELAY
+
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt,2
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or fs:PcIDR, edx
+ xor eax, eax
+
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt,3
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc hes_error
+ cmp ecx, CLOCK2_LEVEL
+ jnc hes_error
+
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ cli
+ and fs:PcIDR, eax
+
+;
+; Get the PIC masks for the current Irql
+;
+ movzx eax, byte ptr fs:PcIrql
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, fs:PcIDR
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+hes_error:
+if DBG
+ int 3
+endif
+ xor eax, eax ; FALSE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/haloli/i386/pcip.h b/private/ntos/nthals/haloli/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/haloli/i386/spspin.asm b/private/ntos/nthals/haloli/i386/spspin.asm
new file mode 100644
index 000000000..0d70c442f
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/spspin.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halsp
+; This is a cpp style symbolic link
+
+include ..\halsp\i386\spspin.asm
diff --git a/private/ntos/nthals/haloli/i386/xxbiosa.asm b/private/ntos/nthals/haloli/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/haloli/i386/xxbiosc.c b/private/ntos/nthals/haloli/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/haloli/i386/xxdisp.c b/private/ntos/nthals/haloli/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/haloli/i386/xxflshbf.c b/private/ntos/nthals/haloli/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/haloli/i386/xxhal.c b/private/ntos/nthals/haloli/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxhal.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxhal.c"
diff --git a/private/ntos/nthals/haloli/i386/xxioacc.asm b/private/ntos/nthals/haloli/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/haloli/i386/xxkdsup.c b/private/ntos/nthals/haloli/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/haloli/i386/xxmemory.c b/private/ntos/nthals/haloli/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/haloli/i386/xxstubs.c b/private/ntos/nthals/haloli/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/haloli/i386/xxtime.c b/private/ntos/nthals/haloli/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/haloli/makefile b/private/ntos/nthals/haloli/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haloli/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haloli/makefile.inc b/private/ntos/nthals/haloli/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/haloli/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/haloli/sources b/private/ntos/nthals/haloli/sources
new file mode 100644
index 000000000..30c7ed5cf
--- /dev/null
+++ b/private/ntos/nthals/haloli/sources
@@ -0,0 +1,96 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haloli
+TARGETPATH=\nt\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixdat.c \
+ i386\ixisabus.c \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixinfo.c \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\ixnmi.c \
+ i386\ixphwsup.c \
+ i386\ixswint.asm \
+ i386\ixthunk.c \
+ i386\ixreboot.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxhal.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c \
+ i386\spspin.asm \
+ i386\oliclock.asm \
+ i386\oliirql.asm \
+ i386\oliipi.asm \
+ i386\olisyint.asm \
+ i386\olimapin.c \
+ i386\olisproc.c \
+ i386\oliproca.asm
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\haloli.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halpinna/alpha/addrsup.c b/private/ntos/nthals/halpinna/alpha/addrsup.c
new file mode 100644
index 000000000..d271cc07a
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/addrsup.c
@@ -0,0 +1,596 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Mikasa EV5 (Pinnacle) system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Scott Lee (Digital) 29-Nov-1995
+ Adapted this from Mikasa version for Mikasa EV5 (Pinnacle) systems.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "mikasa.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call HalCreateQva to
+ build a Quasi Virtual Address and return that to the caller. We then
+ set AddressSpace to a 1, so that the caller will not call MmMapIoSpace.
+ The Caller will use the low 32 bits of the physical address we return
+ as the VA. (Which we built a QVA in).
+
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The buses available on Mikasa are EISA and PCI.
+ // We support any translations for ISA devices as well,
+ // since they can plug into EISA slots just fine.
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system; return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case Eisa:
+
+ //
+ // Eisa is the same as PCI, with respect to kernel mode
+ // sparse and dense space memory support, i.e., its a full 32 bit space,
+ // supports dense memory access.
+ //
+
+ case PCIBus: {
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI/EISA address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI/EISA kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI/EISA memory space
+ //
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus, Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will explicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG)HalCreateQva(*TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Eisa:
+
+ //
+ // Eisa is the same as ISA, with respect to kernel mode
+ // sparse I/O space support, i.e., it is a 16 bit sparse
+ // space.
+ //
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_IO_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will explicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG)HalCreateQva(*TranslatedAddress,va);
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ } // case UserBusMemory
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_SPARSE_IO_PHYSICAL;
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ } // case UserBusIo
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ // Note that ISA and EISA buses can also request this space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = CIA_PCI_DENSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ } // case UserPciDenseMemory
+
+ default: {
+
+ //
+ // Unsupported address space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ } // default
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PHYSICAL_ADDRESS PhysicalOffset;
+ PVOID qva;
+
+ if( (PA.QuadPart >= CIA_PCI_DENSE_MEMORY_PHYSICAL) &&
+ (PA.QuadPart <= (CIA_PCI_DENSE_MEMORY_PHYSICAL +
+ PCI_MAX_DENSE_MEMORY_ADDRESS)) ){
+
+ //
+ // Kernel-mode physical dense address, return VA.
+ //
+
+ return(VA);
+
+ } else if( (PA.QuadPart >=
+ (CIA_PCI_DENSE_MEMORY_PHYSICAL | EV5_USER_IO_ADDRESS_SPACE) ) &&
+ (PA.QuadPart <
+ (CIA_PCI_DENSE_MEMORY_PHYSICAL | EV5_USER_IO_ADDRESS_SPACE +
+ PCI_MAX_DENSE_MEMORY_ADDRESS) ) ){
+
+ //
+ // User-mode physical dense address, return VA.
+ //
+
+ return(VA);
+
+ } else {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ PhysicalOffset.QuadPart = PA.QuadPart - CIA_QVA_PHYSICAL_BASE;
+ qva = (PVOID)(PhysicalOffset.QuadPart >> IO_BIT_SHIFT);
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+}
+
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+ //
+ // For Mikasa we have support three bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support PCI Dense space: check to see if it's really
+ // a QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+ break;
+
+ default:
+
+ return NULL;
+ }
+}
diff --git a/private/ntos/nthals/halpinna/alpha/adjust.c b/private/ntos/nthals/halpinna/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/allstart.c b/private/ntos/nthals/halpinna/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/bios.c b/private/ntos/nthals/halpinna/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/busdata.c b/private/ntos/nthals/halpinna/alpha/busdata.c
new file mode 100644
index 000000000..af95247cd
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/busdata.c
@@ -0,0 +1,138 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from Avanti module for Mikasa.
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halpinna/alpha/cache.c b/private/ntos/nthals/halpinna/alpha/cache.c
new file mode 100644
index 000000000..b058d72ef
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/cache.c
@@ -0,0 +1 @@
+#include "..\halalpha\cache.c"
diff --git a/private/ntos/nthals/halpinna/alpha/chipset.h b/private/ntos/nthals/halpinna/alpha/chipset.h
new file mode 100644
index 000000000..9d4e28d6e
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/chipset.h
@@ -0,0 +1 @@
+#include "cia.h"
diff --git a/private/ntos/nthals/halpinna/alpha/cia.c b/private/ntos/nthals/halpinna/alpha/cia.c
new file mode 100644
index 000000000..7948bfe16
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/cia.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cia.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ciaaddr.c b/private/ntos/nthals/halpinna/alpha/ciaaddr.c
new file mode 100644
index 000000000..890d692a6
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ciaaddr.c
@@ -0,0 +1 @@
+#include "..\halalpha\ciaaddr.c"
diff --git a/private/ntos/nthals/halpinna/alpha/ciaerr.c b/private/ntos/nthals/halpinna/alpha/ciaerr.c
new file mode 100644
index 000000000..7ab595861
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ciaerr.c
@@ -0,0 +1,1636 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ciaerr.c
+
+Abstract:
+
+ This module implements error handling functions for the CIA ASIC.
+
+Author:
+
+ Joe Notarangelo 26-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "cia.h"
+#include "stdio.h"
+
+//
+// Externals and globals.
+//
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+extern ULONG HalDisablePCIParityChecking;
+ULONG CiaCorrectedErrors = 0;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ );
+
+//
+// Allocate a flag that indicates when a PCI Master Abort is expected.
+// PCI Master Aborts are signaled on configuration reads to non-existent
+// PCI slots. A non-zero value indicates that a Master Abort is expected.
+//
+
+ULONG HalpMasterAbortExpected = 0;
+
+
+VOID
+HalpInitializeCiaMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for a CIA-based
+ system by clearing all pending errors in the CIA registers and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CIA_CONTROL CiaControl;
+ CIA_ERR CiaError;
+ CIA_ERR_MASK CiaErrMask;
+
+ //
+ // Clear any pending error bits in the CIA_ERR register:
+ //
+
+ CiaError.all = 0; // Clear all bits
+
+ CiaError.CorErr = 1; // Correctable error
+ CiaError.UnCorErr = 1; // Uncorrectable error
+ CiaError.CpuPe = 1; // Ev5 bus parity error
+ CiaError.MemNem = 1; // Nonexistent memory error
+ CiaError.PciSerr = 1; // PCI bus serr detected
+ CiaError.PciPerr = 1; // PCI bus perr detected
+ CiaError.PciAddrPe = 1; // PCI bus address parity error
+ CiaError.RcvdMasAbt = 1; // Pci Master Abort
+ CiaError.RcvdTarAbt = 1; // Pci Target Abort
+ CiaError.PaPteInv = 1; // Invalid Pte
+ CiaError.FromWrtErr = 1; // Invalid write to flash rom
+ CiaError.IoaTimeout = 1; // Io Timeout occurred
+ CiaError.LostCorErr = 1; // Lost correctable error
+ CiaError.LostUnCorErr = 1; // Lost uncorrectable error
+ CiaError.LostCpuPe = 1; // Lost Ev5 bus parity error
+ CiaError.LostMemNem = 1; // Lost Nonexistent memory error
+ CiaError.LostPciPerr = 1; // Lost PCI bus perr detected
+ CiaError.LostPciAddrPe = 1; // Lost PCI bus address parity error
+ CiaError.LostRcvdMasAbt = 1; // Lost Pci Master Abort
+ CiaError.LostRcvdTarAbt = 1; // Lost Pci Target Abort
+ CiaError.LostPaPteInv = 1; // Lost Invalid Pte
+ CiaError.LostFromWrtErr = 1; // Lost Invalid write to flash rom
+ CiaError.LostIoaTimeout = 1; // Lost Io Timeout occurred
+ CiaError.ErrValid = 1; // Self explanatory
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all
+ );
+
+ //
+ // sclfix - We will read the values set by firmware and change it if
+ // necessary.
+ //
+
+ CiaErrMask.all =
+ READ_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.MemNem = 1; // Enable Nonexistent memory error
+
+ //
+ // Determine PCI parity checking.
+ //
+
+ CiaControl.all = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ if (PciParityChecking == FALSE) {
+
+ CiaControl.AddrPeEn = 0; // Disable PCI address parity checking
+ CiaControl.PerrEn = 0; // Disable PCI data parity checking
+
+ CiaErrMask.PciPerr = 0; // Disable PCI bus perr detected
+ CiaErrMask.PciAddrPe = 0; // Disable PCI bus address parity error
+
+ } else {
+
+ CiaControl.AddrPeEn = PciParityChecking;
+ CiaControl.PerrEn = PciParityChecking;
+
+ CiaErrMask.PciPerr = PciParityChecking;
+ CiaErrMask.PciAddrPe = PciParityChecking;
+
+ }
+
+ CiaErrMask.CorErr = (ReportCorrectableErrors == TRUE);
+
+ WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl,
+ CiaControl.all
+ );
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ //
+ // Set the machine check enables within the EV5.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+
+ } else {
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ return;
+
+}
+
+#define MAX_ERROR_STRING 128
+
+
+BOOLEAN
+HalpCiaUncorrectableError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the CIA error register and determine if an uncorrectable error
+ is latched in the error bits.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE is returned if an uncorrectable error has been detected. FALSE
+ is returned otherwise.
+
+--*/
+{
+ CIA_ERR CiaError;
+
+
+ CiaError.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
+
+ //
+ // If no error is valid then an uncorrectable error was not detected.
+ //
+
+ if( CiaError.ErrValid == 0 ){
+ return FALSE;
+ }
+
+ //
+ // Check each of the individual uncorrectable error bits, if any is set
+ // then return TRUE.
+ //
+
+ if( (CiaError.UnCorErr == 1) ||
+ (CiaError.CpuPe == 1) ||
+ (CiaError.MemNem == 1) ||
+ (CiaError.PciSerr == 1) ||
+ (CiaError.PciPerr == 1) ||
+ (CiaError.PciAddrPe == 1) ||
+ (CiaError.RcvdMasAbt == 1) ||
+ (CiaError.RcvdTarAbt == 1) ||
+ (CiaError.PaPteInv == 1) ||
+ (CiaError.FromWrtErr == 1) ||
+ (CiaError.IoaTimeout == 1) ){
+
+ return TRUE;
+
+ }
+
+ //
+ // None of the uncorrectable error conditions were detected.
+ //
+
+ return FALSE;
+
+}
+
+
+VOID
+HalpBuildCiaConfigurationFrame(
+ PCIA_CONFIGURATION pConfiguration
+ )
+{
+ pConfiguration->CiaRev = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision );
+
+ pConfiguration->CiaCtrl = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ pConfiguration->Mcr = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mcr );
+
+ pConfiguration->Mba0 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba0 );
+
+ pConfiguration->Mba2 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba2 );
+
+ pConfiguration->Mba4 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba4 );
+
+ pConfiguration->Mba6 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba6 );
+
+ pConfiguration->Mba8 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba8 );
+
+ pConfiguration->MbaA = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaA );
+
+ pConfiguration->MbaC = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaC );
+
+ pConfiguration->MbaE = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaE );
+
+ pConfiguration->Tmg0 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg0 );
+
+ pConfiguration->Tmg1 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg1 );
+
+ pConfiguration->Tmg2 = READ_CIA_REGISTER(
+ &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg2 );
+
+}
+
+
+VOID
+HalpCiaReportFatalError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error
+ detected by the CIA chipset. It is assumed that HalGetDisplayOwnership()
+ has been called prior to this function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ CIA_ERR CiaError;
+ CIA_STAT CiaStat;
+ CIA_SYN CiaSyn;
+ CIA_CONTROL CiaControl;
+ CIA_MEM_ERR0 MemErr0;
+ CIA_MEM_ERR1 MemErr1;
+ CIA_PCI_ERR0 PciErr0;
+ CIA_PCI_ERR1 PciErr1;
+ CIA_PCI_ERR2 PciErr2;
+ CIA_CPU_ERR0 CpuErr0;
+ CIA_CPU_ERR1 CpuErr1;
+
+ PUNCORRECTABLE_ERROR uncorr = NULL;
+ PCIA_UNCORRECTABLE_FRAME ciauncorr = NULL;
+ PEXTENDED_ERROR PExtErr;
+
+ //
+ // We will Build the uncorrectable error frame as we read
+ // the registers to report the error to the blue screen.
+ // We generate the extended error frame as we generate
+ // extended messages to print to the screen.
+ //
+
+ if(PUncorrectableError){
+ uncorr = (PUNCORRECTABLE_ERROR)
+ &PUncorrectableError->UncorrectableFrame;
+ ciauncorr = (PCIA_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+ if(uncorr){
+ uncorr->Flags.ProcessorInformationValid = 1;
+ HalpGetProcessorInfo(&uncorr->ReportingProcessor);
+ }
+
+ if(ciauncorr)
+ HalpBuildCiaConfigurationFrame(&ciauncorr->Configuration);
+ //
+ // Read the CIA Error register and decode its contents:
+ //
+
+ CiaError.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr
+ );
+
+ if(ciauncorr)
+ ciauncorr->CiaErr = CiaError.all ;
+
+ //
+ // Read the rest of the error registers and then unlock them by
+ // writing to CIA_ERR
+ //
+
+ CiaStat.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat
+ );
+
+
+ CiaSyn.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn
+ );
+
+
+ MemErr0.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0
+ );
+
+
+ MemErr1.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1
+ );
+
+
+ PciErr0.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0
+ );
+
+
+ PciErr1.PciAddress = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1
+ );
+
+ PciErr2.PciAddress = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2
+ );
+
+ CpuErr0.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr0
+ );
+
+
+ CpuErr1.all = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr1
+ );
+
+ CiaControl.all = READ_CIA_REGISTER(
+ &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl);
+
+ if(ciauncorr){
+ ciauncorr->CiaStat = CiaStat.all;
+ ciauncorr->CiaSyn = CiaSyn.all;
+ ciauncorr->MemErr0 = MemErr0.all;
+ ciauncorr->MemErr1 = MemErr1.all;
+ ciauncorr->PciErr0 = PciErr0.all;
+ ciauncorr->PciErr1 = PciErr1.PciAddress;
+
+ ciauncorr->PciErr2 = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2
+ );
+ ciauncorr->CpuErr0 = CpuErr0.all;
+
+ ciauncorr->CpuErr1 = CpuErr1.all;
+
+ ciauncorr->ErrMask = (ULONG)READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask
+ );
+
+ }
+
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all
+ );
+
+
+ sprintf( OutBuffer, "CIA_CTRL : %08x\n", CiaControl.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CIA_ERR : %08x\n", CiaError.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CIA_STAT : %08x\n", CiaStat.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CIA_SYN : %08x\n", CiaSyn.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "PCI_ERR0 : %08x\n", PciErr0.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "PCI_ERR1 : %08x\n", PciErr1.PciAddress );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "PCI_ERR2 : %08x\n", PciErr2.PciAddress );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CPU_ERR0 : %08x\n", CpuErr0.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "CPU_ERR1 : %08x\n", CpuErr1.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "MEM_ERR0 : %08x\n", MemErr0.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ sprintf( OutBuffer, "MEM_ERR1 : %08x\n", MemErr1.all );
+ HalDisplayString( OutBuffer );
+ DbgPrint( OutBuffer );
+
+ //
+ // If no valid error then no interpretation.
+ //
+
+ if ( CiaError.ErrValid == 0 ){
+
+ return; // No CIA error detected
+
+ }
+
+ //
+ // Interpret any detected errors:
+ //
+
+ if ( CiaError.UnCorErr == 1 ){
+
+ sprintf( OutBuffer,
+ "CIA Uncorrectable ECC error, Addr=%x%x, Cmd=%x\n",
+ CpuErr1.Addr34_32, // bits 34:32
+ CpuErr0.Addr, // bits 31:4
+ CpuErr1.Cmd
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.CpuPe == 1 ){
+
+ sprintf( OutBuffer,
+ "EV5 bus parity error, Addr=%x%x, Cmd=%x\n",
+ CpuErr1.Addr34_32, // bits 34:32
+ CpuErr0.Addr, // bits 31:4
+ CpuErr1.Cmd
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.MemNem == 1 ){
+
+ sprintf( OutBuffer,
+ "CIA Access to non-existent memory, Source=%s, Addr=%x%x\n",
+ MemErr1.MemPortSrc == 1 ? "DMA" : "CPU",
+ MemErr1.MemPortSrc == 1 ? 0 : MemErr1.Addr33_32,
+ MemErr1.MemPortSrc == 1 ? PciErr1.PciAddress : MemErr0.Addr31_4
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.PciSerr == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI bus SERR detected, Cmd=%x, Window=%d, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.PciPerr == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI bus Data Parity error, Cmd=%x, Window=%d, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.PciAddrPe == 1 ){
+
+ sprintf( OutBuffer,
+ "Pci bus Address Parity error, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.RcvdMasAbt == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI Master abort occurred, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.RcvdTarAbt == 1 ){
+
+ sprintf( OutBuffer,
+ "PCI Target abort occurred, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.PaPteInv == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid Scatter/Gather PTE, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+
+ } else if ( CiaError.FromWrtErr == 1 ){
+
+ sprintf( OutBuffer,
+ "Write to Flash ROM with FROM_WRT_EN clear"
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ }
+
+ } else if ( CiaError.IoaTimeout == 1){
+
+ sprintf( OutBuffer,
+ "PCI bus I/O timeout occurred, Cmd=%x, Window=%x, Addr=%x\n",
+ PciErr0.Cmd,
+ PciErr0.Window,
+ PciErr1.PciAddress
+ );
+ if(uncorr){
+ uncorr->Flags.ErrorStringValid = 1;
+ strcpy( uncorr->ErrorString, OutBuffer);
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = PciErr1.PciAddress;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = 0;
+ PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
+ }
+ }
+
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( "\n" );
+ HalDisplayString( OutBuffer );
+
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+
+
+ //
+ // Check for lost errors and output message if any occurred:
+ //
+
+ if ( (CiaError.all & CIA_ERR_LOST_MASK) != 0 ){
+
+ HalDisplayString("\nCIA Lost errors were detected\n\n");
+ }
+
+ return; // Fatal error detected
+}
+
+
+BOOLEAN
+HalpCiaMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ CIA_ERR CiaError;
+
+ //
+ // Read the CIA error register to determine the source of the
+ // error.
+ //
+
+ CiaError.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
+
+#if HALDBG
+
+ DbgPrint( "Cia Mchk: 0x%x\n", CiaError.all );
+
+#endif //HALDBG
+
+ //
+ // Check that an error is valid. If it is not this is a pretty
+ // weird fatal condition.
+ //
+
+ if( CiaError.ErrValid == 0 ){
+ DbgPrint( "Error reported but error valid = 0, CiaErr = 0x%x\n",
+ CiaError.all );
+ goto FatalError;
+ }
+
+ //
+ // Check for any uncorrectable error other than a master abort
+ // on a PCI transaction. Any of these other errors indicate a
+ // fatal condition.
+ //
+
+ if( (CiaError.UnCorErr == 1) || // Uncorrectable error
+ (CiaError.CpuPe == 1) || // Ev5 bus parity error
+ (CiaError.MemNem == 1) || // Nonexistent memory error
+ (CiaError.PciSerr == 1) || // PCI bus serr detected
+ (CiaError.PciPerr == 1) || // PCI bus perr detected
+ (CiaError.PciAddrPe == 1) || // PCI bus address parity error
+ (CiaError.RcvdTarAbt == 1) || // Pci Target Abort
+ (CiaError.PaPteInv == 1) || // Invalid Pte
+ (CiaError.FromWrtErr == 1) || // Invalid write to flash rom
+ (CiaError.IoaTimeout == 1) || // Io Timeout occurred
+ (CiaError.LostUnCorErr == 1) || // Lost uncorrectable error
+ (CiaError.LostCpuPe == 1) || // Lost Ev5 bus parity error
+ (CiaError.LostMemNem == 1) || // Lost Nonexistent memory error
+ (CiaError.LostPciPerr == 1) || // Lost PCI bus perr detected
+ (CiaError.LostPciAddrPe == 1) || // Lost PCI address parity error
+ (CiaError.LostRcvdMasAbt == 1) || // Lost Pci Master Abort
+ (CiaError.LostRcvdTarAbt == 1) || // Lost Pci Target Abort
+ (CiaError.LostPaPteInv == 1) || // Lost Invalid Pte
+ (CiaError.LostFromWrtErr == 1) || // Lost Invalid write to flash rom
+ (CiaError.LostIoaTimeout == 1) // Lost Io Timeout occurred
+ ){
+ DbgPrint( "Explicit fatal error, CiaErr = 0x%x\n",
+ CiaError.all );
+ goto FatalError;
+ }
+
+ //
+ // Check for a PCI configuration read error. The CIA experiences
+ // a master abort on a read to a non-existent PCI slot.
+ //
+
+ if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) ){
+
+ //
+ // So far, the error looks like a PCI configuration space read
+ // that accessed a device that does not exist. In order to fix
+ // this up we expect that the original faulting instruction must
+ // be a load with v0 as the destination register. Unfortunately,
+ // machine checks are not precise exceptions so we may have exectued
+ // many instructions since the faulting load. For EV5 a pair of
+ // memory barrier instructions following the load will stall the pipe
+ // waiting for load completion before the second memory barrier can
+ // be issued. Therefore, we expect the exception PC to point to either
+ // the load instruction of one of the two memory barriers. We will
+ // assume that if the exception pc is not an mb that instead it
+ // points to the load that machine checked. We must be careful to
+ // not reexectute the load.
+ //
+
+ ALPHA_INSTRUCTION FaultingInstruction;
+ BOOLEAN PreviousInstruction = FALSE;
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
+ if( FaultingInstruction.Memory.Opcode != MEMSPC_OP ){
+
+ //
+ // Exception pc does not point to a memory barrier, return
+ // to the instruction after the exception pc.
+ //
+
+ TrapFrame->Fir += 4;
+
+ }
+
+ //
+ // The error has matched all of our conditions. Fix it up by
+ // writing the value 0xffffffff into the destination of the load.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
+
+ //
+ // Clear the error condition in CIA_ERR.
+ //
+
+ CiaError.all = 0;
+ CiaError.RcvdMasAbt = 1;
+ CiaError.ErrValid = 1;
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all );
+
+ return TRUE;
+
+ } //end if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) )
+
+ DbgPrint( "Unexpected master abort\n" );
+
+//
+// The system is not well and cannot continue reliable execution.
+// Print some useful messages and return FALSE to indicate that the error
+// was not handled.
+//
+
+FatalError:
+
+ DbgPrint( "Handling fatal error\n" );
+
+ //
+ // Clear the error condition in the MCES register.
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ //
+ // Proceed to display the error.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+
+ HalpCiaReportFatalError();
+
+ return( FALSE );
+
+}
+
+BOOLEAN
+HalpTranslateSynToEcc(
+ PULONG Syndrome
+ )
+/*++
+
+Routine Description:
+
+ Translate a syndrome code to ECC error bit code.
+
+Arguments:
+
+ Syndrome - pointer to the syndrome.
+
+Return Value:
+
+ True if a data bit is in error. False otherwise.
+
+--*/
+{
+ static UCHAR SynToEccTable[0xff] = {0, };
+ static BOOLEAN SynToEccTableInitialized = FALSE;
+ ULONG Temp;
+
+ //
+ // Initialize the table.
+ //
+
+ if (!SynToEccTableInitialized) {
+
+ SynToEccTableInitialized = TRUE;
+
+ //
+ // Fill in the table.
+ //
+
+ SynToEccTable[0x01] = 0;
+ SynToEccTable[0x02] = 1;
+ SynToEccTable[0x04] = 2;
+ SynToEccTable[0x08] = 3;
+ SynToEccTable[0x10] = 4;
+ SynToEccTable[0x20] = 5;
+ SynToEccTable[0x40] = 6;
+ SynToEccTable[0x80] = 7;
+ SynToEccTable[0xce] = 0;
+ SynToEccTable[0xcb] = 1;
+ SynToEccTable[0xd3] = 2;
+ SynToEccTable[0xd5] = 3;
+ SynToEccTable[0xd6] = 4;
+ SynToEccTable[0xd9] = 5;
+ SynToEccTable[0xda] = 6;
+ SynToEccTable[0xdc] = 7;
+ SynToEccTable[0x23] = 8;
+ SynToEccTable[0x25] = 9;
+ SynToEccTable[0x26] = 10;
+ SynToEccTable[0x29] = 11;
+ SynToEccTable[0x2a] = 12;
+ SynToEccTable[0x2c] = 13;
+ SynToEccTable[0x31] = 14;
+ SynToEccTable[0x34] = 15;
+ SynToEccTable[0x0e] = 16;
+ SynToEccTable[0x0b] = 17;
+ SynToEccTable[0x13] = 18;
+ SynToEccTable[0x15] = 19;
+ SynToEccTable[0x16] = 20;
+ SynToEccTable[0x19] = 21;
+ SynToEccTable[0x1a] = 22;
+ SynToEccTable[0x1c] = 23;
+ SynToEccTable[0xe3] = 24;
+ SynToEccTable[0xe5] = 25;
+ SynToEccTable[0xe6] = 26;
+ SynToEccTable[0xe9] = 27;
+ SynToEccTable[0xea] = 28;
+ SynToEccTable[0xec] = 29;
+ SynToEccTable[0xf1] = 30;
+ SynToEccTable[0xf4] = 31;
+ SynToEccTable[0x4f] = 32;
+ SynToEccTable[0x4a] = 33;
+ SynToEccTable[0x52] = 34;
+ SynToEccTable[0x54] = 35;
+ SynToEccTable[0x57] = 36;
+ SynToEccTable[0x58] = 37;
+ SynToEccTable[0x5b] = 38;
+ SynToEccTable[0x5d] = 39;
+ SynToEccTable[0xa2] = 40;
+ SynToEccTable[0xa4] = 41;
+ SynToEccTable[0xa7] = 42;
+ SynToEccTable[0xa8] = 43;
+ SynToEccTable[0xab] = 44;
+ SynToEccTable[0xad] = 45;
+ SynToEccTable[0xb0] = 46;
+ SynToEccTable[0xb5] = 47;
+ SynToEccTable[0x8f] = 48;
+ SynToEccTable[0x8a] = 49;
+ SynToEccTable[0x92] = 50;
+ SynToEccTable[0x94] = 51;
+ SynToEccTable[0x97] = 52;
+ SynToEccTable[0x98] = 53;
+ SynToEccTable[0x9b] = 54;
+ SynToEccTable[0x9d] = 55;
+ SynToEccTable[0x62] = 56;
+ SynToEccTable[0x64] = 57;
+ SynToEccTable[0x67] = 58;
+ SynToEccTable[0x68] = 59;
+ SynToEccTable[0x6b] = 60;
+ SynToEccTable[0x6d] = 61;
+ SynToEccTable[0x70] = 62;
+ SynToEccTable[0x75] = 63;
+ }
+
+ //
+ // Tranlate the syndrome code.
+ //
+
+ Temp = *Syndrome;
+ *Syndrome = SynToEccTable[Temp];
+
+ //
+ // Is it a data bit or a check bit in error?
+ //
+
+ if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 ||
+ Temp == 0x10 || Temp == 0x20 || Temp == 0x40 || Temp == 0x80) {
+
+ return FALSE;
+
+ } else {
+
+ return TRUE;
+ }
+}
+
+
+
+VOID
+HalpCiaErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle a CIA correctable error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ static ERROR_FRAME Frame;
+ static CIA_CORRECTABLE_FRAME AlcorFrame;
+
+ ERROR_FRAME TempFrame;
+ PCORRECTABLE_ERROR CorrPtr;
+ PBOOLEAN ErrorlogBusy;
+ PULONG DispatchCode;
+ ULONG Syndrome;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+
+ CIA_ERR CiaError;
+ CIA_STAT CiaStat;
+ CIA_SYN CiaSyn;
+ CIA_MEM_ERR0 MemErr0;
+ CIA_MEM_ERR1 MemErr1;
+ CIA_PCI_ERR0 PciErr0;
+ CIA_PCI_ERR1 PciErr1;
+ CIA_PCI_ERR2 PciErr2;
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read/write. Read the error registers relevant
+ // to this error.
+ //
+
+ CiaError.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
+
+ //
+ // Check if an error is latched into the CIA.
+ //
+
+ if( CiaError.ErrValid == 0 ){
+
+#if HALDBG
+
+ DbgPrint( "Cia error interrupt without valid CIA error\n" );
+
+#endif //HALDBG
+
+ return;
+ }
+
+ //
+ // Check for the correctable error bit.
+ //
+
+ if( CiaError.CorErr == 0 ){
+
+#if HALDBG
+
+ DbgPrint( "Cia error interrupt without correctable error indicated\n" );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Real error, get the interrupt object.
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Increment the number of CIA correctable errors.
+ //
+
+ CiaCorrectedErrors += 1;
+
+ CiaStat.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat );
+
+ CiaSyn.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn );
+
+ MemErr0.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0 );
+
+ MemErr1.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1 );
+
+ PciErr0.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0 );
+
+ PciErr1.PciAddress = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1 );
+
+ PciErr2.PciAddress = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2 );
+
+
+ //
+ // Print a correctable error message to the debugger.
+ //
+
+#if HALDBG
+ DbgPrint( "CIA Correctable Error Number %d, state follows: \n",
+ CiaCorrectedErrors );
+ DbgPrint( "\tCIA_ERR : 0x%x\n", CiaError.all );
+ DbgPrint( "\tCIA_STAT: 0x%x\n", CiaStat.all );
+ DbgPrint( "\tCIA_SYN : 0x%x\n", CiaSyn.all );
+ DbgPrint( "\tCIA_MEM0: 0x%x\n", MemErr0.all );
+ DbgPrint( "\tCIA_MEM1: 0x%x\n", MemErr1.all );
+ DbgPrint( "\tPCI_ERR0: 0x%x\n", PciErr0.all );
+#endif //HALDBG
+
+ //
+ // Fill in the error frame information.
+ //
+
+ TempFrame.Signature = ERROR_FRAME_SIGNATURE;
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = CiaCorrectedErrors;
+ TempFrame.PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Check for lost error.
+ //
+
+ if( CiaError.LostCorErr ) {
+
+ //
+ // Since the error registers are locked from a previous error,
+ // we don't know where the error came from. Mark everything
+ // as UNIDENTIFIED.
+ //
+
+ CorrPtr->Flags.LostCorrectable = 1;
+ CorrPtr->Flags.LostAddressSpace = UNIDENTIFIED;
+ CorrPtr->Flags.LostMemoryErrorSource = UNIDENTIFIED;
+ }
+
+ //
+ // Set error bit error masks.
+ //
+
+ CorrPtr->Flags.ErrorBitMasksValid = 1;
+ Syndrome = CiaSyn.all;
+
+ if ( HalpTranslateSynToEcc(&Syndrome) )
+ CorrPtr->DataBitErrorMask = 1 << Syndrome;
+ else
+ CorrPtr->CheckBitErrorMask = 1 << Syndrome;
+
+ //
+ // Determine error type.
+ //
+ switch (CiaStat.DmSt) {
+
+ case CIA_IO_WRITE_ECC:
+
+ //
+ // I/O write ECC error occurred.
+ //
+
+ CorrPtr->Flags.AddressSpace = IO_SPACE;
+
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->ErrorInformation.IoError.Interface = PCIBus;
+ CorrPtr->ErrorInformation.IoError.BusNumber = 0;
+ CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress;
+ CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_WRITE;
+ break;
+
+ case CIA_DMA_READ_ECC:
+
+ CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+
+ //
+ // Where did the error come from?
+ //
+
+ if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from processor cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE;
+
+ //
+ // DMA read or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ;
+
+ } else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from system cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE;
+
+ //
+ // DMA read or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ;
+
+ } else {
+
+ //
+ // Correctable error comes from system memory.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
+
+ //
+ // DMA read or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_READ;
+ else
+ CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_READ;
+ }
+
+ break;
+
+ case CIA_DMA_WRITE_ECC:
+
+ CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+
+ //
+ // Where did the error come from?
+ //
+
+ if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from processor cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE;
+
+ //
+ // DMA write or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE;
+
+ } else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) {
+
+ //
+ // Correctable error comes from system cache.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE;
+
+ //
+ // DMA write or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE;
+ else
+ CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE;
+
+ } else {
+
+ //
+ // Correctable error comes from system memory.
+ //
+
+ CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
+
+ //
+ // DMA write or TLB miss error occurred.
+ //
+
+ if ( CiaStat.TlbMiss )
+ CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_WRITE;
+ else
+ CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_WRITE;
+
+ //
+ //
+ }
+
+ break;
+
+ case CIA_IO_READ_ECC:
+
+ //
+ // I/O read ECC error occurred.
+ //
+
+ CorrPtr->Flags.AddressSpace = IO_SPACE;
+
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->ErrorInformation.IoError.Interface = PCIBus;
+ CorrPtr->ErrorInformation.IoError.BusNumber = 0;
+ CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress;
+ CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_READ;
+ break;
+
+ default:
+
+ //
+ // Something strange happened. Don't know where the error occurred.
+ //
+
+ CorrPtr->Flags.AddressSpace = UNIDENTIFIED;
+ break;
+ }
+
+ //
+ // Get the physical address where the error occurred.
+ //
+
+ CorrPtr->Flags.PhysicalAddressValid = 1;
+ CorrPtr->PhysicalAddress = (MemErr1.all & 0xff) << 32;
+ CorrPtr->PhysicalAddress |= MemErr0.all;
+
+ //
+ // Get bits 7:0 of the address from the PCI address.
+ //
+
+ CorrPtr->PhysicalAddress |= PciErr1.PciAddress & 0xff;
+
+ //
+ // Scrub the error if it's any type of memory error.
+ //
+
+ if ( CorrPtr->Flags.AddressSpace == MEMORY_SPACE &&
+ CorrPtr->Flags.PhysicalAddressValid )
+ CorrPtr->Flags.ScrubError = 1;
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ //
+
+ if (!*ErrorlogBusy) {
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read/write. Read the error registers relevant
+ // to this error.
+ //
+
+ AlcorFrame.CiaErr = CiaError.all;
+
+ AlcorFrame.CiaStat = CiaStat.all;
+
+ AlcorFrame.CiaSyn = CiaSyn.all;
+
+ AlcorFrame.MemErr0 = MemErr0.all;
+
+ AlcorFrame.MemErr1 = MemErr1.all;
+
+ AlcorFrame.PciErr0 = PciErr0.all;
+
+ AlcorFrame.PciErr1 = PciErr1.PciAddress;
+
+ AlcorFrame.PciErr2 = PciErr2.PciAddress;
+
+ //
+ // Read the CIA configuration registers for logging information.
+ //
+
+ AlcorFrame.Configuration.CiaRev =
+ READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS)
+ (CIA_GENERAL_CSRS_QVA))->CiaRevision );
+
+ AlcorFrame.Configuration.CiaCtrl =
+ READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS)
+ (CIA_GENERAL_CSRS_QVA))->CiaCtrl );
+
+ AlcorFrame.Configuration.Mcr =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mcr );
+
+ AlcorFrame.Configuration.Mba0 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba0 );
+
+ AlcorFrame.Configuration.Mba2 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba2 );
+
+ AlcorFrame.Configuration.Mba4 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba4 );
+
+ AlcorFrame.Configuration.Mba6 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba6 );
+
+ AlcorFrame.Configuration.Mba8 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Mba8 );
+
+ AlcorFrame.Configuration.MbaA =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->MbaA );
+
+ AlcorFrame.Configuration.MbaC =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->MbaC );
+
+ AlcorFrame.Configuration.MbaE =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->MbaE );
+
+ AlcorFrame.Configuration.Tmg0 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Tmg0 );
+
+ AlcorFrame.Configuration.Tmg1 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Tmg1 );
+
+ AlcorFrame.Configuration.Tmg2 =
+ READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
+ (CIA_MEMORY_CSRS_QVA))->Tmg2 );
+
+ AlcorFrame.Configuration.CacheCnfg =
+ PCR->SecondLevelCacheSize;
+
+ //
+ // Set the raw system information.
+ //
+
+ CorrPtr->RawSystemInformationLength = sizeof(CIA_CORRECTABLE_FRAME);
+ CorrPtr->RawSystemInformation = &AlcorFrame;
+
+ //
+ // Set the raw processor information. Disregard at the moment.
+ //
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // Set reporting processor information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+
+ //
+ // Set system information. Disregard at the moment.
+ //
+
+ CorrPtr->Flags.SystemInformationValid = 0;
+
+ //
+ // Copy the information that we need to log.
+ //
+
+ RtlCopyMemory(&Frame,
+ &TempFrame,
+ sizeof(ERROR_FRAME));
+
+ //
+ // Put frame into ISR service context.
+ //
+
+ *(PERROR_FRAME *)InterruptObject->ServiceContext = &Frame;
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+
+ //
+ // Clear the corrected error status bit and return to continue
+ // execution.
+ //
+
+ CiaError.all = 0;
+ CiaError.CorErr = 1;
+ WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
+ CiaError.all );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halpinna/alpha/ciaio.s b/private/ntos/nthals/halpinna/alpha/ciaio.s
new file mode 100644
index 000000000..16202a7e1
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ciaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaio.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/cmos8k.c b/private/ntos/nthals/halpinna/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/devintr.s b/private/ntos/nthals/halpinna/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ebsgdma.c b/private/ntos/nthals/halpinna/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/eisasup.c b/private/ntos/nthals/halpinna/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/environ.c b/private/ntos/nthals/halpinna/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ev5cache.c b/private/ntos/nthals/halpinna/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ev5int.c b/private/ntos/nthals/halpinna/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ev5ints.s b/private/ntos/nthals/halpinna/alpha/ev5ints.s
new file mode 100644
index 000000000..18dce1072
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ev5ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ev5mchk.c b/private/ntos/nthals/halpinna/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ev5mem.s b/private/ntos/nthals/halpinna/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ev5prof.c b/private/ntos/nthals/halpinna/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/fwreturn.c b/private/ntos/nthals/halpinna/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/haldebug.c b/private/ntos/nthals/halpinna/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/halpal.s b/private/ntos/nthals/halpinna/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/haltsup.s b/private/ntos/nthals/halpinna/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/idle.s b/private/ntos/nthals/halpinna/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/info.c b/private/ntos/nthals/halpinna/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/inithal.c b/private/ntos/nthals/halpinna/alpha/inithal.c
new file mode 100644
index 000000000..b4eb90ca7
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalcor\alpha\inithal.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/intsup.s b/private/ntos/nthals/halpinna/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halpinna/alpha/ioproc.c b/private/ntos/nthals/halpinna/alpha/ioproc.c
new file mode 100644
index 000000000..d4bd5b0b2
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/ioproc.c
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halpinna/alpha/iousage.c b/private/ntos/nthals/halpinna/alpha/iousage.c
new file mode 100644
index 000000000..ba57097d8
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/iousage.c
@@ -0,0 +1,648 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/halpinna/alpha/iousage.h b/private/ntos/nthals/halpinna/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/halpinna/alpha/machdep.h b/private/ntos/nthals/halpinna/alpha/machdep.h
new file mode 100644
index 000000000..51b1c8dbe
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Mikasa platform-specific definitions.
+//
+
+#include "mikasa.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halpinna/alpha/memory.c b/private/ntos/nthals/halpinna/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/mikasa.h b/private/ntos/nthals/halpinna/alpha/mikasa.h
new file mode 100644
index 000000000..70ad29504
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/mikasa.h
@@ -0,0 +1,796 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mikasa.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Mikasa EV5 modules.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Revision History:
+
+ Scott Lee 29-Nov-1995
+ Adapted from Mikasa module for Mikasa EV5 (Pinnacle).
+
+--*/
+
+#ifndef _MIKASA_
+#define _MIKASA_
+
+#include "alpharef.h"
+#include "cia.h"
+#include "isaaddr.h"
+#include "axp21164.h"
+
+//
+// sclfix - These defines are not used.
+//
+// #define NUMBER_MIKASA_EISA_SLOTS 7
+// #define NUMBER_MIKASA_PCI_SLOTS 3
+// #define NUMBER_MIKASA_COMBO_SLOTS 1
+//
+// #define NUMBER_NORITAKE_EISA_SLOTS 2
+// #define NUMBER_NORITAKE_PCI_SLOTS 7
+//
+
+//
+// Highest local PCI virtual slot number is 14 == IDSEL PCI_AD[25]
+//
+
+#define PCI_MAX_LOCAL_DEVICE 14
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+#if !defined (AXP_FIRMWARE)
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each EV5 processor.
+//
+
+typedef struct _MIKASA_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+} MIKASA_PCR, *PMIKASA_PCR;
+
+#endif
+
+//
+// Define the Mikasa server management data structure.
+//
+
+typedef union _MIKASA_SRV{
+ struct {
+ UCHAR FlashRomEnable : 1; // rw
+ UCHAR DcPowerDisable : 1; // rw
+ UCHAR HaltIncoming : 1; // ro
+ UCHAR TempFail : 1; // ro
+ UCHAR DcOk1 : 1; // ro
+ UCHAR DcOk2 : 1; // ro
+ UCHAR Fan1Fault : 1; // ro
+ UCHAR Fan2Fault : 1; // ro
+ };
+ UCHAR All;
+} MIKASA_SRV, *PMIKASA_SRV;
+
+//
+// Define the Mikasa interrupt mask register. This is how we enable
+// and disable individual PCI interrupts. Actually, it's here more
+// for reference, since the interrupt enable/disable is done with a
+// computational algorithm.
+//
+
+typedef union _MIKASA_IMR{
+ struct {
+ ULONG Slot0IntA : 1;
+ ULONG Slot0IntB : 1;
+ ULONG Slot0IntC : 1;
+ ULONG Slot0IntD : 1;
+ ULONG Slot1IntA : 1;
+ ULONG Slot1IntB : 1;
+ ULONG Slot1IntC : 1;
+ ULONG Slot1IntD : 1;
+ ULONG Slot2IntA : 1;
+ ULONG Slot2IntB : 1;
+ ULONG Slot2IntC : 1;
+ ULONG Slot2IntD : 1;
+ ULONG Ncr810Scsi : 1;
+ ULONG PwrInt : 1;
+ ULONG TempWarn : 1;
+ ULONG Reserved : 17;
+ };
+ ULONG All;
+} MIKASA_IMR, *PMIKASA_IMR;
+
+//
+// Define the Noritake server management data structure.
+//
+
+typedef union _NORITAKE_SRV{
+ struct {
+ UCHAR FlashRomEnable : 1; // rw
+ UCHAR DcPowerDisable : 1; // rw
+ UCHAR Reserved1: 2;
+ UCHAR HaltIncoming : 1; // ro
+ UCHAR FlashReady: 1; // ro
+ UCHAR Reserved2: 1;
+ UCHAR EmbeddedVGAStatus: 1; // rw
+ };
+ UCHAR All;
+} NORITAKE_SRV, *PNORITAKE_SRV;
+
+//
+// Define the Noritake interrupt mask registers. This is how we enable
+// and disable individual PCI interrupts. Actually, it's here more
+// for reference, since the interrupt enable/disable is done with a
+// computational algorithm.
+//
+
+//
+// Note: Slots 0 through 2 are on PCI bus 0, and slots 3 through 6 are
+// on PCI bus 1.
+//
+
+typedef union _NORITAKE_IMR1{
+ struct {
+ ULONG SumIr2And3 : 1;
+ ULONG QLogic: 1;
+ ULONG Slot0IntA : 1;
+ ULONG Slot0IntB : 1;
+ ULONG Slot1IntA : 1;
+ ULONG Slot1IntB : 1;
+ ULONG Slot2IntA : 1;
+ ULONG Slot2IntB : 1;
+ ULONG Slot3IntA : 1;
+ ULONG Slot3IntB : 1;
+ ULONG Slot4IntA : 1;
+ ULONG Slot4IntB : 1;
+ ULONG Slot5IntA : 1;
+ ULONG Slot5IntB : 1;
+ ULONG Slot6IntA : 1;
+ ULONG Slot6IntB : 1;
+ ULONG Reserved : 16;
+ };
+ ULONG ALL;
+} NORITAKE_IMR1, *PNORITAKE_IMR1;
+
+typedef union _NORITAKE_IMR2{
+ struct {
+ ULONG SumUnmaskedIr2 : 1;
+ ULONG SecondaryPCIBusInt : 1;
+ ULONG Slot0IntC : 1;
+ ULONG Slot0IntD : 1;
+ ULONG Slot1IntC : 1;
+ ULONG Slot1IntD : 1;
+ ULONG Slot2IntC : 1;
+ ULONG Slot2IntD : 1;
+ ULONG Slot3IntC : 1;
+ ULONG Slot3IntD : 1;
+ ULONG Slot4IntC : 1;
+ ULONG Slot4IntD : 1;
+ ULONG Slot5IntC : 1;
+ ULONG Slot5IntD : 1;
+ ULONG Slot6IntC : 1;
+ ULONG Slot6IntD : 1;
+ ULONG Reserved : 16;
+ };
+ ULONG ALL;
+} NORITAKE_IMR2, *PNORITAKE_IMR2;
+
+typedef union _NORITAKE_IMR3{
+ struct {
+ ULONG Reserved1 : 2;
+ ULONG Power2Int : 1;
+ ULONG Power1Int : 1;
+ ULONG TempFail : 1;
+ ULONG TempWarn : 1;
+ ULONG Fan2Fail : 1;
+ ULONG Fan1Fail : 1;
+ ULONG Reserved2 : 24;
+ };
+ ULONG ALL;
+} NORITAKE_IMR3, *PNORITAKE_IMR3;
+
+//
+// Define the Corelle server management data structure.
+//
+
+typedef union _CORELLE_SRV {
+ struct {
+ UCHAR FlashRomEnable : 1; // rw
+ UCHAR SoftShut : 1; // rw
+ UCHAR CPU_HALT : 1; // rw
+ UCHAR TempShutDisable: 1; // rw
+ UCHAR HaltIncoming : 1; // ro
+ UCHAR VGAReset: 1; // ro
+ UCHAR WatchDogEnable: 1; // rw
+ UCHAR WatchDogBiscuit: 1; // rw
+ };
+ UCHAR All;
+} CORELLE_SRV, *PCORELLE_SRV;
+
+//
+// Define the Corelle interrupt mask registers. This is how we enable
+// and disable individual PCI interrupts. Actually, it's here more
+// for reference, since the interrupt enable/disable is done with a
+// computational algorithm.
+//
+
+typedef union _CORELLE_IMR1{
+ struct {
+ ULONG SumIr2 : 1;
+ ULONG QLogic : 1;
+ ULONG Slot0IntA : 1;
+ ULONG Slot0IntB : 1;
+ ULONG Slot1IntA : 1;
+ ULONG Slot1IntB : 1;
+ ULONG Slot2IntA : 1;
+ ULONG Slot2IntB : 1;
+ ULONG Slot3IntA : 1;
+ ULONG Slot3IntB : 1;
+ ULONG S3Trio64 : 1;
+ ULONG Reserved1 : 1;
+ ULONG TempFailInt : 1;
+ ULONG TempWarnInt : 1;
+ ULONG Fan1FailInt : 1;
+ ULONG Fan2FailInt : 1;
+ ULONG Reserved2 : 16;
+ };
+ ULONG ALL;
+} CORELLE_IMR1, *PCORELLE_IMR1;
+
+typedef union _CORELLE_IMR2{
+ struct {
+ ULONG Reserved1 : 2;
+ ULONG Slot0IntC : 1;
+ ULONG Slot0IntD : 1;
+ ULONG Slot1IntC : 1;
+ ULONG Slot1IntD : 1;
+ ULONG Slot2IntC : 1;
+ ULONG Slot2IntD : 1;
+ ULONG Slot3IntC : 1;
+ ULONG Slot3IntD : 1;
+ ULONG Reserved2 : 22;
+ };
+ ULONG ALL;
+} CORELLE_IMR2, *PCORELLE_IMR2;
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#define HAL_PCR ( (PMIKASA_PCR)(&(PCR->HalReserved)) )
+
+#define PCI_VECTOR PRIMARY0_VECTOR // from alpharef.h
+#define PCI_MAX_INTERRUPT_VECTOR MAXIMUM_PCI_VECTOR // from alpharef.h
+
+#define PCI_SPARSE_IO_BASE_QVA \
+ ((ULONG)(HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL)))
+
+//
+// The combined Vendor ID, Device ID for the PCEB of the PCI/EISA bridge
+// chip set.
+//
+#define INTEL_PCI_EISA_BRIDGE_ID 0x04828086
+
+//
+// N.B.: The PCI configuration space address is what we're really referring
+// to, here.
+//
+
+#define PCI_CONFIGURATION_BASE_QVA \
+ ((ULONG)(HAL_MAKE_QVA(CIA_PCI_CONFIGURATION_PHYSICAL)))
+
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device
+
+#define PCI_EISA_BRIDGE_HEADER_OFFSET (0x00070000 >> IO_BIT_SHIFT) // AD[18]
+
+//
+// PCI-EISA Bridge Non-Configuration control register offsets. These should
+// be simply ored with PCI_SPARSE_IO_BASE_QVA; they match what's in the
+// Intel handbook for the 82374EB (ESC).
+//
+#define ESC_EDGE_LEVEL_CONTROL_1 0x4d0
+#define ESC_EDGE_LEVEL_CONTROL_2 0x4d1
+#define ESC_CMOS_ISA_PORT 0x800
+
+//
+// BIOS timer address port. This value is stuffed into PCEB configuration
+// space at PCEB/ESC cofiguration.
+//
+#define BIOS_TIMER_PORT 0x78
+
+//
+// Mikasa-unique registers, accessed via PCI_SPARSE_IO_BASE_QVA, via the
+// same protocol as above. Locations of these are intermixed with
+// ESC-specific and ordinary ISA registers in this space. N.B.: the
+// term "port" is used for compatibility with PC industry terminology.
+// We know Alphas don't have I/O instructions, nor ports, as such.
+//
+#define COMBO_CHIP_CONFIG_INDEX_PORT 0x398
+#define COMBO_CHIP_CONFIG_DATA_PORT 0x399
+
+//
+// Define I2C constants
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x530
+#define I2C_INTERFACE_CSR_PORT 0x531
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+//
+// This is the same for both Noritake and Mikasa
+//
+
+#define SERVER_MANAGEMENT_REGISTER 0x532
+
+//
+// Noritake interrupt and interrupt mask register offsets.
+//
+
+#define PCI_INTERRUPT_BASE_ADDRESS 0x540
+#define PCI_INTERRUPT_REGISTER_1 0x542
+#define PCI_INTERRUPT_REGISTER_2 0x544
+#define PCI_INTERRUPT_REGISTER_3 0x546
+#define PCI_INTERRUPT_MASK_REGISTER_1 0x54A
+#define PCI_INTERRUPT_MASK_REGISTER_2 0x54C
+#define PCI_INTERRUPT_MASK_REGISTER_3 0x54E
+
+//
+// Noritake PCI vector offsets. Interrupt vectors that originate from register
+// 1 start at 0x11 for bit position 0. So, when servicing an interrupt from
+// register 1, you must add 0x11 to the bit position to get the interrupt
+// vector. Likewise, if you have an interrupt vector, and you would like to
+// determine which interrupt register it resides in, you can use the vector
+// offsets to determine this. All vectors in interrupt register 1 are between
+// 0x11 and 0x20. All vectors in interrupt register 2 are between 0x21 and
+// 0x30. All vectors in interrupt register 3 are between 0x31 and 0x38.
+// Subtracting the vector offset for a register from the interrupt vector will
+// give you the bit position of the vector. For example, Vector 0x14
+// corresponds to bit 3 of interrupt register 1, Vector 0x27 corresponds to bit
+// 6 of interrupt register 2, and so on.
+//
+
+#define REGISTER_1_VECTOR_OFFSET 0x11
+#define REGISTER_2_VECTOR_OFFSET 0x21
+#define REGISTER_3_VECTOR_OFFSET 0x31
+
+
+//
+// Corelle PCI vector offset. Interrupt vectors that originate from register 1
+// start at 0x10 for bit position 0. Interrupt vectors that originate from
+// register 2 start at 0x20 for bit position 0.
+
+#define CORELLE_INTERRUPT1_OFFSET 0x10
+#define CORELLE_INTERRUPT2_OFFSET 0x20
+
+//
+// Mikasa interrupt and interrupt mask register offsets.
+//
+
+#define PCI_INTERRUPT_REGISTER 0x534
+#define PCI_INTERRUPT_MASK_REGISTER 0x536
+
+//
+// Define the index and data ports for the NS Super IO (87312) chip.
+//
+
+#define SUPERIO_INDEX_PORT 0x398
+#define SUPERIO_DATA_PORT 0x399
+#define SUPERIO_PORT_LENGTH 0x2
+
+//
+// PCI Sparse I/O space offsets for unique functions on the ESC. They are
+// used as the offsets above.
+//
+
+#define ESC_CONFIG_ADDRESS 0x22
+#define ESC_CONFIG_DATA 0x23
+
+//
+// ESC configuration register index addresses. The protocol is:
+// write the configuration register address (one of the following)
+// into ESC_CONTROL_INDEX, then write the data into ESC_CONTROL_DATA.
+//
+#define ESC_INDEX_ESC_ID 0x02 // write 0xf to enable
+#define ESC_INDEX_REVISION_ID 0x08 // ro
+#define ESC_INDEX_MODE_SELECT 0x40 // rw
+#define ESC_INDEX_BIOS_CHIP_SELECT_A 0x42 // rw
+#define ESC_INDEX_BIOS_CHIP_SELECT_B 0x43 // rw
+#define ESC_INDEX_BCLK_CLOCK_DIVISOR 0x4d // rw
+#define ESC_INDEX_PERIPHERAL_CHIP_SELECT_A 0x4e // rw
+#define ESC_INDEX_PERIPHERAL_CHIP_SELECT_B 0x4f // rw
+#define ESC_INDEX_EISA_ID_BYTE_1 0x50 // rw
+#define ESC_INDEX_EISA_ID_BYTE_2 0x51 // rw
+#define ESC_INDEX_EISA_ID_BYTE_3 0x52 // rw
+#define ESC_INDEX_EISA_ID_BYTE_4 0x53 // rw
+#define ESC_INDEX_SG_RELOCATE_BASE 0x57 // rw
+#define ESC_INDEX_PIRQ0_ROUTE_CONTROL 0x60 // rw
+#define ESC_INDEX_PIRQ1_ROUTE_CONTROL 0x61 // rw
+#define ESC_INDEX_PIRQ2_ROUTE_CONTROL 0x62 // rw
+#define ESC_INDEX_PIRQ3_ROUTE_CONTROL 0x63 // rw
+#define ESC_INDEX_GPCS0_BASE_LOW 0x64 // rw
+#define ESC_INDEX_GPCS0_BASE_HIGH 0x65 // rw
+#define ESC_INDEX_GPCS0_MASK 0x66 // rw
+#define ESC_INDEX_GPCS1_BASE_LOW 0x68 // rw
+#define ESC_INDEX_GPCS1_BASE_HIGH 0x69 // rw
+#define ESC_INDEX_GPCS1_MASK 0x6a // rw
+#define ESC_INDEX_GPCS2_BASE_LOW 0x6c // rw
+#define ESC_INDEX_GPCS2_BASE_HIGH 0x6d // rw
+#define ESC_INDEX_GPCS2_MASK 0x6e // rw
+#define ESC_INDEX_GP_XBUS_CONTROL 0x6f // rw
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+typedef union _ESC_MODESEL{
+ struct {
+ UCHAR EisaMasterSupport: 2;
+ UCHAR Reserved1: 1;
+ UCHAR SystemErrorEnable : 1;
+ UCHAR EscSelect : 1;
+ UCHAR CramPageEnable : 1;
+ UCHAR MreqPirqEnable : 1;
+ UCHAR Reserved2: 2;
+ };
+ UCHAR All;
+}ESC_MODESEL, *PESC_MODESEL;
+
+#define MS_4_EISA_MASTERS 0x00
+#define MS_6_EISA_MASTERS 0x01
+#define MS_7_EISA_MASTERS 0x02
+#define MS_8_EISA_MASTERS 0x03
+#define MS_RESERVED_MASK 0x84
+
+#define BIOSCSA_RESERVED_MASK 0xc0
+#define BIOSCSB_RESERVED_MASK 0xf0
+
+#define GPXBC_RESERVED_MASK 0xf8
+
+typedef union _ESC_CLKDIV{
+ struct {
+ UCHAR ClockDivisor: 3;
+ UCHAR Reserved1: 1;
+ UCHAR MouseInterruptEnable : 1;
+ UCHAR CoprocessorError : 1;
+ UCHAR Reserved2: 2;
+ };
+ UCHAR All;
+}ESC_CLKDIV, *PESC_CLKDIV;
+
+#define CLKDIV_33MHZ_EISA 0x00
+#define CLKDIV_25MHZ_EISA 0x01
+#define CLKDIV_RESERVED_MASK 0xc8
+
+typedef union _ESC_PCSA{
+ struct {
+ UCHAR RtcDecode: 1;
+ UCHAR KeyboardControllerDecode: 1;
+ UCHAR FloppyDiskSecondaryDecode : 1;
+ UCHAR FloppyDiskPrimaryDecode : 1;
+ UCHAR IdeDecode : 1;
+ UCHAR FloppyIdeSpaceSecondary : 1;
+ UCHAR Reserved : 2;
+ };
+ UCHAR All;
+}ESC_PCSA, *PESC_PCSA;
+
+#define PCSA_RESERVED_MASK 0xc0
+
+typedef union _ESC_PCSB{
+ struct {
+ UCHAR SerialPortADecode: 2;
+ UCHAR SerialPortBDecode: 2;
+ UCHAR ParallelPortDecode : 2;
+ UCHAR Port92Decode : 1;
+ UCHAR CramDecode : 1;
+ };
+ UCHAR All;
+}ESC_PCSB, *PESC_PCSB;
+
+#define PCSB_DECODE_DISABLE 0x3
+
+typedef union _ESC_PIRQ{
+ struct {
+ UCHAR IrqxRoutingBits: 7;
+ UCHAR RoutePciInterrupts: 1;
+ };
+ UCHAR All;
+}ESC_PIRQ, *PESC_PIRQ;
+
+#define PIRQ_DISABLE_ROUTING 0x01
+#define PIRQ_ENABLE_ROUTING 0x00
+
+typedef union _ESC_GPXBC{
+ struct {
+ UCHAR EnableGpcs0: 1;
+ UCHAR EnableGpcs1: 1;
+ UCHAR EnableGpcs2: 1;
+ UCHAR Reserved: 5;
+ };
+ UCHAR All;
+}ESC_GPXBC, *PESC_GPXBC;
+
+#endif // !_LANGUAGE_ASSEMBLY
+
+//
+// PCI-EISA Bridge Configuration register offsets. These should be
+// simply ored with PCI_CONFIGURATION_BASE_QVA; they match what's
+// in the Intel handbook for the 82375EB (PCEB).
+//
+#define PCI_VENDOR_ID 0x00 // ro
+#define PCI_DEVICE_ID 0x02 // ro
+#define PCI_COMMAND 0x04 // rw
+#define PCI_DEVICE_STATUS 0x06 // ro, rw clear
+#define PCI_REVISION 0x08 // ro
+#define PCI_MASTER_LATENCY_TIMER 0x0d // rw
+#define PCI_CONTROL 0x40 // rw
+#define PCI_ARBITER_CONTROL 0x41 // rw
+#define PCI_ARBITER_PRIORITY_CONTROL 0x42 // rw
+#define PCI_MEMCS_CONTROL 0x44 // rw
+#define PCI_MEMCS_BOTTOM_OF_HOLE 0x45 // rw
+#define PCI_MEMCS_TOP_OF_HOLE 0x46 // rw
+#define PCI_MEMCS_TOP_OF_MEMORY 0x47 // rw
+#define PCI_EISA_ADDRESS_DECODE_CONTROL_1 0x48 // rw
+#define PCI_ISA_IO_RECOVERY_TIME_CONTROL 0x4c // rw
+#define PCI_MEMCS_ATTRIBUTE_REGISTER_1 0x54 // rw
+#define PCI_MEMCS_ATTRIBUTE_REGISTER_2 0x55 // rw
+#define PCI_MEMCS_ATTRIBUTE_REGISTER_3 0x56 // rw
+#define PCI_DECODE_CONTROL 0x58 // rw
+#define PCI_EISA_ADDRESS_DECODE_CONTROL_2 0x5a // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGIONS_ATTR 0x5c // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION1_REGISTER 0x60 // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION2_REGISTER 0x64 // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION3_REGISTER 0x68 // rw
+#define PCI_EISA_TO_PCI_MEMORY_REGION4_REGISTER 0x6c // rw
+#define PCI_EISA_TO_PCI_IO_REGION1_REGISTER 0x70 // rw
+#define PCI_EISA_TO_PCI_IO_REGION2_REGISTER 0x74 // rw
+#define PCI_EISA_TO_PCI_IO_REGION3_REGISTER 0x78 // rw
+#define PCI_EISA_TO_PCI_IO_REGION4_REGISTER 0x7c // rw
+#define PCI_BIOS_TIMER_BASE_ADDRESS 0x80 // rw
+#define PCI_EISA_LATENCY_TIMER_CONTROL_REGISTER 0x84 // rw
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+//
+// Structure definitions of registers in PCEB PCI configuration space.
+// fields marked "Not supported" are Intel placeholders, apparently.
+//
+
+typedef union _PCEB_PCICMD{
+ struct {
+ USHORT IoSpaceEnable : 1;
+ USHORT MemorySpaceEnable : 1;
+ USHORT BusMasterEnable : 1;
+ USHORT SpecialCycleEnable: 1; // Not supported
+ USHORT MemoryWriteInvalidateEnable : 1; // Not supported
+ USHORT VgaPaletteSnoop : 1; // Not supported
+ USHORT ParityErrorEnable : 1;
+ USHORT WaitStateControl : 1; // Not supported
+ USHORT SerreEnable : 1; // Not supported
+ USHORT Reserved : 7;
+ };
+ USHORT All;
+} PCEB_PCICMD, *PPCEB_PCICMD;
+
+typedef union _PCEB_PCISTS{
+ struct {
+ USHORT Reserved : 9;
+ USHORT DevselTiming: 2; // ro
+ USHORT SignaledTargetAbort : 1; // Not supported
+ USHORT ReceivedTargetAbort: 1; // r/wc
+ USHORT MasterAbort : 1; // r/wc
+ USHORT Serrs : 1; // Not supported
+ USHORT ParityError: 1; // r/wc
+ };
+ USHORT All;
+} PCEB_PCISTS, *PPCEB_PCISTS;
+
+typedef union _PCEB_MLT{
+ struct {
+ UCHAR Reserved : 3;
+ UCHAR LatencyTimerCount: 5;
+ };
+ UCHAR All;
+} PCEB_MLT, *PPCEB_MLT;
+
+typedef union _PCEB_PCICON{
+ struct {
+ UCHAR Reserved1 : 2;
+ UCHAR PciPostedWriteBuffersEnable: 1;
+ UCHAR SubtractDecodeSamplePoint: 2;
+ UCHAR InterruptAcknowledgeEnable: 1;
+ UCHAR EisaToPciLineBuffersEnable: 1;
+ UCHAR Reserved2 : 1;
+ };
+ UCHAR All;
+} PCEB_PCICON, *PPCEB_PCICON;
+
+#define PCICON_SDSP_SLOW 0x00
+#define PCICON_SDSP_TYPICAL 0x01
+#define PCICON_SDSP_FAST 0x02
+
+typedef union _PCEB_ARBCON{
+ struct {
+ UCHAR GuaranteedAccessTimeEnable : 1;
+ UCHAR BusLockEnable: 1;
+ UCHAR CpuBusParkEnable: 1;
+ UCHAR MasterRetryTimer: 2;
+ UCHAR Reserved : 2;
+ UCHAR AutoPereqControlEnable: 1;
+ };
+ UCHAR All;
+} PCEB_ARBCON, *PPCEB_ARBCON;
+
+#define ARBCON_RETRY_TIMER_DISABLE 0x00
+#define ARBCON_16_PCICLKS_UNMASK 0x01
+#define ARBCON_32_PCICLKS_UNMASK 0x02
+#define ARBCON_64_PCICLKS_UNMASK 0x03
+
+typedef union _PCEB_ARBPRI{
+ struct {
+ UCHAR Bank0FixedPriorityMode : 1;
+ UCHAR Bank1FixedPriorityMode: 1;
+ UCHAR Bank2FixedPriorityMode: 2;
+ UCHAR Bank0RotateEnable: 1;
+ UCHAR Bank1RotateEnable: 1;
+ UCHAR Bank2RotateEnable: 1;
+ UCHAR Bank3RotateEnable: 1;
+ };
+ UCHAR All;
+} PCEB_ARBPRI, *PPCEB_ARBPRI;
+
+#define ARBPRI_BANK0_BANK3_BANK1 0x00
+#define ARBPRI_BANK3_BANK1_BANK0 0x10
+#define ARBPRI_BANK1_BANK0_BANK3 0x01
+
+typedef union _PCEB_MCSCON{
+ struct {
+ UCHAR ReadEnable512To640 : 1;
+ UCHAR WriteEnable512To640: 1;
+ UCHAR ReadEnableUpper64K: 1;
+ UCHAR WriteEnableUpper64K: 1;
+ UCHAR MemcsMasterEnable: 1;
+ UCHAR Reserved: 3;
+ };
+ UCHAR All;
+} PCEB_MCSCON, *PPCEB_MCSCON;
+
+typedef union _PCEB_EADC1{
+ struct {
+ USHORT Block0To512 : 1;
+ USHORT Block512To640: 1;
+ USHORT Block640To768: 1;
+ USHORT Reserved: 5;
+ USHORT Block768To784: 1;
+ USHORT Block784To800: 1;
+ USHORT Block800To816: 1;
+ USHORT Block816To832: 1;
+ USHORT Block832To848: 1;
+ USHORT Block848To864: 1;
+ USHORT Block864To880: 1;
+ USHORT Block880To896: 1;
+ };
+ UCHAR All;
+} PCEB_EADC1, *PPCEB_EADC1;
+
+typedef union _PCEB_IORT{
+ struct {
+ UCHAR RecoveryTimes16Bit : 2;
+ UCHAR RecoveryEnable16Bit: 1;
+ UCHAR RecoveryTimes8Bit : 3;
+ UCHAR RecoveryEnable8Bit: 1;
+ UCHAR Reserved: 1;
+ };
+ UCHAR All;
+} PCEB_IORT, *PPCEB_IORT;
+
+#define IORT_16BIT_1BCLK 0x01
+#define IORT_16BIT_2BCLKS 0x02
+#define IORT_16BIT_3BCLKS 0x03
+#define IORT_16BIT_4BCLKS 0x00
+
+#define IORT_8BIT_1BCLK 0x01
+#define IORT_8BIT_2BCLKS 0x02
+#define IORT_8BIT_3BCLKS 0x03
+#define IORT_8BIT_4BCLKS 0x04
+#define IORT_8BIT_5BCLKS 0x05
+#define IORT_8BIT_6BCLKS 0x06
+#define IORT_8BIT_7BCLKS 0x07
+#define IORT_8BIT_8BCLKS 0x00
+
+typedef union _PCEB_PDCON{
+ struct {
+ UCHAR PciDecodeMode : 1;
+ UCHAR Reserved1: 3;
+ UCHAR DecodeControlIde : 1;
+ UCHAR DecodeControl8259 : 1;
+ UCHAR Reserved2: 2;
+ };
+ UCHAR All;
+} PCEB_PDCON, *PPCEB_PDCON;
+
+#define SUBTRACTIVE_DECODE 0x00
+#define NEGATIVE_DECODE 0x01
+
+typedef struct _PCEB_EPMRA{
+ struct {
+ UCHAR Region1Attribute : 1;
+ UCHAR Region2Attribute : 1;
+ UCHAR Region3Attribute : 1;
+ UCHAR Region4Attribute : 1;
+ UCHAR Reserved: 4;
+ };
+ UCHAR All;
+} PCEB_EPMRA, *PPCEB_EPMRA;
+
+#define REGION_BUFFERED 0x01
+
+typedef struct _PCEB_MEMREGN{
+ USHORT BaseAddress;
+ USHORT LimitAddress;
+} PCEB_MEMREGN, *PPCEB_MEMREGN;
+
+typedef union _PCEB_IOREGN{
+ struct {
+ ULONG Reserved1: 2;
+ ULONG BaseAddress : 14;
+ ULONG Reserved2: 2;
+ ULONG LimitAddress : 14;
+ };
+ ULONG All;
+} PCEB_IOREGN, *PPCEB_IOREGN;
+
+typedef union _PCEB_BTMR{
+ struct {
+ USHORT BiosTimerEnable: 1;
+ USHORT Reserved: 1;
+ USHORT BaseAddress2thru15 : 14;
+ };
+ USHORT All;
+} PCEB_BTMR, *PPCEB_BTMR;
+
+#endif
+
+//
+// ESC value for setting edge/level operation in the control words.
+//
+#define IRQ0_LEVEL_SENSITIVE 0x01
+#define IRQ1_LEVEL_SENSITIVE 0x02
+#define IRQ2_LEVEL_SENSITIVE 0x04
+#define IRQ3_LEVEL_SENSITIVE 0x08
+#define IRQ4_LEVEL_SENSITIVE 0x10
+#define IRQ5_LEVEL_SENSITIVE 0x20
+#define IRQ6_LEVEL_SENSITIVE 0x40
+#define IRQ7_LEVEL_SENSITIVE 0x80
+#define IRQ8_LEVEL_SENSITIVE 0x01
+#define IRQ9_LEVEL_SENSITIVE 0x02
+#define IRQ10_LEVEL_SENSITIVE 0x04
+#define IRQ11_LEVEL_SENSITIVE 0x08
+#define IRQ12_LEVEL_SENSITIVE 0x10
+#define IRQ13_LEVEL_SENSITIVE 0x20
+#define IRQ14_LEVEL_SENSITIVE 0x40
+#define IRQ15_LEVEL_SENSITIVE 0x80
+
+//
+// Define primary (and only) CPU on an Mikasa system
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0)
+
+//
+// Define the default processor clock frequency used before the actual
+// value can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (200)
+
+#endif // _MIKASA_
diff --git a/private/ntos/nthals/halpinna/alpha/mkinitnt.c b/private/ntos/nthals/halpinna/alpha/mkinitnt.c
new file mode 100644
index 000000000..30bd816bc
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/mkinitnt.c
@@ -0,0 +1,970 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an Mikasa EV5 (Pinnacle) system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Scott Lee 29-Nov-1995
+ Adapted from Mikasa module for Mikasa EV5 (Pinnacle).
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "mikasa.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpFamilyName = "AlphaServer";
+PCHAR HalpProductName;
+ULONG HalpProcessorNumber = 5;
+
+#define MAX_INIT_MSG (80)
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Mikasa
+//
+// IRQ_H[0] = EPIC Error
+// IRQ_H[1] = EISA Interrupt (PIC)
+// IRQ_H[2] = PCI Interrupt
+// IRQ_H[3] = Reserved
+// IRQ_H[4] = Clock
+// IRQ_H[5] = NMI (includes Halt)
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+//ADDRESS_USAGE
+//MikasaPCIMemorySpace = {
+// NULL, CmResourceTypeMemory, PCIUsage,
+// {
+// __8MB, ( __32MB - __8MB ), // Start=8MB; Length=24MB
+// 0,0
+// }
+//};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// Define external references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Determines if the platform is a Noritake or a Corelle.
+//
+
+BOOLEAN HalpNoritakePlatform;
+BOOLEAN HalpCorellePlatform;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpPinnacleErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpNmiInterrupt(
+ VOID
+ );
+
+VOID
+HalpClearInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeMikasaAndNoritakeInterrupts(
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ );
+
+VOID
+HalpDetermineMachineType(
+ VOID
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern ULONG HalpCiaErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+ extern ULONG HalpHaltInterrupt();
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+// jwlfix - Does the following apply to me on Mikasa?
+//
+//jnfix, wkc - init the Eisa interrupts after the chip, don't init the
+// PIC here, fix halenablesysteminterrupt to init the pic
+// interrrupt, as in sable
+
+ //
+ // Initialize EISA, PCI and NMI interrupts.
+ //
+
+ HalpInitializeMikasaAndNoritakeInterrupts();
+
+ //
+ // Initialize the 21164 interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpCiaErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_IPL30] =
+ (PKINTERRUPT_ROUTINE)HalpNmiInterrupt;
+
+ PCR->InterruptRoutine[EV5_IPL31] = // machine check vector
+ (PKINTERRUPT_ROUTINE)HalpPinnacleErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_CRD_VECTOR] =
+ (PKINTERRUPT_ROUTINE)Halp21164CorrectedErrorInterrupt;
+
+ HalpStart21164Interrupts();
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize error handling for CIA.
+ //
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the parity checking
+ //
+
+ PciParityChecking = (BOOLEAN) (HalDisablePCIParityChecking == 0);
+ HalpInitializeCiaMachineChecks(ReportCorrectables = TRUE,
+ PciParityChecking);
+
+ //
+ // Determine which platform we are running on.
+ //
+
+ HalpDetermineMachineType();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Print a message with version number.
+ //
+
+ if ( HalpCorellePlatform ) {
+ HalpProductName = "800";
+ } else {
+ HalpProductName = "1000";
+ }
+
+ sprintf( MsgBuffer,
+ "Digital Equipment Corporation %s %s %d/%d\n",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+ HalDisplayString( MsgBuffer );
+
+ //
+ // Register the name of the HAL.
+ //
+
+ sprintf( MsgBuffer,
+ "%s %s %d/%d PCI/EISA HAL",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+ HalpRegisterPlatformResources( MsgBuffer );
+
+ }
+
+ return;
+
+}
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Eisa);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ Resource.u.Start = SUPERIO_INDEX_PORT;
+ Resource.u.Length = SUPERIO_PORT_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaChannel = 0x4;
+ Resource.u.DmaPort = 0x0;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function is called from HalpAllocateUncorrectableErrorFrame.
+ This function retuns the size of the system specific error frame
+ sizes.
+
+Arguments:
+
+ RawProcessorSize - Processor-specific uncorrectable frame size.
+
+ RawSystemInfoSize - system-specific uncorrectable frame size.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(CIA_UNCORRECTABLE_FRAME);
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ Fills in the system information structure.
+ NOTE: Must later investigate the Fw call to get the firmware revision
+ ID. Must also figure out a way to get the OS version (preferebly the
+ build number).
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION structure.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char systemtype[] = "Pinnacle";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ if ( HalpCorellePlatform ) {
+ strcpy(systemtype, "Corelle");
+ }
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+
+ return;
+}
+
+
+VOID
+HalpDetermineMachineType(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine will determine which the platform we are running and set
+ HalpNoritakePlatform and HalpCorellePlatform accordingly.
+
+Arguments:
+
+ None.
+
+Return value:
+
+ None.
+
+--*/
+{
+
+ PSYSTEM_ID SystemId;
+
+ //
+ // Get the ProductId, and determine the machine type.
+ //
+
+ SystemId = ArcGetSystemId();
+
+ if((strstr( &SystemId->ProductId[0], "Pintake" ) != 0) ||
+ (strstr( &SystemId->ProductId[0], "PinNor") != 0)) {
+
+ HalpNoritakePlatform = TRUE;
+ HalpCorellePlatform = FALSE;
+
+ } else if ( strstr(&SystemId->ProductId[0], "Corelle" ) != 0) {
+
+ HalpNoritakePlatform = FALSE;
+ HalpCorellePlatform = TRUE;
+
+ } else {
+
+ HalpNoritakePlatform = FALSE;
+ HalpCorellePlatform = FALSE;
+
+ }
+
+}
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to Mikasa EV5 and the call should
+// be ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+//
+//jnfix - this variable is needed because the clock interrupt handler
+// - in intsup.s was made to be familiar with ev4prof.c, unfortunate
+// - since we don't use ev4prof.c, so for now this is a hack, later
+// - we will either fix intsup.s or create a new intsup.s that does
+// - not have this hack
+//
+
+ULONG HalpNumberOfTicksReload;
diff --git a/private/ntos/nthals/halpinna/alpha/mkintsup.c b/private/ntos/nthals/halpinna/alpha/mkintsup.c
new file mode 100644
index 000000000..f957e5312
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/mkintsup.c
@@ -0,0 +1,1075 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Mikasa EV5 (Pinnacle) systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Scott Lee (DEC) 30-Nov-1995
+ Adapted from Mikasa module for Mikasa EV5 (Pinnacle).
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "mikasa.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+//
+// Import globals declared in HalpMapIoSpace.
+//
+
+extern PVOID HalpServerControlQva;
+
+extern PVOID HalpMikasaPciIrQva;
+extern PVOID HalpMikasaPciImrQva;
+
+extern PVOID HalpNoritakePciIr1Qva;
+extern PVOID HalpNoritakePciIr2Qva;
+extern PVOID HalpNoritakePciIr3Qva;
+extern PVOID HalpNoritakePciImr1Qva;
+extern PVOID HalpNoritakePciImr2Qva;
+extern PVOID HalpNoritakePciImr3Qva;
+
+extern PVOID HalpCorellePciIr1Qva;
+extern PVOID HalpCorellePciIr2Qva;
+extern PVOID HalpCorellePciImr1Qva;
+extern PVOID HalpCorellePciImr2Qva;
+
+//
+// Import global from PCI interrupt management functions.
+//
+extern USHORT HalpMikasaPciInterruptMask;
+
+extern USHORT HalpNoritakePciInterrupt1Mask;
+extern USHORT HalpNoritakePciInterrupt2Mask;
+extern USHORT HalpNoritakePciInterrupt3Mask;
+
+extern USHORT HalpCorellePciInterrupt1Mask;
+extern USHORT HalpCorellePciInterrupt2Mask;
+
+//
+// Define reference to platform identifier
+//
+
+extern BOOLEAN HalpNoritakePlatform;
+extern BOOLEAN HalpCorellePlatform;
+
+//
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+
+ KINTERRUPT HalpPciInterrupt;
+ KINTERRUPT HalpEisaInterrupt;
+
+//
+// Declare the interrupt dispatch routine for PCI/EISA interrupts. The
+// interrupt dispatch routine, HalpPciDispatch or HalpEisaDispatch, is called
+// from this handler.
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+);
+
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+ULONG NMIcount = 0;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// PCI initialization routines
+//
+
+VOID
+HalpInitializeMikasaPciInterrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeNoritakePciInterrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeCorellePciInterrupts(
+ VOID
+ );
+
+
+BOOLEAN
+HalpInitializeMikasaAndNoritakeInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the EISA interrupt controller; the Mikasa, Noritake, and Corelle ESC
+ interrupt controllers are compatible with the EISA interrupt controller
+ used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // There's no initialization required for the Mikasa PCI interrupt
+ // "controller," as it's the wiring of the hardware, rather than a
+ // PIC like the 82c59 that directs interrupts. We do set the IMR to
+ // zero to disable all interrupts, initially.
+ //
+ // The Noritake requires a separate routine to setup the 3 interrupt
+ // mask registers correctly.
+ //
+ // Corelle requires a separate routine to setup the 2 interrupt mask
+ // registers correctly.
+ //
+
+ if( HalpNoritakePlatform ) {
+
+ HalpInitializeNoritakePciInterrupts();
+
+ } else if ( HalpCorellePlatform ) {
+
+ HalpInitializeCorellePciInterrupts();
+
+ } else {
+
+ HalpInitializeMikasaPciInterrupts();
+
+ }
+
+ //
+ // We must initialize the ESC's PICs, for EISA interrupts.
+ //
+
+ HalpInitializeEisaInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This function is entered as a result of an interrupt being generated via
+ the vector that is connected to an interrupt object associated with the
+ PCI/EISA device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ USHORT IrContents;
+ BOOLEAN returnValue;
+
+ //
+ // Read the PCI interrupt register.
+ //
+
+ if (HalpNoritakePlatform) {
+
+ IrContents =
+ ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr1Qva));
+ IrContents &= HalpNoritakePciInterrupt1Mask;
+
+ } else if ( HalpCorellePlatform ) {
+
+ IrContents =
+ ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpCorellePciIr1Qva));
+ IrContents &= HalpCorellePciInterrupt1Mask;
+
+ } else {
+
+ IrContents =
+ ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpMikasaPciIrQva));
+ IrContents &= HalpMikasaPciInterruptMask;
+
+ }
+
+ //
+ // Determine whether a PCI interrupt or an EISA interrupt occurred
+ //
+
+ if (IrContents) {
+
+ //
+ // PCI interrupt. Call HalpPciDispatch.
+ //
+
+ if (HalpNoritakePlatform) {
+
+ returnValue = HalpPciDispatch(Interrupt, HalpNoritakePciIr1Qva,
+ TrapFrame);
+
+ } else if ( HalpCorellePlatform ) {
+
+ returnValue = HalpPciDispatch(Interrupt, HalpCorellePciIr1Qva,
+ TrapFrame);
+
+ } else {
+
+ returnValue = HalpPciDispatch(Interrupt, HalpMikasaPciIrQva,
+ TrapFrame);
+
+ }
+
+ } else {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ returnValue = HalpEisaDispatch(Interrupt, HalpEisaIntAckBase,
+ TrapFrame);
+
+ }
+
+ return returnValue;
+
+}
+
+
+
+VOID
+HalpNmiInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles the NMI interrupts that are routed to pwr_fail_irq_h.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Call HalHandleNMI to handle the interrupt
+ //
+
+ HalHandleNMI(NULL, NULL);
+
+}
+
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to initialize ESC NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register. Note that the other bits should be left as
+ // they are, according to the chip's documentation.
+ //
+
+ DataByte = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&DataByte))->NmiDisable = 0;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte);
+#ifdef HALDBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", DataByte);
+#endif
+
+}
+
+// jwlfix - I'll have to make this do something useful, since the console
+// halt button on Mikasa is connected to this interrupt. To start,
+// it will be a useful way to see if the interrupt gets connected.
+// The simple path is to check the server management register to
+// see if the "halt" button has been pressed on the operator's
+// console, and then initiate a hardware reset. On the other hand,
+// a server might not want to be halted so readily as that.
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+ UCHAR Datum;
+ ULONG Ir1Contents, Ir3Contents;
+
+ NMIcount++;
+
+ //
+ // Set the Eisa NMI disable bit. We do this to mask further NMI
+ // interrupts while we're servicing this one.
+ //
+ Datum = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&Datum))->NmiDisable = 1;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum);
+#ifdef HALDBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum);
+#endif
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Parity Check / Parity Error\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+#else
+ //
+ // jwlfix - For the present, we're commenting out an NMI parity
+ // error bugcheck, until investigation into its causes
+ // yields a better solution.
+ //
+ // HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ // KeBugCheck(NMI_HARDWARE_FAILURE);
+ // return (TRUE);
+#endif
+ }
+
+ //
+ // Handle the server management interrupts.
+ // sclfix - We will dismiss these interrupts for now. This will need to be
+ // change once we decide how to handle server management features.
+ //
+
+ Datum = READ_PORT_UCHAR((PUCHAR)HalpServerControlQva );
+
+ if (HalpNoritakePlatform) {
+
+ Ir3Contents = (ULONG)(READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr3Qva));
+
+ if (((PNORITAKE_SRV)(&Datum))->HaltIncoming == 0 ||
+ ((PNORITAKE_IMR3)(&Status))->TempWarn == 0 ||
+ ((PNORITAKE_IMR3)(&Status))->Power2Int == 0 ||
+ ((PNORITAKE_IMR3)(&Status))->Power1Int == 0 ||
+ ((PNORITAKE_IMR3)(&Status))->Fan2Fail == 0 ||
+ ((PNORITAKE_IMR3)(&Status))->Fan1Fail == 0) {
+
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Server management NMI\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+ DbgPrint("HalHandleNMI: Server management byte = 0x%x\r\n", Datum);
+ DbgPrint("HalHandleNMI: Ir3 contents = 0x%x\r\n", Ir3Contents);
+#endif
+
+ }
+
+ } else if (HalpCorellePlatform) {
+
+ Ir1Contents = (ULONG)(READ_PORT_USHORT((PUSHORT)HalpCorellePciIr1Qva));
+
+ if (((PCORELLE_SRV)(&Datum))->HaltIncoming == 0 ||
+ ((PCORELLE_IMR1)(&Status))->TempFailInt == 0 ||
+ ((PCORELLE_IMR1)(&Status))->TempWarnInt == 0 ||
+ ((PCORELLE_IMR1)(&Status))->Fan1FailInt == 0 ||
+ ((PCORELLE_IMR1)(&Status))->Fan2FailInt == 0) {
+
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Server management NMI\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+ DbgPrint("HalHandleNMI: Server managemnt byte = 0x%x\r\n", Datum);
+ DbgPrint("HalHandleNMI: Ir1 contents = 0x%x\r\n", Ir1Contents);
+#endif
+
+ }
+
+ } else {
+
+ if (((PMIKASA_SRV)(&Datum))->HaltIncoming == 0 ||
+ ((PMIKASA_SRV)(&Datum))->TempFail == 1 ||
+ ((PMIKASA_SRV)(&Datum))->DcOk1 == 0 ||
+ ((PMIKASA_SRV)(&Datum))->DcOk2 == 0 ||
+ ((PMIKASA_SRV)(&Datum))->Fan1Fault == 0 ||
+ ((PMIKASA_SRV)(&Datum))->Fan2Fault == 0) {
+
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Server management NMI\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+ DbgPrint("HalHandleNMI: Server Management Byte = 0x%x\r\n", Datum);
+#endif
+
+ }
+
+ }
+
+
+ if (StatusByte & 0x40) {
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Channel Check / IOCHK\n");
+ DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte);
+#else
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return (TRUE);
+#endif
+ }
+
+#if 0
+ // jwlfix - This code can be added in later, as we have need
+ // for it. It's good to have it here, for when it
+ // might be of use.
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+ // jwlfix - The following doesn't work, at this moment; it's
+ // likey the 12-bit shift, which should be a 5-bit
+ // shift on Mikasa.
+ //
+
+ BusAddress.HighPart = 0;
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++)
+ {
+ BusAddress.LowPart = (EisaPort << 12) + 0xC80;
+
+ Status = HalTranslateBusAddress(Eisa, // InterfaceType
+ 0, // BusNumber
+ BusAddress,
+ &AddressSpace, // 1=I/O address space
+ &TranslatedAddress); // QVA
+ if (Status == FALSE)
+ {
+ UCHAR pbuf[80];
+ sprintf(pbuf,
+ "Unable to translate bus address %x for EISA slot %d\n",
+ BusAddress.LowPart, EisaPort);
+ HalDisplayString(pbuf);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+
+ port = TranslatedAddress.LowPart;
+
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if its
+ // IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ }
+ }
+#ifdef HALDBG
+ // Reset extended NMI interrupts (for debugging purposes only).
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02);
+#endif
+#endif
+
+#ifdef HALDBG
+ DbgPrint("HalHandleNMI: Resetting PERR#; NMI count = %d\r\n", NMIcount);
+#endif
+
+ //
+ // Reset PERR# and disable it.
+ //
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04);
+
+ //
+ // now enable it again.
+ //
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0);
+
+ //
+ // Clear the Eisa NMI disable bit. This re-enables NMI interrupts,
+ // now that we're done servicing this one.
+ //
+ Datum = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ ((PNMI_ENABLE)(&Datum))->NmiDisable = 0;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum);
+#ifdef HALDBG
+ DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum);
+#endif
+
+ return(TRUE);
+}
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = (UCHAR) (INTERRUPT_ACKNOWLEDGE(ServiceContext));
+
+ return( InterruptVector );
+
+}
+
+
+UCHAR
+HalpAcknowledgeMikasaPciInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the Mikasa PCI interrupt register QVA.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector = 0;
+ USHORT IrContents;
+ int i;
+
+ //
+ // Find the first zero bit in the register, starting from the highest
+ // order bit. This implies a priority ordering that makes a certain
+ // amount of sense, in that bits 14 and 13 indicate temperature and
+ // power faults, while bit 12 is the Ncr53c810. Note that it's
+ // necessary to add one to the bit number to make the interrupt
+ // vector, a unit-origin value in the pin-to-line table. We do
+ // this by starting i at 16 and ending it at 1; that means zero
+ // is a non-enabled interrupt indication.
+ //
+
+ //
+ // First, get and complement the interrupt register, so that the
+ // pending interrupts will be the "1" bits. Then mask with the
+ // enabled mask, HalpMikasaPciInterruptMask;
+ //
+
+ IrContents = ~(0xffff & READ_PORT_USHORT( (PUSHORT)ServiceContext ));
+ IrContents &= HalpMikasaPciInterruptMask;
+
+ for (i = 16; i >= 1; i-- ) {
+ if ( IrContents & 0x8000 ) {
+ InterruptVector = i;
+ break;
+ } else {
+ IrContents <<= 1;
+ }
+ }
+ return( InterruptVector );
+
+}
+
+
+UCHAR
+HalpAcknowledgeNoritakePciInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the Noritake PCI interrupt register 1 QVA.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector = 0;
+ USHORT IrContents;
+ int i;
+
+ //
+ // Interrupt1 register contains the sum of all interrupts of Interrupt2
+ // and Interrupt3 registers in bit 0. The rest of the register contains
+ // the A and B interrupts of the 7 PCI slots. Interrupt2 register
+ // contains the sum of all of the unmasked interrupts of Interrupt 2 in bit
+ // 0. Bit 1 is asserted when any secondary PCI bus interrupt is asserted
+ // (including those in interrupt register 1) and the posted write buffers
+ // in the PPB have been flushed. The rest of the register contians the C
+ // and D interrupts of all of the slots. Interrupt3 register contains some
+ // safety and reliability interrupts. Please see mikasa.h for the
+ // definitions of which interrupt is at which bit in the register.
+ //
+ // Each bit in the registers corresponds to an interrupt vector (which
+ // will later have PCI_VECTORS added to it.) This vector can be obtained
+ // by adding the vector offset for that register to the bit position.
+ // These offsets are also defined in mikasa.h.
+ //
+ // All registers are "reverse-logic" (active low), where a 0 means that an
+ // interrupt is waiting. That is why we must complement the contents of
+ // the register before we mask with HalpNoritakePciInterruptXMask.
+ //
+
+ //
+ // First, get and complement the first interrupt register, so that the
+ // pending interrupts will be the "1" bits. Then mask with the
+ // enabled mask, HalpNoritakePciInterrupt1Mask;
+ //
+
+ IrContents =
+ ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr1Qva));
+ IrContents &= HalpNoritakePciInterrupt1Mask;
+
+ //
+ // Position bit 1 as the lowest bit. We will start checking here - this
+ // is the first "real" interrupt.
+ //
+
+ IrContents >>= 1;
+
+ for( i = 1; i < 16; i++ ) {
+ if( IrContents & 0x1 ) {
+ InterruptVector = i + REGISTER_1_VECTOR_OFFSET;
+ break;
+ }
+ IrContents >>= 1;
+ }
+
+
+ if( InterruptVector == 0 ) {
+
+ //
+ // We didn't find any interrupts in interrupt register 1.
+ // Check interrupt register 2.
+ //
+
+ IrContents =
+ ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr2Qva));
+ IrContents &= HalpNoritakePciInterrupt2Mask;
+
+ //
+ // Position bit 2 in the lowest bit. We will start checking here -
+ // this is the first "real" interrupt.
+ //
+
+ IrContents >>= 2;
+
+ for( i = 2; i < 16; i++ ) {
+ if( IrContents & 0x1 ) {
+ InterruptVector = i + REGISTER_2_VECTOR_OFFSET;
+ break;
+ }
+ IrContents >>= 1;
+ }
+
+ if( InterruptVector == 0 ) {
+
+ //
+ // We didn't find any interrupts in interrupt register 2.
+ // Check Interrupt Register 3.
+ //
+
+ IrContents = ~(0xffff &
+ READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr3Qva));
+ IrContents &= HalpNoritakePciInterrupt3Mask;
+
+ //
+ // Position bit 2 in the lowest bit. We will start checking here -
+ // this is the first "real" interrupt.
+ //
+
+ IrContents >>= 2;
+
+ for( i = 2; i < 6; i++ ) {
+ if( IrContents & 0x1 ) {
+ InterruptVector = i + REGISTER_3_VECTOR_OFFSET;
+ break;
+ }
+ IrContents >>= 1;
+ }
+
+ }
+
+ }
+
+ return( InterruptVector );
+
+}
+
+
+UCHAR
+HalpAcknowledgeCorellePciInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the PCI interrupt. Return the vector number of the
+ highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the Noritake PCI interrupt register 1 QVA.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+
+ UCHAR InterruptVector = 0;
+ USHORT IrContents;
+ int i;
+
+ //
+ // Interrupt register 1 contains the INTA and INTB interrupts. Bit 0 of
+ // the interrupt register contains the sum of all interrupts in interrupt
+ // register 2 which contains the INTC and INTD interrupts. The interrupts
+ // for the onboard SCSI (QLOGIC) and video (S3 TRIO 64) are also contained
+ // in interrupt register 1. All the signals in the interrupt registers are
+ // active low.
+
+ //
+ // First, get and complement the first interrupt register, so that the
+ // pending interrupts will be the "1" bits. Then mask with the
+ // enabled mask, HalpCorellePciInterrupt1Mask;
+ //
+
+ IrContents =
+ ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpCorellePciIr1Qva));
+ IrContents &= HalpCorellePciInterrupt1Mask;
+
+ //
+ // We will check for interrupts by starting from bit 1 of interrupt
+ // register 1. We will stop at bit 10 since bit 11 is reserved and always
+ // 1 and bit 12 to 15 are server management related interrupts.
+ //
+
+ IrContents >>= 1;
+
+ for (i = 1; i < 11; i++) {
+
+ if (IrContents & 0x1) {
+
+ InterruptVector = i + CORELLE_INTERRUPT1_OFFSET;
+ break;
+
+ }
+
+ IrContents >>= 1;
+
+ }
+
+ if (InterruptVector == 0) {
+
+ //
+ // Did not find any interrupts in interrupt register 1. Check interrupt
+ // register 2.
+ //
+
+ IrContents = ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpCorellePciIr2Qva));
+ IrContents &= HalpCorellePciInterrupt2Mask;
+
+ //
+ // We will start at bit 2 and stop at bit 9. The other bits are reserved
+ // and always 1.
+ //
+
+ IrContents >>= 2;
+
+ for (i = 2; i < 10; i++) {
+
+ if (IrContents & 0x1) {
+
+ InterruptVector = i + CORELLE_INTERRUPT2_OFFSET;
+ break;
+
+ }
+
+ IrContents >>= 1;
+
+ }
+
+ }
+
+ return (InterruptVector);
+
+}
+
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Mikasa comes from a Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halpinna/alpha/mkmapio.c b/private/ntos/nthals/halpinna/alpha/mkmapio.c
new file mode 100644
index 000000000..717436b9e
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/mkmapio.c
@@ -0,0 +1,240 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Mikasa EV5 (Pinnacle) system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Scott Lee 29-Nov-1995
+ Adapted from Mikasa module for Mikasa EV5 (Pinnacle) systems.
+
+--*/
+
+#include "halp.h"
+#include "mikasa.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+PVOID HalpServerControlQva;
+
+PVOID HalpMikasaPciIrQva;
+PVOID HalpMikasaPciImrQva;
+
+PVOID HalpNoritakePciIr1Qva;
+PVOID HalpNoritakePciIr2Qva;
+PVOID HalpNoritakePciIr3Qva;
+PVOID HalpNoritakePciImr1Qva;
+PVOID HalpNoritakePciImr2Qva;
+PVOID HalpNoritakePciImr3Qva;
+
+PVOID HalpCorellePciIr1Qva;
+PVOID HalpCorellePciIr2Qva;
+PVOID HalpCorellePciImr1Qva;
+PVOID HalpCorellePciImr2Qva;
+
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a Mikasa system using
+ the Quasi VA mechanism.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( CIA_PCI_SPARSE_IO_PHYSICAL );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( CIA_PCI_INTACK_PHYSICAL );
+
+ //
+ // Set up the Mikasa interrupt registers.
+ //
+ // Map PCI interrupt and interrupt mask registers. The former register
+ // receives the interrupt state of each individual pin in each PCI slot,
+ // the state of the NCR 53C810 interrupt, and two server management
+ // interrupts' states. The PCI interrupt mask register can mask each
+ // of the interrupts in the IR.
+ //
+
+ HalpMikasaPciIrQva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER);
+ HalpMikasaPciImrQva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER);
+
+ //
+ // Set up the Noritake interrupt registers.
+ //
+ // Map the PCI interrupt and interrupt mask registers for Noritake.
+ // There are three interrupt registers, and three mask registers.
+ // The exact contents are described in mikasa.h.
+ //
+ // The Base Address Register of the interrupt registers is set up in SROM.
+ // We can change this if we choose.
+ //
+
+ HalpNoritakePciIr1Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_1);
+ HalpNoritakePciImr1Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_1);
+
+ HalpNoritakePciIr2Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_2);
+ HalpNoritakePciImr2Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_2);
+
+ HalpNoritakePciIr3Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_3);
+ HalpNoritakePciImr3Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_3);
+
+
+ //
+ // Set up the Corelle interrupt registers.
+ //
+ // Map the PCI interrupt and interrupt mask registers for Corelle.
+ // There are two interrupt registers, and two mask registers. The exact
+ // contents are described in mikasa.h.
+ //
+
+ HalpCorellePciIr1Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_1);
+ HalpCorellePciImr1Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_1);
+
+ HalpCorellePciIr2Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_REGISTER_2);
+ HalpCorellePciImr2Qva = (PVOID)((ULONG)PciIoSpaceBase
+ + PCI_INTERRUPT_MASK_REGISTER_2);
+
+ //
+ // Map the Mikasa server management register. This single byte register
+ // contains the bits that enable control of the high-availability options
+ // on Mikasa. This is at the same location in the Noritake, but it has a
+ // slightly different content.
+ //
+
+ HalpServerControlQva = (PVOID)((ULONG)PciIoSpaceBase
+ + SERVER_MANAGEMENT_REGISTER);
+ //
+ // Map CMOS RAM address.
+ //
+
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + ESC_CMOS_ISA_PORT);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halpinna/alpha/mksysint.c b/private/ntos/nthals/halpinna/alpha/mksysint.c
new file mode 100644
index 000000000..51e7ba0a8
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/mksysint.c
@@ -0,0 +1,545 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ mkinitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Mikasa EV5 system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Scott Lee 30-Nov-1995
+ Adapted from Mikasa module for Mikasa EV5 (Pinnacle).
+
+--*/
+
+#include "halp.h"
+#include "mikasa.h"
+#include "axp21164.h"
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisableMikasaPciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableNoritakePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableCorellePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableMikasaPciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpEnableNoritakePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpEnableCorellePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+extern USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define reference to platform identifier
+//
+
+extern BOOLEAN HalpNoritakePlatform;
+extern BOOLEAN HalpCorellePlatform;
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+
+ if( HalpNoritakePlatform ) {
+
+ HalpDisableNoritakePciInterrupt(Vector);
+
+ } else if ( HalpCorellePlatform ) {
+
+ HalpDisableCorellePciInterrupt(Vector);
+
+ } else {
+
+ HalpDisableMikasaPciInterrupt(Vector);
+
+ }
+
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Disable the correctable error interrupt.
+ //
+
+ {
+ CIA_ERR_MASK CiaErrMask;
+
+ CiaErrMask.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.CorErr = 0x0;
+
+ WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ break;
+
+ } //end switch Vector
+
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+
+ if( HalpNoritakePlatform ) {
+
+ HalpEnableNoritakePciInterrupt( Vector, InterruptMode );
+
+ } else if ( HalpCorellePlatform ) {
+
+ HalpEnableCorellePciInterrupt( Vector, InterruptMode );
+
+ } else {
+
+ HalpEnableMikasaPciInterrupt( Vector, InterruptMode );
+
+ }
+
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Enable the correctable error interrupt.
+ //
+
+ {
+ CIA_ERR_MASK CiaErrMask;
+
+ CiaErrMask.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.CorErr = 0x1;
+
+ WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ }
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+jwlfix - How does the above apply to PCI when it's done as in Mikasa? I've
+ made the assumption the the same is true, but that must be checked.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21164.
+ //
+
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else if ((Vector = HalpGet21164CorrectableVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Correctable error interrupt was sucessfully recognized.
+ //
+
+ *Affinity = 1;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus ISA_VECTORS.
+ // N.B.: this encoding technique uses the notion of defining a
+ // base interrupt vector in the space defined by the constant,
+ // ISA_VECTORS, which may or may not differ from EISA_VECTORS or
+ // PCI_VECTORS.
+ //
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR
+ //
+
+ return(BusInterruptLevel + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on Mikasa systems.
+ //
+#if defined(HALDBG)
+ DbgPrint("MKSYSINT: InterfaceType (%d) not supported on Mikasa\r\n",
+ InterfaceType);
+#endif
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Mikasa because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/halpinna/alpha/nvenv.c b/private/ntos/nthals/halpinna/alpha/nvenv.c
new file mode 100644
index 000000000..ba5a5c8f7
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/nvenv.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvenv.c"
diff --git a/private/ntos/nthals/halpinna/alpha/nvram.c b/private/ntos/nthals/halpinna/alpha/nvram.c
new file mode 100644
index 000000000..879c41c68
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/nvram.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvram.c"
diff --git a/private/ntos/nthals/halpinna/alpha/pcibus.c b/private/ntos/nthals/halpinna/alpha/pcibus.c
new file mode 100644
index 000000000..60bff018e
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pcibus.c
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 29-Nov-1995 Scott Lee
+ Adapted from Mikasa module for Mikasa EV5 (Pinnacle).
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+//
+// Reference variable that defines largest PCI bus number.
+//
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0) {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Note that HalpValidPCISlot has already done bounds checking
+ // on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n",
+ pPciAddr->u.AsULONG);
+#endif // DBG
+
+ } else {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if HALDBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halpinna/alpha/pciesc.c b/private/ntos/nthals/halpinna/alpha/pciesc.c
new file mode 100644
index 000000000..49142ea83
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pciesc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pciesc.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/pciir.c b/private/ntos/nthals/halpinna/alpha/pciir.c
new file mode 100644
index 000000000..10c9e3af6
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pciir.c
@@ -0,0 +1,703 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pciir.c
+
+Abstract:
+
+ The module provides the interrupt support for the Mikasa's PCI
+ interrupts.
+
+Author:
+
+ James Livingston 2-May-1994
+
+Revision History:
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define external function prototypes
+//
+
+UCHAR
+HalpAcknowledgeMikasaPciInterrupt(
+ PVOID ServiceContext
+ );
+
+UCHAR
+HalpAcknowledgeNoritakePciInterrupt(
+ PVOID ServiceContext
+ );
+
+UCHAR
+HalpAcknowledgeCorellePciInterrupt(
+ PVOID ServiceContext
+ );
+
+//
+// Import save area for PCI interrupt mask register.
+//
+
+USHORT HalpMikasaPciInterruptMask;
+
+USHORT HalpNoritakePciInterrupt1Mask;
+USHORT HalpNoritakePciInterrupt2Mask;
+USHORT HalpNoritakePciInterrupt3Mask;
+
+USHORT HalpCorellePciInterrupt1Mask;
+USHORT HalpCorellePciInterrupt2Mask;
+
+//
+// Reference for globals defined in I/O mapping module.
+//
+extern PVOID HalpMikasaPciIrQva;
+extern PVOID HalpMikasaPciImrQva;
+
+extern PVOID HalpNoritakePciIr1Qva;
+extern PVOID HalpNoritakePciIr2Qva;
+extern PVOID HalpNoritakePciIr3Qva;
+extern PVOID HalpNoritakePciImr1Qva;
+extern PVOID HalpNoritakePciImr2Qva;
+extern PVOID HalpNoritakePciImr3Qva;
+
+extern PVOID HalpCorellePciIr1Qva;
+extern PVOID HalpCorellePciIr2Qva;
+extern PVOID HalpCorellePciImr1Qva;
+extern PVOID HalpCorellePciImr2Qva;
+
+//
+// Define reference to platform identifier
+//
+
+extern BOOLEAN HalpNoritakePlatform;
+extern BOOLEAN HalpCorellePlatform;
+
+
+VOID
+HalpInitializeMikasaPciInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Mikasa PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Initialize the Mikasa PCI interrupts. There is a single interrupt mask
+ // that permits individual interrupts to be enabled or disabled by
+ // setting the appropriate bit in the interrupt mask register. We
+ // initialize them all to "disabled".
+ //
+
+ HalpMikasaPciInterruptMask = 0;
+ WRITE_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva,
+ HalpMikasaPciInterruptMask );
+
+}
+
+
+VOID
+HalpInitializeNoritakePciInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Noritake PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Initialize the Noritake PCI interrupts. There are three interrupt masks
+ // that permit individual interrupts to be enabled or disabled by
+ // setting the appropriate bit in the interrupt mask register. We
+ // initialize them all to "disabled", except for the SUM bits. (Bit 0
+ // in IR1, and bits 0 and 1 in IR2.)
+ //
+
+ HalpNoritakePciInterrupt1Mask = 0x1;
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva,
+ HalpNoritakePciInterrupt1Mask );
+
+ HalpNoritakePciInterrupt2Mask = 0x3;
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr2Qva,
+ HalpNoritakePciInterrupt2Mask );
+
+ HalpNoritakePciInterrupt3Mask = 0x0;
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr3Qva,
+ HalpNoritakePciInterrupt3Mask );
+
+}
+
+
+VOID
+HalpInitializeCorellePciInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Corelle PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Initialize the Corelle PCI interrupts. There are 2 interrupt masks
+ // that permits individual interrupts to be enabled or disabled by
+ // setting the appropriate bit in the interrupt mask register. We will
+ // initialize them all to "disabled" except bit 0 of interrupt register 1
+ // which is the sum of all interrupts in interrupt register 2.
+ //
+
+ HalpCorellePciInterrupt1Mask = 0x1;
+ WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva,
+ HalpCorellePciInterrupt1Mask );
+
+ HalpCorellePciInterrupt2Mask = 0x0;
+ WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr2Qva,
+ HalpCorellePciInterrupt2Mask );
+
+}
+
+
+VOID
+HalpDisableMikasaPciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0, offset by one.
+ //
+
+ Vector -= PCI_VECTORS + 1;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ HalpMikasaPciInterruptMask =
+ READ_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva );
+ HalpMikasaPciInterruptMask &= (USHORT) ~(1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva,
+ HalpMikasaPciInterruptMask );
+
+}
+
+
+VOID
+HalpDisableNoritakePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // First we must determine which interrupt register the interrupt is in.
+ // In each case, subtract the register offset to get the bit position in
+ // the interrupt register. Then, get the current state of the interrupt
+ // mask register. Finally, set the bit corresponding to the adjusted value
+ // of Vector to zero, to disable that PCI interrupt.
+ //
+
+ if( Vector >= REGISTER_2_VECTOR_OFFSET ) {
+
+ if( Vector >= REGISTER_3_VECTOR_OFFSET ) {
+
+ //
+ // The interrupt is in Interrupt Register 3.
+ //
+
+ Vector -= REGISTER_3_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt3Mask = READ_PORT_USHORT(
+ (PUSHORT)HalpNoritakePciImr3Qva );
+ HalpNoritakePciInterrupt3Mask &= (USHORT) ~(1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr3Qva,
+ HalpNoritakePciInterrupt3Mask );
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 2.
+ //
+
+ Vector -= REGISTER_2_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt2Mask = READ_PORT_USHORT(
+ (PUSHORT)HalpNoritakePciImr2Qva );
+ HalpNoritakePciInterrupt2Mask &= (USHORT) ~(1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr2Qva,
+ HalpNoritakePciInterrupt2Mask );
+
+ }
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 1.
+ //
+
+ Vector -= REGISTER_1_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt1Mask =
+ READ_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva );
+ HalpNoritakePciInterrupt1Mask &= (USHORT) ~(1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva,
+ HalpNoritakePciInterrupt1Mask );
+
+ }
+
+}
+
+
+VOID
+HalpDisableCorellePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // First we must determine which interrupt register the interrupt is in.
+ // Then, get the current state of the interrupt mask register. Finally,
+ // set the bit corresponding to the adjusted value of Vector to zero, to
+ // disable that PCI interrupt.
+ //
+
+ if ( Vector >= CORELLE_INTERRUPT2_OFFSET ) {
+
+ //
+ // The interrupt is in interrupt register 2
+ //
+
+ Vector -= CORELLE_INTERRUPT2_OFFSET;
+
+ HalpCorellePciInterrupt2Mask =
+ READ_PORT_USHORT((PUSHORT)HalpCorellePciImr2Qva );
+ HalpCorellePciInterrupt2Mask &= (USHORT) ~(1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr2Qva,
+ HalpCorellePciInterrupt2Mask );
+
+ } else {
+
+ //
+ // The interrupt is in interrupt register 1
+ //
+
+ Vector -= CORELLE_INTERRUPT1_OFFSET;
+
+ HalpCorellePciInterrupt1Mask =
+ READ_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva );
+ HalpCorellePciInterrupt1Mask &= (USHORT) ~(1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva,
+ HalpCorellePciInterrupt1Mask );
+
+ }
+
+}
+
+
+VOID
+HalpEnableMikasaPciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Mikasa PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0, offset by one.
+ //
+
+ Vector -= PCI_VECTORS + 1;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to one,
+ // to enable that PCI interrupt.
+ //
+
+ HalpMikasaPciInterruptMask =
+ READ_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva );
+ HalpMikasaPciInterruptMask |= (USHORT) (1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva,
+ HalpMikasaPciInterruptMask );
+
+}
+
+
+VOID
+HalpEnableNoritakePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Mikasa PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // First we must determine which interrupt register the interrupt is in.
+ // In each case, subtract the register offset to get the bit position in
+ // the interrupt register. Then, get the current state of the interrupt
+ // mask register. Finally, set the bit corresponding to the adjusted value
+ // of Vector to one, to enable that PCI interrupt.
+ //
+
+ if( Vector >= REGISTER_2_VECTOR_OFFSET ) {
+
+ if( Vector >= REGISTER_3_VECTOR_OFFSET ) {
+
+ //
+ // The interrupt is in Interrupt Register 3.
+ //
+
+ Vector -= REGISTER_3_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt3Mask = READ_PORT_USHORT(
+ (PUSHORT)HalpNoritakePciImr3Qva );
+ HalpNoritakePciInterrupt3Mask |= (USHORT) (1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr3Qva,
+ HalpNoritakePciInterrupt3Mask );
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 2.
+ //
+
+ Vector -= REGISTER_2_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt2Mask = READ_PORT_USHORT(
+ (PUSHORT)HalpNoritakePciImr2Qva );
+ HalpNoritakePciInterrupt2Mask |= (USHORT) (1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr2Qva,
+ HalpNoritakePciInterrupt2Mask );
+
+ }
+
+ } else {
+
+ //
+ // The interrupt is in Interrupt Register 1.
+ //
+
+ Vector -= REGISTER_1_VECTOR_OFFSET;
+
+ HalpNoritakePciInterrupt1Mask =
+ READ_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva );
+ HalpNoritakePciInterrupt1Mask |= (USHORT) (1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva,
+ HalpNoritakePciInterrupt1Mask );
+
+ }
+
+}
+
+
+VOID
+HalpEnableCorellePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Mikasa PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // First we must determine which interrupt register the interrupt is in.
+ // Then, get the current state of the interrupt mask register. Finally,
+ // set the bit corresponding to the adjusted value of Vector to zero, to
+ // disable that PCI interrupt.
+ //
+
+ if ( Vector >= CORELLE_INTERRUPT2_OFFSET ) {
+
+ //
+ // The interrupt is in interrupt register 2
+ //
+
+ Vector -= CORELLE_INTERRUPT2_OFFSET;
+
+ HalpCorellePciInterrupt2Mask =
+ READ_PORT_USHORT((PUSHORT)HalpCorellePciImr2Qva );
+ HalpCorellePciInterrupt2Mask |= (USHORT) (1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr2Qva,
+ HalpCorellePciInterrupt2Mask );
+
+ } else {
+
+ //
+ // The interrupt is in interrupt register 1
+ //
+
+ Vector -= CORELLE_INTERRUPT1_OFFSET;
+
+ HalpCorellePciInterrupt1Mask =
+ READ_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva );
+ HalpCorellePciInterrupt1Mask |= (USHORT) (1 << Vector);
+ WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva,
+ HalpCorellePciInterrupt1Mask );
+
+ }
+
+}
+
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt having been generated
+ via the vector connected to the PCI device interrupt object. Its function
+ is to call the second-level interrupt dispatch routine.
+
+ This service routine could have been connected as follows, where the
+ ISR is the assembly wrapper that does the handoff to this function:
+
+ KeInitializeInterrupt( &Interrupt,
+ HalpPciInterruptHandler,
+ (PVOID) HalpPciIrQva,
+ (PKSPIN_LOCK)NULL,
+ PCI_VECTOR,
+ PCI_DEVICE_LEVEL,
+ PCI_DEVICE_LEVEL,
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE);
+
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR PCIVector;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+
+ //
+ // Acknowledge interrupt and receive the returned interrupt vector.
+ // If we got zero back, there were no enabled interrupts, so we
+ // signal that with a FALSE return, immediately.
+ //
+
+ if( HalpNoritakePlatform ) {
+
+ PCIVector = HalpAcknowledgeNoritakePciInterrupt(ServiceContext);
+
+ } else if ( HalpCorellePlatform ) {
+
+ PCIVector = HalpAcknowledgeCorellePciInterrupt(ServiceContext);
+
+ } else {
+
+ PCIVector = HalpAcknowledgeMikasaPciInterrupt(ServiceContext);
+
+ }
+
+ if (PCIVector == 0) {
+ return( FALSE );
+ }
+
+ PCRInOffset = PCIVector + PCI_VECTORS;
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset],
+ TrapFrame
+ );
+
+ return( returnValue );
+}
+
+
+
+
diff --git a/private/ntos/nthals/halpinna/alpha/pcisup.c b/private/ntos/nthals/halpinna/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/pcrtc.c b/private/ntos/nthals/halpinna/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/pcserial.c b/private/ntos/nthals/halpinna/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/pcspeakr.c b/private/ntos/nthals/halpinna/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/perfcntr.c b/private/ntos/nthals/halpinna/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halpinna/alpha/pinnaerr.c b/private/ntos/nthals/halpinna/alpha/pinnaerr.c
new file mode 100644
index 000000000..1e581ff82
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pinnaerr.c
@@ -0,0 +1,157 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alcorerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Mikasa EV5 (Pinnacle) platform.
+
+Author:
+
+ Joe Notarangelo 27-Jul-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Scott Lee 30-Nov-1995
+
+ Adapted from Alcor module for Mikasa EV5 (Pinnacle).
+
+--*/
+
+#include "halp.h"
+#include "mikasa.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+VOID
+HalpPinnacleErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for a PINNACLE machine check interrupt
+ The function calls HalpCiaReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // If this is a CIA uncorrectable error then report the error and
+ // crash the system.
+ //
+
+ if( HalpCiaUncorrectableError() == TRUE ){
+
+ HalpCiaReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG) PUncorrectableError );
+
+ }
+
+ //
+ // It was not a CIA uncorrectable error, therefore this must be an
+ // NMI interrupt.
+ //
+
+ HalHandleNMI( NULL, NULL );
+
+ return; // never
+
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+ //
+ // All machine check handling on Alcor is determined by the CIA.
+ //
+
+ return( HalpCiaMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ) );
+
+}
diff --git a/private/ntos/nthals/halpinna/alpha/pintolin.h b/private/ntos/nthals/halpinna/alpha/pintolin.h
new file mode 100644
index 000000000..38e016f36
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/pintolin.h
@@ -0,0 +1,251 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Table
+ for Mikasa.
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston (Digital) 10-May-1994
+ Extracted Mikasa-specific table from the combined table
+ of pin-to-line assignments.
+
+ Janet Schneider (Digital) 27-July-1995
+ Added support for the Noritake.
+
+ Scott Lee (Digital) 15-July-1996
+ Added support for Corelle.
+
+--*/
+
+//
+// This table represents the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// On platforms that use an interrupt register or registers instead of,
+// or in addition to cascaded 85c59s, the Interrupt Vector is one greater
+// than the Interrupt Request Register bit, because interrupt vectors
+// can't be zero, and bits in a register are numbered from zero. On
+// Mikasa, the Interrupt Vector also represents the Interrupt Mask
+// Register bit, since the arrangement of its bits is identical to
+// that of the Interrupt Read Register.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// (SlotNumber.DeviceNumber, InterruptPin) -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit + 1
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit + 1
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to:
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table for lookup function is initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (Slot.DeviceNumber + 11)
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]).
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#,
+// INTD#, per the PCI Spec. V2.0, Section 2.2.6. Devices having one
+// interrupt use INTA#; only multifunction devices use INTB#, INTC#,
+// INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which can have the values:
+//
+// INTA# = 1, INTB# = 2, INTC# = 3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots. Each function has its own PCI
+// configuration space, addressed by the SlotNumber.FunctionNumber field,
+// and will identify which interrput pin of the four it will use in its
+// own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts from "downstream" PCI
+// slots must somehow be combined to appear on some combination of the
+// four interrupt pins belonging to the bridge's slot.
+//
+// InterruptLine:
+// This PCI Configuration register is maintained by software, and holds
+// an offset into PCI interrupt vectors. Whenever HalGetBusData or
+// HalGetBusDataByOffset is called, HalpPCIPinToLine() computes the
+// correct InterruptLine register value by using the mapping in
+// HalpPCIPinToLineTable.
+//
+// InterruptRequestRegisterBit:
+// In the table, 0xff is used to mark an invalid cell; this cell cannot
+// be used to produce an interrupt request register bit.
+//
+// InterruptMaskRegisterBit:
+// On Mikasa, the pin-to-line table may also be used to write the
+// InterruptMaskRegister, via
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used, should we be accessing a multifunction device.)
+// Virtual slot 0 represents the device with IDSEL = AD[11], and so on.
+//
+//
+// Interrupt Vector Table Mapping for Mikasa.
+//
+// Mikasa PCI interrupts are mapped to interrupt vectors in the table
+// below. The values are a 1-1 map of the bit numbers in the Mikasa
+// PCI interrupt register that are connected to PCI devices.
+//
+// N.B.: there are two other interrupts in the Mikasa IRR/IMR, but they
+// are not connected to I/O devices, and have no associated PCI virtual
+// slot, so they're not represented in the table. Entries in the table
+// are interrupt vector values for the device having the given virtual
+// slot and pin number.
+//
+// Limit init table to 15 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_MIKASA.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 15 = PCI_AD[25].
+//
+
+PULONG HalpPCIPinToLineTable;
+
+ULONG MikasaPCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xd, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] ESC
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0x1, 0x2, 0x3, 0x4 }, // Virtual Slot 11 = PCI_AD[22] Slot #0
+ { 0x5, 0x6, 0x7, 0x8 }, // Virtual Slot 12 = PCI_AD[23] Slot #1
+ { 0x9, 0xa, 0xb, 0xc }, // Virtual Slot 13 = PCI_AD[24] Slot #2
+ { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 14 = PCI_AD[25]
+};
+
+
+//
+// Limit init table to 15 entries, which is the MAX_PCI_LOCAL_DEVICES_MIKASA.
+// (It is same for Noritake.)
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 14 = PCI_AD[25] on bus 0.
+//
+// Noritake PCI interrupts will be no lower than 0x11 so that they are disjoint
+// from EISA levels.
+//
+
+ULONG NoritakePCIPinToLineTable0[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] PCEB
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] PCI-PCI Bridge
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0x13, 0x14, 0x23, 0x24 }, // Virtual Slot 11 = PCI_AD[22] Slot 0
+ { 0x15, 0x16, 0x25, 0x26 }, // Virtual Slot 12 = PCI_AD[23] Slot 1
+ { 0x17, 0x18, 0x27, 0x28 }, // Virtual Slot 13 = PCI_AD[24] Slot 2
+ { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 14 = PCI_AD[25]
+};
+
+
+ULONG NoritakePCIPinToLineTable1[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0x12, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[16] QLogic
+ { 0x19, 0x1a, 0x29, 0x2a }, // Virtual Slot 1 = PCI_AD[17] Slot 3
+ { 0x1b, 0x1c, 0x2b, 0x2c }, // Virtual Slot 2 = PCI_AD[18] Slot 4
+ { 0x1d, 0x1e, 0x2d, 0x2e }, // Virtual Slot 3 = PCI_AD[19] Slot 5
+ { 0x1f, 0x20, 0x2f, 0x30 } // Virtual Slot 4 = PCI_AD[20] Slot 6
+};
+
+//
+// Define the pintolin table for Corelle.
+//
+
+ULONG CorellePCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x11, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] QLogic
+ { 0x1a, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] S3 Trio 64
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] PCEB
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0x12, 0x13, 0x22, 0x23 }, // Virtual Slot 11 = PCI_AD[22] Slot #0
+ { 0x14, 0x15, 0x24, 0x25 }, // Virtual Slot 12 = PCI_AD[23] Slot #1
+ { 0x16, 0x17, 0x26, 0x27 }, // Virtual Slot 13 = PCI_AD[24] Slot #2
+ { 0x18, 0x19, 0x28, 0x29 } // Virtual Slot 14 = PCI_AD[25] Slot #3
+};
+
+
diff --git a/private/ntos/nthals/halpinna/alpha/vga.c b/private/ntos/nthals/halpinna/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halpinna/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halpinna/drivesup.c b/private/ntos/nthals/halpinna/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halpinna/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halpinna/hal.rc b/private/ntos/nthals/halpinna/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halpinna/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halpinna/hal.src b/private/ntos/nthals/halpinna/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halpinna/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halpinna/makefile b/private/ntos/nthals/halpinna/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halpinna/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halpinna/makefile.inc b/private/ntos/nthals/halpinna/makefile.inc
new file mode 100644
index 000000000..b3e4adbef
--- /dev/null
+++ b/private/ntos/nthals/halpinna/makefile.inc
@@ -0,0 +1,7 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halpinna.lib
+ copy $** $@
+
+
diff --git a/private/ntos/nthals/halpinna/sources b/private/ntos/nthals/halpinna/sources
new file mode 100644
index 000000000..25af904f5
--- /dev/null
+++ b/private/ntos/nthals/halpinna/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halpinna
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DEISA_PLATFORM -DTAGGED_NVRAM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cia.c \
+ alpha\ciaaddr.c \
+ alpha\ciaerr.c \
+ alpha\ciaio.s \
+ alpha\devintr.s \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\ev5cache.c \
+ alpha\ev5int.c \
+ alpha\ev5ints.s \
+ alpha\ev5mchk.c \
+ alpha\ev5mem.s \
+ alpha\ev5prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\haltsup.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\iousage.c \
+ alpha\ioproc.c \
+ alpha\memory.c \
+ alpha\nvenv.c \
+ alpha\nvram.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\pinnaerr.c \
+ alpha\vga.c \
+ alpha\busdata.c \
+ alpha\mkinitnt.c \
+ alpha\mkintsup.c \
+ alpha\mkmapio.c \
+ alpha\mksysint.c \
+ alpha\cmos8k.c \
+ alpha\pcisup.c \
+ alpha\pciir.c \
+ alpha\pciesc.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halppc/hal.rc b/private/ntos/nthals/halppc/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halppc/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halppc/makefile b/private/ntos/nthals/halppc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halppc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halppc/makefile.inc b/private/ntos/nthals/halppc/makefile.inc
new file mode 100644
index 000000000..db43490ff
--- /dev/null
+++ b/private/ntos/nthals/halppc/makefile.inc
@@ -0,0 +1,3 @@
+$(TARGETPATH)\ppc\hal.lib: $(TARGETPATH)\ppc\halppc.lib
+ copy $** $@
+
diff --git a/private/ntos/nthals/halppc/ppc/bbldef.h b/private/ntos/nthals/halppc/ppc/bbldef.h
new file mode 100644
index 000000000..97a9ee69f
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bbldef.h
@@ -0,0 +1,446 @@
+
+#ifndef _H_BBLDEF
+#define _H_BBLDEF
+
+#include "halp.h"
+
+//#include <ntos.h>
+
+//
+// Used for debugging
+//
+
+#if defined(BBL_DBG) && DBG
+#define BBL_DBG_PRINT DbgPrint
+#else
+#define BBL_DBG_PRINT
+#endif // !DBG
+
+//
+// Define the physical memory attribites
+//
+
+//#define BBL_BASE_ADDR 0xD0000000
+//#define BBL_VIDEO_MEMORY_BASE 0xD4000000
+#define BBL_VIDEO_MEMORY_OFFSET 0x04000000
+#define BBL_VIDEO_MEMORY_LENGTH 0x200000 // 2 MB
+//#define BBL_REG_ADDR_BASE 0xDA000000
+#define BBL_REG_ADDR_OFFSET 0x0A000000
+#define BBL_REG_ADDR_LENGTH 0x1000 // 4 K
+#define BBL_SCANLINE_LENGTH 0x800 // 2 K
+
+
+//
+// Define the register base
+//
+
+#define BBL_REG_BASE (HalpBBLRegisterBase)
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_REG (regbase, register, data) *
+* caddr_t regbase; *
+* caddr_t register; *
+* unsigned long data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* register - Register offset of adapter register to write *
+* data - Data to write to the register *
+* *
+* Description: Writes the "data" value in the adapter register *
+* *
+* Notes: This macro may only be used by the device driver because *
+* it does not require the adapter pointer. This macro may *
+* only be called from kernel level code. *
+* *
+******************************************************************************/
+
+#define BBL_SET_REG(regbase, register, data) \
+ (*((volatile unsigned long *) \
+ ((unsigned long)(regbase) | (register)))) = \
+ ((volatile unsigned long)(data))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_REG (regbase, register) *
+* caddr_t regbase; *
+* caddr_t register; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* register - Register offset of adapter register to write *
+* *
+* Description: Reads the value in the adapter register *
+* *
+* Notes: This macro may only be used by the device driver because *
+* it does not require the adapter pointer. This macro may *
+* only be called from kernel level code. *
+* *
+* Returns: This macro is a RHS macro which expands to the value of *
+* the register *
+* *
+******************************************************************************/
+
+#define BBL_GET_REG(regbase, register) \
+ (volatile unsigned long) \
+ (*((volatile unsigned long *) \
+ ((unsigned long)(regbase) | (register))))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_DD_EIEIO *
+* *
+* Parameters: None *
+* *
+* Description: This macro expands to the PowerPC assembly instruction eieio *
+* *
+* Notes: This macro compiles to an in-line assembly instruction so *
+* there is no function call overhead. The eieio instruction *
+* takes between 3 and 6 cycles on the 601 processor which *
+* amounts to 45 - 90 ns on the 66MHX 601 processor. *
+* *
+* Returns: Expands into the "eieio" in-line assembly instruction. *
+* *
+******************************************************************************/
+
+#define BBL_EIEIO __builtin_eieio()
+
+
+//
+// Configure the GXT150 Graphics Adapter. This function sets the
+// necessary PCI config space registers to enable the GXT150P
+// Graphics Adapter in the system for further I/O requests to it
+//
+
+// Standard PCI configuration register offsets
+#define PCI_DEV_VEND_ID_REG 0x00
+#define PCI_CMD_STAT_REG 0x04
+#define PCI_CMD_REG 0x04
+#define PCI_STAT_REG 0x06
+#define PCI_BASE_ADDR_REG 0x10
+
+// GXT150P device specific configuration register offsets
+#define BBL_DEV_CHAR_REG 0x40
+#define BBL_BUID1_REG 0x48
+#define BBL_XIVR_REG 0x60
+#define BBL_INTL_REG 0x64
+#define BBL_BELE_REG 0x70
+
+// GXT150P configuration register values
+#define BBL_DEV_VEND_ID 0x001B1014
+#define BBL_DEV_CHAR_VAL 0x34900040
+#define BBL_BUID1_VAL 0x00A50000
+#define BBL_XIVR_VAL 0x00000004
+#define BBL_INTL_VAL 0x0000000F
+#define BBL_BELE_VAL 0x00000008 // Little Endian Mode
+
+#define BBL_VEN_ID 0x1014
+#define BBL_DEV_ID 0x001b
+
+#define BBL_MEM_ENABLE 0x0002
+
+
+//
+// Define the monitor ID (cable and DIP switch) masks
+//
+
+#define BBL_MON_ID_DIP_SWITCHES_SHIFT 16
+#define BBL_MON_ID_DIP_SWITCHES_MASK \
+ (0xF << BBL_MON_ID_DIP_SWITCHES_SHIFT)
+
+#define BBL_MON_ID_CABLE_ID_0 0x0
+#define BBL_MON_ID_CABLE_ID_H 0x1
+#define BBL_MON_ID_CABLE_ID_V 0x2
+#define BBL_MON_ID_CABLE_ID_1 0x3
+
+#define BBL_MON_ID_CABLE_BIT_0_SHIFT 6
+#define BBL_MON_ID_CABLE_BIT_0_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_0_SHIFT)
+#define BBL_MON_ID_CABLE_BIT_1_SHIFT 4
+#define BBL_MON_ID_CABLE_BIT_1_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_1_SHIFT)
+#define BBL_MON_ID_CABLE_BIT_2_SHIFT 2
+#define BBL_MON_ID_CABLE_BIT_2_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_2_SHIFT)
+#define BBL_MON_ID_CABLE_BIT_3_SHIFT 0
+#define BBL_MON_ID_CABLE_BIT_3_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_3_SHIFT)
+
+
+//
+// For CRT control register:
+//
+// 7 6 5 4 3 2 1 0
+// --------------------------------------------
+// | 0 | 0 | 0 | VSP | HSP | CSE | CSG | BPE |
+// --------------------------------------------
+//
+// where VPS = vert. sync polarity
+// HPS = horz. sync polarity (reversed if either CSE or CSG
+// are on for DD2 parts)
+//
+// CSE = composite sync enable on HSYNC (when enabled, bit 4 -> don't care)
+//
+// CSG = composite sync on green (when enabled, bits 4,3,2 -> don't care)
+// BPE = blanking pedistal enable
+//
+
+
+//
+// Define the monitor types
+//
+
+typedef struct _bbl_mon_data_t {
+ ULONG monitor_id;
+#define BBL_MON_PEDISTAL_ENABLE (1L << 0)
+#define BBL_MON_COMPOSITE_SYNC_ON_GREEN (1L << 1)
+#define BBL_MON_COMPOSITE_SYNC_ON_HSYNC (1L << 2)
+#define BBL_MON_HORZ_SYNC_POLARITY_POSITIVE (1L << 3)
+#define BBL_MON_VERT_SYNC_POLARITY_POSITIVE (1L << 4)
+ ULONG crt_cntl;
+ ULONG x_res;
+ ULONG y_res;
+ ULONG frame_rate;
+ ULONG pixel_freq;
+ ULONG hrz_total;
+ ULONG hrz_disp_end;
+ ULONG hrz_sync_start;
+ ULONG hrz_sync_end1;
+ ULONG hrz_sync_end2;
+ ULONG vrt_total;
+ ULONG vrt_disp_end;
+ ULONG vrt_sync_start;
+ ULONG vrt_sync_end;
+#define BBL_MON_COLOR (1L << 0)
+#define BBL_MON_MONO (0L << 0)
+ ULONG flags;
+} bbl_mon_data_t, *pbbl_mon_data_t;
+
+
+//
+// Set up the monitor data information
+//
+
+static bbl_mon_data_t bbl_mon_data[] = {
+
+ #define BBL_MT_1 0x000200cc /* 0010 1010 */
+ /* 1024x768 70Hz 78Mhz PSYNC */
+ { BBL_MT_1,
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE |
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE,
+ 1024,768,7000,7800,
+ 1367,1023,1047,1327,0,
+ 813,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_2 0x000a00cc /* 1010 1010 */
+ /* 1280x1024 60Hz 112Mhz NSYNC */
+ { BBL_MT_2,
+ 0x0,
+ 1280,1024,6000,11200,
+ 1759,1279,1299,1455,1103,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_3 0x000b00cc /* 1011 1010 */
+ /* 1024x768 75.8Hz 86Mhz PSYNC */
+ { BBL_MT_3,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1351,711,
+ 805,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_4 0x000d00cc /* 1101 1010 */
+ /* 1280x1024 77Hz 148Mhz NSYNC */
+ { BBL_MT_4,
+ 0x0,
+ 1280,1024,7700,14800,
+ 1819,1279,1319,1503,1115,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_5 0x000f00cc /* 1111 1010 */
+ /* 1024x768 60Hz 64Mhz NSYNC */
+ { BBL_MT_5,
+ 0x0,
+ 1024,768,6000,6400,
+ 1311,1023,1055,1151,991,
+ 812,767,770,773,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_6 0x000f003f /* 1111 0111 */
+ /* 1280x1024 67Hz 128Mhz NSYNC */
+ { BBL_MT_6,
+ 0x0,
+ 1280,1024,6700,12800,
+ 1807,1279,1351,1607,0,
+ 1055,1023,1023,1031,
+ BBL_MON_MONO },
+
+ #define BBL_MT_7 0x000f004c /* 1111 H010 */
+ /* 1024x768 70Hz 78Mhz PSYNC */
+ { BBL_MT_7,
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE |
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE,
+ 1024,768,7000,7800,
+ 1367,1023,1047,1327,0,
+ 813,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_8 0x00010030 /* 0001 0100 */
+ /* 1024x768 75.8Hz 86Mhz SOG */
+ { BBL_MT_8,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1351,711,
+ 805,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_8_PATCH 0x000b0030 /* 1011 0100 */
+ /* 1024x768 75.8Hz 86Mhz PSYNC */
+ { BBL_MT_8_PATCH,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1351,711,
+ 805,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_8_PATCH_1 0x00040030 /* 0100 0100 */
+ /* 1024x768 75.8Hz 86Mhz SOG */
+ { BBL_MT_8_PATCH_1,
+ BBL_MON_PEDISTAL_ENABLE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1231,831,
+ 805,767,770,778,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_9 0x00020030 /* 0010 0100 */
+ /* 1024x768 70Hz 75Mhz SOG */
+ { BBL_MT_9,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1024,768,7000,7500,
+ 1323,1023,1115,1191,1039,
+ 807,767,767,769,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_10 0x00030030 /* 0011 0100 */
+ /* 1024x768 60Hz 64Mhz SOG */
+ { BBL_MT_10,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1024,768,6000,6400,
+ 1311,1023,1087,1183,991,
+ 812,767,770,773,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_11 0x00060030 /* 0110 0100 */
+ /* 1280x1024 74Hz 135Mhz SOG */
+ { BBL_MT_11,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,7400,13500,
+ 1711,1279,1311,1455,1167,
+ 1065,1023,1023,1026,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_12 0x00070030 /* 0111 0100 */
+ /* 1280x1024 60Hz 108Mhz SOG */
+ { BBL_MT_12,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,6000,10800,
+ 1707,1279,1323,1507,1139,
+ 1052,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_13 0x000d0030 /* 1101 0100 */
+ /* 1280x1024 77Hz 148Mhz SOG */
+ { BBL_MT_13,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,7700,14800,
+ 1819,1279,1319,1503,1115,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_14 0x000e0030 /* 1110 0100 */
+ /* 1280x1024 67Hz 120Mhz SOG */
+ { BBL_MT_14,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,6700,12000,
+ 1695,1279,1311,1471,1151,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_15 0x000f0030 /* 1111 0100 */
+ /* 1280x1024 60Hz 112Mhz SOG */
+ { BBL_MT_15,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,6000,11200,
+ 1759,1279,1299,1455,1103,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_16 0x000f00bf /* 1111 V111 */
+ /* 1280x1024 72Hz 128Mhz */
+ { BBL_MT_16,
+ 0x0,
+ 1280,1024,7200,12800,
+ 1687,1279,1311,1451,1167,
+ 1059,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_17 0x000400ff /* 0100 1111 */
+ /* 1152x900 66Hz 93Mhz CSYNC */
+ { BBL_MT_17,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_HSYNC,
+ 1152,900,6600,9300,
+ 1503,1151,1179,1307,1051,
+ 936,899,901,905,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_18 0x000500ff /* 0101 1111 */
+ /* 1152x900 76Hz 106Mhz CSYNC */
+ { BBL_MT_18,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_HSYNC,
+ 1152,900,7600,10600,
+ 1471,1151,1163,1259,1067,
+ 942,899,901,909,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_DEFAULT 0x000f00ff /* 1111 1111 */
+ /* THIS IS THE DEFAULT MONITOR ID */
+ /* THIS IS THE NO-MONITOR ATTACHED ID */
+ /* These settings are the same as BBL_MT_5 */
+ /* 1024x768 60Hz 64Mhz NSYNC */
+ { BBL_MT_DEFAULT,
+ 0x0,
+ 1024,768,6000,6400,
+ 1311,1023,1055,1151,991,
+ 812,767,770,773,
+ BBL_MON_COLOR },
+};
+
+#endif // _H_BBLDEF
+
diff --git a/private/ntos/nthals/halppc/ppc/bblfont.h b/private/ntos/nthals/halppc/ppc/bblfont.h
new file mode 100644
index 000000000..450aa9642
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bblfont.h
@@ -0,0 +1,1499 @@
+/*++
+
+Module Name:
+
+ bblfont.h
+
+Abstract:
+
+ This header file defines a font suitable for use with the HAL
+ text on the GXT150P graphics adapter. The font data is standard
+ OEM VGA font data (10x20 glyphs)
+
+--*/
+
+/*
+UCHAR BBLFont[12288] = {
+*/
+UCHAR BBLFont[11832] = {
+0x00, 0x02, 0x3e, 0x2c, 0x00, 0x00, 0x28, 0x63,
+0x29, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
+0x67, 0x68, 0x74, 0x20, 0x42, 0x69, 0x74, 0x73,
+0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x49, 0x6e,
+0x63, 0x2e, 0x20, 0x31, 0x39, 0x38, 0x34, 0x2e,
+0x20, 0x41, 0x6c, 0x6c, 0x20, 0x72, 0x69, 0x67,
+0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65,
+0x72, 0x76, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x60, 0x00,
+0x60, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x90, 0x01, 0xff, 0x0a, 0x00,
+0x14, 0x00, 0x30, 0x0a, 0x00, 0x0a, 0x00, 0x01,
+0xfe, 0x1f, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x36, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x72, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00,
+0x72, 0x04, 0x0a, 0x00, 0x9a, 0x04, 0x0a, 0x00,
+0xc2, 0x04, 0x0a, 0x00, 0xea, 0x04, 0x0a, 0x00,
+0x12, 0x05, 0x0a, 0x00, 0x3a, 0x05, 0x0a, 0x00,
+0x62, 0x05, 0x0a, 0x00, 0x8a, 0x05, 0x0a, 0x00,
+0xb2, 0x05, 0x0a, 0x00, 0xda, 0x05, 0x0a, 0x00,
+0x02, 0x06, 0x0a, 0x00, 0x2a, 0x06, 0x0a, 0x00,
+0x52, 0x06, 0x0a, 0x00, 0x7a, 0x06, 0x0a, 0x00,
+0xa2, 0x06, 0x0a, 0x00, 0xca, 0x06, 0x0a, 0x00,
+0xf2, 0x06, 0x0a, 0x00, 0x1a, 0x07, 0x0a, 0x00,
+0x42, 0x07, 0x0a, 0x00, 0x6a, 0x07, 0x0a, 0x00,
+0x92, 0x07, 0x0a, 0x00, 0xba, 0x07, 0x0a, 0x00,
+0xe2, 0x07, 0x0a, 0x00, 0x0a, 0x08, 0x0a, 0x00,
+0x32, 0x08, 0x0a, 0x00, 0x5a, 0x08, 0x0a, 0x00,
+0x82, 0x08, 0x0a, 0x00, 0xaa, 0x08, 0x0a, 0x00,
+0xd2, 0x08, 0x0a, 0x00, 0xfa, 0x08, 0x0a, 0x00,
+0x22, 0x09, 0x0a, 0x00, 0x4a, 0x09, 0x0a, 0x00,
+0x72, 0x09, 0x0a, 0x00, 0x9a, 0x09, 0x0a, 0x00,
+0xc2, 0x09, 0x0a, 0x00, 0xea, 0x09, 0x0a, 0x00,
+0x12, 0x0a, 0x0a, 0x00, 0x3a, 0x0a, 0x0a, 0x00,
+0x62, 0x0a, 0x0a, 0x00, 0x8a, 0x0a, 0x0a, 0x00,
+0xb2, 0x0a, 0x0a, 0x00, 0xda, 0x0a, 0x0a, 0x00,
+0x02, 0x0b, 0x0a, 0x00, 0x2a, 0x0b, 0x0a, 0x00,
+0x52, 0x0b, 0x0a, 0x00, 0x7a, 0x0b, 0x0a, 0x00,
+0xa2, 0x0b, 0x0a, 0x00, 0xca, 0x0b, 0x0a, 0x00,
+0xf2, 0x0b, 0x0a, 0x00, 0x1a, 0x0c, 0x0a, 0x00,
+0x42, 0x0c, 0x0a, 0x00, 0x6a, 0x0c, 0x0a, 0x00,
+0x92, 0x0c, 0x0a, 0x00, 0xba, 0x0c, 0x0a, 0x00,
+0xe2, 0x0c, 0x0a, 0x00, 0x0a, 0x0d, 0x0a, 0x00,
+0x32, 0x0d, 0x0a, 0x00, 0x5a, 0x0d, 0x0a, 0x00,
+0x82, 0x0d, 0x0a, 0x00, 0xaa, 0x0d, 0x0a, 0x00,
+0xd2, 0x0d, 0x0a, 0x00, 0xfa, 0x0d, 0x0a, 0x00,
+0x22, 0x0e, 0x0a, 0x00, 0x4a, 0x0e, 0x0a, 0x00,
+0x72, 0x0e, 0x0a, 0x00, 0x9a, 0x0e, 0x0a, 0x00,
+0xc2, 0x0e, 0x0a, 0x00, 0xea, 0x0e, 0x0a, 0x00,
+0x12, 0x0f, 0x0a, 0x00, 0x3a, 0x0f, 0x0a, 0x00,
+0x62, 0x0f, 0x0a, 0x00, 0x8a, 0x0f, 0x0a, 0x00,
+0xb2, 0x0f, 0x0a, 0x00, 0xda, 0x0f, 0x0a, 0x00,
+0x02, 0x10, 0x0a, 0x00, 0x2a, 0x10, 0x0a, 0x00,
+0x52, 0x10, 0x0a, 0x00, 0x7a, 0x10, 0x0a, 0x00,
+0xa2, 0x10, 0x0a, 0x00, 0xca, 0x10, 0x0a, 0x00,
+0xf2, 0x10, 0x0a, 0x00, 0x1a, 0x11, 0x0a, 0x00,
+0x42, 0x11, 0x0a, 0x00, 0x6a, 0x11, 0x0a, 0x00,
+0x92, 0x11, 0x0a, 0x00, 0xba, 0x11, 0x0a, 0x00,
+0xe2, 0x11, 0x0a, 0x00, 0x0a, 0x12, 0x0a, 0x00,
+0x32, 0x12, 0x0a, 0x00, 0x5a, 0x12, 0x0a, 0x00,
+0x82, 0x12, 0x0a, 0x00, 0xaa, 0x12, 0x0a, 0x00,
+0xd2, 0x12, 0x0a, 0x00, 0xfa, 0x12, 0x0a, 0x00,
+0x22, 0x13, 0x0a, 0x00, 0x4a, 0x13, 0x0a, 0x00,
+0x72, 0x13, 0x0a, 0x00, 0x9a, 0x13, 0x0a, 0x00,
+0xc2, 0x13, 0x0a, 0x00, 0xea, 0x13, 0x0a, 0x00,
+0x12, 0x14, 0x0a, 0x00, 0x3a, 0x14, 0x0a, 0x00,
+0x62, 0x14, 0x0a, 0x00, 0x8a, 0x14, 0x0a, 0x00,
+0xb2, 0x14, 0x0a, 0x00, 0xda, 0x14, 0x0a, 0x00,
+0x02, 0x15, 0x0a, 0x00, 0x2a, 0x15, 0x0a, 0x00,
+0x52, 0x15, 0x0a, 0x00, 0x7a, 0x15, 0x0a, 0x00,
+0xa2, 0x15, 0x0a, 0x00, 0xca, 0x15, 0x0a, 0x00,
+0xf2, 0x15, 0x0a, 0x00, 0x1a, 0x16, 0x0a, 0x00,
+0x42, 0x16, 0x0a, 0x00, 0x6a, 0x16, 0x0a, 0x00,
+0x92, 0x16, 0x0a, 0x00, 0xba, 0x16, 0x0a, 0x00,
+0xe2, 0x16, 0x0a, 0x00, 0x0a, 0x17, 0x0a, 0x00,
+0x32, 0x17, 0x0a, 0x00, 0x5a, 0x17, 0x0a, 0x00,
+0x82, 0x17, 0x0a, 0x00, 0xaa, 0x17, 0x0a, 0x00,
+0xd2, 0x17, 0x0a, 0x00, 0xfa, 0x17, 0x0a, 0x00,
+0x22, 0x18, 0x0a, 0x00, 0x4a, 0x18, 0x0a, 0x00,
+0x72, 0x18, 0x0a, 0x00, 0x9a, 0x18, 0x0a, 0x00,
+0xc2, 0x18, 0x0a, 0x00, 0xea, 0x18, 0x0a, 0x00,
+0x12, 0x19, 0x0a, 0x00, 0x3a, 0x19, 0x0a, 0x00,
+0x62, 0x19, 0x0a, 0x00, 0x8a, 0x19, 0x0a, 0x00,
+0xb2, 0x19, 0x0a, 0x00, 0xda, 0x19, 0x0a, 0x00,
+0x02, 0x1a, 0x0a, 0x00, 0x2a, 0x1a, 0x0a, 0x00,
+0x52, 0x1a, 0x0a, 0x00, 0x7a, 0x1a, 0x0a, 0x00,
+0xa2, 0x1a, 0x0a, 0x00, 0xca, 0x1a, 0x0a, 0x00,
+0xf2, 0x1a, 0x0a, 0x00, 0x1a, 0x1b, 0x0a, 0x00,
+0x42, 0x1b, 0x0a, 0x00, 0x6a, 0x1b, 0x0a, 0x00,
+0x92, 0x1b, 0x0a, 0x00, 0xba, 0x1b, 0x0a, 0x00,
+0xe2, 0x1b, 0x0a, 0x00, 0x0a, 0x1c, 0x0a, 0x00,
+0x32, 0x1c, 0x0a, 0x00, 0x5a, 0x1c, 0x0a, 0x00,
+0x82, 0x1c, 0x0a, 0x00, 0xaa, 0x1c, 0x0a, 0x00,
+0xd2, 0x1c, 0x0a, 0x00, 0xfa, 0x1c, 0x0a, 0x00,
+0x22, 0x1d, 0x0a, 0x00, 0x4a, 0x1d, 0x0a, 0x00,
+0x72, 0x1d, 0x0a, 0x00, 0x9a, 0x1d, 0x0a, 0x00,
+0xc2, 0x1d, 0x0a, 0x00, 0xea, 0x1d, 0x0a, 0x00,
+0x12, 0x1e, 0x0a, 0x00, 0x3a, 0x1e, 0x0a, 0x00,
+0x62, 0x1e, 0x0a, 0x00, 0x8a, 0x1e, 0x0a, 0x00,
+0xb2, 0x1e, 0x0a, 0x00, 0xda, 0x1e, 0x0a, 0x00,
+0x02, 0x1f, 0x0a, 0x00, 0x2a, 0x1f, 0x0a, 0x00,
+0x52, 0x1f, 0x0a, 0x00, 0x7a, 0x1f, 0x0a, 0x00,
+0xa2, 0x1f, 0x0a, 0x00, 0xca, 0x1f, 0x0a, 0x00,
+0xf2, 0x1f, 0x0a, 0x00, 0x1a, 0x20, 0x0a, 0x00,
+0x42, 0x20, 0x0a, 0x00, 0x6a, 0x20, 0x0a, 0x00,
+0x92, 0x20, 0x0a, 0x00, 0xba, 0x20, 0x0a, 0x00,
+0xe2, 0x20, 0x0a, 0x00, 0x0a, 0x21, 0x0a, 0x00,
+0x32, 0x21, 0x0a, 0x00, 0x5a, 0x21, 0x0a, 0x00,
+0x82, 0x21, 0x0a, 0x00, 0xaa, 0x21, 0x0a, 0x00,
+0xd2, 0x21, 0x0a, 0x00, 0xfa, 0x21, 0x0a, 0x00,
+0x22, 0x22, 0x0a, 0x00, 0x4a, 0x22, 0x0a, 0x00,
+0x72, 0x22, 0x0a, 0x00, 0x9a, 0x22, 0x0a, 0x00,
+0xc2, 0x22, 0x0a, 0x00, 0xea, 0x22, 0x0a, 0x00,
+0x12, 0x23, 0x0a, 0x00, 0x3a, 0x23, 0x0a, 0x00,
+0x62, 0x23, 0x0a, 0x00, 0x8a, 0x23, 0x0a, 0x00,
+0xb2, 0x23, 0x0a, 0x00, 0xda, 0x23, 0x0a, 0x00,
+0x02, 0x24, 0x0a, 0x00, 0x2a, 0x24, 0x0a, 0x00,
+0x52, 0x24, 0x0a, 0x00, 0x7a, 0x24, 0x0a, 0x00,
+0xa2, 0x24, 0x0a, 0x00, 0xca, 0x24, 0x0a, 0x00,
+0xf2, 0x24, 0x0a, 0x00, 0x1a, 0x25, 0x0a, 0x00,
+0x42, 0x25, 0x0a, 0x00, 0x6a, 0x25, 0x0a, 0x00,
+0x92, 0x25, 0x0a, 0x00, 0xba, 0x25, 0x0a, 0x00,
+0xe2, 0x25, 0x0a, 0x00, 0x0a, 0x26, 0x0a, 0x00,
+0x32, 0x26, 0x0a, 0x00, 0x5a, 0x26, 0x0a, 0x00,
+0x82, 0x26, 0x0a, 0x00, 0xaa, 0x26, 0x0a, 0x00,
+0xd2, 0x26, 0x0a, 0x00, 0xfa, 0x26, 0x0a, 0x00,
+0x22, 0x27, 0x0a, 0x00, 0x4a, 0x27, 0x0a, 0x00,
+0x72, 0x27, 0x0a, 0x00, 0x9a, 0x27, 0x0a, 0x00,
+0xc2, 0x27, 0x0a, 0x00, 0xea, 0x27, 0x0a, 0x00,
+0x12, 0x28, 0x0a, 0x00, 0x3a, 0x28, 0x0a, 0x00,
+0x62, 0x28, 0x0a, 0x00, 0x8a, 0x28, 0x0a, 0x00,
+0xb2, 0x28, 0x0a, 0x00, 0xda, 0x28, 0x0a, 0x00,
+0x02, 0x29, 0x0a, 0x00, 0x2a, 0x29, 0x0a, 0x00,
+0x52, 0x29, 0x0a, 0x00, 0x7a, 0x29, 0x0a, 0x00,
+0xa2, 0x29, 0x0a, 0x00, 0xca, 0x29, 0x0a, 0x00,
+0xf2, 0x29, 0x0a, 0x00, 0x1a, 0x2a, 0x0a, 0x00,
+0x42, 0x2a, 0x0a, 0x00, 0x6a, 0x2a, 0x0a, 0x00,
+0x92, 0x2a, 0x0a, 0x00, 0xba, 0x2a, 0x0a, 0x00,
+0xe2, 0x2a, 0x0a, 0x00, 0x0a, 0x2b, 0x0a, 0x00,
+0x32, 0x2b, 0x0a, 0x00, 0x5a, 0x2b, 0x0a, 0x00,
+0x82, 0x2b, 0x0a, 0x00, 0xaa, 0x2b, 0x0a, 0x00,
+0xd2, 0x2b, 0x0a, 0x00, 0xfa, 0x2b, 0x08, 0x00,
+0x22, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f,
+0xe1, 0xc0, 0xd2, 0xd2, 0xc0, 0xde, 0xcc, 0xe1,
+0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f,
+0xff, 0xff, 0xed, 0xed, 0xff, 0xe1, 0xf3, 0xff,
+0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0xf3, 0xff, 0xff, 0xff, 0x7f, 0x3f,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0,
+0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0c, 0x1e, 0x3f, 0x7f, 0xff, 0x7f, 0x3f,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 0x1e, 0x1e, 0x6d, 0xff, 0xff, 0x6d, 0x0c,
+0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 0x1e, 0x3f, 0x7f, 0xff, 0xff, 0x6d, 0x0c,
+0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x1e, 0x1e, 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, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xc0, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x40,
+0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1e, 0x21, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40,
+0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1,
+0x80, 0x80, 0x8c, 0x9e, 0x9e, 0x8c, 0x80, 0x80,
+0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x40, 0x40, 0x40,
+0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01,
+0x03, 0x07, 0x3e, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7,
+0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+0x61, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x3f, 0x0c,
+0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0,
+0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0xfc,
+0xfc, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x79,
+0xfb, 0xf3, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x7f,
+0x33, 0x61, 0x61, 0x33, 0x7f, 0xde, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0x80, 0x00, 0x80, 0x80, 0x00,
+0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x70, 0x78,
+0x7c, 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x7c, 0x78,
+0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07,
+0x0f, 0x1f, 0x3f, 0x7f, 0x3f, 0x1f, 0x0f, 0x07,
+0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f,
+0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x73, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7b,
+0x7b, 0x7b, 0x7b, 0x3b, 0x1b, 0x1b, 0x1b, 0x1b,
+0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33,
+0x30, 0x1c, 0x1e, 0x36, 0x33, 0x33, 0x1b, 0x1e,
+0x0e, 0x03, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f,
+0x3f, 0x1e, 0x0c, 0x7f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f,
+0x3f, 0x1e, 0x0c, 0x00, 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, 0x00, 0x0c,
+0x0e, 0x07, 0x7f, 0x7f, 0x07, 0x0e, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x1c, 0x38, 0x7f, 0x7f, 0x38, 0x1c, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x60, 0x60, 0x60, 0x7f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x33, 0x7f, 0x7f, 0x33, 0x12, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7f, 0x3f, 0x1e, 0x0c, 0x00,
+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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e,
+0x1e, 0x1e, 0x1e, 0x1e, 0x0c, 0x0c, 0x0c, 0x00,
+0x0c, 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, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x33, 0x7f, 0x7f, 0x33, 0x33, 0x7f, 0x7f, 0x33,
+0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x1e, 0x3f,
+0x73, 0x70, 0x38, 0x1c, 0x06, 0x03, 0x03, 0x73,
+0x3f, 0x1e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xdb, 0xdb,
+0x76, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x33, 0x36,
+0x66, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b,
+0x31, 0x1b, 0x0e, 0x18, 0x33, 0x61, 0x61, 0x63,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0xc0, 0x80, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c,
+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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18,
+0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x10, 0x18, 0x0c, 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, 0x30, 0x18, 0x0c,
+0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x06, 0x04, 0x0c, 0x18, 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,
+0x00, 0x61, 0x33, 0x1e, 0x7f, 0x1e, 0x33, 0x61,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x0c, 0x7f, 0x7f, 0x0c, 0x0c, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 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,
+0x0c, 0x0c, 0x04, 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, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 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, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18,
+0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x3c,
+0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 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, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x01, 0x03, 0x0e, 0x0f, 0x03, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x33,
+0x33, 0x33, 0x33, 0x63, 0x7f, 0x7f, 0x03, 0x03,
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x7e, 0x7f, 0x03, 0x01, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x6e, 0x7f, 0x73, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f,
+0x01, 0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x33, 0x1e, 0x3f, 0x73, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x73, 0x3f, 0x1d, 0x01, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00,
+0x0c, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00,
+0x0c, 0x0c, 0x04, 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, 0x03,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c,
+0x06, 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, 0x3e, 0x3e, 0x00, 0x00, 0x3e, 0x3e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
+0x18, 0x0c, 0x06, 0x03, 0x01, 0x03, 0x06, 0x0c,
+0x18, 0x30, 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, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x03, 0x07, 0x0e, 0x0c, 0x0c, 0x00,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x61, 0x61, 0x67, 0x6f, 0x69, 0x69, 0x6f, 0x67,
+0x60, 0x3f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61, 0x61, 0x61,
+0x7f, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63,
+0x7f, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x60, 0x7e, 0x7e, 0x60, 0x60, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x60, 0x7e, 0x7e, 0x60, 0x60, 0x60,
+0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x60, 0x67, 0x67, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 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, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x67,
+0x6e, 0x7c, 0x78, 0x70, 0x78, 0x7c, 0x6e, 0x67,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x73, 0x73, 0x7f, 0x7f, 0x6d, 0x6d, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x71,
+0x71, 0x79, 0x79, 0x6d, 0x6d, 0x67, 0x67, 0x63,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x63, 0x7f, 0x7e, 0x60, 0x60,
+0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x61, 0x61, 0x61, 0x67, 0x77,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x63, 0x7f, 0x7e, 0x63, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x70, 0x38, 0x1c, 0x06, 0x03, 0x03, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x33,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+0x7f, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x33, 0x33, 0x1e, 0x0c, 0x0c, 0x1e, 0x33, 0x33,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x33, 0x1e, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x1e, 0x1e, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06,
+0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x1e, 0x1e, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x1e, 0x33, 0x40, 0x00,
+0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x1c, 0x0c, 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, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x7f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x1d, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1f,
+0x18, 0x18, 0x7f, 0x7f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x03, 0x3f, 0x3e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00,
+0x00, 0x1e, 0x1e, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x0e, 0x3c, 0x38, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x63, 0x66, 0x6c, 0x78, 0x70, 0x7c, 0x66,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6d, 0x7f, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x7f, 0x6e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1d, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6f, 0x7f, 0x78, 0x70, 0x60, 0x60, 0x60,
+0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x61, 0x70, 0x3f, 0x03, 0x61,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+0x18, 0x3f, 0x3f, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x33,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x6d, 0x6d, 0x7f, 0x7f,
+0x73, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x73, 0x3f, 0x1e, 0x0c, 0x1e, 0x3f,
+0x73, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x01, 0x3f, 0x3e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7f, 0x7f, 0x03, 0x06, 0x0c, 0x18, 0x30,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x0c, 0x07, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 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, 0x00, 0x00, 0x00, 0x38, 0x0c,
+0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x0c, 0x38, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6d, 0x47,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+0x1c, 0x3e, 0x77, 0x77, 0xe3, 0xe3, 0xe3, 0xff,
+0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x0c, 0x26, 0x1c, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33, 0x1e,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x0c, 0x26, 0x1c, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x0c, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x1e, 0x33, 0x33, 0x1e, 0x0c, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x0c, 0x18, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x60, 0x7e, 0x7e, 0x60, 0x60, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x77, 0x7f, 0x0c, 0x7c, 0xff, 0xcc, 0xcc,
+0xff, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3f,
+0x6c, 0xcc, 0xcc, 0xcf, 0xcf, 0xfc, 0xfc, 0xcc,
+0xcf, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xc0,
+0xc0, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x01, 0x3f, 0x3e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x1e, 0x3f, 0x73, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1f,
+0x31, 0x31, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x31,
+0x7f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x33, 0x1e, 0x7f, 0x7f, 0x0c, 0x7f,
+0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x63, 0x7f, 0x7e, 0x61, 0x63,
+0x6f, 0x63, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+0x80, 0x00, 0x07, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc,
+0xcc, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x80, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3f, 0x46,
+0x00, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3f, 0x46, 0x00, 0x61, 0x71,
+0x71, 0x79, 0x79, 0x6d, 0x6d, 0x67, 0x67, 0x63,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03,
+0x3f, 0x63, 0x63, 0x3f, 0x00, 0x7f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3b,
+0x31, 0x31, 0x3b, 0x1f, 0x00, 0x3f, 0x3f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x1c,
+0x38, 0x70, 0x61, 0x73, 0x3f, 0x1e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x7f, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x7f, 0x03, 0x03, 0x03, 0x03,
+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, 0x18, 0x38, 0x18, 0x18,
+0x19, 0x1b, 0x07, 0x0e, 0x1c, 0x3b, 0x74, 0xe0,
+0xc0, 0x83, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x40, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x80, 0xc0, 0xc0, 0x80, 0x00, 0xc0, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x18,
+0x19, 0x1b, 0x07, 0x0e, 0x1c, 0x39, 0x73, 0xe5,
+0xcd, 0x8f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x40, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x0c,
+0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 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, 0x00, 0x00,
+0x00, 0x00, 0x19, 0x33, 0x66, 0x33, 0x19, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x66, 0x33, 0x19, 0x33, 0x66, 0x00,
+0x00, 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, 0x84, 0x42, 0x21, 0x10, 0x08, 0x84,
+0x42, 0x21, 0x10, 0x08, 0x84, 0x42, 0x21, 0x10,
+0x08, 0x84, 0x42, 0x21, 0x10, 0x08, 0x00, 0x00,
+0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x80, 0x40,
+0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
+0x80, 0x40, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x40, 0x80,
+0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80,
+0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80,
+0x40, 0x80, 0x7b, 0xf7, 0xef, 0xde, 0xbd, 0x7b,
+0xf7, 0xef, 0xde, 0xbd, 0x7b, 0xf7, 0xef, 0xde,
+0xbd, 0x7b, 0xf7, 0xef, 0xde, 0xbd, 0xc0, 0x80,
+0x40, 0xc0, 0xc0, 0xc0, 0x80, 0x40, 0xc0, 0xc0,
+0xc0, 0x80, 0x40, 0xc0, 0xc0, 0xc0, 0x80, 0x40,
+0xc0, 0xc0, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xfc, 0xfc, 0x0c, 0x0c, 0xfc, 0xfc, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xf3, 0xf3, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xfc, 0xfc, 0x0c, 0x0c, 0xfc, 0xfc, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x03, 0x03, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x03, 0x03, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x03, 0x03, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xfc, 0xfc, 0x0c, 0x0c, 0xfc, 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, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x70, 0x70, 0x7f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7f, 0x7f, 0x70, 0x70, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x70, 0x70, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x00, 0x00, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x7f, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xf3, 0xf3, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xfc, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0x3f, 0x77, 0x63, 0x63, 0x63, 0x77,
+0x3f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x63, 0x62, 0x66, 0x67, 0x63, 0x61, 0x61,
+0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x61, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
+0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x3f,
+0x18, 0x0c, 0x06, 0x03, 0x03, 0x06, 0x0c, 0x18,
+0x3f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xc0, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1f, 0x3f, 0x76, 0x63, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x7f, 0x6d, 0x40, 0x40, 0xc0, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x70, 0xf1, 0x19, 0x0b, 0x0e, 0x0e, 0x0c, 0x0c,
+0x0c, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f,
+0x0c, 0x3f, 0x7f, 0x61, 0x61, 0x7f, 0x3f, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x7f, 0x7f, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x61, 0x21, 0x33,
+0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3f, 0x70, 0x30, 0x18,
+0x0e, 0x3f, 0x73, 0x63, 0x63, 0x63, 0x63, 0x63,
+0x63, 0x76, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
+0x7b, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x77, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0,
+0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x03, 0x1f, 0x37, 0x67, 0x6d, 0x6d, 0x79, 0x7b,
+0x3e, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3f,
+0x70, 0x60, 0x60, 0x7f, 0x7f, 0x60, 0x60, 0x70,
+0x3f, 0x1f, 0x00, 0x00, 0x00, 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, 0x3f, 0x33,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x0c, 0x7f, 0x7f, 0x0c, 0x0c, 0x0c, 0x00,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+0x1c, 0x07, 0x01, 0x07, 0x1c, 0x70, 0x00, 0x7f,
+0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x0e, 0x38, 0x60, 0x38, 0x0e, 0x03, 0x00, 0x7f,
+0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc,
+0xcc, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x0c, 0x00, 0x7f, 0x7f, 0x00, 0x0c, 0x0c,
+0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf8, 0xcc,
+0xcf, 0xc7, 0x00, 0x00, 0x78, 0xf8, 0xcc, 0xcf,
+0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33,
+0x33, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 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, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03,
+0x03, 0x03, 0x63, 0x63, 0x73, 0x73, 0x1b, 0x0f,
+0x0f, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33,
+0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x13,
+0x03, 0x02, 0x0c, 0x1f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f,
+0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x35,
+0x31, 0x34, 0x6f, 0x65, 0x6d, 0x00, 0x00, 0x00,
+0xe8, 0x01, 0x34, 0x00, 0x56, 0x53, 0x5f, 0x56,
+0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49,
+0x4e, 0x46, 0x4f, 0x00, 0xbd, 0x04, 0xef, 0xfe,
+0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x03, 0x00,
+0x67, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x00,
+0x67, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7a, 0x01, 0x00, 0x00, 0x53, 0x74, 0x72, 0x69,
+0x6e, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e,
+0x66, 0x6f, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00,
+0x30, 0x34, 0x30, 0x39, 0x30, 0x34, 0x45, 0x34,
+0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x17, 0x00,
+0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e,
+0x61, 0x6d, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72,
+0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f,
+0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
+0x6e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x2b, 0x00,
+0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63,
+0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00,
+0x38, 0x35, 0x31, 0x34, 0x2f, 0x61, 0x20, 0x28,
+0x31, 0x30, 0x32, 0x34, 0x78, 0x37, 0x36, 0x38,
+0x29, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75,
+0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x65, 0x72,
+0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x6f,
+0x6e, 0x74, 0x00, 0x00, 0x16, 0x00, 0x06, 0x00,
+0x46, 0x69, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73,
+0x69, 0x6f, 0x6e, 0x00, 0x33, 0x2e, 0x31, 0x30,
+0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x09, 0x00,
+0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
+0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00,
+0x4f, 0x45, 0x4d, 0x46, 0x4f, 0x4e, 0x54, 0x53,
+0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x27, 0x00,
+0x4c, 0x65, 0x67, 0x61, 0x6c, 0x43, 0x6f, 0x70,
+0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
+0x74, 0x20, 0xa9, 0x20, 0x4d, 0x69, 0x63, 0x72,
+0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f,
+0x72, 0x70, 0x2e, 0x20, 0x31, 0x39, 0x39, 0x31,
+0x2d, 0x31, 0x39, 0x39, 0x32, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x0c, 0x00, 0x4f, 0x72, 0x69, 0x67,
+0x69, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65,
+0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00,
+0x38, 0x35, 0x31, 0x34, 0x4f, 0x45, 0x4d, 0x2e,
+0x46, 0x4f, 0x4e, 0x00, 0x39, 0x00, 0x29, 0x00,
+0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e,
+0x61, 0x6d, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72,
+0x6f, 0x73, 0x6f, 0x66, 0x74, 0xae, 0x20, 0x57,
+0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x28, 0x54,
+0x4d, 0x29, 0x20, 0x4f, 0x70, 0x65, 0x72, 0x61,
+0x74, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x79, 0x73,
+0x74, 0x65, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1a, 0x00, 0x06, 0x00, 0x50, 0x72, 0x6f, 0x64,
+0x75, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69,
+0x6f, 0x6e, 0x00, 0x00, 0x33, 0x2e, 0x31, 0x30,
+0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+0x56, 0x61, 0x72, 0x46, 0x69, 0x6c, 0x65, 0x49,
+0x6e, 0x66, 0x6f, 0x00, 0x14, 0x00, 0x04, 0x00,
+0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74,
+0x69, 0x6f, 0x6e, 0x00, 0x09, 0x04, 0xe4, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/private/ntos/nthals/halppc/ppc/bblrastz.h b/private/ntos/nthals/halppc/ppc/bblrastz.h
new file mode 100644
index 000000000..839b9ff56
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bblrastz.h
@@ -0,0 +1,113 @@
+
+#ifndef _H_BBLRASTZ
+#define _H_BBLRASTZ
+
+/******************************************************************************
+* *
+* Define the BBL rasterizer register address range: *
+* *
+******************************************************************************/
+
+#define BBL_REGISTER_ADDR_RANGE_START 0x0A000000
+
+
+/******************************************************************************
+* *
+* Define the BBL rasterizer register offsets: *
+* *
+******************************************************************************/
+
+#define BBL_CMD_DATA_REG 0x0000
+#define BBL_STATUS_REG 0x0000
+#define BBL_CNTL_REG 0x0040
+#define BBL_FG_REG 0x0044
+#define BBL_BG_REG 0x0048
+#define BBL_PLANE_MASK_REG 0x0050
+#define BBL_LINE_STYLE_DASH_1234_REG 0x0054
+#define BBL_LINE_STYLE_DASH_5678_REG 0x0058
+#define BBL_SCISSOR_ENABLE_REG 0x007C
+#define BBL_WIN_ORIGIN_OFFSETS_REG 0x0080
+#define BBL_WID_CLIP_TEST_REG 0x0084
+#define BBL_PIXEL_MASK_REG 0x00A0
+#define BBL_INTR_ENABLE_STATUS_REG 0x00B8
+#define BBL_CONFIG_REG 0x00BC
+#define BBL_RAMDAC_C0_C1_0_0_REG 0x00C0
+#define BBL_RAMDAC_C0_C1_0_1_REG 0x00C4
+#define BBL_RAMDAC_C0_C1_1_0_REG 0x00C8
+#define BBL_RAMDAC_C0_C1_1_1_REG 0x00CC
+#define BBL_RESET_CURRENT_CMD_REG 0x00D4
+
+
+/******************************************************************************
+* *
+* Define bitfields for the BBL rasterizer status register: *
+* *
+******************************************************************************/
+
+#define BBL_VERTICAL_RETRACE (1 << 0)
+#define BBL_ADAPTER_BUSY (1 << 2)
+#define BBL_CACHE_LINE_BUFFER_EMPTY (1 << 4)
+#define BBL_FREE_SPACE_SHIFT 16
+
+
+/******************************************************************************
+* *
+* Define the commands: *
+* *
+******************************************************************************/
+
+#define BBL_CMD_SHIFT 24
+#define BBL_POLYFILL_RECT_ID 0x86
+#define BBL_POLYFILL_RECT_CMD \
+ (int) (BBL_POLYFILL_RECT_ID << BBL_CMD_SHIFT)
+
+
+/******************************************************************************
+* *
+* Macro: BBL_FILL_RECT (regbase, dst_x, dst_y, width, height) *
+* caddr_t regbase; *
+* short dst_x, dst_y; *
+* unsigned short width, height; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* dst_x, dst_y - Screen coords of where to start the rect *
+* width, height - Dimensions of the rect *
+* *
+* Description: Performs a fill rectangle command to the adapter *
+* *
+******************************************************************************/
+
+#define BBL_FILL_RECT(regbase, dst_x, dst_y, width, height) \
+ BBL_SET_REG((regbase), BBL_CMD_DATA_REG, \
+ BBL_POLYFILL_RECT_CMD | 0x1); \
+ BBL_SET_REG((regbase), BBL_CMD_DATA_REG, \
+ (((unsigned short)(dst_x) << 16) | \
+ (unsigned short)(dst_y))); \
+ BBL_SET_REG((regbase), BBL_CMD_DATA_REG, \
+ (((unsigned short)(height) << 16) | \
+ (unsigned short)(width)))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_BUSY_POLL (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Performs a busy poll on the adapter and returns when the *
+* adapter is no longer busy. In the case of a shallow bus *
+* interface FIFO on the adapter, this macro will also make *
+* sure that the FIFO is empty and that the adapter is not *
+* busy. This is a synchronous call. *
+* *
+******************************************************************************/
+
+#define BBL_BUSY_POLL(regbase) \
+ while(BBL_GET_REG((regbase), BBL_STATUS_REG) & \
+ BBL_ADAPTER_BUSY) \
+ ;
+
+
+#endif /* ! _H_BBLRASTZ */
+
diff --git a/private/ntos/nthals/halppc/ppc/bblrmdac.h b/private/ntos/nthals/halppc/ppc/bblrmdac.h
new file mode 100644
index 000000000..b5f1176ff
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bblrmdac.h
@@ -0,0 +1,802 @@
+
+#ifndef _H_BBLRMDAC
+#define _H_BBLRMDAC
+
+/******************************************************************************
+* *
+* Define the ramdac register addresses: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_CONFIG_LOW_REG 0x0001
+#define BBL_RAMDAC_CONFIG_HIGH_REG 0x0002
+#define BBL_RAMDAC_RGB_FORMAT_REG 0x0003
+#define BBL_RAMDAC_MONITOR_ID_REG 0x0005
+#define BBL_RAMDAC_VRAM_MASK_REG 0x0006
+#define BBL_RAMDAC_WID_OL_MASK_REG 0x0007
+#define BBL_RAMDAC_PLL_REF_REG 0x0010
+#define BBL_RAMDAC_PLL_VCO_DIVIDER_REG 0x0011
+#define BBL_RAMDAC_CRT_CNTL_REG 0x0012
+#define BBL_RAMDAC_HORIZONTAL_TOTAL_LOW_REG 0x0013
+#define BBL_RAMDAC_HORIZONTAL_TOTAL_HIGH_REG 0x0014
+#define BBL_RAMDAC_HORIZONTAL_DISPLAY_END_LOW_REG 0x0015
+#define BBL_RAMDAC_HORIZONTAL_DISPLAY_END_HIGH_REG 0x0016
+#define BBL_RAMDAC_HSYNC_START_LOW_REG 0x0017
+#define BBL_RAMDAC_HSYNC_START_HIGH_REG 0x0018
+#define BBL_RAMDAC_HSYNC_END1_LOW_REG 0x0019
+#define BBL_RAMDAC_HSYNC_END1_HIGH_REG 0x001A
+#define BBL_RAMDAC_HSYNC_END2_LOW_REG 0x001B
+#define BBL_RAMDAC_HSYNC_END2_HIGH_REG 0x001C
+#define BBL_RAMDAC_VERTICAL_COUNT_LOW_REG 0x001D
+#define BBL_RAMDAC_VERTICAL_COUNT_HIGH_REG 0x001E
+#define BBL_RAMDAC_VERTICAL_DISPLAY_LOW_REG 0x001F
+#define BBL_RAMDAC_VERTICAL_DISPLAY_HIGH_REG 0x0020
+#define BBL_RAMDAC_VERTICAL_SYNC_START_LOW_REG 0x0021
+#define BBL_RAMDAC_VERTICAL_SYNC_START_HIGH_REG 0x0022
+#define BBL_RAMDAC_VERTICAL_SYNC_END_LOW_REG 0x0023
+#define BBL_RAMDAC_VERTICAL_SYNC_END_HIGH_REG 0x0024
+#define BBL_RAMDAC_ICON_CURSOR_CNTL_REG 0x0030
+#define BBL_RAMDAC_ICON_CURSOR_HOTSPOT_X_REG 0x0032
+#define BBL_RAMDAC_ICON_CURSOR_HOTSPOT_Y_REG 0x0033
+#define BBL_RAMDAC_CURSOR_X_POS_LOW_REG 0x0034
+#define BBL_RAMDAC_CURSOR_X_POS_HIGH_REG 0x0035
+#define BBL_RAMDAC_CURSOR_Y_POS_LOW_REG 0x0036
+#define BBL_RAMDAC_CURSOR_Y_POS_HIGH_REG 0x0037
+#define BBL_RAMDAC_CURSOR_BLINK_RATE_REG 0x0043
+#define BBL_RAMDAC_CURSOR_BLINK_DUTY_CYCLE_REG 0x0044
+#define BBL_RAMDAC_ICON_CURSOR_RAM_START_ADDR 0x0100
+#define BBL_RAMDAC_ICON_CURSOR_RAM_END_ADDR 0x04FF
+#define BBL_RAMDAC_WAT_START_ADDR 0x0500
+#define BBL_RAMDAC_WAT_END_ADDR 0x051F
+#define BBL_RAMDAC_FB_LUT_START_ADDR 0x0600
+#define BBL_RAMDAC_FB_LUT_END_ADDR 0x09FF
+#define BBL_RAMDAC_FB_LUT_0_START_ADDR 0x0600
+#define BBL_RAMDAC_FB_LUT_0_END_ADDR 0x06FF
+#define BBL_RAMDAC_CURSOR_LUT_0_START_ADDR 0x0A10
+#define BBL_RAMDAC_CURSOR_LUT_0_END_ADDR 0x0A12
+
+
+/******************************************************************************
+* *
+* Define the frame buffer look up tables and length: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_FB_LUT_0 0
+#define BBL_RAMDAC_FB_LUT_LENGTH 256
+
+
+/******************************************************************************
+* *
+* Define the cursor colormaps lengths: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_CURSOR_LUT_0 0
+#define BBL_RAMDAC_CURSOR_LUT_LENGTH 4
+
+
+/******************************************************************************
+* *
+* Define the cursor pixmap dimensions: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_CURSOR_RAM_LENGTH 1024
+#define BBL_RAMDAC_ICON_CURSOR_WIDTH 64
+#define BBL_RAMDAC_ICON_CURSOR_HEIGHT 64
+#define BBL_RAMDAC_ICON_CURSOR_DEPTH 2
+
+
+/******************************************************************************
+* *
+* Define the icon cursor control register bitfields: *
+* *
+******************************************************************************/
+
+#define BBL_DISABLE_ICON_CURSOR_DISPLAY (0 << 0)
+#define BBL_ENABLE_ICON_CURSOR_DISPLAY (1 << 0)
+#define BBL_DISABLE_ICON_CURSOR_BLINK (0 << 1)
+#define BBL_ENABLE_ICON_CURSOR_BLINK (1 << 1)
+
+
+/******************************************************************************
+* *
+* Define the monitor ID register bitfields: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_MONITOR_ID_CABLE_ID_MASK 0x0F
+#define BBL_RAMDAC_MONITOR_ID_DIP_SWITCH_MASK 0xF0
+
+
+/******************************************************************************
+* *
+* Define the pixel mask bitfields: *
+* *
+******************************************************************************/
+
+#define BBL_DEFAULT_VRAM_PIXEL_MASK_VALUE 0xFF
+#define BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE 0x0F
+
+
+/******************************************************************************
+* *
+* Define the WAT table entry information and length: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_WAT_LENGTH 16
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_ADDRESS_REGS (regbase, address) *
+* caddr_t regbase; *
+* unsigned short address; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* address - RAMDAC address *
+* *
+* Description: Sets the address pointer in the RAMDAC to point *
+* to the "address" parameter. This is used to read and write *
+* RAMDAC registers, look up tables, and any other *
+* memory area on the RAMDAC chip. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_ADDRESS_REGS(regbase, address) \
+ BBL_EIEIO; \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_0_0_REG, \
+ (((volatile unsigned long)(address) & 0x000000FF) << 24)); \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_1_0_REG, \
+ (((volatile unsigned long)(address) & 0x0000FF00) << 16)); \
+ BBL_EIEIO
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_DATA_NON_LUT (regbase, data) *
+* caddr_t regbase; *
+* unsigned char data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - Data to be written to the RAMDAC *
+* *
+* Description: Writes data to a RAMDAC register. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_DATA_NON_LUT(regbase, data) \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_0_1_REG, \
+ (((volatile unsigned long)(data) & 0xFF) << 24))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_RAMDAC_DATA_NON_LUT (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Reads register data from the RAMDAC. *
+* *
+* Returns: This is RHS macro which expands to the data read from *
+* the RAMDAC *
+* *
+******************************************************************************/
+
+#define BBL_GET_RAMDAC_DATA_NON_LUT(regbase) \
+ (unsigned char) \
+ (BBL_GET_REG ((regbase), BBL_RAMDAC_C0_C1_0_1_REG))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_DATA_LUT (regbase, data) *
+* caddr_t regbase; *
+* unsigned char data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - Data to be written to the RAMDAC *
+* *
+* Description: Writes data to a RAMDAC lookup table. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_DATA_LUT(regbase, data) \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_1_1_REG, \
+ (((volatile unsigned long)(data) & 0x000000FF) << 24))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_RAMDAC_DATA_LUT (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Reads lookup table data from the RAMDAC. *
+* *
+* Returns: This is a RHS macro which expands to the data read from the *
+* RAMDAC *
+* *
+******************************************************************************/
+
+#define BBL_GET_RAMDAC_DATA_LUT(regbase) \
+ (unsigned char) \
+ (BBL_GET_REG ((regbase), BBL_RAMDAC_C0_C1_1_1_REG))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_16BIT_RAMDAC_REG (regbase, data) *
+* caddr_t regbase; *
+* unsigned short data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - 16 bit value to write to a 16bit RAMDAC register *
+* *
+* Description: Writes two consecutive 8bit (high/low) RAMDAC registers with *
+* the 16bit data value passed in. *
+* *
+******************************************************************************/
+
+#define BBL_SET_16BIT_RAMDAC_REG(regbase, data) \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), ((data) & 0x00FF)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (((data) & 0xFF00) >> 8))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_PLL_REF_REG (regbase, frequency) *
+* caddr_t regbase; *
+* unsigned short frequency; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* frequency - RAMDAC oscillator is running at *
+* *
+* Description: Writes the frequency value to the RAMDAC PLL reference *
+* register. First the frequency value has to be modified to *
+* match what the hardware expects. This is a simple division *
+* by 2, therefore the frequency value passed in should be a *
+* multiple of 2. *
+* *
+******************************************************************************/
+
+#define BBL_SET_PLL_REF_REG(regbase, frequency) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_PLL_REF_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ ((frequency >> 1) & 0x1F))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_PLL_VCO_DIVIDER_REG (regbase, frequency) *
+* caddr_t regbase; *
+* unsigned short frequency; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* frequency - Drives the pixel clock and VRAM speed *
+* (THIS VALUE IS MULTIPLIED BY 100 !!!) *
+* *
+* Description: Writes the frequency value to the RAMDAC PLL VCO Divider *
+* register. First the frequency value has to be modified to *
+* match what the hardware expects. The register is an 8 bit *
+* register where the upper 2 bits determine the frequency *
+* range and the lower 6 bits indicate a frequency in that *
+* range. The following table illustrates this: *
+* *
+* 7 6 5 4 3 2 1 0 *
+* +---+---+---+---+---+---+---+---+ *
+* | DF | VIDEO COUNT VALUE | *
+* +---+---+---+---+---+---+---+---+ *
+* | 0 | 0 | (4 x VF) - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* | 0 | 1 | (2 x VF) - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* | 1 | 0 | VF - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* | 1 | 1 | (VF / 2) - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* *
+* Where: *
+* *
+* 7-6 DF = Desired Frequency Range *
+* = 0 0 16.25 MHZ - 32.0 MHZ in 0.25 MHZ steps *
+* = 0 1 32.5 MHZ - 64.0 MHZ in 0.5 MHZ steps *
+* = 1 0 65.0 MHZ - 128.0 MHZ in 1.0 MHZ steps *
+* = 1 1 130.0 MHZ - 200.0 MHZ in 2.0 MHZ steps *
+* *
+* Notes: The frequency parameter passed in must be multiplied by 100 *
+* before calling this macro! This eliminates the use of any *
+* floating point. *
+* *
+******************************************************************************/
+
+#define BBL_SET_PLL_VCO_DIVIDER_REG(regbase, frequency) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_PLL_VCO_DIVIDER_REG); \
+ if((frequency) > 12800){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0xC0 | (((frequency) - 13000) / 200))); \
+ }else if((frequency) > 6400){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0x80 | (((frequency) - 6500) / 100))); \
+ }else if((frequency) > 3200){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0x40 | (((frequency) - 3250) / 50))); \
+ }else{ /* frequency <= 3200 */ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0x00 | (((frequency) - 1625) / 25))); \
+ }
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_CRT_CNTL_REG (regbase, control_bits) *
+* caddr_t regbase; *
+* unsigned char control_bits; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* control_bits - Data to write to the 8bit RAMDAC CRT control *
+* register *
+* *
+* Description: Writes the control_bits value into the RAMDAC *
+* CRT control register. *
+* *
+******************************************************************************/
+
+#define BBL_SET_CRT_CNTL_REG(regbase, control_bits) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_CRT_CNTL_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (control_bits))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_TOTAL_REG (regbase, num_pixels) *
+* caddr_t regbase; *
+* unsigned short num_pixels; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* num_pixels - The number of pixels for the HORIZONTAL TOTAL *
+* register. This value must be a multiple of 4 and *
+* range from 0-2044. *
+* *
+* Description: Writes the num_pixels value into the RAMDAC high/low *
+* HORIZONTAL TOTAL registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_TOTAL_REG(regbase, num_pixels) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HORIZONTAL_TOTAL_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((num_pixels) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_DISPLAY_END_REG (regbase, num_pixels) *
+* caddr_t regbase; *
+* unsigned short num_pixels; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* num_pixels - The number of pixels for the HORIZONTAL DISPLAY *
+* END register. This value must be a multiple of 4 *
+* and range from 0 - 2044. *
+* *
+* Description: Writes the num_pixels value into the RAMDAC high/low *
+* HORIZONTAL DISPLAY END registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_DISPLAY_END_REG(regbase, num_pixels) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HORIZONTAL_DISPLAY_END_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((num_pixels) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_SYNC_START_REG (regbase, *
+* pixel_position) *
+* caddr_t regbase; *
+* unsigned short pixel_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* pixel_position - Pixel position for the start of horizontal *
+* retrace. This value has to be a multiple of *
+* of 4 and range from 0 - 2044 *
+* *
+* Description: Writes the pixel_position value into the RAMDAC *
+* high/low HORIZONTAL SYNC START registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_SYNC_START_REG(regbase, pixel_position) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HSYNC_START_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((pixel_position) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_SYNC_END1_REG (regbase, pixel_position) *
+* caddr_t regbase; *
+* unsigned short pixel_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* pixel_position - Pixel position for the end of horizontal *
+* retrace. This value has to be a multiple of *
+* of 4 and range from 0 - 2044 *
+* *
+* Description: Writes the pixel_position value into the RAMDAC *
+* high/low HORIZONTAL SYNC END1 registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_SYNC_END1_REG(regbase, pixel_position) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HSYNC_END1_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((pixel_position) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_SYNC_END2_REG (regbase, pixel_position) *
+* caddr_t regbase; *
+* unsigned short pixel_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* pixel_position - Pixel position for the end of horizontal *
+* retrace. This value has to be a multiple of *
+* of 4 and range from 0 - 2044 *
+* *
+* Description: Writes the pixel_position value into the RAMDAC *
+* high/low HORIZONTAL SYNC END2 registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_SYNC_END2_REG(regbase, pixel_position) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HSYNC_END2_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((pixel_position) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_TOTAL_REG (regbase, num_scan_lines) *
+* caddr_t regbase; *
+* unsigned short num_scan_lines; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* num_scan_lines - Number of scan lines per frame. This value *
+* has to range from 0 - 2047. *
+* *
+* Description: Writes the num_scan_lines value into the RAMDAC *
+* high/low VERTICAL TOTAL registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_TOTAL_REG(regbase, num_scan_lines) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_COUNT_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((num_scan_lines) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_DISPLAY_END_REG (regbase, scan_line) *
+* caddr_t regbase; *
+* unsigned short scan_line; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* scan_line - Last visible scan line. This value has to range *
+* from 0 - 2047. *
+* *
+* Description: Writes the scan_line value into the RAMDAC *
+* high/low VERTICAL DISPLAY END registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_DISPLAY_END_REG(regbase, scan_line) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_DISPLAY_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((scan_line) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_SYNC_START_REG (regbase, scan_line) *
+* caddr_t regbase; *
+* unsigned short scan_line; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* scan_line - Indicates which scan line the vertical sync pulse *
+* begins. This value has to range from 0 - 2047. *
+* *
+* Description: Writes the scan_line value into the RAMDAC *
+* high/low VERTICAL SYNC START registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_SYNC_START_REG(regbase, scan_line) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_SYNC_START_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((scan_line) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_SYNC_END_REG (regbase, scan_line) *
+* caddr_t regbase; *
+* unsigned short scan_line; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* scan_line - Indicates which scan line the vertical sync pulse *
+* ends. This value has to range from 0 - 2047. *
+* *
+* Description: Writes the scan_line value into the RAMDAC *
+* high/low VERTICAL SYNC END registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_SYNC_END_REG(regbase, scan_line) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_SYNC_END_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((scan_line) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_ICON_CURSOR_CNTL (regbase, control_bits) *
+* caddr_t regbase; *
+* unsigned char control_bits; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* control_bits - Control bits to write to the icon cursor *
+* control register *
+* *
+* Description: Writes the control_bits to the RAMDAC icon cursor control *
+* register *
+* *
+* Notes: None. *
+* *
+******************************************************************************/
+
+#define BBL_SET_ICON_CURSOR_CNTL(regbase, control_bits) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_ICON_CURSOR_CNTL_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (control_bits))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_ICON_CURSOR_PIXMAP (regbase, width, height, data) *
+* caddr_t regbase; *
+* unsigned short width, height; *
+* unsigned char *data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - Pointer to the cursor pixmap in memory *
+* *
+* Description: This macro will load the icon cursor pixmap. *
+* *
+* Notes: The format of the data is as follows: *
+* *
+* +--+--+--+--+--+--+--+--+ *
+* | p0 | p1 | p2 | p3 | *
+* +--+--+--+--+--+--+--+--+ *
+* *
+* The data area must be byte aligned for the pixel data *
+* *
+******************************************************************************/
+
+#define BBL_SET_ICON_CURSOR_PIXMAP(regbase, width, height, data) \
+{ \
+ unsigned short _bbl_row, _bbl_col; \
+ unsigned char *_bbl_ptr; \
+ \
+ /* Set the RAMDAC address up for the icon cursor pixmap area */ \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_ICON_CURSOR_RAM_START_ADDR); \
+ \
+ /* Loop through the rows */ \
+ for(_bbl_row=0, _bbl_ptr=(unsigned char *)(data); \
+ _bbl_row < (height); _bbl_row++){ \
+ \
+ /* Loop through the columns 4 at a time */ \
+ for(_bbl_col=0; _bbl_col < ((width) >> 2); _bbl_col++){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ (*_bbl_ptr)); \
+ _bbl_ptr++; \
+ } \
+ /* If the width < 64 pixels, send the 0x00 pixel */ \
+ /* values until width == 64 pixels */ \
+ if(_bbl_col < (BBL_RAMDAC_ICON_CURSOR_WIDTH >> 2)){ \
+ for(;_bbl_col < (BBL_RAMDAC_ICON_CURSOR_WIDTH >> 2); \
+ _bbl_col++){ \
+ \
+ BBL_SET_RAMDAC_DATA_NON_LUT \
+ ((regbase), 0x00); \
+ } \
+ } \
+ } \
+ \
+ for(; _bbl_row < BBL_RAMDAC_ICON_CURSOR_HEIGHT; _bbl_row++){ \
+ for(_bbl_col=0; \
+ _bbl_col < (BBL_RAMDAC_ICON_CURSOR_WIDTH >> 2); \
+ _bbl_col++){ \
+ \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), 0x00); \
+ } \
+ } \
+}
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_CURSOR_POSITION (regbase, x_position, y_position) *
+* caddr_t regbase; *
+* unsigned short x_position, y_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* x_position - Gives the x position of where to put the *
+* icon cursor on the screen *
+* y_position - Gives the y position of where to put the *
+* icon cursor on the screen *
+* *
+* Description: This macro will place the current cursor *
+* at the new screen location specified by the position *
+* parameter. *
+* *
+* Notes: None. *
+* *
+******************************************************************************/
+
+#define BBL_SET_CURSOR_POSITION(regbase, x_position, y_position) \
+ /* Set the RAMDAC address register to point to the first of */ \
+ /* four cursor position registers */ \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_CURSOR_X_POS_LOW_REG); \
+ \
+ /* Write the current cursor position out to the RAMDAC */ \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ ((x_position) & 0x00FF)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ (((x_position) & 0xFF00) >> 8)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ ((y_position) & 0x00FF)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ (((y_position) & 0xFF00) >> 8))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_FB_PIXEL_MASK_REG (regbase, vram_mask) *
+* caddr_t regbase; *
+* unsigned char vram_mask; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* vram_mask - Mask to apply. This is used by the RAMDAC to *
+* mask out unwanted data to the screen *
+* *
+* Description: Sets the RAMDAC frame buffer pixel mask register. This *
+* should only be set during initialization time. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_FB_PIXEL_MASK_REG(regbase, vram_mask) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_VRAM_MASK_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (vram_mask))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_WID_OL_PIXEL_MASK_REG (regbase, vram_mask) *
+* caddr_t regbase; *
+* unsigned char vram_mask; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* vram_mask - Mask to apply. This is used by the RAMDAC to *
+* mask out unwanted data to the screen *
+* *
+* Description: Sets the RAMDAC WID planes and overlay planes pixel mask *
+* register. This should only be set during initialization time. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_WID_OL_PIXEL_MASK_REG(regbase, vram_mask) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_WID_OL_MASK_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (vram_mask))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_MONITOR_ID (regbase, monitor_ID) *
+* caddr_t regbase; *
+* unsigned char monitor_ID; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* monitor_ID - Is the 8bit monitor ID read from the RAMDAC *
+* *
+* Description: Reads the monitor ID register from the RAMDAC. This register *
+* is composed of 4 bits from the cable ID and 4 bits from the *
+* on-card DIP switches. *
+* *
+* Returns: monitor_ID will contain the monitor ID from the RAMDAC *
+* *
+******************************************************************************/
+
+#define BBL_GET_MONITOR_ID(regbase, monitor_ID) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_MONITOR_ID_REG); \
+ (monitor_ID) = ((unsigned char) \
+ (BBL_GET_RAMDAC_DATA_NON_LUT(regbase)))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_LOAD_FB_COLOR_PALETTE (regbase, first_entry, *
+* num_entries, color_values) *
+* caddr_t regbase; *
+* unsigned long first_entry, num_entries; *
+* unsigned char *color_values; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* first_entry - First entry in color palette to update. This *
+* value must range from 0 - 255. To load the *
+* entire color palette, this should be set to 0. *
+* num_entries - Number of entries in color palette to update. *
+* This value must range from 1 - 256. To load the *
+* entire color palette, this should be set to 256 *
+* color_values - Pointer to an array of color value which are *
+* to be loaded into the color palette. The color *
+* values are unsigned chars. *
+* *
+* Description: This macro will load the Frame Buffer color palette with the *
+* colors specified *
+* *
+******************************************************************************/
+
+#define BBL_LOAD_FB_COLOR_PALETTE(regbase, first_entry, \
+ num_entries, color_values) \
+{ \
+ short _bbl_index; \
+ unsigned char *_bbl_colors; \
+ \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_FB_LUT_0_START_ADDR + (first_entry)); \
+ \
+ for(_bbl_index=(first_entry), \
+ _bbl_colors=(unsigned char *)(color_values); \
+ _bbl_index<((first_entry)+(num_entries)); \
+ _bbl_index++){ \
+ \
+ BBL_SET_RAMDAC_DATA_LUT ((regbase), (*_bbl_colors)); \
+ _bbl_colors++; \
+ BBL_SET_RAMDAC_DATA_LUT ((regbase), (*_bbl_colors)); \
+ _bbl_colors++; \
+ BBL_SET_RAMDAC_DATA_LUT ((regbase), (*_bbl_colors)); \
+ _bbl_colors++; \
+ \
+ } \
+}
+
+
+#endif /* _H_BBLRMDAC */
+
+
diff --git a/private/ntos/nthals/halppc/ppc/bldef.h b/private/ntos/nthals/halppc/ppc/bldef.h
new file mode 100644
index 000000000..dbd315f6b
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bldef.h
@@ -0,0 +1,144 @@
+
+#ifndef _H_BLDEF
+#define _H_BLDEF
+
+#include "halp.h"
+
+//#include <ntos.h>
+
+//
+// Used for debugging
+//
+
+#if defined(BL_DBG) && DBG
+#define BL_DBG_PRINT DbgPrint
+#else
+#define BL_DBG_PRINT
+#endif // !DBG
+
+//
+// Define the physical memory attribites
+//
+
+#define BL_SCANLINE_LENGTH 0x1000 // 4K
+
+
+//
+// Define the register base
+//
+
+#define BL_REG_BASE (HalpBLRegisterBase)
+
+// GXT250P/GXT255P configuration register offsets
+#define BL_PCI_ID 0x00
+#define BL_PCI_CMD 0x04
+#define BL_PCI_REV_ID 0x08
+#define BL_PCI_CONFIG_0C 0x0C
+#define BL_PCI_REG_ADDR 0x10
+#define BL_PCI_FB_ADDR 0x14
+#define BL_PCI_ROM_ADDR 0x30
+#define BL_PCI_CONFIG_3C 0x3C
+#define BL_PCI_FUNC_ENABLE 0x40
+#define BL_PCI_EXT_FUNC_ENABLE 0x44
+#define BL_PCI_CONFIG_STRAP 0x48
+
+// GXT250P/GXT255P configuration register values
+// Device Vendor ID (0x00)
+#define BL_SKY_VEN_ID 0x00001014
+#define BL_SKY_DEV_ID 0x003c
+#define BL_SKY_DEV_VEN_ID ((BL_SKY_DEV_ID << 16) | (BL_SKY_VEN_ID))
+// Command register (0x04)
+#define BL_PCI_CMD_VALUE 0x00000206
+#define BL_PCI_MEM_ENABLE BL_PCI_CMD_VALUE
+// 0x0C register value
+#define BL_CONFIG_REG_0C_VALUE 0x0000f808
+// 0x3C register value
+#define BL_CONFIG_REG_3C_VALUE 0x00000100
+// Function enables register (0x40)
+//#define BL_FUNC_VALUE 0x00001a5f
+//#define BL_FUNC_VALUE 0x00001a5C
+#define BL_FUNC_VALUE 0x00001a7C
+// Define PRISM revision levels and mask for the strapping register
+#define BL_STRAP_CHIP_REV_MASK 0xf0000000
+#define BL_STRAP_CHIP_DD2 0x10000000
+#define BL_STRAP_CHIP_DD3 0x20000000
+// Extended function enables register (0x44)
+#define BL_EXT_FUNC_VALUE_DD3 0x00000003
+#define BL_EXT_FUNC_VALUE_DD2 0x00000002
+// Offset to registers from base reg virtual address
+#define BL_REG_OFFSET 0x00004000 // Second aperture
+//#define BL_REG_OFFSET 0x00000000 // First aperture
+// Size of the two memory map spaces
+#define BL_REG_MAP_SIZE 0x00008000 // 32k total
+#define BL_FB_MAP_SIZE 0x01000000 // 16meg total
+// PRISM revision ID mask (for use with the strapping register 0x48)
+#define BL_PRISM_REV_MASK 0xf0000000
+
+// Define PRISM level specific register information for PRISM critical
+// register set
+#define MAX_CFG_PER_ADAPTER 3
+// Ramdac reset constants
+#define AR07 0x03 // VGA control
+#define AR08 0x06 // DAC control
+#define AR15 0x00 // diagnostics
+#define AR16 0x00 // MISR control reg
+// PRISM clock speed settings (aux pll on ramdac)
+// The following constants set PRISM's clock to 50.11Mhz
+#define AR25 1 // aux pll ref div
+#define AR26 13 // aux pll multiplier
+#define AR27 2 // aux pll output div
+#define AR28 5 // aux pll control
+// Control high register settings
+//#define AR00 0x08000045 // sce=8bpp
+#define AR00 0x08010044 // sce=1bpp
+// Control low registers settings
+// Previous settings: C114, C117. Set byte and half word swap bits to
+// disable (little endian format)
+//#define AR01 0x013f0000
+#define AR01 0x01170000
+// Misc PRISM register settings
+#define AR03 0x00ffffff
+#define AR04 0x00000000
+#define AR05 0x00000000
+// Misc ramdac register setting/
+#define AR10 0x00 // cursor control
+#define AR11 0x00 // crosshair control1
+#define AR17 0x03 // wat 0, byte 0
+#define AR18 0x00 // wat 0, byte 1
+#define AR19 0x00 // wat 0, byte 2
+#define AR20 0x00 // wat 0, byte 3
+#define AR21 0x04 // overlay wat 0, byte 0
+#define AR22 0x00 // overlay wat 0, byte 1
+#define AR23 0x00 // overlay wat 0, byte 2
+#define AR24 0x00 // overlay wat 0, byte 3
+// V-sync/H-sync settle time (2ms)
+#define BL_VSHS_SETTLE 2000
+
+//
+// Define the monitor ID (cable and DIP switch) masks
+//
+
+#define BL_MON_ID_DIP_SWITCHES_SHIFT 16
+#define BL_MON_ID_DIP_SWITCHES_MASK \
+ (0xF << BL_MON_ID_DIP_SWITCHES_SHIFT)
+
+#define BL_MON_ID_CABLE_ID_0 0x0
+#define BL_MON_ID_CABLE_ID_H 0x1
+#define BL_MON_ID_CABLE_ID_V 0x2
+#define BL_MON_ID_CABLE_ID_1 0x3
+
+#define BL_MON_ID_CABLE_BIT_0_SHIFT 6
+#define BL_MON_ID_CABLE_BIT_0_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_0_SHIFT)
+#define BL_MON_ID_CABLE_BIT_1_SHIFT 4
+#define BL_MON_ID_CABLE_BIT_1_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_1_SHIFT)
+#define BL_MON_ID_CABLE_BIT_2_SHIFT 2
+#define BL_MON_ID_CABLE_BIT_2_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_2_SHIFT)
+#define BL_MON_ID_CABLE_BIT_3_SHIFT 0
+#define BL_MON_ID_CABLE_BIT_3_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_3_SHIFT)
+
+#endif // _H_BLDEF
+
diff --git a/private/ntos/nthals/halppc/ppc/blfw.h b/private/ntos/nthals/halppc/ppc/blfw.h
new file mode 100644
index 000000000..65d4c1230
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/blfw.h
@@ -0,0 +1,121 @@
+
+#ifndef _H_BLFW
+#define _H_BLFW
+
+extern VOID Eieio ( VOID );
+
+#define BL_EIEIO __builtin_eieio()
+#define HIGH(a) (UCHAR)(((a)>>8) & 0xff)
+#define LOW(a) (UCHAR)((a) & 0xff)
+
+/******************************************************************************
+* *
+* The following identifies the monitor structures and definitions *
+* *
+******************************************************************************/
+
+//
+// Operating modes (8bit only for ARC and HAL)
+//
+typedef enum _BL_MODES
+{
+ m640_480_8_60, // Not used
+ m800_600_8_60, // Default for 1010 ID (SS)
+ m1024_768_8_60, // Not used
+ m1024_768_8_70, // Default for H010 ID (SS)
+ m1280_1024_8_60, // Default for 0100 ID (SOG)
+ m1280_1024_8_67, // Default for 0111 ID (SS)
+ m1280_1024_8_72 // Default for V111 ID (SOG)
+} BL_MODES;
+
+#define BL_NUM_CRT_CTRL_REC_STRUCTS 7
+
+//
+// Monitor ID (cable) values
+//
+#define BL_MT_04 0x04 // 0100
+#define BL_MT_07 0x07 // 0111
+#define BL_MT_0A 0x0A // 1010
+#define BL_MT_0F 0x0F // 1111
+#define BL_MT_1A 0x1A // H010
+#define BL_MT_17 0x17 // V111
+#define BL_MT_MASK 0x1F // Monitor ID mask
+
+// CRT information structure
+typedef struct _bl_crt_ctrl_rec_t {
+ ULONG mode; // Mode for this crt ctrl rec
+ USHORT MonID; // Monitor ID
+ USHORT width; // Number of pixels along the X axis
+ USHORT height; // Number of pixels along the Y axis
+ ULONG refresh; // Refresh rate
+ UCHAR pll_ref_divide; // RAMDAC video PLL ref divide
+ UCHAR pll_mult; // RAMDAC video PLL multiplier
+ UCHAR pll_output_divide; // RAMDAC video PLL output divide
+ UCHAR pll_ctrl; // RAMDAC video PLL control
+ UCHAR sync_ctrl; // RAMDAC sync control
+ ULONG crt_cntl_reg; // PRISM DTG control reg
+ ULONG hrz_total_reg; // PRISM he reg (pixels)
+ ULONG hrz_dsp_end_reg; // PRISM hde reg (pixels)
+ ULONG hsync_start_reg; // PRISM hss reg (pixels)
+ ULONG hsync_end1_reg; // PRISM hse1 reg (pixels)
+ ULONG hsync_end2_reg; // PRISM hse2 reg (pixels)
+ ULONG vrt_total_reg; // PRISM ve reg (scan lines)
+ ULONG vrt_dsp_end_reg; // PRISM vde reg (scan lines)
+ ULONG vsync_start_reg; // PRISM vss reg (scan lines)
+ ULONG vsync_end_reg; // PRISM vse reg (scan lines)
+} bl_crt_ctrl_rec_t;
+
+// Adapter control record structure
+typedef struct _bl_adapter_ctrl_rec_t {
+ USHORT vram; // Amount of VRAM for frame buffer
+ USHORT width; // Number of pixels along the X axis
+ USHORT height; // Number of pixels along the Y axis
+ // PRISM registers
+ ULONG PRISM_cfg; // cfg reg
+ ULONG mem_cfg; // memory cfg reg
+ ULONG DTG_ctrl; // DTG control reg
+ // RAMDAC registers
+ UCHAR pix_ctrl0; // 07:00 pix ctrl
+ UCHAR pix_ctrl1; // 15:08 pix ctrl
+ UCHAR pix_ctrl2; // 23:16 pix ctrl
+ UCHAR pix_ctrl3; // 31:24 pix ctrl
+ UCHAR wid_ctrl0; // 3:0 WID ctrl
+ UCHAR wid_ctrl1; // 7:4 WID ctrl
+ UCHAR serial_mode_ctrl; // serial mode
+ UCHAR pix_interleave; // pixel interleave
+ UCHAR misc_cfg; // misc ctrl
+ UCHAR vram_mask_0; // vram mask reg 0
+ UCHAR vram_mask_1; // vram mask reg 1
+ UCHAR vram_mask_2; // vram mask reg 2
+} bl_adapter_ctrl_rec_t;
+
+// Adapter model record structure
+typedef struct bl_adapter_model_rec_t {
+ ULONG devvend_id; // PCI device id
+ ULONG strapping; // configuration strapping
+ UCHAR prism_rev; // prism chip revision ID
+ UCHAR num_adp_ctrl_recs; // number of adp_ctrl_rec's in array
+ bl_adapter_ctrl_rec_t *adp_ctrl_rec; // pointer to adapter ctrl rec array
+} bl_adapter_model_rec_t;
+
+// Config flag defines
+// System sourced/color reg. pixel depth for DFA apeture 1 and commands
+#define BL_ENABLE_SOURCE_1_BPP (1L << 0)
+#define BL_ENABLE_SOURCE_8_BPP (1L << 1)
+#define BL_ENABLE_SOURCE_16_BPP (1L << 2)
+#define BL_ENABLE_SOURCE_24_BPP (1L << 3)
+// frame buffer pixel depth from DFA apeture 1 and commands
+#define BL_ENABLE_8_BPP (1L << 3)
+#define BL_ENABLE_16_BPP (1L << 4)
+#define BL_ENABLE_24_BPP (1L << 5)
+#define BL_ENABLE_OVERLAY (1L << 0)
+#define BL_ENABLE_DOUBLE_BUFFER (1L << 1)
+#define BL_OVERLAY_AVAILABLE (1L << 0)
+#define BL_8_BPP_DB_AVAILABLE (1L << 1)
+#define BL_16_BPP_DB_AVAILABLE (1L << 2)
+#define BL_8_BPP_AVAILABLE (1L << 3)
+#define BL_16_BPP_AVAILABLE (1L << 4)
+#define BL_24_BPP_AVAILABLE (1L << 5)
+
+#endif // _H_BLFW
+
diff --git a/private/ntos/nthals/halppc/ppc/blrastz.h b/private/ntos/nthals/halppc/ppc/blrastz.h
new file mode 100644
index 000000000..5aa0330ee
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/blrastz.h
@@ -0,0 +1,348 @@
+
+#ifndef _H_BLRASTZ
+#define _H_BLRASTZ
+
+/******************************************************************************
+* *
+* PRSM Register and Port Address *
+* *
+******************************************************************************/
+
+#define BL_PRSM_STATUS_REG 0x0000
+#define BL_PRSM_CMD_REG 0x0000
+#define BL_PRSM_CNTL_HIGH_REG 0x1000
+#define BL_PRSM_CNTL_LOW_REG 0x1004
+#define BL_PRSM_FG_COL_REG 0x1008
+#define BL_PRSM_BG_COL_REG 0x100C
+#define BL_PRSM_PIX_MASK_REG 0x1010
+#define BL_PRSM_LINE_STYLE_PAT_1_REG 0x1014
+#define BL_PRSM_LINE_STYLE_PAT_2_REG 0x1018
+#define BL_PRSM_LINE_STYLE_CUR_CNT_REG 0x101C
+#define BL_PRSM_PLANE_WR_MASK_REG 0x1020
+#define BL_PRSM_CL_TEST_REG 0x1024
+#define BL_PRSM_PIX_PROC_REG 0x1028
+#define BL_PRSM_COL_COMP_REG 0x102C
+#define BL_PRSM_HL_COL_REG 0x1030
+#define BL_PRSM_WIN_ORG_OFF_REG 0x1034
+#define BL_PRSM_SC_ENABLE_REG 0x1038
+#define BL_PRSM_SC_0_MIN_REG 0x103C
+#define BL_PRSM_SC_0_MAX_REG 0x1040
+#define BL_PRSM_SC_1_MIN_REG 0x1044
+#define BL_PRSM_SC_1_MAX_REG 0x1048
+#define BL_PRSM_SC_2_MIN_REG 0x104C
+#define BL_PRSM_SC_2_MAX_REG 0x1050
+#define BL_PRSM_SC_3_MIN_REG 0x1054
+#define BL_PRSM_SC_3_MAX_REG 0x1058
+#define BL_PRSM_STP_OFF_REG 0x105C
+#define BL_PRSM_STP_CACH_DATA_0_REG 0x1060
+#define BL_PRSM_STP_CACH_DATA_1_REG 0x1064
+#define BL_PRSM_STP_CACH_DATA_2_REG 0x1068
+#define BL_PRSM_STP_CACH_DATA_3_REG 0x106C
+#define BL_PRSM_STP_CACH_DATA_4_REG 0x1070
+#define BL_PRSM_STP_CACH_DATA_5_REG 0x1074
+#define BL_PRSM_STP_CACH_DATA_6_REG 0x1078
+#define BL_PRSM_STP_CACH_DATA_7_REG 0x107C
+#define BL_PRSM_CACH_POLL_MASK_REG 0x1080
+#define BL_PRSM_CACH_POLL_PTR_REG 0x1084
+
+#define BL_PRSM_CFG_REG 0x1400
+#define BL_PRSM_MEM_CFG_REG 0x1404
+#define BL_PRSM_RESET_CUR_CMD_REG 0x1408
+#define BL_PRSM_VGA_WIN_ORG_OFF_REG 0x140C
+#define BL_PRSM_VGA_CLIP_TEST_REG 0x1410
+
+#define BL_PRSM_INTR_STATUS_REG 0x2000
+#define BL_PRSM_CORRELATOR_REG 0x2004
+#define BL_PRSM_SOFT_RESET_REG 0x2008
+
+#define BL_PRSM_FR_START_REG 0x2400
+#define BL_PRSM_DTG_CNTL_REG 0x2404
+#define BL_PRSM_HORZ_EXTENT_REG 0x2408
+#define BL_PRSM_HORZ_DISPLAY_END_REG 0x240C
+#define BL_PRSM_HORZ_SYNC_START_REG 0x2410
+#define BL_PRSM_HORZ_SYNC_END_1_REG 0x2414
+#define BL_PRSM_HORZ_SYNC_END_2_REG 0x2418
+#define BL_PRSM_VERT_EXTENT_REG 0x241C
+#define BL_PRSM_VERT_DISPLAY_END_REG 0x2420
+#define BL_PRSM_VERT_SYNC_START_REG 0x2424
+#define BL_PRSM_VERT_SYNC_END_REG 0x2428
+
+#define BL_PRSM_RAMDAC_IMM_PORT 0x2600
+
+#define BL_PRSM_IO_SEL_IMM_PORT 0x2700
+
+#define BL_PRSM_MM_ADDR_PORT 0x2800
+#define BL_PRSM_MM_DATA_PORT 0x2804
+
+/******************************************************************************
+* *
+* Misc DFA Masks *
+* *
+******************************************************************************/
+
+#define BL_PRSM_1BPP_Y_ADDR_MASK 0x00FFF000
+#define BL_PRSM_1BPP_C_BIT_MASK 0x00000400
+#define BL_PRSM_1BPP_I_BIT_MASK 0x00000200
+#define BL_PRSM_1BPP_X_ADDR_MASK 0x000001FC
+
+#define BL_PRSM_8BPP_Y_ADDR_MASK 0x00FFF000
+#define BL_PRSM_8BPP_X_ADDR_MASK 0x00000FFF
+#define BL_PRSM_8BPP_RGB_RED_MASK 0xE0
+#define BL_PRSM_8BPP_RGB_GREEN_MASK 0x1C
+#define BL_PRSM_8BPP_RGB_BLUE_MASK 0x03
+#define BL_PRSM_8BPP_BGR_RED_MASK 0x07
+#define BL_PRSM_8BPP_BGR_GREEN_MASK 0x38
+#define BL_PRSM_8BPP_BGR_BLUE_MASK 0xC0
+
+#define BL_PRSM_16BPP_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_16BPP_X_ADDR_MASK 0x00001FFE
+#define BL_PRSM_16BPP_RGB_RED_MASK 0xF800
+#define BL_PRSM_16BPP_RGB_GREEN_MASK 0x07E0
+#define BL_PRSM_16BPP_RGB_BLUE_MASK 0x001F
+#define BL_PRSM_16BPP_BGR_RED_MASK 0x001F
+#define BL_PRSM_16BPP_BGR_GREEN_MASK 0x07E0
+#define BL_PRSM_16BPP_BGR_BLUE_MASK 0xF800
+
+#define BL_PRSM_24BPP_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_24BPP_X_ADDR_MASK 0x00001FFC
+#define BL_PRSM_24BPP_RGB_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_24BPP_RGB_RED_MASK 0x00FF0000
+#define BL_PRSM_24BPP_RGB_GREEN_MASK 0x0000FF00
+#define BL_PRSM_24BPP_RGB_BLUE_MASK 0x000000FF
+#define BL_PRSM_24BPP_BGR_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_24BPP_BGR_RED_MASK 0x000000FF
+#define BL_PRSM_24BPP_BGR_GREEN_MASK 0x0000FF00
+#define BL_PRSM_24BPP_BGR_BLUE_MASK 0x00FF0000
+#define BL_PRSM_24BPP_SPAN_WIDTH_MASK 0x0000FFFF
+
+#define BL_PRSM_32BPP_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_32BPP_X_ADDR_MASK 0x00001FFC
+#define BL_PRSM_32BPP_RGB_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_32BPP_RGB_RED_MASK 0x00FF0000
+#define BL_PRSM_32BPP_RGB_GREEN_MASK 0x0000FF00
+#define BL_PRSM_32BPP_RGB_BLUE_MASK 0x000000FF
+#define BL_PRSM_32BPP_BGR_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_32BPP_BGR_RED_MASK 0x000000FF
+#define BL_PRSM_32BPP_BGR_GREEN_MASK 0x0000FF00
+#define BL_PRSM_32BPP_BGR_BLUE_MASK 0x00FF0000
+#define BL_PRSM_32BPP_SPAN_WIDTH_MASK 0x0000FFFF
+
+#define BL_PRSM_MDFA_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_MDFA_X_ADDR_MASK 0x00001FFC
+#define BL_PRSM_MDFA_CNT_MASK 0xFF000000
+#define BL_PRSM_MDFA_MASK 0x00FFFFFF
+
+
+/******************************************************************************
+* *
+* Command Data Port Macros *
+* *
+******************************************************************************/
+
+#define BL_PRSM_CMD_DATA_PORT 0x0000
+#define BL_PRSM_CMD_DATA_PORT_START_ADDR 0x0000
+#define BL_PRSM_CMD_DATA_PORT_END_ADDR 0x0FFF
+#define BL_PRSM_CMD_DATA_PORT_LEN 0x1000
+
+
+/******************************************************************************
+* *
+* Control High Register *
+* *
+******************************************************************************/
+
+#define BL_SYS_SRC_DEPTH_A1_MASK 0x00000003
+#define BL_SYS_SRC_DEPTH_A1_1BPP 0x00000000
+#define BL_SYS_SRC_DEPTH_A1_8BPP 0x00000001
+#define BL_SYS_SRC_DEPTH_A1_16BPP 0x00000002
+#define BL_SYS_SRC_DEPTH_A1_24BPP 0x00000003
+#define BL_SYS_SRC_DEPTH_A1_32BPP 0x00000003
+
+#define BL_FB_PIX_DEPTH_A1_MASK 0x0000000C
+#define BL_FB_PIX_DEPTH_A1_8BPP 0x00000004
+#define BL_FB_PIX_DEPTH_A1_16BPP 0x00000008
+#define BL_FB_PIX_DEPTH_A1_24BPP 0x0000000C
+#define BL_FB_PIX_DEPTH_A1_32BPP 0x0000000C
+
+
+/******************************************************************************
+* *
+* Status Register *
+* *
+******************************************************************************/
+
+#define BL_PRSM_VERT_RETRACE 0x00000001
+#define BL_PRSM_HORZ_RETRACE 0x00000002
+
+#define BL_PRSM_IDLE 0x00000004
+#define BL_PRSM_BUSY 0x00000000
+
+#define BL_PRSM_DL_IDLE 0x00000008
+#define BL_PRSM_FIFO_EMPTY 0x00000010
+#define BL_PRSM_WAITING_FOR_SYS_ADDR 0x00000040
+#define BL_PRSM_ERR_DETECTED 0x00000080
+
+#define BL_PRSM_FIFO_FREE_SPACE_MASK 0x000F0000
+#define BL_PRSM_FIFO_FREE_SPACE_SHIFT 16
+
+
+/******************************************************************************
+* *
+* Interrupt Mask and Status Register *
+* *
+* Leave these definitions for possible future direct blit (DMA) support *
+* *
+******************************************************************************/
+
+#define BL_PRSM_DISABLE_RST_INTR 0x8FF3FC00
+
+/******************************************************************************
+* *
+* strapping information for memory configuration setting and detection *
+* *
+******************************************************************************/
+
+#define BL_FRAME_BUFFER_SIZE_MASK (3L << 16)
+#define BL_FRAME_BUFFER_SIZE_2_MEG (0L << 16)
+#define BL_FRAME_BUFFER_SIZE_4_MEG (1L << 16)
+#define BL_FRAME_BUFFER_SIZE_6_MEG (2L << 16)
+#define BL_FRAME_BUFFER_SIZE_8_MEG (3L << 16)
+#define BL_WID_BUFFER_SIZE_MASK (3L << 20)
+#define BL_WID_BUFFER_SIZE_0_MEG (0L << 20)
+#define BL_WID_BUFFER_SIZE_1_MEG (1L << 20)
+#define BL_WID_BUFFER_SIZE_2_MEG (2L << 20)
+#define BL_WID_BUFFER_SIZE_4_MEG (3L << 20)
+
+
+/******************************************************************************
+* *
+* misc defines *
+* *
+******************************************************************************/
+#define BL_CMD_QUEUE_SIZE 8
+
+#define BL_PRSM_NO_OP 0x0000
+
+ /* PRISM commands */
+#define BL_PRSM_BLT_SYS_TO_SCR_IND_OP 0x10000001
+#define BL_PRSM_BLT_SYS_TO_SCR_DIRECT_OP 0x0d400001
+#define BL_PRSM_BLT_SCR_TO_SCR_DIRECT_OP 0x0f030001
+#define BL_PRSM_BLT_SCR_TO_SYS_IND_OP 0x0DC00001
+#define BL_PRSM_POLY_REC 0x80020001
+#define BL_REG_DIRECT_RESTORE_FG 0xe4020001
+#define BL_REG_DIRECT_RESTORE_CTRL_HIGH 0xe4000001
+
+
+#define BL_PRISM_SPIN_PERIOD 1 /* busy spin delay in usec */
+ /* note: bl_delay() argument */
+ /* 1 yields about 1.6us */
+ /* 5 yields about 5.5us */
+ /* number of spin periods while */
+
+ /* waiting for busy to drop before */
+ /* driver asserts (time = 8 seconds) */
+ /* note: loop with bl_delay(1) and */
+ /* prism status read takes about */
+#define BL_PRISM_SPIN_TIME 4000000 /* 1.9-2.0 us */
+
+
+#define BL_DTG_NEG_SYNC 0x00000060 /* negitive sync */
+#define BL_DTG_COMP_SYNC 0x00004000 /* composite sync */
+#define BL_PRSM_NO_VIDEO 0x00000001 /* turn off video */
+#define BL_PRSM_VIDEO 0x00000002 /* turn on video */
+#define BL_PRSM_NO_VERT 0x00000400 /* hold vertical sync inactive */
+#define BL_PRSM_NO_HORZ 0x00001000 /* hold horizontal sync inactive */
+#define BL_PRSM_SYNC_MASK 0x00003e02 /* sync select / video blanking mask*/
+
+#define BL_FRAME_A 0x00000040 /* Frame buffer A select */
+#define BL_FRAME_B 0x00000080 /* Frame buffer B select */
+#define BL_FRAME_MASK 0x000000C0 /* Frame buffer select mask */
+
+#define SCL 0x00000001 /* I2C clock line (io port 2407) */
+#define SDA 0x00000020 /* I2C data line (io port 2407) */
+
+
+#define PRISM_WRT_REG(seg, reg, value) \
+ *((volatile unsigned long *)((seg) + BL_REG_OFFSET + (reg))) \
+ = (unsigned long) (value)
+
+#define PRISM_RD_REG(seg, reg) \
+ *((volatile unsigned long *)((seg) + BL_REG_OFFSET + (reg)))
+
+#define PRISM_WRT_DAC(seg, reg, value) \
+ *((volatile unsigned long *)((seg) + BL_REG_OFFSET + \
+ BL_PRSM_RAMDAC_IMM_PORT + (reg))) = (unsigned long)(value)
+
+#define PRISM_RD_DAC(seg, reg) \
+ (BL_EIEIO, \
+ (unsigned char)(*((volatile unsigned long *) \
+ ((seg) + BL_REG_OFFSET + BL_PRSM_RAMDAC_IMM_PORT + (reg)))))
+
+/******************************************************************************
+* *
+* Macro: BL_BUSY_POLL (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Performs a busy poll on the adapter and returns when the *
+* adapter is no longer busy. In the case of a shallow bus *
+* interface FIFO on the adapter, this macro will also make *
+* sure that the FIFO is empty and that the adapter is not *
+* busy. This is a synchronous call. *
+* *
+******************************************************************************/
+
+#define BL_BUSY_POLL(regbase) \
+ while(PRISM_RD_REG((regbase), BL_PRSM_STATUS_REG) & BL_PRSM_BUSY);
+
+
+/******************************************************************************
+* *
+* Macro: PRISM_BUSY (regbase) *
+* *
+* Parameters: regbase - ptr to base addr of registers *
+* *
+* Description: Determine if PRISM rasterizer is busy or idle. *
+* *
+******************************************************************************/
+#define PRISM_BUSY(regbase) \
+ (BL_EIEIO, \
+ !(PRISM_RD_REG(regbase, BL_PRSM_STATUS_REG) & BL_PRSM_IDLE))
+
+
+/******************************************************************************
+* PRISM_FIFO_NOT_AVAIL *
+******************************************************************************/
+
+#define PRISM_FIFO_NOT_AVAIL(ptr, cnt) \
+ (((PRISM_RD_REG(ptr, BL_PRSM_STATUS_REG) >> 16) & 0x0f) < cnt)
+
+/******************************************************************************
+* *
+* Macro: BL_FILL_RECT (regbase, dst_x, dst_y, width, height) *
+* caddr_t regbase; *
+* short dst_x, dst_y; *
+* unsigned short width, height; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* dst_x, dst_y - Screen coords of where to start the rect *
+* width, height - Dimensions of the rect *
+* *
+* Description: Performs a fill rectangle command to the adapter *
+* *
+******************************************************************************/
+
+#define BL_FILL_RECT(regbase, dst_x, dst_y, width, height) \
+ PRISM_WR_REG((regbase), BB_CMD_DATA_PORT, \
+ BL_POLYFILL_RECT_CMD | 0x1); \
+ PRISM_WR_REG((regbase), BL_CMD_DATA_PORT, \
+ (((unsigned short)(dst_x) << 16) | \
+ (unsigned short)(dst_y))); \
+ PRISM_WR_REG((regbase), BB_CMD_DATA_PORT, \
+ (((unsigned short)(height) << 16) | \
+ (unsigned short)(width)))
+
+
+#endif /* ! _H_BLRASTZ */
+
diff --git a/private/ntos/nthals/halppc/ppc/blrmdac.h b/private/ntos/nthals/halppc/ppc/blrmdac.h
new file mode 100644
index 000000000..33f41d64a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/blrmdac.h
@@ -0,0 +1,152 @@
+
+/*
+ * COMPONENT_NAME: bluedd
+ *
+ * FUNCTIONS: none
+ *
+ * ORIGINS: 156
+ *
+ * IBM CONFIDENTIAL -- (IBM Confidential Restricted when
+ * combined with the aggregated modules for this product)
+ * OBJECT CODE ONLY SOURCE MATERIALS
+ *
+ * (C) COPYRIGHT International Business Machines Corp. 1996
+ * All Rights Reserved
+ * US Government Users Restricted Rights - Use, duplication or
+ * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+ */
+
+#ifndef _H_BL_RAMDAC
+#define _H_BL_RAMDAC
+
+/******************************************************************************
+* *
+* RGB640 (Blue Bayou) *
+* *
+******************************************************************************/
+
+#define BL_RAMDAC_FB_LUT_LENGTH 256
+
+
+/* registers */
+/* WARNING: although not noted in spec, it appears that when setting */
+/* both BL_640_INDEX_LOW and BL_640_INDEX_HI, LOW should be */
+/* set before HI. */
+
+#define BL_640_PALETTE_ADDR_WRT 0x00
+#define BL_640_PALETTE_DATA 0x04
+#define BL_640_PIXEL_MASK 0x08
+#define BL_640_PALETTE_ADDR_RD 0x0C
+#define BL_640_INDEX_LOW 0x10
+#define BL_640_INDEX_HI 0x14
+#define BL_640_INDEX_DATA 0x18
+
+/* indexed registers */
+
+#define BL_640_ID_LOW 0x0000
+#define BL_640_ID_HI 0x0001
+#define BL_640_RAW_PIXEL_CTRL_00 0x0002
+#define BL_640_RAW_PIXEL_CTRL_08 0x0003
+#define BL_640_RAW_PIXEL_CTRL_16 0x0004
+#define BL_640_RAW_PIXEL_CTRL_24 0x0005
+#define BL_640_WID_OUT_CTRL_00 0x0006
+#define BL_640_WID_OUT_CTRL_04 0x0007
+#define BL_640_SERIALIZER_MODE 0x0008
+#define BL_640_PIXEL_INTERLEAVE 0x0009
+
+#define BL_640_MISC_CFG_REG 0x000A
+#define BL_640_WIDCTRL_MASK 0x07
+
+#define BL_640_VGA_CTRL 0x000B
+#define BL_640_MONITOR_ID 0x000C
+#define BL_640_DAC_CTRL 0x000D
+
+#define BL_640_UPDATE_CTRL 0x000E
+#define BL_640_AUTO_INCR 0x01
+
+#define BL_640_SYNC_CTRL 0x000F
+
+#define BL_640_SOG 0x03
+
+#define BL_640_PEDESTAL 0x01
+#define BL_640_COMP_SYNC 0x04
+#define BL_640_NEG_SYNC 0x08
+#define BL_640_POS_SYNC 0x10
+#define BL_640_PWR_LOW_SYNC 0x30
+#define BL_640_PWR_HIGH_VSYNC 0x20
+#define BL_640_PWR_HIGH_HSYNC 0x38
+#define BL_640_FLIP_VSYNC 0x01
+
+#define BL_640_VIDEO_PLL_REF_DIVIDE 0x0010
+#define BL_640_VIDEO_PLL_MULT 0x0011
+#define BL_640_VIDEO_PLL_OUTPUT_DIVIDE 0x0012
+#define BL_640_VIDEO_PLL_CTRL 0x0013
+#define BL_640_AUX_REF_DIVIDE 0x0014
+#define BL_640_AUX_PLL_MULT 0x0015
+#define BL_640_AUX_PLL_OUTPUT_DIVIDE 0x0016
+#define BL_640_AUX_PLL_CTRL 0x0017
+#define BL_640_CHROMA_KEY_REG 0 0x0020
+#define BL_640_CHROMA_KEY_MASK_0 0x0021
+#define BL_640_CHROMA_KEY_REG_1 0x0022
+#define BL_640_CHROMA_KEY_MASK_1 0x0023
+#define BL_640_CROSSHAIR CTRL 0x0030
+#define BL_640_CURSOR_BLINK_RATE 0x0031
+#define BL_640_CURSOR_BLINK_DUTY_CYCLE 0x0032
+#define BL_640_CURSOR_HORIZONTAL_POSITION_LOW 0x0040
+#define BL_640_CURSOR_HORIZONTAL_POSITION_HI 0x0041
+#define BL_640_CURSOR_VERTICAL_POSITION_LOW 0x0042
+#define BL_640_CURSOR_VERTICAL_POSITION_HI 0x0043
+#define BL_640_CURSOR_HORIZONTAL_OFFSET 0x0044
+#define BL_640_CURSOR_VERTICAL_OFFSET 0x0045
+#define BL_640_ADV_FUNC_CURSOR_COLOR_0 0x0046
+#define BL_640_ADV_FUNC_CURSOR_COLOR_1 0x0047
+#define BL_640_ADV_FUNC_CURSOR_COLOR_2 0x0048
+#define BL_640_ADV_FUNC_CURSOR_COLOR_3 0x0049
+#define BL_640_ADV_FUNC_CURSOR_ATTR_TABLE 0x004A
+#define BL_640_CURSOR_CTRL 0x004B
+#define BL_640_CROSSHAIR_HORIZONTAL_POSITION_LOW 0x0050
+#define BL_640_CROSSHAIR_HORIZONTAL_POSITION_HI 0x0051
+#define BL_640_CROSSHAIR_VERTICAL_POSITION_LOW 0x0052
+#define BL_640_CROSSHAIR_VERTICAL_POSITION_HI 0x0053
+#define BL_640_CROSSHAIR_PATTERN COLOR 0x0054
+#define BL_640_CROSSHAIR_VERTICAL_PATTERN 0x0055
+#define BL_640_CROSSHAIR_HORIZONTAL_PATTERN 0x0056
+#define BL_640_CROSSHAIR_CTRL_1 0x0057
+#define BL_640_CROSSHAIR_CTRL_2 0x0058
+#define BL_640_YUV_CONVERSION_COEF_K1 0x0070
+#define BL_640_YUV_CONVERSION_COEF_K2 0x0071
+#define BL_640_YUV_CONVERSION_COEF_K3 0x0072
+#define BL_640_YUV_CONVERSION_COEF_K4 0x0073
+#define BL_640_VRAM_MASK_REG_0 0x00F0
+#define BL_640_VRAM_MASK_REG_1 0x00F1
+#define BL_640_VRAM_MASK_REG_2 0x00F2
+#define BL_640_DIAGNOSTICS 0x00FA
+#define BL_640_MISR_CTRL_STATUS 0x00FB
+#define BL_640_MISR_SIGNATURE_0 0x00FC
+#define BL_640_MISR_SIGNATURE_1 0x00FD
+#define BL_640_MISR_SIGNATURE_2 0x00FE
+#define BL_640_MISR_SIGNATURE_3 0x00FF
+
+#define BL_640_FRAME_BUFFER_WAT 0x0100
+#define BL_640_FRAME_BUFFER_WAT_BYTES 64
+
+#define BL_640_OVERLAY_WAT 0x0200
+#define BL_640_OVERLAY_WAT_BYTES 64
+
+#define BL_640_CURSOR_PIXMAP_WRITE 0x1000
+#define BL_640_CURSOR_PIXMAP_READ 0x2000
+
+/* start of multi-cycle addresses */
+#define BL_640_MULTI_CYCLE 0x40
+
+#define BL_640_COLOR_PALETTE_WRITE 0x4000
+#define BL_640_CURSOR_PALETTE_WRITE 0x4800
+#define BL_640_CROSSHAIR_PALETTE_WRITE 0x4808
+#define BL_640_COLOR_PALETTE_READ 0x8000
+#define BL_640_CURSOR_PALETTE_READ 0x8800
+#define BL_640_CROSSHAIR_PALETTE_READ 0x8808
+
+
+#endif /* _H_BL_RAMDAC */
+
+
diff --git a/private/ntos/nthals/halppc/ppc/fwdebug.h b/private/ntos/nthals/halppc/ppc/fwdebug.h
new file mode 100644
index 000000000..de6d56cb2
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwdebug.h
@@ -0,0 +1,99 @@
+//
+// FWDEBUG.H
+//
+// Prototypes for FWDEBUG.C
+// (automatically generated by CPROTO)
+//
+
+#ifndef _CPROTO_FWDEBUG_
+#define _CPROTO_FWDEBUG_
+
+
+VOID
+DEBUG_START ()
+// Do whatever is required to install, start, or hook up the debugger.
+;
+
+
+VOID
+DEBUG_STOP ()
+// Stop the debugger cleanly.
+;
+
+
+VOID
+DEBUG_DISABLE ()
+// Temporarily disable DEBUG_PRINT, DEBUG_PROMPT, and DEBUG_BREAK
+;
+
+
+VOID
+DEBUG_ENABLE ()
+// Enable the DEBUG_PRINT, DEBUG_PROMPT, and DEBUG_BREAK functions.
+;
+
+
+VOID
+DEBUG_PRINT (
+ LONG DebugLevelReqd,
+ PCHAR DebugMessage,
+ ...
+);
+
+
+VOID
+DEBUG_MESSAGE (
+ PCHAR DebugMessage,
+ ...
+);
+
+
+VOID
+DEBUG_BREAK (
+ LONG DebugLevelReqd
+);
+
+
+VOID
+DEBUG_PROMPT (
+ LONG DebugLevelReqd,
+ PCHAR Prompt,
+ PCHAR Response,
+ LONG ResponseMaxLen
+);
+
+
+VOID
+DEBUG_SETLEVEL (
+ LONG NewLevel
+);
+
+
+LONG
+DEBUG_GETLEVEL (
+);
+
+
+VOID
+DEBUG_SETREGION (
+ ULONG Region
+);
+
+
+LONG
+DEBUG_GETREGION (
+);
+
+
+VOID
+DEBUG_SETREGIONMASK (
+ ULONG Mask
+);
+
+
+LONG
+DEBUG_GETREGIONMASK (
+);
+
+
+#endif // _CPROTO_FWDEBUG_
diff --git a/private/ntos/nthals/halppc/ppc/fwnvr.c b/private/ntos/nthals/halppc/ppc/fwnvr.c
new file mode 100644
index 000000000..83ef93dc4
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwnvr.c
@@ -0,0 +1,2033 @@
+////////////////////////////////////////////////////////////////////////// ++
+//
+// FWNVR.C
+//
+// Copyright 1991-94 IBM, Motorola, Microsoft
+//
+// Functions to access Non-Volatile Ram on PowerPC systems.
+//
+// This module is used exactly as-is by both ARC and HAL. By convention,
+// it originates in the ARC environment and is copied to the HAL tree.
+//
+////////////////////////////////////////////////////////////////////////// --
+
+/*
+YET TO DO:
+ Fix and use NVR size-sensing
+ Use nvr_set_variable() function.
+ Allocate memory even in the ARC environment, since later the size of
+ the buffers required may vary wildly. This won't be a
+ problem (for either HAL or ARC) IF we go to NVR-direct use.
+ NOTE: must handle pool-clearing problems FIRST (ARC only)
+ Q: handle buffer-size changes when nvr_read_nvram() gets actual
+ NVR size? Bufferless fixes this problem too.
+ Handle 24-bit access
+*/
+
+#ifdef _HALNVR_ /////// BUILDING FOR USE IN HAL ///////
+
+#include "halp.h"
+
+#else /////// BUILDING FOR USE IN ARC ///////
+
+#include "fwp.h"
+#define ExAllocatePool(type,size) FwAllocatePool(size)
+
+#endif // _HALNVR_ /////////////////////////////////////////
+
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+
+
+typedef struct _nvr_object
+{
+ struct _nvr_object *self ;
+ HEADER * bhead ;
+ HEADER * lhead ;
+ UCHAR bend [NVSIZE*2] ;
+ UCHAR lend [NVSIZE*2] ;
+} NVR_OBJECT, *PNVR_OBJECT ;
+
+typedef NVRAM_MAP *PNVRAM_MAP ;
+
+extern PVOID HalpIoControlBase ;
+
+#define ENDSWAP_SHORT(_x) (((_x<<8)&0xff00)|((_x>>8)&0x00ff))
+#define ENDSWAP_LONG(_x)\
+ (((_x<<24)&0xff000000)|((_x<<8)&0x00ff0000)|\
+ ((_x>>8)&0x0000ff00)|((_x>>24)&0x000000ff))
+
+#define _toupr_(_c) (((_c >= 'a') && (_c <= 'z')) ? (_c - 'a' + 'A') : _c)
+
+// Define the maximum size required for fetching any item from NVRAM, which
+// is defined to be the maximum size OF the NVRAM.
+// NOTE this is a poor assumption and needs to be sensed at run-time !!
+#define MAXNVRFETCH NVSIZE*2
+
+#define MAXIMUM_ENVIRONMENT_VALUE 1024
+
+
+/////////////////////////////////////////////////////////////////////////////
+// LOCAL DATA, NOT VISIBLE TO OTHER MODULES
+/////////////////////////////////////////////////////////////////////////////
+
+static UCHAR _currentstring[MAXIMUM_ENVIRONMENT_VALUE] ;
+static UCHAR _currentfetch[MAXNVRFETCH] ;
+
+#ifndef _HALNVR_
+NVR_OBJECT nvrobj ;
+#endif // _HALNVR_
+
+PNVR_OBJECT pnvrobj = NULL ;
+
+ // The access method varies with planar construction, and is switched
+ // based on the Planar ID Register.
+#define NVR_ACCESS_UNKNOWN 0
+#define NVR_ACCESS_SANDALFOOT 1
+#define NVR_ACCESS_STANDARD 2
+LONG NvrAccessMethod = NVR_ACCESS_UNKNOWN ;
+ // The use of 24-bit NVRAM addressing is enable with this flag:
+LONG NvrAccess24bit = FALSE ;
+ // These are the ISA port addresses for NVRAM Registers
+#define NVRREG_AD0 0x74 // LS byte of address (bits 0-7)
+#define NVRREG_AD1 0x75 // next byte of address (bits 8-15)
+// Below to be added when register definition finalized
+// #define NVRREG_AD2 0x?? // MS byte of address (bits 16-23)
+#define NVRREG_STDDATA 0x76 // Data Port (R/W), standard
+#define NVRREG_SFTDATA 0x77 // Data Port (R/W), Sandalfoot only
+
+ // The size below is used for error recovery, to either set NVRAM to
+ // a default state (a dubious proposition) or to clear it entirely.
+ULONG NvrFillSize = 4096 ; // "safe" default value
+
+USHORT NvrVersion = 0 ; // MSB=version, LSB=revision
+
+//////// Bring in prototypes automatically generated by CPROTO. These
+//////// should be placed AFTER any other headers and any module data
+//////// and data definitions, and BEFORE module code begins.
+#define _CPROTO_FW_SCOPE_
+#define _CPROTO_FWNVR_STATICS_
+#include "fwdebug.h"
+#include "fwnvr.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+PNVR_OBJECT
+nvr_alloc (
+ ULONG size
+)
+{
+ PNVR_OBJECT p ;
+
+#ifdef _HALNVR_
+ // HAL allocates memory for it so it doesn't sit around all the time
+ p = ExAllocatePool (NonPagedPool, size) ;
+#else
+ // FW uses static allocation (probably change later...)
+ p = &nvrobj ;
+#endif // _HALNVR_
+
+ return (p) ;
+}
+
+
+// !=
+VOID
+nvr_free (
+ PVOID p
+)
+{
+ if ( !p )
+ return ;
+
+ NvrAccessMethod = NVR_ACCESS_UNKNOWN ;
+ NvrAccess24bit = 0 ;
+
+#ifdef _HALNVR_
+ ExFreePool (p) ; // de-allocate HAL memory
+#endif // _HALNVR_
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// ==
+USHORT
+NvrGetVersion (
+ VOID
+)
+{
+ return ( NvrVersion ) ;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// ==
+ULONG
+NvrGetSize (
+ VOID
+)
+// Performs a hardware scan of NVRAM and returns it's size in bytes.
+// The algorithm accepts the fact that the bridge will return the last
+// byte written, even if it did NOT come from a memory location (it's
+// just a latch which is left with a stale value). So in order to get
+// a new value in the latch, we write to NVRAM location 0 between other
+// accesses.
+{
+ ULONG size = 1 ;
+ UCHAR b0, b1, b2, b3, b4 ;
+
+ // Since we'll be writing to location 0 for each byte tested, we
+ // can't test byte 0 without some special gyrations. Instead, we
+ // just start the test at byte 1. Recall that this is not intended
+ // so much as a memory TEST, but more a SIZE check.
+ size = 1 ;
+
+ b4 = nvr_read (0) ; // save byte 0 so the test is non-destructive
+ while ( size < 250000 )
+ {
+ b0 = nvr_read (size) ;
+ nvr_write (size,(UCHAR)(size&0xFF)) ;
+ nvr_write (0,(UCHAR)~(size&0xFF)) ;
+ b1 = nvr_read (size) ;
+ nvr_write (size,(UCHAR)~(size&0xFF)) ;
+ nvr_write (0,(UCHAR)(size&0xFF)) ;
+ b2 = nvr_read (size) ;
+ nvr_write (size,b0) ;
+ b3 = nvr_read (size) ;
+ if ( b3!=b0 || b1 != (UCHAR)(size&0xFF) || b2 != (UCHAR)~(size&0xFF) )
+ break ;
+ size++ ;
+ }
+ nvr_write (0,b4) ; // set first byte back again
+ if ( size == 1 )
+ size = 0 ;
+ return ( size ) ;
+}
+
+
+// ==
+BOOLEAN
+NvrSetSize (
+ LONG NvramSize // size of NVRAM in bytes if non-zero
+)
+{
+ ULONG size = 1 ;
+ UCHAR b0, b1, b2, b3, b4 ;
+
+ if ( NvramSize )
+ {
+ // Caller has specified what fill size is required. Just set
+ // the global variable and return.
+ NvrFillSize = NvramSize ;
+ DEBUG_PRINT (1,"NvrSetSize: fill size caller-set to %d bytes\n",NvrFillSize) ;
+ return TRUE ;
+ }
+ else
+ {
+ // Caller didn't know how big NVRAM is. We try to find out
+ // with a hardware test, and if successful we fill in the
+ // value. If we can't find out either, we disable clearing
+ // of NVRAM by setting NvrFillSize to zero.
+
+ size = NvrGetSize() & 0xFFFFF000 ; // size modulo-4k
+ DEBUG_PRINT (1,"NvrSetSize: fill size measured at %d bytes\n",size) ;
+
+// Overridden temporarily until we decide how to handle caller issues as to
+// whether clearing NVRAM is even legitimate to do. Code above works OK.
+
+ NvrFillSize = 0 ;
+ DEBUG_PRINT (1,"NvrSetSize: fill disabled by setting size to 0 bytes\n") ;
+ }
+ return TRUE ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// ==
+LONG
+NvrGetMethod (
+ VOID
+)
+// Returns the access method in use. If it has not yet been set, a
+// check of the hardware is made in an attempt to set it properly.
+{
+ if ( NvrAccessMethod == NVR_ACCESS_UNKNOWN )
+ NvrSetMethod (0) ;
+ return ( NvrAccessMethod ) ;
+}
+
+
+// ==
+BOOLEAN
+NvrSetMethod (
+ LONG ForcedValue // if Non-zero, set to this value regardless
+)
+// Decide how to access NVRAM, so that the nvr_read() and nvr_write()
+// functions can work properly. If a non-zero parameter is passed in,
+// the method is simply set to this value. If ZERO is passed in, then
+// local code tries to determine the proper method. Either way, the
+// operation is checked afterwards, and FALSE is returned if the access
+// method does recognize values inside NVRAM. If OK, TRUE returned.
+{
+ UCHAR PlanarID = 0;
+ UCHAR endian = '*' ;
+ HEADER *hp = (HEADER *)0;
+
+ // If caller sets it explicitly, just check the results. Otherwise,
+ // use the Planar ID Register to decide what method to use.
+
+ if ( ForcedValue )
+ NvrAccessMethod = ForcedValue ;
+ else
+ {
+ PlanarID = READ_REGISTER_UCHAR ((ULONG)HalpIoControlBase+0x852) ;
+
+ // NOTE that while the 0xDE value is documented as a
+ // Sandalfoot, it was never used as one. Instead, it is used
+ // on Woodfield. Unclear if 0xDD used, but it's defined in
+ // DAKOARCH as a Sandalfoot.
+ if ( (PlanarID >= 0xFC && PlanarID < 0xFF) // Sandalfoot
+ || (PlanarID >= 0xDC && PlanarID < 0xDE) // more Sandalfoot
+ || (PlanarID == 0x95) // Victory
+ || (PlanarID == 0x0C) // Harley
+ || (PlanarID == 0x5a) // Zapatos
+ )
+ NvrAccessMethod = NVR_ACCESS_SANDALFOOT ; // Carolina
+ else
+ NvrAccessMethod = NVR_ACCESS_STANDARD ;
+ }
+
+ endian = nvr_read((ULONG)((ULONG)(&hp->Endian)-(ULONG)hp)) ;
+
+ DEBUG_PRINT (1,"NvrSetMethod: PlanarID=0x%02X, Method set to %d (Endian shown as '%c')\n",
+ PlanarID,NvrAccessMethod,endian) ;
+
+ if ( endian != 'B' && endian != 'L' )
+ {
+ DEBUG_PRINT (0,"NvrSetMethod FAILED: Endian value was '%c'\n",
+ endian) ;
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+
+// ==
+UCHAR
+nvr_read (
+ ULONG addr
+)
+{
+ UCHAR uc = 0 ;
+
+ if ( !NvrAccessMethod )
+ NvrSetMethod (0) ;
+
+ switch ( NvrAccessMethod )
+ {
+ case 0:
+ DEBUG_PRINT (1,"nvr_read: NO NvrAccessMethod\n") ;
+ return 0 ;
+ case 1:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ uc = READ_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_SFTDATA) ;
+ break ;
+ case 2:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ uc = READ_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_STDDATA) ;
+ break ;
+ }
+
+ return ( uc ) ;
+}
+
+
+// ==
+VOID
+nvr_write (
+ ULONG addr,
+ UCHAR data
+)
+{
+ if ( !NvrAccessMethod )
+ NvrSetMethod (0) ;
+
+ switch ( NvrAccessMethod )
+ {
+ case 0:
+ DEBUG_PRINT (1,"nvr_write: NO NvrAccessMethod\n") ;
+ return ;
+ case 1:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_SFTDATA,
+ data) ;
+ break ;
+ case 2:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_STDDATA,
+ data) ;
+ break ;
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_swap_Header (
+ HEADER* dest,
+ HEADER* src
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+
+ if ( !dest || !src )
+ return ; // invalid pointer
+
+ dest->Size = ENDSWAP_SHORT(src->Size) ;
+ dest->Version = src->Version ;
+ dest->Revision = src->Revision ;
+ dest->Crc1 = ENDSWAP_SHORT(src->Crc1) ;
+ dest->Crc2 = ENDSWAP_SHORT(src->Crc2) ;
+ dest->LastOS = src->LastOS ;
+ dest->Endian = src->Endian ;
+ dest->OSAreaUsage = src->OSAreaUsage ;
+ dest->PMMode = src->PMMode ;
+
+
+// NOTE THIS CHANGES WITH UPDATED PPCNVR01.H
+ /* convert NVRRESTART_BLOCK structure of Header */
+ dest->ResumeBlock.CheckSum = ENDSWAP_LONG(src->ResumeBlock.CheckSum) ;
+ dest->ResumeBlock.BootStatus = ENDSWAP_LONG(src->ResumeBlock.BootStatus) ;
+ dest->ResumeBlock.ResumeAddr =
+ (PVOID) ENDSWAP_LONG((ULONG)src->ResumeBlock.ResumeAddr) ;
+ dest->ResumeBlock.SaveAreaAddr =
+ (PVOID) ENDSWAP_LONG((ULONG)src->ResumeBlock.SaveAreaAddr) ;
+ dest->ResumeBlock.SaveAreaLength =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.SaveAreaLength) ;
+ dest->ResumeBlock.HibResumeImageRBA =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.HibResumeImageRBA) ;
+ dest->ResumeBlock.HibResumeImageRBACount =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.HibResumeImageRBACount) ;
+ dest->ResumeBlock.Reserved =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.Reserved) ;
+
+
+ /* convert SECURITY structure */
+ dest->Security.BootErrCnt =
+ ENDSWAP_LONG(src->Security.BootErrCnt) ;
+ dest->Security.ConfigErrCnt =
+ ENDSWAP_LONG(src->Security.ConfigErrCnt) ;
+ dest->Security.BootErrorDT[0] =
+ ENDSWAP_LONG(src->Security.BootErrorDT[0]) ;
+ dest->Security.BootErrorDT[1] =
+ ENDSWAP_LONG(src->Security.BootErrorDT[1]) ;
+ dest->Security.ConfigErrorDT[0] =
+ ENDSWAP_LONG(src->Security.ConfigErrorDT[0]) ;
+ dest->Security.ConfigErrorDT[1] =
+ ENDSWAP_LONG(src->Security.ConfigErrorDT[1]) ;
+ dest->Security.BootCorrectDT[0] =
+ ENDSWAP_LONG(src->Security.BootCorrectDT[0]) ;
+ dest->Security.BootCorrectDT[1] =
+ ENDSWAP_LONG(src->Security.BootCorrectDT[1]) ;
+ dest->Security.ConfigCorrectDT[0] =
+ ENDSWAP_LONG(src->Security.ConfigCorrectDT[0]) ;
+ dest->Security.ConfigCorrectDT[1] =
+ ENDSWAP_LONG(src->Security.ConfigCorrectDT[1]) ;
+ dest->Security.BootSetDT[0] =
+ ENDSWAP_LONG(src->Security.BootSetDT[0]) ;
+ dest->Security.BootSetDT[1] =
+ ENDSWAP_LONG(src->Security.BootSetDT[1]) ;
+ dest->Security.ConfigSetDT[0] =
+ ENDSWAP_LONG(src->Security.ConfigSetDT[0]) ;
+ dest->Security.ConfigSetDT[1] =
+ ENDSWAP_LONG(src->Security.ConfigSetDT[1]) ;
+ for (i = 0 ; i < 16 ; i++)
+ dest->Security.Serial[i] = src->Security.Serial[i] ;
+
+ /* convert ERROR_LOG 0 and ERROR_LOG 1 structure */
+// ASAP: use sizeof() instead of 40 below...
+ for (i = 0 ; i < 40 ; i++)
+ {
+ dest->ErrorLog[0].ErrorLogEntry[i] = src->ErrorLog[0].ErrorLogEntry[i] ;
+ dest->ErrorLog[1].ErrorLogEntry[i] = src->ErrorLog[1].ErrorLogEntry[i] ;
+ }
+
+ /* convert remainder of Header */
+ dest->GEAddress = (PVOID) ENDSWAP_LONG((ULONG)src->GEAddress) ;
+ dest->GELength = ENDSWAP_LONG((ULONG)src->GELength) ;
+ dest->GELastWriteDT[0] = ENDSWAP_LONG(src->GELastWriteDT[0]) ;
+ dest->GELastWriteDT[1] = ENDSWAP_LONG(src->GELastWriteDT[1]) ;
+
+ dest->ConfigAddress =
+ (PVOID) ENDSWAP_LONG((ULONG)src->ConfigAddress) ;
+ dest->ConfigLength = ENDSWAP_LONG(src->ConfigLength) ;
+ dest->ConfigLastWriteDT[0] =
+ ENDSWAP_LONG(src->ConfigLastWriteDT[0]) ;
+ dest->ConfigLastWriteDT[1] =
+ ENDSWAP_LONG(src->ConfigLastWriteDT[1]) ;
+ dest->ConfigCount = ENDSWAP_LONG(src->ConfigCount) ;
+
+ dest->OSAreaAddress =
+ (PVOID) ENDSWAP_LONG((ULONG)src->OSAreaAddress) ;
+ dest->OSAreaLength = ENDSWAP_LONG(src->OSAreaLength) ;
+ dest->OSAreaLastWriteDT[0] =
+ ENDSWAP_LONG(src->OSAreaLastWriteDT[0]) ;
+ dest->OSAreaLastWriteDT[1] =
+ ENDSWAP_LONG(src->OSAreaLastWriteDT[1]) ;
+}
+
+
+// !=
+VOID
+nvr_headb2l (
+ PNVR_OBJECT p
+)
+{
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ nvr_swap_Header (p->lhead,p->bhead) ;
+}
+
+
+// !=
+VOID
+nvr_headl2b (
+ PNVR_OBJECT p
+)
+{
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ nvr_swap_Header (p->bhead,p->lhead) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_default_nvram (
+ PNVR_OBJECT p
+)
+// Attempts to protect operation from faulty intitialization of NVRAM
+// by early versions of ROS. Called only from nvr_read_nvram() when a
+// bad 'endian' indicator or CRC is found.
+{
+ ULONG i ;
+ PUCHAR cp ;
+ HEADER * bethp ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ DEBUG_PRINT (1,"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n") ;
+ DEBUG_PRINT (1,">>>>> CAUTION: Continuing from here will attempt to CLEAR NVRAM ! >>>>>>\n") ;
+ DEBUG_PRINT (1,"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n") ;
+ DEBUG_BREAK (1) ;
+
+ if ( NvrFillSize == 0 )
+ {
+ DEBUG_PRINT (1,">>>>>>>>>> nvr_default_nvram: CAN'T SET NVRAM TO DEFAULT (NO SIZE INFO)!\n") ;
+ DEBUG_BREAK (1) ;
+ return ;
+ }
+
+ DEBUG_PRINT (1,">>>>>>>>>> nvr_default_nvram: SETTING NVRAM TO DEFAULT VALUES!\n") ;
+
+ nvr_clear_nvram () ; // empty the physical NVRAM
+
+ bethp = (HEADER *)p->bend ;
+ cp = (PUCHAR)p->bend ;
+ /* clear internal header */
+ for (i = 0 ; i < sizeof(HEADER) ; i++)
+ *cp++ = 0 ;
+
+// ASAP: interlock with the (allocated) memory space available. We have to
+// never clear more memory than we have allocated!
+
+// ASAP: save size of volatile buffer in struct itself.
+
+ /* clear internal data areas */
+ for (i = 0 ; i < NvrFillSize ; i++)
+ p->bend[i] = p->lend[i] = 0 ;
+
+ bethp->Endian = 'B' ;
+ bethp->Size = ENDSWAP_SHORT((USHORT)NvrFillSize/1024) ;
+
+ // Watch it -- these could come back and byte us !!
+ bethp->Version = 1 ;
+ bethp->Revision = 4 ;
+
+ // Global Environment starts right after header, and uses all the
+ // space not reserved for the OS and CONFIG areas below.
+ bethp->GEAddress = (PVOID) ENDSWAP_LONG((ULONG)sizeof(HEADER)) ;
+ bethp->GELength =
+ ENDSWAP_LONG((ULONG)NvrFillSize-CONFSIZE-OSAREASIZE-sizeof(HEADER)) ;
+
+ // OS Area follows, taking up a default amount of space
+ bethp->OSAreaAddress =
+ (PVOID) ENDSWAP_LONG((ULONG)(NvrFillSize-CONFSIZE-OSAREASIZE)) ;
+ bethp->OSAreaLength = ENDSWAP_LONG((ULONG)OSAREASIZE) ;
+
+ // Set the config area such that it isn't used. This leaves some
+ // free space (CONFSIZE bytes) for it to grow downward into. This is
+ // counterintuitive, but matches what ROS uses for initialization.
+ bethp->ConfigAddress = (PVOID) ENDSWAP_LONG(NvrFillSize) ;
+ bethp->ConfigLength = ENDSWAP_LONG((ULONG)0) ;
+
+ nvr_headb2l (p) ; // copy data to Little-Endian (internal) side
+ nvr_write_Header (p) ; // write header to the hardware
+}
+
+static BOOLEAN crc2_short = FALSE;
+
+USHORT
+nvr_calc2crc_read (
+ PNVR_OBJECT p
+)
+// Checksum the CONFIGURATION AREA ONLY.
+{
+ ULONG ul ;
+ PUCHAR cp ;
+ PUCHAR end ;
+
+ if ( !p || p != p->self )
+ return 0xFFFF ; // invalid pointer
+// Original version returned indeterminate value here !!
+// ASAP: check with ESW for proper resolution!
+// return ;
+
+ ul = 0xFFFF ;
+
+// ASAP: revisit the calculation size. The first Wiltwick had a "gap"
+// between the OS and CFG areas, and it may NOT have been checksummed.
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress) ;
+#if 0
+// end = (PUCHAR)((ULONG)p->bhead +
+// (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) )) ;
+#endif
+
+//
+// PLJ reverted to original code to avoid blowing checksum in config
+// area on sandalfoot.
+//
+
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+
+// end PLJ change
+
+ for ( ; cp < end ; cp++)
+ ul = nvr_computecrc(ul, *cp) ;
+
+ //
+ // Note that we checksummed 1 byte too few, this is to
+ // allow for OLD versions of the firmware. If the checksum
+ // now == expected value, set the boolean crc2_short to TRUE
+ // so we calculate the right value when writing and return
+ // the current value. If it is not currently correct,
+ // checksum 1 more byte and return that value.
+ //
+
+ if ((USHORT)(ul & 0xFFFF) == p->lhead->Crc2) {
+ crc2_short = TRUE;
+ } else {
+ ul = nvr_computecrc(ul, *cp) ;
+ }
+
+ return ( (USHORT)(ul & 0xFFFF) ) ;
+}
+
+USHORT
+nvr_calc2crc_write (
+ PNVR_OBJECT p
+)
+// Checksum the CONFIGURATION AREA ONLY.
+{
+ ULONG ul ;
+ PUCHAR cp ;
+ PUCHAR end ;
+
+ if ( !p || p != p->self )
+ return 0xFFFF ; // invalid pointer
+// Original version returned indeterminate value here !!
+// ASAP: check with ESW for proper resolution!
+// return ;
+
+ ul = 0xFFFF ;
+
+// ASAP: revisit the calculation size. The first Wiltwick had a "gap"
+// between the OS and CFG areas, and it may NOT have been checksummed.
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress) ;
+
+// end = (PUCHAR)((ULONG)p->bhead +
+// (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) )) ;
+
+
+//
+// PLJ if we were short 1 byte on the read, calculate the new checksum
+// 1 byte short also. This is to support old firmware.
+//
+
+ if ( crc2_short ) {
+ end--;
+ }
+
+// end PLJ change
+
+ for ( ; cp < end ; cp++)
+ ul = nvr_computecrc(ul, *cp) ;
+
+ return ( (USHORT)(ul & 0xFFFF) ) ;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+BOOLEAN
+nvr_read_nvram (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+ HEADER * bhp ; // ptr to BE header
+ USHORT crc1a = 0 , crc1c = 0 ; // actual and calculated
+ USHORT crc2a = 0 , crc2c = 0 ; // values for each CRC
+ ULONG nvr_selfsize = 0 ;
+
+ DEBUG_PRINT (2,"nvr_read_nvram: entry\n") ;
+
+ if ( !p || p != p->self )
+ return FALSE ; // invalid pointer
+
+ /* read the HEADER from the NVRAM chip */
+ bhp = p->bhead ;
+ cp = (PUCHAR)p->bend ;
+ for (i = 0 ; i < sizeof(HEADER) ; i++)
+ *cp++ = nvr_read(i) ;
+
+ if ((bhp->Endian != 'B') && (bhp->Endian != 'L'))
+ goto error ;
+
+ // convert big endian header to little endian
+ nvr_headb2l (p) ;
+
+ // read the data areas. We have to do this before calculating the
+ // checksum, since these areas are checked.
+ nvr_read_GEArea(p) ;
+ nvr_read_OSArea(p) ;
+ nvr_read_CFArea(p) ;
+
+ // validate checksum 1
+ crc1a = ENDSWAP_SHORT(bhp->Crc1) ;
+ crc1c = nvr_calc1crc(p) ;
+ if ( crc1a != crc1c )
+ goto error ;
+
+ // validate checksum 2
+ crc2a = ENDSWAP_SHORT(bhp->Crc2) ;
+ crc2c = nvr_calc2crc_read(p) ;
+ if ( crc2a != crc2c )
+ goto error ;
+
+ // At this point the checksum matches, and we have good confidence of
+ // having valid data. We use the data within the NVRAM to firm up
+ // our notion of how big NVRAM is, in case we later have to clear it.
+ nvr_selfsize = ((ULONG)(ENDSWAP_SHORT(bhp->Size))) * 1024 ;
+ NvrSetSize (nvr_selfsize) ;
+
+ // Save the NVR version for later query if required
+ NvrVersion = (bhp->Version<<8) | bhp->Revision ;
+
+// ASAP: cross-check NvrFillSize with all three addresses and sizes stored
+// in NVRAM to see if the values make sense.
+
+ return TRUE ;
+
+ // We get below only if there was an error reading NVRAM. If so,
+ // show whatever we can for debugging and then go set NVRAM to the
+ // "default" state.
+error:
+ DEBUG_PRINT (1,"NVRAM READ ERROR ! Endian byte = '%c'\n",bhp->Endian) ;
+ DEBUG_PRINT (1," CRC1 as read: 0x%04X Calculated: 0x%04X\n",crc1a,crc1c) ;
+ DEBUG_PRINT (1," CRC2 as read: 0x%04X Calculated: 0x%04X\n",crc2a,crc2c) ;
+ nvr_print_object () ; // if debugging, show before deleting
+ nvr_default_nvram (p) ;
+ return FALSE ;
+}
+
+
+// !=
+VOID
+nvr_read_GEArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR lp ;
+ PUCHAR bp ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // Read Global Environment data into both BE and LE areas
+ offset = (ULONG)p->lhead->GEAddress ;
+ lp = (PUCHAR)((ULONG)p->lhead + offset) ;
+ bp = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->GELength ; i++, bp++, lp++)
+ *bp = *lp = nvr_read(offset + i) ;
+}
+
+
+// !=
+VOID
+nvr_read_OSArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR lp ;
+ PUCHAR bp ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // Read OS-Specific Environment data into both BE and LE areas
+ offset = (ULONG)p->lhead->OSAreaAddress ;
+ lp = (PUCHAR)((ULONG)p->lhead + offset) ;
+ bp = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->OSAreaLength ; i++, bp++, lp++)
+ *bp = *lp = nvr_read(offset + i) ;
+}
+
+
+// !=
+VOID
+nvr_read_CFArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR lp ;
+ PUCHAR bp ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // Read Configuration data into both BE and LE areas
+ offset = (ULONG) p->lhead->ConfigAddress ;
+ lp = (PUCHAR) ((ULONG)p->lhead + offset) ;
+ bp = (PUCHAR) ((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->ConfigLength ; i++)
+ bp[i] = lp[i] = nvr_read(offset + i) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_write_Header (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+ USHORT us ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // We treat the LE header as the 'master', so first convert it's
+ // contents into BE format to be written ti NVRAM
+ nvr_headl2b(p) ;
+
+ // Fill in the CRC values. NOTE that changes are made to the LE
+ // header WITHOUT updating the CRC, so we have to do it before
+ // writing the header. It's the BE data that's being checksummed.
+ us = nvr_calc1crc(p) ;
+ p->bhead->Crc1 = ENDSWAP_SHORT(us) ;
+ us = nvr_calc2crc_write(p) ;
+ p->bhead->Crc2 = ENDSWAP_SHORT(us) ;
+
+ // spit out data
+ cp = (PUCHAR)p->bend ;
+ for ( i = 0 ; i < sizeof(HEADER) ; i++ )
+ nvr_write (i, *cp++) ;
+}
+
+
+// !=
+VOID
+nvr_write_GEArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR dest ;
+ PUCHAR src ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->GEAddress ;
+ src = (PUCHAR)((ULONG)p->lhead + offset) ;
+ dest = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->GELength ; i++, dest++, src++)
+ *dest = *src ;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p) ;
+
+ /* spit out global environment data */
+ src = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->GELength ; i++, src++)
+ nvr_write (i+offset, *src) ;
+}
+
+
+// !=
+VOID
+nvr_write_OSArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ ULONG offset ;
+ PUCHAR src ;
+ PUCHAR dest ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG) p->lhead->OSAreaAddress ;
+ src = (PUCHAR) ((ULONG)p->lhead + offset) ;
+ dest = (PUCHAR) ((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->OSAreaLength ; i++, dest++, src++)
+ *dest = *src ;
+
+ /* spit out OS specific data */
+ /* header not needed - no crc for OS Area in Header */
+ src = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->OSAreaLength ; i++, src++)
+ nvr_write (i+offset, *src) ;
+}
+
+
+// !=
+VOID
+nvr_write_CFArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR dest ;
+ PUCHAR src ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->ConfigAddress ;
+ dest = (PUCHAR) ((ULONG)p->bhead + offset - 1) ;
+ src = (PUCHAR) ((ULONG)p->lhead + offset - 1) ;
+ for (i = 0 ; i < p->lhead->ConfigLength ; i++, dest--, src--)
+ *dest = *src ;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p) ;
+
+ /* spit out configuration data */
+ src = (PUCHAR)((ULONG)p->bhead + offset - 1) ;
+ for (i = 1 ; i <= p->lhead->ConfigLength ; i++, src--)
+ nvr_write (i+offset, *src) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// USED_BY_HAL:
+// ==
+VOID
+nvr_delete_object (
+ VOID
+)
+{
+ if ( !pnvrobj || pnvrobj != pnvrobj->self )
+ return ;
+
+ pnvrobj->self = NULL ;
+ nvr_free (pnvrobj) ;
+ pnvrobj = NULL ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+PNVR_OBJECT
+nvr_create_object (
+ VOID
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+ UCHAR pid ;
+
+ // Allocate (or just find) memory for the local NVR Object
+ pnvrobj = nvr_alloc (sizeof(NVR_OBJECT)) ;
+ if ( !pnvrobj )
+ return NULL ; // ERROR: couldn't get memory
+
+ // Zero out the object
+ for (i = 0, cp = (PUCHAR)pnvrobj ; i < sizeof(NVR_OBJECT) ; i++, cp++)
+ *cp = 0 ;
+
+ // initialize internal elements
+ pnvrobj->self = pnvrobj ;
+ pnvrobj->bhead = (HEADER *) pnvrobj->bend ;
+ pnvrobj->lhead = (HEADER *) pnvrobj->lend ;
+
+ return (pnvrobj) ;
+}
+
+
+// USED_BY_HAL:
+
+// ==
+STATUS_TYPE
+nvr_initialize_object (
+ LONG AccessMethod,
+ ULONG Size // NVR size in bytes
+)
+// Set up everything required to be able to access and modify NVRAM.
+// The parameters are "optional" (may be zero).
+//
+// If AccessMethod == 0, the actual value will be derived from the
+// hardware (at this point the hardware test is reliable).
+//
+// If Size == 0, the program will attempt to determine the actual NVRAM
+// size by a hardware test (at this point this is in-op). After the
+// NVRAM is read successfully and the CRC checks, the value will be
+// updated based on the value found inside NVRAM itself. If the caller
+// furnishes no value AND a valid value is NOT found, clearing of NVRAM
+// will be disabled.
+//
+// NOTE that this module must somehow know the Method in order to
+// perform ANY accesses, but that Size is only used in error cases to
+// destroy the entire NVRAM.
+{
+ DEBUG_PRINT (1,"enter nvr_initialize_object\n") ;
+
+ if ( pnvrobj )
+ return stat_exist ; // object ALREADY initialized!
+
+ // create object or get static address
+ if ( !(pnvrobj = nvr_create_object()) )
+ return stat_error ;
+
+ NvrFillSize = Size ;
+
+ // Decide HOW to access NVRAM and set global variable
+ NvrSetMethod (AccessMethod) ;
+
+// ASAP: figure how to handle an error properly. If zero returned from
+// above, the endian indicator didn't show up and we probably can't
+// read NVRAM at all. What to do, what to do??
+
+ NvrSetSize (Size) ;
+
+ // read the header from NVRAM and convert to little endian
+ nvr_read_nvram (pnvrobj) ;
+
+ nvr_print_object() ; // if debugging, print the values
+
+ return stat_ok ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_clear_nvram (
+ VOID
+)
+// Set ALL of NVRAM to zeros: header, checksum, EVERYTHING! This is
+// used to set default values in case a corrupted system is found, OR
+// from the (user-initiated) nvr_destory() function.
+{
+ ULONG i ;
+
+ for ( i = 0 ; i < NvrFillSize ; i++ )
+ nvr_write (i,0) ;
+}
+
+
+// ==
+VOID
+nvr_destroy (
+ LONG AccessMethod,
+ ULONG Size // size of NVRAM
+)
+// This is used as a debugging and recovery feature only. It is accessed
+// via a secret back door in the FWBOOT.C module, and is never executed,
+// other than manually by the user.
+{
+ if ( !pnvrobj || pnvrobj != pnvrobj->self )
+ return ; // invalid pointer
+
+ nvr_delete_object () ; // delete in case corrupt
+ nvr_initialize_object (AccessMethod,Size) ; // get new copy
+ nvr_clear_nvram () ; // EMPTY THE PHYSICAL NVRAM
+ nvr_delete_object() ; // delete local copy
+
+ // re-read so local copy matches
+ nvr_initialize_object (AccessMethod,Size) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// The CRC computation algorithm must match that used by the resident
+// firmware (ROS). The algorithms below were obtained from the ESW Group
+// that develops Dakota Firmware. Whenever there are changes in their
+// algorithms, they must be changed here also.
+/////////////////////////////////////////////////////////////////////////////
+
+#define rol(x,y) ( ( ((x)<<(y)) | ((x)>>(16 - (y))) ) & 0x0FFFF)
+#define ror(x,y) ( ( ((x)>>(y)) | ((x)<<(16 - (y))) ) & 0x0FFFF)
+
+// !=
+ULONG
+nvr_computecrc (
+ ULONG oldcrc,
+ UCHAR data
+)
+{
+ ULONG pd, crc ;
+
+ pd = ((oldcrc>>8) ^ data) << 8 ;
+
+ crc = 0xFF00 & (oldcrc << 8) ;
+ crc |= pd >> 8 ;
+ crc ^= rol(pd,4) & 0xF00F ;
+ crc ^= ror(pd,3) & 0x1FE0 ;
+ crc ^= pd & 0xF000 ;
+ crc ^= ror(pd,7) & 0x01E0 ;
+ return crc ;
+}
+
+
+// !=
+USHORT
+nvr_calc1crc (
+ PNVR_OBJECT p
+)
+{
+ ULONG ul ;
+ ULONG i ;
+ PUCHAR cp ;
+ ULONG len1 ;
+ ULONG len2 ;
+ USHORT us ;
+
+ if ( !p || p != p->self )
+ return 0 ; // invalid pointer
+
+ ul = 0x0ffff ;
+
+ // do not include current Crc1/Crc2 in checksum
+ len1 = (sizeof(p->bhead->Size) +
+ sizeof(p->bhead->Version) +
+ sizeof(p->bhead->Revision)) ;
+ len2 = (ULONG) p->lhead->OSAreaAddress ;
+
+
+ // calculate the area before Crc1/Crc2 in the header
+ for (cp = (PUCHAR)p->bhead, i = 0 ; i < len1 ; i++)
+ ul = nvr_computecrc(ul, cp[i]) ;
+
+// NOTE: this switch was required starting with NVR 1.4 as shipped on Delmar.
+// It's unclear whether the change is really related to 1.4 format or
+// to some other ROS change, but we're switching on 1.4 anyway. If a
+// problem develops where the CRC of a new Machine or ROS goes bad,
+// check this out early. Originally this switch was done at compile-
+// time, and was labelled FIX_D852. Defining this name enabled the
+// (now) post-1.3 code.
+ if ( p->bhead->Version <= 1 && p->bhead->Revision < 4 )
+ i += (sizeof(p->bhead->Crc1) + sizeof(p->bhead->Crc2)) + 1 ;
+ else
+ i += (sizeof(p->bhead->Crc1) + sizeof(p->bhead->Crc2)) ;
+
+ for (i = i ; i < len2 ; i++)
+ ul = nvr_computecrc(ul, cp[i]) ;
+
+ us = (USHORT)(ul & 0x0ffff) ;
+
+ return (us) ;
+}
+
+
+// !=
+USHORT
+nvr_calc2crc (
+ PNVR_OBJECT p
+)
+// Checksum the CONFIGURATION AREA ONLY.
+{
+ ULONG ul ;
+ PUCHAR cp ;
+ PUCHAR end ;
+
+ if ( !p || p != p->self )
+ return 0xFFFF ; // invalid pointer
+// Original version returned indeterminate value here !!
+// ASAP: check with ESW for proper resolution!
+// return ;
+
+ ul = 0xFFFF ;
+
+// ASAP: revisit the calculation size. The first Wiltwick had a "gap"
+// between the OS and CFG areas, and it may NOT have been checksummed.
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress) ;
+#if 0
+// end = (PUCHAR)((ULONG)p->bhead +
+// (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) )) ;
+#endif
+
+//
+// PLJ reverted to original code to avoid blowing checksum in config
+// area on sandalfoot.
+//
+
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+
+// end PLJ change
+
+ for ( ; cp < end ; cp++)
+ ul = nvr_computecrc(ul, *cp) ;
+
+ return ( (USHORT)(ul & 0xFFFF) ) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS PUBLIC TO THE HIGHER LAYERS OF SOFTWARE
+// The functions below operate on the little endian section of the
+// data structure internal to this file. Little endian is the internal
+// (volatile RAM) representation of the NVRAM contents. All access to
+// NVRAM data (variables, etc) are performed on this internal
+// representation. When necessary, the internal representation is
+// loaded back into NVRAM.
+/////////////////////////////////////////////////////////////////////////////
+
+// ==
+VOID
+nvr_print_object (
+ VOID
+)
+// Called by SFENVIR.C after nvr_initialize()
+{
+ PUCHAR cp ;
+ PUCHAR max ;
+ UCHAR tmp ;
+ PNVRAM_MAP mp ;
+ HEADER* hp ;
+ LONG i ;
+ CHAR buf[100] ; // buffer for string creation
+
+ if ( !pnvrobj || pnvrobj != pnvrobj->self )
+ return ; // invalid pointer
+
+ if ( DEBUG_GETLEVEL() < 1 )
+ return ;
+
+ mp = (PNVRAM_MAP) pnvrobj->lend ;
+ hp = pnvrobj->lhead ;
+
+ DEBUG_PRINT (1,"================= INTERNAL NVRAM DISPLAY ==================\n") ;
+ DEBUG_PRINT (1," Object Addr: 0x%08lx\n", (ULONG)pnvrobj->self) ;
+ DEBUG_PRINT (1," BE Header addr: 0x%08lx\n", (ULONG)pnvrobj->bhead) ;
+ DEBUG_PRINT (1," LE Header addr: 0x%08lx\n", (ULONG)pnvrobj->lhead) ;
+
+ DEBUG_PRINT (1,"=============== NVRAM LITTLE-ENDIAN DISPLAY ===============\n") ;
+ DEBUG_PRINT (1," Size: %dK, Version %d.%d CRC1=0x%04X CRC2=0x%04X Endian: '%c'\n",
+ (int)hp->Size,
+ (int)hp->Version, (int)hp->Revision,
+ (int)hp->Crc1,
+ (int)hp->Crc2,
+ hp->Endian
+ ) ;
+
+ // Show the serial number
+ for ( i=0 ;
+ i < sizeof(hp->Security.Serial)
+ && i < (sizeof(buf)-2)
+ && (tmp=hp->Security.Serial[i]) ;
+ i++
+ )
+ buf[i] = tmp ;
+ buf[i] = '\0' ; // terminate the string
+ DEBUG_PRINT (1," Serial: '%s'\n",buf) ;
+
+ DEBUG_PRINT (1," ---- GEAddress: 0x%08lx GELength: 0x%08lx\n",
+ hp->GEAddress, hp->GELength) ;
+ cp = (PUCHAR)((ULONG)hp + (ULONG)hp->GEAddress) ;
+ max = (PUCHAR)((ULONG)cp + hp->GELength) ;
+ while ((*cp) && (cp < max))
+ {
+ DEBUG_PRINT (1," '%s'\n", cp) ;
+ cp += (strlen(cp) + 1) ;
+ }
+
+ DEBUG_PRINT (1," ---- OSAreaAddress: 0x%08lx OSAreaLength: 0x%08lx\n",
+ hp->OSAreaAddress, hp->OSAreaLength) ;
+ cp = (PUCHAR)((ULONG)hp + (ULONG)hp->OSAreaAddress) ;
+ max = (PUCHAR)((ULONG)cp + hp->OSAreaLength) ;
+ while ((*cp) && (cp < max))
+ {
+ DEBUG_PRINT (1," '%s'\n", cp) ;
+ cp += (strlen(cp) + 1) ;
+ }
+
+ DEBUG_PRINT (1," ---- ConfigAddress: 0x%08lx ConfigLength: 0x%08lx Count: 0x%08lx\n",
+ hp->ConfigAddress, hp->ConfigLength, hp->ConfigCount) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// NOT YET USED; other finds will be written in terms of this one ASAP
+
+// ==
+STATUS_TYPE
+nvr_find_variable (
+ PUCHAR VarName, // name of variable to find
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize, // max size of variable array
+ PULONG ni,
+ PULONG vi
+)
+{
+ PUCHAR lvar ;
+ PUCHAR cp ;
+ ULONG i ;
+
+ if ( !VarName || !(*VarName) || !ArrayAddr || !ArraySize )
+ return stat_error ; // bad input
+
+ i = 0 ;
+ while ( TRUE )
+ {
+ lvar = VarName ;
+ *ni = i ; // RETURN Name Index
+ cp = ArrayAddr ;
+
+ // does the variable we want start at this index?
+ while ( i < ArraySize )
+ {
+ /* break if mismatch */
+ if (_toupr_(cp[i]) != _toupr_(*lvar))
+ break ; // mismatch
+ lvar++, i++ ;
+ }
+
+ // if var name matches
+ if ( *lvar == 0 && cp[i] == '=' )
+ {
+ *vi = ++i ; // RETURN Value Index
+ return stat_ok ; // indicate FOUND
+ }
+
+ // no match - set index to start of the next variable
+ if ( i >= ArraySize )
+ return stat_error ;
+ while ( cp[i++] != 0 )
+ {
+ if ( i >= ArraySize )
+ return stat_error ;
+ }
+ }
+}
+
+
+// ==
+STATUS_TYPE
+nvr_set_variable (
+ PUCHAR VarName, // name of variable to add/change
+ PUCHAR VarValue, // value to be set into variable
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize // max size of variable array
+)
+{
+ PUCHAR lvar ;
+ PUCHAR cp ;
+ ULONG i ;
+ ULONG ni ;
+ ULONG vi ;
+ ULONG eos ;
+ PUCHAR str ;
+ ULONG count ;
+ CHAR c ;
+
+ if ( !VarName || !(*VarName) || !ArrayAddr || !ArraySize )
+ return stat_error ; // bad input
+
+// MORE; NOT QUITE READY FOR PRIME TIME
+// Convert to use pointers throughout instead of indexes (including
+// calling convention). At some future time this function will be one
+// of the basic blocks for dealing with NVRAM directly (no buffers),
+// IF the hardware folk say it's OK.
+
+ // find the end of the used space by looking for
+ // the first non-null character from the top
+ eos = ArraySize - 1 ;
+ while ( ArrayAddr[--eos] == 0 )
+ {
+ if ( eos == 0 )
+ break ;
+ }
+
+ // position eos to the first new character, unless
+ // environment space is empty
+ if ( eos != 0 )
+ eos += 2 ;
+
+ count = ArraySize - eos ;
+
+ // find out if the variable already has a value
+ if ( nvr_find_variable(VarName,ArrayAddr,ArraySize,&ni,&vi) == stat_ok )
+ {
+ // The VarName already exists. See if there is room to
+ // substitute it with the new one.
+
+ // count free space
+ // start with the free area at the top and add
+ // the old ni value
+ for ( str = &(ArrayAddr[vi]) ; *str != 0 ; str++ )
+ count++ ;
+
+ // if free area is not large enough to handle new value,
+ // return an error
+ for ( str = VarValue ; *str != 0 ; str++ )
+ {
+ if ( count-- == 0 )
+ return stat_error ;
+ }
+
+ // pack strings
+ // first move vi to the end of the value
+ while ( ArrayAddr[vi++] != 0 )
+ ;
+
+ // now move everything to where the variable starts
+ // covering up the old name/value pair
+ while ( vi < eos )
+ {
+ c = ArrayAddr[vi++] ;
+ ArrayAddr[ni++] = c ;
+ }
+
+ // adjust new top of environment
+ eos = ni ;
+
+ // zero to the end of OS area
+ while ( ni < ArraySize )
+ ArrayAddr[ni++] = 0 ;
+ }
+ else
+ {
+ // variable is new
+ // if free area is not large enough to handle new value return error
+ for ( str = VarValue ; *str != 0 ; str++ )
+ {
+ if ( count-- == 0 )
+ return stat_error ;
+ }
+ }
+
+ // At this point any existing variable by the name specified has been
+ // removed. If there is no new value to be added, we're done
+
+ if ( *VarValue )
+ {
+ // insert new name, converting to upper case.
+ while ( *VarName )
+ {
+ ArrayAddr[eos++] = *VarName++ ;
+ }
+ ArrayAddr[eos++] = '=' ;
+
+ // insert new value, leaving case alone
+ while ( *VarValue )
+ ArrayAddr[eos++] = *VarValue++ ;
+ }
+ return stat_ok;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// ==
+STATUS_TYPE
+nvr_find_OS_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+)
+{
+ PUCHAR cp ;
+ HEADER * lhp ;
+
+ if ( !pnvrobj || !var || !(*var) )
+ return stat_error ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)(lhp->OSAreaAddress)) ;
+
+ return ( nvr_find_variable(var,cp,lhp->OSAreaLength,ni,vi) ) ;
+}
+
+
+// ==
+STATUS_TYPE
+nvr_find_GE_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+)
+{
+ PUCHAR cp ;
+ HEADER * lhp ;
+
+ if ( !pnvrobj || !var || !(*var) )
+ return stat_error ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)(lhp->GEAddress)) ;
+
+ return ( nvr_find_variable(var,cp,lhp->GELength,ni,vi) ) ;
+}
+
+
+// ==
+PUCHAR
+nvr_get_OS_variable (
+ PUCHAR vname
+)
+{
+ ULONG ni ;
+ ULONG vi ;
+ ULONG i ;
+ PNVRAM_MAP lep ;
+ PUCHAR array ;
+
+ if ( !pnvrobj || !vname || !(*vname) )
+ return NULL ;
+
+ if (nvr_find_OS_variable(vname, &ni, &vi) != stat_ok)
+ return NULL ;
+
+ lep = (PNVRAM_MAP)pnvrobj->lend ;
+ array = (PUCHAR)((ULONG)lep + (ULONG)(lep->Header.OSAreaAddress)) ;
+
+ for ( i = 0 ; i < MAXIMUM_ENVIRONMENT_VALUE - 1 ; i++ )
+ {
+ if ( array[vi] == 0 )
+ break ;
+ _currentstring[i] = array[vi++] ;
+ }
+ _currentstring[i] = 0 ;
+
+ return ( _currentstring ) ;
+}
+
+
+// USED_BY_HAL: also SFENVIR.C
+
+// ==
+PUCHAR
+nvr_get_GE_variable (
+ PUCHAR vname
+)
+{
+ ULONG ni ;
+ ULONG vi ;
+ ULONG i ;
+ PUCHAR cp ;
+ HEADER* lhp ;
+
+ if ( !pnvrobj || !vname || !(*vname) )
+ return NULL ;
+
+ if (nvr_find_GE_variable(vname, &ni, &vi) != stat_ok)
+ return NULL ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+
+ for (i = 0 ; i < MAXIMUM_ENVIRONMENT_VALUE - 1 ; i++)
+ {
+ if (cp[vi] == 0)
+ {
+ break ;
+ }
+ _currentstring[i] = cp[vi++] ;
+ }
+ _currentstring[i] = 0 ;
+
+// DEBUG_PRINT (1,"get_GE vname: '%s' value: '%s'\n", vname, _currentstring);
+
+ return (_currentstring) ;
+}
+
+
+// ==
+STATUS_TYPE
+nvr_set_OS_variable (
+ PUCHAR vname,
+ PUCHAR value
+)
+{
+ ULONG nameindex ;
+ ULONG valueindex ;
+ ULONG eos ;
+ PUCHAR str ;
+ ULONG count ;
+ CHAR c ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+
+ if ( !pnvrobj || !vname || !value || !(*vname) )
+ return stat_error ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+
+// DEBUG_PRINT (1,"OS vname: '%s' value: '%s'\n", vname, value);
+
+ /* initialize pointer to OS area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->OSAreaAddress) ;
+
+ // find the end of the used OS space by looking for
+ // the first non-null character from the top
+ eos = lhp->OSAreaLength - 1 ;
+ while (aptr[--eos] == 0)
+ {
+ if (eos == 0)
+ break ;
+ }
+
+ // position eos to the first new character, unless
+ // environment space is empty
+ if (eos != 0)
+ eos += 2 ;
+
+ // find out if the variable already has a value
+ count = lhp->OSAreaLength - eos ;
+ if (nvr_find_OS_variable(vname, &nameindex, &valueindex) == stat_ok)
+ {
+ // count free space
+ // start with the free area at the top and add
+ // the old nameindex value
+ for (str = &(aptr[valueindex]) ; *str != 0 ; str++)
+ count++ ;
+
+ // if free area is not large enough to handle new value return error
+ for (str = value ; *str != 0 ; str++)
+ {
+ if ( count-- == 0 )
+ return stat_error ;
+ }
+
+ // pack strings
+ // first move valueindex to the end of the value
+ while (aptr[valueindex++] != 0)
+ ;
+
+ // now move everything to where the variable starts
+ // covering up the old name/value pair
+ while (valueindex < eos)
+ {
+ c = aptr[valueindex++] ;
+ aptr[nameindex++] = c ;
+ }
+
+ // adjust new top of environment
+ eos = nameindex ;
+
+ // zero to the end of OS area
+ while (nameindex < lhp->OSAreaLength)
+ aptr[nameindex++] = 0 ;
+ }
+ else
+ {
+ // variable is new
+ // if free area is not large enough to handle new value return error
+ for (str = value ; *str != 0 ; str++)
+ {
+ if (count-- == 0)
+ return stat_error ;
+ }
+ }
+
+ /* if value is null, we have removed the variable */
+ if (*value)
+ {
+ // insert new name, converting to upper case.
+ while ( *vname )
+ {
+ aptr[eos++] = *vname++ ;
+ }
+ aptr[eos++] = '=' ;
+
+ // insert new value
+ while ( *value )
+ {
+ aptr[eos++] = *value ;
+ value++ ;
+ }
+ }
+
+ nvr_write_OSArea(pnvrobj) ;
+
+ return stat_ok ;
+}
+
+
+// USED_BY_HAL:
+
+// ==
+STATUS_TYPE
+nvr_set_GE_variable (
+ PUCHAR vname,
+ PUCHAR value
+)
+{
+ ULONG nameindex ;
+ ULONG valueindex ;
+ ULONG toe ;
+ PUCHAR str ;
+ ULONG count ;
+ CHAR c ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+
+ if ( !pnvrobj || !vname || !(*vname) )
+ return stat_error ; // invalid input
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+
+ DEBUG_PRINT (3,"set_GE vname: '%s' value: '%s'\n", vname, value) ;
+
+ /* initialize pointer to GE area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+
+ /* find the top of the used environment space by looking for */
+ /* the first non-null character from the top */
+ toe = lhp->GELength - 1 ;
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+ while (aptr[--toe] == 0)
+ {
+ if (toe == 0)
+ break ;
+ }
+
+ /* adjust toe to the first new character, unless */
+ /* environment space is empty */
+ if (toe != 0)
+ toe += 2 ;
+
+ /* find out if the variable already has a value */
+ count = lhp->GELength - toe ;
+
+ if (nvr_find_GE_variable(vname, &nameindex, &valueindex) == stat_ok)
+ {
+ /* count free space */
+ /* start with the free area at the top and add */
+ /* the old nameindex value */
+ for (str = &(aptr[valueindex]) ; *str != 0 ; str++)
+ count++ ;
+
+ /* if free area is not large enough to handle new value return error */
+ if (value)
+ {
+ for (str = value ; *str != 0 ; str++)
+ {
+ if (count-- == 0)
+ return stat_error ;
+ }
+ }
+
+ /* pack strings */
+ /* first move valueindex to the end of the value */
+ while (aptr[valueindex++] != 0)
+ ;
+
+ /* now move everything to where the variable starts */
+ /* covering up the old name/value pair */
+ while (valueindex < toe)
+ {
+ c = aptr[valueindex++] ;
+ aptr[nameindex++] = c ;
+ }
+
+ /* adjust new top of environment */
+ toe = nameindex ;
+
+ /* zero to the end of GE area */
+ while (nameindex < lhp->GELength)
+ aptr[nameindex++] = 0 ;
+ }
+ else
+ {
+ /* variable is new */
+ /* if free area is not large enough to handle new value return error */
+ if (value)
+ {
+ for (str = value ; *str != 0 ; str++)
+ {
+ if (count-- == 0)
+ return stat_error ;
+ }
+ }
+ }
+
+ /* if value is null or is a pointer to a 0 */
+ /* the variable has been removed */
+
+ if ( value && *value )
+ {
+ /* insert new name, converting to upper case */
+ while ( *vname )
+ {
+ aptr[toe] = *vname++ ;
+ toe++ ;
+ }
+ aptr[toe++] = '=' ;
+
+ /* insert new value */
+ while ( *value )
+ {
+ aptr[toe] = *value ;
+ value++ ;
+ toe++ ;
+ }
+ }
+
+ nvr_write_GEArea(pnvrobj) ;
+
+ return stat_ok ;
+}
+
+
+// ==
+PUCHAR
+nvr_fetch_GE (
+ VOID
+)
+{
+ ULONG i ;
+ ULONG toe ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+ PNVRAM_MAP lep ;
+
+ if (!pnvrobj)
+ return NULL ;
+
+ lep = (PNVRAM_MAP) pnvrobj->lend ;
+
+ NvrCopyFill (pnvrobj->lend + (ULONG)lep->Header.GEAddress,
+ lep->Header.GELength) ;
+
+ return (_currentfetch) ;
+}
+
+
+// ==
+ULONG
+nvr_stat_GE (
+ PULONG size
+)
+{
+ ULONG i ;
+ ULONG toe ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+ ULONG free ;
+
+ if ( !pnvrobj )
+ return 0 ;
+
+ /* initialize pointers to GE area */
+ lhp = (HEADER*) pnvrobj->lhead ;
+ aptr = (PUCHAR) ((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+
+ /* return original size to caller */
+ if (size)
+ *size = lhp->GELength ;
+
+ /* find the top of the used environment space by looking for */
+ /* the first non-null character from the top */
+ toe = lhp->GELength - 1 ;
+ free = 0 ;
+ while ((aptr[--toe]) == 0)
+ {
+ free++ ;
+ if (toe == 0)
+ break ;
+ }
+
+ return ( free ) ;
+}
+
+
+// ==
+PUCHAR
+nvr_fetch_OS (
+ VOID
+)
+{
+ ULONG i ;
+ ULONG toe ;
+ PNVRAM_MAP lep ;
+
+ if ( !pnvrobj )
+ return NULL ;
+
+ lep = (PNVRAM_MAP) pnvrobj->lend ;
+
+ NvrCopyFill (pnvrobj->lend + (ULONG)lep->Header.OSAreaAddress,
+ lep->Header.OSAreaLength) ;
+
+ return ( _currentfetch ) ;
+}
+
+
+// ==
+PUCHAR
+nvr_fetch_CF (
+ VOID
+)
+{
+ ULONG i ;
+ PNVRAM_MAP lep ; // LE ptr to NVRAM volatile image
+
+ if ( !pnvrobj )
+ return NULL ;
+
+ lep = (PNVRAM_MAP) pnvrobj->lend ;
+
+ NvrCopyFill (pnvrobj->lend + (ULONG)lep->Header.ConfigAddress,
+ lep->Header.ConfigLength) ;
+
+ return ( _currentfetch ) ;
+}
+
+
+// ==
+VOID
+NvrCopyFill (
+ PVOID src,
+ ULONG srclen
+)
+// Fill the _currentfetch area from the source described, then fill the
+// remainder of the buffer with zeros. The same buffer is used to pass
+// several areas, and it is the callers responsibility to copy each one
+// if required before fetching another area.
+{
+ PUCHAR srcp = (PUCHAR)src ;
+ PUCHAR dstp = _currentfetch ;
+ ULONG dstlen = MAXNVRFETCH ;
+
+ while ( dstlen-- )
+ {
+ if ( srclen )
+ *dstp++ = *srcp++, srclen-- ;
+ else
+ *dstp++ = 0 ;
+ }
+}
+
+
+
+#ifdef _HALNVR_
+/////////////////////////////////////////////////////////////////////////////
+// Resolve references to debug functions provided by ARC that are not part
+// of the HAL environment. Currently these merely disable the debugging
+// features when used in the HAL, but could be expanded later to provide
+// the same features available in ARC.
+/////////////////////////////////////////////////////////////////////////////
+
+VOID
+DEBUG_PRINT (
+ LONG DebugLevelReqd,
+ PCHAR DebugMessage,
+ ...
+)
+{
+}
+
+VOID
+DEBUG_BREAK (
+ LONG DebugLevelReqd
+)
+{
+}
+
+LONG
+DEBUG_GETLEVEL ()
+{
+ return 0 ;
+}
+
+LONG
+DEBUG_GETREGION ()
+{
+ return 0 ;
+}
+
+#endif
+
diff --git a/private/ntos/nthals/halppc/ppc/fwnvr.h b/private/ntos/nthals/halppc/ppc/fwnvr.h
new file mode 100644
index 000000000..c326bc596
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwnvr.h
@@ -0,0 +1,313 @@
+//
+// FWNVR.H
+//
+// Prototypes for FWNVR.C
+// (automatically generated by CPROTO)
+//
+
+#ifndef _CPROTO_FWNVR_
+#define _CPROTO_FWNVR_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+PNVR_OBJECT
+nvr_alloc (
+ ULONG size
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_free (
+ PVOID p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+BOOLEAN
+NvrSetSize (
+ LONG NvramSize // size of NVRAM in bytes if non-zero
+);
+
+
+BOOLEAN
+NvrSetMethod (
+ LONG ForcedValue // if Non-zero, set to this value regardless
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+UCHAR
+nvr_read (
+ ULONG addr
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write (
+ ULONG addr,
+ UCHAR data
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_swap_Header (
+ HEADER* dest,
+ HEADER* src
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_headb2l (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_headl2b (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_default_nvram (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+BOOLEAN
+nvr_read_nvram (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_read_GEArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_read_OSArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_read_CFArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_Header (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_GEArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_OSArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_CFArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+VOID
+nvr_delete_object (
+ VOID
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+PNVR_OBJECT
+nvr_create_object (
+ VOID
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+STATUS_TYPE
+nvr_initialize_object (
+ LONG AccessMethod,
+ ULONG Size // NVR size in bytes
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_clear_nvram (
+ VOID
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+VOID
+nvr_destroy (
+ LONG AccessMethod,
+ ULONG Size // size of NVRAM
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+ULONG
+nvr_computecrc (
+ ULONG oldcrc,
+ UCHAR data
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+USHORT
+nvr_calc1crc (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+USHORT
+nvr_calc2crc (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+VOID
+nvr_print_object (
+ VOID
+);
+
+
+STATUS_TYPE
+nvr_find_variable (
+ PUCHAR VarName, // name of variable to find
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize, // max size of variable array
+ PULONG ni,
+ PULONG vi
+);
+
+
+STATUS_TYPE
+nvr_set_variable (
+ PUCHAR VarName, // name of variable to add/change
+ PUCHAR VarValue, // value to be set into variable
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize // max size of variable array
+);
+
+
+STATUS_TYPE
+nvr_find_OS_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+);
+
+
+STATUS_TYPE
+nvr_find_GE_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+);
+
+
+PUCHAR
+nvr_get_OS_variable (
+ PUCHAR vname
+);
+
+
+PUCHAR
+nvr_get_GE_variable (
+ PUCHAR vname
+);
+
+
+STATUS_TYPE
+nvr_set_OS_variable (
+ PUCHAR vname,
+ PUCHAR value
+);
+
+
+STATUS_TYPE
+nvr_set_GE_variable (
+ PUCHAR vname,
+ PUCHAR value
+);
+
+
+PUCHAR
+nvr_fetch_GE (
+ VOID
+);
+
+
+ULONG
+nvr_stat_GE (
+ PULONG size
+);
+
+
+PUCHAR
+nvr_fetch_OS (
+ VOID
+);
+
+
+PUCHAR
+nvr_fetch_CF (
+ VOID
+);
+
+
+VOID
+NvrCopyFill (
+ PVOID src,
+ ULONG srclen
+);
+
+
+#endif // _CPROTO_FWNVR_
diff --git a/private/ntos/nthals/halppc/ppc/fwstatus.h b/private/ntos/nthals/halppc/ppc/fwstatus.h
new file mode 100644
index 000000000..fd09e6363
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwstatus.h
@@ -0,0 +1,17 @@
+#ifndef _FWSTATUS_H_
+#define _FWSTATUS_H_
+
+typedef enum _status_type {
+ stat_ok = 0,
+ stat_warning = 1,
+ stat_exist = 2,
+ stat_error = 3,
+ stat_badptr = 4,
+ stat_notexist = 5,
+ stat_noentry = 6,
+ stat_checksum = 7,
+ stat_badlength = 8,
+ stat_last = 0x40
+ } STATUS_TYPE;
+
+#endif /* _FWSTATUS_H_ */
diff --git a/private/ntos/nthals/halppc/ppc/halp.h b/private/ntos/nthals/halppc/ppc/halp.h
new file mode 100644
index 000000000..5220e95d8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/halp.h
@@ -0,0 +1,503 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added PPC specific includes
+ Changed paramaters to HalpProfileInterrupt
+ Added function prototype for HalpWriteCompareRegisterAndClear()
+ Added include for ppcdef.h
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+
+
+#include "ppcdef.h"
+
+#include "hal.h"
+#include "pxhalp.h"
+
+#include "xm86.h"
+#include "x86new.h"
+
+#include "pci.h"
+
+
+
+
+//
+// Resource usage information
+//
+
+#define MAXIMUM_IDTVECTOR 255
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+extern ULONG HalpPciMaxBuses; // in pxpcibus.c
+
+
+//
+// Define PER processor HAL data.
+//
+// This structure is assigned the address &PCR->HalReserved which is
+// an array of 16 ULONGs in the architectually defined section of the
+// PCR.
+//
+
+typedef struct {
+ ULONG HardPriority;
+} UNIPROCESSOR_DATA, *PUNIPROCESSOR_DATA;
+
+#define HALPCR ((PUNIPROCESSOR_DATA)&PCR->HalReserved)
+
+#define HalpGetProcessorVersion() KeGetPvr()
+
+//
+// Override standard definition of _enable/_disable for errata 15.
+//
+
+#if defined(_enable)
+
+#undef _enable
+#undef _disable
+
+#endif
+
+#if _MSC_VER < 1000
+
+//
+// MCL
+//
+
+VOID __builtin_set_msr(ULONG);
+ULONG __builtin_get_msr(VOID);
+VOID __builtin_eieio();
+VOID __builtin_isync();
+
+#define _enable() \
+ __builtin_set_msr(__builtin_get_msr() | 0x00008000)
+
+#define _disable() \
+ __builtin_set_msr(__builtin_get_msr() & 0xFFFF7FFF)
+
+#define ERRATA15WORKAROUND() __builtin_isync()
+
+#else
+
+//
+// VC++
+//
+
+#define _enable() \
+ (__sregister_set(_PPC_MSR_, __sregister_get(_PPC_MSR_) | 0x00008000))
+#define _disable() \
+ (__sregister_set(_PPC_MSR_, __sregister_get(_PPC_MSR_) & 0xffff7fff))
+
+//
+// Errata 15 can use a cror 0,0,0 instruction which is kinder/gentler
+// than an isync.
+//
+
+#define ERRATA15WORKAROUND() __emit(0x4c000382)
+
+#endif
+
+#if !defined(WOODFIELD)
+
+#define HalpEnableInterrupts() _enable()
+#define HalpDisableInterrupts() _disable()
+
+#else
+
+#define HalpEnableInterrupts() (_enable(),ERRATA15WORKAROUND())
+#define HalpDisableInterrupts() (_disable(),ERRATA15WORKAROUND())
+
+#endif
+
+#define KeFlushWriteBuffer() __builtin_eieio()
+
+//
+// Bus handlers
+//
+
+
+PBUS_HANDLER HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN BUS_DATA_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpAllocateConfigSpace HalpAllocateBusHandler
+
+#define HalpHandlerForBus HaliHandlerForBus
+
+#define SPRANGEPOOL NonPagedPool // for now, until crashdump is fixed
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+PSUPPORTED_RANGES
+HalpMergeRanges (
+ IN PSUPPORTED_RANGES Parent,
+ IN PSUPPORTED_RANGES Child
+ );
+
+VOID
+HalpMergeRangeList (
+ PSUPPORTED_RANGE NewList,
+ PSUPPORTED_RANGE Source1,
+ PSUPPORTED_RANGE Source2
+ );
+
+PSUPPORTED_RANGES
+HalpConsolidateRanges (
+ PSUPPORTED_RANGES Ranges
+ );
+
+PSUPPORTED_RANGES
+HalpAllocateNewRangeList (
+ VOID
+ );
+
+VOID
+HalpFreeRangeList (
+ PSUPPORTED_RANGES Ranges
+ );
+
+PSUPPORTED_RANGES
+HalpCopyRanges (
+ PSUPPORTED_RANGES Source
+ );
+
+VOID
+HalpAddRangeList (
+ IN OUT PSUPPORTED_RANGE DRange,
+ OUT PSUPPORTED_RANGE SRange
+ );
+
+VOID
+HalpAddRange (
+ PSUPPORTED_RANGE HRange,
+ ULONG AddressSpace,
+ LONGLONG SystemBase,
+ LONGLONG Base,
+ LONGLONG Limit
+ );
+
+VOID
+HalpRemoveRanges (
+ IN OUT PSUPPORTED_RANGES Minuend,
+ IN PSUPPORTED_RANGES Subtrahend
+ );
+
+VOID
+HalpRemoveRangeList (
+ IN OUT PSUPPORTED_RANGE Minuend,
+ IN PSUPPORTED_RANGE Subtrahend
+ );
+
+
+VOID
+HalpRemoveRange (
+ PSUPPORTED_RANGE HRange,
+ LONGLONG Base,
+ LONGLONG Limit
+ );
+
+VOID
+HalpDisplayAllBusRanges (
+ VOID
+ );
+
+
+//
+// Define function prototypes.
+//
+
+// begin POWER_MANAGEMENT
+
+VOID
+HalInitSystemPhase2(
+ VOID
+ );
+// end POWER_MANAGEMENT
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpCopyBiosShadow(
+ VOID
+ );
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ ULONG VideoDeviceBusNumber,
+ ULONG VideoDeviceSlotNumber
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+BOOLEAN
+HalpCacheSweepSetup(
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+KINTERRUPT_MODE
+HalpGetInterruptMode(
+ ULONG,
+ KIRQL,
+ KINTERRUPT_MODE
+ );
+
+VOID
+HalpSetInterruptMode(
+ ULONG,
+ KIRQL
+ );
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG,
+ ULONG
+ );
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ );
+
+VOID
+HalpHandleIoError (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ );
+
+BOOLEAN
+HalpHandleProfileInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitSuperIo(
+ VOID
+ );
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ );
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableLength,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ );
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+VOID
+HalpPhase0DiscoverPciBuses(
+ IN PCONFIGURATION_COMPONENT_DATA Component
+ );
+
+
+#ifdef POWER_MANAGEMENT
+VOID
+HalpInitInterruptController (
+ VOID
+ );
+
+VOID
+HalpInitDmaController (
+ VOID
+ );
+
+VOID
+HalpRemakeBeep (
+ VOID
+ );
+
+VOID
+HalpResetProfileInterval (
+ VOID
+ );
+
+#endif // POWER_MANAGEMENT
+
+VOID
+HalpProcessorIdle(
+ VOID
+ );
+
+VOID
+HalpSetDpm(
+ VOID
+ );
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KAFFINITY HalpIsaBusAffinity;
+extern ULONG HalpProfileCount;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+
+#define IRQ_VALID 0x01
+#define IRQ_PREFERRED 0x02
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halppc/ppc/ibmppc.h b/private/ntos/nthals/halppc/ppc/ibmppc.h
new file mode 100644
index 000000000..a110f90bf
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/ibmppc.h
@@ -0,0 +1,60 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ ibmppc.h
+
+Abstract:
+
+ This header file defines the enumerated types and "strings" used
+ to identify the various IBM PowerPC (PReP/CHRP) machines.
+
+
+Author:
+
+ Peter Johnston
+
+
+Revision History:
+
+--*/
+
+//
+// Define systems understoof by the "multi" system HAL.
+//
+
+typedef enum _IBM_SYSTEM_TYPES {
+ IBM_UNKNOWN,
+ IBM_VICTORY,
+ IBM_DORAL,
+ IBM_TIGER
+} IBM_SYSTEM_TYPE;
+
+extern IBM_SYSTEM_TYPE HalpSystemType;
+
+//
+// The following strings are passed in from ARC in the
+// SystemClass/ArcSystem registry variable.
+//
+// The following entries are examined for an EXACT match.
+
+#define SID_IBM_SANDAL "IBM-6015"
+#define SID_IBM_WOOD "IBM-6020"
+#define SID_IBM_WILTWICK "IBM-6040"
+#define SID_IBM_WOODPRIME "IBM-6042"
+#define SID_IBM_CAROLINA "IBM-6070"
+#define SID_IBM_OXFORD "IBM-6035"
+#define SID_IBM_VICTORY "IBM-VICT"
+#define SID_IBM_DORAL "IBM-7043"
+#define SID_IBM_TERLINGUA "IBM-7442"
+#define SID_IBM_HARLEY "IBM-Harley"
+#define SID_IBM_KONA "IBM-Kona"
+#define SID_IBM_ZAPATOS "IBM-Zapatos"
+#define SID_IBM_TIGER "IBM-7042"
+
+// If comparisons against the above failed, we check for
+// entries that start with the following.
+
+#define SID_IBM_DORAL_START "IBM PPS Model 7043"
+#define SID_IBM_TERLINGUA_START "IBM PPS Model 7442"
diff --git a/private/ntos/nthals/halppc/ppc/pcip.h b/private/ntos/nthals/halppc/ppc/pcip.h
new file mode 100644
index 000000000..ea4d55264
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pcip.h
@@ -0,0 +1,186 @@
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PVOID Address;
+ PVOID Data;
+ ULONG Fill0;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/prepnvr.h b/private/ntos/nthals/halppc/ppc/prepnvr.h
new file mode 100644
index 000000000..93c8c09bc
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/prepnvr.h
@@ -0,0 +1,134 @@
+/* Structure map for NVRAM on PowerPC Reference Platform */
+
+/* Revision 1 changes (8/25/94):
+ - Power Management (RESTART_BLOCK struct)
+ - Normal added to PM_MODE
+ - OSIRQMask (HEADER struct) */
+
+/* All fields are either character/byte strings which are valid either
+endian or they are big-endian numbers.
+
+There are a number of Date and Time fields which are in RTC format,
+big-endian. These are stored in UT (GMT).
+
+For enum's: if given in hex then they are bit significant, i.e. only
+one bit is on for each enum.
+*/
+
+#ifndef _NVRAM_
+#define _NVRAM_
+
+#define NVSIZE 4096 /* size of NVRAM */
+#define OSAREASIZE 512 /* size of OSArea space */
+#define CONFSIZE 1024 /* guess at size of Configuration space */
+
+typedef struct _SECURITY {
+ unsigned long BootErrCnt; /* Count of boot password errors */
+ unsigned long ConfigErrCnt; /* Count of config password errors */
+ unsigned long BootErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long ConfigErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long BootCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long ConfigCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long BootSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned long ConfigSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned char Serial[16]; /* Box serial number */
+ } SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ WPOS2 = 4,
+ WPAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ Netware = 8,
+ USL = 9,
+ Low_End_Client = 10,
+ SCO = 11
+ } OS_ID;
+
+typedef struct _ERROR_LOG {
+ unsigned char ErrorLogEntry[40]; /* To be architected */
+ } ERROR_LOG;
+
+/*---Revision 1: Change the following struct:---*/
+typedef struct _RESUME_BLOCK {
+ /* Hibernation Resume Device will be an
+ environment variable */
+ unsigned long CheckSum; /* Checksum of RESUME_BLOCK */
+ volatile unsigned long BootStatus;
+
+ void * ResumeAddr; /* For Suspend Resume */
+ void * SaveAreaAddr; /* For Suspend Resume */
+ unsigned long SaveAreaLength; /* For Suspend Resume */
+
+ unsigned long HibResumeImageRBA; /* RBA (512B blocks) of compressed OS
+ memory image to be loaded by FW
+ on Resume from hibernation */
+ unsigned long HibResumeImageRBACount; /* Size of image in 512B blocks*/
+ unsigned long Reserved;
+ } RESUME_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+ } OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80, /* Part of state is in memory */
+ Hibernate = 0x40, /* Nothing in memory - state saved elsewhere */
+/* Revision 1: Normal added (actually was already here) */
+ Normal = 0x00 /* No power management in effect */
+ } PMMode;
+
+typedef struct _HEADER {
+ unsigned short Size; /* NVRAM size in K(1024) */
+ unsigned char Version; /* Structure map different */
+ unsigned char Revision; /* Structure map the same -
+ may be new values in old fields
+ in other words old code still works */
+ unsigned short Crc1; /* check sum from beginning of nvram to OSArea */
+ unsigned short Crc2; /* check sum of config */
+ unsigned char LastOS; /* OS_ID */
+ unsigned char Endian; /* B if big endian, L if little endian */
+ unsigned char OSAreaUsage; /* OSAREA_USAGE */
+ unsigned char PMMode; /* Shutdown mode */
+ RESUME_BLOCK ResumeBlock;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+/* Global Environment information */
+ void * GEAddress;
+ unsigned long GELength;
+ /* Date&Time from RTC of last change to Global Environment */
+ unsigned long GELastWriteDT[2];
+
+/* Configuration information */
+ void * ConfigAddress;
+ unsigned long ConfigLength;
+ /* Date&Time from RTC of last change to Configuration */
+ unsigned long ConfigLastWriteDT[2];
+ unsigned long ConfigCount; /* Count of entries in Configuration */
+
+/* OS dependent temp area */
+ void * OSAreaAddress;
+ unsigned long OSAreaLength;
+ /* Date&Time from RTC of last change to OSAreaArea */
+ unsigned long OSAreaLastWriteDT[2];
+
+/* Revision 1: add this mask - function tbd */
+ /*unsigned short OSIRQMask; OS to FW IRQ Mask - "I've used this one" */
+ } HEADER;
+
+
+/* Here is the whole map of the NVRAM */
+typedef struct _NVRAM_MAP {
+ HEADER Header;
+ unsigned char GEArea[NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER)];
+ unsigned char OSArea[OSAREASIZE];
+ unsigned char ConfigArea[CONFSIZE];
+ } NVRAM_MAP;
+
+#endif /* ndef _NVRAM_ */
diff --git a/private/ntos/nthals/halppc/ppc/pxbbl.c b/private/ntos/nthals/halppc/ppc/pxbbl.c
new file mode 100644
index 000000000..8584c693e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbbl.c
@@ -0,0 +1,1546 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxbbl.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a GXT150P (Baby Blue) video adapter.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "string.h"
+
+// Include GXT150P header file information
+#include "bblrastz.h"
+#include "bblrmdac.h"
+#include "bbldef.h"
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+extern POEM_FONT_FILE_HEADER HalpFontHeader;
+extern ULONG HalpPciMaxSlots;
+
+extern UCHAR TextPalette[];
+
+
+#define TAB_SIZE 4
+
+VOID
+HalpDisplayPpcBBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBBL (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterBBL(
+ IN PUCHAR Glyph
+ );
+
+BOOLEAN
+BBLGetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN PULONG reg_value
+ );
+
+BOOLEAN
+BBLSetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN ULONG reg_value
+ );
+
+VOID
+BBLScrollScreen(
+ VOID
+ );
+
+BOOLEAN
+BBLInitialize (
+ ULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ );
+
+BOOLEAN
+BBLGetMonitorID (
+ PULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ );
+
+VOID
+BBLWaitForVerticalSync (
+ volatile PUCHAR HalpBBLRegisterBase
+ );
+
+
+VOID
+HalpDisplayPpcBBLSetup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GXT150P Graphics Adapter
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG rc, status, monID, count, value;
+ volatile PUCHAR HalpBBLRegisterBase = (PUCHAR)0;
+ ULONG buffer[(BBL_BELE_VAL + 2) >> 2];
+ PPCI_COMMON_CONFIG PciData;
+ PCI_SLOT_NUMBER PciSlot;
+ bbl_mon_data_t *bbl_mon_data_ptr;
+ BOOLEAN found, ok;
+ PHYSICAL_ADDRESS physaddr;
+
+ PHYSICAL_ADDRESS bbl_phys_address;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ //
+ // There is no need to have both the register space and the
+ // DFA space mapped at the same time. This will save us from
+ // having multiple I/O spaces mapped at the same time. Thus
+ // saving DBATs which are in very very short supply...
+ //
+
+ //
+ // Strategy:
+ //
+ // 1. Map the PCI configuration register space
+ // 2. Update the PCI configuration registers
+ // 3. Unmap the PCI configuration register space
+ // 4. Map the register space
+ // 5. Reset the device
+ // 6. Read the monitor ID to figure what resolution and refresh mode to use
+ // 7. Perform device re-initialization (rasterizer, ramdac,
+ // and color palette)
+ // 8. Unmap the register space
+ // 9. Map the DFA space
+ // 10. Clear out VRAM to the default background color
+ // 11. Now can do character blits
+ //
+
+ /*******************************************************************/
+ /* S E T P C I C O N F I G U R A T I O N R E G I S T E R S */
+ /*******************************************************************/
+
+ bbl_phys_address.HighPart = 0x0; //PCI bus devices are in a 32-bit memory space
+
+ ok = BBLGetConfigurationRegister (BBL_DEV_VEND_ID,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]),
+ &bbl_phys_address.LowPart );
+
+ bbl_phys_address.LowPart += PCI_MEMORY_PHYSICAL_BASE; // translate bus-relative address
+
+ if(ok == TRUE){
+ value = BBL_BELE_VAL;
+ ok = BBLSetConfigurationRegister (BBL_DEV_VEND_ID, 0x70, value );
+ }
+ if(ok == FALSE){
+ return;
+ }
+
+ /**************************************************/
+ /* M A P T H E R E G I S T E R S P A C E */
+ /**************************************************/
+
+ //
+ // Map the the adapter register range into memory. Please note that this
+ // adapter will respond to all 256meg of addresses in the address range
+ // given even though we are only temporarily mapping a small region
+ //
+
+
+ if (HalpInitPhase == 0) {
+
+ BBL_DBG_PRINT("call KePhase0MapIo() to map the reg space. Phys=0x%x Len=0x%x %d\n",
+ bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET,
+ BBL_REG_ADDR_LENGTH,
+ BBL_REG_ADDR_LENGTH);
+
+ HalpBBLRegisterBase = (PUCHAR)KePhase0MapIo(bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET,
+ BBL_REG_ADDR_LENGTH); // 4 K
+ } else {
+ physaddr.HighPart = 0;
+ physaddr.LowPart = bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET;
+ HalpBBLRegisterBase = (PUCHAR)MmMapIoSpace(physaddr,
+ BBL_REG_ADDR_LENGTH,
+ FALSE);
+ }
+
+ BBL_DBG_PRINT("HalpBBLRegisterBase = 0x%x\n", HalpBBLRegisterBase);
+
+
+ /**************************************************/
+ /* F I N D F O N T T O U S E */
+ /**************************************************/
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+ BBL_DBG_PRINT("PixelWidth = %d PixelHeight = %d\n HalpFontHeader = 0x%x\n",
+ HalpFontHeader->PixelWidth, HalpFontHeader->PixelHeight, HalpFontHeader);
+
+ /*********************************************/
+ /* D I S A B L E V I D E O D I S P L A Y */
+ /*********************************************/
+
+ //
+ // Turn off display outputs from the ramdac so the screen will go
+ // blank while resetting the adapter and resetting it up
+ //
+
+ /*
+ * Disable Video
+ */
+
+ BBL_DBG_PRINT ("disable video display\n");
+
+ /* Set the ramdac configuration to default values and disable */
+ /* display outputs so nothing is displayed on the screen during */
+ /* initialization */
+
+ /* Config low ... */
+ BBL_DBG_PRINT ("Write config register low = 0x%x\n", 0x00);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_LOW_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x00 );
+
+ /* Config high ... */
+ BBL_DBG_PRINT ("Write config register high = 0x%x\n", 0x08);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_HIGH_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x08 );
+
+
+ /*********************************************/
+ /* R E S E T C A R D */
+ /*********************************************/
+
+ //
+ // Attempt to reset the card. The only this can be done is to first
+ // read the status register, if the status register indicates that the
+ // FIFO is empty and the adapter is idle, then we're good-to-go. If
+ // the adapter is busy and the FIFO is empty, send a RESET_CURRENT_CMD
+ // down the FIFO and see if the adapter becomes idle. If the adapter
+ // does not become idle after a few milliseconds, send 0x0's down the
+ // command port checking status in between each time for adapter idle.
+ // If, after sending down many 0x0's, or if the adapter FIFO was originally
+ // not empty, we have a hung adapter, and there is absolutely nothing
+ // that we can do, which means we're dead, so return
+ //
+
+ status = BBL_GET_REG(BBL_REG_BASE, BBL_STATUS_REG);
+ if(status & BBL_CACHE_LINE_BUFFER_EMPTY){
+ BBL_DBG_PRINT("adapter FIFO is empty\n");
+ if(status & BBL_ADAPTER_BUSY){
+ BBL_DBG_PRINT("adapter is busy, attempting reset\n");
+ // Send down a RESET_CURRENT_COMMAND to the adapter
+ BBL_SET_REG(BBL_REG_BASE, BBL_RESET_CURRENT_CMD_REG, 0x0);
+ BBL_EIEIO;
+ // Wait to see if the adapter comes back
+ for(count=0;((count < 100000)&&(status & BBL_ADAPTER_BUSY));count++){
+ status = BBL_GET_REG(BBL_REG_BASE, BBL_STATUS_REG);
+ }
+ // If adapter still is busy, attempt sending 0x0's to the
+ // command port to force it to finish whatever it was doing last
+ if(status & BBL_ADAPTER_BUSY){
+ BBL_DBG_PRINT("adapter is still busy, attempting to send NULL command data\n");
+ for(count=0;((count < 10000)&&(status & BBL_ADAPTER_BUSY));count++){
+ BBL_SET_REG(BBL_REG_BASE, BBL_CMD_DATA_REG, 0x0);
+ status = BBL_GET_REG(BBL_REG_BASE, BBL_STATUS_REG);
+ }
+ // If we're still hung, we're dead, so just return
+ if(status & BBL_ADAPTER_BUSY){
+ BBL_DBG_PRINT("adapter hung, giving up\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }else{
+ BBL_DBG_PRINT("adapter is NOT busy, sent NULL cmd/data down for %d loops\n", count);
+ }
+ }else{
+ BBL_DBG_PRINT("adapter is NOT busy, waited for %d loops\n", count);
+ }
+ }else{
+ BBL_DBG_PRINT("adapter is NOT busy\n");
+ }
+ }else{
+ // The adapter FIFO is not empty which indicates that it is hung, so return
+ BBL_DBG_PRINT("adapter FIFO is not empty\n");
+ BBL_DBG_PRINT("adapter hung, giving up\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ /*********************************************/
+ /* G E T M O N I T O R I D */
+ /*********************************************/
+
+ //
+ // Read the monitor ID from the card to determine what resolution
+ // to use
+ //
+
+ if(BBLGetMonitorID(&monID, HalpBBLRegisterBase) == FALSE){
+ BBL_DBG_PRINT("BBLGetMonitorID() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ //
+ // Find the correct monitor ID information structure based on
+ // the monitor ID returned from the BBLGetMonitorID() function
+ //
+
+ // Find the monitor info structure from the monitor table
+ // Search for matching monitor ID */
+ bbl_mon_data_ptr = &bbl_mon_data[0];
+ do{
+ if(bbl_mon_data_ptr->monitor_id == monID)
+ break;
+ ++bbl_mon_data_ptr;
+ }while(bbl_mon_data_ptr->monitor_id != BBL_MT_DEFAULT);
+
+ // If we did not find our ID in the table, use the default
+ // The last entry in the table is the default entry...
+
+ BBL_DBG_PRINT("&bbl_mon_data[0]=0x%x bbl_mon_data_ptr=0x%x\n",
+ &bbl_mon_data[0], bbl_mon_data_ptr);
+
+
+ /*********************************************/
+ /* S E T H A L V A R I A B L E S */
+ /*********************************************/
+
+ //
+ // set the correct horizontal and vertical resolutions for HAL
+ //
+
+ HalpHorizontalResolution = bbl_mon_data_ptr->x_res;
+ HalpVerticalResolution = bbl_mon_data_ptr->y_res;
+ BBL_DBG_PRINT("HalpHorizontalResolution = %d HalpVerticalResolution = %d\n",
+ HalpHorizontalResolution, HalpVerticalResolution);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ // GXT150P real scanline length is hardcoded at 2048 pixels independent
+ // of the resolution on the screen
+ HalpScrollLine =
+ BBL_SCANLINE_LENGTH * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+ BBL_DBG_PRINT("DisplayText = %d ScrollLine = %d ScrollLength = %d DisplayWidth = %d\n",
+ HalpDisplayText, HalpScrollLine, HalpScrollLength, HalpDisplayWidth);
+
+
+ /**************************************************/
+ /* R E I N I T I A L I Z E T H E C A R D */
+ /**************************************************/
+
+ //
+ // Initialize the adapter card for the resolution found by looking
+ // at the monitor ID
+ //
+
+ if(BBLInitialize(monID, HalpBBLRegisterBase) == FALSE){
+ BBL_DBG_PRINT("BBLInitialize(monID=0x%x) failed\n", monID);
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ /*********************************************/
+ /* U N M A P R E G I S T E R S P A C E */
+ /*********************************************/
+
+ //
+ // Unmap the the adapter register range from memory. Please note that this
+ // adapter will respond to all 256meg of addresses in the address range
+ // given even though we are only temporarily mapping a small region
+ //
+
+ if (HalpInitPhase == 0) {
+
+ if (HalpBBLRegisterBase) {
+ BBL_DBG_PRINT("call KePhase0DeleteIoMap() to unmap the reg space. Phys=0x%x Len=0x%x %d\n",
+ bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET, BBL_REG_ADDR_LENGTH, BBL_REG_ADDR_LENGTH);
+ KePhase0DeleteIoMap(bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET, BBL_REG_ADDR_LENGTH);
+ HalpBBLRegisterBase = 0x0;
+ }
+ }
+
+
+ /*************************************************/
+ /* M A P F R A M E B U F F E R S P A C E */
+ /*************************************************/
+
+ //
+ // Map in the frame buffer memory which is used to write characters to
+ // the screen. Please note that this adapter will respond to all 256meg
+ // of addresses in the address range
+ //
+
+ if (HalpInitPhase == 0) {
+
+ BBL_DBG_PRINT("call KePhase0MapIo() to map the FB_A space. Phys=0x%x Len=0x%x %d\n",
+ bbl_phys_address.LowPart + BBL_VIDEO_MEMORY_OFFSET,
+ BBL_VIDEO_MEMORY_LENGTH,
+ BBL_VIDEO_MEMORY_LENGTH);
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(bbl_phys_address.LowPart + BBL_VIDEO_MEMORY_OFFSET,
+ BBL_VIDEO_MEMORY_LENGTH); // 2 MB
+ }
+
+ BBL_DBG_PRINT("HalpVideoMemoryBase = 0x%x\n", HalpVideoMemoryBase);
+
+
+ /*********************************************/
+ /* M I S C A N D R E T U R N */
+ /*********************************************/
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ BBL_DBG_PRINT("leaving HalpDisplayPpcBBLSetup()\n");
+ return;
+
+} //end of HalpDisplayPpcBBLSetup
+
+
+BOOLEAN
+BBLInitialize (
+ ULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ Sets up the rasterizer and ramdac registers to the particular
+ resolution and refresh rate selected for the GXT150P card
+
+Arguments:
+
+ monID -- indicates the resolution and refresh rate to use
+
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+--*/
+
+{
+ bbl_mon_data_t *bbl_mon_data_ptr;
+ int i;
+ UCHAR bbl_clut[256*3];
+
+ BBL_DBG_PRINT("Entering BBLInitialize: monID = 0x%x\n", monID);
+
+ // Find the monitor info structure from the monitor table
+
+ // Search for matching monitor ID */
+ bbl_mon_data_ptr = &bbl_mon_data[0];
+ do{
+ if(bbl_mon_data_ptr->monitor_id == monID)
+ break;
+ ++bbl_mon_data_ptr;
+ }while(bbl_mon_data_ptr->monitor_id != BBL_MT_DEFAULT);
+
+ // If we did not find our ID in the table, use the default
+ // The last entry in the table is the default entry...
+
+ BBL_DBG_PRINT("&bbl_mon_data[0]=0x%x bbl_mon_data_ptr=0x%x\n",
+ &bbl_mon_data[0], bbl_mon_data_ptr);
+
+ //
+ // Card has already been RESET and the display outputs been
+ // turned off
+ //
+
+ /*************************************************************/
+ /* B E G I N R A S T R E G I S T E R S E T U P */
+ /*************************************************************/
+
+
+ /*
+ * write Memory Configuration register
+ *
+ */
+
+ BBL_DBG_PRINT ("Writing memory config register = 0x%x\n", 0x0c);
+ BBL_SET_REG( BBL_REG_BASE, BBL_CONFIG_REG, 0x0c );
+
+ /*
+ * set Interrupt Enable register
+ * disable all interrupts
+ */
+
+ BBL_DBG_PRINT ("Disable all interrupts....\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_INTR_ENABLE_STATUS_REG, 0x70);
+
+ /*
+ * set Control register
+ *
+ */
+
+ BBL_DBG_PRINT ("Writing control register = 0x%x\n", 0x01);
+ BBL_SET_REG( BBL_REG_BASE, BBL_CNTL_REG, 0x01 );
+
+
+ /****************************************/
+ /* B E G I N R A M D A C S E T U P */
+ /****************************************/
+
+ /*
+ * Turn off Hardware Cursor
+ */
+
+ BBL_DBG_PRINT ("writing ICON Cursor control reg = DISABLE\n");
+ BBL_SET_ICON_CURSOR_CNTL( BBL_REG_BASE, 0x00);
+
+
+ /***********************/
+ /* S E T U P C R T C */
+ /***********************/
+
+
+ /*
+ * setup CRTC values
+ */
+
+ BBL_DBG_PRINT ("\nSetup_CRTC:\n");
+
+
+ /*
+ * set PLL Reference register = 0x19
+ * set up PLL for reference frequency of 50Mhz.
+ */
+
+
+ BBL_DBG_PRINT ("Set PLL Reference register at offset 0x%x = 0x%x\n",
+ BBL_RAMDAC_PLL_REF_REG, 0x19);
+ BBL_SET_PLL_REF_REG(BBL_REG_BASE, 50);
+
+
+ /*
+ * PLL VCO Divider Register -
+ */
+
+ BBL_DBG_PRINT ("Set VCO_DIVIDER = 0x%x\n",
+ bbl_mon_data_ptr->pixel_freq);
+ BBL_SET_PLL_VCO_DIVIDER_REG( BBL_REG_BASE,
+ bbl_mon_data_ptr->pixel_freq );
+
+ /*
+ * CRT Control Register -
+ */
+ BBL_DBG_PRINT ("Set DTG_CNTL=0x%x\n",
+ bbl_mon_data_ptr->crt_cntl);
+ BBL_SET_CRT_CNTL_REG( BBL_REG_BASE,
+ bbl_mon_data_ptr->crt_cntl);
+
+ /*
+ * Horizontal Total Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_TOTAL=0x%x\n",
+ bbl_mon_data_ptr->hrz_total);
+ BBL_SET_HORIZONTAL_TOTAL_REG( BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_total);
+
+ /*
+ * Horizontal Display End Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_DISP_END=0x%x\n",
+ (bbl_mon_data_ptr->x_res - 1));
+ BBL_SET_HORIZONTAL_DISPLAY_END_REG( BBL_REG_BASE,
+ (bbl_mon_data_ptr->x_res - 1));
+
+ /*
+ * Horizontal Sync Start Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_SYNC_START=0x%x\n",
+ bbl_mon_data_ptr->hrz_sync_start);
+ BBL_SET_HORIZONTAL_SYNC_START_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_sync_start);
+
+ /*
+ * Horizontal Sync End1 Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_SYNC_END1=0x%x\n",
+ bbl_mon_data_ptr->hrz_sync_end1);
+ BBL_SET_HORIZONTAL_SYNC_END1_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_sync_end1);
+
+ /*
+ * Horizontal Sync End2 Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_SYNC_END2=0x%x\n",
+ bbl_mon_data_ptr->hrz_sync_end2);
+ BBL_SET_HORIZONTAL_SYNC_END2_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_sync_end2);
+
+ /*
+ * Vertical Total Register -
+ */
+ BBL_DBG_PRINT ("Set VERT_TOTAL=0x%x\n",
+ bbl_mon_data_ptr->vrt_total);
+ BBL_SET_VERTICAL_TOTAL_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->vrt_total);
+
+ /*
+ * Vertical Display End Register -
+ */
+ BBL_DBG_PRINT ("Set VRT_DISP_END=0x%x\n",
+ (bbl_mon_data_ptr->y_res - 1));
+ BBL_SET_VERTICAL_DISPLAY_END_REG( BBL_REG_BASE,
+ (bbl_mon_data_ptr->y_res - 1));
+
+ /*
+ * Vertical Sync Start Register -
+ */
+ BBL_DBG_PRINT ("Set VERT_SYNC_STRT=0x%x\n",
+ bbl_mon_data_ptr->vrt_sync_start);
+ BBL_SET_VERTICAL_SYNC_START_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->vrt_sync_start);
+
+ /*
+ * Vertical Sync End Register -
+ */
+ BBL_DBG_PRINT ("Set VERT_SYNC_END=0x%x\n",
+ bbl_mon_data_ptr->vrt_sync_end);
+ BBL_SET_VERTICAL_SYNC_END_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->vrt_sync_end);
+
+
+ /*******************************************/
+ /* F I N I S H R A M D A C S E T U P */
+ /*******************************************/
+
+
+ /*
+ * set configuration register low
+ */
+
+ BBL_DBG_PRINT ("Setting up config low register=0x%x\n", 0x31);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_LOW_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x31 );
+
+ /*
+ * set Configuration high register
+ */
+
+ BBL_DBG_PRINT ("Writing RAMDAC config register high = 0x%x\n", 0x68);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_HIGH_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x68 );
+
+ /* Set the RGB format register */
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_RGB_FORMAT_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x00 );
+
+ /*
+ * set WID/OVRLY Mask register = 0x0f
+ */
+
+ BBL_DBG_PRINT ("WID/OVRLY mask register = 0x%x\n",
+ BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE);
+
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_WID_OL_MASK_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE,
+ BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE );
+
+ /*
+ * Set Pixel Mask
+ */
+
+ BBL_DBG_PRINT ("Writing Pixel Mask register = 0x%x\n",
+ BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE);
+ BBL_SET_RAMDAC_FB_PIXEL_MASK_REG( BBL_REG_BASE,
+ BBL_DEFAULT_VRAM_PIXEL_MASK_VALUE );
+
+
+ /*******************/
+ /* S E T W A T S */
+ /*******************/
+
+ /*
+ * Load the default WAT
+ */
+
+ BBL_DBG_PRINT ("update WAT\n");
+
+ BBL_SET_RAMDAC_ADDRESS_REGS ( BBL_REG_BASE,
+ BBL_RAMDAC_WAT_START_ADDR );
+ for(i=0;i<BBL_RAMDAC_WAT_LENGTH;i++){
+ BBL_SET_RAMDAC_DATA_NON_LUT ( BBL_REG_BASE, 0x10);
+ BBL_SET_RAMDAC_DATA_NON_LUT ( BBL_REG_BASE, 0x00);
+ }
+
+
+ /*************************************/
+ /* S E T C O L O R P A L E T T E */
+ /*************************************/
+
+ BBL_DBG_PRINT ("update colormap\n");
+
+ /*
+ * Set the colormap
+ */
+
+ for(i=0; i<256; i++){
+ if((TextPalette[i] == 16)||
+ (TextPalette[i] == 32)||
+ (TextPalette[i] == 63)){
+ bbl_clut[i] = TextPalette[i] * 4;
+ }else{
+ bbl_clut[i] = TextPalette[i];
+ }
+ }
+
+ BBL_DBG_PRINT ("updating colormap\n");
+ BBL_LOAD_FB_COLOR_PALETTE(BBL_REG_BASE, 0,
+ BBL_RAMDAC_FB_LUT_LENGTH, &bbl_clut[0]);
+
+ /************************************************************/
+ /* F I N I S H R A S T R E G I S T E R S E T U P */
+ /************************************************************/
+
+ /*
+ * set PIXEL MASK register = 0xffffffff
+ */
+
+ BBL_DBG_PRINT ("Writing Pixel Mask register = 0xFFFFFFFF\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_PIXEL_MASK_REG, 0xFFFFFFFF);
+
+ /*
+ * set Write Plane Mask register = 0xff
+ */
+
+ BBL_DBG_PRINT ("Writing Plane Mask register = 0x%x\n", 0xFF);
+ BBL_SET_REG( BBL_REG_BASE, BBL_PLANE_MASK_REG, 0xFF);
+
+
+ /*
+ * Disable Line Style Dash 1234
+ */
+
+ BBL_DBG_PRINT ("disable line style dash 1234 register\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_LINE_STYLE_DASH_1234_REG, 0x00);
+
+ /*
+ * Disable Line Style Dash 5678
+ */
+
+ BBL_DBG_PRINT ("disable line style dash 5678 register\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_LINE_STYLE_DASH_5678_REG, 0x00);
+
+
+ /*
+ * Disable Scissors
+ */
+
+ BBL_DBG_PRINT ("Disable scissors\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_SCISSOR_ENABLE_REG, 0x0);
+
+ /*
+ * set Window Origin Offset register ( x = 0, y = 0 )
+ */
+
+ BBL_DBG_PRINT ("setting Window origin 0,0\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_WIN_ORIGIN_OFFSETS_REG, 0x0);
+
+ /*
+ * set Window ID and Clip Test register = DISABLE
+ */
+
+ BBL_DBG_PRINT ("setting Window ID and Clip Test register = DISABLE\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_WID_CLIP_TEST_REG, 0x0);
+
+ /*******************************/
+ /* C L E A R O U T V R A M */
+ /*******************************/
+
+ /*
+ * set Foreground register
+ */
+
+ BBL_DBG_PRINT ("Writing Foreground register = 0x%x\n", 0x0);
+ BBL_SET_REG( BBL_REG_BASE, BBL_FG_REG, 0x0);
+
+ /*
+ * set Background register
+ */
+
+ BBL_DBG_PRINT ("Writing Background register = 0x%x\n", 0x0);
+ BBL_SET_REG( BBL_REG_BASE, BBL_BG_REG, 0x0);
+
+ /*
+ * set destination to WID planes
+ */
+
+ BBL_SET_REG( BBL_REG_BASE, BBL_CNTL_REG, 0x201);
+
+ /*
+ * set Write Plane Mask register = 0x0f
+ */
+
+ BBL_DBG_PRINT ("Writing Plane Mask register = 0x%x\n", 0x0F);
+ BBL_SET_REG( BBL_REG_BASE, BBL_PLANE_MASK_REG, 0x0F);
+ BBL_EIEIO;
+
+ /*
+ * clear out WID planes
+ */
+
+ BBL_BUSY_POLL(BBL_REG_BASE);
+ BBL_FILL_RECT(BBL_REG_BASE, 0, 0, bbl_mon_data_ptr->x_res,
+ bbl_mon_data_ptr->y_res);
+ BBL_EIEIO;
+
+ /*
+ * set destination to FB_A
+ */
+
+ BBL_SET_REG( BBL_REG_BASE, BBL_CNTL_REG, 0x01);
+
+ /*
+ * set Write Plane Mask register = 0xff
+ */
+
+ BBL_DBG_PRINT ("Writing Plane Mask register = 0x%x\n", 0xFF);
+ BBL_SET_REG( BBL_REG_BASE, BBL_PLANE_MASK_REG, 0xFF);
+ BBL_EIEIO;
+
+ /*
+ * clear out FB_A (actually make it dark blue for HAL)
+ */
+
+ BBL_BUSY_POLL(BBL_REG_BASE);
+ BBL_SET_REG( BBL_REG_BASE, BBL_FG_REG, 0x01); // dark blue
+ BBL_FILL_RECT(BBL_REG_BASE, 0, 0, bbl_mon_data_ptr->x_res,
+ bbl_mon_data_ptr->y_res);
+
+ BBL_EIEIO;
+ BBL_BUSY_POLL(BBL_REG_BASE);
+
+
+ /*******************************************/
+ /* E N A B L E V I D E O D I S P L A Y */
+ /*******************************************/
+
+
+ /*
+ * set Configuration high register
+ */
+
+
+ BBL_DBG_PRINT ("Writing RAMDAC config register high = 0x%x\n", 0x69);
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE, BBL_RAMDAC_CONFIG_HIGH_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x69);
+
+ BBL_EIEIO;
+ BBL_DBG_PRINT ("Finished with BBLInitialize()\n");
+
+ return TRUE;
+}
+
+
+BOOLEAN
+BBLGetMonitorID (
+ PULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ )
+{
+ unsigned long switch_id, cable_id, cable_id_tmp;
+ unsigned long status_vert, status_horz, monitor_id;
+ unsigned char monitor_id_orig, monitor_id_tmp;
+
+ BBL_DBG_PRINT("Entering BBLGetMonitorID\n");
+
+ /*
+ * Disable the PLL and the DTG controllers
+ */
+
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_LOW_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x00);
+ BBL_EIEIO;
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x08);
+ BBL_EIEIO;
+
+ /*
+ * Setup the PLL registers
+ */
+
+ BBL_SET_PLL_REF_REG(BBL_REG_BASE, 50);
+ BBL_SET_PLL_VCO_DIVIDER_REG(BBL_REG_BASE, 50 * 100);
+ BBL_EIEIO;
+
+ /*
+ * Enable the PLL
+ */
+
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x48);
+ BBL_EIEIO;
+
+ /*
+ * Enable positive syncs
+ */
+
+ BBL_SET_CRT_CNTL_REG(BBL_REG_BASE, 0x18);
+
+ /*
+ * Setup the horizontal DTG registers
+ */
+
+ BBL_SET_HORIZONTAL_TOTAL_REG(BBL_REG_BASE, 0x00ff);
+ BBL_SET_HORIZONTAL_DISPLAY_END_REG(BBL_REG_BASE, 0x0080);
+ BBL_SET_HORIZONTAL_SYNC_START_REG(BBL_REG_BASE, 0x0103);
+ BBL_SET_HORIZONTAL_SYNC_END1_REG(BBL_REG_BASE, 0x008f);
+ BBL_SET_HORIZONTAL_SYNC_END2_REG(BBL_REG_BASE, 0x0000);
+
+ /*
+ * Setup the vertical DTG registers
+ */
+
+ BBL_SET_VERTICAL_TOTAL_REG(BBL_REG_BASE, 0x00ff);
+ BBL_SET_VERTICAL_DISPLAY_END_REG(BBL_REG_BASE, 0x0080);
+ BBL_SET_VERTICAL_SYNC_START_REG(BBL_REG_BASE, 0x0100);
+ BBL_SET_VERTICAL_SYNC_END_REG(BBL_REG_BASE, 0x0088);
+ BBL_EIEIO;
+
+ /*
+ * Enable the DTG
+ */
+
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x68);
+
+ /*
+ * Delay for 35 ms
+ */
+
+ BBL_EIEIO;
+
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+
+ /*
+ * Read the monitor ID with positive going syncs
+ */
+
+ BBL_GET_MONITOR_ID(BBL_REG_BASE,monitor_id_orig);
+
+ /*
+ * Extract the raw monitor ID along with the DIP switch
+ * settings
+ */
+
+ switch_id = (monitor_id_orig >> 4 ) & 0x0f ;
+ cable_id = (monitor_id_orig & 0x0f);
+ BBL_DBG_PRINT("monitor_id_orig=0x%x switch_id=0x%x cable_id=0x%x\n",
+ monitor_id_orig, switch_id, cable_id);
+
+ /*
+ * Set VSYNC to negative logic
+ */
+ BBL_SET_CRT_CNTL_REG(BBL_REG_BASE, 0x08);
+
+ /*
+ * Delay for 35 ms
+ */
+
+ BBL_EIEIO;
+
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+
+ /*
+ * Read the monitor ID with negative VSYNC logic active
+ */
+
+ BBL_GET_MONITOR_ID(BBL_REG_BASE,monitor_id_tmp);
+
+ /*
+ * Extract the negative VSYNC monitor ID and OR in
+ * the changed bits into the monitor ID
+ */
+
+ status_vert = (monitor_id_tmp & 0x0f) ^ cable_id;
+ cable_id_tmp = monitor_id_tmp & 0x0f;
+ BBL_DBG_PRINT("monitor_id_tmp=0x%x status_vert=0x%x cable_id_tmp=0x%x\n",
+ monitor_id_tmp, status_vert, cable_id_tmp);
+
+ /*
+ * Set HSYNC to negative logic; VSYNC is still negative as well
+ */
+
+ BBL_SET_CRT_CNTL_REG(BBL_REG_BASE, 0x00);
+
+ /*
+ * Delay for 35 ms
+ */
+
+ BBL_EIEIO;
+
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+
+ /*
+ * Read the monitor ID with negative HSYNC and VSYNC logic
+ */
+
+ BBL_GET_MONITOR_ID(BBL_REG_BASE,monitor_id_tmp);
+
+ /*
+ * Extract the negative HSYNC and VSYNC value and OR in
+ * the changed bits into the monitor ID
+ */
+
+ status_horz = (monitor_id_tmp & 0x0f) ^ cable_id_tmp;
+ monitor_id = switch_id << BBL_MON_ID_DIP_SWITCHES_SHIFT;
+ BBL_DBG_PRINT("monitor_id_tmp=0x%x status_horz=0x%x monitor_id=0x%x\n",
+ monitor_id_tmp, status_horz, monitor_id);
+
+ /*
+ * Turn PLL and DTG controllers back off
+ */
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x08);
+ BBL_EIEIO;
+
+ /*
+ * Determine if we have a vert (V) or horz (H) value in the
+ * monitor ID based on what we read the three times above
+ */
+
+ if(status_horz & 0x08)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_0_SHIFT);
+ else if(status_vert & 0x08)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_0_SHIFT);
+ else if(cable_id & 0x08)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_0_SHIFT);
+
+ if(status_horz & 0x04)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_1_SHIFT);
+ else if(status_vert & 0x04)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_1_SHIFT);
+ else if(cable_id & 0x04)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_1_SHIFT);
+
+ if(status_horz & 0x02)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_2_SHIFT);
+ else if(status_vert & 0x02)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_2_SHIFT);
+ else if(cable_id & 0x02)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_2_SHIFT);
+
+ if(status_horz & 0x01)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_3_SHIFT);
+ else if(status_vert & 0x01)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_3_SHIFT);
+ else if(cable_id & 0x01)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_3_SHIFT);
+
+ *monID = monitor_id;
+ BBL_DBG_PRINT ("Monitor id = 0x%x\n", monitor_id);
+
+ return TRUE;
+}
+
+
+VOID
+BBLWaitForVerticalSync (
+ volatile PUCHAR HalpBBLRegisterBase
+ )
+{
+ int counter = 0;
+
+ // Loop until out of Vertical Sync just in case we happened to
+ // catch the tail end of a vertical blank cycle
+ while((BBL_GET_REG(HalpBBLRegisterBase, BBL_STATUS_REG)
+ & BBL_VERTICAL_RETRACE) &&
+ (++counter < 1000000))
+ ;
+
+ counter = 0;
+ // Wait until we hit the leading edge of the Vertical Sync
+ while((!(BBL_GET_REG(HalpBBLRegisterBase, BBL_STATUS_REG)
+ & BBL_VERTICAL_RETRACE)) &&
+ (++counter < 1000000))
+ ;
+
+#ifdef DBG
+ // If counter reaches 1000000, then there is something wrong with
+ // the setup of the ramdac
+#ifdef KDB
+ if(counter == 1000000)
+ DbgBreakPoint();
+#endif
+#endif
+
+}
+
+
+VOID
+HalpDisplayCharacterBBL (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If the character is a newline:
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BBLScrollScreen();
+ }
+ }
+
+ //
+ // If the character is a tab:
+ //
+
+ else if( Character == '\t' ) {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) { // tab beyond end of screen?
+ HalpColumn = 0; // set to 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ BBLScrollScreen();
+ else
+ ++HalpRow;
+ }
+ }
+
+ //
+ // If the character is a return:
+ //
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ }
+
+ //
+ // If the character is a DEL:
+ //
+
+ else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ Character = 0x20 - HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterBBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ }
+
+ //
+ // If not special character:
+ //
+
+ else {
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter))
+ Character = HalpFontHeader->DefaultCharacter;
+ else
+ Character -= HalpFontHeader->FirstCharacter;
+
+ // Auto wrap for HalpDisplayWidth columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BBLScrollScreen();
+ }
+ }
+
+ HalpOutputCharacterBBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterBBL(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ //if (HalpColumn == HalpDisplayWidth) {
+ // HalpDisplayCharacterBBL('\n');
+ //}
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) +
+ (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |=
+ *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination = 0x01; // Clear out any pre-existing char
+ if (FontValue >> 31 != 0)
+ *Destination = 0x3F; // Make this pixel white (ARC color)
+
+ Destination++;
+ FontValue <<= 1;
+ }
+ Destination += (BBL_SCANLINE_LENGTH - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+VOID
+BBLScrollScreen (
+ VOID
+ )
+{
+ PULONG Destination, Source, End;
+ ULONG pix_col, Stride;
+
+ // Scroll up one line
+ Destination = (PULONG) HalpVideoMemoryBase;
+ Source = (PULONG) (HalpVideoMemoryBase + HalpScrollLine);
+ End = (PULONG) ((PUCHAR) Source + HalpScrollLength);
+ Stride = (ULONG) ((BBL_SCANLINE_LENGTH - HalpHorizontalResolution) >> 2);
+
+ while(Source < End){
+ pix_col = 0;
+ while(pix_col++ < (HalpHorizontalResolution >> 2)){
+ *Destination++ = *Source++;
+ }
+ Destination += Stride;
+ Source += Stride;
+ }
+
+ // Blue the bottom line
+ Destination = (PULONG) (HalpVideoMemoryBase + HalpScrollLength);
+ End = (PULONG) ((PUCHAR) Destination + HalpScrollLine);
+ while(Destination < End){
+ for (pix_col =0; pix_col < (HalpHorizontalResolution >> 2);
+ pix_col ++){
+ *Destination++ = 0x01010101;
+ }
+ Destination += Stride;
+ }
+}
+
+
+BOOLEAN
+BBLSetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN ULONG reg_value
+ )
+{
+ ULONG slot = 0, bus = 0, value, i, j;
+ volatile PUCHAR HalpBBLRegisterBase;
+ BOOLEAN found;
+
+
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BBL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ found = FALSE;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+ for (i=0; ((i<HalpPciMaxSlots)&&(found==FALSE)); i++){
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ j,
+ i,
+ &value,
+ 0x0,
+ 4);
+
+ }
+
+ if(value == BBL_DEV_VEND_ID){
+ slot = i;
+ bus = j;
+ found = TRUE;
+ }
+ }
+ }
+
+ if(found == FALSE){
+ BBL_DBG_PRINT("Cannot find adapter!\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace ();
+ return (FALSE);
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0SetPciDataByOffset (bus, slot, &reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalSetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ &reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
+BOOLEAN
+BBLGetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN PULONG reg_value
+ )
+{
+ ULONG slot = 0, bus = 0, value, i, j;
+ volatile PUCHAR HalpBBLRegisterBase;
+ BOOLEAN found;
+
+
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BBL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ found = FALSE;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+ for (i=0; ((i<HalpPciMaxSlots)&&(found==FALSE)); i++){
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ j,
+ i,
+ &value,
+ 0x0,
+ 4);
+
+ }
+
+ if(value == BBL_DEV_VEND_ID){
+ slot = i;
+ bus = j;
+ found = TRUE;
+ }
+ }
+ }
+
+ if(found == FALSE){
+ BBL_DBG_PRINT("Cannot find adapter!\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace ();
+ return (FALSE);
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (bus, slot, reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxbeep.c b/private/ntos/nthals/halppc/ppc/pxbeep.c
new file mode 100644
index 000000000..2ac4b543c
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbeep.c
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a Power PC
+ system.
+
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpIoControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxbl.c b/private/ntos/nthals/halppc/ppc/pxbl.c
new file mode 100644
index 000000000..c98e40913
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbl.c
@@ -0,0 +1,1700 @@
+/*++
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+pxbl.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a GXT200P/GXT250P (Sky Blue) video adapter.
+
+Author:
+
+ Tim White
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "string.h"
+
+// Include GXT250P header file information
+#include "blrastz.h"
+#include "blrmdac.h"
+#include "bldef.h"
+#include "blfw.h"
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+extern POEM_FONT_FILE_HEADER HalpFontHeader;
+extern ULONG HalpPciMaxSlots;
+
+extern UCHAR TextPalette[];
+
+
+#define TAB_SIZE 4
+
+//
+// Set up the monitor data information
+//
+
+bl_crt_ctrl_rec_t bl_crt_ctrl_rec[BL_NUM_CRT_CTRL_REC_STRUCTS] =
+{
+
+/* 640x480@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq:
+ * Pix Clk: 25.2Mhz
+ * Sync: -H,-V
+ * Monitors:
+ */
+ { m640_480_8_60, 0,
+ 640, 480, 60,
+ 0x08, 0x5E, 0x06, 0x06,
+ 0x18, 0x00,
+ 799, 639, 655, 751, 0,
+ 524, 479, 489, 491 },
+
+/* 800x600@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq:
+ * Pix Clk: 40.0Mhz
+ * Sync: -H,+V
+ * Monitors:
+ */
+ { m800_600_8_60, BL_MT_0A,
+ 800, 600, 60,
+ 0x0B, 0x42, 0x02, 0x05,
+ 0x00, 0x00,
+ 1055, 799, 839, 967, 0,
+ 627, 599, 600, 604 },
+
+/* 1024x768@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq: 48.363Khz
+ * Pix Clk: 65Mhz
+ * Sync: vsync+, hsync+
+ * Monitors:
+ */
+ { m1024_768_8_60, 0,
+ 1024, 768, 60,
+ 0x0C, 0x75, 0x02, 0x06,
+ 0x18, 0x00,
+ 1343, 1023, 1047, 1183, 0,
+ 805, 767, 770, 776 },
+
+/* 1024x768@70Hz
+ *
+ * Vfreq: 70Hz
+ * Hfreq: 57.019Khz
+ * Pix Clk: 78Mhz
+ * Sync: SEP (vsync+, hsync+)
+ * Monitors: IBM 8517 (17" color)
+ */
+ { m1024_768_8_70, BL_MT_1A,
+ 1024, 768, 70,
+ 0x08, 0x30, 0x00, 0x05,
+ 0x00, 0x00,
+ 1367, 1023, 1031, 1311, 0,
+ 813, 767, 767, 775 },
+
+/* 1280x1024@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq: 109.37Khz
+ * Pix Clk: 112Mhz
+ * Sync: SOG (+)
+ * Monitors:
+ */
+ { m1280_1024_8_60, BL_MT_04,
+ 1280, 1024, 60,
+ 0x0A, 0x55, 0x00, 0x05,
+ 0x03, BL_DTG_COMP_SYNC,
+ 1759, 1279, 1299, 1455, 1103,
+ 1055, 1023, 1026, 1029 },
+
+/* 1280x1024@67Hz
+ *
+ * Vfreq: 67Hz
+ * Hfreq: 70.8Khz
+ * Pix Clk: 128Mhz
+ * Sync: SEP (vsync-, hsync-)
+ * Monitors: IBM 8508 (19" mono)
+ */
+ { m1280_1024_8_67, BL_MT_07,
+ 1280, 1024, 67,
+ 0x0C, 0x73, 0x00, 0x05,
+ 0x18, 0x00,
+ 1807, 1279, 1351, 1607, 0,
+ 1055, 1023, 1023, 1031 },
+
+/* 1280x1024@72Hz
+ *
+ * Vfreq: 71.537Hz
+ * Hfreq: 75.829Khz
+ * Pix Clk: 128Mhz
+ * Sync: SOG
+ * Monitors: IBM 1091-051 (POWERdisplay 16s)
+ */
+ { m1280_1024_8_72, BL_MT_17,
+ 1280, 1024, 72,
+ 0x0C, 0x73, 0x00, 0x05,
+ 0x03, BL_DTG_COMP_SYNC,
+ 1687, 1279, 1311, 1451, 1171,
+ 1059, 1023, 1026, 1029 }
+
+};
+
+//
+// Set up the adapter data information
+//
+
+bl_adapter_ctrl_rec_t bl_2meg_sky_0_1_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 2 meg */
+/* AUX A (WID) size: 1 meg */
+/* PRISM revision: 0x1 */
+
+ {
+ 2, 1024, 1024,
+ 0x02222024, 0x01800001, 0x0023000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x00, 0x03 },
+
+ {
+ 2, 2048, 1024,
+ 0x02202040, 0x01800001, 0x0023000f,
+ /* 8:1 multiplex */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x04,
+ 0xff, 0x00, 0x0f }
+
+};
+
+bl_adapter_ctrl_rec_t bl_6meg_sky_0_1_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 6 meg */
+/* AUX A (WID) size: 2 meg */
+/* PRISM revision: 0x1 */
+
+// {
+// 6, 2048, 1024,
+// 0x062b2044, 0x00810102, 0x0046000b,
+// /* 4:1 multiplex */
+// 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x01,
+// 0x00, 0x0c,
+// 0xff, 0x0f, 0x03 },
+
+ {
+ 6, 2048, 1024,
+ 0x062b2044, 0x00810003, 0x0046000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x0f, 0x03 }
+
+};
+
+bl_adapter_ctrl_rec_t bl_2meg_sky_1_2_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 2 meg */
+/* AUX A (WID) size: 1 meg */
+/* PRISM revision: 0x2 */
+
+ {
+ 2, 1024, 1024,
+ 0x02222024, 0x01800001, 0x0023000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x00, 0x03 },
+
+ {
+ 2, 2048, 1024,
+ 0x02202040, 0x01800001, 0x0023000f,
+ /* 8:1 multiplex */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x04,
+ 0xff, 0x00, 0x0f }
+
+};
+
+bl_adapter_ctrl_rec_t bl_6meg_sky_1_2_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 6 meg */
+/* AUX A (WID) size: 2 meg */
+/* PRISM revision: 0x2 */
+
+// {
+// 6, 2048, 1024,
+// 0x062b2044, 0x00810102, 0x0046000b,
+// /* 4:1 multiplex */
+// 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x01,
+// 0x00, 0x0c,
+// 0xff, 0x0f, 0x03 },
+
+ {
+ 6, 2048, 1024,
+ 0x062b2044, 0x00810003, 0x0046000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x0f, 0x03 },
+
+ {
+ 6, 2048, 2048,
+ 0xb6292060, 0x00810003, 0x004a000b,
+ /* 8:1 multiplex */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x04,
+ 0xff, 0x00, 0x0f }
+
+};
+
+//
+// Set up the adapter model information
+//
+
+bl_adapter_model_rec_t bl_model[] = {
+ {
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_2_MEG, 1, 2,
+ bl_2meg_sky_0_1_adp_ctrl },
+
+ {
+// BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 1, 2,
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 1, 1,
+ bl_6meg_sky_0_1_adp_ctrl },
+
+// The card_rev of 0x01 and prism rev of 0x02 are guesses only!
+// Fix up the following and/or add additional entries as needed
+
+ {
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_2_MEG, 2, 2,
+ bl_2meg_sky_1_2_adp_ctrl },
+
+ {
+// BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 2, 3,
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 2, 2,
+ bl_6meg_sky_1_2_adp_ctrl },
+
+ {
+ /* end of table indicator */
+ 0, 0, 0, 0, 0 }
+
+};
+
+
+
+VOID
+HalpDisplayPpcBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBL (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterBL(
+ IN PUCHAR Glyph
+ );
+
+BOOLEAN
+BLGetConfigurationInfo (
+ IN ULONG dev_ven_id,
+ IN PULONG bus,
+ IN PULONG slot
+ );
+
+BOOLEAN
+BLGetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN PULONG reg_value
+ );
+
+BOOLEAN
+BLSetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN ULONG reg_value
+ );
+
+VOID
+BLScrollScreen(
+ VOID
+ );
+
+BOOLEAN
+BLInitialize (
+ volatile PUCHAR HalpBLRegisterBase,
+ bl_crt_ctrl_rec_t *crt_rec,
+ bl_adapter_ctrl_rec_t *adpt_rec
+ );
+
+BOOLEAN
+BLGetMonitorID (
+ volatile PUCHAR HalpBLRegisterBase,
+ PULONG monID
+ );
+
+VOID
+HalpDisplayPpcBLSetup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GXT200P/GXT250P Graphics Adapter
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG rc, status, monID, count, value, slot, bus;
+ volatile PUCHAR HalpBLRegisterBase = (PUCHAR)0;
+ PHYSICAL_ADDRESS physaddr;
+ PHYSICAL_ADDRESS bl_phys_address;
+ PHYSICAL_ADDRESS bl_fb_phys_address;
+ ULONG Strapping, Revision, Model;
+ LONG i ;
+ USHORT match = 0, vram = 0;
+ bl_crt_ctrl_rec_t *crt_rec;
+ bl_adapter_ctrl_rec_t *adpt_rec;
+ BOOLEAN found, ok;
+
+ //
+ // There is no need to have both the register space and the
+ // DFA space mapped at the same time. This will save us from
+ // having multiple I/O spaces mapped at the same time. Thus
+ // saving DBATs which are in very very short supply...
+ //
+
+ //
+ // Strategy:
+ //
+ // 1. Map the PCI configuration register space
+ // 2. Update the PCI configuration registers
+ // 3. Unmap the PCI configuration register space
+ // 4. Map the register space
+ // 5. Reset the device
+ // 6. Read the monitor ID to figure what resolution and refresh mode to use
+ // 7. Perform device re-initialization (rasterizer, ramdac,
+ // and color palette)
+ // 8. Unmap the register space
+ // 9. Map the DFA space
+ // 10. Clear out VRAM to the default background color
+ // 11. Now can do character blits
+ //
+
+
+ BL_DBG_PRINT("HalpDisplayPpcBLSetup Enter\n");
+
+ /*******************************************************************/
+ /* S E T P C I C O N F I G U R A T I O N R E G I S T E R S */
+ /*******************************************************************/
+
+ // First find the bus and slot number based off the device/vendor ID
+ // and in the SAME ORDER that ARC searches!
+
+ ok = BLGetConfigurationInfo (BL_SKY_DEV_VEN_ID, &bus, &slot);
+ if(ok == FALSE){
+ BL_DBG_PRINT("Could not find the card! for 0x%08x\n",
+ BL_SKY_DEV_VEN_ID);
+ return;
+ }
+
+ // PCI bus devices are in a 32-bit memory space
+ bl_phys_address.HighPart = 0x0;
+
+ ok = BLGetConfigurationRegister (bus, slot,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ u.type0.BaseAddresses[0]),
+ &bl_phys_address.LowPart );
+
+ // translate bus-relative address
+ bl_phys_address.LowPart += PCI_MEMORY_PHYSICAL_BASE;
+
+ if(ok == FALSE){
+ BL_DBG_PRINT("Could not read PCI cfg reg 0x10\n");
+ return;
+ }
+
+ ok = BLGetConfigurationRegister (bus, slot,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ u.type0.BaseAddresses[1]),
+ &bl_fb_phys_address.LowPart );
+
+ // translate bus-relative address
+ bl_fb_phys_address.LowPart += PCI_MEMORY_PHYSICAL_BASE;
+
+ if(ok == FALSE){
+ BL_DBG_PRINT("Could not read PCI cfg reg 0x14\n");
+ return;
+ }
+ BL_DBG_PRINT("reg_base = 0x%08x fb_base=0x%08x\n",
+ bl_phys_address.LowPart, bl_fb_phys_address.LowPart);
+
+ /**************************************************/
+ /* M A P T H E R E G I S T E R S P A C E */
+ /**************************************************/
+
+ //
+ // Map the the adapter register range into memory.
+ //
+
+
+ if (HalpInitPhase == 0) {
+
+ BL_DBG_PRINT("call KePhase0MapIo() to map the reg space. Phys=0x%x Len=0x%x %d\n",
+ bl_phys_address.LowPart, BL_REG_MAP_SIZE, BL_REG_MAP_SIZE);
+
+ HalpBLRegisterBase = (PUCHAR)KePhase0MapIo(bl_phys_address.LowPart,
+ BL_REG_MAP_SIZE); // 32K
+ } else {
+ physaddr.HighPart = 0;
+ physaddr.LowPart = bl_phys_address.LowPart;
+ HalpBLRegisterBase = (PUCHAR)MmMapIoSpace(physaddr,
+ BL_REG_MAP_SIZE, FALSE);
+ }
+
+ BL_DBG_PRINT("HalpBLRegisterBase = 0x%x\n", HalpBLRegisterBase);
+
+
+ /**************************************************/
+ /* F I N D F O N T T O U S E */
+ /**************************************************/
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+ BL_DBG_PRINT("PixelWidth = %d PixelHeight = %d\n HalpFontHeader = 0x%x\n",
+ HalpFontHeader->PixelWidth, HalpFontHeader->PixelHeight,
+ HalpFontHeader);
+
+ /*********************************************/
+ /* S E T P C I C O N F I G U R A T I O N */
+ /* R E G I S T E R S */
+ /*********************************************/
+
+ BL_DBG_PRINT("BLInit: setting config registers\n") ;
+
+ // Read strapping data
+ if(BLGetConfigurationRegister(bus, slot, BL_PCI_CONFIG_STRAP,
+ &Strapping) == FALSE)
+ {
+ BL_DBG_PRINT("could not read strapping config reg\n");
+ return;
+ }
+ // Read revision data
+ if(BLGetConfigurationRegister(bus, slot, BL_PCI_REV_ID,
+ &Revision) == FALSE)
+ {
+ BL_DBG_PRINT("could not read revision config reg\n");
+ return;
+ }
+ // Set the PCI config register 0x0C
+ // Probably should alreday be set by ROS
+ value = BL_CONFIG_REG_0C_VALUE;
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_CONFIG_0C,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set the 0x0c config reg\n");
+ return;
+ }
+
+ // Set the PCI config register 0x3C
+ // Probably should alreday be set by ROS
+ value = BL_CONFIG_REG_3C_VALUE;
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_CONFIG_3C,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set the 0x3c config reg\n");
+ return;
+ }
+
+ // Enable memory accesses to the card (0x04)
+ if(BLGetConfigurationRegister(bus, slot, BL_PCI_CMD,
+ &value) == FALSE)
+ {
+ BL_DBG_PRINT("could not read the 0x04 config reg\n");
+ return;
+ }
+// Should we force disable VGA (i.e. through 0x46e8 before turning off
+// I/O access? Probably not as long as ROS does not use the VGA function
+ value &= 0xFE; // Disable I/O accesses
+ value |= 0x02; // Enable memory accesses
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_CMD,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not enable memory (0x04)\n");
+ return;
+ }
+
+ // Set the function enable PCI config register (0x40)
+ value = BL_FUNC_VALUE;
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_FUNC_ENABLE,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set func enable reg 0x40\n");
+ return;
+ }
+
+ // Set the extended function enable PCI config register (0x44)
+ // Use the right value depending on whether the card is has a DD2
+ // chip or a DD3 chip on board
+ switch(Strapping & BL_STRAP_CHIP_REV_MASK){
+ case BL_STRAP_CHIP_DD2:
+ value = BL_EXT_FUNC_VALUE_DD2;
+ break;
+ case BL_STRAP_CHIP_DD3:
+ default:
+ value = BL_EXT_FUNC_VALUE_DD3;
+ break;
+ }
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_EXT_FUNC_ENABLE,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set ext func enable reg 0x44\n");
+ return;
+ }
+
+ /*********************************************/
+ /* C R I T I C A L R A M D A C R E G S */
+ /*********************************************/
+
+ // Set ramdac to index auto inc
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_UPDATE_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_UPDATE_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ BL_640_AUTO_INCR);
+ // Turn off DAC to kill video
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_DAC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_DAC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, 0);
+ // Turn off sync's
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ BL_640_PWR_LOW_SYNC);
+ // Set PRISM time base using ramdac aux pll controller registers
+ // Set to run PRISM at 50Mhz
+ BL_DBG_PRINT("set prism time base (ramdac aux pll regs)\n");
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_AUX_REF_DIVIDE));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR25);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR26);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR27);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR28);
+ // Turn off ramdac VGA mode
+ BL_DBG_PRINT("turn off ramdac VGA\n");
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_VGA_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR07);
+
+ /*********************************************/
+ /* B U S Y P O L L A N D R E S E T */
+ /*********************************************/
+
+ BL_DBG_PRINT("reset PRISM and poll for idle\n");
+
+ // Disable and reset PRISM intrs
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_INTR_STATUS_REG,
+ BL_PRSM_DISABLE_RST_INTR);
+
+value = PRISM_RD_REG(HalpBLRegisterBase, BL_PRSM_STATUS_REG);
+BL_DBG_PRINT("status = 0x%08x\n", value);
+
+ // Check for PRISM busy. If busy, soft reset PRISM and poll for idle
+ if (PRISM_BUSY(HalpBLRegisterBase))
+ {
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_SOFT_RESET_REG, 0);
+ BL_EIEIO;
+ while(PRISM_BUSY(HalpBLRegisterBase))
+ ;
+ }
+
+ /*********************************************/
+ /* G E T M O N I T O R I D */
+ /*********************************************/
+
+ if(BLGetMonitorID(HalpBLRegisterBase, &monID) == FALSE){
+ BL_DBG_PRINT("BLGetMonitorID() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ //
+ // Determine which adapter model rec to use
+ //
+
+ BL_DBG_PRINT("DeviceId=0x%08x Strapping=0x%08x Revision=0x%08x\n",
+ BL_SKY_DEV_VEN_ID, Strapping, Revision);
+
+ // For DD2 PRISM based cards, the DD2 model entries *MUST* be
+ // used!!! The DD3 model entries are used for DD3 PRISM based
+ // cards (and future cards). So the DD3 model entries are the
+ // default and should allow for new PRISM chips without code
+ // modification in this area of the GXT250P miniport code
+
+ for(Model=0;;Model++){
+
+ // Ensure we're not at the end of the list first off
+ if(bl_model[Model].devvend_id == 0)
+ break;
+
+ // Ensure we have the right resolution and function capabilities
+ if((Strapping & BL_FRAME_BUFFER_SIZE_MASK)
+ == bl_model[Model].strapping){
+
+ // Check to see if we're a DD2 PRISM chip (not DD2 card!)
+ if((Strapping & BL_STRAP_CHIP_REV_MASK) ==
+ BL_STRAP_CHIP_DD2){
+
+ // If we're a DD2 PRISM chip, ensure we have a
+ // DD2 PRISM level model entry
+ if(((Strapping & BL_STRAP_CHIP_REV_MASK) >> 28) ==
+ bl_model[Model].prism_rev){
+ break;
+ }
+
+ // If we're not DD2 (assume never DD1) PRISM
+ }else{
+
+ // Ensure we are using a DD3 PRISM entry
+ if(bl_model[Model].prism_rev == (BL_STRAP_CHIP_DD3 >> 28)){
+ break;
+ }
+ }
+ }
+ }
+ if (bl_model[Model].devvend_id == 0){
+ BL_DBG_PRINT("Cannot find correct adapter model rec!\n");
+ return;
+ }
+
+ BL_DBG_PRINT("Model = %d\n", Model);
+
+ for(i=0,crt_rec=&bl_crt_ctrl_rec[0];
+ ((!found)&&(i<BL_NUM_CRT_CTRL_REC_STRUCTS));
+ crt_rec++,i++)
+ {
+ if(crt_rec->MonID == (USHORT)monID){
+ found = TRUE;
+ break;
+ }
+ }
+ // If we did not find a valid CRT structure then we have
+ // a serious error since BLGetMonitorID should have already
+ // handled the case where the ID is not valid
+ if(!found){
+ BL_DBG_PRINT("Invalid monitor ID! 0x%04x\n", (USHORT)monID);
+ return;
+ }
+
+ BL_DBG_PRINT ("START MonitorID = 0x%04x\n", (USHORT)monID) ;
+ BL_DBG_PRINT ("width=%d height=%d refresh=%d\n",
+ crt_rec->width, crt_rec->height, crt_rec->refresh);
+
+ //
+ // Determine which adpt_rec to use based off the adapter model
+ // and crt_rec (from monitor ID)
+ //
+
+ adpt_rec = bl_model[Model].adp_ctrl_rec;
+
+ switch(Strapping & BL_FRAME_BUFFER_SIZE_MASK){
+ case BL_FRAME_BUFFER_SIZE_2_MEG:
+ vram = 2;
+ break;
+ case BL_FRAME_BUFFER_SIZE_4_MEG:
+ vram = 4;
+ break;
+ case BL_FRAME_BUFFER_SIZE_6_MEG:
+ vram = 6;
+ break;
+ case BL_FRAME_BUFFER_SIZE_8_MEG:
+ vram = 8;
+ break;
+ }
+
+ BL_DBG_PRINT("crt_rec = 0x%x\n", crt_rec);
+ BL_DBG_PRINT("crt_rec->MonID = %d\n",
+ crt_rec->MonID);
+ BL_DBG_PRINT("crt_rec->width, height = %d,%d\n",
+ crt_rec->width, crt_rec->height);
+
+ found = FALSE;
+ for(i=0;i<bl_model[Model].num_adp_ctrl_recs;i++){
+
+ BL_DBG_PRINT("adpt_rec->width, height = %d,%d\n",
+ adpt_rec->width, adpt_rec->height);
+ BL_DBG_PRINT("adpt_rec->vram, vram = 0x%x, 0x%x\n",
+ adpt_rec->vram, vram);
+
+ if((adpt_rec->vram == vram) &&
+ (crt_rec->width <= adpt_rec->width) &&
+ (crt_rec->height <= adpt_rec->height)){
+ found = TRUE;
+ break;
+ }
+ ++adpt_rec;
+ }
+ // If adapter record not found, then we're hosed!
+ if(!found){
+ BL_DBG_PRINT("Could not find correct adpt rec!\n");
+ return;
+ }
+
+ /*********************************************/
+ /* S E T H A L V A R I A B L E S */
+ /*********************************************/
+
+ //
+ // set the correct horizontal and vertical resolutions for HAL
+ //
+
+ HalpHorizontalResolution = crt_rec->width;
+ HalpVerticalResolution = crt_rec->height;
+ BL_DBG_PRINT("HalpHorizontalResolution = %d HalpVerticalResolution = %d\n",
+ HalpHorizontalResolution, HalpVerticalResolution);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ // GXT200P/GXT250P real scanline length is hardcoded at 4096
+ // pixels independent
+ // of the resolution on the screen
+ HalpScrollLine =
+ BL_SCANLINE_LENGTH * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+ BL_DBG_PRINT("DisplayText = %d ScrollLine = %d ScrollLength = %d DisplayWidth = %d\n",
+ HalpDisplayText, HalpScrollLine, HalpScrollLength, HalpDisplayWidth);
+
+
+ /**************************************************/
+ /* R E I N I T I A L I Z E T H E C A R D */
+ /**************************************************/
+
+ //
+ // Initialize the adapter card for the resolution found by looking
+ // at the monitor ID
+ //
+
+ if(BLInitialize(HalpBLRegisterBase, crt_rec, adpt_rec) == FALSE){
+ BL_DBG_PRINT("BLInitialize(monID=0x%x) failed\n", monID);
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ /*********************************************/
+ /* U N M A P R E G I S T E R S P A C E */
+ /*********************************************/
+
+ //
+ // Unmap the the adapter register range from memory.
+ //
+
+ if (HalpInitPhase == 0) {
+
+ if (HalpBLRegisterBase) {
+ BL_DBG_PRINT("call KePhase0DeleteIoMap() to unmap the reg space. Phys=0x%x Len=0x%x %d\n",
+ bl_phys_address.LowPart, BL_REG_MAP_SIZE, BL_REG_MAP_SIZE);
+ KePhase0DeleteIoMap(bl_phys_address.LowPart, BL_REG_MAP_SIZE);
+ HalpBLRegisterBase = 0x0;
+ }
+ }
+
+
+ /*************************************************/
+ /* M A P F R A M E B U F F E R S P A C E */
+ /*************************************************/
+
+ //
+ // Map in the frame buffer memory which is used to write characters to
+ // the screen.
+ //
+
+ if (HalpInitPhase == 0) {
+
+ BL_DBG_PRINT("call KePhase0MapIo() to map the FB_A space. Phys=0x%x Len=0x%x %d\n",
+ bl_fb_phys_address.LowPart, BL_FB_MAP_SIZE, BL_FB_MAP_SIZE);
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(bl_fb_phys_address.LowPart,
+ (BL_FB_MAP_SIZE >> 1)); // 8MB (MAX BAT)
+ }
+
+ BL_DBG_PRINT("HalpVideoMemoryBase = 0x%x\n", HalpVideoMemoryBase);
+
+
+ /*********************************************/
+ /* M I S C A N D R E T U R N */
+ /*********************************************/
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ BL_DBG_PRINT("leaving HalpDisplayPpcBLSetup()\n");
+ return;
+
+} //end of HalpDisplayPpcBLSetup
+
+
+BOOLEAN
+BLInitialize (
+ volatile PUCHAR HalpBLRegisterBase,
+ bl_crt_ctrl_rec_t *crt_rec,
+ bl_adapter_ctrl_rec_t *adpt_rec
+ )
+
+/*++
+
+Routine Description:
+
+ Sets up the rasterizer and ramdac registers to the particular
+ resolution and refresh rate selected for the GXT200P/GXT250P card
+
+Arguments:
+
+ monID -- indicates the resolution and refresh rate to use
+
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+--*/
+
+{
+ int i;
+ ULONG cfg_high_value = 0;
+ ULONG cfg_low_value = 0;
+ USHORT wat_pixel_type;
+ UCHAR bl_clut[768];
+
+
+ BL_DBG_PRINT("Entering BLInitialize\n");
+
+ // Check for PRISM busy. If busy, soft reset PRISM and poll for idle
+ if (PRISM_BUSY(HalpBLRegisterBase))
+ {
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_SOFT_RESET_REG, 0);
+ BL_EIEIO;
+ while(PRISM_BUSY(HalpBLRegisterBase))
+ ;
+ }
+
+ // Disable video display
+ BL_DBG_PRINT("BLInitialize: Disable video display\n");
+
+ // Turn off monitor syncs
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, BL_640_PWR_LOW_SYNC);
+
+
+ BL_DBG_PRINT("BLInitialize: Setting PRISM config regs to 0x%x\n",
+ adpt_rec->PRISM_cfg);
+ BL_DBG_PRINT("BLInitialize: Setting PRISM mem config regs to 0x%x\n",
+ adpt_rec->mem_cfg);
+
+ // Set PRISM config regs
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CFG_REG, adpt_rec->PRISM_cfg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_MEM_CFG_REG, adpt_rec->mem_cfg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_DTG_CNTL_REG, (adpt_rec->DTG_ctrl |
+ crt_rec->crt_cntl_reg));
+
+ // Set video clock
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_VIDEO_PLL_REF_DIVIDE));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_ref_divide);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_mult);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_output_divide);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_ctrl);
+
+ BL_DBG_PRINT("BLInitialize: Initialize multiplexers\n");
+
+ // Initialize multiplexers
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_RAW_PIXEL_CTRL_00));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl1);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl2);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl3);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->wid_ctrl0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->wid_ctrl1);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->serial_mode_ctrl);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_interleave);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->misc_cfg);
+
+ BL_DBG_PRINT("BLInitialize: Setup VRAM masks\n");
+
+ // Setup VRAM pixel masks
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_VRAM_MASK_REG_0));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->vram_mask_0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->vram_mask_1);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->vram_mask_2);
+
+ BL_DBG_PRINT("BLInitialize: Clear diags and MISR\n");
+
+ // Clear diagnostics and MISR
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_DIAGNOSTICS));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR15);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR16);
+
+ BL_DBG_PRINT("BLInitialize: Load PRISM DTG regs\n");
+
+ BL_DBG_PRINT("BLInitialize: crt_rec stuct elements = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ crt_rec->MonID, crt_rec->width, crt_rec->height,
+ crt_rec->pll_ref_divide, crt_rec->pll_mult,
+ crt_rec->pll_output_divide, crt_rec->pll_ctrl, crt_rec->sync_ctrl,
+ crt_rec->crt_cntl_reg, crt_rec->hrz_total_reg,
+ crt_rec->hrz_dsp_end_reg, crt_rec->hsync_start_reg,
+ crt_rec->hsync_end1_reg, crt_rec->hsync_end2_reg,
+ crt_rec->vrt_total_reg, crt_rec->vrt_dsp_end_reg,
+ crt_rec->vsync_start_reg, crt_rec->vsync_end_reg);
+
+ // Load PRISM DTG regs
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_FR_START_REG, 0);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_EXTENT_REG,
+ crt_rec->hrz_total_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_DISPLAY_END_REG,
+ crt_rec->hrz_dsp_end_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_SYNC_START_REG,
+ crt_rec->hsync_start_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_SYNC_END_1_REG,
+ crt_rec->hsync_end1_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_SYNC_END_2_REG,
+ crt_rec->hsync_end2_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_EXTENT_REG,
+ crt_rec->vrt_total_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_DISPLAY_END_REG,
+ crt_rec->vrt_dsp_end_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_SYNC_START_REG,
+ crt_rec->vsync_start_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_SYNC_END_REG,
+ crt_rec->vsync_end_reg);
+
+ // Release syncs
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ (crt_rec->sync_ctrl | BL_640_FLIP_VSYNC));
+
+ // Set PRISM config regs
+ wat_pixel_type = 0x03; // 8 bit common palette index
+ cfg_high_value = ( (AR00 &
+ (~BL_SYS_SRC_DEPTH_A1_MASK & ~BL_FB_PIX_DEPTH_A1_MASK) )
+ | (BL_SYS_SRC_DEPTH_A1_8BPP | BL_FB_PIX_DEPTH_A1_8BPP) );
+ cfg_low_value = AR01;
+
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CNTL_HIGH_REG, cfg_high_value);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CNTL_LOW_REG, cfg_low_value);
+
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_PLANE_WR_MASK_REG, AR03);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CL_TEST_REG, AR04);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_SC_ENABLE_REG, AR05);
+
+ BL_DBG_PRINT("BLInitialize: PRISM Control regs set\n");
+ BL_DBG_PRINT("BLInitialize: Turn off cursor\n");
+
+ // Turn off cursor
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_CURSOR_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR10);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_CROSSHAIR_CTRL_1));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR11);
+
+ BL_DBG_PRINT("BLInitialize: Turn off WIDS\n");
+
+ // Turn off WID's (use only WAT 0)
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_MISC_CFG_REG));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->misc_cfg & ~BL_640_WIDCTRL_MASK);
+
+ BL_DBG_PRINT("BLInitialize: Initialize Framebuffer WAT 0\n");
+
+ // Initialize WAT 0
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_FRAME_BUFFER_WAT));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_FRAME_BUFFER_WAT));
+
+ // wat_pixel_type set in above case statement
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, wat_pixel_type);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR18);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR19);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR20);
+
+ BL_DBG_PRINT("BLInitialize: Load overlay WAT\n");
+
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_OVERLAY_WAT));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_OVERLAY_WAT));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR21);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR22);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR23);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR24);
+
+ // Load the default color palette
+ BL_DBG_PRINT("BLInitialize: Load default color palette\n");
+
+ /*
+ * Set the colormap
+ */
+
+ for(i=0; i<768; i++){
+ if((TextPalette[i] == 16)||
+ (TextPalette[i] == 32)||
+ (TextPalette[i] == 63)){
+ bl_clut[i] = TextPalette[i] * 4;
+ }else{
+ bl_clut[i] = TextPalette[i];
+ }
+ }
+
+ // Load color palette
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_COLOR_PALETTE_WRITE));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_COLOR_PALETTE_WRITE));
+
+ // Set to default values
+ for(i=0; i<(768); i++)
+ {
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, bl_clut[i]);
+ }
+
+ // Reset index back to zero
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, 0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI, 0);
+
+ BL_DBG_PRINT("BLInitialize: Clear the frame buffer to background\n");
+
+ // Clear frame buffer to background (dark blue HAL color)
+ BL_EIEIO;
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_FG_COL_REG, 0x1);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_BG_COL_REG, 0x0);
+ BL_EIEIO;
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CMD_REG,BL_PRSM_POLY_REC);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CMD_REG,0);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CMD_REG,
+ ((crt_rec->width << 16) | (crt_rec->height)));
+ BL_EIEIO;
+
+ // Wait until clear screen completes before proceeding
+ while(PRISM_BUSY(HalpBLRegisterBase))
+ ;
+
+ // Enable video display
+ BL_DBG_PRINT("BLInitialize: Enable video\n");
+ BL_DBG_PRINT("BLInitialize: Release syncs\n");
+
+ // Release sync's
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI, HIGH(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, crt_rec->sync_ctrl);
+
+ BL_DBG_PRINT("BLInitialize: Turn on video\n");
+
+ // Turn on video
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_DTG_CNTL_REG,
+ (adpt_rec->DTG_ctrl | crt_rec->crt_cntl_reg));
+
+ // Turn on DAC to enable video
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, LOW(BL_640_DAC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR08);
+
+ BL_DBG_PRINT("BLInitializee: FINISH\n") ;
+
+
+ return TRUE;
+}
+
+
+VOID
+BLWaitForVerticalSync (
+ volatile PUCHAR HalpBLRegisterBase
+ )
+{
+ // This function is called by BLGetMonitorID in order to
+ // conform to the ramdac hardware specs when reading the
+ // cable ID information from the monitor ID register on
+ // the ramdac
+
+ int counter = 0;
+
+ // Loop until out of Vertical Sync just in case we happened to
+ // catch the tail end of a vertical blank cycle
+
+ while ((PRISM_RD_REG(HalpBLRegisterBase, BL_PRSM_STATUS_REG) &
+ BL_PRSM_VERT_RETRACE) && (++counter < 1000000))
+ ;
+
+ counter = 0;
+
+ // Wait until we hit the leading edge of the Vertical Sync
+ while ((!(PRISM_RD_REG(HalpBLRegisterBase, BL_PRSM_STATUS_REG) &
+ BL_PRSM_VERT_RETRACE)) && (++counter < 1000000))
+ ;
+
+}
+
+
+UCHAR
+bl_rd_cable_id (
+ ULONG HalpBLRegisterBase
+)
+{
+ UCHAR id;
+
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_MONITOR_ID));
+ BL_EIEIO;
+ id = PRISM_RD_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA);
+
+ BL_DBG_PRINT("bl_rd_cable_id: 0x%02x\n", id);
+ return((id>>4) & 0x0f);
+}
+
+
+BOOLEAN
+BLGetMonitorID (
+ volatile PUCHAR HalpBLRegisterBase,
+ PULONG monID
+ )
+{
+ UCHAR monitor_id, id2, id3;
+
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_HI, HIGH(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_DATA, BL_640_PWR_LOW_SYNC);
+
+ // Stall
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+
+ monitor_id = bl_rd_cable_id((ULONG)HalpBLRegisterBase);
+
+ /* force V-Sync High */
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_DATA, BL_640_PWR_HIGH_VSYNC);
+
+ // Stall
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+
+ id2 = bl_rd_cable_id((ULONG)HalpBLRegisterBase);
+
+ /* force V-Sync low, H-Sync high */
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_DATA, BL_640_PWR_HIGH_HSYNC);
+
+ // Stall
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+
+ id3 = bl_rd_cable_id((ULONG)HalpBLRegisterBase);
+
+ /* if V or H bit value then we must */
+
+ /* generate monitor ID */
+ if ((monitor_id != id2) || (monitor_id != id3)) {
+
+ /* make sure that V/H bit value is */
+ /* only located in bit 3 of cable ID */
+ if ((((monitor_id ^ id2) | (monitor_id ^ id3)) & 0x07) ||
+ (((monitor_id ^ id2) & 0x08) && ((monitor_id ^ id3) & 0x08))) {
+
+ /* too many bits switching, invalid ID */
+ BL_DBG_PRINT("BLGetMonitorID: Invalid ID = 0x%02x 0x%02x 0x%02x\n",
+ monitor_id, id2, id3);
+ monitor_id = 0x0F; /* set to "not connected" value */
+ }else{ /* see if cable ID bit 3 = V */
+ if ((monitor_id ^ id2) & 0x08)
+ monitor_id = (monitor_id & 0x07) | 0x10;
+ else /* cable ID bit 3 must be H */
+ monitor_id = (monitor_id & 0x07) | 0x18;
+ }
+ }
+
+ BL_DBG_PRINT("BLGetMonitorID (read) = 0x%02x\n", monitor_id);
+
+ switch(monitor_id){
+ case BL_MT_04: // 0100
+ case BL_MT_07: // 0111
+ case BL_MT_1A: // H010
+ case BL_MT_17: // V111
+ case BL_MT_0A: // 1010
+ // The above monitor ID's translate directly to a default
+ // CRT structure entry
+ break;
+ case BL_MT_0F: // 1111 (no monitor connected)
+ default: // XXXX (anything else)
+ // The above monitor ID's do not translate to a default
+ // CRT structure entry so we pick a default here
+ monitor_id = BL_MT_0A; // The default monitor ID
+ }
+
+ BL_DBG_PRINT("BLGetMonitorID (returned) = 0x%02x\n", monitor_id);
+ *monID = (ULONG) monitor_id;
+
+ return TRUE;
+}
+
+
+VOID
+HalpDisplayCharacterBL (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If the character is a newline:
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BLScrollScreen();
+ }
+ }
+
+ //
+ // If the character is a tab:
+ //
+
+ else if( Character == '\t' ) {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) { // tab beyond end of screen?
+ HalpColumn = 0; // set to 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ BLScrollScreen();
+ else
+ ++HalpRow;
+ }
+ }
+
+ //
+ // If the character is a return:
+ //
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ }
+
+ //
+ // If the character is a DEL:
+ //
+
+ else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ Character = 0x20 - HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ }
+
+ //
+ // If not special character:
+ //
+
+ else {
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter))
+ Character = HalpFontHeader->DefaultCharacter;
+ else
+ Character -= HalpFontHeader->FirstCharacter;
+
+ // Auto wrap for HalpDisplayWidth columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BLScrollScreen();
+ }
+ }
+
+ HalpOutputCharacterBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterBL(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ //if (HalpColumn == HalpDisplayWidth) {
+ // HalpDisplayCharacterBL('\n');
+ //}
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) +
+ (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |=
+ *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination = 0x01; // Clear out any pre-existing char
+ if (FontValue >> 31 != 0)
+ *Destination = 0x3F; // Make this pixel white (ARC color)
+
+ Destination++;
+ FontValue <<= 1;
+ }
+ Destination += (BL_SCANLINE_LENGTH - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+VOID
+BLScrollScreen (
+ VOID
+ )
+{
+ PULONG Destination, Source, End;
+ ULONG pix_col, Stride;
+
+ // Scroll up one line
+ Destination = (PULONG) HalpVideoMemoryBase;
+ Source = (PULONG) (HalpVideoMemoryBase + HalpScrollLine);
+ End = (PULONG) ((PUCHAR) Source + HalpScrollLength);
+ Stride = (ULONG) ((BL_SCANLINE_LENGTH - HalpHorizontalResolution) >> 2);
+
+ while(Source < End){
+ pix_col = 0;
+ while(pix_col++ < (HalpHorizontalResolution >> 2)){
+ *Destination++ = *Source++;
+ }
+ Destination += Stride;
+ Source += Stride;
+ }
+
+ // Blue the bottom line
+ Destination = (PULONG) (HalpVideoMemoryBase + HalpScrollLength);
+ End = (PULONG) ((PUCHAR) Destination + HalpScrollLine);
+ while(Destination < End){
+ for (pix_col =0; pix_col < (HalpHorizontalResolution >> 2);
+ pix_col ++){
+ *Destination++ = 0x01010101;
+ }
+ Destination += Stride;
+ }
+}
+
+
+BOOLEAN
+BLGetConfigurationInfo (
+ IN ULONG dev_ven_id,
+ IN PULONG bus,
+ IN PULONG slot
+ )
+{
+
+ ULONG value, i, j;
+ volatile PUCHAR HalpBLRegisterBase;
+ BOOLEAN found;
+
+
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ found = FALSE;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+ for (i=0; ((i<HalpPciMaxSlots)&&(found==FALSE)); i++){
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ j,
+ i,
+ &value,
+ 0x0,
+ 4);
+
+ }
+
+ if(value == dev_ven_id){
+ *slot = i;
+ *bus = j;
+ found = TRUE;
+ }
+ }
+ }
+
+ if(found == FALSE){
+ BL_DBG_PRINT("Cannot find adapter!\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace ();
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+BOOLEAN
+BLSetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN ULONG reg_value
+ )
+{
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0SetPciDataByOffset (bus, slot, &reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalSetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ &reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
+BOOLEAN
+BLGetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN PULONG reg_value
+ )
+{
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (bus, slot, reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxbusdat.c b/private/ntos/nthals/halppc/ppc/pxbusdat.c
new file mode 100644
index 000000000..2053ab1e6
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbusdat.c
@@ -0,0 +1,200 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0);
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+
+ return Bus;
+}
+
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxcache.s b/private/ntos/nthals/halppc/ppc/pxcache.s
new file mode 100644
index 000000000..7e7a94d28
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxcache.s
@@ -0,0 +1,1188 @@
+//++
+//
+// Copyright (c) 1993, 94, 95, 96 IBM Corporation
+//
+// Module Name:
+//
+// pxcache.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 27-Dec-93 plj Added 603 support.
+// 13-Mar-94 plj Fixed problem introduced during switch to pas,
+// added 604 support.
+// 18-Jan-95 plj Add 603+, 604+ and 620 support.
+// 15-Nov-95 plj Switch to MP safe version (slightly faster too)
+// Also, support 603++ and 604++.
+//
+//--
+
+#include "kxppc.h"
+
+//
+// Override the ENABLE/DISABLE INTERRUPTS macros from kxppc.h because
+// unless this machine has a 603e/ev in it, we don't need the workaround
+// for errata 15.
+//
+
+#undef DISABLE_INTERRUPTS
+#undef ENABLE_INTERRUPTS
+
+#define DISABLE_INTERRUPTS(p0, s0) ; \
+ mfmsr p0 ; \
+ rlwinm s0,p0,0,~MASK_SPR(MSR_EE,1) ; \
+ mtmsr s0
+
+#define ENABLE_INTERRUPTS(p0) mtmsr p0
+
+ .set HID0, 1008 // H/W Implementation Dependent reg 0
+
+//
+// Define various known processor types.
+//
+
+ .set PV601, 1 // 601
+ .set PV603, 3 // 603
+ .set PV603E, 6 // 603 plus
+ .set PV603EV,7 // 603 plus plus
+ .set PV603ART,8 // Arthur (603xx desig unknown)
+ .set PV604, 4 // 604
+ .set PV604E, 9 // 604 plus
+ // 604 plus plus same as 604 plus
+ .set PV620, 20 // 620
+
+//
+// Note, in the following, the 603's "I-Cache Flash Invalidate"
+// and the 604's "I-Cache Invalidate All" basically perform the
+// same function although the usage is slightly different.
+// In the 603 case, ICFI must be cleared under program control
+// after it is set. In the 604 the bit clears automatically.
+// The 620's ICEFI behaves in the same way as the 604's ICIA.
+//
+
+ .set H0_603_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set H0_604_ICIA, 0x0800 // I-Cache Invalidate All
+ .set H0_620_ICEFI,0x0800 // I-Cache Edge Flash Invalidate
+ .set H0_603_DCFA, 0x0040 // D-Cache Flush Assist (Arthur)
+
+//
+// Cache layout
+//
+// Processor | Size (bytes) | Line | Block | Sets | PVR Processor
+// | I-Cache | D-Cache | Size | Size | | Version
+// ----------------------------------------------------------------------
+// 601 | 32KB Unified | 64B | 32B | | 0x0001xxxx
+// 603 | 8KB | 8KB | 32 | 32 | | 0x0003xxxx
+// 603+ | 16KB | 16KB | 32 | 32 | 4x128 | 0x0006xxxx
+// 603++ | 16KB | 16KB | 32 | 32 | 4x128 | 0x0007xxxx
+// Arthur | 32KB | 32KB | 32 | 32 | 8x128 | 0x0008xxxx
+// 604 | 16KB | 16KB | 32 | 32 | 4x128 | 0x0004xxxx
+// 604+ | 32KB | 32KB | 32 | 32 | 4x128 | 0x0009xxxx
+// 604++ | 32KB | 32KB | 32 | 32 | | 0x0009xxxx
+// 620 | 32KB | 32KB | 64 | 64 | | 0x0014xxxx
+//
+
+ .set DCLSZ601, 64 // 601 cache line size
+ .set DCBSZ601, 32 // 601 cache block size
+ .set DCL601, 32 * 1024 / DCLSZ601 // 601 num cache lines
+ .set DCBSZL2601, 5 // 601 log2(block size)
+
+ .set DCBSZ603, 32 // 603 cache block size
+ .set DCB603, 8 * 1024 / DCBSZ603 // 603 num cache blocks
+ .set DCBSZL2603, 5 // 603 log2(block size)
+
+ .set DCB603E, 16 * 1024 / DCBSZ603 // 603+ num cache blocks
+ .set DCB603ART, 32 * 1024 / DCBSZ603 // Arthur num cache blocks
+
+ .set DCBSZ604, 32 // 604 cache block size
+ .set DCB604, 16 * 1024 / DCBSZ604 // 604 num cache blocks
+ .set DCBSZL2604, 5 // 604 log2(block size)
+
+ .set DCB604E, 32 * 1024 / DCBSZ604 // 604+ num cache blocks
+
+ .set DCBSZ620, 64 // 620 cache block size
+ .set DCB620, 32 * 1024 / DCBSZ620 // 620 num cache blocks
+ .set DCBSZL2620, 6 // 620 log2(block size)
+
+//
+// The following variables are declared locally so their addresses
+// will appear in the TOC. During initialization, we overwrite
+// the TOC entries with the entry points for the cache flushing
+// routines appropriate for the processor we are running on.
+//
+// It is done this way rather than filling in a table to reduce the
+// number of access required to get the address at runtime.
+// (This is known as "Data in TOC" which is not very much used in
+// NT at this time).
+//
+
+ .data
+ .globl HalpSweepDcache
+HalpSweepDcache: .long 0
+ .globl HalpSweepIcache
+HalpSweepIcache: .long 0
+ .globl HalpSweepDcacheRange
+HalpSweepDcacheRange: .long 0
+ .globl HalpSweepIcacheRange
+HalpSweepIcacheRange: .long 0
+
+//++
+//
+// Routine Description:
+//
+// HalpCacheSweepSetup
+//
+// This routine is called during HAL initialization. Its function
+// is to set the branch tables for cache flushing routines according
+// to the processor type.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(HalpCacheSweepSetup)
+
+ mfpvr r.3 // get processor type
+ rlwinm r.3, r.3, 16, 0xffff // remove version
+ cmpwi r.3, PV603E // binary search for the right code
+ lwz r.4, [toc].data(r.toc) // get address of local data section
+ bge hcss.high // jif 603+ or greater
+ cmpwi r.3, PV603
+ beq hcss.603 // jif 603
+ bgt hcss.604 // > 603, < 603+ must be 604
+
+//
+// processor is a 601
+//
+
+ lwz r.5, [toc]HalpSweepDcache601(r.toc)
+ mr r.7, r.5 // do nothing
+ mr r.8, r.5 // do nothing
+ mr r.6, r.5 // 601 icache use dcache routine
+
+//
+// On a 601, the routine HalFlushIoBuffers is not required because the
+// 601 has a unified cache and coherency with other system components
+// is maintained. HalpSweepDcache601 is a no-op, ie it does nothing
+// but return. HalFlushIoBuffers is only called via the TOC (ie it is
+// not used withing the HAL) so change the TOC entry for it to point to
+// HalpSweepDcache601.
+//
+ .extern HalFlushIoBuffers
+
+ stw r.5, [toc]HalFlushIoBuffers(r.toc)
+ b hcss.done
+
+//
+// processor is a 603
+//
+
+hcss.603:
+
+ lwz r.5, [toc]HalpSweepDcache603(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603(r.toc)
+ b hcss.done
+
+//
+// processor is a 604
+//
+
+hcss.604:
+
+ lwz r.5, [toc]HalpSweepDcache604(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604(r.toc)
+ b hcss.done
+
+//
+// Processor type >= 603+, continue isolation of processor type.
+//
+
+hcss.high:
+
+ beq hcss.603p // jif 603 plus
+ cmpwi cr.7, r.3, PV603EV
+ cmpwi cr.0, r.3, PV604E
+ cmpwi cr.1, r.3, PV620
+ cmpwi cr.6, r.3, PV603ART
+ beq cr.7, hcss.603p // treat 603++ same as 603+
+ beq cr.0, hcss.604p // jif 604 plus
+ beq cr.1, hcss.620 // jif 620
+ beq cr.6, hcss.603art // jif Arthur
+
+//
+// If we got here we are running on a processor whose cache characteristics
+// are not known. Return non-zero for error.
+//
+
+ li r.3, 1
+ blr
+
+//
+// processor is a 603 plus
+//
+
+hcss.603p:
+
+ lwz r.5, [toc]HalpSweepDcache603p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603p(r.toc)
+ b hcss.done
+
+//
+// Processor is an Arthur. Note: Arthur uses the 603 routines
+// for everything except SweepDcache.
+//
+
+hcss.603art:
+
+ lwz r.5, [toc]HalpSweepDcache603art(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603(r.toc)
+ b hcss.done
+
+//
+// processor is a 604 plus
+//
+
+hcss.604p:
+
+ lwz r.5, [toc]HalpSweepDcache604p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604p(r.toc)
+ b hcss.done
+
+//
+// processor is a 620
+//
+
+hcss.620:
+
+ lwz r.5, [toc]HalpSweepDcache620(r.toc)
+ lwz r.6, [toc]HalpSweepIcache620(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange620(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange620(r.toc)
+ b hcss.done
+
+
+hcss.done:
+
+//
+// r.5 thru r.9 contain the address of the function descriptors
+// for the routines we really want to use. Dereference them to
+// get at the entry point addresses.
+//
+ lwz r.5, 0(r.5)
+ lwz r.6, 0(r.6)
+ lwz r.7, 0(r.7)
+ lwz r.8, 0(r.8)
+
+//
+// Store the entry point addresses directly into the TOC.
+// This is so direct linkage from within the HAL to the
+// generic cache flushing routines can get to the desired
+// routines for this processor.
+//
+
+ stw r.5, [toc]HalpSweepDcache(r.toc)
+ stw r.6, [toc]HalpSweepIcache(r.toc)
+ stw r.7, [toc]HalpSweepDcacheRange(r.toc)
+ stw r.8, [toc]HalpSweepIcacheRange(r.toc)
+
+//
+// Modify the Function Descriptors for the generic routines to
+// point directly at the target routines so that linkage from
+// other executables (eg the kernel) will be direct rather
+// than via the generic routines.
+//
+
+ lwz r.3, [toc]HalSweepDcache(r.toc)
+ lwz r.4, [toc]HalSweepIcache(r.toc)
+ stw r.5, 0(r.3)
+ stw r.6, 0(r.4)
+ lwz r.3, [toc]HalSweepDcacheRange(r.toc)
+ lwz r.4, [toc]HalSweepIcacheRange(r.toc)
+ stw r.7, 0(r.3)
+ stw r.8, 0(r.4)
+
+ li r.3, 0 // return code = success
+
+ LEAF_EXIT(HalpCacheSweepSetup)
+
+//++
+//
+// Routines HalSweepDcache
+// HalSweepIcache
+// HalSweepDcacheRange
+// HalSweepIcacheRange
+//
+// are simply dispatch points for the appropriate routine for
+// the processor being used.
+//
+//--
+
+
+ LEAF_ENTRY(HalSweepDcache)
+
+ lwz r.12, [toc]HalpSweepDcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcache)
+
+
+
+ LEAF_ENTRY(HalSweepIcache)
+
+ lwz r.12, [toc]HalpSweepIcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcache)
+
+
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+ lwz r.12, [toc]HalpSweepDcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcacheRange)
+
+
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+ lwz r.12, [toc]HalpSweepIcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcacheRange)
+
+
+//++
+//
+// 601 Cache Flushing Routines
+//
+// The 601 has a unified instruction/data cache and coherency is
+// maintained. For this reason these routines don't need to do
+// anything.
+//
+// HalpSweepDcache601
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache601)
+
+ LEAF_EXIT(HalpSweepDcache601)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange603
+//
+// HalpSweepDcacheRange603p
+//
+// HalpSweepDcacheRange604
+//
+// HalpSweepDcacheRange604p
+//
+// Force data in a given address range to memory.
+//
+// Because this routine works on a range of blocks and block size
+// is the same on 601, 603, 603+, 604 and 604+ we can use the same
+// code for each of them.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603p)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ601-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ601-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2601 // number of blocks
+ mtctr r.4
+ sync
+hsdr601.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ601 // bump address
+ bdnz hsdr601.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange604)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange601
+//
+// Due to the unified cache, this routine is meaningless on a 601.
+// The reason for flushing a range of instruction address is because
+// of code modification (eg breakpoints) in which case the nature
+// of the unified cache is that the *right* code is in the cache,
+// or because of a transfer of a code page in which case the unified
+// snooping cache will have done the right thing.
+//
+// Therefore this routine simply returns.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange601)
+
+ // return
+
+ LEAF_EXIT(HalpSweepIcacheRange601)
+
+//++
+//
+// 603, 603+ Cache Flushing Routines
+//
+// The 603 has seperate instruction and data caches of 8 KB each.
+// The 603+ has seperate instruction and data caches of 16 KB each.
+// Line size = Block size = 32 bytes.
+//
+// The mechanics of cache manipulation are the same for the 603 and
+// 603+.
+//
+//
+//
+// HalpSweepDcache603 HalpSweepDcache603p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// The 603 does not have a hashed page table so we can't use the
+// hashed page table as the data range. Instead use the start of
+// KSEG0.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache603p)
+
+ li r.4, DCB603E // size of 603+ cache in blocks
+ b hsd603
+
+ DUMMY_EXIT(HalpSweepDcache603p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache603)
+
+ li r.4, DCB603 // size of 603 cache in blocks
+hsd603:
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ cror 0,0,0 // 603e/603ev errata 15
+ sync // ensure ALL previous stores completed
+ LWI(r.3,0x80000000) // known usable virtual address
+ subi r.5, r.3, DCBSZ603 // dec addr prior to inc
+hsd603.ld:
+ lbzu r.8, DCBSZ603(r.5)
+ bdnz hsd603.ld
+ ENABLE_INTERRUPTS(r.10)
+ cror 0,0,0 // 603e/603ev errata 15
+
+ mtctr r.4
+hsd603.fl:
+ dcbst 0, r.3 // ensure block is in memory
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsd603.fl
+
+ LEAF_EXIT(HalpSweepDcache603)
+
+
+
+
+//++
+//
+// HalpSweepIcache603 HalpSweepIcache603p
+//
+// Sweep the entire instruction cache. The instruction cache (by
+// definition) can never contain modified code (hence there are no
+// icbf or icbst instructions). Therefore what we really need to do
+// here is simply invalidate every block in the cache. This can be
+// done by toggling the Instruction Cache Flash Invalidate (ICFI) bit
+// in the 603's HID0 register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache603)
+
+ ALTERNATE_ENTRY(HalpSweepIcache603p)
+
+ mfspr r.3, HID0 // 603, use Instruction
+ ori r.4, r.3, H0_603_ICFI // Cache Flash Invalidate
+
+ isync
+ mtspr HID0, r.4 // invalidate I-Cache
+ mtspr HID0, r.3 // re-enable
+
+ LEAF_EXIT(HalpSweepIcache603)
+
+
+
+//++
+//
+// HalpSweepIcacheRange603 HalpSweepIcacheRange603p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Note that if this is going to take a long time we flash
+// invalidate the I cache instead. Currently I define a
+// "long time" as greater than 4096 bytes which amounts to
+// 128 trips thru this loop (which should run in 256 clocks).
+// This number was selected without bias or forethought from
+// thin air - plj. I chose this number because gut feel tells
+// me that it will cost me more than 256 clocks in cache misses
+// trying to get back to the function that requested the cache
+// flush in the first place.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange603p)
+
+ cmpwi r.4, 4096 // if range > 4096 bytes, flush
+ bgt- ..HalpSweepIcache603 // entire I cache
+
+ rlwinm r.5, r.3, 0, DCBSZ603-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ603-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2603 // number of blocks
+ mtctr r.4
+hsir603.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsir603.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange603)
+
+//++
+//
+// 603 "Arthur" Cache Flushing Routines
+//
+// Arthur is similar to the 603 in most ways. Differences are:-
+//
+// Size: Arthur's caches are 32KB each.
+// Associativity: Arthur has 128 sets of 8 blocks.
+// Flash Invalidate: Arthur will automatically clear the flash
+// invalidate bit in HID0 where the 603 required
+// that you clear it manually. However, it is
+// ok to to it the old way.
+// Block Replacement Algorithm:
+// Arthur uses a Pseudo Least Recently Used algorithm
+// where other 603s use a strictly LRU mechanism. In
+// order to flush the entire D-Cache we must either
+// touch 12 individual blocks with address bits 20:26
+// that hit the same set, OR, we must set a bit in HID0
+// that causes to use a strict LRU mechanism while doing
+// the flush and turn that bit off again at the end.
+// Hashed Page Table:
+// Arthur DOES use a hashed page table.
+//
+// In light of the above, we use the standard 603 routines for all
+// Arthur's cache flushing routines except the Sweep D-Cache routine.
+//
+//
+// HalpSweepDcache603art
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// Note: Because Arthur has a Hashed Page Table, we use it in the
+// same way as the 604 for cache flushing and therefore do not need
+// the store loop that follows the load loop in the 603 routine.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache603art)
+
+ li r.4, DCB603ART // size of Arthur cache in blocks
+ mfmsr r.10 // prep to disable ints and data xlate
+ mfspr r.9, HID0 // need to set Data Cache Flush Assist
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's useful and we don't
+ // have to flush it).
+ mtctr r.4
+ rlwinm r.11, r.10, 0, 0xffff7fff// clear INT Enable bit
+ sync // ensure ALL previous stores complete
+ mtmsr r.11 // disable interrupts
+ ori r.7, r.9, H0_603_DCFA
+ oris r.3, r.3, 0x8000 // make addr virtual
+ mtspr HID0,r.7 // set Data Cache Flush Assist
+ subi r.3, r.3, DCBSZ603 // dec addr prior to inc
+ isync
+hsd603art.ld:
+ lbzu r.8, DCBSZ603(r.3)
+ bdnz hsd603art.ld
+ sync
+ mtspr HID0,r.9 // clear Data Cache Flush Assist
+ mtmsr r.10 // reset previous interrupt enable
+ // state.
+
+ LEAF_EXIT(HalpSweepDcache603art)
+
+//++
+//
+// 604 Cache Flushing Routines
+//
+// The 604 has seperate instruction and data caches of 16 KB each.
+// The 604+ has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 32 bytes.
+//
+//
+//
+// HalpSweepDcache604 HalpSweepDcache604p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache604p)
+
+ li r.4, DCB604E // size of 604+ cache in blocks
+ b hsd604
+
+ DUMMY_EXIT(HalpSweepDcache604p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache604)
+
+ li r.4, DCB604 // size of cache in cache blocks
+hsd604:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync // ensure ALL previous stores completed
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ604 // dec addr prior to inc
+hsd604.ld:
+ lbzu r.8, DCBSZ604(r.5)
+ bdnz hsd604.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ sync
+
+ LEAF_EXIT(HalpSweepDcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcache604 HalpSweepIcache604p
+//
+// Sweep the entire instruction cache. This routine is functionally
+// similar to the 603 version except that on the 604 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Invali-
+// sate All (ICIA) and it clears automatically after being set.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache604)
+
+ ALTERNATE_ENTRY(HalpSweepIcache604p)
+
+ mfspr r.3, HID0 // 604, use Instruction
+ ori r.3, r.3, H0_604_ICIA // Cache Invalidate All
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange604 HalpSweepIcacheRange604p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ604-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ604-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2604 // number of blocks
+ mtctr r.4
+hsir604.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ604 // bump address
+ bdnz hsir604.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange604)
+
+//++
+//
+// 620 Cache Flushing Routines
+//
+// The 620 has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 64 bytes.
+//
+//
+//
+// HalpSweepDcache620
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache620)
+
+ li r.4, DCB620 // size of cache in cache blocks
+hsd620:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ620 // dec addr prior to inc
+hsd620.ld:
+ lbzu r.8, DCBSZ620(r.5)
+ bdnz hsd620.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ sync
+
+ LEAF_EXIT(HalpSweepDcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcache620
+//
+// Sweep the entire instruction cache. This routine is functionally
+// identical to the 604 version except that on the 620 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Edge
+// Flash Invalidate (ICEFI).
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache620)
+
+ mfspr r.3, HID0 // 620, use Instruction
+ ori r.3, r.3, H0_620_ICEFI // Cache Edge Flash Invalidate
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange620
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+hsir620.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsir620.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange620)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange620
+//
+// Force data in a given address range to memory.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+ sync
+hsdr620.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsdr620.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange620)
+
+//++
+//
+// HalpSweepPhysicalRangeInBothCaches
+//
+// Force data in a given PHYSICAL address range to memory and
+// invalidate from the block in the instruction cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .set PAGE_SHIFT, 12
+
+
+ LEAF_ENTRY(HalpSweepPhysicalRangeInBothCaches)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+ cror 0,0,0 // N.B. 603e/ev errata 15
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspribc
+hspribc:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspribc.real - hspribc
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspribc.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspribc.loop:
+ dcbst 0, r.4 // flush data block to memory
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspribc.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalRangeInBothCaches)
+
+//++
+//
+// HalpSweepPhysicalIcacheRange
+//
+// Invalidate a given PHYSICAL address range from the instruction
+// cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepPhysicalIcacheRange)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+ cror 0,0,0 // N.B. 603e/ev errata 15
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspir
+hspir:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspir.real - hspir
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+//
+// N.B. It may not be required that Data Relocation be disabled here.
+// I can't tell from my Arch spec if ICBI works on a Data or
+// Instruction address. I believe it is probably a Data
+// address even though it would be sensible for it to be an
+// instruction address,....
+//
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspir.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspir.loop:
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspir.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalIcacheRange)
diff --git a/private/ntos/nthals/halppc/ppc/pxcalstl.c b/private/ntos/nthals/halppc/ppc/pxcalstl.c
new file mode 100644
index 000000000..9adb8c453
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxcalstl.c
@@ -0,0 +1,132 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service for a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jim Wooldridge
+ Steve Johns (Motorola)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// KeQueryPerformanceCounter & KeStallExecutionProcessor are called
+// before Phase 0 initialization, so initialize it to a reasonable value.
+//
+ULONG HalpPerformanceFrequency = 80000000/16;
+ULONG CpuFrequency;
+extern ULONG HalpClockCount;
+extern ULONG HalpFullTickClockCount;
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+
+#endif
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Set initial scale factor
+ //
+
+ PCR->StallScaleFactor = 1;
+
+ //
+ // Compute the clock frequency of the Time Base & Decrementer
+ //
+
+ HalpPerformanceFrequency = HalpCalibrateTB();
+
+ if (HalpPerformanceFrequency <= 718200) {
+ DbgBreakPoint();
+ while (HalpPerformanceFrequency <= 718200) {
+ HalpPerformanceFrequency = HalpCalibrateTB();
+ }
+ }
+
+ HalpPerformanceFrequency = (HalpPerformanceFrequency / 1000) * 1000;
+
+
+ //
+ // If it's the POWER architecture, then RTC is clocked at 7.8125 MHz
+ //
+ if (HalpPerformanceFrequency >= 7812000 &&
+ HalpPerformanceFrequency < 7813000) {
+ HalpPerformanceFrequency = 7812500;
+ } else {
+
+ //
+ // Compute (CPU frequency)*10
+ //
+ CpuFrequency = HalpPerformanceFrequency * 8/100000;
+
+ //
+ // Assume RTC/TB frequency = CpuFrequency/8
+ //
+ HalpPerformanceFrequency = CpuFrequency * 100000 / 8;
+
+ }
+ //
+ // Initialize the system clock variable
+ //
+ HalpClockCount = (HalpPerformanceFrequency * (MAXIMUM_INCREMENT/10000)) / 1000;
+ HalpFullTickClockCount = HalpClockCount;
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxclksup.s b/private/ntos/nthals/halppc/ppc/pxclksup.s
new file mode 100644
index 000000000..f947b0a05
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxclksup.s
@@ -0,0 +1,153 @@
+/***********************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+ File Name:
+ PXCLKSUP.S
+
+ Globals:
+ none
+
+ Functions:
+ HalpUpdateDecrementer
+ KeQueryPerformanceCounter
+
+ History:
+ 11-Feb-1994 Steve Johns
+ Original Version
+ 23-Jun-1994 Steve Johns (sjohns@pets.sps.mot.com)
+ Fixed HalpZeroPerformanceCounter. Was writing to RTCU & RTCL.
+ Writes should go to SPR 20 & 21.
+***********************************************************************/
+
+#include <halppc.h>
+#define ERRATA603 TRUE
+
+
+
+
+ LEAF_ENTRY(HalpUpdateDecrementer)
+
+
+ mfpvr r.6 // Read Processor Version Register
+ rlwinm r.6,r.6,16,16,31
+ cmpli 0,0,r.6,1 // Is it an MPC601 ?
+ bne Not_601
+ rlwinm r.3,r.3,7,0,24 // Yes, Count *= 128
+Not_601:
+//
+// Read the DECREMENTER to get the interrupt latency and bias Count by
+// that amount. Otherwise, the latencies would accumulate and the time
+// of day would run slow.
+//
+ mfdec r.7 // Read the DECREMENTER
+ add r.4,r.3,r.7 // + Count
+//
+// We expect that the DECREMENTER should be near 0xFFFFFFxx, so R4 should
+// be less than r.3. If not, we don't want to cause an excessively long
+// clock tick, so just ignore the latency and use Count.
+//
+ cmpl 0,0,r.4,r.3
+ ble SetDecr
+ mr r.4,r.3
+SetDecr:
+
+ mtdec r.4 // Write to the DECREMENTER
+#if ERRATA603
+ isync
+#endif
+
+// Undocumented return value: the latency in servicing this interrupt
+ neg r.3,r.7
+
+
+ LEAF_EXIT(HalpUpdateDecrementer)
+
+
+
+ .extern HalpPerformanceFrequency
+ .extern ..HalpGetTimerRoutine
+
+
+/***********************************************************************
+ Synopsis:
+ ULARGE_INTEGER KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
+
+ Purpose:
+ Supplies a 64-bit realtime counter for use in evaluating performance
+ of routines.
+
+ Returns:
+ This routine returns current 64-bit performance counter and,
+ optionally, the frequency of the Performance Counter.
+
+ Global Variables Referenced:
+ HalpPerformanceFrequency
+
+***********************************************************************/
+
+//
+// Register Definitions
+//
+ .set RetPtr, r.3
+ .set Freq, r.4
+ .set TimerLo, r.4 // MUST be same as defined in PXSTALL.S
+ .set TimerHi, r.5 // MUST be same as defined in PXSTALL.S
+ .set Temp, r.7
+
+ .set RTCU, 4
+ .set RTCL, 5
+ .set TB, 284
+ .set TBU, 285
+
+
+ LEAF_ENTRY(KeQueryPerformanceCounter)
+
+ mflr r.0 // Save Link Register
+
+ cmpli 0,0,Freq,0 // Was PerformanceFrequency passed ?
+ beq GetCpuVersion
+
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp) // PerformanceFrequency.LowPart =
+ stw Temp,0(Freq) // HalpPerformanceFrequency;
+ li Temp,0 // PerformanceFrequency.HighPart = 0;
+ stw Temp,4(Freq)
+
+GetCpuVersion:
+ bl ..HalpGetTimerRoutine
+
+ bctrl // ReadPerformanceCounter();
+
+ stw TimerLo,0(RetPtr)
+ stw TimerHi,4(RetPtr)
+ mtlr r.0 // Restore Link Register
+
+ LEAF_EXIT(KeQueryPerformanceCounter)
+
+
+ LEAF_ENTRY(HalpZeroPerformanceCounter)
+
+
+ mfpvr r.4 // Read Processor Version Register
+ li r.3, 0
+ rlwinm r.4,r.4,16,16,31
+ cmpli 0,0,r.4,1 // Are we running on an MPC601 ?
+ beq ZeroRTC // Branch if yes
+
+ mtspr TB,r.3
+ mtspr TBU,r.3
+
+ blr
+
+ZeroRTC:
+ mtspr 20,r.3 // Zero the RTC registers
+ mtspr 21,r.3
+
+
+ LEAF_EXIT(HalpZeroPerformanceCounter)
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxclock.c b/private/ntos/nthals/halppc/ppc/pxclock.c
new file mode 100644
index 000000000..ace9f2d32
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxclock.c
@@ -0,0 +1,283 @@
+
+/*****************************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ PXCLOCK.C
+
+Abstract:
+
+ This module contains the system clock interrupt handler.
+ The DECREMENTER is used to implement the system clock. The
+ handler resets the DECREMENTER to SYSTEM_TIME (accounting
+ for interrupt latency), and updates the system time.
+
+
+Author:
+
+ Steve Johns 10-Feb-1994
+
+Revision History:
+
+******************************************************************************/
+
+#include "halp.h"
+
+extern ULONG HalpPerformanceFrequency;
+
+BOOLEAN
+KdPollBreakIn (
+ VOID
+ );
+
+ULONG HalpClockCount;
+ULONG HalpFullTickClockCount;
+ULONG HalpUpdateDecrementer();
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNewTimeIncrement;
+
+#if defined(SOFT_HDD_LAMP)
+
+extern HDD_LAMP_STATUS HalpHddLamp;
+
+#endif
+
+BOOLEAN
+HalpHandleDecrementerInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processor 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpClockCount);
+
+ //
+ // Call the kernel to update system time
+ //
+
+ KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
+
+ HalpCurrentTimeIncrement = HalpNewTimeIncrement;
+
+#if defined(SOFT_HDD_LAMP)
+
+ //
+ // If HDD Lamp is on and there have been no new interrupts for
+ // mass storage interrupts for enough ticks that the count has
+ // gone zero, turn it off.
+ //
+
+ if ( HalpHddLamp.Count > 0 ) {
+ if ( --HalpHddLamp.Count == 0 ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 0;
+ }
+ }
+
+#endif
+
+ //
+ // Lower Irql to original value and enable interrupts
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+#if defined(WOODFIELD)
+
+ //
+ // added read to initiate a PCI I/O cycle in order to work around
+ // woodfield prime SIO DMA bug
+ //
+
+ {
+ volatile UCHAR DataByte;
+ DataByte = READ_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + 0xcf8);
+ }
+
+#endif
+
+ HalpEnableInterrupts();
+
+ if ( KdDebuggerEnabled && KdPollBreakIn() ) {
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ }
+
+ return (TRUE);
+}
+
+
+#if defined(_MP_PPC_)
+
+BOOLEAN
+HalpHandleDecrementerInterrupt1(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processors other than 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpFullTickClockCount);
+
+ //
+ // Call the kernel to update run time for this thread and process.
+ //
+
+ KeUpdateRunTime(TrapFrame);
+
+ //
+ // Lower Irql to original value
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ return TRUE;
+}
+
+#endif
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // HalpPerformanceFrequence is the number of times the decrementer
+ // ticks in 1 second. MINIMUM_INCREMENT is the number of 100 is the
+ // number of 100ns units in 1 ms.
+ // Therefore, DesiredIncrement/MINUMUM_INCREMENT is the number of
+ // ms desired. This multiplied by the number of decrementer ticks
+ // in 1 second, divided by 1000 gives the number of ticks in the
+ // desired number of milliseconds. This value will go into the
+ // decrementer.
+ //
+
+ NextIntervalCount = (HalpPerformanceFrequency *
+ (DesiredIncrement/MINIMUM_INCREMENT)) / 1000;
+
+ //
+ // Calculate the number of 100ns units to report to the kernel every
+ // time the decrementer fires with this new period. Note, for small
+ // values of DesiredIncrement (min being 10000, ie 1ms), truncation
+ // in the above may result in a small decrement in the 5th decimal
+ // place. As we are effectively dealing with a 4 digit number, eg
+ // 10000 becomes 9999.something, we really can't do any better than
+ // the following.
+ //
+
+ NewTimeIncrement = DesiredIncrement/MINIMUM_INCREMENT * MINIMUM_INCREMENT;
+ HalpClockCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxdakota.h b/private/ntos/nthals/halppc/ppc/pxdakota.h
new file mode 100644
index 000000000..02a2e2419
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdakota.h
@@ -0,0 +1,67 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxdakota.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Dakota memory controllers.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define stuctures for memory control and planar register
+//
+
+
+
+typedef struct _DAKOTA_CONTROL {
+ UCHAR Reserved0[0x803]; // Offset 0x000
+ UCHAR SimmId; // Offset 0x803
+ UCHAR SimmPresent; // Offset 0x804
+ UCHAR Reserved1[3];
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[3];
+ UCHAR Keylock; // Offset 0x818
+ UCHAR Reserved7[3];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved8[3];
+ UCHAR MemoryController; // Offset 0x820
+ UCHAR MemoryControllerTiming; // Offset 0x821
+ UCHAR Reserved9[0x16];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR Reserved10[3];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR Reserved11[3];
+ UCHAR MemoryParityErrorStatus; // Offset 0x840
+ UCHAR MemoryParityErrorClear; // Offset 0x841
+ UCHAR L2CacheErrorStatus; // Offset 0x842
+ UCHAR L2CacheErrorClear; // Offset 0x843
+ UCHAR TransferErrorStatus; // Offset 0x844
+ UCHAR TransferErrorClear; // Offset 0x845
+ UCHAR Reserved12[0xa];
+ UCHAR IoMap; // Offset 0x850
+ UCHAR Reserved13[3];
+} DAKOTA_CONTROL, *PDAKOTA_CONTROL;
diff --git a/private/ntos/nthals/halppc/ppc/pxdat.c b/private/ntos/nthals/halppc/ppc/pxdat.c
new file mode 100644
index 000000000..f04c00971
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdat.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x000, 0x10, // SIO DMA
+ 0x0C0, 0x20, // SIO DMA
+ 0x080, 0x10, // SIO DMA
+ 0x400, 0x40, // SIO DMA
+ 0x480, 0x10, // SIO DMA
+ 0x4D6, 0x2, // SIO DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+
+ 0x074, 0x4, // NVRAM
+
+ 0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+// This structure will be filled in with the address usage for
+// the MPIC interrupt controller.
+ADDRESS_USAGE HalpMpicSpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0
+ }
+};
+
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+#ifdef POWER_MANAGEMENT
+//
+// From ixinfo.c
+//
+
+WCHAR rgzSuspendCallbackName[] = L"\\Callback\\SuspendHibernateSystem";
+
+#endif // POWER_MANAGEMENT
+
+//
+// From ixpcibrd.c
+//
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
diff --git a/private/ntos/nthals/halppc/ppc/pxdisp.c b/private/ntos/nthals/halppc/ppc/pxdisp.c
new file mode 100644
index 000000000..3aeac5dd8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdisp.c
@@ -0,0 +1,1733 @@
+
+/*++
+
+Copyright (c) 1994, 95, 96 International Business Machines Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
+ video adapter.
+
+Author:
+
+ Jim Wooldridge Sept 1994 - Ported to PowerPC Initial Version
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jess Botts S3 support in text mode Oct-1993
+ Lee Nolan Added Weitek P9000 support Feb-1994
+ Mike Haskell Added Weitek P9100 support Oct-1994
+ Tim White Added GXT150P support Feb-1995
+ Jake Oshins Rearranged everything Jun-1995
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "pxdisp.h"
+#include "string.h"
+#include "pxP91.h"
+
+//=============================================================================
+//
+// IBMBJB added include to get text mode values for the Brooktree 485 DAC's
+// palette registers, removed definition of HDAL and added address
+// definitions for PowerPC
+
+#include "txtpalet.h"
+#include "pci.h"
+#include "pcip.h"
+
+#if defined(_PPC_)
+# define VIDEO_ROM_OFFSET 0x000C0000
+# define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
+# define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
+
+#endif
+
+
+
+#define READ_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//PHYSICAL ADDRESS of WEITEK P9000 video ram
+#define P9_VIDEO_MEMORY_BASE 0xC1200000
+
+//PHYSICAL ADDRESS of WEITEK P9100 video ram
+#define P91_VIDEO_MEMORY_BASE 0xC1800000
+
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+#define S3_928_DEVICE_ID 0x88B05333
+#define S3_864_DEVICE_ID 0x88C05333
+#define P9_DEVICE_ID 0x1300100E
+#define P91_DEVICE_ID 0x9100100E
+#define BBL_DEVICE_ID 0x001B1014
+#define BL_DEVICE_ID 0x003C1014
+#define WD_90C_DEVICE_ID 0xC24A101c
+#define UNKNOWN_DEVICE_ID 0x0
+
+#define MAX_PCI_BUSSES 256
+
+//PHYSICAL ADDRESSES for GXT150P adapter
+// (in bbldef.h)
+
+// Include GXT150P header file information
+//#include "bblrastz.h"
+//#include "bblrmdac.h"
+#include "bbldef.h"
+
+#define TAB_SIZE 4
+
+
+//
+// Prototypes.
+//
+
+#if defined(_MP_PPC_)
+
+VOID
+HalpAcquireDisplayLock(
+ VOID
+ );
+
+VOID
+HalpReleaseDisplayLock(
+ VOID
+ );
+
+#endif
+
+VOID
+HalpDisplayCharacterVgaViaBios (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDispCharVgaViaBios (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplaySetupVgaViaBios (
+ VOID
+ );
+
+VOID
+HalpPositionCursorVgaViaBios (
+ IN ULONG Row,
+ IN ULONG Column
+ );
+
+VOID
+ScrollScreenVgaViaBios (
+ IN UCHAR LinesToScroll
+ );
+
+VOID
+HalpSetupAndClearScreenVgaViaBios (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayPpcWDSetup (
+ VOID
+ );
+
+
+VOID
+HalpCopyOEMFontFile();
+
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+ScreenOn (
+ VOID
+ );
+
+VOID
+ScreenOff (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+
+#if !defined(WOODFIELD)
+
+//
+// Woodfield - IBM PowerPC LapTop machines don't support plug in PCI
+// video adapters so don't pull the init code for those adapters into
+// the HAL.
+//
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcBBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBBL (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBL (
+ IN UCHAR Character
+ );
+
+#endif
+
+//
+//
+//
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+extern ULONG HalpPciMaxSlots;
+
+extern BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ );
+
+extern VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ );
+
+extern VOID
+HalpP91RelinquishDisplayOwnership();
+
+//
+// Define static data.
+//
+BOOLEAN HalpDisplayOwnedByHal;
+
+volatile PUCHAR HalpVideoMemoryBase = (PUCHAR)0;
+volatile PUCHAR HalpVideoCoprocBase = (PUCHAR)0;
+
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+
+ULONG HalpDisplayPciDeviceId;
+extern ULONG HalpInitPhase;
+//
+// Define OEM font variables.
+//
+
+USHORT HalpBytesPerRow;
+USHORT HalpCharacterHeight;
+USHORT HalpCharacterWidth;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+ULONG HalpColumn;
+ULONG HalpRow;
+ULONG HalpHorizontalResolution;
+ULONG HalpVerticalResolution;
+
+
+UCHAR HalpDisplayIdentifier[256] = "";
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+POEM_FONT_FILE_HEADER HalpFontHeader;
+
+extern ULONG HalpEnableInt10Calls;
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+
+BOOLEAN HalpBiosShadowed = FALSE;
+ULONG HalpVideoBiosLength = 0;
+PUCHAR HalpShadowBuffer;
+extern UCHAR HalpShadowBufferPhase0;
+
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ LONG SlotNumber = HalpPciMaxSlots - 1;
+ LONG BusNumber = 0;
+ ULONG VideoDeviceSlotNumber = HalpPciMaxSlots + 1; // start with an impossible value
+ ULONG VideoDeviceBusNumber = 0;
+ UCHAR BaseClassCode;
+ UCHAR SubClassCode;
+ ULONG Device_Vendor_Id;
+ ULONG RomBaseAddress;
+ ULONG PCICommand;
+ ULONG AmountRead = 1;
+ ULONG DeleteIoSpace = 0;
+ ULONG VgaBiosShadowOffset = 0xffffffff;
+
+
+ //
+ // For the Weitek P9100, set the address of the font file header.
+ // Display variables are computed later in HalpDisplayPpcP9Setup.
+ //
+ // This is changed as Phase 1 init starts. The font is copied
+ // out of the LoaderBlock and into non-paged pool so that it
+ // can be used again if the machine bluescreens.
+ //
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+
+
+ //
+ // Read the Registry entry to find out which video adapter the system
+ // is configured for. This code depends on the OSLoader to put the
+ // correct value in the Registry.
+ //
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ //
+ // Determine controller setup routine, display character routine, and PCI device id
+ // via configuration tree
+ //
+
+
+
+ if (ConfigurationEntry != NULL) {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"S3_928")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterS3;
+ HalpDisplayPciDeviceId = S3_928_DEVICE_ID;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"S3_864")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterS3;
+ HalpDisplayPciDeviceId = S3_864_DEVICE_ID;
+
+#if !defined(WOODFIELD)
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP91;
+ HalpDisplayPciDeviceId = P91_DEVICE_ID;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"GXT150P")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcBBLSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterBBL;
+ HalpDisplayPciDeviceId = BBL_DEVICE_ID;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"GXT250P")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcBLSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterBL;
+ HalpDisplayPciDeviceId = BL_DEVICE_ID;
+
+#endif
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"WD_90C")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcWDSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterS3;
+ HalpDisplayPciDeviceId = WD_90C_DEVICE_ID;
+ }
+
+ } else {
+
+ HalpDisplayControllerSetup = NULL;
+ HalpDisplayCharacter = NULL;
+ HalpDisplayPciDeviceId = UNKNOWN_DEVICE_ID;
+ }
+
+ //
+ // Check to see if BIOS exists for the display controller
+ //
+
+ if (HalpPhase0MapBusConfigSpace() == TRUE) {
+
+ while (BusNumber < (LONG)HalpPciMaxBuses) {
+ SlotNumber = HalpPciMaxSlots - 1;
+
+ while (SlotNumber >= 0) {
+
+ //
+ // Just shut off all the video chips. We will re-enable
+ // the one we want later.
+ //
+ HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &BaseClassCode,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ BaseClass),
+ sizeof(BaseClassCode));
+
+ HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &SubClassCode,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ SubClass),
+ sizeof(SubClassCode));
+ //
+ // Is this a display adapter?
+ //
+
+ if (((BaseClassCode == PCI_DISPLAY_CONTROLLER) && (SubClassCode == 0)) ||
+ ((BaseClassCode == PCI_PRE_REV_2) && (SubClassCode == 1))) {
+
+ HalpPhase0GetPciDataByOffset (
+ BusNumber,
+ SlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+ //
+ // Disble IO and Memory space decoding
+ //
+
+ PCICommand &= (~PCI_ENABLE_IO_SPACE &
+ ~PCI_ENABLE_MEMORY_SPACE &
+ ~PCI_ENABLE_BUS_MASTER);
+
+ HalpPhase0SetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &PCICommand,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ Command),
+ sizeof (PCICommand)
+ );
+ }
+
+ //
+ // If we have already found a video card, skip
+ // the following section
+ //
+ if (VideoDeviceSlotNumber < HalpPciMaxSlots) {
+ SlotNumber--;
+ continue;
+ }
+
+ //
+ // Now test to see if this is the one ARC used. (This algorithm
+ // will identify either the chip with the same ID that ARC used
+ // or, in the case that we don't recognize the ID, the chip in
+ // the highest slot number that is a video device.
+
+ if (HalpDisplayPciDeviceId == UNKNOWN_DEVICE_ID) {
+
+ //
+ // Is this a display adapter?
+ //
+
+ if (((BaseClassCode == PCI_DISPLAY_CONTROLLER) && (SubClassCode == 0)) ||
+ ((BaseClassCode == PCI_PRE_REV_2) && (SubClassCode == 1))) {
+ // This is the one we want to use, so save the slot number
+ VideoDeviceSlotNumber = SlotNumber;
+ VideoDeviceBusNumber = BusNumber;
+ }
+ } else {
+
+ //
+ // Find the pci slot of the display controller
+ //
+
+ HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &Device_Vendor_Id,
+ 0,
+ sizeof(Device_Vendor_Id));
+
+
+ //
+ // In the following, when we apply a mask to the
+ // Device_Vendor_Id it's to hide the chip revision.
+ //
+ if ( ((Device_Vendor_Id & 0xFFF0FFFF) == S3_928_DEVICE_ID) ||
+ ((Device_Vendor_Id & 0xFFF0FFFF) == S3_864_DEVICE_ID) ||
+ ((Device_Vendor_Id & 0xFFF0FFFF) == P9_DEVICE_ID) ||
+ ((Device_Vendor_Id & 0xFFF0FFFF) == P91_DEVICE_ID) ||
+ ( Device_Vendor_Id == BBL_DEVICE_ID) ||
+ ( Device_Vendor_Id == BL_DEVICE_ID) ||
+ ( Device_Vendor_Id == WD_90C_DEVICE_ID) ) {
+ VideoDeviceSlotNumber = SlotNumber;
+ VideoDeviceBusNumber = BusNumber;
+ }
+ }
+
+ SlotNumber--;
+
+ }
+ BusNumber++;
+ }
+
+ if (VideoDeviceSlotNumber < HalpPciMaxSlots) {
+ //
+ // Turn the video chip back on
+ //
+ HalpPhase0GetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ Command),
+ sizeof (PCICommand)
+ );
+
+ PCICommand |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalpPhase0SetPciDataByOffset (VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+
+ //
+ // Determine what ROM base address should be
+ //
+
+ // Writing 0xFFFFFFFE to the register and then reading it tells us what
+ // our bounds are.
+ RomBaseAddress = 0xFFFFFFFE;
+ HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+ HalpPhase0GetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+
+ //
+ // Strip lowest bit, which is for enabling decoders.
+ //
+ RomBaseAddress &= 0xFFFFFFFE;
+
+ //
+ // This sets the least significant bit that we were able to change,
+ // which tells us how much space we need for the BIOS.
+ //
+ RomBaseAddress = ((~RomBaseAddress) + 1) & RomBaseAddress;
+
+ // If this ROM is small enough, put it in the normal VGA ROM position
+ if (RomBaseAddress <= 0x10000) {
+ RomBaseAddress = 0x00c0000;
+ }
+ else {
+ RomBaseAddress = 0;
+ }
+
+
+ RomBaseAddress = RomBaseAddress | 0x00000001; //Switch on ROM decoding
+
+ //
+ // Now write it all back
+ //
+ HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+
+ //
+ // Now map I/O memory space so we can look at the BIOS
+ //
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
+ 0x400000); // 4 MB
+ HalpIoMemoryBase = HalpVideoMemoryBase;
+
+ //
+ // Test to see if there is a BIOS present
+ //
+ if ((*((PUSHORT)HalpIoMemoryBase + (0xc0000 / 2))) == 0xaa55) {
+
+ VgaBiosShadowOffset = 0xc0000;
+
+ } else if ((*((PUSHORT)HalpIoMemoryBase)) == 0xaa55) {
+
+ VgaBiosShadowOffset = 0x0;
+ }
+
+ if (VgaBiosShadowOffset != 0xffffffff) {
+
+ //
+ // Shadow the BIOS
+ //
+ HalpVideoBiosLength = (*((PUCHAR)HalpIoMemoryBase + VgaBiosShadowOffset + 2)) * 512;
+
+ HalpShadowBuffer = &HalpShadowBufferPhase0;
+
+ RtlCopyMemory(HalpShadowBuffer,
+ (PUCHAR)HalpIoMemoryBase + VgaBiosShadowOffset,
+ HalpVideoBiosLength);
+
+ HalpBiosShadowed = TRUE;
+
+
+ //
+ // Try INT10
+ //
+ HalpInitializeX86DisplayAdapter(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber);
+
+ }
+
+ if (HalpEnableInt10Calls == TRUE) {
+ HalpDisplayControllerSetup = HalpDisplaySetupVgaViaBios;
+ HalpDisplayCharacter = HalpDisplayCharacterVgaViaBios;
+
+ } else {
+ KePhase0DeleteIoMap(PCI_MEMORY_PHYSICAL_BASE, 0x400000);
+ HalpVideoMemoryBase = NULL;
+ HalpIoMemoryBase = NULL;
+ }
+
+ //
+ // If the BIOS might be too large to leave mapped into ISA expansion
+ // space, stop decoding the BIOS because we have either shadowed it
+ // or it didn't exist in the first place.
+ //
+ // I would unmap all BIOSes, but the S3 chips seem to stop working if I do. -- Jake
+ if ((RomBaseAddress & 0xFFFFFFFE) == 0) {
+ RomBaseAddress = 0;
+ HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+ //
+ // Turn the video chip back on because the previous call may have turned it off
+ //
+ HalpPhase0GetPciDataByOffset (VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+
+ PCICommand |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalpPhase0SetPciDataByOffset (VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+ }
+
+ }
+
+ HalpPhase0UnMapBusConfigSpace();
+ }
+
+
+ // Save the display type in a global variable for use in the
+ // HalAcquireDisplayOwnership() function
+
+ strcpy(HalpDisplayIdentifier,
+ ConfigurationEntry->ComponentEntry.Identifier);
+
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+ HalpDisplayControllerSetup();
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpCopyBiosShadow(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine checks to see if there is a BIOS image in
+ HalpShadowBuffer and copies it to a block of non-paged
+ pool. This is done because HalpShadowBuffer will be
+ thrown away at the end of Phase 1. The idea is to
+ avoid wasting non-paged pool when we aren't using a
+ video BIOS.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ASSERT(HalpInitPhase == 1);
+
+ if (HalpBiosShadowed) {
+
+ HalpShadowBuffer = ExAllocatePool(NonPagedPool, HalpVideoBiosLength);
+
+ ASSERT(HalpShadowBuffer);
+
+ RtlCopyMemory((PVOID)HalpShadowBuffer,
+ (PVOID)&HalpShadowBufferPhase0,
+ HalpVideoBiosLength);
+
+ }
+}
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if !defined(WOODFIELD)
+
+ if (!strcmp(HalpDisplayIdentifier, "GXT150P")){
+
+ //
+ // Deleting access to the frame buffer here since we are about
+ // to give ownership of the display adapter to the miniport so
+ // we'll never touch the adapter again unless the system panics
+ // at which point we re-initialize anyway
+ //
+
+ // KePhase0DeleteIoMap(BBL_VIDEO_MEMORY_BASE,
+ // BBL_VIDEO_MEMORY_LENGTH);
+ }
+ else if (!strcmp(HalpDisplayIdentifier, "P9100")) {
+
+// HalpP91RelinquishDisplayOwnership();
+ }
+
+#endif
+
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+VOID
+HalpDisplaySetupVgaViaBios (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes a vga controller via bios reset.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// Routine Description:
+//
+//
+
+ ULONG DataLong;
+ PHYSICAL_ADDRESS physicalAddress;
+ XM86_CONTEXT Context ;
+
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
+ 0x400000); // 4 MB
+ }
+
+ HalpSetupAndClearScreenVgaViaBios () ;
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 50;
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplaySetupVgaViaBios() */
+
+
+VOID
+HalpDisplayCharacterVgaViaBios (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ ScrollScreenVgaViaBios (1);
+ }
+ } else if( Character == '\t' ) { // tab?
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) { // tab beyond end of screen?
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) ) {
+ ScrollScreenVgaViaBios (1) ; // scroll the screen up
+ } else {
+ ++HalpRow;
+ }
+ }
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpPositionCursorVgaViaBios( HalpRow, HalpColumn ) ;
+ HalpDispCharVgaViaBios(0x20);
+ }
+ } else if (Character >= 0x20) {
+ //
+ // Auto wrap for HalpDisplayWidth columns per line
+ //
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ ScrollScreenVgaViaBios (1);
+ }
+ }
+ HalpPositionCursorVgaViaBios( HalpRow, HalpColumn ) ;
+ HalpDispCharVgaViaBios (Character) ;
+ HalpColumn++ ;
+ }
+ return;
+}
+
+
+VOID
+HalpPositionCursorVgaViaBios (
+ IN ULONG Row,
+ IN ULONG Column
+ )
+
+/*++
+
+Routine Description:
+
+ This routine positions the cusor at a specified location.
+
+Arguments:
+
+ Row - row position for the cursor
+ Column - column position for the cursor
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+
+ // position the cursor
+ Context.Eax = 0x0200 ;
+ Context.Ebx = 0x0000 ;
+ Context.Edx = (Row << 8) | Column ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpPositionCursorVgaViaBios: FAILED\n" ) ;
+ }
+
+ return ;
+
+}
+
+
+
+VOID
+HalpDispCharVgaViaBios (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine prints a charcter at the current cursor positions.
+
+Arguments:
+
+ Character - character to be printed
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+
+ // display the character
+ Context.Eax = 0x0900 | Character ;
+ Context.Ebx = 0x001f ;
+ Context.Ecx = 1 ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpDispCharVgaViaBios: Putchar Call Failed\n" ) ;
+ }
+
+ return ;
+}
+
+
+VOID
+ScrollScreenVgaViaBios (
+ IN UCHAR LinesToScroll
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scrolls the screen up by "LinesToScroll" number of lines.
+
+Arguments:
+
+ LinesToScroll - number of lines to scroll up.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+
+ // scroll screen up
+ Context.Eax = 0x0600 | LinesToScroll ;
+ Context.Ebx = 0x1f00 ;
+ Context.Ecx = 0 ;
+ Context.Edx = 0x314f ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "ScrollScreenVgaViaBios: Scroll screen up Failed\n" ) ;
+ }
+
+ return;
+}
+
+
+
+
+VOID
+HalpSetupAndClearScreenVgaViaBios ( VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the text mode 3, loads ROM double dot set and
+ clears the screen.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+ ULONG x,y ;
+
+
+ // Switch Adaptor to text mode 3
+ Context.Eax = 0x0003 ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpSetupAndClearScreenVgaViaBios: Switch Adaptor to text mode 3 FAILED\n" ) ;
+ }
+
+ // load ROM double dot set
+ Context.Eax = 0x1112 ;
+ Context.Ebx = 0 ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpSetupAndClearScreenVgaViaBios: load ROM double dot set FAILED\n" ) ;
+ }
+
+
+
+ for ( x = 0; x < 50 ; x++ )
+ for ( y = 0; y < 80; y++ ) {
+ HalpPositionCursorVgaViaBios (x, y) ;
+ HalpDispCharVgaViaBios ( 0x20 ) ;
+ }
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpPositionCursorVgaViaBios (HalpRow, HalpColumn) ;
+
+ return ;
+}
+
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, flush the TB, and map the display
+ // frame buffer into the address space of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_MP_PPC_)
+
+ HalpAcquireDisplayLock();
+
+#endif
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+ }
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+
+#if defined(_MP_PPC_)
+
+ HalpReleaseDisplayLock();
+
+#endif
+
+ KeLowerIrql(OldIrql);
+
+ return;
+} /* end of HalpDisplayString() */
+
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth; //IBMLAN
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) { //IBMLAN
+ CursorColumn = HalpDisplayWidth; //IBMLAN
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+
+VOID
+HalpCopyOEMFontFile()
+{
+ PVOID buffer;
+
+ buffer = ExAllocatePool(NonPagedPool,
+ HalpFontHeader->FileSize);
+
+ ASSERT(buffer);
+
+ RtlCopyMemory(buffer,
+ HalpFontHeader,
+ HalpFontHeader->FileSize);
+
+ HalpFontHeader = buffer;
+}
+
+//
+// HalpS3Xxx functions can now be found in pxs3.c
+//
+
+
+
+//
+// The following functions were left here in pxdisp.c
+// because they are used by multiple display modules.
+//
+VOID
+Scroll_Screen(IN UCHAR line)
+{
+UCHAR i, DataByte;
+ULONG target, stop;
+
+ for (i = 0; i < line; i ++) {
+ WaitForVSync(); // wait for vertical sync to make scroll smooth
+
+ target = 0xb8000;
+ stop = target + HalpScrollLength;
+
+ for (; target < stop; target += 2) {
+ DataByte = READ_S3_VRAM(target+HalpScrollLine);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+
+ stop += HalpScrollLine;
+
+ for (; target < stop; target += 2) {
+ WRITE_S3_VRAM(target, 0x20 );
+ }
+
+ }
+}
+
+VOID
+WaitForVSync (VOID)
+{
+ UCHAR DataByte;
+ BOOLEAN test;
+
+ //
+ // Determine 3Dx or 3Bx
+ //
+
+ DataByte = READ_S3_UCHAR(MiscOutR);
+ ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+
+ // Unlock S3 ( S3R8 )
+ // UnLockS3();
+
+ //
+ // Test Chip ID = '81h' ?
+ //
+
+ // For standard VGA text mode this action is not necessary.
+ // WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ // if ((DataByte = READ_S3_UCHAR(S3_3D5_Data)) == 0x81) {
+ //
+ // Wait For Verttical Retrace
+ //
+
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x08 ? FALSE : TRUE;
+ }
+
+ // Wait for H/V blanking
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x01 ? TRUE : FALSE;
+ }
+ // }
+
+ // Lock S3 ( S3R8 )
+ // LockS3();
+
+ return;
+} /* end of WaitForVsync() */
+
+VOID ScreenOn(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte & 0xdf;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+VOID ScreenOff(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte | 0x20;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+// These functions are commented out because the video adapter they
+// are here to support has no support in NT anymore. I'm not
+// deleting them because we may want to add them back some day. - Jake
+
+// VOID
+// HalpDisplayPpcP9Setup (
+// VOID
+// )
+// /*++
+//
+// Routine Description:
+//
+// This routine initializes the Weitek P9000 display contoller chip.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+// {
+// PULONG buffer;
+// ULONG limit, index;
+// PHYSICAL_ADDRESS physicalAddress;
+//
+// // For now I'll leave the P9000 in the same state that the firmware
+// // left it in. This should be 640x480.
+//
+// HalpHorizontalResolution = 640;
+// HalpVerticalResolution = 480;
+//
+// if (HalpInitPhase == 0) {
+//
+// HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P9_VIDEO_MEMORY_BASE,
+// 0x400000); // 4 MB
+//
+// } else {
+//
+// //
+// // Map video memory space via pte's
+// //
+//
+// physicalAddress.HighPart = 0;
+// physicalAddress.LowPart = P9_VIDEO_MEMORY_BASE;
+// HalpVideoMemoryBase = MmMapIoSpace(physicalAddress,
+// 0x400000,
+// FALSE);
+//
+// //
+// // IO control space has already been mapped in phase 1 via halpmapiospace
+// //
+//
+// }
+//
+// //IBMLAN Use font file from OS Loader
+// //
+// // Compute display variables using using HalpFontHeader which is
+// // initialized in HalpInitializeDisplay().
+// //
+// // N.B. The font information suppled by the OS Loader is used during phase
+// // 0 initialization. During phase 1 initialization, a pool buffer is
+// // allocated and the font information is copied from the OS Loader
+// // heap into pool.
+// //
+// //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+// //HalpFontHeader = FontHeader;
+// HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+// HalpCharacterHeight = HalpFontHeader->PixelHeight;
+// HalpCharacterWidth = HalpFontHeader->PixelWidth;
+//
+// //
+// // Compute character output display parameters.
+// //
+//
+// HalpDisplayText =
+// HalpVerticalResolution / HalpCharacterHeight;
+//
+// HalpScrollLine =
+// HalpHorizontalResolution * HalpCharacterHeight;
+//
+// HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+//
+// HalpDisplayWidth =
+// HalpHorizontalResolution / HalpCharacterWidth;
+//
+//
+// //
+// // Set the video memory to address color one.
+// //
+//
+// buffer = (PULONG)HalpVideoMemoryBase;
+// limit = (HalpHorizontalResolution *
+// HalpVerticalResolution) / sizeof(ULONG);
+//
+// for (index = 0; index < limit; index += 1) {
+// *buffer++ = 0x01010101;
+// }
+//
+//
+// //
+// // Initialize the current display column, row, and ownership values.
+// //
+//
+// HalpColumn = 0;
+// HalpRow = 0;
+// HalpDisplayOwnedByHal = TRUE;
+// return;
+//
+// } //end of HalpDisplayPpcP9Setup
+//
+// VOID
+// HalpDisplayCharacterP9 (
+// IN UCHAR Character
+// )
+// /*++
+//
+// Routine Description:
+//
+// This routine displays a character at the current x and y positions in
+// the frame buffer. If a newline is encountered, the frame buffer is
+// scrolled. If characters extend below the end of line, they are not
+// displayed.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+// {
+//
+// PUCHAR Destination;
+// PUCHAR Source;
+// ULONG Index;
+//
+// //
+// // If the character is a newline, then scroll the screen up, blank the
+// // bottom line, and reset the x position.
+// //
+//
+// if (Character == '\n') {
+// HalpColumn = 0;
+// if (HalpRow < (HalpDisplayText - 1)) {
+// HalpRow += 1;
+//
+// } else {
+// //RtlMoveMemory((PVOID)P9_VIDEO_MEMORY_BASE,
+// // (PVOID)(P9_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+// // HalpScrollLengthP9);
+//
+// // Scroll up one line
+// Destination = HalpVideoMemoryBase;
+// Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+// for (Index = 0; Index < HalpScrollLength; Index++) {
+// *Destination++ = *Source++;
+// }
+// // Blue the bottom line
+// Destination = HalpVideoMemoryBase + HalpScrollLength;
+// for (Index = 0; Index < HalpScrollLine; Index += 1) {
+// *Destination++ = 1;
+// }
+// }
+//
+// } else if (Character == '\r') {
+// HalpColumn = 0;
+//
+// } else {
+// if ((Character < HalpFontHeader->FirstCharacter) ||
+// (Character > HalpFontHeader->LastCharacter)) {
+// Character = HalpFontHeader->DefaultCharacter;
+// }
+//
+// Character -= HalpFontHeader->FirstCharacter;
+// HalpOutputCharacterP9((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+// }
+//
+// return;
+// }
+//
+// VOID
+// HalpOutputCharacterP9(
+// IN PUCHAR Glyph
+// )
+//
+// /*++
+//
+// Routine Description:
+//
+// This routine insert a set of pixels into the display at the current x
+// cursor position. If the current x cursor position is at the end of the
+// line, then a newline is displayed before the specified character.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+// {
+//
+// PUCHAR Destination;
+// ULONG FontValue;
+// ULONG tmp;
+// ULONG I;
+// ULONG J;
+//
+// //
+// // If the current x cursor position is at the end of the line, then
+// // output a line feed before displaying the character.
+// //
+//
+// if (HalpColumn == HalpDisplayWidth) {
+// HalpDisplayCharacterP9('\n');
+// }
+//
+// //
+// // Output the specified character and update the x cursor position.
+// //
+//
+// Destination = (PUCHAR)(HalpVideoMemoryBase +
+// (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+//
+// for (I = 0; I < HalpCharacterHeight; I += 1) {
+// FontValue = 0;
+// for (J = 0; J < HalpBytesPerRow; J += 1) {
+// FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+// }
+// // Move the font bits around so the characters look right.
+// tmp = (FontValue >> 3) & 0x11111111; //bits 7 and 3 to the right 3
+// tmp |= (FontValue >> 1) & 0x22222222; //bits 6 and 2 to the right 1
+// tmp |= (FontValue << 1) & 0x44444444; //bits 5 and 1 to the left 1
+// tmp |= (FontValue << 3) & 0x88888888; //bits 4 and 0 to the left 3
+// FontValue = tmp;
+//
+// Glyph += 1;
+// for (J = 0; J < HalpCharacterWidth ; J += 1) {
+// if (FontValue >> 31 != 0)
+// *Destination = 0xFF; //Make this pixel white
+//
+// Destination++;
+// //*Destination++ = (FontValue >> 31) ^ 1;
+// FontValue <<= 1;
+// }
+//
+// Destination +=
+// (HalpHorizontalResolution - HalpCharacterWidth);
+// }
+//
+// HalpColumn += 1;
+// return;
+// }
+
+//
+// HalpP91Xxx functions can now be found in pxp91.c
+//
+
+
+//
+// HalpBBLXxx functions can now be found in pxbbl.c
+//
+
diff --git a/private/ntos/nthals/halppc/ppc/pxdisp.h b/private/ntos/nthals/halppc/ppc/pxdisp.h
new file mode 100644
index 000000000..ac638fad9
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdisp.h
@@ -0,0 +1,360 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ These are common datastructures used by video systems in the
+ HAL.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// VGA palette tables used by S3 and WD functions
+UCHAR DAC_Table[64] = {
+ // DAC for mode 3
+ 0,16, 4,20, 1,17, 5,21,
+ 32,48,36,52,33,49,37,53,
+ 8,24,12,28, 9,25,13,29,
+ 40,56,44,60,41,57,45,61,
+ 2,18, 6,22, 3,19, 7,23,
+ 34,50,38,54,35,51,39,55,
+ 10,26,14,30,11,27,15,31,
+ 42,58,46,62,43,59,47,63
+ };
+
+UCHAR DAC_Color[4] = {0x00, 0x2a, 0x15, 0x3f};
+
+//
+// CRT Controller Registers for 800 x 600 @ 60 Hz (text mode on Woodfield Prime)
+// NOTE: this is for a text mode
+//
+UCHAR CRTC_800x600x60_Text[] =
+ {
+ 0x7f,0x63,0x64,0x82,0x6d,0x1b,0x72,0xf0,0x00,0x6f,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x58,0x2c,0x57,0x32,0x00,0x58,0x71,0xa3,0xff,
+ };
+
+UCHAR CRTC_640x480x60_Text[] =
+ {
+ 0x5f,0x4f,0x50,0x82,0x53,0x9f,0x0b,0x3e,0x00,0x4f,0x0d,0x0e,0x00,
+ 0x00,0x00,0x00,0xea,0x2c,0xdf,0x28,0x1f,0xe7,0x04,0xa3,0xff,
+ };
+
+UCHAR VideoParam[62] = {
+// Mode +3 480 Lines
+// External Registers 3C3, 3C2
+0x01,0x67,
+
+//=============================================================================
+//
+// IBMBJB changed value at offset 17 (5th number on second line) from 0x8e
+// to 0xae to disable the vertical retrace interrupt
+
+// CRT Controller Registers 3D4, 3D5
+0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,
+// 0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+ 0x00,0x00,0x00,0x9c,0xae,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+
+//=============================================================================
+
+// Sequencer Registers 3C4, 3C5
+// 0x01,0x01,0x03,0x00,0x02,
+0x01,0x20,0x03,0x00,0x02,
+
+// Graphic Control Registers
+0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff,
+
+// Attribute Controller Registers
+0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,
+0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00};
+
+
+UCHAR VGAFont8x16[4096] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00
+0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7E,0xFF,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // 8
+0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, // 9
+0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, // a
+0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, // 10
+0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, // 4
+0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 20
+0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // 1
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x18,0x18,0x7C,0xC6,0xC2,0x7C,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 30
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // b
+0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // 40
+0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 50
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // d
+0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, // f
+
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 60
+0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00, // 7
+0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // a
+0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 70
+0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, // 80
+0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, // 7
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // d
+0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // 90
+0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 8
+0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, // b
+0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, // f
+
+0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a0
+0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 1
+0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // 4
+0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 5
+0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, // b
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, // c
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // b0
+0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // 1
+0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // a
+0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // f
+
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c0
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // c
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // e
+0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d0
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 2
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // a
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // c
+0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // d
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // e
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, // e0
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00, // 1
+0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, // f0
+0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, // 3
+0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, // b
+0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // f
+ };
+
diff --git a/private/ntos/nthals/halppc/ppc/pxds1585.h b/private/ntos/nthals/halppc/ppc/pxds1585.h
new file mode 100644
index 000000000..cee3e7fd5
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxds1585.h
@@ -0,0 +1,106 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxds1585.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+
+
+
+typedef struct _RTC_CONTROL {
+ UCHAR Reserved0[0x71];
+ UCHAR RtcData; // Offset 0x71
+} RTC_CONTROL, *PRTC_CONTROL;
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x74];
+ UCHAR NvramIndexLo; // Offset 0x74
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_BATTERY_BACKED_UP_RAM 14 // battery backed up RAM [0..49]
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxenviro.c b/private/ntos/nthals/halppc/ppc/pxenviro.c
new file mode 100644
index 000000000..92a3f2aa2
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxenviro.c
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxenviro.c
+
+Abstract:
+
+ This module implements the interface to the HAL get and set
+ environment variable routines for a Power PC system.
+
+
+Author:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+#include "fwnvr.h"
+
+
+
+KSPIN_LOCK NVRAM_Spinlock;
+
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+
+{
+
+KIRQL Irql;
+PUCHAR tmpbuffer;
+
+
+ //
+ // Check input parameters
+ //
+ if (Variable == NULL ||
+ *Variable == 0 ||
+ Length < 1 ||
+ Buffer == NULL)
+ return(ENOENT);
+
+ //
+ // Grab control of NVRAM
+ //
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql);
+
+ (VOID)nvr_initialize_object(0, 0);
+
+ if ((tmpbuffer = nvr_get_GE_variable(Variable)) == NULL) {
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOENT);
+ }
+
+ //
+ // Copy the environment variable's value to Buffer
+ //
+
+ do {
+ *Buffer = *tmpbuffer++;
+ if (*Buffer++ == 0) {
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ESUCCESS);
+ }
+ } while (--Length);
+
+ //
+ // Truncate the returned string. The buffer was too short.
+ //
+ *--Buffer = 0;
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOMEM);
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+
+{
+ ARC_STATUS ReturnValue;
+ KIRQL Irql;
+
+
+
+ if (Value == NULL) return(ENOENT);
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql); // Grab control of NVRAM
+
+ (VOID)nvr_initialize_object(0, 0);
+// (VOID)nvr_initialize_object(nvr_system_type);
+
+ ReturnValue = nvr_set_GE_variable(Variable,Value);
+
+ nvr_delete_object(); // free object created by nvr_init_object
+
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+
+ return(ReturnValue);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxfirsup.c b/private/ntos/nthals/halppc/ppc/pxfirsup.c
new file mode 100644
index 000000000..4bc0014f8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxfirsup.c
@@ -0,0 +1,1606 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxfirsup.c
+
+Abstract:
+
+ The module provides the support for the fire coral PCI-ISA bridge.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+ Peter L Johnston (plj@vnet.ibm.com) Support Doral. Aug 95.
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxfirsup.h"
+#include <pxmemctl.h>
+#include "bugcodes.h"
+#include "pxmp.h"
+#include "ibmppc.h"
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ );
+
+#define SioId 0x04828086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPhase0GetPciDataByOffset();
+extern ULONG HalpPhase0SetPciDataByOffset();
+
+//
+// Declare the interupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEnableMpicInterrupt(
+ IN ULONG Vector
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt;
+#if defined(_MP_PPC_)
+
+ //
+ // Connect the Inter-Processor Interrupt (IPI) handler.
+ //
+
+ PCR->InterruptRoutine[MPIC_IPI0_VECTOR + DEVICE_VECTORS] =
+ (PKINTERRUPT_ROUTINE)HalpHandleIpi;
+
+#endif // _MP_PPC_
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a number.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+ //
+ // It is now safe to allow 8259 interrupts thru the MPIC.
+ //
+
+ HalpEnableMpicInterrupt(MPIC_8259_VECTOR + DEVICE_VECTORS);
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber;
+ ULONG ChipId;
+ ULONG BufferLength;
+
+
+ Found = FALSE;
+ SlotNumber = 0;
+
+ while (!Found && SlotNumber < HalpPciMaxSlots) {
+
+ BufferLength = HalpPhase0GetPciDataByOffset(0,
+ SlotNumber,
+ &ChipId,
+ 0,
+ sizeof(ChipId));
+ if (ChipId == SioId)
+ Found = TRUE;
+ else
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found)
+ return FALSE;
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0GetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0SetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+
+ DataByte |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+
+ WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+
+ //
+ // Disable Gauranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo())
+
+ return FALSE;
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+
+ // Work around heinous Victory hardware bug:
+ if ((HalpSystemType == IBM_VICTORY) &&
+ (DeviceDescriptor->InterfaceType == Isa) &&
+ (DeviceDescriptor->Master)) {
+
+ return(NULL);
+ }
+
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ //
+ // bit 2 in the extended mode register must be set to 1 for ISA busmastering to work
+ // correctly on Firecoral
+ //
+
+ if (DeviceDescriptor->Master) {
+ extendedMode.TransferSize |= 1;
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // DMA high page must be set to 0x80 for ISA bus masters to work on
+ // FireCoral.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)adapterObject->PagePort,
+ 0x80
+ );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // DMA high page must be set to 0x80 for ISA bus masters to work on
+ // FireCoral.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)adapterObject->PagePort,
+ 0x80
+ );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxfirsup.h b/private/ntos/nthals/halppc/ppc/pxfirsup.h
new file mode 100644
index 000000000..2b91be331
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxfirsup.h
@@ -0,0 +1,219 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x28]; // Offset 0x58
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+// The default Interrupt interval is Interval = 15ms.
+
+
+#define TIME_INCREMENT 150000 // 15ms.
+#define ROLLOVER_COUNT 15 * 1193
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/halppc/ppc/pxflshbf.s b/private/ntos/nthals/halppc/ppc/pxflshbf.s
new file mode 100644
index 000000000..7e9d429e2
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxflshbf.s
@@ -0,0 +1,121 @@
+#if defined(_PPC_)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxflshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a Power PC
+// system.
+//
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+//
+// Used PowerPC eieio instruction to flush writes
+//
+//--
+
+#include "kxppc.h"
+
+
+// SBTTL("Flush Write Buffer")
+//
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ eieio // synchronize I/O
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpSynchronizeExecution()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSynchronizeExecution)
+
+ sync // synchronize
+
+ LEAF_EXIT(HalpSynchronizeExecution)
+
+
+//
+//++
+//
+// VOID
+// SetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+// HashedPageTableSize is unused because we ASSUME that the HPT is 64K
+//
+
+ LEAF_ENTRY(SetSDR1)
+
+ mtsdr1 r.3
+
+ LEAF_EXIT(SetSDR1)
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxflshio.c b/private/ntos/nthals/halppc/ppc/pxflshio.c
new file mode 100644
index 000000000..681d19912
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxflshio.c
@@ -0,0 +1,197 @@
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ psflshio.c
+
+Abstract:
+
+ This module implements miscellaneous PowerPC HAL functions.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.ibm.com)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+//
+// Prototypes.
+//
+
+VOID
+HalpSweepPhysicalRangeInBothCaches(
+ ULONG StartingPage,
+ ULONG Offset,
+ ULONG Length
+ );
+
+VOID
+HalpSweepPhysicalIcacheRange(
+ ULONG StartingPage,
+ ULONG Offset,
+ ULONG Length
+ );
+
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 1;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Length;
+ ULONG PartialLength;
+ ULONG Offset;
+ PULONG Page;
+ BOOLEAN DoDcache = FALSE;
+
+ Length = Mdl->ByteCount;
+
+ if ( !Length ) {
+ return;
+ }
+ //
+ // If the I/O operation is not a DMA operation,
+ // and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the data cache.
+ //
+
+ if (((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ DoDcache = TRUE;
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the range from the cache. Note it is not reasonable to sweep
+ // the entire cache on an MP system as "Flash Invalidate" doesn't
+ // broadcast the invalidate to other processors.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+
+ Offset = Mdl->ByteOffset;
+ PartialLength = PAGE_SIZE - Offset;
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+
+ Page = (PULONG)(Mdl + 1);
+
+ if (DoDcache == TRUE) {
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ } else {
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ }
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxhalp.h b/private/ntos/nthals/halppc/ppc/pxhalp.h
new file mode 100644
index 000000000..710ff6cad
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxhalp.h
@@ -0,0 +1,345 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ PowerPC specific interfaces, defines and structures.
+
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added externs for HalpInterruptBase,HalpPciConfigBase
+ Added extern for HalpIoControlBase
+ Added prototype for HalpHandleDecrementerInterrupt (was in halp.h)
+ changed adapter object structure to be compatible with the intel HAL
+
+--*/
+
+#ifndef _PXHALP_
+#define _PXHALP_
+
+
+//
+// Define global data used to locate the IO control space, the interrupt
+// acknowlege, and the Pci config base.
+//
+
+extern PVOID HalpIoControlBase;
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpInterruptBase;
+extern PVOID HalpPciConfigBase;
+extern PVOID HalpErrorAddressRegister;
+extern PVOID HalpPciIsaBridgeConfigBase;
+
+//
+// Define adapter object structure.
+//
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IsaBusMaster;
+} ADAPTER_OBJECT;
+
+#if defined(SOFT_HDD_LAMP)
+//
+// On IBM PowerPC machines the HDD (Hard Disk Drive) Lamp is software
+// controlled. HDD Lamp state is controlled in the HAL. The Lamp is
+// turned on in the HAL portion of the device interrupt and turned
+// off periodically if it hasn't been turned on recently.
+//
+// Define structure for keeping track of HDD Lamp.
+//
+
+typedef struct _HDD_LAMP_STATUS {
+ LONG Count;
+} HDD_LAMP_STATUS;
+
+//
+// Number of clock ticks the light should remain on for after an
+// interrupt.
+//
+
+#define SOFT_HDD_TICK_COUNT 3
+
+//
+// HDD Lamp is LSB of ISA port 0x808.
+//
+
+#define HDD_LAMP_PORT 0x808
+
+//
+// Indicate to common code that HDD Lamp should be software driven.
+//
+
+#if !defined(SOFT_HDD_LAMP)
+
+#define SOFT_HDD_LAMP 1
+
+#endif
+
+#endif
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters
+ );
+
+BOOLEAN
+HalpCreateSioStructures(
+ VOID
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpFieldExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleDecrementerInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ );
+
+ULONG
+HalpUpdateDecrementer(
+ ULONG
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace(
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace(
+ VOID
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+PVOID
+KePhase0MapIo(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+PVOID
+KePhase0DeleteIoMap(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+ULONG
+HalpCalibrateTB(
+ VOID
+ );
+
+VOID
+HalpZeroPerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ );
+
+VOID
+HalpMapPlugInPciBridges(
+ UCHAR NoBuses
+ );
+
+PVOID
+HalpAssignReservedVirtualSpace(
+ ULONG BasePage,
+ ULONG LengthInPages
+ );
+
+VOID
+HalpReleaseReservedVirtualSpace(
+ PVOID VirtualAddress,
+ ULONG LengthInPages
+ );
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Provide prototype for Decrementer Interrupts on processors other
+// than 0.
+//
+
+#if defined(_MP_PPC_)
+
+BOOLEAN
+HalpHandleDecrementerInterrupt1 (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ );
+
+#endif
+
+#endif // _PXHALP_
diff --git a/private/ntos/nthals/halppc/ppc/pxhwsup.c b/private/ntos/nthals/halppc/ppc/pxhwsup.c
new file mode 100644
index 000000000..2b74faa70
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxhwsup.c
@@ -0,0 +1,2188 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC Port
+ Remove support for internal bus and devices
+ Changed HalFreeCommonBuffer to support S-FOOT address inversion
+ Added PCI, PCMCIA, and ISA bus support
+ Removed support for internal DMA controller
+ Change HalTranslateBusAddress to support S-FOOTS memory map
+ Deleted HalpReadEisaBus - this code was specific to EISA buses
+ Changed IoMapTransfer to support S-FOOT address inversion
+ Added support for guaranteed contigous common buffers
+
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+#include <pxmemctl.h>
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// Define map buffer variables
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Amount
+ );
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Allocate the actual buffer.
+ //
+
+
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+
+
+
+ //
+ // Memory space inverion
+ //
+
+
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (!AdapterObject->IsaBusMaster) {
+ LogicalAddress->LowPart |= IO_CONTROL_PHYSICAL_BASE;
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. If not all of
+ the registers could be allocated this field is updated to show how
+ many were.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+ return;
+
+}
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: PCI, Isa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != PCIBus &&
+ DeviceDescription->InterfaceType != PCMCIABus) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateIsaAdapter( DeviceDescription,
+ NumberOfMapRegisters);
+ return(adapterObject);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == NULL) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->IsaBusMaster = FALSE;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+
+ ULONG pageOffset;
+ ULONG index;
+ ULONG transferLength;
+ PULONG pageFrame;
+ ULONG logicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ BOOLEAN useBuffer;
+ PHYSICAL_ADDRESS returnAddress;
+
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) | IO_CONTROL_PHYSICAL_BASE;
+
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ //
+ // do the memory inversion on the logical address
+ //
+
+ logicalAddress = ( translationEntry->PhysicalAddress + pageOffset)
+ | IO_CONTROL_PHYSICAL_BASE;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // ISA masters require memory to be at less than 16 MB.
+ // always use map buffers for ISA busmasters
+ //
+
+ if (((logicalAddress+transferLength) & ~IO_CONTROL_PHYSICAL_BASE)
+ >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset | IO_CONTROL_PHYSICAL_BASE;
+
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ if (AdapterObject != NULL) {
+ if (AdapterObject->IsaBusMaster == TRUE) {
+ returnAddress.LowPart = logicalAddress & ~IO_CONTROL_PHYSICAL_BASE;
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ } else {
+
+
+ HalpIsaMapTransfer(
+ AdapterObject,
+ logicalAddress,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a PPC Machine Check interrupt occurs.
+ It print the appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Unused
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ //
+ // raise irql to machine check level
+ //
+
+ KeRaiseIrql(MACHINE_CHECK_LEVEL,&OldIrql);
+
+ //
+ // check memory controller machine check sources
+ //
+
+ HalpHandleMemoryError();
+
+ //
+ // check Bus NMI sources
+ //
+
+ HalpHandleIoError();
+
+ //
+ // Bug check
+ //
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ KeLowerIrql(OldIrql);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the required map buffers.
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+{
+
+ PVOID virtualAddress;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ HalpMapBufferPhysicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS;
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ HalpMapBufferSize,
+ HalpMapBufferPhysicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ return FALSE;
+
+ }
+
+ HalpMapBufferPhysicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return TRUE;
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress ||
+ (((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxidaho.h b/private/ntos/nthals/halppc/ppc/pxidaho.h
new file mode 100644
index 000000000..585078bd8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxidaho.h
@@ -0,0 +1,139 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxidaho.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define structures for the idaho memory controller
+//
+
+
+
+typedef struct _IDAHO_CONTROL {
+ UCHAR Reserved1[0x808]; // Offset 0x000
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[7];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved9[0x1B];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR PciInterruptMap1; // Offset 0x839
+ UCHAR Reserved10[2];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR PciInterruptMap2; // Offset 0x83D
+ UCHAR AudioSupport; // Offset 0x83E
+ UCHAR Reserved11[0x14];
+ UCHAR Reserved12[0x2C];
+ UCHAR MemorySimmId1; // Offset 0x880
+ UCHAR Reserved13[3];
+ UCHAR MemorySimmId2; // Offset 0x884
+ UCHAR Reserved14[3];
+ UCHAR MemorySimmId3; // Offset 0x888
+ UCHAR Reserved15[3];
+ UCHAR MemorySimmId4; // Offset 0x88C
+ UCHAR Reserved16[0x46B];
+ ULONG ConfigAddress; // Offset 0xcf8
+ ULONG ConfigData; // Offset 0xcfc
+} IDAHO_CONTROL, *PIDAHO_CONTROL;
+
+typedef struct _IDAHO_CONFIG {
+
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1; // Offset 0x09
+ UCHAR SubclassCode; // Offset 0x0A
+ UCHAR ClassCode; // Offset 0x0B
+ UCHAR Reserved2; // Offset 0x0C
+ UCHAR Reserved3; // Offset 0x0D
+ UCHAR HeaderType; // Offset 0x0E
+ UCHAR BistControl; // Offset 0x0F
+ UCHAR Reserved4[0x2C];
+ UCHAR InterruptLine; // Offset 0x3C
+ UCHAR InterruptPin; // Offset 0x3D
+ UCHAR MinGnt; // Offset 0x3E
+ UCHAR MaxGnt; // Offset 0x3F
+ UCHAR BridgeNumber; // Offset 0x40
+ UCHAR SubordBusNumber; // Offset 0x41
+ UCHAR DisconnectCounter; // Offset 0x42
+ UCHAR ReservedAnger;
+ UCHAR SpecialCycleAddress[2]; // Offset 0x44
+ UCHAR Reserved5[0x3A];
+ UCHAR StartingAddress1; // Offset 0x80
+ UCHAR StartingAddress2; // Offset 0x81
+ UCHAR StartingAddress3; // Offset 0x82
+ UCHAR StartingAddress4; // Offset 0x83
+ UCHAR StartingAddress5; // Offset 0x84
+ UCHAR StartingAddress6; // Offset 0x85
+ UCHAR StartingAddress7; // Offset 0x86
+ UCHAR StartingAddress8; // Offset 0x87
+ UCHAR Reserved6[8];
+ UCHAR EndingAddress1; // Offset 0x90
+ UCHAR EndingAddress2; // Offset 0x91
+ UCHAR EndingAddress3; // Offset 0x92
+ UCHAR EndingAddress4; // Offset 0x93
+ UCHAR EndingAddress5; // Offset 0x94
+ UCHAR EndingAddress6; // Offset 0x95
+ UCHAR EndingAddress7; // Offset 0x96
+ UCHAR EndingAddress8; // Offset 0x97
+ UCHAR Reserved7[8];
+ UCHAR MemoryBankEnable; // Offset 0xA0
+ UCHAR MemoryTiming1; // Offset 0xA1
+ UCHAR MemoryTiming2; // Offset 0xA2
+ UCHAR Reserved8;
+ UCHAR SimmBank1; // Offset 0xA4
+ UCHAR SimmBank2; // Offset 0xA5
+ UCHAR SimmBank3; // Offset 0xA6
+ UCHAR SimmBank4; // Offset 0xA7
+ UCHAR Reserved9[9];
+ UCHAR L2CacheStatus; // Offset 0xB1
+ UCHAR Reserved10[2];
+ UCHAR RefreshCycle; // Offset 0xB4
+ UCHAR RefreshTimer; // Offset 0xB5
+ UCHAR WatchdogTimer; // Offset 0xB6
+ UCHAR BusTimer; // Offset 0xB7
+ UCHAR LocalBusTimer; // Offset 0xB8
+ UCHAR LocalBusIdleTimer; // Offset 0xB9
+ UCHAR Options1; // Offset 0xBA
+ UCHAR Options2; // Offset 0xBB
+ UCHAR Reserved11[4];
+ UCHAR EnableDetection1; // Offset 0xC0
+ UCHAR ErrorDetection1; // Offset 0xC1
+ UCHAR ErrorSimulation1; // Offset 0xC2
+ UCHAR CpuBusErrorStatus; // Offset 0xC3
+ UCHAR EnableDetection2; // Offset 0xC4
+ UCHAR ErrorDetection2; // Offset 0xC5
+ UCHAR ErrorSimulation2; // Offset 0xC6
+ UCHAR PciBusErrorStatus; // Offset 0xC7
+ UCHAR ErrorAddress[4]; // Offset 0xC8
+} IDAHO_CONFIG, *PIDAHO_CONFIG;
+
diff --git a/private/ntos/nthals/halppc/ppc/pxidle.c b/private/ntos/nthals/halppc/ppc/pxidle.c
new file mode 100644
index 000000000..65e5128ec
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxidle.c
@@ -0,0 +1,62 @@
+/*++
+TITLE("Processor Idle")
+
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ pxidle.c
+
+abstract:
+
+ This module implements system platform dependent power management
+ support.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalProcessorIdle(
+ VOID
+ )
+
+/*++
+
+ Routine Description:
+
+ This function is called when the current processor is idle with
+ interrupts disabled. There is no thread active and there are no
+ DPCs to process. Therefore, power can be switched to a standby
+ mode until the the next interrupt occurs on the current processor.
+
+ N.B. This routine is entered with EE in MSR clear. This routine
+ must do any power management enabling necessary, set the EE
+ bit in MSR, then either return or wait for an interrupt.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+
+--*/
+
+{
+ HalpEnableInterrupts();
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxinfo.c b/private/ntos/nthals/halppc/ppc/pxinfo.c
new file mode 100644
index 000000000..8936197db
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxinfo.c
@@ -0,0 +1,213 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef POWER_MANAGEMENT
+
+HAL_CALLBACKS HalCallback;
+
+
+VOID
+HalInitSystemPhase2 (
+ VOID
+ );
+
+VOID
+HalpLockSuspendCode (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ );
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalInitSystemPhase2)
+#pragma alloc_text(PAGE,HalpLockSuspendCode)
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+VOID
+HalInitSystemPhase2 (
+ VOID
+ )
+{
+ EXECUTIVE_CALLBACK_INFORMATION ExCb;
+ NTSTATUS Status;
+
+ //
+ // Create hal callbacks
+ //
+
+
+ ExOpenCallback (&HalCallback.SetSystemInformation, NULL, TRUE, TRUE);
+ ExOpenCallback (&HalCallback.BusInsertionCheck, NULL, TRUE, TRUE);
+
+ //
+ // Connect to suspend callback to lock hal hibaration code
+ //
+
+ ExQueryExecutiveInformation (
+ ExecutiveCallbacks,
+ &ExCb,
+ sizeof (ExCb),
+ NULL
+ );
+
+ ExRegisterCallback (
+ ExCb.SuspendHibernateSystem,
+ HalpLockSuspendCode,
+ NULL
+ );
+
+}
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN ULONG InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+ union {
+ HAL_POWER_INFORMATION PowerInf;
+ HAL_PROCESSOR_SPEED_INFORMATION ProcessorInf;
+ } U;
+
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ case HalPowerInformation:
+ RtlZeroMemory (&U.PowerInf, sizeof(HAL_POWER_INFORMATION));
+
+ InternalBuffer = &U.PowerInf;
+ Length = sizeof (HAL_POWER_INFORMATION);
+ break;
+
+
+ case HalProcessorSpeedInformation:
+ RtlZeroMemory (&U.ProcessorInf, sizeof(HAL_POWER_INFORMATION));
+
+ U.ProcessorInf.MaximumProcessorSpeed = 100;
+ U.ProcessorInf.CurrentAvailableSpeed = 100;
+ U.ProcessorInf.ConfiguredSpeedLimit = 100;
+
+ InternalBuffer = &U.PowerInf;
+ Length = sizeof (HAL_PROCESSOR_SPEED_INFORMATION);
+ break;
+
+ case HalCallbackInformation:
+ InternalBuffer = &HalCallback;
+ Length = sizeof (HAL_CALLBACKS);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN ULONG InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
+VOID
+HalpLockSuspendCode (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ static PVOID CodeLock;
+
+ switch ((ULONG) Argument1) {
+ case 0:
+ //
+ // Lock code down which might be needed to perform a suspend
+ //
+
+ ASSERT (CodeLock == NULL);
+ CodeLock = MmLockPagableCodeSection (&HaliSuspendHibernateSystem);
+ break;
+
+ case 1:
+ //
+ // Release the code lock
+ //
+
+ MmUnlockPagableImageSection (CodeLock);
+ CodeLock = NULL;
+ break;
+ }
+}
+
+#endif // POWER_MANAGEMENT
diff --git a/private/ntos/nthals/halppc/ppc/pxinithl.c b/private/ntos/nthals/halppc/ppc/pxinithl.c
new file mode 100644
index 000000000..6fbea7c9d
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxinithl.c
@@ -0,0 +1,325 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+ internal DMA contoller.
+
+--*/
+
+#include "halp.h"
+#include <pxmemctl.h>
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+
+extern VOID HalpCopyOEMFontFile();
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+PVOID HalpIoMemoryBase = (PVOID) 0;
+
+ULONG HalpInitPhase;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ HalpInitPhase = Phase;
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ //
+ // Get access to I/O space, check if I/O space has already been
+ // mapped by debbuger initialization.
+ //
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_MP_PPC_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#endif
+
+#ifdef POWER_MANAGEMENT
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalSuspendHibernateSystem = HaliSuspendHibernateSystem;
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif // POWER_MANAGEMENT
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ HalpPhase0DiscoverPciBuses(LoaderBlock->ConfigurationRoot);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ if (!HalpInitializeDisplay(LoaderBlock)) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // Calibrate execution stall
+ //
+
+ HalpCalibrateStall();
+
+ //
+ // InitializeInterrupts
+ //
+
+ if (!HalpInitializeInterrupts())
+
+ return FALSE;
+
+ //
+ // return success
+ //
+
+ return TRUE;
+
+
+ } else {
+
+ if (Phase != 1)
+ return(FALSE);
+
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+
+ HalpRegisterInternalBusHandlers ();
+
+
+ if (!HalpAllocateMapBuffer()) {
+ return FALSE;
+ }
+
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+
+ if (!HalpMapIoSpace()) {
+ return FALSE;
+ }
+
+ if (!HalpCreateSioStructures()) {
+ return FALSE;
+ }
+
+ //
+ // retain the OEM Font File for later use
+ //
+
+ HalpCopyOEMFontFile();
+ HalpCopyBiosShadow();
+
+ return TRUE;
+
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the first processor to do so, initialize the cache
+ // sweeping routines depending on type of processor.
+ //
+
+ if ( Number == 0 ) {
+ if ( HalpCacheSweepSetup() ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxintmod.c b/private/ntos/nthals/halppc/ppc/pxintmod.c
new file mode 100644
index 000000000..67c26cd44
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxintmod.c
@@ -0,0 +1,79 @@
+/*++
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ This module implements interrupt mode translation for PowerPC machines.
+
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+
+
+#include "halp.h"
+
+
+//
+// Get the translated interrupt mode for the given vector
+//
+
+
+KINTERRUPT_MODE
+HalpGetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+{
+
+ //
+ // On Sandalfoot irq 15 is reserved for PCI interrupts and is always level sensitive
+ //
+
+ if (Vector == DEVICE_VECTORS + 15) {
+
+ return LevelSensitive;
+
+ //
+ // No other special interrupt mode translations for sandalfoot
+ //
+
+ } else {
+
+ return InterruptMode;
+
+ }
+
+}
+
+//
+// Correct the interrupt mode for the given vector.
+// On Sandalfoot this function simply returns since all interrupt mode translations can be performed
+// at HalpGetInterruptMode time with the interrupt vector.
+//
+
+
+VOID
+HalpSetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+{
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxintrpt.c b/private/ntos/nthals/halppc/ppc/pxintrpt.c
new file mode 100644
index 000000000..299e0535a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxintrpt.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxintrpt.c
+
+Abstract:
+ This is an abbreviated version of the pxintrpt.c
+ found in halvict, haldoral and haltiger. It is
+ here only so that pxsysbus.c can be the same for
+ halppc and the three mentioned above. We could,
+ in the future, make it contain all the code
+ that pxintrpt.c would in the others.
+
+Author:
+
+Environment:
+
+Revision History:
+ Jake Oshins (joshins@vnet.ibm.com) 2-2-96
+
+
+--*/
+#include "halp.h"
+
+#include "eisa.h"
+
+extern UCHAR VectorToIrqlTable[];
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ *Affinity = 1;
+
+
+//NOTE - this should probably go in pxsiosup.c since it is specific to the SIO
+ //
+ // Set the IRQL level. Map the interrupt controllers priority scheme to
+ // NT irql values. The SIO prioritizes irq's as follows:
+ //
+ // irq0, irq1, irq8, irq9 ... irq15, irq3, irq4 ... irq7.
+ //
+
+ *Irql = (KIRQL) VectorToIrqlTable[BusInterruptLevel];
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+}
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxintsup.s b/private/ntos/nthals/halppc/ppc/pxintsup.s
new file mode 100644
index 000000000..df6142aba
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxintsup.s
@@ -0,0 +1,35 @@
+// TITLE("Enable and Disable Processor Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxintsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to enable and disable
+// interrupts on a PPC system.
+//
+// Author:
+//
+// Jim Wooldridge
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 30-Dec-93 plj Added 603 support.
+//
+//--
+#include "halppc.h"
+
+.extern KiDispatchSoftwareInterrupt
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxirql.c b/private/ntos/nthals/halppc/ppc/pxirql.c
new file mode 100644
index 000000000..35e924c61
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxirql.c
@@ -0,0 +1,284 @@
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright (c) 1996 International Business Machines Corporation
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// PXIRQL.C
+//
+// Abstract:
+//
+// This module implements the code necessary to lower and raise the current
+// Interrupt Request Level (IRQL).
+//
+//
+// Author:
+//
+// Jim Wooldridge (IBM)
+// Steve Johns (Motorola)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 22-Feb-94 Steve Johns (Motorola)
+// KeRaiseIrql - Disabled interrupts at PIC if IRQL >= DEVICE_LEVEL
+// KeLowerIrql - Enabled interrupts at PIC if IRQL < DEVICE_LEVEL
+// 15-Apr-94 Jim Wooldridge
+// Added irql interrupt mask table and expanded irql range from (0-8)
+// to (0-31).
+//
+//--
+
+#include "halp.h"
+#include "eisa.h"
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern BOOLEAN HalpProfilingActive;
+
+UCHAR VectorToIrqlTable[] = { MAXIMUM_DEVICE_LEVEL, // irq 0
+ 26, // irq 1
+ 25, // irq 2
+ 16, // irq 3
+ 15, // irq 4
+ 14, // irq 5
+ 13, // irq 6
+ 12, // irq 7
+ 24, // irq 8
+ 23, // irq 9
+ 22, // irq 10
+ 21, // irq 11
+ 20, // irq 12
+ 19, // irq 13
+ 18, // irq 14
+ 17 // irq 15
+ };
+
+
+//
+// Initialize the 8259 irql mask table
+//
+
+USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level
+ 0x0000, // irql1 APC
+ 0x0000, // irql2 Dispatch
+ 0x0000, // irql3
+ 0x0000, // irql4
+ 0x0000, // irql5
+ 0x0000, // irql6
+ 0x0000, // irql7
+ 0x0000, // irql8
+ 0x0000, // irql9
+ 0x0000, // irql10
+ 0x0000, // irql11
+ 0x0080, // irql12 parallel
+ 0x00C0, // irql13 floppy
+ 0x00E0, // irql14 parallel
+ 0x00F0, // irql15 com 1
+ 0x00F8, // irql16 com 2
+ 0x80F8, // irql17 pci slot
+ 0xC0F8, // irql18 isa slot
+ 0xE0F8, // irql19 scsi
+ 0xF0F8, // irql20 mouse
+ 0xF8F8, // irql21 isa slot
+ 0xFCF8, // irql22 audio
+ 0xFEF8, // irql23 isa slot
+ 0xFFF8, // irql24 rtc
+ 0xFFFA, // irql25 cascade
+ 0xFFFA, // irql26 kb
+ 0xFFFB, // irql27 timer 1/ profile
+ 0xFFFF, // irql28 clock level
+ 0xFFFF, // irql29
+ 0xFFFF, // irql30
+ 0xFFFF // irql31 High level
+ };
+
+
+#define IRQ0 1
+
+VOID
+KiDispatchSoftwareInterrupt(
+ VOID
+ );
+
+
+//
+// VOID
+// KeLowerIrql (
+// KIRQL NewIrql
+// )
+//
+// Routine Description:
+//
+// This function lowers the current IRQL to the specified value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+VOID
+KeLowerIrql(
+ KIRQL NewIrql
+ )
+
+{
+KIRQL OldIrql;
+PUCHAR PIC_Address;
+UCHAR PIC_Mask;
+
+
+ OldIrql = PCR->CurrentIrql;
+
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (OldIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If old IRQL is < CLOCK2_LEVEL then interrupt are enabled
+ // in the MSR but the 8259 mask must be updated. If not, then
+ // interrupts need to be enabled, however the 8259 does not need to
+ // be updated.
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+
+
+ if (OldIrql < CLOCK2_LEVEL ) {
+
+
+ //
+ // Get contoller 1 interrupt mask
+ //
+
+ HALPCR->HardPriority = NewIrql;
+
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[NewIrql] & 0x00FF);
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get contoller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[NewIrql] >> 8 );
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ }
+ HalpEnableInterrupts();
+
+ }
+ }
+ else {
+ PCR->CurrentIrql = NewIrql;
+ }
+
+ //
+ // check for DPC's
+
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt)
+ KiDispatchSoftwareInterrupt();
+
+}
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql (
+// KIRQL NewIrql,
+// PKIRQL OldIrql
+// )
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that recieves the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+
+{
+PUCHAR PIC_Address;
+UCHAR PIC_Mask;
+
+
+
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (NewIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If new irql is >= CLOCK2_LEVEL disable interrupts in the MSR but
+ // don't touch the 8259's. If not, leave interrupts enabled and
+ // update the 8259's
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+
+ HALPCR->HardPriority = NewIrql;
+
+ //
+ // Get controller 1 interrupt mask
+ //
+
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[NewIrql] & 0x00FF);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get controller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[NewIrql] >> 8);
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ HalpEnableInterrupts();
+ }
+
+ }
+
+ else {
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ }
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxisabus.c b/private/ntos/nthals/halppc/ppc/pxisabus.c
new file mode 100644
index 000000000..15cd38f5a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxisabus.c
@@ -0,0 +1,133 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
+#pragma alloc_text(PAGE,HalpAdjustResourceListLimits)
+#endif
+
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ //
+ // irq2 shows up on irq9
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ BusInterruptVector = 9;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+
+ InterruptRange.Base = 0;
+
+#ifdef CAROLINA
+ InterruptRange.Limit = 18;
+#else
+ InterruptRange.Limit = 15;
+#endif //CAROLINA
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxmapio.c b/private/ntos/nthals/halppc/ppc/pxmapio.c
new file mode 100644
index 000000000..edf50cc91
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmapio.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a POWER PC
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Map interrupt acknowledge base address
+ Map SIO config base address
+ Remove RTC map - S-FOOT mapsthe RTC into the ISA I/O space
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+//
+// Define global data used to locate the IO control space and the PCI config
+// space.
+//
+
+PVOID HalpInterruptBase;
+PVOID HalpPciConfigBase;
+PVOID HalpErrorAddressRegister;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O, planar control, and bus configuration
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map bus/bridge I/O control space
+ //
+
+ if (!HalpMapIoControlSpace())
+ return FALSE;
+
+ //
+ // Map Planar I/O control space
+ //
+
+ if (!HalpMapPlanarSpace())
+ return FALSE;
+
+ //
+ // Map Bus configuration space
+ //
+
+ if (!HalpMapBusConfigSpace())
+ return FALSE;
+
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxmemctl.c b/private/ntos/nthals/halppc/ppc/pxmemctl.c
new file mode 100644
index 000000000..9e063bb45
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmemctl.c
@@ -0,0 +1,311 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxdakota.h"
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+
+//
+// 604 ERRATA
+//
+ UCHAR DataByte;
+ ULONG ProcessorAndRev;
+
+ ProcessorAndRev = HalpGetProcessorVersion();
+
+ if ( ((ProcessorAndRev >> 16) == 4) &&
+ ((ProcessorAndRev & 0xffff) <= 0x200) ) {
+
+ //
+ // Disable TEA
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PDAKOTA_CONTROL)HalpIoControlBase)->SystemControl);
+ WRITE_REGISTER_UCHAR(&((PDAKOTA_CONTROL)HalpIoControlBase)->SystemControl,
+ DataByte & ~0x20);
+ }
+
+//
+// 604 ERRATA end
+//
+
+ return TRUE;
+
+}
+
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map the error address register
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = ERROR_ADDRESS_REGISTER;
+ HalpErrorAddressRegister = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL || HalpErrorAddressRegister == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map the PCI config space.
+ //
+
+ physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE;
+ HalpPciConfigBase = MmMapIoSpace(physicalAddress,
+ PCI_CONFIG_SIZE,
+ FALSE);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map the PCI config space.
+ //
+
+ HalpPciConfigBase = (PUCHAR)KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Unmap the PCI config space and set HalpPciConfigBase to NULL.
+ //
+
+ KePhase0DeleteIoMap(PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+ HalpPciConfigBase = NULL;
+
+}
+
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+ UCHAR TextAddress[20];
+ ULONG Bits,Byte;
+
+ //
+ // Read the error address register first
+ //
+
+
+ ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister);
+
+ //
+ // Convert error address to HEX characters
+ //
+
+ for (Bits=28,Byte=0 ;Byte < 8; Byte++, Bits= Bits - 4) {
+
+ TextAddress[Byte] = (UCHAR) ((((ErrorAddress >> Bits) & 0xF) > 9) ?
+ ((ErrorAddress >> Bits) & 0xF) - 10 + 'A' :
+ ((ErrorAddress >> Bits) & 0xF) + '0');
+
+ }
+
+ TextAddress[8] = '\n';
+ TextAddress[9] = '\0';
+
+
+ //
+ // Check TEA conditions
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->MemoryParityErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: Memory Parity Error at Address ");
+ HalDisplayString (TextAddress);
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->L2CacheErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: L2 Cache Parity Error\n");
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->TransferErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: Transfer Error at Address ");
+ HalDisplayString (TextAddress);
+ }
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxmemctl.h b/private/ntos/nthals/halppc/ppc/pxmemctl.h
new file mode 100644
index 000000000..8473ddbb5
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmemctl.h
@@ -0,0 +1,38 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Masters systems.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define physical base addresses of planar
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+#define PCI_CONFIG_SIZE 0x00800000
diff --git a/private/ntos/nthals/halppc/ppc/pxmisc.s b/private/ntos/nthals/halppc/ppc/pxmisc.s
new file mode 100644
index 000000000..f8375ed2e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmisc.s
@@ -0,0 +1,159 @@
+//++
+//
+// Copyright (c) 1995 IBM Corporation
+//
+// Module Name:
+//
+// pxmisc.s
+//
+// Abstract:
+//
+// Home for a small number of miscellaneous routines that need to
+// be in assemblu code.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) August 1995
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "kxppc.h"
+
+#define LOCK_RETRY (64*1024*1024)
+
+ .data
+ .globl HalpDisplayLock
+HalpDisplayLock:
+ .long 0
+
+
+//++
+//
+// VOID
+// HalpAcquireDisplayLock(
+// VOID
+// );
+//
+// Routine Description:
+//
+// Acquire a spinlock to ensure only processor is writing to the
+// display (via HalDisplayString) at a time.
+//
+// If the attempt to acquire the lock fails after LOCK_RETRY attempts,
+// just TAKE it on the assumption that the other processor is dead.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpAcquireDisplayLock)
+
+ lwz r.3, [toc]HalpDisplayLock(r.toc) // get address of lock
+ LWI(r.4,LOCK_RETRY) // get retry count
+ mtctr r.4 // set loop count
+ li r.5, 1 // lock value
+
+getlk: lwarx r.4, 0, r.3 // get lock value
+ cmpwi r.4, 0 // already taken?
+ bne waitlk
+ stwcx. r.5, 0, r.3 // set locked
+ beqlr // return if store
+ // succeeded.
+waitlk: lwz r.4, 0(r.3) // wait for lock to
+ // become 0.
+ bdz failed // jif retry limit
+ // exceeded.
+ cmpwi r.4, 0
+ beq getlk // try again.
+ b waitlk // continue wait
+
+failed: stw r.5, 0(r.3)
+
+ LEAF_EXIT(HalpAcquireDisplayLock)
+
+//++
+//
+// VOID
+// HalpReleaseDisplayLock(
+// VOID
+// );
+//
+// Routine Description:
+//
+// Release the lock acquired by HalpAcquireDisplayLock.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReleaseDisplayLock)
+
+ lwz r.3, [toc]HalpDisplayLock(r.toc) // get address of lock
+ li r.0, 0
+ stw r.0, 0(r.3) // release it
+
+ LEAF_EXIT(HalpReleaseDisplayLock)
+
+//++
+//
+// ULONG
+// HalpGetPhysicalProcessorNumber(
+// VOID
+// );
+//
+// Routine Description:
+//
+// Returns the number of this physical processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Processor Number.
+//
+//--
+
+ LEAF_ENTRY(HalpGetPhysicalProcessorNumber)
+
+#if defined(_MP_PPC_)
+
+ mfpvr r.0 // if 604 (or derivative)
+ rlwinm r.0, r.0, 16, 0xffff // get processor number
+ cmpwi cr.0, r.0, 4 // from SPR 1023 (PIR).
+ cmpwi cr.1, r.0, 9 //
+
+ beq cr.0, type604
+ bne cr.1, nota604
+
+type604:
+
+ mfspr r.3, 1023 // read 604 PIR register
+ blr
+
+nota604:
+
+#endif
+
+ li r.3, 0 // fake it
+
+ LEAF_EXIT(HalpGetPhysicalProcessorNumber)
diff --git a/private/ntos/nthals/halppc/ppc/pxmp.h b/private/ntos/nthals/halppc/ppc/pxmp.h
new file mode 100644
index 000000000..c71300e76
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmp.h
@@ -0,0 +1,59 @@
+/*++
+
+ Copyright 1995 International Business Machines
+
+Module Name:
+
+ pxmp.h
+
+Abstract:
+
+ Defines structures specific to IBM MP PowerPC systems/HALs.
+
+Author:
+
+ Peter L Johnston (plj@vnet.ibm.com) August 1995.
+
+--*/
+
+#ifndef __PXMP_H
+
+#define __PXMP_H
+
+#include "pxmpic2.h"
+
+//
+// Define PER processor HAL data.
+//
+// This structure is assigned the address &PCR->HalReserved which is
+// an array of 16 ULONGs in the architectually defined section of the
+// PCR.
+//
+
+typedef struct {
+ ULONG PhysicalProcessor;
+ PMPIC_PER_PROCESSOR_REGS MpicProcessorBase;
+ ULONG HardPriority;
+ ULONG PendingInterrupts;
+} PER_PROCESSOR_DATA, *PPER_PROCESSOR_DATA;
+
+#if defined(HALPCR)
+
+//
+// Remove UNI processor defn in favor of MP defn of HALPCR.
+//
+
+#undef HALPCR
+
+#endif
+
+#define HALPCR ((PPER_PROCESSOR_DATA)&PCR->HalReserved)
+
+ULONG __builtin_cntzlw(ULONG);
+
+#define HIGHEST_PENDING_IRQL() \
+ (31-__builtin_cntzlw(HALPCR->PendingInterrupts))
+
+#define MAXIMUM_PROCESSORS 32
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxmpic2.h b/private/ntos/nthals/halppc/ppc/pxmpic2.h
new file mode 100644
index 000000000..e1d745a7d
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmpic2.h
@@ -0,0 +1,309 @@
+/*++
+
+ Copyright 1995 International Business Machines
+
+Module Name:
+
+ pxmpic2.h
+
+Abstract:
+
+ Defines structures and offsets to those structures of the I/O
+ space for the PowerPC MP Interrupt Controller (MPIC or OPENPIC).
+
+Author:
+
+ Peter L Johnston (plj@vnet.ibm.com) August 1995.
+
+--*/
+
+#ifndef __PXMPIC2_H
+
+#define __PXMPIC2_H
+
+#include "pci.h"
+
+//
+// Define MPIC Global Registers
+//
+
+typedef struct _MPICGLOB_FEATURE_REPORT {
+
+ ULONG VersionId :8; // Controller Version
+ ULONG NumCpu :5; // Num cpus supported by this controller
+ ULONG _res0 :3; //
+ ULONG NumIrq :11; // highest IRQ source supported
+ ULONG _res1 :5; //
+
+} MPICGLOB_FEATURE_REPORT;
+
+typedef struct _MPICGLOB_CONFIG {
+
+ ULONG _base :20; // not used in PCI systems
+ ULONG _res0 :9; //
+ ULONG Mode :2; // Cascade Mode 00 = 8259 pass thru
+ // 01 = Mixed
+ // 10 = reserved
+ ULONG Reset :1; // Reset Controller
+
+} MPICGLOB_CONFIG;
+
+#define MPIC_8259_MODE 0x0
+#define MPIC_MIXED_MODE 0x1
+
+typedef struct _MPICGLOB_VENDOR_ID {
+
+ ULONG VendorId :8; // manufacturer
+ ULONG DeviceId :8; // device id tbd
+ ULONG Stepping :8; // silicon rev
+ ULONG _res0 :8; //
+
+} MPICGLOB_VENDOR_ID;
+
+typedef struct _MPICGLOB_PROCESSOR_INIT {
+
+ ULONG SelectProcessor; // bit mask, causes processor reset
+
+} MPICGLOB_PROCESSOR_INIT;
+
+typedef struct {
+ ULONG Vector :8; // Interrupt Vector
+ ULONG _res0 :8; //
+ ULONG Priority :4; // Interrupt Priority
+ ULONG NMI :1; // Generate NMI (valid in IPI[3] only)
+ ULONG _res1 :9; //
+ ULONG Activity :1; // (RO) in use
+ ULONG Mask :1; // mask interrupt
+} MPIC_IPIVP;
+
+typedef struct _MPIGLOB_IPI {
+ MPIC_IPIVP VectorPriority;
+ UCHAR _fill0[0xc];
+} MPIGLOB_IPI;
+
+typedef struct _MPIGLOB_TIMER {
+
+ ULONG CurrentCount :31; //
+ ULONG Toggle :1; //
+
+ UCHAR _fill0[0xc];
+
+ ULONG BaseCount :31; //
+ ULONG CountInhibit :1; //
+
+ UCHAR _fill1[0xc];
+
+ ULONG Vector :8; // Interrupt Vector
+ ULONG _res0 :8; //
+ ULONG Priority :4; // Interrupt Priority
+ ULONG _res1 :10; //
+ ULONG Activity :1; // (RO) in use
+ ULONG Mask :1; // mask interrupt
+
+ UCHAR _fill2[0xc];
+
+ ULONG SelectProcessor; // destination processor (bit mask)
+
+ UCHAR _fill3[0xc];
+
+} MPIGLOB_TIMER;
+
+
+#define MPIC_SUPPORTED_IPI 4
+
+typedef struct _MPIC_GLOBAL_REGS {
+
+ MPICGLOB_FEATURE_REPORT FeatureReport; // offset 0x00
+
+ UCHAR _fill0[0x20-(0x00+sizeof(MPICGLOB_FEATURE_REPORT))];
+
+ MPICGLOB_CONFIG Configuration; // offset 0x20
+
+ UCHAR _fill1[0x80-(0x20+sizeof(MPICGLOB_CONFIG))];
+
+ MPICGLOB_VENDOR_ID VendorId; // offset 0x80
+
+ UCHAR _fill2[0x90-(0x80+sizeof(MPICGLOB_VENDOR_ID))];
+
+ MPICGLOB_PROCESSOR_INIT ProcessorInit; // offset 0x90
+
+ UCHAR _fill3[0xa0-(0x90+sizeof(MPICGLOB_PROCESSOR_INIT))];
+
+ MPIGLOB_IPI Ipi[MPIC_SUPPORTED_IPI]; // offset 0xa0
+
+ UCHAR _fill4[0xf0-(0xa0+(sizeof(MPIGLOB_IPI)*4))];
+
+ ULONG TimerFreq; // offset 0xf0
+
+ UCHAR _fill5[0x100-(0xf0+sizeof(ULONG))];
+
+ MPIGLOB_TIMER Timer[4];
+
+} MPIC_GLOBAL_REGS, *PMPIC_GLOBAL_REGS;
+
+#define MPIC_GLOBAL_OFFSET 0x01000
+
+
+//
+// Define MPIC Interrupt Source Configuration Registers
+//
+
+typedef struct {
+ ULONG Vector :8; // Interrupt Vector
+ ULONG _res0 :8; //
+ ULONG Priority:4; // Interrupt Priority
+ ULONG _res1 :1; //
+ ULONG _res2 :1; //
+ ULONG Sense :1; // 0 = edge sensitive, 1 = level sens.
+ ULONG Polarity:1; // 0 = active low, 1 = active high
+ ULONG _res3 :6; //
+ ULONG Activity:1; // (RO) in use
+ ULONG Mask :1; // mask interrupt
+} MPIC_ISVP;
+
+#define MPIC_SUPPORTED_INTS 16
+#define HYDRA_MPIC_SUPPORTED_INTS 20
+
+typedef struct _MPIC_INTERRUPT_SOURCE_REGS {
+
+ struct {
+
+ MPIC_ISVP VectorPriority;
+
+ UCHAR _fill0[0xc];
+
+ ULONG SelectProcessor; // destination processor (bit mask)
+
+ UCHAR _fill1[0xc];
+
+ } Int[1]; // really xxx_MPIC_SUPPORTED_INTS
+
+} MPIC_INTERRUPT_SOURCE_REGS, *PMPIC_INTERRUPT_SOURCE_REGS;
+
+#define MPIC_INTERRUPT_SOURCE_OFFSET 0x10000
+
+
+//
+// Define MPIC Per Processor Registers
+//
+
+typedef struct _MPIC_PER_PROCESSOR_REGS {
+
+ UCHAR _fill0[0x40];
+
+ struct {
+ ULONG SelectProcessor;
+ UCHAR _fill0[0xc];
+ } Ipi[MPIC_SUPPORTED_IPI];
+
+ ULONG TaskPriority; // current processor priority
+
+ UCHAR _fill1[0x1c];
+
+ ULONG Acknowledge; // (RO) interrupt acknowledge
+
+ UCHAR _fill2[0xc];
+
+ ULONG EndOfInterrupt;
+
+} MPIC_PER_PROCESSOR_REGS, *PMPIC_PER_PROCESSOR_REGS;
+
+#define MPIC_PROCESSOR_0_OFFSET 0x20000
+#define MPIC_PROCESSOR_REGS_SIZE 0x1000
+
+#define MPIC_MAX_PRIORITY 15
+
+//
+// Define MPIC2 and MPIC2A PCI Vendor and Device IDs
+// Note: redifine MPIC2A below when the real device id is known (plj).
+//
+
+#define MPIC2_PCI_VENDOR_DEVICE 0xffff1014
+#define MPIC2A_PCI_VENDOR_DEVICE 0x00461014
+#define HYDRA_PCI_VENDOR_DEVICE 0x000e106b
+
+extern PMPIC_GLOBAL_REGS HalpMpicGlobal;
+extern PMPIC_INTERRUPT_SOURCE_REGS HalpMpicInterruptSource;
+
+//
+// The function MPIC_SYNC() should be called to ensure writes to
+// the MPIC complete prior to initiating the next operation.
+//
+
+#define MPIC_SYNC() __builtin_eieio()
+
+//
+// Wait for activitiy bit in Interrupt Source n to clear.
+//
+// The MPIC_SYNC in the following is to FORCE MCL to treat the
+// field as volatile as no amount of changing the declaration
+// seems to cause it to reload the field before comparing it
+// again, and again, and again, ...
+//
+
+#define MPIC_WAIT_SOURCE(i) \
+ while((volatile)(HalpMpicInterruptSource->Int[i].VectorPriority.Activity)){\
+ MPIC_SYNC(); \
+ }
+
+//
+// Wait for activity bit to clear in IPI source n.
+//
+
+#define MPIC_WAIT_IPI_SOURCE(i) \
+ while ((volatile)(HalpMpicGlobal->Ipi[i].VectorPriority.Activity)) { \
+ MPIC_SYNC(); \
+ }
+
+//
+// Define MPIC IPI vectors.
+//
+
+#define MPIC_IPI0_VECTOR 36
+#define MPIC_IPI1_VECTOR 37
+#define MPIC_IPI2_VECTOR 38
+#define MPIC_IPI3_VECTOR 39
+
+//
+// Base MPIC device vector, and MAX MPIC vector.
+// Note these are s/w defined and have nothing to do with the MPIC2 h/w.
+//
+
+#define MPIC_BASE_VECTOR 16
+#define MPIC_8259_VECTOR 16
+
+// For use in interrupt routing tables.
+#define NOT_MPIC 0xFF
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+
+NTSTATUS
+HalpGetPciMpicIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+VOID
+HalpEnableMpicInterrupt(
+ IN ULONG Vector
+ );
+
+
+VOID
+HalpDisableMpicInterrupt(
+ IN ULONG Vector
+ );
+
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxmpint.c b/private/ntos/nthals/halppc/ppc/pxmpint.c
new file mode 100644
index 000000000..828bd49ad
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmpint.c
@@ -0,0 +1,323 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmpint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+
+ Peter Johnston
+ Added support for MPIC interrupt controller
+
+ Chris Karamatas
+ Fixed Hal(Dis/En)ableSystemInterrupt function
+
+ Jake Oshins
+ Renamed to pxmpint.c from pxsysint.c
+
+--*/
+
+#include "halp.h"
+#include "pxmp.h"
+#include "pxmpic2.h"
+
+#if _MSC_VER >= 1000
+
+//
+// VC++ doesn't have the same intrinsics as MCL.
+//
+// Although the MSR is not strictly a SPR, the compiler recognizes
+// all ones (~0) as being the MSR and emits the appropriate code.
+//
+
+#define __builtin_set_msr(x) __sregister_set(_PPC_MSR_,x)
+
+#endif
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if (Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ HalpDisableSioInterrupt(Vector);
+
+ } else if ( Vector <= DEVICE_VECTORS + MPIC_MAX_VECTOR ) {
+
+ HalpDisableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if ( Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ //
+ // It's an 8259 vector.
+ //
+ // Get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector,
+ Irql,
+ InterruptMode);
+
+
+ HalpEnableSioInterrupt(Vector, TranslatedInterruptMode);
+
+ } else if ( Vector <= DEVICE_VECTORS + MPIC_MAX_VECTOR ) {
+
+ HalpEnableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(_MP_PPC_)
+
+ extern ULONG Mpic2IpiBugFix;
+ extern ULONG HalpPhysicalIpiMask[];
+ ULONG BugFix = Mpic2IpiBugFix;
+ ULONG PhysicalMask = 0;
+ PULONG PhysicalIpiMask = HalpPhysicalIpiMask;
+ ULONG OldMsr = __builtin_get_msr();
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ __builtin_set_msr(OldMsr & 0xffff7fff); // Disable Interrupts
+
+ //
+ // Mask is a mask of logical CPUs. Convert it to a mask of
+ // Physical CPUs so the IPI requests will be distributed
+ // properly.
+ //
+
+ do {
+ if ( Mask & 1 ) {
+ PhysicalMask |= *PhysicalIpiMask;
+ }
+ PhysicalIpiMask++;
+ Mask >>= 1;
+ } while ( Mask );
+
+ //
+ // Send the IPI interrupt(s).
+ //
+
+ HALPCR->MpicProcessorBase->Ipi[0 ^ BugFix].SelectProcessor = PhysicalMask;
+
+ __builtin_set_msr(OldMsr); // Restore previous interrupt
+ // setting.
+#endif
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an Inter-Processor Interrupt
+ being received by this processor. It passes the request onto the
+ kernel.
+
+Arguments:
+
+ Unused0 - Not used.
+ Unused1 - Not used.
+ TrapFrame - Volatile context at time interrupt occured.
+
+Return Value:
+
+ Returns TRUE (this routine always succeeds).
+
+--*/
+
+{
+
+#if defined(_MP_PPC_)
+
+ KeIpiInterrupt(TrapFrame);
+
+#endif
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxnatsup.c b/private/ntos/nthals/halppc/ppc/pxnatsup.c
new file mode 100644
index 000000000..3da4d7182
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxnatsup.c
@@ -0,0 +1,80 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxnatsup.c
+
+Abstract:
+
+ The module provides the National SuperIO (PC87311) support for Power PC.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "pxnatsup.h"
+
+
+
+BOOLEAN
+HalpInitSuperIo (
+ VOID
+ )
+
+
+{
+
+ //
+ // Initialize the National SuperIO chip
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FER_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ FER_PARALLEL_PORT_ENABLE |
+ FER_UART1_ENABLE |
+ FER_UART2_ENABLE |
+ FER_FDC_ENABLE |
+ FER_IDE);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FAR_ACCESS);
+
+ //
+ // LPT2 - irq5, uart1-com1, UART2-com2,
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x10);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ PTR_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x04);
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxnatsup.h b/private/ntos/nthals/halppc/ppc/pxnatsup.h
new file mode 100644
index 000000000..0820d65fd
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxnatsup.h
@@ -0,0 +1,57 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxnatsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the
+ National (PC87311) SuperIO chip set.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+//
+// SuperIO configuration registers
+//
+
+//
+//index register select
+//
+
+#define FER_ACCESS 0x00
+#define FAR_ACCESS 0x01
+#define PTR_ACCESS 0x02
+
+//
+//FER register bit fields
+//
+
+#define FER_PARALLEL_PORT_ENABLE 0x01
+#define FER_UART1_ENABLE 0x02
+#define FER_UART2_ENABLE 0x04
+#define FER_FDC_ENABLE 0x08
+#define FER_FDD 0x10
+#define FER_FDC_MODE 0x20
+#define FER_IDE 0x30
+#define FER_IDE_MODE 0x40
+
+//
+// Lay the supio control registers onto the I/O control space
+//
+
+typedef struct _NAT_SUPERIO_CONTROL {
+ UCHAR Reserved1[0x398];
+ UCHAR SuperIoIndexRegister; // Offset 0x398
+ UCHAR SuperIoDataRegister; // Offset 0x399
+} NAT_SUPERIO_CONTROL, *PNAT_SUPERIO_CONTROL;
diff --git a/private/ntos/nthals/halppc/ppc/pxp91.c b/private/ntos/nthals/halppc/ppc/pxp91.c
new file mode 100644
index 000000000..0b879b37e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxp91.c
@@ -0,0 +1,1334 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxp91.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a Weitek P9100 video adapter.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxP91.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define MAP_PCI_CONFIG_PHASE0 \
+if (HalpInitPhase == 0) HalpPhase0MapBusConfigSpace()
+
+#define UNMAP_PCI_CONFIG_PHASE0 \
+if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace()
+
+#define MAP_FRAMEBUF_PHASE0 \
+if (HalpInitPhase == 0) HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(HalpP9FramebufPhysicalAddress.LowPart, 0x200000)
+
+#define UNMAP_FRAMEBUF_PHASE0 \
+if (HalpInitPhase == 0) KePhase0DeleteIoMap(HalpP9FramebufPhysicalAddress.LowPart, 0x200000)
+
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpP91RelinquishDisplayOwnership();
+
+VOID
+SetupVideoBackend();
+
+VOID
+WriteIBM525(
+ USHORT index,
+ UCHAR value
+ );
+
+BOOLEAN
+IBM525SetMode();
+
+VOID
+P91_WriteTiming();
+
+VOID
+P91_SysConf();
+
+VOID
+CalcP9100MemConfig ();
+
+VOID
+ProgramClockSynth(
+ USHORT usFrequency,
+ BOOLEAN bSetMemclk,
+ BOOLEAN bUseClockDoubler
+ );
+
+VOID
+Write525PLL(
+ USHORT usFreq
+ );
+
+VOID P91WriteICD(
+ ULONG data
+ );
+
+VOID
+Write9100FreqSel(
+ ULONG cs
+ );
+
+VOID
+WriteP9ConfigRegister(
+ UCHAR index,
+ UCHAR value
+ );
+
+VOID
+VLEnableP91();
+
+UCHAR
+ReadP9ConfigRegister(
+ UCHAR index
+ );
+
+ULONG
+Read9100FreqSel();
+
+VOID
+IBM525PointerOff();
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+//
+// Define static data.
+//
+extern BOOLEAN HalpDisplayOwnedByHal;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpInitPhase;
+
+
+extern volatile PUCHAR HalpVideoMemoryBase;
+extern volatile PUCHAR HalpVideoCoprocBase;
+
+extern PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup;
+extern PHALP_DISPLAY_CHARACTER HalpDisplayCharacter;
+
+//
+// Define OEM font variables.
+//
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+
+//
+// Define display variables.
+//
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+extern POEM_FONT_FILE_HEADER HalpFontHeader;
+
+
+//
+// PCI slot number
+//
+UCHAR HalpP9SlotNumber;
+UCHAR HalpP9BusNumber;
+
+//
+// Framebuffer physical address
+//
+PHYSICAL_ADDRESS HalpP9FramebufPhysicalAddress = {0,0};
+
+//
+// Coprocessor physical address
+PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress = {0,0};
+
+
+
+VOID
+HalpP91RelinquishDisplayOwnership()
+/*++
+
+Routine Description:
+
+ This routine unmaps the BATs that allow us to function in Phase0.
+ It is called when the video miniport takes ownership of the screen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ASSERT(HalpVideoMemoryBase);
+ ASSERT(HalpVideoCoprocBase);
+ ASSERT(HalpP9FramebufPhysicalAddress.LowPart);
+ ASSERT(HalpP9CoprocPhysicalAddress.LowPart);
+ //
+ // Delete the framebuffer
+ //
+ KePhase0DeleteIoMap(HalpP9FramebufPhysicalAddress.LowPart,
+ 0x200000);
+ HalpVideoMemoryBase = NULL;
+
+ //
+ // Unmap the control registers
+ //
+ KePhase0DeleteIoMap(HalpP9CoprocPhysicalAddress.LowPart,
+ 0x10000);
+ HalpVideoCoprocBase = NULL;
+}
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Weitek P9100 display contoller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ volatile ULONG throwaway = 0;
+ ULONG i, j;
+ RGB colors[255];
+ UCHAR *pData, ucpdata;
+ ULONG pdata;
+ ULONG curDACIndex;
+ ULONG value;
+ PHYSICAL_ADDRESS busrelative;
+
+
+ if (HalpInitPhase == 0) {
+ // Discover the PCI slot number, coprocessor physical address, and
+ // frame buffer physical address
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ ASSERT(FALSE);
+ }
+ else
+ {
+ //
+ // In the case that there are two P9100's in the system, this
+ // will identify the one that occupies the lowest PCI slot number.
+ //
+
+ HalpP9BusNumber=0;
+ HalpP9SlotNumber=0;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+
+ for (i=0; i<HalpPciMaxSlots; i++) {
+
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+
+ if(value == ((P91_DEV_ID_WEITEK_PCI << 16) | P91_VEN_ID_WEITEK_PCI)){
+ HalpP9SlotNumber = (UCHAR)i;
+ HalpP9BusNumber = (UCHAR)j;
+ }
+
+ }
+
+ }
+
+ if(i==HalpPciMaxSlots && HalpP9SlotNumber==0){
+ ASSERT(FALSE);
+ return;
+ }
+ }
+
+
+ HalpPhase0GetPciDataByOffset (HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &busrelative.LowPart,
+ 0x10,
+ 4);
+
+ HalpPhase0UnMapBusConfigSpace();
+
+ HalpP9CoprocPhysicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE + busrelative.LowPart;
+
+ HalpP9FramebufPhysicalAddress.LowPart = HalpP9CoprocPhysicalAddress.LowPart +
+ P9100_FRAMEBUF_OFFSET;
+
+
+ //
+ // Now map everything with BATs
+ //
+ if (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(HalpP9FramebufPhysicalAddress.LowPart,
+ 0x200000); // 2 MB
+ }
+
+
+ if (HalpVideoCoprocBase == NULL) {
+ HalpVideoCoprocBase = (PUCHAR)KePhase0MapIo(HalpP9CoprocPhysicalAddress.LowPart,
+ 0x100000); //1MB
+ // I'm pretty sure this covers all the registers we need to hit from
+ // the HAL.
+
+ }
+ }
+ else {
+ //
+ // Map video memory space via pte's
+ //
+
+ // NT may have moved the video frame buffer since we last used it...
+ HalGetBusDataByOffset (PCIConfiguration,
+ HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &busrelative.LowPart,
+ 0x10,
+ 4);
+
+ HalpP9CoprocPhysicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE + busrelative.LowPart;
+
+ HalpP9FramebufPhysicalAddress.LowPart = HalpP9CoprocPhysicalAddress.LowPart +
+ P9100_FRAMEBUF_OFFSET;
+
+
+ ASSERT((HalpP9CoprocPhysicalAddress.LowPart != (ULONG)NULL));
+ ASSERT((HalpP9FramebufPhysicalAddress.LowPart != (ULONG)NULL));
+ ASSERT((HalpP9SlotNumber != 0));
+
+ HalpVideoMemoryBase = MmMapIoSpace(HalpP9FramebufPhysicalAddress,
+ 0x200000,
+ FALSE);
+ HalpVideoCoprocBase = MmMapIoSpace(HalpP9CoprocPhysicalAddress,
+ 0x10000,
+ FALSE);
+ }
+
+
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ //
+ // Set the video mode to 640x480, 8bits, palette enabled, 60Hz
+ //
+ VLEnableP91();
+
+ // IBM_JACOBO
+ // The following section sets the palette so that the HAL writes
+ // white characters on a blue background. It insures this by setting
+ // half of the 256-color palette to blue and the other half to white.
+
+
+ //
+ // ... and now for a little black magic lifted from the ROS/IPL code
+
+ throwaway += P9_RD_REG(P91_PU_CONFIG);
+ throwaway += P9_WR_FB(0x00000200); /* hw bug */
+ P9_WR_REG(P9100_PalCurRamW ,0x00000000); /* point at beginning of table */
+ throwaway += P9_RD_REG(P91_PU_CONFIG); /* ensure 5 clocks between DAC accesses */
+
+ // Create a 256 color palette. The top half of the colors should all be white
+ // and the bottom half should all be blue.
+ for (i = 0; i < 128; i++) {
+ colors[i].red = 0;
+ colors[i].green = 0;
+ colors[i].blue = (char)0x7F;
+ }
+ for (i = 128; i < 256; i++) {
+ colors[i].red = (char)0xFF;
+ colors[i].green = (char)0xFF;
+ colors[i].blue = (char)0xFF;
+ }
+
+ pData = (char*)colors;
+
+ for (curDACIndex = 0;curDACIndex<(256*3);curDACIndex++){
+ ucpdata = *pData++;
+ pdata = (ULONG) ucpdata;
+ throwaway += P9_WR_FB(0x00000200); /* hw bug */
+ P9_WR_REG(P9100_PalData,(pdata<< 24 | pdata<<16 | pdata << 8 | pdata));
+ throwaway += P9_RD_REG(P91_PU_CONFIG); /* ensure 5 clocks between DAC accesses */
+ }
+
+ throwaway += P9_WR_FB(0x00000200); /* hw bug */
+ P9_WR_REG(P9100_PalCurRamR ,0x00000000);
+ throwaway += P9_RD_REG(P91_PU_CONFIG); /* ensure 5 clocks between DAC accesses */
+ /* Wait for Weitek controller not busy */
+
+
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+ // This means that font information is taken from the file VGAOEM.FON,
+ // which is put in memory by the OSLOADER.
+ //
+ //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ //HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+} //end of HalpDisplayPpcP91Setup
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P91_VIDEO_MEMORY_BASE,
+ // (PVOID)(P91_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // Scroll up one line
+ Destination = HalpVideoMemoryBase;
+ Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpVideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP91((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+ This awful little chunk of code reads a font in the format that it
+ is stored in VGAOEM.FON and draws it onto the screen by iterating
+ over the pixels in the position of the cursor.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG tmp;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacterP91('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0) {
+ *Destination = 0xFF; //Make this pixel white
+ } else {
+ *Destination = 0x00; //Make it black
+ }
+
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+
+VOID
+VLEnableP91()
+
+/*++
+
+ Routine Description:
+
+ Perform the OEM specific tasks necessary to enable P9100 Video. These
+ include memory mapping, setting the sync polarities, and enabling the
+ P9100 video output.
+
+ This has been lifted right out of the video miniport driver weitekp9.sys.
+ I cut it down to the point where it only does what is absolutely
+ necessary to for setting the screen to 640x480x8bit at 60Hz. -- Jake
+
+ Arguments:
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ //USHORT usMemClkInUse;
+
+ //
+ // Enable native mode to: No RAMDAC shadowing, memory & I/O enabled.
+ //
+
+ UNMAP_FRAMEBUF_PHASE0;
+ MAP_PCI_CONFIG_PHASE0;
+
+ WriteP9ConfigRegister(P91_CONFIG_MODE, 0); // Native mode
+
+ UNMAP_PCI_CONFIG_PHASE0;
+ MAP_FRAMEBUF_PHASE0;
+
+ // Program MEMCLK
+
+ ProgramClockSynth(0x136f, TRUE, FALSE);
+
+ //
+ // Next setup the pixel clock frequency. We have to handle potential
+ // clock multiplicaiton by the RAMDAC. On the BT485 if the dotfreq
+ // is greater than the maximum clock freq then we will adjust the
+ // dot frequency to program the clock with.
+ //
+
+ //
+ // Program Pix clk
+ //
+
+ ProgramClockSynth(0x9d5, FALSE, TRUE);
+
+ //
+ // Determine size of Vram (ulFrameBufferSize)...
+ //
+
+ //
+ // For some reason we are calling P91SizeVideoMemory here, even
+ // though we've already done this in HwFindAdapter. In order
+ // to free the frame buffer, I have to remove this seemingly
+ // redundant call. Sizing the memory, did have the side effect
+ // of setting one of the coprocessor registers however, so I'll
+ // add code to do that here.
+ //
+
+
+ // Assume that we are working with a 2MB card for now...
+
+ //
+ // this simulates the side-effect of P91SizeVideoMemory
+ //
+ P9_WR_REG(P91_MEM_CONFIG, 0x00000005);
+
+
+
+ //
+ // Init system config & clipping registers...
+ //
+
+ P91_SysConf();
+
+ // Since I have deleted the device extention, all that was left
+ // of CalcP9100MemConfig was this call. It is probably just
+ // a side effect, but I am preserving it. -- Jake
+ ProgramClockSynth(4, TRUE, FALSE);
+
+ //
+ // Load the video timing registers...
+ //
+
+ P91_WriteTiming();
+
+ //
+ // Setup the RAMDAC to the current mode...
+ //
+
+ IBM525PointerOff();
+
+ IBM525SetMode();
+
+ //
+ // Setup MEMCONFIG and SRTCTL regs
+ //
+
+ SetupVideoBackend();
+
+ return;
+
+} // End of VLEnableP91()
+
+VOID
+SetupVideoBackend()
+{
+ // I have limited this function to write the values necessary for
+ // 640x480x256.
+ // This is taken from the miniport function of the same name. Look
+ // there for a complete explanation. -- Jake
+
+ P9_WR_REG(P91_MEM_CONFIG, 0xc818007d);
+ P9_WR_REG(P91_SRTCTL, 0x1a3);
+ P9_WR_REG(P91_SRTCTL2, P91_HSYNC_LOW_TRUE | P91_VSYNC_LOW_TRUE);
+
+
+ return;
+
+} // End of SetupVideoBackend()
+
+
+BOOLEAN
+IBM525SetMode()
+{
+ // This function is a simplified version of the one in the
+ // miniport. Look there for a good explanation -- Jake.
+
+ //
+ // Set the pixel read mask.
+ //
+
+ P9_WR_BYTE_REG(P9100_PIXELMASK, 0xff);
+
+ //
+ // Select the fast DAC slew rate for the sharpest pixels
+ //
+
+ WriteIBM525(RGB525_DAC_OPER, 0x02);
+
+ //
+ // Enable the 64-bit VRAM pixel port
+ //
+
+ WriteIBM525(RGB525_MISC_CTL1, 0x01);
+
+ WriteIBM525(RGB525_MISC_CTL2, 0x45);
+
+ //
+ // Select 8bpp
+ //
+ WriteIBM525(RGB525_MISC_CLOCK_CTL, 0x27);
+ WriteIBM525(RGB525_PIXEL_FORMAT, 0x03);
+ WriteIBM525(RGB525_8BPP_CTL, 0x00);
+
+ return(TRUE);
+}
+
+
+VOID
+P91_WriteTiming()
+{
+ ULONG ulValueRead, ulValueWritten;
+ ULONG ulHRZSR;
+ ULONG ulHRZBR;
+ ULONG ulHRZBF;
+ ULONG ulHRZT;
+
+
+ // These magic numbers come from watching the miniport set the screen to
+ // 640x480x256. -- Jake
+
+ ulHRZSR = 0xa;
+
+ ulHRZBR = 0xe;
+
+ ulHRZBF = 0x5e;
+
+ ulHRZT = 0x63;
+
+ //
+ // Write to the video timing registers
+ //
+
+ do
+ {
+ P9_WR_REG(P91_HRZSR, ulHRZSR);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZSR);
+ } while (ulValueRead != ulHRZSR);
+
+ do
+ {
+ P9_WR_REG(P91_HRZBR, ulHRZBR);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZBR);
+ } while (ulValueRead != ulHRZBR);
+
+ do
+ {
+ P9_WR_REG(P91_HRZBF, ulHRZBF);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZBF);
+ } while (ulValueRead != ulHRZBF);
+
+ do
+ {
+ P9_WR_REG(P91_HRZT, ulHRZT);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZT);
+ } while (ulValueRead != ulHRZT);
+
+ ulValueWritten = (ULONG) 4;
+
+ do
+ {
+ P9_WR_REG(P91_VRTSR, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTSR);
+ } while (ulValueRead != ulValueWritten);
+
+ ulValueWritten = (ULONG) 0x1c;
+ do
+ {
+ P9_WR_REG(P91_VRTBR, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTBR);
+ } while (ulValueRead != ulValueWritten);
+
+ ulValueWritten = (ULONG) 0x1fc;
+ do
+ {
+ P9_WR_REG(P91_VRTBF, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTBF);
+ } while (ulValueRead != ulValueWritten);
+
+ ulValueWritten = (ULONG) 0x20d;
+ do
+ {
+ P9_WR_REG(P91_VRTT, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTT);
+ } while (ulValueRead != ulValueWritten);
+
+ return;
+
+} // End of P91_WriteTimings()
+
+
+
+VOID
+P91_SysConf()
+{
+ // This function taken and simplified from the miniport.
+
+ P9_WR_REG(P91_SYSCONFIG, 0x8563000); // send data to the register
+
+ //
+ // There are two sets of clipping registers. The first takes the
+ // horizontal diemnsion in pixels and the vertical dimension in
+ // scanlines.
+ //
+ P9_WR_REG(P91_DE_P_W_MIN, 0L);
+ P9_WR_REG(P91_DE_P_W_MAX, 0x27f1998);
+
+ //
+ // The second set takes the horizontal dimension in bytes and the
+ // vertical dimension in scanlines.
+ //
+ P9_WR_REG(P91_DE_B_W_MIN, 0L);
+ P9_WR_REG(P91_DE_B_W_MAX, 0x27f1998);
+
+ return;
+
+} // End of P91_SysConf()
+
+
+
+VOID
+ProgramClockSynth(
+ USHORT usFrequency,
+ BOOLEAN bSetMemclk,
+ BOOLEAN bUseClockDoubler
+ )
+
+{
+ ULONG clockstring; // IC designs pixel dot rate shift value
+
+ if ((!bSetMemclk))
+ {
+
+ Write525PLL(usFrequency);
+
+ //
+ // Set reference frequency to 5000 Mhz...
+ //
+
+ usFrequency = 5000;
+ }
+ else
+ {
+ usFrequency = 4975;
+ }
+
+
+ UNMAP_FRAMEBUF_PHASE0;
+ MAP_PCI_CONFIG_PHASE0;
+
+ if (bSetMemclk)
+ {
+ clockstring = 0x16fc91;
+ P91WriteICD(clockstring | IC_MREG); // Memclk
+ }
+ else
+ {
+ clockstring = 0x1c841;
+ P91WriteICD(clockstring | IC_REG2); // Pixclk
+ }
+
+ //
+ // Select custom frequency
+ //
+
+ Write9100FreqSel(ICD2061_EXTSEL9100);
+
+ UNMAP_PCI_CONFIG_PHASE0;
+ MAP_FRAMEBUF_PHASE0;
+
+
+
+} // End of ProgramClockSynth()
+
+
+
+VOID
+WriteIBM525(
+ USHORT index,
+ UCHAR value
+ )
+{
+ IBM525_WR_DAC(P9100_IBM525_INDEX_LOW, (UCHAR) (index & 0x00FF));
+ IBM525_WR_DAC(P9100_IBM525_INDEX_HIGH, (UCHAR) ((index & 0xFF00) >> 8));
+ IBM525_WR_DAC(P9100_IBM525_INDEX_DATA, (UCHAR) value);
+ (void) P9_RD_REG(P91_MEM_CONFIG); // Needed for timinig...
+
+} // End of WriteIBM525()
+
+UCHAR
+ReadIBM525(
+ USHORT index
+ )
+
+{
+ UCHAR j;
+
+ IBM525_WR_DAC(P9100_IBM525_INDEX_LOW, (UCHAR) (index & 0x00FF));
+ IBM525_WR_DAC(P9100_IBM525_INDEX_HIGH, (UCHAR) ((index & 0xFF00) >> 8));
+
+ IBM525_RD_DAC(P9100_IBM525_INDEX_DATA, j);
+
+ return(j);
+
+} // End of ReadIBM525()
+
+VOID
+Write525PLL(
+ USHORT usFreq
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the IBM RGB525 Ramdac to generate and use the
+ specified frequency as its pixel clock frequency.
+
+Arguments:
+
+ Frequency.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT usRoundedFreq;
+ USHORT usVCODivCount;
+ ULONG ulValue;
+
+ usRoundedFreq = 2525;
+ usVCODivCount = 36;
+
+ //
+ // Setup for writing to the PLL Reference Divider register.
+ //
+
+ //
+ // Program REFCLK to a fixed 50MHz.
+ //
+ WriteIBM525(RGB525_FIXED_PLL_REF_DIV, IBM525_PLLD_50MHZ);
+
+ //
+ // Set up for programming frequency register 9.
+ //
+
+ WriteIBM525(RGB525_F9, (UCHAR) (usVCODivCount));
+
+ //
+ // Program PLL Control Register 2.
+ //
+
+ WriteIBM525(RGB525_PLL_CTL2, IBM525_PLL2_F9_REG);
+
+ //
+ // Program PLL Control Register 1.
+ //
+
+ WriteIBM525(RGB525_PLL_CTL1, (IBM525_PLL1_REFCLK_INPUT |
+ IBM525_PLL1_INT_FS) );
+
+ //
+ // Program DAC Operation Register.
+ //
+
+ WriteIBM525(RGB525_DAC_OPER, IBM525_DO_DSR_FAST);
+
+ //
+ // Program Miscellaneous Control Register 1.
+ //
+
+ WriteIBM525(RGB525_MISC_CTL1, IBM525_MC1_VRAM_64_BITS);
+
+ //
+ // Program Miscellaneous Clock Control Register.
+ //
+
+ ulValue = ReadIBM525(RGB525_MISC_CLOCK_CTL);
+
+ //
+ // At 8 Bpp, divide the clock by 8.
+ //
+ ulValue |= IBM525_MCC_PLL_DIV_8 | IBM525_MCC_PLL_ENABLE;
+
+ WriteIBM525(RGB525_MISC_CLOCK_CTL,
+ (UCHAR) ulValue);
+
+ return;
+
+} // End of Write525PLL()
+
+VOID P91WriteICD(
+ ULONG data
+ )
+
+/*++
+
+Routine Description:
+
+ Program the ICD2061a Frequency Synthesizer.
+
+Arguments:
+
+ HwDeviceExtension - Pointer to the miniport driver's device extension.
+ data - Data to be written.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int i;
+ ULONG savestate;
+
+ //
+ // Note: We might have to disable interrupts to preclude the ICD's
+ // watchdog timer from expiring resulting in the ICD resetting to the
+ // idle state.
+ //
+ savestate = Read9100FreqSel();
+
+ //
+ // First, send the "Unlock sequence" to the clock chip.
+ // Raise the data bit and send 5 unlock bits.
+ //
+ Write9100FreqSel(ICD2061_DATA9100);
+ for (i = 0; i < 5; i++) // send at least 5 unlock bits
+ {
+ //
+ // Hold the data while lowering and raising the clock
+ //
+ Write9100FreqSel(ICD2061_DATA9100);
+ Write9100FreqSel( ICD2061_DATA9100 |
+ ICD2061_CLOCK9100);
+ }
+
+ //
+ // Then turn the data clock off and turn the clock on one more time...
+ //
+ Write9100FreqSel( 0);
+ Write9100FreqSel( ICD2061_CLOCK9100);
+
+ //
+ // Now send the start bit: Leave data off, adn lower the clock.
+ //
+ Write9100FreqSel( 0);
+
+ //
+ // Leave data off and raise the clock.
+ //
+ Write9100FreqSel( ICD2061_CLOCK9100);
+
+ //
+ // Localbus position for hacking bits out
+ // Next, send the 24 data bits.
+ //
+ for (i = 0; i < 24; i++)
+ {
+ //
+ // Leaving the clock high, raise the inverse of the data bit
+ //
+ Write9100FreqSel(
+ ((~data << ICD2061_DATASHIFT9100) &
+ ICD2061_DATA9100) | ICD2061_CLOCK9100);
+
+ //
+ // Leaving the inverse data in place, lower the clock.
+ //
+ Write9100FreqSel(
+ (~data << ICD2061_DATASHIFT9100) & ICD2061_DATA9100);
+
+ //
+ // Leaving the clock low, rais the data bit.
+ //
+ Write9100FreqSel(
+ (data << ICD2061_DATASHIFT9100) & ICD2061_DATA9100);
+
+ //
+ // Leaving the data bit in place, raise the clock.
+ //
+ Write9100FreqSel(
+ ((data << ICD2061_DATASHIFT9100) & ICD2061_DATA9100)
+ | ICD2061_CLOCK9100);
+
+ data >>= 1; // get the next bit of the data
+ }
+
+ //
+ // Leaving the clock high, raise the data bit.
+ //
+ Write9100FreqSel(
+ ICD2061_CLOCK9100 | ICD2061_DATA9100);
+
+ //
+ // Leaving the data high, drop the clock low, then high again.
+ //
+ Write9100FreqSel( ICD2061_DATA9100);
+ Write9100FreqSel(
+ ICD2061_CLOCK9100 | ICD2061_DATA9100);
+
+ //
+ // Note: if interrupts were disabled, enable them here.
+ // before restoring the
+ // original value or the ICD
+ // will freak out.
+ Write9100FreqSel( savestate); // restore orig register value
+
+ return;
+
+} // End of WriteICD()
+
+VOID
+Write9100FreqSel(
+ ULONG cs
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the P9100 clock select register preserving the video coprocessor
+ enable bit.
+
+ Statically:
+ Bits [1:0] go to frequency select
+ Dynamically:
+ Bit 1: data
+ Bit 0: clock
+
+Arguments:
+
+ Clock select value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Set the frequency select bits in the P9100 configuration
+ //
+
+ WriteP9ConfigRegister(P91_CONFIG_CKSEL,
+ (UCHAR) ((cs << 2)));
+ return;
+
+} // End of Write9100FreqSel()
+
+
+
+ULONG
+Read9100FreqSel()
+
+{
+ return((ULONG)(ReadP9ConfigRegister(P91_CONFIG_CKSEL)
+ >> 2) & 0x03);
+
+} // End of Read9100FreqSel()
+
+VOID
+WriteP9ConfigRegister(
+ UCHAR index,
+ UCHAR value
+ )
+{
+ if (HalpInitPhase == 0) {
+ HalpPhase0SetPciDataByOffset(HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &value,
+ index,
+ 1);
+ }
+ else {
+ HalSetBusDataByOffset(PCIConfiguration,
+ HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &value,
+ index,
+ 1);
+ }
+}
+
+UCHAR
+ReadP9ConfigRegister(
+ UCHAR index
+ )
+{
+ UCHAR retval;
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset(HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &retval,
+ index,
+ 1);
+ }
+ else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &retval,
+ index,
+ 1);
+ }
+
+ return ( retval );
+
+}
+
+VOID
+IBM525PointerOff(
+ )
+
+/*++
+
+Routine Description:
+
+ Turn off the hardware cursor.
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Turn the cursor off only if it was enabled.
+ //
+ if (CURS_IS_ON_IBM525())
+ {
+ CURS_OFF_IBM525();
+ }
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxp91.h b/private/ntos/nthals/halppc/ppc/pxp91.h
new file mode 100644
index 000000000..f0201a87f
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxp91.h
@@ -0,0 +1,1380 @@
+#include <ntdef.h>
+
+typedef struct {
+ char red;
+ char green;
+ char blue;
+} RGB;
+
+
+//
+// Macros to read and write P9 registers.
+//
+
+#define P9_WR_REG(index, data) \
+ *(volatile PULONG)((ULONG)HalpVideoCoprocBase + (index)) = (ULONG)(data), \
+ KeFlushWriteBuffer()
+
+#define P9_RD_REG(index) \
+ *(volatile ULONG *)((ULONG)HalpVideoCoprocBase + (index))
+
+#define P9_WR_BYTE_REG(index, data) \
+ *(volatile UCHAR *)((ULONG)HalpVideoCoprocBase + (index)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define P9_RD_BYTE_REG(index) \
+ *(volatile UCHAR *)((ULONG)HalpVideoCoprocBase + (index))
+
+#define P9_WR_FB(index) \
+ *(volatile ULONG *)((ULONG)HalpVideoMemoryBase + (index))
+
+
+#define P9100_FRAMEBUF_OFFSET 0x00800000
+
+// These are used by the palette setup section
+#define P9100_PU_CONFIG 0x00000198
+#define P9100_PalCurRamW 0x00000200
+#define P9100_PalData 0x00000204
+#define P9100_PixelMask 0x00000208
+#define P9100_PalCurRamR 0x0000020c
+#define P9100_IndexLow 0x00000210
+#define P9100_IndexHigh 0x00000214
+#define P9100_IndexData 0x00000218
+#define P9100_IndexContr 0x0000021c
+
+//
+// P9100 relocatable memory mapped BT485 register definitions.
+//
+// Note: An extra 2 byte offset is added to the register offset in order
+// to align the offset on the byte of the Dword which contains the
+// DAC data.
+//
+#define P9100_RAMWRITE 0x00000200 + 2
+#define P9100_PALETDATA 0x00000204 + 2
+#define P9100_PIXELMASK 0x00000208 + 2
+#define P9100_RAMREAD 0x0000020C + 2
+#define P9100_COLORWRITE 0x00000210 + 2
+#define P9100_COLORDATA 0x00000214 + 2
+#define P9100_COMREG0 0x00000218 + 2
+#define P9100_COLORREAD 0x0000021C + 2
+#define P9100_COMREG1 0x00000220 + 2
+#define P9100_COMREG2 0x00000224 + 2
+#define P9100_COMREG3 0x00000228 + 2
+#define P9100_STATREG 0x00000228 + 2
+#define P9100_CURSORDATA 0x0000022C + 2
+#define P9100_CURSORX0 0x00000230 + 2
+#define P9100_CURSORX1 0x00000234 + 2
+#define P9100_CURSORY0 0x00000238 + 2
+#define P9100_CURSORY1 0x0000023C + 2
+
+//
+// IBMRGB525 Indexed registers. Those index registers marked // Referenced
+// indicate that they are reference.
+//
+#define RGB525_REVISION_LEVEL (0x00)
+#define RGB525_ID (0x01)
+#define RGB525_MISC_CLOCK_CTL (0x02) // Referenced
+#define RGB525_SYNC_CTL (0x03)
+#define RGB525_HSYNC_POS (0x04)
+#define RGB525_POWER_MGNT (0x05)
+#define RGB525_DAC_OPER (0x06) // Referenced
+#define RGB525_PAL_CTRL (0x07)
+//
+// 08h through 09h are reserved by IBM
+//
+#define RGB525_PIXEL_FORMAT (0x0A) // Referenced
+#define RGB525_8BPP_CTL (0x0B) // Referenced
+#define RGB525_16BPP_CTL (0x0C) // Referenced
+#define RGB525_24BPP_CTL (0x0D) // Referenced
+#define RGB525_32BPP_CTL (0x0E) // Referenced
+//
+// 0Fh is reserved by IBM
+//
+#define RGB525_PLL_CTL1 (0x10) // Referenced
+#define RGB525_PLL_CTL2 (0x11) // Referenced
+//
+// 12h through 13h are reserved by IBM
+//
+#define RGB525_FIXED_PLL_REF_DIV (0x14) // Referenced
+//
+// 15h through 1fh are reserved by IBM
+//
+#define RGB525_F0 (0x20) // Referenced
+#define RGB525_F1 (0x21)
+#define RGB525_F2 (0x22)
+#define RGB525_F3 (0x23)
+#define RGB525_F4 (0x24)
+#define RGB525_F5 (0x25)
+#define RGB525_F6 (0x26)
+#define RGB525_F7 (0x27)
+#define RGB525_F8 (0x28)
+#define RGB525_F9 (0x29)
+#define RGB525_F10 (0x2A)
+#define RGB525_F11 (0x2B)
+#define RGB525_F12 (0x2C)
+#define RGB525_F13 (0x2D)
+#define RGB525_F14 (0x2E)
+#define RGB525_F15 (0x2F)
+#define RGB525_CURSOR_CTL (0x30) // Referenced
+#define RGB525_CURSOR_X_LOW (0x31) // Referenced
+#define RGB525_CURSOR_X_HIGH (0x32) // Referenced
+#define RGB525_CURSOR_Y_LOW (0x33) // Referenced
+#define RGB525_CURSOR_Y_HIGH (0x34) // Referenced
+#define RGB525_CURSOR_HOT_X (0x35) // Referenced
+#define RGB525_CURSOR_HOT_Y (0x36) // Referenced
+//
+// 37h through 3fh are reserved by IBM
+//
+#define RGB525_CURSOR_1_RED (0x40) // Referenced
+#define RGB525_CURSOR_1_GREEN (0x41) // Referenced
+#define RGB525_CURSOR_1_BLUE (0x42) // Referenced
+#define RGB525_CURSOR_2_RED (0x43) // Referenced
+#define RGB525_CURSOR_2_GREEN (0x44) // Referenced
+#define RGB525_CURSOR_2_BLUE (0x45) // Referenced
+#define RGB525_CURSOR_3_RED (0x46)
+#define RGB525_CURSOR_3_GREEN (0x47)
+#define RGB525_CURSOR_3_BLUE (0x48)
+//
+// 49h through 5fh are reserved by IBM
+//
+#define RGB525_BORDER_RED (0x60)
+#define RGB525_BORDER_GREEN (0x61)
+#define RGB525_BORDER_BLUE (0x62)
+//
+// 63h through 6fh are reserved by IBM
+//
+#define RGB525_MISC_CTL1 (0x70) // Referenced
+#define RGB525_MISC_CTL2 (0x71) // Referenced
+#define RGB525_MISC_CTL3 (0x72)
+//
+// 73h through 81h are reserved by IBM
+//
+#define RGB525_DAC_SENSE (0x82)
+//
+// 83h is reserved by IBM
+//
+#define RGB525_MISR_RED (0x84)
+//
+// 85h is reserved by IBM
+//
+#define RGB525_MISR_GREEN (0x86)
+//
+// 87h is reserved by IBM
+//
+#define RGB525_MISR_BLUE (0x88)
+//
+// 89h - 8dh are reserved by IBM
+//
+#define RGB525_PLL_VCO_DIV (0x8E)
+#define RGB525_PLL_REF_DIV_IN (0x8F)
+#define RGB525_VRAM_MASK_LOW (0x90)
+#define RGB525_VRAM_MASK_HIGH (0x91)
+//
+// 92h through 0ffh are reserved by IBM
+//
+#define RGB525_CURSOR_ARRAY (0x100) // Referenced
+
+//
+// Masks used to program the ICD2061a Frequency Synthesizer.
+//
+
+#define IC_REG0 0x0l // Mask selects ICD Video Clock Reg 1
+#define IC_REG1 0x200000l // Mask selects ICD Video Clock Reg 2
+#define IC_REG2 0x400000l // Mask selects ICD Video Clock Reg 3
+#define IC_MREG 0x600000l // Mask selects ICD Mem Timing Clock
+#define IC_CNTL 0xc18000l // Mask selects ICD Control Register
+#define IC_DIV4 0xa40000l
+
+//
+// These values are used to program custom frequencies
+// and to select a custom frequency.
+//
+#define ICD2061_EXTSEL9100 (0x03)
+#define ICD2061_DATA9100 (0x02)
+#define ICD2061_DATASHIFT9100 (0x01)
+#define ICD2061_CLOCK9100 (0x01)
+
+//
+// P9100 relocatable memory mapped IBM 525 register definitions.
+//
+// Note: An extra 2 byte offset is added to the register offset in order
+// to align the offset on the byte of the Dword which contains the
+// DAC data.
+//
+#define P9100_IBM525_PAL_WRITE 0x00000200 + 2
+#define P9100_IBM525_PAL_DATA 0x00000204 + 2
+#define P9100_IBM525_PEL_MASK 0x00000208 + 2
+#define P9100_IBM525_PAL_READ 0x0000020C + 2
+#define P9100_IBM525_INDEX_LOW 0x00000210 + 2
+#define P9100_IBM525_INDEX_HIGH 0x00000214 + 2
+#define P9100_IBM525_INDEX_DATA 0x00000218 + 2
+#define P9100_IBM525_INDEX_CTL 0x0000021C + 2
+
+//
+// PLL Control 1 Register Bit Definitions. (Section 13.2.3.1)
+//
+#define IBM525_PLL1_REF_SRC_MSK 0x10
+#define IBM525_PLL1_REFCLK_INPUT 0x00
+#define IBM525_PLL1_EXTOSC_INPUT 0x10
+#define IBM525_PLL1_EXT_INT_MSK 0x07
+#define IBM525_PLL1_EXT_FS 0x00
+#define IBM525_PLL1_INT_FS 0x02
+
+//
+// PLL Control 2 Register Bit Definitions. (Section 13.2.3.2)
+//
+#define IBM525_PLL2_INT_FS_MSK 0x0F
+#define IBM525_PLL2_F0_REG 0x00
+#define IBM525_PLL2_F1_REG 0x01
+#define IBM525_PLL2_F2_REG 0x02
+#define IBM525_PLL2_F3_REG 0x03
+#define IBM525_PLL2_F4_REG 0x04
+#define IBM525_PLL2_F5_REG 0x05
+#define IBM525_PLL2_F6_REG 0x06
+#define IBM525_PLL2_F7_REG 0x07
+#define IBM525_PLL2_F8_REG 0x08
+#define IBM525_PLL2_F9_REG 0x09
+#define IBM525_PLL2_F10_REG 0x0A
+#define IBM525_PLL2_F11_REG 0x0B
+#define IBM525_PLL2_F12_REG 0x0C
+#define IBM525_PLL2_F13_REG 0x0D
+#define IBM525_PLL2_F14_REG 0x0E
+#define IBM525_PLL2_F15_REG 0x0F
+
+//
+// PLL Reference Divider Register Bit Definitions. (Section 13.2.3.3)
+//
+#define IBM525_PLLD_4MHZ 0x02
+#define IBM525_PLLD_6MHZ 0x03
+#define IBM525_PLLD_8MHZ 0x04
+#define IBM525_PLLD_10MHZ 0x05
+#define IBM525_PLLD_12MHZ 0x06
+#define IBM525_PLLD_14MHZ 0x07
+#define IBM525_PLLD_16MHZ 0x08
+#define IBM525_PLLD_18MHZ 0x09
+#define IBM525_PLLD_20MHZ 0x0A
+#define IBM525_PLLD_22MHZ 0x0B
+#define IBM525_PLLD_24MHZ 0x0C
+#define IBM525_PLLD_26MHZ 0x0D
+#define IBM525_PLLD_28MHZ 0x0E
+#define IBM525_PLLD_30MHZ 0x0F
+#define IBM525_PLLD_32MHZ 0x10
+#define IBM525_PLLD_34MHZ 0x11
+#define IBM525_PLLD_36MHZ 0x12
+#define IBM525_PLLD_38MHZ 0x13
+#define IBM525_PLLD_40MHZ 0x14
+#define IBM525_PLLD_42MHZ 0x15
+#define IBM525_PLLD_44MHZ 0x16
+#define IBM525_PLLD_46MHZ 0x17
+#define IBM525_PLLD_48MHZ 0x18
+#define IBM525_PLLD_50MHZ 0x19
+#define IBM525_PLLD_52MHZ 0x1A
+#define IBM525_PLLD_54MHZ 0x1B
+#define IBM525_PLLD_56MHZ 0x1C
+#define IBM525_PLLD_58MHZ 0x1D
+#define IBM525_PLLD_60MHZ 0x1E
+#define IBM525_PLLD_62MHZ 0x1F
+
+//
+// DAC Operation Register Bit Definitions. (Section 13.2.1.8)
+//
+#define IBM525_DO_SOG_MSK 0x08
+#define IBM525_DO_SOG_DISABLE 0x00
+#define IBM525_DO_SOG_ENABLE 0x08
+#define IBM525_DO_BRB_MSK 0x04
+#define IBM525_DO_BRB_NORMAL 0x00
+#define IBM525_DO_BRB_BLANKED 0x04
+#define IBM525_DO_DSR_MSK 0x02
+#define IBM525_DO_DSR_SLOW 0x00
+#define IBM525_DO_DSR_FAST 0x02
+#define IBM525_DO_DPE_MSK 0x01
+#define IBM525_DO_DPE_DISABLE 0x00
+#define IBM525_DO_DPE_ENABLE 0x01
+
+//
+// Miscellaneous Control 1 Register Bit Definitions. (Section 13.2.1.1)
+//
+#define IBM525_MC1_MISR_CTL_MSK 0x80
+#define IBM525_MC1_MISR_CTL_OFF 0x00
+#define IBM525_MC1_MISR_CTL_ON 0x80
+#define IBM525_MC1_VMSK_CTL_MSK 0x40
+#define IBM525_MC1_VMASK_DISABLE 0x00
+#define IBM525_MC1_VMASK_ENABLE 0x40
+#define IBM525_MC1_PADR_RFMT_MSK 0x20
+#define IBM525_MC1_GET_PAL_ADDR 0x00
+#define IBM525_MC1_GET_ACC_STATE 0x20
+#define IBM525_MC1_SENS_DSAB_MSK 0x10
+#define IBM525_MC1_SENSE_ENABLE 0x00
+#define IBM525_MC1_SENSE_DISABLE 0x10
+#define IBM525_MC1_SENS_SEL_MSK 0x08
+#define IBM525_MC1_SENS_SEL_BIT3 0x00
+#define IBM525_MC1_SENS_SEL_BIT7 0x08
+#define IBM525_MC1_VRAM_SIZE_MSK 0x01
+#define IBM525_MC1_VRAM_32_BITS 0x00
+#define IBM525_MC1_VRAM_64_BITS 0x01
+
+//
+// Miscellaneous Clock Control Register Bit Definitions. (Section 13.2.1.4)
+//
+#define IBM525_MCC_DDOT_DSAB_MSK 0x80
+#define IBM525_MCC_DDOT_ENABLE 0x00
+#define IBM525_MCC_DDOT_DISABLE 0x80
+#define IBM525_MCC_SCLK_DSAB_MSK 0x40
+#define IBM525_MCC_SCLK_ENABLE 0x00
+#define IBM525_MCC_SCLK_DISABLE 0x40
+#define IBM525_MCC_B24P_DDOT_MSK 0x20
+#define IBM525_MCC_B24P_PLL 0x00
+#define IBM525_MCC_B24P_SCLK 0x20
+#define IBM525_MCC_DDOT_DIV_MSK 0x0E
+#define IBM525_MCC_PLL_DIV_1 0x00
+#define IBM525_MCC_PLL_DIV_2 0x02
+#define IBM525_MCC_PLL_DIV_4 0x04
+#define IBM525_MCC_PLL_DIV_8 0x06
+#define IBM525_MCC_PLL_DIV_16 0x08
+#define IBM525_MCC_PLL_ENAB_MSK 0x01
+#define IBM525_MCC_PLL_DISABLE 0x00
+#define IBM525_MCC_PLL_ENABLE 0x01
+
+
+//
+// Define valid P9100 Revision ID's
+//
+
+#define WTK_9100_REV0 0x0000 //
+#define WTK_9100_REV1 0x0000 //
+#define WTK_9100_REV2 0x0002 //
+#define WTK_9100_REV3 0x0003 //
+
+//
+// Define Power 9100 I/O Space Configuration Index Registers.
+//
+
+#define P91_CONFIG_INDEX 0x9100 // Config space index register.
+#define P91_CONFIG_DATA 0x9104 // Config space data register.
+
+//
+// Define the Weitek & OEM specific IDs for P9100 board verification...
+//
+
+#define P91_VEN_ID_WEITEK_VL 0x100E // Standard Weitek VLB Design
+#define P91_VEN_ID_VIPER_VL 0x100E // Standard VIPER VLB Design
+#define P91_VEN_ID_WEITEK_PCI 0x100E // Standard Weitek PCI Design
+#define P90_DEV_ID_WEITEK_VL 0x9000 // Standard Weitek VLB Design
+#define P91_DEV_ID_WEITEK_VL 0x9100 // Standard Weitek VLB Design
+#define P91_DEV_ID_VIPER_VL 0x9100 // Standard VIPER VLB Design
+#define P91_DEV_ID_WEITEK_PCI 0x9100 // Standard Weitek PCI Design
+
+//
+// Configuration Register Definitions, all are Read-only unless specified.
+// Note: offsets are for byte reads/writes.
+//
+
+#define P91_CONFIG_VENDOR_LOW (0) // RO-Low order byte of Vendor ID
+#define P91_CONFIG_VENDOR_HIGH (1) // RO-High order byte of Vendor ID
+#define P91_CONFIG_DEVICE_LOW (2) // RO-Low order byte of Device ID
+#define P91_CONFIG_DEVICE_HIGH (3) // RO-HIGH order byte of Device ID
+#define P91_CONFIG_CONFIGURATION (4) // RW-Configuration Register
+#define P91_CONFIG_STATUS (7) // RO-Status Register
+#define P91_CONFIG_REVISION_ID (8) // RO-Revision ID
+#define P91_CONFIG_VGA_PRESENT (10) // RO-Vga Present - set by PUCONFIG
+#define P91_CONFIG_DISPLAY (11) // RO-PCI Display Controller
+#define P91_CONFIG_WBASE (19) // RW-Memory Base for Native Mode
+#define P91_CONFIG_ROM_ENABLE (48) // RW-ROM decoding enabled
+#define P91_CONFIG_ROM_BASE_0 (49) // RW-ROM Base address, Bit 0
+#define P91_CONFIG_ROM_BASE_8_1 (50) // RW-ROM Base address, Bits 8~1
+#define P91_CONFIG_ROM_BASE_16_9 (51) // RW-ROM Base address, Bits 16~9
+#define P91_CONFIG_CFBGA (64) // RO-Config: BUS, CFBGA & EEDAIN
+#define P91_CONFIG_MODE (65) // RW-Mode select
+#define P91_CONFIG_CKSEL (66) // RW-CKSEl & VCEN
+
+//
+//
+// Clock Synth IDs:
+//
+#define CLK_ID_ICD2061A (0x00) // ICD2061a
+#define CLK_ID_FIXED_MEMCLK (0x20) // Fixed MEMCLK, RAMDAC gens pixclk
+
+//
+// Define Power 9100 coprocesser address prefix bits.
+// (Page 18)
+//
+// Address format:
+//
+// 3 2 2 1 1 1 1 1 1
+// 1 4 3 9 8 7 6 5 4 0
+// ------------------------------------------------------
+// | a a a a a a a a | 0 0 0 0 0 | H | B | b | 0 | o o |
+// ------------------------------------------------------
+//
+// a - Base Address
+// H - Word Swap
+// B - Byte Swap
+// b - Bit Swap
+// o - Coprocessor register offset
+//
+
+#define P91_WORD_SWAP 0x00040000 //
+#define P91_BYTE_SWAP 0x00020000 //
+#define P91_BIT_SWAP 0x00010000 //
+
+//
+// Define Power 9100 coprocesser system control register address offsets.
+// (Page 23)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 0 0 0 0 0 0 0 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00001 - sysconfig
+// 00010 - interrupt
+// 00011 - interrupt_en
+// 00100 - alt_write_bank
+// 00101 - alt_read_bank
+//
+
+#define P91_SYSCONFIG 0x00000004 // System configuration register.
+#define P91_INTERRUPT 0x00000008 // Interrupt register.
+#define P91_INTERRUPT_EN 0x0000000C // Interrupt enable register.
+#define P91_ALT_WRITE_BANK 0x00000010 // Alternate write bank register.
+#define P91_ALT_READ_BANK 0x00000014 // Alternate read bank register.
+
+//
+// Define Power 9100 coprocesser device coordinate register address offsets.
+// (Page 27)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 8 7 6 5 4 3 2 1 0
+// -----------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 1 0 0 0 0 | r r | a | y x | 0 0 0 |
+// -----------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (7-6):
+// 00 - X[0]/Y[0]
+// 01 - X[1]/Y[1]
+// 10 - X[2]/Y[2]
+// 11 - X[3]/Y[3]
+// a - Screen addressing bit (5):
+// 0 - Perform absolute screen addressing.
+// 1 - Perform window-relative screen addressing (write only).
+// yx - 32/16 bit read/write bits (4-3):
+// 00 - Not used.
+// 01 - Read or write 32-bit X value.
+// 10 - Read or write 32-bit Y value.
+// 11 - Read or write 16-bit X value (high 16 bits) Y value (low 16 bits).
+//
+
+#define P91_X0_32 0x00003008 // 32-bit X[0] register.
+#define P91_X1_32 0x00003048 // 32-bit X[1] register.
+#define P91_X2_32 0x00003088 // 32-bit X[2] register.
+#define P91_X3_32 0x000030C8 // 32-bit X[3] register.
+#define P91_Y0_32 0x00003010 // 32-bit Y[0] register.
+#define P91_Y1_32 0x00003050 // 32-bit Y[1] register.
+#define P91_Y2_32 0x00003090 // 32-bit Y[2] register.
+#define P91_Y3_32 0x000030D0 // 32-bit Y[3] register.
+#define P91_X0_Y0_16 0x00003018 // 16-bit X[0]/Y[0] register.
+#define P91_X1_Y1_16 0x00003058 // 16-bit X[1]/Y[1] register.
+#define P91_X2_Y2_16 0x00003098 // 16-bit X[2]/Y[1] register.
+#define P91_X3_Y3_16 0x000030D8 // 16-bit X[3]/Y[1] register.
+#define P91_WIN_REL_BIT 0x00000020 // Window relative addressing bit.
+
+//
+// Define Power 9100 coprocesser status register address offset.
+// (Page 28)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 0 0 0 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_STATUS 0x00002000 // Status register.
+
+//
+// Define Power 9100 coprocesser parameter engine control and
+// condition register address offsets.
+// (Page 29)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 1 1 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00000 - Not Used.
+// 00001 - oor
+// 00010 - Not Used.
+// 00011 - cindex
+// 00100 - w_off_xy
+// 00101 - p_w_min
+// 00110 - p_w_max
+// 00111 - Not Used.
+// 01000 - yclip
+// 01001 - xclip
+// 01010 - xedge_lt
+// 01011 - xedge_gt
+// 01100 - yedge_lt
+// 01101 - yedge_gt
+//
+
+#define P91_PE_OOR 0x00002184 // Out of Range Reg. (read only)
+#define P91_PE_CINDEX 0x0000218C // Index Reg.
+#define P91_PE_W_OFF_XY 0x00002190 // Window Offset Reg.
+#define P91_PE_P_W_MIN 0x00002194 // Pixel Window Min Reg. (read only)
+#define P91_PE_P_W_MAX 0x00002198 // Pixel Window Max Reg. (read only)
+#define P91_PE_YCLIP 0x000021A0 // Y Clip Register. (read only)
+#define P91_PE_XCLIP 0x000021A4 // X Clip Register. (read only)
+#define P91_PE_XEDGE_LT 0x000021A8 // (read only)
+#define P91_PE_XEDGE_GT 0x000021AC // (read only)
+#define P91_PE_YEDGE_LT 0x000021B0 // (read only)
+#define P91_PE_YEDGE_GT 0x000021B4 // (read only)
+
+//
+// Define Power 9100 coprocesser drawing engine register address offsets.
+// (Page 33)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 9 8 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 1 | r r r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (8-2):
+// 0000000 - color[0]
+// 0000001 - color[1]
+// 0000010 - pmask
+// 0000011 - draw_mode
+// 0000100 - pat_originx
+// 0000101 - pat_originy
+// 0000110 - raster
+// 0000111 - pixel8
+// 0001000 - p_w_min
+// 0001001 - p_w_max
+// 0001110 - color[2]
+// 0001111 - color[3]
+// 0100000 - pattern0
+// 0100001 - pattern1
+// 0100010 - pattern2
+// 0100011 - pattern3
+// 0101000 - b_w_min
+// 0101001 - b_w_max
+//
+
+#define P91_DE_COLOR0 0x00002200 // Color register 0.
+#define P91_DE_COLOR1 0x00002204 // Color register 1.
+#define P91_DE_PMASK 0x00002208 // Plane Mask register.
+#define P91_DE_DRAW_MODE 0x0000220C // Draw Mode Register.
+#define P91_DE_PAT_ORIGINX 0x00002210 // Pattern X Origin register.
+#define P91_DE_PAT_ORIGINY 0x00002214 // Pattern Y Origin register.
+#define P91_DE_RASTER 0x00002218 // Raster Operation register.
+#define P91_DE_PIXEL8 0x0000221C // Pixel 8 register.
+#define P91_DE_P_W_MIN 0x00002220 // Pixel Window Clip Minimum.
+#define P91_DE_P_W_MAX 0x00002224 // Pixel Window Clip Maximum.
+#define P91_DE_COLOR2 0x00002238 // Color register 2.
+#define P91_DE_COLOR3 0x0000223C // Color register 3.
+#define P91_DE_PATTERN0 0x00002280 // Pattern 0 register.
+#define P91_DE_PATTERN1 0x00002284 // Pattern 1 register.
+#define P91_DE_PATTERN2 0x00002288 // Pattern 2 register.
+#define P91_DE_PATTERN3 0x0000228C // Pattern 3 register.
+#define P91_DE_B_W_MIN 0x000022A0 // Byte Window Clip Minimum.
+#define P91_DE_B_W_MAX 0x000022A4 // Byte Window Clip Maximum.
+
+//
+// Define Power 9100 coprocesser video control register address offsets.
+// Note: The offsets for these registers are the same as for the Power 9000
+// except for srtctl2 which is new on the Power 9100.
+// (Page 37)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 0 0 0 0 0 1 0 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00001 - hrzc
+// 00010 - hrzt
+// 00011 - hrzsr
+// 00100 - hrzbr
+// 00101 - hrzbf
+// 00110 - prehrzc
+// 00111 - vrtc
+// 01000 - vrtt
+// 01001 - vrtsr
+// 01010 - vrtbr
+// 01011 - vrtbf
+// 01100 - prevrtc
+// 01101 - sraddr
+// 01110 - srtctl
+// 01111 - sraddr_inc
+// 10000 - srtctl2
+//
+
+#define P91_HRZC 0x00000104 // Horiz. counter (read only).
+#define P91_HRZT 0x00000108 // Horiz. length (read/write).
+#define P91_HRZSR 0x0000010C // Horiz. sync rising edge (read/write).
+#define P91_HRZBR 0x00000110 // Horiz. blank rising edge (read/write).
+#define P91_HRZBF 0x00000114 // Horiz. blank falling edge (read/write).
+#define P91_PREHRZC 0x00000118 // Horiz. counter preload (read/write).
+#define P91_VRTC 0x0000011C // Vert. counter (read only).
+#define P91_VRTT 0x00000120 // Vert. length (read/write).
+#define P91_VRTSR 0x00000124 // Vert. sync rising edge (read/write).
+#define P91_VRTBR 0x00000128 // Vert. blank rising edge (read/write).
+#define P91_VRTBF 0x0000012C // Vert. blank falling edge (read/write).
+#define P91_PREVRTC 0x00000130 // Vert. counter preload (read/write).
+#define P91_SRADDR 0x00000134 //
+#define P91_SRTCTL 0x00000138 // Screen repaint timing control 1.
+#define P91_SRADDR_INC 0x0000013C //
+#define P91_SRTCTL2 0x00000140 // Screen repaint timing control 2.
+#define P91_SRTCTL2_N (0x00) // SRTCTL2 sync polarities...
+#define P91_SRTCTL2_P (0x01)
+#define P91_SRTCTL2_H (0x03)
+#define P91_SRTCTL2_L (0x02)
+#define P91_HSYNC_HIGH_TRUE 0x00000000
+#define P91_HSYNC_LOW_TRUE 0x00000001
+#define P91_VSYNC_HIGH_TRUE 0x00000000
+#define P91_VSYNC_LOW_TRUE 0x00000004
+
+//
+// Define Power 9100 coprocesser VRAM control register address offsets.
+// Note: The offsets for these registers are the same as for the Power 9000
+// except for pu_config which is new on the Power 9100.
+// (Page 41)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 0 0 0 0 0 1 1 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00001 - mem_config
+// 00010 - rfperiod
+// 00011 - rfcount
+// 00100 - rlmax
+// 00101 - rlcur
+// 00110 - pu_config
+//
+
+#define P91_MEM_CONFIG 0x00000184 // Memory Configuration Register.
+#define P91_RFPERIOD 0x00000188 // Refresh Period Register.
+#define P91_RFCOUNT 0x0000018C // Refresh Count Register.
+#define P91_RLMAX 0x00000190 // RAS Low Miaximum Register.
+#define P91_RLCUR 0x00000194 // RAS Low Current Register.
+#define P91_PU_CONFIG 0x00000198 // Power-Up Configuration Register.
+#define P91_EXT_IO_ID 0x00000208 // Get external board id value from here
+ // to detect Intergraph board
+//
+// Define Power 9100 coprocesser meta-coordinate pseudo-register address
+// offsets.
+// (Page 43)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 9 8 6 5 4 3 2 1 0
+// -----------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 1 0 0 1 | v v v | a | y x | 0 0 0 |
+// -----------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// v - Vtype bits (8-6):
+// 000 - point
+// 001 - line
+// 010 - triangle
+// 011 - quad
+// 100 - rectangle
+// a - Screen addressing bit (5):
+// 0 - Perform addressing relative to the window offset.
+// 1 - Perform addressing relative to the previos vertex.
+// yx - 32/16 bit read/write bits (4-3):
+// 00 - Not used.
+// 01 - Read or write 32-bit X value.
+// 10 - Read or write 32-bit Y value.
+// 11 - Read or write 16-bit X value (high 16 bits) Y value (low 16 bits).
+//
+
+#define P91_META_X_32 0x00003208 // 32-bit X coordinate value.
+#define P91_META_Y_32 0x00003210 // 32-bit Y coordinate value.
+#define P91_META_X_Y_16 0x00003218 // 16-bit X/Y coordinate value.
+#define P91_META_POINT 0x00000000 // Point draw type bits.
+#define P91_META_LINE 0x00000040 // Line draw type bits.
+#define P91_META_TRIANGLE 0x00000080 // Triangle draw type bits.
+#define P91_META_QUAD 0x000000C0 // Quadrilateral draw type bits.
+#define P91_META_RECT 0x00000100 // Rectangle draw type bits.
+#define P91_META_WIN_REL 0x00000000 // Window relative addressing bits.
+#define P91_META_VERT_REL 0x00000020 // Vertex relative addressing bits.
+
+//
+// Define Power 9100 coprocesser quad command register address offset.
+// (Page 44)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 0 1 0 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_QUAD 0x00002008 // Quad Command Register.
+
+//
+// Define Power 9100 coprocesser blit command register address offset.
+// (Page 44)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 0 0 1 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_BLIT 0x00002004 // Blit Command Register.
+
+//
+// Define Power 9100 coprocesser pixel8 command register address offset.
+// (Page 45)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 1 - - - - - - - - - - - - | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_PIXEL8 0x00004000 // Pixel 8 Command Register.
+
+//
+// Define Power 9100 coprocesser pixel1 command register address offset.
+// (Page 45)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// -------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 1 | # # # # # | 0 0 |
+// -------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_PIXEL1 0x00002080 // Pixel 1 Command Register.
+#define P91_PIXEL1_COUNT_MSK 0x0000007C // Pixel Count Mask
+#define P91_PIXEL1_32_PIXELS 0x0000007C // Maximum Pixel Count
+
+//
+// Define Power 9100 coprocesser next pixels command register address offset.
+// (Page 46)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 1 0 1 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_NEXT_PIXELS 0x00002014 // Next Pixels Command Register.
+
+// 3 1
+// 1 5 0
+// -------------------------------------------------------------------
+// | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 |
+// -------------------------------------------------------------------
+
+
+//
+// Define the Power-Up Configuration Register Bits.
+// Page (Page 13)
+// 2 1 1 1 1
+// 3 6 5 2 1 8 7 5 4 3 2 1 0
+// -------------------------------------------------
+// | 0 | - - - - | 0 | - - - | - | - | - - | - |
+// -------------------------------------------------
+// | | | | | | | | | | | | | |
+// | ------- | ----- | | --- |
+// | | | | | | | ----> Motherboard implementation.
+// | | | | | | ---------> EEProm Type
+// | | | | | --------------> VRAM SAM Size.
+// | | | | ------------------> VRAM Memory Depth.
+// | | | ------------------------> Frequency Synthesizer type.
+// | | -------------------------------> Reserved.
+// | ---------------------------------------> RAMDAC Type.
+// -----------------------------------------------> Reserved.
+//
+// 3 3 2 2 2 2 2
+// 1 0 9 7 6 5 4
+// ---------------------------
+// | - - | - - - | - | - | 0 |
+// ---------------------------
+// | | | | | | | |
+// --- ----- | | ---------------> Reserved.
+// | | | -------------------> VGA presence.
+// | | -----------------------> Initial Mode Select.
+// | -----------------------------> Configuration Registers Base Address.
+// ------------------------------------> Bus Type.
+//
+
+#define P91_PUC_IMPLEMENTATION 0x00000001 //
+#define P91_PUC_MOTHER_BOARD 0x00000000 //
+#define P91_PUC_ADD_IN_CARD 0x00000001 //
+#define P91_PUC_EEPROM_TYPE 0x00000006 //
+#define P91_PUC_EEPROM_AT24C01 0x00000000 //
+#define P91_PUC_VRAM_SAM_SIZE 0x00000008 //
+#define P91_PUC_FULL_SIZE_SHIFT 0x00000000 //
+#define P91_PUC_HALF_SIZE_SHIFT 0x00000008 //
+#define P91_PUC_MEMORY_DEPTH 0x00000010 //
+#define P91_PUC_256K_VRAMS 0x00000000 //
+#define P91_PUC_128K_VRAMS 0x00000010 //
+#define P91_PUC_FREQ_SYNTH_TYPE 0x000000E0 //
+#define P91_PUC_EXT_IO 0x00000100 // External I/O regs are on DAC interface
+#define P91_PUC_ICD_2061A 0x00000000 // ICD2061a
+#define P91_PUC_FIXED_MEMCLK 0x00000020 // Fixed MEMCLK, RAMDAC gens pixclk
+#define P91_PUC_RAMDAC_TYPE 0x0000F000 //
+#define P91_PUC_DAC_BT485 0x00000000 //
+#define P91_PUC_DAC_BT489 0x00001000 //
+#define P91_PUC_DAC_IBM525 0x00008000 //
+#define P91_PUC_VGA_PRESENCE 0x02000000 //
+#define P91_PUC_VGA_ABSENT 0x00000000 //
+#define P91_PUC_VGA_PRESENT 0x02000000 //
+#define P91_PUC_INITIAL_MODSEL 0x04000000 //
+#define P91_PUC_NATIVE_MODE 0x00000000 //
+#define P91_PUC_VGA_MODE 0x04000000 //
+#define P91_PUC_CONFIG_REG_BASE 0x38000000 //
+#define P91_PUC_BASE_9100_9104 0x00000000 //
+#define P91_PUC_BASE_9108_910C 0x08000000 //
+#define P91_PUC_BASE_9110_9114 0x10000000 //
+#define P91_PUC_BASE_9118_911C 0x18000000 //
+#define P91_PUC_BASE_9120_9124 0x20000000 //
+#define P91_PUC_BASE_9128_912C 0x28000000 //
+#define P91_PUC_BASE_9130_9134 0x30000000 //
+#define P91_PUC_BASE_9138_913C 0x38000000 //
+#define P91_PUC_BUS_TYPE 0xC0000000 //
+#define P91_PUC_BUS_PCI 0x40000000 //
+#define P91_PUC_BUS_VESA 0x80000000 //
+
+//
+// Define Power up configuration bit field positions for use in shifting
+// the various fields to bit 0.
+//
+
+#define P91_PUC_EEPROM_SHIFT_CNT 0x01
+#define P91_PUC_SYNTH_SHIFT_CNT 0X05
+#define P91_PUC_RAMDAC_SHIFT_CNT 0x0C
+#define P91_PUC_REG_SHIFT_CNT 0x1B
+#define P91_PUC_BUS_SHIFT_CNT 0x1E
+
+//
+// Define the System Configuration Register Bits.
+// (Page 24)
+// 1 1 1 1 1 1 1 1
+// 9 7 6 4 3 2 1 0 9 8 0
+// -----------------------------------------
+// | - - - | - - - | - | - | - | - | - | 0 |
+// -----------------------------------------
+// | | | | | | | | | | | |
+// ----- ----- | | | | | -> Reserved. Must be 0.
+// | | | | | | -----> Pixel write buffer selection.
+// | | | | | ---------> Pixel read buffer selection.
+// | | | | -------------> Pixel access bit swap.
+// | | | -----------------> Pixel access byte swap.
+// | | ---------------------> Pixel access half-word swap.
+// | ---------------------------> Shift control 2.
+// -----------------------------------> Shift control 1.
+//
+// 3 3 2 2 2 2 2 2 2 2
+// 1 0 9 8 6 5 4 3 2 0
+// ---------------------------------------
+// | 0 | - - | - - - | - | - | - | - - - |
+// ---------------------------------------
+// | | | | | | | | | | |
+// | | ----- | | | -----
+// | | | | | | |
+// | | | | | | -----> Shift control 0.
+// | | | | | -----------> Overide internal PLL.
+// | | | | ---------------> Frame buffer controller drive load.
+// | | | -------------------> Disable internal selftiming on FBC.
+// | | -------------------------> Pixel size for drawing engine.
+// | --------------------------------> Shift control 3.
+// -------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_WRITE_BUF_1 0x00000200
+#define P91_READ_BUF_1 0x00000400
+#define P91_SWAP_BITS 0x00000800
+#define P91_SWAP_BYTES 0x00001000
+#define P91_SWAP_WORDS 0x00002000
+#define P91_SHIFT2_0 0x00000000
+#define P91_SHIFT2_32 0x00004000
+#define P91_SHIFT2_64 0x00008000
+#define P91_SHIFT2_128 0x0000C000
+#define P91_SHIFT2_256 0x00010000
+#define P91_SHIFT2_512 0x00014000
+#define P91_SHIFT2_FIELD_INC 0x00004000
+#define P91_SHIFT1_0 0x00000000
+#define P91_SHIFT1_64 0x00040000
+#define P91_SHIFT1_128 0x00060000
+#define P91_SHIFT1_256 0x00080000
+#define P91_SHIFT1_512 0x000A0000
+#define P91_SHIFT1_1024 0x000C0000
+#define P91_SHIFT1_FIELD_INC 0x00020000
+#define P91_SHIFT0_0 0x00000000
+#define P91_SHIFT0_128 0x00300000
+#define P91_SHIFT0_256 0x00400000
+#define P91_SHIFT0_512 0x00500000
+#define P91_SHIFT0_1024 0x00600000
+#define P91_SHIFT0_2048 0x00700000
+#define P91_SHIFT0_FIELD_INC 0x00100000
+#define P91_EXT_PLL_CLOCK 0x00800000
+#define P91_DBL_DRIVE_LOAD 0x01000000
+#define P91_SELFTIME_DIS 0x02000000
+#define P91_DE_8BPP 0x08000000
+#define P91_DE_16BPP 0x0C000000
+#define P91_DE_24BPP 0x1C000000
+#define P91_DE_32BPP 0x14000000
+#define P91_SHIFT3_0 0x00000000
+#define P91_SHIFT3_1024 0x20000000
+#define P91_SHIFT3_2048 0x40000000
+#define P91_SHIFT3_4096 0x60000000
+#define P91_SHIFT3_FIELD_INC 0x20000000
+
+//
+// Define the Interrupt Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// (Page 25)
+// 3
+// 1 6 5 4 3 2 1 0
+// -------------------------
+// | 0 | - - | - - | - - |
+// -------------------------
+// | | | | | | |
+// | | | | | | -----------------> Draw Engine Idle INT.
+// | | | | | -------------------> Draw Engine Idle INT Write Enable.
+// | | | | -----------------------> Pick Done INT.
+// | | | -------------------------> Pick Done INT. Write Enable.
+// | | -----------------------------> VBlank Done INT.
+// | -------------------------------> VBlank Done INT Write Enable.
+// ------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_DE_IDLE 0x00000001
+#define P91_DE_IDLE_CLEAR 0x00000002
+#define P91_PICK_DONE 0x00000004
+#define P91_PICK_DONE_CLEAR 0x00000008
+#define P91_VBLANK_DONE 0x00000010
+#define P91_VBLANK_DONE_CLEAR 0x00000020
+
+//
+// Define the Interrupt Enable Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// Page (26)
+// 3
+// 1 8 7 6 5 4 3 2 1 0
+// -------------------------------
+// | 0 | - - | - - | - - | - - |
+// -------------------------------
+// | | | | | | | | |
+// | | | | | | | | -----------> Draw Engine Int. Enable.
+// | | | | | | | -------------> Draw Engine Write Enable.
+// | | | | | | -----------------> Pick Int. Enable.
+// | | | | | -------------------> Pick Write Enable.
+// | | | | -----------------------> VBlank Int. Enable.
+// | | | -------------------------> VBlank Write Enable.
+// | | -----------------------------> Master Int. Enable.
+// | -------------------------------> Master Enable Write Enable.
+// ------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_DE_IDLE_DIS 0x00000002 // Disable Draw Engine idle INT.
+#define P91_DE_IDLE_EN 0x00000003 // Enable Draw Engine idle INT.
+#define P91_PICKED_DIS 0x00000008 // Disable Pick INT.
+#define P91_PICKED_EN 0x0000000C // Enable Pick INT.
+#define P91_VBLANKED_DIS 0x00000020 // Disable VBlank INT.
+#define P91_VBLANKED_EN 0x00000030 // Enable VBlank INT.
+#define P91_MASTER_DIS 0x00000080 // Disable all interrupts.
+#define P91_MASTER_EN 0x000000C0 // Enable INTs according to bits 5-0.
+
+//
+// Define the Status Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// (Page 28)
+// 3 3 2
+// 1 0 9 8 7 6 5 4 3 2 1 0
+// -----------------------------------------------
+// | - | - | 0 | - | - | - | - | - | - | - | - |
+// -----------------------------------------------
+// | | | | | | | | | | |
+// | | | | | | | | | | ----> Quad intersects clip window.
+// | | | | | | | | | --------> Quad inside clip window.
+// | | | | | | | | ------------> Quad outside clip window.
+// | | | | | | | ----------------> Quad is concave.
+// | | | | | | --------------------> Quad must be done by software.
+// | | | | | ------------------------> Blit must be done by software.
+// | | | | ----------------------------> Pixel must be done by software.
+// | | | --------------------------------> Pick detected.
+// | | -------------------------------------> Reserved.
+// | ------------------------------------------> Drawing engine busy.
+// -----------------------------------------------> Quad/blit re-initiate.
+//
+
+#define P91_SR_QUAD_INTERSECT 0x00000001
+#define P91_SR_QUAD_VISIBLE 0x00000002
+#define P91_SR_QUAD_HIDDEN 0x00000004
+#define P91_SR_QUAD_CONCAVE 0x00000008
+#define P91_SR_QUAD_SOFTWARE 0x00000010
+#define P91_SR_BLIT_SOFTWARE 0x00000020
+#define P91_SR_PIXEL_SOFTWARE 0x00000040
+#define P91_SR_PICKED 0x00000080
+#define P91_SR_ENGINE_BUSY 0x40000000
+#define P91_SR_NO_REINITIATE 0x80000000
+
+//
+// Define the Draw Mode Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// Page (34)
+// 3
+// 1 4 3 2 1 0
+// -------------------
+// | 0 | - - | - - |
+// -------------------
+// | | | | |
+// | | | | -----------------------> Pick write enable bit.
+// | | | -------------------------> Write enable Pick write enable bit.
+// | | -----------------------------> Buffer selection bit.
+// | -------------------------------> Write enable Buffer selection bit.
+// ------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_WR_INSIDE_WINDOW 0x00000002
+#define P91_SUPPRESS_ALL_WRITES 0x00000003
+#define P91_DE_DRAW_BUFF_0 0x00000008
+#define P91_DE_DRAW_BUFF_1 0x0000000C
+
+//
+// Define the Raster Register Bits.
+// (Page 34)
+// 3 1 1 1 1 1 1 1
+// 1 8 7 6 5 4 3 2 8 7 0
+// ---------------------------------------------------
+// | 0 | - | - | - | - | - | 0 | - - - - - - - - |
+// ---------------------------------------------------
+// | | | | | | | | | | | | | | |
+// | | | | | | | ---------------
+// | | | | | | | |
+// | | | | | | | --------> Minterms.
+// | | | | | | --------------------> Reserved.
+// | | | | | -------------------------> Solid Color Disable.
+// | | | | -----------------------------> Pattern Depth.
+// | | | ---------------------------------> Transparent Pixel1 Enable.
+// | | -------------------------------------> Quad Draw Mode.
+// | -----------------------------------------> Transparent Pattern Enable.
+// ----------------------------------------------> Reserved.
+//
+
+#define P91_RR_SOLID_ENABLE 0x00000000
+#define P91_RR_SOLID_DISABLE 0x00002000
+#define P91_RR_2_CLR_PATTERN 0x00000000
+#define P91_RR_4_CLR_PATTERN 0x00004000
+#define P91_RR_TRANS_PIX1_DISABL 0x00000000
+#define P91_RR_TRANS_PIX1_ENABLE 0x00008000
+#define P91_RR_QUAD_X11_MODE 0x00000000
+#define P91_RR_QUAD_OVERSIZE 0x00010000
+#define P91_RR_TRANS_PAT_DISABL 0x00000000
+#define P91_RR_TRANS_PAT_ENABLE 0x00020000
+
+//
+// Define the Screen Repaint Timing Control (SRTCTL) Register Bits.
+// (Page 40)
+// 3 1 1 1
+// 1 2 1 0 9 8 7 6 5 4 3 2 0
+// -------------------------------------------------
+// | 0 | - | - - | - | - | 0 | - | - | - | - - - |
+// -------------------------------------------------
+// | | | | | | | | | | | | |
+// | | --- | | | | | | -----
+// | | | | | | | | | |
+// | | | | | | | | | -----> QSF Counter Position.
+// | | | | | | | | -----------> Buffer For Display.
+// | | | | | | | ---------------> Screen Repaint Mode.
+// | | | | | | -------------------> Enable Video.
+// | | | | | -----------------------> Reserved.
+// | | | | ---------------------------> Internal Horizontal Sync.
+// | | | -------------------------------> Internal Vertical Sync.
+// | | ------------------------------------> SRADDR Increment Value.
+// | -----------------------------------------> 24-Bit DAC Clock Skip Mode.
+// ----------------------------------------------> Reserved.
+//
+
+#define P91_SRTCTL_QSF_MSK 0x00000007
+#define P91_SRTCTL_DISP_BUFFER 0x00000004
+#define P91_SRTCTL_DISP_BUFF_0 0x00000000
+#define P91_SRTCTL_DISP_BUFF_1 0x00000004
+#define P91_SRTCTL_HBLNK_RELOAD 0x00000010
+#define P91_SRTCTL_HR_NORMAL 0x00000000
+#define P91_SRTCTL_HR_RESTRICTED 0x00000010
+#define P91_SRTCTL_ENABLE_VIDEO 0x00000020
+#define P91_SRTCTL_HSYNC 0x00000080
+#define P91_SRTCTL_HSYNC_EXT 0x00000000
+#define P91_SRTCTL_HSYNC_INT 0x00000080
+#define P91_SRTCTL_VSYNC 0x00000100
+#define P91_SRTCTL_VSYNC_EXT 0x00000000
+#define P91_SRTCTL_VSYNC_INT 0x00000100
+#define P91_SRTCTL_SRC_INCS 0x00000600
+#define P91_SRTCTL_SRC_INC_256 0x00000000
+#define P91_SRTCTL_SRC_INC_512 0x00000200
+#define P91_SRTCTL_SRC_INC_1024 0x00000400
+#define P91_SRTCTL_V_24EN 0x00000800
+#define P91_SRTCTL_24EN_DISABLE 0x00000000
+#define P91_SRTCTL_24EN_ENABLE 0x00000800
+
+//
+// Define the Screen Repaint Timing Control 2 (SRTCTL2) Register Bits.
+// (Page 40)
+// 3
+// 1 4 3 2 1 0
+// -------------------
+// | 0 | - - | - - |
+// -------------------
+// | | | | |
+// | --- ---
+// | | |
+// | | ------------------------> External VSYNC Polarity Control.
+// | ------------------------------> External HSYNC Polarity Control.
+// ------------------------------------> Reserved.
+//
+
+#define P91_SRTCTL2_EXT_VSYNC 0x00000003
+
+#if 0
+#define P91_VSYNC_LOW_TRUE 0x00000000
+#define P91_VSYNC_HIGH_TRUE 0x00000001
+#endif
+
+#define P91_VSYNC_LOW_FORCED 0x00000002
+#define P91_VSYNC_HIGH_FORCED 0x00000003
+#define P91_SRTCTL2_EXT_HSYNC 0x0000000C
+
+#if 0
+#define P91_HSYNC_LOW_TRUE 0x00000000
+#define P91_HSYNC_HIGH_TRUE 0x00000004
+#endif
+
+#define P91_HSYNC_LOW_FORCED 0x00000008
+#define P91_HSYNC_HIGH_FORCED 0x0000000C
+
+//
+// Define the Memory Configuration Register Bits.
+// (Page 42)
+// 9 8 7 6 5 4 3 2 0
+// -------------------------------------
+// | - | - | - | - | - | - | - | - - - |
+// -------------------------------------
+// | | | | | | | | | |
+// | | | | | | | -----
+// | | | | | | | |
+// | | | | | | | -------> VRAM Memory Confiuration [2..0].
+// | | | | | | -------------> VRAM Row Miss Timing Adjustment.
+// | | | | | -----------------> VRAM Read Timing Adjustment.
+// | | | | ---------------------> VRAM Write Timing Adjustment.
+// | | | -------------------------> VCP Priority Select.
+// | | -----------------------------> RAMDAC Access Adjustment.
+// | ---------------------------------> DAC Read/Write signalling mode.
+// -------------------------------------> Memory/Video Reset.
+//
+// 2 2 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 3 2 0
+// ---------------------------------------
+// | - | - | - | 0 | - - | - - - | - - - |
+// ---------------------------------------
+// | | | | | | | | | | | |
+// | | | | --- ----- -----
+// | | | | | | |
+// | | | | | | -----> VRAM Shift Clock State Macine.
+// | | | | | -------------> Internal CRTC Divided Dot Clock.
+// | | | | --------------------> Muxsel pin polarity.
+// | | | -------------------------> Reserved.
+// | | -----------------------------> Clock Edge Syrchonization.
+// | ---------------------------------> Video Clock Source Selection.
+// -------------------------------------> Additional Divide for Video Transfer.
+//
+// 3 3 2 2 2 2 2 2 2 2
+// 1 0 9 8 7 6 5 4 3 2
+// -----------------------------------
+// | - | - | - | - - | 0 | - - | - - |
+// -----------------------------------
+// | | | | | | | | | |
+// | | | --- --- ---
+// | | | | | | |
+// | | | | | | --------> Shift Clock Timing Pattern Selection.
+// | | | | | --------------> Serial Output Timing Pattern Selection.
+// | | | | -------------------> Reserved.
+// | | | ------------------------> Blank Generation Delay Selection.
+// | | -----------------------------> VRAM Memory Configuration [3].
+// | ---------------------------------> Slow Host Interface Adjustment.
+// -------------------------------------> VRAM REad Timing Adjustment.
+//
+//
+//
+
+#define P91_MC_CNFG_2_0_MSK 0x00000007
+#define P91_MC_CNFG_3_MSK 0x20000000
+#define P91_MC_CNFG_MSK 0x20000007
+#define P91_MC_CNFG_1 0x00000001 // 2 banks, 128K VRAMs, 1 1Mb buffer.
+#define P91_MC_CNFG_3 0x00000003 // 4 banks, 128K VRAMs, 1 2Mb buffer.
+#define P91_MC_CNFG_4 0x00000004 // 1 bank, 256K VRAMs, 1 1Mb buffer.
+#define P91_MC_CNFG_5 0x00000005 // 2 banks, 256K VRAMs, 1 2Mb buffer.
+#define P91_MC_CNFG_7 0x00000007 // 4 banks, 256K VRAMs, 1 4Mb buffer.
+#define P91_MC_CNFG_11 0x20000003 // 4 banks, 128K VRAMs, 2 1Mb buffers.
+#define P91_MC_CNFG_14 0x20000006 // 2 banks, 256K VRAMs, 2 1Mb buffers.
+#define P91_MC_CNFG_15 0x20000007 // 4 banks, 256K VRAMs, 2 2Mb buffers.
+#define P91_MC_MISS_ADJ_0 0x00000000
+#define P91_MC_MISS_ADJ_1 0x00000008
+#define P91_MC_READ_ADJ_0 0x00000000
+#define P91_MC_READ_ADJ_1 0x00000010
+#define P91_MC_WRITE_ADJ_0 0x00000000
+#define P91_MC_WRITE_ADJ_1 0x00000020
+#define P91_MC_VCP_PRIORITY_LO 0x00000000
+#define P91_MC_VCP_PRIORITY_HI 0x00000040
+#define P91_MC_DAC_ACCESS_ADJ_0 0x00000000
+#define P91_MC_DAC_ACCESS_ADJ_1 0x00000080
+#define P91_MC_DAC_MODE_0 0x00000000
+#define P91_MC_DAC_MODE_1 0x00000100
+#define P91_MC_HOLD_RESET 0x00000200
+#define P91_MC_MEM_VID_NORMAL 0x00000000
+#define P91_MC_MEM_VID_RESET 0x00000200
+#define P91_MC_SHFT_CLK_DIV_1 0x00000000
+#define P91_MC_SHFT_CLK_DIV_2 0x00000400
+#define P91_MC_SHFT_CLK_DIV_4 0x00000800
+#define P91_MC_SHFT_CLK_DIV_8 0x00000C00
+#define P91_MC_SHFT_CLK_DIV_16 0x00001000
+#define P91_MC_CRTC_CLK_DIV_1 0x00000000
+#define P91_MC_CRTC_CLK_DIV_2 0x00002000
+#define P91_MC_CRTC_CLK_DIV_4 0x00004000
+#define P91_MC_CRTC_CLK_DIV_8 0x00006000
+#define P91_MC_CRTC_CLK_DIV_16 0x00008000
+#define P91_MC_MUXSEL_NORMAL 0x00000000
+#define P91_MC_MUXSEL_INVERT 0x00010000
+#define P91_MC_MUXSEL_LOW 0x00020000
+#define P91_MC_MUXSEL_HIGH 0x00030000
+#define P91_MC_BLANK_EDGE_MSK 0x00080000
+#define P91_MC_SYNC_RISE_EDGE 0x00000000
+#define P91_MC_SYNC_FALL_EDGE 0x00080000
+#define P91_MC_VCLK_SRC_PIXCLK 0x00000000
+#define P91_MC_VCLK_SRC_DDOTCLK 0x00100000
+#define P91_MC_VAD_DIV_1 0x00000000
+#define P91_MC_VAD_DIV_2 0x00200000
+#define P91_MC_SHFT_CLK_1_BANK 0x00000000
+#define P91_MC_SHFT_CLK_2_BANK 0x00400000
+#define P91_MC_SHFT_CLK_4_BANK 0x00800000
+#define P91_MC_SERIAL_OUT_1_BANK 0x00000000
+#define P91_MC_SERIAL_OUT_2_BANK 0x01000000
+#define P91_MC_SERIAL_OUT_4_BANK 0x02000000
+#define P91_MC_BLNKDLY_MSK 0x18000000
+#define P91_MC_BLNKDLY_0_CLK 0x00000000
+#define P91_MC_BLNKDLY_1_CLK 0x08000000
+#define P91_MC_BLNKDLY_2_CLK 0x10000000
+#define P91_MC_BLNKDLY_3_CLK 0x18000000
+#define P91_MC_SLOW_HOST_ADJ_0 0x00000000
+#define P91_MC_SLOW_HOST_ADJ_1 0x40000000
+#define P91_MC_READ_SMPL_ADJ_0 0x00000000
+#define P91_MC_READ_SMPL_ADJ_1 0x80000000
+
+//
+// Miscellaneous command register bit definitions.
+//
+
+#define P91_QUAD_BUSY 0x80000000
+#define P91_BLIT_BUSY 0x80000000
+
+
+typedef union {
+ ULONG ul;
+ USHORT aw[2];
+ UCHAR aj[4];
+} UWB ;
+
+#define IBM525_WR_DAC(index, data) \
+{ \
+ ULONG ulIndex; \
+ UWB uwb; \
+ \
+ uwb.aj[0] = (UCHAR) data; \
+ uwb.aj[1] = uwb.aj[0]; \
+ uwb.aw[1] = uwb.aw[0]; \
+ \
+ ulIndex = index & ~0x3; \
+ \
+ P9_WR_REG(ulIndex, uwb.ul); \
+}
+
+#define IBM525_RD_DAC(index, val) \
+{ \
+ ULONG ulIndex; \
+ UWB uwb; \
+ \
+ ulIndex = index & ~0x3; \
+ \
+ uwb.ul = P9_RD_REG(ulIndex); \
+ \
+ uwb.aj[3] = uwb.aj[2]; \
+ uwb.aw[0] = uwb.aw[1]; \
+ \
+ val = uwb.aj[0]; \
+}
+
+#define CURS_ACTIVE_IBM525 (0x02)
+#define ENB_CURS_IBM525 (0x02)
+#define DIS_CURS_IBM525 ~CURS_ACTIVE_IBM525
+
+#define CURS_IS_ON_IBM525() \
+ (ReadIBM525(RGB525_CURSOR_CTL) & CURS_ACTIVE_IBM525)
+
+#define CURS_ON_IBM525() \
+ WriteIBM525(RGB525_CURSOR_CTL, (UCHAR) (ReadIBM525(RGB525_CURSOR_CTL) | ENB_CURS_IBM525))
+
+#define CURS_OFF_IBM525() \
+ WriteIBM525(RGB525_CURSOR_CTL, (UCHAR) (ReadIBM525(RGB525_CURSOR_CTL) & DIS_CURS_IBM525))
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxpcibrd.c b/private/ntos/nthals/halppc/ppc/pxpcibrd.c
new file mode 100644
index 000000000..3f6c28271
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpcibrd.c
@@ -0,0 +1,1028 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jwooldridge@austin.vnet.ibm.com)
+ Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+// #define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ //Rescan = CB.PciData->u.type1.SecondaryBus; JAKETEMP
+ Rescan = CB.PciData->u.type1.SecondaryBus + 1;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+ // BUGBUG This is OK on existing PPCs too, but this may have to change
+ // on later implementations.
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxpcibus.c b/private/ntos/nthals/halppc/ppc/pxpcibus.c
new file mode 100644
index 000000000..438d63963
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpcibus.c
@@ -0,0 +1,2386 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) - Updated and merged support for various PPC boxes.
+ Jake Oshins (joshins@vnet.ibm.com) -- Further merging and generalization, support for more boxes.
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+ULONG HalpPciMaxBuses = 0;
+extern ULONG HalpPciMaxSlots;
+#if defined(UNION)
+extern PVOID HalpPciConfigAddr[];
+extern PVOID HalpPciConfigData[];
+#endif
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ //
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+ //
+ // Build a tree that shows the relationship of all the PCI busses
+ // to be used when routing interrupts.
+ //
+ HalpMapPlugInPciBridges (PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ // set defaults
+
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetPCIIrq;
+
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+#if defined(UNION)
+ BusData->Config.Type2.Address = HalpPciConfigAddr[BusNo >> 8];
+ BusData->Config.Type2.Data = HalpPciConfigData[BusNo >> 8];
+#else
+ BusData->Config.Type2.Address = (PUCHAR)HalpIoControlBase + 0xCF8;
+ BusData->Config.Type2.Data = (PUCHAR)HalpIoControlBase + 0xCFC;
+#endif
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = HalpPciMaxSlots;
+
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+// DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { //IBMCPK: added =
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer = Tmp.Bytes[i];
+
+// WRITE_PORT_ULONG ((PUCHAR) HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR) HalpIoControlBase + 0xCFC + i);
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer++ = Tmp.Bytes[i++];
+ if ( i == sizeof(ULONG) ) {
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ *Buffer = Tmp.Bytes[i];
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)HalpIoControlBase + 0xCFC + i);
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG(BusData->Config.Type2.Data);
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG);
+// *((PULONG) Buffer) = READ_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCFC);
+
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*Buffer);
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i++] = *Buffer++;
+ if ( i == sizeof(ULONG) ) {
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// WRITE_PORT_USHORT ((PUCHAR)HalpIoControlBase + 0xCFC + (USHORT) i,*((PUSHORT)Buffer));
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, *((PULONG)Buffer));
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG);
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCFC,*((PULONG)Buffer));
+
+ return sizeof(ULONG);
+}
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK:added -1
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK: added -1
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+ // But don't change video devices, they will be enabled or
+ // disabled by HalpInitializeDisplay()
+ //
+ // (For the moment, that means we are shutting off the
+ // S3 chip so that a plug-in Weitek card can get a chance
+ // to talk to GDI.
+
+ if (!(IsVideoDevice(PciData))) {
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+ } else {
+
+ PciData->Command = PciOrigData->Command;
+ }
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+VOID
+HalpPhase0DiscoverPciBuses(
+ IN PCONFIGURATION_COMPONENT_DATA Component
+ )
+/*
+ This function looks down the LoaderBlock looking for nodes that
+ correspond to PCI buses. When it has found them all, it sets
+ HalpPciMaxBuses.
+*/
+{
+ // Check to see if this component would look like a "multi(x)"
+ // entry in ARC.
+ if ((Component->ComponentEntry.Class == AdapterClass) &&
+ (Component->ComponentEntry.Type == MultiFunctionAdapter)) {
+
+ //
+ // First check to see if Identifier is valid, then
+ // check the string it points to.
+ //
+ if (Component->ComponentEntry.Identifier) {
+
+ if ((Component->ComponentEntry.Identifier[0] == 'P') &&
+ (Component->ComponentEntry.Identifier[1] == 'C') &&
+ (Component->ComponentEntry.Identifier[2] == 'I')) {
+
+ HalpPciMaxBuses++; // Increment the number of PCI buses
+
+ }
+ }
+ }
+
+ //
+ // Look at the Siblings of this component
+ //
+ if (Component->Sibling) {
+ HalpPhase0DiscoverPciBuses(Component->Sibling);
+ }
+
+ //
+ // Look at the Children of this component
+ //
+ if (Component->Child) {
+ HalpPhase0DiscoverPciBuses(Component->Child);
+ }
+
+
+}
+
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxpciint.c b/private/ntos/nthals/halppc/ppc/pxpciint.c
new file mode 100644
index 000000000..a67e2d109
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpciint.c
@@ -0,0 +1,254 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+#define P91_DEVICE_ID 0x9100100E
+extern PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress; // in pxp91.c
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+// This function maps the device's InterruptPin to an InterruptLine
+// value.
+//
+// On Sandalfoot and Polo machines PCI interrupts are statically routed
+// via slot number. This routine just returns and the static routing
+// is done in HalpGetIsaFixedPCIIrq
+//
+
+--*/
+{
+
+
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+
+--*/
+{
+}
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG cnt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // This next part is a major HACK. The Weitek video
+ // adapter (which is one of IBM's favorites) needs
+ // to have its frame buffer enabled by the HAL so
+ // that the HAL can write to the screen. The device
+ // driver for this card needs to touch the frame buffer
+ // during its initialization phase, which overlaps with
+ // the period of time that the HAL is writing to the
+ // screen. So, to avoid breaking one or the other,
+ // we need to force the device driver to use the
+ // same I/O space for the frame buffer that the HAL
+ // was using. Unfortunately, this is the only place
+ // to do it. -- Jake Oshins 1/2/96
+
+ // The Baby Blue and Sky Blue video adapters from IBM
+ // have the same requirements. -- Jake Oshins 7/11/96
+
+ HalpGetPCIData(BusHandler,
+ RootHandler,
+ PciSlot,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // We want to do this only for certain video devices that are
+ // already decoding a range of memory.
+ //
+ if (((PciData->VendorID == 0x1014) || // IBM video devices
+ (PciData->VendorID == 0x100E)) && // Weitek video devices
+ (PciData->u.type0.BaseAddresses[0] & 0xfffffff0))
+ {
+ for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
+ switch ((*pResourceList)->List->Descriptors->Type) {
+ case CmResourceTypeInterrupt:
+ case CmResourceTypePort:
+ case CmResourceTypeDma:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Set the bottom of the range to the value in the Base Address Register
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0];
+
+ //
+ // Set the top of the range to the BAR plus the requested length
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0] +
+ (*pResourceList)->List->Descriptors->u.Memory.Length;
+
+ }
+
+ }
+
+ }
+
+ return Status;
+
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxpcisup.c b/private/ntos/nthals/halppc/ppc/pxpcisup.c
new file mode 100644
index 000000000..89fc67141
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpcisup.c
@@ -0,0 +1,326 @@
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ T. White -- Added dword I/O to allow GXT150P to work correctly
+
+Special Note:
+
+ Please make sure that the dword I/O mechanisms are carried
+ forward for any box which is to support the GXT150P graphics
+ adapter. The GXT150P graphics adapter runs in any PowerPC
+ machine with a standard PCI bus connector.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+extern PVOID HalpPciConfigBase;
+#define PCI_INTERRUPT_ROUTING_SCSI 13
+#define PCI_INTERRUPT_ROUTING_OTHER 15
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#endif
+
+ULONG HalpPciConfigSlot[] = { 0x0800,
+ 0x1000,
+ 0x2000,
+ 0x4000,
+ 0x8000,
+ 0x10000,
+ 0x20000,
+ 0x40000,
+ };
+ULONG HalpPciMaxSlots = 7;
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+ This is a sandalfoot memory map implementation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ UNREFERENCED_PARAMETER(BusNumber);
+
+ return ((ULONG) ((PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[SlotNumber]));
+
+}
+
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ to = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ to += Offset;
+ from = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)to & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ from = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ from += Offset;
+ to = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)from & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ ULONG buffer[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)];
+ PPCI_COMMON_CONFIG PciData;
+
+#define PCI_VENDOR_NCR 0x1000
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+
+ if (PciSlot.u.bits.DeviceNumber == 1) {
+ (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_SCSI;
+ (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_SCSI;
+ } else {
+ (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_OTHER;
+ (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_OTHER;
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( (PciData->BaseClass == 1) ||
+ ( (PciData->VendorID == PCI_VENDOR_NCR) && (PciData->DeviceID == 1) ) ) {
+ //
+ // This device is a Mass Storage Controller, set flag to
+ // turn on the HDD Lamp when interrupts come in on this
+ // vector.
+ //
+ // N.B. We recognize NCR 810 controllers as they were implemented
+ // before class codes.
+ //
+
+ extern ULONG HalpMassStorageControllerVectors;
+
+ HalpMassStorageControllerVectors |= 1 << (*Interrupt)->Base;
+ }
+
+#endif
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpMapPlugInPciBridges(
+ UCHAR NoBuses
+ )
+
+/*++
+
+Routine Description:
+
+ Looks for any unexpected (plug-in) PCI-PCI bridges so
+ that interrupts can be mapped from these buses back
+ into the interrupt controller.
+
+Arguments:
+
+ NoBuses -- This is the number of buses that HalpGetPciBridgeConfig found
+
+Return Value:
+
+ none
+
+--*/
+{
+ // Sandalfoot doesn't support plug-in PCI busses!!!
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxport.c b/private/ntos/nthals/halppc/ppc/pxport.c
new file mode 100644
index 000000000..005a02924
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxport.c
@@ -0,0 +1,848 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Chuck Bauman 02-Jun-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+ Steve Johns (sjohns@pets.sps.mot.com)
+ - added support for multple baud rates, alternate COM port
+ - implemented KdPortSave & KdPortRestore
+
+--*/
+
+#include "halp.h"
+#include "ppcserp.h"
+
+#include <pxmemctl.h>
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+ULONG KdCurrentBaudRate= 19200;
+ULONG KdCurrentComPort = COM1_PORT;
+ULONG HalpSavedBaudRate;
+ULONG HalpSavedComPort;
+
+extern PVOID HalpIoControlBase;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 6;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameters - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+
+/*
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+
+*/
+
+ //
+ // Map I/O space if it has not already been mapped.
+ //
+
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE,
+ 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+
+ //
+ // Set COM parameters
+ //
+ if (DebugParameters != NULL) {
+ if (DebugParameters->BaudRate == 0)
+ KdCurrentBaudRate = 19200; // default baud rate
+ else
+ KdCurrentBaudRate = DebugParameters->BaudRate;
+
+ if (DebugParameters->CommunicationPort > 2)
+ return (FALSE);
+ KdCurrentComPort = COM1_PORT; // default COM port
+ if (DebugParameters->CommunicationPort == 1)
+ KdCurrentComPort = COM1_PORT;
+ if (DebugParameters->CommunicationPort == 2)
+ KdCurrentComPort = COM2_PORT;
+
+ }
+
+ HalpBaudRateDivisor = (UCHAR)((1843200/16) / KdCurrentBaudRate);
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+
+
+ KdComPortInUse=(PUCHAR)KdCurrentComPort;
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to requested rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ PSP_MODEM_STATUS LsrByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = (PSP_MODEM_STATUS) READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+DEBUG_PARAMETERS ComParams;
+
+ if (HalpSavedComPort != KdCurrentComPort ||
+ HalpSavedBaudRate != KdCurrentBaudRate) {
+ ComParams.CommunicationPort = HalpSavedComPort;
+ ComParams.BaudRate = HalpSavedBaudRate;
+ KdPortInitialize(&ComParams, NULL, TRUE);
+ }
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpSavedBaudRate = KdCurrentBaudRate;
+ HalpSavedComPort = KdCurrentComPort;
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Supplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxpower.s b/private/ntos/nthals/halppc/ppc/pxpower.s
new file mode 100644
index 000000000..56047c6c3
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpower.s
@@ -0,0 +1,123 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Module Name:
+//
+// pxpower.s
+//
+// Abstract:
+//
+// This module implements the routines to set Doze mode and Dynamic Power management
+// mode on the PowerPC.
+//
+// Author:
+//
+// N. Yoshiyama ( nyoshiyama@vnet.ibm.com )
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "kxppc.h"
+
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+//++
+//
+// VOID
+// HalpProcessorIdle (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets CPU into Doze mode if it is PowerPC 603 and
+// enable External interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProcessorIdle)
+
+ mfmsr r.4 // Read MSR
+ ori r.4, r.4, 0x8000 // Enable External/Decrementer interrupts
+
+ mfpvr r.3 // Read PVR
+ rlwinm r.3, r.3, 16, 16, 31
+ cmpwi cr.0, r.3, 6 // Is it a 603e ?
+ cmpwi cr.1, r.3, 7 // Is it a 603ev ?
+ cmpwi cr.7, r.3, 3 // Is it a 603 ?
+ beq cr.0, SetDozeMode //
+ beq cr.1, SetDozeMode //
+ bne cr.7, EnableInterrupts // If not, just enable interrupts
+
+SetDozeMode:
+ mfspr r.3, HID0 // Set Doze mode in HID0 (bit 8)
+ oris r.3, r.3, 0x0080
+ mtspr HID0, r.3
+
+ oris r.4, r.4, 0x0004 // Set POW in MSR (bit 13)
+ sync
+
+EnableInterrupts:
+ mtmsr r.4
+ isync
+
+ LEAF_EXIT(HalpProcessorIdle)
+
+
+//++
+//
+// VOID
+// HalpSetDpm (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function enables Dynamic Power Management if the CPU is PowerPC 603.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSetDpm)
+
+ mfpvr r.3 // Read PVR
+ rlwinm r.3, r.3, 16, 16, 31
+ cmpwi cr.0, r.3, 6 // Is it a 603e ?
+ cmpwi cr.1, r.3, 7 // Is it a 603ev ?
+ cmpwi cr.7, r.3, 3 // Is it a 603 ?
+ beq cr.0, EnableDpm //
+ beq cr.1, EnableDpm // If so, enable DPM
+ beq cr.7, EnableDpm //
+ ALTERNATE_EXIT(HalpSetDpm) // If not, just return
+
+EnableDpm:
+ mfspr r.3, HID0 // Load r.3 from HID0
+ oris r3, r3, 0x0010 // Set DPM bit
+ mtspr HID0, r3 // Update HID0
+ sync
+
+ LEAF_EXIT(HalpSetDpm)
+
diff --git a/private/ntos/nthals/halppc/ppc/pxproc.c b/private/ntos/nthals/halppc/ppc/pxproc.c
new file mode 100644
index 000000000..5ec201f37
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxproc.c
@@ -0,0 +1,212 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PowerPC HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+extern VOID HalpInitializePciBus (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return FALSE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If there is more than one restart block then this is a multi-
+ // processor system.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ Number = 0;
+ while (NextRestartBlock != NULL) {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Ppc, sizeof(PPC_RESTART_STATE));
+
+ //
+ // Set processor start address.
+ //
+
+ NextRestartBlock->u.Ppc.Iar = ProcessorState->ContextFrame.Iar;
+
+ //
+ // PowerPC linkage conventions pass parameters in registers
+ // r.3 thru r.10. Set all of them to allow as much flexibility
+ // to the kernel as possible.
+ //
+
+ NextRestartBlock->u.Ppc.IntR3 = ProcessorState->ContextFrame.Gpr3;
+ NextRestartBlock->u.Ppc.IntR4 = ProcessorState->ContextFrame.Gpr4;
+ NextRestartBlock->u.Ppc.IntR5 = ProcessorState->ContextFrame.Gpr5;
+ NextRestartBlock->u.Ppc.IntR6 = ProcessorState->ContextFrame.Gpr6;
+ NextRestartBlock->u.Ppc.IntR7 = ProcessorState->ContextFrame.Gpr7;
+ NextRestartBlock->u.Ppc.IntR8 = ProcessorState->ContextFrame.Gpr8;
+ NextRestartBlock->u.Ppc.IntR9 = ProcessorState->ContextFrame.Gpr9;
+ NextRestartBlock->u.Ppc.IntR10 = ProcessorState->ContextFrame.Gpr10;
+
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number++;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ interfacetype = Internal;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ interfacetype = Isa;
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+#ifdef POWER_MANAGEMENT
+ HalInitSystemPhase2();
+#endif
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxprof.c b/private/ntos/nthals/halppc/ppc/pxprof.c
new file mode 100644
index 000000000..692cc302a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxprof.c
@@ -0,0 +1,268 @@
+
+/*****************************************************************************
+
+Copyright (c) 1993 Motorola Inc.
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ PXPROF.C
+
+Abstract:
+
+ This implements the HAL profile functions:
+
+ HalSetProfileInterval
+ HalStartProfileInterrupt
+ HalStopProfileInterrupt
+ HalCalibratePerformanceCounter
+ HalpProfileInterrupt
+
+
+Author:
+
+ Steve Johns 11-Feb-1994
+
+Revision History:
+ Changed from using the DECREMENTER to 8254 Timer 1 10-Feb-94
+
+******************************************************************************/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+
+#define TIMER ((PEISA_CONTROL)HalpIoControlBase)
+#define TIMER0_COMMAND (COMMAND_8254_COUNTER0 + COMMAND_8254_RW_16BIT + COMMAND_8254_MODE2)
+
+ULONG HalpMaxProfileInterval = 540000; // 54 ms maximum
+ULONG HalpMinProfileInterval = 10000; // 1 ms minimum
+ULONG HalpProfileCount;
+BOOLEAN HalpProfilingActive = FALSE;
+ULONG HalpProfileInts = 0;
+
+
+VOID HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine unmasks IRQ0 at the master interrupt controller,
+ enabling the profile interrupt.
+
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding
+ the profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = TRUE;
+ //
+ // Unmasks IRQ 0 (Timer 1)
+ //
+ HalEnableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL, Latched);
+ }
+
+}
+
+
+
+
+
+
+ULONG HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval, rounded to the nearest 100ns units.
+
+--*/
+
+{
+ ULONG ActualInterval;
+ LARGE_INTEGER BigNumber;
+
+ //
+ // Clamp the requested profile interval between the minimum and
+ // maximum supported values.
+ //
+ if (Interval < HalpMinProfileInterval)
+ Interval = HalpMinProfileInterval;
+ else
+ if (Interval > HalpMaxProfileInterval)
+ Interval = HalpMaxProfileInterval;
+ //
+ // Compute Timer 1 counts for requested interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(Interval, TIMER_CLOCK_IN);
+
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber, 10000000, NULL);
+ HalpProfileCount = BigNumber.LowPart;
+
+ //
+ // Program Timer 1 to Mode 2 & program the timer count register.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount >> 8));
+ //
+ // Compute actual interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(HalpProfileCount, 10000000);
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber,TIMER_CLOCK_IN, NULL);
+ ActualInterval = BigNumber.LowPart;
+
+ return (ActualInterval);
+}
+
+
+
+
+BOOLEAN HalpHandleProfileInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+
+ if (HalpProfilingActive)
+ KeProfileInterrupt(TrapFrame);
+
+ return (TRUE);
+}
+
+
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine masks IRQ 0 (Timer 1) at the interrupt controller, thereby
+ stopping profile interrupts.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = FALSE;
+
+ //
+ // Program Timer 1 to Mode 2 & program the LSB of the timer.
+ // That should keep it from interrupting in case IRQ0 accidently
+ // gets enabled.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+
+
+ //
+ // Mask IRQ 0 (Timer 1)
+ //
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+ }
+
+}
+
+
+
+
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Zero the Time Base registers
+ //
+
+ HalpZeroPerformanceCounter();
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxreset.s b/private/ntos/nthals/halppc/ppc/pxreset.s
new file mode 100644
index 000000000..4c9f1259d
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxreset.s
@@ -0,0 +1,455 @@
+//++
+//
+// Copyright (c) 1993, 94, 95, 96 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxreset.s
+//
+// Abstract:
+//
+// This module implements the routine HalpPowerPcReset, which can be
+// used to return the PowerPC to Big Endian with cache flushed and
+// branches to the rom based machine reset handler.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// plj Feb 1995 Zap TLB before resetting, add 603+
+// and 604+ support.
+//
+// jlw Added eagle memory controller support
+//
+//
+//--
+
+#include "kxppc.h"
+
+ .set C_LINE_SZ, 64
+ .set C_LINE_CNT, 64
+ .set C_SETS, 8
+
+ .set C_SIZE, C_LINE_SZ * C_LINE_CNT * C_SETS
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+
+
+ .set H0_603_DCE, 0x4000 // 603 Data Cache Enable
+ .set H0_603_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set H0_603_ICFI, 0x0800 // 603 I-Cache Flash Invalidate
+
+ .set H0_604_DCE, 0x4000 // 604 Data Cache Enable
+ .set H0_604_ICE, 0x8000 // 604 Instruction Cache Enable
+ .set H0_604_DCIA, 0x0400 // 604 I-Cache Invalidate All
+ .set H0_604_ICIA, 0x0800 // 604 I-Cache Invalidate All
+
+ .set TLB_CLASSES_601, 128 // 601 tlb has 128 congruence classes
+ .set TLB_CLASSES_603, 32 // 603 tlb has 32 congruence classes
+ .set TLB_CLASSES_604, 64 // 604 tlb has 64 congruence classes
+
+ LEAF_ENTRY(HalpPowerPcReset)
+ LWI(r.4, 0xfff00100) // address of rom reset handler
+ mfspr r.5, HID0
+ mfpvr r.31 // determine processor type
+ li r.6, -1
+ mtdec r.6
+ isync
+ li r.6, 0
+ li r.7, 0x92
+ oris r.7, r.7, 0x8000
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts
+ mtmsr r.8
+
+ //
+ // invalidate all tlb entries
+ //
+
+ li r.3, TLB_CLASSES_601 // use largest known number of
+ // congruence classes
+ mtctr r.3 // number of classes = iteration count
+zaptlb: tlbie r.3 // invalidate tlb congruence class
+ addi r.3, r.3, 4096 // increment to next class address
+ bdnz zaptlb // loop through all classes
+
+ srwi r.31, r.31, 16 // isolate processor type
+ cmpwi r.31, 1 // is 601?
+
+ bl here // get current address
+here:
+ mflr r.9 // (r.9) = &here
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+ bne not_601
+
+ //
+ // processor is a 601
+ //
+
+ rlwinm r.5, r.5, 0, ~(0x0008) // turn off little endian
+
+ //
+ // disable instruction and data relocation and switch
+ // interrupt prefix to fetch from ROM
+ //
+
+ andi. r.8, r.8, ~DISABLES & 0xffff
+ ori r.8, r.8, MASK_SPR(MSR_IP,1)
+ mtsrr1 r.8 // this will also be target state
+ nop // for rfi
+
+//
+// Ensure all code from 'cachem' to 'end_little' is in cache by loading a
+// byte in each address line in that range.
+
+ addi r.9, r.9, cachem-here // (r.9) = physical &cachem
+
+ // r.9 now contains the physical address of cachem. (assuming
+ // this code was loaded as part of kernel which is loaded at
+ // physical 0 = virtual 0x80000000). We effect the switch to
+ // physical addressing thru an rfi with the target state set
+ // to resume at cachem with relocation and interrupts disabled.
+
+ mtsrr0 r.9 // address of cachem for rfi
+ addi r.10, r.9, end_little-cachem // (r.10) = &end_little
+ addi r.11, r.9, HalpPowerPcReset.end-cachem // (r.11) = &reset_end
+
+ addi r.12, r.9, -C_LINE_SZ // bias addr for 1st iteration by
+ // amount added by lbzu prior to load
+
+ rfi // switch
+cachem:
+ lbzu r.13, C_LINE_SZ(r.12) // get byte at (r.13)+C_LINE_SZ
+ cmplw r.12, r.10 // bumping r.12 by C_LINE_SZ
+ addi r.13, r.13, 1 // ensure load completed.
+ blt cachem // get all in range here-end_little.
+
+ isync
+ mtsrr0 r.4 // set rom reset target for next rfi
+ lis r.9, 0x87f0 // Segment register base 0x87f00000
+ li r.10, 0xf // Set all 16 segment registers
+
+ li r.11, 0
+ mtibatl 0, r.6 // zero bat 0-3 upper and lower
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+
+ mtibatu 3, r.6
+setsr: rlwimi r.11, r.10, 28, 0, 3 // Shift segment reg. # to bits 0-3
+ or r.12, r.9, r.10 // Segment register value 0x87f000sr
+ mtsrin r.12, r.11
+
+ addic. r.10, r.10, -1 // Next segment register
+ bne setsr
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ sync // quiet the machine down
+ sync
+ sync
+
+ sync
+ stb r.6, 0(r.7) // switch memory
+ eieio // flush io
+ sync
+
+ sync
+ sync
+ sync
+ mtspr HID0, r.5 // switch ends on the cpu
+
+ sync
+ sync
+ sync
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsr 0, r.9 // Set the last segment register
+
+ rfi // head off into the reset handler
+ rfi
+ addi r.0, r.1, 0x138 // we never get here
+ oris r.0, r.0, 0x4c // rfi (big-endian)
+end_little:
+
+ b $
+
+//
+// For the 603 (and hopefully other) processor(s) things are a little
+// easier because little-endianness is controlled by the MSR. We still
+// have to change memory seperately so we still want code from the memory
+// switch thru the cpu switch in cache.
+//
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.5 contains HID0 present value.
+// r.6 contains 0.
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the physical address of "here"
+// r.31 contains the processor type
+
+
+not_601:
+ cmpwi cr.0, r.31, 3 // is 603?
+ cmpwi cr.4, r.31, 7 // is 603ev?
+ cmpwi cr.1, r.31, 6 // is 603e?
+ cmpwi cr.2, r.31, 4 // is 604?
+ cmpwi cr.3, r.31, 9 // is 604e?
+ beq cr.0, is_603
+ beq cr.4, is_603
+ bne cr.1, not_603
+
+//
+// 603 I-Cache is invalidated by setting ICFI in HID0. Unlike
+// the 604, this bit is not self clearing.
+//
+
+is_603: rlwinm r.5, r.5, 0, ~H0_603_DCE// turn off D-cache
+ rlwinm r.10, r.5, 0, ~H0_603_ICE// turn off I-cache
+ ori r.10, r.10, H0_603_ICFI // I-Cache Flash Invalidate
+ ori r.5, r.5, H0_603_ICE // I-cache enable
+ isync
+ mtspr HID0, r.10 // invalidate/disable
+ mtspr HID0, r.5 // enable
+ b common_6034
+
+not_603:
+ beq cr.2, is_604
+// bne not_604
+
+// Note: the above branch is commented out because we don't
+// currently have any other options,... 620 will probably
+// be different.
+
+
+is_604: tlbsync // wait all processor tlb invalidate
+
+//
+// 604 caches must be enabled in order to be invalidated. It
+// is acceptable to enable and invalidate with the same move
+// to hid0. The data cache will be left disabled, the instruction
+// cache enabled.
+//
+
+ ori r.5, r.5, H0_604_DCE | H0_604_ICE
+ ori r.10, r.5, H0_604_DCIA | H0_604_ICIA
+
+ rlwinm r.5, r.5, 0, ~H0_604_DCE
+ rlwinm r.5, r.5, 0, ~H0_604_DCIA
+ rlwinm r.5, r.5, 0, ~H0_604_ICIA
+
+ mtspr HID0, r.10 // enable + invalidate
+ mtspr HID0, r.5 // disable data cache
+
+ rlwinm r.10, r.5, 0, ~H0_604_ICE // disable i-cache later
+
+// b common_6034 // join common code
+
+
+//
+// The following is common to both 603 and 604
+//
+
+common_6034:
+
+//
+// MSR bits ILE and POW must be disabled via mtmsr as rfi only moves
+// the least significant 16 bits into the MSR.
+//
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1) // -= Data Relocation
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_POW,1) // -= Power Management
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_ILE,1) // -= Interrupt Little Endian
+ sync
+ mtmsr r.8
+ isync
+
+
+//
+// Use an rfi to switch to big-endian, untranslated, interrupt prefix on
+// with a target address in the nice harmless pallindromic code below.
+// use another rfi to branch to the rom resident reset handler.
+//
+
+ li r.8, MASK_SPR(MSR_ME,1) | MASK_SPR(MSR_IP,1)
+ addi r.9, r.9, uncached_6034-here
+ mtsrr1 r.8 // state = Machine Check Enabled
+ bl here2
+here2: mflr r.28
+ rlwinm r.28, r.28, 0, 0x7fffffff // convert address to physical
+ lwz r.29, endofroutine - here2(r.28)
+ mtsrr0 r.9 // rfi to uncached_6034
+ b jumpswap
+
+memoryswap:
+ ori r.8, r.28, 0
+ addi r.8, r.8, uncached_6034-here2
+ addi r.9, 0, 0
+ li r.15, swapend - uncached_6034
+ addis r.14, 0, 0
+ addi r.14, 0, 4
+swaploop:
+ lwz r.11, 0(r.8)
+ lwz r.12, 4(r.8)
+ stwbrx r.11, r.14, r.8
+ stwbrx r.12, 0, r.8
+ addi r.8, r.8, 8
+ subi r.15, r.15, 8
+ cmpi 0, 0, r.15, 0
+ bgt swaploop
+
+jumpswap:
+
+//
+// The following bizzareness is to ensure that the memory switch thru
+// the disabling of cache is in cache. There is less than 32 bytes so
+// they must be part of either the cache line we are currently in, or
+// the one at the target of the branch. Therefore, branching over them,
+// doing a little and branching back to them should be enough to enure
+// they're cache resident.
+//
+
+ b fill_icache
+goto_bigendian:
+ sync
+ stb r.6, 0(r.7) // switch memory
+ sync
+ lwz r.30, endofroutine - here2(r.28)
+ cmp 0, 0, r.29, r.30
+ beq memoryswap
+ rfi
+fill_icache:
+ isync
+ sync // complete everything!
+ b goto_bigendian
+
+ .align 5
+
+uncached_6034:
+ .big_endian // out of cache fetches must be
+ // assembled in same mode as processor
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsrr0 r.4 // rfi target = 0xfff00100
+ mtspr HID0, r.10 // DISABLE CACHING
+
+ mtibatl 0, r.6 // invalidate/clear all bats
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+
+ mtdbatl 0, r.6
+ mtdbatu 0, r.6
+ mtdbatl 1, r.6
+ mtdbatu 1, r.6
+
+ mtdbatl 2, r.6
+ mtdbatu 2, r.6
+ mtdbatl 3, r.6
+ mtdbatu 3, r.6
+
+ mtsr 0, r.6
+ mtsr 1, r.6
+ mtsr 2, r.6
+ mtsr 3, r.6
+
+ mtsr 4, r.6
+ mtsr 5, r.6
+ mtsr 6, r.6
+ mtsr 7, r.6
+
+ mtsr 8, r.6
+ mtsr 9, r.6
+ mtsr 10, r.6
+ mtsr 11, r.6
+
+ mtsr 12, r.6
+ mtsr 13, r.6
+ mtsr 14, r.6
+ mtsr 15, r.6
+
+ rfi // go to machine reset handler
+ // never get here
+ rfi // previous rfi on a dword boundary
+ // allow for word swap
+ .little_endian
+endofroutine:
+ sync
+ .globl swapend
+ .long swapend
+swapend:
+
+ LEAF_EXIT(HalpPowerPcReset)
diff --git a/private/ntos/nthals/halppc/ppc/pxreturn.c b/private/ntos/nthals/halppc/ppc/pxreturn.c
new file mode 100644
index 000000000..a59dd8087
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxreturn.c
@@ -0,0 +1,187 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Keyboard mapping code was ported to PPC.
+ This function is currently a stub since our firmware is big endian
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "eisa.h"
+
+#if defined(VICTORY)
+
+#include "ibmppc.h"
+
+#endif
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KBD_DATA_PORT 0x60
+#define KBD_COMMAND_PORT 0x64
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT))
+
+VOID
+HalpPowerPcReset(
+ VOID
+ );
+
+#if defined(VICTORY)
+
+VOID
+HalpResetUnion(
+ VOID
+ );
+
+#endif
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ ULONG i;
+ PCI_COMMON_CONFIG PciData;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask=0xFF;
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+
+ HalpUpdateDecrementer(0x7FFFFFFF);
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Disable interrupt controller:
+ //
+
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+#if defined(SOFT_HDD_LAMP)
+ //
+ // Turn off the HDD lamp.
+ //
+
+ *((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 0;
+
+#endif
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+#if defined(VICTORY)
+
+ if ( HalpSystemType == IBM_DORAL ) {
+ //
+ // Poke the Union "Power On Reset" register.
+ // (This should never return).
+ //
+ HalpResetUnion();
+ }
+
+#endif
+
+ HalpPowerPcReset();
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxrtcsup.h b/private/ntos/nthals/halppc/ppc/pxrtcsup.h
new file mode 100644
index 000000000..c472fad77
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxrtcsup.h
@@ -0,0 +1,28 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxrtcsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+//
+// SandalFoot uses the Dallas 1585s RTC chip
+//
+
+#include "pxds1585.h"
+
diff --git a/private/ntos/nthals/halppc/ppc/pxs3.c b/private/ntos/nthals/halppc/ppc/pxs3.c
new file mode 100644
index 000000000..78b31675a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxs3.c
@@ -0,0 +1,677 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxs3.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using an S3 video adapter.
+
+Author:
+
+ Jess Botts
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "string.h"
+#include "pxvgaequ.h"
+
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+// in pxdisp.c
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the S3 display controller chip.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// Routine Description:
+//
+// This is the initialization routine for S3 86C911. This routine initializes
+// the S3 86C911 chip in the sequence of VGA BIOS for AT.
+//
+ ULONG DataLong;
+ USHORT i,j;
+ UCHAR DataByte;
+ UCHAR Index;
+// PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+
+ //
+ // IO control space has already been mapped in phase 1 via halpmapiospace
+ //
+
+ }
+
+
+
+ // Enable Video Subsystem
+ // Accordint to chapter 5.4.2 regular VGA setup sequence
+ // HalDisplayString(" Enable Video Subsystem...\n");
+
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
+
+ // HalDisplayString(" Subsystem Enable = 0x10...\n");
+ WRITE_S3_UCHAR(Setup_OP, 0x01);
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
+
+ WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ WRITE_S3_UCHAR(Seq_Data, 0x21);
+
+ //=========================================================================
+ //
+ // IBMBJB removed this section because it is not currently used, this
+ // was left commented out instead of deleting it in case we use
+ // a monochrome monitor in the future
+ //
+ // // Check monitor type to decide index address (currently not use)
+ // DataByte = READ_S3_UCHAR(MiscOutR);
+ // ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+ //
+ // if (ColorMonitor) {
+ // Index_3x4 = (PVOID)S3_3D4_Index;
+ // Data_3x5 = (PVOID)S3_3D5_Data;
+ // } else {
+ // Index_3x4 = (PVOID)Mono_3B4;
+ // Data_3x5 = (PVOID)Mono_3B5;
+ // }
+ //
+ //=========================================================================
+
+ //
+ // -- Initialization Process Begin --
+ // According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
+ // to set the default values to VGA +3 mode.
+ //
+ WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // For ATI card(0x63) we may want to change the frequence
+ WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // Sequencer Register
+ for (Index = 1; Index < 5; Index++) {
+ WRITE_S3_UCHAR(Seq_Index, Index);
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
+ }
+
+#ifdef POLO // if compiling for a Polo
+
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+
+ if((DataByte & 0xf0) == 0xc0) { // if display adaptor is an S3 864
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte |= 0x01; // use an 8 dot character clock
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+ }
+
+#endif
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+ WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte = DataByte & 0x7f;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // CRTC controller CR0 - CR18
+ for (Index = 0; Index < 25; Index++) {
+ WRITE_S3_UCHAR(S3_3D4_Index, Index);
+ WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
+ }
+
+ // attribute write
+ // program palettes and mode register
+ // HalDisplayString(" Program palettes ...\n");
+ for (Index = 0; Index < 21; Index++) {
+ WaitForVSync();
+
+ DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
+ WRITE_S3_UCHAR(Attr_Index,Index);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
+ }
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ // graphics controller
+ // HalDisplayString(" Graphics controller...\n");
+ for (Index = 0; Index < 9; Index++) {
+ WRITE_S3_UCHAR(GC_Index, Index);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
+ }
+
+ // turn off the text mode cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
+
+ // Unlock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
+
+ // Unlock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
+
+ // Disable enhanced mode
+ WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
+
+ // Turn off H/W Graphic Cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, SC5);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ //=========================================================================
+ //
+ // IBMBJB S3 errata sheet says that CR40 can not be read correctly after
+ // power up until it has been written to, suggested workaround is
+ // to use the power on default (0xA4) Since the intent of the
+ // existing code was to reset bit 0, 0xA4 will be used to reset
+ // the bit. The other bits that are reset select the desired
+ // default configuration.
+ //
+ // If this register is written by the firmware then this fix is
+ // unneccessary. If future modifications of the firmware were to
+ // remove all writes to this register then this fix would have to
+ // be added here. This is being added now to protect this code
+ // from possible firmware changes.
+ //
+ // // Disable enhanced mode registers access
+ // WRITE_S3_UCHAR(S3_3D4_Index, SC0);
+ // DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ // DataByte &= 0xfe;
+ // DataByte ^= 0x0;
+ //
+ // WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+ //
+
+ WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
+
+ //=========================================================================
+
+ // Set Misc 1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xc7;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0x80;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R2 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Set S3R4 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xec;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ //=========================================================================
+ //
+ // IBMBJB added this section to eliminate the DAC hardware cursor, this
+ // is done before setting registers 0x50 - 0x62 to default states
+ // so that R55's default state will not be undone.
+ //
+ // this sequence zeros the 2 least signifigant bits in command
+ // register 2 on the DAC
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
+ DataByte = READ_S3_UCHAR( S3_3D5_Data );
+ DataByte &= 0xfc;
+ DataByte |= 0x02;
+ WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
+
+ DataByte = READ_S3_UCHAR( DAC_Data );
+ DataByte &= 0xfc; // zero CR21,20 in DAC command
+ WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
+
+ //=========================================================================
+ //
+ // IBMBJB Added code to configure for 18 bit color mode and reload the
+ // palette registers because the firmware configures for 24 bit
+ // color. If this is done when the system driver initializes for
+ // graphics mode then the text mode colors can not be changed
+ // properly.
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
+
+ DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
+ DataByte &= 0xfd; // register 0 to select 6 bit
+ WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
+
+ // IBMBJB added write to SDAC PLL control register to make sure CLK0
+ // is correct if we have to reinitialize after graphics mode
+ // initialization, this does not bother the 928/Bt485 card
+ // because the Bt485 DAC looks very much like the SDAC
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
+ WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
+
+ for( i = 0, j = 0; i < 256; ++i ) // load all color registers
+ {
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
+ // state because some of them are set by the firmware and are
+ // not correct for our use
+ //
+ // NOTE: there are some writes to the DAC registers in code that
+ // executes later that depend on R55[1:0] being 00B, if the
+ // default state of R55 is changed make sure that these bits
+ // are not changed
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
+#ifdef SAM_256
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x40 );
+#else
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+#endif
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ // IBMBJB changed value written from 0 to 1 for an S3 864 based card to
+ // clear up bad display caused by 864->SDAC FIFO underrun
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ //=========================================================================
+ //
+ // IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
+ // transfer problem in parallel and continuous addressing modes
+ // Note: side effect of setting bit 7 was a garbled firmware screen after
+ // shutdown.
+
+ // Set SR65 bits 7 and 6
+ WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte |= 0x40;
+// DataByte |= 0xc0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Lock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Lock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+ // HalDisplayString(" Load Fonts into Plane2 ...\n");
+ WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
+
+ WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
+
+ WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data,0x00);
+
+ WRITE_S3_UCHAR(GC_Index,0x06);
+ WRITE_S3_UCHAR(GC_Data,0x04);
+
+ WRITE_S3_UCHAR(GC_Index,0x04);
+ WRITE_S3_UCHAR(GC_Data,0x02);
+
+
+ MemBase = 0xA0000;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 16; j++) {
+ WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
+ MemBase++;
+ }
+ // 32 bytes each character font
+ for (j = 16; j < 32; j++) {
+ WRITE_S3_VRAM(MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_S3_UCHAR(DAC_Mask, 0xff);
+
+ // select plane 0, 1
+ WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
+
+ // access to planes 0, 1.
+ WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x04);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x06);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
+
+ //
+ // Set screen into blue
+ //
+ // HalDisplayString(" Set Screen into Blue ...\n");
+ for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, 0x20);
+ WRITE_S3_VRAM(DataLong+1, 0x1F);
+ }
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplayPpcS3Setup() */
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ Scroll_Screen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterS3(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+ HalpOutputCharacterS3(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterS3() */
+
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < HalpDisplayWidth) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+} /* end of HalpOutputCharacterS3() */
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxs3.h b/private/ntos/nthals/halppc/ppc/pxs3.h
new file mode 100644
index 000000000..1647a0159
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxs3.h
@@ -0,0 +1,445 @@
+/*++
+
+Copyright (c) 1992 ACER Labs Inc.
+
+Module Name:
+
+ pxs3.h
+
+Abstract:
+
+ This header file defines the S3 86C911 GUI accelerator registers.
+
+Author:
+
+ Version 1.0 Kevin Chen 2-Apr-1992
+ Version 2.0 Andrew Chou Nov-24-1992
+ Version 3.0 Jess Botts Oct-06-1993 Power PC Initial Version
+
+--*/
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+extern PVOID HalpIoControlBase;
+
+//
+// Define S3 register I/O Macros
+//
+
+//=============================================================================
+//
+// IBMBJB Changed the semicolons separating statements in the write macros to
+// commas so that if the macro is used as the only statement in a loop
+// all of the statements in the macro will be part of the loop.
+//
+// Commas were used instead of putting braces around the statements
+// because if the macro is used in the true part of a conditional the
+// braces will cause the compiler to generate a syntax error.
+
+#define WRITE_S3_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_S3_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_S3_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_S3_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//=============================================================================
+
+#define DISPLAY_BITS_PER_PIXEL 8 // display bits per pixel
+#define NUMBER_OF_COLORS 256 // number of colors
+
+#define CURSOR_WIDTH 64 // width of hardware cursor
+#define CURSOR_HEIGHT 64 // height of hardware cursor
+#define CURSOR_BITS_PER_PIXEL 2 // hardware cursor bits per pixel
+
+//
+// S3 86C911 GUI, accelerator Video Controller Definitions.
+//
+// Define video register format.
+//
+#define PosID_LO 0x100 // R/W
+#define PosID_HI 0x101 // R/W
+#define Setup_OP 0x102 // R/W
+#define Chck_Ind 0x105 // R
+#define Mono_3B4 0x3B4 // R/W
+#define Mono_3B5 0x3B5 // R/W
+#define MDA_Mode 0x3B8 // W
+#define HGC_SLPEN 0x3B9 // R/W
+#define Stat1_MonoIn 0x3BA // R
+#define FC_MonoW 0x3BA // W
+#define HGC_CLPEN 0x3BB // W
+#define HGC_Config 0x3BF // W
+#define Attr_Index 0x3C0 // R/W
+#define Attr_Data 0x3C0 // R/W
+#define Stat0_In 0x3C2 // R
+#define MiscOutW 0x3C2 // W
+#define VSub_EnB 0x3C3 // R/W
+#define Seq_Index 0x3C4 // R/W
+#define Seq_Data 0x3C5 // R/W
+#define DAC_Mask 0x3C6 // R/W
+#define DAC_RIndex 0x3C7 // W
+#define DAC_Status 0x3C7 // W
+#define DAC_WIndex 0x3C8 // R/W
+#define DAC_Data 0x3C9 // R/W
+#define FC_Read 0x3CA // R
+#define MiscOutR 0x3CC // R
+#define GC_Index 0x3CE // R/W
+#define GC_Data 0x3CF // R/W
+#define S3_3D4_Index 0x3D4 // R/W
+#define S3_3D5_Data 0x3D5 // R/W
+
+#define CGA_Mode 0x3D8 // W
+#define CGA_Color 0x3D9 // W
+#define Stat1_In 0x3DA // R
+#define FC_Write 0x3DA // W
+#define CLPEN 0x3DB
+#define SLPEN 0x3DC
+
+//
+// Define Enhanced registers for S3_86C911
+//
+
+#define SUBSYS_STAT 0x42E8 // R
+#define SUBSYS_CNTL 0x42E8 // W
+#define SUBSYS_ENB 0x46E8 // R/W
+#define ADVFUNC_CNTL 0x4AE8 // W
+#define CUR_Y 0x82E8 // R/W
+#define CUR_X 0x86E8 // R/W
+#define DESTY 0x8AE8 // W
+#define AXIAL_STEP 0x8AE8 // W
+#define DESTX 0x8EE8 // W
+#define DIAG_STEP 0x8EE8 // W
+#define ERR_TERM 0x92E8 // R
+#define MAJ_AXIS_PCNT 0x96E8 // W
+#define RWIDTH 0x96E8 // W
+#define GP_STAT 0x9AE8 // R
+#define DRAW_CMD 0x9AE8 // W
+#define SHORT_STROKE 0x9EE8 // W
+#define BKGD_COLOR 0xA2E8 // W
+#define FRGD_COLOR 0xA6E8 // W
+#define WRITE_MASK 0xAAE8 // W
+#define READ_MASK 0xAEE8 // W
+#define BKGD_MIX 0xB6E8 // W
+#define FRGD_MIX 0xBAE8 // W
+#define MULTIFUNC_CNTL 0xBEE8 // W
+#define RHEIGHT 0xBEE8 // W
+#define PIX_TRANS 0xE2E8 // W
+
+
+//
+// Define Attribute Controller Indexes : ( out 3C0, Index )
+//
+
+#define PALETTE0 0
+#define PALETTE1 1
+#define PALETTE2 2
+#define PALETTE3 3
+#define PALETTE4 4
+#define PALETTE5 5
+#define PALETTE6 6
+#define PALETTE7 7
+#define PALETTE8 8
+#define PALETTE9 9
+#define PALETTE10 10
+#define PALETTE11 11
+#define PALETTE12 12
+#define PALETTE13 13
+#define PALETTE14 14
+#define PALETTE15 15
+#define ATTR_MODE_CTRL 16
+#define BORDER_COLOR 17
+#define COLOR_PLANE_ENABLE 18
+#define HORI_PIXEL_PANNING 19
+#define PIXEL_PADDING 20
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Define Graphics Controller Index ( out 3CE, Index )
+//
+
+#define SET_RESET 0
+#define ENABLE_SET_RESET 1
+#define COLOR_COMPARE 2
+#define DATA_ROTATE 3
+#define READ_PLANE_SELECT 4
+#define GRAPHICS_CTRL_MODE 5
+#define MEMORY_MAP_MODE 6
+#define COLOR_DONT_CARE 7
+#define BIT_MASK 8
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA S3 Indexes
+//
+#define S3R0 0x30
+#define S3R1 0x31
+#define S3R2 0x32
+#define S3R3 0x33
+#define S3R4 0x34
+#define S3R5 0x35
+#define S3R6 0x36
+#define S3R7 0x37
+#define S3R8 0x38
+#define S3R9 0x39
+#define S3R0A 0x3A
+#define S3R0B 0x3B
+#define S3R0C 0x3C
+#define SC0 0x40
+#define SC2 0x42
+#define SC3 0x43
+#define SC5 0x45
+
+//
+// Define System Control Indexes
+//
+#define SYS_CNFG 64
+#define SOFT_STATUS 65
+#define MODE_CTRL 66
+#define EXT_MODE 67
+#define HGC_MODE 69
+#define HGC_ORGX0 70
+#define HGC_ORGX1 71
+#define HGC_ORGY0 72
+#define HGC_ORGY1 73
+#define HGC_YSTART0 76
+#define HGC_YSTART1 77
+#define HGC_DISPX 78
+#define HGC_DISPY 79
+
+#define ENABLE_HARDWARE_CURSOR 1
+#define DISABLE_HARDWARE_CURSOR 0
+
+//
+// define advanced function control register structure
+//
+#define RES_640x480 0
+#define RES_1024x768 1
+#define RES_800x600 1
+
+#define ENABLE_VGA 6
+#define ENABLE_ENHANCED 7
+
+//
+// define draw command register values
+//
+#define NOP_COMMAND 0x0
+#define DRAW_LINE_COMMAND 0x2000
+#define RECTANGLE_FILL_COMMAND 0x4000
+#define BITBLT_COMMAND 0xc000
+#define BYTE_SWAP 0x1000
+#define NO_BYTE_SWAP 0x0
+#define SIXTEEN_BIT_BUS 0x0200
+#define EIGHT_BIT_BUS 0x0
+#define WAIT 0x0100
+#define NO_WAIT 0x0
+#define R0 0x0
+#define R45 0x20
+#define R90 0x40
+#define R135 0x60
+#define R180 0x80
+#define R225 0xa0
+#define R270 0xc0
+#define R315 0xe0
+#define XMAJ 0x0
+#define YMAJ 0x40
+#define XPositive 0x20
+#define YPositive 0x80
+#define XNegative 0x0
+#define YNegative 0x0
+
+#define DRAW_YES 0x10
+#define DRAW_NO 0x0
+#define RADIAL 8
+#define XY_BASE 0
+#define LAST_PIXEL_OFF 4
+#define LAST_PIXEL_ON 0
+#define MULTIPLE_PIXEL 2
+#define SINGLE_PIXEL 0
+#define DRAW_READ 0
+#define DRAW_WRITE 1
+
+#define SSV_DRAW 0x1000
+#define SSV_MOVE 0x0
+
+#define OneEmpty 0x80
+#define TwoEmpty 0x40
+#define ThreeEmpty 0x20
+#define FourEmpty 0x10
+#define FiveEmpty 0x8
+#define SixEmpty 0x4
+#define SevenEmpty 0x2
+#define EightEmpty 0x1
+
+#define BACKGROUND_COLOR 0
+#define FOREGROUND_COLOR 0x20
+#define CPU_DATA 0x40
+#define DISPLAY_MEMORTY 0x60
+#define NOT_SCREEN 0
+#define LOGICAL_ZERO 1
+#define LOGICAL_ONE 2
+#define LEAVE_ALONE 3
+#define NOT_NEW 4
+#define SCREEN_XOR_NEW 5
+#define NOT_SCREEN_XOR_NEW 6
+#define OVERPAINT 7 //( NEW )
+#define NOT_SCREEN_OR_NOT_NEW 8
+#define SCREEN_OR_NOT_NEW 9
+#define NOT_SCREEN_OR_NEW 10
+#define SCREEN_OR_NEW 11
+#define SCREEN_AND_NEW 12
+#define NOT_SCREEN_AND_NEW 13
+#define SCREEN_AND_NOT_NEW 14
+#define NOT_SCREEN_AND_NOT_NEW 15
+
+#define BEE8_1H 1
+#define BEE8_2H 2
+#define BEE8_3H 3
+#define BEE8_4H 4
+#define BEE8_0H 0
+#define L_CLIP 0x1000
+#define R_CLIP 0x2000
+#define B_CLIP 0x3000
+#define T_CLIP 0x4000
+
+#define DATA_EXTENSION 0xa000 // 10100000B
+#define CPU_EXT 0x80
+#define DISPLAY_EXT 0xc0
+#define NO_EXTENSION 0x0
+#define PACK_DATA 0x4
+#define NO_PACK_DATA 0x0
+#define SET_THIS_BIT_TO_ZERO 0;
+
+//
+// Define bits per pixel codes.
+//
+#define ONE_BIT_PER_PIXEL 0 // 1-bit per pixel
+#define TWO_BITS_PER_PIXEL 1 // 2-bits per pixel
+#define FOUR_BITS_PER_PIXEL 2 // 4-bits per pixel
+#define EIGHT_BITS_PER_PIXEL 3 // 8-bits per pixel
+
+//
+// Define address step value.
+//
+#define ADDRESS_STEP_INCREMENT 1 // vram transfer address increment
+
+//
+// Define cross hair thickness values.
+//
+#define ONE_PIXEL_THICK 0x0 // one pixel in thickness
+#define THREE_PIXELS_THICK 0x1 // three pixels in thickness
+#define FIVE_PIXELS_THICK 0x2 // five pixels in thickness
+#define SEVEN_PIXELS_THICK 0x3 // seven pixels in thickness
+
+//
+// Define multiplexer control values.
+//
+#define ONE_TO_ONE 0x0 // 1:1 multiplexing
+#define FOUR_TO_ONE 0x1 // 4:1 multiplexing
+#define FIVE_TO_ONE 0x2 // 5:1 multiplexing
+
+//
+// Define cursor origin values.
+//
+
+#define CURSOR_X_ORIGIN (((2*HORIZONAL_SYNC_VALUE)+BACK_PORCH_VALUE)*4-36)
+#define CURSOR_Y_ORIGIN ((VERTICAL_BLANK_VALUE/2)+24)
+
+ULONG HotspotX, HotspotY;
+
+// Extended VGA BIOS
+#define SUPER_VGA_SUPPORT 4FH
+#define RET_EXT_VGA_INFO 00H
+#define RET_EXT_VGA_MODE_INFO 01H
+#define SET_EXT_VGA_MODE 02H
+#define QUERY_CUR_EXT_VGA_MODE 03H
+
+#define SAVE_RESTORE_FUNCTION 04H
+// Function 04.0 Query Save/Restore Buffer Size
+#define GET_SAVE_BUFFER_SIZE 00H
+// Function 04.1 Save Extended Video state
+#define SAVE_STATE 01H
+// Function 04.2 Restore Extended VGA state
+#define RESTORE_STATE 02H
+
+#define WINDOWS_CONTROL 05H
+// Function 05.0 Set Window Control
+#define SELECT_PAGE_TO_BE_MAPPED 00H
+// fUNCTION 05.1 Get Window Control Setting
+#define GET_PAGE_MAPPED 01H
+
+#define SET_RESET_DUAL_DISPLAY_MODE FFH
+
+BOOLEAN ColorMonitor;
+PVOID S3_3x4, S3_3x5;
+
diff --git a/private/ntos/nthals/halppc/ppc/pxshadbf.s b/private/ntos/nthals/halppc/ppc/pxshadbf.s
new file mode 100644
index 000000000..ec215c2e9
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxshadbf.s
@@ -0,0 +1,37 @@
+//++
+//
+// Copyright (c) 1993, 1994, 1995 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxshadbf.s
+//
+// Abstract:
+//
+// This file creates a 64K buffer that will be thrown away
+// at the end of init time. It is to be used for video
+// bios shadowing.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) July 1995
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+ .new_section INIT,"rcxw"
+ .section INIT,"rcxw"
+
+ .globl HalpShadowBufferPhase0
+HalpShadowBufferPhase0:
+ .space 128*1024
+
diff --git a/private/ntos/nthals/halppc/ppc/pxsiosup.c b/private/ntos/nthals/halppc/ppc/pxsiosup.c
new file mode 100644
index 000000000..64c20c2e6
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsiosup.c
@@ -0,0 +1,2218 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxsiosup.c
+
+Abstract:
+
+ The module provides the PCI ISA bridge support.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include <pxmemctl.h>
+#include "bugcodes.h"
+
+extern UCHAR VectorToIrqlTable[];
+
+#define SioId 0x04848086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPhase0GetPciDataByOffset();
+extern ULONG HalpPhase0SetPciDataByOffset();
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+//
+// Declare the interupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+
+//
+// Define Isa bus interrupt affinity.
+//
+
+KAFFINITY HalpIsaBusAffinity;
+
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern USHORT Halp8259MaskTable[];
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+#if defined(SOFT_HDD_LAMP)
+
+//
+// On PowerPC machines the HDD lamp is software driven. We
+// turn it on any time we take an interrupt from a Mass Storage
+// Controller (assuming it isn't already on) and turn it off the 2nd
+// clock tick after we turn it on if we have not received
+// any more MSC interrupts since the first clock tick.
+//
+
+HDD_LAMP_STATUS HalpHddLamp;
+
+ULONG HalpMassStorageControllerVectors;
+
+#endif
+
+#ifdef POWER_MANAGEMENT
+//
+// Define save area for DMA channel extended mode.
+//
+
+DMA_EXTENDED_MODE Dma1ExtendedMode[4];
+DMA_EXTENDED_MODE Dma2ExtendedMode[4];
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGELK, HalpInitInterruptController)
+#pragma alloc_text(PAGELK, HalpInitDmaController)
+#endif // ALLOC_PRAGMA
+
+#endif // POWER_MANAGEMENT
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG Vector;
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt;
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber;
+ ULONG ChipId;
+ ULONG BufferLength;
+
+
+ Found = FALSE;
+ SlotNumber = 0;
+
+ while (!Found && SlotNumber < HalpPciMaxSlots) {
+
+ BufferLength = HalpPhase0GetPciDataByOffset(0,
+ SlotNumber,
+ &ChipId,
+ 0,
+ sizeof(ChipId));
+ if (ChipId == SioId)
+ Found = TRUE;
+ else
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found)
+ return FALSE;
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0GetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0SetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+
+ DataByte |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+
+ WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+
+ //
+ // Disable Gauranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo())
+
+ return FALSE;
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine in entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ UCHAR Irql;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask;
+
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (interruptVector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+#if DBG
+ HalpSpuriousInterruptCount++;
+#endif
+ return(0);
+
+ }
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( HalpMassStorageControllerVectors & (1 << interruptVector) ) {
+ //
+ // On any Mass Storage Controller interrupt, light the HDD lamp.
+ // The system timer routines will turn it off again in a little
+ // while.
+ //
+
+ if ( !HalpHddLamp.Count ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1;
+ }
+ HalpHddLamp.Count = SOFT_HDD_TICK_COUNT;
+ }
+
+#endif
+
+ //
+ // raise irql
+ //
+
+ Irql = VectorToIrqlTable[interruptVector];
+
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = Irql;
+
+ HalpEnableInterrupts();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers. We disable
+ // interrupts first so we won't get multiple interrupts at this level
+ // without popping the stack.
+ //
+
+ HalpDisableInterrupts();
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Lower IRQL but leave external interrupts disabled.
+ // Return to caller with interrupts disabled.
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ //
+ // Partial lazy irql - if hardware irql mask isn't what is should be
+ // set it and the interrupt controllers mask.
+ //
+
+ if (HALPCR->HardPriority != PCR->CurrentIrql) {
+
+ HALPCR->HardPriority = OldIrql;
+
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[OldIrql] & 0x00FF);
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get contoller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[OldIrql] >> 8 );
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ }
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+#ifdef POWER_MANAGEMENT
+ PDMA_EXTENDED_MODE pointerExtendedMode;
+#endif // POWER_MANAGEMENT
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+#ifdef POWER_MANAGEMENT
+ pointerExtendedMode = Dma1ExtendedMode;
+#endif // POWER_MANAGEMENT
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+#ifdef POWER_MANAGEMENT
+ pointerExtendedMode = Dma2ExtendedMode;
+#endif // POWER_MANAGEMENT
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+#ifdef POWER_MANAGEMENT
+ *(pointerExtendedMode + channelNumber) = extendedMode;
+#endif // POWER_MANAGEMENT
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
+
+#ifdef POWER_MANAGEMENT
+
+VOID
+HalpInitInterruptController (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine re-initializes the SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Disable all of the interrupts
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ 0xFF
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ 0xFF
+ );
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // Re-enable the interrupts
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ return;
+}
+
+
+VOID
+HalpInitDmaController (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine re-initializes the SIO DMA controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+ ULONG channelNumber;
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ //
+ // Initialize the extended mode port.
+ //
+
+ for(channelNumber = 0; channelNumber < 4; channelNumber++)
+ {
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort,
+ *((PUCHAR) (Dma1ExtendedMode + channelNumber))
+ );
+ } /* endfor */
+
+ for(channelNumber = 1; channelNumber < 4; channelNumber++)
+ {
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort,
+ *((PUCHAR) (Dma2ExtendedMode + channelNumber))
+ );
+ } /* endfor */
+
+ return;
+}
+#endif // POWER_MANAGEMENT
diff --git a/private/ntos/nthals/halppc/ppc/pxsiosup.h b/private/ntos/nthals/halppc/ppc/pxsiosup.h
new file mode 100644
index 000000000..2b91be331
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsiosup.h
@@ -0,0 +1,219 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x28]; // Offset 0x58
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+// The default Interrupt interval is Interval = 15ms.
+
+
+#define TIME_INCREMENT 150000 // 15ms.
+#define ROLLOVER_COUNT 15 * 1193
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/halppc/ppc/pxstall.s b/private/ntos/nthals/halppc/ppc/pxstall.s
new file mode 100644
index 000000000..501e2016e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxstall.s
@@ -0,0 +1,324 @@
+//#***********************************************************************
+//
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Copyright 1993 International Buisness Machines Corporation.
+// All Rights Reserved.
+//
+// This file contains copyrighted material. Use of this file is
+// restricted by the provisions of a Motorola/IBM Joint Software
+// License Agreement.
+//
+// File Name:
+// PXSTALL.S
+//
+// Functions:
+// KeStallExecutionProcessor
+// HalpCalibrateStall
+//
+// History:
+// 21-Sep-1993 Steve Johns
+// Original Version
+// 24-Dec-1993 Peter Johnston
+// Adapted to 601 HAL in an attempt to avoid having different
+// versions if at all possible. Original was designed for both
+// 601 and 603 but had some 601 difficulties.
+// 17-Jan-1994 Steve Johns
+// Changed to treat 601 vs PowerPC time base differences more
+// transparently.
+//
+//#***********************************************************************
+
+
+
+#include "kxppc.h"
+
+#define ERRATA603 TRUE
+#define RTCU 4
+#define RTCL 5
+#define CMOS_INDEX 0x70
+#define CMOS_DATA 0x71
+#define RTC_SECOND 0x80
+
+
+ .extern HalpPerformanceFrequency
+ .extern HalpIoControlBase
+
+
+//
+// Register Definitions
+//
+ .set Microsecs, r.3
+ .set TimerLo , r.4 // MUST be same as defined in PXCLKSUP.S
+ .set TimerHi , r.5 // MUST be same as defined in PXCLKSUP.S
+ .set EndTimerLo, r.6
+ .set EndTimerHi, r.7
+ .set Temp , r.8
+ .set Temp2 , r.9
+ .set IO_Base , r.10
+
+//#***********************************************************************
+//
+// Synopsis:
+// VOID KeStallExecutionProcessor(
+// ULONG Microseconds)
+//
+// Purpose:
+// This function stalls the execution at least the specified number
+// of microseconds, but not substantially longer.
+//
+// Returns:
+// Nothing.
+//
+// Global Variables Referenced:
+// HalpPerformanceFrequency
+//#***********************************************************************
+
+ SPECIAL_ENTRY(KeStallExecutionProcessor)
+ mflr r.0 // Save Link Register
+ PROLOGUE_END(KeStallExecutionProcessor)
+
+ cmpli 0,0,Microsecs,0 // if (Microseconds == 0)
+ beqlr- // return;
+
+ bl ..HalpGetTimerRoutine // Get appropriate timer routine
+//
+// Read START time
+//
+ bctrl // ReadPerformanceCounter();
+
+//
+// Get PerformanceCounter frequency
+//
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp)
+//
+// Compute: (Microseconds * PerformanceFrequency) / 1,000,000
+//
+ mullw EndTimerLo,Microsecs,Temp
+ mulhwu. EndTimerHi,Microsecs,Temp
+ bne Shift20Bits
+
+ lis Temp,(1000000 >> 16) // Divide by 1,000,000
+ ori Temp,Temp,(1000000 & 0xFFFF)
+ divwu EndTimerLo,EndTimerLo,Temp
+ b Add64Bits
+
+//
+// The 32 MSBs are non-zero.
+// Instead of performing a 64-bit division, we shift right by 20
+// bits (equivalent to dividing by 1,048576). Then we add back in 1/16th
+// of the shifted amount. The accuracy achieved by this method is:
+//
+// 1,000,000
+// --------- * 1.0625 = 101.3 % of desired value.
+// 1,048,576
+//
+Shift20Bits:
+ mr Temp,EndTimerHi
+ rlwinm EndTimerLo,EndTimerLo,32-20,20,31
+ rlwinm EndTimerHi,EndTimerHi,32-20,20,31
+ rlwimi EndTimerLo,Temp,32-20,0,19
+
+ rlwinm Temp2,EndTimerLo,32-4,4,31
+ rlwinm Temp,EndTimerHi,32-4,4,31
+ rlwimi Temp2,EndTimerHi,32-4,0,3
+ addc EndTimerLo,EndTimerLo,Temp2
+ adde EndTimerHi,EndTimerHi,Temp
+
+//
+// Compute EndTimer
+//
+Add64Bits:
+ addc EndTimerLo,EndTimerLo,TimerLo
+ adde EndTimerHi,EndTimerHi,TimerHi
+//
+// while (ReadPerformanceCounter() < EndTimer);
+//
+StallLoop:
+ bctrl // ReadPerformanceCounter();
+ cmpl 0,0,TimerHi,EndTimerHi // Is TimerHi >= EndTimerHi ?
+ blt- StallLoop // No
+ bgt+ StallExit // Yes
+ cmpl 0,0,TimerLo,EndTimerLo // Is TimerLo >= EndTimerLo ?
+ blt StallLoop // Branch if not
+
+StallExit:
+ mtlr r.0 // Restore Link Register
+
+ SPECIAL_EXIT(KeStallExecutionProcessor)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for the 601 processor.
+// The 601 RTC counts discontinuously (1 is added to RTCU when the value in
+// RTCL passes 999,999,999). This routine converts the RTC count to a
+// continuous 64-bit count by calculating:
+//
+// ((RTC.HighPart * 1,000,000,000) + RTC.LowPart) / 128
+//
+//
+ LEAF_ENTRY (ReadRTC)
+
+ mfspr TimerHi,RTCU // Read the RTC registers coherently
+ mfspr TimerLo,RTCL
+ mfspr Temp,RTCU
+ cmpl 0,0,TimerHi,Temp
+ bne- ..ReadRTC
+
+ lis Temp,(1000000000 >> 16) // RTC.HighPart * 1,000,000
+ ori Temp,Temp,(1000000000 & 0xFFFF)
+ mullw Temp2,Temp,TimerHi
+ mulhwu Temp,Temp,TimerHi
+ addc TimerLo,Temp2,TimerLo // + RTC.LowPart
+ addze TimerHi,Temp
+//
+// Each tick increments the RTC by 128, so let's divide that out.
+//
+ mr Temp,TimerHi // Divide 64-bit value by 128
+ rlwinm TimerLo,TimerLo,32-7,7,31
+ rlwinm TimerHi,TimerHi,32-7,7,31
+ rlwimi TimerLo,Temp,32-7,0,6
+
+ LEAF_EXIT (ReadRTC)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for PowerPC
+// architectures (not the 601).
+//
+ LEAF_ENTRY (ReadTB)
+
+ mftbu TimerHi // Read the TB registers coherently
+ mftb TimerLo
+#if ERRATA603
+ mftb TimerLo
+ mftb TimerLo
+ mftb TimerLo
+#endif
+ mftbu Temp
+ cmpl 0,0,Temp,TimerHi
+ bne- ..ReadTB
+
+ LEAF_EXIT (ReadTB)
+
+
+//
+// Returns in the Count Register the entry point for the routine
+// that reads the appropriate Performance Counter (ReadRTC or ReadTB).
+//
+// Called from KeQueryPerformanceCounter and KeStallExecutionProcessor
+//
+ LEAF_ENTRY (HalpGetTimerRoutine)
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // Are we running on an MPC601 ?
+ lwz Temp,[toc]ReadTB(r.toc)
+ bne+ GetEntryPoint // Branch if not
+
+ lwz Temp,[toc]ReadRTC(r.toc)
+
+GetEntryPoint:
+ lwz Temp,0(Temp) // Get addr to ReadRTC or ReadTB
+ mtctr Temp
+
+ LEAF_EXIT (HalpGetTimerRoutine)
+
+
+
+
+
+//
+// Returns the number of performance counter ticks/second.
+//
+// The DECREMENTER is clocked at the same rate as the PowerPC Time Base (TB)
+// and the POWER RTC. The POWER RTC is supposed to be clocked at 7.8125 MHz,
+// but on early prototypes of the Sandalfoot platform, this is not true).
+// In either case, to keep the calibration routine simple and generic, we
+// will determine the DECREMENTER clock rate by counting ticks for exactly
+// 1 second (as measured against the CMOS RealTimeClock). We then use that
+// value in the KeStallExecutionProcessor() and KeQueryPerformanceCounter()
+//
+ LEAF_ENTRY(HalpCalibrateTB)
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+WaitOnUIP1:
+ li r.6,0x0A // check and wait on busy flag
+ stb r.6,CMOS_INDEX(IO_Base)
+ sync
+ lbz r.7,CMOS_DATA(IO_Base) // Read CMOS data
+ andi. r.7, r.7, 0x0080
+ bgt WaitOnUIP1
+
+
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ sync
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+
+
+
+WaitForTick1:
+ li r.6,0x0A // check and wait on busy flag
+ stb r.6,CMOS_INDEX(IO_Base)
+ sync
+ lbz r.7,CMOS_DATA(IO_Base) // Read CMOS data
+ andi. r.7, r.7, 0x0080
+ bgt WaitForTick1
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ sync
+ lbz r.3,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2:
+ li r.6,0x0A // check and wait on busy flag
+ stb r.6,CMOS_INDEX(IO_Base)
+ sync
+ lbz r.7,CMOS_DATA(IO_Base) // Read CMOS data
+ andi. r.7, r.7, 0x0080
+ bgt WaitForTick2
+ li r.4,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,CMOS_INDEX(IO_Base) // Write CMOS index
+ sync
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // if (CPU != 601)
+ bnelr // return(r.3);
+//
+// On the 601, the DECREMENTER decrements every ns, so the 7 LSBs are
+// not implemented.
+//
+ rlwinm r.3,r.3,32-7,7,31 // Divide count by 128
+
+
+ LEAF_EXIT(HalpCalibrateTB)
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxsysbus.c b/private/ntos/nthals/halppc/ppc/pxsysbus.c
new file mode 100644
index 000000000..8787ee2cd
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsysbus.c
@@ -0,0 +1,111 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - ported to PowerPC
+
+
+--*/
+
+#include "halp.h"
+
+#include "eisa.h"
+#include "pxmemctl.h"
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxsysint.c b/private/ntos/nthals/halppc/ppc/pxsysint.c
new file mode 100644
index 000000000..2eede0663
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsysint.c
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrupt.
+ //
+
+ if (Vector >= DEVICE_VECTORS &&
+ Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= DEVICE_VECTORS &&
+ Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+
+ //
+ // get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector, Irql, InterruptMode);
+
+
+ HalpEnableSioInterrupt( Vector, TranslatedInterruptMode);
+ // HalpEnableSioInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxtime.c b/private/ntos/nthals/halppc/ppc/pxtime.c
new file mode 100644
index 000000000..fad088f59
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxtime.c
@@ -0,0 +1,386 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Change real time clock mapping to port 71.
+ Code assumes the DS1385S chip is compatible with existing
+ PC/AT type RTC's. The only known exception to PC/AT
+ compatibility on S-FOOT is the use of ports 810 and 812.
+ These ports provide password security for the RTC's NVRAM,
+ and are currently unused in this port since this address space
+ is available from kernel mode only in NT.
+
+ Steve Johns (sjohns@pets.sps.mot.com)
+ Changed to support years > 1999
+
+--*/
+
+#include "halp.h"
+#include "pxrtcsup.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if (TimeFields->Year > 1999)
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ else
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData);
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+ can be configured to do this,... but as a quick fix I am doing it
+ here. (plj)
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+
+ BcdValue = HalpReadRawClockRegister(Register);
+ return (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
+}
+
+VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the SIO NMI is always enabled.
+ //
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData, Value);
+ return;
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+ BcdValue = ((Value / 10) << 4) | (Value % 10);
+ HalpWriteRawClockRegister(Register, BcdValue);
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxusage.c b/private/ntos/nthals/halppc/ppc/pxusage.c
new file mode 100644
index 000000000..ce4bae32e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxusage.c
@@ -0,0 +1,499 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+
+ KeInitializeInterrupt( Interrupt,
+ ServiceRoutine,
+ ServiceContext,
+ SpinLock,
+ Vector,
+ Irql,
+ SynchronizeIrql,
+ InterruptMode,
+ ShareVector,
+ ProcessorNumber,
+ FloatingSave
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ if (!KeConnectInterrupt( Interrupt )) {
+
+ return(FALSE);
+ }
+
+ HalpRegisterVector (ReportFlags, BusVector, Vector, Irql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ return(TRUE);
+
+
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+
+ for(i=0; i < DEVICE_VECTORS; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxvgaequ.h b/private/ntos/nthals/halppc/ppc/pxvgaequ.h
new file mode 100644
index 000000000..b8dfc9f14
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxvgaequ.h
@@ -0,0 +1,141 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ This file contains all the VGA-specific definitions. This
+ is meant to be included by all modules that implement
+ VGA support in the HAL. At this time, that includes pxs3.c
+ and pxwd.c. It does not include pxp91.c or pxbbl.c because
+ these video devices don't map VGA registers.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+
+
+//VGA definitions
+
+extern UCHAR DAC_Table[];
+extern UCHAR DAC_Color[];
+extern UCHAR VideoParam[];
+extern UCHAR VGAFont8x16[];
+extern UCHAR TextPalette[];
+
+#define TAB_SIZE 4
+
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA I/O address
+//
+#define PORT_GEN_MISC_RD 0x03cc // GEN - MISC (Read port)
+#define PORT_GEN_MISC_WR 0x03c2 // (Write port)
+#define PORT_GEN_ISR0 0x03c2 // GEN - ISR0
+#define PORT_GEN_ISR1_M 0x03ba // GEN - ISR1 (for Mono)
+#define PORT_GEN_ISR1_C 0x03da // (for Color)
+#define PORT_GEN_FEATURE_RD 0x03ca // GEN - FEARTURE (Read port for both)
+#define PORT_GEN_FEATURE_WR_M 0x03ba // (Write port for Mono)
+#define PORT_GEN_FEATURE_WR_C 0x03da // (Write port for Color)
+
+#define PORT_SEQ_INDEX 0x03c4 // SEQ - INDEX
+#define PORT_SEQ_DATA 0x03c5 // SEQ - DATA
+
+#define PORT_CRTC_INDEX_M 0x03b4 // CRTC - INDEX (for Mono)
+#define PORT_CRTC_INDEX_C 0x03d4 // (for Color)
+#define PORT_CRTC_DATA_M 0x03b5 // CRTC - DATA (for Mono)
+#define PORT_CRTC_DATA_C 0x03d5 // (for Color)
+
+#define PORT_GCR_INDEX 0x03ce // GCR - INDEX
+#define PORT_GCR_DATA 0x03cf // GCR - DATA
+
+#define PORT_ATTR_INDEX 0x03c0 // ATTR - INDEX
+#define PORT_ATTR_DATA_RD 0x03c1 // ATTR - DATA (Read port)
+#define PORT_ATTR_DATA_WR 0x03c0 // (Write port)
+
+#define PORT_DAC_PIX_MASK 0x03c6 //
+#define PORT_DAC_STATE 0x03c7 //
+#define PORT_DAC_READ_PIX_ADDR 0x03c7 // (Write only port) - take care !
+#define PORT_DAC_WRITE_PIX_ADDR 0x03c8 // (Read/Write port)
+#define PORT_DAC_DATA 0x03c9 // DAC - DATA port
+
+#define PORT_SYS_VGA_ENABLE 0x03c3 // SYS - VGA Enable/Disable
+#define PORT_SYS_VIDEO_SUBSYSTEM 0x46e8 // SYS - Video Subsystem Enable/Disable
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Misc. registers
+//
+#define Setup_OP 0x102 // R/W
+
diff --git a/private/ntos/nthals/halppc/ppc/pxvm.c b/private/ntos/nthals/halppc/ppc/pxvm.c
new file mode 100644
index 000000000..b93dace23
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxvm.c
@@ -0,0 +1,297 @@
+/*++
+TITLE("Map Virtual Memory")
+
+
+Copyright (c) 1995 IBM Corporation, Microsoft Corporation.
+
+Module Name:
+
+ pxmapvm.c
+
+abstract:
+
+ This module implements a mechanism to allow the HAL to allocate
+ Virtual Addresses for physical storage (usually I/O space) within
+ the range of memory that is reserved for the HAL.
+
+ This mechanism should only be used for mappings that are required
+ prior to the availability of MmMapIoSpace during system initialization.
+
+ The theory is that the top 4MB of virtual address space are reserved
+ for the HAL. The theory is slightly blemished in that
+
+ (1) three pages of this space are in use by the system, specifically
+ 0xfffff000 Debugger
+ 0xffffe000 Pcr Page 2
+ 0xffffd000 Pcr.
+ (2) To provide unique Pcrs for each processor in the system, segment
+ f has a unique VSID on each processor. This results in there
+ being one entry per processor for any page in segment f.
+
+ The reason the two pcr pages are in the upper 32K of the address
+ space is so they can be accessed in one instruction. This is
+ true for any address in the range 0xffff8000 thru 0xffffffff
+ because the address is sign-extended from the 16 bit D field of
+ the instruction.
+
+ In the interests of maintaing good kernel relations, this module
+ will not allocate from within the uppr 32KB of memory.
+
+ The expected usage of these routines if VERY INFREQUENT and the
+ allocation routines have not been coded for efficiency.
+
+ WARNING: These routines CANNOT be expected to use prior to the
+ success of HalAllocateHPT();
+
+Author:
+
+ Peter L Johnston (plj@vnet.ibm.com) 16-Aug-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define the range of virtual addresses this routine can allocate.
+// Note that the first page is skipped because I'm paranoid (plj).
+//
+// The range is the upper 4MB of Virtual Space - the top 32KB.
+//
+
+#define BASE_VA 0xffc00000
+#define HAL_BASE 0x000ffc01
+#define HAL_TOP 0x000ffff7
+#define PAGE_MASK 0x000fffff
+#define MAX_LENGTH (HAL_TOP-HAL_BASE)
+#define ADDRESS_MASK (PAGE_MASK << 12)
+#define OFFSET_MASK 0x00000ffc
+#define MIN_VA (HAL_BASE << PAGE_SHIFT)
+#define MAX_VA ((HAL_TOP << PAGE_SHIFT) + ((1 << PAGE_SHIFT) - 1))
+
+#define PTE_INDEX(x) (((ULONG)(x) >> PAGE_SHIFT) & 0x3ff)
+
+PHARDWARE_PTE HalpReservedPtes = NULL;
+
+// STATIC
+VOID
+HalpLocateReservedPtes(
+ VOID
+ )
+/*++
+
+ Routine Description: MODULE INTERNAL
+
+ Find the Virtual Address of the Page Table Page for the last
+ 4MB of memory. This range is reserved for the HAL with the
+ exception of the last 32KB. This page table page was allocated
+ by the OSLOADER so we can derive the address within KSEG0 from
+ the physical address which we can get from the Page Directory
+ (who's address we have).
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+--*/
+{
+ HARDWARE_PTE DirectoryEntry;
+
+ //
+ // Get the entry from the Page Directory for the Page Table
+ // Page for the HAL reserved space. The upper 10 bits of the
+ // base address give us the index into the Page Directory (which
+ // is a page of PTEs or 1024 entries). Basically we want the
+ // last one which the following gives us (and will still work
+ // if it moves).
+ //
+
+ DirectoryEntry = *(PHARDWARE_PTE)(PDE_BASE |
+ ((HAL_BASE >> (PDI_SHIFT - 2 - PAGE_SHIFT)) & OFFSET_MASK));
+
+ //
+ // The page number from this PTE * page size + the base address
+ // of KSEG0 gives the virtual address of the Page Table Page we
+ // want.
+ //
+
+ HalpReservedPtes = (PHARDWARE_PTE)(KSEG0_BASE |
+ (DirectoryEntry.PageFrameNumber << PAGE_SHIFT));
+}
+
+PVOID
+HalpAssignReservedVirtualSpace(
+ ULONG BasePage,
+ ULONG LengthInPages
+ )
+
+/*++
+
+ Routine Description:
+
+ This function will attempt to allocate a contiguous range of
+ virtual address to provide access to memory at the requested
+ physical address.
+
+ Arguments:
+
+ Physical page number for which a Virtual Address assignment is
+ needed.
+
+ Length (in pages) of the region to be mapped.
+
+ Return Value:
+
+ Virtual Address in the range HAL_BASE thru HAL_TOP + fff,
+
+ -or-
+
+ NULL if the assignment couldn't be made.
+
+
+--*/
+
+{
+ ULONG Length;
+ HARDWARE_PTE TempPte;
+ HARDWARE_PTE ZeroPte;
+ PHARDWARE_PTE PPte;
+ PHARDWARE_PTE StartingPte;
+
+ //
+ // Sanity Checks
+ //
+
+ if ( (LengthInPages > MAX_LENGTH) ||
+ (!LengthInPages) ||
+ (BasePage & ~PAGE_MASK) ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return NULL;
+ }
+
+ if ( !HalpReservedPtes ) {
+ //
+ // Not initialized yet,... fix it.
+ //
+ HalpLocateReservedPtes();
+ }
+
+ PPte = HalpReservedPtes + PTE_INDEX(MIN_VA);
+ Length = LengthInPages;
+
+ while ( PPte <= (HalpReservedPtes + PTE_INDEX(MIN_VA)) || Length ) {
+ if ( PPte->Valid ) {
+ Length = LengthInPages;
+ } else {
+ Length--;
+ }
+ PPte++;
+ }
+
+ if ( Length ) {
+ return NULL;
+ }
+
+ //
+ // Found a range of pages. PPte is pointing to the entry
+ // beyond the end of the range.
+ //
+
+ StartingPte = PPte - LengthInPages;
+ PPte = StartingPte;
+ *(PULONG)&ZeroPte = 0;
+ TempPte = ZeroPte;
+ TempPte.Write = TRUE;
+ TempPte.CacheDisable = TRUE;
+ TempPte.MemoryCoherence = TRUE;
+ TempPte.GuardedStorage = TRUE;
+ TempPte.Dirty = 0x00; // PP bits KM read/write, UM no access.
+ TempPte.Valid = TRUE;
+
+ while ( LengthInPages-- ) {
+ //
+ // The following is done in a Temp so the actual write
+ // to the page table is done in a single write.
+ //
+ TempPte.PageFrameNumber = BasePage++;
+ *PPte++ = TempPte;
+ }
+ return (PVOID)(BASE_VA |
+ ((ULONG)(StartingPte - HalpReservedPtes) << PAGE_SHIFT));
+}
+
+VOID
+HalpReleaseReservedVirtualSpace(
+ PVOID VirtualAddress,
+ ULONG LengthInPages
+ )
+
+/*++
+
+ Routine Description:
+
+ This function will release the virtual address range previously
+ allocated with HalpAssignReservedVirtualSpace and should be
+ called with a virtual address previously allocated by a call to
+ HalpAssignReservedVirtualSpace the number of pages to release.
+
+ Arguments:
+
+ VirtualAddress of a previously allocated page in the HAL reserved
+ space.
+
+ Length (in pages) to be released.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ PHARDWARE_PTE PPte;
+
+ //
+ // Sanity Checks
+ //
+
+ if ( (LengthInPages > MAX_LENGTH) ||
+ (!LengthInPages) ||
+ ((ULONG)VirtualAddress < MIN_VA) ||
+ ((ULONG)VirtualAddress > MAX_VA) ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+
+ if ( !HalpReservedPtes ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+
+ PPte = HalpReservedPtes + PTE_INDEX(VirtualAddress);
+
+ do {
+ if ( !PPte->Valid ) {
+ break;
+ }
+ PPte->Valid = FALSE;
+ PPte++;
+ } while ( --LengthInPages );
+
+ if ( LengthInPages ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ KeFlushCurrentTb();
+
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxwd.c b/private/ntos/nthals/halppc/ppc/pxwd.c
new file mode 100644
index 000000000..ac0b3a2c0
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxwd.c
@@ -0,0 +1,938 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxwd.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a Western Digital video adapter.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxwd.h"
+#include "string.h"
+//#include "txtpalet.h"
+#include "pci.h"
+
+//
+// Data Types used only in this file
+//
+
+typedef enum _LCD_TYPE{
+ NOT_CHECKED = 0x00, // panel type has not been checked yet
+ NoLCD = 0x01, // CRT
+ IBM_F8515 = 0x02, // CRT + IBM F8515 10.4" TFT LCD
+ IBM_F8532 = 0x04, // CRT + IBM F8532 10.4" TFT SVGA LCD
+ TOSHIBA_DSTNC = 0x08, // CRT + Toshiba 10.4" Dual Scan STN Color LCD
+ UNKNOWN_LCD = 0x80 // panel not recognized
+} LCD_TYPE;
+
+typedef struct{
+ LCD_TYPE Type;
+ ULONG XResolution;
+ ULONG YResolution;
+} PANEL_REC;
+
+extern PUCHAR HalpVideoMemoryBase;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+extern ULONG HalpInitPhase;
+
+//
+// Define OEM font variables.
+//
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+//
+// Prototypes
+//
+
+VOID
+ GetPanelType(),
+ TurnOnLCD( BOOLEAN );
+
+extern VOID WaitForVSync();
+
+//
+// Global variables
+//
+
+PANEL_REC
+ LCDPanel = {NOT_CHECKED, 0, 0};
+
+//
+// Western Digital internal functions
+//
+
+static VOID
+LockPR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = PORT_GCR_INDEX;
+ pData = PORT_GCR_DATA;
+ Index = pr5;
+ Data = pr5_lock;
+ break;
+ case pr10:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr10;
+ Data = pr10_lock;
+ break;
+ case pr11:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr11;
+ Data = pr11_lock;
+ break;
+ case pr1b:
+// case pr1b_ual:
+// case pr1b_ush:
+// case pr1b_upr:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_lock;
+ break;
+ case pr20:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr20;
+ Data = pr20_lock;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ Data = pr30_lock;
+ break;
+ case pr72_alt:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr72;
+ Data = pr72_lock;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ WRITE_WD_UCHAR( pIndex, Index );
+ if (pPRval!=NULL) {
+ *pPRval = READ_WD_UCHAR( pData );
+ } /* endif */
+ WRITE_WD_UCHAR( pData, Data );
+}
+
+static VOID
+UnlockPR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = PORT_GCR_INDEX;
+ pData = PORT_GCR_DATA;
+ Index = pr5;
+ Data = pr5_unlock;
+ break;
+ case pr10:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr10;
+ Data = pr10_unlock;
+ break;
+ case pr11:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr11;
+ Data = pr11_unlock;
+ break;
+// case pr1b:
+ case pr1b_ual:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_unlock;
+ break;
+ case pr1b_ush:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_unlock_shadow;
+ break;
+ case pr1b_upr:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_unlock_pr;
+ break;
+ case pr20:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr20;
+ Data = pr20_unlock;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ Data = pr30_unlock;
+ break;
+ case pr72_alt:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr72;
+ Data = pr72_unlock;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ WRITE_WD_UCHAR( pIndex, Index );
+ if (pPRval!=NULL) {
+ *pPRval = READ_WD_UCHAR( pData );
+ } /* endif */
+ WRITE_WD_UCHAR( pData, Data );
+
+}
+static VOID
+RestorePR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = PORT_GCR_INDEX;
+ pData = PORT_GCR_DATA;
+ Index = pr5;
+ break;
+ case pr10:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr10;
+ break;
+ case pr11:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr11;
+ break;
+ case pr1b:
+// case pr1b_ual:
+// case pr1b_ush:
+// case pr1b_upr:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ break;
+ case pr20:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr20;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ break;
+ case pr72_alt:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr72;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ Data = *pPRval;
+ WRITE_WD_UCHAR( pIndex, Index );
+ WRITE_WD_UCHAR( pData, Data );
+
+}
+
+static VOID
+SetWDVGAConfig (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Set WDVGA compatible configuration except DAC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR SavePR5, SavePR10, SavePR11, SavePR20, SavePR72, Temp;
+ PUCHAR pPRtable;
+
+ LockPR( pr1b, NULL );
+ LockPR( pr30, NULL );
+
+ UnlockPR( pr20, NULL );
+ UnlockPR( pr10, &SavePR10 );
+ UnlockPR( pr11, &SavePR11 );
+
+// non-ISO monitor setting clock
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, CLOCKING_MODE );
+ Temp = READ_WD_UCHAR( PORT_SEQ_DATA );
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, (Temp | 0x01));
+
+ Temp = READ_WD_UCHAR( PORT_GEN_MISC_RD );
+ WRITE_WD_UCHAR( PORT_GEN_MISC_WR, (Temp & 0xf3));
+
+// other clocking chip selects
+ UnlockPR( pr72_alt, &SavePR72 );
+
+ RestorePR( pr72_alt, &SavePR72 );
+
+ RestorePR( pr11, &SavePR11 );
+ RestorePR( pr10, &SavePR10 );
+ LockPR( pr20, NULL );
+
+// start of WD90C24A2 both screen mode table
+
+ if( LCDPanel.Type == IBM_F8532 )
+ pPRtable = wd90c24a_both_800;
+ else
+ pPRtable = wd90c24a_both_640;
+
+ while (*pPRtable != END_PVGA) {
+ switch (*pPRtable++) {
+ case W_CRTC :
+ WRITE_WD_UCHAR( WD_3D4_Index, *pPRtable++ );
+ WRITE_WD_UCHAR( WD_3D5_Data, *pPRtable++ );
+ break;
+ case W_SEQ :
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, *pPRtable++ );
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, *pPRtable++ );
+ break;
+ case W_GCR :
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, *pPRtable++ );
+ WRITE_WD_UCHAR( PORT_GCR_DATA, *pPRtable++ );
+ break;
+ default :
+ break;
+ }
+ }
+
+ // unlock FLAT registers
+
+ UnlockPR( pr1b_ual, NULL );
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, pr68 );
+ Temp = READ_WD_UCHAR( PORT_SEQ_DATA );
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, ((Temp & 0xe7) | 0x10) );
+ else
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, ((Temp & 0xe7) | 0x08) );
+
+ WRITE_WD_UCHAR( WD_3D4_Index, pr19 );
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( WD_3D5_Data, (pr19_s32 & 0xf3));
+ else
+ WRITE_WD_UCHAR( WD_3D5_Data, (pr19_s32 & 0xf3));
+
+ // lock FLAT registers
+
+ LockPR( pr1b, NULL );
+
+} /* SetWDVGAConfig */
+
+VOID
+HalpDisplayPpcWDSetup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the Western Digital display controller chip.
+
+Arguments:
+ None.
+
+Return Value:
+ None.
+
+--*/
+{
+
+ ULONG DataLong, stop;
+ USHORT i, j;
+ UCHAR DataByte;
+ UCHAR Index;
+ PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
+ 0x400000); // 4 MB
+ } else {
+
+ //
+ // Map video memory space via pte's
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE ;
+ HalpVideoMemoryBase = MmMapIoSpace(physicalAddress,
+ 0x400000,
+ FALSE);
+
+ //
+ // IO control space has already been mapped in phase 1 via halpmapiospace
+ //
+
+ }
+
+ if( LCDPanel.Type == NOT_CHECKED )
+ GetPanelType();
+
+ // turn the panel off before configuring it (prevents blowing the fuse)
+
+ TurnOnLCD( FALSE );
+
+ // Enable Video Subsystem according to the WD90C24 reference book
+
+ WRITE_WD_UCHAR( SUBSYS_ENB, 0x16 );
+ WRITE_WD_UCHAR( Setup_OP, 0x01 );
+ WRITE_WD_UCHAR( SUBSYS_ENB, 0x0e );
+
+ WRITE_WD_UCHAR( PORT_SYS_VGA_ENABLE, VideoParam[0] );
+
+ SetWDVGAConfig();
+
+ // turn off the hardware cursor
+
+ WRITE_WD_USHORT( EPR_INDEX, 0x1002 );
+ WRITE_WD_USHORT( EPR_DATA, 0x0000 );
+
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // Synchronous Reset !
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x01 );
+
+ // For ATI card (0x63) we may want to change the frequence
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( PORT_GEN_MISC_WR, (VideoParam[1] & 0xf3) );
+ else
+ WRITE_WD_UCHAR( PORT_GEN_MISC_WR, VideoParam[1] );
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // Synchronous Reset !
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x01 );
+
+ // Sequencer Register
+
+ for( Index = 1; Index < 5; Index++ )
+ {
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, Index );
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET + Index] );
+ }
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+
+ WRITE_WD_UCHAR( WD_3D4_Index, VERTICAL_RETRACE_END );
+
+ DataByte = READ_WD_UCHAR( WD_3D5_Data );
+ DataByte = DataByte & 0x7f;
+ WRITE_WD_UCHAR( WD_3D5_Data, DataByte );
+
+ // CRTC controller CR0 - CR18
+
+ for( Index = 0; Index < 25; Index++ )
+ {
+ WRITE_WD_UCHAR( WD_3D4_Index, Index );
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( WD_3D5_Data, CRTC_800x600x60_Text[Index] );
+ else
+ WRITE_WD_UCHAR( WD_3D5_Data, CRTC_640x480x60_Text[Index] );
+ }
+
+ // attribute write
+ // program palettes and mode register
+
+ for( Index = 0; Index < 21; Index++ )
+ {
+ WaitForVSync();
+ DataByte = READ_WD_UCHAR( PORT_GEN_FEATURE_WR_C ); // Initialize Attr. F/F
+ WRITE_WD_UCHAR( PORT_ATTR_DATA_WR, Index );
+
+// KeStallExecutionProcessor( 5 );
+ WRITE_WD_UCHAR( PORT_ATTR_INDEX, VideoParam[ATTR_OFFSET + Index] );
+
+// KeStallExecutionProcessor( 5 );
+ WRITE_WD_UCHAR( PORT_ATTR_DATA_WR, 0x20 ); // Set into normal operation
+ }
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // reset to normal operation !
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x03 );
+
+ // graphics controller
+
+ for( Index = 0; Index < 9; Index++ )
+ {
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, Index );
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + Index] );
+ }
+
+ // turn off the text mode cursor
+
+ WRITE_WD_UCHAR( WD_3D4_Index, CURSOR_START );
+ WRITE_WD_UCHAR( WD_3D5_Data, 0x2D );
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x02 ); // Enable Write Plane reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x04 ); // select plane 2
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x04 ); // Memory Mode Control reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x06 ); // access to all planes,
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x05 ); // Graphic, Control Mode reg
+ WRITE_WD_UCHAR( PORT_GCR_DATA, 0x00 );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x06 );
+ WRITE_WD_UCHAR( PORT_GCR_DATA, 0x04 );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x04 );
+ WRITE_WD_UCHAR( PORT_GCR_DATA, 0x02 );
+
+ MemBase = 0xA0000; // Font Plane 2
+
+ for( i = 0; i < 256; i++ )
+ {
+ for( j = 0; j < 16; j++ )
+ {
+ WRITE_WD_VRAM( MemBase, VGAFont8x16[i * 16 + j] );
+ MemBase++;
+ }
+
+ // 32 bytes each character font
+
+ for( j = 16; j < 32; j++ )
+ {
+ WRITE_WD_VRAM( MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x01 );
+ DataByte = READ_WD_UCHAR( PORT_SEQ_DATA );
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, DataByte );
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_WD_UCHAR( PORT_DAC_PIX_MASK, 0xff );
+
+ // start loading palette in register 0
+ WRITE_WD_UCHAR( PORT_DAC_WRITE_PIX_ADDR, 0 );
+
+ for( i = 0; i < 768; i++ )
+ {
+ WRITE_WD_UCHAR( PORT_DAC_DATA, TextPalette[i] );
+ }
+
+ //
+ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ // select plane 0, 1
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x02); // Enable Write Plane reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET + 0x02] );
+
+ // access to planes 0, 1.
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x04); // Memory Mode Control reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x05 ); // Graphic, Control Mode reg
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x05] );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x04);
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x04] );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x06);
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x06] );
+
+ //
+ // Set screen into blue
+ //
+
+ if( LCDPanel.Type == IBM_F8532 )
+ stop = 0xb9db0;
+ else
+ stop = 0xb92c0;
+
+ for( DataLong = 0xB8000; DataLong < stop; DataLong += 2 )
+ {
+ WRITE_WD_VRAM( DataLong, 0x20 );
+ WRITE_WD_VRAM( DataLong + 1, 0x1F );
+ }
+
+ //
+ // turn the panel back on
+ //
+
+ TurnOnLCD( TRUE );
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+
+ if( LCDPanel.Type == IBM_F8532 )
+ {
+ HalpDisplayWidth = 100;
+ HalpDisplayText = 37;
+ HalpScrollLine = 200;
+ }
+ else
+ {
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ }
+
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of InitializeWD() */
+
+VOID
+GetPanelType()
+
+/*++
+
+Routine Description:
+
+ This routine get the type of attached LCD display.
+
+Arguments:
+
+ HwDeviceExtension - Pointer to the miniport driver's device extension.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ UCHAR data8;
+
+ //
+ // read the panel controller
+ //
+
+ WRITE_WD_UCHAR(0xd00, 0xff);
+ data8 = READ_WD_UCHAR(0xd01);
+
+ switch (data8 & 0x0f) {
+ case 0x0e:
+ LCDPanel.Type = IBM_F8515;
+ LCDPanel.XResolution = 640;
+ LCDPanel.YResolution = 480;
+ break;
+
+ case 0x0c:
+ LCDPanel.Type = IBM_F8532;
+ LCDPanel.XResolution = 800;
+ LCDPanel.YResolution = 600;
+ break;
+
+ case 0x0d:
+ LCDPanel.Type = TOSHIBA_DSTNC;
+ LCDPanel.XResolution = 640;
+ LCDPanel.YResolution = 480;
+ break;
+
+ default:
+ LCDPanel.Type = UNKNOWN_LCD;
+ LCDPanel.XResolution = 0;
+ LCDPanel.YResolution = 0;
+ break;
+ }
+
+} // end GetPanelType()
+
+BOOLEAN
+HalpPhase0EnablePmController()
+
+{
+
+ ULONG i, BaseAddress;
+ USHORT VendorID, DeviceID, Command;
+
+ //
+ // Locates the controller on the PCI bus, and configures it
+ //
+
+ if (HalpPhase0MapBusConfigSpace() == FALSE){
+
+ return( FALSE );
+
+ } else {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+
+ HalpPhase0GetPciDataByOffset(0,
+ i,
+ &VendorID,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,VendorID),
+ sizeof(VendorID));
+
+ HalpPhase0GetPciDataByOffset(0,
+ i,
+ &DeviceID,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,DeviceID),
+ sizeof(DeviceID));
+
+ if ((VendorID == 0x1014) && (DeviceID == 0x001C)) {
+
+ HalpPhase0GetPciDataByOffset(0,
+ i,
+ &Command,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,Command),
+ sizeof(Command));
+
+ Command |= PCI_ENABLE_IO_SPACE;
+ BaseAddress = (ULONG)0x4100;
+
+ HalpPhase0SetPciDataByOffset(0,
+ i,
+ &Command,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,Command),
+ sizeof(Command));
+
+ HalpPhase0SetPciDataByOffset(0,
+ i,
+ &BaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]),
+ sizeof(BaseAddress));
+
+ break;
+ } /* endif */
+
+ } /* endfor */
+
+ } /* end if map config space succeeds */
+
+ HalpPhase0UnMapBusConfigSpace();
+
+ return( TRUE );
+
+}
+
+BOOLEAN
+HalpPhase1EnablePmController()
+
+{
+
+ ULONG i;
+ PCI_SLOT_NUMBER slot;
+ PCI_COMMON_CONFIG PCIDeviceConfig;
+
+ slot.u.AsULONG = (ULONG)0;
+
+ //
+ // Locates the controller on the PCI bus, and configures it
+ //
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+
+ slot.u.bits.DeviceNumber = i;
+
+ HalGetBusData (
+ PCIConfiguration,
+ 0,
+ slot.u.AsULONG,
+ &PCIDeviceConfig,
+ sizeof (PCIDeviceConfig)
+ );
+
+ if ((PCIDeviceConfig.VendorID == 0x1014) &&
+ (PCIDeviceConfig.DeviceID == 0x001C)) {
+
+ PCIDeviceConfig.Command |= PCI_ENABLE_IO_SPACE;
+ PCIDeviceConfig.u.type0.BaseAddresses[0] = (ULONG)0x4100;
+
+ HalSetBusData (
+ PCIConfiguration,
+ 0,
+ slot.u.AsULONG,
+ &PCIDeviceConfig,
+ sizeof (PCIDeviceConfig)
+ );
+
+ break;
+ } /* endif */
+ } /* endfor */
+
+ return( TRUE );
+
+}
+
+# define PmIoBase 0x4100
+
+VOID
+TurnOnLCD( BOOLEAN PowerState )
+/*++
+
+Routine Description:
+
+ This routine turns on/off LCD.
+
+Arguments:
+
+ HwDeviceExtension - Pointer to the miniport driver's adapter information.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN found = FALSE;
+
+ if (HalpInitPhase == 0)
+ found = HalpPhase0EnablePmController();
+ else
+ found = HalpPhase1EnablePmController();
+
+ if (!found) {
+ return;
+ } /* endif */
+
+ //
+ // Turns on/off LCD
+ //
+
+ if (PowerState) {
+
+ KeStallExecutionProcessor(100 * 1000); // wait 100ms for panel protection
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x02);
+
+ KeStallExecutionProcessor(5 * 1000); // wait 5ms for DC/DC converter
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x0c);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x00);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x80);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x01);
+
+ } else {
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x01);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x00);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x80);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x0C);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x02);
+
+ } /* endif */
+
+} // end TurnOnLCD()
diff --git a/private/ntos/nthals/halppc/ppc/pxwd.h b/private/ntos/nthals/halppc/ppc/pxwd.h
new file mode 100644
index 000000000..56e621d65
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxwd.h
@@ -0,0 +1,706 @@
+/*++
+
+Copyright (c) 1994 IBM Corporation
+
+Module Name:
+
+ wdvga.h
+
+Abstract:
+
+ This header file defines the WD90C24A2 GUI accelerator registers.
+
+Author:
+
+ Hiroshi Itoh 25-Feb-1994
+
+Revision History:
+
+ Peter Johnston Adapted to Woodfield HAL. Apr-1994
+
+--*/
+
+#include "pxvgaequ.h"
+
+extern UCHAR CRTC_800x600x60_Text[];
+extern UCHAR CRTC_640x480x60_Text[];
+
+//-----------------------------------------------------------------------
+// WD 90C24 PR register
+//-----------------------------------------------------------------------
+#define pr0a 0x09 // Address Offset A Reg
+#define pr0b 0x0a // Alternate Address Offset B Reg
+#define pr1 0x0b // Memory Size Reg
+#define pr2 0x0c // Video Select Reg
+#define pr3 0x0d // CRT Lock Control Reg
+#define pr4 0x0e // Video Control Reg
+#define pr5 0x0f // Unlock graphic Controller Extended
+ // Paradise Reg
+
+#define pr10 0x29 // Unlock (PR11-PR17) Reg
+#define pr11 0x2a // Configuraiton Bits Reg
+#define pr12 0x2b // Scratch Pad Reg
+#define pr13 0x2c // Interlace H/2 Start Reg
+#define pr14 0x2d // Interlace H/2 End Reg
+#define pr15 0x2e // Miscellaneous Control 1 Reg
+#define pr16 0x2f // Miscellaneous Control 2 Reg
+#define pr17 0x30 // Miscellaneous Control 3 Reg
+#define pr18 0x31 // Flat Panel Status Reg
+#define pr19 0x32 // Flat Panel Control I Reg
+#define pr1a 0x33 // Flat Panel Control II Reg
+#define pr1b 0x34 // Flat Panel Unlock Reg
+
+#define pr20 0x06 // Unlock Sequencer Extended Reg
+#define pr21 0x07 // Display Configuraiton Status &
+ // Scratch Pad Reg
+#define pr22 0x08 // Scratch Pad Reg
+#define pr23 0x09 // Scratch Pad Reg
+
+#define pr30 0x35 // Mapping RAM Unlock Reg
+
+#define pr30a 0x10 // Memory Interface & FIFO Control Reg
+#define pr31 0x11 // System Interface Control Reg
+#define pr32 0x12 // Miscellaneous Control 4 Reg
+
+#define pr33 0x38 // Mapping RAM Address Counter Reg
+#define pr34 0x39 // Mapping RAM Data Reg
+
+#define pr33a 0x13 // DRAM Timing and 0 wait state control
+#define pr34a 0x14 // Video Memory Mapping Reg
+#define pr35a 0x15 // USR0, USR1 output select
+
+#define pr35 0x3a // Mapping RAM Control Reg
+#define pr36 0x3b // LCD Panel Height Select Reg
+#define pr37 0x3c // Flat Panel Height Select Reg
+#define pr39 0x3e // Color LCD Control Reg
+#define pr41 0x37 // Vertical Expansion Initial Value Reg
+
+#define pr44 0x3f // Power Down Memory Refresh Control Reg
+
+#define pr45 0x16 // Signal Analyzer Control Reg
+#define pr45a 0x17 // Signal Analyzer Data I
+#define pr45b 0x18 // Signal Analyzer Data II
+
+#define pr18a 0x3d // CRTC Vertical Timing Overflow
+
+#define pr57 0x19 // WD90C24 Feature Reg I
+#define pr58 0x20 // WD90C24 Feature Reg II
+#define pr59 0x21 // WD90C24 Memory Arbitration Cycle Setup
+#define pr60 0x22 // Reserved
+#define pr61 0x23 // Reserved
+#define pr62 0x24 // FR Timing Reg
+#define pr63 0x25 //
+#define pr58a 0x26 //
+#define pr64 0x27 //
+#define pr65 0x28 //
+#define pr66 0x29 //
+#define pr68 0x31 //
+#define pr69 0x32 //
+#define pr70 0x33 //
+#define pr71 0x34 //
+#define pr72 0x35 //
+#define pr73 0x36 //
+
+//-----------------------------------------------------------------------
+// pr register lock/unlock pattern
+//-----------------------------------------------------------------------
+#define pr5_lock 0x00 //
+#define pr5_unlock 0x05 //
+
+#define pr10_lock 0x00 //
+#define pr10_unlock 0x85 //
+
+#define pr11_unlock 0x80 //
+#define pr11_lock 0x85 //
+
+#define pr1b_lock 0x00 //
+#define pr1b_unlock_shadow 0x06 //
+#define pr1b_unlock_pr 0xa0 //
+#define pr1b_unlock 0xa6 //
+
+#define pr20_lock 0x00 //
+#define pr20_unlock 0x48 //
+
+#define pr30_lock 0x00 //
+#define pr30_unlock 0x30 //
+
+#define pr72_lock 0x00 //
+#define pr72_unlock 0x50 //
+
+//-----------------------------------------------------------------------
+// WD 90C24 PR register < Initital Value >
+//-----------------------------------------------------------------------
+// CRT TFT Sim STN Sim STNC STNC //
+// all only only 32 only 16 sim only //
+// ---- ---- ---- ---- ---- ---- ---- ---- //
+#define pr0a_all 0x00 //
+#define pr0b_all 0x00 //
+#define pr1_all 0xc5 //
+
+#define pr2_crt 0x00 //
+#define pr2_tft 0x01 //
+#define pr2_s32 0x01 //
+#define pr2_stn 0x01 //
+#define pr2_s16 0x01 //
+#define pr2_stnc 0x01 //
+
+#define pr3_all 0x00 //
+#define pr4_all 0x40 //
+
+#define pr12_all 0x00 //
+#define pr12_244LP 0xe8 //
+
+#define pr13_all 0x00 //
+#define pr14_all 0x00 //
+#define pr15_all 0x00 //
+#define pr16_all 0x42 //
+
+#define pr17_all 0x00 //
+#define pr17_244LP 0x40 //
+
+#define pr18_crt_tft 0x43 //single panel
+#define pr18_crt_stn 0x00 //dual panel
+#define pr18_tft 0xc7 // old d7h
+#define pr18_s32 0x47 // old 57h
+#define pr18_stn 0x80 //
+#define pr18_s16 0x00 //
+#define pr18_stnc 0x00 //
+
+#define pr19_disable 0x40 //
+#define pr19_crt 0x64 //
+#define pr19_tft 0x54 //
+#define pr19_s32 0x74 //
+#define pr19_stn 0x54 //
+#define pr19_s16 0x74 //
+#define pr19_stnc 0x74 //
+#define pr19_stnc_only 0x54 //
+
+#define pr39_crt 0x04 //
+#define pr39_tft 0x20 //
+#define pr39_s32 0x24 //
+#define pr39_stn 0x00 //
+#define pr39_s16 0x04 //
+#define pr39_stnc 0x24 //
+
+#define pr1a_all 0x00 // except STNC
+#define pr1a_stnc 0x60 // STNC
+
+#define pr36_all 0xef //
+
+#define pr37_crt 0x9a //
+#define pr37_tft 0x9a //
+#define pr37_s32 0x9a //
+#define pr37_stn 0x9a //
+#define pr37_s16 0x1a //
+#define pr37_stnc 0x9a //
+
+#define pr18a_all 0x00 //
+#define pr41_all 0x00 //
+#define pr44_all 0x00 //
+#define pr33_all 0x00 //
+#define pr34_all 0x00 //
+
+#define pr35_all 0x22 // old 0a2h
+#define pr35_suspend 0xa2 //
+
+#define pr21_all 0x00 //
+#define pr22_all 0x00 //
+#define pr23_all 0x00 //
+
+#define pr30a_crt 0xc1 //
+#define pr30a_tft 0xc1 //
+#define pr30a_s32 0xc1 //
+#define pr30a_stn 0xc1 //
+#define pr30a_s16 0xe1 //
+#define pr30a_stnc 0xe1 //
+
+#define pr31_all 0x25 //
+#define pr32_all 0x00 //
+
+#define pr33a_all 0x80 //
+#define pr33a_stnc 0x83 //
+
+#define pr34a_all 0x00 //
+#define pr35a_all 0x00 //
+
+#define pr45_all 0x00 //
+#define pr45a_all 0x00 //
+#define pr45b_all 0x00 //
+#define pr57_all 0x31 //
+#define pr58_all 0x00 //
+#define pr58a_all 0x00 //
+
+#define pr59_all_sivA 0x35 //
+#define pr59_crt 0x15 // for SIV-B
+#define pr59_tft 0x15 //
+#define pr59_s32 0x15 //
+#define pr59_stn 0x35 //
+#define pr59_s16 0x35 //
+#define pr59_stnc 0x03 //
+
+#define pr60_all 0x00 //
+#define pr61_all 0x00 //
+#define pr62_all 0x3c //
+#define pr63_all 0x00 //
+
+#define pr64_all 0x03 //enhncd v-exp
+
+#define pr65_all 0x00 //
+
+#define pr66_crt 0x40 //
+#define pr66_tft 0x40 //
+#define pr66_s32 0x40 //
+#define pr66_stn 0x40 //
+#define pr66_s16 0x40 //
+#define pr66_stnc 0x40 //
+
+#define pr68_crt 0x0d //
+#define pr68_tft 0x0d //
+#define pr68_s32 0x0d // old 0bh
+#define pr68_stn 0x1d //
+#define pr68_s16 0x0d //
+#define pr68_stnc 0x0d //
+#define pr68_stnc_only 0x07 //
+
+#define pr69_all 0x00 //
+#define pr69_stnc_only 0x53 // old 3fh
+
+#define pr70_all 0x00 //
+#define pr71_all 0x00 //
+#define pr73_all 0x01 //
+
+//--------------------------------------------------------------------------
+// WD 90C24 Shadow Register < Initial Value >
+//--------------------------------------------------------------------------
+// For TFT color Only Mode
+#define crtc00_tft 0x5f //
+#define crtc02_tft 0x50 //
+#define crtc03_tft 0x82 //
+#define crtc04_tft 0x54 //
+#define crtc05_tft 0x80 //
+#define crtc06_tft 0x0b //
+#define crtc07_tft 0x3e //
+#define crtc10_tft 0xea //
+#define crtc11_tft 0x8c //
+#define crtc15_tft 0xe7 //
+#define crtc16_tft 0x04 //
+
+// For TFT color Simultaneos Mode
+#define crtc00_s32 0x5f //
+#define crtc02_s32 0x50 //
+#define crtc03_s32 0x82 //
+#define crtc04_s32 0x54 //
+#define crtc05_s32 0x80 //
+#define crtc06_s32 0x0b //
+#define crtc07_s32 0x3e //
+#define crtc10_s32 0xea //
+#define crtc11_s32 0x8c //
+#define crtc15_s32 0xe7 //
+#define crtc16_s32 0x04 //
+
+// For STN mono Only Mode
+#define crtc00_stn 0x5f //
+#define crtc02_stn 0x50 //
+#define crtc03_stn 0x82 //
+#define crtc04_stn 0x54 //
+#define crtc05_stn 0x80 //
+#define crtc06_stn 0xf2 //
+#define crtc07_stn 0x12 //
+#define crtc10_stn 0xf0 //
+#define crtc11_stn 0x82 //
+#define crtc15_stn 0xf0 //
+#define crtc16_stn 0xf2 //
+
+// For STN mono Simultaneos Mode
+#define crtc00_s16 0x5f //
+#define crtc02_s16 0x50 //
+#define crtc03_s16 0x82 //
+#define crtc04_s16 0x54 //
+#define crtc05_s16 0x80 //
+#define crtc06_s16 0x12 //
+#define crtc07_s16 0x3e //
+#define crtc10_s16 0xea //
+#define crtc11_s16 0x8c //
+#define crtc15_s16 0xe7 //
+#define crtc16_s16 0x04 //
+
+// For STN Color Simultaneos Mode //new old
+#define crtc00_stnc 0x61 // 60h
+#define crtc02_stnc 0x50 // 51h
+#define crtc03_stnc 0x84 // 82h
+#define crtc04_stnc 0x56 // 54h
+#define crtc05_stnc 0x80 //
+#define crtc06_stnc 0x0e // 0ah
+#define crtc07_stnc 0x3e //
+#define crtc10_stnc 0xea //
+#define crtc11_stnc 0x8e //
+#define crtc15_stnc 0xe7 //
+#define crtc16_stnc 0x04 //
+
+// For STN Color LCD only Mode //new old
+#define crtc00_stnc_only 0x67 // 60h
+#define crtc02_stnc_only 0x50 // 50h
+#define crtc03_stnc_only 0x82 // 82h
+#define crtc04_stnc_only 0x55 // 54h
+#define crtc05_stnc_only 0x81 // 80h
+#define crtc06_stnc_only 0xe6 // 0e6h
+#define crtc07_stnc_only 0x1f // 1fh
+#define crtc10_stnc_only 0xe0 // 0d9h
+#define crtc11_stnc_only 0x82 // 82h
+#define crtc15_stnc_only 0xe0 // 0f0h
+#define crtc16_stnc_only 0xe2 // 00h
+
+//-----------------------------------------------------------------------
+// WD 90C24 Mapping RAM Data
+//-----------------------------------------------------------------------
+#define map_00 0x00
+#define map_01 0x05
+#define map_02 0x05
+#define map_03 0x06
+#define map_04 0x06
+#define map_05 0x07
+#define map_06 0x07
+#define map_07 0x08
+#define map_08 0x08
+#define map_09 0x0a
+#define map_0a 0x0a
+#define map_0b 0x0b
+#define map_0c 0x0c
+#define map_0d 0x0d
+#define map_0e 0x0d
+#define map_0f 0x0f
+
+#define map_10 0x0f
+#define map_11 0x11
+#define map_12 0x12 // old 11h
+#define map_13 0x12 // old 13h
+#define map_14 0x15 // old 13h
+#define map_15 0x15
+#define map_16 0x17 // old 15h
+#define map_17 0x17
+#define map_18 0x19 // old 17h
+#define map_19 0x19
+#define map_1a 0x1b
+#define map_1b 0x1b
+#define map_1c 0x1d
+#define map_1d 0x1d
+#define map_1e 0x1f
+#define map_1f 0x1f
+
+#define map_20 0x20
+#define map_21 0x21
+#define map_22 0x21
+#define map_23 0x23
+#define map_24 0x25 // old 24h
+#define map_25 0x27
+#define map_26 0x27
+#define map_27 0x29
+#define map_28 0x29
+#define map_29 0x2a
+#define map_2a 0x2b
+#define map_2b 0x2b // old 2ch
+#define map_2c 0x2e
+#define map_2d 0x2e
+#define map_2e 0x2f
+#define map_2f 0x2f
+
+#define map_30 0x31
+#define map_31 0x33
+#define map_32 0x33
+#define map_33 0x34
+#define map_34 0x34
+#define map_35 0x35 // old 36h
+#define map_36 0x36
+#define map_37 0x38
+#define map_38 0x39
+#define map_39 0x39
+#define map_3a 0x3a
+#define map_3b 0x3a
+#define map_3c 0x3b
+#define map_3d 0x3b
+#define map_3e 0x3f
+#define map_3f 0x3f
+
+//-----------------------------------------------------------------------
+// Paradise register bit flag definitions
+//-----------------------------------------------------------------------
+// pr19 display position definition
+#define pr19_CENTER 0x04 // display position is CENTER
+#define pr19_TOP 0x00 // display position is TOP
+#define pr19_BOTTOM 0x04 // display position is BOTTOM (N/A)
+#define pr19_VEXP 0x0C // Vertical Expansion
+
+//-----------------------------------------------------------------------
+// Extended Paradise Regs definitions
+//-----------------------------------------------------------------------
+// Global port definitions
+#define EPR_INDEX 0x23c0 // Index Control Reg
+#define EPR_DATA 0x23c2 // Register access port
+
+//
+// Define paradise registers setting variation
+//
+
+#define pr72_alt (pr72 | 0x8000) // avoid pr30 index conflict
+#define pr1b_ual (pr1b) // pr1b unlock variation
+#define pr1b_ush (pr1b | 0x4000) // pr1b unlock variation
+#define pr1b_upr (pr1b | 0x8000) // pr1b unlock variation
+
+
+//
+// Define WD register I/O Macros
+//
+
+
+#define WRITE_WD_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_WD_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_WD_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_WD_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_WD_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_WD_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//
+// Define video register format.
+//
+#define WD_3D4_Index 0x3D4 // R/W
+#define WD_3D5_Data 0x3D5 // R/W
+
+#define SUBSYS_ENB 0x46E8 // R/W
+
+//
+// WD90C24A2 LCD/CRT both screen table
+//
+
+enum { W_SEQ, W_GCR, W_ACR, W_CRTC, R_SEQ, R_GCR, R_ACR, R_CRTC, END_PVGA } pvga_service;
+
+static
+UCHAR
+wd90c24a_both_800[] = {
+ W_CRTC , pr10, pr10_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr11, pr11_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr1b, pr1b_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr19, pr19_disable ,
+//---------------------> start SEQ
+
+ W_SEQ , pr20 , pr20_unlock , // PVGA Sequencer Regs
+// W_SEQ , pr21 , pr21_all , // read only
+ W_SEQ , pr30a, pr30a_s32 ,
+ W_SEQ , pr31 , (pr31_all & ~0x24) ,
+
+ W_SEQ , pr32 , pr32_all ,
+ W_SEQ , pr33a, pr33a_all ,
+ W_SEQ , pr34a, pr34a_all ,
+ W_SEQ , pr35a, pr35a_all ,
+// W_SEQ , pr45 , pr45_all ,
+// W_SEQ , pr45a, pr45a_all ,
+// W_SEQ , pr45b, pr45b_all ,
+ W_SEQ , pr57 , pr57_all ,
+
+
+ W_SEQ , pr58 , pr58_all ,
+ W_SEQ , pr58a, pr58a_all ,
+ W_SEQ , pr59 , pr59_s32 ,
+// W_SEQ , pr60 , pr60_all ,
+// W_SEQ , pr61 , pr61_all ,
+ W_SEQ , pr62 , pr62_all ,
+// W_SEQ , pr63 , pr63_all ,
+ W_SEQ , pr64 , pr64_all ,
+// W_SEQ , pr65 , pr65_all ,
+
+
+ W_SEQ , pr66 , pr66_s32 , // old 00h
+ W_SEQ , pr72 , pr72_unlock , // unlock clock select
+ W_SEQ , pr68 , pr68_s32 , // 0d
+// W_SEQ , pr72 , pr72_lock , // lock clock select
+// W_SEQ , pr72 , pr72_lock , // lock is default
+// W_SEQ , pr69 , pr69_all ,
+// W_SEQ , pr70 , pr70_all ,
+ W_SEQ , pr70 , 0x24 ,
+// W_SEQ , pr71 , pr71_all , // disabled by PR57(1)
+// W_SEQ , pr73 , pr73_all ,
+// W_SEQ , pr20 , pr20_lock ,
+
+
+//---------------------> start GRAPH
+
+ W_GCR , pr5 , pr5_unlock , // PR0(A), PR0(B), PR1, PR2, PR3, PR4
+// W_GCR , pr0a , pr0a_all ,
+// W_GCR , pr0b , pr0b_all ,
+ W_GCR , pr1 , pr1_all ,
+ W_GCR , pr2 , pr2_s32 ,
+ W_GCR , pr3 , pr3_all ,
+ W_GCR , pr4 , pr4_all ,
+ // W_GCR , pr5 , pr5_lock ,
+
+
+//---------------------> start CRTC
+
+ W_CRTC , pr10 , pr10_unlock , // PR11, PR13, PR14, PR15, PR16, PR17
+// W_CRTC , pr11 , pr11_lock , // default is lock
+// W_CRTC , pr12 , pr12_all ,
+ W_CRTC , pr13 , pr13_all ,
+ W_CRTC , pr14 , pr14_all ,
+ W_CRTC , pr15 , pr15_all ,
+ W_CRTC , pr16 , pr16_all ,
+ W_CRTC , pr17 , pr17_all ,
+// W_CRTC , pr10 , pr10_lock ,
+
+
+ W_CRTC , pr1b , pr1b_unlock , // PR18, PR19, PR1A, PR36, PR37, PR39, PR41, PR44
+ W_CRTC , pr18 , pr18_s32 ,
+// W_CRTC , pr19 , pr19_s32 ,
+ W_CRTC , pr19 , pr19_tft & ~0x04 ,
+ W_CRTC , pr39 , pr39_s32 ,
+ W_CRTC , pr1a , 0x90 ,
+ W_CRTC , pr36 , pr36_all ,
+ W_CRTC , pr37 , pr37_s32 ,
+ W_CRTC , pr18a, pr18a_all ,
+// W_CRTC , pr41 , pr41_all ,
+ W_CRTC , pr44 , pr44_all ,
+// W_CRTC , pr1b , pr1b_lock ,
+
+ W_CRTC , pr30 , pr30_unlock , // PR35 (Mapping RAM not initialized)
+// W_CRTC , pr33 , pr33_all ,
+// W_CRTC , pr34 , pr34_all ,
+ W_CRTC , pr35 , pr35_all ,
+// W_CRTC , pr30 , pr30_lock ,
+
+ // Shadow Regs
+// CRTC shadows
+
+ W_CRTC , pr1b , pr1b_unlock_shadow ,// Unlock shadow
+ W_CRTC , 0x11 , crtc11_s32 & 0x7f , // unlock CRTC 0-7
+
+ W_CRTC , 0x00 , 0x7f ,
+ W_CRTC , 0x01 , 0x63 ,
+ W_CRTC , 0x02 , 0x64 ,
+ W_CRTC , 0x03 , 0x82 ,
+ W_CRTC , 0x04 , 0x6b ,
+ W_CRTC , 0x05 , 0x1b ,
+ W_CRTC , 0x06 , 0x72 ,
+ W_CRTC , 0x07 , 0xf0 ,
+ W_CRTC , 0x09 , 0x20 ,
+ W_CRTC , 0x10 , 0x58 ,
+ W_CRTC , 0x11 , 0x8c , // lock CRTC 0-7
+ W_CRTC , 0x15 , 0x58 ,
+ W_CRTC , 0x16 , 0x71 ,
+// W_CRTC , pr17 , 0xe3 , // Lock shadow
+// W_CRTC , pr18 , 0xff , // Lock shadow
+
+//---------------------> start CRTC
+
+ W_CRTC , pr1b, pr1b_unlock_pr ,
+ W_CRTC , pr19 ,(pr19_s32 & ~0x04), // Lock shadow
+
+ END_PVGA
+};
+
+static
+UCHAR
+wd90c24a_both_640[] = {
+ W_CRTC , pr1b, pr1b_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr19, pr19_disable ,
+ W_CRTC , pr1b, pr1b_lock ,
+
+ W_SEQ , pr20 , pr20_unlock , // PVGA Sequencer Regs
+// W_SEQ , pr21 , pr21_all , // read only
+ W_SEQ , pr30a, pr30a_s32 ,
+ W_SEQ , pr31 , pr31_all ,
+ W_SEQ , pr32 , pr32_all ,
+ W_SEQ , pr33a, pr33a_all ,
+ W_SEQ , pr34a, pr34a_all ,
+ W_SEQ , pr35a, pr35a_all ,
+// W_SEQ , pr45 , pr45_all ,
+// W_SEQ , pr45a, pr45a_all ,
+// W_SEQ , pr45b, pr45b_all ,
+ W_SEQ , pr57 , pr57_all ,
+ W_SEQ , pr58 , pr58_all ,
+ W_SEQ , pr58a, pr58a_all ,
+ W_SEQ , pr59 , pr59_s32 ,
+// W_SEQ , pr60 , pr60_all ,
+// W_SEQ , pr61 , pr61_all ,
+ W_SEQ , pr62 , pr62_all ,
+// W_SEQ , pr63 , pr63_all ,
+ W_SEQ , pr64 , pr64_all ,
+// W_SEQ , pr65 , pr65_all ,
+ W_SEQ , pr66 , pr66_s32 , // old 00h
+ W_SEQ , pr72 , pr72_unlock , // unlock clock select
+ W_SEQ , pr68 , pr68_s32 , // 0d
+// W_SEQ , pr72 , pr72_lock , // lock clock select
+ W_SEQ , pr72 , pr72_lock , // lock is default
+// W_SEQ , pr69 , pr69_all ,
+// W_SEQ , pr70 , pr70_all ,
+// W_SEQ , pr71 , pr71_all , // disabled by PR57(1)
+// W_SEQ , pr73 , pr73_all ,
+ W_SEQ , pr20 , pr20_lock ,
+
+ W_GCR , pr5 , pr5_unlock , // PR0(A), PR0(B), PR1, PR2, PR3, PR4
+// W_GCR , pr0a , pr0a_all ,
+// W_GCR , pr0b , pr0b_all ,
+ W_GCR , pr1 , pr1_all ,
+ W_GCR , pr2 , pr2_s32 ,
+ W_GCR , pr3 , pr3_all ,
+ W_GCR , pr4 , pr4_all ,
+ W_GCR , pr5 , pr5_lock ,
+
+ W_CRTC , pr10 , pr10_unlock , // PR11, PR13, PR14, PR15, PR16, PR17
+ W_CRTC , pr11 , pr11_lock , // default is lock
+// W_CRTC , pr12 , pr12_all ,
+ W_CRTC , pr13 , pr13_all ,
+ W_CRTC , pr14 , pr14_all ,
+ W_CRTC , pr15 , pr15_all ,
+ W_CRTC , pr16 , pr16_all ,
+ W_CRTC , pr17 , pr17_all ,
+ W_CRTC , pr10 , pr10_lock ,
+
+ W_CRTC , pr1b , pr1b_unlock , // PR18, PR19, PR1A, PR36, PR37, PR39, PR41, PR44
+ W_CRTC , pr18 , pr18_s32 ,
+ W_CRTC , pr19 , pr19_s32 ,
+ W_CRTC , pr39 , pr39_s32 ,
+ W_CRTC , pr1a , pr1a_all ,
+ W_CRTC , pr36 , pr36_all ,
+ W_CRTC , pr37 , pr37_s32 ,
+ W_CRTC , pr18a, pr18a_all ,
+// W_CRTC , pr41 , pr41_all ,
+ W_CRTC , pr44 , pr44_all ,
+ W_CRTC , pr1b , pr1b_lock ,
+
+ W_CRTC , pr30 , pr30_unlock , // PR35 (Mapping RAM not initialized)
+// W_CRTC , pr33 , pr33_all ,
+// W_CRTC , pr34 , pr34_all ,
+ W_CRTC , pr35 , pr35_all ,
+ W_CRTC , pr30 , pr30_lock ,
+
+ // Shadow Regs
+ W_CRTC , pr1b , pr1b_unlock_shadow ,// Unlock shadow
+ W_CRTC , 0x11 , crtc11_s32 & 0x7f , // unlock CRTC 0-7
+ W_CRTC , 0x00 , crtc00_s32 ,
+ W_CRTC , 0x02 , crtc02_s32 ,
+ W_CRTC , 0x03 , crtc03_s32 ,
+ W_CRTC , 0x04 , crtc04_s32 ,
+ W_CRTC , 0x05 , crtc05_s32 ,
+ W_CRTC , 0x06 , crtc06_s32 ,
+ W_CRTC , 0x07 , crtc07_s32 ,
+ W_CRTC , 0x09 , 0x00 ,
+ W_CRTC , 0x10 , crtc10_s32 ,
+ W_CRTC , 0x11 , crtc11_s32 , // lock CRTC 0-7
+ W_CRTC , 0x15 , crtc15_s32 ,
+ W_CRTC , 0x16 , crtc16_s32 ,
+ W_CRTC , pr1b , pr1b_lock , // Lock shadow
+
+ END_PVGA
+};
diff --git a/private/ntos/nthals/halppc/ppc/txtpalet.h b/private/ntos/nthals/halppc/ppc/txtpalet.h
new file mode 100644
index 000000000..307464362
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/txtpalet.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+
+txtpalet.h
+
+ Author: Jess Botts
+
+ This file contains the text mode palette. Most of the entries are 0
+ because they are not used. The first 8 entries are used for all
+ background colors and normal intensity foregound colors. Background
+ colors are displayed at normal intensity only. The 8 entries that
+ begin at the 56th entry are used for high intensity foreground colors.
+
+ Each entry consists of 3 values, 1 for each color gun.
+
+******************************************************************************/
+
+UCHAR
+ TextPalette[] =
+ { /*
+ Line
+ R G B R G B R G B R G B Index
+ */
+
+// all background colors and normal intensity foregound colors
+
+ 0, 0, 0, 0, 0, 32, 0, 32, 0, 0, 32, 32, // 0
+ 32, 0, 0, 32, 0, 32, 32, 32, 0, 32, 32, 32,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+// high intensity foreground colors
+
+ 16, 16, 16, 0, 0, 63, 0, 63, 0, 0, 63, 63, // 56
+ 63, 0, 0, 63, 0, 63, 63, 63, 0, 63, 63, 63,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+/*****************************************************************************/
diff --git a/private/ntos/nthals/halppc/ppc/x86bios.c b/private/ntos/nthals/halppc/ppc/x86bios.c
new file mode 100644
index 000000000..06317109b
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/x86bios.c
@@ -0,0 +1,359 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+ULONG
+x86BiosGetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+x86BiosSetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+extern PUCHAR HalpShadowBuffer;
+extern ULONG HalpPciMaxBuses;
+extern ULONG HalpInitPhase;
+
+
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+
+ if (x86BiosExecuteInterruptShadowedPci((UCHAR)BiosCommand,
+ &Context,
+ (PVOID)HalpIoControlBase,
+ (PVOID)(HalpShadowBuffer - 0xc0000),
+ (PVOID)HalpIoMemoryBase,
+ (UCHAR)HalpPciMaxBuses,
+ x86BiosGetPciDataByOffset,
+ x86BiosSetPciDataByOffset
+ ) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+}
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ ULONG VideoDeviceBusNumber,
+ ULONG VideoDeviceSlotNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ BiosAddress - If the BIOS is shadowed, this will be a pointer to
+ non-paged pool. If the BIOS is not shadowed, this
+ should be HalpIoMemoryBase + C0000.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If I/O Ports or I/O memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return;
+ }
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBiosShadowedPci(HalpIoControlBase,
+ (PVOID)(HalpShadowBuffer - 0xc0000),
+ (PVOID)HalpIoMemoryBase,
+ (UCHAR)HalpPciMaxBuses,
+ x86BiosGetPciDataByOffset,
+ x86BiosSetPciDataByOffset
+ );
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ // This context specifies where to find the PCI video device in the
+ // format explained in the PCI BIOS Specification.
+ Context.Eax = (VideoDeviceBusNumber << 8) | (VideoDeviceSlotNumber << 3);
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ if (x86BiosInitializeAdapterShadowedPci(0xc0000,
+ &Context,
+ (PVOID)HalpIoControlBase,
+ (PVOID)(HalpShadowBuffer - 0xc0000),
+ (PVOID)HalpIoMemoryBase,
+ (UCHAR)HalpPciMaxBuses,
+ x86BiosGetPciDataByOffset,
+ x86BiosSetPciDataByOffset
+ ) != XM_SUCCESS) {
+
+
+
+ HalpEnableInt10Calls = FALSE;
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+ return;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
+
+ULONG
+x86BiosGetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function is a wrapper. It exists because we don't have
+ a consistent interface to PCI config space during the boot
+ process.
+
+--*/
+{
+
+ if (HalpInitPhase == 0) {
+ return HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ } else {
+ return HalGetBusDataByOffset(PCIConfiguration,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+}
+
+ULONG
+x86BiosSetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function is a wrapper. It exists because we don't have
+ a consistent interface to PCI config space during the boot
+ process.
+
+--*/
+{
+ if (HalpInitPhase == 0) {
+ return HalpPhase0SetPciDataByOffset(BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ } else {
+ return HalSetBusDataByOffset(PCIConfiguration,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+}
+
+
diff --git a/private/ntos/nthals/halppc/sources b/private/ntos/nthals/halppc/sources
new file mode 100644
index 000000000..d58b5d3af
--- /dev/null
+++ b/private/ntos/nthals/halppc/sources
@@ -0,0 +1,106 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revision Histoy:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halppc
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+
+!IF $(PPC)
+TARGETTYPE=HAL
+!ELSE
+TARGETTYPE=DRIVER
+!ENDIF
+
+C_DEFINES=-DDAKOTA -DSANDALFOOT -DSOFT_HDD_LAMP -D_HALNVR_
+
+INCLUDES=..\x86new;$(BASEDIR)\private\ntos\inc
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxsiosup.c \
+ ppc\pxmemctl.c \
+ ppc\pxpcisup.c \
+ ppc\pxdisp.c \
+ ppc\pxp91.c \
+ ppc\pxshadbf.s \
+ ppc\pxwd.c \
+ ppc\pxs3.c \
+ ppc\pxbbl.c \
+ ppc\pxbl.c \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxenviro.c \
+ ppc\pxmapio.c \
+ ppc\pxsysint.c \
+ ppc\pxtime.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxintsup.s \
+ ppc\pxintrpt.c \
+ ppc\pxinithl.c \
+ ppc\pxport.c \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\fwnvr.c \
+ ppc\pxflshio.c \
+ ppc\pxintmod.c \
+ ppc\pxpcibrd.c \
+ ppc\pxinfo.c \
+ ppc\x86bios.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(PPC)
+NTTARGETFILES=$(TARGETPATH)\ppc\hal.lib
+!ENDIF
diff --git a/private/ntos/nthals/halps/hal.rc b/private/ntos/nthals/halps/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halps/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halps/makefile b/private/ntos/nthals/halps/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halps/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halps/ppc/ctrlops.c b/private/ntos/nthals/halps/ppc/ctrlops.c
new file mode 100644
index 000000000..d6419aa5f
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/ctrlops.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\ctrlops.c>
diff --git a/private/ntos/nthals/halps/ppc/fwnvr.c b/private/ntos/nthals/halps/ppc/fwnvr.c
new file mode 100644
index 000000000..34ac6b7a6
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/fwnvr.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\fwnvr.c>
diff --git a/private/ntos/nthals/halps/ppc/mk48time.c b/private/ntos/nthals/halps/ppc/mk48time.c
new file mode 100644
index 000000000..c8af7cb9e
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/mk48time.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\mk48time.c>
diff --git a/private/ntos/nthals/halps/ppc/pcibios.c b/private/ntos/nthals/halps/ppc/pcibios.c
new file mode 100644
index 000000000..63cbc3092
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pcibios.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pcibios.c>
diff --git a/private/ntos/nthals/halps/ppc/pxbeep.c b/private/ntos/nthals/halps/ppc/pxbeep.c
new file mode 100644
index 000000000..11eef682e
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxbeep.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxbeep.c>
diff --git a/private/ntos/nthals/halps/ppc/pxbusdat.c b/private/ntos/nthals/halps/ppc/pxbusdat.c
new file mode 100644
index 000000000..4eb375ea6
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxbusdat.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxbusdat.c>
diff --git a/private/ntos/nthals/halps/ppc/pxcache.s b/private/ntos/nthals/halps/ppc/pxcache.s
new file mode 100644
index 000000000..464a93823
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxcache.s
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxcache.s>
diff --git a/private/ntos/nthals/halps/ppc/pxcalstl.c b/private/ntos/nthals/halps/ppc/pxcalstl.c
new file mode 100644
index 000000000..7b5e7048c
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxcalstl.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxcalstl.c>
diff --git a/private/ntos/nthals/halps/ppc/pxclksup.s b/private/ntos/nthals/halps/ppc/pxclksup.s
new file mode 100644
index 000000000..3bb344c2b
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxclksup.s
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxclksup.s>
diff --git a/private/ntos/nthals/halps/ppc/pxclock.c b/private/ntos/nthals/halps/ppc/pxclock.c
new file mode 100644
index 000000000..140008534
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxclock.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxclock.c>
diff --git a/private/ntos/nthals/halps/ppc/pxdakota.h b/private/ntos/nthals/halps/ppc/pxdakota.h
new file mode 100644
index 000000000..597c7d413
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxdakota.h
@@ -0,0 +1,57 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxdakota.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Dakota memory controllers.
+
+--*/
+
+
+//
+// define stuctures for memory control and planar register
+//
+
+
+
+typedef struct _DAKOTA_CONTROL {
+ UCHAR Reserved0[0x803]; // Offset 0x000
+ UCHAR SimmId; // Offset 0x803
+ UCHAR SimmPresent; // Offset 0x804
+ UCHAR Reserved1[3];
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[3];
+ UCHAR Keylock; // Offset 0x818
+ UCHAR Reserved7[3];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved8[3];
+ UCHAR MemoryController; // Offset 0x820
+ UCHAR MemoryControllerTiming; // Offset 0x821
+ UCHAR Reserved9[0x16];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR Reserved10[3];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR Reserved11[3];
+ UCHAR MemoryParityErrorStatus; // Offset 0x840
+ UCHAR MemoryParityErrorClear; // Offset 0x841
+ UCHAR L2CacheErrorStatus; // Offset 0x842
+ UCHAR L2CacheErrorClear; // Offset 0x843
+ UCHAR TransferErrorStatus; // Offset 0x844
+ UCHAR TransferErrorClear; // Offset 0x845
+ UCHAR Reserved12[0xa];
+ UCHAR IoMap; // Offset 0x850
+ UCHAR Reserved13[3];
+} DAKOTA_CONTROL, *PDAKOTA_CONTROL;
diff --git a/private/ntos/nthals/halps/ppc/pxdat.c b/private/ntos/nthals/halps/ppc/pxdat.c
new file mode 100644
index 000000000..9036550ff
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxdat.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxdat.c>
diff --git a/private/ntos/nthals/halps/ppc/pxdisp.c b/private/ntos/nthals/halps/ppc/pxdisp.c
new file mode 100644
index 000000000..e476e5e83
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxdisp.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxdisp.c>
diff --git a/private/ntos/nthals/halps/ppc/pxds1385.c b/private/ntos/nthals/halps/ppc/pxds1385.c
new file mode 100644
index 000000000..6164c0faa
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxds1385.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxds1385.c>
diff --git a/private/ntos/nthals/halps/ppc/pxenviro.c b/private/ntos/nthals/halps/ppc/pxenviro.c
new file mode 100644
index 000000000..bb67da576
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxenviro.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxenviro.c>
diff --git a/private/ntos/nthals/halps/ppc/pxflshbf.s b/private/ntos/nthals/halps/ppc/pxflshbf.s
new file mode 100644
index 000000000..358b5de88
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxflshbf.s
@@ -0,0 +1,117 @@
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (C) 1991-1995 Microsoft Corporation
+//
+// Copyright (C) 1994,1995 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxflshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a Power PC
+// system.
+//
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+//
+// Used PowerPC eieio instruction to flush writes
+//
+//--
+
+#include "kxppc.h"
+
+
+// SBTTL("Flush Write Buffer")
+//
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ eieio // synchronize I/O
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpSynchronizeExecution()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSynchronizeExecution)
+
+ sync // synchronize
+
+ LEAF_EXIT(HalpSynchronizeExecution)
+
+
+//
+//++
+//
+// VOID
+// HalpSetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+// HashedPageTableSize is unused because we ASSUME that the HPT is 64K
+//
+
+ LEAF_ENTRY(HalpSetSDR1)
+
+ mtsdr1 r.3
+
+ LEAF_EXIT(HalpSetSDR1)
diff --git a/private/ntos/nthals/halps/ppc/pxflshio.c b/private/ntos/nthals/halps/ppc/pxflshio.c
new file mode 100644
index 000000000..50fe4eb28
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxflshio.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxflshio.c>
diff --git a/private/ntos/nthals/halps/ppc/pxhwsup.c b/private/ntos/nthals/halps/ppc/pxhwsup.c
new file mode 100644
index 000000000..af734beb1
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxhwsup.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxhwsup.c>
diff --git a/private/ntos/nthals/halps/ppc/pxidle.c b/private/ntos/nthals/halps/ppc/pxidle.c
new file mode 100644
index 000000000..edd5c4520
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxidle.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxidle.c>
diff --git a/private/ntos/nthals/halps/ppc/pxinfo.c b/private/ntos/nthals/halps/ppc/pxinfo.c
new file mode 100644
index 000000000..5c76d0b6c
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxinfo.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxinfo.c>
diff --git a/private/ntos/nthals/halps/ppc/pxinithl.c b/private/ntos/nthals/halps/ppc/pxinithl.c
new file mode 100644
index 000000000..48149828a
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxinithl.c
@@ -0,0 +1,384 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInitializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+
+--*/
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxsystyp.h"
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPciConfigSize;
+
+ULONG
+HalpSizeL2Cache(
+ VOID
+ );
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+VOID
+HalpCopyROMs(
+ VOID
+ );
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+VOID
+HalpEnableBridgeSettings(
+ VOID
+ );
+
+VOID
+HalpCheckHardwareRevisionLevels(
+ VOID
+ );
+
+VOID
+HalpDumpHardwareState(
+ VOID
+ );
+
+VOID
+HalpEnableL2Cache(
+ VOID
+ );
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ extern KSPIN_LOCK NVRAM_Spinlock;
+ PKPRCB Prcb;
+
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ if (Prcb->Number == 0)
+ HalpSetSystemType( LoaderBlock );
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ //
+ // Get access to I/O space, check if I/O space has already been
+ // mapped by debbuger initialization.
+ //
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+ //
+ // Initialize the display adapter. Must be done early
+ // so KeBugCheck() will be able to display
+ //
+ if (!HalpInitializeDisplay(LoaderBlock))
+ return FALSE;
+
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Initialize Spinlock for NVRAM
+ //
+
+ KeInitializeSpinLock( &NVRAM_Spinlock );
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_MP_PPC_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#endif
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // Calibrate execution stall
+ //
+ HalpCalibrateStall();
+
+ //
+ // Compute size of PCI Configuration Space mapping
+ //
+ HalpPciConfigSize = PAGE_SIZE * ((1 << (HalpPciMaxSlots-2)) + 1);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+
+ }
+
+ //
+ // InitializeInterrupts
+ //
+
+ if (!HalpInitializeInterrupts())
+
+ return FALSE;
+
+ //
+ // return success
+ //
+
+ return TRUE;
+
+
+ } else {
+
+ if (Phase != 1)
+ return(FALSE);
+
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+
+ HalpRegisterInternalBusHandlers ();
+
+
+ if (!HalpAllocateMapBuffer()) {
+ return FALSE;
+ }
+
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+
+ if (!HalpMapIoSpace()) {
+ return FALSE;
+ }
+
+ if (!HalpCreateSioStructures()) {
+ return FALSE;
+ }
+
+ HalpCheckHardwareRevisionLevels();
+ HalpEnableL2Cache();
+ HalpEnableBridgeSettings();
+ HalpDumpHardwareState();
+ HalpCopyROMs();
+
+ return TRUE;
+
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized. In order to access the PCR from this
+ routine, use the PCRsprg1 macro, not the PCR macro.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG IcacheSize, DcacheSize;
+ ULONG CacheBlockAlignment;
+
+ switch (HalpGetProcessorVersion() >> 16) {
+
+ case 1: // 601
+ IcacheSize = 32*1024;
+ DcacheSize = 32*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 3: // 603
+ IcacheSize = 8*1024;
+ DcacheSize = 8*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 6: // 603e
+ case 7: // 603ev
+ case 4: // 604
+ IcacheSize = 16*1024;
+ DcacheSize = 16*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 9: // 604+
+ IcacheSize = 32*1024;
+ DcacheSize = 32*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ default:
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+
+
+ PCRsprg1->FirstLevelIcacheSize = IcacheSize;
+ PCRsprg1->FirstLevelDcacheSize = DcacheSize;
+ PCRsprg1->DcacheAlignment = CacheBlockAlignment;
+ PCRsprg1->IcacheAlignment = CacheBlockAlignment;
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halps/ppc/pxintsup.s b/private/ntos/nthals/halps/ppc/pxintsup.s
new file mode 100644
index 000000000..98c676fb5
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxintsup.s
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxintsup.s>
diff --git a/private/ntos/nthals/halps/ppc/pxirql.c b/private/ntos/nthals/halps/ppc/pxirql.c
new file mode 100644
index 000000000..3889d1b8c
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxirql.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxirql.c>
diff --git a/private/ntos/nthals/halps/ppc/pxisabus.c b/private/ntos/nthals/halps/ppc/pxisabus.c
new file mode 100644
index 000000000..524dfa8ef
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxisabus.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxisabus.c>
diff --git a/private/ntos/nthals/halps/ppc/pxl2.s b/private/ntos/nthals/halps/ppc/pxl2.s
new file mode 100644
index 000000000..a45f5dd6f
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxl2.s
@@ -0,0 +1,183 @@
+//
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// PXL2.S
+//
+// Abstract:
+//
+// This module implements the routines to size the L2 cache
+// on PowerStack based system.
+//
+// Author:
+//
+// Karl Rusnock (karl_rusnock@phx.mcd.mot.com)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 08-Dec-95 kjr Created this file for MCG PowerStack 2 Systems.
+//
+
+#include "kxppc.h"
+#include "halppc.h"
+
+ .extern HalpIoControlBase
+ .set HID0, 1008
+//
+// L2 cache sizes:
+//
+ .set L2_SIZE, 0x3 // Bits 1..0 (LE bit order)
+ .set L2_1M, 0x2
+ .set L2_512K, 0x0
+ .set L2_256K, 0x1
+ .set L2_LINE_SIZE, 32
+
+ .set CacheSize, r.3 // Return value
+ .set L2CONFIG, r.9
+ .set ISA, r.10 // Pointer to ISA I/O space
+
+//***********************************************************************
+//
+// Synopsis:
+// ULONG HalpSizeL2(VOID)
+//
+// Purpose:
+// Sizes the L2 cache.
+//
+// Returns:
+// Size of L2 cache or zero if not installed.
+// Valid sizes are 256, 512, and 1024.
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+
+
+ LEAF_ENTRY(HalpSizeL2)
+
+//
+// Get ptr to Bridge I/O (ISA bus)
+//
+ lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA,0(ISA)
+
+ lbz r.0, 0x823(ISA) // Cache Configuration Register.
+
+ andi. r.0, r.0, L2_SIZE // Isolate L2 size field
+ cmpi 0,0, r.0, L2_SIZE // L2 Cache Not Present?
+ li CacheSize, 0
+ beq L2_Exit
+
+ li CacheSize, 256
+ cmpi 0,0,r.0, L2_256K
+ beq L2_Exit
+
+ li CacheSize, 512
+ cmpi 0,0,r.0, L2_512K
+ beq L2_Exit
+
+ li CacheSize, 1024
+
+L2_Exit:
+
+//
+// r.3 = cache size in KB
+//
+ LEAF_EXIT(HalpSizeL2)
+
+
+//***********************************************************************
+//
+// Synopsis:
+// VOID HalpFlushAndDisableL2(VOID)
+//
+// Purpose:
+// Assumes that the L2 is enabled and in WRITE-THROUGH mode.
+// The L2 is invalidated and disabled.
+//
+// Returns:
+// nothing
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+
+
+ LEAF_ENTRY(HalpFlushAndDisableL2)
+
+ mfspr r.9, HID0 // Lock the Icache
+ ori r.0, r.9, 0x2000
+ mtspr HID0, r.0
+ isync
+
+ li r.3, 0xC0 // Bits controlling L2
+ lwz ISA, [toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA, 0(ISA)
+
+ lbz r.5, 0x81C(ISA) // Read System Control Register.
+ andc r.5, r.5, r.3 // Set bits to disable L2.
+ stb r.5, 0x814(ISA) // Invalidate L2 first.
+ stb r.5, 0x81C(ISA) // Disable L2 second.
+ stb r.5, 0x814(ISA) // Invalidate L2 again, to be safe.
+ lbz r.5, 0x81C(ISA) // Synchronize with I/O.
+ sync
+
+ mtspr HID0, r.9 // Unlock the Icache
+
+ LEAF_EXIT(HalpFlushAndDisableL2)
+
+
+//***********************************************************************
+//
+// Synopsis:
+// VOID HalpFlushAndEnableL2(VOID)
+//
+// Purpose:
+// Assumes that the L2 is Disabled.
+// The L2 is invalidated and enabled.
+//
+// Returns:
+// nothing
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+
+
+ LEAF_ENTRY(HalpFlushAndEnableL2)
+
+ mfspr r.9, HID0 // Lock the Icache
+ ori r.0, r.9, 0x2000
+ mtspr HID0, r.0
+ isync
+
+ li r.3, 0xC0 // Bits controlling L2
+ lwz ISA, [toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA, 0(ISA)
+
+ lbz r.5, 0x81C(ISA) // Read System Control Register.
+ or r.5, r.5, r.3 // Set bits to disable L2.
+ stb r.5, 0x814(ISA) // Invalidate L2 first.
+ stb r.5, 0x81C(ISA) // Enable L2 second.
+ lbz r.5, 0x81C(ISA) // Synchronize with I/O.
+ sync
+
+ mtspr HID0, r.9 // Unlock the Icache
+
+ LEAF_EXIT(HalpFlushAndEnableL2)
+
diff --git a/private/ntos/nthals/halps/ppc/pxmapio.c b/private/ntos/nthals/halps/ppc/pxmapio.c
new file mode 100644
index 000000000..110871d90
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxmapio.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxmapio.c>
diff --git a/private/ntos/nthals/halps/ppc/pxmemctl.c b/private/ntos/nthals/halps/ppc/pxmemctl.c
new file mode 100644
index 000000000..73cdad933
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxmemctl.c
@@ -0,0 +1,1132 @@
+
+/*++
+
+Copyright (C) 1990-1995 Microsoft Corporation
+
+Copyright (C) 1994,1995 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxdakota.h"
+#include "arccodes.h"
+
+
+VOID HalDisplayString(PUCHAR String);
+ULONG HalpGetHID0(VOID);
+VOID HalpSetHID0(ULONG Value);
+BOOLEAN HalpStrCmp( char *, char *);
+VOID HalpEnableL2Cache(VOID);
+ULONG HalpSizeL2Cache(VOID);
+extern ULONG HalpSizeL2(VOID);
+BOOLEAN HalpInitPlanar(VOID);
+BOOLEAN HalpMapPlanarSpace(VOID);
+VOID HalpFlushAndEnableL2(VOID);
+VOID HalpFlushAndDisableL2(VOID);
+VOID HalpEnableBridgeSettings(VOID);
+VOID HalpEnable_HID0_Settings(VOID);
+VOID HalpCheckHardwareRevisionLevels(VOID);
+VOID HalpDumpHardwareState(VOID);
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+#define PCI_CONFIG_SIZE 0x00800000
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpStrCmp)
+#pragma alloc_text(INIT,HalpInitPlanar)
+#pragma alloc_text(INIT,HalpMapPlanarSpace)
+#pragma alloc_text(INIT,HalpEnableL2Cache)
+#pragma alloc_text(INIT,HalpSizeL2Cache)
+#pragma alloc_text(INIT,HalpEnableBridgeSettings)
+#pragma alloc_text(INIT,HalpEnable_HID0_Settings)
+#pragma alloc_text(INIT,HalpCheckHardwareRevisionLevels)
+#endif
+
+#define NEGATECHAR '~'
+
+#define BridgeIndexRegister ((PULONG) (((PUCHAR) HalpIoControlBase) + 0xcf8))
+#define BridgeDataRegister (((ULONG) HalpIoControlBase) + 0xcfc)
+
+#define HalpReadBridgeUlong(Port) \
+ (*BridgeIndexRegister = (Port), __builtin_eieio(), *((PULONG) BridgeDataRegister))
+
+#define HalpWriteBridgeUlong(Port, Value) \
+ (*BridgeIndexRegister = (Port), *((PULONG) BridgeDataRegister) = (Value), __builtin_sync())
+
+#define HalpReadBridgeUshort(Port) \
+ (*BridgeIndexRegister = (Port), __builtin_eieio(), *((PUSHORT)(BridgeDataRegister+(Port&0x2))))
+
+#define HalpWriteBridgeUshort(Port, Value) \
+ (*BridgeIndexRegister = (Port), *((PUSHORT)(BridgeDataRegister+(Port&0x2))) = (Value), __builtin_sync())
+
+#define HalpReadBridgeUchar(Port) \
+ (*BridgeIndexRegister = (Port), __builtin_eieio(), *((PUCHAR)(BridgeDataRegister+(Port&0x3))))
+
+#define HalpWriteBridgeUchar(Port, Value) \
+ (*BridgeIndexRegister = (Port), *((PUCHAR)(BridgeDataRegister+(Port&0x3))) = (Value), __builtin_sync())
+
+
+#define HalpDisplayHex32(Num, Buf) HalpDisplayHex( 32, Num, Buf)
+#define HalpDisplayHex16(Num, Buf) HalpDisplayHex( 16, Num, Buf)
+#define HalpDisplayHex8(Num, Buf) HalpDisplayHex( 8, Num, Buf)
+
+VOID HalpDisplayHex(
+ ULONG NoBits,
+ ULONG Number,
+ IN PUCHAR Buffer
+)
+{ int Bits;
+
+ for (Bits=NoBits-4; Bits >= 0; Bits -=4) {
+ *Buffer++ = (UCHAR) ((((Number >> Bits) & 0xF) > 9) ?
+ ((Number >> Bits) & 0xF) - 10 + 'A' :
+ ((Number >> Bits) & 0xF) + '0');
+ }
+ *Buffer++ = '.';
+ *Buffer++ = '\n';
+ *Buffer++ = '\0';
+
+}
+
+
+UCHAR HalpUpperCase(UCHAR c)
+{
+ if (c >= 'a' && c <= 'z')
+ c -= 'a'-'A';
+ return c;
+}
+
+
+//
+// Routine Description:
+//
+// This routine is a helper routine for parameter parsing.
+// It compares UpperCase of String1 to UpperCase of String2.
+//
+// Return Value
+//
+// TRUE if strings match; otherwise FALSE
+//
+
+BOOLEAN HalpStrCmp( char *String0, char *String1 )
+{
+char *tmp0, *tmp1;
+
+ tmp0 = String0;
+ tmp1 = String1;
+ while( (*tmp0 = toupper( *tmp0 )) && (*tmp1 = toupper( *tmp1 )) )
+ {
+ tmp0++; tmp1++;
+ }
+ return( strcmp(String0, String1) == 0 );
+}
+
+
+// Oem Output Display function filter noise if OEM or quite
+
+VOID OemDisplayString (
+ PUCHAR String
+ )
+
+{
+#define BUF_LEN 120
+UCHAR CharBuffer[BUF_LEN];
+
+ if(HalGetEnvironmentVariable("HALREPORT",sizeof(CharBuffer),&CharBuffer[0]) == ESUCCESS) {
+ if(HalpStrCmp("YES", CharBuffer)) {
+ HalDisplayString(String);
+ }
+ } else {
+ if(HalGetEnvironmentVariable("MOT-OEM-ID",sizeof(CharBuffer),&CharBuffer[0]) != ESUCCESS) {
+ HalDisplayString(String);
+ }
+ }
+}
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+ USHORT CpuRevision, CpuType;
+ UCHAR BridgeRevision, c;
+ UCHAR CharBuffer[20], i;
+
+ OemDisplayString("\nHAL: Motorola PowerStack 2 Systems.");
+ OemDisplayString("\nHAL: Version 2.37 5/24/96.");
+
+ CpuType = (USHORT)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+
+ OemDisplayString("\nHAL: Processor is a 6");
+ i = 0;
+ switch (CpuType) {
+ case 1:
+ case 3:
+ case 4:
+ CharBuffer[i++] = '0';
+ CharBuffer[i++] = (UCHAR)(CpuType) + '0';
+ break;
+
+ case 6:
+ CharBuffer[i++] = '0';
+ CharBuffer[i++] = '3';
+ CharBuffer[i++] = 'e';
+ break;
+
+ case 7:
+ CharBuffer[i++] = '0';
+ CharBuffer[i++] = '3';
+ CharBuffer[i++] = 'e';
+ CharBuffer[i++] = 'v';
+ break;
+
+ case 9:
+ CharBuffer[i++] = '0';
+ CharBuffer[i++] = '4';
+ CharBuffer[i++] = 'e';
+ CharBuffer[i++] = 'v';
+ break;
+
+ case 20:
+ CharBuffer[i++] = '2';
+ CharBuffer[i++] = '0';
+ break;
+
+ default:
+ CharBuffer[i++] = '?';
+ CharBuffer[i++] = '?';
+ break;
+ }
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ OemDisplayString(" revision ");
+ i = 0;
+ c = (UCHAR)((CpuRevision >> 8) & 0xf);
+ CharBuffer[i++] = c + '0';
+ CharBuffer[i++] = '.';
+ if (c = (UCHAR)((CpuRevision >> 4) & 0xf))
+ CharBuffer[i++] = c + '0';
+ c = (UCHAR)(CpuRevision & 0xf);
+ CharBuffer[i++] = c + '0';
+ CharBuffer[i++] = '.';
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ OemDisplayString("\nHAL: Bridge 27-82660 revision ");
+ BridgeRevision = HalpReadBridgeUchar(0x80000008);
+ i = 0;
+ CharBuffer[i++] = (UCHAR) (BridgeRevision >> 4) + '0';
+ CharBuffer[i++] = '.';
+ CharBuffer[i++] = (UCHAR) (BridgeRevision & 0x0F) + '0';
+ CharBuffer[i++] = '.';
+ CharBuffer[i++] = '\n';
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ return TRUE;
+}
+
+char *
+MyStrtok (
+ char * string,
+ const char * control
+ )
+{
+ unsigned char *str;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+
+ static char *nextoken;
+
+ /* Clear control map */
+ for (count = 0; count < 32; count++)
+ map[count] = 0;
+
+ /* Set bits in delimiter table */
+ do {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ } while (*ctrl++);
+
+ /* Initialize str. If string is NULL, set str to the saved
+ * pointer (i.e., continue breaking tokens out of the string
+ * from the last strtok call) */
+ if (string)
+ str = string;
+ else
+ str = nextoken;
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets str to point to the terminal
+ * null (*str == '\0') */
+ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
+ str++;
+
+ string = str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *str ; str++ )
+ if ( map[*str >> 3] & (1 << (*str & 7)) ) {
+ *str++ = '\0';
+ break;
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+ nextoken = str;
+
+ /* Determine if a token has been found. */
+ if ( string == str )
+ return NULL;
+ else
+ return string;
+}
+
+
+VOID
+HalpEnableBridgeSettings(
+ VOID
+ )
+{
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ BOOLEAN Negate;
+ ULONG StatusRegister;
+ volatile ULONG ErrorAddress;
+
+#define SetBridgeUchar( Clear, Offset, Val ) \
+ SetBridgeReg(Clear, Offset, Val, HalpReadBridgeUchar, HalpWriteBridgeUchar);
+
+#define SetBridgeUshort( Clear, Offset, Val ) \
+ SetBridgeReg(Clear, Offset, Val, HalpReadBridgeUshort, HalpWriteBridgeUshort);
+
+#define SetBridgeUlong( Clear, Offset, Val ) \
+ SetBridgeReg(Clear, Offset, Val, HalpReadBridgeUlong, HalpWriteBridgeUlong);
+
+#define SetBridgeReg( Clear, Offset, Val, GetReg, SetReg) \
+{ \
+ if (Clear) { \
+ SetReg(Offset, GetReg(Offset) & ~Val); \
+ } else { \
+ SetReg(Offset, GetReg(Offset) | Val); \
+ } \
+}
+
+ //
+ // MOTKJR - Errata 19 from the Errata Summary Revision 1.3 says:
+ // The error handling logic incorrectly detects EIEIO as a CPU transfer type error.
+ // Always mask CPU transfer type errors (Error Enable 1 bit 0).
+ //
+ StatusRegister = HalpReadBridgeUchar(0x800000C0); // Clear CPU Transfer type error enable bit.
+ HalpWriteBridgeUchar(0x800000C0, ~0x01 & (UCHAR)(StatusRegister));
+
+ //
+ // The environment variable "BRIDGESETTINGS" is defined as:
+ // Matching a string serves to enable that feature while a tilde (~)
+ // immediately before the parameter string indicates that it is to be disabled.
+ //
+
+ if ((HalGetEnvironmentVariable("BRIDGESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) ||
+ (HalGetEnvironmentVariable("EAGLESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS)) {
+
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") ) {
+
+ Negate = FALSE;
+
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ }
+
+ if (HalpStrCmp("PCI_PARITY", Value)) {
+ SetBridgeUshort( Negate, 0x80000004, 0x0040 );
+ }
+ else if (HalpStrCmp("SERR", Value)) {
+ SetBridgeUshort( Negate, 0x80000004, 0x0140 );
+ }
+ else if (HalpStrCmp("MCP_EN", Value) || HalpStrCmp("MCP", Value)) {
+ SetBridgeUchar( Negate, 0x800000BA, 0x01 );
+ }
+ else if (HalpStrCmp("TEA_EN", Value) || HalpStrCmp("TEA", Value)) {
+ SetBridgeUchar( Negate, 0x800000BA, 0x02 );
+ }
+ else if (HalpStrCmp("PCI_ISA_IO_MAPPING", Value)) {
+ SetBridgeUchar( Negate, 0x800000BA, 0x04 );
+ }
+ else if (HalpStrCmp("POWER_MANAGEMENT", Value)) {
+ SetBridgeUchar( Negate, 0x800000BB, 0x02 );
+ }
+ else if (HalpStrCmp("CPU_TRANSFER_TYPE", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x01 );
+ }
+ else if (HalpStrCmp("PARITY", Value) || HalpStrCmp("MEMORY", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x04 );
+ }
+ else if (HalpStrCmp("SINGLE_BIT_ECC", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x04 );
+ }
+ else if (HalpStrCmp("MULTI_BIT_ECC", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x08 );
+ }
+ else if (HalpStrCmp("SELECT", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x20 );
+ }
+ else if (HalpStrCmp("SERR_WHEN_PERR", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x40 );
+ }
+ else if (HalpStrCmp("TARGET_ABORT", Value)) {
+ SetBridgeUchar( Negate, 0x800000C0, 0x80 );
+ }
+ else if (HalpStrCmp("CPU_DATA_BUS_PARITY", Value)) {
+ SetBridgeUchar( Negate, 0x800000C4, 0x04 );
+ }
+ else if (HalpStrCmp("L2_PARITY", Value) || HalpStrCmp("L2", Value)) {
+ SetBridgeUchar( Negate, 0x800000C4, 0x08 );
+ }
+ else if (HalpStrCmp("MASTER_ABORT", Value)) {
+ SetBridgeUchar( Negate, 0x800000C4, 0x10 );
+ }
+ else if (HalpStrCmp("ECC", Value) || HalpStrCmp("MEMORY_ERROR_CHECKING", Value)) {
+ SetBridgeUchar( Negate, 0x800000D4, 0x01 );
+ SetBridgeUchar( Negate, 0x800000C0, 0x08 );
+ }
+ else if (HalpStrCmp("MEMORY_DRAM", Value)) {
+ SetBridgeUchar( Negate, 0x800000D4, 0x04 );
+ }
+ else if (HalpStrCmp("L2_SRAM", Value)) {
+ SetBridgeUchar( Negate, 0x800000D4, 0x08 );
+ }
+ else if (HalpStrCmp("MCP_MODE", Value)) {
+ SetBridgeUchar( Negate, 0x800000D4, 0x10 );
+ }
+ else if (HalpStrCmp("EXTERNAL_REGISTER", Value)) {
+ SetBridgeUchar( Negate, 0x800000D4, 0x20 );
+ }
+ else if (HalpStrCmp("BROADCAST_SNOOP", Value)) {
+ SetBridgeUchar( Negate, 0x800000D4, 0x80 );
+ } else {
+ HalDisplayString("HAL: Error in BRIDGESETTINGS environment variable: ");
+ HalDisplayString(CharBuffer);
+ HalDisplayString("\n");
+ }
+ } // End for
+ } // End If
+
+ //
+ // Clear the error address register and L2 Cache Error register.
+ //
+
+ ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister);
+ StatusRegister = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->L2CacheErrorClear);
+
+ HalpWriteBridgeUchar(0x800000C1, 0xFF); // Clear Error Detection Register 1.
+ HalpWriteBridgeUchar(0x800000C5, 0xFF); // Clear Error Detection Register 2.
+ StatusRegister = HalpReadBridgeUshort(0x80000006); // Get any Un-documented Status bits.
+ HalpWriteBridgeUshort(0x80000006, 0xF900 | (USHORT)(StatusRegister)); // Clear Device Status Register.
+
+ //
+ // Initialize the PowerPC HID0 register here,
+ // before we clear the detection bits in the Kauai/Lanai.
+ // Otherwise we can miss the MCP pin signal transition.
+ //
+ HalpEnable_HID0_Settings(); // Setup HID0 register.
+}
+
+
+ULONG
+HalpSizeL2Cache(
+ VOID
+ )
+{
+ return (HalpSizeL2());
+}
+
+
+VOID
+HalpEnableL2Cache(
+ VOID
+ )
+{
+ BOOLEAN Negate;
+ int i;
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ UCHAR L2_Parameter[BUF_LEN];
+ UCHAR ControlByte;
+
+ //
+ // Parse the environment variable "L2"
+ //
+
+ if (HalGetEnvironmentVariable("L2", BUF_LEN, &CharBuffer[0]) == ESUCCESS) {
+
+ // Copy L2 environment variable
+ i = 0;
+ while (L2_Parameter[i] = CharBuffer[i]) {
+ i++;
+ }
+
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") )
+ {
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ } else
+ Negate = FALSE;
+
+ // Check for L2 = "OFF"
+ if (HalpStrCmp( "OFF", Value ))
+ {
+ OemDisplayString("HAL: L2 cache is disabled via environment variable L2\n");
+ HalpFlushAndDisableL2();
+ PCR->SecondLevelDcacheSize = PCR->SecondLevelIcacheSize = 0;
+ return;
+ }
+ // Check for WriteThrough
+ else if ( HalpStrCmp( "WT", Value ) || HalpStrCmp( "ON", Value ))
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+
+ //
+ // Enable L2 cache on Kauai / Lanai.
+ //
+ HalpFlushAndEnableL2();
+
+ } else {
+
+ParseError: HalDisplayString("HAL: Error in L2 environment variable: ");
+ HalDisplayString(L2_Parameter);
+ HalDisplayString("\n illegal parameter begins here ");
+ for (i = 0; i < Value - CharBuffer; i++)
+ HalDisplayString("\304");
+ HalDisplayString("^\n");
+ break;
+ }
+
+ } // End for
+ } // End If
+
+ return;
+}
+
+VOID
+HalpEnable_HID0_Settings(
+ VOID
+ )
+{
+ USHORT CpuRevision, CpuType;
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ ULONG HidEnable, HidDisable, CurrentHID0;
+ BOOLEAN Negate;
+
+#define HID_MCP (0x80000000)
+#define HID_CACHE (0x40000000)
+#define HID_ADDRESS (0x20000000)
+#define HID_DATA (0x10000000)
+#define HID_PAR (0x01000000)
+#define HID_DPM (0x00100000)
+#define HID_FBIOB (0x00000010)
+#define HID_BHT (0x00000004)
+#define HID_NOOPTI (0x00000001)
+
+#define SetCPUMask( Disable, Val ) \
+{ \
+ if (Disable) \
+ HidDisable |= Val; \
+ else \
+ HidEnable |= Val; \
+}
+
+ CpuType = (USHORT)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+
+ HidEnable = 0;
+ HidDisable = 0;
+ CurrentHID0 = HalpGetHID0();
+
+ switch (CpuType) {
+ case 7: // 603ev
+ //
+ // Work-around for early parts.
+ //
+ CurrentHID0 |= HID_NOOPTI;
+
+ case 3: // 603
+ case 6: // 603e
+ //
+ // Enable Dynamic Power Management
+ //
+ CurrentHID0 |= HID_DPM;
+ break;
+
+ case 4: // 604
+ case 9: // 604e
+ //
+ // Enable L1 Cache Parity Checking
+ //
+ CurrentHID0 |= HID_CACHE;
+ break;
+ }
+
+ //
+ // Set the default CPU Parity Checking.
+ // This default can be platform dependent.
+ //
+
+ CurrentHID0 |= HID_MCP;
+
+ //
+ // The environment variable "HID0SETTINGS" is defined either as:
+ // "CACHE", "ADDRESS", "DATA", "MCP", "DPM" with either blank or semi-colon
+ // characters used as separators. Matching a string serves to enable
+ // that feature while a tilde (~) immediately before the parameter
+ // string indicates that it is to be disabled.
+ //
+
+ if (HalGetEnvironmentVariable("HID0SETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) {
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") ) {
+
+ Negate = FALSE;
+
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ }
+
+ if (HalpStrCmp("MCP", Value)) {
+ SetCPUMask(Negate, HID_MCP);
+ } else if (HalpStrCmp("ADDRESS", Value)) {
+ SetCPUMask(Negate, HID_ADDRESS);
+ } else if (HalpStrCmp("DATA", Value)) {
+ SetCPUMask(Negate, HID_DATA);
+ } else if (HalpStrCmp("PAR", Value)) {
+ SetCPUMask(Negate, HID_PAR);
+ } else if (HalpStrCmp("BHT", Value)) {
+ SetCPUMask(Negate, HID_BHT);
+ } else if (HalpStrCmp("CACHE", Value)) {
+ SetCPUMask(Negate, HID_CACHE);
+ } else if (HalpStrCmp("DPM", Value)) {
+ SetCPUMask(Negate, HID_DPM);
+ } else if (HalpStrCmp("FBIOB", Value)) {
+ SetCPUMask(Negate, HID_FBIOB);
+ } else if (HalpStrCmp("NOOPTI", Value)) {
+ SetCPUMask(Negate, HID_NOOPTI);
+ } else {
+
+ HalDisplayString("HAL: Error in HID0SETTINGS environment variable: ");
+ HalDisplayString(CharBuffer);
+ HalDisplayString("\n");
+ }
+ } // End While
+ } // End If
+
+ //
+ // Check for inconsistencies in HID0SETTINGS
+ //
+ if (HidEnable & HidDisable) {
+ HalDisplayString("HAL: Inconsistent settings in HID0SETTINGS environment variable.\n");
+ HalDisplayString(" Disable setting will override enable setting.\n");
+ //
+ // Enforce DISABLE override ENABLE
+ //
+ HidEnable &= ~HidDisable;
+ }
+
+ //
+ // Disable and Enable the bits in the HID0 register.
+ //
+ CurrentHID0 &= ~HidDisable; // Disable bits first.
+ HalpSetHID0(CurrentHID0);
+
+ CurrentHID0 |= HidEnable; // Enable Bits last.
+ HalpSetHID0(CurrentHID0);
+}
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map the error address register
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = ERROR_ADDRESS_REGISTER;
+ HalpErrorAddressRegister = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL || HalpErrorAddressRegister == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map the PCI config space.
+ //
+
+ physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE;
+ HalpPciConfigBase = MmMapIoSpace(physicalAddress,
+ PCI_CONFIG_SIZE,
+ FALSE);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map the PCI config space.
+ //
+
+ HalpPciConfigBase = (PUCHAR)KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Unmap the PCI config space and set HalpPciConfigBase to NULL.
+ //
+
+ KePhase0DeleteIoMap(PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+ HalpPciConfigBase = NULL;
+
+}
+
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+ UCHAR TextAddress[20];
+ USHORT DeviceStatus;
+
+ //
+ // Read the error address register first
+ //
+
+ ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister);
+
+ //
+ // Convert error address to HEX characters
+ //
+
+ HalpDisplayHex32(ErrorAddress, TextAddress );
+
+ DeviceStatus = HalpReadBridgeUshort(0x80000006);
+ if (DeviceStatus & 0x8100)
+ HalDisplayString("\n27-82660: Status Register: PARITY Error Detected.\n");
+ if (DeviceStatus & 0x4000)
+ HalDisplayString("\n27-82660: Status Register: SERR asserted.\n");
+
+// MOTKJR 08/22/95 - Don't check for the following bit.
+// It is always set when NT scans the slots on the PCI bus.
+// if (DeviceStatus & 0x2000)
+// HalDisplayString("\n27-82660: Status Register: Transaction terminated with master-abort.\n");
+
+ if (DeviceStatus & 0x1000)
+ HalDisplayString("\n27-82660: Status Register: Transaction terminated by target-abort while master.\n");
+ if (DeviceStatus & 0x0800)
+ HalDisplayString("\n27-82660: Status Register: Transaction terminated by target-abort while slave.\n");
+
+ //
+ // Check TEA conditions
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->MemoryParityErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("27-82660: Memory Parity Error at Address ");
+ HalDisplayString (TextAddress);
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->L2CacheErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("27-82660: L2 Cache Parity Error\n");
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->TransferErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("27-82660: Transfer Error at Address ");
+ HalDisplayString (TextAddress);
+ }
+
+ //
+ // Check the Error Status 1 Register
+ //
+
+ StatusByte = HalpReadBridgeUchar(0x800000C1);
+
+ if (StatusByte & 0x03)
+ HalDisplayString("27-82660: CPU Transfer Error.\n");
+
+ if (StatusByte & 0x04)
+ HalDisplayString("27-82660: Memory Parity Error.\n");
+
+ if (StatusByte & 0x08)
+ HalDisplayString("27-82660: Memory Multi-bit ECC Error.\n");
+
+ if (StatusByte & 0x20)
+ HalDisplayString("27-82660: Memory Select Error.\n");
+
+ if (StatusByte & 0x40)
+ HalDisplayString("27-82660: PCI Data Bus Parity Error or PCI_SERR asserted.\n");
+
+ //
+ // Check the Error Status 2 Register
+ //
+
+ StatusByte = HalpReadBridgeUchar(0x800000C5);
+
+ if (StatusByte & 0x04)
+ HalDisplayString("27-82660: CPU Data Bus Parity Error.\n");
+
+ if (StatusByte & 0x08)
+ HalDisplayString("27-82660: L2 Parity Error.\n");
+
+ //
+ // Check the PCI Bus Error Status Register
+ //
+
+ StatusByte = HalpReadBridgeUchar(0x800000C7);
+
+ if (StatusByte & 0x10)
+ HalDisplayString("27-82660: PCI cycle with 82660 Bridge as target.\n");
+
+#if DBG
+ //
+ // We have had a catastrophic hardware malfunction.
+ // Dump the state of the Bridge and HID 0 registers.
+ //
+ HalDisplayString("\n");
+ HalpDumpHardwareState();
+#endif
+}
+
+
+VOID
+HalpCheckHardwareRevisionLevels(
+ VOID
+ )
+{
+ USHORT CpuRevision, CpuType;
+ UCHAR BridgeRevision;
+ UCHAR CharBuffer[20], i;
+ ARC_STATUS Status;
+
+ CpuType = (USHORT)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+ BridgeRevision = HalpReadBridgeUchar(0x80000008);
+
+ //
+ // Minimum hardware requirements:
+ // 660 Bridge: v1.1 or greater
+ // 603 or 604: v3.2 or greater
+ // 603e: v1.4 or greater
+ // 603ev: any CPU revision
+ // 601, 604e, 620: any CPU revision
+ //
+ if (BridgeRevision >= 0x01) {
+ switch (CpuType) {
+ case 3: // 603
+ case 4: // 604
+ if (CpuRevision >= 0x0302)
+ return;
+ break;
+
+ case 6: // 603e
+ if (CpuRevision >= 0x0104)
+ return;
+ break;
+
+ case 1: // 601
+ case 7: // 603ev
+ case 9: // 604e
+ case 20: // 620
+ default:
+ return;
+ }
+ }
+
+ //
+ // If the environment variable BOOTOLDHARDWARE exists
+ // (value is a don't care), then try to boot anyway.
+ //
+ Status = HalGetEnvironmentVariable("BOOTOLDHARDWARE", 5, CharBuffer);
+ if (Status == ESUCCESS || Status == ENOMEM)
+ return;
+
+ HalDisplayString("HAL: Unsupported CPU and/or Bridge revision level.");
+
+ //
+ // Bug check - after stalling to allow
+ // any information printed on the screen
+ // to be read and seen by the user.
+ //
+ for (i=0; i<15; i++) {
+ HalDisplayString(".");
+ KeStallExecutionProcessor(1000000);
+ }
+
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+}
+
+
+VOID HalpDumpHardwareState(VOID)
+{ ULONG BridgeRegister, HID0;
+ UCHAR CharBuffer[12];
+
+#if DBG
+
+ if ( HalGetEnvironmentVariable("DBG_HAL", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) {
+
+ BridgeRegister = HalpReadBridgeUshort(0x80000004);
+ HalDisplayString("HAL: Bridge register 04 = 0x");
+ HalpDisplayHex16(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUshort(0x80000006);
+ HalDisplayString("HAL: Bridge register 06 = 0x");
+ HalpDisplayHex16(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000A0);
+ HalDisplayString("HAL: Bridge register A0 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000A1);
+ HalDisplayString("HAL: Bridge register A1 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000A2);
+ HalDisplayString("HAL: Bridge register A2 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000B1);
+ HalDisplayString("HAL: Bridge register B1 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000BA);
+ HalDisplayString("HAL: Bridge register BA = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000BB);
+ HalDisplayString("HAL: Bridge register BB = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000C0);
+ HalDisplayString("HAL: Bridge register C0 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000C1);
+ HalDisplayString("HAL: Bridge register C1 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000C3);
+ HalDisplayString("HAL: Bridge register C3 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000C4);
+ HalDisplayString("HAL: Bridge register C4 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000C5);
+ HalDisplayString("HAL: Bridge register C5 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000C7);
+ HalDisplayString("HAL: Bridge register C7 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUlong(0x800000C8);
+ HalDisplayString("HAL: Bridge register C8 = 0x");
+ HalpDisplayHex32(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ BridgeRegister = HalpReadBridgeUchar(0x800000D4);
+ HalDisplayString("HAL: Bridge register D4 = 0x");
+ HalpDisplayHex8(BridgeRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ HID0 = HalpGetHID0();
+ HalDisplayString("HAL: PowerPC Register HID0 = 0x");
+ HalpDisplayHex32(HID0, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ HalDisplayString("HAL: PCR Virtual Address - sprg1 = 0x");
+ HalpDisplayHex32((ULONG)PCRsprg1, CharBuffer );
+ HalDisplayString(CharBuffer);
+ }
+
+#endif
+
+}
diff --git a/private/ntos/nthals/halps/ppc/pxmisc.s b/private/ntos/nthals/halps/ppc/pxmisc.s
new file mode 100644
index 000000000..e7014c025
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxmisc.s
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxmisc.s>
diff --git a/private/ntos/nthals/halps/ppc/pxpcibrd.c b/private/ntos/nthals/halps/ppc/pxpcibrd.c
new file mode 100644
index 000000000..d9b36ce5d
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxpcibrd.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxpcibrd.c>
diff --git a/private/ntos/nthals/halps/ppc/pxpcibus.c b/private/ntos/nthals/halps/ppc/pxpcibus.c
new file mode 100644
index 000000000..ef86e6e28
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxpcibus.c
@@ -0,0 +1,2289 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpcibus.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+extern ULONG HalpPciMaxSlots;
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+#if 0
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+#endif
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ // direct Method.
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ // indirect Method.
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ //
+ // Allow access all 32 devices per bus.
+ //
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if 0
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if 0
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ //DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+#define ATIBUG 1
+#if ATIBUG
+ USHORT VendorId;
+ LONG Len;
+#endif
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+#if ATIBUG
+//
+// Temporary Hack (MOTKJR) - We have discovered a problem between the ATI
+// Video Driver and the NCR 810/825 SCSI parts. The NCR chip has hardware
+// registers in Configuration Space above 0x40 which have a side effect that
+// a read from these registers is destructive to its contents. If a SCSI
+// operation is active when these registers are read, the NCR device will
+// abort the operation and further I/O is impossible. Therefore, we will
+// not allow anyone to read from Offset 0x40 to 0xFF for any PCI slot that
+// has an NCR vendor ID number. Care must be taken to check for requests
+// which overlap both the PCI Common Header and the Device Dependent area.
+//
+#define NCR_VENDOR_ID 0x1000
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &VendorId, 0x0, sizeof(VendorId),
+ PCIConfigHandler.ConfigRead);
+
+ if ((VendorId == NCR_VENDOR_ID) && (Offset + Length > PCI_COMMON_HDR_LENGTH)) {
+ Len = PCI_COMMON_HDR_LENGTH - Offset;
+ if (Len < 0)
+ Len = 0;
+ RtlFillMemory ((PVOID)((PUCHAR)Buffer+Len), Length-Len, (UCHAR) -1);
+ if (Offset >= PCI_COMMON_HDR_LENGTH)
+ return;
+ Length = Len;
+ }
+#endif
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.bits.DeviceNumber)
+ + 0x100 * Slot.u.bits.FunctionNumber;
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ if ((PciCfg1->u.bits.BusNumber = BusHandler->BusNumber) == 0) {
+
+ // This hack is to maintain device number compatibility
+ // on bus 0 with the Type1 functions. We do this so that
+ // the installed base maintains the same "slot" numbering.
+ // The notable issue is with network interfaces where the
+ // slot number is stored in the registry at install time.
+ // It was judged too subtle and too painful to have everyone
+ // reinstall networking if they added a bridged device to
+ // their system.
+
+ int MappedDev;
+ ULONG Offset;
+ #define PRESHIFT 9 // Make invalid slot numbers to map to dev 0.
+ // Dev 0 is inaccessible from the 27-82660 Bridge.
+
+ // Get the offset from the Type1 (direct mapping) offset table.
+ // If the device number isn't "valid", use an offset that won't
+ // actually end up selecting any device.
+
+ Offset = (Slot.u.bits.DeviceNumber < HalpPciMaxSlots) ?
+ HalpPciConfigSlot[Slot.u.bits.DeviceNumber] : (1 << (PRESHIFT+1));
+
+ // Determine the device number accessed by the "offset".
+ // If bit 11 is set, MappedDev = 11; bit 12, MappedDev = 12;...
+
+ Offset >>= PRESHIFT;
+ MappedDev = PRESHIFT - 1;
+
+ do {
+ MappedDev++;
+ Offset >>= 1;
+
+ } while (Offset);
+
+ // The 27-82660 docs say to set the device number field to
+ // 10 less than the PCI Address bit number.
+
+ PciCfg1->u.bits.DeviceNumber = MappedDev - 10;
+
+ } else {
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ }
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_UCHAR ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i,*Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_USHORT ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + (USHORT) i,*((PUSHORT)Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData,*((PULONG)Buffer));
+ return sizeof(ULONG);
+}
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+//*BJ* PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ *BaseAddress[RomIndex] &= ~0x7ff;
+
+ //
+ // Rom Base Address resource is not enabled, as the ROM code cannot
+ // be executed on a risk box, and the algorithm below interprets
+ // the card's Rom Base Address requirements incorrectly
+ //
+
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ m = 0;
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m |= PCI_ENABLE_IO_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ m |= PCI_ENABLE_MEMORY_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Set addresses, but do not turn on decodes
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (!(*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) &&
+ (Is64BitBaseAddress(*BaseAddress[j]))) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ // enable IO & Memory decodes (use HalSetBusData since valid settings now set)
+
+ // Set Bus master bit on for win95 compatability
+ m |= PCI_ENABLE_BUS_MASTER;
+
+ PciData->Command |= (USHORT) m;
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halps/ppc/pxpciint.c b/private/ntos/nthals/halps/ppc/pxpciint.c
new file mode 100644
index 000000000..0160a0c96
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxpciint.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxpciint.c>
diff --git a/private/ntos/nthals/halps/ppc/pxpcisup.c b/private/ntos/nthals/halps/ppc/pxpcisup.c
new file mode 100644
index 000000000..abf5bc95f
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxpcisup.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxpcisup.c>
diff --git a/private/ntos/nthals/halps/ppc/pxport.c b/private/ntos/nthals/halps/ppc/pxport.c
new file mode 100644
index 000000000..d6ca10d1f
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxport.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxport.c>
diff --git a/private/ntos/nthals/halps/ppc/pxpower.s b/private/ntos/nthals/halps/ppc/pxpower.s
new file mode 100644
index 000000000..cb0822573
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxpower.s
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxpower.s>
diff --git a/private/ntos/nthals/halps/ppc/pxproc.c b/private/ntos/nthals/halps/ppc/pxproc.c
new file mode 100644
index 000000000..91b9dc338
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxproc.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxproc.c>
diff --git a/private/ntos/nthals/halps/ppc/pxprof.c b/private/ntos/nthals/halps/ppc/pxprof.c
new file mode 100644
index 000000000..e04f3f9bd
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxprof.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxprof.c>
diff --git a/private/ntos/nthals/halps/ppc/pxreset.s b/private/ntos/nthals/halps/ppc/pxreset.s
new file mode 100644
index 000000000..d328bf4a3
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxreset.s
@@ -0,0 +1,433 @@
+//++
+//
+// Copyright (C) 1993-1995 IBM Corporation
+//
+// Copyright (C) 1994-1995 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxreset.s
+//
+// Abstract:
+//
+// This module implements the routine HalpPowerPcReset, which can be
+// used to return the PowerPC to Big Endian with cache flushed and
+// branches to the rom based machine reset handler.
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//
+//--
+
+#include "kxppc.h"
+
+ .set C_LINE_SZ, 64
+ .set C_LINE_CNT, 64
+ .set C_SETS, 8
+
+ .set C_SIZE, C_LINE_SZ * C_LINE_CNT * C_SETS
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+
+
+ .set H0_603_DCE, 0x4000 // 603 Data Cache Enable
+ .set H0_603_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set H0_603_ICFI, 0x0800 // 603 I-Cache Flash Invalidate
+
+ .set H0_604_DCE, 0x4000 // 604 Data Cache Enable
+ .set H0_604_ICE, 0x8000 // 604 Instruction Cache Enable
+ .set H0_604_DCIA, 0x0400 // 604 I-Cache Invalidate All
+ .set H0_604_ICIA, 0x0800 // 604 I-Cache Invalidate All
+
+ .set TLB_CLASSES_601, 128 // 601 tlb has 128 congruence classes
+ .set TLB_CLASSES_603, 32 // 603 tlb has 32 congruence classes
+ .set TLB_CLASSES_604, 64 // 604 tlb has 64 congruence classes
+
+ LEAF_ENTRY(HalpPowerPcReset)
+ LWI(r.4, 0xfff00100) // address of rom reset handler
+ mfspr r.5, HID0
+ mfpvr r.31 // determine processor type
+ li r.6, 0
+ li r.7, 0x92
+ oris r.7, r.7, 0x8000
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts
+ mtmsr r.8
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ //
+ // invalidate all tlb entries
+ //
+
+ li r.3, TLB_CLASSES_601 // use largest known number of
+ // congruence classes
+ mtctr r.3 // number of classes = iteration count
+zaptlb: tlbie r.3 // invalidate tlb congruence class
+ addi r.3, r.3, 4096 // increment to next class address
+ bdnz zaptlb // loop through all classes
+
+ srwi r.31, r.31, 16 // isolate processor type
+ cmpwi r.31, 1 // is 601?
+
+ bl here // get current address
+here:
+ mflr r.9 // (r.9) = &here
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+ bne not_601
+
+ //
+ // processor is a 601
+ //
+
+ rlwinm r.5, r.5, 0, ~(0x0008) // turn off little endian
+
+ //
+ // disable instruction and data relocation and switch
+ // interrupt prefix to fetch from ROM
+ //
+
+ andi. r.8, r.8, ~DISABLES & 0xffff
+ ori r.8, r.8, MASK_SPR(MSR_IP,1)
+ mtsrr1 r.8 // this will also be target state
+ nop // for rfi
+
+//
+// Ensure all code from 'cachem' to 'end_little' is in cache by loading a
+// byte in each address line in that range.
+
+ addi r.9, r.9, cachem-here // (r.9) = physical &cachem
+
+ // r.9 now contains the physical address of cachem. (assuming
+ // this code was loaded as part of kernel which is loaded at
+ // physical 0 = virtual 0x80000000). We effect the switch to
+ // physical addressing thru an rfi with the target state set
+ // to resume at cachem with relocation and interrupts disabled.
+
+ mtsrr0 r.9 // address of cachem for rfi
+ addi r.10, r.9, end_little-cachem // (r.10) = &end_little
+ addi r.11, r.9, HalpPowerPcReset.end-cachem // (r.11) = &reset_end
+
+ addi r.12, r.9, -C_LINE_SZ // bias addr for 1st iteration by
+ // amount added by lbzu prior to load
+
+ rfi // switch
+cachem:
+ lbzu r.13, C_LINE_SZ(r.12) // get byte at (r.13)+C_LINE_SZ
+ cmplw r.12, r.10 // bumping r.12 by C_LINE_SZ
+ addi r.13, r.13, 1 // ensure load completed.
+ blt cachem // get all in range here-end_little.
+
+ mtsrr0 r.4 // set rom reset target for next rfi
+ lis r.9, 0x87f0 // Segment register base 0x87f00000
+ li r.10, 0xf // Set all 16 segment registers
+ li r.11, 0
+ mtibatl 0, r.6 // zero bat 0-3 upper and lower
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+setsr: rlwimi r.11, r.10, 28, 0, 3 // Shift segment reg. # to bits 0-3
+ or r.12, r.9, r.10 // Segment register value 0x87f000sr
+ mtsrin r.12, r.11
+ addic. r.10, r.10, -1 // Next segment register
+ bne setsr
+ mtsr 0, r.9 // Set the last segment register
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ sync // quiet the machine down
+ sync
+ sync
+ sync
+ stb r.6, 0(r.7) // switch memory
+ eieio // flush io
+ sync
+ sync
+ sync
+ sync
+ mtspr HID0, r.5 // switch ends on the cpu
+ sync
+ sync
+ sync
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ rfi // head off into the reset handler
+end_little:
+ addi r.0, r.1, 0x138 // we never get here
+ addi r.0, r.1, 0x138
+
+ b $
+
+//
+// For the 603 (and hopefully other) processor(s) things are a little
+// easier because little-endianness is controlled by the MSR. We still
+// have to change memory seperately so we still want code from the memory
+// switch thru the cpu switch in cache.
+//
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.5 contains HID0 present value.
+// r.6 contains 0.
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the physical address of "here"
+// r.31 contains the processor type
+
+
+not_601:
+ cmpwi r.31, 3 // is 603?
+ beq is_603
+ cmpwi r.31, 6 // is 603+?
+ beq is_603
+ cmpwi r.31, 7 // is 603ev?
+ beq is_603
+
+ cmpwi cr.2, r.31, 4 // is 604?
+ cmpwi cr.3, r.31, 9 // is 604+?
+ b not_603
+
+//
+// 603 I-Cache is invalidated by setting ICFI in HID0. Unlike
+// the 604, this bit is not self clearing.
+//
+
+is_603: rlwinm r.5, r.5, 0, ~H0_603_DCE// turn off D-cache
+ rlwinm r.10, r.5, 0, ~H0_603_ICE// turn off I-cache
+ ori r.10, r.10, H0_603_ICFI // I-Cache Flash Invalidate
+ ori r.5, r.5, H0_603_ICE // I-cache enable
+ isync
+ mtspr HID0, r.10 // invalidate/disable
+ mtspr HID0, r.5 // enable
+ b common_6034
+
+not_603:
+ beq cr.2, is_604
+// bne not_604
+
+// Note: the above branch is commented out because we don't
+// currently have any other options,... 620 will probably
+// be different.
+
+
+is_604: tlbsync // wait all processor tlb invalidate
+
+//
+// 604 caches must be enabled in order to be invalidated. It
+// is acceptable to enable and invalidate with the same move
+// to hid0. The data cache will be left disabled, the instruction
+// cache enabled.
+//
+
+ ori r.5, r.5, H0_604_DCE | H0_604_ICE
+ ori r.10, r.5, H0_604_DCIA | H0_604_ICIA
+
+ rlwinm r.5, r.5, 0, ~H0_604_DCE
+ rlwinm r.5, r.5, 0, ~H0_604_DCIA
+ rlwinm r.5, r.5, 0, ~H0_604_ICIA
+
+ mtspr HID0, r.10 // enable + invalidate
+ mtspr HID0, r.5 // disable data cache
+
+ rlwinm r.10, r.5, 0, ~H0_604_ICE // disable i-cache later
+
+// b common_6034 // join common code
+
+
+//
+// The following is common to both 603 and 604
+//
+
+common_6034:
+
+//
+// MSR bits ILE and POW must be disabled via mtmsr as rfi only moves
+// the least significant 16 bits into the MSR.
+//
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1) // -= Data Relocation
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_POW,1) // -= Power Management
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_ILE,1) // -= Interrupt Little Endian
+ sync
+ mtmsr r.8
+ sync
+
+//
+// Try to issue a hard reset. If this fails, the fall
+// thru and continue to manually return to firmware.
+//
+
+ addi r.5, r.0, 0xFF // All ones
+ stb r.5, 0(r.7) // Reset the System
+ sync
+ sync
+ sync
+ sync
+
+//
+// Continue returning to firmware...
+//
+
+//
+// Use an rfi to switch to big-endian, untranslated, interrupt prefix on
+// with a target address in the nice harmless pallindromic code below.
+// use another rfi to branch to the rom resident reset handler.
+//
+
+ li r.8, MASK_SPR(MSR_ME,1) | MASK_SPR(MSR_IP,1)
+ addi r.9, r.9, uncached_6034-here
+ mtsrr1 r.8 // state = Machine Check Enabled
+ bl here2
+here2: mflr r.28
+ rlwinm r.28, r.28, 0, 0x7fffffff // convert address to physical
+ lwz r.29, endofroutine - here2(r.28)
+ mtsrr0 r.9 // rfi to uncached_6034
+ b jumpswap
+
+memoryswap:
+ ori r.8, r.28, 0
+ addi r.8, r.8, swapend - uncached_6034
+ addis r.15, r.15, 0
+ addi r.9, 0, 0
+ addi r.15, r.15, swapend - uncached_6034
+ addis r.14, 0, 0
+ addi r.14, 0, 4
+swaploop:
+ lwz r.11, 0(r.8)
+ lwz r.12, 4(r.8)
+ stwbrx r.11, r.14, r.8
+ stwbrx r.12, 0, r.8
+ addi r.8, r.8, 8
+ subi r.15, r.15, 8
+ cmpi 0, 0, r.15, 0
+ bgt swaploop
+
+jumpswap:
+
+//
+// The following bizzareness is to ensure that the memory switch thru
+// the disabling of cache is in cache. There is less than 32 bytes so
+// they must be part of either the cache line we are currently in, or
+// the one at the target of the branch. Therefore, branching over them,
+// doing a little and branching back to them should be enough to enure
+// they're cache resident.
+//
+
+ b fill_icache
+goto_bigendian:
+ stb r.6, 0(r.7) // switch memory
+ sync
+ sync
+ sync
+ sync
+ sync
+ lwz r.30, endofroutine - here2(r.28)
+ cmp 0, 0, r.29, r.30
+ beq memoryswap
+ rfi
+fill_icache:
+ isync
+ sync // complete everything!
+ b goto_bigendian
+
+ .align 5
+ .globl uncached_6034
+ .long uncached_6034
+
+uncached_6034:
+ .big_endian // out of cache fetches must be
+ // assembled in same mode as processor
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsrr0 r.4 // rfi target = 0xfff00100
+ mtspr HID0, r.10 // DISABLE CACHING
+ mtibatl 0, r.6 // invalidate/clear all bats
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+ mtdbatl 0, r.6
+ mtdbatu 0, r.6
+ mtdbatl 1, r.6
+ mtdbatu 1, r.6
+ mtdbatl 2, r.6
+ mtdbatu 2, r.6
+ mtdbatl 3, r.6
+ mtdbatu 3, r.6
+ mtsr 0, r.6
+ mtsr 1, r.6
+ mtsr 2, r.6
+ mtsr 3, r.6
+ mtsr 4, r.6
+ mtsr 5, r.6
+ mtsr 6, r.6
+ mtsr 7, r.6
+ mtsr 8, r.6
+ mtsr 9, r.6
+ mtsr 10, r.6
+ mtsr 11, r.6
+ mtsr 12, r.6
+ mtsr 13, r.6
+ mtsr 14, r.6
+ mtsr 15, r.6
+ rfi // go to machine reset handler
+ // never get here
+ .little_endian
+endofroutine:
+ sync
+ .globl swapend
+ .long swapend
+swapend:
+
+ LEAF_EXIT(HalpPowerPcReset)
diff --git a/private/ntos/nthals/halps/ppc/pxreturn.c b/private/ntos/nthals/halps/ppc/pxreturn.c
new file mode 100644
index 000000000..812168de2
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxreturn.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxreturn.c>
diff --git a/private/ntos/nthals/halps/ppc/pxsiosup.c b/private/ntos/nthals/halps/ppc/pxsiosup.c
new file mode 100644
index 000000000..ab763410f
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxsiosup.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxsiosup.c>
diff --git a/private/ntos/nthals/halps/ppc/pxstall.s b/private/ntos/nthals/halps/ppc/pxstall.s
new file mode 100644
index 000000000..b22d5550b
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxstall.s
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxstall.s>
diff --git a/private/ntos/nthals/halps/ppc/pxsysbus.c b/private/ntos/nthals/halps/ppc/pxsysbus.c
new file mode 100644
index 000000000..c3d901bd9
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxsysbus.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxsysbus.c>
diff --git a/private/ntos/nthals/halps/ppc/pxsysint.c b/private/ntos/nthals/halps/ppc/pxsysint.c
new file mode 100644
index 000000000..4c2e8240d
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxsysint.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxsysint.c>
diff --git a/private/ntos/nthals/halps/ppc/pxsystyp.c b/private/ntos/nthals/halps/ppc/pxsystyp.c
new file mode 100644
index 000000000..d80b78b0e
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxsystyp.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxsystyp.c>
diff --git a/private/ntos/nthals/halps/ppc/pxtime.c b/private/ntos/nthals/halps/ppc/pxtime.c
new file mode 100644
index 000000000..fed4558b9
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxtime.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxtime.c>
diff --git a/private/ntos/nthals/halps/ppc/pxusage.c b/private/ntos/nthals/halps/ppc/pxusage.c
new file mode 100644
index 000000000..1c856c8e5
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/pxusage.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\pxusage.c>
diff --git a/private/ntos/nthals/halps/ppc/sysbios.c b/private/ntos/nthals/halps/ppc/sysbios.c
new file mode 100644
index 000000000..9838c5a93
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/sysbios.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\sysbios.c>
diff --git a/private/ntos/nthals/halps/ppc/x86bios.c b/private/ntos/nthals/halps/ppc/x86bios.c
new file mode 100644
index 000000000..62067325c
--- /dev/null
+++ b/private/ntos/nthals/halps/ppc/x86bios.c
@@ -0,0 +1 @@
+#include <..\..\haleagle\ppc\x86bios.c>
diff --git a/private/ntos/nthals/halps/sources b/private/ntos/nthals/halps/sources
new file mode 100644
index 000000000..a6ada9b27
--- /dev/null
+++ b/private/ntos/nthals/halps/sources
@@ -0,0 +1,97 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ Motorola 27-82660 based systems.
+
+
+
+Author:
+
+ Karl Rusnock - 1/8/96
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halps
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+!IF $(PPC)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_HALNVR_
+
+INCLUDES=..\haleagle\ppc;..\x86new;..\..\inc;
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\fwnvr.c \
+ ppc\mk48time.c \
+ ppc\pxbeep.c \
+ ppc\pxbusdat.c \
+ ppc\pxcache.s \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxclock.c \
+ ppc\pxdat.c \
+ ppc\pxdisp.c \
+ ppc\pxds1385.c \
+ ppc\pxenviro.c \
+ ppc\pxflshbf.s \
+ ppc\pxflshio.c \
+ ppc\pxhwsup.c \
+ ppc\pxidle.c \
+ ppc\pxinfo.c \
+ ppc\pxinithl.c \
+ ppc\pxintsup.s \
+ ppc\pxirql.c \
+ ppc\pxisabus.c \
+ ppc\pxl2.s \
+ ppc\pxmapio.c \
+ ppc\pxmemctl.c \
+ ppc\pxmisc.s \
+ ppc\pxpcibrd.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxpcisup.c \
+ ppc\pxport.c \
+ ppc\pxpower.s \
+ ppc\pxproc.c \
+ ppc\pxprof.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxsiosup.c \
+ ppc\pxstall.s \
+ ppc\pxsysbus.c \
+ ppc\pxsysint.c \
+ ppc\pxsystyp.c \
+ ppc\pxtime.c \
+ ppc\pxusage.c \
+ ppc\x86bios.c \
+ ppc\ctrlops.c \
+ ppc\sysbios.c \
+ ppc\pcibios.c
+
+DLLDEF=obj\*\hal.def
+
diff --git a/private/ntos/nthals/halqs/alpha/addrsup.c b/private/ntos/nthals/halqs/alpha/addrsup.c
new file mode 100644
index 000000000..e49bdbc55
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/addrsup.c
@@ -0,0 +1,605 @@
+/*++
+
+Copyright (c) 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the EB66 system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "qsdef.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on EB66 are an ISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if (InterfaceType != Isa &&
+ InterfaceType != Eisa &&
+ InterfaceType != PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+//jnfix - HAE support here
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // IMPORTANT: For now we have set HAE set to zero.
+ //
+ // MAX PCI sparse memory for us is PCI_MAX_SPARSE_MEMORY_ADDRESS=128MB-1
+ // MAX PCI dense memory for us is PCI_MAX_DENSE_MEMORY_ADDRESS=2.5GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply the PCI bus address
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = LCA4_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 16MB (24 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+ // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c)
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ case Eisa: {
+ break;
+ } // case Eisa
+
+ } // switch( InterfaceType )
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciIoPhysical();
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva( *TranslatedAddress,
+ va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI sparse memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = LCA4_PCI_MEMORY_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciIoPhysical();
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Dense space is not supported on Pass 1 LCA4s.
+ //
+
+ if( HalpLca4Revision() == Lca4Pass1 ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return FALSE;
+
+ }
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = HalpLca4PciDensePhysical();
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not a sparse I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PVOID qva;
+
+ //
+ // If the physical address is not in dense space then perform the
+ // QVA shuffle.
+ //
+ // N.B. - Dense space is not supported for Lca4Pass1.
+ //
+
+ if( (HalpLca4Revision() == Lca4Pass1) ||
+ (PA.QuadPart < (LONGLONG)HalpLca4PciDensePhysical()) ){
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+
+ //
+ // It is not a sparse I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For EB66 we have only 2 bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halqs/alpha/adjust.c b/private/ntos/nthals/halqs/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/allstart.c b/private/ntos/nthals/halqs/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/alphaio.s b/private/ntos/nthals/halqs/alpha/alphaio.s
new file mode 100644
index 000000000..d2fe61a53
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/alphaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\alphaio.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/bios.c b/private/ntos/nthals/halqs/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/busdata.c b/private/ntos/nthals/halqs/alpha/busdata.c
new file mode 100644
index 000000000..8195ac8a6
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/busdata.c
@@ -0,0 +1,126 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halqs/alpha/cache.c b/private/ntos/nthals/halqs/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/chipset.h b/private/ntos/nthals/halqs/alpha/chipset.h
new file mode 100644
index 000000000..b5d5b44c3
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/chipset.h
@@ -0,0 +1 @@
+#include "lca4.h"
diff --git a/private/ntos/nthals/halqs/alpha/cmos8k.c b/private/ntos/nthals/halqs/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/ebinitnt.c b/private/ntos/nthals/halqs/alpha/ebinitnt.c
new file mode 100644
index 000000000..46a94e666
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ebinitnt.c
@@ -0,0 +1,749 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a Low Cost Alpha
+ (LCA) system. Contains the VLSI 82C106, the 82357 and an EISA bus.
+
+ Orignally taken from the JENSEN hal code.
+
+Author:
+
+ Wim Colgate (DEC) 26-Oct-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Eric Rehm (DEC) 7-Jan-1994
+ Intialize PCI Bus information during Phase 1 init.
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "qsdef.h"
+#include "halpcsl.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low (All devices except)
+// irql 4 - device high (the serial lines)
+// irql 5 - clock
+// irql 6 - real time
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11 keyboard/mouse
+// 4 serial 12 errors
+// 5 clock 13 parallel
+// 6 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// clock
+// serial
+// parallel
+// keyboard/mouse
+// pic
+
+//
+// This is the HalpIrqlMask for LCA based machines:
+// The LCA interrupt pins:
+//
+// eirq 0 NMI
+// eirq 1 PIC - 82357 interrupts
+// eirq 2 Clock
+
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+//
+
+ADDRESS_USAGE
+QsPCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
+ 0,0
+ }
+};
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpClearInterrupts(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alpha system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Start the peridodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize the EISA and PCI interrupt controllers.
+ //
+
+ HalpInitializePCIInterrupts();
+
+ //
+ // Initialize the 21066 interrupts.
+ //
+ // N.B. - The 21066 uses the 21064 core and so the 21066 HAL
+ // uses 21064 interrupt enable/disable routines.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+ HalpEnable21064HardwareInterrupt( Irq = 0,
+ Irql = HIGH_LEVEL,
+ Vector = EISA_NMI_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = CLOCK_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function no longer does anything.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an LCA
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For LCA, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for LCA is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Clear any error conditions currently pending.
+ //jnfix - report correctables one day
+
+ HalpClearAllErrors( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ HalpRegisterAddressUsage (&QsPCIMemorySpace);
+
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI Bus.
+ //
+
+ HalpInitializePCIBus (LoaderBlock);
+
+ //
+ // Initialize the profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpAcknowledgeClockInterrupt();
+
+ return;
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+
+}
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ // WRITE_REGISTER_ULONG( EPIC_HAXR1_QVA, 0 );
+ // WRITE_REGISTER_ULONG( EPIC_HAXR2_QVA, 0);
+ return;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_LCA_UNCORRECTABLE);
+ *RawSystemInfoSize = 0;
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "QSilver";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_LCA_UNCORRECTABLE processorFrame;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
diff --git a/private/ntos/nthals/halqs/alpha/ebintsup.c b/private/ntos/nthals/halqs/alpha/ebintsup.c
new file mode 100644
index 000000000..a6e9d1a68
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ebintsup.c
@@ -0,0 +1,449 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support QuickSilver system.
+
+Author:
+
+ Robin Alexander (DEC) 13-June-1994
+ Modified from existing Avanti code.
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "qsdef.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+
+//
+// Declare the interrupt handler for the PCI and ISA bus.
+//
+
+BOOLEAN
+HalpSioDispatch(
+ VOID
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpInitializePCIInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ ISA interrupt controller; in the case of the SIO-II in QuickSilver, the
+ integral interrupt controller is compatible with the EISA interrupt
+ contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG PciIsaBridgeHeaderOffset;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ //
+ // Directly connect the ISA interrupt dispatcher to the level for
+ // ISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch;
+ HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive);
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) QSPCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // We must declare the right form for the APECS PCI/ISA bridge
+ // configuration space device selector for use in the initialization
+ // of the interrupts.
+ //
+
+ PciIsaBridgeHeaderOffset = PCI_ISA_BRIDGE_HEADER_OFFSET;
+
+ //
+ // Setup the QuickSilver interrupt assignments for the C-Step SIO; this
+ // is done with registers that are internal to the SIO-II, PIRQ0,
+ // PIRQ1, PIRQ2, and PIRQ3. They're at offsets 0x60, 0x61, 0x62,
+ // and 0x63 of the SIO-II's configuration registers. The effect
+ // of these registers is to steer the PCI interrupts into the IRQx
+ // inputs of the SIO's internal cascaded 82C59 interrupt controllers.
+ // These controllers are then programmed in their usual fashion.
+ //
+ // Set up interrupts from PCI slots 0, 1, and 2, compatible with
+ // QuickSilver pass 1 MLB, i.e., steer the interrupt from each PCI
+ // slot or device into the default IRQL from pass 1 QuickSilver
+ // enable the routings.
+ //
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ0_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ10 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ1_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ15 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ2_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ15 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ //
+ // Set up interrupt from SCSI (IRQ11), and enable the routing.
+ //
+
+ WRITE_CONFIG_UCHAR((PCHAR)(PCI_CONFIGURATION_BASE_QVA
+ | PciIsaBridgeHeaderOffset | PIRQ3_ROUTE_CONTROL),
+ PIRQX_ROUTE_IRQ11 | PIRQX_ROUTE_ENABLE,
+ PCI_CONFIG_CYCLE_TYPE_0);
+
+ //
+ // Select "level" operation for PCI PIRQx interrupt lines, and
+ // "edge" for ISA devices, e.g., mouse at IRQL12. Default is "edge"
+ // so no mention means "edge".
+ //
+
+ WRITE_REGISTER_UCHAR((PCHAR)(PCI_SPARSE_IO_BASE_QVA
+ | SIO_II_EDGE_LEVEL_CONTROL_2),
+ IRQ11_LEVEL_SENSITIVE | IRQ10_LEVEL_SENSITIVE |
+ IRQ15_LEVEL_SENSITIVE);
+
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize SIO NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Sio machine, no extnded nmi information, so just do it.
+ //
+
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the EISA interrupt from the programmable interrupt controller.
+ Return the vector number of the highest priority pending interrupt.
+
+Arguments:
+
+ ServiceContext - Service context of the interrupt service supplies
+ a pointer to the EISA interrupt acknowledge register.
+
+Return Value:
+
+ Return the value of the highest priority pending interrupt.
+
+--*/
+{
+ UCHAR InterruptVector;
+
+ //
+ // Read the interrupt vector from the PIC.
+ //
+
+ InterruptVector = READ_PORT_UCHAR(ServiceContext);
+
+ return( InterruptVector );
+
+}
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB66 comes from the Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halqs/alpha/ebmapio.c b/private/ntos/nthals/halqs/alpha/ebmapio.c
new file mode 100644
index 000000000..35626dfb1
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ebmapio.c
@@ -0,0 +1,158 @@
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This maps I/O addresses used by the HAL on Low Cost Alpha (LCA) machines.
+
+Author:
+
+ Wim Colgate (DEC) 26-Oct-1993
+ Originally taken from the Jensen hal code.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "qsdef.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a LCA based
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map the address spaces on the LCA4.
+ //
+
+ HalpLca4MapAddressSpaces();
+
+ //
+ // Map base addresses into QVA space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( HalpLca4PciIoPhysical() );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+ HalpEisaIntAckBase = HAL_MAKE_QVA( HalpLca4PciIntAckPhysical() );
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Map the address spaces on the LCA4.
+ //
+
+ HalpLca4MapAddressSpaces();
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)(HAL_MAKE_QVA(HalpLca4PciIoPhysical())) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halqs/alpha/ebsgdma.c b/private/ntos/nthals/halqs/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/ebsysint.c b/private/ntos/nthals/halqs/alpha/ebsysint.c
new file mode 100644
index 000000000..2f3cc0a0f
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ebsysint.c
@@ -0,0 +1,394 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Avanti system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "qsdef.h"
+#include "axp21064.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == ISA_DEVICE_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+ We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR
+ //
+
+ return((BusInterruptLevel) + ISA_VECTORS);
+
+ break;
+
+
+
+ default:
+
+ //
+ // Not an interface supported on EB66/Mustang systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Avanti because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halqs/alpha/eisasup.c b/private/ntos/nthals/halqs/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/environ.c b/private/ntos/nthals/halqs/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/ev4cache.c b/private/ntos/nthals/halqs/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/ev4int.c b/private/ntos/nthals/halqs/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/ev4ints.s b/private/ntos/nthals/halqs/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/ev4mem.s b/private/ntos/nthals/halqs/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/ev4parit.c b/private/ntos/nthals/halqs/alpha/ev4parit.c
new file mode 100644
index 000000000..74c6d0d00
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ev4parit.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4parit.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/ev4prof.c b/private/ntos/nthals/halqs/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/fwreturn.c b/private/ntos/nthals/halqs/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/haldebug.c b/private/ntos/nthals/halqs/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/halpal.s b/private/ntos/nthals/halqs/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/idle.s b/private/ntos/nthals/halqs/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/info.c b/private/ntos/nthals/halqs/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/inithal.c b/private/ntos/nthals/halqs/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/intsup.s b/private/ntos/nthals/halqs/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/ioproc.c b/private/ntos/nthals/halqs/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/iousage.c b/private/ntos/nthals/halqs/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/lca4.c b/private/ntos/nthals/halqs/alpha/lca4.c
new file mode 100644
index 000000000..6c2a74470
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/lca4.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lca4.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/lca4err.c b/private/ntos/nthals/halqs/alpha/lca4err.c
new file mode 100644
index 000000000..29b38623e
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/lca4err.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lca4err.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/lcaioacc.s b/private/ntos/nthals/halqs/alpha/lcaioacc.s
new file mode 100644
index 000000000..02bcd070c
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/lcaioacc.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\lcaioacc.s"
+
diff --git a/private/ntos/nthals/halqs/alpha/machdep.h b/private/ntos/nthals/halqs/alpha/machdep.h
new file mode 100644
index 000000000..d145357c4
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/machdep.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include EB66 platform-specific definitions.
+//
+
+#include "lca4.h"
+#include "qsdef.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halqs/alpha/memory.c b/private/ntos/nthals/halqs/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/pcibus.c b/private/ntos/nthals/halqs/alpha/pcibus.c
new file mode 100644
index 000000000..6e9ffd1a9
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pcibus.c
@@ -0,0 +1,99 @@
+/*++
+
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (IN PBUS_HANDLER BusHandler)
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if (ConfigType == PciConfigType0)
+ {
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Device number is mapped to address bits 11:24, which are wired to IDSEL pins.
+ // Note that HalpValidPCISlot has already done bounds checking on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) LCA4_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if HALDBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+ else
+ {
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) LCA4_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+#if HALDBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halqs/alpha/pcisio.c b/private/ntos/nthals/halqs/alpha/pcisio.c
new file mode 100644
index 000000000..cf5f0f462
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pcisio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisio.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/pcisup.c b/private/ntos/nthals/halqs/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/pcrtc.c b/private/ntos/nthals/halqs/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/pcserial.c b/private/ntos/nthals/halqs/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/pcspeakr.c b/private/ntos/nthals/halqs/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/perfcntr.c b/private/ntos/nthals/halqs/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halqs/alpha/pintolin.h b/private/ntos/nthals/halqs/alpha/pintolin.h
new file mode 100644
index 000000000..c83e7ceec
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/pintolin.h
@@ -0,0 +1,175 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang and EB66, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for EB66
+//
+// You can limit init table to MAX_PCI_LOCAL_DEVICES entries.
+// The highest virtual slot between EB66 and Mustang is 9, so
+// MAX_PCI_LOCAL_DEVICE is defined as 9 in the platform dependent
+// header file (MUSTDEF.H). HalpValidPCISlot assures us that
+// we won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 9 = PCI_AD[20].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+//
+// Interrupt Vector Table Mapping for Avanti
+//
+// Avanti PCI interrupts are mapped to ISA IRQs in the table below.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_AVANTI.
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+
+ULONG QSPCIPinToLineTable[][4]=
+{
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0xb, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] SIO
+ { 0xf, 0xf, 0xa, 0xf }, // Virtual Slot 13 = PCI_AD[24] Slot #2
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+ { 0xa, 0xf, 0xf, 0xa }, // Virtual Slot 11 = PCI_AD[22] Slot #0
+ { 0xf, 0xa, 0xf, 0xf }, // Virtual Slot 12 = PCI_AD[23] Slot #1
+};
diff --git a/private/ntos/nthals/halqs/alpha/qsdef.h b/private/ntos/nthals/halqs/alpha/qsdef.h
new file mode 100644
index 000000000..63d2ae4af
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/qsdef.h
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ qsdef.h
+
+Abstract:
+
+ This module specifies platform-specific definitions for the
+ Mustang/EB66 modules.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Revision History:
+
+
+--*/
+
+#ifndef _NONDEF_
+#define _NONDEF_
+
+#include "alpharef.h"
+#include "lca4.h"
+#include "isaaddr.h"
+
+#define NUMBER_ISA_SLOTS 5
+#define NUMBER_PCI_SLOTS 3
+
+// Highest Virtual local PCI Slot.
+// Changed RAA was 13 but this pushes the code over to b000000 i.e AD[24]
+
+#define PCI_MAX_LOCAL_DEVICE 12
+
+// Highest PCI interrupt vector is in PCI vector space
+
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+#define PCI_INTERRUPT_READ_QVA ((PUCHAR)HAL_MAKE_QVA(HalpLca4PciIoPhysical()) + 0x26)
+#define PCI_INTERRUPT_MASK_QVA ((PUCHAR)HAL_MAKE_QVA(HalpLca4PciIoPhysical()) + 0x26)
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (166)
+
+//
+// PCI-E/ISA Bridge chip configuration space base is at physical address
+// 0x1e0000000. The equivalent QVA is:
+// ((0x1e0000000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE
+//
+#define PCI_CONFIGURATION_BASE_QVA 0xaf000000
+#define PCI_SPARSE_IO_BASE_QVA 0xae000000
+#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device
+
+#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00800000 >> IO_BIT_SHIFT) // AD[18]
+
+//#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00040000 >> IO_BIT_SHIFT) // AD[13]
+
+//
+// PCI-ISA Bridge Configuration register offsets.
+//
+#define PCI_VENDOR_ID (0x0000 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_ID (0x0040 >> IO_BIT_SHIFT)
+#define PCI_COMMAND (0x0080 >> IO_BIT_SHIFT)
+#define PCI_DEVICE_STATUS (0x00c0 >> IO_BIT_SHIFT)
+#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT)
+#define PCI_CONTROL (0x0800 >> IO_BIT_SHIFT)
+#define PCI_ARBITER_CONTROL (0x0820 >> IO_BIT_SHIFT)
+#define ISA_ADDR_DECODER_CONTROL (0x0900 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_A (0x09c0 >> IO_BIT_SHIFT)
+#define UTIL_BUS_CHIP_SELECT_ENAB_B (0x09e0 >> IO_BIT_SHIFT)
+#define PIRQ0_ROUTE_CONTROL (0x0c00 >> IO_BIT_SHIFT)
+#define PIRQ1_ROUTE_CONTROL (0x0c20 >> IO_BIT_SHIFT)
+#define PIRQ2_ROUTE_CONTROL (0x0c40 >> IO_BIT_SHIFT)
+#define PIRQ3_ROUTE_CONTROL (0x0c60 >> IO_BIT_SHIFT)
+
+//
+// Values for enabling an IORQ route control setting.
+//
+#define PIRQX_ROUTE_IRQ3 0x03
+#define PIRQX_ROUTE_IRQ4 0x04
+#define PIRQX_ROUTE_IRQ5 0x05
+#define PIRQX_ROUTE_IRQ6 0x06
+#define PIRQX_ROUTE_IRQ7 0x07
+#define PIRQX_ROUTE_IRQ9 0x09
+#define PIRQX_ROUTE_IRQ10 0x0a
+#define PIRQX_ROUTE_IRQ11 0x0b
+#define PIRQX_ROUTE_IRQ12 0x0c
+#define PIRQX_ROUTE_IRQ14 0x0d
+#define PIRQX_ROUTE_IRQ15 0x0f
+#define PIRQX_ROUTE_ENABLE 0x00
+
+//
+// PCI-ISA Bridge Non-Configuration control register offsets.
+//
+#define SIO_II_EDGE_LEVEL_CONTROL_1 (0x9a00 >> IO_BIT_SHIFT)
+#define SIO_II_EDGE_LEVEL_CONTROL_2 (0x9a20 >> IO_BIT_SHIFT)
+
+//
+// SIO-II value for setting edge/level operation in the control words.
+//
+#define IRQ0_LEVEL_SENSITIVE 0x01
+#define IRQ1_LEVEL_SENSITIVE 0x02
+#define IRQ2_LEVEL_SENSITIVE 0x04
+#define IRQ3_LEVEL_SENSITIVE 0x08
+#define IRQ4_LEVEL_SENSITIVE 0x10
+#define IRQ5_LEVEL_SENSITIVE 0x20
+#define IRQ6_LEVEL_SENSITIVE 0x40
+#define IRQ7_LEVEL_SENSITIVE 0x80
+#define IRQ8_LEVEL_SENSITIVE 0x01
+#define IRQ9_LEVEL_SENSITIVE 0x02
+#define IRQ10_LEVEL_SENSITIVE 0x04
+#define IRQ11_LEVEL_SENSITIVE 0x08
+#define IRQ12_LEVEL_SENSITIVE 0x10
+#define IRQ13_LEVEL_SENSITIVE 0x20
+#define IRQ14_LEVEL_SENSITIVE 0x40
+#define IRQ15_LEVEL_SENSITIVE 0x80
+
+#define SIO_II_INIT_COMMAND_1 (0x0400 >> IO_BIT_SHIFT)
+#define SIO_II_INIT_COMMAND_2 (0x1400 >> IO_BIT_SHIFT)
+
+
+
+
+#endif // _NONDEF_
+
diff --git a/private/ntos/nthals/halqs/alpha/vga.c b/private/ntos/nthals/halqs/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halqs/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halqs/drivesup.c b/private/ntos/nthals/halqs/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halqs/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halqs/hal.rc b/private/ntos/nthals/halqs/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halqs/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halqs/hal.src b/private/ntos/nthals/halqs/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halqs/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halqs/makefile b/private/ntos/nthals/halqs/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halqs/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halqs/makefile.inc b/private/ntos/nthals/halqs/makefile.inc
new file mode 100644
index 000000000..f407d02eb
--- /dev/null
+++ b/private/ntos/nthals/halqs/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halqs.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halqs/sources b/private/ntos/nthals/halqs/sources
new file mode 100644
index 000000000..3ccce8802
--- /dev/null
+++ b/private/ntos/nthals/halqs/sources
@@ -0,0 +1,102 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halqs
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3
+C_DEFINES=-DEB66 -DEV4 -DLCA4
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\allstart.c \
+ alpha\alphaio.s \
+ alpha\adjust.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cmos8k.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\environ.c \
+ alpha\ev4cache.c \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev4mem.s \
+ alpha\ev4prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\lca4.c \
+ alpha\lca4err.c \
+ alpha\lcaioacc.s \
+ alpha\memory.c \
+ alpha\pcisio.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\addrsup.c \
+ alpha\busdata.c \
+ alpha\ebinitnt.c \
+ alpha\ebmapio.c \
+ alpha\ebsysint.c \
+ alpha\ebintsup.c \
+ alpha\pcibus.c \
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halr94a/drivesup.c b/private/ntos/nthals/halr94a/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halr94a/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halr94a/hal.rc b/private/ntos/nthals/halr94a/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halr94a/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halr94a/hal.src b/private/ntos/nthals/halr94a/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halr94a/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halr94a/makefile b/private/ntos/nthals/halr94a/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halr94a/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halr94a/makefile.inc b/private/ntos/nthals/halr94a/makefile.inc
new file mode 100644
index 000000000..35bd838fb
--- /dev/null
+++ b/private/ntos/nthals/halr94a/makefile.inc
@@ -0,0 +1,36 @@
+#pragma comment(exestr, "@(#) NEC(MIPS) makefile.inc 1.3 95/10/17 01:16:29" )
+#
+# Revision History
+#
+
+mips\cacherr.s: ..\halfxs\mips\cacherr.s
+
+mips\j4cache.s: ..\halfxs\mips\j4cache.s
+
+mips\j4flshbf.s: ..\halfxs\mips\j4flshbf.s
+
+mips\j4prof.c: ..\halfxs\mips\j4prof.c
+
+mips\jxdmadsp.s: ..\halfxs\mips\jxdmadsp.s
+
+mips\jxmapio.c: ..\halfxs\mips\jxmapio.c
+
+mips\jxmaptb.c: ..\halfxs\mips\jxmaptb.c
+
+mips\jxport.c: ..\halfxs\mips\jxport.c
+
+mips\x4tb.s: ..\halfxs\mips\x4tb.s
+
+mips\xxclock.c: ..\halfxs\mips\xxclock.c
+
+mips\xxidle.s: ..\halfxs\mips\xxidle.s
+
+mips\xxinitnt.c: ..\halfxs\mips\xxinitnt.c
+
+mips\xxipiint.s: ..\halfxs\mips\xxipiint.s
+
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halr94a.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halr94a/mips/allstart.c b/private/ntos/nthals/halr94a/mips/allstart.c
new file mode 100644
index 000000000..428f710e7
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/allstart.c
@@ -0,0 +1,276 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) allstart.c 1.2 95/10/17 01:17:28" ) */
+/*++
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Mon Oct 17 09:29:01 JST 1994 kbnes!kishimoto
+ -chg function name HalpCreateEisaStructures()
+ changed for HalpCreateEisaPCIStructures()
+ H001 Mon Oct 17 19:09:23 JST 1994 kbnes!kishimoto
+ -del Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ M002 Tue Jan 31 17:51:41 JST 1995 kbnes!A.Kuriyama
+ -add set NMI Handle routine to FW
+ M003 Tue Jan 31 18:41:45 JST 1995 kbnes!A.Kuriyama
+ -add NMI Handle valiable
+ S004 Tue Jan 31 19:05:16 JST 1995 kbnes!A.Kuriyama
+ - compile error clear
+ M005 Fri Feb 17 15:57:02 JST 1995 kbnes!A.Kuriyama
+ - set NMI routine at KSEG1_BASE
+ S006 Tue Feb 21 21:04:42 JST 1995 kbnes!A.Kuriyama
+ - disable dump nmi untill dump support.
+ M007 Wed Feb 22 11:27:18 JST 1995 kbnes!kuriyama (A)
+ - change NMI dumpflag
+ - add display NMI register
+ M008 Wed Feb 22 14:14:19 JST 1995 kbnes!kuriyama (A)
+ - compile error clear
+ S009 Wed Feb 22 14:34:31 JST 1995 kbnes!kuriyama (A)
+ - warning clear
+ S010 Tue Mar 07 14:13:41 JST 1995 kbnes!kuriyama (A)
+ - warning clear
+ S011 Sat Mar 18 20:19:57 JST 1995 kbnes!kuriyaam (A)
+ - enable dump nmi
+ M012 Sat Mar 18 20:24:58 JST 1995 kbnes!kuriyama (A)
+ - change nmi logic
+ M013 Mon May 08 23:20:10 JST 1995 kbnes!kuriyama (A)
+ - EISA/PCI interrupt change to CPU-A on MultiProcessor
+ S014 kuriyama@oa2.kb.nec.co.jp Mon May 22 03:55:08 JST 1995
+ - Set Panic Flag for esm
+ M015 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 03:08:04 JST 1995
+ - Change NMI interface address to HalpNMIInterfaceAddress
+ S016 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 04:49:24 JST 1995
+ - NMI Interface bug fix
+ M017 kuriyama@oa2.kb.nec.co.jp Fri Jun 16 20:26:09 JST 1995
+ - add Enable Ecc 1bit error exception
+ S018 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 13:23:19 JST 1995
+ - add set dump switch flag for esm
+ M019 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 18:50:42 JST 1995
+ - change ecc 1bit was not set enable
+ if nvram is not initialize.
+ M020 kisimoto@oa2.kb.nec.co.jp Fri Aug 11 14:11:16 1995
+ - clear M013. delete test code, dump switch interface.
+
+ S021 kuriyama@oa2.kbnes.nec.co.jp Tue Oct 17 00:51:42 JST 1995
+ - change length of NMISave
+
+ S022 kuriyama@oa2.kbnes.nec.co.jp
+ -add for merge R94A/R94A'/R94D HAL
+
+--*/
+
+#include "halp.h"
+#include "esmnvram.h" // M019
+#include <stdio.h> // S010
+
+ULONG HalpNMIFlag = 0;
+ULONG HalpDumpNMIFlag = 0; // S006, M008
+ULONG HalpNMISave0[0x80 / 4]; // S021
+ULONG HalpNMISave1[0x80 / 4]; // S021
+
+extern ULONG HalpNMIInterfaceAddress;
+
+VOID
+HalpNMIDispatch(
+ VOID
+ );
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ //
+ // M002,M005,M015,S016,M020
+ // set NMI Handle routine to firmware interface.
+ //
+
+ if (HalpNMIInterfaceAddress) {
+ *(PVOID *)(KSEG0_BASE|HalpNMIInterfaceAddress) = (PVOID)(KSEG1_BASE | (ULONG)HalpNMIDispatch);
+ }
+
+ //
+ // M017,M019
+ // Enable and clear ECC 1bit error.
+ //
+
+ {
+ ULONG DataWord;
+ KIRQL OldIrql;
+ UCHAR dataBuf[36];
+ UCHAR tempBuf[24];
+
+ #define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+ #define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+ #define NVRAM_VALID 3
+ #define NVRAM_MAGIC 0xff651026
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ KeRaiseIrql(HIGH_LEVEL,&OldIrql);
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+ DataWord =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.LowPart;
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.LowPart =
+ 0xffddffff & DataWord;
+ KeFlushWriteBuffer();
+
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+ KeLowerIrql(OldIrql);
+ }
+
+ }
+
+ //
+ // If the number of processors in the host configuration is one,
+ // then connect EISA interrupts to that processor zero. Otherwise,
+ // connect EISA interrupts to processor one.
+ //
+
+ if (**((PULONG *)(&KeNumberProcessors)) == 1) {
+ return HalpCreateEisaStructures();
+
+ } else if ((PCR->Number == 0) && HalpUseChipSetWorkaround) {
+
+ return HalpCreateEisaStructures();
+
+ } else if ((PCR->Number == 1) && !HalpUseChipSetWorkaround) {
+
+ return HalpCreateEisaStructures();
+
+ } else {
+ return TRUE;
+ }
+}
+
+VOID
+HalpNMIInterrupt(
+ ULONG DumpStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine was called when dump swich was pressed or Fatal NMI occued.
+ We call KeBugCheckEx() in order to Dump.
+
+Arguments:
+
+ DumpStatus: Dump Switch Status
+
+ 0 Dump Switch was not pressed.
+ 1 Dump Switch was pressed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG NMISource;
+ ULONG MemoryFailed;
+ LARGE_INTEGER InvalidAddressValue;
+ LARGE_INTEGER EccDiagnosticValue;
+ UCHAR Buffer[100];
+
+ HalpChangePanicFlag(16, (UCHAR)(0x01 | (4 * DumpStatus)), 0x10); // S014,S018
+
+ //
+ // M007,M012
+ // Check DumpStatus.and Display NMI status.
+ //
+
+ if (DumpStatus == 1) {
+ HalDisplayString("HAL:Dump Switch Pressed!\n");
+ } else {
+ HalDisplayString("HAL:NMI occured\n");
+ }
+
+ //
+ // Display NMI registers
+ //
+
+ NMISource = READ_REGISTER_ULONG(&DMA_CONTROL->NmiSource.Long);
+ sprintf(Buffer, "HAL:NmiSource register = %x\n",NMISource);
+ HalDisplayString((UCHAR *)Buffer);
+
+ MemoryFailed = READ_REGISTER_ULONG(
+ &((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long);
+ sprintf(Buffer,
+ "HAL:MemoryFailedAddress register = %x\n",
+ MemoryFailed);
+ HalDisplayString((UCHAR *)Buffer);
+
+ READ_REGISTER_DWORD(
+ (PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress,
+ &InvalidAddressValue);
+ sprintf(Buffer,
+ "HAL:Processor Invalid Address register = %x %x\n",
+ InvalidAddressValue.HighPart,InvalidAddressValue.LowPart);
+ HalDisplayString((UCHAR *)Buffer);
+
+ READ_REGISTER_DWORD(
+ (PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic,
+ &EccDiagnosticValue);
+ sprintf(Buffer,
+ "HAL:EccDiagnostic register = %x %x\n",
+ EccDiagnosticValue.HighPart,EccDiagnosticValue.LowPart);
+ HalDisplayString((UCHAR *)Buffer);
+
+ //
+ // M007,M008
+ // call KeBugCheckEx() for dump.
+ //
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,DumpStatus,NMISource,0,0);
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halr94a/mips/busdat.c b/private/ntos/nthals/halr94a/mips/busdat.c
new file mode 100644
index 000000000..1218588b8
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/busdat.c
@@ -0,0 +1,1231 @@
+// #pragma comment(exestr, "@(#) busdat.c 1.1 95/09/28 15:30:19 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Jun 30 02:57:29 1995 kbnes!kisimoto
+ - Merge build 1057
+ H002 Sat Jul 1 19:53:41 1995 kbnes!kisimoto
+ - change 'Base' and 'Limit' value on Internal
+
+--*/
+
+#include "halp.h"
+#include "string.h" // H001
+
+UCHAR HalName[] = "NEC MIPS HAL"; // H001
+
+VOID HalpInitializePciBus (VOID); // H001
+VOID HalpInitOtherBuses (VOID);
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#if !defined(_R94A_)
+ULONG HalpcGetCmosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpcSetCmosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpGetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+ULONG HalpSetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+#endif // !_R94A_
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// Prototype for system bus handlers
+//
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+#if defined(_R94A_) // H001
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+#endif
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+NTSTATUS
+HalpHibernateHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+HalpResumeHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+#ifdef MCA
+//
+// Default functionality of MCA handlers is the same as the Eisa handlers,
+// just use them
+//
+
+#define HalpGetMCAInterruptVector HalpGetEisaInterruptVector
+#define HalpAdjustMCAResourceList HalpAdjustEisaResourceList;
+
+HalpGetPosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+#endif
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ // H001: kugi Internal Bus was called with bus-no. 2, We have no idea.
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 1, // Internal BusNumber 1
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+// Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF; // H001
+ Bus->BusAddresses->IO.Limit = 0xFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0; // H001
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ //
+ // start H001, H002
+ // configurate the bus specific data
+ //
+
+ switch(InterfaceType) {
+
+ case Internal:
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->LowPart
+ = 0x80000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0x800FFFFF;
+ Bus->BusAddresses->Memory.SystemBase
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->LowPart
+ = 0x80000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
+ = 0x800FFFFF;
+ Bus->BusAddresses->IO.SystemBase
+ = 0x00000000;
+ break;
+
+ case Eisa:
+ Bus->BusAddresses->Memory.Base = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x03FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_VERSION2_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = EISA_MEMORY_VERSION2_HIGH;
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+
+ case Isa:
+ Bus->BusAddresses->Memory.Base = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x00FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_VERSION2_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = EISA_MEMORY_VERSION2_HIGH;
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+
+ case PCIBus:
+ Bus->BusAddresses->Memory.Base = 0x04000000; // from 64MB
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0xFFFFFFFF; // up to 4GB
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = PCI_MEMORY_PHYSICAL_BASE_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = PCI_MEMORY_PHYSICAL_BASE_HIGH;
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = PCI_CONTROL_PHYSICAL_BASE;
+ break;
+ }
+ }
+
+ return Bus;
+}
+
+
+#if !defined(_R94A_)
+
+//
+// C to Asm thunks for CMos
+//
+
+ULONG HalpcGetCmosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ // bugbug: this interface should be rev'ed to support non-zero offsets
+ if (Offset != 0) {
+ return 0;
+ }
+
+ return HalpGetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length);
+}
+
+
+ULONG HalpcSetCmosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ // bugbug: this interface should be rev'ed to support non-zero offsets
+ if (Offset != 0) {
+ return 0;
+ }
+
+ return HalpSetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length);
+}
+
+#endif // !_R94A_
+
+#if defined(_R94A_)
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+#if 0 // H001: support next version
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+#endif
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Internal // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Affinity = HalpEisaBusAffinity;
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ *Affinity = HalpEisaBusAffinity;
+ *Irql = EISA_DEVICE_LEVEL;
+
+ return(BusInterruptVector + PCI_VECTORS);
+}
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler, // H001
+ IN PBUS_HANDLER RootHandler, // H001
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ PAGED_CODE (); // H001
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+// from ixsysbus.c
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ //
+ //
+ // PCI Translate Bus Address workaround
+ //
+ //
+
+ if (((BusHandler->InterfaceType == PCIBus)) &&
+ (*AddressSpace == 0) &&
+ (BusAddress.QuadPart >= 0) &&
+ (BusAddress.QuadPart <= 0xffffffff )) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + 0x100000000;
+ return TRUE;
+ }
+
+
+ return FALSE;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ *Affinity = 1;
+ *Irql = (KIRQL)BusInterruptLevel;
+
+ if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision) == 0 ){
+
+ //
+ // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
+ // Enable register is zero origin.
+ //
+ // N.B. This obstruction is limiteded to beta-version of STORM chipset.
+ //
+
+ return(BusInterruptVector + DEVICE_VECTORS);
+
+ }else{
+
+ return(BusInterruptVector);
+
+ }
+}
+
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's in the 640k - 1m
+ // range then (for compatibility) try translating it on the
+ // Internal bus for
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 0 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0xA0000 &&
+ BusAddress.LowPart < 0xFFFFF) {
+
+ Status = HalTranslateBusAddress (
+ Internal,
+ 0,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+BOOLEAN
+HalpTranslateIsaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's memory space
+ // then we allow the translation as it would occur on it's
+ // corrisponding EISA bus. We're allowing this because
+ // many VLBus drivers are claiming to be ISA devices.
+ // (yes, they should claim to be VLBus devices, but VLBus is
+ // run by video cards and like everything else about video
+ // there's no hope of fixing it. (At least according to
+ // Andre))
+ //
+
+ if (Status == FALSE && *AddressSpace == 0) {
+ Status = HalTranslateBusAddress (
+ Eisa,
+ BusHandler->BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+#endif // _R94A_
diff --git a/private/ntos/nthals/halr94a/mips/cacherr.s b/private/ntos/nthals/halr94a/mips/cacherr.s
new file mode 100644
index 000000000..0b3cdf5ce
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/cacherr.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\cacherr.s"
diff --git a/private/ntos/nthals/halr94a/mips/cirrus.h b/private/ntos/nthals/halr94a/mips/cirrus.h
new file mode 100644
index 000000000..d827568cf
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/cirrus.h
@@ -0,0 +1,281 @@
+// #pragma comment(exestr, "@(#) cirrus.h 1.1 95/09/28 15:31:10 nec")
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cirrus.h
+
+Abstract:
+
+ This module contains the definitions for the code that implements the
+ Cirrus Logic VGA 6410/6420/542x device driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Miniport Driver Interface
+ *
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ * L002 1993.10.21 Kuroki
+ *
+ * - Warniing clear
+ *
+ * S003 1993.1.13 kbnes!A.Kuriyama
+ *
+ * - VGA Address was changed
+ *
+ */
+
+//
+// Change Ushort to Uchar, because R96 is mips machine.
+//
+
+
+//
+// Base address of VGA memory range. Also used as base address of VGA
+// memory when loading a font, which is done with the VGA mapped at A0000.
+//
+
+/* START L001 */
+
+#define LA_MASK 0xE /* S003 */
+#define MEM_VGA (LA_MASK << 20)
+#define MEM_VGA_SIZE 0x100000
+
+/* END L001 */
+
+//
+// Port definitions for filling the ACCSES_RANGES structure in the miniport
+// information, defines the range of I/O ports the VGA spans.
+// There is a break in the IO ports - a few ports are used for the parallel
+// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped
+// so all VGA ports are in one address range.
+//
+
+#define VGA_BASE_IO_PORT 0x000003B0
+#define VGA_START_BREAK_PORT 0x000003BB
+#define VGA_END_BREAK_PORT 0x000003C0
+#define VGA_MAX_IO_PORT 0x000003DF
+
+//
+// VGA port-related definitions.
+//
+
+//
+// VGA register definitions
+//
+ // ports in monochrome mode
+#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and
+#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode
+#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port
+ // in mono mode
+#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read
+ // port in mono mode
+#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO
+ // Register to read to reset
+ // Attribute Controller index/data
+#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and
+#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port
+ // for writes, but only Address is
+ // readable at 0x010
+#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is
+ // readable here
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write
+ // port
+#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read
+ // port
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the
+ // entire VGA subsystem
+#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and
+#define SEQ_DATA_PORT 0x0015 // Data registers
+#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg
+#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg,
+ // write-only
+#define DAC_STATE_PORT 0x0017 // DAC state (read/write),
+ // read-only
+#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg
+#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg
+#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port
+#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read
+ // port
+#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address
+#define GRAPH_DATA_PORT 0x001F // and Data registers
+
+ // ports in color mode
+#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and
+#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode
+#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port
+#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read
+ // port in color mode
+#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR
+ // Register to read to reset
+ // Attribute Controller index/data
+ // toggle in color mode
+
+//
+// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed
+// VGA registers.
+//
+
+#define CRTC_ADDRESS_MONO_OFFSET 0x04
+#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A
+#define ATT_ADDRESS_OFFSET 0x10
+#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12
+#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13
+#define SEQ_ADDRESS_OFFSET 0x14
+#define DAC_PIXEL_MASK_OFFSET 0x16
+#define DAC_STATE_OFFSET 0x17
+#define DAC_ADDRESS_WRITE_OFFSET 0x18
+#define GRAPH_ADDRESS_OFFSET 0x1E
+#define CRTC_ADDRESS_COLOR_OFFSET 0x24
+#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A
+
+// toggle in color mode
+//
+// VGA indexed register indexes.
+//
+
+// CL-GD542x specific registers:
+//
+#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts
+#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad
+#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register
+//
+#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start
+#define IND_CURSOR_END 0x0B // and End registers
+#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location
+#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers
+#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync
+ // End register, which has the bit
+ // that protects/unprotects CRTC
+ // index registers 0-7
+#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC
+#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC
+#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr
+#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr
+#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr
+#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr
+#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq
+#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer
+#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq
+#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in
+ // CRTC
+#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg
+ // in CRTC
+#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start
+ // synchronous reset
+#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end
+ // synchronous reset
+
+//
+// Values for Attribute Controller Index register to turn video off
+// and on, by setting bit 5 to 0 (off) or 1 (on).
+//
+
+#define VIDEO_DISABLE 0
+#define VIDEO_ENABLE 0x20
+
+// Masks to keep only the significant bits of the Graphics Controller and
+// Sequencer Address registers. Masking is necessary because some VGAs, such
+// as S3-based ones, don't return unused bits set to 0, and some SVGAs use
+// these bits if extensions are enabled.
+//
+
+#define GRAPH_ADDR_MASK 0x0F
+#define SEQ_ADDR_MASK 0x07
+
+//
+// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register.
+//
+
+#define CHAIN4_MASK 0x08
+
+//
+// Value written to the Read Map register when identifying the existence of
+// a VGA in VgaInitialize. This value must be different from the final test
+// value written to the Bit Mask in that routine.
+//
+
+#define READ_MAP_TEST_SETTING 0x03
+
+//
+// Default text mode setting for various registers, used to restore their
+// states if VGA detection fails after they've been modified.
+//
+
+#define MEMORY_MODE_TEXT_DEFAULT 0x02
+#define BIT_MASK_DEFAULT 0xFF
+#define READ_MAP_DEFAULT 0x00
+
+
+//
+// Palette-related info.
+//
+
+//
+// Highest valid DAC color register index.
+//
+
+#define VIDEO_MAX_COLOR_REGISTER 0xFF
+
+//
+// Indices for type of memory mapping; used in ModesVGA[], must match
+// MemoryMap[].
+//
+
+typedef enum _VIDEO_MEMORY_MAP {
+ MemMap_Mono,
+ MemMap_CGA,
+ MemMap_VGA
+} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP;
+
+//
+// For a mode, the type of banking supported. Controls the information
+// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking.
+//
+
+typedef enum _BANK_TYPE {
+ NoBanking = 0,
+ NormalBanking,
+ PlanarHCBanking
+} BANK_TYPE, *PBANK_TYPE;
+
+#define CL6410 0x0001
+#define CL6420 0x0002
+#define CL542x 0x0004
+
+// bitfields for the DisplayType
+#define crt 0x0001
+#define panel 0x0002
+#define simulscan 0x0004 // this means both, but is unused for now.
diff --git a/private/ntos/nthals/halr94a/mips/cmdcnst.h b/private/ntos/nthals/halr94a/mips/cmdcnst.h
new file mode 100644
index 000000000..ea2bba221
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/cmdcnst.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdcnst.h
+
+Abstract:
+
+ This is the command string interpreter definitions
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ This module is same file on Cirrus Minport Driver.
+
+Revision History:
+
+--*/
+
+//--------------------------------------------------------------------------
+// Definition of the set/clear mode command language.
+//
+// Each command is composed of a major portion and a minor portion.
+// The major portion of a command can be found in the most significant
+// nibble of a command byte, while the minor portion is in the least
+// significant portion of a command byte.
+//
+// maj minor Description
+// ---- ----- --------------------------------------------
+// 00 End of data
+//
+// 10 in and out type commands as described by flags
+// flags:
+//
+// xxxx
+// ||||
+// |||+-------- unused
+// ||+--------- 0/1 single/multiple values to output (in's are always
+// |+---------- 0/1 8/16 bit operation single)
+// +----------- 0/1 out/in instruction
+//
+// Outs
+// ----------------------------------------------
+// 0 reg:W val:B
+// 2 reg:W cnt:W val1:B val2:B...valN:B
+// 4 reg:W val:W
+// 6 reg:W cnt:W val1:W val2:W...valN:W
+//
+// Ins
+// ----------------------------------------------
+// 8 reg:W
+// a reg:W cnt:W
+// c reg:W
+// e reg:W cnt:W
+//
+// 20 Special purpose outs
+// 00 do indexed outs for seq, crtc, and gdc
+// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 01 do indexed outs for atc
+// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 02 do masked outs
+// indexreg:W andmask:B xormask:B
+//
+// F0 Nop
+//
+//---------------------------------------------------------------------------
+
+// some useful equates - major commands
+
+#define EOD 0x000 // end of data
+#define INOUT 0x010 // do ins or outs
+#define METAOUT 0x020 // do special types of outs
+#define NCMD 0x0f0 // Nop command
+
+
+// flags for INOUT major command
+
+//#define UNUSED 0x01 // reserved
+#define MULTI 0x02 // multiple or single outs
+#define BW 0x04 // byte/word size of operation
+#define IO 0x08 // out/in instruction
+
+// minor commands for metout
+
+#define INDXOUT 0x00 // do indexed outs
+#define ATCOUT 0x01 // do indexed outs for atc
+#define MASKOUT 0x02 // do masked outs using and-xor masks
+
+
+// composite inout type commands
+
+#define OB (INOUT) // output 8 bit value
+#define OBM (INOUT+MULTI) // output multiple bytes
+#define OW (INOUT+BW) // output single word value
+#define OWM (INOUT+BW+MULTI) // output multiple words
+
+#define IB (INOUT+IO) // input byte
+#define IBM (INOUT+IO+MULTI) // input multiple bytes
+#define IW (INOUT+IO+BW) // input word
+#define IWM (INOUT+IO+BW+MULTI) // input multiple words
diff --git a/private/ntos/nthals/halr94a/mips/eisadumy.s b/private/ntos/nthals/halr94a/mips/eisadumy.s
new file mode 100644
index 000000000..b4feaa445
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/eisadumy.s
@@ -0,0 +1,70 @@
+// .ident "@(#) eisadummy.s 1.1 95/06/30 05:26:23 nec"
+//
+// TITLE("EISA/PCI dummy before acknowledge")
+//++
+//
+// Copyright (c) 1995 NEC Corporation
+//
+// Module Name:
+//
+// eisadummy.s
+//
+// Abstract:
+//
+// This routine make dummy read before EISA/PCI acknowledge.
+//
+// Author:
+//
+// Akitoshi Kuriyama (NEC Software Kobe,Inc)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Wed Jan 25 21:11:53 JST 1995 kbnes!A.Kuriyama
+//
+//--
+#include "halmips.h"
+
+ SBTTL("dummy read befor EISA/PCI acknowledge")
+//++
+//
+// USHORT
+// HalpReadEisaAcknowledgeWithDummy (
+// IN PVOID DummyAddress,
+// IN PVOID AcknowledgeAddress
+// )
+//
+// Routine Description:
+//
+// This function makes dummy read and read EISA/PCI acknowledge register
+// within 64 byte aligned area.
+//
+// Arguments:
+//
+// DummyAddress (a0) - Supplies a pointer to dummy register.
+//
+// AcknowledgeAddress (a1) - Supplies a pointer to EISA/PCI acknowledge
+// register.
+//
+// Return Value:
+//
+// EISA/PCI Acknowledge register's value.
+//
+//--
+
+ LEAF_ENTRY(HalpReadEisaAcknowledgeWithDummy)
+
+ .set noreorder
+
+ lw t0,(a0) // dummy read
+ lh v0,(a1) // read EISA/PCI Ack. Reg.
+
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadEisaAcknowledgeWithDummy
+
diff --git a/private/ntos/nthals/halr94a/mips/esm.c b/private/ntos/nthals/halr94a/mips/esm.c
new file mode 100644
index 000000000..f15acb3c6
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/esm.c
@@ -0,0 +1,1182 @@
+// #pragma comment(exestr, "@(#) esm.c 1.1 95/09/28 15:31:51 nec")
+/*++
+
+Copyright (c) 1995 Kobe NEC Software
+
+Module Name:
+
+ esm.c
+
+Abstract:
+
+ This module implements the ESM service routine
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ L001 kuriyama@oa2.kb.nec.co.jp Thu Jun 15 14:57:14 JST 1995
+ -Change HalpEccError() for support J94C ECC error
+
+ M002 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 14:31:57 JST 1995
+ - add ecc 1bit safety flag
+
+ M003 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 20:40:52 JST 1995
+ - add serialize ecc 1bit routine
+
+ S004 kuriyama@oa2.kb.nec.co.jp Fri Jun 23 16:55:12 JST 1995
+ - bug fix ecc 2bit error
+--*/
+#include "halp.h"
+#include "esmnvram.h"
+#include "bugcodes.h"
+#include "stdio.h"
+
+//
+// define offset.
+//
+
+#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr)
+#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest)
+#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr)
+#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest)
+#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr)
+#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest)
+
+
+#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description)
+#define TIME_STAMP_SIZE 14
+
+//
+// define value
+//
+
+#define NVRAM_VALID 3
+#define NVRAM_MAGIC 0xff651026
+#define ECC_LOG_VALID_FLG 1
+
+// L001++
+#define STORM_ECC_1BIT_ERROR 1
+#define STORM_ECC_2BIT_ERROR 2
+#define STORM_OTHER_ERROR 0
+// L001---
+
+//#define SDCR_SET0_ADDR 0xb9100030
+//#define SDCR_SET1_ADDR 0xb9120030
+
+#define STRING_BUFFER_SIZE 512
+
+#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10
+
+// M002 +++
+
+//
+// Define Ecc safety flags
+//
+
+#define CHECKED 1
+#define NOT_CHECKED 0
+#define RUNNING 1
+#define NOT_RUNNING 0
+// M002 ---
+
+//
+// Define global variable. This variable use in display string into nvram.
+//
+
+ULONG CallCountOfInitDisplay = 0;
+ULONG HalpNvramValid=FALSE;
+USHORT ErrBufferLatest;
+USHORT ErrBufferArea;
+USHORT ErrBufferStart;
+USHORT ErrBufferEnd;
+USHORT ErrBufferCurrent;
+ULONG HalpPanicFlg=0;
+UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE];
+ULONG HalpNvramStringBufferCounter=0;
+
+// L001+++
+//LONG HalpECC1bitDisableFlag=1; // S001
+//LONG HalpECC1bitDisableTime=0; // S003
+//ULONG HalpECC1bitScfrBuffer=0; // S003
+ULONG HalpEcc1bitCount[2] = {0,0};
+ULONG HalpOldMemoryFailed[2] = {0,0};
+ULONG HalpEcc2bitErrorFlag = 0;
+// L001---
+
+// M002 +++
+
+// ecc 1bit total count
+ULONG HalpEcc1bitTotalCount = 0;
+
+// variables for ecc1bit safety flag
+extern ULONG HalpAnotherRunningECC;
+extern ULONG HalpAnotherCheckedECC;
+// M002 ---
+
+
+UCHAR KernelPanicMessage[]="*** STOP: 0x"; // S002
+
+//
+// Define macro
+//
+#if 0
+#define GET_PADDR(addr,sts2,SicSet) { \
+ (addr) = ( ( ((PSTS2_REGISTER)&(sts2) )->COL0_9 << 4 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW0_9 << 14 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->SIMN << 24 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->COL10 << 25 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW10 << 26 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->ARE << 27 ) \
+ + ( (SicSet) << 30 ) ); \
+}
+#endif // 0
+
+#define GET_TIME(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ HalQueryRealTimeClock( &timeBuffer ); \
+ sprintf( (Buffer), \
+ "%04d%02d%02d%02d%02d%02d", \
+ timeBuffer.Year, \
+ timeBuffer.Month, \
+ timeBuffer.Day, \
+ timeBuffer.Hour, \
+ timeBuffer.Minute, \
+ timeBuffer.Second \
+ ); \
+}
+
+// S002, S003 vvv
+#if 0
+#define NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long,buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+
+#define DONT_NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long, \
+ buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+#endif // 0
+// S002, S003 ^^^
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is initialize variable of use when write display data in
+ HalDisplayString into NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SYSTEM_ERR_AREA_INFO infoBuf;
+ UCHAR recordFlg;
+ UCHAR buf[8];
+ UCHAR buf2[8];
+
+ CallCountOfInitDisplay++;
+ if(CallCountOfInitDisplay == 1){
+
+ //
+ // Check NVRAM status
+ //
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 );
+
+ if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){
+ HalpNvramValid=FALSE;
+ return;
+ }
+
+ HalpNvramValid=TRUE;
+
+ //
+ // Get log area infomation.
+ //
+
+ HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ &infoBuf);
+
+ ErrBufferLatest = infoBuf.offset_latest;
+
+ HalNvramRead( infoBuf.offset_latest, 1, &recordFlg);
+
+ //
+ // Check current record flg.
+ //
+
+ if( (recordFlg & 0x01) == 1 ) {
+ infoBuf.offset_latest += infoBuf.size_rec;
+ if( infoBuf.offset_latest >=
+ infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){
+ infoBuf.offset_latest = infoBuf.offset_systemerr;
+ }
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &infoBuf.offset_latest);
+ }
+
+ //
+ // initialize variable. this value use log area access.
+ //
+
+ ErrBufferArea = infoBuf.offset_latest;
+ ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE;
+ ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1;
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // status flg set.
+ //
+
+ HalpPanicFlg = 0;
+
+ recordFlg = 0x11;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ //
+ // buffer initialize.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else {
+
+ //
+ // start Panic log.
+ //
+
+ HalpChangePanicFlag( 1, 1, 0);
+ }
+}
+
+// L001 +++
+
+UCHAR
+HalpFindMemoryGroup(
+ IN ULONG MemoryFailed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds MemoryGroup of MemoryFaled address
+
+Arguments:
+
+ MemoryFailed - MemoryFailed Register value
+
+
+Return Value:
+
+ if MemoryFaied is within any Goup, return MemoryGroup Number.
+
+ Otherwise, return 0xff
+
+--*/
+
+{
+ UCHAR returnValue = 0xff;
+ UCHAR i;
+ ULONG startAddr;
+ ULONG length;
+ ULONG simmType;
+ ULONG dataWord;
+
+ //
+ // find MemoryGroup from MemoryGroup[0:3] register.
+ //
+ // MemoryGroup[0:3] register
+ //
+ // [31] Reserved
+ // [30:22] Starting address
+ // [21:04] Reserved
+ // [03:02] SIMM type
+ // 01=Single-sided 11=Double-sided other=Reserved
+ // [01:00] SIMM size
+ // 00= 1M 01=4M 10=16M 11=64M SIMM
+ //
+ // note: 1 memory group is have 4 SIMM's
+ //
+
+ for (i = 0; i < 4; i++) {
+ dataWord = READ_REGISTER_ULONG(&DMA_CONTROL->MemoryConfig[i]);
+
+ // check SIMM type is valid
+
+ switch (dataWord & 0xc) {
+
+ case 4:
+ simmType = 1;
+ break;
+
+ case 0xc:
+ simmType = 2;
+ break;
+
+ default:
+ simmType = 3;
+ }
+
+ if (simmType == 3) {
+ continue;
+ }
+
+ // compute amount of MemoryGoup SIMM length;
+
+ length = (0x400000 << ((dataWord & 3) * 2)) * simmType;
+
+ // compute MemoryGoup SIMM start address;
+
+ startAddr = dataWord & 0x7fc00000;
+
+ // check if MemoryFailed is within this MemoryGroup
+
+ if ( (startAddr <= MemoryFailed)
+ && (MemoryFailed < (length + startAddr))) {
+ returnValue = i;
+ break;
+ }
+ }
+ return returnValue;
+
+}
+
+
+ULONG
+HalpEccError(
+ IN ULONG EccDiagnostic,
+ IN ULONG MemoryFailed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine check ecc error and error log put in NVRAM.
+
+Arguments:
+
+ EccDiagnostic - EccDiagnostic Register value
+ MemoryFailed - MemoryFailed Register value
+
+
+Return Value:
+
+ return value is the following error occured.
+ 1: ecc 1bit error.
+ 2: ecc 2bit error.
+ 0: other error.
+
+--*/
+
+{
+ ULONG returnValue;
+ USHORT infoOffset;
+ USHORT writeOffset;
+ ULONG buffer; // S001
+ ULONG i; // S002
+ UCHAR dataBuf[36];
+ UCHAR infoBuf[24];
+ UCHAR tempBuf[24];
+ KIRQL OldIrql;
+ ULONG DataWord;
+ ULONG Number;
+
+ //
+ // Check for Ecc 2bit/1bit error
+ //
+
+ if (EccDiagnostic & 0x44000000) {
+ returnValue = STORM_ECC_2BIT_ERROR;
+ infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET;
+ } else if (EccDiagnostic & 0x22000000) {
+ returnValue = STORM_ECC_1BIT_ERROR;
+ infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET;
+ } else {
+ return 0; // Probably Error bit was disappered.
+ }
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+
+ // S002 vvv
+ switch(returnValue) {
+
+ case STORM_ECC_2BIT_ERROR:
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+
+ // set Flag indicate ECC 2bit error.
+
+ HalpEcc2bitErrorFlag = 1;
+
+ //
+ // Log to NVRAM
+ //
+
+ // check for nvram was valid.
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC2_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0;
+ // Error Address was 16Byte Alined.
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC2_ERR_REC)dataBuf)->syndrome = EccDiagnostic;
+
+ ((pECC2_ERR_REC)dataBuf)->specified_group =
+ HalpFindMemoryGroup(MemoryFailed);
+
+ ((pECC2_ERR_REC)dataBuf)->specified_simm = 0;
+
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC2_ERR_REC),
+ (PVOID)dataBuf);
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+ return returnValue; // S004
+
+ case STORM_ECC_1BIT_ERROR:
+
+ //
+ // If MemoryFailed address
+ // is over 512M Nothing can do.
+ //
+ if ((MemoryFailed & 0xfffffff0) > 0x1fffffff) {
+ return returnValue;
+ }
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ Number = KeGetCurrentPrcb()->Number;
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+// M003 +++
+ //
+ // serialize ecc 1bit logging routine
+ //
+
+ for (;;) {
+ KiAcquireSpinLock(&Ecc1bitRoutineLock);
+ if (HalpEcc1bitCount[!Number] == 0) {
+
+ //
+ // Increment HalpEcc1bitCount
+ //
+
+ HalpEcc1bitCount[Number]++;
+ KiReleaseSpinLock(&Ecc1bitRoutineLock);
+ break;
+ }
+ KiReleaseSpinLock(&Ecc1bitRoutineLock);
+ }
+// M003 ---
+
+ switch(HalpEcc1bitCount[Number]) {
+
+ case 1:
+
+ HalpEcc1bitTotalCount++; // M002
+
+
+ HalpOldMemoryFailed[Number] = MemoryFailed;
+
+ //
+ // ReWrite error address
+ // if error address is over 512M
+ // Nothing can do.
+ //
+
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+
+ // disable ecc 1bit error again.
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+
+ DataWord = READ_REGISTER_ULONG(
+ KSEG1_BASE
+ | (MemoryFailed & 0xfffffff0)
+ );
+ WRITE_REGISTER_ULONG(
+ KSEG1_BASE
+ | (MemoryFailed & 0xfffffff0),
+ DataWord
+ );
+
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+
+ //
+ // Wait 20 us.
+ //
+
+ KeStallExecutionProcessor(20);
+
+ //
+ // Enable and clear ECC 1bit error.
+ //
+
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00cc0000;
+ KeFlushWriteBuffer();
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+
+ //
+ // ReRead error address
+ // if error address is over 512M
+ // Nothing can do.
+ //
+ // if Ecc 1bit error occur again , DataBusError will occur.
+ //
+
+ DataWord = READ_REGISTER_ULONG(
+ KSEG1_BASE
+ | (MemoryFailed & 0xfffffff0)
+ );
+
+ // decrement ecc 1bit count
+
+ HalpEcc1bitCount[Number]--;
+
+ return(returnValue);
+
+ case 2:
+
+ if (HalpOldMemoryFailed[Number] != MemoryFailed) {
+ break;
+ }
+ if (MemoryFailed & 2) {
+
+ // if multi error
+ // nothing can do.
+
+ break;
+ }
+
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+
+ //
+ // Search for wheather error address was already logged
+ //
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) {
+ HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)->
+ size_rec * i
+ +((pECC1_ERR_AREA_INFO)infoBuf)->
+ offset_1biterr),
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ if ( ((MemoryFailed & 0xfffffff0)
+ == ((pECC1_ERR_REC)dataBuf)->err_address) &&
+ ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) {
+ break;
+ }
+ }
+
+ if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ break;
+ }
+
+ //
+ // Log to NVRAM
+ //
+
+ // check for nvram was valid.
+
+ ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC1_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0;
+ // Error Address was 16Byte Alined.
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC1_ERR_REC)dataBuf)->syndrome = EccDiagnostic;
+
+ ((pECC1_ERR_REC)dataBuf)->specified_group =
+ HalpFindMemoryGroup(MemoryFailed);
+
+ ((pECC1_ERR_REC)dataBuf)->specified_simm = 0;
+
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+
+
+ // disable ecc 1bit error again.
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+
+ // decrement ecc 1bit count
+
+ HalpEcc1bitCount[Number]--;
+
+ return(returnValue);
+ }
+
+ //
+ // Enable and clear ECC 1bit error.
+ //
+
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00cc0000;
+ KeFlushWriteBuffer();
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+
+
+ // decrement ecc 1bit count
+
+ HalpEcc1bitCount[Number]--;
+
+ return(returnValue);
+ }
+}
+
+// L001 ---
+
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ )
+{
+ UCHAR buf[24];
+
+ //
+ // Set time stamp on initialize display.
+ //
+
+ if(HalpNvramValid == TRUE) {
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+ }
+}
+
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ )
+{
+ UCHAR recordFlg;
+
+ if(HalpNvramValid == TRUE) {
+ recordFlg = 0;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest );
+ }
+}
+
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ )
+{
+ UCHAR recordFlg;
+ UCHAR buf[24];
+
+ if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) {
+ return;
+ }
+
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &ErrBufferArea);
+
+ //
+ // initialize currernt buffer address
+ //
+
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // set panic flag
+ //
+
+ HalNvramRead( ErrBufferArea, 1, &recordFlg );
+ recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+
+ //
+ // set new flag of panic level
+ //
+
+ HalpPanicFlg = NewPanicFlg;
+
+ //
+ // initialize log buffer.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+}
+
+
+// S002 vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ )
+{
+ if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) {
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character;
+ }
+}
+
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ )
+{
+ ULONG i;
+
+ //
+ // Initialize buffer
+ //
+
+ for(i=0; i<STRING_BUFFER_SIZE; i++) {
+ HalpNvramStringBuffer[i] = 0;
+ }
+
+ HalpNvramStringBufferCounter=0;
+
+ //
+ // set string position
+ //
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Column;
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Row;
+}
+
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // if data size is zero, when return
+ //
+
+ if( HalpNvramStringBufferCounter <= 2 ) {
+ return;
+ }
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]='\0';
+
+ //
+ // check panic message
+ //
+
+ for( count=0; ; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != HalpNvramStringBuffer[count+2] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for( count=2; ; count++) {
+ if( HalpNvramStringBuffer[count] == '\0' ){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 2 < ErrBufferEnd ) {
+ HalNvramWrite( ErrBufferCurrent, count, HalpNvramStringBuffer );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( (count + 2 > ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count );
+ }
+ ErrBufferCurrent++;
+ if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+
+#if 0
+VOID
+HalpStringIntoNvram(
+ IN ULONG Column,
+ IN ULONG Row,
+ IN PUCHAR String
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // check panic message
+ //
+
+ for(count=0; 1; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != String[count] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for(count=0;;count++) {
+ if(String[count]=='\0'){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 4 < ErrBufferEnd ) {
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+ HalNvramWrite( ErrBufferCurrent, count, String );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( count + 4 > ErrBufferEnd - ErrBufferStart ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, String+count );
+ }
+ ErrBufferCurrent++;
+ if(String[count]=='\0') {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+#endif
+// S002 ^^^
+
+
+//
+// test code
+//
+
+int
+printNvramData(void)
+{
+ UCHAR buf[256];
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag), 1, buf );
+ DbgPrint("Nvram Flag: 0x%02lx\n", buf[0]);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->when_formatted), 14, buf );
+ buf[14]=0;
+ DbgPrint("Nvram TimeStamp: %s\n", buf);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err),
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC1: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC1: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC1: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC1: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err),
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC2: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC2: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC2: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC2: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->system_err),
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram SYSTEM: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram SYSTEM: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram SYSTEM: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram SYSTEM: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ return(0);
+}
+
+
+int
+TmpInitNvram(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0xff;
+ for(i=0; i<8*1024; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 4, (PUCHAR)&i);
+
+ //
+ // Make 1bit err log info
+ //
+
+ ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768;
+ ((pECC1_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC1_ERR_AREA_INFO)buf)->num_rec=16;
+ ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768;
+
+ ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0;
+
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768; i<768+25*16; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make 2bit err log info
+ //
+
+ ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400;
+ ((pECC2_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC2_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400;
+
+ ((pECC2_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768+400; i<768+400+25*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make system err log info
+ //
+
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280;
+
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=1280; i<1280+512*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ return(0);
+}
+
diff --git a/private/ntos/nthals/halr94a/mips/esmnvram.h b/private/ntos/nthals/halr94a/mips/esmnvram.h
new file mode 100644
index 000000000..2392671e9
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/esmnvram.h
@@ -0,0 +1,688 @@
+// #pragma comment(exestr, "@(#) esmnvram.h 1.1 95/09/28 15:32:22 nec")
+
+/****************************************************************
+ ******* Copyright (C) 1994 NEC Corporation *******
+ ****************************************************************/
+
+/*******
+
+ File Name:
+
+ envram.h
+
+ Abstract:
+
+ This module contains the definitions for the extended NVRAM.
+
+ Author:
+
+ Takehiro Ueda (tueda@oa2.kb.nec.co.jp) 12/22/1994
+
+ Modification History:
+
+ - M000 12/22/94 -
+ created.
+
+*******/
+
+
+
+/*******************************************************************************
+ ******** NVRAM¡Ê8K¥Ð¥¤¥È¡Ë¤ÎÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤ò°Ê²¼¤Ëµ­½Ò¤¹¤ë¡£ ********
+ *******************************************************************************
+ *
+ * S001 11/22/94
+ * ¥ì¥³¡¼¥É¤ÎÍ­¸ú/̵¸ú¥Õ¥é¥°¡¢Check̤/ºÑ¥Õ¥é¥°¤ò³Æ¥ì¥³¡¼¥É¤ÎÀèƬ¤Ë¤ª¤¯¤«
+ * ¤Þ¤È¤á¤Æ¥ì¥³¡¼¥É¥ê¡¼¥¸¥ç¥ó¤ÎÀèƬ¤Ë¤ª¤¯¤«¤Ç¡¢¥ì¥³¡¼¥É¤Î½èÍýÊýË¡¤¬ÊѤï¤Ã¤Æ
+ * ¤¯¤ë¡£¸å¼Ô¤Ï¥é¥ó¥À¥à¥¢¥¯¥»¥¹¡¢Á°¼Ô¤Ï¥·¡¼¥±¥ó¥·¥ã¥ë¥¢¥¯¥»¥¹¤Ë¤à¤¯¡£
+ * º£²ó¤ÏÁ°¼Ô¤òºÎÍÑ¡£
+ *
+ * ¹Ô¤ÎÀèƬ¤Ë¤¢¤ë¿ô»ú¤Ï³ä¤êÅö¤Æ¤ë¥Ð¥¤¥È¿ô¤ò¤¢¤é¤ï¤¹¡£
+ *
+ * ËÜ»ÅÍͤˤ·¤¿¤¬¤Ã¤Æ¹½Â¤ÂΤòºîÀ®Í½Äê¡£
+ *
+ * S002 11/26/94
+ * ³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°´ØÏ¢¡¢etc.¡Ë
+ * ¤ÎÀèƬ¤Î¥Ø¥Ã¥ÀÉô¤òÁ´¤ÆNVRAM¤ÎÀèƬ¤Ë°Ü¤¹¡£NVRAM¤ÎÀèƬ¤Ë¤¢¤ë¥Ø¥Ã¥ÀÆâ¤Ë
+ * ³ÆÎΰè¤Î¥ì¥³¡¼¥É¤òľÀÜ¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥ª¥Õ¥»¥Ã¥È¤ò¤â¤Ä¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * NVRAM¤Î¥¢¥¯¥»¥¹»þ¤Ë¤Ï256¥Ð¥¤¥Èñ°Ì¤Ç¥Ð¥ó¥¯Àڤ괹¤¨¤¬¤ª¤³¤Ê¤ï¤ì¤ë¤¿¤á
+ * ³Æ¥Ç¡¼¥¿¡Ê256¥Ð¥¤¥ÈĹ°Ê²¼¤Î¤â¤Î¡Ë¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤ò¤Þ¤¿¤¬¤é¤Ê¤¤¤è¤¦
+ * ¤ËÇÛθ¡£³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢etc.¡Ë¤ÎÀèƬ¤¬É¬¤º256¥Ð¥¤¥È
+ * ¥Ð¥¦¥ó¥À¥ê¤«¤é³«»Ï¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * ECC¥¨¥é¡¼¥í¥°Æâ¤ÎSIMMÆÃÄê²½¾ðÊó¤ò2¥Ð¥¤¥È¤«¤é1¥Ð¥¤¥È¤ØÊѹ¹¡£
+ *
+ * ¡É¥ª¥Õ¥»¥Ã¥È ¡É¤Ï¤¹¤Ù¤ÆNVRAM¤ÎÀèƬ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¡£
+ *
+ * S003 12/13/94
+ * NW¥¨¡¼¥¸¥§¥ó¥È¤È¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ò¶¦Ä̲½¤¹¤ë¤¿¤áÀèƬ512¥Ð¥¤¥È¤ò
+ * ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤È¤·¡¢¥Õ¥©¡¼¥Þ¥Ã¥È¤òNW¥¨¡¼¥¸¥§¥ó¥È¤ÈÅý°ì¤¹¤ë¡£
+ *
+ * STEP1¤Ç¤Ï¥á¥â¥ê½ÌÂà¤ò¹Ô¤ï¤Ê¤¤¤¿¤áËÜ¥¨¥ê¥¢¤Ï»ÈÍѤ·¤Ê¤¤¡£
+ * ËÜ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ÏNW¥¨¡¼¥¸¥§¥ó¥È¤È¤Î¶¦Ä̲½¤Î¤¿¤á¤Ë¿·¤¿¤ËÀߤ±¤ë
+ * ¤â¤Î¤Ç¤¢¤ê¡¢°ÊÁ°¤«¤é¤ÎECC¥¨¥é¡¼¾ðÊóÎΰè¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£
+ *
+ * 512¥Ð¥¤¥È¤Î¥¨¥ê¥¢¤òÀèƬ¤ËÀߤ±¤ë¤¿¤á¡¢°ÊÁ°¤«¤é¤Î¤½¤Î¾Á´¤Æ¤Î¾ðÊóÎΰè¤Ï
+ * 512¥Ð¥¤¥È¥ª¥Õ¥»¥Ã¥È¤¬Â礭¤¯¤Ê¤ë¤³¤È¤Ë¤Ê¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È2¥Ð¥¤¥È¤òÄɲá£
+ *
+ * ¥ª¥Õ¥»¥Ã¥È¤ÎºÆ·×»»¡£
+ *
+ * S004 12/14/94
+ * ¹½Â¤ÂκîÀ®¡£
+ *
+ * ¡Ç¥Ñ¥Ë¥Ã¥¯ ¡Ç¤ò¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S005 12/23/94
+ * 4byte alignment¤Ë¤½¤Ê¤¨¤Æ¥Ñ¥Ç¥£¥ó¥°¤ò°ìÉôÊѹ¹¡£
+ *
+ * ¥¹¥È¥Ã¥×¥¨¥é¡¼¤Î¥Õ¥é¥°¤Î2¥Ó¥Ã¥È¤Ë¿·¤¿¤ËÄêµÁÄɲá£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤òNVRAM¥Ø¥Ã¥À¤Ë¤È¤ê¤³¤à¡£
+ * ¤³¤ì¤Ë¤È¤â¤Ê¤¤¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ÏÉÔÍפȤʤ뤿¤á
+ * 2¥Ð¥¤¥Èʬ̤»ÈÍѤȤ¹¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ë¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤òÄɲá£ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ¤ò
+ * ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤È¥Õ¥é¥°¤Ç¥Á¥§¥Ã¥¯¤¹¤ë¤è¤¦¤Ë¤¹¤ë¡£¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤Ï
+ * 0xFF651026¤È¤¹¤ë¡£
+ *
+ * ¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ò¡Ç¥·¥¹¥Æ¥à¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S006 12/27/94
+ * #pragma pack() ¤òÄɲÃ
+ *
+ * char reserved[49] ¤ò char reserved[49] ¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ïharmless¤Ç¤¢¤ë
+ * ¤È¿®¤¸¤ë... (^_^;
+ *
+ * unsigned short offset_ecc2err ¤ò offset_2biterr¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ï
+ * harmless¤Ç¤¢¤ë¤È¿®¤¸¤ë... (^_^;
+ *
+ ******************************************************************************
+
+
+ ###################
+ # NVRAM¥Ø¥Ã¥ÀÉô #
+ ###################
+
+ ######################################################
+ # F/WÍÑ¥á¥â¥ê¡¼¥¨¥é¡¼¥¨¥ê¥¢ (NW¥¨¡¼¥¸¥§¥ó¥È¤È¶¦ÄÌ) #
+ ######################################################
+
+ 512 ¥á¥â¥ê¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(2¥Ð¥¤¥È) ¡ß 256
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ ¡¡¡¡1 ¥¹¥Æ¡¼¥¿¥¹ 0:Àµ¾ï 1:°Û¾ï(2bit¥¨¥é¡¼Í­Ìµ)
+ 1 1bit¥¨¥é¡¼¥«¥¦¥ó¥È
+
+¡¡¡¡ ######################
+ # Á´ÂΤ˴ؤ¹¤ë¤â¤Î #
+ ######################
+
+ 1 NVRAM¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 NVRAMÁ´ÂÎÍ­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡1 ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ 0:̵ 1:Í­
+ ¡¡¡¡2 READ-ONLY 0:NO 1:YES
+ ¡¡¡¡3 LOCK 0:NO 1:YES
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 NVRAM¤¬¥Õ¥©¡¼¥Þ¥Ã¥È¤µ¤ì¤¿¥¿¥¤¥à¥¹¥¿¥ó¥×
+
+ 3 [ reserved ]
+
+¡¡¡¡ ###############################
+ # ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ###############################
+
+ 2 ALIVE¾ðÊóÎΰè¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ #######################################
+ # ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 1bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECC1bit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ ¡¡ 8 ECC 1bit¥¨¥é¡¼¥«¥¦¥ó¥È ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô8
+
+¡¡¡¡ #######################################
+ # ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 2bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECCÊ£¿ôbit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ 4 SIMM¸ò´¹¥Õ¥é¥° ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô4
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 ¥°¥ë¡¼¥×NÆâSIMM #0 (N=1¡Á4) 0:OK 1:NG(Í׸ò´¹)
+ ¡¡¡¡1 ¥°¥ë¡¼¥×NÆâSIMM #1 ¢¬
+ ¡¡¡¡2 ¥°¥ë¡¼¥×NÆâSIMM #2¡¡¡¡ ¢¬
+ ¡¡¡¡3 ¥°¥ë¡¼¥×NÆâSIMM #3¡¡¡¡ ¢¬
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¢¬
+ ¡¡¡¡6 ¢¬
+ ¡¡¡¡7¡¡¡¡¡¡¢¬
+ 4 [reserved]
+
+¡¡¡¡ ########################################
+ ¡¡¡¡# ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ¡¡¡¡########################################
+
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É¿ô
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ############################################
+ ¡¡¡¡# ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Îΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ############################################
+
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##################################
+ ¡¡¡¡# ¤·¤­¤¤Ã;ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##################################
+
+ 2 ¤·¤­¤¤Ã;ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##############################
+ ¡¡¡¡# ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##############################
+
+ 2 ¥ê¥¶¡¼¥ÖÎΰè¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+
+ ########################
+ # ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ #
+ ########################
+
+¡¡¡¡¡¡¡¡ 1 ¥·¥¹¥Æ¥à¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ 0 [reserved]
+ ¡¡¡¡1 ¡¡¡¡¢¬
+ ¡¡¡¡2 ¡¡¡¡¢¬
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 3 [reserved]
+ 32 ¥·¥¹¥Æ¥à¤Î¾ðÊó¡Ê¥·¥¹¥Æ¥à̾¡Ë
+ 4 ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼
+ 4 ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼
+ 4 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 640 ¥Ð¥¤¥È
+
+
+ #######################################
+ # ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ #
+ #######################################
+
+ 1 ¸½ºß¤ÎÄÌÊó¥ì¥Ù¥ë
+ 16 ALIVE°ì¼¡ÄÌÊóÀè
+ 16 ALIVEÆó¼¡ÄÌÊóÀè
+ 47 [reserved for pager call]
+
+-----------------------------------------------------------------------------
+TOTAL 80 ¥Ð¥¤¥È
+
+
+ ##############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ##############################################################################
+
+ 48 [reserved]
+
+
+ #######################
+ # ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô #
+ #######################
+
+ 400 1bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 16
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1¡¡¡¡¥Õ¥é¥°
+
+ ¡¡¡¡ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7¡¡¡¡ ¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+ 100 2bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 4
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5¡¡ ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+
+-----------------------------------------------------------------------------
+TOTAL 500 ¥Ð¥¤¥È
+
+
+ ###############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ###############################################################################
+
+ 12 [reserved]
+
+
+ ##########################
+ # ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô #
+ ##########################
+
+ 2048 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô (1¥ì¥³¡¼¥É512¥Ð¥¤¥È ¡ß 4 ¡á 2K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Dump/Dump SW 0:D 1:D SW
+ ¡¡¡¡3 ÄÌÊó¤Î̵ͭ 0:̤ 1:ºÑ
+ ¡¡¡¡4 boot·ë²Ì 0:Àµ¾ï 1:°Û¾ï
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 496 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó
+ 1 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 2048 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç3328¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ###############################################################
+ # ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) #
+ ###############################################################
+
+ 4096 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Panic/Shutdown 0:P 1:S
+ ¡¡¡¡3 [reserved]
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 20 ¥½¡¼¥¹Ì¾
+ 80 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó
+ 13 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 4096 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç7424¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ##############################
+ # ¤·¤­¤¤ÃÍȽÄêÍѥǡ¼¥¿Îΰè #
+ ##############################
+
+ ¡¡ 256 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 256 ¥Ð¥¤¥È
+
+
+ ###############################################################
+ # ¢¬¤³¤³¤Þ¤Ç7680(7K+512)¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ ###############################################################
+
+
+ ##############################
+ # ¥ê¥¶¡¼¥ÖÎΰè (512¥Ð¥¤¥È) #
+ ##############################
+
+ 512 PAiNTSÍÑ?
+
+-----------------------------------------------------------------------------
+TOTAL 512 ¥Ð¥¤¥È
+
+
+ #############################################
+ # ¢¬¤³¤³¤Þ¤Ç8192(8K)¥Ð¥¤¥È¡£NVRAM¤Î¤·¤Ã¤Ý #
+ #############################################
+
+******************************************************************************/
+
+
+#pragma pack(1)
+
+/********************
+ * *
+ * ¡¡¹½Â¤ÂÎÄêµÁ *
+ * *
+ ********************/
+
+
+/*
+ * WAS & PS¶¦ÄÌFWÍÑ¥á¥â¥ê¥¨¥é¡¼¾ðÊóÎΰè
+ */
+typedef struct _MEM_ERR_REC {
+ unsigned char mem_status; /* ¥¹¥Æ¡¼¥¿¥¹ */
+ unsigned char err_count; /* 1bit¥¨¥é¡¼¥«¥¦¥ó¥È */
+} MEM_ERR_REC, *pMEM_ERR_REC;
+
+
+/*
+ * ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ALIVE_AREA_INFO {
+ unsigned short offset_alive;
+ /* ALIVE¾ðÊ󥨥ꥢ¥ª¥Õ¥»¥Ã¥È */
+} ALIVE_AREA_INFO, *pALIVE_AREA_INFO;
+
+
+/*
+ * ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC1_ERR_AREA_INFO {
+ unsigned short offset_1biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char err_count_group0; /* ¥á¥â¥êG#0 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group1; /* ¥á¥â¥êG#1 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group2; /* ¥á¥â¥êG#2 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group3; /* ¥á¥â¥êG#3 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group4; /* ¥á¥â¥êG#4 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group5; /* ¥á¥â¥êG#5 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group6; /* ¥á¥â¥êG#6 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group7; /* ¥á¥â¥êG#7 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO;
+
+
+/*
+ * ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC2_ERR_AREA_INFO {
+ unsigned short offset_2biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char simm_flag_group1; /* ¥á¥â¥êG#1ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group2; /* ¥á¥â¥êG#2ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group3; /* ¥á¥â¥êG#3ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group4; /* ¥á¥â¥êG#4ÆâSIMM¥Õ¥é¥° */
+ char reserved[4]; /* reserved */
+} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _SYSTEM_ERR_AREA_INFO {
+ unsigned short offset_systemerr;/* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO;
+
+
+/*
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _CRITICAL_ERR_AREA_INFO {
+ unsigned short offset_critical; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO;
+
+
+/*
+ * ¤·¤­¤¤ÃÍÅù¤½¤Î¾¤Î¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _MISC_AREA_INFO {
+ unsigned short offset_misc;
+ /* ¤·¤­¤¤¤ÁÅù¤Î¾ðÊ󥨥ꥢÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} MISC_AREA_INFO, *pMISC_AREA_INFO;
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _RESERVE_AREA_INFO {
+ unsigned short offset_reserve;
+ /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢ÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ
+ * 49¥Ð¥¤¥È
+ */
+
+typedef struct _SYS_INFO {
+ unsigned char system_flag; /* ¥·¥¹¥Æ¥à¾õÂ֥ե饰 */
+ char reserved1[3]; /* 4byte alignment¤Ë¤½¤Ê¤¨¤Æ */
+ char sys_description[32]; /* ¥·¥¹¥Æ¥à¤Î¾ðÊó */
+ unsigned long serical_num; /* ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼ */
+ unsigned long magic; /* ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ */
+ char reserved2[4]; /* reserved */
+} SYS_INFO, *pSYS_INFO;
+
+
+
+/*
+ * NVRAM¥Ø¥Ã¥ÀÉô
+ * 640¥Ð¥¤¥È
+ */
+
+typedef struct _NVRAM_HEADER {
+ MEM_ERR_REC mem_err_map[256]; /* ¥á¥â¥ê¥¨¥é¡¼¾ðÊóNT&NW¶¦ÄÌ¥¨¥ê¥¢ */
+ unsigned char nvram_flag; /* nvram¤Î¾õÂ֥ե饰 */
+ char when_formatted[14]; /* ¥Õ¥©¡¼¥Þ¥Ã¥È¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char reserved[3]; /* 4byte alignment ¤Ë¤½¤Ê¤¨¤Æ */
+ ALIVE_AREA_INFO alive; /* ALIVE¾ðÊ󥨥ꥢ */
+ ECC1_ERR_AREA_INFO ecc1bit_err; /* ECC1bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ ECC2_ERR_AREA_INFO ecc2bit_err; /* ECC2bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ SYSTEM_ERR_AREA_INFO system_err;/* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ CRITICAL_ERR_AREA_INFO critical_err_log;
+ /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥¨¥ê¥¢ */
+ MISC_AREA_INFO misc; /* ¤·¤­¤¤¤Á¾ðÊ󥨥ꥢ */
+ RESERVE_AREA_INFO reserve; /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢¥ª¥Õ¥»¥Ã¥È */
+ SYS_INFO system; /* ¥·¥¹¥Æ¥à¾ðÊó */
+} NVRAM_HEADER, *pNVRAM_HEADER;
+
+
+
+/*
+ * ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ
+ * 80¥Ð¥¤¥È
+ */
+
+typedef struct _ALIVE_INFO {
+ unsigned char alert_level; /* ÄÌÊó¥ì¥Ù¥ë¥° */
+ char primary_destination[16]; /* °ì¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char secondary_destinaiton[16]; /* Æó¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char reserved[47]; /* reserved for pager call */
+} ALIVE_INFO, *pALIVE_INFO;
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved[48];
+
+
+typedef struct _ECC1_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC1_ERR_REC, *pECC1_ERR_REC;
+
+
+typedef struct _ECC2_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC2_ERR_REC, *pECC2_ERR_REC;
+
+
+/*
+ * ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô
+ * 500 ¥Ð¥¤¥È
+ */
+
+ECC1_ERR_REC ecc1_err_rec_log[16];
+
+ECC2_ERR_REC ecc2_err_rec_log[4];
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved2[12];
+
+
+typedef struct _STOP_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char err_description[496]; /* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó */
+ char reserved[1]; /* reserved */
+} STOP_ERR_REC, *pSTOP_ERR_REC;
+
+/*
+ * ¥¹¥Ã¥È¥×¥¨¥é¡¼¾ðÊóÉô
+ * 2048 ¥Ð¥¤¥È
+ */
+
+STOP_ERR_REC stop_err_rec_log[4];
+
+
+typedef struct _CRITICAL_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char source[14]; /* ¥½¡¼¥¹Ì¾ */
+ char err_description[496]; /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó */
+ char reserved[13]; /* reserved */
+} CRITICAL_ERR_REC, *pCRITICAL;
+
+
+/* ¡¡
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+ * 4096¥Ð¥¤¥È
+ */
+
+CRITICAL_ERR_REC critical_err_rec_log[32];
+
+
+/*
+ * ¤·¤­¤¤ÃÍȽÄêÍÑÅù¥Ç¡¼¥¿Îΰè.
+ * 256¥Ð¥¤¥È
+ */
+
+char reserved3[256]; /* reserved */
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè(PAiNTSÍÑ?)
+ * 512¥Ð¥¤¥È
+ */
+
+char reserved4[512]; /* reserved for paints ? */
+
+#pragma pack(4)
diff --git a/private/ntos/nthals/halr94a/mips/glint.h b/private/ntos/nthals/halr94a/mips/glint.h
new file mode 100644
index 000000000..ac8c6e07a
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/glint.h
@@ -0,0 +1,580 @@
+// #pragma comment(exestr, "@(#) glint.h 1.1 95/09/28 15:32:57 nec")
+/************************************************************************
+ * *
+ * Copyright (c) 1994 3Dlabs Inc. Ltd. *
+ * All rights reserved *
+ * *
+ * This software and its associated documentation contains proprietary, *
+ * confidential and trade secret information of 3Dlabs Inc. Ltd. and *
+ * except as provided by written agreement with 3Dlabs Inc. Ltd. *
+ * *
+ * a) no part may be disclosed, distributed, reproduced, transmitted, *
+ * transcribed, stored in a retrieval system, adapted or translated *
+ * in any form or by any means electronic, mechanical, magnetic, *
+ * optical, chemical, manual or otherwise, *
+ * *
+ * and *
+ * *
+ * b) the recipient is not entitled to discover through reverse *
+ * engineering or reverse compiling or other such techniques or *
+ * processes the trade secrets contained therein or in the *
+ * documentation. *
+ * *
+ ************************************************************************/
+
+#ifndef __GLINT_H__
+#define __GLINT_H__
+
+typedef unsigned long DWORD;
+
+/************************************************************************/
+/* PCI CONFIGURATION REGION */
+/************************************************************************/
+
+#define __GLINT_CFGVendorId PCI_CS_VENDOR_ID
+#define __GLINT_CFGDeviceId PCI_CS_DEVICE_ID
+#define __GLINT_CFGRevisionId PCI_CS_REVISION_ID
+#define __GLINT_CFGClassCode PCI_CS_CLASS_CODE
+#define __GLINT_CFGHeaderType PCI_CS_HEADER_TYPE
+#define __GLINT_CFGCommand PCI_CS_COMMAND
+#define __GLINT_CFGStatus PCI_CS_STATUS
+#define __GLINT_CFGBist PCI_CS_BIST
+#define __GLINT_CFGLatTimer PCI_CS_MASTER_LATENCY
+#define __GLINT_CFGCacheLine PCI_CS_CACHE_LINE_SIZE
+#define __GLINT_CFGMaxLat PCI_CS_MAX_LAT
+#define __GLINT_CFGMinGrant PCI_CS_MIN_GNT
+#define __GLINT_CFGIntPin PCI_CS_INTERRUPT_PIN
+#define __GLINT_CFGIntLine PCI_CS_INTERRUPT_LINE
+
+#define __GLINT_CFGBaseAddr0 PCI_CS_BASE_ADDRESS_0
+#define __GLINT_CFGBaseAddr1 PCI_CS_BASE_ADDRESS_1
+#define __GLINT_CFGBaseAddr2 PCI_CS_BASE_ADDRESS_2
+#define __GLINT_CFGBaseAddr3 PCI_CS_BASE_ADDRESS_3
+#define __GLINT_CFGBaseAddr4 PCI_CS_BASE_ADDRESS_4
+#define __GLINT_CFGRomAddr PCI_CS_EXPANSION_ROM
+
+/* CFGVendorId[15:0] - 3Dlabs Vendor ID Value */
+
+#define GLINT_VENDOR_ID (0x3D3D)
+
+/* CFGDeviceId[15:0] - GLINT 300SX Device ID */
+
+#define GLINT_DEVICE_ID (0x0001)
+
+/* CFGRevisionID[7:0] - GLINT Revision Code */
+
+#define GLINT_REVISION_A (0x00)
+#define GLINT_REVISION_B (0x01)
+
+/* CFGClassCode[23:0] - Other Display Controller */
+
+#define GLINT_CLASS_CODE ((DWORD) 0x00038000)
+
+/* CFGHeaderType[7:0] - Single Function Device */
+
+#define GLINT_HEADER_TYPE (0x00)
+
+/* CFGCommand[15:0] - Reset Value Zero */
+
+#define GLINT_COMMAND_RESET_VALUE (0x0000)
+
+/* CFGCommand[1] - Memory Access Enable */
+
+#define GLINT_MEMORY_ACCESS_MASK (1 << 0)
+#define GLINT_MEMORY_ACCESS_DISABLE (0 << 0)
+#define GLINT_MEMORY_ACCESS_ENABLE (1 << 1)
+
+/* CFGCommand[2] - Master Enable */
+
+#define GLINT_MASTER_ENABLE_MASK (1 << 2)
+#define GLINT_MASTER_DISABLE (0 << 2)
+#define GLINT_MASTER_ENABLE (1 << 2)
+
+/* CFGStatus[15:0] - Reset Value Zero */
+
+#define GLINT_STATUS_RESET_VALUE (0x0000)
+
+/* CFGBist - Built In Self Test Unsupported */
+
+#define GLINT_BIST (0x00)
+
+/* CFGCacheLine - Cache Line Size Unsupported */
+
+#define GLINT_CACHE_LINE (0x00)
+
+/* CFGIntPin - Interrupt Pin INTA# */
+
+#define GLINT_INTERRUPT_PIN (0x01)
+
+/********************/
+
+#define GLINT_CONTROL_BASE __GLINT_CFGBaseAddr0
+#define GLINT_LOCAL_0_BASE __GLINT_CFGBaseAddr1
+#define GLINT_FRAME_0_BASE __GLINT_CFGBaseAddr2
+#define GLINT_LOCAL_1_BASE __GLINT_CFGBaseAddr3
+#define GLINT_FRAME_1_BASE __GLINT_CFGBaseAddr4
+#define GLINT_EPROM_BASE __GLINT_CFGRomAddr
+
+#define GLINT_EPROM_SIZE ((DWORD)(64L * 1024L))
+
+/************************************************************************/
+/* CONTROL AND STATUS REGISTERS */
+/************************************************************************/
+
+#define GLINT_REGION_0_SIZE ((DWORD)(128L * 1024L))
+
+#define __GLINT_ResetStatus 0x0000
+#define __GLINT_IntEnable 0x0008
+#define __GLINT_IntFlags 0x0010
+#define __GLINT_InFIFOSpace 0x0018
+#define __GLINT_OutFIFOWords 0x0020
+#define __GLINT_DMAAddress 0x0028
+#define __GLINT_DMACount 0x0030
+#define __GLINT_ErrorFlags 0x0038
+#define __GLINT_VClkCtl 0x0040
+#define __GLINT_TestRegister 0x0048
+#define __GLINT_Aperture0 0x0050
+#define __GLINT_Aperture1 0x0058
+#define __GLINT_DMAControl 0x0060
+
+/* ResetStatus[31] - Software Reset Flag */
+
+#define GLINT_RESET_STATUS_MASK ((DWORD) 1 << 31)
+#define GLINT_READY_FOR_USE ((DWORD) 0 << 31)
+#define GLINT_RESET_IN_PROGRESS ((DWORD) 1 << 31)
+
+/* IntEnable[4:0] - Interrupt Enable Register */
+
+#define GLINT_INT_ENABLE_DMA ((DWORD) 1 << 0)
+#define GLINT_INT_ENABLE_SYNC ((DWORD) 1 << 1)
+#define GLINT_INT_ENABLE_EXTERNAL ((DWORD) 1 << 2)
+#define GLINT_INT_ENABLE_ERROR ((DWORD) 1 << 3)
+#define GLINT_INT_ENABLE_VERTICAL ((DWORD) 1 << 4)
+
+/* IntFlags[4:0] - Interrupt Flags Register */
+
+#define GLINT_INT_FLAG_DMA ((DWORD) 1 << 0)
+#define GLINT_INT_FLAG_SYNC ((DWORD) 1 << 1)
+#define GLINT_INT_FLAG_EXTERNAL ((DWORD) 1 << 2)
+#define GLINT_INT_FLAG_ERROR ((DWORD) 1 << 3)
+#define GLINT_INT_FLAG_VERTICAL ((DWORD) 1 << 4)
+
+/* ErrorFlags[2:0] - Error Flags Register */
+
+#define GLINT_ERROR_INPUT_FIFO ((DWORD) 1 << 0)
+#define GLINT_ERROR_OUTPUT_FIFO ((DWORD) 1 << 1)
+#define GLINT_ERROR_COMMAND ((DWORD) 1 << 2)
+
+/* ApertureX[1:0] - Framebuffer Byte Control */
+
+#define GLINT_FB_BYTE_CONTROL_MASK ((DWORD) 3 << 0)
+#define GLINT_FB_LITTLE_ENDIAN ((DWORD) 0 << 0)
+#define GLINT_FB_BIG_ENDIAN ((DWORD) 1 << 0)
+#define GLINT_FB_GIB_ENDIAN ((DWORD) 2 << 0)
+#define GLINT_FB_BYTE_RESERVED ((DWORD) 3 << 0)
+
+/* ApertureX[2] - Localbuffer Byte Control */
+
+#define GLINT_LB_BYTE_CONTROL_MASK ((DWORD) 1 << 2)
+#define GLINT_LB_LITTLE_ENDIAN ((DWORD) 0 << 2)
+#define GLINT_LB_BIG_ENDIAN ((DWORD) 1 << 2)
+
+/* DMAControl[0] - DMA Byte Swap Control */
+
+#define GLINT_DMA_CONTROL_MASK ((DWORD) 1 << 0)
+#define GLINT_DMA_LITTLE_ENDIAN ((DWORD) 0 << 0)
+#define GLINT_DMA_BIG_ENDIAN ((DWORD) 1 << 0)
+
+/************************************************************************/
+/* LOCALBUFFER REGISTERS */
+/************************************************************************/
+
+#define __GLINT_LBMemoryCtl 0x1000
+
+/* LBMemoryCtl[0] - Number of Localbuffer Banks */
+
+#define GLINT_LB_BANK_MASK ((DWORD) 1 << 0)
+#define GLINT_LB_ONE_BANK ((DWORD) 0 << 0)
+#define GLINT_LB_TWO_BANKS ((DWORD) 1 << 0)
+
+/* LBMemoryCtl[2:1] - Localbuffer Page Size */
+
+#define GLINT_LB_PAGE_SIZE_MASK ((DWORD) 2 << 1)
+#define GLINT_LB_PAGE_SIZE_256_PIXELS ((DWORD) 0 << 1)
+#define GLINT_LB_PAGE_SIZE_512_PIXELS ((DWORD) 1 << 1)
+#define GLINT_LB_PAGE_SIZE_1024_PIXELS ((DWORD) 2 << 1)
+#define GLINT_LB_PAGE_SIZE_2048_PIXELS ((DWORD) 3 << 1)
+
+/* LBMemoryCtl[4:3] - Localbuffer RAS-CAS Low */
+
+#define GLINT_LB_RAS_CAS_LOW_MASK ((DWORD) 3 << 3)
+#define GLINT_LB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 3)
+#define GLINT_LB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 3)
+#define GLINT_LB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 3)
+#define GLINT_LB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 3)
+
+/* LBMemoryCtl[6:5] - Localbuffer RAS Precharge */
+
+#define GLINT_LB_RAS_PRECHARGE_MASK ((DWORD) 3 << 5)
+#define GLINT_LB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 5)
+#define GLINT_LB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 5)
+#define GLINT_LB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 5)
+#define GLINT_LB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 5)
+
+/* LBMemoryCtl[8:7] - Localbuffer CAS Low */
+
+#define GLINT_LB_CAS_LOW_MASK ((DWORD) 3 << 7)
+#define GLINT_LB_CAS_LOW_1_CLOCK ((DWORD) 0 << 7)
+#define GLINT_LB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 7)
+#define GLINT_LB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 7)
+#define GLINT_LB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 7)
+
+/* LBMemoryCtl[9] - Localbuffer Page Mode Disable */
+
+#define GLINT_LB_PAGE_MODE_MASK ((DWORD) 1 << 9)
+#define GLINT_LB_PAGE_MODE_ENABLE ((DWORD) 0 << 9)
+#define GLINT_LB_PAGE_MODE_DISABLE ((DWORD) 1 << 9)
+
+/* LBMemoryCtl[17:10] - Localbuffer Refresh Count */
+
+#define GLINT_LB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 10)
+#define GLINT_LB_REFRESH_COUNT_SHIFT (10)
+
+#define GLINT_LB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 10)
+
+/* LBMemoryCtl[18] - Localbuffer Dual Write Enables */
+
+#define GLINT_LB_MEM_TYPE_MASK ((DWORD) 1 << 18)
+#define GLINT_LB_MEM_DUAL_CAS ((DWORD) 0 << 18)
+#define GLINT_LB_MEM_DUAL_WE ((DWORD) 1 << 18)
+
+/* LBMemoryCtl[21:20] - PCI Maximum Latency - Read Only */
+
+#define GLINT_PCI_MAX_LATENCY_MASK ((DWORD) 3 << 20)
+#define GLINT_PCI_MAX_LATENCY_SHIFT (20)
+
+/* LBMemoryCtl[23:22] - PCI Minimum Grant - Read Only */
+
+#define GLINT_PCI_MIN_GRANT_MASK ((DWORD) 3 << 22)
+#define GLINT_PCI_MIN_GRANT_SHIFT (22)
+
+/* LBMemoryCtl[26:24] - Localbuffer Visible Region Size - Read Only */
+
+#define GLINT_LB_REGION_SIZE_MASK ((DWORD) 7 << 24)
+#define GLINT_LB_REGION_SIZE_1_MB ((DWORD) 0 << 24)
+#define GLINT_LB_REGION_SIZE_2_MB ((DWORD) 1 << 24)
+#define GLINT_LB_REGION_SIZE_4_MB ((DWORD) 2 << 24)
+#define GLINT_LB_REGION_SIZE_8_MB ((DWORD) 3 << 24)
+#define GLINT_LB_REGION_SIZE_16_MB ((DWORD) 4 << 24)
+#define GLINT_LB_REGION_SIZE_32_MB ((DWORD) 5 << 24)
+#define GLINT_LB_REGION_SIZE_64_MB ((DWORD) 6 << 24)
+#define GLINT_LB_REGION_SIZE_0_MB ((DWORD) 7 << 24)
+
+/* LBMemoryCtl[29:27] - Localbuffer Width - Read Only */
+
+#define GLINT_LB_WIDTH_MASK ((DWORD) 7 << 27)
+#define GLINT_LB_WIDTH_16_BITS ((DWORD) 0 << 27)
+#define GLINT_LB_WIDTH_18_BITS ((DWORD) 1 << 27)
+#define GLINT_LB_WIDTH_24_BITS ((DWORD) 2 << 27)
+#define GLINT_LB_WIDTH_32_BITS ((DWORD) 3 << 27)
+#define GLINT_LB_WIDTH_36_BITS ((DWORD) 4 << 27)
+#define GLINT_LB_WIDTH_40_BITS ((DWORD) 5 << 27)
+#define GLINT_LB_WIDTH_48_BITS ((DWORD) 6 << 27)
+#define GLINT_LB_WIDTH_OTHER ((DWORD) 7 << 27)
+
+/* LBMemoryCtl[30] - Localbuffer Bypass Packing - Read Only */
+
+#define GLINT_LB_BYPASS_STEP_MASK ((DWORD) 1 << 30)
+#define GLINT_LB_BYPASS_STEP_64_BITS ((DWORD) 0 << 30)
+#define GLINT_LB_BYPASS_STEP_32_BITS ((DWORD) 1 << 30)
+
+/* LBMemoryCtl[31] - Localbuffer Aperture One Enable - Read Only */
+
+#define GLINT_LB_APERTURE_ONE_MASK ((DWORD) 1 << 31)
+#define GLINT_LB_APERTURE_ONE_DISABLE ((DWORD) 0 << 31)
+#define GLINT_LB_APERTURE_ONE_ENABLE ((DWORD) 1 << 31)
+
+/************************************************************************/
+/* FRAMEBUFFER REGISTERS */
+/************************************************************************/
+
+#define __GLINT_FBMemoryCtl 0x1800
+#define __GLINT_FBModeSel 0x1808
+#define __GLINT_FBGCWrMask 0x1810
+#define __GLINT_FBGCColorMask 0x1818
+
+/* FBMemoryCtl[1:0] - Framebuffer RAS-CAS Low */
+
+#define GLINT_FB_RAS_CAS_LOW_MASK ((DWORD) 3 << 0)
+#define GLINT_FB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 0)
+#define GLINT_FB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 0)
+#define GLINT_FB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 0)
+#define GLINT_FB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 0)
+
+/* FBMemoryCtl[3:2] - Framebuffer RAS Precharge */
+
+#define GLINT_FB_RAS_PRECHARGE_MASK ((DWORD) 3 << 2)
+#define GLINT_FB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 2)
+#define GLINT_FB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 2)
+#define GLINT_FB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 2)
+#define GLINT_FB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 2)
+
+/* FBMemoryCtl[5:4] - Framebuffer CAS Low */
+
+#define GLINT_FB_CAS_LOW_MASK ((DWORD) 3 << 4)
+#define GLINT_FB_CAS_LOW_1_CLOCK ((DWORD) 0 << 4)
+#define GLINT_FB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 4)
+#define GLINT_FB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 4)
+#define GLINT_FB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 4)
+
+/* FBMemoryCtl[13:6] - Framebuffer Refresh Count */
+
+#define GLINT_FB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 6)
+#define GLINT_FB_REFRESH_COUNT_SHIFT (6)
+
+#define GLINT_FB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 6)
+
+/* FBMemoryCtl[14] - Framebuffer Page Mode Disable */
+
+#define GLINT_FB_PAGE_MODE_MASK ((DWORD) 1 << 14)
+#define GLINT_FB_PAGE_MODE_ENABLE ((DWORD) 0 << 14)
+#define GLINT_FB_PAGE_MODE_DISABLE ((DWORD) 1 << 14)
+
+/* FBMemoryCtl[25:20] - Reserved - Read Only */
+
+#define GLINT_FB_CTL_RESERVED_MASK ((DWORD) 0x3F << 20)
+#define GLINT_FB_CTL_RESERVED_SHIFT (20)
+
+/* FBMemoryCtl[26] - Byte Swap Configuration Space - Read Only */
+
+#define GLINT_BYTE_SWAP_CONFIG_MASK ((DWORD) 1 << 26)
+#define GLINT_BYTE_SWAP_CONFIG_DISABLE ((DWORD) 0 << 26)
+#define GLINT_BYTE_SWAP_CONFIG_ENABLE ((DWORD) 1 << 26)
+
+/* FBMemoryCtl[28] - Framebuffer Aperture One Enable - Read Only */
+
+#define GLINT_FB_APERTURE_ONE_MASK ((DWORD) 1 << 28)
+#define GLINT_FB_APERTURE_ONE_DISABLE ((DWORD) 0 << 28)
+#define GLINT_FB_APERTURE_ONE_ENABLE ((DWORD) 1 << 28)
+
+/* FBMemoryCtl[31:29] - Framebuffer Visible Region Size - Read Only */
+
+#define GLINT_FB_REGION_SIZE_MASK ((DWORD) 7 << 29)
+#define GLINT_FB_REGION_SIZE_1_MB ((DWORD) 0 << 29)
+#define GLINT_FB_REGION_SIZE_2_MB ((DWORD) 1 << 29)
+#define GLINT_FB_REGION_SIZE_4_MB ((DWORD) 2 << 29)
+#define GLINT_FB_REGION_SIZE_8_MB ((DWORD) 3 << 29)
+#define GLINT_FB_REGION_SIZE_16_MB ((DWORD) 4 << 29)
+#define GLINT_FB_REGION_SIZE_32_MB ((DWORD) 5 << 29)
+#define GLINT_FB_REGION_SIZE_RESERVED ((DWORD) 6 << 29)
+#define GLINT_FB_REGION_SIZE_0_MB ((DWORD) 7 << 29)
+
+/* FBModeSel[0] - Framebuffer Width */
+
+#define GLINT_FB_WIDTH_MASK ((DWORD) 1 << 0)
+#define GLINT_FB_WIDTH_32_BITS ((DWORD) 0 << 0)
+#define GLINT_FB_WIDTH_64_BITS ((DWORD) 1 << 0)
+
+/* FBModeSel[2:1] - Framebuffer Packing */
+
+#define GLINT_FB_PACKING_MASK ((DWORD) 2 << 1)
+#define GLINT_FB_PACKING_32_BITS ((DWORD) 0 << 1)
+#define GLINT_FB_PACKING_16_BITS ((DWORD) 1 << 1)
+#define GLINT_FB_PACKING_8_BITS ((DWORD) 2 << 1)
+#define GLINT_FB_PACKING_RESERVED ((DWORD) 3 << 1)
+
+/* FBModeSel[3] - Fast Mode Disable */
+
+#define GLINT_FB_FAST_MODE_MASK ((DWORD) 1 << 3)
+#define GLINT_FB_FAST_MODE_ENABLE ((DWORD) 0 << 3)
+#define GLINT_FB_FAST_MODE_DISABLE ((DWORD) 1 << 3)
+
+/* FBModeSel[5:4] - Shared Framebuffer Mode - Read Only */
+
+#define GLINT_SFB_MODE_MASK ((DWORD) 3 << 4)
+#define GLINT_SFB_DISABLED ((DWORD) 0 << 4)
+#define GLINT_SFB_ARBITER ((DWORD) 1 << 4)
+#define GLINT_SFB_REQUESTER ((DWORD) 2 << 4)
+#define GLINT_SFB_RESERVED ((DWORD) 3 << 4)
+
+/* FBModeSel[6] - Transfer Disable */
+
+#define GLINT_TRANSFER_MODE_MASK ((DWORD) 1 << 6)
+#define GLINT_TRANSFER_ENABLE ((DWORD) 0 << 6)
+#define GLINT_TRANSFER_DISABLE ((DWORD) 1 << 6)
+
+/* FBModeSel[7] - External VTG Select */
+
+#define GLINT_VTG_SELECT_MASK ((DWORD) 1 << 7)
+#define GLINT_INTERNAL_VTG ((DWORD) 0 << 7)
+#define GLINT_EXTERNAL_VTG ((DWORD) 1 << 7)
+
+/* FBModeSel[9:8] - Framebuffer Interleave */
+
+#define GLINT_FB_INTERLEAVE_MASK ((DWORD) 3 << 8)
+#define GLINT_FB_INTERLEAVE_1_WAY ((DWORD) 0 << 8)
+#define GLINT_FB_INTERLEAVE_2_WAY ((DWORD) 1 << 8)
+#define GLINT_FB_INTERLEAVE_4_WAY ((DWORD) 2 << 8)
+#define GLINT_FB_INTERLEAVE_8_WAY ((DWORD) 3 << 8)
+
+/* FBModeSel[11:10] - Framebuffer Block Fill Size */
+
+#define GLINT_FB_BLOCK_FILL_SIZE_MASK ((DWORD) 3 << 10)
+#define GLINT_FB_BLOCK_FILL_UNSUPPORTED ((DWORD) 0 << 10)
+#define GLINT_FB_BLOCK_FILL_4_PIXEL ((DWORD) 1 << 10)
+#define GLINT_FB_BLOCK_FILL_8_PIXEL ((DWORD) 2 << 10)
+#define GLINT_FB_BLOCK_FILL_RESERVED ((DWORD) 3 << 10)
+
+/* FBModeSel[12] - Framebuffer Dual Write Enables */
+
+#define GLINT_FB_MEM_TYPE_MASK ((DWORD) 1 << 12)
+#define GLINT_FB_MEM_DUAL_CAS ((DWORD) 0 << 12)
+#define GLINT_FB_MEM_DUAL_WE ((DWORD) 1 << 12)
+
+/************************************************************************/
+/* INTERNAL VIDEO TIMING GENERATOR REGISTERS */
+/************************************************************************/
+
+#define __GLINT_VTGHLimit 0x3000
+#define __GLINT_VTGHSyncStart 0x3008
+#define __GLINT_VTGHSyncEnd 0x3010
+#define __GLINT_VTGHBlankEnd 0x3018
+#define __GLINT_VTGVLimit 0x3020
+#define __GLINT_VTGVSyncStart 0x3028
+#define __GLINT_VTGVSyncEnd 0x3030
+#define __GLINT_VTGVBlankEnd 0x3038
+#define __GLINT_VTGHGateStart 0x3040
+#define __GLINT_VTGHGateEnd 0x3048
+#define __GLINT_VTGVGateStart 0x3050
+#define __GLINT_VTGVGateEnd 0x3058
+#define __GLINT_VTGPolarity 0x3060
+#define __GLINT_VTGFrameRowAddr 0x3068
+#define __GLINT_VTGVLineNumber 0x3070
+#define __GLINT_VTGSerialClk 0x3078
+
+/* VTGPolarity[1:0] - HSync Ctl */
+
+#define GLINT_HSYNC_POLARITY_MASK ((DWORD) 3 << 0)
+#define GLINT_HSYNC_ACTIVE_HIGH ((DWORD) 0 << 0)
+#define GLINT_HSYNC_FORCED_HIGH ((DWORD) 1 << 0)
+#define GLINT_HSYNC_ACTIVE_LOW ((DWORD) 2 << 0)
+#define GLINT_HSYNC_FORCED_LOW ((DWORD) 3 << 0)
+
+/* VTGPolarity[3:2] - Vsync Ctl */
+
+#define GLINT_VSYNC_POLARITY_MASK ((DWORD) 3 << 2)
+#define GLINT_VSYNC_ACTIVE_HIGH ((DWORD) 0 << 2)
+#define GLINT_VSYNC_FORCED_HIGH ((DWORD) 1 << 2)
+#define GLINT_VSYNC_ACTIVE_LOW ((DWORD) 2 << 2)
+#define GLINT_VSYNC_FORCED_LOW ((DWORD) 3 << 2)
+
+/* VTGPolarity[5:4] - Csync Ctl */
+
+#define GLINT_CSYNC_POLARITY_MASK ((DWORD) 3 << 4)
+#define GLINT_CSYNC_ACTIVE_HIGH ((DWORD) 0 << 4)
+#define GLINT_CSYNC_FORCED_HIGH ((DWORD) 1 << 4)
+#define GLINT_CSYNC_ACTIVE_LOW ((DWORD) 2 << 4)
+#define GLINT_CSYNC_FORCED_LOW ((DWORD) 3 << 4)
+
+/* VTGPolarity[7:6] - CBlank Ctl */
+
+#define GLINT_CBLANK_POLARITY_MASK ((DWORD) 3 << 6)
+#define GLINT_CBLANK_ACTIVE_HIGH ((DWORD) 0 << 6)
+#define GLINT_CBLANK_FORCED_HIGH ((DWORD) 1 << 6)
+#define GLINT_CBLANK_ACTIVE_LOW ((DWORD) 2 << 6)
+#define GLINT_CBLANK_FORCED_LOW ((DWORD) 3 << 6)
+
+/* VTGSerialClk[0] - QSF Select */
+
+#define GLINT_QSF_SELECT_MASK ((DWORD) 1 << 0)
+#define GLINT_EXTERNAL_QSF ((DWORD) 0 << 0)
+#define GLINT_INTERNAL_QSF ((DWORD) 1 << 0)
+
+/* VTGSerialClk[1] - Split Size */
+
+#define GLINT_SPLIT_SIZE_MASK ((DWORD) 1 << 1)
+#define GLINT_SPLIT_SIZE_128_WORD ((DWORD) 0 << 1)
+#define GLINT_SPLIT_SIZE_256_WORD ((DWORD) 1 << 1)
+
+/* VTGSerialClk[2] - SCLK Ctl */
+
+#define GLINT_SCLK_CTL_MASK ((DWORD) 1 << 2)
+#define GLINT_SCLK_VCLK ((DWORD) 0 << 2)
+#define GLINT_SCLK_VCLK_DIV_2 ((DWORD) 1 << 2)
+
+/* VTGSerialClk[3] - SOE Ctl */
+
+#define GLINT_SOE_CTL_MASK ((DWORD) 1 << 3)
+#define GLINT_SOE_0_ASSERTED ((DWORD) 0 << 3)
+#define GLINT_SOE_1_ASSERTED ((DWORD) 1 << 3)
+
+/************************************************************************/
+/* EXTERNAL VIDEO CONTROL REGISTERS */
+/************************************************************************/
+
+#define __GLINT_ExternalVideoControl 0x4000
+
+/************************************************************************/
+/* GRAPHICS CORE REGISTERS AND FIFO INTERFACE */
+/************************************************************************/
+
+#define __GLINT_GraphicsCoreRegisters 0x8000
+
+#define __GLINT_GraphicsFIFOInterface 0x2000
+
+/************************************************************************/
+/* GLINT ACCESS MACROS */
+/************************************************************************/
+
+#define GLINT_ADDR(base, offset) \
+( \
+/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \
+ (DWORD) ((volatile UCHAR *)(base) + (offset)) \
+)
+
+#define GLINT_WRITE(base, offset, data) \
+{ \
+/* DWORD_WRITE(GLINT_ADDR((base),(offset)), (data)); */ \
+ WRITE_REGISTER_ULONG(GLINT_ADDR((base),(offset)), (ULONG)(data)); \
+}
+
+#define GLINT_READ(base, offset, data) \
+{ \
+/* DWORD_READ(GLINT_ADDR((base),(offset)), (data)); */ \
+ (ULONG)(data) = READ_REGISTER_ULONG(GLINT_ADDR((base),(ULONG)(offset))); \
+}
+
+typedef struct
+{
+ /* image size */
+
+ long ImageWidth;
+ long ImageHeight;
+ long ImageDepth;
+
+ /* video timing */
+
+ DWORD HLimit;
+ DWORD HSyncStart;
+ DWORD HSyncEnd;
+ DWORD HBlankEnd;
+ DWORD HSyncPolarity;
+ DWORD VLimit;
+ DWORD VSyncStart;
+ DWORD VSyncEnd;
+ DWORD VBlankEnd;
+ DWORD VSyncPolarity;
+
+ /* Ramdac config */
+
+ DWORD PixelFormat;
+ DWORD RefDivCount;
+ DWORD PixelClock;
+
+ } __VIDEO, *VIDEO;
+
+/************************************************************************/
+
+#endif /* __GLINT_H__ */
+
+/************************************************************************/
diff --git a/private/ntos/nthals/halr94a/mips/halp.h b/private/ntos/nthals/halr94a/mips/halp.h
new file mode 100644
index 000000000..1bd34fd72
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/halp.h
@@ -0,0 +1,367 @@
+// #pragma comment(exestr, "@(#) halp.h 1.1 95/09/28 15:33:24 nec")
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+ L0001 1994.9.20 kbnes!kuriyama(A)
+ -Modify for R94A original halfxs\mips\halp.h
+ -add #include"r94axxx.h "
+ L0002 Thu Oct 13 18:09:33 JST 1994 kbnes!kuriyama(A)
+ - Del HalpDisplayLED
+ - Del HalpLEDDisplayLock
+ - Del HalpLEDControlBase
+ - Add READ_REGISTER_DWORD
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:31:21 JST 1994
+ - add data definitions for HalReportResourceUsage
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:15:11 JST 1994
+ - resolve compile error
+ ADD002 kisimoto@oa2.kb.nec.co.jp Fri Nov 25 15:46:03 1994
+ add HalpGetStatusRegister() definition
+ S0003 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 16:51:00 JST 1995
+ add _IPI_LIMIT_ support
+ H0004 kisimoto@oa2.kb.nec.co.jp Sun Jun 25 14:39:38 1995
+ - Merge build 1057
+ H0005 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 20:03:30 1995
+ - Merge code for ESM from J94C
+ H0006 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 19:23:03 1995
+ - Removed _J94C_ definitions.
+ _J94C_ definition indicates that the status of
+ the dump switch can acknowledge from Self-test
+ register.
+ S0007 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 20:18:18 JST 1995
+ - change for x86bios support
+ H0008 kisimoto@oa2.kb.nec.co.jp Wed Aug 30 12:23:36 1995
+ - add spinlock to support PCI Fast Back-to-back transfer.
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "hal.h" // H0004
+
+#ifndef _HALI_ // H0004
+#include "..\inc\hali.h"
+#endif
+
+#if defined(_DUO_)
+
+#if defined(_R94A_)
+
+#include "r94adma.h"
+#include "r94adef.h"
+#include "r94aint.h"
+
+#else // _R94A_
+
+#include "duodma.h"
+#include "duodef.h"
+#include "duoint.h"
+
+#endif // _R94A_
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdma.h"
+#include "jazzdef.h"
+#include "jazzint.h"
+
+#endif
+
+#include "jxhalp.h"
+
+#if defined(USE_BIOS_EMULATOR) // H0004
+
+#include "xm86.h"
+#include "x86new.h"
+
+#endif
+
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+// S0007
+// change prototype HalpInitializeX86DisplayAdapter()
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+#if defined(_R94A_)
+VOID
+READ_REGISTER_DWORD(
+ PLARGE_INTEGER,
+ PVOID
+ );
+
+VOID
+WRITE_REGISTER_DWORD(
+ PLARGE_INTEGER,
+ PVOID
+ );
+
+VOID
+HalpGetStatusRegister (
+ IN PULONG Variable
+ );
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer,
+ ULONG Write
+);
+#endif
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern USHORT HalpBuiltinInterruptEnable;
+extern ULONG HalpCurrentTimeIncrement;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KAFFINITY HalpEisaBusAffinity;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KSPIN_LOCK HalpIpiRequestLock;
+extern KSPIN_LOCK Ecc1bitDisableLock;// H005
+extern KSPIN_LOCK Ecc1bitRoutineLock;// H005
+extern KSPIN_LOCK HalpPCIBackToBackLock; // H008
+
+
+// ADD001
+//
+// Resource usage information
+//
+
+#if !defined (_R94A_)
+#pragma pack(1)
+#endif
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+#if !defined (_R94A_)
+#pragma pack()
+#endif
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+// CMP001
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern ADDRESS_USAGE HalpMapRegisterMemorySpace;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+// CMP001
+#define IRQ_PREFERRED 0x02
+#define IRQ_VALID 0x01
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+);
+
+//
+// H0004: from halx86/i386/halp.h
+// Temp definitions to thunk into supporting new bus extension format
+//
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+#if DBG
+ int printNvramData(void);
+#endif // DBG
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halr94a/mips/j4cache.s b/private/ntos/nthals/halr94a/mips/j4cache.s
new file mode 100644
index 000000000..0f17e43bf
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/j4cache.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4cache.s"
diff --git a/private/ntos/nthals/halr94a/mips/j4flshbf.s b/private/ntos/nthals/halr94a/mips/j4flshbf.s
new file mode 100644
index 000000000..04012b70b
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/j4flshbf.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshbf.s"
diff --git a/private/ntos/nthals/halr94a/mips/j4flshio.c b/private/ntos/nthals/halr94a/mips/j4flshio.c
new file mode 100644
index 000000000..2461bc392
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/j4flshio.c
@@ -0,0 +1,236 @@
+// #pragma comment(exestr, "@(#) j4flshio.c 1.1 95/09/28 15:34:41 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Fri Sep 30 20:23:02 JST 1994 kbnes!kishimoto
+ - HalFlushIoBuffers()
+ Modify to return only.
+ R94A supports I/O coherency during I/O translation.
+ N.B. This modify is enabled after Beta-machine.
+ _R94ABBMIO_ means that machine is alpha-version.
+ H001 Sat Mar 18 15:19:33 1995 kbnes!kishimoto
+ - if operation is DMA, we have nothing to do.
+
+ M002 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 10:51:41 JST 1995
+ - add support I/O cache limit _IO_LIMIT_
+--*/
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+#if !defined(_IO_LIMIT_) && defined(_R94A_)
+
+ //
+ // H001
+ // R94A supports cache coherency during DMA operation,
+ // so we have nothing to to.
+ //
+
+ if (DmaOperation == TRUE){
+ return;
+ }
+
+#endif
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halr94a/mips/j4prof.c b/private/ntos/nthals/halr94a/mips/j4prof.c
new file mode 100644
index 000000000..dd8c2b7c9
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/j4prof.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4prof.c"
diff --git a/private/ntos/nthals/halr94a/mips/jxbeep.c b/private/ntos/nthals/halr94a/mips/jxbeep.c
new file mode 100644
index 000000000..922c80816
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxbeep.c
@@ -0,0 +1,215 @@
+// #pragma comment(exestr, "@(#) jxbeep.c 1.1 95/09/28 15:35:24 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ M0001 1994.9.12 kbnes!kuriyama
+ Modify for R94A MIPS R4400
+
+ - HalMakeBeep()
+ At R94A system, Buzzer controled by TYPHOON, not by EISA-Bridge.
+ Buzzer ON/OFF, Freequency Control Register was changed.
+
+ S0002 1994.12.22 kbnes!kuriyama
+ cast miss ? fixed
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+/* start M0001 */
+#if defined(_R94A_)
+ BUZZER_CONTROL BuzzerControl;
+#else // _R94A_
+ NMI_STATUS NmiStatus;
+#endif // _R94A_
+/* end M0001 */
+
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ *((PUCHAR)&BuzzerControl) = READ_REGISTER_UCHAR(&DMA_CONTROL->BuzzerControl.Char);
+//S0002
+ BuzzerControl.SpeakerGate = 0;
+ BuzzerControl.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&DMA_CONTROL->BuzzerControl.Char,*((PUCHAR) &BuzzerControl));
+// S0002
+#else // _R94A_
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+/* start M0001 */
+#if defined(_R94A_)
+ //
+ // R94A Support only even value for newCount
+ //
+
+ newCount &= 0xfffe;
+
+ if (newCount == 0) {
+ newCount = 2;
+ }
+
+#else // _R94A_
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ WRITE_REGISTER_USHORT(&DMA_CONTROL->BuzzerCount.Short,(USHORT) newCount);
+// S0002
+
+#else // _R94A_
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Start the speaker.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ *((PUCHAR)&BuzzerControl) = READ_REGISTER_UCHAR(
+ &DMA_CONTROL->BuzzerControl.Char //S0002
+ );
+ BuzzerControl.SpeakerGate = 1;
+ BuzzerControl.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(
+ &DMA_CONTROL->BuzzerControl.Char,//S0002
+ *((PUCHAR) &BuzzerControl)
+ );
+ Result = TRUE;
+
+#else // _R94A_
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+
+#endif // _R94A_
+/* end M0001 */
+
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
+
diff --git a/private/ntos/nthals/halr94a/mips/jxdisp.c b/private/ntos/nthals/halr94a/mips/jxdisp.c
new file mode 100644
index 000000000..fdf7ebb06
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxdisp.c
@@ -0,0 +1,3605 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.2 95/10/17 01:18:22" ) */
+/*++
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a R4400 R94A system.
+
+History:
+
+
+--*/
+
+/*
+ * New Code for 3.51
+ *
+ * M001 kuriyama@oa2.kb.nec.co.jp Fri Jul 14 11:46:06 JST 1995
+ * -change textmode 80x50
+ *
+ * M002 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:36:23 JST 1995
+ * -change for fw interface
+ *
+ * M003 kuriyama@oa2.kb.nec.co.jp Fri Jul 21 14:14:54 JST 1995
+ * -add call HalpResetDisplayParameters
+ * for bug fix DPI board panic message
+ *
+ * M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 2 14:28:28 JST 1995
+ * -add ESM critical error logging
+ *
+ * S005 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 23:42:59 JST 1995
+ * -change for scroll bug fix
+ *
+ * S006 nishi@oa2.kb.nec.co.jp Mon Sep 4 18:42:00 JST 1995
+ * -change for GLINT new revision board
+ * R01=00,R02=02
+ * M007 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995
+ * - Add Software Power Off, when system panic is occured
+ *
+ * M008 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995
+ * - Change Logic for resume fixed TLB for DMA
+ *
+ * M009 kuriyama@oa2.kbnes.nec.co.jp Mon Sep 18 19:58:22 JST 1995
+ * - bug fix for tga 800x600 72Hz
+ *
+ * M010 v-akitk@microsoft.com
+ * - Change for Software Power Supply(R96B)
+ *
+ */
+
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+#include <tga.h>
+#include <glint.h>
+#include <rgb525.h>
+
+#include "string.h"
+#include "pci.h"
+/* START M007 */
+#define HEADER_FILE
+#include "kxmips.h"
+/* START M007 */
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// for x86bios emulate
+//
+PCHAR K351UseBios=NULL;
+VOID HalpCopyROMs(VOID);
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; // M003
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+typedef
+VOID
+(*PHALP_SCROLL_SCREEN) (
+ UCHAR
+ );
+
+#define TAB_SIZE 4
+#define TEXT_ATTR 0x1F
+
+//
+// Define forward referenced procedure prototypes.
+//
+VOID
+HalpDisplayINT10Setup (
+VOID);
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character );
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacterOld (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterOld(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayCirrusSetup (
+ VOID
+ );
+
+BOOLEAN
+HalpCirrusInterpretCmdStream (
+ PUSHORT pusCmdStream
+ );
+
+VOID
+HalpDisplayTgaSetup (
+ VOID
+ );
+
+/*
+VOID
+RGB525_WRITE(
+ ULONG dac,
+ ULONG offset,
+ UCHAR data);
+
+VOID
+RGB525_SET_REG(
+ ULONG dac,
+ ULONG index,
+ UCHAR data);
+*/
+
+VOID
+HalpDisplayGlintSetup(
+ VOID
+ );
+
+VOID
+Write_Dbg_Uchar(
+PUCHAR,
+UCHAR
+);
+
+//
+// Must use 32Bit transfer. RtlMoveMemory() uses 64Bit transfer.
+//
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+);
+/* Start M007 */
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+);
+/*End M007 */
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+
+//
+// Define memory access constants for VXL
+//
+
+#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+#define CIRRUS_OFFSET ((PUSHORT)0x3b0)
+
+#define TGA_REGISTER_BASE ((ULONG)0x403ff000)
+#define R94A_PCI_ADDR_REG ((PULONG)(0x80000518 | 0xffffc000))
+#define R94A_PCI_DATA_REG ((PULONG)(0x80000520 | 0xffffc000))
+
+#define GLINT_CONTROL_REGISTER_BASE ((ULONG)0x403ff000) // M021
+#define GLINT_VIDEO_REGISTER_BASE ((ULONG)0x403fe000)
+#define RGB525_REGISTER_BASE ((ULONG)0x403fd000)
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+ULONG HalpGlintRevisionId; // S006
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayMemoryBase = 0; // M021
+ULONG HalpDisplayResetRegisterBase = 0;
+ULONG HalpDisplayVxlClockRegisterBase = 0;
+ULONG HalpDisplayVxlBt484RegisterBase = 0;
+ULONG HalpDisplayVxlJaguarRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpG364Type = 0;
+
+LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0};
+
+LARGE_INTEGER HalpTgaPhigicalVideo = {0,0};
+LARGE_INTEGER HalpTgaPhigicalVideoCont = {0,0};
+
+LARGE_INTEGER HalpGlintPhygicalVideo = {0,0};
+LARGE_INTEGER HalpGlintPhygicalVideoCont = {0,0};
+ULONG HalpDisplayPCIDevice = FALSE;
+ULONG HalpDisplayType16BPP = FALSE;
+
+PVOID HalpMrcControlBase = NULL; // M007
+BOOLEAN HalpMrcControlMapped = FALSE; // M007
+
+typedef struct _R94A_PCI_CONFIGURATION_ADDRESS_REG{
+ ULONG Reserved2: 2;
+ ULONG RegisterNumber: 6;
+ ULONG FunctionNumber: 3;
+ ULONG DeviceNumber: 5;
+ ULONG BusNumber: 8;
+ ULONG Reserved1: 7;
+ ULONG ConfigEnable: 1;
+} R94A_PCI_CONFIGURATION_ADDRESS_REG, *PR94A_PCI_CONFIGURATION_ADDRESS_REG;
+
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+BOOLEAN
+HalpCheckPCIDevice (
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+ PCI_SLOT_NUMBER Slot;
+ ULONG ReadValue;
+ PCHAR Options;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n DISP 0\n"); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ MatchKey = 1;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+ }
+
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (LoaderBlock->LoadOptions != NULL) {
+ Options = LoaderBlock->LoadOptions;
+ _strupr(Options);
+ K351UseBios = strstr(Options, "USEBIOS");
+ }
+ if(K351UseBios!=NULL){
+ DbgPrint("\nUSEBIOS---\n");
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpDisplayControlBase = 0x90000000;
+
+ }else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "necvdfrb")) {
+
+ HalpDisplayControllerSetup = HalpDisplayCirrusSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayControlBase = 0x90000000;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"10110004")) {
+ //
+ // for DEC21030 PCI
+ //
+
+ HalpDisplayControllerSetup = HalpDisplayTgaSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayPCIDevice = TRUE;
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (ReadValue == 0x00041011){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+ if ((ReadValue & 0x00000002) == 0x2){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ HalpDisplayControlBase =
+ (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+
+ } else {
+ return FALSE;
+
+ }
+ }
+ }
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"3D3D0001")) {
+
+ //
+ // for GLINT 300SX PCI
+ //
+
+ HalpDisplayControllerSetup = HalpDisplayGlintSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayPCIDevice = TRUE;
+ HalpDisplayType16BPP = TRUE;
+
+ //
+ // FunctionNumber always zero
+ //
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (ReadValue == 0x00013d3d){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+ //
+ // GLINT 300SX has no I/O space regions
+ //
+
+ if (ReadValue & 0x2){
+
+ //
+ // Control Registers
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ HalpDisplayControlBase = (ReadValue & 0xfffffff0);
+
+ //
+ // Framebuffer
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ HalpDisplayMemoryBase = (ReadValue & 0xfffffff0);
+
+ //
+ // Revision ID
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x08); // S006
+ HalpGlintRevisionId = (ReadValue & 0x000000ff);
+
+ } else {
+ return FALSE;
+
+ }
+ }
+ }
+ } else {
+ // M002 +++
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpDisplayControlBase = 0x90000000;
+ HalpDisplayTypeUnknown = TRUE;
+ // M002 ---
+ }
+
+ Child = ConfigurationEntry->Child;
+
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpScrollLine =
+ 1024 * HalpCharacterHeight;
+ } else if (HalpDisplayType16BPP) {
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight * sizeof(USHORT);
+
+ } else {
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+ }
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpDisplayWidth =
+ 1024 / HalpCharacterWidth;
+
+ }else{
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+ }
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ if (HalpDisplayControllerSetup == HalpDisplayINT10Setup) {
+
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = 0;
+
+ Pte.PFN = (HalpCirrusPhigicalVideo.HighPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }else if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = MEM_VGA;
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ HalpTgaPhigicalVideo.HighPart = 1;
+ HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET;
+ Pte.PFN = (HalpTgaPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+ HalpGlintPhygicalVideo.HighPart = 1;
+ HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase;
+ Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) {
+
+ HalpGlintPhygicalVideoCont.HighPart = 1;
+ HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase;
+
+ //
+ // IBM RGB525
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 2) = Pte;
+
+ //
+ // GLINT 300SX Internal Video Registers
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 1) = Pte;
+
+ //
+ // GLINT 300SX Control Status Registers
+ //
+
+ Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayINT10Setup){
+
+#if defined(_X86_DBG_)
+ DbgPrint("Map x86 and cirrus control register\n");
+#endif // _X86_DBG_
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) {
+ *PageFrame-- = Pte;
+#if defined(_X86_DBG_)
+ DbgPrint("Map index %x pfn %x\n",Index,Pte.PFN);
+#endif // _X86_DBG_
+ Pte.PFN -= 1;
+ }
+
+ } else {
+
+ //
+ // If we have a 'NEC-cirrus GD5428'
+ // use the page before last to map the reset register.
+ //
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // M004
+ // ESM critical error logging setup.
+ //
+
+ HalpInitDisplayStringIntoNvram();
+
+ //
+ // Initialize the display controller.
+ //
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n x86adp init GOOO\n"); //DBGDBG
+#endif // _X86_DBG
+
+ if(HalpDisplayControllerSetup == HalpDisplayINT10Setup){
+ if (HalpInitializeX86DisplayAdapter()) {
+#if defined(_X86_DBG_)
+ DbgPrint("\n x86adp init OK\n"); //DBGDBG
+#endif // _X86_DBG
+// HalpDisplayControllerSetup(); // initialize twice bugbug
+
+ }else{
+
+ return FALSE;
+ }
+ }
+
+ HalpDisplayControllerSetup();
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpResetDisplayParameters=ResetDisplayParameters;// M003
+ HalpDisplayOwnedByHal = FALSE;
+
+ //
+ // M010
+ // Set for Software Power supply control
+ //
+
+#if defined (_MRCPOWER_)
+ HalpMrcModeChange((UCHAR)0x1); // M007
+#endif // _MRCPOWER_
+
+ //
+ // M006
+ // ESM critical logging success set success startup.
+ //
+
+ HalpSuccessOsStartUp();
+
+ return;
+}
+
+VOID
+HalpDisplayCirrusSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Cirrus VGA display controlleer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG dac_address, dac_reg;
+
+ ULONG verticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+ if( verticalFrequency < 66 ) {
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 800:
+ if( verticalFrequency < 58 ) {
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_56);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 66 ) {
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 1024:
+
+ if( verticalFrequency < 47 ) {
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if ( verticalFrequency < 65) {
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+ default:
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ return;
+ }
+
+ //
+ // Initialize color pallete.
+ //
+
+ dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT;
+ dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT;
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0);
+
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2));
+
+ //
+ // Set the video memory to address color one.
+ //
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (1024 *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+BOOLEAN
+HalpCirrusInterpretCmdStream(
+ PUSHORT pusCmdStream
+ )
+
+/*++
+
+Routine Description:
+
+ Interprets the appropriate command array to set up VGA registers for the
+ requested mode. Typically used to set the VGA into a particular mode by
+ programming all of the registers
+
+Arguments:
+
+
+ pusCmdStream - array of commands to be interpreted.
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+Revision History:
+--*/
+
+
+
+{
+ ULONG ulCmd;
+ ULONG ulPort;
+ UCHAR jValue;
+ USHORT usValue;
+ ULONG culCount;
+ ULONG ulIndex;
+ ULONG ulBase;
+ if (pusCmdStream == NULL) {
+
+ return TRUE;
+ }
+
+ ulBase = (ULONG)CIRRUS_BASE+0x3b0;
+
+ //
+ // Now set the adapter to the desired mode.
+ //
+
+ while ((ulCmd = *pusCmdStream++) != EOD) {
+
+ //
+ // Determine major command type
+ //
+
+ switch (ulCmd & 0xF0) {
+
+ //
+ // Basic input/output command
+ //
+
+ case INOUT:
+
+ //
+ // Determine type of inout instruction
+ //
+
+ if (!(ulCmd & IO)) {
+
+ //
+ // Out instruction. Single or multiple outs?
+ //
+
+ if (!(ulCmd & MULTI)) {
+
+ //
+ // Single out. Byte or word out?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // Single byte out
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = (UCHAR) *pusCmdStream++;
+
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort),
+ jValue);
+
+ } else {
+
+ //
+ // Single word out
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff));
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8));
+
+
+ }
+
+ } else {
+
+ //
+ // Output a string of values
+ // Byte or word outs?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // String byte outs. Do in a loop; can't use
+ // VideoPortWritePortBufferUchar because the data
+ // is in USHORT form
+ //
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+
+ while (culCount--) {
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ jValue);
+
+ }
+
+ } else {
+
+ //
+ // String word outs
+ //
+
+ ulPort = *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ //
+ // Buffering out is not use on the Miniport Driver for R96 machine.
+ //
+
+
+ while(culCount--)
+ {
+ usValue = *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort), (UCHAR) (usValue & 0x00ff));
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort+1), (UCHAR) (usValue >> 8));
+
+ }
+
+ }
+ }
+
+ } else {
+
+ // In instruction
+ //
+ // Currently, string in instructions aren't supported; all
+ // in instructions are handled as single-byte ins
+ //
+ // Byte or word in?
+ //
+
+ if (!(ulCmd & BW)) {
+ //
+ // Single byte in
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+
+ } else {
+
+ //
+ // Single word in
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = READ_REGISTER_USHORT((PUSHORT)
+ (ulBase+ulPort));
+ }
+
+ }
+
+ break;
+
+ //
+ // Higher-level input/output commands
+ //
+
+ case METAOUT:
+
+ //
+ // Determine type of metaout command, based on minor
+ // command field
+ //
+ switch (ulCmd & 0x0F) {
+
+ //
+ // Indexed outs
+ //
+
+ case INDXOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ usValue = (USHORT) (ulIndex +
+ (((ULONG)(*pusCmdStream++)) << 8));
+
+ Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff));
+
+ Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8));
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // Masked out (read, AND, XOR, write)
+ //
+
+ case MASKOUT:
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+ jValue &= *pusCmdStream++;
+ jValue ^= *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulBase + ulPort,
+ jValue);
+
+ break;
+
+ //
+ // Attribute Controller out
+ //
+
+ case ATCOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ // Write Attribute Controller index
+
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ (UCHAR)ulIndex);
+
+ // Write Attribute Controller data
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulPort, jValue);
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // None of the above; error
+ //
+ default:
+
+ return FALSE;
+
+ }
+
+
+ break;
+
+ //
+ // NOP
+ //
+
+ case NCMD:
+
+ break;
+
+ //
+ // Unknown command; error
+ //
+
+ default:
+
+ return FALSE;
+
+ }
+
+ }
+
+ return TRUE;
+
+} // end HalpCirrusInterpretCmdStream()
+
+
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine initializes the Tga(DEC21030) Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PUCHAR PLLbits;
+ ULONG i, j;
+ ULONG PLLdata;
+ ULONG ColorData;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+// M019+++
+//
+// support for nec dec-ga(tga) board.
+// parameter change.
+//
+#if 0
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xb0, 0x20, 0xc8 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x08, 0x80, 0x24, 0x88, 0x80, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x00, 0x80, 0x24, 0x88, 0x80, 0x78 };
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x70, 0xa0, 0x84 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+#else
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 }; // S007
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+#endif // _NECDEC_
+// M019 ---
+
+ const UCHAR Vga_Ini_ColorTable[48] =
+// { VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B,
+ { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // M010
+ VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B,
+ VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G,
+ VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B,
+ VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B,
+ VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B,
+ VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B,
+ VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B,
+// VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B,
+ VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // M010
+ VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B,
+ VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B,
+ VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B,
+ VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B,
+ VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B,
+ VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B,
+ VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B
+ };
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ //
+ // Write the PLL
+ //
+
+ // Select PLL Data
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits640x480_72; // S012
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S012
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits800x600_72; // S012
+ } else {
+ PLLbits = (PVOID)PLLbits800x600_60; // S012
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ PLLbits = (PVOID)PLLbits1024x768_60; // S012
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S012
+ }
+
+ // Set PLL Data
+ for( i = 0; i <= 6; i++ ){
+ for( j = 0; j <= 7; j++ ){
+ PLLdata = (PLLbits[i] >> (7-j)) & 1;
+ if( i == 6 && j == 7 )
+ PLLdata |= 2; // Set ~HOLD bit on last write
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata);
+ }
+ }
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){
+ }
+
+ // Set to Deep Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 );
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){
+ }
+
+ // Set to Video Base Address Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 );
+
+ // Set to Plane Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff );
+
+ // Set to Pixel Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff );
+
+ // Set to Raster Operation
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d );
+
+ // Set to Block Color Register 0
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 );
+
+ // Set to Block Color Register 1
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 );
+
+ //
+ // Init. video timing registers for each resolution
+ //
+
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x03c294a0 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x01a7a4c8 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x02681cc8 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x04889300 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+
+ // Set to Raster Operation Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 );
+
+ // M019 +++
+
+ //
+ // wait for 10 msec for nec dec-ga support
+ //
+
+ KeStallExecutionProcessor(10000L);
+
+ // M019 ---
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 );
+
+ //
+ // set pass thru on off & on again to verify operation
+ //
+
+ // EEPROM Write Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 );
+
+ //
+ // Fill palette
+ //
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 );
+
+ for( i = 0; i < 48; i++ ){
+ ColorData = Vga_Ini_ColorTable[i];
+ ColorData |= 0x200;
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData );
+ }
+
+ for( i = 48; i < 768; i++ ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 );
+ }
+
+ // Set to Video Valid Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 );
+
+ //
+ // Set Video Memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte;
+ /* Start D001 */
+ ULONG NowDisplayControlBase;
+ ULONG NowDisplayMemoryBase; // M021
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ LONG Index;
+ /* End D001 */
+ PCI_SLOT_NUMBER Slot; // M014
+ ULONG ReadValue; // M014
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_DUO_)
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ if (HalpDisplayPCIDevice == TRUE){
+
+ //
+ // the display type is PCI
+ // check physical address and reinitialize PTE
+ // we assume that the device has no function
+ //
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){
+
+ //
+ // DEC21030
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0)+ TGA_REG_SPC_OFFSET;
+ NowDisplayMemoryBase = 0;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){
+
+ //
+ // GLINT 300SX
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0);
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ NowDisplayMemoryBase = (ReadValue & 0xfffffff0);
+
+ }
+ }
+
+ //
+ // check to see if address has been changed
+ //
+
+ if (HalpDisplayControlBase != NowDisplayControlBase ||
+ HalpDisplayMemoryBase != NowDisplayMemoryBase){
+
+ // Called by OS, so reinitialize PTE
+ HalpDisplayControlBase = NowDisplayControlBase;
+ HalpDisplayMemoryBase = NowDisplayMemoryBase;
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+ Pte.N = 1;
+#endif
+#if defined(R4000)
+ Pte.C = UNCACHED_POLICY;
+#endif
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+
+ HalpGlintPhygicalVideo.HighPart = 1;
+ HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase;
+ Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+ HalpGlintPhygicalVideoCont.HighPart = 1;
+ HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase;
+
+ //
+ // IBM RGB525
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 2) = Pte;
+
+ //
+ // GLINT 300SX Internal Video Registers
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 1) = Pte;
+
+ //
+ // GLINT 300SX Control Status Registers
+ //
+
+ Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+ }
+ }
+ }
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+// M003 +++
+ if (HalpResetDisplayParameters &&
+ HalpDisplayControllerSetup == HalpDisplayINT10Setup) {
+ //
+ // Video work-around. The video driver has a reset function,
+ // call it before resetting the system in case the bios doesn't
+ // know how to reset the displays video mode.
+ //
+
+ if (HalpResetDisplayParameters(80, 50)) {
+ }
+// M003---
+ }
+
+ //
+ // M010
+ // for Software controlled power suply.
+ //
+
+#if defined(_MRCPOWER_)
+ HalpMrcModeChange((UCHAR)0); // M007
+#endif // _MRCPOWER_
+
+ HalpDisplayControllerSetup();
+// HalpResetX86DisplayAdapter();
+
+ //
+ // M004
+ // re-initialize critical message
+ //
+
+ HalpInitDisplayStringIntoNvram();
+
+ }
+
+ //
+ // M004
+ // ESM critical error logging start (set colomn,row)
+ //
+
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ // M004
+ // ESM critical error logging(strings)
+ //
+
+ HalpStringBufferCopyToNvram();
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+#if defined(_DUO_)
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacterOld (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUSHORT DestinationShort; // M021
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE,
+ (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+
+// /* START M002 */
+// RtlMoveMemory((PUCHAR)VIDEO_MEMORY_BASE, // S013
+// (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+// HalpScrollLength);
+// /* END M002 */
+
+ if (HalpDisplayType16BPP) {
+ DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + HalpScrollLength);
+
+ } else {
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ }
+
+ if (HalpDisplayType16BPP) {
+ for (Index = 0; Index < HalpScrollLine/2; Index += 1) {
+ *DestinationShort++ = (USHORT)0x000f;
+ }
+
+ } else {
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ }
+
+ //
+ // M006
+ // ESM critical logging re-print(column, row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ //
+ // M006
+ // ESM critical logging re-print(column,row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ } else {
+
+ //
+ // M006
+ // ESM critical logging put character.
+ //
+
+ HalStringIntoBuffer( Character );
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterOld((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+//351
+VOID
+HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollINT10(1);
+ }
+
+ //
+ // M006
+ // ESM critical logging re-print(column, row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollINT10( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+
+ //
+ // M006
+ // ESM critical logging re-print(column,row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ HalpColumn = 0;
+
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterINT10(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ //
+ // M006
+ // ESM critical logging put character.
+ //
+
+ HalStringIntoBuffer( Character );
+
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollINT10(1);
+ }
+ }
+ HalpOutputCharacterINT10(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacterOld(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUSHORT DestinationShort; // M021
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ if (HalpDisplayType16BPP) {
+ DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth * sizeof(USHORT)));
+
+ } else {
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+ }
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+
+ if (HalpDisplayType16BPP) {
+ if (FontValue >> 31)
+ *DestinationShort++ = (USHORT)0xffff;
+ else
+ *DestinationShort++ = (USHORT)0x000f;
+
+ }else{
+ *Destination++ = (UCHAR) (FontValue >> 31) ^ 1; /* M008 */
+ }
+
+ FontValue <<= 1;
+ }
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ Destination +=
+ (1024 - HalpCharacterWidth);
+ }
+ else if (HalpDisplayType16BPP){
+ DestinationShort +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+ else {
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+
+ }
+ HalpColumn += 1;
+ return;
+}
+
+VOID
+Write_Dbg_Uchar(
+ PUCHAR Ioadress,
+ UCHAR Moji
+ )
+{
+#if defined (R96DBG)
+ DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji);
+#endif
+ WRITE_PORT_UCHAR(Ioadress,Moji);
+}
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+ )
+
+/*++
+ Routine Description:
+
+ This function moves blocks of memory.
+
+ Arguments:
+
+ Destination - Supplies a pointer to the destination address of
+ the move operation.
+
+ Source - Supplies a pointer to the source address of the move
+ operation.
+
+ Length - Supplies the length, in bytes, of the memory to be moved.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Remainder;
+ PUCHAR Dstend;
+ PUCHAR Srcend;
+
+ if ( (Source == Destination) || (Length == 0) ) {
+ return;
+ }
+
+ if ((Source < Destination)&((Source + Length) > Destination)) {
+ if((Destination - Source) > 4){
+ Remainder = (UCHAR) Length &0x03;
+ Length = Length / 4;
+ Dstend = Destination + Length - 4 ;
+ Srcend = Source + Length -4;
+
+ for (; Length > 0; Length--) {
+ *(PULONG)(Dstend) = *(PULONG)(Srcend);
+ Dstend -= 4;
+ Srcend -= 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+ for (; Length > 0; Length--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+
+ else {
+ if( (Source - Destination) > 4 ){
+ Remainder = (UCHAR) Length &0x03;
+ Length = Length / 4;
+ for (; Length > 0; Length--) {
+ *(PULONG)(Destination) = *(PULONG)(Source);
+ Destination += 4;
+ Source += 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ return;
+ }
+
+ for (; Length > 0; Length--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ }
+}
+
+VOID
+HalpOutputCharacterINT10 (
+ IN UCHAR Character
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 2 << 8; // AH = 2
+ Ebx = 0; // BH = page number
+ Edx = (HalpRow << 8) + HalpColumn;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
+ Ebx = 0;
+ Ecx = 1;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ HalpColumn += 1;
+}
+
+VOID
+HalpScrollINT10 (
+ IN UCHAR LinesToScroll
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 6 << 8; // AH = 6 (scroll up)
+ Eax |= LinesToScroll; // AL = lines to scroll
+ Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
+ Ecx = 0; // CH,CL = upper left
+ Edx = ((HalpDisplayText - 1) << 8)
+ + (HalpDisplayWidth - 1); // DH,DL = lower right // M001,S005
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+VOID
+HalpDisplayINT10Setup (
+ VOID
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 50; // M001
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ HalpResetX86DisplayAdapter(); // for compaq q-vision reset
+
+// M001 +++
+ //
+ // Load 8x8 font 80x50 on VGA
+ //
+ Eax = 0x1112; // AH = 11 AL=12
+ Ebx = 0;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+// M001 ---
+
+ //
+ // Set cursor to (0,0)
+ //
+ Eax = 0x02 << 8; // AH = 2
+ Ebx = 0; // BH = page Number
+ Edx = 0; // DH = row DL = column
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Make screen white on blue by scrolling entire screen
+ //
+ Eax = 0x06 << 8; // AH = 6 AL = 0
+ Ebx = TEXT_ATTR << 8; // BH = attribute
+ Ecx = 0; // (x,y) upper left
+ Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
+ Edx += HalpScrollLine/2;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+}
+
+// start M014
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffffffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+
+
+BOOLEAN
+HalpCheckPCIDevice (
+ IN PCI_SLOT_NUMBER Slot
+ )
+
+/*++
+ Routine Description:
+
+ This function checks if spcified PCI slot is valid.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+
+ Return Value:
+
+ TRUE - specified slot is valid
+ FALSE - specified slot is invalid
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ BOOLEAN ReturnValue;
+ ULONG OrigData;
+ ULONG IdValue;
+ KIRQL OldIrql;
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+ OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
+
+ //
+ // read VendorID and DeviceID of the specified slot
+ //
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+ IdValue = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ if ((USHORT)(IdValue & 0xffff) == 0xffff){
+
+ //
+ // waiting until ReceivedMasterAbort bit is set
+ //
+
+ while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
+ ;
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000)
+
+ //
+ // M018
+ // Clear memory address error registers.
+ //
+
+ {
+ LARGE_INTEGER registerLarge;
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ }
+
+ ReturnValue = FALSE;
+
+ } else {
+
+ ReturnValue = TRUE;
+
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+
+ return ReturnValue;
+
+}
+// end M014
+
+#if defined(_R94A_)
+VOID
+HalpDisplayGlintSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GLINT 300SX Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ __VIDEO __Video;
+ VIDEO Video = &__Video;
+ long ClockDivider;
+
+ // for initialize ramdac
+ ULONG Dac = RGB525_REGISTER_BASE;
+ UCHAR ByteVal;
+
+ // for initialize timing
+ ULONG Glint = GLINT_VIDEO_REGISTER_BASE - 0x3000;
+
+ // for initialize control
+ ULONG SerialClk;
+ ULONG Temp;
+ ULONG Data;
+ ULONG Mask;
+
+ // for initialize RampLut
+ ULONG Index;
+
+ // for clear the screen
+ PULONG DestinationUlong;
+ ULONG Length;
+
+ /* check revision id R01 or R02. assume 40MHz(R01) or 50MHz(R02) reference clock for now */
+
+ if ( HalpGlintRevisionId == 0){
+ Video->RefDivCount = RGB525_PLL_REFCLK_40_MHz;
+ } else {
+ Video->RefDivCount = RGB525_PLL_REFCLK_50_MHz; // S006
+ }
+
+//
+// Calculate vertical frequency.
+//
+
+#if defined(_GLINT60HZ_)
+
+ VerticalFrequency = 60;
+
+#else
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+#endif // _GLINT60HZ_
+
+ //
+ // Initialize video data
+ //
+
+ /* get timing values for named resolution */
+
+ if ( HalpMonitorConfigurationData.HorizontalResolution == 1280
+ && HalpMonitorConfigurationData.VerticalResolution == 1024
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 1280;
+ Video->ImageHeight = 1024;
+ Video->HLimit = 8 * 211;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 51;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 1066;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 42;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 134 MHz */
+ Video->PixelClock = RGB525_DF(3) | RGB525_VCO_DIV_COUNT(2);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 164;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 14;
+ Video->HBlankEnd = 8 * 36;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 800;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 32;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ /* 79 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(14);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768
+ && VerticalFrequency == 60)
+ {
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 168;
+ Video->HSyncStart = 8 * 3;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 40;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 806;
+ Video->VSyncStart = 4;
+ Video->VSyncEnd = 10;
+ Video->VBlankEnd = 38;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 65 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 800;
+ Video->ImageHeight = 600;
+ Video->HLimit = 8 * 132;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 12;
+ Video->HBlankEnd = 8 * 32;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 625;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 25;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH;
+ /* 49.5 MHz */
+ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(34);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600
+ && VerticalFrequency == 60)
+ {
+ Video->ImageWidth = 800;
+ Video->ImageHeight = 600;
+ Video->HLimit = 8 * 132;
+ Video->HSyncStart = 8 * 5;
+ Video->HSyncEnd = 8 * 21;
+ Video->HBlankEnd = 8 * 32;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 628;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 6;
+ Video->VBlankEnd = 28;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH;
+ /* 40 MHz */
+ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(15);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 // add 4/5/1995
+ && HalpMonitorConfigurationData.VerticalResolution == 480
+ && VerticalFrequency == 60)
+ {
+ Video->ImageWidth = 640;
+ Video->ImageHeight = 480;
+ Video->HLimit = 8 * 100;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 14;
+ Video->HBlankEnd = 8 * 20;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 525;
+ Video->VSyncStart = 12;
+ Video->VSyncEnd = 13;
+ Video->VBlankEnd = 45;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW;
+ /* 31.5 MHz */
+ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(36);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 640;
+ Video->ImageHeight = 480;
+ Video->HLimit = 8 * 105;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 10;
+ Video->HBlankEnd = 8 * 25;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 500;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 20;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW;
+ /* 31.5 MHz */
+ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(61);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1280
+ && HalpMonitorConfigurationData.VerticalResolution == 1024
+ && VerticalFrequency == 57)
+ {
+ Video->ImageWidth = 1280;
+ Video->ImageHeight = 1024;
+ Video->HLimit = 8 * 211;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 51;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 1066;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 42;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 103 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(38);
+ }
+ else {
+ //
+ // force to set the resolution. 1024x768(60MHz)
+ //
+
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 168;
+ Video->HSyncStart = 8 * 3;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 40;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 806;
+ Video->VSyncStart = 4;
+ Video->VSyncEnd = 10;
+ Video->VBlankEnd = 38;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 65 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0);
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+
+ /* record image depth */
+
+ Video->ImageDepth = 16;
+
+ /* determine video clock divider and pixel format */
+
+ ClockDivider = 4;
+ Video->PixelFormat = RGB525_PIXEL_FORMAT_16_BPP;
+
+ /* adjust horizontal timings */
+
+ Video->HLimit /= ClockDivider;
+ Video->HSyncStart /= ClockDivider;
+ Video->HSyncEnd /= ClockDivider;
+ Video->HBlankEnd /= ClockDivider;
+
+ //
+ // Initialize ramdac data
+ //
+
+ RGB525_WRITE(Dac, __RGB525_PixelMask, 0xff);
+
+ /* set MiscControlOne register */
+ ByteVal = RGB525_MISR_CNTL_OFF
+ | RGB525_VMSK_CNTL_OFF
+ | RGB525_PADR_RFMT_READ_ADDR
+ | RGB525_SENS_DSAB_DISABLE
+ | RGB525_VRAM_SIZE_64;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlOne, ByteVal);
+
+ /* set MiscControlTwo register */
+ ByteVal = RGB525_PCLK_SEL_PLL
+ | RGB525_INTL_MODE_DISABLE
+ | RGB525_BLANK_CNTL_NORMAL
+ | RGB525_COL_RES_8_BIT
+ | RGB525_PORT_SEL_VRAM;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlTwo, ByteVal);
+
+ /* set MiscControlThree register */
+ ByteVal = RGB525_SWAP_RB_DISABLE
+ | RGB525_SWAP_WORD_31_00_FIRST
+ | RGB525_SWAP_NIB_07_04_FIRST;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlThree, ByteVal);
+
+ /* set MiscClockControl register */
+ ByteVal = RGB525_DDOTCLK_DISABLE
+ | RGB525_SCLK_ENABLE
+ | RGB525_PLL_ENABLE;
+ RGB525_SET_REG(Dac, __RGB525_MiscClockControl, ByteVal);
+
+ /* set SyncControl register */
+ ByteVal = RGB525_DLY_CNTL_ADD
+ | RGB525_VSYN_INVT_DISABLE
+ | RGB525_HSYN_INVT_DISABLE
+ | RGB525_VSYN_CNTL_NORMAL
+ | RGB525_HSYN_CNTL_NORMAL;
+ RGB525_SET_REG(Dac, __RGB525_SyncControl, ByteVal);
+
+ /* set HSyncControl register */
+ RGB525_SET_REG(Dac, __RGB525_HSyncControl, RGB525_HSYN_POS(0));
+
+ /* set PowerManagement register */
+ ByteVal = RGB525_SCLK_PWR_NORMAL
+ | RGB525_DDOT_PWR_DISABLE
+ | RGB525_SYNC_PWR_NORMAL
+ | RGB525_ICLK_PWR_NORMAL
+ | RGB525_DAC_PWR_NORMAL;
+ RGB525_SET_REG(Dac, __RGB525_PowerManagement, ByteVal);
+
+ /* set DACOperation register */
+ ByteVal = RGB525_SOG_DISABLE
+ | RGB525_BRB_NORMAL
+ | RGB525_DSR_FAST
+ | RGB525_DPE_ENABLE; /* disable? */
+ RGB525_SET_REG(Dac, __RGB525_DACOperation, ByteVal);
+
+ /* set PaletteControl register */
+ ByteVal = RGB525_6BIT_LINEAR_ENABLE
+ | RGB525_PALETTE_PARTITION(0);
+ RGB525_SET_REG(Dac, __RGB525_PaletteControl, ByteVal);
+
+ /* set PixelFormat register */
+ RGB525_SET_REG(Dac, __RGB525_PixelFormat, Video->PixelFormat);
+
+ /* set 8BitPixelControl register */
+ RGB525_SET_REG(Dac, __RGB525_8BitPixelControl,
+ RGB525_B8_DCOL_INDIRECT);
+
+ /* set 16BitPixelControl register */
+ ByteVal = RGB525_B16_DCOL_INDIRECT
+ | RGB525_B16_565
+ | RGB525_B16_ZIB
+ | RGB525_B16_SPARSE;
+
+ RGB525_SET_REG(Dac, __RGB525_16BitPixelControl, ByteVal);
+
+ /* set 32BitPixelControl register */
+ RGB525_SET_REG(Dac, __RGB525_32BitPixelControl,
+ RGB525_B32_DCOL_INDIRECT);
+
+ /* set PLLControlOne register */
+ ByteVal = RGB525_REF_SRC_REFCLK
+ | RGB525_PLL_INT_FS_DIRECT;
+ RGB525_SET_REG(Dac, __RGB525_PLLControlOne, ByteVal);
+
+ /* set PLLControlTwo register */
+ RGB525_SET_REG(Dac, __RGB525_PLLControlTwo, RGB525_PLL_INT_FS(0));
+
+ /* set PLLRefDivCount register */
+ RGB525_SET_REG(Dac, __RGB525_PLLRefDivCount, Video->RefDivCount);
+
+ /* set F0 register */
+ RGB525_SET_REG(Dac, __RGB525_F0, Video->PixelClock);
+
+ /* set CursorControl register */
+ RGB525_SET_REG(Dac, __RGB525_CursorControl, RGB525_CURSOR_MODE_OFF);
+
+ //
+ // Initialize timing
+ //
+
+ /* horizontal video timing values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGHLimit, Video->HLimit);
+ GLINT_WRITE(Glint, __GLINT_VTGHSyncStart, Video->HSyncStart);
+ GLINT_WRITE(Glint, __GLINT_VTGHSyncEnd, Video->HSyncEnd);
+ GLINT_WRITE(Glint, __GLINT_VTGHBlankEnd, Video->HBlankEnd);
+
+ /* vertical video timing values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGVLimit, Video->VLimit);
+ GLINT_WRITE(Glint, __GLINT_VTGVSyncStart, Video->VSyncStart);
+ GLINT_WRITE(Glint, __GLINT_VTGVSyncEnd, Video->VSyncEnd);
+ GLINT_WRITE(Glint, __GLINT_VTGVBlankEnd, Video->VBlankEnd);
+
+ /* horizontal clock gate values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGHGateStart, Video->HBlankEnd - 2);
+ GLINT_WRITE(Glint, __GLINT_VTGHGateEnd, Video->HLimit - 2);
+
+ /* vertical clock gate values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGVGateStart, Video->VBlankEnd - 1)
+ GLINT_WRITE(Glint, __GLINT_VTGVGateEnd, Video->VBlankEnd);
+
+ //
+ // Initialize control
+ //
+
+ /* serial clock control */
+
+ SerialClk = GLINT_EXTERNAL_QSF
+ | GLINT_SPLIT_SIZE_128_WORD
+ | GLINT_SCLK_VCLK_DIV_2;
+
+ GLINT_WRITE(Glint, __GLINT_VTGSerialClk, SerialClk);
+
+ /* set sync polarities and unblank screen */
+
+ // UpdatePolarityRegister(Glint,
+ // GLINT_CBLANK_ACTIVE_LOW
+ // | Video->HSyncPolarity
+ // | Video->VSyncPolarity,
+ // GLINT_CBLANK_POLARITY_MASK
+ // | GLINT_HSYNC_POLARITY_MASK
+ // | GLINT_VSYNC_POLARITY_MASK);
+
+ Data = GLINT_CBLANK_ACTIVE_LOW
+ | Video->HSyncPolarity
+ | Video->VSyncPolarity;
+ Mask = GLINT_CBLANK_POLARITY_MASK
+ | GLINT_HSYNC_POLARITY_MASK
+ | GLINT_VSYNC_POLARITY_MASK;
+
+ /* read video polarity control register */
+
+ GLINT_READ(Glint, __GLINT_VTGPolarity, Temp);
+
+ /* replace existing polarity field */
+
+ Temp = (Temp & ~Mask) | (Data & Mask);
+
+ /* write result back to polarity register */
+
+ GLINT_WRITE(Glint, __GLINT_VTGPolarity, Temp);
+
+ /* set FrameRowAddr */
+
+ GLINT_WRITE(Glint, __GLINT_VTGFrameRowAddr, 0);
+
+ //
+ // Initialize RampLut
+ //
+
+ /* initialise palette address */
+
+ RGB525_WRITE(Dac, __RGB525_PalAddrWrite, 0);
+
+ /* ramp colour components using auto-increment */
+
+ for (Index = 0; Index <= 0xff; Index++)
+ {
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ }
+
+ //
+ // Clear the screen.
+ //
+
+ DestinationUlong = (PULONG)VIDEO_MEMORY_BASE;
+
+ Length = (HalpMonitorConfigurationData.VerticalResolution *
+ HalpMonitorConfigurationData.HorizontalResolution -1) * sizeof(USHORT);
+
+ for (Index = 0; Index < (Length / sizeof(ULONG)); Index++)
+ *(DestinationUlong++) = (ULONG)0x000f000f;
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+}
+#endif // _R94A_
+
+//
+// M010
+// for software controlled power supply.
+//
+#if defined(_MRCPOWER_)
+/* Start M007 */
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+)
+/*++
+
+Routine Description:
+
+ This routine is change Mode bit on MRC Controller.
+
+Arguments:
+
+ Mode - Parameter for setting Mode bit on MRC
+
+Return Value:
+
+ None
+
+--*/
+{
+
+ PHYSICAL_ADDRESS physicalAddress;
+ UCHAR ModeNow;
+ KIRQL OldIrql;
+ ENTRYLO Pte[2];
+
+ //
+ // MRC Controller Mapping, when first call
+ //
+
+ if (HalpMrcControlMapped == FALSE) {
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = MRC_TEMP_PHYSICAL_BASE;
+ HalpMrcControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ if (HalpMrcControlBase != NULL) {
+ HalpMrcControlMapped = TRUE;
+ }
+ }
+
+ if (HalpMrcControlMapped == TRUE){
+
+ ModeNow = READ_REGISTER_UCHAR(
+ &((PMRC_REGISTERS)HalpMrcControlBase)->Mode
+ );
+
+ //
+ // Set MRC Mode bit
+ //
+ WRITE_REGISTER_UCHAR(
+ &((PMRC_REGISTERS)HalpMrcControlBase)->Mode,
+ ((ModeNow & 0x02) | (Mode << 7)),
+ );
+
+ } else {
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT;
+
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ //
+ // Map MRC using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ ModeNow = READ_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode // B028
+ );
+
+ //
+ // Set MRC Mode bit
+ //
+ WRITE_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode,
+ ((ModeNow & 0x02) | (Mode << 7)),
+ );
+
+
+ // Start M008
+ //
+ // Resume fixed TLB for DMA
+ //
+
+ Pte[0].PFN = DMA_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ Pte[0].C = UNCACHED_POLICY;
+
+
+ Pte[1].PFN = INTERRUPT_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[1].G = 1;
+ Pte[1].V = 1;
+ Pte[1].D = 1;
+
+ Pte[1].C = UNCACHED_POLICY;
+
+ // End M008
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ KeLowerIrql(OldIrql);
+ }
+}
+/* End M007 */
+#endif // _MRCPOWER_
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function writes PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data to write.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffffffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+ WRITE_REGISTER_ULONG(R94A_PCI_DATA_REG, *Buffer);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)));
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+ WRITE_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)));
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+ WRITE_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
diff --git a/private/ntos/nthals/halr94a/mips/jxdmadsp.s b/private/ntos/nthals/halr94a/mips/jxdmadsp.s
new file mode 100644
index 000000000..370edd47f
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxdmadsp.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdmadsp.s"
diff --git a/private/ntos/nthals/halr94a/mips/jxebsup.c b/private/ntos/nthals/halr94a/mips/jxebsup.c
new file mode 100644
index 000000000..5fa4f8677
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxebsup.c
@@ -0,0 +1,1398 @@
+// #pragma comment(exestr, "@(#) jxebsup.c 1.1 95/09/28 15:36:45 nec")
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - HalpCreateEisa(PCI)Structures()
+ function name changed.
+ interrupt dispatcher is changed for PCI/EISA.
+ comment out EISA NMI disable code.
+ - HalpEisaDispatch()
+ add the PCI interrupt handler.
+ add the avoidance the IR7 and IR15 spurious interrupt.
+ H001 Tue Oct 11 18:52:39 JST 1994 kbnes!kishimoto
+ - modify original compile error
+ H002 Mon Oct 17 13:54:43 JST 1994 kbnes!kishimoto
+ - Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ - modify original compile error
+ S003 Thu Dec 22 11:39:57 JST 1994 kbnes!A.Kuriyama
+ -add beta machine limit
+ S004 Mon Jan 23 13:57:08 JST 1995 kbnes!A.Kuriyama
+ -add raise irql for dummyread for EISA/PCI acknouledge
+ H003 Tue Jan 24 19:04:04 1995 kbnes!kishimoto
+ -Add Enable the PCI interrupts to the CPU
+ M005 Wed Jan 25 21:02:51 JST 1995 kbnes!A.Kuriyama
+ -add 64byte align between dummy read and EISA/PCI Ack.
+ H006 Tue Feb 7 21:04:30 JST 1995 kbnes!kisimoto
+ -bug fix when spurious interrupt occurs
+ S007 kuriyama@oa2.kb.nec.co.jp Thu Apr 06 00:18:14 JST 1995
+ - Disable EISA NMI
+ S008 kuriyama@oa2.kb.nec.co.jp Mon May 22 03:58:30 JST 1995
+ - add panicflag for esm
+ S009 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 19:18:10 JST 1995
+ - Merge build 1057
+ H010 kisimoto@oa2.kb.nec.co.jp Fri Aug 11 17:40:26 1995
+ - Removed M005, etc.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+//
+// Define EISA bus interrupt affinity.
+//
+
+KAFFINITY HalpEisaBusAffinity;
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch ((UCHAR)channelNumber) { // H001
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ KIRQL oldIrql;
+
+#if !defined(_DUO_) && !defined(_R94A_) // H000
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#else
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#endif
+
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] =
+ (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // start H003
+ // Enable the following PCI interrupts to the CPU.
+ // Target abort, Master abort
+ // SRetry overflow, ERR, PERR
+ //
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long);
+ DataLong |= ENABLE_PERR_INTERRUPTS;
+ DataLong |= ENABLE_SERR_INTERRUPTS;
+ DataLong |= ENABLE_RETRY_OVERFLOW_EISA_INTERRUPTS;
+ DataLong |= ENABLE_MASTER_ABORT_INTERRUPTS;
+ DataLong |= ENABLE_TARGET_ABORT_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long,
+ DataLong);
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Set EISA bus interrupt affinity.
+ //
+
+ HalpEisaBusAffinity = PCR->SetMember;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+#if defined(_DUO_)
+
+ //
+ // Enable the EISA interrupts to the CPU.
+ //
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_EISA_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+
+#endif
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+#if defined(_DUO_)
+
+ PUSHORT Acknowledge = (PUSHORT)&DMA_CONTROL->EisaInterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_USHORT(Acknowledge);
+
+#else
+
+ PUCHAR Acknowledge = (PUCHAR)&DMA_CONTROL->InterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(Acknowledge);
+
+#endif
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+ if (interruptVector != 0x8000) {
+
+ //
+ // H000
+ // If the interrupt vector is 0x4000 then this is an PCI interrupt.
+ // Call the PCI interrupt handler.
+ //
+
+ if (interruptVector != 0x4000) {
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+
+ //
+ // H000
+ // check to see if this is a spurious interrupt
+ //
+
+ if (interruptVector == 7 || interruptVector == 15){
+ PVOID IsrPortAddressVa;
+ UCHAR IsrValue;
+
+ #define OCW3_READ_ISR 0x0b
+ #define OCW3_READ_IRR 0x0a
+
+ IsrPortAddressVa = (interruptVector == 7) ?
+ &(((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0):
+ &(((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0); // H006
+
+ //
+ // Change mode OCW3 register, bacause we want to read ISR
+ // read ISR on 8259.
+ //
+
+ WRITE_REGISTER_UCHAR(IsrPortAddressVa, OCW3_READ_ISR);
+ IsrValue = READ_REGISTER_UCHAR( IsrPortAddressVa );
+
+ //
+ // resume mode OCW3 register to IRR
+ //
+
+ WRITE_REGISTER_UCHAR(IsrPortAddressVa, OCW3_READ_IRR);
+
+ //
+ // check to see if ISR is zero, then we do not call driver.
+ //
+
+ if ( !IsrValue ){
+
+ goto NotCallDriver;
+
+ }
+ }
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+NotCallDriver:
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+
+ } else {
+ returnValue = HalpPCIDispatch(NULL, NULL);
+ }
+
+ } else {
+ returnValue = HalHandleNMI(NULL, NULL);
+ }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT(Offset >= 0x100000);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // S008
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halr94a/mips/jxenvirv.c b/private/ntos/nthals/halr94a/mips/jxenvirv.c
new file mode 100644
index 000000000..c78505bcf
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxenvirv.c
@@ -0,0 +1,800 @@
+// #pragma comment(exestr, "@(#) jxenvirv.c 1.1 95/09/28 15:37:20 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ M001 95.4.25 Y.Nakatani
+ - Add Interface of NVRAM for ESM
+ M002 kuriyama@oa2.kb.nec.co.jp Sun May 21 20:46:25 JST 1995
+ - Change Nvram virtual address
+ M003 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 19:25:54 JST 1995
+ - Removed _J94C_ definitions.
+ _J94C_ definition indicates that the status of
+ the dump switch can acknowledge from Self-test
+ register.
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "jazznvr.h"
+#include "string.h"
+
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+// M002 +++
+KIRQL
+HalpEsmMapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the ESM NVRAM into a wired TB entry.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO NvramPte[2];
+
+ //
+ // Construct a pair of PTE's to map NVRAM.
+ //
+
+ NvramPte[0].X1 = 0;
+ NvramPte[0].PFN = 0x80013000 >> PAGE_SHIFT;
+ NvramPte[0].G = 0;
+ NvramPte[0].V = 1;
+ NvramPte[0].D = 1;
+ NvramPte[0].C = UNCACHED_POLICY;
+ NvramPte[1] = NvramPte[0];
+ NvramPte[1].PFN += 1;
+
+ //
+ // Raise IRQL to the highest level, allocate a TB entry, map NVRAM
+ // using the alocated entry, and return the previous IRQL.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0],
+ (PVOID)NVRAM_VIRTUAL_BASE,
+ HalpAllocateTbEntry());
+
+ return OldIrql;
+}
+// M002 ---
+
+KIRQL
+HalpMapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into a wired TB entry.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO NvramPte[2];
+
+ //
+ // Construct a pair of PTE's to map NVRAM.
+ //
+
+ NvramPte[0].X1 = 0;
+ NvramPte[0].PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
+ NvramPte[0].G = 0;
+ NvramPte[0].V = 1;
+ NvramPte[0].D = 1;
+ NvramPte[0].C = UNCACHED_POLICY;
+ NvramPte[1] = NvramPte[0];
+ NvramPte[1].PFN += 1;
+
+ //
+ // Raise IRQL to the highest level, allocate a TB entry, map NVRAM
+ // using the alocated entry, and return the previous IRQL.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0],
+ (PVOID)NVRAM_VIRTUAL_BASE,
+ HalpAllocateTbEntry());
+
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from a wired entry in
+ the TB.
+
+Arguments:
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the wired TB entry that was allocated to map NVRAM and lower
+ // IRQL to its previous level.
+ //
+
+ HalpFreeTbEntry();
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram();
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(OldIrql);
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram();
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(OldIrql);
+ return Status;
+}
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Write Byte Count
+ PVOID Buffer // Pointer Of Buffer Write to NVRAM
+){
+ // Write into NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,1);
+}
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Read Byte Count
+ PVOID Buffer // Pointer Of Buffer Read From NVRAM
+){
+ // Read From NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,0);
+}
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset, // Read/Write offset of ESM NVRAM
+ ULONG Count, // Read/Write Byte Count
+ PVOID Buffer, // read/Write Pointer
+ ULONG Write // Operation
+){
+
+ KIRQL OldIrql;
+ ULONG i;
+ //
+ // Check is addr . So decrement 1
+ //
+ if(
+ Offset >=0 &&
+ Count >=0 &&
+ Offset <= 0x1fff && // M002 +++
+ Offset+Count-1 <= 0x1fff // M002 ---
+
+ ){
+
+ if(Write){
+ OldIrql = HalpEsmMapNvram(); // M002
+// if (HalpEsmDebug == 1) // test
+// DbgBreakPoint(); // test
+ for(i=0;i<Count;i++){ // test
+ WRITE_REGISTER_UCHAR((PUCHAR)(NVRAM_VIRTUAL_BASE+Offset+i),((PUCHAR)Buffer)[i]); // M002 +++
+ }
+ HalpUnmapNvram(OldIrql);
+ }else{
+ OldIrql = HalpEsmMapNvram(); // M002
+// if (HalpEsmDebug == 1) // test
+// DbgBreakPoint(); // test
+ for(i=0;i<Count;i++){
+ ((PUCHAR)Buffer)[i] =READ_REGISTER_UCHAR((PUCHAR)(NVRAM_VIRTUAL_BASE+Offset+i)); // M002
+
+ }
+ HalpUnmapNvram(OldIrql); // M002
+ }
+
+ return TRUE;
+
+ }else{
+
+ //
+ // It is no ESM NVRAM Erea.
+ return FALSE;
+ }
+
+}
diff --git a/private/ntos/nthals/halr94a/mips/jxhalp.h b/private/ntos/nthals/halr94a/mips/jxhalp.h
new file mode 100644
index 000000000..54f0f02d4
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxhalp.h
@@ -0,0 +1,228 @@
+// #pragma comment(exestr, "@(#) jxhalp.h 1.1 95/09/28 15:37:58 nec")
+
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - New HalpCreateEisaPCIStructures()
+ - Del HalpCreateEisaStructures()
+ - New function HalpEisaPCIDispatch()
+ - Del function HalpEisaDispatch()
+ L000 Thu Oct 13 18:09:33 JST 1994 kbnes!kuriyama(A)
+ for BBM LED
+ - Add HalpDisplayLED
+ - Add HalpLEDDisplayLock
+ - Add HalpLEDControlBase;
+ L002 Mon Oct 17 14:21:39 JST 1994 kbnes!kuriyama(A)
+ change function name EISAPCI... EISA..
+ H001 Mon Oct 17 14:45:04 JST 1994 kbnes!kishimoto
+ - Del HalDisplayLED() function definitions.
+ (We call HalR94aDebugPrint() instead of that.)
+ H002 Thu Oct 20 20:58:45 JST 1994 kbnes!kishimoto
+ - add extern ULONG R94aBbmLEDMapped
+ for debug use only.
+ H003 Fri Oct 21 15:52:32 JST 1994 kbnes!kishimoto
+ - add HalR94aDebugPrint() prototype definition.
+ H004 Mon Jan 16 02:28:58 1995 kbnes!kishimoto
+ - add HalpPCIConfigLock
+ S005 Tue Mar 07 14:55:42 JST 1995 kbnes!kuriyama (A)
+ - add Dma32BitAddresses to AdapterObject
+ H006 Fri Jul 21 17:40:53 JST 1995 kbnes!kisimoto
+ - merge ESM functions from J94C
+ H007 Sat Aug 12 15:12:28 JST 1995 kbnes!kisimoto
+ - Removed BBMLED, R94ALEDMAP code and _J94C_ definitions.
+ _J94C_ definition indicates that the status of
+ the dump switch can acknowledge from Self-test
+ register.
+
+ S008 kuriyama@oa2.kbnes.nec.co.jp
+ - add for merge R94A/R94A'/R94D HAL
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// S008
+// for merge R94A/R94A'/R94D HAL
+//
+BOOLEAN HalpUseChipSetWorkaround;
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+#if defined(_DMA_EXPAND_) // S005
+ BOOLEAN Dma32BitAddresses;
+#endif //_DMA_EXPAND_
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#if defined(_R94A_)
+
+PADAPTER_OBJECT
+HalpAllocatePCIAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpEnablePCIInterrupt (
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePCIInterrupt (
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID // H004
+HalpInitBusHandlers (
+ VOID
+ );
+
+extern KSPIN_LOCK HalpPCIConfigLock; // H004
+
+#endif
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ );
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ );
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ );
+
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ );
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ );
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ );
+
+#if DBG // H003
+VOID
+HalR94aDebugPrint(
+ ULONG DebugLevel,
+ PUCHAR LedCharactor,
+ PUCHAR Message,
+ ...
+ );
+#endif
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halr94a/mips/jxhwsup.c b/private/ntos/nthals/halr94a/mips/jxhwsup.c
new file mode 100644
index 000000000..aa220a2d8
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxhwsup.c
@@ -0,0 +1,4265 @@
+// #pragma comment(exestr, "@(#) jxhwsup.c 1.1 95/09/28 15:38:22 nec")
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ M0001 1994.9.8 kuriyama@oa2
+ - Modify for R94A MIPS R4400
+
+ HalGetAdapter() - add routine for support PCIBus
+ Modify Internal MAX Dma Channel (r94a 0-3)
+
+ HalTranslateBusAddress() - add routine for support PCIBus
+
+ HalGetBusDataBy
+
+ M0002 1994.10.7 kuriyama@oa2
+ - Modify HalDmaChannel() - terminal count logic bug fix.
+
+ M0003 1994.10.14 kuriyama@oa2
+ - compile error clear
+ CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 23:20:04 JST 1994
+ - Merge BusHandlers
+
+ M0004 Fri Oct 28 14:56:02 JST 1994 kuriyama@oa2
+ - add BBM DMA routine (for edit buffer)(for BBM limited)
+ - add I/O cache flush if physical tag is valid(for BBM limited)
+ D001 ataka@oa2.kb.nec.co.jp (DMA CopyBuffer by kuriyama@oa2, other toghether)
+ Sat Nov 05 16:28:04 JST 1994
+ - Limit Check of Length (Only DbgPrint)
+ - Delete checking ByteMask
+ - TLB fill 0xff(by Kuriyama)
+
+ M005 Tue Dec 13 16:28:25 1994 kbnes!kisimoto
+ - changed the address that copies from, and source re-formated.
+
+ M0006 Thu Dec 22 11:46:16 JST 1994 kbnes!A.kuriyama
+ - add beta machine limit
+
+ S0007 Thu Jan 05 17:13:18 JST 1995 kbnes!A.Kuriyama
+ - warning clear
+
+ M0008 Fri Jan 13 13:49:51 JST 1995 kbnes!A.Kuriyama
+ - I/O cache flush routine was deleted in functions as follows
+ IoMapTransfer()
+ HalFlushCommonBuffer()
+
+ M0009 Mon Jan 23 14:31:44 JST 1995 kbnes!A.Kuriyama
+ - DMA Channel Interrupt routine change
+ - add Internal DMAC bytecount mask
+
+ M0010 Mon Jan 23 15:36:18 JST 1995 kbnes!A.Kuriyama
+ - Dma channel interrupt enable
+ HalpAllocateAdapter()
+ HalpCreateDmaStructure()
+
+ S0011 Tue Jan 24 18:28:55 JST 1995 kbnes!A.Kuriyama
+ - Compile error clear
+
+ M0012 Tue Jan 31 18:04:08 JST 1995 kbnes!A.Kuriyama
+ - add Internal slave dma 1MB limit.
+
+ M0013 Tue Jan 31 18:07:53 JST 1995 kbnes!A.Kuriyama
+
+ M0014 Tue Jan 31 18:37:33 JST 1995 kbnes!A.Kuriyama
+ - change I/O cache flush routine.
+ if length equal 0 no need i/o cache flush.
+
+ S0015 Wed Feb 01 12:03:06 JST 1995 kbnes!A.Kuriyama
+ - sccs update miss error clear
+
+ B0016 Thu Feb 2 22:09:32 1995 kbnes!kishimoto
+ - return pointer to adapterObject if InterfaceType
+ equals PCIBus
+
+ S0017 Wed Feb 22 12:00:58 JST 1995 kbnes!kuriyama (A)
+ - disable dma terminal interrupt
+
+ M0018 Tue Mar 07 11:26:44 JST 1995 kbnes!kuriyama (A)
+ - expand dma logical address space
+
+ S0019 Tue Mar 07 15:22:00 JST 1995 kbnes!kuriyama (A)
+ - compile error clear
+
+ M0020 Fri Mar 10 11:44:25 JST 1995 kbnes!kuriyama (A)
+ - logical address expand bug fix
+
+ S0021 Fri Mar 10 16:23:12 JST 1995 kbnes!kuriyama (A)
+ - internal slave bug fix
+
+ S0022 Tue Jun 27 19:12:30 JST 1995 kbnes!kisimoto
+ - del memmove prototype definition
+ to merge build 1057
+ change strings displaied with Tyhoon error
+
+ S0023 Thu Jul 20 20:11:34 JST 1995 kbnes!kisimoto
+ - add code for ESM from J94C
+
+ M0024 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:36:13 JST 1995
+ - add for x86bios support
+ - (change internal dma address to 1M-4M)
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCreateDmaStructures)
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+#define HalDump(x,y) if(HalDebug > 0) DbgPrint( x,y )
+/* M0006 */
+
+/* start M0004 */
+ULONG HalDebug = 0;
+#if defined(_BBM_DMA_)
+//
+// define copybuffer allocate routine.
+//
+
+VOID
+HalpAllocateCopyBuffer(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+//
+// Allocate Variable for DMA CopyBuffer
+//
+ ULONG CopyBufferPhysicalBase;
+ ULONG CopyBufferVirtualAddress;
+
+#endif // _BBM_DMA_
+
+#if defined(_BETA_LIMIT_)
+PVOID
+HalViewMemory (
+ IN PVOID Destination,
+ IN ULONG Length
+ );
+#endif // _BETA_LIMIT_
+/* end M0004 */
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpDmaChannelInterrupt;
+
+/* start M0001 */
+#if defined(_R94A_)
+//
+// The following is the interrupt object used for Typhoon Error interrupts.
+// Typhoon errorr interrupts occur when internal busmaster device error occurs.
+//
+
+KINTERRUPT HalpTyphoonErrorInterrupt;
+
+#endif // _R94A_
+/* end M0001 */
+
+UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. ";
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+//
+// The following function is called when a DMA channel interrupt occurs.
+//
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[8];
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+/* start M0001 */
+#if defined(_R94A_)
+BOOLEAN
+HalpCreateTyphoonErrorStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpTyphoonError(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+#endif // _R94A_
+/* end M0001 */
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif //_DMA_EXPAND_
+// M0018 ---
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND_
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+
+ if (virtualAddress == NULL) {
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - *NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ Hint,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = Hint;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+#if 0 // M0008
+/* M0006 +++ */
+#if defined(_BETA_LIMIT_)
+{
+ ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, i;
+ KIRQL OldIrql;
+
+ // D001
+// DbgPrint("DmaFlush start\n");
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ Ltag = READ_REGISTER_ULONG(LtagReg);
+ if (Ptag & 0x1) {
+ if (Ltag & 0x1) {
+ if ((LogicalAddress.LowPart & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (LogicalAddress.LowPart + Length))) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+ }
+ }
+ KeLowerIrql(OldIrql);
+// DbgPrint("DmaFlush end\n");
+}
+#endif // _BETA_LIMIT_
+/* M0006 --- */
+#endif // 0 // M0008
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+ return;
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: Internal, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+// M0020 +++
+#if DBG
+#if defined (_DMA_EXPAND_)
+ DbgPrint("\nHalGetAdapter(): DeviceDescription->32BitAddresses = %d\n",DeviceDescription->Dma32BitAddresses);
+#endif // _DMA_EXPAND_
+#endif // DBG
+// M0020 ---
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) {
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+ }
+
+ if (DeviceDescription->InterfaceType == Internal) {
+
+
+ //
+ // Return the adapter pointer for internal adapters.
+ //
+ // If this is a master controler such as the SONIC then return the
+ // last channel.
+ //
+
+ if (DeviceDescription->Master) {
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Create an adapter.
+ //
+
+ adapterObject = HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[7],
+ NULL
+ );
+
+ adapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+
+// M0020 +++
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+#endif DBG
+
+ if (adapterObject->Dma32BitAddresses) {
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("internal master adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses);
+#endif // DBG
+// M0020 ---
+
+ return(adapterObject);
+
+#else // _DMA_EXPAND
+
+ //
+ // Create an adapter if necessary.
+ //
+
+ if (HalpInternalAdapters[7] == NULL) {
+
+ HalpInternalAdapters[7] = HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[7],
+ NULL
+ );
+
+ }
+
+ return(HalpInternalAdapters[7]);
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ }
+
+ //
+ // Make sure the DMA channel range is valid. Only use channels 0-6.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ if (DeviceDescription->DmaChannel > 3) { // duo and r94a have only 0-3 channel
+
+ return(NULL);
+ }
+
+#else // _R94A_
+
+ if (DeviceDescription->DmaChannel > 6) {
+
+ return(NULL);
+ }
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // If necessary allocate an adapter; otherwise,
+ // just return the adapter for the requested channel.
+ //
+
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel] == NULL) {
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel] =
+ HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[DeviceDescription->DmaChannel],
+ NULL
+ );
+
+ }
+
+// M0012 +++
+#if defined(_R94A_)
+// M0020 +++
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+#endif DBG
+// M0020 ---
+
+ //
+ // Internal slave dma limit 1MB. (TYPHOON tip limit)
+ //
+
+ if (*NumberOfMapRegisters > ( 0x100000 >> PAGE_SHIFT )) {
+
+ *NumberOfMapRegisters = ( 0x100000 >> PAGE_SHIFT );
+ }
+
+#endif // _R94A_
+// M0012 ---
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+// M0020 +++
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses) { // S0021
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses
+ = DeviceDescription->Dma32BitAddresses;
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("internal slave HalpInternalAdapters[%d]->Dma32BitAddresses = %d\n",
+ DeviceDescription->DmaChannel,
+ HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses);
+#endif // DBG
+
+// M0020 ---
+#endif // _DMA_EXPAND_
+// M0018 ---
+ return(HalpInternalAdapters[DeviceDescription->DmaChannel]);
+ }
+
+/* start M0001 */
+#if defined(_R94A_)
+ //
+ // PCI Bus check.
+ //
+ if (DeviceDescription->InterfaceType == PCIBus) {
+
+ adapterObject = HalpAllocatePCIAdapter( DeviceDescription );
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+// M0020 +++
+ if (adapterObject->Dma32BitAddresses) {
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+
+ adapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("PCI master adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses);
+#endif // DBG
+// M0020 ---
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ return(adapterObject); // B0016
+
+ }
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != Eisa) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+// M0020 +++
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+#endif DBG
+// M0020 ---
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+// M0020 +++
+ if (adapterObject->Dma32BitAddresses) {
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("eisa/isa adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses);
+#endif // DBG
+// M0020 ---
+
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ return(adapterObject);
+}
+
+#if 0 // CHG0001
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ return(TRUE);
+ }
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != PCIBus) {
+
+#else // _R94A_
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // There is only one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+
+#if !defined(_DUO_)
+
+ if (DMA_CONTROL->RevisionLevel.Long < 2) {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ } else {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+ }
+#else
+
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+#endif
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+}
+#endif
+
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+ ULONG Mode;
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter( 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if (AdapterBaseVa == NULL) {
+
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+ AdapterObject->PagePort = NULL;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+ ULONG MapRegisterSize;
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // set bit for unusable area
+ //
+
+// M0020 +++
+#if DBG
+ DbgPrint("translatiron start %x\n",HalpMapRegisterPhysicalBase);
+ DbgPrint("translatiron size %x\n",MapRegisterSize);
+#endif // DBG
+
+ RtlFindClearBitsAndSet(
+ AdapterObject->MapRegisters,
+ ((EISA_MIN_ADR - ISA_MAX_ADR) / PAGE_SIZE),
+ (ISA_MAX_ADR / PAGE_SIZE)
+ );
+ DbgPrint("unused start %x\n",ISA_MAX_ADR / PAGE_SIZE);
+ DbgPrint("unused length %x\n",(EISA_MIN_ADR - ISA_MAX_ADR) / PAGE_SIZE);
+// M0020 ---
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG1_BASE);
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationBase.Long,
+ HalpMapRegisterPhysicalBase
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationLimit.Long,
+ MapRegisterSize
+ );
+
+ //
+ // Initialize the DMA mode registers for the Floppy, SCSI and Sound.
+ // The initialization values come fomr the System Specification.
+ //
+
+#if defined(_JAZZ_)
+
+ Mode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_120NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_8BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[FLOPPY_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_A].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_B].Mode.Long,
+ (ULONG) Mode
+ );
+
+#endif
+
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ return AdapterObject;
+
+ return (PADAPTER_OBJECT) NULL;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND_
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - Wcb->NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND_
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize the DMA interrupt dispatcher for I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpDmaChannelInterrupt,
+ HalpDmaChannel,
+ (PVOID) NULL,
+ (PKSPIN_LOCK) NULL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpDmaChannelInterrupt );
+
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ PCR->InterruptRoutine[DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpDmaDispatch;
+
+/* start M0001 */
+#if defined(_R94A_)
+
+/* M0010 +++ */
+
+ //
+ // Enable DmaChannel Interrupt
+ //
+{
+ ULONG Dword,Channel;
+
+ Dword = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long);
+
+ Dword |= 1; // S0011
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long, Dword); // S011
+
+#if 0 // S0017
+ //
+ // Enable Interrupt when done every channel
+ //
+
+ for (Channel = 0; Channel < 4; Channel++) {
+ Dword = READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Mode);
+ Dword |= 0x20;
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Mode, Dword);
+ }
+#endif // 0 // S0017
+}
+
+
+/* M0010 --- */
+
+ //
+ // Initialize Typhoon error interrupts.
+ //
+
+ HalpCreateTyphoonErrorStructures();
+
+#endif // _R94A_
+/* end M0001 */
+
+ return TRUE;
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+ KIRQL OldIrql; // kuriyama
+
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+ ULONG bufferAddress;
+ ULONG bufferLogical;
+#endif // _BBM_DMA_
+/* end M0004 */
+
+#if 0 //M0008
+/* M0005 +++ */
+#if defined(_BETA_LIMIT_)
+{
+ ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, logicalAddress;
+ KIRQL OldIrql;
+
+ if (!WriteToDevice) {
+ logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ Ltag = READ_REGISTER_ULONG(LtagReg);
+ if (Ptag & 0x1) {
+ if (Ltag & 0x1) {
+ if ((logicalAddress & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (logicalAddress + *Length))) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+ }
+ }
+ KeLowerIrql(OldIrql);
+ }
+}
+#endif // _BETA_LIMIT_
+/* M0005 --- */
+#endif // 0 // M0008
+
+#if defined(_BBM_DMA_)
+{
+ ULONG PtagReg, Ptag, DummyRead;
+ // D001
+ if (*Length > (PAGE_SIZE * DMA_TRANSLATION_LIMIT / 8 / 8 )) { // kuriyama
+ DbgPrint("IoMapTransfer: *Length > %d pages\n", (DMA_TRANSLATION_LIMIT / 8 / 8));
+ }
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ if (Ptag & 0x1) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+}
+#endif // _BBM_DMA_
+#if 0 // kuriyama // D001 Delete checking ByteMask
+// temp kuriyama start
+ for (i=0; i < 8; i++) {
+ if (READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[i])){
+ DbgPrint("IoMapTransfer : LowByteMask[%d] is 0x%x\n",i,(ULONG)READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[i]));
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ if (READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[i])){
+ DbgPrint("IoMapTransfer : HighByteMask[%d] is 0x%x\n",i,(ULONG)READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[i]));
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ }
+// temp kuriyaam end
+#endif // if 0 // kuriyama
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+ if (!WriteToDevice) {
+// HalSweepDcache();
+// HalSweepIcache();
+ HalDump("IoMapTransfer: AdapterObject = %x\n",(ULONG)AdapterObject);
+ for (i = 0; i < NumberOfPages; i++) {
+ bufferLogical = (((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT) + (i << PAGE_SHIFT);
+ HalDump("IoMapTransfer: bufferLogical = %x\n",bufferLogical);
+ bufferAddress = CopyBufferPhysicalBase + bufferLogical;
+ HalDump("IoMapTransfer: bufferAddress = %x\n",bufferAddress);
+ (DmaMapRegister++)->PageFrame = bufferAddress;
+ }
+ } else {
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+ }
+#else // _BBM_DMA_
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+#endif // _BBM_DMA_
+/* end M0004 */
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+ if (!WriteToDevice) {
+ Offset = 0;
+ ;
+ }
+#endif // _BBM_DMA_
+/* end M0004 */
+
+ //
+ // Set the offset to point to the map register plus the offset.
+ //
+
+ Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+/* start M0004 */
+ if (!WriteToDevice) {
+ HalDump("IoMapTransfer: Offset %x\n",Offset); /* M0004 */
+ HalDump("IoMapTransfer: Length %x\n",*Length); /* M0004 */
+ HalDump("IoMapTransfer: CurrentVa %x\n",CurrentVa); /* M0004 */
+ }
+/* end M0004 */
+
+ //
+ // Invalidate the translation entry.
+ //
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long, 1);
+
+#if defined(_BBM_DMA_)
+ KeLowerIrql(OldIrql); // kuriyama
+#endif //_BBM_DMA_
+ if ( AdapterObject == NULL) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+
+ if (AdapterObject->PagePort == NULL) {
+
+// M0013 +++
+#if defined(_R94A_)
+ //
+ // if Master Device, nothing set to DMAC.
+ //
+
+ if ( AdapterObject->AdapterBaseVa == &(DMA_CONTROL)->Channel[7]) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+#endif // _R94A_
+// M0013 ---
+ //
+ // Set the local DMA Registers.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Address.Long, Offset);
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long, *Length);
+
+ i = 0;
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 1;
+ ((PDMA_CHANNEL_ENABLE) &i)->TransferDirection =
+ WriteToDevice ? DMA_WRITE_OP : DMA_READ_OP;
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, i);
+
+
+ } else {
+
+ //
+ // Start the EISA DMA controller.
+ //
+
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+
+ ULONG i;
+ UCHAR DataByte;
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+
+#if 0
+ PCCHAR bufferAddress;
+#endif
+
+ PCCHAR mapAddress;
+ ULONG logicalAddress;
+ ULONG Offset;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+
+ if (!WriteToDevice) {
+
+ HalDump("IoFlushAdapterBuffers: AdapterObject = %x\n",(ULONG)AdapterObject);
+
+#if 0
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+ HalDump("IoFlushAdapterBuffers: bufferAddress = %x\n",bufferAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",Length);
+#endif
+
+ logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+ HalDump("IoFlushAdapterBuffers: logicalAddress = %x\n",logicalAddress);
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+ HalDump("IoFlushAdapterBuffers: Offset = %x\n",Offset);
+
+ mapAddress = (PCCHAR)(CopyBufferVirtualAddress + logicalAddress);
+
+ HalDump("IoFlushAdapterBuffers: mapAddress = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: CurrentVa = %x\n",CurrentVa);
+
+// DbgBreakPoint();
+// RtlMoveMemory(CurrentVa, mapAddress, Length);
+// DbgBreakPoint();
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ HalDump("IoFlushAdapterBuffers: NumberOfPages = %x\n",NumberOfPages);
+
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ HalDump("IoFlushAdapterBuffers: PageFrameNumber = %x\n",PageFrameNumber);
+
+ if (NumberOfPages == 1) {
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",Length);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE )+ Offset),
+ (PVOID)mapAddress, Length
+ );
+
+ } else if ( NumberOfPages == 2) {
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE - Offset);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ) + Offset),
+ (PVOID)mapAddress, (ULONG)(PAGE_SIZE - Offset)
+ );
+
+#if 0
+ HalDump("IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE)
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + PAGE_SIZE + Offset);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n" , BYTE_OFFSET(Length + Offset - 1) + 1);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ ((PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE )),
+// (PVOID)(mapAddress + PAGE_SIZE + Offset),
+ (PVOID)(mapAddress + PAGE_SIZE - Offset), // H001
+ (ULONG)(BYTE_OFFSET(Length + Offset - 1) + 1)
+ );
+
+ } else {
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE - Offset);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ) + Offset),
+ (PVOID)mapAddress,
+ (ULONG)(PAGE_SIZE - Offset)
+ );
+
+ for (i = 1; i < (NumberOfPages - 1); i++) {
+#if 0
+ HalDump("IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE)
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + (i * PAGE_SIZE) +Offset);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE),
+// (PVOID)((mapAddress + (i * PAGE_SIZE)) + Offset),
+ (PVOID)(mapAddress + (i * PAGE_SIZE) - Offset), // H001
+ PAGE_SIZE
+ );
+
+ }
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + (i * PAGE_SIZE) + Offset);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",BYTE_OFFSET(Length + Offset - 1) + 1);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ),
+// (PVOID)(mapAddress + (i * PAGE_SIZE) + Offset),
+ (PVOID)(mapAddress + (NumberOfPages - 1) * PAGE_SIZE - Offset), // H001
+ (ULONG)(BYTE_OFFSET(Length + Offset - 1) + 1)
+ );
+
+ }
+ }
+#endif // _BBM_DMA_
+/* end M0004 */
+/* M0006 +++ */
+#if defined(_BETA_LIMIT_)
+#if 0 // M0008
+{
+ ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, logicalAddress;
+ KIRQL OldIrql;
+
+ if (!WriteToDevice) { // M0005
+ logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+ // D001
+// DbgPrint("DmaFlush start\n");
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ Ltag = READ_REGISTER_ULONG(LtagReg);
+ if (Ptag & 0x1) {
+ if (Ltag & 0x1) {
+ if ((logicalAddress & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (logicalAddress + Length))) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+ }
+ }
+ KeLowerIrql(OldIrql);
+// DbgPrint("DmaFlush end\n");
+ } // M0005
+
+}
+#endif // 0 //M0008
+/* M0005,M0014 +++ */
+{
+ ULONG Offset, NumberOfPages;
+ PULONG PageFrameNumber;
+ KIRQL OldIrql;
+
+ if (Length != 0) { //S0015
+ if (!WriteToDevice) {
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql); // kuriyama
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ if (NumberOfPages == 1) {
+ HalViewMemory((PVOID)((KSEG1_BASE |(((ULONG) *PageFrameNumber++
+ << PAGE_SHIFT) + Offset))),
+ Length);
+ } else {
+ HalViewMemory( (PVOID)((KSEG1_BASE |(((ULONG) *PageFrameNumber++
+ << PAGE_SHIFT) + Offset))),
+ (PAGE_SIZE - Offset));
+ for (i = 1; i < NumberOfPages -1; i++) {
+ HalViewMemory( (PVOID)((KSEG1_BASE |((ULONG) *PageFrameNumber++
+ << PAGE_SHIFT))), PAGE_SIZE);
+ }
+ HalViewMemory( (PVOID)((KSEG1_BASE
+ |((ULONG) *PageFrameNumber++ << PAGE_SHIFT))),
+ BYTE_OFFSET(Offset + Length -1) +1);
+ }
+ KeLowerIrql(OldIrql);
+ }
+ }
+}
+
+/* M0005,M0014 --- */
+
+#endif // _BETA_LIMIT_
+/* M0006 --- */
+
+ if (AdapterObject == NULL) {
+
+ //
+ // This is a master adadapter so there is nothing to do.
+ //
+
+ return(TRUE);
+ }
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else {
+
+// M0013 +++
+#if defined(_R94A_)
+ //
+ // if Master Device, nothing set to DMAC.
+ //
+
+ if ( AdapterObject->AdapterBaseVa == &(DMA_CONTROL)->Channel[7]) {
+ return(TRUE);
+ }
+#endif // _R94A_
+// M0013 ---
+ //
+ // Clear on board DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ i = READ_REGISTER_USHORT(
+ &((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable
+ );
+ }
+
+ return(TRUE);
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+#if 0 // CHG0001
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+/* start M0001 */
+#if 0
+#if defined(_R94A_)
+
+ case PCIConfiguration:
+ DataLength = HalpReadPCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+#endif // _R94A_
+#endif // 0
+/* end M0001 */
+
+ }
+
+ return(DataLength);
+
+}
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+/* start M0001 */
+#if 0
+#if defined(_R94A_)
+
+ switch (BusDataType) {
+
+ case PCIConfiguration:
+ DataLength = HalpWritePCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+#endif // _R94A_
+#endif // 0
+/* end M0001 */
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory ((PVOID)Buffer, (PVOID)((PUCHAR)SlotInformation + Offset), (ULONG)DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+#endif
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ } else {
+
+ //
+ // Disable the DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ saveEnable = i;
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ //
+ // Read the transfer count.
+ //
+
+ count = 0xfffff & READ_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long); // beta typhoon errata// M0009
+
+ //
+ // Reset the Enable register.
+ //
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ saveEnable
+ );
+
+ }
+
+ return(count);
+}
+
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a DMA channel interrupt occurs.
+ These should never occur. Bugcheck is called if an error does occur.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+
+ ULONG DataWord;
+ ULONG Channel;
+ DMA_CHANNEL_ENABLE ChannelWord;
+ ULONG ErrorFlag = 0; /* M0003 */
+
+#if defined(_JAZZ_)
+
+ //
+ // Read the DMA channel interrupt source register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long);
+
+ for (Channel = 0; Channel < 8; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << Channel))) {
+ continue;
+ }
+
+ DmaChannelMsg[18] = (CHAR) Channel + '0';
+
+ HalDisplayString(DmaChannelMsg);
+
+ *((PULONG) &ChannelWord) =
+ READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long);
+
+ if (ChannelWord.TerminalCount) {
+ HalDisplayString("Terminal count was reached.\n");
+ }
+
+ if (ChannelWord.MemoryError) {
+ HalDisplayString("A memory error was detected.\n");
+ }
+
+ if (ChannelWord.TranslationError) {
+ HalDisplayString("A translation error occured.\n");
+ }
+
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+#endif
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // S0023
+
+ //
+ // Read the DMA channel interrupt source register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->ChannelInterruptAcknowledge.Long);
+
+ for (Channel = 0; Channel < 4; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << Channel))) {
+ continue;
+ }
+
+ DmaChannelMsg[18] = (CHAR) Channel + '0';
+
+
+ *((PULONG) &ChannelWord) =
+ READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long);
+
+/* start M0002 */
+ if (ChannelWord.TerminalCount) {
+ if ((0xfffff & READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].ByteCount.Long)) != 0) { // beta typhoon errta // M0009
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("Terminal count was reached."); // S0011
+ ErrorFlag++;
+ }
+ }
+
+ if (ChannelWord.MemoryError) {
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("A memory error was detected."); // S0011
+ ErrorFlag++;
+ }
+
+ if (ChannelWord.ParityError) {
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("A Parity error occured."); // S0011
+ ErrorFlag++;
+ }
+
+ if (ChannelWord.MasterAbort) {
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("A PCIBus Master Abort error occured."); // S0011
+ ErrorFlag++;
+ }
+
+ // Clear Dma Channel Interrupt
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long, 0x00000100); // M0009
+/* end M0002 */
+ }
+
+ if (ErrorFlag != 0) {
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+#endif // _R94A_
+/* end M0001 */
+
+ return(TRUE);
+}
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ HalpMapRegisterPhysicalBase = PhysicalAddress;
+
+#if defined(_BBM_DMA_)
+/* start kuriyama TLB fill 0xff */ // D001
+ RtlFillMemory( (HalpMapRegisterPhysicalBase | KSEG1_BASE), 0x2000, 0xff);
+/* end kuriyama TLB fill 0xff */
+#endif // _BBM_DMA_
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+ HalpAllocateCopyBuffer(LoaderBlock);
+#endif // _BBM_DMA_
+/* end M0004 */
+}
+
+/* start M0001 */
+#if defined(_R94A_)
+BOOLEAN
+HalpCreateTyphoonErrorStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Typhoon Error
+ interrupt dispatcher. It also connects an interrupt handler to the
+ Typhoon Error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ //
+ // Initialize the Typhoon Error interrupt dispatcher for I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpTyphoonErrorInterrupt,
+ HalpTyphoonError,
+ (PVOID) NULL,
+ (PKSPIN_LOCK) NULL,
+ TYPHOON_ERROR_INTERRUPT_VECTOR,
+ DEVICE_LEVEL,
+ DEVICE_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ return KeConnectInterrupt( &HalpTyphoonErrorInterrupt );
+
+}
+#endif // _R94A_
+/* end M0001 */
+
+/* start M0001 */
+#if defined(_R94A_)
+BOOLEAN
+HalpTyphoonError(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a Typhoon Error interrupt occurs.
+ This error is cretical. Bugcheck is called if an error does occur.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+ Note. This function never return. This function call always KeBugCheck().
+
+--*/
+{
+
+ ULONG DataWord;
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // S0023
+
+ //
+ // Read the Typhoon Error Status register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->TyphoonErrorStatus);
+
+ HalDisplayString("\nHAL: Internal master error occurred.\n"); // S0022
+
+ if ( DataWord & 2) {
+
+ HalDisplayString("ethernet bus master error\n");
+
+ }
+
+ if ( DataWord & 4) {
+
+ HalDisplayString("SCSI port 1 bus master error\n");
+
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+
+ return(TRUE);
+}
+#endif // _R94A_
+/* end M0001 */
+
+#if defined(_BBM_DMA_)
+VOID
+HalpAllocateCopyBuffer(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for copybuffer directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = 0x400000;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ CopyBufferPhysicalBase = PhysicalAddress;
+ HalDump("Common Buffer Physical = %x\n",CopyBufferPhysicalBase);
+ CopyBufferVirtualAddress = PhysicalAddress | KSEG1_BASE;
+ HalDump("Common Buffer Virtual = %x\n",CopyBufferVirtualAddress);
+}
+#endif // _BBM_DMA_
+/* end M0004 */
diff --git a/private/ntos/nthals/halr94a/mips/jxmapio.c b/private/ntos/nthals/halr94a/mips/jxmapio.c
new file mode 100644
index 000000000..879f96410
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxmapio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmapio.c"
diff --git a/private/ntos/nthals/halr94a/mips/jxmaptb.c b/private/ntos/nthals/halr94a/mips/jxmaptb.c
new file mode 100644
index 000000000..9262bc775
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxmaptb.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmaptb.c"
diff --git a/private/ntos/nthals/halr94a/mips/jxport.c b/private/ntos/nthals/halr94a/mips/jxport.c
new file mode 100644
index 000000000..26e310528
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxport.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxport.c"
diff --git a/private/ntos/nthals/halr94a/mips/jxreturn.c b/private/ntos/nthals/halr94a/mips/jxreturn.c
new file mode 100644
index 000000000..d77d5642b
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxreturn.c
@@ -0,0 +1,258 @@
+// #pragma comment(exestr, "@(#) jxreturn.c 1.1 95/09/28 15:40:17 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ H000 Tue Apr 25 16:02:05 1995 kbnes!kisimoto
+ -add Powerdown if argument value indicates
+ HalPowerDownRoutine
+ S001 kuriyama@oa2.kb.nec.co.jp Sun May 21 18:32:55 JST 1995
+ -compile error clear
+ S002 kuriyama@oa2.kb.nec.co.jp Sun May 21 20:19:48 JST 1995
+ - powoff bug? fixed
+ H003 Sat Aug 12 19:33:45 1995 kbnes!kisimoto
+ - Removed _J94C_ definitions.
+ _J94C_ definition indicates that the status of the
+ dump switch can acknowledge from Self-test register.
+
+ M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:28:35 JST 1995
+ - add for x86bios emurator support
+--*/
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO Pte[2];
+ ULONG Index; // A001
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE;
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; //S004
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+
+#if defined (_MRCPOWER_)
+
+ //
+ // S004
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ Eax = 0x12; // AH = 0 AL = 0x12
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // H000,S001
+ // Powerdown the machine
+ //
+
+ //
+ // Map the MRC
+ //
+
+ Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT;
+
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map MRC using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // Send Powerdown Command to the MRC.
+ //
+
+
+ for (;;) { // S002
+ WRITE_REGISTER_UCHAR(
+ &MRC_CONTROL->SoftwarePowerOff,
+ 0x1
+ );
+ }
+
+ for (;;) {
+ }
+#endif //_MRCPOWER_
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ //
+ // S004
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ Eax = 0x12; // AH = 0 AL = 0x12
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Map the keyboard controller
+ //
+
+ Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map keyboard controller using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreData(0);
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
+
diff --git a/private/ntos/nthals/halr94a/mips/jxsysint.c b/private/ntos/nthals/halr94a/mips/jxsysint.c
new file mode 100644
index 000000000..19703799d
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxsysint.c
@@ -0,0 +1,355 @@
+// #pragma comment(exestr, "@(#) jxsysint.c 1.1 95/09/28 15:40:45 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - HalDisableSystemInterrupt()
+ change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL.
+ add the PCI interrupt vector.
+ Interrupt Enable register is zero origin on beta-version of
+ STORM chipset.
+ if ASIC3 register is zero, then chipset is beta-version.
+ - HalEnableSystemInterrupt()
+ change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL.
+ add the PCI interrupt vector.
+ Interrupt Enable register is zero origin on beta-version of
+ STORM chipset.
+ if ASIC3 register is zero, then chipset is beta-version.
+ - HalGetInterruptVector()
+ add PCIBus interface.
+ change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL.
+ If InterfaceType is Internal and ASIC3 register is zero,
+ then return the vector which was plus the offset of DEVICE_VECTORS.
+ H001 Mon Oct 17 14:21:21 JST 1994 kbnes!kishimoto
+ - Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ - XXX_EISA_PCI_XXX rename to XXX_EISA_XXX
+ - MAXIMUM_PCI_SLOT rename to R94A_PCI_SLOT
+ - HalGetInterruptVector()
+ returns PCI-vector plus offset PCI_VECTORS.
+ - modify original compile error
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:46:35 JST 1994
+ - reslve compile error
+ H002 Mon Oct 31 17:45:56 1994 kbnes!kishimoto
+ - HalGetInterruptVector()
+ Internal SCSI interrupt vector set to 5 (for BBM only)
+ M003 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 17:06:37 JST 1995
+ - add _IPI_LIMIT_ support
+ S004 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 11:10:52 JST 1995
+ - compile error clear
+ H005 Fri Aug 11 16:53:13 1995 kbnes!kishimoto
+ - delete M003, and HalGetInterruptVector(move to bushnd.c)
+
+ M006 kuriyama@oa2.kbnes.nec.co.jp
+ - add for merge R94A/R94A'/R94D HAL
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));
+
+#if defined(_R94A_)
+
+ if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){
+
+ //
+ // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
+ // Enable register is zero origin.
+ //
+ // N.B. This obstruction is limiteded to beta-version of STORM chipset.
+ //
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill,
+ HalpBuiltinInterruptEnable);
+ } else {
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+ }
+
+#else
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+
+#endif
+
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+#if defined(_R94A_)
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector <= PCI_VECTORS + R94A_PCI_SLOT &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisablePCIInterrupt(Vector);
+ }
+
+#endif
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // enable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
+
+#if defined(_R94A_)
+
+ if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){
+
+ //
+ // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
+ // Enable register is zero origin.
+ //
+ // N.B. This obstruction is limiteded to beta-version of STORM chipset.
+ //
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill,
+ HalpBuiltinInterruptEnable);
+
+ } else {
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+
+ }
+#else
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+
+#endif
+
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+#if defined(_R94A_)
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector <= PCI_VECTORS + R94A_PCI_SLOT &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnablePCIInterrupt(Vector);
+ }
+
+#endif
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(_DUO_) // S004
+
+ //
+ // For Merge R94A/R94A'/R94D HAL
+ //
+ // Old version need ChipSet Bug Workaround.
+ //
+
+ ULONG OldIpiReq;
+ KIRQL OldIrql;
+
+ if (HalpUseChipSetWorkaround) {
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+ KeRaiseIrql(HIGH_LEVEL,&OldIrql);
+
+ KiAcquireSpinLock(&HalpIpiRequestLock);
+
+ OldIpiReq = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long);
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long,
+ OldIpiReq | Mask);
+
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long);
+
+ KiReleaseSpinLock(&HalpIpiRequestLock);
+
+ KeLowerIrql(OldIrql);
+ } else {
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long, Mask);
+ }
+
+
+#endif
+
+ return;
+}
diff --git a/private/ntos/nthals/halr94a/mips/jxtime.c b/private/ntos/nthals/halr94a/mips/jxtime.c
new file mode 100644
index 000000000..5d9c29705
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxtime.c
@@ -0,0 +1,377 @@
+// #pragma comment(exestr, "@(#) jxtime.c 1.1 95/09/28 15:41:57 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ M0001 1994.9.9 kbnes!A.Kuriyama
+
+ Modify for R94A
+
+ HalpReadClockRegister() - R94A use RTC Index register except EISA NmiEnable
+ register.
+ HalpWriteClockRegister() - R94A use RTC Index register except EISA NmiEnable
+ register.
+
+ M0002 1994.10.8 kbnes!kuriyama(A)
+
+ HalpReadClockRegister()
+ -add specify Read Data register
+ HalpWritelockRegister()
+ -add specify Write Data register
+
+ M0003 1994.10.14 kbnes!kuriyama(A)
+
+ define error clear
+
+ M0004 1994.12.19 kbnes!kuriyama(A)
+
+ define miss fix
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+/* start M0001 */
+#if defined(_R94A_) /* M0003 */
+ // Insert the realtime clock register number, and write the value back
+ // to RTC Index register. This selects the realtime clock register
+ // that is read.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_REGISTERS) HalpRealTimeClockBase)->Index,
+ Register);
+
+
+#else // _R94A_
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ Register |= 0x80;
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Read the realtime clock register value.
+ //
+
+/* start M0002 */
+#if defined(_R94A_) // M0004
+
+ return READ_REGISTER_UCHAR( &((PRTC_REGISTERS) HalpRealTimeClockBase)->Data);
+
+
+#else // _R94A_
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+
+#endif // _R94A_
+/* end M0002 */
+
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+/* start M0001 */
+#if defined(_R94A_)
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to RTC Index register. This selects the realtime clock
+ // register that is written.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_REGISTERS) HalpRealTimeClockBase)->Index,
+ Register);
+
+#else // _R94A_
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ Register |= 0x80;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Write the realtime clock register value.
+ //
+
+/* start M0002 */
+#if defined(_R94A_) // M0004
+
+ WRITE_REGISTER_UCHAR( &((PRTC_REGISTERS) HalpRealTimeClockBase)->Data, Value);
+
+#else // _R94A_
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+
+#endif // _R94A_
+/* end M0002 */
+
+ return;
+}
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr94a/mips/jxusage.c b/private/ntos/nthals/halr94a/mips/jxusage.c
new file mode 100644
index 000000000..12a54de49
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/jxusage.c
@@ -0,0 +1,510 @@
+// #pragma comment(exestr, "@(#) jxusage.c 1.1 95/09/28 15:42:20 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:26:38 JST 1994
+ - Change PRIMARY_VECTOR_BASE to DEVICE_VECTOTRS
+ CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:53:42 JST 1994
+ - delete HalpEnableInterruptHandler, HalpRegisterVector
+ - change IDT vector LOOP, R94A report up to DEVICE_VECTORS
+ - change MAXIMUM_IDTVECTOR to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:53:32 JST 1994
+ - resolve compile error
+ CMP002 ataka@oa2.kb.nec.co.jp Tue Oct 18 22:33:14 JST 1994
+ - add following
+ // HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ // HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ // HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+#if !defined(_R94A_) // CMP001
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif // _R94A
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+#if !defined (_R94A_) // CHG001
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+#endif // _R94A_
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+#if defined(_R94A_)
+// HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+// HalpRegisterAddressUsage (&HalpEisaIoSpace);
+// HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+#endif // _R94A_
+
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+#if defined(_R94A_) // CHG001
+ for(i=0; i < DEVICE_VECTORS; i++) { // ADD001
+ HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+#else
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+#endif
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_VECTOR) { // CHG001
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halr94a/mips/mipsdat.c b/private/ntos/nthals/halr94a/mips/mipsdat.c
new file mode 100644
index 000000000..bfe2b9273
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/mipsdat.c
@@ -0,0 +1,145 @@
+// #pragma comment(exestr, "@(#) mipsdat.c 1.1 95/09/28 15:42:43 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*++
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:53:16 JST 1994
+ - add HalpMapRegisterMemorySpace
+ BUG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:49:18 JST 1994
+ - change HalpMapRegisterMemorySpace Size
+ CNG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:58:30 JST 1994
+ - change HalpIDTUsage size to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:34:47 JST 1994
+ - resolve compile error
+ A002 ataka@oa2.kb.nec.co.jp 1995/6/17
+ - merge 1050
+
+--*/
+
+
+
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC
+ EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC
+
+ EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe
+
+ EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B)
+ EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A
+
+ EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable
+ EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI
+ EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted
+
+ EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers
+
+ EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+#define R94A_MAPREGISTER_BASE 100 // CMP001
+
+// BUG001
+ADDRESS_USAGE HalpMapRegisterMemorySpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ R94A_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001
+ 0, 0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+// CNG001
+#if defined(MIPS)
+IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[]
+#else // CMP001
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif
+
diff --git a/private/ntos/nthals/halr94a/mips/mode542x.h b/private/ntos/nthals/halr94a/mips/mode542x.h
new file mode 100644
index 000000000..3550a0714
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/mode542x.h
@@ -0,0 +1,1302 @@
+// #pragma comment(exestr, "@(#) mode542x.h 1.1 95/09/28 15:43:49 nec")
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Mode542x.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-542x driver.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// The next set of tables are for the CL542x
+// Note: all resolutions supported
+//
+
+//
+// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode
+
+ EOD
+};
+
+//
+// 800x600 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_800x600[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode
+
+ EOD
+};
+
+//
+// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_1024x768[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ EOD
+};
+
+//-----------------------------
+// standard VGA text modes here
+// 80x25 at 640x350
+//
+//-----------------------------
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (720x400 pixel resolution; 9x16 character cell.)
+//
+
+USHORT CL542x_80x25Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (640x350 pixel resolution; 8x14 character cell.)
+//
+
+USHORT CL542x_80x25_14_Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x.
+//
+
+USHORT CL542x_1280x1024[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_64k[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 4,
+ 0x0506, // Some BIOS's set Chain Odd maps bit
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#ifdef _X86_
+
+//
+// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x.
+//
+
+USHORT CL542x_800x600_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#else
+
+//
+// NOTE(DBCS) : Update 94/09/12 - NEC Corporation
+//
+// - Add mode set command string for NEC MIPS machine.
+//
+// - 640x480 256 color 72Hz
+// - 800x600 256 color 56 / 60Hz
+// - 1024x768 256 color 70 / 45Hz
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+//
+// For MIPS NEC machine only
+//
+
+//
+// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xE3,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F,
+ 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x420E,
+ 0x2B1B,0x2F1C,0x301D,0x1F1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h)
+//
+// - Set Mode Type is VESA compatible. (Old Miss match)
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99,
+ 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+
+// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match
+// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode.
+// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B,
+// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+// 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_56[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12,
+ 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x510E,
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B,
+ 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B,0x5B0C,0x450D,0x650E,
+
+#else
+
+ 0x4A0B,0x5B0C,0x450D,0x640E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x760E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x341E,
+
+#else
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x3B0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x1A1E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_70[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x6E0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x2A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for
+// CL 542x. (Interlaced)
+//
+
+USHORT CL542x_1024x768_256_87[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x550E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x361E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99,
+ 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83,
+ 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x84,
+ 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+#endif
diff --git a/private/ntos/nthals/halr94a/mips/modeset.h b/private/ntos/nthals/halr94a/mips/modeset.h
new file mode 100644
index 000000000..63122b13b
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/modeset.h
@@ -0,0 +1,85 @@
+// #pragma comment(exestr, "@(#) modeset.h 1.1 95/09/28 15:45:03 nec")
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Modeset.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-6410 and CL-6420 driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Mode structure.
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ *
+ */
+
+#include "cmdcnst.h"
+
+//---------------------------------------------------------------------------
+//
+// The actual register values for the supported modes are in chipset-specific
+// include files:
+//
+// mode64xx.h has values for CL6410 and CL6420
+// mode542x.h has values for CL5422, CL5424, and CL5426
+//
+
+
+USHORT HalpCirrus_MODESET_1K_WIDE[] = {
+ OW, // stretch scans to 1k
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x8013,
+
+ EOD
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr94a/mips/pcibrd.c b/private/ntos/nthals/halr94a/mips/pcibrd.c
new file mode 100644
index 000000000..2124dda34
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/pcibrd.c
@@ -0,0 +1,1020 @@
+// #pragma comment(exestr, "@(#) pcibrd.c 1.1 95/09/28 15:45:30 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+// #define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halr94a/mips/pcibus.c b/private/ntos/nthals/halr94a/mips/pcibus.c
new file mode 100644
index 000000000..a77edf46e
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/pcibus.c
@@ -0,0 +1,3585 @@
+// #pragma comment(exestr, "@(#) pcibus.c 1.1 95/09/28 15:45:56 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Jun 30 02:54:08 1995 kbnes!kisimoto
+ - Merge build 1057 ixpcibus.c
+ H002 Tue Jul 4 20:43:12 1995 kbnes!kisimoto
+ - disable preferred setting for back-to-back
+ support. If enable, IoAssign... allocates
+ current enabled address space.
+ H003 Wed Jul 5 14:27:46 1995 kbnes!kisimoto
+ - initialize with FALSE
+ H004 Tue Sep 5 20:06:16 1995 kbnes!kisimoto
+ - PCI Fast Back-to-back transfer support
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#if defined(_R94A_) // H001
+#include "r94adef.h"
+#include "string.h"
+#endif // _R94A_
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+#if 0
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+#endif
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+// KSPIN_LOCK HalpPCIConfigLock; // H001
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+BOOLEAN HalpDoingCrashDump = FALSE; // H003
+ULONG HalpFoundUncapablePCIDevice = 0; // H004
+ULONG HalpPCINumberOfMappedGA = 0;
+ULONG HalpPCIBackToBackReg0Start = 0;
+ULONG HalpPCIBackToBackReg1Start = 0;
+ULONG HalpPCIBackToBackReg0Open = 1;
+ULONG HalpPCIBackToBackReg1Open = 1;
+ULONG HalpNumberOfPCIGA = 0;
+ULONG HalpPCIMemoryLimit = 0xffffffff;
+
+#define INIT_VALUE_OF_BACK_TO_BACK_ADDR 0x00000000
+#define INIT_VALUE_OF_BACK_TO_BACK_MASK 0xffffffff
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if defined(_R94A_) // H001
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+ULONG
+HalpGetNumberOfPCIGA(
+ IN ULONG NumberBuses
+ );
+VOID
+HalpSetBackToBackSpace(
+ IN PPCI_COMMON_CONFIG PciConfigRequired,
+ IN PPCI_COMMON_CONFIG PciConfigMapped,
+ IN PBUS_HANDLER BusHandler
+ );
+VOID
+HalpSetBackToBackRegister(
+ IN ULONG BaseAddress,
+ IN ULONG Length,
+ IN ULONG Register
+ );
+#endif // _R94A_
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+ULONG R94aDoTestPci = 0;
+ULONG R94aDoTestPciNec = 0;
+ULONG R94aDoOtherTest = 0;
+VOID
+HalpTestPciNec (
+ ULONG
+ );
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+ );
+VOID
+HalpOtherTestNec (
+ ULONG
+ );
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ PCI_REGISTRY_INFO tPCIRegInfo; // H001
+
+#if 0 // H001
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+// KeInitializeSpinLock (&HalpPCIConfigLock); // H001
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+#endif // 0
+
+#if defined(_R94A_) // H001
+
+ PCIRegInfo = &tPCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism=0x1; // HURRICANE PCI Config Type
+
+#if DBG
+ DbgPrint("PCI System Get Data:\n");
+ DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision );
+ DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision );
+ DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses );
+ DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism );
+#endif // DBG
+
+#endif // _R94A_
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+#if 0 // H001
+ do {
+#endif
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+#if 0 // H001
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+#endif
+
+ //
+ // H005
+ // Compute the number of PCI-GA device and
+ // initialize Fast Back-to-back register.
+ //
+
+ HalpNumberOfPCIGA = HalpGetNumberOfPCIGA(PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#if defined(_R94A_)
+ DbgPrint("HalpInitializePciBus: Call HalpTestPci(%x)\n",R94aDoTestPci);
+ HalpTestPci (R94aDoTestPci);
+ DbgPrint("HalpInitializePciBus: Call HalpTestPciNec(%x)\n",R94aDoTestPciNec);
+ HalpTestPciNec (R94aDoTestPciNec);
+ DbgPrint("HalpInitializePciBus: Call HalpOtherTest(%x)\n",R94aDoOtherTest);
+ HalpOtherTestNec (R94aDoOtherTest);
+#endif
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+#if defined(_R94A_)
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIInterruptVector;
+#else
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+#endif
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+#if defined(_R94A_) // H001
+ BusData->Config.Type1.Address = (PULONG)R94A_PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = R94A_PCI_TYPE1_DATA_PORT;
+#else
+ BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+#endif // _R94A_
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+ BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+ BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = 0x10;
+
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if ((j > 0x2 && j < 0xffff) || j > 0xffffff) { // H001
+ // IO port < 64KB | IO port > 16MB
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x3ffffff) { // H001
+ // Mem address < 64MB
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+#if 0
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ BusHandler->BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, PciData->VendorID, PciData->DeviceID,
+ PciData->RevisionID);
+
+
+ if (PciData->u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin);
+ }
+
+ if (PciData->u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine);
+ }
+
+ if (PciData->u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+
+ { ULONG k, j;
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+ DbgPrint("\n");
+ }
+#endif // DBG
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+#if DBG // H001
+ DbgPrint("SetPciData: PciData2->u.type0.InterruptLine:%x\n",PciData2->u.type0.InterruptLine);
+#endif
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ USHORT IdValue; // H001
+ ULONG OrigData; // H001
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ //
+ // resolve PCI master abort during we are looking for PCI device
+ // check to see if spcified slot is valid.
+ //
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+ OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
+ PCIConfigHandler.ConfigRead);
+
+ if (IdValue == 0xffff){
+
+ //
+ // This PCI slot has no card
+ // wait until ReceivedMasterAbort bit is set
+ //
+
+ while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
+ ;
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
+
+ //
+ // Clear memory address error registers.
+ //
+
+ {
+ LARGE_INTEGER registerLarge;
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ }
+
+ //
+ // Restore the PCIInterruptEnable register, and return no data
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+
+ return ;
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+
+#endif // _R94A_
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ USHORT IdValue; // H001
+ ULONG OrigData; // H001
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ //
+ // resolve PCI master abort during we are looking for PCI device
+ // check to see if spcified slot is valid.
+ //
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+ OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
+ PCIConfigHandler.ConfigRead);
+
+ if (IdValue == 0xffff){
+
+ //
+ // This PCI slot has no card
+ // wait until ReceivedMasterAbort bit is set
+ //
+
+ while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
+ ;
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
+
+ //
+ // Clear memory address error registers.
+ //
+
+ {
+ LARGE_INTEGER registerLarge;
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ }
+
+ //
+ // Restore the PCIInterruptEnable register, and return no data
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+
+ return ;
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+
+#endif // _R94A_
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+#if defined(_R94A_) // H001
+ if (Slot.u.bits.DeviceNumber < 3 ||
+ Slot.u.bits.DeviceNumber > 20) {
+ return FALSE;
+ }
+#else
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+#endif // _R94A_
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.DeviceNumber < 3) { // H001
+#if DBG
+ DbgPrint("HalpPCIConfig: Ignore Slot %x\n",Slot.u.bits.DeviceNumber);
+#endif
+ return;
+ }
+
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (PROFILE_LEVEL, Irql); // H001
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Disable PCI configuration space
+ //
+
+ PciCfg1.u.AsULONG = 0;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
+
+ //
+ // Release spinlock
+ //
+
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql); // H001
+ }
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
+ return sizeof (ULONG);
+}
+
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Initialize Cfg2Addr
+ //
+
+ PciCfg2Addr->u.AsUSHORT = 0;
+ PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
+ PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
+
+ //
+ // Synchronize with type2 config space - type2 config space
+ // remaps 4K of IO space, so we can not allow other I/Os to occur
+ // while using type2 config space.
+ //
+
+ HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ PciCfg2Cse.u.bits.Enable = TRUE;
+ PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
+ PciCfg2Cse.u.bits.Key = 0xff;
+
+ //
+ // Select bus & enable type 2 configuration space
+ //
+
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ //
+ // disable PCI configuration space
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
+
+ //
+ // Restore interrupts, release spinlock
+ //
+
+ HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
+ return sizeof(ULONG);
+}
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_COMMON_CONFIG PciData3; // H005
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+
+#if 0 // H001
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+#endif
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // H004
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory ((PPCI_COMMON_CONFIG)&PciData3, PciData, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+#if 0 // H002
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+#endif
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+#if DBG // H001
+ DbgPrint("HalpAssign: Port %x len %x align %x\n", length, length, m);
+#endif // DBG
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+#if 0 // H002
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+#endif
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+
+#if DBG // H001
+ DbgPrint("HalpAssign: Memory %x len %x align %x\n", length, length, m);
+#endif // DBG
+
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+#if DBG // H001
+ DbgPrint("Call IoAssignResources\n");
+#endif // DBG
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+#if DBG // H001
+ DbgPrint("HalpAssign assigned: Port %x\n", *BaseAddress[j]);
+#endif // DBG
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+#if DBG // H001
+ DbgPrint("HalpAssign assigned: Memory %x\n", *BaseAddress[j]);
+#endif // DBG
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+#if DBG // H001
+ DbgPrint("Set Assigned Resources\n");
+#endif // DBG
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+#if DBG // H001
+ DbgPrint("Read Common header to see write results\n");
+#endif // DBG
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // H004
+ // set memory space as back-to-back available
+ //
+
+ HalpSetBackToBackSpace(&PciData3, PciData2, BusHandler);
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+
+#if defined (_R94A_) // H001
+VOID
+HalpTestPciNec (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag && bus < 1; bus++) { /* R94A_ Support Only 1 */
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) { /* R94A_ Support Only 2 slots(include bridge) */
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, j);
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+ DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, 1);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+ PciData.u.type0.InterruptLine = 5; // For trial
+ DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("We got the bridge\n");
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+ DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+ DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+
+
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+)
+{
+ ULONG i, Lines, pchar;
+
+ DbgPrint("----- I/O Data. (%d)byts.\n", Length);
+
+ for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
+ DbgPrint("%08x: ", Lines * 16);
+ for (i = 0; i < 4; pchar += 4, i++) {
+ if (pchar >= Length)
+ break;
+ DbgPrint("%08x ", *Buffer++);
+ }
+ DbgPrint("\n");
+ }
+}
+
+VOID
+HalpOtherTestNec (
+ IN ULONG doOtherTest
+)
+{
+ if (!doOtherTest)
+ return;
+
+
+ DbgPrint("\n\n===== Additional Testing...\n");
+ {
+ CM_EISA_SLOT_INFORMATION EisaSlotInfo;
+ PCM_EISA_SLOT_INFORMATION EisaBuffer;
+ PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo;
+ ULONG slot, funcs, Length;
+
+ #define MAX_EISA_SLOT 4
+
+ DbgPrint("----- Read Eisa Configration:\n");
+ for (slot = 0; slot < MAX_EISA_SLOT; slot++) {
+ Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo));
+ if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) {
+
+ //
+ // The data is messed up since this should never occur
+ //
+
+ break;
+ }
+ Length = sizeof(CM_EISA_SLOT_INFORMATION) +
+ (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions);
+ EisaBuffer = ExAllocatePool(NonPagedPool, Length);
+ HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length);
+ // Print all Eisa Data
+
+ EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION)
+ ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION));
+
+ DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot);
+ DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n",
+ EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags,
+ EisaBuffer->MajorRevision, EisaBuffer->MinorRevision);
+ DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n",
+ EisaBuffer->Checksum,
+ EisaBuffer->NumberFunctions,
+ EisaBuffer->FunctionInformation,
+ EisaBuffer->CompressedId);
+ for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) {
+ DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n",
+ EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1,
+ EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision,
+ EisaFunctionInfo->MajorRevision);
+
+ // EisaFunctionInfo->Selections[26];
+ // EisaFunctionInfo->FunctionFlags;
+ // EisaFunctionInfo->TypeString[80];
+ // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9];
+ // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7];
+ // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4];
+ // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20];
+ // UCHAR EisaFunctionInfo->InitializationData[60];
+ EisaFunctionInfo++;
+ }
+
+ }
+ }
+ DbgBreakPoint ();
+ {
+ #define MEMORY_SPACE 0
+ #define IO_SPACE 1
+ PHYSICAL_ADDRESS cardAddress;
+ ULONG addressSpace = IO_SPACE;
+ PHYSICAL_ADDRESS PhysAddr;
+
+ PhysAddr.LowPart = 0;
+ PhysAddr.HighPart = 0;
+
+
+
+ DbgPrint("----- Translate Internal Bus Address(I/O): ");
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Internal Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+ }
+ DbgBreakPoint ();
+
+ {
+ KAFFINITY affinity;
+ KIRQL Irql;
+ ULONG Vec;
+
+ DbgPrint("----- GetInterruptVector internal\n");
+ Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Eisa\n");
+ Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Isa\n");
+ Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector PCI\n");
+ Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ }
+ DbgBreakPoint ();
+}
+
+#endif // _R94A_
+#endif // DBG
+
+VOID
+HalpSetBackToBackSpace(
+ IN PPCI_COMMON_CONFIG PciConfigRequired,
+ IN PPCI_COMMON_CONFIG PciConfigMapped,
+ IN PBUS_HANDLER BusHandler
+ )
+/*++
+
+Routine Description:
+
+ This function sets memory space of PCI device to Fast Back-to-back register.
+
+Arguments:
+
+ PciConfigRequired - Supplies the description of the memory space which
+ device required.
+ PciConfigMapped - Supplies the description of the memory space which
+ should be mapped to back-to-back space.
+ BusHandler - Supplies the pointer to Bushandler.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG NoBaseAddress;
+ ULONG BaseAddress, LowerAddress;
+ ULONG CurrentAddress;
+ ULONG FoundMemoryAddress;
+ ULONG i, j, Length;
+
+#if DBG
+ DbgPrint(" check PCI-device!\n");
+ DbgPrint(" - VendorID ................ %04x\n", PciConfigMapped->VendorID);
+ DbgPrint(" - DeviceID ................ %04x\n", PciConfigMapped->DeviceID);
+ DbgPrint(" - back-to-back capable? ... %s\n", (PciConfigMapped->Status & 0x80) ? "o" : "x");
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00 && PciConfigMapped->SubClass == 0x01)){
+ DbgPrint(" - Is this GA device? ...... o\n");
+ } else {
+ DbgPrint(" - Is this GA device? ...... x\n");
+ }
+#endif
+
+ KiAcquireSpinLock(&HalpPCIBackToBackLock);
+
+ //
+ // calulate memory region of this device.
+ //
+
+ switch (PCI_CONFIG_TYPE(PciConfigMapped)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES;
+ break;
+ default:
+ // never come here.
+ // (already except by HalpAssignPCISlotResources)
+ return;
+ }
+
+ Length = 0;
+ BaseAddress = 0xffffffff;
+ LowerAddress = 0xffffffff;
+ FoundMemoryAddress = 0;
+
+ //
+ // get base and limit address
+ //
+
+ for (i = 0; i < NoBaseAddress; i++) {
+ CurrentAddress = PciConfigMapped->u.type0.BaseAddresses[i];
+ if (!(CurrentAddress & PCI_ADDRESS_IO_SPACE)
+ && ((CurrentAddress & PCI_ADDRESS_MEMORY_TYPE_MASK) != 0x2)) {
+
+ //
+ // this is memory space and not need to map below 1M
+ //
+
+ CurrentAddress = CurrentAddress & 0xfffffff0;
+ if (CurrentAddress) {
+ FoundMemoryAddress = 1;
+ if (LowerAddress > CurrentAddress)
+ LowerAddress = CurrentAddress;
+ // scan for first set bit, that's the length & alignment
+ j = 1 << 4;
+ while (!(PciConfigRequired->u.type0.BaseAddresses[i] & j) && j)
+ j <<= 1;
+#if DBG
+ DbgPrint(" - [%d]MemoryAddress ........ 0x%08x\n", i, CurrentAddress);
+ DbgPrint(" - [%d]Length ............... 0x%08x\n", i, j);
+#endif
+ if (Length < j){
+ BaseAddress = CurrentAddress;
+ Length = j;
+ }
+ }
+ }
+ }
+
+#if DBG
+ DbgPrint(" - LowerAddress ............ 0x%08x\n", LowerAddress);
+ DbgPrint(" - BaseAddress ............. 0x%08x\n", BaseAddress);
+ DbgPrint(" - Length .................. 0x%08x\n", Length);
+#endif
+
+ //
+ // If this device has memory space, then change memory limit
+ // value used be allocation for PCI memory space to
+ // 'LowerAddress - 1' of this device, otherwise release spinlock
+ // and return.
+ //
+
+ if (FoundMemoryAddress) {
+ HalpPCIMemoryLimit = LowerAddress - 1;
+ } else {
+ goto NotSetBackToBack;
+ }
+
+ //
+ // We do not support the PCI devices which connected under
+ // PCI-PCI bridge.
+ //
+
+ if (BusHandler->BusNumber == 0) {
+
+ if (PciConfigMapped->Status & 0x80) {
+
+ //
+ // This device is back-to-back capable.
+ // We can map the memory space of this device as
+ // back-to-back available.
+ // Set flag to indicate setting started.
+ //
+
+ if (!HalpPCIBackToBackReg0Start) {
+ HalpPCIBackToBackReg0Start = 1;
+
+ } else if (HalpPCIBackToBackReg0Start && !HalpPCIBackToBackReg0Open) {
+ HalpPCIBackToBackReg1Start = 1;
+
+ }
+
+ //
+ // BUGBUG: Some pci drivers assign its memory space by itself.
+ // This means that we can not control the memory address of
+ // such device by MemoryLimit value. So, we can not enable the
+ // following codes now.
+ // N.B. following code does not finished.
+ //
+
+// if (!HalpFoundUncapablePCIDevice) {
+//
+// //
+// // Uncapable device not mapped yet, so we can expand
+// // back-to-back space.
+// // We expand back-to-back space until uncapable device
+// // is found.
+// //
+//
+// if (back-to-back reg0 == initialize value){
+// HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+// } else {
+// back-to-back reg0 =+ add this memory range;
+// MemoryLimit = the BaseAddress of this device;
+// }
+//
+// if (PciConfigMapped->BaseClass == 0x03
+// || (PciConfigMapped->BaseClass == 0x00
+// && PciConfigMapped->SubClass == 0x01)) {
+// HalpPCINumberOfMappedGA++;
+// }
+//
+// } else {
+
+ if (HalpNumberOfPCIGA > 1) {
+
+ //
+ // There are some PCI-GA cards.
+ // If this is PCI-GA, then set to back-to-back,
+ // else we do not map.
+ //
+
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00
+ && PciConfigMapped->SubClass == 0x01)) {
+
+ switch (HalpPCINumberOfMappedGA) {
+
+ case 0:
+
+ //
+ // We need set PCI-GA to both back-to-back space.
+ // The control reach here, it indicates PCI-GA
+ // not mapped to back-to-back space yet.
+ //
+
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ HalpPCIBackToBackReg0Open = 0;
+ break;
+
+ case 1:
+
+ //
+ // Control is transfered to this routine when one PCI-GA
+ // is already mapped. This means that reg0 had already used.
+ // We use reg1.
+ //
+
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+
+ HalpPCINumberOfMappedGA++;
+ }
+
+ } else {
+
+ //
+ // There is only one-card as PCI-GA.
+ // We need set PCI-GA to back-to-back.
+ // If this is GA and reg0 is opened, then use reg0.
+ // If this is GA and reg0 is closeed, then use reg1.
+ //
+
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00
+ && PciConfigMapped->SubClass == 0x01)) {
+
+ if (HalpPCIBackToBackReg0Open) {
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ HalpPCIBackToBackReg0Open = 0;
+
+ } else {
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+
+ HalpPCINumberOfMappedGA++;
+
+ } else {
+
+ //
+ // We can set only if reg0 or reg1 is not used.
+ //
+
+ if (HalpPCIBackToBackReg0Open) {
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ HalpPCIBackToBackReg0Open = 0;
+
+ } else if (HalpPCIBackToBackReg1Open){
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+ }
+ }
+// }
+
+ } else {
+
+ //
+ // This is back-to-back uncapable.
+ //
+
+ HalpFoundUncapablePCIDevice = 1;
+
+ //
+ // if device is back-to-back uncapable¡¤map only GA.
+ //
+
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00
+ && PciConfigMapped->SubClass == 0x01)) {
+
+ //
+ // In case of two or more cards are connected, the
+ // process is depend on the number of PCI-GA which
+ // already mapped.
+ // But we do not need to map 3rd PCI-GA or more.
+ //
+
+ if (HalpNumberOfPCIGA > 1) {
+
+ switch (HalpPCINumberOfMappedGA) {
+
+ case 0:
+
+ //
+ // Re-nitialize all values to void already settings,
+ // and use reg0
+ //
+
+ HalpPCIBackToBackReg0Start = 1;
+ HalpPCIBackToBackReg1Start = 0;
+ HalpPCIBackToBackReg0Open = 1;
+ HalpPCIBackToBackReg1Open = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ break;
+
+ case 1:
+
+ //
+ // Control is transfered to this routine when one PCI-GA
+ // is already mapped. This means that reg0 had already used.
+ // We use reg1.
+ //
+ // N.B. We do not know reg0 is opened or closed, so close
+ // reg0 here.
+ // (ex) 1st mapped ... capable = 1, not GA
+ // 2nd mapped ... capable = 0, GA
+ //
+
+ HalpPCIBackToBackReg0Open = 0;
+ HalpPCIBackToBackReg1Start = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+
+ }
+
+ } else {
+
+ //
+ // There is only one-card as PCI-GA.
+ // If back-to-back reg0 not being useed, use reg0,
+ // else close the space of reg0 and use reg1.
+ // (Also when reg0 is closed, use reg1)
+ //
+
+ if (!HalpPCIBackToBackReg0Start) {
+ HalpPCIBackToBackReg0Start = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+
+ } else {
+ HalpPCIBackToBackReg0Open = 0;
+ HalpPCIBackToBackReg1Start = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+
+ }
+ }
+ }
+
+ //
+ // if being to set to back-to-back register, we have to close.
+ //
+
+ if (HalpPCIBackToBackReg0Start && HalpPCIBackToBackReg0Open) {
+ HalpPCIBackToBackReg0Open = 0;
+
+ } else if (HalpPCIBackToBackReg1Start && HalpPCIBackToBackReg1Open) {
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+
+ }
+
+ }
+
+NotSetBackToBack:
+ KiReleaseSpinLock(&HalpPCIBackToBackLock);
+
+}
+
+VOID
+HalpSetBackToBackRegister(
+ IN ULONG BaseAddress,
+ IN ULONG Length,
+ IN ULONG Register
+ )
+/*++
+
+Routine Description:
+
+ This function sets memory space of PCI device to Fast Back-to-back register.
+
+Arguments:
+
+ BaseAddress - Supplies the address which to be mapped with back-to-back.
+ Length - Supplies the length which to be mapped with back-to-back.
+ Register - Supplies the back-to-back register number.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Mask;
+
+ //
+ // make mask value
+ //
+
+ Mask = ~(Length - 1);
+
+ //
+ // set to back-to-back register
+ //
+
+#if DBG
+ DbgPrint(" set back-to-back register.\n");
+ DbgPrint(" - Register ................ %d\n", Register);
+ DbgPrint(" - Address ................. 0x%08x\n", BaseAddress);
+ DbgPrint(" - Mask .................... 0x%08x\n", Mask);
+#endif
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Address,
+ BaseAddress
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Mask,
+ Mask
+ );
+
+}
+
+ULONG
+HalpGetNumberOfPCIGA(
+ IN ULONG NumberBuses
+ )
+/*++
+
+Routine Description:
+
+ This function determines the number of PCI-GAs.
+ And initialize Fast Back-to-back register.
+
+Arguments:
+
+ NumberBuses - Supplies the number of the PCI-buses.
+
+Return Value:
+
+ number of PCI-GA.
+
+--*/
+
+{
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Bus;
+ ULONG Slot;
+ ULONG Function;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG Count;
+ ULONG Register;
+ USHORT commandValue;
+
+ Count = 0;
+ PciData = (PPCI_COMMON_CONFIG)&iBuffer;
+
+ //
+ // BUGBUG: Fast Back-to-back transaction can be used
+ // only bus number zero on this version.
+ // PCI devices connected on bus number 1 or more will
+ // be available with back-to-back on future.
+ //
+
+ NumberBuses = 1;
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (Bus = 0; Bus < NumberBuses; Bus++) {
+ BusHandler = HalpHandlerForBus (PCIBus, Bus);
+
+ for (Slot = 0; Slot < PCI_MAX_DEVICES; Slot++) {
+ SlotNumber.u.bits.DeviceNumber = Slot;
+
+ for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
+ SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->BaseClass == 0x03
+ || (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01)){
+
+ //
+ // This is Graphics Adapter. Inclement count.
+ //
+
+ Count++;
+ }
+
+ } // next PCI function
+
+ } // next PCI slot
+
+ } // next PCI bus
+
+#if DBG
+ DbgPrint(" number of PCI-GA.\n");
+ DbgPrint(" - number of PCI-GA ........ %d\n", Count);
+#endif
+
+ //
+ // Initialize Fast Back-to-back register.
+ //
+
+ for (Register = 0; Register < 2; Register++) {
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Address,
+ INIT_VALUE_OF_BACK_TO_BACK_ADDR
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Mask,
+ INIT_VALUE_OF_BACK_TO_BACK_MASK
+ );
+ }
+
+ commandValue = READ_REGISTER_USHORT(&DMA_CONTROL->PCICommand);
+ WRITE_REGISTER_USHORT(&DMA_CONTROL->PCICommand, (commandValue & ~0x0200));
+
+ return Count;
+
+}
diff --git a/private/ntos/nthals/halr94a/mips/pciint.c b/private/ntos/nthals/halr94a/mips/pciint.c
new file mode 100644
index 000000000..06571660d
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/pciint.c
@@ -0,0 +1,376 @@
+// #pragma comment(exestr, "@(#) pciint.c 1.1 95/09/28 15:46:29 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Jun 30 02:58:57 1995 kbnes!kisimoto
+ - Merge build 1057
+ H002 Tue Sep 5 20:21:24 1995 kbnes!kisimoto
+ - PCI Fast Back-to-back transfer support
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG PciIsaIrq;
+ULONG HalpEisaELCR;
+BOOLEAN HalpDoingCrashDump;
+extern ULONG HalpPCIMemoryLimit; // H002
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+#if defined(_R94A_) // H001
+ULONG R94A_PCIPinToLineTable[][4] = {
+ { 0xF, 0xF, 0xF, 0xF }, // Slot 0(Hurricane)No InterruptPin
+ { 0xF, 0xF, 0xF, 0xF }, // Slot 1(Typhoon) No InterruptPin assign
+ { 0xF, 0xF, 0xF, 0xF }, // Slot 2(PCEB) No InterruptPin assign
+ { 0x3, 0x3, 0x3, 0x3 }, // Slot 3 : INT A B C D
+ { 0x2, 0x2, 0x2, 0x2 }, // Slot 4 : INT A B C D
+ { 0x1, 0x1, 0x1, 0x1 } // Slot 5 : INT A B C D
+};
+#endif // _R94A_
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+#ifndef MCA
+ Isa, 0,
+#else
+ MicroChannel, 0,
+#endif
+ BusInterruptLevel ^ IRQXOR,
+ 0,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+ On a DBG build we adjust InterruptLine just to ensure driver's
+ don't connect to it without translating it on the PCI bus.
+
+--*/
+{
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ PciData->u.type0.InterruptLine =
+ (UCHAR)R94A_PCIPinToLineTable[SlotNumber.u.bits.DeviceNumber][PciData->u.type0.InterruptPin];
+
+#else
+
+ //
+ // Set vector as a level vector. (note: this code assumes the
+ // irq is static and does not move).
+ //
+
+ if (PciData->u.type0.InterruptLine >= 1 &&
+ PciData->u.type0.InterruptLine <= 15) {
+
+ //
+ // If this bit was on the in the PIC ELCR register,
+ // then mark it in PciIsaIrq. (for use in hal.dll,
+ // such that we can assume the interrupt controller
+ // has been properly marked as a level interrupt for
+ // this IRQ. Other hals probabily don't care.)
+ //
+
+ PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine);
+ }
+
+ //
+ // On a PC there's no Slot/Pin/Line mapping which needs to
+ // be done.
+ //
+
+ PciData->u.type0.InterruptLine ^= IRQXOR;
+
+#endif // _R94A_
+
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ PciNewData->u.type0.InterruptLine =
+ (UCHAR)R94A_PCIPinToLineTable[SlotNumber.u.bits.DeviceNumber][PciOldData->u.type0.InterruptPin];
+
+#else
+
+ PciNewData->u.type0.InterruptLine ^= IRQXOR;
+
+#endif // _R94A_
+
+#if DBG
+ if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine ||
+ PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) {
+ DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n");
+ // DbgBreakPoint ();
+ }
+#endif
+}
+
+#if !defined(SUBCLASSPCI)
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+#if defined(_R94A_) // H001
+ KeRaiseIrql(PROFILE_LEVEL, Irql);
+#else
+ *Irql = KfRaiseIrql (HIGH_LEVEL);
+#endif
+ KiAcquireSpinLock (SpinLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (SpinLock);
+#if defined(_R94A_) // H001
+ KeLowerIrql (Irql);
+#else
+ KfLowerIrql (Irql);
+#endif // _R94A_
+ }
+}
+
+#endif
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // H002
+ // change Memory.Limit value to BaseAddress which last mapped.
+ //
+
+#if DBG
+ DbgPrint(" change Memory.Limit!\n");
+ DbgPrint(" - Before limit ............ 0x%08x\n",
+ ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart);
+#endif
+
+ ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart = HalpPCIMemoryLimit;
+
+#if DBG
+ DbgPrint(" - After limit ............. 0x%08x\n",
+ ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart);
+#endif
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+#if defined(_R94A_) // H001
+ PPCIPBUSDATA BusData;
+#endif
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+#if defined(_R94A_) // H001
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+#else
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == IRQXOR) {
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+
+#endif // _R94A_
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halr94a/mips/pcip.h b/private/ntos/nthals/halr94a/mips/pcip.h
new file mode 100644
index 000000000..8e6a361a8
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/pcip.h
@@ -0,0 +1,200 @@
+// #pragma comment(exestr, "@(#) pcip.h 1.1 95/09/28 15:46:56 nec")
+/*++
+
+ Modification History
+
+ H001 Fri Jun 30 02:51:55 1995 kbnes!kisimoto
+ - add definition
+
+--*/
+
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+#if defined(_R94A_) // H001
+#define R94A_PCI_TYPE1_ADDR_PORT 0xFFFFc518
+#define R94A_PCI_TYPE1_DATA_PORT 0xFFFFc520
+#endif // _R94A_
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halr94a/mips/pcisup.c b/private/ntos/nthals/halr94a/mips/pcisup.c
new file mode 100644
index 000000000..d46cc00e4
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/pcisup.c
@@ -0,0 +1,632 @@
+// #pragma comment(exestr, "@(#) r94apcisup.c 1.1 95/09/28 18:37:11 nec")
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r94apisup.c
+
+Abstract:
+
+ The module provides the PCI bus support for R94A systems.
+
+Author:
+
+
+Revision History:
+
+ L0001 1994.9.20 kbnes!kuriyama(A)
+ -New module for R94A R4400 system
+ -add HalpAllocaltePCIAdapter()
+
+ H0001 Tue Sep 20 22:58:03 JST 1994 kbnes!kishimoto
+ -add HalpEnablePCIInterrupt()
+ -add HalpDisablePCIInterrupt()
+ -add HalpPCIDispatch()
+ -add HalpPCIFatalError()
+
+ H0002 Tue Oct 4 12:47:58 JST 1994 kbnes!kishimoto
+ -modify HalpPCIFatalError()
+ display the appropriate PCI errors
+
+ L0002 1994.10.13 kbnes!kuriyama(A)
+ -add HalpAllocaltePCIAdapter()
+ -add AdapterBaseVa set routine
+
+ H0003 Fri Oct 14 14:54:40 JST 1994 kbnes!kishimoto
+ -chg use READ_REGISTER_DWORD to read 64-bit I/O register
+
+ H0003 Mon Oct 17 14:36:57 JST 1994 kbnes!kishimoto
+ -chg Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ XXX_EISA_PCI_XXX rename to XXX_EISA_XXX
+ MAXIMUM_PCI_SLOT rename to R94A_PCI_SLOT
+
+ H0004 Wed Oct 19 13:24:51 JST 1994 kbnes!kishimoto
+ -chg HalpPCIDispatch()
+ The PCI-error check change up the order.
+
+ H0005 Wed Oct 19 20:17:09 JST 1994 kbnes!kishimoto
+ -add substitute READ_REGISTER_BUFFER_UCHAR for
+ READ_REGISTER_DWORD because of storm alpha-
+ version cannot 64-bit access.
+
+ L0006 Wed Oct 19 22:01:27 JST 1994 kbnes!kuriyama(A)
+ -chg HalpAllocatePCIAdapter()
+ del useChannel
+ del channelNumber
+ del controllerNumber
+ del eisaSystem
+ chg AdapterBaseVa value
+
+ H0006 Tue Nov 22 22:10:00 1994 kbnes!kishimoto
+ -del delete _R94ABBM32_
+ The limitation of 32bit bus-access is only applied
+ under PCI-bus. I make a wrong application.
+
+ H0007 Fri Jul 21 18:02:55 1995 kbnes!kishimoto
+ -merge source with J94C
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+#if defined(_R94A_)
+
+#include <stdio.h>
+
+/* start H0000 */
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+VOID
+HalpPCIFatalError(
+ STORM_PCI_INTRRUPT_STATUS InterruptStatus
+ );
+
+/* end H0000 */
+
+// start L0001
+PADAPTER_OBJECT
+HalpAllocatePCIAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an PCI adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ UCHAR adapterMode;
+
+ //
+ // All PCI Cards is Master card.
+ //
+
+ if (DeviceDescriptor->InterfaceType == PCIBus &&
+ DeviceDescriptor->Master) {
+
+ } else {
+
+ return(NULL);
+ }
+
+
+/* start L0002 */
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ adapterBaseVa = ~0; /* L0006 */
+/* end L0002 */
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ //
+ // If the channel is not used then indicate the this is an PCI bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+
+}
+// end L0001
+
+/* start H0001 */
+VOID
+HalpEnablePCIInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // enable specified PCI bus interrupt.
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable
+ );
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable,
+ (ULONG)( i | 1 << (Vector - PCI_VECTORS))
+ );
+
+ return;
+
+}
+
+VOID
+HalpDisablePCIInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // disable specified PCI bus interrupt.
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable
+ );
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable,
+ (ULONG)( i & ~(1 << (Vector - PCI_VECTORS)))
+ );
+
+ return;
+
+}
+
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the PCI device interrupts. Its function is to call the third
+ level interrupt dispatch routine and acknowledge the interrupt at the PCI
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_DEVICE_LEVEL, EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the third level routine.
+
+--*/
+
+{
+ STORM_PCI_INTRRUPT_STATUS InterruptStatus;
+ PKINTERRUPT interruptObject;
+ PULONG dispatchCode;
+ BOOLEAN returnValue;
+ LONG Index;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ *((PULONG) &InterruptStatus) = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptStatus);
+
+ //
+ // BUGBUG
+ //
+
+ if (*((PULONG)&InterruptStatus) == 0) {
+
+ //
+ // There is not PCI interrupt.
+ //
+
+ return(FALSE);
+
+ }
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ // R94A has the following PCI error interrupts.
+ // Target abort interrupt
+ // Master abort interrupt
+ // Retry overflow interrupt
+ // SERR interrupt
+ // PERR interrupt
+ //
+
+ if (InterruptStatus.Perr == 1 ||
+ InterruptStatus.Serr == 1 ||
+ InterruptStatus.RetryOverflow == 1 ||
+ InterruptStatus.MasterAbort == 1 ||
+ InterruptStatus.TargetAbort == 1) {
+
+ //
+ // Display the appropriate PCI errors and bugcheck to dump the machine state.
+ //
+
+ HalpPCIFatalError(InterruptStatus);
+ KeBugCheck(DATA_BUS_ERROR);
+
+ //
+ // The following code is never executed.
+ //
+
+ return(FALSE);
+ }
+
+ //
+ // if INT[A.B.C.D] is active, then call the appropriate PCI drivers.
+ //
+
+ if ((*((PULONG)&InterruptStatus) & 0xf) != 0x0) {
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+ // N.B. R94A PCI interrupts flow :
+ //
+ // system slot1 slot2 slot3
+ // INT A <----------+ + +
+ // INT B <------+ + + +
+ // INT C <---+ | + + +
+ // Reserved | | + + +
+ // | +-----------+ |
+ // +----------------------+
+ //
+ //
+ // PCI Interrupt Status Register Bit Definitions are:
+ //
+ // [31:09] Reserved
+ // [08] Target abort interrupt status
+ // [07] Master abort interrupt status
+ // [06] Retry overflow interrupt status
+ // [05] SERR interrupt status
+ // [04] PERR interrupt status
+ // [03] INTA interrupt status
+ // [02] INTB interrupt status
+ // [01] INTC interrupt status
+ // [00] INTD interrupt status
+ //
+
+ for (Index = 3; Index > (3 - R94A_PCI_SLOT); Index--) {
+
+ //
+ // Check if the PCI interrupt occur.
+ //
+
+ if (((*((PULONG)&InterruptStatus) & 0xf) & ((ULONG)1 << Index)) != 0x0) {
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCI_VECTORS + Index]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+ }
+
+ }
+
+ }
+
+ return(returnValue);
+
+}
+
+
+VOID
+HalpPCIFatalError(
+ STORM_PCI_INTRRUPT_STATUS InterruptStatus
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an PCI fatal interrupt.
+ This function displays appropriate PCI error information.
+
+Arguments:
+
+ InterruptStatus - PCI Interrupt Status value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR Buffer[100];
+ UCHAR registerChar;
+ ULONG registerLong;
+ LARGE_INTEGER registerLarge;
+ LARGE_INTEGER InvalidAddressValue;
+ LARGE_INTEGER EccDiagnosticValue;
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // H0007
+
+ HalDisplayString("\nFatal system error occured\n\n");
+
+ //
+ // Display the following register value.
+ //
+ // register name address
+ //
+ // Remode Failed Address 0x80000010 32bit
+ // Memory Failed Address 0x80000018 32bit
+ // Processor Invalid Address 0x80000020 33bit
+ // ECC Diagnostic 0x800001c8 64bit
+ // PCI Status 0x80000606 16bit
+ // PCI Master Retry Timer 0x80000668 32bit
+ //
+
+ //
+ // Display the PCI fatal error information
+ //
+
+ if (InterruptStatus.Perr){
+ HalDisplayString("PCI: Data parity error\n");
+ }
+
+ if (InterruptStatus.Serr){
+ HalDisplayString("PCI: Address parity error\n");
+ }
+
+ if (InterruptStatus.RetryOverflow){
+ HalDisplayString("PCI: Retry overflow\n");
+ }
+
+ if (InterruptStatus.MasterAbort){
+ HalDisplayString("PCI: Master abort\n");
+ }
+
+ if (InterruptStatus.TargetAbort){
+ HalDisplayString("PCI: Target abort\n");
+ }
+
+ // ! start
+ // test test test : dump the hardware registers of R94A
+ // <cording memo>
+ // dump R94A all hardware-registers to buffer instead of display console
+ // registers that is only important for analasis dump are display to console
+ //
+ // registers which display to console are:
+ // 0x80000000 Configuration
+ // 0x80000010 RemoteFailedAddress
+ // 0x80000018 MemoryFailedAddress
+ // 0x80000020 InvalidAddress
+ // 0x80000078 NmiSource
+ // 0x800000f8 InterruptEnable
+ // 0x80000188 Errortype
+ // 0x800001c8 EccDiagnostic
+ // 0x80000530 PCIInterruptEnable
+ // 0x80000538 PCIInterruptStatus
+ // 0x80000606 PCIStatus
+ // 0x800005bc TyphoonErrorStatus
+ // 0x80000668 PCIMasterRetryTimer
+ //
+ // 0x8000f000 I/O Device Interrupt Enable
+ //
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &InvalidAddressValue);
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, &EccDiagnosticValue);
+
+ sprintf(Buffer,
+ "Configuration : %08x RemoteFailedAddress : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->Configuration.Long),
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->RemoteFailedAddress.Long));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "MemoryFailedAddress : %08x InvalidAddress :%01x%08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long),
+ (InvalidAddressValue.HighPart & 0x1), InvalidAddressValue.LowPart);
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "NmiSource : %08x InterruptEnable : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->NmiSource.Long),
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "Errortype : %08x EccDiagnostic(High) : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->NmiSource.Long),
+ EccDiagnosticValue.HighPart);
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "EccDiagnostic(Low) : %08x PCIInterruptEnable : %08x\n",
+ EccDiagnosticValue.LowPart,
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "PCIInterruptStatus : %08x PCIStatus : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptStatus.Long),
+ READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "TyphoonErrorStatus : %08x PCIMasterRetryTimer : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->TyphoonErrorStatus),
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIMasterRetryTimer));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ HalpGetStatusRegister(&registerLong);
+
+ sprintf(Buffer,
+ "I/O DevIntEnable : %08x (CPU)StatusRegister : %08x\n",
+ READ_REGISTER_ULONG((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE),
+ registerLong);
+
+ HalDisplayString((UCHAR *)Buffer);
+
+
+ //
+ // ! end
+ //
+
+// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->RemoteFailedAddress.Long);
+// sprintf ((UCHAR *)Buffer, "RemodeFailedAddress = 0x%08x\n", registerLong);
+// HalDisplayString((UCHAR *)Buffer);
+
+// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long);
+// sprintf ((UCHAR *)Buffer, "MemoryFailedAddress = 0x%08x\n", registerLong);
+// HalDisplayString((UCHAR *)Buffer);
+
+ //
+ // memo
+ //
+ // (./ntos/inc/mips.h)
+ // #define READ_REGISTER_BUFFER_UCHAR(x, y, z) {
+ // PUCHAR registerBuffer = x;
+ // PUCHAR readBuffer = y;
+ // ULONG readCount;
+ // for (readCount = z; readCount--; readBuffer++, registerBuffer++) {
+ // *readBuffer = *(volatile UCHAR * const)(registerBuffer);
+ // }
+ // }
+ //
+
+/* start H0003 */
+
+// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+// sprintf ((UCHAR *)Buffer, "InvalidAddress =0x%01x%08x\n", registerLarge.HighPart & 0x1, registerLarge.LowPart);
+// HalDisplayString((UCHAR *)Buffer);
+
+// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, &registerLarge);
+// sprintf ((UCHAR *)Buffer, "EccDiagnostic(High) = 0x%08x\n", registerLarge.HighPart);
+// HalDisplayString((UCHAR *)Buffer);
+
+// sprintf ((UCHAR *)Buffer, "EccDiagnostic(Low) = 0x%08x\n", registerLarge.LowPart);
+// HalDisplayString((UCHAR *)Buffer);
+
+/* end H0003 */
+
+// registerChar = READ_REGISTER_UCHAR(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus);
+// sprintf ((UCHAR *)Buffer, "PCIStatus = 0x%08x\n", registerChar);
+// HalDisplayString((UCHAR *)Buffer);
+
+// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIMasterRetryTimer);
+// sprintf ((UCHAR *)Buffer, "PCIMasterRetryTimer = 0x%08x\n", registerLong);
+// HalDisplayString((UCHAR *)Buffer);
+
+ return;
+
+}
+
+/* end H0001 */
+#endif // _R94A_
diff --git a/private/ntos/nthals/halr94a/mips/r94adbg.c b/private/ntos/nthals/halr94a/mips/r94adbg.c
new file mode 100644
index 000000000..e48290c04
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94adbg.c
@@ -0,0 +1,157 @@
+// #pragma comment(exestr, "@(#) r94adbg.c 1.1 95/09/28 15:47:19 nec")
+/*++
+
+Copyright (c) 1994 KOBE NEC Software
+
+Module Name:
+
+ r94adbg.c
+
+Abstract:
+
+ The module provides the debug support functions for R94A systems.
+
+Author:
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - add HalDisplayLED()
+ new function.
+ - add HalpOutputCharacterToLED()
+ new function.
+
+ H001 Mon Oct 17 13:01:53 JST 1994 kbnes!kishimoto
+ - add HalR94aDebugPrint()
+ new function.
+ - chg HalpDisplayLED()
+ rename from HalDisplayLED()
+
+ H002 Thu Oct 20 19:42:03 JST 1994 kbnes!kishimoto
+ - add R94aBbmLEDMapped used at KdPortInitialize()(jxport.c)
+ for debug use only
+
+ H003 Fri Oct 21 10:18:01 JST 1994 kbnes!kishimoto
+ - add specify the output device.
+
+ M004 Fri Jan 06 10:49:29 JST 1995 kbnes!kuriyama
+ - add HalpPrintMdl()
+
+ H005 Sat Mar 18 16:23:05 JST 1995 kbnes!kishimoto
+ - always include "halp.h"
+
+ S006 kuriyama@oa2.kb.nec.co.jp Mon Apr 03 10:49:48 JST 1995
+ - delete PrintMdl routine (if defined _PRINT_MDL_)
+
+--*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "halp.h" // H005
+
+#define R94A_LED 0
+#define R94A_DBG 1
+#define R94A_CON 2
+
+ULONG HalpR94aDebugOutput = R94A_DBG ; // start H003
+ULONG R94aDebugLevel = 1;
+
+VOID
+HalR94aDebugPrint(
+ ULONG DebugLevel,
+ PUCHAR LedCharactor,
+ PUCHAR Message,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This function is used to display debug information.
+
+ Usage :
+ HalR94aDebugPrint(
+ (ULONG) 3,
+ "1234",
+ "Dbg : Current file is %s [%d]\n",
+ __FILE__,
+ __LINE__
+ );
+
+Arguments:
+
+ DebugLevel - Debug level for output.
+ If DebugLevel less than R94aDebugLevel, not display.
+
+ LedCharactor - Display charactor for LED.
+
+ Message - Display format for console or debug-teminal.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ va_list argp;
+ ULONG Index;
+ CHAR Buffer[100];
+
+ if (DebugLevel >= R94aDebugLevel) {
+
+ va_start(argp, Message);
+ vsprintf(Buffer, Message, argp);
+
+ if (HalpR94aDebugOutput & (1 << R94A_DBG)) { // H003
+
+ DbgPrint(Buffer);
+
+ }
+
+ if (HalpR94aDebugOutput & (1 << R94A_CON)) {
+
+ HalDisplayString(Buffer);
+
+ }
+
+ va_end(argp);
+ }
+
+ return;
+}
+/* end H001 */
+
+/* M004 +++ */
+#if defined(_PRINT_MDL_) //S006
+VOID
+HalpPrintMdl(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+
+
+ //
+ // Get the lower bound of the free physical memory and the
+ // number of physical pages by walking the memory descriptor lists.
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ MemoryDescriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType);
+ DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage);
+ DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount);
+
+ NextMd = MemoryDescriptor->ListEntry.Flink;
+ }
+}
+#endif // _PRINT_MDL_ // S006
+/* M004 --- */
diff --git a/private/ntos/nthals/halr94a/mips/r94adef.h b/private/ntos/nthals/halr94a/mips/r94adef.h
new file mode 100644
index 000000000..4ebbff766
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94adef.h
@@ -0,0 +1,266 @@
+// #pragma comment(exestr, "@(#) r94adef.h 1.1 95/09/28 15:47:51 nec")
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1994 NEC Corporation
+
+Module Name:
+
+ r94adef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the R94A system.
+
+Author:
+
+ Akitoshi Kuriyama 23-Aug-1994
+
+Revision History:
+
+ M001 1994.8.23 A. Kuriyama
+ - Modify for R94A MIPS R4400 (original duodef.h)
+ M002 1994.9.24 A. Kuriyama
+ - Modify PCI A-D Vector Value
+ H000 Sat Sep 24 23:11:51 JST 1994 kbnes!kishimoto
+ - Add the number of PCI slots
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 17:10:13 JST 1994
+ - Add
+ #define PCI_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+64*1024)
+ #define PCI_MEMORY_PHYSICAL_BASE_LOW (EISA_MEMORY_VERSION2_LOW + 64*1024*1024)
+ #define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x00000001
+ M003 Mon Oct 17 17:26:12 JST 1994 kbnes!kuriyama
+ name change MAXIMUN_PCI_SLOT -> R94A_PCI_SLOT
+ ADD002 ataka@oa2.kb.nec.co.jp Mon Oct 17 19:30:00 JST 1994
+ - change PCI_CONTROL_PHYSICAL_BASE, PCI_MEMORY_PHYSICAL_BASE_LOW
+ 64*1024 -> 10000 64*1024*1024 -> 4000000
+ D001 ataka@oa2.kb.nec.co.jp Sat Nov 05 16:06:26 JST 1994
+ - reduce DMA_TRANSLATION_LIMIT to 4 only for BBM DMA
+ S0004 Thu Dec 22 11:55:04 JST 1994 kbnes!A.Kuriyama
+ -add beta machine limit
+ S0005 Thu Jan 05 17:17:09 JST 1995 kbnes!A.Kuriyama
+ - warning clear
+ S0006 Thu Jan 05 18:52:51 JST 1995 kbnes!A.Kuriyama
+ - dma_limit change
+ M0007 Tue Mar 07 14:34:55 JST 1995 kbnes!kuriyama (A)
+ - expand dma logical address
+ M0008 Fri Mar 10 15:34:25 JST 1995 kbnes!kuriyama (A)
+ - expand dma logical address bug fix
+ M0009 Tue Mar 21 02:45:16 1995 kbnes!kishimoto
+ - physical base of PCI memory set to 64M
+ M0010 Tue Mar 21 03:06:05 1995 kbnes!kishimoto
+ - M0009 could not allocate memory
+ set base to zero.
+ M0011 Tue Apr 25 16:34:35 1995 kbnes!kishimoto
+ - add MRC registers
+ S0012 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 01:55:08 JST 1995
+ - add NVRAM_VIRTUAL_BASE
+ M0011 Sat Aug 12 16:51:50 1995 kbnes!kishimoto
+ - rearrange the comments.
+
+--*/
+
+#ifndef _R94ADEF_
+#define _R94ADEF_
+
+//
+// ADD001,ADD002
+// Define physical base addresses for system mapping.
+//
+
+#define VIDEO_MEMORY_PHYSICAL_BASE 0x40000000 // physical base of video memory
+#define VIDEO_CONTROL_PHYSICAL_BASE 0x60000000 // physical base of video control
+#define CURSOR_CONTROL_PHYSICAL_BASE 0x60008000 // physical base of cursor control
+#define VIDEO_ID_PHYSICAL_BASE 0x60010000 // physical base of video id register
+#define VIDEO_RESET_PHYSICAL_BASE 0x60020000 // physical base of reset register
+#define DEVICE_PHYSICAL_BASE 0x80000000 // physical base of device space
+#define NET_PHYSICAL_BASE 0x80001000 // physical base of ethernet control
+#define SCSI1_PHYSICAL_BASE 0x80002000 // physical base of SCSI1 control
+#define SCSI2_PHYSICAL_BASE 0x80003000 // physical base of SCSI2 control
+#define RTCLOCK_PHYSICAL_BASE 0x80004000 // physical base of realtime clock
+#define KEYBOARD_PHYSICAL_BASE 0x80005000 // physical base of keyboard control
+#define MOUSE_PHYSICAL_BASE 0x80005000 // physical base of mouse control
+#define SERIAL0_PHYSICAL_BASE 0x80006000 // physical base of serial port 0
+#define SERIAL1_PHYSICAL_BASE 0x80007000 // physical base of serial port 1
+#define PARALLEL_PHYSICAL_BASE 0x80008000 // physical base of parallel port
+#define EISA_CONTROL_PHYSICAL_BASE 0x90000000 // physical base of EISA control
+#define EISA_MEMORY_PHYSICAL_BASE 0x91000000 // physical base of EISA memory
+#define EISA_MEMORY_VERSION2_LOW 0x00000000 // physical base of EISA memory
+#define EISA_MEMORY_VERSION2_HIGH 0x00000001 // with version 2 address chip
+#define PROM_PHYSICAL_BASE 0xfff00000 // physical base of boot PROM
+#define EEPROM_PHYSICAL_BASE 0xfff40000 // physical base of FLASH PROM
+#define PCI_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE) // physical base of PCI control
+#define PCI_MEMORY_PHYSICAL_BASE_LOW (EISA_MEMORY_VERSION2_LOW) // physical base of PCI memory
+#define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x00000001 // physical base of PCI memory
+
+//
+// S0012
+// Define virtual/physical base addresses for system mapping.
+//
+
+#define NVRAM_VIRTUAL_BASE 0xffff8000 // virtual base of nonvolatile RAM
+#define NVRAM_PHYSICAL_BASE 0x80009000 // physical base of nonvolatile RAM
+
+#define SP_VIRTUAL_BASE 0xffffa000 // virtual base of serial port 0
+#define SP_PHYSICAL_BASE SERIAL0_PHYSICAL_BASE // physical base of serial port 0
+
+#define DMA_VIRTUAL_BASE 0xffffc000 // virtual base of DMA control
+#define DMA_PHYSICAL_BASE DEVICE_PHYSICAL_BASE // physical base of DMA control
+
+#define INTERRUPT_VIRTUAL_BASE 0xffffd000 // virtual base of interrupt source
+#define INTERRUPT_PHYSICAL_BASE 0x8000f000 // physical base of interrupt source
+
+//
+// Define the size of the DMA translation table.
+//
+
+#if defined (_BBM_DMA_) // D001,S0004,S0005,S0006
+
+#define DMA_TRANSLATION_LIMIT (sizeof(TRANSLATION_ENTRY) * 8 * 4) // translation table limit
+
+#else
+
+#if defined(_DMA_EXPAND_) // M0007,M0008
+
+#define ISA_MAX_ADR 0x400000L // ISA MAX Logical Address
+#define EISA_MIN_ADR 0x1000000L // EISA/PCI MIN Logical Address
+#define EISA_MAX_ADR 0x2000000L // EISA/PCI MAX Logical Address
+#define DMA_TRANSLATION_LIMIT (EISA_MAX_ADR / PAGE_SIZE * sizeof(TRANSLATION_ENTRY) )
+ // translation table limit
+#else // _DMA_EXPAND_
+
+#define DMA_TRANSLATION_LIMIT 0x2000 // translation table limit
+
+#endif // _DMA_EXPAND_
+
+#endif // (_BBM_DMA_)
+
+
+//
+// Define the maximum number of map registers allowed per allocation.
+//
+
+#define DMA_REQUEST_LIMIT (DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY) * 8))
+
+//
+// Define pointer to DMA control registers.
+//
+
+#define DMA_CONTROL ((volatile PDMA_REGISTERS)(DMA_VIRTUAL_BASE))
+
+//
+// Define DMA channel interrupt level.
+//
+
+#define DMA_LEVEL 3
+
+//
+// Define the minimum and maximum system time increment values in 100ns units.
+//
+
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+//
+// Define Duo clock level.
+//
+
+#define CLOCK_LEVEL 6 // Interval clock level
+#define CLOCK_INTERVAL ((MAXIMUM_INCREMENT / (10 * 1000)) - 1) // Ms minus 1
+#define CLOCK2_LEVEL CLOCK_LEVEL //
+
+//
+// Define EISA device level.
+//
+
+#define EISA_DEVICE_LEVEL 5 // EISA bus interrupt level
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define EISA_VECTORS 32
+
+#define IRQL10_VECTOR (10 + EISA_VECTORS) // Eisa interrupt request level 10
+#define IRQL11_VECTOR (11 + EISA_VECTORS) // Eisa interrupt request level 11
+#define IRQL12_VECTOR (12 + EISA_VECTORS) // Eisa interrupt request level 12
+#define IRQL13_VECTOR (13 + EISA_VECTORS) // Eisa interrupt request level 13
+
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+//
+// Define I/O device interrupt level.
+//
+
+#define DEVICE_LEVEL 4 // I/O device interrupt level
+
+//
+// Define device interrupt vectors.
+//
+
+#define DEVICE_VECTORS 16 // starting builtin device vector
+
+#define PARALLEL_VECTOR (1 + DEVICE_VECTORS) // Parallel device interrupt vector
+//#define VIDEO_VECTOR (3 + DEVICE_VECTORS) // video device interrupt vector
+#define AUDIO_VECTOR (3 + DEVICE_VECTORS) // audio device interrupt vector
+#define NET_VECTOR (4 + DEVICE_VECTORS) // ethernet device interrupt vector
+#define SCSI1_VECTOR (5 + DEVICE_VECTORS) // SCSI device interrupt vector
+#define SCSI2_VECTOR (6 + DEVICE_VECTORS) // SCSI device interrupt vector
+#define KEYBOARD_VECTOR (7 + DEVICE_VECTORS) // Keyboard device interrupt vector
+#define MOUSE_VECTOR (8 + DEVICE_VECTORS) // Mouse device interrupt vector
+#define SERIAL0_VECTOR (9 + DEVICE_VECTORS) // Serial device 0 interrupt vector
+#define SERIAL1_VECTOR (10 + DEVICE_VECTORS) // Serial device 1 interrupt vector
+#define TYPHOON_ERROR_INTERRUPT_VECTOR (15 + DEVICE_VECTORS) // TYPHOON error vector
+//#define MAXIMUM_BUILTIN_VECTOR SERIAL1_VECTOR // maximum builtin vector
+#define MAXIMUM_BUILTIN_VECTOR TYPHOON_ERROR_INTERRUPT_VECTOR // maximum builtin vector
+
+//
+// M0001,M0002
+// Define PCI device interrupt vectors.
+//
+
+#define PCI_VECTORS 80
+//#define INTERRUPT_D_VECTOR (0 + PCI_VECTORS)
+//#define INTERRUPT_C_VECTOR (1 + PCI_VECTORS)
+//#define INTERRUPT_B_VECTOR (2 + PCI_VECTORS)
+//#define INTERRUPT_A_VECTOR (3 + PCI_VECTORS)
+//#define MAXIMUM_PCI_VECTOR INTERRUPT_A_VECTOR
+
+//
+// Define the clock speed in megahetz for the SCSI protocol chips.
+//
+
+#define NCR_SCSI_CLOCK_SPEED 24
+
+//
+// PROM entry point definitions.
+//
+// Define base address of prom entry vector and prom entry macro.
+//
+
+#define PROM_BASE (KSEG1_BASE | 0x1fc00000)
+#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8))
+
+//
+// H000,M003
+// the number of lines which PCI interrupts.
+//
+
+#define R94A_PCI_SLOT 3
+
+//
+// M0011
+// Define pointer to MRC control registers.
+//
+
+#define MRC_CONTROL ((volatile PMRC_REGISTERS)(DMA_VIRTUAL_BASE))
+
+//
+// M0011
+// Define physical base addresses for system mapping.
+//
+
+#define MRC_TEMP_PHYSICAL_BASE 0x80012000 // physical base of MRC and TEMP sensor
+
+#endif // _R94ADEF_
+
diff --git a/private/ntos/nthals/halr94a/mips/r94adma.h b/private/ntos/nthals/halr94a/mips/r94adma.h
new file mode 100644
index 000000000..5d8676ebb
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94adma.h
@@ -0,0 +1,433 @@
+// #pragma comment(exestr, "@(#) r94adma.h 1.1 95/09/28 15:48:23 nec")
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1994 NEC Corporation
+
+Module Name:
+
+ r94adma.h
+
+Abstract:
+
+ This module is the header file that describes the DMA control register
+ structure for the R94A system.
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1990
+
+Revision History:
+
+ M001 1994.8.24 A. Kuriyama
+ - Modify for R94A MIPS R4400 (original duodma.h)
+ H000 Sat Sep 24 21:36:20 JST 1994 kbnes!kishimoto
+ - Add PCIInterruptStatus register structure definition
+ M002 Mon Oct 03 19:52:16 JST 1994 kbnes!kuriyama(A)
+ - Add PCI(HURRICANE) register
+ - Change InvalidAddress register to DMA_LARGE_REGISTER
+ - Change RTC_REGISTER structure define.
+ - add Optional... registers
+ H001 Fri Dec 9 18:29:10 1994 kbnes!kishimoto
+ - Modify LEDControl definition (SHORT -> CHAR)
+ H002 Tue Jan 24 18:24:48 1995 kbnes!kishimoto
+ - Add PCI interrupt enable bits definitions.
+ H003 Tue Apr 25 16:38:06 1995 kbnes!kishimoto
+ - Add MRC registers
+ H004 Sat Aug 12 16:18:53 1995 kbnes!kishimoto
+ - rearrange comments.
+
+--*/
+
+#ifndef _R94ADMA_
+#define _R94ADMA_
+
+//
+// M001
+// Define DMA register structures.
+//
+
+typedef struct _DMA_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} DMA_REGISTER, *PDMA_REGISTER;
+
+typedef struct _DMA_CHAR_REGISTER {
+ UCHAR Char;
+ UCHAR Fill;
+ USHORT Fill2;
+} DMA_CHAR_REGISTER, *PDMA_CHAR_REGISTER;
+
+typedef struct _DMA_SHORT_REGISTER {
+ USHORT Short;
+ USHORT Fill;
+} DMA_SHORT_REGISTER, *PDMA_SHORT_REGISTER;
+
+typedef struct _DMA_LARGE_REGISTER {
+ union {
+ LARGE_INTEGER LargeInteger;
+ double Double;
+ } u;
+} DMA_LARGE_REGISTER, *PDMA_LARGE_REGISTER;
+
+//
+// Define DMA channel register structure.
+//
+
+typedef struct _DMA_CHANNEL {
+ DMA_REGISTER Mode;
+ DMA_REGISTER Enable;
+ DMA_REGISTER ByteCount;
+ DMA_REGISTER Address;
+} DMA_CHANNEL, *PDMA_CHANNEL;
+
+//
+// M002
+// Define PCI Address/Mask register structure
+//
+
+typedef struct _PCI_ADDRESS_MASK {
+ ULONG Address;
+ ULONG Mask;
+} PCI_ADDRESS_MASK, *PPCI_ADDRESS_MASK;
+
+//
+// Define DMA control register structure.
+//
+
+typedef volatile struct _DMA_REGISTERS {
+ DMA_REGISTER Configuration; // offset 000
+ DMA_REGISTER RevisionLevel; // offset 008
+ DMA_REGISTER RemoteFailedAddress; // offset 010
+ DMA_REGISTER MemoryFailedAddress; // offset 018
+ DMA_LARGE_REGISTER InvalidAddress; // offset 020 // M002
+ DMA_REGISTER TranslationBase; // offset 028
+ DMA_REGISTER TranslationLimit; // offset 030
+ DMA_REGISTER TranslationInvalidate; // offset 038
+ DMA_REGISTER ChannelInterruptAcknowledge; // offset 040
+ DMA_REGISTER LocalInterruptAcknowledge; // offset 048
+ DMA_REGISTER EisaInterruptAcknowledge; // offset 050
+ DMA_REGISTER TimerInterruptAcknowledge; // offset 058
+ DMA_REGISTER IpInterruptAcknowledge; // offset 060
+ DMA_REGISTER Reserved1; // offset 068
+ DMA_REGISTER WhoAmI; // offset 070
+ DMA_REGISTER NmiSource; // offset 078
+ DMA_REGISTER RemoteSpeed[15]; // offset 080
+ DMA_REGISTER InterruptEnable; // offset 0f8
+ DMA_CHANNEL Channel[4]; // offset 100
+ DMA_REGISTER ArbitrationControl; // offset 180
+ DMA_REGISTER Errortype; // offset 188
+ DMA_REGISTER RefreshRate; // offset 190
+ DMA_REGISTER RefreshCounter; // offset 198
+ DMA_REGISTER SystemSecurity; // offset 1a0
+ DMA_REGISTER InterruptInterval; // offset 1a8
+ DMA_REGISTER IntervalTimer; // offset 1b0
+ DMA_REGISTER IpInterruptRequest; // offset 1b8
+ DMA_REGISTER InterruptDiagnostic; // offset 1c0
+ DMA_LARGE_REGISTER EccDiagnostic; // offset 1c8
+ DMA_REGISTER MemoryConfig[4]; // offset 1d0
+ DMA_REGISTER Reserved2;
+ DMA_REGISTER Reserved3;
+ DMA_LARGE_REGISTER IoCacheBuffer[64]; // offset 200
+ DMA_REGISTER IoCachePhysicalTag[8]; // offset 400
+ DMA_REGISTER IoCacheLogicalTag[8]; // offset 440
+ DMA_REGISTER IoCacheLowByteMask[8]; // offset 480
+ DMA_REGISTER IoCacheHighByteMask[8]; // offset ??? wrong?
+
+ //
+ // M001,M002,H001
+ // new registers of STORM-chipset
+ //
+
+ DMA_REGISTER ProcessorBootModeControl; // offset 500
+ DMA_REGISTER ClockCounter; // offset 508
+ DMA_REGISTER MemoryTimingControl; // offset 510
+ DMA_REGISTER PCIConfigurationAddress; // offset 518
+ DMA_REGISTER PCIConfigurationData; // offset 520
+ DMA_REGISTER PCISpecialCycle; // offset 528
+ DMA_REGISTER PCIInterruptEnable; // offset 530
+ DMA_REGISTER PCIInterruptStatus; // offset 538
+ DMA_REGISTER CopyTagConfiguration; // offset 540
+ DMA_REGISTER CopyTagAddress; // offset 548
+ DMA_REGISTER CopyTagData; // offset 550
+ DMA_REGISTER ASIC2Revision; // offset 558
+ DMA_REGISTER ASIC3Revision; // offset 560
+ DMA_REGISTER Reserved4; // offset 568
+ ULONG OptionalRemoteSpeed1; // offset 570
+ ULONG OptionalRemoteSpeed2; // offset 574
+ ULONG OptionalRemoteSpeed3; // offset 578
+ ULONG OptionalRemoteSpeed4; // offset 57c
+ DMA_REGISTER LocalInterruptAcknowledge2; // offset 580
+ DMA_REGISTER OptionalIoConfiguration1; // offset 588
+ DMA_REGISTER OptionalIoConfiguration2; // offset 590
+ DMA_REGISTER OptionalIoConfiguration3; // offset 598
+ DMA_REGISTER OptionalIoConfiguration4; // offset 5a0
+ DMA_SHORT_REGISTER BuzzerCount; // offset 5a8
+ DMA_CHAR_REGISTER BuzzerControl; // offset 5ac
+ DMA_SHORT_REGISTER LEDCount; // offset 5b0
+ DMA_CHAR_REGISTER LEDControl; // offset 5b4
+ DMA_SHORT_REGISTER NECIoPort; // offset 5b8
+ ULONG TyphoonErrorStatus; // offset 5bc
+ DMA_REGISTER AddressConversionRegion; // offset 5c0
+ DMA_REGISTER AddressConversionMask; // offset 5c8
+ DMA_REGISTER Reserved12; // offset 5d0
+ DMA_REGISTER Reserved13; // offset 5d8
+ DMA_REGISTER Reserved14; // offset 5e0
+ DMA_REGISTER Reserved15; // offset 5e8
+ DMA_REGISTER Reserved16; // offset 5f0
+ DMA_REGISTER Reserved17; // offset 5f8
+ USHORT PCIVenderID; // offset 600
+ USHORT PCIDeviceID; // offset 602
+ USHORT PCICommand; // offset 604
+ USHORT PCIStatus; // offset 606
+ UCHAR PCIRevisionID; // offset 608
+ UCHAR PCIProgIf; // offset 609
+ UCHAR PCISubClass; // offset 60a
+ UCHAR PCIBaseClass; // offset 60b
+ UCHAR PCICacheLineSize; // offset 60c
+ UCHAR PCILatencyTimer; // offset 60d
+ UCHAR PCIHeaderType; // offset 60e
+ UCHAR PCIBIST; // offset 60f
+ DMA_REGISTER Reserved18; // offset 610
+ DMA_REGISTER Reserved19; // offset 618
+ DMA_REGISTER Reserved20; // offset 620
+ DMA_REGISTER Reserved21; // offset 628
+ ULONG PCIROMBaseAddress; // offset 630
+ ULONG Reserved22[2]; // offset 634
+ UCHAR PCIInterruptLine; // offset 63c
+ UCHAR PCIInterruptPin; // offset 63d
+ UCHAR PCIMinimumGrant; // offset 63e
+ UCHAR PCIMaximumLatency; // offset 63f
+ PCI_ADDRESS_MASK PCIFastBackToBack[2]; // offset 640
+ PCI_ADDRESS_MASK PCIBurst[2]; // offset 650
+ PCI_ADDRESS_MASK PCIMemory; // offset 660
+ ULONG PCIMasterRetryTimer; // offset 668
+} DMA_REGISTERS, *PDMA_REGISTERS;
+
+//
+// Configuration Register values.
+//
+
+#define LOAD_CLEAN_EXCLUSIVE 0x20
+#define DISABLE_EISA_MEMORY 0x10
+#define ENABLE_PROCESSOR_B 0x08
+#define MAP_PROM 0x04
+
+//
+// Interrupt Enable bits.
+//
+#define ENABLE_CHANNEL_INTERRUPTS (1 << 0)
+#define ENABLE_DEVICE_INTERRUPTS (1 << 1)
+#define ENABLE_EISA_INTERRUPTS (1 << 2)
+#define ENABLE_TIMER_INTERRUPTS (1 << 3)
+#define ENABLE_IP_INTERRUPTS (1 << 4)
+
+//
+// Eisa Interupt Acknowledge Register values.
+//
+
+#define EISA_NMI_VECTOR 0x8000
+
+//
+// DMA_NMI_SRC register bit definitions.
+//
+
+#define NMI_SRC_MEMORY_ERROR 1
+#define NMI_SRC_R4000_ADDRESS_ERROR 2
+#define NMI_SRC_IO_CACHE_ERROR 4
+#define NMI_SRC_ADR_NMI 8
+
+//
+// Define DMA channel mode register structure.
+//
+
+typedef struct _DMA_CHANNEL_MODE {
+ ULONG AccessTime : 3;
+ ULONG TransferWidth : 2;
+ ULONG InterruptEnable : 1;
+ ULONG BurstMode : 1;
+ ULONG Reserved1 : 25;
+} DMA_CHANNEL_MODE, *PDMA_CHANNEL_MODE;
+
+//
+// Define access time values.
+//
+
+#define ACCESS_40NS 0x0 // 40ns access time
+#define ACCESS_80NS 0x1 // 80ns access time
+#define ACCESS_120NS 0x2 // 120ns access time
+#define ACCESS_160NS 0x3 // 160ns access time
+#define ACCESS_200NS 0x4 // 200ns access time
+#define ACCESS_240NS 0x5 // 240ns access time
+#define ACCESS_280NS 0x6 // 280ns access time
+#define ACCESS_320NS 0x7 // 320ns access time
+
+//
+// Define transfer width values.
+//
+
+#define WIDTH_8BITS 0x1 // 8-bit transfer width
+#define WIDTH_16BITS 0x2 // 16-bit transfer width
+#define WIDTH_32BITS 0x3 // 32-bit transfer width
+
+//
+// M001
+// Define DMA channel enable register structure.
+//
+
+typedef struct _DMA_CHANNEL_ENABLE {
+ ULONG ChannelEnable : 1;
+ ULONG TransferDirection : 1;
+ ULONG Reserved1 : 6;
+ ULONG TerminalCount : 1;
+ ULONG MemoryError : 1;
+// ULONG TranslationError : 1;
+// ULONG Reserved2 : 21;
+ ULONG ParityError : 1;
+ ULONG MasterAbort : 1;
+ ULONG Reserved2 : 20;
+} DMA_CHANNEL_ENABLE, *PDMA_CHANNEL_ENABLE;
+
+//
+// M001,M002
+// define RTC structure.
+//
+
+typedef struct _RTC_REGISTERS {
+ UCHAR Data;
+ UCHAR Index;
+} RTC_REGISTERS, *PRTC_REGISTERS;
+
+//
+// Define transfer direction values.
+//
+
+#define DMA_READ_OP 0x0 // read from device
+#define DMA_WRITE_OP 0x1 // write to device
+
+//
+// Define translation table entry structure.
+//
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ ULONG PageFrame;
+ ULONG Fill;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Error Type Register values
+//
+
+#define SONIC_ADDRESS_ERROR 4
+#define SONIC_MEMORY_ERROR 0x40
+#define EISA_ADDRESS_ERROR 1
+#define EISA_MEMORY_ERROR 2
+
+//
+// Address Mask definitions.
+//
+
+#define LFAR_ADDRESS_MASK 0xfffff000
+#define RFAR_ADDRESS_MASK 0x00ffffc0
+#define MFAR_ADDRESS_MASK 0x1ffffff0
+
+//
+// ECC Register Definitions.
+//
+
+#define ECC_SINGLE_BIT_DP0 0x02000000
+#define ECC_SINGLE_BIT_DP1 0x20000000
+#define ECC_SINGLE_BIT ( ECC_SINGLE_BIT_DP0 | ECC_SINGLE_BIT_DP1 )
+#define ECC_DOUBLE_BIT_DP0 0x04000000
+#define ECC_DOUBLE_BIT_DP1 0x40000000
+#define ECC_DOUBLE_BIT ( ECC_DOUBLE_BIT_DP0 | ECC_DOUBLE_BIT_DP1 )
+#define ECC_MULTIPLE_BIT_DP0 0x08000000
+#define ECC_MULTIPLE_BIT_DP1 0x80000000
+
+#define ECC_FORCE_DP0 0x010000
+#define ECC_FORCE_DP1 0x100000
+#define ECC_DISABLE_SINGLE_DP0 0x020000
+#define ECC_DISABLE_SINGLE_DP1 0x200000
+#define ECC_ENABLE_DP0 0x040000
+#define ECC_ENABLE_DP1 0x400000
+
+//
+// LED/DIAG Register Definitions.
+//
+
+#define DIAG_NMI_SWITCH 2
+
+//
+// Common error bit definitions
+//
+
+#define SINGLE_ERROR 1
+#define MULTIPLE_ERROR 2
+#define RFAR_CACHE_FLUSH 4
+
+//
+// M001
+// Define NMI Status/Control register structure.
+//
+
+typedef struct _BUZZER_CONTROL {
+ UCHAR SpeakerGate : 1;
+ UCHAR SpeakerData : 1;
+ UCHAR Reserved1 : 3;
+ UCHAR SpeakerTimer : 1;
+ UCHAR Reserved2 : 2;
+}BUZZER_CONTROL, *PBUZZER_CONTROL;
+
+//
+// H000
+// Define PCI Interrupt Status register structure.
+//
+
+typedef struct _STORM_PCI_INTRRUPT_STATUS{
+ ULONG IntD: 1;
+ ULONG IntC: 1;
+ ULONG IntB: 1;
+ ULONG IntA: 1;
+ ULONG Perr: 1;
+ ULONG Serr: 1;
+ ULONG RetryOverflow: 1;
+ ULONG MasterAbort: 1;
+ ULONG TargetAbort: 1;
+ ULONG Reserved: 23;
+} STORM_PCI_INTRRUPT_STATUS, *PSTORM_PCI_INTRRUPT_STATUS;
+
+//
+// H002
+// PCI Interrupt Enable bits.
+//
+
+#define ENABLE_TARGET_ABORT_INTERRUPTS (1 << 8)
+#define ENABLE_MASTER_ABORT_INTERRUPTS (1 << 7)
+#define ENABLE_RETRY_OVERFLOW_EISA_INTERRUPTS (1 << 6)
+#define ENABLE_SERR_INTERRUPTS (1 << 5)
+#define ENABLE_PERR_INTERRUPTS (1 << 4)
+
+//
+// H003
+// Define MRC control register structure.
+//
+
+typedef volatile struct _MRC_REGISTERS {
+ UCHAR Reserved1[256]; // offset 000
+ UCHAR Interrupt; // offset 100
+ UCHAR Reserved2[7]; // offset 107
+ UCHAR Mode; // offset 108
+ UCHAR Reserved3[39]; // offset 109
+ UCHAR SoftwarePowerOff; // offset 130
+ UCHAR Reserved4[15]; // offset 131
+ UCHAR LEDBitControl; // offset 140
+ UCHAR Reserved5[3]; // offset 141
+ UCHAR SegmentLEDControl[4]; // offset 144
+ UCHAR Reserved6[155]; // offset 145
+ UCHAR TempEnable; // offset 1e0
+ UCHAR Reserved7[31]; // offset 145
+ UCHAR TempSensor; // offset 200
+ UCHAR Reserved8[3583]; // offset 201
+} MRC_REGISTERS, *PMRC_REGISTERS;
+
+
+#endif // _R94ADMA_
diff --git a/private/ntos/nthals/halr94a/mips/r94ainfo.c b/private/ntos/nthals/halr94a/mips/r94ainfo.c
new file mode 100644
index 000000000..a2c59341b
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94ainfo.c
@@ -0,0 +1,99 @@
+// #pragma comment(exestr, "@(#) r94ainfo.c 1.1 95/09/28 15:48:57 nec")
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History
+
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-ixinfo.h to 1050-halx86-r98info.h
+
+--*/
+
+
+#include "halp.h"
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
diff --git a/private/ntos/nthals/halr94a/mips/r94aint.h b/private/ntos/nthals/halr94a/mips/r94aint.h
new file mode 100644
index 000000000..6904b9a85
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94aint.h
@@ -0,0 +1,35 @@
+// #pragma comment(exestr, "@(#) r94aint.h 1.1 95/09/28 15:49:28 nec")
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ duoint.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the interrupt source and enable registers on the DUO system.
+
+Author:
+
+ Lluis Abello (lluis) 20-Apr-1993
+
+Revision History:
+
+--*/
+
+#ifndef _DUOINT_
+#define _DUOINT_
+
+//
+// Define Interrupt register structure.
+//
+
+typedef struct _INTERRUPT_REGISTERS {
+ USHORT Fill;
+ USHORT Enable;
+} INTERRUPT_REGISTERS, *PINTERRUPT_REGISTERS;
+
+#endif // _DUOINT_
diff --git a/private/ntos/nthals/halr94a/mips/r94aio.s b/private/ntos/nthals/halr94a/mips/r94aio.s
new file mode 100644
index 000000000..fed2171e2
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94aio.s
@@ -0,0 +1,149 @@
+// .ident "@(#) r94aio.s 1.1 95/09/28 18:36:07 nec"
+//++
+//
+// Copyright (c) 1994 KOBE NEC Software Corporation
+//
+// Module Name:
+//
+// r94aio.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to read
+// and write the 64-bit register on a MIPS R4000 R94A system.
+//
+// Author:
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// H000 Fri Oct 7 19:57:09 JST 1994 kbnes!kisimoto
+// new READ_REGISTER_DWORD
+// new WRITE_REGISTER_DWORD
+//
+//--
+
+#if defined(_R94A_)
+
+#include "halmips.h"
+
+//++
+//
+// VOID
+// READ_REGISTER_DWORD (
+// IN PLARGE_INTEGER RegisterAddress,
+// IN PVOID Variable
+// )
+//
+// Routine Description:
+//
+// 64-bit I/O space register read function.
+//
+// Arguments:
+//
+// RegisterAddress (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Variable (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Return Value:
+//
+// None.
+//
+// Destination and Source must be 8-byte aligned.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_DWORD)
+
+ ldc1 f0,0(a0) // move 8-byte block
+ sdc1 f0,0(a1) //
+
+ sync // synchronize read
+
+ j ra // return
+
+ .end READ_REGISTER_DWORD
+
+
+//++
+//
+// VOID
+// WRITE_REGISTER_DWORD (
+// IN PLARGE_INTEGER RegisterAddress,
+// IN PVOID Variable
+// )
+//
+// Routine Description:
+//
+// 64-bit I/O space register write function.
+//
+// Arguments:
+//
+// RegisterAddress (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Variable (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Return Value:
+//
+// None.
+//
+// Destination and Source must be 8-byte aligned.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_DWORD)
+
+ ldc1 f0,0(a1) // move 8-byte block
+ sdc1 f0,0(a0) //
+
+ sync // synchronize write
+
+ j ra // return
+
+ .end WRITE_REGISTER_DWORD
+
+
+//++
+//
+// VOID
+// HalpGetStatusRegister (
+// IN PULONG Variable
+// )
+//
+// Routine Description:
+//
+// This function returns value which is status register of R4400.
+//
+// Arguments:
+//
+// Variable (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpGetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,psr // get current processor status
+ nop // 1 cycle hazzard
+ sw t0,0(a0) // save integer registers a0 - a3
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetStatusRegister
+
+#endif
diff --git a/private/ntos/nthals/halr94a/mips/r94anmi.s b/private/ntos/nthals/halr94a/mips/r94anmi.s
new file mode 100644
index 000000000..b0f87aabb
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/r94anmi.s
@@ -0,0 +1,621 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) r94anmi.s 1.2 95/10/17 01:19:11" ) */
+//
+// TITLE("R94A NMI routine")
+//++
+//
+// Copyright (c) 1995 NEC Corporation
+//
+// Module Name:
+//
+// r94anmi.s
+//
+// Abstract:
+//
+// This routine support for dump switch.
+//
+// Author:
+//
+// Akitoshi Kuriyama (NEC Software Kobe,Inc)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// R4400 based only.
+//
+// Revision History:
+//
+// kuriyama@oa2.kbnes.nec.co.jp Sun Oct 15 20:11:38 JST 1995
+// - new code for J94D (!_MRCDUMP_ _MRCPOWER_ compile option need)
+//
+//--
+#include "halmips.h"
+
+ SBTTL("NMI dispatch routine")
+//++
+//
+// VOID
+// HalpNMIDispatch (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function was called by firmware when NMI occuerd.
+//
+// Arguments:
+//
+// none.
+//
+// Return Value:
+//
+// none.
+//
+//--
+
+ LEAF_ENTRY(HalpNMIDispatch)
+
+ .set noreorder
+ .set noat
+
+//
+// Save temporary Registers for use.
+// save area shoud have for every processros.
+//
+
+ li k0,0xffffc070 // get processor number.
+ lw k0,(k0) //
+ bne k0,zero,10f //
+ nop // fill
+
+ la k1,HalpNMISave0 // set save address.
+ j 20f //
+ nop // fill
+
+10:
+ la k1,HalpNMISave1 // set save address.
+ nop // 1 cycle hazzerd
+
+20:
+ sw AT,0x0(k1) // register save.
+ sw v0,0x4(k1) //
+ sw v1,0x8(k1) //
+ sw a0,0xc(k1) //
+ sw a1,0x10(k1) //
+ sw a2,0x14(k1) //
+ sw a3,0x18(k1) //
+ sw t0,0x1c(k1) //
+ sw t1,0x20(k1) //
+ sw t2,0x24(k1) //
+ sw t3,0x28(k1) //
+ sw t4,0x2c(k1) //
+ sw t5,0x30(k1) //
+ sw t6,0x34(k1) //
+ sw t7,0x38(k1) //
+ sw t8,0x3c(k1) //
+ sw t9,0x40(k1) //
+ sw gp,0x44(k1) //
+ sw sp,0x48(k1) //
+ sw s8,0x4c(k1) //
+ sw ra,0x50(k1) //
+ mfc0 k0,psr //
+ nop //
+ nop //
+ sw k0,0x54(k1) //
+ nop //
+ mfc0 k0,cause //
+ nop //
+ nop //
+ sw k0,0x58(k1) //
+ nop //
+ mfc0 k0,epc //
+ nop //
+ nop //
+ sw k0,0x5c(k1) //
+ nop //
+ mfc0 k0,errorepc //
+ nop //
+ nop //
+ sw k0,0x60(k1) //
+ nop //
+ mfc0 k0,cacheerr //
+ nop //
+ nop //
+ sw k0,0x64(k1) //
+
+ sdc1 f0,0x68(k1) //
+
+//
+// Set Dump Switch Status register to tlb fixed entry
+//
+
+ li t0,4 // set index 4(hurricane register)
+ li t1,0x80012 << 6 // set MRC register
+ li t2,0x8000e << 6 // set Self-Test address
+
+ mfc0 t3,index // save tlb registers
+ mfc0 t4,entryhi //
+ mfc0 t5,entrylo0 //
+ mfc0 t6,entrylo1 //
+ mfc0 t7,pagemask //
+ mtc0 t0,index //
+ nop
+ nop
+ nop
+
+ tlbr // read index 4 tlb
+ nop
+ nop
+ nop
+ nop
+
+ mfc0 t8,entrylo0 // Get entrylo0
+ mfc0 t9,entrylo1 // Get entrylo1
+ nop
+ nop
+ nop
+ or t1,t8,t1 // set MRC address
+ or t2,t8,t2 // set Self-test address
+ nop
+
+ mtc0 t1,entrylo0 // set MRC to tlb 4 0
+ mtc0 t2,entrylo1 // set Self-test to tlb 4 1
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+//
+// read dump status
+//
+
+#if defined(_MRCDUMP_)
+
+ li t1,0xffffc108 // load MRC Mode value
+
+#else // SELFTEST DUMP
+
+ li t1,0xffffd000 // load Self-Test value
+
+ li k0,0x1b // set dash
+ sb k0,(t1) // display led
+ sync
+
+#endif // _MRCDUMP_
+
+ lb k0,(t1) // load Dump switch status.
+ nop //
+ lb k0,(t1) // wait
+ nop //
+
+//
+// Check dump status
+//
+
+ li t1,2 // check for dump switch
+ and k0,k0,t1 //
+
+#if defined(_MRCDUMP_)
+ beq k0,zero,30f // if 0 dump swith was not pressed
+#else // _MRCDUMP_
+ bne k0,zero,30f // if 0 dump swith was pressed
+#endif // _MRCDUMP_
+ nop //
+
+#if !defined(_MRCDUMP_)
+ li t1,0xffffd000 // set dump switch status address
+ li t2,0x1b // display LED dash
+ sb t2,(t1) //
+ sync //
+#endif // not _MRCDUMP_
+
+//
+// enable powoff NMI
+//
+
+#if defined(_MRCPOWER_)
+ li t1,0xffffc108 //
+ li t0,0x82 //
+ nop //
+ sb t0,(t1) //
+ nop //
+ li t0,0x80 //
+ nop //
+ sb t0,(t1) //
+ nop //
+ li t0,0x02 //
+ nop //
+ sb t0,(t1) //
+ nop //
+#endif // _MRCPOWER_
+
+//
+// restore tlb 4 entry
+//
+
+ mtc0 t8,entrylo0 // restore tlb 4 0
+ mtc0 t9,entrylo1 // restore tlb 4 1
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+//
+// restore tlb registers
+//
+ mtc0 t3,index //
+ mtc0 t4,entryhi //
+ mtc0 t5,entrylo0 //
+ mtc0 t6,entrylo1 //
+ mtc0 t7,pagemask //
+
+#if !defined(_MRCDUMP_)
+ la k0,0xffffc5b8 // get NEC I/O port value
+ lb t0,(k0) //
+ nop // 1 cycle hazzerd
+ li t1,0xfd // clear dump enable bit
+ and t0,t0,t1
+ sb t0,(k0) // set NEC I/O port value
+#endif // not _MRCDUMP_
+
+//
+// set NMI flag 1
+//
+
+ la t2,HalpNMIFlag // set NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+//
+// set dump flag 1
+//
+
+ la t2,HalpDumpNMIFlag // set Dump NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+//
+// clear psr BEV bit
+//
+
+ mfc0 t0,psr // get psr
+ li t2,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and t0,t0,t2 //
+ nop //
+ mtc0 t0,psr // set psr
+
+ lw t0,0x1c(k1) // restore temporary registers
+ lw t1,0x20(k1) //
+ lw t2,0x24(k1) //
+ lw t3,0x28(k1) //
+ lw t4,0x2c(k1) //
+ lw t5,0x30(k1) //
+ lw t6,0x34(k1) //
+ lw t7,0x38(k1) //
+ lw t8,0x3c(k1) //
+ lw t9,0x40(k1) //
+ lw AT,0x0(k1) //
+
+ eret // return to error epc
+ nop // errata
+ nop //
+ nop //
+ eret //
+ nop //
+
+30:
+
+//
+// No Dump Switch.
+//
+// Check Power Switch
+
+#if defined(_MRCPOWER_)
+ li t1,0xffffc108
+ nop
+ li t0,0x02
+ nop
+ sb t0,(t1)
+ nop
+
+#endif // _MRCPOWER_
+
+ mtc0 t8,entrylo0 // restore tlb 4
+ mtc0 t9,entrylo1 // restore tlb 4
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+ mtc0 t3,index // restore tlb registers
+ mtc0 t4,entryhi //
+ mtc0 t5,entrylo0 //
+ mtc0 t6,entrylo1 //
+ mtc0 t7,pagemask //
+
+
+//
+// set NMI flag 1
+//
+ la t2,HalpNMIFlag // set NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+// S003 +++
+ li t1,0xffffc078 // check NMI source
+ lw t0,(t1) // check NMI source
+ nop //
+ beq t0,zero,40f //
+ nop //
+ li t1,0xffffc020
+ nop
+ ldc1 f0,(t1) // clear processor invalid
+ nop
+ sdc1 f0,0x70(k1) // save processor invalid
+40:
+// S003 ---
+
+ mfc0 t0,psr // get psr
+ li t2,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and t0,t0,t2 //
+ nop //
+ mtc0 t0,psr // set psr
+
+ lw t0,0x1c(k1) // restore temporary registers
+ lw t1,0x20(k1) //
+ lw t2,0x24(k1) //
+ lw t3,0x28(k1) //
+ lw t4,0x2c(k1) //
+ lw t5,0x30(k1) //
+ lw t6,0x34(k1) //
+ lw t7,0x38(k1) //
+ lw t8,0x3c(k1) //
+ lw t9,0x40(k1) //
+ lw AT,0x0(k1) //
+ ldc1 f0,0x68(k1) //
+ nop
+
+ eret // return to errorepc
+ nop // errata
+ nop //
+ nop //
+ eret //
+ nop //
+
+// L001 ---
+
+ .set at
+ .set reorder
+
+ .end HalpNMIDispatch
+
+// Start M008
+ SBTTL("Software Power Off")
+//++
+//
+// VOID
+// HalpPowOffNMIDispatch (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function was called by firmware when NMI occuerd.
+//
+// Arguments:
+//
+// none.
+//
+// Return Value:
+//
+// none.
+//
+//--
+
+ LEAF_ENTRY(HalpPowOffNMIDispatch)
+
+ .set noat
+ .set noreorder
+
+//
+// Save temporary Registers for use.
+// save area shoud have for every processros.
+//
+
+ li k0,0xffffc070 // get processor number.
+ lw k0,(k0) //
+ bne k0,zero,60f //
+ nop // fill
+
+ la k1,HalpNMISave0 // set save address.
+ j 70f //
+ nop // fill
+
+60:
+ la k1,HalpNMISave1 // set save address.
+ nop // 1 cycle hazzerd
+
+70:
+ sw t0,0(k1) // save temporary registers
+ sw t1,4(k1) //
+ sw t2,8(k1) //
+ sw t3,12(k1) //
+ sw t4,16(k1) //
+ sw t5,20(k1) //
+ sw t6,24(k1) //
+ sw t7,28(k1) //
+ sw AT,32(k1) //
+
+//
+// Set Power Switch Status register to tlb fixed entry
+//
+ li t0,4 // set index 4(hurricane register)
+
+ li t1,0x80012 << 6 // set MRC register
+
+ mfc0 t3,index // save tlb registers
+ mfc0 t4,entryhi //
+ mfc0 t5,entrylo0 //
+ mfc0 t6,entrylo1 //
+ mfc0 t7,pagemask //
+ mtc0 t0,index //
+ nop
+ nop
+ nop
+
+ tlbr // read index 4 tlb
+ nop
+ nop
+ nop
+ nop
+
+ mfc0 t2,entrylo0 // set Self-test address to tlb
+ nop
+ nop
+ nop
+ or t1,t2,t1
+ nop
+
+ mtc0 t1,entrylo0 // set Self-Test to tlb 4
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+ li t1,0xffffc100 // load MRC Int value
+
+ nop
+ lb k0,(t1) // load Interrupt status.
+ nop
+ lb k0,(t1) // wait
+ nop
+
+ li t0,0x01 // set clear value
+ sb t0,(t1) // clear OffSw bit
+
+ li t1,0x4 // check for OffSw switch
+ nop //
+ and k0,k0,t1 //
+
+ beq k0,zero,80f // 0 means Power switch was not pressed
+ nop //
+
+ li t1,0xffffc130 // load MRC Software PowerOff Register
+
+ nop
+
+ lb t0,0x1 // set PowerOff Value
+
+90:
+ sb t0,(t1) // write PowerOff bit
+ beq zero,zero,90b
+ nop
+
+ eret
+ nop
+ nop
+ nop
+ eret
+ nop
+80:
+
+//
+// No Power Switch.
+//
+
+ mtc0 t2,entrylo0 // restore tlb 4
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+ mtc0 t3,index // restore tlb registers
+ mtc0 t4,entryhi //
+ mtc0 t5,entrylo0 //
+ mtc0 t6,entrylo1 //
+ mtc0 t7,pagemask //
+
+
+ la t2,HalpNMIFlag // set NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+ lw t0,0xffffc078 // check NMI source
+ nop //
+ beq t0,zero,45f //
+ nop //
+ lw t0,0xffffc020 // clear processor invalid
+45:
+
+ mfc0 t0,psr // get psr
+ li t2,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and t0,t0,t2 //
+ nop //
+ mtc0 t0,psr // set psr
+
+ lw t0,0(k1) // restore temporary registers
+ lw t1,4(k1) //
+ lw t2,8(k1) //
+ lw t3,12(k1) //
+ lw t4,16(k1) //
+ lw t5,20(k1) //
+ lw t6,24(k1) //
+ lw t7,28(k1) //
+ lw AT,32(k1) //
+
+ eret // return to errorepc
+ nop // errata
+ nop //
+ nop //
+ eret //
+ nop //
+
+ .set reorder
+ .set at
+
+ .end HalpPowOffNMIDispatch
+// End M008
diff --git a/private/ntos/nthals/halr94a/mips/rgb525.h b/private/ntos/nthals/halr94a/mips/rgb525.h
new file mode 100644
index 000000000..a4e53e09e
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/rgb525.h
@@ -0,0 +1,468 @@
+// #pragma comment(exestr, "@(#) rgb525.h 1.2 95/09/28 18:38:14 nec")
+/************************************************************************
+ * *
+ * Copyright (c) 1994 3Dlabs Inc. Ltd. *
+ * All rights reserved *
+ * *
+ * This software and its associated documentation contains proprietary, *
+ * confidential and trade secret information of 3Dlabs Inc. Ltd. and *
+ * except as provided by written agreement with 3Dlabs Inc. Ltd. *
+ * *
+ * a) no part may be disclosed, distributed, reproduced, transmitted, *
+ * transcribed, stored in a retrieval system, adapted or translated *
+ * in any form or by any means electronic, mechanical, magnetic, *
+ * optical, chemical, manual or otherwise, *
+ * *
+ * and *
+ * *
+ * b) the recipient is not entitled to discover through reverse *
+ * engineering or reverse compiling or other such techniques or *
+ * processes the trade secrets contained therein or in the *
+ * documentation. *
+ * *
+ ************************************************************************/
+
+#ifndef __RGB525_H__
+#define __RGB525_H__
+
+/************************************************************************/
+/* DIRECT ACCESS REGISTERS */
+/************************************************************************/
+
+/* direct registers on 64-bit boundaries */
+
+#define __RGB525_PalAddrWrite 0x00
+#define __RGB525_PaletteData 0x08
+#define __RGB525_PixelMask 0x10
+#define __RGB525_PalAddrRead 0x18
+#define __RGB525_IndexLow 0x20
+#define __RGB525_IndexHigh 0x28
+#define __RGB525_IndexedData 0x30
+#define __RGB525_IndexControl 0x38
+
+/************************************************************************/
+/* INDEXED REGISTERS - MISCELLANEOUS CONTROL */
+/************************************************************************/
+
+#define __RGB525_MiscControlOne 0x0070
+#define __RGB525_MiscControlTwo 0x0071
+#define __RGB525_MiscControlThree 0x0072
+#define __RGB525_MiscClockControl 0x0002
+#define __RGB525_SyncControl 0x0003
+#define __RGB525_HSyncControl 0x0004
+#define __RGB525_PowerManagement 0x0005
+#define __RGB525_DACOperation 0x0006
+#define __RGB525_PaletteControl 0x0007
+
+/* MiscControlOne */
+
+#define RGB525_MISR_CNTL_OFF (0 << 7)
+#define RGB525_MISR_CNTL_ON (1 << 7)
+#define RGB525_VMSK_CNTL_OFF (0 << 6)
+#define RGB525_VMSK_CNTL_ON (1 << 6)
+#define RGB525_PADR_RFMT_READ_ADDR (0 << 5)
+#define RGB525_PADR_RFMT_PAL_STATE (1 << 5)
+#define RGB525_SENS_DSAB_ENABLE (0 << 4)
+#define RGB525_SENS_DSAB_DISABLE (1 << 4)
+#define RGB525_SENS_SEL_BIT3 (0 << 3)
+#define RGB525_SENS_SEL_BIT7 (1 << 3)
+#define RGB525_VRAM_SIZE_32 (0 << 0)
+#define RGB525_VRAM_SIZE_64 (1 << 0)
+
+/* MiscControlTwo */
+
+#define RGB525_PCLK_SEL_LCLK (0 << 6)
+#define RGB525_PCLK_SEL_PLL (1 << 6)
+#define RGB525_PCLK_SEL_EXT (2 << 6)
+#define RGB525_INTL_MODE_DISABLE (0 << 5)
+#define RGB525_INTL_MODE_ENABLE (1 << 5)
+#define RGB525_BLANK_CNTL_NORMAL (0 << 4)
+#define RGB525_BLANK_CNTL_BLANKED (1 << 4)
+#define RGB525_COL_RES_6_BIT (0 << 2)
+#define RGB525_COL_RES_8_BIT (1 << 2)
+#define RGB525_PORT_SEL_VGA (0 << 0)
+#define RGB525_PORT_SEL_VRAM (1 << 0)
+
+/* MiscControlThree */
+
+#define RGB525_SWAP_RB_DISABLE (0 << 7)
+#define RGB525_SWAP_RB_ENABLE (1 << 7)
+#define RGB525_SWAP_WORD_31_00_FIRST (0 << 4)
+#define RGB525_SWAP_WORD_63_32_FIRST (1 << 4)
+#define RGB525_SWAP_NIB_07_04_FIRST (0 << 2)
+#define RGB525_SWAP_NIB_03_00_FIRST (1 << 2)
+
+/* MiscClockControl */
+
+#define RGB525_DDOTCLK_ENABLE (0 << 7)
+#define RGB525_DDOTCLK_DISABLE (1 << 7)
+#define RGB525_SCLK_ENABLE (0 << 6)
+#define RGB525_SCLK_DISABLE (1 << 6)
+#define RGB525_B24P_DDOT_DIV_PLL (0 << 5)
+#define RGB525_B24P_DDOT_SCLK (1 << 5)
+#define RGB525_DDOT_PLL_DIV_1 (0 << 1)
+#define RGB525_DDOT_PLL_DIV_2 (1 << 1)
+#define RGB525_DDOT_PLL_DIV_4 (2 << 1)
+#define RGB525_DDOT_PLL_DIV_8 (3 << 1)
+#define RGB525_DDOT_PLL_DIV_16 (4 << 1)
+#define RGB525_PLL_DISABLE (0 << 0)
+#define RGB525_PLL_ENABLE (1 << 0)
+
+/* SyncControl */
+
+#define RGB525_DLY_CNTL_ADD (0 << 7)
+#define RGB525_DLY_SYNC_NOADD (1 << 7)
+#define RGB525_CSYN_INVT_DISABLE (0 << 6)
+#define RGB525_CSYN_INVT_ENABLE (1 << 6)
+#define RGB525_VSYN_INVT_DISABLE (0 << 5)
+#define RGB525_VSYN_INVT_ENABLE (1 << 5)
+#define RGB525_HSYN_INVT_DISABLE (0 << 4)
+#define RGB525_HSYN_INVT_ENABLE (1 << 4)
+#define RGB525_VSYN_CNTL_NORMAL (0 << 2)
+#define RGB525_VSYN_CNTL_HIGH (1 << 2)
+#define RGB525_VSYN_CNTL_LOW (2 << 2)
+#define RGB525_VSYN_CNTL_DISABLE (3 << 2)
+#define RGB525_HSYN_CNTL_NORMAL (0 << 0)
+#define RGB525_HSYN_CNTL_HIGH (1 << 0)
+#define RGB525_HSYN_CNTL_LOW (2 << 0)
+#define RGB525_HSYN_CNTL_DISABLE (3 << 0)
+
+/* HSyncControl */
+
+#define RGB525_HSYN_POS(n) ((n) & 0xF)
+
+/* PowerManagement */
+
+#define RGB525_SCLK_PWR_NORMAL (0 << 4)
+#define RGB525_SCLK_PWR_DISABLE (1 << 4)
+#define RGB525_DDOT_PWR_NORMAL (0 << 3)
+#define RGB525_DDOT_PWR_DISABLE (1 << 3)
+#define RGB525_SYNC_PWR_NORMAL (0 << 2)
+#define RGB525_SYNC_PWR_DISABLE (1 << 2)
+#define RGB525_ICLK_PWR_NORMAL (0 << 1)
+#define RGB525_ICLK_PWR_DISABLE (1 << 1)
+#define RGB525_DAC_PWR_NORMAL (0 << 0)
+#define RGB525_DAC_PWR_DISABLE (1 << 0)
+
+/* DACOperation */
+
+#define RGB525_SOG_DISABLE (0 << 3)
+#define RGB525_SOG_ENABLE (1 << 3)
+#define RGB525_BRB_NORMAL (0 << 2)
+#define RGB525_BRB_ALWAYS (1 << 2)
+#define RGB525_DSR_SLOW (0 << 1)
+#define RGB525_DSR_FAST (1 << 1)
+#define RGB525_DPE_DISABLE (0 << 0)
+#define RGB525_DPE_ENABLE (1 << 0)
+
+/* PaletteControl */
+
+#define RGB525_6BIT_LINEAR_ENABLE (0 << 7)
+#define RGB525_6BIT_LINEAR_DISABLE (1 << 7)
+#define RGB525_PALETTE_PARTITION(n) ((n) & 0xF)
+
+/************************************************************************/
+/* INDEXED REGISTERS - PIXEL REPRESENTATION */
+/************************************************************************/
+
+#define __RGB525_PixelFormat 0x000A
+#define __RGB525_8BitPixelControl 0x000B
+#define __RGB525_16BitPixelControl 0x000C
+#define __RGB525_24BitPixelControl 0x000D
+#define __RGB525_32BitPixelControl 0x000E
+
+/* PixelFormat */
+
+#define RGB525_PIXEL_FORMAT_4_BPP (2 << 0)
+#define RGB525_PIXEL_FORMAT_8_BPP (3 << 0)
+#define RGB525_PIXEL_FORMAT_16_BPP (4 << 0)
+#define RGB525_PIXEL_FORMAT_24_BPP (5 << 0)
+#define RGB525_PIXEL_FORMAT_32_BPP (6 << 0)
+
+/* 8BitPixelControl */
+
+#define RGB525_B8_DCOL_INDIRECT (0 << 0)
+#define RGB525_B8_DCOL_DIRECT (1 << 0)
+
+/* 16BitPixelControl */
+
+#define RGB525_B16_DCOL_INDIRECT (0 << 6)
+#define RGB525_B16_DCOL_DYNAMIC (1 << 6)
+#define RGB525_B16_DCOL_DIRECT (3 << 6)
+#define RGB525_B16_POL_FORCES_BYPASS (0 << 5)
+#define RGB525_B16_POL_FORCES_LOOKUP (1 << 5)
+#define RGB525_B16_ZIB (0 << 2)
+#define RGB525_B16_LINEAR (1 << 2)
+#define RGB525_B16_555 (0 << 1)
+#define RGB525_B16_565 (1 << 1)
+#define RGB525_B16_SPARSE (0 << 0)
+#define RGB525_B16_CONTIGUOUS (1 << 0)
+
+/* 24BitPixelControl */
+
+#define RGB525_B24_DCOL_INDIRECT (0 << 0)
+#define RGB525_B24_DCOL_DIRECT (1 << 0)
+
+/* 32BitPixelControl */
+
+#define RGB525_B32_POL_FORCES_BYPASS (0 << 2)
+#define RGB525_B32_POL_FORCES_LOOKUP (1 << 2)
+#define RGB525_B32_DCOL_INDIRECT (0 << 0)
+#define RGB525_B32_DCOL_DYNAMIC (1 << 0)
+#define RGB525_B32_DCOL_DIRECT (3 << 0)
+
+/************************************************************************/
+/* INDEXED REGISTERS - FREQUENCY CONTROL */
+/************************************************************************/
+
+#define __RGB525_PLLControlOne 0x0010
+#define __RGB525_PLLControlTwo 0x0011
+#define __RGB525_PLLRefDivCount 0x0014
+
+#define __RGB525_F0 0x0020
+#define __RGB525_F1 0x0021
+#define __RGB525_F2 0x0022
+#define __RGB525_F3 0x0023
+#define __RGB525_F4 0x0024
+#define __RGB525_F5 0x0025
+#define __RGB525_F6 0x0026
+#define __RGB525_F7 0x0027
+#define __RGB525_F8 0x0028
+#define __RGB525_F9 0x0029
+#define __RGB525_F10 0x002A
+#define __RGB525_F11 0x002B
+#define __RGB525_F12 0x002C
+#define __RGB525_F13 0x002D
+#define __RGB525_F14 0x002E
+#define __RGB525_F15 0x002F
+
+#define __RGB525_M0 0x0020
+#define __RGB525_M1 0x0022
+#define __RGB525_M2 0x0024
+#define __RGB525_M3 0x0026
+#define __RGB525_M4 0x0028
+#define __RGB525_M5 0x002A
+#define __RGB525_M6 0x002C
+#define __RGB525_M7 ox002E
+
+#define __RGB525_N0 0x0021
+#define __RGB525_N1 0x0023
+#define __RGB525_N2 0x0025
+#define __RGB525_N3 0x0027
+#define __RGB525_N4 0x0029
+#define __RGB525_N5 0x002B
+#define __RGB525_N6 0x002D
+#define __RGB525_N7 ox002F
+
+/* PLLControlOne */
+
+#define RGB525_REF_SRC_REFCLK (0 << 4)
+#define RGB525_REF_SRC_EXTCLK (1 << 4)
+#define RGB525_PLL_EXT_FS_DIRECT (0 << 0)
+#define RGB525_PLL_EXT_FS_M_N (1 << 0)
+#define RGB525_PLL_INT_FS_DIRECT (2 << 0)
+#define RGB525_PLL_INT_FS_M_N (3 << 0)
+
+/* PLLControlTwo */
+
+#define RGB525_PLL_INT_FS(n) ((n) & 0xF)
+
+/* PLLRefDivCount */
+
+#define RGB525_REF_DIV_COUNT(n) ((n) & 0x1F)
+
+#define RGB525_PLL_REFCLK_4_MHz (0x02)
+#define RGB525_PLL_REFCLK_6_MHz (0x03)
+#define RGB525_PLL_REFCLK_8_MHz (0x04)
+#define RGB525_PLL_REFCLK_10_MHz (0x05)
+#define RGB525_PLL_REFCLK_12_MHz (0x06)
+#define RGB525_PLL_REFCLK_14_MHz (0x07)
+#define RGB525_PLL_REFCLK_16_MHz (0x08)
+#define RGB525_PLL_REFCLK_18_MHz (0x09)
+#define RGB525_PLL_REFCLK_20_MHz (0x0A)
+#define RGB525_PLL_REFCLK_22_MHz (0x0B)
+#define RGB525_PLL_REFCLK_24_MHz (0x0C)
+#define RGB525_PLL_REFCLK_26_MHz (0x0D)
+#define RGB525_PLL_REFCLK_28_MHz (0x0E)
+#define RGB525_PLL_REFCLK_30_MHz (0x0F)
+#define RGB525_PLL_REFCLK_32_MHz (0x10)
+#define RGB525_PLL_REFCLK_34_MHz (0x11)
+#define RGB525_PLL_REFCLK_36_MHz (0x12)
+#define RGB525_PLL_REFCLK_38_MHz (0x13)
+#define RGB525_PLL_REFCLK_40_MHz (0x14)
+#define RGB525_PLL_REFCLK_42_MHz (0x15)
+#define RGB525_PLL_REFCLK_44_MHz (0x16)
+#define RGB525_PLL_REFCLK_46_MHz (0x17)
+#define RGB525_PLL_REFCLK_48_MHz (0x18)
+#define RGB525_PLL_REFCLK_50_MHz (0x19)
+#define RGB525_PLL_REFCLK_52_MHz (0x1A)
+#define RGB525_PLL_REFCLK_54_MHz (0x1B)
+#define RGB525_PLL_REFCLK_56_MHz (0x1C)
+#define RGB525_PLL_REFCLK_58_MHz (0x1D)
+#define RGB525_PLL_REFCLK_60_MHz (0x1E)
+#define RGB525_PLL_REFCLK_62_MHz (0x1F)
+
+/* F0-F15[7:0] */
+
+#define RGB525_DF(n) (((n) & 0x3) << 6)
+#define RGB525_VCO_DIV_COUNT(n) ((n) & 0x3F)
+
+/************************************************************************/
+/* INDEXED REGISTERS - CURSOR */
+/************************************************************************/
+
+#define __RGB525_CursorControl 0x0030
+#define __RGB525_CursorXLow 0x0031
+#define __RGB525_CursorXHigh 0x0032
+#define __RGB525_CursorYLow 0x0033
+#define __RGB525_CursorYHigh 0x0034
+#define __RGB525_CursorHotSpotX 0x0035
+#define __RGB525_CursorHotSpotY 0x0036
+#define __RGB525_CursorColor1Red 0x0040
+#define __RGB525_CursorColor1Green 0x0041
+#define __RGB525_CursorColor1Blue 0x0042
+#define __RGB525_CursorColor2Red 0x0043
+#define __RGB525_CursorColor2Green 0x0044
+#define __RGB525_CursorColor2Blue 0x0045
+#define __RGB525_CursorColor3Red 0x0046
+#define __RGB525_CursorColor3Green 0x0047
+#define __RGB525_CursorColor3Blue 0x0048
+
+/* CursorControl */
+
+#define RGB525_SMLC_PART_0 (0 << 6)
+#define RGB525_SMLC_PART_1 (1 << 6)
+#define RGB525_SMLC_PART_2 (2 << 6)
+#define RGB525_SMLC_PART_3 (3 << 6)
+#define RGB525_PIX_ORDER_RIGHT_TO_LEFT (0 << 5)
+#define RGB525_PIX_ORDER_LEFT_TO_RIGHT (1 << 5)
+#define RGB525_LOC_READ_LAST_WRITTEN (0 << 4)
+#define RGB525_LOC_READ_ACTUAL_LOCATION (1 << 4)
+#define RGB525_UPDT_CNTL_DELAYED (0 << 3)
+#define RGB525_UPDT_CNTL_IMMEDIATE (1 << 3)
+#define RGB525_CURSOR_SIZE_32 (0 << 2)
+#define RGB525_CURSOR_SIZE_64 (1 << 2)
+#define RGB525_CURSOR_MODE_OFF (0 << 0)
+#define RGB525_CURSOR_MODE_3_COLOR (1 << 0)
+#define RGB525_CURSOR_MODE_2_COLOR_HL (2 << 0)
+#define RGB525_CURSOR_MODE_2_COLOR (3 << 0)
+
+/************************************************************************/
+/* INDEXED REGISTERS - BORDER COLOR */
+/************************************************************************/
+
+#define __RGB525_BorderColorRed 0x0060
+#define __RGB525_BorderColorGreen 0x0061
+#define __RGB525_BorderColorBlue 0x0062
+
+/************************************************************************/
+/* INDEXED REGISTERS - DIAGNOSTIC SUPPORT */
+/************************************************************************/
+
+#define __RGB525_RevisionLevel 0x0000
+#define __RGB525_ProductID 0x0001
+#define __RGB525_DACSense 0x0082
+#define __RGB525_MISRRed 0x0084
+#define __RGB525_MISRGreen 0x0086
+#define __RGB525_MISRBlue 0x0088
+#define __RGB525_PLLVCODivInput 0x008E
+#define __RGB525_PLLVCORefInput 0x008F
+#define __RGB525_VramMaskLow 0x0090
+#define __RGB525_VramMaskHigh 0x0091
+
+/* RevisionLevel */
+
+#define RGB525_PRODUCT_REV_LEVEL 0xF0
+
+/* ProductID */
+
+#define RGB525_PRODUCT_ID_CODE 0x01
+
+/************************************************************************/
+/* INDEXED REGISTERS - CURSOR ARRAY */
+/************************************************************************/
+
+#define __RGB525_CursorArray 0x0100
+
+/************************************************************************/
+/* DIRECT ACCESS MACROS */
+/************************************************************************/
+/*
+ * The pixel clock must be running to access the palette and the cursor
+ * array, and the timings for the microprocessor signals are specified
+ * in units of pixel clocks. Six clocks must be allowed for an internal
+ * access to complete, following a palette or cursor access.
+ *
+ * In the worst case (VGA 640x480 resolution) the pixel clock is 40 ns,
+ * giving a time of 280 ns for seven pixel clocks. Assuming the fastest
+ * host clock is 100 MHz, a delay of 28 host clocks is required. Again
+ * assuming that the loop below takes 3 clocks per iteration, it should
+ * be executed at least 10 times.
+ */
+
+#define RGB525_DELAY \
+{ \
+ volatile DWORD __rgb525_dly; \
+ \
+ for (__rgb525_dly = 0; __rgb525_dly < 10; __rgb525_dly++); \
+}
+
+/*
+ * All RGB525 accesses are followed by a short delay, as required by
+ * the AC Characteristics table in the RGB525 Databook. However, the
+ * text implies that non-palette or cursor-array accesses can happen
+ * closer together. Everything is delayed here for simplicity.
+ */
+
+#define RGB525_ADDR(base, offset) \
+( \
+/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \
+ (DWORD) ((base) + (offset)) \
+)
+
+#define RGB525_WRITE(dac, offset, data) \
+{ \
+/* DWORD_WRITE(RGB525_ADDR((dac),(offset)), (data)); */ \
+ WRITE_REGISTER_UCHAR(RGB525_ADDR((dac),(offset)), (UCHAR)(data)); \
+ RGB525_DELAY; \
+}
+
+#define RGB525_READ_BYTE(dac, offset, data) \
+{ \
+ DWORD __rgb525_tmp; \
+ \
+/* DWORD_READ(RGB525_ADDR((dac),(offset)), __rgb525_tmp); */ \
+ __rgb525_tmp = READ_REGISTER_UCHAR(RGB525_ADDR((dac),(offset))); \
+/* (data) = (BYTE) (__rgb525_tmp & BYTE_MAX); */ \
+ (data) = (UCHAR) (__rgb525_tmp & 0xff); \
+ RGB525_DELAY; \
+}
+
+/************************************************************************/
+/* INDEXED ACCESS MACROS */
+/************************************************************************/
+
+#define RGB525_SET_INDEX(dac, index) \
+{ \
+ RGB525_WRITE((dac), __RGB525_IndexLow, (index)); \
+/* RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> BYTE_BITS); */ \
+ RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> 8); \
+}
+
+#define RGB525_SET_REG(dac, index, data) \
+{ \
+ RGB525_SET_INDEX((dac), (index)); \
+ RGB525_WRITE((dac), __RGB525_IndexedData, (data)); \
+}
+
+#define RGB525_GET_REG(dac, index, data) \
+{ \
+ RGB525_SET_INDEX((dac), (index)); \
+ RGB525_READ_BYTE((dac), __RGB525_IndexedData, (data)); \
+}
+
+/************************************************************************/
+
+#endif /* __RGB525_H__ */
+
+/************************************************************************/
diff --git a/private/ntos/nthals/halr94a/mips/tga.h b/private/ntos/nthals/halr94a/mips/tga.h
new file mode 100644
index 000000000..3e6257c7c
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/tga.h
@@ -0,0 +1,93 @@
+// #pragma comment(exestr, "@(#) tga.h 1.1 95/09/28 18:38:49 nec")
+/*++
+
+Module Name:
+
+ tga.h
+
+Abstract:
+
+ This module contains the register definitions for the TGA (DEC21030)
+
+Author:
+
+ T.Katoh create-data 1994/11/30
+
+Revision Histort:
+
+--*/
+
+// TGA Core Space Map offset for 8-bpp Frame Buffers
+
+#define TGA_REG_SPC_OFFSET 0x00100000
+#define TGA_DSP_BUF_OFFSET 0x00200000
+
+// TGA register offsets, organized by functionality.
+
+#define PLANE_MASK 0x00000028
+#define ONE_SHOT_PIXEL_MASK 0x0000002C
+#define MODE 0x00000030
+#define RASTER_OP 0x00000034
+#define DEEP 0x00000050
+#define BLK_COLOR_R0 0X00000140
+#define BLK_COLOR_R1 0X00000144
+#define H_CONT 0x00000064
+#define V_CONT 0x00000068
+#define VIDEO_BASE 0x0000006c
+#define VIDEO_VALID 0x00000070
+#define RAMDAC_SETUP 0x000000C0
+#define EEPROM_WRITE 0x000001e0
+#define CLOCK 0x000001e8
+#define RAMDAC_DATA 0X000001f0
+#define COMMAND_STATUS 0x000001f8
+
+// Initiate Palette Data
+
+#define VGA_INI_PALETTE_BLACK_R 0x00
+#define VGA_INI_PALETTE_BLACK_G 0x00
+#define VGA_INI_PALETTE_BLACK_B 0x00
+#define VGA_INI_PALETTE_RED_R 0xAA
+#define VGA_INI_PALETTE_RED_G 0x00
+#define VGA_INI_PALETTE_RED_B 0x00
+#define VGA_INI_PALETTE_GREEN_R 0x00
+#define VGA_INI_PALETTE_GREEN_B 0xAA
+#define VGA_INI_PALETTE_GREEN_G 0x00
+#define VGA_INI_PALETTE_YELLOW_R 0xAA
+#define VGA_INI_PALETTE_YELLOW_G 0xAA
+#define VGA_INI_PALETTE_YELLOW_B 0x00
+#define VGA_INI_PALETTE_BLUE_R 0x00
+#define VGA_INI_PALETTE_BLUE_G 0x00
+#define VGA_INI_PALETTE_BLUE_B 0xAA
+#define VGA_INI_PALETTE_MAGENTA_R 0xAA
+#define VGA_INI_PALETTE_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_MAGENTA_B 0xAA
+#define VGA_INI_PALETTE_CYAN_R 0x00
+#define VGA_INI_PALETTE_CYAN_G 0xAA
+#define VGA_INI_PALETTE_CYAN_B 0xAA
+#define VGA_INI_PALETTE_WHITE_R 0xAA
+#define VGA_INI_PALETTE_WHITE_G 0xAA
+#define VGA_INI_PALETTE_WHITE_B 0xAA
+#define VGA_INI_PALETTE_HI_BLACK_R 0x00
+#define VGA_INI_PALETTE_HI_BLACK_G 0x00
+#define VGA_INI_PALETTE_HI_BLACK_B 0x00
+#define VGA_INI_PALETTE_HI_RED_R 0xFF
+#define VGA_INI_PALETTE_HI_RED_G 0x00
+#define VGA_INI_PALETTE_HI_RED_B 0x00
+#define VGA_INI_PALETTE_HI_GREEN_R 0x00
+#define VGA_INI_PALETTE_HI_GREEN_G 0xFF
+#define VGA_INI_PALETTE_HI_GREEN_B 0x00
+#define VGA_INI_PALETTE_HI_YELLOW_R 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_G 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_B 0x00
+#define VGA_INI_PALETTE_HI_BLUE_R 0x00
+#define VGA_INI_PALETTE_HI_BLUE_G 0x00
+#define VGA_INI_PALETTE_HI_BLUE_B 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_R 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_HI_MAGENTA_B 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_R 0x00
+#define VGA_INI_PALETTE_HI_CYAN_G 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_B 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_R 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_G 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_B 0xFF
diff --git a/private/ntos/nthals/halr94a/mips/x4clock.s b/private/ntos/nthals/halr94a/mips/x4clock.s
new file mode 100644
index 000000000..2e3aaac3a
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/x4clock.s
@@ -0,0 +1,433 @@
+// .ident "@(#) x4clock.s 1.1 95/09/28 18:39:17 nec"
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// M001 Fri Feb 17 17:48:03 JST 1995 kbnes!kuriyama (A)
+// - Change HalpClockInterrupt0(()
+// for dump switch support.
+//
+// S002 Tue Feb 21 21:24:13 JST 1995 kbnes!kuriyama (A)
+// - use HalpNMIFlag
+//
+// S003 Wed Feb 22 11:18:59 JST 1995 kbnes!kuriyama (A)
+// - enter kernel debugger when NMI only checked version
+//
+// S004 Wed Feb 22 14:25:20 JST 1995 kbnes!kuriyama (A)
+// - enter kernel debugger when NMI free version
+//
+// S005 Sat Mar 18 20:30:05 JST 1995 kbnes!kuriyama (A)
+// - nmi logic change
+//
+// M006 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 14:16:29 JST 1995
+// - change nmi logic
+//
+// M007 Thu Jul 20 19:31:41 JST 1995 kbnes!kisimoto
+// - Merge build 1057
+//
+//--
+
+#include "halmips.h"
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdef.h"
+
+#endif
+
+// M001 +++
+#if defined(_R94A_)
+ .extern HalpNMIFlag
+ .extern HalpNMIInterrupt
+ .extern HalpDumpNMIFlag //S002
+#endif //_R94A_
+// M001 ---
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+
+// M001 +++
+#if defined(_R94A_)
+//
+// check if dump swich flag set.
+//
+
+ la t0,HalpNMIFlag // set NMI flag address
+ li t1,0xa0000000 // set KSEG1_BASE
+ or t0,t0,t1
+ lw t1,(t0) // load NMI flag
+ nop
+ beq t1,zero,10f
+ nop
+ sw zero,(t0)
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ nop
+ lbu t0,0(t0) // get debugger enable flag
+ nop
+ beq zero,t0,5f // if eq, debugger not enabled
+ nop
+ nop
+ beq zero,v0,40f // if eq, no breakin requested
+ nop
+ break BREAKIN_BREAKPOINT // break into the debugger
+ nop
+5:
+
+// S002 +++
+ la t0,HalpDumpNMIFlag // set Dump NMI flag address
+ li t1,0xa0000000 // set KSEG1_BASE
+ or t0,t0,t1 //
+ lw a0,(t0) // load Dump NMI flag
+ nop //
+// S003 +++
+ sw zero,(t0) // clear Dump NMI flag
+ nop //
+// S003 ---
+// S005
+ lw zero,DMA_VIRTUAL_BASE + 0x58 // clear acknowledge // M006
+// S002 ---
+ jal HalpNMIInterrupt // jump to NMI routine
+ nop //
+10:
+#endif // _R94A_
+// M001 ---
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+
+#endif
+
+#if defined(_JAZZ_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
+
+#endif
+
+
+ .set reorder
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// The following code is a work around for a bug in the Fusion machines
+// where the clock interrupt is not dismissed by reading the acknowledge
+// register.
+//
+
+#if defined(_JAZZ_)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,cause // read the cause register
+ lw t1,HalpEisaControlBase // get EISA control base address
+ sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit
+ bgez t0,10f // if gez, no clock interrupt pending
+ li t2,0x2 // get NMI port enable bit
+ lb t3,0x70(t1) // save EISA NMI interrupt disable
+ lb t4,0x461(t1) // save EISA extended NMI status
+ sb zero,0x70(t1) // clear EISA NMI interrupt disable
+ sb t2,0x461(t1) // set EISA NMI port enable
+ sb zero,0x462(t1) // generate EISA NMI interrupt
+ sb zero,0x461(t1) // clear EISA extended NMI status
+ sb t2,0x461(t1) //
+ lb zero,0x461(t1) // synchronize clear operatin
+ sb t3,0x70(t1) // restore EISA NMI interupt disable
+ sb t4,0x461(t1) // restore EISA exteneed NMI status
+ lb zero,0x461(t1) // synchronize restore operation
+ .set at
+ .set reorder
+
+10: //
+
+#endif
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,30f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+
+ .set noreorder
+
+#if defined(_DUO_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count
+
+#endif
+
+#if defined(_JAZZ_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
+
+#endif
+
+ .set reorder
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1 //
+
+#else // M007
+
+ j ra //
+
+#endif
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+#if defined(NT_UP)
+
+ la t1,HalpPerformanceCounter // get performance counter address
+
+#else
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+#endif
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halr94a/mips/x4tb.s b/private/ntos/nthals/halr94a/mips/x4tb.s
new file mode 100644
index 000000000..be37d6677
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/x4tb.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4tb.s"
diff --git a/private/ntos/nthals/halr94a/mips/x86bios.c b/private/ntos/nthals/halr94a/mips/x86bios.c
new file mode 100644
index 000000000..68a599e80
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/x86bios.c
@@ -0,0 +1,1261 @@
+// #pragma comment(exestr, "@(#) x86bios.c 1.1 95/09/28 18:40:12 nec")
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ M001 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:45:09 JST 1995
+ - add check intel based bios flag
+
+ M002 kuriyama@oa2.kb.nec.co.jp Thu Jul 20 15:16:52 JST 1995
+ - add for DPI support (NO PCI DATA structure)
+
+ S003 kuriyama@oa2.kb.nec.co.jp Tue Aug 15 14:09:30 JST 1995
+ - bug fix for canopus PowerWindows 864PCI
+
+--*/
+
+
+#define USE_BIOS_EMULATOR
+
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "xm86.h"
+#include "x86new.h"
+
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PSHORT Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PSHORT Buffer,
+ IN ULONG Offset
+ );
+
+// M001 +++
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+// M001 ---
+
+//
+// Define global data.
+//
+
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+PVOID HalpIoMemoryBase = NULL;
+PVOID HalpIoControlBase=NULL;
+PUCHAR HalpRomBase = NULL;
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (64*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+//#define R98_PCICONFIG_START ((PULONG)(0x18ca8800 | KSEG1_BASE))
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+BOOLEAN HalpInitX86Emulator(
+ VOID)
+
+{
+ ULONG ROM_size = 0;
+ PHYSICAL_ADDRESS PhysAddr;
+ UCHAR BaseClass, SubClass, ProgIf;// M001
+ USHORT Cmd,SetCmd, VendorID, DeviceID, Slot; // M002
+ PUCHAR ROM_Ptr, ROM_Shadow;
+ ULONG i;
+ ULONG r;
+ USHORT PciDataOffset; // M001
+ PCI_SLOT_NUMBER PciSlot;
+ UCHAR header;
+ KIRQL Irql;
+ PhysAddr.HighPart = 0x00000000;
+
+
+#if 1
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ //kuku
+ KeRaiseIrql (PROFILE_LEVEL, &Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+#if 0 //tmp 707 // M001
+ // First Check ISA BIOS.Becase PCEB 0-1M Positive Decode So
+ // I Can See ROM Image.
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+
+ HalpIoMemoryBase= (PVOID)0x40000000;
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Look for ISA option video ROM signature
+ //
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ }
+#if defined(_X86_DBG_)
+ DbgPrint("\n EISA ROM BIOS Found \n"); //DBGDBG
+#endif // _X86_DBG_
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ HalpIoControlBase= (PVOID)0x403f0000;
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+ return TRUE;
+
+ }
+#endif
+
+ //
+ // Scan PCI slots for video BIOS ROMs, except 3 PCI "slots" on motherboard
+ //
+ // Slot 0: Hurrucane (host bridge)
+ // Slot 1: Typhoon (Internal-bus bridge)
+ // Slot 2: PCI-EISA bridge
+ //
+ for (Slot = 3; Slot < 6; Slot++) {
+#if defined(_X86_DBG_)
+ DbgPrint("\n PCI SLot Number=%x\n",Slot); //DBGDBG
+#endif // _X86_DBG_
+ //
+ // Create a mapping to PCI configuration space
+ //
+
+ PciSlot.u.bits.FunctionNumber = 0;
+ PciSlot.u.bits.DeviceNumber = Slot ;
+
+ //
+ // Read Vendor ID and check if slot is empty
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&VendorID,FIELD_OFFSET (PCI_COMMON_CONFIG, VendorID));
+
+#if defined(_X86_DBG_)
+DbgPrint("\n Vendor ID=%x\n",VendorID); //DBGDBG
+#endif // _X86_DBG_
+
+ if (VendorID == 0xFFFF){
+ continue; // Slot is empty; go to next slot
+ }
+
+// M002 +++
+ //
+ // Read Device ID and check if slot is empty
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&DeviceID,FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceID));
+
+ //
+ // Check for GLINT or DEC-GA board.
+ //
+
+ if ( (VendorID == 0x3d3d && DeviceID == 0x0001) ||
+ (VendorID == 0x1011 && DeviceID == 0x0004) ) {
+ continue;
+ }
+// M002 ---
+
+
+// M001 +++
+ //
+ // Check Base Class Code
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&BaseClass,FIELD_OFFSET (PCI_COMMON_CONFIG, BaseClass));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n BaseClass =%x\n",BaseClass); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // Check Sub Class Code
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&SubClass,FIELD_OFFSET (PCI_COMMON_CONFIG, SubClass));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n SubClass =%x\n",SubClass); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // Check Proglamming Interface
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&ProgIf,FIELD_OFFSET (PCI_COMMON_CONFIG, ProgIf));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n ProgIf =%x\n",ProgIf); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // check if video card
+ //
+ if ( ( (BaseClass == 0) && (SubClass == 1) && (ProgIf == 0) ) || //S003
+ ( (BaseClass == 3) && (SubClass == 0) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 1) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 0x80) && (ProgIf == 0) ) ) {
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is Video card \n");
+#endif // _X86_DBG_
+ } else {
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is not Video card \n");
+#endif // _X86_DBG_
+ continue;
+ }
+// M001 ---
+
+ //
+ // Get size of ROM
+ //
+
+ ROM_size=0xFFFFFFFF;
+
+#if defined(_X86_DBG_)
+ DbgPrint("ROM size config offset = %x\n",FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+#endif // _X86_DBG_
+ HalpWritePCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ HalpReadPCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+
+#if defined(_X86_DBG_)
+ DbgPrint("\nROM_Size = %0x\n",ROM_size);
+#endif // _X86_DBG_
+
+ if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
+
+
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Set Expansion ROM Base Address & enable ROM
+ //
+
+ PhysAddr.LowPart = 0x000C0000 | PCI_ROMADDRESS_ENABLED;
+
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ //
+ // Enable Memory & I/O spaces in command register
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\nREAD CMD=%0x\n",Cmd);
+#endif // _X86_DBG_
+
+ SetCmd = Cmd|0x3;
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+ // Map Phys C0000000-C00D0000
+ // Create a mapping to the PCI memory space
+ //
+ PhysAddr.HighPart = 1;
+ PhysAddr.LowPart=0;
+
+#if 1
+
+
+ HalpIoMemoryBase= (PVOID)0x40000000;
+#else
+ HalpIoMemoryBase = MmMapIoSpace(PhysAddr, ROM_size,FALSE);
+ if (HalpIoMemoryBase == NULL) {
+#if defined(_X86_DBG_)
+ DbgPrint("\nCan't create mapping to PCI memory space\n");
+#endif // _X86_DBG_
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+ return FALSE;
+ }
+#endif
+ //
+ // Look for PCI option video ROM signature
+ //
+ HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+#if defined(_X86_DBG_)
+ DbgPrint("\nHalpRomBase=%x\n",HalpRomBase);
+#endif // _X86_DBG_
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // Sometimes option ROM and video RAM can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+
+
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+#if defined(_X86_DBG_)
+ DbgPrint("\nROM Short HalpRomBase=%x\n",HalpRomBase);
+#endif // _X86_DBG_
+
+ }
+
+#if 0 // M002
+// M001 +++
+ //
+ // check rom code is INTEL BASE
+ //
+
+ PciDataOffset = *(PUSHORT)(0x400c0000 + 0x18);
+#if defined(_X86_DBG_)
+ DbgPrint("PciDataOffset = %x\n",PciDataOffset);
+#endif // _X86_DBG_
+
+ if ( *(PUCHAR)(0x400c0000 + (ULONG)PciDataOffset + 0x14) == 0 ) {
+// DbgPrint("check PCI rom\n");
+// DbgBreakPoint();
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is intel base rom \n");
+#endif // _X86_DBG_
+ } else {
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is not intel base rom \n");
+#endif // _X86_DBG_
+
+ //
+ // Disable Rom address
+ //
+
+ PhysAddr.LowPart = 0x000C0000;
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ continue;
+ }
+// M001 ---
+#endif // 0 // M002
+
+ //
+ // Io Map.
+ //
+ HalpIoControlBase= (PVOID)0x403f0000;
+
+#if 0 // M001---
+ PhysAddr.LowPart = 0x000C0000;
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+#endif // M001---
+
+#if 0 //706
+ // Found PCI VIDEO ROM.
+ // 1.Map ISA Memory Space
+ // 2.
+#if defined(_X86_DBG_)
+ DbgPrint("\nFound PCI ROM BIOS\n");
+#endif // _X86_DBG_
+
+
+ // 0: rom enable so do PCI
+ // 1: rom disable so do EISA vga
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+#endif
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+// MmUnmapIoSpace ( HalpIoMemoryBase, ROM_size);
+
+ // Not Found So Reset!!.
+ // Delete mapping to PCI memory space
+
+
+#if 1 //706
+ // Found PCI VIDEO ROM.
+ // 1.Map ISA Memory Space
+ // 2.
+#if defined(_X86_DBG_)
+ DbgPrint("\nFound PCI ROM BIOS\n");
+#endif // _X86_DBG_
+
+
+ // 0: rom enable so do PCI
+ // 1: rom disable so do EISA vga
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+#endif
+
+ } // end of if clause
+#if defined(_X86_DBG_)
+ DbgPrint("\n ROM SIZE invalid\n"); //DBGDBG
+#endif // _X86_DBG_
+ } // end of for loop
+#else
+// ROM_size = 0xD0000; // Map to end of option ROM space
+#endif
+
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+#if 1 //tmp 707 // M001
+ // No PCI BIOS SO Search ISA BIOS.
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+
+ HalpIoMemoryBase= (PULONG)0x40000000;
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Look for ISA option video ROM signature
+ //
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+// DbgPrint("check PCI rom\n");
+// DbgBreakPoint();
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ }
+#if defined(_X86_DBG_)
+ DbgPrint("\n EISA ROM BIOS Found \n"); //DBGDBG
+#endif // _X86_DBG_
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ HalpIoControlBase= (PVOID)0x403f0000;
+ return TRUE;
+ }
+#endif
+ //
+ // No video option ROM was found. Delete mapping to PCI memory space.
+ //
+#if defined(_X86_DBG_)
+ DbgPrint("\n 55AA BIOS Not \n"); //DBGDBG
+#endif // _X86_DBG_
+ return FALSE;
+}
+
+//--------------------
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
+ &Context,
+ HalpIoControlBase,
+ HalpIoMemoryBase) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (!HalpInitX86Emulator())
+ return FALSE;
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ HalpEnableInt10Calls = TRUE;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+#endif
+
+ return;
+}
+
+
+//
+// This code came from ..\..\x86new\x86bios.c
+//
+#define LOW_MEMORY_SIZE 0x800
+extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+extern ULONG x86BiosScratchMemory;
+extern ULONG x86BiosIoMemory;
+extern ULONG x86BiosIoSpace;
+
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(HalpRomBase + Offset);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+
+ // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
+ return (PVOID)NULL;
+}
+
+
+VOID HalpCopyROMs(VOID)
+{
+ULONG i;
+PUCHAR ROM_Shadow;
+
+ if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
+ HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
+#if defined(_X86_DBG_)
+ DbgPrint("HalpRomBase=%0x\n",HalpRomBase);
+#endif // _X86_DBG_
+ for (i=0; i<ROM_Length; i++) {
+ *ROM_Shadow++ = ROM_Buffer[i];
+ }
+ }
+}
+
+
+/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
+
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space and the
+// base address of I/O memory space.
+//
+
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+// DbgPrint("read port %x translate %x\n",PortNumber,u.Long);
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+// DbgPrint("write port %x translate %x\n",PortNumber,u.Long);
+ if (DataType == BYTE_DATA) {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n EMU INIT \n"); //DBGDBG
+#endif // _X86_DBG_
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+#if defined(_X86_DBG_)
+ DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
+#endif // _X86_DBG_
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n BIOS INIT \n"); //DBGDBG
+#endif // _X86_DBG_
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+#if defined(_X86_DBG_)
+ DbgPrint("\n Emcall BIOS start \n"); //DBGDBG
+#endif // _X86_DBG_
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+#if defined(_X86_DBG_)
+ DbgPrint("\n Emcall BIOS End \n"); //DBGDBG
+#endif // _X86_DBG_
+ if (Status != XM_SUCCESS) {
+#if defined(_X86_DBG_)
+ DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
+#endif // _X86_DBG_
+ }
+
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halr94a/mips/xxcalstl.c b/private/ntos/nthals/halr94a/mips/xxcalstl.c
new file mode 100644
index 000000000..991432fee
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxcalstl.c
@@ -0,0 +1,302 @@
+// #pragma comment(exestr, "@(#) xxcalstl.c 1.1 95/09/28 18:40:42 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Aug 25 14:21:02 1995 kbnes!kisimoto
+ - change scale factor down range. for 250MHz.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= (Index < 20 ? 1 : 10)) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt0;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the interval timer interrupt.
+ //
+
+#if defined(_DUO_)
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->TimerInterruptAcknowledge.Long);
+
+#else
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+
+#endif
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halr94a/mips/xxclock.c b/private/ntos/nthals/halr94a/mips/xxclock.c
new file mode 100644
index 000000000..c7ec77df5
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxclock.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxclock.c"
diff --git a/private/ntos/nthals/halr94a/mips/xxidle.s b/private/ntos/nthals/halr94a/mips/xxidle.s
new file mode 100644
index 000000000..faf3163a9
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxidle.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxidle.s"
diff --git a/private/ntos/nthals/halr94a/mips/xxinithl.c b/private/ntos/nthals/halr94a/mips/xxinithl.c
new file mode 100644
index 000000000..0c75aae5f
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxinithl.c
@@ -0,0 +1,959 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) xxinithl.c 1.2 95/10/17 01:19:57" ) */
+/*++
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Wed Sep 14 19:38:36 JST 1994 kbnes!kishimoto
+ - HalInitSystem()
+ Define global spin locks used to synchronize
+ various LED operations, and initialize LED spin locks.
+ H001 Fri Oct 14 15:03:38 JST 1994 kbnes!kishimoto
+ - HalInitSystem(),HalpBugCheckCallback(),HalpBusError()
+ Modify to read the 33-bit register.
+ Bacause the InvalidAddress register of R94A is 33-bits long.
+ And original compile errors are modified.
+ H002 Fri Oct 21 14:25:22 JST 1994 kbnes!kishimoto
+ - call HalR94aDebugPrint to display debug infomation.
+ A001 Mon Oct 24 17:19:06 JST 1994 ataka@oa2.kb.nec.co.jp
+ - Call HalpInitBusHandlers
+ H003 Mon Nov 21 22:01:43 1994 kbnes!kishimoto
+ - TEMP TEMP :
+ comment out HalpInitializeX86DisplayAdapter() for R94A BBM
+ M004 Fri Jan 06 10:53:32 JST 1995 kbnes!A.kuriyama
+ - HalpPrintMdl() call
+ H005 Mon Jan 16 02:10:42 1995 kbnes!kishimoto
+ - initialize PCI configuration register spin lock
+ M006 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 17:15:35 JST 1995
+ - add _IPI_LIMIT_ support
+ S007 kuriyama@oa2.kb.nec.co.jp Mon Apr 03 10:31:37 JST 1995
+ - delete PrintMdl ( ifdef _PRINT_MDL_ )
+ S008 kuriyama@oa2.kb.nec.co.jp Mon May 22 02:11:30 JST 1995
+ - add support for esm
+ M009 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 02:53:50 JST 1995
+ - add search NMI interface aread
+ S010 kuriayam@oa2.kb.nec.co.jp Mon Jun 05 04:44:09 JST 1995
+ - NMI interface bug fix
+ M011 kuriyama@oa2.kb.nec.co.jp Fri Jun 16 19:13:45 JST 1995
+ - add support for esm Ecc 1bit/2bit error logging
+ M012 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 10:52:21 JST 1995
+ - add ecc 1bit safty flag
+ M013 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 19:21:44 JST 1995
+ - Merge build 1057 halx86
+ H014 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 14:28:46 1995
+ - Removed IPI_LIMIT, BBMLED code, J94C definitions,
+ and rearrange comments.
+ M015 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:32:18 JST 1995
+ - add for x86bios support
+ H016 kisimoto@oa2.kb.nec.co.jp Tue Sep 5 20:43:22 1995
+ - add initialization of spinlock to support
+ PCI Fast Back-to-back transfer.
+ M017 nishi@oa2.kb.nec.co.jp Tue Sep 18 20:43:22 1995
+ - add Software Power Off, when system panic is occured
+
+ M016 kuriyama@oa2.kbnes.nec.co.jp
+ - add for merge R94A/R94A'/R94D HAL
+
+
+--*/
+
+#include "halp.h"
+/* Start M017 */
+#define HEADER_FILE
+#include "kxmips.h"
+/* End M017 */
+
+
+//
+// M016
+// for Merge R94A/R94A'/R94D HAL
+//
+BOOLEAN HalpUseChipSetWorkaround = TRUE;
+
+//
+// M015
+// Define for x86bios emulator use.
+//
+
+// PCHAR K351UseBios=NULL;
+VOID HalpCopyROMs(VOID);
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpIoControlBase;
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+VOID
+HalpDisplayINT10Setup (
+VOID);
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character );
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+extern PHALP_DISPLAY_CHARACTER HalpDisplayCharacter;
+extern PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup;
+
+//
+// M012
+// Define Ecc safety flags
+//
+
+#define CHECKED 1
+#define NOT_CHECKED 0
+#define RUNNING 1
+#define NOT_RUNNING 0
+
+//
+// M012
+// Define Ecc safety variables
+//
+
+UCHAR HalpAnotherCheckedECC = NOT_CHECKED;
+UCHAR HalpAnotherRunningECC = NOT_RUNNING;
+
+
+//
+// Define forward referenced prototypes.
+//
+
+#if defined(_PRINT_MDL_) // M004,S007
+VOID
+HalpPrintMdl (
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+#endif // _PRINT_MDL_
+
+VOID
+HalpSearchNMIInterface ( // M009
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+ULONG HalpNMIInterfaceAddress = 0;
+
+extern
+VOID // M011
+HalpSetInitDisplayTimeStamp(
+ VOID
+ );
+
+extern
+ULONG // M011
+HalpEccError(
+ IN ULONG EccDiagnostic,
+ IN ULONG MemoryFailed
+ );
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpPCIConfigLock; // H005
+KSPIN_LOCK Ecc1bitDisableLock; // M011
+KSPIN_LOCK Ecc1bitRoutineLock; // M012
+KSPIN_LOCK HalpPCIBackToBackLock; // H016
+KSPIN_LOCK HalpIpiRequestLock;
+
+//
+// Define bug check information buffer and callback record.
+//
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG FailedAddress;
+ ULONG DiagnosticLow;
+ ULONG DiagnosticHigh;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ ULONG FailedAddress;
+ PKPRCB Prcb;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+ LARGE_INTEGER registerLarge; // H001
+
+ UCHAR ModeNow; // M017
+ KIRQL OldIrql; // M017
+ ENTRYLO Pte[2]; // M017
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ PCR->DataBusError = HalpBusError;
+ PCR->InstructionBusError = HalpBusError;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+
+ /* Start M017 */
+ if (Prcb->Number == 0) {
+
+ //
+ // for software controlled power supply.
+ //
+#if defined(_MRCPOWER_)
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT;
+
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ //
+ // Map MRC using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // MRC Mode bit change to 0 ( Power Off interrupt is NMI )
+ //
+ ModeNow = READ_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode,
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode,
+ ModeNow & 0x02,
+ );
+
+ KeLowerIrql(OldIrql);
+
+#endif // _MRCPOWER_
+ }
+ /* End M017*/
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+
+
+ //
+ // M016
+ // Check ChipSet Revision.
+ //
+ // if Revision ==3, This is old chipset. Use Workaround.
+ //
+
+ if (READ_REGISTER_ULONG(&DMA_CONTROL->RevisionLevel.Long) == 3 ) {
+
+ HalpUseChipSetWorkaround = TRUE;
+
+ } else {
+
+ HalpUseChipSetWorkaround = FALSE;
+
+ }
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+#if 0
+ //
+ // M013
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // M013
+ // Set DMA I/O coherency attributes.
+ //
+
+ KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_DUO_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ KeInitializeSpinLock(&HalpIpiRequestLock);
+
+#endif
+
+ KeInitializeSpinLock(&Ecc1bitDisableLock); // M011
+ KeInitializeSpinLock(&Ecc1bitRoutineLock); // M012
+ KeInitializeSpinLock(&HalpPCIConfigLock); // H005
+ KeInitializeSpinLock(&HalpPCIBackToBackLock); // H016
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ // temp
+
+// TmpInitNvram();
+
+#if DBG
+ printNvramData();
+#endif // DBG
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+#if defined(_PRINT_MDL_)
+ HalpPrintMdl(LoaderBlock); // M004,S007
+#endif //_PRINT_MDL
+
+ HalpSearchNMIInterface(LoaderBlock); // M009
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+ }
+
+ //
+ // H001
+ // Clear memory address error registers.
+ //
+
+#if defined(_DUO_)
+
+#if defined(_R94A_)
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ FailedAddress = registerLarge.LowPart;
+
+#else
+
+ FailedAddress = (ULONG)((volatile DMA_REGISTERS *)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; // H001
+
+ //
+ // Initialize interrupts
+ //
+
+ HalpInitializeInterrupts();
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ HalpRegisterInternalBusHandlers (); // M013
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ HalpMapIoSpace();
+
+ HalpSetInitDisplayTimeStamp(); // S008
+
+ HalpCalibrateStall();
+
+ HalpCreateDmaStructures();
+
+ //
+ // M015
+ // for x86bios emulator. bios copy
+ //
+
+ HalpCopyROMs();
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+ //
+ // M014
+ // reset EISA io/memory base for HalCallBios() use.
+ //
+ HalpIoControlBase = HalpEisaControlBase;
+ HalpIoMemoryBase = HalpEisaMemoryBase;
+
+ return TRUE;
+ }
+ }
+}
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+ LARGE_INTEGER registerLarge; // H001
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+#if defined(_DUO_)
+
+#if defined(_R94A_) // H001
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ DumpBuffer->DiagnosticLow = registerLarge.LowPart;
+
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+ return;
+}
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG DiagnosticHigh;
+ ULONG DiagnosticLow;
+ ULONG FailedAddress;
+ LARGE_INTEGER registerLarge; // H001
+
+ //
+ // Bug check specifying the exception code, the virtual address, the
+ // failed memory address, and either the ECC diagnostic registers or
+ // the parity diagnostic registers depending on the platform.
+ //
+
+#if defined(_DUO_)
+
+#if !defined(_R94A_)
+
+ DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+ DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+ DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+
+ // start M011
+ {
+ ULONG returnValue;
+ KIRQL OldIrql;
+
+ //
+ // Call Ecc 1bit/2bit error routine.
+ // if 1bit error return TRUE.(OS run continue)
+ // Otherwise bugcheck.
+ //
+
+ if (DiagnosticHigh & 0x66000000) {
+
+ KeRaiseIrql(HIGH_LEVEL,&OldIrql);
+ returnValue = HalpEccError(DiagnosticHigh, FailedAddress);
+ KeLowerIrql(OldIrql);
+
+ if (returnValue == 2) {
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ FailedAddress,
+ DiagnosticLow,
+ DiagnosticHigh);
+
+ return FALSE;
+ }
+
+ } else { // M012
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ DiagnosticLow = registerLarge.LowPart;
+
+ if (DiagnosticLow & 1) {
+
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ FailedAddress,
+ DiagnosticLow,
+ DiagnosticHigh);
+
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+#if defined(_DUO_)
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+#endif
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+HalpSearchNMIInterface (
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ ULONG FirmwareParmanentCount = 0;
+
+ //
+ // Get the lower bound of the free physical memory and the
+ // number of physical pages by walking the memory descriptor lists.
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ MemoryDescriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if (MemoryDescriptor->MemoryType == MemoryFirmwarePermanent) {
+
+ if (++FirmwareParmanentCount == 2) { // S010
+ HalpNMIInterfaceAddress = MemoryDescriptor->BasePage << PAGE_SHIFT;
+#if DBG
+ DbgPrint("NMI Interface was found!\n");
+ DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType);
+ DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage);
+ DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount);
+#endif // DBG
+ }
+#if DBG
+ DbgPrint("Firmware Parmanent entry was found!\n");
+ DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType);
+ DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage);
+ DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount);
+#endif // DBG
+ }
+ NextMd = MemoryDescriptor->ListEntry.Flink;
+ }
+}
diff --git a/private/ntos/nthals/halr94a/mips/xxinitnt.c b/private/ntos/nthals/halr94a/mips/xxinitnt.c
new file mode 100644
index 000000000..2b57adb0d
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxinitnt.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinitnt.c"
diff --git a/private/ntos/nthals/halr94a/mips/xxipiint.s b/private/ntos/nthals/halr94a/mips/xxipiint.s
new file mode 100644
index 000000000..266246f51
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxipiint.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxipiint.s"
diff --git a/private/ntos/nthals/halr94a/mips/xxmvmem.s b/private/ntos/nthals/halr94a/mips/xxmvmem.s
new file mode 100644
index 000000000..624d77caf
--- /dev/null
+++ b/private/ntos/nthals/halr94a/mips/xxmvmem.s
@@ -0,0 +1,264 @@
+// .ident "@(#) xxmvmem.s 1.1 95/09/28 18:42:46 nec"
+//
+// Stolen from rtl xxmvmem.s this source can be used for r94a
+// beta machine only.
+//
+// 1995.1.5 kbnes!A.Kuriyama
+//
+//
+// TITLE("Compare, Move, Zero, and Fill Memory Support")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// xxmvmem.s
+//
+// Abstract:
+//
+// This module implements functions to compare, move, zero, and fill
+// blocks of memory. If the memory is aligned, then these functions
+// are very efficient.
+//
+// N.B. These routines MUST preserve all floating state since they are
+// frequently called from interrupt service routines that normally
+// do not save or restore floating state.
+//
+// Author:
+//
+// David N. Cutler (davec) 11-Apr-1990
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("View Memory")
+//++
+//
+// PVOID
+// HalViewMemory (
+// IN PVOID Destination,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function zeros memory by first aligning the destination address to
+// a longword boundary, and then zeroing 32-byte blocks, followed by 4-byte
+// blocks, followed by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the memory to zero.
+//
+// Length (a1) - Supplies the length, in bytes, of the memory to be zeroed.
+//
+// Return Value:
+//
+// The destination address is returned as the function value.
+//
+//--
+
+ LEAF_ENTRY_S(HalViewMemory, _TEXT$00)
+
+ move a2,zero // set fill pattern
+ b HalpFillMemory //
+
+
+ SBTTL("Fill Memory")
+//++
+//
+// PVOID
+// HalFillMemory (
+// IN PVOID Destination,
+// IN ULONG Length,
+// IN UCHAR Fill
+// )
+//
+// Routine Description:
+//
+// This function fills memory by first aligning the destination address to
+// a longword boundary, and then filling 32-byte blocks, followed by 4-byte
+// blocks, followed by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the memory to fill.
+//
+// Length (a1) - Supplies the length, in bytes, of the memory to be filled.
+//
+// Fill (a2) - Supplies the fill byte.
+//
+// N.B. The alternate entry memset expects the length and fill arguments
+// to be reversed.
+//
+// Return Value:
+//
+// The destination address is returned as the function value.
+//
+//--
+
+ ALTERNATE_ENTRY(Halmemset)
+
+ move a3,a1 // swap length and fill arguments
+ move a1,a2 //
+ move a2,a3 //
+
+ ALTERNATE_ENTRY(HalFillMemory)
+
+ and a2,a2,0xff // clear excess bits
+ sll t0,a2,8 // duplicate fill byte
+ or a2,a2,t0 // generate fill word
+ sll t0,a2,16 // duplicate fill word
+ or a2,a2,t0 // generate fill longword
+
+//
+// Fill memory with the pattern specified in register a2.
+//
+
+HalpFillMemory: //
+ move v0,a0 // set return value
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu t1,a1,t0 // reduce number of bytes to fill
+ blez t1,60f // if lez, less than 4 bytes to fill
+ move a1,t1 // set number of bytes to fill
+ beq zero,t0,10f // if eq, already aligned
+ lwr t5,0(a0) // fill unaligned bytes
+ addu a0,a0,t0 // align destination address
+
+//
+// Check for 32-byte blocks to fill.
+//
+
+10: and t0,a1,32 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,40f // if eq, no 32-byte blocks to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destintion quadword aligned
+ beq zero,t0,20f // if eq, yes
+ lw t5,0(a0) // store destination longword
+ addu a0,a0,4 // align destination address
+ addu a1,a1,t1 // recompute bytes to fill
+ subu a1,a1,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned.
+//
+
+20: dsll a3,a2,32 // duplicate pattern in upper 32-bits
+ dsrl a2,a3,32 //
+ or a3,a3,a2 //
+ dmtc1 a3,f0 // set pattern value
+ and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,30f // if eq, even number of 32-byte blocks
+
+//
+// Fill one 32-byte block.
+//
+
+ .set noreorder
+ ldc1 f2,0(a0) // fill 32-byte block
+ ldc1 f2,8(a0) //
+ ldc1 f2,16(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ beq a0,t2,40f // if ne, no 64-byte blocks to fill
+ ldc1 f2,-8(a0) //
+ .set reorder
+
+//
+// Fill 64-byte block.
+//
+
+ .set noreorder
+30: ldc1 f2,0(a0) // fill 32-byte block
+ ldc1 f2,8(a0) //
+ ldc1 f2,16(a0) //
+ ldc1 f2,24(a0) //
+ ldc1 f2,32(a0) //
+ ldc1 f2,40(a0) //
+ ldc1 f2,48(a0) //
+ addu a0,a0,64 // advance pointer to next block
+ bne a0,t2,30b // if ne, more 32-byte blocks to fill
+ ldc1 f2,-8(a0) //
+ .set reorder
+
+#endif
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: lw a2,0(a0) // fill 32-byte block
+ lw a2,4(a0) //
+ lw a2,8(a0) //
+ lw a2,12(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ lw a2,-4(a0) //
+ lw a2,-8(a0) //
+ lw a2,-12(a0) //
+ bne a0,t2,20b // if ne, more 32-byte blocks to fill
+ lw a2,-16(a0) //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to fill.
+//
+
+40: and t0,a1,4 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,60f // if eq, no 4-byte block to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 4-byte blocks.
+//
+
+ .set noreorder
+50: addu a0,a0,4 // advance pointer to next block
+ bne a0,t2,50b // if ne, more 4-byte blocks to fill
+ lw t5,-4(a0) // fill 4-byte block
+ .set reorder
+
+//
+// Check for 1-byte blocks to fill.
+//
+
+60: addu t2,a0,a1 // compute ending block address
+ beq zero,a1,80f // if eq, no bytes to fill
+
+//
+// Fill 1-byte blocks.
+//
+
+ .set noreorder
+70: addu a0,a0,1 // advance pointer to next block
+ bne a0,t2,70b // if ne, more 1-byte block to fill
+ lb t5,-1(a0) // fill 1-byte block
+ .set reorder
+
+80: j ra // return
+
+ .end HalViewMemory
diff --git a/private/ntos/nthals/halr94a/sources b/private/ntos/nthals/halr94a/sources
new file mode 100644
index 000000000..eff909afa
--- /dev/null
+++ b/private/ntos/nthals/halr94a/sources
@@ -0,0 +1,131 @@
+!IF 0
+ # pragma comment(exestr, "@(#) NEC(MIPS) sources 1.2 95/10/17 01:15:29" )
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halr94a
+TARGETPATH=\nt\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+# C_DEFINES description.
+#
+# uncomment one for your system.
+#
+# for R94D/R94A/R94A' system
+#
+C_DEFINES=-D_DUO_ -D_R94A_ -DDBCS -D_GLINT60HZ_
+#
+#
+# for R96B/J96B/J96A' system
+#
+# C_DEFINES=-D_DUO_ -D_R94A_ -DDBCS -D_GLINT60HZ_ _MRCDUMP_ _MRCPOWER_
+#
+#
+# for J94D system.
+#
+# C_DEFINES=-D_DUO_ -D_R94A_ -DDBCS -D_GLINT60HZ_ _MRCPOWER_
+#
+
+NT_UP=0
+
+INCLUDES=..\x86new;..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s \
+ mips\r94ainfo.c \
+ mips\r94adbg.c \
+ mips\pcisup.c \
+ mips\r94aio.s \
+ mips\busdat.c \
+ mips\pcibus.c \
+ mips\pciint.c \
+ mips\mipsdat.c \
+ mips\jxusage.c \
+ mips\pcibrd.c \
+ mips\xxmvmem.s \
+ mips\r94anmi.s \
+ mips\esm.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
+
diff --git a/private/ntos/nthals/halr96b/drivesup.c b/private/ntos/nthals/halr96b/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halr96b/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halr96b/hal.rc b/private/ntos/nthals/halr96b/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halr96b/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halr96b/hal.src b/private/ntos/nthals/halr96b/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halr96b/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halr96b/makefile b/private/ntos/nthals/halr96b/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halr96b/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halr96b/makefile.inc b/private/ntos/nthals/halr96b/makefile.inc
new file mode 100644
index 000000000..e23846e2c
--- /dev/null
+++ b/private/ntos/nthals/halr96b/makefile.inc
@@ -0,0 +1,36 @@
+#pragma comment(exestr, "@(#) NEC(MIPS) makefile.inc 1.3 95/10/17 01:16:29" )
+#
+# Revision History
+#
+
+mips\cacherr.s: ..\halfxs\mips\cacherr.s
+
+mips\j4cache.s: ..\halfxs\mips\j4cache.s
+
+mips\j4flshbf.s: ..\halfxs\mips\j4flshbf.s
+
+mips\j4prof.c: ..\halfxs\mips\j4prof.c
+
+mips\jxdmadsp.s: ..\halfxs\mips\jxdmadsp.s
+
+mips\jxmapio.c: ..\halfxs\mips\jxmapio.c
+
+mips\jxmaptb.c: ..\halfxs\mips\jxmaptb.c
+
+mips\jxport.c: ..\halfxs\mips\jxport.c
+
+mips\x4tb.s: ..\halfxs\mips\x4tb.s
+
+mips\xxclock.c: ..\halfxs\mips\xxclock.c
+
+mips\xxidle.s: ..\halfxs\mips\xxidle.s
+
+mips\xxinitnt.c: ..\halfxs\mips\xxinitnt.c
+
+mips\xxipiint.s: ..\halfxs\mips\xxipiint.s
+
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halr96b.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halr96b/mips/allstart.c b/private/ntos/nthals/halr96b/mips/allstart.c
new file mode 100644
index 000000000..8363d1dcc
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/allstart.c
@@ -0,0 +1,272 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) allstart.c 1.2 95/10/17 01:17:28" ) */
+/*++
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Mon Oct 17 09:29:01 JST 1994 kbnes!kishimoto
+ -chg function name HalpCreateEisaStructures()
+ changed for HalpCreateEisaPCIStructures()
+ H001 Mon Oct 17 19:09:23 JST 1994 kbnes!kishimoto
+ -del Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ M002 Tue Jan 31 17:51:41 JST 1995 kbnes!A.Kuriyama
+ -add set NMI Handle routine to FW
+ M003 Tue Jan 31 18:41:45 JST 1995 kbnes!A.Kuriyama
+ -add NMI Handle valiable
+ S004 Tue Jan 31 19:05:16 JST 1995 kbnes!A.Kuriyama
+ - compile error clear
+ M005 Fri Feb 17 15:57:02 JST 1995 kbnes!A.Kuriyama
+ - set NMI routine at KSEG1_BASE
+ S006 Tue Feb 21 21:04:42 JST 1995 kbnes!A.Kuriyama
+ - disable dump nmi untill dump support.
+ M007 Wed Feb 22 11:27:18 JST 1995 kbnes!kuriyama (A)
+ - change NMI dumpflag
+ - add display NMI register
+ M008 Wed Feb 22 14:14:19 JST 1995 kbnes!kuriyama (A)
+ - compile error clear
+ S009 Wed Feb 22 14:34:31 JST 1995 kbnes!kuriyama (A)
+ - warning clear
+ S010 Tue Mar 07 14:13:41 JST 1995 kbnes!kuriyama (A)
+ - warning clear
+ S011 Sat Mar 18 20:19:57 JST 1995 kbnes!kuriyaam (A)
+ - enable dump nmi
+ M012 Sat Mar 18 20:24:58 JST 1995 kbnes!kuriyama (A)
+ - change nmi logic
+ M013 Mon May 08 23:20:10 JST 1995 kbnes!kuriyama (A)
+ - EISA/PCI interrupt change to CPU-A on MultiProcessor
+ S014 kuriyama@oa2.kb.nec.co.jp Mon May 22 03:55:08 JST 1995
+ - Set Panic Flag for esm
+ M015 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 03:08:04 JST 1995
+ - Change NMI interface address to HalpNMIInterfaceAddress
+ S016 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 04:49:24 JST 1995
+ - NMI Interface bug fix
+ M017 kuriyama@oa2.kb.nec.co.jp Fri Jun 16 20:26:09 JST 1995
+ - add Enable Ecc 1bit error exception
+ S018 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 13:23:19 JST 1995
+ - add set dump switch flag for esm
+ M019 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 18:50:42 JST 1995
+ - change ecc 1bit was not set enable
+ if nvram is not initialize.
+ M020 kisimoto@oa2.kb.nec.co.jp Fri Aug 11 14:11:16 1995
+ - clear M013. delete test code, dump switch interface.
+
+ S021 kuriyama@oa2.kbnes.nec.co.jp Tue Oct 17 00:51:42 JST 1995
+ - change length of NMISave
+
+--*/
+
+#include "halp.h"
+#include "esmnvram.h" // M019
+#include <stdio.h> // S010
+
+ULONG HalpNMIFlag = 0;
+ULONG HalpDumpNMIFlag = 0; // S006, M008
+ULONG HalpNMISave0[0x80 / 4]; // S021
+ULONG HalpNMISave1[0x80 / 4]; // S021
+
+extern ULONG HalpNMIInterfaceAddress;
+
+VOID
+HalpNMIDispatch(
+ VOID
+ );
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ //
+ // M002,M005,M015,S016,M020
+ // set NMI Handle routine to firmware interface.
+ //
+
+ if (HalpNMIInterfaceAddress) {
+ *(PVOID *)(KSEG0_BASE|HalpNMIInterfaceAddress) = (PVOID)(KSEG1_BASE | (ULONG)HalpNMIDispatch);
+ }
+
+ //
+ // M017,M019
+ // Enable and clear ECC 1bit error.
+ //
+
+ {
+ ULONG DataWord;
+ KIRQL OldIrql;
+ UCHAR dataBuf[36];
+ UCHAR tempBuf[24];
+
+ #define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+ #define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+ #define NVRAM_VALID 3
+ #define NVRAM_MAGIC 0xff651026
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ KeRaiseIrql(HIGH_LEVEL,&OldIrql);
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+ DataWord =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.LowPart;
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.LowPart =
+ 0xffddffff & DataWord;
+ KeFlushWriteBuffer();
+
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+ KeLowerIrql(OldIrql);
+ }
+
+ }
+
+ //
+ // If the number of processors in the host configuration is one,
+ // then connect EISA interrupts to that processor zero. Otherwise,
+ // connect EISA interrupts to processor one.
+ //
+
+ if (**((PULONG *)(&KeNumberProcessors)) == 1) {
+ return HalpCreateEisaStructures();
+
+#if defined(_INT_LIMIT_)
+ } else if (PCR->Number == 0) {
+#else
+ } else if (PCR->Number == 1) {
+#endif // _INT_LIMIT_
+ return HalpCreateEisaStructures();
+
+ } else {
+ return TRUE;
+ }
+}
+
+VOID
+HalpNMIInterrupt(
+ ULONG DumpStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine was called when dump swich was pressed or Fatal NMI occued.
+ We call KeBugCheckEx() in order to Dump.
+
+Arguments:
+
+ DumpStatus: Dump Switch Status
+
+ 0 Dump Switch was not pressed.
+ 1 Dump Switch was pressed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG NMISource;
+ ULONG MemoryFailed;
+ LARGE_INTEGER InvalidAddressValue;
+ LARGE_INTEGER EccDiagnosticValue;
+ UCHAR Buffer[100];
+
+ HalpChangePanicFlag(16, (UCHAR)(0x01 | (4 * DumpStatus)), 0x10); // S014,S018
+
+ //
+ // M007,M012
+ // Check DumpStatus.and Display NMI status.
+ //
+
+ if (DumpStatus == 1) {
+ HalDisplayString("HAL:Dump Switch Pressed!\n");
+ } else {
+ HalDisplayString("HAL:NMI occured\n");
+ }
+
+ //
+ // Display NMI registers
+ //
+
+ NMISource = READ_REGISTER_ULONG(&DMA_CONTROL->NmiSource.Long);
+ sprintf(Buffer, "HAL:NmiSource register = %x\n",NMISource);
+ HalDisplayString((UCHAR *)Buffer);
+
+ MemoryFailed = READ_REGISTER_ULONG(
+ &((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long);
+ sprintf(Buffer,
+ "HAL:MemoryFailedAddress register = %x\n",
+ MemoryFailed);
+ HalDisplayString((UCHAR *)Buffer);
+
+ READ_REGISTER_DWORD(
+ (PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress,
+ &InvalidAddressValue);
+ sprintf(Buffer,
+ "HAL:Processor Invalid Address register = %x %x\n",
+ InvalidAddressValue.HighPart,InvalidAddressValue.LowPart);
+ HalDisplayString((UCHAR *)Buffer);
+
+ READ_REGISTER_DWORD(
+ (PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic,
+ &EccDiagnosticValue);
+ sprintf(Buffer,
+ "HAL:EccDiagnostic register = %x %x\n",
+ EccDiagnosticValue.HighPart,EccDiagnosticValue.LowPart);
+ HalDisplayString((UCHAR *)Buffer);
+
+ //
+ // M007,M008
+ // call KeBugCheckEx() for dump.
+ //
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,DumpStatus,NMISource,0,0);
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halr96b/mips/busdat.c b/private/ntos/nthals/halr96b/mips/busdat.c
new file mode 100644
index 000000000..1218588b8
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/busdat.c
@@ -0,0 +1,1231 @@
+// #pragma comment(exestr, "@(#) busdat.c 1.1 95/09/28 15:30:19 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Jun 30 02:57:29 1995 kbnes!kisimoto
+ - Merge build 1057
+ H002 Sat Jul 1 19:53:41 1995 kbnes!kisimoto
+ - change 'Base' and 'Limit' value on Internal
+
+--*/
+
+#include "halp.h"
+#include "string.h" // H001
+
+UCHAR HalName[] = "NEC MIPS HAL"; // H001
+
+VOID HalpInitializePciBus (VOID); // H001
+VOID HalpInitOtherBuses (VOID);
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#if !defined(_R94A_)
+ULONG HalpcGetCmosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpcSetCmosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpGetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+ULONG HalpSetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+#endif // !_R94A_
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// Prototype for system bus handlers
+//
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+#if defined(_R94A_) // H001
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+#endif
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+NTSTATUS
+HalpHibernateHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+HalpResumeHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+#ifdef MCA
+//
+// Default functionality of MCA handlers is the same as the Eisa handlers,
+// just use them
+//
+
+#define HalpGetMCAInterruptVector HalpGetEisaInterruptVector
+#define HalpAdjustMCAResourceList HalpAdjustEisaResourceList;
+
+HalpGetPosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+#endif
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ // H001: kugi Internal Bus was called with bus-no. 2, We have no idea.
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 1, // Internal BusNumber 1
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+// Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF; // H001
+ Bus->BusAddresses->IO.Limit = 0xFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0; // H001
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ //
+ // start H001, H002
+ // configurate the bus specific data
+ //
+
+ switch(InterfaceType) {
+
+ case Internal:
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->LowPart
+ = 0x80000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0x800FFFFF;
+ Bus->BusAddresses->Memory.SystemBase
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->LowPart
+ = 0x80000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
+ = 0x800FFFFF;
+ Bus->BusAddresses->IO.SystemBase
+ = 0x00000000;
+ break;
+
+ case Eisa:
+ Bus->BusAddresses->Memory.Base = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x03FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_VERSION2_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = EISA_MEMORY_VERSION2_HIGH;
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+
+ case Isa:
+ Bus->BusAddresses->Memory.Base = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x00FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_VERSION2_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = EISA_MEMORY_VERSION2_HIGH;
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+
+ case PCIBus:
+ Bus->BusAddresses->Memory.Base = 0x04000000; // from 64MB
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0xFFFFFFFF; // up to 4GB
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = PCI_MEMORY_PHYSICAL_BASE_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = PCI_MEMORY_PHYSICAL_BASE_HIGH;
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = PCI_CONTROL_PHYSICAL_BASE;
+ break;
+ }
+ }
+
+ return Bus;
+}
+
+
+#if !defined(_R94A_)
+
+//
+// C to Asm thunks for CMos
+//
+
+ULONG HalpcGetCmosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ // bugbug: this interface should be rev'ed to support non-zero offsets
+ if (Offset != 0) {
+ return 0;
+ }
+
+ return HalpGetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length);
+}
+
+
+ULONG HalpcSetCmosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ // bugbug: this interface should be rev'ed to support non-zero offsets
+ if (Offset != 0) {
+ return 0;
+ }
+
+ return HalpSetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length);
+}
+
+#endif // !_R94A_
+
+#if defined(_R94A_)
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+#if 0 // H001: support next version
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+#endif
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Internal // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Affinity = HalpEisaBusAffinity;
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ *Affinity = HalpEisaBusAffinity;
+ *Irql = EISA_DEVICE_LEVEL;
+
+ return(BusInterruptVector + PCI_VECTORS);
+}
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler, // H001
+ IN PBUS_HANDLER RootHandler, // H001
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ PAGED_CODE (); // H001
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+// from ixsysbus.c
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ //
+ //
+ // PCI Translate Bus Address workaround
+ //
+ //
+
+ if (((BusHandler->InterfaceType == PCIBus)) &&
+ (*AddressSpace == 0) &&
+ (BusAddress.QuadPart >= 0) &&
+ (BusAddress.QuadPart <= 0xffffffff )) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + 0x100000000;
+ return TRUE;
+ }
+
+
+ return FALSE;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ *Affinity = 1;
+ *Irql = (KIRQL)BusInterruptLevel;
+
+ if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision) == 0 ){
+
+ //
+ // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
+ // Enable register is zero origin.
+ //
+ // N.B. This obstruction is limiteded to beta-version of STORM chipset.
+ //
+
+ return(BusInterruptVector + DEVICE_VECTORS);
+
+ }else{
+
+ return(BusInterruptVector);
+
+ }
+}
+
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's in the 640k - 1m
+ // range then (for compatibility) try translating it on the
+ // Internal bus for
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 0 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0xA0000 &&
+ BusAddress.LowPart < 0xFFFFF) {
+
+ Status = HalTranslateBusAddress (
+ Internal,
+ 0,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+BOOLEAN
+HalpTranslateIsaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's memory space
+ // then we allow the translation as it would occur on it's
+ // corrisponding EISA bus. We're allowing this because
+ // many VLBus drivers are claiming to be ISA devices.
+ // (yes, they should claim to be VLBus devices, but VLBus is
+ // run by video cards and like everything else about video
+ // there's no hope of fixing it. (At least according to
+ // Andre))
+ //
+
+ if (Status == FALSE && *AddressSpace == 0) {
+ Status = HalTranslateBusAddress (
+ Eisa,
+ BusHandler->BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+#endif // _R94A_
diff --git a/private/ntos/nthals/halr96b/mips/cacherr.s b/private/ntos/nthals/halr96b/mips/cacherr.s
new file mode 100644
index 000000000..0b3cdf5ce
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/cacherr.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\cacherr.s"
diff --git a/private/ntos/nthals/halr96b/mips/cirrus.h b/private/ntos/nthals/halr96b/mips/cirrus.h
new file mode 100644
index 000000000..d827568cf
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/cirrus.h
@@ -0,0 +1,281 @@
+// #pragma comment(exestr, "@(#) cirrus.h 1.1 95/09/28 15:31:10 nec")
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cirrus.h
+
+Abstract:
+
+ This module contains the definitions for the code that implements the
+ Cirrus Logic VGA 6410/6420/542x device driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Miniport Driver Interface
+ *
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ * L002 1993.10.21 Kuroki
+ *
+ * - Warniing clear
+ *
+ * S003 1993.1.13 kbnes!A.Kuriyama
+ *
+ * - VGA Address was changed
+ *
+ */
+
+//
+// Change Ushort to Uchar, because R96 is mips machine.
+//
+
+
+//
+// Base address of VGA memory range. Also used as base address of VGA
+// memory when loading a font, which is done with the VGA mapped at A0000.
+//
+
+/* START L001 */
+
+#define LA_MASK 0xE /* S003 */
+#define MEM_VGA (LA_MASK << 20)
+#define MEM_VGA_SIZE 0x100000
+
+/* END L001 */
+
+//
+// Port definitions for filling the ACCSES_RANGES structure in the miniport
+// information, defines the range of I/O ports the VGA spans.
+// There is a break in the IO ports - a few ports are used for the parallel
+// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped
+// so all VGA ports are in one address range.
+//
+
+#define VGA_BASE_IO_PORT 0x000003B0
+#define VGA_START_BREAK_PORT 0x000003BB
+#define VGA_END_BREAK_PORT 0x000003C0
+#define VGA_MAX_IO_PORT 0x000003DF
+
+//
+// VGA port-related definitions.
+//
+
+//
+// VGA register definitions
+//
+ // ports in monochrome mode
+#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and
+#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode
+#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port
+ // in mono mode
+#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read
+ // port in mono mode
+#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO
+ // Register to read to reset
+ // Attribute Controller index/data
+#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and
+#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port
+ // for writes, but only Address is
+ // readable at 0x010
+#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is
+ // readable here
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write
+ // port
+#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read
+ // port
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the
+ // entire VGA subsystem
+#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and
+#define SEQ_DATA_PORT 0x0015 // Data registers
+#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg
+#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg,
+ // write-only
+#define DAC_STATE_PORT 0x0017 // DAC state (read/write),
+ // read-only
+#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg
+#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg
+#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port
+#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read
+ // port
+#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address
+#define GRAPH_DATA_PORT 0x001F // and Data registers
+
+ // ports in color mode
+#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and
+#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode
+#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port
+#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read
+ // port in color mode
+#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR
+ // Register to read to reset
+ // Attribute Controller index/data
+ // toggle in color mode
+
+//
+// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed
+// VGA registers.
+//
+
+#define CRTC_ADDRESS_MONO_OFFSET 0x04
+#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A
+#define ATT_ADDRESS_OFFSET 0x10
+#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12
+#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13
+#define SEQ_ADDRESS_OFFSET 0x14
+#define DAC_PIXEL_MASK_OFFSET 0x16
+#define DAC_STATE_OFFSET 0x17
+#define DAC_ADDRESS_WRITE_OFFSET 0x18
+#define GRAPH_ADDRESS_OFFSET 0x1E
+#define CRTC_ADDRESS_COLOR_OFFSET 0x24
+#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A
+
+// toggle in color mode
+//
+// VGA indexed register indexes.
+//
+
+// CL-GD542x specific registers:
+//
+#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts
+#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad
+#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register
+//
+#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start
+#define IND_CURSOR_END 0x0B // and End registers
+#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location
+#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers
+#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync
+ // End register, which has the bit
+ // that protects/unprotects CRTC
+ // index registers 0-7
+#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC
+#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC
+#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr
+#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr
+#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr
+#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr
+#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq
+#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer
+#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq
+#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in
+ // CRTC
+#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg
+ // in CRTC
+#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start
+ // synchronous reset
+#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end
+ // synchronous reset
+
+//
+// Values for Attribute Controller Index register to turn video off
+// and on, by setting bit 5 to 0 (off) or 1 (on).
+//
+
+#define VIDEO_DISABLE 0
+#define VIDEO_ENABLE 0x20
+
+// Masks to keep only the significant bits of the Graphics Controller and
+// Sequencer Address registers. Masking is necessary because some VGAs, such
+// as S3-based ones, don't return unused bits set to 0, and some SVGAs use
+// these bits if extensions are enabled.
+//
+
+#define GRAPH_ADDR_MASK 0x0F
+#define SEQ_ADDR_MASK 0x07
+
+//
+// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register.
+//
+
+#define CHAIN4_MASK 0x08
+
+//
+// Value written to the Read Map register when identifying the existence of
+// a VGA in VgaInitialize. This value must be different from the final test
+// value written to the Bit Mask in that routine.
+//
+
+#define READ_MAP_TEST_SETTING 0x03
+
+//
+// Default text mode setting for various registers, used to restore their
+// states if VGA detection fails after they've been modified.
+//
+
+#define MEMORY_MODE_TEXT_DEFAULT 0x02
+#define BIT_MASK_DEFAULT 0xFF
+#define READ_MAP_DEFAULT 0x00
+
+
+//
+// Palette-related info.
+//
+
+//
+// Highest valid DAC color register index.
+//
+
+#define VIDEO_MAX_COLOR_REGISTER 0xFF
+
+//
+// Indices for type of memory mapping; used in ModesVGA[], must match
+// MemoryMap[].
+//
+
+typedef enum _VIDEO_MEMORY_MAP {
+ MemMap_Mono,
+ MemMap_CGA,
+ MemMap_VGA
+} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP;
+
+//
+// For a mode, the type of banking supported. Controls the information
+// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking.
+//
+
+typedef enum _BANK_TYPE {
+ NoBanking = 0,
+ NormalBanking,
+ PlanarHCBanking
+} BANK_TYPE, *PBANK_TYPE;
+
+#define CL6410 0x0001
+#define CL6420 0x0002
+#define CL542x 0x0004
+
+// bitfields for the DisplayType
+#define crt 0x0001
+#define panel 0x0002
+#define simulscan 0x0004 // this means both, but is unused for now.
diff --git a/private/ntos/nthals/halr96b/mips/cmdcnst.h b/private/ntos/nthals/halr96b/mips/cmdcnst.h
new file mode 100644
index 000000000..ea2bba221
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/cmdcnst.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdcnst.h
+
+Abstract:
+
+ This is the command string interpreter definitions
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ This module is same file on Cirrus Minport Driver.
+
+Revision History:
+
+--*/
+
+//--------------------------------------------------------------------------
+// Definition of the set/clear mode command language.
+//
+// Each command is composed of a major portion and a minor portion.
+// The major portion of a command can be found in the most significant
+// nibble of a command byte, while the minor portion is in the least
+// significant portion of a command byte.
+//
+// maj minor Description
+// ---- ----- --------------------------------------------
+// 00 End of data
+//
+// 10 in and out type commands as described by flags
+// flags:
+//
+// xxxx
+// ||||
+// |||+-------- unused
+// ||+--------- 0/1 single/multiple values to output (in's are always
+// |+---------- 0/1 8/16 bit operation single)
+// +----------- 0/1 out/in instruction
+//
+// Outs
+// ----------------------------------------------
+// 0 reg:W val:B
+// 2 reg:W cnt:W val1:B val2:B...valN:B
+// 4 reg:W val:W
+// 6 reg:W cnt:W val1:W val2:W...valN:W
+//
+// Ins
+// ----------------------------------------------
+// 8 reg:W
+// a reg:W cnt:W
+// c reg:W
+// e reg:W cnt:W
+//
+// 20 Special purpose outs
+// 00 do indexed outs for seq, crtc, and gdc
+// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 01 do indexed outs for atc
+// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 02 do masked outs
+// indexreg:W andmask:B xormask:B
+//
+// F0 Nop
+//
+//---------------------------------------------------------------------------
+
+// some useful equates - major commands
+
+#define EOD 0x000 // end of data
+#define INOUT 0x010 // do ins or outs
+#define METAOUT 0x020 // do special types of outs
+#define NCMD 0x0f0 // Nop command
+
+
+// flags for INOUT major command
+
+//#define UNUSED 0x01 // reserved
+#define MULTI 0x02 // multiple or single outs
+#define BW 0x04 // byte/word size of operation
+#define IO 0x08 // out/in instruction
+
+// minor commands for metout
+
+#define INDXOUT 0x00 // do indexed outs
+#define ATCOUT 0x01 // do indexed outs for atc
+#define MASKOUT 0x02 // do masked outs using and-xor masks
+
+
+// composite inout type commands
+
+#define OB (INOUT) // output 8 bit value
+#define OBM (INOUT+MULTI) // output multiple bytes
+#define OW (INOUT+BW) // output single word value
+#define OWM (INOUT+BW+MULTI) // output multiple words
+
+#define IB (INOUT+IO) // input byte
+#define IBM (INOUT+IO+MULTI) // input multiple bytes
+#define IW (INOUT+IO+BW) // input word
+#define IWM (INOUT+IO+BW+MULTI) // input multiple words
diff --git a/private/ntos/nthals/halr96b/mips/esm.c b/private/ntos/nthals/halr96b/mips/esm.c
new file mode 100644
index 000000000..f15acb3c6
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/esm.c
@@ -0,0 +1,1182 @@
+// #pragma comment(exestr, "@(#) esm.c 1.1 95/09/28 15:31:51 nec")
+/*++
+
+Copyright (c) 1995 Kobe NEC Software
+
+Module Name:
+
+ esm.c
+
+Abstract:
+
+ This module implements the ESM service routine
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ L001 kuriyama@oa2.kb.nec.co.jp Thu Jun 15 14:57:14 JST 1995
+ -Change HalpEccError() for support J94C ECC error
+
+ M002 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 14:31:57 JST 1995
+ - add ecc 1bit safety flag
+
+ M003 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 20:40:52 JST 1995
+ - add serialize ecc 1bit routine
+
+ S004 kuriyama@oa2.kb.nec.co.jp Fri Jun 23 16:55:12 JST 1995
+ - bug fix ecc 2bit error
+--*/
+#include "halp.h"
+#include "esmnvram.h"
+#include "bugcodes.h"
+#include "stdio.h"
+
+//
+// define offset.
+//
+
+#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr)
+#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest)
+#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr)
+#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest)
+#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr)
+#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest)
+
+
+#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description)
+#define TIME_STAMP_SIZE 14
+
+//
+// define value
+//
+
+#define NVRAM_VALID 3
+#define NVRAM_MAGIC 0xff651026
+#define ECC_LOG_VALID_FLG 1
+
+// L001++
+#define STORM_ECC_1BIT_ERROR 1
+#define STORM_ECC_2BIT_ERROR 2
+#define STORM_OTHER_ERROR 0
+// L001---
+
+//#define SDCR_SET0_ADDR 0xb9100030
+//#define SDCR_SET1_ADDR 0xb9120030
+
+#define STRING_BUFFER_SIZE 512
+
+#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10
+
+// M002 +++
+
+//
+// Define Ecc safety flags
+//
+
+#define CHECKED 1
+#define NOT_CHECKED 0
+#define RUNNING 1
+#define NOT_RUNNING 0
+// M002 ---
+
+//
+// Define global variable. This variable use in display string into nvram.
+//
+
+ULONG CallCountOfInitDisplay = 0;
+ULONG HalpNvramValid=FALSE;
+USHORT ErrBufferLatest;
+USHORT ErrBufferArea;
+USHORT ErrBufferStart;
+USHORT ErrBufferEnd;
+USHORT ErrBufferCurrent;
+ULONG HalpPanicFlg=0;
+UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE];
+ULONG HalpNvramStringBufferCounter=0;
+
+// L001+++
+//LONG HalpECC1bitDisableFlag=1; // S001
+//LONG HalpECC1bitDisableTime=0; // S003
+//ULONG HalpECC1bitScfrBuffer=0; // S003
+ULONG HalpEcc1bitCount[2] = {0,0};
+ULONG HalpOldMemoryFailed[2] = {0,0};
+ULONG HalpEcc2bitErrorFlag = 0;
+// L001---
+
+// M002 +++
+
+// ecc 1bit total count
+ULONG HalpEcc1bitTotalCount = 0;
+
+// variables for ecc1bit safety flag
+extern ULONG HalpAnotherRunningECC;
+extern ULONG HalpAnotherCheckedECC;
+// M002 ---
+
+
+UCHAR KernelPanicMessage[]="*** STOP: 0x"; // S002
+
+//
+// Define macro
+//
+#if 0
+#define GET_PADDR(addr,sts2,SicSet) { \
+ (addr) = ( ( ((PSTS2_REGISTER)&(sts2) )->COL0_9 << 4 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW0_9 << 14 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->SIMN << 24 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->COL10 << 25 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW10 << 26 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->ARE << 27 ) \
+ + ( (SicSet) << 30 ) ); \
+}
+#endif // 0
+
+#define GET_TIME(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ HalQueryRealTimeClock( &timeBuffer ); \
+ sprintf( (Buffer), \
+ "%04d%02d%02d%02d%02d%02d", \
+ timeBuffer.Year, \
+ timeBuffer.Month, \
+ timeBuffer.Day, \
+ timeBuffer.Hour, \
+ timeBuffer.Minute, \
+ timeBuffer.Second \
+ ); \
+}
+
+// S002, S003 vvv
+#if 0
+#define NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long,buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+
+#define DONT_NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long, \
+ buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+#endif // 0
+// S002, S003 ^^^
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is initialize variable of use when write display data in
+ HalDisplayString into NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SYSTEM_ERR_AREA_INFO infoBuf;
+ UCHAR recordFlg;
+ UCHAR buf[8];
+ UCHAR buf2[8];
+
+ CallCountOfInitDisplay++;
+ if(CallCountOfInitDisplay == 1){
+
+ //
+ // Check NVRAM status
+ //
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 );
+
+ if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){
+ HalpNvramValid=FALSE;
+ return;
+ }
+
+ HalpNvramValid=TRUE;
+
+ //
+ // Get log area infomation.
+ //
+
+ HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ &infoBuf);
+
+ ErrBufferLatest = infoBuf.offset_latest;
+
+ HalNvramRead( infoBuf.offset_latest, 1, &recordFlg);
+
+ //
+ // Check current record flg.
+ //
+
+ if( (recordFlg & 0x01) == 1 ) {
+ infoBuf.offset_latest += infoBuf.size_rec;
+ if( infoBuf.offset_latest >=
+ infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){
+ infoBuf.offset_latest = infoBuf.offset_systemerr;
+ }
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &infoBuf.offset_latest);
+ }
+
+ //
+ // initialize variable. this value use log area access.
+ //
+
+ ErrBufferArea = infoBuf.offset_latest;
+ ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE;
+ ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1;
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // status flg set.
+ //
+
+ HalpPanicFlg = 0;
+
+ recordFlg = 0x11;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ //
+ // buffer initialize.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else {
+
+ //
+ // start Panic log.
+ //
+
+ HalpChangePanicFlag( 1, 1, 0);
+ }
+}
+
+// L001 +++
+
+UCHAR
+HalpFindMemoryGroup(
+ IN ULONG MemoryFailed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds MemoryGroup of MemoryFaled address
+
+Arguments:
+
+ MemoryFailed - MemoryFailed Register value
+
+
+Return Value:
+
+ if MemoryFaied is within any Goup, return MemoryGroup Number.
+
+ Otherwise, return 0xff
+
+--*/
+
+{
+ UCHAR returnValue = 0xff;
+ UCHAR i;
+ ULONG startAddr;
+ ULONG length;
+ ULONG simmType;
+ ULONG dataWord;
+
+ //
+ // find MemoryGroup from MemoryGroup[0:3] register.
+ //
+ // MemoryGroup[0:3] register
+ //
+ // [31] Reserved
+ // [30:22] Starting address
+ // [21:04] Reserved
+ // [03:02] SIMM type
+ // 01=Single-sided 11=Double-sided other=Reserved
+ // [01:00] SIMM size
+ // 00= 1M 01=4M 10=16M 11=64M SIMM
+ //
+ // note: 1 memory group is have 4 SIMM's
+ //
+
+ for (i = 0; i < 4; i++) {
+ dataWord = READ_REGISTER_ULONG(&DMA_CONTROL->MemoryConfig[i]);
+
+ // check SIMM type is valid
+
+ switch (dataWord & 0xc) {
+
+ case 4:
+ simmType = 1;
+ break;
+
+ case 0xc:
+ simmType = 2;
+ break;
+
+ default:
+ simmType = 3;
+ }
+
+ if (simmType == 3) {
+ continue;
+ }
+
+ // compute amount of MemoryGoup SIMM length;
+
+ length = (0x400000 << ((dataWord & 3) * 2)) * simmType;
+
+ // compute MemoryGoup SIMM start address;
+
+ startAddr = dataWord & 0x7fc00000;
+
+ // check if MemoryFailed is within this MemoryGroup
+
+ if ( (startAddr <= MemoryFailed)
+ && (MemoryFailed < (length + startAddr))) {
+ returnValue = i;
+ break;
+ }
+ }
+ return returnValue;
+
+}
+
+
+ULONG
+HalpEccError(
+ IN ULONG EccDiagnostic,
+ IN ULONG MemoryFailed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine check ecc error and error log put in NVRAM.
+
+Arguments:
+
+ EccDiagnostic - EccDiagnostic Register value
+ MemoryFailed - MemoryFailed Register value
+
+
+Return Value:
+
+ return value is the following error occured.
+ 1: ecc 1bit error.
+ 2: ecc 2bit error.
+ 0: other error.
+
+--*/
+
+{
+ ULONG returnValue;
+ USHORT infoOffset;
+ USHORT writeOffset;
+ ULONG buffer; // S001
+ ULONG i; // S002
+ UCHAR dataBuf[36];
+ UCHAR infoBuf[24];
+ UCHAR tempBuf[24];
+ KIRQL OldIrql;
+ ULONG DataWord;
+ ULONG Number;
+
+ //
+ // Check for Ecc 2bit/1bit error
+ //
+
+ if (EccDiagnostic & 0x44000000) {
+ returnValue = STORM_ECC_2BIT_ERROR;
+ infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET;
+ } else if (EccDiagnostic & 0x22000000) {
+ returnValue = STORM_ECC_1BIT_ERROR;
+ infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET;
+ } else {
+ return 0; // Probably Error bit was disappered.
+ }
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+
+ // S002 vvv
+ switch(returnValue) {
+
+ case STORM_ECC_2BIT_ERROR:
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+
+ // set Flag indicate ECC 2bit error.
+
+ HalpEcc2bitErrorFlag = 1;
+
+ //
+ // Log to NVRAM
+ //
+
+ // check for nvram was valid.
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC2_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0;
+ // Error Address was 16Byte Alined.
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC2_ERR_REC)dataBuf)->syndrome = EccDiagnostic;
+
+ ((pECC2_ERR_REC)dataBuf)->specified_group =
+ HalpFindMemoryGroup(MemoryFailed);
+
+ ((pECC2_ERR_REC)dataBuf)->specified_simm = 0;
+
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC2_ERR_REC),
+ (PVOID)dataBuf);
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+ return returnValue; // S004
+
+ case STORM_ECC_1BIT_ERROR:
+
+ //
+ // If MemoryFailed address
+ // is over 512M Nothing can do.
+ //
+ if ((MemoryFailed & 0xfffffff0) > 0x1fffffff) {
+ return returnValue;
+ }
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ Number = KeGetCurrentPrcb()->Number;
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+// M003 +++
+ //
+ // serialize ecc 1bit logging routine
+ //
+
+ for (;;) {
+ KiAcquireSpinLock(&Ecc1bitRoutineLock);
+ if (HalpEcc1bitCount[!Number] == 0) {
+
+ //
+ // Increment HalpEcc1bitCount
+ //
+
+ HalpEcc1bitCount[Number]++;
+ KiReleaseSpinLock(&Ecc1bitRoutineLock);
+ break;
+ }
+ KiReleaseSpinLock(&Ecc1bitRoutineLock);
+ }
+// M003 ---
+
+ switch(HalpEcc1bitCount[Number]) {
+
+ case 1:
+
+ HalpEcc1bitTotalCount++; // M002
+
+
+ HalpOldMemoryFailed[Number] = MemoryFailed;
+
+ //
+ // ReWrite error address
+ // if error address is over 512M
+ // Nothing can do.
+ //
+
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+
+ // disable ecc 1bit error again.
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+
+ DataWord = READ_REGISTER_ULONG(
+ KSEG1_BASE
+ | (MemoryFailed & 0xfffffff0)
+ );
+ WRITE_REGISTER_ULONG(
+ KSEG1_BASE
+ | (MemoryFailed & 0xfffffff0),
+ DataWord
+ );
+
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+
+ //
+ // Wait 20 us.
+ //
+
+ KeStallExecutionProcessor(20);
+
+ //
+ // Enable and clear ECC 1bit error.
+ //
+
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00cc0000;
+ KeFlushWriteBuffer();
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+
+ //
+ // ReRead error address
+ // if error address is over 512M
+ // Nothing can do.
+ //
+ // if Ecc 1bit error occur again , DataBusError will occur.
+ //
+
+ DataWord = READ_REGISTER_ULONG(
+ KSEG1_BASE
+ | (MemoryFailed & 0xfffffff0)
+ );
+
+ // decrement ecc 1bit count
+
+ HalpEcc1bitCount[Number]--;
+
+ return(returnValue);
+
+ case 2:
+
+ if (HalpOldMemoryFailed[Number] != MemoryFailed) {
+ break;
+ }
+ if (MemoryFailed & 2) {
+
+ // if multi error
+ // nothing can do.
+
+ break;
+ }
+
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+
+ //
+ // Search for wheather error address was already logged
+ //
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) {
+ HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)->
+ size_rec * i
+ +((pECC1_ERR_AREA_INFO)infoBuf)->
+ offset_1biterr),
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ if ( ((MemoryFailed & 0xfffffff0)
+ == ((pECC1_ERR_REC)dataBuf)->err_address) &&
+ ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) {
+ break;
+ }
+ }
+
+ if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ break;
+ }
+
+ //
+ // Log to NVRAM
+ //
+
+ // check for nvram was valid.
+
+ ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC1_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0;
+ // Error Address was 16Byte Alined.
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC1_ERR_REC)dataBuf)->syndrome = EccDiagnostic;
+
+ ((pECC1_ERR_REC)dataBuf)->specified_group =
+ HalpFindMemoryGroup(MemoryFailed);
+
+ ((pECC1_ERR_REC)dataBuf)->specified_simm = 0;
+
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+
+
+ // disable ecc 1bit error again.
+
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00ee0000;
+ KeFlushWriteBuffer();
+
+ // decrement ecc 1bit count
+
+ HalpEcc1bitCount[Number]--;
+
+ return(returnValue);
+ }
+
+ //
+ // Enable and clear ECC 1bit error.
+ //
+
+ KiAcquireSpinLock(&Ecc1bitDisableLock);
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
+ EccDiagnostic.u.LargeInteger.LowPart
+ = 0x00cc0000;
+ KeFlushWriteBuffer();
+ KiReleaseSpinLock(&Ecc1bitDisableLock);
+
+
+ // decrement ecc 1bit count
+
+ HalpEcc1bitCount[Number]--;
+
+ return(returnValue);
+ }
+}
+
+// L001 ---
+
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ )
+{
+ UCHAR buf[24];
+
+ //
+ // Set time stamp on initialize display.
+ //
+
+ if(HalpNvramValid == TRUE) {
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+ }
+}
+
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ )
+{
+ UCHAR recordFlg;
+
+ if(HalpNvramValid == TRUE) {
+ recordFlg = 0;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest );
+ }
+}
+
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ )
+{
+ UCHAR recordFlg;
+ UCHAR buf[24];
+
+ if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) {
+ return;
+ }
+
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &ErrBufferArea);
+
+ //
+ // initialize currernt buffer address
+ //
+
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // set panic flag
+ //
+
+ HalNvramRead( ErrBufferArea, 1, &recordFlg );
+ recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+
+ //
+ // set new flag of panic level
+ //
+
+ HalpPanicFlg = NewPanicFlg;
+
+ //
+ // initialize log buffer.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+}
+
+
+// S002 vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ )
+{
+ if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) {
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character;
+ }
+}
+
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ )
+{
+ ULONG i;
+
+ //
+ // Initialize buffer
+ //
+
+ for(i=0; i<STRING_BUFFER_SIZE; i++) {
+ HalpNvramStringBuffer[i] = 0;
+ }
+
+ HalpNvramStringBufferCounter=0;
+
+ //
+ // set string position
+ //
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Column;
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Row;
+}
+
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // if data size is zero, when return
+ //
+
+ if( HalpNvramStringBufferCounter <= 2 ) {
+ return;
+ }
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]='\0';
+
+ //
+ // check panic message
+ //
+
+ for( count=0; ; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != HalpNvramStringBuffer[count+2] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for( count=2; ; count++) {
+ if( HalpNvramStringBuffer[count] == '\0' ){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 2 < ErrBufferEnd ) {
+ HalNvramWrite( ErrBufferCurrent, count, HalpNvramStringBuffer );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( (count + 2 > ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count );
+ }
+ ErrBufferCurrent++;
+ if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+
+#if 0
+VOID
+HalpStringIntoNvram(
+ IN ULONG Column,
+ IN ULONG Row,
+ IN PUCHAR String
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // check panic message
+ //
+
+ for(count=0; 1; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != String[count] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for(count=0;;count++) {
+ if(String[count]=='\0'){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 4 < ErrBufferEnd ) {
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+ HalNvramWrite( ErrBufferCurrent, count, String );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( count + 4 > ErrBufferEnd - ErrBufferStart ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, String+count );
+ }
+ ErrBufferCurrent++;
+ if(String[count]=='\0') {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+#endif
+// S002 ^^^
+
+
+//
+// test code
+//
+
+int
+printNvramData(void)
+{
+ UCHAR buf[256];
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag), 1, buf );
+ DbgPrint("Nvram Flag: 0x%02lx\n", buf[0]);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->when_formatted), 14, buf );
+ buf[14]=0;
+ DbgPrint("Nvram TimeStamp: %s\n", buf);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err),
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC1: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC1: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC1: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC1: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err),
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC2: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC2: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC2: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC2: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->system_err),
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram SYSTEM: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram SYSTEM: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram SYSTEM: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram SYSTEM: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ return(0);
+}
+
+
+int
+TmpInitNvram(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0xff;
+ for(i=0; i<8*1024; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 4, (PUCHAR)&i);
+
+ //
+ // Make 1bit err log info
+ //
+
+ ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768;
+ ((pECC1_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC1_ERR_AREA_INFO)buf)->num_rec=16;
+ ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768;
+
+ ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0;
+
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768; i<768+25*16; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make 2bit err log info
+ //
+
+ ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400;
+ ((pECC2_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC2_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400;
+
+ ((pECC2_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768+400; i<768+400+25*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make system err log info
+ //
+
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280;
+
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=1280; i<1280+512*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ return(0);
+}
+
diff --git a/private/ntos/nthals/halr96b/mips/esmnvram.h b/private/ntos/nthals/halr96b/mips/esmnvram.h
new file mode 100644
index 000000000..2392671e9
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/esmnvram.h
@@ -0,0 +1,688 @@
+// #pragma comment(exestr, "@(#) esmnvram.h 1.1 95/09/28 15:32:22 nec")
+
+/****************************************************************
+ ******* Copyright (C) 1994 NEC Corporation *******
+ ****************************************************************/
+
+/*******
+
+ File Name:
+
+ envram.h
+
+ Abstract:
+
+ This module contains the definitions for the extended NVRAM.
+
+ Author:
+
+ Takehiro Ueda (tueda@oa2.kb.nec.co.jp) 12/22/1994
+
+ Modification History:
+
+ - M000 12/22/94 -
+ created.
+
+*******/
+
+
+
+/*******************************************************************************
+ ******** NVRAM¡Ê8K¥Ð¥¤¥È¡Ë¤ÎÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤ò°Ê²¼¤Ëµ­½Ò¤¹¤ë¡£ ********
+ *******************************************************************************
+ *
+ * S001 11/22/94
+ * ¥ì¥³¡¼¥É¤ÎÍ­¸ú/̵¸ú¥Õ¥é¥°¡¢Check̤/ºÑ¥Õ¥é¥°¤ò³Æ¥ì¥³¡¼¥É¤ÎÀèƬ¤Ë¤ª¤¯¤«
+ * ¤Þ¤È¤á¤Æ¥ì¥³¡¼¥É¥ê¡¼¥¸¥ç¥ó¤ÎÀèƬ¤Ë¤ª¤¯¤«¤Ç¡¢¥ì¥³¡¼¥É¤Î½èÍýÊýË¡¤¬ÊѤï¤Ã¤Æ
+ * ¤¯¤ë¡£¸å¼Ô¤Ï¥é¥ó¥À¥à¥¢¥¯¥»¥¹¡¢Á°¼Ô¤Ï¥·¡¼¥±¥ó¥·¥ã¥ë¥¢¥¯¥»¥¹¤Ë¤à¤¯¡£
+ * º£²ó¤ÏÁ°¼Ô¤òºÎÍÑ¡£
+ *
+ * ¹Ô¤ÎÀèƬ¤Ë¤¢¤ë¿ô»ú¤Ï³ä¤êÅö¤Æ¤ë¥Ð¥¤¥È¿ô¤ò¤¢¤é¤ï¤¹¡£
+ *
+ * ËÜ»ÅÍͤˤ·¤¿¤¬¤Ã¤Æ¹½Â¤ÂΤòºîÀ®Í½Äê¡£
+ *
+ * S002 11/26/94
+ * ³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°´ØÏ¢¡¢etc.¡Ë
+ * ¤ÎÀèƬ¤Î¥Ø¥Ã¥ÀÉô¤òÁ´¤ÆNVRAM¤ÎÀèƬ¤Ë°Ü¤¹¡£NVRAM¤ÎÀèƬ¤Ë¤¢¤ë¥Ø¥Ã¥ÀÆâ¤Ë
+ * ³ÆÎΰè¤Î¥ì¥³¡¼¥É¤òľÀÜ¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥ª¥Õ¥»¥Ã¥È¤ò¤â¤Ä¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * NVRAM¤Î¥¢¥¯¥»¥¹»þ¤Ë¤Ï256¥Ð¥¤¥Èñ°Ì¤Ç¥Ð¥ó¥¯Àڤ괹¤¨¤¬¤ª¤³¤Ê¤ï¤ì¤ë¤¿¤á
+ * ³Æ¥Ç¡¼¥¿¡Ê256¥Ð¥¤¥ÈĹ°Ê²¼¤Î¤â¤Î¡Ë¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤ò¤Þ¤¿¤¬¤é¤Ê¤¤¤è¤¦
+ * ¤ËÇÛθ¡£³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢etc.¡Ë¤ÎÀèƬ¤¬É¬¤º256¥Ð¥¤¥È
+ * ¥Ð¥¦¥ó¥À¥ê¤«¤é³«»Ï¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * ECC¥¨¥é¡¼¥í¥°Æâ¤ÎSIMMÆÃÄê²½¾ðÊó¤ò2¥Ð¥¤¥È¤«¤é1¥Ð¥¤¥È¤ØÊѹ¹¡£
+ *
+ * ¡É¥ª¥Õ¥»¥Ã¥È ¡É¤Ï¤¹¤Ù¤ÆNVRAM¤ÎÀèƬ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¡£
+ *
+ * S003 12/13/94
+ * NW¥¨¡¼¥¸¥§¥ó¥È¤È¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ò¶¦Ä̲½¤¹¤ë¤¿¤áÀèƬ512¥Ð¥¤¥È¤ò
+ * ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤È¤·¡¢¥Õ¥©¡¼¥Þ¥Ã¥È¤òNW¥¨¡¼¥¸¥§¥ó¥È¤ÈÅý°ì¤¹¤ë¡£
+ *
+ * STEP1¤Ç¤Ï¥á¥â¥ê½ÌÂà¤ò¹Ô¤ï¤Ê¤¤¤¿¤áËÜ¥¨¥ê¥¢¤Ï»ÈÍѤ·¤Ê¤¤¡£
+ * ËÜ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ÏNW¥¨¡¼¥¸¥§¥ó¥È¤È¤Î¶¦Ä̲½¤Î¤¿¤á¤Ë¿·¤¿¤ËÀߤ±¤ë
+ * ¤â¤Î¤Ç¤¢¤ê¡¢°ÊÁ°¤«¤é¤ÎECC¥¨¥é¡¼¾ðÊóÎΰè¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£
+ *
+ * 512¥Ð¥¤¥È¤Î¥¨¥ê¥¢¤òÀèƬ¤ËÀߤ±¤ë¤¿¤á¡¢°ÊÁ°¤«¤é¤Î¤½¤Î¾Á´¤Æ¤Î¾ðÊóÎΰè¤Ï
+ * 512¥Ð¥¤¥È¥ª¥Õ¥»¥Ã¥È¤¬Â礭¤¯¤Ê¤ë¤³¤È¤Ë¤Ê¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È2¥Ð¥¤¥È¤òÄɲá£
+ *
+ * ¥ª¥Õ¥»¥Ã¥È¤ÎºÆ·×»»¡£
+ *
+ * S004 12/14/94
+ * ¹½Â¤ÂκîÀ®¡£
+ *
+ * ¡Ç¥Ñ¥Ë¥Ã¥¯ ¡Ç¤ò¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S005 12/23/94
+ * 4byte alignment¤Ë¤½¤Ê¤¨¤Æ¥Ñ¥Ç¥£¥ó¥°¤ò°ìÉôÊѹ¹¡£
+ *
+ * ¥¹¥È¥Ã¥×¥¨¥é¡¼¤Î¥Õ¥é¥°¤Î2¥Ó¥Ã¥È¤Ë¿·¤¿¤ËÄêµÁÄɲá£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤òNVRAM¥Ø¥Ã¥À¤Ë¤È¤ê¤³¤à¡£
+ * ¤³¤ì¤Ë¤È¤â¤Ê¤¤¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ÏÉÔÍפȤʤ뤿¤á
+ * 2¥Ð¥¤¥Èʬ̤»ÈÍѤȤ¹¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ë¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤òÄɲá£ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ¤ò
+ * ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤È¥Õ¥é¥°¤Ç¥Á¥§¥Ã¥¯¤¹¤ë¤è¤¦¤Ë¤¹¤ë¡£¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤Ï
+ * 0xFF651026¤È¤¹¤ë¡£
+ *
+ * ¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ò¡Ç¥·¥¹¥Æ¥à¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S006 12/27/94
+ * #pragma pack() ¤òÄɲÃ
+ *
+ * char reserved[49] ¤ò char reserved[49] ¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ïharmless¤Ç¤¢¤ë
+ * ¤È¿®¤¸¤ë... (^_^;
+ *
+ * unsigned short offset_ecc2err ¤ò offset_2biterr¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ï
+ * harmless¤Ç¤¢¤ë¤È¿®¤¸¤ë... (^_^;
+ *
+ ******************************************************************************
+
+
+ ###################
+ # NVRAM¥Ø¥Ã¥ÀÉô #
+ ###################
+
+ ######################################################
+ # F/WÍÑ¥á¥â¥ê¡¼¥¨¥é¡¼¥¨¥ê¥¢ (NW¥¨¡¼¥¸¥§¥ó¥È¤È¶¦ÄÌ) #
+ ######################################################
+
+ 512 ¥á¥â¥ê¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(2¥Ð¥¤¥È) ¡ß 256
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ ¡¡¡¡1 ¥¹¥Æ¡¼¥¿¥¹ 0:Àµ¾ï 1:°Û¾ï(2bit¥¨¥é¡¼Í­Ìµ)
+ 1 1bit¥¨¥é¡¼¥«¥¦¥ó¥È
+
+¡¡¡¡ ######################
+ # Á´ÂΤ˴ؤ¹¤ë¤â¤Î #
+ ######################
+
+ 1 NVRAM¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 NVRAMÁ´ÂÎÍ­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡1 ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ 0:̵ 1:Í­
+ ¡¡¡¡2 READ-ONLY 0:NO 1:YES
+ ¡¡¡¡3 LOCK 0:NO 1:YES
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 NVRAM¤¬¥Õ¥©¡¼¥Þ¥Ã¥È¤µ¤ì¤¿¥¿¥¤¥à¥¹¥¿¥ó¥×
+
+ 3 [ reserved ]
+
+¡¡¡¡ ###############################
+ # ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ###############################
+
+ 2 ALIVE¾ðÊóÎΰè¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ #######################################
+ # ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 1bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECC1bit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ ¡¡ 8 ECC 1bit¥¨¥é¡¼¥«¥¦¥ó¥È ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô8
+
+¡¡¡¡ #######################################
+ # ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 2bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECCÊ£¿ôbit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ 4 SIMM¸ò´¹¥Õ¥é¥° ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô4
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 ¥°¥ë¡¼¥×NÆâSIMM #0 (N=1¡Á4) 0:OK 1:NG(Í׸ò´¹)
+ ¡¡¡¡1 ¥°¥ë¡¼¥×NÆâSIMM #1 ¢¬
+ ¡¡¡¡2 ¥°¥ë¡¼¥×NÆâSIMM #2¡¡¡¡ ¢¬
+ ¡¡¡¡3 ¥°¥ë¡¼¥×NÆâSIMM #3¡¡¡¡ ¢¬
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¢¬
+ ¡¡¡¡6 ¢¬
+ ¡¡¡¡7¡¡¡¡¡¡¢¬
+ 4 [reserved]
+
+¡¡¡¡ ########################################
+ ¡¡¡¡# ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ¡¡¡¡########################################
+
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É¿ô
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ############################################
+ ¡¡¡¡# ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Îΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ############################################
+
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##################################
+ ¡¡¡¡# ¤·¤­¤¤Ã;ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##################################
+
+ 2 ¤·¤­¤¤Ã;ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##############################
+ ¡¡¡¡# ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##############################
+
+ 2 ¥ê¥¶¡¼¥ÖÎΰè¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+
+ ########################
+ # ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ #
+ ########################
+
+¡¡¡¡¡¡¡¡ 1 ¥·¥¹¥Æ¥à¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ 0 [reserved]
+ ¡¡¡¡1 ¡¡¡¡¢¬
+ ¡¡¡¡2 ¡¡¡¡¢¬
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 3 [reserved]
+ 32 ¥·¥¹¥Æ¥à¤Î¾ðÊó¡Ê¥·¥¹¥Æ¥à̾¡Ë
+ 4 ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼
+ 4 ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼
+ 4 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 640 ¥Ð¥¤¥È
+
+
+ #######################################
+ # ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ #
+ #######################################
+
+ 1 ¸½ºß¤ÎÄÌÊó¥ì¥Ù¥ë
+ 16 ALIVE°ì¼¡ÄÌÊóÀè
+ 16 ALIVEÆó¼¡ÄÌÊóÀè
+ 47 [reserved for pager call]
+
+-----------------------------------------------------------------------------
+TOTAL 80 ¥Ð¥¤¥È
+
+
+ ##############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ##############################################################################
+
+ 48 [reserved]
+
+
+ #######################
+ # ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô #
+ #######################
+
+ 400 1bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 16
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1¡¡¡¡¥Õ¥é¥°
+
+ ¡¡¡¡ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7¡¡¡¡ ¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+ 100 2bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 4
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5¡¡ ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+
+-----------------------------------------------------------------------------
+TOTAL 500 ¥Ð¥¤¥È
+
+
+ ###############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ###############################################################################
+
+ 12 [reserved]
+
+
+ ##########################
+ # ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô #
+ ##########################
+
+ 2048 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô (1¥ì¥³¡¼¥É512¥Ð¥¤¥È ¡ß 4 ¡á 2K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Dump/Dump SW 0:D 1:D SW
+ ¡¡¡¡3 ÄÌÊó¤Î̵ͭ 0:̤ 1:ºÑ
+ ¡¡¡¡4 boot·ë²Ì 0:Àµ¾ï 1:°Û¾ï
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 496 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó
+ 1 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 2048 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç3328¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ###############################################################
+ # ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) #
+ ###############################################################
+
+ 4096 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Panic/Shutdown 0:P 1:S
+ ¡¡¡¡3 [reserved]
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 20 ¥½¡¼¥¹Ì¾
+ 80 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó
+ 13 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 4096 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç7424¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ##############################
+ # ¤·¤­¤¤ÃÍȽÄêÍѥǡ¼¥¿Îΰè #
+ ##############################
+
+ ¡¡ 256 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 256 ¥Ð¥¤¥È
+
+
+ ###############################################################
+ # ¢¬¤³¤³¤Þ¤Ç7680(7K+512)¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ ###############################################################
+
+
+ ##############################
+ # ¥ê¥¶¡¼¥ÖÎΰè (512¥Ð¥¤¥È) #
+ ##############################
+
+ 512 PAiNTSÍÑ?
+
+-----------------------------------------------------------------------------
+TOTAL 512 ¥Ð¥¤¥È
+
+
+ #############################################
+ # ¢¬¤³¤³¤Þ¤Ç8192(8K)¥Ð¥¤¥È¡£NVRAM¤Î¤·¤Ã¤Ý #
+ #############################################
+
+******************************************************************************/
+
+
+#pragma pack(1)
+
+/********************
+ * *
+ * ¡¡¹½Â¤ÂÎÄêµÁ *
+ * *
+ ********************/
+
+
+/*
+ * WAS & PS¶¦ÄÌFWÍÑ¥á¥â¥ê¥¨¥é¡¼¾ðÊóÎΰè
+ */
+typedef struct _MEM_ERR_REC {
+ unsigned char mem_status; /* ¥¹¥Æ¡¼¥¿¥¹ */
+ unsigned char err_count; /* 1bit¥¨¥é¡¼¥«¥¦¥ó¥È */
+} MEM_ERR_REC, *pMEM_ERR_REC;
+
+
+/*
+ * ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ALIVE_AREA_INFO {
+ unsigned short offset_alive;
+ /* ALIVE¾ðÊ󥨥ꥢ¥ª¥Õ¥»¥Ã¥È */
+} ALIVE_AREA_INFO, *pALIVE_AREA_INFO;
+
+
+/*
+ * ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC1_ERR_AREA_INFO {
+ unsigned short offset_1biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char err_count_group0; /* ¥á¥â¥êG#0 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group1; /* ¥á¥â¥êG#1 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group2; /* ¥á¥â¥êG#2 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group3; /* ¥á¥â¥êG#3 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group4; /* ¥á¥â¥êG#4 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group5; /* ¥á¥â¥êG#5 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group6; /* ¥á¥â¥êG#6 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group7; /* ¥á¥â¥êG#7 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO;
+
+
+/*
+ * ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC2_ERR_AREA_INFO {
+ unsigned short offset_2biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char simm_flag_group1; /* ¥á¥â¥êG#1ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group2; /* ¥á¥â¥êG#2ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group3; /* ¥á¥â¥êG#3ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group4; /* ¥á¥â¥êG#4ÆâSIMM¥Õ¥é¥° */
+ char reserved[4]; /* reserved */
+} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _SYSTEM_ERR_AREA_INFO {
+ unsigned short offset_systemerr;/* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO;
+
+
+/*
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _CRITICAL_ERR_AREA_INFO {
+ unsigned short offset_critical; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO;
+
+
+/*
+ * ¤·¤­¤¤ÃÍÅù¤½¤Î¾¤Î¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _MISC_AREA_INFO {
+ unsigned short offset_misc;
+ /* ¤·¤­¤¤¤ÁÅù¤Î¾ðÊ󥨥ꥢÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} MISC_AREA_INFO, *pMISC_AREA_INFO;
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _RESERVE_AREA_INFO {
+ unsigned short offset_reserve;
+ /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢ÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ
+ * 49¥Ð¥¤¥È
+ */
+
+typedef struct _SYS_INFO {
+ unsigned char system_flag; /* ¥·¥¹¥Æ¥à¾õÂ֥ե饰 */
+ char reserved1[3]; /* 4byte alignment¤Ë¤½¤Ê¤¨¤Æ */
+ char sys_description[32]; /* ¥·¥¹¥Æ¥à¤Î¾ðÊó */
+ unsigned long serical_num; /* ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼ */
+ unsigned long magic; /* ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ */
+ char reserved2[4]; /* reserved */
+} SYS_INFO, *pSYS_INFO;
+
+
+
+/*
+ * NVRAM¥Ø¥Ã¥ÀÉô
+ * 640¥Ð¥¤¥È
+ */
+
+typedef struct _NVRAM_HEADER {
+ MEM_ERR_REC mem_err_map[256]; /* ¥á¥â¥ê¥¨¥é¡¼¾ðÊóNT&NW¶¦ÄÌ¥¨¥ê¥¢ */
+ unsigned char nvram_flag; /* nvram¤Î¾õÂ֥ե饰 */
+ char when_formatted[14]; /* ¥Õ¥©¡¼¥Þ¥Ã¥È¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char reserved[3]; /* 4byte alignment ¤Ë¤½¤Ê¤¨¤Æ */
+ ALIVE_AREA_INFO alive; /* ALIVE¾ðÊ󥨥ꥢ */
+ ECC1_ERR_AREA_INFO ecc1bit_err; /* ECC1bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ ECC2_ERR_AREA_INFO ecc2bit_err; /* ECC2bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ SYSTEM_ERR_AREA_INFO system_err;/* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ CRITICAL_ERR_AREA_INFO critical_err_log;
+ /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥¨¥ê¥¢ */
+ MISC_AREA_INFO misc; /* ¤·¤­¤¤¤Á¾ðÊ󥨥ꥢ */
+ RESERVE_AREA_INFO reserve; /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢¥ª¥Õ¥»¥Ã¥È */
+ SYS_INFO system; /* ¥·¥¹¥Æ¥à¾ðÊó */
+} NVRAM_HEADER, *pNVRAM_HEADER;
+
+
+
+/*
+ * ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ
+ * 80¥Ð¥¤¥È
+ */
+
+typedef struct _ALIVE_INFO {
+ unsigned char alert_level; /* ÄÌÊó¥ì¥Ù¥ë¥° */
+ char primary_destination[16]; /* °ì¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char secondary_destinaiton[16]; /* Æó¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char reserved[47]; /* reserved for pager call */
+} ALIVE_INFO, *pALIVE_INFO;
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved[48];
+
+
+typedef struct _ECC1_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC1_ERR_REC, *pECC1_ERR_REC;
+
+
+typedef struct _ECC2_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC2_ERR_REC, *pECC2_ERR_REC;
+
+
+/*
+ * ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô
+ * 500 ¥Ð¥¤¥È
+ */
+
+ECC1_ERR_REC ecc1_err_rec_log[16];
+
+ECC2_ERR_REC ecc2_err_rec_log[4];
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved2[12];
+
+
+typedef struct _STOP_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char err_description[496]; /* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó */
+ char reserved[1]; /* reserved */
+} STOP_ERR_REC, *pSTOP_ERR_REC;
+
+/*
+ * ¥¹¥Ã¥È¥×¥¨¥é¡¼¾ðÊóÉô
+ * 2048 ¥Ð¥¤¥È
+ */
+
+STOP_ERR_REC stop_err_rec_log[4];
+
+
+typedef struct _CRITICAL_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char source[14]; /* ¥½¡¼¥¹Ì¾ */
+ char err_description[496]; /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó */
+ char reserved[13]; /* reserved */
+} CRITICAL_ERR_REC, *pCRITICAL;
+
+
+/* ¡¡
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+ * 4096¥Ð¥¤¥È
+ */
+
+CRITICAL_ERR_REC critical_err_rec_log[32];
+
+
+/*
+ * ¤·¤­¤¤ÃÍȽÄêÍÑÅù¥Ç¡¼¥¿Îΰè.
+ * 256¥Ð¥¤¥È
+ */
+
+char reserved3[256]; /* reserved */
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè(PAiNTSÍÑ?)
+ * 512¥Ð¥¤¥È
+ */
+
+char reserved4[512]; /* reserved for paints ? */
+
+#pragma pack(4)
diff --git a/private/ntos/nthals/halr96b/mips/glint.h b/private/ntos/nthals/halr96b/mips/glint.h
new file mode 100644
index 000000000..ac8c6e07a
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/glint.h
@@ -0,0 +1,580 @@
+// #pragma comment(exestr, "@(#) glint.h 1.1 95/09/28 15:32:57 nec")
+/************************************************************************
+ * *
+ * Copyright (c) 1994 3Dlabs Inc. Ltd. *
+ * All rights reserved *
+ * *
+ * This software and its associated documentation contains proprietary, *
+ * confidential and trade secret information of 3Dlabs Inc. Ltd. and *
+ * except as provided by written agreement with 3Dlabs Inc. Ltd. *
+ * *
+ * a) no part may be disclosed, distributed, reproduced, transmitted, *
+ * transcribed, stored in a retrieval system, adapted or translated *
+ * in any form or by any means electronic, mechanical, magnetic, *
+ * optical, chemical, manual or otherwise, *
+ * *
+ * and *
+ * *
+ * b) the recipient is not entitled to discover through reverse *
+ * engineering or reverse compiling or other such techniques or *
+ * processes the trade secrets contained therein or in the *
+ * documentation. *
+ * *
+ ************************************************************************/
+
+#ifndef __GLINT_H__
+#define __GLINT_H__
+
+typedef unsigned long DWORD;
+
+/************************************************************************/
+/* PCI CONFIGURATION REGION */
+/************************************************************************/
+
+#define __GLINT_CFGVendorId PCI_CS_VENDOR_ID
+#define __GLINT_CFGDeviceId PCI_CS_DEVICE_ID
+#define __GLINT_CFGRevisionId PCI_CS_REVISION_ID
+#define __GLINT_CFGClassCode PCI_CS_CLASS_CODE
+#define __GLINT_CFGHeaderType PCI_CS_HEADER_TYPE
+#define __GLINT_CFGCommand PCI_CS_COMMAND
+#define __GLINT_CFGStatus PCI_CS_STATUS
+#define __GLINT_CFGBist PCI_CS_BIST
+#define __GLINT_CFGLatTimer PCI_CS_MASTER_LATENCY
+#define __GLINT_CFGCacheLine PCI_CS_CACHE_LINE_SIZE
+#define __GLINT_CFGMaxLat PCI_CS_MAX_LAT
+#define __GLINT_CFGMinGrant PCI_CS_MIN_GNT
+#define __GLINT_CFGIntPin PCI_CS_INTERRUPT_PIN
+#define __GLINT_CFGIntLine PCI_CS_INTERRUPT_LINE
+
+#define __GLINT_CFGBaseAddr0 PCI_CS_BASE_ADDRESS_0
+#define __GLINT_CFGBaseAddr1 PCI_CS_BASE_ADDRESS_1
+#define __GLINT_CFGBaseAddr2 PCI_CS_BASE_ADDRESS_2
+#define __GLINT_CFGBaseAddr3 PCI_CS_BASE_ADDRESS_3
+#define __GLINT_CFGBaseAddr4 PCI_CS_BASE_ADDRESS_4
+#define __GLINT_CFGRomAddr PCI_CS_EXPANSION_ROM
+
+/* CFGVendorId[15:0] - 3Dlabs Vendor ID Value */
+
+#define GLINT_VENDOR_ID (0x3D3D)
+
+/* CFGDeviceId[15:0] - GLINT 300SX Device ID */
+
+#define GLINT_DEVICE_ID (0x0001)
+
+/* CFGRevisionID[7:0] - GLINT Revision Code */
+
+#define GLINT_REVISION_A (0x00)
+#define GLINT_REVISION_B (0x01)
+
+/* CFGClassCode[23:0] - Other Display Controller */
+
+#define GLINT_CLASS_CODE ((DWORD) 0x00038000)
+
+/* CFGHeaderType[7:0] - Single Function Device */
+
+#define GLINT_HEADER_TYPE (0x00)
+
+/* CFGCommand[15:0] - Reset Value Zero */
+
+#define GLINT_COMMAND_RESET_VALUE (0x0000)
+
+/* CFGCommand[1] - Memory Access Enable */
+
+#define GLINT_MEMORY_ACCESS_MASK (1 << 0)
+#define GLINT_MEMORY_ACCESS_DISABLE (0 << 0)
+#define GLINT_MEMORY_ACCESS_ENABLE (1 << 1)
+
+/* CFGCommand[2] - Master Enable */
+
+#define GLINT_MASTER_ENABLE_MASK (1 << 2)
+#define GLINT_MASTER_DISABLE (0 << 2)
+#define GLINT_MASTER_ENABLE (1 << 2)
+
+/* CFGStatus[15:0] - Reset Value Zero */
+
+#define GLINT_STATUS_RESET_VALUE (0x0000)
+
+/* CFGBist - Built In Self Test Unsupported */
+
+#define GLINT_BIST (0x00)
+
+/* CFGCacheLine - Cache Line Size Unsupported */
+
+#define GLINT_CACHE_LINE (0x00)
+
+/* CFGIntPin - Interrupt Pin INTA# */
+
+#define GLINT_INTERRUPT_PIN (0x01)
+
+/********************/
+
+#define GLINT_CONTROL_BASE __GLINT_CFGBaseAddr0
+#define GLINT_LOCAL_0_BASE __GLINT_CFGBaseAddr1
+#define GLINT_FRAME_0_BASE __GLINT_CFGBaseAddr2
+#define GLINT_LOCAL_1_BASE __GLINT_CFGBaseAddr3
+#define GLINT_FRAME_1_BASE __GLINT_CFGBaseAddr4
+#define GLINT_EPROM_BASE __GLINT_CFGRomAddr
+
+#define GLINT_EPROM_SIZE ((DWORD)(64L * 1024L))
+
+/************************************************************************/
+/* CONTROL AND STATUS REGISTERS */
+/************************************************************************/
+
+#define GLINT_REGION_0_SIZE ((DWORD)(128L * 1024L))
+
+#define __GLINT_ResetStatus 0x0000
+#define __GLINT_IntEnable 0x0008
+#define __GLINT_IntFlags 0x0010
+#define __GLINT_InFIFOSpace 0x0018
+#define __GLINT_OutFIFOWords 0x0020
+#define __GLINT_DMAAddress 0x0028
+#define __GLINT_DMACount 0x0030
+#define __GLINT_ErrorFlags 0x0038
+#define __GLINT_VClkCtl 0x0040
+#define __GLINT_TestRegister 0x0048
+#define __GLINT_Aperture0 0x0050
+#define __GLINT_Aperture1 0x0058
+#define __GLINT_DMAControl 0x0060
+
+/* ResetStatus[31] - Software Reset Flag */
+
+#define GLINT_RESET_STATUS_MASK ((DWORD) 1 << 31)
+#define GLINT_READY_FOR_USE ((DWORD) 0 << 31)
+#define GLINT_RESET_IN_PROGRESS ((DWORD) 1 << 31)
+
+/* IntEnable[4:0] - Interrupt Enable Register */
+
+#define GLINT_INT_ENABLE_DMA ((DWORD) 1 << 0)
+#define GLINT_INT_ENABLE_SYNC ((DWORD) 1 << 1)
+#define GLINT_INT_ENABLE_EXTERNAL ((DWORD) 1 << 2)
+#define GLINT_INT_ENABLE_ERROR ((DWORD) 1 << 3)
+#define GLINT_INT_ENABLE_VERTICAL ((DWORD) 1 << 4)
+
+/* IntFlags[4:0] - Interrupt Flags Register */
+
+#define GLINT_INT_FLAG_DMA ((DWORD) 1 << 0)
+#define GLINT_INT_FLAG_SYNC ((DWORD) 1 << 1)
+#define GLINT_INT_FLAG_EXTERNAL ((DWORD) 1 << 2)
+#define GLINT_INT_FLAG_ERROR ((DWORD) 1 << 3)
+#define GLINT_INT_FLAG_VERTICAL ((DWORD) 1 << 4)
+
+/* ErrorFlags[2:0] - Error Flags Register */
+
+#define GLINT_ERROR_INPUT_FIFO ((DWORD) 1 << 0)
+#define GLINT_ERROR_OUTPUT_FIFO ((DWORD) 1 << 1)
+#define GLINT_ERROR_COMMAND ((DWORD) 1 << 2)
+
+/* ApertureX[1:0] - Framebuffer Byte Control */
+
+#define GLINT_FB_BYTE_CONTROL_MASK ((DWORD) 3 << 0)
+#define GLINT_FB_LITTLE_ENDIAN ((DWORD) 0 << 0)
+#define GLINT_FB_BIG_ENDIAN ((DWORD) 1 << 0)
+#define GLINT_FB_GIB_ENDIAN ((DWORD) 2 << 0)
+#define GLINT_FB_BYTE_RESERVED ((DWORD) 3 << 0)
+
+/* ApertureX[2] - Localbuffer Byte Control */
+
+#define GLINT_LB_BYTE_CONTROL_MASK ((DWORD) 1 << 2)
+#define GLINT_LB_LITTLE_ENDIAN ((DWORD) 0 << 2)
+#define GLINT_LB_BIG_ENDIAN ((DWORD) 1 << 2)
+
+/* DMAControl[0] - DMA Byte Swap Control */
+
+#define GLINT_DMA_CONTROL_MASK ((DWORD) 1 << 0)
+#define GLINT_DMA_LITTLE_ENDIAN ((DWORD) 0 << 0)
+#define GLINT_DMA_BIG_ENDIAN ((DWORD) 1 << 0)
+
+/************************************************************************/
+/* LOCALBUFFER REGISTERS */
+/************************************************************************/
+
+#define __GLINT_LBMemoryCtl 0x1000
+
+/* LBMemoryCtl[0] - Number of Localbuffer Banks */
+
+#define GLINT_LB_BANK_MASK ((DWORD) 1 << 0)
+#define GLINT_LB_ONE_BANK ((DWORD) 0 << 0)
+#define GLINT_LB_TWO_BANKS ((DWORD) 1 << 0)
+
+/* LBMemoryCtl[2:1] - Localbuffer Page Size */
+
+#define GLINT_LB_PAGE_SIZE_MASK ((DWORD) 2 << 1)
+#define GLINT_LB_PAGE_SIZE_256_PIXELS ((DWORD) 0 << 1)
+#define GLINT_LB_PAGE_SIZE_512_PIXELS ((DWORD) 1 << 1)
+#define GLINT_LB_PAGE_SIZE_1024_PIXELS ((DWORD) 2 << 1)
+#define GLINT_LB_PAGE_SIZE_2048_PIXELS ((DWORD) 3 << 1)
+
+/* LBMemoryCtl[4:3] - Localbuffer RAS-CAS Low */
+
+#define GLINT_LB_RAS_CAS_LOW_MASK ((DWORD) 3 << 3)
+#define GLINT_LB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 3)
+#define GLINT_LB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 3)
+#define GLINT_LB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 3)
+#define GLINT_LB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 3)
+
+/* LBMemoryCtl[6:5] - Localbuffer RAS Precharge */
+
+#define GLINT_LB_RAS_PRECHARGE_MASK ((DWORD) 3 << 5)
+#define GLINT_LB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 5)
+#define GLINT_LB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 5)
+#define GLINT_LB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 5)
+#define GLINT_LB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 5)
+
+/* LBMemoryCtl[8:7] - Localbuffer CAS Low */
+
+#define GLINT_LB_CAS_LOW_MASK ((DWORD) 3 << 7)
+#define GLINT_LB_CAS_LOW_1_CLOCK ((DWORD) 0 << 7)
+#define GLINT_LB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 7)
+#define GLINT_LB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 7)
+#define GLINT_LB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 7)
+
+/* LBMemoryCtl[9] - Localbuffer Page Mode Disable */
+
+#define GLINT_LB_PAGE_MODE_MASK ((DWORD) 1 << 9)
+#define GLINT_LB_PAGE_MODE_ENABLE ((DWORD) 0 << 9)
+#define GLINT_LB_PAGE_MODE_DISABLE ((DWORD) 1 << 9)
+
+/* LBMemoryCtl[17:10] - Localbuffer Refresh Count */
+
+#define GLINT_LB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 10)
+#define GLINT_LB_REFRESH_COUNT_SHIFT (10)
+
+#define GLINT_LB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 10)
+
+/* LBMemoryCtl[18] - Localbuffer Dual Write Enables */
+
+#define GLINT_LB_MEM_TYPE_MASK ((DWORD) 1 << 18)
+#define GLINT_LB_MEM_DUAL_CAS ((DWORD) 0 << 18)
+#define GLINT_LB_MEM_DUAL_WE ((DWORD) 1 << 18)
+
+/* LBMemoryCtl[21:20] - PCI Maximum Latency - Read Only */
+
+#define GLINT_PCI_MAX_LATENCY_MASK ((DWORD) 3 << 20)
+#define GLINT_PCI_MAX_LATENCY_SHIFT (20)
+
+/* LBMemoryCtl[23:22] - PCI Minimum Grant - Read Only */
+
+#define GLINT_PCI_MIN_GRANT_MASK ((DWORD) 3 << 22)
+#define GLINT_PCI_MIN_GRANT_SHIFT (22)
+
+/* LBMemoryCtl[26:24] - Localbuffer Visible Region Size - Read Only */
+
+#define GLINT_LB_REGION_SIZE_MASK ((DWORD) 7 << 24)
+#define GLINT_LB_REGION_SIZE_1_MB ((DWORD) 0 << 24)
+#define GLINT_LB_REGION_SIZE_2_MB ((DWORD) 1 << 24)
+#define GLINT_LB_REGION_SIZE_4_MB ((DWORD) 2 << 24)
+#define GLINT_LB_REGION_SIZE_8_MB ((DWORD) 3 << 24)
+#define GLINT_LB_REGION_SIZE_16_MB ((DWORD) 4 << 24)
+#define GLINT_LB_REGION_SIZE_32_MB ((DWORD) 5 << 24)
+#define GLINT_LB_REGION_SIZE_64_MB ((DWORD) 6 << 24)
+#define GLINT_LB_REGION_SIZE_0_MB ((DWORD) 7 << 24)
+
+/* LBMemoryCtl[29:27] - Localbuffer Width - Read Only */
+
+#define GLINT_LB_WIDTH_MASK ((DWORD) 7 << 27)
+#define GLINT_LB_WIDTH_16_BITS ((DWORD) 0 << 27)
+#define GLINT_LB_WIDTH_18_BITS ((DWORD) 1 << 27)
+#define GLINT_LB_WIDTH_24_BITS ((DWORD) 2 << 27)
+#define GLINT_LB_WIDTH_32_BITS ((DWORD) 3 << 27)
+#define GLINT_LB_WIDTH_36_BITS ((DWORD) 4 << 27)
+#define GLINT_LB_WIDTH_40_BITS ((DWORD) 5 << 27)
+#define GLINT_LB_WIDTH_48_BITS ((DWORD) 6 << 27)
+#define GLINT_LB_WIDTH_OTHER ((DWORD) 7 << 27)
+
+/* LBMemoryCtl[30] - Localbuffer Bypass Packing - Read Only */
+
+#define GLINT_LB_BYPASS_STEP_MASK ((DWORD) 1 << 30)
+#define GLINT_LB_BYPASS_STEP_64_BITS ((DWORD) 0 << 30)
+#define GLINT_LB_BYPASS_STEP_32_BITS ((DWORD) 1 << 30)
+
+/* LBMemoryCtl[31] - Localbuffer Aperture One Enable - Read Only */
+
+#define GLINT_LB_APERTURE_ONE_MASK ((DWORD) 1 << 31)
+#define GLINT_LB_APERTURE_ONE_DISABLE ((DWORD) 0 << 31)
+#define GLINT_LB_APERTURE_ONE_ENABLE ((DWORD) 1 << 31)
+
+/************************************************************************/
+/* FRAMEBUFFER REGISTERS */
+/************************************************************************/
+
+#define __GLINT_FBMemoryCtl 0x1800
+#define __GLINT_FBModeSel 0x1808
+#define __GLINT_FBGCWrMask 0x1810
+#define __GLINT_FBGCColorMask 0x1818
+
+/* FBMemoryCtl[1:0] - Framebuffer RAS-CAS Low */
+
+#define GLINT_FB_RAS_CAS_LOW_MASK ((DWORD) 3 << 0)
+#define GLINT_FB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 0)
+#define GLINT_FB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 0)
+#define GLINT_FB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 0)
+#define GLINT_FB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 0)
+
+/* FBMemoryCtl[3:2] - Framebuffer RAS Precharge */
+
+#define GLINT_FB_RAS_PRECHARGE_MASK ((DWORD) 3 << 2)
+#define GLINT_FB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 2)
+#define GLINT_FB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 2)
+#define GLINT_FB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 2)
+#define GLINT_FB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 2)
+
+/* FBMemoryCtl[5:4] - Framebuffer CAS Low */
+
+#define GLINT_FB_CAS_LOW_MASK ((DWORD) 3 << 4)
+#define GLINT_FB_CAS_LOW_1_CLOCK ((DWORD) 0 << 4)
+#define GLINT_FB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 4)
+#define GLINT_FB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 4)
+#define GLINT_FB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 4)
+
+/* FBMemoryCtl[13:6] - Framebuffer Refresh Count */
+
+#define GLINT_FB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 6)
+#define GLINT_FB_REFRESH_COUNT_SHIFT (6)
+
+#define GLINT_FB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 6)
+
+/* FBMemoryCtl[14] - Framebuffer Page Mode Disable */
+
+#define GLINT_FB_PAGE_MODE_MASK ((DWORD) 1 << 14)
+#define GLINT_FB_PAGE_MODE_ENABLE ((DWORD) 0 << 14)
+#define GLINT_FB_PAGE_MODE_DISABLE ((DWORD) 1 << 14)
+
+/* FBMemoryCtl[25:20] - Reserved - Read Only */
+
+#define GLINT_FB_CTL_RESERVED_MASK ((DWORD) 0x3F << 20)
+#define GLINT_FB_CTL_RESERVED_SHIFT (20)
+
+/* FBMemoryCtl[26] - Byte Swap Configuration Space - Read Only */
+
+#define GLINT_BYTE_SWAP_CONFIG_MASK ((DWORD) 1 << 26)
+#define GLINT_BYTE_SWAP_CONFIG_DISABLE ((DWORD) 0 << 26)
+#define GLINT_BYTE_SWAP_CONFIG_ENABLE ((DWORD) 1 << 26)
+
+/* FBMemoryCtl[28] - Framebuffer Aperture One Enable - Read Only */
+
+#define GLINT_FB_APERTURE_ONE_MASK ((DWORD) 1 << 28)
+#define GLINT_FB_APERTURE_ONE_DISABLE ((DWORD) 0 << 28)
+#define GLINT_FB_APERTURE_ONE_ENABLE ((DWORD) 1 << 28)
+
+/* FBMemoryCtl[31:29] - Framebuffer Visible Region Size - Read Only */
+
+#define GLINT_FB_REGION_SIZE_MASK ((DWORD) 7 << 29)
+#define GLINT_FB_REGION_SIZE_1_MB ((DWORD) 0 << 29)
+#define GLINT_FB_REGION_SIZE_2_MB ((DWORD) 1 << 29)
+#define GLINT_FB_REGION_SIZE_4_MB ((DWORD) 2 << 29)
+#define GLINT_FB_REGION_SIZE_8_MB ((DWORD) 3 << 29)
+#define GLINT_FB_REGION_SIZE_16_MB ((DWORD) 4 << 29)
+#define GLINT_FB_REGION_SIZE_32_MB ((DWORD) 5 << 29)
+#define GLINT_FB_REGION_SIZE_RESERVED ((DWORD) 6 << 29)
+#define GLINT_FB_REGION_SIZE_0_MB ((DWORD) 7 << 29)
+
+/* FBModeSel[0] - Framebuffer Width */
+
+#define GLINT_FB_WIDTH_MASK ((DWORD) 1 << 0)
+#define GLINT_FB_WIDTH_32_BITS ((DWORD) 0 << 0)
+#define GLINT_FB_WIDTH_64_BITS ((DWORD) 1 << 0)
+
+/* FBModeSel[2:1] - Framebuffer Packing */
+
+#define GLINT_FB_PACKING_MASK ((DWORD) 2 << 1)
+#define GLINT_FB_PACKING_32_BITS ((DWORD) 0 << 1)
+#define GLINT_FB_PACKING_16_BITS ((DWORD) 1 << 1)
+#define GLINT_FB_PACKING_8_BITS ((DWORD) 2 << 1)
+#define GLINT_FB_PACKING_RESERVED ((DWORD) 3 << 1)
+
+/* FBModeSel[3] - Fast Mode Disable */
+
+#define GLINT_FB_FAST_MODE_MASK ((DWORD) 1 << 3)
+#define GLINT_FB_FAST_MODE_ENABLE ((DWORD) 0 << 3)
+#define GLINT_FB_FAST_MODE_DISABLE ((DWORD) 1 << 3)
+
+/* FBModeSel[5:4] - Shared Framebuffer Mode - Read Only */
+
+#define GLINT_SFB_MODE_MASK ((DWORD) 3 << 4)
+#define GLINT_SFB_DISABLED ((DWORD) 0 << 4)
+#define GLINT_SFB_ARBITER ((DWORD) 1 << 4)
+#define GLINT_SFB_REQUESTER ((DWORD) 2 << 4)
+#define GLINT_SFB_RESERVED ((DWORD) 3 << 4)
+
+/* FBModeSel[6] - Transfer Disable */
+
+#define GLINT_TRANSFER_MODE_MASK ((DWORD) 1 << 6)
+#define GLINT_TRANSFER_ENABLE ((DWORD) 0 << 6)
+#define GLINT_TRANSFER_DISABLE ((DWORD) 1 << 6)
+
+/* FBModeSel[7] - External VTG Select */
+
+#define GLINT_VTG_SELECT_MASK ((DWORD) 1 << 7)
+#define GLINT_INTERNAL_VTG ((DWORD) 0 << 7)
+#define GLINT_EXTERNAL_VTG ((DWORD) 1 << 7)
+
+/* FBModeSel[9:8] - Framebuffer Interleave */
+
+#define GLINT_FB_INTERLEAVE_MASK ((DWORD) 3 << 8)
+#define GLINT_FB_INTERLEAVE_1_WAY ((DWORD) 0 << 8)
+#define GLINT_FB_INTERLEAVE_2_WAY ((DWORD) 1 << 8)
+#define GLINT_FB_INTERLEAVE_4_WAY ((DWORD) 2 << 8)
+#define GLINT_FB_INTERLEAVE_8_WAY ((DWORD) 3 << 8)
+
+/* FBModeSel[11:10] - Framebuffer Block Fill Size */
+
+#define GLINT_FB_BLOCK_FILL_SIZE_MASK ((DWORD) 3 << 10)
+#define GLINT_FB_BLOCK_FILL_UNSUPPORTED ((DWORD) 0 << 10)
+#define GLINT_FB_BLOCK_FILL_4_PIXEL ((DWORD) 1 << 10)
+#define GLINT_FB_BLOCK_FILL_8_PIXEL ((DWORD) 2 << 10)
+#define GLINT_FB_BLOCK_FILL_RESERVED ((DWORD) 3 << 10)
+
+/* FBModeSel[12] - Framebuffer Dual Write Enables */
+
+#define GLINT_FB_MEM_TYPE_MASK ((DWORD) 1 << 12)
+#define GLINT_FB_MEM_DUAL_CAS ((DWORD) 0 << 12)
+#define GLINT_FB_MEM_DUAL_WE ((DWORD) 1 << 12)
+
+/************************************************************************/
+/* INTERNAL VIDEO TIMING GENERATOR REGISTERS */
+/************************************************************************/
+
+#define __GLINT_VTGHLimit 0x3000
+#define __GLINT_VTGHSyncStart 0x3008
+#define __GLINT_VTGHSyncEnd 0x3010
+#define __GLINT_VTGHBlankEnd 0x3018
+#define __GLINT_VTGVLimit 0x3020
+#define __GLINT_VTGVSyncStart 0x3028
+#define __GLINT_VTGVSyncEnd 0x3030
+#define __GLINT_VTGVBlankEnd 0x3038
+#define __GLINT_VTGHGateStart 0x3040
+#define __GLINT_VTGHGateEnd 0x3048
+#define __GLINT_VTGVGateStart 0x3050
+#define __GLINT_VTGVGateEnd 0x3058
+#define __GLINT_VTGPolarity 0x3060
+#define __GLINT_VTGFrameRowAddr 0x3068
+#define __GLINT_VTGVLineNumber 0x3070
+#define __GLINT_VTGSerialClk 0x3078
+
+/* VTGPolarity[1:0] - HSync Ctl */
+
+#define GLINT_HSYNC_POLARITY_MASK ((DWORD) 3 << 0)
+#define GLINT_HSYNC_ACTIVE_HIGH ((DWORD) 0 << 0)
+#define GLINT_HSYNC_FORCED_HIGH ((DWORD) 1 << 0)
+#define GLINT_HSYNC_ACTIVE_LOW ((DWORD) 2 << 0)
+#define GLINT_HSYNC_FORCED_LOW ((DWORD) 3 << 0)
+
+/* VTGPolarity[3:2] - Vsync Ctl */
+
+#define GLINT_VSYNC_POLARITY_MASK ((DWORD) 3 << 2)
+#define GLINT_VSYNC_ACTIVE_HIGH ((DWORD) 0 << 2)
+#define GLINT_VSYNC_FORCED_HIGH ((DWORD) 1 << 2)
+#define GLINT_VSYNC_ACTIVE_LOW ((DWORD) 2 << 2)
+#define GLINT_VSYNC_FORCED_LOW ((DWORD) 3 << 2)
+
+/* VTGPolarity[5:4] - Csync Ctl */
+
+#define GLINT_CSYNC_POLARITY_MASK ((DWORD) 3 << 4)
+#define GLINT_CSYNC_ACTIVE_HIGH ((DWORD) 0 << 4)
+#define GLINT_CSYNC_FORCED_HIGH ((DWORD) 1 << 4)
+#define GLINT_CSYNC_ACTIVE_LOW ((DWORD) 2 << 4)
+#define GLINT_CSYNC_FORCED_LOW ((DWORD) 3 << 4)
+
+/* VTGPolarity[7:6] - CBlank Ctl */
+
+#define GLINT_CBLANK_POLARITY_MASK ((DWORD) 3 << 6)
+#define GLINT_CBLANK_ACTIVE_HIGH ((DWORD) 0 << 6)
+#define GLINT_CBLANK_FORCED_HIGH ((DWORD) 1 << 6)
+#define GLINT_CBLANK_ACTIVE_LOW ((DWORD) 2 << 6)
+#define GLINT_CBLANK_FORCED_LOW ((DWORD) 3 << 6)
+
+/* VTGSerialClk[0] - QSF Select */
+
+#define GLINT_QSF_SELECT_MASK ((DWORD) 1 << 0)
+#define GLINT_EXTERNAL_QSF ((DWORD) 0 << 0)
+#define GLINT_INTERNAL_QSF ((DWORD) 1 << 0)
+
+/* VTGSerialClk[1] - Split Size */
+
+#define GLINT_SPLIT_SIZE_MASK ((DWORD) 1 << 1)
+#define GLINT_SPLIT_SIZE_128_WORD ((DWORD) 0 << 1)
+#define GLINT_SPLIT_SIZE_256_WORD ((DWORD) 1 << 1)
+
+/* VTGSerialClk[2] - SCLK Ctl */
+
+#define GLINT_SCLK_CTL_MASK ((DWORD) 1 << 2)
+#define GLINT_SCLK_VCLK ((DWORD) 0 << 2)
+#define GLINT_SCLK_VCLK_DIV_2 ((DWORD) 1 << 2)
+
+/* VTGSerialClk[3] - SOE Ctl */
+
+#define GLINT_SOE_CTL_MASK ((DWORD) 1 << 3)
+#define GLINT_SOE_0_ASSERTED ((DWORD) 0 << 3)
+#define GLINT_SOE_1_ASSERTED ((DWORD) 1 << 3)
+
+/************************************************************************/
+/* EXTERNAL VIDEO CONTROL REGISTERS */
+/************************************************************************/
+
+#define __GLINT_ExternalVideoControl 0x4000
+
+/************************************************************************/
+/* GRAPHICS CORE REGISTERS AND FIFO INTERFACE */
+/************************************************************************/
+
+#define __GLINT_GraphicsCoreRegisters 0x8000
+
+#define __GLINT_GraphicsFIFOInterface 0x2000
+
+/************************************************************************/
+/* GLINT ACCESS MACROS */
+/************************************************************************/
+
+#define GLINT_ADDR(base, offset) \
+( \
+/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \
+ (DWORD) ((volatile UCHAR *)(base) + (offset)) \
+)
+
+#define GLINT_WRITE(base, offset, data) \
+{ \
+/* DWORD_WRITE(GLINT_ADDR((base),(offset)), (data)); */ \
+ WRITE_REGISTER_ULONG(GLINT_ADDR((base),(offset)), (ULONG)(data)); \
+}
+
+#define GLINT_READ(base, offset, data) \
+{ \
+/* DWORD_READ(GLINT_ADDR((base),(offset)), (data)); */ \
+ (ULONG)(data) = READ_REGISTER_ULONG(GLINT_ADDR((base),(ULONG)(offset))); \
+}
+
+typedef struct
+{
+ /* image size */
+
+ long ImageWidth;
+ long ImageHeight;
+ long ImageDepth;
+
+ /* video timing */
+
+ DWORD HLimit;
+ DWORD HSyncStart;
+ DWORD HSyncEnd;
+ DWORD HBlankEnd;
+ DWORD HSyncPolarity;
+ DWORD VLimit;
+ DWORD VSyncStart;
+ DWORD VSyncEnd;
+ DWORD VBlankEnd;
+ DWORD VSyncPolarity;
+
+ /* Ramdac config */
+
+ DWORD PixelFormat;
+ DWORD RefDivCount;
+ DWORD PixelClock;
+
+ } __VIDEO, *VIDEO;
+
+/************************************************************************/
+
+#endif /* __GLINT_H__ */
+
+/************************************************************************/
diff --git a/private/ntos/nthals/halr96b/mips/halp.h b/private/ntos/nthals/halr96b/mips/halp.h
new file mode 100644
index 000000000..13a1b58e0
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/halp.h
@@ -0,0 +1,365 @@
+// #pragma comment(exestr, "@(#) halp.h 1.1 95/09/28 15:33:24 nec")
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+ L0001 1994.9.20 kbnes!kuriyama(A)
+ -Modify for R94A original halfxs\mips\halp.h
+ -add #include"r94axxx.h "
+ L0002 Thu Oct 13 18:09:33 JST 1994 kbnes!kuriyama(A)
+ - Del HalpDisplayLED
+ - Del HalpLEDDisplayLock
+ - Del HalpLEDControlBase
+ - Add READ_REGISTER_DWORD
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:31:21 JST 1994
+ - add data definitions for HalReportResourceUsage
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:15:11 JST 1994
+ - resolve compile error
+ ADD002 kisimoto@oa2.kb.nec.co.jp Fri Nov 25 15:46:03 1994
+ add HalpGetStatusRegister() definition
+ S0003 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 16:51:00 JST 1995
+ add _IPI_LIMIT_ support
+ H0004 kisimoto@oa2.kb.nec.co.jp Sun Jun 25 14:39:38 1995
+ - Merge build 1057
+ H0005 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 20:03:30 1995
+ - Merge code for ESM from J94C
+ H0006 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 19:23:03 1995
+ - Removed _J94C_ definitions.
+ _J94C_ definition indicates that the status of
+ the dump switch can acknowledge from Self-test
+ register.
+ S0007 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 20:18:18 JST 1995
+ - change for x86bios support
+ H0008 kisimoto@oa2.kb.nec.co.jp Wed Aug 30 12:23:36 1995
+ - add spinlock to support PCI Fast Back-to-back transfer.
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "hal.h" // H0004
+
+#ifndef _HALI_ // H0004
+#include "..\inc\hali.h"
+#endif
+
+#if defined(_DUO_)
+
+#if defined(_R94A_)
+
+#include "r94adma.h"
+#include "r94adef.h"
+#include "r94aint.h"
+
+#else // _R94A_
+
+#include "duodma.h"
+#include "duodef.h"
+#include "duoint.h"
+
+#endif // _R94A_
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdma.h"
+#include "jazzdef.h"
+#include "jazzint.h"
+
+#endif
+
+#include "jxhalp.h"
+
+#if defined(USE_BIOS_EMULATOR) // H0004
+
+#include "xm86.h"
+#include "x86new.h"
+
+#endif
+
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+// S0007
+// change prototype HalpInitializeX86DisplayAdapter()
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+#if defined(_R94A_)
+VOID
+READ_REGISTER_DWORD(
+ PLARGE_INTEGER,
+ PVOID
+ );
+
+VOID
+WRITE_REGISTER_DWORD(
+ PLARGE_INTEGER,
+ PVOID
+ );
+
+VOID
+HalpGetStatusRegister (
+ IN PULONG Variable
+ );
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer,
+ ULONG Write
+);
+#endif
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern USHORT HalpBuiltinInterruptEnable;
+extern ULONG HalpCurrentTimeIncrement;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KAFFINITY HalpEisaBusAffinity;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+#if defined(_IPI_LIMIT_)
+extern KSPIN_LOCK HalpIpiRequestLock;
+#endif //_IPI_LIMIT_
+extern KSPIN_LOCK Ecc1bitDisableLock;// H005
+extern KSPIN_LOCK Ecc1bitRoutineLock;// H005
+extern KSPIN_LOCK HalpPCIBackToBackLock; // H008
+
+
+// ADD001
+//
+// Resource usage information
+//
+
+#if !defined (_R94A_)
+#pragma pack(1)
+#endif
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+#if !defined (_R94A_)
+#pragma pack()
+#endif
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+// CMP001
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern ADDRESS_USAGE HalpMapRegisterMemorySpace;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+// CMP001
+#define IRQ_PREFERRED 0x02
+#define IRQ_VALID 0x01
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+);
+
+//
+// H0004: from halx86/i386/halp.h
+// Temp definitions to thunk into supporting new bus extension format
+//
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halr96b/mips/j4cache.s b/private/ntos/nthals/halr96b/mips/j4cache.s
new file mode 100644
index 000000000..0f17e43bf
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/j4cache.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4cache.s"
diff --git a/private/ntos/nthals/halr96b/mips/j4flshbf.s b/private/ntos/nthals/halr96b/mips/j4flshbf.s
new file mode 100644
index 000000000..04012b70b
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/j4flshbf.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4flshbf.s"
diff --git a/private/ntos/nthals/halr96b/mips/j4flshio.c b/private/ntos/nthals/halr96b/mips/j4flshio.c
new file mode 100644
index 000000000..2461bc392
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/j4flshio.c
@@ -0,0 +1,236 @@
+// #pragma comment(exestr, "@(#) j4flshio.c 1.1 95/09/28 15:34:41 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Fri Sep 30 20:23:02 JST 1994 kbnes!kishimoto
+ - HalFlushIoBuffers()
+ Modify to return only.
+ R94A supports I/O coherency during I/O translation.
+ N.B. This modify is enabled after Beta-machine.
+ _R94ABBMIO_ means that machine is alpha-version.
+ H001 Sat Mar 18 15:19:33 1995 kbnes!kishimoto
+ - if operation is DMA, we have nothing to do.
+
+ M002 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 10:51:41 JST 1995
+ - add support I/O cache limit _IO_LIMIT_
+--*/
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+#if !defined(_IO_LIMIT_) && defined(_R94A_)
+
+ //
+ // H001
+ // R94A supports cache coherency during DMA operation,
+ // so we have nothing to to.
+ //
+
+ if (DmaOperation == TRUE){
+ return;
+ }
+
+#endif
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halr96b/mips/j4prof.c b/private/ntos/nthals/halr96b/mips/j4prof.c
new file mode 100644
index 000000000..dd8c2b7c9
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/j4prof.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\j4prof.c"
diff --git a/private/ntos/nthals/halr96b/mips/jxbeep.c b/private/ntos/nthals/halr96b/mips/jxbeep.c
new file mode 100644
index 000000000..922c80816
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxbeep.c
@@ -0,0 +1,215 @@
+// #pragma comment(exestr, "@(#) jxbeep.c 1.1 95/09/28 15:35:24 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ M0001 1994.9.12 kbnes!kuriyama
+ Modify for R94A MIPS R4400
+
+ - HalMakeBeep()
+ At R94A system, Buzzer controled by TYPHOON, not by EISA-Bridge.
+ Buzzer ON/OFF, Freequency Control Register was changed.
+
+ S0002 1994.12.22 kbnes!kuriyama
+ cast miss ? fixed
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+/* start M0001 */
+#if defined(_R94A_)
+ BUZZER_CONTROL BuzzerControl;
+#else // _R94A_
+ NMI_STATUS NmiStatus;
+#endif // _R94A_
+/* end M0001 */
+
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ *((PUCHAR)&BuzzerControl) = READ_REGISTER_UCHAR(&DMA_CONTROL->BuzzerControl.Char);
+//S0002
+ BuzzerControl.SpeakerGate = 0;
+ BuzzerControl.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&DMA_CONTROL->BuzzerControl.Char,*((PUCHAR) &BuzzerControl));
+// S0002
+#else // _R94A_
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+/* start M0001 */
+#if defined(_R94A_)
+ //
+ // R94A Support only even value for newCount
+ //
+
+ newCount &= 0xfffe;
+
+ if (newCount == 0) {
+ newCount = 2;
+ }
+
+#else // _R94A_
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ WRITE_REGISTER_USHORT(&DMA_CONTROL->BuzzerCount.Short,(USHORT) newCount);
+// S0002
+
+#else // _R94A_
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Start the speaker.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ *((PUCHAR)&BuzzerControl) = READ_REGISTER_UCHAR(
+ &DMA_CONTROL->BuzzerControl.Char //S0002
+ );
+ BuzzerControl.SpeakerGate = 1;
+ BuzzerControl.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(
+ &DMA_CONTROL->BuzzerControl.Char,//S0002
+ *((PUCHAR) &BuzzerControl)
+ );
+ Result = TRUE;
+
+#else // _R94A_
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+
+#endif // _R94A_
+/* end M0001 */
+
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
+
diff --git a/private/ntos/nthals/halr96b/mips/jxdisp.c b/private/ntos/nthals/halr96b/mips/jxdisp.c
new file mode 100644
index 000000000..f30afc401
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxdisp.c
@@ -0,0 +1,3605 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.2 95/10/17 01:18:22" ) */
+/*++
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a R4400 R94A system.
+
+History:
+
+
+--*/
+
+/*
+ * New Code for 3.51
+ *
+ * M001 kuriyama@oa2.kb.nec.co.jp Fri Jul 14 11:46:06 JST 1995
+ * -change textmode 80x50
+ *
+ * M002 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:36:23 JST 1995
+ * -change for fw interface
+ *
+ * M003 kuriyama@oa2.kb.nec.co.jp Fri Jul 21 14:14:54 JST 1995
+ * -add call HalpResetDisplayParameters
+ * for bug fix DPI board panic message
+ *
+ * M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 2 14:28:28 JST 1995
+ * -add ESM critical error logging
+ *
+ * S005 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 23:42:59 JST 1995
+ * -change for scroll bug fix
+ *
+ * S006 nishi@oa2.kb.nec.co.jp Mon Sep 4 18:42:00 JST 1995
+ * -change for GLINT new revision board
+ * R01=00,R02=02
+ * M007 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995
+ * - Add Software Power Off, when system panic is occured
+ *
+ * M008 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995
+ * - Change Logic for resume fixed TLB for DMA
+ *
+ * M009 kuriyama@oa2.kbnes.nec.co.jp Mon Sep 18 19:58:22 JST 1995
+ * - bug fix for tga 800x600 72Hz
+ *
+ * M010 v-akitk@microsoft.com
+ * - Change for Software Power Supply(R96B)
+ *
+ */
+
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+#include <tga.h>
+#include <glint.h>
+#include <rgb525.h>
+
+#include "string.h"
+#include "pci.h"
+/* START M007 */
+#define HEADER_FILE
+#include "kxmips.h"
+/* START M007 */
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// for x86bios emulate
+//
+PCHAR K351UseBios=NULL;
+VOID HalpCopyROMs(VOID);
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; // M003
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+typedef
+VOID
+(*PHALP_SCROLL_SCREEN) (
+ UCHAR
+ );
+
+#define TAB_SIZE 4
+#define TEXT_ATTR 0x1F
+
+//
+// Define forward referenced procedure prototypes.
+//
+VOID
+HalpDisplayINT10Setup (
+VOID);
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character );
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacterOld (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterOld(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayCirrusSetup (
+ VOID
+ );
+
+BOOLEAN
+HalpCirrusInterpretCmdStream (
+ PUSHORT pusCmdStream
+ );
+
+VOID
+HalpDisplayTgaSetup (
+ VOID
+ );
+
+/*
+VOID
+RGB525_WRITE(
+ ULONG dac,
+ ULONG offset,
+ UCHAR data);
+
+VOID
+RGB525_SET_REG(
+ ULONG dac,
+ ULONG index,
+ UCHAR data);
+*/
+
+VOID
+HalpDisplayGlintSetup(
+ VOID
+ );
+
+VOID
+Write_Dbg_Uchar(
+PUCHAR,
+UCHAR
+);
+
+//
+// Must use 32Bit transfer. RtlMoveMemory() uses 64Bit transfer.
+//
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+);
+/* Start M007 */
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+);
+/*End M007 */
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+
+//
+// Define memory access constants for VXL
+//
+
+#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+#define CIRRUS_OFFSET ((PUSHORT)0x3b0)
+
+#define TGA_REGISTER_BASE ((ULONG)0x403ff000)
+#define R94A_PCI_ADDR_REG ((PULONG)(0x80000518 | 0xffffc000))
+#define R94A_PCI_DATA_REG ((PULONG)(0x80000520 | 0xffffc000))
+
+#define GLINT_CONTROL_REGISTER_BASE ((ULONG)0x403ff000) // M021
+#define GLINT_VIDEO_REGISTER_BASE ((ULONG)0x403fe000)
+#define RGB525_REGISTER_BASE ((ULONG)0x403fd000)
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+ULONG HalpGlintRevisionId; // S006
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayMemoryBase = 0; // M021
+ULONG HalpDisplayResetRegisterBase = 0;
+ULONG HalpDisplayVxlClockRegisterBase = 0;
+ULONG HalpDisplayVxlBt484RegisterBase = 0;
+ULONG HalpDisplayVxlJaguarRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpG364Type = 0;
+
+LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0};
+
+LARGE_INTEGER HalpTgaPhigicalVideo = {0,0};
+LARGE_INTEGER HalpTgaPhigicalVideoCont = {0,0};
+
+LARGE_INTEGER HalpGlintPhygicalVideo = {0,0};
+LARGE_INTEGER HalpGlintPhygicalVideoCont = {0,0};
+ULONG HalpDisplayPCIDevice = FALSE;
+ULONG HalpDisplayType16BPP = FALSE;
+
+PVOID HalpMrcControlBase = NULL; // M007
+BOOLEAN HalpMrcControlMapped = FALSE; // M007
+
+typedef struct _R94A_PCI_CONFIGURATION_ADDRESS_REG{
+ ULONG Reserved2: 2;
+ ULONG RegisterNumber: 6;
+ ULONG FunctionNumber: 3;
+ ULONG DeviceNumber: 5;
+ ULONG BusNumber: 8;
+ ULONG Reserved1: 7;
+ ULONG ConfigEnable: 1;
+} R94A_PCI_CONFIGURATION_ADDRESS_REG, *PR94A_PCI_CONFIGURATION_ADDRESS_REG;
+
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+BOOLEAN
+HalpCheckPCIDevice (
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+ PCI_SLOT_NUMBER Slot;
+ ULONG ReadValue;
+ PCHAR Options;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n DISP 0\n"); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ MatchKey = 1;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+ }
+
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (LoaderBlock->LoadOptions != NULL) {
+ Options = LoaderBlock->LoadOptions;
+ _strupr(Options);
+ K351UseBios = strstr(Options, "USEBIOS");
+ }
+ if(K351UseBios!=NULL){
+ DbgPrint("\nUSEBIOS---\n");
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpDisplayControlBase = 0x90000000;
+
+ }else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "necvdfrb")) {
+
+ HalpDisplayControllerSetup = HalpDisplayCirrusSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayControlBase = 0x90000000;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"10110004")) {
+ //
+ // for DEC21030 PCI
+ //
+
+ HalpDisplayControllerSetup = HalpDisplayTgaSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayPCIDevice = TRUE;
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (ReadValue == 0x00041011){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+ if ((ReadValue & 0x00000002) == 0x2){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ HalpDisplayControlBase =
+ (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+
+ } else {
+ return FALSE;
+
+ }
+ }
+ }
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"3D3D0001")) {
+
+ //
+ // for GLINT 300SX PCI
+ //
+
+ HalpDisplayControllerSetup = HalpDisplayGlintSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayPCIDevice = TRUE;
+ HalpDisplayType16BPP = TRUE;
+
+ //
+ // FunctionNumber always zero
+ //
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (ReadValue == 0x00013d3d){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+ //
+ // GLINT 300SX has no I/O space regions
+ //
+
+ if (ReadValue & 0x2){
+
+ //
+ // Control Registers
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ HalpDisplayControlBase = (ReadValue & 0xfffffff0);
+
+ //
+ // Framebuffer
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ HalpDisplayMemoryBase = (ReadValue & 0xfffffff0);
+
+ //
+ // Revision ID
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x08); // S006
+ HalpGlintRevisionId = (ReadValue & 0x000000ff);
+
+ } else {
+ return FALSE;
+
+ }
+ }
+ }
+ } else {
+ // M002 +++
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpDisplayControlBase = 0x90000000;
+ HalpDisplayTypeUnknown = TRUE;
+ // M002 ---
+ }
+
+ Child = ConfigurationEntry->Child;
+
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpScrollLine =
+ 1024 * HalpCharacterHeight;
+ } else if (HalpDisplayType16BPP) {
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight * sizeof(USHORT);
+
+ } else {
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+ }
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpDisplayWidth =
+ 1024 / HalpCharacterWidth;
+
+ }else{
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+ }
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ if (HalpDisplayControllerSetup == HalpDisplayINT10Setup) {
+
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = 0;
+
+ Pte.PFN = (HalpCirrusPhigicalVideo.HighPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }else if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = MEM_VGA;
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ HalpTgaPhigicalVideo.HighPart = 1;
+ HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET;
+ Pte.PFN = (HalpTgaPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+ HalpGlintPhygicalVideo.HighPart = 1;
+ HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase;
+ Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) {
+
+ HalpGlintPhygicalVideoCont.HighPart = 1;
+ HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase;
+
+ //
+ // IBM RGB525
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 2) = Pte;
+
+ //
+ // GLINT 300SX Internal Video Registers
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 1) = Pte;
+
+ //
+ // GLINT 300SX Control Status Registers
+ //
+
+ Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayINT10Setup){
+
+#if defined(_X86_DBG_)
+ DbgPrint("Map x86 and cirrus control register\n");
+#endif // _X86_DBG_
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) {
+ *PageFrame-- = Pte;
+#if defined(_X86_DBG_)
+ DbgPrint("Map index %x pfn %x\n",Index,Pte.PFN);
+#endif // _X86_DBG_
+ Pte.PFN -= 1;
+ }
+
+ } else {
+
+ //
+ // If we have a 'NEC-cirrus GD5428'
+ // use the page before last to map the reset register.
+ //
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // M004
+ // ESM critical error logging setup.
+ //
+
+ HalpInitDisplayStringIntoNvram();
+
+ //
+ // Initialize the display controller.
+ //
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n x86adp init GOOO\n"); //DBGDBG
+#endif // _X86_DBG
+
+ if(HalpDisplayControllerSetup == HalpDisplayINT10Setup){
+ if (HalpInitializeX86DisplayAdapter()) {
+#if defined(_X86_DBG_)
+ DbgPrint("\n x86adp init OK\n"); //DBGDBG
+#endif // _X86_DBG
+// HalpDisplayControllerSetup(); // initialize twice bugbug
+
+ }else{
+
+ return FALSE;
+ }
+ }
+
+ HalpDisplayControllerSetup();
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpResetDisplayParameters=ResetDisplayParameters;// M003
+ HalpDisplayOwnedByHal = FALSE;
+
+ //
+ // M010
+ // Set for Software Power supply control
+ //
+
+#if defined (_MRCPOWER_)
+ HalpMrcModeChange((UCHAR)0x1); // M007
+#endif // _MRCPOWER_
+
+ //
+ // M006
+ // ESM critical logging success set success startup.
+ //
+
+ HalpSuccessOsStartUp();
+
+ return;
+}
+
+VOID
+HalpDisplayCirrusSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Cirrus VGA display controlleer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG dac_address, dac_reg;
+
+ ULONG verticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+ if( verticalFrequency < 66 ) {
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 800:
+ if( verticalFrequency < 58 ) {
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_56);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 66 ) {
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 1024:
+
+ if( verticalFrequency < 47 ) {
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if ( verticalFrequency < 65) {
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+ default:
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ return;
+ }
+
+ //
+ // Initialize color pallete.
+ //
+
+ dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT;
+ dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT;
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0);
+
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2));
+
+ //
+ // Set the video memory to address color one.
+ //
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (1024 *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+BOOLEAN
+HalpCirrusInterpretCmdStream(
+ PUSHORT pusCmdStream
+ )
+
+/*++
+
+Routine Description:
+
+ Interprets the appropriate command array to set up VGA registers for the
+ requested mode. Typically used to set the VGA into a particular mode by
+ programming all of the registers
+
+Arguments:
+
+
+ pusCmdStream - array of commands to be interpreted.
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+Revision History:
+--*/
+
+
+
+{
+ ULONG ulCmd;
+ ULONG ulPort;
+ UCHAR jValue;
+ USHORT usValue;
+ ULONG culCount;
+ ULONG ulIndex;
+ ULONG ulBase;
+ if (pusCmdStream == NULL) {
+
+ return TRUE;
+ }
+
+ ulBase = (ULONG)CIRRUS_BASE+0x3b0;
+
+ //
+ // Now set the adapter to the desired mode.
+ //
+
+ while ((ulCmd = *pusCmdStream++) != EOD) {
+
+ //
+ // Determine major command type
+ //
+
+ switch (ulCmd & 0xF0) {
+
+ //
+ // Basic input/output command
+ //
+
+ case INOUT:
+
+ //
+ // Determine type of inout instruction
+ //
+
+ if (!(ulCmd & IO)) {
+
+ //
+ // Out instruction. Single or multiple outs?
+ //
+
+ if (!(ulCmd & MULTI)) {
+
+ //
+ // Single out. Byte or word out?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // Single byte out
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = (UCHAR) *pusCmdStream++;
+
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort),
+ jValue);
+
+ } else {
+
+ //
+ // Single word out
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff));
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8));
+
+
+ }
+
+ } else {
+
+ //
+ // Output a string of values
+ // Byte or word outs?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // String byte outs. Do in a loop; can't use
+ // VideoPortWritePortBufferUchar because the data
+ // is in USHORT form
+ //
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+
+ while (culCount--) {
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ jValue);
+
+ }
+
+ } else {
+
+ //
+ // String word outs
+ //
+
+ ulPort = *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ //
+ // Buffering out is not use on the Miniport Driver for R96 machine.
+ //
+
+
+ while(culCount--)
+ {
+ usValue = *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort), (UCHAR) (usValue & 0x00ff));
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort+1), (UCHAR) (usValue >> 8));
+
+ }
+
+ }
+ }
+
+ } else {
+
+ // In instruction
+ //
+ // Currently, string in instructions aren't supported; all
+ // in instructions are handled as single-byte ins
+ //
+ // Byte or word in?
+ //
+
+ if (!(ulCmd & BW)) {
+ //
+ // Single byte in
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+
+ } else {
+
+ //
+ // Single word in
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = READ_REGISTER_USHORT((PUSHORT)
+ (ulBase+ulPort));
+ }
+
+ }
+
+ break;
+
+ //
+ // Higher-level input/output commands
+ //
+
+ case METAOUT:
+
+ //
+ // Determine type of metaout command, based on minor
+ // command field
+ //
+ switch (ulCmd & 0x0F) {
+
+ //
+ // Indexed outs
+ //
+
+ case INDXOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ usValue = (USHORT) (ulIndex +
+ (((ULONG)(*pusCmdStream++)) << 8));
+
+ Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff));
+
+ Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8));
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // Masked out (read, AND, XOR, write)
+ //
+
+ case MASKOUT:
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+ jValue &= *pusCmdStream++;
+ jValue ^= *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulBase + ulPort,
+ jValue);
+
+ break;
+
+ //
+ // Attribute Controller out
+ //
+
+ case ATCOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ // Write Attribute Controller index
+
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ (UCHAR)ulIndex);
+
+ // Write Attribute Controller data
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulPort, jValue);
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // None of the above; error
+ //
+ default:
+
+ return FALSE;
+
+ }
+
+
+ break;
+
+ //
+ // NOP
+ //
+
+ case NCMD:
+
+ break;
+
+ //
+ // Unknown command; error
+ //
+
+ default:
+
+ return FALSE;
+
+ }
+
+ }
+
+ return TRUE;
+
+} // end HalpCirrusInterpretCmdStream()
+
+
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine initializes the Tga(DEC21030) Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PUCHAR PLLbits;
+ ULONG i, j;
+ ULONG PLLdata;
+ ULONG ColorData;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+// M019+++
+//
+// support for nec dec-ga(tga) board.
+// parameter change.
+//
+#if 0
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xb0, 0x20, 0xc8 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x08, 0x80, 0x24, 0x88, 0x80, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x00, 0x80, 0x24, 0x88, 0x80, 0x78 };
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x70, 0xa0, 0x84 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+#else
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 }; // S007
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+#endif // _NECDEC_
+// M019 ---
+
+ const UCHAR Vga_Ini_ColorTable[48] =
+// { VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B,
+ { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // M010
+ VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B,
+ VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G,
+ VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B,
+ VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B,
+ VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B,
+ VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B,
+ VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B,
+// VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B,
+ VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // M010
+ VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B,
+ VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B,
+ VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B,
+ VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B,
+ VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B,
+ VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B,
+ VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B
+ };
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ //
+ // Write the PLL
+ //
+
+ // Select PLL Data
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits640x480_72; // S012
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S012
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits800x600_72; // S012
+ } else {
+ PLLbits = (PVOID)PLLbits800x600_60; // S012
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ PLLbits = (PVOID)PLLbits1024x768_60; // S012
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S012
+ }
+
+ // Set PLL Data
+ for( i = 0; i <= 6; i++ ){
+ for( j = 0; j <= 7; j++ ){
+ PLLdata = (PLLbits[i] >> (7-j)) & 1;
+ if( i == 6 && j == 7 )
+ PLLdata |= 2; // Set ~HOLD bit on last write
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata);
+ }
+ }
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){
+ }
+
+ // Set to Deep Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 );
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){
+ }
+
+ // Set to Video Base Address Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 );
+
+ // Set to Plane Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff );
+
+ // Set to Pixel Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff );
+
+ // Set to Raster Operation
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d );
+
+ // Set to Block Color Register 0
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 );
+
+ // Set to Block Color Register 1
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 );
+
+ //
+ // Init. video timing registers for each resolution
+ //
+
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x03c294a0 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x01a7a4c8 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x02681cc8 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x04889300 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+
+ // Set to Raster Operation Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 );
+
+ // M019 +++
+
+ //
+ // wait for 10 msec for nec dec-ga support
+ //
+
+ KeStallExecutionProcessor(10000L);
+
+ // M019 ---
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 );
+
+ //
+ // set pass thru on off & on again to verify operation
+ //
+
+ // EEPROM Write Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 );
+
+ //
+ // Fill palette
+ //
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 );
+
+ for( i = 0; i < 48; i++ ){
+ ColorData = Vga_Ini_ColorTable[i];
+ ColorData |= 0x200;
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData );
+ }
+
+ for( i = 48; i < 768; i++ ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 );
+ }
+
+ // Set to Video Valid Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 );
+
+ //
+ // Set Video Memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte;
+ /* Start D001 */
+ ULONG NowDisplayControlBase;
+ ULONG NowDisplayMemoryBase; // M021
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ LONG Index;
+ /* End D001 */
+ PCI_SLOT_NUMBER Slot; // M014
+ ULONG ReadValue; // M014
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_DUO_)
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ if (HalpDisplayPCIDevice == TRUE){
+
+ //
+ // the display type is PCI
+ // check physical address and reinitialize PTE
+ // we assume that the device has no function
+ //
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){
+
+ //
+ // DEC21030
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0)+ TGA_REG_SPC_OFFSET;
+ NowDisplayMemoryBase = 0;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){
+
+ //
+ // GLINT 300SX
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0);
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ NowDisplayMemoryBase = (ReadValue & 0xfffffff0);
+
+ }
+ }
+
+ //
+ // check to see if address has been changed
+ //
+
+ if (HalpDisplayControlBase != NowDisplayControlBase ||
+ HalpDisplayMemoryBase != NowDisplayMemoryBase){
+
+ // Called by OS, so reinitialize PTE
+ HalpDisplayControlBase = NowDisplayControlBase;
+ HalpDisplayMemoryBase = NowDisplayMemoryBase;
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+ Pte.N = 1;
+#endif
+#if defined(R4000)
+ Pte.C = UNCACHED_POLICY;
+#endif
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+
+ HalpGlintPhygicalVideo.HighPart = 1;
+ HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase;
+ Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+ HalpGlintPhygicalVideoCont.HighPart = 1;
+ HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase;
+
+ //
+ // IBM RGB525
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 2) = Pte;
+
+ //
+ // GLINT 300SX Internal Video Registers
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 1) = Pte;
+
+ //
+ // GLINT 300SX Control Status Registers
+ //
+
+ Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+ }
+ }
+ }
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+// M003 +++
+ if (HalpResetDisplayParameters &&
+ HalpDisplayControllerSetup == HalpDisplayINT10Setup) {
+ //
+ // Video work-around. The video driver has a reset function,
+ // call it before resetting the system in case the bios doesn't
+ // know how to reset the displays video mode.
+ //
+
+ if (HalpResetDisplayParameters(80, 50)) {
+ }
+// M003---
+ }
+
+ //
+ // M010
+ // for Software controlled power suply.
+ //
+
+#if defined(_MRCPOWER_)
+ HalpMrcModeChange((UCHAR)0); // M007
+#endif // _MRCPOWER_
+
+ HalpDisplayControllerSetup();
+// HalpResetX86DisplayAdapter();
+
+ //
+ // M004
+ // re-initialize critical message
+ //
+
+ HalpInitDisplayStringIntoNvram();
+
+ }
+
+ //
+ // M004
+ // ESM critical error logging start (set colomn,row)
+ //
+
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ // M004
+ // ESM critical error logging(strings)
+ //
+
+ HalpStringBufferCopyToNvram();
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+#if defined(_DUO_)
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacterOld (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUSHORT DestinationShort; // M021
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE,
+ (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+
+// /* START M002 */
+// RtlMoveMemory((PUCHAR)VIDEO_MEMORY_BASE, // S013
+// (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+// HalpScrollLength);
+// /* END M002 */
+
+ if (HalpDisplayType16BPP) {
+ DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + HalpScrollLength);
+
+ } else {
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ }
+
+ if (HalpDisplayType16BPP) {
+ for (Index = 0; Index < HalpScrollLine/2; Index += 1) {
+ *DestinationShort++ = (USHORT)0x000f;
+ }
+
+ } else {
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ }
+
+ //
+ // M006
+ // ESM critical logging re-print(column, row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ //
+ // M006
+ // ESM critical logging re-print(column,row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ } else {
+
+ //
+ // M006
+ // ESM critical logging put character.
+ //
+
+ HalStringIntoBuffer( Character );
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterOld((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+//351
+VOID
+HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollINT10(1);
+ }
+
+ //
+ // M006
+ // ESM critical logging re-print(column, row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollINT10( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+
+ //
+ // M006
+ // ESM critical logging re-print(column,row)
+ //
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ HalpColumn = 0;
+
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterINT10(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ //
+ // M006
+ // ESM critical logging put character.
+ //
+
+ HalStringIntoBuffer( Character );
+
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollINT10(1);
+ }
+ }
+ HalpOutputCharacterINT10(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacterOld(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUSHORT DestinationShort; // M021
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ if (HalpDisplayType16BPP) {
+ DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth * sizeof(USHORT)));
+
+ } else {
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+ }
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+
+ if (HalpDisplayType16BPP) {
+ if (FontValue >> 31)
+ *DestinationShort++ = (USHORT)0xffff;
+ else
+ *DestinationShort++ = (USHORT)0x000f;
+
+ }else{
+ *Destination++ = (UCHAR) (FontValue >> 31) ^ 1; /* M008 */
+ }
+
+ FontValue <<= 1;
+ }
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ Destination +=
+ (1024 - HalpCharacterWidth);
+ }
+ else if (HalpDisplayType16BPP){
+ DestinationShort +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+ else {
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+
+ }
+ HalpColumn += 1;
+ return;
+}
+
+VOID
+Write_Dbg_Uchar(
+ PUCHAR Ioadress,
+ UCHAR Moji
+ )
+{
+#if defined (R96DBG)
+ DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji);
+#endif
+ WRITE_PORT_UCHAR(Ioadress,Moji);
+}
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+ )
+
+/*++
+ Routine Description:
+
+ This function moves blocks of memory.
+
+ Arguments:
+
+ Destination - Supplies a pointer to the destination address of
+ the move operation.
+
+ Source - Supplies a pointer to the source address of the move
+ operation.
+
+ Length - Supplies the length, in bytes, of the memory to be moved.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Remainder;
+ PUCHAR Dstend;
+ PUCHAR Srcend;
+
+ if ( (Source == Destination) || (Length == 0) ) {
+ return;
+ }
+
+ if ((Source < Destination)&((Source + Length) > Destination)) {
+ if((Destination - Source) > 4){
+ Remainder = (UCHAR) Length &0x03;
+ Length = Length / 4;
+ Dstend = Destination + Length - 4 ;
+ Srcend = Source + Length -4;
+
+ for (; Length > 0; Length--) {
+ *(PULONG)(Dstend) = *(PULONG)(Srcend);
+ Dstend -= 4;
+ Srcend -= 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+ for (; Length > 0; Length--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+
+ else {
+ if( (Source - Destination) > 4 ){
+ Remainder = (UCHAR) Length &0x03;
+ Length = Length / 4;
+ for (; Length > 0; Length--) {
+ *(PULONG)(Destination) = *(PULONG)(Source);
+ Destination += 4;
+ Source += 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ return;
+ }
+
+ for (; Length > 0; Length--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ }
+}
+
+VOID
+HalpOutputCharacterINT10 (
+ IN UCHAR Character
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 2 << 8; // AH = 2
+ Ebx = 0; // BH = page number
+ Edx = (HalpRow << 8) + HalpColumn;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
+ Ebx = 0;
+ Ecx = 1;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ HalpColumn += 1;
+}
+
+VOID
+HalpScrollINT10 (
+ IN UCHAR LinesToScroll
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 6 << 8; // AH = 6 (scroll up)
+ Eax |= LinesToScroll; // AL = lines to scroll
+ Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
+ Ecx = 0; // CH,CL = upper left
+ Edx = ((HalpDisplayText - 1) << 8)
+ + (HalpDisplayWidth - 1); // DH,DL = lower right // M001,S005
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+VOID
+HalpDisplayINT10Setup (
+ VOID
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 50; // M001
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ HalpResetX86DisplayAdapter(); // for compaq q-vision reset
+
+// M001 +++
+ //
+ // Load 8x8 font 80x50 on VGA
+ //
+ Eax = 0x1112; // AH = 11 AL=12
+ Ebx = 0;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+// M001 ---
+
+ //
+ // Set cursor to (0,0)
+ //
+ Eax = 0x02 << 8; // AH = 2
+ Ebx = 0; // BH = page Number
+ Edx = 0; // DH = row DL = column
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Make screen white on blue by scrolling entire screen
+ //
+ Eax = 0x06 << 8; // AH = 6 AL = 0
+ Ebx = TEXT_ATTR << 8; // BH = attribute
+ Ecx = 0; // (x,y) upper left
+ Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
+ Edx += HalpScrollLine/2;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+}
+
+// start M014
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffffffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+
+
+BOOLEAN
+HalpCheckPCIDevice (
+ IN PCI_SLOT_NUMBER Slot
+ )
+
+/*++
+ Routine Description:
+
+ This function checks if spcified PCI slot is valid.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+
+ Return Value:
+
+ TRUE - specified slot is valid
+ FALSE - specified slot is invalid
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ BOOLEAN ReturnValue;
+ ULONG OrigData;
+ ULONG IdValue;
+ KIRQL OldIrql;
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+ OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
+
+ //
+ // read VendorID and DeviceID of the specified slot
+ //
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+ IdValue = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ if ((USHORT)(IdValue & 0xffff) == 0xffff){
+
+ //
+ // waiting until ReceivedMasterAbort bit is set
+ //
+
+ while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
+ ;
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000)
+
+ //
+ // M018
+ // Clear memory address error registers.
+ //
+
+ {
+ LARGE_INTEGER registerLarge;
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ }
+
+ ReturnValue = FALSE;
+
+ } else {
+
+ ReturnValue = TRUE;
+
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+
+ return ReturnValue;
+
+}
+// end M014
+
+#if defined(_R94A_)
+VOID
+HalpDisplayGlintSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GLINT 300SX Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ __VIDEO __Video;
+ VIDEO Video = &__Video;
+ long ClockDivider;
+
+ // for initialize ramdac
+ ULONG Dac = RGB525_REGISTER_BASE;
+ UCHAR ByteVal;
+
+ // for initialize timing
+ ULONG Glint = GLINT_VIDEO_REGISTER_BASE - 0x3000;
+
+ // for initialize control
+ ULONG SerialClk;
+ ULONG Temp;
+ ULONG Data;
+ ULONG Mask;
+
+ // for initialize RampLut
+ ULONG Index;
+
+ // for clear the screen
+ PULONG DestinationUlong;
+ ULONG Length;
+
+ /* check revision id R01 or R02. assume 40MHz(R01) or 50MHz(R02) reference clock for now */
+
+ if ( HalpGlintRevisionId == 0){
+ Video->RefDivCount = RGB525_PLL_REFCLK_40_MHz;
+ } else {
+ Video->RefDivCount = RGB525_PLL_REFCLK_50_MHz; // S006
+ }
+
+//
+// Calculate vertical frequency.
+//
+
+#if defined(_GLINT60HZ_)
+
+ VerticalFrequency = 60;
+
+#else
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+#endif // _GLINT60HZ_
+
+ //
+ // Initialize video data
+ //
+
+ /* get timing values for named resolution */
+
+ if ( HalpMonitorConfigurationData.HorizontalResolution == 1280
+ && HalpMonitorConfigurationData.VerticalResolution == 1024
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 1280;
+ Video->ImageHeight = 1024;
+ Video->HLimit = 8 * 211;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 51;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 1066;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 42;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 134 MHz */
+ Video->PixelClock = RGB525_DF(3) | RGB525_VCO_DIV_COUNT(2);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 164;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 14;
+ Video->HBlankEnd = 8 * 36;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 800;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 32;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ /* 79 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(14);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768
+ && VerticalFrequency == 60)
+ {
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 168;
+ Video->HSyncStart = 8 * 3;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 40;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 806;
+ Video->VSyncStart = 4;
+ Video->VSyncEnd = 10;
+ Video->VBlankEnd = 38;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 65 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 800;
+ Video->ImageHeight = 600;
+ Video->HLimit = 8 * 132;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 12;
+ Video->HBlankEnd = 8 * 32;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 625;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 25;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH;
+ /* 49.5 MHz */
+ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(34);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600
+ && VerticalFrequency == 60)
+ {
+ Video->ImageWidth = 800;
+ Video->ImageHeight = 600;
+ Video->HLimit = 8 * 132;
+ Video->HSyncStart = 8 * 5;
+ Video->HSyncEnd = 8 * 21;
+ Video->HBlankEnd = 8 * 32;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 628;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 6;
+ Video->VBlankEnd = 28;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH;
+ /* 40 MHz */
+ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(15);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 // add 4/5/1995
+ && HalpMonitorConfigurationData.VerticalResolution == 480
+ && VerticalFrequency == 60)
+ {
+ Video->ImageWidth = 640;
+ Video->ImageHeight = 480;
+ Video->HLimit = 8 * 100;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 14;
+ Video->HBlankEnd = 8 * 20;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 525;
+ Video->VSyncStart = 12;
+ Video->VSyncEnd = 13;
+ Video->VBlankEnd = 45;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW;
+ /* 31.5 MHz */
+ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(36);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480
+ && VerticalFrequency == 75)
+ {
+ Video->ImageWidth = 640;
+ Video->ImageHeight = 480;
+ Video->HLimit = 8 * 105;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 10;
+ Video->HBlankEnd = 8 * 25;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 500;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 20;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW;
+ /* 31.5 MHz */
+ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(61);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1280
+ && HalpMonitorConfigurationData.VerticalResolution == 1024
+ && VerticalFrequency == 57)
+ {
+ Video->ImageWidth = 1280;
+ Video->ImageHeight = 1024;
+ Video->HLimit = 8 * 211;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 51;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 1066;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 42;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 103 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(38);
+ }
+ else {
+ //
+ // force to set the resolution. 1024x768(60MHz)
+ //
+
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 168;
+ Video->HSyncStart = 8 * 3;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 40;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 806;
+ Video->VSyncStart = 4;
+ Video->VSyncEnd = 10;
+ Video->VBlankEnd = 38;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 65 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0);
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+
+ /* record image depth */
+
+ Video->ImageDepth = 16;
+
+ /* determine video clock divider and pixel format */
+
+ ClockDivider = 4;
+ Video->PixelFormat = RGB525_PIXEL_FORMAT_16_BPP;
+
+ /* adjust horizontal timings */
+
+ Video->HLimit /= ClockDivider;
+ Video->HSyncStart /= ClockDivider;
+ Video->HSyncEnd /= ClockDivider;
+ Video->HBlankEnd /= ClockDivider;
+
+ //
+ // Initialize ramdac data
+ //
+
+ RGB525_WRITE(Dac, __RGB525_PixelMask, 0xff);
+
+ /* set MiscControlOne register */
+ ByteVal = RGB525_MISR_CNTL_OFF
+ | RGB525_VMSK_CNTL_OFF
+ | RGB525_PADR_RFMT_READ_ADDR
+ | RGB525_SENS_DSAB_DISABLE
+ | RGB525_VRAM_SIZE_64;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlOne, ByteVal);
+
+ /* set MiscControlTwo register */
+ ByteVal = RGB525_PCLK_SEL_PLL
+ | RGB525_INTL_MODE_DISABLE
+ | RGB525_BLANK_CNTL_NORMAL
+ | RGB525_COL_RES_8_BIT
+ | RGB525_PORT_SEL_VRAM;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlTwo, ByteVal);
+
+ /* set MiscControlThree register */
+ ByteVal = RGB525_SWAP_RB_DISABLE
+ | RGB525_SWAP_WORD_31_00_FIRST
+ | RGB525_SWAP_NIB_07_04_FIRST;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlThree, ByteVal);
+
+ /* set MiscClockControl register */
+ ByteVal = RGB525_DDOTCLK_DISABLE
+ | RGB525_SCLK_ENABLE
+ | RGB525_PLL_ENABLE;
+ RGB525_SET_REG(Dac, __RGB525_MiscClockControl, ByteVal);
+
+ /* set SyncControl register */
+ ByteVal = RGB525_DLY_CNTL_ADD
+ | RGB525_VSYN_INVT_DISABLE
+ | RGB525_HSYN_INVT_DISABLE
+ | RGB525_VSYN_CNTL_NORMAL
+ | RGB525_HSYN_CNTL_NORMAL;
+ RGB525_SET_REG(Dac, __RGB525_SyncControl, ByteVal);
+
+ /* set HSyncControl register */
+ RGB525_SET_REG(Dac, __RGB525_HSyncControl, RGB525_HSYN_POS(0));
+
+ /* set PowerManagement register */
+ ByteVal = RGB525_SCLK_PWR_NORMAL
+ | RGB525_DDOT_PWR_DISABLE
+ | RGB525_SYNC_PWR_NORMAL
+ | RGB525_ICLK_PWR_NORMAL
+ | RGB525_DAC_PWR_NORMAL;
+ RGB525_SET_REG(Dac, __RGB525_PowerManagement, ByteVal);
+
+ /* set DACOperation register */
+ ByteVal = RGB525_SOG_DISABLE
+ | RGB525_BRB_NORMAL
+ | RGB525_DSR_FAST
+ | RGB525_DPE_ENABLE; /* disable? */
+ RGB525_SET_REG(Dac, __RGB525_DACOperation, ByteVal);
+
+ /* set PaletteControl register */
+ ByteVal = RGB525_6BIT_LINEAR_ENABLE
+ | RGB525_PALETTE_PARTITION(0);
+ RGB525_SET_REG(Dac, __RGB525_PaletteControl, ByteVal);
+
+ /* set PixelFormat register */
+ RGB525_SET_REG(Dac, __RGB525_PixelFormat, Video->PixelFormat);
+
+ /* set 8BitPixelControl register */
+ RGB525_SET_REG(Dac, __RGB525_8BitPixelControl,
+ RGB525_B8_DCOL_INDIRECT);
+
+ /* set 16BitPixelControl register */
+ ByteVal = RGB525_B16_DCOL_INDIRECT
+ | RGB525_B16_565
+ | RGB525_B16_ZIB
+ | RGB525_B16_SPARSE;
+
+ RGB525_SET_REG(Dac, __RGB525_16BitPixelControl, ByteVal);
+
+ /* set 32BitPixelControl register */
+ RGB525_SET_REG(Dac, __RGB525_32BitPixelControl,
+ RGB525_B32_DCOL_INDIRECT);
+
+ /* set PLLControlOne register */
+ ByteVal = RGB525_REF_SRC_REFCLK
+ | RGB525_PLL_INT_FS_DIRECT;
+ RGB525_SET_REG(Dac, __RGB525_PLLControlOne, ByteVal);
+
+ /* set PLLControlTwo register */
+ RGB525_SET_REG(Dac, __RGB525_PLLControlTwo, RGB525_PLL_INT_FS(0));
+
+ /* set PLLRefDivCount register */
+ RGB525_SET_REG(Dac, __RGB525_PLLRefDivCount, Video->RefDivCount);
+
+ /* set F0 register */
+ RGB525_SET_REG(Dac, __RGB525_F0, Video->PixelClock);
+
+ /* set CursorControl register */
+ RGB525_SET_REG(Dac, __RGB525_CursorControl, RGB525_CURSOR_MODE_OFF);
+
+ //
+ // Initialize timing
+ //
+
+ /* horizontal video timing values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGHLimit, Video->HLimit);
+ GLINT_WRITE(Glint, __GLINT_VTGHSyncStart, Video->HSyncStart);
+ GLINT_WRITE(Glint, __GLINT_VTGHSyncEnd, Video->HSyncEnd);
+ GLINT_WRITE(Glint, __GLINT_VTGHBlankEnd, Video->HBlankEnd);
+
+ /* vertical video timing values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGVLimit, Video->VLimit);
+ GLINT_WRITE(Glint, __GLINT_VTGVSyncStart, Video->VSyncStart);
+ GLINT_WRITE(Glint, __GLINT_VTGVSyncEnd, Video->VSyncEnd);
+ GLINT_WRITE(Glint, __GLINT_VTGVBlankEnd, Video->VBlankEnd);
+
+ /* horizontal clock gate values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGHGateStart, Video->HBlankEnd - 2);
+ GLINT_WRITE(Glint, __GLINT_VTGHGateEnd, Video->HLimit - 2);
+
+ /* vertical clock gate values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGVGateStart, Video->VBlankEnd - 1)
+ GLINT_WRITE(Glint, __GLINT_VTGVGateEnd, Video->VBlankEnd);
+
+ //
+ // Initialize control
+ //
+
+ /* serial clock control */
+
+ SerialClk = GLINT_EXTERNAL_QSF
+ | GLINT_SPLIT_SIZE_128_WORD
+ | GLINT_SCLK_VCLK_DIV_2;
+
+ GLINT_WRITE(Glint, __GLINT_VTGSerialClk, SerialClk);
+
+ /* set sync polarities and unblank screen */
+
+ // UpdatePolarityRegister(Glint,
+ // GLINT_CBLANK_ACTIVE_LOW
+ // | Video->HSyncPolarity
+ // | Video->VSyncPolarity,
+ // GLINT_CBLANK_POLARITY_MASK
+ // | GLINT_HSYNC_POLARITY_MASK
+ // | GLINT_VSYNC_POLARITY_MASK);
+
+ Data = GLINT_CBLANK_ACTIVE_LOW
+ | Video->HSyncPolarity
+ | Video->VSyncPolarity;
+ Mask = GLINT_CBLANK_POLARITY_MASK
+ | GLINT_HSYNC_POLARITY_MASK
+ | GLINT_VSYNC_POLARITY_MASK;
+
+ /* read video polarity control register */
+
+ GLINT_READ(Glint, __GLINT_VTGPolarity, Temp);
+
+ /* replace existing polarity field */
+
+ Temp = (Temp & ~Mask) | (Data & Mask);
+
+ /* write result back to polarity register */
+
+ GLINT_WRITE(Glint, __GLINT_VTGPolarity, Temp);
+
+ /* set FrameRowAddr */
+
+ GLINT_WRITE(Glint, __GLINT_VTGFrameRowAddr, 0);
+
+ //
+ // Initialize RampLut
+ //
+
+ /* initialise palette address */
+
+ RGB525_WRITE(Dac, __RGB525_PalAddrWrite, 0);
+
+ /* ramp colour components using auto-increment */
+
+ for (Index = 0; Index <= 0xff; Index++)
+ {
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ }
+
+ //
+ // Clear the screen.
+ //
+
+ DestinationUlong = (PULONG)VIDEO_MEMORY_BASE;
+
+ Length = (HalpMonitorConfigurationData.VerticalResolution *
+ HalpMonitorConfigurationData.HorizontalResolution -1) * sizeof(USHORT);
+
+ for (Index = 0; Index < (Length / sizeof(ULONG)); Index++)
+ *(DestinationUlong++) = (ULONG)0x000f000f;
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+}
+#endif // _R94A_
+
+//
+// M010
+// for software controlled power supply.
+//
+#if defined(_MRCPOWER_)
+/* Start M007 */
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+)
+/*++
+
+Routine Description:
+
+ This routine is change Mode bit on MRC Controller.
+
+Arguments:
+
+ Mode - Parameter for setting Mode bit on MRC
+
+Return Value:
+
+ None
+
+--*/
+{
+
+ PHYSICAL_ADDRESS physicalAddress;
+ UCHAR ModeNow;
+ KIRQL OldIrql;
+ ENTRYLO Pte[2];
+
+ //
+ // MRC Controller Mapping, when first call
+ //
+
+ if (HalpMrcControlMapped == FALSE) {
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = MRC_TEMP_PHYSICAL_BASE;
+ HalpMrcControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ if (HalpMrcControlBase != NULL) {
+ HalpMrcControlMapped = TRUE;
+ }
+ }
+
+ if (HalpMrcControlMapped == TRUE){
+
+ ModeNow = READ_REGISTER_UCHAR(
+ &((PMRC_REGISTERS)HalpMrcControlBase)->Mode
+ );
+
+ //
+ // Set MRC Mode bit
+ //
+ WRITE_REGISTER_UCHAR(
+ &((PMRC_REGISTERS)HalpMrcControlBase)->Mode,
+ ((ModeNow & 0x02) | (Mode << 7)),
+ );
+
+ } else {
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT;
+
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ //
+ // Map MRC using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ ModeNow = READ_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode // B028
+ );
+
+ //
+ // Set MRC Mode bit
+ //
+ WRITE_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode,
+ ((ModeNow & 0x02) | (Mode << 7)),
+ );
+
+
+ // Start M008
+ //
+ // Resume fixed TLB for DMA
+ //
+
+ Pte[0].PFN = DMA_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ Pte[0].C = UNCACHED_POLICY;
+
+
+ Pte[1].PFN = INTERRUPT_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[1].G = 1;
+ Pte[1].V = 1;
+ Pte[1].D = 1;
+
+ Pte[1].C = UNCACHED_POLICY;
+
+ // End M008
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ KeLowerIrql(OldIrql);
+ }
+}
+/* End M007 */
+#endif // _MRCPOWER_
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function writes PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data to write.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffffffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+ WRITE_REGISTER_ULONG(R94A_PCI_DATA_REG, *Buffer);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)));
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+ WRITE_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)));
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017
+// KiAcquireSpinLock(&HalpPCIConfigLock);
+
+ WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue));
+
+// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG);
+ WRITE_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer);
+
+ //
+ // Release spinlock
+ //
+
+// KiReleaseSpinLock(&HalpPCIConfigLock);
+// KeLowerIrql(OldIrql);
+
+ return;
+}
diff --git a/private/ntos/nthals/halr96b/mips/jxdmadsp.s b/private/ntos/nthals/halr96b/mips/jxdmadsp.s
new file mode 100644
index 000000000..370edd47f
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxdmadsp.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxdmadsp.s"
diff --git a/private/ntos/nthals/halr96b/mips/jxebsup.c b/private/ntos/nthals/halr96b/mips/jxebsup.c
new file mode 100644
index 000000000..5fa4f8677
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxebsup.c
@@ -0,0 +1,1398 @@
+// #pragma comment(exestr, "@(#) jxebsup.c 1.1 95/09/28 15:36:45 nec")
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+Author:
+
+ Jeff Havens (jhavens) 19-Jun-1991
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - HalpCreateEisa(PCI)Structures()
+ function name changed.
+ interrupt dispatcher is changed for PCI/EISA.
+ comment out EISA NMI disable code.
+ - HalpEisaDispatch()
+ add the PCI interrupt handler.
+ add the avoidance the IR7 and IR15 spurious interrupt.
+ H001 Tue Oct 11 18:52:39 JST 1994 kbnes!kishimoto
+ - modify original compile error
+ H002 Mon Oct 17 13:54:43 JST 1994 kbnes!kishimoto
+ - Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ - modify original compile error
+ S003 Thu Dec 22 11:39:57 JST 1994 kbnes!A.Kuriyama
+ -add beta machine limit
+ S004 Mon Jan 23 13:57:08 JST 1995 kbnes!A.Kuriyama
+ -add raise irql for dummyread for EISA/PCI acknouledge
+ H003 Tue Jan 24 19:04:04 1995 kbnes!kishimoto
+ -Add Enable the PCI interrupts to the CPU
+ M005 Wed Jan 25 21:02:51 JST 1995 kbnes!A.Kuriyama
+ -add 64byte align between dummy read and EISA/PCI Ack.
+ H006 Tue Feb 7 21:04:30 JST 1995 kbnes!kisimoto
+ -bug fix when spurious interrupt occurs
+ S007 kuriyama@oa2.kb.nec.co.jp Thu Apr 06 00:18:14 JST 1995
+ - Disable EISA NMI
+ S008 kuriyama@oa2.kb.nec.co.jp Mon May 22 03:58:30 JST 1995
+ - add panicflag for esm
+ S009 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 19:18:10 JST 1995
+ - Merge build 1057
+ H010 kisimoto@oa2.kb.nec.co.jp Fri Aug 11 17:40:26 1995
+ - Removed M005, etc.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+//
+// Define EISA bus interrupt affinity.
+//
+
+KAFFINITY HalpEisaBusAffinity;
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch ((UCHAR)channelNumber) { // H001
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ KIRQL oldIrql;
+
+#if !defined(_DUO_) && !defined(_R94A_) // H000
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#else
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+// DataByte = 0;
+ //
+ // TEMPTEMP Disable the NMI because this is causing machines in the build
+ // lab to fail.
+ //
+ DataByte = 0x80;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+#endif
+
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] =
+ (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // start H003
+ // Enable the following PCI interrupts to the CPU.
+ // Target abort, Master abort
+ // SRetry overflow, ERR, PERR
+ //
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long);
+ DataLong |= ENABLE_PERR_INTERRUPTS;
+ DataLong |= ENABLE_SERR_INTERRUPTS;
+ DataLong |= ENABLE_RETRY_OVERFLOW_EISA_INTERRUPTS;
+ DataLong |= ENABLE_MASTER_ABORT_INTERRUPTS;
+ DataLong |= ENABLE_TARGET_ABORT_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long,
+ DataLong);
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Set EISA bus interrupt affinity.
+ //
+
+ HalpEisaBusAffinity = PCR->SetMember;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+#if defined(_DUO_)
+
+ //
+ // Enable the EISA interrupts to the CPU.
+ //
+
+ DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+ DataLong |= ENABLE_EISA_INTERRUPTS;
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+ DataLong);
+
+#endif
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+#if defined(_DUO_)
+
+ PUSHORT Acknowledge = (PUSHORT)&DMA_CONTROL->EisaInterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_USHORT(Acknowledge);
+
+#else
+
+ PUCHAR Acknowledge = (PUCHAR)&DMA_CONTROL->InterruptAcknowledge.Long;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(Acknowledge);
+
+#endif
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+ if (interruptVector != 0x8000) {
+
+ //
+ // H000
+ // If the interrupt vector is 0x4000 then this is an PCI interrupt.
+ // Call the PCI interrupt handler.
+ //
+
+ if (interruptVector != 0x4000) {
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+
+ //
+ // H000
+ // check to see if this is a spurious interrupt
+ //
+
+ if (interruptVector == 7 || interruptVector == 15){
+ PVOID IsrPortAddressVa;
+ UCHAR IsrValue;
+
+ #define OCW3_READ_ISR 0x0b
+ #define OCW3_READ_IRR 0x0a
+
+ IsrPortAddressVa = (interruptVector == 7) ?
+ &(((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0):
+ &(((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0); // H006
+
+ //
+ // Change mode OCW3 register, bacause we want to read ISR
+ // read ISR on 8259.
+ //
+
+ WRITE_REGISTER_UCHAR(IsrPortAddressVa, OCW3_READ_ISR);
+ IsrValue = READ_REGISTER_UCHAR( IsrPortAddressVa );
+
+ //
+ // resume mode OCW3 register to IRR
+ //
+
+ WRITE_REGISTER_UCHAR(IsrPortAddressVa, OCW3_READ_IRR);
+
+ //
+ // check to see if ISR is zero, then we do not call driver.
+ //
+
+ if ( !IsrValue ){
+
+ goto NotCallDriver;
+
+ }
+ }
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+NotCallDriver:
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+
+ } else {
+ returnValue = HalpPCIDispatch(NULL, NULL);
+ }
+
+ } else {
+ returnValue = HalHandleNMI(NULL, NULL);
+ }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+
+ BytePtr = (PUCHAR) &Offset;
+
+ ASSERT(Offset >= 0x100000);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // S008
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halr96b/mips/jxenvirv.c b/private/ntos/nthals/halr96b/mips/jxenvirv.c
new file mode 100644
index 000000000..c78505bcf
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxenvirv.c
@@ -0,0 +1,800 @@
+// #pragma comment(exestr, "@(#) jxenvirv.c 1.1 95/09/28 15:37:20 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ M001 95.4.25 Y.Nakatani
+ - Add Interface of NVRAM for ESM
+ M002 kuriyama@oa2.kb.nec.co.jp Sun May 21 20:46:25 JST 1995
+ - Change Nvram virtual address
+ M003 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 19:25:54 JST 1995
+ - Removed _J94C_ definitions.
+ _J94C_ definition indicates that the status of
+ the dump switch can acknowledge from Self-test
+ register.
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "jazznvr.h"
+#include "string.h"
+
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+// M002 +++
+KIRQL
+HalpEsmMapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the ESM NVRAM into a wired TB entry.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO NvramPte[2];
+
+ //
+ // Construct a pair of PTE's to map NVRAM.
+ //
+
+ NvramPte[0].X1 = 0;
+ NvramPte[0].PFN = 0x80013000 >> PAGE_SHIFT;
+ NvramPte[0].G = 0;
+ NvramPte[0].V = 1;
+ NvramPte[0].D = 1;
+ NvramPte[0].C = UNCACHED_POLICY;
+ NvramPte[1] = NvramPte[0];
+ NvramPte[1].PFN += 1;
+
+ //
+ // Raise IRQL to the highest level, allocate a TB entry, map NVRAM
+ // using the alocated entry, and return the previous IRQL.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0],
+ (PVOID)NVRAM_VIRTUAL_BASE,
+ HalpAllocateTbEntry());
+
+ return OldIrql;
+}
+// M002 ---
+
+KIRQL
+HalpMapNvram (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into a wired TB entry.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO NvramPte[2];
+
+ //
+ // Construct a pair of PTE's to map NVRAM.
+ //
+
+ NvramPte[0].X1 = 0;
+ NvramPte[0].PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
+ NvramPte[0].G = 0;
+ NvramPte[0].V = 1;
+ NvramPte[0].D = 1;
+ NvramPte[0].C = UNCACHED_POLICY;
+ NvramPte[1] = NvramPte[0];
+ NvramPte[1].PFN += 1;
+
+ //
+ // Raise IRQL to the highest level, allocate a TB entry, map NVRAM
+ // using the alocated entry, and return the previous IRQL.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0],
+ (PVOID)NVRAM_VIRTUAL_BASE,
+ HalpAllocateTbEntry());
+
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from a wired entry in
+ the TB.
+
+Arguments:
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the wired TB entry that was allocated to map NVRAM and lower
+ // IRQL to its previous level.
+ //
+
+ HalpFreeTbEntry();
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram();
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(OldIrql);
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram();
+ Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(OldIrql);
+ return Status;
+}
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Write Byte Count
+ PVOID Buffer // Pointer Of Buffer Write to NVRAM
+){
+ // Write into NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,1);
+}
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Read Byte Count
+ PVOID Buffer // Pointer Of Buffer Read From NVRAM
+){
+ // Read From NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,0);
+}
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset, // Read/Write offset of ESM NVRAM
+ ULONG Count, // Read/Write Byte Count
+ PVOID Buffer, // read/Write Pointer
+ ULONG Write // Operation
+){
+
+ KIRQL OldIrql;
+ ULONG i;
+ //
+ // Check is addr . So decrement 1
+ //
+ if(
+ Offset >=0 &&
+ Count >=0 &&
+ Offset <= 0x1fff && // M002 +++
+ Offset+Count-1 <= 0x1fff // M002 ---
+
+ ){
+
+ if(Write){
+ OldIrql = HalpEsmMapNvram(); // M002
+// if (HalpEsmDebug == 1) // test
+// DbgBreakPoint(); // test
+ for(i=0;i<Count;i++){ // test
+ WRITE_REGISTER_UCHAR((PUCHAR)(NVRAM_VIRTUAL_BASE+Offset+i),((PUCHAR)Buffer)[i]); // M002 +++
+ }
+ HalpUnmapNvram(OldIrql);
+ }else{
+ OldIrql = HalpEsmMapNvram(); // M002
+// if (HalpEsmDebug == 1) // test
+// DbgBreakPoint(); // test
+ for(i=0;i<Count;i++){
+ ((PUCHAR)Buffer)[i] =READ_REGISTER_UCHAR((PUCHAR)(NVRAM_VIRTUAL_BASE+Offset+i)); // M002
+
+ }
+ HalpUnmapNvram(OldIrql); // M002
+ }
+
+ return TRUE;
+
+ }else{
+
+ //
+ // It is no ESM NVRAM Erea.
+ return FALSE;
+ }
+
+}
diff --git a/private/ntos/nthals/halr96b/mips/jxhalp.h b/private/ntos/nthals/halr96b/mips/jxhalp.h
new file mode 100644
index 000000000..7232ebb11
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxhalp.h
@@ -0,0 +1,224 @@
+// #pragma comment(exestr, "@(#) jxhalp.h 1.1 95/09/28 15:37:58 nec")
+
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - New HalpCreateEisaPCIStructures()
+ - Del HalpCreateEisaStructures()
+ - New function HalpEisaPCIDispatch()
+ - Del function HalpEisaDispatch()
+ L000 Thu Oct 13 18:09:33 JST 1994 kbnes!kuriyama(A)
+ for BBM LED
+ - Add HalpDisplayLED
+ - Add HalpLEDDisplayLock
+ - Add HalpLEDControlBase;
+ L002 Mon Oct 17 14:21:39 JST 1994 kbnes!kuriyama(A)
+ change function name EISAPCI... EISA..
+ H001 Mon Oct 17 14:45:04 JST 1994 kbnes!kishimoto
+ - Del HalDisplayLED() function definitions.
+ (We call HalR94aDebugPrint() instead of that.)
+ H002 Thu Oct 20 20:58:45 JST 1994 kbnes!kishimoto
+ - add extern ULONG R94aBbmLEDMapped
+ for debug use only.
+ H003 Fri Oct 21 15:52:32 JST 1994 kbnes!kishimoto
+ - add HalR94aDebugPrint() prototype definition.
+ H004 Mon Jan 16 02:28:58 1995 kbnes!kishimoto
+ - add HalpPCIConfigLock
+ S005 Tue Mar 07 14:55:42 JST 1995 kbnes!kuriyama (A)
+ - add Dma32BitAddresses to AdapterObject
+ H006 Fri Jul 21 17:40:53 JST 1995 kbnes!kisimoto
+ - merge ESM functions from J94C
+ H007 Sat Aug 12 15:12:28 JST 1995 kbnes!kisimoto
+ - Removed BBMLED, R94ALEDMAP code and _J94C_ definitions.
+ _J94C_ definition indicates that the status of
+ the dump switch can acknowledge from Self-test
+ register.
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+#if defined(_DMA_EXPAND_) // S005
+ BOOLEAN Dma32BitAddresses;
+#endif //_DMA_EXPAND_
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#if defined(_R94A_)
+
+PADAPTER_OBJECT
+HalpAllocatePCIAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpEnablePCIInterrupt (
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePCIInterrupt (
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID // H004
+HalpInitBusHandlers (
+ VOID
+ );
+
+extern KSPIN_LOCK HalpPCIConfigLock; // H004
+
+#endif
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ );
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ );
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ );
+
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ );
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ );
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ );
+
+#if DBG // H003
+VOID
+HalR94aDebugPrint(
+ ULONG DebugLevel,
+ PUCHAR LedCharactor,
+ PUCHAR Message,
+ ...
+ );
+
+int
+printNvramData(
+ void
+ );
+
+#endif
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halr96b/mips/jxhwsup.c b/private/ntos/nthals/halr96b/mips/jxhwsup.c
new file mode 100644
index 000000000..aa220a2d8
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxhwsup.c
@@ -0,0 +1,4265 @@
+// #pragma comment(exestr, "@(#) jxhwsup.c 1.1 95/09/28 15:38:22 nec")
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ M0001 1994.9.8 kuriyama@oa2
+ - Modify for R94A MIPS R4400
+
+ HalGetAdapter() - add routine for support PCIBus
+ Modify Internal MAX Dma Channel (r94a 0-3)
+
+ HalTranslateBusAddress() - add routine for support PCIBus
+
+ HalGetBusDataBy
+
+ M0002 1994.10.7 kuriyama@oa2
+ - Modify HalDmaChannel() - terminal count logic bug fix.
+
+ M0003 1994.10.14 kuriyama@oa2
+ - compile error clear
+ CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 23:20:04 JST 1994
+ - Merge BusHandlers
+
+ M0004 Fri Oct 28 14:56:02 JST 1994 kuriyama@oa2
+ - add BBM DMA routine (for edit buffer)(for BBM limited)
+ - add I/O cache flush if physical tag is valid(for BBM limited)
+ D001 ataka@oa2.kb.nec.co.jp (DMA CopyBuffer by kuriyama@oa2, other toghether)
+ Sat Nov 05 16:28:04 JST 1994
+ - Limit Check of Length (Only DbgPrint)
+ - Delete checking ByteMask
+ - TLB fill 0xff(by Kuriyama)
+
+ M005 Tue Dec 13 16:28:25 1994 kbnes!kisimoto
+ - changed the address that copies from, and source re-formated.
+
+ M0006 Thu Dec 22 11:46:16 JST 1994 kbnes!A.kuriyama
+ - add beta machine limit
+
+ S0007 Thu Jan 05 17:13:18 JST 1995 kbnes!A.Kuriyama
+ - warning clear
+
+ M0008 Fri Jan 13 13:49:51 JST 1995 kbnes!A.Kuriyama
+ - I/O cache flush routine was deleted in functions as follows
+ IoMapTransfer()
+ HalFlushCommonBuffer()
+
+ M0009 Mon Jan 23 14:31:44 JST 1995 kbnes!A.Kuriyama
+ - DMA Channel Interrupt routine change
+ - add Internal DMAC bytecount mask
+
+ M0010 Mon Jan 23 15:36:18 JST 1995 kbnes!A.Kuriyama
+ - Dma channel interrupt enable
+ HalpAllocateAdapter()
+ HalpCreateDmaStructure()
+
+ S0011 Tue Jan 24 18:28:55 JST 1995 kbnes!A.Kuriyama
+ - Compile error clear
+
+ M0012 Tue Jan 31 18:04:08 JST 1995 kbnes!A.Kuriyama
+ - add Internal slave dma 1MB limit.
+
+ M0013 Tue Jan 31 18:07:53 JST 1995 kbnes!A.Kuriyama
+
+ M0014 Tue Jan 31 18:37:33 JST 1995 kbnes!A.Kuriyama
+ - change I/O cache flush routine.
+ if length equal 0 no need i/o cache flush.
+
+ S0015 Wed Feb 01 12:03:06 JST 1995 kbnes!A.Kuriyama
+ - sccs update miss error clear
+
+ B0016 Thu Feb 2 22:09:32 1995 kbnes!kishimoto
+ - return pointer to adapterObject if InterfaceType
+ equals PCIBus
+
+ S0017 Wed Feb 22 12:00:58 JST 1995 kbnes!kuriyama (A)
+ - disable dma terminal interrupt
+
+ M0018 Tue Mar 07 11:26:44 JST 1995 kbnes!kuriyama (A)
+ - expand dma logical address space
+
+ S0019 Tue Mar 07 15:22:00 JST 1995 kbnes!kuriyama (A)
+ - compile error clear
+
+ M0020 Fri Mar 10 11:44:25 JST 1995 kbnes!kuriyama (A)
+ - logical address expand bug fix
+
+ S0021 Fri Mar 10 16:23:12 JST 1995 kbnes!kuriyama (A)
+ - internal slave bug fix
+
+ S0022 Tue Jun 27 19:12:30 JST 1995 kbnes!kisimoto
+ - del memmove prototype definition
+ to merge build 1057
+ change strings displaied with Tyhoon error
+
+ S0023 Thu Jul 20 20:11:34 JST 1995 kbnes!kisimoto
+ - add code for ESM from J94C
+
+ M0024 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:36:13 JST 1995
+ - add for x86bios support
+ - (change internal dma address to 1M-4M)
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCreateDmaStructures)
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+#define HalDump(x,y) if(HalDebug > 0) DbgPrint( x,y )
+/* M0006 */
+
+/* start M0004 */
+ULONG HalDebug = 0;
+#if defined(_BBM_DMA_)
+//
+// define copybuffer allocate routine.
+//
+
+VOID
+HalpAllocateCopyBuffer(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+//
+// Allocate Variable for DMA CopyBuffer
+//
+ ULONG CopyBufferPhysicalBase;
+ ULONG CopyBufferVirtualAddress;
+
+#endif // _BBM_DMA_
+
+#if defined(_BETA_LIMIT_)
+PVOID
+HalViewMemory (
+ IN PVOID Destination,
+ IN ULONG Length
+ );
+#endif // _BETA_LIMIT_
+/* end M0004 */
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpDmaChannelInterrupt;
+
+/* start M0001 */
+#if defined(_R94A_)
+//
+// The following is the interrupt object used for Typhoon Error interrupts.
+// Typhoon errorr interrupts occur when internal busmaster device error occurs.
+//
+
+KINTERRUPT HalpTyphoonErrorInterrupt;
+
+#endif // _R94A_
+/* end M0001 */
+
+UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. ";
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+//
+// The following function is called when a DMA channel interrupt occurs.
+//
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[8];
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+/* start M0001 */
+#if defined(_R94A_)
+BOOLEAN
+HalpCreateTyphoonErrorStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpTyphoonError(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+#endif // _R94A_
+/* end M0001 */
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif //_DMA_EXPAND_
+// M0018 ---
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND_
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+
+ if (virtualAddress == NULL) {
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - *NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ Hint,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = Hint;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+#if 0 // M0008
+/* M0006 +++ */
+#if defined(_BETA_LIMIT_)
+{
+ ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, i;
+ KIRQL OldIrql;
+
+ // D001
+// DbgPrint("DmaFlush start\n");
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ Ltag = READ_REGISTER_ULONG(LtagReg);
+ if (Ptag & 0x1) {
+ if (Ltag & 0x1) {
+ if ((LogicalAddress.LowPart & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (LogicalAddress.LowPart + Length))) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+ }
+ }
+ KeLowerIrql(OldIrql);
+// DbgPrint("DmaFlush end\n");
+}
+#endif // _BETA_LIMIT_
+/* M0006 --- */
+#endif // 0 // M0008
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+ return;
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: Internal, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+// M0020 +++
+#if DBG
+#if defined (_DMA_EXPAND_)
+ DbgPrint("\nHalGetAdapter(): DeviceDescription->32BitAddresses = %d\n",DeviceDescription->Dma32BitAddresses);
+#endif // _DMA_EXPAND_
+#endif // DBG
+// M0020 ---
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) {
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+ }
+
+ if (DeviceDescription->InterfaceType == Internal) {
+
+
+ //
+ // Return the adapter pointer for internal adapters.
+ //
+ // If this is a master controler such as the SONIC then return the
+ // last channel.
+ //
+
+ if (DeviceDescription->Master) {
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Create an adapter.
+ //
+
+ adapterObject = HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[7],
+ NULL
+ );
+
+ adapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+
+// M0020 +++
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+#endif DBG
+
+ if (adapterObject->Dma32BitAddresses) {
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("internal master adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses);
+#endif // DBG
+// M0020 ---
+
+ return(adapterObject);
+
+#else // _DMA_EXPAND
+
+ //
+ // Create an adapter if necessary.
+ //
+
+ if (HalpInternalAdapters[7] == NULL) {
+
+ HalpInternalAdapters[7] = HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[7],
+ NULL
+ );
+
+ }
+
+ return(HalpInternalAdapters[7]);
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ }
+
+ //
+ // Make sure the DMA channel range is valid. Only use channels 0-6.
+ //
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ if (DeviceDescription->DmaChannel > 3) { // duo and r94a have only 0-3 channel
+
+ return(NULL);
+ }
+
+#else // _R94A_
+
+ if (DeviceDescription->DmaChannel > 6) {
+
+ return(NULL);
+ }
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // If necessary allocate an adapter; otherwise,
+ // just return the adapter for the requested channel.
+ //
+
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel] == NULL) {
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel] =
+ HalpAllocateAdapter(
+ 0,
+ (PVOID) &(DMA_CONTROL)->Channel[DeviceDescription->DmaChannel],
+ NULL
+ );
+
+ }
+
+// M0012 +++
+#if defined(_R94A_)
+// M0020 +++
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+#endif DBG
+// M0020 ---
+
+ //
+ // Internal slave dma limit 1MB. (TYPHOON tip limit)
+ //
+
+ if (*NumberOfMapRegisters > ( 0x100000 >> PAGE_SHIFT )) {
+
+ *NumberOfMapRegisters = ( 0x100000 >> PAGE_SHIFT );
+ }
+
+#endif // _R94A_
+// M0012 ---
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+// M0020 +++
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses) { // S0021
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses
+ = DeviceDescription->Dma32BitAddresses;
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("internal slave HalpInternalAdapters[%d]->Dma32BitAddresses = %d\n",
+ DeviceDescription->DmaChannel,
+ HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses);
+#endif // DBG
+
+// M0020 ---
+#endif // _DMA_EXPAND_
+// M0018 ---
+ return(HalpInternalAdapters[DeviceDescription->DmaChannel]);
+ }
+
+/* start M0001 */
+#if defined(_R94A_)
+ //
+ // PCI Bus check.
+ //
+ if (DeviceDescription->InterfaceType == PCIBus) {
+
+ adapterObject = HalpAllocatePCIAdapter( DeviceDescription );
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+// M0020 +++
+ if (adapterObject->Dma32BitAddresses) {
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+
+ adapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("PCI master adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses);
+#endif // DBG
+// M0020 ---
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ return(adapterObject); // B0016
+
+ }
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != Eisa) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+// M0020 +++
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+#endif DBG
+// M0020 ---
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+// M0020 +++
+ if (adapterObject->Dma32BitAddresses) {
+ if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR)
+ / PAGE_SIZE / 8L;
+ }
+ } else {
+ if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) {
+ *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L;
+ }
+ }
+
+#if DBG
+ DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters);
+ DbgPrint("eisa/isa adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses);
+#endif // DBG
+// M0020 ---
+
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ return(adapterObject);
+}
+
+#if 0 // CHG0001
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ return(TRUE);
+ }
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != PCIBus) {
+
+#else // _R94A_
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // There is only one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+
+#if !defined(_DUO_)
+
+ if (DMA_CONTROL->RevisionLevel.Long < 2) {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ } else {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+ }
+#else
+
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+#endif
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+}
+#endif
+
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+ ULONG Mode;
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter( 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if (AdapterBaseVa == NULL) {
+
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+ AdapterObject->PagePort = NULL;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+ ULONG MapRegisterSize;
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // set bit for unusable area
+ //
+
+// M0020 +++
+#if DBG
+ DbgPrint("translatiron start %x\n",HalpMapRegisterPhysicalBase);
+ DbgPrint("translatiron size %x\n",MapRegisterSize);
+#endif // DBG
+
+ RtlFindClearBitsAndSet(
+ AdapterObject->MapRegisters,
+ ((EISA_MIN_ADR - ISA_MAX_ADR) / PAGE_SIZE),
+ (ISA_MAX_ADR / PAGE_SIZE)
+ );
+ DbgPrint("unused start %x\n",ISA_MAX_ADR / PAGE_SIZE);
+ DbgPrint("unused length %x\n",(EISA_MIN_ADR - ISA_MAX_ADR) / PAGE_SIZE);
+// M0020 ---
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG1_BASE);
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationBase.Long,
+ HalpMapRegisterPhysicalBase
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->TranslationLimit.Long,
+ MapRegisterSize
+ );
+
+ //
+ // Initialize the DMA mode registers for the Floppy, SCSI and Sound.
+ // The initialization values come fomr the System Specification.
+ //
+
+#if defined(_JAZZ_)
+
+ Mode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_120NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_8BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[FLOPPY_CHANNEL].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_A].Mode.Long,
+ (ULONG) Mode
+ );
+
+ ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS;
+ ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS;
+ ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0;
+ ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1;
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->Channel[SOUND_CHANNEL_B].Mode.Long,
+ (ULONG) Mode
+ );
+
+#endif
+
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ return AdapterObject;
+
+ return (PADAPTER_OBJECT) NULL;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND_
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ ULONG Limit;
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ if (AdapterObject->Dma32BitAddresses) {
+ Hint = EISA_MIN_ADR / PAGE_SIZE;
+ Limit = EISA_MAX_ADR / PAGE_SIZE;
+ } else {
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Limit = ISA_MAX_ADR / PAGE_SIZE - Wcb->NumberOfMapRegisters;
+ }
+#else // _DMA_EXPAND_
+// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+ Hint = (0x100000 / PAGE_SIZE); // M0024
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ Hint
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+// M0018 +++
+#if defined(_DMA_EXPAND_)
+ //
+ // Make sure this map register is valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber >= Limit ) {
+
+ //
+ // Make it look like there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ Wcb->NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = -1;
+ }
+#endif // _DMA_EXPAND_
+// M0018 ---
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize the DMA interrupt dispatcher for I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpDmaChannelInterrupt,
+ HalpDmaChannel,
+ (PVOID) NULL,
+ (PKSPIN_LOCK) NULL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ DMA_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpDmaChannelInterrupt );
+
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ PCR->InterruptRoutine[DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpDmaDispatch;
+
+/* start M0001 */
+#if defined(_R94A_)
+
+/* M0010 +++ */
+
+ //
+ // Enable DmaChannel Interrupt
+ //
+{
+ ULONG Dword,Channel;
+
+ Dword = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long);
+
+ Dword |= 1; // S0011
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long, Dword); // S011
+
+#if 0 // S0017
+ //
+ // Enable Interrupt when done every channel
+ //
+
+ for (Channel = 0; Channel < 4; Channel++) {
+ Dword = READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Mode);
+ Dword |= 0x20;
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Mode, Dword);
+ }
+#endif // 0 // S0017
+}
+
+
+/* M0010 --- */
+
+ //
+ // Initialize Typhoon error interrupts.
+ //
+
+ HalpCreateTyphoonErrorStructures();
+
+#endif // _R94A_
+/* end M0001 */
+
+ return TRUE;
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+ KIRQL OldIrql; // kuriyama
+
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+ ULONG bufferAddress;
+ ULONG bufferLogical;
+#endif // _BBM_DMA_
+/* end M0004 */
+
+#if 0 //M0008
+/* M0005 +++ */
+#if defined(_BETA_LIMIT_)
+{
+ ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, logicalAddress;
+ KIRQL OldIrql;
+
+ if (!WriteToDevice) {
+ logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ Ltag = READ_REGISTER_ULONG(LtagReg);
+ if (Ptag & 0x1) {
+ if (Ltag & 0x1) {
+ if ((logicalAddress & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (logicalAddress + *Length))) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+ }
+ }
+ KeLowerIrql(OldIrql);
+ }
+}
+#endif // _BETA_LIMIT_
+/* M0005 --- */
+#endif // 0 // M0008
+
+#if defined(_BBM_DMA_)
+{
+ ULONG PtagReg, Ptag, DummyRead;
+ // D001
+ if (*Length > (PAGE_SIZE * DMA_TRANSLATION_LIMIT / 8 / 8 )) { // kuriyama
+ DbgPrint("IoMapTransfer: *Length > %d pages\n", (DMA_TRANSLATION_LIMIT / 8 / 8));
+ }
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ if (Ptag & 0x1) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+}
+#endif // _BBM_DMA_
+#if 0 // kuriyama // D001 Delete checking ByteMask
+// temp kuriyama start
+ for (i=0; i < 8; i++) {
+ if (READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[i])){
+ DbgPrint("IoMapTransfer : LowByteMask[%d] is 0x%x\n",i,(ULONG)READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[i]));
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ if (READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[i])){
+ DbgPrint("IoMapTransfer : HighByteMask[%d] is 0x%x\n",i,(ULONG)READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[i]));
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ }
+// temp kuriyaam end
+#endif // if 0 // kuriyama
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+ if (!WriteToDevice) {
+// HalSweepDcache();
+// HalSweepIcache();
+ HalDump("IoMapTransfer: AdapterObject = %x\n",(ULONG)AdapterObject);
+ for (i = 0; i < NumberOfPages; i++) {
+ bufferLogical = (((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT) + (i << PAGE_SHIFT);
+ HalDump("IoMapTransfer: bufferLogical = %x\n",bufferLogical);
+ bufferAddress = CopyBufferPhysicalBase + bufferLogical;
+ HalDump("IoMapTransfer: bufferAddress = %x\n",bufferAddress);
+ (DmaMapRegister++)->PageFrame = bufferAddress;
+ }
+ } else {
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+ }
+#else // _BBM_DMA_
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+#endif // _BBM_DMA_
+/* end M0004 */
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+ if (!WriteToDevice) {
+ Offset = 0;
+ ;
+ }
+#endif // _BBM_DMA_
+/* end M0004 */
+
+ //
+ // Set the offset to point to the map register plus the offset.
+ //
+
+ Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+/* start M0004 */
+ if (!WriteToDevice) {
+ HalDump("IoMapTransfer: Offset %x\n",Offset); /* M0004 */
+ HalDump("IoMapTransfer: Length %x\n",*Length); /* M0004 */
+ HalDump("IoMapTransfer: CurrentVa %x\n",CurrentVa); /* M0004 */
+ }
+/* end M0004 */
+
+ //
+ // Invalidate the translation entry.
+ //
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long, 1);
+
+#if defined(_BBM_DMA_)
+ KeLowerIrql(OldIrql); // kuriyama
+#endif //_BBM_DMA_
+ if ( AdapterObject == NULL) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+
+ if (AdapterObject->PagePort == NULL) {
+
+// M0013 +++
+#if defined(_R94A_)
+ //
+ // if Master Device, nothing set to DMAC.
+ //
+
+ if ( AdapterObject->AdapterBaseVa == &(DMA_CONTROL)->Channel[7]) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+#endif // _R94A_
+// M0013 ---
+ //
+ // Set the local DMA Registers.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Address.Long, Offset);
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long, *Length);
+
+ i = 0;
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 1;
+ ((PDMA_CHANNEL_ENABLE) &i)->TransferDirection =
+ WriteToDevice ? DMA_WRITE_OP : DMA_READ_OP;
+ WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, i);
+
+
+ } else {
+
+ //
+ // Start the EISA DMA controller.
+ //
+
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+
+ ULONG i;
+ UCHAR DataByte;
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+//
+// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice
+//
+
+#if 0
+ PCCHAR bufferAddress;
+#endif
+
+ PCCHAR mapAddress;
+ ULONG logicalAddress;
+ ULONG Offset;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+
+ if (!WriteToDevice) {
+
+ HalDump("IoFlushAdapterBuffers: AdapterObject = %x\n",(ULONG)AdapterObject);
+
+#if 0
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+ HalDump("IoFlushAdapterBuffers: bufferAddress = %x\n",bufferAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",Length);
+#endif
+
+ logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+ HalDump("IoFlushAdapterBuffers: logicalAddress = %x\n",logicalAddress);
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+ HalDump("IoFlushAdapterBuffers: Offset = %x\n",Offset);
+
+ mapAddress = (PCCHAR)(CopyBufferVirtualAddress + logicalAddress);
+
+ HalDump("IoFlushAdapterBuffers: mapAddress = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: CurrentVa = %x\n",CurrentVa);
+
+// DbgBreakPoint();
+// RtlMoveMemory(CurrentVa, mapAddress, Length);
+// DbgBreakPoint();
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ HalDump("IoFlushAdapterBuffers: NumberOfPages = %x\n",NumberOfPages);
+
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ HalDump("IoFlushAdapterBuffers: PageFrameNumber = %x\n",PageFrameNumber);
+
+ if (NumberOfPages == 1) {
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",Length);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE )+ Offset),
+ (PVOID)mapAddress, Length
+ );
+
+ } else if ( NumberOfPages == 2) {
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE - Offset);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ) + Offset),
+ (PVOID)mapAddress, (ULONG)(PAGE_SIZE - Offset)
+ );
+
+#if 0
+ HalDump("IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE)
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + PAGE_SIZE + Offset);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n" , BYTE_OFFSET(Length + Offset - 1) + 1);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ ((PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE )),
+// (PVOID)(mapAddress + PAGE_SIZE + Offset),
+ (PVOID)(mapAddress + PAGE_SIZE - Offset), // H001
+ (ULONG)(BYTE_OFFSET(Length + Offset - 1) + 1)
+ );
+
+ } else {
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE - Offset);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ) + Offset),
+ (PVOID)mapAddress,
+ (ULONG)(PAGE_SIZE - Offset)
+ );
+
+ for (i = 1; i < (NumberOfPages - 1); i++) {
+#if 0
+ HalDump("IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE)
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + (i * PAGE_SIZE) +Offset);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE),
+// (PVOID)((mapAddress + (i * PAGE_SIZE)) + Offset),
+ (PVOID)(mapAddress + (i * PAGE_SIZE) - Offset), // H001
+ PAGE_SIZE
+ );
+
+ }
+
+#if 0
+ HalDump(
+ "IoFlushAdapterBuffers: USERBUFFER = %x\n",
+ (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset
+ );
+ HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + (i * PAGE_SIZE) + Offset);
+ HalDump("IoFlushAdapterBuffers: Length = %x\n",BYTE_OFFSET(Length + Offset - 1) + 1);
+#endif
+
+// HalSweepIcache();
+// HalSweepDcache();
+
+ RtlMoveMemory(
+ (PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ),
+// (PVOID)(mapAddress + (i * PAGE_SIZE) + Offset),
+ (PVOID)(mapAddress + (NumberOfPages - 1) * PAGE_SIZE - Offset), // H001
+ (ULONG)(BYTE_OFFSET(Length + Offset - 1) + 1)
+ );
+
+ }
+ }
+#endif // _BBM_DMA_
+/* end M0004 */
+/* M0006 +++ */
+#if defined(_BETA_LIMIT_)
+#if 0 // M0008
+{
+ ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, logicalAddress;
+ KIRQL OldIrql;
+
+ if (!WriteToDevice) { // M0005
+ logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+ // D001
+// DbgPrint("DmaFlush start\n");
+ KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama
+ for (i = 0; i < 8; i++ ) {
+ PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i];
+ LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i];
+ Ptag = READ_REGISTER_ULONG(PtagReg);
+ Ltag = READ_REGISTER_ULONG(LtagReg);
+ if (Ptag & 0x1) {
+ if (Ltag & 0x1) {
+ if ((logicalAddress & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (logicalAddress + Length))) {
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0)));
+ if (HalDebug)
+ DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n",
+ PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead);
+ }
+ }
+ }
+ }
+ KeLowerIrql(OldIrql);
+// DbgPrint("DmaFlush end\n");
+ } // M0005
+
+}
+#endif // 0 //M0008
+/* M0005,M0014 +++ */
+{
+ ULONG Offset, NumberOfPages;
+ PULONG PageFrameNumber;
+ KIRQL OldIrql;
+
+ if (Length != 0) { //S0015
+ if (!WriteToDevice) {
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql); // kuriyama
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ if (NumberOfPages == 1) {
+ HalViewMemory((PVOID)((KSEG1_BASE |(((ULONG) *PageFrameNumber++
+ << PAGE_SHIFT) + Offset))),
+ Length);
+ } else {
+ HalViewMemory( (PVOID)((KSEG1_BASE |(((ULONG) *PageFrameNumber++
+ << PAGE_SHIFT) + Offset))),
+ (PAGE_SIZE - Offset));
+ for (i = 1; i < NumberOfPages -1; i++) {
+ HalViewMemory( (PVOID)((KSEG1_BASE |((ULONG) *PageFrameNumber++
+ << PAGE_SHIFT))), PAGE_SIZE);
+ }
+ HalViewMemory( (PVOID)((KSEG1_BASE
+ |((ULONG) *PageFrameNumber++ << PAGE_SHIFT))),
+ BYTE_OFFSET(Offset + Length -1) +1);
+ }
+ KeLowerIrql(OldIrql);
+ }
+ }
+}
+
+/* M0005,M0014 --- */
+
+#endif // _BETA_LIMIT_
+/* M0006 --- */
+
+ if (AdapterObject == NULL) {
+
+ //
+ // This is a master adadapter so there is nothing to do.
+ //
+
+ return(TRUE);
+ }
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else {
+
+// M0013 +++
+#if defined(_R94A_)
+ //
+ // if Master Device, nothing set to DMAC.
+ //
+
+ if ( AdapterObject->AdapterBaseVa == &(DMA_CONTROL)->Channel[7]) {
+ return(TRUE);
+ }
+#endif // _R94A_
+// M0013 ---
+ //
+ // Clear on board DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ i = READ_REGISTER_USHORT(
+ &((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable
+ );
+ }
+
+ return(TRUE);
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+#if 0 // CHG0001
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+/* start M0001 */
+#if 0
+#if defined(_R94A_)
+
+ case PCIConfiguration:
+ DataLength = HalpReadPCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+#endif // _R94A_
+#endif // 0
+/* end M0001 */
+
+ }
+
+ return(DataLength);
+
+}
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+/* start M0001 */
+#if 0
+#if defined(_R94A_)
+
+ switch (BusDataType) {
+
+ case PCIConfiguration:
+ DataLength = HalpWritePCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+#endif // _R94A_
+#endif // 0
+/* end M0001 */
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory ((PVOID)Buffer, (PVOID)((PUCHAR)SlotInformation + Offset), (ULONG)DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+#endif
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ } else {
+
+ //
+ // Disable the DMA
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long
+ );
+
+ saveEnable = i;
+
+ ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ i
+ );
+
+ //
+ // Read the transfer count.
+ //
+
+ count = 0xfffff & READ_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long); // beta typhoon errata// M0009
+
+ //
+ // Reset the Enable register.
+ //
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long,
+ saveEnable
+ );
+
+ }
+
+ return(count);
+}
+
+
+BOOLEAN
+HalpDmaChannel(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a DMA channel interrupt occurs.
+ These should never occur. Bugcheck is called if an error does occur.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+
+ ULONG DataWord;
+ ULONG Channel;
+ DMA_CHANNEL_ENABLE ChannelWord;
+ ULONG ErrorFlag = 0; /* M0003 */
+
+#if defined(_JAZZ_)
+
+ //
+ // Read the DMA channel interrupt source register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long);
+
+ for (Channel = 0; Channel < 8; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << Channel))) {
+ continue;
+ }
+
+ DmaChannelMsg[18] = (CHAR) Channel + '0';
+
+ HalDisplayString(DmaChannelMsg);
+
+ *((PULONG) &ChannelWord) =
+ READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long);
+
+ if (ChannelWord.TerminalCount) {
+ HalDisplayString("Terminal count was reached.\n");
+ }
+
+ if (ChannelWord.MemoryError) {
+ HalDisplayString("A memory error was detected.\n");
+ }
+
+ if (ChannelWord.TranslationError) {
+ HalDisplayString("A translation error occured.\n");
+ }
+
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+#endif
+
+/* start M0001 */
+#if defined(_R94A_)
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // S0023
+
+ //
+ // Read the DMA channel interrupt source register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->ChannelInterruptAcknowledge.Long);
+
+ for (Channel = 0; Channel < 4; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << Channel))) {
+ continue;
+ }
+
+ DmaChannelMsg[18] = (CHAR) Channel + '0';
+
+
+ *((PULONG) &ChannelWord) =
+ READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long);
+
+/* start M0002 */
+ if (ChannelWord.TerminalCount) {
+ if ((0xfffff & READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].ByteCount.Long)) != 0) { // beta typhoon errta // M0009
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("Terminal count was reached."); // S0011
+ ErrorFlag++;
+ }
+ }
+
+ if (ChannelWord.MemoryError) {
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("A memory error was detected."); // S0011
+ ErrorFlag++;
+ }
+
+ if (ChannelWord.ParityError) {
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("A Parity error occured."); // S0011
+ ErrorFlag++;
+ }
+
+ if (ChannelWord.MasterAbort) {
+ HalDisplayString(DmaChannelMsg);
+ HalDisplayString("A PCIBus Master Abort error occured."); // S0011
+ ErrorFlag++;
+ }
+
+ // Clear Dma Channel Interrupt
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long, 0x00000100); // M0009
+/* end M0002 */
+ }
+
+ if (ErrorFlag != 0) {
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+#endif // _R94A_
+/* end M0001 */
+
+ return(TRUE);
+}
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ HalpMapRegisterPhysicalBase = PhysicalAddress;
+
+#if defined(_BBM_DMA_)
+/* start kuriyama TLB fill 0xff */ // D001
+ RtlFillMemory( (HalpMapRegisterPhysicalBase | KSEG1_BASE), 0x2000, 0xff);
+/* end kuriyama TLB fill 0xff */
+#endif // _BBM_DMA_
+
+/* start M0004 */
+#if defined(_BBM_DMA_)
+ HalpAllocateCopyBuffer(LoaderBlock);
+#endif // _BBM_DMA_
+/* end M0004 */
+}
+
+/* start M0001 */
+#if defined(_R94A_)
+BOOLEAN
+HalpCreateTyphoonErrorStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Typhoon Error
+ interrupt dispatcher. It also connects an interrupt handler to the
+ Typhoon Error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ //
+ // Initialize the Typhoon Error interrupt dispatcher for I/O interrupts.
+ //
+
+ KeInitializeInterrupt( &HalpTyphoonErrorInterrupt,
+ HalpTyphoonError,
+ (PVOID) NULL,
+ (PKSPIN_LOCK) NULL,
+ TYPHOON_ERROR_INTERRUPT_VECTOR,
+ DEVICE_LEVEL,
+ DEVICE_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ return KeConnectInterrupt( &HalpTyphoonErrorInterrupt );
+
+}
+#endif // _R94A_
+/* end M0001 */
+
+/* start M0001 */
+#if defined(_R94A_)
+BOOLEAN
+HalpTyphoonError(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a Typhoon Error interrupt occurs.
+ This error is cretical. Bugcheck is called if an error does occur.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+ Note. This function never return. This function call always KeBugCheck().
+
+--*/
+{
+
+ ULONG DataWord;
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // S0023
+
+ //
+ // Read the Typhoon Error Status register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->TyphoonErrorStatus);
+
+ HalDisplayString("\nHAL: Internal master error occurred.\n"); // S0022
+
+ if ( DataWord & 2) {
+
+ HalDisplayString("ethernet bus master error\n");
+
+ }
+
+ if ( DataWord & 4) {
+
+ HalDisplayString("SCSI port 1 bus master error\n");
+
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+
+ return(TRUE);
+}
+#endif // _R94A_
+/* end M0001 */
+
+#if defined(_BBM_DMA_)
+VOID
+HalpAllocateCopyBuffer(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for copybuffer directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = 0x400000;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ CopyBufferPhysicalBase = PhysicalAddress;
+ HalDump("Common Buffer Physical = %x\n",CopyBufferPhysicalBase);
+ CopyBufferVirtualAddress = PhysicalAddress | KSEG1_BASE;
+ HalDump("Common Buffer Virtual = %x\n",CopyBufferVirtualAddress);
+}
+#endif // _BBM_DMA_
+/* end M0004 */
diff --git a/private/ntos/nthals/halr96b/mips/jxmapio.c b/private/ntos/nthals/halr96b/mips/jxmapio.c
new file mode 100644
index 000000000..879f96410
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxmapio.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmapio.c"
diff --git a/private/ntos/nthals/halr96b/mips/jxmaptb.c b/private/ntos/nthals/halr96b/mips/jxmaptb.c
new file mode 100644
index 000000000..9262bc775
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxmaptb.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxmaptb.c"
diff --git a/private/ntos/nthals/halr96b/mips/jxport.c b/private/ntos/nthals/halr96b/mips/jxport.c
new file mode 100644
index 000000000..26e310528
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxport.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\jxport.c"
diff --git a/private/ntos/nthals/halr96b/mips/jxreturn.c b/private/ntos/nthals/halr96b/mips/jxreturn.c
new file mode 100644
index 000000000..d77d5642b
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxreturn.c
@@ -0,0 +1,258 @@
+// #pragma comment(exestr, "@(#) jxreturn.c 1.1 95/09/28 15:40:17 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ H000 Tue Apr 25 16:02:05 1995 kbnes!kisimoto
+ -add Powerdown if argument value indicates
+ HalPowerDownRoutine
+ S001 kuriyama@oa2.kb.nec.co.jp Sun May 21 18:32:55 JST 1995
+ -compile error clear
+ S002 kuriyama@oa2.kb.nec.co.jp Sun May 21 20:19:48 JST 1995
+ - powoff bug? fixed
+ H003 Sat Aug 12 19:33:45 1995 kbnes!kisimoto
+ - Removed _J94C_ definitions.
+ _J94C_ definition indicates that the status of the
+ dump switch can acknowledge from Self-test register.
+
+ M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:28:35 JST 1995
+ - add for x86bios emurator support
+--*/
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO Pte[2];
+ ULONG Index; // A001
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE;
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; //S004
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+
+#if defined (_MRCPOWER_)
+
+ //
+ // S004
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ Eax = 0x12; // AH = 0 AL = 0x12
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // H000,S001
+ // Powerdown the machine
+ //
+
+ //
+ // Map the MRC
+ //
+
+ Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT;
+
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map MRC using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // Send Powerdown Command to the MRC.
+ //
+
+
+ for (;;) { // S002
+ WRITE_REGISTER_UCHAR(
+ &MRC_CONTROL->SoftwarePowerOff,
+ 0x1
+ );
+ }
+
+ for (;;) {
+ }
+#endif //_MRCPOWER_
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ //
+ // S004
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ Eax = 0x12; // AH = 0 AL = 0x12
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Map the keyboard controller
+ //
+
+ Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map keyboard controller using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreData(0);
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
+
diff --git a/private/ntos/nthals/halr96b/mips/jxsysint.c b/private/ntos/nthals/halr96b/mips/jxsysint.c
new file mode 100644
index 000000000..ebe54f024
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxsysint.c
@@ -0,0 +1,355 @@
+// #pragma comment(exestr, "@(#) jxsysint.c 1.1 95/09/28 15:40:45 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - HalDisableSystemInterrupt()
+ change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL.
+ add the PCI interrupt vector.
+ Interrupt Enable register is zero origin on beta-version of
+ STORM chipset.
+ if ASIC3 register is zero, then chipset is beta-version.
+ - HalEnableSystemInterrupt()
+ change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL.
+ add the PCI interrupt vector.
+ Interrupt Enable register is zero origin on beta-version of
+ STORM chipset.
+ if ASIC3 register is zero, then chipset is beta-version.
+ - HalGetInterruptVector()
+ add PCIBus interface.
+ change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL.
+ If InterfaceType is Internal and ASIC3 register is zero,
+ then return the vector which was plus the offset of DEVICE_VECTORS.
+ H001 Mon Oct 17 14:21:21 JST 1994 kbnes!kishimoto
+ - Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ - XXX_EISA_PCI_XXX rename to XXX_EISA_XXX
+ - MAXIMUM_PCI_SLOT rename to R94A_PCI_SLOT
+ - HalGetInterruptVector()
+ returns PCI-vector plus offset PCI_VECTORS.
+ - modify original compile error
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:46:35 JST 1994
+ - reslve compile error
+ H002 Mon Oct 31 17:45:56 1994 kbnes!kishimoto
+ - HalGetInterruptVector()
+ Internal SCSI interrupt vector set to 5 (for BBM only)
+ M003 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 17:06:37 JST 1995
+ - add _IPI_LIMIT_ support
+ S004 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 11:10:52 JST 1995
+ - compile error clear
+ H005 Fri Aug 11 16:53:13 1995 kbnes!kishimoto
+ - delete M003, and HalGetInterruptVector(move to bushnd.c)
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));
+
+#if defined(_R94A_)
+
+ if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){
+
+ //
+ // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
+ // Enable register is zero origin.
+ //
+ // N.B. This obstruction is limiteded to beta-version of STORM chipset.
+ //
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill,
+ HalpBuiltinInterruptEnable);
+ } else {
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+ }
+
+#else
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+
+#endif
+
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+#if defined(_R94A_)
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector <= PCI_VECTORS + R94A_PCI_SLOT &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisablePCIInterrupt(Vector);
+ }
+
+#endif
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // enable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
+
+#if defined(_R94A_)
+
+ if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){
+
+ //
+ // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
+ // Enable register is zero origin.
+ //
+ // N.B. This obstruction is limiteded to beta-version of STORM chipset.
+ //
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill,
+ HalpBuiltinInterruptEnable);
+
+ } else {
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+
+ }
+#else
+
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ HalpBuiltinInterruptEnable);
+
+#endif
+
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+#if defined(_R94A_)
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector <= PCI_VECTORS + R94A_PCI_SLOT &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnablePCIInterrupt(Vector);
+ }
+
+#endif
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(_DUO_) // S004
+
+// M003 +++
+#if defined(_IPI_LIMIT_)
+ ULONG OldIpiReq;
+ KIRQL OldIrql;
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+ KeRaiseIrql(HIGH_LEVEL,&OldIrql);
+
+ KiAcquireSpinLock(&HalpIpiRequestLock);
+
+ OldIpiReq = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long);
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long,
+ OldIpiReq | Mask);
+
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long);
+
+ KiReleaseSpinLock(&HalpIpiRequestLock);
+
+ KeLowerIrql(OldIrql);
+
+
+#else // _IPI_LIMIT_
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long,
+ Mask);
+
+#endif //_IPI_LIMIT_
+// M003 ---
+
+#endif
+
+ return;
+}
diff --git a/private/ntos/nthals/halr96b/mips/jxtime.c b/private/ntos/nthals/halr96b/mips/jxtime.c
new file mode 100644
index 000000000..5d9c29705
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxtime.c
@@ -0,0 +1,377 @@
+// #pragma comment(exestr, "@(#) jxtime.c 1.1 95/09/28 15:41:57 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ M0001 1994.9.9 kbnes!A.Kuriyama
+
+ Modify for R94A
+
+ HalpReadClockRegister() - R94A use RTC Index register except EISA NmiEnable
+ register.
+ HalpWriteClockRegister() - R94A use RTC Index register except EISA NmiEnable
+ register.
+
+ M0002 1994.10.8 kbnes!kuriyama(A)
+
+ HalpReadClockRegister()
+ -add specify Read Data register
+ HalpWritelockRegister()
+ -add specify Write Data register
+
+ M0003 1994.10.14 kbnes!kuriyama(A)
+
+ define error clear
+
+ M0004 1994.12.19 kbnes!kuriyama(A)
+
+ define miss fix
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+/* start M0001 */
+#if defined(_R94A_) /* M0003 */
+ // Insert the realtime clock register number, and write the value back
+ // to RTC Index register. This selects the realtime clock register
+ // that is read.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_REGISTERS) HalpRealTimeClockBase)->Index,
+ Register);
+
+
+#else // _R94A_
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ Register |= 0x80;
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Read the realtime clock register value.
+ //
+
+/* start M0002 */
+#if defined(_R94A_) // M0004
+
+ return READ_REGISTER_UCHAR( &((PRTC_REGISTERS) HalpRealTimeClockBase)->Data);
+
+
+#else // _R94A_
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+
+#endif // _R94A_
+/* end M0002 */
+
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+/* start M0001 */
+#if defined(_R94A_)
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to RTC Index register. This selects the realtime clock
+ // register that is written.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_REGISTERS) HalpRealTimeClockBase)->Index,
+ Register);
+
+#else // _R94A_
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ Register |= 0x80;
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+#endif // _R94A_
+/* end M0001 */
+
+ //
+ // Write the realtime clock register value.
+ //
+
+/* start M0002 */
+#if defined(_R94A_) // M0004
+
+ WRITE_REGISTER_UCHAR( &((PRTC_REGISTERS) HalpRealTimeClockBase)->Data, Value);
+
+#else // _R94A_
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+
+#endif // _R94A_
+/* end M0002 */
+
+ return;
+}
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr96b/mips/jxusage.c b/private/ntos/nthals/halr96b/mips/jxusage.c
new file mode 100644
index 000000000..12a54de49
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/jxusage.c
@@ -0,0 +1,510 @@
+// #pragma comment(exestr, "@(#) jxusage.c 1.1 95/09/28 15:42:20 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:26:38 JST 1994
+ - Change PRIMARY_VECTOR_BASE to DEVICE_VECTOTRS
+ CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:53:42 JST 1994
+ - delete HalpEnableInterruptHandler, HalpRegisterVector
+ - change IDT vector LOOP, R94A report up to DEVICE_VECTORS
+ - change MAXIMUM_IDTVECTOR to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:53:32 JST 1994
+ - resolve compile error
+ CMP002 ataka@oa2.kb.nec.co.jp Tue Oct 18 22:33:14 JST 1994
+ - add following
+ // HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ // HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ // HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+#if !defined(_R94A_) // CMP001
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif // _R94A
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+#if !defined (_R94A_) // CHG001
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+#endif // _R94A_
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+#if defined(_R94A_)
+// HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+// HalpRegisterAddressUsage (&HalpEisaIoSpace);
+// HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+#endif // _R94A_
+
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+#if defined(_R94A_) // CHG001
+ for(i=0; i < DEVICE_VECTORS; i++) { // ADD001
+ HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+#else
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+#endif
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_VECTOR) { // CHG001
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halr96b/mips/mipsdat.c b/private/ntos/nthals/halr96b/mips/mipsdat.c
new file mode 100644
index 000000000..bfe2b9273
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/mipsdat.c
@@ -0,0 +1,145 @@
+// #pragma comment(exestr, "@(#) mipsdat.c 1.1 95/09/28 15:42:43 nec")
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*++
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:53:16 JST 1994
+ - add HalpMapRegisterMemorySpace
+ BUG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:49:18 JST 1994
+ - change HalpMapRegisterMemorySpace Size
+ CNG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:58:30 JST 1994
+ - change HalpIDTUsage size to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:34:47 JST 1994
+ - resolve compile error
+ A002 ataka@oa2.kb.nec.co.jp 1995/6/17
+ - merge 1050
+
+--*/
+
+
+
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC
+ EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC
+
+ EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe
+
+ EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B)
+ EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A
+
+ EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable
+ EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI
+ EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted
+
+ EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers
+
+ EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+#define R94A_MAPREGISTER_BASE 100 // CMP001
+
+// BUG001
+ADDRESS_USAGE HalpMapRegisterMemorySpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ R94A_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001
+ 0, 0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+// CNG001
+#if defined(MIPS)
+IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[]
+#else // CMP001
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif
+
diff --git a/private/ntos/nthals/halr96b/mips/mode542x.h b/private/ntos/nthals/halr96b/mips/mode542x.h
new file mode 100644
index 000000000..3550a0714
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/mode542x.h
@@ -0,0 +1,1302 @@
+// #pragma comment(exestr, "@(#) mode542x.h 1.1 95/09/28 15:43:49 nec")
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Mode542x.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-542x driver.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// The next set of tables are for the CL542x
+// Note: all resolutions supported
+//
+
+//
+// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode
+
+ EOD
+};
+
+//
+// 800x600 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_800x600[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode
+
+ EOD
+};
+
+//
+// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_1024x768[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ EOD
+};
+
+//-----------------------------
+// standard VGA text modes here
+// 80x25 at 640x350
+//
+//-----------------------------
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (720x400 pixel resolution; 9x16 character cell.)
+//
+
+USHORT CL542x_80x25Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (640x350 pixel resolution; 8x14 character cell.)
+//
+
+USHORT CL542x_80x25_14_Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x.
+//
+
+USHORT CL542x_1280x1024[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_64k[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 4,
+ 0x0506, // Some BIOS's set Chain Odd maps bit
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#ifdef _X86_
+
+//
+// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x.
+//
+
+USHORT CL542x_800x600_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#else
+
+//
+// NOTE(DBCS) : Update 94/09/12 - NEC Corporation
+//
+// - Add mode set command string for NEC MIPS machine.
+//
+// - 640x480 256 color 72Hz
+// - 800x600 256 color 56 / 60Hz
+// - 1024x768 256 color 70 / 45Hz
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+//
+// For MIPS NEC machine only
+//
+
+//
+// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xE3,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F,
+ 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x420E,
+ 0x2B1B,0x2F1C,0x301D,0x1F1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h)
+//
+// - Set Mode Type is VESA compatible. (Old Miss match)
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99,
+ 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+
+// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match
+// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode.
+// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B,
+// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+// 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_56[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12,
+ 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x510E,
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B,
+ 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B,0x5B0C,0x450D,0x650E,
+
+#else
+
+ 0x4A0B,0x5B0C,0x450D,0x640E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x760E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x341E,
+
+#else
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x3B0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x1A1E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_70[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x6E0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x2A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for
+// CL 542x. (Interlaced)
+//
+
+USHORT CL542x_1024x768_256_87[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x550E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x361E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99,
+ 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83,
+ 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x84,
+ 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+#endif
diff --git a/private/ntos/nthals/halr96b/mips/modeset.h b/private/ntos/nthals/halr96b/mips/modeset.h
new file mode 100644
index 000000000..63122b13b
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/modeset.h
@@ -0,0 +1,85 @@
+// #pragma comment(exestr, "@(#) modeset.h 1.1 95/09/28 15:45:03 nec")
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Modeset.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-6410 and CL-6420 driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Mode structure.
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ *
+ */
+
+#include "cmdcnst.h"
+
+//---------------------------------------------------------------------------
+//
+// The actual register values for the supported modes are in chipset-specific
+// include files:
+//
+// mode64xx.h has values for CL6410 and CL6420
+// mode542x.h has values for CL5422, CL5424, and CL5426
+//
+
+
+USHORT HalpCirrus_MODESET_1K_WIDE[] = {
+ OW, // stretch scans to 1k
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x8013,
+
+ EOD
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr96b/mips/pcibrd.c b/private/ntos/nthals/halr96b/mips/pcibrd.c
new file mode 100644
index 000000000..2124dda34
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/pcibrd.c
@@ -0,0 +1,1020 @@
+// #pragma comment(exestr, "@(#) pcibrd.c 1.1 95/09/28 15:45:30 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+// #define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halr96b/mips/pcibus.c b/private/ntos/nthals/halr96b/mips/pcibus.c
new file mode 100644
index 000000000..a77edf46e
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/pcibus.c
@@ -0,0 +1,3585 @@
+// #pragma comment(exestr, "@(#) pcibus.c 1.1 95/09/28 15:45:56 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Jun 30 02:54:08 1995 kbnes!kisimoto
+ - Merge build 1057 ixpcibus.c
+ H002 Tue Jul 4 20:43:12 1995 kbnes!kisimoto
+ - disable preferred setting for back-to-back
+ support. If enable, IoAssign... allocates
+ current enabled address space.
+ H003 Wed Jul 5 14:27:46 1995 kbnes!kisimoto
+ - initialize with FALSE
+ H004 Tue Sep 5 20:06:16 1995 kbnes!kisimoto
+ - PCI Fast Back-to-back transfer support
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#if defined(_R94A_) // H001
+#include "r94adef.h"
+#include "string.h"
+#endif // _R94A_
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+#if 0
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+#endif
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+// KSPIN_LOCK HalpPCIConfigLock; // H001
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+BOOLEAN HalpDoingCrashDump = FALSE; // H003
+ULONG HalpFoundUncapablePCIDevice = 0; // H004
+ULONG HalpPCINumberOfMappedGA = 0;
+ULONG HalpPCIBackToBackReg0Start = 0;
+ULONG HalpPCIBackToBackReg1Start = 0;
+ULONG HalpPCIBackToBackReg0Open = 1;
+ULONG HalpPCIBackToBackReg1Open = 1;
+ULONG HalpNumberOfPCIGA = 0;
+ULONG HalpPCIMemoryLimit = 0xffffffff;
+
+#define INIT_VALUE_OF_BACK_TO_BACK_ADDR 0x00000000
+#define INIT_VALUE_OF_BACK_TO_BACK_MASK 0xffffffff
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if defined(_R94A_) // H001
+ULONG
+HalpGetPCIInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+ULONG
+HalpGetNumberOfPCIGA(
+ IN ULONG NumberBuses
+ );
+VOID
+HalpSetBackToBackSpace(
+ IN PPCI_COMMON_CONFIG PciConfigRequired,
+ IN PPCI_COMMON_CONFIG PciConfigMapped,
+ IN PBUS_HANDLER BusHandler
+ );
+VOID
+HalpSetBackToBackRegister(
+ IN ULONG BaseAddress,
+ IN ULONG Length,
+ IN ULONG Register
+ );
+#endif // _R94A_
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+ULONG R94aDoTestPci = 0;
+ULONG R94aDoTestPciNec = 0;
+ULONG R94aDoOtherTest = 0;
+VOID
+HalpTestPciNec (
+ ULONG
+ );
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+ );
+VOID
+HalpOtherTestNec (
+ ULONG
+ );
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ PCI_REGISTRY_INFO tPCIRegInfo; // H001
+
+#if 0 // H001
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+// KeInitializeSpinLock (&HalpPCIConfigLock); // H001
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+#endif // 0
+
+#if defined(_R94A_) // H001
+
+ PCIRegInfo = &tPCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism=0x1; // HURRICANE PCI Config Type
+
+#if DBG
+ DbgPrint("PCI System Get Data:\n");
+ DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision );
+ DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision );
+ DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses );
+ DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism );
+#endif // DBG
+
+#endif // _R94A_
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+#if 0 // H001
+ do {
+#endif
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+#if 0 // H001
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+#endif
+
+ //
+ // H005
+ // Compute the number of PCI-GA device and
+ // initialize Fast Back-to-back register.
+ //
+
+ HalpNumberOfPCIGA = HalpGetNumberOfPCIGA(PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#if defined(_R94A_)
+ DbgPrint("HalpInitializePciBus: Call HalpTestPci(%x)\n",R94aDoTestPci);
+ HalpTestPci (R94aDoTestPci);
+ DbgPrint("HalpInitializePciBus: Call HalpTestPciNec(%x)\n",R94aDoTestPciNec);
+ HalpTestPciNec (R94aDoTestPciNec);
+ DbgPrint("HalpInitializePciBus: Call HalpOtherTest(%x)\n",R94aDoOtherTest);
+ HalpOtherTestNec (R94aDoOtherTest);
+#endif
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+#if defined(_R94A_)
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIInterruptVector;
+#else
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+#endif
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+#if defined(_R94A_) // H001
+ BusData->Config.Type1.Address = (PULONG)R94A_PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = R94A_PCI_TYPE1_DATA_PORT;
+#else
+ BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+#endif // _R94A_
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+ BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+ BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = 0x10;
+
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if ((j > 0x2 && j < 0xffff) || j > 0xffffff) { // H001
+ // IO port < 64KB | IO port > 16MB
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x3ffffff) { // H001
+ // Mem address < 64MB
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+#if 0
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ BusHandler->BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, PciData->VendorID, PciData->DeviceID,
+ PciData->RevisionID);
+
+
+ if (PciData->u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin);
+ }
+
+ if (PciData->u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine);
+ }
+
+ if (PciData->u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+
+ { ULONG k, j;
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+ DbgPrint("\n");
+ }
+#endif // DBG
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+#if DBG // H001
+ DbgPrint("SetPciData: PciData2->u.type0.InterruptLine:%x\n",PciData2->u.type0.InterruptLine);
+#endif
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ USHORT IdValue; // H001
+ ULONG OrigData; // H001
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ //
+ // resolve PCI master abort during we are looking for PCI device
+ // check to see if spcified slot is valid.
+ //
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+ OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
+ PCIConfigHandler.ConfigRead);
+
+ if (IdValue == 0xffff){
+
+ //
+ // This PCI slot has no card
+ // wait until ReceivedMasterAbort bit is set
+ //
+
+ while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
+ ;
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
+
+ //
+ // Clear memory address error registers.
+ //
+
+ {
+ LARGE_INTEGER registerLarge;
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ }
+
+ //
+ // Restore the PCIInterruptEnable register, and return no data
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+
+ return ;
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+
+#endif // _R94A_
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ USHORT IdValue; // H001
+ ULONG OrigData; // H001
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ //
+ // resolve PCI master abort during we are looking for PCI device
+ // check to see if spcified slot is valid.
+ //
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+ OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
+ PCIConfigHandler.ConfigRead);
+
+ if (IdValue == 0xffff){
+
+ //
+ // This PCI slot has no card
+ // wait until ReceivedMasterAbort bit is set
+ //
+
+ while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
+ ;
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
+
+ //
+ // Clear memory address error registers.
+ //
+
+ {
+ LARGE_INTEGER registerLarge;
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ }
+
+ //
+ // Restore the PCIInterruptEnable register, and return no data
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+
+ return ;
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
+
+#endif // _R94A_
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+#if defined(_R94A_) // H001
+ if (Slot.u.bits.DeviceNumber < 3 ||
+ Slot.u.bits.DeviceNumber > 20) {
+ return FALSE;
+ }
+#else
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+#endif // _R94A_
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.DeviceNumber < 3) { // H001
+#if DBG
+ DbgPrint("HalpPCIConfig: Ignore Slot %x\n",Slot.u.bits.DeviceNumber);
+#endif
+ return;
+ }
+
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (PROFILE_LEVEL, Irql); // H001
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Disable PCI configuration space
+ //
+
+ PciCfg1.u.AsULONG = 0;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
+
+ //
+ // Release spinlock
+ //
+
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql); // H001
+ }
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
+ return sizeof (ULONG);
+}
+
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Initialize Cfg2Addr
+ //
+
+ PciCfg2Addr->u.AsUSHORT = 0;
+ PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
+ PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
+
+ //
+ // Synchronize with type2 config space - type2 config space
+ // remaps 4K of IO space, so we can not allow other I/Os to occur
+ // while using type2 config space.
+ //
+
+ HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ PciCfg2Cse.u.bits.Enable = TRUE;
+ PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
+ PciCfg2Cse.u.bits.Key = 0xff;
+
+ //
+ // Select bus & enable type 2 configuration space
+ //
+
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ //
+ // disable PCI configuration space
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
+
+ //
+ // Restore interrupts, release spinlock
+ //
+
+ HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
+ return sizeof(ULONG);
+}
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_COMMON_CONFIG PciData3; // H005
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+
+#if 0 // H001
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+#endif
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // H004
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory ((PPCI_COMMON_CONFIG)&PciData3, PciData, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+#if 0 // H002
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+#endif
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+#if DBG // H001
+ DbgPrint("HalpAssign: Port %x len %x align %x\n", length, length, m);
+#endif // DBG
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+#if 0 // H002
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+#endif
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+
+#if DBG // H001
+ DbgPrint("HalpAssign: Memory %x len %x align %x\n", length, length, m);
+#endif // DBG
+
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+#if DBG // H001
+ DbgPrint("Call IoAssignResources\n");
+#endif // DBG
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+#if DBG // H001
+ DbgPrint("HalpAssign assigned: Port %x\n", *BaseAddress[j]);
+#endif // DBG
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+#if DBG // H001
+ DbgPrint("HalpAssign assigned: Memory %x\n", *BaseAddress[j]);
+#endif // DBG
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+#if DBG // H001
+ DbgPrint("Set Assigned Resources\n");
+#endif // DBG
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+#if DBG // H001
+ DbgPrint("Read Common header to see write results\n");
+#endif // DBG
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // H004
+ // set memory space as back-to-back available
+ //
+
+ HalpSetBackToBackSpace(&PciData3, PciData2, BusHandler);
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+
+#if defined (_R94A_) // H001
+VOID
+HalpTestPciNec (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag && bus < 1; bus++) { /* R94A_ Support Only 1 */
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) { /* R94A_ Support Only 2 slots(include bridge) */
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, j);
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+ DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, 1);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+ PciData.u.type0.InterruptLine = 5; // For trial
+ DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("We got the bridge\n");
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+ DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+ DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+
+
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+)
+{
+ ULONG i, Lines, pchar;
+
+ DbgPrint("----- I/O Data. (%d)byts.\n", Length);
+
+ for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
+ DbgPrint("%08x: ", Lines * 16);
+ for (i = 0; i < 4; pchar += 4, i++) {
+ if (pchar >= Length)
+ break;
+ DbgPrint("%08x ", *Buffer++);
+ }
+ DbgPrint("\n");
+ }
+}
+
+VOID
+HalpOtherTestNec (
+ IN ULONG doOtherTest
+)
+{
+ if (!doOtherTest)
+ return;
+
+
+ DbgPrint("\n\n===== Additional Testing...\n");
+ {
+ CM_EISA_SLOT_INFORMATION EisaSlotInfo;
+ PCM_EISA_SLOT_INFORMATION EisaBuffer;
+ PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo;
+ ULONG slot, funcs, Length;
+
+ #define MAX_EISA_SLOT 4
+
+ DbgPrint("----- Read Eisa Configration:\n");
+ for (slot = 0; slot < MAX_EISA_SLOT; slot++) {
+ Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo));
+ if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) {
+
+ //
+ // The data is messed up since this should never occur
+ //
+
+ break;
+ }
+ Length = sizeof(CM_EISA_SLOT_INFORMATION) +
+ (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions);
+ EisaBuffer = ExAllocatePool(NonPagedPool, Length);
+ HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length);
+ // Print all Eisa Data
+
+ EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION)
+ ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION));
+
+ DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot);
+ DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n",
+ EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags,
+ EisaBuffer->MajorRevision, EisaBuffer->MinorRevision);
+ DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n",
+ EisaBuffer->Checksum,
+ EisaBuffer->NumberFunctions,
+ EisaBuffer->FunctionInformation,
+ EisaBuffer->CompressedId);
+ for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) {
+ DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n",
+ EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1,
+ EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision,
+ EisaFunctionInfo->MajorRevision);
+
+ // EisaFunctionInfo->Selections[26];
+ // EisaFunctionInfo->FunctionFlags;
+ // EisaFunctionInfo->TypeString[80];
+ // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9];
+ // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7];
+ // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4];
+ // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20];
+ // UCHAR EisaFunctionInfo->InitializationData[60];
+ EisaFunctionInfo++;
+ }
+
+ }
+ }
+ DbgBreakPoint ();
+ {
+ #define MEMORY_SPACE 0
+ #define IO_SPACE 1
+ PHYSICAL_ADDRESS cardAddress;
+ ULONG addressSpace = IO_SPACE;
+ PHYSICAL_ADDRESS PhysAddr;
+
+ PhysAddr.LowPart = 0;
+ PhysAddr.HighPart = 0;
+
+
+
+ DbgPrint("----- Translate Internal Bus Address(I/O): ");
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Internal Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+ }
+ DbgBreakPoint ();
+
+ {
+ KAFFINITY affinity;
+ KIRQL Irql;
+ ULONG Vec;
+
+ DbgPrint("----- GetInterruptVector internal\n");
+ Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Eisa\n");
+ Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Isa\n");
+ Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector PCI\n");
+ Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ }
+ DbgBreakPoint ();
+}
+
+#endif // _R94A_
+#endif // DBG
+
+VOID
+HalpSetBackToBackSpace(
+ IN PPCI_COMMON_CONFIG PciConfigRequired,
+ IN PPCI_COMMON_CONFIG PciConfigMapped,
+ IN PBUS_HANDLER BusHandler
+ )
+/*++
+
+Routine Description:
+
+ This function sets memory space of PCI device to Fast Back-to-back register.
+
+Arguments:
+
+ PciConfigRequired - Supplies the description of the memory space which
+ device required.
+ PciConfigMapped - Supplies the description of the memory space which
+ should be mapped to back-to-back space.
+ BusHandler - Supplies the pointer to Bushandler.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG NoBaseAddress;
+ ULONG BaseAddress, LowerAddress;
+ ULONG CurrentAddress;
+ ULONG FoundMemoryAddress;
+ ULONG i, j, Length;
+
+#if DBG
+ DbgPrint(" check PCI-device!\n");
+ DbgPrint(" - VendorID ................ %04x\n", PciConfigMapped->VendorID);
+ DbgPrint(" - DeviceID ................ %04x\n", PciConfigMapped->DeviceID);
+ DbgPrint(" - back-to-back capable? ... %s\n", (PciConfigMapped->Status & 0x80) ? "o" : "x");
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00 && PciConfigMapped->SubClass == 0x01)){
+ DbgPrint(" - Is this GA device? ...... o\n");
+ } else {
+ DbgPrint(" - Is this GA device? ...... x\n");
+ }
+#endif
+
+ KiAcquireSpinLock(&HalpPCIBackToBackLock);
+
+ //
+ // calulate memory region of this device.
+ //
+
+ switch (PCI_CONFIG_TYPE(PciConfigMapped)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES;
+ break;
+ default:
+ // never come here.
+ // (already except by HalpAssignPCISlotResources)
+ return;
+ }
+
+ Length = 0;
+ BaseAddress = 0xffffffff;
+ LowerAddress = 0xffffffff;
+ FoundMemoryAddress = 0;
+
+ //
+ // get base and limit address
+ //
+
+ for (i = 0; i < NoBaseAddress; i++) {
+ CurrentAddress = PciConfigMapped->u.type0.BaseAddresses[i];
+ if (!(CurrentAddress & PCI_ADDRESS_IO_SPACE)
+ && ((CurrentAddress & PCI_ADDRESS_MEMORY_TYPE_MASK) != 0x2)) {
+
+ //
+ // this is memory space and not need to map below 1M
+ //
+
+ CurrentAddress = CurrentAddress & 0xfffffff0;
+ if (CurrentAddress) {
+ FoundMemoryAddress = 1;
+ if (LowerAddress > CurrentAddress)
+ LowerAddress = CurrentAddress;
+ // scan for first set bit, that's the length & alignment
+ j = 1 << 4;
+ while (!(PciConfigRequired->u.type0.BaseAddresses[i] & j) && j)
+ j <<= 1;
+#if DBG
+ DbgPrint(" - [%d]MemoryAddress ........ 0x%08x\n", i, CurrentAddress);
+ DbgPrint(" - [%d]Length ............... 0x%08x\n", i, j);
+#endif
+ if (Length < j){
+ BaseAddress = CurrentAddress;
+ Length = j;
+ }
+ }
+ }
+ }
+
+#if DBG
+ DbgPrint(" - LowerAddress ............ 0x%08x\n", LowerAddress);
+ DbgPrint(" - BaseAddress ............. 0x%08x\n", BaseAddress);
+ DbgPrint(" - Length .................. 0x%08x\n", Length);
+#endif
+
+ //
+ // If this device has memory space, then change memory limit
+ // value used be allocation for PCI memory space to
+ // 'LowerAddress - 1' of this device, otherwise release spinlock
+ // and return.
+ //
+
+ if (FoundMemoryAddress) {
+ HalpPCIMemoryLimit = LowerAddress - 1;
+ } else {
+ goto NotSetBackToBack;
+ }
+
+ //
+ // We do not support the PCI devices which connected under
+ // PCI-PCI bridge.
+ //
+
+ if (BusHandler->BusNumber == 0) {
+
+ if (PciConfigMapped->Status & 0x80) {
+
+ //
+ // This device is back-to-back capable.
+ // We can map the memory space of this device as
+ // back-to-back available.
+ // Set flag to indicate setting started.
+ //
+
+ if (!HalpPCIBackToBackReg0Start) {
+ HalpPCIBackToBackReg0Start = 1;
+
+ } else if (HalpPCIBackToBackReg0Start && !HalpPCIBackToBackReg0Open) {
+ HalpPCIBackToBackReg1Start = 1;
+
+ }
+
+ //
+ // BUGBUG: Some pci drivers assign its memory space by itself.
+ // This means that we can not control the memory address of
+ // such device by MemoryLimit value. So, we can not enable the
+ // following codes now.
+ // N.B. following code does not finished.
+ //
+
+// if (!HalpFoundUncapablePCIDevice) {
+//
+// //
+// // Uncapable device not mapped yet, so we can expand
+// // back-to-back space.
+// // We expand back-to-back space until uncapable device
+// // is found.
+// //
+//
+// if (back-to-back reg0 == initialize value){
+// HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+// } else {
+// back-to-back reg0 =+ add this memory range;
+// MemoryLimit = the BaseAddress of this device;
+// }
+//
+// if (PciConfigMapped->BaseClass == 0x03
+// || (PciConfigMapped->BaseClass == 0x00
+// && PciConfigMapped->SubClass == 0x01)) {
+// HalpPCINumberOfMappedGA++;
+// }
+//
+// } else {
+
+ if (HalpNumberOfPCIGA > 1) {
+
+ //
+ // There are some PCI-GA cards.
+ // If this is PCI-GA, then set to back-to-back,
+ // else we do not map.
+ //
+
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00
+ && PciConfigMapped->SubClass == 0x01)) {
+
+ switch (HalpPCINumberOfMappedGA) {
+
+ case 0:
+
+ //
+ // We need set PCI-GA to both back-to-back space.
+ // The control reach here, it indicates PCI-GA
+ // not mapped to back-to-back space yet.
+ //
+
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ HalpPCIBackToBackReg0Open = 0;
+ break;
+
+ case 1:
+
+ //
+ // Control is transfered to this routine when one PCI-GA
+ // is already mapped. This means that reg0 had already used.
+ // We use reg1.
+ //
+
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+
+ HalpPCINumberOfMappedGA++;
+ }
+
+ } else {
+
+ //
+ // There is only one-card as PCI-GA.
+ // We need set PCI-GA to back-to-back.
+ // If this is GA and reg0 is opened, then use reg0.
+ // If this is GA and reg0 is closeed, then use reg1.
+ //
+
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00
+ && PciConfigMapped->SubClass == 0x01)) {
+
+ if (HalpPCIBackToBackReg0Open) {
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ HalpPCIBackToBackReg0Open = 0;
+
+ } else {
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+
+ HalpPCINumberOfMappedGA++;
+
+ } else {
+
+ //
+ // We can set only if reg0 or reg1 is not used.
+ //
+
+ if (HalpPCIBackToBackReg0Open) {
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ HalpPCIBackToBackReg0Open = 0;
+
+ } else if (HalpPCIBackToBackReg1Open){
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+ }
+ }
+// }
+
+ } else {
+
+ //
+ // This is back-to-back uncapable.
+ //
+
+ HalpFoundUncapablePCIDevice = 1;
+
+ //
+ // if device is back-to-back uncapable¡¤map only GA.
+ //
+
+ if (PciConfigMapped->BaseClass == 0x03
+ || (PciConfigMapped->BaseClass == 0x00
+ && PciConfigMapped->SubClass == 0x01)) {
+
+ //
+ // In case of two or more cards are connected, the
+ // process is depend on the number of PCI-GA which
+ // already mapped.
+ // But we do not need to map 3rd PCI-GA or more.
+ //
+
+ if (HalpNumberOfPCIGA > 1) {
+
+ switch (HalpPCINumberOfMappedGA) {
+
+ case 0:
+
+ //
+ // Re-nitialize all values to void already settings,
+ // and use reg0
+ //
+
+ HalpPCIBackToBackReg0Start = 1;
+ HalpPCIBackToBackReg1Start = 0;
+ HalpPCIBackToBackReg0Open = 1;
+ HalpPCIBackToBackReg1Open = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+ break;
+
+ case 1:
+
+ //
+ // Control is transfered to this routine when one PCI-GA
+ // is already mapped. This means that reg0 had already used.
+ // We use reg1.
+ //
+ // N.B. We do not know reg0 is opened or closed, so close
+ // reg0 here.
+ // (ex) 1st mapped ... capable = 1, not GA
+ // 2nd mapped ... capable = 0, GA
+ //
+
+ HalpPCIBackToBackReg0Open = 0;
+ HalpPCIBackToBackReg1Start = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+
+ }
+
+ } else {
+
+ //
+ // There is only one-card as PCI-GA.
+ // If back-to-back reg0 not being useed, use reg0,
+ // else close the space of reg0 and use reg1.
+ // (Also when reg0 is closed, use reg1)
+ //
+
+ if (!HalpPCIBackToBackReg0Start) {
+ HalpPCIBackToBackReg0Start = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
+
+ } else {
+ HalpPCIBackToBackReg0Open = 0;
+ HalpPCIBackToBackReg1Start = 1;
+ HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
+
+ }
+ }
+ }
+
+ //
+ // if being to set to back-to-back register, we have to close.
+ //
+
+ if (HalpPCIBackToBackReg0Start && HalpPCIBackToBackReg0Open) {
+ HalpPCIBackToBackReg0Open = 0;
+
+ } else if (HalpPCIBackToBackReg1Start && HalpPCIBackToBackReg1Open) {
+ HalpPCIBackToBackReg1Open = 0;
+
+ }
+
+ }
+
+ }
+
+NotSetBackToBack:
+ KiReleaseSpinLock(&HalpPCIBackToBackLock);
+
+}
+
+VOID
+HalpSetBackToBackRegister(
+ IN ULONG BaseAddress,
+ IN ULONG Length,
+ IN ULONG Register
+ )
+/*++
+
+Routine Description:
+
+ This function sets memory space of PCI device to Fast Back-to-back register.
+
+Arguments:
+
+ BaseAddress - Supplies the address which to be mapped with back-to-back.
+ Length - Supplies the length which to be mapped with back-to-back.
+ Register - Supplies the back-to-back register number.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Mask;
+
+ //
+ // make mask value
+ //
+
+ Mask = ~(Length - 1);
+
+ //
+ // set to back-to-back register
+ //
+
+#if DBG
+ DbgPrint(" set back-to-back register.\n");
+ DbgPrint(" - Register ................ %d\n", Register);
+ DbgPrint(" - Address ................. 0x%08x\n", BaseAddress);
+ DbgPrint(" - Mask .................... 0x%08x\n", Mask);
+#endif
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Address,
+ BaseAddress
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Mask,
+ Mask
+ );
+
+}
+
+ULONG
+HalpGetNumberOfPCIGA(
+ IN ULONG NumberBuses
+ )
+/*++
+
+Routine Description:
+
+ This function determines the number of PCI-GAs.
+ And initialize Fast Back-to-back register.
+
+Arguments:
+
+ NumberBuses - Supplies the number of the PCI-buses.
+
+Return Value:
+
+ number of PCI-GA.
+
+--*/
+
+{
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Bus;
+ ULONG Slot;
+ ULONG Function;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG Count;
+ ULONG Register;
+ USHORT commandValue;
+
+ Count = 0;
+ PciData = (PPCI_COMMON_CONFIG)&iBuffer;
+
+ //
+ // BUGBUG: Fast Back-to-back transaction can be used
+ // only bus number zero on this version.
+ // PCI devices connected on bus number 1 or more will
+ // be available with back-to-back on future.
+ //
+
+ NumberBuses = 1;
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (Bus = 0; Bus < NumberBuses; Bus++) {
+ BusHandler = HalpHandlerForBus (PCIBus, Bus);
+
+ for (Slot = 0; Slot < PCI_MAX_DEVICES; Slot++) {
+ SlotNumber.u.bits.DeviceNumber = Slot;
+
+ for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
+ SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->BaseClass == 0x03
+ || (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01)){
+
+ //
+ // This is Graphics Adapter. Inclement count.
+ //
+
+ Count++;
+ }
+
+ } // next PCI function
+
+ } // next PCI slot
+
+ } // next PCI bus
+
+#if DBG
+ DbgPrint(" number of PCI-GA.\n");
+ DbgPrint(" - number of PCI-GA ........ %d\n", Count);
+#endif
+
+ //
+ // Initialize Fast Back-to-back register.
+ //
+
+ for (Register = 0; Register < 2; Register++) {
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Address,
+ INIT_VALUE_OF_BACK_TO_BACK_ADDR
+ );
+
+ WRITE_REGISTER_ULONG(
+ &DMA_CONTROL->PCIFastBackToBack[Register].Mask,
+ INIT_VALUE_OF_BACK_TO_BACK_MASK
+ );
+ }
+
+ commandValue = READ_REGISTER_USHORT(&DMA_CONTROL->PCICommand);
+ WRITE_REGISTER_USHORT(&DMA_CONTROL->PCICommand, (commandValue & ~0x0200));
+
+ return Count;
+
+}
diff --git a/private/ntos/nthals/halr96b/mips/pciint.c b/private/ntos/nthals/halr96b/mips/pciint.c
new file mode 100644
index 000000000..06571660d
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/pciint.c
@@ -0,0 +1,376 @@
+// #pragma comment(exestr, "@(#) pciint.c 1.1 95/09/28 15:46:29 nec")
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Jun 30 02:58:57 1995 kbnes!kisimoto
+ - Merge build 1057
+ H002 Tue Sep 5 20:21:24 1995 kbnes!kisimoto
+ - PCI Fast Back-to-back transfer support
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG PciIsaIrq;
+ULONG HalpEisaELCR;
+BOOLEAN HalpDoingCrashDump;
+extern ULONG HalpPCIMemoryLimit; // H002
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+#if defined(_R94A_) // H001
+ULONG R94A_PCIPinToLineTable[][4] = {
+ { 0xF, 0xF, 0xF, 0xF }, // Slot 0(Hurricane)No InterruptPin
+ { 0xF, 0xF, 0xF, 0xF }, // Slot 1(Typhoon) No InterruptPin assign
+ { 0xF, 0xF, 0xF, 0xF }, // Slot 2(PCEB) No InterruptPin assign
+ { 0x3, 0x3, 0x3, 0x3 }, // Slot 3 : INT A B C D
+ { 0x2, 0x2, 0x2, 0x2 }, // Slot 4 : INT A B C D
+ { 0x1, 0x1, 0x1, 0x1 } // Slot 5 : INT A B C D
+};
+#endif // _R94A_
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+#ifndef MCA
+ Isa, 0,
+#else
+ MicroChannel, 0,
+#endif
+ BusInterruptLevel ^ IRQXOR,
+ 0,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+ On a DBG build we adjust InterruptLine just to ensure driver's
+ don't connect to it without translating it on the PCI bus.
+
+--*/
+{
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ PciData->u.type0.InterruptLine =
+ (UCHAR)R94A_PCIPinToLineTable[SlotNumber.u.bits.DeviceNumber][PciData->u.type0.InterruptPin];
+
+#else
+
+ //
+ // Set vector as a level vector. (note: this code assumes the
+ // irq is static and does not move).
+ //
+
+ if (PciData->u.type0.InterruptLine >= 1 &&
+ PciData->u.type0.InterruptLine <= 15) {
+
+ //
+ // If this bit was on the in the PIC ELCR register,
+ // then mark it in PciIsaIrq. (for use in hal.dll,
+ // such that we can assume the interrupt controller
+ // has been properly marked as a level interrupt for
+ // this IRQ. Other hals probabily don't care.)
+ //
+
+ PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine);
+ }
+
+ //
+ // On a PC there's no Slot/Pin/Line mapping which needs to
+ // be done.
+ //
+
+ PciData->u.type0.InterruptLine ^= IRQXOR;
+
+#endif // _R94A_
+
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R94A_) // H001
+
+ PciNewData->u.type0.InterruptLine =
+ (UCHAR)R94A_PCIPinToLineTable[SlotNumber.u.bits.DeviceNumber][PciOldData->u.type0.InterruptPin];
+
+#else
+
+ PciNewData->u.type0.InterruptLine ^= IRQXOR;
+
+#endif // _R94A_
+
+#if DBG
+ if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine ||
+ PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) {
+ DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n");
+ // DbgBreakPoint ();
+ }
+#endif
+}
+
+#if !defined(SUBCLASSPCI)
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+#if defined(_R94A_) // H001
+ KeRaiseIrql(PROFILE_LEVEL, Irql);
+#else
+ *Irql = KfRaiseIrql (HIGH_LEVEL);
+#endif
+ KiAcquireSpinLock (SpinLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (SpinLock);
+#if defined(_R94A_) // H001
+ KeLowerIrql (Irql);
+#else
+ KfLowerIrql (Irql);
+#endif // _R94A_
+ }
+}
+
+#endif
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // H002
+ // change Memory.Limit value to BaseAddress which last mapped.
+ //
+
+#if DBG
+ DbgPrint(" change Memory.Limit!\n");
+ DbgPrint(" - Before limit ............ 0x%08x\n",
+ ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart);
+#endif
+
+ ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart = HalpPCIMemoryLimit;
+
+#if DBG
+ DbgPrint(" - After limit ............. 0x%08x\n",
+ ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart);
+#endif
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+#if defined(_R94A_) // H001
+ PPCIPBUSDATA BusData;
+#endif
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+#if defined(_R94A_) // H001
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+#else
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == IRQXOR) {
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+
+#endif // _R94A_
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halr96b/mips/pcip.h b/private/ntos/nthals/halr96b/mips/pcip.h
new file mode 100644
index 000000000..8e6a361a8
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/pcip.h
@@ -0,0 +1,200 @@
+// #pragma comment(exestr, "@(#) pcip.h 1.1 95/09/28 15:46:56 nec")
+/*++
+
+ Modification History
+
+ H001 Fri Jun 30 02:51:55 1995 kbnes!kisimoto
+ - add definition
+
+--*/
+
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+#if defined(_R94A_) // H001
+#define R94A_PCI_TYPE1_ADDR_PORT 0xFFFFc518
+#define R94A_PCI_TYPE1_DATA_PORT 0xFFFFc520
+#endif // _R94A_
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halr96b/mips/pcisup.c b/private/ntos/nthals/halr96b/mips/pcisup.c
new file mode 100644
index 000000000..d46cc00e4
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/pcisup.c
@@ -0,0 +1,632 @@
+// #pragma comment(exestr, "@(#) r94apcisup.c 1.1 95/09/28 18:37:11 nec")
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r94apisup.c
+
+Abstract:
+
+ The module provides the PCI bus support for R94A systems.
+
+Author:
+
+
+Revision History:
+
+ L0001 1994.9.20 kbnes!kuriyama(A)
+ -New module for R94A R4400 system
+ -add HalpAllocaltePCIAdapter()
+
+ H0001 Tue Sep 20 22:58:03 JST 1994 kbnes!kishimoto
+ -add HalpEnablePCIInterrupt()
+ -add HalpDisablePCIInterrupt()
+ -add HalpPCIDispatch()
+ -add HalpPCIFatalError()
+
+ H0002 Tue Oct 4 12:47:58 JST 1994 kbnes!kishimoto
+ -modify HalpPCIFatalError()
+ display the appropriate PCI errors
+
+ L0002 1994.10.13 kbnes!kuriyama(A)
+ -add HalpAllocaltePCIAdapter()
+ -add AdapterBaseVa set routine
+
+ H0003 Fri Oct 14 14:54:40 JST 1994 kbnes!kishimoto
+ -chg use READ_REGISTER_DWORD to read 64-bit I/O register
+
+ H0003 Mon Oct 17 14:36:57 JST 1994 kbnes!kishimoto
+ -chg Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX()
+ XXX_EISA_PCI_XXX rename to XXX_EISA_XXX
+ MAXIMUM_PCI_SLOT rename to R94A_PCI_SLOT
+
+ H0004 Wed Oct 19 13:24:51 JST 1994 kbnes!kishimoto
+ -chg HalpPCIDispatch()
+ The PCI-error check change up the order.
+
+ H0005 Wed Oct 19 20:17:09 JST 1994 kbnes!kishimoto
+ -add substitute READ_REGISTER_BUFFER_UCHAR for
+ READ_REGISTER_DWORD because of storm alpha-
+ version cannot 64-bit access.
+
+ L0006 Wed Oct 19 22:01:27 JST 1994 kbnes!kuriyama(A)
+ -chg HalpAllocatePCIAdapter()
+ del useChannel
+ del channelNumber
+ del controllerNumber
+ del eisaSystem
+ chg AdapterBaseVa value
+
+ H0006 Tue Nov 22 22:10:00 1994 kbnes!kishimoto
+ -del delete _R94ABBM32_
+ The limitation of 32bit bus-access is only applied
+ under PCI-bus. I make a wrong application.
+
+ H0007 Fri Jul 21 18:02:55 1995 kbnes!kishimoto
+ -merge source with J94C
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+#if defined(_R94A_)
+
+#include <stdio.h>
+
+/* start H0000 */
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+VOID
+HalpPCIFatalError(
+ STORM_PCI_INTRRUPT_STATUS InterruptStatus
+ );
+
+/* end H0000 */
+
+// start L0001
+PADAPTER_OBJECT
+HalpAllocatePCIAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an PCI adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ UCHAR adapterMode;
+
+ //
+ // All PCI Cards is Master card.
+ //
+
+ if (DeviceDescriptor->InterfaceType == PCIBus &&
+ DeviceDescriptor->Master) {
+
+ } else {
+
+ return(NULL);
+ }
+
+
+/* start L0002 */
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ adapterBaseVa = ~0; /* L0006 */
+/* end L0002 */
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ //
+ // If the channel is not used then indicate the this is an PCI bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+
+}
+// end L0001
+
+/* start H0001 */
+VOID
+HalpEnablePCIInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // enable specified PCI bus interrupt.
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable
+ );
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable,
+ (ULONG)( i | 1 << (Vector - PCI_VECTORS))
+ );
+
+ return;
+
+}
+
+VOID
+HalpDisablePCIInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the PCI bus specified PCI bus interrupt.
+ PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6)
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // disable specified PCI bus interrupt.
+ //
+
+ i = READ_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable
+ );
+
+ WRITE_REGISTER_ULONG(
+ &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable,
+ (ULONG)( i & ~(1 << (Vector - PCI_VECTORS)))
+ );
+
+ return;
+
+}
+
+
+BOOLEAN
+HalpPCIDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the PCI device interrupts. Its function is to call the third
+ level interrupt dispatch routine and acknowledge the interrupt at the PCI
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_DEVICE_LEVEL, EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the third level routine.
+
+--*/
+
+{
+ STORM_PCI_INTRRUPT_STATUS InterruptStatus;
+ PKINTERRUPT interruptObject;
+ PULONG dispatchCode;
+ BOOLEAN returnValue;
+ LONG Index;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ *((PULONG) &InterruptStatus) = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptStatus);
+
+ //
+ // BUGBUG
+ //
+
+ if (*((PULONG)&InterruptStatus) == 0) {
+
+ //
+ // There is not PCI interrupt.
+ //
+
+ return(FALSE);
+
+ }
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ // R94A has the following PCI error interrupts.
+ // Target abort interrupt
+ // Master abort interrupt
+ // Retry overflow interrupt
+ // SERR interrupt
+ // PERR interrupt
+ //
+
+ if (InterruptStatus.Perr == 1 ||
+ InterruptStatus.Serr == 1 ||
+ InterruptStatus.RetryOverflow == 1 ||
+ InterruptStatus.MasterAbort == 1 ||
+ InterruptStatus.TargetAbort == 1) {
+
+ //
+ // Display the appropriate PCI errors and bugcheck to dump the machine state.
+ //
+
+ HalpPCIFatalError(InterruptStatus);
+ KeBugCheck(DATA_BUS_ERROR);
+
+ //
+ // The following code is never executed.
+ //
+
+ return(FALSE);
+ }
+
+ //
+ // if INT[A.B.C.D] is active, then call the appropriate PCI drivers.
+ //
+
+ if ((*((PULONG)&InterruptStatus) & 0xf) != 0x0) {
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+ // N.B. R94A PCI interrupts flow :
+ //
+ // system slot1 slot2 slot3
+ // INT A <----------+ + +
+ // INT B <------+ + + +
+ // INT C <---+ | + + +
+ // Reserved | | + + +
+ // | +-----------+ |
+ // +----------------------+
+ //
+ //
+ // PCI Interrupt Status Register Bit Definitions are:
+ //
+ // [31:09] Reserved
+ // [08] Target abort interrupt status
+ // [07] Master abort interrupt status
+ // [06] Retry overflow interrupt status
+ // [05] SERR interrupt status
+ // [04] PERR interrupt status
+ // [03] INTA interrupt status
+ // [02] INTB interrupt status
+ // [01] INTC interrupt status
+ // [00] INTD interrupt status
+ //
+
+ for (Index = 3; Index > (3 - R94A_PCI_SLOT); Index--) {
+
+ //
+ // Check if the PCI interrupt occur.
+ //
+
+ if (((*((PULONG)&InterruptStatus) & 0xf) & ((ULONG)1 << Index)) != 0x0) {
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCI_VECTORS + Index]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+ }
+
+ }
+
+ }
+
+ return(returnValue);
+
+}
+
+
+VOID
+HalpPCIFatalError(
+ STORM_PCI_INTRRUPT_STATUS InterruptStatus
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an PCI fatal interrupt.
+ This function displays appropriate PCI error information.
+
+Arguments:
+
+ InterruptStatus - PCI Interrupt Status value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR Buffer[100];
+ UCHAR registerChar;
+ ULONG registerLong;
+ LARGE_INTEGER registerLarge;
+ LARGE_INTEGER InvalidAddressValue;
+ LARGE_INTEGER EccDiagnosticValue;
+
+ HalpChangePanicFlag(16, 0x01, 0x10); // H0007
+
+ HalDisplayString("\nFatal system error occured\n\n");
+
+ //
+ // Display the following register value.
+ //
+ // register name address
+ //
+ // Remode Failed Address 0x80000010 32bit
+ // Memory Failed Address 0x80000018 32bit
+ // Processor Invalid Address 0x80000020 33bit
+ // ECC Diagnostic 0x800001c8 64bit
+ // PCI Status 0x80000606 16bit
+ // PCI Master Retry Timer 0x80000668 32bit
+ //
+
+ //
+ // Display the PCI fatal error information
+ //
+
+ if (InterruptStatus.Perr){
+ HalDisplayString("PCI: Data parity error\n");
+ }
+
+ if (InterruptStatus.Serr){
+ HalDisplayString("PCI: Address parity error\n");
+ }
+
+ if (InterruptStatus.RetryOverflow){
+ HalDisplayString("PCI: Retry overflow\n");
+ }
+
+ if (InterruptStatus.MasterAbort){
+ HalDisplayString("PCI: Master abort\n");
+ }
+
+ if (InterruptStatus.TargetAbort){
+ HalDisplayString("PCI: Target abort\n");
+ }
+
+ // ! start
+ // test test test : dump the hardware registers of R94A
+ // <cording memo>
+ // dump R94A all hardware-registers to buffer instead of display console
+ // registers that is only important for analasis dump are display to console
+ //
+ // registers which display to console are:
+ // 0x80000000 Configuration
+ // 0x80000010 RemoteFailedAddress
+ // 0x80000018 MemoryFailedAddress
+ // 0x80000020 InvalidAddress
+ // 0x80000078 NmiSource
+ // 0x800000f8 InterruptEnable
+ // 0x80000188 Errortype
+ // 0x800001c8 EccDiagnostic
+ // 0x80000530 PCIInterruptEnable
+ // 0x80000538 PCIInterruptStatus
+ // 0x80000606 PCIStatus
+ // 0x800005bc TyphoonErrorStatus
+ // 0x80000668 PCIMasterRetryTimer
+ //
+ // 0x8000f000 I/O Device Interrupt Enable
+ //
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &InvalidAddressValue);
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, &EccDiagnosticValue);
+
+ sprintf(Buffer,
+ "Configuration : %08x RemoteFailedAddress : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->Configuration.Long),
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->RemoteFailedAddress.Long));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "MemoryFailedAddress : %08x InvalidAddress :%01x%08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long),
+ (InvalidAddressValue.HighPart & 0x1), InvalidAddressValue.LowPart);
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "NmiSource : %08x InterruptEnable : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->NmiSource.Long),
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "Errortype : %08x EccDiagnostic(High) : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->NmiSource.Long),
+ EccDiagnosticValue.HighPart);
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "EccDiagnostic(Low) : %08x PCIInterruptEnable : %08x\n",
+ EccDiagnosticValue.LowPart,
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "PCIInterruptStatus : %08x PCIStatus : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptStatus.Long),
+ READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ sprintf(Buffer,
+ "TyphoonErrorStatus : %08x PCIMasterRetryTimer : %08x\n",
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->TyphoonErrorStatus),
+ READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIMasterRetryTimer));
+
+ HalDisplayString((UCHAR *)Buffer);
+
+ HalpGetStatusRegister(&registerLong);
+
+ sprintf(Buffer,
+ "I/O DevIntEnable : %08x (CPU)StatusRegister : %08x\n",
+ READ_REGISTER_ULONG((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE),
+ registerLong);
+
+ HalDisplayString((UCHAR *)Buffer);
+
+
+ //
+ // ! end
+ //
+
+// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->RemoteFailedAddress.Long);
+// sprintf ((UCHAR *)Buffer, "RemodeFailedAddress = 0x%08x\n", registerLong);
+// HalDisplayString((UCHAR *)Buffer);
+
+// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long);
+// sprintf ((UCHAR *)Buffer, "MemoryFailedAddress = 0x%08x\n", registerLong);
+// HalDisplayString((UCHAR *)Buffer);
+
+ //
+ // memo
+ //
+ // (./ntos/inc/mips.h)
+ // #define READ_REGISTER_BUFFER_UCHAR(x, y, z) {
+ // PUCHAR registerBuffer = x;
+ // PUCHAR readBuffer = y;
+ // ULONG readCount;
+ // for (readCount = z; readCount--; readBuffer++, registerBuffer++) {
+ // *readBuffer = *(volatile UCHAR * const)(registerBuffer);
+ // }
+ // }
+ //
+
+/* start H0003 */
+
+// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+// sprintf ((UCHAR *)Buffer, "InvalidAddress =0x%01x%08x\n", registerLarge.HighPart & 0x1, registerLarge.LowPart);
+// HalDisplayString((UCHAR *)Buffer);
+
+// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, &registerLarge);
+// sprintf ((UCHAR *)Buffer, "EccDiagnostic(High) = 0x%08x\n", registerLarge.HighPart);
+// HalDisplayString((UCHAR *)Buffer);
+
+// sprintf ((UCHAR *)Buffer, "EccDiagnostic(Low) = 0x%08x\n", registerLarge.LowPart);
+// HalDisplayString((UCHAR *)Buffer);
+
+/* end H0003 */
+
+// registerChar = READ_REGISTER_UCHAR(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus);
+// sprintf ((UCHAR *)Buffer, "PCIStatus = 0x%08x\n", registerChar);
+// HalDisplayString((UCHAR *)Buffer);
+
+// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIMasterRetryTimer);
+// sprintf ((UCHAR *)Buffer, "PCIMasterRetryTimer = 0x%08x\n", registerLong);
+// HalDisplayString((UCHAR *)Buffer);
+
+ return;
+
+}
+
+/* end H0001 */
+#endif // _R94A_
diff --git a/private/ntos/nthals/halr96b/mips/r94adbg.c b/private/ntos/nthals/halr96b/mips/r94adbg.c
new file mode 100644
index 000000000..e48290c04
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94adbg.c
@@ -0,0 +1,157 @@
+// #pragma comment(exestr, "@(#) r94adbg.c 1.1 95/09/28 15:47:19 nec")
+/*++
+
+Copyright (c) 1994 KOBE NEC Software
+
+Module Name:
+
+ r94adbg.c
+
+Abstract:
+
+ The module provides the debug support functions for R94A systems.
+
+Author:
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto
+ - add HalDisplayLED()
+ new function.
+ - add HalpOutputCharacterToLED()
+ new function.
+
+ H001 Mon Oct 17 13:01:53 JST 1994 kbnes!kishimoto
+ - add HalR94aDebugPrint()
+ new function.
+ - chg HalpDisplayLED()
+ rename from HalDisplayLED()
+
+ H002 Thu Oct 20 19:42:03 JST 1994 kbnes!kishimoto
+ - add R94aBbmLEDMapped used at KdPortInitialize()(jxport.c)
+ for debug use only
+
+ H003 Fri Oct 21 10:18:01 JST 1994 kbnes!kishimoto
+ - add specify the output device.
+
+ M004 Fri Jan 06 10:49:29 JST 1995 kbnes!kuriyama
+ - add HalpPrintMdl()
+
+ H005 Sat Mar 18 16:23:05 JST 1995 kbnes!kishimoto
+ - always include "halp.h"
+
+ S006 kuriyama@oa2.kb.nec.co.jp Mon Apr 03 10:49:48 JST 1995
+ - delete PrintMdl routine (if defined _PRINT_MDL_)
+
+--*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "halp.h" // H005
+
+#define R94A_LED 0
+#define R94A_DBG 1
+#define R94A_CON 2
+
+ULONG HalpR94aDebugOutput = R94A_DBG ; // start H003
+ULONG R94aDebugLevel = 1;
+
+VOID
+HalR94aDebugPrint(
+ ULONG DebugLevel,
+ PUCHAR LedCharactor,
+ PUCHAR Message,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This function is used to display debug information.
+
+ Usage :
+ HalR94aDebugPrint(
+ (ULONG) 3,
+ "1234",
+ "Dbg : Current file is %s [%d]\n",
+ __FILE__,
+ __LINE__
+ );
+
+Arguments:
+
+ DebugLevel - Debug level for output.
+ If DebugLevel less than R94aDebugLevel, not display.
+
+ LedCharactor - Display charactor for LED.
+
+ Message - Display format for console or debug-teminal.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ va_list argp;
+ ULONG Index;
+ CHAR Buffer[100];
+
+ if (DebugLevel >= R94aDebugLevel) {
+
+ va_start(argp, Message);
+ vsprintf(Buffer, Message, argp);
+
+ if (HalpR94aDebugOutput & (1 << R94A_DBG)) { // H003
+
+ DbgPrint(Buffer);
+
+ }
+
+ if (HalpR94aDebugOutput & (1 << R94A_CON)) {
+
+ HalDisplayString(Buffer);
+
+ }
+
+ va_end(argp);
+ }
+
+ return;
+}
+/* end H001 */
+
+/* M004 +++ */
+#if defined(_PRINT_MDL_) //S006
+VOID
+HalpPrintMdl(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+
+
+ //
+ // Get the lower bound of the free physical memory and the
+ // number of physical pages by walking the memory descriptor lists.
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ MemoryDescriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType);
+ DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage);
+ DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount);
+
+ NextMd = MemoryDescriptor->ListEntry.Flink;
+ }
+}
+#endif // _PRINT_MDL_ // S006
+/* M004 --- */
diff --git a/private/ntos/nthals/halr96b/mips/r94adef.h b/private/ntos/nthals/halr96b/mips/r94adef.h
new file mode 100644
index 000000000..4ebbff766
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94adef.h
@@ -0,0 +1,266 @@
+// #pragma comment(exestr, "@(#) r94adef.h 1.1 95/09/28 15:47:51 nec")
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1994 NEC Corporation
+
+Module Name:
+
+ r94adef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the R94A system.
+
+Author:
+
+ Akitoshi Kuriyama 23-Aug-1994
+
+Revision History:
+
+ M001 1994.8.23 A. Kuriyama
+ - Modify for R94A MIPS R4400 (original duodef.h)
+ M002 1994.9.24 A. Kuriyama
+ - Modify PCI A-D Vector Value
+ H000 Sat Sep 24 23:11:51 JST 1994 kbnes!kishimoto
+ - Add the number of PCI slots
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 17:10:13 JST 1994
+ - Add
+ #define PCI_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+64*1024)
+ #define PCI_MEMORY_PHYSICAL_BASE_LOW (EISA_MEMORY_VERSION2_LOW + 64*1024*1024)
+ #define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x00000001
+ M003 Mon Oct 17 17:26:12 JST 1994 kbnes!kuriyama
+ name change MAXIMUN_PCI_SLOT -> R94A_PCI_SLOT
+ ADD002 ataka@oa2.kb.nec.co.jp Mon Oct 17 19:30:00 JST 1994
+ - change PCI_CONTROL_PHYSICAL_BASE, PCI_MEMORY_PHYSICAL_BASE_LOW
+ 64*1024 -> 10000 64*1024*1024 -> 4000000
+ D001 ataka@oa2.kb.nec.co.jp Sat Nov 05 16:06:26 JST 1994
+ - reduce DMA_TRANSLATION_LIMIT to 4 only for BBM DMA
+ S0004 Thu Dec 22 11:55:04 JST 1994 kbnes!A.Kuriyama
+ -add beta machine limit
+ S0005 Thu Jan 05 17:17:09 JST 1995 kbnes!A.Kuriyama
+ - warning clear
+ S0006 Thu Jan 05 18:52:51 JST 1995 kbnes!A.Kuriyama
+ - dma_limit change
+ M0007 Tue Mar 07 14:34:55 JST 1995 kbnes!kuriyama (A)
+ - expand dma logical address
+ M0008 Fri Mar 10 15:34:25 JST 1995 kbnes!kuriyama (A)
+ - expand dma logical address bug fix
+ M0009 Tue Mar 21 02:45:16 1995 kbnes!kishimoto
+ - physical base of PCI memory set to 64M
+ M0010 Tue Mar 21 03:06:05 1995 kbnes!kishimoto
+ - M0009 could not allocate memory
+ set base to zero.
+ M0011 Tue Apr 25 16:34:35 1995 kbnes!kishimoto
+ - add MRC registers
+ S0012 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 01:55:08 JST 1995
+ - add NVRAM_VIRTUAL_BASE
+ M0011 Sat Aug 12 16:51:50 1995 kbnes!kishimoto
+ - rearrange the comments.
+
+--*/
+
+#ifndef _R94ADEF_
+#define _R94ADEF_
+
+//
+// ADD001,ADD002
+// Define physical base addresses for system mapping.
+//
+
+#define VIDEO_MEMORY_PHYSICAL_BASE 0x40000000 // physical base of video memory
+#define VIDEO_CONTROL_PHYSICAL_BASE 0x60000000 // physical base of video control
+#define CURSOR_CONTROL_PHYSICAL_BASE 0x60008000 // physical base of cursor control
+#define VIDEO_ID_PHYSICAL_BASE 0x60010000 // physical base of video id register
+#define VIDEO_RESET_PHYSICAL_BASE 0x60020000 // physical base of reset register
+#define DEVICE_PHYSICAL_BASE 0x80000000 // physical base of device space
+#define NET_PHYSICAL_BASE 0x80001000 // physical base of ethernet control
+#define SCSI1_PHYSICAL_BASE 0x80002000 // physical base of SCSI1 control
+#define SCSI2_PHYSICAL_BASE 0x80003000 // physical base of SCSI2 control
+#define RTCLOCK_PHYSICAL_BASE 0x80004000 // physical base of realtime clock
+#define KEYBOARD_PHYSICAL_BASE 0x80005000 // physical base of keyboard control
+#define MOUSE_PHYSICAL_BASE 0x80005000 // physical base of mouse control
+#define SERIAL0_PHYSICAL_BASE 0x80006000 // physical base of serial port 0
+#define SERIAL1_PHYSICAL_BASE 0x80007000 // physical base of serial port 1
+#define PARALLEL_PHYSICAL_BASE 0x80008000 // physical base of parallel port
+#define EISA_CONTROL_PHYSICAL_BASE 0x90000000 // physical base of EISA control
+#define EISA_MEMORY_PHYSICAL_BASE 0x91000000 // physical base of EISA memory
+#define EISA_MEMORY_VERSION2_LOW 0x00000000 // physical base of EISA memory
+#define EISA_MEMORY_VERSION2_HIGH 0x00000001 // with version 2 address chip
+#define PROM_PHYSICAL_BASE 0xfff00000 // physical base of boot PROM
+#define EEPROM_PHYSICAL_BASE 0xfff40000 // physical base of FLASH PROM
+#define PCI_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE) // physical base of PCI control
+#define PCI_MEMORY_PHYSICAL_BASE_LOW (EISA_MEMORY_VERSION2_LOW) // physical base of PCI memory
+#define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x00000001 // physical base of PCI memory
+
+//
+// S0012
+// Define virtual/physical base addresses for system mapping.
+//
+
+#define NVRAM_VIRTUAL_BASE 0xffff8000 // virtual base of nonvolatile RAM
+#define NVRAM_PHYSICAL_BASE 0x80009000 // physical base of nonvolatile RAM
+
+#define SP_VIRTUAL_BASE 0xffffa000 // virtual base of serial port 0
+#define SP_PHYSICAL_BASE SERIAL0_PHYSICAL_BASE // physical base of serial port 0
+
+#define DMA_VIRTUAL_BASE 0xffffc000 // virtual base of DMA control
+#define DMA_PHYSICAL_BASE DEVICE_PHYSICAL_BASE // physical base of DMA control
+
+#define INTERRUPT_VIRTUAL_BASE 0xffffd000 // virtual base of interrupt source
+#define INTERRUPT_PHYSICAL_BASE 0x8000f000 // physical base of interrupt source
+
+//
+// Define the size of the DMA translation table.
+//
+
+#if defined (_BBM_DMA_) // D001,S0004,S0005,S0006
+
+#define DMA_TRANSLATION_LIMIT (sizeof(TRANSLATION_ENTRY) * 8 * 4) // translation table limit
+
+#else
+
+#if defined(_DMA_EXPAND_) // M0007,M0008
+
+#define ISA_MAX_ADR 0x400000L // ISA MAX Logical Address
+#define EISA_MIN_ADR 0x1000000L // EISA/PCI MIN Logical Address
+#define EISA_MAX_ADR 0x2000000L // EISA/PCI MAX Logical Address
+#define DMA_TRANSLATION_LIMIT (EISA_MAX_ADR / PAGE_SIZE * sizeof(TRANSLATION_ENTRY) )
+ // translation table limit
+#else // _DMA_EXPAND_
+
+#define DMA_TRANSLATION_LIMIT 0x2000 // translation table limit
+
+#endif // _DMA_EXPAND_
+
+#endif // (_BBM_DMA_)
+
+
+//
+// Define the maximum number of map registers allowed per allocation.
+//
+
+#define DMA_REQUEST_LIMIT (DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY) * 8))
+
+//
+// Define pointer to DMA control registers.
+//
+
+#define DMA_CONTROL ((volatile PDMA_REGISTERS)(DMA_VIRTUAL_BASE))
+
+//
+// Define DMA channel interrupt level.
+//
+
+#define DMA_LEVEL 3
+
+//
+// Define the minimum and maximum system time increment values in 100ns units.
+//
+
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+//
+// Define Duo clock level.
+//
+
+#define CLOCK_LEVEL 6 // Interval clock level
+#define CLOCK_INTERVAL ((MAXIMUM_INCREMENT / (10 * 1000)) - 1) // Ms minus 1
+#define CLOCK2_LEVEL CLOCK_LEVEL //
+
+//
+// Define EISA device level.
+//
+
+#define EISA_DEVICE_LEVEL 5 // EISA bus interrupt level
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define EISA_VECTORS 32
+
+#define IRQL10_VECTOR (10 + EISA_VECTORS) // Eisa interrupt request level 10
+#define IRQL11_VECTOR (11 + EISA_VECTORS) // Eisa interrupt request level 11
+#define IRQL12_VECTOR (12 + EISA_VECTORS) // Eisa interrupt request level 12
+#define IRQL13_VECTOR (13 + EISA_VECTORS) // Eisa interrupt request level 13
+
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+//
+// Define I/O device interrupt level.
+//
+
+#define DEVICE_LEVEL 4 // I/O device interrupt level
+
+//
+// Define device interrupt vectors.
+//
+
+#define DEVICE_VECTORS 16 // starting builtin device vector
+
+#define PARALLEL_VECTOR (1 + DEVICE_VECTORS) // Parallel device interrupt vector
+//#define VIDEO_VECTOR (3 + DEVICE_VECTORS) // video device interrupt vector
+#define AUDIO_VECTOR (3 + DEVICE_VECTORS) // audio device interrupt vector
+#define NET_VECTOR (4 + DEVICE_VECTORS) // ethernet device interrupt vector
+#define SCSI1_VECTOR (5 + DEVICE_VECTORS) // SCSI device interrupt vector
+#define SCSI2_VECTOR (6 + DEVICE_VECTORS) // SCSI device interrupt vector
+#define KEYBOARD_VECTOR (7 + DEVICE_VECTORS) // Keyboard device interrupt vector
+#define MOUSE_VECTOR (8 + DEVICE_VECTORS) // Mouse device interrupt vector
+#define SERIAL0_VECTOR (9 + DEVICE_VECTORS) // Serial device 0 interrupt vector
+#define SERIAL1_VECTOR (10 + DEVICE_VECTORS) // Serial device 1 interrupt vector
+#define TYPHOON_ERROR_INTERRUPT_VECTOR (15 + DEVICE_VECTORS) // TYPHOON error vector
+//#define MAXIMUM_BUILTIN_VECTOR SERIAL1_VECTOR // maximum builtin vector
+#define MAXIMUM_BUILTIN_VECTOR TYPHOON_ERROR_INTERRUPT_VECTOR // maximum builtin vector
+
+//
+// M0001,M0002
+// Define PCI device interrupt vectors.
+//
+
+#define PCI_VECTORS 80
+//#define INTERRUPT_D_VECTOR (0 + PCI_VECTORS)
+//#define INTERRUPT_C_VECTOR (1 + PCI_VECTORS)
+//#define INTERRUPT_B_VECTOR (2 + PCI_VECTORS)
+//#define INTERRUPT_A_VECTOR (3 + PCI_VECTORS)
+//#define MAXIMUM_PCI_VECTOR INTERRUPT_A_VECTOR
+
+//
+// Define the clock speed in megahetz for the SCSI protocol chips.
+//
+
+#define NCR_SCSI_CLOCK_SPEED 24
+
+//
+// PROM entry point definitions.
+//
+// Define base address of prom entry vector and prom entry macro.
+//
+
+#define PROM_BASE (KSEG1_BASE | 0x1fc00000)
+#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8))
+
+//
+// H000,M003
+// the number of lines which PCI interrupts.
+//
+
+#define R94A_PCI_SLOT 3
+
+//
+// M0011
+// Define pointer to MRC control registers.
+//
+
+#define MRC_CONTROL ((volatile PMRC_REGISTERS)(DMA_VIRTUAL_BASE))
+
+//
+// M0011
+// Define physical base addresses for system mapping.
+//
+
+#define MRC_TEMP_PHYSICAL_BASE 0x80012000 // physical base of MRC and TEMP sensor
+
+#endif // _R94ADEF_
+
diff --git a/private/ntos/nthals/halr96b/mips/r94adma.h b/private/ntos/nthals/halr96b/mips/r94adma.h
new file mode 100644
index 000000000..5d8676ebb
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94adma.h
@@ -0,0 +1,433 @@
+// #pragma comment(exestr, "@(#) r94adma.h 1.1 95/09/28 15:48:23 nec")
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1994 NEC Corporation
+
+Module Name:
+
+ r94adma.h
+
+Abstract:
+
+ This module is the header file that describes the DMA control register
+ structure for the R94A system.
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1990
+
+Revision History:
+
+ M001 1994.8.24 A. Kuriyama
+ - Modify for R94A MIPS R4400 (original duodma.h)
+ H000 Sat Sep 24 21:36:20 JST 1994 kbnes!kishimoto
+ - Add PCIInterruptStatus register structure definition
+ M002 Mon Oct 03 19:52:16 JST 1994 kbnes!kuriyama(A)
+ - Add PCI(HURRICANE) register
+ - Change InvalidAddress register to DMA_LARGE_REGISTER
+ - Change RTC_REGISTER structure define.
+ - add Optional... registers
+ H001 Fri Dec 9 18:29:10 1994 kbnes!kishimoto
+ - Modify LEDControl definition (SHORT -> CHAR)
+ H002 Tue Jan 24 18:24:48 1995 kbnes!kishimoto
+ - Add PCI interrupt enable bits definitions.
+ H003 Tue Apr 25 16:38:06 1995 kbnes!kishimoto
+ - Add MRC registers
+ H004 Sat Aug 12 16:18:53 1995 kbnes!kishimoto
+ - rearrange comments.
+
+--*/
+
+#ifndef _R94ADMA_
+#define _R94ADMA_
+
+//
+// M001
+// Define DMA register structures.
+//
+
+typedef struct _DMA_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} DMA_REGISTER, *PDMA_REGISTER;
+
+typedef struct _DMA_CHAR_REGISTER {
+ UCHAR Char;
+ UCHAR Fill;
+ USHORT Fill2;
+} DMA_CHAR_REGISTER, *PDMA_CHAR_REGISTER;
+
+typedef struct _DMA_SHORT_REGISTER {
+ USHORT Short;
+ USHORT Fill;
+} DMA_SHORT_REGISTER, *PDMA_SHORT_REGISTER;
+
+typedef struct _DMA_LARGE_REGISTER {
+ union {
+ LARGE_INTEGER LargeInteger;
+ double Double;
+ } u;
+} DMA_LARGE_REGISTER, *PDMA_LARGE_REGISTER;
+
+//
+// Define DMA channel register structure.
+//
+
+typedef struct _DMA_CHANNEL {
+ DMA_REGISTER Mode;
+ DMA_REGISTER Enable;
+ DMA_REGISTER ByteCount;
+ DMA_REGISTER Address;
+} DMA_CHANNEL, *PDMA_CHANNEL;
+
+//
+// M002
+// Define PCI Address/Mask register structure
+//
+
+typedef struct _PCI_ADDRESS_MASK {
+ ULONG Address;
+ ULONG Mask;
+} PCI_ADDRESS_MASK, *PPCI_ADDRESS_MASK;
+
+//
+// Define DMA control register structure.
+//
+
+typedef volatile struct _DMA_REGISTERS {
+ DMA_REGISTER Configuration; // offset 000
+ DMA_REGISTER RevisionLevel; // offset 008
+ DMA_REGISTER RemoteFailedAddress; // offset 010
+ DMA_REGISTER MemoryFailedAddress; // offset 018
+ DMA_LARGE_REGISTER InvalidAddress; // offset 020 // M002
+ DMA_REGISTER TranslationBase; // offset 028
+ DMA_REGISTER TranslationLimit; // offset 030
+ DMA_REGISTER TranslationInvalidate; // offset 038
+ DMA_REGISTER ChannelInterruptAcknowledge; // offset 040
+ DMA_REGISTER LocalInterruptAcknowledge; // offset 048
+ DMA_REGISTER EisaInterruptAcknowledge; // offset 050
+ DMA_REGISTER TimerInterruptAcknowledge; // offset 058
+ DMA_REGISTER IpInterruptAcknowledge; // offset 060
+ DMA_REGISTER Reserved1; // offset 068
+ DMA_REGISTER WhoAmI; // offset 070
+ DMA_REGISTER NmiSource; // offset 078
+ DMA_REGISTER RemoteSpeed[15]; // offset 080
+ DMA_REGISTER InterruptEnable; // offset 0f8
+ DMA_CHANNEL Channel[4]; // offset 100
+ DMA_REGISTER ArbitrationControl; // offset 180
+ DMA_REGISTER Errortype; // offset 188
+ DMA_REGISTER RefreshRate; // offset 190
+ DMA_REGISTER RefreshCounter; // offset 198
+ DMA_REGISTER SystemSecurity; // offset 1a0
+ DMA_REGISTER InterruptInterval; // offset 1a8
+ DMA_REGISTER IntervalTimer; // offset 1b0
+ DMA_REGISTER IpInterruptRequest; // offset 1b8
+ DMA_REGISTER InterruptDiagnostic; // offset 1c0
+ DMA_LARGE_REGISTER EccDiagnostic; // offset 1c8
+ DMA_REGISTER MemoryConfig[4]; // offset 1d0
+ DMA_REGISTER Reserved2;
+ DMA_REGISTER Reserved3;
+ DMA_LARGE_REGISTER IoCacheBuffer[64]; // offset 200
+ DMA_REGISTER IoCachePhysicalTag[8]; // offset 400
+ DMA_REGISTER IoCacheLogicalTag[8]; // offset 440
+ DMA_REGISTER IoCacheLowByteMask[8]; // offset 480
+ DMA_REGISTER IoCacheHighByteMask[8]; // offset ??? wrong?
+
+ //
+ // M001,M002,H001
+ // new registers of STORM-chipset
+ //
+
+ DMA_REGISTER ProcessorBootModeControl; // offset 500
+ DMA_REGISTER ClockCounter; // offset 508
+ DMA_REGISTER MemoryTimingControl; // offset 510
+ DMA_REGISTER PCIConfigurationAddress; // offset 518
+ DMA_REGISTER PCIConfigurationData; // offset 520
+ DMA_REGISTER PCISpecialCycle; // offset 528
+ DMA_REGISTER PCIInterruptEnable; // offset 530
+ DMA_REGISTER PCIInterruptStatus; // offset 538
+ DMA_REGISTER CopyTagConfiguration; // offset 540
+ DMA_REGISTER CopyTagAddress; // offset 548
+ DMA_REGISTER CopyTagData; // offset 550
+ DMA_REGISTER ASIC2Revision; // offset 558
+ DMA_REGISTER ASIC3Revision; // offset 560
+ DMA_REGISTER Reserved4; // offset 568
+ ULONG OptionalRemoteSpeed1; // offset 570
+ ULONG OptionalRemoteSpeed2; // offset 574
+ ULONG OptionalRemoteSpeed3; // offset 578
+ ULONG OptionalRemoteSpeed4; // offset 57c
+ DMA_REGISTER LocalInterruptAcknowledge2; // offset 580
+ DMA_REGISTER OptionalIoConfiguration1; // offset 588
+ DMA_REGISTER OptionalIoConfiguration2; // offset 590
+ DMA_REGISTER OptionalIoConfiguration3; // offset 598
+ DMA_REGISTER OptionalIoConfiguration4; // offset 5a0
+ DMA_SHORT_REGISTER BuzzerCount; // offset 5a8
+ DMA_CHAR_REGISTER BuzzerControl; // offset 5ac
+ DMA_SHORT_REGISTER LEDCount; // offset 5b0
+ DMA_CHAR_REGISTER LEDControl; // offset 5b4
+ DMA_SHORT_REGISTER NECIoPort; // offset 5b8
+ ULONG TyphoonErrorStatus; // offset 5bc
+ DMA_REGISTER AddressConversionRegion; // offset 5c0
+ DMA_REGISTER AddressConversionMask; // offset 5c8
+ DMA_REGISTER Reserved12; // offset 5d0
+ DMA_REGISTER Reserved13; // offset 5d8
+ DMA_REGISTER Reserved14; // offset 5e0
+ DMA_REGISTER Reserved15; // offset 5e8
+ DMA_REGISTER Reserved16; // offset 5f0
+ DMA_REGISTER Reserved17; // offset 5f8
+ USHORT PCIVenderID; // offset 600
+ USHORT PCIDeviceID; // offset 602
+ USHORT PCICommand; // offset 604
+ USHORT PCIStatus; // offset 606
+ UCHAR PCIRevisionID; // offset 608
+ UCHAR PCIProgIf; // offset 609
+ UCHAR PCISubClass; // offset 60a
+ UCHAR PCIBaseClass; // offset 60b
+ UCHAR PCICacheLineSize; // offset 60c
+ UCHAR PCILatencyTimer; // offset 60d
+ UCHAR PCIHeaderType; // offset 60e
+ UCHAR PCIBIST; // offset 60f
+ DMA_REGISTER Reserved18; // offset 610
+ DMA_REGISTER Reserved19; // offset 618
+ DMA_REGISTER Reserved20; // offset 620
+ DMA_REGISTER Reserved21; // offset 628
+ ULONG PCIROMBaseAddress; // offset 630
+ ULONG Reserved22[2]; // offset 634
+ UCHAR PCIInterruptLine; // offset 63c
+ UCHAR PCIInterruptPin; // offset 63d
+ UCHAR PCIMinimumGrant; // offset 63e
+ UCHAR PCIMaximumLatency; // offset 63f
+ PCI_ADDRESS_MASK PCIFastBackToBack[2]; // offset 640
+ PCI_ADDRESS_MASK PCIBurst[2]; // offset 650
+ PCI_ADDRESS_MASK PCIMemory; // offset 660
+ ULONG PCIMasterRetryTimer; // offset 668
+} DMA_REGISTERS, *PDMA_REGISTERS;
+
+//
+// Configuration Register values.
+//
+
+#define LOAD_CLEAN_EXCLUSIVE 0x20
+#define DISABLE_EISA_MEMORY 0x10
+#define ENABLE_PROCESSOR_B 0x08
+#define MAP_PROM 0x04
+
+//
+// Interrupt Enable bits.
+//
+#define ENABLE_CHANNEL_INTERRUPTS (1 << 0)
+#define ENABLE_DEVICE_INTERRUPTS (1 << 1)
+#define ENABLE_EISA_INTERRUPTS (1 << 2)
+#define ENABLE_TIMER_INTERRUPTS (1 << 3)
+#define ENABLE_IP_INTERRUPTS (1 << 4)
+
+//
+// Eisa Interupt Acknowledge Register values.
+//
+
+#define EISA_NMI_VECTOR 0x8000
+
+//
+// DMA_NMI_SRC register bit definitions.
+//
+
+#define NMI_SRC_MEMORY_ERROR 1
+#define NMI_SRC_R4000_ADDRESS_ERROR 2
+#define NMI_SRC_IO_CACHE_ERROR 4
+#define NMI_SRC_ADR_NMI 8
+
+//
+// Define DMA channel mode register structure.
+//
+
+typedef struct _DMA_CHANNEL_MODE {
+ ULONG AccessTime : 3;
+ ULONG TransferWidth : 2;
+ ULONG InterruptEnable : 1;
+ ULONG BurstMode : 1;
+ ULONG Reserved1 : 25;
+} DMA_CHANNEL_MODE, *PDMA_CHANNEL_MODE;
+
+//
+// Define access time values.
+//
+
+#define ACCESS_40NS 0x0 // 40ns access time
+#define ACCESS_80NS 0x1 // 80ns access time
+#define ACCESS_120NS 0x2 // 120ns access time
+#define ACCESS_160NS 0x3 // 160ns access time
+#define ACCESS_200NS 0x4 // 200ns access time
+#define ACCESS_240NS 0x5 // 240ns access time
+#define ACCESS_280NS 0x6 // 280ns access time
+#define ACCESS_320NS 0x7 // 320ns access time
+
+//
+// Define transfer width values.
+//
+
+#define WIDTH_8BITS 0x1 // 8-bit transfer width
+#define WIDTH_16BITS 0x2 // 16-bit transfer width
+#define WIDTH_32BITS 0x3 // 32-bit transfer width
+
+//
+// M001
+// Define DMA channel enable register structure.
+//
+
+typedef struct _DMA_CHANNEL_ENABLE {
+ ULONG ChannelEnable : 1;
+ ULONG TransferDirection : 1;
+ ULONG Reserved1 : 6;
+ ULONG TerminalCount : 1;
+ ULONG MemoryError : 1;
+// ULONG TranslationError : 1;
+// ULONG Reserved2 : 21;
+ ULONG ParityError : 1;
+ ULONG MasterAbort : 1;
+ ULONG Reserved2 : 20;
+} DMA_CHANNEL_ENABLE, *PDMA_CHANNEL_ENABLE;
+
+//
+// M001,M002
+// define RTC structure.
+//
+
+typedef struct _RTC_REGISTERS {
+ UCHAR Data;
+ UCHAR Index;
+} RTC_REGISTERS, *PRTC_REGISTERS;
+
+//
+// Define transfer direction values.
+//
+
+#define DMA_READ_OP 0x0 // read from device
+#define DMA_WRITE_OP 0x1 // write to device
+
+//
+// Define translation table entry structure.
+//
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ ULONG PageFrame;
+ ULONG Fill;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Error Type Register values
+//
+
+#define SONIC_ADDRESS_ERROR 4
+#define SONIC_MEMORY_ERROR 0x40
+#define EISA_ADDRESS_ERROR 1
+#define EISA_MEMORY_ERROR 2
+
+//
+// Address Mask definitions.
+//
+
+#define LFAR_ADDRESS_MASK 0xfffff000
+#define RFAR_ADDRESS_MASK 0x00ffffc0
+#define MFAR_ADDRESS_MASK 0x1ffffff0
+
+//
+// ECC Register Definitions.
+//
+
+#define ECC_SINGLE_BIT_DP0 0x02000000
+#define ECC_SINGLE_BIT_DP1 0x20000000
+#define ECC_SINGLE_BIT ( ECC_SINGLE_BIT_DP0 | ECC_SINGLE_BIT_DP1 )
+#define ECC_DOUBLE_BIT_DP0 0x04000000
+#define ECC_DOUBLE_BIT_DP1 0x40000000
+#define ECC_DOUBLE_BIT ( ECC_DOUBLE_BIT_DP0 | ECC_DOUBLE_BIT_DP1 )
+#define ECC_MULTIPLE_BIT_DP0 0x08000000
+#define ECC_MULTIPLE_BIT_DP1 0x80000000
+
+#define ECC_FORCE_DP0 0x010000
+#define ECC_FORCE_DP1 0x100000
+#define ECC_DISABLE_SINGLE_DP0 0x020000
+#define ECC_DISABLE_SINGLE_DP1 0x200000
+#define ECC_ENABLE_DP0 0x040000
+#define ECC_ENABLE_DP1 0x400000
+
+//
+// LED/DIAG Register Definitions.
+//
+
+#define DIAG_NMI_SWITCH 2
+
+//
+// Common error bit definitions
+//
+
+#define SINGLE_ERROR 1
+#define MULTIPLE_ERROR 2
+#define RFAR_CACHE_FLUSH 4
+
+//
+// M001
+// Define NMI Status/Control register structure.
+//
+
+typedef struct _BUZZER_CONTROL {
+ UCHAR SpeakerGate : 1;
+ UCHAR SpeakerData : 1;
+ UCHAR Reserved1 : 3;
+ UCHAR SpeakerTimer : 1;
+ UCHAR Reserved2 : 2;
+}BUZZER_CONTROL, *PBUZZER_CONTROL;
+
+//
+// H000
+// Define PCI Interrupt Status register structure.
+//
+
+typedef struct _STORM_PCI_INTRRUPT_STATUS{
+ ULONG IntD: 1;
+ ULONG IntC: 1;
+ ULONG IntB: 1;
+ ULONG IntA: 1;
+ ULONG Perr: 1;
+ ULONG Serr: 1;
+ ULONG RetryOverflow: 1;
+ ULONG MasterAbort: 1;
+ ULONG TargetAbort: 1;
+ ULONG Reserved: 23;
+} STORM_PCI_INTRRUPT_STATUS, *PSTORM_PCI_INTRRUPT_STATUS;
+
+//
+// H002
+// PCI Interrupt Enable bits.
+//
+
+#define ENABLE_TARGET_ABORT_INTERRUPTS (1 << 8)
+#define ENABLE_MASTER_ABORT_INTERRUPTS (1 << 7)
+#define ENABLE_RETRY_OVERFLOW_EISA_INTERRUPTS (1 << 6)
+#define ENABLE_SERR_INTERRUPTS (1 << 5)
+#define ENABLE_PERR_INTERRUPTS (1 << 4)
+
+//
+// H003
+// Define MRC control register structure.
+//
+
+typedef volatile struct _MRC_REGISTERS {
+ UCHAR Reserved1[256]; // offset 000
+ UCHAR Interrupt; // offset 100
+ UCHAR Reserved2[7]; // offset 107
+ UCHAR Mode; // offset 108
+ UCHAR Reserved3[39]; // offset 109
+ UCHAR SoftwarePowerOff; // offset 130
+ UCHAR Reserved4[15]; // offset 131
+ UCHAR LEDBitControl; // offset 140
+ UCHAR Reserved5[3]; // offset 141
+ UCHAR SegmentLEDControl[4]; // offset 144
+ UCHAR Reserved6[155]; // offset 145
+ UCHAR TempEnable; // offset 1e0
+ UCHAR Reserved7[31]; // offset 145
+ UCHAR TempSensor; // offset 200
+ UCHAR Reserved8[3583]; // offset 201
+} MRC_REGISTERS, *PMRC_REGISTERS;
+
+
+#endif // _R94ADMA_
diff --git a/private/ntos/nthals/halr96b/mips/r94ainfo.c b/private/ntos/nthals/halr96b/mips/r94ainfo.c
new file mode 100644
index 000000000..a2c59341b
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94ainfo.c
@@ -0,0 +1,99 @@
+// #pragma comment(exestr, "@(#) r94ainfo.c 1.1 95/09/28 15:48:57 nec")
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History
+
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-ixinfo.h to 1050-halx86-r98info.h
+
+--*/
+
+
+#include "halp.h"
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
diff --git a/private/ntos/nthals/halr96b/mips/r94aint.h b/private/ntos/nthals/halr96b/mips/r94aint.h
new file mode 100644
index 000000000..6904b9a85
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94aint.h
@@ -0,0 +1,35 @@
+// #pragma comment(exestr, "@(#) r94aint.h 1.1 95/09/28 15:49:28 nec")
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ duoint.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the interrupt source and enable registers on the DUO system.
+
+Author:
+
+ Lluis Abello (lluis) 20-Apr-1993
+
+Revision History:
+
+--*/
+
+#ifndef _DUOINT_
+#define _DUOINT_
+
+//
+// Define Interrupt register structure.
+//
+
+typedef struct _INTERRUPT_REGISTERS {
+ USHORT Fill;
+ USHORT Enable;
+} INTERRUPT_REGISTERS, *PINTERRUPT_REGISTERS;
+
+#endif // _DUOINT_
diff --git a/private/ntos/nthals/halr96b/mips/r94aio.s b/private/ntos/nthals/halr96b/mips/r94aio.s
new file mode 100644
index 000000000..fed2171e2
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94aio.s
@@ -0,0 +1,149 @@
+// .ident "@(#) r94aio.s 1.1 95/09/28 18:36:07 nec"
+//++
+//
+// Copyright (c) 1994 KOBE NEC Software Corporation
+//
+// Module Name:
+//
+// r94aio.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to read
+// and write the 64-bit register on a MIPS R4000 R94A system.
+//
+// Author:
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// H000 Fri Oct 7 19:57:09 JST 1994 kbnes!kisimoto
+// new READ_REGISTER_DWORD
+// new WRITE_REGISTER_DWORD
+//
+//--
+
+#if defined(_R94A_)
+
+#include "halmips.h"
+
+//++
+//
+// VOID
+// READ_REGISTER_DWORD (
+// IN PLARGE_INTEGER RegisterAddress,
+// IN PVOID Variable
+// )
+//
+// Routine Description:
+//
+// 64-bit I/O space register read function.
+//
+// Arguments:
+//
+// RegisterAddress (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Variable (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Return Value:
+//
+// None.
+//
+// Destination and Source must be 8-byte aligned.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_DWORD)
+
+ ldc1 f0,0(a0) // move 8-byte block
+ sdc1 f0,0(a1) //
+
+ sync // synchronize read
+
+ j ra // return
+
+ .end READ_REGISTER_DWORD
+
+
+//++
+//
+// VOID
+// WRITE_REGISTER_DWORD (
+// IN PLARGE_INTEGER RegisterAddress,
+// IN PVOID Variable
+// )
+//
+// Routine Description:
+//
+// 64-bit I/O space register write function.
+//
+// Arguments:
+//
+// RegisterAddress (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Variable (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Return Value:
+//
+// None.
+//
+// Destination and Source must be 8-byte aligned.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_DWORD)
+
+ ldc1 f0,0(a1) // move 8-byte block
+ sdc1 f0,0(a0) //
+
+ sync // synchronize write
+
+ j ra // return
+
+ .end WRITE_REGISTER_DWORD
+
+
+//++
+//
+// VOID
+// HalpGetStatusRegister (
+// IN PULONG Variable
+// )
+//
+// Routine Description:
+//
+// This function returns value which is status register of R4400.
+//
+// Arguments:
+//
+// Variable (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpGetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,psr // get current processor status
+ nop // 1 cycle hazzard
+ sw t0,0(a0) // save integer registers a0 - a3
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetStatusRegister
+
+#endif
diff --git a/private/ntos/nthals/halr96b/mips/r94anmi.s b/private/ntos/nthals/halr96b/mips/r94anmi.s
new file mode 100644
index 000000000..b0f87aabb
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/r94anmi.s
@@ -0,0 +1,621 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) r94anmi.s 1.2 95/10/17 01:19:11" ) */
+//
+// TITLE("R94A NMI routine")
+//++
+//
+// Copyright (c) 1995 NEC Corporation
+//
+// Module Name:
+//
+// r94anmi.s
+//
+// Abstract:
+//
+// This routine support for dump switch.
+//
+// Author:
+//
+// Akitoshi Kuriyama (NEC Software Kobe,Inc)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// R4400 based only.
+//
+// Revision History:
+//
+// kuriyama@oa2.kbnes.nec.co.jp Sun Oct 15 20:11:38 JST 1995
+// - new code for J94D (!_MRCDUMP_ _MRCPOWER_ compile option need)
+//
+//--
+#include "halmips.h"
+
+ SBTTL("NMI dispatch routine")
+//++
+//
+// VOID
+// HalpNMIDispatch (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function was called by firmware when NMI occuerd.
+//
+// Arguments:
+//
+// none.
+//
+// Return Value:
+//
+// none.
+//
+//--
+
+ LEAF_ENTRY(HalpNMIDispatch)
+
+ .set noreorder
+ .set noat
+
+//
+// Save temporary Registers for use.
+// save area shoud have for every processros.
+//
+
+ li k0,0xffffc070 // get processor number.
+ lw k0,(k0) //
+ bne k0,zero,10f //
+ nop // fill
+
+ la k1,HalpNMISave0 // set save address.
+ j 20f //
+ nop // fill
+
+10:
+ la k1,HalpNMISave1 // set save address.
+ nop // 1 cycle hazzerd
+
+20:
+ sw AT,0x0(k1) // register save.
+ sw v0,0x4(k1) //
+ sw v1,0x8(k1) //
+ sw a0,0xc(k1) //
+ sw a1,0x10(k1) //
+ sw a2,0x14(k1) //
+ sw a3,0x18(k1) //
+ sw t0,0x1c(k1) //
+ sw t1,0x20(k1) //
+ sw t2,0x24(k1) //
+ sw t3,0x28(k1) //
+ sw t4,0x2c(k1) //
+ sw t5,0x30(k1) //
+ sw t6,0x34(k1) //
+ sw t7,0x38(k1) //
+ sw t8,0x3c(k1) //
+ sw t9,0x40(k1) //
+ sw gp,0x44(k1) //
+ sw sp,0x48(k1) //
+ sw s8,0x4c(k1) //
+ sw ra,0x50(k1) //
+ mfc0 k0,psr //
+ nop //
+ nop //
+ sw k0,0x54(k1) //
+ nop //
+ mfc0 k0,cause //
+ nop //
+ nop //
+ sw k0,0x58(k1) //
+ nop //
+ mfc0 k0,epc //
+ nop //
+ nop //
+ sw k0,0x5c(k1) //
+ nop //
+ mfc0 k0,errorepc //
+ nop //
+ nop //
+ sw k0,0x60(k1) //
+ nop //
+ mfc0 k0,cacheerr //
+ nop //
+ nop //
+ sw k0,0x64(k1) //
+
+ sdc1 f0,0x68(k1) //
+
+//
+// Set Dump Switch Status register to tlb fixed entry
+//
+
+ li t0,4 // set index 4(hurricane register)
+ li t1,0x80012 << 6 // set MRC register
+ li t2,0x8000e << 6 // set Self-Test address
+
+ mfc0 t3,index // save tlb registers
+ mfc0 t4,entryhi //
+ mfc0 t5,entrylo0 //
+ mfc0 t6,entrylo1 //
+ mfc0 t7,pagemask //
+ mtc0 t0,index //
+ nop
+ nop
+ nop
+
+ tlbr // read index 4 tlb
+ nop
+ nop
+ nop
+ nop
+
+ mfc0 t8,entrylo0 // Get entrylo0
+ mfc0 t9,entrylo1 // Get entrylo1
+ nop
+ nop
+ nop
+ or t1,t8,t1 // set MRC address
+ or t2,t8,t2 // set Self-test address
+ nop
+
+ mtc0 t1,entrylo0 // set MRC to tlb 4 0
+ mtc0 t2,entrylo1 // set Self-test to tlb 4 1
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+//
+// read dump status
+//
+
+#if defined(_MRCDUMP_)
+
+ li t1,0xffffc108 // load MRC Mode value
+
+#else // SELFTEST DUMP
+
+ li t1,0xffffd000 // load Self-Test value
+
+ li k0,0x1b // set dash
+ sb k0,(t1) // display led
+ sync
+
+#endif // _MRCDUMP_
+
+ lb k0,(t1) // load Dump switch status.
+ nop //
+ lb k0,(t1) // wait
+ nop //
+
+//
+// Check dump status
+//
+
+ li t1,2 // check for dump switch
+ and k0,k0,t1 //
+
+#if defined(_MRCDUMP_)
+ beq k0,zero,30f // if 0 dump swith was not pressed
+#else // _MRCDUMP_
+ bne k0,zero,30f // if 0 dump swith was pressed
+#endif // _MRCDUMP_
+ nop //
+
+#if !defined(_MRCDUMP_)
+ li t1,0xffffd000 // set dump switch status address
+ li t2,0x1b // display LED dash
+ sb t2,(t1) //
+ sync //
+#endif // not _MRCDUMP_
+
+//
+// enable powoff NMI
+//
+
+#if defined(_MRCPOWER_)
+ li t1,0xffffc108 //
+ li t0,0x82 //
+ nop //
+ sb t0,(t1) //
+ nop //
+ li t0,0x80 //
+ nop //
+ sb t0,(t1) //
+ nop //
+ li t0,0x02 //
+ nop //
+ sb t0,(t1) //
+ nop //
+#endif // _MRCPOWER_
+
+//
+// restore tlb 4 entry
+//
+
+ mtc0 t8,entrylo0 // restore tlb 4 0
+ mtc0 t9,entrylo1 // restore tlb 4 1
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+//
+// restore tlb registers
+//
+ mtc0 t3,index //
+ mtc0 t4,entryhi //
+ mtc0 t5,entrylo0 //
+ mtc0 t6,entrylo1 //
+ mtc0 t7,pagemask //
+
+#if !defined(_MRCDUMP_)
+ la k0,0xffffc5b8 // get NEC I/O port value
+ lb t0,(k0) //
+ nop // 1 cycle hazzerd
+ li t1,0xfd // clear dump enable bit
+ and t0,t0,t1
+ sb t0,(k0) // set NEC I/O port value
+#endif // not _MRCDUMP_
+
+//
+// set NMI flag 1
+//
+
+ la t2,HalpNMIFlag // set NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+//
+// set dump flag 1
+//
+
+ la t2,HalpDumpNMIFlag // set Dump NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+//
+// clear psr BEV bit
+//
+
+ mfc0 t0,psr // get psr
+ li t2,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and t0,t0,t2 //
+ nop //
+ mtc0 t0,psr // set psr
+
+ lw t0,0x1c(k1) // restore temporary registers
+ lw t1,0x20(k1) //
+ lw t2,0x24(k1) //
+ lw t3,0x28(k1) //
+ lw t4,0x2c(k1) //
+ lw t5,0x30(k1) //
+ lw t6,0x34(k1) //
+ lw t7,0x38(k1) //
+ lw t8,0x3c(k1) //
+ lw t9,0x40(k1) //
+ lw AT,0x0(k1) //
+
+ eret // return to error epc
+ nop // errata
+ nop //
+ nop //
+ eret //
+ nop //
+
+30:
+
+//
+// No Dump Switch.
+//
+// Check Power Switch
+
+#if defined(_MRCPOWER_)
+ li t1,0xffffc108
+ nop
+ li t0,0x02
+ nop
+ sb t0,(t1)
+ nop
+
+#endif // _MRCPOWER_
+
+ mtc0 t8,entrylo0 // restore tlb 4
+ mtc0 t9,entrylo1 // restore tlb 4
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+ mtc0 t3,index // restore tlb registers
+ mtc0 t4,entryhi //
+ mtc0 t5,entrylo0 //
+ mtc0 t6,entrylo1 //
+ mtc0 t7,pagemask //
+
+
+//
+// set NMI flag 1
+//
+ la t2,HalpNMIFlag // set NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+// S003 +++
+ li t1,0xffffc078 // check NMI source
+ lw t0,(t1) // check NMI source
+ nop //
+ beq t0,zero,40f //
+ nop //
+ li t1,0xffffc020
+ nop
+ ldc1 f0,(t1) // clear processor invalid
+ nop
+ sdc1 f0,0x70(k1) // save processor invalid
+40:
+// S003 ---
+
+ mfc0 t0,psr // get psr
+ li t2,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and t0,t0,t2 //
+ nop //
+ mtc0 t0,psr // set psr
+
+ lw t0,0x1c(k1) // restore temporary registers
+ lw t1,0x20(k1) //
+ lw t2,0x24(k1) //
+ lw t3,0x28(k1) //
+ lw t4,0x2c(k1) //
+ lw t5,0x30(k1) //
+ lw t6,0x34(k1) //
+ lw t7,0x38(k1) //
+ lw t8,0x3c(k1) //
+ lw t9,0x40(k1) //
+ lw AT,0x0(k1) //
+ ldc1 f0,0x68(k1) //
+ nop
+
+ eret // return to errorepc
+ nop // errata
+ nop //
+ nop //
+ eret //
+ nop //
+
+// L001 ---
+
+ .set at
+ .set reorder
+
+ .end HalpNMIDispatch
+
+// Start M008
+ SBTTL("Software Power Off")
+//++
+//
+// VOID
+// HalpPowOffNMIDispatch (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function was called by firmware when NMI occuerd.
+//
+// Arguments:
+//
+// none.
+//
+// Return Value:
+//
+// none.
+//
+//--
+
+ LEAF_ENTRY(HalpPowOffNMIDispatch)
+
+ .set noat
+ .set noreorder
+
+//
+// Save temporary Registers for use.
+// save area shoud have for every processros.
+//
+
+ li k0,0xffffc070 // get processor number.
+ lw k0,(k0) //
+ bne k0,zero,60f //
+ nop // fill
+
+ la k1,HalpNMISave0 // set save address.
+ j 70f //
+ nop // fill
+
+60:
+ la k1,HalpNMISave1 // set save address.
+ nop // 1 cycle hazzerd
+
+70:
+ sw t0,0(k1) // save temporary registers
+ sw t1,4(k1) //
+ sw t2,8(k1) //
+ sw t3,12(k1) //
+ sw t4,16(k1) //
+ sw t5,20(k1) //
+ sw t6,24(k1) //
+ sw t7,28(k1) //
+ sw AT,32(k1) //
+
+//
+// Set Power Switch Status register to tlb fixed entry
+//
+ li t0,4 // set index 4(hurricane register)
+
+ li t1,0x80012 << 6 // set MRC register
+
+ mfc0 t3,index // save tlb registers
+ mfc0 t4,entryhi //
+ mfc0 t5,entrylo0 //
+ mfc0 t6,entrylo1 //
+ mfc0 t7,pagemask //
+ mtc0 t0,index //
+ nop
+ nop
+ nop
+
+ tlbr // read index 4 tlb
+ nop
+ nop
+ nop
+ nop
+
+ mfc0 t2,entrylo0 // set Self-test address to tlb
+ nop
+ nop
+ nop
+ or t1,t2,t1
+ nop
+
+ mtc0 t1,entrylo0 // set Self-Test to tlb 4
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+ li t1,0xffffc100 // load MRC Int value
+
+ nop
+ lb k0,(t1) // load Interrupt status.
+ nop
+ lb k0,(t1) // wait
+ nop
+
+ li t0,0x01 // set clear value
+ sb t0,(t1) // clear OffSw bit
+
+ li t1,0x4 // check for OffSw switch
+ nop //
+ and k0,k0,t1 //
+
+ beq k0,zero,80f // 0 means Power switch was not pressed
+ nop //
+
+ li t1,0xffffc130 // load MRC Software PowerOff Register
+
+ nop
+
+ lb t0,0x1 // set PowerOff Value
+
+90:
+ sb t0,(t1) // write PowerOff bit
+ beq zero,zero,90b
+ nop
+
+ eret
+ nop
+ nop
+ nop
+ eret
+ nop
+80:
+
+//
+// No Power Switch.
+//
+
+ mtc0 t2,entrylo0 // restore tlb 4
+ nop //
+ nop //
+ nop //
+ nop //
+
+ tlbwi // write to tlb entry
+ nop //
+ nop //
+ nop //
+ nop //
+
+ mtc0 t3,index // restore tlb registers
+ mtc0 t4,entryhi //
+ mtc0 t5,entrylo0 //
+ mtc0 t6,entrylo1 //
+ mtc0 t7,pagemask //
+
+
+ la t2,HalpNMIFlag // set NMI flag address
+ li t3,0xa0000000 // set KSEG1_BASE
+ or t2,t2,t3 //
+ li t3,1 //
+ sw t3,(t2) // set NMI flag 1
+
+ lw t0,0xffffc078 // check NMI source
+ nop //
+ beq t0,zero,45f //
+ nop //
+ lw t0,0xffffc020 // clear processor invalid
+45:
+
+ mfc0 t0,psr // get psr
+ li t2,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and t0,t0,t2 //
+ nop //
+ mtc0 t0,psr // set psr
+
+ lw t0,0(k1) // restore temporary registers
+ lw t1,4(k1) //
+ lw t2,8(k1) //
+ lw t3,12(k1) //
+ lw t4,16(k1) //
+ lw t5,20(k1) //
+ lw t6,24(k1) //
+ lw t7,28(k1) //
+ lw AT,32(k1) //
+
+ eret // return to errorepc
+ nop // errata
+ nop //
+ nop //
+ eret //
+ nop //
+
+ .set reorder
+ .set at
+
+ .end HalpPowOffNMIDispatch
+// End M008
diff --git a/private/ntos/nthals/halr96b/mips/rgb525.h b/private/ntos/nthals/halr96b/mips/rgb525.h
new file mode 100644
index 000000000..a4e53e09e
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/rgb525.h
@@ -0,0 +1,468 @@
+// #pragma comment(exestr, "@(#) rgb525.h 1.2 95/09/28 18:38:14 nec")
+/************************************************************************
+ * *
+ * Copyright (c) 1994 3Dlabs Inc. Ltd. *
+ * All rights reserved *
+ * *
+ * This software and its associated documentation contains proprietary, *
+ * confidential and trade secret information of 3Dlabs Inc. Ltd. and *
+ * except as provided by written agreement with 3Dlabs Inc. Ltd. *
+ * *
+ * a) no part may be disclosed, distributed, reproduced, transmitted, *
+ * transcribed, stored in a retrieval system, adapted or translated *
+ * in any form or by any means electronic, mechanical, magnetic, *
+ * optical, chemical, manual or otherwise, *
+ * *
+ * and *
+ * *
+ * b) the recipient is not entitled to discover through reverse *
+ * engineering or reverse compiling or other such techniques or *
+ * processes the trade secrets contained therein or in the *
+ * documentation. *
+ * *
+ ************************************************************************/
+
+#ifndef __RGB525_H__
+#define __RGB525_H__
+
+/************************************************************************/
+/* DIRECT ACCESS REGISTERS */
+/************************************************************************/
+
+/* direct registers on 64-bit boundaries */
+
+#define __RGB525_PalAddrWrite 0x00
+#define __RGB525_PaletteData 0x08
+#define __RGB525_PixelMask 0x10
+#define __RGB525_PalAddrRead 0x18
+#define __RGB525_IndexLow 0x20
+#define __RGB525_IndexHigh 0x28
+#define __RGB525_IndexedData 0x30
+#define __RGB525_IndexControl 0x38
+
+/************************************************************************/
+/* INDEXED REGISTERS - MISCELLANEOUS CONTROL */
+/************************************************************************/
+
+#define __RGB525_MiscControlOne 0x0070
+#define __RGB525_MiscControlTwo 0x0071
+#define __RGB525_MiscControlThree 0x0072
+#define __RGB525_MiscClockControl 0x0002
+#define __RGB525_SyncControl 0x0003
+#define __RGB525_HSyncControl 0x0004
+#define __RGB525_PowerManagement 0x0005
+#define __RGB525_DACOperation 0x0006
+#define __RGB525_PaletteControl 0x0007
+
+/* MiscControlOne */
+
+#define RGB525_MISR_CNTL_OFF (0 << 7)
+#define RGB525_MISR_CNTL_ON (1 << 7)
+#define RGB525_VMSK_CNTL_OFF (0 << 6)
+#define RGB525_VMSK_CNTL_ON (1 << 6)
+#define RGB525_PADR_RFMT_READ_ADDR (0 << 5)
+#define RGB525_PADR_RFMT_PAL_STATE (1 << 5)
+#define RGB525_SENS_DSAB_ENABLE (0 << 4)
+#define RGB525_SENS_DSAB_DISABLE (1 << 4)
+#define RGB525_SENS_SEL_BIT3 (0 << 3)
+#define RGB525_SENS_SEL_BIT7 (1 << 3)
+#define RGB525_VRAM_SIZE_32 (0 << 0)
+#define RGB525_VRAM_SIZE_64 (1 << 0)
+
+/* MiscControlTwo */
+
+#define RGB525_PCLK_SEL_LCLK (0 << 6)
+#define RGB525_PCLK_SEL_PLL (1 << 6)
+#define RGB525_PCLK_SEL_EXT (2 << 6)
+#define RGB525_INTL_MODE_DISABLE (0 << 5)
+#define RGB525_INTL_MODE_ENABLE (1 << 5)
+#define RGB525_BLANK_CNTL_NORMAL (0 << 4)
+#define RGB525_BLANK_CNTL_BLANKED (1 << 4)
+#define RGB525_COL_RES_6_BIT (0 << 2)
+#define RGB525_COL_RES_8_BIT (1 << 2)
+#define RGB525_PORT_SEL_VGA (0 << 0)
+#define RGB525_PORT_SEL_VRAM (1 << 0)
+
+/* MiscControlThree */
+
+#define RGB525_SWAP_RB_DISABLE (0 << 7)
+#define RGB525_SWAP_RB_ENABLE (1 << 7)
+#define RGB525_SWAP_WORD_31_00_FIRST (0 << 4)
+#define RGB525_SWAP_WORD_63_32_FIRST (1 << 4)
+#define RGB525_SWAP_NIB_07_04_FIRST (0 << 2)
+#define RGB525_SWAP_NIB_03_00_FIRST (1 << 2)
+
+/* MiscClockControl */
+
+#define RGB525_DDOTCLK_ENABLE (0 << 7)
+#define RGB525_DDOTCLK_DISABLE (1 << 7)
+#define RGB525_SCLK_ENABLE (0 << 6)
+#define RGB525_SCLK_DISABLE (1 << 6)
+#define RGB525_B24P_DDOT_DIV_PLL (0 << 5)
+#define RGB525_B24P_DDOT_SCLK (1 << 5)
+#define RGB525_DDOT_PLL_DIV_1 (0 << 1)
+#define RGB525_DDOT_PLL_DIV_2 (1 << 1)
+#define RGB525_DDOT_PLL_DIV_4 (2 << 1)
+#define RGB525_DDOT_PLL_DIV_8 (3 << 1)
+#define RGB525_DDOT_PLL_DIV_16 (4 << 1)
+#define RGB525_PLL_DISABLE (0 << 0)
+#define RGB525_PLL_ENABLE (1 << 0)
+
+/* SyncControl */
+
+#define RGB525_DLY_CNTL_ADD (0 << 7)
+#define RGB525_DLY_SYNC_NOADD (1 << 7)
+#define RGB525_CSYN_INVT_DISABLE (0 << 6)
+#define RGB525_CSYN_INVT_ENABLE (1 << 6)
+#define RGB525_VSYN_INVT_DISABLE (0 << 5)
+#define RGB525_VSYN_INVT_ENABLE (1 << 5)
+#define RGB525_HSYN_INVT_DISABLE (0 << 4)
+#define RGB525_HSYN_INVT_ENABLE (1 << 4)
+#define RGB525_VSYN_CNTL_NORMAL (0 << 2)
+#define RGB525_VSYN_CNTL_HIGH (1 << 2)
+#define RGB525_VSYN_CNTL_LOW (2 << 2)
+#define RGB525_VSYN_CNTL_DISABLE (3 << 2)
+#define RGB525_HSYN_CNTL_NORMAL (0 << 0)
+#define RGB525_HSYN_CNTL_HIGH (1 << 0)
+#define RGB525_HSYN_CNTL_LOW (2 << 0)
+#define RGB525_HSYN_CNTL_DISABLE (3 << 0)
+
+/* HSyncControl */
+
+#define RGB525_HSYN_POS(n) ((n) & 0xF)
+
+/* PowerManagement */
+
+#define RGB525_SCLK_PWR_NORMAL (0 << 4)
+#define RGB525_SCLK_PWR_DISABLE (1 << 4)
+#define RGB525_DDOT_PWR_NORMAL (0 << 3)
+#define RGB525_DDOT_PWR_DISABLE (1 << 3)
+#define RGB525_SYNC_PWR_NORMAL (0 << 2)
+#define RGB525_SYNC_PWR_DISABLE (1 << 2)
+#define RGB525_ICLK_PWR_NORMAL (0 << 1)
+#define RGB525_ICLK_PWR_DISABLE (1 << 1)
+#define RGB525_DAC_PWR_NORMAL (0 << 0)
+#define RGB525_DAC_PWR_DISABLE (1 << 0)
+
+/* DACOperation */
+
+#define RGB525_SOG_DISABLE (0 << 3)
+#define RGB525_SOG_ENABLE (1 << 3)
+#define RGB525_BRB_NORMAL (0 << 2)
+#define RGB525_BRB_ALWAYS (1 << 2)
+#define RGB525_DSR_SLOW (0 << 1)
+#define RGB525_DSR_FAST (1 << 1)
+#define RGB525_DPE_DISABLE (0 << 0)
+#define RGB525_DPE_ENABLE (1 << 0)
+
+/* PaletteControl */
+
+#define RGB525_6BIT_LINEAR_ENABLE (0 << 7)
+#define RGB525_6BIT_LINEAR_DISABLE (1 << 7)
+#define RGB525_PALETTE_PARTITION(n) ((n) & 0xF)
+
+/************************************************************************/
+/* INDEXED REGISTERS - PIXEL REPRESENTATION */
+/************************************************************************/
+
+#define __RGB525_PixelFormat 0x000A
+#define __RGB525_8BitPixelControl 0x000B
+#define __RGB525_16BitPixelControl 0x000C
+#define __RGB525_24BitPixelControl 0x000D
+#define __RGB525_32BitPixelControl 0x000E
+
+/* PixelFormat */
+
+#define RGB525_PIXEL_FORMAT_4_BPP (2 << 0)
+#define RGB525_PIXEL_FORMAT_8_BPP (3 << 0)
+#define RGB525_PIXEL_FORMAT_16_BPP (4 << 0)
+#define RGB525_PIXEL_FORMAT_24_BPP (5 << 0)
+#define RGB525_PIXEL_FORMAT_32_BPP (6 << 0)
+
+/* 8BitPixelControl */
+
+#define RGB525_B8_DCOL_INDIRECT (0 << 0)
+#define RGB525_B8_DCOL_DIRECT (1 << 0)
+
+/* 16BitPixelControl */
+
+#define RGB525_B16_DCOL_INDIRECT (0 << 6)
+#define RGB525_B16_DCOL_DYNAMIC (1 << 6)
+#define RGB525_B16_DCOL_DIRECT (3 << 6)
+#define RGB525_B16_POL_FORCES_BYPASS (0 << 5)
+#define RGB525_B16_POL_FORCES_LOOKUP (1 << 5)
+#define RGB525_B16_ZIB (0 << 2)
+#define RGB525_B16_LINEAR (1 << 2)
+#define RGB525_B16_555 (0 << 1)
+#define RGB525_B16_565 (1 << 1)
+#define RGB525_B16_SPARSE (0 << 0)
+#define RGB525_B16_CONTIGUOUS (1 << 0)
+
+/* 24BitPixelControl */
+
+#define RGB525_B24_DCOL_INDIRECT (0 << 0)
+#define RGB525_B24_DCOL_DIRECT (1 << 0)
+
+/* 32BitPixelControl */
+
+#define RGB525_B32_POL_FORCES_BYPASS (0 << 2)
+#define RGB525_B32_POL_FORCES_LOOKUP (1 << 2)
+#define RGB525_B32_DCOL_INDIRECT (0 << 0)
+#define RGB525_B32_DCOL_DYNAMIC (1 << 0)
+#define RGB525_B32_DCOL_DIRECT (3 << 0)
+
+/************************************************************************/
+/* INDEXED REGISTERS - FREQUENCY CONTROL */
+/************************************************************************/
+
+#define __RGB525_PLLControlOne 0x0010
+#define __RGB525_PLLControlTwo 0x0011
+#define __RGB525_PLLRefDivCount 0x0014
+
+#define __RGB525_F0 0x0020
+#define __RGB525_F1 0x0021
+#define __RGB525_F2 0x0022
+#define __RGB525_F3 0x0023
+#define __RGB525_F4 0x0024
+#define __RGB525_F5 0x0025
+#define __RGB525_F6 0x0026
+#define __RGB525_F7 0x0027
+#define __RGB525_F8 0x0028
+#define __RGB525_F9 0x0029
+#define __RGB525_F10 0x002A
+#define __RGB525_F11 0x002B
+#define __RGB525_F12 0x002C
+#define __RGB525_F13 0x002D
+#define __RGB525_F14 0x002E
+#define __RGB525_F15 0x002F
+
+#define __RGB525_M0 0x0020
+#define __RGB525_M1 0x0022
+#define __RGB525_M2 0x0024
+#define __RGB525_M3 0x0026
+#define __RGB525_M4 0x0028
+#define __RGB525_M5 0x002A
+#define __RGB525_M6 0x002C
+#define __RGB525_M7 ox002E
+
+#define __RGB525_N0 0x0021
+#define __RGB525_N1 0x0023
+#define __RGB525_N2 0x0025
+#define __RGB525_N3 0x0027
+#define __RGB525_N4 0x0029
+#define __RGB525_N5 0x002B
+#define __RGB525_N6 0x002D
+#define __RGB525_N7 ox002F
+
+/* PLLControlOne */
+
+#define RGB525_REF_SRC_REFCLK (0 << 4)
+#define RGB525_REF_SRC_EXTCLK (1 << 4)
+#define RGB525_PLL_EXT_FS_DIRECT (0 << 0)
+#define RGB525_PLL_EXT_FS_M_N (1 << 0)
+#define RGB525_PLL_INT_FS_DIRECT (2 << 0)
+#define RGB525_PLL_INT_FS_M_N (3 << 0)
+
+/* PLLControlTwo */
+
+#define RGB525_PLL_INT_FS(n) ((n) & 0xF)
+
+/* PLLRefDivCount */
+
+#define RGB525_REF_DIV_COUNT(n) ((n) & 0x1F)
+
+#define RGB525_PLL_REFCLK_4_MHz (0x02)
+#define RGB525_PLL_REFCLK_6_MHz (0x03)
+#define RGB525_PLL_REFCLK_8_MHz (0x04)
+#define RGB525_PLL_REFCLK_10_MHz (0x05)
+#define RGB525_PLL_REFCLK_12_MHz (0x06)
+#define RGB525_PLL_REFCLK_14_MHz (0x07)
+#define RGB525_PLL_REFCLK_16_MHz (0x08)
+#define RGB525_PLL_REFCLK_18_MHz (0x09)
+#define RGB525_PLL_REFCLK_20_MHz (0x0A)
+#define RGB525_PLL_REFCLK_22_MHz (0x0B)
+#define RGB525_PLL_REFCLK_24_MHz (0x0C)
+#define RGB525_PLL_REFCLK_26_MHz (0x0D)
+#define RGB525_PLL_REFCLK_28_MHz (0x0E)
+#define RGB525_PLL_REFCLK_30_MHz (0x0F)
+#define RGB525_PLL_REFCLK_32_MHz (0x10)
+#define RGB525_PLL_REFCLK_34_MHz (0x11)
+#define RGB525_PLL_REFCLK_36_MHz (0x12)
+#define RGB525_PLL_REFCLK_38_MHz (0x13)
+#define RGB525_PLL_REFCLK_40_MHz (0x14)
+#define RGB525_PLL_REFCLK_42_MHz (0x15)
+#define RGB525_PLL_REFCLK_44_MHz (0x16)
+#define RGB525_PLL_REFCLK_46_MHz (0x17)
+#define RGB525_PLL_REFCLK_48_MHz (0x18)
+#define RGB525_PLL_REFCLK_50_MHz (0x19)
+#define RGB525_PLL_REFCLK_52_MHz (0x1A)
+#define RGB525_PLL_REFCLK_54_MHz (0x1B)
+#define RGB525_PLL_REFCLK_56_MHz (0x1C)
+#define RGB525_PLL_REFCLK_58_MHz (0x1D)
+#define RGB525_PLL_REFCLK_60_MHz (0x1E)
+#define RGB525_PLL_REFCLK_62_MHz (0x1F)
+
+/* F0-F15[7:0] */
+
+#define RGB525_DF(n) (((n) & 0x3) << 6)
+#define RGB525_VCO_DIV_COUNT(n) ((n) & 0x3F)
+
+/************************************************************************/
+/* INDEXED REGISTERS - CURSOR */
+/************************************************************************/
+
+#define __RGB525_CursorControl 0x0030
+#define __RGB525_CursorXLow 0x0031
+#define __RGB525_CursorXHigh 0x0032
+#define __RGB525_CursorYLow 0x0033
+#define __RGB525_CursorYHigh 0x0034
+#define __RGB525_CursorHotSpotX 0x0035
+#define __RGB525_CursorHotSpotY 0x0036
+#define __RGB525_CursorColor1Red 0x0040
+#define __RGB525_CursorColor1Green 0x0041
+#define __RGB525_CursorColor1Blue 0x0042
+#define __RGB525_CursorColor2Red 0x0043
+#define __RGB525_CursorColor2Green 0x0044
+#define __RGB525_CursorColor2Blue 0x0045
+#define __RGB525_CursorColor3Red 0x0046
+#define __RGB525_CursorColor3Green 0x0047
+#define __RGB525_CursorColor3Blue 0x0048
+
+/* CursorControl */
+
+#define RGB525_SMLC_PART_0 (0 << 6)
+#define RGB525_SMLC_PART_1 (1 << 6)
+#define RGB525_SMLC_PART_2 (2 << 6)
+#define RGB525_SMLC_PART_3 (3 << 6)
+#define RGB525_PIX_ORDER_RIGHT_TO_LEFT (0 << 5)
+#define RGB525_PIX_ORDER_LEFT_TO_RIGHT (1 << 5)
+#define RGB525_LOC_READ_LAST_WRITTEN (0 << 4)
+#define RGB525_LOC_READ_ACTUAL_LOCATION (1 << 4)
+#define RGB525_UPDT_CNTL_DELAYED (0 << 3)
+#define RGB525_UPDT_CNTL_IMMEDIATE (1 << 3)
+#define RGB525_CURSOR_SIZE_32 (0 << 2)
+#define RGB525_CURSOR_SIZE_64 (1 << 2)
+#define RGB525_CURSOR_MODE_OFF (0 << 0)
+#define RGB525_CURSOR_MODE_3_COLOR (1 << 0)
+#define RGB525_CURSOR_MODE_2_COLOR_HL (2 << 0)
+#define RGB525_CURSOR_MODE_2_COLOR (3 << 0)
+
+/************************************************************************/
+/* INDEXED REGISTERS - BORDER COLOR */
+/************************************************************************/
+
+#define __RGB525_BorderColorRed 0x0060
+#define __RGB525_BorderColorGreen 0x0061
+#define __RGB525_BorderColorBlue 0x0062
+
+/************************************************************************/
+/* INDEXED REGISTERS - DIAGNOSTIC SUPPORT */
+/************************************************************************/
+
+#define __RGB525_RevisionLevel 0x0000
+#define __RGB525_ProductID 0x0001
+#define __RGB525_DACSense 0x0082
+#define __RGB525_MISRRed 0x0084
+#define __RGB525_MISRGreen 0x0086
+#define __RGB525_MISRBlue 0x0088
+#define __RGB525_PLLVCODivInput 0x008E
+#define __RGB525_PLLVCORefInput 0x008F
+#define __RGB525_VramMaskLow 0x0090
+#define __RGB525_VramMaskHigh 0x0091
+
+/* RevisionLevel */
+
+#define RGB525_PRODUCT_REV_LEVEL 0xF0
+
+/* ProductID */
+
+#define RGB525_PRODUCT_ID_CODE 0x01
+
+/************************************************************************/
+/* INDEXED REGISTERS - CURSOR ARRAY */
+/************************************************************************/
+
+#define __RGB525_CursorArray 0x0100
+
+/************************************************************************/
+/* DIRECT ACCESS MACROS */
+/************************************************************************/
+/*
+ * The pixel clock must be running to access the palette and the cursor
+ * array, and the timings for the microprocessor signals are specified
+ * in units of pixel clocks. Six clocks must be allowed for an internal
+ * access to complete, following a palette or cursor access.
+ *
+ * In the worst case (VGA 640x480 resolution) the pixel clock is 40 ns,
+ * giving a time of 280 ns for seven pixel clocks. Assuming the fastest
+ * host clock is 100 MHz, a delay of 28 host clocks is required. Again
+ * assuming that the loop below takes 3 clocks per iteration, it should
+ * be executed at least 10 times.
+ */
+
+#define RGB525_DELAY \
+{ \
+ volatile DWORD __rgb525_dly; \
+ \
+ for (__rgb525_dly = 0; __rgb525_dly < 10; __rgb525_dly++); \
+}
+
+/*
+ * All RGB525 accesses are followed by a short delay, as required by
+ * the AC Characteristics table in the RGB525 Databook. However, the
+ * text implies that non-palette or cursor-array accesses can happen
+ * closer together. Everything is delayed here for simplicity.
+ */
+
+#define RGB525_ADDR(base, offset) \
+( \
+/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \
+ (DWORD) ((base) + (offset)) \
+)
+
+#define RGB525_WRITE(dac, offset, data) \
+{ \
+/* DWORD_WRITE(RGB525_ADDR((dac),(offset)), (data)); */ \
+ WRITE_REGISTER_UCHAR(RGB525_ADDR((dac),(offset)), (UCHAR)(data)); \
+ RGB525_DELAY; \
+}
+
+#define RGB525_READ_BYTE(dac, offset, data) \
+{ \
+ DWORD __rgb525_tmp; \
+ \
+/* DWORD_READ(RGB525_ADDR((dac),(offset)), __rgb525_tmp); */ \
+ __rgb525_tmp = READ_REGISTER_UCHAR(RGB525_ADDR((dac),(offset))); \
+/* (data) = (BYTE) (__rgb525_tmp & BYTE_MAX); */ \
+ (data) = (UCHAR) (__rgb525_tmp & 0xff); \
+ RGB525_DELAY; \
+}
+
+/************************************************************************/
+/* INDEXED ACCESS MACROS */
+/************************************************************************/
+
+#define RGB525_SET_INDEX(dac, index) \
+{ \
+ RGB525_WRITE((dac), __RGB525_IndexLow, (index)); \
+/* RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> BYTE_BITS); */ \
+ RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> 8); \
+}
+
+#define RGB525_SET_REG(dac, index, data) \
+{ \
+ RGB525_SET_INDEX((dac), (index)); \
+ RGB525_WRITE((dac), __RGB525_IndexedData, (data)); \
+}
+
+#define RGB525_GET_REG(dac, index, data) \
+{ \
+ RGB525_SET_INDEX((dac), (index)); \
+ RGB525_READ_BYTE((dac), __RGB525_IndexedData, (data)); \
+}
+
+/************************************************************************/
+
+#endif /* __RGB525_H__ */
+
+/************************************************************************/
diff --git a/private/ntos/nthals/halr96b/mips/tga.h b/private/ntos/nthals/halr96b/mips/tga.h
new file mode 100644
index 000000000..3e6257c7c
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/tga.h
@@ -0,0 +1,93 @@
+// #pragma comment(exestr, "@(#) tga.h 1.1 95/09/28 18:38:49 nec")
+/*++
+
+Module Name:
+
+ tga.h
+
+Abstract:
+
+ This module contains the register definitions for the TGA (DEC21030)
+
+Author:
+
+ T.Katoh create-data 1994/11/30
+
+Revision Histort:
+
+--*/
+
+// TGA Core Space Map offset for 8-bpp Frame Buffers
+
+#define TGA_REG_SPC_OFFSET 0x00100000
+#define TGA_DSP_BUF_OFFSET 0x00200000
+
+// TGA register offsets, organized by functionality.
+
+#define PLANE_MASK 0x00000028
+#define ONE_SHOT_PIXEL_MASK 0x0000002C
+#define MODE 0x00000030
+#define RASTER_OP 0x00000034
+#define DEEP 0x00000050
+#define BLK_COLOR_R0 0X00000140
+#define BLK_COLOR_R1 0X00000144
+#define H_CONT 0x00000064
+#define V_CONT 0x00000068
+#define VIDEO_BASE 0x0000006c
+#define VIDEO_VALID 0x00000070
+#define RAMDAC_SETUP 0x000000C0
+#define EEPROM_WRITE 0x000001e0
+#define CLOCK 0x000001e8
+#define RAMDAC_DATA 0X000001f0
+#define COMMAND_STATUS 0x000001f8
+
+// Initiate Palette Data
+
+#define VGA_INI_PALETTE_BLACK_R 0x00
+#define VGA_INI_PALETTE_BLACK_G 0x00
+#define VGA_INI_PALETTE_BLACK_B 0x00
+#define VGA_INI_PALETTE_RED_R 0xAA
+#define VGA_INI_PALETTE_RED_G 0x00
+#define VGA_INI_PALETTE_RED_B 0x00
+#define VGA_INI_PALETTE_GREEN_R 0x00
+#define VGA_INI_PALETTE_GREEN_B 0xAA
+#define VGA_INI_PALETTE_GREEN_G 0x00
+#define VGA_INI_PALETTE_YELLOW_R 0xAA
+#define VGA_INI_PALETTE_YELLOW_G 0xAA
+#define VGA_INI_PALETTE_YELLOW_B 0x00
+#define VGA_INI_PALETTE_BLUE_R 0x00
+#define VGA_INI_PALETTE_BLUE_G 0x00
+#define VGA_INI_PALETTE_BLUE_B 0xAA
+#define VGA_INI_PALETTE_MAGENTA_R 0xAA
+#define VGA_INI_PALETTE_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_MAGENTA_B 0xAA
+#define VGA_INI_PALETTE_CYAN_R 0x00
+#define VGA_INI_PALETTE_CYAN_G 0xAA
+#define VGA_INI_PALETTE_CYAN_B 0xAA
+#define VGA_INI_PALETTE_WHITE_R 0xAA
+#define VGA_INI_PALETTE_WHITE_G 0xAA
+#define VGA_INI_PALETTE_WHITE_B 0xAA
+#define VGA_INI_PALETTE_HI_BLACK_R 0x00
+#define VGA_INI_PALETTE_HI_BLACK_G 0x00
+#define VGA_INI_PALETTE_HI_BLACK_B 0x00
+#define VGA_INI_PALETTE_HI_RED_R 0xFF
+#define VGA_INI_PALETTE_HI_RED_G 0x00
+#define VGA_INI_PALETTE_HI_RED_B 0x00
+#define VGA_INI_PALETTE_HI_GREEN_R 0x00
+#define VGA_INI_PALETTE_HI_GREEN_G 0xFF
+#define VGA_INI_PALETTE_HI_GREEN_B 0x00
+#define VGA_INI_PALETTE_HI_YELLOW_R 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_G 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_B 0x00
+#define VGA_INI_PALETTE_HI_BLUE_R 0x00
+#define VGA_INI_PALETTE_HI_BLUE_G 0x00
+#define VGA_INI_PALETTE_HI_BLUE_B 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_R 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_HI_MAGENTA_B 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_R 0x00
+#define VGA_INI_PALETTE_HI_CYAN_G 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_B 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_R 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_G 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_B 0xFF
diff --git a/private/ntos/nthals/halr96b/mips/x4clock.s b/private/ntos/nthals/halr96b/mips/x4clock.s
new file mode 100644
index 000000000..2e3aaac3a
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/x4clock.s
@@ -0,0 +1,433 @@
+// .ident "@(#) x4clock.s 1.1 95/09/28 18:39:17 nec"
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// M001 Fri Feb 17 17:48:03 JST 1995 kbnes!kuriyama (A)
+// - Change HalpClockInterrupt0(()
+// for dump switch support.
+//
+// S002 Tue Feb 21 21:24:13 JST 1995 kbnes!kuriyama (A)
+// - use HalpNMIFlag
+//
+// S003 Wed Feb 22 11:18:59 JST 1995 kbnes!kuriyama (A)
+// - enter kernel debugger when NMI only checked version
+//
+// S004 Wed Feb 22 14:25:20 JST 1995 kbnes!kuriyama (A)
+// - enter kernel debugger when NMI free version
+//
+// S005 Sat Mar 18 20:30:05 JST 1995 kbnes!kuriyama (A)
+// - nmi logic change
+//
+// M006 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 14:16:29 JST 1995
+// - change nmi logic
+//
+// M007 Thu Jul 20 19:31:41 JST 1995 kbnes!kisimoto
+// - Merge build 1057
+//
+//--
+
+#include "halmips.h"
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdef.h"
+
+#endif
+
+// M001 +++
+#if defined(_R94A_)
+ .extern HalpNMIFlag
+ .extern HalpNMIInterrupt
+ .extern HalpDumpNMIFlag //S002
+#endif //_R94A_
+// M001 ---
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+
+// M001 +++
+#if defined(_R94A_)
+//
+// check if dump swich flag set.
+//
+
+ la t0,HalpNMIFlag // set NMI flag address
+ li t1,0xa0000000 // set KSEG1_BASE
+ or t0,t0,t1
+ lw t1,(t0) // load NMI flag
+ nop
+ beq t1,zero,10f
+ nop
+ sw zero,(t0)
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ nop
+ lbu t0,0(t0) // get debugger enable flag
+ nop
+ beq zero,t0,5f // if eq, debugger not enabled
+ nop
+ nop
+ beq zero,v0,40f // if eq, no breakin requested
+ nop
+ break BREAKIN_BREAKPOINT // break into the debugger
+ nop
+5:
+
+// S002 +++
+ la t0,HalpDumpNMIFlag // set Dump NMI flag address
+ li t1,0xa0000000 // set KSEG1_BASE
+ or t0,t0,t1 //
+ lw a0,(t0) // load Dump NMI flag
+ nop //
+// S003 +++
+ sw zero,(t0) // clear Dump NMI flag
+ nop //
+// S003 ---
+// S005
+ lw zero,DMA_VIRTUAL_BASE + 0x58 // clear acknowledge // M006
+// S002 ---
+ jal HalpNMIInterrupt // jump to NMI routine
+ nop //
+10:
+#endif // _R94A_
+// M001 ---
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+
+#endif
+
+#if defined(_JAZZ_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
+
+#endif
+
+
+ .set reorder
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// The following code is a work around for a bug in the Fusion machines
+// where the clock interrupt is not dismissed by reading the acknowledge
+// register.
+//
+
+#if defined(_JAZZ_)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,cause // read the cause register
+ lw t1,HalpEisaControlBase // get EISA control base address
+ sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit
+ bgez t0,10f // if gez, no clock interrupt pending
+ li t2,0x2 // get NMI port enable bit
+ lb t3,0x70(t1) // save EISA NMI interrupt disable
+ lb t4,0x461(t1) // save EISA extended NMI status
+ sb zero,0x70(t1) // clear EISA NMI interrupt disable
+ sb t2,0x461(t1) // set EISA NMI port enable
+ sb zero,0x462(t1) // generate EISA NMI interrupt
+ sb zero,0x461(t1) // clear EISA extended NMI status
+ sb t2,0x461(t1) //
+ lb zero,0x461(t1) // synchronize clear operatin
+ sb t3,0x70(t1) // restore EISA NMI interupt disable
+ sb t4,0x461(t1) // restore EISA exteneed NMI status
+ lb zero,0x461(t1) // synchronize restore operation
+ .set at
+ .set reorder
+
+10: //
+
+#endif
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,30f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+
+ .set noreorder
+
+#if defined(_DUO_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count
+
+#endif
+
+#if defined(_JAZZ_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
+
+#endif
+
+ .set reorder
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1 //
+
+#else // M007
+
+ j ra //
+
+#endif
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+#if defined(NT_UP)
+
+ la t1,HalpPerformanceCounter // get performance counter address
+
+#else
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+#endif
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halr96b/mips/x4tb.s b/private/ntos/nthals/halr96b/mips/x4tb.s
new file mode 100644
index 000000000..be37d6677
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/x4tb.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\x4tb.s"
diff --git a/private/ntos/nthals/halr96b/mips/x86bios.c b/private/ntos/nthals/halr96b/mips/x86bios.c
new file mode 100644
index 000000000..68a599e80
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/x86bios.c
@@ -0,0 +1,1261 @@
+// #pragma comment(exestr, "@(#) x86bios.c 1.1 95/09/28 18:40:12 nec")
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ M001 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:45:09 JST 1995
+ - add check intel based bios flag
+
+ M002 kuriyama@oa2.kb.nec.co.jp Thu Jul 20 15:16:52 JST 1995
+ - add for DPI support (NO PCI DATA structure)
+
+ S003 kuriyama@oa2.kb.nec.co.jp Tue Aug 15 14:09:30 JST 1995
+ - bug fix for canopus PowerWindows 864PCI
+
+--*/
+
+
+#define USE_BIOS_EMULATOR
+
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "xm86.h"
+#include "x86new.h"
+
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PSHORT Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PSHORT Buffer,
+ IN ULONG Offset
+ );
+
+// M001 +++
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+// M001 ---
+
+//
+// Define global data.
+//
+
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+PVOID HalpIoMemoryBase = NULL;
+PVOID HalpIoControlBase=NULL;
+PUCHAR HalpRomBase = NULL;
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (64*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+//#define R98_PCICONFIG_START ((PULONG)(0x18ca8800 | KSEG1_BASE))
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+BOOLEAN HalpInitX86Emulator(
+ VOID)
+
+{
+ ULONG ROM_size = 0;
+ PHYSICAL_ADDRESS PhysAddr;
+ UCHAR BaseClass, SubClass, ProgIf;// M001
+ USHORT Cmd,SetCmd, VendorID, DeviceID, Slot; // M002
+ PUCHAR ROM_Ptr, ROM_Shadow;
+ ULONG i;
+ ULONG r;
+ USHORT PciDataOffset; // M001
+ PCI_SLOT_NUMBER PciSlot;
+ UCHAR header;
+ KIRQL Irql;
+ PhysAddr.HighPart = 0x00000000;
+
+
+#if 1
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ //kuku
+ KeRaiseIrql (PROFILE_LEVEL, &Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+#if 0 //tmp 707 // M001
+ // First Check ISA BIOS.Becase PCEB 0-1M Positive Decode So
+ // I Can See ROM Image.
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+
+ HalpIoMemoryBase= (PVOID)0x40000000;
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Look for ISA option video ROM signature
+ //
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ }
+#if defined(_X86_DBG_)
+ DbgPrint("\n EISA ROM BIOS Found \n"); //DBGDBG
+#endif // _X86_DBG_
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ HalpIoControlBase= (PVOID)0x403f0000;
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+ return TRUE;
+
+ }
+#endif
+
+ //
+ // Scan PCI slots for video BIOS ROMs, except 3 PCI "slots" on motherboard
+ //
+ // Slot 0: Hurrucane (host bridge)
+ // Slot 1: Typhoon (Internal-bus bridge)
+ // Slot 2: PCI-EISA bridge
+ //
+ for (Slot = 3; Slot < 6; Slot++) {
+#if defined(_X86_DBG_)
+ DbgPrint("\n PCI SLot Number=%x\n",Slot); //DBGDBG
+#endif // _X86_DBG_
+ //
+ // Create a mapping to PCI configuration space
+ //
+
+ PciSlot.u.bits.FunctionNumber = 0;
+ PciSlot.u.bits.DeviceNumber = Slot ;
+
+ //
+ // Read Vendor ID and check if slot is empty
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&VendorID,FIELD_OFFSET (PCI_COMMON_CONFIG, VendorID));
+
+#if defined(_X86_DBG_)
+DbgPrint("\n Vendor ID=%x\n",VendorID); //DBGDBG
+#endif // _X86_DBG_
+
+ if (VendorID == 0xFFFF){
+ continue; // Slot is empty; go to next slot
+ }
+
+// M002 +++
+ //
+ // Read Device ID and check if slot is empty
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&DeviceID,FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceID));
+
+ //
+ // Check for GLINT or DEC-GA board.
+ //
+
+ if ( (VendorID == 0x3d3d && DeviceID == 0x0001) ||
+ (VendorID == 0x1011 && DeviceID == 0x0004) ) {
+ continue;
+ }
+// M002 ---
+
+
+// M001 +++
+ //
+ // Check Base Class Code
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&BaseClass,FIELD_OFFSET (PCI_COMMON_CONFIG, BaseClass));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n BaseClass =%x\n",BaseClass); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // Check Sub Class Code
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&SubClass,FIELD_OFFSET (PCI_COMMON_CONFIG, SubClass));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n SubClass =%x\n",SubClass); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // Check Proglamming Interface
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&ProgIf,FIELD_OFFSET (PCI_COMMON_CONFIG, ProgIf));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n ProgIf =%x\n",ProgIf); //DBGDBG
+#endif // _X86_DBG_
+
+ //
+ // check if video card
+ //
+ if ( ( (BaseClass == 0) && (SubClass == 1) && (ProgIf == 0) ) || //S003
+ ( (BaseClass == 3) && (SubClass == 0) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 1) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 0x80) && (ProgIf == 0) ) ) {
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is Video card \n");
+#endif // _X86_DBG_
+ } else {
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is not Video card \n");
+#endif // _X86_DBG_
+ continue;
+ }
+// M001 ---
+
+ //
+ // Get size of ROM
+ //
+
+ ROM_size=0xFFFFFFFF;
+
+#if defined(_X86_DBG_)
+ DbgPrint("ROM size config offset = %x\n",FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+#endif // _X86_DBG_
+ HalpWritePCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ HalpReadPCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+
+#if defined(_X86_DBG_)
+ DbgPrint("\nROM_Size = %0x\n",ROM_size);
+#endif // _X86_DBG_
+
+ if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
+
+
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Set Expansion ROM Base Address & enable ROM
+ //
+
+ PhysAddr.LowPart = 0x000C0000 | PCI_ROMADDRESS_ENABLED;
+
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ //
+ // Enable Memory & I/O spaces in command register
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+#if defined(_X86_DBG_)
+ DbgPrint("\nREAD CMD=%0x\n",Cmd);
+#endif // _X86_DBG_
+
+ SetCmd = Cmd|0x3;
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+ // Map Phys C0000000-C00D0000
+ // Create a mapping to the PCI memory space
+ //
+ PhysAddr.HighPart = 1;
+ PhysAddr.LowPart=0;
+
+#if 1
+
+
+ HalpIoMemoryBase= (PVOID)0x40000000;
+#else
+ HalpIoMemoryBase = MmMapIoSpace(PhysAddr, ROM_size,FALSE);
+ if (HalpIoMemoryBase == NULL) {
+#if defined(_X86_DBG_)
+ DbgPrint("\nCan't create mapping to PCI memory space\n");
+#endif // _X86_DBG_
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+ return FALSE;
+ }
+#endif
+ //
+ // Look for PCI option video ROM signature
+ //
+ HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+#if defined(_X86_DBG_)
+ DbgPrint("\nHalpRomBase=%x\n",HalpRomBase);
+#endif // _X86_DBG_
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // Sometimes option ROM and video RAM can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+
+
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+#if defined(_X86_DBG_)
+ DbgPrint("\nROM Short HalpRomBase=%x\n",HalpRomBase);
+#endif // _X86_DBG_
+
+ }
+
+#if 0 // M002
+// M001 +++
+ //
+ // check rom code is INTEL BASE
+ //
+
+ PciDataOffset = *(PUSHORT)(0x400c0000 + 0x18);
+#if defined(_X86_DBG_)
+ DbgPrint("PciDataOffset = %x\n",PciDataOffset);
+#endif // _X86_DBG_
+
+ if ( *(PUCHAR)(0x400c0000 + (ULONG)PciDataOffset + 0x14) == 0 ) {
+// DbgPrint("check PCI rom\n");
+// DbgBreakPoint();
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is intel base rom \n");
+#endif // _X86_DBG_
+ } else {
+#if defined(_X86_DBG_)
+ DbgPrint("\n This is not intel base rom \n");
+#endif // _X86_DBG_
+
+ //
+ // Disable Rom address
+ //
+
+ PhysAddr.LowPart = 0x000C0000;
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ continue;
+ }
+// M001 ---
+#endif // 0 // M002
+
+ //
+ // Io Map.
+ //
+ HalpIoControlBase= (PVOID)0x403f0000;
+
+#if 0 // M001---
+ PhysAddr.LowPart = 0x000C0000;
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+#endif // M001---
+
+#if 0 //706
+ // Found PCI VIDEO ROM.
+ // 1.Map ISA Memory Space
+ // 2.
+#if defined(_X86_DBG_)
+ DbgPrint("\nFound PCI ROM BIOS\n");
+#endif // _X86_DBG_
+
+
+ // 0: rom enable so do PCI
+ // 1: rom disable so do EISA vga
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+#endif
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+// MmUnmapIoSpace ( HalpIoMemoryBase, ROM_size);
+
+ // Not Found So Reset!!.
+ // Delete mapping to PCI memory space
+
+
+#if 1 //706
+ // Found PCI VIDEO ROM.
+ // 1.Map ISA Memory Space
+ // 2.
+#if defined(_X86_DBG_)
+ DbgPrint("\nFound PCI ROM BIOS\n");
+#endif // _X86_DBG_
+
+
+ // 0: rom enable so do PCI
+ // 1: rom disable so do EISA vga
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+#endif
+
+ } // end of if clause
+#if defined(_X86_DBG_)
+ DbgPrint("\n ROM SIZE invalid\n"); //DBGDBG
+#endif // _X86_DBG_
+ } // end of for loop
+#else
+// ROM_size = 0xD0000; // Map to end of option ROM space
+#endif
+
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+#if 1 //tmp 707 // M001
+ // No PCI BIOS SO Search ISA BIOS.
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+
+ HalpIoMemoryBase= (PULONG)0x40000000;
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Look for ISA option video ROM signature
+ //
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+// DbgPrint("check PCI rom\n");
+// DbgBreakPoint();
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ }
+#if defined(_X86_DBG_)
+ DbgPrint("\n EISA ROM BIOS Found \n"); //DBGDBG
+#endif // _X86_DBG_
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ HalpIoControlBase= (PVOID)0x403f0000;
+ return TRUE;
+ }
+#endif
+ //
+ // No video option ROM was found. Delete mapping to PCI memory space.
+ //
+#if defined(_X86_DBG_)
+ DbgPrint("\n 55AA BIOS Not \n"); //DBGDBG
+#endif // _X86_DBG_
+ return FALSE;
+}
+
+//--------------------
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
+ &Context,
+ HalpIoControlBase,
+ HalpIoMemoryBase) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (!HalpInitX86Emulator())
+ return FALSE;
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ HalpEnableInt10Calls = TRUE;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+#endif
+
+ return;
+}
+
+
+//
+// This code came from ..\..\x86new\x86bios.c
+//
+#define LOW_MEMORY_SIZE 0x800
+extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+extern ULONG x86BiosScratchMemory;
+extern ULONG x86BiosIoMemory;
+extern ULONG x86BiosIoSpace;
+
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(HalpRomBase + Offset);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+
+ // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
+ return (PVOID)NULL;
+}
+
+
+VOID HalpCopyROMs(VOID)
+{
+ULONG i;
+PUCHAR ROM_Shadow;
+
+ if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
+ HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
+#if defined(_X86_DBG_)
+ DbgPrint("HalpRomBase=%0x\n",HalpRomBase);
+#endif // _X86_DBG_
+ for (i=0; i<ROM_Length; i++) {
+ *ROM_Shadow++ = ROM_Buffer[i];
+ }
+ }
+}
+
+
+/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
+
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space and the
+// base address of I/O memory space.
+//
+
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+// DbgPrint("read port %x translate %x\n",PortNumber,u.Long);
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+// DbgPrint("write port %x translate %x\n",PortNumber,u.Long);
+ if (DataType == BYTE_DATA) {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n EMU INIT \n"); //DBGDBG
+#endif // _X86_DBG_
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+#if defined(_X86_DBG_)
+ DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
+#endif // _X86_DBG_
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+#if defined(_X86_DBG_)
+ DbgPrint("\n BIOS INIT \n"); //DBGDBG
+#endif // _X86_DBG_
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+#if defined(_X86_DBG_)
+ DbgPrint("\n Emcall BIOS start \n"); //DBGDBG
+#endif // _X86_DBG_
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+#if defined(_X86_DBG_)
+ DbgPrint("\n Emcall BIOS End \n"); //DBGDBG
+#endif // _X86_DBG_
+ if (Status != XM_SUCCESS) {
+#if defined(_X86_DBG_)
+ DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
+#endif // _X86_DBG_
+ }
+
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halr96b/mips/xxcalstl.c b/private/ntos/nthals/halr96b/mips/xxcalstl.c
new file mode 100644
index 000000000..991432fee
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxcalstl.c
@@ -0,0 +1,302 @@
+// #pragma comment(exestr, "@(#) xxcalstl.c 1.1 95/09/28 18:40:42 nec")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History:
+
+ H001 Fri Aug 25 14:21:02 1995 kbnes!kisimoto
+ - change scale factor down range. for 250MHz.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= (Index < 20 ? 1 : 10)) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt0;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the interval timer interrupt.
+ //
+
+#if defined(_DUO_)
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->TimerInterruptAcknowledge.Long);
+
+#else
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+
+#endif
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halr96b/mips/xxclock.c b/private/ntos/nthals/halr96b/mips/xxclock.c
new file mode 100644
index 000000000..c7ec77df5
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxclock.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxclock.c"
diff --git a/private/ntos/nthals/halr96b/mips/xxidle.s b/private/ntos/nthals/halr96b/mips/xxidle.s
new file mode 100644
index 000000000..faf3163a9
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxidle.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxidle.s"
diff --git a/private/ntos/nthals/halr96b/mips/xxinithl.c b/private/ntos/nthals/halr96b/mips/xxinithl.c
new file mode 100644
index 000000000..11dfa3c22
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxinithl.c
@@ -0,0 +1,934 @@
+/* #pragma comment(exestr, "@(#) NEC(MIPS) xxinithl.c 1.2 95/10/17 01:19:57" ) */
+/*++
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+ H000 Wed Sep 14 19:38:36 JST 1994 kbnes!kishimoto
+ - HalInitSystem()
+ Define global spin locks used to synchronize
+ various LED operations, and initialize LED spin locks.
+ H001 Fri Oct 14 15:03:38 JST 1994 kbnes!kishimoto
+ - HalInitSystem(),HalpBugCheckCallback(),HalpBusError()
+ Modify to read the 33-bit register.
+ Bacause the InvalidAddress register of R94A is 33-bits long.
+ And original compile errors are modified.
+ H002 Fri Oct 21 14:25:22 JST 1994 kbnes!kishimoto
+ - call HalR94aDebugPrint to display debug infomation.
+ A001 Mon Oct 24 17:19:06 JST 1994 ataka@oa2.kb.nec.co.jp
+ - Call HalpInitBusHandlers
+ H003 Mon Nov 21 22:01:43 1994 kbnes!kishimoto
+ - TEMP TEMP :
+ comment out HalpInitializeX86DisplayAdapter() for R94A BBM
+ M004 Fri Jan 06 10:53:32 JST 1995 kbnes!A.kuriyama
+ - HalpPrintMdl() call
+ H005 Mon Jan 16 02:10:42 1995 kbnes!kishimoto
+ - initialize PCI configuration register spin lock
+ M006 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 17:15:35 JST 1995
+ - add _IPI_LIMIT_ support
+ S007 kuriyama@oa2.kb.nec.co.jp Mon Apr 03 10:31:37 JST 1995
+ - delete PrintMdl ( ifdef _PRINT_MDL_ )
+ S008 kuriyama@oa2.kb.nec.co.jp Mon May 22 02:11:30 JST 1995
+ - add support for esm
+ M009 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 02:53:50 JST 1995
+ - add search NMI interface aread
+ S010 kuriayam@oa2.kb.nec.co.jp Mon Jun 05 04:44:09 JST 1995
+ - NMI interface bug fix
+ M011 kuriyama@oa2.kb.nec.co.jp Fri Jun 16 19:13:45 JST 1995
+ - add support for esm Ecc 1bit/2bit error logging
+ M012 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 10:52:21 JST 1995
+ - add ecc 1bit safty flag
+ M013 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 19:21:44 JST 1995
+ - Merge build 1057 halx86
+ H014 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 14:28:46 1995
+ - Removed IPI_LIMIT, BBMLED code, J94C definitions,
+ and rearrange comments.
+ M015 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:32:18 JST 1995
+ - add for x86bios support
+ H016 kisimoto@oa2.kb.nec.co.jp Tue Sep 5 20:43:22 1995
+ - add initialization of spinlock to support
+ PCI Fast Back-to-back transfer.
+ M017 nishi@oa2.kb.nec.co.jp Tue Sep 18 20:43:22 1995
+ - add Software Power Off, when system panic is occured
+--*/
+
+#include "halp.h"
+/* Start M017 */
+#define HEADER_FILE
+#include "kxmips.h"
+/* End M017 */
+
+
+//
+// M015
+// Define for x86bios emulator use.
+//
+
+// PCHAR K351UseBios=NULL;
+VOID HalpCopyROMs(VOID);
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpIoControlBase;
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+VOID
+HalpDisplayINT10Setup (
+VOID);
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character );
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+extern PHALP_DISPLAY_CHARACTER HalpDisplayCharacter;
+extern PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup;
+
+//
+// M012
+// Define Ecc safety flags
+//
+
+#define CHECKED 1
+#define NOT_CHECKED 0
+#define RUNNING 1
+#define NOT_RUNNING 0
+
+//
+// M012
+// Define Ecc safety variables
+//
+
+UCHAR HalpAnotherCheckedECC = NOT_CHECKED;
+UCHAR HalpAnotherRunningECC = NOT_RUNNING;
+
+
+//
+// Define forward referenced prototypes.
+//
+
+#if defined(_PRINT_MDL_) // M004,S007
+VOID
+HalpPrintMdl (
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+#endif // _PRINT_MDL_
+
+VOID
+HalpSearchNMIInterface ( // M009
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+ULONG HalpNMIInterfaceAddress = 0;
+
+extern
+VOID // M011
+HalpSetInitDisplayTimeStamp(
+ VOID
+ );
+
+extern
+ULONG // M011
+HalpEccError(
+ IN ULONG EccDiagnostic,
+ IN ULONG MemoryFailed
+ );
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpPCIConfigLock; // H005
+KSPIN_LOCK Ecc1bitDisableLock; // M011
+KSPIN_LOCK Ecc1bitRoutineLock; // M012
+KSPIN_LOCK HalpPCIBackToBackLock; // H016
+#if defined(_IPI_LIMIT_)
+KSPIN_LOCK HalpIpiRequestLock;
+#endif //_IPI_LIMIT_
+
+//
+// Define bug check information buffer and callback record.
+//
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG FailedAddress;
+ ULONG DiagnosticLow;
+ ULONG DiagnosticHigh;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ ULONG FailedAddress;
+ PKPRCB Prcb;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+ LARGE_INTEGER registerLarge; // H001
+
+ UCHAR ModeNow; // M017
+ KIRQL OldIrql; // M017
+ ENTRYLO Pte[2]; // M017
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ PCR->DataBusError = HalpBusError;
+ PCR->InstructionBusError = HalpBusError;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+
+ /* Start M017 */
+ if (Prcb->Number == 0) {
+
+ //
+ // for software controlled power supply.
+ //
+#if defined(_MRCPOWER_)
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT;
+
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ //
+ // Map MRC using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+
+ //
+ // MRC Mode bit change to 0 ( Power Off interrupt is NMI )
+ //
+ ModeNow = READ_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode,
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &MRC_CONTROL->Mode,
+ ModeNow & 0x02,
+ );
+
+ KeLowerIrql(OldIrql);
+
+#endif // _MRCPOWER_
+ }
+ /* End M017*/
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+#if 0
+ //
+ // M013
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // M013
+ // Set DMA I/O coherency attributes.
+ //
+
+ KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_DUO_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+#if defined(_IPI_LIMIT_)
+ KeInitializeSpinLock(&HalpIpiRequestLock);
+#endif //_IPI_LIMIT_
+
+#endif
+
+ KeInitializeSpinLock(&Ecc1bitDisableLock); // M011
+ KeInitializeSpinLock(&Ecc1bitRoutineLock); // M012
+ KeInitializeSpinLock(&HalpPCIConfigLock); // H005
+ KeInitializeSpinLock(&HalpPCIBackToBackLock); // H016
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ // temp
+
+// TmpInitNvram();
+
+#if DBG
+ printNvramData();
+#endif // DBG
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+#if defined(_PRINT_MDL_)
+ HalpPrintMdl(LoaderBlock); // M004,S007
+#endif //_PRINT_MDL
+
+ HalpSearchNMIInterface(LoaderBlock); // M009
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+ }
+
+ //
+ // H001
+ // Clear memory address error registers.
+ //
+
+#if defined(_DUO_)
+
+#if defined(_R94A_)
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ FailedAddress = registerLarge.LowPart;
+
+#else
+
+ FailedAddress = (ULONG)((volatile DMA_REGISTERS *)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; // H001
+
+ //
+ // Initialize interrupts
+ //
+
+ HalpInitializeInterrupts();
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ HalpRegisterInternalBusHandlers (); // M013
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ HalpMapIoSpace();
+
+ HalpSetInitDisplayTimeStamp(); // S008
+
+ HalpCalibrateStall();
+
+ HalpCreateDmaStructures();
+
+ //
+ // M015
+ // for x86bios emulator. bios copy
+ //
+
+ HalpCopyROMs();
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+ //
+ // M014
+ // reset EISA io/memory base for HalCallBios() use.
+ //
+ HalpIoControlBase = HalpEisaControlBase;
+ HalpIoMemoryBase = HalpEisaMemoryBase;
+
+ return TRUE;
+ }
+ }
+}
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+ LARGE_INTEGER registerLarge; // H001
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+#if defined(_DUO_)
+
+#if defined(_R94A_) // H001
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ DumpBuffer->DiagnosticLow = registerLarge.LowPart;
+
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+ return;
+}
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG DiagnosticHigh;
+ ULONG DiagnosticLow;
+ ULONG FailedAddress;
+ LARGE_INTEGER registerLarge; // H001
+
+ //
+ // Bug check specifying the exception code, the virtual address, the
+ // failed memory address, and either the ECC diagnostic registers or
+ // the parity diagnostic registers depending on the platform.
+ //
+
+#if defined(_DUO_)
+
+#if !defined(_R94A_)
+
+ DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+#endif
+
+ DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+ DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+
+ // start M011
+ {
+ ULONG returnValue;
+ KIRQL OldIrql;
+
+ //
+ // Call Ecc 1bit/2bit error routine.
+ // if 1bit error return TRUE.(OS run continue)
+ // Otherwise bugcheck.
+ //
+
+ if (DiagnosticHigh & 0x66000000) {
+
+ KeRaiseIrql(HIGH_LEVEL,&OldIrql);
+ returnValue = HalpEccError(DiagnosticHigh, FailedAddress);
+ KeLowerIrql(OldIrql);
+
+ if (returnValue == 2) {
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ FailedAddress,
+ DiagnosticLow,
+ DiagnosticHigh);
+
+ return FALSE;
+ }
+
+ } else { // M012
+
+ READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+ DiagnosticLow = registerLarge.LowPart;
+
+ if (DiagnosticLow & 1) {
+
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ FailedAddress,
+ DiagnosticLow,
+ DiagnosticHigh);
+
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+#if defined(_DUO_)
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+#endif
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+HalpSearchNMIInterface (
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ ULONG FirmwareParmanentCount = 0;
+
+ //
+ // Get the lower bound of the free physical memory and the
+ // number of physical pages by walking the memory descriptor lists.
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ MemoryDescriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if (MemoryDescriptor->MemoryType == MemoryFirmwarePermanent) {
+
+ if (++FirmwareParmanentCount == 2) { // S010
+ HalpNMIInterfaceAddress = MemoryDescriptor->BasePage << PAGE_SHIFT;
+#if DBG
+ DbgPrint("NMI Interface was found!\n");
+ DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType);
+ DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage);
+ DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount);
+#endif // DBG
+ }
+#if DBG
+ DbgPrint("Firmware Parmanent entry was found!\n");
+ DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType);
+ DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage);
+ DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount);
+#endif // DBG
+ }
+ NextMd = MemoryDescriptor->ListEntry.Flink;
+ }
+}
diff --git a/private/ntos/nthals/halr96b/mips/xxinitnt.c b/private/ntos/nthals/halr96b/mips/xxinitnt.c
new file mode 100644
index 000000000..2b57adb0d
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxinitnt.c
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxinitnt.c"
diff --git a/private/ntos/nthals/halr96b/mips/xxipiint.s b/private/ntos/nthals/halr96b/mips/xxipiint.s
new file mode 100644
index 000000000..266246f51
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxipiint.s
@@ -0,0 +1,11 @@
+//
+// This file simply includes the main code from the halfxs directory after
+// undef'ed NT_UP if necessary.
+//
+
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+#include "..\halfxs\mips\xxipiint.s"
diff --git a/private/ntos/nthals/halr96b/mips/xxmvmem.s b/private/ntos/nthals/halr96b/mips/xxmvmem.s
new file mode 100644
index 000000000..1a6364214
--- /dev/null
+++ b/private/ntos/nthals/halr96b/mips/xxmvmem.s
@@ -0,0 +1,264 @@
+// .ident "@(#) xxmvmem.s 1.1 95/09/28 18:42:46 nec"
+//
+// Stolen from rtl xxmvmem.s this source can be used for r94a
+// beta machine only.
+//
+// 1995.1.5 kbnes!A.Kuriyama
+//
+//
+// TITLE("Compare, Move, Zero, and Fill Memory Support")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// xxmvmem.s
+//
+// Abstract:
+//
+// This module implements functions to compare, move, zero, and fill
+// blocks of memory. If the memory is aligned, then these functions
+// are very efficient.
+//
+// N.B. These routines MUST preserve all floating state since they are
+// frequently called from interrupt service routines that normally
+// do not save or restore floating state.
+//
+// Author:
+//
+// David N. Cutler (davec) 11-Apr-1990
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("View Memory")
+//++
+//
+// PVOID
+// HalViewMemory (
+// IN PVOID Destination,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function zeros memory by first aligning the destination address to
+// a longword boundary, and then zeroing 32-byte blocks, followed by 4-byte
+// blocks, followed by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the memory to zero.
+//
+// Length (a1) - Supplies the length, in bytes, of the memory to be zeroed.
+//
+// Return Value:
+//
+// The destination address is returned as the function value.
+//
+//--
+
+ LEAF_ENTRY_S(HalViewMemory, _TEXT$00)
+
+ move a2,zero // set fill pattern
+ b HalpFillMemory //
+
+
+ SBTTL("Fill Memory")
+//++
+//
+// PVOID
+// HalFillMemory (
+// IN PVOID Destination,
+// IN ULONG Length,
+// IN UCHAR Fill
+// )
+//
+// Routine Description:
+//
+// This function fills memory by first aligning the destination address to
+// a longword boundary, and then filling 32-byte blocks, followed by 4-byte
+// blocks, followed by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the memory to fill.
+//
+// Length (a1) - Supplies the length, in bytes, of the memory to be filled.
+//
+// Fill (a2) - Supplies the fill byte.
+//
+// N.B. The alternate entry memset expects the length and fill arguments
+// to be reversed.
+//
+// Return Value:
+//
+// The destination address is returned as the function value.
+//
+//--
+
+ ALTERNATE_ENTRY(Halmemset)
+
+ move a3,a1 // swap length and fill arguments
+ move a1,a2 //
+ move a2,a3 //
+
+ ALTERNATE_ENTRY(HalFillMemory)
+
+ and a2,a2,0xff // clear excess bits
+ sll t0,a2,8 // duplicate fill byte
+ or a2,a2,t0 // generate fill word
+ sll t0,a2,16 // duplicate fill word
+ or a2,a2,t0 // generate fill longword
+
+//
+// Fill memory with the pattern specified in register a2.
+//
+
+HalpFillMemory: //
+ move v0,a0 // set return value
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu t1,a1,t0 // reduce number of bytes to fill
+ blez t1,60f // if lez, less than 4 bytes to fill
+ move a1,t1 // set number of bytes to fill
+ beq zero,t0,10f // if eq, already aligned
+ lwr t5,0(a0) // fill unaligned bytes
+ addu a0,a0,t0 // align destination address
+
+//
+// Check for 32-byte blocks to fill.
+//
+
+10: and t0,a1,32 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,40f // if eq, no 32-byte blocks to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destintion quadword aligned
+ beq zero,t0,20f // if eq, yes
+ lw t5,0(a0) // store destination longword
+ addu a0,a0,4 // align destination address
+ addu a1,a1,t1 // recompute bytes to fill
+ subu a1,a1,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned.
+//
+
+20: dsll a3,a2,32 // duplcate pattern to upper 32-bits
+ dsrl a2,a3,32 //
+ or a3,a3,a2 //
+ dmtc1 a3,f0 // set pattern value
+ and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,30f // if eq, even number of 32-byte blocks
+
+//
+// Fill one 32-byte block.
+//
+
+ .set noreorder
+ ldc1 f2,0(a0) // fill 32-byte block
+ ldc1 f2,8(a0) //
+ ldc1 f2,16(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ beq a0,t2,40f // if ne, no 64-byte blocks to fill
+ ldc1 f2,-8(a0) //
+ .set reorder
+
+//
+// Fill 64-byte block.
+//
+
+ .set noreorder
+30: ldc1 f2,0(a0) // fill 32-byte block
+ ldc1 f2,8(a0) //
+ ldc1 f2,16(a0) //
+ ldc1 f2,24(a0) //
+ ldc1 f2,32(a0) //
+ ldc1 f2,40(a0) //
+ ldc1 f2,48(a0) //
+ addu a0,a0,64 // advance pointer to next block
+ bne a0,t2,30b // if ne, more 32-byte blocks to fill
+ ldc1 f2,-8(a0) //
+ .set reorder
+
+#endif
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: lw a2,0(a0) // fill 32-byte block
+ lw a2,4(a0) //
+ lw a2,8(a0) //
+ lw a2,12(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ lw a2,-4(a0) //
+ lw a2,-8(a0) //
+ lw a2,-12(a0) //
+ bne a0,t2,20b // if ne, more 32-byte blocks to fill
+ lw a2,-16(a0) //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to fill.
+//
+
+40: and t0,a1,4 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,60f // if eq, no 4-byte block to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 4-byte blocks.
+//
+
+ .set noreorder
+50: addu a0,a0,4 // advance pointer to next block
+ bne a0,t2,50b // if ne, more 4-byte blocks to fill
+ lw t5,-4(a0) // fill 4-byte block
+ .set reorder
+
+//
+// Check for 1-byte blocks to fill.
+//
+
+60: addu t2,a0,a1 // compute ending block address
+ beq zero,a1,80f // if eq, no bytes to fill
+
+//
+// Fill 1-byte blocks.
+//
+
+ .set noreorder
+70: addu a0,a0,1 // advance pointer to next block
+ bne a0,t2,70b // if ne, more 1-byte block to fill
+ lb t5,-1(a0) // fill 1-byte block
+ .set reorder
+
+80: j ra // return
+
+ .end HalViewMemory
diff --git a/private/ntos/nthals/halr96b/sources b/private/ntos/nthals/halr96b/sources
new file mode 100644
index 000000000..716ad28e0
--- /dev/null
+++ b/private/ntos/nthals/halr96b/sources
@@ -0,0 +1,122 @@
+!IF 0
+ # pragma comment(exestr, "@(#) NEC(MIPS) sources 1.2 95/10/17 01:15:29" )
+
+Copyright (c) 1995 NEC Corporation
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+Revision History:
+
+Modification History for NEC R94A (MIPS R4400):
+
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halr96b
+TARGETPATH=\nt\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+# every system need -D_DUO_ -D_R94A_ -DDBCS -D_GLINT60HZ_
+#
+# also R94A need _IPI_LIMIT_ _INT_LIMIT_
+#
+# also R94D need none
+#
+# also R96B need _MRCDUMP_ _MRCPOWER_
+
+C_DEFINES=-D_DUO_ -D_R94A_ -DDBCS -D_GLINT60HZ_ -D_MRCDUMP_ -D_MRCPOWER_
+
+NT_UP=0
+
+INCLUDES=..\x86new;..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxdmadsp.s \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\xxipiint.s \
+ mips\x4tb.s \
+ mips\r94ainfo.c \
+ mips\r94adbg.c \
+ mips\pcisup.c \
+ mips\r94aio.s \
+ mips\busdat.c \
+ mips\pcibus.c \
+ mips\pciint.c \
+ mips\mipsdat.c \
+ mips\jxusage.c \
+ mips\pcibrd.c \
+ mips\xxmvmem.s \
+ mips\r94anmi.s \
+ mips\esm.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
+
diff --git a/private/ntos/nthals/halr98b/drivesup.c b/private/ntos/nthals/halr98b/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halr98b/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halr98b/hal.rc b/private/ntos/nthals/halr98b/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halr98b/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halr98b/hal.src b/private/ntos/nthals/halr98b/hal.src
new file mode 100644
index 000000000..73b8ae40a
--- /dev/null
+++ b/private/ntos/nthals/halr98b/hal.src
@@ -0,0 +1,8 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
+
diff --git a/private/ntos/nthals/halr98b/makefile b/private/ntos/nthals/halr98b/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halr98b/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halr98b/makefile.inc b/private/ntos/nthals/halr98b/makefile.inc
new file mode 100644
index 000000000..c64a11c81
--- /dev/null
+++ b/private/ntos/nthals/halr98b/makefile.inc
@@ -0,0 +1,5 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halr98b.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halr98b/mips/allstart.c b/private/ntos/nthals/halr98b/mips/allstart.c
new file mode 100644
index 000000000..debb7dcf6
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/allstart.c
@@ -0,0 +1,412 @@
+
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+--*/
+
+/*
+ */
+
+
+#include "halp.h"
+
+KINTERRUPT HalpEifInterrupt[R98B_MAX_CPU];
+
+//
+// This is Interrupt Level define.
+// HalpIntLevelofIpr[HalpMachineType][Ipr] = INT X
+//
+UCHAR HalpIntLevelofIpr[R98_CPU_NUM_TYPE][NUMBER_OF_IPR_BIT]={
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,5,5,5,5},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,4,4,4,4}
+};
+
+//
+// This is Interrupt connect pattern.
+// [NumberOfCpu][IPR] meas what connect cpu(Affinity But UCHAR. when use you must Cast Affinity)
+//
+UCHAR HalpIntConnectPattern[R98B_MAX_CPU][NUMBER_OF_IPR_BIT]={
+// At 1 Processor System
+{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,
+ 0,0,0x0,0x1,1,1,1,1,0,0,0,0,0,0,0,0, 0x1,0x1,0x1,0x1,0,0,0,0,0x1,0x1,0,0,0,0x1,0x1,0},
+// At 2 Processor System
+// {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1, // snes kai
+{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,2,2,2,2,0,0,0,2,2,2,
+ 0,0,0x0,0x3,1,1,1,1,0,0,0,0,0,0,0,0, 0x3,0x3,0x3,0x3,0,0,0,0,0x3,0x3,0,0,0,0x3,0x3,0},
+// At 3 Processor System
+{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,4,4,2,2,0,0,0,2,4,4,
+ 0,0,0x0,0x7,1,1,1,1,0,0,0,0,0,0,0,0, 0x7,0x7,0x7,0x7,0,0,0,0,0x7,0x7,0,0,0,0x7,0x7,0},
+// At 4 Processor System
+{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,4,8,2,2,0,0,0,2,4,8,
+ 0,0,0x0,0xF,1,1,1,1,0,0,0,0,0,0,0,0, 0xF,0xF,0xF,0xF,0,0,0,0,0xf,0xf,0,0,0,0xF,0xF,0}
+};
+
+
+extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU];
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+ ULONG ipr;
+ PULONG Vp;
+ ULONG NumCpu;
+ KIRQL OldIrql;
+ ULONG Value[2];
+ ULONG IntNo;
+
+ ULONG MagBuffer;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ //
+ // In This Time I know Number Of CPU.
+ //
+ NumCpu = **((PULONG *)(&KeNumberProcessors));
+
+ //
+ // Number to Array Index.
+ //
+ NumCpu--;
+
+
+ for(ipr=0;ipr<64; ipr++){
+ if((HalpIntConnectPattern[NumCpu][ipr] & (1 <<PCR->Number))== 0 ){
+ //
+ // This Interrupt Connect Target CPU Not for me. So Set
+ // ~~~
+ Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][ HalpIntLevelofIpr[HalpMachineCpu][ipr] ].Enable);
+
+ if( ipr < 32){
+ Vp[0] &= ~(0x1 << ipr);
+ Vp[1] &= 0xffffffff;
+ }else{
+ Vp[0] &= 0xffffffff;
+ Vp[1] &= ~(0x1 << (ipr-32));
+ }
+
+ }
+ }
+ //
+ // Enable Interrupt at Columnbs
+ // At This Interrupt Mask is perfact.
+ //
+ Value[0] = (ULONG)0xFFFFFFFF;
+ Value[1] = (ULONG)0xFFFFFFFF;
+ //
+ // ReBuild Mask
+ //
+ for(IntNo=0 ; IntNo< 6 ;IntNo++){
+ Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][IntNo].Enable);
+ Value[0] &= ~Vp[0];
+ Value[1] &= ~Vp[1];
+
+ }
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR;
+ WRITE_REGISTER_ULONG( Vp++,Value[0]);
+ WRITE_REGISTER_ULONG( Vp, Value[1]);
+
+ // 2CPU
+ // Reset Interrupt of do Mask.
+ //
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->IPRR;
+ WRITE_REGISTER_ULONG( Vp++,Value[0]);
+ WRITE_REGISTER_ULONG( Vp, Value[1]);
+
+ //
+ // ECC ERROR CHECK START
+ //
+#if 1 // ECC 1bit error/Multi bit error enable
+ if (PCR->Number == 0) {
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){
+ MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI )
+;
+ MagBuffer &= ECC_ERROR_ENABLE;
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, MagBuffer )
+;
+ }
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){
+ MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI )
+;
+ MagBuffer &= ECC_ERROR_ENABLE;
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, MagBuffer )
+;
+ }
+ }
+#endif
+
+ KeLowerIrql(OldIrql);
+
+#if DBG
+ DbgPrint("All Pro 0 CPU= %x :MKR = Low = 0x%x High = 0x%x\n",PCR->Number,Value[0],Value[1]);
+#endif
+
+
+
+ //
+ // Restart all timer interrupt. because, generate interrupt for same time
+ // All CPU
+
+ if (PCR->Number == 0) {
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->TCIR,
+ TCIR_ALL_CLOCK_RESTART| 0x000f0000);
+ }
+
+
+#if 0
+ //
+ // F/W Setup. So Never Fix.
+ //
+ if (PCR->Number == 0) {
+ IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->PERRI);
+ DbgPrint(" PONCE_PERRI 0= 0x%x\n",IntNo);
+ IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->PERRM);
+ DbgPrint(" PONCE_PERRM 0= 0x%x\n",IntNo);
+#if 0
+ //
+ // Ponce #0 PCI Error Eif Enable.
+ // Future implement.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRM,PONCE_PXERR_PMDER);
+ //
+ // PCI Error Eif inhibit off.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRI,PONCE_PXERR_PMDER);
+#else //test kbnes
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM));
+ //
+ // PCI Error Eif inhibit off.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRI, PONCE_PXERR_PPERM));
+
+
+#endif
+ //
+ // Ponce #1 PCI Error Eif Enable.
+ // Future implement.
+ //
+#if 0
+
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM));
+ //
+ // PCI Error Eif inhibit off.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRI, (PONCE_PXERR_PMDER|PONCE_PXERR_PPERM));
+#else //SNES tst
+ IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->PERRI);
+ DbgPrint(" PONCE_PERRI 1= 0x%x\n",IntNo);
+ IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->PERRM);
+ DbgPrint(" PONCE_PERRM 1= 0x%x\n",IntNo);
+
+
+
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM));
+ //
+ // PCI Error Eif inhibit off.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRI, PONCE_PXERR_PPERM));
+
+
+#endif
+ }
+#endif
+
+ //
+ // On phase 0 EIF_VECTOR: direct connect by hal. so early interrupt imprement!!
+ // After This time. Eif Vector can share with ather device( MRC Driver)
+ //
+
+ KeInitializeInterrupt(
+ &HalpEifInterrupt[PCR->Number],
+ HalpHandleEif,
+ NULL,
+ NULL,
+ EIF_VECTOR,
+ (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][EIF_VECTOR - DEVICE_VECTORS]),
+ (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][EIF_VECTOR - DEVICE_VECTORS]),
+ LevelSensitive,
+ TRUE,
+ PCR->Number,
+ FALSE
+ );
+
+ KeConnectInterrupt( &HalpEifInterrupt[PCR->Number]);
+
+ PCR->InterruptRoutine[UNDEFINE_TLB_VECTOR] = (PKINTERRUPT_ROUTINE)HalpIoTlbLimitOver;
+
+ // F/W Setup. So Never Fix.
+ //
+ //
+ // Columnbs Error Eif and NMI Enable.
+ // Future implement.
+ //
+ // WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK,0x0);
+ //
+ // inhibit off.
+ //
+ // WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRI,0x0);
+
+ //
+ // If the number of processors in the host configuration is one,
+ // all Interrupt connect processor 0.
+ //
+
+#if DBG
+ DbgPrint("SecondLevelIcacheFillSize = 0x%x\n",PCR->SecondLevelIcacheFillSize);
+#endif
+
+ return HalpConnectIoInterrupt(NumCpu);
+
+}
+
+//
+//
+// Which MPU X IPR Bit X Connect
+// N.B
+// All CPU Execute!!
+//
+
+BOOLEAN
+HalpConnectIoInterrupt(
+ IN ULONG NumCpu
+ )
+{
+ PULONG IntTg;
+ PUCHAR Cnpttn;
+ UCHAR Number;
+ ULONG OldIntGValue;
+ ULONG ipr;
+
+
+ ULONG PhysicalNumber;
+
+ Cnpttn = &HalpIntConnectPattern[NumCpu][0];
+ Number = PCR->Number;
+
+ //
+ // If Interrupt for me!! then do so myself.
+ // Ipr 44 of max device interrupt. upper 44 is ipi or clock or profile
+ // or eif. etc...
+ //
+ KiAcquireSpinLock(&HalpIprInterruptLock);
+ for(ipr=0;ipr< 43;ipr++){
+ //
+ // BroadCast Type Implement OK!!.
+ // N.B
+ // But INT Dispatcher not Supported.
+ //
+ if(Cnpttn[ipr] & (0x1 << Number)){
+ HalpResetValue[ipr].Cpu = (UCHAR)Number;
+ IntTg = (PULONG) &PONCE_CNTL(HalpResetValue[ipr].Ponce)->INTTG[10 - HalpResetValue[ipr].IntGResetBit];
+
+#if 0
+ //
+ // Broadcast But Imprement Not Complete.
+ //
+ //
+ OldIntGValue = READ_REGISTER_ULONG( IntTg );
+ OldIntGValue &= 0xf0;
+#else
+ //
+ // Device Interrupt Connect to 1 CPU Only.
+ // Not Broadcast
+ //
+ OldIntGValue = 0x0;
+#endif
+
+ PhysicalNumber=HalpLogicalCPU2PhysicalCPU[Number];
+ WRITE_REGISTER_ULONG(
+ IntTg,
+ (OldIntGValue | (0x10 << PhysicalNumber))
+ );
+ }
+ }
+ KiReleaseSpinLock(&HalpIprInterruptLock);
+ //
+ // if eisa interrupt connect to me!
+ // Initialize EISA bus interrupts.
+ //
+ if(HalpResetValue[EISA_DISPATCH_VECTOR - DEVICE_VECTORS].Cpu == Number){
+ HalpCreateEisaStructures();
+ }
+
+ return TRUE;
+
+}
+//
+// Default All Interrupt Disable.
+//
+ULONG HalpInterruptPonceMask[PONCE_MAX] = { 0x000007ff,0x000007ff,0x000007ff};
+
+//
+//
+// This function Enable or Disable Interrupt connect to Ponce.
+//
+BOOLEAN
+HalpInterruptFromPonce(
+ IN ULONG Vector,
+ IN ULONG Enable
+ )
+{
+ ULONG Ponce;
+ ULONG IprBitNum;
+
+ IprBitNum = Vector - DEVICE_VECTORS; //SNES
+ //
+ // Check interrupt was connected to ponce!!.
+ //
+ if( HalpResetValue[IprBitNum].IntGResetBit > INTSA0)
+ return FALSE;
+
+ Ponce = HalpResetValue[IprBitNum].Ponce;
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ // Bit X
+ // 1: Enable Interrupt
+ // 0: Disable Interrupt
+ if(Enable){
+ HalpInterruptPonceMask[Ponce] &= (ULONG) ~(0x1 <<
+ HalpResetValue[IprBitNum].IntGResetBit);
+ }else{
+ HalpInterruptPonceMask[Ponce] |= (ULONG) (0x1 <<
+ HalpResetValue[IprBitNum].IntGResetBit);
+
+ }
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTM,HalpInterruptPonceMask[Ponce]);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+}
diff --git a/private/ntos/nthals/halr98b/mips/cacherr.h b/private/ntos/nthals/halr98b/mips/cacherr.h
new file mode 100644
index 000000000..94e009714
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/cacherr.h
@@ -0,0 +1,225 @@
+//
+// Error Log Offset
+//
+
+#ifndef _CHELOG_H
+#define _CHELOG_H
+
+//
+// For R10000
+//
+
+#define R10_FATAL_ERR 0x00
+#define R10_NORMAL_ERR 0x80
+
+#define R10_ICHE 0x80
+#define R10_DCHE 0x81
+#define R10_SCHE_2BIT 0x82
+#define R10_SYSAD_PARITY 0x83
+#define R10_CHER_IN_CHER 0x84
+#define R10_SCHE_1BIT 0x86
+
+#define R10_St2 0x0a
+#define R10_St3 0x0b
+#define R10_ErrEPC 0x20
+#define R10_Status 0x28
+#define R10_Config 0x2c
+#define R10_PRid 0x30
+#define R10_CacheEr 0x34
+#define R10_BrDiag 0x38
+#define R10_PC_Ctrl 0x40
+#define R10_PC_Count 0x44
+#define R10_p_count 0x48
+#define R10_s_count 0x4c
+#define R10_CheAdd_1bit 0x50
+#define R10_CheAdd 0x54
+#define R10_TagHi 0x58
+#define R10_TagLo 0x5c
+#define R10_Cache_data0_Hi 0x60
+#define R10_Cache_data0_Lo 0x64
+#define R10_Cache_data1_Hi 0x68
+#define R10_Cache_data1_Lo 0x6c
+#define R10_Cache_data2_Hi 0x70
+#define R10_Cache_data2_Lo 0x74
+#define R10_Cache_data3_Hi 0x78
+#define R10_Cache_data3_Lo 0x7c
+#define R10_Cache_data4_Hi 0x80
+#define R10_Cache_data4_Lo 0x84
+#define R10_Cache_data5_Hi 0x88
+#define R10_Cache_data5_Lo 0x8c
+#define R10_Cache_data6_Hi 0x90
+#define R10_Cache_data6_Lo 0x94
+#define R10_Cache_data7_Hi 0x98
+#define R10_Cache_data7_Lo 0x9c
+#define R10_ECC0 0xa0
+#define R10_ECC1 0xa4
+#define R10_ECC2 0xa8
+#define R10_ECC3 0xac
+#define R10_ECC4 0xb0
+#define R10_ECC5 0xb4
+#define R10_ECC6 0xb8
+#define R10_ECC7 0xbc
+
+#define R10_BrDiag_Hi 0x38
+#define R10_BrDiag_Lo 0x3c
+
+/*
+ * R10000 CacheErr register bit structure define
+ */
+#define R10CHE_KIND_MASK 0xc0000000 /* Kind of Cache error */
+#define R10CHE_KIND_I 0x00000000 /* I-Cache error */
+#define R10CHE_KIND_D 0x40000000 /* D-Cache error */
+#define R10CHE_KIND_S 0x80000000 /* S-Cache error */
+#define R10CHE_KIND_Y 0xc0000000 /* System I/F error */
+#define R10CHE_EW 0x20000000 /* Duplicated cache error */
+#define R10CHE_EE 0x10000000 /* Fatal error(D/Y) */
+#define R10CHE_D_MASK 0x0c000000 /* Data aray(I/D/S/Y) */
+#define R10CHE_D_WAY0 0x04000000 /* way0 */
+#define R10CHE_D_WAY1 0x08000000 /* way1 */
+#define R10CHE_TA_MASK 0x03000000 /* Tag Address aray(I/D/S) */
+#define R10CHE_TA_WAY0 0x01000000 /* way0 */
+#define R10CHE_TA_WAY1 0x02000000 /* way1 */
+#define R10CHE_TS_MASK 0x00c00000 /* Tag State aray(I/D) */
+#define R10CHE_TS_WAY0 0x00400000 /* way0 */
+#define R10CHE_TS_WAY1 0x00800000 /* way1 */
+#define R10CHE_TM_MASK 0x00300000 /* Tag Mod aray(D) */
+#define R10CHE_TM_WAY0 0x00100000 /* way0 */
+#define R10CHE_TM_WAY1 0x00200000 /* way1 */
+#define R10CHE_SA 0x02000000 /* SysAD address parity error */
+#define R10CHE_SC 0x01000000 /* SysCmd parity error */
+#define R10CHE_SR 0x00800000 /* SysResp parity error */
+#define R10CHE_PIDX_BLK 0x00003fC0 /* Primary block index */
+#define R10CHE_PIDX_DW 0x00003ff8 /* Primary double word index */
+#define R10CHE_SIDX_BLK 0x007fffC0 /* Secondary block index */
+#define R10CHE_BLK_SHIFT 6 /* block index shift */
+#define R10CHE_DW_SHIFT 3 /* double word index shift */
+
+/*
+ * R10000 Cache Instruction Opecode define
+ */
+#define IndexInvalidate_I 0x00
+#define IndexLoadTag_I 0x04
+#define IndexStoreTag_I 0x08
+#define HitInvalidate_I 0x10
+#define CacheBarrier_I 0x14
+#define IndexLoadData_I 0x18
+#define IndexStoreData_I 0x1c
+
+#define IndexWriteBack_D 0x01
+#define IndexLoadTag_D 0x05
+#define IndexStoreTag_D 0x09
+#define HitInvalidate_D 0x11
+#define HitWriteBack_D 0x15
+#define IndexLoadData_D 0x19
+#define IndexStoreData_D 0x1d
+
+#define IndexWriteBack_S 0x03
+#define IndexLoadTag_S 0x07
+#define IndexStoreTag_S 0x0b
+#define HitInvalidate_S 0x13
+#define HitWriteBack_S 0x17
+#define IndexLoadData_S 0x1b
+#define IndexStoreData_S 0x1f
+
+
+
+#define branchdiag $22
+
+#if 0
+/* dmfc0 rt, rd */
+#define DMFC0( rt, rd ) \
+ .word 0x40200000 | (rt<<16) | (rd<<11)
+/* dmfc0 rt, rd */
+#define DMTC0( rt, rd ) \
+ .word 0x40a00000 | (rt<<16) | (rd<<11)
+/* mfpc rt, reg */
+#define MFPC( rt, reg ) \
+ .word 0x4000c801 | (rt<<16) | (reg<<1)
+/* mtpc rt, reg */
+#define MTPC( rt, reg ) \
+ .word 0x4080c801 | (rt<<16) | (reg<<1)
+/* mfps rt, reg */
+#define MFPS( rt, reg ) \
+ .word 0x4000c800 | (rt<<16) | (reg<<1)
+/* mtps rt, reg */
+#define MTPS( rt, reg ) \
+ .word 0x4080c800 | (rt<<16) | (reg<<1)
+#endif
+
+
+//
+// For R4400
+//
+
+#define EPC_cpu 0x0
+#define Psr_cpu 0x8
+#define CFG_cpu 0xc
+#define PRID_cpu 0x10
+#define CHERR_cpu 0x14
+#define CheAdd_p 0x18
+#define CheAdd_s 0x1c
+#define TagLo_p 0x20
+#define ECC_p 0x24
+#define TagLo_s 0x28
+#define ECC_s 0x2c
+#define data_s 0x30
+#define Good_data_s 0x38
+#define Good_TagLo_s 0x40
+#define Good_ECC_s 0x44
+#define tag_synd_s 0x48
+#define data_synd_s 0x4c
+#define xkphs_share 0x50
+//Error Code
+
+#define ICHE_EX 0x00
+#define ICHE_TAG 0x01
+#define ICHE_DAT 0x02
+#define ICHE_EB 0x03
+#define ICHE_UNKNOWN 0x0f
+
+#define DCHE_TAG_EX 0x10
+#define DCHE_TAG_CLEAN 0x11
+#define DCHE_TAG_DIRTY 0x12
+#define DCHE_TAG_UNKNOW 0x13
+#define DCHE_DAT_EX 0x14
+#define DCHE_DAT_DIRTY 0x16
+#define DCHE_UNKNOWN 0x1f
+
+#define SCHE_TAG_1BIT 0x20
+#define SCHE_TAG_2BIT 0x21
+#define SCHE_TAG_UNKNOW 0x23
+#define SCHE_DAT_EX 0x24
+#define SCHE_DAT_INV 0x25
+#define SCHE_DAT_1BIT 0x26
+#define SCHE_DAT_2BIT_C 0x27
+#define SCHE_DAT_2BIT_D 0x28
+#define SCHE_DAT_UNKNOW 0x29
+#define SCHE_UNKNOWN 0x2f
+
+#define SYSAD_PARITY 0x30
+// REG MASK
+
+#define CHERR_ER 0x80000000
+#define CHERR_EC 0x40000000
+#define CHERR_ED 0x20000000
+#define CHERR_ET 0x10000000
+#define CHERR_ES 0x08000000
+#define CHERR_EE 0x04000000
+#define CHERR_EB 0x02000000
+#define CHERR_EI 0x01000000
+#define CHERR_EW 0x00800000
+#define CHERR_SIDX 0x0003fff8
+#define CHERR_SIDX2 0x0003fff8
+#define CHERR_PIDX 0x00000007
+
+#define R4CT_PSTAT_MASK 0x000000c0
+#define R4CT_PSTAT_DRE 0x000000c0
+#define R4CT_PTAG_MASK 0xffffff00
+#define R4CT_SSTAT_MASK 0x00001c00
+#define R4CT_SSTAT_DRE 0x00001400
+#define R4CT_SSTAT_INV 0x00000000
+#define R4CT_STAG_MASK 0xffffe000
+
+#define CHERR_PSHF 12
+
+#endif /* _CHELOG_H */
diff --git a/private/ntos/nthals/halr98b/mips/cacherr.s b/private/ntos/nthals/halr98b/mips/cacherr.s
new file mode 100644
index 000000000..bcb23554f
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/cacherr.s
@@ -0,0 +1,1435 @@
+// "@(#) NEC cacherr.s 1.2 94/10/17 11:02:44"
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// N.B. All the code in this routine MUST run in KSEG1 and reference
+// data only in KSEG1 until which time as any cache errors have
+// been corrected.
+//
+// N.B. This routine is NOT COMPLETE. All cache errors result in a
+// soft reset.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "cacherr.h"
+
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved integer register at - a3
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+
+ SBTTL("Cache Error Handling")
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1. If the error is a single bit ECC error in the second
+// level data cache or the error is in the primary instruction cache,
+// then the error is corrected and execution is continued. Otherwise,
+// a fatal system error has occured and control is transfered to the
+// soft reset vector.
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCacheErrorRoutine)
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+ .set noat
+//K001
+// la k0,SavedAt // get address of register save area
+// li k1,KSEG1_BASE // convert address of KSEG1 address
+// or k0,k0,k1 //
+// sw AT,0(k0) // save registers AT - a3
+// sw v0,4(k0) //
+// sw v1,8(k0) //
+// sw a0,12(k0) //
+// sw a1,16(k0) //
+// sw a2,20(k0) //
+ li k1,0xb9800310 // Get CPU#
+ lw k0,0x0(k1)
+ li k1,0x0f000000
+ and k0,k0,k1
+ srl k0,k0,24
+ li k1,0x4
+ sub k0,k0,k1
+ mtc0 k0,lladdr
+ nop
+ nop
+ nop
+ nop
+ li k1,0xd
+ sll k0,k0,k1
+ la k1,HalpCacheErrorStack
+ add k0,k0,k1
+ add k0,k0,0x2000
+ li k1,KSEG1_BASE
+ or k0,k0,k1
+ subu k0,k0,TrapFrameLength
+#if !defined(NT_40)
+ sw sp,TrIntSp(k0) // save integer register sp
+ move sp,k0 // set new stack pointer
+ cfc1 k1,fsr // get floating status register
+ sw gp,TrIntGp(sp) // save integer register gp
+ sw s8,TrIntS8(sp) // save integer register s8
+ sw k1,TrFsr(sp) // save current FSR
+ mfc0 k0,psr
+ nop
+ nop
+ nop
+ sw k0,TrPsr(sp) // save processor state
+ sw ra,TrIntRa(sp) // save integer register ra
+ move s8,sp
+ sw AT,TrIntAt(s8) // save assembler temporary register
+ sw v0,TrIntV0(s8) // save integer register v0
+ sw v1,TrIntV1(s8) // save integer register v1
+ sw a0,TrIntA0(s8) // save integer registers a0 - a3
+ sw a1,TrIntA1(s8) //
+ sw a2,TrIntA2(s8) //
+ sw a3,TrIntA3(s8) //
+ sw t0,TrIntT0(s8) // save integer registers t0 - t2
+ sw t1,TrIntT1(s8) //
+ sw t2,TrIntT2(s8) //
+ sw t3,TrIntT3(s8) // save integer register t3 - t9
+ sw t4,TrIntT4(s8) //
+ sw t5,TrIntT5(s8) //
+ sw t6,TrIntT6(s8) //
+ sw t7,TrIntT7(s8) //
+ sw t8,TrIntT8(s8) //
+ sw t9,TrIntT9(s8) //
+ mflo t3 // get multiplier/quotient lo and hi
+ mfhi t4 //
+ sw t3,TrIntLo(s8) // save multiplier/quotient lo and hi
+ sw t4,TrIntHi(s8) //
+ mfc0 a2,errorepc
+ nop
+ nop
+ nop
+ sw a2,TrFir(s8) // save exception PC
+#else
+ sd sp,TrXIntSp(k0) // save integer register sp
+ move sp,k0 // set new stack pointer
+ cfc1 k1,fsr // get floating status register
+ sd gp,TrXIntGp(sp) // save integer register gp
+ sd s8,TrXIntS8(sp) // save integer register s8
+ sw k1,TrFsr(sp) // save current FSR
+ mfc0 k0,psr
+ nop
+ nop
+ nop
+ sw k0,TrPsr(sp) // save processor state
+ sd ra,TrXIntRa(sp) // save integer register ra
+ move s8,sp
+ sd AT,TrXIntAt(s8) // save assembler temporary register
+ sd v0,TrXIntV0(s8) // save integer register v0
+ sd v1,TrXIntV1(s8) // save integer register v1
+ sd a0,TrXIntA0(s8) // save integer registers a0 - a3
+ sd a1,TrXIntA1(s8) //
+ sd a2,TrXIntA2(s8) //
+ sd a3,TrXIntA3(s8) //
+ sd t0,TrXIntT0(s8) // save integer registers t0 - t2
+ sd t1,TrXIntT1(s8) //
+ sd t2,TrXIntT2(s8) //
+ sd t3,TrXIntT3(s8) // save integer register t3 - t7
+ sd t4,TrXIntT4(s8) //
+ sd t5,TrXIntT5(s8) //
+ sd t6,TrXIntT6(s8) //
+ sd t7,TrXIntT7(s8) //
+ sd s0,TrXIntS0(s8) // save integer registers s0 - s7
+ sd s1,TrXIntS1(s8) //
+ sd s2,TrXIntS2(s8) //
+ sd s3,TrXIntS3(s8) //
+ sd s4,TrXIntS4(s8) //
+ sd s5,TrXIntS5(s8) //
+ sd s6,TrXIntS6(s8) //
+ sd s7,TrXIntS7(s8) //
+ sd t8,TrXIntT8(s8) // save integer registers t8 - t9
+ sd t9,TrXIntT9(s8) //
+ mflo t3 // get multiplier/quotient lo and hi
+ mfhi t4 //
+ sd t3,TrXIntLo(s8) // save multiplier/quotient lo and hi
+ sd t4,TrXIntHi(s8) //
+ mfc0 a2,errorepc
+ nop
+ nop
+ nop
+ sw a2,TrFir(s8) // save exception PC
+
+#endif
+ move a3,k0
+
+//
+// Get the current processor state and cache error register, and check
+// if the error can be corrected.
+//
+
+ mfc0 a0,lladdr
+ nop
+ nop
+ nop
+ li t1,0x1 // Log Format For FW
+ sll t3,t1,a0
+ li t1,0xb9800388 // NVRAM enable
+ li t0,0x00040000
+ sw t0,0x0(t1)
+ li t0,0xbf09fd64 // NVRAM log For FW
+ lw t1,0x0(t0)
+ or t3,t1,t3
+ sb t3,0x0(t0)
+#if 0
+ li t1,0xb9800388 // NVRAM disable
+ li t0,0x04040000
+ sw t0,0x0(t1)
+#endif
+ mfc0 a1,cacheerr // get cache error state
+ nop
+ nop
+ nop
+ la t1,HalpCacheErrorHwLog
+ li t2,KSEG1_BASE
+ or t1,t1,t2
+//
+// Check CPU
+//
+
+// li a1,0x00000000
+
+ mfc0 t2,prid
+ nop
+ nop
+ nop
+ nop
+ and t2,t2,0xff00 // isolate processor id
+ xor t2,t2,0x0900 // check if r10000 processor
+ beq zero,t2,t5clog // if eq, r10000 processor
+
+
+
+//
+// R4400 log
+//
+
+ addi t2,t1,0x20
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+//
+// The following code is temporary and will be removed when full cache
+// error support is included.
+//
+// ****** temp ******
+//
+// K001 For cacheErrorLog
+
+// jal HalpCacheErrorLog
+// nop
+//
+// b SoftReset // ****** all error soft rest
+/********************************
+ * cache error routine
+ *
+ * v0 = return code (return value)
+ *
+ * a0 = log field address (argument)
+ * a1 = error code address (argument)
+ * a2 = TagLo reg
+ * a3 = ECC reg
+ * t0 = cache virtual address
+ * t1 = Cache error reg
+ * t2 = d-cache virtual address for s-cache
+ * t3 = xkphs address
+ * t4 - t7 temprary data
+ * t8 = a2(TagLo) save
+ * t9 = return address
+ ********************************/
+//LEAF(che_log)
+
+ .set noreorder
+// DMFC0 (T8, D_ERROREPC)
+ move v1,a0 // CPU #
+
+ move a0,t2 // Data addr
+ move t2,a1
+ move a1,t1 // Header addr
+ move t1,t2 // CacheError REg
+ move t8,a2 // Error Epc
+// mfc0 t7, C0_SR
+ move t7,a3 // PSR
+ mfc0 t6, config
+ mfc0 t5, prid
+// Log
+ sw t8,EPC_cpu(a0)
+ sw t7,Psr_cpu(a0)
+ sw t6,CFG_cpu(a0)
+ sw t5,PRID_cpu(a0)
+ sw t1,CHERR_cpu(a0)
+// mfc0 t1, C0_CACHEERR
+// or t4, t7, (SR_DE | SR_KX | SR_ERL)
+ or t4,t7,(0x1<<PSR_DE)
+ mtc0 t4, psr
+ nop
+ nop
+ nop
+ .set reorder
+
+ and t4, t1, CHERR_EE # sysad parity error?
+ bnez t4, sysad_log
+
+ and t4, t1, CHERR_EC # primary cache error?
+ bnez t4, sche_log
+
+ and t4, t1, CHERR_ER # p-inst cache error?
+ bnez t4, dche_log
+
+/*
+ * primary instruction cache parity error
+ */
+ and t0, t1, CHERR_PIDX # K1(p) address
+// sll t0, t0,CHERR_PSHFT
+// sll t0, t0,12
+ and t4, t1, CHERR_SIDX2
+ or t0, t4
+ or t0, KSEG0_BASE
+
+ .set noreorder
+ cache 4, 0(t0) # I-cache index load tag
+ nop
+ nop
+ nop
+ mfc0 a2, taglo
+ mfc0 a3, ecc
+ .set reorder
+
+ sw t0, CheAdd_p(a0) # save cache address
+ sw a2, TagLo_p(a0) # save TagLo
+ sw a3, ECC_p(a0) # save ECC
+
+ and t4, t1, CHERR_ES # external reference?
+ bnez t4, iche_log_ex # then degrade error
+
+ and t4, t1, CHERR_EB # also occured data error?
+ bnez t4, iche_log_eb # then fatal error
+
+ and t4, t1, CHERR_ET # tag error?
+ bnez t4, iche_log_tag # then fatal error
+
+ and t4, t1, CHERR_ED # data error?
+ bnez t4, iche_log_dat # then degrade error
+
+// li t4, FATAL_ERR # else fatal error
+// sw t4, (a1)
+ li v0, ICHE_UNKNOWN
+ j iche_log_end
+
+iche_log_dat:
+// # li t4, RECOVER_ERR
+// # sw t4, (a1)
+ li v0, ICHE_DAT
+ j iche_log_end
+
+iche_log_tag:
+// # li t4, FATAL_ERR
+// # sw t4, (a1)
+ li v0, ICHE_TAG
+ j iche_log_end
+
+iche_log_eb:
+// li t4, FATAL_ERR
+ sw t4, (a1)
+ li v0, ICHE_EB
+ j iche_log_end
+
+iche_log_ex:
+// # li t4, RECOVER_ERR
+// # sw t4, (a1)
+ li v0, ICHE_EX
+
+iche_log_end:
+ .set noreorder
+ mtc0 zero,taglo
+ nop
+ cache 8, 0(t0) //# I-cache index store tag(invalid)
+ cache 20,0(t0) //# I-cache fill
+ cache 8, 0(t0) //# I-cache index store tag(invalid)
+ .set reorder
+ j che_log_end
+
+/*
+ * primary data cache parity error
+ */
+dche_log:
+ and t0, t1, CHERR_SIDX2 //# K1(p) address
+ or t0, KSEG0_BASE
+
+dche_log_loop:
+ .set noreorder
+ cache 5, 0(t0) //# D-cache index load tag
+ nop
+ nop
+ nop
+ mfc0 a2, taglo
+ mfc0 a3, ecc
+ .set reorder
+
+ sw t0, CheAdd_p(a0) //# save cache address
+ sw a2, TagLo_p(a0) //# save TagLo
+ sw a3, ECC_p(a0) //# save ECC
+
+ and t4, t1, CHERR_ET //# tag error?
+ beqz t4, dche_log_dat //# else data error
+//#
+//# Tag field error
+//#
+ jal tag_parity_chk //# check tag parity
+ bnez v0, dche_tag_parity
+
+ add t0, 0x1000 //# check next PIDX
+ bltu t0, 0x80004000, dche_log_loop
+ //# less than 16K then loop
+// li t4, FATAL_ERR # else fatal error
+// sw t4, (a1)
+ li v0, DCHE_TAG_UNKNOW
+ j che_log_end
+
+dche_tag_parity:
+ and t4, t1, CHERR_ES //# external reference?
+ bnez t4, dche_tag_ex //# then fatal error
+
+ and t4, a2, R4CT_PSTAT_MASK //# dirty?
+ beq t4, R4CT_PSTAT_DRE, dche_tag_dirty
+ beqz t4, dche_tag_clean
+
+ and t4, a2, R4CT_PTAG_MASK //# k1(s) address
+ sll t4, 4
+ and t5, t1, CHERR_SIDX2
+ or t4, t5
+ and t4, CHERR_SIDX
+ or t4, KSEG0_BASE
+
+ .set noreorder
+ cache 7, 0(t4) //# S-cache index load tag
+ nop
+ nop
+ nop
+ mfc0 t5, taglo
+ mfc0 t6, ecc
+ .set reorder
+
+ sw t4, CheAdd_s(a0) //# save cache address
+ sw t5, TagLo_s(a0) //# save TagLo
+ sw t6, ECC_s(a0) //# save ECC
+
+ and t7, t5, R4CT_SSTAT_MASK //# dirty?
+ beq t7, R4CT_SSTAT_DRE, dche_tag_dirty
+
+dche_tag_clean:
+// li t4, RECOVER_ERR
+// sw t4, (a1)
+ li v0, DCHE_TAG_CLEAN
+ j dche_log_end
+
+dche_tag_dirty:
+// li t4, FATAL_ERR
+// sw t4, (a1)
+ li v0, DCHE_TAG_DIRTY
+ j dche_log_end
+
+dche_tag_ex:
+// li t4, FATAL_ERR
+// sw t4, (a1)
+ li v0, DCHE_TAG_EX
+ j dche_log_end
+
+ //#
+ //# Data field error
+// #
+dche_log_dat:
+ and t4, t1, CHERR_ED //# DATA error?
+ bnez t4, dche_dat //# then data error
+
+// li t4, FATAL_ERR //# else fatal error
+// sw t4, (a1)
+ li v0, DCHE_UNKNOWN
+ j che_log_end
+
+dche_dat:
+ and t4, t1, CHERR_ES //# external reference?
+ beqz t4, dche_dat_chk //# else data error check
+
+// li t4, FATAL_ERR //# then fatal error
+// sw t4, (a1)
+ li v0, DCHE_DAT_EX
+ j che_log_end
+
+dche_dat_chk:
+/* For NT
+ and t4, a2, R4CT_PSTAT_MASK //# invalid?
+ beqz t4, dche_dat_next
+
+ move t8, a2 //# save TagLo
+
+ and t3, a2, R4CT_PTAG_MASK //# xkphs cached address
+ DSLL32 (T3, T3, 0)
+ DSRL (T3, T3, 28)
+ and t4, t1, CHERR_SIDX2
+ or t3, t4
+ li t4, XKPHYSEGMENT_HI_CCS
+ DSLL32 (T4, T4, 0)
+ or t3, t4
+
+ LD (A2, 0, T3) # load erronious data
+ SD (T3, xkphs_share, A0)
+ SD (A2, data_s, A0)
+
+ # jal dat_parity_chk # check data parity
+ move a2, t8 # resotore TagLo
+ # bnez v0, dche_dat_parity
+
+ .set noreorder
+ cache 1, 0(t0) # D-cache index writevack invalidate
+ lw zero, (t0) # D-cache dummy load
+ mtc0 zero, C0_TAGLO
+ nop
+ cache 9, 0(t0) # D-cache index store tag(invalid)
+ .set reorder
+
+dche_dat_next:
+ add t0, 0x1000 # check next PIDX
+ bltu t0, 0x80004000, dche_log_loop
+ # less than 16K then loop
+
+ li t4, FATAL_ERR # all D-cache error is fatal
+ sw t4, (a1)
+*/
+ li v0, DCHE_DAT_DIRTY
+ j che_log_end
+
+/* comment out 1993.11.12
+
+ li t4, FATAL_ERR # else fatal error
+ sw t4, (a1)
+ li v0, DCHE_DAT_UNKNOW
+ j che_log_end
+
+dche_dat_parity:
+ and t4, a2, R4CT_PSTAT_MASK # dirty?
+ beq t4, R4CT_PSTAT_DRE, dche_dat_dirty
+ bnez t4, dche_dat_dirty
+
+dche_dat_clean:
+ li t4, RECOVER_ERR
+ sw t4, (a1)
+ li v0, DCHE_DAT_CLEAN
+ j dche_log_end
+
+dche_dat_dirty:
+ li t4, FATAL_ERR
+ sw t4, (a1)
+ li v0, DCHE_DAT_DIRTY
+*/
+
+dche_log_end:
+ .set noreorder
+ mtc0 zero,taglo
+ nop
+ cache 9, 0(t0) # D-cache index store tag(invalid)
+ lw zero, (t0) # D-cache dummy load
+ cache 9, 0(t0) # D-cache index store tag(invalid)
+ .set reorder
+
+ j che_log_end
+
+/*
+ * secondary cache error
+ */
+sche_log:
+ and t2, t1, CHERR_PIDX # K1(p) address
+// sll t2, t2,CHERR_PSHFT
+ sll t2, t2,12
+ and t4, t1, CHERR_SIDX2
+ or t2, t4
+ or t2, KSEG0_BASE
+ sw t2, CheAdd_p(a0) # save cache address
+
+ and t4, t1, CHERR_EI # store miss error?
+ beqz t4, sche_log_tag # else tag error
+
+ .set noreorder
+ mtc0 zero, taglo
+ nop
+ cache 9, 0(t2) # D-cache index store tag(invalid)
+ .set reorder
+
+sche_log_tag:
+ and t0, t1, CHERR_SIDX # K1(s) address
+ or t0, KSEG0_BASE
+
+ .set noreorder
+ cache 7, 0(t0) # S-cache index load tag
+ nop
+ nop
+ nop
+ mfc0 a2, taglo
+ mfc0 a3, ecc
+ .set reorder
+
+ sw t0, CheAdd_s(a0) # save cache address
+ sw a2, TagLo_s(a0) # save TagLo
+ sw a3, ECC_s(a0) # save ECC
+
+ and t4, t1, CHERR_ET # tag error?
+ beqz t4, sche_log_dat # else data error
+
+// #
+// # Tag field error
+// #
+ move k0,v1
+ jal tag_ecc_chk //# check tag ecc
+ sw v1, tag_synd_s(a0)
+ move v1,k0
+ sw a2, Good_TagLo_s(a0)
+ beq v0, SCHE_TAG_1BIT, sche_tag_1bit
+ beq v0, SCHE_TAG_UNKNOW, sche_tag_noerr
+
+sche_tag_2bit:
+ and t2, ~63 # 64byte boundary
+ .set noreorder
+ mtc0 zero, taglo
+ nop
+ cache 9, 0(t2) # D-cache index store tag(invalid)
+ cache 9, 16(t2)
+ cache 9, 32(t2)
+ cache 9, 48(t2)
+ cache 11, 0(t0) # S-cache index store tag(invalid)
+ .set reorder
+
+// li t4, FATAL_ERR
+ j che_log_end
+
+sche_tag_1bit:
+ .set noreorder
+ mtc0 a2, taglo
+ nop
+ cache 11, 0(t0) # S-cache index store tag(modify)
+ .set reorder
+
+sche_tag_noerr:
+ and t4, t1, CHERR_ED # data error?
+ beqz t4, che_log_end # else end
+
+sche_log_dat:
+ and t4, t1, CHERR_ED # data error?
+ bnez t4, sche_dat_0
+
+// li t4, FATAL_ERR # else fatal error
+// sw t4, (a1)
+ li v0, SCHE_UNKNOWN
+ j che_log_end
+
+sche_dat_0:
+ and t4, t1, CHERR_ES # external reference?
+// *tmp*
+// beqz t4, sche_dat_1
+
+// li t4, FATAL_ERR # then fatal error
+// sw t4, (a1)
+// li v0, SCHE_DAT_EX
+ li v0, SCHE_DAT_UNKNOW
+ j sche_log_end
+/*
+sche_dat_1:
+ and t4, a2, R4CT_SSTAT_MASK # dirty?
+ bne t4, R4CT_SSTAT_INV, sche_dat_chk
+
+ li t4, FATAL_ERR # then fatal error
+ sw t4, (a1)
+ li v0, SCHE_DAT_INV
+ j sche_log_end
+
+sche_dat_chk:
+ move t8, a2 # save TagLo
+
+ and t3, a2, R4CT_STAG_MASK # xkphs cached address
+ DSLL32 (T3, T3, 0)
+ DSRL (T3, T3, 28)
+ and t4, t1, CHERR_SIDX
+ or t3, t4
+ li t4, XKPHYSEGMENT_HI_CCS
+ DSLL32 (T4, T4, 0)
+ or t3, t4
+
+ LD (A2, 0, T3) # load erronious data
+ SD (T3, xkphs_share, A0)
+ SD (A2, data_s, A0)
+ jal dat_ecc_chk # check data ecc
+
+ sw v1, data_synd_s(a0)
+ SD (A2, Good_data_s, A0)
+ sw a3, Good_ECC_s(a0)
+ move v1, a2 # save good data
+ move a2, t8 # resotore TagLo
+ beq v0, SCHE_DAT_2BIT_C, sche_dat_2bit
+ beq v0, SCHE_DAT_UNKNOW, sche_dat_unknown
+
+ SD (V1, 0, T3) # modified data
+ j sche_log_end
+
+sche_dat_2bit:
+ and t4, a2, R4CT_SSTAT_MASK # dirty?
+ beq t4, R4CT_SSTAT_DRE, sche_dat_dirty
+
+sche_dat_clean:
+ lw zero, (t0) # dummy read
+
+ li t4, RECOVER_ERR
+ sw t4, (a1)
+ j sche_log_end
+
+sche_dat_dirty:
+ li v0, SCHE_DAT_2BIT_D
+ SD (V1, 0, T3) # rewrite error data
+
+sche_dat_unknown:
+ li t4, FATAL_ERR
+ sw t4, (a1)
+*/
+sche_log_end:
+ and t2, ~63 # 64byte boundary
+
+ .set noreorder
+ cache 1, 0(t2) # D-cache index write back invalidate
+ cache 1, 16(t2)
+ cache 1, 32(t2)
+ cache 1, 48(t2)
+ cache 3, 0(t0) # S-cache index write back invalidate
+ .set reorder
+
+ j che_log_end
+
+/*
+ * System address data parity error
+ */
+sysad_log:
+// li t4, FATAL_ERR
+// sw t4, (a1)
+ li v0, SYSAD_PARITY
+
+che_log_end:
+//For Log Function areg
+ move t0,a0
+ move a0,v1
+/* lw a2,EPC_cpu(t0)
+ lw a1,CHERR_cpu(t0)
+*/
+ move a2,v0
+ j HalpCacheErrorLog
+//tmp lw t5, Status(a0) # load Status
+/*
+ .set noreorder
+ mfc0 t4, cacheerr
+ mtc0 t5, psr
+ nop
+ nop
+ .set reorder
+
+// tmp
+ and t4, CHERR_EW # cache error in chelog?
+ beqz t4, che_log_end2
+
+ li t4, FATAL_ERR
+ sw t4, (a1)
+ li v0, CHER_IN_CHER
+
+che_log_end2:
+ j t9 # return
+*/
+// END(che_log)
+
+//
+// R10000 log
+//
+
+t5clog:
+// Get Log data.
+ .set noreorder
+
+ move v1,a0
+ move a0,t1 # a0 = data address
+
+ move t8,a2 # t8 = ErrorEpc
+ move t7,a3 # t7 = Status
+ mfc0 t6,config # t6 = Config
+ mfc0 t5,prid # t5 = Prid
+ move t1,a1 # t1 = cache error state
+
+ or t4,t7,( 1 << PSR_ERL )
+ mtc0 t4,psr
+ dmfc0 t3,branchdiag
+// mfps t2,$0
+// mfpc t0,$0
+ move t2,zero
+ move t0,zero
+
+ .set reorder
+
+// Set log data.
+ sw t8,R10_ErrEPC(a0) # save ErrEPC
+ sw t7,R10_Status(a0) # save Status
+ sw t6,R10_Config(a0) # save Config
+ sw t5,R10_PRid(a0) # save Prid
+ sw t1,R10_CacheEr(a0) # save CacheErr
+ sw t3,R10_BrDiag_Hi(a0) # save BranchDiag
+ srl t4,t3,16
+ srl t4,t4,16
+ sw t4,R10_BrDiag_Lo(a0)
+ sw t2,R10_PC_Ctrl(a0) # save PC Control
+ sw t0,R10_PC_Count(a0) # save PC Count
+
+ li t0,KSEG0_BASE # t0 = cache address
+
+ li t4,R10CHE_KIND_MASK
+ and t4,t1,t4
+
+// I-cache error
+ li v0,R10_ICHE
+ li t5,R10CHE_KIND_I
+ beq t4,t5,t5_iche_log # I-cache parity error?
+
+// D-cache error
+ li v0,R10_DCHE
+ li t5,R10CHE_KIND_D
+ beq t4,t5,t5_dche_log # D-cache parity error?
+
+// S-cache error
+ li v0,R10_SCHE_2BIT
+ li t5,R10CHE_KIND_S
+ beq t4,t5,t5_sche_log # S-cache ECC error?
+
+// SysAd error
+ li v0,R10_SYSAD_PARITY
+// li t4,R10_FATAL_ERR
+// sw t4,(a1)
+ and t4,t1,(R10CHE_SA | R10CHE_SC | R10CHE_SR)
+ bne t4,zero,t5_log_end # Sys I/F fatal error
+
+
+t5_sche_log:
+// Make cache addr
+ and t4,t1,R10CHE_SIDX_BLK
+ or t0,t4
+ and t4,t1,(R10CHE_D_WAY1 | R10CHE_TA_WAY1)
+ sne t4,0
+ or t0,t4 # t0 = cache way address
+
+// TagHi & TagLo
+ .set noreorder
+ cache IndexLoadTag_S, 0(t0) # load tag
+ mfc0 t4,taghi
+ mfc0 t5,taglo
+ .set reorder
+
+ sw t0,R10_CheAdd(a0) # save cache address
+ sw t4,R10_TagHi(a0) # save TagHi
+ sw t5,R10_TagLo(a0) # save TagLo
+
+// Cache data & ECC
+ addu t3,t0,64 # t3 = cacne address increment
+ addu t7,a0,64 # t7 = data save address increment
+ addu t8,a0,32 # t8 = ECC save address increment
+
+load_Scache_loop:
+ subu t3,8 # new cache address
+ subu t7,8 # new data save address
+ subu t8,4 # new ECC save address
+
+ .set noreorder
+ cache IndexLoadData_S,0(t3) # load data
+ mfc0 t4,taghi
+ mfc0 t5,taglo
+ mfc0 t6,ecc
+ .set reorder
+
+ sw t4,R10_Cache_data0_Hi(t7) # save data high
+ sw t5,R10_Cache_data0_Lo(t7) # save data low
+ sw t6,R10_ECC0(t8) # save ECC
+
+ bne t3,t0,load_Scache_loop # 8 times
+
+ .set noreorder
+ cache IndexWriteBack_S,0(t0)
+ .set reorder
+
+// li t4,R10_FATAL_ERR
+// sw t4,(a1)
+
+ j t5_log_end
+
+
+// I-cache
+t5_iche_log:
+// Make cache addr
+ and t4, t1, R10CHE_PIDX_BLK
+ or t0, t4
+ and t4, t1, (R10CHE_D_WAY1 | R10CHE_TA_WAY1 | R10CHE_TS_WAY1)
+ sne t4, 0
+ or t0, t4 # t0 = cache way address
+
+// TagHi & TagLo
+ .set noreorder
+ cache IndexLoadTag_I, 0(t0) # load tag
+ mfc0 t4,taghi
+ mfc0 t5,taglo
+ .set reorder
+
+ sw t0,R10_CheAdd(a0) # save cache address
+ sw t4,R10_TagHi(a0) # save TagHi
+ sw t5,R10_TagLo(a0) # save TagLo
+
+// Cache data & ECC
+ addu t3,t0,64 # t3 = cacne address increment
+ addu t7,a0,64 # t7 = data save address increment
+ addu t8,a0,32 # t8 = ECC save address increment
+
+load_Icache_loop:
+ subu t3,4 # new cache address
+ subu t7,4 # new data save address
+ subu t8,2 # new ECC save address
+
+ .set noreorder
+ cache IndexLoadData_I,0(t3) # load data
+ mfc0 t4,taghi
+ mfc0 t5,taglo
+ mfc0 t6,ecc
+ .set reorder
+
+ sw t5,R10_Cache_data0_Hi(t7) # save data low
+ sll t4,8
+ or t6,t4
+ sh t6,R10_ECC0(t8) # save ECC
+
+ bne t3,t0,load_Icache_loop # 16 times
+
+// Cache invalidate
+ .set noreorder
+ cache IndexInvalidate_I, 0(t0)
+ .set reorder
+
+// li t4,NORMAL_ERR
+// sw t4,(a1)
+
+ j t5_log_end
+
+
+// D-cache
+t5_dche_log:
+// Make cache addr
+ and t4,t1,R10CHE_PIDX_DW
+ or t0,t4
+ and t4,t1,(R10CHE_D_WAY1|R10CHE_TA_WAY1|R10CHE_TS_WAY1|R10CHE_TM_WAY1)
+ sne t4,0
+ or t0,t4 # t0 = cache way address
+
+// TagHi & TagLo
+ .set noreorder
+ cache IndexLoadTag_D,0(t0) # load tag
+ mfc0 t4,taghi
+ mfc0 t5,taglo
+ .set reorder
+
+ sw t0,R10_CheAdd(a0) # save cache address
+ sw t4,R10_TagHi(a0) # save TagHi
+ sw t5,R10_TagLo(a0) # save TagLo
+
+// Cache data & ECC
+ and t0,0xffffffe1 # 32 bytes boundary block
+ addu t3,t0,32 # t3 = cacne address increment
+ addu t7,a0,64 # t7 = data save address increment
+ addu t8,a0,32 # t8 = ECC save address increment
+
+load_Dcache_loop:
+ subu t3,4 # new cache address
+ subu t7,8 # new data save address
+ subu t8,4 # new ECC save address
+
+ .set noreorder
+ cache IndexLoadData_D,0(t3) # load data
+ mfc0 t5,taglo
+ mfc0 t6,ecc
+ .set reorder
+
+ sw t5,R10_Cache_data0_Lo(t7) # save data low
+ sw t6,R10_ECC0(t8) # save ECC
+
+ bne t3,t0,load_Dcache_loop # 8 times
+
+ .set noreorder
+ cache IndexWriteBack_D,0(t0)
+ .set reorder
+
+// li t4,FATAL_ERR
+// sw t4,(a1)
+
+t5_log_end:
+ .set noreorder
+
+ lw t5,R10_Status(a0) # save Status
+ mfc0 t4,cacheerr
+ mtc0 t5,psr
+ nop
+ nop
+
+ .set reorder
+
+ and t4,R10CHE_EW # cache error in chelog?
+ beqz t4,t5_che_log_end
+
+ li v0,R10_CHER_IN_CHER
+// li t4,FATAL_ERR
+// sw t4,(a1)
+
+t5_che_log_end:
+
+ move a1,a0
+ move a2,v0
+ move a0,v1
+ j HalpCacheErrorLog
+
+ .end HalpCacheErrorRoutine
+
+
+/*********************************
+ * cache psued failure
+ *
+ * a0 = error code (argument)
+ ********************************/
+/*
+//LEAF(psued_che)
+
+ LEAF_ENTRY(psude_che)
+
+ .set noreorder
+ li t0, PSUED_ADDRESS # error address
+ lw t1, (t0)
+ mfc0 t4, psr # save SR
+ sw t1, (t0)
+ li t6, 1
+ or t5, t4, (SR_CE | SR_DE)
+ mtc0 t6, ecc # ECC error
+ mtc0 t5, psr # set CE,DE bit
+ .set reorder
+
+ beqz a0, sche_yellow
+ li t1, 0xbadfaced
+ sw t1,(t0) # D-cache parity error
+ j psued_end
+
+sche_yellow:
+ .set noreorder
+ cache 1, (t0) # S-cache 2bit error
+ nop
+psued_end:
+ mtc0 C0_SR,t4 # restore sr
+ j ra
+ nop
+ .set reorder
+
+ END(psued_che)
+*/
+
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+/*********************************
+ * 32bit tag parity check
+ *
+ * v0 = return code (return value)
+ * 0 -- no error
+ * 1 -- error
+ *
+ * a0 = log field address (argument) : not used and not broken
+ * a1 = error code address (argument) : not used and not broken
+ * a2 = check data (argument)
+ * t0 = cache virtual address : not used and not broken
+ * t1 = Cache error reg : not used and not broken
+ * t2 = TagLo reg : not used and not broken
+ * t3 = ECC reg : not used and not broken
+ * t4 - t7 temprary data
+ ********************************/
+LEAF_ENTRY(tag_parity_chk)
+ .set reorder
+ li t4, 1 # target check bit
+ move v0, zero # Hparity bit and return value
+
+ptag_chk_loop:
+ and t5, a2, t4
+ sne t5, 0
+ xor v0, t5 # calcurate parity
+ sll t4, 1
+ bnez t4, ptag_chk_loop # loop 31 times
+ j ra
+
+// END(tag_parity_chk)
+ .end tag_parity_chk
+
+/*********************************
+ * 64bit data parity check
+ *
+ * v0 = return code (return value)
+ * 0 -- no error
+ * 1 -- error
+ *
+ * a0 = log field address (argument) : not used and not broken
+ * a1 = error code address (argument) : not used and not broken
+ * a2 = 64bit data (argument)
+ * a3 = 8bit check data (argument)
+ * t0 = cache virtual address : not used and not broken
+ * t1 = Cache error reg : not used and not broken
+ * t2 = TagLo reg : not used and not broken
+ * t3 = ECC reg : not used and not broken
+ * t4 - t7 temprary data
+ ********************************/
+#if 0
+LEAF(dat_parity_chk)
+ .set reorder
+ li t4, 1 # target check bit
+ li t5, 1 # target parity bit
+ li t6, 8 # byte counter
+ move v0, zero # Hparity bit and return value
+
+pdat_chk_loop:
+ and t7, a2, t4
+ sne t7, 0
+ xor v0, t7 # calcurate parity
+ DSLL (T4, T4, 1)
+
+ subu t6, 1 # if 1byte check end?
+ bnez t6, pdat_chk_skip # else skip
+
+ and t7, a3, t5 # then check parity bit
+ sne t7, 0
+ xor v0, t7 # calcurate parity
+ xor v0, 1 # odd parity, not even 1993.11.7
+ sll t5, 1
+ li t6, 8 # reload byte counter
+
+ beqz v0, pdat_chk_skip # if no parity error then continue
+ j ra # else error return
+
+pdat_chk_skip:
+ bnez t4, pdat_chk_loop # loop 63 times
+ j ra
+
+ END(dat_parity_chk)
+#endif
+
+/*********************************
+ * 2nd cache tag ECC check
+ *
+ * v0 = return code (return value)
+ * 0x20 -- SCHE_TAG_1BIT
+ * 0x21 -- SCHE_TAG_2BIT
+ * 0x23 -- SCHE_TAG_UNKNOW
+ * v1 = tag syndrome (return value)
+ *
+ * a0 = log field address (argument) : not used and not broken
+ * a1 = error code address (argument) : not used and not broken
+ * a2 = 2nd Tag erronious data (argument, return value)
+ * t0 = cache virtual address : not used and not broken
+ * t1 = Cache error reg : not used and not broken
+ * t2 = TagLo reg : not used and not broken
+ * t3 = ECC reg : not used and not broken
+ * t4 - t7 temprary data
+ ********************************/
+LEAF_ENTRY(tag_ecc_chk)
+ .set reorder
+ li t4, 1 # target check bit
+ la t5, tag_synd # tag syndrome data
+ move v1, zero # tag syndrome and return value
+
+// # make syndrome data
+tag_ecc_loop1:
+ and t6, a2, t4
+ beqz t6, tag_ecc_skip0
+ lbu t7, (t5) # make syndrome
+ xor v1, t7 #
+tag_ecc_skip0:
+ sll t4, 1
+ addu t5, 1
+ bnez t4, tag_ecc_loop1 # loop 31 times
+
+ bnez v1, tag_ecc_err # if no error
+ li v0, SCHE_TAG_UNKNOW # then unknown error
+ j ra
+
+// # modify data
+tag_ecc_err:
+ li t4, 1 # target check bit
+ la t5, tag_synd # tag syndrome data
+
+tag_ecc_loop2:
+ lbu t7, (t5) # 1bit error
+ beq v1, t7, tag_ecc_1bit # then 1bit error
+
+ sll t4, 1
+ addu t5, 1
+ bnez t4, tag_ecc_loop2 # loop 31 times
+
+ li v0, SCHE_TAG_2BIT # 2bit error
+ j ra
+
+tag_ecc_1bit:
+ xor a2, t4 # modified data
+ li v0, SCHE_TAG_1BIT # 1bit error
+ j ra
+
+tag_synd:
+ .byte 0x01 # ECC 0 (bit 25)
+ .byte 0x02 # ECC 1 (bit 26)
+ .byte 0x04 # ECC 2 (bit 27)
+ .byte 0x08 # ECC 3 (bit 28)
+ .byte 0x10 # ECC 4 (bit 29)
+ .byte 0x20 # ECC 5 (bit 30)
+ .byte 0x40 # ECC 6 (bit 31)
+ .byte 0x45 # Pidx 0 (bit 19)
+ .byte 0x29 # Pidx 1 (bit 20)
+ .byte 0x51 # Pidx 2 (bit 21)
+ .byte 0x13 # CS 0 (bit 22)
+ .byte 0x49 # CS 1 (bit 23)
+ .byte 0x25 # CS 2 (bit 24)
+ .byte 0x07 # STag 00 (bit 00)
+ .byte 0x16 # STag 01 (bit 01)
+ .byte 0x26 # STag 02 (bit 02)
+ .byte 0x46 # STag 03 (bit 03)
+ .byte 0x0d # STag 04 (bit 04)
+ .byte 0x0e # STag 05 (bit 05)
+ .byte 0x1c # STag 06 (bit 06)
+ .byte 0x4c # STag 07 (bit 07)
+ .byte 0x31 # STag 08 (bit 08)
+ .byte 0x32 # STag 09 (bit 09)
+ .byte 0x38 # STag 10 (bit 10)
+ .byte 0x70 # STag 11 (bit 11)
+ .byte 0x61 # STag 12 (bit 12)
+ .byte 0x62 # STag 13 (bit 13)
+ .byte 0x64 # STag 14 (bit 14)
+ .byte 0x68 # STag 15 (bit 15)
+ .byte 0x0b # STag 16 (bit 16)
+ .byte 0x15 # STag 17 (bit 17)
+ .byte 0x23 # STag 18 (bit 18)
+
+// END(tag_ecc_chk)
+ .end tag_ecc_chk
+#if 0
+/*********************************
+ * 2nd cache 64bit data ECC check
+ *
+ * v0 = return code (return value)
+ * 0x26 -- SCHE_DAT_1BIT
+ * 0x27 -- SCHE_DAT_2BIT_C
+ * 0x29 -- SCHE_DAT_UNKNOW
+ * v1 = data syndrome (return value)
+ *
+ * a0 = log field address (argument) : not used and not broken
+ * a1 = error code address (argument) : not used and not broken
+ * a2 = 2nd 64bit data erronious data (argument, return value)
+ * a3 = 8bit ECC data (argument, return value)
+ * t0 = cache virtual address : not used and not broken
+ * t1 = Cache error reg : not used and not broken
+ * t2 = TagLo reg : not used and not broken
+ * t3 = ECC reg : not used and not broken
+ * t4 - t7 temprary data
+ ********************************/
+LEAF(dat_ecc_chk)
+ .set reorder
+ li t4, 1 # target check bit
+ la t5, dat_synd # data syndrome address
+ move v1, zero # data syndrome and return value
+
+ # make syndrome data
+dat_ecc_loop1:
+ and t6, a2, t4
+ beqz t6, dat_ecc_skip0
+ lbu t7, (t5) # make syndrome of data
+ xor v1, t7 #
+dat_ecc_skip0:
+ addu t5, 1
+ DSLL (T4, T4, 1)
+ bnez t4, dat_ecc_loop1 # loop 63 times
+
+ li t4, 1 # target check bit
+dat_ecc_loop2:
+ and t6, a3, t4
+ beqz t6, dat_ecc_skip1
+ lbu t7, (t5) # make syndrome of data
+ xor v1, t7 #
+dat_ecc_skip1:
+ sll t4, 1
+ addu t5, 1
+ bne t4, 0x100, dat_ecc_loop2 # loop 7 times
+
+ bnez v1, dat_ecc_err # if error
+ li v0, SCHE_DAT_UNKNOW # else unknown error
+ j ra
+
+ # modify data
+dat_ecc_err:
+ li t4, 1 # target check bit
+ la t5, dat_synd # tag syndrome data
+
+dat_ecc_loop3:
+ lbu t7, (t5) # 1bit error
+ beq v1, t7, dat_ecc_1bit # then 1bit error
+
+ DSLL (T4, T4, 1)
+ addu t5, 1
+ bnez t4, dat_ecc_loop3 # loop 63 times
+
+ li t4, 1 # target check bit
+
+dat_ecc_loop4:
+ lbu t7, (t5) # 1bit error
+ beq v1, t7, dat_ecc_1bit2 # then 1bit error
+
+ sll t4, 1
+ addu t5, 1
+ bne t4, 0x100, dat_ecc_loop4 # loop 7 times
+
+ li v0, SCHE_DAT_2BIT_C # 2bit error
+ j ra
+
+dat_ecc_1bit2:
+ xor a3, t4 # modified ECC
+ j dat_ecc_1bitend
+
+dat_ecc_1bit:
+ xor a2, t4 # modified data
+dat_ecc_1bitend:
+ li v0, SCHE_DAT_1BIT # 1bit error
+ j ra
+
+dat_synd:
+ .byte 0x13 # Data 00 (bit 00)
+ .byte 0x23 # Data 01 (bit 01)
+ .byte 0x43 # Data 02 (bit 02)
+ .byte 0x83 # Data 03 (bit 03)
+ .byte 0x2f # Data 04 (bit 04)
+ .byte 0xf1 # Data 05 (bit 05)
+ .byte 0x0d # Data 06 (bit 06)
+ .byte 0x07 # Data 07 (bit 07)
+ .byte 0xd0 # Data 08 (bit 08)
+ .byte 0x70 # Data 09 (bit 09)
+ .byte 0x4f # Data 10 (bit 10)
+ .byte 0xf8 # Data 11 (bit 11)
+ .byte 0x61 # Data 12 (bit 12)
+ .byte 0x62 # Data 13 (bit 13)
+ .byte 0x64 # Data 14 (bit 14)
+ .byte 0x68 # Data 15 (bit 15)
+ .byte 0x1c # Data 16 (bit 16)
+ .byte 0x2c # Data 17 (bit 17)
+ .byte 0x4c # Data 18 (bit 18)
+ .byte 0x8c # Data 19 (bit 19)
+ .byte 0x15 # Data 20 (bit 20)
+ .byte 0x25 # Data 21 (bit 21)
+ .byte 0x45 # Data 22 (bit 22)
+ .byte 0x85 # Data 23 (bit 23)
+ .byte 0x19 # Data 24 (bit 24)
+ .byte 0x29 # Data 25 (bit 25)
+ .byte 0x49 # Data 26 (bit 26)
+ .byte 0x89 # Data 27 (bit 27)
+ .byte 0x1a # Data 28 (bit 28)
+ .byte 0x2a # Data 29 (bit 29)
+ .byte 0x4a # Data 30 (bit 30)
+ .byte 0x8a # Data 31 (bit 31)
+ .byte 0x51 # Data 32 (bit 32)
+ .byte 0x52 # Data 33 (bit 33)
+ .byte 0x54 # Data 34 (bit 34)
+ .byte 0x58 # Data 35 (bit 35)
+ .byte 0x91 # Data 36 (bit 36)
+ .byte 0x92 # Data 37 (bit 37)
+ .byte 0x94 # Data 38 (bit 38)
+ .byte 0x98 # Data 39 (bit 39)
+ .byte 0xa1 # Data 40 (bit 40)
+ .byte 0xa2 # Data 41 (bit 41)
+ .byte 0xa4 # Data 42 (bit 42)
+ .byte 0xa8 # Data 43 (bit 43)
+ .byte 0x31 # Data 44 (bit 44)
+ .byte 0x32 # Data 45 (bit 45)
+ .byte 0x34 # Data 46 (bit 46)
+ .byte 0x38 # Data 47 (bit 47)
+ .byte 0x16 # Data 48 (bit 48)
+ .byte 0x26 # Data 49 (bit 49)
+ .byte 0x46 # Data 50 (bit 50)
+ .byte 0x86 # Data 51 (bit 51)
+ .byte 0x1f # Data 52 (bit 52)
+ .byte 0xf2 # Data 53 (bit 53)
+ .byte 0x0b # Data 54 (bit 54)
+ .byte 0x0e # Data 55 (bit 55)
+ .byte 0xb0 # Data 56 (bit 56)
+ .byte 0xe0 # Data 57 (bit 57)
+ .byte 0x8f # Data 58 (bit 58)
+ .byte 0xf4 # Data 59 (bit 59)
+ .byte 0xc1 # Data 60 (bit 60)
+ .byte 0xc2 # Data 61 (bit 61)
+ .byte 0xc4 # Data 62 (bit 62)
+ .byte 0xc8 # Data 63 (bit 63)
+
+ .byte 0x01 # ECC 0 (bit 0)
+ .byte 0x02 # ECC 1 (bit 1)
+ .byte 0x04 # ECC 2 (bit 2)
+ .byte 0x08 # ECC 3 (bit 3)
+ .byte 0x10 # ECC 4 (bit 4)
+ .byte 0x20 # ECC 5 (bit 5)
+ .byte 0x40 # ECC 6 (bit 6)
+ .byte 0x80 # ECC 7 (bit 7)
+
+ END(dat_ecc_chk)
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/cirrus.h b/private/ntos/nthals/halr98b/mips/cirrus.h
new file mode 100644
index 000000000..9f9846aaf
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/cirrus.h
@@ -0,0 +1,298 @@
+#ident "@(#) NEC cirrus.h 1.2 94/11/21 13:58:39"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.7 94/02/03 18:58:17" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.6 94/01/28 11:50:02" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.4 93/10/29 12:25:02" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cirrus.h
+
+Abstract:
+
+ This module contains the definitions for the code that implements the
+ Cirrus Logic VGA 6410/6420/542x device driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Miniport Driver Interface
+ *
+ * M002 1994.2.2 A. Kuriyama @ oa2
+ * - Bug fix
+ *
+ * Modify : Video Memory Physical Address
+ *
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ * L002 1993.10.21 Kuroki
+ *
+ * - Warniing clear
+ *
+ ***************************************************************
+ *
+ * S001 1994.06.06 T.Samezima
+ *
+ * - Modify for R98 MIPS R4400
+ *
+ * Change : LA_MASK
+ *
+ * S002 '94.11/21 T.Samezima
+ * Chg invalid S001
+ *
+ */
+
+//
+// Change Ushort to Uchar, because R96 is mips machine.
+//
+
+
+//
+// Base address of VGA memory range. Also used as base address of VGA
+// memory when loading a font, which is done with the VGA mapped at A0000.
+//
+
+/* START L001 */
+
+/* START M002 */
+#define LA_MASK 0xe // S001, S002
+/* END M002 */
+#define MEM_VGA (LA_MASK << 20)
+#define MEM_VGA_SIZE 0x100000
+
+/* END L001 */
+
+//
+// Port definitions for filling the ACCSES_RANGES structure in the miniport
+// information, defines the range of I/O ports the VGA spans.
+// There is a break in the IO ports - a few ports are used for the parallel
+// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped
+// so all VGA ports are in one address range.
+//
+
+#define VGA_BASE_IO_PORT 0x000003B0
+#define VGA_START_BREAK_PORT 0x000003BB
+#define VGA_END_BREAK_PORT 0x000003C0
+#define VGA_MAX_IO_PORT 0x000003DF
+
+//
+// VGA port-related definitions.
+//
+
+//
+// VGA register definitions
+//
+ // ports in monochrome mode
+#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and
+#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode
+#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port
+ // in mono mode
+#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read
+ // port in mono mode
+#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO
+ // Register to read to reset
+ // Attribute Controller index/data
+#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and
+#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port
+ // for writes, but only Address is
+ // readable at 0x010
+#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is
+ // readable here
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write
+ // port
+#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read
+ // port
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the
+ // entire VGA subsystem
+#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and
+#define SEQ_DATA_PORT 0x0015 // Data registers
+#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg
+#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg,
+ // write-only
+#define DAC_STATE_PORT 0x0017 // DAC state (read/write),
+ // read-only
+#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg
+#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg
+#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port
+#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read
+ // port
+#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address
+#define GRAPH_DATA_PORT 0x001F // and Data registers
+
+ // ports in color mode
+#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and
+#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode
+#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port
+#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read
+ // port in color mode
+#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR
+ // Register to read to reset
+ // Attribute Controller index/data
+ // toggle in color mode
+
+//
+// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed
+// VGA registers.
+//
+
+#define CRTC_ADDRESS_MONO_OFFSET 0x04
+#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A
+#define ATT_ADDRESS_OFFSET 0x10
+#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12
+#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13
+#define SEQ_ADDRESS_OFFSET 0x14
+#define DAC_PIXEL_MASK_OFFSET 0x16
+#define DAC_STATE_OFFSET 0x17
+#define DAC_ADDRESS_WRITE_OFFSET 0x18
+#define GRAPH_ADDRESS_OFFSET 0x1E
+#define CRTC_ADDRESS_COLOR_OFFSET 0x24
+#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A
+
+// toggle in color mode
+//
+// VGA indexed register indexes.
+//
+
+// CL-GD542x specific registers:
+//
+#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts
+#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad
+#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register
+//
+#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start
+#define IND_CURSOR_END 0x0B // and End registers
+#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location
+#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers
+#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync
+ // End register, which has the bit
+ // that protects/unprotects CRTC
+ // index registers 0-7
+#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC
+#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC
+#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr
+#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr
+#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr
+#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr
+#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq
+#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer
+#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq
+#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in
+ // CRTC
+#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg
+ // in CRTC
+#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start
+ // synchronous reset
+#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end
+ // synchronous reset
+
+//
+// Values for Attribute Controller Index register to turn video off
+// and on, by setting bit 5 to 0 (off) or 1 (on).
+//
+
+#define VIDEO_DISABLE 0
+#define VIDEO_ENABLE 0x20
+
+// Masks to keep only the significant bits of the Graphics Controller and
+// Sequencer Address registers. Masking is necessary because some VGAs, such
+// as S3-based ones, don't return unused bits set to 0, and some SVGAs use
+// these bits if extensions are enabled.
+//
+
+#define GRAPH_ADDR_MASK 0x0F
+#define SEQ_ADDR_MASK 0x07
+
+//
+// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register.
+//
+
+#define CHAIN4_MASK 0x08
+
+//
+// Value written to the Read Map register when identifying the existence of
+// a VGA in VgaInitialize. This value must be different from the final test
+// value written to the Bit Mask in that routine.
+//
+
+#define READ_MAP_TEST_SETTING 0x03
+
+//
+// Default text mode setting for various registers, used to restore their
+// states if VGA detection fails after they've been modified.
+//
+
+#define MEMORY_MODE_TEXT_DEFAULT 0x02
+#define BIT_MASK_DEFAULT 0xFF
+#define READ_MAP_DEFAULT 0x00
+
+
+//
+// Palette-related info.
+//
+
+//
+// Highest valid DAC color register index.
+//
+
+#define VIDEO_MAX_COLOR_REGISTER 0xFF
+
+//
+// Indices for type of memory mapping; used in ModesVGA[], must match
+// MemoryMap[].
+//
+
+typedef enum _VIDEO_MEMORY_MAP {
+ MemMap_Mono,
+ MemMap_CGA,
+ MemMap_VGA
+} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP;
+
+//
+// For a mode, the type of banking supported. Controls the information
+// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking.
+//
+
+typedef enum _BANK_TYPE {
+ NoBanking = 0,
+ NormalBanking,
+ PlanarHCBanking
+} BANK_TYPE, *PBANK_TYPE;
+
+#define CL6410 0x0001
+#define CL6420 0x0002
+#define CL542x 0x0004
+
+// bitfields for the DisplayType
+#define crt 0x0001
+#define panel 0x0002
+#define simulscan 0x0004 // this means both, but is unused for now.
diff --git a/private/ntos/nthals/halr98b/mips/cmdcnst.h b/private/ntos/nthals/halr98b/mips/cmdcnst.h
new file mode 100644
index 000000000..ea2bba221
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/cmdcnst.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdcnst.h
+
+Abstract:
+
+ This is the command string interpreter definitions
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ This module is same file on Cirrus Minport Driver.
+
+Revision History:
+
+--*/
+
+//--------------------------------------------------------------------------
+// Definition of the set/clear mode command language.
+//
+// Each command is composed of a major portion and a minor portion.
+// The major portion of a command can be found in the most significant
+// nibble of a command byte, while the minor portion is in the least
+// significant portion of a command byte.
+//
+// maj minor Description
+// ---- ----- --------------------------------------------
+// 00 End of data
+//
+// 10 in and out type commands as described by flags
+// flags:
+//
+// xxxx
+// ||||
+// |||+-------- unused
+// ||+--------- 0/1 single/multiple values to output (in's are always
+// |+---------- 0/1 8/16 bit operation single)
+// +----------- 0/1 out/in instruction
+//
+// Outs
+// ----------------------------------------------
+// 0 reg:W val:B
+// 2 reg:W cnt:W val1:B val2:B...valN:B
+// 4 reg:W val:W
+// 6 reg:W cnt:W val1:W val2:W...valN:W
+//
+// Ins
+// ----------------------------------------------
+// 8 reg:W
+// a reg:W cnt:W
+// c reg:W
+// e reg:W cnt:W
+//
+// 20 Special purpose outs
+// 00 do indexed outs for seq, crtc, and gdc
+// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 01 do indexed outs for atc
+// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 02 do masked outs
+// indexreg:W andmask:B xormask:B
+//
+// F0 Nop
+//
+//---------------------------------------------------------------------------
+
+// some useful equates - major commands
+
+#define EOD 0x000 // end of data
+#define INOUT 0x010 // do ins or outs
+#define METAOUT 0x020 // do special types of outs
+#define NCMD 0x0f0 // Nop command
+
+
+// flags for INOUT major command
+
+//#define UNUSED 0x01 // reserved
+#define MULTI 0x02 // multiple or single outs
+#define BW 0x04 // byte/word size of operation
+#define IO 0x08 // out/in instruction
+
+// minor commands for metout
+
+#define INDXOUT 0x00 // do indexed outs
+#define ATCOUT 0x01 // do indexed outs for atc
+#define MASKOUT 0x02 // do masked outs using and-xor masks
+
+
+// composite inout type commands
+
+#define OB (INOUT) // output 8 bit value
+#define OBM (INOUT+MULTI) // output multiple bytes
+#define OW (INOUT+BW) // output single word value
+#define OWM (INOUT+BW+MULTI) // output multiple words
+
+#define IB (INOUT+IO) // input byte
+#define IBM (INOUT+IO+MULTI) // input multiple bytes
+#define IW (INOUT+IO+BW) // input word
+#define IWM (INOUT+IO+BW+MULTI) // input multiple words
diff --git a/private/ntos/nthals/halr98b/mips/esmnvram.h b/private/ntos/nthals/halr98b/mips/esmnvram.h
new file mode 100644
index 000000000..cded099f2
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/esmnvram.h
@@ -0,0 +1,271 @@
+/*++
+
+Copyright (C) 1994, 1995 NEC Corporation
+
+File Name:
+
+ esmnvram.h
+
+Abstract:
+
+ This module contains the definitions for the extended NVRAM.
+
+Author:
+
+
+Modification History:
+
+ - M000 12/22/94 - created by Takehiro Ueda (tueda@oa2.kbnes.nec.co.jp)
+ - M001 11/22/95 - modified by Masayuki Fujii (masa@oa2.kbnes.nec.co.jp)
+ - M002 02/12/96 - modified by Masayuki Fujii (masa@oa2.kbnes.nec.co.jp)
+--*/
+
+
+#pragma pack(1)
+
+
+//
+// define structures for each area of NVRAM
+//
+
+
+//
+// WAS & PS common infromation for ECC memory error
+//
+
+typedef struct _MEM_ERR_REC {
+ UCHAR mem_status;
+ UCHAR err_count;
+} MEM_ERR_REC, *pMEM_ERR_REC;
+
+
+//
+// setting for ALIVE information area
+//
+
+typedef struct _ALIVE_AREA_INFO {
+ USHORT offset_alive;
+} ALIVE_AREA_INFO, *pALIVE_AREA_INFO;
+
+
+//
+// setting for ECC 1bit error information area
+//
+
+typedef struct _ECC1_ERR_AREA_INFO {
+ USHORT offset_1biterr;
+ USHORT size_rec;
+ USHORT num_rec;
+ USHORT offset_latest;
+ ULONG read_data_latest;
+ UCHAR err_count_group0;
+ UCHAR err_count_group1;
+ UCHAR err_count_group2;
+ UCHAR err_count_group3;
+ UCHAR err_count_group4;
+ UCHAR err_count_group5;
+ UCHAR err_count_group6;
+ UCHAR err_count_group7;
+} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO;
+
+
+//
+// setting for ECC 2bit error information area
+//
+
+typedef struct _ECC2_ERR_AREA_INFO {
+ USHORT offset_2biterr;
+ USHORT size_rec;
+ USHORT num_rec;
+ USHORT offset_latest;
+ ULONG read_data_latest;
+ UCHAR simm_flag_group1;
+ UCHAR simm_flag_group2;
+ UCHAR simm_flag_group3;
+ UCHAR simm_flag_group4;
+ CHAR reserved[4];
+} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO;
+
+
+//
+// setting for system error information area
+//
+
+typedef struct _SYSTEM_ERR_AREA_INFO {
+ USHORT offset_systemerr;
+ USHORT size_rec;
+ USHORT num_rec;
+ USHORT offset_latest;
+} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO;
+
+
+//
+// setting for critical error information area
+//
+
+typedef struct _CRITICAL_ERR_AREA_INFO {
+ USHORT offset_critical;
+ USHORT size_rec;
+ USHORT num_rec;
+ USHORT offset_latest;
+} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO;
+
+
+//
+// setting for reduction information area
+//
+
+typedef struct _RED_AREA_INFO {
+ USHORT offset_red;
+} RED_AREA_INFO, *pRED_AREA_INFO;
+
+
+//
+// setting for reserved area
+//
+
+typedef struct _RESERVE_AREA_INFO {
+ USHORT offset_reserve;
+} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO;
+
+
+//
+// system information structure
+// 49 bytes
+//
+
+typedef struct _SYS_INFO {
+ UCHAR system_flag;
+ CHAR reserved1[3]; // for 4 byte alignment
+ CHAR sys_description[32];
+ ULONG serial_num;
+ ULONG magic;
+ CHAR reserved2[4]; // reserved
+} SYS_INFO, *pSYS_INFO;
+
+
+//
+// NVRAM header structure
+// 640 bytes
+//
+
+typedef struct _NVRAM_HEADER {
+ MEM_ERR_REC mem_err_map[256]; // common area for NT & NW
+ UCHAR nvram_flag;
+ CHAR when_formatted[14];
+ CHAR reserved[3]; // for 4 byte alignment
+ ALIVE_AREA_INFO alive;
+ ECC1_ERR_AREA_INFO ecc1bit_err;
+ ECC2_ERR_AREA_INFO ecc2bit_err;
+ SYSTEM_ERR_AREA_INFO system_err;
+ CRITICAL_ERR_AREA_INFO critical_err_log;
+ RED_AREA_INFO red;
+ RESERVE_AREA_INFO reserve;
+ SYS_INFO system;
+} NVRAM_HEADER, *pNVRAM_HEADER;
+
+
+//
+// ALIVE, pager call information structure
+// 80 bytes
+//
+
+typedef struct _ALIVE_INFO {
+ UCHAR alert_level;
+ CHAR primary_destination[16];
+ CHAR secondary_destinaiton[16];
+ CHAR reserved[47]; // reserved
+} ALIVE_INFO, *pALIVE_INFO;
+
+
+//
+// ECC 1bit error information structure
+//
+
+typedef struct _ECC1_ERR_REC {
+ UCHAR record_flag;
+ ULONG err_address;
+ CHAR when_happened[14];
+ ULONG syndrome;
+ UCHAR specified_group;
+ UCHAR specified_simm;
+} ECC1_ERR_REC, *pECC1_ERR_REC;
+
+
+//
+// ECC 2bit error information structure
+//
+
+typedef struct _ECC2_ERR_REC {
+ UCHAR record_flag;
+ ULONG err_address;
+ CHAR when_happened[14];
+ ULONG syndrome;
+ UCHAR specified_group;
+ UCHAR specified_simm;
+} ECC2_ERR_REC, *pECC2_ERR_REC;
+
+
+//
+// stop error information structure
+//
+
+typedef struct _STOP_ERR_REC {
+ UCHAR record_flag;
+ CHAR when_happened[14];
+ CHAR err_description[496];
+ CHAR reserved[1]; // reserved
+} STOP_ERR_REC, *pSTOP_ERR_REC;
+
+
+//
+// critical error information structure
+//
+
+typedef struct _CRITICAL_ERR_REC {
+ UCHAR record_flag;
+ CHAR when_happened[14];
+ CHAR source[20];
+ CHAR err_description[80];
+ UCHAR error_code;
+ CHAR reserved[12]; // reserved
+} CRITICAL_ERR_REC, *pCRITICAL;
+
+
+//
+// memory reduction information structure
+//
+
+typedef struct _MEM_RED_INF {
+ ULONG simm_red_inf;
+ CHAR simm_rfu0[4]; // reserved
+ ULONG simm_stp_inf;
+ CHAR simm_rfu1[4]; // reserved
+ ULONG simm_phy_inf;
+ CHAR simm_rfu2[12]; // reserved
+} MEM_RED_INF, *pMEM_RED;
+
+
+//
+// SIMM size information structure
+//
+
+typedef struct _MEM_CAP_INF {
+ CHAR simm_phy_cap[64];
+} MEM_CAP_INF, *pMEM_CAP;
+
+
+//
+// CPU reduction information structure
+//
+
+typedef struct _CPU_RED_INF {
+ ULONG cpu_red_inf;
+ ULONG cpu_stp_inf;
+ ULONG cpu_phy_inf;
+ CHAR cpu_rfu[4] ; // reserved
+} CPU_RED_INF, *pCPU_RED;
+
+
+#pragma pack()
+
diff --git a/private/ntos/nthals/halr98b/mips/glint.h b/private/ntos/nthals/halr98b/mips/glint.h
new file mode 100644
index 000000000..156c3efcc
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/glint.h
@@ -0,0 +1,580 @@
+// #ident "@(#) glint.h 1.1 95/06/30 05:27:26 nec"
+/************************************************************************
+ * *
+ * Copyright (c) 1994 3Dlabs Inc. Ltd. *
+ * All rights reserved *
+ * *
+ * This software and its associated documentation contains proprietary, *
+ * confidential and trade secret information of 3Dlabs Inc. Ltd. and *
+ * except as provided by written agreement with 3Dlabs Inc. Ltd. *
+ * *
+ * a) no part may be disclosed, distributed, reproduced, transmitted, *
+ * transcribed, stored in a retrieval system, adapted or translated *
+ * in any form or by any means electronic, mechanical, magnetic, *
+ * optical, chemical, manual or otherwise, *
+ * *
+ * and *
+ * *
+ * b) the recipient is not entitled to discover through reverse *
+ * engineering or reverse compiling or other such techniques or *
+ * processes the trade secrets contained therein or in the *
+ * documentation. *
+ * *
+ ************************************************************************/
+
+#ifndef __GLINT_H__
+#define __GLINT_H__
+
+typedef unsigned long DWORD;
+
+/************************************************************************/
+/* PCI CONFIGURATION REGION */
+/************************************************************************/
+
+#define __GLINT_CFGVendorId PCI_CS_VENDOR_ID
+#define __GLINT_CFGDeviceId PCI_CS_DEVICE_ID
+#define __GLINT_CFGRevisionId PCI_CS_REVISION_ID
+#define __GLINT_CFGClassCode PCI_CS_CLASS_CODE
+#define __GLINT_CFGHeaderType PCI_CS_HEADER_TYPE
+#define __GLINT_CFGCommand PCI_CS_COMMAND
+#define __GLINT_CFGStatus PCI_CS_STATUS
+#define __GLINT_CFGBist PCI_CS_BIST
+#define __GLINT_CFGLatTimer PCI_CS_MASTER_LATENCY
+#define __GLINT_CFGCacheLine PCI_CS_CACHE_LINE_SIZE
+#define __GLINT_CFGMaxLat PCI_CS_MAX_LAT
+#define __GLINT_CFGMinGrant PCI_CS_MIN_GNT
+#define __GLINT_CFGIntPin PCI_CS_INTERRUPT_PIN
+#define __GLINT_CFGIntLine PCI_CS_INTERRUPT_LINE
+
+#define __GLINT_CFGBaseAddr0 PCI_CS_BASE_ADDRESS_0
+#define __GLINT_CFGBaseAddr1 PCI_CS_BASE_ADDRESS_1
+#define __GLINT_CFGBaseAddr2 PCI_CS_BASE_ADDRESS_2
+#define __GLINT_CFGBaseAddr3 PCI_CS_BASE_ADDRESS_3
+#define __GLINT_CFGBaseAddr4 PCI_CS_BASE_ADDRESS_4
+#define __GLINT_CFGRomAddr PCI_CS_EXPANSION_ROM
+
+/* CFGVendorId[15:0] - 3Dlabs Vendor ID Value */
+
+#define GLINT_VENDOR_ID (0x3D3D)
+
+/* CFGDeviceId[15:0] - GLINT 300SX Device ID */
+
+#define GLINT_DEVICE_ID (0x0001)
+
+/* CFGRevisionID[7:0] - GLINT Revision Code */
+
+#define GLINT_REVISION_A (0x00)
+#define GLINT_REVISION_B (0x01)
+
+/* CFGClassCode[23:0] - Other Display Controller */
+
+#define GLINT_CLASS_CODE ((DWORD) 0x00038000)
+
+/* CFGHeaderType[7:0] - Single Function Device */
+
+#define GLINT_HEADER_TYPE (0x00)
+
+/* CFGCommand[15:0] - Reset Value Zero */
+
+#define GLINT_COMMAND_RESET_VALUE (0x0000)
+
+/* CFGCommand[1] - Memory Access Enable */
+
+#define GLINT_MEMORY_ACCESS_MASK (1 << 0)
+#define GLINT_MEMORY_ACCESS_DISABLE (0 << 0)
+#define GLINT_MEMORY_ACCESS_ENABLE (1 << 1)
+
+/* CFGCommand[2] - Master Enable */
+
+#define GLINT_MASTER_ENABLE_MASK (1 << 2)
+#define GLINT_MASTER_DISABLE (0 << 2)
+#define GLINT_MASTER_ENABLE (1 << 2)
+
+/* CFGStatus[15:0] - Reset Value Zero */
+
+#define GLINT_STATUS_RESET_VALUE (0x0000)
+
+/* CFGBist - Built In Self Test Unsupported */
+
+#define GLINT_BIST (0x00)
+
+/* CFGCacheLine - Cache Line Size Unsupported */
+
+#define GLINT_CACHE_LINE (0x00)
+
+/* CFGIntPin - Interrupt Pin INTA# */
+
+#define GLINT_INTERRUPT_PIN (0x01)
+
+/********************/
+
+#define GLINT_CONTROL_BASE __GLINT_CFGBaseAddr0
+#define GLINT_LOCAL_0_BASE __GLINT_CFGBaseAddr1
+#define GLINT_FRAME_0_BASE __GLINT_CFGBaseAddr2
+#define GLINT_LOCAL_1_BASE __GLINT_CFGBaseAddr3
+#define GLINT_FRAME_1_BASE __GLINT_CFGBaseAddr4
+#define GLINT_EPROM_BASE __GLINT_CFGRomAddr
+
+#define GLINT_EPROM_SIZE ((DWORD)(64L * 1024L))
+
+/************************************************************************/
+/* CONTROL AND STATUS REGISTERS */
+/************************************************************************/
+
+#define GLINT_REGION_0_SIZE ((DWORD)(128L * 1024L))
+
+#define __GLINT_ResetStatus 0x0000
+#define __GLINT_IntEnable 0x0008
+#define __GLINT_IntFlags 0x0010
+#define __GLINT_InFIFOSpace 0x0018
+#define __GLINT_OutFIFOWords 0x0020
+#define __GLINT_DMAAddress 0x0028
+#define __GLINT_DMACount 0x0030
+#define __GLINT_ErrorFlags 0x0038
+#define __GLINT_VClkCtl 0x0040
+#define __GLINT_TestRegister 0x0048
+#define __GLINT_Aperture0 0x0050
+#define __GLINT_Aperture1 0x0058
+#define __GLINT_DMAControl 0x0060
+
+/* ResetStatus[31] - Software Reset Flag */
+
+#define GLINT_RESET_STATUS_MASK ((DWORD) 1 << 31)
+#define GLINT_READY_FOR_USE ((DWORD) 0 << 31)
+#define GLINT_RESET_IN_PROGRESS ((DWORD) 1 << 31)
+
+/* IntEnable[4:0] - Interrupt Enable Register */
+
+#define GLINT_INT_ENABLE_DMA ((DWORD) 1 << 0)
+#define GLINT_INT_ENABLE_SYNC ((DWORD) 1 << 1)
+#define GLINT_INT_ENABLE_EXTERNAL ((DWORD) 1 << 2)
+#define GLINT_INT_ENABLE_ERROR ((DWORD) 1 << 3)
+#define GLINT_INT_ENABLE_VERTICAL ((DWORD) 1 << 4)
+
+/* IntFlags[4:0] - Interrupt Flags Register */
+
+#define GLINT_INT_FLAG_DMA ((DWORD) 1 << 0)
+#define GLINT_INT_FLAG_SYNC ((DWORD) 1 << 1)
+#define GLINT_INT_FLAG_EXTERNAL ((DWORD) 1 << 2)
+#define GLINT_INT_FLAG_ERROR ((DWORD) 1 << 3)
+#define GLINT_INT_FLAG_VERTICAL ((DWORD) 1 << 4)
+
+/* ErrorFlags[2:0] - Error Flags Register */
+
+#define GLINT_ERROR_INPUT_FIFO ((DWORD) 1 << 0)
+#define GLINT_ERROR_OUTPUT_FIFO ((DWORD) 1 << 1)
+#define GLINT_ERROR_COMMAND ((DWORD) 1 << 2)
+
+/* ApertureX[1:0] - Framebuffer Byte Control */
+
+#define GLINT_FB_BYTE_CONTROL_MASK ((DWORD) 3 << 0)
+#define GLINT_FB_LITTLE_ENDIAN ((DWORD) 0 << 0)
+#define GLINT_FB_BIG_ENDIAN ((DWORD) 1 << 0)
+#define GLINT_FB_GIB_ENDIAN ((DWORD) 2 << 0)
+#define GLINT_FB_BYTE_RESERVED ((DWORD) 3 << 0)
+
+/* ApertureX[2] - Localbuffer Byte Control */
+
+#define GLINT_LB_BYTE_CONTROL_MASK ((DWORD) 1 << 2)
+#define GLINT_LB_LITTLE_ENDIAN ((DWORD) 0 << 2)
+#define GLINT_LB_BIG_ENDIAN ((DWORD) 1 << 2)
+
+/* DMAControl[0] - DMA Byte Swap Control */
+
+#define GLINT_DMA_CONTROL_MASK ((DWORD) 1 << 0)
+#define GLINT_DMA_LITTLE_ENDIAN ((DWORD) 0 << 0)
+#define GLINT_DMA_BIG_ENDIAN ((DWORD) 1 << 0)
+
+/************************************************************************/
+/* LOCALBUFFER REGISTERS */
+/************************************************************************/
+
+#define __GLINT_LBMemoryCtl 0x1000
+
+/* LBMemoryCtl[0] - Number of Localbuffer Banks */
+
+#define GLINT_LB_BANK_MASK ((DWORD) 1 << 0)
+#define GLINT_LB_ONE_BANK ((DWORD) 0 << 0)
+#define GLINT_LB_TWO_BANKS ((DWORD) 1 << 0)
+
+/* LBMemoryCtl[2:1] - Localbuffer Page Size */
+
+#define GLINT_LB_PAGE_SIZE_MASK ((DWORD) 2 << 1)
+#define GLINT_LB_PAGE_SIZE_256_PIXELS ((DWORD) 0 << 1)
+#define GLINT_LB_PAGE_SIZE_512_PIXELS ((DWORD) 1 << 1)
+#define GLINT_LB_PAGE_SIZE_1024_PIXELS ((DWORD) 2 << 1)
+#define GLINT_LB_PAGE_SIZE_2048_PIXELS ((DWORD) 3 << 1)
+
+/* LBMemoryCtl[4:3] - Localbuffer RAS-CAS Low */
+
+#define GLINT_LB_RAS_CAS_LOW_MASK ((DWORD) 3 << 3)
+#define GLINT_LB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 3)
+#define GLINT_LB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 3)
+#define GLINT_LB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 3)
+#define GLINT_LB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 3)
+
+/* LBMemoryCtl[6:5] - Localbuffer RAS Precharge */
+
+#define GLINT_LB_RAS_PRECHARGE_MASK ((DWORD) 3 << 5)
+#define GLINT_LB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 5)
+#define GLINT_LB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 5)
+#define GLINT_LB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 5)
+#define GLINT_LB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 5)
+
+/* LBMemoryCtl[8:7] - Localbuffer CAS Low */
+
+#define GLINT_LB_CAS_LOW_MASK ((DWORD) 3 << 7)
+#define GLINT_LB_CAS_LOW_1_CLOCK ((DWORD) 0 << 7)
+#define GLINT_LB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 7)
+#define GLINT_LB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 7)
+#define GLINT_LB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 7)
+
+/* LBMemoryCtl[9] - Localbuffer Page Mode Disable */
+
+#define GLINT_LB_PAGE_MODE_MASK ((DWORD) 1 << 9)
+#define GLINT_LB_PAGE_MODE_ENABLE ((DWORD) 0 << 9)
+#define GLINT_LB_PAGE_MODE_DISABLE ((DWORD) 1 << 9)
+
+/* LBMemoryCtl[17:10] - Localbuffer Refresh Count */
+
+#define GLINT_LB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 10)
+#define GLINT_LB_REFRESH_COUNT_SHIFT (10)
+
+#define GLINT_LB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 10)
+
+/* LBMemoryCtl[18] - Localbuffer Dual Write Enables */
+
+#define GLINT_LB_MEM_TYPE_MASK ((DWORD) 1 << 18)
+#define GLINT_LB_MEM_DUAL_CAS ((DWORD) 0 << 18)
+#define GLINT_LB_MEM_DUAL_WE ((DWORD) 1 << 18)
+
+/* LBMemoryCtl[21:20] - PCI Maximum Latency - Read Only */
+
+#define GLINT_PCI_MAX_LATENCY_MASK ((DWORD) 3 << 20)
+#define GLINT_PCI_MAX_LATENCY_SHIFT (20)
+
+/* LBMemoryCtl[23:22] - PCI Minimum Grant - Read Only */
+
+#define GLINT_PCI_MIN_GRANT_MASK ((DWORD) 3 << 22)
+#define GLINT_PCI_MIN_GRANT_SHIFT (22)
+
+/* LBMemoryCtl[26:24] - Localbuffer Visible Region Size - Read Only */
+
+#define GLINT_LB_REGION_SIZE_MASK ((DWORD) 7 << 24)
+#define GLINT_LB_REGION_SIZE_1_MB ((DWORD) 0 << 24)
+#define GLINT_LB_REGION_SIZE_2_MB ((DWORD) 1 << 24)
+#define GLINT_LB_REGION_SIZE_4_MB ((DWORD) 2 << 24)
+#define GLINT_LB_REGION_SIZE_8_MB ((DWORD) 3 << 24)
+#define GLINT_LB_REGION_SIZE_16_MB ((DWORD) 4 << 24)
+#define GLINT_LB_REGION_SIZE_32_MB ((DWORD) 5 << 24)
+#define GLINT_LB_REGION_SIZE_64_MB ((DWORD) 6 << 24)
+#define GLINT_LB_REGION_SIZE_0_MB ((DWORD) 7 << 24)
+
+/* LBMemoryCtl[29:27] - Localbuffer Width - Read Only */
+
+#define GLINT_LB_WIDTH_MASK ((DWORD) 7 << 27)
+#define GLINT_LB_WIDTH_16_BITS ((DWORD) 0 << 27)
+#define GLINT_LB_WIDTH_18_BITS ((DWORD) 1 << 27)
+#define GLINT_LB_WIDTH_24_BITS ((DWORD) 2 << 27)
+#define GLINT_LB_WIDTH_32_BITS ((DWORD) 3 << 27)
+#define GLINT_LB_WIDTH_36_BITS ((DWORD) 4 << 27)
+#define GLINT_LB_WIDTH_40_BITS ((DWORD) 5 << 27)
+#define GLINT_LB_WIDTH_48_BITS ((DWORD) 6 << 27)
+#define GLINT_LB_WIDTH_OTHER ((DWORD) 7 << 27)
+
+/* LBMemoryCtl[30] - Localbuffer Bypass Packing - Read Only */
+
+#define GLINT_LB_BYPASS_STEP_MASK ((DWORD) 1 << 30)
+#define GLINT_LB_BYPASS_STEP_64_BITS ((DWORD) 0 << 30)
+#define GLINT_LB_BYPASS_STEP_32_BITS ((DWORD) 1 << 30)
+
+/* LBMemoryCtl[31] - Localbuffer Aperture One Enable - Read Only */
+
+#define GLINT_LB_APERTURE_ONE_MASK ((DWORD) 1 << 31)
+#define GLINT_LB_APERTURE_ONE_DISABLE ((DWORD) 0 << 31)
+#define GLINT_LB_APERTURE_ONE_ENABLE ((DWORD) 1 << 31)
+
+/************************************************************************/
+/* FRAMEBUFFER REGISTERS */
+/************************************************************************/
+
+#define __GLINT_FBMemoryCtl 0x1800
+#define __GLINT_FBModeSel 0x1808
+#define __GLINT_FBGCWrMask 0x1810
+#define __GLINT_FBGCColorMask 0x1818
+
+/* FBMemoryCtl[1:0] - Framebuffer RAS-CAS Low */
+
+#define GLINT_FB_RAS_CAS_LOW_MASK ((DWORD) 3 << 0)
+#define GLINT_FB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 0)
+#define GLINT_FB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 0)
+#define GLINT_FB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 0)
+#define GLINT_FB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 0)
+
+/* FBMemoryCtl[3:2] - Framebuffer RAS Precharge */
+
+#define GLINT_FB_RAS_PRECHARGE_MASK ((DWORD) 3 << 2)
+#define GLINT_FB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 2)
+#define GLINT_FB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 2)
+#define GLINT_FB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 2)
+#define GLINT_FB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 2)
+
+/* FBMemoryCtl[5:4] - Framebuffer CAS Low */
+
+#define GLINT_FB_CAS_LOW_MASK ((DWORD) 3 << 4)
+#define GLINT_FB_CAS_LOW_1_CLOCK ((DWORD) 0 << 4)
+#define GLINT_FB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 4)
+#define GLINT_FB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 4)
+#define GLINT_FB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 4)
+
+/* FBMemoryCtl[13:6] - Framebuffer Refresh Count */
+
+#define GLINT_FB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 6)
+#define GLINT_FB_REFRESH_COUNT_SHIFT (6)
+
+#define GLINT_FB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 6)
+
+/* FBMemoryCtl[14] - Framebuffer Page Mode Disable */
+
+#define GLINT_FB_PAGE_MODE_MASK ((DWORD) 1 << 14)
+#define GLINT_FB_PAGE_MODE_ENABLE ((DWORD) 0 << 14)
+#define GLINT_FB_PAGE_MODE_DISABLE ((DWORD) 1 << 14)
+
+/* FBMemoryCtl[25:20] - Reserved - Read Only */
+
+#define GLINT_FB_CTL_RESERVED_MASK ((DWORD) 0x3F << 20)
+#define GLINT_FB_CTL_RESERVED_SHIFT (20)
+
+/* FBMemoryCtl[26] - Byte Swap Configuration Space - Read Only */
+
+#define GLINT_BYTE_SWAP_CONFIG_MASK ((DWORD) 1 << 26)
+#define GLINT_BYTE_SWAP_CONFIG_DISABLE ((DWORD) 0 << 26)
+#define GLINT_BYTE_SWAP_CONFIG_ENABLE ((DWORD) 1 << 26)
+
+/* FBMemoryCtl[28] - Framebuffer Aperture One Enable - Read Only */
+
+#define GLINT_FB_APERTURE_ONE_MASK ((DWORD) 1 << 28)
+#define GLINT_FB_APERTURE_ONE_DISABLE ((DWORD) 0 << 28)
+#define GLINT_FB_APERTURE_ONE_ENABLE ((DWORD) 1 << 28)
+
+/* FBMemoryCtl[31:29] - Framebuffer Visible Region Size - Read Only */
+
+#define GLINT_FB_REGION_SIZE_MASK ((DWORD) 7 << 29)
+#define GLINT_FB_REGION_SIZE_1_MB ((DWORD) 0 << 29)
+#define GLINT_FB_REGION_SIZE_2_MB ((DWORD) 1 << 29)
+#define GLINT_FB_REGION_SIZE_4_MB ((DWORD) 2 << 29)
+#define GLINT_FB_REGION_SIZE_8_MB ((DWORD) 3 << 29)
+#define GLINT_FB_REGION_SIZE_16_MB ((DWORD) 4 << 29)
+#define GLINT_FB_REGION_SIZE_32_MB ((DWORD) 5 << 29)
+#define GLINT_FB_REGION_SIZE_RESERVED ((DWORD) 6 << 29)
+#define GLINT_FB_REGION_SIZE_0_MB ((DWORD) 7 << 29)
+
+/* FBModeSel[0] - Framebuffer Width */
+
+#define GLINT_FB_WIDTH_MASK ((DWORD) 1 << 0)
+#define GLINT_FB_WIDTH_32_BITS ((DWORD) 0 << 0)
+#define GLINT_FB_WIDTH_64_BITS ((DWORD) 1 << 0)
+
+/* FBModeSel[2:1] - Framebuffer Packing */
+
+#define GLINT_FB_PACKING_MASK ((DWORD) 2 << 1)
+#define GLINT_FB_PACKING_32_BITS ((DWORD) 0 << 1)
+#define GLINT_FB_PACKING_16_BITS ((DWORD) 1 << 1)
+#define GLINT_FB_PACKING_8_BITS ((DWORD) 2 << 1)
+#define GLINT_FB_PACKING_RESERVED ((DWORD) 3 << 1)
+
+/* FBModeSel[3] - Fast Mode Disable */
+
+#define GLINT_FB_FAST_MODE_MASK ((DWORD) 1 << 3)
+#define GLINT_FB_FAST_MODE_ENABLE ((DWORD) 0 << 3)
+#define GLINT_FB_FAST_MODE_DISABLE ((DWORD) 1 << 3)
+
+/* FBModeSel[5:4] - Shared Framebuffer Mode - Read Only */
+
+#define GLINT_SFB_MODE_MASK ((DWORD) 3 << 4)
+#define GLINT_SFB_DISABLED ((DWORD) 0 << 4)
+#define GLINT_SFB_ARBITER ((DWORD) 1 << 4)
+#define GLINT_SFB_REQUESTER ((DWORD) 2 << 4)
+#define GLINT_SFB_RESERVED ((DWORD) 3 << 4)
+
+/* FBModeSel[6] - Transfer Disable */
+
+#define GLINT_TRANSFER_MODE_MASK ((DWORD) 1 << 6)
+#define GLINT_TRANSFER_ENABLE ((DWORD) 0 << 6)
+#define GLINT_TRANSFER_DISABLE ((DWORD) 1 << 6)
+
+/* FBModeSel[7] - External VTG Select */
+
+#define GLINT_VTG_SELECT_MASK ((DWORD) 1 << 7)
+#define GLINT_INTERNAL_VTG ((DWORD) 0 << 7)
+#define GLINT_EXTERNAL_VTG ((DWORD) 1 << 7)
+
+/* FBModeSel[9:8] - Framebuffer Interleave */
+
+#define GLINT_FB_INTERLEAVE_MASK ((DWORD) 3 << 8)
+#define GLINT_FB_INTERLEAVE_1_WAY ((DWORD) 0 << 8)
+#define GLINT_FB_INTERLEAVE_2_WAY ((DWORD) 1 << 8)
+#define GLINT_FB_INTERLEAVE_4_WAY ((DWORD) 2 << 8)
+#define GLINT_FB_INTERLEAVE_8_WAY ((DWORD) 3 << 8)
+
+/* FBModeSel[11:10] - Framebuffer Block Fill Size */
+
+#define GLINT_FB_BLOCK_FILL_SIZE_MASK ((DWORD) 3 << 10)
+#define GLINT_FB_BLOCK_FILL_UNSUPPORTED ((DWORD) 0 << 10)
+#define GLINT_FB_BLOCK_FILL_4_PIXEL ((DWORD) 1 << 10)
+#define GLINT_FB_BLOCK_FILL_8_PIXEL ((DWORD) 2 << 10)
+#define GLINT_FB_BLOCK_FILL_RESERVED ((DWORD) 3 << 10)
+
+/* FBModeSel[12] - Framebuffer Dual Write Enables */
+
+#define GLINT_FB_MEM_TYPE_MASK ((DWORD) 1 << 12)
+#define GLINT_FB_MEM_DUAL_CAS ((DWORD) 0 << 12)
+#define GLINT_FB_MEM_DUAL_WE ((DWORD) 1 << 12)
+
+/************************************************************************/
+/* INTERNAL VIDEO TIMING GENERATOR REGISTERS */
+/************************************************************************/
+
+#define __GLINT_VTGHLimit 0x3000
+#define __GLINT_VTGHSyncStart 0x3008
+#define __GLINT_VTGHSyncEnd 0x3010
+#define __GLINT_VTGHBlankEnd 0x3018
+#define __GLINT_VTGVLimit 0x3020
+#define __GLINT_VTGVSyncStart 0x3028
+#define __GLINT_VTGVSyncEnd 0x3030
+#define __GLINT_VTGVBlankEnd 0x3038
+#define __GLINT_VTGHGateStart 0x3040
+#define __GLINT_VTGHGateEnd 0x3048
+#define __GLINT_VTGVGateStart 0x3050
+#define __GLINT_VTGVGateEnd 0x3058
+#define __GLINT_VTGPolarity 0x3060
+#define __GLINT_VTGFrameRowAddr 0x3068
+#define __GLINT_VTGVLineNumber 0x3070
+#define __GLINT_VTGSerialClk 0x3078
+
+/* VTGPolarity[1:0] - HSync Ctl */
+
+#define GLINT_HSYNC_POLARITY_MASK ((DWORD) 3 << 0)
+#define GLINT_HSYNC_ACTIVE_HIGH ((DWORD) 0 << 0)
+#define GLINT_HSYNC_FORCED_HIGH ((DWORD) 1 << 0)
+#define GLINT_HSYNC_ACTIVE_LOW ((DWORD) 2 << 0)
+#define GLINT_HSYNC_FORCED_LOW ((DWORD) 3 << 0)
+
+/* VTGPolarity[3:2] - Vsync Ctl */
+
+#define GLINT_VSYNC_POLARITY_MASK ((DWORD) 3 << 2)
+#define GLINT_VSYNC_ACTIVE_HIGH ((DWORD) 0 << 2)
+#define GLINT_VSYNC_FORCED_HIGH ((DWORD) 1 << 2)
+#define GLINT_VSYNC_ACTIVE_LOW ((DWORD) 2 << 2)
+#define GLINT_VSYNC_FORCED_LOW ((DWORD) 3 << 2)
+
+/* VTGPolarity[5:4] - Csync Ctl */
+
+#define GLINT_CSYNC_POLARITY_MASK ((DWORD) 3 << 4)
+#define GLINT_CSYNC_ACTIVE_HIGH ((DWORD) 0 << 4)
+#define GLINT_CSYNC_FORCED_HIGH ((DWORD) 1 << 4)
+#define GLINT_CSYNC_ACTIVE_LOW ((DWORD) 2 << 4)
+#define GLINT_CSYNC_FORCED_LOW ((DWORD) 3 << 4)
+
+/* VTGPolarity[7:6] - CBlank Ctl */
+
+#define GLINT_CBLANK_POLARITY_MASK ((DWORD) 3 << 6)
+#define GLINT_CBLANK_ACTIVE_HIGH ((DWORD) 0 << 6)
+#define GLINT_CBLANK_FORCED_HIGH ((DWORD) 1 << 6)
+#define GLINT_CBLANK_ACTIVE_LOW ((DWORD) 2 << 6)
+#define GLINT_CBLANK_FORCED_LOW ((DWORD) 3 << 6)
+
+/* VTGSerialClk[0] - QSF Select */
+
+#define GLINT_QSF_SELECT_MASK ((DWORD) 1 << 0)
+#define GLINT_EXTERNAL_QSF ((DWORD) 0 << 0)
+#define GLINT_INTERNAL_QSF ((DWORD) 1 << 0)
+
+/* VTGSerialClk[1] - Split Size */
+
+#define GLINT_SPLIT_SIZE_MASK ((DWORD) 1 << 1)
+#define GLINT_SPLIT_SIZE_128_WORD ((DWORD) 0 << 1)
+#define GLINT_SPLIT_SIZE_256_WORD ((DWORD) 1 << 1)
+
+/* VTGSerialClk[2] - SCLK Ctl */
+
+#define GLINT_SCLK_CTL_MASK ((DWORD) 1 << 2)
+#define GLINT_SCLK_VCLK ((DWORD) 0 << 2)
+#define GLINT_SCLK_VCLK_DIV_2 ((DWORD) 1 << 2)
+
+/* VTGSerialClk[3] - SOE Ctl */
+
+#define GLINT_SOE_CTL_MASK ((DWORD) 1 << 3)
+#define GLINT_SOE_0_ASSERTED ((DWORD) 0 << 3)
+#define GLINT_SOE_1_ASSERTED ((DWORD) 1 << 3)
+
+/************************************************************************/
+/* EXTERNAL VIDEO CONTROL REGISTERS */
+/************************************************************************/
+
+#define __GLINT_ExternalVideoControl 0x4000
+
+/************************************************************************/
+/* GRAPHICS CORE REGISTERS AND FIFO INTERFACE */
+/************************************************************************/
+
+#define __GLINT_GraphicsCoreRegisters 0x8000
+
+#define __GLINT_GraphicsFIFOInterface 0x2000
+
+/************************************************************************/
+/* GLINT ACCESS MACROS */
+/************************************************************************/
+
+#define GLINT_ADDR(base, offset) \
+( \
+/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \
+ (DWORD) ((volatile UCHAR *)(base) + (offset)) \
+)
+
+#define GLINT_WRITE(base, offset, data) \
+{ \
+/* DWORD_WRITE(GLINT_ADDR((base),(offset)), (data)); */ \
+ WRITE_REGISTER_ULONG(GLINT_ADDR((base),(offset)), (ULONG)(data)); \
+}
+
+#define GLINT_READ(base, offset, data) \
+{ \
+/* DWORD_READ(GLINT_ADDR((base),(offset)), (data)); */ \
+ (ULONG)(data) = READ_REGISTER_ULONG(GLINT_ADDR((base),(ULONG)(offset))); \
+}
+
+typedef struct
+{
+ /* image size */
+
+ long ImageWidth;
+ long ImageHeight;
+ long ImageDepth;
+
+ /* video timing */
+
+ DWORD HLimit;
+ DWORD HSyncStart;
+ DWORD HSyncEnd;
+ DWORD HBlankEnd;
+ DWORD HSyncPolarity;
+ DWORD VLimit;
+ DWORD VSyncStart;
+ DWORD VSyncEnd;
+ DWORD VBlankEnd;
+ DWORD VSyncPolarity;
+
+ /* Ramdac config */
+
+ DWORD PixelFormat;
+ DWORD RefDivCount;
+ DWORD PixelClock;
+
+ } __VIDEO, *VIDEO;
+
+/************************************************************************/
+
+#endif /* __GLINT_H__ */
+
+/************************************************************************/
diff --git a/private/ntos/nthals/halr98b/mips/halp.h b/private/ntos/nthals/halr98b/mips/halp.h
new file mode 100644
index 000000000..25f675868
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/halp.h
@@ -0,0 +1,674 @@
+/*
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+
+
+#include "nthal.h"
+#include "hal.h"
+
+#include "r98bdef.h"
+#include "r98breg.h"
+#include "rxhalp.h"
+#include "hali.h"
+
+#include "xm86.h"
+#include "x86new.h"
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+extern PVOID HalpEisaMemoryBase;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+
+VOID
+HalpInt0Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt1Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt2Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt3Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt4Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt5Dispatch(
+ VOID
+ );
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ );
+
+
+VOID
+HalpTimerDispatch(
+ VOID
+ );
+
+VOID
+HalpEifDispatch(
+ VOID
+ );
+
+VOID
+HalpOutputSegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ );
+
+VOID
+HalpDisplaySegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreatePciStructures (
+ VOID
+ );
+
+ULONG
+HalpPonceNumber (
+ IN ULONG BusNumber
+ );
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ );
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ );
+
+//
+// I change parameter on following large Register access function.
+// v-masank@microsoft.com
+// 5/21/96
+//
+VOID
+HalpReadLargeRegister(
+ IN volatile PULONGLONG VirtualAddress,
+ OUT PULONGLONG Buffer
+ );
+
+VOID
+HalpWriteLargeRegister(
+ IN volatile PULONGLONG VirtualAddress,
+ IN PULONGLONG Buffer
+ );
+
+VOID
+HalpRegisterNmi(
+ VOID
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+BOOLEAN
+HalpHandleEif(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+ULONG
+HalpGetCause(
+ VOID
+ );
+
+
+VOID
+HalpNmiHandler(
+ VOID
+ );
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer,
+ ULONG Write
+);
+
+VOID
+HalpEccMultiBitError(
+ IN ULONG MagellanAllError,
+ IN UCHAR magSet
+ );
+
+VOID
+HalpEcc1bitError(
+ VOID
+ );
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ );
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ );
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ );
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ );
+
+ULONG
+HalpReadPhysicalAddr(
+ IN ULONG PhysicalAddr
+ );
+
+
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ );
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ );
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ );
+
+
+VOID
+HalpLocalDeviceReadWrite(
+ IN ULONG Offset,
+ IN OUT PUCHAR Data,
+ IN ULONG ReadWrite
+ );
+
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+ );
+
+
+ULONG
+HalpReadAndWritePhysicalAddr(
+ IN ULONG PhysicalAddr
+ );
+
+VOID
+WRITE_REGISTER_ULONGLONG(
+ IN PVOID,
+ IN PVOID
+ );
+
+VOID
+READ_REGISTER_ULONGLONG(
+ IN PVOID,
+ IN PVOID
+ );
+
+
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslatePCIBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+#if DBG
+
+
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+);
+
+
+VOID
+R98DebugOutPut(
+ ULONG DebugPrintLevel, // Debug Level
+ PCSZ DebugMessageLed, // For LED strings. shuld be 4Byte.
+ PCSZ DebugMessage, // For DISPLAY or SIO
+ ...
+ );
+
+
+
+#define R98DbgPrint(_x_) R98DebugOutPut _x_
+#else
+#define R98DbgPrint(_x_)
+#endif
+
+
+#ifdef RtlMoveMemory
+#undef RtlMoveMemory
+#undef RtlCopyMemory
+#undef RtlFillMemory
+#undef RtlZeroMemory
+
+#define RtlCopyMemory(Destination,Source,Length) RtlMoveMemory((Destination),(Source),(Length))
+VOID
+RtlMoveMemory (
+ PVOID Destination,
+ CONST VOID *Source,
+ ULONG Length
+ );
+
+VOID
+RtlFillMemory (
+ PVOID Destination,
+ ULONG Length,
+ UCHAR Fill
+ );
+
+VOID
+RtlZeroMemory (
+ PVOID Destination,
+ ULONG Length
+ );
+
+#endif // #ifdef RtlMoveMemory
+
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KSPIN_LOCK HalpIprInterruptLock;
+extern KSPIN_LOCK HalpDieLock;
+extern KSPIN_LOCK HalpLogLock;
+
+
+extern UCHAR HalpChangeIntervalFlg[];
+extern ULONG HalpChangeIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNewTimeIncrement;
+
+extern ULONG HalpNvramValid;
+extern USHORT ErrBufferArea;
+
+LONG HalpECC1bitDisableFlag;
+LONG HalpECC1bitDisableTime;
+ULONG HalpECC1bitScfrBuffer;
+extern volatile ULONG HalpNMIFlag;
+extern ULONG HalpNMIHappend[R98B_MAX_CPU];
+
+
+//
+//
+// Resource usage information
+//
+
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+#if defined(NT_40)
+ ULONG Length;
+#else
+ USHORT Length;
+#endif
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern ADDRESS_USAGE HalpMapRegisterMemorySpace;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+
+#define IRQ_PREFERRED 0x02
+#define IRQ_VALID 0x01
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+);
+
+//
+// Temp definitions to thunk into supporting new bus extension format
+//
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+BOOLEAN
+HalpIoTlbLimitOver(
+ IN PKINTERRUPT Interrupt
+ );
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halr98b/mips/j4cache.s b/private/ntos/nthals/halr98b/mips/j4cache.s
new file mode 100644
index 000000000..5a4a772a9
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/j4cache.s
@@ -0,0 +1,1190 @@
+// "@(#) NEC j4cache.s 1.5 94/12/06 10:46:13"
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+//--
+
+#include "halmips.h"
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.08/22 T.Samezima on SNES
+ *
+ * Add define _DUO_
+ *
+ * K001 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ * K002 94/12/06 N.Kugimoto
+ * Fix Mem32
+ */
+
+#define _DUO_ // S001
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+ DISABLE_INTERRUPTS(t5) // disable interrupts K002
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+//For T5
+ mfc0 t4,prid
+ nop
+ nop
+ nop
+ nop
+ and t4,t4,0xff00 // isolate processor id
+ xor t3,t4,0x900 // check if r10000 processor
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ nop
+ nop
+ nop
+ nop
+ nop
+ bne zero,t3,12f // if ne, not r10000 processor
+ nop
+ cache INDEX_WRITEBACK_INVALIDATE_D,1(a0) // writeback/invalidate on index way 1 for t5
+ nop
+ nop
+ nop
+ nop
+ nop
+12:
+
+
+
+#if defined(_MIPS_R4600) //K001
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+//For T5
+ mfc0 t4,prid
+ nop
+ nop
+ nop
+ nop
+ and t4,t4,0xff00 // isolate processor id
+ xor t3,t4,0x900 // check if r10000 processor
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ nop
+ nop
+ nop
+ nop
+ nop
+ bne zero,t3,22f // if ne, not r10000 processor
+ nop
+ cache INDEX_WRITEBACK_INVALIDATE_SD,1(a0) // writeback/invalidate on index way 1 for t5
+ nop
+ nop
+ nop
+ nop
+ nop
+22:
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30:
+ ENABLE_INTERRUPTS(t5) // enable interrupts K002
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts K002
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+//For T5
+ mfc0 t4,prid
+ nop
+ nop
+ nop
+ nop
+ and t4,t4,0xff00 // isolate processor id
+ xor t3,t4,0x900 // check if r10000 processor
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ bne zero,t3,12f // if ne, not r10000 processor
+ nop
+ cache INDEX_WRITEBACK_INVALIDATE_D,1(a0) // writeback/invalidate on index way 1 for t5
+ nop
+ nop
+ nop
+ nop
+ nop
+12:
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts K002
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+//For T5
+ mfc0 t4,prid
+ nop
+ nop
+ nop
+ nop
+ and t4,t4,0xff00 // isolate processor id
+ xor t3,t4,0x900 // check if r10000 processor
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ nop
+ nop
+ nop
+ nop
+ nop
+ bne zero,t3,12f // if ne, not r10000 processor
+ nop
+ cache INDEX_INVALIDATE_SI,1(a0) // invalidate on index way 1 for t5
+ nop
+ nop
+ nop
+ nop
+ nop
+12:
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+//For T5
+ mfc0 t4,prid
+ nop
+ nop
+ nop
+ nop
+ and t4,t4,0xff00 // isolate processor id
+ xor t3,t4,0x900 // check if r10000 processor
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ nop
+ nop
+ nop
+ nop
+ nop
+ bne zero,t3,32f // if ne, not r10000 processor
+ nop
+ cache INDEX_INVALIDATE_I,1(a0) // invalidate on index way 1 for t5
+ nop
+ nop
+ nop
+ nop
+ nop
+32:
+
+#if defined(_MIPS_R4600) //K001
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t1) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+//For T5
+ mfc0 t4,prid
+ nop
+ nop
+ nop
+ nop
+ and t4,t4,0xff00 // isolate processor id
+ xor t3,t4,0x900 // check if r10000 processor
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ nop
+ nop
+ nop
+ nop
+ nop
+ bne zero,t3,12f // if ne, not r10000 processor
+ nop
+ cache INDEX_INVALIDATE_I,1(a0) // invalidate on index way 1 for t5
+ nop
+ nop
+ nop
+ nop
+ nop
+12:
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t1) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+#if defined(_DUO_)
+
+30: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,30b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+#if defined(_DUO_)
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halr98b/mips/j4flshbf.s b/private/ntos/nthals/halr98b/mips/j4flshbf.s
new file mode 100644
index 000000000..b9a1cda9b
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/j4flshbf.s
@@ -0,0 +1,58 @@
+// "@(#) NEC j4flshbf.s 1.2 94/10/17 11:11:16"
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/j4flshio.c b/private/ntos/nthals/halr98b/mips/j4flshio.c
new file mode 100644
index 000000000..868141c2a
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/j4flshio.c
@@ -0,0 +1,212 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // R98 I/O Cache Supported So Nothing to Do Dma Operation!!.
+ //
+ if (DmaOperation == TRUE){
+ return;
+ }
+
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halr98b/mips/j4prof.c b/private/ntos/nthals/halr98b/mips/j4prof.c
new file mode 100644
index 000000000..7fdd27e98
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/j4prof.c
@@ -0,0 +1,340 @@
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R98B system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+
+ULONG HalpProfileInterval = DEFAULT_PROFILETIMER_INTERVAL;
+
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ *Frequency = RtlConvertUlongToLargeInteger(HalpProfileCountRate);
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ return RtlLargeIntegerAdd(PerformanceCounter,
+ RtlConvertUlongToLargeInteger(CurrentCount));
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT);
+
+ WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].LowPart = 0;
+ HalpPerformanceCounter[Prcb->Number].HighPart = 0;
+
+ WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMCR2.Long, 0x3);
+
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+
+ if (Interval < MINIMUM_PROFILETIMER_INTERVAL) {
+ Interval = MINIMUM_PROFILETIMER_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILETIMER_INTERVAL) {
+ Interval = MAXIMUM_PROFILETIMER_INTERVAL;
+ }
+
+ HalpProfileInterval = Interval;
+
+
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Reserved
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ ULONG TempValue;
+
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ // The R98A/B machines use the External Interrupt for
+ // the profile and clock interrupt. The hardware requires the
+ // value decremented by 1
+
+ TempValue = HalpProfileInterval * COLUMBUS_CLOCK_FREQUENCY / 1000 / 10 - 1;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+ // SR2 - Columbus chip Internal Countdown register. The Columbus
+ // chip decrements this register every Columbus cycle (COLUMBUS_CLOCK_FREQUENCY).
+ // When the value is zero it signals the External Interrupt
+ // CR2 - Columbus chip clock control register. This enables countdown register
+ // and external interrupts.
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue);
+ WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMSR2.Long, TempValue);
+ WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMCR2.Long, 0x3);
+
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Reserved
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+ // Columbus hardware specifies SET VALUE AS VALUE MINUS ONE
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT-1);
+
+ WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT-1);
+ WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMCR2.Long, 0x3);
+
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxbeep.c b/private/ntos/nthals/halr98b/mips/jxbeep.c
new file mode 100644
index 000000000..d39405c78
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxbeep.c
@@ -0,0 +1,131 @@
+#ident "@(#) NEC jxbeep.c 1.2 94/10/17 11:22:04"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxdisp.c b/private/ntos/nthals/halr98b/mips/jxdisp.c
new file mode 100644
index 000000000..03b9d0c7e
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxdisp.c
@@ -0,0 +1,3544 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R4000 or R10000 R98x system.
+
+History:
+
+--*/
+
+/*
+ * NEW CODE for R98B
+ * 1995/09/11 K.Kitagaki
+ *
+ * S001 1995/11/10 T.Samezima
+ * add x86 bios and GLiNT logic
+ *
+ */
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+#include "string.h"
+#include <tga.h>
+#include <glint.h> // S001
+#include <rgb525.h> // S001
+
+#include "pci.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+// S001 vvv
+#define _GLINT60HZ_
+
+#if defined(R96DBG)
+#define DispDbgPrint(STRING) \
+ DbgPrint STRING;
+#else
+#define DispDbgPrint(STRING)
+#endif
+
+//
+// for x86bios emulate
+//
+PCHAR K351UseBios=NULL;
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+#define TAB_SIZE 4
+#define TEXT_ATTR 0x1F
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayINT10Setup (
+ VOID
+ );
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character
+ );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ );
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterOld (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterOld (
+ IN PUCHAR Glyph
+ );
+// S001 ^^^
+
+VOID
+HalpDisplayCirrusSetup (
+ VOID
+ );
+
+BOOLEAN
+HalpCirrusInterpretCmdStream (
+ PUSHORT pusCmdStream
+ );
+
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ );
+
+VOID
+Write_Dbg_Uchar(
+ PUCHAR,
+ UCHAR
+ );
+
+// S001 vvv
+#if 0
+VOID
+RGB525_WRITE(
+ ULONG dac,
+ ULONG offset,
+ UCHAR data );
+
+VOID
+RGB525_SET_REG(
+ ULONG dac,
+ ULONG index,
+ UCHAR data );
+#endif
+
+VOID
+HalpDisplayGlintSetup(
+ VOID
+ );
+// S001 ^^^
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+
+//
+// Define memory access constants for VXL
+//
+
+#define CIRRUS_BASE ((PJAGUAR_REGISTERS)(0x1c403000 | KSEG1_BASE))
+#define CIRRUS_OFFSET ((PUSHORT)0x3b0)
+#define PCI_0_IO_BASE 0x1c000000 // S001
+#define PCI_1_IO_BASE 0x1c400000
+#define CIRRUS_CONTROL_BASE_OFFSET 0x3000
+#define CIRRUS_MEMORY_BASE_LOW 0xa0000000
+
+#define KSEG1_BASE 0xa0000000
+
+#define TGA_REGISTER_BASE ((ULONG)0x403ff000)
+#define PONCE_ADDR_REG ((PULONG)(0x1a000008 | KSEG1_BASE))
+#define PONCE_DATA_REG ((PULONG)(0x1a000010 | KSEG1_BASE))
+#define PONCE_PERRM ((PULONG)(0x1a000810 | KSEG1_BASE))
+#define PONCE_PAERR ((PULONG)(0x1a000800 | KSEG1_BASE))
+#define PONCE_PERST ((PULONG)(0x1a000820 | KSEG1_BASE))
+
+// S001 vvv
+#define GLINT_CONTROL_REGISTER_BASE ((ULONG)0x403ff000)
+#define GLINT_VIDEO_REGISTER_BASE ((ULONG)0x403fe000)
+#define RGB525_REGISTER_BASE ((ULONG)0x403fd000)
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+typedef
+VOID
+(*PHALP_SCROLL_SCREEN) (
+ UCHAR
+ );
+
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+// S001 ^^^
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+ULONG HalpGlintRevisionId; // S001
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayMemoryBase = 0;
+ULONG HalpDisplayResetRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpDisplayPCIDevice = FALSE;
+
+LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0};
+LARGE_INTEGER HalpTgaPhigicalVideo = {0,0};
+LARGE_INTEGER HalpTgaPhigicalVideoCont = {0,0};
+// S001 vvv
+LARGE_INTEGER HalpGlintPhygicalVideo = {0,0};
+LARGE_INTEGER HalpGlintPhygicalVideoCont = {0,0};
+ULONG HalpDisplayType16BPP = FALSE;
+// S001 ^^^
+
+
+ULONG HalpCirrusAlive=FALSE;
+
+typedef struct _R94A_PCI_CONFIGURATION_ADDRESS_REG{
+ ULONG Reserved2: 2;
+ ULONG RegisterNumber: 6;
+ ULONG FunctionNumber: 3;
+ ULONG DeviceNumber: 5;
+ ULONG BusNumber: 8;
+ ULONG Reserved1: 7;
+ ULONG ConfigEnable: 1;
+} R94A_PCI_CONFIGURATION_ADDRESS_REG, *PR94A_PCI_CONFIGURATION_ADDRESS_REG;
+
+BOOLEAN
+HalpCheckPCIDevice (
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+volatile PULONG HalpPonceConfigAddrReg = PONCE_ADDR_REG;
+volatile PULONG HalpPonceConfigDataReg = PONCE_DATA_REG;
+volatile PULONG HalpPoncePerrm = PONCE_PERRM;
+volatile PULONG HalpPoncePaerr = PONCE_PAERR;
+volatile PULONG HalpPoncePerst = PONCE_PERST;
+
+// S001 vvv
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+// S001 ^^^
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+ )
+/*++
+ Routine Description:
+
+ This function moves blocks of memory.
+
+ Arguments:
+
+ Destination - Supplies a pointer to the destination address of
+ the move operation.
+
+ Source - Supplies a pointer to the source address of the move
+ operation.
+
+ Length - Supplies the length, in bytes, of the memory to be moved.
+
+ Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR Remainder;
+ PUCHAR Dstend;
+ PUCHAR Srcend;
+
+ if ( (Source == Destination) || (Length == 0) ) {
+ return;
+ }
+
+ if ((Source < Destination)&((Source + Length) > Destination)) {
+ if((Destination - Source) > 4){
+ Remainder = (UCHAR)(Length &0x03);
+ Length = Length / 4;
+ Dstend = Destination + Length - 4 ;
+ Srcend = Source + Length -4;
+
+ for (; Length > 0; Length--) {
+ *(PULONG)(Dstend) = *(PULONG)(Srcend);
+ Dstend -= 4;
+ Srcend -= 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+ for (; Length > 0; Length--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ } else {
+ if( (Source - Destination) > 4 ){
+ Remainder = (UCHAR)(Length &0x03);
+ Length = Length / 4;
+ for (; Length > 0; Length--) {
+ *(PULONG)(Destination) = *(PULONG)(Source);
+ Destination += 4;
+ Source += 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ return;
+ }
+
+ for (; Length > 0; Length--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ }
+}
+
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+ PCI_SLOT_NUMBER Slot;
+ ULONG ReadValue;
+ PCHAR Options;
+
+ HalpPonceConfigAddrReg = PONCE_ADDR_REG;
+ HalpPonceConfigDataReg = PONCE_DATA_REG;
+ HalpPoncePerrm = PONCE_PERRM;
+ HalpPoncePaerr = PONCE_PAERR;
+ HalpPoncePerst = PONCE_PERST;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ DispDbgPrint(("Hal: HalpInitializeDisplay0\n")); // S001
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ DispDbgPrint(("Hal: ConfigurationEntry Found\n")); // S001
+
+ if (ConfigurationEntry == NULL) {
+ MatchKey = 1;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ // S001 vvv
+ if (LoaderBlock->LoadOptions != NULL) {
+ Options = LoaderBlock->LoadOptions;
+ //
+ // Why link error occure?
+ // So, I change.
+ // v-masank@microsoft.com
+ // 5/21/96
+ //
+ //strupr(Options);
+ K351UseBios = strstr(Options, "USEBIOS");
+ }
+ if(K351UseBios!=NULL){
+ DispDbgPrint(("HAL: Use X86BIOS emulation\n"));
+
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpDisplayControlBase = PCI_0_IO_BASE;
+ }else
+ // S001 ^^^
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "necvdfrb")) {
+ DispDbgPrint(("necvdfrb Config found\n"));
+
+ HalpDisplayControllerSetup = HalpDisplayCirrusSetup;
+ HalpCirrusAlive =TRUE;
+ HalpDisplayCharacter = HalpDisplayCharacterOld; // S001
+ HalpDisplayControlBase = PCI_1_IO_BASE + CIRRUS_CONTROL_BASE_OFFSET;
+ HalpDisplayMemoryBase = CIRRUS_MEMORY_BASE_LOW;
+ HalpDisplayPCIDevice = TRUE;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"10110004")) {
+ //
+ // for DEC21030 PCI
+ //
+ DispDbgPrint(("DEC G/A found\n"));
+
+ HalpDisplayControllerSetup = HalpDisplayTgaSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld; // S001
+ HalpDisplayPCIDevice = TRUE;
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ DispDbgPrint(("DEC G/A found 2vvvv\n"));
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+#if defined (DBG7)
+ DbgPrint("DEVICE-VENDER=0x%x\n",ReadValue);
+#endif
+ DispDbgPrint(("DEC G/A found 200\n"));
+
+ if (ReadValue == 0x00041011){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+#if defined (DBG7)
+ DbgPrint("PCI-COMMAND=0x%x\n",ReadValue);
+#endif
+
+ if ((ReadValue & 0x00000002) == 0x2){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+#if defined (DBG7)
+ DbgPrint("DISPLAY-MEMORY-BASE=0x%x\n",ReadValue);
+#endif
+ HalpDisplayControlBase =
+ (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+ HalpDisplayControlBase |= 0x40000000;
+#if defined (DBG7)
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x14);
+ DbgPrint("DISPLAY-IO-BASE=0x%x\n",ReadValue);
+ DbgPrint("DEC G/A HalpDisplayControlBase=0x%x\n",HalpDisplayControlBase);
+#endif
+ DispDbgPrint(("DEC G/A found 2\n"));
+
+ } else {
+
+ DispDbgPrint(("DEC G/A found 2-1\n"));
+
+ return FALSE;
+ }
+ }
+ }
+
+ DispDbgPrint(("DEC G/A found 3-0\n"));
+
+ if (HalpNumberOfPonce == 2){
+
+ DispDbgPrint(("DEC G/A found 3\n"));
+
+ HalpPonceConfigAddrReg += 0x400;
+ HalpPonceConfigDataReg += 0x400;
+ HalpPoncePerrm += 0x400;
+ HalpPoncePaerr += 0x400;
+ HalpPoncePerst += 0x400;
+
+ for (Slot.u.bits.DeviceNumber = 5; Slot.u.bits.DeviceNumber < 7; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+#if defined (DBG7)
+ DbgPrint("DEVICE-VENDER=0x%x\n",ReadValue);
+#endif
+
+ if (ReadValue == 0x00041011){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+#if defined (DBG7)
+ DbgPrint("PCI-COMMAND=0x%x\n",ReadValue);
+#endif
+
+ if ((ReadValue & 0x00000002) == 0x2){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+#if defined (DBG7)
+ DbgPrint("DISPLAY-MEMORY-BASE=0x%x\n",ReadValue);
+#endif
+ HalpDisplayControlBase =
+ (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+ HalpDisplayControlBase |= 0x80000000;
+
+#if defined (DBG7)
+ DbgPrint("DEC G/A HalpDisplayControlBase=0x%x\n",HalpDisplayControlBase);
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x14);
+ DbgPrint("DISPLAY-IO-BASE=0x%x\n",ReadValue);
+#endif
+
+ DispDbgPrint(("DEC G/A found 4\n"));
+
+ } else {
+
+ DispDbgPrint(("DEC G/A found 4-1\n"));
+
+ return FALSE;
+ }
+ }
+ }
+ } else {
+
+ DispDbgPrint(("DEC G/A found 5\n"));
+
+ HalpPonceConfigAddrReg += 0x800;
+ HalpPonceConfigDataReg += 0x800;
+ HalpPoncePerrm += 0x800;
+ HalpPoncePaerr += 0x800;
+ HalpPoncePerst += 0x800;
+
+ for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 5; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (ReadValue == 0x00041011){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+ if ((ReadValue & 0x00000002) == 0x2){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ HalpDisplayControlBase =
+ (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+ HalpDisplayControlBase |= 0xC0000000;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ }
+ // S001 vvv
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"3D3D0001")) {
+
+ ULONG ponceNumber;
+ ULONG glintFound=FALSE;
+
+ //
+ // for GLINT 300SX PCI
+ //
+
+ DispDbgPrint(("Hal: GLiNT config entry found\n"));
+
+ HalpDisplayControllerSetup = HalpDisplayGlintSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterOld;
+ HalpDisplayPCIDevice = TRUE;
+ HalpDisplayType16BPP = TRUE;
+
+ //
+ // FunctionNumber always zero
+ //
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ for (ponceNumber = 0; ponceNumber < R98B_MAX_PONCE ; ponceNumber++) {
+ ULONG startDevNum;
+ ULONG endDevNum;
+ ULONG addressOffset;
+
+ HalpPonceConfigAddrReg = PONCE_ADDR_REG + (ponceNumber * 0x400);
+ HalpPonceConfigDataReg = PONCE_DATA_REG + (ponceNumber * 0x400);
+ HalpPoncePerrm = PONCE_PERRM + (ponceNumber * 0x400);
+ HalpPoncePaerr = PONCE_PAERR + (ponceNumber * 0x400);
+ HalpPoncePerst = PONCE_PERST + (ponceNumber * 0x400);
+
+ addressOffset = (ponceNumber+1) * 0x40000000;
+
+ DispDbgPrint(("Hal: search GLiNT board on PONCE#%d\n", ponceNumber));
+
+ switch(ponceNumber){
+ case 0:
+ startDevNum = 2;
+ endDevNum = 5;
+ break;
+
+ case 1:
+ if (HalpNumberOfPonce == 3) {
+ DispDbgPrint(("Hal: Skip PONCE#1\n"));
+ continue;
+ }
+ startDevNum = 3;
+ endDevNum = 6;
+ break;
+
+ case 2:
+ if (HalpNumberOfPonce == 2) {
+ DispDbgPrint(("Hal: Skip PONCE#2\n"));
+ continue;
+ }
+ startDevNum = 1;
+ endDevNum = 4;
+ break;
+
+ default:
+ continue;
+ }
+
+ for (Slot.u.bits.DeviceNumber = startDevNum;
+ Slot.u.bits.DeviceNumber <= endDevNum;
+ Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (ReadValue == 0x00013d3d){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4);
+
+ DispDbgPrint(("Hal: GLiNT found on PONCE#%d, Device=%d\n", ponceNumber,Slot.u.bits.DeviceNumber));
+
+ //
+ // GLINT 300SX has no I/O space regions
+ //
+
+ if (ReadValue & 0x2){
+
+ //
+ // Control Registers
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ HalpDisplayControlBase = (ReadValue & 0xfffffff0);
+ HalpDisplayControlBase |= addressOffset;
+
+ DispDbgPrint(("Hal: GLiNT HalpDisplayControlBase=0x%08lx\n", HalpDisplayControlBase));
+ //
+ // Framebuffer
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ HalpDisplayMemoryBase = (ReadValue & 0xfffffff0);
+ HalpDisplayMemoryBase |= addressOffset;
+
+ DispDbgPrint(("Hal: GLiNT HalpDisplayMemoryBase=0x%08lx\n", HalpDisplayMemoryBase));
+ //
+ // Revision ID
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x08);
+
+ HalpGlintRevisionId = (ReadValue & 0x000000ff);
+
+ DispDbgPrint(("Hal: GLiNT HalpGlintRevisionId=0x%08lx\n", HalpGlintRevisionId));
+
+ //
+ // Enable ROM.
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x30);
+ ReadValue |= 0x1;
+ HalpWritePCIConfigUlongByOffset(Slot,&ReadValue, 0x30);
+
+ glintFound = TRUE;
+
+ break;
+
+ } else {
+ DispDbgPrint(("Hal: GLiNT have not I/O space\n"));
+
+ return FALSE;
+
+ }
+ }
+ }
+
+ if(glintFound == TRUE) {
+ DispDbgPrint(("Hal: GLiNT adapter already found\n"));
+ break;
+ }
+ }
+
+ } else {
+ DispDbgPrint(("DisplayTypeUnknown\n"));
+
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpDisplayControlBase = PCI_0_IO_BASE;
+ HalpDisplayTypeUnknown = TRUE;
+ // S001 ^^^
+ }
+
+ Child = ConfigurationEntry->Child;
+
+ DispDbgPrint(("Hal: parameters read start\n"));
+
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpScrollLine =
+ 1024 * HalpCharacterHeight;
+ // S001 vvv
+ } else if (HalpDisplayType16BPP) {
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight * sizeof(USHORT);
+ // S001 ^^^
+ } else {
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+ }
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpDisplayWidth =
+ 1024 / HalpCharacterWidth;
+
+ }else{
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+ }
+
+ DispDbgPrint(("Hal: HalpDisplayText = %d\n", HalpDisplayText));
+ DispDbgPrint(("Hal: HalpDisplayWidth = %d\n", HalpDisplayWidth));
+ DispDbgPrint(("Hal: HalpScrollLine = %d\n", HalpScrollLine));
+ DispDbgPrint(("Hal: HalpScrollLength = %d\n", HalpScrollLength));
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ DispDbgPrint(("Hal: Mem get \n"));
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+ Pte.C = UNCACHED_POLICY;
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ // S001 vvv
+ if (HalpDisplayControllerSetup == HalpDisplayINT10Setup) {
+
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = 0x40000000;
+
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }else
+ // S001 ^^^
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = CIRRUS_MEMORY_BASE_LOW;
+
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+
+ HalpTgaPhigicalVideo.HighPart = 1;
+ HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET;
+
+#if defined (DBG7)
+ DbgPrint("DEC G/A HalpTgaPhigicalVideo.HighPart=0x%x\n",HalpTgaPhigicalVideo.HighPart);
+ DbgPrint("DEC G/A HalpTgaPhigicalVideo.LowPart=0x%x\n",HalpTgaPhigicalVideo.LowPart);
+#endif
+
+ Pte.PFN = (HalpTgaPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+
+ }
+ // S001 vvv
+ else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021
+
+ HalpGlintPhygicalVideo.HighPart = 1;
+ HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase;
+
+ Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+ // S001 ^^^
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+ Pte.C = UNCACHED_POLICY;
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ HalpTgaPhigicalVideo.HighPart = 1;
+ HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase;
+ Pte.PFN = (HalpDisplayControlBase >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ // S001 vvv
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) {
+
+ HalpGlintPhygicalVideoCont.HighPart = 1;
+ HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase;
+
+ //
+ // IBM RGB525
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 2) = Pte;
+
+ //
+ // GLINT 300SX Internal Video Registers
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 1) = Pte;
+
+ //
+ // GLINT 300SX Control Status Registers
+ //
+
+ Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayINT10Setup){
+ DispDbgPrint(("HAL: Map x86 and cirrus control register\n"));
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) {
+ *PageFrame-- = Pte;
+ DispDbgPrint(("HAL: Map index %x pfn %x\n",Index,Pte.PFN));
+ Pte.PFN -= 1;
+ }
+ // S001 ^^^
+ } else {
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ // S001 vvv
+ if(HalpDisplayControllerSetup == HalpDisplayINT10Setup){
+ if (HalpInitializeX86DisplayAdapter()) {
+// HalpDisplayControllerSetup(); // initialize twice bugbug
+ }else{
+ return FALSE;
+ }
+ }
+ // S001 ^^^
+ HalpDisplayControllerSetup();
+
+ HalpInitDisplayStringIntoNvram();
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+
+ HalpSetInitDisplayTimeStamp();
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpSuccessOsStartUp();
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpResetDisplayParameters=ResetDisplayParameters; // S001
+ HalpMrcModeChange((UCHAR)MRC_OP_DUMP_ONLY_NMI);
+ HalpDisplayOwnedByHal = FALSE;
+
+ DispDbgPrint(("HAL: DisplayOwnedByHal = FALSE, DispResetRoutine = 0x%x\n",
+ (ULONG)HalpResetDisplayParameters));
+
+ return;
+}
+
+VOID
+HalpDisplayCirrusSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Cirrus VGA display controlleer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG dac_address, dac_reg, dac_dmyread;
+
+#if defined(DBCS) && defined(_MIPS_)
+ ULONG verticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+ if( verticalFrequency < 66 ) {
+ DispDbgPrint(("HAL: 640x480 60Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ DispDbgPrint(("HAL: 640x480 72Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 800:
+ if( verticalFrequency < 58 ) {
+ DispDbgPrint(("HAL: 800x600 56Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_56);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 66 ) {
+ DispDbgPrint(("HAL: 800x600 60Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ DispDbgPrint(("HAL: 800x600 72Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 1024:
+ if( verticalFrequency < 52 ) {
+ DispDbgPrint(("HAL: 1024x768 87Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 65 ) {
+ DispDbgPrint(("HAL: 1024x768 60Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 78 ) {
+ DispDbgPrint(("HAL: 1024x768 70Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+ DispDbgPrint(("HAL: 1024x768 87Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+ default:
+ DispDbgPrint(("HAL: 640x480 60Hz setup\n"));
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+// return;
+ }
+#else // defined(DBCS) && defined(_MIPS_)
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+
+ DispDbgPrint(("640x480 setup\n"));
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_640x480_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 800:
+
+ DispDbgPrint(("800x600 setup\n"));
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_800x600_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 1024:
+
+ DispDbgPrint(("1024x768 setup\n"));
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_1024x768_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ default:
+ return;
+ }
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ DispDbgPrint(("color set\n"));
+
+ dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT;
+ dac_dmyread = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_STATE_PORT;
+ dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT;
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ READ_PORT_UCHAR((PUCHAR)dac_dmyread);
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2));
+ READ_PORT_UCHAR((PUCHAR)dac_dmyread);
+
+ //
+ // Set the video memory to address color one.
+ //
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (1024 *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+BOOLEAN
+HalpCirrusInterpretCmdStream(
+ PUSHORT pusCmdStream
+ )
+
+/*++
+
+Routine Description:
+
+ Interprets the appropriate command array to set up VGA registers for the
+ requested mode. Typically used to set the VGA into a particular mode by
+ programming all of the registers
+
+Arguments:
+
+
+ pusCmdStream - array of commands to be interpreted.
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+Revision History:
+--*/
+
+
+
+{
+ ULONG ulCmd;
+ ULONG ulPort;
+ UCHAR jValue;
+ USHORT usValue;
+ ULONG culCount;
+ ULONG ulIndex;
+ ULONG ulBase;
+ if (pusCmdStream == NULL) {
+
+ return TRUE;
+ }
+
+ ulBase = (ULONG)CIRRUS_BASE+0x3b0;
+
+ //
+ // Now set the adapter to the desired mode.
+ //
+
+ while ((ulCmd = *pusCmdStream++) != EOD) {
+
+ //
+ // Determine major command type
+ //
+
+ switch (ulCmd & 0xF0) {
+
+ //
+ // Basic input/output command
+ //
+
+ case INOUT:
+
+ //
+ // Determine type of inout instruction
+ //
+
+ if (!(ulCmd & IO)) {
+
+ //
+ // Out instruction. Single or multiple outs?
+ //
+
+ if (!(ulCmd & MULTI)) {
+
+ //
+ // Single out. Byte or word out?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // Single byte out
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort),
+ jValue);
+
+ } else {
+
+ //
+ // Single word out
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff));
+
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8));
+
+ }
+
+ } else {
+
+ //
+ // Output a string of values
+ // Byte or word outs?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // String byte outs. Do in a loop; can't use
+ // VideoPortWritePortBufferUchar because the data
+ // is in USHORT form
+ //
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+
+ while (culCount--) {
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ jValue);
+
+ }
+
+ } else {
+
+ //
+ // String word outs
+ //
+
+ ulPort = *pusCmdStream++;
+ culCount = *pusCmdStream++;
+//
+// Buffering out is not use on the Miniport Driver for R96 machine.
+//
+
+ while(culCount--)
+ {
+ usValue = *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort), (UCHAR) (usValue & 0x00ff));
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort+1), (UCHAR) (usValue >> 8));
+
+ }
+
+ }
+
+ }
+
+ } else {
+
+ // In instruction
+ //
+ // Currently, string in instructions aren't supported; all
+ // in instructions are handled as single-byte ins
+ //
+ // Byte or word in?
+ //
+
+ if (!(ulCmd & BW)) {
+ //
+ // Single byte in
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+
+ } else {
+
+ //
+ // Single word in
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = READ_REGISTER_USHORT((PUSHORT)
+ (ulBase+ulPort));
+ }
+
+ }
+
+ break;
+
+ //
+ // Higher-level input/output commands
+ //
+
+ case METAOUT:
+
+ //
+ // Determine type of metaout command, based on minor
+ // command field
+ //
+ switch (ulCmd & 0x0F) {
+
+ //
+ // Indexed outs
+ //
+
+ case INDXOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ usValue = (USHORT) (ulIndex +
+ (((ULONG)(*pusCmdStream++)) << 8));
+
+ Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff));
+
+ Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8));
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // Masked out (read, AND, XOR, write)
+ //
+
+ case MASKOUT:
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+ jValue &= *pusCmdStream++;
+ jValue ^= *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulBase + ulPort,
+ jValue);
+
+ break;
+
+ //
+ // Attribute Controller out
+ //
+
+ case ATCOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ // Write Attribute Controller index
+
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ (UCHAR)ulIndex);
+
+
+ // Write Attribute Controller data
+ jValue = (UCHAR) *pusCmdStream++;
+
+ Write_Dbg_Uchar((PUCHAR)ulPort, jValue);
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // None of the above; error
+ //
+ default:
+
+ return FALSE;
+
+ }
+
+
+ break;
+
+ //
+ // NOP
+ //
+
+ case NCMD:
+
+ break;
+
+ //
+ // Unknown command; error
+ //
+
+ default:
+
+ return FALSE;
+
+ }
+
+ }
+
+ return TRUE;
+
+} // end HalpCirrusInterpretCmdStream()
+
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Tga(DEC21030) Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PUCHAR PLLbits;
+ ULONG i, j;
+ ULONG PLLdata;
+ ULONG ColorData;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 };
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+
+ const UCHAR Vga_Ini_ColorTable[48] =
+ { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B,
+ VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B,
+ VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G,
+ VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B,
+ VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B,
+ VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B,
+ VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B,
+ VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B,
+ VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B,
+ VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B,
+ VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B,
+ VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B,
+ VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B,
+ VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B,
+ VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B,
+ VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B
+ };
+
+ DispDbgPrint(("TGA Set Up IN\n"));
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ //
+ // Write the PLL
+ //
+
+ // Select PLL Data
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits640x480_72;
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60;
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits800x600_72;
+ } else {
+ PLLbits = (PVOID)PLLbits800x600_60;
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ PLLbits = (PVOID)PLLbits1024x768_60;
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60;
+ }
+
+ // Set PLL Data
+ for( i = 0; i <= 6; i++ ){
+ for( j = 0; j <= 7; j++ ){
+ PLLdata = (PLLbits[i] >> (7-j)) & 1;
+ if( i == 6 && j == 7 )
+ PLLdata |= 2; // Set ~HOLD bit on last write
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata);
+ }
+ }
+#if defined (DBG7)
+ DbgPrint("TGA Set Up 1\n");
+
+ DbgPrint("TGA_REGISTER_BASE=0x%x\n",TGA_REGISTER_BASE);
+ DbgPrint("COMMAND_STATUS=0x%x\n",COMMAND_STATUS);
+ DbgPrint("TGA_REGISTER_BASE + COMMAND_STATUS=0x%x\n",(READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) )));
+#endif
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){
+ }
+#if defined (DBG7)
+ DbgPrint("TGA Set Up 2\n");
+#endif
+
+ // Set to Deep Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 );
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){
+ }
+#if defined (DBG7)
+ DbgPrint("TGA Set Up 3\n");
+#endif
+
+ // Set to Video Base Address Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 );
+
+ // Set to Plane Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff );
+
+ // Set to Pixel Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff );
+
+ // Set to Raster Operation
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d );
+
+ // Set to Block Color Register 0
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 );
+
+ // Set to Block Color Register 1
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 );
+
+ //
+ // Init. video timing registers for each resolution
+ //
+
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x3c294a0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x1a7a4c8 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x2681cc8 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ //60Hz Only
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x4889300 ); // // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+
+ // Set to Raster Operation Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 );
+#if defined (DBG7)
+ DbgPrint("TGA Set Up 4\n");
+#endif
+
+ KeStallExecutionProcessor(10000L);
+#if defined (DBG7)
+ DbgPrint("TGA Set Up 5\n");
+#endif
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 );
+
+ //
+ // set pass thru on off & on again to verify operation
+ //
+
+ // EEPROM Write Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 );
+
+ //
+ // Fill palette
+ //
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 );
+
+ for( i = 0; i < 48; i++ ){
+ ColorData = Vga_Ini_ColorTable[i];
+ ColorData |= 0x200;
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData );
+ }
+
+ for( i = 48; i < 768; i++ ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 );
+ }
+
+ // Set to Video Valid Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 );
+
+ //
+ // Set Video Memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+#if defined (DBG7)
+ DbgPrint("TGA Set Up End\n");
+#endif
+
+ return;
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte;
+ ULONG NowDisplayControlBase;
+ ULONG NowDisplayMemoryBase;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ LONG Index;
+ PCI_SLOT_NUMBER Slot;
+ ULONG ReadValue;
+ ULONG cpu;
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+// DispDbgPrint(("HalDisplayString\n"));
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ // S001 vvv
+ HalpPonceConfigAddrReg = PONCE_ADDR_REG;
+ HalpPonceConfigDataReg = PONCE_DATA_REG;
+ HalpPoncePerrm = PONCE_PERRM;
+ HalpPoncePaerr = PONCE_PAERR;
+ HalpPoncePerst = PONCE_PERST;
+ // S001 ^^^
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ if (HalpDisplayPCIDevice == TRUE){
+
+ //
+ // the display type is PCI
+ // check physical address and reinitialize PTE
+ // we assume that the device has no function
+ //
+
+ Slot.u.bits.FunctionNumber = 0;
+
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+
+ HalpPonceConfigAddrReg += 0x400;
+ HalpPonceConfigDataReg += 0x400;
+ HalpPoncePerrm += 0x400;
+ HalpPoncePaerr += 0x400;
+ HalpPoncePerst += 0x400;
+
+ Slot.u.bits.DeviceNumber = 4;
+
+ HalpReadPCIConfigUlongByOffset( Slot,&ReadValue,0x14);
+
+ DispDbgPrint(("CirrusControlBase:=0x%x\n",ReadValue));
+
+ NowDisplayControlBase = (ReadValue & 0x0000fc00) + PCI_1_IO_BASE;
+ HalpReadPCIConfigUlongByOffset( Slot,&ReadValue,0x10);
+
+ DispDbgPrint(("NowDisplayControlBase = 0x%x\n",NowDisplayControlBase));
+ DispDbgPrint(("CirrusMemoryBase:=0x%x\n",ReadValue));
+
+ NowDisplayMemoryBase = (ReadValue & 0xff000000) + 0x80000000;
+
+ DispDbgPrint(("NowDisplayMemoryBase = 0x%x\n",NowDisplayMemoryBase));
+
+ } else {
+
+ for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){
+ //
+ // DEC 21030
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ DispDbgPrint(("DECControlBase:=0x%x\n",ReadValue));
+ NowDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+ NowDisplayControlBase |= 0x40000000;
+ NowDisplayMemoryBase = 0;
+
+ // S001 vvv
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){
+ //
+ // GLINT 300SX
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0);
+ NowDisplayControlBase |= 0x40000000;
+ DispDbgPrint(("HAL:GLiNTCtrlBase=0x%08lx,Now=0x%08lx\n",
+ ReadValue, NowDisplayControlBase));
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ NowDisplayMemoryBase = (ReadValue & 0xfffffff0);
+ NowDisplayMemoryBase |= 0x40000000;
+ DispDbgPrint(("HAL:GLiNTMemBase =0x%08lx,Now=0x%08lx\n",
+ ReadValue, NowDisplayMemoryBase));
+ // S001 ^^^
+ }
+ }
+ if (HalpNumberOfPonce == 2){
+
+ HalpPonceConfigAddrReg += 0x400;
+ HalpPonceConfigDataReg += 0x400;
+ HalpPoncePerrm += 0x400;
+ HalpPoncePaerr += 0x400;
+ HalpPoncePerst += 0x400;
+
+ for (Slot.u.bits.DeviceNumber = 5; Slot.u.bits.DeviceNumber < 7; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){
+ //
+ // DEC 21030
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+ NowDisplayControlBase |= 0x80000000;
+ NowDisplayMemoryBase = 0;
+ // S001 vvv
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){
+ //
+ // GLINT 300SX
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0);
+ NowDisplayControlBase |= 0x80000000;
+ DispDbgPrint(("HAL:GLiNTCtrlBase=0x%08lx,Now=0x%08lx\n",
+ ReadValue, NowDisplayControlBase));
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ NowDisplayMemoryBase = (ReadValue & 0xfffffff0);
+ NowDisplayMemoryBase |= 0x80000000;
+ DispDbgPrint(("HAL:GLiNTMemBase =0x%08lx,Now=0x%08lx\n",
+ ReadValue, NowDisplayMemoryBase));
+ // S001 ^^^
+ }
+ }
+ } else {
+ HalpPonceConfigAddrReg += 0x800;
+ HalpPonceConfigDataReg += 0x800;
+ HalpPoncePerrm += 0x800;
+ HalpPoncePaerr += 0x800;
+ HalpPoncePerst += 0x800;
+
+ for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 5; Slot.u.bits.DeviceNumber++){
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0);
+
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){
+
+ //
+ // DEC 21030
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET;
+ NowDisplayControlBase |= 0xC0000000;
+ NowDisplayMemoryBase = 0;
+
+ // S001 vvv
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){
+ //
+ // GLINT 300SX
+ //
+
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10);
+ NowDisplayControlBase = (ReadValue & 0xfffffff0);
+ NowDisplayControlBase |= 0xc0000000;
+ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18);
+ NowDisplayMemoryBase = (ReadValue & 0xfffffff0);
+ NowDisplayMemoryBase |= 0xc0000000;
+ // S001 ^^^
+ }
+ }
+ }
+ }
+
+ //
+ // check to see if address has been changed
+ //
+
+ if (HalpDisplayControlBase != NowDisplayControlBase ||
+ HalpDisplayMemoryBase != NowDisplayMemoryBase){
+
+ // Called by OS, so reinitialize PTE
+ HalpDisplayControlBase = NowDisplayControlBase;
+ HalpDisplayMemoryBase = NowDisplayMemoryBase;
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+ Pte.C = UNCACHED_POLICY;
+
+ PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+ HalpCirrusPhigicalVideo.HighPart = 1;
+ HalpCirrusPhigicalVideo.LowPart = HalpDisplayMemoryBase;
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ // S001 vvv
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) {
+ HalpGlintPhygicalVideo.HighPart = 1;
+ HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase;
+ Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT);
+ // S001 ^^^
+ }
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+
+ } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){
+ HalpTgaPhigicalVideoCont.HighPart = 1;
+ HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase;
+ Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+ // S001 vvv
+ } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) {
+ HalpGlintPhygicalVideoCont.HighPart = 1;
+ HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase;
+
+ //
+ // IBM RGB525
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 2) = Pte;
+
+ //
+ // GLINT 300SX Internal Video Registers
+ //
+
+ Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *(PageFrame - 1) = Pte;
+
+ //
+ // GLINT 300SX Control Status Registers
+ //
+
+ Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT);
+ *PageFrame = Pte;
+ // S001 ^^^
+ }
+ }
+ }
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ // S001 vvv
+
+ DispDbgPrint(("HAL: Re Initialize Controller\n"));
+ DispDbgPrint(("HAL: Str = %s\n",String));
+
+ if (HalpResetDisplayParameters &&
+ (HalpDisplayControllerSetup == HalpDisplayINT10Setup) ) {
+ //
+ // Video work-around. The video driver has a reset function,
+ // call it before resetting the system in case the bios doesn't
+ // know how to reset the displays video mode.
+ //
+
+ DispDbgPrint(("HAL: Call x86 reset routine\n"));
+
+ if (HalpResetDisplayParameters(80, 50)) {
+ }
+ }
+ // S001 ^^^
+
+ if(HalpNMIFlag == 0){
+ //
+ // Non NMI. It is Panic.
+ //
+ HalpMrcModeChange((UCHAR)MRC_OP_DUMP_AND_POWERSW_NMI);
+ //
+ // Do not make eif. retun only at dump key
+ //
+ for (cpu=0;cpu < R98B_MAX_CPU;cpu++)
+ HalpNMIHappend[cpu] = 1;
+ }
+
+ DispDbgPrint(("HAL: Call DisplayControllerSetup\n"));
+
+ HalpDisplayControllerSetup();
+ HalpInitDisplayStringIntoNvram();
+// HalpResetX86DisplayAdapter(); /* for X86 */
+ }
+
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ HalpStringBufferCopyToNvram();
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacterOld (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUSHORT DestinationShort; // S001
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+#if 0
+ RtlMoveMemory((PVOID)VIDEO_MEMORY_BASE,
+ (PVOID)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+#else
+ HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE,
+ (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+#endif
+
+ // S001 vvv
+ if (HalpDisplayType16BPP) {
+ DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + HalpScrollLength); // M022
+ } else {
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ }
+
+ if (HalpDisplayType16BPP) {
+ for (Index = 0; Index < HalpScrollLine/2; Index += 1) {
+ *DestinationShort++ = (USHORT)0x000f;
+ }
+ } else {
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+ // S001 ^^^
+ }
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ HalpStringBufferCopyToNvram();
+ HalStringIntoBufferStart( HalpColumn, HalpRow );
+
+ } else {
+ HalStringIntoBuffer( Character );
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterOld((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+// S001 vvv
+VOID
+HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollINT10(1);
+ }
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollINT10( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterINT10(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollINT10(1);
+ }
+ }
+ HalpOutputCharacterINT10(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+// S001 ^^^
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacterOld(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUSHORT DestinationShort; // S001
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ // S001 vvv
+ if (HalpDisplayType16BPP) {
+ DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth * sizeof(USHORT)));
+ } else {
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+ }
+ // S001 ^^^
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ // S001 vvv
+ if (HalpDisplayType16BPP) {
+ if (FontValue >> 31)
+ *DestinationShort++ = (USHORT)0xffff;
+ else
+ *DestinationShort++ = (USHORT)0x000f;
+ }else{
+ *Destination++ = (UCHAR) (FontValue >> 31) ^ 1;
+ }
+ // S001 ^^^
+ FontValue <<= 1;
+ }
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ Destination +=
+ (1024 - HalpCharacterWidth);
+ // S001 vvv
+ } else if (HalpDisplayType16BPP){
+ DestinationShort +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ // S001 ^^^
+ } else {
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+ }
+ HalpColumn += 1;
+ return;
+}
+
+VOID
+Write_Dbg_Uchar(
+ PUCHAR Ioadress,
+ UCHAR Moji
+ )
+{
+// DispDbgPrint(("Disply I/O Adress %x Char %x \n",Ioadress,Moji));
+
+ WRITE_PORT_UCHAR(Ioadress,Moji);
+}
+
+// S001 vvv
+VOID
+HalpOutputCharacterINT10 (
+ IN UCHAR Character
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 2 << 8; // AH = 2
+ Ebx = 0; // BH = page number
+ Edx = (HalpRow << 8) + HalpColumn;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
+ Ebx = 0;
+ Ecx = 1;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ HalpColumn += 1;
+}
+
+VOID
+HalpScrollINT10 (
+ IN UCHAR LinesToScroll
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 6 << 8; // AH = 6 (scroll up)
+ Eax |= LinesToScroll; // AL = lines to scroll
+ Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
+ Ecx = 0; // CH,CL = upper left
+ Edx = ((HalpDisplayText - 1) << 8)
+ + (HalpDisplayWidth - 1); // DH,DL = lower right
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+VOID
+HalpDisplayINT10Setup (
+ VOID
+ )
+{
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 50;
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ HalpResetX86DisplayAdapter(); // for compaq q-vision reset
+
+ //
+ // Load 8x8 font 80x50 on VGA
+ //
+ Eax = 0x1112; // AH = 11 AL=12
+ Ebx = 0;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Set cursor to (0,0)
+ //
+ Eax = 0x02 << 8; // AH = 2
+ Ebx = 0; // BH = page Number
+ Edx = 0; // DH = row DL = column
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Make screen white on blue by scrolling entire screen
+ //
+ Eax = 0x06 << 8; // AH = 6 AL = 0
+ Ebx = TEXT_ATTR << 8; // BH = attribute
+ Ecx = 0; // (x,y) upper left
+ Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
+ Edx += HalpScrollLine/2;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+}
+// S001 ^^^
+BOOLEAN
+HalpCheckPCIDevice (
+ IN PCI_SLOT_NUMBER Slot
+ )
+
+/*++
+ Routine Description:
+
+ This function checks if spcified PCI slot is valid.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+
+ Return Value:
+
+ TRUE - specified slot is valid
+ FALSE - specified slot is invalid
+
+--*/
+
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ BOOLEAN ReturnValue;
+ ULONG OrigData;
+ ULONG IdValue;
+
+ //
+ // Disable PCI-MasterAbort interrupt during configration read.
+ //
+
+// DispDbgPrint(("Hal: Chk perrmAddr=0x%x, paerrAddr=0x%x\n",HalpPoncePerrm, HalpPoncePaerr));
+
+ OrigData = READ_REGISTER_ULONG(HalpPoncePerrm);
+
+// DispDbgPrint(("Hal: origdata perrm data=0x%08lx\n",OrigData));
+
+ WRITE_REGISTER_ULONG(HalpPoncePerrm, OrigData | 0x00800000);
+
+ //
+ // read VendorID and DeviceID of the specified slot
+ //
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+
+// DispDbgPrint(("Hal: deviceNum=%d, funcNum=%d\n",Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber));
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+ IdValue = READ_REGISTER_ULONG(HalpPonceConfigDataReg);
+
+ //
+ // Release spinlock
+ //
+
+ if ((USHORT)(IdValue & 0xffff) == 0xffff){
+
+ //
+ // waiting until ReceivedMasterAbort bit is set
+ //
+
+// DispDbgPrint(("Hal: chk 0\n"));
+// DispDbgPrint(("Hal: PERRI = 0x%x\n",READ_REGISTER_ULONG((PULONG)0xba000818)));
+// DispDbgPrint(("Hal: paerr = 0x%x\n",READ_REGISTER_ULONG(HalpPoncePaerr)));
+
+ //
+ // clear the ReceivedMasterAbort bit
+ //
+
+ WRITE_REGISTER_ULONG(HalpPoncePerst, 0x00800000);
+
+ //
+ // Clear memory address error registers.
+ //
+
+// {
+// LARGE_INTEGER registerLarge;
+// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
+// }
+
+// DispDbgPrint(("Hal: chk 1\n"));
+
+ ReturnValue = FALSE;
+
+ } else {
+
+// DispDbgPrint(("Hal: chk 2\n"));
+
+ ReturnValue = TRUE;
+
+ }
+
+ //
+ // Restore the PCIInterruptEnable register.
+ //
+
+ WRITE_REGISTER_ULONG(HalpPoncePerrm, OrigData);
+
+// DispDbgPrint(("Hal: chk 3\n"));
+
+ return ReturnValue;
+}
+// S001 vvv
+VOID
+HalpDisplayGlintSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GLINT 300SX Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ __VIDEO __Video;
+ VIDEO Video = &__Video;
+ long ClockDivider;
+
+ // for initialize ramdac
+ ULONG Dac = RGB525_REGISTER_BASE;
+ UCHAR ByteVal;
+
+ // for initialize timing
+ ULONG Glint = GLINT_VIDEO_REGISTER_BASE - 0x3000;
+
+ // for initialize control
+ ULONG SerialClk;
+ ULONG Temp;
+ ULONG Data;
+ ULONG Mask;
+
+ // for initialize RampLut
+ ULONG Index;
+
+ // for clear the screen
+ PULONG DestinationUlong;
+ ULONG Length;
+
+ /* check revision id R01 or R02. assume 40MHz(R01) or 50MHz(R02) reference clock for now */
+ DispDbgPrint(("Hal: GLiNT Display setup\n"));
+
+ if ( HalpGlintRevisionId == 0){
+ Video->RefDivCount = RGB525_PLL_REFCLK_40_MHz;
+ } else {
+ Video->RefDivCount = RGB525_PLL_REFCLK_50_MHz;
+ }
+
+ //
+ // Calculate vertical frequency.
+ //
+
+#if defined(_GLINT60HZ_)
+
+ VerticalFrequency = 60;
+
+#else
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+#endif // _GLINT60HZ_
+
+ DispDbgPrint(("HAL: VerticalResolution=%d\n",HalpMonitorConfigurationData.VerticalResolution));
+ DispDbgPrint(("HAL: horizontalTotal=%d\n",horizontalTotal));
+ DispDbgPrint(("HAL: verticalTotal=%d\n",verticalTotal));
+
+ //
+ // Initialize video data
+ //
+
+ /* get timing values for named resolution */
+
+ if ( HalpMonitorConfigurationData.HorizontalResolution == 1280
+ && HalpMonitorConfigurationData.VerticalResolution == 1024
+ && VerticalFrequency == 75)
+ {
+ DispDbgPrint(("HAL: GLiNT 1280x1024 75Hz setup\n"));
+ Video->ImageWidth = 1280;
+ Video->ImageHeight = 1024;
+ Video->HLimit = 8 * 211;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 51;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 1066;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 42;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 134 MHz */
+ Video->PixelClock = RGB525_DF(3) | RGB525_VCO_DIV_COUNT(2);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768
+ && VerticalFrequency == 75)
+ {
+ DispDbgPrint(("HAL: GLiNT 1024x768 75Hz setup\n"));
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 164;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 14;
+ Video->HBlankEnd = 8 * 36;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 800;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 32;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ /* 79 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(14);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768
+ && VerticalFrequency == 60)
+ {
+ DispDbgPrint(("HAL: GLiNT 1024x768 60Hz setup\n"));
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 168;
+ Video->HSyncStart = 8 * 3;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 40;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 806;
+ Video->VSyncStart = 4;
+ Video->VSyncEnd = 10;
+ Video->VBlankEnd = 38;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 65 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600
+ && VerticalFrequency == 75)
+ {
+ DispDbgPrint(("HAL: GLiNT 800x600 75Hz setup\n"));
+ Video->ImageWidth = 800;
+ Video->ImageHeight = 600;
+ Video->HLimit = 8 * 132;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 12;
+ Video->HBlankEnd = 8 * 32;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 625;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 25;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH;
+ /* 49.5 MHz */
+ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(34);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600
+ && VerticalFrequency == 60)
+ {
+ DispDbgPrint(("HAL: GLiNT 800x600 60Hz setup\n"));
+ Video->ImageWidth = 800;
+ Video->ImageHeight = 600;
+ Video->HLimit = 8 * 132;
+ Video->HSyncStart = 8 * 5;
+ Video->HSyncEnd = 8 * 21;
+ Video->HBlankEnd = 8 * 32;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH;
+ Video->VLimit = 628;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 6;
+ Video->VBlankEnd = 28;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH;
+ /* 40 MHz */
+ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(15);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 // add 4/5/1995
+ && HalpMonitorConfigurationData.VerticalResolution == 480
+ && VerticalFrequency == 60)
+ {
+ DispDbgPrint(("HAL: GLiNT 640x480 60Hz setup\n"));
+ Video->ImageWidth = 640;
+ Video->ImageHeight = 480;
+ Video->HLimit = 8 * 100;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 14;
+ Video->HBlankEnd = 8 * 20;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 525;
+ Video->VSyncStart = 12;
+ Video->VSyncEnd = 13;
+ Video->VBlankEnd = 45;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW;
+ /* 31.5 MHz */
+ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(36);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480
+ && VerticalFrequency == 75)
+ {
+ DispDbgPrint(("HAL: GLiNT 640x480 75Hz setup\n"));
+ Video->ImageWidth = 640;
+ Video->ImageHeight = 480;
+ Video->HLimit = 8 * 105;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 10;
+ Video->HBlankEnd = 8 * 25;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 500;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 20;
+ Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW;
+ /* 31.5 MHz */
+ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(61);
+ }
+ else if ( HalpMonitorConfigurationData.HorizontalResolution == 1280
+ && HalpMonitorConfigurationData.VerticalResolution == 1024
+ && VerticalFrequency == 57)
+ {
+ DispDbgPrint(("HAL: GLiNT 1280x1024 57Hz setup\n"));
+ Video->ImageWidth = 1280;
+ Video->ImageHeight = 1024;
+ Video->HLimit = 8 * 211;
+ Video->HSyncStart = 8 * 2;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 51;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 1066;
+ Video->VSyncStart = 2;
+ Video->VSyncEnd = 5;
+ Video->VBlankEnd = 42;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 103 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(38);
+ }
+ else {
+ //
+ // force to set the resolution. 1024x768(60MHz)
+ //
+
+ DispDbgPrint(("HAL: GLiNT 1024x768 60Hz setup (default setting)\n"));
+ Video->ImageWidth = 1024;
+ Video->ImageHeight = 768;
+ Video->HLimit = 8 * 168;
+ Video->HSyncStart = 8 * 3;
+ Video->HSyncEnd = 8 * 20;
+ Video->HBlankEnd = 8 * 40;
+ Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ Video->VLimit = 806;
+ Video->VSyncStart = 4;
+ Video->VSyncEnd = 10;
+ Video->VBlankEnd = 38;
+ Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW;
+ /* 65 MHz */
+ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0);
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+
+ /* record image depth */
+
+ Video->ImageDepth = 16;
+
+ /* determine video clock divider and pixel format */
+
+ ClockDivider = 4;
+ Video->PixelFormat = RGB525_PIXEL_FORMAT_16_BPP;
+
+ /* adjust horizontal timings */
+
+ Video->HLimit /= ClockDivider;
+ Video->HSyncStart /= ClockDivider;
+ Video->HSyncEnd /= ClockDivider;
+ Video->HBlankEnd /= ClockDivider;
+
+ //
+ // Initialize ramdac data
+ //
+
+ RGB525_WRITE(Dac, __RGB525_PixelMask, 0xff);
+
+ /* set MiscControlOne register */
+ ByteVal = RGB525_MISR_CNTL_OFF
+ | RGB525_VMSK_CNTL_OFF
+ | RGB525_PADR_RFMT_READ_ADDR
+ | RGB525_SENS_DSAB_DISABLE
+ | RGB525_VRAM_SIZE_64;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlOne, ByteVal);
+
+ /* set MiscControlTwo register */
+ ByteVal = RGB525_PCLK_SEL_PLL
+ | RGB525_INTL_MODE_DISABLE
+ | RGB525_BLANK_CNTL_NORMAL
+ | RGB525_COL_RES_8_BIT
+ | RGB525_PORT_SEL_VRAM;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlTwo, ByteVal);
+
+ /* set MiscControlThree register */
+ ByteVal = RGB525_SWAP_RB_DISABLE
+ | RGB525_SWAP_WORD_31_00_FIRST
+ | RGB525_SWAP_NIB_07_04_FIRST;
+ RGB525_SET_REG(Dac, __RGB525_MiscControlThree, ByteVal);
+
+ /* set MiscClockControl register */
+ ByteVal = RGB525_DDOTCLK_DISABLE
+ | RGB525_SCLK_ENABLE
+ | RGB525_PLL_ENABLE;
+ RGB525_SET_REG(Dac, __RGB525_MiscClockControl, ByteVal);
+
+ /* set SyncControl register */
+ ByteVal = RGB525_DLY_CNTL_ADD
+ | RGB525_VSYN_INVT_DISABLE
+ | RGB525_HSYN_INVT_DISABLE
+ | RGB525_VSYN_CNTL_NORMAL
+ | RGB525_HSYN_CNTL_NORMAL;
+ RGB525_SET_REG(Dac, __RGB525_SyncControl, ByteVal);
+
+ /* set HSyncControl register */
+ RGB525_SET_REG(Dac, __RGB525_HSyncControl, RGB525_HSYN_POS(0));
+
+ /* set PowerManagement register */
+ ByteVal = RGB525_SCLK_PWR_NORMAL
+ | RGB525_DDOT_PWR_DISABLE
+ | RGB525_SYNC_PWR_NORMAL
+ | RGB525_ICLK_PWR_NORMAL
+ | RGB525_DAC_PWR_NORMAL;
+ RGB525_SET_REG(Dac, __RGB525_PowerManagement, ByteVal);
+
+ /* set DACOperation register */
+ ByteVal = RGB525_SOG_DISABLE
+ | RGB525_BRB_NORMAL
+ | RGB525_DSR_FAST
+ | RGB525_DPE_ENABLE; /* disable? */
+ RGB525_SET_REG(Dac, __RGB525_DACOperation, ByteVal);
+
+ /* set PaletteControl register */
+ ByteVal = RGB525_6BIT_LINEAR_ENABLE
+ | RGB525_PALETTE_PARTITION(0);
+ RGB525_SET_REG(Dac, __RGB525_PaletteControl, ByteVal);
+
+ /* set PixelFormat register */
+ RGB525_SET_REG(Dac, __RGB525_PixelFormat, Video->PixelFormat);
+
+ /* set 8BitPixelControl register */
+ RGB525_SET_REG(Dac, __RGB525_8BitPixelControl,
+ RGB525_B8_DCOL_INDIRECT);
+
+ /* set 16BitPixelControl register */
+ ByteVal = RGB525_B16_DCOL_INDIRECT
+ | RGB525_B16_565
+ | RGB525_B16_ZIB
+ | RGB525_B16_SPARSE;
+
+ RGB525_SET_REG(Dac, __RGB525_16BitPixelControl, ByteVal);
+
+ /* set 32BitPixelControl register */
+ RGB525_SET_REG(Dac, __RGB525_32BitPixelControl,
+ RGB525_B32_DCOL_INDIRECT);
+
+ /* set PLLControlOne register */
+ ByteVal = RGB525_REF_SRC_REFCLK
+ | RGB525_PLL_INT_FS_DIRECT;
+ RGB525_SET_REG(Dac, __RGB525_PLLControlOne, ByteVal);
+
+ /* set PLLControlTwo register */
+ RGB525_SET_REG(Dac, __RGB525_PLLControlTwo, RGB525_PLL_INT_FS(0));
+
+ /* set PLLRefDivCount register */
+ RGB525_SET_REG(Dac, __RGB525_PLLRefDivCount, Video->RefDivCount);
+
+ /* set F0 register */
+ RGB525_SET_REG(Dac, __RGB525_F0, Video->PixelClock);
+
+ /* set CursorControl register */
+ RGB525_SET_REG(Dac, __RGB525_CursorControl, RGB525_CURSOR_MODE_OFF);
+
+ //
+ // Initialize timing
+ //
+
+ /* horizontal video timing values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGHLimit, Video->HLimit);
+ GLINT_WRITE(Glint, __GLINT_VTGHSyncStart, Video->HSyncStart);
+ GLINT_WRITE(Glint, __GLINT_VTGHSyncEnd, Video->HSyncEnd);
+ GLINT_WRITE(Glint, __GLINT_VTGHBlankEnd, Video->HBlankEnd);
+
+ /* vertical video timing values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGVLimit, Video->VLimit);
+ GLINT_WRITE(Glint, __GLINT_VTGVSyncStart, Video->VSyncStart);
+ GLINT_WRITE(Glint, __GLINT_VTGVSyncEnd, Video->VSyncEnd);
+ GLINT_WRITE(Glint, __GLINT_VTGVBlankEnd, Video->VBlankEnd);
+
+ /* horizontal clock gate values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGHGateStart, Video->HBlankEnd - 2);
+ GLINT_WRITE(Glint, __GLINT_VTGHGateEnd, Video->HLimit - 2);
+
+ /* vertical clock gate values */
+
+ GLINT_WRITE(Glint, __GLINT_VTGVGateStart, Video->VBlankEnd - 1)
+ GLINT_WRITE(Glint, __GLINT_VTGVGateEnd, Video->VBlankEnd);
+
+ //
+ // Initialize control
+ //
+
+ /* serial clock control */
+
+ SerialClk = GLINT_EXTERNAL_QSF
+ | GLINT_SPLIT_SIZE_128_WORD
+ | GLINT_SCLK_VCLK_DIV_2;
+
+ GLINT_WRITE(Glint, __GLINT_VTGSerialClk, SerialClk);
+
+ /* set sync polarities and unblank screen */
+
+ // UpdatePolarityRegister(Glint,
+ // GLINT_CBLANK_ACTIVE_LOW
+ // | Video->HSyncPolarity
+ // | Video->VSyncPolarity,
+ // GLINT_CBLANK_POLARITY_MASK
+ // | GLINT_HSYNC_POLARITY_MASK
+ // | GLINT_VSYNC_POLARITY_MASK);
+
+ Data = GLINT_CBLANK_ACTIVE_LOW
+ | Video->HSyncPolarity
+ | Video->VSyncPolarity;
+ Mask = GLINT_CBLANK_POLARITY_MASK
+ | GLINT_HSYNC_POLARITY_MASK
+ | GLINT_VSYNC_POLARITY_MASK;
+
+ /* read video polarity control register */
+
+ GLINT_READ(Glint, __GLINT_VTGPolarity, Temp);
+
+ /* replace existing polarity field */
+
+ Temp = (Temp & ~Mask) | (Data & Mask);
+
+ /* write result back to polarity register */
+
+ GLINT_WRITE(Glint, __GLINT_VTGPolarity, Temp);
+
+ /* set FrameRowAddr */
+
+ GLINT_WRITE(Glint, __GLINT_VTGFrameRowAddr, 0);
+
+ //
+ // Initialize RampLut
+ //
+
+ /* initialise palette address */
+
+ RGB525_WRITE(Dac, __RGB525_PalAddrWrite, 0);
+
+ /* ramp colour components using auto-increment */
+
+ for (Index = 0; Index <= 0xff; Index++)
+ {
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ RGB525_WRITE(Dac, __RGB525_PaletteData, Index);
+ }
+
+ //
+ // Clear the screen.
+ //
+
+ DestinationUlong = (PULONG)VIDEO_MEMORY_BASE;
+
+ Length = (HalpMonitorConfigurationData.VerticalResolution *
+ HalpMonitorConfigurationData.HorizontalResolution) * sizeof(USHORT);
+
+ for (Index = 0; Index < (Length / sizeof(ULONG)); Index++)
+ *(DestinationUlong++) = (ULONG)0x000f000f;
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ )
+/*++
+ Routine Description:
+
+ This function returns PCI configuration data.
+
+ Arguments:
+
+ Slot - Supplies a PCI slot number and function number.
+ Buffer - Supplies a pointer to a configuration data is returned.
+ Offset - Offset in the PCI configuration header.
+
+ Return Value:
+
+ None.
+
+--*/
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ //
+ // check to see if specified slot is valid
+ //
+
+ if (!HalpCheckPCIDevice(Slot)) {
+
+ //
+ // Invalid SlotID return no data
+ //
+
+ *Buffer = 0xffffffff;
+ return ;
+
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ //
+ // Synchronize with PCI configuration
+ //
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_ULONG(HalpPonceConfigDataReg);
+
+ return;
+}
+
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ )
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ if (!HalpCheckPCIDevice(Slot)) {
+ *Buffer = 0xffff;
+ return ;
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_USHORT((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG)));
+
+ return;
+}
+
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ if (!HalpCheckPCIDevice(Slot)) {
+ *Buffer = 0xff;
+ return ;
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+
+ *Buffer = READ_REGISTER_UCHAR((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG)));
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ )
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ if (!HalpCheckPCIDevice(Slot)) {
+ *Buffer = 0xffffffff;
+ return ;
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigDataReg, *Buffer);
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUSHORT Buffer,
+ IN ULONG Offset
+ )
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ if (!HalpCheckPCIDevice(Slot)) {
+ *Buffer = 0xffff;
+ return ;
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+
+ WRITE_REGISTER_USHORT((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG)),*Buffer);
+
+ return;
+}
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue;
+ USHORT StatusValue;
+ KIRQL OldIrql;
+
+ if (!HalpCheckPCIDevice(Slot)) {
+ *Buffer = 0xff;
+ return ;
+ }
+
+ *((PULONG) &ConfigAddressValue) = 0x0;
+
+ ConfigAddressValue.ConfigEnable = 1;
+ ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber;
+ ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber;
+ ConfigAddressValue.RegisterNumber = Offset >> 2;
+
+ WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue));
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG)), *Buffer);
+
+ return;
+}
+// S001 ^^^
diff --git a/private/ntos/nthals/halr98b/mips/jxebsup.c b/private/ntos/nthals/halr98b/mips/jxebsup.c
new file mode 100644
index 000000000..2b513060c
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxebsup.c
@@ -0,0 +1,1178 @@
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for R98B systems.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber; // S004
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber; // S004
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+ UCHAR charBuffer;
+
+
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DISPATCH_VECTOR] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+ KeRaiseIrql(EISA_LEVEL, &oldIrql);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+
+ //
+ // EISA Interrupt to PONCE Enable!!.
+ //
+ HalpInterruptFromPonce(EISA_DISPATCH_VECTOR ,1); //SNES
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+
+
+ charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus );
+ //
+ // IOCHK# NMI Disable and Clear
+ // PERR# PCI System Board Error Disable
+ //
+ charBuffer = ((charBuffer & 0x03) | 0x0C);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus,
+ charBuffer
+ );
+ //
+ // Disbale Bus Timeout,Fail Safe NMI adn Software NMI
+ //
+ charBuffer = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl
+ );
+
+ charBuffer = (charBuffer & 0x01);
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ charBuffer );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+//
+//
+//extern KSPIN_LOCK HalpIoMapSpinLock;
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ KIRQL Irql;
+
+ BytePtr = (PUCHAR) &Offset;
+
+// ASSERT(Offset >= 0x100000); // S009
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ // Internal Floppy Device used ESC DMA and May be diffirent Onprocessor
+ // with EISA Drivers OnProcessor.
+ // So grab.
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+}
+
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = (UCHAR)READ_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->INTAC);
+
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+// if (interruptVector != 0x8000) {
+ //K001 Start
+ if(interruptVector == 7|| interruptVector==15 ){
+
+ PVOID IsrPortAddr;
+ UCHAR IsrValue;
+
+#define OCW3_READ_ISR 0x0B
+#define OCW3_READ_IRR 0x0A
+
+ //
+ // Master or Slave ?
+ //
+ IsrPortAddr = (interruptVector == 7) ?
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0:
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0;
+
+ // SetUp to ISR Regsiter
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_ISR );
+ // Read ISR Register
+ IsrValue=READ_REGISTER_UCHAR( IsrPortAddr );
+ // Resume to IRR Register
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_IRR);
+
+ if(!IsrValue){
+ // This is a spurious interrupt!!. No Call Driver.
+ goto NocallDriver;
+ }
+ }
+ // K001 End
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+NocallDriver:
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+// } else {
+// returnValue = HalHandleNMI(NULL, NULL);
+// }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxenvirv.c b/private/ntos/nthals/halr98b/mips/jxenvirv.c
new file mode 100644
index 000000000..e6cef4381
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxenvirv.c
@@ -0,0 +1,691 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a R98B system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "rxnvr.h"
+#include "string.h"
+
+//
+// Define base address at which to map NVRAM.
+//
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which receives the old NVRAM
+ PTE values.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ //
+ // disable nvram Write protection. Set Write Enable
+ //
+#if 0
+ //
+ // No Gard. for Driver. Fix.
+ //
+
+
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR ,STSR_WNVWINH);
+#endif
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which contains the old NVRAM
+ PTE values.
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if 0
+ // N.B For Driver.
+ //
+
+ //
+ // Set nvram write protect
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR ,STSR_NVWINH|STSR_WNVWINH);
+#endif
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+#if defined(DBG1)
+ DbgPrint("NVRAM 0S\n");
+#endif
+
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+
+#if defined(DBG1)
+ DbgPrint("NVRAM 0E\n");
+#endif
+
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+#if DBG
+ DbgPrint("NVRAM 1S\n");
+#endif
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+#if DBG
+ DbgPrint("NVRAM 1E\n");
+#endif
+
+
+ return Status;
+}
+
+
diff --git a/private/ntos/nthals/halr98b/mips/jxmapio.c b/private/ntos/nthals/halr98b/mips/jxmapio.c
new file mode 100644
index 000000000..e1daa9da5
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxmapio.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R98B
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase;
+PVOID HalpRealTimeClockBase;
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+#if defined(_R98B_)
+ //
+ // R98B EISA Control area can access KSEG1_BASE.
+ // N.B Implement below 64K
+ // But above 64K I/O area can't !!
+
+ //
+ // set EISA control space.
+ //
+
+ HalpEisaControlBase = (PVOID)(KSEG1_BASE + EISA_CNTL_PHYSICAL_BASE_LOW);
+
+ //
+ // set realtime clock registers.
+ //
+
+ HalpRealTimeClockBase = (PVOID)(KSEG1_BASE + RTCLOCK_PHYSICAL_BASE);
+ return TRUE;
+#else // #if !defined(_R98B_)
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.LowPart = RTCLOCK_PHYSICAL_BASE;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+
+ if ((HalpEisaControlBase == NULL) || (HalpRealTimeClockBase == NULL)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+#endif // #if defined(_R98B_)
+
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxmaptb.c b/private/ntos/nthals/halr98b/mips/jxmaptb.c
new file mode 100644
index 000000000..db2b8a931
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxmaptb.c
@@ -0,0 +1,68 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxmaptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for a MIPS R98B
+ system. It also sets the instruction and data cache line sizes for a
+ R98 system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapFixedTbEntries)
+
+#endif
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is return only.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98b/mips/jxport.c b/private/ntos/nthals/halr98b/mips/jxport.c
new file mode 100644
index 000000000..674276641
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxport.c
@@ -0,0 +1,779 @@
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R98system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS )(SERIAL0_PHYSICAL_BASE|KSEG1_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SERIAL0_PHYSICAL_BASE|KSEG1_BASE))
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 0;
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxreturn.c b/private/ntos/nthals/halr98b/mips/jxreturn.c
new file mode 100644
index 000000000..58340ee80
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxreturn.c
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+--*/
+
+/*
+ * S001 1995/12/01 T.Samezima
+ * add x86 bios logic
+ *
+ */
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+ UCHAR Pad0;
+ UCHAR Pad1;
+ UCHAR Pad2;
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; //S001
+
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)(KEYBOARD_PHYSICAL_BASE|KSEG1_BASE);
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+
+ // S001 vvv
+ //
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ Eax = 0x12; // AH = 0 AL = 0x12
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+ // S001 ^^^
+
+ //
+ // Send Powerdown Command to the MRC.
+ //
+
+ for (;TRUE;) {
+ {
+ UCHAR Data;
+ Data = 0x1;
+ HalpLocalDeviceReadWrite(MRC_SWPOWEROFF, &Data, LOCALDEV_OP_WRITE);
+ }
+ }
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+#if 1
+ {
+#if 0
+ DbgPrint("Hal return 0\n");
+#endif
+ HalpMrcModeChange((UCHAR)MRC_OP_DUMP_AND_POWERSW_NMI);
+#if 0
+ DbgPrint("Hal return 1\n");
+#endif
+
+ }
+#endif
+
+
+ // S001 vvv
+ //
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ Eax = 0x12; // AH = 0 AL = 0x12
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+ // S001 ^^^
+
+ //
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreData(0);
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxsysint.c b/private/ntos/nthals/halr98b/mips/jxsysint.c
new file mode 100644
index 000000000..ad8ddc460
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxsysint.c
@@ -0,0 +1,327 @@
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for R98B
+
+--*/
+
+
+#include "halp.h"
+
+
+//
+// Define Ipi Interrupt Reqest value table.
+// Index is Mask
+// IntIR register target Cpu bit is Not Mask.
+// Mask High Bit is IntIR Target CPU Bit Low.
+//
+ULONG HalpIpiIntRequestMask[] = {
+ IntIR_REQUEST_IPI | (0), //0: error!!.
+ IntIR_REQUEST_IPI | (ToNODE4), //1: to CPU #0
+ IntIR_REQUEST_IPI | ( ToNODE5), //2: to CPU #1
+ IntIR_REQUEST_IPI | (ToNODE4|ToNODE5 ), //3: to CPU #0 #1
+ IntIR_REQUEST_IPI | ( ToNODE6), //4: to CPU #2
+ IntIR_REQUEST_IPI | (ToNODE4| ToNODE6), //5: to CPU #0 #2
+ IntIR_REQUEST_IPI | ( ToNODE5|ToNODE6), //6: to CPU #1 #2
+ IntIR_REQUEST_IPI | (ToNODE4|ToNODE5|ToNODE6 ), //7: to CPU #0 #1 #2
+ IntIR_REQUEST_IPI | ( ToNODE7), //8: to CPU #3
+ IntIR_REQUEST_IPI | (ToNODE4| ToNODE7), //9: to CPU #0 #3
+ IntIR_REQUEST_IPI | ( ToNODE5| ToNODE7), //10:to CPU #1 #3
+ IntIR_REQUEST_IPI | (ToNODE4|ToNODE5| ToNODE7), //11:to CPU #0 #1 #3
+ IntIR_REQUEST_IPI | ( ToNODE6|ToNODE7), //12:to CPU #2 #3
+ IntIR_REQUEST_IPI | (ToNODE4| ToNODE6|ToNODE7), //13:to CPU #0 #2 #3
+ IntIR_REQUEST_IPI | ( ToNODE5|ToNODE6|ToNODE7), //14:to CPU #1 #2 #3
+ IntIR_REQUEST_IPI | (ToNODE4|ToNODE5|ToNODE6|ToNODE7) //15:to CPU #0 #1 #2 #3
+
+ };
+
+
+extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU];
+
+ULONG
+HalpAffinity2Physical (
+ IN ULONG Mask
+ );
+
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(DBG3)
+ DbgPrint("HAL Vector Disable Vector=0x%x\n",Vector);
+#endif
+
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+ if (Vector >= EISA_VECTORS && Vector <= MAXIMUM_EISA_VECTORS){
+#if defined(DBG3)
+ DbgPrint("HAL Vector Disable EISA=0x%x\n",Vector);
+#endif
+
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS )) && (Vector <= MAXIMUM_DEVICE_VECTORS)) {
+#if defined(DBG3)
+ DbgPrint("HAL Vector DIable EISA=0x%x\n",Vector);
+#endif
+
+ HalpInterruptFromPonce(Vector,0);
+ }
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(DBG3)
+ DbgPrint("HAL Vector Enable in =0x%x\n",Vector);
+#endif
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS && Vector <= MAXIMUM_EISA_VECTORS){
+#if DBG
+ DbgPrint("HAL Vector Enable EISA=0x%x\n",Vector);
+#endif
+
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // enable the builtin device interrupt.
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS )) && (Vector <= MAXIMUM_DEVICE_VECTORS)) {
+#if defined(DBG3)
+ DbgPrint("HAL Vector Enable internal or PCI=0x%x\n",Vector);
+#endif
+
+ //
+ // enable interrupt from ponce.
+ //
+ HalpInterruptFromPonce(Vector,1);
+ }
+
+#if defined(DBG3)
+ DbgPrint("HAL Vector Enable Out =0x%x\n",Vector);
+#endif
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+//
+// IPI function.
+//
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG IntIR;
+
+
+
+ ULONG Maskp;
+ ULONG PhysicalNumber;
+
+ if(!Mask){
+ return;
+ }
+
+ Maskp=HalpAffinity2Physical(Mask);
+ PhysicalNumber=HalpLogicalCPU2PhysicalCPU[(ULONG)((PCR->Prcb)->Number)];
+
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+ IntIR = HalpIpiIntRequestMask[(Maskp & 0xf)] |
+ ( (ATLANTIC_CODE_IPI_FROM_CPU0 + PhysicalNumber) << IntIR_CODE_BIT);
+
+#if defined(DBG3)
+ DbgPrint("IntIR = 0x%x\n",IntIR);
+#endif
+
+ //
+ // write IntIR Register. make ipi!!
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->IntIR,IntIR);
+
+ return;
+}
+
+
+
+ULONG
+HalpAffinity2Physical (
+ IN ULONG Mask
+ )
+
+
+/*++
+
+Routine Description:
+
+ This routine translate logical affinity into physical affinity.
+
+Arguments:
+
+ Mask Losical Affinity
+
+Return Value:
+
+ Physical Affinity
+
+--*/
+{
+
+ ULONG i,j,PhysicalAffinity;
+
+ i=0;
+ j=0;
+ PhysicalAffinity=0;
+
+ for(i=0;i<4;i++){
+
+ if(Mask&0x1==0x1){
+ j=HalpLogicalCPU2PhysicalCPU[i];
+ PhysicalAffinity=PhysicalAffinity|(0x1<<j);
+ }
+ Mask=(Mask>>1);
+ }
+
+ return PhysicalAffinity;
+}
+
diff --git a/private/ntos/nthals/halr98b/mips/jxtime.c b/private/ntos/nthals/halr98b/mips/jxtime.c
new file mode 100644
index 000000000..c2678cd45
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxtime.c
@@ -0,0 +1,319 @@
+#ident "@(#) NEC jxtime.c 1.4 94/11/22 20:09:27"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/23 T.Samezima
+ *
+ * Change Irql Level
+ *
+ ***********************************************************************
+ *
+ * S002 94.07/5 T.Samezima
+ *
+ * Change Register access mask
+ *
+ *
+ */
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+#if defined(NT_40)
+ KeRaiseIrql( HIGH_LEVEL, &OldIrql);
+#else
+ KeRaiseIrql((KIRQL)(INT0_LEVEL+HalpIntLevelofIpr[HalpMachineCpu][CLOCK_VECTOR - DEVICE_VECTORS]), &OldIrql);
+#endif
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+#if defined(NT_40)
+ KeRaiseIrql( HIGH_LEVEL, &OldIrql);
+#else
+ KeRaiseIrql((KIRQL)(INT0_LEVEL+HalpIntLevelofIpr[HalpMachineCpu][CLOCK_VECTOR - DEVICE_VECTORS]), &OldIrql);
+#endif
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ /* Start S002 */
+ Register |= 0x80;
+ /* End S002 */
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ /* Start S002 */
+ Register |= 0x80;
+ /* End S002 */
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/halr98b/mips/jxusage.c b/private/ntos/nthals/halr98b/mips/jxusage.c
new file mode 100644
index 000000000..2d6809693
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/jxusage.c
@@ -0,0 +1,541 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+//
+// Array to remember hal's IDT usage
+//
+#if !defined(_R98B_) // CMP001
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif // _R98B_
+
+UCHAR HalName[] = "NEC Mips HAL Frontier 3.00";
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+#if !defined (_R98B_)
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+#endif // _R98B_
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+#if defined(_R98B_)
+ for(i=0; i < EISA_VECTORS; i++) {
+ HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+#else
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+#endif
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_VECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+#if 1
+ PCIBus // device space interface type
+#else
+ Internal
+#endif
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ // Get PCI RegInfo.
+ //
+ //
+ //
+ HalpInitializePciBus ();
+
+ //
+ // SVP Board Check!!
+ //
+ HalpSVPSlotDetect();
+#if DBG
+ HalpDisplayAllBusRanges();
+ DbgPrint("HAL Report finished\n");
+#endif
+}
+
diff --git a/private/ntos/nthals/halr98b/mips/mipsdat.c b/private/ntos/nthals/halr98b/mips/mipsdat.c
new file mode 100644
index 000000000..e50fbfe7e
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/mipsdat.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*++
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC
+ EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC
+
+ EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe
+
+ EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B)
+ EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A
+
+ EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable
+ EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI
+ EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted
+
+ EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers
+
+ EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+#define R98_MAPREGISTER_BASE 100
+
+
+ADDRESS_USAGE HalpMapRegisterMemorySpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ R98_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001
+ 0, 0
+ }
+};
+
+//
+// from ixdat.c
+//
+
+UCHAR HalpSzBreak[] = "BREAK";
+UCHAR HalpSzPciLock[] = "PCILOCK";
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+//
+#if defined(MIPS)
+IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[]
+#else
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif
+
diff --git a/private/ntos/nthals/halr98b/mips/mode542x.h b/private/ntos/nthals/halr98b/mips/mode542x.h
new file mode 100644
index 000000000..00445a6d9
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/mode542x.h
@@ -0,0 +1,1302 @@
+#ident "@(#) NEC mode542x.h 1.3 95/07/05 13:10:57"
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Mode542x.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-542x driver.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// The next set of tables are for the CL542x
+// Note: all resolutions supported
+//
+
+//
+// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode
+
+ EOD
+};
+
+//
+// 800x600 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_800x600[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode
+
+ EOD
+};
+
+//
+// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_1024x768[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ EOD
+};
+
+//-----------------------------
+// standard VGA text modes here
+// 80x25 at 640x350
+//
+//-----------------------------
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (720x400 pixel resolution; 9x16 character cell.)
+//
+
+USHORT CL542x_80x25Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (640x350 pixel resolution; 8x14 character cell.)
+//
+
+USHORT CL542x_80x25_14_Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x.
+//
+
+USHORT CL542x_1280x1024[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_64k[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 4,
+ 0x0506, // Some BIOS's set Chain Odd maps bit
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#ifdef _X86_
+
+//
+// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x.
+//
+
+USHORT CL542x_800x600_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#else
+
+//
+// NOTE(DBCS) : Update 94/09/12 - NEC Corporation
+//
+// - Add mode set command string for NEC MIPS machine.
+//
+// - 640x480 256 color 72Hz
+// - 800x600 256 color 56 / 60Hz
+// - 1024x768 256 color 70 / 45Hz
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+//
+// For MIPS NEC machine only
+//
+
+//
+// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xE3,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F,
+ 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x420E,
+ 0x2B1B,0x2F1C,0x301D,0x1F1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h)
+//
+// - Set Mode Type is VESA compatible. (Old Miss match)
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99,
+ 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+
+// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match
+// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode.
+// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B,
+// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+// 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_56[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12,
+ 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x510E,
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B,
+ 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B,0x5B0C,0x450D,0x650E,
+
+#else
+
+ 0x4A0B,0x5B0C,0x450D,0x640E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x760E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x341E,
+
+#else
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x3B0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x1A1E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_70[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x6E0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x2A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for
+// CL 542x. (Interlaced)
+//
+
+USHORT CL542x_1024x768_256_87[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x550E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x361E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99,
+ 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83,
+ 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x84,
+ 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/modeset.h b/private/ntos/nthals/halr98b/mips/modeset.h
new file mode 100644
index 000000000..b699eacc7
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/modeset.h
@@ -0,0 +1,86 @@
+#ident "@(#) NEC modeset.h 1.1 94/07/05 14:06:24"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) modeset.h 1.3 93/10/29 12:25:59" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Modeset.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-6410 and CL-6420 driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Mode structure.
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ *
+ */
+
+#include "cmdcnst.h"
+
+//---------------------------------------------------------------------------
+//
+// The actual register values for the supported modes are in chipset-specific
+// include files:
+//
+// mode64xx.h has values for CL6410 and CL6420
+// mode542x.h has values for CL5422, CL5424, and CL5426
+//
+
+
+USHORT HalpCirrus_MODESET_1K_WIDE[] = {
+ OW, // stretch scans to 1k
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x8013,
+
+ EOD
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98b/mips/pcip.h b/private/ntos/nthals/halr98b/mips/pcip.h
new file mode 100644
index 000000000..d0337f7d3
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/pcip.h
@@ -0,0 +1,189 @@
+#ident "@(#) NEC pcip.h 1.4 95/06/19 11:13:40"
+
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+
+VOID
+HalpPCIPin2SystemLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCISystemLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN ULONG StartPciBus, //R98B
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/r98bdef.h b/private/ntos/nthals/halr98b/mips/r98bdef.h
new file mode 100644
index 000000000..6166a583e
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/r98bdef.h
@@ -0,0 +1,228 @@
+/*
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r98bdef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the r98B system.
+
+Author:
+
+
+
+Revision History:
+
+--*/
+
+#ifndef _R98BDEF_
+#define _R98BDEF_
+
+//
+// Define the size of the DMA translation table.
+//
+#define DMA_TRANSLATION_LIMIT 0x5000 // translation table limit
+
+//
+// Define the maximum number of map registers allowed per allocation.
+//
+// 2M 2M 2M
+// + PONCE0: PONCE1:
+// | | |
+// | +-------------+
+// +
+// +
+// EISA/ISA
+// Max 3 Slot + Internal Floppy(Use ESC DMA channel #2) = 4 --> 512K *4 = 2M
+//
+// 2M is for 1M Logical Area Reserv!!.
+//
+#define DMA_TRANSLATION_RESERV 0x1000 // 4k /8 = 2M
+#define DMA_REQUEST_LIMIT ((DMA_TRANSLATION_LIMIT-DMA_TRANSLATION_RESERV)/(sizeof(TRANSLATION_ENTRY) * 16))
+//
+//#define DMA_REQUEST_LIMIT (DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY) * 4))
+//
+// N.B
+// May be 1 page reserved for PCEB Prefetch cycle.
+// It Cause Ponce I/O TLB page fault.
+//
+#define DMA_REQUEST_EISA_LIMIT (DMA_REQUEST_LIMIT-1)
+#define EISA_MAX_DEVICE 3
+
+
+#define R98B_MAX_CPU 4
+
+#define R98B_MAX_MAGELLAN 2
+
+#define R98B_MAX_PONCE 3 //R100
+
+#define R98_CPU_R4400 0
+#define R98_CPU_R10000 1
+#define R98_CPU_NUM_TYPE 2
+
+#define DEVICE_VECTORS 32
+#define EISA_DISPATCH_VECTOR (13+DEVICE_VECTORS)
+#define PARALLEL_VECTOR (14+DEVICE_VECTORS) // Parallel device interrupt vector
+#define NET_VECTOR (29+DEVICE_VECTORS) // ethernet device interrupt vector
+#define SCSI0_VECTOR (31+DEVICE_VECTORS) // SCSI device interrupt vector
+#define SCSI1_VECTOR (30+DEVICE_VECTORS) // SCSI device interrupt vector
+#define UNDEFINE_TLB_VECTOR (35+DEVICE_VECTORS) // TLB undefine address interrupt vector
+#define MOUSE_VECTOR (36+DEVICE_VECTORS) // Mouse device interrupt vector
+#define KEYBOARD_VECTOR (37+DEVICE_VECTORS) // Keyboard device interrupt vector
+#define SERIAL1_VECTOR (38+DEVICE_VECTORS) // Serial device 1 interrupt vector
+#define SERIAL0_VECTOR (39+DEVICE_VECTORS) // Serial device 0 interrupt vector
+#define IPI_VECTOR3 (48+DEVICE_VECTORS) // IPI From #3
+#define IPI_VECTOR2 (49+DEVICE_VECTORS) // IPI From #2
+#define IPI_VECTOR1 (50+DEVICE_VECTORS) // IPI From #1
+#define IPI_VECTOR0 (51+DEVICE_VECTORS) // IPI From #0
+#define PROFILE_VECTOR (56+DEVICE_VECTORS) // Define Profile interrupt vector
+#define CLOCK_VECTOR (57+DEVICE_VECTORS) // Define Clock interrupt vector
+
+#define EIF_VECTOR (61+DEVICE_VECTORS) // EIF Vector
+
+#define ECC_1BIT_VECTOR (62+DEVICE_VECTORS) // ECC 1bit Error interrupt vector
+
+//SNES #define MAXIMUM_DEVICE_VECTORS 43 // IPR Bit 43
+#define MAXIMUM_DEVICE_VECTORS (43+DEVICE_VECTORS)
+//
+// Define EISA device interrupt vectors.
+//
+#define EISA_VECTORS 16
+#define MAXIMUM_EISA_VECTORS (15 + EISA_VECTORS) // maximum EISA vector
+
+#define INT0_LEVEL 3 // PCR->InterruptRoutine[3]
+#define INT1_LEVEL 4 // PCR->InterruptRoutine[4]
+#define INT2_LEVEL 5 // PCR->InterruptRoutine[5]
+#define INT3_LEVEL 6 // PCR->InterruptRoutine[6]
+#define INT4_LEVEL 7 // PCR->InterruptRoutine[7]
+#define INT5_LEVEL 8 // PCR->InterruptRoutine[8]
+
+#define EISA_LEVEL INT0_LEVEL // R98B/R98A same
+#define NUMBER_OF_INT 6
+
+//
+// Define the minimum and maximum system time increment values in 100ns units.
+//
+
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+//
+//
+// Time increment in 1us units
+// The Columbus chip clock frequency is 1.024 MHZ
+#define COLUMBUS_CLOCK_FREQUENCY 1024
+
+// The hardware expects that this value is decremented by one
+#define CLOCK_INTERVAL (((MAXIMUM_INCREMENT * COLUMBUS_CLOCK_FREQUENCY) / 1000) / 10)
+
+//
+// 1 Interval != 1 micro sec. ==> 1 Interval = 1/1.024 microsec
+// 1 Count (H/W register) is 1/1.024 microsec
+//
+#define DEFAULT_PROFILETIMER_INTERVAL (500 * 10) // = 500 us (100ns units)
+#define MAXIMUM_PROFILETIMER_INTERVAL (64000 * 10) // = 64 ms (100ns units)
+#define DEFAULT_PROFILETIMER_COUNT (MAXIMUM_PROFILETIMER_INTERVAL / 10) //Set count value
+#define MINIMUM_PROFILETIMER_INTERVAL (40 * 10) // = 40 us (100ns units)
+
+
+
+
+//
+// Chip Set Addr
+//
+#define COLUMNBS_LPHYSICAL_BASE 0x19800000
+#define COLUMNBS_GPHYSICAL_BASE 0x19000000
+#define PONCE_PHYSICAL_BASE 0x1a000000
+#define MAGELLAN_0_PHYSICAL_BASE 0x18000000
+#define MAGELLAN_1_PHYSICAL_BASE 0x18020000
+#define LOCALDEV_PHYSICAL_BASE 0x1f0f0000
+
+
+
+#define EISA_CONTROL_PHYSICAL_BASE 0x1C000000 // physical base of EISA control
+#define SERIAL0_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+0x3f8) //serial
+#define KEYBOARD_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+0x60) //serial
+//
+// R98X have 2 I/O Area(per Ponce). But Not Use apper area!!.
+// used lower area only.
+//
+#define PCI_CNTL_PHYSICAL_BASE 0x1c000000
+#define PCI_MAX_CNTL_SIZE 0x400000 //4M
+
+//
+// R98X PCI Memory area size 1Gmax. Not 4G!!.
+//
+#define PCI_MAX_MEMORY_SIZE 0x40000000 //1G max
+#define PCI_MEMORY_PHYSICAL_BASE_LOW 0x40000000
+#define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x1
+
+// Ponce #0 have EISA/ISA.
+//
+#define EISA_MEMORY_PHYSICAL_BASE_LOW PCI_MEMORY_PHYSICAL_BASE_LOW
+#define EISA_MEMORY_PHYSICAL_BASE_HIGH PCI_MEMORY_PHYSICAL_BASE_HIGH
+
+#define EISA_CNTL_PHYSICAL_BASE PCI_CNTL_PHYSICAL_BASE
+#define EISA_CNTL_PHYSICAL_BASE_LOW PCI_CNTL_PHYSICAL_BASE
+#define EISA_CNTL_PHYSICAL_BASE_HIGH 0x0
+
+//
+// RTC Register
+//
+#define RTCLOCK_PHYSICAL_BASE 0x1c000071 // physical base of realtime clock
+
+//
+// Actually nvram start at
+//
+#define NVRAM_ACTUALLY_PHYSICAL_BASE 0x1F080000 // physical base of NonVolatile RAM
+//
+// s/w read/write ble erea this address
+//
+#define NVRAM_PHYSICAL_BASE 0x1F082000 // physical base of NonVolatile RAM For S/W
+#define NVRAM_MEMORY_BASE (KSEG1_BASE + NVRAM_PHYSICAL_BASE)
+
+//
+// R4400 cause register.
+//
+#define CAUSE_INT_PEND_BIT 0xA //Int0 base
+
+//
+// Local Device Function Operation.
+//
+#define LOCALDEV_OP_READ 0x1
+#define LOCALDEV_OP_WRITE 0x0
+
+
+//
+// Local Device MRC Function Operation.
+//
+#define MRC_OP_DUMP_ONLY_NMI 0x1
+#define MRC_OP_DUMP_AND_POWERSW_NMI 0x0
+
+//
+// ECC 1bit/Multi bit Error Operation.
+//
+#define ECC_1BIT_ENABLE 0xfffffff5
+#define ECC_MULTI_ENABLE 0xfffffffa
+#define ECC_ERROR_DISABLE 0x0000000f
+#define ECC_ERROR_ENABLE 0xfffffff0
+#define MAGELLAN_ERRI_OFFSET 0x2330
+
+//
+// Define cause register read macro
+//
+
+#define READ_CAUSE_REGISTER(reg) \
+ .set noreorder; \
+ .set noat; \
+ mfc0 reg,cause; \
+ nop; \
+ nop; \
+ .set at; \
+ .set reorder;
+
+
+#endif // _R98BDEF_
diff --git a/private/ntos/nthals/halr98b/mips/r98breg.h b/private/ntos/nthals/halr98b/mips/r98breg.h
new file mode 100644
index 000000000..5fc5e2f67
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/r98breg.h
@@ -0,0 +1,649 @@
+
+#ifndef _R98BREG_
+#define _R98BREG_
+
+
+#include <r98bdef.h>
+//
+// R98B Chip Set Register Define
+//
+//
+// Define COLUMBS register structure.
+//
+typedef struct _COLUMNBUS_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} COLUMNBUS_REGISTER, *PCOLUMNBUS_REGISTER;
+
+typedef struct _COLUMNBUS_LARGE_REGISTER {
+// ULONG Low;
+// ULONG High;
+
+ ULONGLONG Llong;
+} COLUMNBUS_LARGE_REGISTER, *PCOLUMNBUS_LARGE_REGISTER;
+
+typedef volatile struct _COLUMNBUS_REGISTERS {
+ // offset(H)
+ COLUMNBUS_LARGE_REGISTER IPR; // 0x0
+ COLUMNBUS_LARGE_REGISTER MKR; // 0x8
+ COLUMNBUS_LARGE_REGISTER IPRR; // 0x10
+ COLUMNBUS_REGISTER IPSR; // 0x18
+ COLUMNBUS_REGISTER MKRR; // 0x20
+ COLUMNBUS_REGISTER MKSR; // 0x28
+ COLUMNBUS_REGISTER NMIR; // 0x30
+ COLUMNBUS_REGISTER NMIRST; // 0x38
+ COLUMNBUS_REGISTER TMSR1; // 0x40
+ COLUMNBUS_REGISTER TMR1; // 0x48
+ COLUMNBUS_REGISTER TOVCT1; // 0x50
+ COLUMNBUS_REGISTER TMCR1; // 0x58
+ COLUMNBUS_REGISTER TMSR2; // 0x60
+ COLUMNBUS_REGISTER TMR2; // 0x68
+ COLUMNBUS_REGISTER TOVCT2; // 0x70
+ COLUMNBUS_REGISTER TMCR2; // 0x78
+ COLUMNBUS_REGISTER WDTSR; // 0x80
+ COLUMNBUS_REGISTER WDT; // 0x88
+ COLUMNBUS_REGISTER WDTCR; // 0x90
+ COLUMNBUS_REGISTER IRLEV; // 0x98
+ COLUMNBUS_REGISTER Reserved1[12]; // 0xa0-0xF8
+ COLUMNBUS_REGISTER SYNDM; // 0x100
+ COLUMNBUS_REGISTER SDMRST; // 0x108
+ COLUMNBUS_REGISTER Reserved2[14]; // 0x110
+ COLUMNBUS_REGISTER STCON; // 0x180
+ COLUMNBUS_REGISTER STSAD; // 0x188
+ COLUMNBUS_REGISTER STADMK; // 0x190
+ COLUMNBUS_REGISTER STDATH; // 0x198
+ COLUMNBUS_REGISTER STDATL; // 0x1a0
+ COLUMNBUS_REGISTER Reserved21; // 0x1a8
+ COLUMNBUS_REGISTER Reserved3[10]; // 0x1b0 - 0x1f8
+ COLUMNBUS_REGISTER CTAddr; // 0x200
+ COLUMNBUS_REGISTER CTDataA; // 0x208
+ COLUMNBUS_REGISTER CTDataB; // 0x210
+ COLUMNBUS_REGISTER CTCTL; // 0x218
+ COLUMNBUS_REGISTER EVCNT1H; // 0x220
+ COLUMNBUS_REGISTER EVCNT1L; // 0x228
+ COLUMNBUS_REGISTER EVCNTCR1; // 0x230
+ COLUMNBUS_REGISTER Reserved4[25]; // 0x238- 0x2F8
+ COLUMNBUS_REGISTER CNFG; // 0x300
+ COLUMNBUS_REGISTER DISN; // 0x208
+ COLUMNBUS_REGISTER REVR; // 0x310
+ COLUMNBUS_REGISTER AERR; // 0x318
+ COLUMNBUS_REGISTER FERR; // 0x320
+ COLUMNBUS_REGISTER ERRMK; // 0x328
+ COLUMNBUS_REGISTER ERRI; // 0x330
+ COLUMNBUS_REGISTER ERRST; // 0x338
+ COLUMNBUS_REGISTER NMIM; // 0x340
+ COLUMNBUS_REGISTER EAHI; // 0x348
+ COLUMNBUS_REGISTER EALI; // 0x350
+ COLUMNBUS_REGISTER AERR2; // 0x358
+ COLUMNBUS_REGISTER FERR2; // 0x360
+ COLUMNBUS_REGISTER ERRMK2; // 0x368
+ COLUMNBUS_REGISTER ERRI2; // 0x370
+ COLUMNBUS_REGISTER ERRST2; // 0x378
+ COLUMNBUS_REGISTER NMIM2; // 0x380
+ COLUMNBUS_REGISTER STSR; // 0x388
+ COLUMNBUS_REGISTER EVCNT0H; // 0x390
+ COLUMNBUS_REGISTER EVCNT0L; // 0x398
+ COLUMNBUS_REGISTER EVCNTCR0; // 0x3a0
+ COLUMNBUS_REGISTER MODE; // 0x3a8
+ COLUMNBUS_REGISTER Reserved5[10]; // 0x3b0- 0x3f8
+ COLUMNBUS_REGISTER RRMT0H; // 0x400
+ COLUMNBUS_REGISTER RRMT0L; // 0x408
+ COLUMNBUS_REGISTER RRMT1H; // 0x410
+ COLUMNBUS_REGISTER RRMT1L; // 0x418
+ COLUMNBUS_REGISTER RRMT2H; // 0x420
+ COLUMNBUS_REGISTER RRMT2L; // 0x428
+ COLUMNBUS_REGISTER RRMT3H; // 0x430
+ COLUMNBUS_REGISTER RRMT3L; // 0x438
+ COLUMNBUS_REGISTER RRMT4H; // 0x440
+ COLUMNBUS_REGISTER RRMT4L; // 0x448
+ COLUMNBUS_REGISTER RRMT5H; // 0x450
+ COLUMNBUS_REGISTER RRMT5L; // 0x458
+ COLUMNBUS_REGISTER RRMT6H; // 0x460
+ COLUMNBUS_REGISTER RRMT6L; // 0x468
+ COLUMNBUS_REGISTER RRMT7H; // 0x470
+ COLUMNBUS_REGISTER RRMT7L; // 0x478
+ COLUMNBUS_REGISTER RRMT8H; // 0x480
+ COLUMNBUS_REGISTER RRMT8L; // 0x488
+ COLUMNBUS_REGISTER RRMT9H; // 0x490
+ COLUMNBUS_REGISTER RRMT9L; // 0x498
+ COLUMNBUS_REGISTER RRMT10H; // 0x4a0
+ COLUMNBUS_REGISTER RRMT10L; // 0x4a8
+ COLUMNBUS_REGISTER RRMT11H; // 0x4b0
+ COLUMNBUS_REGISTER RRMT11L; // 0x4b8
+ COLUMNBUS_REGISTER RRMT12H; // 0x4c0
+ COLUMNBUS_REGISTER RRMT12L; // 0x4c8
+ COLUMNBUS_REGISTER RRMT13H; // 0x4d0
+ COLUMNBUS_REGISTER RRMT13L; // 0x4d8
+ COLUMNBUS_REGISTER RRMT14H; // 0x4e0
+ COLUMNBUS_REGISTER RRMT14L; // 0x4e8
+ COLUMNBUS_REGISTER RRMT15H; // 0x4f0
+ COLUMNBUS_REGISTER RRMT15L; // 0x4f8
+ COLUMNBUS_REGISTER HPT0; // 0x500
+ COLUMNBUS_REGISTER HPT1; // 0x508
+ COLUMNBUS_REGISTER HPT2; // 0x510
+ COLUMNBUS_REGISTER HPT3; // 0x518
+ COLUMNBUS_REGISTER HPT4; // 0x520
+ COLUMNBUS_REGISTER HPT5; // 0x528
+ COLUMNBUS_REGISTER HPT6; // 0x530
+ COLUMNBUS_REGISTER HPT7; // 0x538
+ COLUMNBUS_REGISTER HPT8; // 0x540
+ COLUMNBUS_REGISTER HPT9; // 0x548
+ COLUMNBUS_REGISTER NRTY1; // 0x550
+ COLUMNBUS_REGISTER Reserved6[5]; // 0x558-0x57f
+ COLUMNBUS_REGISTER IntIR; // 0x580
+ COLUMNBUS_REGISTER RCIR; // 0x588
+ COLUMNBUS_REGISTER TCIR; // 0x590
+ COLUMNBUS_REGISTER HPTIR; // 0x598
+ COLUMNBUS_REGISTER CBIR; // 0x5a0
+ COLUMNBUS_REGISTER Reserved7[11]; // 0x5a8-0x5f8
+ COLUMNBUS_REGISTER SIOCNT; // 0x600
+ COLUMNBUS_REGISTER SIODAT; // 0x608
+ COLUMNBUS_REGISTER ERRNOD; // 0x610
+ COLUMNBUS_REGISTER ERNDRS; // 0x618
+ COLUMNBUS_REGISTER Reserved8[28]; // 0x620-0x6f8
+ COLUMNBUS_REGISTER ARTYCT; // 0x700
+ COLUMNBUS_REGISTER DRTYCT; // 0x708
+ COLUMNBUS_REGISTER TOSR; // 0x710
+ COLUMNBUS_REGISTER NRTY2; // 0x718
+
+} COLUMNBUS_REGISTERS, *PCOLUMNBUS_REGISTERS;
+
+
+
+#define COLUMNBS_GADDR_SHIFT 12
+//
+// How to Access Local Area
+//
+#define COLUMNBS_LCNTL ((volatile PCOLUMNBUS_REGISTERS)(KSEG1_BASE | COLUMNBS_LPHYSICAL_BASE))
+//
+// How to Access Gloabal Area
+// N.B parameter is Node
+// Columbs #0: NODE 4
+// Columbs #1: NODE 5
+// Columbs #2: NODE 6
+// Columbs #3: NODE 7
+//
+#define COLUMNBS_GCNTL( Node ) ((volatile PCOLUMNBUS_REGISTERS)(KSEG1_BASE | \
+ COLUMNBS_GPHYSICAL_BASE | \
+ ((Node) << COLUMNBS_GADDR_SHIFT)))
+//
+// IPR Register
+//
+#define NUMBER_OF_IPR_BIT 64
+
+//
+// TMCRX Register Bit Define
+//
+#define TIMER_NOOP 0x00
+#define TIMER_STOP 0x1
+#define TIMER_START 0x2
+#define TIMER_RELOAD_START 0x3
+
+//
+// TCIR Register Bit Define
+//
+#define TCIR_CLOCK_CMD_SHIFT 26
+#define TCIR_PROFILE_CMD_SHIFT 24
+#define TCIR_ALL_CLOCK_RESTART (TIMER_RELOAD_START << TCIR_CLOCK_CMD_SHIFT)
+
+//
+// STSR Register Bit Define
+//
+#define STSR_EIF 0x80000000
+#define STSR_EIFMK 0x40000000
+#define STSR_FREEZ 0x20000000
+#define STSR_NMIMK 0x08000000
+#define STSR_NVWINH 0x04000000
+#define STSR_NVBINH 0x02000000
+#define STSR_WEIF 0x00800000
+#define STSR_WEIFMK 0x00400000
+#define STSR_WFREEZ 0x00200000
+#define STSR_WNMIMK 0x00080000
+#define STSR_WNVWINH 0x00040000
+#define STSR_WNVBINH 0x00020000
+#define STSR_CLBER 0x00008000
+#define STSR_WAMRST 0x00004000
+#define STSR_EFIFOEMP 0x00000800
+#define STSR_ITVPND 0x00000400
+#define STSR_WRPND 0x00000200
+#define STSR_CTEXE 0x00000100
+#define STSR_MPU 0x00000080
+#define STSR_ENDIAN 0x00000040
+#define STSR_SCSIZE 0x0000001c
+
+//
+// IntIR Register define
+//
+#define IntIR_REQUEST_IPI 0x80000000 // Interrupt Kick
+#define IntIR_CODE_BIT 24 // Bit 24-30 is interrupt code
+#define ATLANTIC_CODE_IPI_FROM_CPU0 0xC
+#define ToNODE4 0x00080000 // to CPU#0
+#define ToNODE5 0x00040000 // to CPU#1
+#define ToNODE6 0x00020000 // to CPU#2
+#define ToNODE7 0x00010000 // to CPU#3
+
+//
+// ERRNOD Register define
+//
+#define ERRNOD_NODE0 0x0008 //PONCE#0
+#define ERRNOD_NODE1 0x0004 //PONCE#1
+#define ERRNOD_NODE4 0x8000 //CPU#0
+#define ERRNOD_NODE5 0x4000 //CPU#1
+#define ERRNOD_NODE6 0x2000 //CPU#2
+#define ERRNOD_NODE7 0x1000 //CPU#3
+#define ERRNOD_NODE8 0x0080 //Magellan#0
+#define ERRNOD_NODE9 0x0040 //Magellan#1
+#define ERRNOD_EISANMI 0x0200 //EISANMI
+#define ERRNOD_ALARM 0x0100 //ALARM
+
+
+//
+// CNFG Register define
+//
+//
+#define CNFG_CONNECT0_PONCE0 0x80000000 //it is Ponce 0
+#define CNFG_CONNECT1_PONCE1 0x40000000 //it is Ponce 1
+#define CNFG_CONNECT4_CPU0 0x08000000 //it is CPU #0
+#define CNFG_CONNECT4_CPU1 0x04000000 //it is CPU #1
+#define CNFG_CONNECT4_CPU2 0x02000000 //it is CPU #2
+#define CNFG_CONNECT4_CPU3 0x01000000 //it is CPU #3
+#define CNFG_CONNECT4_MAGELLAN0 0x00800000 //it is MAGELLAN 0
+#define CNFG_CONNECT4_MAGELLAN1 0x00400000 //it is MAGELLAN 1
+
+
+#define ERRNOD_ALLNODE ((ERRNOD_NODE0|ERRNOD_NODE1| \
+ ERRNOD_NODE4|ERRNOD_NODE5| \
+ ERRNOD_NODE6|ERRNOD_NODE7| \
+ ERRNOD_NODE8|ERRNOD_NODE9))
+
+//
+// NMIR Register define
+//
+//
+#define NMIR_EXNMI 0x0008 //DUMP Key
+#define NMIR_WDTOV 0x0004 //watch dog timer
+#define NMIR_CLBNMI 0x0002 //COLUMBUS Internal
+#define NMIR_UNANMI 0x0001 //F/W,S/W
+
+//
+// ********************************************************************
+// PONCE Register
+//
+typedef struct _PONCE_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+}PONCE_REGISTER,*PPONCE_REGISTER;
+//
+// PONCE Register define
+//
+typedef volatile struct _PONCE_REGISTERS {
+
+ PONCE_REGISTER INTAC; //0x000
+ PONCE_REGISTER CONFA; //0x008
+ PONCE_REGISTER CONFD; //0x010
+ PONCE_REGISTER PTBSR; //0x018
+ PONCE_REGISTER Reserve0; //0x020
+ PONCE_REGISTER PTLMR; //0x028
+ PONCE_REGISTER Reserve1; //0x030
+ PONCE_REGISTER TFLSR; //0x038
+ PONCE_REGISTER Reserve2; //0x040
+ PONCE_REGISTER TLBTG[8]; //0x048
+ PONCE_REGISTER Reserve3[9]; //0x088
+ PONCE_REGISTER ADCFR0; //0x0d0
+ PONCE_REGISTER Reserve4; //0x0d8
+ PONCE_REGISTER PMODR; //0x0e0
+ PONCE_REGISTER Reserve5[3]; //0x0e8
+ PONCE_REGISTER VENID; //0x100
+ PONCE_REGISTER DEVID; //0x108
+ PONCE_REGISTER PCMDN; //0x110
+ PONCE_REGISTER PSTAT; //0x118
+ PONCE_REGISTER REVID; //0x120
+ PONCE_REGISTER CLASS; //0x128
+ PONCE_REGISTER LTNCY; //0x130
+ PONCE_REGISTER Reserve6[2]; //0x138
+ PONCE_REGISTER TLBDT[8]; //0x148
+ PONCE_REGISTER Reserve7[0xf]; //0x188
+
+ PONCE_REGISTER INTRG; //0x200
+ PONCE_REGISTER INTM; //0x208
+ PONCE_REGISTER INTPH; //0x210
+ PONCE_REGISTER INTPL; //0x218
+ PONCE_REGISTER INTTG[11]; //0x220
+ PONCE_REGISTER INTCD[11]; //0x278 - 0x2c8
+ PONCE_REGISTER CAFLS; //0x2d0
+ PONCE_REGISTER CASEL; //0x2d8
+ PONCE_REGISTER CADATH; //0x2e0
+ PONCE_REGISTER CADATL; //0x2e8
+ PONCE_REGISTER CATAGH; //0x2f0
+ PONCE_REGISTER CATAGL; //0x2f8
+ PONCE_REGISTER Reserve8[2]; //0x300 0x308
+ PONCE_REGISTER REVR; //0x310
+ PONCE_REGISTER AERR; //0x318
+ PONCE_REGISTER FERR; //0x320
+ PONCE_REGISTER ERRM; //0x328
+ PONCE_REGISTER ERRI; //0x330
+ PONCE_REGISTER ERRST; //0x338
+ PONCE_REGISTER Reserve9; //0x340
+ PONCE_REGISTER EAHI; //0x348
+ PONCE_REGISTER EALI; //0x350
+ PONCE_REGISTER Reservea[21]; //0x358
+ PONCE_REGISTER RRMT0H; //0x400
+ PONCE_REGISTER RRMT0L; //0x408
+ PONCE_REGISTER RRMT1H; //0x410
+ PONCE_REGISTER RRMT1L; //0x418
+ PONCE_REGISTER RRMT2H; //0x420
+ PONCE_REGISTER RRMT2L; //0x428
+ PONCE_REGISTER RRMT3H; //0x430
+ PONCE_REGISTER RRMT3L; //0x438
+ PONCE_REGISTER RRMT4H; //0x440
+ PONCE_REGISTER RRMT4L; //0x448
+ PONCE_REGISTER RRMT5H; //0x450
+ PONCE_REGISTER RRMT5L; //0x458
+ PONCE_REGISTER RRMT6H; //0x460
+ PONCE_REGISTER RRMT6L; //0x468
+ PONCE_REGISTER RRMT7H; //0x470
+ PONCE_REGISTER RRMT7L; //0x478
+ PONCE_REGISTER Reserveb[16]; //0x480
+
+ PONCE_REGISTER HPT0; //0x500
+ PONCE_REGISTER HPT1; //0x508
+ PONCE_REGISTER HPT2; //0x510
+ PONCE_REGISTER HPT3; //0x518
+ PONCE_REGISTER HPT4; //0x520
+ PONCE_REGISTER HPT5; //0x528
+ PONCE_REGISTER HPT6; //0x530
+ PONCE_REGISTER HPT7; //0x538
+ PONCE_REGISTER HPT8; //0x540
+ PONCE_REGISTER HPT9; //0x548
+ PONCE_REGISTER Reservec[54]; //0x550
+
+ PONCE_REGISTER ANRC; //0x700
+ PONCE_REGISTER DNRC; //0x708
+ PONCE_REGISTER ABRMT; //0x710
+ PONCE_REGISTER Reserved; //0x718
+ PONCE_REGISTER ANKRL2; //0x720
+ PONCE_REGISTER DISN; //0x728
+ PONCE_REGISTER Reserved2[26]; //0x730
+
+ PONCE_REGISTER PAERR; //0x800
+ PONCE_REGISTER PFERR; //0x808
+ PONCE_REGISTER PERRM; //0x810
+ PONCE_REGISTER PERRI; //0x818
+ PONCE_REGISTER PERST; //0x820
+ PONCE_REGISTER PTOL; //0x828
+ PONCE_REGISTER Reservee; //0x830
+ PONCE_REGISTER PNRT; //0x838
+ PONCE_REGISTER PRCOL; //0x840
+ PONCE_REGISTER PMDL; //0x848
+ PONCE_REGISTER PRST; //0x850
+ PONCE_REGISTER ERITTG[3]; //0x858,0x860,0x868
+ PONCE_REGISTER ERITCD[3]; //0x870,0x878,0x880
+ PONCE_REGISTER Reservef[0xf]; //0x888
+ PONCE_REGISTER TRSM; //0x900
+ PONCE_REGISTER TROM; //0x908
+ PONCE_REGISTER TRAC; //0x910
+ PONCE_REGISTER TRDS; //0x918
+ PONCE_REGISTER TRDE; //0x920
+ PONCE_REGISTER TRDO; //0x928
+ PONCE_REGISTER Reserve10[2]; //0x930,0x938
+ PONCE_REGISTER INTSM; //0x940
+
+}PONCE_REGISTERS,*PPONCE_REGISTERS;
+
+
+#define PONCE_ADDR_SHIFT 12
+#define PONCE_MAX 3 //R98[a-z] max Ponce is 3.
+#define PONCE_ADDR_MASK (PONCE_MAX << PONCE_ADDR_SHIFT)
+
+#define PONCE_IOADDR_SHIFT 22
+//
+// Ponce max pci device( Never PCI_MAX_DEVICES)
+//
+#define PONCE_PCI_MAX_DEVICES 21
+
+//
+// I/O TLB
+//
+#define PONCE_MAX_IOTLB_ENTRY 8
+//
+// PONCE Register Access
+//
+#define PONCE_CNTL_BASE_SHIFT 12
+#define PONCE_CNTL(Ponce) ((volatile PPONCE_REGISTERS) \
+ (KSEG1_BASE | PONCE_PHYSICAL_BASE | \
+ ((Ponce) << PONCE_ADDR_SHIFT)))
+
+
+
+//
+// PAERR,PFERR,PERRM,PERRI,PERST Registers Bit Define
+// Bit31 - Bit21 only other is MBZ
+//
+#define PONCE_PXERR_PPERM 0x80000000
+#define PONCE_PXERR_PPERS 0x40000000
+#define PONCE_PXERR_PPERN 0x20000000
+#define PONCE_PXERR_PSERR 0x10000000
+#define PONCE_PXERR_PPCER 0x08000000
+#define PONCE_PXERR_PTOUT 0x04000000
+#define PONCE_PXERR_PROER 0x02000000
+#define PONCE_PXERR_PMDER 0x01000000
+#define PONCE_PXERR_PMABS 0x00800000
+#define PONCE_PXERR_PTABS 0x00400000
+#define PONCE_PXERR_PTABO 0x00200000
+#define PONCE_PXERR_MASK 0xFFE00000
+
+//
+// AERR,FERR,ERRM,ERRI,ERRST Registers Bit Define
+// Bit31 - Bit9 only other is RFU
+//
+#define PONCE_XERR_ACPBERR 0x80000000
+#define PONCE_XERR_RRIBERR 0x40000000
+#define PONCE_XERR_ZERO 0x20000000
+#define PONCE_XERR_SNDERR 0x10000000
+#define PONCE_XERR_ABTMOT 0x08000000
+#define PONCE_XERR_ABWTLT 0x04000000
+#define PONCE_XERR_ABRTYOV 0x02000000
+#define PONCE_XERR_ABRERTOV 0x01000000
+#define PONCE_XERR_NERRR 0x00800000
+#define PONCE_XERR_UNADER 0x00400000
+#define PONCE_XERR_UNCMDER 0x00200000
+#define PONCE_XERR_BWDPER 0x00100000
+#define PONCE_XERR_SLWDPER 0x00080000
+#define PONCE_XERR_BDRPER 0x00040000
+#define PONCE_XERR_SLDRPER 0x00020000
+#define PONCE_XERR_ADPER 0x00010000
+#define PONCE_XERR_CDPER 0x00008000
+#define PONCE_XERR_RRPER 0x00004000
+#define PONCE_XERR_CHICT 0x00002000
+#define PONCE_XERR_STATUMT 0x00001000
+#define PONCE_XERR_TUAER 0x00000800
+#define PONCE_XERR_TIVER 0x00000400
+#define PONCE_XERR_MOVER 0x00000200
+#define PONCE_XERR_MASK 0xDFFFFE00
+
+
+//
+// Dummy Read Registers Index
+//
+typedef enum _INTRG{
+ PCIINTD,
+ PCIINTC,
+ PCIINTB,
+ PCIINTA3,
+ PCIINTA2,
+ PCIINTA1,
+ PCIINTA0,
+ INTSB1,
+ INTSB0,
+ INTSA1,
+ INTSA0,
+}INTRG,*PINTRG;
+
+
+//
+// Dummy Read Registers
+//
+//
+typedef enum _DUMMY_ADDR{
+ DUMMY_A0,
+ DUMMY_A1,
+ DUMMY_A2,
+ DUMMY_A3,
+ DUMMY_A4,
+ DUMMY_A5
+}DUMMY_ADDR,*PDUMMY_ADDR;
+
+#define PONCE0 0x0
+#define PONCE1 0x1
+
+
+//
+// Magellan registers
+//
+//
+
+typedef struct _MAGELLAN_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+}MAGELLAN_REGISTER,*PMAGELLAN_REGISTER;
+//
+// PONCE Register define
+//
+
+typedef volatile struct _MAGELLAN_REGISTERS{
+ MAGELLAN_REGISTER ADEC0; //0x0000
+ MAGELLAN_REGISTER ADEC1; //0x0008
+ MAGELLAN_REGISTER ADEC2; //0x0010
+ MAGELLAN_REGISTER ADEC3; //0x0018
+ MAGELLAN_REGISTER Reserved0[0x1c]; //0x0020
+ MAGELLAN_REGISTER EAADEC0; //0x0100
+ MAGELLAN_REGISTER EAADEC1; //0x0108
+ MAGELLAN_REGISTER Reserved1[0x1de]; //0x0110
+ MAGELLAN_REGISTER INLC; //0x1000
+ MAGELLAN_REGISTER RCFD; //0x1008
+ MAGELLAN_REGISTER Reserved2; //0x1010
+ MAGELLAN_REGISTER DTRG; //0x1018
+ MAGELLAN_REGISTER Reserved4[0x5d]; //0x1020
+ MAGELLAN_REGISTER DISN; //0x1308
+ MAGELLAN_REGISTER REVR; //0x1310
+ MAGELLAN_REGISTER Reserved5[0x3d]; //0x1318
+ MAGELLAN_REGISTER HPT0; //0x1500
+ MAGELLAN_REGISTER HPT1; //0x1508
+ MAGELLAN_REGISTER HPT2; //0x1510
+ MAGELLAN_REGISTER HPT3; //0x1518
+ MAGELLAN_REGISTER HPT4; //0x1520
+ MAGELLAN_REGISTER HPT5; //0x1528
+ MAGELLAN_REGISTER HPT6; //0x1530
+ MAGELLAN_REGISTER HPT7; //0x1538
+ MAGELLAN_REGISTER HPT8; //0x1540
+ MAGELLAN_REGISTER HPT9; //0x1548
+ MAGELLAN_REGISTER Reserved6[0x1b9]; //0x1550
+ MAGELLAN_REGISTER AERR; //0x2318
+ MAGELLAN_REGISTER FERR; //0x2320
+ MAGELLAN_REGISTER ERRM; //0x2328
+ MAGELLAN_REGISTER ERRI; //0x2330
+ MAGELLAN_REGISTER ERRST; //0x2338
+ MAGELLAN_REGISTER Reserved7; //0x2340
+ MAGELLAN_REGISTER EIFM; //0x2348
+ MAGELLAN_REGISTER EAHI; //0x2350
+ MAGELLAN_REGISTER EALI; //0x2358
+ MAGELLAN_REGISTER Reserved8[2]; //0x2360
+ MAGELLAN_REGISTER CKE0; //0x2370
+ MAGELLAN_REGISTER Reserved9; //0x2378
+ MAGELLAN_REGISTER SECT; //0x2380
+ MAGELLAN_REGISTER STS1; //0x2388
+ MAGELLAN_REGISTER RSRG; //0x2390
+ MAGELLAN_REGISTER DATM; //0x2398
+ MAGELLAN_REGISTER DSRG; //0x23a0
+ MAGELLAN_REGISTER SDLM; //0x23a8
+ MAGELLAN_REGISTER Reserveda[0x18a]; //0x23b0
+ MAGELLAN_REGISTER SDCR; //0x3000
+ MAGELLAN_REGISTER Reservedb[0x27f]; //0x3008
+ MAGELLAN_REGISTER RRMTH0; //0x4400
+ MAGELLAN_REGISTER RRMTL0; //0x4408
+ MAGELLAN_REGISTER RRMTH1; //0x4410
+ MAGELLAN_REGISTER RRMTL1; //0x4418
+ MAGELLAN_REGISTER RRMTH2; //0x4420
+ MAGELLAN_REGISTER RRMTL2; //0x4428
+ MAGELLAN_REGISTER RRMTH3; //0x4430
+ MAGELLAN_REGISTER RRMTL3; //0x4438
+ MAGELLAN_REGISTER RRMTH4; //0x4440
+ MAGELLAN_REGISTER RRMTL4; //0x4448
+ MAGELLAN_REGISTER RRMTH5; //0x4450
+ MAGELLAN_REGISTER RRMTL5; //0x4458
+ MAGELLAN_REGISTER RRMTH6; //0x4460
+ MAGELLAN_REGISTER RRMTL6; //0x4468
+ MAGELLAN_REGISTER RRMTH7; //0x4470
+ MAGELLAN_REGISTER RRMTL7; //0x4478
+ MAGELLAN_REGISTER Reservedc[0x170]; //0x4480
+ MAGELLAN_REGISTER PCM; //0x5000
+ MAGELLAN_REGISTER PCH; //0x5008
+ MAGELLAN_REGISTER Reservedd[0x1e]; //0x5010
+ MAGELLAN_REGISTER TMOD; //0x5100
+ MAGELLAN_REGISTER TRA; //0x5108
+ MAGELLAN_REGISTER Reservede[0x1e]; //0x5110
+ MAGELLAN_REGISTER TRM0[0x20]; //0x5200
+ MAGELLAN_REGISTER TRM1[0x20]; //0x5300
+ MAGELLAN_REGISTER TRM2[0x20]; //0x5400
+}MAGELLAN_REGISTERS,*PMAGELLAN_REGISTERS;
+
+
+
+//
+// How to Access Local Area
+//
+#define MAGELLAN_0_CNTL ((volatile PMAGELLAN_REGISTERS)(KSEG1_BASE | MAGELLAN_0_PHYSICAL_BASE))
+#define MAGELLAN_1_CNTL ((volatile PMAGELLAN_REGISTERS)(KSEG1_BASE | MAGELLAN_1_PHYSICAL_BASE))
+
+#define MAGELLAN_X_CNTL(x) ((volatile PMAGELLAN_REGISTERS)(KSEG1_BASE |\
+ ((x) ? MAGELLAN_1_PHYSICAL_BASE : MAGELLAN_0_PHYSICAL_BASE)))
+
+//
+// Define LOCAL device Control register structure.
+//
+typedef struct _LOCAL_REGISTERS { // offset(H)
+ UCHAR LBCTL; // 0x0
+ UCHAR Reserved0[15];
+ UCHAR LBADL; // 0x10
+ UCHAR Reserved1[7];
+ UCHAR LBADH; // 0x18
+ UCHAR Reserved2[7];
+ UCHAR LBDT; // 0x20
+}LOCAL_REGISTERS, *PLOCAL_REGISTERS;
+
+
+//
+// LBCTL Regiser Bit define
+//
+
+#define LBCTL_SWE 0x80
+#define LBCTL_SEMAPHORE 0x40
+#define LBCTL_CMD 0x10
+#define LBCTL_READ 0x08
+
+//
+// MRC Register Offset
+//
+#define MRCINT 0x0200
+#define MRCMODE 0x0208
+#define MRC_SWPOWEROFF 0x0230
+#define MRC_FDWRITEPROTECT 0x0250
+
+
+//
+// ALARM Register Offset
+//
+#define ALARM_LOW 0x410
+#define ALARM_HIGH 0x411
+#define ALMINH_LOW 0x414
+#define ALMINH_HIGH 0x415
+#define ALMSNS_LOW 0x418
+#define ALMSNS_HIGH 0x419
+
+//
+// Define pointer to Local Device Control registers.
+//
+#define LOCAL_CNTL ((volatile PLOCAL_REGISTERS)(KSEG1_BASE | LOCALDEV_PHYSICAL_BASE))
+
+
+#endif _R98BREG_
diff --git a/private/ntos/nthals/halr98b/mips/rgb525.h b/private/ntos/nthals/halr98b/mips/rgb525.h
new file mode 100644
index 000000000..9c157bc95
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rgb525.h
@@ -0,0 +1,468 @@
+// #pragma comment(exestr, "@(#) rgb525.h 1.1 95/07/24 10:53:20 nec")
+/************************************************************************
+ * *
+ * Copyright (c) 1994 3Dlabs Inc. Ltd. *
+ * All rights reserved *
+ * *
+ * This software and its associated documentation contains proprietary, *
+ * confidential and trade secret information of 3Dlabs Inc. Ltd. and *
+ * except as provided by written agreement with 3Dlabs Inc. Ltd. *
+ * *
+ * a) no part may be disclosed, distributed, reproduced, transmitted, *
+ * transcribed, stored in a retrieval system, adapted or translated *
+ * in any form or by any means electronic, mechanical, magnetic, *
+ * optical, chemical, manual or otherwise, *
+ * *
+ * and *
+ * *
+ * b) the recipient is not entitled to discover through reverse *
+ * engineering or reverse compiling or other such techniques or *
+ * processes the trade secrets contained therein or in the *
+ * documentation. *
+ * *
+ ************************************************************************/
+
+#ifndef __RGB525_H__
+#define __RGB525_H__
+
+/************************************************************************/
+/* DIRECT ACCESS REGISTERS */
+/************************************************************************/
+
+/* direct registers on 64-bit boundaries */
+
+#define __RGB525_PalAddrWrite 0x00
+#define __RGB525_PaletteData 0x08
+#define __RGB525_PixelMask 0x10
+#define __RGB525_PalAddrRead 0x18
+#define __RGB525_IndexLow 0x20
+#define __RGB525_IndexHigh 0x28
+#define __RGB525_IndexedData 0x30
+#define __RGB525_IndexControl 0x38
+
+/************************************************************************/
+/* INDEXED REGISTERS - MISCELLANEOUS CONTROL */
+/************************************************************************/
+
+#define __RGB525_MiscControlOne 0x0070
+#define __RGB525_MiscControlTwo 0x0071
+#define __RGB525_MiscControlThree 0x0072
+#define __RGB525_MiscClockControl 0x0002
+#define __RGB525_SyncControl 0x0003
+#define __RGB525_HSyncControl 0x0004
+#define __RGB525_PowerManagement 0x0005
+#define __RGB525_DACOperation 0x0006
+#define __RGB525_PaletteControl 0x0007
+
+/* MiscControlOne */
+
+#define RGB525_MISR_CNTL_OFF (0 << 7)
+#define RGB525_MISR_CNTL_ON (1 << 7)
+#define RGB525_VMSK_CNTL_OFF (0 << 6)
+#define RGB525_VMSK_CNTL_ON (1 << 6)
+#define RGB525_PADR_RFMT_READ_ADDR (0 << 5)
+#define RGB525_PADR_RFMT_PAL_STATE (1 << 5)
+#define RGB525_SENS_DSAB_ENABLE (0 << 4)
+#define RGB525_SENS_DSAB_DISABLE (1 << 4)
+#define RGB525_SENS_SEL_BIT3 (0 << 3)
+#define RGB525_SENS_SEL_BIT7 (1 << 3)
+#define RGB525_VRAM_SIZE_32 (0 << 0)
+#define RGB525_VRAM_SIZE_64 (1 << 0)
+
+/* MiscControlTwo */
+
+#define RGB525_PCLK_SEL_LCLK (0 << 6)
+#define RGB525_PCLK_SEL_PLL (1 << 6)
+#define RGB525_PCLK_SEL_EXT (2 << 6)
+#define RGB525_INTL_MODE_DISABLE (0 << 5)
+#define RGB525_INTL_MODE_ENABLE (1 << 5)
+#define RGB525_BLANK_CNTL_NORMAL (0 << 4)
+#define RGB525_BLANK_CNTL_BLANKED (1 << 4)
+#define RGB525_COL_RES_6_BIT (0 << 2)
+#define RGB525_COL_RES_8_BIT (1 << 2)
+#define RGB525_PORT_SEL_VGA (0 << 0)
+#define RGB525_PORT_SEL_VRAM (1 << 0)
+
+/* MiscControlThree */
+
+#define RGB525_SWAP_RB_DISABLE (0 << 7)
+#define RGB525_SWAP_RB_ENABLE (1 << 7)
+#define RGB525_SWAP_WORD_31_00_FIRST (0 << 4)
+#define RGB525_SWAP_WORD_63_32_FIRST (1 << 4)
+#define RGB525_SWAP_NIB_07_04_FIRST (0 << 2)
+#define RGB525_SWAP_NIB_03_00_FIRST (1 << 2)
+
+/* MiscClockControl */
+
+#define RGB525_DDOTCLK_ENABLE (0 << 7)
+#define RGB525_DDOTCLK_DISABLE (1 << 7)
+#define RGB525_SCLK_ENABLE (0 << 6)
+#define RGB525_SCLK_DISABLE (1 << 6)
+#define RGB525_B24P_DDOT_DIV_PLL (0 << 5)
+#define RGB525_B24P_DDOT_SCLK (1 << 5)
+#define RGB525_DDOT_PLL_DIV_1 (0 << 1)
+#define RGB525_DDOT_PLL_DIV_2 (1 << 1)
+#define RGB525_DDOT_PLL_DIV_4 (2 << 1)
+#define RGB525_DDOT_PLL_DIV_8 (3 << 1)
+#define RGB525_DDOT_PLL_DIV_16 (4 << 1)
+#define RGB525_PLL_DISABLE (0 << 0)
+#define RGB525_PLL_ENABLE (1 << 0)
+
+/* SyncControl */
+
+#define RGB525_DLY_CNTL_ADD (0 << 7)
+#define RGB525_DLY_SYNC_NOADD (1 << 7)
+#define RGB525_CSYN_INVT_DISABLE (0 << 6)
+#define RGB525_CSYN_INVT_ENABLE (1 << 6)
+#define RGB525_VSYN_INVT_DISABLE (0 << 5)
+#define RGB525_VSYN_INVT_ENABLE (1 << 5)
+#define RGB525_HSYN_INVT_DISABLE (0 << 4)
+#define RGB525_HSYN_INVT_ENABLE (1 << 4)
+#define RGB525_VSYN_CNTL_NORMAL (0 << 2)
+#define RGB525_VSYN_CNTL_HIGH (1 << 2)
+#define RGB525_VSYN_CNTL_LOW (2 << 2)
+#define RGB525_VSYN_CNTL_DISABLE (3 << 2)
+#define RGB525_HSYN_CNTL_NORMAL (0 << 0)
+#define RGB525_HSYN_CNTL_HIGH (1 << 0)
+#define RGB525_HSYN_CNTL_LOW (2 << 0)
+#define RGB525_HSYN_CNTL_DISABLE (3 << 0)
+
+/* HSyncControl */
+
+#define RGB525_HSYN_POS(n) ((n) & 0xF)
+
+/* PowerManagement */
+
+#define RGB525_SCLK_PWR_NORMAL (0 << 4)
+#define RGB525_SCLK_PWR_DISABLE (1 << 4)
+#define RGB525_DDOT_PWR_NORMAL (0 << 3)
+#define RGB525_DDOT_PWR_DISABLE (1 << 3)
+#define RGB525_SYNC_PWR_NORMAL (0 << 2)
+#define RGB525_SYNC_PWR_DISABLE (1 << 2)
+#define RGB525_ICLK_PWR_NORMAL (0 << 1)
+#define RGB525_ICLK_PWR_DISABLE (1 << 1)
+#define RGB525_DAC_PWR_NORMAL (0 << 0)
+#define RGB525_DAC_PWR_DISABLE (1 << 0)
+
+/* DACOperation */
+
+#define RGB525_SOG_DISABLE (0 << 3)
+#define RGB525_SOG_ENABLE (1 << 3)
+#define RGB525_BRB_NORMAL (0 << 2)
+#define RGB525_BRB_ALWAYS (1 << 2)
+#define RGB525_DSR_SLOW (0 << 1)
+#define RGB525_DSR_FAST (1 << 1)
+#define RGB525_DPE_DISABLE (0 << 0)
+#define RGB525_DPE_ENABLE (1 << 0)
+
+/* PaletteControl */
+
+#define RGB525_6BIT_LINEAR_ENABLE (0 << 7)
+#define RGB525_6BIT_LINEAR_DISABLE (1 << 7)
+#define RGB525_PALETTE_PARTITION(n) ((n) & 0xF)
+
+/************************************************************************/
+/* INDEXED REGISTERS - PIXEL REPRESENTATION */
+/************************************************************************/
+
+#define __RGB525_PixelFormat 0x000A
+#define __RGB525_8BitPixelControl 0x000B
+#define __RGB525_16BitPixelControl 0x000C
+#define __RGB525_24BitPixelControl 0x000D
+#define __RGB525_32BitPixelControl 0x000E
+
+/* PixelFormat */
+
+#define RGB525_PIXEL_FORMAT_4_BPP (2 << 0)
+#define RGB525_PIXEL_FORMAT_8_BPP (3 << 0)
+#define RGB525_PIXEL_FORMAT_16_BPP (4 << 0)
+#define RGB525_PIXEL_FORMAT_24_BPP (5 << 0)
+#define RGB525_PIXEL_FORMAT_32_BPP (6 << 0)
+
+/* 8BitPixelControl */
+
+#define RGB525_B8_DCOL_INDIRECT (0 << 0)
+#define RGB525_B8_DCOL_DIRECT (1 << 0)
+
+/* 16BitPixelControl */
+
+#define RGB525_B16_DCOL_INDIRECT (0 << 6)
+#define RGB525_B16_DCOL_DYNAMIC (1 << 6)
+#define RGB525_B16_DCOL_DIRECT (3 << 6)
+#define RGB525_B16_POL_FORCES_BYPASS (0 << 5)
+#define RGB525_B16_POL_FORCES_LOOKUP (1 << 5)
+#define RGB525_B16_ZIB (0 << 2)
+#define RGB525_B16_LINEAR (1 << 2)
+#define RGB525_B16_555 (0 << 1)
+#define RGB525_B16_565 (1 << 1)
+#define RGB525_B16_SPARSE (0 << 0)
+#define RGB525_B16_CONTIGUOUS (1 << 0)
+
+/* 24BitPixelControl */
+
+#define RGB525_B24_DCOL_INDIRECT (0 << 0)
+#define RGB525_B24_DCOL_DIRECT (1 << 0)
+
+/* 32BitPixelControl */
+
+#define RGB525_B32_POL_FORCES_BYPASS (0 << 2)
+#define RGB525_B32_POL_FORCES_LOOKUP (1 << 2)
+#define RGB525_B32_DCOL_INDIRECT (0 << 0)
+#define RGB525_B32_DCOL_DYNAMIC (1 << 0)
+#define RGB525_B32_DCOL_DIRECT (3 << 0)
+
+/************************************************************************/
+/* INDEXED REGISTERS - FREQUENCY CONTROL */
+/************************************************************************/
+
+#define __RGB525_PLLControlOne 0x0010
+#define __RGB525_PLLControlTwo 0x0011
+#define __RGB525_PLLRefDivCount 0x0014
+
+#define __RGB525_F0 0x0020
+#define __RGB525_F1 0x0021
+#define __RGB525_F2 0x0022
+#define __RGB525_F3 0x0023
+#define __RGB525_F4 0x0024
+#define __RGB525_F5 0x0025
+#define __RGB525_F6 0x0026
+#define __RGB525_F7 0x0027
+#define __RGB525_F8 0x0028
+#define __RGB525_F9 0x0029
+#define __RGB525_F10 0x002A
+#define __RGB525_F11 0x002B
+#define __RGB525_F12 0x002C
+#define __RGB525_F13 0x002D
+#define __RGB525_F14 0x002E
+#define __RGB525_F15 0x002F
+
+#define __RGB525_M0 0x0020
+#define __RGB525_M1 0x0022
+#define __RGB525_M2 0x0024
+#define __RGB525_M3 0x0026
+#define __RGB525_M4 0x0028
+#define __RGB525_M5 0x002A
+#define __RGB525_M6 0x002C
+#define __RGB525_M7 ox002E
+
+#define __RGB525_N0 0x0021
+#define __RGB525_N1 0x0023
+#define __RGB525_N2 0x0025
+#define __RGB525_N3 0x0027
+#define __RGB525_N4 0x0029
+#define __RGB525_N5 0x002B
+#define __RGB525_N6 0x002D
+#define __RGB525_N7 ox002F
+
+/* PLLControlOne */
+
+#define RGB525_REF_SRC_REFCLK (0 << 4)
+#define RGB525_REF_SRC_EXTCLK (1 << 4)
+#define RGB525_PLL_EXT_FS_DIRECT (0 << 0)
+#define RGB525_PLL_EXT_FS_M_N (1 << 0)
+#define RGB525_PLL_INT_FS_DIRECT (2 << 0)
+#define RGB525_PLL_INT_FS_M_N (3 << 0)
+
+/* PLLControlTwo */
+
+#define RGB525_PLL_INT_FS(n) ((n) & 0xF)
+
+/* PLLRefDivCount */
+
+#define RGB525_REF_DIV_COUNT(n) ((n) & 0x1F)
+
+#define RGB525_PLL_REFCLK_4_MHz (0x02)
+#define RGB525_PLL_REFCLK_6_MHz (0x03)
+#define RGB525_PLL_REFCLK_8_MHz (0x04)
+#define RGB525_PLL_REFCLK_10_MHz (0x05)
+#define RGB525_PLL_REFCLK_12_MHz (0x06)
+#define RGB525_PLL_REFCLK_14_MHz (0x07)
+#define RGB525_PLL_REFCLK_16_MHz (0x08)
+#define RGB525_PLL_REFCLK_18_MHz (0x09)
+#define RGB525_PLL_REFCLK_20_MHz (0x0A)
+#define RGB525_PLL_REFCLK_22_MHz (0x0B)
+#define RGB525_PLL_REFCLK_24_MHz (0x0C)
+#define RGB525_PLL_REFCLK_26_MHz (0x0D)
+#define RGB525_PLL_REFCLK_28_MHz (0x0E)
+#define RGB525_PLL_REFCLK_30_MHz (0x0F)
+#define RGB525_PLL_REFCLK_32_MHz (0x10)
+#define RGB525_PLL_REFCLK_34_MHz (0x11)
+#define RGB525_PLL_REFCLK_36_MHz (0x12)
+#define RGB525_PLL_REFCLK_38_MHz (0x13)
+#define RGB525_PLL_REFCLK_40_MHz (0x14)
+#define RGB525_PLL_REFCLK_42_MHz (0x15)
+#define RGB525_PLL_REFCLK_44_MHz (0x16)
+#define RGB525_PLL_REFCLK_46_MHz (0x17)
+#define RGB525_PLL_REFCLK_48_MHz (0x18)
+#define RGB525_PLL_REFCLK_50_MHz (0x19)
+#define RGB525_PLL_REFCLK_52_MHz (0x1A)
+#define RGB525_PLL_REFCLK_54_MHz (0x1B)
+#define RGB525_PLL_REFCLK_56_MHz (0x1C)
+#define RGB525_PLL_REFCLK_58_MHz (0x1D)
+#define RGB525_PLL_REFCLK_60_MHz (0x1E)
+#define RGB525_PLL_REFCLK_62_MHz (0x1F)
+
+/* F0-F15[7:0] */
+
+#define RGB525_DF(n) (((n) & 0x3) << 6)
+#define RGB525_VCO_DIV_COUNT(n) ((n) & 0x3F)
+
+/************************************************************************/
+/* INDEXED REGISTERS - CURSOR */
+/************************************************************************/
+
+#define __RGB525_CursorControl 0x0030
+#define __RGB525_CursorXLow 0x0031
+#define __RGB525_CursorXHigh 0x0032
+#define __RGB525_CursorYLow 0x0033
+#define __RGB525_CursorYHigh 0x0034
+#define __RGB525_CursorHotSpotX 0x0035
+#define __RGB525_CursorHotSpotY 0x0036
+#define __RGB525_CursorColor1Red 0x0040
+#define __RGB525_CursorColor1Green 0x0041
+#define __RGB525_CursorColor1Blue 0x0042
+#define __RGB525_CursorColor2Red 0x0043
+#define __RGB525_CursorColor2Green 0x0044
+#define __RGB525_CursorColor2Blue 0x0045
+#define __RGB525_CursorColor3Red 0x0046
+#define __RGB525_CursorColor3Green 0x0047
+#define __RGB525_CursorColor3Blue 0x0048
+
+/* CursorControl */
+
+#define RGB525_SMLC_PART_0 (0 << 6)
+#define RGB525_SMLC_PART_1 (1 << 6)
+#define RGB525_SMLC_PART_2 (2 << 6)
+#define RGB525_SMLC_PART_3 (3 << 6)
+#define RGB525_PIX_ORDER_RIGHT_TO_LEFT (0 << 5)
+#define RGB525_PIX_ORDER_LEFT_TO_RIGHT (1 << 5)
+#define RGB525_LOC_READ_LAST_WRITTEN (0 << 4)
+#define RGB525_LOC_READ_ACTUAL_LOCATION (1 << 4)
+#define RGB525_UPDT_CNTL_DELAYED (0 << 3)
+#define RGB525_UPDT_CNTL_IMMEDIATE (1 << 3)
+#define RGB525_CURSOR_SIZE_32 (0 << 2)
+#define RGB525_CURSOR_SIZE_64 (1 << 2)
+#define RGB525_CURSOR_MODE_OFF (0 << 0)
+#define RGB525_CURSOR_MODE_3_COLOR (1 << 0)
+#define RGB525_CURSOR_MODE_2_COLOR_HL (2 << 0)
+#define RGB525_CURSOR_MODE_2_COLOR (3 << 0)
+
+/************************************************************************/
+/* INDEXED REGISTERS - BORDER COLOR */
+/************************************************************************/
+
+#define __RGB525_BorderColorRed 0x0060
+#define __RGB525_BorderColorGreen 0x0061
+#define __RGB525_BorderColorBlue 0x0062
+
+/************************************************************************/
+/* INDEXED REGISTERS - DIAGNOSTIC SUPPORT */
+/************************************************************************/
+
+#define __RGB525_RevisionLevel 0x0000
+#define __RGB525_ProductID 0x0001
+#define __RGB525_DACSense 0x0082
+#define __RGB525_MISRRed 0x0084
+#define __RGB525_MISRGreen 0x0086
+#define __RGB525_MISRBlue 0x0088
+#define __RGB525_PLLVCODivInput 0x008E
+#define __RGB525_PLLVCORefInput 0x008F
+#define __RGB525_VramMaskLow 0x0090
+#define __RGB525_VramMaskHigh 0x0091
+
+/* RevisionLevel */
+
+#define RGB525_PRODUCT_REV_LEVEL 0xF0
+
+/* ProductID */
+
+#define RGB525_PRODUCT_ID_CODE 0x01
+
+/************************************************************************/
+/* INDEXED REGISTERS - CURSOR ARRAY */
+/************************************************************************/
+
+#define __RGB525_CursorArray 0x0100
+
+/************************************************************************/
+/* DIRECT ACCESS MACROS */
+/************************************************************************/
+/*
+ * The pixel clock must be running to access the palette and the cursor
+ * array, and the timings for the microprocessor signals are specified
+ * in units of pixel clocks. Six clocks must be allowed for an internal
+ * access to complete, following a palette or cursor access.
+ *
+ * In the worst case (VGA 640x480 resolution) the pixel clock is 40 ns,
+ * giving a time of 280 ns for seven pixel clocks. Assuming the fastest
+ * host clock is 100 MHz, a delay of 28 host clocks is required. Again
+ * assuming that the loop below takes 3 clocks per iteration, it should
+ * be executed at least 10 times.
+ */
+
+#define RGB525_DELAY \
+{ \
+ volatile DWORD __rgb525_dly; \
+ \
+ for (__rgb525_dly = 0; __rgb525_dly < 10; __rgb525_dly++); \
+}
+
+/*
+ * All RGB525 accesses are followed by a short delay, as required by
+ * the AC Characteristics table in the RGB525 Databook. However, the
+ * text implies that non-palette or cursor-array accesses can happen
+ * closer together. Everything is delayed here for simplicity.
+ */
+
+#define RGB525_ADDR(base, offset) \
+( \
+/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \
+ (DWORD) ((base) + (offset)) \
+)
+
+#define RGB525_WRITE(dac, offset, data) \
+{ \
+/* DWORD_WRITE(RGB525_ADDR((dac),(offset)), (data)); */ \
+ WRITE_REGISTER_UCHAR(RGB525_ADDR((dac),(offset)), (UCHAR)(data)); \
+ RGB525_DELAY; \
+}
+
+#define RGB525_READ_BYTE(dac, offset, data) \
+{ \
+ DWORD __rgb525_tmp; \
+ \
+/* DWORD_READ(RGB525_ADDR((dac),(offset)), __rgb525_tmp); */ \
+ __rgb525_tmp = READ_REGISTER_UCHAR(RGB525_ADDR((dac),(offset))); \
+/* (data) = (BYTE) (__rgb525_tmp & BYTE_MAX); */ \
+ (data) = (UCHAR) (__rgb525_tmp & 0xff); \
+ RGB525_DELAY; \
+}
+
+/************************************************************************/
+/* INDEXED ACCESS MACROS */
+/************************************************************************/
+
+#define RGB525_SET_INDEX(dac, index) \
+{ \
+ RGB525_WRITE((dac), __RGB525_IndexLow, (index)); \
+/* RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> BYTE_BITS); */ \
+ RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> 8); \
+}
+
+#define RGB525_SET_REG(dac, index, data) \
+{ \
+ RGB525_SET_INDEX((dac), (index)); \
+ RGB525_WRITE((dac), __RGB525_IndexedData, (data)); \
+}
+
+#define RGB525_GET_REG(dac, index, data) \
+{ \
+ RGB525_SET_INDEX((dac), (index)); \
+ RGB525_READ_BYTE((dac), __RGB525_IndexedData, (data)); \
+}
+
+/************************************************************************/
+
+#endif /* __RGB525_H__ */
+
+/************************************************************************/
diff --git a/private/ntos/nthals/halr98b/mips/rxbusdat.c b/private/ntos/nthals/halr98b/mips/rxbusdat.c
new file mode 100644
index 000000000..fdf6541bb
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxbusdat.c
@@ -0,0 +1,290 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ rxbusdat.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpHibernateHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+HalpResumeHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+#if 0
+ //
+ // Hibernate and resume the hal by getting notifications
+ // for when this bus is hibernated or resumed. Since it's
+ // the first bus to be added, it will be the last to hibernate
+ // and the first to resume
+ //
+
+ Bus->HibernateBus = HalpHibernateHal;
+ Bus->ResumeBus = HalpResumeHal;
+#endif
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+ //
+ // R98B Build Other Bus (PCIBus)
+ // move to jxusage.c
+ // HalpInitializePciBus();
+
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+ ULONG Ponce;
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+
+ // R98B must be MemorySpace!!.
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ switch(InterfaceType) {
+
+ case PCIBus:
+
+ Ponce = HalpPonceNumber((ULONG)BusNumber);
+ if(Ponce == 0){
+ // Ponce 0: Below 64M is EISA/ISA Memory Area.
+ Bus->BusAddresses->Memory.Base = 0x04000000;
+ }else{
+// Bus->BusAddresses->Memory.Base = 0x0;
+ // Less than 16M is PCI DMA area.
+ Bus->BusAddresses->Memory.Base = 0x01000000;
+ }
+ Bus->BusAddresses->Memory.Limit = 0x3fffffff; //1G
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = PCI_MEMORY_PHYSICAL_BASE_LOW+
+ PCI_MAX_MEMORY_SIZE * Ponce;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = PCI_MEMORY_PHYSICAL_BASE_HIGH;
+ if(Ponce == 0){
+ // N.B
+ // Io Manager allocate PCI I/O area From high addr of I/O space.
+ // EISA I/O Addr is Slot dependent and R98B max eisa slot is 3.
+ // So EISA i/o addr is below 0x4000. Perhaps PCI and EISA I/O area
+ // not conflict. But When One of PCI Device big I/O area required
+ // whitch EISA Device Slot dependent I/O area.
+ // PCI device positive decode and EISA Device can't decode.
+ // EISA device can decode when PCEB substruct decode of PCI cycle.
+ // (Any Device can't positivedecode)
+ // So Set IO.Base EISA 4 slot I/O addr.(Never EISA Slot 4)
+ //
+// Bus->BusAddresses->IO.Base = 0x00004000;
+ //
+ // 4000 - 4fff is dummy backward compatibility for scsi.
+ // It is Dummy Area. See
+ //
+ Bus->BusAddresses->IO.Base = 0x00005000;
+ }else{
+ Bus->BusAddresses->IO.Base = 0x00000000;
+ }
+ Bus->BusAddresses->IO.Limit = 0x0000FFFF; //64K
+
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = PCI_CNTL_PHYSICAL_BASE+
+ PCI_MAX_CNTL_SIZE * Ponce;
+
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->HighPart
+ = 0x0;
+ break;
+
+
+ case Internal:
+
+ Bus->BusAddresses->Dma.Limit = 7; // 0-7 channel
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0x3FFFFFFF; // 1G
+ Bus->BusAddresses->Memory.SystemBase
+ = 0x00000000;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
+ = 0x3FFFFFFF; // 1G
+ Bus->BusAddresses->IO.SystemBase
+ = 0x00000000;
+ break;
+
+
+ case Eisa:
+ case Isa:
+
+ Bus->BusAddresses->Dma.Limit = 7; // 0-7 channel
+
+ Bus->BusAddresses->Memory.Base = 0x00000000;
+
+ if(InterfaceType == Eisa){
+ Bus->BusAddresses->Memory.Limit = 0x03FFFFFF; //64M
+ }else{
+ //
+ // ISA or Internal(XBus)
+ //
+ Bus->BusAddresses->Memory.Limit = 0x00FFFFFF; //16M
+ }
+
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_PHYSICAL_BASE_LOW;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart
+ = EISA_MEMORY_PHYSICAL_BASE_HIGH;
+
+ Bus->BusAddresses->IO.Base = 0x00000000;
+
+ //
+ // Max Slot is 3 . Bad Alias . So 3fff --> 4fff
+ //
+ Bus->BusAddresses->IO.Limit = 0x00004fff; // For max 3 slot.
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CNTL_PHYSICAL_BASE;
+
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->HighPart
+ = 0;
+ break;
+ }
+ }
+
+ return Bus;
+}
diff --git a/private/ntos/nthals/halr98b/mips/rxclock.s b/private/ntos/nthals/halr98b/mips/rxclock.s
new file mode 100644
index 000000000..9c0010046
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxclock.s
@@ -0,0 +1,368 @@
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// r98clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+//--
+
+#include "halmips.h"
+#include "r98bdef.h"
+
+#define ECC_ERROR_COUNT_LIMIT 1
+#define CNFG_CONNECT4_MAGELLAN0 0x00800000 //it is MAGELLAN 0
+#define CNFG_CONNECT4_MAGELLAN1 0x00400000 //it is MAGELLAN 1
+
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ sw zero,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x50(zero) // Columnbs TOVCT1 reg.
+
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// The following code is a work around for a bug in the Fusion machines
+// where the clock interrupt is not dismissed by reading the acknowledge
+// register.
+//
+
+ la t0,HalpStartWDTFlag
+ lw t1,0x0(t0)
+ beq zero,t1,2f
+ la t2,HalpSetWDTCount
+ lw t1,0x0(t2)
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x80(zero) // Columnbs reg.
+ li t1,0x00000002
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg.
+ sw zero,0x0(t0)
+2: la t0,HalpStopWDTFlag
+ lw t1,0x0(t0)
+ beq zero,t1,3f
+ li t1,0x00000001
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg.
+ sw zero,0x0(t0)
+3: la t0,HalpSetWDTFlag
+ lw t1,0x0(t0)
+ beq zero,t1,4f
+ li t1,0x00000002
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg.
+ sw zero,0x0(t0)
+4:
+
+//
+// Check ECC 1bit error flag.
+//
+
+ lw t0,HalpECC1bitDisableTime // get value of disable time
+ beq zero,t0,10f // if ne, check ecc 1bit
+ lw t1,HalpCurrentTimeIncrement // get current time increment
+ subu t0,t0,t1 // declement disable time
+ sw t0,HalpECC1bitDisableTime //
+ blez t0,5f // if lez, enable ecc 1bit
+ beq zero,zero,10f // not lez,
+
+5: sw zero,HalpECC1bitDisableTime // clear disable time
+ li t0,ECC_ERROR_COUNT_LIMIT // set new flag
+ sw t0,HalpECC1bitDisableFlag //
+ la t1,KSEG1_BASE+MAGELLAN_0_PHYSICAL_BASE+MAGELLAN_ERRI_OFFSET
+ lw t2,HalpPhysicalNode // check connect to Magellan
+ and t0,t2,CNFG_CONNECT4_MAGELLAN0
+ bne t0,zero,7f
+ lw t0,0x0(t1)
+ and t0,ECC_1BIT_ENABLE
+ sw t0,0x0(t1) // enable ECC 1bit error
+7:
+ and t0,t2,CNFG_CONNECT4_MAGELLAN1
+ bne t0,zero,10f
+ la t1,KSEG1_BASE+MAGELLAN_1_PHYSICAL_BASE+MAGELLAN_ERRI_OFFSET
+ lw t0,0x0(t1)
+ and t0,ECC_1BIT_ENABLE
+ sw t0,0x0(t1) // enable ECC 1bit error
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+10: lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,30f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+
+ .set noreorder
+
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x40(zero) // Columnbs TMSR1 reg.
+
+ .set reorder
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ break BREAKIN_BREAKPOINT // break into the debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+ sw zero,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x50(zero) // Columnbs TOVCT1 reg.
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+
+#if 0
+ la t2,HalpChangeIntervalFlg // get change flag of timer interval
+ lbu t1,PbNumber(t1) // get processor number
+ add t2,t1,t2 // check flag
+ lb t1,0x0(t2) // get change flag of this CPU
+ beq t1,zero,10f // if eq, no change timer interval
+ sb zero,0x0(t2) // clear change flag of timer interval
+
+ lw t1,HalpChangeIntervalCount // get next interval count
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x40(zero) // Columnbs TMSR1 reg.
+10:
+#endif
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ lbu t4,PbNumber(t1) // get processor number
+ sll t4,t4,2 // compute address
+ la t0,HalpStartWDTFlag
+ addu t0,t0,t4 //
+ lw t1,0x0(t0)
+ beq zero,t1,12f
+ la t2,HalpSetWDTCount
+ addu t2,t2,t4 //
+ lw t1,0x0(t2)
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x80(zero) // Columnbs reg.
+ li t1,0x00000002
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg.
+ sw zero,0x0(t0)
+12: la t0,HalpStopWDTFlag
+ addu t0,t0,t4 //
+ lw t1,0x0(t0)
+ beq zero,t1,14f
+ li t1,0x00000001
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg.
+ sw zero,0x0(t0)
+14: la t0,HalpSetWDTFlag
+ addu t0,t0,t4 //
+ lw t1,0x0(t0)
+ beq zero,t1,16f
+ li t1,0x00000002
+ sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg.
+ sw zero,0x0(t0)
+16: lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+
+ li t0,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x70
+ sw zero 0x0(t0)
+
+ mfc0 t0,count // get current count value
+ addu t1,zero,3 // set initial count value
+ mtc0 t1,count // set new count register value
+
+ .set at
+ .set reorder
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halr98b/mips/rxdisp.c b/private/ntos/nthals/halr98b/mips/rxdisp.c
new file mode 100644
index 000000000..a006c603e
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxdisp.c
@@ -0,0 +1,61 @@
+//
+// Compile test for stub
+//
+//
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+
+#include "string.h"
+#include <tga.h>
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+{
+ return;
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+{ return;}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+{ return;}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+{return;}
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{return TRUE;}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+{return TRUE;}
diff --git a/private/ntos/nthals/halr98b/mips/rxdspt.c b/private/ntos/nthals/halr98b/mips/rxdspt.c
new file mode 100644
index 000000000..11aa9fc80
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxdspt.c
@@ -0,0 +1,547 @@
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ rxdspt.c
+
+Abstract:
+
+ This module implements the interrupt dispatch routines for R98
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+
+
+#include "halp.h"
+
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PTIMER_DISPATCH)(
+ ULONG TrapFrame
+ );
+
+
+//
+// Dummy Read Registers
+//
+//
+volatile ULONG DUMMYADDRS[]={
+ 0x1c0003f1|KSEG1_BASE, //FDC37C665 config register
+ 0x1c4033c7|KSEG1_BASE, //VGA DAC STATE register
+ 0x1c0003f1|KSEG1_BASE, //FDC37C665 config register
+ 0x1c000023|KSEG1_BASE, //ESC Configuration register
+ 0x1c4033c7|KSEG1_BASE, //VGA DAC STATE register
+ 0x19800610|KSEG1_BASE //Err node register
+
+};
+
+//
+// Following structures will be changed by HalAllProcessorsStarted() on
+// boot up HAL.
+// Because each interrupt connects each processor on boot up HAL.
+// v-masank@microsoft.com
+//
+
+INT_ENTRY HalpIntEntry[R98_CPU_NUM_TYPE][R98B_MAX_CPU][NUMBER_OF_INT]={
+
+{// For R4400 [CPU][INT x] {StartBit, NumberOfBit,Arbitar,Enable,Open}
+
+ { // For CPU #0
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
+ {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
+ },
+ { // For CPU #1
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
+ {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
+ },
+ { // For CPU #2
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
+ {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
+ },
+ { // For CPU #3
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
+ {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
+ }
+
+},
+
+{// For R10000 [CPU][INT x] {StartBit, NumberOfBit,Arbitar,Enable,Open}
+
+
+ {
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
+ {NONE, 0 ,0,(ULONGLONG)0,0} //INT5
+ },
+ {
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
+ {NONE, 0 ,0,(ULONGLONG)0,0} //INT5
+ },
+ {
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
+ {NONE, 0 ,0,(ULONGLONG)0,0} //INT5
+ },
+ {
+ {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
+ {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
+ {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
+ {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
+ {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
+ {NONE, 0 ,0,(ULONGLONG)0,0} //INT5
+ }
+}
+
+};
+
+RESET_REGISTER HalpResetValue[NUMBER_OF_IPR_BIT]={
+ {0,0,0,0}, //Bit 0
+ {PONCE1,PCIINTD,0,DUMMY_A4}, //Bit 1 PCI I/O Slot#8-#10 INTD
+ {PONCE0,PCIINTD,0,DUMMY_A3}, //Bit 2 PCI I/O Slot#4-#7 INTD
+ {0x0,0x0,0,0}, //Bit 3
+
+ {PONCE1,PCIINTC,0,DUMMY_A4}, //Bit 4 PCI I/O Slot#8-#10 INTC
+ {PONCE0,PCIINTC,0,DUMMY_A3}, //Bit 5 PCI I/O Slot#4-#7 INTC
+ {0x0,0x0,0,0} , //Bit 6
+ {PONCE1,PCIINTB,0,DUMMY_A4}, //Bit 7 PCI I/O Slot#8-#10 INTB
+
+ {PONCE0,PCIINTB,0,DUMMY_A3}, //Bit8 PCI I/O Slot#4-#7 INTB
+ {0x0,0x0,0,0}, //Bit9
+ {0x0,0x0,0,0}, //Bit10
+ {0x0,0x0,0,0}, //Bit11
+
+ {0x0,0x0,0,0}, //Bit12
+ {PONCE0,INTSA0,0x0,DUMMY_A3}, //Bit13 EISA Bridge
+ {PONCE1,INTSB0,0x0,DUMMY_A2}, //Bit14 Parallel
+ {PONCE0,INTSB0,0x0,DUMMY_A2}, //Bit15 FDC
+
+ {0x0,0x0,0,0}, //Bit16
+ {0x0,0x0,0,0}, //Bit17
+ {0x0,0x0,0,0}, //Bit18
+ {0x0,0x0,0,0}, //Bit19
+
+ {PONCE1,PCIINTA1,0x0,DUMMY_A4}, //Bit20 PCI I/O Slot#8 INTA
+ {PONCE1,PCIINTA0,0x0,DUMMY_A4}, //Bit21 PCI I/O Slot#9 INTA
+ {PONCE0,PCIINTA3,0x0,DUMMY_A3}, //Bit22 PCI I/O Slot#4 INTA
+ {PONCE0,PCIINTA2,0x0,DUMMY_A3}, //Bit23 PCI I/O Slot#5 INTA
+
+ {PONCE0,PCIINTA1,0,DUMMY_A3}, //Bit24 PCI I/O Slot#6 INTA
+ {PONCE0,PCIINTA0,0,DUMMY_A3}, //Bit25 PCI I/O Slot#7 INTA
+ {0x0,0x0,0,0}, //Bit26
+ {0x0,0x0,0,0}, //Bit27
+
+ {0x0,0x0,0,0}, //Bit28
+ {PONCE1,INTSA0,0x0,DUMMY_A1}, //Bit29 LAN(Ethernet)
+ {PONCE1,PCIINTA3,0x0,DUMMY_A1}, //Bit30 SCSI#1(Narrow)
+ {PONCE1,PCIINTA2,0x0,DUMMY_A1}, //Bit31 SCSI#0(Wide)
+
+ {0x0,0x0,0,0}, //Bit32
+ {0x0,0x0,0,0}, //Bit33
+ {0x0,0x0,0,0}, //Bit34 Tracer ponce Internal
+ {0x0,0x0,0,0}, //Bit35 TLB Undefine Address
+
+ {PONCE1,INTSB1,0,DUMMY_A0}, //Bit36 Mouse
+ {PONCE1,INTSA1,0,DUMMY_A0}, //Bit37 KeyBoard
+ {PONCE0,INTSB1,0,DUMMY_A0}, //Bit38 SIO#1
+ {PONCE0,INTSA1,0,DUMMY_A0}, //Bit39 SIO#0
+
+ { RFU,0,0,0}, //Bit40
+ { RFU,0,0,0}, //Bit41
+ { RFU,0,0,0}, //Bit42
+ { RFU,0,0,0}, //Bit43
+
+// Never Used This is no Device Interrupt.
+
+ { RFU,0,0,0}, //Bit44
+ { RFU,0,0,0}, //Bit45
+ { RFU,0,0,0}, //Bit46
+ { RFU,0,0,0}, //Bit47
+
+ { RFU,0,0,0}, //Bit48 From CPU#3 IPI
+ { RFU,0,0,0}, //Bit49 From CPU#2 IPI
+ { RFU,0,0,0}, //Bit50 From CPU#1 IPI
+ { RFU,0,0,0}, //Bit51 From CPU#0 IPI
+
+ { RFU,0,0,0}, //Bit52
+ { RFU,0,0,0}, //Bit53
+ { RFU,0,0,0}, //Bit54
+ { RFU,0,0,0}, //Bit55
+
+ { RFU,0,0,0}, //Bit56 Interval timer 2 Profile
+ { RFU,0,0,0}, //Bit57 Interval timer 1 Clock
+ { RFU,0,0,0}, //Bit58
+ { RFU,0,0,0}, //Bit59
+
+ { RFU,0,0,0}, //Bit60
+ { RFU,0,0,0}, //Bit61 EIF+MRCINT
+ { RFU,0,0,0}, //Bit62 Memory 1Bit Error
+ { RFU,0,0,0} //Bit63
+
+};
+
+// Thanks very much for pete-san's cooporation.
+// Pete-san write most of following source code.
+// v-masak@microsoft.com
+// 5/17/96
+
+#define HalpFindFirstSetMember(Set) \
+ ((Set & 0xFF) ? HalpFindFirstSet[Set & 0xFF] : \
+ ((Set & 0xFF00) ? HalpFindFirstSet[(Set >> 8) & 0xFF] + 8 : \
+ ((Set & 0xFF0000) ? HalpFindFirstSet[(Set >> 16) & 0xFF] + 16 : \
+ HalpFindFirstSet[(Set >> 24) & 0xff] + 24)))
+
+ULONG HalpFindFirstSet[256] = {
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
+
+PINT_ENTRY HalpIntEntryPointer;
+
+//
+// I use LargeReigester access function for performance
+// v-masank@microsoft.com
+// I used 64 bit shift.
+// v-masank@microsoft.com
+//
+
+VOID
+HalpGeneralDispatch(
+ IN ULONG TrapFrame,
+ IN ULONG IntNo
+ )
+
+/*++
+
+Routine Description:
+
+ This is the general hal interrupt dispatch routine. This services hardware interrupts
+ for range ip[3..8]
+
+
+Arguments:
+
+ IN ULONG TrapFrame - This interrupts trapframe
+ IN ULONG IntNo - The current Interrupt Number range IntNo[0..5] maps to IP[3..8]
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ volatile PULONGLONG Register;
+ ULONGLONG Enable;
+ volatile ULONGLONG IPR;
+ ULONGLONG IprBit;
+ ULONG ULIPR;
+ ULONG CpuNumber;
+ ULONG cnt;
+ ULONG IprBitNumber;
+ ULONG Ponce;
+ UCHAR Data;
+ ULONG StartBit;
+ //
+ // Get CpuNumber
+ //
+ CpuNumber = PCR->Number;
+
+ //
+ // Get Enable table offset
+ //
+ cnt = CpuNumber * NUMBER_OF_INT;
+ //
+ // The interrupt controller on the R98A/B occasionally (rarely) sends
+ // an interrupt to multiple processors. One is the correct processor to
+ // handle the interrupt the other is not. The enable bit
+ // determines if this processor handles this interrupt.
+ //
+ // The table HalpIntEntryPointer gets initalized for the correct processor at boot
+ // (i.e., R98A or R98B).
+
+ Enable=HalpIntEntryPointer[cnt+IntNo].Enable;
+ StartBit = HalpIntEntryPointer[cnt+IntNo].StartBitNo;
+ //
+ // Do until no more interrupts pending
+ //
+ do {
+
+ //
+ // IPR register read
+ //
+ Register = (PULONGLONG)&((COLUMNBS_LCNTL)->IPR);
+ HalpReadLargeRegister(Register,(PULONGLONG)&IPR);
+
+ // MASK
+ //
+ // Determine if this Interrupt enabled for this processor
+ //
+ IPR = IPR & Enable;
+ //
+ // 28 is the largest interrupt bit vector possible on these machines
+ // StartBit is the starting bit position for this interrupt level
+ // Shift the 64 bit interrupt register into a 32 bit field
+ // to make the find first bit set operation easier
+ ULIPR = (ULONG) (IPR >> StartBit);
+ if(ULIPR==0){
+ continue; // No interrupts handled by this processor
+ }
+ do{
+ //
+ // Service all pending interrupts for this ip level
+ //
+ while(ULIPR!=0){
+
+ //
+ // Get Interrupt bit set No. on IPR.
+ //
+ IprBitNumber = HalpFindFirstSetMember(ULIPR) + StartBit;
+ IprBit = 1UI64 << IprBitNumber; // Save this value for clearing INT
+ //
+ // IPR register read
+ // IntNo 0 1 2 3 4 5
+ //
+ // R98A Starting bit pos 0 16 32 56 48 61
+ // R98B Starting bit pos 0 16 56 48 61 NA
+ //
+ // On the R98A/B Each interrupt level can have multiple
+ // concurrentinterrupt sources
+ // (e.g., the read of IPR can have more than 1 bit set
+ //
+ //
+ // Hardware Ip #of possible interrupt sources
+ // R98A R98B
+ // ip[3] 16 16
+ // ip[4] 16 28
+ // ip[5] 12 2
+ // ip[6] 2 4
+ // ip[7] 4 2
+ // ip[8] 2 0
+ //
+ // During initialization the HAL assigns affinity to interrupt sources. So that
+ // the interrupt always gets serviced on the same processor
+
+
+
+ switch (IprBitNumber) {
+
+ case 62:
+ //
+ // call Ecc Error service routine
+ //
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[62+DEVICE_VECTORS])
+ (PCR->InterruptRoutine[62+DEVICE_VECTORS]);
+ //
+ // Clear IPR
+ //
+ Register=(PULONGLONG) &((COLUMNBS_LCNTL)->IPRR);
+ HalpWriteLargeRegister(Register,&IprBit);
+ break;
+ case 61:
+ //
+ // This interrupt gets sent to all processors.
+ // Our friend the HalpDieLock controls exclusive access
+ // protecting the power switch interrupt service routine
+ // and for some reason the read/write of the Power interrupt
+ // register.
+ //
+ //
+ KiAcquireSpinLock(&HalpDieLock);
+ //
+ // It's EIF or MRC INT
+ //
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[61+DEVICE_VECTORS])
+ (PCR->InterruptRoutine[61+DEVICE_VECTORS]);
+
+
+ // HACK HACK HACK !!
+ HalpLocalDeviceReadWrite(MRCINT,&Data,LOCALDEV_OP_READ);
+ if( Data & 0x04){
+ //
+ // At This time If MRCINT Register reported Power Interrupt.
+ // Power Driver failed or happenig ocurred.
+ // if anyone push DUMP KEY. Hal may be system reset.
+ // So Reset Power Interrupt.
+ //
+
+ Data = 0x0;
+ HalpLocalDeviceReadWrite(MRCINT, &Data, LOCALDEV_OP_WRITE);
+ }
+
+ KiReleaseSpinLock(&HalpDieLock);
+
+ //
+ //Clear IPR
+ //
+
+ Register= (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR;
+ HalpWriteLargeRegister(Register,&IprBit);
+ break;
+ case 56:
+ case 57:
+ //
+ // Profile or Clock
+ //
+ ((PTIMER_DISPATCH)PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(TrapFrame);
+ //
+ //Clear IPR
+ //
+
+ Register= (PULONGLONG)&(COLUMNBS_LCNTL)->IPRR;
+ HalpWriteLargeRegister(Register,&IprBit);
+ break;
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+
+ //
+ // Clear IPR
+ //
+
+ Register= (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR;
+ HalpWriteLargeRegister(Register,&IprBit);
+
+ //
+ // IPI interrupts. One for each possible CPU
+ //
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(TrapFrame);
+ break;
+ default:
+ //
+ // Device Interrupt !!
+ //
+ Ponce = HalpResetValue[IprBitNumber].Ponce;
+
+
+ //
+ // 1. Clear INTRG register of PONCE
+ //
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->INTRG,
+ 0x1 << HalpResetValue[IprBitNumber].IntGResetBit);
+
+ //
+ // 2. Call interrupt service routine
+ //
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(
+ PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS]);
+
+ //
+ // 3. Dummy Read execute
+ //
+
+ READ_REGISTER_UCHAR( DUMMYADDRS[HalpResetValue[IprBitNumber].Dummy]);
+ READ_REGISTER_UCHAR( DUMMYADDRS[HalpResetValue[IprBitNumber].Dummy]);
+
+ //
+ // 4. Clear IPR Bit By IPRR Register
+ //
+
+ Register = (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR;
+ HalpWriteLargeRegister(Register,&IprBit);
+
+ //
+ // 5.Clear INTRG register of PONCE
+ //
+
+
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->INTRG,
+ 0x1 << (HalpResetValue[IprBitNumber].IntGResetBit + 21));
+
+ } // End Switch
+ //
+ // Clear the bit in the interrupt register
+ // that we just serviced
+ //
+ ULIPR = ULIPR & ~(1 << (IprBitNumber - StartBit));
+ } // End while servicing current interrupt. Check for more
+ //
+ // Determine if another interrupt pending at the same level before leaving
+ // this dispatch routine. The hardware spec implies that there is
+ // a small window that the interrupt register has bits set before the
+ // cause register. So it suggests checking the interrupt register
+ // before the cause
+ //
+ //
+ // check new interrupt
+ //
+ //
+ // IPR register read
+ //
+ Register = (PULONGLONG)&((COLUMNBS_LCNTL)->IPR);
+ HalpReadLargeRegister(Register,(PULONGLONG)&IPR);
+
+ // MASK
+ //
+ // Determine if this Interrupt enabled for this processor
+ //
+
+ IPR = IPR & Enable;
+ ULIPR = (ULONG) (IPR >> StartBit);
+ }while(ULIPR!=0); // End do-while
+ //
+ // Check cause register to see if an interrupt pending for the current level
+ //
+ } while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+IntNo));
+}
+
diff --git a/private/ntos/nthals/halr98b/mips/rxecc.c b/private/ntos/nthals/halr98b/mips/rxecc.c
new file mode 100644
index 000000000..677fe877e
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxecc.c
@@ -0,0 +1,791 @@
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ rxecc.c
+
+Abstract:
+
+ This module implements the ECC 1bit/Multi bit Error interrupt service routine for R98B
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ *
+ * NEW CODE '95.11/17 K.Kitagaki
+ *
+ */
+
+#include "halp.h"
+#include "esmnvram.h"
+#include "rxesm.h"
+#include "bugcodes.h"
+#include "stdio.h"
+
+#if defined(ECC_DBG)
+int
+TmpInitNvram(void);
+int
+TmpInitNvram2(void);
+#endif
+
+//
+// define offset.
+//
+#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr)
+#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest)
+#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr)
+#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest)
+
+#define ESM_MM_SYUKUTAI_TOPOST_OFFSET 0x1d08
+
+
+#define TIME_STAMP_SIZE 14
+
+//
+// define value
+//
+#define NVRAM_VALID 3
+#define ECC_LOG_VALID_FLG 1
+
+#define STRING_BUFFER_SIZE 512
+
+#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10
+
+#define ECC_1BIT_ENABLE_MASK 0x0000000a
+#define ECC_1BIT_DISABLE_MASK 0xfffffff5
+
+//
+// Define global variable. This variable use in display string into nvram.
+//
+USHORT ErrBufferLatest;
+USHORT ErrBufferArea;
+USHORT ErrBufferStart;
+USHORT ErrBufferEnd;
+USHORT ErrBufferCurrent;
+UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE];
+
+LONG HalpECC1bitDisableFlag=1;
+LONG HalpECC1bitDisableTime=0;
+ULONG HalpECC1bitScfrBuffer=0;
+
+VOID
+HalpEcc1Logger(
+ IN ULONG Node
+);
+VOID
+HalpEcc2Logger(
+ IN ULONG Node
+);
+//
+// Define macro
+//
+
+#define GET_TIME(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));\
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\
+ 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\
+ HalQueryRealTimeClock( &timeBuffer ); \
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));\
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\
+ 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\
+ sprintf( (Buffer), \
+ "%04d%02d%02d%02d%02d%02d", \
+ timeBuffer.Year, \
+ timeBuffer.Month, \
+ timeBuffer.Day, \
+ timeBuffer.Hour, \
+ timeBuffer.Minute, \
+ timeBuffer.Second \
+ ); \
+}
+
+#define DONT_NOTIFY_ECC1BIT { \
+ ULONG buffer; \
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ \
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ); \
+ buffer |= ECC_1BIT_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, buffer); \
+ } \
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ \
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ); \
+ buffer |= ECC_1BIT_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, buffer); \
+ } \
+}
+
+#define NOTIFY_ECC1BIT { \
+ ULONG buffer; \
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ \
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ); \
+ buffer &= ECC_1BIT_DISABLE_MASK; \
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, buffer); \
+ } \
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ \
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ); \
+ buffer &= ECC_1BIT_DISABLE_MASK; \
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, buffer); \
+ } \
+}
+
+#if 1 // suported
+
+VOID
+HalpEcc1bitError(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine check ecc 1bit error and error log put in NVRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG magSet;
+ USHORT infoOffset;
+ USHORT writeOffset;
+ ULONG sts1Buffer;
+ ULONG sdlmBuffer;
+ ULONG dsrgBuffer;
+ ULONG buffer;
+ ULONG i;
+ ULONG errAddr;
+ UCHAR dataBuf[36];
+ UCHAR infoBuf[24];
+ UCHAR tempBuf[24];
+
+ ULONG Ponce0AllError;
+ ULONG MagellanAdec;
+ ULONG Magellan0AllError = 0;
+ ULONG Magellan1AllError = 0;
+ ULONG simmMIN;
+ ULONG MemoryBlock;
+ volatile PULONG Registerp;
+
+#if defined(ECC_DBG)
+ DbgPrint("ECC 1Bit Error IN !!!\n");
+#endif
+
+// HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+ Ponce0AllError = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->AERR);
+
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){
+ Magellan0AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->AERR );
+ }
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){
+ Magellan1AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->AERR );
+ }
+
+ //
+ // Check ECC 1bit error
+ //
+
+ if ( Ponce0AllError & 0x00000200 ){
+ if ( Magellan0AllError & 0x0000000a ){
+ magSet = 0;
+#if defined(ECC_DBG)
+ DbgPrint("Magellan#%x:AERR = %x\n",magSet,Magellan0AllError);
+#endif
+ } else if ( Magellan1AllError & 0x0000000a ){
+ magSet = 1;
+#if defined(ECC_DBG)
+ DbgPrint("Magellan#%x:AERR = %x\n",magSet,Magellan1AllError);
+#endif
+ } else {
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:OTHER ERR 1\n");
+#endif
+ return;
+ }
+ } else {
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:OTHER ERR 2\n");
+#endif
+ return;
+ }
+
+ //
+ // read diagnosis registers.
+ //
+
+ sts1Buffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->STS1 );
+ dsrgBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->DSRG );
+ sdlmBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDLM );
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan#%x:STS1 = %x\n",magSet,sts1Buffer);
+#endif
+
+ Registerp = (PULONG)&MAGELLAN_X_CNTL(magSet)->ADEC0;
+ MagellanAdec = READ_REGISTER_ULONG( Registerp + ((sts1Buffer>>30)<<1) );
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ADEC%x = %x\n",(sts1Buffer>>30),MagellanAdec);
+#endif
+
+ simmMIN = (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MIN ) << 24;
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 1 ) {
+ MemoryBlock = 0x00000000;
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 2 ) {
+ MemoryBlock = 0x20000000;
+ } else {
+ return;
+ }
+
+ //
+ // HW Logging
+ //
+ HalpEcc1Logger( 8 + magSet );
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:MemoryBlock = %x\n",MemoryBlock);
+
+// TmpInitNvram();
+#endif
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+
+// case MAGELLAN_ECC_1BIT_ERROR:
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:Nvram Save Routine IN !!!\n");
+#endif
+ infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET;
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ DONT_NOTIFY_ECC1BIT;
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ECC 1bit Disable\n");
+#endif
+
+ WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->ERRST, 0x0a );
+ WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDCR, 0x00 );
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ERRST, SDCR CLEAR\n");
+#endif
+
+ do {
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(magSet)->AERR );
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:AERR = %x\n", buffer);
+// DbgBreakPoint();
+#endif
+ } while ( (buffer & 0x0000000a) != 0 );
+
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRST, 0x00000200 );
+
+ Registerp = (PULONG)&(COLUMNBS_LCNTL)->IPRR;
+ WRITE_REGISTER_ULONG( Registerp++, 0x40000000 );
+#if defined(ECC_DBG)
+ DbgPrint("Columbus:IPRR CLEAR\n");
+#endif
+
+ //
+ // Check New error or Old error.
+ //
+
+ //
+ // Error Address Generate
+ //
+
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 0 ) { // B-MODE
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 24) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 14);
+#if defined(ECC_DBG)
+ DbgPrint("ERROR_ADDR = %x\n",errAddr);
+#endif
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 26) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 14) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 25);
+ }
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 1 ) { // M-MODE
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 25) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)( magSet << 6 )) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15);
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 27) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)( magSet << 6 )) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 15) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 16) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 26);
+ }
+ }
+
+
+ HalpReadAndWritePhysicalAddr( errAddr );
+
+ for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) {
+ HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)->size_rec * i
+ +((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr),
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ if ( (errAddr == ((pECC1_ERR_REC)dataBuf)->err_address) &&
+ ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) {
+#if defined(ECC_DBG)
+ DbgPrint("for loop break\n");
+#endif
+ break;
+ }
+ }
+
+ if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+#if defined(ECC_DBG)
+ DbgPrint("goto next1bit P-1\n");
+#endif
+ goto next1bit;
+ }
+
+ //
+ // wait 20 us.
+ //
+
+ KeStallExecutionProcessor(20);
+
+ //
+ // Enable ECC 1bit error.
+ //
+
+ NOTIFY_ECC1BIT;
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ECC 1bit Enable\n");
+#endif
+
+ //
+ // Check ECC 1bit error.
+ //
+
+ HalpReadPhysicalAddr( errAddr );
+
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(magSet)->AERR );
+
+ if( (buffer & 0x0000000a) == 0 ) {
+#if defined(ECC_DBG)
+ DbgPrint("goto next1bit P-2\n");
+#endif
+ goto next1bit;
+ }
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:AERR = %x\n", buffer);
+#endif
+
+ //
+ // ECC 1bit error occur again.
+ //
+
+ ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC1_ERR_REC)dataBuf)->err_address = errAddr;
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC1_ERR_REC)dataBuf)->syndrome = sdlmBuffer;
+
+ ((pECC1_ERR_REC)dataBuf)->specified_group =
+ (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->ARE + magSet * 4);
+
+ ((pECC1_ERR_REC)dataBuf)->specified_simm =
+ (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->BANK );
+
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+
+next1bit:
+
+// if(returnValue == SIC_ECC_1BIT_ERROR) {
+
+ DONT_NOTIFY_ECC1BIT;
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ECC 1bit Disable\n");
+#endif
+
+ WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->ERRST, 0x0a );
+
+ do {
+ buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(magSet)->AERR );
+ } while ( (buffer & 0x0000000a) != 0 );
+
+ WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDCR, 0x00 );
+
+ do {
+ sts1Buffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->STS1 );
+ sdlmBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDLM );
+ } while ( ((sdlmBuffer) != 0) && ((sts1Buffer & 0x0a000000) == 0) );
+
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRST, 0x00000200 );
+
+ Registerp = (PULONG)&(COLUMNBS_LCNTL)->IPRR;
+ WRITE_REGISTER_ULONG( Registerp++, 0x40000000 );
+
+#if defined(ECC_DBG)
+ DbgPrint("HalpECC1bitDisableFlag = %x\n",HalpECC1bitDisableFlag);
+#endif
+ if(HalpECC1bitDisableFlag > 0) {
+ HalpECC1bitDisableFlag--;
+ if(HalpECC1bitDisableFlag > 0) {
+ NOTIFY_ECC1BIT;
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ECC 1bit Enable\n");
+#endif
+ }
+ else {
+ HalpECC1bitDisableTime = ECC_1BIT_ERROR_DISABLE_TIME;
+ HalpECC1bitDisableFlag = 0;
+#if defined(ECC_DBG)
+ DbgPrint("HalpECC1bitDisableTime = %x\n",HalpECC1bitDisableTime);
+#endif
+ }
+ }
+
+ return;
+}
+
+#endif // don't suported yet
+
+VOID
+HalpEccMultiBitError(
+ IN ULONG MagellanAllError,
+ IN UCHAR magSet
+ )
+
+/*++
+
+Routine Description:
+
+ This routine check ecc multi bit error and error log put in NVRAM.
+
+Arguments:
+
+ MagellanAllError - Magellan#0/#1 AERR register.
+ magSet - Magellan Number(#0 or #1).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT infoOffset;
+ USHORT writeOffset;
+ ULONG sts1Buffer;
+ ULONG sdlmBuffer;
+ ULONG dsrgBuffer;
+ ULONG errAddr;
+ UCHAR dataBuf[36];
+ UCHAR infoBuf[24];
+ UCHAR tempBuf[24];
+ ULONG simmMIN;
+ ULONG MemoryBlock;
+ ULONG MagellanAdec;
+ ULONG syukuBuffer;
+ volatile PULONG Registerp;
+
+#if defined(ECC_DBG)
+ DbgPrint("ECC Multi Bit Error IN !!!\n");
+#endif
+
+// HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+
+ //
+ // read diagnosis registers.
+ //
+
+ sts1Buffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->STS1 );
+ dsrgBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->DSRG );
+ sdlmBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDLM );
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan#%x:AERR = %x\n",magSet,MagellanAllError);
+ DbgPrint("Magellan#%x:STS1 = %x\n",magSet,sts1Buffer);
+#endif
+
+ Registerp = (PULONG)&MAGELLAN_X_CNTL(magSet)->ADEC0;
+ MagellanAdec = READ_REGISTER_ULONG( Registerp + ((sts1Buffer>>30)<<1) );
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:ADEC%x = %x\n",(sts1Buffer>>30),MagellanAdec);
+#endif
+
+ simmMIN = (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MIN ) << 24;
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 1 ) {
+ MemoryBlock = 0x00000000;
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 2 ) {
+ MemoryBlock = 0x20000000;
+ } else {
+ return;
+ }
+
+ //
+ // HW Logging
+ //
+ HalpEcc2Logger( 8 + magSet );
+
+#if defined(ECC_DBG)
+ DbgPrint("Magellan:MemoryBlock = %x\n",MemoryBlock);
+
+// TmpInitNvram2();
+#endif
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ infoOffset = ECC_2BIT_ERROR_LOG_INFO_OFFSET;
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ //
+ // Error address generate
+ //
+
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 0 ) { // B-MODE
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 24) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 14);
+#if defined(ECC_DBG)
+ DbgPrint("ERROR_ADDR = %x\n",errAddr);
+#endif
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 26) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 14) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 25);
+ }
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 1 ) { // M-MODE
+ if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 25) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)( magSet << 6 )) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15);
+ } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) {
+ errAddr = MemoryBlock + simmMIN +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 27) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) +
+ ((ULONG)( magSet << 6 )) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 15) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 16) +
+ ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 26);
+ }
+ }
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC2_ERR_REC)dataBuf)->err_address = errAddr;
+ ((pECC2_ERR_REC)dataBuf)->syndrome = sdlmBuffer;
+
+ ((pECC2_ERR_REC)dataBuf)->specified_group =
+ (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->ARE + magSet * 4);
+
+ ((pECC2_ERR_REC)dataBuf)->specified_simm =
+ (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->BANK );
+
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC2_ERR_REC),
+ (PVOID)dataBuf);
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+
+ //
+ // MM sykutai to POST
+ //
+ syukuBuffer = 0x0f << ((((pECC2_ERR_REC)dataBuf)->specified_group) << 2 );
+ HalNvramWrite( ESM_MM_SYUKUTAI_TOPOST_OFFSET,
+ 4,
+ (PVOID)&syukuBuffer);
+
+ }
+ return;
+}
+
+#if 0 // for test mode
+
+int
+TmpInitNvram(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0x77;
+ for(i=768; i<768+25*16; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 4, (PUCHAR)&i);
+
+
+#if defined(ECC_DBG)
+ DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_STATE_FLG_OFFSET);
+ DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_MAGIC_NO_OFFSET);
+#endif
+
+ //
+ // Make 1bit err log info
+ //
+
+ ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768;
+ ((pECC1_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC1_ERR_AREA_INFO)buf)->num_rec=16;
+ ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768;
+
+ ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0;
+
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf);
+
+ return(0);
+}
+
+int
+TmpInitNvram2(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0x77;
+ for(i=768+400; i<768+400+25*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 4, (PUCHAR)&i);
+
+
+#if defined(ECC_DBG)
+ DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_STATE_FLG_OFFSET);
+ DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_MAGIC_NO_OFFSET);
+#endif
+
+ //
+ // Make 2bit err log info
+ //
+
+ ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400;
+ ((pECC2_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC2_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400;
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ return(0);
+}
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/rxeif.c b/private/ntos/nthals/halr98b/mips/rxeif.c
new file mode 100644
index 000000000..224715021
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxeif.c
@@ -0,0 +1,694 @@
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ rxeif.c
+
+Abstract:
+
+ This module implements the Eif interrupt service routine for R98B
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#include "bugcodes.h"
+#include "eisa.h"
+#include "stdio.h"
+
+extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU];
+
+//
+// define Columnbs buffer index
+//
+
+typedef enum _COLUMNBS_BUFFER_INDEX {
+ COLUMNBS_AERR,
+ COLUMNBS_FERR,
+ COLUMNBS_ERRMK,
+ COLUMNBS_ERRI,
+ COLUMNBS_ERRST,
+ COLUMNBS_NMIM,
+ COLUMNBS_EAHI,
+ COLUMNBS_EALI,
+ COLUMNBS_AERR2,
+ COLUMNBS_FERR2,
+ COLUMNBS_ERRMK2,
+ COLUMNBS_ERRI2,
+ COLUMNBS_ERRST2,
+ COLUMNBS_NMIM2,
+ COLUMNBS_STSR,
+ COLUMNBS_ERRNOD,
+ COLUMNBS_MAX_REGISTER
+}COLUMNBS_BUFFER_INDEX,*PCOLUMNBS_BUFFER_INDEX;
+
+//
+// define MAGELLAN buffer index
+//
+typedef enum _MAGELLAN_BUFFER_INDEX {
+ MAGELLAN_AERR,
+ MAGELLAN_FERR,
+ MAGELLAN_ERRM,
+ MAGELLAN_ERRI,
+ MAGELLAN_ERRST,
+ MAGELLAN_EIFM,
+ MAGELLAN_EAHI,
+ MAGELLAN_EALI,
+ MAGELLAN_CKE0,
+ MAGELLAN_SECT,
+ MAGELLAN_STS1,
+ MAGELLAN_DATM,
+ MAGELLAN_DSRG,
+ MAGELLAN_MAX_REGISTER
+}MAGELLAN_BUFFER_INDEX,*PMAGELLAN_BUFFER_INDEX;
+
+
+//
+// define PONCE buffer index
+//
+typedef enum _PONCE_BUFFER_INDEX {
+ PONCE_AERR,
+ PONCE_FERR,
+ PONCE_ERRM,
+ PONCE_ERRI,
+ PONCE_ERRST,
+ PONCE_EAHI,
+ PONCE_EALI,
+ PONCE_PAERR,
+ PONCE_PFERR,
+ PONCE_PERRM,
+ PONCE_PERRI,
+ PONCE_PERST,
+ PONCE_PTOL,
+ PONCE_MAX_REGISTER
+}PONCE_BUFFER_INDEX,*PPONCE_BUFFER_INDEX;
+
+//
+// System Diagnotics Registers of R98
+//
+ULONG r98bDiagColumnbs[R98B_MAX_CPU][COLUMNBS_MAX_REGISTER];
+ULONG r98bDiagMagellan[R98B_MAX_MAGELLAN][MAGELLAN_MAX_REGISTER];
+ULONG r98bDiagPonce[R98B_MAX_PONCE][PONCE_MAX_REGISTER];
+ULONG r98bDiagEisaNmi;
+
+
+volatile ULONG HalpNMIFlag=0;
+ULONG HalpNMIHappend[R98B_MAX_CPU];
+ULONG HalpNmiSvp[R98B_MAX_CPU];
+ULONG HalpDumpFlag=0;
+
+#if DBG
+ULONG HalpNMISecond[R98B_MAX_CPU];
+ULONG HalpResetCount[R98B_MAX_CPU];
+
+#endif
+
+
+BOOLEAN
+HalpHandleEif(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine manage the eif interrupt
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR messageBuffer[256];
+ UCHAR charBuffer;
+ ULONG counter;
+
+ UCHAR EisaPort;
+ ULONG port;
+
+ ULONG displaycount;
+ ULONG CpuNo;
+ ULONG CpuNumber;
+ PCOLUMNBUS_REGISTER ColumnbusRegister;
+ ULONG i;
+ ULONG ERRNOD;
+ ULONG Cregisters;
+ volatile ULONG CpuCount=0;
+ ULONG PhysicalCpuNumber;
+ ULONG data1,data2,data3,data4;
+
+ PULONG Vp;
+ ULONG Value[2];
+ ULONG Magellan0AllError = 0;
+ ULONG Magellan1AllError = 0;
+ UCHAR Data;
+
+ // I am ..
+ CpuNo=(PCR->Prcb)->Number;
+ CpuCount=**((PULONG *)(&KeNumberProcessors));
+
+// DbgBreakPoint(); //for snes
+
+ //
+ // Get Node. What happend NODE X!!.
+ //
+ PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNo];
+
+
+ ERRNOD = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD );
+ r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_ERRNOD] = ERRNOD;
+
+ //
+ // First Check is MRC. This is Power SW Interrupt!!.
+ //
+ HalpLocalDeviceReadWrite(MRCINT,&Data,LOCALDEV_OP_READ);
+ if( Data & 0x04){
+ Data = 0x0;
+ //
+ // Reset is MRC Interrupt debug Only.
+ //
+ // HalpLocalDeviceReadWrite(MRCINT, &Data, LOCALDEV_OP_WRITE);
+
+ return FALSE;
+
+ }else
+
+ //
+ // Is This Alarm EIF?
+ //
+ if( ERRNOD & ERRNOD_ALARM ) {
+ //
+ // Second time DUMMY Read.
+ //
+ READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD );
+ //
+ // Do Hwlogging
+ //
+ HalpEifReturnLog();
+
+ //
+ // We Reset Node Register. Now Register had Locked.
+ // If We Reset Node Register. Other CPU which EIF Broadcasted was
+ // Never aknowrege EIF Ocurred. So Quick Return.
+ //
+ //WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD,ERRNOD_ALARM );
+
+ return FALSE;
+
+ }
+
+ if(( (ERRNOD & ERRNOD_ALLNODE) == 0) && (HalpNMIFlag == 0) ){
+
+ // DbgBreakPoint();
+ // Any Node Reported EIF.
+ //
+ return FALSE;
+ }
+
+
+ //
+ //
+ // We Will die.
+ //
+
+ if(HalpNMIFlag == 0){
+ for (i=0;i< R98B_MAX_CPU;i++)
+ HalpNMIHappend[i] = 1;
+
+ }
+
+
+ //
+ // CHeck ECC Multi Bit Error
+ //
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){
+ Magellan0AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->AERR );
+ }
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){
+ Magellan1AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->AERR );
+ }
+
+ if ( Magellan0AllError & 0x00000005 ){
+ HalpEccMultiBitError( Magellan0AllError, 0 );
+ } else if ( Magellan1AllError & 0x00000005 ){
+ HalpEccMultiBitError( Magellan1AllError, 1 );
+ }
+
+ // cpu #0 cpu #1 cpu #2 cpu #3
+ // r98bDiagbuffers[]
+ // save H/W register Context of COLUMNBS.
+ //
+
+ for(CpuNumber = 0; CpuNumber < CpuCount; CpuNumber++){
+ PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNumber];
+ ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(4+PhysicalCpuNumber)->AERR;
+ for(Cregisters = 0; Cregisters < COLUMNBS_ERRNOD;Cregisters++){
+ r98bDiagColumnbs[PhysicalCpuNumber][Cregisters] =
+ READ_REGISTER_ULONG( (PULONG)ColumnbusRegister );
+ ColumnbusRegister++;
+ }
+
+ }
+
+ //
+ // Save H/W register Context of Magellan.
+ //
+ for(i = 0; i < R98B_MAX_MAGELLAN ; i++){
+ if( !(HalpPhysicalNode & (CNFG_CONNECT4_MAGELLAN0 >> i))){
+ r98bDiagMagellan[i][MAGELLAN_AERR] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->AERR );
+ r98bDiagMagellan[i][MAGELLAN_FERR] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->FERR );
+ r98bDiagMagellan[i][MAGELLAN_ERRM] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->ERRM );
+ r98bDiagMagellan[i][MAGELLAN_ERRI] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->ERRI );
+// r98bDiagMagellan[i][MAGELLAN_ERRST] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->ERRST);
+
+// r98bDiagMagellan[i][MAGELLAN_EIFM] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->EIFM );
+ r98bDiagMagellan[i][MAGELLAN_EAHI] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->EAHI );
+ r98bDiagMagellan[i][MAGELLAN_EALI] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->EALI );
+
+ r98bDiagMagellan[i][MAGELLAN_CKE0] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->CKE0 );
+ r98bDiagMagellan[i][MAGELLAN_SECT] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->SECT );
+
+ r98bDiagMagellan[i][MAGELLAN_STS1] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->STS1 );
+ r98bDiagMagellan[i][MAGELLAN_DATM] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->DATM );
+ r98bDiagMagellan[i][MAGELLAN_DSRG] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->DSRG );
+ }
+ }
+
+ //
+ // Save H/W register Context of Ponce.
+ //
+ for(i = 0; i < HalpNumberOfPonce; i++){
+ r98bDiagPonce[i][PONCE_AERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->AERR);
+ r98bDiagPonce[i][PONCE_FERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->FERR);
+ r98bDiagPonce[i][PONCE_ERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRM);
+ r98bDiagPonce[i][PONCE_ERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRI);
+ //
+ // THis Register is write only
+ //
+ //r98bDiagPonce[i][PONCE_ERRST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRST);
+ r98bDiagPonce[i][PONCE_EAHI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EAHI);
+ r98bDiagPonce[i][PONCE_EALI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EALI);
+ r98bDiagPonce[i][PONCE_PAERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PAERR);
+ r98bDiagPonce[i][PONCE_PFERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PFERR);
+ r98bDiagPonce[i][PONCE_PERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRM);
+ r98bDiagPonce[i][PONCE_PERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRI);
+ //
+ // This Register is Read Only.....
+ //
+// r98bDiagPonce[i][PONCE_PERST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERST);
+ r98bDiagPonce[i][PONCE_PTOL] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PTOL);
+ }
+
+ //
+ // Display EISA Nmi status.
+ //
+
+ charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus);
+ r98bDiagEisaNmi = charBuffer << 24;
+
+ charBuffer = READ_REGISTER_UCHAR(
+ &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl
+ );
+ r98bDiagEisaNmi |= charBuffer << 16;
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ charBuffer = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((charBuffer & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+ charBuffer = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (charBuffer & 0x2) {
+ r98bDiagEisaNmi |= EisaPort;
+ }
+ }
+ }
+
+
+ //
+ // Display COLUMNBS Register
+ //
+ for(CpuNumber = 0; CpuNumber < CpuCount; CpuNumber++){
+ displaycount = 0;
+ PhysicalCpuNumber=HalpLogicalCPU2PhysicalCPU[CpuNumber];
+ sprintf( (char *)messageBuffer, "\nMPU Controller %1d Registers:\n",PhysicalCpuNumber );
+ HalDisplayString( (char *)messageBuffer );
+
+ for(Cregisters = 0; Cregisters < COLUMNBS_MAX_REGISTER;Cregisters++){
+
+ sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagColumnbs[PhysicalCpuNumber][Cregisters] );
+
+ HalDisplayString( (char *)messageBuffer );
+ if( (displaycount % 7) == 6 ) {
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+ }
+ displaycount++;
+ }
+ }
+
+
+ //
+ // Display MAGELLAN Register
+ //
+ for(i = 0; i < R98B_MAX_MAGELLAN ; i++){
+ displaycount=0;
+ if( !(HalpPhysicalNode & (CNFG_CONNECT4_MAGELLAN0 >> i))){
+ sprintf( (char *)messageBuffer, "\nMEMORY Controller %1d Registers:\n",i );
+ HalDisplayString( (char *)messageBuffer );
+
+ for(Cregisters = 0; Cregisters < MAGELLAN_MAX_REGISTER;Cregisters++){
+ sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagMagellan[i][Cregisters] );
+ HalDisplayString( (char *)messageBuffer );
+ if( (displaycount % 7) == 6 ) {
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+ }
+ displaycount++;
+ }
+
+ }else{
+ sprintf( (char *)messageBuffer, "\nMEMORY Controller %1d Not Present.",i );
+ HalDisplayString( (char *)messageBuffer );
+ }
+ }
+
+ //
+ // Display PONCE Register
+ //
+ for(i = 0; i < HalpNumberOfPonce; i++){
+ displaycount=0;
+ sprintf( (char *)messageBuffer, "\nPCI Controller %1d Registers:\n",i );
+ HalDisplayString( (char *)messageBuffer );
+
+ for(Cregisters = 0; Cregisters < PONCE_MAX_REGISTER;Cregisters++){
+ sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagPonce[i][Cregisters] );
+ HalDisplayString( (char *)messageBuffer );
+ if( (displaycount % 7) == 6 ) {
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+ }
+ displaycount++;
+ }
+ }
+
+
+
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR;
+ Value[0]= READ_REGISTER_ULONG( Vp++);
+ Value[1]= READ_REGISTER_ULONG( Vp);
+
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR;
+ WRITE_REGISTER_ULONG( Vp++,0xffffffff);
+ WRITE_REGISTER_ULONG( Vp, 0xffffffff);
+
+ PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNo];
+
+// if( ((HalpNMIFlag & 0xffff) == NMIR_EXNMI) && !HalpNmiSvp[PhysicalCpuNumber] ) {
+ if( ((HalpNMIFlag & 0xffff) == NMIR_EXNMI) && HalpDumpFlag ) {
+ HalpChangePanicFlag( 16, 0x05, 0x10);
+ } else {
+ HalpChangePanicFlag( 16, 0x01, 0x10);
+ }
+
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR;
+ WRITE_REGISTER_ULONG( Vp++,Value[0]);
+ WRITE_REGISTER_ULONG( Vp, Value[1]);
+
+ //
+ if( HalpNMIFlag != 0 ){
+ //
+ // From Nmi. Nmi is supported by Cause EIF at nmi occured!!.
+ //
+ HalDisplayString("\nNMI: ");
+
+ switch( HalpNMIFlag & 0xffff){
+ case NMIR_EXNMI:
+// if(HalpNmiSvp[PhysicalCpuNumber])
+ if(HalpDumpFlag==0)
+ HalDisplayString("SVP issued NMI");
+ else
+ HalDisplayString("Dump Switch Pressed");
+ break;
+ case NMIR_WDTOV:
+ HalDisplayString("Time out of Watch-dog Timer occured");
+ break;
+ case NMIR_CLBNMI:
+ HalDisplayString("MPU Controller Internal Error");
+ break;
+ case NMIR_UNANMI:
+ HalDisplayString("Invalid Access");
+ break;
+ default:
+ HalDisplayString("[Other ?]");
+ }
+
+ data1 = r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_AERR];
+ data2 = r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_AERR2];
+ data3 = HalpNMIFlag;
+ data4 = r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_NMIM];
+
+ HalpNmiLog();
+
+ }else {
+ //
+ // Acutually EIF Interrupt Occured!
+ //
+
+ if( ( Magellan0AllError & 0x00000005 ) ||
+ ( Magellan1AllError & 0x00000005 ) ){
+ HalDisplayString("\nEIF: Uncorrectable Error in Memory");
+ }
+
+ HalDisplayString("\nEIF Reported: ");
+ sprintf( (char *)messageBuffer, "Exe CPU=No.%1d NodeR = %x ",
+ CpuNo, r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_ERRNOD]);
+ HalDisplayString( (char *)messageBuffer );
+
+ switch( r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_ERRNOD] & 0xf3cc){
+ case ERRNOD_NODE0 :
+ HalDisplayString("[ From PCI Controller 0]");
+ data1 = r98bDiagPonce[0][PONCE_AERR];
+ data2 = r98bDiagPonce[0][PONCE_FERR];
+ data3 = r98bDiagPonce[0][PONCE_PAERR];
+ data4 = r98bDiagPonce[0][PONCE_PFERR];
+ break;
+ case ERRNOD_NODE1 :
+ HalDisplayString("[ From PCI Controller 1]");
+ data1 = r98bDiagPonce[1][PONCE_AERR];
+ data2 = r98bDiagPonce[1][PONCE_FERR];
+ data3 = r98bDiagPonce[1][PONCE_PAERR];
+ data4 = r98bDiagPonce[1][PONCE_PFERR];
+ break;
+ case ERRNOD_NODE4 :
+ HalDisplayString("[ From MPU Controller 0]");
+ data1 = r98bDiagColumnbs[0][COLUMNBS_AERR];
+ data2 = r98bDiagColumnbs[0][COLUMNBS_AERR2];
+ data3 = r98bDiagColumnbs[0][COLUMNBS_EAHI];
+ data4 = r98bDiagColumnbs[0][COLUMNBS_EALI];
+ break;
+ case ERRNOD_NODE5 :
+ HalDisplayString("[ From MPU Controller 1]");
+ data1 = r98bDiagColumnbs[1][COLUMNBS_AERR];
+ data2 = r98bDiagColumnbs[1][COLUMNBS_AERR2];
+ data3 = r98bDiagColumnbs[1][COLUMNBS_EAHI];
+ data4 = r98bDiagColumnbs[1][COLUMNBS_EALI];
+ break;
+ case ERRNOD_NODE6 :
+ HalDisplayString("[ From MPU Controller 2]");
+ data1 = r98bDiagColumnbs[2][COLUMNBS_AERR];
+ data2 = r98bDiagColumnbs[2][COLUMNBS_AERR2];
+ data3 = r98bDiagColumnbs[2][COLUMNBS_EAHI];
+ data4 = r98bDiagColumnbs[2][COLUMNBS_EALI];
+ break;
+ case ERRNOD_NODE7 :
+ HalDisplayString("[ From MPU Controller 3]");
+ data1 = r98bDiagColumnbs[3][COLUMNBS_AERR];
+ data2 = r98bDiagColumnbs[3][COLUMNBS_AERR2];
+ data3 = r98bDiagColumnbs[3][COLUMNBS_EAHI];
+ data4 = r98bDiagColumnbs[3][COLUMNBS_EALI];
+ break;
+ case ERRNOD_NODE8 :
+ HalDisplayString("[ From MEMORY Controller 0]");
+ data1 = r98bDiagMagellan[0][MAGELLAN_AERR];
+ data2 = r98bDiagMagellan[0][MAGELLAN_FERR];
+ data3 = r98bDiagMagellan[0][MAGELLAN_EAHI];
+ data4 = r98bDiagMagellan[0][MAGELLAN_EALI];
+ break;
+ case ERRNOD_NODE9 :
+ HalDisplayString("[ From MEMORY Controller 1]");
+ data1 = r98bDiagMagellan[1][MAGELLAN_AERR];
+ data2 = r98bDiagMagellan[1][MAGELLAN_FERR];
+ data3 = r98bDiagMagellan[1][MAGELLAN_EAHI];
+ data4 = r98bDiagMagellan[1][MAGELLAN_EALI];
+ break;
+ case ERRNOD_EISANMI:
+ HalDisplayString("[ From EISA]");
+ data1 = r98bDiagEisaNmi;
+ data2 = 0;
+ data3 = 0;
+ data4 = 0;
+ break;
+//
+// This case never happend.
+//
+ case ERRNOD_ALARM :
+ HalDisplayString("[ From ALARM]");
+ data1 = 0;
+ data2 = 0;
+ data3 = 0;
+ data4 = 0;
+ break;
+
+
+ default:
+ HalDisplayString("[Other ?]");
+ data1 = 0;
+ data2 = 0;
+ data3 = 0;
+ data4 = 0;
+ }
+ // HwLog kusano
+ HalpEifLog();
+
+ }
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,
+ data1,
+ data2,
+ data3,
+ data4
+ );
+
+#if 1 // WORK_AROUND_BBM for compiler
+ return FALSE;
+#endif
+}
+
+
+BOOLEAN
+HalpIoTlbLimitOver(
+ PKINTERRUPT Interrupt
+ )
+{
+ KIRQL irql;
+ ULONG data1,data2,data3,data4;
+ ULONG i;
+ ULONG displaycount;
+ UCHAR messageBuffer[256];
+ ULONG Cregisters;
+
+ KeRaiseIrql(HIGH_LEVEL, &irql);
+ KiAcquireSpinLock(&HalpDieLock);
+
+ //
+ // Save H/W register Context of Ponce.
+ //
+ for(i = 0; i < HalpNumberOfPonce; i++){
+ r98bDiagPonce[i][PONCE_AERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->AERR);
+ r98bDiagPonce[i][PONCE_FERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->FERR);
+ r98bDiagPonce[i][PONCE_ERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRM);
+ r98bDiagPonce[i][PONCE_ERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRI);
+ //
+ // THis Register is write only
+ //
+ //r98bDiagPonce[i][PONCE_ERRST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRST);
+ r98bDiagPonce[i][PONCE_EAHI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EAHI);
+ r98bDiagPonce[i][PONCE_EALI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EALI);
+ r98bDiagPonce[i][PONCE_PAERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PAERR);
+ r98bDiagPonce[i][PONCE_PFERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PFERR);
+ r98bDiagPonce[i][PONCE_PERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRM);
+ r98bDiagPonce[i][PONCE_PERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRI);
+ //
+ // This Register is Read Only.....
+ //
+// r98bDiagPonce[i][PONCE_PERST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERST);
+ r98bDiagPonce[i][PONCE_PTOL] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PTOL);
+ }
+
+ //
+ // Display PONCE Register
+ //
+ for(i = 0; i < HalpNumberOfPonce; i++){
+ displaycount=0;
+ sprintf( (char *)messageBuffer, "\nPCI Controller %1d Registers:\n",i );
+ HalDisplayString( (char *)messageBuffer );
+
+ for(Cregisters = 0; Cregisters < PONCE_MAX_REGISTER;Cregisters++){
+ sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagPonce[i][Cregisters] );
+ HalDisplayString( (char *)messageBuffer );
+ if( (displaycount % 7) == 6 ) {
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+ }
+ displaycount++;
+ }
+ }
+
+ if( r98bDiagPonce[1][PONCE_AERR] & (PONCE_XERR_TUAER | PONCE_XERR_TIVER) ){
+ data1 = r98bDiagPonce[1][PONCE_AERR];
+ data2 = r98bDiagPonce[1][PONCE_FERR];
+ data3 = r98bDiagPonce[1][PONCE_PAERR];
+ data4 = r98bDiagPonce[1][PONCE_PFERR];
+ i = 1;
+ } else {
+ data1 = r98bDiagPonce[0][PONCE_AERR];
+ data2 = r98bDiagPonce[0][PONCE_FERR];
+ data3 = r98bDiagPonce[0][PONCE_PAERR];
+ data4 = r98bDiagPonce[0][PONCE_PFERR];
+ i = 0;
+ }
+
+ HalpChangePanicFlag( 16, 0x01, 0x10);
+
+ if ( data1 & PONCE_XERR_TUAER ){
+ HalDisplayString("\nI/O TLB Logical Address Limit Over\n");
+ } else {
+ HalDisplayString("\nI/O TLB Invalid\n");
+ }
+
+ sprintf( (char *)messageBuffer, " [ From PCI Controller %d]\n",i );
+ HalDisplayString( (char *)messageBuffer );
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,
+ data1,
+ data2,
+ data3,
+ data4
+ );
+
+ KiReleaseSpinLock (&HalpDieLock);
+ KeLowerIrql (irql);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halr98b/mips/rxesm.c b/private/ntos/nthals/halr98b/mips/rxesm.c
new file mode 100644
index 000000000..d10a659a6
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxesm.c
@@ -0,0 +1,761 @@
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ rxesm.c
+
+Abstract:
+
+ This module implements the ESM service routine for R98B
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "rxesm.h"
+#include "esmnvram.h"
+#include "bugcodes.h"
+#include "stdio.h"
+#include "halp.h"
+
+
+//
+// define offset.
+//
+#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+
+#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr)
+#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest)
+
+#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description)
+
+//
+// Define global variable. This variable use in display string into nvram.
+//
+ULONG HalpNvramValid=FALSE;
+ULONG CallCountOfInitDisplay=0;
+USHORT ErrBufferLatest;
+USHORT ErrBufferArea;
+USHORT ErrBufferStart;
+USHORT ErrBufferEnd;
+USHORT ErrBufferCurrent;
+ULONG HalpPanicFlg=0;
+UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE];
+ULONG HalpNvramStringBufferCounter=0;
+
+UCHAR KernelPanicMessage[]="*** STOP: 0x";
+
+extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU];
+extern ULONG HalpSvpEisaSlot;
+extern ULONG HalpSvpWindow0;
+extern ULONG HalpSvpWindow1;
+extern ULONG HalpSvpWindow2;
+extern ULONG HalpSvpGlobal;
+extern ULONG HalpSvpAlive ;
+
+#define GET_TIME(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));\
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\
+ 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\
+ HalQueryRealTimeClock( &timeBuffer ); \
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));\
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\
+ 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\
+ sprintf( (Buffer), \
+ "%04d%02d%02d%02d%02d%02d", \
+ timeBuffer.Year, \
+ timeBuffer.Month, \
+ timeBuffer.Day, \
+ timeBuffer.Hour, \
+ timeBuffer.Minute, \
+ timeBuffer.Second \
+ ); \
+}
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Write Byte Count
+ PVOID Buffer // Pointer Of Buffer Write to NVRAM
+){
+ // Write into NVRAM
+#if defined(DBG1)
+ DbgPrint("NVRAM write start\n");
+#endif
+ return HalpNvramReadWrite(Offset,Count,Buffer,1);
+#if defined(DBG1)
+ DbgPrint("NVRAM write end\n");
+#endif
+}
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Read Byte Count
+ PVOID Buffer // Pointer Of Buffer Read From NVRAM
+){
+ // Read From NVRAM
+#if defined(DBG1)
+ DbgPrint("NVRAM read start\n");
+#endif
+ return HalpNvramReadWrite(Offset,Count,Buffer,0);
+#if defined(DBG1)
+ DbgPrint("NVRAM read end\n");
+#endif
+}
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset, // Read/Write offset of ESM NVRAM
+ ULONG Count, // Read/Write Byte Count
+ PVOID Buffer, // read/Write Pointer
+ ULONG Write // Operation
+){
+
+ ENTRYLO SavedPte[2];
+ KIRQL OldIrql;
+ ULONG i;
+ //
+ // Check is addr . So decrement 1
+ //
+ if(
+ Offset >=0 &&
+ Count >=0 &&
+ NVRAM_ESM_BASE+Offset <=NVRAM_ESM_END &&
+ NVRAM_ESM_BASE+Offset+Count-1 <=NVRAM_ESM_END
+
+ ){
+
+ if(Write){
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ for(i=0;i<Count;i++){
+ WRITE_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i),((PUCHAR)Buffer)[i]);
+ }
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ }else{
+ for(i=0;i<Count;i++){
+ ((PUCHAR)Buffer)[i] =READ_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i));
+
+ }
+ }
+
+ return TRUE;
+
+ }else{
+
+ //
+ // It is no ESM NVRAM Erea.
+ return FALSE;
+ }
+
+}
+
+
+#if 0
+
+int
+TmpInitNvram(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0x00;
+ for(i=0; i<8*1024; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 4, (PUCHAR)&i);
+
+
+#if DBG
+ DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_STATE_FLG_OFFSET);
+ DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_MAGIC_NO_OFFSET);
+#endif
+
+ //
+ // Make system err log info
+ //
+
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280;
+
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ buf);
+
+ return(0);
+}
+
+#endif
+
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is initialize variable of use when write display data in
+ HalDisplayString into NVRAM.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SYSTEM_ERR_AREA_INFO infoBuf;
+ UCHAR recordFlg;
+ UCHAR buf[8];
+ UCHAR buf2[8];
+
+ CallCountOfInitDisplay++;
+ if(CallCountOfInitDisplay == 1){
+
+#if 0 //test only
+ TmpInitNvram();
+#endif
+ //
+ // Check NVRAM status
+ //
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 );
+
+ if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){
+ HalpNvramValid=FALSE;
+ return;
+ }
+
+ HalpNvramValid=TRUE;
+
+ //
+ // Get log area infomation.
+ //
+
+ HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ &infoBuf);
+
+ ErrBufferLatest = infoBuf.offset_latest;
+
+ HalNvramRead( infoBuf.offset_latest, 1, &recordFlg);
+
+ //
+ // Check current record flg.
+ //
+
+ if( (recordFlg & 0x01) == 1 ) {
+ infoBuf.offset_latest += infoBuf.size_rec;
+ if( infoBuf.offset_latest >=
+ infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){
+ infoBuf.offset_latest = infoBuf.offset_systemerr;
+ }
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &infoBuf.offset_latest);
+ }
+
+ //
+ // initialize variable. this value use log area access.
+ //
+
+ ErrBufferArea = infoBuf.offset_latest;
+ ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE;
+ ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1;
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // status flg set.
+ //
+
+ HalpPanicFlg = 0;
+
+ recordFlg = 0x11;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ //
+ // buffer initialize.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else {
+
+ //
+ // start Panic log.
+ //
+
+ HalpChangePanicFlag( 1, 1, 0);
+ }
+}
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ )
+{
+ UCHAR buf[32];
+
+ //
+ // Set time stamp on initialize display.
+ //
+
+ if(HalpNvramValid == TRUE) {
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+ }
+}
+
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ )
+{
+ UCHAR recordFlg;
+
+ if(HalpNvramValid == TRUE) {
+ recordFlg = 0;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest );
+ }
+}
+
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ )
+{
+ UCHAR recordFlg;
+ UCHAR buf[32];
+// For WDT STOP and NVRAM set
+ volatile ULONG CpuCount=0;
+ ULONG PhysicalCpuNumber;
+ ULONG CpuNumber;
+ PUCHAR FwNvram;
+ UCHAR Bootflag;
+ PCOLUMNBUS_REGISTER ColumnbusRegister;
+ CpuCount=**((PULONG *)(&KeNumberProcessors));
+
+ if((NewPanicFlg>HalpPanicFlg)&(NewPanicFlg>0)){
+ for(CpuNumber = 0; CpuNumber < CpuCount; CpuNumber++){
+ PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNumber];
+ ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(4+PhysicalCpuNumber)->WDTCR;
+ WRITE_REGISTER_ULONG( (PULONG)ColumnbusRegister,0x00000001);
+ }
+ (ULONG)FwNvram=0xbf081c00;
+ Bootflag=(*FwNvram);
+ *FwNvram=Bootflag|0x10;
+ // SVP EIF MASK
+ if(HalpSvpAlive){
+ WRITE_PORT_UCHAR(HalpSvpGlobal + 0x49,0x00 );
+ }
+ }
+
+
+
+ if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) {
+ return;
+ }
+
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &ErrBufferArea);
+
+ //
+ // initialize currernt buffer address
+ //
+
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // set panic flag
+ //
+
+ HalNvramRead( ErrBufferArea, 1, &recordFlg );
+ recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+
+ //
+ // set new flag of panic level
+ //
+
+ HalpPanicFlg = NewPanicFlg;
+
+ //
+ // initialize log buffer.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+}
+
+
+// S002 vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ )
+{
+ if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) {
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character;
+ }
+}
+
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ )
+{
+ ULONG i;
+
+ //
+ // Initialize buffer
+ //
+
+ for(i=0; i<STRING_BUFFER_SIZE; i++) {
+ HalpNvramStringBuffer[i] = 0;
+ }
+
+ HalpNvramStringBufferCounter=0;
+
+ //
+ // set string position
+ //
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Column;
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Row;
+}
+
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // if data size is zero, when return
+ //
+
+ if( HalpNvramStringBufferCounter <= 2 ) {
+ return;
+ }
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]='\0';
+
+ //
+ // check panic message
+ //
+
+ for( count=0; ; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != HalpNvramStringBuffer[count+2] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for( count=2; ; count++) {
+ if( HalpNvramStringBuffer[count] == '\0' ){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 2 < ErrBufferEnd ) {
+ HalNvramWrite( ErrBufferCurrent, count, HalpNvramStringBuffer );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( (count + 2 > ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count );
+ }
+ ErrBufferCurrent++;
+ if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+
+
+
+VOID
+HalpLocalDeviceReadWrite(
+ IN ULONG Offset,
+ IN OUT PUCHAR Data,
+ IN ULONG ReadOp
+)
+/*++
+
+Routine Description:
+
+ This routine is Access Local Device
+
+Arguments:
+ Offset Register Offset of Local Device
+ Data Pointer of read or write data
+ ReadOp 1 is Read.
+
+Return Value:
+
+ None
+
+--*/
+{
+ ULONG stsr;
+ KIRQL oldirql;
+#if DBG0
+ DbgPrint("LOCAL: 1 \n");
+#endif
+ // NMI and EIF mask
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR,0x08080000) ;
+ KeRaiseIrql(HIGH_LEVEL, &oldirql);
+
+ //
+ // Get H/W Semaphore
+ //
+ while (READ_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL) & LBCTL_SEMAPHORE )
+ ;
+
+#if DBG0
+ DbgPrint("LOCAL: 2\n");
+#endif
+
+ //
+ // Set register Offset Hi Byte
+ //
+ WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBADH, (UCHAR)(Offset >> 8) );
+
+#if DBG0
+ DbgPrint("LOCAL: 3\n");
+#endif
+
+
+ //
+ // Set register Offset Lo Byte
+ //
+ WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBADL, (UCHAR)(Offset & 0xFF));
+
+#if DBG0
+ DbgPrint("LOCAL: 4\n");
+#endif
+
+ if(ReadOp){
+ //
+ // LBCTL Device read command Set.
+ //
+ WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL, LBCTL_CMD|LBCTL_READ);
+
+ }else{
+ //
+ // Write data Set
+ //
+ WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBDT,*Data);
+ //
+ // LBCTL Device Write command Set.
+ //
+ WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL, LBCTL_CMD);
+
+ }
+#if DBG0
+ DbgPrint("LOCAL: 5\n");
+#endif
+
+ //
+ // pooling LBCTL cmmand bit
+ //
+ while (READ_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL) & LBCTL_CMD )
+ ;
+
+#if DBG0
+ DbgPrint("LOCAL: 6\n");
+#endif
+
+
+ //
+ // If Read Operation Data Get
+ //
+ if(ReadOp)
+ *Data = READ_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBDT);
+
+#if DBG0
+ DbgPrint("LOCAL: 7\n");
+#endif
+
+ //
+ // Finish!!
+ //
+ WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL,LBCTL_SWE );
+
+ // EIF NMI enable
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR,0x00080000) ;
+ KeLowerIrql(oldirql);
+
+}
+
+VOID
+HalLocalDeviceReadWrite(
+ IN ULONG Offset,
+ IN OUT PUCHAR Data,
+ IN ULONG ReadOp
+)
+/*++
+
+Routine Description:
+
+ This routine is Access Local Device for Driver
+
+Arguments:
+ Offset Register Offset of Local Device
+ Data Pointer of read or write data
+ ReadOp 1 is Read.
+
+Return Value:
+
+ None
+
+--*/
+{
+ HalpLocalDeviceReadWrite(Offset,Data,ReadOp);
+}
+
+
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+)
+/*++
+
+Routine Description:
+
+ This routine is change Mode bit on MRC Controller.
+
+Arguments:
+
+ Mode - Parameter for setting Mode bit on MRC
+
+Return Value:
+
+ None
+
+--*/
+{
+
+
+ UCHAR ModeNow;
+ //
+ // Read MRC Mode Register
+ //
+ HalpLocalDeviceReadWrite(MRCMODE,&ModeNow,LOCALDEV_OP_READ);
+
+#if DBG0
+ DbgPrint("MRC Read : 1 = 0x%x\n",(UCHAR)ModeNow);
+#endif
+
+ //
+ // Write MRC Mode bit
+ //
+
+ ModeNow = ((ModeNow & 0x02) | (Mode << 7));
+#if DBG0
+ DbgPrint("MRC WRITE : 2 = 0x%x\n",(UCHAR)ModeNow);
+#endif
+
+ HalpLocalDeviceReadWrite(MRCMODE,&ModeNow,LOCALDEV_OP_WRITE);
+
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98b/mips/rxesm.h b/private/ntos/nthals/halr98b/mips/rxesm.h
new file mode 100644
index 000000000..7fc976409
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxesm.h
@@ -0,0 +1,84 @@
+/*
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ rxesm.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the r98B system.
+
+Author:
+
+
+
+Revision History:
+
+--*/
+
+#ifndef _RXESM_
+#define _RXESM_
+
+#include "halp.h"
+
+#define NVRAM_ESM_PHYSICAL_BASE 0x1f09e000 // See rxnvr.h
+#define NVRAM_ESM_PHYSICAL_END 0x1f09ffff // See rxnvr.h
+#define NVRAM_ESM_BASE (NVRAM_ESM_PHYSICAL_BASE + KSEG1_BASE)
+#define NVRAM_ESM_END (NVRAM_ESM_PHYSICAL_END + KSEG1_BASE)
+
+
+
+//
+// define value
+//
+#define NVRAM_VALID 3
+//#define NVRAM_MAGIC 0xff651026
+#define NVRAM_MAGIC 0xff951115
+#define STRING_BUFFER_SIZE 512
+#define TIME_STAMP_SIZE 14
+
+
+VOID
+HalpMrcModeChange(
+ UCHAR Mode
+ );
+
+//
+// Define STS1 register
+//
+typedef struct _STS1_REGISTER {
+ ULONG COL0_1 : 2;
+ ULONG COL2_9 : 8;
+ ULONG COL10 : 1;
+ ULONG ROW0_9 : 10;
+ ULONG ROW10 : 1;
+ ULONG RF : 1;
+ ULONG RW : 1;
+ ULONG MBE1 : 1;
+ ULONG SBE1 : 1;
+ ULONG MBE0 : 1;
+ ULONG SBE0 : 1;
+ ULONG SIDE : 1;
+ ULONG BANK : 1;
+ ULONG ARE : 2;
+} STS1_REGISTER, *PSTS1_REGISTER;
+
+//
+// Define ADEC register
+//
+typedef struct _ADEC_REGISTER {
+ ULONG MIN : 7;
+ ULONG NOUSE1 : 1;
+ ULONG MAX : 7;
+ ULONG NOUSE2 : 9;
+ ULONG SIMM_1 : 1;
+ ULONG SIMM_2 : 1;
+ ULONG NOUSE3 : 1;
+ ULONG MAG : 1;
+ ULONG BLOCK : 3;
+ ULONG NOUSE4 : 1;
+} ADEC_REGISTER, *PADEC_REGISTER;
+
+#endif // _RXESM_
diff --git a/private/ntos/nthals/halr98b/mips/rxhalp.h b/private/ntos/nthals/halr98b/mips/rxhalp.h
new file mode 100644
index 000000000..d5b2f0e71
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxhalp.h
@@ -0,0 +1,212 @@
+/*
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ rxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ R98[a-z]* specific interfaces, defines and structures.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+#ifndef _RXHALP_
+#define _RXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+extern ULONG HalpMachineCpu;
+extern ULONG HalpNumberOfPonce;
+extern ULONG HalpPhysicalNode;
+extern UCHAR HalpIntLevelofIpr[R98_CPU_NUM_TYPE][NUMBER_OF_IPR_BIT];
+extern ULONG HalpStartPciBusNumberPonce[];
+extern ULONG HalpCirrusAlive;
+
+typedef struct _INT_ENTRY {
+ ULONG StartBitNo;
+ ULONG NumberOfBit;
+ ULONG Arbitar;
+ ULONGLONG Enable; // 1: Enable 0: Open
+ ULONGLONG Open; // This Int Group Open Bit
+}INT_ENTRY,*PINT_ENTRY;
+
+extern INT_ENTRY HalpIntEntry[R98_CPU_NUM_TYPE][R98B_MAX_CPU][NUMBER_OF_INT];
+
+//
+// This is PONCE Interrupt relationship
+//
+
+typedef struct _RESET_REGISTER {
+ UCHAR Ponce; //Connet Interrupt Ponce
+ UCHAR IntGResetBit; //ResetValue Bit Define
+ UCHAR Cpu; //Connet CPU Initialize at inittime.
+ UCHAR Dummy; //Dummy Read Addr Index
+}RESET_REGISTER,*PRESET_REGISTER;
+
+extern RESET_REGISTER HalpResetValue[64];
+
+
+#define NONE (0xFFFFFFFF)
+#define RFU ((UCHAR)(0xFF))
+
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+} ADAPTER_OBJECT;
+
+
+// I/O TLB Entry Format(PTE Format)
+// 63 33 32 12 0
+// +---------+-------+----+-+
+// |MBZ | PFN |MBZ |V|
+// +---------+-------+----+-+
+// Valid : 1 Valid
+// : 0 InValid
+// Define translation table entry structure.
+//
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ ULONG PageFrame;
+ ULONG Fill;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+#define PAGE_TABLE_ENTRY_VALID 0x1
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpInterruptFromPonce(
+ IN ULONG Vector,
+ IN ULONG Enable
+ );
+
+BOOLEAN
+HalpConnectIoInterrupt(
+ IN ULONG NumCpu
+ );
+
+
+VOID
+HalpSetupNmiHandler(
+ VOID
+ );
+
+VOID
+HalpCpuCheck(
+ VOID
+ );
+
+VOID
+HalpSVPSlotDetect(
+ VOID
+);
+
+
+VOID
+HalpBusErrorLog(
+ VOID
+ );
+
+VOID
+HalpEifLog(
+ VOID
+ );
+
+VOID
+HalpEifReturnLog(
+ VOID
+ );
+
+VOID
+HalpNmiLog(
+ VOID
+ );
+
+VOID
+HalpHwLogger(
+ IN ULONG Type,
+ IN ULONG Context
+ );
+
+#endif // _RXHALP_
diff --git a/private/ntos/nthals/halr98b/mips/rxhwlog.c b/private/ntos/nthals/halr98b/mips/rxhwlog.c
new file mode 100644
index 000000000..d3308e395
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxhwlog.c
@@ -0,0 +1,1409 @@
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ rxhwlog.c
+
+Abstract:
+
+ This module implements the ESM service routine for R98B
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "rxhwlog.h"
+#include "eisa.h"
+#include "stdio.h"
+
+UCHAR HwLogBuff[HWLOG_RECORD_SIZE+HWLOG_REV1_RECORD_SIZE+1024];
+extern ULONG HalpLogicalCPU2PhysicalCPU[];
+extern ULONG HalpNmiSvp[];
+
+#define NMI_BUFFER_SIZE 64
+
+ULONG HalpNMIBuf[R98B_MAX_CPU][NMI_BUFFER_SIZE];
+
+#define GET_TIME2(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));\
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\
+ 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\
+ HalQueryRealTimeClock( &timeBuffer ); \
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));\
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\
+ 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\
+ Header->YY = (timeBuffer.Year % 100) + ((timeBuffer.Year % 100) / 10) * 6; \
+ Header->MM = timeBuffer.Month+ (timeBuffer.Month/ 10) * 6; \
+ Header->DD = timeBuffer.Day + (timeBuffer.Day / 10) * 6; \
+ Header->hh = timeBuffer.Hour + (timeBuffer.Hour / 10) * 6; \
+ Header->mm = timeBuffer.Minute+(timeBuffer.Minute/10) * 6; \
+ Header->ss = timeBuffer.Second+(timeBuffer.Second/10) * 6; \
+}
+
+
+//
+// Interrupt set register 2 ( 0xz447 )
+//
+#define SVP_INTR2_SET_VIT3SET 0x0040
+#define SVP_WINDOW0_OFFSET 0x0000 // Window 0 start offset ( EISA I/O Space)
+#define SVP_WINDOW1_OFFSET 0x0800 // Window 1 start offset ( EISA I/O Space)
+#define SVP_WINDOW2_OFFSET 0x0c00 // Window 2 start offset ( EISA I/O Space)
+#define SVP_GLOBAL_OFFSET 0x0400 // Global Window start offset ( EISA I/O Space)
+//
+// EISA Slot is 1 orign. so When HalpSvpEisaSLot is 0 SPV no slot in.
+//
+ULONG HalpSvpEisaSlot = 0;
+ULONG HalpSvpWindow0;
+ULONG HalpSvpWindow1;
+ULONG HalpSvpWindow2;
+ULONG HalpSvpGlobal;
+ULONG HalpSvpAlive = FALSE;
+ULONG HalpBusySvpFlag=0;
+// For Cache
+
+// For Cache
+VOID
+HalpCacheErrorLog(
+ IN ULONG cpu,
+ IN PVOID pbuf,
+ IN ULONG errorcode
+);
+ULONG HalpCacheErrorStack[8196];
+UCHAR HalpCacheErrorHwLog[HWLOG_RECORD_SIZE+HWLOG_REV1_RECORD_SIZE];
+#define HEADER_CACHE 0x06
+
+//
+// SVP ISA Board Detect. This Borad is ISA but EISA Configration!!.
+// So Search EISA Configration.
+//
+VOID
+HalpSVPSlotDetect(
+ VOID
+)
+{
+ ULONG SlotNumber;
+ ULONG DataLength;
+ ULONG CompressedId;
+ UCHAR Buf[ sizeof(CM_EISA_SLOT_INFORMATION) + sizeof(CM_EISA_FUNCTION_INFORMATION)];
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ PCM_EISA_FUNCTION_INFORMATION funcInformation;
+ ULONG i;
+ UCHAR Data;
+
+ //
+ // SVP H/W Alive by F/W.
+ //
+ HalpLocalDeviceReadWrite(ALMSNS_HIGH,&Data,LOCALDEV_OP_READ);
+ //
+ // detected By F/W .
+ //
+ if( Data & 0x1){
+ //
+ //F/W diag is fail !!
+ //
+ return;
+ }
+
+
+ for(SlotNumber =1 ;SlotNumber <= EISA_MAX_DEVICE;SlotNumber++){
+ for (i =0;i<sizeof(CM_EISA_SLOT_INFORMATION) + sizeof(CM_EISA_FUNCTION_INFORMATION);i++)
+ Buf[i]=0;
+
+ DataLength = HalGetBusData(
+ EisaConfiguration,
+ 0, //EISA Bus is 0
+ SlotNumber,
+ Buf,
+ sizeof(CM_EISA_SLOT_INFORMATION) +
+ sizeof(CM_EISA_FUNCTION_INFORMATION)
+ );
+ SlotInformation=( PCM_EISA_SLOT_INFORMATION)Buf;
+ funcInformation=( PCM_EISA_FUNCTION_INFORMATION)&Buf[sizeof(CM_EISA_SLOT_INFORMATION)];
+ //
+ // 0x018ca338 == > NEC SVP (38 a3 8c 01)
+ //
+ //
+ if(((SlotInformation->CompressedId) &0xffffff)== 0x8ca338){
+ HalpSvpEisaSlot = SlotNumber;
+ HalpSvpWindow0 = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_WINDOW0_OFFSET);
+ HalpSvpWindow1 = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_WINDOW1_OFFSET);
+ HalpSvpWindow2 = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_WINDOW2_OFFSET);
+ HalpSvpGlobal = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_GLOBAL_OFFSET);
+ break;
+ }
+#if DBG
+
+ DbgPrint("EISA Slot #%x DataLen= 0x%x\n",SlotNumber, DataLength );
+ DbgPrint("EISA Slot #%x CompressedId = 0x%x\n",SlotNumber, SlotInformation->CompressedId);
+ DbgPrint("EISA Slot #%x RetunCode = 0x%x\n",SlotNumber, SlotInformation->ReturnCode);
+ DbgPrint("EISA Slot #%x Checksum = 0x%x\n",SlotNumber, SlotInformation->Checksum);
+
+ DbgPrint("EISA Slot #%x FCompressedId = 0x%x\n",SlotNumber, funcInformation->CompressedId);
+ DbgPrint("EISA Slot #%x FMinorRevision= 0x%x\n",SlotNumber, funcInformation->MinorRevision);
+ DbgPrint("EISA Slot #%x FMajorRevision= 0x%x\n",SlotNumber, funcInformation->MajorRevision);
+ DbgPrint("EISA Slot #%x FFunctionFlags= 0x%x\n",SlotNumber, funcInformation->FunctionFlags);
+
+ DbgPrint("EISA Slot #%x FTypeString = %s\n",SlotNumber, funcInformation->TypeString);
+#endif
+ }
+ //
+ // Eisa Configration Ok.
+ //
+ if( HalpSvpEisaSlot){
+ HalpSvpAlive = TRUE;
+#if DBG
+ DbgPrint("SVP ALIVE\n" );
+#endif
+ }
+}
+
+VOID
+HalSvpIntToSvp(
+ VOID
+ )
+{
+
+ UCHAR Status;
+ UCHAR LockCode;
+ UCHAR LockCode2;
+ ULONG i;
+
+ ULONG RetryCount =10;
+ UCHAR Code = 0x7;
+
+ KiAcquireSpinLock(&HalpLogLock);
+
+
+
+ Status = READ_PORT_UCHAR( HalpSvpWindow2 + 0xc1 );
+ KeStallExecutionProcessor( 1000 ); // wait 1msec
+
+ for( i = 0; (i < RetryCount ) && (Status != 0); i++ ){
+ KeStallExecutionProcessor( 1000 ); // wait 1msec
+ Status = READ_PORT_UCHAR( HalpSvpWindow2 + 0xc1 );
+ }
+
+ if( Status != 0x00 ){
+ // Flag on for dump
+ HalpBusySvpFlag = 1;
+ return;
+ }
+
+
+ LockCode = READ_PORT_UCHAR( HalpSvpGlobal + 0x58 );
+ WRITE_PORT_UCHAR(HalpSvpGlobal + 0x58,0xff );
+ LockCode2= READ_PORT_UCHAR( HalpSvpGlobal + 0x50 );
+ WRITE_PORT_UCHAR(HalpSvpGlobal + 0x50,0xff );
+
+ WRITE_PORT_UCHAR( HalpSvpWindow2 + 0xc1, Code );
+
+ WRITE_PORT_UCHAR( HalpSvpGlobal + 0x58,LockCode );
+ WRITE_PORT_UCHAR( HalpSvpGlobal + 0x50,LockCode2 );
+
+ WRITE_PORT_UCHAR( HalpSvpGlobal + 0x47,SVP_INTR2_SET_VIT3SET);
+
+ KiReleaseSpinLock(&HalpLogLock);
+
+ return;
+}
+
+
+
+
+VOID
+NVRAM_HWLOG_WRITE(
+ IN PVOID Buff,
+ IN ULONG StartBlockNo,
+ IN ULONG NumBlock
+){
+
+ ULONG i,j;
+
+
+ for(i=0;i<NumBlock;i++){
+ for(j=0;j<HWLOG_RECORD_SIZE;j++){
+ //
+ // Byte write only.
+ //
+ WRITE_REGISTER_UCHAR(
+ (PUCHAR)(NVRAM_HWLOG_BASE+
+// (PUCHAR)(NVRAM_HWLOG_BASE+HWLOG_RECORD_SIZE +
+ StartBlockNo * HWLOG_RECORD_SIZE +
+ i*HWLOG_RECORD_SIZE+
+ j),
+
+ ((PUCHAR)Buff)[i*HWLOG_RECORD_SIZE + j]
+ );
+ }
+ }
+
+
+}
+
+
+
+VOID
+NVRAM_HWLOG_READ(
+ IN PVOID Buff,
+ IN ULONG StartBlockNo,
+ IN ULONG NumBlock
+){
+
+ ULONG i,j;
+
+
+ for(i=0;i<NumBlock;i++){
+ for(j=0;j<HWLOG_RECORD_SIZE;j++){
+ //
+ // read
+ //
+ ((PUCHAR)Buff)[i*HWLOG_RECORD_SIZE + j]= READ_REGISTER_UCHAR( (PUCHAR)(NVRAM_HWLOG_BASE+ StartBlockNo * HWLOG_RECORD_SIZE + i*HWLOG_RECORD_SIZE+ j) );
+ }
+ }
+
+
+}
+
+VOID
+HalpHwLogBuffInit(
+){
+ ULONG i;
+ for(i=0;i< HWLOG_RECORD_SIZE+HWLOG_REV1_RECORD_SIZE;i++)
+ HwLogBuff[i] = 0x0;
+}
+
+VOID
+HalpHwLogHeaderInit(
+
+){
+ PHW_LOG_AREA_HEADER Header;
+ PUCHAR Sump;
+ ULONG i;
+ //
+ // Genelic Buffer Initialization to all 0x0
+ //
+ HalpHwLogBuffInit();
+
+ Header = (PHW_LOG_AREA_HEADER)HwLogBuff;
+ //
+ // Build This record header
+ //
+ Header->Ident = (USHORT)HEADER_IDENT_REV0;
+ //
+ // Time Field is BCD
+ //
+ GET_TIME2(&(Header->YY));
+ Header->RCT = HEADER_PANIC;
+ Header->ST1 = 0;
+ Header->ST2 = 0;
+ Header->ST3 = 0;
+ Header->DTLEN = HWLOG_REV1_RECORD_SIZE;
+ //
+ // Endian Convert to Big
+ //
+ Header->DTLEN = (
+ ((Header->DTLEN & 0xFF) << 8) |
+ ((Header->DTLEN & 0xFF00) >> 8)
+ );
+ Header->FRU1[0]=Header->FRU1[1] = 0;
+ Header->FRU2[0]=Header->FRU2[1] = 0;
+
+ //Make Check Sum
+ Header->CSM = 0;
+ Sump = (PUCHAR) HwLogBuff;
+ for (i= 0; i<= 14; i++){
+ Header->CSM += *(Sump+i);
+ }
+ Header->CSM = (UCHAR)( Header->CSM & 0xff);
+ // Header Build Conpleate!!
+
+
+}
+
+BOOLEAN
+HalpSetHwLog(
+ IN PVOID Buff,
+ IN ULONG NumBlock
+){
+
+ PHWLOG_CONTROL_INFO Control;
+ HW_LOG_AREA_HEADER Header;
+ ULONG StartBlockNo;
+ ULONG AllFree;
+ ULONG RemainFree;
+ ULONG i;
+ UCHAR InBuff[sizeof(HWLOG_CONTROL_INFO)];
+ PUCHAR Sump;
+ ULONG Csm;
+ ULONG FreeLen,Len;
+
+#if 0 //test only
+ //
+ // Get Control area
+ //
+ for (i = 0;i < sizeof(HWLOG_CONTROL_INFO);i++)
+ InBuff[i] = 0;
+ NVRAM_HWLOG_WRITE((PUCHAR)InBuff, 0x0,1);
+
+#endif
+
+
+ //
+ // Get Control area
+ //
+ for (i = 0;i < sizeof(HWLOG_CONTROL_INFO);i++)
+ InBuff[i] = READ_REGISTER_UCHAR( (PUCHAR)(NVRAM_HWLOG_BASE+i));
+
+ Control= ( PHWLOG_CONTROL_INFO)InBuff;
+ //Convert Endian to littl
+ Control->BASE = ( ((Control->BASE & 0xFF00) >> 8) | ((Control->BASE & 0x00FF) << 8) );
+ Control->NREC = ( ((Control->NREC & 0xFF00) >> 8) | ((Control->NREC & 0x00FF) << 8) );
+ Control->TBASE= ( ((Control->TBASE& 0xFF00) >> 8) | ((Control->TBASE& 0x00FF) << 8) );
+ Control->TN = ( ((Control->TN & 0xFF00) >> 8) | ((Control->TN & 0x00FF) << 8) );
+ Control->RBASE= ( ((Control->RBASE& 0xFF00) >> 8) | ((Control->RBASE& 0x00FF) << 8) );
+ //
+ // Write Log Number
+ // This data Big endian
+ //
+ ((PHW_LOG_AREA_HEADER)Buff)->LGN = Control->LOGNUM;
+ Csm = 0;
+ Sump = (PUCHAR) Buff;
+ for (i= 0; i<= 14; i++){
+ Csm += (ULONG)(*(Sump+i));
+ }
+// Csm = ((PHW_LOG_AREA_HEADER)Buff)->CSM + Control->LOGNUM;
+ ((PHW_LOG_AREA_HEADER)Buff)->CSM = (UCHAR)(Csm & 0xFF);
+ Control->RN = ( ((Control->RN & 0xFF00) >> 8) | ((Control->RN & 0x00FF) << 8) );
+
+ //
+ // Log Field Invalid
+ //
+#if 1
+ if ( (Control->STAT & 0x01) == 0 ){
+ // If SVP Board alive So write port of svp.
+ // IF EIF Occured SVP Board required reset port.
+ //
+
+ if(HalpSvpAlive)
+ HalSvpIntToSvp();
+ return FALSE;
+ }
+#endif
+
+ if ((Control->BASE < 0) || (NVRAM_HWLOG_MAX_ENTRY <= Control->BASE ) ||
+ (Control->NREC < 0) || (NVRAM_HWLOG_MAX_ENTRY < Control->NREC ) ||
+ (Control->RBASE < 0) || (NVRAM_HWLOG_MAX_ENTRY <= Control->RBASE) ||
+ (Control->RN < 0) || (NVRAM_HWLOG_MAX_ENTRY < Control->RN ))
+ {
+ // If SVP Board alive So write port of svp.
+ // IF EIF Occured SVP Board required reset port.
+ //
+
+ if(HalpSvpAlive)
+ HalSvpIntToSvp();
+ return FALSE;
+ }
+
+ StartBlockNo = Control->RBASE+Control->RN;
+
+ if(StartBlockNo > NVRAM_HWLOG_MAX_ENTRY)
+ StartBlockNo -= NVRAM_HWLOG_MAX_ENTRY;
+
+ //
+ // We Can't Logging. as if used log area wrieted back disk.
+ //
+ if(
+ ( (NVRAM_HWLOG_MAX_ENTRY - Control->NREC) < NumBlock) ||
+ ( (NVRAM_HWLOG_MAX_ENTRY - Control->NREC == 0))
+ ){
+ // If SVP Board alive So write port of svp.
+ // IF EIF Occured SVP Board required reset port.
+ //
+
+ if(HalpSvpAlive)
+ HalSvpIntToSvp();
+
+ return FALSE;
+ }
+
+ //
+ // as if used log area writed back disk as posible.
+ //
+ if(
+ (NVRAM_HWLOG_MAX_ENTRY - Control->RN) < NumBlock &&
+ (NVRAM_HWLOG_MAX_ENTRY - Control->NREC) >= NumBlock
+ ){
+
+
+ RemainFree = (NVRAM_HWLOG_MAX_ENTRY - Control->RN);
+
+ NVRAM_HWLOG_WRITE(Buff, StartBlockNo+1,RemainFree);
+ Control->NREC += (USHORT)RemainFree;
+ Control->RN += (USHORT)RemainFree;
+ NumBlock -= RemainFree;
+#if 0
+ Control->RBASE += (USHORT)NumBlock;
+
+#endif
+ //
+ // Move RBASE
+ //
+ FreeLen=0;
+
+ do{
+ //
+ // Read RBASE Header
+ //
+
+ NVRAM_HWLOG_READ(&Header,Control->RBASE,1);
+
+ //
+ // Check Header
+ //
+
+ if(Header.Ident != HEADER_IDENT_REV0){
+ // If SVP Board alive So write port of svp.
+ // IF EIF Occured SVP Board required reset port.
+ //
+
+ if(HalpSvpAlive)
+ HalSvpIntToSvp();
+ return FALSE;
+ }
+
+ //
+ // Check Csm
+ //
+
+ Csm = 0;
+ Sump = (PUCHAR) &Header;
+ for (i= 0; i<= 14; i++){
+ Csm += *(Sump+i);
+ }
+ Csm = (UCHAR)( Csm & 0xff);
+ if(Header.CSM!=Csm){
+ // If SVP Board alive So write port of svp.
+ // IF EIF Occured SVP Board required reset port.
+ //
+
+ if(HalpSvpAlive)
+ HalSvpIntToSvp();
+ return FALSE;
+ }
+ //
+ // FreeLen
+ //
+ Len=0;
+ Len = ( ((Header.DTLEN & 0xFF) << 8) | ((Header.DTLEN & 0xFF00) >> 8) );
+ if(Len%32){
+ Len=(Len/32)+1;
+ }else{
+ Len=Len/32;
+ }
+ FreeLen=FreeLen+Len+1;
+
+ //
+ // Move RBASE
+ //
+ Control->RBASE = Control->RBASE+(USHORT)FreeLen;
+ if(Control->RBASE >= NVRAM_HWLOG_MAX_ENTRY){
+ Control->RBASE=Control->RBASE - NVRAM_HWLOG_MAX_ENTRY;
+ }
+ }while(FreeLen < NumBlock);
+
+ Control->RN=Control->RN - (USHORT)FreeLen;
+ StartBlockNo = 0;
+ }
+
+ NVRAM_HWLOG_WRITE(Buff, StartBlockNo+1,NumBlock);
+
+ Control->RN += (USHORT)NumBlock;
+ if(Control->LOGNUM==0xff){
+ Control->LOGNUM=0;
+ }else{
+ Control->LOGNUM++;
+ }
+ Control->NREC += (USHORT)NumBlock;
+
+ //
+ // Convet endian to big
+ //
+ Control->BASE = ( ((Control->BASE & 0xFF00) >> 8) | ((Control->BASE & 0x00FF) << 8) );
+ Control->NREC = ( ((Control->NREC & 0xFF00) >> 8) | ((Control->NREC & 0x00FF) << 8) );
+ Control->TBASE= ( ((Control->TBASE& 0xFF00) >> 8) | ((Control->TBASE& 0x00FF) << 8) );
+ Control->TN = ( ((Control->TN & 0xFF00) >> 8) | ((Control->TN & 0x00FF) << 8) );
+ Control->RBASE= ( ((Control->RBASE& 0xFF00) >> 8) | ((Control->RBASE& 0x00FF) << 8) );
+ Control->RN = ( ((Control->RN & 0xFF00) >> 8) | ((Control->RN & 0x00FF) << 8) );
+
+ //
+ // Write fix HW Log Control Area.
+ // Block No = 0;
+ // Number of block = 1;
+ NVRAM_HWLOG_WRITE((PUCHAR)Control, 0x0,1);
+
+
+ // If SVP Board alive So write port of svp.
+ // IF EIF Occured SVP Board required reset port.
+ //
+
+ if(HalpSvpAlive)
+ HalSvpIntToSvp();
+
+ return TRUE;
+}
+
+VOID
+HalpColumnbsSysbusLogger(
+ IN ULONG Node
+){
+
+ PHW_LOG_COLUMNBS_SYSBUS_CONTEXT Buf;
+ PCOLUMNBUS_REGISTER ColumnbusRegister;
+ ULONG i;
+ ULONG PhysicalCpuNumber;
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+
+ Buf = (PHW_LOG_COLUMNBS_SYSBUS_CONTEXT)HwLogBuff;
+
+ //
+ // CPU Context.
+ //
+ Buf->EPC.Long = 0;
+ Buf->STATUS = 0;
+ Buf->CAUSE = 0;
+ Buf->CONFIG = 0;
+ Buf->LLADR = 0;
+ Buf->RPID = 0;
+ Buf->CASHEER = 0;
+ Buf->ERREPC.Long = 0;
+
+ //
+ // This Register is local read Only.
+ //
+ Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+#if 0
+ //
+ // Error CPU detect
+ //
+ if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE4){
+ Node = COLUMBUS0_NODE;
+ break;
+ else if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE5)
+ Node = COLUMBUS1_NODE;
+ break;
+ else if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE6)
+ Node = COLUMBUS2_NODE;
+ break;
+ else if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE7)
+ Node = COLUMBUS3_NODE;
+ break;
+ default :
+ break;
+
+ }
+#endif
+ //
+ // Erred Columbus H/W Register Context.
+ //
+ Buf->COLUMNBS_NMIR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->NMIR);
+ Buf->COLUMNBS_CNFG = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->CNFG);
+ Buf->COLUMNBS_STSR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STSR);
+ //
+ // This Register is local read Only.
+ //
+// Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+
+ Buf->COLUMNBS_AERR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR);
+ Buf->COLUMNBS_AERR2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR2);
+ Buf->COLUMNBS_FERR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->FERR);
+ Buf->COLUMNBS_FERR2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->FERR2);
+ Buf->COLUMNBS_ERRMK = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRMK);
+ Buf->COLUMNBS_ERRMK2= READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRMK2);
+ Buf->COLUMNBS_ERRI = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRI);
+ Buf->COLUMNBS_ERRI2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRI2);
+ Buf->COLUMNBS_NMIM = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->NMIM);
+ Buf->COLUMNBS_NMIM2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->NMIM2);
+ Buf->COLUMNBS_ARTYCT= READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ARTYCT);
+ Buf->COLUMNBS_DRTYCT= READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->DRTYCT);
+ Buf->COLUMNBS_REVR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->REVR);
+ Buf->COLUMNBS_MODE = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->MODE);
+ Buf->IPR.Long = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->IPR);
+ Buf->IPR.Fill = READ_REGISTER_ULONG( ((PULONG)&COLUMNBS_GCNTL(Node)->IPR) +1);
+ Buf->MKR.Long = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->MKR);
+ Buf->MKR.Fill = READ_REGISTER_ULONG( ((PULONG)&COLUMNBS_GCNTL(Node)->MKR) +1);
+
+#if 1
+ ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(Node)->RRMT0H;
+
+ for(i=0;i< 8;i++){
+ Buf->RRMTXX[i].Long = READ_REGISTER_ULONG( (PULONG)(ColumnbusRegister++) );
+ Buf->RRMTXX[i].Fill = READ_REGISTER_ULONG( (PULONG)(ColumnbusRegister++) );
+// ColumnbusRegister++;
+ }
+
+ //
+ // STCON Register Local Access Only. So We report when CPU == happned CPU.
+ //
+ PhysicalCpuNumber = Node & 0x3;
+ if(PhysicalCpuNumber == HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number]){
+ Buf->COLUMNBS_SYNDM = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->SYNDM);
+ Buf->COLUMNBS_STCON = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON);
+ Buf->COLUMNBS_STSAD = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STSAD);
+ Buf->COLUMNBS_STADMK = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STADMK);
+
+ ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(Node)->STDATH;
+
+ WRITE_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON,
+ Buf->COLUMNBS_STCON & 0x004fffff);
+ while(READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON ) & 0x00800000)
+ ;
+ for(i=0;i< 64;i++){
+ Buf->TRACE[i].Long = READ_REGISTER_ULONG( (PULONG)ColumnbusRegister );
+ Buf->TRACE[i].Fill = READ_REGISTER_ULONG( (PULONG)(ColumnbusRegister+1) );
+// ColumnbusRegister++;
+ }
+ WRITE_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON,
+ Buf->COLUMNBS_STCON | 0x00800000 );
+ }
+#endif
+
+ //
+ // Write Log Record
+ //
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+}
+
+VOID
+HalpMpuLogger(
+ IN ULONG Node
+){
+ HalpColumnbsSysbusLogger(Node);
+}
+
+
+//
+//
+//
+VOID
+HalpPoncePciBuserrLogger(
+ IN ULONG Node
+){
+ //
+ //
+
+ PHW_LOG_PONCE_CONTEXT Buf;
+ ULONG Ponce;
+ PPONCE_REGISTER PonceRegister;
+ ULONG i;
+
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+
+ Buf = (PHW_LOG_PONCE_CONTEXT)HwLogBuff;
+ Ponce = Node;
+ //
+ // CPU Context.
+ //
+ Buf->EPC.Long = 0;
+ //
+ // Columbus H/W Register Context.
+ //
+ Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+ Buf->PONCE_REVR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->REVR);
+ Buf->PONCE_AERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->AERR);
+ Buf->PONCE_FERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->FERR);
+ Buf->PONCE_ERRM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->ERRM);
+ Buf->PONCE_ERRI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->ERRI);
+ Buf->PONCE_EAHI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->EAHI);
+ Buf->PONCE_EALI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->EALI);
+ Buf->PONCE_PAERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PAERR);
+ Buf->PONCE_PFERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PFERR);
+ Buf->PONCE_PERRM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRM);
+ Buf->PONCE_PERRI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRI);
+ Buf->PONCE_PTOL = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PTOL);
+ Buf->PONCE_PNRT = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PNRT);
+ Buf->PONCE_PRCOL = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PRCOL);
+ Buf->PONCE_PMDL = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PMDL);
+ Buf->PONCE_ANRC = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->ANRC);
+ Buf->PONCE_DNRC = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->DNRC);
+ Buf->PONCE_PCMDN = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PCMDN);
+ Buf->PONCE_PSTAT = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PSTAT);
+ Buf->PONCE_REVID = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->REVID);
+ Buf->PONCE_LTNCY = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->LTNCY);
+
+#if 0
+ PonceRegister = (PPONCE_REGISTER)&PONCE_CNTL(Ponce)->RRMT0H;
+
+ for(i=0;i< 8;i++){
+ Buf->PONCE_RRMTX[i].Long = READ_REGISTER_ULONG( (PULONG)PonceRegister );
+ Buf->PONCE_RRMTX[i].Fill = READ_REGISTER_ULONG( (PULONG)(PonceRegister+1) );
+ PonceRegister++;
+ }
+
+ Buf->PONCE_TRSM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TRSM);
+// Buf->PONCE_TROM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TROM);
+ Buf->PONCE_TRAC = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TRAC);
+ Buf->PONCE_TRDS = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TRDS);
+#endif
+
+ //
+ // Write Log Record
+ //
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+}
+
+VOID
+HalpPonceSysbuserrLogger(
+ IN ULONG Node
+){
+
+ HalpPoncePciBuserrLogger(Node);
+
+}
+
+VOID
+HalpMagellanSysbuserrLogger(
+ IN ULONG Node
+){
+
+
+ PHW_LOG_MAGELLAN_SYSBUS_CONTEXT Buf;
+ ULONG Magellan;
+ ULONG i;
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+
+ Buf = ( PHW_LOG_MAGELLAN_SYSBUS_CONTEXT)HwLogBuff;
+ Magellan = Node - MAGELLAN0_NODE;
+ //
+ // Magellan Context.
+ //
+ Buf->MAGELLAN_AERR = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->AERR );
+ Buf->MAGELLAN_FERR = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->FERR );
+ Buf->MAGELLAN_ERRM = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ERRM );
+ Buf->MAGELLAN_ERRI = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ERRI );
+#if 0 //non support
+ Buf->MAGELLAN_NMIM = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->NMIM );
+#endif
+ Buf->MAGELLAN_EAHI = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EAHI );
+ Buf->MAGELLAN_EALI = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EALI );
+ Buf->MAGELLAN_CKE0 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->CKE0 );
+ Buf->MAGELLAN_SECT = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->SECT );
+ Buf->MAGELLAN_STS1 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->STS1 );
+ Buf->MAGELLAN_DATM.Long =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->DATM );
+ Buf->MAGELLAN_DSRG.Long =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->DSRG );
+ Buf->MAGELLAN_SDLM.Long = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->SDLM );
+
+ Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+
+ Buf->ECC1ERROR_COUNT = 0;
+ Buf->SIMM_ITF_RESULT = 0;
+ Buf->MEMORYMAP_ITF_RESULT =0;
+
+
+ Buf->MAGELLAN_INLC = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->INLC );
+ Buf->MAGELLAN_RCFD = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->RCFD );
+ Buf->MAGELLAN_DTRG = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->DTRG );
+ Buf->MAGELLAN_REVR = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->REVR );
+ Buf->MAGELLAN_ADECX[0] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC0 );
+ Buf->MAGELLAN_ADECX[1] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC1 );
+ Buf->MAGELLAN_ADECX[2] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC2 );
+ Buf->MAGELLAN_ADECX[3] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC3 );
+ Buf->MAGELLAN_EADECX[1]=READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EAADEC0 );
+ Buf->MAGELLAN_EADECX[2]=READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EAADEC1 );
+ Buf->EPC.Long = 0;
+
+#if 1
+ //
+ // These registers are not S/W specification
+ //
+ Buf->MAGELLAN_TMODE = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD) );
+ Buf->MAGELLAN_TRA = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRA) );
+
+ WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD),
+ Buf->MAGELLAN_TMODE & 0x7fffffff);
+ while( READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD) ) & 0x80000000)
+ ;
+
+ i = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD ) );
+ WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD),
+ i | 0x08000000);
+ while( !(READ_REGISTER_ULONG((PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD)) & 0x08000000) )
+ ;
+
+ for(i=0;i<32;i++){
+ Buf->TRMX[i][0] = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRM0[i]) );
+ Buf->TRMX[i][1] = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRM1[i]) );
+ Buf->TRMX[i][2] = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRM2[i]) );
+ }
+ i = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD ) );
+ WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD),
+ i & 0xf7ffffff );
+ WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD),
+ ( i & 0xf7ffffff ) | 0x80000000);
+#endif
+
+ //
+ // Write Log Record
+ //
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+}
+
+//
+//
+VOID
+HalpEcc1Logger(
+ IN ULONG Node
+)
+{
+ HalpMagellanSysbuserrLogger(Node);
+}
+
+//
+//
+VOID
+HalpEcc2Logger(
+ IN ULONG Node
+)
+{
+ HalpMagellanSysbuserrLogger(Node);
+}
+
+VOID
+HalpEisaLogger(
+ IN ULONG Node
+){
+
+ PHW_LOG_EISA_CONTEXT Buf;
+
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+
+ Buf = ( PHW_LOG_EISA_CONTEXT)HwLogBuff;
+
+ Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+
+ Buf->ESC_NMISC = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus);
+ Buf->ESC_NMIERTC = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
+ Buf->ESC_NMIESC = READ_REGISTER_UCHAR(
+ &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl
+ );
+ Buf->ESC_SOFTNMI = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiIoInterruptPort);
+
+ //
+ // Write Log Record
+ //
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+}
+
+VOID
+HalpCacheErrorLog(
+ IN ULONG cpu,
+ IN PVOID pbuf,
+ IN ULONG errorcode
+ )
+{
+ UCHAR string[256];
+ ULONG cacherr,errorepc;
+
+ PHW_LOG_AREA_HEADER Header;
+ PUCHAR Sump;
+ ULONG i;
+ PHW_LOG_CACHE_ERROR PCache_err;
+ //
+ // Genelic Buffer Initialization to all 0x0
+ //
+
+ Header = (PHW_LOG_AREA_HEADER)pbuf;
+ //
+ // Build This record header
+ //
+ Header->Ident = (USHORT)HEADER_IDENT_REV0;
+ //
+ // Time Field is BCD
+ //
+ GET_TIME2(&(Header->YY));
+ Header->RCT = HEADER_PANIC;
+ Header->ST1 = HEADER_CACHE;
+ Header->ST2 = (UCHAR)cpu;
+ Header->ST3 = (UCHAR)errorcode;
+ Header->DTLEN = HWLOG_REV1_RECORD_SIZE;
+ //
+ // Endian Convert to Big
+ //
+ Header->DTLEN = (
+ ((Header->DTLEN & 0xFF) << 8) |
+ ((Header->DTLEN & 0xFF00) >> 8)
+ );
+ Header->FRU1[0]=Header->FRU1[1] = 0;
+ Header->FRU2[0]=Header->FRU2[1] = 0;
+ Header->CSM = 0;
+ Sump = (PUCHAR) pbuf;
+ for (i= 0; i<= 14; i++){
+ Header->CSM += *(Sump+i);
+ }
+ Header->CSM = (UCHAR)( Header->CSM & 0xff);
+ // Header Build Conpleate!!
+ // Set hw log
+
+ HalpSetHwLog(pbuf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+
+ // Display Error message
+
+ PCache_err=(PHW_LOG_CACHE_ERROR)pbuf;
+ cacherr=PCache_err->CHERR_cpu;
+ errorepc=PCache_err->EPC_cpu;
+ sprintf(string,"CPU #%x Cache Error %x %x %x ",cpu,cacherr,errorepc,errorcode);
+ HalpChangePanicFlag( 16, 0x01, 0x10);
+ HalDisplayString(string);
+ for(;;){
+// DbgBreakPoint();
+ }
+}
+
+VOID
+HalpCacheerrR4400Logger(
+ IN ULONG Node
+){
+
+}
+
+VOID
+HalpCacheerrR10000Logger(
+ IN ULONG Node
+){
+
+}
+
+VOID
+HalpNmiCpuContextCopy(
+ IN ULONG Node
+){
+ PHW_LOG_WDT_CONTEXT Buf;
+ ULONG Cpu;
+
+ Buf = (PHW_LOG_WDT_CONTEXT)HwLogBuff;
+
+ Cpu = Node - COLUMBUS0_NODE;
+
+ Buf->Cpu.At.Long =HalpNMIBuf[Cpu][0];
+ Buf->Cpu.V0.Long =HalpNMIBuf[Cpu][1];
+ Buf->Cpu.V1.Long =HalpNMIBuf[Cpu][2];
+ Buf->Cpu.A0.Long =HalpNMIBuf[Cpu][3];
+ Buf->Cpu.A1.Long =HalpNMIBuf[Cpu][4];
+ Buf->Cpu.A2.Long =HalpNMIBuf[Cpu][5];
+ Buf->Cpu.A3.Long =HalpNMIBuf[Cpu][6];
+ Buf->Cpu.T0.Long =HalpNMIBuf[Cpu][7];
+ Buf->Cpu.T1.Long =HalpNMIBuf[Cpu][8];
+ Buf->Cpu.T2.Long =HalpNMIBuf[Cpu][9];
+ Buf->Cpu.T3.Long =HalpNMIBuf[Cpu][10];
+ Buf->Cpu.T4.Long =HalpNMIBuf[Cpu][11];
+ Buf->Cpu.T5.Long =HalpNMIBuf[Cpu][12];
+ Buf->Cpu.T6.Long =HalpNMIBuf[Cpu][13];
+ Buf->Cpu.T7.Long =HalpNMIBuf[Cpu][14];
+ Buf->Cpu.T8.Long =HalpNMIBuf[Cpu][15];
+ Buf->Cpu.T9.Long =HalpNMIBuf[Cpu][16];
+ Buf->Cpu.GP.Long =HalpNMIBuf[Cpu][17];
+ Buf->Cpu.SP.Long =HalpNMIBuf[Cpu][18];
+ Buf->Cpu.FP.Long =HalpNMIBuf[Cpu][19];
+ Buf->Cpu.RA.Long =HalpNMIBuf[Cpu][20];
+ Buf->Cpu.STATUS =HalpNMIBuf[Cpu][21];
+ Buf->Cpu.CAUSE =HalpNMIBuf[Cpu][22];
+
+ Buf->Cpu.EPC.Long =HalpNMIBuf[Cpu][23];
+ Buf->Cpu.ERREPC.Long =HalpNMIBuf[Cpu][24];
+
+ Buf->Cpu.S0.Long = HalpNMIBuf[Cpu][25];
+ Buf->Cpu.S1.Long = HalpNMIBuf[Cpu][26];
+ Buf->Cpu.S2.Long = HalpNMIBuf[Cpu][27];
+ Buf->Cpu.S3.Long = HalpNMIBuf[Cpu][28];
+ Buf->Cpu.S4.Long = HalpNMIBuf[Cpu][29];
+ Buf->Cpu.S5.Long = HalpNMIBuf[Cpu][30];
+ Buf->Cpu.S6.Long = HalpNMIBuf[Cpu][31];
+ Buf->Cpu.S7.Long = HalpNMIBuf[Cpu][32];
+
+ Buf->Cpu.K0.Long = 0;
+
+ Buf->Cpu.ENTRYLO0.Long = HalpNMIBuf[Cpu][33];
+ Buf->Cpu.ENTRYLO1.Long = HalpNMIBuf[Cpu][34];
+ Buf->Cpu.BADVADDR.Long = HalpNMIBuf[Cpu][35];
+ Buf->Cpu.ENTRYHI.Long = HalpNMIBuf[Cpu][36];
+
+
+ Buf->Cpu.PAGEMASK = HalpNMIBuf[Cpu][37];
+ Buf->Cpu.PRID = HalpNMIBuf[Cpu][38];
+ Buf->Cpu.CONFIG = HalpNMIBuf[Cpu][39];
+ Buf->Cpu.LLADDR = HalpNMIBuf[Cpu][40];
+ Buf->Cpu.WATCHLO = HalpNMIBuf[Cpu][41];
+ Buf->Cpu.WATCHHI = HalpNMIBuf[Cpu][42];
+ Buf->Cpu.XCONTEXT.Long = HalpNMIBuf[Cpu][43];
+ Buf->Cpu.ECC = HalpNMIBuf[Cpu][44];
+ Buf->Cpu.CASEER = HalpNMIBuf[Cpu][45];
+ Buf->Cpu.TAGLO = HalpNMIBuf[Cpu][46];
+ Buf->Cpu.TAGHI = HalpNMIBuf[Cpu][47];
+
+}
+
+
+
+VOID
+HalpNmiWdtLogger(
+ IN ULONG Node
+){
+
+ PHW_LOG_WDT_CONTEXT Buf;
+
+ Buf = (PHW_LOG_WDT_CONTEXT)HwLogBuff;
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+
+ HalpNmiCpuContextCopy(Node);
+
+ Buf->COLUMNBS_NMIR = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->NMIR);
+ Buf->COLUMNBS_CNFG = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->CNFG);
+ Buf->COLUMNBS_WDTSR= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->WDTSR);
+ Buf->COLUMNBS_WDT = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->WDT);
+ Buf->IPR.Long = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->IPR);
+ Buf->IPR.Fill = READ_REGISTER_ULONG( ((PULONG)&(COLUMNBS_LCNTL)->IPR+1));
+ Buf->MKR.Long = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKR);
+ Buf->MKR.Fill = READ_REGISTER_ULONG( ((PULONG)&(COLUMNBS_LCNTL)->MKR+1));
+
+ //
+ // Write Log Record
+ //
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+}
+
+VOID
+HalpNmiSvpLogger(
+ IN ULONG Node
+){
+
+ PHW_LOG_SVP_CONTEXT Buf;
+
+ Buf = (PHW_LOG_SVP_CONTEXT)HwLogBuff;
+
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+
+ HalpNmiCpuContextCopy(Node);
+ //
+ // Write Log Record
+ //
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+}
+
+VOID
+HalpNmiLog(
+ VOID
+){
+ ULONG PhysicalCpuNumber;
+ ULONG Node;
+
+ PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number];
+ Node = PhysicalCpuNumber + COLUMBUS0_NODE;
+
+ switch( HalpNMIFlag & 0xffff){
+ case NMIR_EXNMI :
+// if(HalpNmiSvp[PhysicalCpuNumber])
+ HalpNmiSvpLogger(Node);
+
+
+ break;
+ case NMIR_WDTOV:
+ HalpNmiWdtLogger(Node);
+ break;
+#if 0
+ case NMIR_CLBNMI:
+ case NMIR_UNANMI:
+ HalpColumnbsSysbusLogger(Node);
+ break;
+#endif
+ default:
+ if ( READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR) & HW_LOG_MPU_INTERNAL_AERR)
+ HalpMpuLogger(Node);
+ else
+ HalpColumnbsSysbusLogger(Node);
+ break;
+ }
+
+
+}
+
+
+VOID
+HalpPowerLogger(
+ IN ULONG Node
+//
+// Node Not used.
+//
+//
+
+){
+
+
+ PHW_LOG_POWER_CONTEXT Buf;
+ UCHAR Data;
+ PHW_LOG_AREA_HEADER Header;
+ //
+ // Builg Log Header
+ //
+ HalpHwLogHeaderInit();
+ Header = (PHW_LOG_AREA_HEADER)HwLogBuff;
+
+ Header->RCT = HEADER_NOT_PANIC;
+ Buf = (PHW_LOG_POWER_CONTEXT)HwLogBuff;
+
+ Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD);
+
+ HalpLocalDeviceReadWrite(ALARM_LOW,&Data,LOCALDEV_OP_READ);
+ Buf->LOCAL_ALARM = (USHORT)Data;
+ HalpLocalDeviceReadWrite(ALARM_HIGH,&Data,LOCALDEV_OP_READ);
+ Buf->LOCAL_ALARM |= (USHORT)(Data << 8);
+
+
+ HalpLocalDeviceReadWrite(ALMINH_LOW, &Data,LOCALDEV_OP_READ);
+ Buf->LOCAL_ALMINH = (USHORT)Data;
+ HalpLocalDeviceReadWrite(ALMINH_HIGH,&Data,LOCALDEV_OP_READ);
+ Buf->LOCAL_ALMINH |= (USHORT)(Data << 8);
+
+
+ HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1);
+
+
+
+}
+
+VOID
+HalpEifReturnLog(
+ VOID
+){
+
+ HalpPowerLogger(0);
+
+}
+
+
+VOID
+HalpHwLogger(
+ IN ULONG Type,
+ IN ULONG Context
+){
+
+ switch(Type){
+ case HWLOG_MPU_INTERNAL:
+ HalpMpuLogger(Context); //fix
+ break;
+ case HWLOG_COLUMNBS_SYSBUS:
+ HalpColumnbsSysbusLogger(Context); //fix
+ break;
+ case HWLOG_PCI_BUSERROR:
+ HalpPoncePciBuserrLogger(Context); //fix
+ break;
+ case HWLOG_PONCE_SYSBUS:
+ HalpPonceSysbuserrLogger(Context); //fix
+ break;
+ case HWLOG_MAGELLAN_SYSBUS:
+ HalpMagellanSysbuserrLogger(Context); //fix
+ break;
+ case HWLOG_EISA:
+ HalpEisaLogger(Context); //fix
+ break;
+ case HWLOG_POWER:
+ HalpPowerLogger(Context); //fix
+ break;
+ case HWLOG_2BITERROR:
+ HalpEcc2Logger(Context); //fix
+ break;
+ case HWLOG_CACHEERR_R4400:
+ HalpCacheerrR4400Logger(Context);
+ break;
+ case HWLOG_CACHEERR_R10000:
+ case HWLOG_SYSCORERR:
+ HalpCacheerrR10000Logger(Context);
+ break;
+ case HWLOG_NMI_WDT:
+ HalpNmiWdtLogger(Context);
+ break;
+
+ case HWLOG_NMI_SVP:
+ HalpNmiSvpLogger(Context); //fix
+ break;
+ case HWLOG_ECC1:
+ HalpEcc1Logger(Context); //fix
+ break;
+ default :
+ break;
+ }
+
+}
+
+//
+// This Function Called HalpHandleEif()
+//
+VOID
+HalpEifLog(
+ VOID
+){
+ ULONG Noder;
+ ULONG Node;
+ ULONG ErrorType;
+ ULONG Context;
+
+
+#if 0
+ //
+ // EIF logging only exec 1 cpu.
+ //
+ KiAcquireSpinLock(&HalpLogLock);
+#endif
+ //
+ // Node Get By reported CPU.
+ //
+ Noder = (READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD)& 0xf3cc);
+
+ switch(Noder){
+ case ERRNOD_NODE0 :
+ case ERRNOD_NODE1 :
+ if(Noder & ERRNOD_NODE0)
+ Node = PONCE0_NODE;
+ else
+ Node = PONCE1_NODE;
+
+ if(READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Node)->AERR))
+ ErrorType = HWLOG_PONCE_SYSBUS; //bugbug
+ else
+ ErrorType = HWLOG_PCI_BUSERROR;
+ break;
+ case ERRNOD_NODE4 :
+ case ERRNOD_NODE5 :
+ case ERRNOD_NODE6 :
+ case ERRNOD_NODE7 :
+ if(Noder & ERRNOD_NODE4)
+ Node = COLUMBUS0_NODE;
+ else if(Noder & ERRNOD_NODE5)
+ Node = COLUMBUS1_NODE;
+ else if(Noder & ERRNOD_NODE6)
+ Node = COLUMBUS2_NODE;
+ else if(Noder & ERRNOD_NODE7)
+ Node = COLUMBUS3_NODE;
+
+ //
+ // Read AERR2 Register From EIF happend CPU. Not Reported CPU!!
+ //
+ if ( READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR2) & HW_LOG_MPU_INTERNAL_AERR2)
+ ErrorType = HWLOG_MPU_INTERNAL;
+ else
+ ErrorType = HWLOG_COLUMNBS_SYSBUS;
+
+ break;
+ case ERRNOD_NODE8 :
+ case ERRNOD_NODE9 :
+
+ ErrorType = HWLOG_MAGELLAN_SYSBUS;
+
+ if(Noder & ERRNOD_NODE8)
+ Node = MAGELLAN0_NODE;
+ else
+ Node = MAGELLAN1_NODE;
+ break;
+
+ case ERRNOD_EISANMI:
+ ErrorType = HWLOG_EISA;
+ break;
+
+ default:
+ //
+ // if There is no CPU Coused EIF. So Reported CPU set.
+ //
+ ErrorType = HWLOG_COLUMNBS_SYSBUS;
+ Node = HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number] + COLUMBUS0_NODE;
+ break;
+ }
+ Context = Node;
+ HalpHwLogger(ErrorType, Context);
+
+#if 0
+ KiReleaseSpinLock(&HalpLogLock);
+#endif
+}
+
+
+//
+// This Function Called HalpBusError()
+//
+VOID
+HalpBusErrorLog(
+ VOID
+){
+ ULONG Node;
+ ULONG ErrorType;
+ ULONG Context;
+
+
+// KiAcquireSpinLock(&HalpLogLock);
+ //
+ // Node Get By reported CPU.
+ //
+ Node = (READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->EAHI) & 0xF000) >> 12;
+
+ switch(Node){
+ case PONCE0_NODE:
+ case PONCE1_NODE:
+ ErrorType = HWLOG_PONCE_SYSBUS;
+ break;
+ case COLUMBUS0_NODE:
+ case COLUMBUS1_NODE:
+ case COLUMBUS2_NODE:
+ case COLUMBUS3_NODE:
+ ErrorType = HWLOG_COLUMNBS_SYSBUS;
+ break;
+ case MAGELLAN0_NODE:
+ case MAGELLAN1_NODE:
+ ErrorType = HWLOG_2BITERROR;
+ break;
+ default:
+ ErrorType = HWLOG_COLUMNBS_SYSBUS;
+ //
+ // This is safe code
+ //
+ Node = HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number] + COLUMBUS0_NODE;
+ break;
+ }
+ Context = Node;
+ HalpHwLogger(ErrorType, Context);
+
+
+// KiReleaseSpinLock(&HalpLogLock);
+}
diff --git a/private/ntos/nthals/halr98b/mips/rxhwlog.h b/private/ntos/nthals/halr98b/mips/rxhwlog.h
new file mode 100644
index 000000000..077f3816f
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxhwlog.h
@@ -0,0 +1,469 @@
+/*
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ rxhwlog.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the r98B system.
+
+Author:
+
+
+
+Revision History:
+
+--*/
+
+#ifndef _RXHWLOG_
+#define _RXHWLOG_
+
+#include "halp.h"
+
+
+#define NVRAM_HWLOG_PHYSIACL_ADDRESS 0x1F084000
+#define NVRAM_HWLOG_END 0x1F08C000
+#define NVRAM_HWLOG_BASE (KSEG1_BASE|NVRAM_HWLOG_PHYSIACL_ADDRESS)
+#define NVRAM_HWLOG_MAX_ENTRY (((NVRAM_HWLOG_END - NVRAM_HWLOG_PHYSIACL_ADDRESS)\
+ - sizeof(HWLOG_CONTROL_INFO)) / HWLOG_RECORD_SIZE)
+
+#define HWLOG_RECORD_SIZE 0x20
+#define HWLOG_REV1_RECORD_SIZE (0x200)
+//
+// Log Record RCT field
+//
+#define RCT_EPU 0x00
+#define RCT_MEMORY 0x01
+#define RCT_SYSBUS 0x03
+#define RCT_IOBUS 0x04
+#define RCT_CACHE 0x05
+#define RCT_SVP 0x06
+#define RCT_POWER 0x08
+#define RCT_COLUMNUS_SYSBUS 0x03
+
+
+//
+// Log Record ST1 field
+// PC: PCI BusNumber
+// EC: Errcode
+// MP: MPU Number
+//
+#define ST1_WDT_RUNOUT 0x00
+#define ST1_SVPNMI 0x08
+#define ST1_MPU 0x10
+#define ST1_SYS_IF_TRACE_LOG 0x12
+#define ST1_MEMORY_2BIT_ERR 0x00
+#define ST1_MEMORY_1BIT_HARD1 0x01
+#define ST1_MEMORY_1BIT_HARDN 0x02
+#define ST1_MEMORY_1BIT_HARD 0x03
+#define ST1_MEMORY_INTERNAL 0x10
+//#define ST1_COLUMNBUS_SYSBUS 0xEC
+//#define ST1_PONCE_SYSBUS 0xEC
+//#define ST1_MAGELLAN_SYSBUS 0xEC
+#define ST1_SYSBUS_TRACE_LOG 0x09
+//#define ST1_PCI_BUS_ERR PC
+#define ST1_EISA_BUS_ERR 0x07
+//#define ST1_CACHE_ERR_R4400 MP
+//#define ST1_CACHE_ERR_R10000 MP
+#define ST1_SVP_COM 0x01
+#define ST1_POWER_ALARM 0x20
+#define ST1_FAN_ALARM 0x21
+#define ST1_NPCI2_ALARM 0x22
+#define ST1_SVP_ALARM 0x23
+
+
+//
+// Log Record DTLEN
+//
+
+#define DTLEN_WDT 0x8001
+#define DTLEN_SVPNMI 0x6001
+#define DTLEN_MPU_INTERNAL 0x0002
+#define DTLEN_SYSTEM_IF_TRACE_LOG 0x0002
+#define DTLEN_ECC1_BIT 0x0002
+
+//
+// Log Record FRU1
+//
+#define FRU1_WDT "MPUx"
+#define FRU1_SVPNMI "MPUx"
+
+#pragma pack(1)
+
+typedef struct _MPU_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} MPU_REGISTER, *PMPU_REGISTER;
+
+typedef struct _HWLOG_CONTROL_INFO {
+ USHORT PAD0;
+ USHORT BASE;
+
+ USHORT PAD1;
+ USHORT NREC;
+
+ USHORT PAD2;
+ UCHAR PAD3;
+ UCHAR LOGNUM;
+
+ USHORT PAD4;
+ UCHAR PAD5;
+ UCHAR STAT;
+
+ USHORT PAD6;
+ USHORT TBASE;
+
+ USHORT PAD7;
+ USHORT TN;
+
+ USHORT PAD8;
+ USHORT RBASE;
+
+ USHORT PAD9;
+ USHORT RN;
+
+} HWLOG_CONTROL_INFO,*PHWLOG_CONTROL_INFO;
+
+
+typedef struct _HW_LOG_AREA_HEADER {
+ USHORT Ident;
+ UCHAR YY;
+ UCHAR MM;
+
+ UCHAR DD;
+ UCHAR hh;
+ UCHAR mm;
+ UCHAR ss;
+
+ UCHAR RCT;
+ UCHAR ST1;
+ UCHAR ST2;
+ UCHAR ST3;
+
+ USHORT DTLEN;
+ UCHAR LGN;
+ UCHAR CSM;
+
+ ULONG FRU1[2];
+ ULONG FRU2[2];
+
+}HW_LOG_AREA_HEADER,*PHW_LOG_AREA_HEADER;
+
+
+#define HEADER_IDENT_REV0 0xFFFFF
+#define HEADER_PANIC 0x10
+#define HEADER_NOT_PANIC 0x11
+typedef struct _HW_LOG_CPU_CONTEXT {
+ MPU_REGISTER At;
+ MPU_REGISTER V0;
+ MPU_REGISTER V1;
+ MPU_REGISTER V2;
+ MPU_REGISTER A0;
+ MPU_REGISTER A1;
+ MPU_REGISTER A2;
+ MPU_REGISTER A3;
+ MPU_REGISTER T0;
+ MPU_REGISTER T1;
+ MPU_REGISTER T2;
+ MPU_REGISTER T3;
+ MPU_REGISTER T4;
+ MPU_REGISTER T5;
+ MPU_REGISTER T6;
+ MPU_REGISTER T7;
+ MPU_REGISTER S0;
+ MPU_REGISTER S1;
+ MPU_REGISTER S2;
+ MPU_REGISTER S3;
+ MPU_REGISTER S4;
+ MPU_REGISTER S5;
+ MPU_REGISTER S6;
+ MPU_REGISTER S7;
+ MPU_REGISTER T8;
+ MPU_REGISTER T9;
+ MPU_REGISTER K0;
+ MPU_REGISTER GP;
+ MPU_REGISTER SP;
+ MPU_REGISTER FP;
+ MPU_REGISTER RA;
+ MPU_REGISTER ENTRYLO0;
+ MPU_REGISTER ENTRYLO1;
+ MPU_REGISTER CONTEXT;
+ MPU_REGISTER BADVADDR;
+ MPU_REGISTER ENTRYHI;
+ ULONG STATUS;
+ ULONG CAUSE;
+ MPU_REGISTER EPC;
+ ULONG PAGEMASK;
+ ULONG PRID;
+ ULONG CONFIG;
+ ULONG LLADDR;
+ ULONG WATCHLO;
+ ULONG WATCHHI;
+ MPU_REGISTER XCONTEXT;
+ ULONG ECC;
+ ULONG CASEER;
+ ULONG TAGLO;
+ ULONG TAGHI;
+ MPU_REGISTER ERREPC;
+}HW_LOG_CPU_CONTEXT,*PHW_LOG_CPU_CONTEXT;
+
+
+typedef struct _HW_LOG_WDT_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ HW_LOG_CPU_CONTEXT Cpu;
+ ULONG COLUMNBS_NMIR;
+ ULONG COLUMNBS_CNFG;
+ ULONG COLUMNBS_WDTSR;
+ ULONG COLUMNBS_WDT;
+ COLUMNBUS_REGISTER IPR;
+ COLUMNBUS_REGISTER MKR;
+}HW_LOG_WDT_CONTEXT,*PHW_LOG_WDT_CONTEXT;
+
+
+typedef struct _HW_LOG_SVP_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ HW_LOG_CPU_CONTEXT Cpu;
+}HW_LOG_SVP_CONTEXT,*PHW_LOG_SVP_CONTEXT;
+
+
+typedef struct _HW_LOG_MPU_INTERNAL_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+
+ MPU_REGISTER EPC;
+ ULONG STATUS;
+ ULONG CAUSE;
+ ULONG CONFIG;
+ ULONG LLADR;
+ ULONG RPID;
+ ULONG CASHEER;
+ MPU_REGISTER ERREPC;
+
+ ULONG COLUMNBS_NMIR;
+ ULONG COLUMNBS_CNFG;
+ ULONG COLUMNBS_STSR;
+ ULONG COLUMNBS_ERRNOD;
+ ULONG COLUMNBS_AERR;
+ ULONG COLUMNBS_AERR2;
+ ULONG COLUMNBS_FERR;
+ ULONG COLUMNBS_FERR2;
+ ULONG COLUMNBS_ERRMK;
+ ULONG COLUMNBS_ERRMK2;
+ ULONG COLUMNBS_ERRI;
+ ULONG COLUMNBS_ERRI2;
+ ULONG COLUMNBS_NMIM;
+ ULONG COLUMNBS_NMIM2;
+ ULONG COLUMNBS_ARTYCT;
+ ULONG COLUMNBS_DRTYCT;
+ ULONG COLUMNBS_REVR;
+ ULONG COLUMNBS_MODE;
+ COLUMNBUS_REGISTER IPR;
+ COLUMNBUS_REGISTER MKR;
+ COLUMNBUS_REGISTER RRMTXX[8];
+ ULONG COLUMNBS_SYNDM;
+ ULONG COLUMNBS_STCON;
+ ULONG COLUMNBS_STSAD;
+ ULONG COLUMNBS_STADMK;
+ COLUMNBUS_REGISTER TRACE[64];
+}HW_LOG_MPU_INTERNAL_CONTEXT,*PHW_LOG_MPU_INTERNAL_CONTEXT;
+
+#define HW_LOG_COLUMNBS_SYSBUS_CONTEXT HW_LOG_MPU_INTERNAL_CONTEXT
+#define PHW_LOG_COLUMNBS_SYSBUS_CONTEXT PHW_LOG_MPU_INTERNAL_CONTEXT
+
+#define HW_BUSERROR_MPU_CONTEXT HW_LOG_MPU_INTERNAL_CONTEXT
+#define PHW_BUSERROR_MPU_CONTEXT PHW_LOG_MPU_INTERNAL_CONTEXT
+
+#define HW_NMI_COLUMNBS_CONTEXT HW_LOG_MPU_INTERNAL_CONTEXT
+#define PHW_NMI_COLUMNBS_CONTEXT PHW_LOG_MPU_INTERNAL_CONTEXT
+
+#define HW_LOG_ECC1_CONTEXT HW_LOG_MAGELLAN_SYSBUS_CONTEXT
+#define PHW_LOG_ECC1_CONTEXT PHW_LOG_MAGELLAN_SYSBUS_CONTEXT
+
+#if 0
+typedef struct HW_LOG_MPU_INTERNAL_CONTEXT HW_LOG_COLUMNBS_SYSBUS_CONTEXT;
+typedef struct HW_LOG_COLUMNBS_SYSBUS_CONTEXT * PHW_LOG_COLUMNBS_SYSBUS_CONTEXT;
+typedef struct HW_LOG_MPU_INTERNAL_CONTEXT HW_BUSERROR_MPU_CONTEXT,*PHW_BUSERROR_MPU_CONTEXT;
+typedef struct HW_LOG_MPU_INTERNAL_CONTEXT HW_NMI_COLUMNBS_CONTEXT,*PHW_NMI_COLUMNBS_CONTEXT;
+typedef struct HW_LOG_MAGELLAN_SYSBUS_CONTEXT HW_LOG_ECC1_CONTEXT,*PHW_LOG_ECC1_CONTEXT;
+#endif
+
+typedef struct _HW_LOG_SYSTEM_IF_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ COLUMNBUS_REGISTER SYNDM;
+ COLUMNBUS_REGISTER STCON;
+ COLUMNBUS_REGISTER STSAD;
+ COLUMNBUS_REGISTER STADMK;
+ USHORT STDATHL[64][2];
+}HW_LOG_SYSTEM_IF_CONTEXT,*PHW_LOG_SYSTEM_IF_CONTEXT;
+
+
+
+typedef struct _HW_LOG_MAGELLAN_SYSBUS_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ ULONG MAGELLAN_AERR;
+ ULONG MAGELLAN_FERR;
+ ULONG MAGELLAN_ERRM;
+ ULONG MAGELLAN_ERRI;
+ ULONG MAGELLAN_NMIM;
+ ULONG MAGELLAN_EAHI;
+ ULONG MAGELLAN_EALI;
+ ULONG MAGELLAN_CKE0;
+ ULONG MAGELLAN_SECT;
+ ULONG MAGELLAN_STS1;
+ MAGELLAN_REGISTER MAGELLAN_DATM;
+ MAGELLAN_REGISTER MAGELLAN_DSRG;
+ MAGELLAN_REGISTER MAGELLAN_SDLM;
+ ULONG COLUMNBS_ERRNOD;
+ ULONG ECC1ERROR_COUNT;
+ ULONG SIMM_ITF_RESULT;
+ ULONG MEMORYMAP_ITF_RESULT;
+ ULONG MAGELLAN_INLC;
+ ULONG MAGELLAN_RCFD;
+ ULONG MAGELLAN_DTRG;
+ ULONG MAGELLAN_REVR;
+ ULONG MAGELLAN_ADECX[4];
+ ULONG MAGELLAN_EADECX[2];
+ MPU_REGISTER EPC;
+ ULONG MAGELLAN_TMODE;
+ ULONG MAGELLAN_TRA;
+ ULONG TRMX[32][3];
+}HW_LOG_MAGELLAN_SYSBUS_CONTEXT,*PHW_LOG_MAGELLAN_SYSBUS_CONTEXT;
+
+typedef struct _HW_LOG_PONCE_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ MPU_REGISTER EPC;
+ ULONG COLUMNBS_ERRNOD;
+ ULONG PONCE_REVR;
+ ULONG PONCE_AERR;
+ ULONG PONCE_FERR;
+ ULONG PONCE_ERRM;
+ ULONG PONCE_ERRI;
+ ULONG PONCE_EAHI;
+ ULONG PONCE_EALI;
+ ULONG PONCE_PAERR;
+ ULONG PONCE_PFERR;
+ ULONG PONCE_PERRM;
+ ULONG PONCE_PERRI;
+ ULONG PONCE_PTOL;
+ ULONG PONCE_PNRT;
+ ULONG PONCE_PRCOL;
+ ULONG PONCE_PMDL;
+ ULONG PONCE_ANRC;
+ ULONG PONCE_DNRC;
+ ULONG PONCE_PCMDN;
+ ULONG PONCE_PSTAT;
+ ULONG PONCE_REVID;
+ ULONG PONCE_LTNCY;
+ PONCE_REGISTER PONCE_RRMTX[8];
+ ULONG PONCE_TRSM;
+ ULONG PONCE_TROM;
+ ULONG PONCE_TRAC;
+ ULONG PONCE_TRDS;
+ UCHAR PONCE_BUSTRACE[344]; //All 0
+}HW_LOG_PONCE_CONTEXT,*PHW_LOG_PONCE_CONTEXT;
+
+typedef struct _HW_LOG_SYSBUS_TRACE_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ ULONG MAGELLAN_TMOD;
+ ULONG MAGELLAN_TRA;
+ ULONG TRMX[42][3];
+}HW_LOG_SYSBUS_TRACE_CONTEXT,*PHW_LOG_SYSBUS_TRACE_CONTEXT;
+
+
+typedef struct _HW_LOG_EISA_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ ULONG COLUMNBS_ERRNOD;
+ ULONG ESC_NMISC;
+ ULONG ESC_NMIERTC;
+ ULONG ESC_NMIESC;
+ ULONG ESC_SOFTNMI;
+}HW_LOG_EISA_CONTEXT,*PHW_LOG_EISA_CONTEXT;
+
+
+
+
+typedef struct _HW_LOG_SVP_CON_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+}HW_LOG_SVP_CON_CONTEXT,*PHW_LOG_SVP_CON_CONTEXT;
+
+
+typedef struct _HW_LOG_POWER_CONTEXT {
+ HW_LOG_AREA_HEADER Header;
+ ULONG COLUMNBS_ERRNOD;
+ USHORT LOCAL_ALARM;
+ USHORT LOCAL_ALMINH;
+}HW_LOG_POWER_CONTEXT,*PHW_LOG_POWER_CONTEXT;
+
+#pragma pack(4)
+
+
+#define HWLOG_MPU_INTERNAL 0x1
+#define HWLOG_COLUMNBS_SYSBUS 0x2
+
+#define HWLOG_PCI_BUSERROR 0x100
+#define HWLOG_PONCE_SYSBUS 0x200
+#define HWLOG_MAGELLAN_SYSBUS 0x400
+
+#define HWLOG_EISA 0x10
+#define HWLOG_POWER 0x20
+#define HWLOG_2BITERROR 0x40
+
+#define HWLOG_CACHEERR_R4400 0x80
+#define HWLOG_CACHEERR_R10000 0x1000
+#define HWLOG_SYSCORERR 0x2000
+#define HWLOG_NMI_WDT 0x4000
+
+
+#define HWLOG_NMI_SVP 0x100000
+#define HWLOG_ECC1 0x200000
+
+
+#define HW_LOG_MPU_INTERNAL_AERR 0x37f
+#define HW_LOG_MPU_INTERNAL_AERR2 0xffffffff
+
+
+#define PONCE0_NODE 0
+#define PONCE1_NODE 1
+#define COLUMBUS0_NODE 4
+#define COLUMBUS1_NODE 5
+#define COLUMBUS2_NODE 6
+#define COLUMBUS3_NODE 7
+
+#define MAGELLAN0_NODE 8
+#define MAGELLAN1_NODE 9
+
+//Cache Error Log
+
+typedef struct _HW_LOG_CACHE_ERROR{
+ HW_LOG_AREA_HEADER Header;
+ ULONG EPC_cpu;
+ ULONG Rev;
+ ULONG Psr_cpu;
+ ULONG CFG_cpu;
+ ULONG PRID_cpu;
+ ULONG CHERR_cpu;
+ ULONG CheAdd_p;
+ ULONG CheAdd_s;
+ ULONG TagLo_p;
+ ULONG ECC_p;
+ ULONG TagLo_s;
+ ULONG ECC_s;
+ LONGLONG data_s;
+ LONGLONG Good_data_s;
+ ULONG Good_TagLo_s;
+ ULONG Good_ECC_s;
+ ULONG tag_synd_s;
+ ULONG data_synd_s;
+ LONGLONG xkphs_share;
+}HW_LOG_CACHE_ERROR,*PHW_LOG_CACHE_ERROR;
+
+
+
+
+#endif // _RXHWLOG_
+
+
+
+
diff --git a/private/ntos/nthals/halr98b/mips/rxhwsup.c b/private/ntos/nthals/halr98b/mips/rxhwsup.c
new file mode 100644
index 000000000..d4cc09ef1
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxhwsup.c
@@ -0,0 +1,2124 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Module Name:
+
+ rxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ S001 96/2/9 T.Samezima
+ -Add TLB limit over check.
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCreateDmaStructures)
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+extern ULONG HalpLogicalCPU2PhysicalCPU[];
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpInt0Interrupt;
+
+UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. ";
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+ULONG HalpLogicalAddressLimit = 0; // S001
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+//
+
+//
+// R98B AdapterObject for PCIBus is per PONCE
+//
+PADAPTER_OBJECT HalpPciAdapterObject[PONCE_MAX];
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ (0x100000 / PAGE_SIZE)
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ // No Check !! R98B 0-1M Never Free
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // R98B Must Be Cached!!
+ //
+ CacheEnabled =TRUE;
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+
+ if (virtualAddress == NULL) {
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ // R98
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ (0x100000 / PAGE_SIZE)
+ );
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ // No Check. R98B 0-1M Never Free!!.
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ (0x100000 / PAGE_SIZE),
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber =(0x100000 / PAGE_SIZE) ;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+
+
+ //
+ // R98B Must Be Cached!!
+ //
+ CacheEnabled =TRUE;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+ return;
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: Internal, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ ULONG Ponce;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT ) {
+#if DBG
+ DbgPrint("NumberOfMapRegister REQUEST = 0x%x\n",*NumberOfMapRegisters);
+#endif
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+
+
+ }
+
+ if (DeviceDescription->InterfaceType == PCIBus) {
+
+ //
+ // Create a PCI adapter object.
+ //
+ Ponce = HalpPonceNumber(DeviceDescription->BusNumber);
+
+ if (HalpPciAdapterObject[Ponce] == NULL) {
+ adapterObject = HalpAllocateAdapter(0, &HalpPciAdapterObject[Ponce], NULL);
+ HalpPciAdapterObject[Ponce] = adapterObject;
+
+ } else {
+ adapterObject = HalpPciAdapterObject[Ponce];
+
+ }
+
+ return(adapterObject);
+
+ }
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != Eisa &&
+ //
+ // R98B Internal(Xbus) floppy used ESC DMAC channel 2
+ //
+ (DeviceDescription->InterfaceType == Internal && (DeviceDescription->DmaChannel !=2))
+ ) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+//
+// USE Limit DMA_REQUEST_LIMIT
+//
+//
+#if 0
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / EISA_MAX_DEVICE) {
+
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / EISA_MAX_DEVICE;
+ }
+#endif
+ return(adapterObject);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+ ULONG Mode;
+ ULONG Ponce;
+ PTRANSLATION_ENTRY PageTableEntry;
+ ULONG i;
+ ULONG NodeMask;
+
+ ULONG tst; //SNES
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter( 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if (AdapterBaseVa == NULL) {
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+ AdapterObject->PagePort = NULL;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+ ULONG MapRegisterSize;
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+ // R98B
+ // Reserv 0 - (1M-1) Logical addr!!.
+ //
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0x0, // Start 0
+ 0x100 // 256 is 1M
+ );
+ // R98B
+ // Reserv 15M - (16M-1) Logical addr!!.
+ //
+ //RtlSetBits (
+ // AdapterObject->MapRegisters,
+ // 0xF00, // Start 15M
+ // 0x100 // END 16M-1
+ //);
+
+ // R98B
+ // Reserv Last 1 Logical addr!!. For PCEB Prefetch Cycle.
+ //
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))-1, // Last 1 page.
+ 0x1 // 1 page Reserved.
+ );
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ // R98B Page Table must be Cached!!.
+ //
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG0_BASE);
+
+ //
+ // N.B This Version Selected
+ // PCEB Prefetch cycle may be Cause TLB refill!!.
+ // So Set Valid Bit All Entry.as We could't invalid transfer.
+ // ~~~~~~~~~~~~~~~~~
+ // Another aprouch.
+ // When Request Mapregster at "NumberOfMapregister"
+ // reserve NumberOfMapregster+1.This one page for PCEB Prefetch
+ // cycle. Driver unknown plus 1 page. Hal know only.
+ //
+ PageTableEntry= (PTRANSLATION_ENTRY)AdapterObject->MapRegisterBase;
+
+ for(i=0;i< DMA_TRANSLATION_LIMIT/ sizeof( TRANSLATION_ENTRY); i++){
+ (PageTableEntry)->PageFrame = (ULONG) PAGE_TABLE_ENTRY_VALID;
+ (PageTableEntry)->Fill = (ULONG) 0;
+ PageTableEntry++;
+ }
+#if defined(DBG5)
+ DbgPrint("HAL Channel init Master\n");
+ DbgPrint("HAL Page Table is 0x%x\n",AdapterObject->MapRegisterBase);
+#endif
+
+ for(Ponce=0;Ponce < HalpNumberOfPonce; Ponce++){
+ //
+ // I/O TLB Page Table Base Set.
+ //
+#if defined(DBG5)
+ DbgPrint("HAL:Ponce No = 0x%x PTBSR addr =0x%x\n",Ponce,(PULONG)&PONCE_CNTL(Ponce)->PTBSR);
+#endif
+
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->PTBSR,
+ (HalpMapRegisterPhysicalBase) >> 1 //SNES
+ );
+#if defined(DBG5)
+ DbgPrint("HAL:Ponce No = 0x%x PTLMR addr =0x%x\n",Ponce,(PULONG)&PONCE_CNTL(Ponce)->PTLMR);
+
+ tst=READ_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->PMODR,
+ );
+
+ DbgPrint("HAL:Ponce No = 0x%x PMODR data =0x%x\n",Ponce,tst);
+ tst |= 0x10000000;
+
+ //
+ // I/O TLB Page Table Limit
+ //
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->PMODR,
+ tst
+ );
+#endif
+
+ //
+ // I/O TLB Page Table Limit
+ //
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->PTLMR,
+ ((HalpMapRegisterPhysicalBase+MapRegisterSize)) >>1
+ );
+#if defined(DBG5)
+ DbgPrint("HAL:Ponce No = 0x%x TFLSR addr =0x%x\n",Ponce,(PULONG)&PONCE_CNTL(Ponce)->TFLSR);
+#endif
+
+ //
+ // I/O TLB Entry All Flush!!
+ //
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->TFLSR,
+ 0x1
+ );
+ //
+ // Enable I/O TLB error.
+ //
+ NodeMask = 0;
+ for(i=0; i < **((PULONG *)(&KeNumberProcessors)); i++){
+ NodeMask |= 0x10 << HalpLogicalCPU2PhysicalCPU[i];
+ }
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->ERITTG[1], NodeMask );
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->ERITTG[1], NodeMask );
+ }
+ }
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ return AdapterObject;
+
+ return (PADAPTER_OBJECT) NULL;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+ // R98B mapregiser allways allocated 1M.
+ // 0-1M reserved hal.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0x100000 / PAGE_SIZE
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ // No Check. Because 0-1M was never free.
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0x100000 / PAGE_SIZE
+ );
+
+ //
+ // Make sure this map register is valid for this adapter.
+ // R98B No Check!!. 0-1M Never free!!
+ //
+
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ // This code is executed phase 1 on processor 0
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ return TRUE;
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+ ULONG Ponce;
+ //
+ // Begin by determining where in the buffer this portion of the operation
+ // is taking place.
+ //
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ // S001 vvv
+ // Set the offset to point to the map register plus the offset.
+ //
+
+ Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT;
+
+ if ( Offset + *Length >= HalpLogicalAddressLimit ){
+ UCHAR messageBuffer[256];
+
+ HalpChangePanicFlag( 16, 0x01, 0x10);
+
+ HalDisplayString("\nHAL I/O TLB SETUP: Logical address limit over.\n");
+
+ sprintf( (char *)messageBuffer, " Offst=0x%08lx, Len =0x%08lx, Limit=0x%08lx\n",
+ Offset, *Length, HalpLogicalAddressLimit );
+ HalDisplayString( (char *)messageBuffer );
+
+ sprintf( (char *)messageBuffer, " CurVa=0x%08lx, StrVa=0x%08lx, RegBs=0x%08lx, MsrBs=0x%08lx\n",
+ (ULONG)CurrentVa, (ULONG)Mdl->StartVa, (ULONG)MapRegisterBase, (ULONG)MasterAdapterObject->MapRegisterBase);
+ HalDisplayString( (char *)messageBuffer );
+
+ sprintf( (char *)messageBuffer, " AdObj=0x%08lx, Mdl =0x%08lx, Write=%d\n",
+ (ULONG)AdapterObject, (ULONG)Mdl, (ULONG)WriteToDevice );
+ HalDisplayString( (char *)messageBuffer );
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,
+ Offset,
+ *Length,
+ HalpLogicalAddressLimit,
+ 0
+ );
+ }
+
+ //
+ // Setup I/O TLB entry.
+ //
+
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) (*PageFrameNumber++ << PAGE_SHIFT)
+ | PAGE_TABLE_ENTRY_VALID;
+ } // S001 ^^^
+#if 0
+ for(Ponce = 0;Ponce < HalpNumberOfPonce;Ponce++){
+ //
+ // I/O TLB Entry All Flush!!
+ //
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->TFLSR,
+ 0x1
+ );
+ }
+
+#else
+ //
+ // Invalidate the translation entry.
+ //
+ if(NumberOfPages >= PONCE_MAX_IOTLB_ENTRY){
+
+ for(Ponce = 0;Ponce < HalpNumberOfPonce;Ponce++){
+ //
+ // I/O TLB Entry All Flush!!
+ //
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->TFLSR,
+ 0x1
+ );
+ }
+ } else {
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // I/O TLB Entry Flush!!
+ //
+ for(Ponce = 0;Ponce <HalpNumberOfPonce;Ponce++){
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->TFLSR,
+ (Offset + i*PAGE_SIZE) & 0xFFFFF000 );
+ }
+ }
+ }
+#endif
+ //
+ // Are You BusMaster?. So Nothing to do anymore!!.
+ //
+ if ( AdapterObject == NULL) {
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+ // R98B
+ // Start the EISA DMA controller program.
+ // EISA DMA slave or ISA BusMaster or ISA Slave
+
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+
+
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+
+ ULONG i;
+ UCHAR DataByte;
+
+ if (AdapterObject == NULL) {
+
+ //
+ // This is a master adadapter so there is nothing to do.
+ //
+
+ return(TRUE);
+ }
+
+
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return(TRUE);
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+ KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ return(count);
+}
+
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+ }
+
+ //
+ // Save the map register base.
+ //
+
+ HalpMapRegisterPhysicalBase = PhysicalAddress;
+
+ // S001 vvv
+ HalpLogicalAddressLimit = (DMA_TRANSLATION_LIMIT / sizeof(TRANSLATION_ENTRY)) << PAGE_SHIFT;
+#if DBG
+ DbgPrint("HAL: HalpLogicalAddressLimit = 0x%x\n",HalpLogicalAddressLimit);
+#endif
+ // S001 ^^^
+}
diff --git a/private/ntos/nthals/halr98b/mips/rxinfo.c b/private/ntos/nthals/halr98b/mips/rxinfo.c
new file mode 100644
index 000000000..2d616d754
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxinfo.c
@@ -0,0 +1,95 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ rxinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History
+
+--*/
+
+
+#include "halp.h"
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
diff --git a/private/ntos/nthals/halr98b/mips/rxint.s b/private/ntos/nthals/halr98b/mips/rxint.s
new file mode 100644
index 000000000..e2604fc68
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxint.s
@@ -0,0 +1,1564 @@
+//
+// TITLE("Interrupts service routine")
+//++
+//
+// Copyright (c) 1994 Kobe NEC Software
+//
+// Module Name:
+//
+// rxint.s
+//
+// Abstract:
+//
+//
+// Author:
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//
+//--
+
+#include "halmips.h"
+#include "r98bdef.h"
+
+
+
+ SBTTL("HalpNmiHandler")
+//++
+// K001
+// Routine Description:
+//
+// This routine is reset status Register on NMI.
+// Return from this function EIF Interrupt Occur!!
+// Argments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpNmiHandler)
+ .set noat
+ .set noreorder //
+
+ //
+ // reset NMIR register, set NMI flag and save CPU register.
+ //
+
+ li k0,0xb9800388 // Set Colombs STSR local address
+ li k1,0x08080000 // Disable NMI
+ sw k1,0x0(k0) // store value
+ la k0,HalpSvpAlive // SVP check
+ lw k1,0x0(k0)
+ nop
+ beq k1,zero,10f
+ nop
+ la k0,HalpLogLock
+3: ll k1,0(k0) // get current lock value
+ bne zero,k1,3b // if ne, spin lock owned
+ nop
+ li k1,0x1
+ sc k1,0(k0) // set spin lock owned
+ beq zero,k1,3b // if eq, store conditional failure
+ nop
+ la k0,HalpSvpGlobal // NMI clear
+ lw k1,0x0(k0)
+ li k0,0x80
+ sb k0,0x42(k1)
+ sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ la k0,HalpSvpWindow2 // Nmi para clear
+ lw k1,0x0(k0)
+ lb k0,0xe6(k1)
+ sync
+ la k0,HalpSvpGlobal //Svp EIF MASK
+ lw k1,0x0(k0)
+ sb zero,0x49(k1)
+ sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ lb k0,0x58(k1) // Windows2 write lock
+ la k1,HalpNmiSvp
+ sw k0,0x0(k1)
+ sync
+ la k0,HalpSvpGlobal
+ lw k1,0x0(k0)
+ li k0,0xff
+ sb k0,0x58(k1)
+ sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ la k0,HalpSvpWindow2 // Nmi para clear
+ lw k1,0x0(k0)
+4:
+ sb zero,0xe6(k1)
+ sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ lb k0,0xe6(k1)
+ bne zero,k0,4b
+ nop
+ la k0,HalpNmiSvp // Svp Window2 lock
+ lw k1,0x0(k0)
+ la k0,HalpSvpGlobal
+ lw k0,0x0(k0)
+ nop
+ sb k1,0x58(k0)
+ sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ la k0,HalpLogLock // ZERO CLEAR
+ sw zero,0x0(k0)
+ nop
+
+// spinlock
+// lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread
+#if 0
+ la k0,HalpLogLock
+5: ll k1,0(k0) // get current lock value
+ bne zero,k1,5b // if ne, spin lock owned
+ nop
+ li k1,0x1
+ sc k1,0(k0) // set spin lock owned
+ beq zero,k1,5b // if eq, store conditional failure
+ nop
+#endif
+
+//
+// Check it DUMP Key or Power SW
+// To Checked Interrupt cause SetUp MRCMODE to PowerSW Interrupt mode.
+//
+
+10:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k0, (k0)
+ li k1, 0x40
+ and k1,k0,k1
+ bne zero,k1,10b
+ nop
+//
+// Local Device Lock Complete
+//
+#if 1 //SVP
+//
+// when EXTNMI happend. which NMI DUMP Key or SVP
+//
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //MRCMODE Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x08 //MRCMODE li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x18 //Read Command
+ sb k1, (k0)
+
+
+99:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, 99b
+ nop
+
+ li k0, 0xbf0f0020 //LBDT addr
+ lb k0, (k0) //Read MRMODE Register Value
+
+
+ li k1,0x2 //MRCMODE register DUMP Bit
+ and k1,k0,k1
+ bne zero,k1,Dump // if neq --> dump key
+ nop
+ nop
+
+
+// Save CPU Register Context
+//
+//
+#if 0
+ li k0,0xb9800310 // get Colombs REVR Local Address
+ lw k0 ,0x0(k0) // get value
+
+ li k1,0x03000000 // NODE Bit Mask. But low 2 bit only
+ and k0,k0,k1 // Get NODE Bit Only
+ srl k0,k0,17 // shift right 17(23 - 6) bit for offset
+
+ la k1,HalpNmiSvp // get performance counter address
+ addu k0,k0,k1 // compute address of nmi buffer
+ lw k1,0x0(k0)
+ addi k1,k1,1
+ sw k1,0x0(k0)
+ nop
+ nop
+//#endif
+ la k0,HalpSvpAlive // SVP check
+ lw k1,0x0(k0)
+ nop
+ beq k1,zero,5f
+ nop
+ la k0,HalpLogLock
+3: ll k1,0(k0) // get current lock value
+ bne zero,k1,3b // if ne, spin lock owned
+ nop
+ li k1,0x1
+ sc k1,0(k0) // set spin lock owned
+ beq zero,k1,3b // if eq, store conditional failure
+ nop
+ la k0,HalpSvpGlobal //Svp Windows2 lock
+ lb k1,0x58(k0)
+ la k0,HalpNmiSvp
+ sb k1,0x0(k0)
+ sync
+ la k0,HalpSvpGlobal
+ li k1,0xff
+ sb k1,0x58(k0)
+ sync
+ la k0,HalpSvpWindow2 // Nmi para clear
+ lb k1,0xe6(k1)
+ sb zero,0xe6(k0)
+ sync
+ la k0,HalpNmiSvp // Svp Window2 lock
+ lb k1,0x0(k0)
+ la k0,HalpSvpGlobal
+ sb k1,0x58(k0)
+ sync
+ la k0,HalpLogLock // ZERO CLEAR
+ sw zero,0x0(k0)
+ nop
+#endif
+ j 25f
+ nop
+
+
+
+Dump:
+#endif
+ la k0,HalpDumpFlag
+ li k1,0x01
+ sw k1,0x0(k0)
+
+
+
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //MRCMODE Addr Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x08 //MRCMODE Addr li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0020 //LBDT addr
+ li k1, 0x80 //
+ sb k1, (k0) //
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x10 //Write Command
+ sb k1, (k0)
+
+20:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, 20b
+ nop
+25:
+
+//
+// MRCMODE Setuped to MRCINT mode.
+// So Check DUMP Key or Power Switch
+
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //MRCINT Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x00 //MRCINT li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x18 //Read Command
+ sb k1, (k0)
+
+
+50:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, 50b
+ nop
+
+
+ li k0, 0xbf0f0020 //LBDT addr
+ lb k0, (k0) //Read MRCINT Register Value
+
+ li k1,0x4 //MRCINT register OFFSW Bit
+ and k1,k0,k1
+ beq zero,k1,DumpKey // if eq --> Not Power SW. it is DUMP Key.
+ nop
+ nop
+
+
+#if DBG
+
+
+ li k0,0xb9800310 // get Colombs REVR Local Address
+ lw k1 ,0x0(k0) // get value
+ li k0,0x03000000 // NODE Bit Mask. But low 2 bit only
+
+ and k0,k0,k1 // Get NODE Bit Only
+ srl k1,k0,22 // shift right 24>> <<2 bit for offset
+
+ la k0,HalpResetCount // get address
+ addu k0,k0,k1 // compute address of nmihappend buffer
+ lw k1,0x0(k0)
+ addi k1,k1,1
+ sw k1,0x0(k0)
+ nop
+#endif
+
+
+//
+// This Is Power Switch NMI so Power down.
+//
+
+resetloop:
+
+
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //Power S/W Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x30 //Power S/W li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0020 //LBDT addr
+ li k1, 0x01 //Set Power SW OFF
+ sb k1, (k0)
+
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x10 //Write Command
+ sb k1, (k0)
+
+
+poll6:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, poll6
+ nop
+
+ j resetloop
+ nop
+ nop
+
+//
+// This Is DUMP KEY NMI
+//
+DumpKey:
+
+
+//
+// Early time I was crashed ?
+//
+ li k0,0xb9800310 // get Colombs REVR Local Address
+ lw k1 ,0x0(k0) // get value
+ li k0,0x03000000 // NODE Bit Mask. But low 2 bit only
+
+ and k0,k0,k1 // Get NODE Bit Only
+ srl k1,k0,22 // shift right 24>> <<2 bit for offset
+
+ la k0,HalpNMIHappend // get address
+ addu k0,k0,k1 // compute address of nmihappend buffer
+ lw k1,0x0(k0)
+ nop
+ nop
+
+ beq zero,k1,doeif //if eq it was first time dump key.
+ nop
+ nop
+
+ //
+ // Setup DUMP Key And Power Key to NMI
+ //
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //MRCMODE Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x08 //MRCMODE li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0020 //LBDT addr
+ li k1, 0x0 //DUMP KEY Reset.
+ sb k1, (k0) //
+
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x10 //Write Command
+ sb k1, (k0)
+
+34:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, 34b
+ nop
+
+
+
+#if DBG
+
+ li k0,0xb9800310 // get Colombs REVR Local Address
+ lw k1 ,0x0(k0) // get value
+ li k0,0x03000000 // NODE Bit Mask. But low 2 bit only
+
+ and k0,k0,k1 // Get NODE Bit Only
+ srl k1,k0,22 // shift right 24>> <<2 bit for offset
+
+ la k0,HalpNMISecond // get address
+ addu k0,k0,k1 // compute address of nmihappend buffer
+ lw k1,0x0(k0)
+ addi k1,k1,1
+ sw k1,0x0(k0)
+
+#endif
+
+
+nomakeeif:
+ //
+ // UnLock
+ //
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x80 //
+ sb k1, (k0)
+ nop
+ nop
+
+ // CHIPSet Reset
+ // This version implement of EXNMI Only.
+ //
+ //
+
+ li k0,0xb9800038 // get Colombs NMIRST Local Address
+ li k1,0xf // Bit Reset
+ sw k1,(k0) // reset nmi
+
+
+ li k0,0xb9800388 // Set Colombs STSR local address
+ li k1,0x00080000 // Enable NMI
+ sw k1,0x0(k0) // store value
+ nop
+
+ // CPU Reset.
+ // This is a test code.
+ // We must clear BEV bit of psr register.
+ //
+
+ mfc0 k1,psr // get psr
+ li k0,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and k1,k1,k0 //
+ nop //
+ nop //
+ mtc0 k1,psr // set psr
+ nop // fill
+ nop //
+ nop //
+ nop
+ eret // return to errorepc
+ nop
+ nop
+ nop
+ eret // errata
+ nop
+
+
+// This Is First NMI By DUMP Key.
+// Save CPU Context. And Markd.
+// And Make EIF!!
+//
+doeif:
+ addi k1, k1, 0x1 // mark set.
+ nop
+ sw k1, 0x0(k0) // HalpNMIHappend[NODE] = 1
+ nop
+
+ //
+ // MRCMODE Register Set Up For Next NMI (DumpKey and PoeHwerSW)
+ //
+#if 0
+
+
+ //
+ // MRCINT Clear
+ //
+ nop
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //MRCINT Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x00 //MRCINT li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0020 //LBDT addr
+ li k1, 0x0 //Reset PowerOff Interrupt
+ sb k1, (k0)
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x10 //Write Command
+ sb k1, (k0)
+
+
+250:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, 250b
+ nop
+
+#endif
+
+
+ //
+ // Reset NMI
+ //
+ li k0, 0xbf0f0018 //LBADH addr
+ li k1, 0x02 //MRCMODE Hi
+ sb k1, (k0)
+
+ li k0, 0xbf0f0010 //LBADL addr
+ li k1, 0x08 //MRCMODE li
+ sb k1, (k0)
+
+ li k0, 0xbf0f0020 //LBDT addr
+ li k1, 0x0 //DUMP KEY Reset.
+ sb k1, (k0) //
+
+
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x10 //Write Command
+ sb k1, (k0)
+
+64:
+ li k0, 0xbf0f0000 //LBCTL addr
+ lb k1, (k0) //LBCTL read
+ li k0, 0x10 //CMD Bit
+ and k1,k0,k1
+ bne zero,k1, 64b
+ nop
+
+
+
+#if 0
+
+ //
+ // SetUp NMIFlag for rxeif.c
+ //
+ la k0,HalpNMIFlag // set NMI flag address
+ li k1,0xb9800030 // set Colombs NMIR local address
+ lw k1,(k1) // get NMIR register value
+ //
+ // N.B NMIR register high 16 bit is RFU.
+ // so used s/w flag for Hal.
+ sw k1,(k0) // store NMIR regiser value to HalpNmiFlag
+
+
+
+//
+// UnLock Local Device
+//
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x80 //
+ sb k1, (k0)
+
+#endif
+
+
+// Save CPU Register Context
+//
+//
+ li k0,0xb9800310 // get Colombs REVR Local Address
+ lw k0 ,0x0(k0) // get value
+
+ li k1,0x03000000 // NODE Bit Mask. But low 2 bit only
+ and k0,k0,k1 // Get NODE Bit Only
+ srl k0,k0,16 // shift right 16(23 - 5) bit for offset
+
+ la k1,HalpNMIBuf // get performance counter address
+ addu k0,k0,k1 // compute address of nmi buffer
+
+// sw at,0x0(k0) // register save.0
+ sw v0,0x4(k0) // 1
+ sw v1,0x8(k0) // 2
+ sw a0,0xc(k0) // 3
+ sw a1,0x10(k0) // 4
+ sw a2,0x14(k0) // 5
+ sw a3,0x18(k0) // 6
+ sw t0,0x1c(k0) // 7
+ sw t1,0x20(k0) // 8
+ sw t2,0x24(k0) // 9
+ sw t3,0x28(k0) // 10
+ sw t4,0x2c(k0) // 11
+ sw t5,0x30(k0) // 12
+ sw t6,0x34(k0) // 13
+ sw t7,0x38(k0) // 14
+ sw t8,0x3c(k0) // 15
+ sw t9,0x40(k0) // 16
+ sw gp,0x44(k0) // 17
+ sw sp,0x48(k0) // 18
+ sw s8,0x4c(k0) // 19
+ sw ra,0x50(k0) // 20
+
+ mfc0 k1,psr // 21
+ sw k1,0x54(k0) //
+ mfc0 k1,cause // 22
+ sw k1,0x58(k0) //
+ mfc0 k1,epc // 23
+ sw k1,0x5c(k0) //
+ mfc0 k1,errorepc // 24
+ sw k1,0x60(k0) //
+
+
+
+#if 1 //ras
+
+ sw s0,0x64(k0) // 25
+ sw s1,0x68(k0) // 26
+ sw s2,0x6c(k0) // 27
+ sw s3,0x70(k0) // 28
+ sw s4,0x74(k0) // 29
+ sw s5,0x78(k0) // 30
+ sw s6,0x7c(k0) // 31
+ sw s7,0x80(k0) // 32
+
+ mfc0 k1,entrylo0 //
+ sw k1,0x84(k0) // 33
+
+ mfc0 k1,entrylo1 //
+ sw k1,0x88(k0) // 34
+
+ mfc0 k1,badvaddr //
+ sw k1,0x8c(k0) // 35
+
+ mfc0 k1,entryhi
+ sw k1,0x90(k0) // 36
+
+
+ mfc0 k1,pagemask
+ sw k1,0x94(k0) // 37
+
+ mfc0 k1,prid
+ sw k1,0x98(k0) // 38
+
+ mfc0 k1,config
+ sw k1,0x9c(k0) // 39
+
+ mfc0 k1,lladdr
+ sw k1,0xa0(k0) // 40
+
+ mfc0 k1,watchlo
+ sw k1,0xa4(k0) // 41
+
+ mfc0 k1,watchhi
+ sw k1,0xa8(k0) // 42
+
+ mfc0 k1,$20 //xcontext
+ sw k1,0xac(k0) // 43
+
+ mfc0 k1,ecc
+ sw k1,0xb0(k0) // 44
+
+ mfc0 k1,cacheerr
+ sw k1,0xb4(k0) // 45
+
+ mfc0 k1,taglo
+ sw k1,0xb8(k0) // 46
+
+ mfc0 k1,taghi
+ sw k1,0xbc(k0) // 47
+
+#endif
+
+#if 0
+//
+// Copy CPU state to NvRAM.
+//
+
+ li t0,0xb9800388 // Set Colombs STSR local address
+ li t1,0x00040000 // Enable write to NvRam
+ sw t1,0x0(t0) // store value
+
+ li t0,0xb9800310 // get Colombs REVR Local Address
+ lw t0,0x0(t0) // get value
+
+ li t1,0x03000000 // NODE Bit Mask. But low 2 bit only
+ and t0,t0,t1 // Get NODE Bit Only
+ srl t0,t0,16 // shift right 16(23 - 5) bit for offset
+
+ li t1,0xbf09dc00
+ addu t0,t0,t1 // compute address of nmi buffer
+ move t1,k0 // src address
+ li t2,0x100 // calc end address
+ addu t2,t2,t0
+
+cploop:
+ lb t3,0(t1)
+ addiu t1,t1,1
+ sb t3,0(t0)
+ addiu t0,t0,1
+ bne t2,t0,cploop
+ nop
+
+ lw t0,0x1c(k0) // 7
+ lw t1,0x20(k0) // 8
+ lw t2,0x24(k0) // 9
+ lw t3,0x28(k0) // 10
+#endif
+
+#if 1
+ //
+ // SetUp NMIFlag for rxeif.c
+ //
+ la k0,HalpNMIFlag // set NMI flag address
+ lw k1,(k0) // get HalpNmiFlag
+ bne zero,k1, nomakeeif
+ nop
+
+ li k1,0xb9800030 // set Colombs NMIR local address
+ lw k1,(k1) // get NMIR register value
+ //
+ // N.B NMIR register high 16 bit is RFU.
+ // so used s/w flag for Hal.
+ sw k1,(k0) // store NMIR regiser value to HalpNmiFlag
+
+#endif
+
+ //
+ // UnLock
+ //
+ li k0, 0xbf0f0000 //LBCTL addr
+ li k1, 0x80 //
+ sb k1, (k0)
+
+ // CHIPSet Reset
+ // This version implement of EXNMI Only.
+ //
+ //
+
+ li k0,0xb9800038 // get Colombs NMIRST Local Address
+ li k1,0xf // Bit Reset
+ sw k1,(k0) // reset nmi
+
+
+ li k0,0xb9800388 // Set Colombs STSR local address
+ li k1,0x00080000 // Enable NMI
+ sw k1,0x0(k0) // store value
+ nop
+
+
+ // CPU Reset.
+ // This is a test code.
+ // We must clear BEV bit of psr register.
+ //
+
+ mfc0 k1,psr // get psr
+ li k0,0xffbfffff // clear BEV bit
+ nop // fill
+ nop // fill
+ and k1,k1,k0 //
+ nop //
+ nop //
+ mtc0 k1,psr // set psr
+ nop // fill
+ nop //
+ nop //
+
+ //
+ // Do EIF to Myself.
+ //
+ //
+
+
+ li k0,0xb9800310 // get Colombs REVR Local Address
+ lw k0 ,0x0(k0) // get value
+
+ li k1,0x03000000 // NODE Bit Mask. node 4-7
+ and k0,k0,k1 // Get NODE Bit Only (lower 3 Bit Only)
+ srl k0,k0,24 // Convert CPU number
+
+ li k1,0x00080000 // Node 4 set
+ srl k1,k1,k0 // make Node Bit (NODE 4 >> CpuNumber)
+
+
+ li k0,0x82000000 // OP bit And Atlantic code 0x2 = EIF
+ or k1,k1,k0 // make OP Bit And CODE And NODE
+
+
+ li k0,0xb9800580 // get Colombs IntIR Local Address
+ sw k1,(k0) //
+
+ nop
+ nop
+ eret // return to errorepc
+ nop
+ nop
+ nop
+ eret // errata
+ nop
+ nop // for interrupt cache aligned line
+ nop
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+
+ .end HalpNmiHandler
+
+
+
+
+ SBTTL("Int 1 Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 1 interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInt1Dispatch)
+
+ move a0,s8 // trap frame
+ li a1,0x1 // Interrupt is INT1
+ j HalpGeneralDispatch
+
+ .end
+
+ SBTTL("Int 2 Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 2 interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInt2Dispatch)
+
+ move a0,s8 // trap frame
+ li a1,0x2 // Interrupt is INT2
+ j HalpGeneralDispatch
+
+ .end
+
+ SBTTL("Int 3 Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 3 interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInt3Dispatch)
+
+ move a0,s8 // trap frame
+ li a1,0x3 // Interrupt is INT3
+ j HalpGeneralDispatch
+
+ .end
+
+ SBTTL("Int 4 Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 4 interrupt.
+//
+// This routine checks for IPI interrupt. The IPI interrupt is
+// ip[5] on the R98B and ip[6] on the R98A. So this routine
+// reads the cause register to determine correct dispatch function
+//
+// CAVEAT: This is an R98B specific routine. It is only
+// called on an R98B.
+// CAVEAT: This routine is only used on NT 4.0 because Nt3.51 does
+// not have SYNC IRQL
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#if defined(NT_40)
+
+//
+// SYNCH Level must enable IPI on R98B.
+// Sync level enable IPI on R98A .
+// But on R98B, Sync level disable IPI.
+// So, on R98B, we need to change Irql mask table.
+// Hal determines IPI or EIF here.
+// Because when IPI occured, HAl returns same IRQL value from EIF.
+// v-masank@microsoft.com 5/11/96
+// Thanks for samejima's comments
+// I change that following function is for R98B only.
+// Because R98A does not need following function.
+// v-masank@microsoft.com 5/21/96
+//
+ LEAF_ENTRY(HalpT5Int4Dispatch)
+
+ move a0,s8 // trap frame
+ READ_CAUSE_REGISTER(t0) // Read Cause register
+ and t0,t0,0x00004000 // INT4 ?
+ bne t0,zero,10f // ne INT4
+ li a1,0x3 // INT3
+ j HalpGeneralDispatch
+
+10:
+ li a1,0x4 // Interrupt is INT4
+ j HalpGeneralDispatch
+ .end
+#endif
+
+
+
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 4 interrupt.
+//
+// CAVEAT: This routine used by R98A on NT 3.51 and NT4.0
+// This routine used by R98B on NT 3.51
+//
+// CAVEAT: This routine is only used on NT 3.51 because Nt3.51 does
+// not have SYNC IRQL
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInt4Dispatch)
+
+ move a0,s8 // trap frame
+ li a1,0x4 // Interrupt is INT4
+ j HalpGeneralDispatch
+
+ .end
+
+ SBTTL("Read Cause Register")
+//++
+// S005
+// Routine Description:
+//
+// This routine is get of cause register
+//
+// Argments:
+//
+// None.
+//
+// Return Value:
+//
+// cause rezister value.
+//
+//--
+
+ LEAF_ENTRY(HalpGetCause)
+
+ READ_CAUSE_REGISTER(v0)
+
+ j ra // return
+
+ .end HalpGetCause
+
+
+
+ SBTTL("Int 0 Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 1 interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInt0Dispatch)
+
+ move a0,s8 // trap frame
+ li a1,0x0 // Interrupt is INT0
+ j HalpGeneralDispatch
+
+ .end
+
+
+
+ SBTTL("Int 5 Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an Int 1 interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInt5Dispatch)
+
+ move a0,s8 // trap frame
+ li a1,0x5 // Interrupt is INT5
+ j HalpGeneralDispatch
+
+ .end
+
+
+//#if 0
+// I use following function for performance.
+// v-masank@microsoft.com 5/21/96
+//++
+ SBTTL("Read Large Register")
+//
+// Routine Description:
+//
+// This routine is read of large register
+//
+// Argments:
+//
+// a0 - Virtual address
+//
+// a1 - pointer to buffer of large register
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReadLargeRegister)
+#if !defined(NT_40)
+ lw t2,0x0(a0) // get register(upper)
+ lw t3,0x4(a0) // get register(lower)
+
+ sw t2,0x0(a1) // set upper register value
+ sw t3,0x4(a1) // set lower register value
+#else
+ ld t2,0x0(a0) // get register
+ sd t2,0x0(a1) // set register
+#endif
+
+ j ra // return
+
+ .end HalpReadLargeRegister
+
+
+
+ SBTTL("Write Large Register")
+//++
+//
+// Routine Description:
+//
+// This routine is write of large register
+//
+// Argments:
+//
+// a0 - Virtual address
+//
+// a1 - pointer to value of large register
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteLargeRegister)
+
+#if !defined(NT_40)
+
+ lw t2,0x0(a1) // load register value
+ lw t3,0x4(a1) //
+
+ sw t2,0x0(a0) // set register value
+ sw t3,0x4(a0) //
+#else
+ ld t2,0x0(a1)
+ sd t2,0x0(a0)
+#endif
+
+ sync //
+
+ j ra // return
+
+ .end HalpWriteLargeRegister
+
+
+//#endif
+
+// S005 vvv
+ SBTTL("Read Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is read of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// Return Value:
+//
+// read data.
+//
+//--
+
+ LEAF_ENTRY(HalpReadPhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ lw v0,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadPhysicalAddress
+// S005 ^^^
+// S006 vvv
+ SBTTL("Write Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is Write of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// a1 - Write Data
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWritePhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ sw a1,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWritePhysicalAddress
+
+
+ SBTTL("Read And Write Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is read and write of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// Return Value:
+//
+// read data.
+//
+//--
+
+ LEAF_ENTRY(HalpReadAndWritePhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ lw v0,0(t0)
+ sw v0,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadAndWritePhysicalAddress
+// S006 ^^^
+
+
+#if 0 //koredmo ugoku kedo waikomi disable ha amari yokuarimasenn....
+
+//++
+//
+// VOID
+// READ_REGISTER_ULONGLONG (
+// IN PLARGE_INTEGER RegisterAddress,
+// IN PVOID Variable
+// )
+//
+// Routine Description:
+//
+// 64-bit register read function.
+//
+// Arguments:
+//
+// RegisterAddress (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Variable (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Return Value:
+//
+// None.
+//
+// Destination and Source must be 8-byte aligned.
+//
+//--
+
+#if 1
+ .struct 0
+sv1f0: .space 4*2
+Length1F0:
+ NESTED_ENTRY(READ_REGISTER_ULONGLONG, Length1F0, zero)
+ subu sp,sp,Length1F0 // allocate stack frame
+ DISABLE_INTERRUPTS(t7) // disable interrupts
+ sdc1 f0,sv1f0(sp) // f0 save
+#else
+ LEAF_ENTRY(READ_REGISTER_ULONGLONG)
+#endif
+
+ ldc1 f0,0(a0) // move 8-byte block
+ sdc1 f0,0(a1) //
+#if 1
+ ldc1 f0,sv1f0(sp) // f0 resume
+ addu sp,sp,Length1F0 // deallocate stack frame
+ ENABLE_INTERRUPTS(t7) // enable interrupts
+#endif
+
+ sync // synchronize read
+
+ j ra // return
+
+ .end READ_REGISTER_ULONGLONG
+
+
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONGLONG (
+// IN PLARGE_INTEGER RegisterAddress,
+// IN PVOID Variable
+// )
+//
+// Routine Description:
+//
+// 64-bit I/O space register write function.
+//
+// Arguments:
+//
+// RegisterAddress (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Variable (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Return Value:
+//
+// None.
+//
+// Destination and Source must be 8-byte aligned.
+//
+//--
+
+#if 1
+ .struct 0
+sv2f0: .space 4*2
+Length2F0:
+ NESTED_ENTRY(WRITE_REGISTER_ULONGLONG, Length2F0, zero)
+ subu sp,sp,Length2F0 // allocate stack frame
+ DISABLE_INTERRUPTS(t7) // disable interrupts
+ sdc1 f0,sv2f0(sp) // f0 save
+#else
+ LEAF_ENTRY(WRITE_REGISTER_ULONGLONG)
+#endif
+
+ ldc1 f0,0(a1) // move 8-byte block
+ sdc1 f0,0(a0) //
+#if 1
+ ldc1 f0,sv2f0(sp) // f0 resume
+ addu sp,sp,Length2F0 // deallocate stack frame
+ ENABLE_INTERRUPTS(t7) // enable interrupts
+#endif
+
+ sync // synchronize write
+
+ j ra // return
+
+ .end WRITE_REGISTER_ULONGLONG
+
+#else //korede warikomi ha enable no mama syori dekimasu.
+//
+//
+//
+//
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+Rt7: .space 4
+Rt8: .space 4
+
+LengthRtN:
+
+ NESTED_ENTRY(READ_REGISTER_ULONGLONG, LengthRtN, zero)
+// DISABLE_INTERRUPTS(t9) // disable interrupts
+ subu sp,sp,LengthRtN // allocate stack frame
+
+
+ PROLOGUE_END
+ sw t7,Rt7(sp)
+ sw t8,Rt8(sp)
+
+ lw t7,0x0(a0)
+ lw t8,0x4(a0)
+
+ sw t7,0x0(a1)
+ sw t8,0x4(a1)
+
+ lw t7,Rt7(sp)
+ lw t8,Rt8(sp)
+
+ addu sp,sp,LengthRtN // deallocate stack frame
+// ENABLE_INTERRUPTS(t9) // enable interrupts
+ sync // synchronize read
+
+ j ra // return
+
+ .end READ_REGISTER_ULONGLONG
+
+//
+//
+//
+//
+ .struct 0
+DiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+Wt7: .space 4
+Wt8: .space 4
+
+LengthWtN:
+
+ NESTED_ENTRY(WRITE_REGISTER_ULONGLONG, LengthWtN, zero)
+// DISABLE_INTERRUPTS(t9) // disable interrupts
+ subu sp,sp,LengthWtN // allocate stack frame
+
+
+ PROLOGUE_END
+
+ sw t7,Wt7(sp)
+ sw t8,Wt8(sp)
+
+ lw t7,0x0(a1)
+ lw t8,0x4(a1)
+ sw t7,0x0(a0)
+ sw t8,0x4(a0)
+
+ lw t7,Wt7(sp)
+ lw t8,Wt8(sp)
+
+ addu sp,sp,LengthWtN // deallocate stack frame
+// ENABLE_INTERRUPTS(t9) // enable interrupts
+ sync // synchronize read
+
+ j ra // return
+
+ .end WRITE_REGISTER_ULONGLONG
+
+#endif
+
+
+ SBTTL("T5 Int 5 Interrupt")
+//
+// On the R98B (r10k) this hardware interrupt is for the internal timer
+// interrupt. This is not used for the PROFILE interrupt on the R98B
+//
+
+//
+// InternalTimer interrupt does not use for profile interrupt.
+// So,Here is only clear internal interrupt.
+// v-masank@microsoft.com
+
+ LEAF_ENTRY(HalpT5Int5Dispatch)
+
+ .set noreorder
+ .set noat
+// mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+// addu t1,t1,8 // factor in lost cycles
+// subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ nop
+ nop
+ .set at
+ .set reorder
+
+ move a0,s8 // trap frame
+ li a1,0x5 // Interrupt is INT5
+ j HalpGeneralDispatch
+
+ .end HalpT5Int5Dispatch
+
+
diff --git a/private/ntos/nthals/halr98b/mips/rxipiint.s b/private/ntos/nthals/halr98b/mips/rxipiint.s
new file mode 100644
index 000000000..c3e99ffd2
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxipiint.s
@@ -0,0 +1,79 @@
+// TITLE("Interprocessor Interrupts")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// rxipiint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a MIPS R98 system.
+//
+// Author:
+//
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt.
+// Its function is to acknowledge the interrupt and transfer control to
+// the standard system routine to process interprocessor requrests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame at hal first dispatch
+// a0 - Supplies a pointer to a trap frame at kernel trap frame
+// a1 - intx
+// Return Value:
+//
+// None.
+//
+//--
+// secondary
+
+ .struct 0
+ //
+liArgs: .space 4 * 4 // saved arguments
+IiS8: .space 4 //
+IiRa: .space 4 //
+IiFrameLength: //
+
+ NESTED_ENTRY(HalpIpiInterrupt, IiFrameLength, zero)
+
+ subu sp,sp,IiFrameLength // allocate stack frame
+ sw s8,IiS8(sp) // save s8
+ sw ra,IiRa(sp) // save Ra
+
+ PROLOGUE_END
+
+ or s8,a0,zero // set up trapframe to s8
+ // KeIpiInterrupt require trapframe at s8
+
+ lw t1,__imp_KeIpiInterrupt // process interprocessor requests
+ jal t1 //
+
+ lw ra,IiRa(sp) // restore ra
+ lw s8,IiS8(sp) // restore s8
+ addu sp,sp,IiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpIpIInterrupt
+
+
diff --git a/private/ntos/nthals/halr98b/mips/rxisabus.c b/private/ntos/nthals/halr98b/mips/rxisabus.c
new file mode 100644
index 000000000..abc396c95
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxisabus.c
@@ -0,0 +1,729 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
+#pragma alloc_text(PAGE,HalpGetEisaData)
+#endif
+
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
+ // up on IRQ 9.
+ //
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ *Irql = (KIRQL)(INT0_LEVEL+HalpIntLevelofIpr[HalpMachineCpu][EISA_DISPATCH_VECTOR-DEVICE_VECTORS]);
+ *Affinity = 0x1 <<HalpResetValue[EISA_DISPATCH_VECTOR-DEVICE_VECTORS].Cpu;
+
+ //
+ // Get parent's translation from here..
+ //
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+}
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+BOOLEAN
+HalpTranslateIsaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+#if 1
+ PHYSICAL_ADDRESS BusAddressTmp;
+#endif
+ //
+ // Translated normally
+ //
+#if defined(DBG1)
+ DbgPrint("Hal: Trans ISA IN\n");
+#endif
+
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+#if DBG
+// DbgPrint("Hal: Trans ISA IN 2 Status = 0x%x\n",Status);
+#endif
+
+
+ //
+ // If it could not be translated, and it's memory space
+ // then we allow the translation as it would occur on it's
+ // corrisponding EISA bus. We're allowing this because
+ // many VLBus drivers are claiming to be ISA devices.
+ // (yes, they should claim to be VLBus devices, but VLBus is
+ // run by video cards and like everything else about video
+ // there's no hope of fixing it. (At least according to
+ // Andre))
+ //
+
+ if (Status == FALSE && *AddressSpace == 0) {
+#if DBG
+// DbgPrint("Hal: Trans ISA IN3\n");
+#endif
+
+ Status = HalTranslateBusAddress (
+ Eisa,
+ BusHandler->BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+ //
+ // Add BackWard Compatibility.
+ //
+ //
+#if 1
+ else
+
+ //
+ // If it could not be translated, and It's ISA Alias at Eisa Slot
+ // range then (for compatibility) try translating it on the
+ // dummy slot io range
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 1 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0x4000 &&
+ BusAddress.LowPart <= 0xFFFF) {
+
+#if DBG
+// DbgPrint("Isa Low ffffffffff= 0x%x\n",BusAddress.LowPart);
+// DbgPrint("Isa Hig ffffffffff= 0x%x\n",BusAddress.HighPart);
+// DbgPrint("Isa add ffffffffff= 0x%x\n", *AddressSpace);
+
+#endif
+ BusAddressTmp.LowPart = BusAddress.LowPart;
+ BusAddressTmp.LowPart &= 0x0fff;
+ BusAddressTmp.LowPart |= 0x4000;
+ BusAddressTmp.HighPart = 0 ;
+
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddressTmp,
+ AddressSpace,
+ TranslatedAddress
+ );
+#if DBG
+// DbgPrint("EIsa Low = 0x%x\n",TranslatedAddress->LowPart);
+// DbgPrint("EIsa Hig = 0x%x\n",TranslatedAddress->HighPart);
+// DbgPrint("EIsa add = 0x%x\n", *AddressSpace);
+// DbgPrint("Eisa Status = 0x%x\n", Status);
+#endif
+
+ }
+#endif
+
+
+
+#if defined(DBG)
+// DbgPrint("Hal: Trans ISA Out\n");
+
+// DbgPrint("Isa Low = 0x%x\n",BusAddress.LowPart);
+// DbgPrint("Isa Hig = 0x%x\n",BusAddress.HighPart);
+// DbgPrint("Isa add = 0x%x\n", *AddressSpace);
+// DbgPrint("Isa TLow = 0x%x\n",TranslatedAddress->LowPart);
+// DbgPrint("Isa THig = 0x%x\n",TranslatedAddress->HighPart);
+// DbgPrint("Isa Status = 0x%x\n", Status);
+
+
+#endif
+
+
+ return Status;
+}
+
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+#if 1
+ PHYSICAL_ADDRESS BusAddressTmp;
+#endif
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's in the 640k - 1m
+ // range then (for compatibility) try translating it on the
+ // Internal bus for
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 0 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0xA0000 &&
+ BusAddress.LowPart < 0xFFFFF) {
+
+ Status = HalTranslateBusAddress (
+ Internal,
+ 0,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+ //
+ // Add BackWard Compatibility.
+ //
+ //
+#if 1
+
+ else
+
+
+ //
+ // If it could not be translated, and It's EISA Slot
+ // range then (for compatibility) try translating it on the
+ // dummy slot io range
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 1 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0x4000 &&
+ BusAddress.LowPart <= 0xFFFF) {
+
+#if DBG
+// DbgPrint("EIsa Low ffffffffff= 0x%x\n",BusAddress.LowPart);
+// DbgPrint("EIsa Hig ffffffffff= 0x%x\n",BusAddress.HighPart);
+// DbgPrint("EIsa add ffffffffff= 0x%x\n", *AddressSpace);
+#endif
+
+ BusAddressTmp.LowPart = BusAddress.LowPart;
+ BusAddressTmp.LowPart &= 0x0fff;
+ BusAddressTmp.LowPart |= 0x4000;
+ BusAddressTmp.HighPart = 0 ;
+
+
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddressTmp,
+ AddressSpace,
+ TranslatedAddress
+ );
+#if DBG
+// DbgPrint("EIsa Low = 0x%x\n",TranslatedAddress->LowPart);
+// DbgPrint("EIsa Hig = 0x%x\n",TranslatedAddress->HighPart);
+// DbgPrint("EIsa add = 0x%x\n", *AddressSpace);
+// DbgPrint("Eisa Status = 0x%x\n", Status);
+#endif
+
+ }
+#endif
+
+ return Status;
+}
+
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ PAGED_CODE ();
+
+#if DBG //SNES
+ DbgPrint("Halp Get Eisa DataOh!\n");
+#endif
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+#if DBG
+ DbgPrint("Halp Get EisaAdapter Key Open Complete !\n");
+#endif
+
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+#endif
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
diff --git a/private/ntos/nthals/halr98b/mips/rxnvr.h b/private/ntos/nthals/halr98b/mips/rxnvr.h
new file mode 100644
index 000000000..71824fe8c
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxnvr.h
@@ -0,0 +1,176 @@
+
+/*++
+
+Module Name:
+
+ rxnvr.h
+
+Abstract:
+
+ This module contains definitions for the R98B non-volatile ram structures.
+
+--*/
+
+
+#ifndef _RXNVR_
+#define _RXNVR_
+
+
+//
+// R98B Nvram Physicall Map
+//
+// 0x1f08 0000 +-------+
+// | 4K | POST/ITF and NMI Vector
+// 0x1f08 1000 +-------+
+// | 2K |
+// 0x1f08 1800 +-------+
+// | 2K | Free
+// 0x1f08 2000 +-------+
+// | 800B | Configuration Packet
+// 0x1f08 2320 +-------+
+// | 516B | Identifier
+// 0x1f08 2524 +-------+
+// | 2K | Configuration Data
+// 0x1f08 2d24 +-------+
+// | 4B | Checksum1
+// 0x1f08 2d28 +-------+
+// | 1K | Environment
+// 0x1f08 3128 +-------+
+// | 4BK | Checksum2
+// 0x1f08 312c +-------+
+// | 3796B | Reserved For ARC FW
+// 0x1f08 4000 +-------+
+// | 32K | H/W Logging field
+// 0x1f08 c000 +-------+
+// | 4K | Reserved
+// 0x1f08 d000 +-------+
+// | 4K | XXXXXX
+// 0x1f08 e000 +-------+
+// | 8B | Ethrnet Address
+// 0x1f08 e008 +-------+
+// | 2K | UP Area
+// 0x1f08 e800 +-------+
+// | 4092B | EISA Configuration
+// 0x1f08 f7fc +-------+
+// | 4B | Checksum3
+// 0x1f08 f800 +-------+
+// | 57K | Free
+// 0x1f09 dc00 +-------+
+// | 1K | Hal
+// 0x1f09 e000 +-------+
+// | 8K | ESM
+// 0x1f0a 0000 +-------+
+//
+
+
+
+// Define the private configuration packet structure, which contains a
+// configuration component as well as pointers to the component's parent,
+// peer, child, and configuration data.
+//
+
+typedef struct _CONFIGURATION_PACKET {
+ CONFIGURATION_COMPONENT Component;
+ struct _CONFIGURATION_PACKET *Parent;
+ struct _CONFIGURATION_PACKET *Peer;
+ struct _CONFIGURATION_PACKET *Child;
+ PVOID ConfigurationData;
+} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET;
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ USHORT Version;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+//
+// Defines for the volatile and non-volatile configuration tables.
+//
+
+#define NUMBER_OF_ENTRIES 50
+#define LENGTH_OF_IDENTIFIER 516
+#define LENGTH_OF_DATA 2048
+#define LENGTH_OF_ENVIRONMENT 1024
+#define LENGTH_OF_EISA_DATA 4092
+
+//
+// The volatile configuration table structure.
+//
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+//
+// The non-volatile configuration table structure.
+//
+
+
+typedef struct _NV_CONFIGURATION {
+
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; // 800B =16B * 50 Entry
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER]; // 516B
+ UCHAR Data[LENGTH_OF_DATA]; // 2048B
+
+ UCHAR Checksum1[4];
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT]; // 1024B
+ UCHAR Checksum2[4];
+ UCHAR ArcReserved[3796];
+ UCHAR HwLogging[1024 * 32];
+ UCHAR Reserved0[1024 * 4];
+ UCHAR Reserved1[1224 * 4];
+ UCHAR EthernetAddress[8];
+ UCHAR UPArea[1024 * 2];
+ UCHAR EisaData[LENGTH_OF_EISA_DATA]; // 4092B
+ UCHAR Checksum3[4];
+ UCHAR Reserved2[ 1024 * 57];
+ UCHAR Hal[ 1024];
+ UCHAR Esm[1024 * 8];
+// UCHAR NmiVector[4];
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+
+//
+// Nmi Vecter Address table structure. by kita
+//
+#define NMIVECTER_PHYSICAL_BASE 0x1F080000
+#define NMIVECTER_BASE (KSEG1_BASE + NMIVECTER_PHYSICAL_BASE)
+
+typedef struct _NVRAM_NMIVECTER {
+ UCHAR NotUsed[12];
+ UCHAR NmiVector[4];
+} NVRAM_NMIVECTER, *PNVRAM_NMIVECTER;
+
+
+
+//
+// Non-volatile ram layout.
+//
+
+#if defined(MIPS)
+
+#define NVRAM_CONFIGURATION NVRAM_VIRTUAL_BASE
+#define NVRAM_SYSTEM_ID NVRAM_VIRTUAL_BASE + 0x00002000
+
+#endif
+
+#endif // _RXNVR_
diff --git a/private/ntos/nthals/halr98b/mips/rxpcibrd.c b/private/ntos/nthals/halr98b/mips/rxpcibrd.c
new file mode 100644
index 000000000..37aef5f43
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxpcibrd.c
@@ -0,0 +1,1157 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ rxpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+//#define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN ULONG StartPciBus, //R98B
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+ ULONG Ponce;
+
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+ // This is Ponce Number;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ // R98B
+ //
+#if DBG
+ DbgPrint("HAL PCI StartPCIBusNo =0x%x\n",(ULONG)StartPciBus);
+ DbgPrint("HAL PCI MaxPciBus =0x%x\n",*MaxPciBus);
+#endif
+
+ for (BusNo=StartPciBus; BusNo < *MaxPciBus; BusNo++) {
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+#if DBG
+ DbgPrint("HAL PCI BusNo =0x%x\n",(ULONG)BusNo);
+// DbgPrint("HAL PCI brg =0x%x\n",(ULONG)CB.BusHandler);
+// DbgPrint("HAL PCI busdata =0x%x\n",(ULONG)CB.BusData);
+#endif
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+#if DBG
+ HalpTestPciPrintResult((PULONG)CB.PciData,PCI_COMMON_HDR_LENGTH );
+#if 0 //f/w debug
+
+ CB.PciData->Command = 0x7;
+
+ if(BusNo == 0 && CB.PciData->u.type1.SecondaryBus == 1){
+ CB.PciData->u.type1.IOBase = 0x50;
+ CB.PciData->u.type1.IOLimit = 0x60;
+
+ }else if(BusNo == 0 && CB.PciData->u.type1.SecondaryBus == 2 ){
+ CB.PciData->u.type1.IOBase = 0x70;
+ CB.PciData->u.type1.IOLimit = 0x80;
+ CB.PciData->u.type1.MemoryBase =0x0620;
+ CB.PciData->u.type1.MemoryLimit =0x0630;
+
+ }
+ else if(BusNo == 3 && CB.PciData->u.type1.SecondaryBus == 1 ){
+ CB.PciData->u.type1.IOBase = 0x40;
+ CB.PciData->u.type1.IOLimit = 0x50;
+
+ }
+ else if(BusNo == 3 && CB.PciData->u.type1.SecondaryBus == 2 ){
+ CB.PciData->u.type1.IOBase = 0x60;
+ CB.PciData->u.type1.IOLimit = 0x70;
+
+ CB.PciData->u.type1.MemoryBase =0x0620;
+ CB.PciData->u.type1.MemoryLimit =0x0630;
+
+
+// CB.PciData->u.type1.PrefetchBase = 0x0010;
+// CB.PciData->u.type1.PrefetchLimit= 0x0010;
+
+ }
+
+ HalpWritePCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+#if DBG
+ DbgPrint ("HAL Brdge fix -----------!!!\n");
+#endif
+// HalpReadPCIConfig (
+// CB.BusHandler,
+// CB.SlotNumber,
+// CB.PciData,
+// 0,
+// PCI_COMMON_HDR_LENGTH
+// );
+
+// HalpTestPciPrintResult((PULONG)CB.PciData,PCI_COMMON_HDR_LENGTH );
+
+#endif
+#endif
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+
+ // this PCI bridge is not enabled - skip it for now
+ DBGMSG ("HAL Bridge is not enable contineu!!!\n");
+ FoundDisabledBridge = TRUE;
+ continue;
+
+ }
+
+ // R98B First PCI Bus of Ponce Must be 0.
+ // So Convert System(NT) BusNumber to required BusNumber for PONCE.
+ //
+ Ponce = HalpPonceNumber(CB.BusHandler->BusNumber);
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber - HalpStartPciBusNumberPonce[Ponce]) {
+#if DBG
+ DbgPrint ("HAL GetPciData: bad BusNumber =0x%x!!!\n",(ULONG) CB.BusHandler->BusNumber);
+ DbgPrint ("HAL GetPciData: bad primarybus =0x%x!!!\n",(ULONG) CB.PciData->u.type1.PrimaryBus);
+ // what to do?
+#endif
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+#if DBG
+ DbgPrint ("HAL Bridge secondrybus =0x%x!!!\n",(ULONG) CB.PciData->u.type1.SecondaryBus);
+#endif
+
+ ChildBus = HalpHandlerForBus (PCIBus,
+ CB.PciData->u.type1.SecondaryBus+HalpStartPciBusNumberPonce[Ponce]
+ );
+
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus+HalpStartPciBusNumberPonce[Ponce] > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus+(UCHAR)HalpStartPciBusNumberPonce[Ponce]+1;
+ HalpStartPciBusNumberPonce[Ponce+1]++;
+ }
+ continue;
+ }
+
+ //
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+#if DBG
+ DbgPrint("Hal Bridge VGA Busnum =0x%x\n",ChildBus->BusNumber);
+#endif
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+#if DBG
+ DbgPrint("Hal Bridge 256 limit\n");
+#endif
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ (ULONG)0, // address space
+ (LONGLONG)(PCI_CNTL_PHYSICAL_BASE+ // system base
+ PCI_MAX_CNTL_SIZE * Ponce),
+ (LONGLONG)i, // bus address
+ (LONGLONG)(i + 256) // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+#if 1
+//
+// If F/W setup PrefetchBaseUpper32 == 0
+// This Bus Range add PrefetchMemory area. This Range not support..
+// Under Ponce #0. Memory area start 64MG so never append prefetch memory area.
+// But Punder Pnce 1#. Memory area start 0MG So append prefetch memory area by addrange.
+//
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+#if DBG
+ DbgPrint("Hal Bridge prefetch upper32\n");
+#endif
+
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+#endif
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+#if DBG
+ DbgPrint("HAL Fix Range 0\n");
+#endif
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+#if DBG
+ DbgPrint("HAL Fix Range 1\n");
+#endif
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+ //
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+#if DBG
+ DbgPrint("HAL Fix Range 2\n");
+#endif
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+#if DBG
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ DbgPrint("HAL: PCIBus#%d, MemBase=%x.%x, Lmt=%x.%x, SysBase=%x.%x, IoBase=%x.%x, Lmt=%x.%x\n",
+ i,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->HighPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->LowPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->HighPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->HighPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->LowPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->HighPart,
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
+ );
+ }
+#endif
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/rxpcibus.c b/private/ntos/nthals/halr98b/mips/rxpcibus.c
new file mode 100644
index 000000000..6796e1804
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxpcibus.c
@@ -0,0 +1,2826 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ rxpcibus.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#if defined(INTEL_9036)
+ULONG intel_9036=FALSE;
+#endif
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+ULONG HalpCirrusDel = FALSE;
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+// R98B Configuration Mechanism #1.
+//
+PCI_CONFIG_HANDLER PCIConfigHandler = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+extern BOOLEAN HalpDoingCrashDump;
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+// Number Of PCI Bus.
+//
+UCHAR HalpNumberOfAllPciBus=0;
+
+// Start Pci BusNumber of PONCE #0,#1 #n ,,,
+//
+ULONG HalpStartPciBusNumberPonce[R98B_MAX_PONCE+1];
+//
+// Get PONCE Number (0 origin) From System(NT) BusNumber.
+//
+ULONG
+HalpPonceNumber (
+ IN ULONG BusNumber
+ )
+{
+ ULONG Ponce;
+
+ if( BusNumber <HalpStartPciBusNumberPonce[1]){
+ Ponce = 0;
+ }else if(BusNumber <HalpStartPciBusNumberPonce[2]){
+ Ponce = 1;
+ }else if(BusNumber <HalpStartPciBusNumberPonce[3]){
+ Ponce = 2;
+ }
+
+ return Ponce;
+
+}
+
+#if DBG
+
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+)
+{
+ ULONG i, Lines, pchar;
+
+ DbgPrint("----- I/O Data. (%d)byts.\n", Length);
+
+ for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
+ DbgPrint("%08x: ", Lines);
+ for (i = 0; i < 4; pchar += 4, i++) {
+ if (pchar >= Length)
+ break;
+ DbgPrint("%08x ", *Buffer++);
+ }
+ DbgPrint("\n");
+ }
+}
+
+
+VOID
+HalpTestPciNec (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+ ULONG MaxDevice;
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgPrint("Nec Test Start --------------------------------------------\n");
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag && bus < HalpNumberOfAllPciBus; bus++) { /* R98B Support Only 2 */
+// for (bus = 3; flag && bus < 4; bus++) { //under ponce #1 only
+ DbgPrint("Config data BusNumber = 0x%x --------------------------------------------\n",bus);
+ if( (bus == HalpStartPciBusNumberPonce[0]) || (bus == HalpStartPciBusNumberPonce[1]) )
+ MaxDevice = 7;
+ else
+ MaxDevice = PONCE_PCI_MAX_DEVICES;
+
+ for (i = 0; i < MaxDevice; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+ DbgPrint("===== GetBusData bus(%d) slot(%d) func(%d) ", bus,i, f);
+
+ //
+ // Read PCI configuration information
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+ HalpTestPciPrintResult((PULONG)&PciData, j);
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+ DbgPrint("===== SetBusData bus(%d) slot(%d) func(%d) ", bus,i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, 1);
+ DbgPrint("===== GetBusData bus(%d) slot(%d) func(%d) ", bus,i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+ PciData.u.type0.InterruptLine = 5; // For trial
+ DbgPrint("===== (Change Contents (SetBusData) bus(%d) slot(%d) func(%d) ", bus,i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
+ DbgPrint("===== GetBusData bus(%d) slot(%d) func(%d) ", bus, i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("We got the bridge\n");
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+ DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+ DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+
+}
+
+#endif
+
+#define KOTEI 0
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+ ULONG Ponce;
+
+#if 1
+ PBUS_HANDLER Bus;
+ PSUPPORTED_RANGES Addresses;
+#endif
+
+
+#if KOTEI
+
+ PCI_REGISTRY_INFO tPCIRegInfo; // only for debug
+
+#endif
+ ULONG mnum;
+
+
+#if DBG
+ DbgPrint("HAL PCI init\n");
+#endif
+
+
+#if !KOTEI
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("HAL PCI init 0 Status = 0x%x\n",status);
+#endif
+
+ return ;
+ }
+
+
+#if DBG
+ DbgPrint("HAL PCI init 0\n");
+#endif
+
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+#endif // !KOTEI
+
+
+ // Number Of Host Bridge
+ for(Ponce = 0 ;Ponce < HalpNumberOfPonce;Ponce++){
+
+#if !KOTEI // Original mode
+
+//org for (i=HalpStartPciBusNumberPonce[Ponce]; TRUE; i++) {
+ for (i=HalpStartPciBusNumberPonce[Ponce]+1; TRUE; i++) {
+
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+#else //SNES BBM Kotei Mode
+
+
+ PCIRegInfo = &tPCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism=0x1;
+
+#endif
+
+#if DBG
+ DbgPrint("HAL PCI init 3 NoBuses = 0x%x\n",PCIRegInfo->NoBuses);
+#endif
+
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ // First Time Only.
+ if(Ponce == 0)
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the ARC System
+ // R98B HardwareMechanism is #1 Only.
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ // R98B
+ // HalpStartPciBusNumberPonce[Ponce #0] = 0 (allways)
+ // HalpStartPciBusNumberPonce[Ponce #1] = Number Of PCIbus Ponce#0 = start pci number
+ // HalpStartPciBusNumberPonce[Ponce #2] = Number Of PCIbus Ponce#0,#1 = start pci number
+ // HalpStartPciBusNumberPonce[ ] = Number Of PCIbus Ponce#1,#2 = start pci number
+ //
+
+
+ HalpNumberOfAllPciBus += PCIRegInfo->NoBuses;
+ HalpStartPciBusNumberPonce[Ponce+1]=
+ HalpStartPciBusNumberPonce[Ponce]+PCIRegInfo->NoBuses;
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ // R98B
+ // SNES
+// for (i=HalpStartPciBusNumberPonce[Ponce]; i < HalpStartPciBusNumberPonce[Ponce] +PCIRegInfo->NoBuses; i++) {
+ for (i=HalpStartPciBusNumberPonce[Ponce]; i < HalpNumberOfAllPciBus;i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+#if DBG
+ DbgPrint("HAL PCI init 5\n");
+#endif
+
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+#if DBG
+ DbgPrint("HAL PCI init 6\n");
+#endif
+
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ // R98B
+
+ } while (HalpGetPciBridgeConfig (HwType,HalpStartPciBusNumberPonce[Ponce] ,&HalpNumberOfAllPciBus)) ;
+
+// HalpNumberOfAllPciBus += PCIRegInfo->NoBuses;
+// HalpStartPciBusNumberPonce[Ponce+1]=
+// HalpStartPciBusNumberPonce[Ponce]+PCIRegInfo->NoBuses;
+
+ //
+ // Search Next Ponce!!.
+ //
+
+ }
+#if DBG
+ DbgPrint("HAL PCI init 7\n");
+
+ for(Ponce =0;Ponce < 4;Ponce++)
+ DbgPrint( "HalpStartPciBusNumberPonce[%x] = 0x%x\n",Ponce,HalpStartPciBusNumberPonce[Ponce]);
+
+ DbgPrint("HalpNumberOfAllPciBus = 0x%x\n",HalpNumberOfAllPciBus);
+#endif
+
+ //
+ // Fixup SUPPORTED_RANGES
+ // R98B fix NumberOfPcibus
+
+ HalpFixupPciSupportedRanges ( HalpNumberOfAllPciBus );
+
+#if 1 //org
+ //
+ // If not Display is CIRRUS. deleate range CIRRUS VGA I/O area.
+ // As interrupt Dummy read register is CIRRUS register.
+ // So Allways had mapped CIRRUS I/O area.
+ //
+ // If did not delete rage of CIRRUS I/O. Another PCI Driver
+ // May be Configration by I/O manager allocate CIRRUS I/O Area.
+ // confrict ocurred.
+ //
+ // Do Cirrus Memory area disable. So that another device allocate
+ // memory area.
+ //
+ if (!HalpCirrusAlive) {
+ Bus = HaliHandlerForBus (PCIBus, HalpStartPciBusNumberPonce[1]);
+ Addresses = Bus->BusAddresses;
+ HalpRemoveRange(&Addresses->IO,0x3000,0x3fff);
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.DeviceNumber = 0x4;
+ SlotNumber.u.bits.FunctionNumber = 0;
+ //
+ // Cconfig command only
+ //
+ HalpReadPCIConfig (Bus, SlotNumber, PciData, 0x0, PCI_COMMON_HDR_LENGTH);
+
+ PciData->Command &= ~(PCI_ENABLE_MEMORY_SPACE);
+ //
+ // Cirrus Memory Space Disable
+ //
+ PciData->Command |= PCI_ENABLE_IO_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ //
+ // Cconfig command only
+ //
+ HalpWritePCIConfig (Bus, SlotNumber, PciData, 0x0, PCI_COMMON_HDR_LENGTH);
+ //
+ // after this flag. CIRRUS device can't see Software.(Hal Only)
+ //
+ //
+ HalpCirrusDel = TRUE;
+
+ //for test only snes
+// HalpRemoveRange(&Addresses->Memory,0x08000000,0x2fffffff);
+ }
+#endif
+
+
+#if DBG
+ DbgPrint("HAL PCI init 8\n");
+#endif
+
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ //
+ // R98B fix NumberOfPcibus
+ //
+ for (BusNo=0; BusNo < HalpNumberOfAllPciBus ; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+#if DBG
+ DbgPrint("HAL PCI init 9\n");
+#endif
+
+#if DBG
+ HalpTestPci (0);
+ HalpTestPciNec(0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+ ULONG Ponce;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+#if 0
+ Internal, // child of this bus
+ 0, // and number
+#else
+ InterfaceTypeUndefined, // R98B
+ 0,
+#endif
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ //
+ // R98B
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetSystemInterruptVector;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+ //
+ // R98B
+// Bus->TranslateBusAddress = HalpTranslatePCIBusAddress;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ //
+ // R98B
+ //
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2SystemLine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCISystemLine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ BusData->MaxDevice = PONCE_PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ // R98B
+ Ponce = HalpPonceNumber(BusNo);
+ BusData->Config.Type1.Address = (PULONG)&PONCE_CNTL(Ponce)->CONFA;
+ BusData->Config.Type1.Data = (ULONG)&PONCE_CNTL(Ponce)->CONFD;
+ break;
+
+ case 2:
+ // R98B Not Support Configuration Mechanism #2.
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+#if defined(DBG7)
+ DbgPrint("HalpSetPCIData:in\n");
+#endif
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ }
+#endif
+
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+#if defined(DBG7)
+ DbgPrint("HalpSetPCIData:out 1\n");
+#endif
+
+ return Len;
+}
+
+#if DBG
+
+ULONG HalsavePonce;
+#endif
+
+// On PONCE If device num cause master Abort!!.
+//
+ULONG
+HalpConfigMask(
+ IN PPCIPBUSDATA BusData
+ )
+{
+
+ ULONG PERRM;
+ ULONG Ponce;
+
+ // PONCE!!.
+ Ponce = ((ULONG)BusData->Config.Type1.Address & PONCE_ADDR_MASK) >> PONCE_ADDR_SHIFT;
+
+
+ // save original mask value
+ PERRM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRM);
+
+ // Set Mask of PONCE.
+ //
+ WRITE_REGISTER_ULONG(
+ (PULONG)&PONCE_CNTL(Ponce)->PERRM,
+ PERRM |(PONCE_PXERR_PMABS)
+ );
+ return PERRM;
+}
+
+BOOLEAN
+HalpConfigUnMask(
+ IN PPCIPBUSDATA BusData,
+ IN ULONG PERRM
+#if DBG
+,
+PCI_SLOT_NUMBER Slot
+#endif
+ )
+{
+
+ BOOLEAN Error;
+ ULONG PAERR;
+ ULONG Ponce;
+
+
+
+ Error=FALSE;
+
+ // whitch PONCE!!.
+ Ponce = ((ULONG)BusData->Config.Type1.Address & PONCE_ADDR_MASK) >>PONCE_ADDR_SHIFT;
+
+ // Check Abort was Occured!!.
+ //
+ PAERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PAERR)
+ & (PONCE_PXERR_PMABS);
+ if(PAERR){
+#if DBG
+ // Abort Occured!!. So Reset
+ DbgPrint("PCI Master Abort Occured\n ");
+ DbgPrint("DeviceNumber=0x%x\n ",Slot.u.bits.DeviceNumber);
+ DbgPrint("FUnction=0x%x\n \n",Slot.u.bits.FunctionNumber);
+ DbgPrint("ULONG=0x%x\n ",(ULONG)Slot.u.AsULONG);
+#endif
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERST,PAERR);
+ Error=TRUE;
+ }
+
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRM, PERRM );
+
+ return Error;
+}
+
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ ULONG IdValue;
+ ULONG PERRM;
+
+
+ IdValue = 0x0;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+
+ return FALSE;
+ }
+ // R98B Ponce max device is 21
+
+#if 0 //kugi 1214
+ if (Slot.u.bits.DeviceNumber == 0) {
+
+ return FALSE;
+ }
+#endif
+
+#if 1
+ // Hack Hack
+ // display is !cirrus. But Driver installed cirrus.
+ // cirrus configration must do fail to panic.
+ // "DISPLAY ......."
+ //
+ // If Booted display is not CIRRUS.
+ // PCI Configration can't see CIRRUS.
+ //
+ if( !HalpCirrusAlive && HalpCirrusDel &&
+ (BusHandler->BusNumber == HalpStartPciBusNumberPonce[1]) &&
+ (Slot.u.bits.DeviceNumber == 0x4)
+ )
+ return FALSE;
+#endif
+
+
+
+ // R98B Ponce max device is 21
+ // 0 <= device number <= 21 (PONCE_PCI_MAX_DEVICES)
+ //
+ if ( (
+ (BusHandler->BusNumber == HalpStartPciBusNumberPonce[0]) ||
+ (BusHandler->BusNumber == HalpStartPciBusNumberPonce[1])
+ ) &&
+
+ (Slot.u.bits.DeviceNumber > 6)
+ )
+ {
+ return FALSE;
+ }else if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+
+
+ // Check Actually device is there!!. Do Vendor ID register Read.
+ //
+ PERRM=HalpConfigMask(BusData);
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 4,
+ PCIConfigHandler.ConfigRead);
+
+
+#if DBG
+ HalpConfigUnMask(BusData,PERRM,Slot);
+#else
+ HalpConfigUnMask(BusData,PERRM);
+#endif
+
+#if DBG
+ if(Slot.u.bits.FunctionNumber !=Slot.u.bits.FunctionNumber){
+ DbgPrint("BAd Function = 0x%x\n",Slot.u.bits.FunctionNumber);
+ DbgPrint("Bad Function ato= 0x%x\n",Slot.u.bits.FunctionNumber);
+ }
+#endif
+
+
+ if ((IdValue & 0x0000ffff) == 0xffff){
+#if defined(DBG9)
+ DbgPrint("ID Value Function = 0x%x",Slot.u.bits.FunctionNumber);
+ DbgPrint("ID Value Device = 0x%x",Slot.u.bits.DeviceNumber);
+ DbgPrint("ID Value BusNum = 0x%x\n",BusHandler->BusNumber);
+#endif
+
+ return FALSE;
+ }
+
+#if defined(INTEL_9036)
+{
+ ULONG RevisionID;
+
+ PERRM=HalpConfigMask(BusData);
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &RevisionID, 0x8, 4,
+ PCIConfigHandler.ConfigRead);
+
+ if( (IdValue & 0x0000ffff)==0x8086 &&
+ (IdValue & 0xffff0000)==0x12260000 &&
+ (RevisionID & 0xff) <=0x3
+ ){
+ intel_9036=TRUE;
+#if DBG
+ DbgPrint("EtherExpress tm PRO/PCI Found!!\n");
+#endif
+ }else{
+ intel_9036=FALSE;
+ }
+#if DBG
+ HalpConfigUnMask(BusData,PERRM,Slot);
+#else
+ HalpConfigUnMask(BusData,PERRM);
+#endif
+}
+#endif
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+#if defined(DBG9)
+ DbgPrint("Header bad type = 0x%x\n",HeaderType);
+#endif
+
+
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ ULONG Ponce;
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ //
+ // First PCIBus Number of PONCE must be 0. So Conver System(NT) BusNumber
+ // H/W required BusNumber.
+ //
+ Ponce = HalpPonceNumber(BusHandler->BusNumber);
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber - HalpStartPciBusNumberPonce[Ponce];
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (HIGH_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Disable PCI configuration space
+ //
+
+ PciCfg1.u.AsULONG = 0;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if 0 //snes
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
+#else
+// dame READ_PORT_ULONG (BusData->Config.Type1.Data);
+// ok demo moxtuto eehouhouga aru KeStallExecutionProcessor(20);
+KeStallExecutionProcessor(20);
+
+#endif
+ //
+ // Release spinlock
+ //
+
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+ }
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+#if defined(INTEL_9036)
+ if(intel_9036){
+ *Buffer = *((PUCHAR)(& READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data))+i);
+ }else
+#endif
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+#if defined(INTEL_9036)
+ {
+ ULONG data;
+
+ if(intel_9036){
+ data = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+ *((PUCHAR)(&data)+i) = *Buffer;
+// WRITE_PORT_ULONG (PUCHAR) (BusData->Config.Type1.Data + i), data);
+#if 1 //SNES WORK_AROUND
+ READ_PORT_ULONG ((PULONG) (BusData->Config.Type1.Data ));
+#endif
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, data);
+#if 1 //SNES WORK_AROUND
+ READ_PORT_ULONG ((PULONG) (BusData->Config.Type1.Data ));
+#endif
+ return sizeof (UCHAR);
+ }
+ }
+#endif
+
+ WRITE_PORT_UCHAR ((PUCHAR) BusData->Config.Type1.Data + i, *Buffer);
+
+#if 1 //SNES WORK_AROUND
+ READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
+#endif
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
+#if 1 //SNES WORK_AROUND
+ READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
+#endif
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+#if 1
+ extern volatile ULONG DUMMYADDRS[];
+#endif
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
+
+#if 1
+ //
+ // Hack Hack.
+ //
+ if(BusData->Config.Type1.Address == (PULONG)&PONCE_CNTL(1)->CONFA &&
+ PciCfg1->u.bits.BusNumber == 0 &&
+ PciCfg1->u.bits.DeviceNumber == 0x04 &&
+ PciCfg1->u.bits.RegisterNumber== (0x14 / 4 ) &&
+ (*((PULONG) Buffer) & 0xffff0000) == 0
+ ){
+ DUMMYADDRS[1]= DUMMYADDRS[4]= (*((PULONG) Buffer) & 0xfffc) + 0xBc4003c7;
+#if DBG
+ DbgPrint("DUMMYADDRS[1] = 0x%x\n", DUMMYADDRS[1]);
+#endif
+ }
+#endif
+
+#if 1 //SNES WORK_AROUND
+ READ_PORT_ULONG ((PULONG) (BusData->Config.Type1.Data ));
+#endif
+
+ return sizeof (ULONG);
+}
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+#if 0
+ ULONG Ponce;
+#endif
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+#if 1 //org SNES
+ BusNumber = BusHandler->BusNumber;
+#else
+ Ponce = HalpPonceNumber(BusHandler->BusNumber);
+ BusNumber = BusHandler->BusNumber - HalpStartPciBusNumberPonce[Ponce];
+#endif
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+#if DBG
+ DbgPrint ("HalAssign faild return 0\n");
+#endif
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+#if DBG
+ DbgPrint ("HalAssign faild return 1\n");
+#endif
+
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+#if DBG
+ DbgPrint ("HalAssign faild return \n");
+#endif
+
+
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint ("HalAssign Io Assgin faild: = 0x%x\n",status);
+#endif
+
+
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+#if DBG
+ DbgPrint ("Vector: = 0x%x\n",PciData->u.type0.InterruptLine);
+#endif
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+#if DBG
+
+ DbgPrint("HalAssign: Port Address %x\n", *BaseAddress[j]);
+ DbgPrint("HalAssign: BusNumber %x\n",BusHandler->BusNumber );
+#endif
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+#if DBG
+ DbgPrint("HalAssign: Memory Address %x\n", *BaseAddress[j]);
+ DbgPrint("HalAssign: BusNumber %x\n",BusHandler->BusNumber );
+#endif
+
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ // koko de new ni kakikomunoda..
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+#if 0 //SNE org
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+#else
+ if(
+#endif
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+
+#if DBG
+ DbgPrint ("W InterruptLine = 0x%x\n",PciData->u.type0.InterruptLine);
+ DbgPrint ("W InterruptPinn = 0x%x\n",PciData->u.type0.InterruptPin);
+ DbgPrint ("W RomBaseAddress= 0x%x\n",PciData->u.type0.ROMBaseAddress);
+
+ DbgPrint ("R InterruptLine = 0x%x\n",PciData2->u.type0.InterruptLine);
+ DbgPrint ("R InterruptPinn = 0x%x\n",PciData2->u.type0.InterruptPin);
+ DbgPrint ("R RomBaseAddress= 0x%x\n",PciData2->u.type0.ROMBaseAddress);
+
+#endif
+
+
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+
+
+
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+
+#if 0 //intel networktest
+ if (PciData.u.type0.BaseAddresses[j] == 0x10001) {
+ DbgPrint (" Express INTEL\n");
+ PciData.u.type0.BaseAddresses[j] = 0x5001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ }
+#endif
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halr98b/mips/rxpciint.c b/private/ntos/nthals/halr98b/mips/rxpciint.c
new file mode 100644
index 000000000..717d6cf3a
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxpciint.c
@@ -0,0 +1,615 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG PciIsaIrq;
+ULONG HalpEisaELCR;
+BOOLEAN HalpDoingCrashDump = FALSE;
+BOOLEAN HalpPciLockSettings;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+//
+// PCI Configuration Type #0 Area Offset 0x3D: Interrupt Pin
+//
+// Interrupt Pin INT
+// ----------------+-----------------
+// 0 :Non Use Interrupt
+// 1 :INT A
+// 2 :INT B
+// 3 :INT C
+// 4 :INT D
+//
+// Device or Phys Slot # :PONCE # : Device Number:
+// ------------------------+--------+------------------------------
+// PCEB/ESC :PONCE0 : 1 :PCI/EISA Bridge
+// SLOT #4 :PONCE0 : 2 :
+// SLOT #5 :PONCE0 : 3 :
+// SLOT #6 :PONCE0 : 4 :
+// SLOT #7 :PONCE0 : 5 :
+// ------------------------+--------+------------------------------
+// 53C825#0 :PONCE1 : 1 :SCSI(Wide)
+// 53C825#1 :PONCE1 : 2 :SCSI(Narrow)
+// SLOT #1 DEC21140 :PONCE1 : 3 :Ehternet Card
+// GD5430 :PONCE1 : 4 :VGA
+// SLOT #2 :PONCE1 : 5 :
+// SLOT #3 :PONCE1 : 6 :
+// ------------------------+--------+------------------------------
+
+// (See 8-15)
+// R98B_PCIPinToLineTableForPonceX[] is Convert table for PCI Pin OutPut to Line.
+// Line is Same as Columbus IPR Rgister Bit3.
+//
+// Table Access is [DeviceNumber][Interrupt Pin].
+//
+// INTA is Per Device/Slot.
+// INTB,INTC,INTD was Shared
+//
+UCHAR R98B_PCIPinTolineTable[R98B_MAX_PONCE][7][5] = {
+#if 0
+ { // { Interrupt NonUse,INTA,INTB,INTC,INTD}
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY)
+ { RFU, 13,RFU,RFU,RFU }, // Device Num #1 is PCEB/ESC
+ { RFU, 25, 8, 5, 2 }, // Device Num #2 is Slot #7
+ { RFU, 24, 8, 5, 2 }, // Device Num #3 is Slot #6
+ { RFU, 23, 8, 5, 2 }, // Device Num #4 is Slot #5
+ { RFU, 22, 8, 5, 2 }, // Device Num #5 is Slot #4
+ { RFU,RFU,RFU,RFU,RFU } // Device Num #6 is none. (DUMMY)
+ },
+
+ { // { Interrupt NonUse,INTA,INTB,INTC,INTD}
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY)
+ { RFU, 31,RFU,RFU,RFU }, // Device Num #1 is 53C825#0 SCSI(Wide)
+ { RFU, 30,RFU,RFU,RFU }, // Device Num #2 is 53C825#1 SCSI(Narrow)
+ { RFU, 29, 7, 4, 1 }, // Device Num #3 is Slot #1 DEC21440 Ether
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #4 is GD5430 nonused.
+ { RFU, 21, 7, 4, 1 }, // Device Num #5 is Slot #9
+ { RFU, 20, 7, 4, 1 } // Device Num #6 is Slot #8
+ },
+
+ { // { Interrupt NonUse,INTA,INTB,INTC,INTD}
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #0
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #1
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #2
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #3
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #4
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #5
+ { RFU,RFU,RFU,RFU,RFU } // Device Num #6
+ }
+#endif
+ { // { Interrupt NonUse,INTA,INTB,INTC,INTD}
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY)
+ { RFU, 13,RFU,RFU,RFU }, // Device Num #1 is PCEB/ESC
+ { RFU, 5, 7, 15, 12 }, // Device Num #2 is Slot #7
+ { RFU, 4, 7, 15, 12 }, // Device Num #3 is Slot #6
+ { RFU, 3, 7, 15, 12 }, // Device Num #4 is Slot #5
+ { RFU, 2, 7, 15, 12 }, // Device Num #5 is Slot #4
+ { RFU,RFU,RFU,RFU,RFU } // Device Num #6 is none. (DUMMY)
+ },
+
+ { // { Interrupt NonUse,INTA,INTB,INTC,INTD}
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY)
+ { RFU, 31,RFU,RFU,RFU }, // Device Num #1 is 53C825#0 SCSI(Wide)
+ { RFU, 30,RFU,RFU,RFU }, // Device Num #2 is 53C825#1 SCSI(Narrow)
+ { RFU, 9, 6, 14, 11 }, // Device Num #3 is Slot #1 DEC21440 Ethe
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #4 is GD5430 nonused.
+ { RFU, 1, 6, 14, 11 }, // Device Num #5 is Slot #9
+ { RFU, 10, 6, 14, 11 } // Device Num #6 is Slot #8
+ },
+
+ { // { Interrupt NonUse,INTA,INTB,INTC,INTD}
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #0
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #1
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #2
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #3
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #4
+ { RFU,RFU,RFU,RFU,RFU }, // Device Num #5
+ { RFU,RFU,RFU,RFU,RFU } // Device Num #6
+ }
+};
+UCHAR HalpPciLogical2PhysicalInt[32]=
+ {0,21,22,23,24,25, 7, 8, 0,29,20, 1, 2,13, 4, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,30,31};
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+#ifndef MCA
+ Isa, 0,
+#else
+ MicroChannel, 0,
+#endif
+ BusInterruptLevel ^ IRQXOR,
+ 0,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2SystemLine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+ On a DBG build we adjust InterruptLine just to ensure driver's
+ don't connect to it without translating it on the PCI bus.
+
+--*/
+{
+ ULONG Ponce;
+ PPCIBUSDATA BusData;
+ PBUS_HANDLER tBusHandler, pBusHandler;
+ PCI_SLOT_NUMBER bSlotNumber;
+ ULONG ActualSlotNumber;
+ ULONG PinNo;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ Ponce = HalpPonceNumber ( BusHandler->BusNumber );
+
+ tBusHandler = BusHandler;
+ pBusHandler = BusHandler->ParentHandler;
+
+ //
+ // My Mother Search!!
+ //
+ if(pBusHandler)
+ for(;TRUE;){
+ if (pBusHandler->BusNumber != HalpStartPciBusNumberPonce[Ponce]) {
+ tBusHandler = pBusHandler;
+ pBusHandler = pBusHandler->ParentHandler;
+ } else {
+ break;
+ }
+ }
+
+ BusData = (PPCIBUSDATA)tBusHandler->BusData;
+
+ if(pBusHandler)
+ bSlotNumber = BusData->ParentSlot;
+ else
+ bSlotNumber = SlotNumber;
+
+ ActualSlotNumber = bSlotNumber.u.bits.DeviceNumber;
+
+ if(pBusHandler)
+ PinNo = (PciData->u.type0.InterruptPin + SlotNumber.u.bits.DeviceNumber) % 4;
+ else
+ PinNo = PciData->u.type0.InterruptPin;
+
+ //
+ //
+ //
+ PciData->u.type0.InterruptLine =
+ (UCHAR) R98B_PCIPinTolineTable[Ponce][ActualSlotNumber][PinNo];
+
+}
+
+
+
+VOID
+HalpPCISystemLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+ ULONG Ponce;
+ PPCIBUSDATA BusData;
+ PBUS_HANDLER tBusHandler, pBusHandler;
+ PCI_SLOT_NUMBER bSlotNumber;
+ ULONG ActualSlotNumber;
+ ULONG PinNo;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+
+ Ponce = HalpPonceNumber ( BusHandler->BusNumber );
+
+ tBusHandler = BusHandler;
+ pBusHandler = BusHandler->ParentHandler;
+
+ //
+ // My Mother Search!!
+ //
+
+ if(pBusHandler)
+ for(;TRUE;){
+ if (pBusHandler->BusNumber != HalpStartPciBusNumberPonce[Ponce]) {
+ tBusHandler = pBusHandler;
+ pBusHandler = pBusHandler->ParentHandler;
+ } else {
+ break;
+ }
+ }
+
+ BusData = (PPCIBUSDATA)tBusHandler->BusData;
+
+ if(pBusHandler)
+ bSlotNumber = BusData->ParentSlot;
+ else
+ bSlotNumber = SlotNumber;
+
+ ActualSlotNumber = bSlotNumber.u.bits.DeviceNumber;
+
+ if(pBusHandler)
+ PinNo = (PciOldData->u.type0.InterruptPin + SlotNumber.u.bits.DeviceNumber) % 4;
+ else
+ PinNo = PciOldData->u.type0.InterruptPin;
+
+ //
+ //
+ //
+ PciNewData->u.type0.InterruptLine =
+ (UCHAR) R98B_PCIPinTolineTable[Ponce][ActualSlotNumber][PinNo];
+
+
+#if DBG
+ if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine ||
+ PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) {
+ DbgPrint ("HalpPCISystem2Pin: System does not support changing the PCI device interrupt routing\n");
+
+// DbgPrint ("N Line = 0x%x\n",PciNewData->u.type0.InterruptLine);
+// DbgPrint ("O Line = 0x%x\n",PciOldData->u.type0.InterruptLine);
+// DbgPrint ("N Pin = 0x%x\n",PciNewData->u.type0.InterruptPin);
+// DbgPrint ("O Pin = 0x%x\n",PciOldData->u.type0.InterruptPin);
+// DbgBreakPoint ();
+ }
+#endif
+}
+
+#if !defined(SUBCLASSPCI)
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (HIGH_LEVEL, Irql);
+ KiAcquireSpinLock (SpinLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (SpinLock);
+ KeLowerIrql (Irql);
+ }
+}
+
+#endif
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+ PSUPPORTED_RANGE Range;
+ PSUPPORTED_RANGES SupportedRanges;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR buffer2[PCI_COMMON_HDR_LENGTH];
+ BOOLEAN UseBusRanges;
+ ULONG i, j, RomIndex, length, ebit;
+ ULONG Base[PCI_TYPE0_ADDRESSES + 1];
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ SupportedRanges = NULL;
+ UseBusRanges = TRUE;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ if (HalpPciLockSettings) {
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PciOrigData = (PPCI_COMMON_CONFIG) buffer2;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // If this is a device, and it current has its decodes enabled,
+ // then use the currently programmed ranges only
+ //
+
+ if (PCI_CONFIG_TYPE(PciData) == 0 &&
+ (PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
+
+ //
+ // Save current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+
+ //
+ // Write all one-bits to determine lengths for each address
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+ Base[j] = *BaseAddress[j];
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // restore original settings
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Build a memory & io range list of just the ranges already
+ // programmed into the device
+ //
+
+ UseBusRanges = FALSE;
+ SupportedRanges = HalpAllocateNewRangeList();
+ if (!SupportedRanges) {
+ goto CleanUp;
+ }
+
+ *BaseAddress[RomIndex] &= ~PCI_ADDRESS_IO_SPACE;
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+
+ i = *BaseAddress[j];
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ length = 1 << 2;
+ Range = &SupportedRanges->IO;
+ ebit = PCI_ENABLE_IO_SPACE;
+
+ } else {
+ length = 1 << 4;
+ Range = &SupportedRanges->Memory;
+ ebit = PCI_ENABLE_MEMORY_SPACE;
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Range = &SupportedRanges->PrefetchMemory;
+ }
+ }
+
+ Base[j] &= ~(length-1);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ if (j == RomIndex &&
+ !(PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)) {
+
+ // range not enabled, don't use it
+ length = 0;
+ }
+
+ if (length) {
+ if (!(PciOrigData->Command & ebit)) {
+ // range not enabled, don't use preprogrammed values
+ UseBusRanges = TRUE;
+ }
+
+ if (Range->Limit >= Range->Base) {
+ Range->Next = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ Range = Range->Next;
+ if (!Range) {
+ goto CleanUp;
+ }
+
+ Range->Next = NULL;
+ }
+
+ Range->Base = Base[j];
+ Range->Limit = Base[j] + length - 1;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ UseBusRanges ? BusHandler->BusAddresses : SupportedRanges,
+ Interrupt,
+ pResourceList
+ );
+
+CleanUp:
+ if (SupportedRanges) {
+ HalpFreeRangeList (SupportedRanges);
+ }
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+ PPCIPBUSDATA BusData;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+ //
+ // R98B
+ //
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
+
+
diff --git a/private/ntos/nthals/halr98b/mips/rxsysbus.c b/private/ntos/nthals/halr98b/mips/rxsysbus.c
new file mode 100644
index 000000000..c2e592eb0
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/rxsysbus.c
@@ -0,0 +1,214 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+ULONG HalpDefaultInterruptAffinity;
+extern UCHAR HalpPciLogical2PhysicalInt[];
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+#if DBG
+ PULONG datap;
+ PULONG datap2;
+#endif
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+
+
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+
+
+#if 0
+
+ datap = (PULONG)&(BusAddress.QuadPart);
+
+ DbgPrint("HAL T BusAddress HIGH:LOW = %08lX:%08lX \n",
+ datap[1],
+ datap[0]
+ );
+ datap = (PULONG)&(pRange->Base);
+ datap2 =(PULONG)&(pRange->Limit);
+ DbgPrint("HAL T RBase-RLimit HIGH:LOW = %08lX:%08lX -- %08lX:%08lX\n",
+ datap[1],
+ datap[0],
+ datap2[1],
+ datap2[0]
+ );
+
+ datap = (PULONG)&(pRange->SystemBase);
+ DbgPrint("HAL T RSysbase HIGH:LOW = %08lX:%08lX \n",
+ datap[1],
+ datap[0]
+ );
+
+ DbgPrint("HAL T BusNo = (0x%x) AddrSpace = 0x%x TransAddr HIGH:LOW = %08lX:%08lX \n",
+ BusHandler->BusNumber,
+ *AddressSpace,
+ TranslatedAddress->u.HighPart,
+ TranslatedAddress->u.LowPart
+ );
+#endif
+
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+ ULONG NumCpu;
+ ULONG PhysicalInterrupt;
+
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ //
+ // R98B
+ //
+ if(BusHandler->InterfaceType == PCIBus){
+ PhysicalInterrupt= (ULONG)HalpPciLogical2PhysicalInt[BusInterruptVector];
+ SystemVector = PhysicalInterrupt + DEVICE_VECTORS;
+ }else{
+ PhysicalInterrupt= BusInterruptVector;
+ SystemVector = BusInterruptVector + DEVICE_VECTORS;
+ }
+ *Irql = (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][PhysicalInterrupt]);
+ //For MRCINT
+ if(PhysicalInterrupt < 43){
+ *Affinity = 0x1 <<HalpResetValue[PhysicalInterrupt].Cpu;
+ }else{
+ NumCpu = (**((PULONG *)(&KeNumberProcessors)));
+ *Affinity = (0x1 <<NumCpu)-1;
+ }
+
+ return SystemVector;
+}
+
diff --git a/private/ntos/nthals/halr98b/mips/tga.h b/private/ntos/nthals/halr98b/mips/tga.h
new file mode 100644
index 000000000..a8db1925a
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/tga.h
@@ -0,0 +1,101 @@
+#ident "@(#) NEC tga.h 1.1 94/11/29 14:09:17"
+/*++
+
+Module Name:
+
+ tga.h
+
+Abstract:
+
+ This module contains the register definitions for the TGA (DEC21030)
+
+Author:
+
+ T.Katoh create-data 1994/11/11
+
+Revision Histort:
+
+--*/
+
+/*
+ * D001 1994.11.29 T.Katoh
+ *
+ * Del: non-used definitions
+ * Chg: TGA_DSP_BUF_OFFSET value
+ * Add: VIDEO_BASE definition
+ */
+
+// TGA Core Space Map offset for 8-bpp Frame Buffers
+
+#define TGA_REG_SPC_OFFSET 0x00100000
+#define TGA_DSP_BUF_OFFSET 0x00200000 // D001
+
+// TGA register offsets, organized by functionality.
+
+#define PLANE_MASK 0x00000028
+#define ONE_SHOT_PIXEL_MASK 0x0000002C
+#define MODE 0x00000030
+#define RASTER_OP 0x00000034
+#define DEEP 0x00000050
+#define BLK_COLOR_R0 0X00000140
+#define BLK_COLOR_R1 0X00000144
+#define H_CONT 0x00000064
+#define V_CONT 0x00000068
+#define VIDEO_BASE 0x0000006c // D001
+#define VIDEO_VALID 0x00000070
+#define RAMDAC_SETUP 0x000000C0
+#define EEPROM_WRITE 0x000001e0
+#define CLOCK 0x000001e8
+#define RAMDAC_DATA 0X000001f0
+#define COMMAND_STATUS 0x000001f8
+
+// Initiate Palette Data
+
+#define VGA_INI_PALETTE_BLACK_R 0x00
+#define VGA_INI_PALETTE_BLACK_G 0x00
+#define VGA_INI_PALETTE_BLACK_B 0x00
+#define VGA_INI_PALETTE_RED_R 0xAA
+#define VGA_INI_PALETTE_RED_G 0x00
+#define VGA_INI_PALETTE_RED_B 0x00
+#define VGA_INI_PALETTE_GREEN_R 0x00
+#define VGA_INI_PALETTE_GREEN_B 0xAA
+#define VGA_INI_PALETTE_GREEN_G 0x00
+#define VGA_INI_PALETTE_YELLOW_R 0xAA
+#define VGA_INI_PALETTE_YELLOW_G 0xAA
+#define VGA_INI_PALETTE_YELLOW_B 0x00
+#define VGA_INI_PALETTE_BLUE_R 0x00
+#define VGA_INI_PALETTE_BLUE_G 0x00
+#define VGA_INI_PALETTE_BLUE_B 0xAA
+#define VGA_INI_PALETTE_MAGENTA_R 0xAA
+#define VGA_INI_PALETTE_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_MAGENTA_B 0xAA
+#define VGA_INI_PALETTE_CYAN_R 0x00
+#define VGA_INI_PALETTE_CYAN_G 0xAA
+#define VGA_INI_PALETTE_CYAN_B 0xAA
+#define VGA_INI_PALETTE_WHITE_R 0xAA
+#define VGA_INI_PALETTE_WHITE_G 0xAA
+#define VGA_INI_PALETTE_WHITE_B 0xAA
+#define VGA_INI_PALETTE_HI_BLACK_R 0x00
+#define VGA_INI_PALETTE_HI_BLACK_G 0x00
+#define VGA_INI_PALETTE_HI_BLACK_B 0x00
+#define VGA_INI_PALETTE_HI_RED_R 0xFF
+#define VGA_INI_PALETTE_HI_RED_G 0x00
+#define VGA_INI_PALETTE_HI_RED_B 0x00
+#define VGA_INI_PALETTE_HI_GREEN_R 0x00
+#define VGA_INI_PALETTE_HI_GREEN_G 0xFF
+#define VGA_INI_PALETTE_HI_GREEN_B 0x00
+#define VGA_INI_PALETTE_HI_YELLOW_R 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_G 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_B 0x00
+#define VGA_INI_PALETTE_HI_BLUE_R 0x00
+#define VGA_INI_PALETTE_HI_BLUE_G 0x00
+#define VGA_INI_PALETTE_HI_BLUE_B 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_R 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_HI_MAGENTA_B 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_R 0x00
+#define VGA_INI_PALETTE_HI_CYAN_G 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_B 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_R 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_G 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_B 0xFF
diff --git a/private/ntos/nthals/halr98b/mips/x86bios.c b/private/ntos/nthals/halr98b/mips/x86bios.c
new file mode 100644
index 000000000..46543c412
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/x86bios.c
@@ -0,0 +1,1256 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * S001 samezima@oa2.kbnes.nec.co.jp
+ * - marge r94d glint and x86bios source and.
+ *
+ */
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+//#include "xm86.h"
+//#include "x86new.h"
+
+#if defined(_X86_DBG_)
+#define X86DbgPrint(STRING) \
+ DbgPrint STRING;
+#else
+#define X86DbgPrint(STRING)
+#endif
+
+#define VIDEO_MEMORY_BASE 0x40000000
+
+#define PCI_0_IO_BASE 0x1c000000
+
+#define PONCE_ADDR_REG ((PULONG)(0x1a000008 | KSEG1_BASE))
+#define PONCE_DATA_REG ((PULONG)(0x1a000010 | KSEG1_BASE))
+#define PONCE_PERRM ((PULONG)(0x1a000810 | KSEG1_BASE))
+#define PONCE_PAERR ((PULONG)(0x1a000800 | KSEG1_BASE))
+#define PONCE_PERST ((PULONG)(0x1a000820 | KSEG1_BASE))
+
+extern PULONG HalpPonceConfigAddrReg;
+extern PULONG HalpPonceConfigDataReg;
+extern PULONG HalpPoncePerrm;
+extern PULONG HalpPoncePaerr;
+extern PULONG HalpPoncePerst;
+
+VOID
+HalpReadPCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUlongByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PULONG Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpReadPCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PSHORT Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUshortByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PSHORT Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpReadPCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpWritePCIConfigUcharByOffset (
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+extern ULONG HalpDisplayControlBase;
+
+// S001 ^^^
+
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+// S001 vvv
+PVOID HalpIoMemoryBase = NULL;
+PVOID HalpIoControlBase= NULL;
+PUCHAR HalpRomBase = NULL;
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (64*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+ULONG X86BoardOnPonce = 0; // S001
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+
+BOOLEAN
+HalpInitX86Emulator(
+ VOID
+ )
+{
+ ULONG ROMsave, ROM_size = 0;
+ PHYSICAL_ADDRESS PhysAddr;
+ UCHAR BaseClass, SubClass, ProgIf;
+ USHORT Cmd,SetCmd, VendorID, DeviceID, Slot;
+ PUCHAR ROM_Ptr, ROM_Shadow;
+ ULONG i;
+ ULONG r;
+ USHORT PciDataOffset;
+ PCI_SLOT_NUMBER PciSlot;
+ UCHAR header;
+ KIRQL Irql;
+ ULONG ponceNumber; // S001
+ ULONG Index;
+ ENTRYLO Pte;
+ PENTRYLO PageFrame;
+ LARGE_INTEGER HalpX86PhigicalVideo = {0,0};
+
+ PhysAddr.HighPart = 0x00000000;
+
+// KeInitializeSpinLock (&HalpPCIConfigLock);
+ KeRaiseIrql (PROFILE_LEVEL, &Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+// Temp Same vvv
+ ponceNumber = 1;
+ HalpPonceConfigAddrReg = PONCE_ADDR_REG + (ponceNumber * 0x400);
+ HalpPonceConfigDataReg = PONCE_DATA_REG + (ponceNumber * 0x400);
+ HalpPoncePerrm = PONCE_PERRM + (ponceNumber * 0x400);
+ HalpPoncePaerr = PONCE_PAERR + (ponceNumber * 0x400);
+ HalpPoncePerst = PONCE_PERST + (ponceNumber * 0x400);
+
+ PciSlot.u.bits.FunctionNumber = 0;
+ PciSlot.u.bits.DeviceNumber = 4;
+
+ //
+ // Disable on-board cirrus memory space
+ //
+
+ HalpReadPCIConfigUshortByOffset(
+ PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command)
+ );
+// SetCmd = Cmd & 0xfffd;
+ SetCmd = Cmd;
+ HalpWritePCIConfigUshortByOffset(
+ PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command)
+ );
+// Temp Same ^^^
+
+ //
+ // Scan PCI slots for video BIOS ROMs, except 3 PCI "slots" on motherboard
+ //
+
+ for (ponceNumber = 0; ponceNumber < R98B_MAX_PONCE ; ponceNumber++) {
+ ULONG startDevNum;
+ ULONG endDevNum;
+ ULONG Slot;
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ HalpX86PhigicalVideo.HighPart = 1;
+ HalpX86PhigicalVideo.LowPart = 0x40000000 * (ponceNumber+1);
+
+ HalpDisplayControlBase = PCI_0_IO_BASE + (ponceNumber * 0x400000);
+
+ Pte.PFN = (HalpX86PhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpX86PhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+ Pte.C = UNCACHED_POLICY;
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) {
+ *PageFrame-- = Pte;
+ Pte.PFN -= 1;
+ }
+
+ HalpPonceConfigAddrReg = PONCE_ADDR_REG + (ponceNumber * 0x400);
+ HalpPonceConfigDataReg = PONCE_DATA_REG + (ponceNumber * 0x400);
+ HalpPoncePerrm = PONCE_PERRM + (ponceNumber * 0x400);
+ HalpPoncePaerr = PONCE_PAERR + (ponceNumber * 0x400);
+ HalpPoncePerst = PONCE_PERST + (ponceNumber * 0x400);
+
+ switch(ponceNumber){
+ case 0:
+ startDevNum = 2;
+ endDevNum = 5;
+ break;
+
+ case 1:
+ if (HalpNumberOfPonce == 3)
+ continue;
+ startDevNum = 3;
+ endDevNum = 6;
+ break;
+
+ case 2:
+ if (HalpNumberOfPonce == 2)
+ continue;
+ startDevNum = 1;
+ endDevNum = 4;
+ break;
+
+ default:
+ continue;
+ }
+
+ for (Slot = startDevNum; Slot <= endDevNum; Slot++) {
+
+ X86DbgPrint(("HAL: PCI SLot Number=%x",Slot));
+
+ //
+ // Create a mapping to PCI configuration space
+ //
+ PciSlot.u.bits.FunctionNumber = 0;
+ PciSlot.u.bits.DeviceNumber = Slot;
+
+ //
+ // Read Vendor ID and check if slot is empty
+ //
+ HalpReadPCIConfigUshortByOffset(PciSlot,&VendorID,FIELD_OFFSET (PCI_COMMON_CONFIG, VendorID));
+ X86DbgPrint((" Vendor ID=%x",VendorID));
+
+ if (VendorID == 0xFFFF){
+ X86DbgPrint(("\n"));
+ continue; // Slot is empty; go to next slot
+ }
+
+ //
+ // Read Device ID and check if slot is empty
+ //
+ HalpReadPCIConfigUshortByOffset(PciSlot,&DeviceID,FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceID));
+
+ //
+ // Check for GLINT or DEC-GA board.
+ //
+ if ( (VendorID == 0x3d3d && DeviceID == 0x0001) ||
+ (VendorID == 0x1013 && DeviceID == 0x00a0) || // S001
+ (VendorID == 0x1011 && DeviceID == 0x0004) ) {
+
+ X86DbgPrint(("\n"));
+ continue;
+ }
+
+ //
+ // Check Base Class Code
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&BaseClass,FIELD_OFFSET (PCI_COMMON_CONFIG, BaseClass));
+
+ //
+ // Check Sub Class Code
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&SubClass,FIELD_OFFSET (PCI_COMMON_CONFIG, SubClass));
+
+ //
+ // Check Proglamming Interface
+ //
+ HalpReadPCIConfigUcharByOffset(PciSlot,&ProgIf,FIELD_OFFSET (PCI_COMMON_CONFIG, ProgIf));
+ X86DbgPrint((" BaseClass =%x, SubClass =%x, ProgIf =%x\n", BaseClass, SubClass, ProgIf));
+
+ //
+ // check if video card
+ //
+ if ( ( (BaseClass == 0) && (SubClass == 1) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 0) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 1) && (ProgIf == 0) ) ||
+ ( (BaseClass == 3) && (SubClass == 0x80) && (ProgIf == 0) ) ) {
+
+ X86DbgPrint(("HAL: This is Video card \n"));
+
+ } else {
+ X86DbgPrint(("HAL: This is not Video card \n"));
+ continue;
+ }
+
+ //
+ // Get size of ROM
+ //
+
+ ROM_size=0xFFFFFFFF;
+
+ HalpReadPCIConfigUlongByOffset(PciSlot,&ROMsave,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ HalpWritePCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+ HalpReadPCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ HalpWritePCIConfigUlongByOffset(PciSlot,&ROMsave,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ X86DbgPrint(("HAL: ROM_Size = %0x\n",ROM_size));
+
+ if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
+
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Set Expansion ROM Base Address & enable ROM
+ //
+
+ PhysAddr.LowPart = 0x000C0000 | PCI_ROMADDRESS_ENABLED;
+
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ //
+ // Enable Memory & I/O spaces in command register
+ //
+
+ HalpReadPCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+ X86DbgPrint(("HAL: READ CMD=%0x\n",Cmd));
+
+ SetCmd = Cmd|0x3;
+ HalpWritePCIConfigUshortByOffset(PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+ //
+ // Create a mapping to the PCI memory space
+ //
+ HalpIoMemoryBase = (PVOID)0x40000000;
+ //
+ // Look for PCI option video ROM signature
+ //
+ HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+
+ X86DbgPrint(("HAL: HalpRomBase=%x,\n",HalpRomBase));
+ X86DbgPrint(("HAL: RomSignature[0]=%x, RomSignature[1]=%x, RomSize=%x\n",
+ *(ROM_Ptr+0), *(ROM_Ptr+1), *(ROM_Ptr+2)<<9 ));
+
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // Sometimes option ROM and video RAM can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+
+ if (ROM_Length <= BUFFER_SIZE) {
+ X86DbgPrint(("HAL: ROM Copy:"));
+
+ for (i=0; i<ROM_Length; i++){
+ ROM_Buffer[i] = *ROM_Ptr++;
+ if( !(i % 0x400) )
+ X86DbgPrint(("."));
+ }
+
+ X86DbgPrint(("\n"));
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+
+ }
+ X86DbgPrint(("HAL: ROM Short HalpRomBase=%x\n",HalpRomBase));
+
+ //
+ // Io Map.
+ //
+ HalpIoControlBase= (PVOID)0x403f0000;
+
+ PhysAddr.LowPart = 0x000C0000;
+ HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+ X86BoardOnPonce = ponceNumber; // S001
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+
+ // Not Found So Reset!!.
+ // Delete mapping to PCI memory space
+
+ // Found PCI VIDEO ROM.
+ // 1.Map ISA Memory Space
+ // 2.
+
+ X86DbgPrint(("HAL: Found PCI ROM BIOS\n"));
+
+ // 0: rom enable so do PCI
+ // 1: rom disable so do EISA vga
+
+ HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
+
+ } // end of if clause
+
+ X86DbgPrint(("HAL: ROM SIZE invalid\n"));
+
+ } // end of for loop
+
+ } // end of ponce searce loop
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+ X86DbgPrint(("HAL: Search (E)ISA ROM BIOS\n"));
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ HalpX86PhigicalVideo.HighPart = 1;
+ HalpX86PhigicalVideo.LowPart = 0x40000000;
+
+ HalpDisplayControlBase = PCI_0_IO_BASE;
+
+ Pte.PFN = (HalpX86PhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpX86PhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+ Pte.C = UNCACHED_POLICY;
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) {
+ *PageFrame-- = Pte;
+ Pte.PFN -= 1;
+ }
+
+ //
+ // No PCI BIOS SO Search ISA BIOS.
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+
+ HalpIoMemoryBase = (PULONG)0x40000000;
+ ROM_size = 0xD0000; // Map to end of option ROM space
+
+ //
+ // Look for ISA option video ROM signature
+ //
+
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ X86DbgPrint(("HAL: EISA ROM BIOS Found \n"));
+
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ }
+
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ HalpIoControlBase= (PVOID)0x403f0000;
+ return TRUE;
+ }
+
+ //
+ // No video option ROM was found. Delete mapping to PCI memory space.
+ //
+
+ X86DbgPrint(("HAL: 55AA BIOS Not \n"));
+
+ return FALSE;
+}
+// S001 ^^^
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ // S001 vvv
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
+ &Context,
+ HalpIoControlBase,
+ HalpIoMemoryBase) != XM_SUCCESS) {
+ return FALSE;
+ }
+ // S001 ^^^
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+}
+
+// S001 vvv
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ VOID
+ )
+// S001 ^^^
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ // S001 vvv
+ if (!HalpInitX86Emulator()){
+ X86DbgPrint(("HAL: X86 HalpInitX86Emulator() False\n")); // S001
+ return FALSE;
+ }
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ X86DbgPrint(("HAL: X86 Bios or Mem Base False\n")); // S001
+ return FALSE;
+ }
+ // S001 ^^^
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase); // S001
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) { // S001
+ HalpEnableInt10Calls = FALSE;
+ return FALSE; // S001
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+ return TRUE; // S001
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+ return;
+}
+
+// S001 vvv
+//
+// This code came from ..\..\x86new\x86bios.c
+//
+#define LOW_MEMORY_SIZE 0x800
+extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+extern ULONG x86BiosScratchMemory;
+extern ULONG x86BiosIoMemory;
+extern ULONG x86BiosIoSpace;
+
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(HalpRomBase + Offset);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+
+ // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
+ return (PVOID)NULL;
+}
+
+
+VOID HalpCopyROMs(VOID)
+{
+ ULONG i;
+ PUCHAR ROM_Shadow;
+
+ if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
+ HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
+
+ X86DbgPrint(("HAL: HalpRomBase=%0x\n",HalpRomBase));
+
+ for (i=0; i<ROM_Length; i++) {
+ *ROM_Shadow++ = ROM_Buffer[i];
+ }
+ }
+}
+
+
+/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
+
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space and the
+// base address of I/O memory space.
+//
+
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+
+ if (DataType == BYTE_DATA) {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+ X86DbgPrint(("HAL: EMU INIT \n"));
+
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+
+ X86DbgPrint(("HAL: Interrupt emulation failed, status %lx\n", Status));
+
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+
+ X86DbgPrint(("HAL: BIOS INIT \n"));
+
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ X86DbgPrint(("HAL: x86BiosInitializeAdapter() False 1\n"));
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ X86DbgPrint(("HAL: x86BiosInitializeAdapter() False 2\n"));
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+
+ X86DbgPrint(("HAL: Emcall BIOS start \n"));
+
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+
+ X86DbgPrint(("HAL: Emcall BIOS End \n"));
+
+ if (Status != XM_SUCCESS) {
+
+ X86DbgPrint(("HAL: Adapter initialization falied, status %lx\n", Status));
+
+ }
+
+ return Status;
+}
+// S001 ^^^
diff --git a/private/ntos/nthals/halr98b/mips/xxcalstl.c b/private/ntos/nthals/halr98b/mips/xxcalstl.c
new file mode 100644
index 000000000..0a8a7197d
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/xxcalstl.c
@@ -0,0 +1,260 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R98 System
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= (Index < 20 ? 1 : 10)) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt0;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->MKRR, PROFILE_VECTOR - DEVICE_VECTORS);
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMCR2, TIMER_RELOAD_START);
+
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+ HalpWriteCompareRegisterAndClear(0);
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98b/mips/xxclock.c b/private/ntos/nthals/halr98b/mips/xxclock.c
new file mode 100644
index 000000000..4f953ab8d
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/xxclock.c
@@ -0,0 +1,207 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * K001 95.11.24 M.Kusano
+ * Add for WDT
+ */
+
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+//K001
+ULONG HalpStartWDTFlag[R98B_MAX_CPU];
+ULONG HalpStopWDTFlag[R98B_MAX_CPU];
+ULONG HalpSetWDTFlag[R98B_MAX_CPU];
+ULONG HalpSetWDTCount[R98B_MAX_CPU];
+
+VOID
+HalStartWDT(
+ IN ULONG Count
+ );
+
+VOID
+HalStopWDT(
+ VOID
+ );
+
+VOID
+HalSetWDTCounter(
+ VOID
+ );
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // If the specified time increment value is less that the minimum value
+ // or greater than the maximum value ,then set the time increment value
+ // to the minimum or maximum as appropriate.
+ //
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+
+ } else if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ // Adjust clock values to the Columbus clock frequency
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ NextIntervalCount = ((DesiredIncrement * COLUMBUS_CLOCK_FREQUENCY) / 1000) / 10;
+ NewTimeIncrement = (NextIntervalCount * 1000 * 10) / COLUMBUS_CLOCK_FREQUENCY;
+ HalpNextIntervalCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
+
+//K001
+VOID HalStartWDT(
+ IN ULONG Count
+)
+/*++
+Routine Description:
+
+ This function is called to start WDT.
+
+Arguments:
+
+ Count - Counter value for WDT.
+
+Return Value:
+
+ NONE
+--*/
+{
+ ULONG NumCPU,i;
+
+ NumCPU=**((PULONG *)(&KeNumberProcessors));
+ NumCPU--;
+
+ for(i=0;i<=NumCPU;i++){
+ HalpStartWDTFlag[i]=1;
+ HalpSetWDTCount[i]=Count;
+ }
+}
+
+VOID HalStopWDT(
+)
+/*++
+Routine Description:
+
+ This function is called to stop WDT.
+
+Arguments:
+
+ NONE
+
+Return Value:
+
+ NONE
+--*/
+{
+ ULONG NumCPU,i;
+
+ NumCPU=**((PULONG *)(&KeNumberProcessors));
+ NumCPU--;
+
+ for(i=0;i<=NumCPU;i++){
+ HalpStopWDTFlag[i]=1;
+ }
+}
+
+VOID HalSetWDTCounter(
+)
+/*++
+Routine Description:
+
+ This function is called to stop WDT.
+
+Arguments:
+
+ NONE
+
+Return Value:
+
+ NONE
+--*/
+{
+ ULONG NumCPU,i;
+
+ NumCPU=**((PULONG *)(&KeNumberProcessors));
+ NumCPU--;
+
+ for(i=0;i<=NumCPU;i++){
+ HalpSetWDTFlag[i]=1;
+ }
+}
diff --git a/private/ntos/nthals/halr98b/mips/xxidle.s b/private/ntos/nthals/halr98b/mips/xxidle.s
new file mode 100644
index 000000000..e202c795c
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/xxidle.s
@@ -0,0 +1,76 @@
+// "@(#) NEC xxidle.s 1.2 94/10/17 11:59:42"
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halr98b/mips/xxinithl.c b/private/ntos/nthals/halr98b/mips/xxinithl.c
new file mode 100644
index 000000000..5071b6b61
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/xxinithl.c
@@ -0,0 +1,894 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R98B system.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+// For CPU
+#define CPU_PHY_INF_OFFSET 0x1d68
+#define CPU_RED_INF_OFFSET 0x1d60
+//For Memory
+#define SIMM_PHY_INF_OFFSET 0x1d10
+#define SIMM_RED_INF_OFFSET 0x1d00
+#define SIMM_PHY_CAP_OFFSET 0x1d20
+#define FW_NOT_DETECT 0x0000
+#define FW_16_DETECT 0x0001
+#define FW_32_DETECT 0x0002
+#define FW_64_DETECT 0x0004
+#define FW_128_DETECT 0x0008
+
+
+ULONG HalpMachineCpu;
+ULONG HalpNumberOfPonce;
+ULONG HalpPhysicalNode;
+
+
+//For CPU
+ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU];
+ULONG HalpPhysicalAffinity=0;
+ULONG HalpFwAffinity=0;
+ULONG HalpFwDetectErrorCpu=0;
+// For Memory
+ULONG HalpFwDetectMemory=0;
+ULONG HalpPhysicalMemory=0;
+ULONG HalpFwDetectErrorMemory=0;
+UCHAR HalpPhysicalSimmSize[64];
+// For INTERRUPT
+// v-masank@microsoft.com
+//
+extern PINT_ENTRY HalpIntEntryPointer;
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+VOID
+HalpCopyROMs(
+ VOID
+ );
+
+extern PVOID HalpIoControlBase;
+extern PVOID HalpIoMemoryBase;
+extern UCHAR HalpSzPciLock[];
+extern UCHAR HalpSzBreak[];
+extern BOOLEAN HalpPciLockSettings;
+
+VOID
+HalpGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalpGetParameters)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+#pragma alloc_text(INIT, HalpCpuCheck)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpIprInterruptLock;
+KSPIN_LOCK HalpDieLock;
+KSPIN_LOCK HalpLogLock;
+//
+// Define bug check information buffer and callback record.
+//
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG FailedAddress;
+ ULONG DiagnosticLow;
+ ULONG DiagnosticHigh;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+extern ULONG HalpX86BiosInitialized;
+extern ULONG X86BoardOnPonce;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+
+VOID
+HalpGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This gets any parameters from the boot.ini invocation line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PCHAR Options;
+
+ if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
+ Options = LoaderBlock->LoadOptions;
+
+ //
+ // Check if PCI settings are locked down
+ //
+
+ if (strstr(Options, HalpSzPciLock)) {
+ HalpPciLockSettings = TRUE;
+ }
+
+ //
+ // Has the user asked for an initial BreakPoint?
+ //
+
+ if (strstr(Options, HalpSzBreak)) {
+ DbgBreakPoint();
+ }
+
+ }
+
+ return;
+}
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+
+ ULONG Revr;
+ ULONG PhysicalNumber;
+
+ ULONG Cnfg;
+ ULONG TmpAffinity;
+ PUCHAR FwNvram;
+ PULONG FwNvram2;
+ UCHAR FwCpu;
+ ULONG i,j;
+ ULONG FwMemory;
+ ULONG FwNoMemory;
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ //
+ // DataBuserr handling
+ //
+ PCR->DataBusError = HalpBusError;
+ //
+ // Instruction BusError handling
+ //
+ PCR->InstructionBusError = HalpBusError;
+
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+ HalpGetParameters (LoaderBlock);
+
+ Revr=READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->REVR ) ;
+ PhysicalNumber=((Revr&0x0f000000)>>24)-4;
+ HalpLogicalCPU2PhysicalCPU[Prcb->Number]=PhysicalNumber;
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+#if !defined(NT_40)
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif
+
+ //
+ // Set NMI interrupt service routine on NVRAM
+ //
+
+ HalpSetupNmiHandler(); // DUMP by kita
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+
+ //
+ // Cpu Type
+ //
+
+ HalpCpuCheck();
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Set DMA I/O coherency attributes.
+ //
+
+ KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP);
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ KeInitializeSpinLock(&HalpIprInterruptLock);
+ KeInitializeSpinLock(&HalpDieLock);
+ KeInitializeSpinLock(&HalpLogLock);
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+
+ // For CPU log(FW Nvram -> OS Nvram)
+ Cnfg=READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->CNFG ) ;
+ TmpAffinity=((~((Cnfg&0x0f000000)>>24))&0x0000000f);
+
+ for(i=0;i<4;i++){
+ HalpPhysicalAffinity = HalpPhysicalAffinity | ((TmpAffinity>>i)&0x1);
+ if(i==3){
+ break;
+ }
+ HalpPhysicalAffinity=(HalpPhysicalAffinity)<<1;
+ }
+
+ (ULONG)FwNvram=0xbf080000;
+ FwCpu=(*FwNvram);
+ HalpFwAffinity=(ULONG)FwCpu;
+ HalpFwDetectErrorCpu=((HalpPhysicalAffinity)&(~HalpFwAffinity));
+ HalNvramWrite(CPU_RED_INF_OFFSET,4,&HalpFwDetectErrorCpu);
+ HalNvramWrite(CPU_PHY_INF_OFFSET,4,&HalpPhysicalAffinity);
+
+ //For memory Log(FW Nvram -> OS NVram)
+ (ULONG)FwNvram2=0xbf080050;
+ HalpFwDetectMemory=(*FwNvram2);
+ FwMemory=0;
+ FwNoMemory=0;
+ for(i=0;i<4;i++){
+ FwMemory=((FwMemory)|((HalpFwDetectMemory <<(i*8))& 0xff000000)) ;
+ if(i==3){
+ break;
+ }
+ FwMemory=((FwMemory)>>8);
+ }
+ for(i=0;i<8;i++){
+ switch(FwMemory&0xf){
+ case FW_NOT_DETECT:
+ FwNoMemory=(FwNoMemory|(0xf<<(i*4)));
+ break;
+ case FW_16_DETECT:
+ for(j=0;j<4;j++){
+ HalpPhysicalSimmSize[i*4+j]=0x04;
+ }
+ break;
+ case FW_32_DETECT:
+ for(j=0;j<4;j++){
+ HalpPhysicalSimmSize[i*4+j]=0x08;
+ }
+ break;
+ case FW_64_DETECT:
+ for(j=0;j<4;j++){
+ HalpPhysicalSimmSize[i*4+j]=0x16;
+ }
+ break;
+ case FW_128_DETECT:
+ for(j=0;j<4;j++){
+ HalpPhysicalSimmSize[i*4+j]=0x32;
+ }
+ break;
+ default:
+ HalpFwDetectErrorMemory=(HalpFwDetectErrorMemory|(0xf<<(i*4) ));
+ }
+ FwMemory=((FwMemory)>>4);
+ }
+ HalpPhysicalMemory=~(FwNoMemory);
+
+ HalNvramWrite(SIMM_RED_INF_OFFSET,4,&HalpFwDetectErrorMemory);
+ HalNvramWrite(SIMM_PHY_INF_OFFSET,4,&HalpPhysicalMemory);
+ HalNvramWrite(SIMM_PHY_CAP_OFFSET,64,HalpPhysicalSimmSize);
+ }
+
+ //
+ // Initialize I/O address
+ //
+
+ HalpMapIoSpace();
+
+#if DBG
+ DbgPrint("Errnod addr is 0x%x\n",(PULONG)&(COLUMNBS_LCNTL)->ERRNOD );
+#endif
+ //
+ // Initialize interrupts
+ //
+
+ HalpInitializeInterrupts();
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+ HalpRegisterInternalBusHandlers ();
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ HalpCalibrateStall();
+
+ HalpCreateDmaStructures();
+
+ //
+ // for x86bios emulator. bios copy
+ //
+
+ HalpCopyROMs();
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+ //
+ // reset EISA io/memory base for HalCallBios() use.
+ //
+ if( HalpX86BiosInitialized ){
+ if(X86BoardOnPonce == 0){
+ HalpIoControlBase = HalpEisaControlBase;
+ HalpIoMemoryBase = HalpEisaMemoryBase;
+ } else {
+ HalpIoControlBase = (PVOID)(
+ KSEG1_BASE +
+ PCI_CNTL_PHYSICAL_BASE +
+ (0x40000 * X86BoardOnPonce )
+ );
+ PhysicalAddress.HighPart = 1;
+ PhysicalAddress.LowPart = 0x40000000 * (X86BoardOnPonce+1);
+ HalpIoMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE
+ );
+ }
+ DbgPrint("HAL: X86 Bus=%d, HalpIoControlBase = 0x%x, HalpIoMemoryBase = 0x%x%x\n",
+ X86BoardOnPonce, HalpIoControlBase, HalpIoMemoryBase);
+ }
+
+#if DBG
+ DbgPrint("HAL: EisaMemoryBase = 0x%x\n", HalpEisaMemoryBase);
+#endif
+// HalpInitializeX86DisplayAdapter();
+
+ return TRUE;
+ }
+ }
+}
+
+//
+// Check MPU is R4400 or R10000
+//
+VOID
+HalpCpuCheck(
+ VOID
+ )
+{
+ //
+ // For Driver. NVRAM Erea Write Enable Any Time.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR ,STSR_WNVWINH);
+ //
+ // Default setup. future implement is daynamic diagnotics.
+ //
+ HalpNumberOfPonce = 2;
+
+ //
+ // Set DUMP Key Only NMI.
+ // PUSH Power SW coused Interrupt. Not NMI!!
+ //
+ HalpMrcModeChange((UCHAR)MRC_OP_DUMP_AND_POWERSW_NMI);
+
+ HalpPhysicalNode = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->CNFG );
+
+ if( READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR) & STSR_MPU){
+ HalpMachineCpu = R98_CPU_R4400;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ }else{
+ HalpMachineCpu = R98_CPU_R10000;
+ **((PULONG *)(&KeNumberTbEntries)) = 64;
+
+#if defined(NT_40)
+ //
+ // Set SyncIrql
+ //
+ // Hal must not set SyncIrql
+ // v-masank@microsoft.com 5/10/96
+ // KeSetSynchIrql(5);
+#endif
+ }
+ //v-masank@microsoft.com for interrupt
+ //
+ HalpIntEntryPointer= (&HalpIntEntry[HalpMachineCpu][0][0]);
+}
+
+
+
+#include "rxnvr.h"
+
+VOID
+HalpSetupNmiHandler(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set NMI handler to nvRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+#if 1 //NMI Vector not imprement yet -> modify by kita
+ ULONG funcAddr;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ PNVRAM_NMIVECTER NvramNmiVecter;
+
+ //
+ // Get address of HalpNmiHandler
+ //
+
+ funcAddr = (ULONG)HalpNmiHandler;
+
+
+ ASSERT( ((ULONG)&HalpNmiHandler >= KSEG0_BASE) &&
+ ((ULONG)&HalpNmiHandler < KSEG2_BASE) );
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ NvramNmiVecter = (PNVRAM_NMIVECTER)NMIVECTER_BASE;
+
+ WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[0],
+ (UCHAR)(funcAddr >> 24));
+
+ WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[1],
+ (UCHAR)((funcAddr >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[2],
+ (UCHAR)((funcAddr >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[3],
+ (UCHAR)(funcAddr & 0xFF));
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+#endif
+ return;
+}
+
+
+
+
+//
+// no change
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // N.B This version Not Implement.
+ // Future support!!
+ //
+ return;
+}
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG MagellanAllError0 =0;
+ ULONG MagellanAllError1 =0;
+ ULONG ColumbsAllError;
+
+ //
+ // Only one Eif or Buserr trap
+ //
+
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,
+ 63-(EIF_VECTOR-DEVICE_VECTORS ));
+
+ KiAcquireSpinLock(&HalpDieLock);
+ HalpBusErrorLog();
+
+// KiReleaseSpinLock(&HalpDieLock);
+ //
+ // Bus Error case (Instruction Fetch and Data Load or Store)
+ // -At Memory Read Multi Bit Error.
+ // -Read to Memory Hole Area
+ // -Read to reserved area or protection area
+ //
+ if(!(HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0 ))
+ MagellanAllError0 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->AERR );
+ if(!(HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1 ))
+ MagellanAllError1 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->AERR );
+
+ ColumbsAllError = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->AERR);
+
+
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+ ColumbsAllError,
+ MagellanAllError0,
+ MagellanAllError1
+ );
+ return FALSE;
+}
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ if (NextRestartBlock->BootStatus.ProcessorReady != FALSE){
+ Number += 1;
+ }
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98b/mips/xxinitnt.c b/private/ntos/nthals/halr98b/mips/xxinitnt.c
new file mode 100644
index 000000000..e0f4bae5a
--- /dev/null
+++ b/private/ntos/nthals/halr98b/mips/xxinitnt.c
@@ -0,0 +1,424 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R98B
+ system.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+
+#endif
+
+VOID
+HalpT5Int5Dispatch(
+ VOID
+ );
+
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+#if defined(NT_40)
+//
+// SYNCH Level must enable IPI on R98B.
+// Sync level enable IPI on R98A .
+// But on R98B, Sync level disable IPI.
+// So, on R98B, we need to change Irql mask table.
+// v-masank@microsoft.com 5/10/96
+//
+// And mask Internal Timer.
+// Because Internal Timer does not use for Profile Interrupt.
+// v-masank@microsoft.com 5/14/96
+// For R98B INT4 handler.
+// v-masank@microsoft.com 5/21/96
+//
+UCHAR HalpIrqlMaskForR98b[] = {4, 5, 7, 7, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+
+// On the R98B ip[7] is the internal clock. The internal clock
+// is not used for profile interrupt. On the R98B ip[4] used
+// for Profile Interrupt AND clock interrupt. The ip[4] has
+// two external clock interrupts.
+
+UCHAR HalpIrqlTableForR98b[] = {0x7f, // IRQL 0
+ 0x7e, // IRQL 1
+ 0x7c, // IRQL 2
+ 0x78, // IRQL 3
+ 0x70, // IRQL 4
+ 0x60, // IRQL 5
+ 0x60, // IRQL 6
+ 0x00, // IRQL 7
+ 0x00}; // IRQL 8
+VOID
+HalpT5Int4Dispatch(
+ VOID
+ );
+#endif
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Jazz or Duo MIPS system.
+
+ N.B. This function is only called during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Value[2];
+
+ PULONG Vp;
+ PKPRCB Prcb;
+ ULONG fcpu;
+ ULONG IntNo;
+ ULONG Index;
+ ULONG TmpValue;
+ ULONG Ponce;
+ ULONG DataLong;
+ ULONG BitCount;
+ ULONG repeatCounter;
+ ULONG MagBuffer;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+#if defined(NT_40)
+ //
+ // SYNCH Level must enable IPI on R98B.
+ // Sync level enable IPI on R98A .
+ // But on R98B, Sync level disable IPI.
+ // So, On R98B, we need to change Irql mask table.
+ // v-masank@microsoft.com 5/10/96
+ //
+ if( HalpMachineCpu == R98_CPU_R10000 ){
+ for (Index = 0; Index < sizeof(HalpIrqlMaskForR98b); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMaskForR98b[Index];
+ }
+ for (Index = 0; Index < sizeof(HalpIrqlTableForR98b); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTableForR98b[Index];
+ }
+ }else{
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+ }
+#else
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+#endif
+
+
+ //
+ // All interrupt disables.
+ //
+ Value[0] = (ULONG)0xFFFFFFFF;
+ Value[1] = (ULONG)0xFFFFFFFF;
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR;
+ WRITE_REGISTER_ULONG( Vp++, Value[0]);
+ WRITE_REGISTER_ULONG( Vp, Value[1]);
+
+ if( HalpMachineCpu == R98_CPU_R10000 ){
+
+ //
+ // Disable illegal memory access error on Columbus.
+ //
+ TmpValue = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK) | 0x94400000;
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK, TmpValue);
+
+ TmpValue = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK2) | 0x00000540;
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK2, TmpValue);
+
+ TmpValue = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->NMIM2) | 0x00000540;
+ WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->NMIM2, TmpValue);
+
+ if( Prcb->Number == 0 ){
+ //
+ // Disable illegal memory access error on Magellan.
+ //
+
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){
+
+ TmpValue = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRM) | 0x000000c0;
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRM, TmpValue );
+
+ }
+
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){
+
+ TmpValue = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRM) | 0x000000c0;
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRM, TmpValue );
+
+ }
+
+ //
+ // Disable illegal memory access error on Ponce.
+ //
+
+ TmpValue = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRM ) | 0x90400000;
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRM, TmpValue );
+
+ TmpValue = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->ERRM ) | 0x90400000;
+ WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->ERRM, TmpValue );
+ }
+ }
+
+ //
+ // If processor 0 is being initialized, then set all device
+ // interrupt disables.
+ //
+
+ if (Prcb->Number == 0) {
+
+ for (Ponce = 0;Ponce <HalpNumberOfPonce;Ponce++){
+ repeatCounter = 0;
+ while(
+ ((DataLong = READ_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTRG) & 0x07ff07ff) != 0) &&
+ (++repeatCounter < 60)
+ ) {
+
+ for( BitCount = 0 ; BitCount <=10 ; BitCount++ ) {
+ if( (DataLong & ( 1 << BitCount )) != 0) {
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTRG,0x1 << (BitCount));
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTRG,0x1 << (BitCount+21));
+ }
+ }
+ }
+
+ //
+ // Disable I/O TLB error.
+ //
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->ERITTG[1], 0x0 );
+ WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->ERRST, PONCE_XERR_TUAER | PONCE_XERR_TIVER );
+ }
+ }
+
+ PCR->InterruptRoutine[INT0_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt0Dispatch;
+ PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch;
+ PCR->InterruptRoutine[INT2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt2Dispatch;
+ PCR->InterruptRoutine[INT3_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt3Dispatch;
+
+ //
+ // On NT4.0 , INT4 handler is different between R98A and R98B.
+ // v-masank@microsoft.com 5/21/96
+ //
+ PCR->InterruptRoutine[INT4_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt4Dispatch;
+
+
+ if( HalpMachineCpu == R98_CPU_R4400){
+ //
+ // R4400 System (R98A)
+ //
+ PCR->InterruptRoutine[INT5_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt5Dispatch;
+
+ }else{
+ //
+ // R10000 System (R98B)
+ //
+#if defined(NT_40)
+ PCR->InterruptRoutine[INT4_LEVEL] = (PKINTERRUPT_ROUTINE) HalpT5Int4Dispatch;
+#endif
+ PCR->InterruptRoutine[INT5_LEVEL] = (PKINTERRUPT_ROUTINE) HalpT5Int5Dispatch;
+
+ }
+
+ //
+ // If processor 0 is being initialized, then connect the interval timer
+ // interrupt to the stall interrupt routine so the stall execution count
+ // can be computed during phase 1 initialization. Otherwise, connect the
+ // interval timer interrupt to the appropriate interrupt service routine
+ // and set stall execution count from the computation made on processor
+ // 0.
+ //
+
+ if (Prcb->Number == 0) {
+
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt;
+
+ } else {
+
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt1;
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+ }
+
+ //
+ // Initialize the interval timer to interrupt at the specified interval.
+ //
+
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMSR1, CLOCK_INTERVAL-1);
+
+ //
+ // Initialize the profile timer to interrupt at the default interval.
+ //
+
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMSR2,
+ DEFAULT_PROFILETIMER_COUNT);
+ //
+ // Enable the interval timer interrupt on the current processor.
+ //
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->MKRR, CLOCK_VECTOR - DEVICE_VECTORS);
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMCR1, TIMER_RELOAD_START);
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\comapre interrupt to the appropriate interrupt service routine.
+ //
+
+ if (Prcb->Number != 0) {
+ PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->MKRR, PROFILE_VECTOR - DEVICE_VECTORS);
+ WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMCR2,TIMER_RELOAD_START);
+ }
+
+ //
+ // ECC 1Bit Error Vector Set
+ //
+
+ if (Prcb->Number == 0) {
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){
+ MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI );
+ MagBuffer |= ECC_ERROR_DISABLE;
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, MagBuffer );
+ }
+ if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){
+ MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI );
+ MagBuffer |= ECC_ERROR_DISABLE;
+ WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, MagBuffer );
+ }
+ }
+ PCR->InterruptRoutine[ECC_1BIT_VECTOR] = HalpEcc1bitError;
+
+ //
+ // Connect the interprocessor interrupt service routine and enable
+ // interprocessor interrupts.
+ //
+ for(fcpu = 0;fcpu < R98B_MAX_CPU;fcpu++)
+ PCR->InterruptRoutine[IPI_VECTOR3+fcpu] = HalpIpiInterrupt;
+
+
+ //
+ // Enable Interrupt at Columnbs
+ // N.B
+ // At This Interrupt Mask is not perfact. Because Number Of CPU is unknown.
+ // So fix at HalAllProcessorsStarted ()
+ //
+ Value[0] = (ULONG)0xFFFFFFFF;
+ Value[1] = (ULONG)0xFFFFFFFF;
+
+ //
+ // Build Mask
+ //
+ for(IntNo=0 ; IntNo< 6 ;IntNo++){
+ Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][IntNo].Enable);
+#if DBG
+ DbgPrint("Init Interrupt CPU= %x: INT 0x%x Low =0x%x High = 0x%X\n",
+ PCR->Number,IntNo, Vp[0], Vp[1]);
+#endif
+ Value[0] &= ~Vp[0];
+ Value[1] &= ~Vp[1];
+ }
+#if DBG
+ DbgPrint("Init Interrupt CPU= %x :MKR Low =0x%x High = 0x%X\n",
+ PCR->Number,Value[0], Value[1]);
+#endif
+ Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR;
+ WRITE_REGISTER_ULONG(Vp++,Value[0]);
+ WRITE_REGISTER_ULONG(Vp, Value[1]);
+
+ //
+ // Reserve the local device interrupt vector for exclusive use by the HAL.
+ //
+ PCR->ReservedVectors |= ((1 << INT0_LEVEL) |(1 << INT1_LEVEL)|(1 << INT2_LEVEL)|
+ (1 << INT4_LEVEL));
+
+ if( HalpMachineCpu == R98_CPU_R4400){
+ PCR->ReservedVectors = (0x1 <<INT5_LEVEL);
+ }
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halr98b/rangesup.c b/private/ntos/nthals/halr98b/rangesup.c
new file mode 100644
index 000000000..d9d8db63f
--- /dev/null
+++ b/private/ntos/nthals/halr98b/rangesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\rangesup.c"
diff --git a/private/ntos/nthals/halr98b/sources b/private/ntos/nthals/halr98b/sources
new file mode 100644
index 000000000..dfd9d3fba
--- /dev/null
+++ b/private/ntos/nthals/halr98b/sources
@@ -0,0 +1,107 @@
+!IF 0
+# @(#) sources 1.6 94/10/14 17:29:42 nec
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halr98b
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+!IF 0
+C_DEFINES=-D_R98B_ -DDBCS -DBBM_R98A -DINTEL_9036
+!ELSE
+C_DEFINES=-D_R98B_ -DDBCS -DBBM_R98A -DINTEL_9036 -DNT_40
+!ENDIF
+
+INCLUDES=..\x86new;..\inc;..\..\inc;
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\rxdspt.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxebsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\x86bios.c \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\rxinfo.c \
+ mips\rxipiint.c \
+ mips\rxclock.s \
+ mips\rxeif.c \
+ mips\rxint.s \
+ mips\rxbusdat.c \
+ mips\rxsysbus.c \
+ mips\rxisabus.c \
+ mips\rxpciint.c \
+ mips\rxpcibrd.c \
+ mips\rxpcibus.c \
+ mips\mipsdat.c \
+ mips\jxport.c \
+ mips\rxhwsup.c \
+ mips\jxreturn.c \
+ mips\jxusage.c \
+ mips\jxdisp.c \
+ mips\rxesm.c \
+ mips\rxecc.c \
+ mips\rxhwlog.c
+
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halr98mp/drivesup.c b/private/ntos/nthals/halr98mp/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halr98mp/hal.rc b/private/ntos/nthals/halr98mp/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halr98mp/hal.src b/private/ntos/nthals/halr98mp/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halr98mp/makefile b/private/ntos/nthals/halr98mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halr98mp/makefile.inc b/private/ntos/nthals/halr98mp/makefile.inc
new file mode 100644
index 000000000..181fa3cec
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/makefile.inc
@@ -0,0 +1,5 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halr98mp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halr98mp/mips/allstart.c b/private/ntos/nthals/halr98mp/mips/allstart.c
new file mode 100644
index 000000000..480e6933f
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/allstart.c
@@ -0,0 +1,200 @@
+#pragma comment(exestr, "@(#) allstart.c 1.6 94/12/07 23:10:52 nec")
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+--*/
+
+/*
+ * Original source: Build Number 1.807
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 '94.10/14 T.Samezima
+ * Add HalpConnectInt1Interrupt()
+ * valiable HalpInt1Affinity.
+ * Call HalpConnectInt1Interrupt()
+ * Del Call HalpCreateEisaStructures()
+ *
+ * S002 '94.10/18 T.Samezima
+ * Chg Enable interrupt on MKR register only exist device,
+ *
+ * S003 '94.10/22 T.Samezima
+ * Chg Issue restart timer interrupt on CPU#0 to all CPU
+ *
+ * S004 '94.12/07 T.Samezima
+ * Del warning
+ *
+ */
+
+
+#include "halp.h"
+
+// S001 vvv
+//
+// Define INT1 interrupt affinity.
+//
+
+KAFFINITY HalpInt1Affinity;
+
+BOOLEAN // S004
+HalpConnectInt1Interrupt(
+ VOID
+ );
+// S001 ^^^
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+ // S001, S003 vvv
+ // Restart all timer interrupt. because, generate interrupt for same time
+ //
+
+ if (PCR->Number == 0) {
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TCIR.Long,
+ TCIR_ALL_CLOCK_RESTART); // S007
+ }
+ // S001, S003 ^^^
+
+ //
+ // If the number of processors in the host configuration is one,
+ // then connect EISA interrupts to that processor zero. Otherwise,
+ // connect EISA interrupts to processor one.
+ //
+
+ if (**((PULONG *)(&KeNumberProcessors)) == 1) {
+ return HalpConnectInt1Interrupt(); // S001
+
+ } else if (PCR->Number == 1) {
+ return HalpConnectInt1Interrupt(); // S001
+
+ } else {
+ return TRUE;
+ }
+}
+
+// S001 vvv
+ULONG AII1Mask;
+ULONG AII2Mask;
+
+BOOLEAN // S004
+HalpConnectInt1Interrupt(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function connect int1 interrupt on execution processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ return TRUE.
+
+--*/
+
+{
+
+ ULONG number;
+ ULONG pmcRegisterAddr;
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+
+ //
+ // Get CPU number.
+ //
+
+ number = PCR->Number;
+
+ //
+ // Set route for notice of interrupt
+ //
+
+ AII1Mask = AII_INIT_DATA >> number;
+ AII2Mask = ( ((AII_INIT_DATA >> number) & 0xffff0000)
+ | (AII_INIT_DATA & 0x0000ffff) );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long,
+ AII1Mask );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long,
+ AII2Mask );
+
+ //
+ // Enable INT1 interrupt on PMC
+ //
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR );
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT1_DEVICE_ENABLE_LOW ); // S002
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ PCR->ReservedVectors |= (1 << INT1_LEVEL);
+
+ //
+ // Set Int1 interrupt affinity.
+ //
+
+ HalpInt1Affinity = PCR->SetMember;
+
+ //
+ // Initialize the interrupt dispatcher for I/O interrupts.
+ //
+
+ PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch;
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ HalpCreateEisaStructures();
+
+ //
+ // Initialize PCI bus interrupts.
+ //
+
+ return HalpCreatePciStructures ();
+}
+// S001 ^^^
diff --git a/private/ntos/nthals/halr98mp/mips/cacherr.s b/private/ntos/nthals/halr98mp/mips/cacherr.s
new file mode 100644
index 000000000..95f59c0cd
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/cacherr.s
@@ -0,0 +1,196 @@
+// "@(#) NEC cacherr.s 1.2 94/10/17 11:02:44"
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// N.B. All the code in this routine MUST run in KSEG1 and reference
+// data only in KSEG1 until which time as any cache errors have
+// been corrected.
+//
+// N.B. This routine is NOT COMPLETE. All cache errors result in a
+// soft reset.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved integer register at - a3
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+
+ SBTTL("Cache Error Handling")
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1. If the error is a single bit ECC error in the second
+// level data cache or the error is in the primary instruction cache,
+// then the error is corrected and execution is continued. Otherwise,
+// a fatal system error has occured and control is transfered to the
+// soft reset vector.
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCacheErrorRoutine)
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw AT,0(k0) // save registers AT - a3
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+
+//
+// Get the current processor state and cache error register, and check
+// if the error can be corrected.
+//
+
+ mfc0 v0,psr // get current processor state
+ mfc0 v1,cacheerr // get cache error state
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+//
+// The following code is temporary and will be removed when full cache
+// error support is included.
+//
+// ****** temp ******
+//
+
+ b SoftReset // ****** all error soft rest
+
+//
+// If the EXL bit is set in the processor state, then the error is not
+// recoverable because the EXL bit may be erroneously set (errata) and
+// it cannot be determined whether is should or should not be set, e.g.,
+// the exact addresses ranges over which EXL might be correctly set are
+// not verifiable. Also, k0 and k1 are destroyed before they are saved
+// and are used by the exception handling code (there is no way to save
+// a register in noncached memory wihtout the use of a register).
+//
+
+ sll a0,v0,31 - PSR_EXL // shift EXL bit in sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// If the error occured on the SysAd bus, then the error is not correctable.
+//
+
+ sll a0,v1,31 - CACHEERR_EE // shift EE bit into sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// Determine whether the error is in the instruction or data cache.
+//
+
+ sll a0,v1,31 - CACHEERR_ER // shift ER bit into sign
+ bgez a0,IcacheError // if gez, instruction cache error
+
+//
+// The error occured in the data cache.
+//
+// If the error is a data error in the primary cache, then the error
+// is not correctable since the cache line dirty bit is included in
+// the parity calculation and therefore may be wrong.
+//
+
+DcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bgez a0,SoftReset // if gez, error in primary cache
+ b ExitError // exit error
+
+//
+// The error occured in the instruction cache.
+//
+// If the error occured in the secondary data cache, then the error is not
+// correctable since there is not secondary instruciton cache.
+//
+
+IcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bltz a0,SoftReset // if ltz, error in secondary cache
+
+//
+// The cache error has been corrected - restore register state and continue
+// execution.
+//
+
+ExitError: //
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw AT,0(k0) // restore registers AT - a3
+ lw v0,4(k0) //
+ lw v1,8(k0) //
+ lw a0,12(k0) //
+ lw a1,16(k0) //
+ lw a2,20(k0) //
+ eret //
+ .set at
+ .set reorder
+
+//
+// Cache error cannot be corrected - transfer control to soft reset vector.
+//
+
+SoftReset: //
+ la k0,SOFT_RESET_VECTOR // get address of soft reset vector
+ j k0 // perform a soft reset
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halr98mp/mips/cirrus.h b/private/ntos/nthals/halr98mp/mips/cirrus.h
new file mode 100644
index 000000000..9f9846aaf
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/cirrus.h
@@ -0,0 +1,298 @@
+#ident "@(#) NEC cirrus.h 1.2 94/11/21 13:58:39"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.7 94/02/03 18:58:17" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.6 94/01/28 11:50:02" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.4 93/10/29 12:25:02" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cirrus.h
+
+Abstract:
+
+ This module contains the definitions for the code that implements the
+ Cirrus Logic VGA 6410/6420/542x device driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Miniport Driver Interface
+ *
+ * M002 1994.2.2 A. Kuriyama @ oa2
+ * - Bug fix
+ *
+ * Modify : Video Memory Physical Address
+ *
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ * L002 1993.10.21 Kuroki
+ *
+ * - Warniing clear
+ *
+ ***************************************************************
+ *
+ * S001 1994.06.06 T.Samezima
+ *
+ * - Modify for R98 MIPS R4400
+ *
+ * Change : LA_MASK
+ *
+ * S002 '94.11/21 T.Samezima
+ * Chg invalid S001
+ *
+ */
+
+//
+// Change Ushort to Uchar, because R96 is mips machine.
+//
+
+
+//
+// Base address of VGA memory range. Also used as base address of VGA
+// memory when loading a font, which is done with the VGA mapped at A0000.
+//
+
+/* START L001 */
+
+/* START M002 */
+#define LA_MASK 0xe // S001, S002
+/* END M002 */
+#define MEM_VGA (LA_MASK << 20)
+#define MEM_VGA_SIZE 0x100000
+
+/* END L001 */
+
+//
+// Port definitions for filling the ACCSES_RANGES structure in the miniport
+// information, defines the range of I/O ports the VGA spans.
+// There is a break in the IO ports - a few ports are used for the parallel
+// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped
+// so all VGA ports are in one address range.
+//
+
+#define VGA_BASE_IO_PORT 0x000003B0
+#define VGA_START_BREAK_PORT 0x000003BB
+#define VGA_END_BREAK_PORT 0x000003C0
+#define VGA_MAX_IO_PORT 0x000003DF
+
+//
+// VGA port-related definitions.
+//
+
+//
+// VGA register definitions
+//
+ // ports in monochrome mode
+#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and
+#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode
+#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port
+ // in mono mode
+#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read
+ // port in mono mode
+#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO
+ // Register to read to reset
+ // Attribute Controller index/data
+#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and
+#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port
+ // for writes, but only Address is
+ // readable at 0x010
+#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is
+ // readable here
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write
+ // port
+#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read
+ // port
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the
+ // entire VGA subsystem
+#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and
+#define SEQ_DATA_PORT 0x0015 // Data registers
+#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg
+#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg,
+ // write-only
+#define DAC_STATE_PORT 0x0017 // DAC state (read/write),
+ // read-only
+#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg
+#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg
+#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port
+#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read
+ // port
+#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address
+#define GRAPH_DATA_PORT 0x001F // and Data registers
+
+ // ports in color mode
+#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and
+#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode
+#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port
+#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read
+ // port in color mode
+#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR
+ // Register to read to reset
+ // Attribute Controller index/data
+ // toggle in color mode
+
+//
+// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed
+// VGA registers.
+//
+
+#define CRTC_ADDRESS_MONO_OFFSET 0x04
+#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A
+#define ATT_ADDRESS_OFFSET 0x10
+#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12
+#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13
+#define SEQ_ADDRESS_OFFSET 0x14
+#define DAC_PIXEL_MASK_OFFSET 0x16
+#define DAC_STATE_OFFSET 0x17
+#define DAC_ADDRESS_WRITE_OFFSET 0x18
+#define GRAPH_ADDRESS_OFFSET 0x1E
+#define CRTC_ADDRESS_COLOR_OFFSET 0x24
+#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A
+
+// toggle in color mode
+//
+// VGA indexed register indexes.
+//
+
+// CL-GD542x specific registers:
+//
+#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts
+#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad
+#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register
+//
+#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start
+#define IND_CURSOR_END 0x0B // and End registers
+#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location
+#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers
+#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync
+ // End register, which has the bit
+ // that protects/unprotects CRTC
+ // index registers 0-7
+#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC
+#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC
+#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr
+#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr
+#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr
+#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr
+#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq
+#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer
+#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq
+#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in
+ // CRTC
+#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg
+ // in CRTC
+#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start
+ // synchronous reset
+#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end
+ // synchronous reset
+
+//
+// Values for Attribute Controller Index register to turn video off
+// and on, by setting bit 5 to 0 (off) or 1 (on).
+//
+
+#define VIDEO_DISABLE 0
+#define VIDEO_ENABLE 0x20
+
+// Masks to keep only the significant bits of the Graphics Controller and
+// Sequencer Address registers. Masking is necessary because some VGAs, such
+// as S3-based ones, don't return unused bits set to 0, and some SVGAs use
+// these bits if extensions are enabled.
+//
+
+#define GRAPH_ADDR_MASK 0x0F
+#define SEQ_ADDR_MASK 0x07
+
+//
+// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register.
+//
+
+#define CHAIN4_MASK 0x08
+
+//
+// Value written to the Read Map register when identifying the existence of
+// a VGA in VgaInitialize. This value must be different from the final test
+// value written to the Bit Mask in that routine.
+//
+
+#define READ_MAP_TEST_SETTING 0x03
+
+//
+// Default text mode setting for various registers, used to restore their
+// states if VGA detection fails after they've been modified.
+//
+
+#define MEMORY_MODE_TEXT_DEFAULT 0x02
+#define BIT_MASK_DEFAULT 0xFF
+#define READ_MAP_DEFAULT 0x00
+
+
+//
+// Palette-related info.
+//
+
+//
+// Highest valid DAC color register index.
+//
+
+#define VIDEO_MAX_COLOR_REGISTER 0xFF
+
+//
+// Indices for type of memory mapping; used in ModesVGA[], must match
+// MemoryMap[].
+//
+
+typedef enum _VIDEO_MEMORY_MAP {
+ MemMap_Mono,
+ MemMap_CGA,
+ MemMap_VGA
+} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP;
+
+//
+// For a mode, the type of banking supported. Controls the information
+// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking.
+//
+
+typedef enum _BANK_TYPE {
+ NoBanking = 0,
+ NormalBanking,
+ PlanarHCBanking
+} BANK_TYPE, *PBANK_TYPE;
+
+#define CL6410 0x0001
+#define CL6420 0x0002
+#define CL542x 0x0004
+
+// bitfields for the DisplayType
+#define crt 0x0001
+#define panel 0x0002
+#define simulscan 0x0004 // this means both, but is unused for now.
diff --git a/private/ntos/nthals/halr98mp/mips/cmdcnst.h b/private/ntos/nthals/halr98mp/mips/cmdcnst.h
new file mode 100644
index 000000000..ea2bba221
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/cmdcnst.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdcnst.h
+
+Abstract:
+
+ This is the command string interpreter definitions
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ This module is same file on Cirrus Minport Driver.
+
+Revision History:
+
+--*/
+
+//--------------------------------------------------------------------------
+// Definition of the set/clear mode command language.
+//
+// Each command is composed of a major portion and a minor portion.
+// The major portion of a command can be found in the most significant
+// nibble of a command byte, while the minor portion is in the least
+// significant portion of a command byte.
+//
+// maj minor Description
+// ---- ----- --------------------------------------------
+// 00 End of data
+//
+// 10 in and out type commands as described by flags
+// flags:
+//
+// xxxx
+// ||||
+// |||+-------- unused
+// ||+--------- 0/1 single/multiple values to output (in's are always
+// |+---------- 0/1 8/16 bit operation single)
+// +----------- 0/1 out/in instruction
+//
+// Outs
+// ----------------------------------------------
+// 0 reg:W val:B
+// 2 reg:W cnt:W val1:B val2:B...valN:B
+// 4 reg:W val:W
+// 6 reg:W cnt:W val1:W val2:W...valN:W
+//
+// Ins
+// ----------------------------------------------
+// 8 reg:W
+// a reg:W cnt:W
+// c reg:W
+// e reg:W cnt:W
+//
+// 20 Special purpose outs
+// 00 do indexed outs for seq, crtc, and gdc
+// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 01 do indexed outs for atc
+// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 02 do masked outs
+// indexreg:W andmask:B xormask:B
+//
+// F0 Nop
+//
+//---------------------------------------------------------------------------
+
+// some useful equates - major commands
+
+#define EOD 0x000 // end of data
+#define INOUT 0x010 // do ins or outs
+#define METAOUT 0x020 // do special types of outs
+#define NCMD 0x0f0 // Nop command
+
+
+// flags for INOUT major command
+
+//#define UNUSED 0x01 // reserved
+#define MULTI 0x02 // multiple or single outs
+#define BW 0x04 // byte/word size of operation
+#define IO 0x08 // out/in instruction
+
+// minor commands for metout
+
+#define INDXOUT 0x00 // do indexed outs
+#define ATCOUT 0x01 // do indexed outs for atc
+#define MASKOUT 0x02 // do masked outs using and-xor masks
+
+
+// composite inout type commands
+
+#define OB (INOUT) // output 8 bit value
+#define OBM (INOUT+MULTI) // output multiple bytes
+#define OW (INOUT+BW) // output single word value
+#define OWM (INOUT+BW+MULTI) // output multiple words
+
+#define IB (INOUT+IO) // input byte
+#define IBM (INOUT+IO+MULTI) // input multiple bytes
+#define IW (INOUT+IO+BW) // input word
+#define IWM (INOUT+IO+BW+MULTI) // input multiple words
diff --git a/private/ntos/nthals/halr98mp/mips/esmnvram.h b/private/ntos/nthals/halr98mp/mips/esmnvram.h
new file mode 100644
index 000000000..313bec380
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/esmnvram.h
@@ -0,0 +1,687 @@
+#ident "@(#) NEC esmnvram.h 1.1 95/02/20 16:50:43"
+/****************************************************************
+ ******* Copyright (C) 1994 NEC Corporation *******
+ ****************************************************************/
+
+/*******
+
+ File Name:
+
+ envram.h
+
+ Abstract:
+
+ This module contains the definitions for the extended NVRAM.
+
+ Author:
+
+ Takehiro Ueda (tueda@oa2.kb.nec.co.jp) 12/22/1994
+
+ Modification History:
+
+ - M000 12/22/94 -
+ created.
+
+*******/
+
+
+
+/*******************************************************************************
+ ******** NVRAM¡Ê8K¥Ð¥¤¥È¡Ë¤ÎÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤ò°Ê²¼¤Ëµ­½Ò¤¹¤ë¡£ ********
+ *******************************************************************************
+ *
+ * S001 11/22/94
+ * ¥ì¥³¡¼¥É¤ÎÍ­¸ú/̵¸ú¥Õ¥é¥°¡¢Check̤/ºÑ¥Õ¥é¥°¤ò³Æ¥ì¥³¡¼¥É¤ÎÀèƬ¤Ë¤ª¤¯¤«
+ * ¤Þ¤È¤á¤Æ¥ì¥³¡¼¥É¥ê¡¼¥¸¥ç¥ó¤ÎÀèƬ¤Ë¤ª¤¯¤«¤Ç¡¢¥ì¥³¡¼¥É¤Î½èÍýÊýË¡¤¬ÊѤï¤Ã¤Æ
+ * ¤¯¤ë¡£¸å¼Ô¤Ï¥é¥ó¥À¥à¥¢¥¯¥»¥¹¡¢Á°¼Ô¤Ï¥·¡¼¥±¥ó¥·¥ã¥ë¥¢¥¯¥»¥¹¤Ë¤à¤¯¡£
+ * º£²ó¤ÏÁ°¼Ô¤òºÎÍÑ¡£
+ *
+ * ¹Ô¤ÎÀèƬ¤Ë¤¢¤ë¿ô»ú¤Ï³ä¤êÅö¤Æ¤ë¥Ð¥¤¥È¿ô¤ò¤¢¤é¤ï¤¹¡£
+ *
+ * ËÜ»ÅÍͤˤ·¤¿¤¬¤Ã¤Æ¹½Â¤ÂΤòºîÀ®Í½Äê¡£
+ *
+ * S002 11/26/94
+ * ³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°´ØÏ¢¡¢etc.¡Ë
+ * ¤ÎÀèƬ¤Î¥Ø¥Ã¥ÀÉô¤òÁ´¤ÆNVRAM¤ÎÀèƬ¤Ë°Ü¤¹¡£NVRAM¤ÎÀèƬ¤Ë¤¢¤ë¥Ø¥Ã¥ÀÆâ¤Ë
+ * ³ÆÎΰè¤Î¥ì¥³¡¼¥É¤òľÀÜ¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥ª¥Õ¥»¥Ã¥È¤ò¤â¤Ä¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * NVRAM¤Î¥¢¥¯¥»¥¹»þ¤Ë¤Ï256¥Ð¥¤¥Èñ°Ì¤Ç¥Ð¥ó¥¯Àڤ괹¤¨¤¬¤ª¤³¤Ê¤ï¤ì¤ë¤¿¤á
+ * ³Æ¥Ç¡¼¥¿¡Ê256¥Ð¥¤¥ÈĹ°Ê²¼¤Î¤â¤Î¡Ë¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤ò¤Þ¤¿¤¬¤é¤Ê¤¤¤è¤¦
+ * ¤ËÇÛθ¡£³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢etc.¡Ë¤ÎÀèƬ¤¬É¬¤º256¥Ð¥¤¥È
+ * ¥Ð¥¦¥ó¥À¥ê¤«¤é³«»Ï¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * ECC¥¨¥é¡¼¥í¥°Æâ¤ÎSIMMÆÃÄê²½¾ðÊó¤ò2¥Ð¥¤¥È¤«¤é1¥Ð¥¤¥È¤ØÊѹ¹¡£
+ *
+ * ¡É¥ª¥Õ¥»¥Ã¥È ¡É¤Ï¤¹¤Ù¤ÆNVRAM¤ÎÀèƬ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¡£
+ *
+ * S003 12/13/94
+ * NW¥¨¡¼¥¸¥§¥ó¥È¤È¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ò¶¦Ä̲½¤¹¤ë¤¿¤áÀèƬ512¥Ð¥¤¥È¤ò
+ * ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤È¤·¡¢¥Õ¥©¡¼¥Þ¥Ã¥È¤òNW¥¨¡¼¥¸¥§¥ó¥È¤ÈÅý°ì¤¹¤ë¡£
+ *
+ * STEP1¤Ç¤Ï¥á¥â¥ê½ÌÂà¤ò¹Ô¤ï¤Ê¤¤¤¿¤áËÜ¥¨¥ê¥¢¤Ï»ÈÍѤ·¤Ê¤¤¡£
+ * ËÜ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ÏNW¥¨¡¼¥¸¥§¥ó¥È¤È¤Î¶¦Ä̲½¤Î¤¿¤á¤Ë¿·¤¿¤ËÀߤ±¤ë
+ * ¤â¤Î¤Ç¤¢¤ê¡¢°ÊÁ°¤«¤é¤ÎECC¥¨¥é¡¼¾ðÊóÎΰè¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£
+ *
+ * 512¥Ð¥¤¥È¤Î¥¨¥ê¥¢¤òÀèƬ¤ËÀߤ±¤ë¤¿¤á¡¢°ÊÁ°¤«¤é¤Î¤½¤Î¾Á´¤Æ¤Î¾ðÊóÎΰè¤Ï
+ * 512¥Ð¥¤¥È¥ª¥Õ¥»¥Ã¥È¤¬Â礭¤¯¤Ê¤ë¤³¤È¤Ë¤Ê¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È2¥Ð¥¤¥È¤òÄɲá£
+ *
+ * ¥ª¥Õ¥»¥Ã¥È¤ÎºÆ·×»»¡£
+ *
+ * S004 12/14/94
+ * ¹½Â¤ÂκîÀ®¡£
+ *
+ * ¡Ç¥Ñ¥Ë¥Ã¥¯ ¡Ç¤ò¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S005 12/23/94
+ * 4byte alignment¤Ë¤½¤Ê¤¨¤Æ¥Ñ¥Ç¥£¥ó¥°¤ò°ìÉôÊѹ¹¡£
+ *
+ * ¥¹¥È¥Ã¥×¥¨¥é¡¼¤Î¥Õ¥é¥°¤Î2¥Ó¥Ã¥È¤Ë¿·¤¿¤ËÄêµÁÄɲá£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤òNVRAM¥Ø¥Ã¥À¤Ë¤È¤ê¤³¤à¡£
+ * ¤³¤ì¤Ë¤È¤â¤Ê¤¤¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ÏÉÔÍפȤʤ뤿¤á
+ * 2¥Ð¥¤¥Èʬ̤»ÈÍѤȤ¹¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ë¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤òÄɲá£ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ¤ò
+ * ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤È¥Õ¥é¥°¤Ç¥Á¥§¥Ã¥¯¤¹¤ë¤è¤¦¤Ë¤¹¤ë¡£¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤Ï
+ * 0xFF651026¤È¤¹¤ë¡£
+ *
+ * ¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ò¡Ç¥·¥¹¥Æ¥à¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S006 12/27/94
+ * #pragma pack() ¤òÄɲÃ
+ *
+ * char reserved[49] ¤ò char reserved[49] ¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ïharmless¤Ç¤¢¤ë
+ * ¤È¿®¤¸¤ë... (^_^;
+ *
+ * unsigned short offset_ecc2err ¤ò offset_2biterr¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ï
+ * harmless¤Ç¤¢¤ë¤È¿®¤¸¤ë... (^_^;
+ *
+ ******************************************************************************
+
+
+ ###################
+ # NVRAM¥Ø¥Ã¥ÀÉô #
+ ###################
+
+ ######################################################
+ # F/WÍÑ¥á¥â¥ê¡¼¥¨¥é¡¼¥¨¥ê¥¢ (NW¥¨¡¼¥¸¥§¥ó¥È¤È¶¦ÄÌ) #
+ ######################################################
+
+ 512 ¥á¥â¥ê¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(2¥Ð¥¤¥È) ¡ß 256
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ ¡¡¡¡1 ¥¹¥Æ¡¼¥¿¥¹ 0:Àµ¾ï 1:°Û¾ï(2bit¥¨¥é¡¼Í­Ìµ)
+ 1 1bit¥¨¥é¡¼¥«¥¦¥ó¥È
+
+¡¡¡¡ ######################
+ # Á´ÂΤ˴ؤ¹¤ë¤â¤Î #
+ ######################
+
+ 1 NVRAM¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 NVRAMÁ´ÂÎÍ­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡1 ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ 0:̵ 1:Í­
+ ¡¡¡¡2 READ-ONLY 0:NO 1:YES
+ ¡¡¡¡3 LOCK 0:NO 1:YES
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 NVRAM¤¬¥Õ¥©¡¼¥Þ¥Ã¥È¤µ¤ì¤¿¥¿¥¤¥à¥¹¥¿¥ó¥×
+
+ 3 [ reserved ]
+
+¡¡¡¡ ###############################
+ # ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ###############################
+
+ 2 ALIVE¾ðÊóÎΰè¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ #######################################
+ # ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 1bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECC1bit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ ¡¡ 8 ECC 1bit¥¨¥é¡¼¥«¥¦¥ó¥È ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô8
+
+¡¡¡¡ #######################################
+ # ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 2bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECCÊ£¿ôbit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ 4 SIMM¸ò´¹¥Õ¥é¥° ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô4
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 ¥°¥ë¡¼¥×NÆâSIMM #0 (N=1¡Á4) 0:OK 1:NG(Í׸ò´¹)
+ ¡¡¡¡1 ¥°¥ë¡¼¥×NÆâSIMM #1 ¢¬
+ ¡¡¡¡2 ¥°¥ë¡¼¥×NÆâSIMM #2¡¡¡¡ ¢¬
+ ¡¡¡¡3 ¥°¥ë¡¼¥×NÆâSIMM #3¡¡¡¡ ¢¬
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¢¬
+ ¡¡¡¡6 ¢¬
+ ¡¡¡¡7¡¡¡¡¡¡¢¬
+ 4 [reserved]
+
+¡¡¡¡ ########################################
+ ¡¡¡¡# ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ¡¡¡¡########################################
+
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É¿ô
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ############################################
+ ¡¡¡¡# ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Îΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ############################################
+
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##################################
+ ¡¡¡¡# ¤·¤­¤¤Ã;ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##################################
+
+ 2 ¤·¤­¤¤Ã;ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##############################
+ ¡¡¡¡# ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##############################
+
+ 2 ¥ê¥¶¡¼¥ÖÎΰè¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+
+ ########################
+ # ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ #
+ ########################
+
+¡¡¡¡¡¡¡¡ 1 ¥·¥¹¥Æ¥à¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ 0 [reserved]
+ ¡¡¡¡1 ¡¡¡¡¢¬
+ ¡¡¡¡2 ¡¡¡¡¢¬
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 3 [reserved]
+ 32 ¥·¥¹¥Æ¥à¤Î¾ðÊó¡Ê¥·¥¹¥Æ¥à̾¡Ë
+ 4 ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼
+ 4 ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼
+ 4 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 640 ¥Ð¥¤¥È
+
+
+ #######################################
+ # ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ #
+ #######################################
+
+ 1 ¸½ºß¤ÎÄÌÊó¥ì¥Ù¥ë
+ 16 ALIVE°ì¼¡ÄÌÊóÀè
+ 16 ALIVEÆó¼¡ÄÌÊóÀè
+ 47 [reserved for pager call]
+
+-----------------------------------------------------------------------------
+TOTAL 80 ¥Ð¥¤¥È
+
+
+ ##############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ##############################################################################
+
+ 48 [reserved]
+
+
+ #######################
+ # ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô #
+ #######################
+
+ 400 1bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 16
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1¡¡¡¡¥Õ¥é¥°
+
+ ¡¡¡¡ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7¡¡¡¡ ¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+ 100 2bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 4
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5¡¡ ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+
+-----------------------------------------------------------------------------
+TOTAL 500 ¥Ð¥¤¥È
+
+
+ ###############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ###############################################################################
+
+ 12 [reserved]
+
+
+ ##########################
+ # ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô #
+ ##########################
+
+ 2048 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô (1¥ì¥³¡¼¥É512¥Ð¥¤¥È ¡ß 4 ¡á 2K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Dump/Dump SW 0:D 1:D SW
+ ¡¡¡¡3 ÄÌÊó¤Î̵ͭ 0:̤ 1:ºÑ
+ ¡¡¡¡4 boot·ë²Ì 0:Àµ¾ï 1:°Û¾ï
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 496 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó
+ 1 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 2048 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç3328¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ###############################################################
+ # ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) #
+ ###############################################################
+
+ 4096 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Panic/Shutdown 0:P 1:S
+ ¡¡¡¡3 [reserved]
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 20 ¥½¡¼¥¹Ì¾
+ 80 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó
+ 13 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 4096 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç7424¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ##############################
+ # ¤·¤­¤¤ÃÍȽÄêÍѥǡ¼¥¿Îΰè #
+ ##############################
+
+ ¡¡ 256 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 256 ¥Ð¥¤¥È
+
+
+ ###############################################################
+ # ¢¬¤³¤³¤Þ¤Ç7680(7K+512)¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ ###############################################################
+
+
+ ##############################
+ # ¥ê¥¶¡¼¥ÖÎΰè (512¥Ð¥¤¥È) #
+ ##############################
+
+ 512 PAiNTSÍÑ?
+
+-----------------------------------------------------------------------------
+TOTAL 512 ¥Ð¥¤¥È
+
+
+ #############################################
+ # ¢¬¤³¤³¤Þ¤Ç8192(8K)¥Ð¥¤¥È¡£NVRAM¤Î¤·¤Ã¤Ý #
+ #############################################
+
+******************************************************************************/
+
+
+#pragma pack(1)
+
+/********************
+ * *
+ * ¡¡¹½Â¤ÂÎÄêµÁ *
+ * *
+ ********************/
+
+
+/*
+ * WAS & PS¶¦ÄÌFWÍÑ¥á¥â¥ê¥¨¥é¡¼¾ðÊóÎΰè
+ */
+typedef struct _MEM_ERR_REC {
+ unsigned char mem_status; /* ¥¹¥Æ¡¼¥¿¥¹ */
+ unsigned char err_count; /* 1bit¥¨¥é¡¼¥«¥¦¥ó¥È */
+} MEM_ERR_REC, *pMEM_ERR_REC;
+
+
+/*
+ * ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ALIVE_AREA_INFO {
+ unsigned short offset_alive;
+ /* ALIVE¾ðÊ󥨥ꥢ¥ª¥Õ¥»¥Ã¥È */
+} ALIVE_AREA_INFO, *pALIVE_AREA_INFO;
+
+
+/*
+ * ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC1_ERR_AREA_INFO {
+ unsigned short offset_1biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char err_count_group0; /* ¥á¥â¥êG#0 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group1; /* ¥á¥â¥êG#1 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group2; /* ¥á¥â¥êG#2 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group3; /* ¥á¥â¥êG#3 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group4; /* ¥á¥â¥êG#4 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group5; /* ¥á¥â¥êG#5 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group6; /* ¥á¥â¥êG#6 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group7; /* ¥á¥â¥êG#7 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO;
+
+
+/*
+ * ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC2_ERR_AREA_INFO {
+ unsigned short offset_2biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char simm_flag_group1; /* ¥á¥â¥êG#1ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group2; /* ¥á¥â¥êG#2ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group3; /* ¥á¥â¥êG#3ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group4; /* ¥á¥â¥êG#4ÆâSIMM¥Õ¥é¥° */
+ char reserved[4]; /* reserved */
+} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _SYSTEM_ERR_AREA_INFO {
+ unsigned short offset_systemerr;/* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO;
+
+
+/*
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _CRITICAL_ERR_AREA_INFO {
+ unsigned short offset_critical; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO;
+
+
+/*
+ * ¤·¤­¤¤ÃÍÅù¤½¤Î¾¤Î¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _MISC_AREA_INFO {
+ unsigned short offset_misc;
+ /* ¤·¤­¤¤¤ÁÅù¤Î¾ðÊ󥨥ꥢÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} MISC_AREA_INFO, *pMISC_AREA_INFO;
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _RESERVE_AREA_INFO {
+ unsigned short offset_reserve;
+ /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢ÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ
+ * 49¥Ð¥¤¥È
+ */
+
+typedef struct _SYS_INFO {
+ unsigned char system_flag; /* ¥·¥¹¥Æ¥à¾õÂ֥ե饰 */
+ char reserved1[3]; /* 4byte alignment¤Ë¤½¤Ê¤¨¤Æ */
+ char sys_description[32]; /* ¥·¥¹¥Æ¥à¤Î¾ðÊó */
+ unsigned long serical_num; /* ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼ */
+ unsigned long magic; /* ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ */
+ char reserved2[4]; /* reserved */
+} SYS_INFO, *pSYS_INFO;
+
+
+
+/*
+ * NVRAM¥Ø¥Ã¥ÀÉô
+ * 640¥Ð¥¤¥È
+ */
+
+typedef struct _NVRAM_HEADER {
+ MEM_ERR_REC mem_err_map[256]; /* ¥á¥â¥ê¥¨¥é¡¼¾ðÊóNT&NW¶¦ÄÌ¥¨¥ê¥¢ */
+ unsigned char nvram_flag; /* nvram¤Î¾õÂ֥ե饰 */
+ char when_formatted[14]; /* ¥Õ¥©¡¼¥Þ¥Ã¥È¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char reserved[3]; /* 4byte alignment ¤Ë¤½¤Ê¤¨¤Æ */
+ ALIVE_AREA_INFO alive; /* ALIVE¾ðÊ󥨥ꥢ */
+ ECC1_ERR_AREA_INFO ecc1bit_err; /* ECC1bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ ECC2_ERR_AREA_INFO ecc2bit_err; /* ECC2bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ SYSTEM_ERR_AREA_INFO system_err;/* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ CRITICAL_ERR_AREA_INFO critical_err_log;
+ /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥¨¥ê¥¢ */
+ MISC_AREA_INFO misc; /* ¤·¤­¤¤¤Á¾ðÊ󥨥ꥢ */
+ RESERVE_AREA_INFO reserve; /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢¥ª¥Õ¥»¥Ã¥È */
+ SYS_INFO system; /* ¥·¥¹¥Æ¥à¾ðÊó */
+} NVRAM_HEADER, *pNVRAM_HEADER;
+
+
+
+/*
+ * ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ
+ * 80¥Ð¥¤¥È
+ */
+
+typedef struct _ALIVE_INFO {
+ unsigned char alert_level; /* ÄÌÊó¥ì¥Ù¥ë¥° */
+ char primary_destination[16]; /* °ì¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char secondary_destinaiton[16]; /* Æó¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char reserved[47]; /* reserved for pager call */
+} ALIVE_INFO, *pALIVE_INFO;
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved[48];
+
+
+typedef struct _ECC1_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC1_ERR_REC, *pECC1_ERR_REC;
+
+
+typedef struct _ECC2_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC2_ERR_REC, *pECC2_ERR_REC;
+
+
+/*
+ * ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô
+ * 500 ¥Ð¥¤¥È
+ */
+
+ECC1_ERR_REC ecc1_err_rec_log[16];
+
+ECC2_ERR_REC ecc2_err_rec_log[4];
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved2[12];
+
+
+typedef struct _STOP_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char err_description[496]; /* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó */
+ char reserved[1]; /* reserved */
+} STOP_ERR_REC, *pSTOP_ERR_REC;
+
+/*
+ * ¥¹¥Ã¥È¥×¥¨¥é¡¼¾ðÊóÉô
+ * 2048 ¥Ð¥¤¥È
+ */
+
+STOP_ERR_REC stop_err_rec_log[4];
+
+
+typedef struct _CRITICAL_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char source[14]; /* ¥½¡¼¥¹Ì¾ */
+ char err_description[496]; /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó */
+ char reserved[13]; /* reserved */
+} CRITICAL_ERR_REC, *pCRITICAL;
+
+
+/* ¡¡
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+ * 4096¥Ð¥¤¥È
+ */
+
+CRITICAL_ERR_REC critical_err_rec_log[32];
+
+
+/*
+ * ¤·¤­¤¤ÃÍȽÄêÍÑÅù¥Ç¡¼¥¿Îΰè.
+ * 256¥Ð¥¤¥È
+ */
+
+char reserved3[256]; /* reserved */
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè(PAiNTSÍÑ?)
+ * 512¥Ð¥¤¥È
+ */
+
+char reserved4[512]; /* reserved for paints ? */
+
+#pragma pack(4)
diff --git a/private/ntos/nthals/halr98mp/mips/halp.h b/private/ntos/nthals/halr98mp/mips/halp.h
new file mode 100644
index 000000000..f3d80fe71
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/halp.h
@@ -0,0 +1,708 @@
+#ident "@(#) NEC halp.h 1.19 95/06/19 10:53:45"
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+--*/
+
+/*
+ * Original source: Build Number 1.531
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 3/25-5/30 T.Samezima
+ *
+ * add Spinlock HalpEifInterruptLock
+ * define function
+ * define external references
+ *
+ * change include file
+ *
+ * del '#if defined(_JAZZ_)' with content
+ * '#if defined(_DUO_)' with content
+ *
+ ***********************************************************************
+ *
+ * S002 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S003 7/7 T.Samezima
+ *
+ * Del Arbitration point variable name
+ *
+ * Add Function define
+ *
+ *
+ ***********************************************************************
+ *
+ * S004 8/22 T.Samezima on SNES
+ *
+ * Chg Register buffer size from USHORT to ULONG
+ *
+ ***********************************************************************
+ *
+ * S005 '94.9/27 T.Samezima
+ *
+ * Add Define debug Print
+ *
+ * K000 94/10/11 N.Kugimoto
+ * Fix 807 base
+ * K001 94/10/12 N.Kugimoto
+ * add halpNmihandler
+ * K002 94/10/13 N.Kugimoto
+ * add HalpEifRegisterBuffer
+ * K003 94/10/13 N.Kugimoto
+ * add HalpEisaMemoryBase
+ * chg extern
+ *
+ * S006 '94.10/14 T.Samezima
+ * Add extern valiable
+ * Chg Change condition of ifdef
+ *
+ * A001 ataka@oa2.kb.nec.co.jp
+ * add ADD001 Resource Usage Information
+ *
+ * S007 '94.10/23 T.Samezima
+ * chg variable size from ULONG to UCHAR
+ *
+ * K004 94/12/06 N.Kugimoto
+ * Add ESM NVRAM Interface Add
+ *
+ * S008 94/12/07 N.Kugimoto
+ * Add HalpDisablePciInterrupt,HalpEnablePciInterrupt
+ *
+ * S009 94/12/23 T.Samezima
+ * Add ESM function and variable.
+ *
+ * S00a 94/01/15 T.Samezima
+ * Add ESM function.
+ *
+ * S00b 94/01/16-20 T.Samezima
+ * Add ESM variable and ESM function.
+ *
+ * S00c 94/03/10 T.Samezima
+ * Add HalpNMIFlag
+ *
+ * S00d 94/03/10 T.Samezima
+ * Add HalpLRErrorInterrupt(), HalpReadAndWritePhysicalAddr()
+ *
+ * A002 95/06/13 ataka@oa2.kb.nec.co.jp
+ * Marge build 1050
+ *
+ */
+
+
+#ifndef _HALP_
+#define _HALP_
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+#include "nthal.h"
+#include "hal.h" // A002
+
+#ifndef _HALI_ // A002
+#include "..\inc\hali.h"
+#endif
+
+/* Start S001 */
+#include "r98def.h"
+#include "r98reg.h"
+#include "r98hal.h" // S002
+/* End S001 */
+
+
+#if defined(USE_BIOS_EMULATOR) // A002
+#include "xm86.h"
+#include "x86new.h"
+#endif
+
+/* Start S002 */
+// #include "jxhalp.h"
+
+
+// A002
+// Define map register translation entry structure.
+//
+//typedef struct _TRANSLATION_ENTRY {
+// PVOID VirtualAddress;
+// ULONG PhysicalAddress;
+// ULONG Index;
+//} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+extern PVOID HalpEisaMemoryBase; //K003
+/* End S002 */
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+/* Start S002 */
+#if !defined(_R98_)
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+#endif
+/* End S002 */
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID //K000
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID //K000
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+
+/* Start S001 */
+/* Start S002 */
+VOID
+HalpInt0Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt1Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt2Dispatch(
+ VOID
+ );
+
+VOID
+HalpTimerDispatch(
+ VOID
+ );
+
+VOID
+HalpEifDispatch(
+ VOID
+ );
+/* End S002 */
+
+VOID
+HalpOutputSegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ );
+
+VOID
+HalpDisplaySegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ );
+/* End S001 */
+
+/* Start S002 */
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PINTERNAL_TRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreatePciStructures (
+ VOID
+ );
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ );
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+// S008 vvv
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ );
+// S008 ^^^
+
+VOID
+HalpReadLargeRegister(
+ IN ULONG VirtualAddress,
+ OUT PULONG UpperPart,
+ OUT PULONG LowerPart
+ );
+
+VOID
+HalpWriteLargeRegister(
+ IN ULONG VirtualAddress,
+ IN PULONG UpperPart,
+ IN PULONG LowerPart
+ );
+
+VOID
+HalpRegisterNmi(
+ VOID
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+/* Start S003 */
+VOID
+HalpHandleEif(
+ VOID
+ );
+
+ULONG
+HalpGetCause(
+ VOID
+ );
+/* End S003 */
+
+//K001
+VOID
+HalpNmiHandler(
+ VOID
+ );
+
+//K004 Start
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer,
+ ULONG Write
+);
+
+//K004 End
+//S009 vvv
+ULONG
+HalpEccError(
+ IN ULONG EifrRegister
+ );
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ );
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ );
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ );
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ );
+
+#if 0 // S00b
+VOID
+HalpStringIntoNvram(
+ IN ULONG Column,
+ IN ULONG Row,
+ IN PUCHAR String
+ );
+#endif // S00b
+//S009 ^^^
+
+// S00a vvv
+ULONG
+HalpReadPhysicalAddr(
+ IN ULONG PhysicalAddr
+ );
+// S00a ^^^
+// S00b vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ );
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ );
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ );
+// S00b ^^^
+// S00d vvv
+ULONG
+HalpReadAndWritePhysicalAddr(
+ IN ULONG PhysicalAddr
+ );
+
+BOOLEAN
+HalpLRErrorInterrupt(
+ VOID
+ );
+// S00d ^^^
+
+/* Start S005 */
+#if DBG // S006
+VOID
+R98DebugOutPut(
+ ULONG DebugPrintLevel, // Debug Level
+ PCSZ DebugMessageLed, // For LED strings. shuld be 4Byte.
+ PCSZ DebugMessage, // For DISPLAY or SIO
+ ...
+ );
+
+#define R98DbgPrint(_x_) R98DebugOutPut _x_
+#else
+#define R98DbgPrint(_x_)
+#endif
+/* End S005 */
+
+#ifdef RtlMoveMemory
+#undef RtlMoveMemory
+#undef RtlCopyMemory
+#undef RtlFillMemory
+#undef RtlZeroMemory
+
+#define RtlCopyMemory(Destination,Source,Length) RtlMoveMemory((Destination),(Source),(Length))
+VOID
+RtlMoveMemory (
+ PVOID Destination,
+ CONST VOID *Source,
+ ULONG Length
+ );
+
+VOID
+RtlFillMemory (
+ PVOID Destination,
+ ULONG Length,
+ UCHAR Fill
+ );
+
+VOID
+RtlZeroMemory (
+ PVOID Destination,
+ ULONG Length
+ );
+
+#endif // #ifdef RtlMoveMemory
+/* End S002 */
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern ULONG HalpBuiltinInterruptEnable; // S004
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+/* Start S001 */
+extern KSPIN_LOCK HalpEifInterruptLock;
+/* Start S003 */
+extern ULONG HalpInt2ArbitrationPoint;
+extern ULONG HalpInt1ArbitrationPoint;
+extern ULONG HalpInt0ArbitrationPoint;
+/* End S003 */
+extern ULONG HalpUnknownInterruptCount[];
+/* Start S002 */
+extern KAFFINITY HalpEisaBusAffinity; //K000
+extern KAFFINITY HalpPCIBusAffinity; //S006
+extern KAFFINITY HalpInt1Affinity; //S006
+extern UCHAR HalpChangeIntervalFlg[]; //S006, S007
+extern ULONG HalpChangeIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNewTimeIncrement;
+/* End S002 */
+/* End S001 */
+extern ULONG HalpEifRegisterBuffer[]; //K002,K003
+
+// S009 vvv
+extern ULONG HalpNvramValid;
+extern USHORT ErrBufferArea;
+// S009 ^^^
+// S00b vvv
+LONG HalpECC1bitDisableFlag;
+LONG HalpECC1bitDisableTime;
+ULONG HalpECC1bitScfrBuffer;
+// S00b ^^^
+extern volatile ULONG HalpNMIFlag; // R98TEMP
+
+
+// ADD001
+//
+// Resource usage information
+//
+
+#if !defined (_R98_)
+#pragma pack(1)
+#endif
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+#if !defined (_R98_)
+#pragma pack()
+#endif
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+// CMP001
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern ADDRESS_USAGE HalpMapRegisterMemorySpace;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+// CMP001
+#define IRQ_PREFERRED 0x02
+#define IRQ_VALID 0x01
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+);
+
+//
+// Temp definitions to thunk into supporting new bus extension format
+//
+// A002
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+// A002
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+// A002
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halr98mp/mips/j4cache.s b/private/ntos/nthals/halr98mp/mips/j4cache.s
new file mode 100644
index 000000000..d6e9f2dd6
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4cache.s
@@ -0,0 +1,1056 @@
+// "@(#) NEC j4cache.s 1.5 94/12/06 10:46:13"
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+//--
+
+#include "halmips.h"
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.08/22 T.Samezima on SNES
+ *
+ * Add define _DUO_
+ *
+ * K001 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ * K002 94/12/06 N.Kugimoto
+ * Fix Mem32
+ */
+
+#define _DUO_ // S001
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+ DISABLE_INTERRUPTS(t5) // disable interrupts K002
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(_MIPS_R4600) //K001
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30:
+ ENABLE_INTERRUPTS(t5) // enable interrupts K002
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts K002
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts K002
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(_MIPS_R4600) //K001
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t1) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t1) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+#if defined(_DUO_)
+
+30: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,30b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+#if defined(_DUO_)
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halr98mp/mips/j4flshbf.s b/private/ntos/nthals/halr98mp/mips/j4flshbf.s
new file mode 100644
index 000000000..b9a1cda9b
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4flshbf.s
@@ -0,0 +1,58 @@
+// "@(#) NEC j4flshbf.s 1.2 94/10/17 11:11:16"
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/j4flshio.c b/private/ntos/nthals/halr98mp/mips/j4flshio.c
new file mode 100644
index 000000000..d509d6522
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4flshio.c
@@ -0,0 +1,238 @@
+#pragma comment(exestr, "@(#) j4flshio.c 1.7 95/03/10 19:31:22 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 94/5/31 (Tue) N.Kugimoto
+ * Add At Dma Nothing to Do.( I/O Cache By R98 H/W)
+ * K002 94/9/26 N.Kugimoto
+ * Bug define bug
+ * K003 94/10/11 N.Kugimoto
+ * H/W Work around for LR4360
+ * K004 94/10/18 N.Kugimoto
+ * Add Flush LR4360 Read Cache at DMA READ(MemotryToDevice)
+ * K005 95/03/10 N.Kugimoto
+ * H/W flush
+ */
+
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+#if defined(_R98_)
+ // K001,K002
+ // R98 I/O Cache Supported So Nothing to Do Dma Operation!!.
+ //
+ if (DmaOperation == TRUE){
+ // LR4360 Bug. IO cache Flush!!
+ //
+ // MemoryToDevice
+ //
+ if(ReadOperation==FALSE) //K004
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K003,K005
+ return;
+ }
+#endif
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/j4prof.c b/private/ntos/nthals/halr98mp/mips/j4prof.c
new file mode 100644
index 000000000..80ead3885
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4prof.c
@@ -0,0 +1,362 @@
+#ident "@(#) NEC j4prof.c 1.4 95/06/19 10:54:59"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/23-5/25 T.Samezima
+ *
+ * change establish interrupt interval setting
+ * init PROFILE interrupt interval
+ * range of PROFILE interrupt interval
+ *
+ * add restart interrupt
+ * calculate change of unit from 100ns to 1us
+ *
+ * del calculate from interrupt interval to clock number
+ *
+ ***********************************************************************
+ *
+ * S002 94.07/5 T.Samezima
+ *
+ * change Irql level from PROFILE_LEVEL to EIF_LEVEL
+ *
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - resolve compile wornings.
+ */
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+/* Start S001 */
+ULONG HalpProfileInterval = DEFAULT_PROFILETIMER_INTERVAL;
+/* End S001 */
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ /* Start S002 */
+ KeRaiseIrql(EIF_LEVEL, &OldIrql);
+ /* End S002 */
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ *Frequency = RtlConvertUlongToLargeInteger(HalpProfileCountRate);
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ return RtlLargeIntegerAdd(PerformanceCounter,
+ RtlConvertUlongToLargeInteger(CurrentCount));
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT);
+ /* Start S001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+ /* End S001 */
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].LowPart = 0;
+ HalpPerformanceCounter[Prcb->Number].HighPart = 0;
+ /* Start S001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ /* End S001 */
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+// LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ /* Start S001 */
+ if (Interval < MINIMUM_PROFILETIMER_INTERVAL) {
+ Interval = MINIMUM_PROFILETIMER_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILETIMER_INTERVAL) {
+ Interval = MAXIMUM_PROFILETIMER_INTERVAL;
+ }
+
+ HalpProfileInterval = Interval;
+ /* End S001 */
+
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Reserved // A002
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ /* Start S001 */
+ ULONG TempValue;
+ /* End S001 */
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ /* Start S001 */
+ TempValue = HalpProfileInterval / 10;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue);
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long, TempValue);
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ /* End S001 */
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Reserved // A002
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT);
+ /* Start S001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ /* End S001 */
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jazznvr.h b/private/ntos/nthals/halr98mp/mips/jazznvr.h
new file mode 100644
index 000000000..79ab847cf
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jazznvr.h
@@ -0,0 +1,164 @@
+#ident "@(#) NEC jazznvr.h 1.2 94/10/17 12:10:14"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jazznvr.h
+
+Abstract:
+
+ This module contains definitions for the Jazz non-volatile ram structures.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 '94.6/02 T.Samezima
+ *
+ * Change NV_CONFIGURATION structure and define
+ *
+ ***********************************************************************
+ *
+ * S002 '94.8/22 T.Samezima on SNES
+ *
+ * Chg NV_CONFIGURATION structure and define
+ *
+ *
+ */
+
+
+#ifndef _JAZZNVR_
+#define _JAZZNVR_
+
+//
+// Define the private configuration packet structure, which contains a
+// configuration component as well as pointers to the component's parent,
+// peer, child, and configuration data.
+//
+
+typedef struct _CONFIGURATION_PACKET {
+ CONFIGURATION_COMPONENT Component;
+ struct _CONFIGURATION_PACKET *Parent;
+ struct _CONFIGURATION_PACKET *Peer;
+ struct _CONFIGURATION_PACKET *Child;
+ PVOID ConfigurationData;
+} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET;
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ USHORT Version;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+//
+// Defines for the volatile and non-volatile configuration tables.
+//
+
+#if defined(_R98_)
+
+// Start S002
+#define NUMBER_OF_ENTRIES 50 // REV 05 1994/05/23
+#define LENGTH_OF_IDENTIFIER 516 // REV 05 1994/05/23
+#define LENGTH_OF_DATA 2048 // REV 05 1994/05/23
+#define LENGTH_OF_ENVIRONMENT 1024 // R98 support 1994/01/31(REV 01)
+#define LENGTH_OF_EISA_DATA 2044 // R98 support 1994/01/31(REV 01)
+#define LENGTH_OF_PCI_DATA 512 // REV 06 1994/06/17
+#define LENGTH_OF_ITF_DATA 128 // R98 support 1994/01/31(REV 01)
+#define NUMBER_MEM_ENTRIES 90 // REV 05 1994/05/23
+#define LENGTH_MEM_IDENTIFIER 1024 // REV 05 1994/05/23
+// End S002
+
+#else // #if defined(_R98_)
+
+#define NUMBER_OF_ENTRIES 32
+#define LENGTH_OF_IDENTIFIER 504
+#define LENGTH_OF_DATA 2048
+#define LENGTH_OF_ENVIRONMENT 1024
+
+#endif // #if defined(_R98_)
+
+#define MAXIMUM_ENVIRONMENT_VALUE 128
+
+//
+// The volatile configuration table structure.
+//
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+//
+// The non-volatile configuration table structure.
+//
+
+
+typedef struct _NV_CONFIGURATION {
+
+// Start S002
+#if defined(_R98_)
+
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; // R98 support 1994/01/31(REV 01)
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER]; // R98 support 1994/01/31(REV 01)
+ UCHAR Data[LENGTH_OF_DATA]; // R98 support 1994/01/31(REV 01)
+ UCHAR Checksum1[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT]; // R98 support 1994/01/31(REV 01)
+ UCHAR Checksum2[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR EisaData[LENGTH_OF_EISA_DATA]; // R98 support 1994/01/31(REV 01)
+ UCHAR Checksum3[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR EthernetAddress[8]; // R98 support 1994/01/31(REV 01)
+ UCHAR NmiVector[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR ItfUseArea[LENGTH_OF_ITF_DATA]; // R98 support 1994/01/31(REV 01)
+ UCHAR Reserved[1608]; // R98 support 1994/01/31(REV 01)
+
+#else // #if defined(_R98_)
+
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+ UCHAR Checksum1[4];
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT];
+ UCHAR Checksum2[4];
+
+#endif // #if defined(_R98_)
+// End S002
+
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+//
+// Non-volatile ram layout.
+//
+
+#if defined(MIPS)
+
+#define NVRAM_CONFIGURATION NVRAM_VIRTUAL_BASE
+#define NVRAM_SYSTEM_ID NVRAM_VIRTUAL_BASE + 0x00002000
+
+#endif
+
+#endif // _JAZZNVR_
diff --git a/private/ntos/nthals/halr98mp/mips/jxbeep.c b/private/ntos/nthals/halr98mp/mips/jxbeep.c
new file mode 100644
index 000000000..d39405c78
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxbeep.c
@@ -0,0 +1,131 @@
+#ident "@(#) NEC jxbeep.c 1.2 94/10/17 11:22:04"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxdisp.c b/private/ntos/nthals/halr98mp/mips/jxdisp.c
new file mode 100644
index 000000000..1882d69ee
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxdisp.c
@@ -0,0 +1,3132 @@
+#ident "@(#) NEC jxdisp.c 1.19 95/07/05 16:32:19"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.10 93/12/01 12:18:22" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.9 93/11/19 13:48:37" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.7 93/11/18 14:57:07" ) */
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+History:
+
+--*/
+
+/*
+ * M001 1993.10.28 A. Kuriyama@oa2
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Add : Initialize routine for Cirrus CL5428.
+ *
+ * Notes : HalpCirrusInterpretCmdStream() based on VgaInterpretCmdStream()
+ * in Cirrus Miniport Driver.
+ *
+ * M002 1993.11.10 M. Kusano
+ *
+ * - initialize bug fixed
+ *
+ * Add : Color palette initialize sequence.
+ *
+ * - scroll bug fixed
+ *
+ * Add : 32bit Move Memory routine.
+ *
+ * M003 1993.11.18 A. Kuriyama@oa2
+ *
+ * - Exchanged HalpMoveMemory32()
+ *
+ * Add : HalpMoveMemory32()
+ *
+ * M004 1993.11.18 M. Kusano
+ *
+ * - Modefy HalpMoveMemory32()
+ *
+ * Bug fix
+ *
+ *
+ * M005 1993.11.30 M.Kusano
+ *
+ * - Modefy Display Identifier
+ * Cirrus GD5428 -> necvdfrb
+ *
+ * #if defined(DBCS) && defined(_MIPS_)
+ *
+ * M006 1994.10.29 T.Samezima
+ *
+ * - Add display mode on vga
+ *
+ * #endif // DBCS && _MIPS_
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 in Miniport Driver
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ ***************************************************************
+ *
+ * S001 1994.06/06 T.Samezima
+ *
+ * - Modify for R98 MIPS R4400
+ *
+ * Change : memory and I/O Address
+ *
+ ***********************************************************************
+ *
+ * S002 1994.6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***************************************************************
+ *
+ * S003 1994.07/12 T.Samezima
+ *
+ * Change : I/O Address
+ *
+ *
+ * K000 94/10/11 N.Kugimoto
+ * fix 807 base
+ * K001 94/10/13 N.Kugimoto
+ * Chg resest-->reset
+ *
+ * S004 94/10/25 T.Samezima
+ * Add define _DUO_
+ *
+ * S005 94/11/23 T.Samezima
+ * Add Marge TGA(DEC21030) initialize rotine (program by T.Katoh 1994.11/15)
+ *
+ * S006 94/11/29 T.Katoh
+ * Bug Fix
+ *
+ * S007 94/12/07 T.Samezima
+ * Chg Color palet change.
+ *
+ * S008 94/12/12 T.Samezima
+ * Add Config read function.
+ * Chg Change PCI configuration read function from READ_REGISTER_ULONG
+ * to PciReadConfigUlong.
+ *
+ * S009 94/12/24-95/1/9 T.Samezima
+ * Add ESM logic.
+ *
+ * S00a 95/01/14 T.Samezima
+ * Chg Display string into nvram.
+ *
+ * S00b 95/03/14 T.Samezima
+ * Chg TGA parametor change.
+ * Add stall execution.
+ * Del Warning
+ * S00c 95/04/4 T.Samezima
+ * Chg TGA parametor change for adjust standard of VESA
+ * Windows-NT 3.51
+ * K1001 '95.7.5 N.Kugimoto
+ * Chg TGA parametor change for adjust standard of VESA
+ *
+ */
+
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+/* START M001 */
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+/* END M001 */
+#include "string.h"
+/* START S005 */
+#include <tga.h>
+/* END S005 */
+
+#define _DUO_ // S004
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayG364Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayVxlSetup (
+ VOID
+ );
+
+/* START M001 */
+VOID
+HalpDisplayCirrusSetup (
+ VOID
+ );
+
+BOOLEAN
+HalpCirrusInterpretCmdStream (
+ PUSHORT pusCmdStream
+ );
+/* END M001 */
+
+/* START M002 */
+VOID
+Write_Dbg_Uchar(
+PUCHAR,
+UCHAR
+);
+/* END M002 */
+
+/* START M003 */
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+);
+/* END M003 */
+/* START S005 */
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ );
+/* END S005 */
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+#define G300_VIDEO_CONTROL ((PG300_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_CONTROL ((PG364_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_RESET ((PVIDEO_REGISTER)0x403fe000)
+
+//
+// Define memory access constants for VXL
+//
+
+#define VXL_VIDEO_MEMORY_BASE 0x40000000
+#define BT484_BASE ((PBT484_REGISTERS)0x403fd000)
+#define CLOCK_BASE ((PUCHAR)0x403fe000)
+#define JAGUAR_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+/* START M001 */
+/* Start S001 */
+#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+/* End S001 */
+#define CIRRUS_OFFSET ((PUSHORT)0x3b0)
+/* END M001 */
+
+/* START S005 */
+#define KSEG1_BASE 0xa0000000
+#define TGA_REGISTER_BASE ((ULONG)0x403ff000) // S006
+#define R98_PCI_SPACE_BASE ((ULONG)0xc0000000) // S006
+#define R98_PCI1_ID ((PULONG)(0x18ca8800 | KSEG1_BASE))
+#define R98_PCI1_MEM_BASE ((PULONG)(0x18ca8810 | KSEG1_BASE))
+#define R98_PCI1_CS_REG ((PULONG)(0x18ca8804 | KSEG1_BASE))
+#define R98_PCI2_ID ((PULONG)(0x18ca9000 | KSEG1_BASE))
+#define R98_PCI2_MEM_BASE ((PULONG)(0x18ca9010 | KSEG1_BASE))
+#define R98_PCI2_CS_REG ((PULONG)(0x18ca9004 | KSEG1_BASE))
+#define R98_PCI3_ID ((PULONG)(0x18ca9800 | KSEG1_BASE))
+#define R98_PCI3_MEM_BASE ((PULONG)(0x18ca9810 | KSEG1_BASE))
+#define R98_PCI3_CS_REG ((PULONG)(0x18ca9804 | KSEG1_BASE))
+
+/* END S005 */
+
+//
+// The three type of g364 boards we support
+//
+
+#define JAZZG364 1
+#define MIPSG364 2
+#define OLIVETTIG364 3
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayResetRegisterBase = 0;
+ULONG HalpDisplayVxlClockRegisterBase = 0;
+ULONG HalpDisplayVxlBt484RegisterBase = 0;
+ULONG HalpDisplayVxlJaguarRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpG364Type = 0;
+/* START M001 */
+LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0};
+/* END M001 */
+
+// S008 vvv
+ULONG
+PciReadConfigUlong(
+ PULONG Addr
+ )
+{
+ ULONG reg;
+ ULONG regTmp;
+ ULONG returnValue;
+
+ reg = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN );
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, (reg & 0xffbfffff));
+
+ returnValue = READ_PORT_ULONG( Addr );
+
+ regTmp = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS );
+ if( regTmp & 0x80000000 ){
+ WRITE_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS, 0x80000000);
+ regTmp = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE );
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE, (regTmp & 0xffbfffff) );
+ returnValue = 0xffffffff;
+ }
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, reg);
+ return returnValue;
+}
+// S008 ^^^
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("HalpInitializeDisplay0\n");
+#endif
+ /* END M002 */
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("ConfigurationEntry Found\n");
+#endif
+ /* END M002 */
+
+ if (ConfigurationEntry == NULL) {
+ /* START S005 */
+ MatchKey = 1;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ /* END S005 */
+ return FALSE;
+ /* START S005 */
+ }
+ /* END S005 */
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G300")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG300Setup;
+
+ HalpDisplayControlBase =
+ ((PJAZZ_G300_CONFIGURATION_DATA)
+ (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = JAZZG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Mips G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = MIPSG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "OLIVETTI_G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = OLIVETTIG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "VXL")) {
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("VXL config found\n");
+#endif
+ /* END M002 */
+ HalpDisplayControllerSetup = HalpDisplayVxlSetup;
+ HalpDisplayVxlBt484RegisterBase = 0x60100000;
+ HalpDisplayVxlClockRegisterBase = 0x60200000;
+ HalpDisplayVxlJaguarRegisterBase = 0x60300000;
+
+ /* START M001 */
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "necvdfrb")) { /* M005 */
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("necvdfrb Config found\n"); /* M005 */
+#endif
+ /* END M002 */
+
+ HalpDisplayControllerSetup = HalpDisplayCirrusSetup;
+ /* Start S001,S003 */
+ HalpDisplayControlBase = 0x18cc0000;
+ /* End S001,S003 */
+ /* END M001 */
+
+ } else {
+
+ /* START S005 */
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "10110004")) {
+ HalpDisplayControllerSetup = HalpDisplayTgaSetup;
+
+ if (PciReadConfigUlong(R98_PCI1_ID) == 0x00041011) { // S006
+ if ((PciReadConfigUlong(R98_PCI1_CS_REG) & 0x00000002) == 2){ // S006
+ HalpDisplayControlBase
+ = (PciReadConfigUlong(R98_PCI1_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE // S006
+ + TGA_REG_SPC_OFFSET;
+ } else {
+ return FALSE;
+ }
+ } else if (PciReadConfigUlong(R98_PCI2_ID) == 0x00041011) { // S006
+ if ((PciReadConfigUlong(R98_PCI2_CS_REG) & 0x00000002) == 2){ // S006
+ HalpDisplayControlBase
+ = (PciReadConfigUlong(R98_PCI2_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE // S006
+ + TGA_REG_SPC_OFFSET;
+ } else {
+ return FALSE;
+ }
+ } else if (PciReadConfigUlong(R98_PCI3_ID) == 0x00041011) { // S006
+ if ((PciReadConfigUlong(R98_PCI3_CS_REG) & 0x00000002) == 2){ // S006
+ HalpDisplayControlBase
+ = (PciReadConfigUlong(R98_PCI3_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE // S006
+ + TGA_REG_SPC_OFFSET;
+ } else {
+ return FALSE;
+ }
+ }
+
+ } else {
+ /* END S005 */
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("DisplayTypeUnknown\n");
+#endif
+ /* END M002 */
+
+ HalpDisplayTypeUnknown = TRUE;
+ /* START S005 */
+ }
+ /* END S005 */
+ }
+ /* START M001 */
+ }
+ /* END M001 */
+ }
+ }
+ }
+ }
+
+ Child = ConfigurationEntry->Child;
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("parameters read start\n");
+#endif
+ /* END M002 */
+
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ /* START M002 */
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpScrollLine =
+ 1024 * HalpCharacterHeight;
+ }else{
+ /* END M002 */
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+
+ /* START M002 */
+ }
+ /* END M002 */
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ /* START M002 */
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpDisplayWidth =
+ 1024 / HalpCharacterWidth;
+
+ }else{
+ /* END M002 */
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+ /* START M002 */
+ }
+ /* END M002 */
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("Mem get \n");
+#endif
+ /* END M002 */
+
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ /* START M001 */
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+ /* Start S001 */
+ HalpCirrusPhigicalVideo.HighPart = 0;
+ HalpCirrusPhigicalVideo.LowPart = MEM_VGA | EISA_MEMORY_PHYSICAL_BASE;
+ /* End S001 */
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+ else {
+ /* END M001 */
+ /* START S005 */
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT;
+ } else {
+ /* END S005 */
+ Pte.PFN = VIDEO_MEMORY_BASE >> PAGE_SHIFT;
+ /* START S005 */
+ }
+ /* END S005 */
+ /* START M001 */
+ }
+ /* END M001 */
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayVxlSetup) {
+
+ //
+ // If this is VXL then map a page for the
+ // brooktree base
+ // Clock base
+ // jaguar base
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlBt484RegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 2) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlClockRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlJaguarRegisterBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+
+ } else {
+
+ //
+ // If we have a G364, use the page before last to map the reset register.
+ //
+
+ if (HalpDisplayControllerSetup == HalpDisplayG364Setup) {
+ Pte.PFN = ((ULONG)HalpDisplayResetRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+ }
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+
+ HalpInitDisplayStringIntoNvram(); // S009
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+
+ HalpSetInitDisplayTimeStamp(); // S009
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters //K001
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpSuccessOsStartUp(); // S009
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G300B display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG BackPorch;
+ PULONG Buffer;
+ ULONG DataLong;
+ ULONG FrontPorch;
+ ULONG HalfLineTime;
+ ULONG HalfSync;
+ ULONG Index;
+ ULONG Limit;
+ ULONG MultiplierValue;
+ ULONG ScreenUnitRate;
+ ULONG VerticalBlank;
+ ULONG ShortDisplay;
+ ULONG TransferDelay;
+
+ //
+ // Disable the G300B display controller.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Initialize the G300B boot register value.
+ //
+
+ ScreenUnitRate =
+ (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ MultiplierValue = 125000 / (ScreenUnitRate / 4);
+ DataLong = 0;
+ ((PG300_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue;
+ ((PG300_VIDEO_BOOT)(&DataLong))->ClockSelect = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Boot.Long, DataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G300B operational values.
+ //
+
+ HalfSync =
+ (HalpMonitorConfigurationData.HorizontalSync * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->HorizonalSync.Long, HalfSync);
+
+ BackPorch =
+ (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / ScreenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BackPorch.Long, BackPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ HalfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineTime.Long, HalfLineTime * 2);
+ FrontPorch =
+ (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) / ScreenUnitRate;
+
+ ShortDisplay = HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ShortDisplay.Long, ShortDisplay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BroadPulse.Long,
+ HalfLineTime - FrontPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ VerticalBlank = (HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalBackPorch -
+ (HalpMonitorConfigurationData.VerticalSync * 2)) * 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalBlank.Long,
+ VerticalBlank);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineStart.Long, LINE_START_VALUE);
+ if (BackPorch < ShortDisplay) {
+ TransferDelay = BackPorch - 1;
+ } else {
+ TransferDelay = ShortDisplay - 1;
+ }
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->TransferDelay.Long, TransferDelay);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - TransferDelay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->PixelMask.Long, G300_PIXEL_MASK_VALUE);
+
+ //
+ // Initialize the G300B control parameters.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->SeparateSync = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G300_DELAY_SYNC_CYCLES;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BlankOutput = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->AddressStep = 2;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Set up the color map for two colors.
+ //
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[1], 0x900000);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpDisplayG364Setup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G364 display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG videoClock;
+ ULONG videoPeriod;
+ ULONG backPorch;
+ ULONG dataLong;
+ ULONG frontPorch;
+ ULONG halfLineTime;
+ ULONG halfSync;
+ PULONG buffer;
+ ULONG index;
+ ULONG limit;
+ ULONG multiplierValue;
+ ULONG screenUnitRate;
+ ULONG shortDisplay;
+ ULONG transferDelay;
+ ULONG verticalBlank;
+
+ //
+ // Reset the G364 display controller.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_RESET->Long,
+ 0);
+
+ //
+ // Initialize the G364 boot register value.
+ //
+
+ if (HalpG364Type == MIPSG364) {
+
+ videoClock = 5000000;
+
+ } else {
+
+ videoClock = 8000000;
+
+ }
+
+ videoPeriod = 1000000000 / (videoClock / 1000);
+
+ screenUnitRate = (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ multiplierValue = videoPeriod / (screenUnitRate / 4);
+ dataLong = 0;
+ ((PG364_VIDEO_BOOT)(&dataLong))->Multiplier = multiplierValue;
+ ((PG364_VIDEO_BOOT)(&dataLong))->ClockSelect = 1;
+ ((PG364_VIDEO_BOOT)(&dataLong))->MicroPort64Bits = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Boot.Long,
+ dataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G364 control parameters.
+ //
+
+ dataLong = 0;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DelaySync = G364_DELAY_SYNC_CYCLES;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->AddressStep = G364_ADDRESS_STEP_INCREMENT;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DisableCursor = 1;
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize the G364 control parameters for VDR1 with patch for HSync
+ // problem during the VBlank. The control register is set to 0xB03041
+ // according to the hardware specs. @msu, Olivetti, 5/14/92
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->VideoOnly = 1;
+
+ } else {
+
+ //
+ // Only set tesselated sync in non-olivetti G364 cards when
+ // vertical frontporch is set to 1
+ //
+
+ if (HalpMonitorConfigurationData.VerticalFrontPorch != 1) {
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->PlainSync = 1;
+ }
+
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Initialize the G364 operational values.
+ //
+
+ halfSync = (HalpMonitorConfigurationData.HorizontalSync * 1000) / screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->HorizontalSync.Long,
+ halfSync);
+
+ backPorch = (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / screenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BackPorch.Long,
+ backPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ halfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) /
+ screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineTime.Long,
+ halfLineTime * 2);
+
+ frontPorch = (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) /
+ screenUnitRate;
+
+ shortDisplay = halfLineTime - ((halfSync * 2) + backPorch + frontPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ShortDisplay.Long,
+ shortDisplay);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize Broad Pulse, Vertical PreEqualize and Vertical
+ // PostEqualize registers to work with Olivetti monitors.
+ // @msu, Olivetti, 5/14/92
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ 0x30);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ } else {
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ halfLineTime - frontPorch);
+
+ // NOTE: changed the order to simplify if statement .
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ HalpMonitorConfigurationData.VerticalFrontPorch * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ }
+
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ verticalBlank = (HalpMonitorConfigurationData.VerticalBackPorch - 1) * 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalBlank.Long,
+ verticalBlank);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineStart.Long,
+ LINE_START_VALUE);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Fixes for Olivetti monitors, @msu, Olivetti
+ //
+
+ transferDelay = 30; // @msu
+
+ } else {
+
+ if (backPorch < shortDisplay) {
+ transferDelay = backPorch - 1;
+ } else {
+ transferDelay = shortDisplay - 4;
+ }
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->TransferDelay.Long,
+ transferDelay);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - transferDelay);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->PixelMask.Long,
+ 0xFFFFFF);
+
+ //
+ // Enable video
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->EnableVideo = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Set up the color map for two colors.
+ // NOTE: this device is not RGB but BGR.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[1], 0x000090);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)VIDEO_MEMORY_BASE;
+ limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpDisplayVxlSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the JazzVxl Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ UCHAR DataChar;
+ UCHAR CmdReg0;
+ ULONG Status;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+
+
+ //
+ // Define clock value for the ICS part (pS)
+ //
+
+ LONG ClockResList[32] = { 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4,42918,40984,38760,36724,33523,31017,
+ 29197,27548,24882,23491,22482,21468,20509,19920,
+ 18692,18054,16722,15015,14773,14053,13040, 4};
+
+ JAGUAR_REG_INIT JagInitData;
+
+ LONG HorDisplayTime;
+ LONG HorResolutionDiv;
+ LONG RequestedClockPeriod;
+ LONG CurrentClockError;
+ LONG MinErrorValue;
+ USHORT MinErrorIndex;
+ LONG ShiftClockPeriod;
+
+ USHORT BoardTypeBt485;
+
+
+
+ //
+ // Determine if this is a Bt484 or Bt485 board. To do this write a 1 to command
+ // register bit 07 then write 01 to the address register 0. This will enable
+ // read/writes to command register 3 on a Bt485 but not on a Bt484. Clear
+ // Command register 3 then read it back. On a Bt485 the return value will be 0x00,
+ // on a Bt484 it will be 0x40.
+ //
+ // Get the value in command register 0, then set bit 07
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Command0.Byte);
+ DataChar |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,DataChar);
+
+ //
+ // Write 0x01 to the address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Clear command register 3
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,0x00);
+
+ //
+ // Read Command Register 3 back and compare
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Status.Byte);
+
+ if (DataChar != 0x00) {
+
+ //
+ // This is a Bt484
+ //
+
+ BoardTypeBt485 = 0;
+ JagInitData.Bt485Multiply = 0;
+
+ } else {
+
+ //
+ // This is a Bt485
+ //
+
+ BoardTypeBt485 = 1;
+ JagInitData.Bt485Multiply = 0;
+ }
+
+ //
+ // Calculate the requested clock frequency then find the closest match in the
+ // ICS clock frequency table. The requested clock frequency in picoseconds =
+ //
+ // Horizontal display time * 1000000
+ // ---------------------------------
+ // horizontal resolution
+ //
+ //
+
+ HorDisplayTime = HalpMonitorConfigurationData.HorizontalDisplayTime * 1000;
+ HorResolutionDiv = HalpMonitorConfigurationData.HorizontalResolution;
+ RequestedClockPeriod = HorDisplayTime / HorResolutionDiv;
+
+ //
+ // Check for a Bt485 frequency
+ //
+
+ if ((BoardTypeBt485 == 1) && (RequestedClockPeriod < ClockResList[30])) {
+ RequestedClockPeriod = RequestedClockPeriod * 2;
+ JagInitData.Bt485Multiply = 1;
+ }
+
+ MinErrorIndex = 0;
+
+ //
+ // Gaurentee a maximum starting error
+ //
+
+ MinErrorValue = RequestedClockPeriod + 1;
+ for (Index = 0; Index < 32; Index++) {
+
+ //
+ // Calculate the absolute value of clock error and find the
+ // closest match in the array of clock values
+ //
+
+ CurrentClockError = RequestedClockPeriod - ClockResList[Index];
+ if (CurrentClockError < 0) {
+ CurrentClockError *= -1;
+ }
+
+ if (CurrentClockError < MinErrorValue) {
+ MinErrorValue = CurrentClockError;
+ MinErrorIndex = (USHORT)Index;
+ }
+ }
+
+ //
+ // We now have a closest match in the clock array, now calculate the
+ // values for the Bt484/Bt485 register values
+ //
+
+ JagInitData.ClockFreq = (UCHAR)MinErrorIndex; // S002
+ JagInitData.BitBltControl = 1;
+ JagInitData.TopOfScreen = 0;
+ JagInitData.XferLength = 0x200;
+ JagInitData.VerticalInterruptLine = 4;
+ JagInitData.HorizontalDisplay = HalpMonitorConfigurationData.HorizontalResolution;
+
+ //
+ // All jaguar timing values are based on the brooktree shift clock value which
+ // is the clock frequency divided by 4. (period * 4) If this is a Bt485 using
+ // its internal 2x clock multiplier than is is period * 2; (freq * 2 / 4)
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 2;
+ } else {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 4;
+ }
+
+ JagInitData.HorizontalBlank = (USHORT)( ((HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod); // S002
+
+ JagInitData.HorizontalBeginSync = (USHORT)((HalpMonitorConfigurationData.HorizontalFrontPorch * 1000)
+ / ShiftClockPeriod); // S002
+
+ JagInitData.HorizontalEndSync = (USHORT)(((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod); // S002
+
+ JagInitData.HorizontalLine = JagInitData.HorizontalBlank +
+ (HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ JagInitData.VerticalBlank = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalBeginSync = HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalEndSync = HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalSync;
+
+ JagInitData.VerticalLine = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalResolution;
+
+ //
+ // Start ICS Clock pll and stabilize.
+ //
+
+ WRITE_REGISTER_UCHAR(CLOCK_BASE,JagInitData.ClockFreq);
+
+ //
+ // Wait 10 uS for PLL clock to stabilize on the video board
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+
+ //
+ // Initialize Bt484 Command Register 0 to:
+ //
+ // 8 Bit DAC Resolution
+ //
+
+ CmdReg0 = 0;
+ ((PBT484_COMMAND0)(&CmdReg0))->DacResolution = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->GreenSyncEnable = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->SetupEnable = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Initialize Command Register 1 to:
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND1)(&DataChar))->BitsPerPixel = VXL_EIGHT_BITS_PER_PIXEL;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command1.Byte,DataChar);
+
+ //
+ // Initialize Command Register 2 to:
+ //
+ // SCLK Enabled
+ // TestMode disabled
+ // PortselMask Non Masked
+ // PCLK 1
+ // NonInterlaced
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND2)(&DataChar))->SclkDisable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->TestEnable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PortselMask = 1;
+ ((PBT484_COMMAND2)(&DataChar))->PclkSelect = 1;
+ ((PBT484_COMMAND2)(&DataChar))->InterlacedDisplay = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PaletteIndexing = CONTIGUOUS_PALETTE;
+ ((PBT484_COMMAND2)(&DataChar))->CursorMode = BT_CURSOR_WINDOWS;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command2.Byte,DataChar);
+
+ //
+ // if JagInitData.ClockFreq bit 8 is set then this is a Bt485 mode that requires
+ // the internal 2x clock multiplier to be enabled.
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+
+ //
+ // To access cmd register 3, first set bit CR17 in command register 0
+ //
+
+ CmdReg0 |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Write a 0x01 to Address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Write to cmd register 3 in the status register location. Cmd3 is initialized
+ // to turn on the 2x clock multiplier.
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND3)(&DataChar))->ClockMultiplier = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,DataChar);
+
+ //
+ // Allow 10 uS for the 2x multiplier to stabilize
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+ }
+
+ //
+ // Initialize Color Palette. Only init the first 2 entries
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+
+ //
+ // Entry 0 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 1 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x90);
+
+ //
+ // Initialize Cursor and Overscan color.
+ //
+ // Set address pointer base.
+ // Zero 4 entries.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColorWrAddress.Byte,0);
+ for (Index = 0; Index < 4*3; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColor.Byte,0);
+ }
+
+ //
+ // Initialize cursor RAM
+ //
+ // Set address pointer to base of ram.
+ // Clear both planes
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+ for (Index = 0; Index < 256; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorRam.Byte,0);
+ }
+
+ //
+ // Initialize cursor position registers--cursor off.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXHigh.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYHigh.Byte,0);
+
+ //
+ // Initialize pixel mask.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PixelMask.Byte,0xFF);
+
+ //
+ // Init Jaguar Registers
+ //
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->TopOfScreen.Short,
+ JagInitData.TopOfScreen);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBlank.Short,
+ JagInitData.HorizontalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBeginSync.Short,
+ JagInitData.HorizontalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalEndSync.Short,
+ JagInitData.HorizontalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalLine.Short,
+ JagInitData.HorizontalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBlank.Short,
+ JagInitData.VerticalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBeginSync.Short,
+ JagInitData.VerticalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalEndSync.Short,
+ JagInitData.VerticalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalLine.Short,
+ JagInitData.VerticalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->XferLength.Short,
+ JagInitData.XferLength);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalInterruptLine.Short,
+ JagInitData.VerticalInterruptLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalDisplay.Short,
+ JagInitData.HorizontalDisplay);
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->BitBltControl.Byte,
+ JagInitData.BitBltControl);
+
+ //
+ // Enable timing.
+ //
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->MonitorControl,MONITOR_TIMING_ENABLE);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VXL_VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+/* START M001 */
+VOID
+HalpDisplayCirrusSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Cirrus VGA display controlleer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG dac_address, dac_reg;
+
+#if defined(DBCS) && defined(_MIPS_)
+ // M006 vvv
+ ULONG verticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+ if( verticalFrequency < 66 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 72Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 800:
+ if( verticalFrequency < 58 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 56Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_56);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 66 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 72Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 1024:
+ // S005 vvv
+ if( verticalFrequency < 52 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 87Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else
+ // S005 ^^^
+ if( verticalFrequency < 65 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 78 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 70Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 87Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+ default:
+ // S005 vvv
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+// return;
+ // S005 ^^^
+ }
+ // M006 ^^^
+#else // defined(DBCS) && defined(_MIPS_)
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("640x480 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_640x480_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 800:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("800x600 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_800x600_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 1024:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("1024x768 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_1024x768_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ default:
+ return;
+ }
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("color set\n");
+#endif
+
+ dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT;
+ dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT;
+
+
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0);
+
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2));
+ /* END M002 */
+
+ //
+ // Set the video memory to address color one.
+ //
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+// Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+// HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+ /* START M002 */
+ Limit = (1024 *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+ /* END M002 */
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+BOOLEAN
+HalpCirrusInterpretCmdStream(
+ PUSHORT pusCmdStream
+ )
+
+/*++
+
+Routine Description:
+
+ Interprets the appropriate command array to set up VGA registers for the
+ requested mode. Typically used to set the VGA into a particular mode by
+ programming all of the registers
+
+Arguments:
+
+
+ pusCmdStream - array of commands to be interpreted.
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+Revision History:
+--*/
+
+
+
+{
+ ULONG ulCmd;
+ ULONG ulPort;
+ UCHAR jValue;
+ USHORT usValue;
+ ULONG culCount;
+ ULONG ulIndex;
+ ULONG ulBase;
+ if (pusCmdStream == NULL) {
+
+ return TRUE;
+ }
+
+ ulBase = (ULONG)CIRRUS_BASE+0x3b0;
+
+ //
+ // Now set the adapter to the desired mode.
+ //
+
+ while ((ulCmd = *pusCmdStream++) != EOD) {
+
+ //
+ // Determine major command type
+ //
+
+ switch (ulCmd & 0xF0) {
+
+ //
+ // Basic input/output command
+ //
+
+ case INOUT:
+
+ //
+ // Determine type of inout instruction
+ //
+
+ if (!(ulCmd & IO)) {
+
+ //
+ // Out instruction. Single or multiple outs?
+ //
+
+ if (!(ulCmd & MULTI)) {
+
+ //
+ // Single out. Byte or word out?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // Single byte out
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort),
+ jValue);
+ /* END M002 */
+
+
+ } else {
+
+ //
+ // Single word out
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff));
+ /* END M002 */
+
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8));
+ /* END M002 */
+
+
+ }
+
+ } else {
+
+ //
+ // Output a string of values
+ // Byte or word outs?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // String byte outs. Do in a loop; can't use
+ // VideoPortWritePortBufferUchar because the data
+ // is in USHORT form
+ //
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+
+ while (culCount--) {
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ jValue);
+ /* END M002 */
+
+
+ }
+
+ } else {
+
+ //
+ // String word outs
+ //
+
+ ulPort = *pusCmdStream++;
+ culCount = *pusCmdStream++;
+//
+// Buffering out is not use on the Miniport Driver for R96 machine.
+//
+
+ /* START L001 */
+
+ while(culCount--)
+ {
+ usValue = *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort), (UCHAR) (usValue & 0x00ff));
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort+1), (UCHAR) (usValue >> 8));
+ /* END M002 */
+
+ }
+
+ /* END L001 */
+ }
+ }
+
+ } else {
+
+ // In instruction
+ //
+ // Currently, string in instructions aren't supported; all
+ // in instructions are handled as single-byte ins
+ //
+ // Byte or word in?
+ //
+
+ if (!(ulCmd & BW)) {
+ //
+ // Single byte in
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+
+ } else {
+
+ //
+ // Single word in
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = READ_REGISTER_USHORT((PUSHORT)
+ (ulBase+ulPort));
+ }
+
+ }
+
+ break;
+
+ //
+ // Higher-level input/output commands
+ //
+
+ case METAOUT:
+
+ //
+ // Determine type of metaout command, based on minor
+ // command field
+ //
+ switch (ulCmd & 0x0F) {
+
+ //
+ // Indexed outs
+ //
+
+ case INDXOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ usValue = (USHORT) (ulIndex +
+ (((ULONG)(*pusCmdStream++)) << 8));
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff));
+ /* END M002 */
+
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8));
+ /* END M002 */
+
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // Masked out (read, AND, XOR, write)
+ //
+
+ case MASKOUT:
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+ jValue &= *pusCmdStream++;
+ jValue ^= *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulBase + ulPort,
+ jValue);
+ /* END M002 */
+
+ break;
+
+ //
+ // Attribute Controller out
+ //
+
+ case ATCOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ // Write Attribute Controller index
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ (UCHAR)ulIndex);
+ /* END M002 */
+
+
+ // Write Attribute Controller data
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort, jValue);
+ /* END M002 */
+
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // None of the above; error
+ //
+ default:
+
+ return FALSE;
+
+ }
+
+
+ break;
+
+ //
+ // NOP
+ //
+
+ case NCMD:
+
+ break;
+
+ //
+ // Unknown command; error
+ //
+
+ default:
+
+ return FALSE;
+
+ }
+
+ }
+
+ return TRUE;
+
+} // end HalpCirrusInterpretCmdStream()
+/* END M001 */
+
+/* START S005 */
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Tga(DEC21030) Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PUCHAR PLLbits;
+ ULONG i, j;
+ ULONG PLLdata;
+ ULONG ColorData;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ // Start S006
+ // ULONG NowDisplayControlBase;
+ // PENTRYLO PageFrame;
+ // ENTRYLO Pte;
+ // End S006
+
+ // S00b vvv
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 }; // S00c
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+ // S00b ^^^
+
+ const UCHAR Vga_Ini_ColorTable[48] =
+ { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // S006, S007
+ VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B, // S006
+ VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G,
+ VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B,
+ VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B, // S006
+ VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B,
+ VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B,
+ VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B, // S006
+ VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // S006, S007
+ VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B, // S006
+ VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B,
+ VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B,
+ VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B, // S006
+ VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B,
+ VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B,
+ VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B // S006
+ };
+
+ // Start S006
+ ////
+ //// Check Phisical Address and reinitialize PTE
+ ////
+ //
+ //if (READ_REGISTER_ULONG(R98_PCI1_ID) == 0x10110004) {
+ // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI1_MEM_BASE) & 0xfffffff0)
+ // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET;
+ //} else if (READ_REGISTER_ULONG(R98_PCI2_ID) == 0x10110004) {
+ // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI2_MEM_BASE) & 0xfffffff0)
+ // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET;
+ //} else if (READ_REGISTER_ULONG(R98_PCI3_ID) == 0x10110004) {
+ // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI3_MEM_BASE) & 0xfffffff0)
+ // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET;
+ //}
+ //
+ //if (HalpDisplayControlBase != NowDisplayControlBase){
+ // // Called by OS, so reinitialize PTE
+ // HalpDisplayControlBase = NowDisplayControlBase;
+ //
+ // Pte.G = 0;
+ // Pte.V = 1;
+ // Pte.D = 1;
+ //
+ //#if defined(R3000)
+ // Pte.N = 1;
+ //#endif
+ //#if defined(R4000)
+ // Pte.C = UNCACHED_POLICY;
+ //#endif
+ // PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+ // Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT;
+ //
+ // for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ // *PageFrame++ = Pte;
+ // Pte.PFN += 1;
+ // }
+ //
+ // Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ // *PageFrame = Pte;
+ //}
+ // End S006
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ //
+ // Write the PLL
+ //
+
+ // Select PLL Data
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits640x480_72; // S00b
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S00b
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits800x600_72; // S00b
+ } else {
+ PLLbits = (PVOID)PLLbits800x600_60; // S00b
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ PLLbits = (PVOID)PLLbits1024x768_60; // S00b
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S00b
+ }
+
+ // Set PLL Data
+ for( i = 0; i <= 6; i++ ){
+ for( j = 0; j <= 7; j++ ){
+ PLLdata = (PLLbits[i] >> (7-j)) & 1;
+ if( i == 6 && j == 7 )
+ PLLdata |= 2; // Set ~HOLD bit on last write
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata);
+ }
+ }
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ // S006
+ }
+
+ // Set to Deep Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 );
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ // S006
+ }
+
+ // Start S006
+ // Set to Video Base Address Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 );
+ // End S006
+
+ // Set to Plane Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff );
+
+ // Set to Pixel Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff );
+
+ // Set to Raster Operation
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d );
+
+ // Set to Block Color Register 0
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 );
+
+ // Set to Block Color Register 1
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 );
+
+ //
+ // Init. video timing registers for each resolution
+ //
+
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x3c294a0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x1a7a4c8 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x2681cc8 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ //60Hz Only
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x4889300 ); // // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+
+ // Set to Raster Operation Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 );
+
+ KeStallExecutionProcessor(10000L); // S00b
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 );
+
+ //
+ // set pass thru on off & on again to verify operation
+ //
+
+ // EEPROM Write Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 );
+
+ //
+ // Fill palette
+ //
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 );
+
+ for( i = 0; i < 48; i++ ){
+ ColorData = Vga_Ini_ColorTable[i];
+ ColorData |= 0x200;
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData );
+ }
+
+ for( i = 48; i < 768; i++ ){ // S006
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 );
+ }
+
+ // Set to Video Valid Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 );
+
+ //
+ // Set Video Memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Buffer++ = 0x01010101;
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+}
+
+/* END S005 */
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ ENTRYLO SavedPte;
+ // Start S006
+ ULONG NowDisplayControlBase;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ LONG Index;
+ // End S006
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("HalDisplayString\n");
+#endif
+ /* END M002 */
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_DUO_)
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ // Start S006
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ if (PciReadConfigUlong(R98_PCI1_ID) == 0x00041011) {
+ NowDisplayControlBase = (PciReadConfigUlong(R98_PCI1_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE
+ + TGA_REG_SPC_OFFSET;
+ } else if (PciReadConfigUlong(R98_PCI2_ID) == 0x00041011) {
+ NowDisplayControlBase = (PciReadConfigUlong(R98_PCI2_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE
+ + TGA_REG_SPC_OFFSET;
+ } else if (PciReadConfigUlong(R98_PCI3_ID) == 0x00041011) {
+ NowDisplayControlBase = (PciReadConfigUlong(R98_PCI3_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE
+ + TGA_REG_SPC_OFFSET;
+ }
+
+ if (HalpDisplayControlBase != NowDisplayControlBase){
+ HalpDisplayControlBase = NowDisplayControlBase;
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+ Pte.N = 1;
+#endif
+#if defined(R4000)
+ Pte.C = UNCACHED_POLICY;
+#endif
+ PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+ Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+ }
+ // End S006
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ HalpInitDisplayStringIntoNvram(); // S009
+ HalpResetX86DisplayAdapter(); //K000
+ }
+
+// HalpStringIntoNvram(HalpColumn, HalpRow, String); // S009, S00a
+ HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ HalpStringBufferCopyToNvram(); // S00a
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+#if defined(_DUO_)
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ /* START M002 */
+ HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE,
+ (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+ /* END M002 */
+
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ HalpStringBufferCopyToNvram(); // S00a
+ HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ HalpStringBufferCopyToNvram(); // S00a
+ HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a
+
+ } else {
+ HalStringIntoBuffer( Character ); // S00a
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination++ = (UCHAR)((FontValue >> 31) ^ 1); // S002
+ FontValue <<= 1;
+ }
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ Destination +=
+ (1024 - HalpCharacterWidth);
+ }else{
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+ }
+ HalpColumn += 1;
+ return;
+}
+
+/* START M002 */
+VOID
+Write_Dbg_Uchar(
+ PUCHAR Ioadress,
+UCHAR Moji
+)
+
+{
+#if defined (R96DBG)
+ DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji);
+#endif
+ WRITE_PORT_UCHAR(Ioadress,Moji);
+}
+/* END M002 */
+
+/* START M003 */
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+ )
+
+/*++
+ Routine Description:
+
+ This function moves blocks of memory.
+
+ Arguments:
+
+ Destination - Supplies a pointer to the destination address of
+ the move operation.
+
+ Source - Supplies a pointer to the source address of the move
+ operation.
+
+ Length - Supplies the length, in bytes, of the memory to be moved.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Remainder;
+ PUCHAR Dstend; /* M004 */
+ PUCHAR Srcend; /* M004 */
+
+ if ( (Source == Destination) || (Length == 0) ) { /* M004 */
+ return;
+ }
+
+ if ((Source < Destination)&((Source + Length) > Destination)) { /* M004 vvv */
+ if((Destination - Source) > 4){
+ Remainder = (UCHAR)(Length &0x03); // S002
+ Length = Length / 4;
+ Dstend = Destination + Length - 4 ;
+ Srcend = Source + Length -4;
+
+ for (; Length > 0; Length--) {
+ *(PULONG)(Dstend) = *(PULONG)(Srcend);
+ Dstend -= 4;
+ Srcend -= 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+ for (; Length > 0; Length--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+
+ else {
+ if( (Source - Destination) > 4 ){
+ Remainder = (UCHAR)(Length &0x03); // S002
+ Length = Length / 4;
+ for (; Length > 0; Length--) {
+ *(PULONG)(Destination) = *(PULONG)(Source);
+ Destination += 4;
+ Source += 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ return;
+ }
+
+ for (; Length > 0; Length--) {
+ *Destination = *Source;
+ Destination++;
+ Source++; /* M004 ^^^*/
+ }
+ }
+}
+
+/* END M003 */
diff --git a/private/ntos/nthals/halr98mp/mips/jxebsup.c b/private/ntos/nthals/halr98mp/mips/jxebsup.c
new file mode 100644
index 000000000..464a35673
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxebsup.c
@@ -0,0 +1,1275 @@
+#ident "@(#) NEC jxebsup.c 1.13 95/06/19 11:10:34"
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/25 T.Samezima
+ *
+ * HalpCreateEisaStructure
+ *
+ * Del #ifdef of Duo
+ * Disable NMI Interrupt
+ *
+ * Change Parameter of initialize interrupt
+ * Irql Level
+ *
+ ***********************************************************************
+ *
+ * S002 94.04/19 T.Samezima
+ *
+ * HalpEisaDispatch
+ *
+ * Del #ifdef of Duo
+ * K001 94/5/31 (Tue) N.Kugimoto
+ * Add SpinLock HalpEisaMapTransfer()
+ *
+ ***********************************************************************
+ *
+ * S003 94.06/01 T.Samezima
+ *
+ * HalHandleNMI
+ *
+ * Del display interrupt information
+ *
+ ***********************************************************************
+ *
+ * S004 94.6/13 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S005 94.7/5 T.Samezima
+ *
+ * Chg base i/o address to kseg1_base
+ *
+ *
+ ***********************************************************************
+ *
+ * S006 94.8/22 T.Samezima on SNES
+ *
+ * Add Move EISA NMI enable logic from HalpInitializeInterrupts()
+ *
+ ***********************************************************************
+ *
+ * S007 94.8/23 T.Samezima
+ *
+ * Chg Register read size from long to short
+ *
+ *
+ * K001 94/9/13 N.Kugimoto
+ * Add For a spurious interrupt PIC IR7
+ * K002 94/9/13 N.Kugimoto
+ * Chg Interrupt Ack reg non USHORT.must UCHAR!!.
+ *
+ * S008 94.10/13 T.Samezima
+ * Fix Version Up at build807
+ * S009 94.11/21 T.Samezima
+ * Chg Disable EISA NMI
+ * Disable ASSERT(). because. senseless ASSERT on r98
+ *
+ * K003 95/04/24 N.Kugimoto
+ * Add DUMMDMA
+ * LR4360 workaround. can't TLB flush while dma.
+ * So ESC DMAC channel2 use.
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - resolve compile wornings.
+ */
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+// Start S008
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+// End S008
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+// Start S008
+// Define EISA bus interrupt affinity.
+//
+
+KAFFINITY HalpEisaBusAffinity;
+// End S008
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR)channelNumber; // S004
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber; // S004
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+ UCHAR charBuffer; // S006
+
+ /* Start S001, S008 */
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_VECTOR] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch; // A002
+ /* End S001, S008 */
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ /* Start S001 */
+ KeRaiseIrql(INT1_LEVEL, &oldIrql);
+ /* End S001 */
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL); // S004
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ // Start S008
+ // Set EISA bus interrupt affinity.
+ //
+
+ HalpEisaBusAffinity = PCR->SetMember;
+ // End S008
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ /* Start S001, S008 */
+ //
+ // Enable eisa interrupt on LR4360
+ //
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ HalpBuiltinInterruptEnable |= iREN_ENABLE_EISA_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ /* End S008 */
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+ /* End S001 */
+
+ // Start S006
+ charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus );
+// charBuffer = (charBuffer & 0x03); // S009
+ charBuffer = ((charBuffer & 0x03) | 0X0C); // S009
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus,
+ charBuffer
+ );
+ /* Start S001 in xxinitnt.c */
+ charBuffer = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl
+ );
+ /* End S001 in xxinitnt.c */
+// charBuffer = ( (charBuffer & 0x01) | 0x0e ); // S009
+ charBuffer = (charBuffer & 0x01); // S009
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ charBuffer ); // S007
+ // End S006
+
+ return(TRUE);
+}
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+//
+//
+//extern KSPIN_LOCK HalpIoMapSpinLock;
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ KIRQL Irql; // K001
+
+ BytePtr = (PUCHAR) &Offset;
+
+// ASSERT(Offset >= 0x100000); // S009
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ // K001
+ // grab the spinlock for the system DMA controller
+ //
+#if !defined(DUMMYDMA)
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+#endif
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+ }
+#if !defined(DUMMYDMA)
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+#endif
+}
+
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+}
+
+// Start S008
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = (UCHAR)READ_REGISTER_UCHAR( (PVOID)(LR_PHYSICAL_PCI_INT_ACK_BASE | KSEG1_BASE));
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+// if (interruptVector != 0x8000) {
+ //K001 Start
+ if(interruptVector == 7|| interruptVector==15 ){
+
+ PVOID IsrPortAddr;
+ UCHAR IsrValue;
+
+#define OCW3_READ_ISR 0x0B
+#define OCW3_READ_IRR 0x0A
+
+ //
+ // Master or Slave ?
+ //
+ IsrPortAddr = (interruptVector == 7) ?
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0:
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0;
+
+ // SetUp to ISR Regsiter
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_ISR );
+ // Read ISR Register
+ IsrValue=READ_REGISTER_UCHAR( IsrPortAddr );
+ // Resume to IRR Register
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_IRR);
+
+ if(!IsrValue){
+ // This is a spurious interrupt!!. No Call Driver.
+ goto NocallDriver;
+ }
+ }
+ // K001 End
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+NocallDriver:
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+// } else {
+// returnValue = HalHandleNMI(NULL, NULL);
+// }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+// End S008
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxenvirv.c b/private/ntos/nthals/halr98mp/mips/jxenvirv.c
new file mode 100644
index 000000000..5e9446d73
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxenvirv.c
@@ -0,0 +1,818 @@
+#pragma comment(exestr, "@(#) jxenvirv.c 1.8 94/12/06 15:07:37 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 94.5/31 (Tue) N.Kugimoto
+ * Del No Map TLB. & nvram base define -->def.h
+ * Add Nvram write enable
+ * K002 94/6/10 (Fri) N.Kugimoto
+ * Chg Compile err del.
+ * K003 94/8/29 (Mon) N.Kugimoto
+ * -1 BUG HalpUnmapNvram() stsr register write value bug.
+ * -2 Chg HalpMapNvram() stsr register write value is absolute.
+ * K004 94/10/11 N.Kugimoto
+ * H/W Work Around. NVRAM can't write protect!!.
+ * K005 94/12/06 N.Kugimoto
+ * Add ESM Interface
+ * -2 Miss ;; -->,
+ */
+
+#include "halp.h"
+#include "arccodes.h"
+#include "jazznvr.h"
+#include "string.h"
+
+//
+// Define base address at which to map NVRAM.
+//
+#if !defined(_R98_) // K001
+#define NVRAM_MEMORY_BASE PTE_BASE
+#endif
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which receives the old NVRAM
+ PTE values.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+#if defined(_R98_) // K001
+ //
+ // Nvram Write enable
+ // K002
+ WRITE_REGISTER_ULONG(
+ &( PMC_CONTROL1 )->STSR.Long,
+ STSR_NVWINH_ENABLE //K003-2
+ );
+
+#else // K001
+ ENTRYLO NvramPte;
+ PENTRYLO PtePointer;
+
+ //
+ // Construct a PTE to map NVRAM into the address space of the current
+ // process.
+ //
+
+ NvramPte.X1 = 0;
+ NvramPte.PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
+ NvramPte.G = 0;
+ NvramPte.V = 1;
+ NvramPte.D = 1;
+
+#if defined(R3000)
+
+ NvramPte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ NvramPte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Raise IRQL to the highest level, flush the TB, map the NVRAM into
+ // the address space of the current process, and return the previous
+ // IRQL.
+ //
+
+ PtePointer = (PENTRYLO)PDE_BASE;
+#endif // _R98_
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+#if !defined(_R98_)
+ SavedPte[0] = PtePointer[0];
+ SavedPte[1] = PtePointer[1];
+ KeFlushCurrentTb();
+ PtePointer[0] = NvramPte;
+ NvramPte.PFN += 1;
+ PtePointer[1] = NvramPte;
+#endif //_R98_
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which contains the old NVRAM
+ PTE values.
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(_R98_) // K001
+#if 0 //K004 vvvvv
+ //
+ // Nvram write disable
+ // K002
+ WRITE_REGISTER_ULONG(
+ &( PMC_CONTROL1 )->STSR.Long,
+ STSR_NVWINH_DISABLE //K003-1
+ );
+
+#endif //K004 ^^^^^
+#else
+ PENTRYLO PtePointer;
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+
+ PtePointer = (PENTRYLO)PDE_BASE;
+ KeFlushCurrentTb();
+ PtePointer[0] = SavedPte[0];
+ PtePointer[1] = SavedPte[1];
+#endif //_R98_
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return Status;
+}
+
+
+
+#if defined(_R98_) //K005 Start VVVVV
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Write Byte Count
+ PVOID Buffer // Pointer Of Buffer Write to NVRAM
+){
+ // Write into NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,1);
+}
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Read Byte Count
+ PVOID Buffer // Pointer Of Buffer Read From NVRAM
+){
+ // Read From NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,0);
+}
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset, // Read/Write offset of ESM NVRAM
+ ULONG Count, // Read/Write Byte Count
+ PVOID Buffer, // read/Write Pointer
+ ULONG Write // Operation
+){
+
+ ENTRYLO SavedPte[2];
+ KIRQL OldIrql;
+ ULONG i;
+ //
+ // Check is addr . So decrement 1
+ //
+ if(
+ Offset >=0 &&
+ Count >=0 &&
+ NVRAM_ESM_BASE+Offset <=NVRAM_ESM_END &&
+ NVRAM_ESM_BASE+Offset+Count-1 <=NVRAM_ESM_END
+
+ ){
+
+ if(Write){
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ for(i=0;i<Count;i++){
+ WRITE_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i),((PUCHAR)Buffer)[i]);
+ }
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ }else{
+ for(i=0;i<Count;i++){
+ ((PUCHAR)Buffer)[i] =READ_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i));
+
+ }
+ }
+
+ return TRUE;
+
+ }else{
+
+ //
+ // It is no ESM NVRAM Erea.
+ return FALSE;
+ }
+
+}
+
+//K005 End ^^^^^
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/jxhalp.h b/private/ntos/nthals/halr98mp/mips/jxhalp.h
new file mode 100644
index 000000000..ed8f602ec
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxhalp.h
@@ -0,0 +1,99 @@
+#ident "@(#) NEC jxhalp.h 1.2 94/10/17 11:28:33"
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halr98mp/mips/jxmapio.c b/private/ntos/nthals/halr98mp/mips/jxmapio.c
new file mode 100644
index 000000000..6304228b1
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxmapio.c
@@ -0,0 +1,153 @@
+#ident "@(#) NEC jxmapio.c 1.6 94/10/17 11:37:41"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.06/02 T.Samezima
+ *
+ * Del I/O space mapping
+ *
+ * Add set kseg1 base I/O address
+ *
+ ***********************************************************************
+ *
+ * S002 94.6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S003 94.7/5 T.Samezima
+ *
+ * Del Error check
+ *
+ * K000 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ */
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase; //K000
+PVOID HalpRealTimeClockBase;
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ /* Start M001 */
+#if !defined(_R98_)
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.LowPart = RTCLOCK_PHYSICAL_BASE;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+#else // #if !defined(_R98_)
+
+ //
+ // set EISA control space.
+ //
+
+ HalpEisaControlBase = (PVOID)(KSEG1_BASE + EISA_CONTROL_PHYSICAL_BASE); // S002
+
+ //
+ // set realtime clock registers.
+ //
+
+ HalpRealTimeClockBase = (PVOID)(KSEG1_BASE + RTCLOCK_PHYSICAL_BASE); // S002
+
+#endif // #if !defined(_R98_)
+ /* End M001 */
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ /* Start S003 */
+// if ((HalpEisaControlBase == NULL) ||
+// (HalpRealTimeClockBase == NULL)) {
+// return FALSE;
+// } else {
+// return TRUE;
+// }
+ return TRUE;
+ /* End S003 */
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxmaptb.c b/private/ntos/nthals/halr98mp/mips/jxmaptb.c
new file mode 100644
index 000000000..cb338fb94
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxmaptb.c
@@ -0,0 +1,84 @@
+#ident "@(#) NEC jxmaptb.c 1.2 94/10/17 11:39:05"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxmaptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for a MIPS R3000
+ or R4000 Jazz system. It also sets the instruction and data cache line
+ sizes for a MIPS R3000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * L001 94.03/16 T.Samezima
+ *
+ * Change return only of HalpMapFixedTbEntries
+ *
+ *
+ */
+
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapFixedTbEntries)
+
+#endif
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is return only.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98mp/mips/jxport.c b/private/ntos/nthals/halr98mp/mips/jxport.c
new file mode 100644
index 000000000..a6a57ad48
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxport.c
@@ -0,0 +1,897 @@
+#pragma comment(exestr, "@(#) jxport.c 1.4 94/10/17 11:46:16 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 94/5/31 (Tue) N.Kugimoto
+ * Del TLB mapping del. see KSEG1_BASE.
+ * K002 94/6/10 (Fri) N.Kugimoto
+ * Chg Compile err del.
+ */
+
+
+#include "halp.h"
+#include "jazzserp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+#if defined(_R98_) // K001 K002
+#define SP_READ ((PSP_READ_REGISTERS)(SERIAL0_PHYSICAL_BASE|KSEG1_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SERIAL0_PHYSICAL_BASE|KSEG1_BASE))
+#else
+#define SP_READ ((PSP_READ_REGISTERS)(SP_VIRTUAL_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SP_VIRTUAL_BASE))
+#endif // _R98_
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 0;
+
+#if !defined(_R98_) // K001
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+#endif
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+#if !defined(_R98_)
+ ULONG KdPortEntry;
+#endif //!defined(_R98_) K002
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+#if !defined(_R98_) // K001
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = SP_PHYSICAL_BASE >> PAGE_SHIFT;
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry and set the noncached bit in the PTE that will
+ // map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+ HalpPte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+#endif
+#endif // _R98_
+
+ KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+
+#if !defined(_R98_) // K001
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+#endif // _R98_
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+#if !defined(_R98_) // K002
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+#endif
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+#if !defined(_R98_) // K001
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+#endif // _R98_
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#if !defined(_R98_) // K001
+ ULONG KdPortEntry;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+
+#endif
+
+ //
+ // Map the serial controller through a allocated TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+#endif // _R98_
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxreturn.c b/private/ntos/nthals/halr98mp/mips/jxreturn.c
new file mode 100644
index 000000000..0afe8eed8
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxreturn.c
@@ -0,0 +1,189 @@
+#pragma comment(exestr, "@(#) jxreturn.c 1.5 94/10/17 11:47:45 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 95/5/31 (Tue) N.Kugimoto
+ * Del TLB mapping del.
+ *
+ * S002 94/6/13 (Mon) T.Samezima
+ * Chg Compile err del
+ *
+ * K002 94/10/11 (Tue) N.Kugimoto
+ * Fix 807 Base
+ */
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+#if defined(_R98_) // K001
+ // S001
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)(KEYBOARD_PHYSICAL_BASE|KSEG1_BASE);
+#else
+ ENTRYLO Pte[2];
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE;
+
+#endif // _R98_
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ // K002
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ HalpResetX86DisplayAdapter();
+
+#if !defined(_R98_) // K001
+ //
+ // Map the keyboard controller
+ //
+
+ Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map keyboard controller using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+#endif // K001
+
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreData(0);
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxsysint.c b/private/ntos/nthals/halr98mp/mips/jxsysint.c
new file mode 100644
index 000000000..5b3f855c3
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxsysint.c
@@ -0,0 +1,454 @@
+#ident "@(#) NEC jxsysint.c 1.13 94/11/08 16:20:09"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for R98
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * M001 94.03/25-5/31 T.Samezima
+ *
+ * Change Interrupt control
+ * Irql level
+ *
+ * Add Correspond to PCIBus
+ * Exchange mask data
+ * define table of ipi interrupt request
+ *
+ * Del #ifdef DUO
+ *
+ ***********************************************************************
+ *
+ * S002 94.06/02 T.Samezima
+ *
+ * Add HalGetInterruptVector
+ *
+ ***********************************************************************
+ *
+ * S003 94,6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S004 94,7/5 T.Samezima
+ *
+ * Chg Mask value
+ * Maximun EISA vecter
+ *
+ ***********************************************************************
+ *
+ * S005 94,7/8 T.Samezima
+ *
+ * Chg Maximun EISA vecter
+ *
+ ***********************************************************************
+ *
+ * S006 94,7/21 T.Samezima
+ *
+ * Chg Fixd to PCI
+ *
+ *
+ ***********************************************************************
+ *
+ * S007 94,8/22 T.Samezima on SNES
+ *
+ * Chg Designate member
+ *
+ ***********************************************************************
+ *
+ * K001 94/09/26 N.Kugimoto
+ * Mov Move Source code to r98busdat.c
+ ***********************************************************************
+ *
+ * S008 94/09/30 T.Samezima
+ *
+ * Bug Miss define of PCI Interrupt vector.
+ *
+ * S009 94/11/08 T.Samezima
+ * Bug Miss define of IpiRequestMask.
+ *
+ *
+ */
+
+#include "halp.h"
+
+/* Start M001 */
+//
+// Define Ipi Interrupt Reqest value table.
+//
+/* Start S003 */
+ULONG HalpIpiIntRequestMask[] = {
+ IntIR_REQUEST_IPI | (0x00 << IntIR_CPU3_BIT) , // 0000 -> 0000
+ IntIR_REQUEST_IPI | (0x08 << IntIR_CPU3_BIT) , // 0001 -> 1000
+ IntIR_REQUEST_IPI | (0x04 << IntIR_CPU3_BIT) , // 0010 -> 0100
+ IntIR_REQUEST_IPI | (0x0c << IntIR_CPU3_BIT) , // 0011 -> 1100
+ IntIR_REQUEST_IPI | (0x02 << IntIR_CPU3_BIT) , // 0100 -> 0010
+ IntIR_REQUEST_IPI | (0x0a << IntIR_CPU3_BIT) , // 0101 -> 1010
+ IntIR_REQUEST_IPI | (0x06 << IntIR_CPU3_BIT) , // 0110 -> 0110
+ IntIR_REQUEST_IPI | (0x0e << IntIR_CPU3_BIT) , // 0111 -> 1110
+ IntIR_REQUEST_IPI | (0x01 << IntIR_CPU3_BIT) , // 1000 -> 0001
+ IntIR_REQUEST_IPI | (0x09 << IntIR_CPU3_BIT) , // 1001 -> 1001
+ IntIR_REQUEST_IPI | (0x05 << IntIR_CPU3_BIT) , // 1010 -> 0101
+ IntIR_REQUEST_IPI | (0x0d << IntIR_CPU3_BIT) , // 1011 -> 1101
+ IntIR_REQUEST_IPI | (0x03 << IntIR_CPU3_BIT) , // 1100 -> 0011 // S009
+ IntIR_REQUEST_IPI | (0x0b << IntIR_CPU3_BIT) , // 1101 -> 1011
+ IntIR_REQUEST_IPI | (0x07 << IntIR_CPU3_BIT) , // 1110 -> 0111
+ IntIR_REQUEST_IPI | (0x0f << IntIR_CPU3_BIT) // 1111 -> 1111
+ };
+/* End S003 */
+/* End M001 */
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));
+ /* Start M001 */
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ /* End M001 */
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ /* Start M001 */
+ /* Start S003 */
+ if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTORS && // S004
+ Irql == INT1_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+ /* End S003 */
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ /* Start S006 */
+ if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+ /* End S006 */
+ /* End M001 */
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of builtin devices, then
+ // enable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
+ /* Start M001 */
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ /* End M001 */
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ /* Start M001 */
+ /* Start S003 */
+ if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTORS && // S005
+ Irql == INT1_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+ /* End S003 */
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ /* Start S006 */
+ if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) {
+ HalpEnablePciInterrupt(Vector);
+ }
+ /* End S006 */
+ /* End M001 */
+
+ //
+ // Release the device enable spin loc and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ /* Start M001 */
+ ULONG buffer;
+ /* End M001 */
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ /* Start M001 */
+ buffer = HalpIpiIntRequestMask[(Mask & 0xf)] | // S004
+ ( (((PCR->Prcb)->Number) & 0x3) << IntIR_CODE_BIT );
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->IntIR.Long, buffer); // S007
+ /* End M001 */
+
+ return;
+}
+
+#if 0 //K001
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector.
+ The system interrupt vector and IRQL are suitable for use in a
+ subsequent call to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // N.B. On Jazz systems which are single processor systems, all interrupts
+ // go to processor 0. On Duo systems both processors could handle
+ // interrupts, but the hardware does not arbitrate and distribute
+ // interrupts, and therefore, both processors would get all interrupts.
+ //
+
+ *Affinity = 1;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ *Irql = (KIRQL)BusInterruptLevel;
+ /* Start S002 */
+ return(BusInterruptVector + DEVICE_VECTORS);
+ /* End S002 */
+ }
+
+ /* Start S002 */
+ //
+ // If this is for the pci bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == PCIBus) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ *Irql = INT1_LEVEL;
+ return(PCI_DEVICE_VECTOR); // S008
+ }
+ /* End S002 */
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+
+ }
+
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ /* Start S001 */
+ *Irql = INT1_LEVEL;
+ /* End S001 */
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/jxtime.c b/private/ntos/nthals/halr98mp/mips/jxtime.c
new file mode 100644
index 000000000..b9d543f1b
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxtime.c
@@ -0,0 +1,313 @@
+#ident "@(#) NEC jxtime.c 1.4 94/11/22 20:09:27"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/23 T.Samezima
+ *
+ * Change Irql Level
+ *
+ ***********************************************************************
+ *
+ * S002 94.07/5 T.Samezima
+ *
+ * Change Register access mask
+ *
+ *
+ */
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ /* Start S001 */
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ /* End S001 */
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ /* Start S001 */
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ /* End S001 */
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+ /* Start S002 */
+ Register |= 0x80;
+ /* End S002 */
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ /* Start S002 */
+ Register |= 0x80;
+ /* End S002 */
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxusage.c b/private/ntos/nthals/halr98mp/mips/jxusage.c
new file mode 100644
index 000000000..dd480366e
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxusage.c
@@ -0,0 +1,497 @@
+#ident "@(#) NEC jxusage.c 1.3 94/10/19 22:05:01"
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:26:38 JST 1994
+ - Change PRIMARY_VECTOR_BASE to DEVICE_VECTOTRS
+ CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:53:42 JST 1994
+ - delete HalpEnableInterruptHandler, HalpRegisterVector
+ - change IDT vector LOOP, R98 report up to DEVICE_VECTORS
+ - change MAXIMUM_IDTVECTOR to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:53:32 JST 1994
+ - resolve compile error
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+#if !defined(_R98_) // CMP001
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif // _R98
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+#if !defined (_R98_) // CHG001
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+#endif // _R98_
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+#if defined(_R98_) // CHG001
+ for(i=0; i < DEVICE_VECTORS; i++) { // ADD001
+ HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+#else
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+#endif
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_VECTOR) { // CHG001
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halr98mp/mips/mipsdat.c b/private/ntos/nthals/halr98mp/mips/mipsdat.c
new file mode 100644
index 000000000..23a92be23
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/mipsdat.c
@@ -0,0 +1,144 @@
+#ident "@(#) NEC mipsdat.c 1.2 95/06/19 11:11:45"
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*++
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:53:16 JST 1994
+ - add HalpMapRegisterMemorySpace
+ BUG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:49:18 JST 1994
+ - change HalpMapRegisterMemorySpace Size
+ CNG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:58:30 JST 1994
+ - change HalpIDTUsage size to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:34:47 JST 1994
+ - resolve compile error
+ A002 ataka@oa2.kb.nec.co.jp 1995/6/17
+ - marge 1050
+--*/
+
+
+
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC
+ EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC
+
+ EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe
+
+ EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B)
+ EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A
+
+ EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable
+ EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI
+ EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted
+
+ EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers
+
+ EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+#define R98_MAPREGISTER_BASE 100 // CMP001
+
+// BUG001
+ADDRESS_USAGE HalpMapRegisterMemorySpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ R98_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001
+ 0, 0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+// CNG001
+#if defined(MIPS)
+IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[]
+#else // CMP001
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif
+
diff --git a/private/ntos/nthals/halr98mp/mips/mode542x.h b/private/ntos/nthals/halr98mp/mips/mode542x.h
new file mode 100644
index 000000000..00445a6d9
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/mode542x.h
@@ -0,0 +1,1302 @@
+#ident "@(#) NEC mode542x.h 1.3 95/07/05 13:10:57"
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Mode542x.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-542x driver.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// The next set of tables are for the CL542x
+// Note: all resolutions supported
+//
+
+//
+// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode
+
+ EOD
+};
+
+//
+// 800x600 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_800x600[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode
+
+ EOD
+};
+
+//
+// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_1024x768[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ EOD
+};
+
+//-----------------------------
+// standard VGA text modes here
+// 80x25 at 640x350
+//
+//-----------------------------
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (720x400 pixel resolution; 9x16 character cell.)
+//
+
+USHORT CL542x_80x25Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (640x350 pixel resolution; 8x14 character cell.)
+//
+
+USHORT CL542x_80x25_14_Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x.
+//
+
+USHORT CL542x_1280x1024[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_64k[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 4,
+ 0x0506, // Some BIOS's set Chain Odd maps bit
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#ifdef _X86_
+
+//
+// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x.
+//
+
+USHORT CL542x_800x600_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#else
+
+//
+// NOTE(DBCS) : Update 94/09/12 - NEC Corporation
+//
+// - Add mode set command string for NEC MIPS machine.
+//
+// - 640x480 256 color 72Hz
+// - 800x600 256 color 56 / 60Hz
+// - 1024x768 256 color 70 / 45Hz
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+//
+// For MIPS NEC machine only
+//
+
+//
+// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xE3,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F,
+ 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x420E,
+ 0x2B1B,0x2F1C,0x301D,0x1F1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h)
+//
+// - Set Mode Type is VESA compatible. (Old Miss match)
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99,
+ 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+
+// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match
+// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode.
+// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B,
+// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+// 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_56[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12,
+ 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x510E,
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B,
+ 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B,0x5B0C,0x450D,0x650E,
+
+#else
+
+ 0x4A0B,0x5B0C,0x450D,0x640E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x760E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x341E,
+
+#else
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x3B0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x1A1E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_70[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x6E0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x2A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for
+// CL 542x. (Interlaced)
+//
+
+USHORT CL542x_1024x768_256_87[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x550E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x361E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99,
+ 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83,
+ 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x84,
+ 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/modeset.h b/private/ntos/nthals/halr98mp/mips/modeset.h
new file mode 100644
index 000000000..b699eacc7
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/modeset.h
@@ -0,0 +1,86 @@
+#ident "@(#) NEC modeset.h 1.1 94/07/05 14:06:24"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) modeset.h 1.3 93/10/29 12:25:59" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Modeset.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-6410 and CL-6420 driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Mode structure.
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ *
+ */
+
+#include "cmdcnst.h"
+
+//---------------------------------------------------------------------------
+//
+// The actual register values for the supported modes are in chipset-specific
+// include files:
+//
+// mode64xx.h has values for CL6410 and CL6420
+// mode542x.h has values for CL5422, CL5424, and CL5426
+//
+
+
+USHORT HalpCirrus_MODESET_1K_WIDE[] = {
+ OW, // stretch scans to 1k
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x8013,
+
+ EOD
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98mp/mips/pcibrd.c b/private/ntos/nthals/halr98mp/mips/pcibrd.c
new file mode 100644
index 000000000..c4ea03464
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/pcibrd.c
@@ -0,0 +1,1020 @@
+#ident "@(#) NEC pcibrd.c 1.2 95/06/19 11:12:35"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+// #define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/pcip.h b/private/ntos/nthals/halr98mp/mips/pcip.h
new file mode 100644
index 000000000..b757a07a7
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/pcip.h
@@ -0,0 +1,214 @@
+#ident "@(#) NEC pcip.h 1.4 95/06/19 11:13:40"
+/*
+
+ Revision History
+
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-pcip.h to 1050-halx86-pcip.h
+*/
+
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+#if defined(_R98_) // A002
+
+typedef struct _PCI_TYPER98_CFG_BITS {
+ union {
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG SlotNumber:2;
+ ULONG BaseAddress:19;
+ } bits;
+
+ ULONG AsULONG;
+ } u;
+} PCI_TYPER98_CFG_BITS, *PPCI_TYPER98_CFG_BITS;
+
+#define PCI_CONFIG_BASE_ADDRESS 0xb8ca8000 /* N001 */
+
+#endif
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/r98busdt.c b/private/ntos/nthals/halr98mp/mips/r98busdt.c
new file mode 100644
index 000000000..a14d3cf4c
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98busdt.c
@@ -0,0 +1,1181 @@
+#ident "@(#) NEC r98busdt.c 1.16 95/06/19 11:30:31"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+/*++
+
+ Modification History
+
+ N- NEW
+ D- Only For Debug
+ B- Bug Fix
+
+B001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:40:10 JST 1994
+ - add DbgPrints
+
+B002 samezima@oa2.kb.nec.co.jp MON Nov 21
+ - chg Mask translate address
+
+N005 samezima@oa2.kb.nec.co.jp MON Mar 13
+ - change PIO interrupt vector from internal to eisa.
+A002 ataka@oa2.kb.nec.co.jp 1995/6/17
+ - Marge 1050 halx86 many sources to 807 r98busdat.c
+ and named r98busdt.c
+
+--*/
+
+#include "halp.h"
+#include "string.h" // CMP001
+
+
+UCHAR HalName[] = "NEC MIPS HAL"; // N003
+
+VOID HalpInitializePciBus (VOID); // CMP001
+VOID HalpInitOtherBuses (VOID);
+
+
+//
+// Prototype for system bus handlers
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslatePCIBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+#if DBG // A002
+VOID
+HalpDisplayAllBusRanges (
+ VOID
+ );
+VOID
+HalpDisplayAddressRange (
+ PSUPPORTED_RANGE Address,
+ PUCHAR String
+);
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#pragma alloc_text(PAGE,HalGetInterruptVector)
+/* B001 */
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
+#pragma alloc_text(PAGE,HalpGetEisaData)
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ // B003 kugi Internal Bus was called with bus-no. 2, We have no idea.
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 1, // Internal BusNumber 1
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+#if defined(_R98_) // A001
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+#endif // _R98_
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+
+ HalpInitOtherBuses ();
+#if DBG // A002
+ HalpDisplayAllBusRanges ();
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ // A001
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->IO.Base = 0;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ switch(InterfaceType) {
+ case Internal:
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0xFFFFFFFF;
+ Bus->BusAddresses->Memory.SystemBase
+ = 0x00000000;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
+ = 0xFFFFFFFF;
+ Bus->BusAddresses->IO.SystemBase
+ = 0x00000000;
+ break;
+ case Eisa:
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+// = 0x01000000;
+ Bus->BusAddresses->Memory.Limit
+ = 0x03FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ Bus->BusAddresses->IO.Limit
+ = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+ case Isa:
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+ Bus->BusAddresses->Memory.Limit
+ = 0x00FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ Bus->BusAddresses->IO.Limit
+ = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+ case PCIBus:
+ Bus->BusAddresses->Memory.Base
+ = 0x04000000; // from 64MB
+ Bus->BusAddresses->Memory.Limit
+ = 0x0FFFFFFF; // up to 256MB
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ Bus->BusAddresses->IO.Limit
+ = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = PCI_CONTROL_SLOT1_PHYSICAL_BASE;
+ break;
+ }
+ }
+
+ return Bus;
+}
+
+// N003
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+
+ // N004
+#if 0 // support next version
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+#endif
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Internal // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+
+
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Affinity = HalpEisaBusAffinity; // N003
+
+ *Irql = INT1_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ PAGED_CODE (); // A001
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+
+
+// N001
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ /* N003 vvv */
+ ULONG vector;
+
+ *Irql = (KIRQL)BusInterruptLevel;
+ vector = BusInterruptVector + DEVICE_VECTORS;
+
+ switch(vector) {
+ case SCSI1_VECTOR:
+ case SCSI0_VECTOR:
+ case ETHER_VECTOR:
+ *Affinity = HalpInt1Affinity;
+ break;
+
+ // N005 vvv
+ case PIO_VECTOR:
+ return HalpGetEisaInterruptVector( (PBUS_HANDLER)NULL,
+ (PBUS_HANDLER)NULL,
+ 1,
+ 1,
+ Irql,
+ Affinity
+ );
+ // N005 ^^^
+
+ default:
+ *Affinity = 1;
+ }
+
+ return vector;
+ /* N003 ^^^ */
+}
+
+
+// A001
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+// A001
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+#if DBG
+// DbgPrint("\nHalpTranslateSystemBusAddress-searching(Mem)....");
+#endif
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+#if DBG
+// HalpDisplayAddressRange (pRange, "\n PrefetchMemory:");
+#endif // DBG
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+#if DBG
+// HalpDisplayAddressRange (pRange, "\n Memory:");
+#endif // DBG
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+#if DBG
+// DbgPrint("HalpTranslateSystemBusAddress-searching(Io)....\n");
+#endif
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+#if DBG
+// HalpDisplayAddressRange (pRange, "\n Io:");
+#endif // DBG
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+#if DBG
+// DbgPrint("\n Translated=0x%08x:%08x\nEnd of Translating Success!\n", TranslatedAddress->HighPart,
+// TranslatedAddress->LowPart);
+#endif // DBG
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+#if DBG
+// DbgPrint("\nEnd of Translating. False!\n");
+#endif
+
+ return FALSE;
+}
+
+// A001
+BOOLEAN
+HalpTranslateIsaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's memory space
+ // then we allow the translation as it would occur on it's
+ // corrisponding EISA bus. We're allowing this because
+ // many VLBus drivers are claiming to be ISA devices.
+ // (yes, they should claim to be VLBus devices, but VLBus is
+ // run by video cards and like everything else about video
+ // there's no hope of fixing it. (At least according to
+ // Andre))
+ //
+
+ if (Status == FALSE && *AddressSpace == 0) {
+ Status = HalTranslateBusAddress (
+ Eisa,
+ BusHandler->BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+// A001
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's in the 640k - 1m
+ // range then (for compatibility) try translating it on the
+ // Internal bus for
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 0 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0xA0000 &&
+ BusAddress.LowPart < 0xFFFFF) {
+
+ Status = HalTranslateBusAddress (
+ Internal,
+ 0,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+#if DBG
+VOID
+HalpDisplayAddressRange (
+ PSUPPORTED_RANGE Address,
+ PUCHAR String
+ )
+/*++
+
+Routine Description:
+
+ Debugging code. Used only by HalpDisplayAllBusRanges
+
+--*/
+{
+ ULONG i;
+
+ i = 0;
+ while (Address) {
+ if (i == 0) {
+ DbgPrint (String);
+ i = 3;
+ }
+
+ i -= 1;
+ DbgPrint (" %x:%08x - %x:%08x + %x:%08x",
+ (ULONG) (Address->Base >> 32),
+ (ULONG) (Address->Base),
+ (ULONG) (Address->Limit >> 32),
+ (ULONG) (Address->Limit),
+ (ULONG) (Address->SystemBase >> 32),
+ (ULONG) (Address->SystemBase)
+ );
+
+ Address = Address->Next;
+ }
+}
+#endif // DBG
diff --git a/private/ntos/nthals/halr98mp/mips/r98busdt.h b/private/ntos/nthals/halr98mp/mips/r98busdt.h
new file mode 100644
index 000000000..0517105f5
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98busdt.h
@@ -0,0 +1,142 @@
+#ident "@(#) NEC r98busdat.h 1.2 94/10/19 22:15:10"
+/*++
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+--*/
+/*++
+
+ Modification History
+
+ N- NEW
+ D- Only For Debug
+ B- Bug Fix
+
+ N001 ataka@oa2.kb.nec.co.jp Tue Oct 4 21:29:32 JST 1994
+ - (from r98busdat.h && halx86/i386/halp.h)
+
+--*/
+
+//
+// Bus handlers
+//
+
+typedef ULONG
+(*PGETSETBUSDATA)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+typedef ULONG
+(*PGETINTERRUPTVECTOR)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+typedef BOOLEAN
+(*PTRANSLATEBUSADDRESS)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+typedef NTSTATUS
+(*PADJUSTRESOURCELIST)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+typedef NTSTATUS
+(*PASSIGNSLOTRESOURCES)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+typedef struct tagBUSHANDLER {
+ struct tagBUSHANDLER *Next;
+
+ // this entry is for:
+ INTERFACE_TYPE InterfaceType;
+ BUS_DATA_TYPE ConfigurationType;
+ ULONG BusNumber;
+
+ // bus specific data:
+ struct tagBUSHANDLER *ParentHandler;
+ PVOID BusData;
+
+ // handlers for bus functions
+ PGETSETBUSDATA GetBusData;
+ PGETSETBUSDATA SetBusData;
+ PADJUSTRESOURCELIST AdjustResourceList;
+ PASSIGNSLOTRESOURCES AssignSlotResources;
+ PGETINTERRUPTVECTOR GetInterruptVector;
+ PTRANSLATEBUSADDRESS TranslateBusAddress;
+} BUSHANDLER, *PBUSHANDLER;
+
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+PBUSHANDLER HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN BUS_DATA_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+#define HalpAllocateConfigSpace HalpAllocateBusHandler
+
+PBUSHANDLER HalpHandlerForBus (
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber
+ );
+
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUSHANDLER BusHandler,
+ IN PBUSHANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableLength,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ );
diff --git a/private/ntos/nthals/halr98mp/mips/r98clock.s b/private/ntos/nthals/halr98mp/mips/r98clock.s
new file mode 100644
index 000000000..73f629f57
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98clock.s
@@ -0,0 +1,471 @@
+// "@(#) NEC r98clock.s 1.10 95/02/20 17:04:37"
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// r98clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+//--
+
+//
+// Original source: Build Number 1.612
+//
+// Modify for R98(MIPS/R4400)
+//
+//***********************************************************************
+//
+// M001 94.03/16-5/31 T.Samezima
+//
+// change header file from duo to r98
+// change value of use to update of parformance counter
+// initial value of count register
+//
+// del clear interrupt
+//
+//***********************************************************************
+//
+// S002 94.6/13 T.Samezima
+//
+// Del Compile err
+//
+//
+//***********************************************************************
+//
+// S003 94.7/19 T.Samezima
+//
+// Chg Function interface change
+//
+//***********************************************************************
+//
+// S004 94.7/19 T.Samezima
+//
+// Bug PMC register address is not change of KSEG1_BASE
+//
+//***********************************************************************
+//
+// S005 94.10/12 T.Samezima
+//
+// Fix Version Up at build807
+//
+// S006 '94.10/14 T.Samezima
+// Chg Logic of set interval count
+//
+// S007 '94.01/11 T.Samezima
+// Del delete 'if NT_UP'.
+//
+// S008 '94.01/16 T.Samezima
+// Add Check ECC 1bit err flag and enable ECC 1bit err.
+//
+//
+
+#include "halmips.h"
+// Start M001
+#if defined(_R98_)
+
+#include "r98def.h"
+// #include "r98reg.h" // S002
+
+#else // if defined(_R98_)
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdef.h"
+
+#endif
+#endif // #if !defined(_R98_)
+// End M001
+
+#define ECC_ERROR_COUNT_LIMIT 1 // S008
+
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame. // S003
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+// Start M001
+#if !defined(_R98_)
+ .set noreorder
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+
+#endif
+
+#if defined(_JAZZ_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
+
+#endif
+
+ .set reorder
+#endif // #if !defined(_R98_)
+// End M001
+
+// S003
+// move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time // S005
+ jal t0 // // S005
+
+//
+// The following code is a work around for a bug in the Fusion machines
+// where the clock interrupt is not dismissed by reading the acknowledge
+// register.
+//
+
+// Start M001
+#if !defined(_R98_)
+#if defined(_JAZZ_)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,cause // read the cause register
+ lw t1,HalpEisaControlBase // get EISA control base address
+ sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit
+ bgez t0,10f // if gez, no clock interrupt pending
+ li t2,0x2 // get NMI port enable bit
+ lb t3,0x70(t1) // save EISA NMI interrupt disable
+ lb t4,0x461(t1) // save EISA extended NMI status
+ sb zero,0x70(t1) // clear EISA NMI interrupt disable
+ sb t2,0x461(t1) // set EISA NMI port enable
+ sb zero,0x462(t1) // generate EISA NMI interrupt
+ sb zero,0x461(t1) // clear EISA extended NMI status
+ sb t2,0x461(t1) //
+ lb zero,0x461(t1) // synchronize clear operatin
+ sb t3,0x70(t1) // restore EISA NMI interupt disable
+ sb t4,0x461(t1) // restore EISA exteneed NMI status
+ lb zero,0x461(t1) // synchronize restore operation
+ .set at
+ .set reorder
+
+10: //
+
+#endif
+#endif // #if !defined(_R98_)
+// End M001
+
+// S008 vvv
+//
+// Check ECC 1bit error flag.
+//
+
+ lw t0,HalpECC1bitDisableTime // get value of disable time
+ beq zero,t0,10f // if ne, check ecc 1bit
+ lw t1,HalpCurrentTimeIncrement // get current time increment
+ subu t0,t0,t1 // declement disable time
+ sw t0,HalpECC1bitDisableTime //
+ blez t0,5f // if lez, enable ecc 1bit
+ beq zero,zero,10f // not lez,
+
+5: sw zero,HalpECC1bitDisableTime // clear disable time
+ li t0,ECC_ERROR_COUNT_LIMIT // set new flag
+ sw t0,HalpECC1bitDisableFlag //
+ la t1,KSEG1_BASE+SIC_PHYSICAL_BASE+SIC_DATA_OFFSET+SIC_SET0_OFFSET
+ sw zero,0x0(t1) // enable ECC 1bit error
+ lw t0,HalpECC1bitScfrBuffer // check connect to SIC1
+ andi t0,SCFR_SIC_SET1_CONNECT //
+ bne t0,zero,10f //
+ la t1,KSEG1_BASE+SIC_PHYSICAL_BASE+SIC_DATA_OFFSET+SIC_SET1_OFFSET
+ sw zero,0x0(t1) // enable ECC 1bit error
+// S008 ^^^
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+10: lw t0,KdDebuggerEnabled // get address of debugger enable // S008
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,30f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+
+// Start M001
+ .set noreorder
+
+#if !defined(_R98_)
+#if defined(_DUO_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count
+
+#endif
+
+#if defined(_JAZZ_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
+
+#endif
+# else // #if !defined(_R98_)
+
+ sw t1,KSEG1_BASE+PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+0x40(zero) // S004
+
+#endif // #if !defined(_R98_)
+
+ .set reorder
+// End M001
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame. // S003
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+#if !defined(_R98_)
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+ move a0,s8 // set address of trap frame
+ j KeUpdateRunTime // update system time
+
+#endif
+#else // #if !defined(_R98_)
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+
+// S006 vvv
+ la t2,HalpChangeIntervalFlg // get change flag of timer interval
+ lbu t1,PbNumber(t1) // get processor number
+ add t2,t1,t2 // check flag
+ lb t1,0x0(t2) // get change flag of this CPU
+ beq t1,zero,10f // if eq, no change timer interval
+ sb zero,0x0(t2) // clear change flag of timer interval
+// S006 ^^^
+
+ lw t1,HalpChangeIntervalCount // get next interval count
+ sw t1,KSEG1_BASE+PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+0x40(zero) // S004
+
+// Start S003, S005
+//10: move a0,s8 // set address of trap frame
+10: lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1 //
+// End S003, S005
+
+#endif // #if !defined(_R98_)
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame. // S003
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+// Start M001
+ mfc0 t0,count // get current count value
+ addu t1,zero,3 // set initial count value
+ mtc0 t1,count // set new count register value
+// End M001
+ .set at
+ .set reorder
+
+#if 0 // S007
+//#if defined(NT_UP)
+
+ la t1,HalpPerformanceCounter // get performance counter address
+
+//#else
+#endif
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+// #endif // S007
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+
+// move a0,s8 // set address of trap frame // S003
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt // S005
+ j t4 // // S005
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halr98mp/mips/r98def.h b/private/ntos/nthals/halr98mp/mips/r98def.h
new file mode 100644
index 000000000..62e2aabaf
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98def.h
@@ -0,0 +1,471 @@
+#ident "@(#) NEC r98def.h 1.25 95/03/17 11:54:20"
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r98def.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the r98.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ *
+ ***********************************************************************
+ *
+ * S002 7/5 T.Samezima
+ *
+ * Chg define miss
+ *
+ ***********************************************************************
+ *
+ * S003 7/5 T.Samezima
+ *
+ * Add define unknown counter buffer length
+ *
+ ***********************************************************************
+ *
+ * S004 7/5 T.Samezima
+ *
+ * Add define err pci and dma in iRSF
+ * define dummy single read addr
+ *
+ ***********************************************************************
+ *
+ * S005 7/12 T.Samezima
+ *
+ * Chg define miss and define change
+ *
+ ***********************************************************************
+ *
+ * S006 7/19 T.Samezima
+ *
+ * Add define PCI err interrupt vector
+ *
+ ***********************************************************************
+ *
+ * S007 7/22 T.Samezima
+ *
+ * Add define PMC Dummy single read address.
+ *
+ ***********************************************************************
+ *
+ * S008 7/23 T.Samezima
+ *
+ * Add define SIC set0/1 offset
+ * define value of enable EIF interrupt of SIC CKE0/1 register
+ *
+ ***********************************************************************
+ *
+ * S009 8/22 T.Samezima on SNES
+ *
+ * Chg RTC physical base
+ *
+ ***********************************************************************
+ *
+ * S00a 8/22 T.Samezima on SNES
+ *
+ * Chg PIO, FDC interrupt pending bit on iRSF
+ *
+ * S00B 8/29 N.Kugimoto
+ *
+ * Bug NVRAM disable logic.
+ *
+ * K00C 9/5 N.Kugimoto
+ * add PCI slot 0 addr
+ *
+ * K00D 94/9/22 N.Kugimoto
+ * -1 chg No Used!
+ *
+ * S00E 94/10/13 T.Samezima
+ * Add define EISA interrupt enable bit
+ * define all clock interrupt restart command on TCIR in PMC
+ *
+ * S00F 94/10/18 T.Samezima
+ * Add define interrupt enable bit for device only
+ *
+ * S010 94/11/21 T.Samezima
+ * Add correspond SIC3 H/W Bug on R98
+ * Chg Dummy read address change. because old address is
+ * break scsi script.
+ *
+ * S011 '94.12/06 T.Samezima
+ * Add define CKE0 disable mask. (Disable Single bit error mask on SIC)
+ * Chg CKE0 enable mask change. (Disable Single bit error mask on SIC)
+ * ERRMK enable mask change. (bit 17,22 is must be zero. )
+ *
+ * K00E 94/12/06 N.Kugimoto
+ * Add ESM NVRAM Area
+ *
+ * S012 94/12/08 T.Samezima
+ * Add Disable NMI
+ *
+ * S013 '95.01/08 T.Samezima
+ * Add Enable ECC 1bit error.
+ *
+ * S014 '95.01/13 T.Samezima
+ * Add Define Disable ECC 1bit error.
+ *
+ * S015 '95.03/13 T.Samezima
+ * Add Define LR4360 error.
+ *
+ */
+
+#ifndef _R98DEF_
+#define _R98DEF_
+
+//
+// define address map
+//
+#define PMC_PHYSICAL_BASE1 0x19900000 // Physical base of PMC registers1
+#define PMC_PHYSICAL_BASE2 0x19800000 // Physical base of PMC registers2
+#define PMC_LOCAL_OFFSET 0x80000
+
+#define IOB_PHYSICAL_BASE 0x18000000 // Physical base of IOB
+
+#define SIC_PHYSICAL_BASE 0x19000000 // Physical base of SIC registers
+#define SIC_ERR_OFFSET 0x2000 // Error registers offset of SIC
+#define SIC_DATA_OFFSET 0x3000 // Data registers offset of SIC
+#define SIC_SET0_OFFSET 0x0 // Offset SET0 of SIC // S008
+#define SIC_SET1_OFFSET 0x20000 // Offset SET1 of SIC // S008
+#define SIC_NO0_OFFSET 0x4000 // Offset No.0 of SIC
+#define SIC_NO1_OFFSET 0x8000 // Offset No.1 of SIC
+// Start S005,S008
+#define SIC_NO2_OFFSET (SIC_SET1_OFFSET+SIC_NO0_OFFSET) // Offset No.2 of SIC
+#define SIC_NO3_OFFSET (SIC_SET1_OFFSET+SIC_NO1_OFFSET) // Offset No.3 of SIC
+// End S005,S008
+
+#define LR_PHYSICAL_CMNBASE1 0x18c08000 // Physical base of LR4360 registers1 // S005
+#define LR_PHYSICAL_CMNBASE2 0x18c0a000 // Physical base of LR4360 registers2
+#define LR_PHYSICAL_PCI_INT_ACK_BASE 0x18caa000 // Physical base of LR4360 pci interrupt acknowledge
+#define LR_PHYSICAL_PCI_DEV_REG_BASE 0x18cbb000 // Physical base of LR4360 pci device registers
+
+// Bbus DMA
+#define LR_CHANNEL_BASE 0x18c08000 // LR4360 - Device Channel Register Base
+ // 0x18Cn0000 : n:channel number
+#define LR_CHANNEL_SHIFT 0x10 // LR4360 - channel shift bit
+
+#define SERIAL0_PHYSICAL_BASE 0x18c103f8 // physical base of serial port 0
+#define KEYBOARD_PHYSICAL_BASE 0x18c20060 // physical base of keyboard control
+#define RTCLOCK_PHYSICAL_BASE 0x18cc0071 // physical base of realtime clock // S005, S009
+
+#define NVRAM_PHYSICAL_BASE 0x18c70000 // physical base of nonvolatile RAM
+#define NVRAM_MEMORY_BASE (KSEG1_BASE + NVRAM_PHYSICAL_BASE)
+#define NVRAM_NMI_BASE (NVRAM_MEMORY_BASE + 0x1934)
+
+#define NVRAM_ESM_BASE NVRAM_MEMORY_BASE+1024*8 //Start of ESM Area K00E
+#define NVRAM_ESM_END NVRAM_MEMORY_BASE+1024*16-1 //End of ESM Area K00E
+
+#define MRC_PHYSICAL_BASE 0x18c80000 // physical base of MRC
+
+#define EISA_MEMORY_PHYSICAL_BASE 0xc0000000 // physical base of EISA memory
+#define EISA_CONTROL_PHYSICAL_BASE 0x18cc0000 // physical base of EISA control
+#define EISA_CONFIG_REGISTERS_MEMREGN 0x18ca8060 // MEMREG[] register
+
+#define PCI_MEMORY_PHYSICAL_BASE EISA_MEMORY_PHYSICAL_BASE // physical base of PCI memory
+
+#define PCI_MEMORY_SLOT1_PHYSICAL_BASE 0xc4000000 // PCI slot1 memory space
+#define PCI_MEMORY_SLOT2_PHYSICAL_BASE 0xc8000000 // PCI slot2 memory space
+#define PCI_MEMORY_SLOT3_PHYSICAL_BASE 0xcc000000 // PCI slot3 memory space
+
+#define PCI_CONTROL_SLOT1_PHYSICAL_BASE 0x18cd0000 // PCI slot1 I/O space
+#define PCI_CONTROL_SLOT2_PHYSICAL_BASE 0x18ce0000 // PCI slot2 I/O space
+#define PCI_CONTROL_SLOT3_PHYSICAL_BASE 0x18cf0000 // PCI slot2 I/O space
+#define PCI_LOGICAL_START_ADDRESS 0x00000000 // S001,K00D-1
+
+//
+// define IDT vector
+//
+
+#define INT0_LEVEL 3 // Define I/O interrupt Low level
+#define INT1_LEVEL 4 // Define I/O interrupt High level
+#define INT2_LEVEL 5 // Define I/O interrupt level
+#define TIMER_LEVEL 6 // Define Timer interrupt level
+#define IPI_LEVEL 7 // Define Ipi interrupt level
+#define EIF_LEVEL 8 // Define Eif interrupt level
+#define CLOCK_VECTOR 14 // Define Clock interrupt vector
+#define PROFILE_VECTOR 15 // Define Profile interrupt vector
+
+#define DEVICE_VECTORS 16 // Define starting builtin device and bus vectors
+#define EISA_DEVICE_VECTOR (2 + DEVICE_VECTORS) // Define Eisa interrupt vector
+#define KBMS_VECTOR (3 + DEVICE_VECTORS)
+#define SIO_VECTOR (4 + DEVICE_VECTORS)
+#define PIO_VECTOR (5 + DEVICE_VECTORS) // S005, S00a
+#define FDC_VECTOR (6 + DEVICE_VECTORS) // S005, S00a
+#define SCSI1_VECTOR (7 + DEVICE_VECTORS)
+#define SCSI0_VECTOR (8 + DEVICE_VECTORS)
+#define ETHER_VECTOR (9 + DEVICE_VECTORS)
+#define PCI_DEVICE_VECTOR (10+ DEVICE_VECTORS) // Define PCI interrupt vector
+#define LR_ERR_VECTOR (13+ DEVICE_VECTORS) // Define LR4360 err vector // S015
+#define PCI_ERR_VECTOR (14+ DEVICE_VECTORS) // Define PCI err vector // S006
+#define DMA_VECTOR (15+ DEVICE_VECTORS) // Define Dma interrupt vector
+
+#define EISA_VECTORS 32 // Define EISA Device interrupt vectors
+#define PCI_VECTORS 48 // Define Pci Device interrupt vectors
+
+#define MAXIMUM_BUILTIN_VECTOR ETHER_VECTOR // maximum builtin vector
+#define MAXIMUM_EISA_VECTORS (15 + EISA_VECTORS) // maximum EISA vector
+#define MAXIMUM_PCI_VECTORS (3 + PCI_VECTORS) // maximum PCI vector // S005
+
+//
+// define etc
+//
+
+#define MAXIMUM_CPU_NUMBER 3 // maximum cpu number
+// S003
+#define UNKNOWN_COUNT_BUF_LEN 64 // unknown interrupt counter buffer size
+
+/* Start S001 */
+//
+// define PMC registers value
+//
+
+#define PMC_CPU_SHIFT 0xc // S002
+
+#define MKR_DISABLE_ALL_INTERRUPT_HIGH 0x0
+#define MKR_DISABLE_ALL_INTERRUPT_LOW 0x0
+
+#define MKR_INT0_ENABLE_HIGH 0x0
+// S001
+#define MKR_INT0_ENABLE_LOW 0x00000fff
+#define MKR_INT1_ENABLE_HIGH 0x0
+#define MKR_INT1_ENABLE_LOW 0x00fff000
+#define MKR_INT2_ENABLE_HIGH 0x0
+#define MKR_INT2_ENABLE_LOW 0xff000000
+#define MKR_INT3_ENABLE_HIGH 0x00030000
+#define MKR_INT3_ENABLE_LOW 0x0
+#define MKR_INT4_ENABLE_HIGH 0x0000ffff
+#define MKR_INT4_ENABLE_LOW 0x0
+#define MKR_INT5_ENABLE_HIGH 0xff000000
+#define MKR_INT5_ENABLE_LOW 0x0
+
+// S00F vvv
+#define MKR_INT0_DEVICE_ENABLE_HIGH 0x0
+#define MKR_INT0_DEVICE_ENABLE_LOW 0x0
+#define MKR_INT1_DEVICE_ENABLE_HIGH 0x0
+#define MKR_INT1_DEVICE_ENABLE_LOW 0x00a88000
+#define MKR_INT2_DEVICE_ENABLE_HIGH 0x0
+#define MKR_INT2_DEVICE_ENABLE_LOW 0xaa000000
+// S00F ^^^
+
+#define IPR_EIF_BIT_NO 61
+#define IPR_EIF_BIT_HIGH 0x20000000
+#define IPR_EIF_BIT_LOW 0x0
+#define IPR_CLOCK_BIT_NO 49
+#define IPR_CLOCK_BIT_HIGH 0x00020000
+#define IPR_CLOCK_BIT_LOW 0x0
+#define IPR_PROFILE_BIT_NO 48
+#define IPR_PROFILE_BIT_HIGH 0x00010000
+#define IPR_PROFILE_BIT_LOW 0x0
+#define IPR_IPI0_BIT_NO 47
+#define IPR_IPI0_BIT_HIGH 0x00008000
+#define IPR_IPI0_BIT_LOW 0x0
+#define IPR_IPI1_BIT_NO 46
+#define IPR_IPI1_BIT_HIGH 0x00004000
+#define IPR_IPI1_BIT_LOW 0x0
+#define IPR_IPI2_BIT_NO 45
+#define IPR_IPI2_BIT_HIGH 0x00002000
+#define IPR_IPI2_BIT_LOW 0x0
+#define IPR_IPI3_BIT_NO 44
+#define IPR_IPI3_BIT_HIGH 0x00001000
+#define IPR_IPI3_BIT_LOW 0x0
+#define IPR_SIO_BIT_NO 31
+#define IPR_SIO_BIT_HIGH 0x0
+#define IPR_SIO_BIT_LOW 0x80000000
+#define IPR_FDC_PIO_BIT_NO 29
+#define IPR_FDC_PIO_BIT_HIGH 0x0
+#define IPR_FDC_PIO_BIT_LOW 0x20000000
+#define IPR_DMA_BIT_NO 27
+#define IPR_DMA_BIT_HIGH 0x0
+#define IPR_DMA_BIT_LOW 0x08000000
+#define IPR_KB_MS_BIT_NO 25
+#define IPR_KB_MS_BIT_HIGH 0x0
+#define IPR_KB_MS_BIT_LOW 0x02000000
+#define IPR_ETHER_BIT_NO 23
+#define IPR_ETHER_BIT_HIGH 0x0
+#define IPR_ETHER_BIT_LOW 0x00800000
+#define IPR_SCSI_BIT_NO 21
+#define IPR_SCSI_BIT_HIGH 0x0
+#define IPR_SCSI_BIT_LOW 0x00200000
+#define IPR_PCI_BIT_NO 19
+#define IPR_PCI_BIT_HIGH 0x0
+#define IPR_PCI_BIT_LOW 0x00080000
+#define IPR_EISA_BIT_NO 15
+#define IPR_EISA_BIT_HIGH 0x0
+#define IPR_EISA_BIT_LOW 0x00008000
+
+#define IntIR_REQUEST_IPI 0x00900000
+#define IntIR_CPU3_BIT 12
+#define IntIR_CODE_BIT 16
+
+#define TCIR_ALL_CLOCK_RESTART 0x000cf000 // S00E
+
+// S002
+#if defined(DISABLE_NMI)
+#define STSR_NMI_DISABLE 0x08080000 // S008
+#endif
+#define STSR_EIF_ENABLE 0x40400000
+#define STSR_NVWINH_ENABLE 0x04040000 // S005
+#define STSR_NVWINH_DISABLE 0x00040000 // S00B
+#define ERRMK_EIF_ENABLE 0xffbdfffe // S011
+
+//
+// Define the minimum and maximum system time increment values in 100ns units.
+//
+// original ntos/inc/duodef.h
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+//
+// Time increment in 1us units
+//
+#define CLOCK_INTERVAL (MAXIMUM_INCREMENT / 10)
+
+// original ntos/inc/mips.h
+#define DEFAULT_PROFILETIMER_COUNT 65000 // = 65 ms
+#define DEFAULT_PROFILETIMER_INTERVAL (500 * 10) // = 500 us (100ns units)
+#define MAXIMUM_PROFILETIMER_INTERVAL (65000 * 10) // = 65 ms (100ns units)
+#define MINIMUM_PROFILETIMER_INTERVAL (40 * 10) // = 40 us (100ns units)
+
+//
+// define IOB registers value
+//
+
+#define EIMR_DISABLE_ALL_EIF 0x0
+#define EIMR_ENABLE_ALL_EIF 0xffe00000 // S002
+#define IEMR_ENABLE_ALL_EIF 0xfffffe00 // S002
+
+#define SCFR_CPU0_CONNECT 0x8000
+#define SCFR_CPU1_CONNECT 0x4000
+#define SCFR_CPU2_CONNECT 0x2000
+#define SCFR_CPU3_CONNECT 0x1000
+#define SCFR_SIC_SET0_CONNECT 0x0800
+#define SCFR_SIC_SET1_CONNECT 0x0400
+
+#define AII_INIT_DATA 0x80008000
+
+// Start S008, S010
+//
+// define IOB registers value
+//
+#define CKE0_DISABLE_SBE 0xffffffff // S011, S013
+#define DPCM_ENABLE_MASK 0x1fffffff // S013
+#define DPCM_ECC1BIT_BIT 0x40000000 // S013, S014
+
+#define SECT_REWRITE_ENABLE 0x0000000f // S013
+
+#if defined(WORKAROUND_SIC3)
+//#define CKE0_DISABLE_SBE 0xf7ffffff // S011
+//#define CKE0_ENABLE_ALL_EIF 0xf040ff00 // S011 //R98TEMP SIC3 H/W Bug
+#define CKE0_ENABLE_ALL_EIF 0xf840ff00 // S011, S013
+#define CKE1_ENABLE_ALL_EIF 0xff700000 //R98TEMP SIC3 H/W Bug
+#else
+//#define CKE0_DISABLE_SBE 0xf7ffffff // S011
+#define CKE0_ENABLE_ALL_EIF 0xf8c0ff00 // S011, S013
+#define CKE1_ENABLE_ALL_EIF 0xfff00000
+#endif
+// End S008, S010
+
+//
+// Define NABus code
+//
+
+#define NACODE_SIO ((0x1f-IPR_SIO_BIT_NO) << 0x2)
+#define NACODE_FDC_PIO ((0x1f-IPR_FDC_PIO_BIT_NO) << 0x2)
+#define NACODE_DMA ((0x1f-IPR_DMA_BIT_NO) << 0x2)
+#define NACODE_KB_MS ((0x1f-IPR_KB_MS_BIT_NO) << 0x2)
+#define NACODE_ETHER ((0x1f-IPR_ETHER_BIT_NO) << 0x2)
+#define NACODE_SCSI ((0x1f-IPR_SCSI_BIT_NO) << 0x2)
+#define NACODE_PCI ((0x1f-IPR_PCI_BIT_NO) << 0x2)
+#define NACODE_EISA ((0x1f-IPR_EISA_BIT_NO) << 0x2)
+
+//
+// define LR4360 registers value
+//
+#define ERRS_ERROR_BIT 0x00008000 // S005
+#define iREN_DISABLE_ALL_INTERRUPT 0x0
+#define iREN_ENABLE_DMA_INTERRUPT 0x00020000
+#define iREN_ENABLE_LR_ERR_INTERRUPT 0x00010000 // S015
+#define iREN_ENABLE_PCI_INTERRUPT 0x00000200 // S006
+#define iREN_ENABLE_PCI_ERR_INTERRUPT 0x00400000 // S006
+#define iREN_ENABLE_EISA_INTERRUPT 0x00000002 // S00E
+#define iRRE_MASK 0x004203fe
+#define iRSF_CLEAR_INTERRUPT 0x000003fe // S005
+// Start S004
+#define iRSF_ERRPCI_BIT 0x00400000
+#define iRSF_DMA_BIT 0x00020000
+#define iRSF_LR_ERR_BIT 0x00010000 // S015
+// End S004
+#define iRSF_PCI_BIT 0x00000200
+#define iRSF_ETHER_BIT 0x00000100
+#define iRSF_SCSI0_BIT 0x00000080
+#define iRSF_SCSI1_BIT 0x00000040
+#define iRSF_FDC_BIT 0x00000020 // S005, S00a
+#define iRSF_PIO_BIT 0x00000010 // S005, S00a
+#define iRSF_SIO_BIT 0x0000008
+#define iRSF_KBMS_BIT 0x00000004
+#define iRSF_EISA_BIT 0x00000002
+#define LR_iRSF_REG_iNSF_SHIFT 0x11
+#define LR4360PTSZ4K 0x1
+#define LR4360PTSZ8K 0x2
+#define LR4360PTSZ16K 0x4
+#define LR4360PTSZ32K 0x8
+#define LR4360PTSZSHIFT 0xc
+#define LR_DMA_MODE_NORMAL 0x00
+
+//
+// Define dummy single read address
+//
+
+#define SIO_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define PIO_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define FDC_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define DMA_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000
+#define KBMS_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define ETHER_DUMMY_READ_ADDR KSEG1_BASE+0x018600000
+#define SCSI0_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S010
+#define SCSI1_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S010
+#define PCI_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000
+#define EISA_DUMMY_READ_ADDR KSEG1_BASE+0x018cc0023
+#define EIF_DUMMY_READ_ADDR KSEG1_BASE+0x018000218 // S005
+
+#define PMC_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S007
+
+//
+// Define cause register bit offset
+//
+
+#define CAUSE_INT_PEND_BIT 0x8
+
+//
+// Define cause register read macro
+//
+
+#define READ_CAUSE_REGISTER(reg) \
+ .set noreorder; \
+ .set noat; \
+ mfc0 reg,cause; \
+ nop; \
+ nop; \
+ .set at; \
+ .set reorder;
+
+/* End S001 */
+
+#endif _R98DEF_
diff --git a/private/ntos/nthals/halr98mp/mips/r98dspt.c b/private/ntos/nthals/halr98mp/mips/r98dspt.c
new file mode 100644
index 000000000..3c89949ec
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98dspt.c
@@ -0,0 +1,704 @@
+#ident "@(#) NEC r98dspt.c 1.14 95/03/17 11:55:28"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98dspt.c
+
+Abstract:
+
+ This module implements the interrupt dispatch routines for R98
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 7/7 T.Samezima
+ *
+ * Chg all alteration Int0-2 dispach routine
+ *
+ * Del move some define in r98def.h
+ *
+ ***********************************************************************
+ *
+ * S002 8/22 T.Samezima on SNES
+ *
+ * Add Buffer for register save when unknown interrupt
+ * Count up at loop counter
+ *
+ * Chg Modify loop logic
+ *
+ ***********************************************************************
+ *
+ * S003 9/30 T.Samezima
+ *
+ * Bug define miss on Int1 dispatch table.
+ *
+ * S004 '94.10/14 T.Samezima
+ * Chg Display IPR and iRSF register on bugcheck
+ *
+ * S005 '94.11/8 T.Samezima
+ * Del Delete call of KeBugCheck. because of wrong interrupt ocure
+ * of LR4360 bug
+ *
+ * S006 '94.11/21 T.Samezima
+ * Chg Change size of dummy read
+ *
+ * S007 '94.12/28 T.Samezima
+ * Add interrupt clear Broadcast in Unknown interrupt
+ *
+ * S009 '95.01/11 T.Samezima
+ * Add Dummy single read on EIF interrupt.
+ *
+ * S00a '95.03/13 T.Samezima
+ * Del PIO interrupt check.
+ * Add LR4360 error check.
+ * check dummy single read
+ *
+ */
+
+#include "halp.h"
+//#include "halmips.h"
+#include "bugcodes.h"
+
+/* Start S001 */
+//
+// Define table in use interrupt dispatch routine
+//
+#define INT2_DATA_TABLE_SIZE 5
+#define INT1_DATA_TABLE_SIZE 6
+
+enum _INT_DISP_TABLE {
+ iRSF_BIT=0,
+ IPR_BIT,
+ IDT_VECTOR,
+ DUMMY_READ_ADDR,
+ DUMMY_READ_SIZE,
+ NA_CODE
+ };
+
+typedef struct _DISPATCH_DATA_TABLE {
+ ULONG IrsfMask;
+ ULONG IprMask;
+ ULONG IdtVector;
+ ULONG DummyReadAddr;
+ ULONG DummyReadSize;
+ ULONG NaCode;
+} DISPATCH_DATA_TABLE, *PDISPATCH_DATA_TABLE;
+
+DISPATCH_DATA_TABLE HalpInt2DispatchDataTable[] = {
+ {iRSF_KBMS_BIT, IPR_KB_MS_BIT_LOW, KBMS_VECTOR,
+ KBMS_DUMMY_READ_ADDR, 1, NACODE_KB_MS},
+// {iRSF_PIO_BIT, IPR_FDC_PIO_BIT_LOW, PIO_VECTOR,
+// PIO_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a
+ {iRSF_LR_ERR_BIT,IPR_DMA_BIT_LOW, LR_ERR_VECTOR,
+ DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}, // S00a
+ {iRSF_FDC_BIT, IPR_FDC_PIO_BIT_LOW, FDC_VECTOR,
+ FDC_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a
+ {iRSF_SIO_BIT, IPR_SIO_BIT_LOW, SIO_VECTOR,
+ SIO_DUMMY_READ_ADDR, 1, NACODE_SIO},
+ {iRSF_DMA_BIT, IPR_DMA_BIT_LOW, DMA_VECTOR,
+ DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}
+};
+
+DISPATCH_DATA_TABLE HalpInt1DispatchDataTable[] = {
+ {iRSF_EISA_BIT, IPR_EISA_BIT_LOW, EISA_DEVICE_VECTOR,
+ EISA_DUMMY_READ_ADDR, 1, NACODE_EISA},
+ {iRSF_SCSI1_BIT, IPR_SCSI_BIT_LOW, SCSI1_VECTOR,
+ SCSI1_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006
+ {iRSF_ETHER_BIT, IPR_ETHER_BIT_LOW, ETHER_VECTOR,
+ ETHER_DUMMY_READ_ADDR, 2, NACODE_ETHER},
+ {iRSF_PCI_BIT, IPR_PCI_BIT_LOW, PCI_DEVICE_VECTOR,
+ PCI_DUMMY_READ_ADDR, 4, NACODE_PCI}, // S003
+ {iRSF_SCSI0_BIT, IPR_SCSI_BIT_LOW, SCSI0_VECTOR,
+ SCSI0_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006, S00a
+ {iRSF_ERRPCI_BIT,IPR_PCI_BIT_LOW, PCI_ERR_VECTOR,
+ PCI_DUMMY_READ_ADDR, 4, NACODE_PCI} // S003
+};
+
+// DISPATCH_DATA_TABLE HalpInt0DispatchDataTable[];
+
+enum _INT_TABLE_DATA{
+ TABLE_SIZE=0,
+ MKR_MASK,
+ INT_LEVEL
+ };
+
+ULONG HalpIntData[3][3] = {
+ {0, MKR_INT0_ENABLE_LOW, INT0_LEVEL},
+ {INT1_DATA_TABLE_SIZE, MKR_INT1_ENABLE_LOW, INT1_LEVEL},
+ {INT2_DATA_TABLE_SIZE, MKR_INT2_ENABLE_LOW, INT2_LEVEL}
+};
+
+//
+// Define pointer of interrupt arbitration
+//
+ULONG HalpInt2ArbitrationPoint = 0;
+ULONG HalpInt1ArbitrationPoint = 0;
+ULONG HalpInt0ArbitrationPoint = 0;
+/* End S001 */
+
+#if DBG
+//
+// Register buffer
+//
+
+ULONG HalpUnknownCause = 0; // S002
+ULONG HalpUnknownIPRUpper = 0;
+ULONG HalpUnknownIPRLower = 0;
+ULONG HalpUnknownMKRUpper = 0;
+ULONG HalpUnknownMKRLower = 0;
+ULONG HalpUnknowniRRE = 0; // S002
+ULONG HalpUnknowniREN = 0; // S002
+ULONG HalpUnknowniRSF = 0; // S002
+ULONG HalpUnknownIprUpperBuf = 0; // S002
+ULONG HalpUnknownIprLowerBuf = 0; // S002
+ULONG HalpIoIntLoopCounter; // S002
+
+#endif
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PTIMER_DISPATCH)(
+ ULONG TrapFrame
+ );
+
+
+VOID
+HalpUnknownInterrupt(
+ IN ULONG IprUpper,
+ IN ULONG IprLower
+ )
+/*++
+
+Routine Description:
+
+ This function is reset of unknown interrupt.
+
+Argments:
+
+ IprUpper (a0) - Supplies upper 32bit of result of "IPR & MKR" in present INT level.
+
+ IprLower (a1) - Supplies lower 32bit of result of "IPR & MKR" in present INT level.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG i;
+
+// Start S002
+#if DBG
+ HalpUnknownCause = HalpGetCause();
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &HalpUnknownIPRUpper,
+ &HalpUnknownIPRLower
+ );
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &HalpUnknownMKRUpper,
+ &HalpUnknownMKRLower
+ );
+
+ HalpUnknownIprUpperBuf = IprUpper;
+ HalpUnknownIprLowerBuf = IprLower;
+
+ HalpUnknowniRRE = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE );
+ HalpUnknowniREN = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN );
+ HalpUnknowniRSF = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF );
+
+#if 0 // S005 vvv
+ KeBugCheckEx(INTERRUPT_EXCEPTION_NOT_HANDLED,
+ IprUpper,
+ IprLower,
+ HalpUnknowniRSF,
+ HalpUnknowniRRE
+ ); // S004
+#endif // S005 ^^^
+
+#endif
+// End S002
+
+ //
+ // clear interrupt pending bit
+ //
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &IprUpper,
+ &IprLower
+ );
+ // S007 vvv
+ //
+ // issue broadcast of unknown interrupt clear
+ //
+
+ if( IprLower != 0 ) {
+ PDISPATCH_DATA_TABLE dataTable;
+ ULONG tableSize;
+
+ if( IprLower & MKR_INT2_ENABLE_LOW ) {
+ dataTable = HalpInt2DispatchDataTable;
+ tableSize = INT2_DATA_TABLE_SIZE;
+ } else if( IprLower & MKR_INT1_ENABLE_LOW ) {
+ dataTable = HalpInt1DispatchDataTable;
+ tableSize = INT1_DATA_TABLE_SIZE;
+ }
+
+ for( i=0; i<tableSize; i++) {
+ if( i == 1 )
+ continue;
+ if( (IprLower & dataTable[i].IprMask) != 0 ) {
+ WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ),
+ dataTable[i].NaCode );
+ }
+ }
+ }
+ // S007 ^^^
+
+ //
+ // count up unknown interrupt
+ //
+
+ for ( i=0 ; i < 32 ; i++ ) {
+ HalpUnknownInterruptCount[i] += (IprUpper >> i) & 1;
+ HalpUnknownInterruptCount[i+32] += (IprLower >> i) & 1;
+ }
+}
+
+VOID
+HalpEifDispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an eif interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG zero=0;
+ ULONG buffer;
+
+ //
+ // Get interrpt pending bit
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+Loop:
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterUpperPart &= pmcIPRRegisterUpperPart;
+
+ //
+ // Check eif interrupt
+ //
+
+ buffer=pmcRegisterUpperPart & IPR_EIF_BIT_HIGH;
+
+ if( buffer ){
+ //
+ // issue dummy single read
+ //
+
+ READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+ READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+
+ HalpHandleEif();
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ } else {
+ HalpUnknownInterrupt( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH,
+ 0 );
+ }
+
+ //
+ // Check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ if( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH ){
+ goto Loop;
+ }
+ } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + EIF_LEVEL - 1)) );
+
+ return;
+}
+
+
+VOID
+HalpTimerScDispatch(
+ IN ULONG TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an timer interrupt.
+
+Argments:
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG zero=0;
+ ULONG buffer;
+
+ //
+ // read IPR register
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ //
+ // read MKR register
+ //
+
+Loop:
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterUpperPart &= pmcIPRRegisterUpperPart;
+
+ //
+ // check profile and clock interrupt
+ //
+
+ buffer=pmcRegisterUpperPart & IPR_PROFILE_BIT_HIGH;
+
+ if( buffer ){
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT2.Long), 0x0 ); // S002
+
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[PROFILE_VECTOR])(TrapFrame);
+ } else {
+ buffer=pmcRegisterUpperPart & IPR_CLOCK_BIT_HIGH;
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT1.Long), 0x0 ); // S002
+
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[CLOCK_VECTOR])(TrapFrame);
+ }
+
+ //
+ // Check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ if( pmcIPRRegisterUpperPart & MKR_INT3_ENABLE_HIGH ){
+ goto Loop;
+ }
+ } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + TIMER_LEVEL - 1)) );
+
+ return;
+}
+
+
+/* Start S001 */
+VOID
+HalpIoIntDispatch(
+ IN PDISPATCH_DATA_TABLE DataTable,
+ IN OUT PULONG ArbitrationPoint,
+ IN ULONG IntNo
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int0, int1, and int2 interrupt.
+
+Argments:
+
+ DataTable - Supplies a table useing judge interrupt factor.
+
+ ArbitrationPoint - Supplies a start point of checking interrupt.
+
+ IntNo - Supplies interrupt level.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG buffer;
+ ULONG counter;
+ ULONG position;
+ ULONG zero=0;
+ ULONG flag;
+
+ // Start S002
+#if DBG
+ HalpIoIntLoopCounter = 0;
+#endif
+ // End S002
+
+ //
+ // Get interrpt pending bit
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+//Loop: // S002
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterLowerPart &= pmcIPRRegisterLowerPart;
+
+Loop: // S002
+ buffer = READ_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF) );
+
+ (*ArbitrationPoint)++;
+
+ flag = FALSE;
+
+ for(counter = 0; counter < HalpIntData[IntNo][TABLE_SIZE] ; counter++){
+
+ position = ( (*ArbitrationPoint + counter) % HalpIntData[IntNo][TABLE_SIZE]);
+
+ //
+ // check interrupt
+ //
+
+ if( ((buffer & DataTable[position].IrsfMask) == 0) ||
+ ((pmcRegisterLowerPart & DataTable[position].IprMask) == 0) ) {
+ continue;
+ }
+
+ flag = TRUE;
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &zero,
+ &(DataTable[position].IprMask)
+ );
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[DataTable[position].IdtVector])(
+ PCR->InterruptRoutine[DataTable[position].IdtVector]
+ );
+
+ // Start S002
+ //
+ // Clear Interrupt pending bit in iRSF register
+ //
+
+ WRITE_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF),
+ DataTable[position].IrsfMask );
+ // End S002
+
+ //
+ // issue dummy single read
+ //
+
+ switch(DataTable[position].DummyReadSize){
+ case 1:
+ READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr );
+ READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr );
+ break;
+ case 2:
+ READ_REGISTER_USHORT( DataTable[position].DummyReadAddr );
+ READ_REGISTER_USHORT( DataTable[position].DummyReadAddr );
+ break;
+ case 4:
+ READ_REGISTER_ULONG( DataTable[position].DummyReadAddr );
+ READ_REGISTER_ULONG( DataTable[position].DummyReadAddr );
+ break;
+ }
+
+ //
+ // issue broadcast of interrupt clear
+ //
+
+ WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ),
+ DataTable[position].NaCode );
+
+ break; // S006
+ }
+
+ if (flag == FALSE){
+ HalpUnknownInterrupt( 0,
+ pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK]
+ );
+ }
+
+ //
+ // check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ // Start S002
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterLowerPart &= pmcIPRRegisterLowerPart;
+ // end S002
+
+ if( pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK] ){
+ // Start S002
+#if DBG
+ HalpIoIntLoopCounter++;
+#endif
+ // End S002
+ goto Loop;
+ }
+ } while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+HalpIntData[IntNo][INT_LEVEL]-1));
+
+ return;
+}
+
+
+VOID
+HalpInt2Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int2 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( HalpInt2DispatchDataTable,
+ &HalpInt2ArbitrationPoint,
+ 2
+ );
+}
+
+
+VOID
+HalpInt1Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int1 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( HalpInt1DispatchDataTable,
+ &HalpInt1ArbitrationPoint,
+ 1
+ );
+}
+
+
+VOID
+HalpInt0Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int0 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( (PDISPATCH_DATA_TABLE)NULL,
+ &HalpInt0ArbitrationPoint,
+ 0
+ );
+}
+/* End S001 */
diff --git a/private/ntos/nthals/halr98mp/mips/r98eif.c b/private/ntos/nthals/halr98mp/mips/r98eif.c
new file mode 100644
index 000000000..98aefd3d1
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98eif.c
@@ -0,0 +1,801 @@
+#ident "@(#) NEC r98eif.c 1.16 95/03/17 11:56:21"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98eif.c
+
+Abstract:
+
+ This module implements the Eif interrupt service routine for R98
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S002 7/5 T.Samezima
+ *
+ * Chg CPU No set miss
+ *
+ ***********************************************************************
+ *
+ * S003 7/22 T.Samezima
+ *
+ * Add give the dummy read after IOB and SIC register read
+ * for PMC3 bug
+ *
+ ***********************************************************************
+ *
+ * S004 8/23 T.Samezima
+ *
+ * Chg Condition change
+ *
+ ***********************************************************************
+ *
+ * S005 8/24 T.Samezima
+ *
+ * Chg Change a form of display on eif status
+ * Define buffer name
+ *
+ ***********************************************************************
+ *
+ * S006 9/22 T.Samezima
+ *
+ * Add Execution owner flag
+ * Lower the Irql level to TIMER_LEVEL. Because KdPrint
+ * use to inter processor interrupt.
+ *
+ * Chg buffer size
+ *
+ ***********************************************************************
+ *
+ * S007 9/27 T.Samezima
+ *
+ * Chg Arg miss
+ *
+ ***********************************************************************
+ *
+ * S008 9/27 T.Samezima
+ *
+ * Chg Init value
+ *
+ * S009 10/25 T.Samezima
+ * Add Variable of KeBugCheckEx()
+ *
+ * S00a 11/29 T.Samezima
+ * Add Enable _R98DBG_
+ *
+ * S00b 12/07 T.Samezima
+ * Chg print format.
+ *
+ * S00c 12/24 T.Samezima
+ * Add ESM logic.
+ * Del move EIFR_REGISTER define to r98reg.h
+ *
+ * S00d '95.01/11 T.Samezima
+ * Add Disable EIF interrupt in wait loop.
+ *
+ * S00e '95.01/13 T.Samezima
+ * Add Wait for all processers in wait loop.
+ *
+ * S00f '95.01/16-25 T.Samezima
+ * Add Check ECC 1bit flag.
+ *
+ * S010 '95.03/10 T.Samezima
+ * Add NMI switch check.
+ *
+ * S011 '95.03/14 T.Samezima
+ * Add HalpLRErrorInterrupt()
+ *
+ */
+
+#include "halp.h"
+/* Start S001 */
+#include "bugcodes.h"
+#include "eisa.h"
+#include "stdio.h"
+/* End S001 */
+
+#define _R98DBG_ 1 // S00a
+
+// Start S005
+
+//
+// define buffer name
+//
+
+enum _EIF_BUFFER {
+ PMC0_ERR=0, // 0
+ PMC0_AERR,
+ PMC1_ERR,
+ PMC1_AERR,
+ PMC2_ERR,
+ PMC2_AERR, // 5
+ PMC3_ERR,
+ PMC3_AERR,
+ PMC_EADRH,
+ PMC_EADRL,
+ IOB_IERR, // 10
+ IOB_AMAH,
+ IOB_AMAL,
+ IOB_ANAH,
+ IOB_ANAL,
+ IOB_MPER, // 15
+ IOB_EIFR,
+ SIC_N0_EIF0,
+ SIC_N1_EIF0,
+ SIC_N0_EIF1,
+ SIC_N1_EIF1, // 20
+ SIC_N0_STS1,
+ SIC_N1_STS1,
+ SIC_N0_STS2,
+ SIC_N1_STS2,
+ SIC_N0_DSRG, // 25
+ SIC_N1_DSRG,
+ SIC_N2_EIF0,
+ SIC_N3_EIF0,
+ SIC_N2_EIF1,
+ SIC_N3_EIF1, // 30
+ SIC_N2_STS1,
+ SIC_N3_STS1,
+ SIC_N2_STS2,
+ SIC_N3_STS2,
+ SIC_N2_DSRG, // 35
+ SIC_N3_DSRG,
+ LR_ERRS,
+ LR_PEAR,
+ LR_AEAR,
+ EISA_NMI, // 40
+ MAXMUM_EIF_BUFFER
+};
+
+#if 0 // S00c
+typedef struct _EIFR_REGISTER {
+ ULONG Reserved : 21;
+ ULONG MPDISCN : 1;
+ ULONG IOBERR : 1;
+ ULONG Reserved2 : 1;
+ ULONG EISANMI : 1;
+ ULONG LRERR : 1;
+ ULONG SIC1ERR : 1;
+ ULONG SIC0ERR : 1;
+ ULONG PMC3ERR : 1;
+ ULONG PMC2ERR : 1;
+ ULONG PMC1ERR : 1;
+ ULONG PMC0ERR : 1;
+} EIFR_REGISTER, *PEIFR_REGISTER;
+#endif
+
+// End S005
+
+//
+// define buffer size
+//
+
+#define REG_BUFFER_SIZE MAXMUM_EIF_BUFFER // S005
+
+//
+// buffer
+//
+
+ULONG HalpEifRegisterBuffer[REG_BUFFER_SIZE];
+
+// Start S006
+//
+// Owner flag
+//
+
+volatile ULONG EifOwnFlg=0;
+// End S006
+
+volatile ULONG CpuCount=0; // S00e
+volatile ULONG EccOccurFlag[4]={0,0,0,0}; // S00f
+
+// S010 vvv
+#define NMI_BUFFER_SIZE 32
+
+volatile ULONG HalpNMIFlag=0;
+ULONG HalpNMIBuf[NMI_BUFFER_SIZE*4];
+// S010 ^^^
+
+// S011 vvv
+ULONG HalpLRErrorFlag=0;
+
+BOOLEAN
+HalpLRErrorInterrupt(
+ VOID
+ )
+{
+ //
+ // LR4360 error flag set.
+ //
+ HalpLRErrorFlag=1;
+
+ //
+ // Issue EIF interrupt.
+ //
+ WRITE_REGISTER_ULONG( 0xb9980100, 0x0082f000 );
+
+ return TRUE;
+}
+// S011 ^^^
+
+
+VOID
+HalpHandleEif(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine manage the eif interrupt
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR charBuffer; // S001
+ ULONG buffer;
+ ULONG errsBuffer;
+ UCHAR messageBuffer[REG_BUFFER_SIZE*12+16]; // S006
+ ULONG counter;
+ UCHAR EisaPort;
+ ULONG port;
+
+ ULONG cpuNo; // S006
+ ULONG EifFlg=0; // S006, S007
+ KIRQL oldIrql; // S006
+ ULONG i; // S00f
+
+ // Start S005
+#if defined(_R98DBG_)
+ PEIFR_REGISTER eifrbuf;
+#endif
+ // End S005
+
+ //
+ // Acquire eif interrupt spin lock.
+ //
+
+ KiAcquireSpinLock(&HalpEifInterruptLock);
+
+ // Start S006
+ //
+ // Get CPU Number.
+ //
+
+ cpuNo=(PCR->Prcb)->Number;
+
+ if(EifOwnFlg == 0) {
+// CpuCount=**((PULONG *)(&KeNumberProcessors)); // S00e, S00f
+ EifOwnFlg = 1;
+ EifFlg = 1;
+ }
+
+// CpuCount--; // S00e, S00f
+
+ KiReleaseSpinLock(&HalpEifInterruptLock);
+
+ if(EifFlg == 0) {
+//#ifdef DBG
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKRR.Long,
+ 63-IPR_EIF_BIT_NO ); // S00d
+ KeRaiseIrql(TIMER_LEVEL, &oldIrql);
+ while( EifOwnFlg == 1 );
+ KeLowerIrql(oldIrql);
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long,
+ 63-IPR_EIF_BIT_NO ); // S00d
+//#else
+// while( EifOwnFlg == 1 );
+//#endif
+ EccOccurFlag[cpuNo]=0; // S00f
+ return;
+ }
+
+ // S00c vvv
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+
+ if( (HalpNMIFlag == 0) && (HalpLRErrorFlag == 0) && // S010, S011
+ ((((PEIFR_REGISTER)&buffer)->SIC0ERR == 1) ||
+ (((PEIFR_REGISTER)&buffer)->SIC1ERR == 1)) ){
+ buffer = HalpEccError(buffer);
+ if(buffer == 1){
+// while( CpuCount != 0 ); // S00e
+ // S00f vvv
+ for( i=0; i<4; i++) {
+ EccOccurFlag[i]=1;
+ }
+ EccOccurFlag[cpuNo]=0;
+ // S00f ^^^
+ EifOwnFlg = 0;
+ return;
+ }
+ }
+ // S00c ^^^
+ // S00f vvv
+ else if( (HalpNMIFlag == 0) && (HalpLRErrorFlag == 0) &&
+ ((buffer & 0xff600000) == 0) && (EccOccurFlag[cpuNo] == 1) ){ // S010, S011
+ EccOccurFlag[cpuNo]=0;
+ EifOwnFlg = 0;
+ return;
+ }
+ // S00f ^^^
+
+ // S010 vvv
+ if( HalpNMIFlag == 0 ) {
+ HalDisplayString("\nEIF interrupt status: "); // S005
+#ifdef DBG
+ sprintf( (char *)messageBuffer, "Exe CPU=No.%1d\n", cpuNo ); // S007
+#else
+ sprintf( (char *)messageBuffer, "\n" ); // S007
+#endif
+ HalDisplayString( (char *)messageBuffer );
+ } else {
+ HalDisplayString("\nNMI occur: \n");
+ }
+ // S010 ^^^
+ // End S006
+
+ //
+ // Check LR4360 status.
+ //
+
+ errsBuffer = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS );
+
+ if( (errsBuffer & ERRS_ERROR_BIT) != 0 ) {
+ WRITE_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS,
+ ERRS_ERROR_BIT );
+ }
+
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
+ IOB_DUMMY_READ; // S003
+
+ //
+ // get register value on ERR, AERR, EADRH and EADRL registers of PMC
+ //
+
+ for(counter=0 ; counter<REG_BUFFER_SIZE ; counter++) {
+ HalpEifRegisterBuffer[counter]=0;
+ }
+
+ if( (buffer & SCFR_CPU0_CONNECT) == 0 ) { // S004
+ /* Start S001 */
+ HalpEifRegisterBuffer[PMC0_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 0<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC0_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 0<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001 */
+ }
+
+ if( (buffer & SCFR_CPU1_CONNECT) == 0 ) { // S004
+ /* Start S001,S002 */
+ HalpEifRegisterBuffer[PMC1_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 1<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC1_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 1<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001,S002 */
+ }
+
+ if( (buffer & SCFR_CPU2_CONNECT) == 0 ) { // S004
+ /* Start S001,S002 */
+ HalpEifRegisterBuffer[PMC2_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 2<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC2_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 2<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001,S002 */
+ }
+
+ if( (buffer & SCFR_CPU3_CONNECT) == 0 ) { // S004
+ /* Start S001,S002 */
+ HalpEifRegisterBuffer[PMC3_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 3<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC3_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 3<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001,S002 */
+ }
+
+ /* Start S001 */
+ HalpEifRegisterBuffer[PMC_EADRH] = READ_REGISTER_ULONG( // S005
+ &( PMC_CONTROL2 )->EADRH.Long
+ );
+ HalpEifRegisterBuffer[PMC_EADRL] = READ_REGISTER_ULONG( // S005
+ &( PMC_CONTROL2 )->EADRL.Long
+ );
+ /* End S001 */
+
+ //
+ // get register value on IERR, AMAH, AMAL, ANAH, ANAL,MPER and EIFR
+ // registers of IOB.
+ //
+
+ HalpEifRegisterBuffer[IOB_IERR] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->IERR.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_AMAH] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->AMAH.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_AMAL] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->AMAL.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_ANAH] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->ANAH.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_ANAL] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->ANAL.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_MPER] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->MPER.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_EIFR] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->EIFR.Long,
+ );
+ IOB_DUMMY_READ; // S003
+
+ //
+ // get register value on EIF0, EIF1, STS1, STS2 and DSRG registers of SIC.
+ //
+
+ if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S004
+ /* Start S001 */
+ HalpEifRegisterBuffer[SIC_N0_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO0_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO1_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ /* End S001 */
+ }
+
+ if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S004
+ /* Start S001 */
+ HalpEifRegisterBuffer[SIC_N2_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO2_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO3_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ /* End S001 */
+ }
+
+ //
+ // get register value on ERRS, PEAR and AEAR registers of LR4360.
+ //
+
+ HalpEifRegisterBuffer[LR_ERRS] = errsBuffer; // S005
+ HalpEifRegisterBuffer[LR_PEAR] = READ_REGISTER_ULONG( // S005
+ &( LR_PCI_DEV_REG_CONTROL )->PEAR,
+ );
+ HalpEifRegisterBuffer[LR_AEAR] = READ_REGISTER_ULONG( // S005
+ &( LR_PCI_DEV_REG_CONTROL )->AEAR,
+ );
+
+ //
+ // Display EISA Nmi status.
+ //
+
+ charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus);
+ HalpEifRegisterBuffer[EISA_NMI] = charBuffer << 24; // S001, S005
+
+ charBuffer = READ_REGISTER_UCHAR(
+ &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl
+ );
+ HalpEifRegisterBuffer[EISA_NMI] |= charBuffer << 16; // S001, S005
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ charBuffer = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((charBuffer & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+ charBuffer = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (charBuffer & 0x2) {
+ HalpEifRegisterBuffer[EISA_NMI] |= EisaPort; // S005
+ }
+ }
+ }
+
+#ifdef DBG // R98TEMP
+ KdPrint(("HAL: EIF Interrupt\n"));
+#endif // R98TEMP
+
+ // Start S005
+ for( counter=0 ; counter<REG_BUFFER_SIZE ; counter++) {
+ sprintf( (char *)messageBuffer, "0x%08lX,", HalpEifRegisterBuffer[counter] );
+ HalDisplayString( (char *)messageBuffer );
+#ifdef DBG // R98TEMP
+ KdPrint(( (char *)messageBuffer ));
+#endif // R98TEMP
+ if( (counter % 7) == 6 ) {
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+#ifdef DBG // R98TEMP
+ KdPrint(( (char *)messageBuffer ));
+#endif // R98TEMP
+ }
+ }
+
+#if defined(_R98DBG_)
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+
+ HalpChangePanicFlag( 16, 0x01, 0x10); // S00c
+
+ eifrbuf = (PEIFR_REGISTER)(&(HalpEifRegisterBuffer[IOB_EIFR]));
+
+ if( eifrbuf->PMC0ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC0: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC0_ERR],
+ HalpEifRegisterBuffer[PMC0_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->PMC1ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC1: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC1_ERR],
+ HalpEifRegisterBuffer[PMC1_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->PMC2ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC2: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC2_ERR],
+ HalpEifRegisterBuffer[PMC2_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->PMC3ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC3: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC3_ERR],
+ HalpEifRegisterBuffer[PMC3_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->SIC0ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from SIC SET0\n"
+ " No0 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n"
+ " No1 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n",
+ HalpEifRegisterBuffer[SIC_N0_EIF0],
+ HalpEifRegisterBuffer[SIC_N0_EIF1],
+ HalpEifRegisterBuffer[SIC_N0_DSRG],
+ HalpEifRegisterBuffer[SIC_N0_STS1],
+ HalpEifRegisterBuffer[SIC_N0_STS2],
+ HalpEifRegisterBuffer[SIC_N1_EIF0],
+ HalpEifRegisterBuffer[SIC_N1_EIF1],
+ HalpEifRegisterBuffer[SIC_N1_DSRG],
+ HalpEifRegisterBuffer[SIC_N1_STS1],
+ HalpEifRegisterBuffer[SIC_N1_STS2]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->SIC1ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from SIC SET1\n"
+ " No2 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n"
+ " No3 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n",
+ HalpEifRegisterBuffer[SIC_N2_EIF0],
+ HalpEifRegisterBuffer[SIC_N2_EIF1],
+ HalpEifRegisterBuffer[SIC_N2_DSRG],
+ HalpEifRegisterBuffer[SIC_N2_STS1],
+ HalpEifRegisterBuffer[SIC_N2_STS2],
+ HalpEifRegisterBuffer[SIC_N3_EIF0],
+ HalpEifRegisterBuffer[SIC_N3_EIF1],
+ HalpEifRegisterBuffer[SIC_N3_DSRG],
+ HalpEifRegisterBuffer[SIC_N3_STS1],
+ HalpEifRegisterBuffer[SIC_N3_STS2]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( HalpLRErrorFlag == 1 ){ // S011
+ sprintf( (char *)messageBuffer,
+ "LR4360 Error Acknowledge Interrupt:\n" // S011
+ " ERRS=0x%08lX, PEAR=0x%08lX, AEAR=0x%08lX\n", // S011
+ HalpEifRegisterBuffer[LR_ERRS],
+ HalpEifRegisterBuffer[LR_PEAR],
+ HalpEifRegisterBuffer[LR_AEAR]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( (eifrbuf->IOBERR == 1) || (eifrbuf->MPDISCN == 1) ){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from IOB: IERR=0x%08lX, AMAH=0x%08lX, AMAL=0x%08lX\n"
+ " ANAH=0x%08lX, ANAL=0x%08lX, EIFR=0x%08lX, MPER=0x%08lX\n",
+ HalpEifRegisterBuffer[IOB_IERR],
+ HalpEifRegisterBuffer[IOB_AMAH],
+ HalpEifRegisterBuffer[IOB_AMAL],
+ HalpEifRegisterBuffer[IOB_ANAH],
+ HalpEifRegisterBuffer[IOB_ANAL],
+ HalpEifRegisterBuffer[IOB_EIFR],
+ HalpEifRegisterBuffer[IOB_MPER]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->EISANMI == 1){
+
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from EISA NMI: NmiStatus=0x%02lX\n"
+ " ExtendedNmiResetControl=0x%02lX, Port=%d\n",
+ ((HalpEifRegisterBuffer[EISA_NMI] >> 24) & 0xff),
+ ((HalpEifRegisterBuffer[EISA_NMI] >> 16) & 0xff),
+ (HalpEifRegisterBuffer[EISA_NMI] & 0xff)
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ // S010 vvv
+ if( (HalpNMIFlag & 0x0000008) != 0 ) {
+ sprintf( (char *)messageBuffer,
+ "NMI from MRC\n"
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+ // S010 ^^^
+#endif
+ // End S005
+
+ EifOwnFlg == 0;
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,
+ HalpEifRegisterBuffer[IOB_EIFR],
+ HalpNMIFlag, // S010
+ HalpLRErrorFlag ? HalpEifRegisterBuffer[LR_ERRS] : 0, // S011
+ 0
+ ); // S009
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98esm.c b/private/ntos/nthals/halr98mp/mips/r98esm.c
new file mode 100644
index 000000000..bf98bf092
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98esm.c
@@ -0,0 +1,1026 @@
+#ident "@(#) NEC r98esm.c 1.1 95/02/20 17:21:21"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98esm.c
+
+Abstract:
+
+ This module implements the ESM service routine for R98
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ *
+ * S001 '95.01/13 T.Samezima
+ * Add disable ECC 1bit error for a few second.
+ * Chg ECC 1bit error interrupt clear logic.
+ *
+ * S002 '95.01/14 T.Samezima
+ * Chg Entirely change logic to display String into nvram
+ * Entirely change logic to ECC error log into nvram
+ *
+ * S003 '95.01/15-24 T.Samezima
+ * Add wait from ECC 1bit error disable to enable.
+ * disable ECC 1bit error with SIC set 1 and SIC set 2.
+ * rewrite data on ECC 1bit error.
+ *
+ * S004 '95.01/26 T.Samezima
+ * Add wait to clear of register.
+ *
+ */
+
+#include "halp.h"
+#include "esmnvram.h"
+#include "bugcodes.h"
+#include "stdio.h"
+
+//
+// define offset.
+//
+#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr)
+#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest)
+#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr)
+#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest)
+#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr)
+#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest)
+
+
+#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description)
+#define TIME_STAMP_SIZE 14
+
+//
+// define value
+//
+#define NVRAM_VALID 3
+#define NVRAM_MAGIC 0xff651026
+#define ECC_LOG_VALID_FLG 1
+
+#define SIC_ECC_1BIT_ERROR 1
+#define SIC_ECC_2BIT_ERROR 2
+#define SIC_OTHER_ERROR 0
+
+#define SDCR_SET0_ADDR 0xb9100030
+#define SDCR_SET1_ADDR 0xb9120030
+
+#define STRING_BUFFER_SIZE 512
+
+#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10
+
+//
+// Define global variable. This variable use in display string into nvram.
+//
+ULONG HalpNvramValid=FALSE;
+ULONG CallCountOfInitDisplay=0;
+USHORT ErrBufferLatest;
+USHORT ErrBufferArea;
+USHORT ErrBufferStart;
+USHORT ErrBufferEnd;
+USHORT ErrBufferCurrent;
+ULONG HalpPanicFlg=0;
+UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE];
+ULONG HalpNvramStringBufferCounter=0;
+
+LONG HalpECC1bitDisableFlag=1; // S001
+LONG HalpECC1bitDisableTime=0; // S003
+ULONG HalpECC1bitScfrBuffer=0; // S003
+
+UCHAR KernelPanicMessage[]="*** STOP: 0x"; // S002
+
+//
+// Define macro
+//
+
+#define GET_PADDR(addr,sts2,SicSet) { \
+ (addr) = ( ( ((PSTS2_REGISTER)&(sts2) )->COL0_9 << 4 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW0_9 << 14 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->SIMN << 24 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->COL10 << 25 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW10 << 26 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->ARE << 27 ) \
+ + ( (SicSet) << 30 ) ); \
+}
+
+#define GET_TIME(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKRR.Long, \
+ 63-IPR_EIF_BIT_NO ); \
+ HalQueryRealTimeClock( &timeBuffer ); \
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, \
+ 63-IPR_EIF_BIT_NO ); \
+ sprintf( (Buffer), \
+ "%04d%02d%02d%02d%02d%02d", \
+ timeBuffer.Year, \
+ timeBuffer.Month, \
+ timeBuffer.Day, \
+ timeBuffer.Hour, \
+ timeBuffer.Minute, \
+ timeBuffer.Second \
+ ); \
+}
+
+// S002, S003 vvv
+#define NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long,buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+
+#define DONT_NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long, \
+ buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+// S002, S003 ^^^
+
+
+ULONG
+HalpEccError(
+ IN ULONG EifrRegister
+ )
+
+/*++
+
+Routine Description:
+
+ This routine check ecc error and error log put in NVRAM.
+
+Arguments:
+
+ EifrRegister - EIFR register value in IOB.
+
+Return Value:
+
+ return value is the following error occured.
+ 1: ecc 1bit error.
+ 2: ecc 2bit error.
+ 0: other error.
+
+--*/
+
+{
+ ULONG returnValue;
+ ULONG sicSet;
+ ULONG sicOffset;
+ USHORT infoOffset;
+ USHORT writeOffset;
+ ULONG eif0Buffer;
+ ULONG sts2Buffer;
+ ULONG sdlmBuffer;
+ ULONG buffer; // S001
+ ULONG i; // S002
+ ULONG errAddr; // S002
+ UCHAR dataBuf[36];
+ UCHAR infoBuf[24];
+ UCHAR tempBuf[24];
+
+ HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
+ IOB_DUMMY_READ;
+
+ //
+ // check interrupt from where.
+ //
+
+ if ( ((PEIFR_REGISTER)&EifrRegister)->SIC1ERR == 1){
+ sicSet = 1;
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ if(eif0Buffer & 0x000000c0){
+ sicOffset = SIC_NO2_OFFSET;
+ } else {
+ sicOffset = SIC_NO3_OFFSET;
+ }
+ }else{
+ sicSet = 0;
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ if(eif0Buffer & 0x000000c0){
+ sicOffset = SIC_NO0_OFFSET;
+ } else {
+ sicOffset = SIC_NO1_OFFSET;
+ }
+ }
+
+ //
+ // read diagnosis registers.
+ //
+
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ sts2Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->STS2.Long );
+ SIC_DUMMY_READ;
+ sdlmBuffer = READ_REGISTER_ULONG(
+ &( SIC_DATA_CONTROL_OR( sicOffset ) )->SDLM.Long );
+ SIC_DUMMY_READ;
+
+ //
+ // Check ECC 1bit or 2bit err
+ //
+
+ if( (eif0Buffer & 0x08000000) &&
+ ((eif0Buffer & 0xf0000000) == 0) &&
+ ((EifrRegister & 0xf3600000) == 0) ){
+ returnValue= SIC_ECC_1BIT_ERROR;
+ infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET;
+ } else if (eif0Buffer & 0x00000040){
+ returnValue= SIC_ECC_2BIT_ERROR;
+ infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET;
+ } else {
+ return(SIC_OTHER_ERROR);
+ }
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+
+ // S002 vvv
+ switch(returnValue) {
+
+ case SIC_ECC_2BIT_ERROR:
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ GET_PADDR( (((pECC2_ERR_REC)dataBuf)->err_address), sts2Buffer, sicSet);
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC2_ERR_REC)dataBuf)->syndrome = sdlmBuffer;
+
+ ((pECC2_ERR_REC)dataBuf)->specified_group =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->ARE + sicSet * 4);
+
+ ((pECC2_ERR_REC)dataBuf)->specified_simm =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->SIMN );
+
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC2_ERR_REC),
+ (PVOID)dataBuf);
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+ break;
+
+
+ case SIC_ECC_1BIT_ERROR:
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ DONT_NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+
+ if(sicSet == 0){
+ WRITE_REGISTER_ULONG( SDCR_SET0_ADDR, 0x0 );
+ } else {
+ WRITE_REGISTER_ULONG( SDCR_SET1_ADDR, 0x0 );
+ }
+
+ do {
+ buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ } while ( (buffer & 0x08000000) != 0 );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long,
+ EifrRegister & 0x0c000000 );
+
+ //
+ // Check New error or Old error.
+ //
+
+ GET_PADDR( errAddr, sts2Buffer, sicSet);
+ HalpReadAndWritePhysicalAddr( errAddr ); // S003
+
+ for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) {
+ HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)->size_rec * i
+ +((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr),
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ if ( (errAddr == ((pECC1_ERR_REC)dataBuf)->err_address) &&
+ ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) {
+ break;
+ }
+ }
+
+ if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ break;
+ }
+
+ //
+ // wait 20 us.
+ //
+
+ KeStallExecutionProcessor(20);
+
+ //
+ // Enable ECC 1bit error.
+ //
+
+ NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+
+ //
+ // Check ECC 1bit error.
+ //
+
+ HalpReadPhysicalAddr( errAddr );
+
+ buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+
+ if( (buffer & 0x08000000) == 0 ) {
+ break;
+ }
+
+ //
+ // ECC 1bit error occur again.
+ //
+
+ ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC1_ERR_REC)dataBuf)->err_address = errAddr;
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC1_ERR_REC)dataBuf)->syndrome = sdlmBuffer;
+
+ ((pECC1_ERR_REC)dataBuf)->specified_group =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->ARE + sicSet * 4);
+
+ ((pECC1_ERR_REC)dataBuf)->specified_simm =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->SIMN );
+
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+
+ break;
+ }
+
+ if(returnValue == SIC_ECC_1BIT_ERROR) {
+
+ DONT_NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+
+ if(sicSet == 0){
+ WRITE_REGISTER_ULONG( SDCR_SET0_ADDR, 0x0 );
+ } else {
+ WRITE_REGISTER_ULONG( SDCR_SET1_ADDR, 0x0 );
+ }
+
+ do {
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ } while ( (eif0Buffer & 0x08000000) != 0 );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long,
+ EifrRegister & 0x0c000000 );
+ // S004 vvv
+ do {
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+ IOB_DUMMY_READ;
+ } while ( ((buffer & 0x0c000000) != 0) && ((eif0Buffer & 0xf8000000) == 0) );
+ // S004 ^^^
+
+ if(HalpECC1bitDisableFlag > 0) {
+ HalpECC1bitDisableFlag--;
+ if(HalpECC1bitDisableFlag > 0) {
+ NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+ }
+ // S003 vvv
+ else {
+ HalpECC1bitDisableTime = ECC_1BIT_ERROR_DISABLE_TIME;
+ HalpECC1bitDisableFlag = 0;
+ }
+ // S003 ^^^
+ }
+ }
+ // S002 ^^^
+
+ return(returnValue);
+}
+
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is initialize variable of use when write display data in
+ HalDisplayString into NVRAM.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SYSTEM_ERR_AREA_INFO infoBuf;
+ UCHAR recordFlg;
+ UCHAR buf[8];
+ UCHAR buf2[8];
+
+ CallCountOfInitDisplay++;
+ if(CallCountOfInitDisplay == 1){
+
+ //
+ // Check NVRAM status
+ //
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 );
+
+ if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){
+ HalpNvramValid=FALSE;
+ return;
+ }
+
+ HalpNvramValid=TRUE;
+
+ //
+ // Get log area infomation.
+ //
+
+ HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ &infoBuf);
+
+ ErrBufferLatest = infoBuf.offset_latest;
+
+ HalNvramRead( infoBuf.offset_latest, 1, &recordFlg);
+
+ //
+ // Check current record flg.
+ //
+
+ if( (recordFlg & 0x01) == 1 ) {
+ infoBuf.offset_latest += infoBuf.size_rec;
+ if( infoBuf.offset_latest >=
+ infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){
+ infoBuf.offset_latest = infoBuf.offset_systemerr;
+ }
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &infoBuf.offset_latest);
+ }
+
+ //
+ // initialize variable. this value use log area access.
+ //
+
+ ErrBufferArea = infoBuf.offset_latest;
+ ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE;
+ ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1;
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // status flg set.
+ //
+
+ HalpPanicFlg = 0;
+
+ recordFlg = 0x11;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ //
+ // buffer initialize.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else {
+
+ //
+ // start Panic log.
+ //
+
+ HalpChangePanicFlag( 1, 1, 0);
+ }
+}
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ )
+{
+ UCHAR buf[24];
+
+ //
+ // Set time stamp on initialize display.
+ //
+
+ if(HalpNvramValid == TRUE) {
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+ }
+}
+
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ )
+{
+ UCHAR recordFlg;
+
+ if(HalpNvramValid == TRUE) {
+ recordFlg = 0;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest );
+ }
+}
+
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ )
+{
+ UCHAR recordFlg;
+ UCHAR buf[24];
+
+ if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) {
+ return;
+ }
+
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &ErrBufferArea);
+
+ //
+ // initialize currernt buffer address
+ //
+
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // set panic flag
+ //
+
+ HalNvramRead( ErrBufferArea, 1, &recordFlg );
+ recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+
+ //
+ // set new flag of panic level
+ //
+
+ HalpPanicFlg = NewPanicFlg;
+
+ //
+ // initialize log buffer.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+}
+
+
+// S002 vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ )
+{
+ if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) {
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character;
+ }
+}
+
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ )
+{
+ ULONG i;
+
+ //
+ // Initialize buffer
+ //
+
+ for(i=0; i<STRING_BUFFER_SIZE; i++) {
+ HalpNvramStringBuffer[i] = 0;
+ }
+
+ HalpNvramStringBufferCounter=0;
+
+ //
+ // set string position
+ //
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Column;
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Row;
+}
+
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // if data size is zero, when return
+ //
+
+ if( HalpNvramStringBufferCounter <= 2 ) {
+ return;
+ }
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]='\0';
+
+ //
+ // check panic message
+ //
+
+ for( count=0; ; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != HalpNvramStringBuffer[count+2] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for( count=2; ; count++) {
+ if( HalpNvramStringBuffer[count] == '\0' ){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 2 < ErrBufferEnd ) {
+ HalNvramWrite( ErrBufferCurrent, count, HalpNvramStringBuffer );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( (count + 2 > ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count );
+ }
+ ErrBufferCurrent++;
+ if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+
+#if 0
+VOID
+HalpStringIntoNvram(
+ IN ULONG Column,
+ IN ULONG Row,
+ IN PUCHAR String
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // check panic message
+ //
+
+ for(count=0; 1; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != String[count] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for(count=0;;count++) {
+ if(String[count]=='\0'){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 4 < ErrBufferEnd ) {
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+ HalNvramWrite( ErrBufferCurrent, count, String );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( count + 4 > ErrBufferEnd - ErrBufferStart ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, String+count );
+ }
+ ErrBufferCurrent++;
+ if(String[count]=='\0') {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+#endif
+// S002 ^^^
+
+
+//
+// test code
+//
+
+int
+printNvramData(void)
+{
+ UCHAR buf[256];
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag), 1, buf );
+ DbgPrint("Nvram Flag: 0x%02lx\n", buf[0]);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->when_formatted), 14, buf );
+ buf[14]=0;
+ DbgPrint("Nvram TimeStamp: %s\n", buf);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err),
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC1: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC1: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC1: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC1: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err),
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC2: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC2: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC2: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC2: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->system_err),
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram SYSTEM: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram SYSTEM: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram SYSTEM: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram SYSTEM: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ return(0);
+}
+
+
+int
+TmpInitNvram(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0xff;
+ for(i=0; i<8*1024; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 1, (PUCHAR)&i);
+
+ //
+ // Make 1bit err log info
+ //
+
+ ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768;
+ ((pECC1_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC1_ERR_AREA_INFO)buf)->num_rec=16;
+ ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768;
+
+ ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0;
+
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768; i<768+25*16; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make 2bit err log info
+ //
+
+ ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400;
+ ((pECC2_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC2_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400;
+
+ ((pECC2_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768+400; i<768+400+25*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make system err log info
+ //
+
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280;
+
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=1280; i<1280+512*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ return(0);
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98hal.h b/private/ntos/nthals/halr98mp/mips/r98hal.h
new file mode 100644
index 000000000..63bfa51df
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98hal.h
@@ -0,0 +1,132 @@
+#ident "@(#) NEC r98hal.h 1.4 94/09/22 16:56:52"
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r98hal.h
+
+
+Abstract:
+
+ This module is the header that dma structure and etc.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 7/12 T.Samezima
+ *
+ * Chg define chenge
+ *
+ * K001 94/09/22 N.Kugimoto
+ * Chg DMA logcal addres sapce 4M--->16M
+ */
+
+#ifndef _R98HAL_
+#define _R98HAL_
+
+// Start S001
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+// End S001
+
+//
+// define structure of adapter object
+//
+typedef struct _ADAPTER_OBJECT { // (= ntos/hal/i386/ixisa.h)
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters; // new add
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+} ADAPTER_OBJECT; // del duo's SingleMaskPort
+
+//
+// Define map register translation entry structure For Internal.
+//
+
+typedef struct _INTERNAL_TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} INTERNAL_TRANSLATION_ENTRY, *PINTERNAL_TRANSLATION_ENTRY;
+
+// Start S001
+typedef struct _TRANSLATION_ENTRY {
+ ULONG PageFrame;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+// End S001
+
+//
+// define dma
+//
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000 // 64 page
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE MAXIMUM_MAP_BUFFER_SIZE
+#define INITIAL_MAP_BUFFER_LARGE_SIZE MAXIMUM_MAP_BUFFER_SIZE
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000 // 16 page
+#define MAXIMUM_ISA_MAP_REGISTER (MAXIMUM_MAP_BUFFER_SIZE/(PAGE_SIZE*2))
+ // 32 page
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x60000000 // max : 16MB // S001
+
+#define COPY_BUFFER 0xFFFFFFFF
+#define NO_SCATTER_GATHER 0x00000001
+#define DMA_TRANSLATION_LIMIT 0x4000 // TLB alloc size K001
+
+//
+// Define pointer to DMA control registers.
+//
+// Start S001
+#define DMA_CONTROL(x) ((volatile PDMA_CHANNEL)((ULONG)(KSEG1_BASE | LR_CHANNEL_BASE |(x))))
+// End S001
+
+//
+// Define MRC register structure.
+//
+typedef struct _MRC_REGISTERS { // offset(H)
+ UCHAR Reserved1[48]; // 0-2f
+ UCHAR SwReset; // 30
+ UCHAR Reserved2[19]; // 31-43
+ UCHAR LedData0; // 44
+ UCHAR LedData1; // 45
+ UCHAR LedData2; // 46
+ UCHAR LedData3; // 47
+} MRC_REGISTERS, *PMRC_REGISTERS;
+
+//
+// Define pointer to MRC registers.
+//
+#define MRC_CONTROL ((volatile PMRC_REGISTERS)(KSEG1_BASE | MRC_PHYSICAL_BASE))
+
+#endif _R98HAL_
diff --git a/private/ntos/nthals/halr98mp/mips/r98hwsup.c b/private/ntos/nthals/halr98mp/mips/r98hwsup.c
new file mode 100644
index 000000000..4cee934f9
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98hwsup.c
@@ -0,0 +1,4771 @@
+#ident "@(#) NEC r98hwsup.c 1.41 95/06/19 11:31:38"
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ r98hwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * HalpCreateDmaStructures()
+ *
+ * L001 94.03/24 T.Samezima
+ *
+ * Change Interrupt service routine
+ *
+ * Add Call initialize of PCI interrupt
+ * Interrupt enable
+ *
+ * K001 '94.5/30 (Mon) N.Kugimoto
+ * -1 Add HalAllocateAdapterChannel():
+ * -2 Add HalAllocateCommonBuffer():
+ * -3 Non HalFlushCommonBuffer()
+ * -4 Add HalFreeCommonBuffer(): For Internal Device
+ * -5 Chg HalGetAdapter(): New!!
+ * -6 Mix HalpAllocateAdapter(): mix halfxs,halx86
+ * -7 Add IoFreeMapRegisters(): For Internal Device
+ * -8 Add IoFreeAdapterChannel(): For Internal Device
+ * -9 FRM HalpAllocateMapRegisters() From halx86
+ * -A Mix IoMapTransfer() mix halfxs,halx86
+ * -B Mix IoFlushAdapterBuffers() mix halfxs,halx86
+ * -C FRM HalpAllocationRoutine () From halfxs
+ * -D FRM HalReadDmaCounter() From halfxs
+ * -E Del HalpDmaInterrupt() allways retrun 1
+ * -F FRM HalpGrowMapBuffers() halx86
+ * -G FRM HalpCopyBufferMap() from halx86 and Argument chg.
+ *
+ * K002 Add MasterAdapterObjectForInternal
+ * K003 Chg HalpInternalAdapters[5]: LR4360 DMA have 5 channel
+ * K004 Add HalpDmaInterrupt()
+ * K005 fix spell miss
+ * K006 FRM global value define!! From halx86
+ * K007 Chg if def chg
+ * K008 94/5/31 N.Kugimoto
+ * Chg HalTranslateBusAddress()
+ * N.B. Pci trans addr is per slot ??.
+ * K009 94/5/31 N.Kugimoto
+ * BUG AddressSpace!!
+ * K00A 94/6/2 (Thu) N.Kugimoto
+ * Chg HalAllocateCrashDumpRegisters()
+ * N.B. check is OK??
+ *
+ * S002 94.03/24 T.Samezima
+ *
+ * Add HalpNmiHandler()
+ * HalpRegisterNmi() ???
+ *
+ * K00B 94/6/3 (Fri) N.Kugimoto
+ * Del
+ * K00C 94/6/6 (Mon) N.Kugimoto
+ * Chg K007 enable
+ * K00D 94/6/9 (Thu) N.kugimoto
+ * Chg Compile err del.
+ * K00E 94/7/1 (Fri) N.Kugimoto
+ * -1 Chg IoFlushAdapterBuffers()
+ * -2 Add IoFlushAdapterBuffers() Reserved Bit set 0.
+ * -3 Del HalAllocateCrashDumpRegisters() limit check del.
+ * -4 Bug IoMapTransfer() transferLength is Bad!!.
+ * -5 Bug MasterAdapterObject ==> AdapterObject.
+ * -6 Bug at this line. LR4360 dma
+ * -7 Bug enable #if 0 and eisadma is del.
+ * -8 Del This code is never use. so del.
+ * K00F 94/7/6 (Wed) N.Kugimoto
+ * Mov HalGetAdapter() CnDC->FiFoF Flush LR4360 DMA FiFo Move IoMapTransfer()
+ * Per DMA Translation.
+ * K010 94/7/8 (Fri) N.Kugimoto
+ * -1 Chg enable check logic.
+ * -2 Add comment add. LR4360 DMA Byte Count Register 64M. Bit25-Bit0.
+ * -3 Add Comment add. This value use only as flag. Not Port Addr.
+ * K011 94/8/22 (Mon) N.Kugimoto
+ * -1 Bug if {} else not match!!. Debug On SNES.
+ * -2 Bug HalpDmaInterrupt() enable Because First run rather than
+ * IoFlushAdapterBuffers().Debug On SNES.
+ * K012 94/9/22 N.Kugimoto
+ * -1 Bug MasterAdapterObject->NumberOfMapRegiser is Non Initialize.
+ * K013 94/9/22 N.Kugimoto
+ * -1 Chg Externl logical addr first allocation 1M align.
+ * second allocaton is start offset 0.
+ * -2 Bug MasterAdapter can't use this line.
+ * K014 94/9/22 N.Kugimoto
+ * compile err
+ * K015 94/09/26 N.Kugimoto
+ * Mov move code to r98busdat.c
+ * K016 94/09/29 N.Kugimoto
+ * -1 Chg allocate memory is less than 512M. To see from KSEG1_BASE.
+ * -2 Add cast ULONG .
+ * K017 94/10/05 N.Kugimoto
+ * -1 Bug must be () .
+ * K018 94/10/07 N.Kugimoto
+ * -1 Bug align 1m Logic Bug.
+ * K019 94/10/06 N.Kugimoto
+ * -1 Bug LR4360 PTBARn Register must be PFN. Not KSEG1_BASE value.
+ * K020 94/10/11 N.Kugimoto
+ * -1 Fix Version Up At 807 Base.
+ * K021 94/10/11 N.Kugimoto
+ * -1 Add page table clear
+ * -2 Add tlb flush
+ * K022 94/10/11 N.Kugimoto
+ * Add NMI Logic
+ * K023 94/10/12 N.Kugimoto
+ * K024 94/10/13 N.Kugimoto
+ * Chg Compile err
+ * S025 94/10/14 T.Samezima
+ * Del Move logic on connect int1 interrupt to allstart.c
+ * K025 94/10/17 N.Kugimoto
+ * Bug K020-1 miss
+ * K026 94/10/18 N.Kugimoto
+ * -1 Bug LR4360 Page Table is KSEG0_BASE
+ * -2 Chg Page table Entry Invalidate.
+ * -3 Chg tlb flush timing chg
+ * K027 94/11/11 N.Kugimoto
+ * -1 Chg cache enable
+ * -2 Chg Som Logical addr range not Used.
+ *
+ * K028 95/2/22 N.Kugimoto
+ * Chg PCEB Prefetch sycle caused LR4360 page fault
+ * K029 95/2/22 N.Kugimoto
+ * Add LR4360 TLB RoundUp.
+ * K030 95/2/22 N.Kugimoto
+ * Chg LR4360 TLB No Flush. Because At DMA ....
+ * K031 95/2/22 N.Kugimoto
+ * Add LR4360 I/O Read Cache Flush
+ * K032 95/3/13 N.Kugimoto
+ * Chg #if #else fix Miss.
+ *
+ * S003 95/3/14 T.Samezima
+ * Add Add HalpLRErrorInterrupt() at dispatch table.
+ * K034 95/04/12 N.Kugimoto
+ * Del NOTLBFLUSH
+ * Add DUMMYDMA This is Work around.
+ * LR4360 can't TLB flush while dma. So ESC DMAC channel 2 use
+ * Dummy dma 1byte. It't cause TLB flush .
+ * S004 95/5/15 T.Samezima
+ * Chg vaild page table on LR4360
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - resolve compile error.
+ * -------------------------------------------------------------------
+ * K035 95/6/16 N.Kugimoto
+ * Up version Up 3.51
+ */
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+#include "jazznvr.h" //K00D
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCreateDmaStructures)
+#pragma alloc_text(PAGE,HalpGrowMapBuffers) //K035
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+//
+// K002
+//
+PADAPTER_OBJECT MasterAdapterObjectForInternal;
+
+
+// K006
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+
+// PCEB Prefetch sycle cause LR4360 Page Fault
+// So reserved DummyPhysicalPage
+ULONG HalpNec0DummyPhysicalBase; // K028
+ULONG HalpNec1DummyPhysicalBase; // K028
+
+ULONG HalpLogicalAddrArbPoint=0;
+KSPIN_LOCK HalpIoMapSpinLock;
+
+// K004
+// The following function is called when a DMA channel interrupt occurs.
+//
+
+BOOLEAN
+HalpDmaInterrupt(
+ VOID //K00D
+ );
+
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+// K003
+// N.B: Internal Device without Scatter/Gather not use this array.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[5];
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+// A002
+PVOID
+RtlFillMemoryUlong (
+ IN PVOID Destination,
+ IN ULONG Length,
+ IN ULONG Pattern
+ );
+// A002
+VOID
+HalpDummyTlbFlush(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ /* Start L001 */
+ ULONG buffer;
+
+ //
+ // Initialize the interrupt dispatcher for I/O interrupts.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ PCR->InterruptRoutine[INT2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt2Dispatch;
+// PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch; // S025
+
+ PCR->InterruptRoutine[INT0_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt0Dispatch;
+
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+
+ PCR->InterruptRoutine[DMA_VECTOR] = (PKINTERRUPT_ROUTINE) HalpDmaInterrupt;
+
+ // S003
+ PCR->InterruptRoutine[LR_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpLRErrorInterrupt;
+
+ //
+ //
+ //
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ HalpBuiltinInterruptEnable |=
+ (iREN_ENABLE_DMA_INTERRUPT | iREN_ENABLE_LR_ERR_INTERRUPT ); // S003
+
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+#if 0 // Start S025
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ HalpCreateEisaStructures();
+
+ //
+ // Initialize PCI bus interrupts.
+ //
+
+ return HalpCreatePciStructures ();
+#else
+ return TRUE;
+#endif // End S025
+ /* End L001 */
+}
+
+// K001:
+//
+//
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG srachPoint;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ // dicide MasterAdapter whitch Intrenal Scatter/gathero or PCI,EISA,ISA
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )){
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ //
+ //
+ //
+ if (NumberOfMapRegisters != 0 && AdapterObject->MasterAdapter != NULL) {
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ //K011-1
+ //
+ // At Internal check adapterobject itself.
+ //
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ }else{
+ //
+ // At PCI,EISA,ISA check with Masteradapter
+ //
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ } //K011-1
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ if(MasterAdapter == MasterAdapterObject){
+ srachPoint = HalpLogicalAddrArbPoint;
+ HalpLogicalAddrArbPoint = (HalpLogicalAddrArbPoint+256) %
+ (DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY));
+ } else {
+ srachPoint = 0;
+ }
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ MasterAdapter ==
+ MasterAdapterObject ? NumberOfMapRegisters+1 : NumberOfMapRegisters, //K028
+ srachPoint
+
+ );
+
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase
+ + MapRegisterNumber);
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported on Internal Device.
+ // ~~~~~~~
+ //
+
+ AdapterObject->MapRegisterBase =
+ (PVOID)((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }else{
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase
+ + MapRegisterNumber ); //add1 non
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ }else {
+ AdapterObject->MapRegisterBase = NULL;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject)
+ IoFreeAdapterChannel( AdapterObject );
+
+ }
+ }
+ return(STATUS_SUCCESS);
+}
+
+// K001-2
+//
+//
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ CacheEnabled =TRUE; //K027-1
+ // Is it Internal Device ?.
+ //
+
+
+ if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal ||
+ (AdapterObject->MasterAdapter==NULL ) // K00B
+ ){
+ //
+ // Internal Device Not use LR4360 TLB.
+ // LowPart is Any.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS-1;
+ physicalAddress.HighPart = 0;
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return(virtualAddress);
+ }
+
+ //
+ // PCI,EISA,ISA Device use LR4360 TLB.
+ //
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+ if (CacheEnabled != FALSE) { //K020-1
+
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+ if (virtualAddress == NULL) {
+
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) { //K020-1
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+ if (CacheEnabled != FALSE) { //K020-1
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+ // mapRegisterBase was set up at HalAllocateAdapterChannel()-->ExecutionRoutine()-->
+ // HalpAllocationRoutine() (value same MapRegisterBase)
+ //
+ //
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ //DbgPrint("\n Common Logical = 0x %x \n",*LogicalAddress);
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled //K020-1
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+// K00A
+//
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters //K020-1
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+//K020-1 ULONG NumberOfMapRegisters;
+ ULONG MapRegisterNumber;
+#if !defined(_R98_)
+ ULONG Hint;
+#endif
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+#if defined(_R98_)
+ // MasterAdapter==NULL This is Internal Device with Scatter/Gather.
+ // So Nothing to Do. Never Use Mapregisters for contigus memory.
+ // N.B. MasterAdapterObject[ForInternal] does not come here!!.
+ // So No check !!.
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ return AdapterObject->MapRegisterBase;
+#else
+ MasterAdapter = AdapterObject;
+#endif
+
+
+ }
+
+ //
+ // Set the number of map registers required.
+ //
+
+//K020-1 *NumberOfMapRegisters = 16;
+
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+#if 1 // K010-1
+ // K00E-3
+ //
+ if(MasterAdapter == MasterAdapterObjectForInternal){
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { //K020-1
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+ }else{
+ // PCI,EISA,ISA device's limit is MasterAdapter.
+ //
+ if (*NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { //K020-1
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ }
+#endif
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+#if !defined(_R98_)
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+#endif
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ MasterAdapter == MasterAdapterObject ? *NumberOfMapRegisters+1 : *NumberOfMapRegisters, //K028
+#if defined(_R98_)
+ 0
+#else
+ Hint
+#endif
+ );
+
+#if !defined(_R98_)
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters //K020-1
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+#endif
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+#if defined(_R98_)
+ 0, // 0M was reserved
+#else
+ Hint,
+#endif // K00D
+ *NumberOfMapRegisters+1
+ );
+#if defined(_R98_)
+ MapRegisterNumber = 0x0;
+#else
+ MapRegisterNumber = Hint;
+#endif
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+#if defined(_R98_)
+ if(MasterAdapter == MasterAdapterObjectForInternal){
+ AdapterObject->MapRegisterBase = ((PINTERNAL_TRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ //
+ // Set the no scatter/gather flag .
+ // in there R98 Internal Device is Not always Scatter/Gather supported.
+ //
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }else
+#endif
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+
+
+// K001-3
+//
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( VirtualAddress );
+
+ return(TRUE);
+
+}
+
+// K001-4
+//
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+ CacheEnabled = TRUE; //K027-1
+
+ if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal||
+ (AdapterObject->MasterAdapter==NULL ) // K00B
+ ){
+ //
+ // Internal Device
+ //
+ MmFreeContiguousMemory (VirtualAddress);
+ }else{
+
+ //
+ // PCI,EISA,ISA.
+ //
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ //
+ // For PCI,EISA,ISA Logical address started at PCI_LOGICAL_START_ADDRESS
+ // See. IoMapTransfer!!.
+ //
+ mapRegisterNumber = (LogicalAddress.LowPart - PCI_LOGICAL_START_ADDRESS) >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) { //K020-1
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+
+ }
+
+ return;
+}
+
+// K001-5
+// As PCI,EISA,ISA Device is used TLB of LR4360.
+// Scatter/Gather is supported By Hal.
+//
+// Internal Device Never use TLB of LR4360.
+// So Device without Scatter/Gather is use continuguas memory.
+//
+// Internal Device at Bbus Device is used LR4360 DMA.
+// LR4360's DMA have Scatter/Gather .But Not use this version hal.
+// So use continuguas memory.
+//
+//
+//
+//
+// Source Base 612 halfxs/mips/jxhwsup.c,halx86/i386/ixisasup.c
+//
+//
+//
+//
+//
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: Internal, Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ ULONG maximumLength;
+ ULONG numberOfMapRegisters;
+ ULONG value; //K00D
+ //
+ // Make sure this is the correct version.
+ //
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) //K020-1,K025
+ return(NULL);
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+#if 0
+ //
+ // 612 halfx code not use. Because Number of R98 PCI,EISA device is 8 and
+ // Limit By MasterAdapterObject->MapRegisterPerChannel / 8
+ //
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) {
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+ }
+#endif
+
+ //
+ // Get AdapterObject
+ // At 1 st call HalpAllocateAdapter() Allocateted MasterAdapterObject or
+ // MasterAdapterObjectForInternal.
+
+ switch(DeviceDescription->InterfaceType){
+ case Internal:
+ //
+ // Return the adapter pointer for internal adapters.
+ // such as SCSI,SONIC,Floppy LR4360
+ // K00D
+
+ if(DeviceDescription->Master){ // Bus Master Device
+ if(DeviceDescription->ScatterGather){ // Device is Scatter/Gather support!!
+ numberOfMapRegisters=0; // then no use Mapregister.
+ }else{
+ numberOfMapRegisters=1; // else use 1 Mapregister.
+ }
+
+#if defined(NONARB)
+ if (((HalpInternalAdapters[3] == NULL) && DeviceDescription->ScatterGather) ||
+ ( (HalpInternalAdapters[4] == NULL) && (DeviceDescription->ScatterGather==0)) ) {
+
+#endif
+
+ adapterObject=
+ HalpAllocateAdapter(
+ numberOfMapRegisters,
+ NULL,
+ (PVOID)-1 // K00D
+ );
+#if defined(NONARB)
+ if(DeviceDescription->ScatterGather ){
+ HalpInternalAdapters[3] = adapterObject; //SCSI0,SCSI1
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ return(adapterObject); // K005
+
+
+ }else{
+ HalpInternalAdapters[4] = adapterObject; //SONIC
+
+ }
+ }else{
+ if(DeviceDescription->ScatterGather){
+ return(HalpInternalAdapters[3]);
+ }else{
+ adapterObject=HalpInternalAdapters[4];
+ }
+
+ }
+
+#endif
+
+ // K00D K00E-6
+ }else if (HalpInternalAdapters[DeviceDescription->DmaChannel] != NULL ) {
+ //
+ // If necessary allocate an adapter; otherwise,
+ // just return the adapter for the requested channel.
+ //
+ // LR4360 DMA channel 1 is floppy.
+ //
+ // K00D
+ adapterObject = HalpInternalAdapters[DeviceDescription->DmaChannel];
+ //
+ // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K
+ //
+ *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters;
+
+
+ }else{
+ //
+ // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K
+ //
+
+ *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters;
+
+ adapterObject=
+ HalpAllocateAdapter(
+ 1,
+ // KSEG1_BASE K00D
+ // K010-3 This value use only as flag.
+ &(DMA_CONTROL ( DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))->CnDC, // K00D
+ (PVOID)-1 // K00D
+ );
+
+ //
+ // Driver of use LR4360 DMA
+ // HalpInternalAdapters[]
+ //
+ HalpInternalAdapters[DeviceDescription->DmaChannel] = adapterObject;
+
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ }
+#if !defined(NONARB)
+ //
+ // Bus Master of Internal Device with Scatter/gather then Nothing to Do.
+ // K00D
+ if(DeviceDescription->Master && DeviceDescription->ScatterGather){
+ //
+ // No Limit Because MapRegisters were not used.
+ //
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ return(adapterObject); // K005
+
+ }
+#endif
+ //
+ // new request > primiry request
+ //
+ if (*NumberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ }
+ // K00D
+ if(DeviceDescription->Master){
+ //
+ // Internal device Master without Scatter/Gather.
+ //
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObjectForInternal->CommittedMapRegisters +=
+ (*NumberOfMapRegisters) * 2;
+
+ }else{
+ //
+ // Internal device with LR4360 DMA. etc floppy
+ //
+
+ MasterAdapterObjectForInternal->CommittedMapRegisters +=
+ (*NumberOfMapRegisters);
+ }
+ //
+ // See MasterAdapterObjectForInternal and
+ // Grow--!!. && Link To MapRegister.
+ //
+ if (MasterAdapterObjectForInternal->CommittedMapRegisters >
+ MasterAdapterObjectForInternal->NumberOfMapRegisters &&
+ MasterAdapterObjectForInternal->CommittedMapRegisters -
+ MasterAdapterObjectForInternal->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER)
+ {
+ //
+ // increment INCREMENT_MAP_BUFFER_SIZE=64K
+ // Number of Mapregister is 64K*4 /4K
+ //
+ HalpGrowMapBuffers(
+ MasterAdapterObjectForInternal,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+ //
+ // check LR4360 DMA Channel
+ // K00D
+ if(!DeviceDescription->Master){
+ adapterObject->ChannelNumber =(UCHAR)DeviceDescription->DmaChannel; //K00D
+ //
+ // LR4360 DMA have Scatter/Gather But not support this version.
+ // Set Up DMA default value.
+ //
+ // 1.DMA mode :Normal mode
+ //
+ // K00D ULONG value;
+
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL(
+ (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))
+ )->CnDF
+ );
+
+ ((PLR_DMA_CONFIG)&value)->Reserved1=0;
+ ((PLR_DMA_CONFIG)&value)->Reserved2=0;
+
+ ((PLR_DMA_CONFIG)&value)->TMODE=LR_DMA_MODE_NORMAL;
+ ((PLR_DMA_CONFIG)&value)->iNEDi=1; //K00D
+ ((PLR_DMA_CONFIG)&value)->iNEDE=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))
+ )->CnDF,
+ value
+ );
+
+
+ // K00F Under Code Move IoMapTransfer()
+
+ }
+ return(adapterObject); // K005 K00D
+
+ case Isa:
+ case Eisa:
+ //
+ // Create an adapter object For Pci Device
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+ //DbgPrint("\nEISA: = 0x%x\n",adapterObject);
+
+ break;
+
+ case PCIBus:
+ //
+ // Create an adapter object For Pci Device.
+ //
+
+ adapterObject = HalpAllocateAdapter( 0,NULL,NULL );
+ break;
+
+ default:
+ // Another Bus Not Suport !!
+ return(NULL);
+ }
+#if defined(DUMMYDMA) // K034 vvv
+ // Max is 1M-2: 0xffe000
+ //
+ //
+ if (*NumberOfMapRegisters > 0x100 -2)
+ *NumberOfMapRegisters = 0x100-2;
+
+#else
+ //
+ // PCI,EISA,ISA Device use LR4360 TLB.(PCI<-->ASOBus)
+ // Max Limit Of MapRegister Per Channel For PCI,EISA,ISA Device Set beyond MasterRegisterPerChannel
+ //
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 8)
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 8;
+#endif // K034 ^^^
+ // Check By HalAllocateAdapterChannel for MasterAdapter.
+ // adapterObject->NeedsMapRegisters = TRUE;
+ //
+ return(adapterObject);
+}
+
+#if 0 //K015
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ //
+ // R98 HighPart never carry!!
+ //
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ return(TRUE);
+ }
+
+#if defined(_R98_) // K008
+
+ switch(InterfaceType){
+
+ case PCIBus:
+ if(*AddressSpace){ // I/O
+ // N.B. Pci trans addr is per slot ??.
+ // So How get slot number!!.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart+PCI_CONTROL_SLOT1_PHYSICAL_BASE;
+
+ }else{ // Memory
+ TranslatedAddress->LowPart = BusAddress.LowPart+PCI_MEMORY_PHYSICAL_BASE;
+
+ }
+ break;
+ case Eisa:
+ case Isa:
+ if(*AddressSpace){ // I/O
+ TranslatedAddress->LowPart = BusAddress.LowPart+EISA_CONTROL_PHYSICAL_BASE;
+
+ }else{ // Memory
+ TranslatedAddress->LowPart = BusAddress.LowPart+EISA_MEMORY_PHYSICAL_BASE;
+
+ }
+ break;
+
+ default: // UnKnow K00D
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ *AddressSpace = 0; // K009
+ return(TRUE);
+
+#else // _R98_
+ if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != Pci) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // There is only one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+
+#if !defined(_DUO_)
+
+ if (DMA_CONTROL->RevisionLevel.Long < 2) {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ } else {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+ }
+#else
+
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+#endif
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+
+#endif // _R98_
+}
+#endif //K015
+
+
+// K00-6
+// MapRegistersPerChannel,AdapterBaseVa,MapRegisterBase
+//--------------------+-----------------------+-------------+---------------+
+// Internal with S/G 0 0 -1
+// Internal no S/G 1 0 -1
+// Internal DMA 1 XX -1
+// Internal MasterAdp 1 -1 -1
+// EISA 0 XX 0
+// PCI 0 0 0
+// MasterAdp 0 -1 -1
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - If (PVOID) -1 then Not MasterAdapter allocate.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+ ULONG i; //K021-2
+ //
+ // Internal without Scatter/Gather or LR4360 DMA
+ // then allocate MasterAdapterObjectForInternal
+ //
+
+ if (MasterAdapterObjectForInternal == NULL && AdapterBaseVa !=(PVOID)-1
+ && MapRegistersPerChannel
+ ){
+
+ MasterAdapterObjectForInternal
+ = HalpAllocateAdapter(
+ 1,
+ (PVOID) -1,
+ (PVOID) -1
+ );
+
+ //
+ // If we could not allocate the master adapter For Internal then give up.
+ //
+
+ if (MasterAdapterObjectForInternal == NULL)
+ return(NULL);
+
+ }else if (MasterAdapterObject == NULL && MapRegisterBase !=(PVOID)-1) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ 0,
+ (PVOID)-1,
+ (PVOID)-1
+ );
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL)
+ return(NULL);
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+
+ if (AdapterBaseVa == (PVOID)-1 && MapRegistersPerChannel) {
+ //
+ // MasterAdapterForInternal
+ //
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ }else if(AdapterBaseVa == (PVOID)-1 && MapRegistersPerChannel==0) {
+ //
+ // MasterAdapter
+ //
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else
+ //
+ // Not Master Adapter.(Have not Bit Map)
+ //
+ Size = sizeof( ADAPTER_OBJECT );
+
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject(
+ KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject
+ );
+ // This code is 612 base.
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ RtlZeroMemory (AdapterObject, sizeof (ADAPTER_OBJECT)); //K035
+
+ Status = ObInsertObject(
+ AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle
+ );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ //
+ // Set ->MasterAdapter
+ //
+
+ if(AdapterBaseVa == (PVOID)-1)
+ // I am
+ // Masteradpter or MasterAdapterForInternal.
+ //
+ AdapterObject->MasterAdapter = NULL;
+ else if(MapRegistersPerChannel)
+ // I am
+ // Bbus (LR4360 DMA)or ASOBus with No Scatter/Gather.
+ //
+ AdapterObject->MasterAdapter = MasterAdapterObjectForInternal;
+ else if(MapRegisterBase ==NULL){
+ //
+ // I am PCI or EISA or ISA.
+ //
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ // Limit was Set End of HalGetAdapter().
+ //AdapterObject->MapRegistersPerChannel =
+ // DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ //
+ }else
+ // I am
+ // Internal Device With Scatter/Gather.
+ //
+ AdapterObject->MasterAdapter = NULL;
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if(AdapterBaseVa == (PVOID)-1){
+ //
+ // MasterAdapterObject and MasterAdapterObjectForInternal.
+ //
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ AdapterObject->NumberOfMapRegisters = 0; //K012
+ if(MapRegistersPerChannel) {
+ //
+ // MasterAdapterObjectForInternal.
+ // (For Bbus LR4360 DMA and Internal Device without Scatter/Gather
+ // may be continuguas memory)
+ //
+ AdapterObject->MapRegistersPerChannel =1;
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters))
+ + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+
+ // K012 AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase =
+ ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(INTERNAL_TRANSLATION_ENTRY)
+ );
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(INTERNAL_TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+
+ }else{
+ // Not use R98
+ //ULONG MapRegisterSize;
+ //
+ PULONG Map;
+ //
+ // Limit is This code.
+ // The Number of MapRegisters For PCI,EISA,ISA use LR4360 TLB.
+ //
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters))
+ + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+ // On PCI,EISA,ISA Set Up LR4360TLB Mapping and
+ // PECB EISA->PCI Mapping.
+ //
+ //
+
+ // Not use R98
+ //MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ //MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+ // HalpMapRegisterPhysicalBase is Set up HalpAllocateMapRegisters().
+ // area of KSEG1_BASE is 512M. So get less than Physical addr 512M
+ // by HalpAllocateMapRegisters().
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG0_BASE); //K026-1
+
+ // dummy page data is "CEN CEN CEN". for What happend!!. K028
+ RtlFillMemoryUlong( (PULONG)((HalpNec0DummyPhysicalBase) |KSEG0_BASE),
+ PAGE_SIZE,0x4E454320); // A002
+
+ RtlFillMemoryUlong( (PULONG)((HalpNec1DummyPhysicalBase) |KSEG0_BASE),
+ PAGE_SIZE,0x4E454e20); // A002
+ // LR4360 Page table Set DumyPhysicalBase.
+ // LR4360 Page Table Size is DMA_TRANSLATION_LIMIT. K028
+ // Set to InValid.
+ RtlFillMemoryUlong( AdapterObject->MapRegisterBase,
+#if defined(PTEINVALID) // S004 vvv
+ DMA_TRANSLATION_LIMIT,(HalpNec0DummyPhysicalBase | 0x1));
+#else
+ DMA_TRANSLATION_LIMIT,HalpNec0DummyPhysicalBase );
+#endif // S004 ^^^
+
+#if defined(DUMMYDMA) // K034 vvv
+ // 256 is Number of page teble entry per 1 TLB
+ // 1M Align Logical Last Page is DUMYY page for TLB FLush!!.
+ //
+ Map =AdapterObject->MapRegisterBase;
+ for(i=0;i<(DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) / 256;i++){
+
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xff+0x100*i,//1M*i-1 page. Start
+ 0x1 //1 page DUMMY
+ );
+ Map[i* 0x100+0xff] =HalpNec1DummyPhysicalBase;
+
+ }
+#else
+ // Reserved For PCEB PreFetch cycle Cause LR4360 TLB miss.
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xfff, //0xFFFFFF
+ 0x1
+ );
+
+#endif // K034 ^^^
+ // 1M Low del
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0x0, //0x0
+ 0xff
+ );
+
+ // eisa vram del
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xE00, //0xe00000
+ 0xff
+ );
+
+ // 16M Low del
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xf00, //0xf00000
+ 0xff
+
+ );
+
+ //
+ // LR4360 TLB Set Up
+ // LR4360:PTBAR0
+ // ( Use 0M-4M-1 Logical address) K013
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR0,
+ (ULONG)HalpMapRegisterPhysicalBase
+ );//K013-2,K016-2,K019-1
+
+ //
+ // LR4360:PTBAR1 ( Use 4M-8M-1 Logical address)
+ //
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR1,
+ // K013
+ (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE //K019-1
+ );
+
+ //
+ // LR4360:PTBAR2 ( Use 8M-12M-1 Logical address)
+ // K013
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR2,
+ (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*2 //K019-1
+ );
+ //
+ // LR4360:PTBAR3 ( Use 12M-12M-1 Logical address)
+ // K013
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR3,
+ (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*3 //K019-1
+ );
+
+ //
+ // LR4360:PTSZR (Set Page Table Size is 4K)
+ // K00D
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTSZR,
+ LR4360PTSZ4K << LR4360PTSZSHIFT
+ );
+
+ //
+ // LR4360:PABAR Logical addr start 0x00000000(0M)
+ // Logical addr end 0x00ffffff(16M-1)
+ //
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PABAR,0x0);
+
+
+ //K021-2 Flush TLB all ,K0026-3
+ for (i = 0;i < 16; i++) { //K024
+
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->TFLR,i);
+ }
+
+
+#if 0 //snes 302
+
+ // K007, K00C, K013
+ // EISA-->PCI map 0M-16M
+ // PCEB MEMREGN[4:1]
+ //
+ WRITE_REGISTER_ULONG(
+ &((volatile PULONG )
+ (KSEG1_BASE|EISA_CONFIG_REGISTERS_MEMREGN))[0],
+ 0xff0000|0x00
+ );
+#endif
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f);
+
+#if defined(DUMMYDMA) // K034 vvv
+ {
+ UCHAR adapterMode;
+ DMA_EXTENDED_MODE extendedMode;
+ PVOID adapterBaseVa;
+ PDMA1_CONTROL dmaControl;
+ //
+ // SetUp Ext Mode reg.
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = 2; //2 is floppy
+ extendedMode.TimingMode = COMPATIBLITY_TIMING; //ISA compati
+ extendedMode.TransferSize = BY_BYTE_8_BITS; //8bit DMA
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // SetUp Mode reg
+ dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+ adapterMode=0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = 2;
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = BLOCK_REQUEST_MODE;
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 0;
+ //
+ // Determine the mode based on the transfer direction.
+ // Read From The Device. it is little first.
+
+// ((PDMA_EISA_MODE) &adapterMode)->TransferType = READ_TRANSFER;
+ // it is safety.
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WRITE_TRANSFER;
+
+ //
+ // This request is for DMA controller 1
+ //
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+ KeInitializeSpinLock (&HalpIoMapSpinLock);
+
+ }
+
+#endif // K034 ^^^
+
+ } // MasterAdapterObject (For PCI,EISA,ISA)
+
+
+ } // MasterAdapterObject and MasterAdapterObjectForInternal.
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+
+ } else {
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+
+ return AdapterObject;
+ // K00E-8
+ // return (PADAPTER_OBJECT) NULL;
+}
+
+// K001-7
+//
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+#if defined(DUMMYDMA)
+ ULONG i;
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+#endif
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+ //
+ // Internal Master Device with Scatter/Gather.
+ // Mapregister Not Used.
+ //
+ return;
+ }
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){
+ //
+ // Internal Device without Scatter/Gather.
+ // Strip no scatter/gather flag.
+ //
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PINTERNAL_TRANSLATION_ENTRY) MapRegisterBase -
+ (PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+ }else{
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ }
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+ //
+ // Return the registers to the bit map.
+ //
+
+#if defined(DUMMYDMA)
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ MasterAdapter == MasterAdapterObject ?
+ NumberOfMapRegisters+1 :NumberOfMapRegisters //K028
+ );
+ //
+ // LR4360 PTE InValid.
+ if(MasterAdapter==MasterAdapterObject){
+ for (i = 0; i < NumberOfMapRegisters+1; i++) {
+#if defined(PTEINVALID) // S004 vvv
+ (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1);
+#else
+ (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase;
+#endif // S004 ^^^
+ DmaMapRegister++;
+ }
+ }
+
+#else
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ MasterAdapter == MasterAdapterObject ?
+ NumberOfMapRegisters+1 :NumberOfMapRegisters //K028
+ );
+#endif
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->MasterAdapter == MasterAdapterObject ?
+ AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters, //K028
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){
+
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PINTERNAL_TRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ //
+ // Set the no scatter/gather flag.
+ // if there device Not Sactter/Gather
+ //
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }else{
+ // DbgPrint("\nIoFreeMapRegisters = 0x%x\n",MapRegisterNumber+1);
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber );//add1 non
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->MasterAdapter == MasterAdapterObject ?
+ AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters //K028
+ );
+#if defined(DUMMYDMA)
+
+ if(MasterAdapter == MasterAdapterObject){
+ DmaMapRegister= (PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber;
+ for (i = 0; i < AdapterObject->NumberOfMapRegisters+1; i++) {
+#if defined(PTEINVALID) // S004 vvv
+ (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1);
+#else
+ (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase;
+#endif // S004 ^^^
+ DmaMapRegister++;
+ }
+ }
+
+#endif
+
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+
+// K001-8
+//
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+ //
+ // CASE:
+ // Internal Master Device without Scatter/Gather.
+ // Internal Device with LR4360 DMA(Always without Scatter/Gather)
+ // PCI,EISA,ISA Device with LR4360 TLB.
+ //
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter!=NULL)
+ {
+ // K00D
+ // MasterAdapterObject??
+ //
+ if ( MasterAdapter== MasterAdapterObject)
+ //
+ // PCI,EISA,ISA Device with LR4360 TLB.
+ //
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ MasterAdapter == MasterAdapterObject ?
+ Wcb->NumberOfMapRegisters+1:Wcb->NumberOfMapRegisters, //K028
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ if (MasterAdapter == MasterAdapterObjectForInternal){
+ //
+ // Internal Device without Sactter/Gather.
+ //
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PINTERNAL_TRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }else{
+
+ //
+ // PCI,EISA,ISA with LR4360 TLB
+ //
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ }
+
+ }
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }else{
+ //
+ // Only Internal Master Device with Scatter/Gather.
+ // Always AdapterObject->MasterAdapter ==NULL.
+ //
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext
+ );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+// K001-9
+//
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = PAGE_SIZE*2+DMA_TRANSLATION_LIMIT; //K028
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ //MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+ // less than 512M.
+ MaxPageAddress = (0x20000000 >> PAGE_SHIFT) - 1 ; //K016
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //K028
+ //
+ // Save the map register base.
+ //
+
+ HalpNec0DummyPhysicalBase =PhysicalAddress;
+ HalpNec1DummyPhysicalBase =HalpNec0DummyPhysicalBase+PAGE_SIZE;
+ HalpMapRegisterPhysicalBase=HalpNec0DummyPhysicalBase+PAGE_SIZE*2;
+
+}
+
+#if defined(DUMMYDMA) // K034 vvv
+VOID
+HalpDummyTlbFlush(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed. DUMMY DUMMY DUMMY DUMMY
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes. DUMMY DUMMY DUMMY DUMMY
+
+ WriteToDevice - Indicates the direction of the transfer. DUMMY DUMMY DUMMY DUMMY
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ volatile UCHAR Status;
+// volatile UCHAR Mask;
+ UCHAR adapterMode;
+ PUCHAR PagePort;
+ PUCHAR BytePtr;
+ volatile PUCHAR BytePtr2;
+ volatile ULONG Count;
+ PDMA1_CONTROL dmaControl;
+// PDMA2_CONTROL dmaControl2;
+ BytePtr2 = (PUCHAR) &Count;
+ BytePtr = (PUCHAR) &Offset;
+ PagePort = &((PDMA_PAGE) 0)->Channel2;
+ dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+// dmaControl2 = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+// Mask=READ_REGISTER_UCHAR( &dmaControl2->AllMask );
+// WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, (UCHAR) (0xf) );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[0] );
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[1] );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)PagePort,
+ 0
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ // transfer Count is 1 Byte . So Set 1-1=0
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0x1);
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0);
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5]),
+ (UCHAR) 0
+ );
+
+
+ //Flush LR4360 Read Cache.
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
+ //
+ // SoftWare DMA Request, channel 2
+ //
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x4 | 0x2) );
+ //
+ // check dma transfer was finished!!.
+ //
+ do{
+ Count=0;
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+ BytePtr2[0]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount);
+ BytePtr2[1]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount);
+ BytePtr2[2]=
+ READ_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5])
+ );
+ if((Count & 0xffffff)== 0xffffff)
+ break;
+ }while(1);
+
+// WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x0 | 0x2) );
+// WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, 0x0 );
+
+}
+
+#endif // K034 ^^^
+
+
+// K001-A
+//
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+#if defined(DUMMYDMA) // K034 vvv
+ KIRQL Irql;
+#endif // K034 ^^^
+ ULONG value;
+ //
+ // May be check Bus Master: AdapterObject==NULL!!.
+ // Internal Device:
+ // ASOBus with Scatter/Gather:MapRegisterBase ==NULL
+ // without Scatter/Gather always allocate MapRegister
+ // So check As if use MapRegister.
+ //
+ // ASOBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1
+ // BBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1
+ //
+ //
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+ ULONG logicalAddress;
+ ULONG transferLength;
+ PINTERNAL_TRANSLATION_ENTRY translationEntry;
+ ULONG index; //K00D
+
+ //K00E-4
+ transferLength=PAGE_SIZE - BYTE_OFFSET((PUCHAR) CurrentVa );
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+ logicalAddress = (*PageFrameNumber << PAGE_SHIFT) + Offset;
+ //K00D
+ if((MapRegisterBase== NULL) || ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) ){
+
+ // BusMaster with Scatter/gather || witout Scatter/Gather
+ //
+
+ while(transferLength < *Length ){
+
+ if (*PageFrameNumber + 1 != *(PageFrameNumber + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ PageFrameNumber++;
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // ASOBus Master without Scatter/Gather && contigous < request
+ // or
+ // Bbus Device Floppy use LR4360 DMA(it's not use Scatter/Gater) && contigous < request
+ //
+ //
+ if ( (ULONG)MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length ){
+
+ translationEntry = (PINTERNAL_TRANSLATION_ENTRY)
+ ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ logicalAddress = translationEntry->PhysicalAddress + Offset;
+ //
+ // It's means I have not Scatter/Gather && contigous < request then I use buffer
+ // At IoFlushAdapterBuffers() Do ?Hal Buffer-->user mem
+ //
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ // Do Copy So avaleable transfer is request size
+ transferLength = *Length;
+
+ // When Memory --> Device, Copy From memory to conigous buffer
+ //
+ if ( WriteToDevice)
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+ *Length=transferLength;
+ //
+ // ASOBus Master without Scatter/Gather. ||
+ // ASOBus Master with Scatter/Gather
+ //
+ // (Thus ASObus Master Don't use LR4360 DMA.)
+ //
+ if ( AdapterObject == NULL || MapRegisterBase ==NULL)
+ return(RtlConvertUlongToLargeInteger(logicalAddress));
+
+ //
+ // Bbus DMA used Device etc..Floppy
+ // Then Set Up LR4360 DMA Controlor
+ //
+
+ //K00F From HalGetAdapter()
+ // Flush LR4360 FiFo.
+ // Note: LR4360 DMA Set up Do Drain. So At this time
+ // FiFo have Never Data.....
+
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->FiFoF=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ //
+ // Sleep till CnDC->iNED =1 ??
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+
+ //K00D
+ if(((PLR_DMA_CONTROL)&value)->iNEDS){
+ //
+ // what sec to wait !!
+ // K00D N.B microsecond
+ KeStallExecutionProcessor(100);
+
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ //
+ // the die .....
+ // K00D
+ if(((PLR_DMA_CONTROL)&value)->iNEDS)
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+ //
+ // transfer count set
+ //K010-2
+ // N.B *Length must be below 0x03ffffff.(64M)
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnBC,
+ *Length
+ );
+ //
+ // transfer addr set
+ //
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnMA,
+ // K00D RtlConvertUlongToLargeInteger(logicalAddress)
+ logicalAddress
+ );
+ //
+ // direction set
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ //K00D
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->MEMWE=1;
+
+ if ( WriteToDevice) {
+ ((PLR_DMA_CONTROL)&value)->MEMWT=0;
+ //
+ // For End of DMA function .see HalpDmaInterrupt()
+ //
+ //
+ // Memory --> Device
+ //
+ //
+ // AdapterObject->TransferType = WRITE_TRANSFER;
+ //
+
+ }else{
+ ((PLR_DMA_CONTROL)&value)->MEMWT=1;
+ //
+ // Device --> Memory
+ //
+ // AdapterObject->TransferType = READ_TRANSFER;
+ //
+ }
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+ //
+ // Enable Input BREQ line
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0; //K00D
+
+ ((PLR_DMA_CONTROL)&value)->REQWE=1; //K00D
+ ((PLR_DMA_CONTROL)&value)->REQiE=1; //K00D
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+ //
+ // End of LR4360 DMA Set Up.
+ //
+ return(RtlConvertUlongToLargeInteger(logicalAddress));
+ }else{
+#if defined(DUMMYDMA) // K034 vvv
+ KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql);
+#endif
+
+ //
+ // Determine the maximum number of pages required to satisfy this request.
+ //
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ //
+ // Set up phys addr in LR4360 Page table entry.
+ //
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+
+ //
+ // PCI,EISA,ISA is used TLB of LR4360.
+ // So There is Inside Logical address Pci.
+ // K00D offset -->Offset
+ Offset += (
+ (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ ) << PAGE_SHIFT;
+
+ // Not use LR4360 PTBA0 Register ( 0-4M)
+ //
+ // use only 4M-8M. !!!!
+ //
+ Offset += PCI_LOGICAL_START_ADDRESS;
+
+#if defined(DUMMYDMA) // K034
+ // If PTE is InValid. Set to DummyPage for PCEB Prefetch.
+ // else It was seted by another IoMapTransfer.
+#if defined(PTEINVALID) // S004 vvv
+ if((DmaMapRegister)->PageFrame & 0x1)
+ (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase;
+#endif // S004 ^^^
+
+
+ HalpDummyTlbFlush((PADAPTER_OBJECT)NULL,(Offset & 0x00f00000) | 0x000ff800,(ULONG)NULL,(BOOLEAN)NULL); // A002
+
+#else
+ //
+ // Flush Translation Look a Side Buffer.
+ // ( 1 Entry is 1M )
+ for (i = Offset >>20 ; i <= ((Offset+NumberOfPages*PAGE_SIZE)>>20); i++) {
+
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->TFLR,i);
+ }
+
+#endif // K034 ^^^
+ if ( AdapterObject != NULL) //K00D
+ //
+ // Set Up ESC DMA of EISA,ISA.
+ //
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+ //
+ // BUS Master
+ // else PCI(always Master) or EISA,ISA Busmaster.
+ //
+ }
+#if defined(DUMMYDMA) // K034 vvv
+ KeReleaseSpinLock( &HalpIoMapSpinLock, Irql );
+#endif
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+//
+// K001-B
+//
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers and clears the
+ enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+ // case: Not use Mapregister.
+ // 1. Internal Master with Scatter/Gather. Never use Mapregiter.
+ // 2. Internal Master without Scatter/Gather But Not use Mapregister.
+ // When contigus buffer > request
+ // 3. Internal Slave with LR4360 DMA (Floppy)But Not use Mapregister.
+ // When contigus buffer > request
+ //
+ // Internal or external device and use Mapregister.
+ // Case:
+ // 4. Internal Master without Scatter/Gather use Mapregister.
+ // When contigus buffer <request (use copy buffer)
+ // 5. Internal Slave LR4360 DMA(Floppy)
+ // When contigus buffer <request (use copy buffer)
+ // 6. PCI,EISA,ISA Master Device is used Mapregister For LR4360
+ // TLB.(Page Table)
+ // 7. EISA,ISA Slave(ESC DMA) Device is used Mapregister For LR4360
+ // TLB.(Page Table)
+
+ ULONG DataWord;
+ ULONG Channel;
+ ULONG value;
+
+
+ PINTERNAL_TRANSLATION_ENTRY translationEntry;
+
+ ULONG i;
+ UCHAR DataByte;
+ //
+ //
+ if ( MapRegisterBase == NULL ) {
+
+ // Case:
+ // 1. Internal Master with Scatter/Gather. Never use Mapregiter.
+ // So MaregisterBase allways NULL
+ //if(AdapterObject == NULL )
+ //
+ //
+ //
+ return(TRUE);
+ }else{
+ //
+ // Case: 2,3,4,5,6,7
+ //
+ if(AdapterObject==NULL){
+ if( ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) == 0){ //K00D,K017
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
+ //
+ // Case: 6
+ //
+ return(TRUE);
+ }
+ }
+ }
+ //
+ // At This Point case is 2,3,4,5,7
+ //
+ //
+ if (AdapterObject->PagePort) {
+
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
+
+
+ //
+ // case 7.
+ //
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ return(TRUE);
+ }
+
+ //
+ // At case 2,3,4,5
+ // ~ ~
+
+
+ if(AdapterObject != NULL){
+ // Master Device is allways NULL
+ //
+ // case 3,5 use LR4360 DMA
+ //
+ // this line it's may be HalpDmaInterrupt(). but it is not good that
+ // two End of DMA function (this func,and HalpDmaInterrupt()).
+ // Because Work at Interrupt from LR4360DMA is Not first (100%)
+ //
+
+ //
+ // Read CnDC register.
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ // K00E-2
+ // Do Write then Reserved Bit must be 0.
+ //
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->Reserved2=0;
+ //
+ // At Memory-->Device Do drain So Not FiFo flush !!.
+ //
+ //
+ // Device --> Memory
+ // K00D
+ if(!WriteToDevice){
+ if( ((PLR_DMA_CONTROL)&value)->FiFoV){
+ //
+ // FiFo have valid Data So Flush!!
+ // K00D
+ ((PLR_DMA_CONTROL)&value)->FiFoD=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ }
+ }
+ //
+ // iNEDS is clear by set 1 write
+ // K00D
+ ((PLR_DMA_CONTROL)&value)->iNEDS=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+
+ //
+ // Device --> Memory.
+ //
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PINTERNAL_TRANSLATION_ENTRY)
+ ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+ //
+ // case: 2,3,4,5
+ //
+ if (translationEntry->Index == COPY_BUFFER) {
+ //
+ // case: 4,5
+ //
+ if(AdapterObject != NULL)
+ //
+ // case: 5 used DMA
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ //
+ // case: 4,5
+ //
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+ }
+ //else
+ //
+ // case: 2,3
+ // Not Used Copy Buffer then Nothing to Do. through !!.
+ //
+ //
+ // Strip no scatter/gather flag.
+ // K00D
+ }
+
+ }
+ translationEntry = (PINTERNAL_TRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+ //
+ // Clear index in map register.
+ //
+ translationEntry->Index = 0;
+ return( TRUE );
+}
+
+
+
+// K001-C
+//
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+// K001-D
+//
+//
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+#if defined(DUMMYDMA)
+ KIRQL Irql;
+#endif
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+ //
+ // PCI,EISA,ISA
+ //
+ //
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+#if defined(DUMMYDMA)
+ KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql);
+#endif
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+#if defined(DUMMYDMA)
+ KeReleaseSpinLock( &HalpIoMapSpinLock, Irql );
+#endif
+ } else {
+ //
+ // Internal Device With LR4360 DMA.
+ //
+ //
+ // read CnBC register.
+ //
+ count=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnBC
+ );
+
+ }
+
+ return(count);
+}
+
+
+//
+// K001-E
+// always return 1: See IoFlushAdapterBuffers()
+//
+BOOLEAN
+HalpDmaInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a DMA channel interrupt occurs.
+ LR4360 DMA
+Arguments:
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+#if 0 //K011-2
+ return(TRUE);
+#else
+ PADAPTER_OBJECT AdapterObject;
+ ULONG DataWord;
+ ULONG Channel;
+ ULONG value;
+ //
+ // Read the Inerrupt Service Factor Register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&(LR_CONTROL2)->iRSF);
+
+ for (Channel = 0; Channel < 5; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << (Channel+LR_iRSF_REG_iNSF_SHIFT)))) {
+ continue;
+ }
+
+ //
+ // DMA Channel LR4360 is 1 origin.
+ //
+ if((AdapterObject=HalpInternalAdapters[Channel+1])==NULL){
+#if 0
+ DmaChannelMsg[18] = (CHAR) Channel+ '1';
+ HalDisplayString(DmaChannelMsg);
+#endif
+ //
+ //
+ //
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ //
+ // read CnDC register.
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ //
+ // At Memory-->Device drain So Don't FiFo flush.
+ //
+ //
+ // Device --> Memory
+ //
+ if( ((PLR_DMA_CONTROL)&value)->MEMWT==0){
+ if( ((PLR_DMA_CONTROL)&value)->FiFoV){
+
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->Reserved2=0;
+ //
+ // FiFo Data is valid So Flush.
+ //
+ ((PLR_DMA_CONTROL)&value)->FiFoD=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ }
+ }
+ //
+ // iNEDS is clear by 1 write
+ // K00D
+ ((PLR_DMA_CONTROL)&value)->iNEDS=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+ return(TRUE);
+ }
+#endif
+}
+
+// K001-F
+//
+//
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PINTERNAL_TRANSLATION_ENTRY TranslationEntry ;
+ LONG NumberOfPages;
+ LONG i;
+
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+ PVOID CodeLockHandle; //K035
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+ CodeLockHandle = MmLockPagableCodeSection (&HalpGrowMapBuffers);
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql ); //K025
+
+ TranslationEntry = ((PINTERNAL_TRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (LONG)i < NumberOfPages; i++) { //K00D K035
+
+#if 1 // Enable K00E-7
+ //
+ // Use at R98: LR4360 DMA Not boundry 64K. But per Grow size is 64K incremnet!!.
+ //
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress )) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+#endif
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PINTERNAL_TRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ MmUnlockPagableImageSection (CodeLockHandle); //K035
+ return(TRUE);
+}
+
+// K001-G
+//
+//
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PINTERNAL_TRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+#if 0 //K023 move to r98int.s
+/* Start S002 */
+VOID
+HalpNmiHandler(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is call from ROM at NMI
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ // K022
+ // NMI was not happend!!.
+ //
+ HalpResetNmi();
+ //
+ // Cause EIF !!
+ //
+ WRITE_REGISTER_UCHAR(0xB9980100,0x00828000);
+ return;
+}
+#endif
+
+VOID
+HalpRegisterNmi(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set NMI handler to nvRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+// VOID (*funcAddr)();
+ ULONG funcAddr; // K00D
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Get address of HalpNmiHandler
+ //
+
+ funcAddr = (ULONG)HalpNmiHandler; // K00D
+// funcAddr += (KSEG1_BASE - KSEG0_BASE); //K023
+
+ ASSERT( ((ULONG)&HalpNmiHandler >= KSEG0_BASE) &&
+ ((ULONG)&HalpNmiHandler < KSEG2_BASE) );
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[0],
+ (UCHAR)(funcAddr >> 24));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[1],
+ (UCHAR)((funcAddr >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[2],
+ (UCHAR)((funcAddr >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[3],
+ (UCHAR)(funcAddr & 0xFF));
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return;
+}
+/* End S002 */
+
+#if 0 //K015
+//
+// K00D form halfxs/mips/jxhwsup.c
+//
+//
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+
+#endif //K015
diff --git a/private/ntos/nthals/halr98mp/mips/r98info.c b/private/ntos/nthals/halr98mp/mips/r98info.c
new file mode 100644
index 000000000..c574c0a6c
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98info.c
@@ -0,0 +1,99 @@
+#ident "@(#) NEC r98info.c 1.1 95/06/19 11:34:28"
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History
+
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-ixinfo.h to 1050-halx86-r98info.h
+
+--*/
+
+
+#include "halp.h"
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
diff --git a/private/ntos/nthals/halr98mp/mips/r98int.s b/private/ntos/nthals/halr98mp/mips/r98int.s
new file mode 100644
index 000000000..d5d05d25d
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98int.s
@@ -0,0 +1,522 @@
+// "@(#) NEC r98int.s 1.14 95/06/19 11:35:43"
+// TITLE("Interrupts service routine")
+//++
+//
+// Copyright (c) 1994 Kobe NEC Software
+//
+// Module Name:
+//
+// r98int.s
+//
+// Abstract:
+//
+//
+// Author:
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// S001 '94.6/03 T.Samezima
+//
+// Del iRSF interrupt clear
+//
+//**************************************************************
+//
+// S002 94.6/13 T.Samezima
+//
+// Del Compile err
+//
+//**************************************************************
+//
+// S003 94.7/15 T.Samezima
+//
+// Chg change register access from 8byte access to 4byte access
+//
+//**************************************************************
+//
+// S004 94.7/20 T.Samezima
+//
+// Del Compile err
+// K001 94/10/11 N.Kugimoto
+// Add.chg HalpNmiHandler() from r98hwsup.c and chg
+//
+// S005 94/01/15 T.Samezima
+// Add HalpReadPhysicalAddr()
+//
+// S006 94/01/24 T.Samezima
+// Add HalpWritePhysicalAddr(),HalpReadAndWritePhysicalAddr(),
+//
+// S007 94/03/10-17 T.Samezima
+// Chg HalpNMIHandler().
+//
+// A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+// - resolve compile error or logic error?
+//--
+
+#include "halmips.h"
+#include "r98def.h"
+
+
+ SBTTL("Timer Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an timer interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpTimerDispatch)
+
+ move a0,s8
+ j HalpTimerScDispatch
+
+ .end HalpTimerDispatch
+
+
+ SBTTL("Read Large Register")
+//++
+//
+// Routine Description:
+//
+// This routine is read of large register
+//
+// Argments:
+//
+// a0 - Virtual address
+//
+// a1 - pointer to buffer of upper 32bit large register
+//
+// a2 - pointer to buffer of lower 32bit large register
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReadLargeRegister)
+
+// Start S003
+#if 0
+ DISABLE_INTERRUPTS(t7) // disable interrupts
+
+ mfc1 t0,f0 // save f0 register
+ mfc1 t1,f1 // save f1 register
+
+ ldc1 f0,0x0(a0) // read register
+ mfc1 t2,f0 // get register(upper)
+ mfc1 t3,f1 // get register(lower)
+#endif
+
+ lw t2,0x0(a0) // get register(upper)
+ lw t3,0x4(a0) // get register(lower)
+
+ sw t2,0x0(a1) // set upper register value
+ sw t3,0x0(a2) // set lower register value
+
+#if 0
+ mtc1 t0,f0 // restore f0 register
+ mtc1 t1,f1 // restore f1 register
+
+ sync //
+
+ ENABLE_INTERRUPTS(t7) // enable interrupts
+#endif
+// End S003
+ j ra // return
+
+ .end HalpReadLargeRegister
+
+
+
+ SBTTL("Write Large Register")
+//++
+//
+// Routine Description:
+//
+// This routine is write of large register
+//
+// Argments:
+//
+// a0 - Virtual address
+//
+// a1 - pointer to value of upper 32bit of large register
+//
+// a2 - pointer to value of lower 32bit of large register
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteLargeRegister)
+
+// Start S003
+#if 0
+ DISABLE_INTERRUPTS(t7) // disable interrupts
+
+ mfc1 t0,f0 // save f0 register
+ mfc1 t1,f1 // save f1 register
+#endif
+
+ lw t2,0x0(a1) // load upper register value
+ lw t3,0x0(a2) // load lower register value
+
+ sw t2,0x0(a0) // set upper register value
+ sw t3,0x4(a0) // set lower register value
+
+#if 0
+ mtc1 t2,f0 // set register(upper)
+ mtc1 t3,f1 // set register(lower)
+ sdc1 f0,0x0(a0) // write register
+
+ mtc1 t0,f0 // restore f0 register
+ mtc1 t1,f1 // restore f1 register
+#endif
+
+ sync //
+
+// ENABLE_INTERRUPTS(t7) // enable interrupts
+// End S003
+
+ j ra // return
+
+ .end HalpWriteLargeRegister
+
+
+ SBTTL("Read Cause Register")
+//++
+// S005
+// Routine Description:
+//
+// This routine is get of cause register
+//
+// Argments:
+//
+// None.
+//
+// Return Value:
+//
+// cause rezister value.
+//
+//--
+
+ LEAF_ENTRY(HalpGetCause)
+
+ READ_CAUSE_REGISTER(v0)
+
+ j ra // return
+
+ .end HalpGetCause
+
+
+// S005 vvv
+ SBTTL("Read Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is read of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// Return Value:
+//
+// read data.
+//
+//--
+
+ LEAF_ENTRY(HalpReadPhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ lw v0,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadPhysicalAddress
+// S005 ^^^
+// S006 vvv
+ SBTTL("Write Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is Write of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// a1 - Write Data
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWritePhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ sw a1,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWritePhysicalAddress
+
+
+ SBTTL("Read And Write Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is read and write of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// Return Value:
+//
+// read data.
+//
+//--
+
+ LEAF_ENTRY(HalpReadAndWritePhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ lw v0,0(t0)
+ sw v0,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadAndWritePhysicalAddress
+// S006 ^^^
+
+ SBTTL("HalpNmiHandler")
+//++
+// K001
+// Routine Description:
+//
+// This routine is reset status Register on NMI.
+// Return from this function EIF Interrupt Occur!!
+// Argments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpNmiHandler)
+ .set noat
+
+// S007 vvv
+ //
+ // reset NMIR register, set NMI flag and save CPU register.
+ //
+
+ li k0,0xb9980308 // Set STSR address
+ li k1,0x08080000 // Disable NMI
+ sw k1,0x0(k0) //
+
+ la k0,HalpNMIFlag // set NMI flag address
+// li k1,0xa0000000 // KSEG1_ACCESS
+// or k0,k0,k1 //
+ li k1,0xb9980030 // set NMIR address
+ lw k1,(k1) // get NMIR register
+ addi k1,k1,1 // set NMI flag
+ sw k1,(k0) //
+
+ li k1,0xb8c80000 // Reset NMI
+ sb zero,0x0(k1) //
+
+#if 1
+// lw k0,KiPcr + PcPrcb(zero) // get current processor block address
+// la k1,HalpNMIBuf // get performance counter address
+// lbu k0,PbNumber(k0) // get processor number
+// sll k0,k0,7 // compute address of nmi buffer
+// addu k0,k0,k1 //
+
+ li k0,0xb9980300 // get CNFG Register Addr of PMC
+ li k1,0x00007000 // Mask Node Of CPU0-CPU3
+ lw k0 ,0x0(k0) // get value of etc of PMC
+ and k0,k0,k1 // get value of NODE
+ la k1,HalpNMIBuf // get performance counter address
+ srl k0,k0,5 // shift right 7 bit for offset
+ addu k0,k0,k1 // compute address of nmi buffer
+
+// sw at,0x0(k0) // register save.
+ sw v0,0x4(k0) //
+ sw v1,0x8(k0) //
+ sw a0,0xc(k0) //
+ sw a1,0x10(k0) //
+ sw a2,0x14(k0) //
+ sw a3,0x18(k0) //
+ sw t0,0x1c(k0) //
+ sw t1,0x20(k0) //
+ sw t2,0x24(k0) //
+ sw t3,0x28(k0) //
+ sw t4,0x2c(k0) //
+ sw t5,0x30(k0) //
+ sw t6,0x34(k0) //
+ sw t7,0x38(k0) //
+ sw t8,0x3c(k0) //
+ sw t9,0x40(k0) //
+ sw gp,0x44(k0) //
+ sw sp,0x48(k0) //
+ sw s8,0x4c(k0) //
+ sw ra,0x50(k0) //
+
+ .set noreorder
+
+ mfc0 k1,psr //
+ sw k1,0x54(k0) //
+ mfc0 k1,cause //
+ sw k1,0x58(k0) //
+ mfc0 k1,epc //
+ sw k1,0x5c(k0) //
+ mfc0 k1,errorepc //
+ sw k1,0x60(k0) //
+
+ .set reorder
+
+#endif
+
+ li k0,0xb9980038 // set NMIRST address
+ li k1,0x8 // it is DUMP Key NMI
+ sw k1,(k0) // reset nmi
+ .set noreorder // A002
+ nop
+//
+// This is a test code.
+// We must clear BEV bit of psr register.
+//
+
+ mfc0 k1,psr // get psr
+ li k0,0xffafffff // BEV bit clear
+ nop // fill
+ and k1,k1,k0 //
+ nop //
+ mtc0 k1,psr // set psr
+ nop // fill
+ nop //
+ nop //
+
+// li k0,0xb9980308 // Read STSR Register
+// lw k1,(k0) //
+// or k1,k1,0x80800000// make eif
+// sw k1,(k0) //
+// nop
+
+ li k0,0xb9980100 // IntIR Register addr
+ li k1,0x0082f000 // Do eif to CPU0 only.
+ sw k1,(k0) //
+
+ nop
+ eret // return to errorepc
+ nop
+ nop
+ nop
+ eret // errata
+ nop
+#if 0
+ mfc0 k0,epc // As if behave No Nmi
+ nop
+ nop
+ j k0 // As if behave No Nmi.
+#endif // I Hope EIF Interrut
+ // Occur later!!.
+ //
+// S007 ^^^
+
+ .set at
+ .set reorder
+
+
+ .end HalpNmiHandler
+
diff --git a/private/ntos/nthals/halr98mp/mips/r98ipint.s b/private/ntos/nthals/halr98mp/mips/r98ipint.s
new file mode 100644
index 000000000..b6176b490
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98ipint.s
@@ -0,0 +1,176 @@
+// "@(#) NEC r98ipint.s 1.5 94/10/11 23:04:02"
+// TITLE("Interprocessor Interrupts")
+//++
+//
+//
+// Module Name:
+//
+// r98ipint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a r98
+//
+// Author:
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//
+// S001 94.6/13 T.Samezima
+//
+// Del Compile err
+//
+// S002 94.7/14 T.Samezima
+//
+// Chg define register base address
+// change register access from 8byte access to 4byte access
+//
+// S003 94.7/20 T.Samezima
+//
+// Del Compile err del
+//
+// S004 94.10/11 T.Samezima
+//
+// Fix Version Up at build807
+//
+//
+//--
+
+#include "halmips.h"
+#include "r98def.h"
+//#include "r98reg.h" // S001
+
+// Start S002
+//
+// Define interrupt control registers base
+//
+
+#define PMC_BASE PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+KSEG1_BASE
+// End S002
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt.
+// Its function is to acknowledge the interrupt and transfer control to
+// the standard system routine to process interprocessor requrests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+IiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+IiRa: .space 4 // saved return address
+IiFrameLength: //
+
+ NESTED_ENTRY(HalpIpiInterrupt, IiFrameLength, zero)
+
+ subu sp,sp,IiFrameLength // allocate stack frame
+ sw ra,IiRa(sp) // save return address
+
+ PROLOGUE_END
+
+// Start S002
+// mfc1 t5,f0 // save f0 register
+// sw t5,IiF0(sp) //
+// mfc1 t6,f1 // save f1 register
+// sw t6,IiF1(sp) //
+// End S002
+
+ li t7,PMC_BASE // get register address // S002
+
+// Start S002
+ lw t0,0x0(t7) // get upper 32bit of IPR register
+
+// ldc1 f0,0x0(t7) // read IPR register
+// mfc1 t0,f0 // get upper 32bit of IPR register
+
+10: lw t1,0x8(t7) // get upper 32bit of MKR register
+
+// ldc1 f0,0x8(t7) // read MKR register
+// mfc1 t1,f0 // get upper 32bit of MKR register
+// End S002
+
+ and t1,t0,t1 // calculate upper 32bit of 'IPR & MKR'
+ andi t2,t1,IPR_IPI0_BIT_HIGH // check IPI0 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor0
+ andi t2,t1,IPR_IPI1_BIT_HIGH // check IPI1 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor1
+ andi t2,t1,IPR_IPI2_BIT_HIGH // check IPI2 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor2
+ andi t2,t1,IPR_IPI3_BIT_HIGH // check IPI3 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor3
+
+//
+// Unknown interrupt.
+//
+
+ li t4,MKR_INT4_ENABLE_HIGH // make argument
+ and a0,t1,t4 //
+ and a1,zero,a1 //
+ jal HalpUnknownInterrupt // call unknown interrupt handler
+ b 30f
+
+//
+// Interprocessor interrupt.
+//
+
+// Start S002
+20: sw t2,0x10(t7) // set IPRR register
+ sw zero,0x14(t7) //
+
+// mtc1 t2,f0 // set IPRR register
+// mtc1 zero,f1 //
+// sdc1 f0,0x10(t7) //
+// End S002
+
+ lw t1,__imp_KeIpiInterrupt // process interprocessor requests // S004
+ jal t1 // // S004
+
+//
+// check other interrupt.
+//
+
+30: li t7,PMC_BASE // get register address // S002
+// Start S002
+ lw t0,0x0(t7) // get upper 32bit of IPR register
+// ldc1 f0,0x0(t7) // read IPR register
+// mfc1 t0,f0 // get upper 32bit of IPR register
+// End S002
+ andi t1,t0,MKR_INT4_ENABLE_HIGH // check interrupt of int4 level
+ bne t1,zero,10b // if neq, occur new interrupt.
+
+ READ_CAUSE_REGISTER(t2) // get cause // S002
+
+ andi t3,t2,1 << (CAUSE_INTPEND + IPI_LEVEL - 1 ) // check interrupt
+ bne t3,zero,30b // if neq, check new interrupt
+
+// Start S003
+// lw t0,IiF0(sp) // restore f0 register
+// mtc1 t0,f0 //
+// lw t1,IiF1(sp) // restore f1 register
+// mtc1 t1,f1 //
+// End S003
+
+ lw ra,IiRa(sp) // save return address
+ addu sp,sp,IiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpIpiInterrupt
diff --git a/private/ntos/nthals/halr98mp/mips/r98led.c b/private/ntos/nthals/halr98mp/mips/r98led.c
new file mode 100644
index 000000000..219d3abd9
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98led.c
@@ -0,0 +1,252 @@
+#ident "@(#) NEC r98led.c 1.5 95/06/19 11:36:14"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98led.c
+
+Abstract:
+
+ This module implements the Led output routines for R98
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ S001 9/26/94 By T.Samezima
+
+ Add Debug Print
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - resolve compile error.
+
+--*/
+
+#include "halp.h"
+
+//
+// Set table size
+//
+#define SEGMENT_TABLE_SIZE 16
+
+//
+// Define spin lock
+//
+KSPIN_LOCK HalpLedLock;
+
+//
+// Define flag of initialize led
+//
+ULONG HalpLedInitFlg = 0;
+
+//
+// Buffer of output data at port
+//
+UCHAR HalpSegmentDisplayData[4] = { 0, 0, 0, 0 };
+
+//
+// Define character table
+//
+UCHAR HalpSegmentCharTableL[] = "0123456789abcdef";
+UCHAR HalpSegmentCharTableU[] = "0123456789ABCDEF";
+
+//
+// Define table of change from output character data to output port data
+//
+UCHAR HalpSegmentPatternTable[] = { 0xfa, 0x30, 0xdc, 0x7c, //0-3
+ 0x36, 0x6e, 0xee, 0x3a, //4-7
+ 0xfe, 0x7e, 0xfc, 0xe6, //8-b
+ 0xc4, 0xf4, 0xce, 0x8e, //c-f
+ 0x04 }; //err
+
+
+VOID
+HalpOutputSegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is output a character data in led segment.
+
+Arguments:
+
+ Number - Segment number(range 0-3.)
+
+ Data - Output data on port.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG lednumber;
+
+ //
+ // Get segment number.
+ //
+
+ lednumber = Number & 0x3;
+
+ if(HalpLedInitFlg == 0){
+ KeInitializeSpinLock(&HalpLedLock);
+ HalpLedInitFlg = 1;
+ }
+
+ KiAcquireSpinLock(&HalpLedLock);
+
+ //
+ // Display data.
+ //
+
+ HalpSegmentDisplayData[Number] = Data;
+
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData3,
+ HalpSegmentDisplayData[3] );
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData2,
+ HalpSegmentDisplayData[2] );
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData1,
+ HalpSegmentDisplayData[1] );
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData0,
+ HalpSegmentDisplayData[0] );
+
+ KiReleaseSpinLock(&HalpLedLock);
+
+ return;
+}
+
+VOID
+HalpDisplaySegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is display a character in led segment.
+
+Arguments:
+
+ Number - Segment number(range 0-3.)
+
+ Data - Output data character on port.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG counter;
+
+ //
+ // Search character data.
+ //
+
+ for( counter=0 ; counter<SEGMENT_TABLE_SIZE ; counter++ ) {
+ if( ( Data == HalpSegmentCharTableL[counter])
+ | ( Data == HalpSegmentCharTableU[counter]) ) {
+ break;
+ }
+ }
+
+ HalpOutputSegment( Number, HalpSegmentPatternTable[counter]);
+ return;
+}
+
+// Start S001
+#if 1
+
+#include "stdarg.h"
+#include "stdio.h"
+
+#define DBG_SERIAL 0x0001 // For Debugger
+#define DBG_COLOR 0x0002 // For Display
+#define DBG_LED 0x0004 // For Led
+ULONG R98DebugLevel=8;
+ULONG DebugOutput = (DBG_LED | DBG_SERIAL);
+//ULONG DebugOutput = (DBG_LED | DBG_COLOR | DBG_SERIAL);
+//ULONG DebugOutput = (DBG_LED | DBG_COLOR);
+//ULONG DebugOutput = (DBG_LED);
+
+
+// caller
+// R98DbgPrint((1,"1234","\n\nI'm Here : value is =%d\n",value));
+//
+//
+
+VOID
+R98DebugOutPut(
+ ULONG DebugPrintLevel, // Debug Level
+ PCSZ DebugMessageLed, // For LED strings. shuld be 4Byte.
+ PCSZ DebugMessage, // For DISPLAY or SIO
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ Debug print routine.
+
+Arguments:
+
+ Debug print level between 0,and 3, with 3 being the most verbose.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ va_list ap;
+ char *p,LedNumber;
+ CHAR buffer[128];
+
+ if (DebugPrintLevel >= R98DebugLevel) {
+ if (DebugOutput & DBG_LED) {
+ // Message is "1-a-f"
+ for(p=(char *)DebugMessageLed,LedNumber=0; LedNumber<4;p++,LedNumber++) // A002
+ HalpDisplaySegment(LedNumber,*p);
+ }
+
+ // sdk/inc/crt/stdarg.h
+ va_start(ap, DebugMessage);
+
+ // stdlib ?? (sdk/inc/crt/stdio.h)
+ (VOID) vsprintf(buffer, DebugMessage, ap);
+
+ //
+ if (DebugOutput & DBG_SERIAL) {
+ DbgPrint(buffer);
+ }
+
+ // Console =Vram Write
+ //
+ if (DebugOutput & DBG_COLOR) {
+ HalDisplayString(buffer);
+ }
+
+ }
+
+ va_end(ap);
+
+}
+#endif
+// End S001
diff --git a/private/ntos/nthals/halr98mp/mips/r98pci.c b/private/ntos/nthals/halr98mp/mips/r98pci.c
new file mode 100644
index 000000000..64703837d
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98pci.c
@@ -0,0 +1,289 @@
+#ident "@(#) NEC r98pci.c 1.8 95/01/11 22:30:24"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98pci.c
+
+Abstract:
+
+ This module implements the pci bus support routine for R98
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ S001 94.7/20 T.Samezima
+ Chg Del compile err
+
+ S002 '94.10/14 T.Samezima
+ Add Set PCI bus interrupt affinity.
+
+ S003 '94.10/24 T.Samezima
+ Add Error register read and print.
+
+ S004 '94.12/07 T.Samezima
+ Add Error register read and print.
+
+ S005 '94.01/11 T.Samezima
+ Del del werning.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h" // S005
+
+//
+// Enable PCI count
+//
+
+ULONG HalpEnablePCIInterruptCount;
+
+// Start S002
+// Define PCI bus interrupt affinity.
+//
+
+KAFFINITY HalpPCIBusAffinity;
+// End S002
+
+// S001
+BOOLEAN
+HalpPCIDispatch( // S001
+ IN PKINTERRUPT Interrupt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of PCI err interrupt.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt function address.
+
+Return Value:
+
+
+--*/
+
+{
+ // S003 vvv
+ // S004 vvv
+ ULONG errsBuffer;
+ ULONG pearBuffer;
+ ULONG aearBuffer;
+ UCHAR messageBuffer[256];
+
+ errsBuffer = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS );
+ pearBuffer = READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->PEAR );
+ aearBuffer = READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->AEAR );
+
+ if ( errsBuffer & 0x80000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: Master Abort: PEAR=0x%08lX\n",
+ pearBuffer
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x40000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: Target Abort: PEAR=0x%08lX\n",
+ pearBuffer
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x20000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: System error\n"
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x10000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: Parity error\n"
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x08000000 ) {
+ sprintf( (char *)messageBuffer,
+ "Page fault in NA Bus master transaction\n"
+ " ERRS=0x%08lX, AEAR=0x%08lX\n",
+ errsBuffer,
+ aearBuffer
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+ // S004 ^^^
+
+ KeBugCheckEx(DATA_BUS_ERROR,
+ READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS ),
+ READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->PEAR ),
+ READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->AEAR ),
+ 0 );
+ // S003 ^^^
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpCreatePciStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for PCI operations
+ and connects the intermediate interrupt dispatcher.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ //
+ // Initialize the interrupt dispatcher for PCI err interrupts.
+ //
+
+ PCR->InterruptRoutine[PCI_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpPCIDispatch;
+
+ // Start S002
+ // Set PCI bus interrupt affinity.
+ //
+
+ HalpPCIBusAffinity = PCR->SetMember;
+ // End S002
+
+ //
+ // Enable PCI err interrupt
+ //
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ HalpBuiltinInterruptEnable |= iREN_ENABLE_PCI_ERR_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ return TRUE;
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+
+ memo: This routine enter following condition
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Count up enable count
+ //
+
+ HalpEnablePCIInterruptCount++;
+
+ //
+ // Check interrupt enable count. if interrupt is not already enable, then
+ // enable PCI interrupt.
+ //
+
+ if(HalpEnablePCIInterruptCount == 1){
+ HalpBuiltinInterruptEnable |= iREN_ENABLE_PCI_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ }
+
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI bus specified PCI bus interrupt.
+
+ memo: This routine enter following condition
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Count down enable count
+ //
+
+ if( HalpEnablePCIInterruptCount > 0){
+ --HalpEnablePCIInterruptCount;
+ }
+
+ //
+ // Check interrupt enable count. if count equal zero, then disable
+ // PCI interrupt.
+ //
+
+ if(HalpEnablePCIInterruptCount == 0){
+ HalpBuiltinInterruptEnable &= ~iREN_ENABLE_PCI_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ }
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98pcibs.c b/private/ntos/nthals/halr98mp/mips/r98pcibs.c
new file mode 100644
index 000000000..bca258f3e
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98pcibs.c
@@ -0,0 +1,3180 @@
+#ident "@(#) NEC r98pcibs.c 1.20 95/06/29 16:09:32"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+A001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:33:30 JST 1994
+ - ³Æ¼ïDbgPrint¤ÎÁÞÆþ
+ - r98DoPciTest = 1, r98DoGetDataPrint = 1
+ - r98PCIIoBase¤ÎÊѹ¹(Á´¤Æ1ecd0000¤ËÀßÄê)
+K001 kugimoto@oa2
+ -defined(DBG) chg IF DBG
+K002 kugimoto@oa2
+ -1:r98DoPciTest = 0, r98DoGetDataPrint = 0
+ -2:ASSERT del
+S001 samezima@oa2
+ - disable DbgPrint
+S002 samezima@oa2
+ - Bug. Change potision of #ifdef.
+A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-r98pcibus.c to 1050 ixpcibus.c
+ and named r98pcibs.c
+K003 95/06/29 Kugimoto@oa2
+ -Mips Arc have not BIOS. So Set ROM Enable always.
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+#if defined (_R98_) // A002
+VOID HalpPCISynchronizeTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+#endif // _R98_ A002
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+#if defined (_R98_) // A002
+PCI_CONFIG_HANDLER PCIConfigHandlerTypeR98 = {
+ HalpPCISynchronizeTypeR98,
+ HalpPCIReleaseSynchronzationTypeR98,
+ {
+ HalpPCIReadUlongTypeR98, // 0
+ HalpPCIReadUcharTypeR98, // 1
+ HalpPCIReadUshortTypeR98 // 2
+ },
+ {
+ HalpPCIWriteUlongTypeR98, // 0
+ HalpPCIWriteUcharTypeR98, // 1
+ HalpPCIWriteUshortTypeR98 // 2
+ }
+};
+#endif // _R98_ A002
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+BOOLEAN HalpDoingCrashDump;
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#if defined (_R98_) // A002
+VOID
+HalpTestPciNec (
+ ULONG
+ );
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+ );
+VOID
+HalpOtherTestNec (
+ ULONG
+ );
+ULONG r98DbgCfg = 0;
+ULONG r98DoPciTest = 0; // A001 K002-1
+ULONG r98DoOthrTest = 0;
+ULONG r98DoMultiBytes = 0;
+ULONG r98DoGetDataPrint = 0; // A001 K002-1
+#define r98DbgCfgBits { \
+ if (r98DbgCfg) {\
+ DbgPrint("RegNo=%x ", PciCfgR98->u.bits.RegisterNumber); \
+ DbgPrint("FncNo=%x ", PciCfgR98->u.bits.FunctionNumber); \
+ DbgPrint("SltNo=%x ", PciCfgR98->u.bits.SlotNumber); \
+ DbgPrint("All=%x", PciCfgR98->u.AsULONG); \
+ } \
+ }
+#endif // _R98_ A002
+#else
+#define DBGMSG(a)
+#endif
+
+#if defined(_R98_) // A002
+ULONG r98PCIIoBase[] = { // This must be fixed to flexible configration
+ 0x00000000,
+ 0x1ecd0000,
+ 0x1ecd0000,
+ 0x1ecd0000
+ };
+#endif // _R98_ A002
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ PCI_REGISTRY_INFO tPCIRegInfo; // only for debug A002
+
+#if 0 // A002
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+#endif // only for debug A002
+
+
+#if defined (_R98_) // only for debug A002
+// PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ PCIRegInfo = &tPCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism=0xF; // LR4360 PCI Config Type
+#if DBG // S001, S002
+ DbgPrint("PCI System Get Data:\n");
+ DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision );
+ DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision );
+ DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses );
+ DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism );
+#endif // S001, S002
+#endif // only for debug A002
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+#if DBG
+ HalpTestPci (0);
+#if defined (_R98_) // A002
+ HalpTestPciNec (r98DoPciTest);
+ HalpOtherTestNec (r98DoOthrTest);
+ DbgPrint("HalpInitializePciBus: return\n");
+#endif // _R98_ A002
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+ BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+ BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = 0x10;
+
+ break;
+#if defined (_R98_) // A002
+ case 0xF:
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerTypeR98,
+ sizeof (PCIConfigHandler));
+ BusData->MaxDevice = 0x4;
+ break;
+#endif // _R98_ A002
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+#if DBG //K001 A002
+ if (r98DoGetDataPrint) {
+ DbgPrint("HalpGetPCIData: \n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx\n",
+ BusHandler->BusNumber, Slot.u.bits.DeviceNumber,
+ Slot.u.bits.FunctionNumber, PciData->VendorID,
+ PciData->DeviceID, PciData->RevisionID);
+ if (PciData->u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin);
+ }
+
+ if (PciData->u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine);
+ }
+
+ if (PciData->u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+ {ULONG j;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx\n", j, PciData->u.type0.BaseAddresses[j]);
+ }
+ }}
+ DbgPrint("\n");
+ }
+#endif // A002
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (HIGH_LEVEL,Irql); // A002
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Disable PCI configuration space
+ //
+
+ PciCfg1.u.AsULONG = 0;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
+
+ //
+ // Release spinlock
+ //
+
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql); // A002
+ }
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
+ return sizeof (ULONG);
+}
+
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Initialize Cfg2Addr
+ //
+
+ PciCfg2Addr->u.AsUSHORT = 0;
+ PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
+ PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
+
+ //
+ // Synchronize with type2 config space - type2 config space
+ // remaps 4K of IO space, so we can not allow other I/Os to occur
+ // while using type2 config space.
+ //
+
+ HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ PciCfg2Cse.u.bits.Enable = TRUE;
+ PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
+ PciCfg2Cse.u.bits.Key = 0xff;
+
+ //
+ // Select bus & enable type 2 configuration space
+ //
+
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ //
+ // disable PCI configuration space
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
+
+ //
+ // Restore interrupts, release spinlock
+ //
+
+ HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
+ return sizeof(ULONG);
+}
+
+#if defined (_R98_) // A002
+VOID HalpPCISynchronizeTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98
+ )
+{
+ //
+ // Initialize PciCfgR98
+ //
+
+ PciCfgR98->u.AsULONG = PCI_CONFIG_BASE_ADDRESS;
+//K002-2 ASSERT(Slot.u.bits.DeviceNumber >=0 && Slot.u.bits.DeviceNumber < 4); /* only 0-3 */
+ PciCfgR98->u.bits.SlotNumber = (Slot.u.bits.DeviceNumber & 3);
+ PciCfgR98->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+}
+
+VOID HalpPCIReleaseSynchronzationTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ //
+ // Release spinlock
+ //
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+}
+// LR4360 bug work around for debug time B004
+halplrbug0(){
+ ULONG reg1;
+ reg1 = READ_REGISTER_ULONG(0xb8c0a00c);
+ WRITE_REGISTER_ULONG(0xb8c0a00c,(reg1&0xffbfffff));
+ return reg1;
+}
+
+halplrbug1(ULONG reg1){
+ ULONG err,ERR_VALUE,iRRE;
+ ERR_VALUE = READ_REGISTER_ULONG(0xb8c09008);
+ if(ERR_VALUE & 0x80000000){
+ WRITE_REGISTER_ULONG(0xb8c09008,0x80000000);
+ iRRE = READ_REGISTER_ULONG(0xb8c0a008);
+ WRITE_REGISTER_ULONG(0xb8c0a008,(iRRE & 0xffbfffff));
+ err=1;
+ }else{
+ err=0;
+ }
+ WRITE_REGISTER_ULONG(0xb8c0a00c,reg1);
+ return err;
+}
+
+ULONG
+HalpPCIReadUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfgR98->u.AsULONG + i));
+ if(halplrbug1(reg1)) //B004
+ *Buffer=0xFF;
+#if DBG // B009
+ r98DbgCfgBits("Read Uchar: ",*Buffer);
+#endif
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ ASSERT((Offset % sizeof(USHORT)) == 0);
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ *((PUSHORT)Buffer) = READ_PORT_USHORT ((PUSHORT) (PciCfgR98->u.AsULONG + i));
+ if(halplrbug1(reg1)) //B004
+ *((PUSHORT)Buffer)=0xFFFF;
+#if DBG // B009
+ r98DbgCfgBits("Read Ushort: ",*((PUSHORT)Buffer));
+#endif
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+
+
+ ULONG reg1;
+ reg1=halplrbug0();
+ ASSERT((Offset % sizeof(ULONG)) == 0);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+#if DBG // B008
+ if (r98DoMultiBytes) {
+ HalpPCIReadUcharTypeR98 (BusData, PciCfgR98, Buffer, Offset);
+ HalpPCIReadUcharTypeR98 (BusData, PciCfgR98, Buffer+1, Offset+1);
+ HalpPCIReadUshortTypeR98 (BusData, PciCfgR98, Buffer+2, Offset+2);
+ } else
+#endif
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfgR98->u.AsULONG));
+ if(halplrbug1(reg1))
+ *((PULONG)Buffer)=0xFFFFFFFF;
+#if DBG
+ r98DbgCfgBits("Read Ulong: ",*((PULONG)Buffer));
+#endif
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_UCHAR(((PUCHAR)(PciCfgR98->u.AsULONG + i)), (*((PUCHAR)Buffer)));
+#if DBG
+ r98DbgCfgBits("Write Uchar: ",*((PUCHAR)Buffer));
+#endif
+ halplrbug1(reg1);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ ASSERT((Offset % sizeof(USHORT)) == 0);
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_USHORT(((PULONG)(PciCfgR98->u.AsULONG + i)), (*((PUSHORT)Buffer)));
+#if DBG
+ r98DbgCfgBits("Write Ushort: ",*((PUSHORT)Buffer));
+#endif
+ halplrbug1(reg1);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG reg1;
+ reg1=halplrbug0();
+ ASSERT((Offset % sizeof(ULONG)) == 0);
+
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+#if DBG
+ if (r98DoMultiBytes) {
+ HalpPCIWriteUcharTypeR98 (BusData, PciCfgR98, Buffer, Offset);
+ HalpPCIWriteUcharTypeR98 (BusData, PciCfgR98, Buffer+1, Offset+1);
+ HalpPCIWriteUshortTypeR98 (BusData, PciCfgR98, Buffer+2, Offset+2);
+ } else
+#endif
+ WRITE_PORT_ULONG (((PULONG)(PciCfgR98->u.AsULONG)), (*((PULONG)Buffer)));
+#if DBG
+ r98DbgCfgBits("Write Ulong: ",*((PULONG)Buffer));
+#endif
+ halplrbug1(reg1);
+ return sizeof (ULONG);
+}
+#endif // A002
+
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+#if DBG // A002
+ DbgPrint("HalpAssignPCISlotResources: befor fill to ffff\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ BusNumber, Slot, 0, PciData->VendorID, PciData->DeviceID,
+ PciData->RevisionID);
+ if (PciData->u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin);
+ }
+
+ if (PciData->u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine);
+ }
+
+ if (PciData->u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
+ }
+ }
+ DbgPrint("\n");
+#endif // A002
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+#if 0 //K003
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+#endif
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+#if DBG // A002
+ DbgPrint("HalpAssignPCISlotResources: befor fill to ffff\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ BusNumber, Slot, 0, PciData->VendorID, PciData->DeviceID,
+ PciData->RevisionID);
+ if (PciData->u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin);
+ }
+
+ if (PciData->u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine);
+ }
+
+ if (PciData->u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
+ }
+ }
+ DbgPrint("\n");
+#endif // A002
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+#if DBG // A002
+ DbgPrint("\nCmResourceTypeInterrupt: CmResourceShared\n");
+ DbgPrint("CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE ");
+ DbgPrint("Min=%x Max=%x\n", Descriptor->u.Interrupt.MinimumVector,
+ Descriptor->u.Interrupt.MaximumVector);
+#endif // A002
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+#if defined (_R98_) // A002
+#if DBG
+ DbgPrint("Assigned: Port Address %x\n", CmDescriptor->u.Port.Start.LowPart);
+#endif
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart | r98PCIIoBase[Slot];
+#if DBG
+ DbgPrint("Assign: Port Address %x\n", *BaseAddress[j]);
+#endif
+#else
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+#endif // _R98_ // ADD001
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+#if DBG // A002
+ DbgPrint("Assign: memory Address %x\n", *BaseAddress[j]);
+#endif // _R98_ // ADD001
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#if defined (_R98_) // A002
+VOID
+HalpTestPciNec (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag && bus < 1; bus++) { /* R98 Support Only 1 */
+
+ for (i = 0; i < 4; i++) { /* R98 Support Only 4 slots(include bridge) */
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, j);
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+ DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, 1);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+ PciData.u.type0.InterruptLine = 5; // For trial
+ DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("We got the bridge\n");
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+ DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+ DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+
+
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+)
+{
+ ULONG i, Lines, pchar;
+
+ DbgPrint("----- I/O Data. (%d)byts.\n", Length);
+
+ for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
+ DbgPrint("%08x: ", Lines);
+ for (i = 0; i < 4; pchar += 4, i++) {
+ if (pchar >= Length)
+ break;
+ DbgPrint("%08x ", *Buffer++);
+ }
+ DbgPrint("\n");
+ }
+}
+
+VOID
+HalpOtherTestNec (
+ IN ULONG doOtherTest
+)
+{
+ if (!doOtherTest)
+ return;
+
+
+ DbgPrint("\n\n===== Additional Testing...\n");
+ {
+ CM_EISA_SLOT_INFORMATION EisaSlotInfo;
+ PCM_EISA_SLOT_INFORMATION EisaBuffer;
+ PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo;
+ ULONG slot, funcs, Length;
+
+ #define MAX_EISA_SLOT 4
+
+ DbgPrint("----- Read Eisa Configration:\n");
+ for (slot = 0; slot < MAX_EISA_SLOT; slot++) {
+ Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo));
+ if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) {
+
+ //
+ // The data is messed up since this should never occur
+ //
+
+ break;
+ }
+ Length = sizeof(CM_EISA_SLOT_INFORMATION) +
+ (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions);
+ EisaBuffer = ExAllocatePool(NonPagedPool, Length);
+ HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length);
+ // Print all Eisa Data
+
+ EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION)
+ ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION));
+
+ DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot);
+ DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n",
+ EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags,
+ EisaBuffer->MajorRevision, EisaBuffer->MinorRevision);
+ DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n",
+ EisaBuffer->Checksum,
+ EisaBuffer->NumberFunctions,
+ EisaBuffer->FunctionInformation,
+ EisaBuffer->CompressedId);
+ for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) {
+ DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n",
+ EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1,
+ EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision,
+ EisaFunctionInfo->MajorRevision);
+
+ // EisaFunctionInfo->Selections[26];
+ // EisaFunctionInfo->FunctionFlags;
+ // EisaFunctionInfo->TypeString[80];
+ // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9];
+ // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7];
+ // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4];
+ // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20];
+ // UCHAR EisaFunctionInfo->InitializationData[60];
+ EisaFunctionInfo++;
+ }
+
+ }
+ }
+ DbgBreakPoint ();
+ {
+ #define MEMORY_SPACE 0
+ #define IO_SPACE 1
+ PHYSICAL_ADDRESS cardAddress;
+ ULONG addressSpace = IO_SPACE;
+ PHYSICAL_ADDRESS PhysAddr;
+
+ PhysAddr.LowPart = 0;
+ PhysAddr.HighPart = 0;
+
+
+ DbgPrint("----- \nTranslate Internal Bus Address(I/O): ");
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Internal Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+ }
+ DbgBreakPoint ();
+
+ {
+ KAFFINITY affinity;
+ KIRQL Irql;
+ ULONG Vec;
+
+ DbgPrint("----- \nGetInterruptVector internal\n");
+ Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Eisa\n");
+ Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Isa\n");
+ Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector PCI\n");
+ Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ }
+ DbgBreakPoint ();
+}
+#endif // A002
+
+
+
+#endif
+
diff --git a/private/ntos/nthals/halr98mp/mips/r98pcint.c b/private/ntos/nthals/halr98mp/mips/r98pcint.c
new file mode 100644
index 000000000..d54acb3eb
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98pcint.c
@@ -0,0 +1,384 @@
+#ident "@(#) NEC r98pcint.c 1.13 95/06/29 16:13:28"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ A001 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-r98pciint.c to 1050 ixpciint.c
+ and named r98pcint.c
+
+ K001 '95/6/29 Kugimoto@oa2
+ - PPCIBUSDATA-->PPCIPBUSDATA
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG PciIsaIrq;
+ULONG HalpEisaELCR;
+BOOLEAN HalpDoingCrashDump;
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+#if defined(_R98_) // A001
+ *Affinity = HalpPCIBusAffinity;
+
+ *Irql = INT1_LEVEL;
+ return(PCI_DEVICE_VECTOR);
+
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+#else
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+#ifndef MCA
+ Isa, 0,
+#else
+ MicroChannel, 0,
+#endif
+ BusInterruptLevel ^ IRQXOR,
+ 0,
+ Irql,
+ Affinity
+ );
+#endif //_R98_
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+ On a DBG build we adjust InterruptLine just to ensure driver's
+ don't connect to it without translating it on the PCI bus.
+
+--*/
+{
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R98_) // A001
+ PciData->u.type0.InterruptLine = PciData->u.type0.InterruptPin;
+#else
+ //
+ // Set vector as a level vector. (note: this code assumes the
+ // irq is static and does not move).
+ //
+
+ if (PciData->u.type0.InterruptLine >= 1 &&
+ PciData->u.type0.InterruptLine <= 15) {
+
+ //
+ // If this bit was on the in the PIC ELCR register,
+ // then mark it in PciIsaIrq. (for use in hal.dll,
+ // such that we can assume the interrupt controller
+ // has been properly marked as a level interrupt for
+ // this IRQ. Other hals probabily don't care.)
+ //
+
+ PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine);
+ }
+
+ //
+ // On a PC there's no Slot/Pin/Line mapping which needs to
+ // be done.
+ //
+
+ PciData->u.type0.InterruptLine ^= IRQXOR;
+#endif // _R98_
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R98_) // A001
+ PciNewData->u.type0.InterruptLine = PciOldData->u.type0.InterruptPin;
+#else
+ PciNewData->u.type0.InterruptLine ^= IRQXOR;
+
+#if DBG
+ if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine ||
+ PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) {
+ DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n");
+ DbgBreakPoint ();
+ }
+#endif
+#endif // _R98_
+}
+
+#if !defined(SUBCLASSPCI)
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (PROFILE_LEVEL, Irql); // A001
+ KiAcquireSpinLock (SpinLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (SpinLock);
+ KeLowerIrql (Irql); // A001
+ }
+}
+
+#endif
+
+
+halpPciMemoryLimit=64* 1024*1024; // K001
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+
+ // Start K000 A001
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList;
+ PIO_RESOURCE_LIST InResourceList;
+ ULONG cnt,alt;
+
+ InCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) *pResourceList;
+ InResourceList = InCompleteList->List;
+#if DBG
+ DbgPrint("\n HalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit);
+#endif
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+
+ Descriptor = InResourceList->Descriptors;
+
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+ if(
+ Descriptor->Type==CmResourceTypeMemory
+ && halpPciMemoryLimit < (1024*1024*256-1)
+ ){
+ halpPciMemoryLimit=(
+ ( halpPciMemoryLimit
+ +Descriptor->u.Memory.Length
+ +(Descriptor->u.Memory.Alignment-1)
+ ) & ~ (Descriptor->u.Memory.Alignment-1)
+ )-1;
+
+ if(halpPciMemoryLimit >= (1024*1024*256-1)){
+ halpPciMemoryLimit=(1024*1024*256-1);
+ }
+
+
+#if DBG
+ DbgPrint("\n InHalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit);
+ DbgPrint("\n Length= 0x%x\n",Descriptor->u.Memory.Length);
+ DbgPrint("\n Alignment= 0x%x\n",Descriptor->u.Memory.Alignment);
+#endif
+ }
+ Descriptor++;
+ }
+
+ }
+#if DBG
+ DbgPrint("\n FixHalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit);
+#endif
+ // End of K001 A002
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusHandler->BusAddresses->Memory.Limit = halpPciMemoryLimit; //K001 A002
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+#if defined(_R98_) // A001 K001
+ PPCIPBUSDATA BusData;
+#endif // _R98_
+
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+
+#if defined(_R98_) // A001
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+#else
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == IRQXOR) {
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+#endif // _R98_
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98reg.h b/private/ntos/nthals/halr98mp/mips/r98reg.h
new file mode 100644
index 000000000..d89d560bd
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98reg.h
@@ -0,0 +1,475 @@
+#ident "@(#) NEC r98reg.h 1.8 95/02/20 17:25:49"
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ r98reg.h
+
+Abstract:
+
+ This module is the header file that structure I/O registers for the r98.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S002 6/10 T.Samezima
+ *
+ * Add I/O access macro
+ *
+ ***********************************************************************
+ *
+ * S003 7/5 T.Samezima
+ *
+ * Chg define miss
+ * structure define miss
+ ***********************************************************************
+ *
+ * S004 7/12 T.Samezima
+ *
+ * Chg structure define change
+ *
+ ***********************************************************************
+ *
+ * S005 7/14 T.Samezima
+ *
+ * Chg structure define change
+ *
+ ***********************************************************************
+ *
+ * S006 7/22 T.Samezima
+ *
+ * Add define IOB and SIC register dummy read macro
+ * (correspondence PMC3 bug)
+ *
+ * S007 12/24 T.Samezima
+ * Add define EIFR register define.
+ *
+ * S008 '95.1/7 T.Samezima
+ * Add define EIF0,STS2 register define.
+ *
+ * S009 '95.1/11 T.Samezima
+ * Del miss define
+ *
+ *
+ */
+
+#ifndef _R98REG_
+#define _R98REG_
+
+//
+// Define PMC register structure.
+//
+typedef struct _PMC_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} PMC_REGISTER, *PPMC_REGISTER;
+
+typedef struct _PMC_LARGE_REGISTER {
+// Start S005
+ ULONG High;
+ ULONG Low;
+// End S005
+} PMC_LARGE_REGISTER, *PPMC_LARGE_REGISTER;
+
+typedef volatile struct _PMC_REGISTERS1 {
+ // offset(H)
+ PMC_LARGE_REGISTER IPR; // 0
+ PMC_LARGE_REGISTER MKR; // 8
+ PMC_LARGE_REGISTER IPRR; // 10
+ PMC_REGISTER IPSR; // 18
+ PMC_REGISTER MKRR; // 20
+ PMC_REGISTER MKSR; // 28
+ PMC_REGISTER NMIR; // 30
+ PMC_REGISTER NMIRST; // 38
+ PMC_REGISTER TMSR1; // 40
+ PMC_REGISTER TMR1; // 48
+ PMC_REGISTER TOVCT1; // 50
+ PMC_REGISTER TMCR1; // 58
+ PMC_REGISTER TMSR2; // 60
+ PMC_REGISTER TMR2; // 68
+ PMC_REGISTER TOVCT2; // 70
+ PMC_REGISTER TMCR2; // 78
+ PMC_REGISTER WDTSR; // 80
+ PMC_REGISTER WDT; // 88
+ PMC_REGISTER WDTCR; // 90
+ PMC_REGISTER Reserved1[13]; // 98-F8
+ PMC_REGISTER IntIR; // 100
+ PMC_REGISTER Reserved2; // 108
+ PMC_REGISTER TCIR; // 110
+ PMC_REGISTER Reserved3[29]; // 118-1F8
+ PMC_REGISTER CTAddr; // 200
+ PMC_REGISTER CTData; // 208
+ PMC_REGISTER CTCTL; // 210
+ PMC_REGISTER EVCNT1H; // 218
+ PMC_REGISTER EVCNT1L; // 220
+ PMC_REGISTER EVCNTCR1; // 228
+ PMC_REGISTER Reserved4[26]; // 230-2F8
+ PMC_REGISTER CNFG; // 300
+ PMC_REGISTER STSR; // 308
+ PMC_REGISTER ERRRST; // 310
+ PMC_REGISTER ERR; // 318
+ PMC_REGISTER AERR; // 320
+ PMC_REGISTER ERRMK; // 328
+ PMC_REGISTER TOSR; // 330
+ PMC_REGISTER EVCNT0H; // 338
+ PMC_REGISTER EVCNT0L; // 340
+ PMC_REGISTER EVCNTCR0; // 348
+} PMC_REGISTERS1, *PPMC_REGISTERS1;
+
+typedef volatile struct _PMC_REGISTERS2 {
+ // offset(H)
+ PMC_REGISTER RRMT0H; // 0
+ PMC_REGISTER RRMT0L; // 8
+ PMC_REGISTER RRMT1H; // 10
+ PMC_REGISTER RRMT1L; // 18
+ PMC_REGISTER RRMT2H; // 20
+ PMC_REGISTER RRMT2L; // 28
+ PMC_REGISTER RRMT3H; // 30
+ PMC_REGISTER RRMT3L; // 38
+ PMC_REGISTER RRMT4H; // 40
+ PMC_REGISTER RRMT4L; // 48
+ PMC_REGISTER RRMT5H; // 50
+ PMC_REGISTER RRMT5L; // 58
+ PMC_REGISTER RRMT6H; // 60
+ PMC_REGISTER RRMT6L; // 68
+ PMC_REGISTER RRMT7H; // 70
+ PMC_REGISTER RRMT7L; // 78
+ PMC_REGISTER Reserved1[2]; // 80-88
+ PMC_REGISTER DISCON; // 90
+ PMC_REGISTER Reserved2[3]; // 98-a8
+ PMC_REGISTER EADRH; // b0
+ PMC_REGISTER EADRL; // b8
+ PMC_REGISTER Reserved3[2]; // c0-c8
+ PMC_REGISTER RTYCNT; // d0
+} PMC_REGISTERS2, *PPMC_REGISTERS2;
+
+//
+// Define pointer to PMC registers.
+//
+#define PMC_GLOBAL_CONTROL1 ((volatile PPMC_REGISTERS1)(KSEG1_BASE | PMC_PHYSICAL_BASE1))
+#define PMC_GLOBAL_CONTROL2 ((volatile PPMC_REGISTERS2)(KSEG1_BASE | PMC_PHYSICAL_BASE2))
+/* Start S002 */
+#define PMC_GLOBAL_CONTROL1_OR(x) ((volatile PPMC_REGISTERS1)(KSEG1_BASE | PMC_PHYSICAL_BASE1 | (x) ))
+#define PMC_GLOBAL_CONTROL2_OR(x) ((volatile PPMC_REGISTERS2)(KSEG1_BASE | PMC_PHYSICAL_BASE2 | (x) ))
+/* End S002 */
+/* Start S001 */
+#define PMC_CONTROL1 ((volatile PPMC_REGISTERS1)((ULONG)PMC_GLOBAL_CONTROL1 | PMC_LOCAL_OFFSET))
+#define PMC_CONTROL2 ((volatile PPMC_REGISTERS2)((ULONG)PMC_GLOBAL_CONTROL2 | PMC_LOCAL_OFFSET))
+/* End S001 */
+/* Start S002 */
+#define PMC_CONTROL1_OR(x) ((volatile PPMC_REGISTERS1)((ULONG)PMC_GLOBAL_CONTROL1 | PMC_LOCAL_OFFSET | (x) ))
+#define PMC_CONTROL2_OR(x) ((volatile PPMC_REGISTERS2)((ULONG)PMC_GLOBAL_CONTROL2 | PMC_LOCAL_OFFSET | (x) ))
+/* End S002 */
+
+/* Start S006 */
+//
+// Define dummy read macro. This macro use to not lead to time out of PMC
+//
+
+#define IOB_DUMMY_READ READ_REGISTER_ULONG(PMC_DUMMY_READ_ADDR)
+#define SIC_DUMMY_READ READ_REGISTER_ULONG(PMC_DUMMY_READ_ADDR)
+/* End S006 */
+
+//
+// Define IOB register structure.
+//
+typedef struct _IOB_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} IOB_REGISTER, *PIOB_REGISTER;
+
+typedef volatile struct _IOB_REGISTERS {
+ // offset(H)
+ IOB_REGISTER AIMR; // 0
+ IOB_REGISTER AII0; // 8
+ IOB_REGISTER AII1; // 10
+ IOB_REGISTER AII2; // 18
+ IOB_REGISTER AII3; // 20
+ IOB_REGISTER AISR; // 28
+ IOB_REGISTER ITRR; // 30
+ IOB_REGISTER ADC0; // 38
+ IOB_REGISTER ADC1; // 40
+ IOB_REGISTER ADC2; // 48
+ IOB_REGISTER ADC3; // 50
+ IOB_REGISTER AMMD; // 58
+ IOB_REGISTER ANMD; // 60
+ IOB_REGISTER IERR; // 68
+ IOB_REGISTER IEMR; // 70
+ IOB_REGISTER IEER; // 78
+ IOB_REGISTER AMAL; // 80
+ IOB_REGISTER AMAH; // 88
+ IOB_REGISTER ANAL; // 90
+ IOB_REGISTER ANAH; // 98
+ IOB_REGISTER AMRC; // a0
+ IOB_REGISTER ANRC; // a8
+ IOB_REGISTER AMRT; // b0
+ IOB_REGISTER ANMT; // b8
+ IOB_REGISTER ANST; // c0
+ IOB_REGISTER Reserved1[7]; // c8-f8
+ IOB_REGISTER ADG0; // 100
+ IOB_REGISTER ADG1; // 108
+ IOB_REGISTER CNTD; // 110
+ IOB_REGISTER CNTE; // 118
+ IOB_REGISTER CABS; // 120
+ IOB_REGISTER CAWS; // 128
+ IOB_REGISTER CTGL; // 130
+ IOB_REGISTER CTGH; // 138
+ IOB_REGISTER ARMS; // 140
+ IOB_REGISTER ARML; // 148
+ IOB_REGISTER ARMH; // 150
+ IOB_REGISTER Reserved2[21]; // 158-1f8
+ IOB_REGISTER SCFR; // 200
+ IOB_REGISTER MPER; // 208
+ IOB_REGISTER EIMR; // 210
+ IOB_REGISTER EIFR; // 218
+ IOB_REGISTER Reserved3[28]; // 220-2f8
+// DCDW; // 300
+// IOB_REGISTER ATCNF; // 400
+} IOB_REGISTERS, *PIOB_REGISTERS;
+
+// S007 vvv
+//
+// Define EIFR register
+//
+typedef struct _EIFR_REGISTER {
+ ULONG Reserved : 21;
+ ULONG MPDISCN : 1;
+ ULONG IOBERR : 1;
+ ULONG Reserved2 : 1;
+ ULONG EISANMI : 1;
+ ULONG LRERR : 1;
+ ULONG SIC1ERR : 1;
+ ULONG SIC0ERR : 1;
+ ULONG PMC3ERR : 1;
+ ULONG PMC2ERR : 1;
+ ULONG PMC1ERR : 1;
+ ULONG PMC0ERR : 1;
+} EIFR_REGISTER, *PEIFR_REGISTER;
+// S007 ^^^
+
+//
+// Define pointer to IOB registers.
+//
+#define IOB_CONTROL ((volatile PIOB_REGISTERS)(KSEG1_BASE | IOB_PHYSICAL_BASE))
+
+
+//
+// Define SIC register structure.
+//
+typedef struct _SIC_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} SIC_REGISTER, *PSIC_REGISTER;
+
+typedef volatile struct _SIC_ERR_REGISTERS {
+ // offset(H)
+ SIC_REGISTER EIF0; // 0
+ SIC_REGISTER EIF1; // 8
+ SIC_REGISTER CKE0; // 10
+ SIC_REGISTER CKE1; // 18
+ SIC_REGISTER SECT; // 20
+ SIC_REGISTER Reserved; // 28
+ SIC_REGISTER STS1; // 30
+ SIC_REGISTER STS2; // 38
+ SIC_REGISTER RSRG; // 40
+} SIC_ERR_REGISTERS, *PSIC_ERR_REGISTERS;
+
+typedef volatile struct _SIC_DATA_REGISTERS {
+ // offset(H)
+ SIC_REGISTER DPCM; // 0
+ SIC_REGISTER DSRG; // 8
+ SIC_REGISTER SDLM; // 10
+// SIC_REGISTER Reserved[3]; // 18-28 // S009
+// SIC_REGISTER SDCR; // 30 // S009
+} SIC_DATA_REGISTERS, *PSIC_DATA_REGISTERS;
+
+// S008 vvv
+//
+// Define EIF0 register
+//
+typedef struct _EIF0_REGISTER {
+ ULONG Reserved : 2;
+ ULONG EXTD0MBE : 1;
+ ULONG EXTD0SBE : 1;
+ ULONG Reserved1 : 1;
+ ULONG INTD0PTE : 1;
+ ULONG INTD0MBE : 1;
+ ULONG INTD0SBE : 1;
+ ULONG ICEC : 1;
+ ULONG CPEC : 1;
+ ULONG APEC : 1;
+ ULONG RE1C : 1;
+ ULONG RE0C : 1;
+ ULONG SREC : 1;
+ ULONG RSEC : 1;
+ ULONG DTEJ : 1;
+ ULONG RSEJ : 1;
+ ULONG USYC : 1;
+ ULONG Reserved2 : 4;
+ ULONG IRMC : 1;
+ ULONG IRRC : 1;
+ ULONG Reserved3 : 3;
+ ULONG SBE : 1;
+ ULONG DPCG : 1;
+ ULONG APCG : 1;
+ ULONG MPRG : 1;
+ ULONG SWRG : 1;
+} EIF0_REGISTER, *PEIF0_REGISTER;
+
+//
+// Define STS2 register
+//
+typedef struct _STS2_REGISTER {
+ ULONG COL0_9 : 10;
+ ULONG COL10 : 1;
+ ULONG LOW0_9 : 10;
+ ULONG LOW10 : 1;
+ ULONG Reserved : 2;
+ ULONG RW : 1;
+ ULONG EXTMBE0 : 1;
+ ULONG EXTSBE0 : 1;
+ ULONG MBE0 : 1;
+ ULONG SBE0 : 1;
+ ULONG SIMN : 1;
+ ULONG ARE : 2;
+} STS2_REGISTER, *PSTS2_REGISTER;
+// S008 ^^^
+
+//
+// Define pointer to SIC registers.
+//
+#define SIC_ERR_CONTROL ((volatile PSIC_ERR_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_ERR_OFFSET))
+#define SIC_DATA_CONTROL ((volatile PSIC_DATA_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_DATA_OFFSET))
+/* Start S002 */
+#define SIC_ERR_CONTROL_OR(x) ((volatile PSIC_ERR_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_ERR_OFFSET | (x) ))
+#define SIC_DATA_CONTROL_OR(x) ((volatile PSIC_DATA_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_DATA_OFFSET | (x) ))
+/* End S002 */
+
+//
+// Define LR4360 register structure.
+//
+typedef volatile struct _LR_REGISTERS1 {
+ /* Start S004 */
+ // offset(H)
+ ULONG RSTC; // 0x0
+ ULONG DPRC; // 0x4
+ ULONG Reserved[1024]; // 0x8-0x1004
+ ULONG ERRS; // 0x1008
+ /* End S004 */
+} LR_REGISTERS1, *PLR_REGISTERS1;
+
+typedef volatile struct _LR_REGISTERS2 {
+ // offset(H)
+ ULONG iRPo; // 0
+ ULONG iRED; // 4
+ ULONG iRRE; // 8
+ ULONG iREN; // c
+ ULONG iRSF; // 10
+ ULONG iPoE; // 14
+ ULONG Reserved0[2]; // 18-1c
+ ULONG iFGE; // 20
+ ULONG iFGi; // 24
+ ULONG iRCS0; // 28
+ ULONG iRCS1; // 2c
+} LR_REGISTERS2, *PLR_REGISTERS2;
+
+typedef volatile struct _LR_PCI_DEVICE_REGISTERS {
+ // offset(H)
+ ULONG PTBAR0; // 0
+ ULONG PTBAR1; // 4
+ ULONG PTBAR2; // 8
+ ULONG PTBAR3; // c
+ ULONG PTBAR4; // 10
+ ULONG PTBAR5; // 14
+ ULONG PTBAR6; // 18
+ ULONG PTBAR7; // 1c
+ ULONG PTSZR; // 20
+ ULONG TPASZR; // 24
+ ULONG TFLR; // 28
+ ULONG PABAR; // 2c
+ ULONG AEAR; // 30
+ ULONG PEAR; // 34
+} LR_PCI_DEVICE_REGISTERS, *PLR_PCI_DEVICE_REGISTERS;
+
+//
+// Define Bbus LR4360 DMA channel register structure.
+//
+typedef struct _DMA_CHANNEL { // offset(H)
+ ULONG CnCF; // 0
+ ULONG CnDF; // 4
+ ULONG CnDC; // 8
+ ULONG Reserved1; // c
+ ULONG CnMA; // 10
+ ULONG CnBC; // 14
+ ULONG CnAK; // 18
+ ULONG CnFA; // 1c
+ ULONG CnCA; // 20
+} DMA_CHANNEL, *PDMA_CHANNEL;
+
+//
+// Define Device Channel # DMA Configuration register (CnDF register)
+//
+typedef struct _LR_DMA_CONFIG {
+ ULONG SWAP :1;
+ ULONG ASET :1;
+ ULONG ACKP :1;
+ ULONG REQP :1;
+ ULONG EOPCF :2;
+ ULONG EOPHO :1;
+ ULONG BUOFF :1;
+ ULONG EDEDE :1;
+ ULONG EXEDi :1;
+ ULONG iNEDE :1;
+ ULONG iNEDi :1;
+ ULONG CPUTi :1;
+ ULONG Reserved1 :3;
+ ULONG TMODE :2;
+ ULONG Reserved2 :14;
+} LR_DMA_CONFIG,*PLR_DMA_CONFIG;
+
+//
+// Define Device Channel # DMA Control register (CnDC register)
+//
+typedef struct _LR_DMA_CONTROL {
+ ULONG REQiE :1;
+ ULONG REQii :1;
+ ULONG REQWE :1;
+ ULONG REQiS :1;
+ ULONG MEMWT :1;
+ ULONG MEMWE :1;
+ ULONG Reserved1:2;
+ ULONG EXEDS :1;
+ ULONG iNEDS :1;
+ ULONG CREQS :1;
+ ULONG CERRS :1;
+ ULONG BFiFo :4;
+ ULONG FiFoV :1;
+ ULONG FiFoD :1;
+ ULONG FiFoF :1;
+ ULONG CHACOM :1;
+ ULONG Reserved2 :12;
+} LR_DMA_CONTROL,*PLR_DMA_CONTROL;
+
+//
+// Define pointer to LR4360 registers.
+//
+#define LR_CONTROL1 ((volatile PLR_REGISTERS1)(KSEG1_BASE | LR_PHYSICAL_CMNBASE1))
+#define LR_CONTROL2 ((volatile PLR_REGISTERS2)(KSEG1_BASE | LR_PHYSICAL_CMNBASE2))
+#define LR_PCI_DEV_REG_CONTROL ((volatile PLR_PCI_DEVICE_REGISTERS)(KSEG1_BASE | LR_PHYSICAL_PCI_DEV_REG_BASE))
+
+#endif // _R98REG_
diff --git a/private/ntos/nthals/halr98mp/mips/tga.h b/private/ntos/nthals/halr98mp/mips/tga.h
new file mode 100644
index 000000000..a8db1925a
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/tga.h
@@ -0,0 +1,101 @@
+#ident "@(#) NEC tga.h 1.1 94/11/29 14:09:17"
+/*++
+
+Module Name:
+
+ tga.h
+
+Abstract:
+
+ This module contains the register definitions for the TGA (DEC21030)
+
+Author:
+
+ T.Katoh create-data 1994/11/11
+
+Revision Histort:
+
+--*/
+
+/*
+ * D001 1994.11.29 T.Katoh
+ *
+ * Del: non-used definitions
+ * Chg: TGA_DSP_BUF_OFFSET value
+ * Add: VIDEO_BASE definition
+ */
+
+// TGA Core Space Map offset for 8-bpp Frame Buffers
+
+#define TGA_REG_SPC_OFFSET 0x00100000
+#define TGA_DSP_BUF_OFFSET 0x00200000 // D001
+
+// TGA register offsets, organized by functionality.
+
+#define PLANE_MASK 0x00000028
+#define ONE_SHOT_PIXEL_MASK 0x0000002C
+#define MODE 0x00000030
+#define RASTER_OP 0x00000034
+#define DEEP 0x00000050
+#define BLK_COLOR_R0 0X00000140
+#define BLK_COLOR_R1 0X00000144
+#define H_CONT 0x00000064
+#define V_CONT 0x00000068
+#define VIDEO_BASE 0x0000006c // D001
+#define VIDEO_VALID 0x00000070
+#define RAMDAC_SETUP 0x000000C0
+#define EEPROM_WRITE 0x000001e0
+#define CLOCK 0x000001e8
+#define RAMDAC_DATA 0X000001f0
+#define COMMAND_STATUS 0x000001f8
+
+// Initiate Palette Data
+
+#define VGA_INI_PALETTE_BLACK_R 0x00
+#define VGA_INI_PALETTE_BLACK_G 0x00
+#define VGA_INI_PALETTE_BLACK_B 0x00
+#define VGA_INI_PALETTE_RED_R 0xAA
+#define VGA_INI_PALETTE_RED_G 0x00
+#define VGA_INI_PALETTE_RED_B 0x00
+#define VGA_INI_PALETTE_GREEN_R 0x00
+#define VGA_INI_PALETTE_GREEN_B 0xAA
+#define VGA_INI_PALETTE_GREEN_G 0x00
+#define VGA_INI_PALETTE_YELLOW_R 0xAA
+#define VGA_INI_PALETTE_YELLOW_G 0xAA
+#define VGA_INI_PALETTE_YELLOW_B 0x00
+#define VGA_INI_PALETTE_BLUE_R 0x00
+#define VGA_INI_PALETTE_BLUE_G 0x00
+#define VGA_INI_PALETTE_BLUE_B 0xAA
+#define VGA_INI_PALETTE_MAGENTA_R 0xAA
+#define VGA_INI_PALETTE_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_MAGENTA_B 0xAA
+#define VGA_INI_PALETTE_CYAN_R 0x00
+#define VGA_INI_PALETTE_CYAN_G 0xAA
+#define VGA_INI_PALETTE_CYAN_B 0xAA
+#define VGA_INI_PALETTE_WHITE_R 0xAA
+#define VGA_INI_PALETTE_WHITE_G 0xAA
+#define VGA_INI_PALETTE_WHITE_B 0xAA
+#define VGA_INI_PALETTE_HI_BLACK_R 0x00
+#define VGA_INI_PALETTE_HI_BLACK_G 0x00
+#define VGA_INI_PALETTE_HI_BLACK_B 0x00
+#define VGA_INI_PALETTE_HI_RED_R 0xFF
+#define VGA_INI_PALETTE_HI_RED_G 0x00
+#define VGA_INI_PALETTE_HI_RED_B 0x00
+#define VGA_INI_PALETTE_HI_GREEN_R 0x00
+#define VGA_INI_PALETTE_HI_GREEN_G 0xFF
+#define VGA_INI_PALETTE_HI_GREEN_B 0x00
+#define VGA_INI_PALETTE_HI_YELLOW_R 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_G 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_B 0x00
+#define VGA_INI_PALETTE_HI_BLUE_R 0x00
+#define VGA_INI_PALETTE_HI_BLUE_G 0x00
+#define VGA_INI_PALETTE_HI_BLUE_B 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_R 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_HI_MAGENTA_B 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_R 0x00
+#define VGA_INI_PALETTE_HI_CYAN_G 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_B 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_R 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_G 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_B 0xFF
diff --git a/private/ntos/nthals/halr98mp/mips/x86bios.c b/private/ntos/nthals/halr98mp/mips/x86bios.c
new file mode 100644
index 000000000..4d65ad4e7
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/x86bios.c
@@ -0,0 +1,2 @@
+#pragma comment(exestr, "@(#) x86bios.c 1.3 95/06/19 11:44:39 nec")
+#include <..\..\halfxs\mips\x86bios.c>
diff --git a/private/ntos/nthals/halr98mp/mips/xxcalstl.c b/private/ntos/nthals/halr98mp/mips/xxcalstl.c
new file mode 100644
index 000000000..1ae682434
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxcalstl.c
@@ -0,0 +1,290 @@
+#ident "@(#) NEC xxcalstl.c 1.4 94/10/17 11:57:45"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/16-5/13 T.Samezima
+ *
+ * change HalpClockInterrupt0 vector
+ * HalpProfileInterrupt vector
+ *
+ * add PROFILE interrupt control
+ *
+ * del interrupt clear
+ * '#if defined(R3000)' with content
+ * only '#if defined(R4000)'
+ *
+ ***********************************************************************
+ *
+ * S002 94.03/16-5/13 T.Samezima
+ *
+ * Chg Designate member of structures
+ *
+ * S003 94.08/22 N.Kugimoto
+ * Chg Number 0 Bit Position is MSB (64Bit). So decremenet from 0x3f.
+ */
+
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ /* Start S001 */
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt0;
+ /* End S001 */
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ /* Start S001 */
+ PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO ); // S002 S003
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->TMCR2.Long, 0x3 ); // S002
+ /* End S001 */
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+ HalpWriteCompareRegisterAndClear(0);
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxclock.c b/private/ntos/nthals/halr98mp/mips/xxclock.c
new file mode 100644
index 000000000..51559bd63
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxclock.c
@@ -0,0 +1,131 @@
+#ident "@(#) NEC xxclock.c 1.4 94/10/23 20:39:13"
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * M001 94.05/31 T.Samezima
+ *
+ * add check timer increment value
+ * set value use from HalpClockInterrupt1
+ *
+ * change increment unit from 1ms to 1us
+ *
+ * S002 '94.10/14 T.Samezima
+ * chg interval change flag
+ *
+ * S003 '94.10/23 T.Samezima
+ * chg variable size from ULONG to UCHAR
+ *
+ *
+ */
+
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+/* Start M001 */
+UCHAR HalpChangeIntervalFlg[4]={0, 0, 0, 0}; // S003
+ULONG HalpChangeIntervalCount;
+/* End M001 */
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ /* Start M001 */
+ //
+ // If the specified time increment value is less that the minimum value
+ // or greater than the maximum value ,then set the time increment value
+ // to the minimum or maximum as appropriate.
+ //
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+
+ } else if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+ /* End S001 */
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ /* Start M001 */
+ NextIntervalCount = DesiredIncrement / 10;
+ NewTimeIncrement = NextIntervalCount * 10;
+ /* End M001 */
+ HalpNextIntervalCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ /* Start M001 */
+ HalpChangeIntervalFlg[1] = 0xff; // S002
+ HalpChangeIntervalFlg[2] = 0xff; // S002
+ HalpChangeIntervalFlg[3] = 0xff; // S002
+ HalpChangeIntervalCount = HalpNextIntervalCount;
+ /* End M001 */
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxidle.s b/private/ntos/nthals/halr98mp/mips/xxidle.s
new file mode 100644
index 000000000..e202c795c
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxidle.s
@@ -0,0 +1,76 @@
+// "@(#) NEC xxidle.s 1.2 94/10/17 11:59:42"
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halr98mp/mips/xxinithl.c b/private/ntos/nthals/halr98mp/mips/xxinithl.c
new file mode 100644
index 000000000..917e97d75
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxinithl.c
@@ -0,0 +1,660 @@
+#ident "@(#) NEC xxinithl.c 1.12 95/06/19 11:45:28"
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/09 T.Samezima
+ *
+ * add Spinlock HalpEifInterruptLock
+ *
+ * del only '#if defined(_DUO_)'
+ *
+ * K001 '94.5/30 (Mon) N.Kugimoto
+ * Add allocate contigus phys memory for Internal device
+ * use buffer.
+ *
+ * S002 '94.6/02 T.Samezima
+ *
+ * Add call HalpRegisterNmi
+ *
+ * S003 '94.8/25 T.Samezima
+ *
+ * Chg Set Io address before initialize interrupt
+ *
+ * S004 '94.9/26 T.Samezima
+ *
+ * Add Merge PCI Source Code
+ *
+ * K002 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ * K003 94/10/13 N.Kugimoto
+ * Chg HalpBugCheckBuffer -->HalpEifRegisterBuffer
+ * -1 Chg HalpBusError logic change
+ * K004 94/10/13 N.Kugimoto
+ *
+ * S005 '94.12/08 T.Samezima
+ * Add Disable NMI.
+ *
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - marge 1050 halx86
+ * S006 1995/7/17 T.Samezima
+ * Del Init header.
+ */
+
+#include "halp.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+/* Start S001 */
+KSPIN_LOCK HalpEifInterruptLock;
+/* End S001 */
+
+
+// K002 vvvvv
+// Define bug check information buffer and callback record.
+//
+#if !defined(_R98_) //K003
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG FailedAddress;
+ ULONG DiagnosticLow;
+ ULONG DiagnosticHigh;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+#endif
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+// K002^^^^
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ //K002 vvvv
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+ //K002 ^^^^
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ PCR->DataBusError = HalpBusError; //K002
+ PCR->InstructionBusError = HalpBusError; //K002
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+
+ /* Start S002 */
+ //
+ // Set NMI interrupt service routine
+ //
+
+#if !defined(DISABLE_NMI) //
+ HalpRegisterNmi();
+#endif
+ /* End S002 */
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ // A002
+ // Set DMA I/O coherency attributes.
+ //
+ KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP);
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ /* Start S001 */
+ KeInitializeSpinLock(&HalpEifInterruptLock);
+ /* End S001 */
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ // K001 Start
+ // For Internal Device use buffer
+ //
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+
+ } // End of K001
+ // K002 vvvv
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+#if defined(_R98_) //K003
+ HalpEifRegisterBuffer,
+#else
+ &HalpBugCheckBuffer,
+#endif
+ 41*4, //K003
+ &HalpComponentId[0]);
+
+ // K002 ^^^^
+
+ }
+
+ // Start S003
+#if defined(_R98_)
+ //
+ // Initialize I/O address
+ //
+
+ HalpMapIoSpace();
+#endif
+ // End S003
+
+ //
+ // Initialize interrupts
+ //
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ HalpRegisterInternalBusHandlers (); // A002
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ // Start S003
+#if !defined(_R98_)
+ HalpMapIoSpace();
+#endif
+ // End S003
+ HalpCalibrateStall();
+ HalpCreateDmaStructures();
+
+ // K002 vvvvv
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+ HalpInitializeX86DisplayAdapter();
+
+ // K002 ^^^^^
+
+ return TRUE;
+ }
+ }
+}
+
+//K002 vvvv
+// no change
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if !defined(_R98_) //K003
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+#if defined(_DUO_)
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+#endif //_R98_
+ return;
+}
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG DiagnosticHigh;
+ ULONG DiagnosticLow;
+#if !defined(_R98_) //K003-1
+ ULONG FailedAddress;
+
+
+ //
+ // Bug check specifying the exception code, the virtual address, the
+ // failed memory address, and either the ECC diagnostic registers or
+ // the parity diagnostic registers depending on the platform.
+ //
+
+#if defined(_DUO_)
+
+ DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+ DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+ DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+#else //_R98_
+ ULONG AllError;
+ DiagnosticLow =READ_REGISTER_ULONG(&( PMC_CONTROL2 )->EADRL.Long);
+ DiagnosticHigh =READ_REGISTER_ULONG(&( PMC_CONTROL2 )->EADRH.Long);
+ AllError =READ_REGISTER_ULONG(&( PMC_CONTROL1 )->AERR.Long); //K003
+#endif
+
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+#if defined(_R98_) //K003
+ AllError,
+#else
+ FailedAddress,
+#endif
+ DiagnosticLow,
+
+ DiagnosticHigh);
+
+ return FALSE;
+}
+
+//K002 ^^^^
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxinitnt.c b/private/ntos/nthals/halr98mp/mips/xxinitnt.c
new file mode 100644
index 000000000..ad3750771
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxinitnt.c
@@ -0,0 +1,556 @@
+#ident "@(#) NEC xxinitnt.c 1.18 95/03/17 11:59:37"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * L001 94.03/22-5/13 T.Samezima
+ *
+ * add control of Eif interrupt.
+ * make table of change from iRRE bit number to NABus code.
+ * make table of arbitration table and arbitration pointer.
+ * make variable for access of registers.
+ * connect the timer interrupt service routine.
+ * clear unknown interrupt counter
+ *
+ * del only '#if defined(_DUO_)'
+ * '#if defined(_JAZZ_)' with content
+ * HalpCountInterrupt()
+ *
+ * change interrupt control
+ * various vector of interrupt service routine
+ *
+ ***********************************************************************
+ *
+ * S002 94.5/17 T.Samezima
+ *
+ * del Arbitration table
+ *
+ ***********************************************************************
+ *
+ * S003 94.6/10-14 T.Samezima
+ *
+ * del Compile err
+ *
+ ***********************************************************************
+ *
+ * S004 94.7/7 T.Samezima
+ *
+ * Chg Use UNKNOWN_COUNT_BUF_LEN to max
+ * for HalpUnknownInterruptCount
+ *
+ ***********************************************************************
+ *
+ * S005 94.7/7 T.Samezima
+ *
+ * Del move interrupt arbitration pointer to r98dspt.c
+ *
+ ***********************************************************************
+ *
+ * S006 94.7/23 T.Samezima
+ *
+ * Add Enable EIF interrupt on SIC.
+ *
+ ***********************************************************************
+ *
+ * S007 94.8/22 T.Samezima on SNES
+ *
+ * Chg Register buffer size from USHORT to ULONG
+ * Value of set to MKSR register
+ * Condition change
+ *
+ * Add Clear interrupt pending bit on edge level interrupt
+ *
+ * Del Move EISA NMI enable logic to HalpCreateEisaStructure()
+ *
+ ***********************************************************************
+ *
+ * S008 94.9/5 T.Samezima
+ *
+ * Add Institute number of repeat for interrupt clear loop
+ *
+ ***********************************************************************
+ *
+ * S009 94.9/16 T.Samezima
+ *
+ * Chg Only CPU#0 on I/O Initerrupt clear
+ *
+ ***********************************************************************
+ *
+ * S00a 94.10/14 T.Samezima
+ *
+ * Fix Version Up at build807
+ * -Move Int1 interrupt enable to allstart.c
+ *
+ * S00b 94.10/18 T.Samezima
+ * Chg Enable interrupt on MKR register only exist device,
+ *
+ * S00c 94.12/06 T.Samezima
+ * Bug Disable ECC 1bit error interrupt.
+ *
+ * S00d 94.12/06 T.Samezima
+ * Add Disable NMI
+ *
+ * S00e 95.01/10 T.Samezima
+ * Add Enable ECC 1bit error interrupt
+ * Rewrite cycle start on ecc 1bit error
+ *
+ * S00f 95.01/24 T.Samezima
+ * Add Disable rewrite cycle on ecc 1bit error
+ *
+ * S010 95.03/13 T.Samezima
+ * Add Enable HW cache flush.
+ *
+ */
+
+#include "halp.h"
+#include "eisa.h" // S003
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+
+#endif
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+ULONG HalpBuiltinInterruptEnable; // S007
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+/* Start L001 */
+//
+// Define table of change from iRRE bit number to NABus code
+//
+ULONG HalpNaBusCodeTable[] = {0x8000, 0x0010, // iRRE bit0,1
+ 0x0006, 0x0000, // iRRE bit2,3
+ 0x0002, 0x0002, // iRRE bit4,5
+ 0x000a, 0x000a, // iRRE bit6,7
+ 0x0008, 0x000c, // iRRE bit8,9
+ 0x8000, 0x8000, // iRRE bit10,11
+ 0x8000, 0x8000, // iRRE bit12,13
+ 0x8000, 0x8000, // iRRE bit14,15
+ 0x8000, 0x0004, // iRRE bit16,17
+ 0x8000, 0x8000, // iRRE bit18,19
+ 0x8000, 0x8000, // iRRE bit20,21
+ 0x000c, 0x8000, // iRRE bit22,23
+ 0x8000, 0x8000, // iRRE bit24,25
+ 0x8000, 0x8000, // iRRE bit26,27
+ 0x8000, 0x8000, // iRRE bit28,29
+ 0x8000, 0x8000 }; // iRRE bit30,31
+
+//
+// Define table of order of interrupt arbitration
+//
+
+ULONG HalpUnknownInterruptCount[UNKNOWN_COUNT_BUF_LEN]; // S004
+
+/* End L001*/
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Jazz or Duo MIPS system.
+
+ N.B. This function is only called during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ USHORT DataShort;
+ ULONG DataLong;
+ ULONG Index;
+ PKPRCB Prcb;
+ /* Start L001 */
+ ULONG pmcRegisterAddr;
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG bitCount;
+ ULONG buffer;
+ ULONG buffer2; // S006
+ UCHAR charBuffer;
+ LONG repeatCounter; // S008
+ /* End L001 */
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ /* Start L001 */
+ //
+ // All interrupt disables.
+ //
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ pmcRegisterUpperPart = MKR_DISABLE_ALL_INTERRUPT_HIGH;
+ pmcRegisterLowerPart = MKR_DISABLE_ALL_INTERRUPT_LOW;
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ //
+ // If processor 0 is being initialized, then set all device
+ // interrupt disables.
+ //
+
+ if (Prcb->Number == 0) {
+ HalpBuiltinInterruptEnable = iREN_DISABLE_ALL_INTERRUPT;
+
+ for (Index = 0; Index < UNKNOWN_COUNT_BUF_LEN; Index += 1) { // S004
+ HalpUnknownInterruptCount[Index] = 0;
+ }
+// } // S009
+ /* End L001 */
+
+ //
+ // Disable individual device interrupts and make sure no device interrupts
+ // are pending.
+ //
+
+ /* Start L001 */
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long,
+ EIMR_DISABLE_ALL_EIF );
+
+ repeatCounter = 0; // S008
+
+ while( ((DataLong = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE) & iRRE_MASK) != 0) &&
+ (++repeatCounter < 16) ) { // S008
+ for( bitCount = 0 ; bitCount <= 31 ; bitCount++ ) {
+ if( (DataLong & ( 1 << bitCount )) != 0) {
+ // Start S007
+ if( bitCount < 15 ){
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF,
+ ( 1 << bitCount ) );
+ }
+ // End S007
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AIMR.Long,
+ HalpNaBusCodeTable[bitCount] );
+ }
+ }
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF,
+ iRSF_CLEAR_INTERRUPT );
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->IPRR ); // S003
+ pmcRegisterUpperPart = 0x0;
+ pmcRegisterLowerPart = 0xffffffff;
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ }
+ /* End L001 */
+
+ HalpBuiltinInterruptEnable |= 0x10; // S010
+
+ //
+ // If processor 0 is being initialized, then enable device interrupts.
+ //
+
+// if (Prcb->Number == 0) { // S009
+ /* Start L001 */
+ //
+ // Enable INT0-1 interrupt on PMC
+ //
+
+ /* Start S003 */
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII0.Long,
+ AII_INIT_DATA );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long,
+ AII_INIT_DATA );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long,
+ AII_INIT_DATA );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII3.Long,
+ AII_INIT_DATA );
+ /* End S003 */
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart
+ | MKR_INT0_DEVICE_ENABLE_LOW // S00b
+// | MKR_INT1_DEVICE_ENABLE_LOW // S00a, S00b
+ | MKR_INT2_DEVICE_ENABLE_LOW // S00b
+ ); // S003
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+// DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+// DataLong |= ENABLE_DEVICE_INTERRUPTS;
+// WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+// DataLong);
+ /* End L001 */
+ }
+
+ /* Start L001 */
+ //
+ // Connect the eif interrupt to the eif interrupt routine
+ //
+
+ PCR->InterruptRoutine[EIF_LEVEL] = HalpEifDispatch;
+
+ //
+ // Enable the eif interrupt
+ //
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT5_ENABLE_HIGH );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT5_ENABLE_LOW );
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ buffer = READ_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long);
+ buffer = (buffer | STSR_EIF_ENABLE);
+#if defined(DISABLE_NMI) // S00d
+ buffer = (buffer | STSR_NMI_DISABLE);
+#endif
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long, buffer);
+
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->ERRMK.Long, ERRMK_EIF_ENABLE);
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->IEMR.Long, IEMR_ENABLE_ALL_EIF);
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long, EIMR_ENABLE_ALL_EIF);
+
+ /* Start S006 */
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
+ IOB_DUMMY_READ;
+
+ if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S007
+ buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO0_OFFSET))->CKE0.Long );
+ buffer2 &= CKE0_DISABLE_SBE; // S00c
+ buffer2 |= CKE0_ENABLE_ALL_EIF;
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE0.Long,
+ buffer2
+ );
+ // S00e vvv
+ buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO0_OFFSET))->DPCM.Long );
+ buffer2 &= DPCM_ENABLE_MASK; // S00c
+ WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET0_OFFSET) )->DPCM.Long,
+ buffer2
+ );
+
+#if 0 // S00f
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->SECT.Long,
+ SECT_REWRITE_ENABLE
+ );
+#endif
+ // S00e ^^^
+
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE1.Long,
+ CKE1_ENABLE_ALL_EIF
+ );
+ }
+
+ if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S007
+ buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO2_OFFSET))->CKE0.Long );
+ buffer2 &= CKE0_DISABLE_SBE; // S00c
+ buffer2 |= CKE0_ENABLE_ALL_EIF;
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE0.Long,
+ buffer2
+ );
+ // S00e vvv
+ buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO2_OFFSET))->DPCM.Long );
+ buffer2 &= DPCM_ENABLE_MASK; // S00c
+ WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET1_OFFSET) )->DPCM.Long,
+ buffer2
+ );
+#if 0 // S00f
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->SECT.Long,
+ SECT_REWRITE_ENABLE
+ );
+#endif
+ // S00e ^^^
+
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE1.Long,
+ CKE1_ENABLE_ALL_EIF
+ );
+ }
+ /* End S006 */
+
+ // S007
+
+ //
+ // If processor 0 is being initialized, then connect the interval timer
+ // interrupt to the stall interrupt routine so the stall execution count
+ // can be computed during phase 1 initialization. Otherwise, connect the
+ // interval timer interrupt to the appropriate interrupt service routine
+ // and set stall execution count from the computation made on processor
+ // 0.
+ //
+
+ PCR->InterruptRoutine[TIMER_LEVEL] = HalpTimerDispatch; // S003
+
+ if (Prcb->Number == 0) {
+ /* Start L001 */
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt;
+ /* End L001 */
+ } else {
+ /* Start L001 */
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt1;
+ /* End L001 */
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+ }
+
+ //
+ // Initialize the interval timer to interrupt at the specified interval.
+ //
+
+ /* Start L001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR1.Long, CLOCK_INTERVAL);
+
+ //
+ // Initialize the profile timer to interrupt at the default interval.
+ //
+
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+ /* End L001 */
+
+ //
+ // Enable the interval timer interrupt on the current processor.
+ //
+
+ /* Start L001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_CLOCK_BIT_NO); // S007
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR1.Long, 0x3);
+ /* End L001 */
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\comapre interrupt to the appropriate interrupt service routine.
+ //
+
+ /* Start L001 */
+ if (Prcb->Number != 0) {
+ PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO); // S007
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ }
+ /* End L001 */
+
+ //
+ // Connect the interprocessor interrupt service routine and enable
+ // interprocessor interrupts.
+ //
+
+ PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt;
+
+ /*Start L001 */
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT4_ENABLE_HIGH );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT4_ENABLE_LOW );
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ /*End L001 */
+
+ //
+ // Reserve the local device interrupt vector for exclusive use by the HAL.
+ //
+
+
+ /* Start L001 */
+// PCR->ReservedVectors |= (1 << DEVICE_LEVEL);
+// PCR->ReservedVectors |= (1 << INT1_LEVEL); // S00a
+ PCR->ReservedVectors |= (1 << INT2_LEVEL);
+ /* End L001 */
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxmemory.c b/private/ntos/nthals/halr98mp/mips/xxmemory.c
new file mode 100644
index 000000000..bd7dba343
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxmemory.c
@@ -0,0 +1,184 @@
+#pragma comment(exestr, "@(#) xxmemory.c 1.3 94/10/17 13:25:21 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow the HAL to map physical memory.
+
+Environment:
+
+ Phase 0 initialization only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * K001 '94.5/30 (Mon) N.Kugimoto
+ * FRM HalpAllocPhysicalMemory() From halx86
+ *
+ ***********************************************************************
+ *
+ * S001 '94.6/14 T.Samezima
+ * Chg Compile err del
+ *
+ *
+ */
+
+#include "halp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpAllocPhysicalMemory)
+#endif
+
+// S001
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The physical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+
+ PhysicalAddress =
+ (Descriptor->BasePage + AlignmentOffset) << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+ return PhysicalAddress;
+}
diff --git a/private/ntos/nthals/halr98mp/sources b/private/ntos/nthals/halr98mp/sources
new file mode 100644
index 000000000..b24752ef4
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/sources
@@ -0,0 +1,103 @@
+!IF 0
+# @(#) sources 1.6 94/10/14 17:29:42 nec
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halr98mp
+TARGETPATH=\nt\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_R98_ -DWORKAROUND_SIC3 -DLOGCALADDRBAD -DDUMMYDMA -DDBCS
+
+INCLUDES=..\x86new;..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\jxbeep.c \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\r98hwsup.c \
+ mips\jxmapio.c \
+ mips\jxmaptb.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\x86bios.c \
+ mips\r98clock.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c \
+ mips\r98info.c \
+ mips\r98ipint.s \
+ mips\r98pci.c \
+ mips\r98eif.c \
+ mips\r98int.s \
+ mips\r98dspt.c \
+ mips\r98led.c \
+ mips\r98busdt.c \
+ mips\r98pcint.c \
+ mips\r98pcibs.c \
+ mips\pcibrd.c \
+ mips\xxmemory.c \
+ mips\jxusage.c \
+ mips\mipsdat.c \
+ mips\r98esm.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halraw/alpha/adjust.c b/private/ntos/nthals/halraw/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/allstart.c b/private/ntos/nthals/halraw/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/as4000.h b/private/ntos/nthals/halraw/alpha/as4000.h
new file mode 100644
index 000000000..9e66de6da
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/as4000.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 1996 Digital Equipment Corporation
+
+Module Name:
+
+ as4000.h
+
+Abstract:
+
+ This file defines the AS4000 internal bus interrupts for Windows NT 3.51
+
+Author:
+
+ Matthew Buchman 18 March 1996
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _AS4000_
+#define _AS4000_
+
+/*++
+
+ Value added drivers for the AS4000 running Windows NT 3.51 can take
+ advantage of interrupts for the Correctable Error and the I2c Bus.
+ These interrupts are made visible to device drivers on the "Internal"
+ bus. A device driver may connect one of these interrupts via a call to
+ HalGetInterruptVector(). The bus interrupt level/vector are defined
+ below for the Correctable Error, I2c Bus, and I2c Controller interrupts.
+
+ For example, to connect the I2c bus interrupt vector:
+
+ HalGetInterruptVector(
+ Internal,
+ 0,
+ AS4000I2cBusInterruptVector,
+ AS4000I2cBusInterruptVector,
+ &Irql,
+ &Affinity
+ );
+
+ See the Windows NT Network Developers CD for more information on
+ the steps necessary to connect an interrupt service routine for
+ kernel mode device drivers.
+
+-*/
+
+enum _AS4000_INTERNAL_BUS_INTERRUPT_LEVEL {
+
+ AS4000SoftErrInterruptLevel, // Correctable Error
+ AS4000I2cCtrlInterruptLevel, // I2C Controller
+ AS4000I2cBusInterruptLevel // I2C Bus
+
+};
+
+#endif // _AS4000_
diff --git a/private/ntos/nthals/halraw/alpha/bios.c b/private/ntos/nthals/halraw/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/bitmap.c b/private/ntos/nthals/halraw/alpha/bitmap.c
new file mode 100644
index 000000000..6f01b6908
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/bitmap.c
@@ -0,0 +1,3007 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ BitMap.c
+
+Abstract:
+
+ Implementation of the bit map routines for the NT rtl.
+
+ Bit numbers within the bit map are zero based. The first is numbered
+ zero.
+
+ The bit map routines keep track of the number of bits clear or set by
+ subtracting or adding the number of bits operated on as bit ranges
+ are cleared or set; individual bit states are not tested.
+ This means that if a range of bits is set,
+ it is assumed that the total range is currently clear.
+
+Author:
+
+ Gary Kimura (GaryKi) & Lou Perazzoli (LouP) 29-Jan-1990
+
+Revision History:
+
+ Eric Rehm 9-Nov-1995 - Rename to Rtl to Halp for use in Rawhide HAL
+
+--*/
+
+// #include "ntrtlp.h"
+
+#include "halp.h"
+#include "rawhide.h"
+
+#define RightShiftUlong(E1,E2) ((E2) < 32 ? (E1) >> (E2) : 0)
+#define LeftShiftUlong(E1,E2) ((E2) < 32 ? (E1) << (E2) : 0)
+
+//
+// Macro that tells how many contiguous bits are set (i.e., 1) in
+// a byte
+//
+
+#define HalppBitSetAnywhere( Byte ) HalppBitsClearAnywhere[ (~(Byte) & 0xFF) ]
+
+
+//
+// Macro that tells how many contiguous LOW order bits are set
+// (i.e., 1) in a byte
+//
+
+#define HalppBitsSetLow( Byte ) HalppBitsClearLow[ (~(Byte) & 0xFF) ]
+
+
+//
+// Macro that tells how many contiguous HIGH order bits are set
+// (i.e., 1) in a byte
+//
+
+#define HalppBitsSetHigh( Byte ) HalppBitsClearHigh[ (~(Byte) & 0xFF) ]
+
+
+//
+// Macro that tells how many set bits (i.e., 1) there are in a byte
+//
+
+#define HalppBitsSetTotal( Byte ) HalppBitsClearTotal[ (~(Byte) & 0xFF) ]
+
+
+#if DBG
+VOID
+HalpDumpBitMap (
+ PRTL_BITMAP BitMap
+ )
+{
+ ULONG i;
+ BOOLEAN AllZeros, AllOnes;
+
+ DbgPrint(" BitMap:%08lx", BitMap);
+
+ KdPrint((" (%08x)", BitMap->SizeOfBitMap));
+ KdPrint((" %08lx\n", BitMap->Buffer));
+
+ AllZeros = FALSE;
+ AllOnes = FALSE;
+
+ for (i = 0; i < ((BitMap->SizeOfBitMap + 31) / 32); i += 1) {
+
+ if (BitMap->Buffer[i] == 0) {
+
+ if (AllZeros) {
+
+ NOTHING;
+
+ } else {
+
+ DbgPrint("%4d:", i);
+ DbgPrint(" %08lx\n", BitMap->Buffer[i]);
+ }
+
+ AllZeros = TRUE;
+
+ } else if (BitMap->Buffer[i] == 0xFFFFFFFF) {
+
+ if (AllOnes) {
+
+ NOTHING;
+
+ } else {
+
+ DbgPrint("%4d:", i);
+ DbgPrint(" %08lx\n", BitMap->Buffer[i]);
+ }
+
+ AllOnes = TRUE;
+
+ } else {
+
+ AllZeros = FALSE;
+ AllOnes = FALSE;
+
+ DbgPrint("%4d:", i);
+ DbgPrint(" %08lx\n", BitMap->Buffer[i]);
+ }
+ }
+}
+
+#endif
+
+
+//
+// There are three macros to make reading the bytes in a bitmap easier.
+//
+
+#define GET_BYTE_DECLARATIONS() \
+ PUCHAR _CURRENT_POSITION;
+
+#define GET_BYTE_INITIALIZATION(RTL_BITMAP,BYTE_INDEX) { \
+ _CURRENT_POSITION = &((PUCHAR)((RTL_BITMAP)->Buffer))[BYTE_INDEX]; \
+}
+
+#define GET_BYTE(THIS_BYTE) ( \
+ THIS_BYTE = *(_CURRENT_POSITION++) \
+)
+
+
+//
+// Lookup table that tells how many contiguous bits are clear (i.e., 0) in
+// a byte
+//
+
+CCHAR HalppBitsClearAnywhere[] =
+ { 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
+ 4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 5,4,3,3,2,2,2,2,3,2,2,2,2,2,2,2,
+ 4,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,
+ 6,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 7,6,5,5,4,4,4,4,3,3,3,3,3,3,3,3,
+ 4,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,
+ 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 6,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,0 };
+
+//
+// Lookup table that tells how many contiguous LOW order bits are clear
+// (i.e., 0) in a byte
+//
+
+CCHAR HalppBitsClearLow[] =
+ { 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+
+//
+// Lookup table that tells how many contiguous HIGH order bits are clear
+// (i.e., 0) in a byte
+//
+
+CCHAR HalppBitsClearHigh[] =
+ { 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+
+//
+// Lookup table that tells how many clear bits (i.e., 0) there are in a byte
+//
+
+CCHAR HalppBitsClearTotal[] =
+ { 8,7,7,6,7,6,6,5,7,6,6,5,6,5,5,4,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
+
+//
+// Bit Mask for clearing and setting bits within bytes
+//
+
+static UCHAR FillMask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
+
+static UCHAR ZeroMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
+
+
+VOID
+HalpInitializeBitMap (
+ IN PRTL_BITMAP BitMapHeader,
+ IN PULONG BitMapBuffer,
+ IN ULONG SizeOfBitMap
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure initializes a bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the BitMap Header to initialize
+
+ BitMapBuffer - Supplies a pointer to the buffer that is to serve as the
+ BitMap. This must be an a multiple number of longwords in size.
+
+ SizeOfBitMap - Supplies the number of bits required in the Bit Map.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //RTL_PAGED_CODE();
+
+ //
+ // Initialize the BitMap header.
+ //
+
+ BitMapHeader->SizeOfBitMap = SizeOfBitMap;
+ BitMapHeader->Buffer = BitMapBuffer;
+
+ //
+ // And return to our caller
+ //
+
+ //DbgPrint("InitializeBitMap"); DumpBitMap(BitMapHeader);
+ return;
+}
+
+
+VOID
+HalpClearAllBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure clears all bits in the specified Bit Map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Clear all the bits
+ //
+
+ RtlZeroMemory( BitMapHeader->Buffer,
+ ((BitMapHeader->SizeOfBitMap + 31) / 32) * 4
+ );
+
+ //
+ // And return to our caller
+ //
+
+ //DbgPrint("ClearAllBits"); DumpBitMap(BitMapHeader);
+ return;
+}
+
+
+VOID
+HalpSetAllBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sets all bits in the specified Bit Map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Set all the bits
+ //
+
+ RtlFillMemoryUlong( BitMapHeader->Buffer,
+ ((BitMapHeader->SizeOfBitMap + 31) / 32) * 4,
+ 0xffffffff
+ );
+
+ //
+ // And return to our caller
+ //
+
+ //DbgPrint("SetAllBits"); DumpBitMap(BitMapHeader);
+ return;
+}
+
+
+ULONG
+HalpFindClearBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of clear bits. If a run is not found from the
+ hint to the end of the bitmap, we will search again from the
+ beginning of the bitmap.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region of clear bits found. If not such a region cannot be found
+ a -1 (i.e. 0xffffffff) is returned.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG HintBit;
+ ULONG MainLoopIndex;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the
+ // fields from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Calculate from the hint index where the hint byte is and set ourselves
+ // up to read the hint on the next call to GET_BYTE. To make the
+ // algorithm run fast we'll only honor hints down to the byte level of
+ // granularity. There is a possibility that we'll need to execute
+ // our main logic twice. Once to test from the hint byte to the end of
+ // the bitmap and the other to test from the start of the bitmap. First
+ // we need to make sure the Hint Index is within range.
+ //
+
+ if (HintIndex >= SizeOfBitMap) {
+
+ HintIndex = 0;
+ }
+
+ HintBit = HintIndex % 8;
+
+ for (MainLoopIndex = 0; MainLoopIndex < 2; MainLoopIndex += 1) {
+
+ ULONG StartByteIndex;
+ ULONG EndByteIndex;
+
+ UCHAR CurrentByte;
+
+ //
+ // Check for the first time through the main loop, which indicates
+ // that we are going to start our search at our hint byte
+ //
+
+ if (MainLoopIndex == 0) {
+
+ StartByteIndex = HintIndex / 8;
+ EndByteIndex = SizeInBytes;
+
+ //
+ // This is the second time through the loop, make sure there is
+ // actually something to check before the hint byte
+ //
+
+ } else if (HintIndex != 0) {
+
+ //
+ // The end index for the second time around is based on the
+ // number of bits we need to find. We need to use this inorder
+ // to take the case where the preceding byte to the hint byte
+ // is the start of our run, and the run includes the hint byte
+ // and some following bytes, based on the number of bits needed
+ // The computation is to take the number of bits needed minus
+ // 2 divided by 8 and then add 2. This will take in to account
+ // the worst possible case where we have one bit hanging off
+ // of each end byte, and all intervening bytes are all zero.
+ //
+
+ if (NumberToFind < 2) {
+
+ EndByteIndex = 0;
+
+ } else {
+
+ EndByteIndex = (HintIndex / 8) + ((NumberToFind - 2) / 8) + 2;
+
+ //
+ // Make sure we don't overrun the end of the bitmap
+ //
+
+ if (EndByteIndex > SizeInBytes) {
+
+ EndByteIndex = SizeInBytes;
+ }
+ }
+
+ HintIndex = 0;
+ HintBit = 0;
+ StartByteIndex = 0;
+
+ //
+ // Otherwise we already did a complete loop through the bitmap
+ // so we should simply return -1 to say nothing was found
+ //
+
+ } else {
+
+ return 0xffffffff;
+ }
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION(BitMapHeader, StartByteIndex);
+
+ //
+ // Get the first byte, and set any bits before the hint bit.
+ //
+
+ GET_BYTE( CurrentByte );
+
+ CurrentByte |= FillMask[HintBit];
+
+ //
+ // If the number of bits can only fit in 1 or 2 bytes (i.e., 9 bits or
+ // less) we do the following test case.
+ //
+
+ if (NumberToFind <= 9) {
+
+ ULONG CurrentBitIndex;
+ UCHAR PreviousByte;
+
+ PreviousByte = 0xff;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ CurrentBitIndex = StartByteIndex * 8;
+
+ while (TRUE) {
+
+ //
+ // If this is the first itteration of the loop, mask Current
+ // byte with the real hint.
+ //
+
+ //
+ // The current byte does not satisfy our requirements so we'll
+ // check the previous and current byte together to see if
+ // we'll fit. To check uses the high part of the previous
+ // byte and low part of the current byte.
+ //
+
+ if (((ULONG)HalppBitsClearHigh[PreviousByte] +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first cleared
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsClearHigh[PreviousByte];
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // Check to see if a single byte will satisfy the requirement
+ //
+
+ if ((ULONG)HalppBitsClearAnywhere[CurrentByte] >= NumberToFind) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // It all fits in a single byte, so calculate the bit
+ // number. We do this by taking a mask of the appropriate
+ // size and shifting it over until it fits. It fits when
+ // we can bitwise-and the current byte with the bitmask
+ // and get a zero back.
+ //
+
+ BitMask = FillMask[ NumberToFind ];
+ for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ //
+ // return to our caller the located bit index, and the
+ // number that we found.
+ //
+
+ return CurrentBitIndex + i;
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousByte = CurrentByte;
+
+ //
+ // Increment our Bit Index, and either exit, or get the
+ // next byte.
+ //
+
+ CurrentBitIndex += 8;
+
+ if ( CurrentBitIndex < EndByteIndex * 8 ) {
+
+ GET_BYTE( CurrentByte );
+
+ } else {
+
+ break;
+ }
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than 9 but if it is less than 15
+ // then we know it can be satisfied with at most 2 bytes, or 3 bytes
+ // if the middle byte (of the 3) is all zeros.
+ //
+
+ } else if (NumberToFind < 15) {
+
+ ULONG CurrentBitIndex;
+
+ UCHAR PreviousPreviousByte;
+ UCHAR PreviousByte;
+
+ PreviousPreviousByte = 0xff;
+ PreviousByte = 0xff;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ CurrentBitIndex = StartByteIndex * 8;
+
+ while (TRUE) {
+
+ //
+ // Check to see if the Previous byte and current byte
+ // together satisfy the request.
+ //
+
+ if (((ULONG)HalppBitsClearHigh[PreviousByte] +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first cleared
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsClearHigh[PreviousByte];
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // if the previous byte is all zeros then maybe the
+ // request can be satisfied using the Previous Previous Byte
+ // Previous Byte, and the Current Byte.
+ //
+
+ if ((PreviousByte == 0)
+
+ &&
+
+ (((ULONG)HalppBitsClearHigh[PreviousPreviousByte] + 8 +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind)) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these three bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the previous byte (bit 0) and subtracting
+ // the number of bits its takes to get to the first
+ // cleared high bit.
+ //
+
+ StartingIndex = (CurrentBitIndex - 8) -
+ (LONG)HalppBitsClearHigh[PreviousPreviousByte];
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, the previous
+ // byte into the previous previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousPreviousByte = PreviousByte;
+ PreviousByte = CurrentByte;
+
+ //
+ // Increment our Bit Index, and either exit, or get the
+ // next byte.
+ //
+
+ CurrentBitIndex += 8;
+
+ if ( CurrentBitIndex < EndByteIndex * 8 ) {
+
+ GET_BYTE( CurrentByte );
+
+ } else {
+
+ break;
+ }
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than or equal to 15. This request
+ // has to have at least one byte of all zeros to be satisfied
+ //
+
+ } else {
+
+ ULONG CurrentByteIndex;
+
+ ULONG ZeroBytesNeeded;
+ ULONG ZeroBytesFound;
+
+ UCHAR StartOfRunByte;
+ LONG StartOfRunIndex;
+
+ //
+ // First precalculate how many zero bytes we're going to need
+ //
+
+ ZeroBytesNeeded = (NumberToFind - 7) / 8;
+
+ //
+ // Indicate for the first time through our loop that we haven't
+ // found a zero byte yet, and indicate that the start of the
+ // run is the byte just before the start byte index
+ //
+
+ ZeroBytesFound = 0;
+ StartOfRunByte = 0xff;
+ StartOfRunIndex = StartByteIndex - 1;
+
+ //
+ // Examine all the bytes in our test range searching for a fit
+ //
+
+ CurrentByteIndex = StartByteIndex;
+
+ while (TRUE) {
+
+ //
+ // If the number of zero bytes fits our minimum requirements
+ // then we can do the additional test to see if we
+ // actually found a fit
+ //
+
+ if ((ZeroBytesFound >= ZeroBytesNeeded)
+
+ &&
+
+ ((ULONG)HalppBitsClearHigh[StartOfRunByte] + ZeroBytesFound*8 +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these bytes, so we can compute
+ // the starting index. This is done by taking the
+ // StartOfRunIndex times 8 and adding the number of bits
+ // it takes to get to the first cleared high bit.
+ //
+
+ StartingIndex = (StartOfRunIndex * 8) +
+ (8 - (LONG)HalppBitsClearHigh[StartOfRunByte]);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // Check to see if the byte is zero and increment
+ // the number of zero bytes found
+ //
+
+ if (CurrentByte == 0) {
+
+ ZeroBytesFound += 1;
+
+ //
+ // The byte isn't a zero so we need to start over again
+ // looking for zero bytes.
+ //
+
+ } else {
+
+ ZeroBytesFound = 0;
+ StartOfRunByte = CurrentByte;
+ StartOfRunIndex = CurrentByteIndex;
+ }
+
+ //
+ // Increment our Byte Index, and either exit, or get the
+ // next byte.
+ //
+
+ CurrentByteIndex += 1;
+
+ if ( CurrentByteIndex < EndByteIndex ) {
+
+ GET_BYTE( CurrentByte );
+
+ } else {
+
+ break;
+ }
+
+ } // end loop CurrentByteIndex
+ }
+ }
+
+ //
+ // We never found a fit so we'll return -1
+ //
+
+ return 0xffffffff;
+}
+
+
+ULONG
+HalpFindSetBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of set bits.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region of set bits found. If such a region cannot be found then
+ a -1 (i.e., 0xffffffff) is returned.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG HintByte;
+
+ ULONG MainLoopIndex;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the
+ // fields from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Calculate from the hint index where the hint byte is and set ourselves
+ // up to read the hint on the next call to GET_BYTE. To make the
+ // algorithm run fast we'll only honor hints down to the byte level of
+ // granularity. There is a possibility that we'll need to execute
+ // our main logic twice. Once to test from the hint byte to the end of
+ // the bitmap and the other to test from the start of the bitmap. First
+ // we need to make sure the Hint Index is within range.
+ //
+
+ if (HintIndex >= SizeOfBitMap) {
+
+ HintIndex = 0;
+ }
+
+ HintByte = HintIndex / 8;
+
+ for (MainLoopIndex = 0; MainLoopIndex < 2; MainLoopIndex += 1) {
+
+ ULONG StartByteIndex;
+ ULONG EndByteIndex;
+
+ //
+ // Check for the first time through the main loop, which indicates
+ // that we are going to start our search at our hint byte
+ //
+
+ if (MainLoopIndex == 0) {
+
+ StartByteIndex = HintByte;
+ EndByteIndex = SizeInBytes;
+
+ //
+ // This is the second time through the loop, make sure there is
+ // actually something to check before the hint byte
+ //
+
+ } else if (HintByte != 0) {
+
+ StartByteIndex = 0;
+
+ //
+ // The end index for the second time around is based on the
+ // number of bits we need to find. We need to use this inorder
+ // to take the case where the preceding byte to the hint byte
+ // is the start of our run, and the run includes the hint byte
+ // and some following bytes, based on the number of bits needed
+ // The computation is to take the number of bits needed minus
+ // 2 divided by 8 and then add 2. This will take in to account
+ // the worst possible case where we have one bit hanging off
+ // of each end byte, and all intervening bytes are all zero.
+ // We only need to add one in the following equation because
+ // HintByte is already counted.
+ //
+
+ if (NumberToFind < 2) {
+
+ EndByteIndex = HintByte;
+
+ } else {
+
+ EndByteIndex = HintByte + ((NumberToFind - 2) / 8) + 1;
+
+ //
+ // Make sure we don't overrun the end of the bitmap
+ //
+
+ if (EndByteIndex > SizeInBytes) {
+
+ EndByteIndex = SizeInBytes;
+ }
+ }
+
+ //
+ // Otherwise we already did a complete loop through the bitmap
+ // so we should simply return -1 to say nothing was found
+ //
+
+ } else {
+
+ return 0xffffffff;
+
+ }
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION(BitMapHeader, StartByteIndex);
+
+ //
+ // If the number of bits can only fit in 1 or 2 bytes (i.e., 9 bits or
+ // less) we do the following test case.
+ //
+
+ if (NumberToFind <= 9) {
+
+ ULONG CurrentBitIndex;
+
+ UCHAR PreviousByte;
+ UCHAR CurrentByte;
+
+ PreviousByte = 0x00;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ for (CurrentBitIndex = StartByteIndex * 8;
+ CurrentBitIndex < EndByteIndex * 8;
+ CurrentBitIndex += 8) {
+
+ //
+ // Get the current byte
+ //
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // Check to see if a single byte will satisfy the requirement
+ //
+
+ if ((ULONG)HalppBitSetAnywhere(CurrentByte) >= NumberToFind) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // It all fits in a single byte, so calculate the bit
+ // number. We do this by taking a mask of the appropriate
+ // size and shifting it over until it fits. It fits when
+ // we can bitwise-and the current byte with the bit mask
+ // and get back the bit mask.
+ //
+
+ BitMask = FillMask[ NumberToFind ];
+ for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ //
+ // return to our caller the located bit index, and the
+ // number that we found.
+ //
+
+ return CurrentBitIndex + i;
+ }
+
+ //
+ // The current byte does not satisfy our requirements so we'll
+ // check the previous and current byte together to see if
+ // we'll fit. To check uses the high part of the previous
+ // byte and low part of the current byte.
+ //
+
+ if (((ULONG)HalppBitsSetHigh(PreviousByte) +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first set
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsSetHigh(PreviousByte);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousByte = CurrentByte;
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than 9 but if it is less than 15
+ // then we know it can be satisfied with at most 2 bytes, or 3 bytes
+ // if the middle byte (of the 3) is all ones.
+ //
+
+ } else if (NumberToFind < 15) {
+
+ ULONG CurrentBitIndex;
+
+ UCHAR PreviousPreviousByte;
+ UCHAR PreviousByte;
+ UCHAR CurrentByte;
+
+ PreviousPreviousByte = 0x00;
+ PreviousByte = 0x00;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ for (CurrentBitIndex = StartByteIndex * 8;
+ CurrentBitIndex < EndByteIndex * 8;
+ CurrentBitIndex += 8) {
+
+ //
+ // Get the current byte
+ //
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // Check to see if the Previous byte and current byte
+ // together satisfy the request.
+ //
+
+ if (((ULONG)HalppBitsSetHigh(PreviousByte) +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first set
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsSetHigh(PreviousByte);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // if the previous byte is all ones then maybe the
+ // request can be satisfied using the Previous Previous Byte
+ // Previous Byte, and the Current Byte.
+ //
+
+ if ((PreviousByte == 0xff)
+
+ &&
+
+ (((ULONG)HalppBitsSetHigh(PreviousPreviousByte) + 8 +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind)) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these three bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the previous byte (bit 0) and subtracting
+ // the number of bits its takes to get to the first
+ // set high bit.
+ //
+
+ StartingIndex = (CurrentBitIndex - 8) -
+ (LONG)HalppBitsSetHigh(PreviousPreviousByte);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, the previous
+ // byte into the previous previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousPreviousByte = PreviousByte;
+ PreviousByte = CurrentByte;
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than or equal to 15. This request
+ // has to have at least one byte of all ones to be satisfied
+ //
+
+ } else {
+
+ ULONG CurrentByteIndex;
+
+ UCHAR CurrentByte;
+
+ ULONG OneBytesNeeded;
+ ULONG OneBytesFound;
+
+ UCHAR StartOfRunByte;
+ LONG StartOfRunIndex;
+
+ //
+ // First precalculate how many one bytes we're going to need
+ //
+
+ OneBytesNeeded = (NumberToFind - 7) / 8;
+
+ //
+ // Indicate for the first time through our loop that we haven't
+ // found a one byte yet, and indicate that the start of the
+ // run is the byte just before the start byte index
+ //
+
+ OneBytesFound = 0;
+ StartOfRunByte = 0x00;
+ StartOfRunIndex = StartByteIndex - 1;
+
+ //
+ // Examine all the bytes in our test range searching for a fit
+ //
+
+ for (CurrentByteIndex = StartByteIndex;
+ CurrentByteIndex < EndByteIndex;
+ CurrentByteIndex += 1) {
+
+ //
+ // Get the current byte
+ //
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the number of zero bytes fits our minimum requirements
+ // then we can do the additional test to see if we
+ // actually found a fit
+ //
+
+ if ((OneBytesFound >= OneBytesNeeded)
+
+ &&
+
+ ((ULONG)HalppBitsSetHigh(StartOfRunByte) + OneBytesFound*8 +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these bytes, so we can compute
+ // the starting index. This is done by taking the
+ // StartOfRunIndex times 8 and adding the number of bits
+ // it takes to get to the first set high bit.
+ //
+
+ StartingIndex = (StartOfRunIndex * 8) +
+ (8 - (LONG)HalppBitsSetHigh(StartOfRunByte));
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // Check to see if the byte is all ones and increment
+ // the number of one bytes found
+ //
+
+ if (CurrentByte == 0xff) {
+
+ OneBytesFound += 1;
+
+ //
+ // The byte isn't all ones so we need to start over again
+ // looking for one bytes.
+ //
+
+ } else {
+
+ OneBytesFound = 0;
+ StartOfRunByte = CurrentByte;
+ StartOfRunIndex = CurrentByteIndex;
+ }
+
+ } // end loop CurrentByteIndex
+ }
+ }
+
+ //
+ // We never found a fit so we'll return -1
+ //
+
+ return 0xffffffff;
+}
+
+
+ULONG
+HalpFindClearBitsAndSet (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of clear bits, sets the bits and returns the
+ number of bits found, and the starting bit number which was clear
+ then set.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region found. If such a region cannot be located a -1 (i.e.,
+ 0xffffffff) is returned.
+
+--*/
+
+{
+ ULONG StartingIndex;
+
+ //
+ // First look for a run of clear bits that equals the size requested
+ //
+
+ StartingIndex = HalpFindClearBits( BitMapHeader,
+ NumberToFind,
+ HintIndex );
+
+ //DbgPrint("FindClearBits %08lx, ", NumberToFind);
+ //DbgPrint("%08lx", StartingIndex);
+ //DumpBitMap(BitMapHeader);
+
+ if (StartingIndex != 0xffffffff) {
+
+ //
+ // We found a large enough run of clear bits so now set them
+ //
+
+ HalpSetBits( BitMapHeader, StartingIndex, NumberToFind );
+ }
+
+ //
+ // And return to our caller
+ //
+
+ return StartingIndex;
+
+}
+
+
+ULONG
+HalpFindSetBitsAndClear (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of set bits, clears the bits and returns the
+ number of bits found and the starting bit number which was set then
+ clear.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region found. If such a region cannot be located a -1 (i.e.,
+ 0xffffffff) is returned.
+
+
+--*/
+
+{
+ ULONG StartingIndex;
+
+ //
+ // First look for a run of set bits that equals the size requested
+ //
+
+ if ((StartingIndex = HalpFindSetBits( BitMapHeader,
+ NumberToFind,
+ HintIndex )) != 0xffffffff) {
+
+ //
+ // We found a large enough run of set bits so now clear them
+ //
+
+ HalpClearBits( BitMapHeader, StartingIndex, NumberToFind );
+ }
+
+ //
+ // And return to our caller
+ //
+
+ return StartingIndex;
+}
+
+
+VOID
+HalpClearBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG NumberToClear
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure clears the specified range of bits within the
+ specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized Bit Map.
+
+ StartingIndex - Supplies the index (zero based) of the first bit to clear.
+
+ NumberToClear - Supplies the number of bits to clear.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BitOffset;
+ PULONG CurrentLong;
+
+ //DbgPrint("ClearBits %08lx, ", NumberToClear);
+ //DbgPrint("%08lx", StartingIndex);
+
+ ASSERT( StartingIndex + NumberToClear <= BitMapHeader->SizeOfBitMap );
+
+ //
+ // Special case the situation where the number of bits to clear is
+ // zero. Turn this into a noop.
+ //
+
+ if (NumberToClear == 0) {
+
+ return;
+ }
+
+ BitOffset = StartingIndex % 32;
+
+ //
+ // Get a pointer to the first longword that needs to be zeroed out
+ //
+
+ CurrentLong = &BitMapHeader->Buffer[ StartingIndex / 32 ];
+
+ //
+ // Check if we can only need to clear out one longword.
+ //
+
+ if ((BitOffset + NumberToClear) <= 32) {
+
+ //
+ // To build a mask of bits to clear we shift left to get the number
+ // of bits we're clearing and then shift right to put it in position.
+ // We'll typecast the right shift to ULONG to make sure it doesn't
+ // do a sign extend.
+ //
+
+ *CurrentLong &= ~LeftShiftUlong(RightShiftUlong(((ULONG)0xFFFFFFFF),(32 - NumberToClear)),
+ BitOffset);
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+ }
+
+ //
+ // We can clear out to the end of the first longword so we'll
+ // do that right now.
+ //
+
+ *CurrentLong &= ~LeftShiftUlong(0xFFFFFFFF, BitOffset);
+
+ //
+ // And indicate what the next longword to clear is and how many
+ // bits are left to clear
+ //
+
+ CurrentLong += 1;
+ NumberToClear -= 32 - BitOffset;
+
+ //
+ // The bit position is now long aligned, so we can continue
+ // clearing longwords until the number to clear is less than 32
+ //
+
+ while (NumberToClear >= 32) {
+
+ *CurrentLong = 0;
+ CurrentLong += 1;
+ NumberToClear -= 32;
+ }
+
+ //
+ // And now we can clear the remaining bits, if there are any, in the
+ // last longword
+ //
+
+ if (NumberToClear > 0) {
+
+ *CurrentLong &= LeftShiftUlong(0xFFFFFFFF, NumberToClear);
+ }
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+}
+
+VOID
+HalpSetBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG NumberToSet
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sets the specified range of bits within the
+ specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialied BitMap.
+
+ StartingIndex - Supplies the index (zero based) of the first bit to set.
+
+ NumberToSet - Supplies the number of bits to set.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BitOffset;
+ PULONG CurrentLong;
+
+ //DbgPrint("SetBits %08lx, ", NumberToSet);
+ //DbgPrint("%08lx", StartingIndex);
+
+ ASSERT( StartingIndex + NumberToSet <= BitMapHeader->SizeOfBitMap );
+
+ //
+ // Special case the situation where the number of bits to set is
+ // zero. Turn this into a noop.
+ //
+
+ if (NumberToSet == 0) {
+
+ return;
+ }
+
+ BitOffset = StartingIndex % 32;
+
+ //
+ // Get a pointer to the first longword that needs to be set
+ //
+
+ CurrentLong = &BitMapHeader->Buffer[ StartingIndex / 32 ];
+
+ //
+ // Check if we can only need to set one longword.
+ //
+
+ if ((BitOffset + NumberToSet) <= 32) {
+
+ //
+ // To build a mask of bits to set we shift left to get the number
+ // of bits we're setting and then shift right to put it in position.
+ // We'll typecast the right shift to ULONG to make sure it doesn't
+ // do a sign extend.
+ //
+
+ *CurrentLong |= LeftShiftUlong(RightShiftUlong(((ULONG)0xFFFFFFFF),(32 - NumberToSet)),
+ BitOffset);
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+ }
+
+ //
+ // We can set bits out to the end of the first longword so we'll
+ // do that right now.
+ //
+
+ *CurrentLong |= LeftShiftUlong(0xFFFFFFFF, BitOffset);
+
+ //
+ // And indicate what the next longword to set is and how many
+ // bits are left to set
+ //
+
+ CurrentLong += 1;
+ NumberToSet -= 32 - BitOffset;
+
+ //
+ // The bit position is now long aligned, so we can continue
+ // setting longwords until the number to set is less than 32
+ //
+
+ while (NumberToSet >= 32) {
+
+ *CurrentLong = 0xffffffff;
+ CurrentLong += 1;
+ NumberToSet -= 32;
+ }
+
+ //
+ // And now we can set the remaining bits, if there are any, in the
+ // last longword
+ //
+
+ if (NumberToSet > 0) {
+
+ *CurrentLong |= ~LeftShiftUlong(0xFFFFFFFF, NumberToSet);
+ }
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+}
+
+
+ULONG
+HalpFindLongestRunClear (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the largest contiguous range of clear bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of clear bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the largest contiguous
+ run of clear bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG LongestRunSize;
+ ULONG LongestRunIndex;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our longest and current run variables
+ //
+
+ LongestRunSize = 0;
+ LongestRunIndex = 0;
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0;
+
+ //
+ // Examine every byte in the BitMap
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is not all zeros we need to
+ // (1) check if the current run is big enough to supercede the
+ // longest run, and (2) check if the current byte inside of
+ // itself can supercede the longest run, and (3) start a new
+ // current run
+ //
+
+ if (CurrentByte != 0x00) {
+
+ UCHAR Temp;
+
+ //
+ // Compute the final size of the current run
+ //
+
+ CurrentRunSize += HalppBitsClearLow[CurrentByte];
+
+ //
+ // Check if the current run is larger than the longest run that
+ // we've found so far
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // The next run starts with the remaining clear bits in the
+ // current byte. We set this up before we check inside the
+ // current byte for a longer run, because the latter test
+ // might require extra work.
+ //
+
+ CurrentRunSize = HalppBitsClearHigh[ CurrentByte ];
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+
+ //
+ // Check if the current byte contains a run inside of it that
+ // is both greater than the longest run size, and the current
+ // run size. But we'll only both with this test if the
+ // longest run size, and current run size are both less than 8.
+ //
+
+ if ((LongestRunSize < 8) && (CurrentRunSize < 8) &&
+ ((ULONG)(Temp = HalppBitsClearAnywhere[CurrentByte]) > LongestRunSize) &&
+ ((ULONG)Temp > CurrentRunSize)) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // Somewhere in the current byte is a run longer than the
+ // longest run, or the current run. All we need to do now
+ // is find the index for this new longest run.
+ //
+
+ BitMask = FillMask[ Temp ];
+
+ for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ LongestRunIndex = (CurrentByteIndex * 8) + i;
+ LongestRunSize = Temp;
+ }
+
+ //
+ // Otherwise the current byte is all zeros and
+ // we simply continue with the current run
+ //
+
+ } else {
+
+ CurrentRunSize += 8;
+ }
+ }
+
+ //
+ // See if we finished looking over the bitmap with an open current
+ // run that is longer than the longest saved run
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = LongestRunIndex;
+ return LongestRunSize;
+}
+
+
+ULONG
+HalpFindLongestRunSet (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the largest contiguous range of set bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of set bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the largest contiguous
+ run of set bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG LongestRunSize;
+ ULONG LongestRunIndex;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our longest and current run variables
+ //
+
+ LongestRunSize = 0;
+ LongestRunIndex = 0;
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0;
+
+ //
+ // Examine every byte in the BitMap
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is not all ones we need to
+ // (1) check if the current run is big enough to supercede the
+ // longest run, and (2) check if the current byte inside of
+ // itself can supercede the longest run, and (3) start a new
+ // current run
+ //
+
+ if (CurrentByte != 0xff) {
+
+ UCHAR Temp;
+
+ //
+ // Compute the final size of the current run
+ //
+
+ CurrentRunSize += HalppBitsSetLow(CurrentByte);
+
+ //
+ // Check if the current run is larger than the longest run that
+ // we've found so far
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // The next run starts with the remaining set bits in the
+ // current byte. We set this up before we check inside the
+ // current byte for a longer run, because the latter test
+ // might require extra work.
+ //
+
+ CurrentRunSize = HalppBitsSetHigh( CurrentByte );
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+
+ //
+ // Check if the current byte contains a run inside of it that
+ // is both greater than the longest run size, and the current
+ // run size. But we'll only both with this test if the
+ // longest run size, and current run size are both less than 8.
+ //
+
+ if ((LongestRunSize < 8) && (CurrentRunSize < 8) &&
+ ((ULONG)(Temp = HalppBitSetAnywhere(CurrentByte)) > LongestRunSize) &&
+ ((ULONG)Temp > CurrentRunSize)) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // Somewhere in the current byte is a run longer than the
+ // longest run, or the current run. All we need to do now
+ // is find the index for this new longest run.
+ //
+
+ BitMask = FillMask[ Temp ];
+
+ for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ LongestRunIndex = (CurrentByteIndex * 8) + i;
+ LongestRunSize = Temp;
+ }
+
+ //
+ // Otherwise the current byte is all ones and
+ // we simply continue with the current run
+ //
+
+ } else {
+
+ CurrentRunSize += 8;
+ }
+ }
+
+ //
+ // See if we finished looking over the bitmap with an open current
+ // run that is longer than the longest saved run
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = LongestRunIndex;
+ return LongestRunSize;
+}
+
+
+ULONG
+HalpFindFirstRunClear (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the first contiguous range of clear bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of clear bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the first contiguous
+ run of clear bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our current run variables
+ //
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0xffffffff;
+
+ //
+ // Examine every byte in the BitMap. We'll also break out of this
+ // loop if ever we finish off a run.
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is all ones and the run size is zero then
+ // skip over this byte because we haven't found the start of a
+ // run yet.
+ //
+
+ if ((CurrentByte == 0xff) && (CurrentRunSize == 0)) {
+
+ NOTHING;
+
+ //
+ // See if the current byte is all zeros, because if it is then
+ // we simply continue with the current run
+ //
+
+ } else if (CurrentByte == 0x00) {
+
+ CurrentRunSize += 8;
+
+ if (CurrentRunIndex == 0xffffffff) {
+
+ CurrentRunIndex = (CurrentByteIndex * 8);
+ }
+
+ //
+ // Otherwise the current byte is not all zeros, so we need to
+ // (1) check if we have a current run, or (2) check if the
+ // current byte inside of itself is a run, or (3) start a
+ // current run.
+ //
+ // Check if we have a current run, we do that by checking
+ // if the low bits are clear.
+ //
+
+ } else if (CurrentRunSize != 0) {
+
+ CurrentRunSize += HalppBitsClearLow[CurrentByte];
+ break;
+
+ //
+ // Check if we have an internal run, we do that by checking
+ // if the high bits are not clear. This check actually cheats
+ // a bit in that the current byte might have an inside run
+ // but we'll skip over it because we can start a run at the
+ // end of the byte.
+ //
+
+ } else if (HalppBitsClearHigh[CurrentByte] == 0) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ ASSERT( HalppBitsClearAnywhere[CurrentByte] != 0 );
+
+ CurrentRunSize = HalppBitsClearAnywhere[CurrentByte];
+
+ //
+ // Somewhere in the current byte is a run. All we need to do now
+ // is find the index for this new run.
+ //
+
+ BitMask = FillMask[ CurrentRunSize ];
+
+ for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ CurrentRunIndex = (CurrentByteIndex * 8) + i;
+ break;
+
+ //
+ // Otherwise we start a new current run. It starts with the
+ // remaining clear bits in the current byte.
+ //
+
+ } else {
+
+ CurrentRunSize = HalppBitsClearHigh[ CurrentByte ];
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+ }
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = CurrentRunIndex;
+ return CurrentRunSize;
+}
+
+
+ULONG
+HalpFindFirstRunSet (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the first contiguous range of set bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of set bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the largest contiguous
+ run of set bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our current run variables
+ //
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0xffffffff;
+
+ //
+ // Examine every byte in the BitMap. We'll also break out of this
+ // loop if ever we finish off a run.
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is all zeros and the run size is zero then
+ // skip over this byte because we haven't found the start of a
+ // run yet.
+ //
+
+ if ((CurrentByte == 0x00) && (CurrentRunSize == 0)) {
+
+ NOTHING;
+
+ //
+ // See if the current byte is all ones, because if it is then
+ // we simply continue with the current run
+ //
+
+ } else if (CurrentByte == 0xff) {
+
+ CurrentRunSize += 8;
+
+ if (CurrentRunIndex == 0xffffffff) {
+
+ CurrentRunIndex = (CurrentByteIndex * 8);
+ }
+
+ //
+ // Otherwise the current byte is not all ones, so we need to
+ // (1) check if we have the current run, or (2) check if the
+ // current byte inside of itself is a run, or (3) start a
+ // current run.
+ //
+ // Check if we have a current run, we do that by checking
+ // if the low bits are set.
+ //
+
+ } else if (CurrentRunSize != 0) {
+
+ CurrentRunSize += HalppBitsSetLow(CurrentByte);
+ break;
+
+ //
+ // Check if we have an internal run, we do that by checking
+ // if the high bits are not set. This check actually cheats
+ // a bit in that the current byte might have an inside run
+ // but we'll skip over it because we can start a run at the
+ // end of the byte.
+ //
+
+ } else if (HalppBitsSetHigh(CurrentByte) == 0) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ ASSERT( HalppBitSetAnywhere(CurrentByte) != 0 );
+
+ CurrentRunSize = HalppBitSetAnywhere(CurrentByte);
+
+ //
+ // Somewhere in the current byte is a run. All we need to do now
+ // is find the index for this new run.
+ //
+
+ BitMask = FillMask[ CurrentRunSize ];
+
+ for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ CurrentRunIndex = (CurrentByteIndex * 8) + i;
+ break;
+
+ //
+ // Otherwise we start a new current run. It starts with the
+ // remaining set bits in the current byte.
+ //
+
+ } else {
+
+ CurrentRunSize = HalppBitsSetHigh( CurrentByte );
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+ }
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = CurrentRunIndex;
+ return CurrentRunSize;
+}
+
+
+ULONG
+HalpNumberOfClearBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure counts and returns the number of clears bits within
+ the specified bitmap.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+Return Value:
+
+ ULONG - The total number of clear bits in the bitmap
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG i;
+ UCHAR CurrentByte;
+
+ ULONG TotalClear;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we don't count them. We
+ // do this by first checking if there are any odd bits in the last byte
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set if up so we can use the GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0 );
+
+ //
+ // Examine every byte in the bitmap
+ //
+
+ TotalClear = 0;
+ for (i = 0; i < SizeInBytes; i += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ TotalClear += HalppBitsClearTotal[CurrentByte];
+ }
+
+ return TotalClear;
+}
+
+
+ULONG
+HalpNumberOfSetBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure counts and returns the number of set bits within
+ the specified bitmap.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+Return Value:
+
+ ULONG - The total number of set bits in the bitmap
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG i;
+ UCHAR CurrentByte;
+
+ ULONG TotalSet;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Clear any unused bits in the last byte so we don't count them. We
+ // do this by first checking if there are any odd bits in the last byte
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set if up so we can use the GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0 );
+
+ //
+ // Examine every byte in the bitmap
+ //
+
+ TotalSet = 0;
+ for (i = 0; i < SizeInBytes; i += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ TotalSet += HalppBitsSetTotal(CurrentByte);
+ }
+
+ return TotalSet;
+}
+
+
+BOOLEAN
+HalpAreBitsClear (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure determines if the range of specified bits are all clear.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+ StartingIndex - Supplies the starting bit index to examine
+
+ Length - Supplies the number of bits to examine
+
+Return Value:
+
+ BOOLEAN - TRUE if the specified bits in the bitmap are all clear, and
+ FALSE if any are set or if the range is outside the bitmap or if
+ Length is zero.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG EndingIndex;
+
+ ULONG StartingByte;
+ ULONG EndingByte;
+
+ ULONG StartingOffset;
+ ULONG EndingOffset;
+
+ ULONG i;
+ UCHAR Byte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the fields
+ // from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // First make sure that the specified range is contained within the
+ // bitmap, and the length is not zero.
+ //
+
+ if ((StartingIndex + Length > SizeOfBitMap) || (Length == 0)) {
+
+ return FALSE;
+ }
+
+ //
+ // Compute the ending index, starting and ending byte, and the starting
+ // and ending offset within each byte
+ //
+
+ EndingIndex = StartingIndex + Length - 1;
+
+ StartingByte = StartingIndex / 8;
+ EndingByte = EndingIndex / 8;
+
+ StartingOffset = StartingIndex % 8;
+ EndingOffset = EndingIndex % 8;
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, StartingByte );
+
+ //
+ // Special case the situation where the starting byte and ending
+ // byte are one in the same
+ //
+
+ if (StartingByte == EndingByte) {
+
+ //
+ // Get the single byte we are to look at
+ //
+
+ GET_BYTE( Byte );
+
+ //
+ // Now we compute the mask of bits we're after and then AND it with
+ // the byte. If it is zero then the bits in question are all clear
+ // otherwise at least one of them is set.
+ //
+
+ if ((ZeroMask[StartingOffset] & FillMask[EndingOffset+1] & Byte) == 0) {
+
+ return TRUE;
+
+ } else {
+
+ return FALSE;
+ }
+
+ } else {
+
+ //
+ // Get the first byte that we're after, and then
+ // compute the mask of bits we're after for the first byte then
+ // AND it with the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((ZeroMask[StartingOffset] & Byte) != 0) {
+
+ return FALSE;
+ }
+
+ //
+ // Now for every whole byte inbetween read in the byte,
+ // and make sure it is all zeros
+ //
+
+ for (i = StartingByte+1; i < EndingByte; i += 1) {
+
+ GET_BYTE( Byte );
+
+ if (Byte != 0) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // Get the last byte we're after, and then
+ // compute the mask of bits we're after for the last byte then
+ // AND it with the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((FillMask[EndingOffset+1] & Byte) != 0) {
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpAreBitsSet (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure determines if the range of specified bits are all set.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+ StartingIndex - Supplies the starting bit index to examine
+
+ Length - Supplies the number of bits to examine
+
+Return Value:
+
+ BOOLEAN - TRUE if the specified bits in the bitmap are all set, and
+ FALSE if any are clear or if the range is outside the bitmap or if
+ Length is zero.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG EndingIndex;
+
+ ULONG StartingByte;
+ ULONG EndingByte;
+
+ ULONG StartingOffset;
+ ULONG EndingOffset;
+
+ ULONG i;
+ UCHAR Byte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the fields
+ // from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // First make sure that the specified range is contained within the
+ // bitmap, and the length is not zero.
+ //
+
+ if ((StartingIndex + Length > SizeOfBitMap) || (Length == 0)) {
+
+ return FALSE;
+ }
+
+ //
+ // Compute the ending index, starting and ending byte, and the starting
+ // and ending offset within each byte
+ //
+
+ EndingIndex = StartingIndex + Length - 1;
+
+ StartingByte = StartingIndex / 8;
+ EndingByte = EndingIndex / 8;
+
+ StartingOffset = StartingIndex % 8;
+ EndingOffset = EndingIndex % 8;
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, StartingByte );
+
+ //
+ // Special case the situation where the starting byte and ending
+ // byte are one in the same
+ //
+
+ if (StartingByte == EndingByte) {
+
+ //
+ // Get the single byte we are to look at
+ //
+
+ GET_BYTE( Byte );
+
+ //
+ // Now we compute the mask of bits we're after and then AND it with
+ // the complement of the byte If it is zero then the bits in question
+ // are all clear otherwise at least one of them is clear.
+ //
+
+ if ((ZeroMask[StartingOffset] & FillMask[EndingOffset+1] & ~Byte) == 0) {
+
+ return TRUE;
+
+ } else {
+
+ return FALSE;
+ }
+
+ } else {
+
+ //
+ // Get the first byte that we're after, and then
+ // compute the mask of bits we're after for the first byte then
+ // AND it with the complement of the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((ZeroMask[StartingOffset] & ~Byte) != 0) {
+
+ return FALSE;
+ }
+
+ //
+ // Now for every whole byte inbetween read in the byte,
+ // and make sure it is all ones
+ //
+
+ for (i = StartingByte+1; i < EndingByte; i += 1) {
+
+ GET_BYTE( Byte );
+
+ if (Byte != 0xff) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // Get the last byte we're after, and then
+ // compute the mask of bits we're after for the last byte then
+ // AND it with the complement of the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((FillMask[EndingOffset+1] & ~Byte) != 0) {
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+//ULONG
+//HalpCheckBit (
+// IN PRTL_BITMAP BitMapHeader,
+// IN ULONG BitPosition
+// )
+//
+///*++
+//
+//Routine Description:
+//
+// This procedure returns the state of the specified bit within the
+// specified bit map.
+//
+//Arguments:
+//
+// BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+//
+// BitPosition - Supplies the bit number of which to return the state.
+//
+//Return Value:
+//
+// ULONG - The state of the specified bit.
+//
+//--*/
+//
+//{
+// ULONG results;
+//
+// results = ((BitMapHeader->Buffer[BitPosition / 32]) >> (BitPosition % 32)) & 0x00000001;
+//
+// //DbgPrint("CheckBit %08lx", BitPosition);
+// //DbgPrint(" %08lx", results);
+// //DumpBitMap(BitMapHeader);
+//
+// return results;
+//}
+
diff --git a/private/ntos/nthals/halraw/alpha/bitmap.h b/private/ntos/nthals/halraw/alpha/bitmap.h
new file mode 100644
index 000000000..744f8544e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/bitmap.h
@@ -0,0 +1,252 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ bitmap.h
+
+Abstract:
+
+
+ ecrfix - (non-paged) copy of Rtl bitmap routines in HAL
+
+ Later: only include routines we really use, or come up with
+ a different solution.
+
+ This file defines the structures and definitions registers on a
+ Rawhide I/O Daughter card. These register reside on the CAP chip,
+ MDP chips, and flash ROM.
+
+
+Author:
+
+ Eric Rehm 17-Nov-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _BITMAPH_
+#define _BITMAPH_
+
+//
+// The following routine initializes a new bitmap. It does not alter the
+// data currently in the bitmap. This routine must be called before
+// any other bitmap routine/macro.
+//
+
+
+NTSYSAPI
+VOID
+NTAPI
+RtlFillMemoryUlong (
+ PVOID Destination,
+ ULONG Length,
+ ULONG Pattern
+ );
+
+VOID
+HalpInitializeBitMap (
+ PRTL_BITMAP BitMapHeader,
+ PULONG BitMapBuffer,
+ ULONG SizeOfBitMap
+ );
+
+//
+// The following two routines either clear or set all of the bits
+// in a bitmap.
+//
+
+
+VOID
+HalpClearAllBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+
+VOID
+HalpSetAllBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+//
+// The following two routines locate a contiguous region of either
+// clear or set bits within the bitmap. The region will be at least
+// as large as the number specified, and the search of the bitmap will
+// begin at the specified hint index (which is a bit index within the
+// bitmap, zero based). The return value is the bit index of the located
+// region (zero based) or -1 (i.e., 0xffffffff) if such a region cannot
+// be located
+//
+
+
+ULONG
+HalpFindClearBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+
+ULONG
+HalpFindSetBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+//
+// The following two routines locate a contiguous region of either
+// clear or set bits within the bitmap and either set or clear the bits
+// within the located region. The region will be as large as the number
+// specified, and the search for the region will begin at the specified
+// hint index (which is a bit index within the bitmap, zero based). The
+// return value is the bit index of the located region (zero based) or
+// -1 (i.e., 0xffffffff) if such a region cannot be located. If a region
+// cannot be located then the setting/clearing of the bitmap is not performed.
+//
+
+
+ULONG
+HalpFindClearBitsAndSet (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+
+ULONG
+HalpFindSetBitsAndClear (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+//
+// The following two routines clear or set bits within a specified region
+// of the bitmap. The starting index is zero based.
+//
+
+
+VOID
+HalpClearBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG NumberToClear
+ );
+
+
+VOID
+HalpSetBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG NumberToSet
+ );
+
+//
+// The following two routines locate the longest contiguous region of
+// clear or set bits within the bitmap. The returned starting index value
+// denotes the first contiguous region located satisfying our requirements
+// The return value is the length (in bits) of the longest region found.
+//
+
+
+ULONG
+HalpFindLongestRunClear (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+
+ULONG
+HalpFindLongestRunSet (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+//
+// The following two routines locate the first contiguous region of
+// clear or set bits within the bitmap. The returned starting index value
+// denotes the first contiguous region located satisfying our requirements
+// The return value is the length (in bits) of the region found.
+//
+
+
+ULONG
+HalpFindFirstRunClear (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+
+ULONG
+HalpFindFirstRunSet (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+//
+// The following macro returns the value of the bit stored within the
+// bitmap at the specified location. If the bit is set a value of 1 is
+// returned otherwise a value of 0 is returned.
+//
+// ULONG
+// HalpCheckBit (
+// PRTL_BITMAP BitMapHeader,
+// ULONG BitPosition
+// );
+//
+//
+// To implement CheckBit the macro retrieves the longword containing the
+// bit in question, shifts the longword to get the bit in question into the
+// low order bit position and masks out all other bits.
+//
+
+#define HalpCheckBit(BMH,BP) ((((BMH)->Buffer[(BP) / 32]) >> ((BP) % 32)) & 0x1)
+
+//
+// The following two procedures return to the caller the total number of
+// clear or set bits within the specified bitmap.
+//
+
+
+ULONG
+HalpNumberOfClearBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+
+ULONG
+HalpNumberOfSetBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+//
+// The following two procedures return to the caller a boolean value
+// indicating if the specified range of bits are all clear or set.
+//
+
+
+BOOLEAN
+HalpAreBitsClear (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG Length
+ );
+
+
+BOOLEAN
+HalpAreBitsSet (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG Length
+ );
+
+#endif //_BITMAPH_
diff --git a/private/ntos/nthals/halraw/alpha/busdata.c b/private/ntos/nthals/halraw/alpha/busdata.c
new file mode 100644
index 000000000..2c56e0c0e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/busdata.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+ Eric Rehm 13-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
+
diff --git a/private/ntos/nthals/halraw/alpha/cache.c b/private/ntos/nthals/halraw/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/devintr.s b/private/ntos/nthals/halraw/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/drivesup.c b/private/ntos/nthals/halraw/alpha/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halraw/alpha/ebsgdma.c b/private/ntos/nthals/halraw/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/eeprom8k.c b/private/ntos/nthals/halraw/alpha/eeprom8k.c
new file mode 100644
index 000000000..c03d04c0d
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/eeprom8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eeprom8k.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/eisaprof.c b/private/ntos/nthals/halraw/alpha/eisaprof.c
new file mode 100644
index 000000000..1fbc6426e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/eisaprof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisaprof.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/eisasup.c b/private/ntos/nthals/halraw/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5cache.c b/private/ntos/nthals/halraw/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5int.c b/private/ntos/nthals/halraw/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5ints.s b/private/ntos/nthals/halraw/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5mchk.c b/private/ntos/nthals/halraw/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5mem.s b/private/ntos/nthals/halraw/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5prof.c b/private/ntos/nthals/halraw/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/fwreturn.c b/private/ntos/nthals/halraw/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/haldebug.c b/private/ntos/nthals/halraw/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/halpal.s b/private/ntos/nthals/halraw/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/haltsup.s b/private/ntos/nthals/halraw/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/idle.s b/private/ntos/nthals/halraw/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/info.c b/private/ntos/nthals/halraw/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/inithal.c b/private/ntos/nthals/halraw/alpha/inithal.c
new file mode 100644
index 000000000..47f0a5b17
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/inithal.c
@@ -0,0 +1,1126 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inithal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+ 24-Sep-1993 Joe Notarangelo
+ Restructured to make this module platform-independent.
+
+--*/
+
+#include "halp.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+
+PERROR_FRAME PUncorrectableError = NULL;
+
+//
+// external
+//
+
+ULONG HalDisablePCIParityChecking = 0xffffffff;
+
+//
+// Define HAL spinlocks.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Mask of all of the processors that are currently active.
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// Mapping of the logical processor numbers to the physical processors.
+//
+
+HALP_PROCESSOR_ID HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ULONG AlreadySet = 0;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ;
+
+ULONGLONG HalpContiguousPhysicalMemorySize;
+
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+VOID
+HalpEarlyInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ );
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ );
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ MC_DEVICE_ID McDevid;
+ IOD_WHOAMI IodWhoAmI;
+ Prcb = PCR->Prcb;
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: entered, Processor = %d\n", PCR->Number );
+#endif
+ //
+ // Perform initialization for the primary processor.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+ if (Phase == 0) {
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+ HalpDumpMemoryDescriptors( LoaderBlock );
+#endif //HALDBG
+
+ //
+ // Get the memory Size.
+ //
+
+ HalpContiguousPhysicalMemorySize =
+ HalpGetContiguousMemorySize( LoaderBlock );
+
+ //
+ // Set second level cache size
+ // NOTE: Although we set the PCR with the right cache size this
+ // could be overridden by setting the Registry key
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
+ // \Control\Session Manager
+ // \Memory Management\SecondLevelDataCache.
+ //
+ // If the secondlevel cache size is 0 or 512KB then it is
+ // possible that the firmware is an old one. In which case
+ // we determine the cache size here. If the value is anything
+ // other than these then it is a new firmware and probably
+ // reporting the correct cache size hence use this value.
+ //
+
+ if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 ||
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){
+ PCR->SecondLevelCacheSize = HalpGetBCacheSize(
+ HalpContiguousPhysicalMemorySize
+ );
+ } else {
+ PCR->SecondLevelCacheSize =
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize;
+ }
+
+ //
+ // Initialize HAL spinlocks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Phase 0 initialization.
+ //
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d Callouts\n", Phase );
+ DbgPrint( "HAL/HalInitSystem: Early Machine Init\n");
+#endif //HALDBG
+ HalpEarlyInitializeMachineDependent( Phase, LoaderBlock );
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Set Time Increment\n");
+#endif //HALDBG
+ HalpSetTimeIncrement();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Map IO Space\n");
+#endif //HALDBG
+ HalpMapIoSpace();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Create DMA Structures\n");
+#endif //HALDBG
+ HalpCreateDmaStructures(LoaderBlock);
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Establish Error Handler\n");
+#endif //HALDBG
+ HalpEstablishErrorHandler();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Display\n");
+#endif //HALDBG
+ HalpInitializeDisplay(LoaderBlock);
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Machine Dependent\n");
+#endif //HALDBG
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Interrupts\n");
+#endif //HALDBG
+ HalpInitializeInterrupts();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Verify Prcb Version\n");
+#endif //HALDBG
+ HalpVerifyPrcbVersion();
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d complete\n", Phase );
+#endif //HALDBG
+ return TRUE;
+
+ } else {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ //
+ // Phase 1 initialization.
+ //
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d Callouts\n", Phase );
+ DbgPrint( "HAL/HalInitSystem: Init Clock Interrupts\n");
+#endif //HALDBG
+ HalpInitializeClockInterrupts();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Machine Dependent\n");
+#endif //HALDBG
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Allocate memory for the uncorrectable frame
+ //
+
+ HalpAllocateUncorrectableFrame();
+
+ //
+ // Initialize the Buffer for Uncorrectable Error.
+ //
+
+ HalpInitializeUncorrectableErrorFrame();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d Complete\n", Phase );
+#endif //HALDBG
+ return TRUE;
+
+ }
+ }
+
+ //
+ // Perform necessary processor-specific initialization for
+ // secondary processors. Phase is ignored as this will be called
+ // only once on each secondary processor.
+ //
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Map IO Space\n");
+#endif //HALDBG
+
+ HalpMapIoSpace();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Initialize Interrupts\n");
+#endif //HALDBG
+
+ HalpInitializeInterrupts();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Initialize Machine Dependent\n");
+#endif //HALDBG
+
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Set Active Processor Mask\n");
+#endif //HALDBG
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors |= 1 << Prcb->Number;
+
+#if HALDBG
+
+ DbgPrint( "Secondary %d is alive\n", Prcb->Number );
+
+#endif //HALDBG
+
+ return TRUE;
+}
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called after the Phase1 Machine Dependent initialization.
+ It must be called only after Phase1 machine-dependent initialization.
+ This function allocates the necessary amountof memory for storing the
+ uncorrectable error frame. This function makes a call to a machine-
+ dependent function 'HalpGetMachineDependentErrorFrameSizes' for
+ getting the size of the Processor Specific and System Specific error
+ frame size. The machine-dependent code will know the size of these
+ frames after the machine-dependent Phase1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG RawProcessorFrameSize;
+ ULONG RawSystemFrameSize;
+ ULONG EntireErrorFrameSize;
+
+ //
+ // First get the machine-dependent error frame sizes.
+ //
+ HalpGetMachineDependentErrorFrameSizes(
+ &RawProcessorFrameSize,
+ &RawSystemFrameSize);
+
+ //
+ // Compute the total size of the error frame
+ //
+ EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize +
+ RawSystemFrameSize;
+
+ //
+ // Allocate space to store the error frame.
+ // Not sure if it is OK to use ExAllocatePool at this instant.
+ // We will give this a try if it doesn't work What do we do??!!
+ //
+
+ PUncorrectableError = ExAllocatePool(NonPagedPool,
+ EntireErrorFrameSize);
+ if(PUncorrectableError == NULL) {
+ return;
+ }
+
+ PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize;
+
+ //
+ // if the size is not equal to zero then set the RawInformation pointers
+ // to point to the right place. If not set the pointer to NULL and set
+ // size to 0.
+ //
+
+ //
+ // make Raw processor info to point right after the error frame.
+ //
+ if(RawProcessorFrameSize) {
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ (PVOID)((PUCHAR)(&PUncorrectableError->UncorrectableFrame) + sizeof(ERROR_FRAME) );
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ RawProcessorFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ 0;
+ }
+ if(RawSystemFrameSize){
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame.
+ RawProcessorInformation + RawProcessorFrameSize);
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ RawSystemFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ 0;
+ }
+}
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+ )
+/*++
+
+Routine Description:
+
+ Collects the Processor Information and fills in the buffer.
+
+Arguments:
+
+ pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which
+ the processor information will be filled in.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+
+ pProcessorInfo->ProcessorType = PCR->ProcessorType;
+ pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision;
+
+ Prcb = PCR->Prcb;
+ pProcessorInfo->LogicalProcessorNumber = Prcb->Number;
+ pProcessorInfo->PhysicalProcessorNumber =
+ (ULONG) (MCDEVID_TO_PHYS_CPU(
+ HalpLogicalToPhysicalProcessor[Prcb->Number].all)
+ );
+ return;
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ ULONG LogicalNumber;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PhysicalNumber;
+ PKPRCB Prcb;
+
+#if !defined(NT_UP)
+
+#if 0 //HALDBG
+ DbgPrint("HalStartNextProcessor: enter\n");
+#endif
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ LogicalNumber = 0;
+ PhysicalNumber = 0;
+ do {
+
+ if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){
+
+#if 0 //HALDBG
+ DbgPrint(
+ "HalStartNextProcessor: Processor %d not ready\n",
+ PhysicalNumber
+ );
+#endif
+ PhysicalNumber += 1;
+
+ } else {
+
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ //
+ // Check if this processor has already been started.
+ // If it has not then start it now.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){
+
+ RtlZeroMemory( &NextRestartBlock->u.Alpha,
+ sizeof(ALPHA_RESTART_STATE));
+ NextRestartBlock->u.Alpha.IntA0 =
+ ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Alpha.IntSp =
+ ProcessorState->ContextFrame.IntSp;
+ NextRestartBlock->u.Alpha.ReiRestartAddress =
+ (ULONG) ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)LogicalNumber;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+
+ HalpInitializeProcessorMapping(
+ LogicalNumber,
+ PhysicalNumber,
+ LoaderBlock
+ );
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Ensure that the logical to physical mapping has been
+ // established for this processor.
+ //
+
+ HalpInitializeProcessorMapping(
+ LogicalNumber,
+ PhysicalNumber,
+ LoaderBlock
+ );
+
+ }
+
+ LogicalNumber += 1;
+ PhysicalNumber += 1;
+ }
+
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+
+ } while (NextRestartBlock != NULL);
+
+#endif // !defined(NT_UP)
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the HAL matches the kernel. If there
+ is a mismatch the HAL bugchecks the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PKPRCB Prcb;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+
+}
+
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PWSTR NameString;
+
+ //
+ // Quick out
+ //
+
+ if (AlreadySet) {
+ return;
+ }
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+ HalDisablePCIParityChecking = Component->Flags.ConsoleOut;
+ AlreadySet = TRUE;
+#if HALDBG
+ DbgPrint("ARC tree sets PCI parity checking to %s\n",
+ HalDisablePCIParityChecking ? "OFF" : "ON");
+#endif
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return ( ((ULONG) (Count2 - Count1)) *(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the processor counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+#if HALDBG
+ DbgPrint(
+ "Frequency = %d\nMegaHertz = %d\n",
+ HalpClockFrequency,
+ HalpClockMegaHertz
+ );
+#endif //HALDBG
+
+}
+
+
+
+
+#if 0
+VOID
+HalpGatherPerformanceParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
diff --git a/private/ntos/nthals/halraw/alpha/intsup.s b/private/ntos/nthals/halraw/alpha/intsup.s
new file mode 100644
index 000000000..fa1669189
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/intsup.s
@@ -0,0 +1,256 @@
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// intsup.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 24-Sep-93 Joe Notarangelo
+// Make this module platform-independent.
+//--
+
+#include "halalpha.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// VOID
+// HalpClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the primary processor. The routine is responsible for acknowledging the
+// interrupt and calling the kernel to update the system time.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+CiRa: .space 8 // space for return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt.
+//
+
+ bsr ra, HalpAcknowledgeRawhideClockInterrupt // ack the interrupt
+ beq v0, 30f // Roll over? No: return
+
+//
+// Yes: Call the kernel to update the system time.
+//
+
+ ldl a1, HalpCurrentTimeIncrement // Get current time increment
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateSystemTime
+ jsr ra, (t0) // call kernel
+
+// ldl t0, HalpNextTimeIncrement // Get next time increment
+// stl t0, HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+
+ ldl a0, HalpNextRateSelect // Get NextIntervalCount. If 0, no change required
+ beq a0, 20f
+
+ stl zero, HalpNextRateSelect // Set NextRateSelect to 0
+ bsr ra, HalpProgramIntervalTimer // Program timer with new rate select
+
+ ldl t0, HalpNewTimeIncrement
+ stl t0, HalpCurrentTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+// stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+
+//
+// Call to handle performance counter wrap.
+//
+20:
+ bsr ra, HalpCheckPerformanceCounter // check for perf. counter wrap
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ BREAK_BREAKIN // execute breakin breakpoint
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+30:
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpClockInterrupt
+
+
+#ifndef NT_UP
+
+ SBTTL("Secondary Processor Clock Interrupt")
+//++
+//
+// VOID
+// HalpSecondaryClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the current secondary processor. The routine is responsible for
+// acknowledging the interrupt and calling the kernel to update the
+// run time for the current processor.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ NESTED_ENTRY(HalpSecondaryClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt.
+//
+
+ bsr ra, HalpAcknowledgeRawhideClockInterrupt // ack the interrupt
+ beq v0, 40f // Roll over? No: return
+
+//
+// Call the kernel to update the run time.
+//
+10:
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateRunTime
+ jsr ra, (t0) // call kernel
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ BREAK_BREAKIN // execute breakin breakpoint
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+40:
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpSecondaryClockInterrupt
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// VOID
+// HalpIpiInterruptHandler
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interprocessor
+// interrupt asserted on the current processor. This function is
+// responsible for acknowledging the interrupt and dispatching to
+// the kernel for processing.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+IpiRa: .space 8 // space for return address
+IpiFrameLength: //
+
+ NESTED_ENTRY(HalpIpiInterruptHandler, IpiFrameLength, zero )
+
+ lda sp, -IpiFrameLength(sp) // allocate stack frame
+ stq ra, IpiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ bsr ra, HalpAcknowledgeIpiInterrupt // acknowledge interrupt
+
+ ldl t0, __imp_KeIpiInterrupt
+ jsr ra, (t0) // call kernel to process
+
+ ldq ra, IpiRa(sp) // restore return address
+ ret zero, (ra) // return
+
+ .end HalpIpiInterruptHandler
+
+
+#endif //NT_UP
+
diff --git a/private/ntos/nthals/halraw/alpha/iod.c b/private/ntos/nthals/halraw/alpha/iod.c
new file mode 100644
index 000000000..c04d46a85
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iod.c
@@ -0,0 +1,1467 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ iod.c
+
+Abstract:
+
+ This module implements functions that are specific to the IOD ASIC.
+ The IOD ASIC is a control ASIC for PCI on EV5-based Rawhide
+ systems.
+
+Author:
+
+ Eric Rehm 12-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+BOOLEAN IodInitialized = FALSE;
+
+MC_DEVICE_MASK HalpIodMask = 0x0;
+MC_DEVICE_MASK HalpCpuMask = 0x0;
+MC_DEVICE_MASK HalpGcdMask = 0x0;
+
+//
+// Declare the IOD interrupt vector table and global pointer
+// Due to the fact that the MC_DEVICE_ID specifies the 64
+// byte offset into this global table, we must allocate
+// full table for all
+//
+
+
+PIOD_POSTED_INTERRUPT HalpIodPostedInterrupts;
+
+//
+// Declare the PCI logical to physical mapping structure
+//
+
+MC_DEVICE_ID HalpIodLogicalToPhysical[RAWHIDE_MAXIMUM_PCI_BUS];
+
+//
+// The revision of the IOD. Software visible differences may exist between
+// passes of the IOD. The revision is determined once at the start of
+// run-time and used in places where the software must diverge.
+//
+
+IOD_PCI_REVISION HalpIodRevision;
+
+//
+// Declare routines local to this module
+//
+
+
+VOID
+HalpInitializeBitMap (
+ IN PRTL_BITMAP BitMapHeader,
+ IN PULONG BitMapBuffer,
+ IN ULONG SizeOfBitMap
+);
+
+
+
+VOID
+HalpInitializeIodMappingTable(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+/*++
+
+Routine Description:
+
+ This enumeration routine initialize the IOD logical to physical
+ mapping table. The Logical IOD number is via a static variable
+ that is incremented for each invokation of this routine.
+
+Arguments:
+
+ McDeviceId - IOD device id to be mapped.
+
+ PciBusNumber - Logical PCI Bus number (unused).
+
+ Arguments - variable arguments. None for this routine.
+
+Return Values:
+
+ None:
+
+--*/
+
+{
+ HalpIodLogicalToPhysical[PciBusNumber].all = 0;
+ HalpIodLogicalToPhysical[PciBusNumber].Gid = McDeviceId.Gid;
+ HalpIodLogicalToPhysical[PciBusNumber].Mid = McDeviceId.Mid;
+
+#if HALDBG
+ DbgPrint("HalpIodLogicalToPhysical[%d] = %x\n",
+ PciBusNumber,
+ HalpIodLogicalToPhysical[PciBusNumber]);
+#endif // HALDBG
+
+}
+
+VOID
+HalpInitializeIodVectorTable(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the global pointer to the IOD vector table.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Allocate the Global Iod vector table.
+ //
+
+ // mdbfix - we only need 4K, but require a page aligned
+ // address due to the fact that IOD uses target CPU's
+ // MC_DEVICE_ID as bits <11,6> of the vector table address
+ // in memory. So we allocate a PAGE more to guarantee
+ // a page aligned address.
+ //
+
+ HalpIodPostedInterrupts =
+ ExAllocatePool(
+ NonPagedPool,
+ __4K + __8K
+ );
+
+#if HALDBG
+ DbgPrint("HalpIodPostedInterrupts = 0x%x\n", HalpIodPostedInterrupts);
+#endif
+
+ if (HalpIodPostedInterrupts == NULL) {
+
+ DbgBreakPoint();
+
+ }
+}
+
+
+VOID
+HalpInitializeIod(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+/*++
+
+Routine Description:
+
+ This enumeration routine initializes the corresponding IOD.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical PCI Bus number (unused).
+
+ Arguments - Variable arguments including:
+
+ 1) LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_CAP_CONTROL IodCapControl;
+ IOD_CAP_ERR IodCapError;
+ IOD_WBASE Wbase;
+ IOD_TBASE Tbase;
+ IOD_WMASK Wmask;
+ IOD_TBIA Tbia;
+ IOD_MDPA_STAT IodMdpaStat;
+ IOD_MDPB_STAT IodMdpbStat;
+ IOD_MDPA_DIAG IodMdpaDiag;
+ IOD_MDPB_DIAG IodMdpbDiag;
+ PLOADER_PARAMETER_BLOCK LoaderBlock;
+
+ //
+ // Initialize parameters
+ //
+
+// mdbfix - this is not used
+// LoaderBlock = va_arg(Arguments, PLOADER_PARAMETER_BLOCK);
+
+ //
+ // Read the IOD revision.
+ //
+
+ HalpIodRevision.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision );
+
+#if HALDBG
+
+ DbgPrint( "Entry - HalpInitializeIod\n\n");
+
+ DbgPrint( "IOD (%x,%x) Revision: \n", McDeviceId.Gid, McDeviceId.Mid);
+ DbgPrint( "\tCAP = 0x%x\n", HalpIodRevision.CapRev );
+ DbgPrint( "\tHorse = 0x%x\n", HalpIodRevision.HorseRev );
+ DbgPrint( "\tSaddle = 0x%x\n", HalpIodRevision.SaddleRev );
+ DbgPrint( "\tSaddle Type = 0x%x\n", HalpIodRevision.SaddleType );
+ DbgPrint( "\tEISA Present = 0x%x\n", HalpIodRevision.EisaPresent );
+ DbgPrint( "\tPCI Class, Subclass = 0x%0.2x%0.2x\n",
+ HalpIodRevision.BaseClass, HalpIodRevision.SubClass );
+
+#endif //HALDBG
+
+ //
+ // Initialize IOD Control. Currently, take the initial values
+ // set by the Extended SROM.
+ //
+
+ IodCapControl.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
+
+#if HALDBG
+
+ DbgPrint( "Read Iod CAP Control = 0x%0.4x\n", IodCapControl.all );
+
+#endif //HALDBG
+
+
+#ifdef RISP //ecrfix
+
+ //
+ // For RISP, initialized as per Rawhide S/W Programmers Manual
+ //
+
+ IodCapControl.DlyRdEn = 1;
+ IodCapControl.PciMemEn = 1;
+ IodCapControl.PciReq64 = 1;
+ IodCapControl.PciAck64 = 1;
+ IodCapControl.PciAddrPe= 1;
+ IodCapControl.McCmdAddrPe= 1;
+ IodCapControl.McNxmEn = 1;
+ IodCapControl.McBusMonEn= 1;
+ IodCapControl.PendNum = 11; // 12 - [ (0 * 2) + 1 + (0 * 2)]
+ IodCapControl.RdType = 2;
+ IodCapControl.RlType = 2;
+ IodCapControl.RmType = 2;
+ IodCapControl.PartialWrEn = 0;
+ IodCapControl.ArbMode = 0;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl,
+ IodCapControl.all );
+#if HALDBG
+
+ IodCapControl.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
+
+ DbgPrint( "Read Iod CAP Control = 0x%0.4x\n (after sets)", IodCapControl.all );
+
+#endif //HALDBG
+
+#endif //RISP
+
+
+ //
+ // Disable all of the scatter/gather windows.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 0;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base,
+ Wbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base,
+ Wbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2base,
+ Wbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3base,
+ Wbase.all );
+
+ //
+ // Invalidate all of the TLB Entries.
+ //
+
+ Tbia.all = 0;
+
+ //
+ // Perform the invalidation.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia,
+ Tbia.all );
+
+ //
+ // Clear any pending error bits in the IOD_CAP_ERR register:
+ //
+
+ IodCapError.all = 0; // Clear all bits
+
+ IodCapError.Perr = 1; // PCI bus perr detected
+ IodCapError.Serr = 1; // PCI bus serr detected
+ IodCapError.Mab = 1; // PCI bus master abort detected
+ IodCapError.PteInv = 1; // Invalid Pte
+ IodCapError.PioOvfl = 1; // Pio Ovfl
+ IodCapError.LostMcErr = 1; // Lost error
+ IodCapError.McAddrPerr = 1; // MC bus comd/addr parity error
+ IodCapError.Nxm = 1; // MC bus Non-existent memory error
+ IodCapError.CrdA = 1; // Correctable ECC error on MDPA
+ IodCapError.CrdB = 1; // Correctable ECC error on MDPB
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapError.all );
+
+ //
+ // Clear any ECC error syndrome bits in the IOD_MDPA/B_SYN registers:
+ //
+
+ IodMdpaStat.all = 0;
+ IodMdpaStat.Crd = 1; // Correctable ECC error (also clears Rds bit)
+
+ IodMdpbStat.all = 0;
+ IodMdpbStat.Crd = 1; // Correctable ECC error (also clears Rds bit)
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodMdpaStat.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat,
+ IodMdpbStat.all );
+
+#if 0 // CAP/MDP Bug
+
+ IodMdpaStat.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat );
+
+ DbgPrint( "MDPA (%x,%x) Revision = 0x%x\n",
+ McDeviceId.Gid, McDeviceId.Mid, IodMdpaStat.MdpaRev);
+
+ IodMdpaStat.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat );
+
+ DbgPrint( "MDPB (%x,%x) Revision = 0x%x\n",
+ McDeviceId.Gid, McDeviceId.Mid, IodMdpbStat.MdpbRev);
+
+#endif
+
+
+ //
+ // Initialize MDP Diagnostic Checking. Currently just take the
+ // initial values set by the Extended SROM. Do both Mdpa and Mdpb.
+ //
+
+#if 0 // CAP/MDP Bug
+
+ IodMdpaDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag );
+
+ DbgPrint( "Read Iod MDPA Diag = 0x%0.4x\n", IodMdpaDiag.all );
+
+ IodMdpbDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag );
+
+ DbgPrint( "Read Iod MDPB Diag = 0x%0.4x\n", IodMdpbDiag.all );
+
+#endif
+
+#if defined(AXP_FIRMWARE)
+
+ //
+ // Disable MCI bus interrupts
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
+ );
+
+ //
+ // Clear interrupt request register (New for CAP Rev2.3)
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq,
+ IodIntMask
+ );
+
+ //
+ // Clear all pending interrupts for this IOD
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
+ 0x0
+ );
+
+ //
+ // Clear all pending EISA interrupts for IOD 0
+ //
+
+ if ( (McDeviceId.Gid == GidPrimary) && (McDeviceId.Mid == MidPci0) ) {
+
+ INTERRUPT_ACKNOWLEDGE((PVOID)IOD_PCI0_IACK_QVA);
+
+ }
+
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ (GidPrimary << 9)|(MidCpu1 << 6)|
+ (GidPrimary << 3)|(MidCpu0)
+ );
+
+ //
+ // Initialize the mask bits for target 0 and 1
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0,
+ 0
+ );
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1,
+ 0
+ );
+
+#endif //if defined(AXP_FIRMWARE)
+
+ IodInitialized = TRUE;
+
+}
+
+VOID
+HalpClearAllIods(
+ IOD_CAP_ERR IodCapErrMask
+)
+/*++
+
+Routine Description:
+
+ Clears specified CapErr bits on all IODs.
+
+Arguments:
+
+ IodCapErrMask - Mask of bits to be cleared in each IOD_CAP_ERR.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+ IOD_CAP_ERR IodCapErr;
+
+
+ //
+ // Clear all the error conditions in CAP_ERR on all IODs
+ // (Note - on 2 Mb Cached CPU, LostMcErr may also be set, so
+ // clear everything to be fer-sure, fer-sure.)
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Clear all errors on all IODs.
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read it
+ //
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+ //
+ // Mask it.
+ //
+
+ IodCapErr.all &= IodCapErrMask.all;
+
+ //
+ // If there is anything to clear, then do it.
+ //
+
+ if (IodCapErr.all != 0) {
+
+ WRITE_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapErr.all );
+
+
+ }
+ }
+ }
+
+
+VOID
+HalpInitializeIodVectorCSRs(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+/*++
+
+Routine Description:
+
+ This enumeration routine initializes Interrupt Vector Table CSRS
+ for the corresponding IOD.
+
+ The address used by an IOD during interrupt vector writes
+ is:
+
+ 39 38 32 31 12 11 6 5 2 1 0
+ | | | | | | | | | | |
+ ===================================================================
+ |0 | INT_ADDR_EXT | INT_ADDR_LO | TARGET ID | PCI BUS OFFSET | 00 |
+ ===================================================================
+
+ Where:
+ INT_ADDR_EXT = 0 since our table resides in KSEG0_BASE.
+ INT_ADDR_LO = upper 20 bits (4K Page Addr) of Table Physical Address
+ TARGET_ID = MC_DEVICE_ID of Target CPU obtained from INT_TARG(0|1)
+ PCI_BUS_OFFSET = Logical PCI bus number used as an offset into vector
+ table by the interrupting IOD.
+
+ The assignment of PCI_BUS_OFFSET is based on the PCI bus number static
+ variable. This number is incremented with each invokation of this routine.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical PCI Bus number (unused).
+
+ Arguments - Variable Arguments. None for this routine.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_INT_ADDR IodIntAddr;
+ IOD_INT_ADDR_EXT IodIntAddrExt;
+ IOD_INT_CONTROL IodIntControl;
+
+ //
+ // Initialize the Interrupt Vector Table Address register
+ // for this IOD.
+ //
+
+ IodIntAddr.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr );
+
+ IodIntAddr.Reserved1 = 0; // MBZ
+ IodIntAddr.PciOffset = PciBusNumber; // Logical IOD #
+ IodIntAddr.Reserved2 = 0; // MBZ
+ IodIntAddr.IntAddrLo = ((ULONG)HalpIodPostedInterrupts / __4K);
+
+ //
+ // Mask off the KSEG0_BASE to convert this to a physical
+ // address.
+ //
+
+ IodIntAddr.all &= ~KSEG0_BASE;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr,
+ IodIntAddr.all );
+
+ //
+ // Initialize the interrupt vector table Address Extension
+ // register to zero since our address resides in KSEG0_BASE.
+ //
+
+ IodIntAddrExt.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt );
+
+ IodIntAddrExt.all = 0;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt,
+ IodIntAddrExt.all );
+}
+
+
+VOID
+HalpIodInitializeSfwWindow(
+// ecrfix MC_DEVICE_ID McDeviceId,
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ IOD_WINDOW_NUMBER WindowNumber
+ )
+/*++
+
+Routine Description:
+
+ Initialize the DMA Control software window registers for the specified
+ DMA Window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control.
+
+ WindowNumber - Supplies the window number initialized. (0 = Isa Dma
+ Window, 1 = Master Dma Window).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ switch( WindowNumber ){
+
+ //
+ // The ISA DMA Window.
+ //
+
+ case IodIsaWindow:
+
+ WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T1base;
+ WindowRegisters->WindowBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base;
+ WindowRegisters->WindowMaskRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1mask;
+ WindowRegisters->WindowTbiaRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
+
+ break;
+
+ case IodMasterWindow:
+
+ WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T0base;
+ WindowRegisters->WindowBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base;
+ WindowRegisters->WindowMaskRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0mask;
+ WindowRegisters->WindowTbiaRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
+
+ break;
+
+ default:
+
+#if HALDBG
+
+ DbgPrint( "IodInitializeSfwWindow: Bad Window Number = %x\n",
+ WindowNumber );
+
+#endif //HALDBG
+
+ break;
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpIodProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ Program the control windows in the hardware so that DMA can be started
+ to the DMA window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ MapRegisterBase - Supplies the logical address of the scatter/gather
+ array in system memory.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_WBASE Wbase;
+ IOD_TBASE Tbase;
+ IOD_WMASK Wmask;
+ IOD_TBIA Tbia;
+
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceId;
+
+ //
+ // Program the windows as specified by the caller.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 1;
+ Wbase.SgEn = 1;
+ Wbase.Wbase = (ULONG)(WindowRegisters->WindowBase) >> 20;
+
+ Wmask.all = 0;
+ Wmask.Wmask = (WindowRegisters->WindowSize >> 20) - 1;
+
+ Tbase.all = 0;
+ Tbase.Tbase = (ULONG)MapRegisterBase >> 10;
+
+ Tbia.all = 0;
+
+ //
+ // Dump the IOD registers.
+ //
+
+#if HALDBG
+
+// DumpAllIods( IodScatterGatherRegisters );
+
+#endif //HALDBG
+
+ //
+ // Loop through all of the Iods
+ //
+ // ecrfix - is it OK to do it one at a time this way?
+ //
+
+ HalpMcBusEnumStart( HalpIodMask, &mcCtx );
+
+ while ( HalpMcBusEnum ( &mcCtx ) ) {
+
+ McDeviceId = mcCtx.McDeviceId;
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowBaseRegister, 0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->TranslatedBaseRegister,
+ Tbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowMaskRegister,
+ Wmask.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowBaseRegister,
+ Wbase.all );
+
+ //
+ // Flush the volatile entries in this IOD's scatter/gather Tlb.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowTbiaRegister,
+ Tbia.all );
+ }
+
+ // ecrfix - we did it above. HalpIodInvalidateTlb( WindowRegisters );
+
+ //
+ // Dump the IOD registers.
+ //
+
+#if HALDBG
+
+// DumpAllIods( IodScatterGatherRegisters | IodGeneralRegisters );
+
+#endif //HALDBG
+
+ return;
+}
+
+
+ULONG
+HalpMcBusEnumStart(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_CONTEXT McContext
+ )
+/*++
+
+Routine Description:
+
+ Given a particular MC Bus device mask:
+
+ * Set up state so that subsequent MC Bus devices can be enumerated
+ by calling HalpMcBusEnum( McContext ).
+
+ * Return the first MC_DEVICE_ID in that mask via McContext.
+ (ECRFIX: IFDEF out for now!)
+
+ N.B. The search will start with GID = 7, i.e., McDeviceMask<56>
+ because the primary GID is 7.
+
+Arguments:
+
+ McDeviceMask - Supplies a bitfield of MC Bus devices to be enumerated.
+
+ McContext - A structure that contains the MC_DEVICE_ID to be enumerated
+ and associated enumerator state.
+
+
+Return Value:
+
+ Number of MC Bus devices to be enumerated.
+
+--*/
+{
+ ULONG count;
+
+ //
+ // Intialize the bitmap from the McDeviceMask.
+ // (Make a copy so that McDeviceMask is preserved for the caller.)
+ //
+
+ McContext->tempMask = McDeviceMask;
+
+// RtlInitializeBitMap(&McContext->McDeviceBitmap,
+ HalpInitializeBitMap(&McContext->McDeviceBitmap,
+ (PULONG) &McContext->tempMask,
+ sizeof(MC_DEVICE_MASK) * 8);
+
+ //
+ // Count the number of device to be enuerated
+ //
+
+ count = HalpNumberOfSetBits (&McContext->McDeviceBitmap);
+
+ //
+
+ // Start looking at GID = 7.
+ //
+
+ McContext->nextBit = GidPrimary * 8;
+
+#if 0
+ //
+ // Find the first MC Bus device to be enumerated.
+ //
+
+ McContext->nextBit = HalpFindSetBitsAndClear (&McContext->McDeviceBitmap,
+ 1,
+ McContext->nextBit);
+
+ //
+ // Convert first non-zero bit found to MC_DEVICE_ID
+ //
+
+ McContext->McDeviceId.all = 0;
+ McContext->McDeviceId.Gid = McContext->nextBit / 8;
+ McContext->McDeviceId.Mid = McContext->nextBit % 8;
+#endif
+
+ return ( count );
+
+}
+
+BOOLEAN
+HalpMcBusEnum(
+ PMC_ENUM_CONTEXT McContext
+ )
+/*++
+
+Routine Description:
+
+ Enumerate MC Bus devices until none are left
+
+Arguments:
+
+ McContext - A structure that contains the MC_DEVICE_ID to be enumerated
+ and associated enumerator state.
+
+
+Return Value:
+
+ TRUE, unless there were no more MC Bus devices to be enumerated,
+ in which case, returns FALSE.
+
+--*/
+{
+ //
+ // Find the next MC Bus device.
+ //
+
+ McContext->nextBit = HalpFindSetBitsAndClear (&McContext->McDeviceBitmap,
+ 1,
+ McContext->nextBit);
+
+ if ( McContext->nextBit != 0xffffffff) {
+
+ //
+ // Convert the non-zero bit found to MC_DEVICE_ID
+ //
+
+ McContext->McDeviceId.all = 0;
+ McContext->McDeviceId.Gid = McContext->nextBit / 8;
+ McContext->McDeviceId.Mid = McContext->nextBit % 8;
+
+ //
+ // Since we just set nextBit to zero, we can start the
+ // next search one bit higher. This will speed up the
+ // next call to HalpMcBusEnum.
+ //
+
+ McContext->nextBit++;
+
+ return ( TRUE );
+
+ } else {
+
+ return ( FALSE) ;
+
+ }
+
+}
+
+VOID
+HalpMcBusEnumAndCall(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_ROUTINE McBusEnumRoutine,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Execute the Call routine for all devices in the MC device mask.
+ This routine provides a general method to enumerate an MC_DEVICE_MASK
+ and execute a caller-supplied routine for each device. A logical
+ device number and variable arguments are passed to the routine.
+
+Arguments:
+
+ McDeviceMask - Supplies a bitfield of MC Bus devices to be enumerated.
+
+ McBusEnumRoutine - Routine that is called for each MC Bus device.
+
+ ... - Variable arguments passed by the caller.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ ULONG LogicalDeviceNumber = 0;
+ va_list Arguments;
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( McDeviceMask, &mcCtx );
+
+ //
+ // Execute routine for each device.
+ //
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+ va_start(Arguments, McBusEnumRoutine);
+ McBusEnumRoutine( mcCtx.McDeviceId, LogicalDeviceNumber++, Arguments );
+ va_end(Arguments);
+ }
+}
+
+
+ULONG
+HalpReadWhoAmI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the WHOAMI register.
+Arguments:
+
+ None.
+Return Value:
+
+ The value of the WHOAMI.
+
+--*/
+{
+
+ MC_DEVICE_ID McDeviceId;
+ IOD_WHOAMI IodWhoAmI;
+
+
+ //
+ // Initialize Id for IOD 0.
+ //
+
+ McDeviceId.all = 0;
+ McDeviceId.Gid = GidPrimary;
+ McDeviceId.Mid = MidPci0;
+
+
+ return (
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI )
+ );
+
+}
+
+
+VOID
+HalpIodInvalidateTlb(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters
+ )
+/*++
+
+Routine Description:
+
+ Invalidate the DMA Scatter/Gather TLB in all the IODs.
+ The TLB is invalidated whenever the scatter/gather translation
+ entries are modified.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Perform the S/G TLB invalidation
+ //
+
+ IOD_TBIA Tbia;
+ MC_ENUM_CONTEXT mcCtx;
+
+ Tbia.all = 0;
+
+ HalpMcBusEnumStart(HalpIodMask, &mcCtx);
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+
+ WRITE_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ WindowRegisters->WindowTbiaRegister,
+ Tbia.all );
+
+ }
+
+}
+
+
+#if HALDBG || DUMPIODS
+
+IOD_REGISTER_CLASS DumpIodFlag = AllRegisters;
+
+VOID
+DumpAllIods(
+ IOD_REGISTER_CLASS RegistersToDump
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting Iod registers and print them to the debug port.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be dumped
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG NumIods;
+
+ DbgPrint( "Dump All IODs: \n" );
+
+ NumIods = HalpMcBusEnumStart(HalpIodMask, &mcCtx);
+
+ DbgPrint( "Dump All IODs: (%d IODs)\n", NumIods );
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+
+ DumpIod( mcCtx.McDeviceId,
+ RegistersToDump );
+ }
+
+
+}
+
+VOID
+DumpIod(
+ MC_DEVICE_ID McDeviceId,
+ IOD_REGISTER_CLASS RegistersToDump
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting Iod registers and print them to the debug port.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be dumped
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ ULONG Value;
+
+ DbgPrint( "IOD (%x, %x) Register Dump: \n", McDeviceId.Gid, McDeviceId.Mid );
+
+ //
+ // Dump the IOD General Control registers.
+ //
+
+ if( (RegistersToDump & IodGeneralRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IodRevision = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "WhoAmI = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciLat;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "PciLat = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IodCtrl = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeMem;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "HaeMem = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeIo;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "HaeIo = 0x%x\n", Value );
+
+#if 0 // ecrfix - don't read this on PCI0 - creates an IACK cycle
+ // on the EISA bus. Don't read this on PCI1,2,3, because
+ // (apparently), it doesn't exist there.
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->IackSc;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IackSc = 0x%x\n", Value );
+#endif
+
+ }
+
+ //
+ // Dump the IOD Interrupt registers.
+ //
+
+ if( (RegistersToDump & IodInterruptRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntCtrl = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntReq = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntTarg = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntAddr = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntAddrExt = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntMask0 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntMask1 = 0x%x\n", Value );
+
+
+ }
+
+ //
+ // Dump the IOD Diagnostic registers.
+ //
+
+ if( (RegistersToDump & IodDiagnosticRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_DIAG_CSRS)(IOD_DIAG_CSRS_QVA))->CapDiag;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "CapDiag = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_DIAG_CSRS)(IOD_DIAG_CSRS_QVA))->Scratch;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Scratch = 0x%x\n", Value );
+
+ }
+
+ //
+ // Dump the IOD Error registers.
+ //
+
+ if( (RegistersToDump & IodErrorRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr0;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MCErr0 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MCErr1 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "CapErr = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "PciErr1 = 0x%x\n", Value );
+
+#if 0 // CAP/MDP Bug
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpaStat = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaSyn;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpaSyn = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpaDiag = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpbStat = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbSyn;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpbSyn = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpbDiag = 0x%x\n", Value );
+#endif
+ }
+
+ //
+ // Dump the PCI Scatter/Gather registers.
+ //
+
+ if( (RegistersToDump & IodScatterGatherRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Tbia = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Hbase;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Hbase = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W0base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W0mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T0base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T0base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W1base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W1mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T1base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T1base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W2base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W2mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T2base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T2base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W3base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W3mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T3base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T3base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Wdac;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Wdac = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag0;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag0 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag1 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag2;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag2 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag3;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag3 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag4;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag4 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag5;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag5 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag6;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag6 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag7;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag7 = 0x%x\n", Value );
+ }
+
+ //
+ // Dump the IOD Reset register.
+ //
+
+ if( (RegistersToDump & IodResetRegister) != 0 ){
+
+ RegisterQva = (PIOD_ELCR1)((ULONG)HalpEisaControlBase + 27);
+ Value = (ULONG) READ_PORT_UCHAR( (PUCHAR) RegisterQva );
+ DbgPrint( "ELCR2 = 0x%x\n", Value );
+
+ }
+
+
+ DbgPrint( "--end IOD Register dump\n\n" );
+
+ return;
+
+}
+
+#endif //HALDBG || DUMPIODS
+
diff --git a/private/ntos/nthals/halraw/alpha/iod.h b/private/ntos/nthals/halraw/alpha/iod.h
new file mode 100644
index 000000000..6aee89719
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iod.h
@@ -0,0 +1,1669 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ iod.h
+
+Abstract:
+
+ This file defines the structures and definitions registers on a
+ Rawhide I/O Daughter card. These register reside on the CAP chip,
+ MDP chips, and flash ROM.
+
+
+Author:
+
+ Eric Rehm 16-Feb-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _IODH_
+#define _IODH_
+
+
+//
+// IOD Revision definitions.
+//
+
+#define IOD_REVISION_1 (0)
+#define IOD_REVISION_2 (1)
+
+//
+// Define QVA constants.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xA0000000) // Identify VA as a QVA
+
+#endif //QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+#define IOD_SPARSE_SELECTORS (0x18000000) // BusNumber is encoded in QVA<28:27>
+#define IOD_SPARSE_ENABLE (0xB8000000) // QVA_SELECTORS|IOD_SPARSE_SELECTORS
+#define IOD_SPARSE_BUS_SHIFT 0x06 // Bits to shift BusNumber into MID
+
+#define IOD_DENSE_SELECTORS (0xC0000000) // BusNumber is encoded in QVA<31:30>
+#define IOD_DENSE_ENABLE (0xC0000000) // Same as IOD_DENSE_SELECTORS
+#define IOD_DENSE_BUS_SHIFT 0x03 // Bits to shift BusNumber into MID
+
+//
+// Define size of I/O and memory space for the CIA.
+// Assume that the HAE==0.
+//
+
+#define PCI_MAX_IO_ADDRESS (__32MB - 1) // I/O: 0 - 32MB
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS (__128MB - 1) // Mem: 0 - 128MB
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MAX_SPARSE_MEMORY_ADDRESS + 1
+#define PCI_MAX_DENSE_MEMORY_ADDRESS (__1GB - 1) // Dense: 128 Mb - 1.0 Gb
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+#define GID_TO_PHYS_ADDR( GID ) ((ULONGLONG)(((GID & 0x7) << 36))
+#define MCDEVID_FROM_PHYS_ADDR( PA ) ( (ULONG)(((PA) >> 33) & 0x3f) )
+#if 0
+#define MCDEVID_TO_PHYS_ADDR( MCDEVID ) \
+ ((ULONGLONG)((ULONGLONG)(MCDEVID & 0x3F ) << 33 ))
+#else
+#define MCDEVID_TO_PHYS_ADDR( MCDEVID ) \
+ ((ULONGLONG)((ULONGLONG)(MCDEVID & 0x07 ) << 33 ))
+#endif
+#define MCDEVID_TO_PHYS_CPU( MCDEVID ) \
+ ( (((MCDEVID) & 0x07) < 4) ? \
+ (((MCDEVID) & 0x07) - 2) : \
+ (((MCDEVID) & 0x07) - 4) )
+#define PHYS_ADDR_TO_OFFSET( PA ) ( (PA) & ( (ULONGLONG) 0x1FFFFFFFF) )
+#define IOD_QVA_PHYSICAL_BASE ((ULONGLONG)0xf800000000)
+
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | \
+ (ULONG)( (PA - IOD_QVA_PHYSICAL_BASE) >> IO_BIT_SHIFT) ) )
+
+//
+// QVA
+// HAL_MAKE_IOD_SPARSE_QVA(
+// ULONG BusNumber,
+// ULONG BusAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in sparse I/O
+// or sparse memory space.
+//
+// Arguments:
+//
+// BusNumber - Supplies a bus number between 0-3.
+// BusAddress - Supplies a 32-bit PCI bus address.
+//
+// Return Value:
+//
+// The Qva associated with bus number and bus address.
+// HAL I/O access routines can use this to constrct the
+// correct physical address for the accesss.
+//
+
+#define HAL_MAKE_IOD_SPARSE_QVA(BUS_NUMBER, BA) \
+ ( (PVOID)( QVA_ENABLE | (BUS_NUMBER << 27) | ((ULONG) BA) ) )
+
+
+//
+// QVA
+// HAL_MAKE_IOD_DENSE_QVA(
+// ULONG BusNumber,
+// ULONG BusAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in dense
+// memory space space.
+//
+// Arguments:
+//
+// BusNumber - Supplies a bus number between 0-3.
+// BusAddress - Supplies a 32-bit PCI bus address.
+//
+// Return Value:
+//
+// The Qva associated with bus number and bus address.
+// HAL I/O access routines can use this to constrct the
+// correct physical address for the accesss.
+//
+
+#define HAL_MAKE_IOD_DENSE_QVA(BUS_NUMBER, BA) \
+ ( (PVOID)( (BUS_NUMBER << 30) | ((ULONG) BA) ) )
+
+
+
+
+//
+// Define GID/MIDs for IIP and PIO flavors of MC Bus
+//
+
+#define IOD_DODGE_GID 0x7
+#define IOD_DURANGO_GID IOD_DODGE_GID
+
+#define IOD_GCD_MID 0x0
+#define IOD_MEM_MID 0x1
+#define IOD_CPU0_MID 0x2
+#define IOD_CPU1_MID 0x3
+#define IOD_PCI0_MID 0x4
+#define IOD_PCI1_MID 0x5
+#define IOD_CPU2_MID 0x6
+#define IOD_PCI2_MID IOD_CPU2_MID
+#define IOD_CPU3_MID 0x7
+#define IOD PCI3_MID IOD_CPU3_MID
+
+//
+// QVA
+// HAL_MAKE_NEW_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_NEW_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | (ULONG)( (PA) >> IO_BIT_SHIFT) ) )
+
+//
+// Define IO space offsets for generic rawhide
+//
+
+#define IOD_IO_SPACE_START ((ULONGLONG)0x8000000000)
+
+//
+// These offsets are from IOD_IO_SPACE_START
+//
+
+#define IOD_GCD_CSRS_OFFSET ((ULONGLONG)0x0000000000)
+#define IOD_MEMORY_CSRS_OFFSET ((ULONGLONG)0x0200000000)
+
+#define IOD_CPU_IP_INTR_OFFSET ((ULONGLONG)0x0010000000)
+#define IOD_CPU_NODE_HALT_OFFSET ((ULONGLONG)0x0070000000)
+#define IOD_CPU_INTTIM_ACK_OFFSET ((ULONGLONG)0x0100000000)
+#define IOD_CPU_IO_INTR_OFFSET ((ULONGLONG)0x00f0000000)
+#define IOD_CPU_IP_ACK_OFFSET ((ULONGLONG)0x0110000000)
+#define IOD_CPU_MCHK_ACK_OFFSET ((ULONGLONG)0x0130000000)
+#define IOD_CPU_DTAG_EN_0_OFFSET ((ULONGLONG)0x0140000000)
+#define IOD_CPU_DTAG_EN_1_OFFSET ((ULONGLONG)0x0150000000)
+#define IOD_CPU_HALT_ACK_OFFSET ((ULONGLONG)0x0170000000)
+
+#define IOD_SPARSE_MEM_OFFSET ((ULONGLONG)0x0000000000)
+#define IOD_DENSE_MEM_OFFSET ((ULONGLONG)0x0100000000)
+#define IOD_SPARSE_IO_OFFSET ((ULONGLONG)0x0180000000)
+#define IOD_SPARSE_CONFIG_OFFSET ((ULONGLONG)0x01c0000000)
+#define IOD_SPARSE_CSR_OFFSET ((ULONGLONG)0x01e0000000)
+
+//
+// Generic Rawhide I/O Address Computation macros
+//
+
+#define IOD_GCD_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_GCD_CSRS_OFFSET))
+
+#define IOD_MEMORY_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_MEMORY_CSRS_OFFSET))
+
+#define IOD_CPU_IP_INTR_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_IP_INTR_OFFSET))
+
+#define IOD_CPU_NODE_HALT_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_NODE_HALT_OFFSET))
+
+#define IOD_CPU_IO_INTR_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_IO_INTR_OFFSET))
+
+#define IOD_CPU_INTTIM_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_INTTIM_ACK_OFFSET))
+
+#define IOD_CPU_IP_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_IP_ACK_OFFSET))
+
+#define IOD_CPU_MCHK_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_MCHK_ACK_OFFSET))
+
+#define IOD_CPU_DTAG_EN_0_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_DTAG_EN_0_OFFSET))
+
+#define IOD_CPU_DTAG_EN_1_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_DTAG_EN_1_OFFSET))
+
+#define IOD_CPU_HALT_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_HALT_ACK_OFFSET))
+
+#define IOD_SPARSE_MEM_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_MEM_OFFSET ))
+
+#define IOD_DENSE_MEM_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_DENSE_MEM_OFFSET ))
+
+#define IOD_SPARSE_IO_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_IO_OFFSET ))
+
+#define IOD_SPARSE_CONFIG_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CONFIG_OFFSET ))
+
+#define IOD_SPARSE_CSR_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET ))
+
+#define IOD_GENERAL_CSRS_QVA IOD_SPARSE_CSR_QVA
+
+#define IOD_PCI_IACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x480))
+
+#define IOD_INT_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x500))
+
+#define IOD_DIAG_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x700))
+
+#define IOD_ERROR_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x800))
+
+#define IOD_SG_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x1300))
+
+//
+// Define physical address space for 1 CPU at GID=7, MID=1,
+// and XSone IOD. // ecrfix
+//
+
+#define IOD_GCD_CSRS_PHYSICAL ((ULONGLONG)0xf000000000)
+#define IOD_MEMORY_CSRS_PHYSICAL ((ULONGLONG)0xf200000000)
+
+#define IOD_CPU0_IO_INTR_PHYSICAL ((ULONGLONG)0xf400000000)
+#define IOD_CPU0_IP_INTR_PHYSICAL ((ULONGLONG)0xf510000000)
+#define IOD_CPU0_NODE_HALT_PHYSICAL ((ULONGLONG)0xf520000000)
+
+//
+// PCI Bus 0
+//
+
+// old ecrfix #define IOD_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0xf800000000)
+// old ecrfix #define IOD_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0xf900000000)
+#define IOD_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0xf800000000)
+#define IOD_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0xf900000000)
+#define IOD_PCI0_SPARSE_IO_PHYSICAL ((ULONGLONG)0xf980000000)
+#define IOD_PCI0_CONFIGURATION_PHYSICAL ((ULONGLONG)0xf9C0000000)
+#define IOD_MAIN0_CSRS_PHYSICAL ((ULONGLONG)0xf9E0000000)
+
+#define IOD_PCI0_CONFIG_BASE_QVA (HAL_MAKE_QVA(IOD_PCI0_CONFIGURATION_PHYSICAL))
+#define IOD_PCI0_SPARSE_IO_QVA (HAL_MAKE_QVA(IOD_PCI0_SPARSE_IO_PHYSICAL))
+#define IOD_PCI0_SPARSE_MEMORY_QVA (HAL_MAKE_QVA(IOD_PCI0_SPARSE_MEMORY_PHYSICAL))
+
+#define IOD_GENERAL0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL)
+#define IOD_GENERAL0_CSRS_QVA HAL_MAKE_QVA(IOD_GENERAL0_CSRS_PHYSICAL)
+
+#define IOD_PCI0_IACK_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x480)
+#define IOD_PCI0_IACK_QVA HAL_MAKE_QVA(IOD_PCI0_IACK_PHYSICAL)
+
+#define IOD_INT0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x500)
+#define IOD_INT0_CSRS_QVA HAL_MAKE_QVA(IOD_INT0_CSRS_PHYSICAL)
+#define IOD_DIAG0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x700)
+#define IOD_DIAG0_CSRS_QVA HAL_MAKE_QVA(IOD_DIAG0_CSRS_PHYSICAL)
+
+#define IOD_ERROR0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x800)
+#define IOD_ERROR0_CSRS_QVA HAL_MAKE_QVA(IOD_ERROR0_CSRS_PHYSICAL)
+
+#define IOD_SCATTER_GATHER0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x1300)
+#define IOD_SG0_CSRS_QVA (HAL_MAKE_QVA(IOD_SCATTER_GATHER0_CSRS_PHYSICAL))
+
+//
+// PCI Bus 1
+//
+
+#define IOD_PCI1_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0xfa00000000)
+#define IOD_PCI1_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0xfb00000000)
+#define IOD_PCI1_SPARSE_IO_PHYSICAL ((ULONGLONG)0xfb80000000)
+#define IOD_PCI1_CONFIGURATION_PHYSICAL ((ULONGLONG)0xfbC0000000)
+#define IOD_MAIN1_CSRS_PHYSICAL ((ULONGLONG)0xfbE0000000)
+
+#define IOD_PCI1_CONFIG_BASE_QVA (HAL_MAKE_QVA(IOD_PCI1_CONFIGURATION_PHYSICAL))
+#define IOD_PCI1_SPARSE_IO_QVA (HAL_MAKE_QVA(IOD_PCI1_SPARSE_IO_PHYSICAL))
+#define IOD_PCI1_SPARSE_MEMORY_QVA (HAL_MAKE_QVA(IOD_PCI1_SPARSE_MEMORY_PHYSICAL))
+
+#define IOD_GENERAL1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL)
+#define IOD_GENERAL1_CSRS_QVA HAL_MAKE_QVA(IOD_GENERAL1_CSRS_PHYSICAL)
+
+#define IOD_INT1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x500)
+#define IOD_INT1_CSRS_QVA HAL_MAKE_QVA(IOD_INT1_CSRS_PHYSICAL)
+
+#define IOD_DIAG1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x700)
+#define IOD_DIAG1_CSRS_QVA HAL_MAKE_QVA(IOD_DIAG1_CSRS_PHYSICAL)
+
+#define IOD_ERROR1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x800)
+#define IOD_ERROR1_CSRS_QVA HAL_MAKE_QVA(IOD_ERROR1_CSRS_PHYSICAL)
+
+#define IOD_SCATTER_GATHER1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x1300)
+#define IOD_SG_CSRS1_QVA (HAL_MAKE_QVA(IOD_SCATTER_GATHER1_CSRS_PHYSICAL))
+
+//
+// Define the classes of IOD registers.
+//
+
+typedef enum _IOD_REGISTER_CLASS{
+ IodGeneralRegisters = 0x1,
+ IodInterruptRegisters = 0x2,
+ IodDiagnosticRegisters = 0x3,
+ IodErrorRegisters = 0x4,
+ IodScatterGatherRegisters = 0x5,
+ IodFlashRomRegisters = 0x6,
+ IodResetRegister = 0x7,
+ AllRegisters = 0xffffffff
+} IOD_REGISTER_CLASS, *PIOD_REGISTER_CLASS;
+
+//
+// Define the MC bus global id's
+//
+
+typedef enum _MC_GLOBAL_ID{
+ GidPrimary = 0x7
+} MC_GLOBAL_ID, *PMC_GLOBAL_ID;
+
+//
+// Define the MC bus module id's
+//
+
+typedef enum _MC_MODULE_ID{
+ MidGcd = 0x0,
+ MidMem = 0x1,
+ MidCpu0 = 0x2,
+ MidCpu1 = 0x3,
+ MidPci0 = 0x4,
+ MidPci1 = 0x5,
+ MidCpu2 = 0x6, // Dodge, IIP Motherboard
+ MidCpu3 = 0x7, // Dodge, IIP Motherboard
+ MidPci2 = 0x6, // Durango, PIO Motherboard
+ MidPci3 = 0x7 // Durango, PIO Motherboard
+} MC_MODULE_ID, *PMC_MODULE_ID;
+
+//
+// Define the MC device id type
+//
+
+typedef union _MC_DEVICE_ID{
+ struct{
+ ULONG Mid: 3; // <2:0> Module Id
+ ULONG Gid: 3; // <5:3> Global Id
+ ULONG Reserved0: 26; //
+ };
+ ULONG all; // <5:0> MC Bus Device Id
+} MC_DEVICE_ID, *PMC_DEVICE_ID;
+
+extern MC_DEVICE_ID HalpIodLogicalToPhysical[];
+
+//
+// Define the MC bus enumeration types
+//
+
+typedef ULONGLONG MC_DEVICE_MASK;
+
+extern MC_DEVICE_MASK HalpIodMask;
+extern MC_DEVICE_MASK HalpCpuMask;
+extern MC_DEVICE_MASK HalpGcdMask;
+
+//
+// Define the number of IOD's and CPU's in the system
+//
+
+extern ULONG HalpNumberOfIods;
+extern ULONG HalpNumberOfCpus;
+
+typedef struct _MC_ENUM_CONTEXT {
+ RTL_BITMAP McDeviceBitmap; // Device mask being enumerated
+ MC_DEVICE_MASK tempMask; // Bitmap storage
+ ULONG nextBit; // Hint to speed up enumeration
+ // N.B. this is the only public member of this structure:
+ MC_DEVICE_ID McDeviceId; // Currently enumerated McDeviceID
+} MC_ENUM_CONTEXT, *PMC_ENUM_CONTEXT;
+
+//
+// The Bus enumeration routine is called from HalpMcBusEnumAndCall()
+// to perform operations on an enumerated device mask.
+//
+
+typedef
+VOID (*PMC_ENUM_ROUTINE) (
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list McEnumBusArgs
+ );
+
+//
+// Define expected machine check data type
+//
+
+typedef struct _IOD_EXPECTED_ERROR {
+ ULONG Number; // Processor Number
+ ULONGLONG Addr; // SuperPage mode address causing Fill_Error
+} IOD_EXPECTED_ERROR, *PIOD_EXPECTED_ERROR;
+
+#define MASTER_ABORT_NOT_EXPECTED 0xffffffff
+
+//
+// Define the format of the posted interrupt written that the
+// bridge writes to system memory.
+//
+
+typedef union _IOD_POSTED_INTERRUPT {
+
+ struct{
+ ULONG Pci: 16; // <15:0> PCI interrupt State
+ ULONG Eisa: 1; // <17> Eisa/NCR810 interrupt state
+ ULONG I2cCtrl: 1; // <17> 8254 I2C Controller (PCI 0 Only)
+ ULONG I2cBus: 1; // <18> 8254 I2C Bus: (PCI 0 Only)
+ ULONG Reserved0: 2; // <20:19>
+ ULONG Nmi: 1; // <21> 8259 Eisa NMI
+ ULONG SoftErr: 1; // <22> Soft (correctable) error interrupt
+ ULONG HardErr: 1; // <23> Hard error interrupt
+ ULONG Target: 1; // <24> Target device number (0,1)
+ ULONG McDevId: 6; // PCI source of interrupt
+ ULONG Valid: 1; // Device interrupt pending/serviced
+ } ;
+ struct{
+ ULONG IntReq: 24; // <23:0> InterruptState
+ } ;
+ ULONG all;
+
+} IOD_POSTED_INTERRUPT, *PIOD_POSTED_INTERRUPT;
+
+extern PIOD_POSTED_INTERRUPT HalpIodPostedInterrupts;
+
+//
+// Address of vector table in memory
+//
+
+typedef union _IOD_POSTED_INTERRUPT_ADDR {
+ struct{
+ ULONG BusVectorOffset: 2; // QuadWord per vector entry
+ ULONG PciBusOffset: 4; // PCI bus offset into CPU area
+ ULONG CpuOffset: 6; // 64K area per CPU
+ ULONG Base4KPage: 20; // 4K page address of table
+ };
+ ULONG all;
+
+} IOD_POSTED_INTERRUPT_ADDR, PIOD_POSTED_INTERRUPT_ADDR;
+
+
+#define Ncr810 Eisa
+
+//
+// Define the structures to access the IOD general CSRs.
+//
+
+typedef struct _IOD_GENERAL_CSRS{
+ UCHAR PciRevision; // (000) PCI Revision
+ UCHAR Filler1; // (020)
+ UCHAR WhoAmI; // (040) WhoAmI
+ UCHAR Filler2; // (060)
+ UCHAR PciLat; // (080) PCI Latency
+ UCHAR Filler3[3]; // (0a0 - 0e0)
+ UCHAR CapCtrl; // (100) CAP control (MC-PCI Bridge Command)
+ UCHAR Filler4[15]; // (120 - 2e0)
+ UCHAR PerfMon; // (300) Performance Monitor Counter
+ UCHAR Filler5; // (320)
+ UCHAR PerfCon; // (340) Peformance Monitor Ctrl Register
+ UCHAR Filler6[5]; // (360 - 3e0)
+ UCHAR HaeMem; // (400) Host address extension, sparse memory
+ UCHAR Filler7; // (420)
+ UCHAR HaeIo; // (440) Host address extension, space i/o
+ UCHAR Filler8; // (460)
+ UCHAR IackSc; // (480) Interrup Acknowledge / Special Cycle
+ UCHAR Filler9; // (4A0)
+ UCHAR HaeDense; // (4C0) Host address extension, dense memory
+} IOD_GENERAL_CSRS, *PIOD_GENERAL_CSRS;
+
+typedef union _IOD_PCI_REVISION{
+ struct{
+ ULONG CapRev: 4; // <3:0> CAP Revision Id
+ ULONG HorseRev: 4; // <7:4> Horse Revision Id
+ ULONG SaddleRev: 4; // <11:8> Saddle Revision Id
+ ULONG SaddleType: 3; // <14:12> Type Id
+ ULONG EisaPresent: 1; // <15> Set if EISA bus present
+ ULONG SubClass: 8; // <23:16> PCI Host bus bridge sub class
+ ULONG BaseClass: 8; // <3:124> PCI Host bus bridge base class
+ };
+ ULONG all;
+} IOD_PCI_REVISION, *PIOD_PCI_REVISION;
+
+extern ULONG HalpIodPciRevision; // global containing IOD PCI revision id
+
+typedef union _IOD_WHOAMI{
+ struct{
+ ULONG Devid: 6; // <5:0> MC Bus Device Id
+ ULONG CpuInfo: 8; // <13:6> Data Bits
+ ULONG Reserved0: 18; // <31:14> MBZ
+ };
+ MC_DEVICE_ID McDevId; // <5:0> MC Bus Device Id
+ ULONG all;
+} IOD_WHOAMI, *PIOD_WHOAMI;
+
+#define CACHED_CPU_FILL_ERROR 0x80 // CpuInfo Data Bits
+#define CACHED_CPU_DTAG_PARITY_ERROR 0x40 // CpuInfo Data Bits
+
+typedef union _IOD_PCI_LAT{
+ struct{
+ ULONG Reserved0: 8; // <7:0>
+ ULONG Latency: 8; // <15:8> PCI Master Latency timer (in PCI clocks)
+ ULONG Reserved1: 16; // <31:16>
+ };
+ ULONG all;
+} IOD_PCI_LAT, *PIOD_PCI_LAT;
+
+typedef union _IOD_CAP_CONTROL{
+ struct{
+ ULONG Led: 1; // <0> Selftest passed LED
+ ULONG Reserved0: 3; // <3:1>
+ ULONG DlyRdEn: 1; // <4> Enables PCI delayed read protocol ( > 16 clks)
+ ULONG PciMemEn: 1; // <5> Enables Bridge response to PCI transactions
+ ULONG PciReq64: 1; // <6> Enables request for 64-bit PCI transactions
+ ULONG PciAck64: 1; // <7> Enables accepting 64-bit PCI transactions
+ ULONG PciAddrPe: 1; // <8> Enables PCI address parity checking & SERR#
+ ULONG McCmdAddrPe: 1; // <9> Enables Check MC bus CMD / Address Parity
+ ULONG McNxmEn: 1; // <10> Enables Check MC bus NXM on IO space reads
+ ULONG McBusMonEn: 1; // <11> Enables Check MC bus errors when a bystander
+ ULONG Reserved1: 4; // <15:12>
+ ULONG PendNum: 4; // <19:16> Write Pend Number Threshold
+ ULONG RdType: 2; // <21:20> Memory Read Prefetch Type
+ ULONG RlType: 2; // <23:22> Memory Read Line Prefetch Type
+ ULONG RmType: 2; // <25:24> Memory Read Multiple Prefetch Type
+ ULONG PartialWrEn: 1; // <26> Partial Write Enable
+ ULONG Reserved3: 3; // <29:27>
+ ULONG ArbMode: 2; // <31:30> PCI Arbitration Mode
+ };
+ ULONG all;
+} IOD_CAP_CONTROL, *PIOD_CAP_CONTROL;
+
+typedef enum _IOD_READ_PREFETCH_TYPE{
+ IodPrefetchShort = 0x00,
+ IodPrefetchMedium = 0x01,
+ IodPrefetchLong = 0x02,
+ IodPrefetchReserved = 0x03
+} IOD_READ_PREFETCH_TYPE, *PIOD_READ_PREFETCH_TYPE;
+
+typedef enum _IOD_PCI_ARB_MODE{
+ IodArbBridgePriority = 0x00,
+ IodArbRoundRobin = 0x01,
+ IodArbModRoundRobin = 0x02,
+ IodArbReserved = 0x03
+} IOD_PCI_ARB_MODE, *PIOD_PCI_ARB_MODE;
+
+typedef union _IOD_PERF_MON{
+ struct{
+ ULONG Counter: 24; // <23:0>
+ ULONG Reserved0: 8; // <31:24> sets HAE for sparse memory space
+ };
+ ULONG all;
+} IOD_PERF_MON, *PIOD_PERF_MON;
+
+typedef union _IOD_PERF_CON{
+ struct{
+ ULONG CntFrame: 1; // <0> 0 = count PCI Frame#, 1 = cnt TLB miss
+ ULONG Reserved0: 31; // <31:1>
+ };
+ ULONG all;
+} IOD_PERF_CON, *PIOD_PERF_CON;
+
+typedef enum _IOD_PERF_COUNTER_MODE{
+ IodPerfMonPciFrame = 0x0,
+ IodPerfMonTlbMiss = 0x1
+} IOD_PERF_COUNTER_MODE, *PIOD_PERF_COUNTER_MODE;
+
+typedef union _IOD_HAE_MEM{
+ struct{
+ ULONG Reserved0: 26; // <25:0>
+ ULONG HaeMem: 6; // <31:26> sets HAE for sparse memory space
+ };
+ ULONG all;
+} IOD_HAE_MEM, *PIOD_HAE_MEM;
+
+typedef union _IOD_HAE_IO{
+ struct{
+ ULONG Reserved0: 25; // <24:0>
+ ULONG HaeIo: 7; // <31:25> sets HAE for sparse i/o space
+ };
+ ULONG all;
+} IOD_HAE_IO, *PIOD_HAE_IO;
+
+typedef union _IOD_IACK_SC{
+ struct{
+ ULONG Message: 16; // <15:0> Encoded Message
+ ULONG MessageEx: 16; // <31:16> Message Dependent
+ };
+ ULONG all;
+} IOD_IACK_SC, *PIOD_IACK_SC;
+
+//
+// Define the structures and definitions for the IOD interrupt registers.
+//
+
+typedef struct _IOD_INT_CSRS{
+ UCHAR IntCtrl; // (500) Interrupt Control
+ UCHAR Filler1; // (520)
+ UCHAR IntReq; // (540) Interrupt Request
+ UCHAR Filler2; // (560)
+ UCHAR IntTarg; // (580) Interrupt Target Devices
+ UCHAR Filler3; // (5a0)
+ UCHAR IntAddr; // (5c0) Interrupt Target Address
+ UCHAR Filler4; // (5e0)
+ UCHAR IntAddrExt; // (600) Interrupt Target Address Extension
+ UCHAR Filler5; // (620)
+ UCHAR IntMask0; // (640) Interrupt Mask 0
+ UCHAR Filler6; // (660)
+ UCHAR IntMask1; // (680) Interrupt Mask 1
+ UCHAR Filler7[0x8001c3]; // (6a0 - 10003ea0)
+ UCHAR IntAck0; // (10003f00) Interrupt Target 0 Acknowledge
+ UCHAR Filler8; // (10003f20)
+ UCHAR IntAck1; // (10003f40) Interrupt Target 1 Acknowledge
+} IOD_INT_CSRS, *PIOD_INT_CSRS;
+
+//
+// 16 PCI vectors per IOD
+//
+
+#define IOD_PCI_VECTORS 0x10
+
+typedef union _IOD_INT_CONTROL{
+ struct{
+ ULONG EnInt: 1; // <0> Enable MC Bus IO interrupt transactions
+ ULONG EnIntNum: 1; // <1> Enable MC Bus interrupt number write
+ ULONG Reserved: 4; // <31:2>
+ };
+ ULONG all;
+} IOD_INT_CONTROL, *PIOD_INT_CONTROL;
+
+#define IOD_INT_CTL_ENABLE_IO_INT 0x1
+#define IOD_INT_CTL_DISABLE_IO_INT 0x0
+#define IOD_INT_CTL_ENABLE_VECT_WRITE 0x2
+#define IOD_INT_CTL_DISABLE_VECT_WRITE 0x0
+
+
+typedef union _IOD_INT_REQUEST{
+ struct{
+ ULONG IntReq: 22; // <21:0> Interrupt State
+ ULONG SoftErr: 1; // <22> Soft (correctable) error interrupt
+ ULONG HardErr: 1; // <23> Hard error interrupt
+ ULONG Reserved: 8; // <31:24>
+ };
+ ULONG all;
+} IOD_INT_REQUEST, *PIOD_INT_REQUEST;
+
+typedef union _IOD_INT_TARGET_DEVICE{
+ struct{
+ ULONG Int0TargDevId: 6; // <5:0> Interrupt Target 0 McDevid
+ ULONG Int1TargDevId: 6; // <11:6> Interrupt Target 1 McDevid
+ ULONG Reserved: 20; // <31:12> MBZ
+ };
+ ULONG all;
+} IOD_INT_TARGET_DEVICE, *PIOD_INT_TARGET_DEVICE;
+
+#define IOD_MAX_INT_TARG 2
+
+typedef union _IOD_INT_ADDR{
+ struct{
+ ULONG Reserved1: 2; // <1:0> MBZ
+ ULONG PciOffset: 4; // <5:2> PCI Offset
+ ULONG Reserved2: 6; // <11:6> MBZ
+ ULONG IntAddrLo: 20; // <31:12> Page address of interrupt target
+ };
+ ULONG all;
+} IOD_INT_ADDR, *PIOD_INT_ADDR;
+
+typedef union _IOD_INT_ADDR_EXT{
+ struct{
+ ULONG IntAddrExt: 7; // <6:0> Upper bits of interrupt target address
+ ULONG Reserved: 25; // <31:7> MBZ
+ };
+ ULONG all;
+} IOD_INT_ADDR_EXT, *PIOD_INT_ADDR_EXT;
+
+
+//
+// IOD_INT_MASK applies to IntMask0 and IntMask1
+//
+
+typedef union _IOD_INT_MASK{
+ struct{
+ ULONG IntMask: 24; // <23:0> Interrupt Mask
+ ULONG Reserved: 8; // <31:24>
+ };
+ struct{
+ ULONG IntA0: 1; // <0> PCI Slot 0
+ ULONG IntB0: 1;
+ ULONG IntC0: 1;
+ ULONG IntD0: 1;
+ ULONG IntA1: 1; // <4> PCI Slot 1
+ ULONG IntB1: 1;
+ ULONG IntC1: 1;
+ ULONG IntD1: 1;
+ ULONG IntA2: 1; // <8> PCI Slot 2
+ ULONG IntB2: 1;
+ ULONG IntC2: 1;
+ ULONG IntD2: 1;
+ ULONG IntA3: 1; // <12> PCI Slot 3
+ ULONG IntB3: 1;
+ ULONG IntC3: 1;
+ ULONG IntD3: 1;
+ ULONG EisaInt: 1; // <16> 8259 Eisa IRQ's (PCI 0), NCR810 SCSI (PCI 1)
+ ULONG I2cCtrl: 1; // <17> 8254 I2C Controller (PCI 0 Only)
+ ULONG I2cBus: 1; // <18> 8254 I2C Bus: Pwr, Fan, etc. (PCI 0 Only)
+ ULONG Reserved0: 2; // <20:19>
+ ULONG Nmi: 1; // <21> 8259 Eisa NMI
+ ULONG SoftErr: 1; // <22> Soft Error from CAP Chip
+ ULONG HardErr: 1; // <23> Hard Error from CAP Chip
+ ULONG Reserved1 :8; // <31:24>
+ };
+ ULONG all;
+} IOD_INT_MASK, *PIOD_INT_MASK;
+
+typedef enum _IOD_MASK_DEFS{
+ IodPci0IntMask = (1 << 0),
+ IodPci1IntMask = (1 << 1),
+ IodPci2IntMask = (1 << 2),
+ IodPci3IntMask = (1 << 3),
+ IodPci4IntMask = (1 << 4),
+ IodPci5IntMask = (1 << 5),
+ IodPci6IntMask = (1 << 6),
+ IodPci7IntMask = (1 << 7),
+ IodPci8IntMask = (1 << 8),
+ IodPci9IntMask = (1 << 9),
+ IodPci10IntMask = (1 << 10),
+ IodPci11IntMask = (1 << 11),
+ IodPci12IntMask = (1 << 12),
+ IodPci13IntMask = (1 << 13),
+ IodPci14IntMask = (1 << 14),
+ IodPci15IntMask = (1 << 15),
+ IodEisaIntMask = (1 << 16),
+ IodScsiIntMask = (1 << 16),
+ IodI2cCtrlIntMask = (1 << 17),
+ IodI2cBusIntMask = (1 << 18),
+ IodEisaNmiIntMask = (1 << 21),
+ IodSoftErrIntMask = (1 << 22),
+ IodHardErrIntMask = (1 << 23),
+
+ IodIntMask = 0x03ffffff,
+ IodPciIntMask = 0x0000ffff,
+ IodIntDisableMask = 0x00000000,
+
+} IOD_MASK_DEFS, *PIOD_MASK_DEFS;
+
+
+//
+// IOD_INT_ACK applies to IntAck0 and IntAck1
+//
+
+typedef union _IOD_INT_ACK{
+ struct{
+ ULONG Reserved: 32; // <31:0> Reserved
+ };
+ ULONG all;
+} IOD_INT_ACK, *PIOD_INT_ACK;
+
+
+
+//
+// Define the structures and definitions for the IOD diagnostic registers.
+//
+
+typedef struct _IOD_DIAG_CSRS{
+ UCHAR CapDiag; // (700) CAP Diagnostic Control register
+ UCHAR Filler1; // (720)
+ UCHAR Scratch; // (740) General Purpose Scratch register
+ UCHAR Filler2; // (760)
+ UCHAR ScratchAlias; // (780) General Purpose Scratch register alias
+ UCHAR Filler3; // (7a0)
+ UCHAR TopOfMem; // (7c0) Top of Memory
+} IOD_DIAG_CSRS, *PIOD_DIAG_CSRS;
+
+typedef union _IOD_CAP_DIAG {
+ struct{
+ ULONG PciReset: 1; // <0> Reset PCI (must be cleared with 100 us)
+ ULONG Reserved0: 30; // <29:1>
+ ULONG ForceMcAddrPe: 1; // <30> Force bad parity to MC bus (one-shot)
+ ULONG ForcePciAddrPe: 1;// <31> Force bad parity to PCI bus (one-shot)
+ };
+ ULONG all;
+} IOD_CAP_DIAG, *PIOD_CAP_DIAG;
+
+
+//
+// Define the structures and definitions for the IOD error symptom registers.
+//
+
+typedef struct _IOD_ERROR_CSRS{
+ UCHAR McErr0; // (800) MC Error Information Register 0
+ UCHAR Filler0; // (820)
+ UCHAR McErr1; // (840) MC Error Information Register 1
+ UCHAR Filler1; // (860)
+ UCHAR CapErr; // (880) CAP Error Register
+ UCHAR Filler2[61]; // (8a0-1020)
+ UCHAR PciErr1; // (1040) PCI error - failing address
+ UCHAR Filler3[381]; // (1060-3fe0)
+ UCHAR MdpaStat; // (4000) MDPA Status Register
+ UCHAR Filler4; // (4020)
+ UCHAR MdpaSyn; // (4040) MDPA Error Syndrome register
+ UCHAR Filler5; // (4060)
+ UCHAR MdpaDiag; // (4080) MDPA Diagnostic Check Register
+ UCHAR Filler6[507]; // (40a0-7fe0)
+ UCHAR MdpbStat; // (8000) MDPB Status Register
+ UCHAR Filler7; // (8020)
+ UCHAR MdpbSyn; // (8040) MDPB Error Syndrome register
+ UCHAR Filler8; // (8060)
+ UCHAR MdpbDiag; // (8080) MDPB Diagnostic Check Register
+} IOD_ERROR_CSRS, *PIOD_ERROR_CSRS;
+
+typedef union _IOD_MC_ERR0{
+ struct{
+ ULONG Addr: 32; // <31:0> address bits 31-4 of current MC bus error
+ };
+ ULONG all;
+} IOD_MC_ERR0, *PIOD_MC_ERR0;
+
+typedef union _IOD_MC_ERR1{
+ struct{
+ ULONG Addr39_32: 8; // <7:0> address bits 39-32 of current MC bus error
+ ULONG McCmd: 6; // <13:8> MC Bus command active at time of error
+ ULONG DevId: 6; // <19:14> Gid,Mid of bus master at time of error
+ ULONG Dirty: 1; // <20> Set if MC Bus Read/Dirty transaction
+ ULONG Reserved0: 10; // <30:21>
+ ULONG Valid: 1; // <31> OR of CAP_ERR<30:23), McErr0 and McErr1 valid
+ };
+ ULONG all;
+} IOD_MC_ERR1, *PIOD_MC_ERR1;
+
+typedef union _IOD_CAP_ERR{
+ struct{
+ ULONG Perr: 1; // <0> PCI bus PERR# observed by bridge
+ ULONG Serr: 1; // <1> PCI bus SERR# observed by bridge
+ ULONG Mab: 1; // <2> PCI target abort observed by bridge
+ ULONG PteInv: 1; // <3> Invalid Pte
+
+ ULONG PciErrValid: 1; // <4> (RO) PCI Error Valid - Logical OR of <3:0>
+ ULONG Reserved0: 18; // <22:5>
+ ULONG PioOvfl: 1; // <23> CAP buffer full, transaction lost
+
+ ULONG LostMcErr: 1; // <24> Lost uncorrectable MC error
+ ULONG McAddrPerr: 1; // <25> MC Bus command/address parity error
+ ULONG Nxm: 1; // <26> Nonexistent MC Bus address error
+ ULONG CrdA: 1; // <27> Correctable ECC error detected by MDPA
+
+ ULONG CrdB: 1; // <28> Correctable ECC error detected by MDPB
+ ULONG RdsA: 1; // <29> Uncorrectable ECC error detected by MDPA
+ ULONG RdsB: 1; // <30> Uncorrectable ECC error detected by MDPB
+ ULONG McErrValid: 1; // <31> (RO) MC Error Valid - Logical OR of <30:23>
+ };
+ ULONG all;
+} IOD_CAP_ERR, *PIOD_CAP_ERR;
+
+typedef struct _IOD_PCI_ERR1{
+ ULONG PciAddress; // (RO) <31:0> PCI Address
+} IOD_PCI_ERR1, *PIOD_PCI_ERR1;
+
+typedef union _IOD_MDPA_STAT{
+ struct{
+ ULONG MdpaRev: 4; // <3:0> MDP chip revision level
+ ULONG Reserved: 26; // <29:4>
+ ULONG Crd: 1; // <30> MdpaSyn contains correctable error syndrome
+ ULONG Rds: 1; // <31> MdpaSyn contains uncorrectable error syndrome
+ };
+ ULONG all;
+} IOD_MDPA_STAT, *PIOD_MDPA_STAT;
+
+typedef union _IOD_MDPB_STAT{
+ struct{
+ ULONG MdpbRev: 4; // <3:0> MDP chip revision level
+ ULONG Reserved: 26; // <29:4>
+ ULONG Crd: 1; // <30> MdpaSyn contains correctable error syndrome
+ ULONG Rds: 1; // <31> MdpaSyn contains uncorrectable error syndrome
+ };
+ ULONG all;
+} IOD_MDPB_STAT, *PIOD_MDPB_STAT;
+
+typedef union _IOD_MDPA_SYN{
+ struct{
+ ULONG EccSyndrome0: 8; // <8:0> Cycle 0 ECC Syndrome
+ ULONG EccSyndrome1: 8; // <15:9> Cycle 1 ECC Syndrome
+ ULONG EccSyndrome2: 8; // <23:16> Cycle 2 ECC Syndrome
+ ULONG EccSyndrome3: 8; // <31:24> Cycle 3 ECC Syndrome
+ };
+ ULONG all;
+} IOD_MDPA_SYN, *PIOD_MDPA_SYN;
+
+typedef union _IOD_MDPB_SYN{
+ struct{
+ ULONG EccSyndrome0: 8; // <8:0> Cycle 0 ECC Syndrome
+ ULONG EccSyndrome1: 8; // <15:9> Cycle 1 ECC Syndrome
+ ULONG EccSyndrome2: 8; // <23:16> Cycle 2 ECC Syndrome
+ ULONG EccSyndrome3: 8; // <31:24> Cycle 3 ECC Syndrome
+ };
+ ULONG all;
+} IOD_MDPB_SYN, *PIOD_MDPB_SYN;
+
+typedef union _IOD_MDPA_DIAG{
+ struct{
+ ULONG DiagCheck: 8; // <7:0> Data for ECC in diag DMA writes
+ ULONG Reserved: 20; // <27:8>
+ ULONG EccCkEn: 1; // <28> Enable ECC check
+ ULONG ParCkEn: 1; // <29> Enable PCI data parity check
+ ULONG FpePciLo: 1; // <30> Force bad PCI parity on low 32 bits of data
+ ULONG UseDiagCheck: 1; // <31> DMA write cycles to mem use DiagCheck as ECC
+ };
+ ULONG all;
+} IOD_MDPA_DIAG, *PIOD_MDPA_DIAG;
+
+typedef union _IOD_MDPB_DIAG{
+ struct{
+ ULONG DiagCheck: 8; // <7:0> Data for ECC in diag DMA writes
+ ULONG Reserved: 20; // <27:8>
+ ULONG EccCkEn: 1; // <28> Enable ECC check
+ ULONG ParCkEn: 1; // <29> Enable PCI data parity check
+ ULONG FpePciHi: 1; // <30> Force bad PCI parity on high 32 bits of data
+ ULONG UseDiagCheck: 1; // <31> DMA write cycles to mem use DiagCheck as ECC
+ };
+ ULONG all;
+} IOD_MDPB_DIAG, *PIOD_MDPB_DIAG;
+
+//
+// Define I/O CSRs specific to the Rawhide IOD
+//
+
+#if 0
+typedef union _IOD_ELCR1{
+ struct{
+ ULONG From0Rdy: 1; // <0> (RO) Primary flash ROM ready to accept cmds
+ ULONG From1Rdy: 1; // <1> (RO) Secondary flash ROM ready to accept cmds
+ ULONG FsafeWrProt: 1; // <2> (RO) Fail Safe Write Protect (if set)
+ ULONG AvpPresent: 1; // <3> (RO) Programming jumper inserted (if set)
+ ULONG From1Sel: 1; // <4> Selects secondary flash ROM
+ ULONG FromAddr: 3; // <7:5> Selects 64Kb flash ROM range
+ };
+ ULONG all;
+} IOD_ELCR1, *PIOD_ELCR1;
+#else
+typedef union _IOD_ELCR1{
+ struct{
+ ULONG From0Rdy: 1; // <0> (RO) Primary flash ROM ready to accept cmds
+ ULONG From1Rdy: 1; // <1> (RO) Secondary flash ROM ready to accept cmds
+ ULONG AvpPresent: 1; // <2> (RO) Programming jumper inserted (if set)
+ ULONG FromSel: 1; // <3> (RW) Selects secondary flash ROM
+ ULONG FromAddr: 4; // <7:4> (RW) Selects 64Kb flash ROM range
+ };
+ ULONG all;
+} IOD_ELCR1, *PIOD_ELCR1;
+#endif
+
+typedef union _IOD_ELCR2{
+ struct{
+ ULONG SfwResetReq: 1; // <0> (WO) System-wide reset to Power Control Module
+ ULONG SfwReset: 1; // <1> (RO) Most recent reset was via SfwResetReq
+ ULONG CapReset: 1; // <2> (RO) Most recent reset was from CAP chip
+ ULONG OcpReset: 1; // <3> (RO) Most recent reset was via OCP reset swtch
+ ULONG RsmReset: 1; // <4> (RO) Most recent reset was via RSM module
+ ULONG Reserved0: 3; // <7:5>
+ };
+ ULONG all;
+} IOD_ELCR2, *PIOD_ELCR2;
+
+
+//
+// Define structures and definitions for Scatter/Gather control registers:
+//
+
+typedef struct _IOD_SG_CSRS{
+ UCHAR Tbia; // (1300) Translation buffer invalidate all
+ UCHAR Filler; // (1320)
+ UCHAR Hbase; // (1340) PC Hole Compatibility Register
+ UCHAR Filler0[5]; // (1360-13e0)
+ UCHAR W0base; // (1400) Base address, DMA window 0
+ UCHAR Filler1; // (1420)
+ UCHAR W0mask; // (1440) Mask Register, DMA window 0
+ UCHAR Filler2; // (1460)
+ UCHAR T0base; // (1480) Translation Base, DMA window 0
+ UCHAR Filler3[3]; // (14a0 - 14e0)
+ UCHAR W1base; // (1500) Base address, DMA window 1
+ UCHAR Filler4; // (1520)
+ UCHAR W1mask; // (1540) Mask Register, DMA window 1
+ UCHAR Filler5; // (1560)
+ UCHAR T1base; // (1580) Translation Base, DMA window 1
+ UCHAR Filler6[3]; // (15a0 - 15e0)
+ UCHAR W2base; // (1600) Base address, DMA window 2
+ UCHAR Filler7; // (1620)
+ UCHAR W2mask; // (1640) Mask Register, DMA window 2
+ UCHAR Filler8; // (1660)
+ UCHAR T2base; // (1680) Translation Base, DMA window 2
+ UCHAR Filler9[3]; // (16a0 - 16e0)
+ UCHAR W3base; // (1700) Base address, DMA window 3
+ UCHAR Filler10; // (1720)
+ UCHAR W3mask; // (1740) Mask Register, DMA window 3
+ UCHAR Filler11; // (1760)
+ UCHAR T3base; // (1780) Translation Base, DMA window 3
+ UCHAR Filler12; // (17a0)
+ UCHAR Wdac; // (17c0) Window DAC Base
+ UCHAR Filler13; // (17e0)
+ UCHAR TbTag0; // (1800) Translation Buffer Tag 0
+ UCHAR Filler14; // (1820)
+ UCHAR TbTag1; // (1840) Translation Buffer Tag 1
+ UCHAR Filler15; // (1860)
+ UCHAR TbTag2; // (1880) Translation Buffer Tag 2
+ UCHAR Filler16; // (18a0)
+ UCHAR TbTag3; // (18c0) Translation Buffer Tag 3
+ UCHAR Filler17; // (18e0)
+ UCHAR TbTag4; // (1900) Translation Buffer Tag 4
+ UCHAR Filler18; // (1920)
+ UCHAR TbTag5; // (1940) Translation Buffer Tag 5
+ UCHAR Filler19; // (1960)
+ UCHAR TbTag6; // (1980) Translation Buffer Tag 6
+ UCHAR Filler20; // (19a0)
+ UCHAR TbTag7; // (19c0) Translation Buffer Tag 7
+ UCHAR Filler21; // (19e0)
+ UCHAR Tb0Page0; // (2000) Translation Buffer 0 Page 0
+ UCHAR Filler22; // (2020)
+ UCHAR Tb0Page1; // (2040) Translation Buffer 0 Page 1
+ UCHAR Filler23; // (2060)
+ UCHAR Tb0Page2; // (2080) Translation Buffer 0 Page 2
+ UCHAR Filler24; // (20a0)
+ UCHAR Tb0Page3; // (20c0) Translation Buffer 0 Page 3
+ UCHAR Filler25; // (20e0)
+ UCHAR Tb1Page0; // (2100) Translation Buffer 1 Page 0
+ UCHAR Filler26; // (2120)
+ UCHAR Tb1Page1; // (2140) Translation Buffer 1 Page 1
+ UCHAR Filler27; // (2160)
+ UCHAR Tb1Page2; // (2180) Translation Buffer 1 Page 2
+ UCHAR Filler28; // (21a0)
+ UCHAR Tb1Page3; // (21c0) Translation Buffer 1 Page 3
+ UCHAR Filler29; // (21e0)
+ UCHAR Tb2Page0; // (2200) Translation Buffer 2 Page 0
+ UCHAR Filler30; // (2220)
+ UCHAR Tb2Page1; // (2240) Translation Buffer 2 Page 1
+ UCHAR Filler31; // (2260)
+ UCHAR Tb2Page2; // (2280) Translation Buffer 2 Page 2
+ UCHAR Filler32; // (22a0)
+ UCHAR Tb2Page3; // (22c0) Translation Buffer 2 Page 3
+ UCHAR Filler33; // (22e0)
+ UCHAR Tb3Page0; // (2300) Translation Buffer 3 Page 0
+ UCHAR Filler34; // (2320)
+ UCHAR Tb3Page1; // (2340) Translation Buffer 3 Page 1
+ UCHAR Filler35; // (2360)
+ UCHAR Tb3Page2; // (2380) Translation Buffer 3 Page 2
+ UCHAR Filler36; // (23a0)
+ UCHAR Tb3Page3; // (23c0) Translation Buffer 3 Page 3
+ UCHAR Filler37; // (23e0)
+ UCHAR Tb4Page0; // (2400) Translation Buffer 4 Page 0
+ UCHAR Filler38; // (2420)
+ UCHAR Tb4Page1; // (2440) Translation Buffer 4 Page 1
+ UCHAR Filler39; // (2460)
+ UCHAR Tb4Page2; // (2480) Translation Buffer 4 Page 2
+ UCHAR Filler40; // (24a0)
+ UCHAR Tb4Page3; // (24c0) Translation Buffer 4 Page 3
+ UCHAR Filler41; // (24e0)
+ UCHAR Tb5Page0; // (2500) Translation Buffer 5 Page 0
+ UCHAR Filler42; // (2520)
+ UCHAR Tb5Page1; // (2540) Translation Buffer 5 Page 1
+ UCHAR Filler43; // (2560)
+ UCHAR Tb5Page2; // (2580) Translation Buffer 5 Page 2
+ UCHAR Filler44; // (25a0)
+ UCHAR Tb5Page3; // (25c0) Translation Buffer 5 Page 3
+ UCHAR Filler45; // (25e0)
+ UCHAR Tb6Page0; // (2600) Translation Buffer 6 Page 0
+ UCHAR Filler46; // (2620)
+ UCHAR Tb6Page1; // (2640) Translation Buffer 6 Page 1
+ UCHAR Filler47; // (2660)
+ UCHAR Tb6Page2; // (2680) Translation Buffer 6 Page 2
+ UCHAR Filler48; // (26a0)
+ UCHAR Tb6Page3; // (26c0) Translation Buffer 6 Page 3
+ UCHAR Filler49; // (26e0)
+ UCHAR Tb7Page0; // (2700) Translation Buffer 7 Page 0
+ UCHAR Filler50; // (2720
+ UCHAR Tb7Page1; // (2740) Translation Buffer 7 Page 1
+ UCHAR Filler51; // (2760)
+ UCHAR Tb7Page2; // (2780) Translation Buffer 7 Page 2
+ UCHAR Filler52; // (27a0)
+ UCHAR Tb7Page3; // (27c0) Translation Buffer 7 Page 3
+
+} IOD_SG_CSRS, *PIOD_SG_CSRS;
+
+
+typedef union _IOD_TBIA{
+ struct{
+ ULONG Reserved0: 32; // <31:0> Don't care
+ };
+ ULONG all;
+} IOD_TBIA, *PIOD_TBIA;
+
+typedef union _IOD_HBASE{
+ struct{
+ ULONG Hbound: 9; // <8:0> PC compatibility hole upper bound
+ ULONG Reserved0: 4; // <12:9>
+ ULONG PcHe1: 1; // <13> Fixed hole (512 Kb - 1 Mb) enable
+ ULONG PcHe2: 1; // <14> Moveable hole (Hbase - Hbound) enable
+ ULONG Hbase: 9; // <23:15> PC compatibility hole lower bound
+ ULONG Reserved1: 8; // <31:24>
+ };
+ ULONG all;
+} IOD_HBASE, *PIOD_HBASE;
+
+typedef union _IOD_WBASE{
+ struct{
+ ULONG Wen: 1; // <0> Window enable
+ ULONG SgEn: 1; // <1> Scatter Gather enable
+ ULONG Reserved: 1; // <2>
+ ULONG DacEn: 1; // <3> DAC Enable (W3base only)
+ ULONG Reserved0: 16; // <19:4>
+ ULONG Wbase: 12; // <31:20> Base address of DMA window, bits <31:20>
+ };
+ ULONG all;
+} IOD_WBASE, *PIOD_WBASE;
+
+typedef union _IOD_WMASK{
+ struct{
+ ULONG Reserved0: 20; // <19:0>
+ ULONG Wmask: 12; // <31:20> Window mask
+ };
+ ULONG all;
+} IOD_WMASK, *PIOD_WMASK;
+
+typedef union _IOD_TBASE{
+ struct{
+ ULONG Reserved0: 2; // <1:0>
+ ULONG Tbase: 30; // <31:2> Translation base address, bits <39:10>
+ };
+ ULONG all;
+} IOD_TBASE, *PIOD_TBASE;
+
+typedef union _IOD_WDAC{
+ struct{
+ ULONG Wdac: 8; // <7:0> Bbase addr of DAC DMA window 3, bits <39:32>
+ ULONG Reserved0: 24; // <31:8>
+ };
+ ULONG all;
+} IOD_WDAC, *PIOD_WDAC;
+
+typedef union _IOD_TB_TAG{
+ struct{
+ ULONG Valid: 1; // <0> SG TB tag is valid
+ ULONG Reserved0: 1; // <1>
+ ULONG Dac: 1; // <2> SG TB tag corresponds to a 64-bit (DAC) addr
+ ULONG Reserved1: 12; // <14:3>
+ ULONG TbTag: 17; // <31:15> SG TB tag itself
+ };
+ ULONG all;
+} IOD_TB_TAG, *PIOD_TB_TAG;
+
+typedef union _IOD_TB_PAGE{
+ struct{
+ ULONG Valid: 1; // <0> SG Page address is valid
+ ULONG PageAddr: 27; // <27:1> SG TB Page address
+ ULONG Reserved1: 12; // <31:28>
+ };
+ ULONG all;
+} IOD_TB_PAGE, *PIOD_TB_PAGE;
+
+
+//
+// DMA Window Values.
+//
+// The IOD will be initialized to allow 2 DMA windows.
+// The first window will be for the use of of ISA devices and DMA slaves
+// and therefore must have logical addresses below 16MB.
+// The second window will be for bus masters (non-ISA) and so may be
+// above 16MB.
+//
+// The arrangement of the windows will be as follows:
+//
+// Window Logical Start Address Window Size
+// ------ --------------------- -----------
+// Isa 8MB 8MB
+// Master 16MB 16MB
+//
+
+#define ISA_DMA_WINDOW_BASE (__8MB)
+#define ISA_DMA_WINDOW_SIZE (__8MB)
+
+#define MASTER_DMA_WINDOW_BASE (__16MB)
+#define MASTER_DMA_WINDOW_SIZE (__16MB)
+
+//
+// Define the software control registers for a DMA window.
+//
+
+typedef struct _WINDOW_CONTROL_REGISTERS{
+ PVOID WindowBase;
+ ULONG WindowSize;
+ PVOID TranslatedBaseRegister;
+ PVOID WindowBaseRegister;
+ PVOID WindowMaskRegister;
+ PVOID WindowTbiaRegister;
+} WINDOW_CONTROL_REGISTERS, *PWINDOW_CONTROL_REGISTERS;
+
+//
+// Define types of windows.
+//
+
+typedef enum _IOD_WINDOW_NUMBER{
+ IodIsaWindow,
+ IodMasterWindow
+} IOD_WINDOW_NUMBER, *PIOD_WINDOW_NUMBER;
+
+//
+// Define IOD Window Control routines.
+//
+
+VOID
+HalpIodInitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ IOD_WINDOW_NUMBER WindowNumber
+ );
+
+VOID
+HalpIodProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ );
+
+VOID
+HalpIodInvalidateTlb(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters
+ );
+
+PKPCR
+HalpRdPcr(
+ VOID
+ );
+
+//
+// Define IOD CSR Routines
+//
+
+VOID
+WRITE_IOD_REGISTER(
+ PVOID,
+ ULONG
+ );
+
+ULONG
+READ_IOD_REGISTER(
+ PVOID
+ );
+
+VOID
+WRITE_IOD_REGISTER_NEW(
+ MC_DEVICE_ID,
+ PVOID,
+ ULONG
+ );
+
+ULONG
+READ_IOD_REGISTER_NEW(
+ MC_DEVICE_ID,
+ PVOID
+ );
+
+//
+// Define IOD interrupt request/acknowledge routines
+//
+
+ULONG
+INTERRUPT_ACKNOWLEDGE(
+ PVOID
+ );
+
+VOID
+IOD_INTERRUPT_ACKNOWLEDGE(
+ MC_DEVICE_ID McDeviceId,
+ ULONG Target
+ );
+
+VOID
+CPU_CLOCK_ACKNOWLEDGE(
+ MC_DEVICE_ID McDeviceId
+ );
+
+VOID
+IP_INTERRUPT_REQUEST(
+ MC_DEVICE_ID McDeviceId
+ );
+
+VOID
+IP_INTERRUPT_ACKNOWLEDGE(
+ MC_DEVICE_ID McDeviceId
+ );
+
+//
+// Define MC Bus emumerator routines
+//
+
+
+ULONG
+HalpMcBusEnumStart(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_CONTEXT McContext
+ );
+
+BOOLEAN
+HalpMcBusEnum(
+ PMC_ENUM_CONTEXT McContext
+ );
+
+VOID
+HalpMcBusEnumAndCall(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_ROUTINE McBusEnumRoutine,
+ ...
+ );
+
+//
+// Define other IOD routines
+//
+
+ULONG
+HalpReadWhoAmI(
+ VOID
+ );
+
+VOID
+HalpInitializeIodVectorTable(
+ VOID
+ );
+
+VOID
+HalpInitializeIodMappingTable(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+BOOLEAN
+HalpIodUncorrectableError(
+ PMC_DEVICE_ID pMcDeviceId
+ );
+
+VOID
+HalpIodReportFatalError(
+ MC_DEVICE_ID McDevid
+ );
+
+BOOLEAN
+HalpIodMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+VOID
+HalpInitializeIod(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+VOID
+HalpInitializeIodVectorCSRs(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+VOID
+HalpInitializeIodMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ );
+
+VOID
+HalpIodSoftErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpIodHardErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpClearAllIods(
+ IOD_CAP_ERR IodCapErrMask
+);
+
+#define ALL_CAP_ERRORS 0xffffffff
+
+
+#if HALDBG || defined(DUMPIODS)
+
+VOID
+DumpIod(
+ MC_DEVICE_ID DevId,
+ IOD_REGISTER_CLASS RegistersToDump
+ );
+
+VOID
+DumpAllIods(
+ IOD_REGISTER_CLASS RegistersToDump
+ );
+
+#endif //HALDBG
+
+
+//
+// VOID
+// INITIALIZE_ISA_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_ISA_DMA_CONTROL( WR ) \
+ HalpIodInitializeSfwWindow( (WR), IodIsaWindow );
+
+
+//
+// VOID
+// INITIALIZE_MASTER_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the PCI
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_MASTER_DMA_CONTROL( WR ) \
+ HalpIodInitializeSfwWindow( (WR), IodMasterWindow );
+
+
+//
+// VOID
+// INITIALIZE_DMA_WINDOW(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters,
+// PTRANSLATION_ENTRY MapRegisterBase
+// )
+//
+// Routine Description:
+//
+// Program the control windows so that DMA can be started to the
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window register
+// control structure.
+//
+// MapRegisterBase - Supplies the logical address of the scatter/gather
+// array in system memory.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_DMA_WINDOW( WR, MRB ) \
+ HalpIodProgramDmaWindow( (WR), (MRB) );
+
+
+//
+// VOID
+// INVALIDATE_DMA_TRANSLATIONS(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Invalidate all of the cached translations for a DMA window.
+//
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control
+// registers.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INVALIDATE_DMA_TRANSLATIONS( WR ) \
+ HalpIodInvalidateTlb( (WR) );
+
+
+//
+// Define the format of a translation entry aka a scatter/gather entry
+// or map register.
+//
+
+typedef struct _TRANSLATION_ENTRY{
+ ULONG Valid: 1;
+ ULONG Pfn: 31;
+ ULONG Reserved;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+
+//
+// VOID
+// HAL_MAKE_VALID_TRANSLATION(
+// PTRANSLATION_ENTRY Entry,
+// ULONG PageFrameNumber
+// )
+//
+// Routine Description:
+//
+// Make the scatter/gather entry pointed to by Entry valid with
+// a translation to the page indicated by PageFrameNumber.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation entry to make valid.
+//
+// PageFrameNumber - Supplies the page frame of the valid translation.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_MAKE_VALID_TRANSLATION( ENTRY, PFN ) \
+ { \
+ (ENTRY)->Valid = 1; \
+ (ENTRY)->Pfn = PFN; \
+ (ENTRY)->Reserved = 0; \
+ }
+
+
+//
+// VOID
+// HAL_INVALIDATE_TRANSLATION(
+// PTRANSLATION_ENTRY Entry
+// )
+//
+// Routine Description:
+//
+// Invalidate the translation indicated by Entry.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation to be invalidated.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_INVALIDATE_TRANSLATION( ENTRY ) \
+ (ENTRY)->Valid = 0;
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_IODH_
diff --git a/private/ntos/nthals/halraw/alpha/iodaddr.c b/private/ntos/nthals/halraw/alpha/iodaddr.c
new file mode 100644
index 000000000..d0a2958f3
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iodaddr.c
@@ -0,0 +1,731 @@
+/*++
+
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iodaddr.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Rawhide system.
+
+Author:
+
+ Eric Rehm 10-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on Alpha and MIPS machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we use the macro
+ HAL_MAKE_IOD_SPARSE_QVA to build a Quasi Virtual address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+
+ Note that KernelPciDenseMemory *is* mapped via MmMapIoSpace.
+
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 40 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+Rawhide notes:
+
+ QVA's on Rawhide encode a BusNumber and an offset on that bus, i.e.,
+ the physical address is not directly coded in the QVA. The actual
+ superpage physical address is constructed at the time of access.
+
+ Sparse QVA space from A000.0000 - C000.0000 is separate for I/O
+ and memory space. For example, sparse memory address 0 on BusNumber
+ 0 has QVA = A000.0000 and sparse I/O address 0 on BusNumber 0 also
+ has QVA = A000.0000. The user of a QVA must know what they're
+ doing, and properly call the correct access routine for the
+ address space that they desire.
+
+ Finally, sparse and dense memory QVA's must coexist with the
+ same memory access routines (READ/WRITE_REGISTER_*). Since
+ Rawhide has 4 I/O buses, supporting 4 * 1 Gb dense spaces +
+ 4 * 128 Mb sparse spaces is not possible using a 32 bit QVA.
+ Therefore, we arbitrarily "short sheet" the dense address space
+ of BusNumber 2 to 512 Mb to make room for the sparse space QVAs.
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ MC_DEVICE_ID McDeviceId;
+ PPCIPBUSDATA BusData;
+ ULONG HwBusNumber;
+
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // Check InterfaceType:
+ // The only buses available on Rawhide are an EISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if ( (InterfaceType != Isa) &&
+ (InterfaceType != Eisa) &&
+ (InterfaceType != PCIBus) ) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+#if HALDBG
+ DbgPrint( "HalTBA: Unhandled interface type = %x\n", InterfaceType );
+#endif //HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Next, generate the IOD number (HwBusNumber).
+ //
+ // If it's ISA or EISA, BusNumber and HwBusNumber = 0.
+ // If it's PCI, we get HwBusNumber from PCI-specific bus data.
+ //
+
+ HwBusNumber = 0; // Isa, Eisa
+ if (InterfaceType == PCIBus ) {
+
+ //
+ // Get a pointer to the PCIBus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // In particular, what root PCI bus (IOD) are we on?
+ //
+
+ HwBusNumber = BusData->HwBusNumber;
+ }
+
+ //
+ // Build MC Bus device id for this bus using HwBusNumber.
+ // Currently, only the Primary Global Id (0x7) is supported.
+ //
+
+ McDeviceId.all = 0;
+ McDeviceId.Gid = GidPrimary;
+ McDeviceId.Mid = MidPci0 + HwBusNumber;
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case Eisa:
+
+ //
+ // Eisa is the same as PCI, with respect to kernel mode
+ // sparse and dense space memory support, i.e., its a full 32 bit space,
+ // supports dense memory access.
+ //
+
+ case PCIBus: {
+
+ //
+ // Don't allow accesses to PCI/EISA addresses below
+ // 1 Mb on root buses other than PCI-0.
+ //
+#if 1 // ecrfix - needed for WINT3.51 !!!
+ if ( BusAddress.LowPart < __1MB &&
+ HwBusNumber > 0 ) {
+#if HALDBG
+ DbgPrint ("Unsupported PCI-%d (ISA legacy) address %x:%x\n",
+ HwBusNumber,
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+#endif
+
+ //
+ // Check legal PCI bus address ranges
+ //
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply PCI bus address offset
+ // from the base dense memory address for that bus.
+ // The bus number is encoded in bits <31:30>.
+ //
+
+ TranslatedAddress->LowPart = (ULONG)
+ HAL_MAKE_IOD_DENSE_QVA(HwBusNumber, BusAddress.LowPart);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ //
+ // Now create the QVA from the HwBusNumber and BusAddress.
+ //
+ // Unlike many other Alpha platfroms, the QVA is *not* an
+ // encoding of the physical address. The full physical address
+ // will can be constructed at the time of the I/O access with the
+ // information encoded here in the QVA: HwBusNumber and BusAddress.
+ // (The bus number is encoded in bits <28:27> of the QVA.)
+ //
+
+ TranslatedAddress->LowPart = (ULONG)
+ HAL_MAKE_IOD_SPARSE_QVA(HwBusNumber, BusAddress.LowPart);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Eisa:
+
+ //
+ // Eisa is the same as ISA, with respect to kernel mode
+ // sparse I/O space support, i.e., it is a 16 bit sparse
+ // space.
+ //
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 32MB (25 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+
+ if( BusAddress.LowPart >= __32MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ //
+ // Now create the QVA from the HwBusNumber and BusAddress.
+ //
+ // Unlike many other Alpha platfroms, the QVA is *not* an
+ // encoding of the physical address. The full physical address
+ // will can be constructed at the time of the I/O access with the
+ // information encoded here in the QVA: HwBusNumber and BusAddress.
+ // (The bus number is encoded in bits <28:27> of the QVA.)
+ //
+
+ TranslatedAddress->LowPart = (ULONG)
+ HAL_MAKE_IOD_SPARSE_QVA(HwBusNumber, BusAddress.LowPart);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = IOD_SPARSE_MEM_OFFSET;
+ TranslatedAddress->QuadPart |= MCDEVID_TO_PHYS_ADDR( McDeviceId.all );
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += (((ULONGLONG)BusAddress.LowPart) << IO_BIT_SHIFT);
+
+#if HALDBG
+ DbgPrint ("Translating PCI user mem sparse address %x:%x to %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart,
+ TranslatedAddress->HighPart,
+ TranslatedAddress->LowPart);
+#endif
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = IOD_SPARSE_IO_OFFSET;
+ TranslatedAddress->QuadPart |= MCDEVID_TO_PHYS_ADDR( McDeviceId.all );
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += (((ULONGLONG)BusAddress.LowPart) << IO_BIT_SHIFT);
+
+#if HALDBG
+ DbgPrint ("Translating PCI user I/O sparse address %x:%x to %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart,
+ TranslatedAddress->HighPart,
+ TranslatedAddress->LowPart);
+#endif
+
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI dense memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = IOD_DENSE_MEM_OFFSET;
+ TranslatedAddress->QuadPart |= MCDEVID_TO_PHYS_ADDR( McDeviceId.all );
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+#if HALDBG
+ DbgPrint("HTBA: UserPciDenseMemory %x to %x;%x\n",
+ BusAddress.LowPart,
+ TranslatedAddress->HighPart,
+ TranslatedAddress->LowPart);
+#endif // HALDBG
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ }
+
+
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is only available to a caller constructing a QVA
+ as a result of a page table mapping via ZwMapViewOfSection or
+ MmMapIoSpace.
+
+ N.B. HalTranslateBusAddress, or other HAL routines MUST NOT
+ CALL THIS ROUTINE. This is because on Rawhide, a kernel-mode
+ dense or sparse superpage QVA cannot be contructed without
+ knowledge of the BusNumber, which is not passed into this routine.
+
+ If the input parameter VA is zero, then we assume the caller
+ was incorrectly attempting to create a super page and build
+ a QUASI virtual address, and results in an error.
+
+ If the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not an I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PHYSICAL_ADDRESS PhysicalOffset;
+ PVOID qva;
+
+ PhysicalOffset.QuadPart = PHYS_ADDR_TO_OFFSET( PA.QuadPart );
+
+#if HALDBG
+ DbgPrint("HalCreateQva: PhysicalOffset = %x;%x\n",
+ PhysicalOffset.HighPart,
+ PhysicalOffset.LowPart);
+#endif
+
+
+ if (VA == 0) {
+
+ //
+ // Error - HalCreateQva should not be called to create
+ // a superpage QVA.
+ //
+
+#if HALDBG
+
+ DbgPrint( "HalCreateQva: Should not be called to create a superpage QVA from %x:%x\n", PA.HighPart, PA.LowPart );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ return (VA);
+
+ } else if( (PhysicalOffset.QuadPart >= IOD_DENSE_MEM_OFFSET) &&
+ (PhysicalOffset.QuadPart <= (IOD_DENSE_MEM_OFFSET +
+ PCI_MAX_DENSE_MEMORY_ADDRESS)) ){
+
+ //
+ // Physical dense address, return VA.
+ //
+
+#if HALDBG
+ DbgPrint("HalCreateQva: User Mode Dense QVA = VA = %x\n", VA);
+#endif
+ return(VA);
+
+ } else {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+#if HALDBG
+ DbgPrint("HalCreateQva: User Mode Sparse QVA = %x\n", qva);
+#endif
+ return(qva);
+ }
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Sable we have three supported bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+ break;
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
+
diff --git a/private/ntos/nthals/halraw/alpha/ioderr.c b/private/ntos/nthals/halraw/alpha/ioderr.c
new file mode 100644
index 000000000..f0038b5e5
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ioderr.c
@@ -0,0 +1,2304 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ ioderr.c
+
+Abstract:
+
+ This module implements error handling functions for the Rawhide
+ IOD (CAP and MDP ASICs).
+
+Author:
+
+ Eric Rehm 13-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+//#include "iod.h"
+#include "rawhide.h"
+#include "stdio.h"
+
+//
+// Externals and globals.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+extern ULONG HalDisablePCIParityChecking;
+ULONG IodCorrectedErrors = 0;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+//
+// The Soft Error interrupt is always turned on for Rawhide. When a
+// Soft Error interrupt occurs, HalpIodSoftErrorInterrupt() must
+// be called to reset the error condition on the offending IOD to
+// insure system integrity.
+//
+// A Correctable Error Driver might also connect to the Soft Error interrupt
+// via the Internal Bus interface. When a Soft Error interrupt occurs,
+// we determine if it is also necessary to dispatch an ISR for the
+// Correctable Error Driver via a boolean.
+//
+
+BOOLEAN HalpLogCorrectableErrors = FALSE;
+
+//
+// Keep the first time we read the WhoAmI register
+// since it does not always read the same the second time.
+//
+// Zero value indicates that we haven't read WhoAmI yet and that
+// this global variable is not valid.
+//
+// (On machine checks that we dismiss, we must remember to
+// to reset this to zero.)
+//
+
+IOD_WHOAMI HalpIodWhoAmIOnError = { 0 };
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ );
+
+//
+// Function prototypes for routines not visible outside this module
+//
+
+VOID
+HalpBuildIodErrorFrame(
+ MC_DEVICE_ID McDeviceId,
+ PIOD_ERROR_FRAME IodErrorFrame
+ );
+
+BOOLEAN
+bFindIodError(
+ PMC_DEVICE_ID pMcDeviceId,
+ PIOD_CAP_ERR pIodCapErr
+);
+
+BOOLEAN
+bHandleFatalIodError(
+ MC_DEVICE_ID McDeviceId,
+ BOOLEAN bMachineCheck
+ );
+
+BOOLEAN
+bHandleIsaError(
+ MC_DEVICE_ID pMcDeviceId,
+ IOD_CAP_ERR IodCapErr
+);
+
+VOID
+HalpErrorFrameString(
+ PUNCORRECTABLE_ERROR uncorr,
+ PUCHAR OutBuffer
+ );
+
+ULONG
+BuildActiveCpus (
+ VOID
+ );
+
+//
+// Allocate a flag that indicates when a PCI Master Abort is expected.
+// PCI Master Aborts are signaled on configuration reads to non-existent
+// PCI slots. A cardinal value (0-128) indicates that a Master Abort is expected.
+// A value of 0xffffffff indicates that a Master Abort is *not* expected.
+//
+
+IOD_EXPECTED_ERROR HalpMasterAbortExpected = {MASTER_ABORT_NOT_EXPECTED, 0x0};
+
+
+VOID
+HalpInitializeIodMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for a IOD-based
+ system by clearing all pending errors in the IOD registers and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_CAP_CONTROL IodCapControl;
+ IOD_CAP_ERR IodCapError;
+ IOD_MDPA_DIAG IodMdpaDiag;
+ IOD_MDPB_DIAG IodMdpbDiag;
+ IOD_INT_MASK IodIntMask;
+
+ MC_DEVICE_ID McDeviceId;
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+
+ //
+ // Clear any pending error bits in the IOD_CAP_ERR register:
+ //
+
+ IodCapError.all = 0; // Clear all bits
+
+ IodCapError.Perr = 1; // PCI bus perr detected
+ IodCapError.Serr = 1; // PCI bus serr detected
+ IodCapError.Mab = 1; // PCI bus master abort detected
+ IodCapError.PteInv = 1; // Invalid Pte
+ IodCapError.PioOvfl = 1; // Pio Ovfl
+ IodCapError.LostMcErr = 1; // Lost error
+ IodCapError.McAddrPerr = 1; // MC bus comd/addr parity error
+ IodCapError.Nxm = 1; // Non-existent memory error
+ IodCapError.CrdA = 1; // Correctable ECC error on MDPA
+ IodCapError.CrdB = 1; // Correctable ECC error on MDPB
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Intialize each Iod
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ McDeviceId = mcCtx.McDeviceId;
+
+ //
+ // Initialize IOD_CAP_ERR
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapError.all );
+
+ //
+ // Set the Iod error enable bits in the IOD_CAP_CTRL and
+ // IOD_MDPA/B_DIAG registers. The configuration bits in the IOD
+ // will be left as set by the Extended SROM, with the few
+ // exceptions documented below.
+ //
+
+ IodCapControl.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
+
+#if 0 // CAP/MDP Bug
+ IodMdpaDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag );
+
+ IodMdpbDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag );
+#else
+
+ //
+ // Clear Mdp Diagnotic Check Registers....
+ //
+
+ IodMdpaDiag.all = 0;
+ IodMdpbDiag.all = 0;
+
+ //
+ // Enable ECC checking on all MC Bus transactions
+ //
+
+ IodMdpaDiag.EccCkEn = 1;
+ IodMdpbDiag.EccCkEn = 1;
+
+#endif
+
+ //
+ // Disable/enable PCI parity checking as requested
+ //
+
+ if (PciParityChecking == FALSE) {
+
+ IodCapControl.PciAddrPe= 0; // Do *not* check PCI address parity
+ IodMdpaDiag.ParCkEn = 0; // Do *not* check PCI data parity
+ IodMdpbDiag.ParCkEn = 0; // Do *not* check PCI data parity
+
+ } else {
+
+ IodCapControl.PciAddrPe= PciParityChecking;
+ IodMdpaDiag.ParCkEn = PciParityChecking;
+ IodMdpbDiag.ParCkEn = PciParityChecking;
+
+ }
+
+
+ //
+ // Disable McBus NXM's
+ //
+ // (If enabled, accesses to non-existent McBus device will cause an
+ // EV5 fill error. Non existant CSRs will return all 0s most of the time
+ // and not fill error.)
+ //
+
+ IodCapControl.McNxmEn = 0;
+
+ //
+ // Disable monitoring of McBus bystander errors.
+ //
+ // That means the IOD will not capture the failing address in the event of
+ // an MC bus NXM. It has no effect on what the IOD does in the event of a
+ // PCI NXM (which causes a Master Abort).
+ //
+ // Regardless of how McBusMonEn PCI PERR, SERR, MAB, and PTE_INV
+ // will only show up in IOD CAP_ERR of the participant in the transaction.
+ //
+ // If McBusMonEn is set, there can be a difference between the bystander CAP_ERR
+ // state and the participant CAP_ERR state (as per Sam Duncan, 5/3/95)
+ // shows up in an unlikely situation:
+ // "Cache single bit or double bit error: read is dirty in a cache
+ // and the fill has an ecc error, don't want to indite a memory for this
+ // (very unlikely) error."
+ // Thus, we choose not to be able to correctly detect this situation in
+ // order to make machine check and error handling easier, i.e., we
+ // always only need to clear only one IOD's CAP_ERROR.
+ //
+
+ IodCapControl.McBusMonEn= 0;
+
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl,
+ IodCapControl.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag,
+ IodMdpaDiag.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag,
+ IodMdpbDiag.all );
+
+
+ //
+ // Soft and Hard Error handling
+ //
+ // ecrfix - IntMask0 on Bus 0 only.
+
+ IodIntMask.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0 );
+
+ IodIntMask.SoftErr = (ReportCorrectableErrors == TRUE);
+ IodIntMask.HardErr = 0; // ecrfix - Mask Hard Errors for now
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0,
+ IodIntMask.all );
+
+ } // while ( HalpMcBusEnum ( &mcCtx ) )
+
+ //
+ // Set the machine check enables within the EV5.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ } else {
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ return;
+
+}
+
+#define MAX_ERROR_STRING 128
+
+
+BOOLEAN
+HalpIodUncorrectableError(
+ PMC_DEVICE_ID pMcDeviceId
+ )
+/*++
+
+Routine Description:
+
+ Read the IOD error register and determine if an uncorrectable error
+ is latched in the error bits.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE is returned if an uncorrectable error has been detected. FALSE
+ is returned otherwise.
+
+--*/
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ IOD_WHOAMI IodWhoAmI;
+ IOD_CAP_ERR IodCapErr;
+
+ //
+ // Check for a duplicate tag parity error on this (in the Smalltalk
+ // sense) processor.
+ //
+
+ IodWhoAmI.all = HalpReadWhoAmI();
+ HalpIodWhoAmIOnError.all = IodWhoAmI.all;
+
+ if ( IodWhoAmI.CpuInfo & CACHED_CPU_DTAG_PARITY_ERROR ) {
+
+ pMcDeviceId->all = IodWhoAmI.Devid;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // None of the uncorrectable error conditions were detected.
+ //
+
+ return FALSE;
+ }
+
+}
+
+VOID
+HalpBuildIodErrorFrame(
+ MC_DEVICE_ID McDeviceId,
+ PIOD_ERROR_FRAME IodErrorFrame
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error
+ detected by the IOD chipset. It is assumed that HalGetDisplayOwnership()
+ has been called prior to this function.
+
+Arguments:
+
+ McDevid - Supplies the MC Bus Device ID of the IOD
+ IodErrorFrame - Supplies a pointer to an IOD_ERROR_FRAME
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Clear it first, since caller may reuse the IodErrorFrame
+ //
+
+ RtlZeroMemory(IodErrorFrame, sizeof(IOD_ERROR_FRAME));
+
+ //
+ // Everything is valid
+ //
+
+ IodErrorFrame->ValidBits.all = 0xffffffff; // all valid
+
+
+ //
+ // Read the General registers
+ //
+
+ IodErrorFrame->BaseAddress = IOD_IO_SPACE_START |
+ IOD_SPARSE_CSR_OFFSET |
+ MCDEVID_TO_PHYS_ADDR(McDeviceId.all);
+
+ IodErrorFrame->WhoAmI = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI
+ );
+
+ IodErrorFrame->PciRevision = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision
+ );
+
+ IodErrorFrame->CapCtrl = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl
+ );
+
+ IodErrorFrame->HaeMem = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeMem
+ );
+
+ IodErrorFrame->HaeIo = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeIo
+ );
+
+ //
+ // Read Interrupt Control and Status Registers
+ //
+
+ IodErrorFrame->IntCtrl = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl
+ );
+
+ IodErrorFrame->IntReq = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq
+ );
+
+ IodErrorFrame->IntMask0 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0
+ );
+
+ IodErrorFrame->IntMask1 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1
+ );
+
+ //
+ // Read the rest of the error registers and then unlock them by
+ // writing to CAP_ERR
+ //
+
+ IodErrorFrame->CapErr = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr
+ );
+
+ IodErrorFrame->PciErr1 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1
+ );
+
+ IodErrorFrame->McErr0 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr0
+ );
+
+ IodErrorFrame->McErr1 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1
+ );
+#if 0 // CAP/MDP Bug
+ IodErrorFrame->MdpaStat = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat
+ );
+
+ IodErrorFrame->MdpaSyn = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaSyn
+ );
+
+ IodErrorFrame->MdpbStat = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat
+ );
+
+ IodErrorFrame->MdpbSyn = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbSyn
+ );
+#else
+
+ //
+ // CAP/MDP Bug - these registers are not valid.
+ //
+
+ IodErrorFrame->ValidBits.MdpaStatValid = 0;
+ IodErrorFrame->ValidBits.MdpbStatValid = 0;
+ IodErrorFrame->ValidBits.MdpaSynValid = 0;
+ IodErrorFrame->ValidBits.MdpbSynValid = 0;
+
+#endif // CAP/MDP Bug
+
+}
+
+VOID
+HalpIodReportFatalError(
+ MC_DEVICE_ID ErrorMcDeviceId
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error
+ detected by the IOD chipset. It is assumed that HalGetDisplayOwnership()
+ has been called prior to this function.
+
+Arguments:
+
+ ErrorMcDeviceId - Supplies the MC Bus Device ID of the IOD
+ where the error was found
+
+ - In the case of a Duplicate Tag Parity Error, supplies
+ the CPU that took the error. Note, in this case
+ the ErrorMcDeviceId will never match a IOD McDeviceId.
+ No MC Bus snapshot is present in this case.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ IOD_ERROR_FRAME IodErrorFrame, *pCurrentIodErrorFrame;
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceId;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+
+ PUNCORRECTABLE_ERROR uncorr = NULL;
+ PRAWHIDE_UNCORRECTABLE_FRAME rawerr = NULL;
+ PEXTENDED_ERROR PExtErr;
+
+ //
+ // Do we have an uncorrectable error frame?
+ //
+
+ if (PUncorrectableError) {
+ uncorr = (PUNCORRECTABLE_ERROR)
+ &PUncorrectableError->UncorrectableFrame;
+ rawerr = (PRAWHIDE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ //
+ // Validate the ProcessorInfo portion of the Error Frame.
+ //
+
+ if (uncorr) {
+ uncorr->Flags.ProcessorInformationValid = 1;
+ HalpGetProcessorInfo(&uncorr->ReportingProcessor);
+
+ //
+ // Initialize our "error string accumulator"
+ //
+
+ HalpErrorFrameString( uncorr, NULL );
+
+ }
+
+ //
+ // Validate the Rawhide Uncorrectable Frame
+ // (Common RCUD Header was already set up.)
+ //
+
+ if (rawerr) {
+ rawerr->Revision = RAWHIDE_UNCORRECTABLE_FRAME_REVISION;
+ rawerr->WhoAmI = HalpIodWhoAmIOnError.all;
+ rawerr->ErrorSubpacketFlags.all = 0;
+ rawerr->CudHeader.ActiveCpus = BuildActiveCpus();
+
+ }
+
+ //
+ // Handle cached CPU duplicate tag parity error.
+ // (Note that a DTAG parity error implies that we don't
+ // take an MC Bus Snapshot.
+ //
+
+ if ( HalpIodWhoAmIOnError.CpuInfo & CACHED_CPU_DTAG_PARITY_ERROR ) {
+
+ sprintf( OutBuffer, "Duplicate Tag Parity Error on CPU %x\n",
+ MCDEVID_TO_PHYS_CPU(HalpIodWhoAmIOnError.McDevId.all) );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( "Duplicate Tag Parity Error on CPU (%d, %d)\n",
+ HalpIodWhoAmIOnError.McDevId.Gid, HalpIodWhoAmIOnError.McDevId.Mid);
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer );
+
+ //
+ // OK. This is tedious:
+ // * Error is in memory space and is the system (external) cache.
+ // * And we know this is the L3 cache.
+ // * And we'll subvert the "CacheBoard" to squirrel away the
+ // Cached CPU Revision Info and Cache size.
+ //
+
+ uncorr->Flags.AddressSpace = MEMORY_SPACE;
+ uncorr->Flags.ExtendedErrorValid = 1;
+ uncorr->Flags.MemoryErrorSource = SYSTEM_CACHE;
+ PExtErr->CacheError.Flags.CacheLevelValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.Flags.CacheSimmValid = 0;
+ PExtErr->CacheError.CacheLevel = 3;
+ PExtErr->CacheError.CacheBoardNumber = HalpIodWhoAmIOnError.CpuInfo;
+
+ return;
+ }
+
+ //
+ // Handle cached CPU fill error.
+ // Since this could be caused by an MC Bus or PCI error,
+ // we continue to create an MC Bus snapshot.
+ //
+
+ if ( HalpIodWhoAmIOnError.CpuInfo & CACHED_CPU_FILL_ERROR ) {
+
+ sprintf( OutBuffer, "Fill Error on CPU %x\n",
+ MCDEVID_TO_PHYS_CPU(HalpIodWhoAmIOnError.McDevId.all) );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( "Fill Error on CPU (%d, %d)\n",
+ HalpIodWhoAmIOnError.McDevId.Gid, HalpIodWhoAmIOnError.McDevId.Mid);
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer );
+
+ //
+ // * WhoAmI tells us Addr<38:33> of reference causing error.
+ // * However, PciErr1 and/or McErr0/McErr1 give us more bits,
+ // so the data entered here my get overwritten later.
+ //
+
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress =
+ ( ((ULONGLONG)(HalpIodWhoAmIOnError.CpuInfo & 0x3f)) << 33 );
+
+ }
+
+ //
+ // Validate the MCBusSnapshot header.
+ //
+
+ if (rawerr) {
+ rawerr->ErrorSubpacketFlags.McBusPresent = 1;
+ rawerr->McBusSnapshot.ReportingCpuBaseAddr =
+ IOD_IO_SPACE_START |
+ MCDEVID_TO_PHYS_ADDR( HalpIodWhoAmIOnError.Devid );
+ pCurrentIodErrorFrame = (PIOD_ERROR_FRAME) (rawerr + 1);
+ }
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+ ASSERT( numIods == HalpNumberOfIods);
+
+ //
+ // Gather data from each Iod
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ McDeviceId.all = mcCtx.McDeviceId.all;
+
+ HalpBuildIodErrorFrame( McDeviceId, &IodErrorFrame );
+
+ //
+ // Fill in IOD_ERROR_FRAME portion of the RAWHIDE_UNCORRECTABLE_FRAME
+ //
+
+ if (rawerr) {
+
+ RtlCopyMemory( pCurrentIodErrorFrame,
+ &IodErrorFrame,
+ sizeof(IOD_ERROR_FRAME));
+
+ pCurrentIodErrorFrame++;
+ }
+
+ //
+ // If this is the IOD where we found the error
+ // a. clear the error
+ // b. complete the uncorrectable error frame processing
+ // c. Display an interpretation of the error to the screen
+ //
+
+ if (ErrorMcDeviceId.all == McDeviceId.all) {
+
+ // ecrfix Put below into HalpInterpretIodError(McDeviceId, IodErrorFrame) ???
+ IOD_WHOAMI IodWhoAmI;
+ IOD_CAP_CONTROL IodCapCtrl;
+ IOD_CAP_ERR IodCapErr;
+ IOD_PCI_ERR1 IodPciErr1;
+ IOD_MC_ERR0 IodMcErr0;
+ IOD_MC_ERR1 IodMcErr1;
+ IOD_MDPA_STAT IodMdpaStat;
+ IOD_MDPB_STAT IodMdpbStat;
+ ULONG HwBusNumber = ErrorMcDeviceId.Mid & 0x3;
+
+ //
+ // Copy error frame variables in locals for bitfield access
+ //
+
+ IodWhoAmI.all = IodErrorFrame.WhoAmI;
+ IodCapCtrl.all = IodErrorFrame.CapCtrl;
+ IodCapErr.all = IodErrorFrame.CapErr;
+ IodPciErr1.PciAddress = IodErrorFrame.PciErr1;
+ IodMcErr0.all = IodErrorFrame.McErr0;
+ IodMcErr1.all = IodErrorFrame.McErr1;
+
+ #if 0 // CAP/MDP Bug
+ IodMdpaStat.all = IodErrorFrame.MdpaStat;
+ IodMdpbStat.all = IodErrorFrame.MdpbStat;
+ IodMdpaSyn.all = IodErrorFrame.MdpaSyn;
+ IodMdpbSyn.all = IodErrorFrame.MdpbSyn;
+ #else
+ IodMdpaStat.all = 0xffffffff;
+ IodMdpbStat.all = 0xffffffff;
+ #endif // CAP/MDP Bug
+
+
+
+ //
+ // Clear state in MDPA and MDPB before clearing CAP_ERR
+ //
+
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodErrorFrame.MdpaStat
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat,
+ IodErrorFrame.MdpbStat
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodErrorFrame.CapErr
+ );
+
+ sprintf( OutBuffer,
+ "IOD MC_DEVICE_ID : (%x, %x) CAP_CTRL : %08x CAP_ERR : %08x\n",
+ McDeviceId.Gid, McDeviceId.Mid,
+ IodCapCtrl.all,
+ IodCapErr.all );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+
+ sprintf( OutBuffer,
+ "PCI_ERR1 %08x MC_ERR0 : %08x MC_ERR1 : %08x\n",
+ IodPciErr1.PciAddress,
+ IodMcErr0.all,
+ IodMcErr1.all );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+
+ #if 0 // CAP/MDP Bug
+ sprintf( OutBuffer,
+ "MDPA_STAT : %08x MDPA_SYN : %08x MDPB_STAT : %08x MDPB_SYN : %08x\n",
+ IodMdpaStat.all,
+ IodMdpaSyn.all,
+ IodMdpbStat.all,
+ IodMdpbSyn.all );
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ #endif
+
+ //
+ // If no valid error then no interpretation.
+ //
+
+ if (( IodCapErr.PciErrValid == 0 ) && ( IodCapErr.McErrValid == 0 ) ){
+
+ return; // No IOD error detected
+
+ }
+
+ //
+ // Interpret any detected errors:
+ //
+
+ if (IodCapErr.McErrValid == 1) {
+
+ if ( IodMcErr1.Dirty != 1 ) {
+ sprintf( OutBuffer,
+ "MC Bus Error, Bus Master=(%x,%x)\n",
+
+ ( ( IodMcErr1.DevId & 0x38) >> 3 ),
+ ( IodMcErr1.DevId & 0x07)
+ );
+ } else {
+
+ sprintf( OutBuffer,
+ "MC bus error on a read/dirty transaction\n"
+ );
+ }
+
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+
+ sprintf( OutBuffer,
+ "IOD Addr=%x%x, Cmd=%x\n",
+ IodMcErr1.Addr39_32, // bits 39:32
+ IodMcErr0.Addr, // bits 31:4
+ IodMcErr1.McCmd
+ );
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+ //
+ // Interpret specific MC bus error
+ //
+
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = (
+ (((ULONGLONG)IodMcErr1.Addr39_32) << 32) |
+ ((ULONGLONG)IodMcErr0.Addr) );
+
+ //
+ // McAddr<39> indicates whether this was a
+ // memory or I/O transaction.
+ //
+
+ if ( (IodMcErr1.Addr39_32 & 0x80) == 1) {
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ } else {
+ uncorr->Flags.AddressSpace = MEMORY_SPACE;
+ }
+
+ if ( IodCapErr.PioOvfl == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD PIO Overflow, PendNumb=%x\n",
+ IodCapCtrl.PendNum
+ );
+
+ } else if ( IodCapErr.McAddrPerr == 1 ){
+
+ sprintf( OutBuffer,
+ "MC bus parity error\n"
+ );
+
+ } else if ( IodCapErr.Nxm == 1 ){
+
+ sprintf( OutBuffer,
+ "MC bus NXM\n"
+ );
+
+ } else if ( IodCapErr.CrdA == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Correctable ECC error in MDPA\n"
+ );
+
+ } else if ( IodCapErr.CrdB == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Correctable ECC error in MDPB\n"
+ );
+
+ } else if ( IodCapErr.RdsA == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Uncorrectable ECC error in MDPA\n"
+ );
+
+ } else if ( IodCapErr.RdsB == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Uncorrectable ECC error in MDPB\n"
+ );
+
+ }
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+ }
+
+ if ( IodCapErr.PciErrValid == 1 ){
+
+ //
+ // Interpret specific PCI bus error
+ //
+
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = IOD_IO_SPACE_START |
+ MCDEVID_TO_PHYS_ADDR(IodWhoAmI.McDevId.all) |
+ IodPciErr1.PciAddress << IO_BIT_SHIFT;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = HwBusNumber;
+ PExtErr->IoError.BusAddress.LowPart = IodPciErr1.PciAddress;
+
+ if ( IodCapErr.Perr == 1 ){
+ sprintf( OutBuffer,
+ "PERR detected on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+
+ } else if ( IodCapErr.Serr == 1 ){
+
+ sprintf( OutBuffer,
+ "SERR detected on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+
+ } else if ( IodCapErr.Mab == 1 ){
+
+ sprintf( OutBuffer,
+ "Master Abort on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+
+ } else if ( IodCapErr.PteInv == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid Scatter/Gather PTE on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+ }
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+ }
+
+ //
+ // Check for lost errors and output message if any occurred:
+ //
+
+ if ( IodCapErr.LostMcErr == 1 ){
+ HalDisplayString("IOD Lost errors were detected\n");
+#if HALDBG
+ DbgPrint("IOD Lost errors were detected\n");
+#endif
+ HalpErrorFrameString(uncorr, "IOD Lost errors were detected\n");
+ }
+
+ } // if (ErrorMcDeviceID == McDeviceId)
+
+ } // while (bfoundIod = HalpMcBusEnum)
+
+ return; // Fatal error detected
+}
+
+
+BOOLEAN
+HalpIodMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the IOD chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ IOD_CAP_ERR IodCapErr;
+ IOD_CAP_ERR IodCapErrMask;
+ IOD_MC_ERR1 IodMcErr1;
+ IOD_WHOAMI IodWhoAmI;
+ MC_DEVICE_ID McDeviceId;
+ BOOLEAN ExpectedMchk;
+ BOOLEAN ExpectedMcAddrPerr;
+ BOOLEAN PciMemReadMchk;
+ BOOLEAN bfoundIod;
+
+ //
+ // We don't expect a machine check yet...
+ //
+
+ ExpectedMchk = FALSE;
+ ExpectedMcAddrPerr = FALSE;
+
+ //
+ // Make sure any error due to 2Mb/4Mb Cached CUD bug is latched.
+ //
+ // At this point, WhoAmI may indicate the symptoms of a fill_error
+ // and CUD cache size is not available. We'll read it again when
+ // we need to know the Cache size. However, we save he here so we
+ // can figure out if this was a fill error or not.
+ //
+
+ HalpIodWhoAmIOnError.all = HalpReadWhoAmI();
+
+ //
+ // Where do we look for the error symptoms?
+ //
+ // 1. If we expected this machine check, then we know which
+ // IOD to check.
+ // 2. If we didn't expect this machine check, find the IOD that
+ // generated the error.
+ //
+
+ //
+ // For an expected machine check, HalpMasterAbortExpected will
+ // contain the processor number and address of a PCI config
+ // space read. CAP_ERR will indicate a MasterAbort.
+ //
+
+ if( HalpMasterAbortExpected.Number == (ULONG)KeGetCurrentProcessorNumber() ) {
+
+ //
+ // Determine expected IOD from the address of the PCI config read
+ //
+
+ McDeviceId.all = MCDEVID_FROM_PHYS_ADDR(HalpMasterAbortExpected.Addr);
+
+ //
+ // Now get the Bcache size information.
+ //
+
+ IodWhoAmI.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI);
+
+ //
+ //
+ // Make sure there is a Master abort on this IOD
+ //
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+
+ if( IodCapErr.Mab == 1 ) {
+ ExpectedMchk = TRUE;
+
+ //
+ // If 2Mb or 4 Mb cached CUD, and we may get an MCbus address parity
+ // error with MC command signature in MC_ERR1 equal to zero (cached
+ // CPU idle transaction). Also dismiss this error that's the result
+ // of the cached 2Mb/4Mb cached CPU VCTY bug.
+ //
+
+ IodMcErr1.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1 );
+
+ if ((IodWhoAmI.CpuInfo & 0x7) && // Cached CPU?
+ IodCapErr.McAddrPerr && // McAddrPerr?
+ (IodMcErr1.McCmd == 0) ) { // McCmd is zero?
+
+ ExpectedMcAddrPerr = TRUE; // All yes, then dismiss it!
+ }
+ }
+
+#if HALDBG
+ DbgPrint( "Expected Mchk (Mab) on IOD (%x, %x), Processor number %x\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ HalpMasterAbortExpected.Number);
+#endif //HALDBG
+ }
+
+ //
+ // If this isn't the machine check we expected, then
+ // we must find the IOD that took the error.
+ //
+
+ if (!ExpectedMchk) {
+
+ bfoundIod = bFindIodError( &McDeviceId, &IodCapErr );
+
+ //
+ // Check that we found an IOD that has a valid PCI or MC error.
+ // If it is not this is a pretty weird (fatal???) condition.
+ // For now, we'll just go return TRUE.
+ //
+ // ecrfix - should we check the error interrupts? probably not...
+ //
+
+ if( !bfoundIod ) {
+
+#if HALDBG
+ DbgPrint( "HalpIodMachineCheck called but no PCI or MC error found\n");
+#endif
+ return (TRUE);
+ }
+
+
+#if 0 // HALDBG
+ DbgPrint( "Unexpected Mchk on IOD (%x, %x)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid );
+#endif //HALDBG
+
+ //
+ // Case: Uexpected Master Abort, e.g. a PCI memory or I/O space read to
+ // legacy ISA space (0 - 1 Mb) on PCI-1,2,3.
+ //
+
+ if ( bHandleIsaError( McDeviceId, IodCapErr) ) {
+ return TRUE;
+ }
+
+ }
+
+ //
+ // Case: PCI or MC Bus error other than master abort
+ //
+ // At this point we have either:
+ // (a) an expected PCI Master Abort (ExpectedMchk == TRUE), or
+ // (b) an unexpected PCI or MC Bus error.
+ //
+ // However, it's possible that we have *both* (a) AND (b).
+ // So, even if ExpectedMch == TRUE, check for other PCI or MC Bus
+ // errors. Any of these other errors indicate a
+ // fatal condition.
+ //
+
+ if( (IodCapErr.Perr == 1) || // PCI bus perr detected
+ (IodCapErr.Serr == 1) || // PCI bus serr detected
+ (IodCapErr.PteInv == 1) || // Invalid Pte
+ (IodCapErr.PioOvfl == 1) || // Pio Ovfl
+
+ //
+ // Cached CUD with 2 Mb and 4 Mb Cache may also assert an MCAddrPerr
+ // or Nxm upon a config space read. Lost Error bit will also be set.
+ //
+ //
+
+ ( (IodCapErr.LostMcErr == 1) && !ExpectedMcAddrPerr) ||
+ // Lost error
+ ( (IodCapErr.McAddrPerr == 1) && !ExpectedMcAddrPerr ) ||
+ // MC bus comd/addr parity error
+
+
+ ( (IodCapErr.Nxm == 1) && !ExpectedMcAddrPerr ) ||
+ // Non-existent memory error
+ (IodCapErr.CrdA == 1) || // Correctable ECC error on MDPA
+ (IodCapErr.CrdB == 1) || // Correctable ECC error on MDPB
+ (IodCapErr.RdsA == 1) || // Uncorrectable ECC error on MDPA
+ (IodCapErr.RdsA == 1) // Uncorrectable ECC error on MDPA
+
+ ){
+ return ( bHandleFatalIodError(McDeviceId, TRUE) );
+ }
+
+ //
+ // At this point, we have either an expected or unexpected Master
+ // abort. There are three cases:
+ // 1. Expected MAB from a PCI config space read that must be handled
+ // 2. Unexpected MAB from a PCI memory or I/O space read in ISA legacy
+ // space that can be handled.
+ // 3. Unexpected MAB. Don't handle or fix up this error condition.
+ // (Really take the machine check.)
+ //
+
+ //
+ // Case 1: Expected Master Abort, e.g. a PCI configuration read error.
+ //
+
+ if ( (IodCapErr.Mab == 1) && ExpectedMchk ){
+
+ //
+ // Here's how a PCI config space read to an empty slot will transpire:
+ //
+ // READ_CONFIG_Usize indicates the issuing CPU and address in
+ // HalpMasterAbortExpected.Number and HalpMasterAbortExpected.Addr.
+ //
+ // PCI config space read will case a MC Bus FILL_ERROR on the issuing CPU
+ // FILL_ERROR causes a machine check.
+ //
+ // The targeted MC-PCI bus bridge will set CAP_ERR<MasterAbort> bit.
+ //
+ // So far, the error looks like a PCI configuration space read
+ // that accessed a device that does not exist. In order to fix
+ // this up we expect that the original faulting instruction must
+ // be a load with v0 as the destination register. Unfortunately,
+ // machine checks are not precise exceptions so we may have exectued
+ // many instructions since the faulting load. For EV5 a pair of
+ // memory barrier instructions following the load will stall the pipe
+ // waiting for load completion before the second memory barrier can
+ // be issued. Therefore, we expect the exception PC to point to either
+ // the load instruction or one of the two memory barriers. We will
+ // assume that if the exception pc is not an mb that instead it
+ // points to the load that machine checked. We must be careful to
+ // not reexectute the load.
+ //
+
+ ALPHA_INSTRUCTION FaultingInstruction;
+
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
+ if( FaultingInstruction.Memory.Opcode != MEMSPC_OP ){
+
+ //
+ // Exception pc does not point to a memory barrier, return
+ // to the instruction after the exception pc.
+ //
+
+ TrapFrame->Fir += 4;
+
+ }
+
+ //
+ // The error has matched all of our conditions. Fix it up by
+ // writing the value 0xffffffff into the destination of the load.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
+
+ //
+ // Clear all error conditions in CAP_ERR.
+ // (McAddrPerr, LostMcErr, Mab)
+ //
+#if 0
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapErr.all );
+#else
+ IodCapErrMask.all = ALL_CAP_ERRORS;
+ HalpClearAllIods( IodCapErrMask );
+#endif
+
+ //
+ // Clear the hard error interrupt.
+ // ecrfix - For now, the Hard error interrupt is masked, so
+ // we don't have to clear it.
+ //
+
+ return TRUE;
+
+ }
+#if 0
+ //
+ // Case 2: Uexpected Master Abort, e.g. a PCI memory or I/O space read to
+ // legacy ISA space (0 - 1 Mb) on PCI-1,2,3.
+ //
+
+ if ( bHandleIsaError( McDeviceId, IodCapErr) ) {
+ return TRUE;
+ }
+#endif
+ //
+ // Case 3: Unexpected Master abort.
+ // (Or anything I might have missed.... )
+ //
+
+#if (DBG) || (HALDBG)
+ DbgPrint( "Unexpected PCI master abort\n" );
+#endif
+
+ return ( bHandleFatalIodError(McDeviceId, TRUE) );
+
+}
+
+
+#define ENTIRE_FRAME_SIZE (sizeof(ERROR_FRAME) + sizeof(RAWHIDE_CORRECTABLE_FRAME))
+VOID
+HalpIodSoftErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle a IOD soft (correctable) error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN bfoundIod;
+ MC_DEVICE_ID McDeviceId;
+
+ static UCHAR Frame[ENTIRE_FRAME_SIZE];
+ static PERROR_FRAME pFrame;
+ static RAWHIDE_CORRECTABLE_FRAME RawhideFrame;
+ static BOOLEAN RawhideFrameInitialized = FALSE;
+
+ UCHAR TempFrame[ENTIRE_FRAME_SIZE];
+ PERROR_FRAME pTempFrame;
+ PCORRECTABLE_ERROR pCorr;
+ PRAWHIDE_CORRECTABLE_FRAME pRawCorr;
+
+ PBOOLEAN ErrorlogBusy;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+ PRAWHIDE_UNCORRECTABLE_FRAME rawerr;
+
+ IOD_CAP_ERR IodCapErr;
+ IOD_MDPA_STAT IodMdpaStat;
+ IOD_MDPA_STAT IodMdpbStat;
+ IOD_MC_ERR0 IodMcErr0;
+ IOD_MC_ERR1 IodMcErr1;
+
+ KIRQL Irql;
+
+#if 0 // CAP/MDP Bug
+ IOD_MDPA_SYN IodMdpaSyn;
+ IOD_MDPB_SYN IodMdpbSyn;
+#endif
+
+
+//ecrfix - later we should log the error, throttle the logging and turn off
+// correctable error reporting if the frequency is too high
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read/write. Read the error registers relevant
+ // to this error.
+ //
+
+ //
+ // Find the IOD that latched the error.
+ //
+
+ bfoundIod = bFindIodError( &McDeviceId, &IodCapErr );
+
+#ifdef FORCE_CORRECTABLE_ERROR
+ IodCapErr.all = 0x88000000;
+ bfoundIod = 1;
+#endif // FORCE_CORRECTABLE_ERROR
+
+ //
+ // Check that we found an IOD that has a valid PCI or MC error.
+ // If it is not this is a pretty weird (fatal???) condition.
+ // For now, we'll just go return TRUE.
+ //
+
+ if( !bfoundIod ) {
+
+#if 0 //HALDBG
+ DbgPrint( "HalpIodSoftErrorInterrupt: no PCI or MC error found.\n");
+#endif
+ return;
+ }
+
+ //
+ // Check if an error is latched into the IOD. If not, goodbye.
+ //
+
+ if( IodCapErr.McErrValid == 0 ){
+
+#if HALDBG
+ DbgPrint( "Iod soft error interrupt without valid MC error\n" );
+#endif //HALDBG
+
+ return;
+ }
+
+ //
+ // Check for the correctable error bit.
+ //
+
+ if( (IodCapErr.CrdA == 0) && (IodCapErr.CrdB == 0) ){
+
+#if HALDBG
+ DbgPrint( "Iod soft error interrupt without correctable error indicated in CapErr\n" );
+#endif //HALDBG
+
+ }
+
+
+ //
+ // Increment the number of IOD correctable errors.
+ //
+
+ IodCorrectedErrors += 1;
+
+ //
+ // Read the rest of the error registers
+ //
+
+ IodMcErr0.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->McErr0
+ );
+
+ IodMcErr1.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->McErr1
+ );
+#ifdef FORCE_CORRECTABLE_ERROR
+ IodMcErr0.all = 0x00bebad0;
+ IodMcErr1.all = 0x800f3f00;
+#endif // FORCE_CORRECTABLE_ERROR
+
+#if 0 // CAP/MDP Bug
+ IodMdpaStat.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpaStat
+ );
+
+ IodMdpaSyn.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpaSyn
+ );
+
+ IodMdpbStat.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpbStat
+ );
+
+ IodMdpbSyn.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpbSyn
+ );
+#endif
+
+
+#if HALDBG
+
+ //
+ // Print a correctable error message to the debugger.
+ //
+
+ DbgPrint( "IOD Correctable Error Number %d, state follows: \n",
+ IodCorrectedErrors );
+ DbgPrint( "\tIOD_CAP_ERR: 0x%x\n", IodCapErr.all );
+ DbgPrint( "\tIOD_MC_ERR0: 0x%x\n", IodMcErr0.all );
+ DbgPrint( "\tIOD_MC_ERR1: 0x%x\n", IodMcErr1.all );
+// DbgPrint( "\tIOD_MDPA_STAT: 0x%x\n", IodMdpaStat.all );
+// DbgPrint( "\tIOD_MDPA_SYN: 0x%x\n", IodMdpaSyn.all );
+// DbgPrint( "\tIOD_MDPB_STAT: 0x%x\n", IodMdpbStat.all );
+// DbgPrint( "\tIOD_MDPB_SYN: 0x%x\n", IodMdpbSyn.all );
+
+#endif //HALDBG
+
+ //
+ // Fill in the Correctable Error frame only if we've connected
+ // to the Correctable Error interrupt.
+ //
+
+ if (HalpLogCorrectableErrors) {
+
+ //
+ // Real error, get the interrupt object.
+ //
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[RawhideSoftErrVector];
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ pFrame = (PERROR_FRAME) Frame;
+ pTempFrame = (PERROR_FRAME) TempFrame;
+ pCorr = (PCORRECTABLE_ERROR) &pTempFrame->CorrectableFrame;
+ pRawCorr = (PRAWHIDE_CORRECTABLE_FRAME) (TempFrame +
+ sizeof(ERROR_FRAME) );
+
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, ENTIRE_FRAME_SIZE);
+
+ //
+ // Fill in the error frame information.
+ //
+
+ pTempFrame->Signature = ERROR_FRAME_SIGNATURE;
+ pTempFrame->LengthOfEntireErrorFrame = ENTIRE_FRAME_SIZE;
+ pTempFrame->FrameType = CorrectableFrame;
+ pTempFrame->VersionNumber = ERROR_FRAME_VERSION;
+ pTempFrame->SequenceNumber = IodCorrectedErrors;
+ pTempFrame->PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Check for lost error.
+ //
+
+ if( IodCapErr.LostMcErr ) {
+
+ //
+ // Since the error registers are locked from a previous error,
+ // we do not know where the error came from. Mark everything
+ // as UNIDENTIFIED.
+ //
+
+ pCorr->Flags.LostCorrectable = 1;
+ pCorr->Flags.LostAddressSpace = UNIDENTIFIED;
+ pCorr->Flags.LostMemoryErrorSource = UNIDENTIFIED;
+ }
+
+ pCorr->Flags.ErrorBitMasksValid = 0;
+
+ //
+ // Determine error type.
+ //
+
+ if (IodMcErr1.Addr39_32 & 0x80) {
+
+ //
+ // I/O ECC error occurred.
+ //
+
+ pCorr->Flags.AddressSpace = IO_SPACE;
+ pCorr->Flags.ExtendedErrorValid = 1;
+ pCorr->ErrorInformation.IoError.Interface = PCIBus;
+ pCorr->ErrorInformation.IoError.BusNumber = IodMcErr1.DevId & 0x3;
+
+ // We never alloc PCI address higher than 1 Gb for any PCI
+ // address space (sparse mem, dense mem, sparse I/O), so this
+ // trick works.
+
+ pCorr->ErrorInformation.IoError.BusAddress.LowPart =
+ ((IodMcErr0.Addr & 0x3FFFFFFF) >> IO_BIT_SHIFT);
+
+ // The code below is not strictly correct. Based on the MC Bus
+ // spec, p.32, we can roughly say that McCmd<3> tells us whether
+ // there was a write or read transaction on the bus. If I looked
+ // at the spec harder, I might be able to distinguish a PIO op
+ // from a DMA operation.
+
+ pCorr->ErrorInformation.IoError.TransferType
+ = ((IodMcErr1.McCmd & 0x8) ? BUS_IO_READ : BUS_IO_WRITE);
+
+ } else {
+
+ //
+ // Memory ECC error occurred.
+ //
+
+ pCorr->Flags.AddressSpace = MEMORY_SPACE;
+
+ }
+
+ //
+ // Get the physical address where the error occurred.
+ //
+
+ if (IodMcErr1.Valid) {
+ pCorr->Flags.PhysicalAddressValid = 1;
+ pCorr->PhysicalAddress =
+ ((ULONGLONG) (IodMcErr1.Addr39_32)) << 32;
+ pCorr->PhysicalAddress |= IodMcErr0.all;
+ }
+
+ //
+ // Scrub the error if it's any type of memory error.
+ //
+
+ if ( pCorr->Flags.AddressSpace == MEMORY_SPACE &&
+ pCorr->Flags.PhysicalAddressValid ) {
+ pCorr->Flags.ScrubError = 1;
+ }
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KeAcquireSpinLock(ErrorlogSpinLock, &Irql );
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ //
+
+ if (!*ErrorlogBusy) {
+
+ //
+ // Set reporting processor information. Disregard at the moment.
+ //
+
+ pCorr->Flags.ProcessorInformationValid = 0;
+
+ //
+ // Copy the SYSTEM_INFORMATION from the uncorrectable frame
+ //
+
+ pCorr->System = PUncorrectableError->UncorrectableFrame.System;
+
+ //
+ //
+ // Set raw system information flag.
+ //
+
+ pCorr->Flags.SystemInformationValid = 1;
+
+ //
+ // Do the Rawhide-specific stuff here
+ //
+
+ pRawCorr->Revision = RAWHIDE_CORRECTABLE_FRAME_REVISION;
+
+ //
+ // Copy the CUD header from the uncorrectable frame
+ //
+
+ rawerr = (PRAWHIDE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ if (rawerr) {
+ pRawCorr->CudHeader = rawerr->CudHeader;
+ }
+
+ //
+ // Fill in the rest of the dynamic portion of the
+ // correctable frame.
+ //
+
+ pRawCorr->CudHeader.ActiveCpus = BuildActiveCpus();
+ pRawCorr->ErrorSubpacketFlags.all = 0;
+ pRawCorr->ErrorSubpacketFlags.IodSubpacketPresent = 1;
+ pRawCorr->WhoAmI = HalpReadWhoAmI();
+ HalpBuildIodErrorFrame( McDeviceId, &(pRawCorr->IodErrorFrame) );
+
+ //
+ // Copy the information that we need to log.
+ //
+
+ RtlCopyMemory(&Frame,
+ &TempFrame,
+ ENTIRE_FRAME_SIZE);
+
+ pFrame->CorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)pFrame + sizeof(ERROR_FRAME) );
+
+ pFrame->CorrectableFrame.RawSystemInformationLength =
+ sizeof(RAWHIDE_CORRECTABLE_FRAME);
+
+
+ //
+ // Put frame into ISR service context.
+ //
+
+ *(PERROR_FRAME *)InterruptObject->ServiceContext = pFrame;
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ pFrame->CorrectableFrame.Flags.LostCorrectable = TRUE;
+ pFrame->CorrectableFrame.Flags.LostAddressSpace =
+ pTempFrame->CorrectableFrame.Flags.AddressSpace;
+ pFrame->CorrectableFrame.Flags.LostMemoryErrorSource =
+ pTempFrame->CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KeReleaseSpinLock(ErrorlogSpinLock, Irql );
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+ }
+
+
+
+ //
+ // Clear state in MDPA and MDPB before clearing CAP_ERR
+ //
+
+ IodCapErr.all = 0;
+ IodCapErr.CrdA = 1;
+ IodCapErr.CrdB = 1;
+ IodMdpaStat.all = 0xffffffff;
+ IodMdpbStat.all = 0xffffffff;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodMdpaStat.all
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodMdpbStat.all
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapErr.all
+ );
+
+ return;
+
+}
+
+VOID
+HalpIodHardErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle a IOD hard (uncorrectable) error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN bfoundIod;
+ MC_DEVICE_ID McDeviceId;
+ IOD_CAP_ERR IodCapErr;
+ IOD_WHOAMI IodWhoAmI;
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level.
+ // Prevents us from taking other hard error interrupts
+ // during this one.
+ //
+ // Also, acquire a spin lock to keep entry
+ // to this code serialized.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Find the IOD that latched the error.
+ //
+
+ bfoundIod = bFindIodError( &McDeviceId, &IodCapErr );
+
+ //
+ // Check that we found an IOD that has a valid PCI or MC error.
+ // If it is not this is a pretty weird (fatal???) condition.
+ // For now, we'll just return.
+ //
+
+ if( !bfoundIod ) {
+
+#if 0 // HALDBG
+ DbgPrint( "HalpIodHardErrorInterrupt: no PCI or MC error found.\n");
+#endif
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+ }
+
+#if 1 // ecrfix
+ //
+ // See if this was an ISA legacy space access
+ // on PCI-1,2,3. If so, dismiss this interrupt.
+ //
+
+ if ( bHandleIsaError( McDeviceId, IodCapErr) ) {
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+ }
+#endif
+
+#if HALDBG
+ DbgPrint( "Hard Error Found on IOD (%x, %x)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid );
+#endif //HALDBG
+
+ //
+ // Save IodWhoAmI
+ //
+
+ IodWhoAmI.all = HalpReadWhoAmI();
+ HalpIodWhoAmIOnError.all = IodWhoAmI.all;
+
+ //
+ // Handle the Fatal Error
+ //
+
+ bHandleFatalIodError( McDeviceId, FALSE );
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xbeadfeed, //ecrfix - quick error interrupt id
+ McDeviceId.all,
+ 0,
+ (ULONG) PUncorrectableError );
+
+
+}
+
+BOOLEAN
+bHandleFatalIodError(
+ MC_DEVICE_ID McDeviceId,
+ BOOLEAN bMachineCheck
+ )
+/*++
+
+Routine Description:
+
+ Handles the epilogue of a fatal IOD unccorrectable error
+ from either a machine check or IOD hard error interrupt.
+
+Arguments:
+
+ McDeviceId - IOD on which the error was found
+
+ bMachineCheck - TRUE if we're handling a fatal machine check
+ FALSE if we're handling a fatal hard error interrupt
+
+Return Value:
+
+ TRUE is returned if the IOD error has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+#if HALDBG
+ if (bMachineCheck ) {
+ DbgPrint( "Handling fatal error - machine check\n" );
+ } else {
+ DbgPrint( "Handling fatal error - hard error interrupt\n" );
+ }
+#endif
+
+ //
+ // Clear the error condition in the MCES register.
+ //
+ // ecrfix - the way this is written, this will be done on hard
+ // error interrupts too (where there has been *no* machine check).
+ // I hope it will be benign in this case....
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ //
+ // Proceed to display the error.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n" );
+
+#ifdef DUMPIODS
+ DumpAllIods(AllRegisters);
+#endif
+
+
+ HalpIodReportFatalError( McDeviceId );
+
+ return( FALSE );
+
+}
+
+BOOLEAN
+bFindIodError(
+ PMC_DEVICE_ID pMcDeviceId,
+ PIOD_CAP_ERR pIodCapErr
+)
+/*++
+
+Routine Description:
+
+ Determines which IOD has an error latched in it.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if an IOD was found with an error latched in CAP_ERR.
+ FALSE otherwise.
+
+--*/
+{
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+ IOD_CAP_ERR IodCapErr;
+
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+#if 0 // HALDBG
+ DbgPrint( "FindIodError: Searching: %d Iods: ", numIods);
+#endif // HALDBG
+
+ //
+ // Search each Iod and look for a PCI or McBus error.
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read the IOD error register to determine the source of the
+ // error.
+ //
+
+#if 0 //HALDBG
+ DbgPrint( "(%d, %d) ", mcCtx.McDeviceId.Gid, mcCtx.McDeviceId.Mid);
+#endif // HALDBG
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+ if( (IodCapErr.PciErrValid != 0) || (IodCapErr.McErrValid != 0) ){
+ break;
+ }
+ }
+
+#if 0 // HALDBG
+ if (bfoundIod) {
+ DbgPrint( "Found!\n");
+ } else {
+ DbgPrint( "Error Not Found!\n");
+ }
+#endif // HALDBG
+
+ //
+ // Return the McDeviceId and CapErr register contents
+ // of the first IOD that has an error.
+ //
+
+ *pMcDeviceId = mcCtx.McDeviceId;
+ pIodCapErr->all = IodCapErr.all;
+
+ return (bfoundIod);
+}
+
+BOOLEAN
+bHandleIsaError(
+ MC_DEVICE_ID McDeviceId,
+ IOD_CAP_ERR IodCapErrIn
+)
+/*++
+
+Routine Description:
+
+ Gives PCI-1,2,3 ISA legacy semantics for I/O and memory accesses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if the error was handled.
+ FALSE otherwise.
+
+--*/
+{
+
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceIdWithMab;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+ IOD_CAP_ERR IodCapErr;
+ IOD_CAP_ERR IodCapErrMask;
+
+
+ //
+ // Find an IOD that has Mab set. If we do not find one, then
+ // we don't have this error.
+ //
+
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Search each Iod and look for a PCI or McBus error.
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read the IOD error register to determine who has Mab set
+ //
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+ if( (IodCapErr.PciErrValid == 1) &&
+ (IodCapErr.Perr == 0) &&
+ (IodCapErr.Serr == 0) &&
+ (IodCapErr.Mab == 1) &&
+ (IodCapErr.PteInv == 0) ) {
+ break;
+ }
+ }
+
+ //
+ // If we didn't find an IOD with Mab set, then do not handle this error.
+ //
+
+ if (!bfoundIod) {
+ return FALSE;
+ }
+
+ //
+ // Save the McDevice Id of the offending IOD
+ //
+
+ McDeviceIdWithMab.all = mcCtx.McDeviceId.all;
+
+ //
+ // This must be on a bus other than PCI0 for us to handle this error
+ // (PCI0 reads to non-existent ISA addresses will be fixed by by the
+ // PCI-EISA bridge. Thus we'll never get here on PCI0 unless there
+ // really is an error.)
+ //
+
+ if ( McDeviceIdWithMab.Mid != MidPci0 ) {
+
+
+ IOD_PCI_ERR1 IodPciErr1;
+
+ //
+ // Get the PCI address of the transaction that caused the MAB
+ //
+
+ IodPciErr1.PciAddress =
+ (ULONG) READ_IOD_REGISTER_NEW( McDeviceIdWithMab,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1 );
+
+
+ //
+ // To be handled as an ISA legacy memory or I/O space read, the
+ // FaultingPciAddress must be in the range 0-1 Mb
+ //
+
+ if( IodPciErr1.PciAddress < __1MB ) {
+
+ //
+ // The error has matched all of our conditions. Assume that
+ // V0 has already been set to 0xffffffff. (This is a contract
+ // with the HAL access routines in iodio.s.)
+ //
+
+ IodCapErrMask.all = ALL_CAP_ERRORS;
+ HalpClearAllIods( IodCapErrMask );
+
+ return TRUE;
+
+ }
+
+#if HALDBG
+ DbgPrint( "Failed checking for legacy ISA read:\n");
+ DbgPrint( "PciErr1 : %08x\n", IodPciErr1.PciAddress );
+#endif //HALDBG
+
+ }
+
+ //
+ // We have a PCI Mab on PCI0. Do not handle this error.
+ //
+
+ return FALSE;
+
+ }
+
+VOID
+HalpErrorFrameString(
+ PUNCORRECTABLE_ERROR uncorr,
+ PUCHAR OutBuffer
+ )
+/*++
+
+Routine Description:
+
+ Append an Error message to the Uncorrectable Error Frame
+ string
+
+Arguments:
+
+ uncorr - Pointer to the UNCORRECTABLE_ERROR frame.
+
+ OutBuffer - message to be appended.
+ (If null, no string is appended, and pCurrentString
+ is reset to NULL).
+
+
+Return Value:
+
+ none.
+
+--*/
+{
+ ULONG len;
+ static PCHAR pCurrentString = NULL;
+
+ //
+ // If OutBuffer is NULL, reset pointer and flag
+ //
+
+ if (OutBuffer == NULL) {
+ pCurrentString = NULL;
+ if (uncorr) uncorr->Flags.ErrorStringValid = 0;
+ return;
+ }
+
+ //
+ // Uncorrectable frame valid?
+ //
+
+ if (uncorr) {
+
+ //
+ // On first error message:
+ // * Init pCurrentString to beginning of ErrorString
+ // * Set valid flag
+ //
+
+ if (pCurrentString == NULL) {
+ pCurrentString = uncorr->ErrorString;
+ uncorr->Flags.ErrorStringValid = 1;
+ }
+
+ //
+ // Append OutBuffer to ErrorString
+ //
+
+ len = strlen(OutBuffer);
+ strncpy(pCurrentString,
+ OutBuffer,
+ len);
+
+ //
+ // Zero-terminate the error string.
+ //
+
+ pCurrentString += len;
+ *pCurrentString = 0;
+
+ }
+}
+
+ULONG
+BuildActiveCpus (
+ VOID
+ )
+{
+ ULONG ActiveLogicalProcessors = HalpActiveProcessors;
+ ULONG ActivePhysicalCpus = 0;
+ ULONG i;
+
+ //
+ // Make a physical processor mask from the logical processor mask
+ //
+
+ for (i = 0; i < HalpNumberOfCpus; i++, ActiveLogicalProcessors >> 1) {
+ if (ActiveLogicalProcessors & 0x1) {
+ ActivePhysicalCpus |= (1 << (ULONG) (MCDEVID_TO_PHYS_CPU(
+ HalpLogicalToPhysicalProcessor[i].all)));
+ }
+ }
+
+ return (ActivePhysicalCpus);
+
+}
diff --git a/private/ntos/nthals/halraw/alpha/iodio.s b/private/ntos/nthals/halraw/alpha/iodio.s
new file mode 100644
index 000000000..6edc5f9d0
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iodio.s
@@ -0,0 +1,2997 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ iodio.s
+
+Abstract:
+
+ This module implements the I/O access routines for the IOD
+ (CAP/MDP) ASICs.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+
+Author:
+
+ Eric Rehm 10-Apr-1995
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "halalpha.h"
+#include "iod.h"
+
+
+//
+// Superpage VAs
+//
+// The following constants are used to construct the physical addresses
+// used to access i/o space.
+//
+// assembler BUGBUG:
+//
+// The following values are hacks to get around the intelligent
+// Alpha assemblers. Instead of sign extending 16 bit quantities greater
+// than 32K-1, the assembler generates a ldah/lda pair to load exactly
+// the sixteen bit quantity specified, without sign extending.
+//
+// By specifying the quantity as a negative number, the assembler allows
+// a single lda instruction, with sign extension.
+//
+
+
+//
+// ecrfix - these definitions are good for PCI 0 (GID = 7, MID = 4) ONLY!!!
+//
+
+
+#define IOD_SPARSE_MEM_SVA -0x3080 // negative of 0xcf80
+#define IOD_DENSE_MEM_SVA -0x3070 // negative of 0xcf90
+#define IOD_SPARSE_IO_SVA -0x3068 // negative of 0xcf98
+#define IOD_REGISTER_SVA -0x3062 // negative of 0xcf9E
+
+//
+// These definitions are based on GID=0, MID=0 and can be used
+// to construct an superpage address for any (GID, MID).
+//
+
+#define IOD_PCI0_REGISTER_SVA -0x3062 // negative of 0xcf9E
+#define IOD_REGISTER_NEW_SVA -0x3800 // negative of 0xc800
+#define IOD_IP_INTR_SVA -0x37ff // negative of 0xc801 (to CUD only)
+#define IOD_INTTIM_SVA -0x37f0 // negative of 0xc810 (to CUD only)
+#define IOD_IP_ACK_SVA -0x37ef // negative of 0xc811 (to CUD only)
+#define IOD_MCHK_ACK_SVA -0x37ee // negative of 0xc812 (to CUD only)
+#define IOD_HALT_ACK_SVA -0x37e9 // negative of 0xc817 (to CUD only)
+#define IOD_PCI_CONFIG_SVA -0x37e4 // negative of 0xc81C
+#define IOD_INT_ACK_SVA -0x37e1 // negative of 0xc81F
+
+#define IOD_TARGET0_OFFSET 0x3f00
+#define IOD_TARGET1_OFFSET 0x3f40
+
+#define MabNumber 0 // offset of HalpMasterAbortExpected.Number
+#define MabAddr 8 // offset of HalpMasterAbortExpected.Addr
+#define MASTER_ABORT_NOT_EXPECTED 0xffffffff
+
+#define GET_PROCESSOR_CONTROL_BLOCK_BASE \
+ call_pal rdpcr; \
+ ldl v0, PcPrcb(v0)
+
+
+ SBTTL( "Return PCR address for current processor" )
+//++
+//
+// PVOID
+// HalpRdPcr(
+// )
+//
+// Routine Description:
+//
+// Calls PAL to obtain PCR for current processor
+//
+// Arguments:
+//
+// None
+//
+// Return Value:
+//
+// v0 - Address of PCR
+//
+//--
+
+ LEAF_ENTRY(HalpRdPcr)
+
+
+ call_pal rdpcr; // CallPal to read PCR
+ ret zero, (ra) // return
+
+ .end HalpRdPcr
+
+
+
+ SBTTL( "Read byte from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, 3, t3 // capture byte offset
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ bis zero, 0xffffffff,v0 // ecrfix
+ mb // ensure all writes are visible
+ ldl v0, 0(t0) // read from dense space
+ extbl v0, t3, v0 // extract appropriate byte
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_UCHAR
+
+
+
+ SBTTL( "Read byte from PCI sparse i/o" )
+//++
+//
+// UCHAR
+// READ_PORT_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff cf98 0000
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_UCHAR
+
+
+ SBTTL( "Read short from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a short location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory short to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI memory.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extwl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, 3, t3 // capture byte offset
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // read from dense space
+ extwl v0, t3, v0 // extract appropriate word
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_USHORT
+
+
+ SBTTL( "Read short from PCI sparse I/O" )
+//++
+//
+// UCHAR
+// READ_PORT_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a short location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the i/o short to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI I/O.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extwl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_USHORT
+
+
+ SBTTL( "Read long from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a long location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory long to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI memory.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to long
+
+ mb // ensure all writes are visible
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, (t0) // get the longword
+#if 0 //mdbfix support Canonical ULONG form
+ extll v0, 0, v0 // if NXM, make exception more precise
+#endif
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // read from dense space
+#if 0 //mdbfix support Canonical ULONG form
+ extll v0, 0, v0 // if NXM, make exception more precise
+#endif
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_ULONG
+
+
+ SBTTL( "Read long from PCI sparse I/O" )
+//++
+//
+// UCHAR
+// READ_PORT_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a long location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the i/o long to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI I/O.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to short
+
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_ULONG
+
+
+ SBTTL( "Write byte to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ insbl a1, t3, v0 // insert to proper byte lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+
+ ldl t1, (t0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+
+
+ insbl a1, t3, a1 // insert to appropriate byte lane
+ bis a1, t1, a1 // merge byte in result
+ stl a1, (t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write byte to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_UCHAR(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ insbl a1, t3, v0 // insert to proper byte lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_UCHAR
+
+
+ SBTTL( "Write short to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory short to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+
+ inswl a1, t3, v0 // insert to proper short lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ bis t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ ldl t1, (t0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, a1 // insert to appropriate short lane
+ bis a1, t1, a1 // merge in result
+ stl a1, (t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write short to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_USHORT(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+
+ inswl a1, t3, v0 // insert to proper short lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_USHORT
+
+
+
+ SBTTL( "Write long to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a long to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory long to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to long
+
+ stl a1, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ stl a1, 0(t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_ULONG
+
+
+ SBTTL( "Write long to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_ULONG(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a long to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O long to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to long
+
+ stl a1, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_ULONG
+
+
+ SBTTL( "Write IOD Register" )
+//++
+//
+// VOID
+// WRITE_IOD_REGISTER(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Write an IOD control register.
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Value(a1) - Longword value to be written to the control register.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. Since the physical address of the IOD CSRS exceed the 34 bit
+// capacity of the QVAs, the QVA values of the IOD CSRS specify
+// the offset of the QVAs from the IOD CSR base address (89.e000.0000)
+//--
+
+ LEAF_ENTRY(WRITE_IOD_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_GRU_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, IOD_REGISTER_SVA(zero) // 0xffff ffff ffff cf9e
+ sll t4, 28, t4 // 0xffff fcf9 e000 0000
+ or t0, t4, t0 // superpage mode
+ stl a1, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end WRITE_IOD_REGISTER
+
+
+ SBTTL( "Read IOD Register" )
+//++
+//
+// ULONG
+// READ_IOD_REGISTER(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Read an IOD Control register
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Return Value:
+//
+// v0 - Return the value read from the control register.
+//
+//--
+
+ LEAF_ENTRY(READ_IOD_REGISTER)
+
+//
+// Generate the superpage address of the requested IOD register.
+//
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 20f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, IOD_REGISTER_SVA(zero) // 0xffff ffff ffff cf9e
+ sll t4, 28, t4 // 0xffff fcf9 e000 0000
+ or t0, t4, t0 // superpage mode
+
+//
+// Perform the read of the requested IOD register and return.
+//
+
+ ldl v0, (t0) // read the register
+
+ ret zero, (ra) // return
+
+//
+// The requested IOD register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+20: // flag bad QVAs
+ BREAK_DEBUG_STOP // take a breakpoint
+
+ ret zero, (ra) // return
+
+ .end READ_IOD_REGISTER
+
+
+ SBTTL( "Write IOD Register_New" )
+//++
+//
+// VOID
+// WRITE_IOD_REGISTER_NEW(
+// IN ULONG McDevid
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Write a IOD control register.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of this IOD
+//
+// RegisterQva(a1) - Qva of control register to be written.
+// N.B. RegisterQva *does not* specifiy which IOD to write to.
+// That's why we pass in McDevid
+//
+// Value(a2) - Longword value to be written to the control register.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_IOD_REGISTER_NEW)
+
+//
+// Generate the superpage address of the requested IOD register.
+//
+
+ // Args are actually byte values:
+ and a1, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a1, 0xf0, a1 // clear <63:32>
+ bic a1, QVA_ENABLE, a1 // clear QVA fields so shift is correct
+ sll a1, IO_BIT_SHIFT, t4 // shift RegisterOffset into position
+
+ extbl a0, zero, a0 // McDevId
+
+ lda t0, IOD_REGISTER_NEW_SVA(zero) // 0xffff ffff ffff c800
+ sll a0, 5, t1 // shift McDevId into position
+ bis t0, t1, t0 // create SVA for this IOD
+ sll t0, 28, t0 // 0xffff fcXX 0000 0000
+
+ or t0, t4, t0 // superpage mode
+ stl a2, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+//
+// The requested IOD register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end WRITE_IOD_REGISTER_NEW
+
+
+ SBTTL( "Read IOD Register_NEW" )
+//++
+//
+// ULONG
+// READ_IOD_REGISTER_NEW(
+// IN ULONG McDevid
+// IN ULONG RegisterOffset
+// )
+//
+// Routine Description:
+//
+// Read an IOD Control register
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of this IOD.
+//
+// RegisterQva(a1) - QVA of control register to be read.
+//
+// Return Value:
+//
+// v0 - Return the value read from the control register.
+//
+//--
+
+ LEAF_ENTRY(READ_IOD_REGISTER_NEW)
+
+//
+// Generate the superpage address of the requested IOD register.
+//
+
+ and a1, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a1, 0xf0, a1 // clear <63:32>
+ bic a1, QVA_ENABLE, a1 // clear QVA fields so shift is correct
+ sll a1, IO_BIT_SHIFT, t4 // shift RegisterQva into position
+
+ extbl a0, zero, a0 // McDevId
+
+ lda t0, IOD_REGISTER_NEW_SVA(zero) // 0xffff ffff ffff c800
+ sll a0, 5, t1 // shift McDevId into position
+ bis t0, t1, t0 // create SVA for this IOD
+ sll t0, 28, t0 // 0xffff fcXX 0000 0000
+
+ or t0, t4, t0 // superpage mode
+
+//
+// Perform the read of the requested IOD register and return.
+//
+
+ ldl v0, (t0) // read the register
+
+ ret zero, (ra) // return
+
+//
+// The requested IOD register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end READ_IOD_REGISTER_NEW
+
+
+ SBTTL( "Read Buffer from Port Space in Uchars")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push the write off the chip
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push write off the chip
+ addl a1, 4, a1 // increment buffer
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ bis zero, 0xffffffff,t1 // ecrfix
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ bis zero, 0xffffffff,t2 // ecrfix
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ ldil t7, 1 // DENSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ ldil t7, 0 // SPARSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 11f // if not DENSE goto 11f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 12f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+11:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+12:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 51f // if not DENSE goto 51f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 52f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+51:
+ stl t1, 0(t0) // store to buffer
+52:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 81f // if not DENSE goto 81f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 82f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+81:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+82:
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 121f // if not DENSE goto 122f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 122f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+121:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+122:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+#if 0 //ecrfix
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved McDevid
+CfgA1: .space 8 // saved BusNumber
+CfgA2: .space 8 // saved SlotNumber
+CfgA3: .space 8 // saved Offset
+CfgA4: .space 8 // padding for 16 byte alignment
+CfgFrameLength:
+
+#endif
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ LEAF_ENTRY( READ_CONFIG_UCHAR )
+
+//
+// Set the flag indicating the number of the processor upon which a PCI master abort
+// may be expected by the machine check handler.
+//
+
+#if !defined(AXP_FIRMWARE)
+ GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = prcb base address
+ ldl t0, PbNumber(v0) // capture current processor number
+#else
+ bis zero,zero,t0 // Force processor zero in fw
+#endif
+ extbl t0, 0, t0 // PbNumber is of type CCHAR
+ lda t4, HalpMasterAbortExpected // get address of flag
+ stl t0, MabNumber(t4) // save current processor number
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture byte lane
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_BYTE_LEN, t7 // or in the byte enables
+ stq t7, MabAddr(t4) // save current access address
+
+ .set noreorder // cannot reorder these instructions
+
+ mb // order the writes
+ ldl v0, (t7) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+ extbl v0, t3, v0 // return byte from requested lane
+
+ .set reorder // reordering can begin again
+
+ lda t5, MASTER_ABORT_NOT_EXPECTED(zero)
+ stl t5, MabNumber(t4) // "clear" flag
+
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write an unsigned byte to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ LEAF_ENTRY( WRITE_CONFIG_UCHAR )
+
+//
+// Perform the write to configuration space
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture byte lane
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_BYTE_LEN, t7 // or in the byte enables
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t7) // write the configuration byte
+ mb // synchronize
+
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a short from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ LEAF_ENTRY( READ_CONFIG_USHORT )
+
+//
+// Set the flag indicating the number of the processor upon which a PCI master abort
+// may be expected by the machine check handler.
+//
+
+#if !defined(AXP_FIRMWARE)
+ GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = prcb base address
+ ldl t0, PbNumber(v0) // capture current processor number
+#else
+ bis zero,zero,t0 // Force processor zero in fw
+#endif
+ extbl t0, 0, t0 // PbNumber is of type CCHAR
+ lda t4, HalpMasterAbortExpected // get address of flag
+ stl t0, MabNumber(t4) // save current processor number
+
+//
+// Perform the read from configuration space.
+//
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture word offset
+ zapnot a0, 0x7,a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_WORD_LEN, t7 // or in the byte enables
+ stq t7, MabAddr(t4) // save current access address
+
+ .set noreorder // cannot reorder these instructions
+
+ mb // order the write
+ ldl v0, (t7) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+ extwl v0, t3, v0 // return word from requested lanes
+
+ .set reorder // reordering can begin again
+
+ lda t5, MASTER_ABORT_NOT_EXPECTED(zero)
+ stl t5, MabNumber(t4) // "clear" flag
+
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ LEAF_ENTRY( WRITE_CONFIG_USHORT )
+
+//
+// Perform the write to configuration space.
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture word offset
+ zapnot a0, 0x7,a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_WORD_LEN, t7 // or in the byte enables
+
+ inswl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t7) // write the configuration byte
+ mb // synchronize
+
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ LEAF_ENTRY( READ_CONFIG_ULONG )
+
+//
+// Set the flag indicating the number of the processor upon which a PCI master abort
+// may be expected by the machine check handler.
+//
+
+#if !defined(AXP_FIRMWARE)
+ GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = prcb base address
+ ldl t0, PbNumber(v0) // capture current processor number
+#else
+ bis zero,zero,t0 // Force processor zero in fw
+#endif
+ extbl t0, 0, t0 // PbNumber is of type CCHAR
+ lda t4, HalpMasterAbortExpected // get address of flag
+ stl t0, MabNumber(t4) // save current processor number
+
+//
+// Perform the read from configuration space.
+//
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_LONG_LEN, t7 // or in the byte enables
+ stq t7, MabAddr(t4) // save current access address
+
+ .set noreorder // cannot reorder these instructions
+
+ mb // order the writes
+ ldl v0, (t7) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+
+ .set reorder // reordering can begin again
+
+ lda t5, MASTER_ABORT_NOT_EXPECTED(zero)
+ stl t5, MabNumber(t4) // "clear" flag
+
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ LEAF_ENTRY( WRITE_CONFIG_ULONG )
+
+//
+// Perform the write to configuration space.
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_LONG_LEN, t7 // or in the byte enables
+
+ stl a1, (t7) // write the longword
+ mb // synchronize
+
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
+
+//++
+//
+// ULONG
+// INTERRUPT_ACKNOWLEDGE(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Perform an interrupt acknowledge cycle on PCI bus 0
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// (v0) Returns the vector returned by the interrupt acknowledge
+// read.
+//
+//--
+
+
+ LEAF_ENTRY( INTERRUPT_ACKNOWLEDGE )
+
+ lda t0, IOD_PCI0_REGISTER_SVA(zero) // 0xffff ffff ffff cf9e
+ sll t0, 28, t0 // 0xffff fcf9 e000 0000
+ lda t0, 0x480(t0) // 0xffff fcf9 e000 0480
+
+ ldl v0, 0(t0) // perform PCI0 IACK, get vector
+
+ ret zero, (ra) // return
+
+ .end INTERRUPT_ACKNOWLEDGE
+
+ SBTTL( "IOD Interrupt Acknowledge" )
+//++
+//
+// VOID
+// IOD_INTERRUPT_ACKNOWEDGE
+// IN ULONG McDeviceId,
+// IN ULONG Target
+// )
+//
+// Routine Description:
+//
+// Perform an IOD interrupt acknowledge to the selected
+// interrupt target.
+//
+// Arguments:
+//
+// McDeviceId(a0) - MC Bus Device ID of the IOD to acknowledge
+//
+// Target(a1) - Which one of two interrupt targets generated
+// the interrupt. Must be 0 or 1.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(IOD_INTERRUPT_ACKNOWLEDGE)
+
+//
+// Generate the superpage address of the requested IOD INT_ACK register
+//
+ mb
+
+ extbl a0, zero, a0 // McDevId
+
+ sll a1, 6, a1 // Which target?
+ lda t4, IOD_TARGET0_OFFSET // If target = 0, offset = 0x3f00
+ bis a1, t4, t4 // If target = 1, offset = 0x3f40
+
+ lda t0, IOD_INT_ACK_SVA(zero) //0xffff ffff ffff c81f
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc81 f000 0000
+ sll t0, 28, t0 // 0xffff fcXX f000 0000
+
+ or t0, t4, t0 // 0xffff fcXX f000 3f00/3f40
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end IOD_INTERRUPT_ACKNOWLEDGE
+
+
+ SBTTL( "CPU Clock Interrupt Acknowledge" )
+//++
+//
+// VOID
+// CPU_CLOCK_ACKNOWEDGE
+// IN ULONG McDeviceId
+// )
+//
+// Routine Description:
+//
+// Perform an clock (interval timer) interrupt acknowledge to the
+// selected CPU.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of the CPU to acknowledge.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(CPU_CLOCK_ACKNOWLEDGE)
+
+//
+// Generate the superpage address of the requested CUD's INTTIM_ACK register
+//
+
+
+ extbl a0, zero, a0 // McDeviceId
+
+ lda t0, IOD_INTTIM_SVA(zero) //0xffff ffff ffff c810
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc81 0000 0000
+ sll t0, 28, t0 // 0xffff fcXX 0000 0000
+
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end CPU_CLOCK_ACKNOWLEDGE
+
+
+
+ SBTTL( "Interprocessor Interrupt Request" )
+//++
+//
+// VOID
+// IP_INTERRUPT_REQUEST
+// IN ULONG McDeviceId
+// )
+//
+// Routine Description:
+//
+// Perform an inteprocessor interrupt request to the
+// selected CPU.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of the CPU to send an IPI request.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(IP_INTERRUPT_REQUEST)
+
+//
+// Generate the superpage address of the requested CUD's IP_INTR register
+//
+
+
+ extbl a0, zero, a0 // McDeviceId
+
+ lda t0, IOD_IP_INTR_SVA(zero) // 0xffff ffff ffff c801
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc80 1000 0000
+ sll t0, 28, t0 // 0xffff fcXX 1000 0000
+
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end IP_INTERRUPT_REQUEST
+
+
+ SBTTL( "Interprocessor Interrupt Acknowledge" )
+//++
+//
+// VOID
+// IP_INTERRUPT_ACKNOWEDGE
+// IN ULONG McDeviceId
+// )
+//
+// Routine Description:
+//
+// Perform an inteprocessor interrupt acknowledge to the
+// selected CPU.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of the CPU to send an IPI acknowledge.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(IP_INTERRUPT_ACKNOWLEDGE)
+
+//
+// Generate the superpage address of the requested CUD's IP_ACK register
+//
+
+
+ extbl a0, zero, a0 // McDeviceId
+
+ lda t0, IOD_IP_ACK_SVA(zero) // 0xffff ffff ffff c811
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc81 1000 0000
+ sll t0, 28, t0 // 0xffff fcXX 1000 0000
+
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end IP_INTERRUPT_ACKNOWLEDGE
diff --git a/private/ntos/nthals/halraw/alpha/iodmapio.c b/private/ntos/nthals/halraw/alpha/iodmapio.c
new file mode 100644
index 000000000..2970fb955
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iodmapio.c
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ iodmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on IOD-based systems.
+
+Author:
+
+ Eric Rehm 26-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "isaaddr.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpPciIrQva;
+PVOID HalpPciImrQva;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for an IOD-based system using
+ the Quasi VA mechanism.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+// PciIoSpaceBase = HAL_MAKE_QVA( IOD_PCI0_SPARSE_IO_PHYSICAL );
+
+ //
+ // IoSpace Base for PCI 0 is a bus address 0.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_IOD_SPARSE_QVA( 0, 0 );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+
+// ecrfix - not needed? HalpEisaIntAckBase = HAL_MAKE_IOD_SPARSE_QVA(0, 0);
+
+ //
+ // Map CMOS RAM address.
+ //
+
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // COM ports are on PCI bus 0.
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_IOD_SPARSE_QVA( 0, 0 ) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
+
+
diff --git a/private/ntos/nthals/halraw/alpha/ioproc.c b/private/ntos/nthals/halraw/alpha/ioproc.c
new file mode 100644
index 000000000..8789e513c
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ioproc.c
@@ -0,0 +1,75 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halraw/alpha/iousage.c b/private/ntos/nthals/halraw/alpha/iousage.c
new file mode 100644
index 000000000..6ac8f6f4e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iousage.c
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/halraw/alpha/iousage.h b/private/ntos/nthals/halraw/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/halraw/alpha/machdep.h b/private/ntos/nthals/halraw/alpha/machdep.h
new file mode 100644
index 000000000..d45f00988
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993,1995 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Rawhide platform-specific definitions.
+//
+
+#include "rawhide.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halraw/alpha/memory.c b/private/ntos/nthals/halraw/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/nvenv.c b/private/ntos/nthals/halraw/alpha/nvenv.c
new file mode 100644
index 000000000..8a8dfdeb5
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/nvenv.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\nvenv.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/nvram.c b/private/ntos/nthals/halraw/alpha/nvram.c
new file mode 100644
index 000000000..6fd93ab46
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/nvram.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\nvram.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pcibus.c b/private/ntos/nthals/halraw/alpha/pcibus.c
new file mode 100644
index 000000000..80a22247b
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcibus.c
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+ Eric Rehm 6-June-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+
+extern ULONG PCIMaxBus;
+
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ PPCIPBUSDATA BusData;
+ BOOLEAN BusIsAcrossPPB;
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Get the flag that tells use whether this is
+ // a root bus or not.
+ //
+
+ BusIsAcrossPPB = BusData->BusIsAcrossPPB;
+
+ //
+ // Valid Config cycles for Bus # < PCIMaxBus
+ //
+ // Then, Type 1 config cycles only when bus is across
+ // a PPB.
+ //
+
+ if (BusNumber < PCIMaxBus) {
+ ConfigType = PciConfigType0;
+ if (BusIsAcrossPPB == TRUE)
+ {
+ ConfigType = PciConfigType1;
+ }
+ } else {
+ ConfigType = PciConfigTypeInvalid;
+ }
+
+#if HALDBG
+ DbgPrint("BusNumber %d BusIsAcrossPPB %d ConfigType %d\n",
+ BusNumber, BusIsAcrossPPB, ConfigType);
+#endif
+
+ return ConfigType;
+
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+ MC_DEVICE_ID McDevid;
+ ULONG BusNumber = BusHandler->BusNumber;
+ PPCIPBUSDATA BusData;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+#if HALDBG
+
+ DbgPrint( "PCI Config Access: Bus = %d, Device = %d, BusIsAcrossPPB %d ConfigType = %d\n",
+ BusNumber, Slot.u.bits.DeviceNumber, BusData->BusIsAcrossPPB, ConfigType );
+
+#endif //HALDBG
+
+ //
+ // From the root bus number (a.k.a. HwBusNumber), get
+ // the MC_DEVICE_ID of the IOD that we're attempting to access.
+ //
+
+ McDevid = HalpIodLogicalToPhysical[BusData->HwBusNumber];
+
+ //
+ // If this is an access to an PCI device on a root bus,
+ // then we want to generate a Type 0 config cycle. To do this
+ // on Rawhide, you must set BusNumber to zero.
+ //
+ // We know that an access is destined to a root bus when
+ // when the bus being accessed is *not* across a PPB.
+ //
+
+ if (BusData->BusIsAcrossPPB == FALSE) {
+ BusNumber = 0;
+ }
+
+
+ //
+ // Initialize PciAddr for a PCI type 1 configuration cycle
+ //
+
+ pPciAddr->u.AsULONG = McDevid.all << 24;
+ pPciAddr->u.bits1.BusNumber = BusNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1; // don't care!
+
+
+ return;
+}
diff --git a/private/ntos/nthals/halraw/alpha/pciesc.c b/private/ntos/nthals/halraw/alpha/pciesc.c
new file mode 100644
index 000000000..ef14f3c15
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pciesc.c
@@ -0,0 +1,489 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pciesc.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI ESC's
+ cascaded 82c59 programmable interrupt controllers.
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from pcisio.c module for Intel 82374EB (ESC).
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// Import save area for ESC interrupt mask registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+BOOLEAN
+HalpInitializeEisaInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 82c59 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must be initialized with 4
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word sets the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0, which is the default
+ // edge-sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ return (TRUE);
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is for controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2; it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+ }
+ }
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second-level
+ interrupt dispatch routine and acknowledge the interrupt at the ESC
+ controller.
+
+ This service routine could be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, ISA_LEVEL, ISA_LEVEL, ISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR EISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ EISAVector = HalpAcknowledgeEisaInterrupt(ServiceContext);
+
+
+ if ((EISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return FALSE; // ecrfix - now returns a value
+
+ }
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = EISAVector + EISA_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Dismiss the interrupt in the ESC interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (EISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+}
diff --git a/private/ntos/nthals/halraw/alpha/pcisup.c b/private/ntos/nthals/halraw/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pcrtc.c b/private/ntos/nthals/halraw/alpha/pcrtc.c
new file mode 100644
index 000000000..b5006ddf7
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcrtc.c
@@ -0,0 +1,383 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ pcrtc.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ the standard pc-compatible real time clock use on Alpha AXP systems.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+ Jeff McLeman (mcleman) 3-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 13-Jul-1992 Jeff McLeman
+ use VTI access routines to access clock
+
+ 3-June-1992 Jeff McLeman
+ Adapt this module into a Jensen specific module
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+
+//
+// Local function prototypes.
+//
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ );
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+#ifdef AXP_FIRMWARE
+
+//
+// Put these functions in the discardable text section.
+//
+
+#pragma alloc_text(DISTEXT, HalQueryRealTimeClock )
+#pragma alloc_text(DISTEXT, HalSetRealTimeClock )
+#pragma alloc_text(DISTEXT, HalpReadClockRegister )
+#pragma alloc_text(DISTEXT, HalpWriteClockRegister )
+
+#endif // AXP_FIRMWARE
+
+//
+// Define globals used to map the realtime clock address and data ports.
+//
+
+PVOID HalpRtcAddressPort = NULL;
+PVOID HalpRtcDataPort = NULL;
+
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Status;
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ Status = TRUE;
+
+ } else {
+ Status = FALSE;
+ }
+
+ KeLowerIrql(OldIrql);
+ return(Status);
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ UCHAR DataByte;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+
+#ifdef RTC_SQE
+
+ //
+ // If the platform requires it, make sure that the Square
+ // Wave output of the RTC is turned on.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1;
+
+#endif //RTC_SQE
+
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ // (Make sure periodic interrupt is enabled)
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Read the realtime clock register value.
+ //
+
+ WRITE_PORT_UCHAR( HalpRtcAddressPort, Register );
+
+ return READ_PORT_UCHAR( HalpRtcDataPort );
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_PORT_UCHAR( HalpRtcAddressPort, Register );
+
+ WRITE_PORT_UCHAR( HalpRtcDataPort, Value );
+
+ return;
+}
+
+
+#if 0 // ecrfix - should not be in this common routine!!!!
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+ On Sable the periodic interrupt comes from the square ware output of
+ the Dallas 1489A RTC on the Standard I/O board. Each processor
+ receives this clock phase shifted by at least 90 degrees from all
+ other processors. The periodic interrupt from the RTC is not used and
+ thus doesn't need to be enabled or acknowledged. Each processor has
+ its own clock interrupt latch that is cleared locally. This routine is
+ not used for Sable platforms.
+
+ Because of the phase shifting among the processors, the clock is
+ half the rate given to the RTC. So, the RTC is programmed twice
+ as fast as on a system that takes the RTC periodic interrupt in
+ directly.
+
+Arguments:
+
+ RateSelect - Supplies rate select to be placed in the clock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Set the new rate
+ //
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->RateSelect = (UCHAR)RateSelect;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->TimebaseDivisor = RTC_TIMEBASE_DIVISOR;
+ HalpWriteClockRegister( RTC_CONTROL_REGISTERA, DataByte );
+
+ //
+ // Set the correct mode
+ //
+ DataByte = 0;
+#if defined(RTC_SQE)
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1;
+#else
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+#endif
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ HalpWriteClockRegister( RTC_CONTROL_REGISTERB, DataByte );
+}
+#endif
diff --git a/private/ntos/nthals/halraw/alpha/pcserial.c b/private/ntos/nthals/halraw/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pcspeakr.c b/private/ntos/nthals/halraw/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/perf8254.c b/private/ntos/nthals/halraw/alpha/perf8254.c
new file mode 100644
index 000000000..5fade7e42
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/perf8254.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perf8254.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pintolin.h b/private/ntos/nthals/halraw/alpha/pintolin.h
new file mode 100644
index 000000000..44cc02593
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pintolin.h
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+ Steve Brooks 6-July 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for Rawhide.
+//
+// Alcor PCI interrupts are mapped to arbitrary interrupt numbers
+// in the table below. The values are a 1-1 map of the bit numbers
+// in the Alcor PCI interrupt register that are connected to PCI
+// devices. N.B.: there are two other interrupts in this register,
+// but they are not connected to I/O devices, so they're not
+// represented in the table.
+//
+// Limit init table to 5 entries, which is the
+// MAX_PCI_LOCAL_DEVICE.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 5 = PCI_AD[16].
+//
+// ecrfix - I don't do this, but I might....
+// N.B. - Have biased the bus interrupt vectors/levels for PCI to start
+// at 0x11 so they are disjoint from EISA levels
+//
+
+//
+// Offset the pin-to-line entries by an offset of 0x20 so interrupt
+// vectors reported by WinXXX will be unique.
+//
+
+enum _RAWHIDE_PIN_TO_LINE {
+ RawhideNcr810PinToLine = (RawhidePinToLineOffset + 0x11)
+};
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG RawhidePCIPinToLineTable[][4]=
+{
+ //
+ // Virtual Slot 0 = PCI_AD[11]
+ //
+
+ { 0xff, // Pin 1
+ 0xff, // Pin 2
+ 0xff, // Pin 3
+ 0xff }, // Pin 4
+
+ //
+ // Virtual Slot 1 = PCI_AD[12] EISA/NCR810
+ //
+
+ { RawhidePinToLineOffset + 0x11, // Pin 1
+ 0xff, // Pin 2
+ 0xff, // Pin 3
+ 0xff }, // Pin 4
+
+ //
+ // Virtual Slot 2 = PCI_AD[13] Slot #0
+ //
+
+ { RawhidePinToLineOffset + 0x01, // Pin 1
+ RawhidePinToLineOffset + 0x02, // Pin 2
+ RawhidePinToLineOffset + 0x03, // Pin 3
+ RawhidePinToLineOffset + 0x04 },// Pin 4
+
+ //
+ // Virtual Slot 3 = PCI_AD[14] Slot #1
+ //
+
+ { RawhidePinToLineOffset + 0x05, // Pin 1
+ RawhidePinToLineOffset + 0x06, // Pin 2
+ RawhidePinToLineOffset + 0x07, // Pin 3
+ RawhidePinToLineOffset + 0x08 },// Pin 4
+
+ //
+ // Virtual Slot 4 = PCI_AD[15] Slot #2
+ //
+
+ { RawhidePinToLineOffset + 0x09, // Pin 1
+ RawhidePinToLineOffset + 0x0a, // Pin 2
+ RawhidePinToLineOffset + 0x0b, // Pin 3
+ RawhidePinToLineOffset + 0x0c },// Pin 4
+
+ //
+ // Virtual Slot 5 = PCI_AD[16] Slot #3
+ //
+
+ { RawhidePinToLineOffset + 0x0d, // Pin 1
+ RawhidePinToLineOffset + 0x0e, // Pin 2
+ RawhidePinToLineOffset + 0x0f, // Pin 3
+ RawhidePinToLineOffset + 0x10 } // Pin 4
+};
+
diff --git a/private/ntos/nthals/halraw/alpha/rawerr.c b/private/ntos/nthals/halraw/alpha/rawerr.c
new file mode 100644
index 000000000..b30d9b19e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rawerr.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rawerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Rawhide platform.
+
+Author:
+
+ Eric Rehm 13-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+//
+// Declare the extern variables.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+VOID
+HalpCacheErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for a Rawhide machine check interrupt
+ The function calls HalpIodReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+ MC_DEVICE_ID McDeviceId;
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // If this is a IOD uncorrectable error then report the error and
+ // crash the system.
+ //
+
+ if( HalpIodUncorrectableError( &McDeviceId ) == TRUE ){
+
+ HalpIodReportFatalError( McDeviceId);
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ McDeviceId.all,
+ 0,
+ (ULONG) PUncorrectableError );
+
+ }
+
+ //
+ // It was not a IOD uncorrectable error, therefore this must be an
+ // NMI interrupt.
+ //
+
+ HalHandleNMI( NULL, NULL );
+
+ return; // never
+
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the IOD chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+ //
+ // All machine check handling on Rawhide is determined by the IOD.
+ //
+
+ return( HalpIodMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ) );
+
+}
diff --git a/private/ntos/nthals/halraw/alpha/rawerror.h b/private/ntos/nthals/halraw/alpha/rawerror.h
new file mode 100644
index 000000000..dd2d38787
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rawerror.h
@@ -0,0 +1,301 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rawerror.h
+
+Abstract:
+
+ This file defines the structures and definitions of correctable and
+ uncorrectable Rawhide error frames, as well as various optional
+ subpackets, snapshots, and frames.
+
+Author:
+
+ Eric Rehm 20-June-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RAWERRORH_
+#define _RAWERRORH_
+
+//
+// Error Frame Revision definitions.
+//
+
+#define UNCORRECTABLE_REVISION_1 (0)
+#define UNCORRECTABLE_REVISION_2 (1)
+#define CORRECTABLE_FRAME_REVISION_1 (0)
+#define CORRECTABLE_FRAME_REVISION_2 (1)
+
+
+//
+// CPU Daughter Card (CUD) Header
+//
+
+// #pragma pack(1)
+typedef struct _CUD_HEADER { // As Per Rawhide SPM
+ ULONG Reserved0[4]; // (0x00-0x0c)
+ ULONG ActiveCpus; // (0x10)
+ ULONG Reserved1; // (0x14)
+ UCHAR SystemSN[10]; // (0x18-0x21) Same as FRU System Serial Number
+ UCHAR Reserved2[6]; // (0x22-0x27)
+ UCHAR ProcessorSN[10]; // (0x28-0x31) Module (processor) S/N, if available
+ USHORT ModType; // (0x32)
+ ULONG Reserved3; // (0x34)
+ ULONG DisabledResources; // (0x38)
+ ULONG SystemRev; // (0x3c) Same as FRY System Revision Level?
+} CUD_HEADER, *PCUD_HEADER;
+
+
+
+//
+// IOD Error Frame
+//
+// N.B. Used in Uncorrectable *and* correctable error frames for
+// information on the IOD that recevied the machine check.
+// It is uses as well in MC Bus snapshot (for each IOD) and Iod Register
+// Subpacket.
+// As far as I'm concerned, they IOD information is the same in each case.
+// We can use the ValidBits field to optionally disable irrelevant
+// fields.
+//
+
+typedef struct _IOD_ERROR_FRAME {
+ ULONGLONG IodBaseAddr; // (0x00)
+ ULONG WhoAmI; // (0x08) - (Reserved in Rawhide SPM)
+ ULONG ValidBits; // (0x0c)
+ ULONG PciRev; // (0x10)
+ ULONG CapCtrl; // (0x14)
+ ULONG HaeMem; // (0x18)
+ ULONG HaeIo; // (0x1c)
+ ULONG IntCtrl; // (0x20)
+ ULONG IntReq; // (0x24)
+ ULONG IntMask0; // (0x28)
+ ULONG IntMask1; // (0x2c)
+ ULONG McErr0; // (0x30)
+ ULONG McErr1; // (0x34)
+ ULONG CapErr; // (0x38)
+ ULONG Reserved0; // (0x3c)
+ ULONG PciErr1; // (0x40)
+ ULONG MdpaStat; // (0x44)
+ ULONG MdpaSyn; // (0x48)
+ ULONG MdpbStat; // (0x4c)
+ ULONG MdpbSyn; // (0x50)
+ ULONG Reserved1[3]; // (0x54-0x5f)
+} IOD_ERROR_FRAME, *PIOD_ERROR_FRAME;
+
+//
+// IOD Error Frame Valid Bits
+//
+// Corresponds to bitfields of ValidBits in the Iod Error Frame
+//
+
+typedef union _IOD_ERROR_FRAME_VALID_BITS {
+ struct {
+ ULONG IodBaseAddrValid: 1; // <0>
+ ULONG WhoAmIValid: 1; // <1>
+ ULONG PciRevValid: 1; // <2>
+ ULONG CapCtrlValid: 1; // <3>
+ ULONG HaeMemValid: 1; // <4>
+ ULONG HaeIoValid: 1; // <5>
+ ULONG IntCtrlValid: 1; // <6>
+ ULONG IntReqValid: 1; // <7>
+ ULONG IntMask0Valid: 1; // <8>
+ ULONG IntMask1Valid: 1; // <9>
+ ULONG McErr0Valid: 1; // <10>
+ ULONG McErr1Valid: 1; // <11>
+ ULONG CapErrValid: 1; // <12>
+ ULONG PciErr1Valid: 1; // <13>
+ ULONG MdpaStatValid: 1; // <14>
+ ULONG MdpaSynValid: 1; // <15>
+ ULONG MdpbStatValid: 1; // <16>
+ ULONG MdpbSynValid: 1; // <17>
+ };
+ ULONG all;
+} IOD_ERROR_FRAME_VALID_BITS, *PIOD_ERROR_FRAME_VALID_BITS;
+
+//
+// Optional Snapshots for which headers or frames are defined below:
+// PCI Bus Snapshot
+// MC Bus Snapshot
+// Memory Size Frame
+// System Managment Frame
+// ESC Frame
+//
+
+//
+// Flags indicating which of the optional snapshots or frames are present
+// in a correctable or uncorrectable error frame
+//
+
+typedef union _ERROR_SUBPACKET_FLAGS {
+ struct {
+ ULONGLONG Reserved0: 10; // <0:9> Reserved
+ ULONGLONG SysEnvPresent : 1; // <10>
+ ULONGLONG MemSizePreset : 1; // <11>
+ ULONGLONG Reserved1: 8; // <12:19> Reserved
+ ULONGLONG McBusPresent: 1; // <20>
+ ULONGLONG GcdBusPresent: 1; // <21>
+ ULONGLONG Reserved2: 8; // <22:29> Reserved
+ ULONGLONG IodSubpacketPresent: 1; // <30>
+ ULONGLONG PciSnapshotPresent: 1; // <31>
+ ULONGLONG EscSubpacketPresent: 1; // <32>
+ ULONGLONG Reserved3: 7; // <33:39> Reserved
+ ULONGLONG Iod2SubpacketPresent: 1; // <40> ???
+ ULONGLONG Pci2SnapshotPresent: 1; // <41> ???
+ };
+ ULONGLONG all;
+} ERROR_SUBPACKET_FLAGS, *PERROR_SUBPACKET_FLAGS;
+
+
+//
+// PCI Bus Snapshot Header
+//
+// Header is followed PCI_COMMON_CONFIG packets (256 bytes each) for each PCI
+// device present in the system. Therefore,
+// Length = sizeof (PCI_BUS_SNAPSHOT) + NumberOfNodes*sizeof(PCI_COMMON_CONFIG)
+//
+// N.B. PCI_COMMON_CONFIG is defined \nt\private\ntos\inc\pci.h
+//
+
+
+typedef struct _PCI_BUS_SNAPSHOT {
+ ULONG Length; // (0x00)
+ USHORT BusNumber; // (0x04)
+ USHORT NumberOfNodes; // (0x06)
+ //
+ // NumberOfNodes packets follow (0x08)
+ //
+} PCI_BUS_SNAPSHOT, *PPCI_BUS_SNAPSHOT;
+
+
+
+//
+// MC Bus Snapshot Header
+//
+// Header is followed a IOD_ERROR_FRAME for each IOD on the system;
+// Therefore,
+// Length = sizeof (MC_BUS_SNAPSHOT) + NumberOfIods*sizeof(IOD_ERROR_FRAME)
+//
+
+typedef struct _MC_BUS_SNAPSHOT {
+ ULONG Length; // (0x00)
+ ULONG NumberOfIods; // (0x04)
+ ULONGLONG ReportingCpuBaseAddr; // (0x08)
+ //
+ // NumberOfIods packets follow (0x10)
+ //
+} MC_BUS_SNAPSHOT, *PMC_BUS_SNAPSHOT;
+
+
+//
+// Memory Size Frame
+//
+
+typedef struct _MEMORY_SIZE_FRAME {
+ ULONGLONG MemorySize; // (0x00)
+} MEMORY_SIZE_FRAME, *PMEMORY_SIZE_FRAME;
+
+typedef union _MEMORY_SIZE {
+ struct {
+ ULONGLONG MemorySize0: 8; // <0:7>
+ ULONGLONG MemorySize1: 8; // <8:15>
+ ULONGLONG MemorySize2: 8; // <16:23>
+ ULONGLONG MemorySize3: 8; // <24:31>
+ ULONGLONG Reserved: 24; // <32:55>
+ ULONGLONG MemorySize0Valid: 1; // <56>
+ ULONGLONG MemorySize1Valid: 1; // <57>
+ ULONGLONG MemorySize2Valid: 1; // <58>
+ ULONGLONG MemorySize3Valid: 1; // <59>
+ };
+ ULONGLONG all;
+} MEMORY_SIZE, *PMEMORY_SIZE;
+
+
+//
+// System Managment Frame
+//
+
+typedef struct _SYSTEM_MANAGEMENT_FRAME {
+ ULONGLONG SystemEnvironment; // (0x00)
+ ULONG Elcr2; // (0x08) (see IOD_ELCR2 in iod.h)
+ ULONG Reserved0; // (0x0c)
+} SYSTEM_MANAGEMENT_FRAME, *PSYSTEM_MANAGEMENT_FRAME;
+
+typedef union _SYSTEM_ENVIRONMENT {
+ struct {
+ ULONGLONG FanFailReg: 8; // <0:7> I2C Fain Fail Register
+ ULONGLONG SensorReg1: 8; // <8:15> I2C Sensor Register 1
+ ULONGLONG OpcControl: 8; // <16:23> I2C OPC Control
+ ULONGLONG SensorReg2: 8; // <24:31> I2C Sensor Register 2
+ ULONGLONG Reserved: 24; // <32:55> I2C Sensor Register 1
+ ULONGLONG FanFailValid: 1; // <56>
+ ULONGLONG SensorReg1Valid: 1; // <57>
+ ULONGLONG OpcControlValid: 1; // <58>
+ ULONGLONG SensorReg2Valid: 1; // <59>
+ };
+ ULONGLONG all;
+} SYSTEM_ENVIRONMENT, *PSYSTEM_ENVIRONMENT;
+
+
+//
+// ESC Frame
+//
+// This isn't just and ESC frame. EISA Id information is also contained herein.
+//
+// N.B. "index" refers to an indexed config ESC register accessed at index/data
+// ports 0x22/0x23.
+//
+
+
+typedef struct _ESC_FRAME {
+ UCHAR Id[4]; // (0x00) "ESC\0"
+ ULONG ByteCount; // (0x04) ???
+ UCHAR EscId; // (0x08) ESC ID Register (index 0x02)
+ UCHAR Filler0[7]; // (0x09-0x0f)
+ UCHAR Rid; // (0x0c) Revision Id (index 0x08)
+ UCHAR Filler1[3]; // (0x0d-0x0f)
+ UCHAR ModeSel; // (0x10) Mode Select Reg (index 0x40)
+ UCHAR Filler2[3]; // (0x11-0x13)
+ UCHAR EisaId[4]; // (0x14-0x17) EisaId of devices in EISA Slots
+ UCHAR SgRba; // (0x18) S-G Reloate Base Addr Reg (index 57)
+ UCHAR Filler3[3]; // (0x19-0x1b)
+ UCHAR Pirq[4]; // (0x1c-0x1f) PIRQ Route Ctrl (index 0x60-0x63)
+ UCHAR NmiSc; // (0x20) NMI Status & Ctrl (port 0x61)
+ UCHAR Filler4[3]; // (0x21-0x23)
+ UCHAR NmiEsc; // (0x24) NMI Ext. Status & Ctrl (port 0x461)
+ UCHAR Filler5[3]; // (0x25-0x27)
+ UCHAR LEisaMg; // (0x28) Last EISA Master Granted (port 0x464)
+ UCHAR Filler6[3]; // (0x29-0x2b)
+} ESC_FRAME, *PESC_FRAME;
+
+
+//
+// Rawhide Uncorrectable (Hard) Error Frame
+// Rawhide Correctable (Soft) Error Frame
+//
+
+typedef union _RAWHIDE_CORRECTABLE_FRAME {
+ ULONG Revision; // (0x00)
+ ULONG Reserved0; // (0x04)
+ ULONGLONG ErrorSubpacketFlags; // (0x08)
+ CUD_HEADER CudHeader; // (0x10-0x4f)
+ IOD_ERROR_FRAME IodErrorFrame; // (0x50-0xaf)
+ //
+ // Optional Error Subpackets // (0xb0)
+ // as per ErrorSubpackFlags
+ //
+} RAWHIDE_CORRECTABLE_FRAME, *PRAWHIDE_CORRECTABLE_FRAME,
+ RAWHIDE_UNCORRECTABLE_FRAME, *PRAWHIDE_UNCORRECTABLE_FRAME;
+
+#endif // _RAWERRORH_
diff --git a/private/ntos/nthals/halraw/alpha/rawhide.h b/private/ntos/nthals/halraw/alpha/rawhide.h
new file mode 100644
index 000000000..9d237a01e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rawhide.h
@@ -0,0 +1,349 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rawhide.h
+
+Abstract:
+
+ This file contains definitions specific to the Rawhide platform
+
+Author:
+
+ Eric Rehm 16-Feb-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RAWHIDEH_
+#define _RAWHIDEH_
+
+//
+// Include definitions for the components that make up Alcor.
+//
+
+#include "axp21164.h" // 21164 (EV5) microprocessor definitions
+#include "stdarg.h" // VarArgs support
+#include "iod.h" // CAP/MDP controller definitions
+#include "rwintbal.h" // Interrupt Balancing definitions
+#include "rwref.h" // Interrupt Vector Layout
+#include "bitmap.h" // Local copy of RTL bitmap routines
+
+#define CACHE_BLOCK_SIZE 0x40 // 64 byte cache line size
+
+//
+// Define number of PCI, EISA, and combo slots
+//
+// ecrfix - this is only good for PCI0
+//
+
+#define NUMBER_EISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 4
+#define NUMBER_COMBO_SLOTS 1
+
+//
+// Define the data and csr ports for the I2C bus and OCP.
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x530
+#define I2C_INTERFACE_CSR_PORT 0x531
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+//
+// Define the index and data ports for the NS Super IO chip.
+//
+
+#define SUPERIO_INDEX_PORT 0x398
+#define SUPERIO_DATA_PORT 0x399
+#define SUPERIO_PORT_LENGTH 0x2
+
+//
+// Define the csr ports for Rawhide-specific Reset and Flash control
+//
+
+#define RAWHIDE_RESET_PORT 0x26
+#define RAWHIDE_FLASH_CONTROL_PORT 0x27
+
+//
+// PCI bus address values:
+//
+
+#define PCI_MAX_LOCAL_DEVICE 5
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+//
+// PCI bus interrupt vector base value
+//
+
+#define RawhidePinToLineOffset 0x20
+
+//
+// Define the platform processor id type
+//
+
+typedef MC_DEVICE_ID HALP_PROCESSOR_ID, *PHALP_PROCESSOR_ID;
+
+extern HALP_PROCESSOR_ID HalpLogicalToPhysicalProcessor[];
+
+//
+// Define numbers and names of cpus.
+//
+
+#define RAWHIDE_PRIMARY_PROCESSOR ((ULONG) 0x0)
+#define RAWHIDE_MAXIMUM_PROCESSOR ((ULONG) 0x3)
+
+#define HAL_PRIMARY_PROCESSOR (RAWHIDE_PRIMARY_PROCESSOR)
+#define HAL_MAXIMUM_PROCESSOR (RAWHIDE_MAXIMUM_PROCESSOR)
+
+//
+// Define maximum number of MC-PCI bus bridges
+//
+
+#define RAWHIDE_MAXIMUM_PCI_BUS ((ULONG) 0x10)
+
+//
+// NCR810 SCSI device on PCI bus 1
+//
+
+#define RAWHIDE_SCSI_PCI_BUS ((ULONG) 0x01)
+
+//
+// Define default processor frequency.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (250)
+
+//
+// Define Rawhide-specific routines that are really macros for performance.
+//
+
+#define HalpAcknowledgeEisaInterrupt(x) (UCHAR) (INTERRUPT_ACKNOWLEDGE(x))
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+//
+// Define the per-processor data structures allocated in the PCR.
+//
+
+typedef struct _RAWHIDE_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONGLONG IpirSva; // Superpage VA of per-perocessor IPIR CSR
+ PVOID CpuCsrsQva; // Qva of per-cpu csrs
+ EV5ProfileCount ProfileCount; // Profile counter state
+ PIOD_POSTED_INTERRUPT PostedInterrupts; // per-cpu area in vector table
+ } RAWHIDE_PCR, *PRAWHIDE_PCR;
+
+#define HAL_PCR ( (PRAWHIDE_PCR)(&(PCR->HalReserved)) )
+
+//
+// Rawhide Memory information.
+//
+
+typedef enum _RAWHIDE_MEMORY_TYPE {
+ RawhideMemoryFree, // Good memory
+ RawhideMemoryHole, // Hole memory
+ RawhideMemoryBad, // Bad memory
+ RawhideMemoryMaximum
+} RAWHIDE_MEMORY_TYPE;
+
+
+typedef struct _RAWHIDE_MEMORY_DESCRIPTOR {
+ RAWHIDE_MEMORY_TYPE MemoryType; // From above
+ ULONG BasePage; // Base page number
+ ULONG PageCount; // Number of pages in this descriptor
+ ULONG bTested; // TRUE if memory has been tested
+} RAWHIDE_MEMORY_DESCRIPTOR, *PRAWHIDE_MEMORY_DESCRIPTOR;
+
+
+//
+// Rawhide Resource Configuration Subpackets
+//
+// N.B. Only the System Platform Configuration Subpacket is defined
+//
+
+//
+// Echo data structure constructed for SRM FRU table
+//
+// N.B. Minimum value length is 4.
+//
+
+#define TAG_INVALID 0
+#define TAG_ISO_LATIN1 1
+#define TAG_QUOTED 2
+#define TAG_BINARY 3
+#define TAG_UNICODE 4
+#define TAG_RESERVED 5
+
+typedef struct _TLV {
+ USHORT Tag; // Code describing data type of field
+ USHORT Length; // Length of Value field in bytes (>=4)
+ ULONG Value; // Beginning of data
+} TLV, *PTLV;
+
+//
+// System Platform Configuration Subpacket
+//
+
+#define SYSTEM_CONFIGURATION_SUBPACKET_CLASS 1
+#define SYSTEM_PLATFORM_SUBPACKET_TYPE 1
+
+//
+// System Platform Configuration Subpacket
+// (As per Russ McManus Config & FRU Table doc, but no Environement Variables.)
+//
+// N.B., the length of this subpacket is variable due to TLV type fields.
+// Total length of the subpacket is available in the Length field.
+//
+// Any field that is invalid will have TLV.Tag = 0.
+//
+
+#if 0
+typedef struct _RAWHIDE_SYSTEM_CONFIGURATION {
+ USHORT Length; // (0x00) Total length of subpacket
+ USHORT Class; // (0x02) Subpacket class
+ USHORT Type; // (0x04) Subpacket type
+ USHORT Reserved; // (0x06)
+ TLV SystemManufacturer; // (0x08) System Manufacturer (string)
+ TLV SystemModel; // (....) Model Name (string)
+ TLV SystemSerialNumber; // (....) SystemSerialNumber (string)
+ TLV SystemRevisionLevel; // (....) SystemRevisionLevel (string)
+ TLV SystemVariation; // (....) SystemVariation
+ TLV ConsoleTypeRev; // (....) SRM Console Rev (string)
+} RAWHIDE_SYSTEM_CONFIGURATION, *PRAWHIDE_SYSTEM_CONFIGURATION;
+#endif
+
+//
+// System Platform Configuration Subpacket
+//
+// (If you prefer something simpler....)
+
+typedef struct _RAWHIDE_SYSTEM_CONFIGURATION {
+ ULONG ValidBits; // (0x00) Valid fields below
+ UCHAR SystemManufacturer[80]; // (0x04) System Manufacturer (string)
+ UCHAR SystemModel[80]; // (0x54) Model Name (string)
+ UCHAR SystemSerialNumber[16]; // (0xA4) SystemSerialNumber (string)
+ UCHAR SystemRevisionLevel[4]; // (0xB4) SystemRevisionLevel (string)
+ UCHAR SystemVariation[80]; // (0xB8) SystemVariation
+ UCHAR ConsoleTypeRev[80]; // (0x108) SRM Console Rev (string)
+} RAWHIDE_SYSTEM_CONFIGURATION, *PRAWHIDE_SYSTEM_CONFIGURATION;
+
+typedef union _RAWHIDE_SYSTEM_CONFIG_VALID_BITS {
+ struct {
+ ULONG SystemManufacturerValid: 1; // <0>
+ ULONG SystemModelValid: 1; // <1>
+ ULONG SystemSerialNumberValid: 1; // <2>
+ ULONG SystemRevisionLevel: 1; // <3>
+ ULONG SystemVariationValid: 1; // <4>
+ ULONG ConsoleTypeRevValid: 1; // <5>
+ };
+ ULONG all;
+} RAWHIDE_SYSTEM_CONFIG_VALID_BITS, *PRAWHIDE_SYSTEM_CONFIG_VALID_BITS;
+
+
+//
+// Define up to 64 Rawhide flags.
+//
+
+typedef union _RAWHIDE_FLAGS {
+ struct {
+ ULONGLONG CpuMaskValid: 1; // <0>
+ ULONGLONG GcdMaskValid: 1; // <1>
+ ULONGLONG IodMaskValid: 1; // <2>
+ ULONGLONG SystemConfigValid: 1; // <3>
+ ULONGLONG MemoryDescriptorValid: 1; // <4>
+ };
+ ULONGLONG all;
+} RAWHIDE_FLAGS, *PRAWHIDE_FLAGS;
+
+//
+// Define data structure for Rawhide machine dependent data
+//
+
+typedef struct _RAWHIDE_SYSTEM_CLASS_DATA {
+ ULONG Length; // (0x00) Length of Rawhide spec. data
+ ULONG Version; // (0x04) Initially 0x1
+ RAWHIDE_FLAGS Flags; // (0x08)
+ ULONGLONG CpuMask; // (0x10) <GID*8+MID> set if CPU presnt
+ ULONGLONG GcdMask; // (0x18) <GID*8+MID> set if GCD presnt
+ ULONGLONG IodMask; // (0x20) <GID*8+MID> set if IOD presnt
+ RAWHIDE_SYSTEM_CONFIGURATION SystemConfig; // (0x28) System config info
+ ULONG MemoryDescriptorCount; // (...)Number of memory descriptors
+ RAWHIDE_MEMORY_DESCRIPTOR MemoryDescriptor[1]; // (...) Array of descriptors
+} RAWHIDE_SYSTEM_CLASS_DATA, *PRAWHIDE_SYSTEM_CLASS_DATA;
+
+//
+// Rawhide interval timer data structure
+//
+
+typedef struct _CLOCK_TABLE {
+ ULONG RollOver;
+ ULONG TimeIncr;
+} CLOCK_TABLE, *PCLOCK_TABLE;
+
+#define NUM_CLOCK_RATES 4
+#define MAXIMUM_CLOCK_INCREMENT (NUM_CLOCK_RATES)
+#define MINIMUM_CLOCK_INCREMENT 1
+
+//
+// Rawhide interrupt routine prototypes.
+//
+
+BOOLEAN
+HalpAcknowledgeRawhideClockInterrupt(
+ VOID
+ );
+
+ULONG
+HalpGetRawhidePciInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetRawhideEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetRawhideInternalInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpInitializeProcessorMapping(
+ IN ULONG LogicalProcessor,
+ IN ULONG PhysicalProcessor,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpInitializeSystemClassData(
+ ULONG Phase,
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
+
+#endif //_RAWHIDEH_
diff --git a/private/ntos/nthals/halraw/alpha/rwclock.c b/private/ntos/nthals/halraw/alpha/rwclock.c
new file mode 100644
index 000000000..69a27aa27
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwclock.c
@@ -0,0 +1,308 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwclock.c
+
+Abstract:
+
+ This module implements the code necessary to field and process the
+ interval clock interrupt.
+
+
+Author:
+
+ Eric Rehm 1-Dec-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG HalpNextRateSelect;
+
+ULONG HalpCurrentRollOver[RAWHIDE_MAXIMUM_PROCESSOR+1];
+ULONG HalpNextRollOver;
+
+//
+// The Rawhide Interval Timer has an accuracy of 100 ppm:
+// Nominal: 833.3333 us
+// Min: 833.41668 us
+// Max: 833.25001 us
+//
+// The following clock table values indicated the number of actual
+// clock interrupts we should take before we tell the system the time
+// has changed (a.k.a "RollOver count"). Each RollOver count has
+// and associated time increment = INT(RollOver * 833.3333 * 10)
+// that is in units of 100 us.
+//
+// RollOver Time Nominal Error
+// Count Increment MS (ms/day)
+
+CLOCK_TABLE
+HalpRollOverTable[NUM_CLOCK_RATES] =
+ { {2, 16667}, // 1.667 ms
+ {3, 25000}, // 2.5 ms +0.864
+ {6, 50000}, // 5.0 ms +1.728
+ {9, 75000} // 7.5 ms +2.592
+
+// {12, 100000}, // 10.0 ms +3.456
+// {15, 125000}, // 12.5 ms +4.320
+// {18, 150000} // 15.0 ms +5.184
+// debug {1, 8334} // .8333 ms +287.7
+
+ };
+
+BOOLEAN
+HalpAcknowledgeRawhideClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Rawhide comes from an onboard oscillator, divided down
+ by the processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_ID McDeviceId;
+ PKPRCB Prcb;
+
+
+ //
+ // Avoid a WhoAmI register read by using the PCR
+ //
+
+ Prcb = PCR->Prcb;
+ McDeviceId.all = HalpLogicalToPhysicalProcessor[Prcb->Number].all;
+
+ //
+ // Acknownledge the clock interrupt by writing to our own
+ // clock interrupt acknowledge.
+ //
+
+ CPU_CLOCK_ACKNOWLEDGE( McDeviceId );
+
+ //
+ // Has the roll-over counter expired for this processor's clock?
+ //
+
+ if ( (--HalpCurrentRollOver[Prcb->Number]) == 0 ) {
+
+ //
+ // Yes. Reset count to latest RollOver count and
+ // tell caller to do something.
+ //
+
+ HalpCurrentRollOver[Prcb->Number] = HalpNextRollOver;
+ return TRUE;
+ }
+
+ //
+ // No. Tell caller to do nothing.
+ //
+
+ return FALSE;
+
+
+}
+
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt routine to change the hearbeat timer rate when a call
+ to HalSetTimeIncrement has been made in the previous time slice.
+
+Arguments:
+
+ RateSelect - Supplies rate select to be placed in the clock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // Set the new rate via the global "next" roll-over count.
+ //
+ // When each processor's private roll-over counter
+ // (HalpCurrentRollOver[i]) expires, it will be reset to the
+ // this global "next" roll-over count;
+ //
+
+#if HALDBG
+ DbgPrint( "HalpProgramIntervalTimer: Set to new rate %d, RollOver %d\n",
+ RateSelect,
+ HalpRollOverTable[RateSelect-1].RollOver );
+#endif // HALDBG
+
+ HalpNextRollOver = HalpRollOverTable[RateSelect-1].RollOver;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV5
+ based machine via a call into the kernel. This routine is
+ only called by the primary processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG i;
+
+ //
+ // Set the time increment value.
+ //
+
+
+ HalpCurrentTimeIncrement
+ = HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].TimeIncr;
+
+
+ for (i = 0; i <= RAWHIDE_MAXIMUM_PROCESSOR; i++) {
+ HalpCurrentRollOver[i] =
+ HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].RollOver;
+ }
+
+ HalpNextRollOver =
+ HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].RollOver;
+
+ HalpNextRateSelect = 0;
+
+ KeSetTimeIncrement( HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].TimeIncr,
+ HalpRollOverTable[MINIMUM_CLOCK_INCREMENT-1].TimeIncr);
+
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ ULONG rate;
+ ULONG BestIndex;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+
+ for (rate = 1; rate < NUM_CLOCK_RATES; rate++) {
+ if (DesiredIncrement < HalpRollOverTable[rate].TimeIncr) {
+ break;
+ }
+ }
+
+ BestIndex = rate - 1;
+
+#if HALDBG
+ DbgPrint(
+ "HalSetTimeIncrement: Desired %d, BestIndex: %d TimeIncr %d RollOver %d \n",
+ DesiredIncrement,
+ BestIndex,
+ HalpRollOverTable[BestIndex].TimeIncr,
+ HalpRollOverTable[BestIndex].RollOver
+ );
+#endif // HALDBG
+
+ //
+ // Set the new time increment and the rate select (RollOverTable index)
+ // that will be used on the next tick of each processor's "soft"
+ // clock counter (HalpCurrentRollOver[i]).
+ //
+
+ HalpNewTimeIncrement = HalpRollOverTable[BestIndex].TimeIncr;
+ HalpNextRateSelect = BestIndex + 1;
+
+
+ KeLowerIrql(OldIrql);
+
+ return HalpNewTimeIncrement;
+
+}
+
+
+
+
diff --git a/private/ntos/nthals/halraw/alpha/rwinitnt.c b/private/ntos/nthals/halraw/alpha/rwinitnt.c
new file mode 100644
index 000000000..3ea569e93
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwinitnt.c
@@ -0,0 +1,1324 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ a Rawhide system.
+
+Author:
+
+ Eric Rehm 4-May-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+#include "iousage.h"
+#include "stdio.h"
+
+// Includes for Error Logging
+
+#include "fwcallbk.h" // To get firmware revisions
+#include <ntverp.h> // To O/S build number
+#include "errframe.h" // Error Frame Definitions
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+extern IOD_REGISTER_CLASS DumpIodFlag;
+
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpFamilyName = "AlphaServer";
+PCHAR HalpProductName = "4000";
+ULONG HalpProcessorNumber = 5;
+
+#define MAX_INIT_MSG (80)
+
+PRAWHIDE_SYSTEM_CLASS_DATA HalpSystemClassData;
+ULONG HalpNumberOfIods;
+ULONG HalpNumberOfCpus;
+
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+//
+// Define external references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeRawhideInterrupts (
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ );
+
+#if HALDBG
+VOID
+HalpDumpSystemClassData(
+ PRAWHIDE_SYSTEM_CLASS_DATA SystemClassData
+);
+#endif // HALDBG
+
+
+//
+// Irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - interval clock
+// irql 6 - not used
+// irql 7 - error, mchk, nmi, performance counters
+//
+//
+
+//
+// The hardware interrupt pins are used as follows for Rawhide
+//
+// IRQ0 = Reserved (unused)
+// IRQ1 = IOD Interrupts (PCI, ESC, and CAP interrupts)
+// IRQ2 = Interval Clock
+// IRQ3 = IP Interrupt
+// SYS_MCH_CHK_IRQ = Duplicate TAG parity error (cached CUD only)
+// MCH_HLT_IRQ = Halt button or CPU halt
+//
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alcor system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern VOID HalpCacheErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+#if !defined(NT_UP)
+ extern VOID HalpIpiInterruptHandler();
+#endif //NT_UP
+ extern ULONG HalpHaltInterrupt();
+ PKPRCB Prcb;
+ ULONG Vector;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize interrupt handling for the primary processor and
+ // any system-wide interrupt initialization.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Primary Processor\n");
+#endif // HALDBG
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init Processor Params\n");
+#endif // HALDBG
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Program Interval Timer\n");
+#endif // HALDBG
+ HalpProgramIntervalTimer(MAXIMUM_CLOCK_INCREMENT);
+
+ //
+ // Initialize Rawhide interrupts.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init Rawhide Interrupts\n");
+#endif // HALDBG
+ HalpInitializeRawhideInterrupts();
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init 21164 Interrupts\n");
+#endif // HALDBG
+ HalpInitialize21164Interrupts();
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init IDT entries\n");
+#endif // HALDBG
+#if 0
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = // IRQ0 is unused on Rawhide
+ (PKINTERRUPT_ROUTINE) NULL;
+#endif
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = // IOD Interrupt
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = // Interval Timer Interrupt
+ (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+#if !defined(NT_UP)
+ PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = // IP Interrupt
+ (PKINTERRUPT_ROUTINE)HalpIpiInterruptHandler;
+#endif //NT_UP
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] = // Halt button, CPU halt
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = // Duplicate TAG Parity Error
+ (PKINTERRUPT_ROUTINE)HalpCacheErrorInterrupt; // (cached CUD only).
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Start 21164 Interrupts\n");
+#endif // HALDBG
+ HalpStart21164Interrupts();
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag & IodInterruptRegisters);
+
+ DbgPrint("HalpInitializeInterrupts: Primary Processor Complete\n");
+#endif // HALDBG
+
+ } else {
+
+#if !defined(NT_UP)
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Secondary Processor\n");
+#endif // HALDBG
+
+ //
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+#if 0
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = // IRQ0 is unused on Rawhide
+ (PKINTERRUPT_ROUTINE) NULL;
+#endif
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = // IOD Interrupt
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = // Interval Timer Interrupt
+ (PKINTERRUPT_ROUTINE)HalpSecondaryClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = // IP Interrupt
+ (PKINTERRUPT_ROUTINE)HalpIpiInterruptHandler;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] = // Halt button, CPU halt
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = // Duplicate TAG Parity Error
+ (PKINTERRUPT_ROUTINE)HalpCacheErrorInterrupt; // (cached CUD only).
+
+ HalpStart21164Interrupts();
+#endif //NT_UP
+ }
+
+ return TRUE;
+
+}
+
+
+
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#if 0
+// mdbfix - who references this?
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+#endif
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpClockInterrupt;
+
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ HalpInitializeIodMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+
+VOID
+HalpInitializeSystemClassData(
+ ULONG Phase,
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ Initialize the Rawhide configuration masks passed in the ARC tree.
+ For phase 0, only initialize the hardware masks. Wait until phase 1,
+ (after memory manager started) to allocate and save.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigComponent;
+ PRAWHIDE_SYSTEM_CLASS_DATA SystemClassData;
+ MC_ENUM_CONTEXT mcCtx;
+
+ ConfigComponent = KeFindConfigurationEntry(
+ LoaderBlock->ConfigurationRoot,
+ SystemClass, // Class
+ ArcSystem, // Type
+ 0
+ );
+
+ //
+ // Check for errors
+ //
+
+ if ( (ConfigComponent == NULL) ||
+ (ConfigComponent->ConfigurationData == NULL) ) {
+
+#if HALDBG
+ DbgPrint ("HalpInitializeSystemClassData: Configuration Data Missing\n");
+ DbgBreakPoint ();
+#endif // HALDBG
+ }
+
+
+ SystemClassData = (PRAWHIDE_SYSTEM_CLASS_DATA)
+ ConfigComponent->ConfigurationData;
+
+ if (Phase == 0) {
+
+#if HALDBG
+ HalpDumpSystemClassData(SystemClassData);
+#endif
+
+ //
+ // Initialize the rawhide configuration masks
+ //
+
+ HalpIodMask = SystemClassData->IodMask;
+ HalpCpuMask = SystemClassData->CpuMask;
+ HalpGcdMask = SystemClassData->GcdMask;
+
+ HalpNumberOfIods = HalpMcBusEnumStart(HalpIodMask, &mcCtx);
+ HalpNumberOfCpus = HalpMcBusEnumStart(HalpCpuMask, &mcCtx);
+
+ } else {
+
+ //
+ // Allocate memory and save
+ //
+
+ HalpSystemClassData = (PRAWHIDE_SYSTEM_CLASS_DATA)
+ ExAllocatePool(NonPagedPool, SystemClassData->Length);
+
+ RtlMoveMemory(
+ HalpSystemClassData,
+ ConfigComponent->ConfigurationData,
+ SystemClassData->Length
+ );
+ }
+
+}
+
+#if HALDBG
+VOID
+HalpDumpSystemClassData(
+ PRAWHIDE_SYSTEM_CLASS_DATA SystemClassData
+ )
+{
+
+#define ONE_MB 1024
+
+ ULONG entry;
+ ULONGLONG TotalMemorySize;
+ ULONGLONG FreeMemorySize;
+ ULONGLONG BadMemorySize;
+ ULONGLONG EntrySizeInBytes;
+
+ //
+ // Print out machine dependent data for debug
+ //
+
+ DbgPrint("System Class Data:\r\n");
+ DbgPrint("Length: %x\n", SystemClassData->Length);
+ DbgPrint("Version: %x\n", SystemClassData->Version);
+ DbgPrint("Flags: %8.8x %8.8x\n", SystemClassData->Flags.all >> 32,
+ SystemClassData->Flags);
+ DbgPrint("CpuMask: %8.8x %8.8x\n", SystemClassData->CpuMask >> 32,
+ SystemClassData->CpuMask);
+ DbgPrint("GcdMask: %8.8x %8.8x\n", SystemClassData->GcdMask >> 32,
+ SystemClassData->GcdMask);
+ DbgPrint("IodMask: %8.8x %8.8x\n", SystemClassData->IodMask >> 32,
+ SystemClassData->IodMask);
+ DbgPrint("System Configuration:\n");
+ DbgPrint("\tValidBits: %x\n", SystemClassData->SystemConfig.ValidBits);
+
+ DbgPrint("\tSystemManufacturer: %s\r\n",
+ SystemClassData->SystemConfig.SystemManufacturer);
+
+ DbgPrint("\tSystemModel: %s\r\n",
+ SystemClassData->SystemConfig.SystemModel);
+
+ DbgPrint("\tSystemSerialNumber: %s\r\n",
+ SystemClassData->SystemConfig.SystemSerialNumber);
+
+ DbgPrint("\tSystemRevisionLevel: %s\r\n",
+ SystemClassData->SystemConfig.SystemRevisionLevel);
+
+ DbgPrint("\tSystemVariation: %s\r\n",
+ SystemClassData->SystemConfig.SystemVariation);
+
+ DbgPrint("\tSystemConsoleTypeRev: %s\r\n",
+ SystemClassData->SystemConfig.ConsoleTypeRev);
+
+ DbgPrint("MemoryDescriptor is: %s\r\n",
+ (SystemClassData->Flags.MemoryDescriptorValid ?
+ "Valid" : "Invalid"));
+ DbgPrint("MemoryDescriptorCount: %d\r\n",
+ SystemClassData->MemoryDescriptorCount);
+
+ DbgPrint("MemoryDescriptor is: %s\n",
+ (SystemClassData->Flags.MemoryDescriptorValid ?
+ "Valid" : "Invalid"));
+ DbgPrint("MemoryDescriptorCount: %d\n", SystemClassData->MemoryDescriptorCount);
+
+ DbgPrint("Descriptor\tMemoryType\tBasePage\tPageCount\tSize\tTested?\n");
+
+ TotalMemorySize = 0;
+ FreeMemorySize = 0;
+ BadMemorySize = 0;
+
+ for (entry = 0; entry < SystemClassData->MemoryDescriptorCount; entry++) {
+
+ EntrySizeInBytes =
+ (SystemClassData->MemoryDescriptor[entry].PageCount) << PAGE_SHIFT;
+
+ DbgPrint("[%d]\t\t%d\t\t%x\t\t%8x\t%4d Mb %x\n",
+ entry,
+ SystemClassData->MemoryDescriptor[entry].MemoryType,
+ SystemClassData->MemoryDescriptor[entry].BasePage,
+ SystemClassData->MemoryDescriptor[entry].PageCount,
+ (EntrySizeInBytes / ONE_MB),
+ SystemClassData->MemoryDescriptor[entry].bTested
+ );
+
+ //
+ // Total up free (good memory) entries
+ //
+
+ if (SystemClassData->MemoryDescriptor[entry].MemoryType
+ == RawhideMemoryFree) {
+ FreeMemorySize += EntrySizeInBytes;
+ }
+
+ //
+ // Total up hole (bad memory) entries
+ // Remember them so that they can be removed later.
+ //
+
+ if (SystemClassData->MemoryDescriptor[entry].MemoryType
+ == RawhideMemoryBad) {
+
+ //
+ // N.B. If this is the last descriptor, and it's a hole
+ // (bad memory), then ignore it.
+ //
+
+ if (entry == (SystemClassData->MemoryDescriptorCount - 1)) {
+ break;
+ }
+
+ BadMemorySize += EntrySizeInBytes;
+
+ }
+
+ //
+ // Total up all entries, except a trailing hole
+ //
+
+ TotalMemorySize += EntrySizeInBytes;
+
+
+ }
+
+ DbgPrint("Total Size:\t\t\t\t\t%8x\t%4d Mb\n\n",
+ (TotalMemorySize >> PAGE_SHIFT),
+ (TotalMemorySize / ONE_MB));
+ DbgPrint("Free Memory Size:\t\t\t\t%8x\t%4d Mb\n",
+ (FreeMemorySize >> PAGE_SHIFT),
+ (FreeMemorySize / ONE_MB));
+ DbgPrint("Bad Memory Size:\t\t\t\t%8x\t%4d Mb\n",
+ (BadMemorySize >> PAGE_SHIFT),
+ (BadMemorySize / ONE_MB));
+
+}
+#endif // HALDBG
+
+
+VOID
+HalpEarlyInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any critical Platform-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Initialize the Rawhide hardware configuration masks from the
+ // SRM Machine Dependent Data passed in the Configuration Tree.
+ //
+
+ HalpInitializeSystemClassData(Phase, LoaderBlock);
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Platform-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+ PKPRCB Prcb;
+ PRAWHIDE_PCR pRawhidePcr;
+ IOD_POSTED_INTERRUPT_ADDR PostingTable;
+ IOD_WHOAMI IodWhoAmI;
+
+ Prcb = PCR->Prcb;
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Phase = %d\n", Phase);
+#endif // HALDBG
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR) {
+
+ if( Phase == 0 ){
+
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Parse Loader Block\n");
+#endif // HALDBG
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the PCI parity checking.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: \n");
+#endif // HALDBG
+ if( HalDisablePCIParityChecking != 0 ){
+ PciParityChecking = FALSE;
+ } else {
+ PciParityChecking = TRUE;
+ }
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Machine Checks\n");
+#endif // HALDBG
+ HalpInitializeIodMachineChecks( ReportCorrectables = TRUE,
+ PciParityChecking );
+
+ //
+ // Initialize the IOD mapping table, assigning logical
+ // numbers to all IOD's. This logical number cooresponds
+ // to the HwBusNumber found in PCIPBUSDATA.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Mapping Table\n");
+#endif // HALDBG
+ HalpMcBusEnumAndCall(HalpIodMask, HalpInitializeIodMappingTable);
+
+ //
+ // Initialize the logical to physical processor mapping
+ // for the primary processor.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init HalpLogicalToPhysicalProcesor\n");
+#endif // HALDBG
+
+ HalpInitializeProcessorMapping(
+ HAL_PRIMARY_PROCESSOR,
+ HAL_PRIMARY_PROCESSOR,
+ LoaderBlock
+ );
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Phase %d complete\n", Phase);
+#endif // HALDBG
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Save the Machine Dependent Data now that Memory Manager started.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init System Class Data\n");
+#endif // HALDBG
+ HalpInitializeSystemClassData(Phase, LoaderBlock);
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Register Internal Bus Handlers\n");
+#endif // HALDBG
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init PCI Bus\n");
+#endif // HALDBG
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize the IOD vector table
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Vector Table\n");
+#endif // HALDBG
+ HalpInitializeIodVectorTable();
+
+ //
+ // Initialize the IOD interrupt vector table CSR's
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Vector CSRs\n");
+#endif // HALDBG
+ HalpMcBusEnumAndCall(HalpIodMask, HalpInitializeIodVectorCSRs);
+
+ //
+ // Generate pointer to the CPU's area in the IOD vector table
+ //
+
+ PostingTable.all = 0;
+ PostingTable.Base4KPage = ((ULONG)HalpIodPostedInterrupts / __4K);
+ PostingTable.CpuOffset =
+ HalpLogicalToPhysicalProcessor[PCR->Number].all;
+
+ HAL_PCR->PostedInterrupts =
+ (PIOD_POSTED_INTERRUPT)PostingTable.all;
+
+ //
+ // Initialize the IOD and CPU interrupt Vector table
+ //
+
+ HalpInitializeVectorBalanceData();
+
+ //
+ // Initialize the CPU vector entry for this processor
+ //
+
+ HalpInitializeCpuVectorData(PCR->Number);
+
+ //
+ // Assign the primary processors vectors
+ //
+
+ HalpAssignPrimaryProcessorVectors(&HalpIodVectorDataHead);
+
+ //
+ // Initialize profiler.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Profiler\n");
+#endif // HALDBG
+ HalpInitializeProfiler();
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Print Version Message\n");
+#endif // HALDBG
+ //
+ // Print a message with version number.
+ //
+
+ sprintf( MsgBuffer,
+ "Digital Equipment Corporation %s %s %d/%d\n",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+ HalDisplayString( MsgBuffer );
+
+ //
+ // Register the name of the HAL.
+ //
+
+ sprintf( MsgBuffer,
+ "%s %s %d/%d PCI/EISA HAL",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Register Platform Resources\n");
+#endif // HALDBG
+ HalpRegisterPlatformResources( MsgBuffer );
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Phase %d Complete\n", Phase);
+#endif // HALDBG
+ }
+
+ } else {
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Rawhide is the default EV4 parity-mode handler. Note
+ // that this was done in HalpEstablishErrorHandler() for the
+ // primary processor.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Generate pointer to the CPU's area in the IOD vector table
+ //
+
+ PostingTable.all = 0;
+ PostingTable.Base4KPage = ((ULONG)HalpIodPostedInterrupts / __4K);
+ PostingTable.CpuOffset = HalpLogicalToPhysicalProcessor[PCR->Number].all;
+
+ HAL_PCR->PostedInterrupts = (PIOD_POSTED_INTERRUPT)PostingTable.all;
+
+ //
+ // Initialize profiler on this secondary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Initialize the CPU vector entry for this processor
+ //
+
+ HalpInitializeCpuVectorData(PCR->Number);
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpInitializeProcessorMapping(
+ IN ULONG LogicalProcessor,
+ IN ULONG PhysicalProcessor,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the logical to physical processor mapping
+ entry in the processor mapping table. The physical mapping is passed
+ by ARC FW via the configuration tree.
+
+Arguments:
+
+ LogicalProcessor - logical processor number.
+
+ PhysicalProcessor - restart block number.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+
+
+{
+ PCONFIGURATION_COMPONENT_DATA CpuConfigComponent;
+ PHALP_PROCESSOR_ID HalpProcessorId;
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ //
+ // Get a pointer to the configuration entry for this processor.
+ // The configuration data will contain the processors MC device ID.
+ //
+
+ CpuConfigComponent = KeFindConfigurationEntry(
+ LoaderBlock->ConfigurationRoot,
+ ProcessorClass,
+ CentralProcessor,
+ &PhysicalProcessor
+ );
+
+ //
+ // Check for errors.
+ //
+
+ if ( (CpuConfigComponent == NULL) ||
+ (CpuConfigComponent->ConfigurationData == NULL) ) {
+
+#if 0 //HALDBG
+ DbgPrint ("HalStartNextProcessor: Configuration Data Missing\n");
+#endif //HALDBG
+ // What to do now?
+ DbgBreakPoint ();
+ }
+
+ //
+ // Obtain a pointer to the processor Id from the configuration data.
+ //
+
+ HalpProcessorId =
+ ((PHALP_PROCESSOR_ID)CpuConfigComponent->ConfigurationData);
+
+ //
+ // Initialize the table entry for this processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[LogicalProcessor].all = HalpProcessorId->all;
+
+}
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Eisa);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+
+#if 0
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+#endif
+
+ Resource.u.Start = SUPERIO_INDEX_PORT;
+ Resource.u.Length = SUPERIO_PORT_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaChannel = 0x4;
+ Resource.u.DmaPort = 0x0;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to Alcor and the call should be
+// ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(RAWHIDE_UNCORRECTABLE_FRAME)
+ + HalpNumberOfIods * sizeof(IOD_ERROR_FRAME);
+
+ //
+ // ecrfix - will have to figure out something else for
+ // PCI, ESC snapshots and System Mgmt Frame.
+ //
+
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Rawhide";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType, systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+// RtlCopyMemory(SystemInfo->SystemSerialNumber,
+// PCR->SystemSerialNumber,
+// 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PRAWHIDE_UNCORRECTABLE_FRAME rawerr;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ //
+ // Fill in Common RCUD Header
+ //
+
+ rawerr = (PRAWHIDE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+
+ strncpy( PUncorrectableError->UncorrectableFrame.System.SystemSerialNumber,
+ HalpSystemClassData->SystemConfig.SystemSerialNumber, 10);
+
+ strncpy( rawerr->CudHeader.SystemSN,
+ HalpSystemClassData->SystemConfig.SystemSerialNumber, 10);
+
+ strncpy( rawerr->CudHeader.SystemRev,
+ HalpSystemClassData->SystemConfig.SystemRevisionLevel, 4);
+
+ // Jam the SRM console revision in the Module SN
+
+ strncpy( rawerr->CudHeader.ModuleSN,
+ HalpSystemClassData->SystemConfig.ConsoleTypeRev, 9);
+ rawerr->CudHeader.ModuleSN[9] = '\0';
+
+ // Jam the first 5 chars of System Model (4x00, etc.) in a reserved field
+
+ strncpy( rawerr->CudHeader.Reserved2,
+ HalpSystemClassData->SystemConfig.SystemModel, 5);
+ rawerr->CudHeader.Reserved2[5] = '\0';
+
+ //
+ // The following RCUD header data is not valid for Windows NT.
+ //
+
+ rawerr->CudHeader.HwRevision = 0;
+ rawerr->CudHeader.ModType = 0;
+ rawerr->CudHeader.DisabledResources = 0;
+
+ //
+ // Fill in MC Bus Snapshot header
+ //
+
+ rawerr->McBusSnapshot.Length = sizeof(MC_BUS_SNAPSHOT)
+ + HalpNumberOfIods * sizeof(IOD_ERROR_FRAME);
+
+ rawerr->McBusSnapshot.NumberOfIods = HalpNumberOfIods;
+
+ return;
+}
diff --git a/private/ntos/nthals/halraw/alpha/rwintbal.c b/private/ntos/nthals/halraw/alpha/rwintbal.c
new file mode 100644
index 000000000..f32f533b1
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwintbal.c
@@ -0,0 +1,1762 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwintbal.c
+
+Abstract:
+
+ The module provides support for distributing interrupt load among
+ processors for Rawhide systems.
+
+Author:
+
+ Matthew Buchman (DEC) 29-November-1995
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "rawhide.h"
+#include "pcrtc.h"
+
+//
+// The enable mask for all interrupts sourced from the IOD (all device
+// interrupts, and all from PCI). A "1" indicates the interrupt is enabled.
+//
+
+extern PULONG *HalpIodInterruptMask;
+
+//
+// Declare IOD and CPU affinity tables
+//
+
+LIST_ENTRY HalpIodVectorDataHead;
+LIST_ENTRY HalpCpuVectorDataHead;
+
+PIOD_VECTOR_DATA HalpIodVectorData;
+PCPU_VECTOR_DATA HalpCpuVectorData;
+
+
+//
+// The number of target CPUS, mainly for performance comparison of
+// one processor vs. distributed interrupt load
+//
+
+#if 1
+ULONG HalpNumberOfTargetCpus = IOD_MAX_INT_TARG;
+#else
+ULONG HalpNumberOfTargetCpus = 1;
+#endif
+
+
+
+PVOID
+HalpFindWeightedEntry(
+ PLIST_ENTRY ListHead,
+ WEIGHTED_SEARCH_CRITERIA SearchCriteria
+ )
+/*++
+
+Routine Description:
+
+ This routine searches a WEIGHTED list searching for the maximum
+ or minimum weight, depending on the SearchCriteria. A WEIGHTED
+ list entry overlays the generic LIST_ENTRY provided by NT. This
+ allows us to use the generic LIST_ENTRY routines for list
+ manipulation. To treat this as an ordered list, we must traverse
+ this list by hand to find the maximum element.
+
+ The entry matching the search criteria is removed from the list
+ as a side effect.
+
+Arguments:
+
+ ListHead - a pointer the list head.
+
+ SearchCriteria - either FindMaxEntry or FindMinEntry
+
+Return Value:
+
+ Return a pointer to the maximum element or NULL for
+ an empty list.
+
+--*/
+{
+ PLIST_ENTRY NextEntry;
+ PLIST_ENTRY CurrentMaxMinEntry;
+ PWEIGHTED_LIST_ENTRY WeightedEntry;
+ LONG CurrentMaxMinWeight;
+
+
+ //
+ // Handle the empty list case
+ //
+
+ if (IsListEmpty(ListHead)) {
+ return (NULL);
+ }
+
+ //
+ // Traverse this list looking for the maximum weight
+ //
+
+ for (
+ NextEntry = ListHead->Flink,
+ CurrentMaxMinEntry = NULL;
+
+ NextEntry != ListHead;
+
+ NextEntry = NextEntry->Flink
+
+ ) {
+
+ //
+ // The WEIGHTED_LIST_ENTRY overlays the LIST_ENTRY
+ //
+
+ WeightedEntry = (PWEIGHTED_LIST_ENTRY)NextEntry;
+
+ if (CurrentMaxMinEntry == NULL) {
+
+ CurrentMaxMinEntry = NextEntry;
+ CurrentMaxMinWeight = WeightedEntry->Weight;
+
+ } else {
+
+ if (SearchCriteria == FindMaxWeight) {
+
+ if (WeightedEntry->Weight > CurrentMaxMinWeight) {
+ CurrentMaxMinEntry = NextEntry;
+ CurrentMaxMinWeight = WeightedEntry->Weight;
+ }
+
+ } else {
+
+ if (WeightedEntry->Weight < CurrentMaxMinWeight) {
+ CurrentMaxMinEntry = NextEntry;
+ CurrentMaxMinWeight = WeightedEntry->Weight;
+ }
+
+ }
+ }
+ }
+
+ //
+ // Remove the maximum from the list
+ //
+
+ RemoveEntryList(CurrentMaxMinEntry);
+
+ return ((PVOID)CurrentMaxMinEntry);
+}
+
+// mdbfix - delete these routines later!
+#if 0
+
+//
+// Declare the lower-level routine used to read PCI config space
+//
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpFindPciBusVectors(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PVOID ConfigurationData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds all device interrupt vectors for the PCI bus
+ handler obtained from the configuration tree and sets the
+ corresponding bits in the VectorPresent bitmap for the IOD.
+
+Arguments:
+
+ Component - The ARC configuration component for this bus.
+
+ ConfigurationData - The configuration data payload (or NULL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_PCI_CONFIGURATION ArcPciConfiguration;
+ ULONG BusNumber;
+ ULONG HwBusNumber;
+ BOOLEAN BusIsAcrossPPB;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCIPBUSDATA BusContext;
+ RTL_BITMAP DevicePresent;
+ PCI_SLOT_NUMBER SlotNumber;
+ PIOD_VECTOR_DATA IodIoVectors;
+ ULONG DeviceNumber;
+ ULONG NextDevice;
+ ULONG FunctionNumber;
+ ULONG InterruptLine;
+ PCI_COMMON_CONFIG CommonConfig;
+
+ //
+ // Copy the configuration data from the component.
+ //
+
+ RtlCopyMemory(
+ &ArcPciConfiguration,
+ ConfigurationData,
+ sizeof (ARC_PCI_CONFIGURATION)
+ );
+
+ //
+ // Use the values provided.
+ //
+
+ BusNumber = ArcPciConfiguration.BusNumber;
+ HwBusNumber = ArcPciConfiguration.HwBusNumber;
+ BusIsAcrossPPB = ArcPciConfiguration.BusIsAcrossPPB;
+ IodIoVectors = HalpIodVectorData + HwBusNumber;
+
+ //
+ // Initialize the BusNumber for this IOD now.
+ // We might want to use it later to obtain the bus handler
+ //
+
+ IodIoVectors->BusNumber = BusNumber;
+
+ //
+ // Allocate and initialize the handler for this bus. N.B. device-present
+ // checking is disabled at this point. We will enable it below.
+ //
+
+ BusHandler = HaliHandlerForBus(
+ PCIBus,
+ BusNumber
+ );
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Use the device-present bitmap for this bus to query configuration
+ // Space for InterruptLine values.
+ //
+
+ //
+ // Initialize the device-present bitmap for this bus.
+ //
+
+ HalpInitializeBitMap(
+ &BusContext.DevicePresent,
+ BusContext.DevicePresentBits,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ //
+ // Copy the bitmap from the bus handler.
+ //
+
+ RtlCopyMemory(
+ &BusContext.DevicePresentBits,
+ &BusData->DevicePresentBits,
+ sizeof (BusData->DevicePresentBits)
+ );
+
+
+ //
+ // Starting with device 0, scan the device present
+ // bitmap.
+ //
+
+ DeviceNumber = 0;
+
+ while ( (DeviceNumber =
+ HalpFindSetBitsAndClear(
+ &BusContext.DevicePresent,
+ 1,
+ DeviceNumber
+ ) ) != -1 ) {
+
+ //
+ // Initialize the slot number.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function number.
+ //
+
+ for (FunctionNumber = 0;
+ FunctionNumber < PCI_MAX_FUNCTION;
+ FunctionNumber++) {
+
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the common configuration header.
+ //
+
+ HalpReadPCIConfig(
+ BusHandler,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If the Vendor ID is invalid, then no device is present
+ // at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+ if (FunctionNumber == 0) {
+ break;
+ }
+ continue;
+ }
+
+ //
+ // Obtain the vector assigned to this Device:Function
+ // during PCI configuration.
+ //
+
+ if (CommonConfig.u.type0.InterruptLine) {
+
+ //
+ // Obtain vector and normalize
+ //
+
+ InterruptLine =CommonConfig.u.type0.InterruptLine;
+ InterruptLine -= (RawhidePinToLineOffset + 1);
+
+ //
+ // Determine if this is a shared vector
+ //
+
+ if ( HalpAreBitsSet(
+ &IodIoVectors->VectorPresent[0],
+ InterruptLine,
+ 1
+ ) == TRUE ) {
+
+ //
+ // Indicate vector is shared in bitmap
+ //
+
+ HalpSetBits(
+ &IodIoVectors->SharedVector[0],
+ InterruptLine,
+ 1
+ );
+
+ HalpDumpBitMap(&IodIoVectors->SharedVector[0]);
+
+ } else {
+
+ //
+ // Indicate device is present in bitmap
+ //
+
+ HalpSetBits(
+ &IodIoVectors->VectorPresent[0],
+ InterruptLine,
+ 1
+ );
+
+ HalpDumpBitMap(&IodIoVectors->VectorPresent[0]);
+
+ }
+
+ //
+ // Increment the weight
+ //
+
+ IodIoVectors->ListEntry.Weight++;
+
+ } // if (CommonConfig.InterruptLine)
+
+ //
+ // If this is not a multi-function device, then terminate
+ // the function number loop.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+
+ } // for (FunctionNumber...)
+
+ } // while (DeviceNumber != -1)
+}
+
+
+VOID
+HalpFindAllPciVectors(
+ IN PCONFIGURATION_COMPONENT_DATA Root
+ )
+/*++
+
+Routine Description:
+
+ This function loops through each multi-function adapter component
+ in the ARC configuration tree and calls HalpFindPciBusVectors()
+ searching for device vectors.
+
+Arguments:
+
+ Root - The root of the ARC configuration tree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Key;
+ PCONFIGURATION_COMPONENT_DATA Adapter;
+
+ //
+ // Loop through each multi-function adapter component in the ARC
+ // configuration tree.
+ //
+
+ for (Key = 0; TRUE; Key++) {
+
+ //
+ // Get a pointer to the component data.
+ //
+
+ Adapter = KeFindConfigurationEntry(
+ Root,
+ AdapterClass,
+ MultiFunctionAdapter,
+ &Key
+ );
+
+ //
+ // If there are no more multi-function adapters in the ARC
+ // configuration tree, then we're done.
+ //
+
+ if (Adapter == NULL) {
+ break;
+ }
+
+ //
+ // Ascertain whether this is a PCI multi-function adapter component.
+ // If so, find the device vectors.
+ //
+
+ if (stricmp(Adapter->ComponentEntry.Identifier, "PCI") == 0) {
+ HalpFindPciBusVectors(
+ &Adapter->ComponentEntry,
+ Adapter->ConfigurationData
+ );
+ }
+ }
+}
+
+
+VOID
+HalpBalanceVectorLoadForIod(
+ PIOD_VECTOR_DATA IodVectorData
+ )
+/*++
+
+Routine Description:
+
+ Balance the vector load for the given IOD among the
+ CPU pair. The basic algorithm is:
+
+ 1. Find a device present from the bitmap.
+ 2. Choose the CPUwith the minimum vector load.
+ 3. Assign the device vector from (1) to this CPU
+ and update the CPU's vector load (weight) by 1.
+ 4. If the vector is shared (multiple devices
+ connect), update the CPU's vector load by 1.
+ While this does not accurately reflect the
+ actual vector's sharing the device, it will
+ due for algorithmic simplicity.
+ 5. Update the CPU's IOD service mask.
+ 6. repeat for all vectors.
+
+
+Arguments:
+
+ IodListHead - head of temporary IOD vector info list.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RTL_BITMAP VectorPresent;
+ ULONG VectorPresentBits;
+ ULONG IRRBitNumber;
+ ULONG InterruptBit;
+
+ HalpInitializeBitMap(
+ &VectorPresent,
+ (PULONG)&VectorPresentBits,
+ 32
+ );
+
+ //
+ // Copy the device present bitmap from the IOD information.
+ //
+
+ RtlCopyMemory(
+ &VectorPresentBits,
+ &IodVectorData->VectorPresentBits[0],
+ sizeof (IodVectorData->VectorPresentBits[0])
+ );
+
+ //
+ // Now that we have a copy of all device vectors for this
+ // IOD, clear the device present bitmap for target 0.
+ // This was only being used as temporary storage.
+ //
+
+ HalpClearAllBits(&IodVectorData->VectorPresent[0]);
+
+ //
+ // Start with the first IRR bit.
+ //
+
+ IRRBitNumber = 0;
+
+ //
+ // Find the next Device present.
+ // Remember that this bitmap actually represents
+ // the interrupt vector assigned to devices.
+ //
+
+ while (( IRRBitNumber =
+ HalpFindSetBitsAndClear(
+ &VectorPresent,
+ 1,
+ IRRBitNumber) ) != -1 ) {
+
+ InterruptBit = (1 << IRRBitNumber);
+
+ //
+ // Assign the vector for this IOD
+ //
+
+ HalpAssignInterruptForIod(IodVectorData, InterruptBit);
+
+ }
+
+}
+
+
+VOID
+HalpBalanceIoVectorLoad(
+ PLIST_ENTRY IodListHead
+ )
+/*++
+
+Routine Description:
+
+ Balance the vector load among the set of processors.
+ The basic algorithm is:
+
+ 1. Find an IOD to process:
+
+ From the IOD set, find the IOD with the maximum
+ number of vectors, and permanantly remove this
+ IOD from the set.
+
+ 2. Find a CPU pair that will act as targets for
+ the selected IOD interrupts:
+
+ a. From the CPU set, find the first CPU with the
+ minimum number of vectors assigned and temporarily
+ remove this CPU from the CPU set.
+
+ b. From the CPU set, find the second CPU with the
+ minimum number of vectors assigned and temporarily
+ remove this CPU from the CPU set.
+
+ 3. Call HalpBalanceIodVectorLoad to divide the IOD
+ vectors among the two CPU's.
+
+ 5. Add the CPU's back the the CPU set. This makes them
+ available for selection during the next iteration.
+
+ 6. Repeat until the IOD set is empty.
+
+Arguments:
+
+ IodListHead - head of temporary IOD vector info list.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIOD_VECTOR_DATA IodVectorData;
+
+ //
+ // Balance the vector load for each IOD,
+ // assigning vector affinity in the process
+ //
+
+ while (!IsListEmpty(IodListHead)) {
+
+ //
+ // Find the IOD with the maximum number of
+ // vectors. It is removed from the list as
+ // a side effect.
+ //
+
+ IodVectorData = (PIOD_VECTOR_DATA)
+ HalpFindWeightedEntry(IodListHead, FindMaxWeight);
+
+ //
+ // Assign the interrupt vector affinity for this IOD
+ //
+
+ HalpBalanceVectorLoadForIod(
+ IodVectorData
+ );
+
+ //
+ // Add this to the global list of IOD's.
+ // Use shortcut to obtain LIST_ENTRY.
+ //
+
+ InsertHeadList(
+ &HalpIodVectorDataHead,
+ &IodVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+}
+
+
+VOID
+HalpInitializeIoVectorAffinity(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ The IOD and CPU vector information tables are used balance the
+ interrupt load from all IOD's among the set of available CPU's.
+
+ Allocate and initialize the IOD and CPU vector information tables,
+ pre-assign vectors for EISA, I2c, SoftErr, and HardErr, and
+ call HalpIoVectorLoad() to assign IOD vectors to CPU's.
+
+Arguments:
+
+ LoaderParameterBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_MASK IodMask = HalpIodMask;
+ MC_DEVICE_MASK CpuMask = HalpCpuMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ PCPU_VECTOR_DATA CpuVectorData;
+ LIST_ENTRY IodListHead;
+ ULONG LogicalNumber;
+ ULONG Target;
+
+ //
+ // Allocate the IOD device affinity table.
+ //
+
+ HalpIodVectorData = (PIOD_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(IOD_VECTOR_DATA)* HalpNumberOfIods
+ );
+
+ RtlZeroMemory(
+ HalpIodVectorData,
+ sizeof(IOD_VECTOR_DATA)*HalpNumberOfIods
+ );
+
+ //
+ // Initialize the IOD vector affinity list.
+ //
+
+ InitializeListHead(&HalpIodVectorDataHead);
+ InitializeListHead(&IodListHead);
+
+ for ( LogicalNumber = 0, IodVectorData = HalpIodVectorData;
+ LogicalNumber < HalpNumberOfIods;
+ LogicalNumber++, IodVectorData++ ) {
+
+
+ //
+ // Initialize bitmaps for each target.
+
+ for (Target = 0; Target < IOD_MAX_INT_TARG; Target++) {
+
+ //
+ // The VectorBitmap represents the devices on this IOD
+ // that been assigned vectors and to which target the
+ // vectors have been assigned.
+ //
+
+
+ HalpInitializeBitMap(
+ &IodVectorData->VectorPresent[Target] ,
+ (PULONG)&IodVectorData->VectorPresentBits[Target],
+ 32
+ );
+
+ //
+ // The SharedBitmap represents vectors that are shared
+ // by devices on this IOD. It is used to make decisions
+ // on which target to assign vectors.
+ //
+
+ HalpInitializeBitMap(
+ &IodVectorData->SharedVector[Target],
+ (PULONG)&IodVectorData->SharedVectorBits[Target],
+ 32
+ );
+
+ }
+
+ //
+ // Assign the device number. This cooresponds to the logical
+ // IOD number.
+ //
+
+ IodVectorData->HwBusNumber = LogicalNumber;
+
+ //
+ // Add this IOD to temporary list. The IOD will be added
+ // to permanent list after it is processed.
+ //
+
+ InsertTailList(
+ &IodListHead,
+ &IodVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+ //
+ // Allocate the CPU IO device affinity table.
+ //
+
+ HalpCpuVectorData = (PCPU_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(CPU_VECTOR_DATA) * HalpNumberOfCpus
+ );
+
+ RtlZeroMemory(
+ HalpCpuVectorData,
+ sizeof(CPU_VECTOR_DATA)*HalpNumberOfCpus
+ );
+
+ //
+ // Initialize the CPU vector affinity list.
+ //
+
+ InitializeListHead(&HalpCpuVectorDataHead);
+
+ for ( LogicalNumber = 0, CpuVectorData = HalpCpuVectorData;
+ LogicalNumber < HalpNumberOfCpus;
+ LogicalNumber++, CpuVectorData++ ) {
+
+ //
+ // Assign the device number. This cooresponds to the logical
+ // CPU number.
+ //
+
+ CpuVectorData->LogicalNumber = LogicalNumber;
+ CpuVectorData->McDeviceId.Gid = GidPrimary;
+
+ switch (LogicalNumber) {
+
+ case 0:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu1;
+ break;
+
+ case 1:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu1;
+ break;
+
+ case 2:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu2;
+ break;
+
+ case 3:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu3;
+ break;
+
+ }
+ //
+ // Insert this CPU into the list
+ //
+
+ InsertTailList(
+ &HalpCpuVectorDataHead,
+ &CpuVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+ //
+ // Find all PCI Iod Vectors.
+ //
+
+ HalpFindAllPciVectors(LoaderBlock->ConfigurationRoot);
+
+ //
+ // Preassign error vectors for all IOD's as well as EISA, EISANMI
+ // and I2c vectors to the primary processor.
+ //
+
+ HalpAssignPrimaryProcessorVectors(&IodListHead);
+
+ //
+ // Balance the IO vector load among the CPU's
+ //
+
+ HalpBalanceIoVectorLoad(&IodListHead);
+
+#if HALDBG
+
+ HalpDumpIoVectorAffinity();
+
+#endif
+
+}
+
+
+VOID
+HalpAssignIodInterrupts(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+
+/*++
+
+Routine Description:
+
+ This enumeration routine assigns the Rawhide interrupts for the
+ corresponding IOD and sets up the target CPU's. The interrupts
+ are initialized with the values determined by
+ HalpInitializeIoVectorAffinity()
+
+ Interrupts were previously routed to the primary processor
+ by HalpInitializeIodInterrupts. Now that All processors are
+ started, we must reassign HardErr, Eisa, and EisaNMI interrupts.
+
+ The logical bus is assigned from the static variable PciBusNumber, which is
+ incremented with each invokation.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical (Hardware) bus number.
+
+ Arguments - Variable Arguments. None for this routine.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIOD_VECTOR_DATA IodVectorData;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PVOID IntMaskQva;
+ ULONG Target;
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Disable MCI bus interrupts
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
+ );
+
+ //
+ // Initialize the target register base on assigned values
+ //
+
+ IntTarg.Int0TargDevId = (ULONG)IodVectorData->IntTarg[0].all;
+ IntTarg.Int1TargDevId = (ULONG)IodVectorData->IntTarg[1].all;
+
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ IntTarg.all
+ );
+
+ //
+ // Write the mask bits for target 0 and 1
+ //
+
+ for (Target = 0; Target < IOD_MAX_INT_TARG; Target++) {
+
+ //
+ // Obtain the target IRR QVA
+ //
+
+ if (Target) {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
+
+ } else {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
+
+ }
+ IntMask.all = IodVectorData->IntMask[Target].all;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+ }
+
+ //
+ // Enable Interrupts.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ IOD_INT_CTL_ENABLE_IO_INT
+ );
+
+}
+
+#endif // STATIC BALANCE
+
+
+VOID
+HalpInitializeVectorBalanceData(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The IOD and CPU vector information tables are used balance the
+ interrupt load from all IOD's among the set of available CPU's.
+
+ Allocate and initialize the IOD and CPU vector information tables,
+ pre-assign vectors for EISA, I2c, SoftErr, and HardErr, and
+ call HalpIoVectorLoad() to assign IOD vectors to CPU's.
+
+Arguments:
+
+ LoaderParameterBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_MASK IodMask = HalpIodMask;
+ MC_DEVICE_MASK CpuMask = HalpCpuMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ ULONG LogicalNumber;
+ ULONG Target;
+
+ //
+ // Allocate the IOD device affinity table.
+ //
+
+ HalpIodVectorData = (PIOD_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(IOD_VECTOR_DATA)* HalpNumberOfIods
+ );
+
+ RtlZeroMemory(
+ HalpIodVectorData,
+ sizeof(IOD_VECTOR_DATA)*HalpNumberOfIods
+ );
+
+ //
+ // Initialize the IOD vector affinity list.
+ //
+
+ InitializeListHead(&HalpIodVectorDataHead);
+
+ for ( LogicalNumber = 0, IodVectorData = HalpIodVectorData;
+ LogicalNumber < HalpNumberOfIods;
+ LogicalNumber++, IodVectorData++ ) {
+
+ //
+ // Assign the device number. This cooresponds to the logical
+ // IOD number.
+ //
+
+ IodVectorData->HwBusNumber = LogicalNumber;
+
+ //
+ // Add this IOD to temporary list. The IOD will be added
+ // to permanent list after it is processed.
+ //
+
+ InsertTailList(
+ &HalpIodVectorDataHead,
+ &IodVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+ //
+ // Allocate the CPU vector data table for the maximum
+ // processor configuration.
+ //
+
+ HalpCpuVectorData = (PCPU_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(CPU_VECTOR_DATA)*HalpNumberOfCpus
+ );
+
+ RtlZeroMemory(
+ HalpCpuVectorData,
+ sizeof(CPU_VECTOR_DATA)*HalpNumberOfCpus
+ );
+
+ //
+ // Initialize the CPU vector affinity list.
+ // CPU's will add their entry later.
+ //
+
+ InitializeListHead(&HalpCpuVectorDataHead);
+
+}
+
+
+VOID
+HalpInitializeCpuVectorData(
+ ULONG LogicalCpu
+ )
+/*++
+
+Routine Description:
+
+ Allocate and initialize the CPU vector entry for this logical
+ CPU and add it to the global list,
+
+Arguments:
+
+ LogicalCpu - Logical CPU number assigned by HalStartNextProcessor().
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_MASK CpuMask = HalpCpuMask;
+ PCPU_VECTOR_DATA CpuVectorData;
+ ULONG Target;
+
+ //
+ // Use the logical processor number to offset into in the
+ // global CPU table.
+ //
+
+ CpuVectorData = HalpCpuVectorData + LogicalCpu;
+
+ //
+ // Initalize CPU vector data fields
+ //
+
+ CpuVectorData->LogicalNumber = LogicalCpu;
+
+ //
+ // Insert into global list
+ //
+
+ InsertTailList(
+ &HalpCpuVectorDataHead,
+ &CpuVectorData->ListEntry.ListEntry
+ );
+
+#if HALDBG
+ DbgPrint(
+ "Initialized vector data for CPU %d (%d, %d)\n",
+ CpuVectorData->LogicalNumber,
+ HalpLogicalToPhysicalProcessor[LogicalCpu].Gid,
+ HalpLogicalToPhysicalProcessor[LogicalCpu].Mid
+ );
+#endif
+
+}
+
+
+VOID
+HalpAssignPrimaryProcessorVectors(
+ PLIST_ENTRY IodListHead
+ )
+/*++
+
+Routine Description:
+
+ Assign primary processor vectors. This includes the following:
+
+ HardErr
+ SoftErr
+ Eisa
+ EisaNMI
+ I2cBus
+ I2cCtrl
+
+ By having the primary processor handle the error vectors, we
+ prevent hard errors from being serviced by multiple
+ processors.
+
+Arguments:
+
+ IodListHead - head of temporary IOD vector info list.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PLIST_ENTRY ListEntry;
+ PIOD_VECTOR_DATA IodVectorData;
+ PCPU_VECTOR_DATA PrimaryCpuVectorData;
+ MC_DEVICE_ID McDeviceId;
+ ULONG Target;
+
+ //
+ // Obtain the vector data structure for the primary processor
+ //
+
+ PrimaryCpuVectorData = HalpCpuVectorData;
+
+ //
+ // Assign the hard and soft error interrupt for each IOD
+ // to the primary processor
+ //
+
+ for ( ListEntry = IodListHead->Flink;
+ ListEntry != IodListHead;
+ ListEntry = ListEntry->Flink ) {
+
+ //
+ // Obtain the IOD vector data.
+ //
+
+ IodVectorData = (PIOD_VECTOR_DATA)ListEntry;
+
+ McDeviceId = HalpIodLogicalToPhysical[IodVectorData->HwBusNumber];
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) Target 0 to Primary Processor\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+#endif
+
+ //
+ // Assign the Target 0 CPU for this IOD
+ //
+
+ IodVectorData->TargetCpu[0] = PrimaryCpuVectorData;
+
+ //
+ // Assign the SoftErr and HardErr interrupts to each IOD
+ //
+
+ IodVectorData->IntMask[0].all |= (1 << IodHardErrIrrBit);
+ IodVectorData->IntMask[0].all |= (1 << IodSoftErrIrrBit);
+
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) HardError to Target 0, CPU 0\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+#endif
+
+ //
+ // Assign the Eisa, EisaNMI, and I2C interrupts for PCI bus 0
+ // to the primary processor.
+ //
+
+ if (IodVectorData->HwBusNumber == 0) {
+
+ IodVectorData->IntMask[0].all |= (1 << IodEisaIrrBit);
+// mdbfix - I2c not enabled
+// IodVectorData->IntMask[0].all |= (1 << IodI2cBusIrrBit);
+// IodVectorData->IntMask[0].all |= (1 << IodI2cCtrlIrrBit);
+ IodVectorData->IntMask[0].all |= (1 << IodEisaNmiIrrBit);
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) EISA & EISANMI to Target 0, CPU 0\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+#endif
+
+// mdbfix -
+#if 0
+ //
+ // Weight this Processor for EISA vectors KBD, MOUSE, etc.
+ //
+
+ PrimaryCpuVectorData->ListEntry.Weight++;
+#endif
+ }
+
+ //
+ // Initialize the affinity mask, target, and CPU vector link
+ //
+
+ IodVectorData->Affinity[0] |= 1;
+
+ IodVectorData->IntTarg[0] =
+ HalpLogicalToPhysicalProcessor[HAL_PRIMARY_PROCESSOR];
+
+ IodVectorData->TargetCpu[0] = PrimaryCpuVectorData;
+
+ }
+
+}
+
+
+ULONG
+HalpAssignInterruptForIod(
+ PIOD_VECTOR_DATA IodVectorData,
+ ULONG InterruptBit
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ IodVectorData - IOD to assign interrupt
+
+ InterruptBit - Interrupt bit in the IRR to set
+
+Return Value:
+
+ Return the logical CPU number assigned the interrupt
+
+--*/
+
+{
+ PCPU_VECTOR_DATA TargetCpu;
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ ULONG Target;
+ ULONG LogicalCpu;
+
+ McDeviceId = HalpIodLogicalToPhysical[IodVectorData->HwBusNumber];
+
+#if HALDBG
+
+ DbgPrint(
+ "Assigning IOD (%d, %d) Interrupt 0x%x\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ InterruptBit
+ );
+#endif
+
+ //
+ // If both of the target CPU's have not been assigned,
+ // assign them now.
+ //
+
+ if ( !IodVectorData->TargetCpu[0] || !IodVectorData->TargetCpu[1] ) {
+
+
+ for (Target = 0; Target < HalpNumberOfTargetCpus; Target++) {
+
+ if ((TargetCpu = IodVectorData->TargetCpu[Target]) == NULL) {
+
+ TargetCpu = (PCPU_VECTOR_DATA)
+ HalpFindWeightedEntry(
+ &HalpCpuVectorDataHead,
+ FindMinWeight
+ );
+
+ //
+ // Handle for UP and second target not assigned
+ //
+
+ if (TargetCpu == NULL) {
+
+ break;
+
+ }
+
+#if HALDBG
+ DbgPrint(
+ "IOD (%d, %d) Target %d assigned to CPU %d\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ Target,
+ TargetCpu->LogicalNumber
+ );
+#endif
+
+ LogicalCpu = TargetCpu->LogicalNumber;
+
+ //
+ // Initialize the affinity mask, target, and CPU vector link
+ //
+
+ IodVectorData->Affinity[Target] |= (1 << LogicalCpu);
+ IodVectorData->IntTarg[Target] =
+ HalpLogicalToPhysicalProcessor[LogicalCpu];
+ IodVectorData->TargetCpu[Target] = TargetCpu;
+
+ //
+ // Initialize the MC_DEVICE_ID for this target.
+ //
+
+
+ //
+ // Read the target register.
+ //
+
+ IntTarg.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg
+ );
+
+
+ //
+ // Obtain the Target assigned by Vector Balancing
+ //
+
+ if (Target) {
+
+ IntTarg.Int1TargDevId = (ULONG)
+ IodVectorData->IntTarg[Target].all;
+
+ } else {
+
+ IntTarg.Int1TargDevId = (ULONG)
+ IodVectorData->IntTarg[Target].all;
+
+ }
+
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ IntTarg.all
+ );
+
+ } else {
+
+ //
+ // Remove this entry from the list before assigning
+ // the next CPU
+ //
+
+ RemoveEntryList(&TargetCpu->ListEntry.ListEntry);
+
+ }
+ }
+
+ //
+ // Add the CPU's back to the global list.
+ //
+
+ for (Target = 0; Target < HalpNumberOfTargetCpus; Target++) {
+
+ if (IodVectorData->TargetCpu[Target]) {
+
+ InsertTailList(
+ &HalpCpuVectorDataHead,
+ &IodVectorData->TargetCpu[Target]->ListEntry.ListEntry
+ );
+
+ }
+ }
+
+ }
+
+ //
+ // Determine if the vector has already been assigned a target.
+ // If so, return the target cpu that is was assigned to.
+ // If not Choose the CPU with the minimum weight. The weight
+ // is an indication of how many PCI vectors have already been
+ // assigned to a CPU.
+ //
+
+ if ( (IodVectorData->TargetCpu[0] != NULL) &&
+ (IodVectorData->IntMask[0].all & InterruptBit) ) {
+
+ Target = 0;
+
+ } else if ( (IodVectorData->TargetCpu[1] != NULL) &&
+ (IodVectorData->IntMask[1].all & InterruptBit) ) {
+
+ Target = 1;
+
+ } else if ( !IodVectorData->TargetCpu[1] ) {
+
+ //
+ // If the second target CPU was not assigned,
+ // this is a UP system so choose target 0.
+ //
+
+ Target = 0;
+
+ } else if ( IodVectorData->TargetCpu[0]->ListEntry.Weight <
+ IodVectorData->TargetCpu[1]->ListEntry.Weight ) {
+
+ //
+ // Target 0 currently has a lower interrupt load
+ //
+
+ Target = 0;
+
+ } else {
+
+ //
+ // Target 1 currently has a lower interrupt load
+ //
+
+ Target = 1;
+
+ }
+
+ TargetCpu = IodVectorData->TargetCpu[Target];
+ LogicalCpu = TargetCpu->LogicalNumber;
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) Interrupt 0x%x to Target %d, CPU %d\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ InterruptBit,
+ Target,
+ TargetCpu->LogicalNumber
+ );
+
+#endif
+
+ //
+ // Enable this vector in the IOD Interrupt Mask
+ // This value is written later to the IntReq register
+ //
+
+ IodVectorData->IntMask[Target].all |= InterruptBit;
+
+ //
+ // Update the weight of the target CPU.
+ //
+
+ TargetCpu->ListEntry.Weight++;
+
+ return (LogicalCpu);
+
+}
+
+#if HALDBG
+//
+// Declare the lower-level routine used to read PCI config space
+//
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpDumpIoVectorAffinity(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Dump IO vector Affinity Assignment
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIOD_VECTOR_DATA IodVectorData;
+ PCPU_VECTOR_DATA CpuVectorData;
+ MC_DEVICE_ID McDeviceId;
+ MC_ENUM_CONTEXT mcCtx;
+ PCI_COMMON_CONFIG CommonConfig;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCIPBUSDATA BusContext;
+ RTL_BITMAP DevicePresent;
+ PCI_SLOT_NUMBER SlotNumber;
+ PLIST_ENTRY NextEntry;
+ ULONG HwBusNumber;
+ ULONG BusNumber;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ ULONG Target;
+
+
+ DbgPrint("Dump IOD VECTOR DATA\n\n");
+
+ //
+ // Traverse Iod Vector Data List
+ //
+
+ for (
+ NextEntry = HalpIodVectorDataHead.Flink;
+ NextEntry != &HalpIodVectorDataHead;
+ NextEntry = NextEntry->Flink
+ ) {
+
+
+ IodVectorData = (PIOD_VECTOR_DATA) NextEntry;
+ HwBusNumber = IodVectorData->HwBusNumber;
+ BusNumber = IodVectorData->BusNumber;
+ McDeviceId = HalpIodLogicalToPhysical[HwBusNumber];
+
+ DbgPrint(
+ "\n\nIod: Logical %d, Physical (%d, %d)\n\n",
+ HwBusNumber,
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+
+
+ BusHandler = HaliHandlerForBus(PCIBus,BusNumber);
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Use the device-present bitmap for this bus to query configuration
+ // Space for InterruptLine values.
+ //
+
+ //
+ // Initialize the device-present bitmap for this bus.
+ //
+
+ HalpInitializeBitMap(
+ &BusContext.DevicePresent,
+ BusContext.DevicePresentBits,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ //
+ // Copy the bitmap from the bus handler.
+ //
+
+ RtlCopyMemory(
+ &BusContext.DevicePresentBits,
+ &BusData->DevicePresentBits,
+ sizeof (BusData->DevicePresentBits)
+ );
+
+
+ //
+ // Starting with device 0, scan the device present
+ // bitmap.
+ //
+
+ DeviceNumber = 0;
+
+ DbgPrint("Devices Present on Bus:\n\n");
+
+ while ( (DeviceNumber =
+ HalpFindSetBitsAndClear(
+ &BusContext.DevicePresent,
+ 1,
+ DeviceNumber
+ ) ) != -1 ) {
+
+ DbgPrint("Device Number %d\n", DeviceNumber);
+
+ //
+ // Initialize the slot number.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function number.
+ //
+
+ for (FunctionNumber = 0;
+ FunctionNumber < PCI_MAX_FUNCTION;
+ FunctionNumber++) {
+
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the common configuration header.
+ //
+
+ HalpReadPCIConfig(
+ BusHandler,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If the Vendor ID is invalid, then no device is present
+ // at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+ if (FunctionNumber == 0) {
+ break;
+ }
+ continue;
+ }
+
+ DbgPrint(
+ "Device %d, Function %d\n",
+ DeviceNumber,
+ FunctionNumber
+ );
+
+ DbgPrint(
+ "VendorId 0x%x, InterruptLine 0x%x\n",
+ CommonConfig.VendorID,
+ CommonConfig.u.type0.InterruptLine
+ );
+
+ //
+ // If this is not a multi-function device, then terminate
+ // the function number loop.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+
+ } // for (FunctionNumber...)
+
+ } // while (DeviceNumber)
+
+
+ DbgPrint("\nIOD Targets:\n\n");
+
+ for (Target = 0; Target < IOD_MAX_INT_TARG; Target++) {
+
+ DbgPrint(
+ "DevId: (%d, %d), Mask: 0x%x\n",
+ IodVectorData->IntTarg[Target].Gid,
+ IodVectorData->IntTarg[Target].Mid,
+ IodVectorData->IntMask[Target].all
+ );
+
+ }
+
+ } //for (IodVectorData)
+
+ DbgPrint("\nDump CPU VECTOR DATA\n\n");
+
+ for (
+ NextEntry = HalpCpuVectorDataHead.Flink;
+ NextEntry != &HalpCpuVectorDataHead;
+ NextEntry = NextEntry->Flink
+ ) {
+
+
+ CpuVectorData = (PCPU_VECTOR_DATA) NextEntry;
+ McDeviceId =
+ HalpLogicalToPhysicalProcessor[CpuVectorData->LogicalNumber];
+
+ DbgPrint(
+ "Cpu: Logical %d Physical (%d,%d)\n",
+ CpuVectorData->LogicalNumber,
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+
+ }
+
+}
+
+#endif // HALDBG
diff --git a/private/ntos/nthals/halraw/alpha/rwintbal.h b/private/ntos/nthals/halraw/alpha/rwintbal.h
new file mode 100644
index 000000000..ba3d5fb0a
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwintbal.h
@@ -0,0 +1,200 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rwintbal.h
+
+Abstract:
+
+ This file contains definitions specific to the Rawhide platform
+
+Author:
+
+ Matthew Buchman 29-Nov-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RWINTBALH_
+#define _RWINTBALH_
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+//
+// Define the structures for assigning vector affinity
+//
+
+//
+// Generic weighted list. The weight field is used by the
+// affinity assignment algorithm when selecting IOD and CPU's
+//
+
+typedef struct _WEIGHTED_LIST_ENTRY {
+ LIST_ENTRY ListEntry;
+ LONG Weight;
+} WEIGHTED_LIST_ENTRY, *PWEIGHTED_LIST_ENTRY;
+
+//
+// Search Criteria enum for MAX/MIN search
+//
+
+typedef enum _WEIGHTED_SEARCH_CRITERIA {
+ FindMaxWeight,
+ FindMinWeight
+} WEIGHTED_SEARCH_CRITERIA, *PWEIGHTED_SEARC_CRITERIA;
+
+//
+// Define CPU vector information structure.
+//
+
+typedef struct _CPU_VECTOR_DATA {
+
+ WEIGHTED_LIST_ENTRY ListEntry; // Generic list
+ ULONG LogicalNumber; // Logical Id for this CPU
+
+} CPU_VECTOR_DATA, *PCPU_VECTOR_DATA;
+
+//
+// Define IOD vector data structure. This structure
+// contains information on devices present on an IOD, their
+// vectors, and shadow registers for IntReq and IntTarg
+//
+
+typedef struct _IOD_VECTOR_DATA {
+
+ WEIGHTED_LIST_ENTRY ListEntry; // Generic list
+
+ PCPU_VECTOR_DATA TargetCpu[2]; // Target CPU vector data
+
+ RTL_BITMAP VectorPresent[2]; // IOD device vectors present
+ RTL_BITMAP SharedVector[2]; // IOD device vectors shared
+ ULONG VectorPresentBits[2]; // bitmap storage
+ ULONG SharedVectorBits[2]; // bitmap storage
+ ULONG BusNumber; // Logical bus number for this IOD
+ ULONG HwBusNumber; // Physical bus number for this IOD
+ ULONG Affinity[2]; // Vector AFFINITY for targets 0/1
+ IOD_INT_MASK IntMask[2]; // Shadow of IOD IntMaskX
+ MC_DEVICE_ID IntTarg[2]; // Shadow of IOD IntTargX
+
+} IOD_VECTOR_DATA, *PIOD_VECTOR_DATA;
+
+
+typedef enum _IOD_IRR_BITS{
+
+ IodPci0IrrBit = 0,
+ IodPci1IrrBit = 1,
+ IodPci2IrrBit = 2,
+ IodPci3IrrBit = 3,
+ IodPci4IrrBit = 4,
+ IodPci5IrrBit = 5,
+ IodPci6IrrBit = 6,
+ IodPci7IrrBit = 7,
+ IodPci8IrrBit = 8,
+ IodPci9IrrBit = 9,
+ IodPci10IrrBit = 10,
+ IodPci11IrrBit = 11,
+ IodPci12IrrBit = 12,
+ IodPci13IrrBit = 13,
+ IodPci14IrrBit = 14,
+ IodPci15IrrBit = 15,
+ IodEisaIrrBit = 16,
+ IodScsiIrrBit = 16,
+ IodI2cCtrlIrrBit = 17,
+ IodI2cBusIrrBit = 18,
+ IodEisaNmiIrrBit = 21,
+ IodSoftErrIrrBit = 22,
+ IodHardErrIrrBit = 23
+
+} IOD_IRR_BITS, *PIOD_IRR_BITS;
+
+extern PIOD_VECTOR_DATA HalpIodVectorData;
+extern PCPU_VECTOR_DATA HalpCpuVectorData;
+
+extern MC_DEVICE_ID HalpProcessorMcDeviceId[];
+
+extern LIST_ENTRY HalpIodVectorDataHead;
+extern LIST_ENTRY HalpCpuVectorDataHead;
+
+//
+// Weighted list manipulation routines
+//
+
+PWEIGHTED_LIST_ENTRY
+HalpFindWeightedList(
+ PLIST_ENTRY ListHead,
+ WEIGHTED_SEARCH_CRITERIA SearchCriteria
+ );
+
+
+//
+// Rawhide interrupt routine prototypes.
+//
+
+#if 0
+VOID
+HalpFindAllPciVectors(
+ IN PCONFIGURATION_COMPONENT_DATA Root
+ );
+
+VOID
+HalpFindPciBusVectors(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PVOID ConfigurationData
+ );
+
+VOID
+HalpInitializeIoVectorAffinity(
+ PLOADER_PARAMETER_BLOCK AFFINITYerBlock
+ );
+
+VOID
+HalpBalanceIoVectorLoad(
+ PLIST_ENTRY pIodListHead
+ );
+
+VOID
+HalpBalanceVectorLoadForIod(
+ PIOD_VECTOR_DATA IodVectorData
+ );
+
+#endif
+
+VOID
+HalpInitializeVectorBalanceData(
+ VOID
+ );
+
+VOID
+HalpInitializeCpuVectorData(
+ ULONG LogicalCpu
+ );
+
+VOID
+HalpAssignPrimaryProcessorVectors(
+ PLIST_ENTRY
+ );
+
+ULONG
+HalpAssignInterruptForIod(
+ PIOD_VECTOR_DATA IodVectorData,
+ ULONG InterruptVector
+ );
+
+#ifdef HALDBG
+VOID
+HalpDumpIoVectorAffinity(
+ VOID
+ );
+#endif
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
+
+#endif //_RWINTBALH_
diff --git a/private/ntos/nthals/halraw/alpha/rwintsup.c b/private/ntos/nthals/halraw/alpha/rwintsup.c
new file mode 100644
index 000000000..53f546dc3
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwintsup.c
@@ -0,0 +1,2364 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Rawhide systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Eric Rehm (DEC) 26-July-1994
+ Adapted from Alcor module for Rawhide.
+
+--*/
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "rawhide.h"
+#include "pintolin.h"
+
+extern IOD_REGISTER_CLASS DumpIodFlag;
+
+//
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+
+KINTERRUPT HalpPciInterrupt;
+KINTERRUPT HalpEisaInterrupt;
+
+extern BOOLEAN HalpLogCorrectableErrors;
+
+//
+// The enable mask for all interrupts sourced from the IOD (all device
+// interrupts, and all from PCI). A "1" indicates the interrupt is enabled.
+//
+
+ULONG HalpIodInterruptMask[RAWHIDE_MAXIMUM_PCI_BUS][2] = {0};
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Declare the interrupt handler for the EISA bus. The interrupt dispatch
+// routine, HalpEisaDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following functions handle the PCI interrupts.
+//
+
+VOID
+HalpInitializeIodInterrupts(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Private prototypes
+
+VOID
+HalpRawhideDecodePciVector(
+ IN ULONG PciVector,
+ OUT PULONG PciBusNumber,
+ OUT PULONG InterruptLine
+ );
+
+
+ULONG
+HalpGetRawhidePciInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified PCI bus interrupt level and/or vector.
+ PCI vectors for rawhide are allocated starting with vector 0x40.
+ Vectors are assigned using the BusInterruptVector and the HwBusNumber.
+ One execption to this is NCR810 SCSI on PCI bus 1, which is always
+ allocated vector 0x32.
+
+ The HwBusNumber is encoded in the PCI vector by allocating vectors
+ in blocks of 16 (each IOD supports 16 PCI vectors) as shown below.
+
+ RawhidePciVectors:
+ 0x40 |-------------------|
+ | PCI 0 vectors |
+ |-------------------|
+ 0x50 | PCI 1 vectors |
+ |-------------------|
+ .
+ .
+ PCI interrupt routines may use the vector assigned to obtain the
+ PCI bus number and IRR bit as follows.
+
+ PciBus = (Vector - RawhidePciVectors) / 0x10
+ IrrBitShift = (Vector - RawhidePciVectors) % 0x10
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector
+ assigned to the device during PCI configuration
+ using the Pin-to-line table.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the PCI device.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PIOD_VECTOR_DATA IodVectorData;
+ PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+ ULONG LogicalProcessor;
+ ULONG TargetCpu;
+ ULONG MaskBit;
+ ULONG PciVector;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+
+ //
+ // NCR 810 on Bus 1 is a special case
+ //
+
+ if ( (BusInterruptVector == RawhideNcr810PinToLine) &&
+ (BusData->HwBusNumber == 1) ) {
+
+ PciVector = RawhideScsiVector;
+
+ } else {
+
+#if HALDBG
+ DbgPrint(
+ "HalpGetRawhidePciInterruptVector: Bus %d\n",
+ BusData->HwBusNumber
+ );
+#endif
+ //
+ // Build the rawhide vector.
+ //
+
+ PciVector = RawhidePciVectors;
+ PciVector += (BusData->HwBusNumber << 4);
+
+ //
+ // BusInterruptVectors are numbered 1-16, so
+ // subtract one to convert to table offset.
+ //
+
+ PciVector += (BusInterruptVector - 1);
+
+ //
+ // Rawhide Pin2Line table entries contain an arbitrary offset
+ // so that PCI InterruptLine values don't appear to conflict
+ // with EISA/ISA vectors reported by WINMSD.
+ //
+
+ PciVector -= RawhidePinToLineOffset;
+
+ }
+
+ //
+ // Decode the PCI bus number and interrupt line from the Vector
+ //
+
+ HalpRawhideDecodePciVector(PciVector, &PciBusNumber, &InterruptLine);
+
+#if HALDBG
+ DbgPrint(
+ "Vector 0x%x maps to PCI %d, InterruptLine %d\n",
+ PciVector,
+ PciBusNumber,
+ InterruptLine
+ );
+#endif
+
+ //
+ // Determine which IOD this interrupt is assigned to
+ // and obtain the IOD's geographic address.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Determine the IRR bit
+ //
+
+ MaskBit = (ULONG) 1<< InterruptLine;
+
+ //
+ // Obtain the IOD vector table entry
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Assign this vector to a CPU. This will update the target
+ // mask for this IOD as a side effect.
+ //
+
+ TargetCpu = HalpAssignInterruptForIod(IodVectorData, MaskBit);
+
+#if HALDBG
+ DbgPrint("HalpGetRawhidePCIVector: CPU %d\n", TargetCpu);
+#endif
+
+ //
+ // Assign affinity for all processors. This will cause
+ // the kernel to add an IDT entry for all processors.
+ // This is necessary if we are going to dynamically
+ // reassign the interrupt to a different processor at
+ // a later time.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ *Affinity = (1 << TargetCpu);
+
+#if HALDBG
+ DbgPrint(
+ "HalpGetRawhidePCIVector: vector 0x%x, Iqrl 0x%x, Affinity 0x%x\n",
+ PciVector,
+ *Irql,
+ *Affinity
+ );
+#endif
+
+ return ( PciVector );
+
+}
+
+
+ULONG
+HalpGetRawhideEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified Eisa/Isa interrupt level and/or vector.
+ Eisa vectors for rawhide are allocated starting at vector 0x20.
+ Vectors are assigned using the BusInterruptLevel.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG EisaVector;
+ PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Build the Eisa/Isa vector
+ //
+
+ EisaVector = RawhideEisaVectors;
+ EisaVector += BusInterruptLevel;
+
+ //
+ // Assign affinity for all processors. This will cause
+ // the kernel to add an IDT entry for all processors.
+ // This is necessary if we are going to dynamically
+ // reassign the interrupt to a different processor at
+ // a later time.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ *Affinity = (1 << HAL_PRIMARY_PROCESSOR);
+
+ return ( EisaVector );
+}
+
+
+ULONG
+HalpGetRawhideInternalInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified Internal Bus interrupt level.
+ Vectors are assigned using the BusInterruptLevel.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+ PIOD_VECTOR_DATA IodVectorData;
+ ULONG InternalVector;
+ ULONG TargetCpu;
+ ULONG MaskBit;
+
+ //
+ // Build the Eisa/Isa vector
+ //
+
+ InternalVector = RawhideInternalBusVectors;
+ InternalVector += BusInterruptLevel;
+
+ //
+ // The Soft Error has already been assigned
+ // to the primary processor.
+ //
+
+ if (InternalVector == RawhideSoftErrVector) {
+
+ TargetCpu = HAL_PRIMARY_PROCESSOR;
+
+ }
+
+ //
+ // The only other Internal device support by
+ // Rawhide is the I2c bus. This reside on PCI0.
+ //
+
+ else {
+
+ //
+ // Map the vector to an interrupt line.
+ //
+
+ switch (InternalVector) {
+
+ case RawhideI2cCtrlVector:
+
+ MaskBit = IodI2cCtrlIntMask;
+ break;
+
+ case RawhideI2cBusVector:
+
+ MaskBit = IodI2cBusIntMask;
+ break;
+
+ }
+
+ //
+ // Obtain PCI0 vector data
+ //
+
+ IodVectorData = HalpIodVectorData;
+
+ //
+ // Assign this vector to a CPU. This will update the target
+ // mask for this IOD as a side effect.
+ //
+
+ TargetCpu = HalpAssignInterruptForIod(IodVectorData, MaskBit);
+
+#if HALDBG
+ DbgPrint("HalpGetRawhideInternalVector: CPU %d\n", TargetCpu);
+#endif
+
+ }
+
+ //
+ // Assign the vector affinity.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ *Affinity = (1 << TargetCpu);
+
+#if HALDBG
+ DbgPrint(
+ "HalpGetRawhideInternalVector: vector 0x%x, Iqrl 0x%x, Affinity 0x%x\n",
+ InternalVector,
+ *Irql,
+ *Affinity
+ );
+#endif
+
+ return ( InternalVector );
+}
+
+
+BOOLEAN
+HalpInitializeRawhideInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the EISA interrupt controller; the Rawhide ESC's interrupt controller is
+ compatible with the EISA interrupt contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) RawhidePCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // Initialize the ESC's PICs for EISA interrupts.
+ //
+
+ HalpInitializeEisaInterrupts();
+
+ //
+ // Initialize the interrupt request masks for all IOD's
+ //
+
+ HalpMcBusEnumAndCall(HalpIodMask, HalpInitializeIodInterrupts);
+
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag);
+#endif
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+ Rawhide uses the Axp legacy ESC NMI vector.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IodIntMask;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeIodInterrupts(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+
+/*++
+
+Routine Description:
+
+ This enumeration routine is called during Phase 0 to assign the
+ Rawhide Error interrupts for the corresponding IOD to the Primary CPU.
+ The interrupts
+ are initialized as follows:
+
+ PCI - disabled
+ HardErr - DISABLED!!! //ecrfix enabled
+ SoftErr - disabled
+ Eisa - enabled (Bus 0 only)
+ EisaNmi - enabled (Bus 0 only)
+ I2c - disabled (Bus 0 only)
+
+ The logical bus is assigned from the static variable PciBusNumber, which is
+ incremented with each invokation.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical (Hardware) PCI Bus number.
+
+ Arguments - Variable Arguments. None for this routine.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ IOD_INT_MASK IntMask;
+ PVOID IntMaskQva;
+ ULONG Target;
+
+ //
+ // Disable MCI bus interrupts
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
+ );
+
+
+ //
+ // Clear all pending interrupts for this IOD
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
+ 0x0
+ );
+
+ //
+ // Clear interrupt request register (New for CAP Rev2.3)
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq,
+ IodIntMask
+ );
+
+ //
+ // Clear all pending EISA interrupts for IOD 0
+ //
+
+ if (PciBusNumber == 0) {
+
+ INTERRUPT_ACKNOWLEDGE((PVOID)IOD_PCI0_IACK_QVA);
+
+ }
+
+
+ // mdbfix - For now, target0 = CPU0, target1 = CPU1
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ HalpLogicalToPhysicalProcessor[0].all
+ );
+
+ //
+ // Write the mask bits for target 0 and 1
+ //
+
+ for (Target = 0; Target < 2; Target++) {
+
+ //
+ // Obtain the target IRR QVA
+ //
+
+ if (Target) {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
+
+ } else {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
+
+ }
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ //
+ // Initialize HardErr for all buses, but Eisa and EisaNmi
+ // only for Bus 0
+ //
+
+ if (PciBusNumber == 0) {
+
+ IntMask.all =
+ IodHardErrIntMask | IodSoftErrIntMask |
+ IodEisaIntMask |IodEisaNmiIntMask;
+
+ } else {
+
+ IntMask.all = IodHardErrIntMask | IodSoftErrIntMask;
+
+ }
+
+ if (Target ) {
+
+ IntMask.all = 0;
+
+ }
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+ HalpIodInterruptMask[PciBusNumber][Target] = IntMask.all;
+ }
+
+ //
+ // Enable Interrupts.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_ENABLE_IO_INT | IOD_INT_CTL_ENABLE_VECT_WRITE)
+ );
+}
+
+
+VOID
+HalpRawhideDecodePciVector(
+ IN ULONG PciVector,
+ OUT PULONG PciBusNumber,
+ OUT PULONG InterruptLine
+ )
+
+/*++
+
+Routine Description:
+
+ This decodes a PCI vector to obtain the PCI hardware bus number
+ and the InterruptLine.
+
+Arguments:
+
+ PciVector - Supplies the vector of the PCI interrupt that is disabled.
+
+ PciBusNumber - IOD number encoded in vector
+
+ InterruptLine - IRR interrupt bit number encoded in vector
+
+Return Value:
+
+ The PCI bus number and interrupt line are returned.
+
+--*/
+
+{
+ //
+ // Special case for NCR810 vector
+ //
+
+ if (PciVector == RawhideScsiVector) {
+
+ *PciBusNumber = RAWHIDE_SCSI_PCI_BUS;
+ *InterruptLine = IodScsiIrrBit;
+
+ } else {
+
+ //
+ // Extract the Pci bus number and Interrupt line from the vector
+ //
+
+ PciVector -= RawhidePciVectors;
+ *PciBusNumber = PciVector / IOD_PCI_VECTORS;
+ *InterruptLine = PciVector % IOD_PCI_VECTORS;
+
+ }
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Target = 0;
+
+ //
+ // Decode the PCI bus number and interrupt line from the vector
+ //
+
+ HalpRawhideDecodePciVector(Vector, &PciBusNumber, &InterruptLine);
+
+ //
+ // Determine which IOD this interrupt is assigned to
+ // and obtain the IOD's geographic address.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Determine the IRR bit
+ //
+
+ MaskBit = ~(1 << InterruptLine);
+
+ //
+ // Obtain the IOD vector table entry
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Determine the target CPU for this vector and
+ // obtain the cooresponding IntMask QVA
+ //
+
+ if (IodVectorData->IntMask[0].all & MaskBit) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else if (IodVectorData->IntMask[1].all & MaskBit) {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: Vector not assigned target\n");
+#endif
+ return;
+
+ }
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: Target %d\n", Target);
+#endif
+
+ //
+ // Unassign this vector in the IOD vector data
+ //
+
+ IodVectorData->IntMask[Target].all &= MaskBit;
+
+ //
+ // Decrement CPU vector weight
+ //
+
+ IodVectorData->TargetCpu[Target]->ListEntry.Weight--;
+
+ //
+ // Get the current state of the interrupt mask register, then clear
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpDisablePCIVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all &= MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpDisablePCIVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+ //
+ // Turn off this interrupt in the software mask
+ //
+
+ HalpIodInterruptMask[PciBusNumber][Target] &= MaskBit;
+
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Rawhide PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Affinity;
+ ULONG Target = 0;
+
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnablePciInterrupt: Vector 0x%x, Mode 0x%x\n",
+ Vector,
+ InterruptMode
+ );
+#endif
+
+ //
+ // The kernel will call this routine on the processor
+ // who will receive the interrupt
+ //
+
+ Affinity = ( 1 << PCR->Prcb->Number);
+
+ //
+ // Decode the PCI bus number and interrupt line from the Vector
+ //
+
+ HalpRawhideDecodePciVector(Vector, &PciBusNumber, &InterruptLine);
+
+#if HALDBG
+ DbgPrint(
+ "Vector 0x%x maps to PCI %d, InterruptLine %d\n",
+ Vector,
+ PciBusNumber,
+ InterruptLine
+ );
+#endif
+
+ //
+ // Determine which IOD this interrupt is assigned to
+ // and obtain the IOD's geographic address.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Determine the IRR bit
+ //
+
+ MaskBit = (ULONG) 1<< InterruptLine;
+
+ //
+ // Obtain the IOD vector table entry
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Obtain the Target CPU
+ //
+
+
+ if (IodVectorData->Affinity[0] == Affinity) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ }
+
+ //
+ // Handle the case where another device shares this interrupt line.
+ //
+
+ if ( HalpIodInterruptMask[PciBusNumber][Target] & MaskBit) {
+
+#if HALDBG
+ DbgPrint("Vector 0x%x already assigned\n", Vector);
+#endif
+
+ return;
+
+ }
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to enable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpEnablePCIVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all |= MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpEnablePCIVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag & IodInterruptRegisters);
+#endif
+
+ HalpIodInterruptMask[PciBusNumber][Target] |= MaskBit;
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnablePCIVector: Software Mask 0x%x\n",
+ HalpIodInterruptMask[PciBusNumber][Target]
+ );
+#endif
+}
+
+
+VOID
+HalpDisableInternalInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the Internal Bus interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the Internal Bus interrupt to disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Target = 0;
+
+ //
+ // Do not physically disable the Soft Error Vector because
+ // the HAL Correctable Error Handler must execute when
+ // a Soft Error occurs for system integrity.
+ //
+
+ if (Vector == RawhideSoftErrVector) {
+
+ HalpLogCorrectableErrors = FALSE;
+ return;
+
+ }
+
+ //
+ // Map the vector to an interrupt line.
+ //
+
+ switch (Vector) {
+
+ case RawhideI2cCtrlVector:
+
+ //
+ // I2C ctrl interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cCtrlIntMask;
+
+ break;
+
+
+ case RawhideI2cBusVector:
+
+ //
+ // I2C bus interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cBusIntMask;
+ break;
+
+
+ default:
+ return;
+
+ }
+
+ //
+ // Obtain the IOD geographic address for the PCI bus.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Obtain the IOD vector data for the PCI bus.
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Determine the target CPU for this vector and
+ // obtain the cooresponding IntMask QVA
+ //
+
+ if (IodVectorData->IntMask[0].all & MaskBit) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else if (IodVectorData->IntMask[1].all & MaskBit) {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: Vector not assigned target\n");
+#endif
+ return;
+
+ }
+
+#if HALDBG
+ DbgPrint("HalpDisableInteralInterrupt: Target %d\n", Target);
+#endif
+
+ //
+ // Unassign this vector in the IOD vector data
+ //
+
+ IodVectorData->IntMask[Target].all &= ~MaskBit;
+
+ //
+ // Decrement CPU vector weight
+ //
+
+ IodVectorData->TargetCpu[Target]->ListEntry.Weight--;
+
+ //
+ // Get the current state of the interrupt mask register, then clear
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpEnablePCIVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all &= ~MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpEnablePCIVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+ //
+ // Turn off this interrupt in the software mask
+ //
+
+ HalpIodInterruptMask[PciBusNumber][Target] &= ~MaskBit;
+
+}
+
+
+VOID
+HalpEnableInternalInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Internal Bus interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the Internal Bus interrupt that is enabled.
+
+ InterruptMode - Ignored. Rawhide device interrupts level sensitive.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Affinity;
+ ULONG Target = 0;
+
+
+ //
+ // Do not physically disable the Soft Error Vector because
+ // the HAL Correctable Error Handler must execute when
+ // a Soft Error occurs for system integrity.
+ //
+
+ if (Vector == RawhideSoftErrVector) {
+
+ HalpLogCorrectableErrors = TRUE;
+ return;
+
+ }
+
+ //
+ // The kernel will call this routine on the processor
+ // who will receive the interrupt
+ //
+
+ Affinity = ( 1 << PCR->Prcb->Number);
+
+ //
+ // Map the vector to an interrupt line.
+ //
+
+ switch (Vector) {
+
+ case RawhideI2cCtrlVector:
+
+ //
+ // I2C ctrl interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cCtrlIntMask;
+
+ break;
+
+ case RawhideI2cBusVector:
+
+ //
+ // I2C ctrl interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cBusIntMask;
+
+ break;
+
+
+ default:
+ return;
+
+ }
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnableInternalInterrupt: Vector 0x%x, Mode 0x%x\n",
+ Vector,
+ InterruptMode
+ );
+#endif
+
+
+#if HALDBG
+ DbgPrint(
+ "Vector 0x%x maps to PCI %d, InterruptLine %d\n",
+ Vector,
+ 0,
+ MaskBit
+ );
+#endif
+
+ //
+ // Obtain the IOD geographic address for the PCI bus.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Obtain the IOD vector table entry for the PCI bus.
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Determine the target CPU for this vector and
+ // obtain the cooresponding IntMask QVA
+ //
+
+ if (IodVectorData->Affinity[0] == Affinity) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ }
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to enable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpEnableInternalVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all |= MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpEnableInternalVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag & IodInterruptRegisters);
+#endif
+
+ HalpIodInterruptMask[PciBusNumber][Target] |= MaskBit;
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnableInternalVector: Software Mask 0x%x\n",
+ HalpIodInterruptMask[PciBusNumber][Target]
+ );
+#endif
+}
+
+
+#if HALDBG
+ULONG DeviceDispatchFlag = 0;
+
+#define DispatchPrint(_X_)\
+{ \
+ if (DeviceDispatchFlag) DbgPrint _X_; \
+} \
+
+#else
+
+#define DispatchPrint(_X_)
+
+#endif
+
+#ifdef FORCE_CORRECTABLE_ERROR
+ULONG DispatchSoftError = 0;
+#endif // FORCE_CORRECTABLE_ERROR
+
+
+#ifndef POSTED
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ IOD_POSTED_INTERRUPT IntReq;
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG PciIdtIndex;
+ ULONG VectorShift;
+ ULONG PciBusNumber;
+ ULONG Target = 0;
+ volatile IOD_PCI_REVISION IodRevision;
+
+ DispatchPrint(("HalpDeviceDispatch: enter\n"));
+
+ //
+ // Intialize enumerator.
+ //
+
+ HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Handle interrupts for each IOD as follows.
+ //
+ // 1. read interrupt request register for IOD
+ // 2. process pending EISA interrupt.
+ // 3. process all pending PCI interrupts.
+ // 4. acknowledge the interrupts serviced.
+ // 5. start over with next IOD.
+ //
+
+ PciBusNumber = 0;
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read in the interrupt register.
+ //
+
+ IntReq.all = READ_IOD_REGISTER_NEW(
+ mcCtx.McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntReq);
+
+ DispatchPrint((
+ "HalpDeviceDispatch: IOD 0x%x, IRR 0x%x\n",
+ mcCtx.McDeviceId.all,
+ IntReq.all
+ ));
+
+ // mdbfix - is this really necessary?
+ //
+ // Consider only those interrupts which are currently enabled.
+ //
+
+#if HALDBG
+ if ( IntReq.all !=
+ (IntReq.all & HalpIodInterruptMask[PciBusNumber][Target]) ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: IOD (%d, %d), IRR Unmasked 0x%x != IRR Masked 0x%x\n",
+ mcCtx.McDeviceId.Gid,
+ mcCtx.McDeviceId.Mid,
+ IntReq.all,
+ (IntReq.all & HalpIodInterruptMask[PciBusNumber][Target])
+ ));
+ }
+#endif
+
+ IntReq.all &= HalpIodInterruptMask[PciBusNumber][Target];
+
+ DispatchPrint((
+ "HalpDeviceDispatch: IRR masked 0x%x\n",
+ IntReq.all
+ ));
+
+ //
+ // If no interrupts pending, do not
+ // send INT ACK and skip to next bus.
+ //
+
+ if (IntReq.all == 0) {
+ PciBusNumber++;
+ continue;
+ }
+
+ //
+ // Handle Error Interrupts
+ //
+
+ if (IntReq.HardErr ) {
+
+ //
+ // Handle hard error interrupt
+ //
+#if HALDBG
+ DispatchPrint((
+ "Hard Error Interrupt on IOD (%d, %d)\n",
+ mcCtx.McDeviceId.Gid,
+ mcCtx.McDeviceId.Mid
+ ));
+#endif // HALDBG
+
+ HalpIodHardErrorInterrupt();
+
+ }
+
+ if ( IntReq.SoftErr ) {
+
+ //
+ // Dispatch Event logging interrupt.
+ //
+
+#if HALDBG
+ DispatchPrint((
+ "Soft Error Interrupt on IOD (%d, %d)\n",
+ mcCtx.McDeviceId.Gid,
+ mcCtx.McDeviceId.Mid
+ ));
+#endif // HALDBG
+
+#if 1
+// mdbfix - until an error log driver exists to connect the
+// soft error interrupt, explicitly call the ISR.
+
+ HalpIodSoftErrorInterrupt();
+
+#else
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideSoftErrVector];
+
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+#endif
+ }
+
+ //
+ // Process PCI interrupts.
+ //
+
+ if ( IntReq.Pci ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: PCI interrupt\n", IntReq.all
+ ));
+
+ //
+ // Initialize IDT offset to PCI vectors and obtain
+ // the vector table section for this PCI bus
+ //
+
+ PciIdtIndex = RawhidePciVectors + (PciBusNumber << 4);
+
+ VectorShift = IntReq.Pci;
+
+ while (VectorShift) {
+
+ if ( VectorShift & 0x1 ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: Dispatch PCI IDT Index %d\n",
+ PciIdtIndex
+ ));
+
+
+ //
+ // Map the Interrupt Request Register bit to a vector
+ //
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PciIdtIndex];
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+
+ }
+
+ //
+ // Try next vector
+ //
+
+ PciIdtIndex++;
+ VectorShift = VectorShift >> 1;
+
+ } //end while(VectorShift);
+
+ } //end if(IntReq.Pci);
+
+ //
+ // Handle bus 0 specific interrupts
+ //
+
+ if ( PciBusNumber == 0 ) {
+
+ if ( IntReq.Eisa ) {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ HalpEisaDispatch(
+ Interrupt,
+ (PVOID)IOD_PCI0_IACK_QVA,
+ TrapFrame
+ );
+
+ }
+
+ if (IntReq.I2cBus) {
+
+ //
+ // I2c Bus Vector
+ //
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cBusVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ if (IntReq.I2cCtrl) {
+
+ //
+ // I2c Controller Vector
+ //
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cCtrlVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ }
+
+ //
+ // Handle NCR810 for PCI bus 1
+ //
+
+ if ( ( PciBusNumber == 1 ) && ( IntReq.Ncr810 ) ) {
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[RawhideScsiVector];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+ }
+
+
+ //
+ // Acknowledge after All pending interrupts serviced for this IOD
+ // for UP interrupt scheme, all Interrupts routed to targe 0.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ mcCtx.McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
+ 0x0
+ );
+
+ //
+ // ecrfix - Read the IOD revision to force the write.
+ //
+
+ IodRevision.all =
+ READ_IOD_REGISTER_NEW(
+ mcCtx.McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision );
+
+
+ //
+ // Next PCI bus number
+ //
+
+ PciBusNumber++;
+
+ } //end while (HalpMcBusEnum())
+
+ return TRUE;
+
+}
+
+#else // POSTED
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PIOD_POSTED_INTERRUPT PostedInterrupts;
+ IOD_POSTED_INTERRUPT IntReq;
+ MC_DEVICE_ID McDeviceId;
+ PKPRCB Prcb;
+ PVOID IodAckQva;
+ ULONG PciIdtIndex;
+ ULONG VectorShift;
+ ULONG PciBusNumber;
+ ULONG Target = 0;
+ volatile IOD_PCI_REVISION IodRevision;
+
+ Prcb = PCR->Prcb;
+ PciIdtIndex = RawhidePciVectors;
+
+
+ //
+ // Obtain the processor area in IOD vector table
+ // and the IOD service mask.
+ //
+
+ PostedInterrupts = (PIOD_POSTED_INTERRUPT) HAL_PCR->PostedInterrupts;
+
+ DispatchPrint((
+ "DeviceDispatch: enter, IodVectorTable 0x%x\n",
+ PostedInterrupts
+ ));
+
+
+ //
+ // Handle interrupts for each IOD as follows.
+ //
+ // 1. read the interrupt vector table entry.
+ // 2. process pending EISA interrupt.
+ // 3. process all pending PCI interrupts.
+ // 4. acknowledge the interrupts serviced.
+ // 5. start over with next IOD.
+ //
+
+
+ for ( PciBusNumber = 0;
+ PciBusNumber < HalpNumberOfIods;
+ PciBusNumber++, PostedInterrupts++) {
+
+ DispatchPrint((
+ "DeviceDispatch: IntReq: 0x%x\n\tTarget: %d\n\tDevice: (%d, %d)",
+ PostedInterrupts->IntReq,
+ PostedInterrupts->Target,
+ (PostedInterrupts->McDevId >> 0x3) & 0x7,
+ PostedInterrupts->McDevId & 0x7
+ ));
+
+ //
+ // Perform a passive release.
+ //
+
+ if (PostedInterrupts->Valid && (PostedInterrupts->IntReq == 0) ) {
+
+ IntReq.all = PostedInterrupts->IntReq;
+ McDeviceId.all = PostedInterrupts->McDevId;
+
+ Target = PostedInterrupts->Target;
+
+ //
+ // Invalidate this entry to prevent the next device interrupt
+ // dispatch from using stale information. We must do this
+ // before the ACK, which allows the IOD to post.
+ //
+
+ PostedInterrupts->all = 0;
+
+ IOD_INTERRUPT_ACKNOWLEDGE(McDeviceId, Target);
+
+ //
+ // Skip to check next vector
+ //
+
+ continue;
+
+ }
+
+ if (PostedInterrupts->Valid && PostedInterrupts->IntReq) {
+
+ DispatchPrint((
+ "DeviceDispatch: Interrupt(s) Pending on PCI bus %d\n",
+ PciBusNumber
+ ));
+
+
+ IntReq.all = PostedInterrupts->IntReq;
+ McDeviceId.all = PostedInterrupts->McDevId;
+
+ Target = PostedInterrupts->Target;
+
+ DispatchPrint((
+ "DeviceDispatch: IodVectorTable\n\tIntReq: 0x%x\n\tTarget: %d\n\tDevice: (%d, %d)",
+ PostedInterrupts->IntReq,
+ PostedInterrupts->Target,
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ ));
+
+ //
+ // Consider only those interrupts which are currently enabled.
+ //
+
+ IntReq.all &= HalpIodInterruptMask[PciBusNumber][Target];
+
+ DispatchPrint((
+ "DeviceDispatch: IntReq (masked) 0x%x\n",
+ IntReq.all
+ ));
+
+ //
+ // Handle Error Interrupts
+ //
+
+ if (IntReq.HardErr ) {
+
+ //
+ // Handle hard error interrupt
+ //
+
+ DispatchPrint((
+ "Hard Error Interrupt on IOD (%d, %d)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ ));
+
+ HalpIodHardErrorInterrupt();
+
+ }
+
+ if ( IntReq.SoftErr ) {
+
+ //
+ // Dispatch Event logging interrupt.
+ //
+
+ DispatchPrint((
+ "Soft Error Interrupt on IOD (%d, %d)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ ));
+
+ HalpIodSoftErrorInterrupt();
+
+ }
+
+#ifdef FORCE_CORRECTABLE_ERROR
+ if ( (PCR->Number == HAL_PRIMARY_PROCESSOR) &&
+ DispatchSoftError ) {
+ DispatchSoftError = 0;
+ HalpIodSoftErrorInterrupt();
+ }
+#endif // FORCE_CORRECTABLE_ERROR
+
+ //
+ // Process PCI interrupts.
+ //
+
+ if ( IntReq.Pci ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: PCI interrupt\n", IntReq.all
+ ));
+
+ //
+ // Initialize IDT offset to PCI vectors and obtain
+ // the vector table section for this PCI bus
+ //
+
+ PciIdtIndex = RawhidePciVectors + (PciBusNumber << 4);
+
+ VectorShift = IntReq.Pci;
+
+ while (VectorShift) {
+
+ if ( VectorShift & 0x1 ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: Dispatch PCI IDT Index %d\n",
+ PciIdtIndex
+ ));
+
+
+ //
+ // Map the Interrupt Request Register bit to a vector
+ //
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PciIdtIndex];
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+
+ }
+
+ //
+ // Try next vector
+ //
+
+ PciIdtIndex++;
+ VectorShift = VectorShift >> 1;
+
+ } //end while(VectorShift);
+
+ } //end if(IntReq.Pci);
+
+ //
+ // Handle bus 0 specific interrupts
+ //
+
+ if ( PciBusNumber == 0 ) {
+
+ if ( IntReq.Eisa ) {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ HalpEisaDispatch(
+ Interrupt,
+ (PVOID)IOD_PCI0_IACK_QVA,
+ TrapFrame
+ );
+
+ }
+
+ //
+ // Handle I2c Bus Vector
+ //
+
+ if (IntReq.I2cBus) {
+
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cBusVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ //
+ // Handle I2c Controller Vector
+ //
+
+ if (IntReq.I2cCtrl) {
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cCtrlVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ }
+
+ //
+ // Handle NCR810 for PCI bus 1
+ //
+
+ if ( ( PciBusNumber == 1 ) && ( IntReq.Ncr810 ) ) {
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[RawhideScsiVector];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+ }
+
+ //
+ // Invalidate this entry to prevent the next device interrupt
+ // dispatch from using stale information. We must do this
+ // before the ACK, which allows the IOD to post.
+ //
+
+ PostedInterrupts->all = 0;
+
+ //
+ // Acknowledge the interrupt
+ //
+
+ IOD_INTERRUPT_ACKNOWLEDGE(McDeviceId, Target);
+
+ } //end if (PostedInterrupts.Valid && PostedInterrupts.IntReq)
+
+
+ } //end for
+
+ return TRUE;
+
+}
+
+#endif //POSTED
+
+
+VOID
+HalpAcknowledgeIpiInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the interprocessor interrupt on the current processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIOD_GENERAL_CSRS IodGeneralCsrs;
+ IOD_WHOAMI IodWhoAmI;
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceId;
+ volatile IOD_PCI_REVISION IodRevision;
+
+ PKPRCB Prcb;
+
+
+ //
+ // Avoid a WhoAmI register read by using the PCR
+ //
+
+ Prcb = PCR->Prcb;
+ McDeviceId.all = HalpLogicalToPhysicalProcessor[Prcb->Number].all;
+
+ //
+ // Acknownledge the ip interrupt by writing to our own
+ // ip interrupt acknowledge.
+ //
+
+ IP_INTERRUPT_ACKNOWLEDGE( McDeviceId );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halraw/alpha/rwref.h b/private/ntos/nthals/halraw/alpha/rwref.h
new file mode 100644
index 000000000..1b691e0e0
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwref.h
@@ -0,0 +1,109 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rwref.h
+
+Abstract:
+
+ This file defines the structures and definitions of the Rawhide
+ interrupt architecture.
+
+Author:
+
+ Matthew Buchman 18 Sept 1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _RAWREFH_
+#define _RAWREFH_
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// Layout of platform usable portion of vector table
+//
+
+enum _RAWHIDE_INTERRUPT_VECTORS {
+
+ //
+ // 16 Eisa/Isa vectors starting at vector 32.
+ //
+
+ RawhideEisaVectors = EISA_VECTORS, // Eisa base vector
+ RawhideIsaVectors = ISA_VECTORS, // Isa base vector
+
+ RawhideMaxEisaVector = MAXIMUM_EISA_VECTOR, // Maximum Eisa/Isa vector
+
+ //
+ // All buses, except bus 1, have 16 PCI vectors
+ // PciVector = 16*BusNumber + PinToLine(Slot, Interrupt)
+ //
+
+ RawhidePciVectors = PCI_VECTORS,
+
+ RawhidePci0Vectors = PCI_VECTORS, // PCI bus 0
+ RawhidePci1Vectors = (PCI_VECTORS + 0x10), // PCI bus 1
+ RawhidePci2Vectors = (PCI_VECTORS + 0x20), // PCI bus 2
+ RawhidePci3Vectors = (PCI_VECTORS + 0x30), // PCI bus 3
+
+ // One special case for PCI vectors is NCR810 Scsi on bus 1
+ // whereas MAXIMUM_PCI_VECTOR is unused on other platforms,
+ // we use it for this special case.
+
+ RawhideScsiVector = MAXIMUM_PCI_VECTOR, // NCR810 SCSI, bus 1
+
+ RawhideMaxPciVector = MAXIMUM_PCI_VECTOR, // Max Rawhide PCI vector
+
+ //
+ // Miscellaneous
+ //
+
+
+ RawhideHardErrVector, // IOD Hard Error
+
+ //
+ // Internal Bus Vectors
+ //
+
+ RawhideInternalBusVectors,
+
+ RawhideSoftErrVector = RawhideInternalBusVectors, // IOD Soft Error
+
+ RawhideI2cCtrlVector, // I^2C Controller, bus 0
+ RawhideI2cBusVector, // I^2C vector, bus 0
+
+ RawhideMaxInternalBusVector
+
+};
+
+#define IOD_PCI_VECTORS 0x10
+
+//
+// Internal Bus interrupt line values
+//
+// These line values allow device drivers to connect
+// to interrupts for the Correctable, I2C Bus, and I2C
+// controller interrupts. These interrupts are connected
+// via the internal bus for NT 3.51
+//
+
+enum _RAWHIDE_INTERNAL_BUS_INTERRUPT_LINE {
+
+ RawhideSoftErrInterruptLine, // IOD Soft Error
+ RawhideI2cCtrlInterruptLine, // I^2C Controller, bus 0
+ RawhideI2cBusInterruptLine // I^2C vector, bus 0
+
+};
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _RAWREFH_
diff --git a/private/ntos/nthals/halraw/alpha/rwsysint.c b/private/ntos/nthals/halraw/alpha/rwsysint.c
new file mode 100644
index 000000000..f3450c747
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwsysint.c
@@ -0,0 +1,501 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Alcor system.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableInternalInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableInternalInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt. Remember that, unlike other platforms,
+ // MAXIMUM_PCI_VECTOR is assigned rather than used as a place holder.
+ //
+
+ if (Vector >= RawhidePciVectors &&
+ Vector < RawhideMaxPciVector &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the Intenal bus
+ // interrupts, then disable the interrupt.
+ //
+
+ if (Vector >= RawhideInternalBusVectors &&
+ Vector <= RawhideMaxInternalBusVector &&
+ Irql == DEVICE_HIGH_LEVEL ) {
+ HalpDisableInternalInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+#if 0 // ecrfix
+ DbgPrint(
+ "HalEnableSystemInterrupt: Vector 0x%x, Irql 0x%x, InterruptMode 0x%x\n",
+ Vector,
+ Irql,
+ InterruptMode
+ );
+#endif
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Eisa Vector\n");
+#endif
+ HalpEnableEisaInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt. Remember, unlike other platforms,
+ // MAXIMUM_PCI_VECTOR is assigned rather than used as a place holder.
+ //
+
+ else if (Vector >= RawhidePciVectors &&
+ Vector <= RawhideMaxPciVector &&
+ Irql == DEVICE_HIGH_LEVEL) {
+
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Pci Vector\n");
+#endif
+ HalpEnablePciInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the Intenal bus
+ // interrupts.
+ //
+
+ if (Vector >= RawhideInternalBusVectors &&
+ Vector < RawhideMaxInternalBusVector &&
+ Irql == DEVICE_HIGH_LEVEL ) {
+
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Internal Vector\n");
+#endif
+ HalpEnableInternalInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Enabled = %s\n", Enabled?"TRUE":"FALSE");
+#endif
+
+ return Enabled;
+
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ ULONG Vector;
+
+#if HALDBG
+ DbgPrint("HalpGetSystemInterruptVector: Vector 0x%x\n", BusInterruptVector);
+#endif
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( InterfaceType == ProcessorInternal ) {
+
+ Vector = HalpGet21164PerformanceVector( BusInterruptLevel, Irql );
+
+ if( Vector != 0 ){
+
+ //
+ // Success
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ }
+
+ }
+
+ //
+ // Rawhide uses the Internal bus to make system management interupts
+ // visible to device drivers. The devices defined for the internal
+ // bus for Rawhide are the Correctable Error and the I2C Bus.
+ //
+
+ if( (InterfaceType == Internal) ) {
+
+
+#if HALDBG
+ DbgPrint("HalpGetSystemInterruptVector: Internal Vector\n");
+#endif
+
+ return HalpGetRawhideInternalInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ //
+ // Handle Isa/Eisa bus devices.
+ //
+ // N.B. The bus interrupt level is the actual E/ISA signal name for
+ // option boards while the bus interrupt level is the actual
+ // interrupt vector number for internal devices.
+ //
+
+ if( (InterfaceType == Isa) ||
+ (InterfaceType == Eisa) ){
+
+#if HALDBG
+ DbgPrint("HalpGetSystemInterruptVector: Eisa Vector\n");
+#endif
+
+ return HalpGetRawhideEisaInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ if( (InterfaceType == PCIBus) ) {
+#if HALDBG
+ DbgPrint(
+ "HalpGetSystemInterruptVector: PCIBUS, level 0x%x, vector 0x%x\n",
+ BusInterruptLevel,
+ BusInterruptVector
+ );
+#endif
+
+ return HalpGetRawhidePciInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+ }
+
+
+ //
+ // Not an interface supported on Alpha systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ MC_DEVICE_ID McDeviceId;
+ ULONG LogicalCpu;
+
+ //
+ // Scan the mask for logical CPU numbers
+ //
+
+ for (LogicalCpu=0; LogicalCpu< (HAL_MAXIMUM_PROCESSOR+1); LogicalCpu++) {
+
+ //
+ // The Logical to Geographic ID was saved
+ // in HalStartNextProcessor
+ //
+
+ if (Mask & 0x1) {
+
+ McDeviceId.all = HalpLogicalToPhysicalProcessor[LogicalCpu].all;
+
+ //
+ // Send the IP interrupt by writing to the
+ // IP interrupt for the Device Id.
+ //
+
+ IP_INTERRUPT_REQUEST( McDeviceId );
+ }
+
+ Mask = Mask >> 1;
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halraw/alpha/vga.c b/private/ntos/nthals/halraw/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halraw/bushnd.c b/private/ntos/nthals/halraw/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halraw/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halraw/dirs b/private/ntos/nthals/halraw/dirs
new file mode 100644
index 000000000..a2a38f0fd
--- /dev/null
+++ b/private/ntos/nthals/halraw/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up
+
+OPTIONAL_DIRS=mp
diff --git a/private/ntos/nthals/halraw/drivesup.c b/private/ntos/nthals/halraw/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halraw/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halraw/hal.rc b/private/ntos/nthals/halraw/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halraw/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halraw/hal.src b/private/ntos/nthals/halraw/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halraw/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halraw/mp/makefile b/private/ntos/nthals/halraw/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halraw/mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halraw/mp/makefile.inc b/private/ntos/nthals/halraw/mp/makefile.inc
new file mode 100644
index 000000000..a434415d9
--- /dev/null
+++ b/private/ntos/nthals/halraw/mp/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halrawmp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halraw/mp/sources b/private/ntos/nthals/halraw/mp/sources
new file mode 100644
index 000000000..18f050720
--- /dev/null
+++ b/private/ntos/nthals/halraw/mp/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halrawmp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DAXPRAW -DEISA_PLATFORM -DTAGGED_NVRAM -DPOSTED
+
+NT_UP=0
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha;..\..\halraw\alpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\alpha\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\bios.c \
+ ..\alpha\bitmap.c \
+ ..\alpha\cache.c \
+ ..\alpha\devintr.s \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\ev5cache.c \
+ ..\alpha\ev5int.c \
+ ..\alpha\ev5mchk.c \
+ ..\alpha\ev5mem.s \
+ ..\alpha\ev5prof.c \
+ ..\alpha\ev5ints.s \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\haltsup.s \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\memory.c \
+ ..\alpha\nvenv.c \
+ ..\alpha\nvram.c \
+ ..\alpha\pciesc.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\vga.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\iod.c \
+ ..\alpha\iodaddr.c \
+ ..\alpha\ioderr.c \
+ ..\alpha\iodio.s \
+ ..\alpha\iodmapio.c \
+ ..\alpha\rawerr.c \
+ ..\alpha\rwclock.c \
+ ..\alpha\rwinitnt.c \
+ ..\alpha\rwintbal.c \
+ ..\alpha\rwintsup.c \
+ ..\alpha\rwsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halraw/up/makefile b/private/ntos/nthals/halraw/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halraw/up/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halraw/up/makefile.inc b/private/ntos/nthals/halraw/up/makefile.inc
new file mode 100644
index 000000000..e06ce5247
--- /dev/null
+++ b/private/ntos/nthals/halraw/up/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halrawup.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halraw/up/sources b/private/ntos/nthals/halraw/up/sources
new file mode 100644
index 000000000..0caeb41eb
--- /dev/null
+++ b/private/ntos/nthals/halraw/up/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halrawup
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DAXPRAW -DEISA_PLATFORM -DTAGGED_NVRAM -DPOSTED
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha;..\..\halraw\alpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\alpha\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\bios.c \
+ ..\alpha\bitmap.c \
+ ..\alpha\cache.c \
+ ..\alpha\devintr.s \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\ev5cache.c \
+ ..\alpha\ev5int.c \
+ ..\alpha\ev5mchk.c \
+ ..\alpha\ev5mem.s \
+ ..\alpha\ev5prof.c \
+ ..\alpha\ev5ints.s \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\haltsup.s \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\memory.c \
+ ..\alpha\nvenv.c \
+ ..\alpha\nvram.c \
+ ..\alpha\pciesc.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\vga.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\iod.c \
+ ..\alpha\iodaddr.c \
+ ..\alpha\ioderr.c \
+ ..\alpha\iodio.s \
+ ..\alpha\iodmapio.c \
+ ..\alpha\rawerr.c \
+ ..\alpha\rwclock.c \
+ ..\alpha\rwinitnt.c \
+ ..\alpha\rwintbal.c \
+ ..\alpha\rwintsup.c \
+ ..\alpha\rwsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halsable/alpha/addrsup.c b/private/ntos/nthals/halsable/alpha/addrsup.c
new file mode 100644
index 000000000..93fdf47dd
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/addrsup.c
@@ -0,0 +1,883 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ tbaqva.c (addrsup.c)
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Sable system.
+
+Author:
+
+ Joe Notarangelo 26-Oct-1993
+ Steve Jenness 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUS_HANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUS_HANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber;
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on Sable are an EISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if ( (InterfaceType != Isa) &&
+ (InterfaceType != Eisa) &&
+ (InterfaceType != PCIBus) &&
+ (InterfaceType != Internal) ) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+#if HALDBG
+ DbgPrint( "HalTBA: Unhandled interface type = %x\n", InterfaceType );
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // BusData is valid only for the PCI bus.
+ //
+
+ if( (InterfaceType == PCIBus) &&
+ (BusHandler != NULL) &&
+ (BusHandler->BusData != NULL) ) {
+
+ BusNumber = ((PPCIPBUSDATA)(BusHandler->BusData))->HwBusNumber;
+
+ } else {
+
+ //
+ // smdfix: (What should we do here?)
+ // OH MY GOD! We didn't get any BusData. Default to 0.
+ //
+
+ BusNumber = 0;
+
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Internal:
+
+ //
+ // SMDFIX: Make Internal bus constraints the same as Isa.
+ //
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+
+ if( BusAddress.LowPart >= __16MB ) {
+
+#if HALDBG
+ DbgPrint ("Unsupported ISA address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ //
+ // else fall through.
+ //
+
+ } // case Isa
+
+ case Eisa:
+
+ //
+ // Eisa is the same as PCI, with respect to kernel mode
+ // sparse and dense space memory support, i.e., its a full
+ // 32 bit space, supports dense memory access.
+ //
+
+ case PCIBus: {
+
+ if( BusNumber == 0 ) {
+
+ //
+ // PCI 0 Bus support.
+ // PCI0_MAX_SPARSE_MEMORY_ADDRESS= 128MB-1
+ // PCI0_MIN_DENSE_MEMORY_ADDRESS = 128MB
+ // PCI0_MAX_DENSE_MEMORY_ADDRESS = 1GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI0_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 0 address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else
+ if( BusAddress.LowPart >= PCI0_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI0_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // offset
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI0_DENSE_MEMORY_PHYSICAL;
+
+ TranslatedAddress->QuadPart +=
+ (ULONGLONG)BusAddress.LowPart;
+
+ } else {
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI0_SPARSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ }
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will
+ // implicitly set AddressSpace to a 1. The caller then
+ // will not call MmMapIoSpace and will use the address
+ // we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } else { // if BusNumber == 0
+
+ //
+ // PCI 1 Bus support (64Bit Pci Bus).
+ // PCI1_MAX_SPARSE_MEMORY_ADDRESS = 64MB-1
+ // PCI1_MIN_DENSE_MEMORY_ADDRESS = 64MB
+ // PCI1_MAX_DENSE_MEMORY_ADDRESS = 1GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI1_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 1 address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else
+ if( BusAddress.LowPart >= PCI1_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI1_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // offset
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI1_DENSE_MEMORY_PHYSICAL;
+
+ TranslatedAddress->QuadPart +=
+ (ULONGLONG)BusAddress.LowPart;
+
+ } else {
+
+ //
+ // Start with the base physical address and add the bus
+ // address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI1_SPARSE_MEMORY_PHYSICAL;
+
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+
+ }
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly
+ // set AddressSpace to a 1. The caller then will not call
+ // MmMapIoSpace and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // if (BusNumber == 0)
+
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Eisa:
+
+ //
+ // Eisa is the same as ISA, with respect to kernel mode
+ // sparse I/O space support, i.e., it is a 16 bit sparse
+ // space.
+ //
+
+ case Internal:
+
+ //
+ // SMDFIX: Make Internal bus constraints the same as Isa.
+ //
+
+ case Isa: {
+
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+
+ if( BusAddress.LowPart >= __64K ){
+
+#if HALDBG
+ DbgPrint ("Unsupported ISA IO address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ //
+ // Fall through
+ //
+
+ } // case Isa
+
+ case PCIBus: {
+
+ if( BusNumber == 0 ) {
+
+ //
+ // PCI 0 Bus Support.
+ // PCI0_MAX_IO_ADDRESS = 16MB-1
+ //
+
+ if( BusAddress.LowPart >= PCI0_MAX_IO_ADDRESS ){
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 0 IO address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ } else {
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI0_SPARSE_IO_PHYSICAL;
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will
+ // implicitly set AddressSpace to a 1. The caller then
+ // will not call MmMapIoSpace and will use the address
+ // we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // Make sure user doesn't call MmMapIoSpace.
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+ }
+
+
+ } else { // if (BusNumber == 0)
+
+ //
+ // PCI 1 Bus Support.
+ // PCI1_MAX_SPARSE_IO_ADDRESS = 16MB-1
+ //
+
+ if( BusAddress.LowPart >= PCI1_MAX_SPARSE_IO_ADDRESS ){
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 1 IO address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ } else {
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI1_SPARSE_IO_PHYSICAL;
+//
+// smdfix:
+//
+// The above should actually check if this hal is running on a Lynx machine
+// since the location of PCI1_SPARSE_IO is different. For now we support
+// SABLE only.
+//
+// (LynxMachine)? LYNX_PCI1_SPARSE_IO_PHYSICAL: SABLE_PCI1_SPARSE_IO_PHYSICAL;
+//
+
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA that
+ // we'll return to the caller. Then we will implicitly
+ // set AddressSpace to a 1. The caller then will not
+ // call MmMapIoSpace and will use the address we return
+ // as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // Make sure user doesn't call MmMapIoSpace.
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+ }
+
+ } // if (BusNumber == 0)
+
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ if( BusNumber == 0 ) {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI0_SPARSE_MEMORY_PHYSICAL;
+ } else {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI1_SPARSE_MEMORY_PHYSICAL;
+ }
+
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ if( BusNumber == 0 ) {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI0_SPARSE_IO_PHYSICAL;
+ } else {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI1_SPARSE_IO_PHYSICAL;
+ }
+
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Make sure user can call MmMapIoSpace.
+ //
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ if( BusNumber == 0 ) {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI0_DENSE_MEMORY_PHYSICAL;
+ } else {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI1_DENSE_MEMORY_PHYSICAL;
+ }
+
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart);
+
+ //
+ // Let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+ }
+ } // switch (*AddressSpace)
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not an I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+ PVOID qva;
+
+ //
+ // Clear bit 35 (if present) for user mode address spaces.
+ //
+
+ if( VA != NULL ){
+ PA.QuadPart &= 0x83FFFFFFFF;
+ }
+
+ if( (PA.QuadPart >= SABLE_PCI0_SPARSE_MEMORY_PHYSICAL) &&
+ (PA.QuadPart < SABLE_PCI1_SPARSE_MEMORY_PHYSICAL) ||
+
+ (PA.QuadPart >= SABLE_PCI1_SPARSE_MEMORY_PHYSICAL) &&
+ (PA.QuadPart < SABLE_CBUS_CSRS_PHYSICAL) ||
+
+ (PA.QuadPart >= SABLE_PCI0_SPARSE_IO_PHYSICAL) &&
+ (PA.QuadPart < SABLE_PCI0_DENSE_MEMORY_PHYSICAL) ||
+
+ (PA.QuadPart >= SABLE_PCI1_SPARSE_IO_PHYSICAL) &&
+ (PA.QuadPart <=
+ SABLE_PCI1_SPARSE_IO_PHYSICAL + PCI1_MAX_SPARSE_IO_ADDRESS) ){
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+ else if( PA.QuadPart >= SABLE_PCI0_DENSE_MEMORY_PHYSICAL &&
+ PA.QuadPart <= SABLE_PCI0_DENSE_MEMORY_PHYSICAL +
+ PCI0_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // The physical address is within the 1 GB dense space of PCI bus 0.
+ //
+
+ if (VA == 0) {
+
+ //
+ // Kernel mode: create a QVA
+ //
+ // Subtract out physical address base.
+ // Now we just have the PCI 0 bus address.
+
+ PA.QuadPart -= SABLE_PCI0_DENSE_MEMORY_PHYSICAL;
+
+ // Add in the QVA base for PCI Bus 0
+
+ PA.QuadPart += SABLE_PCI0_DENSE_MEMORY_QVA;
+
+ qva = (PVOID) PA.LowPart;
+
+ return(qva);
+
+ } else {
+
+ //
+ // Use mode, return the VA as the QVA
+ //
+
+ return(VA);
+ }
+ }
+ else if( PA.QuadPart >= SABLE_PCI1_DENSE_MEMORY_PHYSICAL &&
+ PA.QuadPart <= SABLE_PCI1_DENSE_MEMORY_PHYSICAL +
+ PCI1_MAX_DENSE_MEMORY_ADDRESS) {
+
+ //
+ // The physical address is within the 2 GB dense space of PCI bus 1.
+ //
+
+ if (VA == 0) {
+
+ // Subtract out physical address base.
+ // Now we just have the PCI 1 bus address.
+
+ PA.QuadPart -= SABLE_PCI1_DENSE_MEMORY_PHYSICAL;
+
+ // Add in the QVA base for PCI Bus 1
+
+ PA.QuadPart += SABLE_PCI1_DENSE_MEMORY_QVA;
+
+ qva = (PVOID) PA.LowPart;
+
+ return(qva);
+
+ } else {
+
+ //
+ // Use mode, return the VA as the QVA
+ //
+
+ return(VA);
+ }
+ }
+
+ //
+ // It is not an I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Sable we have three supported bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+ break;
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/adjust.c b/private/ntos/nthals/halsable/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/allstart.c b/private/ntos/nthals/halsable/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/alphaio.s b/private/ntos/nthals/halsable/alpha/alphaio.s
new file mode 100644
index 000000000..efcac0fda
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/alphaio.s
@@ -0,0 +1,1332 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alphaio.s
+
+Abstract:
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ 12-Jul-1994 - Eric Rehm
+
+ Added dense space I/O
+
+ 27-July-1994 - Sameer Dekate
+
+ Make a common file for all machines and optimize Read/Write
+ register buffer routines. Made a common routine with different
+ entry points for READ & WRITE_REGISTER_BUFFER routines
+
+ 4-April-1995 - Sameer Dekate
+
+ Added support for PCI 1 dense space.
+
+--*/
+
+#include "chipset.h"
+#include "halalpha.h"
+
+
+
+ SBTTL( "Read I/O byte" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(READ_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ mb
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extbl v0, t3, v0 // get correct byte
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_UCHAR
+
+
+ SBTTL( "Read I/O word(16 bits)" )
+//++
+//
+// USHORT
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(READ_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // get the longword
+ extwl v0,t3,v0 // get the correct word
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extwl v0, t3, v0 // get correct word
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_USHORT
+
+
+ SBTTL( "Read I/O longword(32 bits)" )
+//++
+//
+// ULONG
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(READ_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // read the longword
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_ULONG
+
+ SBTTL( "Write I/O byte" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva,
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Writes a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ insbl a1,t3,t4 // put the byte in the correct position
+ stl t4, (t0) // write the byte
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+ insbl a1, t3, t2 // put byte into position
+ bis t1, t2, t1 // merge byte in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write I/O word (16 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva,
+// IN USHORT Value
+// )
+//
+// Routine Description:
+//
+// Writes a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1,t3,t2 // put the word in the correct place
+ stl t2, (t0) // write the word
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, t2 // put word into position
+ bis t1, t2, t1 // merge in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write I/O longword (32 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ stl a1, (a0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_ULONG
+
+
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ bne a2, 2b // while count != 0
+3:
+ ret zero, (ra) // return
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x4000 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ addl a1, 4, a1 // increment buffer
+ bne a2, 2b // while count != 0
+
+3:
+ ret zero, (ra) // return
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store to buffer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
diff --git a/private/ntos/nthals/halsable/alpha/bios.c b/private/ntos/nthals/halsable/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/busdata.c b/private/ntos/nthals/halsable/alpha/busdata.c
new file mode 100644
index 000000000..2e805db9c
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/busdata.c
@@ -0,0 +1,136 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/cache.c b/private/ntos/nthals/halsable/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/chipset.h b/private/ntos/nthals/halsable/alpha/chipset.h
new file mode 100644
index 000000000..93c34f79b
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/chipset.h
@@ -0,0 +1 @@
+#include "sable.h"
diff --git a/private/ntos/nthals/halsable/alpha/ebsgdma.c b/private/ntos/nthals/halsable/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/eeprom8k.c b/private/ntos/nthals/halsable/alpha/eeprom8k.c
new file mode 100644
index 000000000..c03d04c0d
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/eeprom8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eeprom8k.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/eisasup.c b/private/ntos/nthals/halsable/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/environ.c b/private/ntos/nthals/halsable/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4cache.c b/private/ntos/nthals/halsable/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4int.c b/private/ntos/nthals/halsable/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4ints.s b/private/ntos/nthals/halsable/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4mchk.c b/private/ntos/nthals/halsable/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4mem.s b/private/ntos/nthals/halsable/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4parit.c b/private/ntos/nthals/halsable/alpha/ev4parit.c
new file mode 100644
index 000000000..74c6d0d00
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4parit.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4parit.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4prof.c b/private/ntos/nthals/halsable/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/fwreturn.c b/private/ntos/nthals/halsable/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/haldebug.c b/private/ntos/nthals/halsable/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/halpal.s b/private/ntos/nthals/halsable/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/haltsup.s b/private/ntos/nthals/halsable/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/icic.c b/private/ntos/nthals/halsable/alpha/icic.c
new file mode 100644
index 000000000..7d853513a
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/icic.c
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ icic.c
+
+Abstract:
+
+ This module implements functions specific to the Interrupt
+ Controller IC (ICIC).
+
+Author:
+
+ Dave Richards 26-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "t2.h"
+#include "icic.h"
+
+
+ULONGLONG
+READ_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister
+ )
+
+/*++
+
+Routine Description:
+
+ Read a 64-bit value from an ICIC register.
+
+Arguments:
+
+ TxQva - The QVA of the T3/T4 CSR space.
+
+ IcIcRegister - The register number to read.
+
+Return Value:
+
+ The 64-bit value read.
+
+--*/
+
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)TxQva)->Air, IcIcRegister );
+
+ return READ_T2_REGISTER( &((PT2_CSRS)TxQva)->Dir );
+}
+
+
+VOID
+WRITE_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister,
+ IN ULONGLONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write a 64-bit value to an ICIC register.
+
+Arguments:
+
+ TxQva - The QVA of the T3/T4 CSR space.
+
+ IcIcRegister - The register number to write.
+
+ Value - The 64-bit value to write.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)TxQva)->Air, IcIcRegister );
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)TxQva)->Dir, Value );
+
+ (VOID)READ_T2_REGISTER( &((PT2_CSRS)TxQva)->Dir );
+}
diff --git a/private/ntos/nthals/halsable/alpha/icic.h b/private/ntos/nthals/halsable/alpha/icic.h
new file mode 100644
index 000000000..3c3407943
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/icic.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ icic.h
+
+Abstract:
+
+ This file defines the structures and definitions describing the
+ Interrupt Controller IC (ICIC).
+
+Author:
+
+ Dave Richards 23-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _ICICH_
+#define _ICICH_
+
+typedef enum _ICIC_REGISTER {
+ IcIcMaskRegister = 0x40,
+ IcIcElcrRegister = 0x50,
+ IcIcEisaRegister = 0x60,
+ IcIcModeRegister = 0x70
+} ICIC_REGISTER;
+
+typedef ULONGLONG ICIC_MASK_REGISTER, *PICIC_MASK_REGISTER;
+typedef ULONGLONG ICIC_ELCR_REGISTER, *PICIC_ELCR_REGISTER;
+typedef ULONGLONG ICIC_EISA_REGISTER, *PICIC_EISA_REGISTER;
+
+typedef union _ICIC_MODE_REGISTER {
+ struct {
+ ULONGLONG Mode: 1;
+ ULONGLONG Reset: 1;
+ ULONGLONG Reserved: 62;
+ };
+ ULONGLONG all;
+} ICIC_MODE_REGISTER, *PICIC_MODE_REGISTER;
+
+ULONGLONG
+READ_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister
+ );
+
+VOID
+WRITE_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister,
+ IN ULONGLONG Value
+ );
+
+#endif // _ICICH_
diff --git a/private/ntos/nthals/halsable/alpha/idle.s b/private/ntos/nthals/halsable/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/info.c b/private/ntos/nthals/halsable/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/inithal.c b/private/ntos/nthals/halsable/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/intsup.s b/private/ntos/nthals/halsable/alpha/intsup.s
new file mode 100644
index 000000000..4716cba36
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "sablertc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/ioproc.c b/private/ntos/nthals/halsable/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/iousage.c b/private/ntos/nthals/halsable/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/lyintsup.c b/private/ntos/nthals/halsable/alpha/lyintsup.c
new file mode 100644
index 000000000..b9f6486dc
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/lyintsup.c
@@ -0,0 +1,517 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ lyintsup.c
+
+Abstract:
+
+ This module provides interrupt support for the Lynx family
+ Standard I/O board.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "t2.h"
+#include "icic.h"
+#include "xiintsup.h"
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// Cached copies of the corresponding ICIC registers.
+//
+
+ICIC_ELCR_REGISTER LynxIcIcElcrRegister;
+ICIC_MASK_REGISTER LynxIcIcMaskRegister;
+
+
+ULONG
+HalpGetLynxSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ *Irql = DEVICE_LEVEL;
+ *Affinity = HAL_CPU0_MASK;
+
+ switch( BusInterruptLevel ){
+
+ case EisaInterruptLevel3:
+ return( LynxEisaIrq3Vector );
+
+ case EisaInterruptLevel4:
+ return( LynxEisaIrq4Vector );
+
+ case EisaInterruptLevel5:
+ return( LynxEisaIrq5Vector );
+
+ case EisaInterruptLevel6:
+ return( LynxEisaIrq6Vector );
+
+ case EisaInterruptLevel7:
+ return( LynxEisaIrq7Vector );
+
+ case EisaInterruptLevel9:
+ return( LynxEisaIrq9Vector );
+
+ case EisaInterruptLevel10:
+ return( LynxEisaIrq10Vector );
+
+ case EisaInterruptLevel11:
+ return( LynxEisaIrq11Vector );
+
+ case EisaInterruptLevel12:
+ return( LynxEisaIrq12Vector );
+
+ case EisaInterruptLevel14:
+ return( LynxEisaIrq14Vector );
+
+ case EisaInterruptLevel15:
+ return( LynxEisaIrq15Vector );
+
+ //
+ // Handle Vectors for the Internal bus devices.
+ //
+
+ case LynxMouseVector:
+ case LynxKeyboardVector:
+ case LynxFloppyVector:
+ case LynxSerialPort1Vector:
+ case LynxParallelPortVector:
+ case LynxSerialPort0Vector:
+ case LynxI2cVector:
+
+ //
+ // Handle Vectors for PCI devices.
+ //
+
+ case LynxScsi0Vector:
+ case LynxScsi1Vector:
+ case LynxPciSlot0AVector:
+ case LynxPciSlot0BVector:
+ case LynxPciSlot0CVector:
+ case LynxPciSlot0DVector:
+ case LynxPciSlot1AVector:
+ case LynxPciSlot1BVector:
+ case LynxPciSlot1CVector:
+ case LynxPciSlot1DVector:
+ case LynxPciSlot2AVector:
+ case LynxPciSlot2BVector:
+ case LynxPciSlot2CVector:
+ case LynxPciSlot2DVector:
+ case LynxPciSlot3AVector:
+ case LynxPciSlot3BVector:
+ case LynxPciSlot3CVector:
+ case LynxPciSlot3DVector:
+ case LynxPciSlot4AVector:
+ case LynxPciSlot4BVector:
+ case LynxPciSlot4CVector:
+ case LynxPciSlot4DVector:
+ case LynxPciSlot5AVector:
+ case LynxPciSlot5BVector:
+ case LynxPciSlot5CVector:
+ case LynxPciSlot5DVector:
+ case LynxPciSlot6AVector:
+ case LynxPciSlot6BVector:
+ case LynxPciSlot6CVector:
+ case LynxPciSlot6DVector:
+ case LynxPciSlot7AVector:
+ case LynxPciSlot7BVector:
+ case LynxPciSlot7CVector:
+ case LynxPciSlot7DVector:
+
+ return( BusInterruptLevel );
+
+ default:
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpGetXioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+#else
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+#endif
+
+ }
+}
+
+
+BOOLEAN
+HalpInitializeLynxSioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the ICIC on the Standard I/O module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE.
+
+--*/
+
+{
+ T2_ICE Ice;
+ ICIC_EISA_REGISTER LynxIcIcEisaRegister;
+
+ //
+ // Initialize the interface between the T3/T4 and the ICIC.
+ //
+
+ Ice.all = 0;
+ Ice.EisaFlushAddress = 0x542;
+ Ice.IcEnable = 1;
+ Ice.HalfSpeedEnable = 0;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Ice,
+ Ice.all );
+
+ //
+ // Initialize the ICIC Mask Register.
+ //
+
+ LynxIcIcMaskRegister = (ULONGLONG)-1;
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
+ LynxIcIcMaskRegister );
+
+ //
+ // Initialize the ICIC Edge/Level Control Register.
+ //
+
+ LynxIcIcElcrRegister =
+ ((ICIC_ELCR_REGISTER)1 << (LynxScsi0Vector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxScsi1Vector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3DVector - LynxBaseVector));
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcElcrRegister,
+ LynxIcIcElcrRegister );
+
+ //
+ // Initialize the ICIC EISA Register.
+ //
+
+ LynxIcIcEisaRegister =
+ (1 << (LynxEisaIrq3Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq4Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq5Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq6Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq7Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq9Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq10Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq11Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq12Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq14Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq15Vector - LynxBaseVector));
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcEisaRegister,
+ LynxIcIcEisaRegister );
+
+ //
+ // Initialize the ICIC Mode Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcModeRegister, (ULONGLONG)0 );
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpLynxSioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dispatches interrupts received by the Standard I/O
+ ICIC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the interrupt was handled by
+ the FLIH/SLIH.
+
+--*/
+
+{
+ T2_VAR Var;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ BOOLEAN ReturnValue;
+
+ //
+ // Get the interrupt vector.
+ //
+
+ Var.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Var );
+
+ //
+ // If this is a passive release, ignore the interrupt.
+ //
+
+ if( Var.PassiveRelease == 1 ){
+
+ return(TRUE);
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[LynxBaseVector + Var.Vector];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ ReturnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Send an SEOI.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Var, Var.Vector );
+
+ return(ReturnValue);
+}
+
+VOID
+HalpDisableLynxSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables interrupts associated with the Standard I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= LynxBaseVector) &&
+ (Vector <= LynxPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - LynxBaseVector);
+
+ //
+ // Mask the interrupt.
+ //
+
+ LynxIcIcMaskRegister |= IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
+ LynxIcIcMaskRegister );
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ HalpDisableXioInterrupt( Vector );
+
+#endif
+
+ }
+}
+
+BOOLEAN
+HalpEnableLynxSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables interrupts associated with the Standard I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to enable.
+
+ InterruptMode - An indication of whether the interrupt should
+ be edge-triggered/level-sensitive.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= LynxBaseVector) &&
+ (Vector <= LynxPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - LynxBaseVector);
+
+ //
+ // For EISA interrupts InterruptMode indicates whether the interrupt
+ // is level sensitive (active low) or edge-triggered (low-to-high).
+ // We use this information to update the Edge/Level Control Register
+ // bit for this IRQ.
+ //
+
+ switch( Vector ){
+
+ case LynxEisaIrq3Vector:
+ case LynxEisaIrq4Vector:
+ case LynxEisaIrq5Vector:
+ case LynxEisaIrq6Vector:
+ case LynxEisaIrq7Vector:
+ case LynxEisaIrq9Vector:
+ case LynxEisaIrq10Vector:
+ case LynxEisaIrq11Vector:
+ case LynxEisaIrq12Vector:
+ case LynxEisaIrq14Vector:
+ case LynxEisaIrq15Vector:
+
+ //
+ // Set/Clear the ELCR bit (as appropriate).
+ //
+
+ if( InterruptMode == LevelSensitive ){
+ LynxIcIcElcrRegister |= IrqMask;
+ } else {
+ LynxIcIcElcrRegister &= ~IrqMask;
+ }
+
+ //
+ // Update the ICIC Edge/Level Control Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcElcrRegister,
+ LynxIcIcElcrRegister );
+
+ break;
+
+ }
+
+ //
+ // Un-mask the interrupt.
+ //
+
+ LynxIcIcMaskRegister &= ~IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
+ LynxIcIcMaskRegister );
+
+ return TRUE;
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpEnableXioInterrupt( Vector, InterruptMode );
+
+#endif
+
+ }
+
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halsable/alpha/lyintsup.h b/private/ntos/nthals/halsable/alpha/lyintsup.h
new file mode 100644
index 000000000..0f43e9b0d
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/lyintsup.h
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ lyintsup.h
+
+Abstract:
+
+ This header file contains prototypes for lyintsup.c.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+ULONG
+HalpGetLynxSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpInitializeLynxSioInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpLynxSioDispatch(
+ VOID
+ );
+
+VOID
+HalpDisableLynxSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEnableLynxSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
diff --git a/private/ntos/nthals/halsable/alpha/lynxref.h b/private/ntos/nthals/halsable/alpha/lynxref.h
new file mode 100644
index 000000000..5275062ff
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/lynxref.h
@@ -0,0 +1,111 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ lynxref.h
+
+Abstract:
+
+ This file defines the structures and definitions of the Lynx
+ interrupt architecture.
+
+Author:
+
+ Dave Richards 12-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _LYNXREFH_
+#define _LYNXREFH_
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+enum _LYNX_INTERRUPT_VECTORS {
+
+ LynxBaseVector = 0x80, // Lynx/SIO Base Vector
+ LynxReservedVector = 0x80, //
+ LynxIcIcIrq0 = 0x80, //
+ LynxIcIcIrq1, //
+ LynxIcIcIrq2, // ESC interrupt
+ LynxMouseVector, // Mouse
+ LynxIcIcIrq4, //
+ LynxIcIcIrq5, //
+ LynxKeyboardVector, // Keyboard
+ LynxFloppyVector, // Floppy
+ LynxSerialPort1Vector, // Serial port 1 (COM2)
+ LynxParallelPortVector, // Parallel port
+ LynxEisaIrq3Vector, // EISA IRQ 3
+ LynxEisaIrq4Vector, // EISA IRQ 4
+ LynxEisaIrq5Vector, // EISA IRQ 5
+ LynxEisaIrq6Vector, // EISA IRQ 6
+ LynxEisaIrq7Vector, // EISA IRQ 7
+ LynxSerialPort0Vector, // Serial port 0 (COM1)
+ LynxEisaIrq9Vector, // EISA IRQ 9
+ LynxEisaIrq10Vector, // EISA IRQ 10
+ LynxEisaIrq11Vector, // EISA IRQ 11
+ LynxEisaIrq12Vector, // EISA IRQ 12
+ LynxIcIcIrq20, //
+ LynxEisaIrq14Vector, // EISA IRQ 14
+ LynxEisaIrq15Vector, // EISA IRQ 15
+ LynxI2cVector, // I^2C
+ LynxScsi0Vector = 0x98, // SCSI
+ RmLpLynxEthVector = 0x98, // RM/LP (Spanky) on-board Tulip
+ LynxIcIcIrq25, //
+ LynxIcIcIrq26, //
+ LynxIcIcIrq27, //
+ LynxScsi1Vector, // SCSI
+ LynxIcIcIrq29, //
+ LynxIcIcIrq30, //
+ LynxIcIcIrq31, //
+ LynxPciSlot4AVector, // PCI Slot 4 A
+ LynxPciSlot4BVector, // PCI Slot 4 B
+ LynxPciSlot4CVector, // PCI Slot 4 C
+ LynxPciSlot4DVector, // PCI Slot 4 D
+ LynxPciSlot5AVector, // PCI Slot 5 A
+ LynxPciSlot5BVector, // PCI Slot 5 B
+ LynxPciSlot5CVector, // PCI Slot 5 C
+ LynxPciSlot5DVector, // PCI Slot 5 D
+ LynxPciSlot6AVector, // PCI Slot 6 A
+ LynxPciSlot6BVector, // PCI Slot 6 B
+ LynxPciSlot6CVector, // PCI Slot 6 C
+ LynxPciSlot6DVector, // PCI Slot 6 D
+ LynxPciSlot7AVector, // PCI Slot 7 A
+ LynxPciSlot7BVector, // PCI Slot 7 B
+ LynxPciSlot7CVector, // PCI Slot 7 C
+ LynxPciSlot7DVector, // PCI Slot 7 D
+ LynxPciSlot0AVector, // PCI Slot 0 A
+ LynxPciSlot0BVector, // PCI Slot 0 B
+ LynxPciSlot0CVector, // PCI Slot 0 C
+ LynxPciSlot0DVector, // PCI Slot 0 D
+ LynxPciSlot1AVector, // PCI Slot 1 A
+ LynxPciSlot1BVector, // PCI Slot 1 B
+ LynxPciSlot1CVector, // PCI Slot 1 C
+ LynxPciSlot1DVector, // PCI Slot 1 D
+ LynxPciSlot2AVector, // PCI Slot 2 A
+ LynxPciSlot2BVector, // PCI Slot 2 B
+ LynxPciSlot2CVector, // PCI Slot 2 C
+ LynxPciSlot2DVector, // PCI Slot 2 D
+ LynxPciSlot3AVector, // PCI Slot 3 A
+ LynxPciSlot3BVector, // PCI Slot 3 B
+ LynxPciSlot3CVector, // PCI Slot 3 C
+ LynxPciSlot3DVector, // PCI Slot 3 D
+
+};
+
+//
+// The following variable indicates whether this is a Lynx platform.
+//
+
+extern BOOLEAN HalpLynxPlatform;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _LYNXREFH_
diff --git a/private/ntos/nthals/halsable/alpha/machdep.h b/private/ntos/nthals/halsable/alpha/machdep.h
new file mode 100644
index 000000000..c88134e44
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Sable platform-specific definitions.
+//
+
+#include "sable.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halsable/alpha/memory.c b/private/ntos/nthals/halsable/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcibus.c b/private/ntos/nthals/halsable/alpha/pcibus.c
new file mode 100644
index 000000000..2f8eb2b84
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcibus.c
@@ -0,0 +1,118 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ BOOLEAN BusIsAcrossPPB;
+
+ BusIsAcrossPPB = ((PPCIPBUSDATA)(BusHandler->BusData))->BusIsAcrossPPB;
+
+ //
+ // If the bus is across a PCI-to-PCI bridge use type 1 configuration
+ // cycles, otherwise use type 0.
+ //
+
+ if( BusIsAcrossPPB ){
+
+ return PciConfigType1;
+
+ } else {
+
+ return PciConfigType0;
+
+ }
+}
+
+VOID
+HalpPCIConfigAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+ ULONG HwBusNumber;
+
+ HwBusNumber = ((PPCIPBUSDATA)(BusHandler->BusData))->HwBusNumber;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if( ConfigType == PciConfigType0 ){
+
+ //
+ // Initialize pPciAddr for a type 0 configuration cycle. Device
+ // number is mapped to address bits 11:24, which are wired to the
+ // IDSEL pins.
+ //
+
+ if( HwBusNumber == 0 ){
+
+ pPciAddr->u.AsULONG = (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI0_CONFIGURATION_PHYSICAL));
+
+ } else {
+
+ pPciAddr->u.AsULONG = (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI1_CONFIGURATION_PHYSICAL));
+ }
+
+ pPciAddr->u.AsULONG += (1 << (Slot.u.bits.DeviceNumber + 11));
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+ } else {
+
+ //
+ // Initialize pPciAddr for a type 1 configuration cycle.
+ //
+
+ pPciAddr->u.AsULONG = 0;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+ if( HwBusNumber == 0 ){
+
+ pPciAddr->u.AsULONG += (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI0_CONFIGURATION_PHYSICAL));
+
+ } else {
+
+ pPciAddr->u.AsULONG += (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI1_CONFIGURATION_PHYSICAL));
+
+ }
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halsable/alpha/pcisup.c b/private/ntos/nthals/halsable/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcrtc.c b/private/ntos/nthals/halsable/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcrtc.h b/private/ntos/nthals/halsable/alpha/pcrtc.h
new file mode 100644
index 000000000..f4d1bff50
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcrtc.h
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ d1287rtc.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the Dallas 1287 Toy clock.
+
+Author:
+
+ David N. Cutler (davec) 3-May-1991
+ Jeff McLeman (mcleman) 4-Jun-1992
+
+Revision History:
+
+ 94.01.16 Steve Jenness
+
+ Split out the Dallas RTC definitions from the platform specific
+ RTC definitions.
+
+--*/
+
+#ifndef _D1287RTC_
+#define _D1287RTC_
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _SABLERTC_
diff --git a/private/ntos/nthals/halsable/alpha/pcserial.c b/private/ntos/nthals/halsable/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcspeakr.c b/private/ntos/nthals/halsable/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/perf8254.c b/private/ntos/nthals/halsable/alpha/perf8254.c
new file mode 100644
index 000000000..5fade7e42
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/perf8254.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perf8254.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pintolin.h b/private/ntos/nthals/halsable/alpha/pintolin.h
new file mode 100644
index 000000000..d0cd18244
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pintolin.h
@@ -0,0 +1,544 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston (Digital) 23-June-1994
+
+ Extracted Sable table from common.
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Changed EB66PCIPinToLineTable for pass2 of the module.
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang and EB66, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the SablePCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+#if 0
+
+//
+// The following PinToLineTable is used with old
+// Standard I/O boards that didn't have the 5th 8259.
+// The 5th 8259 (Slave 3) was added to break out the
+// PCI A,B,C,D interrupts to separate interrupt pins.
+//
+
+ULONG OldSablePCIPinToLineTable[][4] = {
+ { EthernetPortVector, // Virtual Slot 0 = PCI_AD[11] Tulip
+ EthernetPortVector,
+ EthernetPortVector,
+ EthernetPortVector },
+
+ { ScsiPortVector, // Virtual Slot 1 = PCI_AD[12] SCSI
+ ScsiPortVector,
+ ScsiPortVector,
+ ScsiPortVector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] Eisa Bridge
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] Not used
+
+ { OldPciSlot0Vector, // Virtual Slot 6 = PCI_AD[17] Phys. Slot #0
+ OldPciSlot0Vector,
+ OldPciSlot0Vector,
+ OldPciSlot0Vector },
+
+ { OldPciSlot1Vector, // Virtual Slot 7 = PCI_AD[18] Phys. Slot #1
+ OldPciSlot1Vector,
+ OldPciSlot1Vector,
+ OldPciSlot1Vector },
+
+ { OldPciSlot2Vector, // Virtual Slot 8 = PCI_AD[19] Phys. Slot #2
+ OldPciSlot2Vector,
+ OldPciSlot2Vector,
+ OldPciSlot2Vector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] Not used
+ { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 10 = PCI_AD[21] Not used
+};
+
+#endif
+
+//
+// Interrupt Vector Table Mapping for Sable (PCI 0)
+//
+
+ULONG SablePinToLineTable[][4] = {
+ { EthernetPortVector, // Virtual Slot 0 = PCI_AD[11] Tulip
+ EthernetPortVector,
+ EthernetPortVector,
+ EthernetPortVector },
+
+ { ScsiPortVector, // Virtual Slot 1 = PCI_AD[12] SCSI
+ ScsiPortVector,
+ ScsiPortVector,
+ ScsiPortVector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] Eisa Bridge
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] Not used
+
+ { PciSlot0AVector, // Virtual Slot 6 = PCI_AD[17] Phys. Slot #0
+ PciSlot0BVector,
+ PciSlot0CVector,
+ PciSlot0DVector },
+
+ { PciSlot1AVector, // Virtual Slot 7 = PCI_AD[18] Phys. Slot #1
+ PciSlot1BVector,
+ PciSlot1CVector,
+ PciSlot1DVector },
+
+ { PciSlot2AVector, // Virtual Slot 8 = PCI_AD[19] Phys. Slot #2
+ PciSlot2BVector,
+ PciSlot2CVector,
+ PciSlot2DVector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] Not used
+ { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 10 = PCI_AD[21] Not used
+};
+
+//
+// Interrupt Vector Table Mapping for Lynx (PCI 0)
+//
+
+ULONG LynxPinToLineTable1[][4] = {
+
+ { LynxReservedVector, // Virtual slot 0 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 1 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 2 - PCI-EISA Bridge
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 3 - PCI-PCI Bridge
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxScsi0Vector, // Virtual slot 4 - NCRC810A
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 5 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxPciSlot4AVector, // Virtual slot 6 - PCI slot 4
+ LynxPciSlot4BVector,
+ LynxPciSlot4CVector,
+ LynxPciSlot4DVector },
+
+ { LynxPciSlot5AVector, // Virtual slot 7 - PCI slot 5
+ LynxPciSlot5BVector,
+ LynxPciSlot5CVector,
+ LynxPciSlot5DVector },
+
+ { LynxPciSlot6AVector, // Virtual slot 8 - PCI slot 6
+ LynxPciSlot6BVector,
+ LynxPciSlot6CVector,
+ LynxPciSlot6DVector },
+
+ { LynxPciSlot7AVector, // Virtual slot 9 - PCI slot 7
+ LynxPciSlot7BVector,
+ LynxPciSlot7CVector,
+ LynxPciSlot7DVector },
+
+ { LynxReservedVector, // Virtual slot 10 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector }
+};
+
+ULONG LynxPinToLineTable2[][4] = {
+ { RmLpLynxEthVector, // Virtual slot 0 - dc21040 for RM/LP
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxScsi1Vector, // Virtual slot 1 - NCRC810A (SCSI)
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 2 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 3 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 4 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 5 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxPciSlot0AVector, // Virtual slot 6 - PCI slot 0
+ LynxPciSlot0BVector,
+ LynxPciSlot0CVector,
+ LynxPciSlot0DVector },
+
+ { LynxPciSlot1AVector, // Virtual slot 7 - PCI slot 1
+ LynxPciSlot1BVector,
+ LynxPciSlot1CVector,
+ LynxPciSlot1DVector },
+
+ { LynxPciSlot2AVector, // Virtual slot 8 - PCI slot 2
+ LynxPciSlot2BVector,
+ LynxPciSlot2CVector,
+ LynxPciSlot2DVector },
+
+ { LynxPciSlot3AVector, // Virtual slot 9 - PCI slot 3
+ LynxPciSlot3BVector,
+ LynxPciSlot3CVector,
+ LynxPciSlot3DVector },
+
+ { LynxReservedVector, // Virtual slot 10 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 11 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 12 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 13 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 14 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 15 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector }
+};
+
+#ifdef XIO_PASS1
+
+//
+// Interrupt Vector Table Mapping for XIO (Pass 1)
+//
+
+ULONG XioPinToLineTable[][4] = {
+ { XioReservedVector, // Virtual slot 0 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioPciSlot0AVector, // Virtual Slot 1 = PCI Slot 0
+ XioPciSlot0BVector,
+ XioPciSlot0CVector,
+ XioPciSlot0DVector },
+
+ { XioPciSlot1AVector, // Virtual Slot 2 = PCI Slot 1
+ XioPciSlot1BVector,
+ XioPciSlot1CVector,
+ XioPciSlot1DVector }
+};
+
+#endif // XIO_PASS1
+
+#ifdef XIO_PASS2
+
+//
+// Interrupt Vector Table Mapping for XIO (Pass 2)
+//
+
+ULONG XioPinToLineTable1[][4] = {
+ { XioReservedVector, // Virtual slot 0 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 1 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 2 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 3 - PCI-PCI Bridge
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 4 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 5 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioPciSlot4AVector, // Virtual slot 6 - PCI slot 4
+ XioPciSlot4BVector,
+ XioPciSlot4CVector,
+ XioPciSlot4DVector },
+
+ { XioPciSlot5AVector, // Virtual slot 7 - PCI slot 5
+ XioPciSlot5BVector,
+ XioPciSlot5CVector,
+ XioPciSlot5DVector },
+
+ { XioPciSlot6AVector, // Virtual slot 8 - PCI slot 6
+ XioPciSlot6BVector,
+ XioPciSlot6CVector,
+ XioPciSlot6DVector },
+
+ { XioPciSlot7AVector, // Virtual slot 9 - PCI slot 7
+ XioPciSlot7BVector,
+ XioPciSlot7CVector,
+ XioPciSlot7DVector },
+
+ { XioReservedVector, // Virtual slot 10 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector }
+};
+
+ULONG XioPinToLineTable2[][4] = {
+ { XioReservedVector, // Virtual slot 0 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 1 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 2 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 3 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 4 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 5 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioPciSlot0AVector, // Virtual slot 6 - PCI slot 0
+ XioPciSlot0BVector,
+ XioPciSlot0CVector,
+ XioPciSlot0DVector },
+
+ { XioPciSlot1AVector, // Virtual slot 7 - PCI slot 1
+ XioPciSlot1BVector,
+ XioPciSlot1CVector,
+ XioPciSlot1DVector },
+
+ { XioPciSlot2AVector, // Virtual slot 8 - PCI slot 2
+ XioPciSlot2BVector,
+ XioPciSlot2CVector,
+ XioPciSlot2DVector },
+
+ { XioPciSlot3AVector, // Virtual slot 9 - PCI slot 3
+ XioPciSlot3BVector,
+ XioPciSlot3CVector,
+ XioPciSlot3DVector },
+
+ { XioReservedVector, // Virtual slot 10 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 11 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 12 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 13 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 14 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 15 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector }
+};
+
+#endif // XIO_PASS2
diff --git a/private/ntos/nthals/halsable/alpha/sable.h b/private/ntos/nthals/halsable/alpha/sable.h
new file mode 100644
index 000000000..52989dc94
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sable.h
@@ -0,0 +1,519 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sable.h
+
+Abstract:
+
+ This file defines the structures and definitions common to all
+ sable-based platforms.
+
+Author:
+
+ Joe Notarangelo 26-Oct-1993
+ Steve Jenness 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _SABLEH_
+#define _SABLEH_
+
+
+#include "sableref.h" // Sable reference I/O structure
+#include "lynxref.h" // Lynx interrupt structure
+#include "xioref.h" // XIO interrupt structure
+#if !defined(_LANGUAGE_ASSEMBLY)
+#include "errframe.h"
+#endif
+
+//
+// Constants used by dense space I/O routines
+//
+
+#define SABLE_PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc03c0000000
+#define SABLE_PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc0180000000
+
+#define PCI_DENSE_BASE_PHYSICAL_SUPERPAGE \
+ (SABLE_PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE - SABLE_PCI0_DENSE_MEMORY_QVA)
+
+#define PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE \
+ (SABLE_PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE - SABLE_PCI1_DENSE_MEMORY_QVA)
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+#include "t2.h" // T2 chipset definitions
+#include "icic.h" // ICIC definitions
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | (ULONG)(PA >> IO_BIT_SHIFT) ) )
+
+
+
+//
+// Define physical address spaces for SABLE.
+//
+// PCI0 - 32bit PCI bus
+// PCI1 - 64bit PCI bus
+//
+
+#define SABLE_PCI1_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x180000000)
+#define SABLE_PCI1_SPARSE_IO_PHYSICAL ((ULONGLONG)0x1C0000000)
+#define SABLE_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x200000000)
+#define SABLE_PCI1_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x300000000)
+
+#define SABLE_CBUS_CSRS_PHYSICAL ((ULONGLONG)0x380000000)
+#define SABLE_CPU0_CSRS_PHYSICAL ((ULONGLONG)0x380000000)
+#define SABLE_CPU1_CSRS_PHYSICAL ((ULONGLONG)0x381000000)
+#define SABLE_CPU2_CSRS_PHYSICAL ((ULONGLONG)0x382000000)
+#define SABLE_CPU3_CSRS_PHYSICAL ((ULONGLONG)0x383000000)
+#define SABLE_CPU0_IPIR_PHYSICAL ((ULONGLONG)0x380000160)
+#define SABLE_CPU1_IPIR_PHYSICAL ((ULONGLONG)0x381000160)
+#define SABLE_CPU2_IPIR_PHYSICAL ((ULONGLONG)0x382000160)
+#define SABLE_CPU3_IPIR_PHYSICAL ((ULONGLONG)0x383000160)
+#define SABLE_MEM0_CSRS_PHYSICAL ((ULONGLONG)0x388000000)
+#define SABLE_MEM1_CSRS_PHYSICAL ((ULONGLONG)0x389000000)
+#define SABLE_MEM2_CSRS_PHYSICAL ((ULONGLONG)0x38A000000)
+#define SABLE_MEM3_CSRS_PHYSICAL ((ULONGLONG)0x38B000000)
+#define SABLE_T2_CSRS_PHYSICAL ((ULONGLONG)0x38E000000)
+#define SABLE_T4_CSRS_PHYSICAL ((ULONGLONG)0x38F000000)
+#define T2_CSRS_QVA (HAL_MAKE_QVA(SABLE_T2_CSRS_PHYSICAL))
+#define T4_CSRS_QVA (HAL_MAKE_QVA(SABLE_T4_CSRS_PHYSICAL))
+
+#define SABLE_PCI0_CONFIGURATION_PHYSICAL ((ULONGLONG)0x390000000)
+#define SABLE_PCI1_CONFIGURATION_PHYSICAL ((ULONGLONG)0x398000000)
+#define SABLE_PCI0_SPARSE_IO_PHYSICAL ((ULONGLONG)0x3A0000000)
+#define SABLE_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x3C0000000)
+
+//
+// Define the limits of User mode Sparse and Dense space:
+//
+
+#define SABLE_USER_PCI1_DENSE_MEMORY_PHYSICAL (ULONGLONG)0x180000000
+#define SABLE_USER_PCI1_SPARSE_IO_PHYSICAL (ULONGLONG)0x1C0000000
+#define SABLE_USER_PCI1_SPARSE_IO_END_PHYSICAL (ULONGLONG)0x1E0000000
+#define SABLE_USER_PCI0_SPARSE_MEMORY_PHYSICAL (ULONGLONG)0x200000000
+#define SABLE_USER_PCI0_SPARSE_MEMORY_END_PHYSICAL (ULONGLONG)0x300000000
+#define SABLE_USER_PCI1_SPARSE_MEMORY_PHYSICAL (ULONGLONG)0x300000000
+#define SABLE_USER_PCI1_SPARSE_MEMORY_END_PHYSICAL (ULONGLONG)0x380000000
+#define SABLE_USER_PCI0_SPARSE_IO_PHYSICAL (ULONGLONG)0x3A0000000
+#define SABLE_USER_PCI0_SPARSE_IO_END_PHYSICAL (ULONGLONG)0x3C0000000
+#define SABLE_USER_PCI0_DENSE_MEMORY_PHYSICAL (ULONGLONG)0x3C0000000
+
+#define SABLE_EDGE_LEVEL_CSRS_PHYSICAL ((ULONGLONG)0x3A00004C0)
+#define SABLE_INTERRUPT_CSRS_PHYSICAL ((ULONGLONG)0x3A000A640)
+#define XIO_INTERRUPT_CSRS_PHYSICAL ((ULONGLONG)0x1C0000530)
+#define XIO_INTERRUPT_CSRS_QVA (HAL_MAKE_QVA(XIO_INTERRUPT_CSRS_PHYSICAL))
+
+//
+// Define Interrupt Controller CSRs.
+//
+
+#define SABLE_EDGE_LEVEL_CSRS_QVA (HAL_MAKE_QVA(SABLE_EDGE_LEVEL_CSRS_PHYSICAL))
+#define SABLE_INTERRUPT_CSRS_QVA (HAL_MAKE_QVA(SABLE_INTERRUPT_CSRS_PHYSICAL))
+
+//
+// Define the XIO_VECTOR <CIRQL1>
+//
+
+#define XIO_VECTOR UNUSED_VECTOR
+
+
+//
+// Define CPU CSRs and masks.
+//
+
+#define SABLE_CPU0_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU0_CSRS_PHYSICAL))
+#define SABLE_CPU1_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU1_CSRS_PHYSICAL))
+#define SABLE_CPU2_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU2_CSRS_PHYSICAL))
+#define SABLE_CPU3_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU3_CSRS_PHYSICAL))
+#define SABLE_MEM0_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM0_CSRS_PHYSICAL))
+#define SABLE_MEM1_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM1_CSRS_PHYSICAL))
+#define SABLE_MEM2_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM2_CSRS_PHYSICAL))
+#define SABLE_MEM3_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM3_CSRS_PHYSICAL))
+
+#define SABLE_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define SABLE_SECONDARY_PROCESSOR ((ULONG)0x1)
+#define SABLE_MAXIMUM_PROCESSOR ((ULONG)0x3)
+#define HAL_PRIMARY_PROCESSOR (SABLE_PRIMARY_PROCESSOR)
+#define HAL_MAXIMUM_PROCESSOR (SABLE_MAXIMUM_PROCESSOR)
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (275)
+
+enum {
+ NoError,
+ UncorrectableError,
+ CorrectableError
+} ErrorType;
+
+//
+// Define the list of CSR's...
+//
+
+typedef struct _SABLE_CPU_CSRS {
+ UCHAR Bcc; // B-Cache Control Register
+ UCHAR Bcce; // B-Cache Correctable Error Register
+ UCHAR Bccea; // B-Cache Correctable Error Address Register
+ UCHAR Bcue; // B-Cache Uncorrectable Error Register
+ UCHAR Bcuea; // B-Cache Uncorrectable Error Address Register
+ UCHAR Dter; // Duplicate Tag Error Register
+ UCHAR Cbctl; // System Bus Control Register
+ UCHAR Cb2; // System Bus Error Register
+ UCHAR Cbeal; // System Bus Error Address Low Register
+ UCHAR Cbeah; // System Bus Error Address High Register
+ UCHAR Pmbx; // Processor Mailbox Register
+ UCHAR Ipir; // Inter-Processor Interrupt Request Register
+ UCHAR Sic; // System Interrupt Clear Register
+ UCHAR Adlk; // Address Lock Register
+ UCHAR Madrl; // Miss Address Register
+ UCHAR Crrevs; // C4 Revision Register
+} SABLE_CPU_CSRS, *PSABLE_CPU_CSRS;
+
+//
+// Define the System Bus Control Register
+//
+
+typedef struct _SABLE_CBCTL_CSR{
+ ULONG DataWrongParity: 1; // 0
+ ULONG CaWrongParity: 2; // 1
+ ULONG EnableParityCheck: 1; // 3
+ ULONG ForceShared: 1; // 4
+ ULONG CommaderId: 3; // 5
+ ULONG Reserved0: 3; // 8
+ ULONG EnableCbusErrorInterrupt: 1; // 11
+ ULONG Reserved1: 1; // 12
+ ULONG SecondQuadwordSelect: 1; // 13
+ ULONG SelectDrack: 1; // 14
+ ULONG Reserved2: 17; // 15
+
+ ULONG DataWrongParityHigh: 1; // 32
+ ULONG CaWrongParityHigh: 2; // 33
+ ULONG EnableParityCheckHigh: 1; // 35
+ ULONG ForceSharedHigh: 1; // 36
+ ULONG CommanderIdHigh: 3; // 37
+ ULONG Reserved3: 3; // 40
+ ULONG EnableCbusErrorInterruptHigh: 1; // 43
+ ULONG DisableBackToBackArbitration: 1; // 44
+ ULONG SecondQuadwordSelectHigh: 1; // 45
+ ULONG SelectDrackHigh: 1; // 46
+ ULONG Reserved4: 17; // 47
+} SABLE_CBCTL_CSR, *PSABLE_CBCTL_CSR;
+
+//
+// Define all the System Bus (CobraBus or CBus) Control and Error Registers
+// listed above: Bcc, Bcce, Bccea, Bcue, Bcuea
+//
+
+typedef struct _SABLE_BCACHE_BCC_CSR0 {
+ union {
+ ULONG EnableAllocateL: 1; // 0
+ ULONG ForceFillSharedL: 1; // 1
+ ULONG EnbTagParCheckL: 1; // 2
+ ULONG FillWrongTagParL: 1; // 3
+ ULONG FillWrongContolParL: 1; // 4
+ ULONG FillWrongDupTagStoreParL: 1; // 5
+ ULONG EnableCorrectableErrorInterruptL: 1; // 6
+ ULONG EnableEDCCorrectionL: 1; // 7
+ ULONG EnableEDCCheckL: 1; // 8
+ ULONG EnableBCacheConditionIOUpdatesL: 1; // 9
+ ULONG DisableBlockWriteAroundL: 1; // 10
+ ULONG EnableBCacheInitL: 1; // 11
+ ULONG ForceEDCControlL: 1; // 12
+ ULONG SharedDirtyValidL: 3; // 13-15
+ ULONG EDCL: 14; // 16-29
+ ULONG Reserved1: 1; // 30
+ ULONG CacheSizeL: 1; // 31
+
+ ULONG EnableAllocateH: 1; // 32
+ ULONG ForceFillSharedH: 1; // 33
+ ULONG EnbTagParCheckH: 1; // 34
+ ULONG FillWronTagParH: 1; // 35
+ ULONG FillWrongContolParH: 1; // 36
+ ULONG FillWrongDupTagStoreParH: 1; // 37
+ ULONG EnableCorrectableErrorInterruptH: 1; // 38
+ ULONG EnableEDCCorrectionH: 1; // 39
+ ULONG EnableEDCCheckH: 1; // 40
+ ULONG EnableBCacheConditionIOUpdatesH: 1; // 41
+ ULONG DisableBlockWriteAroundH: 1; // 42
+ ULONG EnableBCacheInitH: 1; // 43
+ ULONG ForceEDCControlH: 1; // 44
+ ULONG SharedDirtyValidH: 3; // 45-47
+ ULONG EDCH: 14; // 48-61
+ ULONG Reserved2: 1; // 62
+ ULONG CacheSizeH: 1; // 63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCC_CSR0, *PSABLE_BCACHE_BCC_CSR0;
+
+//
+// Define the Backup Cache correctable error register
+//
+
+typedef struct _SABLE_BCACHE_BCCE_CSR1 {
+ union {
+ ULONG Reserved1: 2; // 0-1
+ ULONG MissedCorrectableError: 1; // 2
+ ULONG CorrectableError: 1; // 3
+ ULONG Reserved2: 4; // 4-7
+ ULONG ControlBitParity: 1; // 8
+ ULONG Shared: 1; // 9
+ ULONG Dirty: 1; // 10
+ ULONG Valid: 1; // 11
+ ULONG Reserved3: 5; // 12-16
+ ULONG EDCError1: 1; // 17
+ ULONG EDCSyndrome0: 7; // 18-24
+ ULONG EDCSyndrome2: 7; // 25-31
+ ULONG Reserved4: 2; // 32-33
+ ULONG MissedCorrectableErrorH: 1; // 34
+ ULONG CorrectableErrorH: 1; // 35
+ ULONG Undefined: 13; // 36-48
+ ULONG EDCError2: 1; // 49
+ ULONG EDCSyndrome1: 7; // 50-56
+ ULONG EDCSyndrome3: 7; // 57-63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCCE_CSR1, *PSABLE_BCACHE_BCCE_CSR1;
+
+
+//
+// Define the Backup Cache correctable error address register
+//
+
+typedef struct _SABLE_BCACHE_BCCEA_CSR2 {
+ union {
+ ULONG BcacheMapOffsetL: 17; // 0-16
+ ULONG Reserved1: 1; // 17
+ ULONG TagParityL: 1; // 18
+ ULONG TagValueL: 12; // 19-30
+ ULONG Reserved2: 1; // 31
+ ULONG BcacheMapOffsetH: 17; // 32-48
+ ULONG Reserved3: 1; // 49
+ ULONG TagParityH: 1; // 50
+ ULONG TagValueH: 12; // 51-62
+ ULONG Reserved4: 1; // 63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCCEA_CSR2, *PSABLE_BCACHE_BCCEA_CSR2;
+
+//
+// Define the Backup Cache uncorrectable error register
+//
+
+typedef struct _SABLE_BCACHE_BCUE_CSR3 {
+ union {
+ ULONG MissedParErrorL: 1; // 0
+ ULONG ParityErrorL: 1; // 1
+ ULONG MissedUncorrectableErrorL: 1; // 2
+ ULONG UncorrectableErrorL: 1; // 3
+ ULONG Reserved1: 4; // 4-7
+ ULONG ControlBitParityL: 1; // 8
+ ULONG Shared: 1; // 9
+ ULONG Dirty: 1; // 10
+ ULONG Valid: 1; // 11
+ ULONG Resrved2: 5; // 12-16
+ ULONG BCacheEDCError1: 1; // 17
+ ULONG EDCSyndrome0: 7; // 18-24
+ ULONG EDCSyndrome2: 7; // 25-31
+ ULONG MissedParErrorH: 1; // 32
+ ULONG ParityErrorH: 1; // 33
+ ULONG MissedUncorrectableErrorH: 1; // 34
+ ULONG UncorrectableErrorH: 1; // 35
+ ULONG Resreved3: 13; // 36-48
+ ULONG BCacheEDCError2: 1; // 49
+ ULONG EDCSyndrome1: 7; // 50-56
+ ULONG EDCSyndrome3: 7; // 57-63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCUE_CSR3, *PSABLE_BCACHE_BCUE_CSR3;
+
+//
+// Define the Backup Cache uncorrectable error address register
+//
+
+typedef struct _SABLE_BCACHE_BCUEA_CSR4 {
+ union {
+ ULONG BCacheMapOffsetL: 17; // 0-16
+ ULONG PredictedTagParL: 1; // 17
+ ULONG TagParityL: 1; // 18
+ ULONG TagValueL: 12; // 19-30
+ ULONG Reserved1: 1; // 31
+ ULONG BCacheMapOffsetH: 17; // 32-48
+ ULONG PredictedTagParH: 1; // 49
+ ULONG TagParityJ: 1; // 50
+ ULONG TagValueH: 12; // 51-62
+ ULONG Reserved2: 1; // 63
+
+ };
+ ULONGLONG all;
+} SABLE_BCACHE_BCUEA_CSR4, *PSABLE_BCACHE_BCUEA_CSR4;
+
+//
+// Define the memory module CSRs
+//
+
+typedef struct _SGL_MEM_CSR0 {
+ union {
+ ULONG ErrorSummary1: 1; // 0
+ ULONG SyncError1: 1; // 1
+ ULONG CAParityError1: 1; // 2
+ ULONG CAMissedParityError1: 1; // 3
+ ULONG WriteParityError1: 1; // 4
+ ULONG MissedWriteParityError1: 1; // 5
+ ULONG Reserved1: 2; // 6-7
+
+ ULONG CAParityErrorLW0: 1; // 8
+ ULONG CAParityErrorLW2: 1; // 9
+ ULONG ParityErrorLW0: 1; // 10
+ ULONG ParityErrorLW2: 1; // 11
+ ULONG ParityErrorLW4: 1; // 12
+ ULONG ParityErrorLW6: 1; // 13
+ ULONG Reserved2: 2; // 14-15
+
+ ULONG EDCUncorrectable1: 1; // 16
+ ULONG EDCMissedUncorrectable1: 1; // 17
+ ULONG EDCCorrectable1: 1; // 18
+ ULONG EDCMissdedCorrectable1: 1; // 19
+ ULONG Reserved3: 12; // 20-31
+
+ ULONG ErrorSummary2: 1; // 32
+ ULONG SyncError2: 1; // 33
+ ULONG CAParityError2: 1; // 34
+ ULONG CAMissedParityError2: 1; // 35
+ ULONG WriteParityError2: 1; // 36
+ ULONG MissedWriteParityError2: 1; // 37
+ ULONG Reserved4: 2; // 38-39
+
+ ULONG CAParityErrorLW1: 1; // 40
+ ULONG CAParityErrorLW3: 1; // 41
+ ULONG ParityErrorLW1: 1; // 42
+ ULONG ParityErrorLW3: 1; // 43
+ ULONG ParityErrorLW5: 1; // 44
+ ULONG ParityErrorLW7: 1; // 45
+ ULONG Reserved5: 2; // 46-47
+
+ ULONG EDCUncorrectable2: 1; // 48
+ ULONG EDCMissedUncorrectable2: 1; // 49
+ ULONG EDCCorrectable2: 1; // 50
+ ULONG EDCMissdedCorrectable2: 1; // 51
+ ULONG Reserved6: 12; // 52-63
+ };
+ ULONGLONG all;
+
+} SGL_MEM_CSR0, *PSGL_MEM_CSR0;
+
+//
+// Define the Interprocessor Interrupt Request Register.
+//
+
+typedef union _SABLE_IPIR_CSR{
+ struct{
+ ULONG RequestInterrupt: 1;
+ ULONG Reserved0: 31;
+ ULONG Undefined: 1;
+ ULONG Reserved1: 2;
+ ULONG RequestNodeHaltInterrupt: 1;
+ ULONG Reserved2: 28;
+ };
+ ULONGLONG all;
+} SABLE_IPIR_CSR, *PSABLE_IPIR_CSR;
+
+//
+// Define the System Interrupt Clear Register format.
+//
+
+typedef union _SABLE_SIC_CSR{
+ struct{
+ ULONG Undefined1: 1;
+ ULONG Undefined2: 1;
+ ULONG SystemBusErrorInterruptClear: 1;
+ ULONG Undefined3: 1;
+ ULONG Reserved1: 28;
+ ULONG IntervalTimerInterruptClear: 1;
+ ULONG SystemEventClear: 1;
+ ULONG Undefinded4: 1;
+ ULONG NodeHaltInterruptClear: 1;
+ ULONG Reserved2: 28;
+ };
+ ULONGLONG all;
+} SABLE_SIC_CSR, *PSABLE_SIC_CSR;
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each Sable processor.
+//
+
+typedef struct _SABLE_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ ULONGLONG IpirSva; // Superpage Va of per-processor IPIR CSR
+ PVOID CpuCsrsQva; // Qva of per-cpu csrs
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} SABLE_PCR, *PSABLE_PCR;
+
+#define HAL_PCR ( (PSABLE_PCR)(&(PCR->HalReserved)) )
+
+//
+// Define Miscellaneous Sable routines.
+//
+
+VOID
+WRITE_CPU_REGISTER(
+ PVOID,
+ ULONGLONG
+ );
+
+ULONGLONG
+READ_CPU_REGISTER(
+ PVOID
+ );
+
+ULONGLONG
+READ_MEM_REGISTER(
+ PVOID
+ );
+
+VOID
+HalpSableIpiInterrupt(
+ VOID
+ );
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_SABLEH_
diff --git a/private/ntos/nthals/halsable/alpha/sableerr.c b/private/ntos/nthals/halsable/alpha/sableerr.c
new file mode 100644
index 000000000..304678e17
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sableerr.c
@@ -0,0 +1,2081 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ sableerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Sable platform.
+
+Author:
+
+ Joe Notarangelo 15-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+//jnfix - this module current only deals with errors initiated by the
+//jnfix - T2, there is nothing completed for CPU Asic errors
+
+#include "halp.h"
+#include "axp21064.h"
+#include "stdio.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+extern ULONG HalDisablePCIParityChecking;
+extern ULONG HalpMemorySlot[];
+extern ULONG HalpCPUSlot[];
+
+ULONG SlotToPhysicalCPU[4] = {3, 0, 1, 2};
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+ULONG
+HalpTranslateSyndromToECC(
+ PULONG Syndrome
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpSableReportFatalError(
+ VOID
+ );
+
+#define MAX_ERROR_STRING 128
+
+ULONG SGLCorrectedErrors = 0;
+
+
+VOID
+HalpInitializeMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for an APECS-based
+ system by clearing all pending errors in the COMANCHE and EPIC and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ T2_PERR1 Perr1;
+ T2_IOCSR Iocsr;
+
+ //
+ // Clear any pending CBUS errors.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1, Cerr1.all );
+
+ //
+ // Clear any pending PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ Perr1.ForceReadDataParityError64 = 0;
+ Perr1.ForceAddressParityError64 = 0;
+ Perr1.ForceWriteDataParityError64 = 0;
+ Perr1.DetectTargetAbort = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1, Perr1.all );
+
+ //
+ // Enable the errors we want to handle in the T2 via the Iocsr,
+ // must read-modify-write Iocsr as it contains values we want to
+ // preserve.
+ //
+
+ Iocsr.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr );
+
+ //
+ // Enable all of the hard error checking and error interrupts.
+ //
+
+ Iocsr.EnableTlbErrorCheck = 1;
+ Iocsr.EnableCxAckCheckForDma = 1;
+// Iocsr.EnableCommandOutOfSyncCheck = 1;
+ Iocsr.EnableCbusErrorInterrupt = 1;
+ Iocsr.EnableCbusParityCheck = 1;
+
+#if 0
+ //
+ // T3 Bug: There are 2 write buffers which can be used for PIO or
+ // PPC. By default they are initialized to PIO. However, using
+ // them for PIO causes T3 state machine errors. To work around this
+ // problem convert them to PPC buffers, instead. This decreases PIO
+ // performance.
+ //
+
+ if (Iocsr.T2RevisionNumber >= 4) {
+
+ Iocsr.EnablePpc1 = 1;
+ Iocsr.EnablePpc2 = 1;
+
+ }
+#endif // wkc - the SRM should be setting this now.
+
+ Iocsr.ForcePciRdpeDetect = 0;
+ Iocsr.ForcePciApeDetect = 0;
+ Iocsr.ForcePciWdpeDetect = 0;
+ Iocsr.EnablePciNmi = 1;
+ Iocsr.EnablePciDti = 1;
+ Iocsr.EnablePciSerr = 1;
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+
+ //
+ // Disable PCI Parity Checking
+ //
+
+ Iocsr.EnablePciPerr = 0;
+ Iocsr.EnablePciRdp = 0;
+ Iocsr.EnablePciAp = 0;
+ Iocsr.EnablePciWdp = 0;
+
+ } else {
+
+ Iocsr.EnablePciPerr = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciRdp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp = !HalDisablePCIParityChecking;
+
+ }
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ Iocsr.all );
+
+ //
+ // Ascertain whether this is a Gamma or Lynx platform.
+ //
+
+ if( Iocsr.T2RevisionNumber >= 4 ){
+
+ HalpLynxPlatform = TRUE;
+
+ }
+
+ //
+ // Set the machine check enables within the EV4.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ } else {
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // The next line *may* generate a machine check. This would happen
+ // if an XIO module is not present in the system. It should be safe
+ // to take machine checks now. Here goes nothing...
+ //
+
+ Iocsr.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr );
+
+ if( Iocsr.all != (ULONGLONG)-1 ){
+
+ HalpXioPresent = TRUE;
+
+ //
+ // Clear any pending CBUS errors.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1, Cerr1.all );
+
+ //
+ // Clear any pending PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1 );
+
+ Perr1.ForceReadDataParityError64 = 0;
+ Perr1.ForceAddressParityError64 = 0;
+ Perr1.ForceWriteDataParityError64 = 0;
+ Perr1.DetectTargetAbort = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1, Perr1.all );
+
+ Iocsr.EnableTlbErrorCheck = 1;
+ Iocsr.EnableCxAckCheckForDma = 1;
+// Iocsr.EnableCommandOutOfSyncCheck = 1;
+ Iocsr.EnableCbusErrorInterrupt = 1;
+ Iocsr.EnableCbusParityCheck = 1;
+
+ //
+ // T3 Bug: There are 2 write buffers which can be used for PIO or
+ // PPC. By default they are initialized to PIO. However, using
+ // them for PIO causes T3 state machine errors. To work around
+ // this problem convert them to PPC buffers, instead. This
+ // decreases PIO performance.
+ //
+
+ Iocsr.EnablePpc1 = 1;
+ Iocsr.EnablePpc2 = 1;
+
+ Iocsr.EnablePciStall = 0;
+ Iocsr.ForcePciRdpeDetect = 0;
+ Iocsr.ForcePciApeDetect = 0;
+ Iocsr.ForcePciWdpeDetect = 0;
+ Iocsr.EnablePciNmi = 1;
+ Iocsr.EnablePciDti = 1;
+ Iocsr.EnablePciSerr = 1;
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+
+ //
+ // Disable PCI Parity Checking
+ //
+
+ Iocsr.EnablePciRdp64 = 0;
+ Iocsr.EnablePciAp64 = 0;
+ Iocsr.EnablePciWdp64 = 0;
+ Iocsr.EnablePciPerr = 0;
+ Iocsr.EnablePciRdp = 0;
+ Iocsr.EnablePciAp = 0;
+ Iocsr.EnablePciWdp = 0;
+
+ } else {
+
+ Iocsr.EnablePciRdp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciPerr = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciRdp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp = !HalDisablePCIParityChecking;
+
+ }
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr,
+ Iocsr.all );
+
+ }
+
+#endif
+
+#if HALDBG
+ if (HalDisablePCIParityChecking == 0) {
+ DbgPrint("sableerr: PCI Parity Checking ON\n");
+ } else if (HalDisablePCIParityChecking == 1) {
+ DbgPrint("sableerr: PCI Parity Checking OFF\n");
+ } else {
+ DbgPrint("sableerr: PCI Parity Checking OFF - not set by ARC yet\n");
+ }
+#endif
+
+ return;
+
+}
+
+
+VOID
+HalpBuildSableUncorrectableErrorFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when an uncorrectable error occurs.
+ This routine builds the global Sable Uncorrectable Error frame.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ //
+ // We will *try* to get the CPU module information that was active at the
+ // time of the machine check.
+ // We will *try* to get as much information about the system, the CPU
+ // modules and the memory modules at the time of the crash.
+ //
+ extern ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+ extern PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+ extern KAFFINITY HalpActiveProcessors;
+
+ PSABLE_CPU_CSRS CpuCsrsQva;
+ PSABLE_UNCORRECTABLE_FRAME sableuncorrerr = NULL;
+ PEXTENDED_ERROR PExtErr;
+ ULONG LogicalCpuNumber;
+ ULONG i = 0;
+ ULONG TotalNumberOfCpus = 0;
+ T2_IOCSR Iocsr;
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+
+ if(PUncorrectableError){
+ sableuncorrerr = (PSABLE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ if(sableuncorrerr){
+ //
+ // Get the Error registers from all the CPU modules.
+ // Although called CPU error this is sable specific and not CPU
+ // specific the CPU error itself will be logged in the EV4 error frame.
+ // HalpActiveProcessors is a mask of all processors that are active.
+ // 8 bits per byte to get the total number of bits in KAFFINITY
+ //
+ DbgPrint("sableerr.c - HalpBuildSableUncorrectableErrorFrame :\n");
+ for(i = 0 ; i < sizeof(KAFFINITY)*8 ; i++ ) {
+ if( (HalpActiveProcessors >> i) & 0x1UL) {
+ LogicalCpuNumber = i;
+ TotalNumberOfCpus++;
+ }
+ else
+ continue;
+
+ CpuCsrsQva = HalpSableCpuCsrs[LogicalCpuNumber];
+
+ DbgPrint("\tCurrent CPU Module's[LN#=%d] CSRS QVA = %08lx\n",
+ LogicalCpuNumber, CpuCsrsQva);
+ DbgPrint("\n\t CPU Module Error Log : \n");
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Bcue);
+ DbgPrint("\t\tBcue = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Bcuea);
+ DbgPrint("\t\tBcuea = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea);
+
+ //
+ // If the Parity Error Bit is Set then
+ //
+ if(sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue &
+ (ULONGLONG)0x2) {
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "B-Cache Tag Error or Control Store Parity Error");
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_CACHE;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.CacheBoardNumber = LogicalCpuNumber;
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+
+ }
+ if(sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue &
+ (ULONGLONG)0x8) {
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_CACHE;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.CacheBoardNumber = LogicalCpuNumber;
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+ }
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Dter =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Dter);
+ DbgPrint("\t\tDter = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Dter);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cberr =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cb2);
+ DbgPrint("\t\tCberr = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cberr);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeal =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbeal);
+ DbgPrint("\t\tCbeal = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeal);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeah =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbeah);
+ DbgPrint("\t\tCbeah = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeah);
+
+
+ //
+ // Fill in some of the control registers in the configuration
+ // structures.
+ //
+ DbgPrint("\n\t CPU Module Configuration : \n");
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Cbctl =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbctl);
+ DbgPrint("\t\tCbctl = %016Lx\n",
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Cbctl);
+
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Pmbx =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Pmbx);
+ DbgPrint("\t\tPmbx = %016Lx\n",
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Pmbx);
+
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].C4rev =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Crrevs);
+ DbgPrint("\t\tC4rev = %016Lx\n",
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].C4rev);
+
+ }
+
+ sableuncorrerr->Configuration.NumberOfCpus = TotalNumberOfCpus;
+ DbgPrint("\tTotalNumberOfCpus = %d\n", TotalNumberOfCpus);
+
+ //
+ // Since I dont know how to get how many memory modules
+ // are available and which slots they are in we will skip
+ // the memory error logging. When we do this we will also fill in
+ // the memory configuration details.
+ //
+
+ //
+ // Get T2 errors.
+ //
+ DbgPrint("\n\tT2 Error Log :\n");
+ sableuncorrerr->IoChipsetError.Cerr1 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ DbgPrint("\t\tCerr1 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Cerr1);
+
+ Perr1.all = sableuncorrerr->IoChipsetError.Perr1 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+ DbgPrint("\t\tPerr1 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Perr1);
+
+ sableuncorrerr->IoChipsetError.Cerr2 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr2 );
+ DbgPrint("\t\tCerr2 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Cerr2);
+
+ sableuncorrerr->IoChipsetError.Cerr3 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr3 );
+ DbgPrint("\t\tCerr3 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Cerr3);
+
+ Perr2.all = sableuncorrerr->IoChipsetError.Perr2 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr2 );
+ DbgPrint("\t\tPerr2 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Perr2);
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ Perr2.ErrorAddress;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ }
+
+
+
+ //
+ // T2 Configurations
+ //
+ DbgPrint("\n\tT2 Configuration :\n");
+ Iocsr.all = sableuncorrerr->Configuration.T2IoCsr =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr );
+ DbgPrint("\t\tIocsr = %016Lx\n",
+ sableuncorrerr->Configuration.T2IoCsr);
+
+ sableuncorrerr->Configuration.T2Revision = Iocsr.T2RevisionNumber;
+ DbgPrint("\t\tT2 Revision = %d\n",
+ sableuncorrerr->Configuration.T2Revision);
+
+
+ }
+
+ //
+ // Now fill in the Extended error information.
+ //
+ return;
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the APECS chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+//jnfix - again note that this only deals with errors signaled by the T2
+
+ T2_CERR1 Cerr1;
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+ PLOGOUT_FRAME_21064 LogoutFrame;
+ ULONGLONG PA;
+ enum {
+ Pci0ConfigurationSpace,
+ Pci1ConfigurationSpace,
+ MemCsrSpace,
+ CPUCsrSpace,
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+ T4CsrSpace
+#endif
+ } AddressSpace;
+ PVOID TxCsrQva;
+ PALPHA_INSTRUCTION FaultingInstruction;
+ CHAR ErrSpace[32];
+
+ //
+ // Check if there are any CBUS errors pending. Any of these errors
+ // are fatal.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+
+ sprintf(ErrSpace,"System Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = CBus;
+ goto FatalError;
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent ){
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1);
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+#if HALDBG
+ DbgPrint("HalpPlatformMachineCheck: T4 CERR1 = %Lx\n",
+ Cerr1.all);
+#endif
+
+ goto FatalError;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ sprintf(ErrSpace,"PCI Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = PCIBus;
+ goto FatalError;
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the external I/O module is present, check the T4's CBUS and PCI
+ // error registers, as well.
+ //
+
+ if( HalpXioPresent ){
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1 );
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ goto FatalError;
+
+ }
+ }
+
+#endif
+
+ //
+ // Get a pointer to the EV4 machine check logout frame.
+ //
+
+ LogoutFrame = (PLOGOUT_FRAME_21064)
+ ExceptionRecord->ExceptionInformation[1];
+
+ //
+ // Get the physical address which caused the machine check.
+ //
+
+ PA = LogoutFrame->BiuAddr.QuadPart;
+
+ //
+ // We handle and dismiss 3 classes of machine checks:
+ //
+ // - Read accesses from PCI 0 configuration space
+ // - Read accesses from PCI 1 configuration space
+ // - Read accesses from T4 CSR space
+ //
+ // Any other type of machine check is fatal.
+ //
+ // The following set of conditionals check which address space the
+ // machine check occured in, to decide how to handle it.
+ //
+
+ if( (PA >= SABLE_PCI0_CONFIGURATION_PHYSICAL) &&
+ (PA < SABLE_PCI1_CONFIGURATION_PHYSICAL) ){
+
+ //
+ // The machine check occured in PCI 0 configuration space. Save
+ // the address space and a QVA to T2 CSR space, we'll need them
+ // below.
+ //
+
+ AddressSpace = Pci0ConfigurationSpace;
+ TxCsrQva = (PVOID)T2_CSRS_QVA;
+
+ } else if( (PA >= SABLE_PCI1_CONFIGURATION_PHYSICAL) &&
+ (PA < SABLE_PCI0_SPARSE_IO_PHYSICAL) ){
+
+ //
+ // The machine check occured in PCI 1 configuration space.
+ // Save the address space and a QVA to T2 CSR space, we'll
+ // need them below.
+ //
+
+ AddressSpace = Pci1ConfigurationSpace;
+ TxCsrQva = (PVOID)T4_CSRS_QVA;
+
+ } else if ( (PA >= SABLE_CPU0_CSRS_PHYSICAL) &&
+ (PA <= SABLE_CPU3_IPIR_PHYSICAL)) {
+
+ //
+ // The machine check occured within CPU CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = CPUCsrSpace;
+
+ } else if ( (PA >= SABLE_MEM0_CSRS_PHYSICAL) &&
+ (PA < SABLE_T2_CSRS_PHYSICAL)) {
+
+ //
+ // The machine check occured within MEM CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = MemCsrSpace;
+
+ //
+ // Just based on the physical address, we have determined
+ // we cannot handle this machine check.
+ //
+ } else
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( (PA >= SABLE_T4_CSRS_PHYSICAL) &&
+ (PA < SABLE_PCI0_CONFIGURATION_PHYSICAL) ){
+
+ //
+ // The machine check occured within T4 CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = T4CsrSpace;
+
+ } else
+
+#endif
+ {
+ goto FatalError;
+ }
+
+ //
+ // Get a pointer to the faulting instruction. (It is possible
+ // that the exception address is actually an instruction or two
+ // beyond the instruction which actually caused the machine check.)
+ //
+
+ FaultingInstruction = (PALPHA_INSTRUCTION)TrapFrame->Fir;
+
+ //
+ // There are typically 2 MBs which follow the load which caused the
+ // machine check. The exception address could be one of them.
+ // If it is, advance the instruction pointer ahead of them.
+ //
+
+ while( (FaultingInstruction->Memory.Opcode == MEMSPC_OP) &&
+ (FaultingInstruction->Memory.MemDisp == MB_FUNC) ){
+
+ FaultingInstruction--;
+
+ }
+
+ //
+ // If the instruction uses v0 as Ra (i.e. v0 is the target register
+ // of the instruction) then this would typically indicate an T2 or
+ // configuration space access routine, and getting a machine check
+ // therein is acceptable. Otherwise, we took it someplace else, and
+ // it is fatal.
+ //
+
+ if( FaultingInstruction->Memory.Ra != V0_REG ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Perform address space-dependent handling.
+ //
+
+ switch( AddressSpace ){
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ case Pci0ConfigurationSpace:
+
+ //
+ // If no XIO module is present then we do not fix-up read accesses
+ // from PCI 1 configuration space. (This should never happen.)
+ //
+
+ if( !HalpXioPresent ){
+
+ goto FatalError;
+
+ }
+
+#endif
+
+ case Pci1ConfigurationSpace:
+
+ //
+ // Read the state of the T2/T4.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr1 );
+ Perr2.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr2 );
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Cerr1 );
+
+ //
+ // The T2/T4 responds differently when an error was received
+ // on type 0 and type 1 configuration cycles. For type 0 the
+ // T2/T4 detects and reports the device timeout. For type 1
+ // the PPB detects the timeout. Type 0 cycles error with
+ // the DeviceTimeout bit set. Type 1 cycles look just like
+ // NXM. Thus, the code below requires both checks.
+ //
+
+ if( (Perr1.DeviceTimeoutError != 1) &&
+ ((Perr1.all != 0) ||
+ (Cerr1.all != 0) ||
+ (Perr2.PciCommand != 0xA)) ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Clear any PCI or Cbus errors which may have been latched.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr1, Perr1.all );
+
+ break;
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ case T4CsrSpace:
+
+ //
+ // A read was performed from T4 CSR space when no XIO module was
+ // present. This was done, presumably, to detect the presence of
+ // the T4, and correspondingly, the XIO module. There is nothing
+ // special to do in this case, just fix-up the reference and
+ // dismiss the machine check.
+ //
+
+ break;
+#endif
+
+ case MemCsrSpace:
+ case CPUCsrSpace:
+
+ //
+ // A read was performed from Mem CSR space when no memory module was
+ // present. This was done, presumably, to detect the presence of
+ // a memory board.
+ //
+
+ break;
+
+ }
+
+ //
+ // Advance the instruction pointer.
+ //
+
+ TrapFrame->Fir += 4;
+
+ //
+ // Make it appear as if the load instruction read all ones.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)-1;
+
+ //
+ // Dismiss the machine check.
+ //
+
+ return TRUE;
+
+
+//
+// The system is not well and cannot continue reliable execution.
+// Print some useful messages and return FALSE to indicate that the error
+// was not handled.
+//
+
+FatalError:
+ //
+ // Build the error frame. Later may be move it in front and use
+ // the field in the error frame rather than reading the error registers
+ // twice.
+ //
+
+ HalpBuildSableUncorrectableErrorFrame();
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Sable: Uncorrectable Error detected in %s", ErrSpace);
+ }
+
+
+ HalpSableReportFatalError();
+
+ return FALSE;
+
+}
+
+
+ULONG
+HalpTranslateSyndromToECC(
+ IN OUT PULONG Syndrome
+ )
+/*++
+
+Routine Description:
+
+ Translate the syndrome to a particular bit. If the syndrome indicates
+ a data bit, then return 0, if a check bit, then return 1.
+
+ In the place of the incoming syndrome, stuff the resulting bit.
+
+Arguments:
+
+ Syndrome Pointer to the syndrome
+
+Return Value:
+
+ 0 for data bit
+ 1 for check bit
+
+--*/
+{
+
+ static UCHAR SyndromeToECCTable[0xff] = {0, };
+ static BOOLEAN SyndromeToECCTableInitialized = FALSE;
+
+ ULONG Temp = *Syndrome;
+
+ //
+ // Initialize the table.
+ //
+
+ if (!SyndromeToECCTableInitialized) {
+ SyndromeToECCTableInitialized = TRUE;
+
+ //
+ // fill in the table
+ //
+
+ SyndromeToECCTable[0x1] = 0;
+ SyndromeToECCTable[0x2] = 1;
+ SyndromeToECCTable[0x4] = 2;
+ SyndromeToECCTable[0x8] = 3;
+ SyndromeToECCTable[0x10] = 4;
+ SyndromeToECCTable[0x20] = 5;
+ SyndromeToECCTable[0x40] = 6;
+
+ SyndromeToECCTable[0x4F] = 0;
+ SyndromeToECCTable[0x4A] = 1;
+ SyndromeToECCTable[0x52] = 2;
+ SyndromeToECCTable[0x54] = 3;
+ SyndromeToECCTable[0x57] = 4;
+ SyndromeToECCTable[0x58] = 5;
+ SyndromeToECCTable[0x5B] = 6;
+ SyndromeToECCTable[0x5D] = 7;
+ SyndromeToECCTable[0x23] = 8;
+ SyndromeToECCTable[0x25] = 9;
+ SyndromeToECCTable[0x26] = 10;
+ SyndromeToECCTable[0x29] = 11;
+ SyndromeToECCTable[0x2A] = 12;
+ SyndromeToECCTable[0x2C] = 13;
+ SyndromeToECCTable[0x31] = 14;
+ SyndromeToECCTable[0x34] = 15;
+ SyndromeToECCTable[0x0E] = 16;
+ SyndromeToECCTable[0x0B] = 17;
+ SyndromeToECCTable[0x13] = 18;
+ SyndromeToECCTable[0x15] = 19;
+ SyndromeToECCTable[0x16] = 20;
+ SyndromeToECCTable[0x19] = 21;
+ SyndromeToECCTable[0x1A] = 22;
+ SyndromeToECCTable[0x1C] = 23;
+ SyndromeToECCTable[0x62] = 24;
+ SyndromeToECCTable[0x64] = 25;
+ SyndromeToECCTable[0x67] = 26;
+ SyndromeToECCTable[0x68] = 27;
+ SyndromeToECCTable[0x6B] = 28;
+ SyndromeToECCTable[0x6D] = 29;
+ SyndromeToECCTable[0x70] = 30;
+ SyndromeToECCTable[0x75] = 31;
+ }
+
+ *Syndrome = SyndromeToECCTable[Temp];
+
+ if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 ||
+ Temp == 0x10 || Temp == 0x20 || Temp == 0x40) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+VOID
+HalpCPUCorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on a CPU
+ module -- the only thing this can be is a Bcache error. Populate the
+ correctable error frame.
+
+Arguments:
+
+ PhysicalSlot Physical CPU slot number
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ SABLE_BCACHE_BCCE_CSR1 CSR1;
+ ULONG CERBase;
+ PULONGLONG VariableData = (PULONGLONG)CorrPtr->RawSystemInformation;
+
+ //
+ // Get CPU's bcache CER
+ //
+
+ CERBase = HalpCPUSlot[PhysicalSlot];
+ CSR1.all = READ_CPU_REGISTER((PVOID)(CERBase | 0x1));
+
+ //
+ // Set the bits, one by one
+ //
+
+ CorrPtr->Flags.AddressSpace = 1; // memory space
+ CorrPtr->Flags.PhysicalAddressValid = 0;
+ CorrPtr->Flags.ErrorBitMasksValid = 0;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.ProcessorInformationValid = 1;
+ CorrPtr->Flags.SystemInformationValid = 0;
+ CorrPtr->Flags.ServerManagementInformationValid = 0;
+ CorrPtr->Flags.MemoryErrorSource = 2; // processor cache
+
+ CorrPtr->Flags.ScrubError = 0; // ??
+ CorrPtr->Flags.LostCorrectable = CSR1.MissedCorrectableError |
+ CSR1.MissedCorrectableErrorH;
+
+
+ CorrPtr->Flags.LostAddressSpace = 0;
+ CorrPtr->Flags.LostMemoryErrorSource = 0;
+
+ CorrPtr->PhysicalAddress = 0;
+ CorrPtr->DataBitErrorMask = 0;
+ CorrPtr->CheckBitErrorMask = 0;
+
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheLevelValid = 0;
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheBoardValid = 0;
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheSimmValid = 0;
+
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.ProcessorType = 21064;
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.ProcessorRevision = 0;
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.PhysicalProcessorNumber =
+ SlotToPhysicalCPU[PhysicalSlot];
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.LogicalProcessorNumber = 0;
+ CorrPtr->ErrorInformation.CacheError.CacheLevel = 0;
+ CorrPtr->ErrorInformation.CacheError.CacheSimm = 0;
+ CorrPtr->ErrorInformation.CacheError.TransferType = 0;
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+
+ //
+ // Dump raw Register Data (CSR0, 1, 2, 3, 4)
+ //
+
+ CorrPtr->RawSystemInformationLength = (5 * sizeof(ULONGLONG));
+
+ //
+ // Get CSR0 -- Bcache control register
+ //
+
+ *VariableData++ = READ_CPU_REGISTER((PVOID)(CERBase));
+
+ //
+ // Get CSR1 -- correctable error register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x1));
+
+ //
+ // Get CSR2 -- correctable error address register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x2));
+
+ //
+ // Get CSR3 -- uncorrectable error register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x3));
+
+ //
+ // Get CSR4 -- uncorrectable error address register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x4));
+
+ //
+ // wkcfix -- processor data?
+ //
+ // CorrPtr->RawProcessorInformationLength
+ // CorrPtr->RawProcessorInformation
+ //
+
+}
+
+
+VOID
+HalpMemoryCorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on a memory
+ module. Populate the correctable error frame.
+
+Arguments:
+
+ PhysicalSlot The physical slot of the falting board
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+ SGL_MEM_CSR0 CSR;
+ ULONG CSRBase;
+ PULONGLONG VariableData = (PULONGLONG)CorrPtr->RawSystemInformation;
+
+ //
+ // Get MEM modules base addr
+ //
+
+ CSRBase = HalpMemorySlot[PhysicalSlot];
+
+ //
+ // Get CSR0
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)CSRBase);
+
+ //
+ // Set the bits, one by one
+ //
+
+ CorrPtr->Flags.AddressSpace = 0; // ??
+ CorrPtr->Flags.PhysicalAddressValid = 0;
+ CorrPtr->Flags.ErrorBitMasksValid = 0;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+ CorrPtr->Flags.SystemInformationValid = 0;
+ CorrPtr->Flags.ServerManagementInformationValid = 0;
+ CorrPtr->Flags.MemoryErrorSource = 4; // processor memory
+
+ CorrPtr->PhysicalAddress = 0;
+ CorrPtr->DataBitErrorMask = 0;
+ CorrPtr->CheckBitErrorMask = 0;
+
+ CorrPtr->ErrorInformation.MemoryError.Flags.MemoryBoardValid = 0;
+ CorrPtr->ErrorInformation.MemoryError.Flags.MemorySimmValid = 0;
+
+ CorrPtr->ErrorInformation.MemoryError.MemoryBoard = PhysicalSlot;
+ CorrPtr->ErrorInformation.MemoryError.MemorySimm = 0;
+ CorrPtr->ErrorInformation.MemoryError.TransferType = 0;
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // Dump raw CSR data (CSRO, 1, 2, 4)
+ //
+
+ CorrPtr->RawSystemInformationLength = (4 * sizeof(ULONGLONG));
+ *VariableData++ = CSR.all;
+
+ //
+ // Get CSR1
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)(CSRBase | 0x1));
+ *VariableData++ = CSR.all;
+
+ //
+ // Get CSR2
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)(CSRBase | 0x2));
+ *VariableData++ = CSR.all;
+
+ //
+ // Get CSR4
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)(CSRBase | 0x4));
+ *VariableData++ = CSR.all;
+
+
+ //
+ // wkcfix -- processor data?
+ //
+ // CorrPtr->RawProcessorInformationLength
+ // CorrPtr->RawProcessorInformation
+ //
+
+}
+
+
+VOID
+HalpT2CorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on the CBus.
+ Populate the correctable error frame.
+
+Arguments:
+
+ Physical Slot
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // This should never be called, because there are no correctable T2 errors.
+ //
+}
+
+
+
+ULONG
+HalpCheckCPUForError(
+ IN OUT PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the CPU module CSR for BCACHE error.
+
+Arguments:
+
+ Slot The return value for the slot if an error is found
+
+Return Value:
+
+ Either CorrectableError or NoError
+
+--*/
+{
+
+ ULONG i;
+ SABLE_BCACHE_BCCE_CSR1 CSR1;
+ ULONG BaseCSRQVA;
+
+ //
+ // Run through the CPU modules looking for a correctable
+ // error.
+ //
+
+ for (i=0; i<4; i++) {
+
+ //
+ // If a cpu board is present, then use the QVA stored in that
+ // location -- if a CPU module is not present, then the value is 0.
+ //
+
+ if (HalpCPUSlot[i] != 0) {
+
+ BaseCSRQVA = HalpCPUSlot[i];
+
+ //
+ // Read the backup cache correctable error register (CSR1)
+ //
+
+ CSR1.all = READ_CPU_REGISTER((PVOID)(BaseCSRQVA | 0x1));
+
+ //
+ // Check the two correctable error bits -- if one at least one
+ // is set, then go off and build the frame and jump directly
+ // to the correctable error flow.
+ //
+
+ if (CSR1.CorrectableError || CSR1.CorrectableErrorH ||
+ CSR1.MissedCorrectableError || CSR1.MissedCorrectableErrorH) {
+
+ *Slot = i;
+ return CorrectableError;
+ }
+ }
+ }
+
+ return NoError;
+}
+
+
+ULONG
+HalpCheckMEMForError(
+ PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the Memory module CSR for errors.
+
+Arguments:
+
+ Slot The return value for the slot if an error is found
+
+Return Value:
+
+ Either CorrectableError or NoError or UncorrectableError
+
+--*/
+{
+
+ SGL_MEM_CSR0 CSR;
+ ULONG i;
+ ULONG BaseCSRQVA;
+
+ //
+ // If we have fallen through the CPU correctable errors,
+ // check the Memory boards
+ //
+
+ for (i=0; i<4; i++) {
+
+ //
+ // If a memory board is present, then the value is the QVA of CSR0
+ // on that memory board. If not present, the value is 0.
+ //
+
+ if (HalpMemorySlot[i] != 0) {
+
+ BaseCSRQVA = HalpMemorySlot[i];
+
+ CSR.all = READ_MEM_REGISTER((PVOID)BaseCSRQVA);
+
+ //
+ // Sync Errors are NOT part of the summary registers (bogus
+ // if you ask me....), but check them first.
+ //
+
+ if (CSR.SyncError1 || CSR.SyncError2) {
+ *Slot = i;
+ return CorrectableError;
+ }
+
+ //
+ // The error summary bit indicates if ANY error bits are
+ // lit. If no error on this module, then skip to the next one.
+ //
+
+ if (CSR.ErrorSummary1 == 0 && CSR.ErrorSummary2 == 0) {
+ continue;
+ }
+
+ //
+ // Because one of the summary registers are set, then this memory
+ // module has indicated an error. Check the correctable bits. If
+ // any are set, then build a correctable error frame, otherwise,
+ // drop back 20 and punt.
+ //
+
+ *Slot = i;
+
+ if (CSR.EDCCorrectable1 || CSR.EDCCorrectable2 ||
+ CSR.EDCMissdedCorrectable1 || CSR.EDCMissdedCorrectable2) {
+
+ return CorrectableError;
+ } else {
+ return UncorrectableError;
+ }
+ }
+ }
+
+ return NoError;
+
+}
+
+
+ULONG
+HalpCheckT2ForError(
+ PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the System Host Chips for Errors.
+
+Arguments:
+
+ Slot The return value for the QVA of the T2 of an error is returned.
+
+Return Value:
+
+ Either CorrectableError or NoError or UncorrectableError
+
+--*/
+{
+ T2_CERR1 Cerr1;
+
+ *Slot = 0;
+
+ //
+ // Run through the T2 chips (OK, they may be T2, or T3 or T4...)
+ // and check for correctable errors
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+ return UncorrectableError;
+ }
+
+ //
+ // There are no uncorrectable CBus errors
+ //
+
+ return NoError;
+}
+
+
+VOID
+HalpSableErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an error interrupt from the
+ T2 on a Sable system. This function determines if the error is
+ fatal or recoverable and if recoverable performs the recovery and
+ error logging.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ static ERROR_FRAME Frame;
+
+ ULONG DetectedError;
+
+ ULONG Slot = 0;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+ PCORRECTABLE_ERROR CorrPtr;
+ PBOOLEAN ErrorlogBusy;
+ ERROR_FRAME TempFrame;
+
+ //
+ // Get the interrupt information
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Find out if a CPU module had any errors
+ //
+
+ DetectedError = HalpCheckCPUForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpCPUCorrectableError(Slot, CorrPtr);
+ goto CError;
+ }
+
+ //
+ // Find out if Memory module had any errors
+ //
+
+ DetectedError = HalpCheckMEMForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpMemoryCorrectableError(Slot, CorrPtr);
+ goto CError;
+ }
+
+
+ //
+ // Find out if the T2's had any errors
+ //
+
+ DetectedError = HalpCheckT2ForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpT2CorrectableError(Slot, CorrPtr);
+ goto CError;
+ } else {
+ return; // no error?
+ }
+
+CError:
+
+ //
+ // Build the rest of the error frame
+ //
+
+ SGLCorrectedErrors += 1;
+
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = SGLCorrectedErrors;
+ TempFrame.PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ // Then add our platform info...
+ //
+
+ if (!*ErrorlogBusy) {
+
+ // wkc fix....
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+ //
+ // Clear the error and return (wkcfix -- clear now? or in routines).
+ //
+
+ return;
+
+
+UCError: // wkcfix
+
+ //
+ // The interrupt indicates a fatal system error.
+ // Display information about the error and shutdown the machine.
+ //
+
+ HalpBuildSableUncorrectableErrorFrame();
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Sable: Uncorrectable Error interrupt from T2");
+ }
+
+
+ HalpSableReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+}
+
+
+VOID
+HalpSableReportFatalError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error on
+ a Sable system. Currently, only the T2 error registers - CERR1 and PERR1
+ are used to interpret the error.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ ULONGLONG Cerr2;
+ ULONGLONG Cerr3;
+ UCHAR OutBuffer[MAX_ERROR_STRING];
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+ PCHAR parityErrString = NULL;
+ PEXTENDED_ERROR exterr;
+
+ if(PUncorrectableError) {
+ exterr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ parityErrString = PUncorrectableError->UncorrectableFrame.ErrorString;
+ }
+
+ //
+ // Begin the error output by acquiring ownership of the display
+ // and printing the dreaded banner.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // Read both of the error registers. It is possible that more
+ // than one error was reported simulataneously.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ //
+ // Read all of the relevant error address registers.
+ //
+
+ Cerr2 = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr2 );
+ Cerr3 = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr3 );
+
+ Perr2.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr2 );
+
+ //
+ // Interpret any errors from CERR1.
+ //
+
+ sprintf( OutBuffer, "T2 CERR1 = 0x%Lx\n", Cerr1.all );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.UncorrectableReadError == 1 ){
+
+ sprintf( OutBuffer,
+ "Uncorrectable read error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.NoAcknowledgeError == 1 ){
+
+ sprintf( OutBuffer,
+ "No Acknowledgement Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.CommandAddressParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( OutBuffer,
+ "Command Address Parity Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.CaParityErrorLw3 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 3\n");
+ HalDisplayString( "C/A Parity Error on longword 3\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw2 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 2\n" );
+ HalDisplayString( "C/A Parity Error on longword 2\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw1 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 1\n");
+ HalDisplayString( "C/A Parity Error on longword 1\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw0 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 0\n" );
+ HalDisplayString( "C/A Parity Error on longword 0\n" );
+ }
+
+ }
+
+ if( Cerr1.MissedCommandAddressParity == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( parityErrString,
+ "Missed C/A Parity Error\n" );
+ HalDisplayString( "Missed C/A Parity Error\n" );
+ }
+
+ if( (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( OutBuffer,
+ "T2 detected Data Parity error, CBUS Address = 0x%Lx16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "T2 was %s on error transaction\n",
+ Cerr1.ResponderWriteDataParityError == 1 ? "responder" :
+ "commander" );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.DataParityErrorLw0 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 0\n" );
+ HalDisplayString( "Data Parity on longword 0\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw1 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 1\n" );
+ HalDisplayString( "Data Parity on longword 1\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw2 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 2\n");
+ HalDisplayString( "Data Parity on longword 2\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw3 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 3\n" );
+ HalDisplayString( "Data Parity on longword 3\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw4 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 4\n" );
+ HalDisplayString( "Data Parity on longword 4\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw5 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 5\n" );
+ HalDisplayString( "Data Parity on longword 5\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw6 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 6\n" );
+ HalDisplayString( "Data Parity on longword 6\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw7 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 7\n" );
+ HalDisplayString( "Data Parity on longword 7\n" );
+ }
+
+ } //(Cerr1.ResponderWriteDataParityError == 1) || ...
+
+
+ if( Cerr1.MissedRspWriteDataParityError == 1 ){
+ HalDisplayString( "Missed data parity error as responder\n" );
+ }
+
+ if( Cerr1.MissedReadDataParityError == 1 ){
+ HalDisplayString( "Missed data parity error as commander\n" );
+ }
+
+
+ if( Cerr1.CmdrWriteDataParityError == 1 ){
+
+ sprintf( OutBuffer,
+ "Commander Write Parity Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.BusSynchronizationError == 1 ){
+
+ sprintf( OutBuffer,
+ "Bus Synchronization Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.InvalidPfnError == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid PFN for scatter/gather, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Interpret any errors from T2 PERR1.
+ //
+
+ sprintf( OutBuffer, "PERR1 = 0x%Lx\n", Perr1.all );
+ HalDisplayString( OutBuffer );
+
+ if( Perr1.WriteDataParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( parityErrString,
+ "T2 (slave) detected write parity error\n");
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+ sprintf( OutBuffer,
+ "T2 (slave) detected write parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.AddressParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (slave) detected address parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+ sprintf( OutBuffer,
+ "T2 (slave) detected address parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ReadDataParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (master) detected read parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "T2 (master) detected read parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Participant asserted PERR#, parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "Participant asserted PERR#, parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Slave asserted SERR#, parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "Slave asserted SERR#, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.DeviceTimeoutError == 1 ){
+
+ sprintf( OutBuffer,
+ "Device timeout error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.DeviceTimeoutError == 1 ){
+
+ HalDisplayString( "PCI NMI asserted.\n" );
+
+ }
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/sableio.s b/private/ntos/nthals/halsable/alpha/sableio.s
new file mode 100644
index 000000000..fd3a6f188
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sableio.s
@@ -0,0 +1,956 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sableio.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Sable system.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+ (We are using EV4 64-bit superpage mode.)
+
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "sable.h"
+#include "halalpha.h"
+
+.set noreorder
+
+
+ LEAF_ENTRY(WRITE_T2_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_CPU_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_MEM_REGISTER)
+
+/*++
+Routine Description:
+ Writes a T2, Memory Module or a CPU CSR.
+
+Arguments:
+ a0 QVA of register to be written.
+ a1 Longword to be written.
+
+Return Value:
+ None.
+--*/
+
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, -0x4000
+ sll t4, 28, t4
+ or t0, t4, t0 // superpage mode
+ stq a1, (t0) // write the quadword
+ mb // order the write
+ mb
+ ret zero, (ra)
+
+2:
+ BREAK_DEBUG_STOP // Bad Qva
+ ret zero, (ra)
+
+ .end WRITE_T2_REGISTER
+
+
+
+ LEAF_ENTRY(READ_T2_REGISTER)
+
+ ALTERNATE_ENTRY(READ_CPU_REGISTER)
+
+ ALTERNATE_ENTRY(READ_MEM_REGISTER)
+
+/*++
+
+Routine Description:
+ Read a T2, Memory Module or CPU CSR.
+
+Arguments:
+ a0 QVA of register to be read.
+
+Return Value:
+ The quadword read from the register.
+
+--*/
+
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, -0x4000
+ sll t4, 28, t4
+ or t0, t4, t0 // superpage mode
+
+ ldq v0, (t0) // read the register
+ mb // synchronize
+ mb //
+
+ ret zero, (ra)
+
+2:
+ BREAK_DEBUG_STOP // Bad Qva
+ ret zero, (ra)
+
+ .end READ_T2_REGISTER
+
+
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the QVA for the Configuration Cycle Type register within the
+// IOC.
+//
+
+// PASS 1 SABLE SUPPORT
+
+#define T2_HAE0_2_QVA (0xbc700008)
+#define T2_HAE02_CYCLETYPE_SHIFT 30
+#define T2_HAE02_CYCLETYPE_MASK 0xc0000000
+
+// PASS 2 SABLE SUPPORT
+
+#define T2_HAE0_3_QVA (0xbc700012)
+#define T2_HAE03_CYCLETYPE_SHIFT 30
+#define T2_HAE03_CYCLETYPE_MASK 0xc0000000
+#define T2_CONFIG_ADDR_QVA (0xbc800000)
+
+// T4 SUPPORT
+
+#define T4_HAE0_3_QVA (0xbc780012)
+#define T4_CONFIG_ADDR_QVA (0xbcc00000)
+
+#define T2_OR_T4 (0x00400000)
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved ConfigurationAddress
+CfgA1: .space 8 // saved ConfigurationData
+CfgA2: .space 8 // padding for 16 byte alignment
+CfgFrameLength:
+
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+
+//
+// PASS 2 sable or Xio access:
+// Cycle type are the only bits in HAE0_3 register
+//
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type in position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual read
+
+//
+// PASS 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1// put cycle type in position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extbl v0, t3, v0 // return byte from requested lane
+ // also, consume loaded value
+ // to cause a pipeline stall
+ mb // Sable requires MBs or the
+ mb // machine check may happen
+ // much later
+
+3: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// PASS 2 sable
+// Merge the configuration cycle type into the HAE0_3 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f
+
+//
+// Merge the configuration cycle type into the HAE0_3 register within
+// the T2.
+//
+
+1:
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t0) // write the configuration byte
+ mb // synchronize
+ mb // synchronize
+
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// Pass 2 Sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual io
+
+//
+// Pass 1 Sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+2:
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extwl v0, t3, v0 // return word from requested lanes
+ // also, consume loaded value
+ // to cause a pipeline stall
+ mb // Sable requires MBs or the
+ mb // machine check may happen
+ // much later
+
+3:
+
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// USHORT ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// Pass 2 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual transfer
+
+
+//
+// Pass 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1, t3, t4 // put data to appropriate lane
+ stl t4, (t0) // read the longword
+ mb // synchronize
+ mb // synchronize
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// PASS 2 sable:
+// Cycle type are the only bits in HAE0_3 register
+//
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type in position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual read
+
+//
+// PASS 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1// put cycle type in position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+2:
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ bis v0, zero, t1 // consume loaded value to cause
+ // a pipeline stall
+ mb // Sable requires MBs or the
+ mb // machine check may happen
+ // much later
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// Pass 2 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual transfer
+
+
+//
+// Pass 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // synchronize
+ mb // synchronize
+
+3: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
diff --git a/private/ntos/nthals/halsable/alpha/sableref.h b/private/ntos/nthals/halsable/alpha/sableref.h
new file mode 100644
index 000000000..b39ca9ce1
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sableref.h
@@ -0,0 +1,280 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ sableref.h
+
+Abstract:
+
+ This file defines the structures and definitions describing the
+ basic Sable family IO structure. These definitions are common to
+ all sable family systems (Sable, Gamma, Lynx...)
+
+Author:
+
+ Steve Brooks 28-Dec 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _SABLEREFH_
+#define _SABLEREFH_
+
+//
+// Define QVA constants for SABLE.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xA0000000) // Identify VA as a QVA
+
+#endif //QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+#define IO_QUAD_OFFSET 0x100 // Offset to next quad
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+//
+// Define size of I/O and memory space for Sable
+// Assume that the HAE==0. This reduces the maximum space from
+// 4Gbytes to 128Mbytes.
+//
+
+#define PCI0_MAX_IO_ADDRESS ((16*1024*1024) - 1)
+#define PCI0_MAX_SPARSE_MEMORY_ADDRESS ((128*1024*1024) - 1)
+#define PCI0_MIN_DENSE_MEMORY_ADDRESS (PCI0_MAX_SPARSE_MEMORY_ADDRESS + 1)
+#define PCI0_MAX_DENSE_MEMORY_ADDRESS (__1GB - 1)
+
+//
+// Definitions for 64Bit PCI Bus (PCI 1)
+//
+
+#define PCI1_MAX_SPARSE_IO_ADDRESS ((16*1024*1024) - 1)
+#define PCI1_MAX_SPARSE_MEMORY_ADDRESS ((64*1024*1024) - 1)
+#define PCI1_MIN_DENSE_MEMORY_ADDRESS (PCI1_MAX_SPARSE_MEMORY_ADDRESS + 1)
+#define PCI1_MAX_DENSE_MEMORY_ADDRESS (__1GB - 1)
+
+//
+// The following constants define the base QVA's for Sables
+// PCI dense spaces. The bus address is used as an offset into this space.
+//
+
+#define SABLE_PCI0_DENSE_MEMORY_QVA 0xc0000000
+#define SABLE_PCI1_DENSE_MEMORY_QVA 0x00000000
+
+// Highest Virtual local PCI Slot is 10 == PCI_AD[21]
+
+#define PCI_MAX_LOCAL_DEVICE 10
+
+//
+// Define physical processor numbers:
+//
+#define SABLE_CPU0 0
+#define SABLE_CPU1 1
+#define SABLE_CPU2 2
+#define SABLE_CPU3 3
+
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// PCI CONFIG_ADDRESS configuration space offsets for Sable PCI devices
+// These are CPU address bit masks, shifted to set in a QVA.
+// PCI
+// IDSEL
+// -----
+#define PCI0_SCSI_HEADER_OFFSET (0x00020000 >> IO_BIT_SHIFT) // AD[12]
+#define PCI0_EISA_BRIDGE_HEADER_OFFSET (0x00040000 >> IO_BIT_SHIFT) // AD[13]
+#define PCI0_SLOT_0_HEADER_OFFSET (0x00400000 >> IO_BIT_SHIFT) // AD[17]
+#define PCI0_SLOT_1_HEADER_OFFSET (0x00800000 >> IO_BIT_SHIFT) // AD[18]
+
+
+//
+// Define the values for the Eisa/Isa bus interrupt levels.
+//
+
+typedef enum _SABLE_EISA_BUS_LEVELS{
+ EisaInterruptLevel3 = 3,
+ EisaInterruptLevel4 = 4,
+ EisaInterruptLevel5 = 5,
+ EisaInterruptLevel6 = 6,
+ EisaInterruptLevel7 = 7,
+ EisaInterruptLevel9 = 9,
+ EisaInterruptLevel10 = 10,
+ EisaInterruptLevel11 = 11,
+ EisaInterruptLevel12 = 12,
+ EisaInterruptLevel14 = 14,
+ EisaInterruptLevel15 = 15
+} SABLE_EISA_BUS_LEVELS, *PSABLE_EISA_BUS_LEVELS;
+
+
+//
+// N.B. The structure below defines the address offsets of the control
+// registers when used with the base QVA. It does NOT define the
+// size or structure of the individual registers.
+//
+typedef struct _SABLE_EDGE_LEVEL_CSRS{
+ UCHAR EdgeLevelControl1;
+ UCHAR EdgeLevelControl2;
+} SABLE_EDGE_LEVEL_CSRS, *PSABLE_EDGE_LEVEL_CSRS;
+
+typedef struct _SABLE_EDGE_LEVEL1_MASK{
+ UCHAR Irq3 : 1;
+ UCHAR Irq4 : 1;
+ UCHAR Irq5 : 1;
+ UCHAR Irq6 : 1;
+ UCHAR Irq7 : 1;
+ UCHAR Irq9 : 1;
+ UCHAR Irq10 : 1;
+ UCHAR Irq11 : 1;
+} SABLE_EDGE_LEVEL1_MASK, *PSABLE_EDGE_LEVEL1_MASK;
+
+typedef struct _SABLE_EDGE_LEVEL2_MASK{
+ UCHAR Irq12 : 1;
+ UCHAR Irq14 : 1;
+ UCHAR Irq15 : 1;
+ UCHAR Reserved : 4;
+ UCHAR Sab : 1;
+} SABLE_EDGE_LEVEL2_MASK, *PSABLE_EDGE_LEVEL2_MASK;
+
+typedef struct _SABLE_INTERRUPT_CSRS{
+ UCHAR InterruptAcknowledge;
+ UCHAR Filler0;
+ UCHAR MasterControl;
+ UCHAR MasterMask;
+ UCHAR Slave0Control;
+ UCHAR Slave0Mask;
+ UCHAR Filler1;
+ UCHAR Filler2;
+ UCHAR Slave1Control;
+ UCHAR Slave1Mask;
+ UCHAR Slave2Control;
+ UCHAR Slave2Mask;
+ UCHAR Slave3Control;
+ UCHAR Slave3Mask;
+} SABLE_INTERRUPT_CSRS, *PSABLE_INTERRUPT_CSRS;
+
+
+//
+// The Sable interrupt vectors are allocated to make dispatching code
+// as efficient as possible. The bits in the 8 bit vector are broken
+// into two fields (sssssooo):
+//
+// sssss - value that selects the slave
+// 0000x = Non-PIC interrupts (always the first 16 vectors)
+// 00010 = Master
+// 00100 = Slave 0
+// 01000 = Slave 1
+// 10000 = Slave 2
+// 10001 = Slave 3
+// ooo - vector offset for the slave
+//
+
+typedef enum _SABLE_INTERRUPT_VECTORS {
+
+ MasterBaseVector = 0x10,
+ MasterVector0 = 0x10,
+ Slave0CascadeVector,
+ MasterVector2,
+ Slave1CascadeVector,
+ Slave2CascadeVector,
+ Slave3CascadeVector,
+ MasterVector6,
+ MasterVector7,
+ MasterPassiveVector = 0x17,
+
+ Slave0BaseVector = 0x20,
+ PciSlot0AVector = 0x20,
+ ScsiPortVector,
+ EthernetPortVector,
+ MouseVector,
+ PciSlot1AVector,
+ PciSlot2AVector,
+ KeyboardVector,
+ FloppyVector,
+ Slave0PassiveVector = 0x27,
+
+ Slave1BaseVector = 0x40,
+ SerialPort1Vector = 0x40,
+ ParallelPortVector,
+ EisaIrq3Vector,
+ EisaIrq4Vector,
+ EisaIrq5Vector,
+ EisaIrq6Vector,
+ EisaIrq7Vector,
+ SerialPort0Vector,
+ Slave1PassiveVector = 0x47,
+
+ Slave2BaseVector = 0x80,
+ EisaIrq9Vector = 0x80,
+ EisaIrq10Vector,
+ EisaIrq11Vector,
+ EisaIrq12Vector,
+ PciSlot2BVector,
+ EisaIrq14Vector,
+ EisaIrq15Vector,
+ I2cVector,
+ Slave2PassiveVector = 0x87,
+
+ Slave3BaseVector = 0x88,
+ PciSlot0BVector = 0x88,
+ PciSlot1BVector,
+ PciSlot0CVector,
+ PciSlot1CVector,
+ PciSlot2CVector,
+ PciSlot0DVector,
+ PciSlot1DVector,
+ PciSlot2DVector,
+ Slave3PassiveVector = 0x8F,
+
+ MaximumSableVector
+
+} SABLE_INTERRUPT_VECTORS, *PSABLE_INTERRUPT_VECTORS;
+
+
+#define SlaveVectorMask (Slave0BaseVector | Slave1BaseVector | Slave2BaseVector | Slave3BaseVector)
+
+//
+// Define the position of the interrupt vectors within the
+// InterruptDispatchTable.
+//
+
+#define SABLE_VECTORS 0x20
+#define SABLE_VECTORS_MAXIMUM (SABLE_VECTORS + MaximumSableVector)
+
+// Highest PCI interrupt vector is in Sable Vector Space
+
+#define PCI_MAX_INTERRUPT_VECTOR MaximumSableVector
+
+//
+// Definitions for the old Standard I/O board (before
+// the 5th (Slave 3) 8259 was added to break out the
+// individual PCI A,B,C,D interrupt pins.
+//
+
+#define OldSlaveVectorMask (Slave0BaseVector | Slave1BaseVector | Slave2BaseVector)
+#define OldPciSlot0Vector PciSlot0AVector
+#define OldPciSlot1Vector PciSlot1AVector
+#define OldPciSlot2Vector PciSlot2AVector
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _SABLEREFH_
diff --git a/private/ntos/nthals/halsable/alpha/sablertc.h b/private/ntos/nthals/halsable/alpha/sablertc.h
new file mode 100644
index 000000000..c0c0d1659
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sablertc.h
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ sablertc.h
+
+Abstract:
+
+ This module is the header file that describes the TOY clock
+ for the Sable.
+
+Author:
+
+ 94.01.16 Steve Jenness
+
+Revision History:
+
+ This file was accidentally removed. It has since been added back.
+ However, since the history information will be lost, the one liner
+ history information was put here.
+
+ Log for ntos\NTHALS\HALSABLE\ALPHA:
+
+ 02-25-94@13:05 V-SJEN3 addfile sablertc.h v1 [v-ntdec] latest Alpha Hal
+ 06-10-94@11:41 JVERT4 in sablertc.h v2 halsettimeincrement
+ 03-28-95@14:29 V-NTDEC1 in sablertc.h v3 fix for 9760 - NVRAM envi
+ 05-25-95@10:59 V-NTDEC1 delfile sablertc.h v4 checked in for 9760
+
+--*/
+
+#ifndef _SABLERTC_
+#define _SABLERTC_
+
+//
+// Sable's RTC is a Dallas Semiconductor 1287
+//
+
+// The APORT and DPORT CSR addresses are defined in a platform
+// specific file.
+
+//
+// The RTC NVRAM byte offsets are 0x0e -- 0x3f.
+//
+// Offsets 0x0E -- 0x3D are reserved for use by VMS/OSF.
+//
+
+#define RTC_RAM_NT_FLAGS0 0x3E // NT firmware flag set #0
+#define RTC_RAM_CONSOLE_SELECTION 0x3F // VMS/OSF/NT boot selection
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_REGNUMBER_RTC_CR1 0x6A
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+//
+// NT firmware flags in TOY NVRAM
+//
+
+typedef struct _RTC_RAM_NT_FLAGS_0 {
+ UCHAR AutoRunECU : 1; // Go directly to ECU
+ UCHAR ResetAfterECU : 1; // Force user to reset after ECU runs
+ UCHAR Fill : 5;
+ UCHAR ConfigurationBit : 1; // Serial line console only
+} RTC_RAM_NT_FLAGS_0, *PRTC_RAM_NT_FLAGS_0;
+
+#define RTC_RAM_NT_FLAGS_0_RUNARCAPP (0x01)
+#define RTC_RAM_NT_FLAGS_0_RESERVED (0x7E)
+#define RTC_RAM_NT_FLAGS_0_USECOM1FORIO (0x80)
+
+#endif //_LANGUAGE_ASSEMBLY
+
+//
+// Values for RTC_RAM_CONSOLE_SELECTION
+//
+
+#define RTC_RAM_CONSOLE_SELECTION_NT 1
+#define RTC_RAM_CONSOLE_SELECTION_VMS 2
+#define RTC_RAM_CONSOLE_SELECTION_OSF 3
+
+//
+// Define initialization values for Sable interval timer
+// rate is 7.8125 ms, 7812.5 us, 78125 clunks
+//
+// The Sable clock is divided by 2 by the
+// Multiprocessor interval clock phasing hardware.
+// The rate select is half what would otherwise be used.
+//
+// #define RTC_RATE_SELECT 0x01
+// #define RTC_PERIOD_IN_CLUNKS 78125
+
+#define RTC_TIMEBASE_DIVISOR 0x02
+
+//
+// Define initialization values for Sable interval timer
+// There are four different rates that are used under NT
+// (see page 9-8 of KN121 System Module Programmer's Reference)
+//
+// .976562 ms
+// 1.953125 ms
+// 3.90625 ms
+// 7.8125 ms
+//
+// The Sable clock is divided by 2 by the
+// Multiprocessor interval clock phasing hardware.
+// The rate select is half what would otherwise be used.
+//
+#define RTC_RATE_SELECT1 5
+#define RTC_RATE_SELECT2 6
+#define RTC_RATE_SELECT3 7
+#define RTC_RATE_SELECT4 8
+
+//
+// note that rates 1-3 have some rounding error,
+// since they are not expressible in even 100ns units
+//
+
+#define RTC_PERIOD_IN_CLUNKS1 9766
+#define RTC_PERIOD_IN_CLUNKS2 19531
+#define RTC_PERIOD_IN_CLUNKS3 39063
+#define RTC_PERIOD_IN_CLUNKS4 78125
+
+//
+// Defaults
+//
+#define MINIMUM_INCREMENT RTC_PERIOD_IN_CLUNKS1
+#define MAXIMUM_INCREMENT RTC_PERIOD_IN_CLUNKS4
+#define MAXIMUM_RATE_SELECT RTC_RATE_SELECT4
+
+#endif // _SABLERTC_
diff --git a/private/ntos/nthals/halsable/alpha/sbinitnt.c b/private/ntos/nthals/halsable/alpha/sbinitnt.c
new file mode 100644
index 000000000..d05e95631
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbinitnt.c
@@ -0,0 +1,1292 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sbinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ a Sable system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+ Steve Jenness 28-Oct-1993 (Sable)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "sablertc.h"
+#include "halpcsl.h"
+#include "pci.h"
+#include "pcip.h"
+#include "isaaddr.h"
+#include "eisa.h"
+#include "iousage.h"
+#include "lyintsup.h"
+#include "siintsup.h"
+#include "xiintsup.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h>
+
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Don't change these values unless you know exactly what you are doing
+//
+#define HAE0_1_REGISTER_VALUE 0x0 // to address SPARSE PCI MEMORY
+#define HAE0_2_REGISTER_VALUE 0x0 // to address PCI IO space
+#define HAE0_3_REGISTER_VALUE 0x0 // For PCI config cycle type
+#define HAE0_4_REGISTER_VALUE 0x0 // to address DENCE PCI Memory
+
+ULONG HalpMemorySlot[4] = { (ULONG)SABLE_MEM0_CSRS_QVA,
+ (ULONG)SABLE_MEM1_CSRS_QVA,
+ (ULONG)SABLE_MEM2_CSRS_QVA,
+ (ULONG)SABLE_MEM3_CSRS_QVA };
+
+ULONG HalpCPUSlot[4] = { (ULONG)SABLE_CPU0_CSRS_QVA,
+ (ULONG)SABLE_CPU1_CSRS_QVA,
+ (ULONG)SABLE_CPU2_CSRS_QVA,
+ (ULONG)SABLE_CPU3_CSRS_QVA };
+
+//
+// Prototypes
+//
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpSenseCBusSlots(
+ VOID
+ );
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+// Block out 8Mb to 144MB
+//
+
+ADDRESS_USAGE
+SablePCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, (__32MB - __8MB), // Start=8MB; Length=24MB
+ 0,0
+ }
+};
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define global for saving the T2 Chipset's version
+//
+
+ULONG T2VersionNumber;
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Sable
+//
+// IRQ_H[0] = Hardware Error
+// IRQ_H[1] = PCI
+// IRQ_H[2] = External IO
+// IRQ_H[3] = IPI
+// IRQ_H[4] = Clock
+// IRQ_H[5] = NMI
+//
+
+// smjfix - This comment doesn't match what is currently happening in the
+// code. Plus it isn't clear that EISA and ISA entries can
+// be split apart.
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+// smjfix - Why is this here? It is a compile time constant for the
+// platform. This is useful only if one HAL is being used
+// for multiple platforms and is being passed from the firmware
+// or detected.
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+//
+// Is the external I/O module present?
+//
+
+BOOLEAN HalpXioPresent = FALSE;
+
+#endif
+
+//
+// Is this a Lynx platform?
+//
+
+BOOLEAN HalpLynxPlatform = FALSE;
+
+//
+// How many processors are ready to run?
+//
+
+ULONG HalpProcessors = 0;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpClearInterrupts(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Sable system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ PKPRCB Prcb;
+ UCHAR Priority;
+ ULONG Vector;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize interrupt handling for the primary processor and
+ // any system-wide interrupt initialization.
+ //
+
+ if( Prcb->Number == SABLE_PRIMARY_PROCESSOR ){
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+//jnfix - this is a noop, can we change this
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt;
+
+#if !defined(NT_UP)
+
+ //
+ // Connect the interprocessor interrupt handler.
+ //
+
+ PCR->InterruptRoutine[IPI_VECTOR] = HalpSableIpiInterrupt;
+
+#endif //NT_UP
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Initialize SIO interrupts.
+ //
+
+ if( HalpLynxPlatform ){
+
+ HalpInitializeLynxSioInterrupts();
+
+ } else {
+
+ HalpInitializeSableSioInterrupts();
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // Initialize XIO interrupts.
+ //
+
+ if( HalpXioPresent ){
+
+ HalpInitializeXioInterrupts();
+
+ }
+
+#endif
+
+ //
+ // Initialize the 21064 interrupts on the current processor
+ // before enabling the individual interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ //
+ // Enable the interrupts for the clock, ipi, pic, xio, APC, and DPC.
+ //
+ // jnfix - enable error interrupts later, including correctable
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ if( HalpLynxPlatform ){
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpLynxSioDispatch;
+
+ } else {
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSableSioDispatch;
+
+ }
+
+ HalEnableSystemInterrupt(PIC_VECTOR, EISA_DEVICE_LEVEL,
+ LevelSensitive);
+
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 1 );
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent && HalpProcessors < 2 ){
+
+ PCR->InterruptRoutine[XIO_VECTOR] = HalpXioDispatch;
+ HalEnableSystemInterrupt(XIO_VECTOR, EISA_DEVICE_LEVEL,
+ LevelSensitive);
+
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = XIO_VECTOR,
+ Priority = 1 );
+
+ }
+
+#endif
+
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK2_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+
+#if !defined(NT_UP)
+
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = IPI_LEVEL,
+ Vector = IPI_VECTOR,
+ Priority = 0 );
+
+#endif //NT_UP
+
+ //
+ // Start the periodic interrupt from the RTC.
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ return TRUE;
+
+ } //end if Prcb->Number == SABLE_PRIMARY_PROCESSOR
+
+
+#if !defined(NT_UP)
+
+ //
+ // Initialize interrupts for the current, secondary processor.
+ //
+
+ //
+ // Connect the clock and ipi interrupt handlers.
+ // jnfix - For now these are the only interrupts we will accept on
+ // jnfix - secondary processors. Later we will add PCI interrupts
+ // jnfix - and the error interrupts.
+ //
+
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpSecondaryClockInterrupt;
+ PCR->InterruptRoutine[IPI_VECTOR] = HalpSableIpiInterrupt;
+
+ //
+ // Initialize the 21064 interrupts for the current processor
+ // before enabling the individual interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ //
+ // Enable the clock, ipi, APC, and DPC interrupts.
+ //
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent && Prcb->Number == SABLE_SECONDARY_PROCESSOR ){
+
+ PCR->InterruptRoutine[XIO_VECTOR] = HalpXioDispatch;
+ HalEnableSystemInterrupt(XIO_VECTOR, EISA_DEVICE_LEVEL,
+ LevelSensitive);
+
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = XIO_VECTOR,
+ Priority = 1 );
+
+ }
+
+#endif
+
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK2_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = IPI_LEVEL,
+ Vector = IPI_VECTOR,
+ Priority = 0 );
+
+#endif //NT_UP
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function clears all pending interrupts on the Sable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for Sable
+ via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+// smjfix - Where is this referenced?
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For Sable, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Sable is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize machine check handling for Sable.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Sable-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies the loader block passed in via the OsLoader.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+ PRESTART_BLOCK RestartBlock;
+ ULONGLONG Value;
+ T2_IOCSR Iocsr;
+
+ Prcb = PCR->Prcb;
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR) {
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Determine how many processors are ready to run. We use
+ // this information to decide whether to split SIO/XIO
+ // interrupts across two processors or not.
+ //
+
+#ifdef NT_UP
+
+ HalpProcessors = 1;
+
+#else
+
+ HalpProcessors = 0;
+
+ for( RestartBlock = SYSTEM_BLOCK->RestartBlock;
+ RestartBlock != NULL;
+ RestartBlock = RestartBlock->NextRestartBlock ){
+
+ if( RestartBlock->BootStatus.ProcessorReady ){
+
+ HalpProcessors++;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Initialize the performance counter.
+ //
+
+ HalCalibratePerformanceCounter( NULL );
+
+
+ //
+ // Parse the loader block - this sets global for PCI parity check
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish Error Handler to pick up PCI parity changes
+ //
+
+ HalpEstablishErrorHandler();
+
+ //
+ // Determine the T2 Chipset's Version Number. Save Version in Global.
+ //
+ // T2VersionNumber Pass
+ //
+ // 000 1
+ // 001 2
+ //
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T2_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+ T2VersionNumber = Iocsr.T2RevisionNumber;
+
+ HalpInitializeHAERegisters();
+
+ HalpSenseCBusSlots();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiling for the primary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ } else {
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Sable is the default EV4 parity-mode handler. Note
+ // that this was done in HalpEstablishErrorHandler() for the
+ // primary processor.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize profiling on this secondary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR data;
+ SABLE_SIC_CSR Sic;
+
+ //
+ // Acknowledge the clock interrupt in the real time clock.
+ // We don't need to do an ACK to the RTC since we're using the
+ // DS1459A RTC's square wave instead of periodic interrupt to
+ // generate the periodic clock. Each processor board has it's own
+ // periodic clock interrupt latch that needs to be cleared.
+ //
+ // This code is MP safe since the Sic is per-processor.
+
+ RtlZeroMemory( &Sic, sizeof(Sic) );
+
+ Sic.IntervalTimerInterruptClear = 1;
+
+ WRITE_CPU_REGISTER( &((PSABLE_CPU_CSRS)(SABLE_CPU0_CSRS_QVA))->Sic,
+ *(PULONGLONG)&Sic );
+
+ return;
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+//
+//
+//
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the T2 chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // Set Hae0_1, Hae0_2, Hae0_3 and Hae0_4 registers
+ //
+ // IMPORTANT: IF YOU CHANGE THE VALUE OF THE HAE0_1 REGISTERS PLEASE
+ // REMEMBER YOU WILL NEED TO CHANGE:
+ //
+ // PCI_MAX_MEMORY_ADDRESS IN halalpha\sable.h
+ // SablePCIMemorySpace in this file to report holes
+ //
+
+ // SPARSE SPACE: Hae0_1
+ //
+ // We set Hae0_1 to 0MB. Which means we have the following
+ // PCI Sparse Memory addresses:
+ // 0 to 8MB VALID. Hae0_1 Not used in address translation
+ // 8 to 16MB Invalid.
+ // 16 to 32MB Invalid. Used for Isa DMA copy for above 16MB
+ // 32 to 128MB VALID. Hae0_1 used in address translation
+
+ //
+ // All invalid addresses are reported to be used by the hal.
+ // see SablePCIMemorySpace above.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1,
+ HAE0_1_REGISTER_VALUE );
+
+
+ // PCI IO SPACE: Hae0_2
+ //
+ // We set Hae0_2 to MB. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. Hae0_2 Not used in address translation
+ // 64K to 16MB VALID. Hae0_2 is used in the address translation
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2,
+ HAE0_2_REGISTER_VALUE );
+
+
+ if( T2VersionNumber != 0 ) {
+
+ // PCI CONFIG CYCLE TYPE: Hae0_3
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3,
+ HAE0_3_REGISTER_VALUE );
+
+ // PCI DENSE MEMORY: Hae0_4
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4,
+ HAE0_4_REGISTER_VALUE );
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the external I/O module is present, initialize the HAe
+ // register on the T4.
+ //
+
+ if( HalpXioPresent ){
+
+ //
+ // All invalid addresses are reported to be used by the hal.
+ // see SablePCIMemorySpace above.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_1,
+ HAE0_1_REGISTER_VALUE );
+
+ //
+ // PCI IO SPACE: Hae0_2
+ //
+ // We set Hae0_2 to MB. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. Hae0_2 Not used in address translation
+ // 64K to 16MB VALID. Hae0_2 is used in the address translation
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_2,
+ HAE0_2_REGISTER_VALUE );
+
+
+ //
+ // PCI CONFIG CYCLE TYPE: Hae0_3
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_3,
+ HAE0_3_REGISTER_VALUE );
+
+ //
+ // PCI DENSE MEMORY: Hae0_4
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_4,
+ HAE0_4_REGISTER_VALUE );
+
+ }
+
+#endif
+
+ //
+ // Report that the SPARSE SPACE mapping to the Io subsystem
+ //
+
+ HalpRegisterAddressUsage (&SablePCIMemorySpace);
+
+}
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1, 0 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2, 0 );
+
+ if( T2VersionNumber != 0) {
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3, 0 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4, 0 );
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpSenseCBusSlots(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function Probes the Cbus looking for slots that are filled.
+ are only 8 Cbus locations we can look at (4 memory, 4 CPU).
+
+ If we find a module, we will fill in the table at the
+ appropriate location -- if no module is found, then place a
+ zero there.
+
+Note:
+
+ This routine will machine check in an empty slot -- and is expected.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ ULONG i;
+ ULONG CSR;
+
+ for (i=0; i<4; i++) {
+ if (HalpMemorySlot[i] != 0) {
+ CSR = (ULONG)READ_MEM_REGISTER((PVOID)HalpMemorySlot[i]);
+ if (CSR == 0xffffffff) {
+ HalpMemorySlot[i] = 0;
+ }
+#if HALDBG
+ if (HalpMemorySlot[i] == 0) {
+ DbgPrint("Memory Slot %d is EMPTY\n", i);
+ } else {
+ DbgPrint("Memory Slot %d is POPULATED\n", i);
+ }
+#endif
+ }
+ }
+
+ for (i=0; i<4; i++) {
+ if (HalpCPUSlot[i] != 0) {
+ CSR = (ULONG)READ_CPU_REGISTER((PVOID)HalpCPUSlot[i]);
+ if (CSR == 0xffffffff) {
+ HalpCPUSlot[i] = 0;
+ }
+#if HALDBG
+ if (HalpCPUSlot[i] == 0) {
+ DbgPrint("CPU Slot %d is EMPTY\n", i);
+ } else {
+ DbgPrint("CPU Slot %d is POPULATED\n", i);
+ }
+#endif
+ }
+ }
+}
+
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(SABLE_UNCORRECTABLE_FRAME);
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Sable";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV4_UNCORRECTABLE processorFrame;
+ SABLE_UNCORRECTABLE_FRAME SableUnCorrrectable;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halsable/alpha/sbintr.s b/private/ntos/nthals/halsable/alpha/sbintr.s
new file mode 100644
index 000000000..1ae7df100
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbintr.s
@@ -0,0 +1,94 @@
+// TITLE("Clock and Eisa Interrupt Handlers")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// sbintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for the
+// Sable system.
+//
+// Author:
+//
+// Joe Notarangelo 29-Oct-1993
+// Steve Jenness 29-Oct-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halalpha.h"
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// VOID
+// HalpSableIpiInterrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interprocessor
+// interrupt asserted on the current processor. This function is
+// responsible for acknowledging the interrupt and dispatching to
+// the kernel for processing.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSableIpiInterrupt)
+
+//
+// Acknowledge the IPI interrupt by clearing the RequestInterrupt bit
+// of the IPIR register for the current processor.
+//
+// N.B. - Clearing the RequestInterrupt bit of the IPIR is accomplished
+// by writing a zero to the register. This eliminates the need
+// to perform a read-modify-write operation but loses the state
+// of the RequestNodeHaltInterrupt bit. Currently, this is fine
+// because the RequestNodeHalt feature is not used. Were it to
+// be used in the future, then this short-cut would have to be
+// reconsidered.
+//
+// N.B. - The code to write a sable CPU register is inlined here for
+// performance.
+//
+
+//jnfix - define elsewhere
+#define PcHalIpirSva 0x18
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldq v0, PcHalReserved + PcHalIpirSva(v0) // get per-processor
+ // CPU IPIR SVA
+ stq zero, (v0) // clear IPIR
+ mb // synchronize the write
+
+//
+// Call the kernel to processor the interprocessor request.
+//
+ ldl t0, __imp_KeIpiInterrupt
+ jmp zero, (t0) // call kernel to process
+
+//
+// Control is returned from KeIpiInterrupt to the caller.
+//
+
+ .end HalpSableIpiInterrupt
+
diff --git a/private/ntos/nthals/halsable/alpha/sbintsup.c b/private/ntos/nthals/halsable/alpha/sbintsup.c
new file mode 100644
index 000000000..66e167389
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbintsup.c
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sbintsup.c
+
+Abstract:
+
+ This module provides support for Sable-specific interrupts.
+
+Author:
+
+ Steve Jenness 28-Oct-1993
+ Joe Notarangelo 28-Oct-1993
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Sable comes from the Dallas DS1287A real-time clock. Sable
+ uses the Square Wave from the RTC and distributes it out of phase
+ to each of the processors. The acknowledgement of the interrupt is
+ done by clearing an interrupt latch on each processor board.
+
+ The interrupt generated directly by the RTC is not used and does not
+ need to be acknowledged.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PSABLE_CPU_CSRS CurrentCpuCsrs;
+ SABLE_SIC_CSR Sic;
+
+ CurrentCpuCsrs = HAL_PCR->CpuCsrsQva;
+
+ //
+ // Acknowledge the interval timer interrupt on the current processor.
+ //
+
+ Sic.all = 0;
+ Sic.IntervalTimerInterruptClear = 1;
+
+ WRITE_CPU_REGISTER( &CurrentCpuCsrs->Sic,
+ *(PULONGLONG)&Sic );
+
+ return;
+}
+
+VOID
+HalpAcknowledgeIpiInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the interprocessor interrupt on the current processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PSABLE_CPU_CSRS CurrentCpuCsrs;
+
+ CurrentCpuCsrs = HAL_PCR->CpuCsrsQva;
+
+ //
+ // Acknowledge the interprocessor interrupt by clearing the
+ // RequestInterrupt bit of the IPIR register for the current processor.
+ //
+ // N.B. - Clearing the RequestInterrupt bit of the IPIR is accomplished
+ // by writing a zero to the register. This eliminates the need
+ // to perform a read-modify-write operation but loses the state
+ // of the RequestNodeHaltInterrupt bit. Currently, this is fine
+ // because the RequestNodeHalt feature is not used. Were it to
+ // be used in the future, then this short-cut would have to be
+ // reconsidered.
+ //
+
+ WRITE_CPU_REGISTER( &CurrentCpuCsrs->Ipir,
+ (ULONGLONG)0 );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/sbmapio.c b/private/ntos/nthals/halsable/alpha/sbmapio.c
new file mode 100644
index 000000000..f902b1506
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbmapio.c
@@ -0,0 +1,205 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Sable system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "isaaddr.h"
+
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+//
+// Define the array that maps logical processor numbers to the corresponding
+// QVA for that processor's CPU CSRs.
+//
+
+PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a Sable
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+#if !defined(AXP_FIRMWARE)
+
+ PKPRCB Prcb;
+ extern HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Assign CPU specific CSR address
+ //
+
+ switch( HalpLogicalToPhysicalProcessor[Prcb->Number] ) {
+
+ case SABLE_CPU0:
+ HAL_PCR->IpirSva = SABLE_CPU0_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU0_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU0_CSRS_QVA;
+ break;
+
+ case SABLE_CPU1:
+ HAL_PCR->IpirSva = SABLE_CPU1_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU1_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU1_CSRS_QVA;
+ break;
+
+ case SABLE_CPU2:
+ HAL_PCR->IpirSva = SABLE_CPU2_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU2_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU2_CSRS_QVA;
+ break;
+
+ case SABLE_CPU3:
+ HAL_PCR->IpirSva = SABLE_CPU3_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU3_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU3_CSRS_QVA;
+ break;
+
+ default:
+#ifdef HALDBG
+ DbgPrint("HalpMapIoSpace: Invalid Cpu number %d\n", Prcb->Number);
+ DbgBreakPoint();
+#else
+ ;
+#endif // HALDBG
+ }
+
+#endif // AXP_FIRMWARE
+
+ //
+ // Map EISA control space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( SABLE_PCI0_SPARSE_IO_PHYSICAL );
+ HalpEisaControlBase = PciIoSpaceBase;
+
+ HalpCMOSRamBase = (PVOID)
+ ( (ULONG)HAL_MAKE_QVA( SABLE_PCI0_SPARSE_IO_PHYSICAL ) +
+ CMOS_ISA_PORT_ADDRESS );
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(SABLE_PCI0_SPARSE_IO_PHYSICAL) +
+ ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/sbsysint.c b/private/ntos/nthals/halsable/alpha/sbsysint.c
new file mode 100644
index 000000000..3dd114faa
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbsysint.c
@@ -0,0 +1,456 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sbsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Sable system.
+
+Author:
+
+ Joe Notarangelo 29-Oct-1993
+ Steve Jenness 29-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+#include "siintsup.h"
+#include "lyintsup.h"
+#include "xiintsup.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire the system interrupt
+ // lock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch( Vector ){
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+
+ break;
+
+ default:
+
+ if( Irql == DEVICE_LEVEL ){
+
+ if( HalpLynxPlatform ){
+
+ HalpDisableLynxSioInterrupt( Vector );
+
+ } else {
+
+ HalpDisableSableSioInterrupt( Vector );
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ //
+ // Release the system interrupt lock and restore the IRWL.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ KeLowerIrql(OldIrql);
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ default:
+
+ if( HalpLynxPlatform ){
+
+ Enabled = HalpEnableLynxSioInterrupt( Vector, InterruptMode );
+
+ } else {
+
+ Enabled = HalpEnableSableSioInterrupt( Vector, InterruptMode );
+
+ }
+
+ break;
+
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ return Enabled;
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+// We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
+ for ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ ULONG Vector;
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( InterfaceType == ProcessorInternal ) {
+
+ Vector = HalpGet21064PerformanceVector( BusInterruptLevel, Irql );
+
+ if( Vector != 0 ){
+
+ //
+ // Success
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ }
+
+ }
+
+ //
+ // Handle Isa/Eisa bus and Internal devices.
+ //
+ // N.B. The bus interrupt level is the actual E/ISA signal name for
+ // option boards while the bus interrupt level is the actual
+ // interrupt vector number for internal devices. The interrupt
+ // vectors for internal devices are specified in the firmware
+ // configuration and are agreed upon between the firmware and this
+ // code.
+ //
+
+ if( (InterfaceType == Internal) ||
+ (InterfaceType == Isa) ||
+ (InterfaceType == PCIBus) ||
+ (InterfaceType == Eisa) ){
+
+ if( HalpLynxPlatform ){
+
+ return HalpGetLynxSioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ } else {
+
+ return HalpGetSableSioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ }
+
+
+ //
+ // Not an interface supported on Alpha systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SABLE_IPIR_CSR Ipir;
+ extern PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+
+ //
+ // Set up to request an interprocessor interrupt.
+ //
+
+ Ipir.all = 0;
+ Ipir.RequestInterrupt = 1;
+
+ //
+ // N.B. Sable supports up to 4 processors only.
+ //
+ // N.B. A read-modify-write is not performed on the Ipir register
+ // which implies that the value of the request halt interrupt
+ // bit may be lost. Currently, this is not an important
+ // consideration because that feature is not being used.
+ // If later it is used than more consideration must be given
+ // to the possibility of losing the bit.
+ //
+
+ //
+ // The request mask is specified as a mask of the logical processors
+ // that must receive IPI requests. HalpSableCpuCsrs[] contains the
+ // CPU CSRs address for the logical processors.
+ //
+
+ //
+ // Request an IPI for processor 0 if requested.
+ //
+
+ if( Mask & HAL_CPU0_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU0]->Ipir), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 1 if requested.
+ //
+
+ if( Mask & HAL_CPU1_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU1]->Ipir), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 2 if requested.
+ //
+
+ if( Mask & HAL_CPU2_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU2]->Ipir), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 3 if requested.
+ //
+
+ if( Mask & HAL_CPU3_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU3]->Ipir), Ipir.all );
+
+ }
+
+
+
+
+ return;
+}
diff --git a/private/ntos/nthals/halsable/alpha/siintsup.c b/private/ntos/nthals/halsable/alpha/siintsup.c
new file mode 100644
index 000000000..6ea2a3784
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/siintsup.c
@@ -0,0 +1,1332 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ siintsup.c
+
+Abstract:
+
+ This module provides interrupt support for the Sable Standard I/O
+ board.
+
+Author:
+
+ Steve Jenness 28-Oct-1993
+ Joe Notarangelo 28-Oct-1993
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "xiintsup.h"
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for 8259 interrupt mask registers.
+//
+// N.B. - Mask values of 1 indicate that the interrupt is disabled.
+//
+
+UCHAR MasterInterruptMask;
+UCHAR Slave0InterruptMask;
+UCHAR Slave1InterruptMask;
+UCHAR Slave2InterruptMask;
+UCHAR Slave3InterruptMask;
+
+//
+// Define save area for Edge/Level controls.
+//
+// N.B. - Mask values of 1 indicate that the interrupt is level triggered.
+// Mask values of 0 indicate that the interrupt is edge triggered.
+//
+
+SABLE_EDGE_LEVEL1_MASK EdgeLevel1Mask;
+SABLE_EDGE_LEVEL2_MASK EdgeLevel2Mask;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+
+ULONG
+HalpGetSableSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ *Irql = DEVICE_LEVEL;
+ *Affinity = HAL_CPU0_MASK;
+
+ switch( BusInterruptLevel ){
+
+ case EisaInterruptLevel3:
+ return( SABLE_VECTORS + EisaIrq3Vector );
+
+ case EisaInterruptLevel4:
+ return( SABLE_VECTORS + EisaIrq4Vector );
+
+ case EisaInterruptLevel5:
+ return( SABLE_VECTORS + EisaIrq5Vector );
+
+ case EisaInterruptLevel6:
+ return( SABLE_VECTORS + EisaIrq6Vector );
+
+ case EisaInterruptLevel7:
+ return( SABLE_VECTORS + EisaIrq7Vector );
+
+ case EisaInterruptLevel9:
+ return( SABLE_VECTORS + EisaIrq9Vector );
+
+ case EisaInterruptLevel10:
+ return( SABLE_VECTORS + EisaIrq10Vector );
+
+ case EisaInterruptLevel11:
+ return( SABLE_VECTORS + EisaIrq11Vector );
+
+ case EisaInterruptLevel12:
+ return( SABLE_VECTORS + EisaIrq12Vector );
+
+ case EisaInterruptLevel14:
+ return( SABLE_VECTORS + EisaIrq14Vector );
+
+ case EisaInterruptLevel15:
+ return( SABLE_VECTORS + EisaIrq15Vector );
+
+ //
+ // Handle Vectors for the Internal bus devices.
+ //
+
+ case MouseVector:
+ case KeyboardVector:
+ case FloppyVector:
+ case SerialPort1Vector:
+ case ParallelPortVector:
+ case SerialPort0Vector:
+ case I2cVector:
+
+ //
+ // Handle Vectors for PCI devices.
+ //
+
+ case ScsiPortVector:
+ case EthernetPortVector:
+ case PciSlot0AVector:
+ case PciSlot0BVector:
+ case PciSlot0CVector:
+ case PciSlot0DVector:
+ case PciSlot1AVector:
+ case PciSlot1BVector:
+ case PciSlot1CVector:
+ case PciSlot1DVector:
+ case PciSlot2AVector:
+ case PciSlot2BVector:
+ case PciSlot2CVector:
+ case PciSlot2DVector:
+
+ return( SABLE_VECTORS + BusInterruptLevel );
+
+ default:
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpGetXioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+#else
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+#endif
+
+ }
+}
+
+
+BOOLEAN
+HalpInitializeSableSioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+#if 0
+
+// smjfix - EISA NMI support needs to be done.
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Enable Software-Generated NMI interrupts by setting bit 1 of port 0x461.
+ //
+
+ DataByte = 0x02;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+#endif //0
+
+ //
+ // Raise the IRQL while the Sable interrupt controllers are initialized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the Sable interrupt controllers. The interrupt structure
+ // is one master interrupt controller with 3 cascaded slave controllers.
+ // Proceed through each control word programming each of the controllers.
+ //
+
+ //
+ // Default all E/ISA interrupts to edge triggered.
+ //
+
+ RtlZeroMemory( &EdgeLevel1Mask, sizeof(EdgeLevel1Mask) );
+ RtlZeroMemory( &EdgeLevel2Mask, sizeof(EdgeLevel2Mask) );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl1,
+ *(PUCHAR)&EdgeLevel1Mask
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl2,
+ *(PUCHAR)&EdgeLevel2Mask
+ );
+
+ //
+ // Write control word 1 for each of the controllers, indicate
+ // that initialization is in progress and the control word 4 will
+ // be used.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control,
+ DataByte
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control,
+ DataByte
+ );
+
+ //
+ // Write control word 2 for each of the controllers, set the base
+ // interrupt vector for each controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ MasterBaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0BaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1BaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2BaseVector
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3BaseVector
+ );
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ DataByte = ( (1 << (Slave0CascadeVector & 0x7)) |
+ (1 << (Slave1CascadeVector & 0x7)) |
+ (1 << (Slave2CascadeVector & 0x7)) |
+ (1 << (Slave3CascadeVector & 0x7))
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ (Slave0CascadeVector & 0x7)
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ (Slave1CascadeVector & 0x7)
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ (Slave2CascadeVector & 0x7)
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ (Slave3CascadeVector & 0x7)
+ );
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+#ifdef SIO_AEOI
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
+#endif
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ DataByte
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ DataByte
+ );
+
+ //
+ // Disable all of the interrupts except the slave interrupts to the
+ // master controller.
+ //
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ MasterInterruptMask = (UCHAR)( ~( (1 << (Slave0CascadeVector & 0x7)) |
+ (1 << (Slave1CascadeVector & 0x7)) |
+ (1 << (Slave2CascadeVector & 0x7)) |
+ (1 << (Slave3CascadeVector & 0x7))
+ )
+ );
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ MasterInterruptMask
+ );
+
+ Slave0InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0InterruptMask
+ );
+
+ Slave1InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1InterruptMask
+ );
+
+ Slave2InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2InterruptMask
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ Slave3InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3InterruptMask
+ );
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpSableSioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ This routine is responsible for determining the
+ source of the interrupt, performing the secondary dispatch and
+ acknowledging the interrupt in the 8259 controllers.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT IdtIndex;
+ UCHAR MasterInService;
+ UCHAR Slave0InService;
+ UCHAR Slave1InService;
+ UCHAR Slave2InService;
+ UCHAR Slave3InService;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS)
+ SABLE_INTERRUPT_CSRS_QVA)->InterruptAcknowledge
+ );
+
+ switch( interruptVector ){
+
+ //
+ // Check for possible passive release in the master controller.
+ //
+
+//jnfix - #define for 0x0b
+ case MasterPassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( MasterInterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Master in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ 0x0B
+ );
+
+ MasterInService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl);
+
+ if( !(MasterInService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+
+ //
+ // Check for possible passive release in the slave0 controller.
+ //
+
+ case Slave0PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave0InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 0 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control,
+ 0x0B
+ );
+
+ Slave0InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control);
+
+ if( !(Slave0InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+ //
+ // Check for possible passive release in the slave1 controller.
+ //
+
+ case Slave1PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave1InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 1 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control,
+ 0x0B
+ );
+
+ Slave1InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control);
+
+ if( !(Slave1InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+ //
+ // Check for possible passive release in the slave2 controller.
+ //
+
+ case Slave2PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave2InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 2 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control,
+ 0x0B
+ );
+
+ Slave2InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control);
+
+ if( !(Slave2InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ //
+ // Check for possible passive release in the slave3 controller.
+ //
+
+ case Slave3PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave3InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 3 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control,
+ 0x0B
+ );
+
+ Slave3InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control);
+
+ if( !(Slave3InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+ //
+ // The vector is NOT a possible passive release.
+ //
+
+ default:
+
+ break;
+
+ } //end switch( interruptVector )
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ IdtIndex = interruptVector + SABLE_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+#ifndef SIO_AEOI
+
+ //
+ // Dismiss the interrupt in the 8259 interrupt controllers.
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ switch (interruptVector & SlaveVectorMask) {
+
+ case Slave0BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+
+ case Slave1BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+
+ case Slave2BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+
+ case Slave3BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+#endif // SIO_AEOI
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the Sable bus specified Sable bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the Sable interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Interrupt;
+
+ if( ((Vector >= SABLE_VECTORS + MasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + MasterPassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave0BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave0PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave1BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave1PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave2BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave2PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave3BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave3PassiveVector)) ){
+
+ //
+ // Calculate the Sable relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & ~SlaveVectorMask;
+
+ //
+ // Disable the interrupt for the appropriate interrupt controller.
+ //
+
+ switch (Vector & SlaveVectorMask) {
+
+ case Slave0BaseVector:
+
+ Slave0InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0InterruptMask
+ );
+
+ break;
+
+ case Slave1BaseVector:
+
+ Slave1InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1InterruptMask
+ );
+
+ break;
+
+ case Slave2BaseVector:
+
+ Slave2InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2InterruptMask
+ );
+
+ break;
+
+ case Slave3BaseVector:
+
+ Slave3InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3InterruptMask
+ );
+
+ break;
+
+ case MasterBaseVector:
+
+ break;
+ }
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ HalpDisableXioInterrupt( Vector );
+
+#endif
+
+ }
+}
+
+BOOLEAN
+HalpEnableSableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Sable specified interrupt in the
+ appropriate 8259 interrupt controllers. It also supports the
+ edge/level control for EISA bus interrupts. By default, all interrupts
+ are edge detected (and latched).
+
+Arguments:
+
+ Vector - Supplies the vector of the Sable interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (Edge).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Interrupt;
+ UCHAR ModeBit;
+
+ if( ((Vector >= SABLE_VECTORS + MasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + MasterPassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave0BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave0PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave1BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave1PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave2BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave2PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave3BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave3PassiveVector)) ){
+
+ //
+ // Calculate the Sable relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & ~SlaveVectorMask;
+
+ //
+ // Enable the interrupt for the appropriate interrupt controller.
+ //
+
+ switch( Vector & SlaveVectorMask ) {
+
+ case Slave0BaseVector:
+
+ Slave0InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0InterruptMask
+ );
+
+ break;
+
+ case Slave1BaseVector:
+
+ if( InterruptMode == LevelSensitive )
+ ModeBit = 1;
+ else
+ ModeBit = 0;
+
+ switch( Vector ) {
+
+ case EisaIrq3Vector:
+ EdgeLevel1Mask.Irq3 = ModeBit;
+ break;
+
+ case EisaIrq4Vector:
+ EdgeLevel1Mask.Irq4 = ModeBit;
+ break;
+
+ case EisaIrq5Vector:
+ EdgeLevel1Mask.Irq5 = ModeBit;
+ break;
+
+ case EisaIrq6Vector:
+ EdgeLevel1Mask.Irq6 = ModeBit;
+ break;
+
+ case EisaIrq7Vector:
+ EdgeLevel1Mask.Irq7 = ModeBit;
+ break;
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl1,
+ *(PUCHAR)&EdgeLevel1Mask
+ );
+
+ Slave1InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1InterruptMask
+ );
+
+ break;
+
+ case Slave2BaseVector:
+
+ if( InterruptMode == LevelSensitive )
+ ModeBit = 1;
+ else
+ ModeBit = 0;
+
+ switch( Vector ) {
+
+ case EisaIrq9Vector:
+ EdgeLevel1Mask.Irq9 = ModeBit;
+ break;
+
+ case EisaIrq10Vector:
+ EdgeLevel1Mask.Irq10 = ModeBit;
+ break;
+
+ case EisaIrq11Vector:
+ EdgeLevel1Mask.Irq11 = ModeBit;
+ break;
+
+ case EisaIrq12Vector:
+ EdgeLevel2Mask.Irq12 = ModeBit;
+ break;
+
+ case EisaIrq14Vector:
+ EdgeLevel2Mask.Irq14 = ModeBit;
+ break;
+
+ case EisaIrq15Vector:
+ EdgeLevel2Mask.Irq15 = ModeBit;
+ break;
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl1,
+ *(PUCHAR)&EdgeLevel1Mask
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl2,
+ *(PUCHAR)&EdgeLevel2Mask
+ );
+
+ Slave2InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2InterruptMask
+ );
+
+ break;
+
+ case Slave3BaseVector:
+
+ Slave3InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3InterruptMask
+ );
+
+ break;
+
+ case MasterBaseVector:
+
+ break;
+ }
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpEnableXioInterrupt( Vector, InterruptMode );
+
+#else
+
+ return FALSE;
+
+#endif
+
+ }
+
+ return TRUE;
+}
+
+
+#if 0 //jnfix - add NMI handling later
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ BusAddress.HighPart = 0;
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++)
+ {
+ BusAddress.LowPart = (EisaPort << 12) + 0xC80;
+
+ Status = HalTranslateBusAddress(Eisa, // InterfaceType
+ 0, // BusNumber
+ BusAddress,
+ &AddressSpace, // 1=I/O address space
+ &TranslatedAddress); // QVA
+ if (Status == FALSE)
+ {
+ UCHAR pbuf[80];
+ sprintf(pbuf,
+ "Unable to translate bus address %x for EISA slot %d\n",
+ BusAddress.LowPart, EisaPort);
+ HalDisplayString(pbuf);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+
+ port = TranslatedAddress.LowPart;
+
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+#if 0
+ // Reset NMI interrupts (for debugging purposes only).
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02);
+#endif
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+#endif //0
+
+//smjfix - This routine should be removed. The eisasup.c module should be
+// broken apart and restructured.
+
+//
+// This is a stub routine required because all of the EISA support is in
+// a single module in halalpha\eisasup.c.
+//
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ IN PVOID ServiceContext
+ )
+{
+ DbgPrint("HalpAcknowledgeEisaInterrupt: this should not be called on Sable");
+ DbgBreakPoint();
+
+ return(0);
+}
diff --git a/private/ntos/nthals/halsable/alpha/siintsup.h b/private/ntos/nthals/halsable/alpha/siintsup.h
new file mode 100644
index 000000000..dcaf4a029
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/siintsup.h
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ siintsup.h
+
+Abstract:
+
+ This header file contains prototypes for siintsup.c.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+ULONG
+HalpGetSableSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpInitializeSableSioInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpSableSioDispatch(
+ VOID
+ );
+
+VOID
+HalpDisableSableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEnableSableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
diff --git a/private/ntos/nthals/halsable/alpha/t2.c b/private/ntos/nthals/halsable/alpha/t2.c
new file mode 100644
index 000000000..f333da400
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/t2.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\t2.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/vga.c b/private/ntos/nthals/halsable/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/xiintsup.c b/private/ntos/nthals/halsable/alpha/xiintsup.c
new file mode 100644
index 000000000..4c14ce127
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/xiintsup.c
@@ -0,0 +1,912 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ xiintsup.c
+
+Abstract:
+
+ This module provides interrupt support for the Sable/Gamma/Lynx
+ External I/O module.
+
+Author:
+
+ Dave Richarda 1-June-1995
+
+Revision History:
+
+--*/
+
+#ifdef XIO_PASS1
+
+#include "halp.h"
+#include "eisa.h"
+#include "sableref.h"
+#include "xiintsup.h"
+
+//
+// External I/O 8259 Mask registers.
+//
+
+UCHAR XioMasterInterruptMask;
+UCHAR XioSlaveInterruptMask;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+extern ULONG HalpProcessors;
+
+
+ULONG
+HalpGetXioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if( HalpXioPresent ){
+
+ switch( BusInterruptLevel ){
+
+ case XioPciSlot0AVector:
+ case XioPciSlot0BVector:
+ case XioPciSlot0CVector:
+ case XioPciSlot0DVector:
+ case XioPciSlot1AVector:
+ case XioPciSlot1BVector:
+ case XioPciSlot1CVector:
+ case XioPciSlot1DVector:
+
+ *Irql = PCI_DEVICE_LEVEL;
+
+ if( HalpProcessors > 1 ){
+ *Affinity = HAL_CPU1_MASK;
+ } else {
+ *Affinity = HAL_CPU0_MASK;
+ }
+
+ return( SABLE_VECTORS + BusInterruptLevel );
+
+ }
+ }
+
+ //
+ // The caller specified a bus level not support by this platform.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+}
+
+
+BOOLEAN
+HalpInitializeXioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine does the following:
+ (1) initializes the Xio 8259 interrupt registers
+ (2) initializes structures necessary for EISA operations
+ (3) connects the intermediate interrupt dispatcher.
+ (4) initializes the EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the Xio interrupt controllers. The interrupt structure
+ // is one master interrupt controller with 1 cascaded slave controller.
+ // Proceed through each control word programming each of the controllers.
+ //
+
+ //
+ // Write control word 1 for each of the controllers, indicate
+ // that initialization is in progress and the control word 4 will
+ // be used.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+// ((PINITIALIZATION_COMMAND_1) &DataByte)->LevelTriggeredMode = 1;
+ DataByte |= 0x04;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
+ DataByte
+ );
+
+ //
+ // Write control word 2 for each of the controllers, set the base
+ // interrupt vector for each controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ XioMasterBaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveBaseVector
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = (1 << (XioSlaveCascadeVector & ~XioMasterBaseVector) );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ (XioSlaveCascadeVector & ~XioMasterBaseVector)
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+#ifdef XIO_AEOI
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
+#endif
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ DataByte
+ );
+
+ //
+ // Disable all of the interrupts except the slave interrupts to the
+ // master controller.
+ //
+
+ XioMasterInterruptMask =
+ (UCHAR)( ~(1 << (XioSlaveCascadeVector & ~XioMasterBaseVector)) );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ XioMasterInterruptMask
+ );
+
+ XioSlaveInterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveInterruptMask
+ );
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpXioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an interrupt being generated
+ via the vector that is directly connected XIO device interrupt.
+
+ This routine is responsible for determining the
+ source of the interrupt, performing the secondary dispatch and
+ acknowledging the interrupt in the 8259 controllers.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ BOOLEAN returnValue;
+ USHORT IdtIndex;
+ UCHAR InService;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &((PXIO_INTERRUPT_CSRS)
+ XIO_INTERRUPT_CSRS_QVA)->InterruptAcknowledge
+ );
+
+ //
+ // If we get a passive release, send a non-specific end of interrupt
+ // command and return TRUE, indicating that we processed the interrupt.
+ //
+
+ switch( interruptVector ){
+
+ case XioMasterPassiveReleaseVector:
+
+#ifdef XIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( XioMasterInterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // XIO_AEOI
+
+ //
+ // Read the "in-service" mask.
+ //
+
+ WRITE_PORT_UCHAR( &((PSABLE_INTERRUPT_CSRS)SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ 0x0B
+ );
+
+ InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl
+ );
+
+ if( (InService & 0x80) == 0 ){
+
+ //
+ // Send end of interrupt to clear the passive release in the
+ // master controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+
+ }
+
+#endif // XIO_AEOI
+
+ break;
+
+ case XioSlavePassiveReleaseVector:
+
+#ifdef XIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( XioSlaveInterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // XIO_AEOI
+
+ //
+ // Read the "in-service" mask.
+ //
+
+ WRITE_PORT_UCHAR( &((PSABLE_INTERRUPT_CSRS)SABLE_INTERRUPT_CSRS_QVA)->SlaveControl,
+ 0x0B
+ );
+
+ InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->SlaveControl
+ );
+
+ if( (InService & 0x80) == 0 ){
+
+ //
+ // Send end of interrupt to clear the passive release in the
+ // slave controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+
+ }
+
+#endif // XIO_AEOI
+
+ break;
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ IdtIndex = interruptVector + SABLE_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+#ifndef XIO_AEOI
+
+ //
+ // Dismiss the interrupt in the 8259 interrupt controllers.
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if( (interruptVector & XioSlaveBaseVector) == XioSlaveBaseVector ){
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+#endif // XIO_AEOI
+
+ return(returnValue);
+
+}
+
+
+
+VOID
+HalpDisableXioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the External IO specified interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the Xio interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Interrupt;
+
+ if( (Vector >= SABLE_VECTORS + XioMasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + XioSlavePassiveReleaseVector) ){
+
+ //
+ // Calculate the Xio relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & 0x7;
+
+ //
+ // Enable the interrupt for the appropriate interrupt controller.
+ //
+
+ if( (Vector & XioSlaveBaseVector) == XioSlaveBaseVector ){
+
+ XioSlaveInterruptMask |= (UCHAR) (1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveInterruptMask
+ );
+
+ }
+ }
+}
+
+BOOLEAN
+HalpEnableXioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Xio specified interrupt in the
+ appropriate 8259 interrupt controllers. It also supports the
+ edge/level control for EISA bus interrupts. By default, all interrupts
+ are edge detected (and latched).
+
+Arguments:
+
+ Vector - Supplies the vector of the Xio interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (Edge).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Interrupt;
+
+ if( (Vector >= SABLE_VECTORS + XioMasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + XioSlavePassiveReleaseVector) ){
+
+ //
+ // Calculate the Xio relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & 0x7;
+
+ //
+ // Enable the interrupt for the appropriate interrupt controller.
+ //
+
+ if( (Vector & XioSlaveBaseVector) == XioSlaveBaseVector ){
+
+ XioSlaveInterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveInterruptMask
+ );
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif // XIO_PASS1
+
+#ifdef XIO_PASS2
+
+#include "halp.h"
+#include "t2.h"
+#include "icic.h"
+#include "xiintsup.h"
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+extern ULONG HalpProcessors;
+
+//
+// Cached copies of the corresponding ICIC register(s).
+//
+
+ICIC_MASK_REGISTER XioIcIcMaskRegister;
+
+
+ULONG
+HalpGetXioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if( HalpXioPresent ){
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Handle Vectors for PCI devices.
+ //
+
+ case XioPciSlot0AVector:
+ case XioPciSlot0BVector:
+ case XioPciSlot0CVector:
+ case XioPciSlot0DVector:
+ case XioPciSlot1AVector:
+ case XioPciSlot1BVector:
+ case XioPciSlot1CVector:
+ case XioPciSlot1DVector:
+ case XioPciSlot2AVector:
+ case XioPciSlot2BVector:
+ case XioPciSlot2CVector:
+ case XioPciSlot2DVector:
+ case XioPciSlot3AVector:
+ case XioPciSlot3BVector:
+ case XioPciSlot3CVector:
+ case XioPciSlot3DVector:
+ case XioPciSlot4AVector:
+ case XioPciSlot4BVector:
+ case XioPciSlot4CVector:
+ case XioPciSlot4DVector:
+ case XioPciSlot5AVector:
+ case XioPciSlot5BVector:
+ case XioPciSlot5CVector:
+ case XioPciSlot5DVector:
+ case XioPciSlot6AVector:
+ case XioPciSlot6BVector:
+ case XioPciSlot6CVector:
+ case XioPciSlot6DVector:
+ case XioPciSlot7AVector:
+ case XioPciSlot7BVector:
+ case XioPciSlot7CVector:
+ case XioPciSlot7DVector:
+
+ *Irql = DEVICE_LEVEL;
+
+ if( HalpProcessors > 1 ){
+ *Affinity = HAL_CPU1_MASK;
+ } else {
+ *Affinity = HAL_CPU0_MASK;
+ }
+
+ return( BusInterruptLevel );
+
+ }
+ }
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+}
+
+
+BOOLEAN
+HalpInitializeXioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the ICIC on the Standard I/O module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE.
+
+--*/
+
+{
+ T2_ICE Ice;
+ ICIC_ELCR_REGISTER XioIcIcElcrRegister;
+
+ //
+ // Initialize the interface between the T3/T4 and the ICIC.
+ //
+
+ Ice.all = 0;
+ Ice.EisaFlushAddress = 0x542;
+ Ice.IcEnable = 1;
+ Ice.HalfSpeedEnable = 0;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Ice,
+ Ice.all );
+
+ //
+ // Initialize the ICIC Mask Register.
+ //
+
+ XioIcIcMaskRegister = (ULONGLONG)-1;
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
+ XioIcIcMaskRegister );
+
+ //
+ // Initialize the ICIC Edge/Level Control Register.
+ //
+
+ XioIcIcElcrRegister =
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3DVector - XioBaseVector));
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcElcrRegister,
+ XioIcIcElcrRegister );
+
+ //
+ // Initialize the ICIC EISA Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcEisaRegister, (ULONGLONG)0 );
+
+ //
+ // Initialize the ICIC Mode Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcModeRegister, (ULONGLONG)0 );
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpXioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dispatches interrupts received by the External I/O
+ ICIC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the interrupt was handled by
+ the FLIH/SLIH.
+
+--*/
+
+{
+ T2_VAR Var;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ BOOLEAN ReturnValue;
+
+ //
+ // Get the interrupt vector.
+ //
+
+ Var.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Var );
+
+ //
+ // If this is a passive release, ignore the interrupt.
+ //
+
+ if( Var.PassiveRelease == 1 ){
+
+ return(TRUE);
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[XioBaseVector + Var.Vector];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ ReturnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Send an SEOI.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Var, Var.Vector );
+
+ return(ReturnValue);
+}
+
+VOID
+HalpDisableXioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables interrupts associated with the External I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= XioBaseVector) &&
+ (Vector <= XioPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - XioBaseVector);
+
+ //
+ // Mask the interrupt.
+ //
+
+ XioIcIcMaskRegister |= IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
+ XioIcIcMaskRegister );
+
+ }
+}
+
+BOOLEAN
+HalpEnableXioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables interrupts associated with the External I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to enable.
+
+ InterruptMode - An indication of whether the interrupt should
+ be edge-triggered/level-sensitive. (Ignored)
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= XioBaseVector) &&
+ (Vector <= XioPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - XioBaseVector);
+
+ //
+ // Un-mask the interrupt.
+ //
+
+ XioIcIcMaskRegister &= ~IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
+ XioIcIcMaskRegister );
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#endif // XIO_PASS2
diff --git a/private/ntos/nthals/halsable/alpha/xiintsup.h b/private/ntos/nthals/halsable/alpha/xiintsup.h
new file mode 100644
index 000000000..01b39ffd3
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/xiintsup.h
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ xiintsup.h
+
+Abstract:
+
+ This header file contains prototypes for xiintsup.c.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+ULONG
+HalpGetXioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpInitializeXioInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpXioDispatch(
+ VOID
+ );
+
+VOID
+HalpDisableXioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEnableXioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
diff --git a/private/ntos/nthals/halsable/alpha/xioref.h b/private/ntos/nthals/halsable/alpha/xioref.h
new file mode 100644
index 000000000..4b2b2bde0
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/xioref.h
@@ -0,0 +1,148 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ xioref.h
+
+Abstract:
+
+ This file defines the structures and definitions of the XIO
+ interrupt architecture.
+
+Author:
+
+ Dave Richards 12-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _XIOREFH_
+#define _XIOREFH_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#ifdef XIO_PASS1
+
+typedef struct _XIO_INTERRUPT_CSRS{
+ UCHAR InterruptAcknowledge; // IO Address 0x0532
+ UCHAR Filler0; //
+ UCHAR MasterControl; // IO Address 0x0534
+ UCHAR MasterMask; // IO Address 0x0535
+ UCHAR SlaveControl; // IO Address 0x0536
+ UCHAR SlaveMask; // IO Address 0x0537
+} XIO_INTERRUPT_CSRS, *PXIO_INTERRUPT_CSRS;
+
+enum _XIO_INTERRUPT_VECTORS {
+
+ XioMasterBaseVector = 0x30,
+ XioReservedVector = 0x30,
+ XioSlaveCascadeVector,
+ XioMasterPassiveReleaseVector = 0x37,
+
+ XioSlaveBaseVector = 0x38,
+ XioPciSlot0AVector = 0x38,
+ XioPciSlot0BVector,
+ XioPciSlot0CVector,
+ XioPciSlot0DVector,
+ XioPciSlot1AVector,
+ XioPciSlot1BVector,
+ XioPciSlot1CVector,
+ XioPciSlot1DVector,
+ XioSlavePassiveReleaseVector = 0x3f,
+
+};
+
+#endif // XIO_PASS1
+
+#ifdef XIO_PASS2
+
+enum _XIO_INTERRUPT_VECTORS {
+
+ XioBaseVector = 0xc0, // XIO Base Vector
+ XioReservedVector = 0xc0, //
+ XioIcIcIrq0 = 0xc0, //
+ XioIcIcIrq1, //
+ XioIcIcIrq2, //
+ XioIcIcIrq3, //
+ XioIcIcIrq4, //
+ XioIcIcIrq5, //
+ XioIcIcIrq6, //
+ XioIcIcIrq7, //
+ XioIcIcIrq8, //
+ XioIcIcIrq9, //
+ XioIcIcIrq10, //
+ XioIcIcIrq11, //
+ XioIcIcIrq12, //
+ XioIcIcIrq13, //
+ XioIcIcIrq14, //
+ XioIcIcIrq15, //
+ XioIcIcIrq16, //
+ XioIcIcIrq17, //
+ XioIcIcIrq18, //
+ XioIcIcIrq19, //
+ XioIcIcIrq20, //
+ XioIcIcIrq21, //
+ XioIcIcIrq22, //
+ XioIcIcIrq23, //
+ XioIcIcIrq24, //
+ XioIcIcIrq25, //
+ XioIcIcIrq26, //
+ XioIcIcIrq27, //
+ XioIcIcIrq28, //
+ XioIcIcIrq29, //
+ XioIcIcIrq30, //
+ XioIcIcIrq31, //
+ XioPciSlot4AVector, // PCI Slot 4 A
+ XioPciSlot4BVector, // PCI Slot 4 B
+ XioPciSlot4CVector, // PCI Slot 4 C
+ XioPciSlot4DVector, // PCI Slot 4 D
+ XioPciSlot5AVector, // PCI Slot 5 A
+ XioPciSlot5BVector, // PCI Slot 5 B
+ XioPciSlot5CVector, // PCI Slot 5 C
+ XioPciSlot5DVector, // PCI Slot 5 D
+ XioPciSlot6AVector, // PCI Slot 6 A
+ XioPciSlot6BVector, // PCI Slot 6 B
+ XioPciSlot6CVector, // PCI Slot 6 C
+ XioPciSlot6DVector, // PCI Slot 6 D
+ XioPciSlot7AVector, // PCI Slot 7 A
+ XioPciSlot7BVector, // PCI Slot 7 B
+ XioPciSlot7CVector, // PCI Slot 7 C
+ XioPciSlot7DVector, // PCI Slot 7 D
+ XioPciSlot0AVector, // PCI Slot 0 A
+ XioPciSlot0BVector, // PCI Slot 0 B
+ XioPciSlot0CVector, // PCI Slot 0 C
+ XioPciSlot0DVector, // PCI Slot 0 D
+ XioPciSlot1AVector, // PCI Slot 1 A
+ XioPciSlot1BVector, // PCI Slot 1 B
+ XioPciSlot1CVector, // PCI Slot 1 C
+ XioPciSlot1DVector, // PCI Slot 1 D
+ XioPciSlot2AVector, // PCI Slot 2 A
+ XioPciSlot2BVector, // PCI Slot 2 B
+ XioPciSlot2CVector, // PCI Slot 2 C
+ XioPciSlot2DVector, // PCI Slot 2 D
+ XioPciSlot3AVector, // PCI Slot 3 A
+ XioPciSlot3BVector, // PCI Slot 3 B
+ XioPciSlot3CVector, // PCI Slot 3 C
+ XioPciSlot3DVector // PCI Slot 3 D
+
+};
+
+#endif // XIO_PASS2
+
+//
+// The following variable indicates whether an XIO module is present
+// in the system.
+//
+
+extern BOOLEAN HalpXioPresent;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _XIOREFH_
diff --git a/private/ntos/nthals/halsable/bushnd.c b/private/ntos/nthals/halsable/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halsable/bushnd.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\bushnd.c"
diff --git a/private/ntos/nthals/halsable/dirs b/private/ntos/nthals/halsable/dirs
new file mode 100644
index 000000000..a2a38f0fd
--- /dev/null
+++ b/private/ntos/nthals/halsable/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up
+
+OPTIONAL_DIRS=mp
diff --git a/private/ntos/nthals/halsable/drivesup.c b/private/ntos/nthals/halsable/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halsable/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halsable/hal.rc b/private/ntos/nthals/halsable/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halsable/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halsable/hal.src b/private/ntos/nthals/halsable/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halsable/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halsable/mp/makefile b/private/ntos/nthals/halsable/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halsable/mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halsable/mp/makefile.inc b/private/ntos/nthals/halsable/mp/makefile.inc
new file mode 100644
index 000000000..6985ce07a
--- /dev/null
+++ b/private/ntos/nthals/halsable/mp/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halsabmp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halsable/mp/sources b/private/ntos/nthals/halsable/mp/sources
new file mode 100644
index 000000000..3e7936dc4
--- /dev/null
+++ b/private/ntos/nthals/halsable/mp/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halsabmp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DAXPSABLE -DRTC_SQE -DEISA_PLATFORM -DSIO_AEOI
+
+NT_UP=0
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\alphaio.s \
+ ..\alpha\bios.c \
+ ..\alpha\cache.c \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\environ.c \
+ ..\alpha\ev4cache.c \
+ ..\alpha\ev4int.c \
+ ..\alpha\ev4ints.s \
+ ..\alpha\ev4mchk.c \
+ ..\alpha\ev4mem.s \
+ ..\alpha\ev4prof.c \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\icic.c \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\lyintsup.c \
+ ..\alpha\memory.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\siintsup.c \
+ ..\alpha\t2.c \
+ ..\alpha\vga.c \
+ ..\alpha\xiintsup.c \
+ ..\alpha\addrsup.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\sableerr.c \
+ ..\alpha\sableio.s \
+ ..\alpha\sbinitnt.c \
+ ..\alpha\sbintr.s \
+ ..\alpha\sbintsup.c \
+ ..\alpha\sbmapio.c \
+ ..\alpha\sbsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halsable/up/makefile b/private/ntos/nthals/halsable/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halsable/up/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halsable/up/makefile.inc b/private/ntos/nthals/halsable/up/makefile.inc
new file mode 100644
index 000000000..76942c78b
--- /dev/null
+++ b/private/ntos/nthals/halsable/up/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halsabup.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halsable/up/sources b/private/ntos/nthals/halsable/up/sources
new file mode 100644
index 000000000..84207c08c
--- /dev/null
+++ b/private/ntos/nthals/halsable/up/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halsabup
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV4 -DAXPSABLE -DRTC_SQE -DEISA_PLATFORM -DSIO_AEOI
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\alphaio.s \
+ ..\alpha\bios.c \
+ ..\alpha\cache.c \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\environ.c \
+ ..\alpha\ev4cache.c \
+ ..\alpha\ev4int.c \
+ ..\alpha\ev4ints.s \
+ ..\alpha\ev4mchk.c \
+ ..\alpha\ev4mem.s \
+ ..\alpha\ev4prof.c \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\icic.c \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\lyintsup.c \
+ ..\alpha\memory.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\siintsup.c \
+ ..\alpha\t2.c \
+ ..\alpha\vga.c \
+ ..\alpha\xiintsup.c \
+ ..\alpha\addrsup.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\sableio.s \
+ ..\alpha\sableerr.c \
+ ..\alpha\sbinitnt.c \
+ ..\alpha\sbintr.s \
+ ..\alpha\sbintsup.c \
+ ..\alpha\sbmapio.c \
+ ..\alpha\sbsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halsgi/drivesup.c b/private/ntos/nthals/halsgi/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halsgi/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halsgi/hal.rc b/private/ntos/nthals/halsgi/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halsgi/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halsgi/hal.src b/private/ntos/nthals/halsgi/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halsgi/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halsgi/makefile b/private/ntos/nthals/halsgi/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halsgi/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halsgi/makefile.inc b/private/ntos/nthals/halsgi/makefile.inc
new file mode 100644
index 000000000..c02e8df77
--- /dev/null
+++ b/private/ntos/nthals/halsgi/makefile.inc
@@ -0,0 +1,6 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halsgi.lib
+ copy $** $@
+
diff --git a/private/ntos/nthals/halsgi/mips/allstart.c b/private/ntos/nthals/halsgi/mips/allstart.c
new file mode 100644
index 000000000..8d81b6eb8
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/allstart.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halsgi/mips/halp.h b/private/ntos/nthals/halsgi/mips/halp.h
new file mode 100644
index 000000000..383317ca6
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/halp.h
@@ -0,0 +1,134 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "hal.h"
+#include "sgidef.h"
+
+
+//
+// Define function prototypes.
+//
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay0(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpInitNvram(
+ VOID
+ );
+
+VOID
+HalpSystemInit(
+ VOID
+ );
+
+//
+// Define external references.
+//
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halsgi/mips/s4cache.s b/private/ntos/nthals/halsgi/mips/s4cache.s
new file mode 100644
index 000000000..de9d70ba2
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/s4cache.s
@@ -0,0 +1,1192 @@
+#if defined(R4000)
+
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+// Copyright (c) 1992 Silicon Graphics, Inc.
+//
+// Module Name:
+//
+// s4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+// Kevin Meier (o-kevinm) 20-Jan-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "sgidef.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+#if defined(NUKE_ME)
+ SBTTL("Copy Page")
+//++
+//
+// VOID
+// HalCopyPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame,
+// IN PVOID Source
+// )
+//
+// Routine Description:
+//
+// This function copies a page of memory.
+//
+// The algorithm used to copy a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Copy the source page to the destination page using the new
+// color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that receives the copy.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that receives the copy.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// receives the copy.
+//
+// Source (a3) - Supplies the virtual address the page that is copied.
+//
+// N.B. This page must be valid.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CyRa: .space 4 // saved return address
+CyFrameLength: // length of stack frame
+CyA0: .space 4 // (a0)
+CyA1: .space 4 // (a1)
+CyA2: .space 4 // (a2)
+CyA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalCopyPage, CyFrameLength, zero)
+
+ subu sp,sp,CyFrameLength // allocate stack frame
+ sw ra,CyRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,CyA0(sp) // save new color bits
+ sw a1,CyA1(sp) // save old color bits
+ sw a2,CyA2(sp) // save page frame
+ sw a3,CyA3(sp) // save source address
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,CyA1(sp) // get old color value
+ lw a1,CyA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+
+10: lw a3,CyA0(sp) // get new color bits
+ lw a1,CyA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ lw a2,CyA3(sp) // get source address
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ bne zero,v0,60f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Copy page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ nop // fill
+ ldc1 f0,0(a2) // get 16 bytes from source
+ ldc1 f2,8(a2) //
+ bne zero,t8,40f // if ne, 16-byte cache line
+ addu a2,a2,16 // advance source address
+ ldc1 f4,0(a2) // get 16 bytes from source
+ ldc1 f6,8(a2) //
+ addu a2,a2,16 // advance source address
+ sdc1 f0,-32(t0) // store first 16 bytes
+ sdc1 f2,-24(t0) //
+ sdc1 f4,-16(t0) // store second 16 bytes
+ bne t0,t9,30b // if ne, more blocks to move
+ sdc1 f6,-8(t0) //
+ b 50f //
+ nop //
+
+40: sdc1 f0,-16(t0) // store first 16 byts
+ bne t0,t9,30b // if ne, more blocks to move
+ sdc1 f2,-8(t0) //
+ .set at
+ .set reorder
+
+50: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,CyRa(sp) // get return address
+ addu sp,sp,CyFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Copy page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+60: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+ nop // fill
+70: nop // ****** temp ******
+//70: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create primary cache block
+ addu t0,t0,t4 // compute next primary block address
+ nop // fill
+ ldc1 f0,0(a2) // get 16 bytes from source
+ ldc1 f2,8(a2) //
+ bne zero,t8,80f // if ne, 16-byte primary cache line
+ addu a2,a2,16 // advance source address
+ ldc1 f4,0(a2) // get 16 bytes from source
+ ldc1 f6,8(a2) //
+ addu a2,a2,16 // advance source address
+ sdc1 f0,-32(t0) // store first 16 bytes
+ sdc1 f2,-24(t0) //
+ sdc1 f4,-16(t0) // store second 16 bytes
+ bne t0,v1,70b // if ne, more primary blocks to move
+ sdc1 f6,-8(t0) //
+ bne t0,t9,60b // if ne, more secondary blocks to move
+ nop // fill
+ b 90f //
+ nop // fill
+
+80: sdc1 f0,-16(t0) // store first 16 byts
+ bne t0,v1,70b // if ne, more primary blocks to move
+ sdc1 f2,-8(t0) //
+ bne t0,t9,60b // if ne, more secondary blocks to move
+ nop // fill
+ .set at
+ .set reorder
+
+90: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,CyRa(sp) // get return address
+ addu sp,sp,CyFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalCopyPage
+#endif
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_RAMBASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_RAMBASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30: j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_RAMBASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_RAMBASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,ZpA1(sp) // get old color value
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ mtc1 zero,f0 // set write pattern
+ mtc1 zero,f1 //
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
+
+#endif
diff --git a/private/ntos/nthals/halsgi/mips/s4flshio.c b/private/ntos/nthals/halsgi/mips/s4flshio.c
new file mode 100644
index 000000000..f2045d370
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/s4flshio.c
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on the SGI Indigo R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, export or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then export the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halsgi/mips/s4prof.c b/private/ntos/nthals/halsgi/mips/s4prof.c
new file mode 100644
index 000000000..70b855a14
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/s4prof.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for the SGI Indigo R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter;
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter;
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ HalpPerformanceCounter.QuadPart = 0;
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxbeep.c b/private/ntos/nthals/halsgi/mips/sxbeep.c
new file mode 100644
index 000000000..2d62dac72
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxbeep.c
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3beep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for
+ an Indigo system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ Since audio has to go through the DSP, this function won't be
+ implemented.
+
+Arguments:
+
+Return Value:
+
+ Always FALSE for unsuccessful.
+
+--*/
+
+{
+ return(FALSE);
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxdisp.c b/private/ntos/nthals/halsgi/mips/sxdisp.c
new file mode 100644
index 000000000..2a1cfce42
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxdisp.c
@@ -0,0 +1,1384 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3disp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output
+ routines for the SGI Indigo system.
+
+Author:
+
+ David N. Cutler (davec) 27-Apr-1991
+ Kevin Meier (o-kevinm ) 8-Sept-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "sgirex.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpInitializeREX
+(
+ VOID
+);
+
+VOID
+HalpInitializeCLK
+(
+ VOID
+);
+
+VOID
+HalpInitializeDAC
+(
+ VOID
+);
+
+VOID
+HalpLoadSRAM
+(
+ IN PUCHAR Data,
+ IN USHORT Addr,
+ IN USHORT Length
+);
+
+VOID
+HalpInitializeVC1
+(
+ VOID
+);
+
+VOID
+HalpDisplayCharacter
+(
+ IN UCHAR Character
+);
+
+VOID
+HalpOutputCharacter
+(
+ IN PUCHAR Glyph
+);
+
+//
+// Define frame buffer parameters.
+//
+
+#define DISPLAY_WIDTH 1024 // number of pixels in scan line
+#define DISPLAY_HEIGHT 768 // number of scan lines in display
+//#define CHARACTER_WIDTH 9 // number of pixels per character
+//#define CHARACTER_HEIGHT 15 // number of scan lines per character
+//#define CHARACTER_LINES (DISPLAY_HEIGHT/CHARACTER_HEIGHT)
+//#define GLYPH_SIZE CHARACTER_HEIGHT - 1 // size of glyph in ulongs
+
+//
+// Define virtual address of the REX chip
+//
+
+#define REX_BASE (KSEG1_BASE | REX_ADDRESS)
+
+//
+// Memory layout of VC1 SRAM
+//
+
+#define VC1_VID_LINE_TBL_ADDR 0x0000
+#define VC1_VID_FRAME_TBL_ADDR 0x0800
+#define VC1_CURSOR_GLYPH_ADDR 0x0700
+#define VC1_DID_LINE_TBL_ADDR 0x4800
+#define VC1_DID_FRAME_TBL_ADDR 0x4000
+
+//
+// Define global data used for the x and y positions in the frame buffer
+// and the address of the idle process kernel object.
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+PREX_REGS HalpRexRegs;
+
+ULONG HalpSmallMon;
+ULONG HalpBoardRev;
+
+#define LG1_SMALLMON 6
+
+//
+// Declare externally defined data.
+//
+
+extern ULONG HalpUsFont8x14[];
+
+static UCHAR clkStuff[17] =
+{
+ 0xC4, 0x00, 0x10, 0x24, 0x30, 0x40, 0x59, 0x60, 0x72, 0x80, 0x90,
+ 0xAD, 0xB6, 0xD1, 0xE0, 0xF0, 0xC4
+};
+
+static UCHAR vtgLineTable[] =
+{
+0x08, 0x00, 0x98, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c,
+0x85, 0x7f, 0x8c, 0x78, 0x0c, 0x05, 0x90, 0x81, 0x00, 0x00,
+0x00, 0x08, 0x00, 0x98, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03,
+0x0c, 0x85, 0x7f, 0x8c, 0xf9, 0x00, 0x00, 0x15, 0x08, 0x00,
+0x99, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x7f,
+0x8c, 0x78, 0x0c, 0x8f, 0x81, 0x00, 0x00, 0x26, 0x08, 0x00,
+0x9d, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x7f,
+0x8c, 0x78, 0x0c, 0x8f, 0x81, 0x00, 0x00, 0x3a, 0x08, 0x00,
+0x9d, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x78,
+0x0c, 0x07, 0x9f, 0x7f, 0x0c, 0x8f, 0x81, 0x00, 0x00, 0x4e,
+0x04, 0x00, 0x9f, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c,
+0x87, 0x14, 0xac, 0x01, 0xf8, 0x02, 0xfc, 0x02, 0xfe, 0x02,
+0x7e, 0xa7, 0x01, 0x7f, 0xf7, 0x7f, 0xff, 0x39, 0xdf, 0x01,
+0x8f, 0x11, 0x8d, 0x02, 0x0d, 0xd7, 0x01, 0x0c, 0x87, 0x0e,
+0x0c, 0x8f, 0x81, 0x00, 0x00, 0x92, 0x04, 0x00, 0x9f, 0x02,
+0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x0a, 0xfc, 0x01,
+0xf8, 0x02, 0xfc, 0x0c, 0xfe, 0x02, 0x7e, 0xa7, 0x01, 0x7f,
+0xf7, 0x61, 0xaf, 0x01, 0x87, 0x02, 0x8f, 0x11, 0xff, 0x01,
+0xfb, 0x02, 0xff, 0x4a, 0xbf, 0x01, 0x8f, 0x07, 0x8d, 0x02,
+0x0d, 0xd7, 0x01, 0x0c, 0x87, 0x0e, 0x0c, 0x8f, 0x81, 0x00,
+0x00, 0xca, 0x04, 0x00, 0x9f, 0x02, 0x8c, 0x0b, 0x0c, 0x84,
+0x03, 0x0c, 0x87, 0x14, 0xac, 0x01, 0xf8, 0x02, 0xfc, 0x02,
+0xfe, 0x02, 0x7e, 0xa7, 0x01, 0x7f, 0xf7, 0x7f, 0xff, 0x39,
+0xdf, 0x01, 0x8f, 0x11, 0x8d, 0x02, 0x0d, 0xd7, 0x01, 0x0c,
+0x87, 0x0e, 0x0c, 0x8f, 0x81, 0x00, 0x00, 0xf8, 0x04, 0x00,
+0x9f, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x05,
+0xdc, 0x01, 0xfc, 0x01, 0xf8, 0x02, 0xfc, 0x10, 0xfe, 0x02,
+0x7e, 0xa7, 0x01, 0x7f, 0xf7, 0x10, 0xaf, 0x01, 0x87, 0x02,
+0x8f, 0x11, 0xff, 0x01, 0xfb, 0x02, 0xff, 0x7f, 0xff, 0x18,
+0xaf, 0x01, 0x8f, 0x0b, 0x8d, 0x02, 0x0d, 0xd7, 0x01, 0x0c,
+0x87, 0x0e, 0x0c, 0x8f, 0x81, 0x00, 0x01, 0x34, 0x04, 0x00,
+0x9f, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x0c,
+0xbc, 0x01, 0xfc, 0x01, 0xf8, 0x02, 0xfc, 0x09, 0xfe, 0x02,
+0x7e, 0xa7, 0x01, 0x7f, 0xf7, 0x7f, 0xff, 0x0b, 0x8f, 0x01,
+0x87, 0x02, 0x8f, 0x10, 0xdf, 0x01, 0xfb, 0x02, 0xff, 0x24,
+0xdf, 0x01, 0x8f, 0x05, 0x8d, 0x02, 0x0d, 0xd7, 0x01, 0x0c,
+0x87, 0x0e, 0x0c, 0x8f, 0x81, 0x00, 0x01, 0x70, 0x04, 0x00,
+0x9f, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x14,
+0xac, 0x01, 0xf8, 0x02, 0xfc, 0x02, 0xfe, 0x02, 0x7e, 0xa7,
+0x01, 0x7f, 0xf7, 0x7f, 0xff, 0x39, 0xdf, 0x01, 0x8f, 0x11,
+0x8d, 0x02, 0x0d, 0xd7, 0x01, 0x0c, 0x87, 0x0e, 0x0c, 0x8f,
+0x81, 0x00, 0x01, 0x9e, 0x04, 0x00, 0x9f, 0x02, 0x8c, 0x0b,
+0x0c, 0x84, 0x03, 0x0c, 0x87, 0x08, 0xac, 0x01, 0xf8, 0x02,
+0xfc, 0x0e, 0xfe, 0x02, 0x7e, 0xa7, 0x01, 0x7f, 0xf7, 0x39,
+0x8f, 0x01, 0x87, 0x02, 0x8f, 0x10, 0xdf, 0x01, 0xfb, 0x02,
+0xff, 0x71, 0xcf, 0x01, 0x8f, 0x09, 0x8d, 0x02, 0x0d, 0xd7,
+0x01, 0x0c, 0x87, 0x0e, 0x0c, 0x8f, 0x81, 0x00, 0x01, 0xd6,
+0x04, 0x00, 0x9f, 0x02, 0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c,
+0x87, 0x14, 0xac, 0x01, 0xf8, 0x02, 0xfc, 0x02, 0xfe, 0x02,
+0x7e, 0xa7, 0x01, 0x7f, 0xf7, 0x7f, 0xff, 0x39, 0xdf, 0x01,
+0x8f, 0x11, 0x8d, 0x02, 0x0d, 0xd7, 0x01, 0x0c, 0x87, 0x0e,
+0x0c, 0x8f, 0x81, 0x00, 0x00, 0x64, 0x04, 0x00, 0x9f, 0x02,
+0x8c, 0x0b, 0x0c, 0x84, 0x03, 0x0c, 0x87, 0x14, 0xac, 0x01,
+0xf8, 0x02, 0xfc, 0x02, 0xfe, 0x02, 0x7e, 0xa7, 0x01, 0x7f,
+0xf7, 0x7f, 0xff, 0x39, 0xdf, 0x01, 0x8f, 0x11, 0x8d, 0x02,
+0x0d, 0xd7, 0x01, 0x0c, 0x87, 0x0e, 0x0c, 0x8f, 0x81, 0x00,
+0x02, 0x04
+};
+
+static UCHAR vtgFrameTable[] =
+{
+0x03, 0x2d, 0x00, 0x00, 0x01, 0x00, 0x15, 0x02, 0x00, 0x3a,
+0x26, 0x00, 0x4e, 0x01, 0x00, 0x64, 0x78, 0x00, 0x64, 0x78,
+0x00, 0x64, 0x78, 0x00, 0x64, 0x78, 0x00, 0x64, 0x78, 0x00,
+0x64, 0x78, 0x00, 0x64, 0x2f, 0x02, 0x04, 0x01, 0x00, 0x26,
+0x03, 0x00
+};
+
+static UCHAR didLineTable[] =
+{
+0x0,0x1,0x0,0x0,
+0x0,0x1,0x0,0x1,
+0x0,0x1,0x0,0x2,
+0x0,0x1,0x0,0x3,
+0x0,0x1,0x0,0x4,
+0x0,0x1,0x0,0x5,
+0x0,0x1,0x0,0x6,
+0x0,0x1,0x0,0x7,
+0x0,0x1,0x0,0x8,
+0x0,0x1,0x0,0x9,
+0x0,0x1,0x0,0xa,
+0x0,0x1,0x0,0xb,
+0x0,0x1,0x0,0xc,
+0x0,0x1,0x0,0xd,
+0x0,0x1,0x0,0xe,
+0x0,0x1,0x0,0xf,
+0x0,0x1,0x0,0x10,
+0x0,0x1,0x0,0x11,
+0x0,0x1,0x0,0x12,
+0x0,0x1,0x0,0x13,
+0x0,0x1,0x0,0x14,
+0x0,0x1,0x0,0x15,
+0x0,0x1,0x0,0x16,
+0x0,0x1,0x0,0x17,
+0x0,0x1,0x0,0x18,
+0x0,0x1,0x0,0x19,
+0x0,0x1,0x0,0x1a,
+0x0,0x1,0x0,0x1b,
+0x0,0x1,0x0,0x1c,
+0x0,0x1,0x0,0x1d,
+0x0,0x1,0x0,0x1e,
+0x0,0x1,0x0,0x1f,
+0x0,0x4,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0
+};
+
+VOID
+HalpInitializeREX
+(
+ VOID
+)
+
+/*++
+
+Routine Description:
+
+ Initialize the REX chip and clear both overlay and pixel planes.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Wait for chip to become idle
+ //
+
+ REX_WAIT(HalpRexRegs);
+
+ //
+ // Set origin to upper left of screen
+ //
+
+ HalpRexRegs->Config.Set.xyWin = 0x08000800;
+
+ //
+ // Set max FIFO depths (disables FIFO INTs) and set VC1 clock for 1024
+ //
+
+// HalpRexRegs->Config.Set.ConfigMode = BFIFOMAX(0x1F) | DFIFOMAX(0x5) | FASTCLOCK;
+ HalpRexRegs->Config.Set.ConfigMode = BFIFOMAX(6) | DFIFOMAX(11) | FASTCLOCK;
+
+ //
+ // Bits for GL are set to 0 for Windows
+ //
+
+ HalpRexRegs->Draw.Set.Aux1 = 0;
+
+ HalpRexRegs->Draw.Go.Command = OC_NOOP;
+
+ REX_WAIT(HalpRexRegs);
+
+ //
+ // Clear overlay planes
+ //
+
+ HalpRexRegs->Config.Set.Aux2 = PLANES_OVERLAY;
+ HalpRexRegs->Draw.Set.Command = OC_DRAW | STOPONX | STOPONY | BLOCK | QUADMODE;
+ HalpRexRegs->Draw.Set.State = 0x03FF0000;
+ HalpRexRegs->Draw.Set.xStartI = 0;
+ HalpRexRegs->Draw.Set.yStartI = 0;
+ HalpRexRegs->Draw.Set.xEndI = 1023;
+ HalpRexRegs->Draw.Go.yEndI = 767;
+
+ REX_WAIT(HalpRexRegs);
+
+ //
+ // Clear pixel planes
+ //
+
+ HalpRexRegs->Config.Set.Aux2 = PLANES_PIXEL;
+ HalpRexRegs->Draw.Set.Command = OC_DRAW | STOPONX | STOPONY | BLOCK | QUADMODE;
+ HalpRexRegs->Draw.Set.State = 0x03FF0001;
+ HalpRexRegs->Draw.Set.xStartI = 0;
+ HalpRexRegs->Draw.Set.yStartI = 0;
+ HalpRexRegs->Draw.Set.xEndI = 1023;
+ HalpRexRegs->Draw.Go.yEndI = 767;
+
+ //
+ // Set background color to 1, foreground to 0
+ //
+
+ HalpRexRegs->Draw.Set.State = 0x03FF0100;
+}
+
+VOID
+HalpInitializeCLK
+(
+ VOID
+)
+
+/*++
+
+Routine Description:
+
+ Initialize the clock timing table.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT i;
+
+ HalpRexRegs->Config.Go.ConfigSel = 2;
+ for (i = 0; i < 17; i++)
+ {
+ HalpRexRegs->Config.Set.WClock = clkStuff[i];
+ HalpRexRegs->Config.Go.WClock = clkStuff[i];
+ }
+}
+
+VOID
+HalpInitializeBt
+(
+ ULONG Sync
+)
+
+/*++
+
+Routine Description:
+
+ Initiliaze the bt479 DAC. Load a GL colorramp into cmap 0 and clear
+ the rest.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT i;
+
+ //
+ // Address of windows bounds register
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x00);
+
+ //
+ // Init 8 bytes for each of 16 windows to 0
+ //
+
+ for (i = 0; i < 128; i++)
+ {
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, i);
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x00);
+ }
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x82);
+
+ //
+ // Command register 0
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x00);
+
+ //
+ // Command register 1
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x02 | (Sync << 3));
+
+ //
+ // Flood register lo
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x00);
+
+ //
+ // Flood register hi
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x00);
+
+ //
+ // Pixel read mask
+ //
+
+ DAC_WRITE(HalpRexRegs, PIXEL_READ_MASK, 0xFF);
+
+ //
+ // Init color map 0
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x82);
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x00);
+
+ //
+ // Init address to start of map
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x00);
+
+ //
+ // For first map, set entry 0 to WHITE, entry 1 to BLUE
+ //
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xFF);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xFF);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xFF);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x90);
+
+ for (i = 2; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map 1
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x82);
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x10);
+
+ //
+ // Init address to start of map
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x00);
+
+ for (i = 0; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map 2
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x82);
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x20);
+
+ //
+ // Init address to start of map
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x00);
+
+ for (i = 0; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map 3
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x82);
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x30);
+
+ //
+ // Init address to start of map
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xff);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xff);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xff);
+
+ for (i = 4; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map
+ //
+
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x82);
+
+ //
+ // Command register 0
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, 0x00);
+}
+
+VOID
+HalpInitializeLUT
+(
+ ULONG Sync
+)
+
+/*++
+
+Routine Description:
+
+ Load the LUT on the LG2 board
+
+Arguments:
+
+ Sync - Enable Sync-on-green
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int i;
+ ULONG lutcmd;
+
+ HalpRexRegs->Config.Set.ConfigSel = 6;
+ if ( Sync )
+ HalpRexRegs->Config.Go.RWDAC = 3; /* sync on green */
+ else
+ HalpRexRegs->Config.Go.RWDAC = 2;
+
+ HalpRexRegs->Config.Set.ConfigSel = CONTROL;
+ lutcmd = HalpRexRegs->Config.Go.RWDAC;
+ lutcmd = HalpRexRegs->Config.Set.RWDAC;
+ lutcmd &= 0xf;
+
+ //
+ // Init color map 0
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, lutcmd);
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0x00);
+
+ //
+ // For first map, set entry 0 to WHITE, entry 1 to BLUE
+ //
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xFF);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xFF);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xFF);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x90);
+
+ for (i = 2; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map 1
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, lutcmd | (1 << 6));
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0);
+
+ for (i = 0; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map 2
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, lutcmd | (2 << 6));
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0);
+
+ for (i = 0; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Init color map 3
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, lutcmd | (3 << 6));
+ DAC_WRITE(HalpRexRegs, WRITE_ADDR, 0);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xff);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xff);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0xff);
+
+ for (i = 4; i < 256; i++)
+ {
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ DAC_WRITE(HalpRexRegs, PALETTE_RAM, 0x00);
+ }
+
+ //
+ // Command register 0
+ //
+
+ DAC_WRITE(HalpRexRegs, CONTROL, lutcmd);
+ return;
+}
+
+VOID
+HalpInitializeDAC
+(
+ VOID
+)
+
+/*++
+
+Routine Description:
+
+ Load the DAC on the LG1/2 board
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpBoardRev >= 2)
+ HalpInitializeLUT (!(HalpSmallMon == LG1_SMALLMON));
+ else
+ HalpInitializeBt (!(HalpSmallMon == LG1_SMALLMON));
+
+ return;
+}
+
+
+VOID
+HalpLoadSRAM
+(
+ IN PUCHAR Data,
+ IN USHORT Addr,
+ IN USHORT Length
+)
+
+/*++
+
+Routine Description:
+
+ Load the data table into the external SRAM of the VC1.
+
+Arguments:
+
+ Data - Pointer to data array to be placed in SRAM
+ Addr - Address in SRAM to load table
+ Length - Lenght of data table in bytes
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT i;
+
+ VC1_WRITE_ADDR(HalpRexRegs, Addr, 0x02);
+ KeStallExecutionProcessor(1);
+ for (i = 0; i < Length; i += 2)
+ {
+ VC1_WRITE8(HalpRexRegs, Data[i]);
+ VC1_WRITE8(HalpRexRegs, Data[i + 1]);
+ KeStallExecutionProcessor(1);
+ }
+}
+
+
+VOID
+HalpInitializeVC1
+(
+ VOID
+)
+
+/*++
+
+Routine Description:
+
+ Initialize the VC1 by loading all the timing and display tables into
+ external SRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT i;
+ UCHAR didFrameTable[768 * 2];
+ UCHAR cursorTable[256];
+
+ //
+ // Disable VC1 function
+ //
+
+ HalpRexRegs->Config.Go.ConfigSel = 0x06;
+ VC1_WRITE8(HalpRexRegs, 0x03);
+
+ //
+ // Load video timing generator table
+ //
+
+ HalpLoadSRAM(vtgLineTable, VC1_VID_LINE_TBL_ADDR, sizeof(vtgLineTable));
+ HalpLoadSRAM(vtgFrameTable, VC1_VID_FRAME_TBL_ADDR, sizeof(vtgFrameTable));
+
+ //
+ // Write VC1 VID_EP, VID_ENCODE(0x1D) register
+ //
+
+ VC1_WRITE_ADDR(HalpRexRegs, 0x00, 0x00);
+ VC1_WRITE16(HalpRexRegs, (VC1_VID_FRAME_TBL_ADDR) | 0x8000);
+ VC1_WRITE_ADDR(HalpRexRegs, 0x14, 0x00);
+ VC1_WRITE16(HalpRexRegs, 0x1d00);
+
+ //
+ // Load DID table
+ //
+
+ for (i = 0; i < sizeof(didFrameTable); i += 2)
+ {
+ didFrameTable[i] = 0x48;
+ didFrameTable[i + 1] = 0x00;
+ }
+ didFrameTable[767 * 2] = 0x48;
+ didFrameTable[767 * 2 + 1] = 0x40;
+ HalpLoadSRAM(didFrameTable, VC1_DID_FRAME_TBL_ADDR, sizeof(didFrameTable));
+ HalpLoadSRAM(didLineTable, VC1_DID_LINE_TBL_ADDR, sizeof(didLineTable));
+
+ //
+ // Write VC1 WIDs
+ //
+
+ VC1_WRITE_ADDR(HalpRexRegs, 0x40, 0x00);
+ VC1_WRITE16(HalpRexRegs, 0x4000);
+ VC1_WRITE16(HalpRexRegs, 0x4600);
+ VC1_WRITE8(HalpRexRegs, 1024/5);
+ VC1_WRITE8(HalpRexRegs, 1024%5);
+ VC1_WRITE_ADDR(HalpRexRegs, 0x60, 0x00);
+ VC1_WRITE8(HalpRexRegs, 0x01);
+ VC1_WRITE8(HalpRexRegs, 0x01);
+
+ //
+ // Write VC1 DID mode registers
+ //
+
+ VC1_WRITE_ADDR(HalpRexRegs, 0x00, 0x01);
+ for (i = 0; i < 0x40; i += 2)
+ {
+ VC1_WRITE16(HalpRexRegs, 0x0000);
+ }
+
+ //
+ // Load NULL cursor
+ //
+
+ for (i = 0; i < 256; i++)
+ cursorTable[i] = 0x00;
+ HalpLoadSRAM(cursorTable, 0x3000, sizeof(cursorTable));
+ VC1_WRITE_ADDR(HalpRexRegs, 0x20, 0x00);
+ VC1_WRITE16(HalpRexRegs, 0x3000);
+ VC1_WRITE16(HalpRexRegs, 0x0240);
+ VC1_WRITE16(HalpRexRegs, 0x0240);
+
+ // Set cursor XMAP 3, submap 0, mode normal
+ //
+ VC1_WRITE16(HalpRexRegs, 0xC000);
+
+ //
+ // Enable VC1 function
+ //
+
+ HalpRexRegs->Config.Go.ConfigSel = 6;
+ VC1_WRITE8(HalpRexRegs, 0xBD);
+}
+
+VOID
+HalpReinitializeDisplay (
+ VOID
+)
+{
+ ULONG rev;
+
+ // figure out board revision
+ //
+ HalpRexRegs->Config.Set.ConfigSel = 4;
+ rev = HalpRexRegs->Config.Go.WClock;
+ rev = HalpRexRegs->Config.Set.WClock;
+ HalpBoardRev = rev & 0x7;
+ HalpSmallMon = (rev >> 3) & 0x7;
+
+ HalpInitializeREX();
+ HalpInitializeCLK();
+ HalpInitializeDAC();
+ HalpInitializeVC1();
+
+ HalpDisplayOwnedByHal = TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay0
+(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+)
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Starter Graphics subsystem
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG CpuCtrl;
+ POEM_FONT_FILE_HEADER FontHeader;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText = DISPLAY_HEIGHT / HalpCharacterHeight;
+ HalpDisplayWidth = DISPLAY_WIDTH / HalpCharacterWidth;
+
+
+ HalpRexRegs = (PREX_REGS)REX_BASE;
+
+ //
+ // Reset the REX chip through the CPU configuration register
+ //
+
+ CpuCtrl = READ_REGISTER_ULONG(SGI_CPUCTRL_BASE);
+ WRITE_REGISTER_ULONG(SGI_CPUCTRL_BASE, CpuCtrl & ~0x8000);
+ KeStallExecutionProcessor(15);
+ WRITE_REGISTER_ULONG(SGI_CPUCTRL_BASE, CpuCtrl | 0x8000);
+ KeStallExecutionProcessor(15);
+
+ HalpReinitializeDisplay();
+
+ //
+ // Display welcome message
+ //
+ HalpColumn = 40;
+ HalpRow = 0;
+ HalDisplayString("Silicon Graphics, Inc. (c) 1993\n");
+ HalDisplayString("\n");
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+VOID
+HalDisplayString
+(
+ PUCHAR String
+)
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (HalpDisplayOwnedByHal == FALSE)
+ HalpReinitializeDisplay();
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+ while (*String != 0)
+ {
+ HalpDisplayCharacter(*String++);
+ }
+
+ KeLowerIrql(OldIrql);
+}
+
+VOID
+HalpDisplayCharacter
+(
+ IN UCHAR Character
+)
+
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n')
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ {
+ //
+ // Program REX to do a screen-screen BLT for scrolling.
+ //
+
+ REX_WAIT(HalpRexRegs);
+
+ HalpRexRegs->Draw.Set.xStartI = 0;
+ HalpRexRegs->Draw.Set.yStartI = 0;
+ HalpRexRegs->Draw.Set.xEndI = 1023;
+ HalpRexRegs->Draw.Set.yEndI = 764 - HalpCharacterHeight;
+ HalpRexRegs->Draw.Set.xyMove = HalpCharacterHeight;
+ HalpRexRegs->Draw.Go.Command = OC_DRAW
+ | LO_COPY
+ | LOGICSRC
+ | STOPONX
+ | STOPONY
+ | BLOCK
+ | QUADMODE;
+
+ //
+ // Clear bottom text line.
+ //
+
+ REX_WAIT(HalpRexRegs);
+
+ HalpRexRegs->Draw.Set.xStartI = 0;
+ HalpRexRegs->Draw.Set.yStartI = 764 - HalpCharacterHeight;
+ HalpRexRegs->Draw.Set.xEndI = 1023;
+ HalpRexRegs->Draw.Set.yEndI = 767;
+ HalpRexRegs->Draw.Go.Command = OC_DRAW
+ | LO_COPY
+ | STOPONX
+ | STOPONY
+ | BLOCK
+ | QUADMODE;
+ }
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacter
+(
+ IN PUCHAR Glyph
+)
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+Arguments:
+
+ Glyph - Supplies a character bitmap to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG x;
+ ULONG y;
+ USHORT i, j;
+ ULONG FontValue;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ //
+ // Calculate pixel positions for the character.
+ //
+
+ x = HalpColumn * HalpCharacterWidth;
+ y = HalpRow * HalpCharacterHeight;
+
+ //
+ // Wait for REX to become idle.
+ //
+
+ REX_WAIT(HalpRexRegs);
+
+ //
+ // Program REX to do a pattern block fill.
+ //
+
+ HalpRexRegs->Draw.Set.xStartI = x;
+ HalpRexRegs->Draw.Set.yStartI = y;
+ HalpRexRegs->Draw.Set.xEndI = x + HalpCharacterWidth - 1;
+ HalpRexRegs->Draw.Set.yEndI = y + HalpCharacterHeight - 1;
+ HalpRexRegs->Draw.Go.Command = OC_NOOP;
+
+ HalpRexRegs->Draw.Set.Command = OC_DRAW
+ | LO_COPY
+ | STOPONX
+ | XYCONTINUE
+ | BLOCK
+ | QUADMODE
+ | ENLSPATTERN
+ | LSOPAQUE;
+
+ for (i = 0; i <= HalpCharacterHeight; i++) {
+ FontValue = 0;
+ for (j = 0; j < HalpBytesPerRow; j++) {
+ FontValue |= *(Glyph + (j * HalpCharacterHeight)) << (24 - (j * 8));
+ }
+ HalpRexRegs->Draw.Go.lsPattern = FontValue;
+
+ Glyph++;
+ }
+
+ HalpColumn++;
+ return;
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxenvirv.c b/private/ntos/nthals/halsgi/mips/sxenvirv.c
new file mode 100644
index 000000000..8721d4d19
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxenvirv.c
@@ -0,0 +1,610 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3envirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable
+ routines for the SGI Indigo system.
+
+Author:
+
+ Kevin Meier (o-kevinm) 16-Sept-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+
+#define NVLEN_MAX 256 // Number of bytes on the 93cs56
+
+// Control opcodes for nonvolatile ram
+#define SER_READ 0xc000 // serial memory read
+#define SER_WEN 0x9800 // write enable before prog modes
+#define SER_WRITE 0xa000 // serial memory write
+#define SER_WRALL 0x8800 // write all registers
+#define SER_WDS 0x8000 // disable all programming
+#define SER_PRREAD 0xc000 // read protect register
+#define SER_PREN 0x9800 // enable protect register mode
+#define SER_PRCLEAR 0xffff // clear protect register
+#define SER_PRWRITE 0xa000 // write protect register
+#define SER_PRDS 0x8000 // disable protect register, forever
+
+#define NVRAM_ENTRIES 26 // max number of nvram entries
+#define MAXNVNAMELEN 32 // max length of variable name
+#define MAX_ENTRY_LEN 64 // max length of variable value
+
+#define NVOFF_CHECKSUM 0 // Checksum offset in nvram
+#define NVLEN_CHECKSUM 1 // Checksum length in nvram
+
+//
+// Format used to store nvram table information
+//
+typedef struct _NvramEntry {
+ char NvName[MAXNVNAMELEN]; // string name of entry
+ char *NvValue; // PROM: string for default value
+ int NvAddr; // offset to entry in nvram
+ int NvLen; // length of entry in nvram
+} NvramEntry;
+
+volatile UCHAR *CpuAuxControl;
+
+NvramEntry NvramTable[NVRAM_ENTRIES]; // local storage for nvram
+char NvramValues[NVRAM_ENTRIES * MAX_ENTRY_LEN];
+
+typedef
+LONG
+(*PVEN_NVRAM_TABLE_ROUTINE) (
+ IN PVOID Table,
+ IN ULONG Size
+ );
+
+#define NvramTableRoutine 1
+#define VenNvramTable(x,y) \
+((PVEN_NVRAM_TABLE_ROUTINE)(SYSTEM_BLOCK->VendorVector[NvramTableRoutine])) \
+ ((x), (y))
+
+static USHORT NvramReadRegister(int);
+static void NvramReadString(int, int, char *);
+
+//
+// Fetch the nvram table from the PROM through the arcs private vector.
+// Must be called before the DSP is enabled.
+// We know if the table has grown by the return value.
+//
+
+void
+HalpInitNvram(void)
+{
+ ULONG Size;
+ int Entry;
+
+ CpuAuxControl = (volatile UCHAR *)SGI_AUX_BASE;
+
+ Size = VenNvramTable(NvramTable, sizeof(NvramTable));
+
+ if(Size) {
+#ifdef DBG
+ char buf[64];
+ sprintf(buf, "Nvram table has grown (%d).\n", Size);
+ HalDisplayString(buf);
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ RtlZeroMemory (NvramValues, sizeof NvramValues);
+ for (Entry = 0; Entry < NVRAM_ENTRIES; ++Entry) {
+ if (NvramTable[Entry].NvLen == 0) {
+ // DbgPrint ("Nvram has %d entries\n", Entry);
+ break;
+ }
+ NvramTable[Entry].NvValue = &NvramValues[Entry * MAX_ENTRY_LEN];
+ if (NvramTable[Entry].NvLen <= MAX_ENTRY_LEN) {
+ NvramReadString(NvramTable[Entry].NvAddr, NvramTable[Entry].NvLen,
+ NvramTable[Entry].NvValue);
+ }
+ else {
+#ifdef DBG
+ DbgPrint ("NvEntry %s too large\n", NvramTable[Entry].NvName);
+#endif
+ NvramTable[Entry].NvName[0] = 0;
+ }
+ }
+#ifdef DBG
+ if (Entry >= NVRAM_ENTRIES)
+ DbgPrint("Nvram: too many entries\n");
+#endif
+}
+
+static UCHAR ConsoleLedState;
+
+//
+// Enable the serial memory by setting the console chip select
+//
+
+static void
+ChipSelOn(void)
+{
+ ConsoleLedState = *CpuAuxControl & CONSOLE_LED;
+
+ *CpuAuxControl &= ~CPU_TO_SER;
+ *CpuAuxControl &= ~SERCLK;
+ *CpuAuxControl &= ~NVRAM_PRE;
+ KeStallExecutionProcessor(1);
+ *CpuAuxControl |= CONSOLE_CS;
+ *CpuAuxControl |= SERCLK;
+}
+
+//
+// Turn off the chip select
+//
+
+static void
+ChipSelOff(void)
+{
+ *CpuAuxControl &= ~SERCLK;
+ *CpuAuxControl &= ~CONSOLE_CS;
+ *CpuAuxControl |= NVRAM_PRE;
+ *CpuAuxControl |= SERCLK;
+
+ *CpuAuxControl = (*CpuAuxControl & ~CONSOLE_LED) | ConsoleLedState;
+}
+
+#define BITS_IN_COMMAND 11
+
+//
+// Clock in the nvram command and the register number. For the National
+// nvram chip the op code is 3 bits and the address is 6/8 bits.
+//
+
+static void
+NvramCommand(ULONG Command, ULONG Register)
+{
+ USHORT SerialCmd;
+ int BitCount;
+
+ SerialCmd = (USHORT)(Command | (Register << (16 - BITS_IN_COMMAND)));
+ for (BitCount = 0; BitCount < BITS_IN_COMMAND; BitCount++) {
+ if (SerialCmd & 0x8000) /* if high order bit set */
+ *CpuAuxControl |= CPU_TO_SER;
+ else
+ *CpuAuxControl &= ~CPU_TO_SER;
+ *CpuAuxControl &= ~SERCLK;
+ *CpuAuxControl |= SERCLK;
+ SerialCmd <<= 1;
+ }
+ *CpuAuxControl &= ~CPU_TO_SER; /* see data sheet timing diagram */
+}
+
+//
+// After write/erase commands, we must wait for the command to complete.
+// Write cycle time is 10 ms max (~5 ms nom); we timeout after ~20 ms.
+// NVDELAY_TIME * NVDELAY_LIMIT = 20 ms
+//
+#define NVDELAY_TIME 100 // 100 us delay times
+#define NVDELAY_LIMIT 200 // 200 delay limit
+
+static int
+NvramHold(void)
+{
+ int Error, Timeout = NVDELAY_LIMIT;
+
+ ChipSelOn();
+ while (!(*CpuAuxControl & SER_TO_CPU) && Timeout--)
+ KeStallExecutionProcessor(NVDELAY_TIME);
+
+ Error = (*CpuAuxControl & SER_TO_CPU) ? ESUCCESS : EIO;
+
+ ChipSelOff();
+
+ return Error;
+}
+
+static char
+NvramChecksum(void)
+{
+ int Register;
+ USHORT Value;
+ char Checksum;
+
+ // Seed the checksum so all-zeroes (all-ones) nvram doesn't have a zero
+ // (all-ones) checksum.
+ //
+ Checksum = '\xA5';
+
+ // Checksum all of the nvram, but skip the checksum byte.
+ //
+ for (Register = 0; Register < NVLEN_MAX / 2; Register++) {
+ Value = NvramReadRegister(Register);
+ if(Register == (NVOFF_CHECKSUM / 2))
+#if NVOFF_CHECKSUM & 0x01
+ Checksum ^= Value >> 8;
+#else
+ Checksum ^= Value & 0xff;
+#endif
+ else
+ Checksum ^= (Value >> 8) ^ (Value & 0xff);
+ // following is a tricky way to rotate
+ Checksum = (Checksum << 1) | (Checksum < 0);
+ }
+
+ return Checksum;
+}
+
+//
+// NvramReadRegister -- read a 16 bit register from non-volatile memory.
+// Bytes are stored in this string in big-endian order in each 16 bit word.
+//
+
+static USHORT
+NvramReadRegister(int Register)
+{
+ USHORT ReadBits = 0;
+ int BitCount;
+ UCHAR ConsoleLedOff = *CpuAuxControl & CONSOLE_LED;
+
+ *CpuAuxControl &= ~NVRAM_PRE;
+ ChipSelOn(); /* enable chip select */
+ NvramCommand(SER_READ, Register);
+
+ /* clock the data ouf of serial mem */
+ for (BitCount = 0; BitCount < 16; BitCount++) {
+ *CpuAuxControl &= ~SERCLK;
+ *CpuAuxControl |= SERCLK;
+ ReadBits <<= 1;
+ ReadBits |= (*CpuAuxControl & SER_TO_CPU) ? 1 : 0;
+ }
+
+ ChipSelOff();
+
+ *CpuAuxControl = (*CpuAuxControl & ~CONSOLE_LED) | ConsoleLedOff;
+
+ return ReadBits;
+}
+
+
+//
+// NvramWriteRegister -- writes a 16 bit word into non-volatile memory. Bytes
+// are stored in this register in big-endian order in each 16 bit word.
+//
+
+static ARC_STATUS
+NvramWriteRegister(int Register, USHORT Value)
+{
+ int Error, BitCount;
+ UCHAR ConsoleLedOff = *CpuAuxControl & CONSOLE_LED;
+
+ *CpuAuxControl &= ~NVRAM_PRE;
+ ChipSelOn();
+ NvramCommand(SER_WEN, 0);
+ ChipSelOff();
+
+ ChipSelOn();
+ NvramCommand(SER_WRITE, Register);
+
+ //
+ // clock the data into serial mem
+ //
+ for (BitCount = 0; BitCount < 16; BitCount++) {
+ if (Value & 0x8000) // get the high bit
+ *CpuAuxControl |= CPU_TO_SER;
+ else
+ *CpuAuxControl &= ~CPU_TO_SER;
+ *CpuAuxControl &= ~SERCLK;
+ *CpuAuxControl |= SERCLK;
+ Value <<= 1;
+ }
+ *CpuAuxControl &= ~CPU_TO_SER;
+
+ ChipSelOff();
+ Error = NvramHold();
+
+ ChipSelOn();
+ NvramCommand(SER_WDS, 0);
+ ChipSelOff();
+
+ *CpuAuxControl = (*CpuAuxControl & ~CONSOLE_LED) | ConsoleLedOff;
+
+ return Error;
+}
+
+//
+// NvramReadString -- read nvram contents into a buffer
+//
+
+static void
+NvramReadString(int Offset, int Length, char *Buffer)
+{
+ char *BufPtr;
+ int LenCount;
+ USHORT Contents;
+
+ BufPtr = Buffer;
+ if (Offset % 2 == 1) {
+ Contents = NvramReadRegister(Offset / 2);
+ *BufPtr++ = Contents & 0xff;
+ Offset++;
+ Length--;
+ }
+
+ for (LenCount = 0; LenCount < Length / 2; LenCount++) {
+ Contents = NvramReadRegister(Offset / 2 + LenCount);
+ *BufPtr++ = (char)(Contents >> 8);
+ *BufPtr++ = (char)(Contents & 0xff);
+ }
+
+ if (Length % 2 == 1) {
+ Contents = NvramReadRegister((Offset + Length) / 2);
+ *BufPtr++ = Contents >> 8;
+ }
+
+ *BufPtr = 0;
+}
+
+//
+// NvramWriteString -- write string to non-volatile memory
+//
+
+static ARC_STATUS
+NvramWriteString(int Offset, int Length, char *String)
+{
+ USHORT CurrentVal;
+ char Checksum[2];
+ int OffsetSave;
+ int LenCount;
+
+ OffsetSave = Offset;
+
+ if (Offset % 2) {
+ CurrentVal = NvramReadRegister(Offset / 2);
+ CurrentVal &= 0xff00;
+ CurrentVal |= *String;
+ if (NvramWriteRegister(Offset / 2, CurrentVal))
+ return EIO;
+ if (*String)
+ String++;
+ Offset++;
+ Length--;
+ }
+
+ for (LenCount = 0; LenCount < Length / 2; LenCount++) {
+ if (*String) {
+ CurrentVal = (USHORT) *String++ << 8;
+ CurrentVal |= *String;
+ if (*String)
+ *String++;
+ } else
+ CurrentVal = 0;
+
+ if (NvramWriteRegister(Offset / 2 + LenCount, CurrentVal))
+ return EIO;
+ }
+
+ if (Length % 2 == 1) {
+ CurrentVal = NvramReadRegister((Offset + Length) / 2);
+ CurrentVal &= 0x00ff;
+ CurrentVal |= (USHORT) *String << 8;
+ if (NvramWriteRegister((Offset + Length) / 2, CurrentVal))
+ return EIO;
+ }
+
+ if (OffsetSave != NVOFF_CHECKSUM) {
+ Checksum[0] = NvramChecksum();
+ Checksum[1] = 0;
+ return NvramWriteString(NVOFF_CHECKSUM, NVLEN_CHECKSUM, Checksum);
+ }
+ else
+ return ESUCCESS;
+}
+
+#ifdef MFG_EADDR
+
+//
+// NvramSetEaddr - set ethernet address in nvram
+//
+
+#define TOHEX(c) ((('0'<=(c))&&((c)<='9')) ? ((c)-'0') : ((c)-'a'+10))
+
+static ARC_STATUS
+NvramSetEaddr (char *Value)
+{
+ char Digit[6], *cp;
+ int DigitCount;
+
+ // Expect value to be the address of an ethernet address string
+ // of the form xx:xx:xx:xx:xx:xx (lower case only)
+ //
+ for (DigitCount = 0, cp = Value; *cp ; ) {
+ if (*cp == ':') {
+ cp++;
+ continue;
+ } else if (!ISXDIGIT(*cp) || !ISXDIGIT(*(cp+1))) {
+ return EINVAL;
+ } else {
+ if (DigitCount >= 6)
+ return EINVAL;
+ Digit[DigitCount++] = (TOHEX(*cp)<<4) + TOHEX(*(cp+1));
+ cp += 2;
+ }
+ }
+
+ for (DigitCount = 0; DigitCount < NVLEN_ENET; ++DigitCount)
+ if (NvramWriteString(NVOFF_ENET+DigitCount, 1, &Digit[DigitCount]))
+ return EIO;
+
+ return ESUCCESS;
+}
+#endif /* MFG_EADDR */
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ EACCES is returned if the variable is read-only, ENOSPC is returned
+ if the buffer is too large, or ENOENT is returned if an entry for
+ this variable is not found.
+
+--*/
+
+{
+ NvramEntry *NvEntry;
+ int ValueLen = strlen(Value);
+ char _value[20];
+ int _valuelen;
+
+ if (!strcmp("eaddr", Variable))
+#ifdef MFG_EADDR
+ return NvramSetEaddr(Value);
+#else
+ return EACCES;
+#endif /* MFG_EADDR */
+
+ // Don't allow setting the password from the OS, only clearing.
+ //
+ if (!strcmp(Variable, "passwd_key") && ValueLen)
+ return EACCES;
+
+ // Change the netaddr to binary for the nvram
+ //
+ if (strcmp(Variable, "netaddr") == 0) {
+ char buf[4];
+ char *ptr = Value;
+ int i;
+
+ strcpy(_value, Value);
+ _valuelen = ValueLen;
+
+ while (*ptr) // to the end of the string
+ ptr++;
+
+ /* convert string to number, one at a time */
+ for (i = 3; i >= 0; i--) {
+ while (*ptr != '.' && ptr >= Value)
+ ptr--;
+ buf[i] = atoi(ptr + 1);
+ if (ptr > Value)
+ *ptr = 0;
+ }
+ Value[0] = buf[0];
+ Value[1] = buf[1];
+ Value[2] = buf[2];
+ Value[3] = buf[3];
+ ValueLen = 4;
+ }
+
+ // check to see if it is a valid nvram name
+ //
+ for (NvEntry = NvramTable; NvEntry->NvLen; NvEntry++)
+ if (!strcmp(NvEntry->NvName, Variable)) {
+ int Error;
+
+ if(ValueLen > NvEntry->NvLen)
+ return ENOSPC;
+ if(ValueLen < NvEntry->NvLen)
+ ++ValueLen; /* write out NULL */
+ Error = NvramWriteString(NvEntry->NvAddr, ValueLen, Value);
+
+ if (strcmp(Variable, "netaddr") == 0) {
+ strcpy(Value, _value);
+ ValueLen = _valuelen;
+ }
+
+ if (!Error)
+ strncpy (NvEntry->NvValue, Value, ValueLen);
+
+ return Error;
+ }
+
+ return ENOENT;
+}
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned if the entry is not found, or ENOSPC is returned
+ if the buffer isn't large enough.
+
+--*/
+
+{
+ NvramEntry *NvEntry;
+ ULONG VarLength;
+ int Count;
+
+ if (!Variable)
+ return ENOENT;
+
+ VarLength = strlen(Variable);
+
+ // check to see if it is a valid nvram name
+ //
+ for (NvEntry = NvramTable; NvEntry->NvLen; NvEntry++) {
+ if (!strncmp(NvEntry->NvName, Variable, VarLength)) {
+
+ if(NvEntry->NvLen > Length)
+ return ENOSPC;
+
+ for (Count = 0; Count < NvEntry->NvLen; Count++)
+ Buffer[Count] = NvEntry->NvValue[Count];
+
+ return ESUCCESS;
+ }
+ }
+
+ return ENOENT;
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxflshbf.s b/private/ntos/nthals/halsgi/mips/sxflshbf.s
new file mode 100644
index 000000000..3a9a71172
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxflshbf.s
@@ -0,0 +1,76 @@
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+// Copyright (c) 1992 Silicon Graphics, Inc.
+//
+// Module Name:
+//
+// s3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer on the SGI Indigo system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "sgidef.h"
+#include "ksmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+
+ .set noreorder
+ .set noat
+
+#if defined(R3000)
+ li t0,SGI_CPUCTRL_BASE
+ j ra
+ lw zero,0(t0)
+#else
+ lui t0,SGI_CPUCTRL_BASE>>16
+ or t0,SGI_CPUCTRL_BASE&0xffff
+ lw t0,0(t0)
+ nop
+ nop
+ nop
+ j ra
+ nop
+#endif
+ .set at
+ .set reorder
+
+ .end KeFlushWritebuffer
diff --git a/private/ntos/nthals/halsgi/mips/sxhwsup.c b/private/ntos/nthals/halsgi/mips/sxhwsup.c
new file mode 100644
index 000000000..e306fccf8
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxhwsup.c
@@ -0,0 +1,2387 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3hwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent.
+
+Author:
+
+ Jeff Havens (jhavens ) 14-Feb-1990
+ Tom Bonola (o-tomb ) 28-Aug-1991
+ Kevin Meier (o-kevinm ) 14-Jan-1992
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+#define ENABLE_FIFOFULL
+
+#undef DMADEBUG
+#ifdef DMADEBUG
+ULONG Hal2Debug = 1;
+#endif // DMADEBUG
+
+#undef IOMAPDEBUG
+#ifdef IOMAPDEBUG
+ULONG HalDebug = 0;
+ULONG Hal3Debug = 1;
+ULONG Hal4Debug = 1;
+ULONG Hal5Debug = 0;
+ULONG Hal6Debug = 1;
+ULONG HalIoMapped = 0;
+#endif // IOMAPDEBUG
+
+//
+// Define adapter object structure used for DMA transfers
+// on SGI MIPS machines.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentDevice;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters; // bit map used to keep track of free map regs
+ CHAR ChannelNumber; // (represents channel owner (SCSI, ENET, or IDE)
+ UCHAR AdapterNumber;
+} ADAPTER_OBJECT;
+
+//
+// Define translation table entry structure.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// The DMA controller has a larger number of map registers which may
+// be used by any adapter channel. In order to pool all of the map registers
+// a master adapter object is used. This object is allocated and saved
+// internal to this file. It contains a bit map for allocation of the
+// registers and a queue for requests which are waiting for more map
+// registers. This object is allocated during the first request to allocate
+// an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// The following are interrupt objects used for the 2nd level
+// interrupt dispatch routines.
+//
+
+KINTERRUPT HalpLoc0Interrupt;
+KINTERRUPT HalpLoc1Interrupt;
+
+//
+// The following spinlocks are used for the 2nd level interrupt
+// dispatch routines.
+//
+
+KSPIN_LOCK HalpLoc0Spinlock;
+KSPIN_LOCK HalpLoc1Spinlock;
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[SGI_MAX_DMA_CHANNELS];
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN ULONG AdapterChannel,
+ IN PVOID MapRegisterBase
+ );
+
+PADAPTER_OBJECT
+HalpAllocateMasterAdapter(
+ VOID
+ );
+
+
+//
+// This priority based index table contains offsets into
+// the IDT for a device ISR to execute. This table corresponds
+// to a left-to-right bit priority in the LOCAL0 register.
+//
+// The table works in the following way...
+//
+// The LOCAL0 masked status register is read.
+// The value read from the masked status register will index
+// into this table to obtain the offset into the IDT.
+//
+// Note the following example based on the table below...
+//
+// Assume the LOCAL0 masked status register has the value 9Ch.
+// This bit pattern, 10011100, shows that the following interrupts
+// are pending (from left to right):
+//
+// - VME0
+// - Graphics DMA
+// - Ethernet
+// - SCSI
+//
+// Since we have established a left-to-right prioritization scheme,
+// the VME0 interrupt will be vectored to based on our table
+// below. Entry 9Ch corresponds to bit 7 (from FFINTR).
+// Entry 7 in this table provides the interrupt vector for
+// this interrupt.
+//
+
+
+UCHAR HalpVector0[8] = {
+ SGI_VECTOR_GIO0FIFOFULL, // 0
+ SGI_VECTOR_IDEDMA, // 1
+ SGI_VECTOR_SCSI, // 2
+ SGI_VECTOR_ETHERNET, // 3
+ SGI_VECTOR_GRAPHICSDMA, // 4
+ SGI_VECTOR_SGIDUART, // 5
+ SGI_VECTOR_GIO1GE, // 6
+ SGI_VECTOR_VME0, // 7
+};
+
+//
+// This priority based index table contains offsets into
+// the IDT for a device ISR to execute. This table corresponds
+// to a left-to-right bit priority in the LOCAL1 register.
+//
+// This table works in the same way as the LOCAL1 vector table.
+//
+
+UCHAR HalpVector1[8] = {
+ 0, // 0 reserved
+ 0, // 1 reserved
+ 0, // 2 reserved
+ SGI_VECTOR_VME1, // 3
+ SGI_VECTOR_DSP, // 4
+ SGI_VECTOR_ACFAIL, // 5
+ SGI_VECTOR_VIDEOOPTION, // 6
+ SGI_VECTOR_GIO2VERTRET, // 7
+};
+
+// Find first bit set in local interrupt status register
+//
+static UCHAR fftab_hi[16] = {0, 4, 5,5, 6,6,6,6, 7,7,7,7,7,7,7,7};
+static UCHAR fftab_lo[16] = {0, 0, 1,1, 2,2,2,2, 3,3,3,3,3,3,3,3};
+#define FFINTR(m) (((m)>>4)?fftab_hi[m>>4]:fftab_lo[m&0xf])
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef VOID (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Define the secondary interrupt dispatch routines.
+//
+
+BOOLEAN
+HalpLoc0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpLoc1Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. The only bus type supported for the
+ Indigo is Internal.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adpater object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+ return( NULL );
+ }
+
+ //
+ // Create the master adapter object if it is not already.
+ //
+
+ if( MasterAdapterObject == NULL ) {
+ if( !(MasterAdapterObject = HalpAllocateMasterAdapter()) ) {
+ return( NULL );
+ }
+ }
+
+ //
+ // Set the maximum number of map registers if requested.
+ //
+
+ if (NumberOfMapRegisters != NULL) {
+
+ //
+ // Return half the total number of map registers per channel.
+ //
+
+ *NumberOfMapRegisters =
+ MasterAdapterObject->MapRegistersPerChannel / 2;
+ }
+
+ //
+ // Make sure the DMA access is for the HPC devices (internal).
+ // The GIO devices on this machine are SCSI, ENET, and IDE.
+ //
+
+ if (DeviceDescription->InterfaceType == Internal) {
+
+ //
+ // Make sure the DMA channel range is valid. Only use channels 0-2.
+ //
+
+ if (DeviceDescription->DmaChannel > SGI_MAX_DMA_CHANNELS) {
+ return( NULL );
+ }
+
+ //
+ // If the adapter has not been allocated yet, allocate the
+ // adapter for this channel and return the adapter object.
+ //
+ // CAVEAT: Originally HalpAllocateAdapter was written to
+ // specify the VA of the DMA channel as the second
+ // parameter. However, this is not going to be used
+ // for the SGI machine since SGI MIPS machines
+ // can potentially support a number of DMA devices
+ // than can have more than 1 virtual address for
+ // DMA control per channel (i.e. ENET on the GIO
+ // bus has separate VAs for XMIT and RECV on one
+ // DMA/HPC channel). IoMapTransfer will keep track
+ // of the virtual addresses for the required DMA
+ // channel request. Another field has been added
+ // to the ADAPTER_OBJECT structure to indicate what
+ // DMA channel is being requested.
+ //
+
+ if (HalpInternalAdapters[DeviceDescription->DmaChannel] == NULL) {
+
+ HalpInternalAdapters[DeviceDescription->DmaChannel] =
+ HalpAllocateAdapter(
+ 0, // map registers/channel
+ DeviceDescription->DmaChannel, // DMA channel number
+ NULL // map register base
+ );
+
+ }
+
+ return(HalpInternalAdapters[DeviceDescription->DmaChannel]);
+
+ } else {
+ return( NULL ); // This bus type is not supported.
+ }
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN ULONG AdapterChannel,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterChannel - The DMA channel for this adapter.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object.
+ //
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (SHORT)Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY );
+ AdapterObject->ChannelNumber = (UCHAR)AdapterChannel;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+ AdapterObject->AdapterNumber = 1;
+
+ //
+ // Initialize the channel wait queue for this adapter.
+ //
+
+ KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
+
+ } else {
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+ return( NULL );
+ }
+ } else {
+ return( NULL );
+ }
+
+ return AdapterObject;
+}
+
+PADAPTER_OBJECT
+HalpAllocateMasterAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes the master adapter object
+ used to pool DMA map registers in the system. A map register is
+ an arbitrary data structure defined by the HAL and used to
+ implement DMA transfers. For the SGI MIPS machine, the map
+ registers are structures to HPC descriptors.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ The function value is a pointer to the allocated master adapter object.
+
+--*/
+
+{
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the master adapter object and allocate space
+ // for the register bit map.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof(TRANSLATION_ENTRY))+7>>3))+3)&~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the master adapter object.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (SHORT)Size;
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY );
+ AdapterObject->ChannelNumber = -1;
+ AdapterObject->MasterAdapter = AdapterObject;
+ AdapterObject->AdapterNumber = 1;
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ //
+ // Initialize the channel wait queue for this adapter.
+ //
+ KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
+
+ //
+ // Initialize the register bit map, AdapterQueue, and spin lock.
+ //
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ RtlInitializeBitMap(
+ AdapterObject->MapRegisters,
+ (PULONG)(((PCHAR)(AdapterObject->MapRegisters)) +
+ sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+ //
+ // Allocate a page of memory to use as the map registers. This
+ // memory must be large enough to hold a all the registers and
+ // page aligned.
+ //
+
+ Size = DMA_TRANSLATION_LIMIT;
+ Size = ROUND_TO_PAGES( Size );
+
+ AdapterObject->MapRegisterBase = MmAllocateNonCachedMemory(Size);
+
+#ifdef IOMAPDEBUG
+#define PMASK ~0xfff
+ if (((unsigned)AdapterObject->MapRegisterBase & PMASK) !=
+ (((unsigned)AdapterObject->MapRegisterBase +
+ (DMA_TRANSLATION_LIMIT-1)) & PMASK)) {
+ DbgPrint("HalpAllocateMasterAdapter: "
+ "Map registers cross page boundary.\n");
+ DbgPrint("MapRegisterBase = 0x%x\n",
+ AdapterObject->MapRegisterBase);
+ DbgBreakPoint();
+ }
+#endif // IOMAPDEBUG
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+ ObDereferenceObject( AdapterObject );
+ return( NULL );
+ }
+
+ } else {
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+ return( NULL );
+ }
+ } else {
+ return( NULL );
+ }
+
+ return AdapterObject;
+}
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // If so, then queue the device object to the master adapter queue
+ // to wait for them to become available. If the driver wants map
+ // registers, ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ AdapterObject->CurrentDevice = Wcb;
+ AdapterObject->NumberOfMapRegisters =
+ Wcb->NumberOfMapRegisters;
+
+ if (NumberOfMapRegisters != 0) {
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase =
+ (PVOID)((PTRANSLATION_ENTRY)MasterAdapter->MapRegisterBase +
+ MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the
+ // number allocated to zero and set the action to deallocate
+ // object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+ IoFreeAdapterChannel( AdapterObject );
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. If not all of
+ the register could be allocated, then this field is updated to show
+ how many were allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters
+ );
+
+ MapRegisterNumber = (ULONG)-1;
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue
+ // and the bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentDevice;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber =
+ RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MapRegisterNumber
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ break;
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase =
+ (PVOID)((PTRANSLATION_ENTRY)MasterAdapter->MapRegisterBase +
+ MapRegisterNumber);
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action =
+ Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if
+ // there are no requests in the master adapter queue, then
+ // IoFreeMapRegisters will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }//END WHILE
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ){
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+ //
+ // There are no more requests break out of the loop.
+ //
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentDevice = Wcb;
+ AdapterObject->NumberOfMapRegisters =
+ Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0) {
+ if (Wcb->NumberOfMapRegisters >
+ MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber =
+ RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+ AdapterObject->MapRegisterBase =
+ (PVOID)((PTRANSLATION_ENTRY)MasterAdapter->MapRegisterBase +
+ MapRegisterNumber);
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentDevice = Wcb;
+ Action =
+ Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatchers.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ //
+ // Initialize the 2 2nd level dispatch interrupt routines.
+ //
+
+ KeInitializeSpinLock( &HalpLoc0Spinlock );
+ KeInitializeSpinLock( &HalpLoc1Spinlock );
+
+ //
+ // This routine is the 2nd level dispatch routine for the
+ // devices connected to the LOCAL0 interrupt controller
+ // register.
+ //
+
+ KeInitializeInterrupt( &HalpLoc0Interrupt,
+ HalpLoc0Dispatch,
+ (PVOID)0L,
+ &HalpLoc0Spinlock,
+ LOCAL0_LEVEL,
+ LOCAL0_LEVEL,
+ LOCAL0_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpLoc0Interrupt )) {
+ return(FALSE);
+ }
+
+ //
+ // This routine is the 2nd level dispatch routine for the
+ // devices connected to the LOCAL1 interrupt controller
+ // register.
+ //
+
+ KeInitializeInterrupt( &HalpLoc1Interrupt,
+ HalpLoc1Dispatch,
+ (PVOID)0L,
+ &HalpLoc1Spinlock,
+ LOCAL1_LEVEL,
+ LOCAL1_LEVEL,
+ LOCAL1_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ if (!KeConnectInterrupt( &HalpLoc1Interrupt )) {
+ return(FALSE);
+ }
+
+#ifdef ENABLE_FIFOFULL
+ HalEnableSystemInterrupt (SGI_VECTOR_GIO0FIFOFULL, LOCAL0_LEVEL, Latched);
+#endif
+ {
+ ULONG cpuctrl1 = *(volatile ULONG *)0xbfa00008;
+ cpuctrl1 = (cpuctrl1 & 0xfffffff0) | 0xd;
+ *(volatile ULONG *)0xbfa00008 = cpuctrl1;
+ }
+
+ return (TRUE);
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device. This routine will start the DMA
+ transfer for the HPC device.
+
+ Scatter/Gather DMA transfers can be performed by building the scatter
+ gather list into the MDL. IoMapTransfer will handle mapping the
+ MDL list to the Scatter/Gather map registers defined by the DMA channel.
+
+ NB: This routine may need a spinlock to exclude access to DMA registers
+ that are programmed within this procedure. If no DMA registers are
+ programmed in this procedure, no spinlock is required.
+
+ This routine also needs to account for being called recursively
+ where CurrentVa is the buffer to work with from the StartVa in
+ the Mdl. This affects where to start in the Mdl and MapRegisterBase.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from. The assumption is
+ made that this address is equal to or some increment above
+ MDL->StartVa.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG PhysMapRegister, NumberOfPages;
+ ULONG ByteCount, Offset, Len, i;
+ ULONG ShortPhysAddress;
+ PVOID Pa;
+
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+
+ //
+ // If an Adapter Object is not defined, then this request is from a
+ // master.
+ //
+
+ if( AdapterObject == NULL ) {
+#ifdef IOMAPDEBUG
+ DbgPrint ("IoMapTransfer: called for master adapter object.\n");
+ DbgBreakPoint();
+#endif // IOMAPDEBUG
+ return(RtlConvertUlongToLargeInteger(Offset));
+ }
+
+#ifdef IOMAPDEBUG
+ if (HalIoMapped) {
+ DbgPrint ("IoMapTransfer: Io Mapped before flushed.\n");
+ DbgBreakPoint();
+ }
+ HalIoMapped = 1;
+#endif // IOMAPDEBUG
+
+ Len = *Length;
+
+ //
+ // Get a pointer to the array of physical pages located just after
+ // the MDL header structure.
+ //
+
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+
+ //
+ // Determine the maximum number of pages required to satisfy this request.
+ //
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ //
+ // Build the DMA descriptor list by mapping the MDL page(s) into the
+ // map registers. For the HPC DMA, there is a one-to-one mapping of
+ // MDL pages to HPC descriptors.
+ //
+ ByteCount = (NumberOfPages == 1 ? Len : PAGE_SIZE - Offset);
+ for( i = 0; i < NumberOfPages; i++, DmaMapRegister++ ) {
+
+ //
+ // If this is the first entry, add the byte offset to
+ // the first physical page address.
+ //
+ if( i == 0 )
+ Pa = (PVOID)((*PageFrameNumber++ << PAGE_SHIFT) + Offset);
+ else
+ Pa = (PVOID)(*PageFrameNumber++ << PAGE_SHIFT);
+
+ //
+ // Update the HPC descriptor fields.
+ //
+
+ ZERO_TRANSLATION_ENTRY( DmaMapRegister );
+ ASSERT (ByteCount <= (ULONG)0x1000);
+ SET_HPC_BC( DmaMapRegister, ByteCount );
+ SET_HPC_CBP( DmaMapRegister, Pa );
+
+ //
+ // If this is the last entry, indicate that this is the last
+ // HPC descriptor in the list, else point to the next one in
+ // the chain.
+ //
+
+ if( (i + 1) == NumberOfPages ) {
+ SET_HPC_EOD( DmaMapRegister );
+ } else {
+ ShortPhysAddress = MmGetPhysicalAddress(DmaMapRegister + 1).LowPart;
+ SET_HPC_NBP( DmaMapRegister, ShortPhysAddress );
+ }
+
+ //
+ // Compute the byte count for the next entry.
+ //
+
+ if( (i + 2) == NumberOfPages )
+ ByteCount = Len - ((PAGE_SIZE * (NumberOfPages-1)) - Offset);
+ else
+ ByteCount = PAGE_SIZE;
+ } //END FOR
+
+ //
+ // Setup the HPC for the DMA transfer and transfer the data.
+ //
+
+ ShortPhysAddress = MmGetPhysicalAddress(MapRegisterBase).LowPart;
+ PhysMapRegister = ShortPhysAddress;
+
+ switch( AdapterObject->ChannelNumber ) {
+
+ case SGI_SCSI_DMA_CHANNEL:
+
+#ifdef IOMAPDEBUG
+ // Examine aux register on wd chip. If it's busy, then
+ // something's wrong.
+ if (Hal3Debug) {
+ volatile unsigned char aux = *(volatile unsigned char *)0xbfb80121;
+ unsigned long auxcount = 0;
+#ifdef OLD
+ if (aux & 0x20) {
+ DbgPrint ("IoMapTransfer: wd chip already busy\n");
+ DbgBreakPoint();
+ }
+#else // !OLD
+ while ((aux & 0x20) && (auxcount < 100000)) {
+ auxcount++;
+ aux = *(volatile unsigned char *)0xbfb80121;
+ }
+ if (auxcount) {
+ DbgPrint ("IoMapTransfer: wd chip already busy: %d\n",
+ auxcount);
+ if (Hal6Debug)
+ DbgBreakPoint();
+ }
+#endif // !OLD
+
+ if (READ_REGISTER_ULONG(&SCSI0_HPCREG->ScsiCNTL) &
+ SGI_CNTL_SCSIDMASTART) {
+ DbgPrint ("IoMapTransfer: dma start bit still set\n");
+ DbgBreakPoint();
+ }
+ }
+
+ //
+ // This was the infamous delay bug.
+ // If HalDebug is set to 0x2000, everything works
+ //
+ if( HalDebug )
+ KeStallExecutionProcessor(HalDebug);
+#endif // IOMAPDEBUG
+#ifdef DMADEBUG
+ if (Hal2Debug) {
+ if (READ_REGISTER_ULONG(&SCSI0_HPCREG->ScsiCNTL) &
+ SGI_CNTL_SCSIDMASTART) {
+ DbgPrint ("IoMapTransfer: dma start bit still set\n");
+ DbgBreakPoint();
+ }
+ }
+#endif // DMADEBUG
+
+ WRITE_REGISTER_ULONG( &SCSI0_HPCREG->ScsiNBP, PhysMapRegister );
+ WRITE_REGISTER_ULONG( &SCSI0_HPCREG->ScsiCNTL, (WriteToDevice ?
+ (SGI_CNTL_SCSIDMASTART) :
+ (SGI_CNTL_SCSIDMASTART | SGI_CNTL_SCSITOMEMORY)) );
+ break;
+
+ case SGI_ENET_DMA_CHANNEL:
+ case SGI_PARALLEL_DMA_CHANNEL:
+ default:
+ DbgPrint( "HAL: Dma Channel not supported %u\n",
+ AdapterObject->ChannelNumber );
+ DbgBreakPoint();
+ break;
+
+ }// END SWITCH
+
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ None
+
+--*/
+{
+ ULONG timeout; // in microseconds
+
+ //
+ // We will only flush slave DMA adapters.
+ //
+
+ if( AdapterObject == NULL )
+ return FALSE;
+
+#ifdef IOMAPDEBUG
+ if (!HalIoMapped) {
+ DbgPrint ("HalFlushAdapter: Io Not Mapped.\n");
+ DbgBreakPoint();
+ }
+ HalIoMapped = 0;
+#endif // IOMAPDEBUG
+
+ //
+ // If the last DMA transfer was a SCSI read, flush the DMA fifos.
+ //
+
+ if( AdapterObject->ChannelNumber == SGI_SCSI_DMA_CHANNEL ) {
+
+#ifdef IOMAPDEBUG
+ // Examine aux register on wd chip. If it's busy, then
+ // something's wrong.
+ if (Hal4Debug) {
+ unsigned char aux = *(volatile unsigned char *)0xbfb80121;
+ if (aux & 0x20) {
+ int timeout = 1000;
+ if (Hal5Debug)
+ DbgPrint ("IoFlushAdapterBuffers: wd chip still busy\n");
+ while (timeout--) {
+ aux = *(volatile unsigned char *)0xbfb80121;
+ if (!(aux & 0x20))
+ break;
+ }
+ if (!timeout) {
+ DbgPrint("wd chip busy timed out\n");
+ DbgBreakPoint();
+ }
+ }
+ }
+#endif // IOMAPDEBUG
+
+ // If the transfer was a read, set the HPC's flush bit to flush the
+ // fifos.
+ //
+ if( !WriteToDevice ) { // if read...
+
+ WRITE_REGISTER_ULONG(&SCSI0_HPCREG->ScsiCNTL,
+ (ULONG)(READ_REGISTER_ULONG( &SCSI0_HPCREG->ScsiCNTL ) |
+ SGI_CNTL_SCSIFLUSH));
+
+ //
+ // Make sure the fifo is flushed and the DMA transfer has
+ // completed for a read.
+ //
+
+ for( timeout = 1000000; timeout; timeout--)
+ if(!(READ_REGISTER_ULONG( &SCSI0_HPCREG->ScsiCNTL ) &
+ SGI_CNTL_SCSIDMASTART) )
+ break; // flush complete, get out of loop
+
+ //
+ // If a timeout occurred, then our DMA transfer did not flush
+ // for some reason and it is probably hosed.
+ //
+
+ if( !timeout ) {
+ DbgPrint("\nIoFlushAdapterBuffers: DMA not flushed.\n");
+ DbgPrint( " SCSI.CNTL = %08lx\n\n",
+ READ_REGISTER_ULONG( &SCSI0_HPCREG->ScsiCNTL ));
+ DbgBreakPoint();
+ }
+ }
+ // Turn off DMA start bit
+ //
+ WRITE_REGISTER_ULONG( &SCSI0_HPCREG->ScsiCNTL, 0 );
+ } else
+ DbgBreakPoint();
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpLoc0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the LOCAL0 device interrupts. Its function is to call the second
+ level interrupt dispatch routine.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt( &HalpLoc0Interrupt,
+ HalpLoc0Dispatch,
+ (PVOID)0L,
+ &HalpLoc0Spinlock,
+ LOCAL0_LEVEL,
+ LOCAL0_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE,
+ (PKINTERRUPT)NULL
+ );
+ KeConnectInterrupt( &HalpLoc0Interrupt );
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to an arbitrary data structure.
+
+Return Value:
+
+ Returns the value returned from the 2nd level routine.
+
+--*/
+
+{
+ UCHAR mask, stat;
+
+ //
+ // Since the mask registers ONLY disable the interrupt generating
+ // capability of the bits in the status register, we need to mask
+ // off any extraneous bits that we really want masked as to not
+ // process them.
+ //
+
+ stat = READ_REGISTER_UCHAR(SGI_LISTAT0_BASE);
+ mask = READ_REGISTER_UCHAR(SGI_LIMASK0_BASE);
+
+ // Fast (if you can call it that :) path for fifofull interrupt
+ //
+ if ((mask & L0_MASK_GIO0FIFOFULL) &&
+ ((stat & L0_MASK_GIO0FIFOFULL) || !stat)) {
+
+ // Unlatch interrupt
+ //
+ mask &= ~L0_MASK_GIO0FIFOFULL;
+ WRITE_REGISTER_UCHAR(SGI_LIMASK0_BASE, mask);
+ mask |= L0_MASK_GIO0FIFOFULL;
+ WRITE_REGISTER_UCHAR(SGI_LIMASK0_BASE, mask);
+
+ if (stat) {
+ ULONG timeout;
+#define FIFO_TIMEOUT 300000 // ~300 ms
+
+// DbgPrint("FIFOFULL interrupt\n");
+ for (timeout = FIFO_TIMEOUT;
+ timeout > 0 && (stat & L0_MASK_GIO0FIFOFULL);
+ timeout--) {
+
+ stat = READ_REGISTER_UCHAR(SGI_LISTAT0_BASE);
+ KeStallExecutionProcessor(1);
+ }
+
+ if (!timeout)
+ DbgPrint("Fifo timeout\n");
+ }
+// else
+// DbgPrint("Stray FIFOFULL interrupt\n");
+
+ return TRUE;
+ }
+
+ mask &= stat;
+
+ //
+ // Dispatch to the secondary interrupt service routine for each
+ // interrupt asserted.
+ //
+
+ if (mask) do {
+ register UCHAR ffintr = FFINTR(mask);
+ register PKINTERRUPT_ROUTINE IntrFunc =
+ PCR->InterruptRoutine[HalpVector0[ffintr]];
+
+ // Kernel dispatch code actually restores the arguments
+ // for the second level service routine from dispatch
+ // function pointer.
+ //
+ ((PSECONDARY_DISPATCH)IntrFunc)(IntrFunc);
+
+ mask &= ~(1<<ffintr);
+ } while (mask);
+ else {
+ DbgPrint ("Stray Local 0 Interrupt\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOLEAN
+HalpLoc1Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the LOCAL1 device interrupts. Its function is to call the second
+ level interrupt dispatch routine.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt( &HalpLoc1Interrupt,
+ HalpLoc1Dispatch,
+ (PVOID)0L,
+ &HalpLoc1Spinlock,
+ LOCAL1_LEVEL,
+ LOCAL1_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE,
+ (PKINTERRUPT)NULL
+ );
+ KeConnectInterrupt( &HalpLoc1Interrupt );
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to an arbitrary data structure.
+
+Return Value:
+
+ Returns the value returned from the 2nd level routine.
+
+--*/
+
+{
+ UCHAR mask;
+
+ //
+ // Since the mask registers ONLY disable the interrupt generating
+ // capability of the bits in the status register, we need to mask
+ // off any extraneous bits that we really want masked as to not
+ // process them.
+ //
+
+ mask = ( READ_REGISTER_UCHAR(SGI_LISTAT1_BASE) &
+ READ_REGISTER_UCHAR(SGI_LIMASK1_BASE) );
+
+ //
+ // Dispatch to the secondary interrupt service routine for each
+ // interrupt asserted.
+ //
+
+ if (mask) do {
+ register UCHAR ffintr = FFINTR(mask);
+ register PKINTERRUPT_ROUTINE IntrFunc =
+ PCR->InterruptRoutine[HalpVector1[ffintr]];
+
+ // Kernel dispatch code actually restores the arguments
+ // for the second level service routine from dispatch
+ // function pointer.
+ //
+ ((PSECONDARY_DISPATCH)IntrFunc)(IntrFunc);
+
+ mask &= ~(1<<ffintr);
+ } while (mask);
+ else {
+ DbgPrint ("Stray Local 1 Interrupt\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+
+ return(NULL);
+
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return(0);
+}
+
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return(0);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ return(0);
+}
+
+static char outbuf[64];
+
+VOID
+HalpBuserrInterrupt(void)
+{
+ ULONG stat, addr;
+
+ HalDisplayString("Hal: bus error interrupt detected\n");
+ addr = *(volatile ULONG *)CPU_ERR_ADDR;
+ stat = *(volatile ULONG *)CPU_ERR_STAT;
+ sprintf (outbuf, "CPU: Stat = 0x%x, Addr = 0x%x\n", stat, addr);
+ HalDisplayString(outbuf);
+ addr = *(volatile ULONG *)GIO_ERR_ADDR;
+ stat = *(volatile ULONG *)GIO_ERR_STAT;
+ sprintf (outbuf, "GIO: Stat = 0x%x, Addr = 0x%x\n", stat, addr);
+ HalDisplayString(outbuf);
+ *(volatile ULONG *)CPU_ERR_ADDR = 0;
+ *(volatile ULONG *)CPU_ERR_STAT = 0;
+ *(volatile ULONG *)GIO_ERR_ADDR = 0;
+ *(volatile ULONG *)GIO_ERR_STAT = 0;
+
+ while (1)
+ DbgBreakPoint();
+}
+
+VOID
+HalpSystemInit(void)
+{
+ PCR->InterruptRoutine[SYSBUS_LEVEL] = HalpBuserrInterrupt;
+ HalpInitNvram();
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxmapio.c b/private/ntos/nthals/halsgi/mips/sxmapio.c
new file mode 100644
index 000000000..c2a8db419
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxmapio.c
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3mapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for the
+ SGI Indigo system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Since the IO space for the SGI Indigo system is unmapped, this routine
+ has nothing to do.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Since all of the physical device addresses can be accessed
+ // directly from KSEG1, there is no need to map these physical
+ // addresses into TLB entries for the MIPS R3000/4000.
+ //
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxmaptb.c b/private/ntos/nthals/halsgi/mips/sxmaptb.c
new file mode 100644
index 000000000..3da71ed6f
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxmaptb.c
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3maptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for the
+ SGI Indigo system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ It does not do any DMA mapping because the DMA device(s) are
+ located in 'unmapped' space.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Always TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxport.c b/private/ntos/nthals/halsgi/mips/sxport.c
new file mode 100644
index 000000000..57814824d
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxport.c
@@ -0,0 +1,294 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3port.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on SGI's Indigo system and the host system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Kevin Meier (o-kevinm) 20-Jan-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+// BUGBUG put these in a header file!!!
+// Defines from sgikbmou.h for the z8530
+//
+#define DBGPORT_BASE 0xbfb80d10
+
+#define DBGPORT_CTRL DBGPORT_BASE
+#define DBGPORT_DATA (DBGPORT_BASE+4)
+
+#define RR0_TX_EMPTY 0x04 /* Tx buffer empty */
+#define RR0_RX_CHR 0x01 /* Rx character available */
+
+#define RR1_FRAMING_ERR 0x40 /* framing error */
+#define RR1_RX_ORUN_ERR 0x20 /* Rx overrun */
+#define RR1_PARITY_ERR 0x10 /* parity error */
+
+#define WR0_RST_ERR 0x30 /* reset error (bits in RR1) */
+
+#define RR1 1 /* Rx condition status/residue codes */
+#define WR12 12
+#define WR13 13
+#define WR14 14
+#define WR14_BRG_ENBL 0x01
+
+#define Z8530_DELAY KeStallExecutionProcessor(1)
+#define BRATE 19200
+#define CLK_SPEED 3672000
+#define CLK_FACTOR 16
+#define WR_CNTRL(p, r, v) {Z8530_DELAY; \
+ WRITE_REGISTER_ULONG((p), (ULONG)(r)); \
+ Z8530_DELAY; \
+ WRITE_REGISTER_ULONG((p), (ULONG)(v));}
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG For now, the kernel debugger will use this variable to
+// port to the debugger port it is using.
+//
+PUCHAR KdComPortInUse = NULL;
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+{
+ ULONG baud =
+ (CLK_SPEED + BRATE * CLK_FACTOR) / (BRATE * CLK_FACTOR * 2) - 2;
+
+
+ //
+ // If the debugger is not being enabled, then return. There is no
+ // need to capture any parameters.
+ //
+
+ if (Initialize == FALSE) {
+ return(TRUE);
+ }
+
+ //
+ // BUGBUG For now, simply save the physical base of the
+ // uart being used for debugging. The serial driver will
+ // use this to prevent itself from using the UART.
+ //
+ KdComPortInUse = (PUCHAR)DBGPORT_CTRL;
+
+ // The prom has already initialized the port, simply set the baud
+ // rate to 19200.
+ //
+ WR_CNTRL(DBGPORT_CTRL, WR14, 0x00)
+ WR_CNTRL(DBGPORT_CTRL, WR12, baud & 0xff)
+ WR_CNTRL(DBGPORT_CTRL, WR13, (baud >> 8) & 0xff)
+ WR_CNTRL(DBGPORT_CTRL, WR14, WR14_BRG_ENBL)
+
+ return TRUE;
+}
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ if (!(READ_REGISTER_ULONG(DBGPORT_CTRL) & RR0_RX_CHR))
+ continue;
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+ WRITE_REGISTER_ULONG(DBGPORT_CTRL, RR1);
+ if((READ_REGISTER_ULONG(DBGPORT_CTRL) &
+ (RR1_RX_ORUN_ERR | RR1_FRAMING_ERR | RR1_PARITY_ERR))) {
+ WRITE_REGISTER_ULONG(DBGPORT_CTRL, WR0_RST_ERR);
+ return CP_GET_ERROR;
+ } else {
+ *Input = (UCHAR)(READ_REGISTER_ULONG(DBGPORT_DATA));
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (IN UCHAR Output)
+{
+ // Wait for the transmit buffer to empty, and write the char.
+ //
+ while(!(READ_REGISTER_ULONG(DBGPORT_CTRL) & RR0_TX_EMPTY))
+ ; // empty
+ WRITE_REGISTER_ULONG(DBGPORT_DATA,(ULONG)Output);
+ return;
+}
+
+VOID
+KdPortRestore (VOID)
+{
+ return;
+}
+
+VOID
+KdPortSave (VOID)
+{
+ return;
+}
+
+#ifdef DBG
+VOID
+SgiPortPuts(IN PCHAR pString)
+{
+ for(; *pString; KdPortPutByte((UCHAR)*pString), ++pString );
+}
+#endif
diff --git a/private/ntos/nthals/halsgi/mips/sxreturn.c b/private/ntos/nthals/halsgi/mips/sxreturn.c
new file mode 100644
index 000000000..f8ca080ce
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxreturn.c
@@ -0,0 +1,80 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3return.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+ Kevin Meier (o-kevinm) 20-Jan-1992
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KeStallExecutionProcessor(10000); // short (10 ms) delay
+ HalDisplayString(""); // clear screen
+
+ // back to prom
+ //
+ switch (Routine) {
+ case HalHaltRoutine:
+ ArcHalt();
+ break;
+ case HalPowerDownRoutine:
+ ArcPowerDown();
+ break;
+ case HalRestartRoutine:
+ ArcRestart();
+ break;
+ case HalRebootRoutine:
+ ArcReboot();
+ break;
+ case HalInteractiveModeRoutine:
+ ArcEnterInteractiveMode();
+ break;
+ default:
+ HalDisplayString("Unknown ARCS restart function.\n");
+ DbgBreakPoint();
+ }
+ /* NOTREACHED */
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxsysint.c b/private/ntos/nthals/halsgi/mips/sxsysint.c
new file mode 100644
index 000000000..bc336ae7b
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxsysint.c
@@ -0,0 +1,294 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3sysint.c
+
+Abstract:
+
+ This module implements the HAL procedures required to maintain
+ system interrupt processing for a SGI Indigo system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+ Kevin Meier (o-kevinm) 20-Jan-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to disable a system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // This is a temp solution until these vectors can be obtained
+ // via the configuration manager. For now, these vectors are
+ // hardcoded in "sgidef.h".
+ //
+
+ switch( (UCHAR)Vector ){
+
+ //
+ // LOCAL0 vectors.
+ //
+
+ case SGI_VECTOR_GIO0FIFOFULL: // (0 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_IDEDMA: // (1 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_SCSI: // (2 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_ETHERNET: // (3 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_GRAPHICSDMA: // (4 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_SGIDUART: // (5 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_GIO1GE: // (6 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_VME0: // (7 + SGI_LOCAL0_VECTORS)
+ DISABLE_LOCAL0_IRQ( 1 << ((UCHAR)Vector - SGI_LOCAL0_VECTORS) );
+ break;
+
+ //
+ // LOCAL1 vectors.
+ //
+
+ case SGI_VECTOR_VME1: // (3 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_DSP: // (4 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_ACFAIL: // (5 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_VIDEOOPTION: // (6 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_GIO2VERTRET: // (7 + SGI_LOCAL1_VECTORS)
+ DISABLE_LOCAL1_IRQ( 1 << ((UCHAR)Vector - SGI_LOCAL1_VECTORS) );
+ break;
+
+ //
+ // Gets here when the disconnect interrupt routine is called
+ // for the second level dispatch routine (never)
+ //
+
+ case SGI_VECTOR_LOCAL0:
+ case SGI_VECTOR_LOCAL1:
+ break;
+
+ default:
+ DbgPrint("\nInvalid Vector (0x%x) passed.\n", (UCHAR)Vector);
+ DbgBreakPoint();
+
+ }// END SWITCH
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to enable a system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // This is a temp solution until these vectors can be obtained
+ // via the configuration manager. For now, these vectors are
+ // hardcoded in "sgidef.h".
+ //
+
+ switch( (UCHAR)Vector ){
+
+ //
+ // LOCAL0 vectors.
+ //
+
+ case SGI_VECTOR_GIO0FIFOFULL: // (0 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_IDEDMA: // (1 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_SCSI: // (2 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_ETHERNET: // (3 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_GRAPHICSDMA: // (4 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_SGIDUART: // (5 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_GIO1GE: // (6 + SGI_LOCAL0_VECTORS)
+ case SGI_VECTOR_VME0: // (7 + SGI_LOCAL0_VECTORS)
+ ENABLE_LOCAL0_IRQ( 1 << ((UCHAR)Vector - SGI_LOCAL0_VECTORS) );
+ break;
+
+ //
+ // LOCAL1 vectors.
+ //
+
+ case SGI_VECTOR_VME1: // (3 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_DSP: // (4 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_ACFAIL: // (5 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_VIDEOOPTION: // (6 + SGI_LOCAL1_VECTORS)
+ case SGI_VECTOR_GIO2VERTRET: // (7 + SGI_LOCAL1_VECTORS)
+ ENABLE_LOCAL1_IRQ( 1 << ((UCHAR)Vector - SGI_LOCAL1_VECTORS) );
+ break;
+
+ //
+ // Gets here when the connect interrupt routine is called
+ // for the second level dispatch routine (init only)
+ //
+
+ case SGI_VECTOR_LOCAL0:
+ case SGI_VECTOR_LOCAL1:
+ break;
+
+ default:
+ DbgPrint("\nHal: Invalid Vector (0x%x) passed.\n",(UCHAR)Vector);
+ DbgBreakPoint();
+
+ }// END SWITCH
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ //
+ // Just return the passed parameters for now.
+ //
+
+ *Irql = (UCHAR)BusInterruptLevel;
+ *Affinity = 1;
+ return( BusInterruptVector );
+
+}
+VOID
+HalRequestIpi(
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ Requests an interprocessor interrupt
+
+Arguments:
+
+ Mask - Supplies a mask of the processors to interrupt
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+}
diff --git a/private/ntos/nthals/halsgi/mips/sxtime.c b/private/ntos/nthals/halsgi/mips/sxtime.c
new file mode 100644
index 000000000..e031608dc
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxtime.c
@@ -0,0 +1,281 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992 Silicon Graphics, Inc.
+
+Module Name:
+
+ s3time.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ the SGI Indigo system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+ Kevin Meier (o-kevinm) 21-Jan-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+struct dp8573_clk {
+ volatile unsigned int ck_status; /* main status reg */
+ union {
+ struct {
+ int fill[2];
+ volatile unsigned int ck_pflag; /* periodic flag */
+ volatile unsigned int ck_tsavctl; /* time save control */
+ } rs0;
+ struct {
+ volatile unsigned int ck_rtime; /* real time mode */
+ volatile unsigned int ck_outmode; /* output mode */
+ volatile unsigned int ck_int0ctl; /* interrupt control 0 */
+ volatile unsigned int ck_int1ctl; /* interrupt control 1 */
+ } rs1;
+ } rs;
+ volatile unsigned int ck_counter[10]; /* the counters */
+ int fill1[4];
+ volatile unsigned int ck_cmpram[6]; /* time compare ram */
+ volatile unsigned int ck_timsav[5]; /* time save ram */
+ volatile unsigned int ram[2]; /* ram */
+};
+
+#define ck_pflag0 rs.rs0.ck_pflag
+#define ck_tsavctl0 rs.rs0.ck_tsavctl
+#define ck_rtime1 rs.rs1.ck_rtime
+#define ck_outmode1 rs.rs1.ck_outmode
+#define ck_int0ctl1 rs.rs1.ck_int0ctl
+#define ck_int1ctl1 rs.rs1.ck_int1ctl
+
+#define RT_CLOCK_ADDR 0xbfb80e00
+#define CLOCK_READ 0 /* _clock_func read command */
+#define CLOCK_WRITE 1 /* _clock_func write command */
+
+#define CLK_SHIFT 0 /* Indigo uses the LSB */
+
+#define RTC_RUN (3 << (CLK_SHIFT + 3))
+#define RTC_RS (1 << (CLK_SHIFT + 6))
+#define RTC_TIMSAVON (1 << (CLK_SHIFT + 7))
+#define RTC_TIMSAVOFF 0
+#define RTC_STATINIT 0
+#define RTC_INT1INIT (0x80 << CLK_SHIFT)
+#define RTC_PFLAGINIT 0
+#define RTC_OUTMODINIT 0
+
+#define YRREF 1990
+
+static void _clock_func(int, char *);
+static int counter_not_moving (void);
+int rtclock_ok = 0;
+
+
+BOOLEAN
+HalQueryRealTimeClock (
+ IN PTIME_FIELDS t
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ char buf[8];
+ int tries = 0;
+
+again:
+ _clock_func(CLOCK_READ, buf);
+
+ if (!(((int)buf[ 4 ] << CLK_SHIFT) & RTC_RUN) ||
+ (!rtclock_ok && counter_not_moving ())) {
+ //
+ // XXX Initialize to something that's not too unreasonable
+ // if the clock's out of whack. Currently the prom resets
+ // the clock to 0 when it powers on.
+ //
+ t->Second = 0;
+ t->Minute = 0;
+ t->Hour = 0;
+ t->Day = 1;
+ t->Month = 1;
+ t->Year = 1992;
+ t->Milliseconds = 0;
+ HalDisplayString ("Setting clock to 1/1/92, 00:00:00\n");
+ HalSetRealTimeClock (t);
+ if ( tries++ )
+ return FALSE;
+ goto again;
+ }
+
+ t->Second = (unsigned)(buf[ 0 ] & 0xf);
+ t->Second += (unsigned)(buf[ 0 ] >> 4) * 10;
+
+ t->Minute = (unsigned)(buf[ 1 ] & 0xf);
+ t->Minute += (unsigned)(buf[ 1 ] >> 4) * 10;
+
+ /*
+ ** we use 24 hr mode, so bits 4 and 5 represent to 2 ten-hour
+ ** bits
+ */
+ t->Hour = (unsigned)( buf[ 2 ] & 0xf );
+ t->Hour += (unsigned)( ( buf[ 2 ] >> 4 ) & 0x3 ) * 10;
+
+ /*
+ ** actually day of month
+ */
+ t->Day = (unsigned)( buf[ 3 ] & 0xf );
+ t->Day += (unsigned)( buf[ 3 ] >> 4 ) * 10;
+
+ t->Month = (unsigned)( buf[ 5 ] & 0xf );
+ t->Month += (unsigned)( buf[ 5 ] >> 4 ) * 10;
+
+ t->Year = (unsigned)( buf[ 6 ] & 0xf );
+ t->Year += (unsigned)( buf[ 6 ] >> 4 ) * 10;
+ t->Year += YRREF;
+
+ t->Milliseconds = 0;
+
+ /*
+ ** if the year is set to zero, then the clock must have stopped
+ */
+ if (!buf[6])
+ return FALSE;
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS t
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ char buf[ 8 ];
+
+ buf[0] = 0;
+ buf[1] = ((t->Second / 10) << 4) | (t->Second % 10);
+ buf[2] = ((t->Minute / 10) << 4) | (t->Minute % 10);
+ buf[3] = ((t->Hour / 10) << 4) | (t->Hour % 10);
+ buf[4] = 0;
+ buf[5] = ((t->Day / 10) << 4) | (t->Day % 10);
+ buf[6] = ((t->Month / 10) << 4) | (t->Month % 10);
+ buf[7] = (((t->Year-YRREF) / 10) << 4) | ((t->Year-YRREF) % 10);
+ _clock_func(CLOCK_WRITE, buf);
+
+ if (!rtclock_ok && counter_not_moving())
+ return FALSE;
+ return TRUE;
+}
+
+static void
+_clock_func(int func, char *ptr)
+{
+ register struct dp8573_clk *clock;
+ char *state;
+ int leap, i;
+
+ clock = (struct dp8573_clk *)RT_CLOCK_ADDR;
+
+ if (func == CLOCK_READ) {
+ /* clear the time save RAM */
+ for (i = 0; i < 5; i++)
+ clock->ck_timsav[i] = 0;
+ /* latch the Time Save RAM */
+ clock->ck_status = RTC_STATINIT;
+ clock->ck_tsavctl0 = RTC_TIMSAVON;
+ clock->ck_tsavctl0 = RTC_TIMSAVOFF;
+ for (i = 0; i < 5; i++) {
+ if (i == 4) /* keep the format the same */
+ state = ptr++; /* as for IP4 */
+ *ptr++ = (char) (clock->ck_timsav[i] >> CLK_SHIFT);
+ }
+ *ptr = (char) (clock->ck_counter[6] >> CLK_SHIFT);
+ clock->ck_status |= RTC_RS;
+ *state = (char) (clock->ck_rtime1 >> CLK_SHIFT);
+ } else {
+ clock->ck_status = RTC_STATINIT;
+ clock->ck_tsavctl0 = RTC_TIMSAVOFF;
+ clock->ck_pflag0 = RTC_PFLAGINIT;
+ clock->ck_status = RTC_RS;
+ clock->ck_int1ctl1 = RTC_INT1INIT;
+ clock->ck_outmode1 = RTC_OUTMODINIT;
+
+ clock->ck_rtime1 &= ~RTC_RUN;
+ for (i = 0; i < 7; i++) {
+ if (i == 4)
+ ptr++;
+ clock->ck_counter[i] = *ptr++ << CLK_SHIFT;
+ }
+ leap = clock->ck_counter[6] % 4;
+ clock->ck_rtime1 = RTC_RUN | (leap << CLK_SHIFT);
+ }
+
+}
+
+static int
+counter_not_moving (void)
+{
+ struct dp8573_clk *clock = (struct dp8573_clk *)RT_CLOCK_ADDR;
+ int delay_count = 1000000;
+ unsigned char initial;
+
+ rtclock_ok = 1;
+ clock->ck_status = RTC_STATINIT;
+ initial = (unsigned char)(clock->ck_counter[0] >> CLK_SHIFT);
+
+ while (delay_count--)
+ if ((unsigned char)(clock->ck_counter[0] >> CLK_SHIFT) != initial)
+ return (0);
+
+ rtclock_ok = 0;
+ return (1);
+} /* counter_not_moving */
diff --git a/private/ntos/nthals/halsgi/mips/sxusage.c b/private/ntos/nthals/halsgi/mips/sxusage.c
new file mode 100644
index 000000000..07cecfba6
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/sxusage.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ sxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the SGI hal.
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/halsgi/mips/x4clock.s b/private/ntos/nthals/halsgi/mips/x4clock.s
new file mode 100644
index 000000000..c2d606ed1
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/x4clock.s
@@ -0,0 +1,210 @@
+#if defined(R4000)
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+#if defined(SGI)
+#include "sgidef.h"
+
+ li t0,SGI_CLRTIMER_BASE // Get time address
+ li t1,TC_CLEAR_TIMER1 // Get timer to Ack
+ sb t1,0(t0) // Ack timer
+
+#endif
+
+ move a0,s8 // set address of trap frame
+ li a1,10 * 1000 * 10 // ****** temp *****
+ jal KeUpdateSystemTime // update system time
+ lw t0,KdDebuggerEnabled // check if debugger enabled
+ lbu t0,0(t0) //
+ beq zero,t0,10f // if eq, debuger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,10f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+10: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ la t1,HalpPerformanceCounter // get performance counter address
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ j KeProfileInterrupt // process profile entries
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+#endif
diff --git a/private/ntos/nthals/halsgi/mips/x4tb.s b/private/ntos/nthals/halsgi/mips/x4tb.s
new file mode 100644
index 000000000..1840cdff9
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/x4tb.s
@@ -0,0 +1,5 @@
+//
+// Include code from halfxs
+// This is a cpp style symbolic link
+
+#include "..\halfxs\mips\x4tb.s"
diff --git a/private/ntos/nthals/halsgi/mips/x86bios.c b/private/ntos/nthals/halsgi/mips/x86bios.c
new file mode 100644
index 000000000..d931c324e
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/x86bios.c
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halsgi/mips/xxcalstl.c b/private/ntos/nthals/halsgi/mips/xxcalstl.c
new file mode 100644
index 000000000..bdf16dd6f
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/xxcalstl.c
@@ -0,0 +1,299 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (TIME_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((TIME_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / TIME_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / TIME_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((TIME_INCREMENT / 10) - 1)) / (TIME_INCREMENT / 10);
+
+ if (PCR->StallScaleFactor <= 0) {
+ PCR->StallScaleFactor = 1;
+ }
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the clock interrupt.
+ //
+
+#if defined(JAZZ)
+
+ READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+
+#endif
+
+#if defined(SGI)
+ TC_ACK_INTERVAL();
+#endif
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halsgi/mips/xxclock.c b/private/ntos/nthals/halsgi/mips/xxclock.c
new file mode 100644
index 000000000..45ab218c3
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/xxclock.c
@@ -0,0 +1,64 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ return TIME_INCREMENT;
+}
diff --git a/private/ntos/nthals/halsgi/mips/xxidle.s b/private/ntos/nthals/halsgi/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halsgi/mips/xxinithl.c b/private/ntos/nthals/halsgi/mips/xxinithl.c
new file mode 100644
index 000000000..e7095dbb4
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/xxinithl.c
@@ -0,0 +1,237 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = TIME_INCREMENT;
+ HalpNextTimeIncrement = TIME_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(TIME_INCREMENT, TIME_INCREMENT);
+
+ //
+ // Map the fixed TB entries and initiakize the display.
+ //
+
+ HalpMapFixedTbEntries();
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ // BuildType: free - DBG=0, NT_UP=0; checked - DBG=1, NT_UP=0
+#if DBG
+
+ BuildType |= PRCB_BUILD_DEBUG;
+
+#endif
+
+#ifdef NT_UP
+
+ BuildType |= PRCB_BUILD_UNIPROCESSOR;
+
+#endif
+
+ Prcb = PCR->Prcb;
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION ||
+ Prcb->BuildType != BuildType) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Initialize interrupts
+ //
+ //
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+ HalpMapIoSpace();
+ HalpCalibrateStall();
+ HalpCreateDmaStructures();
+ return TRUE;
+ }
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halsgi/mips/xxinitnt.c b/private/ntos/nthals/halsgi/mips/xxinitnt.c
new file mode 100644
index 000000000..91b0575b8
--- /dev/null
+++ b/private/ntos/nthals/halsgi/mips/xxinitnt.c
@@ -0,0 +1,220 @@
+#if defined(JAZZ) || defined(SGI)
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#if defined(JAZZ)
+#include "jazzint.h"
+#endif
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+#if defined(R4000)
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+#endif
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+#if defined(JAZZ)
+ UCHAR DataByte;
+ USHORT DataShort;
+ ULONG DataLong;
+#endif // JAZZ
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Clear all builtin device interrupt enables.
+ //
+
+#if defined(JAZZ)
+
+ HalpBuiltinInterruptEnable = 0;
+ WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ 0);
+
+ do {
+ DataShort = READ_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Source) & 0x3ff;
+ } while (DataShort != 0);
+
+#endif
+
+#if defined (SGI)
+ DISABLE_DEVICE_IRQS();
+#endif
+
+ //
+ // Connect the clock interrupt to the stall interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Start the system clock to interrupt at TIME_INCREMENT intervals.
+ //
+ // N.B. TIME_INCREMENT is in 100ns units.
+ //
+
+#if defined(JAZZ)
+
+ WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptInterval.Long, CLOCK_INTERVAL);
+
+#endif
+
+#if defined (SGI)
+ HalpSystemInit();
+#endif
+
+ //
+ // Connect the R4000 count/compare interrupt to the early interrupt
+ // routine.
+ //
+
+#if defined(R4000)
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+#endif
+
+#if defined (SGI)
+ TC_INIT_TIMERS();
+ TC_INTERVAL_ON( TIME_INCREMENT );
+#endif
+
+ return TRUE;
+}
+
+#endif
diff --git a/private/ntos/nthals/halsgi/sources b/private/ntos/nthals/halsgi/sources
new file mode 100644
index 000000000..d91206e71
--- /dev/null
+++ b/private/ntos/nthals/halsgi/sources
@@ -0,0 +1,87 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halsgi
+TARGETPATH=\nt\public\sdk\lib
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-DSGI
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+ALPHA_SOURCES=
+
+i386_SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\s4cache.s \
+ mips\s4flshio.c \
+ mips\s4prof.c \
+ mips\sxbeep.c \
+ mips\sxdisp.c \
+ mips\sxenvirv.c \
+ mips\sxflshbf.s \
+ mips\sxhwsup.c \
+ mips\sxmapio.c \
+ mips\sxmaptb.c \
+ mips\sxport.c \
+ mips\sxreturn.c \
+ mips\sxsysint.c \
+ mips\sxtime.c \
+ mips\sxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\x4tb.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\xxinitnt.c \
+ mips\xxinithl.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halsni4x/drivesup.c b/private/ntos/nthals/halsni4x/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halsni4x/hal.rc b/private/ntos/nthals/halsni4x/hal.rc
new file mode 100644
index 000000000..73b67f096
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/hal.rc
@@ -0,0 +1,17 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "SNI RM200/RM400 Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+#if defined(SNI_INTERNAL)
+#define VER_FILEVERSION_STR "2.0 A0008"
+#include "vlbsupp.ver"
+#else
+#define VER_FILEVERSION_STR "2.0 B0008"
+#endif
+#include "common.ver"
+
+
diff --git a/private/ntos/nthals/halsni4x/hal.src b/private/ntos/nthals/halsni4x/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halsni4x/makefile b/private/ntos/nthals/halsni4x/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halsni4x/makefile.inc b/private/ntos/nthals/halsni4x/makefile.inc
new file mode 100644
index 000000000..15c0bae90
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/makefile.inc
@@ -0,0 +1,5 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halsni4x.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halsni4x/mips/allstart.c b/private/ntos/nthals/halsni4x/mips/allstart.c
new file mode 100644
index 000000000..8e4dbcc41
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/allstart.c
@@ -0,0 +1,59 @@
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+
+extern VOID HalpInit2MPAgent( );
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+ Note: this HAL is for the Siemens Nixdorf Uni-/MultiProcessor Computers
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ if ((PCR->Number == HalpNetProcessor) && (HalpProcessorId == MPAGENT)){
+ PCR->InterruptRoutine[NETMULTI_LEVEL] = (PKINTERRUPT_ROUTINE)HalpRM400Int5Process;
+ HalpInit2MPAgent( );
+ }
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halsni4x/mips/cacherr.s b/private/ntos/nthals/halsni4x/mips/cacherr.s
new file mode 100644
index 000000000..a8363b179
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/cacherr.s
@@ -0,0 +1,196 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/cacherr.s,v 1.1 1994/10/13 15:47:06 holli Exp $")
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// N.B. All the code in this routine MUST run in KSEG1 and reference
+// data only in KSEG1 until which time as any cache errors have
+// been corrected.
+//
+// N.B. This routine is NOT COMPLETE. All cache errors result in a
+// soft reset.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved integer register at - a3
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+
+ SBTTL("Cache Error Handling")
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1. If the error is a single bit ECC error in the second
+// level data cache or the error is in the primary instruction cache,
+// then the error is corrected and execution is continued. Otherwise,
+// a fatal system error has occured and control is transfered to the
+// soft reset vector.
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCacheErrorRoutine)
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw AT,0(k0) // save registers AT - a3
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+
+//
+// Get the current processor state and cache error register, and check
+// if the error can be corrected.
+//
+
+ mfc0 v0,psr // get current processor state
+ mfc0 v1,cacheerr // get cache error state
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+//
+// The following code is temporary and will be removed when full cache
+// error support is included.
+//
+// ****** temp ******
+//
+
+ b SoftReset // ****** all error soft rest
+
+//
+// If the EXL bit is set in the processor state, then the error is not
+// recoverable because the EXL bit may be erroneously set (errata) and
+// it cannot be determined whether is should or should not be set, e.g.,
+// the exact addresses ranges over which EXL might be correctly set are
+// not verifiable. Also, k0 and k1 are destroyed before they are saved
+// and are used by the exception handling code (there is no way to save
+// a register in noncached memory wihtout the use of a register).
+//
+
+ sll a0,v0,31 - PSR_EXL // shift EXL bit in sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// If the error occured on the SysAd bus, then the error is not correctable.
+//
+
+ sll a0,v1,31 - CACHEERR_EE // shift EE bit into sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// Determine whether the error is in the instruction or data cache.
+//
+
+ sll a0,v1,31 - CACHEERR_ER // shift ER bit into sign
+ bgez a0,IcacheError // if gez, instruction cache error
+
+//
+// The error occured in the data cache.
+//
+// If the error is a data error in the primary cache, then the error
+// is not correctable since the cache line dirty bit is included in
+// the parity calculation and therefore may be wrong.
+//
+
+DcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bgez a0,SoftReset // if gez, error in primary cache
+ b ExitError // exit error
+
+//
+// The error occured in the instruction cache.
+//
+// If the error occured in the secondary data cache, then the error is not
+// correctable since there is not secondary instruciton cache.
+//
+
+IcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bltz a0,SoftReset // if ltz, error in secondary cache
+
+//
+// The cache error has been corrected - restore register state and continue
+// execution.
+//
+
+ExitError: //
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw AT,0(k0) // restore registers AT - a3
+ lw v0,4(k0) //
+ lw v1,8(k0) //
+ lw a0,12(k0) //
+ lw a1,16(k0) //
+ lw a2,20(k0) //
+ eret //
+ .set at
+ .set reorder
+
+//
+// Cache error cannot be corrected - transfer control to soft reset vector.
+//
+
+SoftReset: //
+ la k0,SOFT_RESET_VECTOR // get address of soft reset vector
+ j k0 // perform a soft reset
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halsni4x/mips/deskdef.h b/private/ntos/nthals/halsni4x/mips/deskdef.h
new file mode 100644
index 000000000..54ec5c26c
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/deskdef.h
@@ -0,0 +1,93 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/deskdef.h,v 1.1 1994/10/13 15:47:06 holli Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ DESKdef.h
+
+Abstract:
+
+ This file describes hardware addresses for the new
+ SNI Desktop Model (RM200)
+ which are not common to all SNI machines.
+
+
+
+---*/
+
+#ifndef _DESKDEF_
+#define _DESKDEF_
+
+//
+// define various masks for the interrupt sources register
+//
+/*
+ The interrupt Source Register on an Desktop has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +---------------|---------------+
+ | 0 | 0 | x | 0 | 1 | 0 | 1 | 1 | 0 Low Activ; 1 High activ; x not connected
+ +---------------|---------------+
+ |________ ISA (onboard)Interrupt
+ |____________ EISA (extension board) Interrupt
+ |________________ SCSI Interrupt (SCSI Driver)
+ |____________________ Ethernet (Net driver)
+ |________________________ Push Button (HalpInt5Dispatch)
+ |____________________________ unused
+ |________________________________ TimeOut Interrupt
+ |____________________________________ Eisa extension board installed
+
+*/
+
+#define RM200_ONBOARD_MASK 0x01
+#define RM200_EISA_MASK 0x02
+#define RM200_SCSI_MASK 0x04
+#define RM200_NET_MASK 0x08
+#define RM200_PB_MASK 0x10
+#define RM200_TIMEOUT_MASK 0x20
+#define RM200_INTERRUPT_MASK 0x54
+
+#define RM200_ONBOARD_CONTROL_PHYSICAL_BASE 0x16000000
+#define RM200_ONBOARD_MEMORY_PHYSICAL_BASE 0x12000000
+#define RM200_ONBOARD_IO (RM200_ONBOARD_CONTROL_PHYSICAL_BASE | KSEG1_BASE)
+#define RM200_ONBOARD_MEMORY (RM200_ONBOARD_MEMORY_PHYSICAL_BASE | KSEG1_BASE)
+
+//
+// SNI ASIC registers
+//
+
+
+#define RM200_ONBOARD_INT_ACK_PHYSICAL_BASE 0x1a080000 // physical base of interrupt (ext. request) register
+#define RM200_ONBOARD_INT_ACK_REGISTER 0xba080000 // physical base | KSEG1_BASE
+#define RM200_EISA_INT_ACK_PHYSICAL_BASE 0x1a000000 // physical base of EISA interrupt ack for the chipset
+#define RM200_EISA_INT_ACK_REGISTER 0xba000000 // physical base | KSEG1_BASE
+#define RM200_INTERRUPT_SOURCE_PHYSICAL_BASE 0x1c000000 // physical base of interrupt source register
+#define RM200_INTERRUPT_SOURCE_REGISTER 0xbc000000 // physical base | KSEG1_BASE
+#define RM200_INTERRUPT_MASK_PHYSICAL_BASE 0x1c080000 // physical base of interrupt mask register
+#define RM200_INTERRUPT_MASK_REGISTER 0xbc080000 // physical base | KSEG1_BASE
+
+#define RM200_ONBOARD_MAP_PHYSICAL_BASE 0x1fc80000 // physical base of ISA map register (for BusMaster Devices)
+#define RM200_ONBOARD_MAP 0xbfc80000 // physical base | KSEG1_BASE
+#define RM200_EXTENSION_BOARD_MAP_PHYS_BASE 0x1fca0000 // physical base of ISA map register (for BusMaster Devices)
+#define RM200_EXTENSION_BOARD_MAP 0xbfca0000 // physical base | KSEG1_BASE
+#define RM200_VESA_MAP_PHYSICAL_BASE 0x1fcc0000 // physical base of VLB map register
+#define RM200_VESA_MAP 0xbfcc0000 // physical base | KSEG1_BASE
+#define RM200_ONBOARD_VRAM_PHYSICAL_BASE 0x1e000000 // physical base of onboard Video Ram
+#define RM200_ONBOARD_VRAM 0xbe000000 // physical base | KSEG1_BASE
+
+
+#define RM200_LED_PHYSICAL_ADDR 0x1fe00000 // LED Register physical
+#define RM200_LED_ADDR 0xbfe00000 // LED Register | KSEG1_BASE
+#define RM200_MCR_PHYSICAL_ADDR 0x1fd80000 // MachineConfigRegister
+#define RM200_MCR_ADDR 0xbfd80000 // MachineConfigRegister | KSEG1
+
+#define RM200_NVRAM_PHYSICAL_BASE 0x1cd40000 // physical base of nonvolatile RAM and RTC
+#define RM200_REAL_TIME_CLOCK_ADDRESS 0x1cd40000 // physical base of RTC
+#define RM200_REAL_TIME_CLOCK 0xbcd40000 // physical base of RTC | KSEG1_BASE
+#define RM200_RESET_DBG_BUT 0xbfe80000 // reset debugger int | KSEG1_BASE
+#define RM200_RESET_TEMPBAT_INTR 0xbfe80000 // reset Temperature/Battery int | KSEG1
+
+
+#endif // _DESKDEF_
diff --git a/private/ntos/nthals/halsni4x/mips/duocache.s b/private/ntos/nthals/halsni4x/mips/duocache.s
new file mode 100644
index 000000000..a869cdde7
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/duocache.s
@@ -0,0 +1,774 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halvlbms/src/hal/halsni4x/mips/RCS/duocache.s,v 1.1 1995/05/19 10:44:26 flo Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// duocache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// MIPS R4000 MultiProcerssor Machines. It is very special to SNI machines,
+// which use a special MP Agent Asic.
+//`
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+// NON COHERENT algorithm : to use the replace facility of the MP_Agent
+
+#define CONFIG_NONCOH(reg) \
+ .set noreorder; \
+ .set noat; \
+ mfc0 reg,config; \
+ nop; \
+ nop; \
+ and AT,reg,~(7); \
+ or AT,AT,0x3; \
+ mtc0 AT,config; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ .set at; \
+ .set reorder
+
+// restauration of CONFIG register
+
+#define CONFIG_RESTORE(reg) \
+ .set noreorder; \
+ mtc0 reg,config; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ .set reorder
+
+
+
+ LEAF_ENTRY(HalpGetTaglo)
+
+ .set noreorder
+ .set noat
+
+ cache INDEX_LOAD_TAG_SD,0(a0) // get a copy of the SLC TAG
+ mfc0 v0, taglo
+// and v0, v0, 0xffff8000 // mask address bits A18:A17
+ sll v0, v0, 4 // dismiss A35:A32
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetTaglo
+
+
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+#define ZERO_PAGE 0x0c // 0000 1100
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+ SBTTL("MpAgent Identification")
+//++
+//
+// VOID
+// HalpMpAgentIdentify()
+//
+// Routine Description:
+//
+// This function attempts to access to the MpAgent registers (base = 0x1ffff000).
+// It reads 'base' and 'base + 0x40' addresses which correspond to two different registers
+// of the MP Agent so two different contents.
+// If there is no existing MPAgent, the hardware will access in fact the old Asic
+// (base 0x1fff0000). Only 'base' to 'base+0x32' addresses are existing for this ASIC.
+// So when we will attempt to access to 'base+0x40', we will read 'base'. So we will
+// see that 'base' and 'base+0x40' have the same contents.
+// WARNING : cache error must be disabled to access to the single processor ASIC
+//
+// Arguments:
+//
+// None
+//
+// Return Value:
+//
+// TRUE : a MpAgent is detected
+// FALSE : no MpAgent
+//
+//--
+
+ LEAF_ENTRY(HalpMpAgentIdentify)
+
+ .set noreorder
+ mfc0 a0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ nop
+ move a3,a0
+ or a0,a0,0x00010000 // disable error cache to access single proc ASIC
+ mtc0 a0,psr
+ nop // fill
+ nop
+ nop
+ nop
+
+ li a0,0xbffff000 // MpAgent address
+ lw a1,0(a0) // address + 0
+ lw a2,0x40(a0) // address + 0x40
+ li v0,0x01
+ beql a2,a1,10f
+ li v0,0x00 // v0 = 0 only if a2 == a1 (branch likely)
+
+10:
+ mtc0 a3,psr // restore PSR
+ nop // fill
+ nop
+ nop
+ nop
+ .set reorder
+
+ j ra
+
+ .end HalpMpAgentIdentify
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageMulti (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFlushDcachePageMulti)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, FLUSH_DCACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+
+#endif
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the primary and secondary data caches.
+//
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not update the SC
+// TagRam copy in the MP Agent. So we do cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ or t0,t7,a0 // physical address + offset
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,MPAGENT_RESERVED | KSEG0_BASE // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+ CONFIG_RESTORE(t2)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageMulti
+
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageMulti (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeIcachePageMulti)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, PURGE_ICACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+//
+// multi-processor machine
+//
+
+40: move t7,t8
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not work. So we do cache replace.
+// We use a MP agent facility to do that : a 4Mb area is stolen to the upper EISA space
+// and this address is notified to the MP agent. When the cache replace is done, no
+// access to the memory is done : the MP agent returns zero as value for these addresses.
+// Be careful : to use this mechanism, CONFIG register must be programmed in NON COHERENT
+// mode, so we must be protected from interrupts.
+//
+
+ li t8,PAGE_SIZE
+ add t8,t8,-1 // page mask
+ and t8,t7,t8 // offset in the page
+ sll t7,a1,PAGE_SHIFT // physical address
+ or t8,t7,t8 // physical address + offset
+//
+// note: we have a Unified SLC, so SecondLevelIcacheSize is set to 0
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get cache size
+
+ addu t9,t8,a2 // compute ending physical address
+ subu t9,t9,t4 // compute ending loop address
+
+ add t0,t0,-1 // mask of the cache size
+ and t8,t8,t0 // first cache line to invalidate
+ and t9,t9,t0 // last cache line to invalidate
+
+ li a2, MPAGENT_RESERVED | KSEG0_BASE
+
+ or t8,a2,t8 // starting address
+ or t9,a2,t9 // ending address
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+50: lw zero,0(t8) // invalidate sc
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+
+ CONFIG_RESTORE(t2)
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheMulti (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheMulti)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, SWEEP_DCACHE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache in the MP Agent
+//
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not update the SC
+// TagRam copy in the MP Agent. So we do cache replace.
+//
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+
+ li a0,MPAGENT_RESERVED | KSEG0_BASE // starting address
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+
+ .set noreorder
+ .set noat
+
+25:
+ lw zero,0(a0)
+ bne a0,a1,25b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ CONFIG_RESTORE(t2)
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+
+ .end HalpSweepDcacheMulti
+
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheMulti (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheMulti)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, SWEEP_ICACHE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache
+// SNI machines have only an Unified SL cache
+// NOTE: PcSecondLevelIcacheSize and PcSecondLevelICacheFillSize is set to 0
+// on SNI machines
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,MPAGENT_RESERVED | KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+10: lw zero,0(a0)
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ CONFIG_RESTORE(t2)
+ .set noreorder
+ .set noat
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+ j ra // return
+
+ .end HalSweepIcache
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageMulti (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalpZeroPageMulti, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+#if DBG
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, ZERO_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpZeroPageMulti
+
+
diff --git a/private/ntos/nthals/halsni4x/mips/halp.h b/private/ntos/nthals/halsni4x/mips/halp.h
new file mode 100644
index 000000000..647f51316
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/halp.h
@@ -0,0 +1,161 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/halp.h,v 1.1 1995/05/19 10:44:50 flo Exp $")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "hal.h"
+#include "SNIhalp.h"
+#include "xm86.h"
+#include "x86new.h"
+
+
+//
+// Define function prototypes.
+//
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt(
+ VOID
+ );
+
+
+VOID
+HalpClockInterrupt1(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay0(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpSendIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ );
+
+VOID
+HalpProcessIpi (
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+VOID
+HalpInitMPAgent (
+ IN ULONG Number
+ );
+
+ULONG
+HalpGetMyAgent(
+ VOID
+ );
+
+BOOLEAN
+HalpCheckSpuriousInt(
+ VOID
+ );
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ );
+
+ULONG
+HalpGetTaglo(
+ IN ULONG Address
+ );
+
+//
+// Define external references.
+//
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KSPIN_LOCK HalpDmaLock;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern LONG HalpNetProcessor;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halsni4x/mips/i82c54.h b/private/ntos/nthals/halsni4x/mips/i82c54.h
new file mode 100644
index 000000000..17e77af31
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/i82c54.h
@@ -0,0 +1,34 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/i82c54.h,v 1.1 1994/10/13 15:47:06 holli Exp $")
+/*++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ i82C54.h
+
+Abstract:
+
+ This header file defines the private Address structure for
+ the Intel 82C54 Timer chip found on the SNI Minitower and RM400-10.
+
+
+--*/
+
+#ifndef _I82C54_
+#define _I82C54_
+//
+// the SNI Clock (i82C54) Structure
+//
+
+typedef struct _LOCAL_8254 {
+ UCHAR counter0; /* counter 0 port */
+ char fill_1[3];
+ UCHAR counter1; /* counter 1 port */
+ char fill_2[3];
+ UCHAR counter2; /* counter 2 port */
+ char fill_3[3];
+ UCHAR control; /* control word */
+} LOCAL_8254, *PLOCAL_8254;
+
+#endif
diff --git a/private/ntos/nthals/halsni4x/mips/j4cache.s b/private/ntos/nthals/halsni4x/mips/j4cache.s
new file mode 100644
index 000000000..dbf8b8eb5
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/j4cache.s
@@ -0,0 +1,1064 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/j4cache.s,v 1.1 1994/10/13 15:47:06 holli Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5)
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+
+#if defined(ORION)
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10:
+ cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+
+30:
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5)
+#endif
+
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+#if defined(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // do other set on Orion
+#endif
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+
+#if defined(ORION)
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0)
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+10:
+
+ cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0) // do set B first on Orion
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,ZpA1(sp) // get old color bits
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ mtc1 zero,f0 // set write pattern
+ mtc1 zero,f1 //
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+#if defined(_MULTI_)
+
+30: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,30b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+#if defined(_MULTI_)
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halsni4x/mips/j4flshbf.s b/private/ntos/nthals/halsni4x/mips/j4flshbf.s
new file mode 100644
index 000000000..2b6978d6c
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/j4flshbf.s
@@ -0,0 +1,53 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/j4flshbf.s,v 1.1 1994/10/13 15:47:06 holli Exp $")
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// j4flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+
+#endif
diff --git a/private/ntos/nthals/halsni4x/mips/j4flshio.c b/private/ntos/nthals/halsni4x/mips/j4flshio.c
new file mode 100644
index 000000000..93ae1123d
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/j4flshio.c
@@ -0,0 +1,202 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/j4flshio.c,v 1.2 1994/12/01 15:18:29 holli Exp $")
+
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halsni4x/mips/j4prof.c b/private/ntos/nthals/halsni4x/mips/j4prof.c
new file mode 100644
index 000000000..1f76f3616
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/j4prof.c
@@ -0,0 +1,325 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ *Frequency = RtlConvertUlongToLargeInteger(HalpProfileCountRate);
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ return RtlLargeIntegerAdd(PerformanceCounter,
+ RtlConvertUlongToLargeInteger(CurrentCount));
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].LowPart = 0;
+ HalpPerformanceCounter[Prcb->Number].HighPart = 0;
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue = RtlLargeIntegerAdd(TempValue,
+ RtlConvertUlongToLargeInteger(ROUND_VALUE));
+
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Reserved
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue = RtlLargeIntegerAdd(TempValue,
+ RtlConvertUlongToLargeInteger(ROUND_VALUE));
+
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Reserved
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
diff --git a/private/ntos/nthals/halsni4x/mips/jxbeep.c b/private/ntos/nthals/halsni4x/mips/jxbeep.c
new file mode 100644
index 000000000..13d80a99c
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxbeep.c
@@ -0,0 +1,132 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxbeep.c,v 1.1 1994/10/13 15:47:06 holli Exp $")
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpOnboardControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halsni4x/mips/jxebsup.c b/private/ntos/nthals/halsni4x/mips/jxebsup.c
new file mode 100644
index 000000000..48f523bb9
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxebsup.c
@@ -0,0 +1,2851 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxebsup.c,v 1.3 1995/04/07 09:56:05 flo Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the ISA/EISA bus support for SNI systems.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Declare the interrupt structure and spinlock for the intermediate EISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpEisaInterrupt;
+KINTERRUPT HalpOnboardInterrupt;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+PADAPTER_OBJECT HalpOnboardAdapter[8];
+PADAPTER_OBJECT HalpInternalAdapters[2];
+
+//
+// Define save area for EISA interrupt mask registers and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+UCHAR HalpOnboardInterrupt1Mask;
+UCHAR HalpOnboardInterrupt2Mask;
+UCHAR HalpOnboardInterrupt1Level;
+UCHAR HalpOnboardInterrupt2Level;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice,
+ IN ULONG noncachedAddress
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+
+ return(STATUS_SUCCESS);
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the device.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject, tmpAdapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+ UCHAR DataByte;
+ PEISA_CONTROL controlBase;
+
+ if (MasterAdapterObject == NULL)
+ MasterAdapterObject = HalpAllocateAdapter(
+ 10,
+ (PVOID) -1,
+ NULL
+ );
+
+ if (DeviceDescriptor->InterfaceType == Internal) {
+
+ if (DeviceDescriptor->Master) {
+
+ // The SNI machines support only Master Devices on the
+ // internal Bus; most of this stuff is the same as for EISA
+
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ }
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ NULL,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+ return(NULL);
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 5;
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters ) {
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ // calculated Count for allocation was 0 ...
+ // ScatterGather Device on internal Bus
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+ adapterObject->MasterDevice = TRUE;
+ return (adapterObject);
+
+ } // end of Master Device
+
+ } // end of Internal Interface
+
+//+++++++++++++++EISA/ISA/MCA etc ...++++++++++++++++++++++++++++++++++++
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // determine the controlBase, depending on Interface Type
+ //
+
+ //
+ // Isa and Eisa Requests have to go to the Eisa Controller on the
+ // Eisa Extension, onboard components (Floppy) have to have the InterfaceType
+ // Internal in the Device Description !!!
+ //
+
+ if(HalpEisaExtensionInstalled && (DeviceDescriptor->InterfaceType != Internal)) {
+ controlBase = (PEISA_CONTROL)HalpEisaControlBase;
+ } else
+
+
+ //
+ // If we have no Eisa Extension installed we direct all to the
+ // PC core (also if UseChannel = TRUE and InterfaceType == Internal )
+ //
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Support for ISA local bus machines:
+ // If the driver is a Master but really does not want a channel since it
+ // is using the local bus DMA, just don't use an ISA channel.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->DmaChannel > 7) {
+
+ useChannel = FALSE;
+ }
+
+ //
+ // Determine if Eisa DMA is supported.
+ //
+
+ if ((HalpBusType == MACHINE_TYPE_EISA) && (DeviceDescriptor->InterfaceType == Eisa)) {
+
+ WRITE_REGISTER_UCHAR(&(controlBase)->DmaPageHighPort.Channel2, 0x55);
+ DataByte = READ_REGISTER_UCHAR(&(controlBase)->DmaPageHighPort.Channel2);
+
+ if (DataByte == 0x55) {
+ HalpEisaDma = TRUE;
+ }
+
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!HalpEisaDma &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+ //
+ // If the device is not a master and does scatter/Gather,
+ // then it only needs one map register
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &(controlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &(controlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if(HalpEisaExtensionInstalled && (DeviceDescriptor->InterfaceType != Internal))
+ tmpAdapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+ else
+ tmpAdapterObject = HalpOnboardAdapter[DeviceDescriptor->DmaChannel];
+
+
+ if (useChannel && tmpAdapterObject != NULL) {
+
+ adapterObject = tmpAdapterObject;
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ if(HalpEisaExtensionInstalled && (DeviceDescriptor->InterfaceType != Internal))
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+ else
+ HalpOnboardAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 5;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &(controlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &(controlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (HalpEisaDma) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+ ULONG noncachedAddress;
+ ULONG partialLength;
+ ULONG temp;
+ PEISA_CONTROL controlBase;
+
+
+ if(AdapterObject !=NULL && HalpEisaExtensionInstalled && (AdapterObject->InterfaceType != Internal)) {
+ controlBase = (PEISA_CONTROL)HalpEisaControlBase;
+ } else
+
+ // for minitower or Eisa Interface Type (default case)
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous and does not cross a 64 K bountry then
+ // just extend the buffer. The 64 K bountry restriction does not apply
+ // to Eisa systems.
+ //
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ } else {
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1) ||
+ (*pageFrame & ~0x0f) != (*(pageFrame + 1) & ~0x0f)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+ }
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+ if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ temp = transferLength;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= *Length ) {
+
+ noncachedAddress = KSEG1_BASE | ((*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa));
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = *Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ noncachedAddress = KSEG1_BASE | ((*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa));
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ }
+
+ transferLength = temp;
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+ ULONG logicalAddress;
+ ULONG noncachedAddress;
+
+ ULONG PagesAbove16MB;
+ ULONG PagesBelow16MB;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ }
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ PagesBelow16MB = 0;
+ PagesAbove16MB = 0;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ PagesAbove16MB++;
+
+ }
+
+ else {
+
+ PagesBelow16MB++;
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + BYTE_OFFSET(CurrentVa);
+ noncachedAddress = KSEG1_BASE | logicalAddress;
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice,
+ noncachedAddress
+ );
+
+ PagesAbove16MB++;
+
+ }
+
+ else {
+
+ PagesBelow16MB++;
+
+ }
+ }
+
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // If this is a 16 bit dma the multiply the count by 2.
+ //
+
+ if (AdapterObject->Width16Bits) {
+
+ count *= 2;
+
+ }
+
+ return(count);
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEnableOnboardInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the ISA bus (onboard) specified ISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA(onboard) interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the ISA interrupt vector.
+ //
+
+ Vector -= ONBOARD_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpOnboardInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpOnboardInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2EdgeLevel,
+ HalpOnboardInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpOnboardInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpOnboardInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1EdgeLevel,
+ HalpOnboardInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableOnboardInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the ISA(Onboard) bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the Onboard interrupt vector.
+ //
+
+ Vector -= ONBOARD_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ IN INTERFACE_TYPE InterfaceType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Isa (Desktop onboard) or
+ EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+ PEISA_CONTROL controlBase;
+
+
+ if (HalpEisaExtensionInstalled && (InterfaceType == Eisa) ) {
+
+ controlBase = (PEISA_CONTROL)HalpEisaControlBase;
+
+#ifdef NEVER
+
+ // we call this direct from the first level dispatcher ...
+
+ //
+ // Initialize the interrupt dispatcher for the EISA Extension board on an RM200
+ // (same Interrupt routine but different Acknowledge Address, this is told
+ // to HalpEisaDispatch via the ServiceContext Parameter)
+ //
+
+ KeInitializeInterrupt( &HalpEisaInterrupt,
+ HalpEisaDispatch,
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE, // Service Context
+ (PKSPIN_LOCK)NULL,
+ EISA_VECTOR, // entry in IDT
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL, // Synchronization level
+ // EISA_DEVICE_LEVEL == SCSIEISA_LEVEL
+ // new SCSI Interrupt ???
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+
+ if (!KeConnectInterrupt( &HalpEisaInterrupt )) {
+ return(FALSE);
+ }
+#endif
+
+ } else {
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+#ifdef NEVER
+
+ // we call this direct from the first level dispatcher ...
+
+ //
+ // Initialize the interrupt dispatcher for onboard components
+ // in the PC core
+ //
+
+ KeInitializeInterrupt( &HalpOnboardInterrupt,
+ HalpEisaDispatch,
+ (PVOID)RM200_ONBOARD_CONTROL_PHYSICAL_BASE,// Service Context
+ (PKSPIN_LOCK)NULL,
+ ONBOARD_VECTOR, // entry in IDT
+ EISA_DEVICE_LEVEL,
+ EISA_DEVICE_LEVEL, // Synchronization level
+ // EISA_DEVICE_LEVEL == SCSIEISA_LEVEL
+ // new SCSI Interrupt ???
+ LevelSensitive,
+ TRUE,
+ 0,
+ FALSE
+ );
+
+
+ if (!KeConnectInterrupt( &HalpOnboardInterrupt )) {
+ return(FALSE);
+ }
+#endif
+
+ }
+
+ //
+ // Raise the IRQL while the interrupt controller is initialized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the Isa/EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0x00;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ if (HalpEisaExtensionInstalled && (InterfaceType == Eisa)) {
+
+ //
+ // this is for the EISA Extension board
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ } else {
+
+ //
+ // this is for the onboard components
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpOnboardInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ HalpOnboardInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpOnboardInterrupt1Level = 0;
+ HalpOnboardInterrupt2Level = 0;
+
+ } // closing if statement
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_LEVEL, EISA_LEVEL, EISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ USHORT PCRInOffset;
+ PUCHAR InterruptAckAddr;
+ BOOLEAN returnValue;
+ PEISA_CONTROL controlBase;
+
+
+
+ if(HalpEisaExtensionInstalled && ((ULONG)ServiceContext == EISA_CONTROL_PHYSICAL_BASE)){
+
+ //
+ // this is when the Eisa Extension is installed
+ //
+
+ controlBase = (PEISA_CONTROL)HalpEisaControlBase;
+ InterruptAckAddr = (HalpIsRM200) ?
+ (PUCHAR)RM200_EISA_INT_ACK_REGISTER:
+ (PUCHAR)RM400_EISA_INT_ACK_REGISTER;
+ PCRInOffset = EISA_VECTORS;
+
+ } else {
+
+ PCRInOffset = ONBOARD_VECTORS;
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+ InterruptAckAddr = (HalpIsRM200) ?
+ (PUCHAR)RM200_ONBOARD_INT_ACK_REGISTER:
+ (PUCHAR)RM400_ONBOARD_INT_ACK_REGISTER;
+
+ }
+
+ //
+ // start an 80x86 Interrupt Ack cycle by the SNI Hardware and reset the
+ // bit in the chipset
+ //
+
+ interruptVector =READ_REGISTER_UCHAR(InterruptAckAddr);
+
+ PCRInOffset += (USHORT) (interruptVector & ~0x80);
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ if (interruptVector & 0x08) {
+
+ //
+ // The interrupt was on controler 2
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ //
+ // The interrupt was on controler 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+}
+
+#ifdef NEVER
+
+BOOLEAN
+HalpEisaDispatch_OK(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+ This service routine should be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpEisaDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, EISA_LEVEL, EISA_LEVEL, EISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ UCHAR IntRequest;
+ ULONG i;
+ USHORT PCRInOffset, Offset;
+ BOOLEAN returnValue;
+ PEISA_CONTROL controlBase;
+
+
+
+ if(HalpEisaExtensionInstalled && ((ULONG)ServiceContext == EISA_CONTROL_PHYSICAL_BASE)){
+
+ //
+ // this was an interrupt in the Eisa backplane
+ //
+
+ controlBase = (PEISA_CONTROL)HalpEisaControlBase;
+ PCRInOffset = EISA_VECTORS;
+ Offset = EISA_VECTORS;
+
+ } else {
+
+ //
+ // this is the default case
+ // the interrupts occur on the onboard PC core
+ //
+
+ PCRInOffset = ONBOARD_VECTORS;
+ Offset = ONBOARD_VECTORS;
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ }
+
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset += (USHORT)interruptVector;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ } else {
+
+ //
+ // This interrupt is on the second interrupt controller
+ //
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ PCRInOffset += (USHORT)(interruptVector + 8);
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ }
+ }
+ }
+}
+#endif
diff --git a/private/ntos/nthals/halsni4x/mips/jxenvirv.c b/private/ntos/nthals/halsni4x/mips/jxenvirv.c
new file mode 100644
index 000000000..15a057425
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxenvirv.c
@@ -0,0 +1,192 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxenvirv.c,v 1.1 1994/10/13 15:47:06 holli Exp $")
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Siemens Nixdorf Informationssyteme AG
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Environment:
+
+ Kernel mode
+
+NOTES:
+ --- Preliminary using ARC function calls ---
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+#include "arc.h"
+
+ // preliminary calls to the ARC functions (function vector call)
+
+ /* NOTE:
+ This is strongly discouraged by the ARC specifications.
+ Only "reset"/return calls to the prom are recommended.
+ All other system access to the NVRAM should be handled
+ by operating systems functions directly. For that the
+ operating system has to know the algorithms for handling
+ those data structures (e.g. the checksum calculations).
+ Though is a drawback in terms of HW/FW-independance NT
+ seems to avoid side effects of ARC function code that way,
+ e.g. via register/stack manipulations.
+ */
+
+//
+// The following addresses are defined by ARC and handed over to the osloader.
+// For now we assume that the osloader will leave this memory part unchanged
+// for the operating system (NT), which itself also doesn't overwrite that
+// data structure.
+// We don't (yet) know yet know whether the firmware copies or maps/banks
+// runnable code into the physical memory (or if it just sets up a vector
+// into the prom). We also do not know whether the NVRAM variables are copied
+// into physical memory or mapped/banked by the (ARC) firmware.
+//
+
+//
+// Therefore we preliminary use the ARC entry vectors from ARC.H
+//
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+NOTE:
+ This implementation returns the error code ENOMEM if the output buffer
+ is too small.
+
+--*/
+
+{
+
+ PUCHAR Environment_var;
+ ULONG Index;
+ ARC_STATUS Status;
+
+ //
+ // retrieve the variable
+ //
+
+ Environment_var = (PUCHAR)ArcGetEnvironmentVariable(Variable);
+
+ if (Environment_var == (PUCHAR)NULL) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(Environment_var);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ Environment_var += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+NOTES:
+ This preliminary implementation always returns ESUCCESS even in case of
+ error.
+
+--*/
+
+{
+
+ ARC_STATUS Status;
+
+ Status = ArcSetEnvironmentVariable(Variable, Value);
+
+ switch (Status) {
+
+ case ESUCCESS:
+ break;
+
+ case ENOSPC:
+ break; // until further we assume NT can handle that
+
+ case ENOMEM:
+ default:
+ Status = ENOMEM;
+ break;
+ }
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halsni4x/mips/jxhwsup.c b/private/ntos/nthals/halsni4x/mips/jxhwsup.c
new file mode 100644
index 000000000..07f6d5bc2
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxhwsup.c
@@ -0,0 +1,2437 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/jxhwsup.c,v 1.1 1995/05/19 11:19:03 flo Exp $")
+/*++
+
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+
+Environment:
+
+ Kernel mode
+
++++*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+extern VOID NtClose();
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+
+//
+// Map buffer parameters. These are initialized in HalInitSystem
+//
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the additional pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocation amount so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+ return(FALSE);
+
+ }
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocating a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disable. Importent for DMA if we
+ // have more than 16Mb memory in our SNI
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initialize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry and that a 64K physical boundary is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!HalpEisaDma &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this boundary.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ physically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1 &&
+ MapRegistersPerChannel) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( ((MAXIMUM_MAP_BUFFER_SIZE*9)/8) / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *IoAdapterObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoAdapterObjectType,
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ NtClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+
+
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+
+
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+
+ return AdapterObject;
+
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice,
+ IN ULONG noncachedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, (PCCHAR)noncachedAddress, Length);
+
+ } else {
+
+ RtlMoveMemory( (PCCHAR)noncachedAddress, mapAddress, Length);
+
+
+ }
+
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+PTRANSLATION_ENTRY
+HalpAcquireMapBuffers(
+ ULONG NumberOfMapRegisters,
+ PADAPTER_OBJECT MasterAdapter)
+{
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+ PTRANSLATION_ENTRY MapRegisterBase;
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber > MasterAdapter->NumberOfMapRegisters) {
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ if (MapRegisterNumber > MasterAdapter->NumberOfMapRegisters)
+ MapRegisterNumber = (ULONG)-1;
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+// InsertTailList( &MasterAdapter->AdapterQueue,
+// &AdapterObject->AdapterQueue
+// );
+// Busy = 1;
+
+ MapRegisterBase = NULL;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ return(MapRegisterBase);
+}
+
+
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+ PTRANSLATION_ENTRY MapRegisterTranslation;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+
+ } else {
+ MapRegisterTranslation = HalpAcquireMapBuffers(numberOfMapRegisters,MasterAdapterObject);
+ if (MapRegisterTranslation == NULL) return(NULL);
+ virtualAddress = MapRegisterTranslation->VirtualAddress;
+ LogicalAddress->LowPart = MapRegisterTranslation->PhysicalAddress;
+ LogicalAddress->HighPart = 0;
+ KeStallExecutionProcessor(50000);
+ return(virtualAddress);
+ }
+
+
+ if (virtualAddress == NULL) {
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) {
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ // for some reason, we have to pause if we have the onboard scsi controller AND
+ // an Adaptec AHA1740 Eisa SCSI controller ...
+ // trial and error ...
+ //
+
+ KeStallExecutionProcessor(50000);
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase,resultat;
+ ULONG numberOfMapRegisters;
+ ULONG i;
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) {
+
+ ExFreePool(VirtualAddress);
+
+ } else {
+
+// MmFreeNonCachedMemory(VirtualAddress, Length);
+// if(AdapterObject->NeedsMapRegisters == FALSE) return;
+// }
+
+ }
+
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ // mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase;
+ resultat = NULL;
+
+ for (i = 0; i < MasterAdapterObject->NumberOfMapRegisters; i++) {
+
+ if (mapRegisterBase->VirtualAddress == VirtualAddress) {
+ resultat = mapRegisterBase;
+ break;
+ }
+
+ mapRegisterBase++;
+
+ }
+
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) resultat,
+ numberOfMapRegisters
+ );
+
+ return;
+}
+#ifdef NEVER
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(CacheEnabled);
+
+ // Because we support ISA devices, and they cannot reference
+ // past 16MB of memory, we must make sure that the contiguous
+ // memory we allocate is below 16Mb.
+
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS -1;
+ physicalAddress.HighPart = 0;
+
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ DbgPrint("MmAllocateContiguousMemory returns 0x%x ... \n", virtualAddress);
+
+ if (!HALP_IS_PHYSICAL_ADDRESS(virtualAddress)) {
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ } else {
+
+ *LogicalAddress = RtlConvertUlongToLargeInteger(
+ (ULONG)virtualAddress &
+ (~KSEG0_BASE)
+ );
+
+ }
+ return((PVOID)((ULONG)virtualAddress | KSEG1_BASE));
+}
+
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(Length);
+ UNREFERENCED_PARAMETER(LogicalAddress);
+ UNREFERENCED_PARAMETER(VirtualAddress);
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(Length);
+ UNREFERENCED_PARAMETER(LogicalAddress);
+ UNREFERENCED_PARAMETER(CacheEnabled);
+
+ MmFreeContiguousMemory((PVOID)(((ULONG)VirtualAddress & (~KSEG1_BASE)) | KSEG0_BASE));
+
+
+}
+
+#endif
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0);
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG)AdapterObject->MapRegisterBase |NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if
+ // there are no requests in the master adapter queue, then
+ // IoFreeMapRegisters will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+
+ //
+ // SNI only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+
+ UNREFERENCED_PARAMETER( BusNumber );
+
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // There is no difference between IoSpace and MemorySpace in the internal Interface.
+ // Mips Processors have only memory mapped I/O
+ //
+
+ *AddressSpace = 0;
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ return(TRUE);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ DebugPrint(("HAL: HalTranslateBusAddress: WRONG INTERFACE (%d) ", InterfaceType));
+
+ //
+ // Not on this system -- return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ // we always direct Isa and Eisa Adresses to the extension board
+ //
+
+ *AddressSpace = 0;
+
+ TranslatedAddress->LowPart = BusAddress.LowPart +
+ EISA_CONTROL_PHYSICAL_BASE;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ // we always direct Isa and Eisa Adresses to the extension board
+ //
+
+ *AddressSpace = 0;
+
+ TranslatedAddress->LowPart = BusAddress.LowPart +
+ EISA_MEMORY_PHYSICAL_BASE;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+
+ return(TRUE);
+
+ }
+
+ DebugPrint(("HAL: HalTranslateBusAddress: Beeing in the very bad tree\n"));
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+ return(FALSE);
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+// IN OUT PVOID Argument0
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
diff --git a/private/ntos/nthals/halsni4x/mips/jxmapio.c b/private/ntos/nthals/halsni4x/mips/jxmapio.c
new file mode 100644
index 000000000..482a287f3
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxmapio.c
@@ -0,0 +1,133 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxmapio.c,v 1.1 1994/10/13 15:47:06 holli Exp $")
+
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 - 1994 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a SNI
+ or R4x00 system.
+ For use of EISA I/O Space during phase 0 we go via KSEG1_BASE
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase =(PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+PVOID HalpOnboardControlBase=(PVOID) (RM200_ONBOARD_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+PVOID HalpEisaMemoryBase =(PVOID) (EISA_MEMORY_PHYSICAL_BASE | KSEG1_BASE);
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R4x00 SNI
+ system (Phase 1, so the mapping goes via MmMapIoSpace()).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ // (64KB I/O Space)
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // for the sni deskop model, may need an extra address space
+ // HalpEisaExtensionInstalled can only be TRUE on RM200 (Desktop)
+ //
+
+ if (HalpEisaExtensionInstalled) {
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = RM200_ONBOARD_CONTROL_PHYSICAL_BASE;
+ HalpOnboardControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ } else
+
+ //
+ // In the SNI Minitower model, we have only one
+ // address space
+ //
+
+ HalpOnboardControlBase = HalpEisaControlBase;
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA/Isa slot.
+ // (first 1MB only to have access to Card Bioses)
+ // We do not have to call HalTranslateBusAddress on our SNI machines,
+ // because we always use EISA_MEMORY_PHYSICAL_BASE for Extension Cards
+ // on all machines
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_MEMORY_PHYSICAL_BASE;
+ HalpEisaMemoryBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase == NULL) ||
+ (HalpOnboardControlBase == NULL) ||
+ (HalpEisaMemoryBase == NULL)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halsni4x/mips/jxport.c b/private/ntos/nthals/halsni4x/mips/jxport.c
new file mode 100644
index 000000000..11b17a6d6
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxport.c
@@ -0,0 +1,805 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxport.c,v 1.2 1995/02/13 12:49:39 flo Exp $")
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R4000 system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+// set the correct divisor for the SNI serial ports / quartz clock
+#if defined(SNI)
+ #undef BAUD_RATE_9600
+ #undef BAUD_RATE_19200
+ #define BAUD_RATE_9600 12
+ #define BAUD_RATE_19200 6
+#endif // SNI
+
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#if defined(USE_COM2)
+
+// Assume COM2 for the kernel debugger.
+
+#define SP_READ ((PSP_READ_REGISTERS) ((ULONG)HalpOnboardControlBase + SERIAL1_RELATIVE_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((ULONG)HalpOnboardControlBase + SERIAL1_RELATIVE_BASE))
+
+
+#else
+
+// Assume COM1 for the kernel debugger.
+
+#define SP_READ ((PSP_READ_REGISTERS) ((ULONG)HalpOnboardControlBase + SERIAL0_RELATIVE_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((ULONG)HalpOnboardControlBase + SERIAL0_RELATIVE_BASE))
+
+#endif
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = BAUD_RATE_19200;
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+//
+// BUGBUG the FW configuration sets the serial 0 Port config relativ to
+// the EISA/ISA Base Address, so the serial driver doesn't get the right
+// information when debugging is enabled ....
+//
+
+#if defined(USE_COM2)
+ KdComPortInUse=(PUCHAR)(SERIAL1_PHYSICAL_BASE);
+#else
+ KdComPortInUse=(PUCHAR)(SERIAL0_PHYSICAL_BASE);
+#endif
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halsni4x/mips/jxreturn.c b/private/ntos/nthals/halsni4x/mips/jxreturn.c
new file mode 100644
index 000000000..7999a2690
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxreturn.c
@@ -0,0 +1,239 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxreturn.c,v 1.3 1995/02/13 12:49:56 flo Exp $")
+
+/*++
+
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "SNIregs.h"
+#include "mpagent.h"
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ );
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ UCHAR DataByte;
+ PUCHAR MachineControlRegister = (HalpIsRM200) ?
+ (PUCHAR) RM200_MCR_ADDR :
+ (PUCHAR) RM400_MCR_ADDR;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+ for (;;) {}
+
+ case HalPowerDownRoutine:
+
+ //
+ // PowerOff is done by the SNI machines by writing the Power_Off bit to the machine control register ...
+ //
+
+ WRITE_REGISTER_UCHAR(MachineControlRegister, MCR_POWER_OFF);
+ for (;;) {} // hang looping
+
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+
+ if (HalpIsMulti) {
+ ULONG Mask;
+
+ Mask = HalpActiveProcessors & ~(PCR->SetMember);
+#if DBG
+ DbgPrint("Send message RESTART to maskcpu = %x \n",Mask);
+#endif
+
+ HalpSendIpi(Mask,MPA_RESTART_MESSAGE);
+ //
+ // if this is not the Boot CPU, we call a special Firmware entry to stop it
+ //
+
+ if (PCR->Number ) {
+ //
+ // remove this processor from the list of active processors
+ //
+ HalpActiveProcessors &= (~(PCR->SetMember));
+
+ HalSweepDcache(); // this should run only local ...
+#if DBG
+ DbgPrint(" Reinit slave %x \n", ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave);
+#endif
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
+
+ } else HalpBootCpuRestart();
+ }
+
+
+ DataByte = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(10000);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ if (HalpIsRM200) {
+
+ //
+ // Reset the SNI RM200 machines by writing the reset bit to the machine control register ...
+ // ArcReboot does not work correctly on the RM200 (Reset of the Isa Bus)
+ //
+
+ WRITE_REGISTER_UCHAR(MachineControlRegister, (MCR_INRESET | MCR_PODD));
+
+ } else {
+
+ ArcReboot();
+ }
+
+ for (;;) ;
+
+ default:
+ DbgPrint("HalReturnToFirmware invalid argument\n");
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the firmware Arcreboot routine.
+ it waits until all other cpu's have beet shut down.
+ this code is executed only on the boot cpu
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Does not return.
+
+--*/
+{
+ UCHAR DataByte;
+ ULONG cpt;
+
+ cpt = 0;
+ while(HalpActiveProcessors != PCR->SetMember) {
+ KeStallExecutionProcessor(500000);
+ ++cpt;if (cpt == 20) break;
+ }
+ //
+ // if there are still ssome processors active, we do a reset of the entire machine
+ //
+ if (HalpActiveProcessors != PCR->SetMember) {
+
+#if DBG
+ DbgPrint(" Some processors did not answer (%x). Reset machine started. \n", HalpActiveProcessors);
+#endif
+ WRITE_REGISTER_UCHAR((PUCHAR) RM400_MCR_ADDR, (MCR_INRESET | MCR_PODD));
+
+ } else {
+
+#if DBG
+ DbgPrint("Reboot started \n");
+#endif
+
+ }
+
+ DataByte = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(10000);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+
+ ArcReboot();
+
+ for (;;) ;
+}
+
+
+
+
+
diff --git a/private/ntos/nthals/halsni4x/mips/jxsysint.c b/private/ntos/nthals/halsni4x/mips/jxsysint.c
new file mode 100644
index 000000000..ee70178da
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxsysint.c
@@ -0,0 +1,380 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/jxsysint.c,v 1.1 1995/05/19 11:20:52 flo Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the onboard interrupts, then
+ // disable the onboard interrrupt.
+ // This may be an Isa (Desktop) or Isa/Eisa (Minitower) Interrupt
+ //
+
+ if (Vector >= ONBOARD_VECTORS &&
+ Vector <= MAXIMUM_ONBOARD_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableOnboardInterrupt(Vector);
+ }
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt on the Eisa Backplane (Eisa Extension).
+ //
+
+ else if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the onboard interrupts, then
+ // enable the onboard interrrupt and set the Level/Edge register to latched,
+ // because the onboard Opti 499 (Desktop)is a real Isa Controler and cannot share interrupts.
+ // even the i82350 Chipset on the Minitower cannot share interrupts (why ?)
+ //
+
+ if (Vector >= ONBOARD_VECTORS &&
+ Vector <= MAXIMUM_ONBOARD_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+
+ if (HalpIsRM200)
+ //
+ // the RM200 has an Opti 499 Chip, which is an "real" Isa Chipset
+ // so we cannot support Level sensitive Interrupts ...
+ //
+
+ HalpEnableOnboardInterrupt( Vector, Latched);
+ else
+ HalpEnableOnboardInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt in the Eisa Backplane (Eisa Extension) and set the Level/Edge register.
+ //
+
+ else if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+
+
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+
+ *Affinity = 1;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ if (BusInterruptVector >= ONBOARD_VECTORS &&
+ BusInterruptVector <= MAXIMUM_ONBOARD_VECTOR ) {
+
+ //
+ // this is one of the onboard components of the PC core
+ // (floppy, serial, parallel, mouse etc.)
+ // they should be configured in the Firmware tree with an Offset of
+ // ONBOARD_VECTORS (e.g. 0x10 to make them different to the real onboard components
+ // like scsi or ethernet) and with an Irql of EISA_DEVICE_LEVEL (actually 4)
+ // we need Firmware release 1.04 or later ...
+ //
+
+ //
+ // Bus interrupt vector 2 of Onboard PC core interrupts is actually mapped to
+ // vector 9 in the Isa/Eisa hardware.
+ //
+
+ if (BusInterruptVector == ONBOARD_VECTORS + 2) {
+ BusInterruptVector = ONBOARD_VECTORS + 9;
+ }
+
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ return(BusInterruptVector);
+ }
+
+ //
+ // these are the "real" Onboard components (scsi and Ethernet)
+ // Return the passed parameters.
+ //
+
+ *Irql = (KIRQL) BusInterruptLevel;
+
+ //
+ // this is the special case of the onboard Ethernet Controller
+ // At CPU Modules with an R4400 PC this goes directly to corresponding
+ // Cause Register Bit IP7 (bad bad ..)
+ // on MUltiPro machines this IP7 is used for IPI Interrupts so we have to
+ // manipulate this.
+ //
+
+ if (BusInterruptVector == NET_DEFAULT_VECTOR){
+
+ extern BOOLEAN HalpProcPc;
+ //
+ // the RM200 and all SC machines have a central Device Interrupt
+ // which is software managed by this HAL ...
+ // leave al other cases as they are ...
+ //
+
+ if ( ((HalpProcPc == FALSE) && (HalpProcessorId != ORIONSC)) || (HalpMainBoard==M8036)) {
+
+ if (HalpProcessorId == MPAGENT) {
+
+ BusInterruptVector = NET_LEVEL;
+ *Irql = (KIRQL) NETMULTI_LEVEL;
+ *Affinity = 1 << HalpNetProcessor; // proc 1 if started
+
+ } else {
+
+ BusInterruptVector = NET_LEVEL;
+
+ //
+ // Irql is equal to the most common Device Interrupt Level
+ // (currently 4)
+ //
+
+ *Irql = (KIRQL) SCSIEISA_LEVEL;
+ }
+
+ }
+
+ return ( BusInterruptVector);
+ }
+
+ //
+ // this is another special case of the EIP Interrupt for RM400 Tower
+ // we have an agreement with the EIP developer
+ // we meet each other on InterruptVector 15, so we limit the Irql to Device Level
+ //
+
+ if ( (HalpMainBoard==M8032) && (BusInterruptVector == EIP_VECTOR) ){
+
+ //
+ // Irql is equal to the most common Device Interrupt Level
+ // (currently 4)
+ //
+
+ if (HalpProcessorId == MPAGENT) *Irql = (KIRQL) INT3_LEVEL; else *Irql = (KIRQL) SCSIEISA_LEVEL;
+
+ }
+
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+ }
+
+ //
+ // Isa/Eisa Interrupts which are not configured in the Firmware
+ // (boards should be located in the Expansion Slots ...)
+ // The IRQL level is always equal to the EISA level.
+ // WARNING: some driver call HalGetInterruptVector
+ // with the BusInterruptLevel == BusInterruptVector
+ // but some call it with different values.
+ // In this part of the source tree we match the Jazz reference
+ // sources (see Internal handling; which is different)
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt 2 is actually mapped to bus interrupt 9 in the Isa/Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the ONBOARD/EISA_VECTORS.
+ // in any case the interrupt vector for Isa or Eisa card has to be on the
+ // Backplane, so if an Eisa Extension is installed this is an Eisa Interrupt
+ //
+
+ if (HalpEisaExtensionInstalled ) {
+ return( BusInterruptLevel + EISA_VECTORS);
+ } else
+
+ //
+ // if there is no Eisa Extension installed
+ // all Isa/Eisa Interrupts should be handled by the onboard PC core
+ //
+
+ return(BusInterruptLevel + ONBOARD_VECTORS);
+
+}
diff --git a/private/ntos/nthals/halsni4x/mips/jxtime.c b/private/ntos/nthals/halsni4x/mips/jxtime.c
new file mode 100644
index 000000000..0e156e5c8
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxtime.c
@@ -0,0 +1,334 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxtime.c,v 1.1 1994/10/13 15:47:06 holli Exp $")
+
+/*++
+
+Copyright (c) 1993 SNI
+
+Module Name:
+
+ SNItime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R4000 SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+
+#define NVINDEX_STATE 0x6
+#define NVSTATE_TODVALID 0x1
+
+
+
+#define bcd_to_dec(x) ( ((((x) >> 4 ) & 0xf ) * 10 ) + ((x) & 0xf) )
+#define dec_to_bcd(x) ( (((x) / 10) << 4) | ((x) % 10) )
+
+
+#define RTC_NVRAM_SIZE 0x7ff // NVRAM size on this chip
+
+
+typedef struct _RealTimeClock {
+ struct rtc_mem {
+ UCHAR value;
+ UCHAR FILL0[3]; // byte-wide device
+ } Memory[RTC_NVRAM_SIZE]; // Non-volatile ram
+ UCHAR ControlRegister; // control register
+ UCHAR FILL1[3];
+} RealTimeClock, *PRealTimeClock;
+
+
+
+/* Smartwatch offset registers */
+
+#define REG_CENT_SECS 0
+#define REG_SECS 1
+#define REG_MINS 2
+#define REG_HOURS 3
+#define REG_DAY_W 4
+#define REG_DAY_M 5
+#define REG_MONTH 6
+#define REG_YEAR 7
+
+/* masks to get valid information */
+
+#define MASK_CENT_SECS 0xFF
+#define MASK_SECS 0x7F
+#define MASK_MINS 0x7F
+#define MASK_HOURS 0x3F
+#define MASK_DAY_W 0x07
+#define MASK_DAY_M 0x3F
+#define MASK_MONTH 0x1F
+#define MASK_YEAR 0xFF
+
+//
+// the reference year (we have only two digits for the year on the chip)
+//
+
+#define YRREF 1900
+
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ );
+
+VOID
+HalpWriteClockRegister(
+ IN UCHAR number
+ );
+
+UCHAR
+HalpReadClockRegister(
+ VOID
+ );
+
+VOID
+HalpWritePattern(
+ VOID
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. this comment stand in jxtime.c:
+ This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ register CSHORT month, dayweek, daymonth, year, hours, mins, secs, msecs;
+ int i;
+ UCHAR tmp[8];
+ KIRQL oldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+
+ // write the pattern to gain access to the smartwatch registers
+
+
+ HalpWritePattern();
+
+ // Read the 8 registers of smartwatch
+
+ for (i = 0; i < 8; i++)
+ tmp[i] = HalpReadClockRegister();
+
+ KeLowerIrql(oldIrql);
+
+ // Convert the contents of smartwatch registers into CSHORT
+
+
+ msecs = ( (CSHORT) bcd_to_dec(tmp[REG_CENT_SECS] & MASK_CENT_SECS) ) * 10;
+ secs = (CSHORT) bcd_to_dec(tmp[REG_SECS] & MASK_SECS);
+ mins = (CSHORT) bcd_to_dec(tmp[REG_MINS] & MASK_MINS);
+ hours = (CSHORT) bcd_to_dec(tmp[REG_HOURS] & MASK_HOURS);
+ daymonth = (CSHORT) bcd_to_dec(tmp[REG_DAY_M] & MASK_DAY_M);
+ dayweek = (CSHORT) bcd_to_dec(tmp[REG_DAY_W] & MASK_DAY_W);
+ month = (CSHORT) bcd_to_dec(tmp[REG_MONTH] & MASK_MONTH);
+ year = (CSHORT) bcd_to_dec(tmp[REG_YEAR] & MASK_YEAR);
+
+
+ if (TimeFields)
+ {
+ TimeFields->Year = year+YRREF;
+ TimeFields->Month = month;
+ TimeFields->Day = daymonth;
+ TimeFields->Weekday = dayweek;
+ TimeFields->Hour = hours;
+ TimeFields->Minute = mins;
+ TimeFields->Second = secs;
+ TimeFields->Milliseconds = msecs;
+ }
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. this comment stand in jxtime.c:
+ This routine is required to provide anq synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ UCHAR tmp[8];
+ KIRQL oldIrql;
+ UCHAR year, month, daymonth, dayweek, hours, mins, secs, msecs;
+ int i;
+
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ // this part has to be written
+ // if (...) return FALSE;
+ year = (UCHAR) ( (TimeFields->Year - YRREF) % 100 );
+ month = (UCHAR) TimeFields->Month;
+ daymonth = (UCHAR) TimeFields->Day;
+ dayweek = (UCHAR) TimeFields->Weekday;
+ hours = (UCHAR) TimeFields->Hour;
+ mins = (UCHAR) TimeFields->Minute;
+ secs = (UCHAR) TimeFields->Second;
+ msecs = (UCHAR) TimeFields->Milliseconds;
+
+
+ tmp[REG_CENT_SECS] = (UCHAR) (dec_to_bcd(msecs/10) & MASK_CENT_SECS);
+ tmp[REG_SECS] = (UCHAR) (dec_to_bcd(secs) & MASK_SECS);
+ tmp[REG_MINS] = (UCHAR) (dec_to_bcd(mins) & MASK_MINS);
+ tmp[REG_HOURS] = (UCHAR) (dec_to_bcd(hours) & MASK_HOURS);
+ tmp[REG_DAY_W] = (UCHAR) (dec_to_bcd(dayweek) & MASK_DAY_W);
+ tmp[REG_DAY_M] = (UCHAR) (dec_to_bcd(daymonth) & MASK_DAY_M);
+ tmp[REG_MONTH] = (UCHAR) (dec_to_bcd(month) & MASK_MONTH);
+ tmp[REG_YEAR] = (UCHAR) (dec_to_bcd(year) & MASK_YEAR);
+
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+
+ // write the pattern to gain access to the smartwatch registers
+
+ HalpWritePattern();
+
+ // Write the 8 registers of smartwatch
+
+ for (i=0; i <8; i++)
+ HalpWriteClockRegister(tmp[i]);
+
+ KeLowerIrql(oldIrql);
+
+ return TRUE;
+
+}
+
+//
+// Write a BCD 2-digits number in the smartwatch
+// This is done one bit at a time, LSB first
+//
+
+VOID
+HalpWriteClockRegister(
+ IN UCHAR number
+ )
+{
+ PRealTimeClock rtc;
+ UCHAR i;
+
+ rtc = (HalpIsRM200) ? (PRealTimeClock )(RM200_REAL_TIME_CLOCK):
+ (PRealTimeClock )(RM400_REAL_TIME_CLOCK);
+
+ for (i = 1; i <= 8; i++) {
+ WRITE_REGISTER_UCHAR(&rtc->ControlRegister, number);
+ number = number >> 1; // next bit to write
+ }
+
+}
+
+//
+// Read a BCD 2-digits number in the smartwatch
+// This is done one bit at a time, LSB first
+//
+
+UCHAR
+HalpReadClockRegister(
+ VOID
+ )
+{
+ PRealTimeClock rtc;
+ UCHAR i;
+ UCHAR number;
+
+ rtc = (HalpIsRM200) ? (PRealTimeClock )(RM200_REAL_TIME_CLOCK):
+ (PRealTimeClock )(RM400_REAL_TIME_CLOCK);
+
+ for (i = 0, number = 0; i < 8; i++) {
+ number += (READ_REGISTER_UCHAR(&rtc->ControlRegister) & 0x01) << i; // Read a bit and shift it
+ }
+
+ return(number);
+}
+
+//
+// Write a pattern to gain access to the smartwatch registers
+// First we do 9 read's to reset the pointer
+//
+
+VOID
+HalpWritePattern(
+ VOID
+ )
+{
+
+ // Pattern to use before reading or writing
+
+ static UCHAR ClockPattern[4] = {0xc5,0x3a,0xa3,0x5c};
+
+ register UCHAR *pt;
+ register UCHAR i;
+
+ for (i = 0; i <= 8; i++) (VOID) HalpReadClockRegister();
+ for (i = 0, pt = ClockPattern; i < sizeof(ClockPattern); i++) HalpWriteClockRegister(*pt++);
+ for (i = 0, pt = ClockPattern; i < sizeof(ClockPattern); i++) HalpWriteClockRegister(*pt++);
+
+}
+
+
diff --git a/private/ntos/nthals/halsni4x/mips/jxusage.c b/private/ntos/nthals/halsni4x/mips/jxusage.c
new file mode 100644
index 000000000..cde6fd09e
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/jxusage.c
@@ -0,0 +1,47 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxusage.c,v 1.1 1994/10/13 15:47:06 holli Exp $")
+
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/halsni4x/mips/minidef.h b/private/ntos/nthals/halsni4x/mips/minidef.h
new file mode 100644
index 000000000..0e9e98eb7
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/minidef.h
@@ -0,0 +1,141 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/minidef.h,v 1.2 1994/11/09 07:54:26 holli Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ MINIdef.h
+
+Abstract:
+
+ This file describes hardware addresses
+ for SNI Minitower and RM400-Tower which are not common
+ to all SNI machines.
+
+
+
+---*/
+
+#ifndef _MINIDEF_
+#define _MINIDEF_
+
+//
+// define various masks for the interrupt sources register
+//
+
+/*
+ The interrupt Source Register on an MiniTower has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | 1 | 0 | 1 | 0 | 0 | x | 0 | 0 | 0 Low Activ; 1 High activ; x not connected
+ +-------------------------------+
+ |________ EISA/ ISA Interrupt (HalpEisaDispatch)
+ |____________ SCSI Interrupt (SCSI Driver)
+ |________________ EIP Interrupt (RM400 Tower Only/ Unused on Minitower)
+ |____________________ Timer 0 (HalpClockInterrupt1 on MULTI)
+ |________________________ Timer 1 (unused)
+ |____________________________ Ethernet (Net driver)
+ |________________________________ Push Button/Timeouts (HalpInt0Dispatch or HalpInt1Dispatch)
+ |____________________________________ Irq 9 (unused)
+
+ The second source for Interrupt Information is the MachineStatusRegister, which has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | x | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 Low Activ; 1 High activ; x not connected
+ +-------------------------------+
+ |________ ColdStart (unused)
+ |____________ OverTemperature Int. (dismiss only / unused on Tower)
+ |________________ EIP Interrupt (RM400 Tower Only/ unused on Minitower)
+ |____________________ Timer 1 (unused)
+ |________________________ Timer 0 (HalpClockInterrupt1 on MULTI)
+ |____________________________ PushButton (HalpInt0Dispatch or HalpInt1Dispatch)
+ |________________________________ Timeouts (HalpInt0Dispatch or HalpInt1Dispatch)
+ |____________________________________ not connected (unused)
+*/
+
+#define RM400_EISA_MASK 0x01 // these are the interrupts from the Eisa PC core
+#define RM400_SCSI_MASK 0x02
+#define RM400_SCSI_EISA_MASK 0x03
+#define RM400_NET_MASK 0x20
+#define RM400_PB_MASK 0x40
+#define RM400_MSR_TEMP_MASK 0x02 // OverTemperature Interrupt in the MSR (RM400MT only) (high active)
+#define RM400_MSR_EIP_MASK 0x04 // EIP Interrupt in the MSR (RM400 Tower only) (low active)
+#define RM400_MSR_TIMER0_MASK 0x10 // Timer 0 Interrupt in the MachineStatusRegister (low active)
+#define RM400_MSR_TIMER1_MASK 0x08 // Timer 1 Interrupt in the MachineStatusRegister (low active)
+#define RM400_MSR_PB_MASK 0x20 // PushButton is also reported in the MachineStatusRegister (low actice)
+#define RM400_MSR_TIMEOUT_MASK 0x40 // Timeout's are indicated in the MachineStatusRegister (low active)
+#define RM400_INTERRUPT_MASK 0x5f
+#define RM400_MSR_MASK 0xfc // 11111100 -> xor gives High active bits
+
+#define RM400_TOWER_EISA_MASK 0x01
+#define RM400_TOWER_SCSI_MASK 0x02
+#define RM400_TOWER_SCSI_EISA_MASK 0x03
+#define RM400_TOWER_EIP_MASK 0x04 // this is the famous EIP Interrupt ... (tower only)
+#define RM400_TOWER_NET_MASK 0x20
+#define RM400_TOWER_PB_MASK 0x40
+#define RM400_TOWER_TIMEOUT_MASK 0x40
+#define RM400_TOWER_INTERRUPT_MASK 0x5f
+
+#define RM400_ONBOARD_CONTROL_PHYSICAL_BASE EISA_CONTROL_PHYSICAL_BASE
+#define RM400_ONBOARD_MEMORY_PHYSICAL_BASE EISA_MEMORY_PHYSICAL_BASE
+#define RM400_ONBOARD_IO (ONBOARD_CONTROL_PHYSICAL_BASE | KSEG1_BASE)
+#define RM400_ONBOARD_MEMORY (ONBOARD_MEMORY_PHYSICAL_BASE | KSEG1_BASE)
+
+//
+// SNI ASIC registers
+//
+
+#define RM400_INTERRUPT_ACK_PHYSICAL_BASE 0x1c000000 // physical base of interrupt (ext. request) register
+#define RM400_INTERRUPT_ACK_REGISTER 0xbc000000 // physical base | KSEG1_BASE
+#define RM400_EISA_INT_ACK_PHYSICAL_BASE 0x1a000000 // physical base of EISA interrupt ack for the chipset
+#define RM400_EISA_INT_ACK_REGISTER 0xba000000 // physical base | KSEG1_BASE
+#define RM400_ONBOARD_INT_ACK_PHYSICAL_BASE RM400_EISA_INT_ACK_PHYSICAL_BASE // physical base of EISA interrupt ack for the chipset
+#define RM400_ONBOARD_INT_ACK_REGISTER RM400_EISA_INT_ACK_REGISTER // physical base | KSEG1_BASE
+#define RM400_INTERRUPT_SOURCE_PHYSICAL_BASE 0x1c020000 // physical base of interrupt source register
+#define RM400_INTERRUPT_SOURCE_REGISTER 0xbc020000 // physical base | KSEG1_BASE
+#define RM400_VESA_MAP_PHYSICAL_BASE 0x1c010000 // physical base of VLB map register
+#define RM400_VESA_MAP 0xbc010000 // physical base | KSEG1_BASE
+#define RM400_ISA_MAP_PHYSICAL_BASE 0x1c0e0000 // physical base of ISA map register (for BusMaster Devices)
+#define RM400_ISA_MAP 0xbc0e0000 // physical base | KSEG1_BASE
+
+#define RM400_LED_PHYSICAL_ADDR 0x1c090000 // LED Register physical
+#define RM400_LED_ADDR 0xbc090000 // LED Register | KSEG1_BASE
+#define RM400_MCR_PHYSICAL_ADDR 0x1c0b0000 // MachineConfigRegister
+#define RM400_MCR_ADDR 0xbc0b0000 // MachineConfigRegister | KSEG1
+#define RM400_MSR_PHYSICAL_ADDR 0x1c0a0000 // machine status register
+#define RM400_MSR_ADDR 0xbc0a0000 // machine status register | KSEG1
+
+//
+// System Timer (i82C54) and RealTimeClock Chip on RM400-10 and Minitower
+//
+
+#define RM400_TIMER0_MASK 0x10
+#define RM400_TIMER1_MASK 0x08
+#define RM400_TIMER_MASK 0x18 // Timer0 and Timer1
+#define RM400_EXTRA_TIMER_PHYSICAL_ADDR 0x1c040000 // physical base of Timer for system Clock
+#define RM400_EXTRA_TIMER_ADDR 0xbc040000 // Timer for system Clock |KSEG1_BASE
+#define RM400_TIMER0_ACK_ADDR 0xbc050000 // reset Timer0 Interrupt |KSEG1_BASE
+#define RM400_TIMER1_ACK_ADDR 0xbc060000 // reset Timer1 Interrupt |KSEG1_BASE
+
+#define RM400_NVRAM_PHYSICAL_BASE 0x1c080000 // physical base of nonvolatile RAM and RTC
+#define RM400_REAL_TIME_CLOCK_ADDRESS 0x1c080000 // physical base of RTC
+#define RM400_REAL_TIME_CLOCK 0xbc080000 // physical base of RTC | KSEG1_BASE
+#define RM400_RESET_DBG_BUT 0xbc0f0000 // reset debugger int | KSEG1_BASE
+#define RM400_RESET_TEMPBAT_INTR 0xbc0f0000 // reset Temperature/Battery int | KSEG1
+
+//
+// RM400 Tower (M8032)
+// specific Addresses
+//
+
+#define RM400_TOWER_INTERRUPT_SOURCE_PHYSICAL_BASE 0x1c010000 // physical base of interrupt source register
+#define RM400_TOWER_INTERRUPT_SOURCE_REGISTER 0xbc010000 // physical base | KSEG1_BASE
+#define RM400_TOWER_VESA0_MAP_PHYSICAL_BASE 0x1c0c0000 // physical base of Vesa Slot 0 map register
+#define RM400_TOWER_VESA0_MAP 0xbc0c0000 // physical base | KSEG1_BASE
+#define RM400_TOWER_VESA1_MAP_PHYSICAL_BASE 0x1c0d0000 // physical base of Vesa Slot 1 map register
+#define RM400_TOWER_VESA1_MAP 0xbc0d0000 // physical base | KSEG1_BASE
+
+#endif // _MINIDEF_
diff --git a/private/ntos/nthals/halsni4x/mips/mpagent.c b/private/ntos/nthals/halsni4x/mips/mpagent.c
new file mode 100644
index 000000000..7ea99caa1
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/mpagent.c
@@ -0,0 +1,681 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/mpagent.c,v 1.1 1995/05/19 11:22:19 flo Exp $")
+
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ mpagent.c
+
+Abstract:
+
+ This module implements the routines dealing with the SNI MP Agent on
+ SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "MPagent.h"
+
+typedef struct _mp_agent{
+
+ /* Register Register
+ * name number offset description
+ * ---------- ---- ------ --------------------------------- */
+ ULONG cpureg; /* 0x00 0x000 configuration cpu register */
+ ULONG invalid_0;
+ ULONG cpuda1reg; /* 0x01 0x008 general register */
+ ULONG invalid_1;
+ ULONG msgdata; /* 0x02 0x010 data for message passing */
+ ULONG invalid_2;
+ ULONG msgstatus; /* 0x03 0x018 message status */
+ ULONG invalid_3;
+ ULONG snooper; /* 0x04 0x020 snooper configuration register */
+ ULONG invalid_4;
+ ULONG tagreg; /* 0x05 0x028 tag ram R/W index register */
+ ULONG invalid_5;
+ ULONG snpadreg; /* 0x06 0x030 adress of first MBus fatal error */
+ ULONG invalid_6;
+ ULONG itpend; /* 0x07 0x038 Interrupt register */
+ ULONG invalid_7;
+ ULONG datamsg1; /* 0x08 0x040 data message register 1 */
+ ULONG invalid_8;
+ ULONG datamsg2; /* 0x09 0x048 data message register 2 */
+ ULONG invalid_9;
+ ULONG datamsg3; /* 0x0a 0x050 data message register 3 */
+ ULONG invalid_a;
+ ULONG lppreg0; /* 0x0b 0x058 LPP register cpu 0 */
+ ULONG invalid_b;
+ ULONG lppreg1; /* 0x0c 0x060 LPP register cpu 1 */
+ ULONG invalid_c;
+ ULONG lppreg2; /* 0x0d 0x068 LPP register cpu 2 */
+ ULONG invalid_d;
+ ULONG lppreg3; /* 0x0e 0x070 LPP register cpu 3 */
+ ULONG invalid_e;
+ ULONG tagram; /* 0x0f 0x078 tag ram R/W register */
+ ULONG invalid_f;
+ ULONG crefcpt; /* 0x10 0x080 cpu general read counter register */
+ ULONG invalid_10;
+ ULONG ctarcpt; /* 0x11 0x088 cpu programmable access counter */
+ ULONG invalid_11;
+ ULONG srefcpt; /* 0x12 0x090 snooper general read counter reg. */
+ ULONG invalid_12;
+ ULONG starcpt; /* 0x13 0x098 snooper programmable accesscounter*/
+ ULONG invalid_13;
+ ULONG linkreg; /* 0x14 0x0a0 link register */
+ ULONG invalid_14;
+ ULONG software1; /* 0x15 0x0a8 software register1 */
+ ULONG invalid_15;
+ ULONG msgaddress; /* 0x16 0x0b0 address message register */
+ ULONG invalid_16;
+ ULONG mem_operator; /* 0x17 0x0b8 operator internal burst register */
+ ULONG invalid_17;
+ ULONG software2; /* 0x18 0x0c0 software register2 */
+}MP_AGENT, *PMP_AGENT;
+
+#define mpagent ((volatile PMP_AGENT) MPA_BASE_ADDRESS) // mpagent address
+
+
+VOID
+HalpInitMPAgent(
+ IN ULONG Number
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the MutiProcessor_Agent chipset:
+ - reset an eventual MP_Agent fatal error,
+ - enable message passing (send/receive),
+ - fix routage for internal IT -> external IT,
+ - enable the internal interrupts,
+ - fix the mask for wanted external interrupts,
+ - disable Low Process Priority mode for
+ external interrupts,
+ - enable cache replace operator and update the
+ 'cache_rpl_buffer' global variable with a KSEG0
+ 4 Mb reserved address.
+
+Arguments:
+
+ Number : Logical number of the processor to be initialised
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ULONG reg;
+
+#if DBG
+ PCR->HalReserved[0] =0;
+#endif
+
+ //
+ // set up the snooper register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
+ reg |= (MPA_ENRCVMESS | /* enable message receiving */
+ MPA_RSTSNPERR | /* reset an eventual old MP_Agent fatal error */
+ MPA_ENLINK | /* enable read and link command */
+ MPA_ENCOHREQ | /* enable coherency on the MP bus for this agent */
+ 0); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
+
+ reg &= ~(MPA_RSTSNPERR); /* enable new interrupt for MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
+
+
+ //
+ // cpu1reg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpuda1reg)); /* read the current value */
+ reg &= ~(MPA_ENDIRECT | /* disable LPP mechanism */
+ MPA_ENTESTIT | /* disable interrupt test mode (interrupts from MPBus) */
+ MPA_SELITI_MASK | /* reset old internal interrupt routage */
+ 0); /* keep other fields */
+
+ reg |= MPA_SELITI_SR_IP5; /* send internal interrupts on external interrupt SR_IP5*/
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpuda1reg), reg);
+
+ //
+ // cpureg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ reg &= ~(MPA_ENINT_MASK | /* reset old values for interrupts */
+ MPA_INTCONF_MASK| /* force falling edge for all interrupts */
+ MPA_ENSHARED | /* don't put optimal mode for KERNEL */
+ 0); /* keep other fields */
+ reg |= (MPA_ENSENDMSG | /* enable sending message */
+ MPA_ENINT_MPBERR | /* enable internal interrupt for MP_Agent fatal error */
+ MPA_ENINT_ITMSG1 | /* enable internal interrupt for message1 register */
+ MPA_ENINT_ITMSG2 | /* enable internal interrupt for message2 register */
+ MPA_ENINT_ITMSG3 | /* enable internal interrupt for message3 register */
+ MPA_INTMSK | /* mask sent during external request stage */
+ 0); /* keep other fields */
+
+ //
+ // external Interrupts routing in the MP Agent
+ //
+
+ if (Number == 0) {
+
+ //
+ // For this release, the device interrupts are only processed by bootcpu.
+ //
+
+ reg |= (MPA_ENINT_SR_IP3
+ | MPA_ENINT_SR_IP4
+ | MPA_ENINT_SR_IP5
+// | MPA_ENINT_SR_IP6
+// | MPA_ENINT_SR_IP7
+ );
+
+ } else {
+
+ //
+ // place something special to non boot cpu here ...
+ //
+
+ reg |= (MPA_ENINT_SR_IP6 // Enable Extra Clock Interrupts (IP6)
+// | MPA_ENINT_SR_IP7
+ );
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
+
+ //
+ // clear pending interrupts by reading of the message registers
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg1));
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg2));
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg3));
+
+ reg = ((MPAGENT_RESERVED & // put the reserved physical address (4Mb long)
+ MPA_OP_ADDR_MASK) |
+ MPA_OP_ENABLE); // enable the operator
+
+ WRITE_REGISTER_ULONG(&(mpagent->mem_operator), reg);
+
+}
+
+
+VOID
+HalpInit2MPAgent(
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the MutiProcessor_Agent chipset:
+ - enable net interrupt on the current processor
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ULONG reg;
+
+ //
+ // cpureg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+
+ reg |= MPA_ENINT_SR_IP7;
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
+}
+
+
+VOID
+HalRequestIpi(
+ IN ULONG CpuMask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ULONG physmask, cpt;
+PRESTART_BLOCK NextRestartBlock;
+
+ // CpuMask is a logical mask. We must use a mask with the physical
+ // numbers of cpus to communicate with the MP_Agent.
+
+ physmask = 0;cpt = 0;
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ while (NextRestartBlock != NULL) {
+
+ if (CpuMask & ( 1 << cpt))
+ physmask |= (1 << (NextRestartBlock->ProcessorId));
+
+ ++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+ HalpSendIpi(physmask,MPA_KERNEL_MESSAGE);
+
+}
+
+
+VOID
+HalpSendIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ )
+/*++
+
+Routine Description:
+
+ This routine sends an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ pcpumask - Supplies the set of processors that are sent an interprocessor
+ interrupt. It contains physical numbers.
+
+ msg_data _ Supplies the kind of message to be send : kernel demand or HAL internal demand.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+KIRQL OldIrql;
+LONG msg_retries, watchdog;
+ULONG msg_address, msg_status;
+
+ if (!pcpumask || !HalpIsMulti) {
+
+ return;
+
+ }
+
+ //
+ // Raise IRQL to ??? level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // form the Message Address register (Message register 1 / 2, CPUMask)
+ // The SNI MP Agent supports up to 4 CPU's
+ //
+
+ msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG1;
+
+ msg_data = ((msg_data << 24) | (pcpumask & MPA_CPUTARGET_MASK));
+
+ msg_retries = MPA_MSG_RETRY;
+
+ /*
+ * Go on, just do it.
+ * If at first you don't succeed, then try, try and try again...
+ */
+
+ do {
+
+ watchdog = 10;
+
+ WRITE_REGISTER_ULONG(&(mpagent->msgaddress), msg_address);
+ WRITE_REGISTER_ULONG(&(mpagent->msgdata), msg_data);
+
+ /*
+ * so, what happened? poll either until we know or the watchdog counter runs out
+ */
+ do {
+
+ KeStallExecutionProcessor(5);
+
+ //
+ // read the message status register
+ //
+ msg_status = READ_REGISTER_ULONG(&(mpagent->msgstatus));
+
+
+ } while (((msg_status & MPA_VALSTAT) == 0) && watchdog--);
+
+ if ((msg_status & MPA_VALSTAT) != MPA_VALSTAT) {
+
+#if DBG
+ DbgPrint("HAL: Watchdog Overrun !\n");
+#endif
+ KeStallExecutionProcessor(100);
+ continue;
+
+ } else {
+
+ //
+ // okay, we have a Valid status bit
+ // so test of busy
+
+ if ((msg_status & MPA_ERRMSG) == 0) {
+
+ //
+ // all is fine
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+ } else {
+
+#if DBGG
+ DbgPrint("HAL: Could not deliver IPI (busy)!\n");
+#endif
+ msg_retries = MPA_MSG_RETRY;
+ KeStallExecutionProcessor(100);
+ continue;
+ }
+
+ }
+
+
+ KeStallExecutionProcessor(10);
+
+ } while (--msg_retries); /* message aborted, try again */
+
+ KeLowerIrql(OldIrql);
+
+#if DBG
+ DbgPrint("HAL: WARNING - Could not deliver IPI (0x%x) MPA->status: 0x%2x! \n", msg_data, msg_status);
+ DbgPrint("HAL: pending Interupts: 0x%8x\n", READ_REGISTER_ULONG(&(mpagent->itpend)));
+#endif
+
+ return;
+
+}
+
+
+VOID
+HalpProcessIpi(
+ IN struct _KTRAP_FRAME *TrapFrame
+ )
+/*++
+
+ Routine Description:
+
+ This routine is entered as the result of an IP5 interrupt. This function
+ will looks at the MPagent to see if an IPI has just occurred.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+
+--*/
+{
+ ULONG itpend, msg_data;
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
+
+
+ if (itpend & MPA_INTN_ITMSG1) {
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ //
+
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg1)) >> 24);
+ HalpCheckSpuriousInt();
+
+ if (msg_data == MPA_KERNEL_MESSAGE) {
+ KeIpiInterrupt(TrapFrame);
+ return;
+ }
+
+ if (msg_data == MPA_RESTART_MESSAGE) {
+
+ if (PCR->Number) {
+
+#if DBGG
+ DbgPrint("Got shutdown message ...\n");
+#endif
+
+ // remove this processor from the list of active processors
+ HalpActiveProcessors &= (~(PCR->SetMember));
+
+ HalSweepDcache(); // flush the value above for the other processors
+
+ // call a firmware funtion to stop slave cpu's which will break the caches
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
+
+ } else {
+
+ HalpBootCpuRestart();
+ }
+
+ }
+
+#if DBGG
+ DbgPrint("HAL: Warning: unknown IPI Interrupt Message in Register 1\n");
+#endif
+
+ }
+
+ if ((itpend & MPA_INTN_INT_MASK) == 0) {
+
+ ULONG snooper = READ_REGISTER_ULONG(&(mpagent->snooper));
+
+ //
+ // None of the MP Agent internal Interrupts was pending --> just return
+ //
+
+ HalpCheckSpuriousInt();
+#if DBGG
+ DbgPrint("HAL: Got unexpected Interrupt in the MP Agent - \nnothing is pending [0x%08x] snooper 0x%08x cause: 0x%08x status: 0x%08xspurious = %d \n",
+ itpend, snooper, HalpGetCauseRegister(), HalpGetStatusRegister(),HalpCheckSpuriousInt());
+#endif
+
+ return;
+ }
+
+ if (itpend & MPA_INTN_MPBERR) {
+
+ //
+ // Fatal Error
+ //
+
+ ULONG snooper, cpureg ;
+
+#if DBGG
+ ULONG snpadreg, data, data2 ;
+ DbgPrint("HAL: FATAL - Fatal Error Interrupt in the MP Agent !!! \n");
+#endif
+
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
+ ); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+ snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
+
+#if DBGG
+ snpadreg = READ_REGISTER_ULONG(&(mpagent->snpadreg));
+ WRITE_REGISTER_ULONG( &(mpagent->tagreg),snpadreg);
+ data = READ_REGISTER_ULONG(&(mpagent->tagram));
+ data2 = HalpGetTaglo( data | KSEG0_BASE);
+ DbgPrint("snooper %08x Bad Address was: 0x%08x \nData in the Tag Copy is: 0x%08x\nData in the TagLo is: 0x%08x \n",snooper, snpadreg, data, data2);
+#endif
+
+ snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+ snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+
+ HalpCheckSpuriousInt();
+ return;
+ }
+
+ if (itpend & MPA_INTN_ITMSG2) {
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ // we use message register 2 for the restart message
+ //
+
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg2)) >> 24);
+ HalpCheckSpuriousInt();
+
+#if DBGG
+ DbgPrint("HAL: Warning: IPI Interrupt Message in Register 2\n");
+#endif
+
+ return;
+ }
+
+ if (itpend & MPA_INTN_ITMSG3) {
+
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ //
+
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg3)) >> 24);
+ HalpCheckSpuriousInt();
+
+#if DBGG
+ DbgPrint("HAL: Warning: IPI Interrupt Message in Register 3\n");
+#endif
+
+ return;
+ }
+
+}
+
+ULONG
+HalpGetMyAgent(
+ VOID
+ )
+{
+ ULONG reg;
+ reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
+ return( (reg & MPA_ADAGT_MASK) >> MPA_ADAGT_SHIFT);
+}
+
+
+
+/*
+ * ======================================================================
+ *
+ * NAME: mpa_check_spurious_intr
+ *
+ * PURPOSE: Fix a bug in the MP_Agent which sometimes make a bad
+ * update of the cause register.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: = 0 no possible spurious interrupt
+ * 1 possible spurious interrupt
+ *
+ * ======================================================================
+ */
+BOOLEAN HalpCheckSpuriousInt(VOID)
+{
+
+ULONG itpend, causeit, pending;
+ULONG cpureg, tempreg;
+
+ if ( HalpProcessorId != MPAGENT) {
+ return 0;
+ }
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* read the interrupt pending MP_Agent register */
+
+ causeit = (itpend & MPA_OINTN_MASKGEN) >> MPA_OINTN_SHIFT;
+ pending = (itpend & MPA_INTN_MASKGEN );
+
+ if (causeit != pending) {
+
+ /*
+ * Need a second filter for pending interrupt which don't take care
+ * of real enabled interrupt mask of cpureg.
+ */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read interrupt enable mask for this cpu */
+
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP3 |
+ MPA_ENINT_SR_IP4 |
+ MPA_ENINT_SR_IP5 |
+ MPA_ENINT_SR_IP6 |
+ MPA_ENINT_SR_IP7)) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ if (causeit != pending) {
+
+ /*
+ * There is sometimes an MP_Agent interrupt with values different in
+ * MPA_INTN_... = 0 and MPA_OINTN_....
+ * That means : The cause register has been updated with a wrong value!
+ * We need to force a new update of the cause register to avoid looping
+ * on this interrupt until a new external interrupt happens.
+ */
+
+ if (cpureg & MPA_INTCONF_SR_IP8) {
+ tempreg = (cpureg & (~MPA_INTCONF_SR_IP8)) | MPA_ENINT_SR_IP8;
+ } else {
+ tempreg = (cpureg | MPA_INTCONF_SR_IP8 | MPA_ENINT_SR_IP8);
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), tempreg); // write the new value in the MP_Agent register /
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // Restore initial value
+#if DBG
+ ++PCR->HalReserved[0] ;
+#endif
+ return 1; /* Possible spurious ! */
+ }
+ }
+
+ return 0; /* No possible spurious ! */
+
+}
diff --git a/private/ntos/nthals/halsni4x/mips/mpagent.h b/private/ntos/nthals/halsni4x/mips/mpagent.h
new file mode 100644
index 000000000..bb3d3447a
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/mpagent.h
@@ -0,0 +1,535 @@
+//
+// Defines for Access to the MP Agent
+// this file can be used on assembly language files and C Files
+//
+
+#ifndef _MPAGENT_H_
+#define _MPAGENT_H_
+
+
+#define MPA_BASE_ADDRESS 0xbffff000 /* Base to address the MP_Agent */
+#define MPA_BOOT_MESSAGE 6 /* to start the other processors */
+#define MPA_KERNEL_MESSAGE 10 /* kernel requested IPI */
+#define MPA_TIMER_MESSAGE 11 /* timer interrupt */
+#define MPA_RESTART_MESSAGE 12 /* restart requested */
+
+//
+// define relative offsets of the MP Agent registers
+// (little endian mode)
+//
+
+#define MPA_cpureg 0x000 // (0x00 * 8) configuration cpu register
+#define MPA_cpuda1reg 0x008 // (0x01 * 8) general register
+#define MPA_msgdata 0x010 // (0x02 * 8) data for message passing
+#define MPA_msgstatus 0x018 // (0x03 * 8) message status
+#define MPA_snooper 0x020 // (0x04 * 8) snooper configuration register
+#define MPA_tagreg 0x028 // (0x05 * 8) tag ram R/W index register
+#define MPA_snpadreg 0x030 // (0x06 * 8) adress of first MBus fatal error
+#define MPA_itpend 0x038 // (0x07 * 8) Interrupt register
+#define MPA_datamsg1 0x040 // (0x08 * 8) data message register 1
+#define MPA_datamsg2 0x048 // (0x09 * 8) data message register 2
+#define MPA_datamsg3 0x050 // (0x0a * 8) data message register 3
+#define MPA_lppreg0 0x058 // (0x0b * 8) LPP register cpu 0
+#define MPA_lppreg1 0x060 // (0x0c * 8) LPP register cpu 1
+#define MPA_lppreg2 0x068 // (0x0d * 8) LPP register cpu 2
+#define MPA_lppreg3 0x070 // (0x0e * 8) LPP register cpu 3
+#define MPA_tagram 0x078 // (0x0f * 8) tag ram R/W register
+#define MPA_crefcpt 0x080 // (0x10 * 8) cpu general read counter register
+#define MPA_ctarcpt 0x088 // (0x11 * 8) cpu programmable access counter
+#define MPA_srefcpt 0x090 // (0x12 * 8) snooper general read counter reg.
+#define MPA_starcpt 0x098 // (0x13 * 8) snooper programmable accesscounter
+#define MPA_linkreg 0x0a0 // (0x14 * 8) link register
+#define MPA_software1 0x0a8 // (0x15 * 8) software register1
+#define MPA_msgaddress 0x0b0 // (0x16 * 8) address message register
+#define MPA_mem_operator 0x0b8 // (0x17 * 8) operator internal burst register
+#define MPA_software2 0x0c0 // (0x18 * 8) software register2
+
+
+/* +---------------------------+ */
+/* ! cpureg register (0x00) ! */
+/* +---------------------------+ */
+/*
+
+ The CPUREG Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | ED| ED| ED| | MI| MI| MI| EI| EI| EI| EI| EI| EI| R | 1 | 0 | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |__________ enable shared 1-> TagCopy for S
+ |_____________ enable message sending
+ |_________________ reserved
+ |_____________________ enable external Interrupts
+ |________________________ enable external Interrupts
+ |____________________________ enable external Interrupts
+ |________________________________ enable external Interrupts
+ |____________________________________ enable external Interrupts
+
+ |__________________________________________ enable external Interrupts
+ |______________________________________________ enable Message Reg. Int.
+ |__________________________________________________ enable Message Reg. Int.
+ |______________________________________________________ enable Message Reg. Int.
+ |__________________________________________________________
+ |______________________________________________________________ Edge Config for Interrupts
+ |__________________________________________________________________ Edge Config for Interrupts
+ |______________________________________________________________________ Edge Config for Interrupts
+
+
+ The CPUREG Register (HIGH-PART), which has the following bits:
+
+
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | 1 | 1 | 1 | 1 | 1 | MA| MA| MA| MA| MA| MA| MA| ED| ED| ED| ED| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Edge Config for Interrupts
+ |_____________ Edge Config for Interrupts
+ |________________ Edge Config for Interrupts
+ |____________________ Edge Config for Interrupts
+ |________________________ Interrupt Mask on external Request
+ |____________________________ Interrupt Mask on external Request
+ |________________________________ Interrupt Mask on external Request
+ |____________________________________ Interrupt Mask on external Request
+
+ |__________________________________________ Interrupt Mask on external Request
+ |______________________________________________ Interrupt Mask on external Request
+ |__________________________________________________ Interrupt Mask on external Request
+ |______________________________________________________ maximal Retry Count on MP-Bus
+ |__________________________________________________________ maximal Retry Count on MP-Bus
+ |______________________________________________________________ maximal Retry Count on MP-Bus
+ |__________________________________________________________________ maximal Retry Count on MP-Bus
+ |______________________________________________________________________ maximal Retry Count on MP-Bus
+
+*/
+
+#define MPA_ENSHARED 0x00000001 /* (0) If the MP_Agent has not the data in
+ * exclusif state, the MP_Agent forces
+ * the data to shared state for all
+ * coherent access.
+ *
+ * (1) If no other MP_agent has the data
+ * in exclusif state, the requester
+ * can put the data in share or exclusif
+ * state.
+ */
+
+#define MPA_ENSENDMSG 0x00000002 /* (1) 0 -> disable message passing
+ * 1 -> enable message passing
+ */
+
+#define MPA_ENINT_MASK 0x00001ffc /* (12:2) enable interrupt mask */
+#define MPA_ENINT_MASKSHIFT 3 /* shift for enable interrupt mask */
+#define MPA_ENINT_SR_IP3 0x00000008 /* (3) enable external interrupt SR_IP3 */
+#define MPA_ENINT_SR_IP4 0x00000010 /* (4) enable external interrupt SR_IP4 */
+#define MPA_ENINT_SR_IP5 0x00000020 /* (5) enable external interrupt SR_IP5 */
+#define MPA_ENINT_SR_IP6 0x00000040 /* (6) enable external interrupt SR_IP6 */
+#define MPA_ENINT_SR_IP7 0x00000080 /* (7) enable external interrupt SR_IP7 */
+#define MPA_ENINT_SR_IP8 0x00000100 /* (8) enable external interrupt SR_IP8 */
+#define MPA_ENINT_ITMSG1 0x00000200 /* (9) enable interrupt message1 register */
+#define MPA_ENINT_ITMSG2 0x00000400 /* (10) enable interrupt message2 register */
+#define MPA_ENINT_ITMSG3 0x00000800 /* (11) enable interrupt message3 register */
+#define MPA_ENINT_MPBERR 0x00001000 /* (12) enable interrupt MP_Agent fatal error */
+
+#define MPA_INTCONF_MASK 0x000fe000 /* (19:13) select interrupt level
+ * 0 -> falling
+ * 1 -> raising */
+#define MPA_INTCONF_SR_IP3 0x00002000 /* (13) select raising mode for SR_IP3 */
+#define MPA_INTCONF_SR_IP4 0x00004000 /* (14) select raising mode for SR_IP4 */
+#define MPA_INTCONF_SR_IP5 0x00008000 /* (15) select raising mode for SR_IP5 */
+#define MPA_INTCONF_SR_IP6 0x00010000 /* (16) select raising mode for SR_IP6 */
+#define MPA_INTCONF_SR_IP7 0x00020000 /* (17) select raising mode for SR_IP7 */
+#define MPA_INTCONF_SR_IP8 0x00040000 /* (18) select raising mode for SR_IP8 */
+#define MPA_INTCONF_SR_NMI 0x00080000 /* (19) select raising mode for SR_NMI */
+
+#define MPA_INTMSK 0x07f00000 /* (26:20) mask sent during external request stage */
+
+#define MPA_MAXRTY_MASK 0xf8000000 /* (31:27) mask for maximum number of retry on
+ * INV / UPD / MESS / RD_COH */
+
+/* +---------------------------+ */
+/* ! cpuda1reg register (0x01) ! */
+/* +---------------------------+ */
+/*
+ The CPU1REG Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | SS| SS| TI| 1 | DP| DP| R | R | R | R | R | R | R | R | R | R | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ reserved
+ |_____________ reserved
+ |________________ reserved
+ |____________________ reserved
+ |________________________ reserved
+ |____________________________ reserved
+ |________________________________ reserved
+ |____________________________________ reserved
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ CPU Data Pattern
+ |______________________________________________________ CPU Data Pattern
+ |__________________________________________________________ Int. Update Policy 0 - direct
+ |______________________________________________________________ Test Interrupts
+ |__________________________________________________________________ Cpu Port Statistics
+ |______________________________________________________________________ Cpu Port Statistics
+
+
+ The CPU1REG Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | R | R | R | R | R | R | R | R | R | R | R | IS| IS| IS| 1 | SS| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Cpu Port Statistics
+ |_____________ Enable Read Anticipate mode
+ |________________ Select Interrupt for Internal Ints
+ |____________________ Select Interrupt for Internal Ints
+ |________________________ Select Interrupt for Internal Ints
+ |____________________________ reserved
+ |________________________________ reserved
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ reserved
+
+*/
+
+#define MPA_CPURDPAT_MASK 0x00000c00 /* (11:10) number of wait-state between 2 double
+ * cpu reads. */
+#define MPA_CPURDPAT_DD 0x00000000 /* 0 : dd */
+#define MPA_CPURDPAT_DDX 0x00000400 /* 1 : dd. */
+#define MPA_CPURDPAT_DDXX 0x00000800 /* 2 : dd.. */
+#define MPA_CPURDPAT_DXDX 0x00000c00 /* 3 : d.d. */
+
+#define MPA_ENDIRECT 0x00001000 /* (12) 0 send interrupt to all MP_Agent
+ * 1 use LPP mechanism to dispatch interrupt
+ */
+
+#define MPA_ENTESTIT 0x00002000 /* (13) 0 disable test mode (interrupts from MPBus)
+ * 1 enable test mode (interrupts from INTCONF(6:0))
+ */
+
+#define MPA_CPUSELSTAT_MASK 0x0001c000 /* (16:14) select programmable mode for cpu
+ * access
+ */
+
+#define MPA_ENRDANT 0x00020000 /* (17) 0 disable overlapping memory/MP_Agent
+ *
+ * 1 enable overlapping memory/MP_Agent
+ * The Tag copy checking is done concurently
+ * with memory access. The memory must support
+ * the 'read abort' command (not supported
+ * by current Asic chipset rev.0).
+ */
+
+#define MPA_SELITI_MASK 0x001c0000 /* (20:18) define routage for internal interrupts */
+#define MPA_SELITI_SR_IP3 0x00000000 /* Internal interrupts go on SR_IP3 */
+#define MPA_SELITI_SR_IP4 0x00040000 /* Internal interrupts go on SR_IP4 */
+#define MPA_SELITI_SR_IP5 0x00080000 /* Internal interrupts go on SR_IP5 */
+#define MPA_SELITI_SR_IP6 0x000c0000 /* Internal interrupts go on SR_IP6 */
+#define MPA_SELITI_SR_IP7 0x00100000 /* Internal interrupts go on SR_IP7 */
+#define MPA_SELITI_SR_IP8 0x00140000 /* Internal interrupts go on SR_IP8 */
+
+/* +---------------------------+ */
+/* ! msgstatus register (0x03) ! */
+/* +---------------------------+ */
+
+/* message passing status register */
+
+#define MPA_VALSTAT 0x00000001 /* (0) 0 -> status is invalid
+ * 1 -> status is valid */
+//
+// if (MPA_VALSTAT != 0)
+//
+
+#define MPA_SENDMSG 0x00000002 /* (1) 1 -> message not acknowledged by MPBus */
+#define MPA_ERRMSG 0x00000004 /* (2) 0 -> message has been acknowledged
+ * 1 -> at least one MP_Agent has refused */
+
+#define MPA_ADERR_MASK 0x000000f0 /* (7:4) list of refusing processor(s) */
+#define MPA_ADERR_SHIFT 0x4
+
+
+/* +---------------------------+ */
+/* ! snooper register (0x04) ! */
+/* +---------------------------+ */
+
+/*
+ The SNOOPER Register (LOW-PART), which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | 1 | R | R | R | R | - | - | - | 1 | 1 | 1 | - | - | R | R | 1 | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ enable Message receive
+ |_____________ reserved
+ |________________ reserved
+ |____________________ LineSize
+ |________________________ LineSize
+ |____________________________ Three/ Two Party
+ |________________________________ enable Read+Link
+ |____________________________________ enable Coherency
+
+ |__________________________________________ MP Statistics
+ |______________________________________________ MP Statistics
+ |__________________________________________________ MP Statistics
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ FATAL INTERRUPT inactive
+
+
+ The SNOOPER Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | 1 | 1 | 1 | 1 | 1 | R | R | R | R | R | M | M | M | C | C | C | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Cderrtag TagSeq direct error code
+ |_____________ Cderrtag
+ |________________ Cderrtag
+ |____________________ Mderrtag SnpTagSeq memo Error code
+ |________________________ Mderrtag
+ |____________________________ Mderrtag
+ |________________________________ reserved
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ Agent Address
+ |__________________________________________________________ Agent Address
+ |______________________________________________________________ seq. cpu error
+ |__________________________________________________________________ tag seq. error
+ |______________________________________________________________________ ext. seq. error
+
+*/
+
+#define MPA_ENRCVMESS 0x00000001 /* (0) 0 -> disable message receiving
+ * 1 -> enable message receiving */
+
+#define MPA_LSIZE_MASK 0x00000018 /* (4:3) secondary linesize mask */
+#define MPA_LSIZE16 0x00000000 /* secondary linesize = 16 bytes */
+#define MPA_LSIZE32 0x00000008 /* secondary linesize = 32 bytes */
+#define MPA_LSIZE64 0x00000010 /* secondary linesize = 64 bytes */
+#define MPA_LSIZE128 0x00000018 /* secondary linesize = 128 bytes */
+
+/* NOTE: MP_Agent doesn't support linesize greater than 64 bytes !! */
+
+#define MPA_DISTPARTY 0x00000020 /* (5) 0 -> enable three-party mode
+ * MP_Agent requester/MP_Agent target
+ * + memory (for update)
+ *
+ * 1 -> disable three-party mode
+ * MP_Agent requester/MP_Agent target
+ */
+
+#define MPA_ENLINK 0x00000040 /* (6) 0 -> The cpu read and link command is
+ * disabled.
+ * 1 -> The cpu read and link command is
+ * enabled.
+ */
+
+#define MPA_ENCOHREQ 0x00000080 /* (7) 0 -> disable sending external request
+ * for coherency to cpu by his MP_Agent
+ * 1 -> enable sending external request
+ * for coherency to cpu by his MP_Agent
+ */
+
+#define MPA_SNPSELSTAT_MASK 0x00000700 /* (10:8) select programmable mode for snooper
+ * access
+ */
+
+#define MPA_RSTSNPERR 0x00008000 /* (15) 1 -> reset all MP bus fatal error
+ *
+ * 0 -> enable new fatal error on MP bus
+ * sent by interrupt.
+ */
+
+#define MPA_CDERRTAG 0x00070000 /* (18:16) (Read only) error code */
+
+#define MPA_MCDERRTAG 0x00380000 /* (21:19) (Read only) error code */
+
+#define MPA_MCDERREXT 0x00c00000 /* (23:22) (Read only) error code */
+
+#define MPA_ADAGT_MASK 0x18000000 /* (28:27) (Read only) MP_Agent address mask */
+#define MPA_ADAGT_SHIFT 27 /* shift address agent value */
+
+#define MPA_MSEQERR 0xe0000000 /* (31:29) (Read only) error code */
+
+
+/* +---------------------------+ */
+/* ! itpend register (0x07) ! */
+/*+---------------------------+ */
+
+/*
+ The Interrupt Pending Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | UE| UE| UE| UE| R | F | M | M | M | R | E | E | E | E | E | E | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ pending external Interrupts
+ |_____________ pending external Interrupts
+ |________________ pending external Interrupts
+ |____________________ pending external Interrupts
+ |________________________ pending external Interrupts
+ |____________________________ pending external Interrupts
+ |________________________________ reserved
+ |____________________________________ Message Register 1
+
+ |__________________________________________ Message Register 2
+ |______________________________________________ Message Register 3
+ |__________________________________________________ FATAL MP Agent Error
+ |______________________________________________________ reserved
+ |__________________________________________________________ last updated external State
+ |______________________________________________________________ last updated external State
+ |__________________________________________________________________ last updated external State
+ |______________________________________________________________________ last updated external State
+
+ The Interrupt Pending Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | R | R | R | R | R | R | R | R | R | UF| UM| UM| UM| R | UE| UE| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ last updated external State
+ |_____________ last updated external State
+ |________________ reserved
+ |____________________ last updated Message State
+ |________________________ last updated Message State
+ |____________________________ last updated Message State
+ |________________________________ last updated FATAL E State
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ reserved
+
+*/
+
+/* external interrupts */
+#define MPA_INTN_MASKGEN 0x000007ff /* (10:0) pending general interrupt mask */
+#define MPA_INTN_EXT_MASK 0x0000003f /* (5:0) pending external interrupt mask */
+#define MPA_INTN_SR_IP3 0x00000001 /* (0) pending external interrupt SR_IP3 */
+#define MPA_INTN_SR_IP4 0x00000002 /* (1) pending external interrupt SR_IP4 */
+#define MPA_INTN_SR_IP5 0x00000004 /* (2) pending external interrupt SR_IP5 */
+#define MPA_INTN_SR_IP6 0x00000008 /* (3) pending external interrupt SR_IP6 */
+#define MPA_INTN_SR_IP7 0x00000010 /* (4) pending external interrupt SR_IP7 */
+#define MPA_INTN_SR_IP8 0x00000020 /* (5) pending external interrupt SR_IP8 */
+
+/* internal interrupts */
+#define MPA_INTN_ITNMI 0x00000040 /* (6) unused */
+#define MPA_INTN_ITMSG1 0x00000080 /* (7) pending interrupt message1 register */
+#define MPA_INTN_ITMSG2 0x00000100 /* (8) pending interrupt message2 register */
+#define MPA_INTN_ITMSG3 0x00000200 /* (9) pending interrupt message3 register */
+#define MPA_INTN_MPBERR 0x00000400 /* (10) pending interrupt MP_Agent fatal error */
+/* pending internal interrupts mask */
+#define MPA_INTN_INT_MASK (MPA_INTN_ITNMI | \
+ MPA_INTN_ITMSG1 | \
+ MPA_INTN_ITMSG2 | \
+ MPA_INTN_ITMSG3 | \
+ MPA_INTN_MPBERR)
+
+/* old interrupts written in the processor cause register */
+
+/* external interrupts */
+#define MPA_OINTN_MASKGEN 0x007ff000 /* (22:12) old general interrupt mask */
+#define MPA_OINTN_SHIFT 12 /* shift to compare to pending interrupt */
+#define MPA_OINTN_MASK 0x0003f000 /* (17:12) old external interrupt mask */
+#define MPA_OINTN_SR_IP3 0x00001000 /* (12) old external interrupt SR_IP3 */
+#define MPA_OINTN_SR_IP4 0x00002000 /* (13) old external interrupt SR_IP4 */
+#define MPA_OINTN_SR_IP5 0x00004000 /* (14) old external interrupt SR_IP5 */
+#define MPA_OINTN_SR_IP6 0x00008000 /* (15) old external interrupt SR_IP6 */
+#define MPA_OINTN_SR_IP7 0x00010000 /* (16) old external interrupt SR_IP7 */
+#define MPA_OINTN_SR_IP8 0x00020000 /* (17) old external interrupt SR_IP8 */
+
+/* internal interrupts */
+#define MPA_OINTN_ITNMI 0x00040000 /* (18) unused */
+#define MPA_OINTN_ITMSG1 0x00080000 /* (19) old interrupt message1 register */
+#define MPA_OINTN_ITMSG2 0x00100000 /* (20) old interrupt message2 register */
+#define MPA_OINTN_ITMSG3 0x00200000 /* (21) old interrupt message3 register */
+#define MPA_OINTN_MPBERR 0x00400000 /* (22) old interrupt MP_Agent fatal error */
+
+
+/* +---------------------------+ */
+/* ! msgaddress register(0x16) ! */
+/* +---------------------------+ */
+
+/* Message address for message passing */
+
+#define MPA_CPUTARGET_MASK 0x0000000f /* (3:0) target cpu mask */
+#define MPA_CPUTARGET_ALL 0x0000000f /* cpu target : all */
+#define MPA_CPUTARGET_CPU0 0x00000001 /* cpu target : 0 */
+#define MPA_CPUTARGET_CPU1 0x00000002 /* cpu target : 1 */
+#define MPA_CPUTARGET_CPU2 0x00000004 /* cpu target : 2 */
+#define MPA_CPUTARGET_CPU3 0x00000008 /* cpu target : 3 */
+
+#define MPA_REGTARGET_MASK 0x000001f0 /* (8:4) target register */
+#define MPA_REGTARGET_MSG1 0x00000080 /* msg1reg target register */
+#define MPA_REGTARGET_MSG2 0x00000090 /* msg2reg target register */
+#define MPA_REGTARGET_MSG3 0x000000a0 /* msg3reg target register */
+
+#define MPA_ENMSGLPP 0x00000200 /* (9) 0 disable LPP mode for message passing */
+
+/* +---------------------------+ */
+/* ! mem_operator reg. (0x17) ! */
+/* +---------------------------+ */
+
+/* For fake read on a 4Mb segment. Used for cache replace functions */
+
+#define MPA_OP_ENABLE 0x00000001 /* (0) 0 disable operator (address invalid)
+ * 1 enable operator (address valid)
+ */
+
+#define MPA_OP_ADDR_MASK 0xffc00000 /* (31:22) base physical address of a 4Mb kseg0
+ * reserved segment (4Mb == 0x00400000).
+ */
+
+
+#define MPA_TAGREG_ADDR_MASK 0x003ffff0
+#define MPA_TR_STATE_MASK 0x00000003
+#define MPA_TR_NOCOHERENT 0x00000000
+/*
+ * Number of retries before sending a fatal error
+ */
+#define MPA_MSG_RETRY 100
+
+#endif
diff --git a/private/ntos/nthals/halsni4x/mips/orcache.s b/private/ntos/nthals/halsni4x/mips/orcache.s
new file mode 100644
index 000000000..5376f1f11
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/orcache.s
@@ -0,0 +1,628 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halvlbms/src/hal/halsni4x/mips/RCS/orcache.s,v 1.1 1995/05/19 11:22:59 flo Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// orcache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// R4600 orion Machines.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+#define ORION_REPLACE 0xb5000000
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+#define ZERO_PAGE 0x0c // 0000 1100
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+ SBTTL("Orion Processor Identification")
+//++
+//
+// VOID
+// HalpOrionIdentify()
+//
+// Routine Description:
+//
+// This function reads the implementation number in the prid register if
+// a secondary cache exists : ORION without SC = R4x000.
+//
+// Arguments:
+//
+// None
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpOrionIdentify)
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ nop
+ beq v0,zero,10f
+ nop
+ mfc0 v0,prid
+ srl v0,PRID_IMP
+ and v0,0xff
+10: j ra
+
+ .end HalpOrionIdentify
+
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageOrion (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (cache replace) up to a page of data
+// from the secondary data cache. (primary cache is already processed)
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFlushDcachePageOrion)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, FLUSH_DCACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+
+#endif
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the secondary data caches => cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ or t0,t7,a0 // physical address + offset
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,ORION_REPLACE // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+
+ .set noreorder
+ .set noat
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageOrion
+
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageOrion (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeIcachePageOrion)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, PURGE_ICACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the secondary data caches => cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ beq t4,zero,60f
+ or t0,t7,a0 // physical address + offset
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,ORION_REPLACE // get base flush address
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeIcachePageOrion
+
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheOrion (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheOrion)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, SWEEP_DCACHE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Sweep the primary data cache.
+//
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+10:
+ cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+//
+// sweep secondary cache
+//
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+
+ li a0,ORION_REPLACE // starting address
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+25:
+ lw zero,0(a0)
+ bne a0,a1,25b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+
+ .end HalpSweepDcacheMulti
+
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheOrion (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheOrion)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, SWEEP_ICACHE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t0,20f // if eq, no second level cache
+ li a0,ORION_REPLACE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+10: lw zero,0(a0)
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+//
+// Sweep the primary instruction cache.
+//
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,8192(a0)
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+ j ra // return
+
+ .end HalpSweepIcacheOrion
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageOrion (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalpZeroPageOrion, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+#if DBG
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, ZERO_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpZeroPageOrion
+
+
diff --git a/private/ntos/nthals/halsni4x/mips/r4intdsp.c b/private/ntos/nthals/halsni4x/mips/r4intdsp.c
new file mode 100644
index 000000000..855e2a4fd
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/r4intdsp.c
@@ -0,0 +1,1052 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/r4intdsp.c,v 1.1 1995/05/19 11:23:26 flo Exp $")
+
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ r4intdsp.c
+
+Abstract:
+
+ This module contains the HalpXxx routines which are important to
+ handle the Interrupts on the SNI machines.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "SNIregs.h"
+#include "mpagent.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PINT0_DISPATCH)(
+ PKINTERRUPT Interupt,
+ PVOID ServiceContext
+ );
+
+extern VOID HalpDismissTimeoutInterrupts();
+extern VOID HalpDisableTimeoutInterrupts();
+extern VOID HalpEnableTimeoutInterrupts();
+extern VOID HalpSendIpi(IN ULONG pcpumask, IN ULONG msg_data);
+
+#define TIMEOUT_MAX_COUNT 100
+
+KINTERRUPT HalpInt0Interrupt; // Interrupt Object for SC machines (centralised interrupt)
+KINTERRUPT HalpInt1Interrupt; // for SCSI/EISA interrupts (???)
+KINTERRUPT HalpInt3Interrupt; // Interrupt Object for IT3 tower multipro
+KINTERRUPT HalpInt4Interrupt; // Interrupt Object for IT4 tower multipro
+
+ULONG HalpTimeoutCount=0; // simple counter
+
+
+BOOLEAN
+HalpCreateIntStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Int0-handling
+ and connects the intermediate interrupt dispatcher.
+ Also the structures necessary for Int1 (EISA/SCSI)
+ (nicht noetig , Int4 (duart), Int6 (ethernet) and Int7 (BPINT) )
+ are initialized and connected.
+ The timer interrupt handler was directly written in the IDT (see
+ CLOCK2_LEVEL entries in r4initnt.c and r4calstl.c )
+ The last step in this routine is the call of
+ HalpCreateEisaStructures() - a function which initializes
+ the EISA interrupt controllers and
+ connects the central EISA ISR HalpEisaDispatch().
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID InterruptSourceRegister;
+ PINT0_DISPATCH (DispatchRoutine);
+
+ switch (HalpMainBoard) {
+ case M8036 : InterruptSourceRegister = (PVOID)RM200_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpRM200Int0Dispatch;
+ break;
+ case M8032 : InterruptSourceRegister = (PVOID)RM400_TOWER_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpRM400TowerInt0Dispatch;
+ break;
+ case M8042 :
+ default: InterruptSourceRegister = (PVOID)RM400_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpRM400Int0Dispatch;
+ }
+
+ KeInitializeInterrupt( &HalpInt0Interrupt,
+ DispatchRoutine,
+ InterruptSourceRegister,
+ (PKSPIN_LOCK)NULL,
+ INT0_LEVEL,
+ INT0_LEVEL, //INT0_LEVEL,
+ INT0_LEVEL, //Synchr. Level
+ LevelSensitive,
+ FALSE, // only one Intobject ispossible for int0
+ 0, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+ if (!KeConnectInterrupt( &HalpInt0Interrupt )) {
+
+ //
+ // this is the central Interrupt for the SNI SecondLevel Cache Machines
+ //
+
+ HalDisplayString("Failed to connect Int0!\n");
+ return(FALSE);
+ }
+
+ //
+ // this is the "fast" way to connect the interrupt
+ // PCR->InterruptRoutine[INT0_LEVEL] = HalpInt0Dispatch;
+
+
+ //
+ // Initialize the EISA/SCSI interrupt dispatcher for the Minitower.
+ //
+
+ KeInitializeInterrupt( &HalpInt1Interrupt,
+ HalpInt1Dispatch,
+ InterruptSourceRegister, // Interrupt Source Register
+ (PKSPIN_LOCK)NULL,
+ SCSIEISA_LEVEL, //INT1_INDEX,
+ SCSIEISA_LEVEL, //INT1_LEVEL,
+ SCSIEISA_LEVEL, //INT1_SYNC_LEVEL,
+ //Synchronize Irql ???
+ LevelSensitive,
+ TRUE,
+ 0, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+ if (!KeConnectInterrupt( &HalpInt1Interrupt )) {
+
+ //
+ // this is the SCSI/EISA Interrupt for the SNI machines
+ //
+
+ HalDisplayString(" Failed to connect Int 1\n");
+ return(FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+BOOLEAN
+HalpCreateIntMultiStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for
+ dispatch interrupts management (not centralised ones).
+ Only used with mpagent.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ KeInitializeInterrupt( &HalpInt3Interrupt,
+ HalpRM400Int3Process,
+ (PVOID)RM400_TOWER_INTERRUPT_SOURCE_REGISTER,
+ (PKSPIN_LOCK)NULL,
+ INT3_LEVEL,
+ INT3_LEVEL, //INT3_LEVEL,
+ INT3_LEVEL, //Synchr. Level
+ LevelSensitive,
+ FALSE,
+ 0, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+ if (!KeConnectInterrupt( &HalpInt3Interrupt )) {
+
+ //
+ // this is the Interrupt for Debug, Timeout and EIP
+ //
+
+ HalDisplayString("Failed to connect Int3!\n");
+ return(FALSE);
+ }
+
+ KeInitializeInterrupt( &HalpInt4Interrupt,
+ HalpRM400Int4Process,
+ (PVOID)RM400_TOWER_INTERRUPT_SOURCE_REGISTER,
+ (PKSPIN_LOCK)NULL,
+ SCSIEISA_LEVEL,
+ SCSIEISA_LEVEL, // SCSIEISA_LEVEL,
+ SCSIEISA_LEVEL, // Synchr. Level
+ LevelSensitive,
+ FALSE,
+ 0, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+ if (!KeConnectInterrupt( &HalpInt4Interrupt )) {
+
+ //
+ // this is the Interrupt for Debug, Timeout and EIP
+ //
+
+ HalDisplayString("Failed to connect Int4!\n");
+ return(FALSE);
+ }
+
+
+ return (TRUE);
+}
+
+BOOLEAN
+HalpRM200Int0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI Desktop Model
+ To decide which interrupt, read the Interrupt Source Register
+
+
+ At the moment we test different interrupt handling
+ Handle all pending interrupts from highest level to the lowest or
+ Handle the highest Interrupt only
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR IntSource;
+ BOOLEAN SCSIresult, NETresult ;
+
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+
+
+ IntSource ^= RM200_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // ans XOR the high active with 0 gives 1
+
+ //
+ // on the Desktop Model, most interrupt will occcur on the onboard components
+ // so, give them the highest priority by serving them first, but FIRST check for timeout
+ // interrupts
+
+ // At the moment we have assigned the following priorities:
+ // Timeout Interrupt (a timeout may prevent other interrupt dispatch code to work correct)
+ // Onboard (System Clock on Isa Interrupt 0 every 10ms)
+ // SCSI Controller
+ // Network Controller
+ // Eisa Extension Board
+ // PushButton
+
+ if ( IntSource & RM200_TIMEOUT_MASK) { // TIMEOUT Interrupt
+
+ HalpDismissTimeoutInterrupts();
+
+ if (++HalpTimeoutCount >= TIMEOUT_MAX_COUNT) {
+
+ //
+ // if we get a lot of them, simply disable them ...
+ //
+
+ HalpDisableTimeoutInterrupts();
+
+ }
+ }
+
+ if ( IntSource & RM200_ONBOARD_MASK) { // ISA (onboard) Interrupt
+
+ return HalpEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)RM200_ONBOARD_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & RM200_SCSI_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+ return(SCSIresult);
+ }
+
+ //
+ // look for an Ethernet Interrupt
+ //
+
+ if ( IntSource & RM200_NET_MASK){
+ NETresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
+ PCR->InterruptRoutine[NET_LEVEL]
+ );
+ return(NETresult);
+ }
+
+ //
+ // on an Desktop we may only have Eisa Interrupts when the
+ // Eisa backplane is installed
+ //
+
+ if ( IntSource & RM200_EISA_MASK) { // EISA Interrupt
+
+ if (HalpEisaExtensionInstalled) {
+ return HalpEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+
+ } else {
+ DebugPrint(("HAL: Unexpected EISA interrupt with no EISA backplane installed !\n"));
+ }
+ }
+
+
+ //
+ // look for an PushButton Interrupt
+ // we may use this on a checked build for breaking into debugger
+ //
+
+ if ( IntSource & RM200_PB_MASK){
+
+ WRITE_REGISTER_UCHAR( RM200_RESET_DBG_BUT ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+
+ }
+
+ return (TRUE); // perhaps on of the interrupts was pending :-)
+}
+
+
+BOOLEAN
+HalpRM400Int0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI R4x00SC Minitower
+ To decide which interrupt, read the Interrupt Source Register
+
+ On an SC model and on the SNI Desktop, we havew to manage priorities by software,
+ because the HW priority over the Cause Bits has only 1 input - the Int0
+
+ At the moment we test different interrupt handling
+ Handle all pending interrupts from highest level to the lowest or
+ Handle the highest Interrupt only
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR IntSource;
+
+ UCHAR MaStatus;
+
+ BOOLEAN SCSIresult, NETresult;
+
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+
+
+ IntSource ^= RM400_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // ans XOR the high active with 0 gives 1
+ // so 0101 1111 gives 1 for EISA, SCSI, Timer0,
+ // Timer1, Net and Push Button
+
+
+ //
+ // on an RM400 we may have to look for OverTemperature and Timeout Interrupts
+ // and PushButton in the machineStatus register
+ //
+
+ MaStatus = READ_REGISTER_UCHAR(RM400_MSR_ADDR);
+
+ //
+ // I like High actice bits ....
+ //
+
+ MaStatus ^= RM400_MSR_MASK;
+
+ // these are the priorities on an Minitower
+ // Timeout Interrupt (a timeout may prevent other interrupt dispatch code to work correct)
+ // Eisa (onboard)Interrupts
+ // SCSI Controler
+ // Network
+ // NO extra Timer in local I/O space (not used on UniProcessor)
+ // PushButton
+ // Temperature
+ //
+
+ if ( MaStatus & RM400_MSR_TIMEOUT_MASK) { // TIMEOUT Interrupt
+
+ DebugPrint(("Interrupt - Timeout\n"));
+ HalpDismissTimeoutInterrupts();
+
+ if (++HalpTimeoutCount >= TIMEOUT_MAX_COUNT) {
+
+ //
+ // if we get a lot of them, simply disable them ...
+ //
+
+ HalpDisableTimeoutInterrupts();
+
+ }
+ }
+
+ if ( IntSource & RM400_EISA_MASK) { // EISA Interrupt
+
+ return HalpEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & RM400_SCSI_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI interrupt !\n"));
+#endif
+ return(SCSIresult);
+
+ }
+
+
+ //
+ // look for an Ethernet Interrupt
+ //
+
+ if ( IntSource & RM400_NET_MASK){
+ NETresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
+ PCR->InterruptRoutine[NET_LEVEL]
+ );
+ return(NETresult);
+ }
+
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & RM400_MSR_PB_MASK){
+ DebugPrint(("Interrupt - PushButton\n"));
+ WRITE_REGISTER_UCHAR( RM400_RESET_DBG_BUT ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+ }
+
+ //
+ // look for an OverTemperature Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & RM400_MSR_TEMP_MASK){
+
+ DebugPrint(("Interrupt - Temperature\n"));
+
+ // Reset hardware detection
+
+ WRITE_REGISTER_UCHAR( RM400_MCR_ADDR ,MCR_TEMPBATACK | MCR_PODD);
+
+ // Enable new hardware detection
+
+ WRITE_REGISTER_UCHAR( RM400_MCR_ADDR , MCR_PODD);
+ WRITE_REGISTER_UCHAR( RM400_RESET_TEMPBAT_INTR ,0x0); // reset interrupt
+
+ // currently, no action
+ }
+
+ return (TRUE); // perhaps on of the interrupts was pending :-)
+}
+
+
+BOOLEAN
+HalpRM400TowerInt0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI R4x00SC Tower
+ To decide which interrupt, read the Interrupt Source Register
+
+ On an Tower model, we have also to manage priorities by software,
+ because the HW priority over the Cause Bits has only 1 input - the Int0
+
+ At the moment we test different interrupt handling
+ Handle all pending interrupts from highest level to the lowest or
+ Handle the highest Interrupt only
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR IntSource;
+
+ UCHAR MaStatus;
+
+ BOOLEAN SCSIresult, NETresult;
+
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+
+ IntSource ^= RM400_TOWER_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // ans XOR the high active with 0 gives 1
+ // so 0101 1111 gives 1 for EISA, SCSI, Timer0,
+ // Timer1, Net and Push Button
+
+
+ //
+ // on an RM400 Tower we may have to look for EIP, Timeout Interrupts
+ // and PushButton in the machineStatus register
+ // OverTemperature, Fan Control, BBU etc is handled by the EIP Processor
+ //
+
+ MaStatus = READ_REGISTER_UCHAR(RM400_MSR_ADDR);
+
+ //
+ // I like High actice bits ....
+ //
+
+ MaStatus ^= RM400_MSR_MASK;
+
+ // these are the priorities on an RM400-TOwer
+ // Extra Clock (used only on MultiPro machines)
+ // Timeout Interrupts
+ // Eisa (onboard)Interrupts
+ // SCSI Controler
+ // Network
+ // extra Timer in local I/O space (this may be changed on an MULTI)
+ // PushButton
+ // EIP Peripherial Processor
+
+ if ( MaStatus & RM400_MSR_TIMEOUT_MASK) { // TIMEOUT Interrupt
+
+ DebugPrint(("Interrupt - Timeout\n"));
+ HalpDismissTimeoutInterrupts();
+
+ if (++HalpTimeoutCount >= TIMEOUT_MAX_COUNT) {
+
+ //
+ // if we get a lot of them, simply disable them ...
+ //
+
+ HalpDisableTimeoutInterrupts();
+
+ }
+
+ return TRUE;
+ }
+
+ if ( IntSource & RM400_TOWER_EISA_MASK) { // EISA(onboard) Interrupt
+
+ return HalpEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & RM400_TOWER_SCSI_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI interrupt !\n"));
+#endif
+ return(SCSIresult);
+
+ }
+
+
+ //
+ // look for an Ethernet Interrupt
+ //
+
+ if ( IntSource & RM400_TOWER_NET_MASK){
+ NETresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
+ PCR->InterruptRoutine[NET_LEVEL]
+ );
+ return(NETresult);
+ }
+
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & RM400_MSR_PB_MASK){
+ DebugPrint(("Interrupt - PushButton\n"));
+ WRITE_REGISTER_UCHAR( RM400_RESET_DBG_BUT ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+ }
+
+ //
+ // look for an EIP Interrupt and ????
+ //
+
+ if ( MaStatus & RM400_MSR_EIP_MASK){
+
+ //
+ // we dont't know exactly how to handle this and it is not
+ // part of the HAL Spec. So we have assigned an IRQL to this -
+ // the EIP Software will know this and handle it correct
+ //
+
+ DebugPrint(("Got EIP Interrupts\nTransfering control to EIP Handling Routine\n"));
+
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[EIP_VECTOR])(
+ PCR->InterruptRoutine[EIP_VECTOR]
+ );
+ //
+ // currently, no other action
+ //
+
+ }
+
+ return TRUE; // perhaps on of the interrupts was pending :-)
+}
+
+
+BOOLEAN
+HalpInt1Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ If we use an R4x00PC model as CPU, we have some more direct hardware interrupts
+ direct connected to the CPU. So we have to test for timeout etc. at this place.
+ Handles on an RM400Minitower the SCSI/EISA Interrupt for R4x00 PC
+ To decide which interrupt, read the Interrupt Source Register
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+ None.
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+
+ UCHAR IntSource;
+ UCHAR MaStatus;
+ BOOLEAN SCSIresult;
+
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+ IntSource ^= RM400_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // ans XOR the high active with 0 gives 1
+ // so 0101 1111 gives 1 for EISA, SCSI, Timer0,
+ // Timer1, Net and Push Button
+
+
+ //
+ // on an RM400 MiniTower we may have to look for Timeout Interrupts, OverTemperature
+ // and PushButton in the machineStatus register
+ //
+
+ MaStatus = READ_REGISTER_UCHAR(RM400_MSR_ADDR);
+
+ //
+ // I like High actice bits ....
+ //
+
+ MaStatus ^= RM400_MSR_MASK;
+
+ if ( MaStatus & RM400_MSR_TIMEOUT_MASK) { // TIMEOUT Interrupt
+
+ DebugPrint(("Interrupt - Timeout\n"));
+ HalpDismissTimeoutInterrupts();
+
+ if (++HalpTimeoutCount >= TIMEOUT_MAX_COUNT) {
+
+ //
+ // if we get a lot of them, simply disable them ...
+ //
+
+ HalpDisableTimeoutInterrupts();
+
+ }
+ }
+
+
+ //
+ // this is a new Minitower mainboard, so we can look in the Interrupt
+ // Source register for Interrupts ...
+ //
+
+
+ if ( IntSource & RM400_SCSI_MASK){ // SCSI Interrupt
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI interrupt !\n"));
+#endif
+ }
+
+ if ( IntSource & RM400_EISA_MASK) { // EISA (onboard)Interrupt
+ return HalpEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ }
+
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+//#ifdef XXX
+
+ if ( MaStatus & RM400_MSR_PB_MASK){
+ DebugPrint(("Interrupt - PushButton\n"));
+ WRITE_REGISTER_UCHAR( RM400_RESET_DBG_BUT ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+ }
+
+//#endif
+
+ //
+ // look for an OverTemperature Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & RM400_MSR_TEMP_MASK){
+
+ DebugPrint(("Interrupt - Temperature\n"));
+
+ // Reset hardware detection
+
+ WRITE_REGISTER_UCHAR( RM400_MCR_ADDR ,MCR_TEMPBATACK | MCR_PODD);
+
+ // Enable new hardware detection
+
+ WRITE_REGISTER_UCHAR( RM400_MCR_ADDR , MCR_PODD);
+ WRITE_REGISTER_UCHAR( RM400_RESET_TEMPBAT_INTR ,0x0); // reset interrupt
+
+ // currently, no action
+ }
+
+
+ return TRUE; // perhaps on of the interrupts was pending :-)
+}
+
+
+
+BOOLEAN
+HalpRM400Int3Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the INT3 Interrupt on an SNI R4x00SC Tower :
+
+ - Timeout
+ - Debug button
+ - EIP
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR MaStatus;
+
+ //
+ // on an RM400 Tower we may have to look for EIP, Timeout Interrupts
+ // and PushButton in the machineStatus register
+ // OverTemperature, Fan Control, BBU etc is handled by the EIP Processor
+ //
+
+ MaStatus = READ_REGISTER_UCHAR(RM400_MSR_ADDR);
+
+ MaStatus ^= RM400_MSR_MASK; // I like High actice bits ....
+
+ if ( MaStatus & RM400_MSR_TIMEOUT_MASK) { // TIMEOUT Interrupt
+
+ DebugPrint(("Interrupt - Timeout\n"));
+ HalpDismissTimeoutInterrupts();
+
+ if (++HalpTimeoutCount >= TIMEOUT_MAX_COUNT) {
+
+ //
+ // if we get a lot of them, simply disable them ...
+ //
+
+ HalpDisableTimeoutInterrupts();
+
+ }
+
+ return TRUE;
+ }
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & RM400_MSR_PB_MASK){
+ DebugPrint(("Interrupt - PushButton\n"));
+ WRITE_REGISTER_UCHAR( RM400_RESET_DBG_BUT ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+ }
+
+ //
+ // look for an EIP Interrupt and ????
+ //
+
+ if ( MaStatus & RM400_MSR_EIP_MASK){
+
+ //
+ // we dont't know exactly how to handle this and it is not
+ // part of the HAL Spec. So we have assigned an IRQL to this -
+ // the EIP Software will know this and handle it correct
+ //
+
+ DebugPrint(("Got EIP Interrupts\nTransfering control to EIP Handling Routine\n"));
+
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[EIP_VECTOR])(
+ PCR->InterruptRoutine[EIP_VECTOR]
+ );
+ //
+ // currently, no other action
+ //
+
+ }
+
+ return TRUE; // perhaps on of the interrupts was pending :-)
+}
+
+
+
+BOOLEAN
+HalpRM400Int4Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the INT4 Interrupt on an SNI R4x00SC Tower :
+
+ - EISA
+ - SCSI
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR IntSource;
+
+ BOOLEAN Result;
+
+ Result = FALSE;
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+
+ IntSource ^= RM400_TOWER_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // ans XOR the high active with 0 gives 1
+ // so 0101 1111 gives 1 for EISA, SCSI, Timer0,
+ // Timer1, Net and Push Button
+
+ if ( IntSource & RM400_TOWER_EISA_MASK) { // EISA(onboard) Interrupt
+
+ Result = HalpEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & RM400_TOWER_SCSI_MASK){
+ Result = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+#if DBG
+ if(!Result) DebugPrint(("Got an invalid SCSI interrupt !\n"));
+#endif
+
+ }
+
+ HalpCheckSpuriousInt();
+ return(Result);
+
+}
+
+
+VOID
+HalpRM400Int5Process (
+ )
+/*++
+Routine Description:
+
+ This routine handles the INT5 Interrupt on an SNI R4x00SC Tower :
+
+ - NET
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ BOOLEAN Result;
+
+ Result = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
+ PCR->InterruptRoutine[NET_LEVEL]
+ );
+#if DBG
+ if(!Result) DebugPrint(("Got an invalid NET interrupt !\n"));
+#endif
+
+ HalpCheckSpuriousInt();
+
+}
diff --git a/private/ntos/nthals/halsni4x/mips/snidef.h b/private/ntos/nthals/halsni4x/mips/snidef.h
new file mode 100644
index 000000000..7eabd8dd8
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/snidef.h
@@ -0,0 +1,215 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/snidef.h,v 1.6 1995/04/07 10:00:01 flo Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ SNIdef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ common for all SNI systems.
+
+
+
+---*/
+
+#ifndef _SNIDEF_
+#define _SNIDEF_
+
+
+#if DBG
+#define DebugPrint(arg) DbgPrint arg
+#else
+#define DebugPrint(arg) ;
+#endif
+
+#include "DESKdef.h"
+#include "MINIdef.h"
+
+
+#define VESA_BUS_PHYSICAL_BASE 0x1d000000
+#define VESA_BUS (VESA_BUS_PHYSICAL_BASE | KSEG1_BASE)
+#define VESA_IO_PHYSICAL_BASE 0x1e000000
+#define VESA_IO (VESA_IO_PHYSICAL_BASE | KSEG1_BASE)
+#define PROM_PHYSICAL_BASE 0x1fc00000 // physical base of boot PROM
+#define EISA_MEMORY_PHYSICAL_BASE 0x10000000 // physical base of EISA memory
+#define EISA_CONTROL_PHYSICAL_BASE 0x14000000 // physical base of EISA I/O Space
+#define EISA_MEMORY_BASE (EISA_MEMORY_PHYSICAL_BASE | KSEG1_BASE)
+#define EISA_IO (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE)
+#define MPAGENT_RESERVED 0x17c00000 // KSEG1 address of a 4M segment stolen
+ // in the upper part of the I/O EISA space
+ // to be used for cache replace operation.
+#define NET_PHYSICAL_BASE 0x18000000 // physical base of ethernet control
+#define SCSI_PHYSICAL_BASE 0x19000000 // physical base of SCSI control 1
+
+#define FLOPPY_CHANNEL 0x2 // Floppy DMA channel
+#define FLOPPY_RELATIVE_BASE 0x3f0 // base of floppy control
+#define PARALLEL_RELATIVE_BASE 0x3bc // base of parallel port
+#define SERIAL0_RELATIVE_BASE 0x3f8 // base of serial port 0
+#define SERIAL1_RELATIVE_BASE 0x2f8 // base of serial port 1
+
+#define FLOPPY_PHYSICAL_BASE 0x160003f0 // base of floppy control
+#define PARALLEL_PHYSICAL_BASE 0x160003bc // base of parallel port
+#define SERIAL0_PHYSICAL_BASE 0x160003f8 // base of serial port 0
+#define SERIAL1_PHYSICAL_BASE 0x160002f8 // base of serial port 1
+
+
+//
+// the UCONF, MachineStatus, LED and MachineConfig Registers in the ASIC
+// (identical on all SNI machines)
+//
+
+#define UCONF_PHYSICAL_ADDR 0x1fff0000 // interruptions, interface protocol
+#define UCONF_ADDR 0xbfff0000 // interruptions, | KSEG1_BASE
+#define IOMEMCONF_PHYSICAL_ADDR 0x1fff0010 // I/O and Memory Config (for disable Timeout int)
+#define IOMEMCONF_ADDR 0xbfff0010 // I/O and memconf | KSEG1_BASE
+
+//
+// some debugging information registers in the ASIC
+// common on all SNI machines
+//
+
+#define DMACCES_PHYSICAL_ADDR 0x1fff0028 // Counter: # of DMA accesses
+#define DMACCES 0xbfff0028 // Counter: # of DMA accesses | KSEG1_BASE
+#define DMAHIT_PHYSICAL_ADDR 0x1fff0030 // Counter: # of DMA hits
+#define DMAHIT 0xbfff0030 // Counter: # of DMA hits | KSEG1_BASE
+#define IOMMU_PHYSICAL_ADDR 0x1fff0018 // Select IO space addressing
+#define IOMMU 0xbfff0018 // Select IO space addressing | KSEG1_BASE
+#define IOADTIMEOUT1_PHYSICAL_ADDR 0x1fff0020 // Current IO context for the first CPU timeout
+#define IOADTIMEOUT1 0xbfff0020 // first CPU timeout | KSEG1_BASE
+#define IOADTIMEOUT2_PHYSICAL_ADDR 0x1fff0008 // Current IO context on all CPU timeouts
+#define IOADTIMEOUT2 0xbfff0008 // all CPU timeouts | KSEG1_BASE
+
+
+//
+// Define system time increment value.
+//
+
+#define TIME_INCREMENT (10 * 1000 * 10) // Time increment in 100ns units
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+
+#define EXTRA_TIMER_CLOCK_IN 3686400 // 3.6864 Mhz
+#define PRE_COUNT 3 //
+
+
+//
+// Define basic Interrupt Levels which correspond to Cause register bits.
+//
+
+#define INT0_LEVEL 3
+#define INT3_LEVEL 3
+#define SCSIEISA_LEVEL 4 // SCSI/EISA device int. vector
+#define EISA_DEVICE_LEVEL 4 // EISA bus interrupt level ???
+#define DUART_VECTOR 5 // DUART SC 2681 int. vector
+#define EXTRA_CLOCK_LEVEL 6 // this is one of the extra timers on RM400
+#define PROFILE_LEVEL 8 // Profiling level via Count/compare Interrupt
+
+#define CLOCK_LEVEL (ONBOARD_VECTORS + 0) // Timer channel 0 in the PC core
+
+//
+// all others are vectors in the interrupt dispatch table.
+//
+
+#define SCSI_VECTOR 9 // SCSI device interrupt vector
+
+#define NET_DEFAULT_VECTOR 7 // ethernet device internal vector on R4x00 PC !!!
+ // configured in the Firmware Tree !!!!!
+#define NET_LEVEL 10 // ethernet device int. vector
+
+#define OUR_IPI_LEVEL 7 // multipro machine
+#define NETMULTI_LEVEL 5 // multipro machine : ethernet device int. vector
+
+#define EIP_VECTOR 15 // EIP Interrupt routine
+
+#define CLOCK2_LEVEL CLOCK_LEVEL // System Clock Level
+
+#define ONBOARD_VECTORS 16
+#define MAXIMUM_ONBOARD_VECTOR (15 + ONBOARD_VECTORS) // maximum Onboard (PC core) vector
+
+//
+// Define EISA device interrupt vectors.
+// they only occur when an Eisa Extension is installed in the Desktop model
+//
+
+#define EISA_VECTORS 32
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+//
+// relative interrupt vectors
+// only the interrupt vectors relative to the Isa/EISA bus are defined
+//
+
+#define KEYBOARD_VECTOR 1 // Keyboard device interrupt vector
+#define SERIAL1_VECTOR 3 // Serial device 1 interrupt vector
+#define SERIAL0_VECTOR 4 // Serial device 0 interrupt vector
+#define FLOPPY_VECTOR 6 // Floppy device interrupt vector
+#define PARALLEL_VECTOR 7 // Parallel device interrupt vector
+#define MOUSE_VECTOR 12 // PS/2 Mouse device interrupt vector
+
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0xc0000 // 768KB for today
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0xc0000 // 256KB as start
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 512
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+// (16MB)
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the maximum physical address of Main memory on SNI machines
+// (256 MB)
+//
+
+#define MAXIMUM_MEMORY_PHYSICAL_ADDRESS 0x10000000
+
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+
+
+#endif /* _SNIDEF_ */
diff --git a/private/ntos/nthals/halsni4x/mips/snidisp.c b/private/ntos/nthals/halsni4x/mips/snidisp.c
new file mode 100644
index 000000000..343d20a6a
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/snidisp.c
@@ -0,0 +1,1475 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/snidisp.c,v 1.3 1995/10/06 09:43:09 flo Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991-93 Microsoft Corporation
+
+Module Name:
+
+ SNIdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for the different SNI machines.
+ Because we have no full working Configuration management (yet), we try to
+ identitify some graphic boards ourself.
+
+ CHANGE CHANGE CHANGE now we have a working display configuration entry
+ Thanx to Mr. Pierre Sanguard, the firmware people from SNI France (Plaisir)
+
+ At the moment we know about the following boards:
+ P9000 based Cards: Orchid P9000 VLB / Diamond Viper
+ Standard S3 based ISA/VLB cards ( 80x50 Alpha Mode)
+ Standard Cirrus ISA/VLB cards ( 80x50 Alpha Mode)
+ Standard (unknown) VGA on ISA/VLB( 80x50 Alpha Mode)
+
+
+ If we can not identify the board, we don't initialise the display and we call
+ the vendor printf to display strings.
+
+ At the boot phase all I/O is done via the unmapped uncached Segment (KSEG1) of the
+ R4000 (HalpEisaControlBase); later with the mapped value of HalpEisaControlBase
+ Memory is always accessed via unmapped/uncached (KSEG1) area
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Removed HalpInitializeDisplay1, because we do no longer use the P9000 in graphic mode ...
+
+
+NOTE:
+
+
+ We did use our own ...MoveMemory() instead of RtlMoveMemory(),
+ as there is a Hardware bug in our machine and RtlMoveMemory uses
+ the floating point registers for fast 64 bit move and on our bus
+ only 32 bit can be found ... :-)
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+#include "vgadata.h"
+
+
+#define MEGA_MOVE_MEMORY(D,S,L) MegaMoveMemory(D,S,L) // orig. RtlMoveMemory()
+
+//
+// supported VGA text modi
+//
+
+typedef enum _TEXT_MODE {
+ TEXT_80x50,
+ TEXT_132x50
+} TEXT_MODE;
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+BOOLEAN ICD2061LoadClockgen (PUCHAR port, ULONG data, LONG bitpos);
+BOOLEAN Bt485InitRamdac (VOID);
+LONG ICD2061CalcClockgen (LONG freq);
+VOID HalpDisplaySmallCharacter (IN UCHAR Character);
+VOID HalpOutputSmallCharacter (IN PUCHAR Font);
+VOID HalpInitializeVGADisplay(TEXT_MODE TextMode);
+VOID HalpClearVGADisplay (VOID);
+VOID HalpDisplayVGAString (PUCHAR String);
+VOID HalpPutVGACharacter (UCHAR Character);
+VOID HalpNextVGALine (VOID);
+VOID HalpScrollVGADisplay (VOID);
+VOID DownLoadVGAFont (VOID);
+VOID HalpResetS3Chip (VOID);
+VOID HalpResetCirrusChip (VOID);
+VOID HalpResetP9000 (VOID);
+VOID HalpResetP9100 (VOID);
+VOID HalpVGASetup (VOID);
+VOID HalpDoNoSetup (VOID);
+
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+
+//
+// Supported board definitions.
+//
+
+typedef enum _VIDEO_BOARD {
+ P9000_RM400 = 0, // SNI specific Video Board for the RM400-10
+ P9000_ORCHID, // Orchid P9000 VLB (Vesa Local Bus)
+ P9000_VIPER, // Diamond Viper (Vesa Local Bus P9000)
+ S3_GENERIC, // Standard S3 based Card (miro crystal 8s)
+ S3_GENERIC_VLB, // Standard S3 based Card (Local Bus)
+ CIRRUS_GENERIC, // Generic Cirrus VGA (Cirrus CL54xx)
+ CIRRUS_GENERIC_VLB, // Generic Cirrus VGA (Cirrus CL54xx) (Local Bus)
+ CIRRUS_ONBOARD, // The Desktop onboard VGA (Cirrus CL5434)
+ VGA_GENERIC, // generic (unknown) VGA
+ VGA_GENERIC_VLB, // generic (unknown) VGA on the Vesa Local BUS
+ P9100_WEITEK, // Diamond (Vesa Local Bus P9100)
+ VIDEO_BOARD_UNKNOWN // unknown Display Adapter
+} VIDEO_BOARD;
+
+//
+// some supported VGA chips
+//
+
+typedef enum _VIDEO_CHIP {
+ P9000 = 0,
+ S3,
+ CIRRUS,
+ VGA, // generic (unknown) VGA
+ VGA_P9000,
+ VGA_P9100,
+ VIDEO_CHIP_UNKNOWN
+} VIDEO_CHIP;
+
+typedef struct _VIDEO_BOARD_INFO {
+ PUCHAR FirmwareString;
+ PHALP_CONTROLLER_SETUP ControllerSetup;
+ VIDEO_BOARD VideoBoard;
+ VIDEO_CHIP VideoChip;
+} VIDEO_BOARD_INFO, *PVIDEO_BOARD_INFO;
+
+
+VIDEO_BOARD_INFO KnownVideoBoards[] = {
+ {"ORCHID P9000 VLBUS", HalpVGASetup , P9000_ORCHID , VGA_P9000 },
+ {"DIAMOND P9000 VLBUS", HalpVGASetup , P9000_VIPER , VGA_P9000 },
+ {"VGA ON ATBUS", HalpVGASetup , VGA_GENERIC , VGA },
+ {"S3 BASED VLBUS", HalpVGASetup , S3_GENERIC_VLB, S3 },
+ {"CIRRUS BASED VLBUS", HalpVGASetup , CIRRUS_GENERIC_VLB, CIRRUS},
+ {"CIRRUS ON BOARD", HalpVGASetup , CIRRUS_ONBOARD, CIRRUS},
+ {"CIRRUS ONBOARD", HalpVGASetup , CIRRUS_ONBOARD, CIRRUS},
+ {"VGA ON VLBUS", HalpVGASetup , VGA_GENERIC_VLB, VGA },
+ {"DIAMOND P9100 VLBUS", HalpVGASetup , P9100_WEITEK , VGA_P9100 }
+};
+
+LONG numVideoBoards = sizeof (KnownVideoBoards) / sizeof(VIDEO_BOARD_INFO);
+
+//
+// Define static data.
+//
+
+VIDEO_BOARD HalpVideoBoard = VIDEO_BOARD_UNKNOWN;
+VIDEO_CHIP HalpVideoChip = VIDEO_CHIP_UNKNOWN;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = HalpDoNoSetup;
+
+ULONG HalpColumn;
+ULONG HalpRow;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+ULONG HalpBytesPerRow;
+PVOID HalpVGAControlBase=( PVOID)( EISA_IO); // Base Address for VGA register access
+PUSHORT VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000);
+PUCHAR FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000);
+BOOLEAN HalpFirstBoot = TRUE;
+
+//
+// Declare externally defined data.
+//
+
+
+BOOLEAN HalpDisplayOwnedByHal;
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+
+
+VOID MegaMoveMemory(
+ OUT PVOID Destination,
+ IN PVOID Source,
+ IN ULONG Length
+ )
+/*++
+
+ Our private function written to substitute the RtlMoveMemory()
+ function (64 bit problem).
+
+--*/
+{
+ULONG lo_index_ul;
+PULONG Dst, Src;
+
+ Dst = (PULONG)Destination;
+ Src = (PULONG)Source;
+ for (lo_index_ul=0; lo_index_ul < Length/sizeof(ULONG); lo_index_ul++)
+ *Dst++ = *Src++;
+}
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PVIDEO_BOARD_INFO VideoBoard;
+ LONG Index;
+ ULONG MatchKey;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // N.B. Be carefull with debug prints during Phase 0, it
+ // will kill the initial break point request from the debugger ...
+ //
+
+
+ for( Index=0, VideoBoard = KnownVideoBoards; Index < numVideoBoards; Index++, VideoBoard++) {
+
+ if (!strcmp( ConfigurationEntry->ComponentEntry.Identifier,
+ VideoBoard->FirmwareString
+ )) {
+ HalpVideoBoard = VideoBoard->VideoBoard;
+ HalpVideoChip = VideoBoard->VideoChip;
+ HalpDisplayControllerSetup = VideoBoard->ControllerSetup;
+ break;
+ }
+ }
+
+ if (Index >= numVideoBoards) {
+ HalpVideoBoard = VIDEO_BOARD_UNKNOWN;
+ HalpVideoChip = VIDEO_CHIP_UNKNOWN;
+ HalpDisplayControllerSetup = HalpDoNoSetup;
+
+ //
+ // let's see, if the bios emulator can initialize the card ....
+ //
+
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ return TRUE;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+
+ HalpFirstBoot = FALSE;
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine normally allocates pool for the OEM font file, but
+ in this version we use only VGA facilities of the Grapgic boards
+ so we simply return TRUE
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ TRUE
+
+--*/
+
+{
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+VOID
+HalpDoNoSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine does nothing...
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpVGASetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes a VGA based Graphic card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR byte;
+
+
+ switch (HalpVideoBoard){
+ case S3_GENERIC_VLB:
+ case CIRRUS_GENERIC_VLB:
+ case VGA_GENERIC_VLB:
+ case P9100_WEITEK:
+//
+// N.B.
+// on an SNI desktop model the VL I/O space is transparent, so
+// acces in the normal Backplane area results in correct values
+// the minitower instead, does not decode all VL signals correct,
+// so ther is an EXTRA I/O space for accessing VL I/O (0x1exxxxxx)
+// this is handled in the definition of VESA_IO in SNIdef.h
+//
+
+ HalpVGAControlBase = (HalpIsRM200) ? (PVOID)HalpEisaControlBase : (PVOID)VESA_IO;
+ VideoBuffer = ( PUSHORT)( VESA_BUS + 0xb8000);
+ FontBuffer = ( PUCHAR )( VESA_BUS + 0xa0000);
+
+ break;
+
+ case CIRRUS_ONBOARD:
+ HalpVGAControlBase = (PVOID)HalpOnboardControlBase;
+ VideoBuffer = ( PUSHORT)( RM200_ONBOARD_MEMORY + 0xb8000);
+ FontBuffer = ( PUCHAR )( RM200_ONBOARD_MEMORY + 0xa0000);
+ break;
+
+ case S3_GENERIC:
+ case CIRRUS_GENERIC:
+ case VGA_GENERIC:
+ default:
+ HalpVGAControlBase = (PVOID)HalpEisaControlBase;
+ VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000);
+ FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000);
+ break;
+ }
+
+
+
+ //
+ // if "only" VGA is detected look for an S3 or cirrus chip (VGA ON ATBUS)
+ // if the firmware detects an S3 chip, look if this is an 805i (interleave)
+ //
+
+
+ if ((HalpVideoChip == VGA) || (HalpVideoChip == S3)){
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // look for Cirrus chips
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); // read it back
+ if (byte != 0x12) { // no cirrus
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x30); // look for s3 chip id
+ byte = READ_REGISTER_UCHAR(VGA_CRT_DATA) ; // look only for major id
+ switch (byte & 0xf0){
+ case 0xa0: // 801/805 chipset
+ if (byte == 0xa8) { // the new 805i (interleave)
+// DebugPrint(("HAL: Found the new 805i Chip resetting to 805 mode\n"));
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0067);
+ }
+ case 0x80:
+ case 0x90:
+// DebugPrint(("HAL: Found S3 Chip set - Chip id 0x%x\n",byte));
+ HalpVideoChip = S3;
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs
+ break;
+ default: DebugPrint(("HAL: This seems to be no S3 Chip\n"));
+ }
+ } else { // this may be an cirrus
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x27); // cirrus id reg
+ byte = READ_REGISTER_UCHAR(VGA_CRT_DATA);
+ if ((byte & 0xe0) == 0x80) { // look for 100xxxxx
+// DebugPrint(("HAL: Found Cirrus Chip set - Chip id 0x%x\n",byte));
+ HalpVideoChip = CIRRUS;
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0006); // lock Cirrus extensions
+ }
+ }
+ }
+
+
+ switch (HalpVideoChip) {
+
+ case VGA_P9000:
+ HalpResetP9000();
+
+ //
+ // we have programmed the clock into register 0 of the ICD2061, so
+ // select it via the VGA_MISC register
+ //
+
+// WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0xa3);
+ break;
+
+ case S3: HalpResetS3Chip();
+ break;
+
+ case CIRRUS: HalpResetCirrusChip();
+ break;
+
+ case VGA_P9100:
+ HalpResetP9100();
+ break;
+
+ default: ;
+ }
+
+ HalpInitializeVGADisplay(TEXT_80x50);
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if(HalpIsMulti) KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+
+ HalpDisplayControllerSetup();
+
+ }
+
+ // display the string
+
+ if( HalpVideoChip == VIDEO_CHIP_UNKNOWN) {
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->printf(String);
+ } else {
+ HalpDisplayVGAString(String);
+ }
+
+ if(HalpIsMulti) KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+
+VOID
+HalpDisplayVGAString (
+ PUCHAR String
+ )
+{
+ while (*String) {
+ switch (*String) {
+ case '\n':
+ HalpNextVGALine();
+ break;
+ case '\r':
+ HalpColumn = 0;
+ break;
+ default:
+ HalpPutVGACharacter(*String);
+ if (++HalpColumn == HalpDisplayWidth) {
+ HalpNextVGALine();
+ }
+ }
+ ++String;
+ }
+
+ return;
+}
+
+
+VOID
+HalpNextVGALine(
+ VOID
+ )
+{
+ if (HalpRow==HalpDisplayText-1) {
+ HalpScrollVGADisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+}
+
+VOID
+HalpScrollVGADisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Scrolls the text on the display up one line.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUSHORT NewStart;
+ ULONG i;
+
+
+ NewStart = VideoBuffer+HalpDisplayWidth;
+ MegaMoveMemory((PVOID)VideoBuffer, (PVOID)NewStart, (HalpDisplayText-1)*HalpDisplayWidth*sizeof(USHORT));
+
+ for (i=(HalpDisplayText-1)*HalpDisplayWidth; i<HalpDisplayText*HalpDisplayWidth; i++) {
+ VideoBuffer[i] = (REVERSE_ATTRIBUTE << 8) | ' ';
+ }
+}
+
+VOID
+HalpPutVGACharacter(
+ UCHAR Character
+ )
+{
+ PUSHORT cp = (PUSHORT)VideoBuffer;
+ int x = HalpColumn;
+ int y = HalpRow;
+
+ cp[y*HalpDisplayWidth + x] = (USHORT)((REVERSE_ATTRIBUTE << 8) | (Character ));
+}
+
+
+VOID
+HalpClearVGADisplay(
+ VOID
+ )
+{
+ ULONG i;
+ PUSHORT cp = (PUSHORT)VideoBuffer;
+ USHORT Attribute = (REVERSE_ATTRIBUTE << 8) | ' ';
+
+ for(i=0; i < HalpDisplayText*HalpDisplayWidth; i++) {
+ VideoBuffer[i] = Attribute;
+ }
+
+ HalpColumn=0;
+ HalpColumn=0;
+}
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ HARDWARE specific Part of Display routines
+
+ this part of this file deals with special Hardware parts of some
+ graphic adapters (RamDac, Clock Generator, VGA Chipsets etc.
+
+-------------------------------------------------------------------*/
+
+VOID
+DownLoadVGAFont(
+ VOID
+ )
+/*+++
+
+ The Space occupied for 1 caracter in the charackter generator memory of an VGA
+ is 0x20 bytes, The font itself uses only 8 bytes, so we skip over the difference
+
+---*/
+{
+
+ PUCHAR dst = (PUCHAR)FontBuffer;
+ PUCHAR src = (PUCHAR)font_8x8;
+ long i, count = 256;
+
+ INIT_VGA_FONT();
+
+ while(count--){
+ for (i=0; i<8; i++)
+ *dst++ = *src++;
+ dst += 0x18;
+ }
+ EXIT_VGA_FONT() ;
+}
+
+VOID
+HalpInitializeVGADisplay(
+ TEXT_MODE TextMode
+ )
+{
+
+static UCHAR _80x50_crt_regs [MAX_CRT] = { // 80x50 text mode
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, // cr0 - cr4
+ 0x81, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char
+ 0x20, 0x00, 0x00, 0x00, 0x00, // cra - cursor off
+ 0x00, 0x9c, 0x8e, 0x8f, 0x28,
+ 0x1f, 0x96, 0xb9, 0xa3, 0xff
+ };
+
+static UCHAR _132x50_crt_regs [MAX_CRT] = { // 132x50 text mode
+ 0xa0, 0x83, 0x84, 0x83, 0x8a, // cr0 - cr4
+ 0x9e, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char
+ 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x9c, 0x85, 0x8f, 0x42,
+ 0x1f, 0x95, 0xa5, 0xa3, 0xff
+ };
+
+static UCHAR default_graph_regs[GRAPH_MAX] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x0e, 0x00, 0xff
+ };
+
+static UCHAR default_pal_regs[MAX_PALETTE] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x14, 0x7, 0x38, 0x39,
+ 0x3A, 0x3B, 0x3C, 0x3d, 0x3e,
+ 0x3f, 0x08, 0x00, 0x0f, 0x00,
+ 0x00
+ };
+
+ int i;
+ UCHAR byte;
+
+ // reset ATC FlipFlop
+ byte = READ_REGISTER_UCHAR(VGA_ATC_FF);
+ WRITE_REGISTER_UCHAR(VGA_ATC_DATA, 0); // Disable palette
+
+ // stop the sequencer
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0100);
+
+ if (TextMode == TEXT_132x50) {
+ // external clock (40MHz)
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0xAF);
+ } else {
+ // COLOR registers , enable RAM, 25 MHz (???) 400 Lines,
+ if (HalpVideoChip == VGA_P9100) {
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x67) ; // 28.322 Mhz
+ } else {
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63) ; // 25,175 MHz (don't use with P9100).
+ }
+ }
+
+ // Select the timing sequencer values
+ // 8 dot/char
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0101);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0302);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0003);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0204);
+
+ // start the sequencer
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0300);
+
+ // Unprotect CRT regs and program them
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX , 0x0011);
+
+ for(i=0; i<MAX_CRT; i++) {
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, i);
+ if (TextMode == TEXT_132x50){
+ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _132x50_crt_regs[i]);
+ } else {
+ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _80x50_crt_regs[i]);
+ }
+ }
+
+ DownLoadVGAFont();
+
+ HalpDisplayWidth = (TextMode == TEXT_132x50) ? 132 : 80;
+ HalpDisplayText = 50;
+
+ HalpClearVGADisplay();
+
+ i = READ_REGISTER_UCHAR(VGA_ATC_FF); // Reset attr FF
+
+ if (!HalpFirstBoot) {
+
+ //
+ // if this is not the First Boot
+ // i.e. an Bugcheck; we have to setup
+ // the Attribute and colors of the VGA PART
+ //
+
+ for(i=0; i<GRAPH_MAX; i++) {
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX , i);
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, default_graph_regs[i]);
+ }
+
+ for(i=0; i<MAX_PALETTE; i++) { // PALETTE (ATC)
+ WRITE_REGISTER_UCHAR(VGA_ATC_IDX , i);
+ WRITE_REGISTER_UCHAR(VGA_ATC_DATA, default_pal_regs[i]);
+ }
+
+ }
+
+ WRITE_REGISTER_UCHAR(VGA_DAC_MASK , 0xff);
+
+ //
+ // set the 16 base colors for text mode in the DAC
+ //
+
+ WRITE_REGISTER_UCHAR(VGA_DAC_WRITE_INDEX, 0x00);
+ for(i=0; i<48; i++) {
+ WRITE_REGISTER_UCHAR(VGA_DAC_DATA, base_colors[i]);
+ }
+
+ WRITE_REGISTER_UCHAR(VGA_ATC_IDX, 0x20);
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer
+}
+
+VOID
+HalpResetP9100(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA part of an Orchid P9000VLB or Diamond Viper card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LONG IcdVal;
+ int i;
+
+ //
+ // First, reprogram register broken by the p9100 driver
+ //
+
+ switch (HalpMainBoard) {
+ case M8036:
+ WRITE_REGISTER_UCHAR (0xbfcc0000, 0x00); // RM200
+ break;
+ case M8042 :
+ WRITE_REGISTER_UCHAR (0xbc010000, 0xff); // RM400 MT
+ break;
+ case M8032 :
+ WRITE_REGISTER_UCHAR (0xbc0c0000, 0xff); // RM400 T
+ break;
+ }
+
+ //
+ // unlock and disable the P9000 on the board
+ //
+
+ WRITE_REGISTER_UCHAR (VGA_SEQ_IDX, 0x11);
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA,0x00); // unlock extended SEQ reg
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA,0x00);
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA,0x00);
+ WRITE_REGISTER_UCHAR (VGA_SEQ_IDX, 0x12); // select extended reg 0x12
+
+ if (HalpVideoBoard == P9000_ORCHID) {
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA, 0x08);
+ } else {
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA, 0x88);
+ }
+
+ //
+ // init the clock generator, we use use the 80x50 Text mode
+ // so we need a 25.175Mhz clock
+ //
+
+// if(( IcdVal = ICD2061CalcClockgen(25175)) == -1){
+// DebugPrint(("HAL: Error calculating ICD Value for 25.175Mhz\n"));
+// }
+
+// byte = READ_REGISTER_UCHAR((PUCHAR) VGA_MISC_WRITE);
+ IcdVal = 0x7170a0;ICD2061LoadClockgen((PUCHAR) VGA_MISC_WRITE , IcdVal, 2);
+ IcdVal = 0x01a8bc;ICD2061LoadClockgen((PUCHAR) VGA_MISC_WRITE , IcdVal, 2);
+ IcdVal = 0x2560ac;ICD2061LoadClockgen((PUCHAR) VGA_MISC_WRITE , IcdVal, 2);
+ IcdVal = 0x4560ac;ICD2061LoadClockgen((PUCHAR) VGA_MISC_WRITE , IcdVal, 2);
+// WRITE_REGISTER_UCHAR((PUCHAR) VGA_MISC_WRITE,byte);
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x67) ; // 28.322 Mhz - crt ad = 3dx
+
+ //
+ // if this is the first initialisation i.e. Systemboot,
+ // the firmware has initialized the VGA part properly
+ //
+
+ if (HalpFirstBoot) return;
+
+ WRITE_REGISTER_UCHAR( P9100_CFG_IDX, P9100_CONFIG_REG); // enable VGA
+ WRITE_REGISTER_UCHAR( P9100_CFG_DATA, 0x02);
+
+ WRITE_REGISTER_UCHAR( P9100_CFG_IDX, P9100_COMMAND_REG); // enable I/O space - ctl VGA palette snoop
+ WRITE_REGISTER_UCHAR( P9100_CFG_DATA, 0x83);
+
+ WRITE_REGISTER_UCHAR( P9100_CFG_IDX, P9100_MEM_BASE_ADDR_REG); // why not...
+ WRITE_REGISTER_UCHAR( P9100_CFG_DATA, 0x00);
+
+ // init ramdac (bug workaround + other unknown things...)
+ WRITE_REGISTER_UCHAR( P9100_CFG_IDX, P9100_CONFIG_REG); // enable VGA
+ WRITE_REGISTER_UCHAR( P9100_CFG_DATA, 0x00);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x90909090);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x01010101);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x03030303);
+
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x70707070);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x01010101);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x40404040);
+
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x0a0a0a0a);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x02020202);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x40404040);
+
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x71717171);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x01010101);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x40404040);
+
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x71717171);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x01010101);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x00000000);
+
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x02020202);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x01010101);
+ for(i=2;i <= 0x72; ++i) {
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x00000000);
+ }
+
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_HIGH_ADDR, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_CTRL, 0x00000000);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x02020202);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x01010101);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x0a0a0a0a);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x03030303);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x14141414);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x0e0e0e0e);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x20202020);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x24242424);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_LOW_ADDR, 0x21212121);
+ WRITE_REGISTER_ULONG( P9100_RAMDAC_DATA, 0x30303030);
+
+ WRITE_REGISTER_UCHAR( P9100_CFG_IDX, P9100_CONFIG_REG); // enable VGA
+ WRITE_REGISTER_UCHAR( P9100_CFG_DATA, 0x02);
+
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x67) ; // 28.322 Mhz - crt ad = 3dx
+
+}
+
+VOID
+HalpResetP9000(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA part of an Orchid P9000VLB or Diamond Viper card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LONG IcdVal;
+
+ //
+ // unlock and disable the P9000 on the board
+ //
+
+ WRITE_REGISTER_UCHAR (VGA_SEQ_IDX, 0x11);
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA,0x00); // unlock extended SEQ reg
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA,0x00);
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA,0x00);
+ WRITE_REGISTER_UCHAR (VGA_SEQ_IDX, 0x12); // select extended reg 0x12
+
+ if (HalpVideoBoard == P9000_ORCHID) {
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA, 0x08);
+ } else {
+ WRITE_REGISTER_UCHAR (VGA_SEQ_DATA, 0x88);
+ }
+
+
+ //
+ // init the clock generator, we use use the 80x50 Text mode
+ // so we need a 25.175Mhz clock
+ //
+
+ if(( IcdVal = ICD2061CalcClockgen(25175)) == -1){
+ DebugPrint(("HAL: Error calculating ICD Value for 25.175Mhz\n"));
+ }
+
+ ICD2061LoadClockgen((PUCHAR) VGA_MISC_WRITE , IcdVal, 2);
+
+ //
+ // if this is the first initialisation i.e. Systemboot,
+ // the firmware has initialized the VGA part properly
+ //
+
+ if (HalpFirstBoot) return;
+
+ //
+ // reset the RamDac (Bt485) to VGA mode, no clock doubler
+ //
+
+ WRITE_REGISTER_UCHAR( Bt485_CR0, 0xa0); // 6 bit operations, no sync on colors
+ WRITE_REGISTER_UCHAR( Bt485_CR1, 0x00); //
+// WRITE_REGISTER_UCHAR( Bt485_CR1, 0x40); //
+ WRITE_REGISTER_UCHAR( Bt485_CR2, 0x00); // select VGA port
+
+ // enable CR3 via CR0
+
+ WRITE_REGISTER_UCHAR( Bt485_ADDR, 0x01);
+ WRITE_REGISTER_UCHAR( Bt485_CR3, 0x00); // disable clock multiplier
+ WRITE_REGISTER_UCHAR( Bt485_MASK, 0xff);
+
+}
+
+VOID
+HalpResetS3Chip(
+ VOID
+ )
+/*+++
+
+ This function resets/loads default values to the S3 Chip
+ extended registers
+
+ this code is borrowed/derived from the s3 miniport driver
+
+---*/
+{
+ UCHAR byte;
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0140); // Enable the enhanced 8514 registers
+ WRITE_REGISTER_USHORT(S3_ADVFUNC_CNTL, 0x02); // reset to normal VGA operation
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0032); // Backward Compat 3
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0035); // CRTC Lock
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // async reset
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x01); //
+
+ WRITE_REGISTER_UCHAR(VGA_FEAT_CNTRL, 0x00); // normal sync
+ WRITE_REGISTER_UCHAR(VGA_MISC_READ, 0x00); //
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8531);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x2033); // Backward Compat 2
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0034); // Backward Compat 3
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x853a); // S3 Misc 1
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x5a3b); // Data Transfer Exec Pos
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x103c); // Interlace Retrace start
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // start the sequencer
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); //
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa640); // VLB: 3Wait
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x1841);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0050);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0051);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff52);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x3854);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0055);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0056);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0057);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8058); // ISA Latch ? (bit 3)
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005c);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005d);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005e);
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0760);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8061);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa162);
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0043); // Extended Mode
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0045); // HW graphics Cursor Mode
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0046); // HW graphics Cursor Orig x
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff47); // HW graphics Cursor Orig x
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xfc48); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff49); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4a); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4b); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4c); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4d); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4e); // Dsp Start x pixel pos
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xdf4f); // Dsp Start y pixel pos
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0042); // select default clock
+
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63); // Clock select
+/*
+// this should be done in the InitializeVGA code ...
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer
+*/
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs
+
+}
+
+VOID
+HalpResetCirrusChip(
+ VOID
+ )
+/*+++
+
+ This function resets/loads default values to the Cirrus Chip
+ extended registers for use with extended text mode (80x50)
+
+ Register values found in the cirrus manual, appendix D5
+
+---*/
+{
+ UCHAR byte;
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer
+
+ // extended sequencer and crtc regs for cirrus
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // unlock the extended registers
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x4008);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x5709);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x180a);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x660b);
+
+ // new modifs
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x000f);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0016);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x001b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x0009);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000a);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000b);
+ // end new modifs
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0010);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0011);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0012);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0013);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0018);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0119);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x001a);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x2f1c);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x301d);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x331e);
+
+}
+
+BOOLEAN
+ICD2061LoadClockgen(
+ PUCHAR port,
+ ULONG data,
+ LONG bitpos
+ )
+/*++
+
+Routine Description:
+
+ The ICD2061LoadClockgen() routine.
+ This routine loads the ICD206x Clock Generator with the given data
+ The circuit is programmed serial over 2 data Lines lines; clock and data
+ On an Plaisir Graphics board clock bit is bit 0
+ data bit is bit 1
+ On most VGA with an ICD2061 the lines are connected over the VGA_MISC Register
+ clock bit is bit 2
+ data bit is bit 3
+
+Arguments:
+
+ Arguments: the port for programming
+ the value
+ the BitPosition of the output port for clock and data line
+
+Return Value:
+
+ TRUE on success
+
+--*/
+{
+#define w_icd(x) WRITE_REGISTER_UCHAR(port, mask & (x))
+
+ ULONG tmp;
+ LONG i;
+ UCHAR mask = 0x3; // 00000011
+ UCHAR ck0 = 0x0; // Clock Bit = low
+ UCHAR ck1 = 0x1; // Clock Bit = high
+ UCHAR dat0 = 0x0; // Data Bit = low
+ UCHAR dat1 = 0x2; // Data Bit = high
+ ULONG shift = bitpos + 1; // Data bit
+
+ mask = mask << bitpos;
+ ck1 = ck1 << bitpos;
+ dat1 = dat1 << bitpos;
+
+ tmp = 0;
+ for (i=0; i<5; i++) {
+ w_icd(ck0 | dat1); // unlock bit 1-5
+ w_icd(ck1 | dat1);
+ }
+ w_icd(ck0 | dat0); // end of unlock sequence
+ w_icd(ck1 | dat0);
+ w_icd(ck0 | dat0); // start bit falling
+ w_icd(ck1 | dat0); // start bit rising
+
+ for (i=0; i<24; i++) { // write the 24 bits of data
+ w_icd(ck1 | (UCHAR)(((~data)&1)<<shift));
+ w_icd(ck0 | (UCHAR)(((~data)&1)<<shift));
+ w_icd(ck0 | (UCHAR)((data&1)<<shift));
+ w_icd(ck1 | (UCHAR)((data&1)<<shift));
+ data >>= 1;
+ }
+
+ w_icd(ck1 | dat1);
+ w_icd(ck0 | dat1); // stop bit
+ w_icd(ck1 | dat1); // stop bit
+ w_icd(0); // select REG0 video frequency
+
+
+ return (TRUE);
+}
+#undef w_icd
+
+LONG
+ICD2061CalcClockgen(
+ LONG freq
+ )
+/*++
+
+Routine Description:
+
+ The ICD2061CalcClockgen() routine.
+ This routine calculates the data for the ICD2062/ ICD2061 Clock Generator from the
+ given pixel frequency (in kHz).
+ The frequency in is kHz rather than MHz because the kernel does not support
+ floating point, and this routine had to be converted to integer.
+
+Arguments:
+
+ requested frequency.
+
+Return Value:
+
+ (-1), on error
+ the calculated data word, otherwise
+
+--*/
+{
+ int p, q, qlow, qhigh, bestp, bestq, mux, index;
+ int diff, bestdiff;
+ int fref = 14318;
+ int fvco, fcalc, qoverp;
+
+// check that frequency is derivable
+ if (freq < 625) return (-1);
+ else if (freq < 1250) mux = 6;
+ else if (freq < 2500) mux = 5;
+ else if (freq < 5000) mux = 4;
+ else if (freq < 10000) mux = 3;
+ else if (freq < 20000) mux = 2;
+ else if (freq < 40000) mux = 1;
+ else if (freq < 160000) mux = 0;
+ else return (-1);
+
+// calculate the index field
+ fvco = (1 << mux) * freq;
+
+ if (fvco < 40000) index = 0;
+ else if (fvco < 47500) index = 1;
+ else if (fvco < 52200) index = 2;
+ else if (fvco < 56300) index = 3;
+ else if (fvco < 61900) index = 4;
+ else if (fvco < 65000) index = 5;
+ else if (fvco < 68100) index = 6;
+ else if (fvco < 82300) index = 7;
+ else if (fvco < 86000) index = 8;
+ else if (fvco < 88000) index = 9;
+ else if (fvco < 90500) index = 10;
+ else if (fvco < 95000) index = 11;
+ else if (fvco < 100000) index = 12;
+ else index = 13;
+
+ qoverp = 1000 * 2 * fref / fvco;
+ qlow = (fref + 500)/1000;
+ qhigh = (fref * 5 - 500)/1000;
+ bestp = bestq = 0;
+ bestdiff = 10000;
+
+ for (p = 130; p >= 4; p--) {
+ q = (int)((qoverp * p + 500)/1000);
+ if ((q < qlow) || (q > qhigh)) continue;
+ fcalc = 2 * fref * p / q;
+ if (fcalc > fvco) diff = fcalc - fvco;
+ else diff = fvco - fcalc;
+ if (diff < bestdiff) {
+ bestdiff = diff;
+ bestp = p;
+ bestq = q;
+ }
+ }
+
+ if ((bestp == 0) || (bestq == 0)) return (-1);
+
+ return ( (index << 17) |
+ ((~(130 - bestp) & 0x7f) << 10) |
+ (mux << 7) |
+ (~(129 - bestq) & 0x7f) );
+}
+
+
diff --git a/private/ntos/nthals/halsni4x/mips/snihalp.h b/private/ntos/nthals/halsni4x/mips/snihalp.h
new file mode 100644
index 000000000..1967a0b91
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/snihalp.h
@@ -0,0 +1,338 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/snihalp.h,v 1.1 1995/05/19 11:24:26 flo Exp $")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ SNIhalp.h, original file jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ SNI specific interfaces, defines and structures.
+
+
+--*/
+
+#ifndef _SNIHALP_
+#define _SNIHALP_
+#include "SNIdef.h"
+
+//
+// Determine if an virtual address is really a physical address.
+//
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+#define IS_KSEG0_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG1_BASE)) ? TRUE : FALSE)
+
+#define IS_KSEG1_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG1_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+#define KSEG0_TO_KSEG1(Va) { \
+ Va &= ~KSEG0_BASE; \
+ Va |= KSEG1_BASE; \
+ }
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpOnboardControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+extern PVOID HalpEisaMemoryBase;
+
+extern BOOLEAN HalpEisaExtensionInstalled;
+extern BOOLEAN HalpIsRM200;
+extern BOOLEAN HalpIsMulti;
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// possibly processor types for SNI machines ...
+//
+
+typedef enum _HalpProcessorType {
+ ORIONSC, // Orion + Writeback secondary cache
+ MPAGENT, // R4000 + MpAgent
+ R4x00, // R4000 SC
+ UNKNOWN // not yet identified (initial value)
+} HalpProcessorType;
+
+//
+// Kind of processor of SNI machines
+//
+
+extern HalpProcessorType HalpProcessorId;
+
+#define HalpR4600 32
+
+//
+// possibly moterboard types for SNI machines ...
+//
+
+typedef enum _MotherBoardType {
+ M8022 = 2, // RM400-10 mother board
+ M8022D = 3, // RM400-10 mother board (new PCB)
+ M8032 = 4, // RM400 Tower
+ M8042 = 5, // RM400 Minitower
+ M8036 = 7 // RM200 Desktop
+} MotherBoardType;
+
+//
+// Kind of Mainboard of SNI machines
+//
+
+extern MotherBoardType HalpMainBoard;
+
+//
+// Define map register translation entry structure.
+//
+
+typedef struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ INTERFACE_TYPE InterfaceType;
+} ADAPTER_OBJECT;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern POBJECT_TYPE *IoAdapterObjectType;
+
+extern BOOLEAN LessThan16Mb;
+extern BOOLEAN HalpEisaDma;
+
+//
+// Map buffer parameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+extern ULONG HalpBusType;
+
+//
+// Firmware interface
+//
+
+typedef struct {
+ CHAR (*getchar)();
+ PCHAR (*gets)();
+ VOID (*printf)();
+ PCHAR (*parsefile)();
+ VOID (*reinit_slave)();
+} SNI_PRIVATE_VECTOR;
+
+//
+// Define function prototypes.
+//
+
+
+ULONG
+HalpGetStatusRegister(
+ VOID
+ );
+
+ULONG
+HalpSetStatusRegister(
+ ULONG Value
+ );
+
+ULONG
+HalpGetCauseRegister(
+ VOID
+ );
+
+ULONG
+HalpSetCauseRegister(
+ ULONG value
+ );
+
+ULONG
+HalpGetConfigRegister(
+ VOID
+ );
+
+ULONG
+HalpSetConfigRegister(
+ ULONG value
+ );
+
+BOOLEAN
+HalpMapIoSpace(
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntStructures(
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntMultiStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ IN INTERFACE_TYPE Interface
+ );
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableOnboardInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableOnboardInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+BOOLEAN
+HalpRM200Int0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400TowerInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInt1Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int3Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int4Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpRM400Int5Process (
+ );
+
+VOID
+HalpSystemInit(
+ VOID
+ );
+
+VOID
+HalpDisplayCopyRight(
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt(
+ VOID
+ );
+
+VOID
+HalpInitMPAgent(
+ ULONG Number
+ );
+
+ULONG
+HalpOrionIdentify(
+ VOID
+ );
+
+BOOLEAN
+HalpMpAgentIdentify(
+ VOID
+ );
+
+#endif // _SNIHALP_
diff --git a/private/ntos/nthals/halsni4x/mips/sniregs.h b/private/ntos/nthals/halsni4x/mips/sniregs.h
new file mode 100644
index 000000000..83456a9b9
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/sniregs.h
@@ -0,0 +1,139 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/sniregs.h,v 1.1 1994/10/13 15:47:06 holli Exp $")
+/*++
+
+Copyright (c) 1993 SNI
+
+Module Name:
+
+ SNIregs.h
+
+Abstract:
+
+ This module is the header file that describes hardware structures
+ for the system board registers
+ The System addresses are found in SNIdef.h
+
+--*/
+
+#ifndef _SNIREGS_
+#define _SNIREGS_
+
+
+/*******************************************************************
+** Description of the R4x000 ASIC Chipset registers for SNI Machines
+**
+** 32 bits access only
+*******************************************************************/
+
+//
+// UCONF register
+//
+
+#define UCONF_ENSCMODE (1<<0) /* Secondary mode valid for R4000 */
+#define UCONF_ENEXTINT (1<<1) /* External interruption request */
+#define UCONF_NMI (1<<5) /* Interrupt level for NMI */
+#define UCONF_NMI_MSK (1<<6) /* Interrupt mask for NMI */
+#define UCONF_MDINT (1<<7) /* Select test mode for interruptions */
+#define UCONF_INT0_MSK (1<<8) /* Interrupt mask for INT0 ( eisa ) */
+#define UCONF_INT1_MSK (1<<9) /* Interrupt mask for INT1 ( scci 1, 2 ) */
+#define UCONF_INT2_MSK (1<<10) /* Interrupt mask for INT2 ( duart 2681 ) */
+#define UCONF_INT3_MSK (1<<11) /* Interrupt mask for INT3 ( timer 8254 ) */
+#define UCONF_INT4_MSK (1<<12) /* Interrupt mask for INT4 ( lance ) */
+#define UCONF_INT5_MSK (1<<13) /* Interrupt mask for INT5 ( dbg button ) */
+#define UCONF_INT0 (1<<14) /* Interrupt level for INT0 ( eisa ) */
+#define UCONF_INT1 (1<<15) /* Interrupt level for INT1 ( scci 1, 2 ) */
+#define UCONF_INT2 (1<<16) /* Interrupt level for INT2 ( duart 2681 ) */
+#define UCONF_INT3 (1<<17) /* Interrupt level for INT3 ( timer 8254 ) */
+#define UCONF_INT4 (1<<18) /* Interrupt level for INT4 ( lance ) */
+#define UCONF_INT5 (1<<19) /* Interrupt level for INT5 ( dbg button ) */
+#define UCONF_ENCPUHIT (1<<20) /* Enable address comparators */
+#define UCONF_ENCKDATA (1<<25) /* Enable check bits on data read */
+#define UCONF_SYSCMD0 (1<<26)
+#define UCONF_SYSCMD1 (1<<27)
+#define UCONF_SYSCMD2 (1<<28)
+#define UCONF_SYSCMD3 (1<<29)
+
+#define UCONF_INT UCONF_INT4|UCONF_INT0
+
+//
+// IOADTIMEOUT2 & IOADTIMEOUT1
+//
+
+#define IO_HOLD (1<<0) /* The R4K_CS request the IO bus */
+#define IO_HLDA (1<<1) /* The IO arbitrer acknowledge */
+#define IO_HWR (1<<3) /* Set to 1 for a write IO cycle */
+#define IO_HADR_MASK 0x3FFFFFF8 /* IO address (29:3) in progress */
+
+//
+// IOMEMCONF
+//
+
+
+#define IOMEM_RAFPER 8 /* Select Refresh Period */
+#define IOMEM_SELRC (1<<4) /* Select fast Ttc time on memory */
+#define IOMEM_SELRAF (1<<5) /* Select fast refresh precharge */
+#define IOMEM_SELSIDE (1<<6) /* Select dual side SIPS */
+#define IOMEM_SELDD (1<<7) /* Select DD pattern for memory */
+#define IOMEM_SEL16MB (1<<8) /* Select 16 Mb technology SIPS */
+#define IOMEM_SELDHOLD (1<<9) /* Select long hold time on data write */
+#define IOMEM_DISHLDA (1<<15) /* Mask arbitrer acknowledge */
+#define IOMEM_ENRDCMP (1<<16) /* Enable anticipation on IO read */
+#define IOMEM_ENWRCMP (1<<20) /* Enable bufferisation on IO write */
+#define IOMEM_ENIOTMOUT (1<<21) /* Enable output timeout */
+#define IOMEM_SELIODD (1<<22) /* Enable fast mode for IO burst DD */
+#define IOMEM_MDTIMEOUT (1<<23) /* Select short timeout */
+
+#define BANK_16 0
+#define BANK_32 IOMEM_SELSIDE
+#define BANK_64 IOMEM_SEL16MB
+#define BANK_128 IOMEM_SEL16MB | IOMEM_SELSIDE
+
+#define IOMEM_INIT IOMEM_RAFPER /* Initial register load */
+
+//
+// IOMMU
+//
+
+#define IOMMU_SWAP 0x7fff /* all segments swapped */
+#define IOMMU_BITS 0x0000 /* all segments 32 bits */
+
+
+//
+// DMACCESS & DMAHIT
+//
+
+#define DMA_COUNT_MASK 0x0000FFFF /* Count mask (15:0) */
+
+
+//
+// MACHINE STATUS REGISTER (MSR)
+//
+
+/* SNI machine status register information */
+
+#define MSR_VSYNC (1<<0) /* active high - video synchronization */
+#define MSR_TEMP (1<<1) /* active high - excessive temperature */
+#define MSR_LINEGOOD (1<<2) /* active low - power good */
+#define MSR_TIMER1 (1<<3) /* active low - int timer 1 */
+#define MSR_TIMER0 (1<<4) /* active low - int timer 0 */
+#define MSR_DBG_BUT (1<<5) /* active low - debug button int */
+#define MSR_TIMEOUT (1<<6) /* active low - timeout int */
+#define MSR_BAT_EN (1<<7) /* active high - batteries connected */
+
+//
+// MACHINE CONFIGURATION REGISTER (MCR)
+//
+
+/* SNI machine configuration register */
+
+#define MCR_TEMPBATACK (1<<0) /* active high - Disable / clear TEMP an Temp info */
+#define MCR_POWER_OFF (1<<1) /* active high - Stop power */
+#define MCR_STOP_BAT (1<<2) /* active high - Stop batteries */
+#define MCR_PODD (1<<3) /* active high - Select ODD parity R4K_CS */
+#define MCR_INRESET (1<<5) /* active high - Reset board */
+#define MCR_ENBREAK (1<<7) /* active high - Enable Break Duart B machine reset */
+
+
+#define LINEGOOD_L MSR_LINEGOOD /* high : powerfail */
+
+#endif // _SNIREGS_
diff --git a/private/ntos/nthals/halsni4x/mips/unicache.s b/private/ntos/nthals/halsni4x/mips/unicache.s
new file mode 100644
index 000000000..d91a0f13a
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/unicache.s
@@ -0,0 +1,1098 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halvlbms/src/hal/halsni4x/mips/RCS/unicache.s,v 1.1 1995/05/19 11:26:20 flo Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// unicache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// MIPS R4000 Uni Processor machine.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+//
+// Note: On the SNI machines all single processor machines are configured in the Firmware
+// tree with the size of the Primary cache matching the physical size.
+// So, even Orion CPU are configured with 16KB not 2 sets of 8Kb.
+// In this case wqe can use the Routines special for Orion CPU also for
+// R4400 CPU.
+//
+
+#if!defined(ORION)
+#define ORION
+#endif
+
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFlushDcachePageUni)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, FLUSH_DCACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageUni
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalpPurgeDcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeDcachePageUni)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, PURGE_DCACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeDcachePageUni
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeIcachePageUni)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, PURGE_ICACHE_PAGE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeIcachePageUni
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheUni (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheUni)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, SWEEP_DCACHE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5)
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+
+#if defined(ORION)
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10:
+ cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+
+30:
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5)
+#endif
+
+ j ra // return
+
+ .end HalpSweepDcacheUni
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+#if defined(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // do other set on Orion
+#endif
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheUni (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheUni)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+ la t0, HalpLedAddress // get the address for the LED register
+ lw t0, 0(t0)
+ lw t1, KiPcr + PcSetMember(zero) // get a bitmapped value for Processor Number
+ or t1, t1, SWEEP_ICACHE // what are we doing ?
+ xor t1, t1, 0xff // inverse
+ sb t1, 0(t0) // display it
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+
+#if defined(ORION)
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0)
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalpSweepIcacheUni
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+10:
+
+ cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0) // do set B first on Orion
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageUni (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalpZeroPageUni, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,ZpA1(sp) // get old color bits
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpZeroPageUni
diff --git a/private/ntos/nthals/halsni4x/mips/vgadata.h b/private/ntos/nthals/halsni4x/mips/vgadata.h
new file mode 100644
index 000000000..a98ee7e65
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/vgadata.h
@@ -0,0 +1,406 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/vgadata.h,v 1.1 1994/10/13 15:47:06 holli Exp flo $")
+
+#define MAX_CRT 0x19
+#define GRAPH_MAX 0x9
+#define MAX_PALETTE 0x15
+
+// VGA constants
+
+#define REVERSE_ATTRIBUTE 0x17 // white on blue
+
+#define INIT_VGA_FONT() \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x05); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x08); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x01);
+
+#define EXIT_VGA_FONT() \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x00); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x05); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x10); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x0e);
+
+
+//
+// Adresses for the Bt485 RamDac on the Orchid VLB and Diamond Viper board
+//
+
+#define Bt485_MASK ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c6))
+#define Bt485_ADDRRD ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c7))
+#define Bt485_ADDR ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c8))
+#define Bt485_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c9))
+#define Bt485_CR0 ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c6))
+#define Bt485_ADDRCURRD ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c7))
+#define Bt485_ADDRCUR ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c8))
+#define Bt485_DATACUR ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c9))
+#define Bt485_STATUS ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c6))
+#define Bt485_CR3 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c6)) /* if enabled */
+#define Bt485_CURSORRAM ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c7))
+#define Bt485_CR1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c8))
+#define Bt485_CR2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c9))
+#define Bt485_CURSOR_YL ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c6))
+#define Bt485_CURSOR_YH ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c7))
+#define Bt485_CURSOR_XL ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c8))
+#define Bt485_CURSOR_XH ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c9))
+
+// Some VGA Registers
+
+#define VGA_MISC_READ ((PVOID) ((ULONG)HalpVGAControlBase + 0x03cc))
+#define VGA_MISC_WRITE ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c2))
+#define VGA_SEQ_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c4))
+#define VGA_SEQ_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c5))
+#define VGA_CRT_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03d4))
+#define VGA_CRT_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03d5))
+#define VGA_ATC_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c0))
+#define VGA_ATC_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c0))
+#define VGA_GRAPH_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03ce))
+#define VGA_GRAPH_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03cf))
+#define VGA_ATC_FF ((PVOID) ((ULONG)HalpVGAControlBase + 0x03da))
+#define VGA_DAC_MASK ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c6))
+#define VGA_DAC_STATUS ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c7))
+#define VGA_DAC_WRITE_INDEX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c8))
+#define VGA_DAC_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c9))
+#define VGA_FEAT_CNTRL ((PVOID) ((ULONG)HalpVGAControlBase + 0x03ca))
+#define S3_ADVFUNC_CNTL ((PVOID) ((ULONG)HalpVGAControlBase + 0x4ae8))
+
+// the same registers as offset for use in SetHwMode()
+
+#define MISC_READ 0x03cc
+#define MISC_WRITE 0x03c2
+#define SEQ_IDX 0x03c4
+#define SEQ_DATA 0x03c5
+#define CRT_IDX 0x03d4
+#define CRT_DATA 0x03d5
+#define ATC_IDX 0x03c0
+#define ATC_DATA 0x03c0
+#define GRAPH_IDX 0x03ce
+#define GRAPH_DATA 0x03cf
+#define ATC_FF 0x03da
+#define DAC_MASK 0x03c6
+#define DAC_STATUS 0x03c7
+#define DAC_WRITE_INDEX 0x03c8
+#define DAC_DATA 0x03c9
+#define FEAT_CNTRL 0x03ca
+
+// S3 Advanced Function control register
+
+#define ADVFUNC_CNTL 0x4ae8
+
+#define MAGIC_REG1 0x46e8
+#define MAGIC_REG2 0x0102
+#define CIRRUS_MAGIC1 0x03c3
+#define CIRRUS_MAGIC2 0x0094
+
+//
+// "magic" registers to enable the Video System on VGA
+// for non Intel Systems
+//
+#define VGA_MAGIC_REG1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x46e8))
+#define VGA_MAGIC_REG2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x0102))
+#define CIRRUS_MAGIC_REG1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c3))
+#define CIRRUS_MAGIC_REG2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x0094))
+
+
+UCHAR base_colors[] = {
+ 0, 0, 0, // color 0 (black)
+ 0, 0, 42, // color 1 (drk. blue)
+ 0, 42, 0, // color 2 (olive)
+ 0, 42, 42, // color 3 ()
+42, 0, 0, // color 4 (brown)
+42, 0, 42, // color 5 (turquise)
+42, 21, 0, // color 6 (tundra )
+63, 63, 63, // color 7 (lt. grey(42,42,42 but we set it to white)
+21, 21, 21, // color 8 (drk. grey)
+21, 21, 63, // color 9 (blue)
+21, 63, 21, // color 10 (green)
+21, 63, 63, // color 11 (lt. blue)
+63, 0, 0, // color 12 (red)
+63, 0, 63, // color 13 (cyan)
+63, 63, 0, // color 14 (yellow)
+63, 63, 63 // color 15 (white)
+};
+
+//
+// this is an VGA 8x8 font (Codepage 437)
+//
+
+UCHAR font_8x8[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0x00
+0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, //0x01
+0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, //0x02
+0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, //0x03
+0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
+0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
+0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
+0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
+0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
+0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
+0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
+0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
+0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
+0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
+0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
+0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
+0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
+0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
+0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
+0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
+0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
+0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
+0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
+0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
+0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
+0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
+0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
+0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
+0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
+0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
+0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
+0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
+0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
+0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, // =
+0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, // >
+0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, // ?
+0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, // @
+0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, // A
+0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, // B
+0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, // C
+0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, // D
+0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, // E
+0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
+0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
+0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
+0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
+0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
+0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
+0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
+0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
+0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
+0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
+0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
+0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
+0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
+0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
+0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
+0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
+0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
+0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
+0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
+0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
+0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
+0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
+0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
+0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
+0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
+0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
+0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
+0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
+0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
+0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, // 8 bit codes 0x80
+0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x81 ü
+0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x82 é
+0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, // 0x83 â
+0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x84 ä
+0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x85 à
+0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x86°a
+0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, // 0x87,c
+0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, // 0x88 ê
+0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x89 ..e
+0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x8a è
+0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, // 0x8b ..i
+0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, // 0x8c î
+0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, // 0x8d ì
+0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, // 0x8e Ä
+0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, // 0x8f °A
+0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, // 0x90
+0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, // 0x91
+0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, // 0x92
+0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x93 ô
+0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x94 ö
+0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x95 ò
+0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x96 û
+0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x97 ù
+0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, // 0x98 ..y
+0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, // 0x99 Ö
+0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, // 0x9a ü
+0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, // 0x9b
+0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, // 0x9c
+0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, // 0x9d
+0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, // 0x9e
+0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, // 0x9f
+0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
+0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
+0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
+0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
+0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
+0x38, 0x74, 0xaa, 0xba, 0xaa, 0x64, 0x38, 0x00, // (R)
+0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
+0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
+0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
+0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
+0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
+0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
+0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
+0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, // (c)
+0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
+0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
+0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
+0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
+0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
+0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
+0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
+0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
+0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
+0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
+0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
+0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
+0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
+0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
+0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
+0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
+0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
+0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
+0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00,
+0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
+0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
+0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
+0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
+0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
+0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
+0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
+0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
+0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
+0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define P9100_CFG_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x9100))
+#define P9100_CFG_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x9104))
+#define P9100_CONFIG_REG 0x41
+#define P9100_COMMAND_REG 0x04
+#define P9100_MEM_BASE_ADDR_REG 0x13
+#define P9100_RAMDAC ((PVOID) ((ULONG)VESA_BUS + 0x60210))
+#define P9100_RAMDAC_LOW_ADDR ((PVOID) ((ULONG)VESA_BUS + 0x60210))
+#define P9100_RAMDAC_HIGH_ADDR ((PVOID) ((ULONG)VESA_BUS + 0x60214))
+#define P9100_RAMDAC_DATA ((PVOID) ((ULONG)VESA_BUS + 0x60218))
+#define P9100_RAMDAC_CTRL ((PVOID) ((ULONG)VESA_BUS + 0x6021c))
+
diff --git a/private/ntos/nthals/halsni4x/mips/x4clock.s b/private/ntos/nthals/halsni4x/mips/x4clock.s
new file mode 100644
index 000000000..44a813ebd
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/x4clock.s
@@ -0,0 +1,325 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/x4clock.s,v 1.4 1995/02/13 12:54:07 flo Exp $")
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+#if DBG
+#else
+
+//
+// we use this only when we have the machine up and running ...
+// LED's can show us something, what we do not see in the debugger
+//
+
+ la t0,HalpLedRegister // get current Value of LED Register
+ lw a0,0(t0)
+ addu a0,a0,1 // increment
+ sw a0,0(t0) // store and
+ la t0, HalpLedAddress // get address of the variable
+ lw t0,0(t0) // get value
+ sb a0,0(t0) // display LSByte (set the LED)
+#endif
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the new time increment is nonzero, then the new time
+// increment is moved to the next time increment and the timer is reprogramed
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNewTimeIncrement // get new time increment
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // new interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // pipeline current increment value
+ bne zero,t4,10f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+10: sw zero,HalpNewTimeIncrement // clear new time increment
+ beq zero,t1,15f // if eq, not interval count change
+ sw t1,HalpNextTimeIncrement // set next time increment value
+ move a0,t1 // prepare to call HalpProgramIntervalTimer
+ jal HalpProgramIntervalTimer // program timer chip ...
+15: beq zero,t0,40f // if eq, debugger not enabled
+//15: beq zero,t0,20f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+// beq zero,v0,20f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+
+//
+// Check if profiling is active and the profile interval has expired.
+//
+//
+//20: la t0,HalpCountCompareInterrupt // profiling via CountCompare ?
+// lb t1,0(t0)
+// bne zero,t1,40f // if set, profiling is done via CountCompare Interrupt
+// lw t0,KiPcr + PcProfileCount(zero) // get remaining profile count
+// li t1,TIME_INCREMENT // get time increment value
+// beq zero,t0,40f // if eq, profiling not enabled
+// subu t0,t0,t1 // subtract time increment from count
+// bgtz t0,30f // if gtz, not end of profile interval
+// move a0,s8 // set address of trap frame
+// jal KeProfileInterrupt // process profile entries
+// lw t0,KiPcr + PcProfileInterval(zero) // get profile interval value
+//30: sw t0,KiPcr + PcProfileCount(zero) // set remaining profile count
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the extra interval timer in the slave processors. Its function is
+// to transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Note: We plan to use the extra timer for our MultiProcessor (SNI)Machine
+// MAYBE, if we have arbitrated interrupts, we have to acknowledge
+// this interrupt here and send an message to the other processors
+// (Quadro machine)
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpClockInterrupt1, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ li t0, RM400_TIMER0_ACK_ADDR // get address of acknowledge register
+ sb zero,0(t0) // acknowledge timer interrupt
+ jal HalpCheckSpuriousInt
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j t1 //
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpProfileInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+ .set noat
+
+ jal HalpCheckSpuriousInt
+ nop
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+//
+// we prefer the MultiPro version, which also works on UniPro machines
+//
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halsni4x/mips/x4misc.s b/private/ntos/nthals/halsni4x/mips/x4misc.s
new file mode 100644
index 000000000..3a2515a7d
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/x4misc.s
@@ -0,0 +1,472 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/x4misc.s,v 1.4 1995/02/13 12:54:22 flo Exp $")
+
+// TITLE("Misc R4000 Functions")
+//++
+//
+// Copyright (c) 1994 Siemens Nixdorf Informationssysteme AG
+//
+// Module Name:
+//
+// x4misc.s
+//
+// Abstract:
+//
+// This module implements some R4000 basic register access routines
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+#define STATUS_DE 0x10000 // Disable Cache error ands ECC Errors bit
+#define STATUS_IE 0x00001 // Interrupt Enable/Disable Bit
+
+#define UNCACHED 0x2
+#define CACHABLE_NONCOHERENT 0x3
+#define CACHABLE_COHERENT_EXCLUSIVE 0x4
+#define CACHABLE_COHERENT_EXCLUSIVE_ON_WRITE 0x5
+#define CACHABLE_COHERENT_UPDATE_ON_WRITE 0x6
+
+ SBTTL("Get R4000 Status Register")
+//++
+//
+// ULONG
+// HalpGetStatusRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetStatusRegister
+
+ SBTTL("Set R4000 Status Register")
+//++
+//
+// ULONG
+// HalpSetStatusRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current (old)PSR
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,psr
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetStatusRegister
+
+ SBTTL("Get R4000 Cause Register")
+//++
+//
+// ULONG
+// HalpGetCauseRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the cause register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the cause register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetCauseRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,cause // get current cause
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetCauseRegister
+
+ SBTTL("Set R4000 Cause Register")
+//++
+//
+// ULONG
+// HalpSetCauseRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the Cause register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Cause register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetCauseRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,cause // get current (old)Cause
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,cause
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetCauseRegister
+
+ SBTTL("Get R4000 Config Register")
+//++
+//
+// ULONG
+// HalpGetConfigRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the Config register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Config register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetConfigRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,config // get current Config
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetConfigRegister
+
+ SBTTL("Set R4000 Config Register")
+//++
+//
+// ULONG
+// HalpSetConfigRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the R4000 Config register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Config register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetConfigRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,config // get current (old)Config
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,config
+ nop
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetConfigRegister
+
+ SBTTL("Dismiss (acknowledge) Timeout Interrupts")
+//++
+//
+// ULONG
+// HalpDismissTimeoutInterrupts(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function it is called as an result of an (single) Timeout Interrupt
+// we reset the Bit 21 of the IOMemconf Register (disable Timeout) wait
+// and than we reenable Timeout Interrupts by setting Bit 21
+//
+// Note: Because the SNI ASIC is located at a special Address,
+// ( I have to study the docs again ...)
+// We have to set the Disable Parity Error and ECC Detection Bit in the
+// R4x00 Status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpDismissTimeoutInterrupts)
+
+ .set noreorder
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ or v1, v0, STATUS_DE // disable Parity/ Cache errors
+ and v1, v1, ~(STATUS_IE) // disable Interrupts
+ mtc0 v1, psr
+ nop
+ nop
+ nop
+ li t0, IOMEMCONF_ADDR // Timeout (and other) register
+ lw a0, 0(t0) // get the current value
+ and a1, a0, 0xffdfffff // reset bit 21
+ sw a1, 0(t0) // set IOMemconf Register
+ sync // flush write buffers
+
+//
+// execute a small time loop
+//
+
+ li a1,0x10
+1: nop
+ bne a1,zero,1b
+ subu a1,1 // BDSLOT
+
+ sw a0,0(t0) // restore old IOMemconf Register value
+ sync // flush write buffers
+
+ mtc0 v0, psr // restore old R4000 Status Register
+ nop
+ nop
+ nop
+ nop
+
+ .set reorder
+
+ j ra // return
+
+ .end HalpDismissTimeoutInterrupts
+
+ SBTTL("Disable Timeout Interrupts")
+//++
+//
+// ULONG
+// HalpDisableTimeoutInterrupts(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function it is called as an result of LOTS of LOTS of Timeout Interrupts,
+// so we disable them in the IOMemconfRegister (bit 21)
+// this is a stripped down version of HalpDismissTimeoutInterrupts()
+//
+// Note: Because the SNI ASIC is located at a special Address,
+// ( I have to study the docs again ...)
+// We have to set the Disable Parity Error and ECC Detection Bit in the
+// R4x00 Status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpDisableTimeoutInterrupts)
+
+ .set noreorder
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ or v1, v0, STATUS_DE // disable Parity/ Cache errors
+ and v1, v1, ~(STATUS_IE) // disable Interrupts
+ mtc0 v1, psr
+ nop
+ nop
+ nop
+ li t0, IOMEMCONF_ADDR // Timeout (and other) register
+ lw a0, 0(t0) // get the current value
+ and a1, a0, 0xffdfffff // reset bit 21
+ sw a1, 0(t0) // set register
+ sync // flush write buffers
+
+ mtc0 v0, psr // restore old R4000 Status Register
+ nop
+ nop
+ nop
+ nop
+
+ .set reorder
+
+ j ra // return
+
+ .end HalpDisableTimeoutInterrupts
+
+ SBTTL("Enable Timeout Interrupts")
+//++
+//
+// ULONG
+// HalpEnableTimeoutInterrupts(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is the Counterpart of HalpDisableTimeoutInterrupts
+// We hope, it is never called
+//
+// Note: Because the SNI ASIC is located at a special Address,
+// ( I have to study the docs again ...)
+// We have to set the Disable Parity Error and ECC Detection Bit in the
+// R4x00 Status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpEnableTimeoutInterrupts)
+
+ .set noreorder
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ or v1, v0, STATUS_DE // disable Parity/ Cache errors
+ and v1, v1, ~(STATUS_IE) // disable Interrupts
+ mtc0 v1, psr
+ nop
+ nop
+ nop
+ li t0, IOMEMCONF_ADDR // Timeout (and other) register
+ lw a0, 0(t0) // get the current value
+ or a1, a0, 0x00200000 // set bit 21
+ sw a1, 0(t0) // set register
+ sync // flush write buffers
+
+ mtc0 v0, psr // restore old R4000 Status Register
+ nop
+ nop
+ nop
+
+ .set reorder
+
+ j ra // return
+
+ .end HalpEnableTimeoutInterrupts
+
+#endif
+
diff --git a/private/ntos/nthals/halsni4x/mips/x4tb.s b/private/ntos/nthals/halsni4x/mips/x4tb.s
new file mode 100644
index 000000000..2728c10ea
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/x4tb.s
@@ -0,0 +1,110 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/x4tb.s,v 1.2 1994/12/01 15:18:29 holli Exp $")
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpFreeTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halsni4x/mips/x86bios.c b/private/ntos/nthals/halsni4x/mips/x86bios.c
new file mode 100644
index 000000000..17cd688aa
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/x86bios.c
@@ -0,0 +1,191 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data.
+// per default, we enable int10's but we do nort use them on our well known
+// SNI graphic cards
+// if we have an unknown card, we try to initialize it via the emulator and the card
+// bios. if this fails, we disable int10 calls
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = TRUE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the X86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if (BiosCommand == 0x10){
+
+ if(HalpEnableInt10Calls == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // if Int10 commands are still enabled, Initialize the Card
+ // if it fails, disable Int10's
+ // this should make sense ...
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x50 16 color text mode.
+ // this is done by two int10 calls like on an standard PC
+ // hopefully this works ...
+ // the sample code sets only 80x25 mode, but we want more !!!
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+ //
+ // Now change it to 80x50 8x8Font Mode
+ //
+
+ Context.Eax = 0x1112; // use 8x8 font (causes 50 line mode)
+ Context.Ebx = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
diff --git a/private/ntos/nthals/halsni4x/mips/xxcache.c b/private/ntos/nthals/halsni4x/mips/xxcache.c
new file mode 100644
index 000000000..0bf8143ae
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxcache.c
@@ -0,0 +1,399 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/xxcache.c,v 1.4 1995/04/07 10:02:52 flo Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ xxcache.c
+
+Abstract:
+
+
+ This module implements the functions necessesary to call the correct Cache routines
+ depending on Uni- or MultiProcessor machine typ.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "mpagent.h"
+
+HalpProcessorType HalpProcessorId = UNKNOWN;
+
+//
+// Prototypes for private functions
+// they match the ones defined for the HAL ...
+// they diffrentiate in ending Uni/Multi
+//
+
+VOID
+HalpZeroPageOrion(
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ );
+VOID
+HalpZeroPageMulti(
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ );
+VOID
+HalpZeroPageUni(
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ );
+VOID
+HalpSweepIcacheOrion (
+ VOID
+ );
+VOID
+HalpSweepIcacheMulti (
+ VOID
+ );
+VOID
+HalpSweepIcacheUni (
+ VOID
+ );
+VOID
+HalpSweepDcacheOrion(
+ VOID
+ );
+VOID
+HalpSweepDcacheMulti(
+ VOID
+ );
+VOID
+HalpSweepDcacheUni(
+ VOID
+ );
+VOID
+HalpPurgeIcachePageOrion(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+VOID
+HalpPurgeIcachePageMulti(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+VOID
+HalpPurgeIcachePageUni(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+VOID
+HalpPurgeDcachePageUni (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+VOID
+HalpFlushDcachePageOrion(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+VOID
+HalpFlushDcachePageMulti(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+VOID
+HalpFlushDcachePageUni(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpProcessorConfig()
+{
+
+ if (HalpOrionIdentify() == HalpR4600) {
+ HalpProcessorId = ORIONSC;
+ return;
+ }
+
+ if (HalpMpAgentIdentify() == TRUE) {
+ HalpProcessorId = MPAGENT;
+ return;
+ }
+
+ HalpProcessorId = R4x00;
+
+ return;
+}
+
+VOID
+HalFlushDcachePage(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpFlushDcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepDcacheRange(
+ Color,
+ Length
+ );
+ HalpFlushDcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpFlushDcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalFlushDcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpFlushDcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepDcacheRange(
+ Color,
+ Length
+ );
+ HalpFlushDcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpPurgeDcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalPurgeDcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalPurgeIcachePage(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpPurgeIcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepIcacheRange(
+ Color,
+ Length
+ );
+ HalpPurgeIcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpPurgeIcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalPurgeIcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalSweepDcache(
+ VOID
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpSweepDcacheMulti();
+ break;
+
+ case ORIONSC:
+
+ HalpSweepDcacheOrion();
+ break;
+
+ case R4x00:
+
+ HalpSweepDcacheUni();
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalSweepDcache();
+
+ }
+
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpSweepIcacheMulti();
+ break;
+
+ case ORIONSC:
+
+ HalpSweepIcacheOrion();
+ break;
+
+ case R4x00:
+
+ HalpSweepIcacheUni();
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalSweepIcache();
+
+ }
+
+}
+
+VOID
+HalZeroPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpZeroPageMulti(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case ORIONSC:
+
+ HalpZeroPageOrion(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case R4x00:
+
+ HalpZeroPageUni(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalZeroPage(NewColor, OldColor, PageFrame);
+
+ }
+
+}
+
diff --git a/private/ntos/nthals/halsni4x/mips/xxcalstl.c b/private/ntos/nthals/halsni4x/mips/xxcalstl.c
new file mode 100644
index 000000000..a3a883da5
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxcalstl.c
@@ -0,0 +1,270 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/xxcalstl.c,v 1.2 1995/10/06 09:42:11 flo Exp $")
+/*++
+
+Copyright (c) 1991 - 1994 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 200; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 4000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ if (Index == 0) {
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºWARNING: Cannot compute stall factor º\n");
+ HalDisplayString("ºWARNING: Using default value (250 Mhz) º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+ HalpStallScaleFactor = 0x20;
+ HalpProfileCountRate = 125*1000000;
+ }
+ else {
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt if profiling is done via count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpProfileInterrupt;
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+
+ HalpStallEnd = 0;
+
+ HalpWriteCompareRegisterAndClear(0);
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+ }
+
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halsni4x/mips/xxclock.c b/private/ntos/nthals/halsni4x/mips/xxclock.c
new file mode 100644
index 000000000..0016c5194
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxclock.c
@@ -0,0 +1,233 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/xxclock.c,v 1.3 1995/02/13 12:54:54 flo Exp $")
+
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1985-94 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "i82C54.h"
+
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ KIRQL OldIrql;
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ NewTimeIncrement = DesiredIncrement / MINIMUM_INCREMENT;
+ NewTimeIncrement = NewTimeIncrement * MINIMUM_INCREMENT;
+ HalpNewTimeIncrement = NewTimeIncrement ;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the System clock according to the frequency
+ required by the specified time increment value.
+
+ N.B. this information was found in the jenson (ALPHA) HAL
+ also valid for MIPS computer ???
+
+ There are four different rates that are used under NT
+ (see page 9-8 of KN121 System Module Programmer's Reference)
+
+ .976562 ms
+ 1.953125 ms
+ 3.90625 ms
+ 7.8125 ms
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+ PEISA_CONTROL controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+ ULONG Count;
+ TIMER_CONTROL timerControl;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Start the system clock to interrupt at the desired interval.
+ //
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ //
+ // use timer in the onboard PC core
+ //
+
+ Count = TIMER_CLOCK_IN / ( 10000000 / Interval );
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)Count);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(Count >> 8));
+
+ KeLowerIrql(OldIrql);
+}
+
+
+VOID
+HalpProgramExtraTimer (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the second clock generator in a multiprocessor System
+ according to the frequency required by the specified Interval value (in 100ns units).
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+
+ volatile PLOCAL_8254 pt = (PLOCAL_8254) RM400_EXTRA_TIMER_ADDR;
+ ULONG Count;
+ TIMER_CONTROL timerControl;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Start the system clock to interrupt at the desired interval.
+ //
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ Count = EXTRA_TIMER_CLOCK_IN / (PRE_COUNT * 10000000 / Interval );
+
+ WRITE_REGISTER_UCHAR( &pt->control, *((PUCHAR) &timerControl));
+ WRITE_REGISTER_UCHAR(&(pt->counter0), (UCHAR)Count);
+ WRITE_REGISTER_UCHAR(&(pt->counter0), (UCHAR)(Count >> 8));
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_RATE_GENERATOR;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ // the output of counter 2 is hardwired as input to counter 0/1
+ // so we use it as a pre-counter
+
+ WRITE_REGISTER_UCHAR( &pt->control, *((PUCHAR) &timerControl));
+ WRITE_REGISTER_UCHAR(&(pt->counter2), (UCHAR)PRE_COUNT);
+ WRITE_REGISTER_UCHAR(&(pt->counter2), (UCHAR)(PRE_COUNT >>8));
+
+ KeLowerIrql(OldIrql);
+
+}
+
diff --git a/private/ntos/nthals/halsni4x/mips/xxidle.s b/private/ntos/nthals/halsni4x/mips/xxidle.s
new file mode 100644
index 000000000..44ae154f7
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxidle.s
@@ -0,0 +1,78 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/xxidle.s,v 1.5 1995/04/07 10:04:26 flo Exp $")
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j HalpCheckSpuriousInt // return
+
+ .end HalProcessorIdle
+
diff --git a/private/ntos/nthals/halsni4x/mips/xxinithl.c b/private/ntos/nthals/halsni4x/mips/xxinithl.c
new file mode 100644
index 000000000..8e05dea91
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxinithl.c
@@ -0,0 +1,746 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk351/src/hal/halsni4x/mips/RCS/xxinithl.c,v 1.4 1995/10/06 09:40:49 flo Exp $")
+/*--
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "string.h"
+#include "mpagent.h"
+
+
+#if DBG
+UCHAR HalpBuffer[128];
+#endif
+
+VOID HalpNetTowerInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+typedef struct _HALP_NET_CONFIG {
+ UCHAR Reserved[2];
+ UCHAR SysBus; // 54
+ UCHAR Reserved1[5];
+ ULONG PISCP; // adress ISCP
+ UCHAR Busy;
+ UCHAR Reserved2[3];
+ ULONG PSCB; // adress SCB
+ USHORT Status;
+ USHORT Command;
+ ULONG Reseved3[9];
+} HALP_NET_CONFIG, *PHALP_NET_CONFIG;
+
+ULONG HalpNetReserved[18];
+
+ULONG HalpLedRegister;
+PUCHAR HalpLedAddress = (PUCHAR)RM400_LED_ADDR;
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+//ULONG HalpBusType = MACHINE_TYPE_EISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+PHALP_NET_CONFIG HalpNetStructureAddress;
+BOOLEAN LessThan16Mb;
+BOOLEAN HalpEisaDma;
+BOOLEAN HalpProcPc = TRUE; // kind of CPU module (without second. cache)
+BOOLEAN HalpEisaExtensionInstalled = FALSE;
+BOOLEAN HalpIsRM200 = FALSE;
+MotherBoardType HalpMainBoard = M8042; // default is RM400 Minitower
+
+
+BOOLEAN HalpIsMulti = FALSE; // MultiProcessor machine has a MpAgent per processor
+BOOLEAN HalpCountCompareInterrupt = FALSE;
+KAFFINITY HalpActiveProcessors;
+LONG HalpNetProcessor = 0;
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+#pragma alloc_text(INIT, HalpDisplayCopyRight)
+
+#endif
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ UCHAR Byte;
+ PRESTART_BLOCK NextRestartBlock;
+
+ Prcb = PCR->Prcb;
+
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ if ( (LoaderBlock->u.Mips.SecondLevelDcacheSize) == 0 )
+ HalpProcPc = TRUE;
+ else
+ HalpProcPc = FALSE;
+
+ //
+ // Processor 0 specific
+ //
+
+ if(Prcb->Number == 0) {
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // try to identify the Kind of Mainboard
+ //
+
+ HalpMainBoard = (MotherBoardType) READ_REGISTER_UCHAR(0xbff0002a);
+
+ if (HalpMainBoard == M8036) {
+
+ //
+ // this is the "nice" Desktop Model RM200
+ //
+ HalpIsRM200 = TRUE;
+
+ //
+ // test, if the EISA Extension board is installed in the desktop
+ //
+
+ Byte = READ_REGISTER_UCHAR(RM200_INTERRUPT_SOURCE_REGISTER);
+
+ // this bit is low active
+
+ if ((Byte & 0x80) == 0)
+ HalpEisaExtensionInstalled = TRUE;
+
+ //
+ // enable all Interrupts by resetting there bits in the interrupt mask register
+ // except Timeout interrupts, which we don't like at this moment
+ //
+
+ // WRITE_REGISTER_UCHAR(RM200_INTERRUPT_MASK_REGISTER, (UCHAR)(RM200_TIMEOUT_MASK));
+ WRITE_REGISTER_UCHAR(RM200_INTERRUPT_MASK_REGISTER, (UCHAR)(0x00));
+
+ }
+
+
+ HalpLedRegister = 0;
+ HalpLedAddress = (HalpIsRM200) ? (PUCHAR)RM200_LED_ADDR : (PUCHAR)RM400_LED_ADDR;
+
+ //
+ // for Isa/Eisa access during phase 0 we use KSEG1 addresses
+ // N.B. HalpEisaExtensionInstalled can only be TRUE on an RM200 (Desktop)
+ //
+
+ if (HalpEisaExtensionInstalled )
+ HalpOnboardControlBase = (PVOID) (RM200_ONBOARD_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ else
+
+ HalpOnboardControlBase = (PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ HalpEisaControlBase = (PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only needed for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ //
+ // Is this machine a multi-processor one ?
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if ((NextRestartBlock != NULL) && (NextRestartBlock->NextRestartBlock != NULL)) {
+
+#if DBG
+ HalDisplayString("Multiprocessor machine detected by RestartBlock\n");
+#endif
+
+ //
+ // There is more than one processor
+ // be sure, the boot (this one) is set to running and started
+ //
+
+ HalpIsMulti = TRUE;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ NextRestartBlock->BootStatus.ProcessorReady = 1;
+
+ //
+ // set up Interrupt routing, Cache replace Address etc.
+ //
+
+ PCR->InterruptRoutine[OUR_IPI_LEVEL] = HalpIpiInterrupt;
+
+ } else {
+#if DBG
+ HalDisplayString("UniProcessor machine detected\n");
+#endif
+ HalpIsMulti = FALSE;
+ }
+
+ // Initialize the MP Agent
+
+ if (HalpProcessorId == MPAGENT) {
+ HalpInitMPAgent(0);
+ HalpActiveProcessors = 0x01;
+ }
+
+ //
+ // For the moment, we say all Eisa/ Isa(Onboard) Interrupts should go to processor 0
+ //
+
+ HalpCreateEisaStructures(Isa); // Initialize Onboard Interrupts and Controller
+
+ //
+ // The RM200 is in Fact a real Uni Processor machine
+ //
+
+ if(HalpEisaExtensionInstalled) {
+ HalpCreateEisaStructures(Eisa); // Initialize Eisa Extension board Interrupts
+ // and Controller for the RM200
+ }
+
+ // Correction pb Tower with memory > 128 mb + minitower with adaptec
+
+ if ((HalpMainBoard == M8032) || (HalpMainBoard == M8042))
+ HalpNetTowerInit(LoaderBlock);
+
+ //
+ // Initialize SNI specific interrupts
+ // (only once needed)
+ //
+
+ if (HalpProcessorId == MPAGENT) HalpCreateIntMultiStructures(); else HalpCreateIntStructures();
+
+ } else {
+
+#if DBG
+// sprintf(HalpBuffer,"HalInitSystem: running on %d\n", HalpGetMyAgent());
+// HalDisplayString(HalpBuffer);
+#endif
+ //
+ // Place something special only to Slave Processors here ...
+ //
+
+ HalpInitMPAgent(Prcb->Number); // enables IPI, init cache replace address
+ PCR->InterruptRoutine[OUR_IPI_LEVEL] = HalpIpiInterrupt;
+ }
+
+
+ //
+ // PCR tables and System Timer Initialisation
+ //
+
+ HalpInitializeInterrupts();
+
+ return (TRUE);
+
+ } else {
+
+ extern BOOLEAN HalpX86BiosInitialized;
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Mapping of the EISA Control Space via MmMapIoSpace()
+ //
+
+ HalpMapIoSpace();
+
+ HalpCalibrateStall();
+
+ //
+ // Initialisation of the x86 Bios Emulator ...
+ //
+
+ x86BiosInitializeBios(HalpEisaControlBase, HalpEisaMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Be sure, that the NET_LEVEL is not in the reserved vector .
+ // (NET_DEFAULT_VECTOR == IPI_LEVEL = 7) => only used for
+ // machine != RM200 (mainboard 8036) and processor without
+ // secondary cache
+ //
+
+ if ((HalpProcPc) || ((HalpProcessorId == ORIONSC) && (HalpMainBoard != M8036)))
+ PCR->ReservedVectors &= ~(1 << NET_DEFAULT_VECTOR);
+
+ HalpDisplayCopyRight();
+
+ return TRUE;
+ }
+}
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+//
+// The boot processor is already initialized
+//
+
+if (Number == 0)
+ return;
+
+#if DBG
+// sprintf(HalpBuffer,"HalInitializeProcessor %d\n",Number);
+// HalDisplayString(HalpBuffer);
+#endif
+
+return;
+
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ if(!HalpIsMulti) {
+ return FALSE;
+ }
+
+#if DBG
+// sprintf(HalpBuffer,"HalStartNextProcessor running on %d\n", HalpGetMyAgent());
+// HalDisplayString(HalpBuffer);
+#endif
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+//
+// start it by sending him a special IPI message (SNI special to avoid traffic on
+// the MP bus during boot)
+//
+ HalpActiveProcessors |= (1 << (NextRestartBlock->ProcessorId));
+ HalpSendIpi(1 << (NextRestartBlock->ProcessorId), MPA_BOOT_MESSAGE );
+ HalpNetProcessor = 1; // If proc 1 started, net interrupts will be connected to it
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+HalpDisplayCopyRight(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function displays the CopyRight Information in the correct SNI Style
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+//
+// Define Identification Strings.
+//
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºMicrosoft(R) Windows NT(TM) 3.51 Hardware Abstraction Layer º\n");
+ HalDisplayString("ºfor Siemens Nixdorf RM200/RM400 Release 2.0 B0006 º\n");
+ HalDisplayString("ºCopyright(c) Siemens Nixdorf Informationssysteme AG 1995 º\n");
+ HalDisplayString("ºCopyright(c) Microsoft Corporation 1985-1995 º\n");
+ HalDisplayString("ºAll Rights Reserved º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ //
+ // this does not seem to work correct on NT 3.51 builds (872) at least
+ // on our MultiPro machine
+ //
+ if(!HalpCountCompareInterrupt) {
+
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºWARNING: CountCompare Interrupt is not enabled º\n");
+ HalDisplayString("ºWARNING: please contact your local Siemens Nixdorf º\n");
+ HalDisplayString("ºWARNING: Service Center. º\n");
+ HalDisplayString("ºWARNING: º\n");
+ HalDisplayString("ºWARNING: Your System will come up - but some º\n");
+ HalDisplayString("ºWARNING: performance measurement issues º\n");
+ HalDisplayString("ºWARNING: WILL NOT FUNCTION PROPERLY º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ }
+
+
+}
+
+
+
+VOID
+HalpNetTowerInit(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function is only used on Tower machines. It initialises the net chip.
+ It is used because of a hardware problem when the machine has
+ more than 128 Mb memory : net interrupts may happen with no
+ installed network.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ULONG Cmd;
+PUSHORT Port = (PUSHORT)0xb8000000;
+PULONG ChannelAttention = (PULONG)0xb8010000;
+ULONG Time;
+USHORT Status;
+
+ HalpNetStructureAddress =
+ (PHALP_NET_CONFIG) (((ULONG)((PUCHAR)HalpNetReserved + 0xf)) & 0xfffffff0); // aligned on 16
+ HalpNetStructureAddress = (PHALP_NET_CONFIG) ((ULONG)HalpNetStructureAddress | 0xa0000000);
+ HalSweepDcache(); // because we are going to use non cached addresses
+ HalpNetStructureAddress->SysBus = 0x54;
+ HalpNetStructureAddress->Busy = 0xff;
+ HalpNetStructureAddress->PISCP = (ULONG)(((PULONG)HalpNetStructureAddress) + 3) & 0x5fffffff;
+ HalpNetStructureAddress->PSCB = (ULONG)(((PULONG)HalpNetStructureAddress) + 5) & 0x5fffffff;
+
+ Cmd = 0;
+ WRITE_REGISTER_USHORT(Port, (USHORT)Cmd);
+ WRITE_REGISTER_USHORT(Port, (USHORT)Cmd);
+ KeStallExecutionProcessor(50000);
+
+ Cmd = (((ULONG)HalpNetStructureAddress) & 0x5fffffff) | 0x02;
+ WRITE_REGISTER_USHORT(Port, (USHORT)Cmd);
+ WRITE_REGISTER_USHORT(Port, (USHORT)(Cmd >> 16));
+
+ Cmd = 0;
+ WRITE_REGISTER_ULONG(ChannelAttention,Cmd);
+
+ Time = 20;
+ while (Time > 0) {
+ if (!(HalpNetStructureAddress->Busy !=0)) {
+ break;
+ }
+ KeStallExecutionProcessor(10000);
+ Time--;
+ }
+
+ Status = HalpNetStructureAddress->Status;
+ Status = Status & 0xf000;
+ HalpNetStructureAddress->Command = Status;
+ KeFlushWriteBuffer();
+
+ Cmd = 0;
+ WRITE_REGISTER_ULONG(ChannelAttention,Cmd);
+}
diff --git a/private/ntos/nthals/halsni4x/mips/xxinitnt.c b/private/ntos/nthals/halsni4x/mips/xxinitnt.c
new file mode 100644
index 000000000..2d34c4c38
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxinitnt.c
@@ -0,0 +1,369 @@
+#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/xxinitnt.c,v 1.6 1995/04/07 10:08:17 flo Exp $")
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+extern BOOLEAN HalpProcPc;
+extern BOOLEAN HalpCountCompareInterrupt;
+
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpAckExtraClockInterrupt(
+ VOID
+ );
+
+VOID
+HalpCountInterrupt (
+ VOID
+ );
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG Interval
+ );
+
+VOID
+HalpProgramExtraTimer (
+ IN ULONG Interval
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+#pragma alloc_text(INIT, HalpCountInterrupt)
+
+#endif
+
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+/*+++
+
+
+ The interrupts bits in the cause Register have the following Hardware Interrupts:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | x | x | x | x | x | x | x | x |
+ +-------------------------------+
+ | | | | | | | |
+ | | | | | | | +-------- APC LEVEL (Software)
+ | | | | | | +------------ Dispatch LEVEL (Software)
+ | | | | | +---------------- central Int0 for R4x00 SC machines
+ | | | | +-------------------- SCSI_EISA LEVEL
+ | | | +------------------------ DUART (Console)
+ | | +---------------------------- TIMER (82C54 in the local I/O part)
+ | +-------------------------------- Ethernet (intel 82596 onboard)
+ +------------------------------------ CountCompare (Profiling) or PushButton Int.
+
+---*/
+
+//
+// On an R4x00SC, the processor has only 1 central interrupt pin, so all
+// should be directed to this interrupt, except the (internal) CountCompare interrupt
+// This is also true for the oncomming SNI Desktop model, which has only the
+// central interrupt connected
+//
+
+UCHAR
+HalpIrqlMask_SC[] = {3, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+
+UCHAR
+HalpIrqlTable_SC[] = {0x87, // IRQL 0
+ 0x86, // IRQL 1
+ 0x84, // IRQL 2
+ 0x80, // Int0Dispatch Level
+ // allow only Irql 8 (profiling & HIGH_LEVEL) ?!
+ 0x80, // IRQL 4
+ 0x80, // IRQL 5
+ 0x80, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+//
+// On an R4x00MC, all the interrupts enable/disable per processor is managed by the MPagent
+//
+
+/*+++ Note from Dave Cutler "Mr. NT"
+
+| How can this happen ?
+|
+
+You cannot use the interrupt mask field of the status register to
+enable/disable per processor interrupts. In fact, the IRQL mask table
+that is initialized by the HAL must be the same for all processors.
+
+When threads start execution they have all interrupts in the
+interrupt mask field set according to the PASSIVE_LEVEL entry in the
+interrupt mapping table of the processor they start on. They are
+immediately context switchable. If per processor interrupts weere
+controlled by the interrupt mask field of the status register, then
+as soon as the thread got scheduled on another processor, the enables
+would no longer be correct.
+
+d
+
+---*/
+
+UCHAR HalpIrqlMask_MC[] = {4, 7, 6, 7, 5, 7, 6, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+
+UCHAR HalpIrqlTable_MC[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xb0, // IRQL 5 NET
+ 0x90, // IRQL 6 CLOCK
+ 0x80, // IRQL 7 IPI
+ 0x00}; // IRQL 8
+
+UCHAR
+HalpIrqlMask_PC[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR
+HalpIrqlTable_PC[] = {0xfb, // IRQL 0 1111 1011
+ 0xfa, // IRQL 1 1111 1010
+ 0xf8, // IRQL 2 1111 1000
+ 0xf8, // IRQL 3 1111 1000
+ 0xf0, // IRQL 4 1111 0000
+ 0xe0, // IRQL 5 1110 0000
+ 0xc0, // IRQL 6 1100 0000
+ 0x80, // IRQL 7 1000 0000
+ 0x00}; // IRQL 8 0000 0000
+
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ extern ULONG HalpProfileInterval;
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+ HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+ HalpCountCompareInterrupt = TRUE;
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ if (HalpIsRM200) {
+
+ //
+ // On an RM200 (Desktop) we have only 1 interrupt, which is like
+ // the central Interrupt for R4x00SC machines
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_SC); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_SC[Index];
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable_SC); Index += 1)
+
+ PCR->IrqlTable[Index] = HalpIrqlTable_SC[Index];
+
+ } else {
+
+ //
+ // if this is not a Desktop, we have to check if this is an
+ // R4x00 SC model or a R4x00 MC (multiprocessor model)
+ //
+
+ if (HalpProcessorId == MPAGENT) {
+
+ //
+ // this is the boot processor in an MultiProcessor Environment
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_MC); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_MC[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_MC); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_MC[Index];
+
+ } else {
+
+ if ((HalpProcPc) || (HalpProcessorId == ORIONSC)) {
+
+ //
+ // this is an R4000PC or a R4600 model in an UniProcessor Environment
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PC); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PC[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PC); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PC[Index];
+
+ } else {
+
+ //
+ // this is an R4x00SC model in an UniProcessor Environment
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_SC); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_SC[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_SC); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_SC[Index];
+ }
+
+ }
+ }
+
+ //
+ // the main system clock is always in the onboard PC core
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE)HalpStallInterrupt;
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\compare interrupt to the appropriate interrupt service routine.
+ //
+
+
+
+ //
+ // force a CountCompare interrupt
+ //
+
+ HalpWriteCompareRegisterAndClear(100);
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ HalpProgramIntervalTimer (MAXIMUM_INCREMENT);
+ HalpEnableOnboardInterrupt(CLOCK2_LEVEL,Latched); // Enable Timer1,Counter0 interrupt
+
+ } else {
+
+ //
+ // MultiProcessorEnvironment Processor N
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_MC); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_MC[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_MC); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_MC[Index];
+
+ HalpProgramExtraTimer (MAXIMUM_INCREMENT);
+ PCR->InterruptRoutine[EXTRA_CLOCK_LEVEL] = HalpClockInterrupt1;
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ }
+
+ return TRUE;
+}
+
diff --git a/private/ntos/nthals/halsni4x/mips/xxipiint.s b/private/ntos/nthals/halsni4x/mips/xxipiint.s
new file mode 100644
index 000000000..fbdb99fd5
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxipiint.s
@@ -0,0 +1,56 @@
+// TITLE("Interprocessor Interrupts")
+//++
+//
+// Copyright (c) 1993-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxipiint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a MIPS R4000 Duo system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt.
+// Its function is to acknowledge the interrupt and transfer control to
+// the standard system routine to process interprocessor requrests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpIpiInterrupt)
+//
+// Inter processor interrupt processing
+//
+
+ move a0,s8
+ j HalpProcessIpi // acknowledgement Ipi
+
+ .end HalpIpiInterrupt
+
diff --git a/private/ntos/nthals/halsni4x/mips/xxmemory.c b/private/ntos/nthals/halsni4x/mips/xxmemory.c
new file mode 100644
index 000000000..3a9063157
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/mips/xxmemory.c
@@ -0,0 +1,179 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/xxmemory.c,v 1.2 1994/11/09 07:54:26 holli Exp $")
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow the HAL to map physical memory.
+
+Environment:
+
+ Phase 0 initialization only.
+
+Changes:
+
+ All stuff comes from the x86 HAL Sources (xxmemory.c)
+
+--*/
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalpAllocPhysicalMemory)
+#endif
+
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The pyhsical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which contains a memory chunk
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+
+ PhysicalAddress = (AlignmentOffset + Descriptor->BasePage)
+ << PAGE_SHIFT;
+
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+
+ return PhysicalAddress;
+}
diff --git a/private/ntos/nthals/halsni4x/sources b/private/ntos/nthals/halsni4x/sources
new file mode 100644
index 000000000..491d21b3c
--- /dev/null
+++ b/private/ntos/nthals/halsni4x/sources
@@ -0,0 +1,91 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halsni4x
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-DSNI -DORION
+
+INCLUDES=..\x86new;..\..\inc
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\x86bios.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\unicache.s \
+ mips\duocache.s \
+ mips\orcache.s \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\j4prof.c \
+ mips\jxebsup.c \
+ mips\jxenvirv.c \
+ mips\jxport.c \
+ mips\jxbeep.c \
+ mips\jxreturn.c \
+ mips\jxmapio.c \
+ mips\SNIdisp.c \
+ mips\jxhwsup.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\xxcalstl.c \
+ mips\xxinithl.c \
+ mips\xxinitnt.c \
+ mips\r4intdsp.c \
+ mips\xxmemory.c \
+ mips\mpagent.c \
+ mips\xxcache.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\x4misc.s \
+ mips\xxipiint.s \
+ mips\x4clock.s \
+ mips\xxipiint.s \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halsnip/hal.rc b/private/ntos/nthals/halsnip/hal.rc
new file mode 100644
index 000000000..0a9d8d789
--- /dev/null
+++ b/private/ntos/nthals/halsnip/hal.rc
@@ -0,0 +1,17 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "SNI RM200/RM300/RM400 Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+#if defined(SNI_INTERNAL)
+#define VER_FILEVERSION_STR "3.0 A0008"
+
+#include "pcisupp.ver"
+#else
+#define VER_FILEVERSION_STR "3.0 B0008"
+#endif
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halsnip/hal.src b/private/ntos/nthals/halsnip/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halsnip/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halsnip/makefile b/private/ntos/nthals/halsnip/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halsnip/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halsnip/makefile.inc b/private/ntos/nthals/halsnip/makefile.inc
new file mode 100644
index 000000000..03970e6e4
--- /dev/null
+++ b/private/ntos/nthals/halsnip/makefile.inc
@@ -0,0 +1,5 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\halsnip.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halsnip/mips/allstart.c b/private/ntos/nthals/halsnip/mips/allstart.c
new file mode 100644
index 000000000..07274b604
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/allstart.c
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+ Note: this HAL is for the Siemens Nixdorf Uni-/MultiProcessor Computers
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+
+ if (HalpIsTowerPci){
+
+ // on PCI tower, MAUI_INT is on processor number 1 if more than one processor
+
+ if ((PCR->Number == 1) || (HalpIsMulti == 0 )){
+
+ HalpCreateIntPciMAUIStructures(PCR->Number);
+ HalpInitMAUIMPAgent();
+
+ }
+ }
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/cacherr.s b/private/ntos/nthals/halsnip/mips/cacherr.s
new file mode 100644
index 000000000..c0ea29908
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/cacherr.s
@@ -0,0 +1,645 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/cacherr.s,v 1.2 1996/02/23 17:55:12 pierre Exp $")
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// No correction is done. We only try to get the physical address
+// that causes this exception
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ .globl HalpCacheErrFirst
+ .globl HalpErrCacheMsg // cache error
+ .globl HalpParityErrMsg // parity error
+ .globl HalpAddrErrMsg // no addr found
+ .globl HalpComputeNum // compute memory sip number
+ .globl HalpKeBugCheck0
+ .globl HalpKeBugCheck1
+ .globl HalpKeBugCheck2
+ .globl HalpKeBugCheck3
+ .globl HalpKeBugCheck4
+ .globl HalpBugCheckNumber
+
+#define CACHE_ERR_ER 0x80000000
+#define CACHE_ERR_EC 0x40000000
+#define CACHE_ERR_ED 0x20000000
+#define CACHE_ERR_ET 0x10000000
+#define CACHE_ERR_ES 0x08000000
+#define CACHE_ERR_EE 0x04000000
+#define CACHE_ERR_EB 0x02000000
+#define CACHE_ERR_EI 0x01000000
+#define CACHE_ERR_SIDX 0x003ffff8
+#define CACHE_ERR_PIDX 0x00000007
+#define PIDX_PD_MASK 0x00001000 // cache size 8k
+
+#define HALP_OPCODE_MASK 0xfc000000
+#define HALP_OPCODE_SHIFT 24 // because we test opcode number on 8 bits
+#define HALP_RT1_REG 0x001f0000
+#define HALP_RT1_SHIFT 16
+#define HALP_RT2_REG 0x03e00000
+#define HALP_RT2_SHIFT 21
+
+#define HALP_SWC1 0xe4 //
+#define HALP_SDC1 0xf4 //
+#define HALP_LWC1 0xc4 //
+#define HALP_LDC1 0xd4 //
+#define HALP_LB 0x80 //
+#define HALP_LH 0x82 //
+#define HALP_LW 0x8c //
+#define HALP_LD 0xdc //
+#define HALP_LBU 0x90 //
+#define HALP_LHU 0x94 //
+#define HALP_SB 0xa0 //
+#define HALP_SH 0xa4 //
+#define HALP_SW 0xac //
+#define HALP_SD 0xfc //
+#define HALP_LWL 0x88 //
+#define HALP_LWR 0x98 //
+#define HALP_LDL 0x68 //
+#define HALP_LDR 0x6c //
+#define HALP_LWU 0x9c //
+#define HALP_SDL 0xb0 //
+#define HALP_SDR 0xb4 //
+#define HALP_LL 0xc0 //
+#define HALP_LLD 0xd0 //
+#define HALP_SC 0xe0 //
+#define HALP_SCD 0xf0 //
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved registers
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+SavedT0:.space 4 //
+SavedT1:.space 4 //
+SavedT2:.space 4 //
+SavedT3:.space 4 //
+SavedT4:.space 4 //
+SavedT5:.space 4 //
+SavedT6:.space 4 //
+SavedT7:.space 4 //
+SavedS0:.space 4 //
+SavedS1:.space 4 //
+SavedS2:.space 4 //
+SavedS3:.space 4 //
+SavedS4:.space 4 //
+SavedS5:.space 4 //
+SavedS6:.space 4 //
+SavedS7:.space 4 //
+SavedT8:.space 4 //
+SavedT9:.space 4 //
+SavedK0:.space 4 //
+SavedK1:.space 4 //
+SavedGP:.space 4 //
+SavedSP:.space 4 //
+SavedS8:.space 4 //
+SavedRA:.space 4 //
+SavedErrorEpc:.space 4 //
+SavedCacheError:.space 4 //
+
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1 and with finished with a fatal system error :
+//
+// Msg Hal : CACHE ERROR - PARITY ERROR - ADDR IN ERROR NOT FOUND
+// KeBugCheckEx :
+// a0 = 0x80 Hardware malfunction
+// a1 = 18 (parity pb) or 19 (cache error)
+// a2 = physical address in error (or 0x00)
+// a3 = sim number
+// a4 = cacheerror register contents
+//
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ .struct 0
+
+ .struct 0
+CiArgs0:.space 4 // saved arguments
+CiArgs1:.space 4 // saved arguments
+CiArgs2:.space 4 // saved arguments
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpCacheErrorRoutine, CiFrameLength, zero)
+
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+
+//
+// Protection to avoid to execute twice in multipro
+// (modif of psr doesn't seem very effective)
+//
+
+ la k0,HalpCacheErrFirst
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k1,k0,k1 //
+ lw k0,0(k1)
+ nop
+ beq k0,zero,1f
+ nop
+
+// cache error during cache error routine
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret // hope we don't need k0 and k1...
+ nop
+
+1: add k0,k0,0x01
+ sw k0,0(k1)
+
+//
+// Save all the registers
+//
+
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ .set noat
+ sw AT,0(k0) // save registers AT - a3
+ .set at
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+ sw a3,24(k0) //
+ sw t0,28(k0) //
+ sw t1,32(k0) //
+ sw t2,36(k0) //
+ sw t3,40(k0) //
+ sw t4,44(k0) //
+ sw t5,48(k0) //
+ sw t6,52(k0) //
+ sw t7,56(k0) //
+ sw s0,60(k0) //
+ sw s1,64(k0) //
+ sw s2,68(k0) //
+ sw s3,72(k0) //
+ sw s4,76(k0) //
+ sw s5,80(k0) //
+ sw s6,84(k0) //
+ sw s7,88(k0) //
+ sw t8,92(k0) //
+ sw t9,96(k0) //
+ sw s8,100(k0) //
+ sw k0,104(k0) //
+ sw k1,108(k0) //
+ sw gp,112(k0) //
+ sw sp,116(k0) //
+ sw s8,120(k0) //
+ sw ra,124(k0) //
+
+ mfc0 a1,cacheerr // get cache error state
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ mfc0 a0,errorepc // get error address
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw a0,0(k0) // save errorepc register
+ sw a1,4(k0) // save cache error register
+//
+// Disable ECC and parity detection (HalpCacheFirstErr will help...)
+//
+
+ mfc0 k0,psr // get current processor state
+ nop
+ nop
+ nop
+ nop
+ nop
+ or k0,k0,0x00010000 // disable ECC and Parity detection
+ and k0,k0,0xfffffffe // disable interrupt
+ mtc0 k0,psr
+ and k0,k0,0xffff00e0
+ mtc0 k0,psr
+
+
+// Analysis of cacheerror register
+
+ la k0,SavedCacheError // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw t0,0(k0) // restore cache error register in t0
+
+ and t1,t0,CACHE_ERR_EE // parity error
+ bne t1,zero,ParityError
+ nop
+
+//
+// Cache error message
+//
+
+ la a0,HalpErrCacheMsg
+ and a0,a0,0x1fffffff
+ or a0,a0,0xa0000000
+ la t0,HalDisplayString
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ nop
+
+ la k0,SavedCacheError // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw t0,0(k0) // restore cache error register in t0
+
+ and t1,t0,CACHE_ERR_SIDX // grab low bits of PAddr
+ lw t2,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ subu t2,t2,1
+ not t2
+ and t1,t2 // t1=PAddre(21..scache_block_size); SCache index
+// lw t2,KiPcr + PcSecondLevelDcacheSize(zero) // get 2nd size
+// subu t2,t2,1
+// and t1,t2 // t1=PAddre(21..scache_block_size); SCache index
+
+ and t5,t0,CACHE_ERR_PIDX
+ sll t5,t5,0xc // align PIDX (bits 15:13)
+ and t2,t1,~(PIDX_PD_MASK) // suppress PIDX bits for VAddr
+ or t2,t5 // t2=VAddr(15..scache_block_size);PCache base index
+
+ or t1,0x80000000 // SCache index with K0SEG address
+ or t2,0x80000000 // PCache base index with K0SEG address
+
+ and t5,t0,CACHE_ERR_EC // Cache level of the error (0=primary, 1=secondary)
+ bne zero,t5,3f // if EC=0, Primary Cache Parity Error
+ nop
+
+1: // primary cache
+
+ // int error
+ and t5,t0,CACHE_ERR_ER // data or instruction flag
+ bne zero,t5,2f // if ER=1 Data error
+ nop
+
+ move a2,t2
+ // primary cache - inst
+ cache INDEX_LOAD_TAG_I,0(t2)
+
+ nop
+ mfc0 a3,taglo
+ b 5f
+ nop
+
+2: // primary cache - data
+ move a2,t2
+ cache INDEX_LOAD_TAG_D,0(t2)
+
+ nop
+ mfc0 a3,taglo
+ b 5f
+ nop
+
+3: // secondary cache - inst/data
+ move a2,t1
+ cache INDEX_LOAD_TAG_SD,0(t1)
+
+ nop
+ mfc0 a3,taglo
+5:
+
+// maybe a3 will be the erroneous physical address...
+
+ li a0,0x80 // harware error
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ li a1,19 // restore error epc register
+ lw a2,4(k0) // restore cache error register
+ la t1,HalpKeBugCheck0
+ sw a0,0(t1)
+ la t1,HalpKeBugCheck1
+ sw a1,0(t1)
+ la t1,HalpKeBugCheck2
+ sw a2,0(t1)
+ la t1,HalpKeBugCheck3
+ sw a3,0(t1)
+ la t1,HalpKeBugCheck4
+ sw zero,0(t1)
+ la t1,HalpBugCheckNumber
+ sw a1,0(t1)
+ la t0,KeBugCheckEx
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ sw zero,0x10(sp)
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret
+ nop
+
+ParityError:
+
+//
+// cacheerr contents are not usable if parity error.
+// Then we must disassemble the errorepc code, get the used register
+// and get the contents of this register which must cause the error.
+//
+
+//
+// Parity Error Msg
+//
+
+ la a0,HalpParityErrMsg
+ and a0,a0,0x1fffffff
+ or a0,a0,0xa0000000
+ la t0,HalDisplayString
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ nop
+
+//
+// disasm
+//
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw a0,0(k0)
+ li a2,0x00 // init for one loop
+ move t0,a0
+
+10: lw a0,0(a0) // instruction
+ move a1,a0 // instruction saved in a1
+ li a3,HALP_OPCODE_MASK
+ and a0,a0,a3
+ srl a0,a0,HALP_OPCODE_SHIFT
+ li a2,0x00
+ beq a0,HALP_SWC1,8f
+ nop
+ beq a0,HALP_SDC1,8f
+ nop
+ beq a0,HALP_LWC1,8f
+ nop
+ beq a0,HALP_LDC1,8f
+ nop
+ beq a0,HALP_LB,8f
+ nop
+ beq a0,HALP_LH,8f
+ nop
+ beq a0,HALP_LW,8f
+ nop
+ beq a0,HALP_LD,8f
+ nop
+ beq a0,HALP_LBU,8f
+ nop
+ beq a0,HALP_LHU,8f
+ nop
+ beq a0,HALP_SB,8f
+ nop
+ beq a0,HALP_SH,8f
+ nop
+ beq a0,HALP_SW,8f
+ nop
+ beq a0,HALP_SD,8f
+ nop
+ beq a0,HALP_LWL,8f
+ nop
+ beq a0,HALP_LWR,8f
+ nop
+ beq a0,HALP_LDL,8f
+ nop
+ beq a0,HALP_LDR,8f
+ nop
+ beq a0,HALP_LWU,8f
+ nop
+ beq a0,HALP_SDL,8f
+ nop
+ beq a0,HALP_SDR,8f
+ nop
+ beq a0,HALP_LWU,8f
+ nop
+ beq a0,HALP_SDL,8f
+ nop
+ beq a0,HALP_SDR,8f
+ nop
+ beq a0,HALP_LL,8f
+ nop
+ beq a0,HALP_SC,8f
+ nop
+ beq a0,HALP_SCD,8f
+ nop
+ move a0,t0
+ addu a0,a0,4
+ beq a2,zero,10b // try the next instruction (case of branch...)
+ addu a2,a2,1
+
+ beq zero,zero,NotFoundAddr
+
+8: // a1 = inst en erreur
+
+ move a2,a1
+
+ li a3,HALP_RT2_REG
+ and a2,a2,a3
+ srl a3,a2,HALP_RT2_SHIFT
+
+ subu a3,1 // reg at has 1 as number
+ sll a3,a3,0x2 // *4
+
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ addu k0,k0,a3
+ lw a3,0(k0) // contents of the register
+//
+// Try To find the physical address
+// a3 = virtual address
+//
+
+ move a0,a3
+ srl a0,a0,30 // two upper bits
+ li a2,0x2 // binary 10
+ beq a0,a2,FoundAddr // KSEG0 or KSEG1 addr
+ nop
+// mapped address => try to find it in the TLB
+ move a0,a3
+ mfc0 t1,entryhi // get current PID and VPN2
+ srl t2,a0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t2,t2,ENTRYHI_VPN2 //
+ and t1,t1,PID_MASK << ENTRYHI_PID // isolate current PID
+ or t2,t2,t1 // merge PID with VPN2 of virtual address
+ mtc0 t2,entryhi // set VPN2 and PID for probe
+ nop // 3 cycle hazzard
+ nop //
+ nop //
+ tlbp // probe for entry in TB
+ nop // 2 cycle hazzard
+ nop //
+ mfc0 t3,index // read result of probe
+ nop
+ bltz t3,NotFoundAddr // if ltz, entry is not in TB
+ sll a0,a0,0x1f - (ENTRYHI_VPN2 - 1) // shift VPN<12> into sign
+ tlbr // read entry from TB
+ nop // 3 cycle hazzard
+ nop //
+ nop //
+ bltz a0,11f // if ltz, check second PTE
+ mfc0 t2,entrylo1 // get second PTE for probe
+ mfc0 t2,entrylo0 // get first PTE for probe
+11: mtc0 t1,entryhi // restore current PID
+ mtc0 zero,pagemask // restore page mask register
+// t2 = entrylo
+ srl t2,t2,ENTRYLO_PFN
+ sll t2,t2,PAGE_SHIFT
+ li a2,PAGE_SIZE
+ subu a2,a2,1
+ and a3,a3,a2
+ or a3,a3,t2
+
+FoundAddr:
+// a3 = Physical addr
+ li a2,0x1fffffff
+ and a3,a3,a2 // 3 upper bits deleted
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw a1,0(k0) // load error epc register
+ lw a2,4(k0) // load cache error register
+
+ // compute sip num
+ sw a3,CiArgs0(sp)
+ sw a1,CiArgs1(sp)
+ sw a2,CiArgs2(sp)
+ move a0,a3
+ la t0,HalpComputeNum
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 // compute sip num
+ nop
+ lw a3,CiArgs2(sp)
+ sw a3,0x10(sp)
+ li a1,18
+ lw a2,CiArgs0(sp)
+ShowMsg:
+ li a0,0x80
+
+ la t1,HalpKeBugCheck0
+ sw a0,0(t1)
+ la t1,HalpKeBugCheck1
+ sw a1,0(t1)
+ la t1,HalpKeBugCheck2
+ sw a2,0(t1)
+ la t1,HalpKeBugCheck3
+ sw v0,0(t1)
+ la t1,HalpKeBugCheck4
+ sw a3,0(t1)
+ la t1,HalpBugCheckNumber
+ sw a1,0(t1)
+ la t0,KeBugCheckEx
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ move a3,v0 // sip num
+
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret //
+
+NotFoundAddr:
+
+ la a0,HalpAddrErrMsg
+ and a0,a0,0x1fffffff
+ or a0,a0,0xa0000000
+ la t0,HalDisplayString
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ nop
+
+ move a3,a1
+ li a0,0x80
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ li a1,18
+ li a2,0x00
+ lw a3,4(k0)
+ sw a3,0x10(sp)
+ la t1,HalpKeBugCheck0
+ sw a0,0(t1)
+ la t1,HalpKeBugCheck1
+ sw a1,0(t1)
+ la t1,HalpKeBugCheck2
+ sw a2,0(t1)
+ la t1,HalpKeBugCheck3
+ sw v0,0(t1)
+ la t1,HalpKeBugCheck4
+ sw a3,0(t1)
+ la t1,HalpBugCheckNumber
+ sw a1,0(t1)
+ la t0,KeBugCheckEx
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ li a3,0xff
+
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret //
+
+ .set reorder
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halsnip/mips/duocache.s b/private/ntos/nthals/halsnip/mips/duocache.s
new file mode 100644
index 000000000..8d743a0b5
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/duocache.s
@@ -0,0 +1,780 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/duocache.s,v 1.4 1996/02/23 17:55:12 pierre Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// duocache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// MIPS R4000 MultiProcerssor Machines. It is very special to SNI machines,
+// which use a special MP Agent Asic.
+//`
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+// NON COHERENT algorithm : to use the replace facility of the MP_Agent
+
+#define CONFIG_NONCOH(reg) \
+ .set noreorder; \
+ .set noat; \
+ mfc0 reg,config; \
+ nop; \
+ nop; \
+ and AT,reg,~(7); \
+ or AT,AT,0x3; \
+ mtc0 AT,config; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ .set at; \
+ .set reorder
+
+// restauration of CONFIG register
+
+#define CONFIG_RESTORE(reg) \
+ .set noreorder; \
+ mtc0 reg,config; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ .set reorder
+
+// beql : if the cond branch is not taken, the inst in the delay-slot is nullified
+
+#define LOAD_RPL_ADDR(reg,reg1) \
+ lw reg,HalpMpaCacheReplace; \
+2:
+
+
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+ SBTTL("Processor Identification")
+//++
+//
+// VOID
+// HalpProcIdentify()
+//
+// Routine Description:
+//
+// This function reads the implementation number in the prid register.
+//
+// Arguments:
+//
+// None
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProcIdentify)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,prid
+ nop
+ srl v0,PRID_IMP
+ and v0,0xff
+ j ra
+ nop
+
+ .end HalpProcIdentify
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageMulti (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFlushDcachePageMulti)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+#endif
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the primary and secondary data caches.
+//
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not update the SC
+// TagRam copy in the MP Agent. So we do cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ or t0,t7,a0 // physical address + offset
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ LOAD_RPL_ADDR(a3,a2) // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+ CONFIG_RESTORE(t2)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageMulti
+
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageMulti (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeIcachePageMulti)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary and secondary instruction caches.
+//
+ .set noreorder
+ .set noat
+
+40: move t7,t8
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not work. So we do cache replace.
+// We use a MP agent facility to do that : a 4Mb area is stolen to the upper EISA space
+// and this address is notified to the MP agent. When the cache replace is done, no
+// access to the memory is done : the MP agent returns zero as value for these addresses.
+// Be careful : to use this mechanism, CONFIG register must be programmed in NON COHERENT
+// mode, so we must be protected from interrupts.
+//
+
+ li t8,PAGE_SIZE
+ add t8,t8,-1 // page mask
+ and t8,t7,t8 // offset in the page
+ sll t7,a1,PAGE_SHIFT // physical address
+ or t8,t7,t8 // physical address + offset
+
+//
+// note: we have a Unified SLC, so SecondLevelIcacheSize is set to 0
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get cache size
+
+ addu t9,t8,a2 // compute ending physical address
+ subu t9,t9,t4 // compute ending loop address
+
+ add t0,t0,-1 // mask of the cache size
+ and t8,t8,t0 // first cache line to invalidate
+ and t9,t9,t0 // last cache line to invalidate
+
+ LOAD_RPL_ADDR(a2,a3)
+
+ or t8,a2,t8 // starting address
+ or t9,a2,t9 // ending address
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+50: lw zero,0(t8) // invalidate sc
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+
+ CONFIG_RESTORE(t2)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheMulti (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheMulti)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+#endif
+
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache in the MP Agent
+//
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not update the SC
+// TagRam copy in the MP Agent. So we do cache replace.
+//
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+
+ LOAD_RPL_ADDR(a0,t5) // starting address
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+
+ .set noreorder
+ .set noat
+
+25:
+ lw zero,0(a0)
+ bne a0,a1,25b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ CONFIG_RESTORE(t2)
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+
+ .end HalpSweepDcacheMulti
+
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheMulti (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheMulti)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+#endif
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache
+// SNI machines have only an Unified SL cache
+// NOTE: PcSecondLevelIcacheSize and PcSecondLevelICacheFillSize is set to 0
+// on SNI machines
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ LOAD_RPL_ADDR(a0,a3) // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+10: lw zero,0(a0)
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ CONFIG_RESTORE(t2)
+ .set noreorder
+ .set noat
+
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+ j ra // return
+
+ .end HalSweepIcache
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageMulti (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalpZeroPageMulti, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpZeroPageMulti
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpMultiPciEccCorrector (
+// IN PVOID PhysicalAddr,
+// IN PVOID PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function corrects an ECC.
+//
+//
+// Arguments:
+//
+// a0 : virtual
+// a1 : pfn
+// a2 : length
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpMultiPciEccCorrector)
+
+//
+// to avoid Virtual Coherency Exception (unrecoverable with NT)
+// flush of the primary cache. So the physical address won't
+// be twice in the primary cache.
+//
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+//
+// first, we make a virtual address to get the corrected address in the cache
+// secondly, we flush it by cache replace mechanism
+//
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+
+15: mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// load data and flush it to correct the ECC
+//
+
+ LOAD_RPL_ADDR(a3,a2) // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+ .set noreorder
+ .set noat
+
+50: lw t7,0(t8)
+ sw t7,0(t8)
+
+ and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ lw zero,0(t7) // load Cache -> Write back old Data
+ CONFIG_RESTORE(t2)
+
+ lw t7,0(t8) // t8 fffe0400 et entree tlb ->417 =>ok
+
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60:
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+
+ .end HalpMultiPciEccCorrector
diff --git a/private/ntos/nthals/halsnip/mips/halp.h b/private/ntos/nthals/halsnip/mips/halp.h
new file mode 100644
index 000000000..d6edc0499
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/halp.h
@@ -0,0 +1,280 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/halp.h,v 1.4 1996/02/23 17:55:12 pierre Exp $")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "hal.h"
+#include "SNIhalp.h"
+#include "xm86.h"
+#include "x86new.h"
+
+
+extern ULONG HalpKeBugCheck0;
+extern ULONG HalpKeBugCheck1;
+extern ULONG HalpKeBugCheck2;
+extern ULONG HalpKeBugCheck3;
+extern ULONG HalpKeBugCheck4;
+
+#define HalpKeBugCheckEx(p0,p1,p2,p3,p4) \
+ {\
+ HalpKeBugCheck0 = p0;\
+ HalpKeBugCheck1 = p1;\
+ HalpKeBugCheck2 = p2;\
+ HalpKeBugCheck3 = p3;\
+ HalpKeBugCheck4 = p4;\
+ KeBugCheckEx(p0,p1,p2,p3,p4); \
+ }\
+
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG Par0;
+ ULONG Par1;
+ ULONG Par2;
+ ULONG Par3;
+ ULONG Par4;
+ ULONG MainBoard;
+ UCHAR TEXT[50];
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+//
+// Define function prototypes.
+//
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt(
+ VOID
+ );
+
+
+VOID
+HalpClockInterruptPciTower(
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay0(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpSendIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ );
+
+VOID
+HalpRequestIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ );
+
+VOID
+HalpProcessIpi (
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+VOID
+HalpInitMPAgent (
+ IN ULONG Number
+ );
+
+ULONG
+HalpGetMyAgent(
+ VOID
+ );
+
+BOOLEAN
+HalpCheckSpuriousInt(
+ ULONG mask
+ );
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ );
+
+ULONG
+HalpGetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ ) ;
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN ULONG BusNumber,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpInit2MPAgent(
+ VOID
+ );
+
+VOID
+HalpInitMAUIMPAgent(
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntPciMAUIStructures(
+ CCHAR Number
+ );
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+ULONG
+HalpFindEccAddr(
+ ULONG Addr, // from ECC Error Asic Register
+ PVOID ErrStatusRegister, // register which indicates parity and Ecc error
+ PVOID ErrStatusBits // bits which indicates errors in the previous register
+ );
+
+USHORT
+HalpComputeNum(
+ UCHAR *PhysAddr
+ );
+
+//
+// Define external references.
+//
+
+extern HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+extern KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+extern UCHAR HalpComponentId[];
+
+extern ULONG HalpBugCheckNumber;
+
+extern PUCHAR HalpBugCheckMessage[];
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern KINTERRUPT HalpInt3Interrupt; // Interrupt Object for IT3 tower multipro
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KSPIN_LOCK HalpInterruptLock;
+extern KSPIN_LOCK HalpMemoryBufferLock;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern PULONG HalpPciConfigAddr;
+extern PULONG HalpPciConfigData;
+extern UCHAR HalpIntAMax;
+extern UCHAR HalpIntBMax;
+extern UCHAR HalpIntCMax;
+extern UCHAR HalpIntDMax;
+#endif // _HALP_
diff --git a/private/ntos/nthals/halsnip/mips/i82c54.h b/private/ntos/nthals/halsnip/mips/i82c54.h
new file mode 100644
index 000000000..3eb213052
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/i82c54.h
@@ -0,0 +1,34 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/i82c54.h,v 1.1 1995/07/20 15:55:16 flo Exp $")
+/*++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ i82C54.h
+
+Abstract:
+
+ This header file defines the private Address structure for
+ the Intel 82C54 Timer chip found on the SNI Minitower and RM400-10.
+
+
+--*/
+
+#ifndef _I82C54_
+#define _I82C54_
+//
+// the SNI Clock (i82C54) Structure
+//
+
+typedef struct _LOCAL_8254 {
+ UCHAR counter0; /* counter 0 port */
+ char fill_1[3];
+ UCHAR counter1; /* counter 1 port */
+ char fill_2[3];
+ UCHAR counter2; /* counter 2 port */
+ char fill_3[3];
+ UCHAR control; /* control word */
+} LOCAL_8254, *PLOCAL_8254;
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/j4flshbf.s b/private/ntos/nthals/halsnip/mips/j4flshbf.s
new file mode 100644
index 000000000..a4ce6e784
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/j4flshbf.s
@@ -0,0 +1,53 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/j4flshbf.s,v 1.1 1995/07/20 15:56:14 flo Exp $")
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// j4flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/j4flshio.c b/private/ntos/nthals/halsnip/mips/j4flshio.c
new file mode 100644
index 000000000..7a785169a
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/j4flshio.c
@@ -0,0 +1,199 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/j4flshio.c,v 1.3 1996/03/04 13:14:32 pierre Exp $")
+
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a SNI MIPS R4x00 machine.
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The SNI MIPS R4x00 machines use a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush
+ // individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA read or a page read
+ // operation, then flush the data cache.
+ //
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halsnip/mips/j4prof.c b/private/ntos/nthals/halsnip/mips/j4prof.c
new file mode 100644
index 000000000..7b360f1cc
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/j4prof.c
@@ -0,0 +1,316 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (InterlockedDecrement(Number) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart = 0;
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxbeep.c b/private/ntos/nthals/halsnip/mips/jxbeep.c
new file mode 100644
index 000000000..a2a99459b
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxbeep.c
@@ -0,0 +1,132 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxbeep.c,v 1.1 1995/07/20 15:56:54 flo Exp $")
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpOnboardControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxebsup.c b/private/ntos/nthals/halsnip/mips/jxebsup.c
new file mode 100644
index 000000000..acae485bc
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxebsup.c
@@ -0,0 +1,2760 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxebsup.c,v 1.6 1996/03/04 13:15:15 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the ISA/EISA bus support for SNI systems.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Declare the interrupt structure and spinlock for the intermediate EISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpEisaInterrupt;
+KINTERRUPT HalpOnboardInterrupt;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+PADAPTER_OBJECT HalpOnboardAdapter[8];
+PADAPTER_OBJECT HalpInternalAdapters[2];
+
+//
+// Define save area for EISA interrupt mask registers and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+UCHAR HalpOnboardInterrupt1Mask;
+UCHAR HalpOnboardInterrupt2Mask;
+UCHAR HalpOnboardInterrupt1Level;
+UCHAR HalpOnboardInterrupt2Level;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ //
+ // For PCI devices we don't have to deal with
+ // map registers
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters && AdapterObject->InterfaceType != PCIBus) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+
+ return(STATUS_SUCCESS);
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the device.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject, tmpAdapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+ UCHAR DataByte;
+ PEISA_CONTROL controlBase;
+
+ if (MasterAdapterObject == NULL)
+ MasterAdapterObject = HalpAllocateAdapter(
+ 10,
+ (PVOID) -1,
+ NULL
+ );
+
+ if ((DeviceDescriptor->InterfaceType == Internal) || (DeviceDescriptor->InterfaceType == PCIBus)) {
+
+ if (DeviceDescriptor->Master) {
+
+ // The SNI machines support only Master Devices on the
+ // internal Bus; most of this stuff is the same as for EISA
+
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if ((DeviceDescriptor->ScatterGather) || (DeviceDescriptor->InterfaceType == PCIBus)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ }
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ NULL,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+ return(NULL);
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 5;
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters ) {
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ // calculated Count for allocation was 0 ...
+ // ScatterGather Device on internal Bus
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+ }
+
+ adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+ adapterObject->MasterDevice = TRUE;
+ return (adapterObject);
+
+ } // end of Master Device
+
+ } // end of Internal Interface
+
+//+++++++++++++++EISA/ISA/MCA etc ...++++++++++++++++++++++++++++++++++++
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // determine the controlBase, depending on Interface Type
+ //
+
+ //
+ // Isa and Eisa Requests have to go to the Eisa Controller on the
+ // Eisa Extension, onboard components (Floppy) have to have the InterfaceType
+ // Internal in the Device Description !!!
+ //
+ if(DeviceDescriptor->InterfaceType == PCIBus) {
+ DbgBreakPoint();
+ }
+
+ //
+ // we direct all to the
+ // PC core (also if UseChannel = TRUE and InterfaceType == Internal )
+ //
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Support for ISA local bus machines:
+ // If the driver is a Master but really does not want a channel since it
+ // is using the local bus DMA, just don't use an ISA channel.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->DmaChannel > 7) {
+
+ useChannel = FALSE;
+ }
+
+ //
+ // Determine if Eisa DMA is supported.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa) {
+
+ WRITE_REGISTER_UCHAR(&(controlBase)->DmaPageHighPort.Channel2, 0x55);
+ DataByte = READ_REGISTER_UCHAR(&(controlBase)->DmaPageHighPort.Channel2);
+
+ if (DataByte == 0x55) {
+ HalpEisaDma = TRUE;
+ }
+
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!HalpEisaDma &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+ //
+ // If the device is not a master and does scatter/Gather,
+ // then it only needs one map register
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &(controlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &(controlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ tmpAdapterObject = HalpOnboardAdapter[DeviceDescriptor->DmaChannel];
+
+
+ if (useChannel && tmpAdapterObject != NULL) {
+
+ adapterObject = tmpAdapterObject;
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpOnboardAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 5;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &(controlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &(controlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (HalpEisaDma) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+ ULONG partialLength;
+ ULONG temp;
+ PEISA_CONTROL controlBase;
+
+ // for minitower or Eisa Interface Type (default case)
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous and does not cross a 64 K bountry then
+ // just extend the buffer. The 64 K bountry restriction does not apply
+ // to Eisa systems.
+ //
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+ if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ temp = transferLength;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= *Length ) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = *Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ transferLength = temp;
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // If this is a 16 bit dma the multiply the count by 2.
+ //
+
+ if (AdapterObject->Width16Bits) {
+
+ count *= 2;
+
+ }
+
+ return(count);
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEnableOnboardInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the ISA bus (onboard) specified ISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA(onboard) interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the ISA interrupt vector.
+ //
+
+ Vector -= ONBOARD_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpOnboardInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpOnboardInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2EdgeLevel,
+ HalpOnboardInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpOnboardInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpOnboardInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1EdgeLevel,
+ HalpOnboardInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableOnboardInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the ISA(Onboard) bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the Onboard interrupt vector.
+ //
+
+ Vector -= ONBOARD_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ IN INTERFACE_TYPE InterfaceType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Isa (Desktop onboard) or
+ EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+ PEISA_CONTROL controlBase;
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Raise the IRQL while the interrupt controller is initialized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the Isa/EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0x00;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // this is for the onboard components
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpOnboardInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ HalpOnboardInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpOnboardInterrupt1Level = 0;
+ HalpOnboardInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpPciEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ USHORT PCRInOffset, Offset;
+ BOOLEAN returnValue;
+ PEISA_CONTROL controlBase;
+
+ //
+ // this is the default case
+ // the interrupts occur on the onboard PC core
+ //
+
+ PCRInOffset = ONBOARD_VECTORS;
+ Offset = ONBOARD_VECTORS;
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset += (USHORT)interruptVector;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ } else {
+
+ //
+ // This interrupt is on the second interrupt controller
+ //
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ PCRInOffset += (USHORT)(interruptVector + 8);
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ }
+ }
+ }
+}
+
+BOOLEAN
+HalpPciEisaSBDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+!!!!!!!!! This routine is only use with the chip 82375 SB (for the moment only PCI Tower)
+ * Bug : This version doesn't report an interrupt request coming from the slave interrupt controller
+ * Workaround :
+ - to detect interrupts from slave controller :
+ * master controller : read ISR to detect pending interrupt IRQ2
+ * if no valid interrupt on master controller --> interrupt from slave controller
+ - slave controller : Loop until there is no more interrupt valid
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector = 0;
+ UCHAR PollSlave;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue;
+ PEISA_CONTROL controlBase;
+ UCHAR isr;
+
+
+
+ PCRInOffset = ONBOARD_VECTORS;
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+
+
+ // read ISR
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0xb
+ );
+
+ isr = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+
+ if (isr == 0x4) interruptVector = 2;
+
+
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset += (USHORT)interruptVector;
+
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ (SPECIFIC_END_OF_INTERRUPT | interruptVector)
+ );
+ return returnValue;
+
+ }
+
+ }
+
+
+
+ do {
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ PollSlave = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+
+
+ if (PollSlave & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector = PollSlave & 0x07;
+
+
+ PCRInOffset = (USHORT)(interruptVector + 8) + ONBOARD_VECTORS;
+
+
+
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ (SPECIFIC_END_OF_INTERRUPT | interruptVector)
+ );
+
+
+ }
+
+
+
+ } while ( PollSlave & 0x80);
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ (SPECIFIC_END_OF_INTERRUPT | 0x2)
+ );
+ return returnValue;
+}
+
+/*++
+
+Routine Description:
+
+ Get the revision ID of the 82374 PCI_EISA Bridge
+
+Arguments:
+
+
+Return Value:
+
+ Returns the revision of the 82374 PCI_EISA Bridge
+
+--*/
+
+
+UCHAR HalpRevIdESC(VOID)
+{
+UCHAR save_value,Rev_ID;
+
+// save value
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_ESC_ID_82374);
+save_value = READ_REGISTER_UCHAR(PCI_ESC_DATA);
+
+//free to read
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_ESC_ID_82374);
+WRITE_REGISTER_UCHAR(PCI_ESC_DATA,0xf);
+
+//get current version
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_REV_ID_82374);
+Rev_ID =READ_REGISTER_UCHAR(PCI_ESC_DATA);
+
+//restore old value
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_ESC_ID_82374);
+WRITE_REGISTER_UCHAR(PCI_ESC_DATA,save_value);
+
+return (Rev_ID );
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxenvirv.c b/private/ntos/nthals/halsnip/mips/jxenvirv.c
new file mode 100644
index 000000000..6584e3a56
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxenvirv.c
@@ -0,0 +1,192 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxenvirv.c,v 1.2 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Siemens Nixdorf Informationssyteme AG
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Environment:
+
+ Kernel mode
+
+NOTES:
+ --- Preliminary using ARC function calls ---
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+#include "arc.h"
+
+ // preliminary calls to the ARC functions (function vector call)
+
+ /* NOTE:
+ This is strongly discouraged by the ARC specifications.
+ Only "reset"/return calls to the prom are recommended.
+ All other system access to the NVRAM should be handled
+ by operating systems functions directly. For that the
+ operating system has to know the algorithms for handling
+ those data structures (e.g. the checksum calculations).
+ Though is a drawback in terms of HW/FW-independance NT
+ seems to avoid side effects of ARC function code that way,
+ e.g. via register/stack manipulations.
+ */
+
+//
+// The following addresses are defined by ARC and handed over to the osloader.
+// For now we assume that the osloader will leave this memory part unchanged
+// for the operating system (NT), which itself also doesn't overwrite that
+// data structure.
+// We don't (yet) know yet know whether the firmware copies or maps/banks
+// runnable code into the physical memory (or if it just sets up a vector
+// into the prom). We also do not know whether the NVRAM variables are copied
+// into physical memory or mapped/banked by the (ARC) firmware.
+//
+
+//
+// Therefore we preliminary use the ARC entry vectors from ARC.H
+//
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+NOTE:
+ This implementation returns the error code ENOMEM if the output buffer
+ is too small.
+
+--*/
+
+{
+
+ PUCHAR Environment_var;
+ ULONG Index;
+ ARC_STATUS Status;
+
+ //
+ // retrieve the variable
+ //
+
+ Environment_var = (PUCHAR)ArcGetEnvironmentVariable(Variable);
+
+ if (Environment_var == (PUCHAR)NULL) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(Environment_var);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ Environment_var += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+NOTES:
+ This preliminary implementation always returns ESUCCESS even in case of
+ error.
+
+--*/
+
+{
+
+ ARC_STATUS Status;
+
+ Status = ArcSetEnvironmentVariable(Variable, Value);
+
+ switch (Status) {
+
+ case ESUCCESS:
+ break;
+
+ case ENOSPC:
+ break; // until further we assume NT can handle that
+
+ case ENOMEM:
+ default:
+ Status = ENOMEM;
+ break;
+ }
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/jxhwsup.c b/private/ntos/nthals/halsnip/mips/jxhwsup.c
new file mode 100644
index 000000000..07bd0f121
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxhwsup.c
@@ -0,0 +1,2250 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxhwsup.c,v 1.7 1996/03/12 14:56:20 pierre Exp $")
+/*++
+
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+
+Environment:
+
+ Kernel mode
+
++++*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+extern VOID NtClose();
+
+typedef struct {
+ PVOID MmContiguousAddr;
+ PVOID MmMapIoSpaceAddr;
+ PVOID Next;
+} HALP_MEMORY;
+
+HALP_MEMORY HalpMemoryBuffer ={0,0,0}, * HalpMemoryBufferPt;
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+
+//
+// Map buffer parameters. These are initialized in HalInitSystem
+//
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+ This routine is used when the machine is less than 16Mb memory.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+ PULONG Page;
+ PMDL mdl;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the additional pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+// (NumberOfPages * PAGE_SIZE) / 0x10000 +
+ 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocation amount so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+ return(FALSE);
+
+ }
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocating a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disable. Importent for DMA if we
+ // have more than 16Mb memory in our SNI
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ // (We use MmAllocateContiguousMemory because we need a specific physical limit to the address)
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ //
+ // flush the new allocated memory area
+ // because we are going to use it uncached.
+ //
+
+ mdl = MmCreateMdl(NULL,MapBufferVirtualAddress,NumberOfPages * PAGE_SIZE);
+ Page = (PULONG) (mdl + 1);
+ for (i=0;i < NumberOfPages; ++i) {
+ *Page = (MapBufferPhysicalAddress >> PAGE_SHIFT)+i;
+ ++Page;
+ }
+ KeFlushIoBuffers(mdl,TRUE,TRUE);
+
+ //
+ // Map registers need to be uncached.
+ //
+
+ physicalAddress.LowPart = MapBufferPhysicalAddress;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmMapIoSpace(
+ physicalAddress,
+ NumberOfPages * PAGE_SIZE,
+ FALSE
+ );
+
+ }
+
+ //
+ // Initialize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress ) ){
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this boundary.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+#if 0
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry and that a 64K physical boundary is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!HalpEisaDma &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this boundary.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+#endif
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ physically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1 &&
+ MapRegistersPerChannel) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( ((MAXIMUM_MAP_BUFFER_SIZE*9)/8) / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *IoAdapterObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoAdapterObjectType,
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ NtClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+
+
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+
+
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+
+ return AdapterObject;
+
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, (PCCHAR)bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory( (PCCHAR)bufferAddress, mapAddress, Length);
+
+
+ }
+
+}
+
+PTRANSLATION_ENTRY
+HalpAcquireMapBuffers(
+ ULONG NumberOfMapRegisters,
+ PADAPTER_OBJECT MasterAdapter)
+{
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+ PTRANSLATION_ENTRY MapRegisterBase;
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber > MasterAdapter->NumberOfMapRegisters) {
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ if (MapRegisterNumber > MasterAdapter->NumberOfMapRegisters)
+ MapRegisterNumber = (ULONG)-1;
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+// InsertTailList( &MasterAdapter->AdapterQueue,
+// &AdapterObject->AdapterQueue
+// );
+// Busy = 1;
+
+ MapRegisterBase = NULL;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ return(MapRegisterBase);
+}
+
+
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ ULONG numberOfMapRegisters;
+ PTRANSLATION_ENTRY MapRegisterTranslation;
+ PHYSICAL_ADDRESS physicalAddress;
+ KIRQL Irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (AdapterObject->InterfaceType != PCIBus) {
+
+ // address < 16Mb (isa compatibility) - cut to 64k
+ MapRegisterTranslation = HalpAcquireMapBuffers(numberOfMapRegisters,MasterAdapterObject);
+ if (MapRegisterTranslation == NULL) return(NULL);
+ virtualAddress = MapRegisterTranslation->VirtualAddress;
+ LogicalAddress->LowPart = MapRegisterTranslation->PhysicalAddress;
+ LogicalAddress->HighPart = 0;
+
+ } else {
+
+ // no limitation : address contiguous because we cannot use map registers
+ // for scatter-gather in this function
+ physicalAddress.LowPart = 0x7FFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (CacheEnabled == FALSE) {
+ PULONG Page;
+ ULONG i;
+ PMDL mdl;
+
+ //
+ // flush the new allocated memory area
+ // because we are going to use it uncached.
+ //
+
+ mdl = MmCreateMdl(NULL,virtualAddress,Length);
+ Page = (PULONG) (mdl + 1);
+ for (i=0;i < numberOfMapRegisters; ++i) {
+ *Page = (((LogicalAddress->LowPart)) >> PAGE_SHIFT)+i;
+ ++Page;
+ }
+ KeFlushIoBuffers(mdl,TRUE,TRUE);
+
+ // save the allocated address to be able to free it later.
+
+ KeAcquireSpinLock(&HalpMemoryBufferLock,&Irql);
+ HalpMemoryBufferPt = &HalpMemoryBuffer;
+ while (HalpMemoryBufferPt->Next) HalpMemoryBufferPt = HalpMemoryBufferPt->Next;
+ HalpMemoryBufferPt->Next = ExAllocatePool(PagedPool,sizeof(HALP_MEMORY));
+ HalpMemoryBufferPt = HalpMemoryBufferPt->Next;
+ HalpMemoryBufferPt->Next = NULL;
+ HalpMemoryBufferPt->MmContiguousAddr = virtualAddress;
+
+ // second mapping to get uncached addresses...
+ virtualAddress = MmMapIoSpace(
+ *LogicalAddress,
+ Length,
+ FALSE
+ );
+
+ HalpMemoryBufferPt->MmMapIoSpaceAddr = virtualAddress;
+ KeReleaseSpinLock(&HalpMemoryBufferLock,Irql);
+ }
+ }
+// KeStallExecutionProcessor(50000);
+ return(virtualAddress);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase,resultat;
+ ULONG numberOfMapRegisters;
+// ULONG mapRegisterNumber;
+ ULONG i;
+ HALP_MEMORY * HalpMemoryPrevious;
+ KIRQL Irql;
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (AdapterObject->InterfaceType == PCIBus) {
+
+ if (CacheEnabled == FALSE) {
+
+ KeAcquireSpinLock(&HalpMemoryBufferLock ,&Irql);
+ HalpMemoryPrevious = HalpMemoryBufferPt = &HalpMemoryBuffer;
+ while (HalpMemoryBufferPt) {
+ if (HalpMemoryBufferPt->MmMapIoSpaceAddr == VirtualAddress) {
+ MmUnmapIoSpace(VirtualAddress, Length);
+ MmFreeContiguousMemory(HalpMemoryBufferPt->MmContiguousAddr);
+ HalpMemoryPrevious->Next = HalpMemoryBufferPt->Next;
+ ExFreePool(HalpMemoryBufferPt);
+ KeReleaseSpinLock(&HalpMemoryBufferLock,Irql);
+ return;
+ }
+ HalpMemoryPrevious = HalpMemoryBufferPt;
+ HalpMemoryBufferPt = HalpMemoryBufferPt->Next;
+ }
+ KeReleaseSpinLock(&HalpMemoryBufferLock,Irql);
+
+ } else MmFreeContiguousMemory(VirtualAddress);
+
+ return;
+
+ }
+
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ // mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase;
+ resultat = NULL;
+
+ for (i = 0; i < MasterAdapterObject->NumberOfMapRegisters; i++) {
+
+ if (mapRegisterBase->VirtualAddress == VirtualAddress) {
+ resultat = mapRegisterBase;
+ break;
+ }
+
+ mapRegisterBase++;
+
+ }
+
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) resultat,
+ numberOfMapRegisters
+ );
+
+ return;
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0);
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG)AdapterObject->MapRegisterBase |NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if
+ // there are no requests in the master adapter queue, then
+ // IoFreeMapRegisters will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+
+ //
+ // SNI only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+
+ UNREFERENCED_PARAMETER( BusNumber );
+
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // There is no difference between IoSpace and MemorySpace in the internal Interface.
+ // Mips Processors have only memory mapped I/O
+ //
+
+ *AddressSpace = 0;
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ return(TRUE);
+ }
+
+ if (InterfaceType == PCIBus) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ if (*AddressSpace == 1) {
+
+ //
+ // PCI IO Space
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | PCI_IO_PHYSICAL_BASE;
+
+ } else {
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | PCI_MEMORY_BELOW1M_PHYSICAL_BASE;
+
+ }
+
+ *AddressSpace = 0;
+
+ return (TRUE);
+ }
+
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ DebugPrint(("HAL: HalTranslateBusAddress: WRONG INTERFACE (%d) ", InterfaceType));
+
+ //
+ // Not on this system -- return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ // we always direct Isa and Eisa Adresses to the extension board
+ //
+
+ *AddressSpace = 0;
+
+ TranslatedAddress->LowPart = BusAddress.LowPart |
+ EISA_CONTROL_PHYSICAL_BASE;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ // we always direct Isa and Eisa Adresses to the extension board
+ //
+
+ *AddressSpace = 0;
+
+ TranslatedAddress->LowPart = BusAddress.LowPart |
+ EISA_MEMORY_PHYSICAL_BASE;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+
+ return(TRUE);
+
+ }
+
+ DebugPrint(("HAL: HalTranslateBusAddress: Beeing in the very bad tree\n"));
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+ return(FALSE);
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+
+ case PCIConfiguration:
+ DataLength = HalpGetPCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+
+ switch (BusDataType) {
+
+ case PCIConfiguration:
+ DataLength = HalpSetPCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+ default:
+ break;
+
+ }
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ switch (BusType) {
+
+ case PCIBus:
+
+ return HalpAssignPCISlotResources (BusNumber,
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ SlotNumber,
+ AllocatedResources);
+ break;
+
+ default:
+ return STATUS_NOT_SUPPORTED;
+ break;
+
+ }
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ if ((*pResourceList)->InterfaceType == PCIBus)
+ return HalpAdjustPCIResourceList ((*pResourceList)->BusNumber, pResourceList);
+
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/jxmapio.c b/private/ntos/nthals/halsnip/mips/jxmapio.c
new file mode 100644
index 000000000..b9d54e3ca
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxmapio.c
@@ -0,0 +1,120 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxmapio.c,v 1.2 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 - 1994 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a SNI
+ or R4x00 system.
+ For use of EISA I/O Space during phase 0 we go via KSEG1_BASE
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase =(PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+//
+// be careful : HalpOnboardControlBase value is used before the init in xxinithl.c
+//
+
+PVOID HalpOnboardControlBase=(PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+PVOID HalpEisaMemoryBase =(PVOID) (EISA_MEMORY_PHYSICAL_BASE | KSEG1_BASE);
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R4x00 SNI
+ system (Phase 1, so the mapping goes via MmMapIoSpace()).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ // (64KB I/O Space)
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ HalpOnboardControlBase = HalpEisaControlBase;
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA/Isa slot.
+ // (first 1MB only to have access to Card Bioses)
+ // We do not have to call HalTranslateBusAddress on our SNI machines,
+ // because we always use EISA_MEMORY_PHYSICAL_BASE for Extension Cards
+ // on all machines
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_MEMORY_PHYSICAL_BASE;
+ HalpEisaMemoryBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase == NULL) ||
+ (HalpOnboardControlBase == NULL) ||
+ (HalpEisaMemoryBase == NULL)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxport.c b/private/ntos/nthals/halsnip/mips/jxport.c
new file mode 100644
index 000000000..d56b8c559
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxport.c
@@ -0,0 +1,805 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxport.c,v 1.1 1995/07/20 15:58:02 flo Exp $")
+
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R4000 system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+// set the correct divisor for the SNI serial ports / quartz clock
+#if defined(SNI)
+ #undef BAUD_RATE_9600
+ #undef BAUD_RATE_19200
+ #define BAUD_RATE_9600 12
+ #define BAUD_RATE_19200 6
+#endif // SNI
+
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#if defined(USE_COM2)
+
+// Assume COM2 for the kernel debugger.
+
+#define SP_READ ((PSP_READ_REGISTERS) ((ULONG)HalpOnboardControlBase + SERIAL1_RELATIVE_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((ULONG)HalpOnboardControlBase + SERIAL1_RELATIVE_BASE))
+
+
+#else
+
+// Assume COM1 for the kernel debugger.
+
+#define SP_READ ((PSP_READ_REGISTERS) ((ULONG)HalpOnboardControlBase + SERIAL0_RELATIVE_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((ULONG)HalpOnboardControlBase + SERIAL0_RELATIVE_BASE))
+
+#endif
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = BAUD_RATE_19200;
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+//
+// BUGBUG the FW configuration sets the serial 0 Port config relativ to
+// the EISA/ISA Base Address, so the serial driver doesn't get the right
+// information when debugging is enabled ....
+//
+
+#if defined(USE_COM2)
+ KdComPortInUse=(PUCHAR)(SERIAL1_PHYSICAL_BASE);
+#else
+ KdComPortInUse=(PUCHAR)(SERIAL0_PHYSICAL_BASE);
+#endif
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxreturn.c b/private/ntos/nthals/halsnip/mips/jxreturn.c
new file mode 100644
index 000000000..f5f7c4711
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxreturn.c
@@ -0,0 +1,286 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxreturn.c,v 1.6 1996/03/12 16:28:26 pierre Exp $")
+
+/*++
+
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "SNIregs.h"
+#include "mpagent.h"
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ );
+VOID
+HalpClearVGADisplay(
+ VOID
+ );
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ UCHAR DataByte;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ // power off asked by DCU/IDC (power - fan or ... failure)
+ if (((ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) != (ULONG)-1) &&
+ (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipHalInfo == 1))
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine(
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext
+ );
+ for (;;) {}
+
+ case HalPowerDownRoutine:
+
+ // power off always done by DCU
+
+ if ((ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) != (ULONG)-1)
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine(
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext
+ );
+ //
+ // PowerOff is done by the SNI machines by writing the Power_Off bit to the machine control register ...
+ //
+ if (HalpIsTowerPci){
+ WRITE_REGISTER_ULONG((PULONG) PCI_TOWER_DCU_CONTROL, DC_POWEROFF);
+ }else{
+ WRITE_REGISTER_UCHAR((PUCHAR) PCI_MCR_ADDR, PCI_MCR_POWEROFF);
+ }
+
+ for (;;) {} // hang looping
+
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ // power off asked by DCU/IDC (power - fan or ... failure)
+ if (((ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) != (ULONG)-1) &&
+ (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipHalInfo == 1))
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine(
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext
+ );
+
+ if (HalpIsMulti) {
+ ULONG Mask,i;
+
+ for (i=0;i<HalpIsMulti;i++)
+ if (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number])
+ Mask |= 1<<i;
+
+
+ Mask = Mask & ~(PCR->SetMember);
+#if DBGG
+ DbgPrint("Send message RESTART to maskcpu = %x \n",Mask);
+#endif
+
+ HalpRequestIpi(Mask,MPA_RESTART_MESSAGE);
+ //
+ // if this is not the Boot CPU, we call a special Firmware entry to stop it
+ //
+
+ //
+ // remove this processor from the list of active processors
+ //
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number]=0;
+
+ if (PCR->Number ) {
+
+#if DBGG
+ DbgPrint(" Reinit slave %x \n", ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave);
+#endif
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
+
+ } else HalpBootCpuRestart();
+ }
+
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalDisplayString("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+ HalDisplayString(" ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" º Restart in Progress º\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ DataByte = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(10000);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ ArcReboot();
+
+ for (;;) ;
+
+ default:
+ DbgPrint("HalReturnToFirmware invalid argument\n");
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the firmware Arcreboot routine.
+ it waits until all other cpu's have beet shut down.
+ this code is executed only on the boot cpu
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Does not return.
+
+--*/
+{
+ UCHAR DataByte;
+ ULONG cpt;
+
+
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalDisplayString("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+ HalDisplayString(" ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" º Restart in Progress º\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ cpt = 0;
+ while(*(PULONG)(& (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[0]) )) {
+ KeStallExecutionProcessor(500000);
+ ++cpt;if (cpt == 20) break;
+ }
+ //
+ // if there are still ssome processors active, we do a reset of the entire machine
+ //
+ if (*(PULONG)(& (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[0]) )) {
+
+#if DBG
+ DbgPrint(" Some processors did not answer . Reset machine started. \n");
+#endif
+ if (HalpIsTowerPci) {
+ WRITE_REGISTER_ULONG((PULONG) PCI_TOWER_DCU_CONTROL, DC_SWRESET);
+ }else {
+
+ WRITE_REGISTER_UCHAR((PUCHAR) PCI_MCR_ADDR, PCI_MCR_SOFTRESET);
+ }
+ } else {
+
+#if DBG
+ DbgPrint("Reboot started \n");
+#endif
+
+ }
+
+ DataByte = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(10000);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+
+ ArcReboot();
+
+ for (;;) ;
+}
+
+
+
+
+
diff --git a/private/ntos/nthals/halsnip/mips/jxsysint.c b/private/ntos/nthals/halsnip/mips/jxsysint.c
new file mode 100644
index 000000000..1e32051c2
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxsysint.c
@@ -0,0 +1,335 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxsysint.c,v 1.3 1996/03/04 13:19:54 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the onboard interrupts, then
+ // disable the onboard interrrupt.
+ // This may be an Isa (Desktop) or Isa/Eisa (Minitower) Interrupt
+ //
+
+ if (Vector >= ONBOARD_VECTORS &&
+ Vector <= MAXIMUM_ONBOARD_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableOnboardInterrupt(Vector);
+ }
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt on the Eisa Backplane (Eisa Extension).
+ //
+
+ else if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the onboard interrupts, then
+ // enable the onboard interrrupt and set the Level/Edge register to latched,
+ // because the onboard Opti 499 (Desktop)is a real Isa Controler and cannot share interrupts.
+ // even the i82350 Chipset on the Minitower cannot share interrupts (why ?)
+ //
+
+ if (Vector >= ONBOARD_VECTORS &&
+ Vector <= MAXIMUM_ONBOARD_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+
+ HalpEnableOnboardInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt in the Eisa Backplane (Eisa Extension) and set the Level/Edge register.
+ //
+
+ else if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+
+
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+
+ *Affinity = 1;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ if (BusInterruptVector >= ONBOARD_VECTORS &&
+ BusInterruptVector <= MAXIMUM_ONBOARD_VECTOR ) {
+
+ //
+ // this is one of the onboard components of the PC core
+ // (floppy, serial, parallel, mouse etc.)
+ // they should be configured in the Firmware tree with an Offset of
+ // ONBOARD_VECTORS (e.g. 0x10 to make them different to the real onboard components
+ // like scsi or ethernet) and with an Irql of EISA_DEVICE_LEVEL (actually 4)
+ // we need Firmware release 1.04 or later ...
+ //
+
+ //
+ // Bus interrupt vector 2 of Onboard PC core interrupts is actually mapped to
+ // vector 9 in the Isa/Eisa hardware.
+ //
+
+ if (BusInterruptVector == ONBOARD_VECTORS + 2) {
+ BusInterruptVector = ONBOARD_VECTORS + 9;
+ }
+
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ return(BusInterruptVector);
+ }
+
+ //
+ // this is another special case of the DCU Interrupt for PCI Tower
+ // we have an agreement with the DCU developer
+ // we meet each other on InterruptVector 15, so we limit the Irql to Device Level
+ //
+
+ if ( BusInterruptVector == DCU_VECTOR ) {
+
+ if (HalpIsTowerPci) {
+ *Irql = (KIRQL) INT6_LEVEL;
+ // if more than one proc , DCU Interrupt is connected to proc 1
+ if (HalpIsMulti !=0) *Affinity = 2;
+ return(BusInterruptVector);
+ } else {
+ *Irql = EISA_DEVICE_LEVEL;
+ return(BusInterruptVector);
+ }
+
+ }
+
+
+ //
+ // these are the "real" Onboard components (scsi and Ethernet)
+ // Return the passed parameters.
+ //
+
+ *Irql = (KIRQL) BusInterruptLevel;
+
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType == PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Irql = (KIRQL) SCSIEISA_LEVEL;
+
+
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+ }
+
+ //
+ // Isa/Eisa Interrupts which are not configured in the Firmware
+ // (boards should be located in the Expansion Slots ...)
+ // The IRQL level is always equal to the EISA level.
+ // WARNING: some driver call HalGetInterruptVector
+ // with the BusInterruptLevel == BusInterruptVector
+ // but some call it with different values.
+ // In this part of the source tree we match the Jazz reference
+ // sources (see Internal handling; which is different)
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt 2 is actually mapped to bus interrupt 9 in the Isa/Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // all Isa/Eisa Interrupts should be handled by the onboard PC core
+ //
+
+ return(BusInterruptLevel + ONBOARD_VECTORS);
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxtime.c b/private/ntos/nthals/halsnip/mips/jxtime.c
new file mode 100644
index 000000000..a13ed8ec1
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxtime.c
@@ -0,0 +1,359 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxtime.c,v 1.2 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1993 SNI
+
+Module Name:
+
+ SNItime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R4000 SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+
+#define NVINDEX_STATE 0x6
+#define NVSTATE_TODVALID 0x1
+
+
+
+#define bcd_to_dec(x) ( ((((x) >> 4 ) & 0xf ) * 10 ) + ((x) & 0xf) )
+#define dec_to_bcd(x) ( (((x) / 10) << 4) | ((x) % 10) )
+
+
+#define RTC_NVRAM_SIZE 0x7ff // NVRAM size on this chip
+
+// definitions for rtc 146818
+
+#define RTC_SECS 0
+#define RTC_SECA 1
+#define RTC_MINS 2
+#define RTC_MINA 3
+#define RTC_HOURS 4
+#define RTC_HOURA 5
+#define RTC_DAYW 6
+#define RTC_DAYM 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+#define RTC_REGA 10
+#define RTC_REGB 11
+#define RTC_REGC 12
+#define RTC_REGD 13
+#define RTC_MEM1 14
+#define RTC_MEM2 128
+
+/*
+ * Register B bit definitions
+ */
+#define RTCB_SET 0x80 /* inhibit date update */
+#define RTCB_PIE 0x40 /* enable periodic interrupt */
+#define RTCB_AIE 0x20 /* enable alarm interrupt */
+#define RTCB_UIE 0x10 /* enable update-ended interrupt */
+#define RTCB_SQWE 0x08 /* square wave enable */
+#define RTCB_DMBINARY 0x04 /* binary data (0 => bcd data) */
+#define RTCB_24HR 0x02 /* 24 hour mode (0 => 12 hour) */
+#define RTCB_DSE 0x01 /* daylight savings mode enable */
+
+/* Time of Day Clock */
+
+struct todc {
+ short htenths;
+ short hsecs;
+ short hmins;
+ short hhours;
+ short hdays;
+ short hweekday;
+ short hmonth;
+ short hyear;
+};
+
+/* masks to get valid information */
+
+#define MASK_CENT_SECS 0xFF
+#define MASK_SECS 0x7F
+#define MASK_MINS 0x7F
+#define MASK_HOURS 0x3F
+#define MASK_DAY_W 0x07
+#define MASK_DAY_M 0x3F
+#define MASK_MONTH 0x1F
+#define MASK_YEAR 0xFF
+
+//
+// the reference year (we have only two digits for the year on the chip)
+//
+
+#define YRREF 1900
+
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ );
+
+VOID
+HalpWrite146818(struct todc *todp, PUCHAR index, PUCHAR data);
+
+VOID
+HalpRead146818(struct todc *todp, PUCHAR index, PUCHAR data);
+
+VOID
+HalpPciReadTodc(struct todc *todp);
+
+VOID
+HalpPciWriteTodc(struct todc *todp);
+
+UCHAR
+HalpReadRegister146818(PUCHAR index, PUCHAR data, int reg);
+
+VOID HalpWriteRegister146818(PUCHAR index, PUCHAR data, int reg, UCHAR val);
+
+
+
+/* Calendar clock : For PCI Minitower and Desktop systems, the RTC is part of
+ * --------------- the SUPER_IO pc87323.
+ * It is software compatible with rtc146818.
+ */
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. this comment stand in jxtime.c:
+ This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ register CSHORT month, dayweek, daymonth, year, hours, mins, secs, msecs;
+ struct todc ltodc;
+ KIRQL oldIrql;
+
+
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+
+ HalpPciReadTodc(&ltodc);
+
+ KeLowerIrql(oldIrql);
+
+ msecs = 0;
+ secs = ltodc.hsecs;
+ mins = ltodc.hmins;
+ hours = ltodc.hhours;
+ daymonth = ltodc.hdays;
+ dayweek = ltodc.hweekday;
+ month = ltodc.hmonth;
+ year = ltodc.hyear;
+
+
+ if (TimeFields)
+ {
+ TimeFields->Year = year+YRREF;
+ TimeFields->Month = month;
+ TimeFields->Day = daymonth;
+ TimeFields->Weekday = dayweek;
+ TimeFields->Hour = hours;
+ TimeFields->Minute = mins;
+ TimeFields->Second = secs;
+ TimeFields->Milliseconds = msecs;
+ }
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. this comment stand in jxtime.c:
+ This routine is required to provide anq synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ struct todc ltodc;
+
+ KIRQL oldIrql;
+ UCHAR year, month, daymonth, dayweek, hours, mins, secs, msecs;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ // this part has to be written
+ // if (...) return FALSE;
+ year = (UCHAR) ( (TimeFields->Year - YRREF) % 100 );
+ month = (UCHAR) TimeFields->Month;
+ daymonth = (UCHAR) TimeFields->Day;
+ dayweek = (UCHAR) TimeFields->Weekday;
+ hours = (UCHAR) TimeFields->Hour;
+ mins = (UCHAR) TimeFields->Minute;
+ secs = (UCHAR) TimeFields->Second;
+ msecs = (UCHAR) TimeFields->Milliseconds;
+
+
+ ltodc.htenths = 0;
+ ltodc.hsecs = secs;
+ ltodc.hmins = mins;
+ ltodc.hhours = hours;
+ ltodc.hdays = daymonth;
+ ltodc.hweekday = dayweek;
+ ltodc.hmonth = month;
+ ltodc.hyear = year;
+
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+
+ HalpPciWriteTodc(&ltodc);
+
+ KeLowerIrql(oldIrql);
+
+
+
+ return TRUE;
+
+}
+/* HAL_RTODC() */
+VOID
+HalpPciReadTodc(struct todc *todp)
+{
+ PUCHAR rtc_index = (PUCHAR) RTC_ADDR_PCIMT;
+ PUCHAR rtc_data = (PUCHAR) RTC_DATA_PCIMT;
+ HalpRead146818(todp,rtc_index,rtc_data);
+}
+
+/* HAL_WTODC() */
+VOID
+HalpPciWriteTodc(struct todc *todp)
+{
+
+ PUCHAR rtc_index = (PUCHAR) RTC_ADDR_PCIMT;
+ PUCHAR rtc_data = (PUCHAR)RTC_DATA_PCIMT;
+ HalpWrite146818(todp, rtc_index, rtc_data);
+}
+
+
+VOID
+HalpWrite146818(struct todc *todp, PUCHAR index, PUCHAR data)
+{
+ UCHAR temp;
+ /*
+ * Write information to rtc146818 chip
+ */
+ HalpWriteRegister146818(index,data,RTC_REGB,temp=(HalpReadRegister146818(index,data,RTC_REGB)|RTCB_SET));
+ HalpWriteRegister146818(index,data,RTC_SECS,dec_to_bcd(todp->hsecs)&MASK_SECS);
+ HalpWriteRegister146818(index,data,RTC_MINS,dec_to_bcd(todp->hmins)&MASK_MINS);
+ HalpWriteRegister146818(index,data,RTC_HOURS,dec_to_bcd(todp->hhours)&MASK_HOURS);
+ HalpWriteRegister146818(index,data,RTC_DAYM,dec_to_bcd(todp->hdays)&MASK_DAY_M);
+ HalpWriteRegister146818(index,data,RTC_DAYW,dec_to_bcd(todp->hweekday)&MASK_DAY_W);
+ HalpWriteRegister146818(index,data,RTC_MONTH,dec_to_bcd(todp->hmonth)&MASK_MONTH);
+
+ HalpWriteRegister146818(index,data,RTC_YEAR,dec_to_bcd(todp->hyear)&MASK_YEAR);
+
+
+
+ HalpWriteRegister146818(index,data,RTC_REGB, temp &= ~RTCB_SET);
+}
+
+VOID
+HalpRead146818(struct todc *todp, PUCHAR index, PUCHAR data)
+{
+ UCHAR temp;
+
+ HalpWriteRegister146818(index,data,RTC_REGB,temp=(HalpReadRegister146818(index,data,RTC_REGB)|RTCB_SET));
+
+ todp->htenths = 0;
+ todp->hsecs=bcd_to_dec(HalpReadRegister146818(index,data,RTC_SECS)&MASK_SECS);
+ todp->hmins=bcd_to_dec(HalpReadRegister146818(index,data,RTC_MINS)&MASK_MINS);
+ todp->hhours=bcd_to_dec(HalpReadRegister146818(index,data,RTC_HOURS)&MASK_HOURS);
+ todp->hdays=bcd_to_dec(HalpReadRegister146818(index,data,RTC_DAYM)&MASK_DAY_M);
+ todp->hweekday=bcd_to_dec(HalpReadRegister146818(index,data,RTC_DAYW)&MASK_DAY_W);
+ todp->hmonth=bcd_to_dec(HalpReadRegister146818(index,data,RTC_MONTH)&MASK_MONTH);
+ todp->hyear=bcd_to_dec(HalpReadRegister146818(index,data,RTC_YEAR)&MASK_YEAR);
+
+ HalpWriteRegister146818(index,data,RTC_REGB, temp &= ~RTCB_SET);
+}
+
+
+
+UCHAR
+HalpReadRegister146818(PUCHAR index, PUCHAR data, int reg)
+{
+ WRITE_REGISTER_UCHAR(index,reg);
+ // *index = reg;
+ // wbflush();
+ // return(*data)
+ return(READ_REGISTER_UCHAR(data));
+}
+
+VOID HalpWriteRegister146818(PUCHAR index, PUCHAR data, int reg, UCHAR val)
+{
+ WRITE_REGISTER_UCHAR(index,reg);
+// *index = reg;
+// wbflush();
+ WRITE_REGISTER_UCHAR(data, val);
+// *data = val;
+// wbflush();
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/jxusage.c b/private/ntos/nthals/halsnip/mips/jxusage.c
new file mode 100644
index 000000000..b39cab418
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxusage.c
@@ -0,0 +1,47 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxusage.c,v 1.1 1995/07/20 15:58:57 flo Exp $")
+
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/halsnip/mips/mpagent.c b/private/ntos/nthals/halsnip/mips/mpagent.c
new file mode 100644
index 000000000..7420911ff
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/mpagent.c
@@ -0,0 +1,745 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/mpagent.c,v 1.7 1996/02/23 17:55:12 pierre Exp $")
+
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ mpagent.c
+
+Abstract:
+
+ This module implements the routines dealing with the SNI MP Agent on
+ SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "MPagent.h"
+
+extern VOID
+KeUpdateRunTime(
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+
+VOID
+HalpInitMPAgent(
+ IN ULONG Number
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the MutiProcessor_Agent chipset:
+ - reset an eventual MP_Agent fatal error,
+ - enable message passing (send/receive),
+ - fix routage for internal IT -> external IT,
+ - enable the internal interrupts,
+ - fix the mask for wanted external interrupts,
+ - disable Low Process Priority mode for
+ external interrupts,
+ - enable cache replace operator and update the
+ 'cache_rpl_buffer' global variable with a KSEG0
+ 4 Mb reserved address.
+
+Arguments:
+
+ Number : Logical number of the processor to be initialised
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ULONG reg;
+
+
+
+ //
+ // set up the snooper register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
+ reg |= (MPA_ENRCVMESS | /* enable message receiving */
+ MPA_RSTSNPERR | /* reset an eventual old MP_Agent fatal error */
+ MPA_ENLINK | /* enable read and link command */
+ MPA_ENCOHREQ | /* enable coherency on the MP bus for this agent */
+ 0); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
+
+ // RM300 with mono-processors boards with mp-agent can be configured with 1Mb cache,
+ // but the MP-agent tag RAM can be configured with 4Mb or 2MB. So we disable the MPbus error.
+ // (With monoprocessor machine the MP-agent tag ram is not useful at all ...)
+
+ if ((HalpIsMulti) || (HalpIsTowerPci))
+ reg &= ~(MPA_RSTSNPERR); /* enable new interrupt for MP_Agent fatal error */
+
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
+
+
+ //
+ // cpu1reg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpuda1reg)); /* read the current value */
+ reg &= ~(MPA_ENDIRECT | /* disable LPP mechanism */
+ MPA_ENTESTIT | /* disable interrupt test mode (interrupts from MPBus) */
+ MPA_SELITI_MASK | /* reset old internal interrupt routage */
+ 0); /* keep other fields */
+
+ reg |= MPA_SELITI_SR_IP7; /* send internal interrupts on external interrupt SR_IP7*/
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpuda1reg), reg);
+
+ //
+ // cpureg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ reg &= ~(MPA_ENINT_MASK | /* reset old values for interrupts */
+ MPA_INTCONF_MASK| /* force falling edge for all interrupts */
+ MPA_ENSHARED | /* don't put optimal mode for KERNEL */
+ 0);
+ reg |= (MPA_ENSENDMSG | /* enable sending message */
+ MPA_ENINT_MPBERR | /* enable internal interrupt for MP_Agent fatal error */
+ MPA_ENINT_ITMSG1 | /* enable internal interrupt for message1 register */
+ MPA_ENINT_ITMSG2 | /* enable internal interrupt for message2 register */
+ MPA_ENINT_ITMSG3 | /* enable internal interrupt for message3 register */
+ MPA_INTMSK | /* mask sent during external request stage */
+ 0); /* keep other fields */
+
+ //
+ // external Interrupts routing in the MP Agent
+ //
+
+ // pci tower -> force raising edges for all interrupts
+
+ if (HalpIsTowerPci) reg |= MPA_INTCONF_MASK;
+
+ // pci multi-processor machines => interrupts are centralized.
+
+ if (Number == 0) reg |= MPA_ENINT_SR_IP3; // device interrupts are only processed by bootcpu.
+ // Timer processor 1 : IP5 for RM300 - IP6 for RM400
+
+ if (Number == 1)
+ if (!HalpIsTowerPci) reg |= MPA_ENINT_SR_IP5;
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
+
+ //
+ // clear pending interrupts by reading of the message registers
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg1));
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg2));
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg3));
+
+ // Modif PS 20 June -> Don't use the operator with ASIC PCI -> BUGBUG
+
+ if (HalpMpaCacheReplace == MPAGENT_RESERVED | KSEG0_BASE) {
+ reg = ((MPAGENT_RESERVED & // put the reserved physical address (4Mb long)
+ MPA_OP_ADDR_MASK) |
+ MPA_OP_ENABLE); // enable the operator
+ } else {
+ reg = 0;
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->mem_operator), reg); // for all procs (done for proc 0 in xxcache)
+
+}
+
+
+VOID
+HalpInitMAUIMPAgent(
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the MutiProcessor_Agent chipset:
+ - enable MAUI interrupt on the current processor
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ULONG reg;
+
+ //
+ // cpureg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+
+ reg |= MPA_ENINT_SR_IP6;
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
+}
+
+
+VOID
+HalRequestIpi(
+ IN ULONG CpuMask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ULONG physmask, cpt;
+PRESTART_BLOCK NextRestartBlock;
+
+ // CpuMask is a logical mask. We must use a mask with the physical
+ // numbers of cpus to communicate with the MP_Agent.
+
+ physmask = 0;cpt = 0;
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ while (NextRestartBlock != NULL) {
+
+ if (CpuMask & ( 1 << cpt)) {
+ physmask = (1 << (NextRestartBlock->ProcessorId));
+ HalpSendIpi(physmask,MPA_KERNEL_MESSAGE);
+ }
+ ++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+}
+
+ VOID
+HalpRequestIpi(
+ IN ULONG CpuMask,
+ IN ULONG msg_data
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ULONG physmask, cpt;
+PRESTART_BLOCK NextRestartBlock;
+
+ // CpuMask is a logical mask. We must use a mask with the physical
+ // numbers of cpus to communicate with the MP_Agent.
+
+ physmask = 0;cpt = 0;
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ while (NextRestartBlock != NULL) {
+
+ if (CpuMask & ( 1 << cpt)) {
+ physmask = (1 << (NextRestartBlock->ProcessorId));
+ HalpSendIpi(physmask,msg_data);
+ }
+ ++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+}
+
+
+VOID
+HalpSendIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ )
+/*++
+
+Routine Description:
+
+ This routine sends an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ pcpumask - Supplies the set of processors that are sent an interprocessor
+ interrupt. It contains physical numbers.
+
+ msg_data _ Supplies the kind of message to be send : kernel demand or HAL internal demand.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+KIRQL OldIrql;
+LONG msg_retries, watchdog;
+ULONG msg_address, msg_status, itpend;
+
+
+ if (!pcpumask || !HalpIsMulti) {
+
+ return;
+
+ }
+
+ //
+ // Raise IRQL to ??? level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ //
+ // form the Message Address register (Message register 1 / 2, CPUMask)
+ // The SNI MP Agent supports up to 4 CPU's
+ //
+
+ if (msg_data ==MPA_TIMER_MESSAGE )
+ msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG2;
+ else
+ msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG1;
+
+ msg_data = ((msg_data << 24) | (pcpumask & MPA_CPUTARGET_MASK));
+
+ msg_retries = MPA_MSG_RETRY;
+
+ /*
+ * Go on, just do it.
+ * If at first you don't succeed, then try, try and try again...
+ */
+
+ do {
+
+ watchdog = 10;
+
+ WRITE_REGISTER_ULONG(&(mpagent->msgaddress), msg_address);
+ WRITE_REGISTER_ULONG(&(mpagent->msgdata), msg_data);
+
+ /*
+ * so, what happened? poll either until we know or the watchdog counter runs out
+ */
+ do {
+
+ KeStallExecutionProcessor(5);
+
+ //
+ // read the message status register
+ //
+ msg_status = READ_REGISTER_ULONG(&(mpagent->msgstatus));
+
+ } while (((msg_status & MPA_VALSTAT) == 0) && watchdog--);
+
+
+// KeLowerIrql(OldIrql);
+
+
+ if ((msg_status & MPA_VALSTAT) != MPA_VALSTAT) {
+
+
+ KeStallExecutionProcessor(100);
+// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ continue;
+
+ } else {
+
+ //
+ // okay, we have a Valid status bit
+ // so test of busy
+
+ if ((msg_status & MPA_ERRMSG) == 0) {
+
+ //
+ // all is fine
+ //
+ KeLowerIrql(OldIrql);
+ return;
+
+ } else {
+
+ // we have to verify that it is not a MPA_RETRY error.
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
+
+ if (itpend & MPA_INTN_MPBERR) {
+
+ ULONG snooper, cpureg, tmp ;
+
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
+ ); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+ snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
+
+ tmp = READ_REGISTER_ULONG(&(mpagent->snpadreg)); /* read the current value */
+ snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+
+ if ((snooper & MPA_MSEQERR == MPA_RETRYERR) || (snooper & MPA_MSEQERR ==0)) {
+ snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg |= (MPA_ENINT_MPBERR); /* enable interrupt for MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+
+ }
+ }
+
+// msg_retries = MPA_MSG_RETRY;
+ KeStallExecutionProcessor(100);
+// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (itpend & MPA_INTN_MPBERR) {
+ continue;
+ } else {
+ KeLowerIrql(OldIrql);
+ return;
+ }
+ }
+
+ }
+
+
+// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeStallExecutionProcessor(10);
+
+ } while (--msg_retries); /* message aborted, try again */
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpProcessIpi(
+ IN struct _KTRAP_FRAME *TrapFrame
+ )
+/*++
+
+ Routine Description:
+
+ This routine is entered as the result of an IP5 interrupt. This function
+ will looks at the MPagent to see if an IPI has just occurred.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+
+--*/
+{
+ ULONG itpend, msg_data;
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
+
+ if (itpend & (MPA_INTN_ITMSG1 | MPA_INTN_ITMSG2)) {
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ //
+
+ if (itpend & MPA_INTN_ITMSG1) {
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg1)) >> 24);
+ if (msg_data == MPA_KERNEL_MESSAGE) {
+ KeIpiInterrupt(TrapFrame);
+ } else {
+ // remove this processor from the list of active processors
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number]=0;
+ if (PCR->Number) {
+
+ // call a firmware funtion to stop slave cpu's which will break the caches
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
+
+ } else {
+
+ HalpBootCpuRestart();
+ }
+ }
+ }
+
+ if (itpend & MPA_INTN_ITMSG2) {
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg2)) >> 24);
+ KeUpdateRunTime(TrapFrame);
+ }
+
+ HalpCheckSpuriousInt(0);
+
+ return ;
+ }
+
+ if ((itpend & MPA_INTN_INT_MASK) == 0) {
+
+ ULONG snooper = READ_REGISTER_ULONG(&(mpagent->snooper));
+
+ //
+ // None of the MP Agent internal Interrupts was pending --> just return
+ //
+
+ HalpCheckSpuriousInt(0);
+
+
+ return ;
+ }
+
+ if (itpend & MPA_INTN_MPBERR) {
+
+ //
+ // Fatal Error
+ //
+
+ ULONG snooper, cpureg, tmp ;
+
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
+ ); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+ snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
+
+ tmp = READ_REGISTER_ULONG(&(mpagent->snpadreg)); /* read the current value */
+ snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+
+ if ((snooper & MPA_MSEQERR == MPA_RETRYERR) || (snooper & MPA_MSEQERR ==0)) {
+ snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg |= (MPA_ENINT_MPBERR); /* enable interrupt for MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+
+ } else {
+#if DBG
+ DebugPrint(("MP_Agent fatal error : adresse=0x%x snooper=0x%x\n",tmp,snooper));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 0;
+ HalDisplayString(HalpBugCheckMessage[0]); // "MP_Agent fatal error\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,snooper,tmp,0);
+#endif
+
+ }
+
+ HalpCheckSpuriousInt(0);
+
+ return ;
+ }
+
+ if (itpend & MPA_INTN_ITMSG3) {
+
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ //
+
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg3)) >> 24);
+ HalpCheckSpuriousInt(0);
+
+ return ;
+ }
+}
+
+ULONG
+HalpGetMyAgent(
+ VOID
+ )
+{
+ ULONG reg;
+ reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
+ return( (reg & MPA_ADAGT_MASK) >> MPA_ADAGT_SHIFT);
+}
+
+
+
+/*
+ * ======================================================================
+ *
+ * NAME: mpa_check_spurious_intr
+ *
+ * PURPOSE: Fix a bug in the MP_Agent which sometimes make a bad
+ * update of the cause register.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: = 0 no possible spurious interrupt
+ * 1 possible spurious interrupt
+ *
+ * ======================================================================
+ */
+BOOLEAN HalpCheckSpuriousInt(ULONG mask)
+{
+
+ULONG itpend, causeit, pending;
+ULONG cpureg, tempreg, reg;
+
+ if ( HalpProcessorId != MPAGENT) {
+ return 0;
+ }
+
+
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* read the interrupt pending MP_Agent register */
+
+ causeit = (itpend & MPA_OINTN_MASKGEN) >> MPA_OINTN_SHIFT;
+ pending = (itpend & MPA_INTN_MASKGEN );
+
+ if (causeit != pending) {
+
+ /*
+ * Need a second filter for pending interrupt which don't take care
+ * of real enabled interrupt mask of cpureg.
+ */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read interrupt enable mask for this cpu */
+
+ if (PCR->Prcb->Number == 0) {
+ if (HalpIsTowerPci && HalpIsMulti == 0)
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP3 | MPA_ENINT_SR_IP6 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ else
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP3 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ } else if (PCR->Prcb->Number == 1){
+ if (HalpIsTowerPci){
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP6 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ }else{
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP5 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ }
+ } else {
+ pending &= (
+ ((cpureg & MPA_ENINT_SR_IP7 ) >> MPA_ENINT_MASKSHIFT)
+
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+
+ }
+
+ if (causeit != pending) {
+
+ /*
+ * There is sometimes an MP_Agent interrupt with values different in
+ * MPA_INTN_... = 0 and MPA_OINTN_....
+ * That means : The cause register has been updated with a wrong value!
+ * We need to force a new update of the cause register to avoid looping
+ * on this interrupt until a new external interrupt happens.
+ */
+ if (cpureg & MPA_INTCONF_SR_IP8) {
+ tempreg = (cpureg & (~MPA_INTCONF_SR_IP8)) | MPA_ENINT_SR_IP8;
+ } else {
+ tempreg = (cpureg | MPA_INTCONF_SR_IP8 | MPA_ENINT_SR_IP8);
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), tempreg); // write the new value in the MP_Agent register /
+
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // Restore initial value
+
+
+ if (mask <= 1) {
+
+
+
+ return 0;
+ }
+
+ reg = HalpGetCauseRegister();
+ if ( reg & mask ) {
+
+
+ return 0;
+ } else {
+
+
+ return 1;
+ }
+ }
+ }
+
+
+
+ return 0; /* No possible spurious ! */
+
+}
+
+
diff --git a/private/ntos/nthals/halsnip/mips/mpagent.h b/private/ntos/nthals/halsnip/mips/mpagent.h
new file mode 100644
index 000000000..650cb4d81
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/mpagent.h
@@ -0,0 +1,594 @@
+//
+// Defines for Access to the MP Agent
+// this file can be used on assembly language files and C Files
+//
+
+#ifndef _MPAGENT_H_
+#define _MPAGENT_H_
+
+
+#define MPA_BASE_ADDRESS 0xbffff000 /* Base to address the MP_Agent */
+#define MPA_BOOT_MESSAGE 6 /* to start the other processors */
+#define MPA_KERNEL_MESSAGE 10 /* kernel requested IPI */
+#define MPA_TIMER_MESSAGE 11 /* timer interrupt */
+#define MPA_RESTART_MESSAGE 12 /* restart requested */
+
+//
+// define relative offsets of the MP Agent registers
+// (little endian mode)
+//
+
+#define MPA_cpureg 0x000 // (0x00 * 8) configuration cpu register
+#define MPA_cpuda1reg 0x008 // (0x01 * 8) general register
+#define MPA_msgdata 0x010 // (0x02 * 8) data for message passing
+#define MPA_msgstatus 0x018 // (0x03 * 8) message status
+#define MPA_snooper 0x020 // (0x04 * 8) snooper configuration register
+#define MPA_tagreg 0x028 // (0x05 * 8) tag ram R/W index register
+#define MPA_snpadreg 0x030 // (0x06 * 8) adress of first MBus fatal error
+#define MPA_itpend 0x038 // (0x07 * 8) Interrupt register
+#define MPA_datamsg1 0x040 // (0x08 * 8) data message register 1
+#define MPA_datamsg2 0x048 // (0x09 * 8) data message register 2
+#define MPA_datamsg3 0x050 // (0x0a * 8) data message register 3
+#define MPA_lppreg0 0x058 // (0x0b * 8) LPP register cpu 0
+#define MPA_lppreg1 0x060 // (0x0c * 8) LPP register cpu 1
+#define MPA_lppreg2 0x068 // (0x0d * 8) LPP register cpu 2
+#define MPA_lppreg3 0x070 // (0x0e * 8) LPP register cpu 3
+#define MPA_tagram 0x078 // (0x0f * 8) tag ram R/W register
+#define MPA_crefcpt 0x080 // (0x10 * 8) cpu general read counter register
+#define MPA_ctarcpt 0x088 // (0x11 * 8) cpu programmable access counter
+#define MPA_srefcpt 0x090 // (0x12 * 8) snooper general read counter reg.
+#define MPA_starcpt 0x098 // (0x13 * 8) snooper programmable accesscounter
+#define MPA_linkreg 0x0a0 // (0x14 * 8) link register
+#define MPA_software1 0x0a8 // (0x15 * 8) software register1
+#define MPA_msgaddress 0x0b0 // (0x16 * 8) address message register
+#define MPA_mem_operator 0x0b8 // (0x17 * 8) operator internal burst register
+#define MPA_software2 0x0c0 // (0x18 * 8) software register2
+
+
+/* +---------------------------+ */
+/* ! cpureg register (0x00) ! */
+/* +---------------------------+ */
+/*
+
+ The CPUREG Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | ED| ED| ED| | MI| MI| MI| EI| EI| EI| EI| EI| EI| R | 1 | 0 | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |__________ enable shared 1-> TagCopy for S
+ |_____________ enable message sending
+ |_________________ reserved
+ |_____________________ enable external Interrupts
+ |________________________ enable external Interrupts
+ |____________________________ enable external Interrupts
+ |________________________________ enable external Interrupts
+ |____________________________________ enable external Interrupts
+
+ |__________________________________________ enable external Interrupts
+ |______________________________________________ enable Message Reg. Int.
+ |__________________________________________________ enable Message Reg. Int.
+ |______________________________________________________ enable Message Reg. Int.
+ |__________________________________________________________
+ |______________________________________________________________ Edge Config for Interrupts
+ |__________________________________________________________________ Edge Config for Interrupts
+ |______________________________________________________________________ Edge Config for Interrupts
+
+
+ The CPUREG Register (HIGH-PART), which has the following bits:
+
+
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | 1 | 1 | 1 | 1 | 1 | MA| MA| MA| MA| MA| MA| MA| ED| ED| ED| ED| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Edge Config for Interrupts
+ |_____________ Edge Config for Interrupts
+ |________________ Edge Config for Interrupts
+ |____________________ Edge Config for Interrupts
+ |________________________ Interrupt Mask on external Request
+ |____________________________ Interrupt Mask on external Request
+ |________________________________ Interrupt Mask on external Request
+ |____________________________________ Interrupt Mask on external Request
+
+ |__________________________________________ Interrupt Mask on external Request
+ |______________________________________________ Interrupt Mask on external Request
+ |__________________________________________________ Interrupt Mask on external Request
+ |______________________________________________________ maximal Retry Count on MP-Bus
+ |__________________________________________________________ maximal Retry Count on MP-Bus
+ |______________________________________________________________ maximal Retry Count on MP-Bus
+ |__________________________________________________________________ maximal Retry Count on MP-Bus
+ |______________________________________________________________________ maximal Retry Count on MP-Bus
+
+*/
+
+#define MPA_ENSHARED 0x00000001 /* (0) If the MP_Agent has not the data in
+ * exclusif state, the MP_Agent forces
+ * the data to shared state for all
+ * coherent access.
+ *
+ * (1) If no other MP_agent has the data
+ * in exclusif state, the requester
+ * can put the data in share or exclusif
+ * state.
+ */
+
+#define MPA_ENSENDMSG 0x00000002 /* (1) 0 -> disable message passing
+ * 1 -> enable message passing
+ */
+
+#define MPA_ENINT_MASK 0x00001ffc /* (12:2) enable interrupt mask */
+#define MPA_ENINT_MASKSHIFT 3 /* shift for enable interrupt mask */
+#define MPA_ENINT_SR_IP3 0x00000008 /* (3) enable external interrupt SR_IP3 */
+#define MPA_ENINT_SR_IP4 0x00000010 /* (4) enable external interrupt SR_IP4 */
+#define MPA_ENINT_SR_IP5 0x00000020 /* (5) enable external interrupt SR_IP5 */
+#define MPA_ENINT_SR_IP6 0x00000040 /* (6) enable external interrupt SR_IP6 */
+#define MPA_ENINT_SR_IP7 0x00000080 /* (7) enable external interrupt SR_IP7 */
+#define MPA_ENINT_SR_IP8 0x00000100 /* (8) enable external interrupt SR_IP8 */
+#define MPA_ENINT_ITMSG1 0x00000200 /* (9) enable interrupt message1 register */
+#define MPA_ENINT_ITMSG2 0x00000400 /* (10) enable interrupt message2 register */
+#define MPA_ENINT_ITMSG3 0x00000800 /* (11) enable interrupt message3 register */
+#define MPA_ENINT_MPBERR 0x00001000 /* (12) enable interrupt MP_Agent fatal error */
+
+#define MPA_INTCONF_MASK 0x000fe000 /* (19:13) select interrupt level
+ * 0 -> falling
+ * 1 -> raising */
+#define MPA_INTCONF_SR_IP3 0x00002000 /* (13) select raising mode for SR_IP3 */
+#define MPA_INTCONF_SR_IP4 0x00004000 /* (14) select raising mode for SR_IP4 */
+#define MPA_INTCONF_SR_IP5 0x00008000 /* (15) select raising mode for SR_IP5 */
+#define MPA_INTCONF_SR_IP6 0x00010000 /* (16) select raising mode for SR_IP6 */
+#define MPA_INTCONF_SR_IP7 0x00020000 /* (17) select raising mode for SR_IP7 */
+#define MPA_INTCONF_SR_IP8 0x00040000 /* (18) select raising mode for SR_IP8 */
+#define MPA_INTCONF_SR_NMI 0x00080000 /* (19) select raising mode for SR_NMI */
+
+#define MPA_INTMSK 0x07f00000 /* (26:20) mask sent during external request stage */
+
+#define MPA_MAXRTY_MASK 0xf8000000 /* (31:27) mask for maximum number of retry on
+ * INV / UPD / MESS / RD_COH */
+
+/* +---------------------------+ */
+/* ! cpuda1reg register (0x01) ! */
+/* +---------------------------+ */
+/*
+ The CPU1REG Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | SS| SS| TI| 1 | DP| DP| R | R | R | R | R | R | R | R | R | R | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ reserved
+ |_____________ reserved
+ |________________ reserved
+ |____________________ reserved
+ |________________________ reserved
+ |____________________________ reserved
+ |________________________________ reserved
+ |____________________________________ reserved
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ CPU Data Pattern
+ |______________________________________________________ CPU Data Pattern
+ |__________________________________________________________ Int. Update Policy 0 - direct
+ |______________________________________________________________ Test Interrupts
+ |__________________________________________________________________ Cpu Port Statistics
+ |______________________________________________________________________ Cpu Port Statistics
+
+
+ The CPU1REG Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | R | R | R | R | R | R | R | R | R | R | R | IS| IS| IS| 1 | SS| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Cpu Port Statistics
+ |_____________ Enable Read Anticipate mode
+ |________________ Select Interrupt for Internal Ints
+ |____________________ Select Interrupt for Internal Ints
+ |________________________ Select Interrupt for Internal Ints
+ |____________________________ reserved
+ |________________________________ reserved
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ reserved
+
+*/
+
+#define MPA_CPURDPAT_MASK 0x00000c00 /* (11:10) number of wait-state between 2 double
+ * cpu reads. */
+#define MPA_CPURDPAT_DD 0x00000000 /* 0 : dd */
+#define MPA_CPURDPAT_DDX 0x00000400 /* 1 : dd. */
+#define MPA_CPURDPAT_DDXX 0x00000800 /* 2 : dd.. */
+#define MPA_CPURDPAT_DXDX 0x00000c00 /* 3 : d.d. */
+
+#define MPA_ENDIRECT 0x00001000 /* (12) 0 send interrupt to all MP_Agent
+ * 1 use LPP mechanism to dispatch interrupt
+ */
+
+#define MPA_ENTESTIT 0x00002000 /* (13) 0 disable test mode (interrupts from MPBus)
+ * 1 enable test mode (interrupts from INTCONF(6:0))
+ */
+
+#define MPA_CPUSELSTAT_MASK 0x0001c000 /* (16:14) select programmable mode for cpu
+ * access
+ */
+
+#define MPA_ENRDANT 0x00020000 /* (17) 0 disable overlapping memory/MP_Agent
+ *
+ * 1 enable overlapping memory/MP_Agent
+ * The Tag copy checking is done concurently
+ * with memory access. The memory must support
+ * the 'read abort' command (not supported
+ * by current Asic chipset rev.0).
+ */
+
+#define MPA_SELITI_MASK 0x001c0000 /* (20:18) define routage for internal interrupts */
+#define MPA_SELITI_SR_IP3 0x00000000 /* Internal interrupts go on SR_IP3 */
+#define MPA_SELITI_SR_IP4 0x00040000 /* Internal interrupts go on SR_IP4 */
+#define MPA_SELITI_SR_IP5 0x00080000 /* Internal interrupts go on SR_IP5 */
+#define MPA_SELITI_SR_IP6 0x000c0000 /* Internal interrupts go on SR_IP6 */
+#define MPA_SELITI_SR_IP7 0x00100000 /* Internal interrupts go on SR_IP7 */
+#define MPA_SELITI_SR_IP8 0x00140000 /* Internal interrupts go on SR_IP8 */
+
+/* +---------------------------+ */
+/* ! msgstatus register (0x03) ! */
+/* +---------------------------+ */
+
+/* message passing status register */
+
+#define MPA_VALSTAT 0x00000001 /* (0) 0 -> status is invalid
+ * 1 -> status is valid */
+//
+// if (MPA_VALSTAT != 0)
+//
+
+#define MPA_SENDMSG 0x00000002 /* (1) 1 -> message not acknowledged by MPBus */
+#define MPA_ERRMSG 0x00000004 /* (2) 0 -> message has been acknowledged
+ * 1 -> at least one MP_Agent has refused */
+#define MPA_BUSY 0x00000008
+#define MPA_ADERR_MASK 0x000000f0 /* (7:4) list of refusing processor(s) */
+#define MPA_ADERR_SHIFT 0x4
+
+
+/* +---------------------------+ */
+/* ! snooper register (0x04) ! */
+/* +---------------------------+ */
+
+/*
+ The SNOOPER Register (LOW-PART), which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | 1 | R | R | R | R | - | - | - | 1 | 1 | 1 | - | - | R | R | 1 | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ enable Message receive
+ |_____________ reserved
+ |________________ reserved
+ |____________________ LineSize
+ |________________________ LineSize
+ |____________________________ Three/ Two Party
+ |________________________________ enable Read+Link
+ |____________________________________ enable Coherency
+
+ |__________________________________________ MP Statistics
+ |______________________________________________ MP Statistics
+ |__________________________________________________ MP Statistics
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ FATAL INTERRUPT inactive
+
+
+ The SNOOPER Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | 1 | 1 | 1 | 1 | 1 | R | R | R | R | R | M | M | M | C | C | C | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Cderrtag TagSeq direct error code
+ |_____________ Cderrtag
+ |________________ Cderrtag
+ |____________________ Mderrtag SnpTagSeq memo Error code
+ |________________________ Mderrtag
+ |____________________________ Mderrtag
+ |________________________________ reserved
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ Agent Address
+ |__________________________________________________________ Agent Address
+ |______________________________________________________________ seq. cpu error
+ |__________________________________________________________________ tag seq. error
+ |______________________________________________________________________ ext. seq. error
+
+*/
+
+#define MPA_ENRCVMESS 0x00000001 /* (0) 0 -> disable message receiving
+ * 1 -> enable message receiving */
+
+#define MPA_LSIZE_MASK 0x00000018 /* (4:3) secondary linesize mask */
+#define MPA_LSIZE16 0x00000000 /* secondary linesize = 16 bytes */
+#define MPA_LSIZE32 0x00000008 /* secondary linesize = 32 bytes */
+#define MPA_LSIZE64 0x00000010 /* secondary linesize = 64 bytes */
+#define MPA_LSIZE128 0x00000018 /* secondary linesize = 128 bytes */
+
+/* NOTE: MP_Agent doesn't support linesize greater than 64 bytes !! */
+
+#define MPA_DISTPARTY 0x00000020 /* (5) 0 -> enable three-party mode
+ * MP_Agent requester/MP_Agent target
+ * + memory (for update)
+ *
+ * 1 -> disable three-party mode
+ * MP_Agent requester/MP_Agent target
+ */
+
+#define MPA_ENLINK 0x00000040 /* (6) 0 -> The cpu read and link command is
+ * disabled.
+ * 1 -> The cpu read and link command is
+ * enabled.
+ */
+
+#define MPA_ENCOHREQ 0x00000080 /* (7) 0 -> disable sending external request
+ * for coherency to cpu by his MP_Agent
+ * 1 -> enable sending external request
+ * for coherency to cpu by his MP_Agent
+ */
+
+#define MPA_SNPSELSTAT_MASK 0x00000700 /* (10:8) select programmable mode for snooper
+ * access
+ */
+
+#define MPA_RSTSNPERR 0x00008000 /* (15) 1 -> reset all MP bus fatal error
+ *
+ * 0 -> enable new fatal error on MP bus
+ * sent by interrupt.
+ */
+
+#define MPA_CDERRTAG 0x00070000 /* (18:16) (Read only) error code */
+
+#define MPA_MCDERRTAG 0x00380000 /* (21:19) (Read only) error code */
+
+#define MPA_MCDERREXT 0x00c00000 /* (23:22) (Read only) error code */
+
+#define MPA_ADAGT_MASK 0x18000000 /* (28:27) (Read only) MP_Agent address mask */
+#define MPA_ADAGT_SHIFT 27 /* shift address agent value */
+
+#define MPA_MSEQERR 0xe0000000 /* (31:29) (Read only) error code */
+#define MPA_RETRYERR 0x20000000 /* (31:29) (Read only) error code */
+
+
+/* +---------------------------+ */
+/* ! itpend register (0x07) ! */
+/*+---------------------------+ */
+
+/*
+ The Interrupt Pending Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | UE| UE| UE| UE| R | F | M | M | M | R | E | E | E | E | E | E | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ pending external Interrupts
+ |_____________ pending external Interrupts
+ |________________ pending external Interrupts
+ |____________________ pending external Interrupts
+ |________________________ pending external Interrupts
+ |____________________________ pending external Interrupts
+ |________________________________ reserved
+ |____________________________________ Message Register 1
+
+ |__________________________________________ Message Register 2
+ |______________________________________________ Message Register 3
+ |__________________________________________________ FATAL MP Agent Error
+ |______________________________________________________ reserved
+ |__________________________________________________________ last updated external State
+ |______________________________________________________________ last updated external State
+ |__________________________________________________________________ last updated external State
+ |______________________________________________________________________ last updated external State
+
+ The Interrupt Pending Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | R | R | R | R | R | R | R | R | R | UF| UM| UM| UM| R | UE| UE| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ last updated external State
+ |_____________ last updated external State
+ |________________ reserved
+ |____________________ last updated Message State
+ |________________________ last updated Message State
+ |____________________________ last updated Message State
+ |________________________________ last updated FATAL E State
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ reserved
+
+*/
+
+/* external interrupts */
+#define MPA_INTN_MASKGEN 0x000007ff /* (10:0) pending general interrupt mask */
+#define MPA_INTN_EXT_MASK 0x0000003f /* (5:0) pending external interrupt mask */
+#define MPA_INTN_SR_IP3 0x00000001 /* (0) pending external interrupt SR_IP3 */
+#define MPA_INTN_SR_IP4 0x00000002 /* (1) pending external interrupt SR_IP4 */
+#define MPA_INTN_SR_IP5 0x00000004 /* (2) pending external interrupt SR_IP5 */
+#define MPA_INTN_SR_IP6 0x00000008 /* (3) pending external interrupt SR_IP6 */
+#define MPA_INTN_SR_IP7 0x00000010 /* (4) pending external interrupt SR_IP7 */
+#define MPA_INTN_SR_IP8 0x00000020 /* (5) pending external interrupt SR_IP8 */
+
+/* internal interrupts */
+#define MPA_INTN_ITNMI 0x00000040 /* (6) unused */
+#define MPA_INTN_ITMSG1 0x00000080 /* (7) pending interrupt message1 register */
+#define MPA_INTN_ITMSG2 0x00000100 /* (8) pending interrupt message2 register */
+#define MPA_INTN_ITMSG3 0x00000200 /* (9) pending interrupt message3 register */
+#define MPA_INTN_MPBERR 0x00000400 /* (10) pending interrupt MP_Agent fatal error */
+/* pending internal interrupts mask */
+#define MPA_INTN_INT_MASK (MPA_INTN_ITNMI | \
+ MPA_INTN_ITMSG1 | \
+ MPA_INTN_ITMSG2 | \
+ MPA_INTN_ITMSG3 | \
+ MPA_INTN_MPBERR)
+
+/* old interrupts written in the processor cause register */
+
+/* external interrupts */
+#define MPA_OINTN_MASKGEN 0x007ff000 /* (22:12) old general interrupt mask */
+#define MPA_OINTN_SHIFT 12 /* shift to compare to pending interrupt */
+#define MPA_OINTN_MASK 0x0003f000 /* (17:12) old external interrupt mask */
+#define MPA_OINTN_SR_IP3 0x00001000 /* (12) old external interrupt SR_IP3 */
+#define MPA_OINTN_SR_IP4 0x00002000 /* (13) old external interrupt SR_IP4 */
+#define MPA_OINTN_SR_IP5 0x00004000 /* (14) old external interrupt SR_IP5 */
+#define MPA_OINTN_SR_IP6 0x00008000 /* (15) old external interrupt SR_IP6 */
+#define MPA_OINTN_SR_IP7 0x00010000 /* (16) old external interrupt SR_IP7 */
+#define MPA_OINTN_SR_IP8 0x00020000 /* (17) old external interrupt SR_IP8 */
+
+/* internal interrupts */
+#define MPA_OINTN_ITNMI 0x00040000 /* (18) unused */
+#define MPA_OINTN_ITMSG1 0x00080000 /* (19) old interrupt message1 register */
+#define MPA_OINTN_ITMSG2 0x00100000 /* (20) old interrupt message2 register */
+#define MPA_OINTN_ITMSG3 0x00200000 /* (21) old interrupt message3 register */
+#define MPA_OINTN_MPBERR 0x00400000 /* (22) old interrupt MP_Agent fatal error */
+
+
+/* +---------------------------+ */
+/* ! msgaddress register(0x16) ! */
+/* +---------------------------+ */
+
+/* Message address for message passing */
+
+#define MPA_CPUTARGET_MASK 0x0000000f /* (3:0) target cpu mask */
+#define MPA_CPUTARGET_ALL 0x0000000f /* cpu target : all */
+#define MPA_CPUTARGET_CPU0 0x00000001 /* cpu target : 0 */
+#define MPA_CPUTARGET_CPU1 0x00000002 /* cpu target : 1 */
+#define MPA_CPUTARGET_CPU2 0x00000004 /* cpu target : 2 */
+#define MPA_CPUTARGET_CPU3 0x00000008 /* cpu target : 3 */
+
+#define MPA_REGTARGET_MASK 0x000001f0 /* (8:4) target register */
+#define MPA_REGTARGET_MSG1 0x00000080 /* msg1reg target register */
+#define MPA_REGTARGET_MSG2 0x00000090 /* msg2reg target register */
+#define MPA_REGTARGET_MSG3 0x000000a0 /* msg3reg target register */
+
+#define MPA_ENMSGLPP 0x00000200 /* (9) 0 disable LPP mode for message passing */
+
+/* +---------------------------+ */
+/* ! mem_operator reg. (0x17) ! */
+/* +---------------------------+ */
+
+/* For fake read on a 4Mb segment. Used for cache replace functions */
+
+#define MPA_OP_ENABLE 0x00000001 /* (0) 0 disable operator (address invalid)
+ * 1 enable operator (address valid)
+ */
+
+#define MPA_OP_ADDR_MASK 0xffc00000 /* (31:22) base physical address of a 4Mb kseg0
+ * reserved segment (4Mb == 0x00400000).
+ */
+
+
+#define MPA_TAGREG_ADDR_MASK 0x003ffff0
+#define MPA_TR_STATE_MASK 0x00000003
+#define MPA_TR_NOCOHERENT 0x00000000
+/*
+ * Number of retries before sending a fatal error
+ */
+#define MPA_MSG_RETRY 10
+
+typedef struct _mp_agent{
+
+ /* Register Register
+ * name number offset description
+ * ---------- ---- ------ --------------------------------- */
+ ULONG cpureg; /* 0x00 0x000 configuration cpu register */
+ ULONG invalid_0;
+ ULONG cpuda1reg; /* 0x01 0x008 general register */
+ ULONG invalid_1;
+ ULONG msgdata; /* 0x02 0x010 data for message passing */
+ ULONG invalid_2;
+ ULONG msgstatus; /* 0x03 0x018 message status */
+ ULONG invalid_3;
+ ULONG snooper; /* 0x04 0x020 snooper configuration register */
+ ULONG invalid_4;
+ ULONG tagreg; /* 0x05 0x028 tag ram R/W index register */
+ ULONG invalid_5;
+ ULONG snpadreg; /* 0x06 0x030 adress of first MBus fatal error */
+ ULONG invalid_6;
+ ULONG itpend; /* 0x07 0x038 Interrupt register */
+ ULONG invalid_7;
+ ULONG datamsg1; /* 0x08 0x040 data message register 1 */
+ ULONG invalid_8;
+ ULONG datamsg2; /* 0x09 0x048 data message register 2 */
+ ULONG invalid_9;
+ ULONG datamsg3; /* 0x0a 0x050 data message register 3 */
+ ULONG invalid_a;
+ ULONG lppreg0; /* 0x0b 0x058 LPP register cpu 0 */
+ ULONG invalid_b;
+ ULONG lppreg1; /* 0x0c 0x060 LPP register cpu 1 */
+ ULONG invalid_c;
+ ULONG lppreg2; /* 0x0d 0x068 LPP register cpu 2 */
+ ULONG invalid_d;
+ ULONG lppreg3; /* 0x0e 0x070 LPP register cpu 3 */
+ ULONG invalid_e;
+ ULONG tagram; /* 0x0f 0x078 tag ram R/W register */
+ ULONG invalid_f;
+ ULONG crefcpt; /* 0x10 0x080 cpu general read counter register */
+ ULONG invalid_10;
+ ULONG ctarcpt; /* 0x11 0x088 cpu programmable access counter */
+ ULONG invalid_11;
+ ULONG srefcpt; /* 0x12 0x090 snooper general read counter reg. */
+ ULONG invalid_12;
+ ULONG starcpt; /* 0x13 0x098 snooper programmable accesscounter*/
+ ULONG invalid_13;
+ ULONG linkreg; /* 0x14 0x0a0 link register */
+ ULONG invalid_14;
+ ULONG software1; /* 0x15 0x0a8 software register1 */
+ ULONG invalid_15;
+ ULONG msgaddress; /* 0x16 0x0b0 address message register */
+ ULONG invalid_16;
+ ULONG mem_operator; /* 0x17 0x0b8 operator internal burst register */
+ ULONG invalid_17;
+ ULONG software2; /* 0x18 0x0c0 software register2 */
+}MP_AGENT, *PMP_AGENT;
+
+#define mpagent ((volatile PMP_AGENT) MPA_BASE_ADDRESS) // mpagent address
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/orcache.s b/private/ntos/nthals/halsnip/mips/orcache.s
new file mode 100644
index 000000000..bf3024fe7
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/orcache.s
@@ -0,0 +1,561 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/orcache.s,v 1.3 1996/02/23 17:55:12 pierre Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// orcache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// R4600 orion Machines.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+#define ORION_REPLACE 0x17c00000
+
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+#define ZERO_PAGE 0x0c // 0000 1100
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageOrion (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (cache replace) up to a page of data
+// from the secondary data cache. (primary cache is already processed)
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFlushDcachePageOrion)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the secondary data caches => cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ or t0,t7,a0 // physical address + offset
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,ORION_REPLACE // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+
+ .set noreorder
+ .set noat
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageOrion
+
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageOrion (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeIcachePageOrion)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the secondary data caches => cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ beq t4,zero,60f
+ or t0,t7,a0 // physical address + offset
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,ORION_REPLACE // get base flush address
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeIcachePageOrion
+
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheOrion (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheOrion)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+#endif
+
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Sweep the primary data cache.
+//
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+10:
+ cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+//
+// sweep secondary cache
+//
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+
+ li a0,ORION_REPLACE // starting address
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+25:
+ lw zero,0(a0)
+ bne a0,a1,25b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+
+ .end HalpSweepDcacheMulti
+
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheOrion (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheOrion)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+#endif
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t0,20f // if eq, no second level cache
+ li a0,ORION_REPLACE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+10: lw zero,0(a0)
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+//
+// Sweep the primary instruction cache.
+//
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,8192(a0)
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+ j ra // return
+
+ .end HalpSweepIcacheOrion
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageOrion (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalpZeroPageOrion, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpZeroPageOrion
+
+
diff --git a/private/ntos/nthals/halsnip/mips/r4intdsp.c b/private/ntos/nthals/halsnip/mips/r4intdsp.c
new file mode 100644
index 000000000..08f79fb39
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/r4intdsp.c
@@ -0,0 +1,1307 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/r4intdsp.c,v 1.9 1996/02/23 17:55:12 pierre Exp $")
+
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ r4intdsp.c
+
+Abstract:
+
+ This module contains the HalpXxx routines which are important to
+ handle the Interrupts on the SNI machines.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "SNIregs.h"
+#include "mpagent.h"
+#include "eisa.h"
+#include "pci.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PINT0_DISPATCH)(
+ PKINTERRUPT Interupt,
+ PVOID ServiceContext
+ );
+
+extern VOID HalpSendIpi(IN ULONG pcpumask, IN ULONG msg_data);
+
+KINTERRUPT HalpInt0Interrupt; // Interrupt Object for SC machines (centralised interrupt)
+KINTERRUPT HalpInt3Interrupt; // Interrupt Object for IT3 tower multipro
+
+ULONG HalpTargetRetryCnt=0; // Counter for pci error ( initiator receives target retry)
+ULONG HalpSingleEccCounter = 0; // Single Ecc Error Counter (for RM200/RM300)
+
+extern VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+extern VOID
+HalpWritePCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+extern BOOLEAN
+HalpPciEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ ) ;
+
+extern BOOLEAN
+HalpPciEisaSBDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ ) ;
+
+extern BOOLEAN HalpESC_SB;
+
+BOOLEAN
+HalpCreateIntPciStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Int0-handling
+ and connects the intermediate interrupt dispatcher.
+ Also the structures necessary for PCI tower Int3 (MAUI interrupt)
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID InterruptSourceRegister;
+ PINT0_DISPATCH (DispatchRoutine);
+ PKSPIN_LOCK pSpinLock;
+
+ switch (HalpMainBoard) {
+ case M8150 : InterruptSourceRegister = (PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpPciTowerInt0Dispatch;
+ pSpinLock = (PKSPIN_LOCK)NULL;
+ break;
+
+ default: InterruptSourceRegister = (PVOID)PCI_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpPciInt0Dispatch;
+ pSpinLock = &HalpInterruptLock;
+ }
+
+ KeInitializeInterrupt( &HalpInt0Interrupt,
+ DispatchRoutine,
+ InterruptSourceRegister,
+ (PKSPIN_LOCK)pSpinLock,
+ INT0_LEVEL,
+ INT0_LEVEL, //INT0_LEVEL,
+ INT0_LEVEL, //Synchr. Level
+ LevelSensitive,
+ FALSE, // only one Intobject ispossible for int0
+ 0, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+
+ if (!KeConnectInterrupt( &HalpInt0Interrupt )) {
+
+ //
+ // this is the central Interrupt for the SNI SecondLevel Cache Machines
+ //
+
+ HalDisplayString("Failed to connect Int0!\n");
+ return(FALSE);
+ }
+
+
+
+ return (TRUE);
+}
+
+
+
+BOOLEAN
+HalpCreateIntPciMAUIStructures (
+ CCHAR Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary
+ for PCI tower Int3 (MAUI interrupt)
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+PVOID InterruptSourceRegister;
+
+ InterruptSourceRegister = (PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER;
+
+ KeInitializeInterrupt( &HalpInt3Interrupt,
+ HalpPciTowerInt3Dispatch,
+ InterruptSourceRegister,
+ (PKSPIN_LOCK)&HalpInterruptLock,
+ INT6_LEVEL,
+ INT6_LEVEL, //INT6_LEVEL,
+ INT6_LEVEL, //Synchr. Level
+ LevelSensitive,
+ FALSE, // only one Intobject ispossible for int0
+ Number, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+
+ if (!KeConnectInterrupt( &HalpInt3Interrupt )) {
+
+ //
+ // this is the central Interrupt for the SNI SecondLevel Cache Machines
+ //
+
+ HalDisplayString("Failed to connect Int3!\n");
+ return(FALSE);
+ }
+ }
+
+
+
+BOOLEAN
+HalpPciInt0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI PCI Desktop or Minitower
+ To decide which interrupt, read the Interrupt Source Register
+
+ We have to manage priorities by software.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR IntSource;
+ UCHAR MaStatus;
+ ULONG Itpend;
+
+ BOOLEAN SCSIresult, NETresult, result;
+
+ if (HalpCheckSpuriousInt(0x400)) return(FALSE);
+
+
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+
+ IntSource ^= PCI_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // and XOR the high active with 0 gives 1
+
+ if ( IntSource & PCI_EISA_MASK) { // EISA Interrupt
+
+ if (HalpESC_SB)
+ result = HalpPciEisaSBDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ else
+ result = HalpPciEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+
+ HalpCheckSpuriousInt(0x00);
+ return(result);
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & PCI_SCSI_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI interrupt !\n"));
+#endif
+ HalpCheckSpuriousInt(0x00);
+ return(SCSIresult);
+
+ }
+
+ //
+ // PCI interrupts
+ //
+
+ if ( IntSource & PCI_INTA_MASK){
+ int i;
+ for (i=INTA_VECTOR;i<HalpIntAMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_INTB_MASK){
+ int i;
+ for (i=INTB_VECTOR;i<HalpIntBMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_INTC_MASK){
+ int i;
+ for (i=INTC_VECTOR;i<HalpIntCMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_INTD_MASK){
+ int i;
+ for (i=INTD_VECTOR;i<HalpIntDMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ //
+ // look for an Ethernet Interrupt
+ //
+
+ if ( IntSource & PCI_NET_MASK){
+ NETresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
+ PCR->InterruptRoutine[NET_LEVEL]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(NETresult);
+ }
+
+ //
+ // Other interrupts => look in MSR register
+ //
+
+ if ( IntSource & PCI_INT2_MASK) {
+
+ MaStatus = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (HalpMainBoard == DesktopPCI) {
+ MaStatus ^= PCI_MSR_MASK_D;
+ } else {
+ MaStatus ^= PCI_MSR_MASK_MT;
+ }
+
+ //
+ // look for an ASIC interrupt
+ //
+
+ if ( MaStatus & PCI_MSR_ASIC_MASK){
+
+ Itpend = READ_REGISTER_ULONG(PCI_ITPEND_REGISTER);
+
+ if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR)) {
+
+ ULONG ErrAddr, AsicErrAddr, Syndrome, ErrStatus, irqsel;
+
+ AsicErrAddr = ErrAddr = READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER);
+ Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
+ Syndrome &= 0xff; // only 8 lower bits are significant
+ ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
+
+ if (ErrStatus & PCI_MEMSTAT_PARERR) {
+ // Parity error (PCI_ASIC <-> CPU)
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & 0x70000)); // PARERR it not routed
+ ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_PARERR);
+
+ if (ErrAddr == -1) ErrAddr = AsicErrAddr;
+
+#if DBG
+ DebugPrint(("pci_memory_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 1;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }
+
+ if (ErrStatus & PCI_MEMSTAT_ECCERR) {
+ // ECC error (PCI_ASIC <-> Memory access)
+ AsicErrAddr &= 0xfffffff8;
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & 0xe000)); // ECC it not routed
+ ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_ECCERR);
+
+ if (ErrAddr == -1) ErrAddr = AsicErrAddr;
+
+ if (ErrStatus & PCI_MEMSTAT_ECCSINGLE) {
+// HalSweepDcacheRange(0x80000000,2*(PCR->FirstLevelDcacheSize)); // to avoid data_coherency_exception
+// HalSweepIcacheRange(0x80000000,2*(PCR->FirstLevelIcacheSize)); // to avoid data_coherency_exception
+ if (HalpProcessorId == MPAGENT)
+ HalpMultiPciEccCorrector(ErrAddr,ErrAddr >> PAGE_SHIFT,4);
+ else
+ HalpPciEccCorrector(ErrAddr,ErrAddr >> PAGE_SHIFT,4);
+// HalSweepDcacheRange(0x80000000,2*(PCR->FirstLevelDcacheSize)); // to avoid data_coherency_exception
+// HalSweepIcacheRange(0x80000000,2*(PCR->FirstLevelIcacheSize)); // to avoid data_coherency_exception
+
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER, irqsel); // restore routage ECC
+
+ if (ErrAddr == READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER)) {
+ Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
+ ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
+ KeStallExecutionProcessor(100);
+ }
+
+ // We use SNI_PRIVATE_VECTOR to transmit parameters to the RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved=0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis=FLAG_ECC_ERROR;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorSimmNum=HalpComputeNum((UCHAR *)ErrAddr);
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorAddress=ErrAddr;
+
+ // Call the 'RM300 equivalent DCU' driver to log the ECC error in event viewer
+
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+ ++HalpSingleEccCounter;
+ if (HalpSingleEccCounter > 0xffff) {
+#if DBG
+ HalpSingleEccCounter = 0;
+ DebugPrint(("Memory Read Error Counter Overflow\n"));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 2;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "ECC SINGLE ERROR COUNTER OVERFLOW\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }
+
+ } else {
+
+#if DBG
+ // UNIX => PANIC
+ DebugPrint(("pci_ecc_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 3;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "UNCORRECTABLE ECC ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }
+
+ }
+
+ }
+
+ if ( Itpend & PCI_ASIC_IOTIMEOUT ) {
+
+ ULONG ioadtimeout2, iomemconf;
+
+ ioadtimeout2 = READ_REGISTER_ULONG(PCI_IOADTIMEOUT2_REGISTER);
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT)));
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+#if DBG
+ DebugPrint(("pci_timeout_error : adresse=0x%x \n",ioadtimeout2));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 4;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI TIMEOUT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ioadtimeout2,0,0);
+#endif
+ }
+ }
+
+ //
+ // Pb NMI because of cirrus chip which generates a parity which is understood by the ASIC
+ // like an error and transmit as an NMI EISA.
+ //
+
+ if (MaStatus & PCI_MSR_NMI) {
+
+ UCHAR DataByte;
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus);
+
+ if (((PNMI_STATUS) &DataByte)->ParityNmi == 1) {
+
+ DebugPrint(("Parity error from system memory\n"));
+
+ // reset NMI interrupt
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+ }
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ if (((PNMI_EXTENDED_CONTROL) &DataByte)->PendingBusMasterTimeout == 1) {
+
+ DebugPrint(("EISA Bus Master timeout\n"));
+
+ // reset NMI interrupt
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+
+ }
+
+ }
+
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & PCI_MSR_PB_MASK){
+ DebugPrint(("Interrupt - PushButton\n"));
+ WRITE_REGISTER_ULONG( PCI_CSRSTBP_ADDR ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+ }
+
+ //
+ // look for an OverTemperature Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & PCI_MSR_TEMP_MASK){
+
+ DebugPrint(("Interrupt - Temperature\n"));
+
+ // we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the 'RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //no ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, Reset interrupt + auto-rearm
+
+ READ_REGISTER_ULONG( PCI_CLR_TMP_ADDR);
+
+ }
+
+ //
+ // look for an power off
+ //
+
+ if ( MaStatus & PCI_MSR_POFF_MASK){
+
+ // we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the 'RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, Reset interrupt + auto-rearm
+
+ WRITE_REGISTER_ULONG( PCI_CLRPOFF_ADDR,0);
+ }
+
+ //
+ // look for an power management
+ //
+
+ if ( MaStatus & PCI_MSR_PMGNT_MASK){
+
+ // we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the 'RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, Reset interrupt + auto-rearm
+
+ WRITE_REGISTER_ULONG( PCI_PWDN_ADDR,0); // power down
+ }
+ }
+
+ HalpCheckSpuriousInt(0x00);
+ return (TRUE); // perhaps one of the interrupts was pending :-)
+}
+
+
+BOOLEAN
+HalpPciTowerInt0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI PCI tower
+ To decide which interrupt, read the Interrupt Source Register
+
+ We have to manage priorities by software.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ ULONG IntSource;
+ BOOLEAN SCSIresult, result;
+
+ if (HalpCheckSpuriousInt(0x400)) return(FALSE);
+
+ IntSource = READ_REGISTER_ULONG(ServiceContext);
+
+
+
+ if ( IntSource & PCI_TOWER_EISA_MASK) { // EISA Interrupt
+ if (HalpESC_SB)
+ result = HalpPciEisaSBDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ else
+ result = HalpPciEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(result);
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & PCI_TOWER_SCSI1_MASK){
+
+
+
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI1_VECTOR])(
+ PCR->InterruptRoutine[SCSI1_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI 1 interrupt !\n"));
+#endif
+ HalpCheckSpuriousInt(0x00);
+ return(SCSIresult);
+
+ }
+ if ( IntSource & PCI_TOWER_SCSI2_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI2_VECTOR])(
+ PCR->InterruptRoutine[SCSI2_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI 2 interrupt !\n"));
+#endif
+ HalpCheckSpuriousInt(0x00);
+ return(SCSIresult);
+
+ }
+ //
+ // PCI interrupts
+ //
+
+ if ( IntSource & PCI_TOWER_INTA_MASK){
+ int i;
+ for (i=INTA_VECTOR;i<HalpIntAMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_TOWER_INTB_MASK){
+ int i;
+ for (i=INTB_VECTOR;i<HalpIntBMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_TOWER_INTC_MASK){
+ int i;
+ for (i=INTC_VECTOR;i<HalpIntCMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_TOWER_INTD_MASK){
+ int i;
+ for (i=INTD_VECTOR;i<HalpIntDMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+
+
+
+
+ HalpCheckSpuriousInt(0x00);
+ return (TRUE); // perhaps one of the interrupts was pending :-)
+}
+
+
+
+BOOLEAN
+HalpPciTowerInt3Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the MAUI-INT4 Interrupt on an SNI PCI tower :
+ - DCU interrupt (extra_timer,...)
+ - MPBus error
+ - Memory error
+ - PCI error
+
+ To decide which interrupt, read the Interrupt Source Register
+
+ We have to manage priorities by software.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ ULONG IntSource;
+ ULONG mem_addr,status;
+ ULONG status0,status1;
+ BOOLEAN result;
+
+
+ if (HalpCheckSpuriousInt(0x2000)) return(FALSE);
+
+
+ IntSource = READ_REGISTER_ULONG(ServiceContext);
+
+
+ //
+ // look if a DCU_INDICATE interrupt occured
+ //
+ //
+
+ if (IntSource & PCI_TOWER_D_INDICATE_MASK){
+
+
+ status = READ_REGISTER_ULONG(PCI_TOWER_INDICATE);
+
+ //
+ // look if extra timer interrupt
+ //
+
+ if (status & PCI_TOWER_DI_EXTRA_TIMER){
+
+ HalpClockInterruptPciTower();
+ return(TRUE);
+ }
+
+ DebugPrint(("DCU_INDICATE interrupt\n"));
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+
+ if ( status & PCI_TOWER_DI_PB_MASK){
+
+ DebugPrint(("Interrupt - PushButton\n"));
+
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+
+ return(TRUE);
+ }
+
+
+ //The reading of DCU_INDICATE register clears the interrupt sources
+ // --> we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the DCU driver
+ result = TRUE;
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= status;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, reset EISA_NMI interrupt if necessary
+
+ if (status & PCI_TOWER_DI_EISA_NMI)
+ {
+ UCHAR DataByte;
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus);
+
+
+ if (((PNMI_STATUS) &DataByte)->ParityNmi == 1)
+ {
+ DebugPrint(("Parity error from system memory\n"));
+
+ //reset NMI interrupt //
+
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+ }
+
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ if (((PNMI_EXTENDED_CONTROL) &DataByte)->PendingBusMasterTimeout == 1)
+ {
+ DebugPrint(("EISA Bus Master timeout\n"));
+
+ //reset NMI interrupt //
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+ }
+ }
+
+ return (result);
+ }
+
+ //
+ // look if a DCU_ERROR interrupt occured
+ //
+ //
+
+ if (IntSource & PCI_TOWER_D_ERROR_MASK){
+
+ status = 0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= 0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result =(((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+ // read DCU_ERROR register to clear interrupt source if DCU driver not installed
+ READ_REGISTER_ULONG(PCI_TOWER_DCU_ERROR);
+ return (result);
+ }
+
+
+
+ //
+ // look if MP_BUS error
+ //
+
+
+ if (IntSource & PCI_TOWER_MP_BUS_MASK){
+
+
+ status = READ_REGISTER_ULONG(PCI_TOWER_MP_BUS_ERROR_STATUS);
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MP_BUS_ERROR_ADDR);
+
+ // Clear MP_Bus interrupt
+
+ WRITE_REGISTER_ULONG (ServiceContext,IntSource);
+
+
+ if (IntSource & PCI_TOWER_C_PARITY_MASK){
+
+#if DBG
+ DebugPrint(("MP_Bus Parity Error : MPBusErrorStatus = 0x%x MPBusErrorAddress = 0x%x \n",
+ status,mem_addr));
+ //DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 5;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MP_BUS PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+ }
+
+ if (IntSource & PCI_TOWER_C_REGSIZE){
+#if DBG
+ DebugPrint(("MP_Bus Register Size Error : MPBusErrorStatus = 0x%x \n",
+ status));
+ DbgBreakPoint();
+
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 6;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MP_BUS REGISTER SIZE ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,0,0);
+#endif
+ }
+ }
+
+ //
+ // look if Memory error
+ //
+ if (IntSource & PCI_TOWER_M_ECC_MASK){
+
+
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR)& MEM_ADDR_MASK;
+
+ // correct ECC error
+ HalpMultiPciEccCorrector(mem_addr ,mem_addr >> PAGE_SHIFT,4);
+
+ IntSource = READ_REGISTER_ULONG(PCI_TOWER_GEN_INTERRUPT);
+ if (IntSource & PCI_TOWER_M_ECC_MASK){
+
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR)& MEM_ADDR_MASK;
+ KeStallExecutionProcessor(100);
+ }
+ // We use SNI_PRIVATE_VECTOR to transmit parameters to DCU driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved=0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis=FLAG_ECC_ERROR;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorSimmNum=HalpComputeNum((UCHAR *)mem_addr);
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorAddress= mem_addr ;
+
+ // Call the 'DCU' driver to log the ECC error in event viewer
+
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+
+ }
+
+ if (IntSource & PCI_TOWER_M_ADDR_MASK){
+
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR);
+#if DBG
+ DebugPrint(("Memory Address Error : MemErrorAddr = 0x%x \n",mem_addr));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 7;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY ADDRESS ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,mem_addr,0,0);
+#endif
+ }
+
+ if (IntSource & PCI_TOWER_M_SLT_MASK){
+
+ ULONG MemControl2,MemConf;
+
+ MemControl2 = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_2);
+ MemConf = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONFIG);
+#if DBG
+ DebugPrint(("Memory slot Error : MemControl2 = 0x%x, MemConf = 0x%x \n",MemControl2,MemConf));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 8;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY SLOT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,MemControl2,MemConf,0);
+#endif
+ }
+
+ if (IntSource & PCI_TOWER_M_CFG_MASK){
+
+ ULONG MemControl2,MemConf;
+
+ MemControl2 = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_2);
+ MemConf = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONFIG);
+#if DBG
+ DebugPrint(("Memory Config Error : MemControl2 = 0x%x, MemConf = 0x%x \n",MemControl2,MemConf));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 9;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY CONFIG ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,MemControl2,MemConf,0);
+#endif
+ }
+
+
+ if (IntSource & PCI_TOWER_M_RC_MASK){
+
+ // reset error counter
+ WRITE_REGISTER_ULONG (PCI_TOWER_MEM_CONTROL_1, (READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_1) & ERROR_COUNTER_MASK) | ERROR_COUNTER_INITVALUE);
+
+#if DBG
+ DebugPrint(("Memory Read Error Counter Overflow\n"));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 2;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "ECC SINGLE ERROR COUNTER OVERFLOW\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,0,0,0);
+#endif
+ }
+
+
+
+ //
+ // look if PCI interrupt
+ //
+ if (IntSource & PCI_TOWER_P_ERROR_MASK){
+ ULONG PciDataInt,PciData;
+
+ DebugPrint(("PCI interrupt \n"));
+
+
+ PciDataInt = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+
+ status = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+
+ // First Initiator interrupt
+
+ if (status & PI_INITF){
+
+ PciData = PCI_TOWER_INITIATOR_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // Reset interrupt with write-1-to-clear bit Initiator_Interrupts
+ status0 = PI_INITF;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+ if (status & PI_REC_TARGET_RETRY)
+ HalpTargetRetryCnt++;
+ else {
+
+#if DBG
+ DebugPrint(("PCI Iniatiator interrupt error : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 10;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI INITIATOR INTERRUPT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+ }
+ }
+
+ // First Target interrupt
+
+ if (status & PI_TARGF){
+ PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // Reset interrupt with write-1-to-clear bit Target_Interrupts
+ status0 = PI_TARGF;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+
+#if DBG
+ DebugPrint(("PCI Target interrupt error : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 11;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI TARGET INTERRUPT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+
+ }
+
+ // First parity error
+
+ if (status & PI_PARF){
+
+ // Reset interrupt with write-1-to-clear bit Parity_Interrupts
+ status0 = PI_PARF;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+ PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status0 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ PciData = PCI_TOWER_PAR_1_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status1 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+#if DBG
+ DebugPrint(("PCI Parity interrupt error : Parity_0 register = 0x%x , Parity_1 register = 0x%x\n",
+ status0,status1));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 12;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI PARITY INTERRUPT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status0,status1,0);
+#endif
+
+ }
+
+
+ // Multiple Initiator interrupts
+
+ if (status & PI_INITM){
+
+ PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+ // Reset interrupt with write-1-to-clear bit Multiple Initiator_Interrupts
+ status0 = PI_INITM;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+
+
+ if (!(status & PI_REC_TARGET_RETRY)) {
+#if DBG
+ DebugPrint(("Multiple PCI Iniatiator interrupt : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 13;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI INITIATOR ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+ }
+ }
+
+ // Multiple Target interrupts
+
+ if (status & PI_TARGM){
+
+ PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // Reset interrupt with write-1-to-clear bit Multiple Target_interrupts
+ status0 = PI_TARGM;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+
+
+#if DBG
+ DebugPrint(("Multiple PCI Target interrupt : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 14;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI TARGET ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+
+ }
+
+ // Multiple Parity interrupts
+
+ if (status & PI_PARM){
+
+ // Reset interrupt with write-1-to-clear bit Multiple Parity_Interrupts
+ status0 = PI_PARM;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+ PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status0 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ PciData = PCI_TOWER_PAR_1_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status1 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+
+#if DBG
+ DebugPrint(("Multiple PCI Parity interrupt : Parity_0 register = 0x%x , Parity_1 register = 0x%x\n",
+ status0,status1));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 15;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status0,status1,0);
+#endif
+
+ }
+ //reenable PCI interrupt
+ status &= MASK_INT;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status));
+
+ }
+ HalpCheckSpuriousInt(0x00);
+ return (TRUE); // perhaps one of the interrupts was pending :-)
+}
+
+
+
+
diff --git a/private/ntos/nthals/halsnip/mips/snidef.h b/private/ntos/nthals/halsnip/mips/snidef.h
new file mode 100644
index 000000000..8f803cb46
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snidef.h
@@ -0,0 +1,225 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snidef.h,v 1.5 1995/11/30 11:12:21 sylvie Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ SNIdef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ common for all SNI systems.
+
+
+
+---*/
+
+#ifndef _SNIDEF_
+#define _SNIDEF_
+
+
+#if DBG
+#define DebugPrint(arg) DbgPrint arg
+#else
+#define DebugPrint(arg) ;
+#endif
+
+#include "snipci.h"
+
+#define VESA_BUS_PHYSICAL_BASE 0x1d000000
+#define VESA_BUS (VESA_BUS_PHYSICAL_BASE | KSEG1_BASE)
+#define VESA_IO_PHYSICAL_BASE 0x1e000000
+#define VESA_IO (VESA_IO_PHYSICAL_BASE | KSEG1_BASE)
+#define PROM_PHYSICAL_BASE 0x1fc00000 // physical base of boot PROM
+#define EISA_MEMORY_PHYSICAL_BASE 0x10000000 // physical base of EISA memory
+#define EISA_CONTROL_PHYSICAL_BASE 0x14000000 // physical base of EISA I/O Space
+#define EISA_MEMORY_BASE (EISA_MEMORY_PHYSICAL_BASE | KSEG1_BASE)
+#define EISA_IO (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE)
+
+// Cache replace addresse for multi-processor machines
+#define MPAGENT_RESERVED 0x17c00000 // MP-Agent operator (VL machines and tower PCI)
+#define RM300_RESERVED 0x00c00000 // cache replace (memory) for RM300 PCI
+
+#define NET_PHYSICAL_BASE 0x18000000 // physical base of ethernet control
+#define SCSI_PHYSICAL_BASE 0x19000000 // physical base of SCSI control 1
+
+#define FLOPPY_CHANNEL 0x2 // Floppy DMA channel
+#define FLOPPY_RELATIVE_BASE 0x3f0 // base of floppy control
+#define PARALLEL_RELATIVE_BASE 0x3bc // base of parallel port
+#define SERIAL0_RELATIVE_BASE 0x3f8 // base of serial port 0
+#define SERIAL1_RELATIVE_BASE 0x2f8 // base of serial port 1
+
+#define FLOPPY_PHYSICAL_BASE 0x140003f0 // base of floppy control
+#define PARALLEL_PHYSICAL_BASE 0x140003bc // base of parallel port
+#define SERIAL0_PHYSICAL_BASE 0x140003f8 // base of serial port 0
+#define SERIAL1_PHYSICAL_BASE 0x140002f8 // base of serial port 1
+
+//
+// the UCONF, MachineStatus, LED and MachineConfig Registers in the ASIC
+// (identical on all SNI machines)
+//
+
+#define UCONF_PHYSICAL_ADDR 0x1fff0000 // interruptions, interface protocol
+#define UCONF_ADDR 0xbfff0000 // interruptions, | KSEG1_BASE
+#define IOMEMCONF_PHYSICAL_ADDR 0x1fff0010 // I/O and Memory Config (for disable Timeout int)
+#define IOMEMCONF_ADDR 0xbfff0010 // I/O and memconf | KSEG1_BASE
+
+//
+// some debugging information registers in the ASIC
+// common on all SNI machines
+//
+
+#define DMACCES_PHYSICAL_ADDR 0x1fff0028 // Counter: # of DMA accesses
+#define DMACCES 0xbfff0028 // Counter: # of DMA accesses | KSEG1_BASE
+#define DMAHIT_PHYSICAL_ADDR 0x1fff0030 // Counter: # of DMA hits
+#define DMAHIT 0xbfff0030 // Counter: # of DMA hits | KSEG1_BASE
+#define IOMMU_PHYSICAL_ADDR 0x1fff0018 // Select IO space addressing
+#define IOMMU 0xbfff0018 // Select IO space addressing | KSEG1_BASE
+#define IOADTIMEOUT1_PHYSICAL_ADDR 0x1fff0020 // Current IO context for the first CPU timeout
+#define IOADTIMEOUT1 0xbfff0020 // first CPU timeout | KSEG1_BASE
+#define IOADTIMEOUT2_PHYSICAL_ADDR 0x1fff0008 // Current IO context on all CPU timeouts
+#define IOADTIMEOUT2 0xbfff0008 // all CPU timeouts | KSEG1_BASE
+
+//
+// Define system time increment value.
+//
+
+#define TIME_INCREMENT (10 * 1000 * 10) // Time increment in 100ns units
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+#define EXTRA_TIMER_CLOCK_IN 7159090 // 7.15909 Mhz (hard value)
+// #define EXTRA_TIMER_CLOCK_IN 7900000 // adjustement to get fq = 10ms
+
+#define PRE_COUNT 3 //
+
+//
+// Define basic Interrupt Levels which correspond to Cause register bits.
+//
+
+#define INT0_LEVEL 3
+#define INT3_LEVEL 3
+#define SCSIEISA_LEVEL 4 // SCSI/EISA device int. vector
+#define EISA_DEVICE_LEVEL 4 // EISA bus interrupt level ???
+#define DUART_VECTOR 5 // DUART SC 2681 int. vector
+
+#define INT6_LEVEL 6
+#define EXTRA_CLOCK_LEVEL 5 // extra timer on RM300
+
+#define PROFILE_LEVEL 8 // Profiling level via Count/compare Interrupt
+
+#define CLOCK_LEVEL (ONBOARD_VECTORS + 0) // Timer channel 0 in the PC core
+
+//
+// all others are vectors in the interrupt dispatch table.
+//
+
+#define SCSI_VECTOR 9 // SCSI device interrupt vector
+#define SCSI1_VECTOR 9 // SCSI 1 device interrupt vector
+#define SCSI2_VECTOR 10 // SCSI 2 device interrupt vector
+#define NET_DEFAULT_VECTOR 7 // ethernet device internal vector on R4x00 PC !!!
+ // configured in the Firmware Tree !!!!!
+#define NET_LEVEL 10 // ethernet device int. vector
+
+#define OUR_IPI_LEVEL 7 // multipro machine
+#define NETMULTI_LEVEL 5 // multipro machine : ethernet device int. vector
+
+#define EIP_VECTOR 15 // EIP Interrupt routine
+#define DCU_VECTOR 15 // DCU Interrupt routine
+
+#define CLOCK2_LEVEL CLOCK_LEVEL // System Clock Level
+
+#define ONBOARD_VECTORS 16
+#define MAXIMUM_ONBOARD_VECTOR (15 + ONBOARD_VECTORS) // maximum Onboard (PC core) vector
+
+//
+// Define EISA device interrupt vectors.
+// they only occur when an Eisa Extension is installed in the Desktop model
+//
+
+#define EISA_VECTORS 32
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+//
+// relative interrupt vectors
+// only the interrupt vectors relative to the Isa/EISA bus are defined
+//
+
+#define KEYBOARD_VECTOR 1 // Keyboard device interrupt vector
+#define SERIAL1_VECTOR 3 // Serial device 1 interrupt vector
+#define SERIAL0_VECTOR 4 // Serial device 0 interrupt vector
+#define FLOPPY_VECTOR 6 // Floppy device interrupt vector
+#define PARALLEL_VECTOR 7 // Parallel device interrupt vector
+#define MOUSE_VECTOR 12 // PS/2 Mouse device interrupt vector
+
+
+// PCI interrupts
+
+#define INTA_VECTOR 50 // PCI INTA first interrupt number
+#define INTB_VECTOR 100 // PCI INTB first interrupt number
+#define INTC_VECTOR 150 // PCI INTC first interrupt number
+#define INTD_VECTOR 200 // PCI INTD first interrupt number
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0xc0000 // 768KB for today
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0xc0000 // 256KB as start
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 512
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+// (16MB)
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the maximum physical address of Main memory on SNI machines
+// (256 MB)
+//
+
+#define MAXIMUM_MEMORY_PHYSICAL_ADDRESS 0x10000000
+
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+
+
+#endif /* _SNIDEF_ */
diff --git a/private/ntos/nthals/halsnip/mips/snidisp.c b/private/ntos/nthals/halsnip/mips/snidisp.c
new file mode 100644
index 000000000..0e31d4fc0
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snidisp.c
@@ -0,0 +1,1201 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snidisp.c,v 1.5 1996/03/04 13:24:39 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991-93 Microsoft Corporation
+
+Module Name:
+
+ SNIdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for the different SNI machines.
+
+ At the moment we know about the following boards:
+ WEITEK P9100 PCIBUS (not in the HAL at the moment...)
+ MATROX STORM PCIBUS ( 80x50 Alpha Mode)
+ Cirrus 5434 PCI cards ( 80x50 Alpha Mode)
+ Standard (unknown) VGA on PCI( 80x50 Alpha Mode)
+
+ If we can not identify the board, we don't initialise the display and we call
+ the vendor printf to display strings.
+
+ At the boot phase all I/O is done via the unmapped uncached Segment (KSEG1) of the
+ R4000 (HalpEisaControlBase); later with the mapped value of HalpEisaControlBase
+ Memory is always accessed via unmapped/uncached (KSEG1) area
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Removed HalpInitializeDisplay1, because we do no longer use the P9000 in graphic mode ...
+
+
+NOTE:
+
+
+ We did use our own ...MoveMemory() instead of RtlMoveMemory(),
+ as there is a Hardware bug in our machine and RtlMoveMemory uses
+ the floating point registers for fast 64 bit move and on our bus
+ only 32 bit can be found ... :-)
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+#include "vgadata.h"
+
+#define MEGA_MOVE_MEMORY(D,S,L) MegaMoveMemory(D,S,L) // orig. RtlMoveMemory()
+
+//
+// supported VGA text modi
+//
+
+typedef enum _TEXT_MODE {
+ TEXT_80x50,
+ TEXT_132x50
+} TEXT_MODE;
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+extern VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID HalpDisplaySmallCharacter (IN UCHAR Character);
+VOID HalpOutputSmallCharacter (IN PUCHAR Font);
+VOID HalpInitializeVGADisplay(TEXT_MODE TextMode);
+VOID HalpClearVGADisplay (VOID);
+VOID HalpDisplayVGAString (PUCHAR String);
+VOID HalpPutVGACharacter (UCHAR Character);
+VOID HalpNextVGALine (VOID);
+VOID HalpScrollVGADisplay (VOID);
+VOID DownLoadVGAFont (VOID);
+VOID HalpResetS3Chip (VOID);
+VOID HalpResetCirrusChip (VOID);
+VOID HalpResetP9000 (VOID);
+VOID HalpResetMatroxStorm (VOID);
+VOID HalpVGASetup (VOID);
+VOID HalpDoNoSetup (VOID);
+
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+
+//
+// Supported board definitions.
+//
+
+typedef enum _VIDEO_BOARD {
+ S3_GENERIC, // Standard S3 based Card (miro crystal 8s)
+ S3_GENERIC_VLB, // Standard S3 based Card (Local Bus)
+ CIRRUS_GENERIC, // Generic Cirrus VGA (Cirrus CL54xx)
+ CIRRUS_GENERIC_VLB, // Generic Cirrus VGA (Cirrus CL54xx) (Local Bus)
+ CIRRUS_ONBOARD, // The Desktop onboard VGA (Cirrus CL5434)
+ VGA_GENERIC, // generic (unknown) VGA
+ VGA_GENERIC_VLB, // generic (unknown) VGA on the Vesa Local BUS
+ MATROX_STORM,
+ VIDEO_BOARD_UNKNOWN // unknown Display Adapter
+} VIDEO_BOARD;
+
+//
+// some supported VGA chips
+//
+
+typedef enum _VIDEO_CHIP {
+ S3,
+ CIRRUS,
+ VGA, // generic (unknown) VGA
+ VGA_P9000,
+ VGA_STORM,
+ VIDEO_CHIP_UNKNOWN
+} VIDEO_CHIP;
+
+typedef struct _VIDEO_BOARD_INFO {
+ PUCHAR FirmwareString;
+ PHALP_CONTROLLER_SETUP ControllerSetup;
+ VIDEO_BOARD VideoBoard;
+ VIDEO_CHIP VideoChip;
+} VIDEO_BOARD_INFO, *PVIDEO_BOARD_INFO;
+
+
+VIDEO_BOARD_INFO KnownVideoBoards[] = {
+ {"VGA ON PCIBUS", HalpVGASetup , VGA_GENERIC, VGA },
+ {"CIRRUS 5434 PCIBUS", HalpVGASetup , CIRRUS_GENERIC, CIRRUS},
+ {"MATROX STORM PCIBUS", HalpVGASetup , MATROX_STORM , VGA_STORM }
+};
+
+LONG numVideoBoards = sizeof (KnownVideoBoards) / sizeof(VIDEO_BOARD_INFO);
+
+//
+// Define static data.
+//
+
+VIDEO_BOARD HalpVideoBoard = VIDEO_BOARD_UNKNOWN;
+VIDEO_CHIP HalpVideoChip = VIDEO_CHIP_UNKNOWN;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = HalpDoNoSetup;
+
+ULONG HalpColumn;
+ULONG HalpRow;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+ULONG HalpBytesPerRow;
+PVOID HalpVGAControlBase=( PVOID)( EISA_IO); // Base Address for VGA register access
+PUSHORT VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000);
+PUCHAR FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000);
+BOOLEAN HalpFirstBoot = TRUE;
+
+ULONG HalpMgaStormBase = 0;
+ULONG Halpval40;
+ULONG HalpMatroxBus,HalpMatroxSlot;
+//
+// Declare externally defined data.
+//
+
+
+BOOLEAN HalpDisplayOwnedByHal;
+PHAL_RESET_DISPLAY_PARAMETERS HalpReturnToVga;
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+
+
+VOID MegaMoveMemory(
+ OUT PVOID Destination,
+ IN PVOID Source,
+ IN ULONG Length
+ )
+/*++
+
+ Our private function written to substitute the RtlMoveMemory()
+ function (64 bit problem).
+
+--*/
+{
+ULONG lo_index_ul;
+PULONG Dst, Src;
+
+ Dst = (PULONG)Destination;
+ Src = (PULONG)Source;
+ for (lo_index_ul=0; lo_index_ul < Length/sizeof(ULONG); lo_index_ul++)
+ *Dst++ = *Src++;
+}
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PVIDEO_BOARD_INFO VideoBoard;
+ LONG Index;
+ ULONG MatchKey;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // N.B. Be carefull with debug prints during Phase 0, it
+ // will kill the initial break point request from the debugger ...
+ //
+
+
+ for( Index=0, VideoBoard = KnownVideoBoards; Index < numVideoBoards; Index++, VideoBoard++) {
+
+ if (!strcmp( ConfigurationEntry->ComponentEntry.Identifier,
+ VideoBoard->FirmwareString
+ )) {
+ HalpVideoBoard = VideoBoard->VideoBoard;
+ HalpVideoChip = VideoBoard->VideoChip;
+ HalpDisplayControllerSetup = VideoBoard->ControllerSetup;
+ break;
+ }
+ }
+
+ if (Index >= numVideoBoards) {
+ HalpVideoBoard = VIDEO_BOARD_UNKNOWN;
+ HalpVideoChip = VIDEO_CHIP_UNKNOWN;
+ HalpDisplayControllerSetup = HalpVGASetup;
+
+ //
+ // let's see, if the bios emulator can initialize the card ....
+ //
+
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ return TRUE;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+
+ HalpFirstBoot = FALSE;
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine normally allocates pool for the OEM font file, but
+ in this version we use only VGA facilities of the Grapgic boards
+ so we simply return TRUE
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ TRUE
+
+--*/
+
+{
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ HalpReturnToVga = ResetDisplayParameters;
+ return;
+}
+
+VOID
+HalpDoNoSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine does nothing...
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpVGASetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes a VGA based Graphic card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR byte;
+
+ HalpVGAControlBase = (PVOID)HalpEisaControlBase;
+ VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000);
+ FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000);
+
+ //
+ // if "only" VGA is detected look for an S3 or cirrus chip (VGA ON ATBUS)
+ // if the firmware detects an S3 chip, look if this is an 805i (interleave)
+ //
+
+
+ if ((HalpVideoChip == VGA) || (HalpVideoChip == S3)){
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // look for Cirrus chips
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); // read it back
+ if (byte != 0x12) { // no cirrus
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x30); // look for s3 chip id
+ byte = READ_REGISTER_UCHAR(VGA_CRT_DATA) ; // look only for major id
+ switch (byte & 0xf0){
+ case 0xa0: // 801/805 chipset
+ if (byte == 0xa8) { // the new 805i (interleave)
+// DebugPrint(("HAL: Found the new 805i Chip resetting to 805 mode\n"));
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0067);
+ }
+ case 0x80:
+ case 0x90:
+// DebugPrint(("HAL: Found S3 Chip set - Chip id 0x%x\n",byte));
+ HalpVideoChip = S3;
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs
+ break;
+ default: DebugPrint(("HAL: This seems to be no S3 Chip\n"));
+ }
+ } else { // this may be an cirrus
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x27); // cirrus id reg
+ byte = READ_REGISTER_UCHAR(VGA_CRT_DATA);
+ if ((byte & 0xe0) == 0x80) { // look for 100xxxxx
+// DebugPrint(("HAL: Found Cirrus Chip set - Chip id 0x%x\n",byte));
+ HalpVideoChip = CIRRUS;
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0006); // lock Cirrus extensions
+ }
+ }
+ }
+
+
+ switch (HalpVideoChip) {
+
+ case S3: HalpResetS3Chip();
+ break;
+
+ case CIRRUS: HalpResetCirrusChip();
+ break;
+
+ case VGA_STORM:
+ HalpResetMatroxStorm();
+ break;
+
+ default: ;
+ }
+
+ HalpInitializeVGADisplay(TEXT_80x50);
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if(HalpIsMulti) KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+
+ if (((HalpVideoBoard == VIDEO_BOARD_UNKNOWN) || (HalpVideoBoard == VGA_GENERIC)) && (HalpReturnToVga != NULL)) {
+ (HalpReturnToVga)(80,25);
+ }
+ HalpDisplayControllerSetup();
+
+ }
+
+ // display the string
+
+// if( HalpVideoChip == VIDEO_CHIP_UNKNOWN) {
+// ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->printf(String);
+// } else {
+ HalpDisplayVGAString(String);
+// }
+
+ if(HalpIsMulti) KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+
+VOID
+HalpDisplayVGAString (
+ PUCHAR String
+ )
+{
+ while (*String) {
+ switch (*String) {
+ case '\n':
+ HalpNextVGALine();
+ break;
+ case '\r':
+ HalpColumn = 0;
+ break;
+ default:
+ HalpPutVGACharacter(*String);
+ if (++HalpColumn == HalpDisplayWidth) {
+ HalpNextVGALine();
+ }
+ }
+ ++String;
+ }
+
+ return;
+}
+
+
+VOID
+HalpNextVGALine(
+ VOID
+ )
+{
+ if (HalpRow==HalpDisplayText-1) {
+ HalpScrollVGADisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+}
+
+VOID
+HalpScrollVGADisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Scrolls the text on the display up one line.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUSHORT NewStart;
+ ULONG i;
+
+
+ NewStart = VideoBuffer+HalpDisplayWidth;
+ MegaMoveMemory((PVOID)VideoBuffer, (PVOID)NewStart, (HalpDisplayText-1)*HalpDisplayWidth*sizeof(USHORT));
+
+ for (i=(HalpDisplayText-1)*HalpDisplayWidth; i<HalpDisplayText*HalpDisplayWidth; i++) {
+ VideoBuffer[i] = (REVERSE_ATTRIBUTE << 8) | ' ';
+ }
+}
+
+VOID
+HalpPutVGACharacter(
+ UCHAR Character
+ )
+{
+ PUSHORT cp = (PUSHORT)VideoBuffer;
+ int x = HalpColumn;
+ int y = HalpRow;
+
+ cp[y*HalpDisplayWidth + x] = (USHORT)((REVERSE_ATTRIBUTE << 8) | (Character ));
+}
+
+
+VOID
+HalpClearVGADisplay(
+ VOID
+ )
+{
+ ULONG i;
+ PUSHORT cp = (PUSHORT)VideoBuffer;
+ USHORT Attribute = (REVERSE_ATTRIBUTE << 8) | ' ';
+
+ for(i=0; i < HalpDisplayText*HalpDisplayWidth; i++) {
+ VideoBuffer[i] = Attribute;
+ }
+
+ HalpColumn=0;
+ HalpColumn=0;
+}
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ HARDWARE specific Part of Display routines
+
+ this part of this file deals with special Hardware parts of some
+ graphic adapters (RamDac, Clock Generator, VGA Chipsets etc.
+
+-------------------------------------------------------------------*/
+
+VOID
+DownLoadVGAFont(
+ VOID
+ )
+/*+++
+
+ The Space occupied for 1 caracter in the charackter generator memory of an VGA
+ is 0x20 bytes, The font itself uses only 8 bytes, so we skip over the difference
+
+---*/
+{
+
+ PUCHAR dst = (PUCHAR)FontBuffer;
+ PUCHAR src = (PUCHAR)font_8x8;
+ long i, count = 256;
+
+ INIT_VGA_FONT();
+
+ while(count--){
+ for (i=0; i<8; i++)
+ *dst++ = *src++;
+ dst += 0x18;
+ }
+ EXIT_VGA_FONT() ;
+}
+
+VOID
+HalpInitializeVGADisplay(
+ TEXT_MODE TextMode
+ )
+{
+
+static UCHAR _80x50_crt_regs [MAX_CRT] = { // 80x50 text mode
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, // cr0 - cr4
+ 0x81, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char
+ 0x20, 0x00, 0x00, 0x00, 0x00, // cra - cursor off
+ 0x00, 0x9c, 0x8e, 0x8f, 0x28,
+ 0x1f, 0x96, 0xb9, 0xa3, 0xff
+ };
+
+static UCHAR _132x50_crt_regs [MAX_CRT] = { // 132x50 text mode
+ 0xa0, 0x83, 0x84, 0x83, 0x8a, // cr0 - cr4
+ 0x9e, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char
+ 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x9c, 0x85, 0x8f, 0x42,
+ 0x1f, 0x95, 0xa5, 0xa3, 0xff
+ };
+
+static UCHAR default_graph_regs[GRAPH_MAX] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x0e, 0x00, 0xff
+ };
+
+static UCHAR default_pal_regs[MAX_PALETTE] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x14, 0x7, 0x38, 0x39,
+ 0x3A, 0x3B, 0x3C, 0x3d, 0x3e,
+ 0x3f, 0x08, 0x00, 0x0f, 0x00,
+ 0x00
+ };
+
+ int i;
+ UCHAR byte;
+
+ //
+ // Matrox modification : (cf I/O space mapping p 3.9 of MGA STORM specification)
+ // PCI convention states that i/o space should only be accessed in bytes)
+ //
+
+ //
+ // VGA_MISC : 25.xxx MHZ frequency -> 640 horizontal pixels (val = 63)
+ // VGA_MISC : 28.xxx MHZ frequency -> 720 horizontal pixels (val = 67)
+ //
+
+ if (HalpVideoChip == VGA_STORM) WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x67) ; // else little frame
+
+ // reset ATC FlipFlop
+ byte = READ_REGISTER_UCHAR(VGA_ATC_FF);
+ WRITE_REGISTER_UCHAR(VGA_ATC_DATA, 0); // Disable palette
+
+ // stop the sequencer
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0100);
+
+ if (HalpVideoChip != VGA_STORM) {
+ if (TextMode == TEXT_132x50) {
+ // external clock (40MHz)
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0xAF);
+ } else {
+ // COLOR registers , enable RAM, 25 MHz 400 Lines,
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63) ;
+ }
+ }
+
+ // Select the timing sequencer values
+ // 8 dot/char
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0101);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0302);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0003);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0204);
+
+ // start the sequencer
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0300);
+
+ // Unprotect CRT regs and program them
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX , 0x0011);
+
+ for(i=0; i<MAX_CRT; i++) {
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, i);
+ if (TextMode == TEXT_132x50){
+ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _132x50_crt_regs[i]);
+ } else {
+ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _80x50_crt_regs[i]);
+ }
+ }
+
+ DownLoadVGAFont();
+
+ HalpDisplayWidth = (TextMode == TEXT_132x50) ? 132 : 80;
+ HalpDisplayText = 50;
+
+ HalpClearVGADisplay();
+
+ i = READ_REGISTER_UCHAR(VGA_ATC_FF); // Reset attr FF
+
+ if (!HalpFirstBoot) {
+
+ //
+ // if this is not the First Boot
+ // i.e. an Bugcheck; we have to setup
+ // the Attribute and colors of the VGA PART
+ //
+
+ for(i=0; i<GRAPH_MAX; i++) {
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX , i);
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, default_graph_regs[i]);
+ }
+
+ for(i=0; i<MAX_PALETTE; i++) { // PALETTE (ATC)
+ WRITE_REGISTER_UCHAR(VGA_ATC_IDX , i);
+ WRITE_REGISTER_UCHAR(VGA_ATC_DATA, default_pal_regs[i]);
+ }
+
+
+ }
+
+ WRITE_REGISTER_UCHAR(VGA_DAC_MASK , 0xff);
+
+ //
+ // set the 16 base colors for text mode in the DAC
+ //
+
+ WRITE_REGISTER_UCHAR(VGA_DAC_WRITE_INDEX, 0x00);
+ for(i=0; i<48; i++) {
+ WRITE_REGISTER_UCHAR(VGA_DAC_DATA, base_colors[i]);
+ }
+
+ WRITE_REGISTER_UCHAR(VGA_ATC_IDX, 0x20);
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer
+}
+
+VOID
+HalpMgaWaitLock(
+ UCHAR clock,
+ UCHAR p
+ )
+{
+UCHAR tmpByte;
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xea);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,clock);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,(p & 0x7f));
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xea);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,clock);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,p );
+ KeStallExecutionProcessor(10);
+
+ tmpByte = 0;
+ while (!(tmpByte & 0x40)) {
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,clock);
+ tmpByte = READ_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA);
+ KeStallExecutionProcessor(10);
+ }
+
+}
+
+
+VOID
+HalpResetMatroxStorm(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA part of an Matrox storm card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT buffer[8];
+ UCHAR tmpByte;
+
+ if (!HalpMgaStormBase) {
+ for(HalpMatroxBus=0;HalpMatroxBus<32;++HalpMatroxBus) {
+
+ for(HalpMatroxSlot=0;HalpMatroxSlot<32;++HalpMatroxSlot) {
+
+ HalpReadPCIConfig(HalpMatroxBus,HalpMatroxSlot,&buffer,0,14);
+
+ if ((buffer[0] == 0x102b) && (buffer[1] == 0x0519) && (buffer[5] == 0x0300)) {
+ HalpReadPCIConfig(HalpMatroxBus,HalpMatroxSlot,&HalpMgaStormBase,0x10,4);
+ break;
+
+ }
+ }
+ if (HalpMgaStormBase) break;
+ }
+ }
+ if ( HalpMgaStormBase == (ULONG)0) return;
+
+ // tranlated address
+ HalpMgaStormBase |= 0xa0000000;
+
+ /*** wait for the drawing engine to be idle ***/
+ tmpByte = 0;
+ while (tmpByte & 0x01) tmpByte = READ_REGISTER_UCHAR(HalpMgaStormBase + STORM_OFFSET + STORM_STATUS + 2);
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET + STORM_MISC_W, 0x67);
+
+ if (HalpFirstBoot) {
+ HalpReadPCIConfig(HalpMatroxBus,HalpMatroxSlot,&Halpval40,STORM_PCI_OPTION,4);
+ } else {
+ // interleave bit is reset - gclk not divided - VGA io locations decoded
+ HalpSetPCIData(HalpMatroxBus,HalpMatroxSlot,(PUCHAR)(&Halpval40),STORM_PCI_OPTION,4);
+ }
+
+ if (!HalpFirstBoot) {
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET +STORM_MISC_W, 0x2f);
+
+ /*** first : reset (especially for cursor...) ***/
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_RESET);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0);
+
+ /*** like fw -> pgm clocks (50Mhz) ***/
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET +STORM_MISC_W, 0x2f); // to pgm PLL
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PIX_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xfd);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PIX_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x3a);
+ HalpMgaWaitLock(STORM_TVP3026_PIX_CLK_DATA,0xb2);
+
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x0);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x8);
+
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MEM_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xfd);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MEM_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x3a);
+ HalpMgaWaitLock(STORM_TVP3026_MEM_CLK_DATA,0xb2);
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x10);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x18);
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET + STORM_MISC_W, 0x67); // VGA clock 25.xxxMhz
+
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT1);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT2);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT3);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT4);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT5);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ }
+
+}
+
+
+VOID
+HalpResetS3Chip(
+ VOID
+ )
+/*+++
+
+ This function resets/loads default values to the S3 Chip
+ extended registers
+
+ this code is borrowed/derived from the s3 miniport driver
+
+---*/
+{
+ UCHAR byte;
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0140); // Enable the enhanced 8514 registers
+ WRITE_REGISTER_USHORT(S3_ADVFUNC_CNTL, 0x02); // reset to normal VGA operation
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0032); // Backward Compat 3
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0035); // CRTC Lock
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // async reset
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x01); //
+
+ WRITE_REGISTER_UCHAR(VGA_FEAT_CNTRL, 0x00); // normal sync
+ WRITE_REGISTER_UCHAR(VGA_MISC_READ, 0x00); //
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8531);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x2033); // Backward Compat 2
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0034); // Backward Compat 3
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x853a); // S3 Misc 1
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x5a3b); // Data Transfer Exec Pos
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x103c); // Interlace Retrace start
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // start the sequencer
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); //
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa640); // VLB: 3Wait
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x1841);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0050);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0051);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff52);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x3854);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0055);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0056);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0057);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8058); // ISA Latch ? (bit 3)
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005c);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005d);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005e);
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0760);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8061);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa162);
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0043); // Extended Mode
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0045); // HW graphics Cursor Mode
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0046); // HW graphics Cursor Orig x
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff47); // HW graphics Cursor Orig x
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xfc48); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff49); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4a); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4b); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4c); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4d); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4e); // Dsp Start x pixel pos
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xdf4f); // Dsp Start y pixel pos
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0042); // select default clock
+
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63); // Clock select
+/*
+// this should be done in the InitializeVGA code ...
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer
+*/
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs
+
+}
+
+VOID
+HalpResetCirrusChip(
+ VOID
+ )
+/*+++
+
+ This function resets/loads default values to the Cirrus Chip
+ extended registers for use with extended text mode (80x50)
+
+ Register values found in the cirrus manual, appendix D5
+
+---*/
+{
+ UCHAR byte;
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer
+
+ // extended sequencer and crtc regs for cirrus
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // unlock the extended registers
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x4008);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x5709);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x180a);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x660b);
+
+ // new modifs
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x000f);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0016);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x001b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x0009);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000a);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000b);
+ // end new modifs
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0010);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0011);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0012);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0013);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0018);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0119);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x001a);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x2f1c);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x301d);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x331e);
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/snihalp.h b/private/ntos/nthals/halsnip/mips/snihalp.h
new file mode 100644
index 000000000..9bfc31e99
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snihalp.h
@@ -0,0 +1,422 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snihalp.h,v 1.5 1996/03/12 14:56:20 pierre Exp $")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ SNIhalp.h, original file jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ SNI specific interfaces, defines and structures.
+
+
+--*/
+
+#ifndef _SNIHALP_
+#define _SNIHALP_
+#include "SNIdef.h"
+
+//
+// Determine if an virtual address is really a physical address.
+//
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+#define IS_KSEG0_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG1_BASE)) ? TRUE : FALSE)
+
+#define IS_KSEG1_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG1_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+#define KSEG0_TO_KSEG1(Va) { \
+ Va &= ~KSEG0_BASE; \
+ Va |= KSEG1_BASE; \
+ }
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpOnboardControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+extern PVOID HalpEisaMemoryBase;
+
+extern UCHAR HalpIsMulti;
+extern BOOLEAN HalpIsTowerPci;
+extern ULONG HalpMpaCacheReplace; // address to be used for cache replace operation.
+extern ULONG HalpTwoWayBit; // size of one set for associative cache R5000-R4600-R4700
+
+//
+// possibly processor types for SNI machines ...
+//
+
+typedef enum _HalpProcessorType {
+ ORIONSC, // Orion + Writeback secondary cache
+ MPAGENT, // R4000 + MpAgent
+ R4x00, // R4000 SC
+ UNKNOWN // not yet identified (initial value)
+} HalpProcessorType;
+
+//
+// Kind of processor of SNI machines
+//
+
+extern HalpProcessorType HalpProcessorId;
+
+#define HalpR4600 32
+#define HalpR4700 33
+//
+// possibly moterboard types for SNI machines ...
+//
+
+typedef enum _MotherBoardType {
+// M8022 = 2, // RM400-10 mother board
+// M8022D = 3, // RM400-10 mother board (new PCB)
+// M8032 = 4, // RM400 Tower
+// M8042 = 5, // RM400 Minitower
+ M8150 = 6, // RM400 PCI Tower
+// M8036 = 7, // RM200 Desktop
+ MinitowerPCI= 8, // minitower PCI
+ DesktopPCI = 9 // Desktop PCI
+} MotherBoardType;
+
+//
+// Kind of Mainboard of SNI machines
+//
+
+extern MotherBoardType HalpMainBoard;
+
+//
+// Define map register translation entry structure.
+//
+
+typedef struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ INTERFACE_TYPE InterfaceType;
+} ADAPTER_OBJECT;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern POBJECT_TYPE *IoAdapterObjectType;
+
+extern BOOLEAN LessThan16Mb;
+extern BOOLEAN HalpEisaDma;
+
+//
+// Map buffer parameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+//
+// Firmware interface
+//
+
+typedef struct {
+ CHAR (*getchar)();
+ PCHAR (*gets)();
+ VOID (*printf)();
+ PCHAR (*parsefile)();
+ VOID (*reinit_slave)();
+ ULONG DCU_reserved;
+ UCHAR ActiveProcessor[4];
+ USHORT DCU_reserved_bis;
+ USHORT EccErrorSimmNum;
+ ULONG EccErrorAddress;
+ struct mpmsg_s *MsgPassArea;
+ struct bank *MemConfArea;
+ ULONG NbMemBanks;
+ ULONG scram_ctlr; // fw reserved (ram disk)
+ ULONG (*EipRoutine)();
+ ULONG EipContext;
+ UCHAR EipHalInfo;
+ UCHAR pad[3];
+ ULONG reserved[5];
+ } SNI_PRIVATE_VECTOR;
+
+
+// definitions for DCU_reserved_bis
+
+#define FLAG_ECC_ERROR 1
+
+
+ struct mpmsg_s {
+ ULONG *mpmsg_wlckp; /* pointer to the writer lock */
+ ULONG *mpmsg_bp; /* beginning pointer message[0] */
+ ULONG *mpmsg_ep; /* endding pointer message[MPMSG_NMAXMSG] */
+ ULONG *mpmsg_rp; /* current read pointer in message[] */
+ ULONG *mpmsg_wp; /* current write pointer in message[] */
+};
+
+
+struct bank {
+ ULONG total_size;
+ UCHAR *first_addr;
+ ULONG first_piece_size;
+ UCHAR *second_addr;
+ ULONG second_piece_size;
+};
+
+
+
+//
+// Define function prototypes.
+//
+
+
+ULONG
+HalpGetStatusRegister(
+ VOID
+ );
+
+ULONG
+HalpSetStatusRegister(
+ ULONG Value
+ );
+
+ULONG
+HalpGetCauseRegister(
+ VOID
+ );
+
+ULONG
+HalpSetCauseRegister(
+ ULONG value
+ );
+
+ULONG
+HalpGetConfigRegister(
+ VOID
+ );
+
+ULONG
+HalpSetConfigRegister(
+ ULONG value
+ );
+
+BOOLEAN
+HalpMapIoSpace(
+ VOID
+ );
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntStructures(
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntMultiStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntPciStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ IN INTERFACE_TYPE Interface
+ );
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableOnboardInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableOnboardInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+BOOLEAN
+HalpPciInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpPciTowerInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpPciTowerInt3Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpRM200Int0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400TowerInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInt1Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int3Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int4Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int5Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpSystemInit(
+ VOID
+ );
+
+VOID
+HalpDisplayCopyRight(
+ VOID
+ );
+
+VOID
+HalpClearVGADisplay(
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt(
+ VOID
+ );
+
+VOID
+HalpInitMPAgent(
+ ULONG Number
+ );
+
+ULONG
+HalpProcIdentify(
+ VOID
+ );
+
+BOOLEAN
+HalpPciEccCorrector(
+ ULONG Addr,
+ ULONG Pfn,
+ ULONG Length
+ );
+
+BOOLEAN
+HalpMultiPciEccCorrector(
+ ULONG Addr,
+ ULONG Pfn,
+ ULONG Length
+ );
+
+#endif // _SNIHALP_
diff --git a/private/ntos/nthals/halsnip/mips/snipbus.c b/private/ntos/nthals/halsnip/mips/snipbus.c
new file mode 100644
index 000000000..0fb0d1063
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snipbus.c
@@ -0,0 +1,2051 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ Platform-independent PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "snipci.h"
+#include "snipbus.h"
+#include "pci.h"
+#include "eisa.h"
+
+UCHAR HalpInterruptLine[10][32];
+
+//
+// Define PCI slot validity
+//
+typedef enum _VALID_SLOT {
+ InvalidBus = 0,
+ InvalidSlot,
+ ValidSlot
+} VALID_SLOT;
+
+//
+// Local prototypes for routines supporting HalpGet/SetPCIData
+//
+
+VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpWritePCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpPCIConfigPartialRead(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ );
+
+VOID
+HalpPCIConfigPartialWrite(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ );
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+VOID
+HalpIntLineUpdate(
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ PPCI_COMMON_CONFIG PciData
+ );
+
+BOOLEAN HalpTowerTestConf(
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+);
+
+//
+// Pragmas to assign functions to different kinds of pages.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePCIBus)
+#endif // ALLOC_PRAGMA
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+extern BOOLEAN HalPCIRegistryInitialized;
+ULONG PCIMaxBuses;
+ULONG PCIMaxLocalDevice;
+ULONG PCIMaxDevice;
+ULONG PCIMaxBusZeroDevice;
+PULONG HalpPciConfigAddr;
+PULONG HalpPciConfigData;
+UCHAR HalpIntAMax;
+UCHAR HalpIntBMax;
+UCHAR HalpIntCMax;
+UCHAR HalpIntDMax;
+
+//
+// Registry stuff
+//
+
+PCWSTR rgzMultiFunctionAdapter = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+PCWSTR rgzConfigurationData = L"Configuration Data";
+PCWSTR rgzIdentifier = L"Identifier";
+PCWSTR rgzPCIIdentifier = L"PCI";
+
+
+
+/*++
+
+Routine Description:
+
+ This function looks at the registry to find if the current machine
+ has a PCI bus or not.
+
+ The Arc firmware is responsible for building configuration information
+ about the number of PCI buses on the system and nature (local vs. secondary
+ - across a PCI-PCI bridge) of the each bus. This state is held in
+ PCIRegInfo.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PPCI_REGISTRY_INFO PCIRegInfo = NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR HalpDesc;
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+#if DBG
+ HalDisplayString("PCI Machine detected\n");
+#endif
+ HalpDesc = ((PCM_PARTIAL_RESOURCE_LIST)(CurrentEntry->ConfigurationData))->PartialDescriptors;
+ if (HalpDesc->Type == CmResourceTypeDeviceSpecific) {
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (HalpDesc+1);
+ PCIMaxBuses = PCIRegInfo->NoBuses;
+ HalPCIRegistryInitialized = TRUE;
+ }
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+/*++
+
+Routine Description:
+
+ The function intializes global PCI bus state from execpt those from the registry.
+
+ The maximum virtual slot number on the local (type 0 config cycle)
+ PCI bus is registered here, based on the machine dependent define
+ PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice.
+
+ The maximum number of virtual slots on a secondary bus is fixed by the
+ PCI Specification and is represented by PCI_MAX_DEVICES. This
+ state is held in PCIMaxDevice.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ )
+
+{
+ ULONG irqsel, iomemconf;
+
+ PCIMaxLocalDevice = PCI_MAX_DEVICES - 1;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+
+ if (HalpIsTowerPci) {
+ PCIMaxBusZeroDevice = PCI_MAX_DEVICES - 1;
+ } else {
+ PCIMaxBusZeroDevice = 7;
+ }
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+
+ //
+ // Specific sni init to distinguish between desktop/minitower and tower ASIC
+ //
+
+ if (HalpIsTowerPci) HalpPciConfigAddr = (PULONG) (PCI_TOWER_CONF_ADDR_REGISTER);
+ else HalpPciConfigAddr = (PULONG) (PCI_CONF_ADDR_REGISTER);
+ HalpPciConfigData = (PULONG)(PCI_IO_BASE | 0xcfc);
+
+ HalpIntAMax = INTA_VECTOR ;
+ HalpIntBMax = INTB_VECTOR ;
+ HalpIntCMax = INTC_VECTOR ;
+ HalpIntDMax = INTD_VECTOR ;
+
+ // enable PCI timeout interrupts
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout + enable ECC detector-corrector
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf | PCI_IOMEMCONF_ENCHKECC);
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ ((irqsel | PCI_IRQSEL_MASK ) & PCI_IRQSEL_INT));
+ } else {
+ // init ECC single counter to autorize 0xffff single ECC errors before system crash
+ WRITE_REGISTER_ULONG (PCI_TOWER_MEM_CONTROL_1, (READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_1) & ERROR_COUNTER_MASK) | ERROR_COUNTER_INITVALUE);
+ }
+
+}
+
+
+
+/*++
+
+Routine Description:
+
+ The function returns the PCI bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+
+ULONG
+HalpGetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+ ULONG j;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusNumber, PciSlot, PciData, 0, sizeof(ULONG));
+
+ //
+ // Check for non-existent bus
+ //
+
+ if (PciData->VendorID == 0x00) {
+ return 0; // Requested bus does not exist. Return no data.
+ }
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ if ((Offset == 0) && (Length >=2)) *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2;
+ }
+
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusNumber, PciSlot, PciData, 0, Len);
+
+ //
+ // Check for non-existent bus
+ //
+
+ if (PciData->VendorID == 0x00) {
+ return 0; // Requested bus does not exist. Return no data.
+ }
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ if ((Offset == 0) && (Length >=2)) *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2; // only return invalid id
+ }
+
+ //
+ // Update interrupt line
+ //
+
+ HalpIntLineUpdate(BusNumber, Slot, PciData);
+
+ //
+ // Pb concerning especially SCSI : skip IO address when = 3bf0000
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+
+ if ( (((ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0x3) | 0x01) == 0x3bf0001 )
+ PciData->u.type0.BaseAddresses[j] = 0;
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusNumber, PciSlot, Buffer, Offset, Length);
+ Len += Length;
+
+ }
+
+ }
+
+ return Len;
+}
+
+
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+ULONG
+HalpSetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusNumber, PciSlot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PciData->VendorID == 0x00) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusNumber, PciSlot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00 ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ //
+ // no device, or header type unkown
+ //
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ //HalpPCILineToPin (BusNumber, PciSlot, PciData2, PciData);
+
+
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusNumber, PciSlot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusNumber, PciSlot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ KIRQL OldIrql;
+ PCI_CONFIG_ADDR PciConfigAddrData;
+ PUCHAR BufferOrg;
+ ULONG LengthOrg;
+ ULONG PartialLength;
+ ULONG irqsel, iomemconf;
+ BOOLEAN result;
+ //
+ // Read the slot, if it's valid.
+ // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
+ // or a null (zero) buffer if we have a non-existant bus.
+ //
+
+ BufferOrg = Buffer;LengthOrg = Length;
+
+ switch (HalpValidPCISlot (BusNumber, Slot)) {
+
+ case ValidSlot:
+
+ //
+ // Acquire Spin Lock
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ // disable PCI timeout to avoid timeout interrupt when drivers attempt to access invalid slot
+
+ if (!HalpIsTowerPci) {
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & ~PCI_IRQSEL_TIMEOUTMASK));
+ }
+
+ //
+ // Program PciConfigAddr register
+ //
+
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciConfigAddrData.FunctionNumber = 0;
+// PciConfigAddrData.DeviceNumber = (BusNumber ? Slot.u.bits.DeviceNumber : 0);
+// PciConfigAddrData.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciConfigAddrData.Reserved = 0;
+ PciConfigAddrData.Enable = 1;
+
+ //
+ // Issue PCI Configuration Cycles
+ //
+
+ if (Offset % 4) {
+
+ PartialLength = (Length > (4 - (Offset % 4))) ? (4 - (Offset % 4)) : Length;
+
+ PciConfigAddrData.RegisterNumber = (Offset - (Offset % 4)) >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,MP_BUS_PCI_LOCK_REQ);
+
+ result = HalpPCIConfigPartialRead((4 - (Offset % 4)),PartialLength, Buffer);
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,0);
+
+ if (!result){
+
+ RtlFillMemory (BufferOrg, LengthOrg, (UCHAR) -1);
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ return;
+ }
+ Offset += PartialLength;
+ Length -= PartialLength;
+ Buffer += PartialLength;
+
+ }
+
+ while (Length >= 4) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,MP_BUS_PCI_LOCK_REQ);
+
+ * (PULONG) Buffer = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ if (HalpIsTowerPci && (PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,0);
+
+ if (* (PULONG) Buffer == 0XFFFFFFFF) {
+ RtlFillMemory (BufferOrg, LengthOrg, (UCHAR) -1);
+
+ if (!HalpIsTowerPci) {
+ // reenable timeout
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ return;
+ }
+
+ Offset += 4;
+ Buffer += 4;
+ Length -= 4;
+
+ }
+
+ if ( Length > 0) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,MP_BUS_PCI_LOCK_REQ);
+
+ result = HalpPCIConfigPartialRead(0,Length,Buffer);
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,0);
+
+ if (!result) {
+
+ RtlFillMemory (BufferOrg, LengthOrg, (UCHAR) -1);
+
+ if (!HalpIsTowerPci) {
+ // reenable timeout
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ return;
+ }
+
+ Offset += Length;
+ Length -= Length;
+ Buffer += Length;
+
+ }
+
+ //
+ // Release Spin Lock
+ //
+
+ // reenable timeout
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ break;
+
+ case InvalidSlot:
+
+ //
+ // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ break ;
+
+ case InvalidBus:
+
+ //
+ // Invalid Bus, return return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) 0);
+ break ;
+
+ }
+
+
+ return;
+
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpWritePCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ KIRQL OldIrql;
+ PCI_CONFIG_ADDR PciConfigAddrData;
+ ULONG PartialLength;
+ ULONG irqsel, iomemconf;
+
+ if (HalpValidPCISlot (BusNumber, Slot) != ValidSlot) {
+
+ //
+ // Invalid SlotID do nothing
+ //
+
+ return ;
+ }
+
+
+ //
+ // Acquire Spin Lock
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ // disable PCI timeout to avoid timeout interrupt when drivers attempt to access invalid slot
+
+ if (!HalpIsTowerPci) {
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & ~PCI_IRQSEL_TIMEOUTMASK));
+ }
+
+
+ //
+ // Program PciConfigAddr register
+ //
+
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciConfigAddrData.FunctionNumber = 0;
+// PciConfigAddrData.DeviceNumber = (BusNumber ? Slot.u.bits.DeviceNumber : 0);
+// PciConfigAddrData.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciConfigAddrData.Reserved = 0;
+ PciConfigAddrData.Enable = 1;
+
+ //
+ // Issue PCI Configuration Cycles
+ //
+
+ if (Offset % 4) {
+
+ PartialLength = (Length > (4 - (Offset % 4))) ? (4 - (Offset % 4)) : Length;
+
+ PciConfigAddrData.RegisterNumber = (Offset - (Offset % 4)) >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ HalpPCIConfigPartialWrite((4 - (Offset % 4)),PartialLength, Buffer);
+
+ Offset += PartialLength;
+ Length -= PartialLength;
+ Buffer += PartialLength;
+
+ }
+
+ while (Length >= 4) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG)Buffer));
+
+ Offset += 4;
+ Buffer += 4;
+ Length -= 4;
+
+ }
+
+ if ( Length > 0) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ HalpPCIConfigPartialWrite(0,Length,Buffer);
+
+ Offset += Length;
+ Length -= Length;
+ Buffer += Length;
+
+ }
+
+ //
+ // Release Spin Lock
+ //
+
+ // reenable timeout
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+
+
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ UCHAR HeaderType;
+ ULONG i;
+ PCI_CONFIGURATION_TYPES PciConfigType;
+
+
+ //
+ // Get the config cycle type for the proposed bus.
+ // (PciConfigTypeInvalid indicates a non-existent bus.)
+ //
+
+ PciConfigType = HalpPCIConfigCycleType(BusNumber, Slot);
+
+ //
+ // The number of devices allowed on a local PCI bus may be different
+ // than that across a PCI-PCI bridge.
+ //
+
+ switch(PciConfigType) {
+
+ case PciConfigType0:
+
+ if ((BusNumber == 0) && (Slot.u.bits.DeviceNumber > PCIMaxBusZeroDevice)) {
+
+ return InvalidSlot;
+ }
+ if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) {
+
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigType1:
+
+ if ((BusNumber == 0) && (Slot.u.bits.DeviceNumber > PCIMaxBusZeroDevice)) {
+
+ return InvalidSlot;
+ }
+ if (Slot.u.bits.DeviceNumber > PCIMaxDevice) {
+
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigTypeInvalid:
+
+ return InvalidBus;
+
+ break;
+
+ }
+
+ //
+ // Check function number
+ //
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ if (HalpTowerTestConf(BusNumber, Slot)) return ValidSlot;else return InvalidSlot;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ if ( ! HalpTowerTestConf(BusNumber, Slot2)) return InvalidSlot;
+
+ HalpReadPCIConfig (BusNumber,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof(UCHAR) );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) {
+
+ //
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ //
+
+ return InvalidSlot;
+
+ }
+
+ return ValidSlot;
+}
+
+
+/*++
+
+Routine Description:
+
+ Partial write in the PCI config space ( less than one ULONG)
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+VOID
+HalpPCIConfigPartialWrite(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ )
+{
+ switch(Offset) {
+
+ case 0:
+
+ if (Length > 1) {
+ WRITE_REGISTER_USHORT ((PULONG) HalpPciConfigData, *(PUSHORT)Buffer);
+ Buffer +=2;Offset +=2;
+ }
+ if (Length !=2) {
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + Offset), *Buffer);
+ ++Buffer;
+ }
+ break;
+
+ case 1:
+
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1), *Buffer);
+ ++Buffer;
+ if (Length == 2)
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *Buffer);
+ if (Length == 3)
+ WRITE_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *(PUSHORT)Buffer);
+
+ break;
+
+ case 2:
+
+ if (Length < 2) {
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *Buffer);
+ } else {
+ WRITE_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *(PUSHORT)Buffer);
+ }
+ break;
+
+ case 3:
+
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1), *Buffer);
+ break;
+ }
+
+}
+
+
+
+
+
+/*++
+
+Routine Description:
+
+ Partial read in the PCI config space ( less than one ULONG)
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+BOOLEAN
+HalpPCIConfigPartialRead(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ )
+{
+ switch(Offset) {
+
+ case 0:
+
+ if (Length > 1) {
+ * (PUSHORT) Buffer = READ_REGISTER_USHORT ((PULONG) HalpPciConfigData);
+ if (* (PUSHORT) Buffer == 0XFFFF) return FALSE;
+ Buffer +=2; Offset+=2;
+ }
+ if (Length !=2) {
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + Offset));
+ if (* Buffer == 0XFF) return FALSE;
+ }
+ break;
+
+ case 1:
+
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1));
+ if (* Buffer == 0XFF) return FALSE;
+ ++Buffer;
+ if (Length == 2) {
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* Buffer == 0XFF) return FALSE;
+ } else {
+ if (Length == 3) {
+ * (PUSHORT) Buffer = READ_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* (PUSHORT) Buffer == 0XFFFF) return FALSE;
+ }
+ }
+ break;
+
+ case 2:
+
+ if (Length < 2) {
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* Buffer == 0XFF) return FALSE;
+ } else {
+ * (PUSHORT) Buffer = READ_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* (PUSHORT) Buffer == 0XFFFF) return FALSE;
+ }
+ break;
+
+ case 3:
+
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1)); ++Buffer;
+ if (* Buffer == 0XFF) return FALSE;
+ break;
+ }
+
+ return TRUE ;
+}
+
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ )
+
+{
+
+ //
+ // Determine if Type0, Type1, or Invalid
+ //
+
+ if (BusNumber < 0 || BusNumber > (PCIMaxBuses - 1)) {
+ return PciConfigTypeInvalid;
+ } else if (BusNumber) {
+ return PciConfigType1;
+ } else {
+ return PciConfigType0;
+ }
+
+}
+
+/*++
+
+Routine Description:
+
+
+ Update interrupt line : the read value in the PCI config space is form 0 to 6.
+ Each device needs a unique system interrupt number. This number is given by
+ this routine. The array HalpInterruptLine keeps the given system value.
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpIntLineUpdate(
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ PPCI_COMMON_CONFIG PciData
+ )
+
+{
+
+ if (HalpInterruptLine[BusNumber][Slot] == 0) {
+
+ switch (PciData->u.type0.InterruptLine) {
+ case 1:
+ if (HalpIntAMax > INTA_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTA\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+
+ HalpInterruptLine[BusNumber][Slot] = HalpIntAMax;
+ ++ HalpIntAMax;
+ break;
+ case 2:
+ if (HalpIntBMax > INTB_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTB\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+ HalpInterruptLine[BusNumber][Slot] = HalpIntBMax;
+ ++ HalpIntBMax;
+ break;
+ case 3:
+ if (HalpIntCMax > INTC_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTC\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+ HalpInterruptLine[BusNumber][Slot] = HalpIntCMax;
+ ++ HalpIntCMax;
+ break;
+ case 4:
+ if (HalpIntDMax > INTD_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTD\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+ HalpInterruptLine[BusNumber][Slot] = HalpIntDMax;
+ ++ HalpIntDMax;
+ break;
+ case 5:
+ HalpInterruptLine[BusNumber][Slot] = SCSI_VECTOR;
+ break;
+ case 6:
+ HalpInterruptLine[BusNumber][Slot] = NET_LEVEL;
+ break;
+ }
+
+ }
+
+ PciData->u.type0.InterruptLine = HalpInterruptLine[BusNumber][Slot];
+
+}
+
+BOOLEAN HalpTowerTestConf(
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+)
+
+/*++
+
+Routine Description
+
+ Only for tower.
+ An access to an empty slot will do an exception if we don't care.
+
+Arguments
+
+ None
+
+Return value
+
+ True : slot ok
+ False : slot not ok
+
+++*/
+
+{
+ULONG PciData,Buffer,SaveReg;
+PCI_CONFIG_ADDR PciConfigAddrData;
+
+ if (!HalpIsTowerPci) return TRUE;
+
+
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ // Save PCI interrupt register
+ SaveReg = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // reset MAUI PCI error, set flag for exception routine
+ PciData = PI_RESET ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // write to vendor-id (ro) to see if exception appears.
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciConfigAddrData.FunctionNumber = 0;
+ PciConfigAddrData.Reserved = 0;
+ PciConfigAddrData.Enable = 1;
+ PciConfigAddrData.RegisterNumber = 0; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ PciData = 0xffffffff;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // read MAUI PCI error
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+ Buffer = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ if ( Buffer & PI_CPU_PCI_TIMO) {
+ // reset MAUI PCI error, set flag for exception routine
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = PI_RESET ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // restore PCI interrupt
+ PciData = SaveReg;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ return FALSE;
+ } else {
+ // restore PCI interrupt
+ PciData = SaveReg;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+ return TRUE;
+ }
+}
+
+
+
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN ULONG BusNumber,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+
+{
+
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData;
+ PCI_SLOT_NUMBER PciSlot;
+ PCM_RESOURCE_LIST CmRes;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG i, j, length, memtype, BaseAd, BaseAd2, Offset;
+ ULONG BaseAddresses[10];
+ ULONG cnt, len;
+ BOOLEAN conflict;
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH * 2;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+
+ if (!WorkingPool) {
+
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CmRes = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH );
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusNumber, PciSlot, (PUCHAR) PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PciData->VendorID == 0x00) {
+
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+
+ }
+
+ //
+ // Update interrupt line
+ //
+
+ HalpIntLineUpdate(BusNumber, Slot, PciData);
+
+ //
+ // Build an CM_RESOURCE_LIST for the PCI device to report resources
+ // to IoReportResourceUsage.
+ //
+ // This code does *not* use IoAssignResources, as the PCI
+ // address space resources have been previously assigned by the ARC firmware
+ //
+
+ CmRes->Count = 1;
+ CmRes->List[0].InterfaceType = PCIBus;
+ CmRes->List[0].BusNumber = BusNumber;
+
+ CmRes->List[0].PartialResourceList.Count = 0;
+
+ //
+ // Set current CM_RESOURCE_LIST version and revision
+ //
+
+ CmRes->List[0].PartialResourceList.Version = 0;
+ CmRes->List[0].PartialResourceList.Revision = 0;
+
+ CmDescriptor = CmRes->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ CmDescriptor->Type = CmResourceTypeInterrupt;
+ CmDescriptor->ShareDisposition = CmResourceShareShared;
+ CmDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ CmDescriptor->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ CmDescriptor->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDescriptor++;
+
+ }
+
+ //
+ // Add a memory/port resource for each PCI resource
+ //
+
+ Offset = FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++,Offset += sizeof(LONG)) {
+
+//
+// Pb concerning especially SCSI : skip IO address when = 3bf0000
+//
+
+ if ( (((ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0x3) | 0x01) != 0x3bf0001 ) {
+
+ BaseAddresses[j] = 0xFFFFFFFF;
+
+ HalpWritePCIConfig (BusNumber, PciSlot,(PUCHAR)(&(BaseAddresses[j])), Offset, sizeof(LONG));
+ HalpReadPCIConfig (BusNumber, PciSlot, (PUCHAR)(&(BaseAddresses[j])), Offset, sizeof(LONG));
+
+
+ BaseAd = BaseAddresses[j];
+
+ if (BaseAd) {
+
+ //
+ // calculate the length necessary -
+ // memory : the four less significant bits are only indicators
+ // IO : the two less significant bits are indicators
+ //
+
+ length = 1 << ( BaseAd & PCI_ADDRESS_IO_SPACE ? 2 : 4); // mask the indicator bits
+
+ while ( !( BaseAd & length ) && length ) {
+ length <<= 1;
+ }
+
+ // now length => less significant bit set to 1.
+
+ // scan for the most significant bit set to 1
+
+ if (BaseAd & PCI_ADDRESS_IO_SPACE) {
+
+ memtype = 0;
+ BaseAd2 = (ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0x3;
+// BaseAd2 |= PCI_IO_BASE;
+
+ CmDescriptor->Type = CmResourceTypePort;
+ CmDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDescriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ CmDescriptor->u.Port.Length = length;
+ CmDescriptor->u.Port.Start.LowPart = BaseAd2;
+
+ } else {
+
+ memtype = BaseAd & PCI_ADDRESS_MEMORY_TYPE_MASK;
+ BaseAd2 = (ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0xf;
+
+ CmDescriptor->Type = CmResourceTypeMemory;
+ CmDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+
+ CmDescriptor->u.Memory.Length = length;
+ CmDescriptor->u.Memory.Start.LowPart = BaseAd2;
+ }
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDescriptor++;
+
+ HalpWritePCIConfig (BusNumber, PciSlot, (PUCHAR)(&(PciData->u.type0.BaseAddresses[j])), Offset, sizeof(ULONG));
+
+ }
+ } else {
+
+ DebugPrint(("HalAssignResources : skip 0x3bf0001\n"));
+ }
+ }
+
+
+ //
+ // Setup the resource list.
+ // Count only the acquired resources.
+ //
+
+ *pAllocatedResources = CmRes;
+ cnt = CmRes->List[0].PartialResourceList.Count;
+ len = sizeof (CM_RESOURCE_LIST) +
+ cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)",
+ cnt, len, *pAllocatedResources);
+#endif
+
+ //
+ // Report the IO resource assignments
+ //
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ *pAllocatedResources, // DriverList
+ len, // DriverListSize
+ DeviceObject, // DeviceObject
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ *pAllocatedResources, // DeviceList
+ len, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ if (NT_SUCCESS(status) && conflict) {
+
+ //
+ // IopReportResourceUsage saw a conflict?
+ //
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n",
+ status);
+#endif
+ status = STATUS_CONFLICTING_ADDRESSES;
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status);
+#endif
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+// ExFreePool (WorkingPool);
+
+ return status;
+
+}
+
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+
+--*/
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER PciSlot;
+ PPCI_COMMON_CONFIG PciData;
+ LARGE_INTEGER liIo, liMem;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+ return STATUS_SUCCESS;
+
+ liIo = RtlConvertUlongToLargeInteger (PCI_MAX_IO_ADDRESS);
+ liMem = RtlConvertUlongToLargeInteger (PCI_MAX_MEMORY_ADDRESS);
+
+ //
+ // First, shrink to limits
+ //
+
+ HalpAdjustResourceListUpperLimits (pResourceList,
+ liIo, // IO Maximum Address
+ liMem, // Memory Maximum Address
+ PCI_MAX_INTERRUPT_VECTOR, // irq
+ 0xffff); // dma
+
+ //
+ // Fix any requested IRQs for this device to be the
+ // support value for this device.
+ //
+
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber),
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData ( PCIConfiguration,
+ BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PCI_CONFIG_TYPE (PciData) != 0) {
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ switch (Descriptor->Type) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Interrupt lines on a PCI device can not move.
+ // Make sure the request fits within the PCI device's
+ // requirements.
+ //
+
+ if (Descriptor->u.Interrupt.MinimumVector > PciData->u.type0.InterruptLine ||
+ Descriptor->u.Interrupt.MaximumVector < PciData->u.type0.InterruptLine) {
+
+ //
+ // descriptor doesn't fit requirements
+ //
+
+ return STATUS_UNSUCCESSFUL;
+
+ }
+
+ //
+ // Fix the interrupt at the HAL programed routing
+ //
+
+ Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine;
+ break;
+
+ case CmResourceTypePort:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Check for prefetchable memory
+ //
+
+ if ( Descriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE)
+ {
+ // Set upper limit to max dense space address
+
+ Descriptor->u.Memory.MinimumAddress.HighPart = 0;
+ Descriptor->u.Memory.MinimumAddress.LowPart =
+ PCI_MIN_DENSE_MEMORY_ADDRESS;
+
+ Descriptor->u.Memory.MaximumAddress.HighPart = 0;
+ Descriptor->u.Memory.MaximumAddress.LowPart =
+ PCI_MAX_DENSE_MEMORY_ADDRESS;
+ }
+
+ break;
+
+ default:
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Next descriptor
+ //
+
+ Descriptor++;
+
+ }
+
+ //
+ // Next Resource List
+ //
+
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+
+--*/
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ )
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+
+ //
+ // Walk each ResourceList and shrink any values to system limits
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+
+ //
+ // Make sure descriptor limits fall within the
+ // CompleteList->InterfaceType & CompleteList->BusNumber.
+ //
+ //
+
+ switch (Descriptor->Type) {
+
+ case CmResourceTypePort:
+
+ if (Descriptor->u.Port.MaximumAddress.QuadPart >
+ MaximumPortAddress.QuadPart) {
+
+ Descriptor->u.Port.MaximumAddress = MaximumPortAddress;
+ }
+ break;
+
+ case CmResourceTypeInterrupt:
+
+ if (Descriptor->u.Interrupt.MaximumVector > MaximumInterruptVector ) {
+
+ Descriptor->u.Interrupt.MaximumVector = MaximumInterruptVector;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+
+ if (Descriptor->u.Memory.MaximumAddress.QuadPart >
+ MaximumMemoryAddress.QuadPart) {
+
+ Descriptor->u.Memory.MaximumAddress = MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (Descriptor->u.Dma.MaximumChannel > MaximumDmaChannel ) {
+
+ Descriptor->u.Dma.MaximumChannel = MaximumDmaChannel;
+ }
+ break;
+
+ }
+
+ //
+ // Next descriptor
+ //
+
+ Descriptor++;
+
+ }
+
+ //
+ // Next Resource List
+ //
+
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+
+ }
+
+}
+
+
diff --git a/private/ntos/nthals/halsnip/mips/snipbus.h b/private/ntos/nthals/halsnip/mips/snipbus.h
new file mode 100644
index 000000000..f1ba64346
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snipbus.h
@@ -0,0 +1,104 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snipbus.h,v 1.2 1995/11/02 11:04:33 flo Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ PCIdef.h
+
+Abstract:
+
+ Hal specific PCI bus structures */
+
+
+#define PCI_MAX_LOCAL_DEVICE 32
+#define PCI_MAX_BUS_NUMBER 250
+#define PCI_MAX_IO_ADDRESS 0x1FFFFFFF
+#define PCI_MAX_MEMORY_ADDRESS 0x1FFFFFFF
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS PCI_MAX_MEMORY_ADDRESS
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MEMORY_PHYSICAL_BASE
+#define PCI_MAX_DENSE_MEMORY_ADDRESS PCI_MAX_MEMORY_ADDRESS
+#define PCI_MAX_INTERRUPT_VECTOR 0x100
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+//
+// Define PciConfigAddr register structure
+//
+typedef struct _PCI_CONFIG_ADDR {
+ ULONG Type : 2;
+ ULONG RegisterNumber : 6;
+ ULONG FunctionNumber : 3;
+ ULONG DeviceNumber : 5;
+ ULONG BusNumber : 8;
+ ULONG Reserved : 7;
+ ULONG Enable : 1;
+} PCI_CONFIG_ADDR, *PPCI_CONFIG_ADDR;
+
+//
+// Define PCI configuration cycle types.
+//
+typedef enum _PCI_CONFIGURATION_TYPES {
+ PciConfigTypeInvalid = -1,
+ PciConfigType0 = 0,
+ PciConfigType1 = 1
+} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES;
+
+//
+// Define PCI cycle/command types.
+//
+
+typedef enum _PCI_COMMAND_TYPES{
+ PciCommandInterruptAcknowledge = 0x0,
+ PciCommandSpecialCycle = 0x1,
+ PciCommandIoRead = 0x2,
+ PciCommandIoWrite = 0x3,
+ PciCommandMemoryRead = 0x6,
+ PciCommandMemoryWrite = 0x7,
+ PciCommandConfigurationRead = 0xa,
+ PciCommandConfigurationWrite = 0xb,
+ PciCommandMemoryReadMultiple = 0xc,
+ PciCommandDualAddressCycle = 0xd,
+ PciCommandMemoryReadLine = 0xe,
+ PciCommandMemoryWriteAndInvalidate = 0xf,
+ MaximumPciCommand
+} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES;
+
+
+//
+// PCI platform-specific functions
+//
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
diff --git a/private/ntos/nthals/halsnip/mips/snipci.h b/private/ntos/nthals/halsnip/mips/snipci.h
new file mode 100644
index 000000000..0a4651ebe
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snipci.h
@@ -0,0 +1,366 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snipci.h,v 1.6 1996/02/23 17:55:12 pierre Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ PCIdef.h
+
+Abstract:
+
+ This file describes hardware addresses
+ for SNI PCI machines.
+
+
+
+---*/
+
+#ifndef _PCIDEF_
+#define _PCIDEF_
+
+
+// ---------------------
+// desktop and minitower -
+// ---------------------
+
+
+//
+// define various masks for the interrupt sources register
+//
+
+/*
+ The interrupt Source Register on a PCI minitower or desktop has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 Low Activ; 1 High activ; x not connected
+ +-------------------------------+
+ |________ INT2 Interrupt (Push button, high temp, pci asic)
+ |____________ PCI_INTD
+ |________________ PCI_INTC
+ |____________________ PCI_INTB
+ |________________________ PCI_INTA
+ |____________________________ EISA_INT
+ |________________________________ SCSI_INT
+ |____________________________________ ETHERNET_INT
+
+
+ The second source for Interrupt Information is the MachineStatusRegister, which has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | x | 0 | 0 | 1 | x | 0 | 0 | 0 | 0 Low Activ; 1 High activ; x not connected
+ +-------------------------------+
+ |________ Power Off Request (only RM200)
+ |____________ ASIC int
+ |________________ PushButton
+ |________________________ NMI
+ |____________________________ Power Management ie system wakeup (only rm200)
+ |________________________________ High Temperature
+*/
+
+#define PCI_INTERRUPT_MASK 0xdf
+#define PCI_INT2_MASK 0x01 // push-button, high temp, asic...
+#define PCI_INTD_MASK 0x02
+#define PCI_INTC_MASK 0x04
+#define PCI_INTB_MASK 0x08
+#define PCI_INTA_MASK 0x10
+#define PCI_EISA_MASK 0x20
+#define PCI_SCSI_MASK 0x40
+#define PCI_NET_MASK 0x80
+
+#define PCI_MSR_MASK_D 0x67
+#define PCI_MSR_MASK_MT 0x46
+#define PCI_MSR_POFF_MASK 0x01
+#define PCI_MSR_ASIC_MASK 0x02
+#define PCI_MSR_PB_MASK 0x04
+#define PCI_MSR_NMI 0x10 // NMI from the EISA controller
+#define PCI_MSR_TEMP_MASK 0x40 // OverTemperature Interrupt in the MSR (RM400MT only) (high active)
+#define PCI_MSR_PMGNT_MASK 0x20 // power management (system wake-up)
+
+#define PCI_NVMEM_PHYSICAL_BASE 0x1ff00000 // physical base of nonvolatile RAM and RTC
+
+//
+// SNI ASIC registers
+//
+
+#define PCI_UCONF_REGISTER 0xbfff0000
+#define PCI_IOADTIMEOUT2_REGISTER 0xbfff0008
+#define PCI_IOMEMCONF_REGISTER 0xbfff0010
+#define PCI_IOMMU_REGISTER 0xbfff0018
+#define PCI_IOADTIMEOUT1_REGISTER 0xbfff0020
+#define PCI_DMAACCESS_REGISTER 0xbfff0028
+#define PCI_DMAHIT_REGISTER 0xbfff0030
+#define PCI_ERRSTATUS_REGISTER 0xbfff0038
+#define PCI_MEMSTAT_ECCERR (1<<0)
+#define PCI_MEMSTAT_ECCSINGLE (1<<3)
+#define PCI_MEMSTAT_PARERR (1<<4)
+#define PCI_ERRADDR_REGISTER 0xbfff0040
+#define PCI_SYNDROME_REGISTER 0xbfff0048
+#define PCI_ITPEND_REGISTER 0xbfff0050
+#define PCI_ASIC_ECCERROR (1<<8)
+#define PCI_ASIC_TRPERROR (1<<9)
+#define PCI_ASIC_IOTIMEOUT (1<<7)
+#define PCI_IRQSEL_REGISTER 0xbfff0058
+#define PCI_TESTMEM_REGISTER 0xbfff0060
+#define PCI_ECCREG_REGISTER 0xbfff0068
+#define PCI_CONF_ADDR_REGISTER 0xbfff0070 // (EISA_IO + 0xcf8)
+#define PCI_ASIC_ID_REGISTER 0xbfff0078 // Read
+#define PCI_SOFT_RESET_REGISTER 0xbfff0078 //Write
+#define PCI_PIA_OE_REGISTER 0xbfff0080
+#define PCI_PIA_DATAOUT_REGISTER 0xbfff0088
+#define PCI_PIA_DATAIN_REGISTER 0xbfff0090
+#define PCI_CACHECONF_REGISTER 0xbfff0098
+#define PCI_INVSPACE_REGISTER 0xbfff00A0
+#define PCI_PCICONF_REGISTER 0xbfff0100
+
+//
+// System dependant registers
+//
+
+#define PCI_MSR_PHYSICAL_ADDR 0x1fd00000 // machine status register
+#define PCI_MSR_ADDR 0xbfd00000 // machine status register | KSEG1
+#define PCI_CSWITCH_PHYSICAL_ADDR 0x1fd10000 // DIP switch register
+#define PCI_CSWITCH_ADDR 0xbfd10000 // DIP switch register | KSEG1
+#define PCI_INTERRUPT_SOURCE_PHYSICAL_BASE 0x1fd20000 // physical base of interrupt source register
+#define PCI_INTERRUPT_SOURCE_REGISTER 0xbfd20000 // physical base | KSEG1_BASE
+#define PCI_CLR_TMP_PHYSICAL_ADDR 0x1fd40000 // Clear Temperature Register
+#define PCI_CLR_TMP_ADDR 0xbfd40000 // Clear Temperature Register | KSEG1
+#define PCI_MCR_PHYSICAL_ADDR 0x1fd80000 // MachineConfigRegister
+#define PCI_MCR_ADDR 0xbfd80000 // MachineConfigRegister | KSEG1
+#define PCI_LED_PHYSICAL_ADDR 0x1fda0000 // LED Register physical
+#define PCI_LED_ADDR 0xbfda0000 // LED Register | KSEG1_BASE
+#define PCI_ISA_MAP_PHYSICAL_BASE 0x1fdb0000 // physical base of ISA map register (for BusMaster Devices)
+#define PCI_ISA_MAP 0xbfdb0000 // physical base | KSEG1_BASE
+#define PCI_CSRSTBP_PHYSICAL_ADDR 0x1fdc0000 // reset dbg button int
+#define PCI_CSRSTBP_ADDR 0xbfdc0000 // reset dbg button int
+#define PCI_CLRPOFF_PHYSICAL_ADDR 0x1fdd0000 // RM200 only
+#define PCI_CLRPOFF_ADDR 0xbfdd0000 // RM200 only
+#define PCI_PWDN_PHYSICAL_ADDR 0x1fdf0000 // RM200 only
+#define PCI_PWDN_ADDR 0xbfdf0000 // RM200 only
+#define PCI_MCR_SOFTRESET 0xdf // bit 6 set to zero
+#define PCI_MCR_POWEROFF 0xfd // bit 2 set to zero
+
+//
+// RealTimeClock Chip
+//
+
+#define PCI_REAL_TIME_CLOCK_ADDRESS 0x14000070 // physical base of RTC
+#define PCI_REAL_TIME_CLOCK 0xb4000070 // physical base of RTC | KSEG1_BASE
+
+#define RTC_ADDR_PCIMT PCI_REAL_TIME_CLOCK
+#define RTC_DATA_PCIMT PCI_REAL_TIME_CLOCK + 1
+
+//
+// Standard PCI addresses
+//
+
+#define PCI_IO_PHYSICAL_BASE 0x14000000
+#define PCI_IO_BASE 0xb4000000
+#define PCI_MEMORY_PHYSICAL_BASE 0x18000000 // memory area (cpu 0x18... chip 0x18...)
+#define PCI_MEMORY_BELOW1M_PHYSICAL_BASE 0x10000000 // for memory below 1Mb (cpu 0x10... chip 0x00...)
+#define PCI_MEMORY_BASE 0xb8000000
+
+#define PCI_CONF_DATA_REGISTER (PCI_IO_BASE + 0xcfc)
+
+#define PCI_IOMEMCONF_ENIOTMOUT (1 <<21 )
+#define PCI_IOMEMCONF_FORCE_ECC (1 <<29 )
+#define PCI_IOMEMCONF_ENCHKECC (1 <<30 )
+
+#define PCI_ECCTEST_REGISTER (1 <<30 )
+
+// def for PCI_MSR_REGISTER
+
+#define PCI_MSR_REV_ASIC (1 <<3 )
+
+// def for PCI_IRQSEL_REGISTER
+
+#define PCI_IRQSEL_MASK 0x380 // enable IOTIMEOUT ECCERROR TRPERROR
+#define PCI_IRQSEL_TIMEOUTMASK 0x80 // enable IOTIMEOUT
+#define PCI_IRQSEL_INT 0x803ff // Int line = 0 for IOTIMOUT, ECCERROR and TRPERROR
+
+//
+// RM300 extra timer (on board)
+//
+
+#define PCI_EXTRA_TIMER_PHYSICAL_ADDR 0x1fde0000 // Timer for system clock
+#define PCI_EXTRA_TIMER_ADDR 0xbfde0000 // Timer for system clock | KSEG1_BASE
+#define PCI_EXTRA_TIMER_ACK_ADDR 0xbfd90000 // reset extra Timer Interrupt | KSEG1_BASE
+
+//
+// Definitions for 82374 Bridge PCI_EISA
+//
+
+#define PCI_ESC_ADDR 0xb4000022
+#define PCI_ESC_DATA 0xb4000023
+#define PCI_ESC_ID_82374 0x2
+#define PCI_REV_ID_82374 0x8
+
+#define REV_ID_82374_SB 0x3
+
+
+// -------------------------
+// definitions for PCI Tower -
+// -------------------------
+
+
+
+#define PCI_TOWER_CONF_ADDR_REGISTER (PCI_IO_BASE + 0xcf8)
+#define PCI_TOWER_LED_ADDR PCI_TOWER_CPU_STATUS
+#define PCI_TOWER_LED_MASK 0xFFFCFFFC
+
+//
+// MAUI MP_BUS Configuration/Status
+//
+
+#define PCI_TOWER_MP_BUS_CONFIG 0xbfff0000
+
+#define PCI_TOWER_GEN_INTERRUPT 0xbfff0008
+#define PCI_TOWER_INTERRUPT_SOURCE_REGISTER PCI_TOWER_GEN_INTERRUPT
+
+// define various mask for interrupt
+
+
+#define PCI_TOWER_EISA_MASK 0x00400000
+#define PCI_TOWER_SCSI1_MASK 0x00100000
+#define PCI_TOWER_SCSI2_MASK 0x00200000
+#define PCI_TOWER_INTA_MASK 0x00010000
+#define PCI_TOWER_INTB_MASK 0x00020000
+#define PCI_TOWER_INTC_MASK 0x00040000
+#define PCI_TOWER_INTD_MASK 0x00080000
+#define PCI_TOWER_MP_BUS_MASK 0x00000003
+#define PCI_TOWER_C_PARITY_MASK 0x00000001
+#define PCI_TOWER_C_REGSIZE 0x00000002
+#define PCI_TOWER_M_ECC_MASK 0x00000004
+#define PCI_TOWER_M_ADDR_MASK 0x00000008
+#define PCI_TOWER_M_SLT_MASK 0x00000010
+#define PCI_TOWER_M_CFG_MASK 0x00000020
+#define PCI_TOWER_M_RC_MASK 0x00000040
+#define PCI_TOWER_D_INDICATE_MASK 0x00000080
+#define PCI_TOWER_D_ERROR_MASK 0x00000100
+#define PCI_TOWER_P_ERROR_MASK 0x00000200
+
+#define PCI_TOWER_MP_BUS_ERROR_STATUS 0xbfff0010
+#define PCI_TOWER_MP_BUS_ERROR_ADDR 0xbfff0018
+#define PCI_TOWER_MP_BUS_PCI_LOCK 0xbfff0020
+#define MP_BUS_PCI_LOCK_REQ 0x2
+#define MP_BUS_PCI_LOCK_ACK 0x1
+
+//
+// MAUI Memory Configuration registers
+//
+
+#define PCI_TOWER_MEM_SLOT_0 0xbfff1000
+#define PCI_TOWER_MEM_SLOT_1 0xbfff1008
+#define PCI_TOWER_MEM_SLOT_2 0xbfff1010
+#define PCI_TOWER_MEM_SLOT_3 0xbfff1018
+#define PCI_TOWER_MEM_SLOT_4 0xbfff1020
+#define PCI_TOWER_MEM_SLOT_5 0xbfff1028
+#define PCI_TOWER_MEM_SLOT_6 0xbfff1030
+#define PCI_TOWER_MEM_SLOT_7 0xbfff1038
+
+#define PCI_TOWER_MEM_CONTROL_0 0xbfff1040
+
+#define ERROR_COUNTER_MASK 0xff000000
+#define ERROR_COUNTER_INITVALUE 0xff0000 // to get overflow with ffff errors
+#define PCI_TOWER_MEM_CONTROL_1 0xbfff1048
+#define PCI_TOWER_MEM_CONTROL_2 0xbfff1050
+
+#define PCI_TOWER_MEM_CONFIG 0xbfff1058
+#define PCI_TOWER_MEM_ERROR_DATA_H 0xbfff1060
+#define PCI_TOWER_MEM_ERROR_DATA_L 0xbfff1068
+#define PCI_TOWER_MEM_ERROR_ECC 0xbfff1070
+#define PCI_TOWER_MEM_ERROR_ADDR 0xbfff1078
+#define MEM_ADDR_MASK 0xffffffe0
+
+// PCI configuration register
+#define PCI_TOWER_COMMAND_OFFSET 0x04
+#define PCI_TOWER_PM_LOCKSPACE 0x64
+#define PCI_TOWER_INTERRUPT_OFFSET 0x68
+#define PCI_TOWER_INITIATOR_ADDR_OFFSET 0x6c
+#define PCI_TOWER_TARGET_ADDR_OFFSET 0x70
+#define PCI_TOWER_PAR_0_OFFSET 0x74
+#define PCI_TOWER_PAR_1_OFFSET 0x78
+
+// definitions for command register
+
+#define EN_SERR 0x100
+
+// definitions for PCI_interrupt register
+
+#define PI_RESET 0xff000000 // reset interrupt in PCI_Interrupt
+
+#define PI_INITF 0x80000000 // mask for first Initiator interrupt in PCI_Interrupt
+#define PI_INITM 0x40000000 // mask for multi Initiator interrupt in PCI_Interrupt
+#define PI_TARGF 0x20000000 // mask for first Target interrupt in PCI_Interrupt
+#define PI_TARGM 0x10000000 // mask for multi Target interrupt in PCI_Interrupt
+#define PI_PARF 0x08000000 // mask for first Parity interrupt in PCI_Interrupt
+#define PI_PARM 0x04000000 // mask for multi Parity interrupt in PCI_Interrupt
+
+
+// Cause for initiator interrupts
+#define PI_READ_PCI 0x00200000 // from PCI
+#define PI_CPU_PCI_TIMO 0x00100000 // CPU to PCI timeout
+#define PI_CPU_PCI_ADDR 0x00080000 // address error
+#define PI_CPU_PCI_PAR 0x00020000 // initiator receives target abort
+#define PI_REC_TARGET_RETRY 0x00010000 // initiator receives target retry
+#define PI_REC_TARGET_DISCON 0x00008000 // initiator receives target disconnect
+// Cause for target interrupts
+#define PI_TARGET_MEM 0x00000080 // read error from memory
+#define PI_TARGET_RETRY 0x00000040 // target acts retry
+#define PI_TARGET_ADDR_PAR 0X00000020 // PCI_to_MEM addr parity
+#define PI_TARGET_DATA_PAR 0x00000010 // PCI_to_MEM data patity
+// enable interrupts
+#define EN_INIT_INT 0x00800000 // enable initiator interrupt
+#define EN_INIT_INTR 0x00400000 // enable initiator receives target disconnect
+#define EN_TARG_INTR 0x00000001 // enable target interrupt
+#define MASK_INT 0x00c00001
+//
+// DCU interface registers
+//
+
+#define PCI_TOWER_CONTROL 0xbfff2000
+
+#define PCI_TOWER_INDICATE 0xbfff2008
+
+// sources for DCU interrupt
+
+#define PCI_TOWER_DI_PB_MASK 0x00000100
+#define PCI_TOWER_DI_EISA_NMI 0x00000080
+#define PCI_TOWER_DI_AC_FAIL 0x00000004
+#define PCI_TOWER_DI_FAN_FAIL 0x00000008
+#define PCI_TOWER_DI_THERMO1_FAIL 0x00000010
+#define PCI_TOWER_DI_THERMO2_FAIL 0x00000020
+#define PCI_TOWER_DI_THERMO3_FAIL 0x00000040
+#define PCI_TOWER_DI_NT_FAN_FAIL 0x00000200
+#define PCI_TOWER_DI_SCSI1_TERM_FAIL 0x00000400
+#define PCI_TOWER_DI_SCSI2_INT_TERM_FAIL 0x00000800
+#define PCI_TOWER_DI_SCSI2_EXT_TERM_FAIL 0x00001000
+#define PCI_TOWER_DI_AUI_FAIL 0x00002000
+#define PCI_TOWER_DI_EXTRA_TIMER 0x00040000
+
+#define PCI_TOWER_DCU_CONTROL 0xbfff2000
+#define PCI_TOWER_DCU_STATUS 0xbfff2010
+#define PCI_TOWER_CPU_STATUS 0xbfff2018
+#define PCI_TOWER_DCU_ERROR 0xbfff2020
+
+// definitions for DCU error
+
+#define DE_CPU_ID 0x00006000
+#define DE_WRN 0x00001000
+#define DE_ADDR 0x00000fe0
+#define DE_ERR_ADDR 0x1fff2000
+
+// definitions for additional timer
+
+#define PCI_TOWER_TIMER_CMD_REG 0xbff03ffb
+#define PCI_TOWER_TIMER_COUNT_REG 0xbff03ffc
+#define PCI_TOWER_TIMER_VALUE_REG 0xbff03ffd
+
+// definitions for DCU Control
+
+#define DC_SWRESET 0x04000000
+#define DC_POWEROFF 0x02000000
+
+#endif // _PCIDEF_
diff --git a/private/ntos/nthals/halsnip/mips/sniregs.h b/private/ntos/nthals/halsnip/mips/sniregs.h
new file mode 100644
index 000000000..6f50d42f0
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/sniregs.h
@@ -0,0 +1,139 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/sniregs.h,v 1.1 1995/07/20 16:03:21 flo Exp $")
+/*++
+
+Copyright (c) 1993 SNI
+
+Module Name:
+
+ SNIregs.h
+
+Abstract:
+
+ This module is the header file that describes hardware structures
+ for the system board registers
+ The System addresses are found in SNIdef.h
+
+--*/
+
+#ifndef _SNIREGS_
+#define _SNIREGS_
+
+
+/*******************************************************************
+** Description of the R4x000 ASIC Chipset registers for SNI Machines
+**
+** 32 bits access only
+*******************************************************************/
+
+//
+// UCONF register
+//
+
+#define UCONF_ENSCMODE (1<<0) /* Secondary mode valid for R4000 */
+#define UCONF_ENEXTINT (1<<1) /* External interruption request */
+#define UCONF_NMI (1<<5) /* Interrupt level for NMI */
+#define UCONF_NMI_MSK (1<<6) /* Interrupt mask for NMI */
+#define UCONF_MDINT (1<<7) /* Select test mode for interruptions */
+#define UCONF_INT0_MSK (1<<8) /* Interrupt mask for INT0 ( eisa ) */
+#define UCONF_INT1_MSK (1<<9) /* Interrupt mask for INT1 ( scci 1, 2 ) */
+#define UCONF_INT2_MSK (1<<10) /* Interrupt mask for INT2 ( duart 2681 ) */
+#define UCONF_INT3_MSK (1<<11) /* Interrupt mask for INT3 ( timer 8254 ) */
+#define UCONF_INT4_MSK (1<<12) /* Interrupt mask for INT4 ( lance ) */
+#define UCONF_INT5_MSK (1<<13) /* Interrupt mask for INT5 ( dbg button ) */
+#define UCONF_INT0 (1<<14) /* Interrupt level for INT0 ( eisa ) */
+#define UCONF_INT1 (1<<15) /* Interrupt level for INT1 ( scci 1, 2 ) */
+#define UCONF_INT2 (1<<16) /* Interrupt level for INT2 ( duart 2681 ) */
+#define UCONF_INT3 (1<<17) /* Interrupt level for INT3 ( timer 8254 ) */
+#define UCONF_INT4 (1<<18) /* Interrupt level for INT4 ( lance ) */
+#define UCONF_INT5 (1<<19) /* Interrupt level for INT5 ( dbg button ) */
+#define UCONF_ENCPUHIT (1<<20) /* Enable address comparators */
+#define UCONF_ENCKDATA (1<<25) /* Enable check bits on data read */
+#define UCONF_SYSCMD0 (1<<26)
+#define UCONF_SYSCMD1 (1<<27)
+#define UCONF_SYSCMD2 (1<<28)
+#define UCONF_SYSCMD3 (1<<29)
+
+#define UCONF_INT UCONF_INT4|UCONF_INT0
+
+//
+// IOADTIMEOUT2 & IOADTIMEOUT1
+//
+
+#define IO_HOLD (1<<0) /* The R4K_CS request the IO bus */
+#define IO_HLDA (1<<1) /* The IO arbitrer acknowledge */
+#define IO_HWR (1<<3) /* Set to 1 for a write IO cycle */
+#define IO_HADR_MASK 0x3FFFFFF8 /* IO address (29:3) in progress */
+
+//
+// IOMEMCONF
+//
+
+
+#define IOMEM_RAFPER 8 /* Select Refresh Period */
+#define IOMEM_SELRC (1<<4) /* Select fast Ttc time on memory */
+#define IOMEM_SELRAF (1<<5) /* Select fast refresh precharge */
+#define IOMEM_SELSIDE (1<<6) /* Select dual side SIPS */
+#define IOMEM_SELDD (1<<7) /* Select DD pattern for memory */
+#define IOMEM_SEL16MB (1<<8) /* Select 16 Mb technology SIPS */
+#define IOMEM_SELDHOLD (1<<9) /* Select long hold time on data write */
+#define IOMEM_DISHLDA (1<<15) /* Mask arbitrer acknowledge */
+#define IOMEM_ENRDCMP (1<<16) /* Enable anticipation on IO read */
+#define IOMEM_ENWRCMP (1<<20) /* Enable bufferisation on IO write */
+#define IOMEM_ENIOTMOUT (1<<21) /* Enable output timeout */
+#define IOMEM_SELIODD (1<<22) /* Enable fast mode for IO burst DD */
+#define IOMEM_MDTIMEOUT (1<<23) /* Select short timeout */
+
+#define BANK_16 0
+#define BANK_32 IOMEM_SELSIDE
+#define BANK_64 IOMEM_SEL16MB
+#define BANK_128 IOMEM_SEL16MB | IOMEM_SELSIDE
+
+#define IOMEM_INIT IOMEM_RAFPER /* Initial register load */
+
+//
+// IOMMU
+//
+
+#define IOMMU_SWAP 0x7fff /* all segments swapped */
+#define IOMMU_BITS 0x0000 /* all segments 32 bits */
+
+
+//
+// DMACCESS & DMAHIT
+//
+
+#define DMA_COUNT_MASK 0x0000FFFF /* Count mask (15:0) */
+
+
+//
+// MACHINE STATUS REGISTER (MSR)
+//
+
+/* SNI machine status register information */
+
+#define MSR_VSYNC (1<<0) /* active high - video synchronization */
+#define MSR_TEMP (1<<1) /* active high - excessive temperature */
+#define MSR_LINEGOOD (1<<2) /* active low - power good */
+#define MSR_TIMER1 (1<<3) /* active low - int timer 1 */
+#define MSR_TIMER0 (1<<4) /* active low - int timer 0 */
+#define MSR_DBG_BUT (1<<5) /* active low - debug button int */
+#define MSR_TIMEOUT (1<<6) /* active low - timeout int */
+#define MSR_BAT_EN (1<<7) /* active high - batteries connected */
+
+//
+// MACHINE CONFIGURATION REGISTER (MCR)
+//
+
+/* SNI machine configuration register */
+
+#define MCR_TEMPBATACK (1<<0) /* active high - Disable / clear TEMP an Temp info */
+#define MCR_POWER_OFF (1<<1) /* active high - Stop power */
+#define MCR_STOP_BAT (1<<2) /* active high - Stop batteries */
+#define MCR_PODD (1<<3) /* active high - Select ODD parity R4K_CS */
+#define MCR_INRESET (1<<5) /* active high - Reset board */
+#define MCR_ENBREAK (1<<7) /* active high - Enable Break Duart B machine reset */
+
+
+#define LINEGOOD_L MSR_LINEGOOD /* high : powerfail */
+
+#endif // _SNIREGS_
diff --git a/private/ntos/nthals/halsnip/mips/unicache.s b/private/ntos/nthals/halsnip/mips/unicache.s
new file mode 100644
index 000000000..7be37c8ee
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/unicache.s
@@ -0,0 +1,1155 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/unicache.s,v 1.2 1995/11/02 11:04:33 flo Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// unicache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// MIPS R4000 Uni Processor machine.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+//
+// Note: On the SNI machines all single processor machines are configured in the Firmware
+// tree with the size of the Primary cache matching the physical size.
+// So, even Orion CPU are configured with 16KB not 2 sets of 8Kb.
+// In this case wqe can use the Routines special for Orion CPU also for
+// R4400 CPU.
+//
+
+#if!defined(ORION)
+#define ORION
+#endif
+
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D) ) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFlushDcachePageUni)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageUni
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalpPurgeDcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeDcachePageUni)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeDcachePageUni
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpPurgeIcachePageUni)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeIcachePageUni
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheUni (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheUni)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5)
+#endif
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+
+#if defined(ORION)
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10:
+ cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+
+30:
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5)
+#endif
+
+ j ra // return
+
+ .end HalpSweepDcacheUni
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+#if defined(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // do other set on Orion
+#endif
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheUni (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheUni)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+
+#if defined(ORION)
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0)
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalpSweepIcacheUni
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+10:
+
+ cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0) // do set B first on Orion
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageUni (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalpZeroPageUni, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,ZpA1(sp) // get old color bits
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpZeroPageUni
+
+
+
+
+ LEAF_ENTRY(HalpPciEccCorrector)
+// a0 : offset
+// a1 : pfn
+// a2 : length
+
+ .set noreorder
+ .set noat
+ and a0,a0,PAGE_SIZE -1 // PageOffset
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+ .set noreorder
+ .set noat
+
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+// beq zero,v0,40f // if eq, no second level cache
+
+//
+// Flush the secondary data cache.
+//
+
+20: lw t7,0(t8)
+ sw t7,0(t8)
+ cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+
+ nop
+ nop
+
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+40:
+
+ j ra // return
+
+ .end HalpPciEccCorrector
+
+
diff --git a/private/ntos/nthals/halsnip/mips/vgadata.h b/private/ntos/nthals/halsnip/mips/vgadata.h
new file mode 100644
index 000000000..a996b85a7
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/vgadata.h
@@ -0,0 +1,420 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/vgadata.h,v 1.3 1995/11/02 11:04:33 flo Exp $")
+
+#define MAX_CRT 0x19
+#define GRAPH_MAX 0x9
+#define MAX_PALETTE 0x15
+
+// VGA constants
+
+#define REVERSE_ATTRIBUTE 0x17 // white on blue
+
+#define INIT_VGA_FONT() \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x05); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x08); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x01);
+
+#define EXIT_VGA_FONT() \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x00); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x05); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x10); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x0e);
+
+
+//
+// Adresses for the Bt485 RamDac on the Orchid VLB and Diamond Viper board
+//
+
+#define Bt485_MASK ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c6))
+#define Bt485_ADDRRD ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c7))
+#define Bt485_ADDR ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c8))
+#define Bt485_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c9))
+#define Bt485_CR0 ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c6))
+#define Bt485_ADDRCURRD ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c7))
+#define Bt485_ADDRCUR ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c8))
+#define Bt485_DATACUR ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c9))
+#define Bt485_STATUS ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c6))
+#define Bt485_CR3 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c6)) /* if enabled */
+#define Bt485_CURSORRAM ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c7))
+#define Bt485_CR1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c8))
+#define Bt485_CR2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c9))
+#define Bt485_CURSOR_YL ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c6))
+#define Bt485_CURSOR_YH ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c7))
+#define Bt485_CURSOR_XL ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c8))
+#define Bt485_CURSOR_XH ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c9))
+
+// Some VGA Registers
+
+#define VGA_MISC_READ ((PVOID) ((ULONG)HalpVGAControlBase + 0x03cc))
+#define VGA_MISC_WRITE ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c2))
+#define VGA_SEQ_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c4))
+#define VGA_SEQ_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c5))
+#define VGA_CRT_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03d4))
+#define VGA_CRT_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03d5))
+#define VGA_ATC_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c0))
+#define VGA_ATC_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c0))
+#define VGA_GRAPH_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03ce))
+#define VGA_GRAPH_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03cf))
+#define VGA_ATC_FF ((PVOID) ((ULONG)HalpVGAControlBase + 0x03da))
+#define VGA_DAC_MASK ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c6))
+#define VGA_DAC_STATUS ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c7))
+#define VGA_DAC_WRITE_INDEX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c8))
+#define VGA_DAC_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c9))
+#define VGA_FEAT_CNTRL ((PVOID) ((ULONG)HalpVGAControlBase + 0x03ca))
+#define S3_ADVFUNC_CNTL ((PVOID) ((ULONG)HalpVGAControlBase + 0x4ae8))
+
+// the same registers as offset for use in SetHwMode()
+
+#define MISC_READ 0x03cc
+#define MISC_WRITE 0x03c2
+#define SEQ_IDX 0x03c4
+#define SEQ_DATA 0x03c5
+#define CRT_IDX 0x03d4
+#define CRT_DATA 0x03d5
+#define ATC_IDX 0x03c0
+#define ATC_DATA 0x03c0
+#define GRAPH_IDX 0x03ce
+#define GRAPH_DATA 0x03cf
+#define ATC_FF 0x03da
+#define DAC_MASK 0x03c6
+#define DAC_STATUS 0x03c7
+#define DAC_WRITE_INDEX 0x03c8
+#define DAC_DATA 0x03c9
+#define FEAT_CNTRL 0x03ca
+
+// S3 Advanced Function control register
+
+#define ADVFUNC_CNTL 0x4ae8
+
+#define MAGIC_REG1 0x46e8
+#define MAGIC_REG2 0x0102
+#define CIRRUS_MAGIC1 0x03c3
+#define CIRRUS_MAGIC2 0x0094
+
+//
+// "magic" registers to enable the Video System on VGA
+// for non Intel Systems
+//
+#define VGA_MAGIC_REG1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x46e8))
+#define VGA_MAGIC_REG2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x0102))
+#define CIRRUS_MAGIC_REG1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c3))
+#define CIRRUS_MAGIC_REG2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x0094))
+
+
+UCHAR base_colors[] = {
+ 0, 0, 0, // color 0 (black)
+ 0, 0, 42, // color 1 (drk. blue)
+ 0, 42, 0, // color 2 (olive)
+ 0, 42, 42, // color 3 ()
+42, 0, 0, // color 4 (brown)
+42, 0, 42, // color 5 (turquise)
+42, 21, 0, // color 6 (tundra )
+63, 63, 63, // color 7 (lt. grey(42,42,42 but we set it to white)
+21, 21, 21, // color 8 (drk. grey)
+21, 21, 63, // color 9 (blue)
+21, 63, 21, // color 10 (green)
+21, 63, 63, // color 11 (lt. blue)
+63, 0, 0, // color 12 (red)
+63, 0, 63, // color 13 (cyan)
+63, 63, 0, // color 14 (yellow)
+63, 63, 63 // color 15 (white)
+};
+
+//
+// this is an VGA 8x8 font (Codepage 437)
+//
+
+UCHAR font_8x8[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0x00
+0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, //0x01
+0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, //0x02
+0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, //0x03
+0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
+0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
+0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
+0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
+0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
+0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
+0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
+0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
+0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
+0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
+0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
+0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
+0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
+0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
+0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
+0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
+0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
+0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
+0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
+0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
+0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
+0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
+0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
+0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
+0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
+0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
+0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
+0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
+0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
+0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, // =
+0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, // >
+0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, // ?
+0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, // @
+0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, // A
+0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, // B
+0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, // C
+0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, // D
+0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, // E
+0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
+0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
+0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
+0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
+0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
+0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
+0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
+0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
+0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
+0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
+0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
+0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
+0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
+0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
+0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
+0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
+0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
+0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
+0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
+0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
+0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
+0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
+0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
+0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
+0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
+0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
+0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
+0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
+0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
+0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, // 8 bit codes 0x80
+0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x81 ü
+0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x82 é
+0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, // 0x83 â
+0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x84 ä
+0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x85 à
+0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x86°a
+0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, // 0x87,c
+0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, // 0x88 ê
+0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x89 ..e
+0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x8a è
+0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, // 0x8b ..i
+0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, // 0x8c î
+0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, // 0x8d ì
+0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, // 0x8e Ä
+0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, // 0x8f °A
+0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, // 0x90
+0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, // 0x91
+0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, // 0x92
+0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x93 ô
+0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x94 ö
+0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x95 ò
+0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x96 û
+0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x97 ù
+0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, // 0x98 ..y
+0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, // 0x99 Ö
+0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, // 0x9a ü
+0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, // 0x9b
+0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, // 0x9c
+0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, // 0x9d
+0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, // 0x9e
+0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, // 0x9f
+0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
+0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
+0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
+0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
+0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
+0x38, 0x74, 0xaa, 0xba, 0xaa, 0x64, 0x38, 0x00, // (R)
+0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
+0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
+0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
+0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
+0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
+0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
+0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
+0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, // (c)
+0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
+0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
+0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
+0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
+0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
+0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
+0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
+0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
+0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
+0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
+0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
+0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
+0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
+0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
+0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
+0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
+0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
+0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
+0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00,
+0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
+0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
+0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
+0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
+0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
+0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
+0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
+0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
+0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
+0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define STORM_OFFSET 0x1c00
+#define STORM_MISC_W 0x3c2
+#define STORM_PCI_OPTION 0x40
+
+#define STORM_RAMDAC_OFFSET 0x3c00
+#define STORM_TVP3026_INDEX 0x00
+#define STORM_TVP3026_DATA 0x0a
+
+#define STORM_TVP3026_PIX_CLK_DATA 0x2d
+#define STORM_TVP3026_MEM_CLK_DATA 0x2e
+#define STORM_TVP3026_MCLK_CTL 0x39
+
+#define STORM_TVP3026_PLL_ADDR 0x2c
+#define STORM_TVP3026_PLL_RESET 0xff
+
+#define VGA_CRTCEXT_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03de))
+#define VGA_CRTCEXT_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03df))
+#define VGA_CRTCEXT0 0x00
+#define VGA_CRTCEXT1 0x01
+#define VGA_CRTCEXT2 0x02
+#define VGA_CRTCEXT3 0x03
+#define VGA_CRTCEXT4 0x04
+#define VGA_CRTCEXT5 0x05
+
+#define STORM_STATUS 0x214
diff --git a/private/ntos/nthals/halsnip/mips/x4clock.s b/private/ntos/nthals/halsnip/mips/x4clock.s
new file mode 100644
index 000000000..82df85dee
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x4clock.s
@@ -0,0 +1,457 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/x4clock.s,v 1.6 1996/03/12 14:56:20 pierre Exp $")
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+#define MPA_TIMER_MESSAGE 11 /* timer interrupt */
+
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// we use this only when we have the machine up and running ...
+// LED's can show us something, what we do not see in the debugger
+//
+
+ la t0,HalpLedRegister // get current Value of LED Register
+ lw a0,0(t0)
+ addu a0,a0,1 // increment
+ sw a0,0(t0) // store and
+
+ lw t0,HalpIsTowerPci
+ beq t0,zero,2f
+ jal HalpPciTowerDisplayLed
+ b 3f
+
+2:
+ la t0, HalpLedAddress // get address of the variable
+ lw t0,0(t0) // get value
+ sb a0,0(t0) // display LSByte (set the LED)
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the new time increment is nonzero, then the new time
+// increment is moved to the next time increment and the timer is reprogramed
+//
+
+3: lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNewTimeIncrement // get new time increment
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // new interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // pipeline current increment value
+ bne zero,t4,10f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+10: sw zero,HalpNewTimeIncrement // clear new time increment
+ beq zero,t1,15f // if eq, not interval count change
+ sw t1,HalpNextTimeIncrement // set next time increment value
+ move a0,t1 // prepare to call HalpProgramIntervalTimer
+ jal HalpProgramIntervalTimer // program timer chip ...
+15: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ break BREAKIN_BREAKPOINT // break into the debugger
+
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the extra interval timer in the slave processors. Its function is
+// to transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Note: We plan to use the extra timer for our MultiProcessor (SNI)Machine
+// MAYBE, if we have arbitrated interrupts, we have to acknowledge
+// this interrupt here and send an message to the other processors
+// (Quadro machine)
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpClockInterrupt1, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ li a0,0x1000
+ jal HalpCheckSpuriousInt
+ beq v0,0,10f
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra
+
+10:
+ li t0, PCI_EXTRA_TIMER_ACK_ADDR // get address of acknowledge register
+ sb zero,0(t0) // acknowledge timer interrupt
+
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j t1 //
+ .end HalpClockInterrupt1
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the extra interval timer in the slave processors. Its function is
+// to transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// We use the extra timer for our MultiProcessor (SNI)Machine
+// we have to acknowledge
+// this interrupt here and send an message to the other processors
+// (Quadro machine)
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpClockInterruptPciTower, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+
+
+ //
+ // Send a "TIMER" ipi
+ //
+ lw a0,HalpIsMulti // test if more than 2 procs
+ li a1,2
+ slt a2,a1,a0
+ beq a2,0,10f // if no more than 2 proc , no need to send Ipi
+
+ li a0,0xc // send IPI to proc 2 and 3
+ li a1,MPA_TIMER_MESSAGE
+ jal HalpRequestIpi
+
+10: move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j t1 //
+ .end HalpClockInterruptPciTower
+
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpProfileInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+// li a0,0x8000
+// jal HalpCheckSpuriousInt
+// beq v0,zero,10f
+// lw ra,CiRa(sp) // restore return address
+// addu sp,sp,CiFrameLength // deallocate stack frame
+// j ra
+
+10: .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+
+
+//
+// we prefer the MultiPro version, which also works on UniPro machines
+//
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ li a0,0x00
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ jal t4 //
+
+
+
+ jal HalpCheckSpuriousInt
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra
+ .end HalpProfileInterrupt
+
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+ NESTED_ENTRY(HalpPciTowerDisplayLed, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+
+ //
+ // code for PCI tower
+ //
+ li t5,8,
+ divu a0,t5
+ mfhi t4
+ li t5,1
+ .word 0x018d2004 # sllv a0,t5,t4
+
+
+// t4 -> temp-reg.
+// t5 -> low-reg. 32 bits
+// t6 -> high-reg. 32 bits
+
+ and t5,a0,0x01 # bit0 shift to bit0(LED0)
+
+ and t4,a0,0x02 # bit1 shift to bit16(LED1)
+ sll t4,t4,16-1
+ or t5,t5,t4
+
+ and t4,a0,0x04 # bit2 shift to bit32(LED2) -> bit0/high_reg.
+ srl t6,t4,2-0
+
+ and t4,a0,0x08 # bit3 shift to bit48(LED3) -> bit16/high_reg.
+ sll t4,t4,16-3
+ or t6,t6,t4
+
+ and t4,a0,0x10 # bit4 shift to bit1(LED4)
+ srl t4,t4,4-1
+ or t5,t5,t4
+
+ and t4,a0,0x20 # bit5 shift to bit17(LED5)
+ sll t4,t4,17-5
+ or t5,t5,t4
+
+ and t4,a0,0x40 # bit6 shift to bit33(LED6) -> bit1/high_reg.
+ srl t4,t4,6-1
+ or t6,t6,t4
+
+ and t4,a0,0x80 # bit7 shift to bit49(LED7) -> bit17/high_reg.
+ sll t4,t4,17-7
+ or t6,t6,t4
+
+ lw a1,HalpLedAddress
+ lw t4,0(a1)
+ and t4,t4,PCI_TOWER_LED_MASK # led mask
+ or t4,t4,t5 # t5 -> low 32 bits
+ sw t4,0(a1)
+ jal KeFlushWriteBuffer
+
+ lw a1,HalpLedAddress
+ lw t4,4(a1)
+ and t4,t4,PCI_TOWER_LED_MASK # led mask
+ or t4,t4,t6 # t6 -> high 32 bits
+ sw t4,4(a1)
+ jal KeFlushWriteBuffer
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra
+
+ .end HalpPciTowerDisplayLed
+//
+// end code for PCI 1tower
+//
diff --git a/private/ntos/nthals/halsnip/mips/x4misc.s b/private/ntos/nthals/halsnip/mips/x4misc.s
new file mode 100644
index 000000000..c4c49fffd
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x4misc.s
@@ -0,0 +1,410 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/x4misc.s,v 1.4 1996/02/23 17:55:12 pierre Exp $")
+
+// TITLE("Misc R4000 Functions")
+//++
+//
+// Copyright (c) 1994 Siemens Nixdorf Informationssysteme AG
+//
+// Module Name:
+//
+// x4misc.s
+//
+// Abstract:
+//
+// This module implements some R4000 basic register access routines
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+#define STATUS_DE 0x10000 // Disable Cache error ands ECC Errors bit
+#define STATUS_IE 0x00001 // Interrupt Enable/Disable Bit
+#define STATUS_KX 0x80
+
+#define UNCACHED 0x2
+#define CACHABLE_NONCOHERENT 0x3
+#define CACHABLE_COHERENT_EXCLUSIVE 0x4
+#define CACHABLE_COHERENT_EXCLUSIVE_ON_WRITE 0x5
+#define CACHABLE_COHERENT_UPDATE_ON_WRITE 0x6
+
+ SBTTL("Get R4000 Status Register")
+//++
+//
+// ULONG
+// HalpGetStatusRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetStatusRegister
+
+ SBTTL("Set R4000 Status Register")
+//++
+//
+// ULONG
+// HalpSetStatusRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current (old)PSR
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,psr
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetStatusRegister
+
+ SBTTL("Get R4000 Cause Register")
+//++
+//
+// ULONG
+// HalpGetCauseRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the cause register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the cause register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetCauseRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,cause // get current cause
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetCauseRegister
+
+ SBTTL("Set R4000 Cause Register")
+//++
+//
+// ULONG
+// HalpSetCauseRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the Cause register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Cause register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetCauseRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,cause // get current (old)Cause
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,cause
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetCauseRegister
+
+ SBTTL("Get R4000 Config Register")
+//++
+//
+// ULONG
+// HalpGetConfigRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the Config register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Config register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetConfigRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,config // get current Config
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetConfigRegister
+
+ SBTTL("Set R4000 Config Register")
+//++
+//
+// ULONG
+// HalpSetConfigRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the R4000 Config register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Config register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetConfigRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,config // get current (old)Config
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,config
+ nop
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetConfigRegister
+#endif
+
+
+//++
+//
+// ULONG
+// HalpDisableInterrupts(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called to disable interrupts after a PCI error interrupt,
+// The machine is then stopped by a KeBugCheckEx().
+// This is indispensable for MATROX boards....
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpDisableInterrupts)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ and v0, v0, ~(STATUS_IE) // disable Interrupts
+ mtc0 v0,psr // enable interrupts
+
+ .set reorder
+10: j ra
+ .end HalpDisableInterrupts
+
+
+//++
+//
+// ULONG
+// HalpFindEccAddr(
+// ULONG Addr, // from ECC Error Asic Register
+// PVOID ErrStatusRegister, // register which indicates parity and Ecc error
+// PVOID ErrStatusBits // bits which indicates errors in the previous register
+// )
+//
+// Routine Description:
+//
+// This function is called to find the real physical address where the error occurs,
+// The Ecc Error Asic register contains the block address where the error address is.
+// To get ride of memory above 0x10000000, we use 64bits addressing capabilities of
+// the processor.
+// To detect the faulty address, we read all the block of data, word by word...
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFindEccAddr)
+
+
+ .set noreorder
+// adjust addr to a cache line
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ subu t3,t4,1
+ nor t3,t3,zero
+ and a0,a0,t3
+
+// generate 64 bits addr
+ mfc0 t1,psr // get current PSR saved in t1
+ nop // fill
+ and v0, t1, ~(STATUS_IE) // disable Interrupts
+// or v0, v0, PSR_KX // 64 bits adressing in kernel
+ mtc0 v0,psr // enable interrupts
+ nop
+ nop
+ nop
+
+ li t0,0x90000000
+ .word 0x0008403c // dsll32 t0,t0,zero
+ or a0,a0,t0 // beginning KSEG1 addr in 64bits
+ daddu t0,a0,t4 // ending KSEG1 addr in 64bits
+
+ or v0, v0, STATUS_KX // 64 bits adressing in kernel
+ mtc0 v0,psr
+ nop
+ nop
+ nop
+
+// reading loop
+1: lw t8,0(a0)
+ nop
+ sync
+
+ lw t8,0(a1) // PCI Error Status
+ nop
+ sync
+
+ and t9,t8,a2 // test memory/ecc error bits
+ nop
+ beq t9,zero,2f
+ nop
+// addr found
+ move v0,a0
+ j 10f
+ nop
+2: // addr not found => continue loop
+ daddiu a0,4 // word by word
+ bltu a0,t0,1b
+ nop
+ li v0,-1 // end of the loop - no addr found!
+
+10:
+ mtc0 t1,psr // enable interrupts + back to 32bits addressing
+ nop
+ nop
+ nop
+ .set reorder
+ j ra
+ .end HalpFindEccAddr
+
diff --git a/private/ntos/nthals/halsnip/mips/x4tb.s b/private/ntos/nthals/halsnip/mips/x4tb.s
new file mode 100644
index 000000000..4120525f4
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x4tb.s
@@ -0,0 +1,110 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/x4tb.s,v 1.1 1995/07/20 16:04:27 flo Exp $")
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpFreeTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/x86bios.c b/private/ntos/nthals/halsnip/mips/x86bios.c
new file mode 100644
index 000000000..17cd688aa
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x86bios.c
@@ -0,0 +1,191 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data.
+// per default, we enable int10's but we do nort use them on our well known
+// SNI graphic cards
+// if we have an unknown card, we try to initialize it via the emulator and the card
+// bios. if this fails, we disable int10 calls
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = TRUE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the X86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if (BiosCommand == 0x10){
+
+ if(HalpEnableInt10Calls == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // if Int10 commands are still enabled, Initialize the Card
+ // if it fails, disable Int10's
+ // this should make sense ...
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x50 16 color text mode.
+ // this is done by two int10 calls like on an standard PC
+ // hopefully this works ...
+ // the sample code sets only 80x25 mode, but we want more !!!
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+ //
+ // Now change it to 80x50 8x8Font Mode
+ //
+
+ Context.Eax = 0x1112; // use 8x8 font (causes 50 line mode)
+ Context.Ebx = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
diff --git a/private/ntos/nthals/halsnip/mips/xxcache.c b/private/ntos/nthals/halsnip/mips/xxcache.c
new file mode 100644
index 000000000..69d72396f
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxcache.c
@@ -0,0 +1,346 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxcache.c,v 1.4 1996/03/04 13:27:00 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ xxcache.c
+
+Abstract:
+
+
+ This module implements the functions necessesary to call the correct Cache routines
+ depending on Uni- or MultiProcessor machine typ.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "mpagent.h"
+#include "xxcache.h"
+
+HalpProcessorType HalpProcessorId = UNKNOWN;
+
+
+
+// Desktop : processor may be R4600 or R4700 both of them with or without SC
+// Minitower : processors may be R4700 with or without SC or R4400 + MPAgent (1 or 2)
+
+VOID
+HalpProcessorConfig()
+{
+ULONG Proc, reg;
+
+ Proc = HalpProcIdentify();
+ HalpMainBoard = (MotherBoardType) READ_REGISTER_UCHAR(0xbff0002a);
+ if (HalpMainBoard == M8150) HalpIsTowerPci = TRUE;
+
+ switch (Proc) {
+
+ case HalpR4600:
+ case HalpR4700:
+ if (PCR->SecondLevelDcacheFillSize) HalpProcessorId = ORIONSC; // ASIC driven SC
+ else HalpProcessorId = R4x00;
+ break;
+
+ default:
+ // RM200 and RM300 use the same bit but use the opposite value to determine the new ASIC revision...
+ // ASIC rev 1.0 => cache replace memory (special area reserved by the firmware).
+ // ASIC rev >= 1.1 => cache replace with the ASIC register value.
+ if (HalpMainBoard == DesktopPCI) {
+ UCHAR tmp;
+ tmp = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (tmp & PCI_MSR_REV_ASIC) HalpMpaCacheReplace = RM300_RESERVED | KSEG0_BASE; // rev 1.0
+ else HalpMpaCacheReplace = MPAGENT_RESERVED | KSEG0_BASE; // rev 1.1
+ } else {
+ if (HalpMainBoard == MinitowerPCI) {
+ UCHAR tmp;
+ tmp = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (tmp & PCI_MSR_REV_ASIC) HalpMpaCacheReplace = MPAGENT_RESERVED | KSEG0_BASE; // rev 1.1
+ else HalpMpaCacheReplace = RM300_RESERVED | KSEG0_BASE; // rev 1.0
+ } else HalpMpaCacheReplace = MPAGENT_RESERVED | KSEG0_BASE; // RM400 all ASIC
+ }
+
+ HalpProcessorId = MPAGENT; // R4x00 always with MPAgent on the PCI range.
+
+ if (HalpMpaCacheReplace == MPAGENT_RESERVED | KSEG0_BASE) {
+ reg = ((MPAGENT_RESERVED & // put the reserved physical address (4Mb long)
+ MPA_OP_ADDR_MASK) |
+ MPA_OP_ENABLE); // enable the operator
+ } else {
+ reg = 0;
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->mem_operator), reg); // for all procs (done for proc 0 in xxcache)
+
+ }
+
+ return;
+}
+
+VOID
+HalFlushDcachePage(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpFlushDcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepDcacheRange(
+ Color,
+ Length
+ );
+ HalpFlushDcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpFlushDcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalFlushDcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpFlushDcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepDcacheRange(
+ Color,
+ Length
+ );
+ HalpFlushDcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpPurgeDcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalPurgeDcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalPurgeIcachePage(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpPurgeIcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepIcacheRange(
+ Color,
+ Length
+ );
+ HalpPurgeIcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpPurgeIcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalPurgeIcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalSweepDcache(
+ VOID
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpSweepDcacheMulti();
+ break;
+
+ case ORIONSC:
+
+ HalpSweepDcacheOrion();
+ break;
+
+ case R4x00:
+
+ HalpSweepDcacheUni();
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalSweepDcache();
+
+ }
+
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpSweepIcacheMulti();
+ break;
+
+ case ORIONSC:
+
+ HalpSweepIcacheOrion();
+ break;
+
+ case R4x00:
+
+ HalpSweepIcacheUni();
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalSweepIcache();
+
+ }
+
+}
+
+VOID
+HalZeroPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpZeroPageMulti(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case ORIONSC:
+
+ HalpZeroPageOrion(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case R4x00:
+
+ HalpZeroPageUni(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalZeroPage(NewColor, OldColor, PageFrame);
+
+ }
+
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxcache.h b/private/ntos/nthals/halsnip/mips/xxcache.h
new file mode 100644
index 000000000..6bc20b155
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxcache.h
@@ -0,0 +1,30 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxcache.h,v 1.2 1996/03/04 13:27:16 pierre Exp $")
+
+//
+// Prototypes for private cache functions
+// they match the ones defined for the HAL ...
+//
+
+VOID HalpZeroPageOrion(IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame);
+VOID HalpZeroPageMulti(IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame);
+VOID HalpZeroPageUni(IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame);
+
+VOID HalpSweepIcacheOrion(VOID);
+VOID HalpSweepIcacheMulti(VOID);
+VOID HalpSweepIcacheUni(VOID);
+
+VOID HalpSweepDcacheOrion(VOID);
+VOID HalpSweepDcacheMulti(VOID);
+VOID HalpSweepDcacheUni(VOID);
+
+VOID HalpPurgeIcachePageOrion(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpPurgeIcachePageMulti(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpPurgeIcachePageUni(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+
+VOID HalpPurgeDcachePageUni(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+
+VOID HalpFlushDcachePageOrion(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpFlushDcachePageMulti(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpFlushDcachePageUni(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+
+
diff --git a/private/ntos/nthals/halsnip/mips/xxcalstl.c b/private/ntos/nthals/halsnip/mips/xxcalstl.c
new file mode 100644
index 000000000..1eb6e4c17
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxcalstl.c
@@ -0,0 +1,278 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxcalstl.c,v 1.4 1996/03/04 13:27:51 pierre Exp $")
+/*++
+
+Copyright (c) 1991 - 1994 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+#if DBG
+UCHAR HalpBuffer[128];
+#endif
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 200; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 4000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ if (Index == 0) {
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºWARNING: Cannot compute stall factor º\n");
+ HalDisplayString("ºWARNING: Using default value (250 Mhz) º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+ HalpStallScaleFactor = 0x20;
+ HalpProfileCountRate = 125*1000000;
+ }
+ else {
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt if profiling is done via count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpProfileInterrupt;
+
+#if DBG
+ sprintf(HalpBuffer,"HalpCalibrateStall : CPU frequency is %d MHz, StallFactor is %d\n", (HalpProfileCountRate/1000000)*2, HalpStallScaleFactor);
+ HalDisplayString(HalpBuffer);
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+
+ HalpStallEnd = 0;
+
+ HalpWriteCompareRegisterAndClear(0);
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+ }
+
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxclock.c b/private/ntos/nthals/halsnip/mips/xxclock.c
new file mode 100644
index 000000000..c9da66a5c
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxclock.c
@@ -0,0 +1,277 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxclock.c,v 1.3 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1985-94 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "i82C54.h"
+
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ KIRQL OldIrql;
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ NewTimeIncrement = DesiredIncrement / MINIMUM_INCREMENT;
+ NewTimeIncrement = NewTimeIncrement * MINIMUM_INCREMENT;
+ HalpNewTimeIncrement = NewTimeIncrement ;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the System clock according to the frequency
+ required by the specified time increment value.
+
+ N.B. this information was found in the jenson (ALPHA) HAL
+ also valid for MIPS computer ???
+
+ There are four different rates that are used under NT
+ (see page 9-8 of KN121 System Module Programmer's Reference)
+
+ .976562 ms
+ 1.953125 ms
+ 3.90625 ms
+ 7.8125 ms
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+ PEISA_CONTROL controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+ ULONG Count;
+ TIMER_CONTROL timerControl;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Start the system clock to interrupt at the desired interval.
+ //
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ //
+ // use timer in the onboard PC core
+ //
+
+ Count = TIMER_CLOCK_IN / ( 10000000 / Interval );
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)Count);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(Count >> 8));
+
+ KeLowerIrql(OldIrql);
+}
+
+
+VOID
+HalpProgramExtraTimer (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the second clock generator in a multiprocessor System
+ according to the frequency required by the specified Interval value (in 100ns units).
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+
+ volatile PLOCAL_8254 pt = (PLOCAL_8254) PCI_EXTRA_TIMER_ADDR;
+ ULONG Count;
+ TIMER_CONTROL timerControl;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Start the system clock to interrupt at the desired interval.
+ //
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ Count = EXTRA_TIMER_CLOCK_IN / (PRE_COUNT * 10000000 / Interval );
+
+ WRITE_REGISTER_UCHAR( &pt->control, *((PUCHAR) &timerControl));
+ WRITE_REGISTER_UCHAR(&(pt->counter0), (UCHAR)Count);
+ WRITE_REGISTER_UCHAR(&(pt->counter0), (UCHAR)(Count >> 8));
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_RATE_GENERATOR;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ // the output of counter 2 is hardwired as input to counter 0/1
+ // so we use it as a pre-counter
+
+ WRITE_REGISTER_UCHAR( &pt->control, *((PUCHAR) &timerControl));
+ WRITE_REGISTER_UCHAR(&(pt->counter2), (UCHAR)PRE_COUNT);
+ WRITE_REGISTER_UCHAR(&(pt->counter2), (UCHAR)(PRE_COUNT >>8));
+
+ KeLowerIrql(OldIrql);
+
+}
+
+
+VOID
+HalpProgramExtraTimerPciT (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the second clock generator in PCI tower
+ according to the frequency required by the specified Interval value (in 100ns units).
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+
+ KIRQL OldIrql;
+
+ //Stop the timer
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,0);
+
+ //Reset Timer-Count Register
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_COUNT_REG,0);
+
+ //Set Timer-Value Register in ms
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_VALUE_REG,(UCHAR)(Interval/10000));
+
+ //Start Timer
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,1);
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KeLowerIrql(OldIrql);
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/xxerror.c b/private/ntos/nthals/halsnip/mips/xxerror.c
new file mode 100644
index 000000000..f55c9dd81
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxerror.c
@@ -0,0 +1,293 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxerror.c,v 1.3 1996/05/15 08:13:24 pierre Exp $")
+/*--
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxerror.c
+
+Abstract:
+
+
+ This module implements the management of errors (KeBugCheckEx, HalpBusError)
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+
+//
+// Messages for CacheError routine
+//
+
+UCHAR HalpErrCacheMsg[] = "\nCACHE ERROR\n";
+UCHAR HalpParityErrMsg[] = "\nPARITY ERROR\n";
+UCHAR HalpAddrErrMsg[] = "Address in error not found\n";
+ULONG HalpCacheErrFirst = 0;
+
+ULONG HalpKeBugCheck0;
+ULONG HalpKeBugCheck1;
+ULONG HalpKeBugCheck2;
+ULONG HalpKeBugCheck3;
+ULONG HalpKeBugCheck4;
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+//
+// Define bug check information buffer and callback record.
+//
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+//
+// Define BugCheck Number and BugCheck Additional Message
+//
+
+ULONG HalpBugCheckNumber = (ULONG)(-1);
+
+PUCHAR HalpBugCheckMessage[] = {
+"MP_Agent fatal error\n", // #0
+"ASIC PCI TRANSFER ERROR\n", // #1
+"ECC SINGLE ERROR COUNTER OVERFLOW\n", // #2
+"UNCORRECTABLE ECC ERROR\n", // #3
+"PCI TIMEOUT ERROR\n", // #4
+"MP_BUS PARITY ERROR\n", // #5
+"MP_BUS REGISTER SIZE ERROR\n", // #6
+"MEMORY ADDRESS ERROR\n", // #7
+"MEMORY SLOT ERROR\n", // #8
+"MEMORY CONFIG ERROR\n", // #9
+"PCI INITIATOR INTERRUPT ERROR\n", // #10
+"PCI TARGET INTERRUPT ERROR\n", // #11
+"PCI PARITY INTERRUPT ERROR\n", // #12
+"MULTIPLE PCI INITIATOR ERROR\n", // #13
+"MULTIPLE PCI TARGET ERROR\n", // #14
+"MULTIPLE PCI PARITY ERROR\n", // #15
+"DATA_BUS_ERROR\n", // #16
+"INSTRUCTION_BUS_ERROR\n", // #17
+"PARITY ERROR\n", // #18
+"CACHE ERROR\n" // #19
+};
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+ PUCHAR p,q;
+
+ if (HalpBugCheckNumber == -1) return; // that is not a HAL bugcheck ...
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+ DumpBuffer->Par0 = HalpKeBugCheck0;
+ DumpBuffer->Par1 = HalpKeBugCheck1;
+ DumpBuffer->Par2 = HalpKeBugCheck2;
+ DumpBuffer->Par3 = HalpKeBugCheck3;
+ DumpBuffer->Par4 = HalpKeBugCheck4;
+ DumpBuffer->MainBoard = HalpMainBoard;
+ p = DumpBuffer->TEXT;q = HalpBugCheckMessage[HalpBugCheckNumber];
+ while (*q) *p++ = *q++;
+ return;
+}
+
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ UCHAR IntSource;
+ UCHAR MaStatus;
+ ULONG Itpend;
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpInterruptLock);
+
+
+
+ if (HalpIsTowerPci){
+ // stop the extra-timer
+
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,0);
+
+
+ HalpPciTowerInt3Dispatch(&HalpInt3Interrupt,(PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER);
+ }else{
+
+ IntSource = READ_REGISTER_UCHAR(PCI_INTERRUPT_SOURCE_REGISTER);
+
+ IntSource ^= PCI_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // and XOR the high active with 0 gives 1
+ if ( IntSource & PCI_INT2_MASK) {
+
+ MaStatus = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (HalpMainBoard == DesktopPCI) {
+ MaStatus ^= PCI_MSR_MASK_D;
+ } else {
+ MaStatus ^= PCI_MSR_MASK_MT;
+ }//(HalpMainBoard == DesktopPCI)
+
+ //
+ // look for an ASIC interrupt
+ //
+
+ if ( MaStatus & PCI_MSR_ASIC_MASK){
+
+ Itpend = READ_REGISTER_ULONG(PCI_ITPEND_REGISTER);
+
+ if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR)) {
+
+ ULONG AsicErrAddr, ErrAddr, Syndrome, ErrStatus;
+
+ ErrAddr = READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER);
+ Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
+ ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
+
+ if (ErrStatus & PCI_MEMSTAT_PARERR) {
+ // Parity error (PCI_ASIC <-> CPU)
+#if DBG
+ DebugPrint(("pci_memory_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 1;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }//if (ErrStatus & PCI_MEMSTAT_PARERR)
+
+
+
+ if (ErrStatus & PCI_MEMSTAT_ECCERR) {
+
+ AsicErrAddr &= 0xfffffff8;
+ ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_ECCERR);
+ if (ErrAddr == -1) ErrAddr = AsicErrAddr;
+
+#if DBG
+ // UNIX => PANIC
+ DebugPrint(("pci_ecc_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 3;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "UNCORRECTABLE ECC ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ } //if (ErrStatus & PCI_MEMSTAT_ECCERR)
+ } //if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR))
+
+
+ }//if ( MaStatus & PCI_MSR_ASIC_MASK)
+
+ }//if ( IntSource & PCI_INT2_MASK)
+ }//if (HalpIsTowerPci)
+
+ // arrive here if no interruption found
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ if (( ExceptionRecord->ExceptionCode & DATA_BUS_ERROR ) == DATA_BUS_ERROR) {
+ HalpBugCheckNumber = 16;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "DATA_BUS_ERROR\n"
+ } else {
+ HalpBugCheckNumber = 17;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "INSTRUCTION_BUS_ERROR\n"
+ }
+
+ HalpKeBugCheckEx(ExceptionRecord->ExceptionCode ,
+ HalpBugCheckNumber,
+ (ULONG)VirtualAddress,
+ (ULONG)PhysicalAddress.LowPart,
+ 0);
+
+ KiReleaseSpinLock(&HalpInterruptLock);
+ KeLowerIrql(OldIrql);
+
+return FALSE;
+}
diff --git a/private/ntos/nthals/halsnip/mips/xxidle.s b/private/ntos/nthals/halsnip/mips/xxidle.s
new file mode 100644
index 000000000..97c9a8d6d
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxidle.s
@@ -0,0 +1,79 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxidle.s,v 1.3 1995/11/02 11:04:33 flo Exp $")
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+ li a0,0x01
+ j HalpCheckSpuriousInt // return
+
+10: j ra
+ .end HalProcessorIdle
+
diff --git a/private/ntos/nthals/halsnip/mips/xxinithl.c b/private/ntos/nthals/halsnip/mips/xxinithl.c
new file mode 100644
index 000000000..61e462bb0
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxinithl.c
@@ -0,0 +1,695 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxinithl.c,v 1.13 1996/05/15 08:14:04 pierre Exp $")
+/*--
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "string.h"
+#include "mpagent.h"
+#include "snipbus.h"
+
+ULONG HalpLedRegister;
+PUCHAR HalpLedAddress = (PUCHAR)PCI_LED_ADDR;;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+BOOLEAN LessThan16Mb;
+BOOLEAN HalpEisaDma;
+MotherBoardType HalpMainBoard;
+
+// MultiProcessor machine has a MpAgent per processor
+// Values of HalpIsMulti are :
+// 0 : 1 processor
+// 2 : 2 processors
+// n : n processors
+
+UCHAR HalpIsMulti = 0;
+
+BOOLEAN HalpCountCompareInterrupt = FALSE;
+BOOLEAN HalpIsTowerPci = FALSE;
+ULONG HalpMpaCacheReplace = RM300_RESERVED | KSEG0_BASE; // address to be used for cache replace operation.
+ULONG HalpTwoWayBit; // size of one set for associative cache R5000-R4600-R4700
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpInterruptLock;
+KSPIN_LOCK HalpMemoryBufferLock;
+
+extern VOID HalpParseLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock) ;
+BOOLEAN HalPCIRegistryInitialized = FALSE;
+BOOLEAN HalpESC_SB;
+
+extern UCHAR
+HalpRevIdESC(
+ VOID
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+#pragma alloc_text(INIT, HalpDisplayCopyRight)
+
+#endif
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PciData;
+
+ Prcb = PCR->Prcb;
+
+ PCR->DataBusError = HalpBusError;
+ PCR->InstructionBusError = HalpBusError;
+
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Processor 0 specific
+ //
+
+ if(Prcb->Number == 0) {
+
+ *(PULONG)(& (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[0]) )=0;
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ KeInitializeSpinLock(&HalpInterruptLock);
+ KeInitializeSpinLock(&HalpMemoryBufferLock);
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // try to identify the Kind of Mainboard => already done in HalpProcessorIdentify
+ //
+
+// HalpMainBoard = (MotherBoardType) READ_REGISTER_UCHAR(0xbff0002a);
+
+ if (HalpRevIdESC() == REV_ID_82374_SB ) HalpESC_SB = TRUE;
+ else HalpESC_SB = FALSE;
+
+ if (HalpMainBoard == M8150) HalpIsTowerPci = TRUE;
+
+ if (HalpIsTowerPci)
+ HalpLedAddress = (PUCHAR)PCI_TOWER_LED_ADDR;
+ else
+ HalpLedAddress = (PUCHAR)PCI_LED_ADDR;
+
+ HalpLedRegister = 0;
+
+ //
+ // for Isa/Eisa access during phase 0 we use KSEG1 addresses
+ //
+
+ HalpOnboardControlBase = (PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ HalpEisaControlBase = (PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ HalpParseLoaderBlock(LoaderBlock) ;
+
+ HalpInitializePCIBus();
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+#if DBG
+ if (!HalPCIRegistryInitialized) HalDisplayString("Non PCI Machine detected\n");;
+#endif
+
+ if (!HalPCIRegistryInitialized) HalDisplayString("Non PCI Machine detected - This HAL is not the right one\n");;
+
+ (ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) = (ULONG)-1;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext = 0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipHalInfo = 0;
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only needed for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ //
+ // Is this machine a multi-processor one ?
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if ((NextRestartBlock != NULL) && (NextRestartBlock->NextRestartBlock != NULL)) {
+
+#if DBG
+ HalDisplayString("Multiprocessor machine detected by RestartBlock\n");
+#endif
+
+ //
+ // There is more than one processor
+ // be sure, the boot (this one) is set to running and started
+ //
+
+ if (!HalpIsMulti) HalpIsMulti = TRUE;
+
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ NextRestartBlock->BootStatus.ProcessorReady = 1;
+
+ } else {
+#if DBG
+ HalDisplayString("UniProcessor machine detected\n");
+#endif
+ HalpIsMulti = FALSE;
+ }
+
+ // Initialize the MP Agent
+
+ if (HalpProcessorId == MPAGENT) {
+ HalpInitMPAgent(0);
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number] = 0x01;
+ PCR->InterruptRoutine[OUR_IPI_LEVEL] = HalpIpiInterrupt;
+ }
+
+ //
+ // For the moment, we say all Eisa/ Isa(Onboard) Interrupts should go to processor 0
+ //
+
+ HalpCreateEisaStructures(Isa); // Initialize Onboard Interrupts and Controller
+
+ //
+ // Initialize SNI specific interrupts
+ // (only once needed)
+ //
+
+ HalpCreateIntPciStructures();
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+
+ } else {
+
+#if DBG
+// sprintf(HalpBuffer,"HalInitSystem: running on %d\n", HalpGetMyAgent());
+// HalDisplayString(HalpBuffer);
+#endif
+ //
+ // Place something special only to Slave Processors here ...
+ //
+
+ HalpInitMPAgent(Prcb->Number); // enables IPI, init cache replace address
+ PCR->InterruptRoutine[OUR_IPI_LEVEL] = HalpIpiInterrupt;
+
+
+ }
+
+ //
+ // PCR tables and System Timer Initialisation
+ //
+
+ HalpInitializeInterrupts();
+
+ if (HalpIsTowerPci){
+
+ // enable PCI interrupt
+
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = EN_TARG_INTR | EN_INIT_INT ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // enable PCI parity interrupt
+
+ PciData = PCI_TOWER_COMMAND_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = EN_SERR ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData,READ_REGISTER_ULONG((PULONG) HalpPciConfigData) | *((PULONG) &PciData));
+
+
+ PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = 0x1f0 ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // LOCKSPACE for workaround ethernet
+ PciData = PCI_TOWER_PM_LOCKSPACE | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = 0x80000000 ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+ }
+
+ return (TRUE);
+
+ } else {
+
+ extern BOOLEAN HalpX86BiosInitialized;
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Mapping of the EISA Control Space via MmMapIoSpace()
+ //
+
+ HalpMapIoSpace();
+
+ HalpCalibrateStall();
+
+ //
+ // Initialisation of the x86 Bios Emulator ...
+ //
+
+ x86BiosInitializeBios(HalpEisaControlBase, HalpEisaMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Be sure, that the NET_LEVEL is not in the reserved vector .
+ // (NET_DEFAULT_VECTOR == IPI_LEVEL = 7) => only used for
+ // machine != RM200 (mainboard 8036) and processor without
+ // secondary cache
+ //
+
+ PCR->ReservedVectors &= ~(1 << NET_DEFAULT_VECTOR);
+
+ HalpDisplayCopyRight();
+
+ return TRUE;
+ }
+}
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+//
+// The boot processor is already initialized
+//
+
+#if DBG
+// sprintf(HalpBuffer,"HalInitializeProcessor %d\n",Number);
+// HalDisplayString(HalpBuffer);
+#endif
+
+return;
+
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ if(!HalpIsMulti) {
+ return FALSE;
+ }
+
+
+#if DBG
+// sprintf(HalpBuffer,"HalStartNextProcessor running on %d\n", HalpGetMyAgent());
+// HalDisplayString(HalpBuffer);
+#endif
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+//
+// start it by sending him a special IPI message (SNI special to avoid traffic on
+// the MP bus during boot)
+//
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[Number] = 0x01;
+ HalpSendIpi(1 << (NextRestartBlock->ProcessorId), MPA_BOOT_MESSAGE );
+
+ HalpIsMulti++; //the number of processors is incremented
+
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+VOID
+HalpDisplayCopyRight(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function displays the CopyRight Information in the correct SNI Style
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+//
+// Define Identification Strings.
+//
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+#if defined(SNI_INTERNAL)
+ HalDisplayString("ºMicrosoft(R) Windows NT(TM) 3.51 Hardware Abstraction Layer º\n");
+ HalDisplayString("ºfor Siemens Nixdorf RM200/RM300/RM400 Release 3.0 A0008 º\n");
+#else
+ HalDisplayString("ºMicrosoft(R) Windows NT(TM) 4.00 Hardware Abstraction Layer º\n");
+ HalDisplayString("ºfor Siemens Nixdorf RM200/RM300/RM400 Release 3.0 B0008 º\n");
+#endif
+ HalDisplayString("ºCopyright(c) Siemens Nixdorf Informationssysteme AG 1996 º\n");
+ HalDisplayString("ºCopyright(c) Microsoft Corporation 1985-1996 º\n");
+ HalDisplayString("ºAll Rights Reserved º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ //
+ // this does not seem to work correct on NT 3.51 builds (872) at least
+ // on our MultiPro machine
+ //
+ if(!HalpCountCompareInterrupt) {
+
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºWARNING: CountCompare Interrupt is not enabled º\n");
+ HalDisplayString("ºWARNING: please contact your local Siemens Nixdorf º\n");
+ HalDisplayString("ºWARNING: Service Center. º\n");
+ HalDisplayString("ºWARNING: º\n");
+ HalDisplayString("ºWARNING: Your System will come up - but some º\n");
+ HalDisplayString("ºWARNING: performance measurement issues º\n");
+ HalDisplayString("ºWARNING: WILL NOT FUNCTION PROPERLY º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ }
+
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxinitnt.c b/private/ntos/nthals/halsnip/mips/xxinitnt.c
new file mode 100644
index 000000000..eeb252c3a
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxinitnt.c
@@ -0,0 +1,345 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxinitnt.c,v 1.5 1996/03/04 13:29:07 pierre Exp $")
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+extern BOOLEAN HalpCountCompareInterrupt;
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpAckExtraClockInterrupt(
+ VOID
+ );
+
+VOID
+HalpCountInterrupt (
+ VOID
+ );
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG Interval
+ );
+
+VOID
+HalpProgramExtraTimer (
+ IN ULONG Interval
+ );
+
+
+VOID
+HalpProgramExtraTimerPciT (
+ IN ULONG Interval
+ );
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpInitializeInterrupts)
+#pragma alloc_text(INIT, HalpCountInterrupt)
+
+#endif
+
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+/*+++
+
+
+ The interrupts bits in the cause Register have the following Hardware Interrupts:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | x | x | x | x | x | x | x | x |
+ +-------------------------------+
+ | | | | | | | |
+ | | | | | | | +-------- APC LEVEL (Software)
+ | | | | | | +------------ Dispatch LEVEL (Software)
+ | | | | | +---------------- central Int0 (proc 0)
+ | | | | +-------------------- None
+ | | | +------------------------ None
+ | | +---------------------------- TIMER (Proc 1 for RM300MP only)
+ | +-------------------------------- DCU (Proc 1 for RM400MP only - proc 0 for RM400UP only)
+ +------------------------------------ CountCompare (Profiling)
+
+---*/
+
+//
+// On an PCI Desktop or minitower single-processor (ORION), the processor has only 1 central
+// interrupt pin, so all should be directed to this interrupt, except the (internal)
+// CountCompare interrupt
+//
+
+UCHAR
+HalpIrqlMask_PCIs[] = {3, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+
+UCHAR
+HalpIrqlTable_PCIs[] = {0x87, // IRQL 0
+ 0x86, // IRQL 1
+ 0x84, // IRQL 2
+ 0x80, // Int0Dispatch Level
+ // allow only Irql 8 (profiling & HIGH_LEVEL) ?!
+ 0x80, // IRQL 4
+ 0x80, // IRQL 5
+ 0x80, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+//
+// On a PCI Tower, all the external interrupts are centralised
+// on one central pin except DCU on IP6 (because of the extra-timer).
+// The internal MP-Agent interrupt is directed on the seventh pin.
+//
+
+UCHAR
+HalpIrqlMask_PCIm_ExT[] = {3, 3, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+UCHAR
+HalpIrqlTable_PCIm_ExT[] = {0xe7, // IRQL 0
+ 0xe6, // IRQL 1
+ 0xe4, // IRQL 2
+ 0xe0, // Int0Dispatch Level
+ 0xe0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+//
+// On a PCI multi-processor minitower (or mono-processor with MPagent),
+// all the external interrupts are centralised
+// on one central pin except extra-timer on IP6 (not used if mono).
+// The internal MP-Agent interrupt is directed on the seventh pin.
+//
+
+UCHAR
+HalpIrqlMask_PCIm[] = {3, 5, 3, 5, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+UCHAR
+HalpIrqlTable_PCIm[] = {0xd7, // IRQL 0
+ 0xd6, // IRQL 1
+ 0xd4, // IRQL 2
+ 0xd0, // Int0Dispatch Level
+ 0xd0, // IRQL 4
+ 0xc0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ extern ULONG HalpProfileInterval;
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+ HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+ HalpCountCompareInterrupt = TRUE;
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ if (HalpProcessorId != MPAGENT) {
+
+ //
+ // this is a PCI desktop or a single-processor PCI minitower
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIs); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIs[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIs); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIs[Index];
+
+ } else {
+
+ //
+ // this is a PCI minitower or PCI tower
+ //
+
+ if (HalpIsTowerPci){
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm_ExT); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm_ExT[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm_ExT); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm_ExT[Index];
+ }else{
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm[Index];
+ }
+
+ }
+
+ //
+ // the main system clock is always in the onboard PC core
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE)HalpStallInterrupt;
+
+ //
+ // force a CountCompare interrupt
+ //
+
+ HalpWriteCompareRegisterAndClear(100);
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\compare interrupt to the appropriate interrupt service routine.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ HalpProgramIntervalTimer (MAXIMUM_INCREMENT);
+ HalpEnableOnboardInterrupt(CLOCK2_LEVEL,Latched); // Enable Timer1,Counter0 interrupt
+
+ } else {
+
+ //
+ // MultiProcessorEnvironment Processor N
+ //
+
+ if (HalpIsTowerPci){
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm_ExT); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm_ExT[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm_ExT); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm_ExT[Index];
+ }else{
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm[Index];
+ }
+
+ if (Prcb->Number==1){
+ if (HalpIsTowerPci){
+ HalpProgramExtraTimerPciT(MAXIMUM_INCREMENT);
+ }else{
+ HalpProgramExtraTimer (MAXIMUM_INCREMENT);
+ PCR->InterruptRoutine[EXTRA_CLOCK_LEVEL] = HalpClockInterrupt1;
+ }
+ }
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ }
+
+ return TRUE;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxipiint.s b/private/ntos/nthals/halsnip/mips/xxipiint.s
new file mode 100644
index 000000000..20c0302ac
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxipiint.s
@@ -0,0 +1,56 @@
+// TITLE("Interprocessor Interrupts")
+//++
+//
+// Copyright (c) 1993-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxipiint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a MIPS R4000 Duo system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt.
+// Its function is to acknowledge the interrupt and transfer control to
+// the standard system routine to process interprocessor requrests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpIpiInterrupt)
+
+//
+// Inter processor interrupt processing
+//
+
+ move a0,s8
+ j HalpProcessIpi // acknowledgement Ipi
+
+ .end HalpIpiInterrupt
+
diff --git a/private/ntos/nthals/halsnip/mips/xxmemory.c b/private/ntos/nthals/halsnip/mips/xxmemory.c
new file mode 100644
index 000000000..2d9806212
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxmemory.c
@@ -0,0 +1,246 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxmemory.c,v 1.2 1996/02/23 17:55:12 pierre Exp $")
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow the HAL to map physical memory.
+
+Environment:
+
+ Phase 0 initialization only.
+
+Changes:
+
+ All stuff comes from the x86 HAL Sources (xxmemory.c)
+
+--*/
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalpAllocPhysicalMemory)
+#endif
+
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The pyhsical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which contains a memory chunk
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+
+ PhysicalAddress = (AlignmentOffset + Descriptor->BasePage)
+ << PAGE_SHIFT;
+
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+
+ return PhysicalAddress;
+}
+
+
+#define MEMBASE 0x20000000
+
+USHORT HalpComputeNum (phys_addr)
+UCHAR *phys_addr;
+{
+ USHORT board_or_simm_num;
+ ULONG i;
+ struct bank *pbank =((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->MemConfArea;
+ ULONG nb_banks =((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))-> NbMemBanks;
+ UCHAR *conf_addr;
+
+
+
+ if (pbank == 0) return((USHORT)(-1)); // firmware revision < 4.5 --> function non implemented
+
+
+ // Rebase phys_addr at 0x20000000
+ (ULONG)phys_addr |= MEMBASE;
+
+ for (i = 0; i < nb_banks; i++, pbank++) {
+
+ // Rebase conf_addr at 0x20000000
+ conf_addr =(UCHAR *)( (ULONG)pbank->first_addr | MEMBASE);
+
+ if ((phys_addr >= conf_addr) && (phys_addr < (conf_addr + pbank->first_piece_size))){
+
+ break;
+ }
+
+ if (pbank->second_piece_size != 0) {
+
+ // Rebase conf_addr at 0x20000000
+ conf_addr =(UCHAR *)((ULONG) pbank->second_addr | MEMBASE);
+
+ if ((phys_addr >= conf_addr) && (phys_addr < (conf_addr + pbank->second_piece_size))) {
+
+ break;
+ }
+ }
+ }
+
+ if (i == nb_banks) {
+
+ // Unable to find the board or SIMM
+ board_or_simm_num = (USHORT)(-1);
+ }
+
+ else {
+ // On RM400 we have one board per bank from 1 to nb_banks
+ if (HalpIsTowerPci) {
+ board_or_simm_num = (USHORT)(i + 1);
+ }
+ // On RM200/RM300 we have two SIMM's per bank from 0 to 2*nb_banks - 1
+ else {
+ board_or_simm_num = (USHORT)( (2*i) + (((ULONG)phys_addr >> 3) & 0x01));
+ }
+ }
+
+ return (board_or_simm_num);
+}
+
+
+
+
+
diff --git a/private/ntos/nthals/halsnip/sources b/private/ntos/nthals/halsnip/sources
new file mode 100644
index 000000000..8f47a87e9
--- /dev/null
+++ b/private/ntos/nthals/halsnip/sources
@@ -0,0 +1,92 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halsnip
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-DSNI -DORION
+
+INCLUDES=..\x86new;..\..\inc
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\x86bios.c \
+ mips\allstart.c \
+ mips\cacherr.s \
+ mips\unicache.s \
+ mips\duocache.s \
+ mips\orcache.s \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\j4prof.c \
+ mips\jxebsup.c \
+ mips\jxenvirv.c \
+ mips\jxport.c \
+ mips\jxbeep.c \
+ mips\jxreturn.c \
+ mips\jxmapio.c \
+ mips\SNIdisp.c \
+ mips\jxhwsup.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\xxcalstl.c \
+ mips\xxinithl.c \
+ mips\xxinitnt.c \
+ mips\r4intdsp.c \
+ mips\xxmemory.c \
+ mips\mpagent.c \
+ mips\xxcache.c \
+ mips\xxclock.c \
+ mips\xxidle.s \
+ mips\x4misc.s \
+ mips\xxipiint.s \
+ mips\x4clock.s \
+ mips\snipbus.c \
+ mips\xxerror.c \
+ mips\x4tb.s
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halsp/drivesup.c b/private/ntos/nthals/halsp/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halsp/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halsp/hal.rc b/private/ntos/nthals/halsp/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halsp/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halsp/hal.src b/private/ntos/nthals/halsp/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halsp/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halsp/i386/halnls.h b/private/ntos/nthals/halsp/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/halsp/i386/halp.h b/private/ntos/nthals/halsp/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halsp/i386/ix8259.inc b/private/ntos/nthals/halsp/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halsp/i386/ixbusdat.c b/private/ntos/nthals/halsp/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halsp/i386/ixcmos.asm b/private/ntos/nthals/halsp/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halsp/i386/ixcmos.inc b/private/ntos/nthals/halsp/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halsp/i386/ixdat.c b/private/ntos/nthals/halsp/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halsp/i386/ixenvirv.c b/private/ntos/nthals/halsp/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halsp/i386/ixfirm.c b/private/ntos/nthals/halsp/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halsp/i386/ixhwsup.c b/private/ntos/nthals/halsp/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halsp/i386/ixidle.asm b/private/ntos/nthals/halsp/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halsp/i386/ixinfo.c b/private/ntos/nthals/halsp/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halsp/i386/ixisa.h b/private/ntos/nthals/halsp/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halsp/i386/ixisabus.c b/private/ntos/nthals/halsp/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halsp/i386/ixisasup.c b/private/ntos/nthals/halsp/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halsp/i386/ixkdcom.c b/private/ntos/nthals/halsp/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halsp/i386/ixkdcom.h b/private/ntos/nthals/halsp/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halsp/i386/ixmca.c b/private/ntos/nthals/halsp/i386/ixmca.c
new file mode 100644
index 000000000..378abfb24
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixmca.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixmca.c"
diff --git a/private/ntos/nthals/halsp/i386/ixmcaa.asm b/private/ntos/nthals/halsp/i386/ixmcaa.asm
new file mode 100644
index 000000000..d018edfc4
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixmcaa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixmcaa.asm
diff --git a/private/ntos/nthals/halsp/i386/ixnmi.c b/private/ntos/nthals/halsp/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/halsp/i386/ixpcibrd.c b/private/ntos/nthals/halsp/i386/ixpcibrd.c
new file mode 100644
index 000000000..02fd82821
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixpcibrd.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/halsp/i386/ixpcibus.c b/private/ntos/nthals/halsp/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/halsp/i386/ixpciint.c b/private/ntos/nthals/halsp/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/halsp/i386/ixphwsup.c b/private/ntos/nthals/halsp/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halsp/i386/ixreboot.c b/private/ntos/nthals/halsp/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halsp/i386/ixstall.asm b/private/ntos/nthals/halsp/i386/ixstall.asm
new file mode 100644
index 000000000..115c6c9c1
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixstall.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixstall.asm
diff --git a/private/ntos/nthals/halsp/i386/ixsysbus.c b/private/ntos/nthals/halsp/i386/ixsysbus.c
new file mode 100644
index 000000000..b4776da76
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixsysbus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixsysbus.c"
diff --git a/private/ntos/nthals/halsp/i386/ixthunk.c b/private/ntos/nthals/halsp/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halsp/i386/ixusage.c b/private/ntos/nthals/halsp/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halsp/i386/pcip.h b/private/ntos/nthals/halsp/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/halsp/i386/spacer.c b/private/ntos/nthals/halsp/i386/spacer.c
new file mode 100644
index 000000000..4d74bb4c2
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spacer.c
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) 1993 ACER America Corporation
+
+Module Name:
+
+ acer.c
+
+Abstract:
+
+ ACER Write-back Secondary Cache Control c code.
+
+ This module implements the code which detects and enables the
+ secondary write-back cache on ACER products (ICL also).
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "halp.h"
+#include "spacer.h" // i/o addresses & bit definitions
+
+
+ULONG HalpGetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+
+VOID HalpAcerInitializeCache ( VOID ); // externally used
+BOOLEAN has_write_back_cache( VOID ); // local only
+
+
+// ************************ routines ****************************
+
+BOOLEAN has_write_back_cache( VOID )
+/*++
+
+Routine Description:
+
+ This routine checks to see if this machine supports a secondary
+ write-back cache.
+
+ This routine checks if the machine is an ACER, ALTOS, or ICL product.
+
+ eisa id: acr32xx - acer product
+ eisa id: acs32xx - altos product
+ eisa id: icl00xx - icl product
+
+ The only thing that tells us whether or not the CPU has a secondary
+ write-back cache is the least significant byte of the EISA id.
+
+ xx = 61h for cpu0 indicates the presence of a write-back cache
+
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE machine supports a secondary write-back cache.
+ FALSE machine is not known to support a write-back cache.
+
+--*/
+
+{
+ UCHAR id0, id1, id2, id3;
+
+ // grab cpu0's eisa id information
+ id0 = READ_PORT_UCHAR( (PUCHAR) ACER_CPU0_EISA_ID0 );
+ id1 = READ_PORT_UCHAR( (PUCHAR) ACER_CPU0_EISA_ID1 );
+ id2 = READ_PORT_UCHAR( (PUCHAR) ACER_CPU0_EISA_ID2 );
+
+
+ // are we a acer or altos machine?
+ if ( (id0 == (UCHAR) ACER_ID0 &&
+ id1 == (UCHAR) ACER_ID1 &&
+ id2 == (UCHAR) ACER_ID2 ) ||
+ (id0 == (UCHAR) ALTOS_ID0 &&
+ id1 == (UCHAR) ALTOS_ID1 &&
+ id2 == (UCHAR) ALTOS_ID2 ) ) {
+
+ // check the lsw id cpu to see if it has a write back cache
+ // All acer/altos/icl machines can only have 1 cpu type, so if the
+ // first cpu supports a write-back cache then all of them do.
+ id3 = READ_PORT_UCHAR( (PUCHAR) ACER_CPU0_EISA_ID3 );
+
+ if ( id3 == (UCHAR) ACER_EISA_ID_WB_CPU0 )
+ return TRUE; // gotcha
+
+ }
+
+
+ // are we an icl mx machine?
+ if ( (id0 == (UCHAR) ICL_ID0 &&
+ id1 == (UCHAR) ICL_ID1 &&
+ id2 == (UCHAR) ICL_ID2 ) ) {
+
+ // check the lsw id cpu to see if it has a write back cache
+ // All acer/altos/icl machines can only have 1 cpu type, so if the
+ // first cpu supports a write-back cache then all of them do.
+ id3 = READ_PORT_UCHAR( (PUCHAR) ACER_CPU0_EISA_ID3 );
+
+ if ( id3 == (UCHAR) ICL_EISA_ID_WB_CPU0 )
+ return TRUE; // gotcha
+
+ }
+
+ return FALSE; // when in doubt be safe
+}
+
+
+VOID
+HalpAcerInitializeCache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine enables the write-back cache available on certain
+ ACER product. If the write-back cache is supported then it enables
+ it.
+
+ NOTE: 1) This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information. Or that
+ the HAL code which is calling this routine has serialized access.
+ 2) For CSR bit definitions see the acer.h file
+
+
+ You cannot call dbgprint to talk to the debugger since the port is not
+ initialized yet.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+SideEffects:
+
+ NMI mask is enabled.
+
+--*/
+
+{
+
+ UCHAR shadow_ram_setup; // tmp var for current shadow stat
+ UCHAR high_ram_setup; // tmp var for current ram setup
+
+
+ // say hello to the outside world
+ //HalDisplayString(ACER_HAL_VERSION_NUMBER);
+ //HalDisplayString("Acer HAL: Searching for secondary write-back cache\n");
+
+
+ // check to see if this particular ACER model even has a
+ // write-back cache
+ if ( !has_write_back_cache() ) {
+ //HalDisplayString("Acer HAL: No write-back cache found\n");
+ return;
+ }
+
+
+ // retrieve BIOS setup shadow ram status
+ // read in byte, mask off bit 0 - 1-RAM BIOS 0-ROM BIOS
+ HalpGetCmosData((ULONG) 0, (ULONG) ACER_SHADOW_IDX,
+ (PVOID) &shadow_ram_setup, (ULONG) 1 );
+
+
+ // Set up shadow_ram_setup:
+ // bit 0 - 1-BIOS Shadow 0=No Shadowing
+
+ shadow_ram_setup &= RAM_ROM_MASK;
+
+ if ( shadow_ram_setup == 0 ) {
+ //HalDisplayString("Acer HAL: NO BIOS RAM Shadowing\n");
+ } else {
+ //HalDisplayString("Acer HAL: BIOS RAM Shadowing\n");
+ }
+
+ // retrieve BIOS setup 15MB-16MB ram status
+ // mask off bit 1 -
+ // 1-(15MB-16MB) RAM 0-(15MB-16MB) EISA
+
+ HalpGetCmosData((ULONG) 0, (ULONG) ACER_15M_16M_IDX,
+ (PVOID) &high_ram_setup, (ULONG) 1 );
+
+
+ // 15MB-16MB memory setup (high_ram_setup):
+ // bit 5 1=EISA 0=System RAM
+ // note: the polarity is opposite from what getcmosdata read
+
+ high_ram_setup &= DRAM_EISA_MASK; // just grab bit 1
+ high_ram_setup ^= DRAM_EISA_MASK; // invert polarity
+ high_ram_setup <<= 4; // place at bit<4>
+
+ if ( high_ram_setup == 0) {
+ //HalDisplayString("Acer HAL: 15Mb to 16Mb Allocated to System RAM\n");
+ } else {
+ //HalDisplayString("Acer HAL: 15Mb to 16Mb Allocated to I/O Space\n");
+ }
+
+ // Enable write-back secondary cache on cpus 0 & 1
+ // by setting bit<2>
+ WRITE_PORT_UCHAR( (PUCHAR) ACER_PORT_CPU01,
+ (UCHAR) (WRITE_BALLOC_ON | shadow_ram_setup | high_ram_setup));
+
+
+ // always set write-back secondary cache on cpus 2 & 3
+ // even if system does not have cpus 2 & 3
+ WRITE_PORT_UCHAR( (PUCHAR) ACER_PORT_CPU23,
+ (UCHAR) (WRITE_BALLOC_ON | shadow_ram_setup | high_ram_setup));
+
+ // flush the last pending i/o write by reading a safe io location
+ READ_PORT_UCHAR( (PUCHAR) EISA_FLUSH_ADDR );
+
+ // that's all folks
+ //HalDisplayString("Acer HAL: Write-back cache enabled!\n");
+}
diff --git a/private/ntos/nthals/halsp/i386/spacer.h b/private/ntos/nthals/halsp/i386/spacer.h
new file mode 100644
index 000000000..c1cc4ac22
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spacer.h
@@ -0,0 +1,193 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1993 ACER America Corporation
+
+Module Name:
+
+ acer.h
+
+Abstract:
+
+ This header file defines the unique interfaces, defines and structures
+ for the ACER product line
+
+Revision History:
+ 1.0b - plm initial release
+ 1.1b - acer.c: halpacereisa: handle scrabled eisa data gracefully.
+
+--*/
+
+#define ACER_HAL_VERSION_NUMBER "Acer HAL Version 1.1b for October Windows NT Beta.\n"
+
+
+/* ACER Special I/O Port defintions
+ * I/O Port Address 0xcc4h
+ * |
+ * 0: cpu0 & cpu1
+ * c: cpu2 & cpu3
+ *
+ * bits < 7 6 5 4 3 2 1 0 > (WRITE-ONLY)
+ * 0 0 | 0 0 | 0 |
+ * | | BIOS Shadow Control
+ * | | 0: ROM BIOS
+ * | | 1: RAM BIOS
+ * | |
+ * | |
+ * | Write-Back Cache Control
+ * | 0: write-thru ( write-back disabled)
+ * | 1: write-back enabled
+ * |
+ * 15Mb to 16Mb Memory Setup
+ * 0: Ram
+ * 1: EISA
+ *
+ */
+
+
+// where do i find the CSR which controls the write-back enabling?
+#define ACER_PORT_CPU01 0xcc4 // write only - setup reg. cpu 0,1
+#define ACER_PORT_CPU23 0xccc4 // write onlY - setup reg. cpu 2,3
+
+#define WRITE_BALLOC_ON 0x04 // bit<2> - enable write-back cache bit
+#define WRITE_BALLOC_OFF 0x00 // bit<2> - disable write-back cache bit
+
+/* ACER RT/CMOS contents
+ *
+ * index 35h bit<1>: 15Mb to 16Mb Memory Setup
+ * 0: EISA
+ * 1: Ram
+ * all other bits RESERVED
+ *
+ * index 39h bit<0>: BIOS Shadow Control
+ * 0: ROM BIOS
+ * 1: RAM BIOS
+ * all other bits RESERVED
+ *
+ */
+
+// RT/CMOS indexes where special Acer machine config info is kept
+// where is the information kept that tells me if bios shadowing is eabled?
+#define ACER_SHADOW_IDX 0x39 // RT/CMOS index for shadow bios control
+
+#define RAM_ROM_MASK 0x01 // bit<0>, 0:RAM BIOS 1:ROM BIOS
+
+// where is the information kept that tells me if 15M-16M is EISA or RAM?
+#define ACER_15M_16M_IDX 0x35 // RT/CMOS index for 15Mb-16Mb mem cntrl
+
+#define DRAM_EISA_MASK 0x02 // bit<1>, 0:EISA 1:RAM
+
+// EISA ID base addresses for cpu0
+#define ACER_CPU0_EISA_ID0 0x0c80 /* 1 digit + part of digit 2 */
+#define ACER_CPU0_EISA_ID1 0x0c81 /* rest of digit 2 + digit 3 */
+#define ACER_CPU0_EISA_ID2 0x0c82 /* msw id */
+#define ACER_CPU0_EISA_ID3 0x0c83 /* msw id */
+
+// ACER EISA ID's
+#define ACER_ID0 0x04 /* acr32xx */
+#define ACER_ID1 0x72
+#define ACER_ID2 0x32
+
+// ALTOS EISA ID's
+#define ALTOS_ID0 0x04 /* acs32xx */
+#define ALTOS_ID1 0x73
+#define ALTOS_ID2 0x32
+
+// ICL EISA ID's
+#define ICL_ID0 0x24 /* icl00xx */
+#define ICL_ID1 0x6c
+#define ICL_ID2 0x00
+
+
+// EISA IDs of ACER/ALTOS machines which support a write-back secondary cache
+#define ACER_EISA_ID_WB_CPU0 0x61
+
+// EISA IDs of ICL machine (acer oem) which supports write-back scndry cache
+// NOTE: THESE IDS ARE STILL TBD!!!
+#define ICL_EISA_ID_WB_CPU0 0x61
+
+// EISA constants
+#define MAX_IRQS_PER_EISABUS 16 // how many irq to search for
+#define MAX_EISA_SLOTS 16 // number of eisa slots
+
+// magic number for kefindconfigurationentry
+//#define EISA_DATA_OFFSET 24 // offset to data portion of eisa pointer
+
+// cpu0's i/o address space for cpu1's pic's
+//
+// NOTE: These defines MUST MATCH EXACTLY the equ's found in spirql.asm
+//
+#define CPU1_PIC1_PORT0 0xc024
+#define CPU1_PIC1_PORT1 0xc0a4
+#define CPU1_PIC2_PORT0 0xc025
+#define CPU1_PIC2_PORT1 0xc0a5
+
+#define CPU0_PIC1_PORT0 0x020
+#define CPU0_PIC1_PORT1 0x0a0
+
+// cpu0's eisa level/edge register
+#define EISA_LEVEL_EDGE_PIC1 0x04d0
+#define EISA_LEVEL_EDGE_PIC2 0x04d1
+
+#define SET_TO_EDGE ((UCHAR) 0x0000)
+#define SET_TO_LEVEL ((UCHAR) -1)
+
+// eisa level/edge register bit which MUST BE edges
+#define EISA_LEVEL_EDGE_PIC1_INIT 0xb8
+#define EISA_LEVEL_EDGE_PIC2_INIT 0xde
+
+// eisa 8259
+#define READ_IRR 0x0a
+#define READ_ISR 0x0b
+
+// a safe eisa i/o location that can be read to force any caches
+// to flush any pending i/o writes. This just happens to be
+// the eisa manufacturer i.d. location
+#define EISA_FLUSH_ADDR 0x0c80
+
+// This define MUST EXACTLY MATCH asm equ located in file spmp.inc
+#define SMP_ACER 3
+
+#define MAX_ACER_CPUS 4 // maximum number of cpus a acer can hold
+
+//
+// acer_irq_distribution callback data structure
+//
+typedef struct _ACER_IRQ_DISTRIBUTION {
+
+ BOOLEAN distribte_irqs; // shall i try to distribute irqs across cpus
+
+ // cpu x pics can handle level irqs?
+ BOOLEAN px_set_to_level_irqs[ MAX_ACER_CPUS ];
+
+ // number of irqs which have been assigned, used for load balancing
+ SHORT px_numb_irqs_assigned[ MAX_ACER_CPUS ];
+
+ // only a certain number of irqs per pic pair can handle level triggerring
+ BOOLEAN eisa_level_compatable[ MAX_IRQS_PER_EISABUS ];
+
+} ACER_IRQ_DISTRIBUTION, *PACER_IRQ_DISTRIBUTION;
+
+// default number of irq's assinged
+#define ACER_IRQS_ASSIGED_CPU0 1 // stay away from 0 for init case
+#define ACER_IRQS_ASSIGED_CPU1 0
+#define ACER_IRQS_ASSIGED_CPU2 0
+#define ACER_IRQS_ASSIGED_CPU3 0
+
+
+// what irqs can be level distriubted?
+#define ACER_DISTRIBUTE_LEVEL_IRQ0 FALSE
+#define ACER_DISTRIBUTE_LEVEL_IRQ1 FALSE
+#define ACER_DISTRIBUTE_LEVEL_IRQ2 FALSE
+#define ACER_DISTRIBUTE_LEVEL_IRQ3 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ4 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ5 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ6 FALSE
+#define ACER_DISTRIBUTE_LEVEL_IRQ7 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ8 FALSE
+#define ACER_DISTRIBUTE_LEVEL_IRQ9 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ10 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ11 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ12 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ13 FALSE
+#define ACER_DISTRIBUTE_LEVEL_IRQ14 TRUE
+#define ACER_DISTRIBUTE_LEVEL_IRQ15 TRUE
diff --git a/private/ntos/nthals/halsp/i386/spbeep.asm b/private/ntos/nthals/halsp/i386/spbeep.asm
new file mode 100644
index 000000000..fcde8b5d8
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spbeep.asm
@@ -0,0 +1,246 @@
+ title "Hal Beep"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; spbeep.asm
+;
+;Abstract:
+;
+; HAL routine to make noise. It needs to synchronize its access to the
+; 8254, since we also use the 8254 for the profiling interrupt.
+;
+;
+;Author:
+;
+; John Vert (jvert) 31-Jul-1991
+;
+;Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\spmp.inc
+
+ .list
+
+ extrn _Halp8254Lock:DWORD
+ extrn _SpType:BYTE
+
+;
+; Defines used to program the i8254 for the speaker.
+;
+
+I8254_TIMER_CONTROL_PORT EQU 43h
+I8254_TIMER_DATA_PORT EQU 42h
+I8254_TIMER_CLOCK_IN EQU 1193167
+I8254_TIMER_TONE_MAX EQU 65536
+I8254_TIMER_CONTROL_SELECT EQU 0B6h
+SPEAKER_CONTROL_PORT EQU 61h
+SPEAKER_OFF_MASK EQU 0FCh
+SPEAKER_ON_MASK EQU 03h
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "HalMakeBeep"
+;++
+;
+; BOOLEAN
+; HalMakeBeep(
+; IN ULONG Frequency
+; )
+;
+; Routine Description:
+;
+; This function sets the frequency of the speaker, causing it to sound a
+; tone. The tone will sound until the speaker is explicitly turned off,
+; so the driver is responsible for controlling the duration of the tone.
+;
+;Arguments:
+;
+; Frequency - Supplies the frequency of the desired tone. A frequency of
+; 0 means the speaker should be shut off.
+;
+;Return Value:
+;
+; TRUE - Operation was successful (frequency within range or zero)
+; FALSE - Operation was unsuccessful (frequency was out of range)
+; Current tone (if any) is unchanged.
+;
+;--
+
+Frequency equ [ebp + 8]
+
+cPublicProc _HalMakeBeep, 1
+
+ push ebp ; save ebp
+ mov ebp, esp ;
+ push ebx ; save ebx
+
+Hmb10Sp:pushfd ; save flags
+ cli ; disable interrupts
+
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax,Hmb99Sp
+
+ cmp _SpType, SMP_SYSPRO2 ; On SysPro2 do it differently
+ je HalMakeBeepSmp
+
+ ;
+ ; Stop the speaker.
+ ;
+
+ in al, SPEAKER_CONTROL_PORT
+ jmp $+2
+ and al, SPEAKER_OFF_MASK
+ out SPEAKER_CONTROL_PORT, al
+ jmp $+2
+
+ ;
+ ; Calculate Tone: Tone = 1.193MHz / Frequency.
+ ; N.B. Tone must fit in 16 bits.
+ ;
+
+ mov ecx, DWORD PTR [Frequency] ; ecx <- frequency
+ or ecx, ecx ; (ecx) == 0?
+ je SHORT Hmb30Sp ; goto Hmb30Sp
+
+ mov eax, I8254_TIMER_CLOCK_IN ; eax <- 1.193MHz, the clockin
+ ; for the speaker tone
+ sub edx, edx ; edx <- zero
+ div ecx ; eax <- 1.193MHz / frequency
+ cmp eax, I8254_TIMER_TONE_MAX ; (eax) < 2**16?
+ jb SHORT Hmb20Sp ; goto Hmb20Sp
+
+ ;
+ ; Invalid frequency. Return FALSE.
+ ;
+
+ sub al, al
+ jmp SHORT Hmb40Sp
+Hmb20Sp:
+ ;
+ ; Program the 8254 with the calculated tone.
+ ;
+
+ push eax ; save Tone
+ mov al, I8254_TIMER_CONTROL_SELECT
+ out I8254_TIMER_CONTROL_PORT, al ; select timer control register
+ jmp $+2
+
+ pop eax ; restore Tone
+ out I8254_TIMER_DATA_PORT, al ; program 8254 with Tone lsb
+ jmp $+2
+ mov al, ah
+ out I8254_TIMER_DATA_PORT, al ; program 8254 with Tone msb
+ jmp $+2
+
+ ;
+ ; Turn the speaker on.
+ ;
+
+ in al, SPEAKER_CONTROL_PORT
+ jmp $+2
+ or al, SPEAKER_ON_MASK
+ out SPEAKER_CONTROL_PORT, al
+ jmp $+2
+
+Hmb30Sp:
+ ;
+ ; Return TRUE.
+ ;
+
+ mov al, 1
+
+Hmb40Sp:
+ lea ebx, _Halp8254Lock
+ RELEASE_SPINLOCK ebx
+
+ popfd
+ pop ebx ; restore ebx
+ pop ebp ; restore ebp
+ stdRET _HalMakeBeep
+
+Hmb99Sp:popfd
+ SPIN_ON_SPINLOCK eax,<Hmb10Sp>
+
+
+HalMakeBeepSmp:
+; A BELIZE/PHOENIX machine MUST always enable and disable the beep via
+; CPU 0 regardless of the originating CPU. This is done through indexed
+; IO.
+;
+; Note the indexed IO is serialized with the 8254 spinlock
+
+
+ ;
+ ; Stop the speaker.
+ ;
+
+ INDEXED_IO_READ 0,SPEAKER_CONTROL_PORT
+ and al, SPEAKER_OFF_MASK
+
+ INDEXED_IO_WRITE 0,SPEAKER_CONTROL_PORT,al
+
+ ;
+ ; Calculate Tone: Tone = 1.193MHz / Frequency.
+ ; N.B. Tone must fit in 16 bits.
+ ;
+
+ mov ecx, DWORD PTR [Frequency] ; ecx <- frequency
+ or ecx, ecx ; (ecx) == 0?
+ je Hmb30Sp ; goto Hmb30
+
+ mov eax, I8254_TIMER_CLOCK_IN ; eax <- 1.193MHz, the clockin
+ ; for the speaker tone
+ sub edx, edx ; edx <- zero
+ div ecx ; eax <- 1.193MHz / frequency
+ cmp eax, I8254_TIMER_TONE_MAX ; (eax) < 2**16?
+ jb SHORT Hmb20 ; goto Hmb20
+
+ ;
+ ; Invalid frequency. Return FALSE.
+ ;
+
+ sub al, al
+ jmp Hmb40Sp
+Hmb20:
+ ;
+ ; Program the 8254 with the calculated tone.
+ ;
+
+ push eax ; save Tone
+ mov al, I8254_TIMER_CONTROL_SELECT
+
+ INDEXED_IO_WRITE 0,I8254_TIMER_CONTROL_PORT,al
+
+ pop eax ; restore Tone
+
+ INDEXED_IO_WRITE 0,I8254_TIMER_DATA_PORT,al
+ mov al, ah
+
+ INDEXED_IO_WRITE 0,I8254_TIMER_DATA_PORT,al
+
+ ;
+ ; Turn the speaker on.
+ ;
+
+ INDEXED_IO_READ 0,SPEAKER_CONTROL_PORT
+ or al, SPEAKER_ON_MASK
+
+ INDEXED_IO_WRITE 0,SPEAKER_CONTROL_PORT,al
+ jmp Hmb30Sp
+
+stdENDP _HalMakeBeep
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halsp/i386/spclock.asm b/private/ntos/nthals/halsp/i386/spclock.asm
new file mode 100644
index 000000000..9b0f38c7a
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spclock.asm
@@ -0,0 +1,1096 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT. It works on UP and SystemPro.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+;
+;--
+
+.386p
+ .xlist
+include callconv.inc
+include hal386.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\spmp.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalRequestIpi,1
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _KeStallExecutionProcessor, 1
+ extrn _HalpProcessorPCR:DWORD
+ extrn _HalpSystemHardwareLock:DWORD
+ extrn _HalpFindFirstSetRight:BYTE
+ extrn _Sp8259PerProcessorMode:BYTE
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ EXTRNP _HalpMcaQueueDpc, 0
+ extrn _SpType:BYTE
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193182
+
+;
+; ==== Values used for System Clock ====
+;
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec.
+;
+;
+; The best fit value closest to 10ms (but not below) is 10.0144012689ms:
+; ROLLOVER_COUNT 11949
+; TIME_INCREMENT 100144
+; Calculated error is -.0109472 s/day
+;
+; The best fit value closest to 15ms (but not above) is 14.9952019ms:
+; ROLLOVER_COUNT 17892
+; TIME_INCREMENT 149952
+; Calculated error is -.0109472 s/day
+;
+; On 486 class machines or better we use a 10ms tick, on 386
+; class machines we use a 15ms tick
+;
+
+ROLLOVER_COUNT_10MS EQU 11949
+TIME_INCREMENT_10MS EQU 100144
+
+;
+; Value for KeQueryPerf retries.
+;
+
+MAX_PERF_RETRY equ 3 ; Odly enough 3 is plenty.
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+ public _HalpIpiClock
+_HalpIpiClock dd 0 ; Processors to IPI clock pulse to
+
+;
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+_Halp8254Lock dd 0
+
+
+ public HalpPerfCounterLow
+ public HalpPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpPerfP0Value dd 0
+HalpCalibrateFlag db 0
+ db 0
+ dw 0
+
+HalpRollOverCount dd 0
+
+ public _HalpClockWork, _HalpClockSetMSRate, _HalpClockMcaQueueDpc
+_HalpClockWork label dword
+ _HalpClockSetMSRate db 0
+ _HalpClockMcaQueueDpc db 0
+ _bReserved1 db 0
+ _bReserved2 db 0
+
+;
+; Storage for variable to ensure that queries are always
+; greater than the last.
+;
+
+HalpLastQueryLowValue dd 0
+HalpLastQueryHighValue dd 0
+HalpForceDataLock dd 0
+
+; endmod
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0
+;
+; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock ,0
+
+;
+; Use 15ms or 10ms clock tick?
+;
+
+ mov edx, TIME_INCREMENT_10MS ; yes, use 10ms clock
+ mov ecx, ROLLOVER_COUNT_10MS
+;
+; Fill in PCR value with TIME_INCREMENT
+; (edx) = TIME_INCREMENT
+; (ecx) = ROLLOVER_COUNT
+;
+ cmp byte ptr PCR[PcHal.PcrNumber], 0
+ jne short icl_10
+
+ push ecx
+ stdCall _KeSetTimeIncrement, <edx, edx>
+ pop ecx
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+; (ecx) = RollOverCount
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+ mov HalpRollOverCount, ecx ; Set RollOverCount & initialized
+ stdRET _HalpInitializeClock
+
+
+icl_10:
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+;
+; initialize clock, non-p0
+; (ecx) = ROLLOVER_COUNT
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter, 1
+
+ mov eax, [esp+4] ; ponter to Number
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ test _Sp8259PerProcessorMode, SP_SMPCLOCK
+ jz short cal_exit ; 8254 per processor?
+
+ xor ecx, ecx
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ; Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ; Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx, al
+ in al, TIMER1_DATA_PORT0 ; Read PIT Ctr 0, MSByte.
+ mov ch, al ; (CX) = PIT Ctr 0 count.
+
+ cmp byte ptr PCR[PcHal.PcrNumber], 0 ; is this the processor
+ jz short cal_p0 ; which updates HalpPerfCounter?
+
+@@: cmp HalpCalibrateFlag, 0 ; wait for P0 to post it's counter
+ jz short @b
+
+ sub ecx, HalpPerfP0Value ; compute difference
+ neg ecx
+ mov PCR[PcHal.PcrPerfSkew], ecx
+
+cal_exit:
+ popfd
+ stdRET _HalCalibratePerformanceCounter
+
+cal_p0: mov HalpPerfP0Value, ecx ; post our timer value
+ mov HalpCalibrateFlag, 1 ; signal we are done
+ jmp short cal_exit
+
+stdENDP _HalCalibratePerformanceCounter
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+20] ; User supplied Performance Frequence
+RetryPerfCount EQU [esp] ; Local retry variable
+
+
+cPublicProc _KeQueryPerformanceCounter ,1
+
+ push ebx
+ push esi
+ push edi
+ push 0 ; make space for RetryPerfCount
+
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before 8254
+; initialization has occured. Reading garbage off the 8254 is not reasonable.
+;
+ cmp HalpRollOverCount, 0
+ jne short Kqpc11 ; ok, perf counter has been initialized
+
+;
+; Initialization hasn't occured yet, so just return zeroes.
+;
+ mov eax, 0
+ mov edx, 0
+ jmp Kqpc50
+
+Kqpc11: pushfd
+ cli
+
+Kqpc20:
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+; NOTE:
+; Need to watch for Px reading the 'CounterLow', P0 updates both
+; then Px finishes reading 'CounterHigh' [getting the wrong value].
+; After reading both, make sure that 'CounterLow' didn't change.
+; If it did, read it again. This way, we won't have to use a spinlock.
+
+
+@@:
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+ cmp ebx, HalpPerfCounterLow ;
+ jne short @b
+
+
+;
+; Fetch the current counter value from the hardware
+;
+
+;
+; Background: Belize style systems have an 8254 per Processor.
+;
+; In short the original implementation kinda assumes that each
+; timer on each processor will be in perfect sycnh with each other.
+; This is a bad assumption, and the reason why we have attempted
+; to use only the timer on P0.
+;
+; There is an existing window where the return value may not be accurate.
+; The window will occur when multiple queries are made back to back
+; in an MP environment, and there are a lot of IPIs going on. Intuitive,
+; right. The problem is that this routine may return a value with the
+; the hardware system timer on P0 that has already generated an interrupt
+; and reset its rollover, but the software has yet to process the interrupt
+; to update the performance counter value. When this occurs, the second
+; querry will seem to have a lower value than the first.
+;
+; So, why don't I just fix it. Well the cause of the problem is the
+; overhead associated with handling the interrupt, and the fact that
+; the IPI has a higher IRQL. In addition, a busy system could be
+; issueing multiple IPIs back to back, which could extend this window
+; even further.
+;
+; I have managed to close the window most of the way for most normal
+; conditions. It takes several minutes on a busy system, with
+; multiple applications running with back to back queries to get
+; an invalid value. It can happen though.
+;
+; A retry implementation has been instrumented on top off the
+; Indexed IO implementation to finally close the window.
+; It seems to work OK.
+;
+; In reality, I think the fix is sufficient. The performance counter
+; is not designed propperly (via only software) to yield very accurate
+; values on sub timer tic (10-15msec) ranges on multiprocessor systems.
+;
+; Problems with this design:
+;
+; On an idle system threads executing from P0 will always
+; use less overhead than threads executing on P1.
+; On a ProLiant 2000 with 2 P5-66s the difference in 2
+; consecutive KeQueryPerformanceCounter calls from P0
+; is about 14, while from P1 is about 22. Unfortunately
+; on a busy system P0 performs about the same, but P1
+; is much slower due to the overhead involved in performing
+; an Indexed_IO. This means the busyier your system gets
+; the less accurate your performance values will become.
+;
+; The solution:
+;
+; A system wide hardware timer needs to be used. This is about the
+; only way to get accurate performance numbers from multiple
+; processors without causing unnecessary software overhead.
+;
+; Supposedly there is a 48 bit counter that we may be able to use
+; with SystemPro XL, and ProLiant systems, unfortunately it does
+; not appear that any OS is currently using this feature, so
+; its dependability may be suspect.
+;
+; JSL
+;
+
+;
+; Essentially all we are doing is always using the timer value on P0.
+; The indexed_io is a mechanism for one processor to access IOSPACE
+; on another processor's IOSPACE. I suspect this will have a greater
+; impact on performance than just reading the timer locally.
+; By using the indexed_io you are gauranteed of going out on the bus.
+;
+; But, hey if the user understands anything about performance, they
+; know that there will be some amount of overhead each time you make
+; this KeQueryPerformanceCounter call.
+;
+
+;
+; Increment the Retry counter now for convenience
+;
+
+ inc dword ptr RetryPerfCount+4
+
+;
+; This is Belize specific.
+;
+
+ cmp _SpType, SMP_SYSPRO2
+ jne timer_p0
+
+
+ ;
+ ; Only use Indexed_IO on a nonP0 processor
+ ;
+
+ cmp byte ptr PCR[PcHal.PcrNumber], 0 ; is this the processor
+ je timer_p0 ; which updates HalpPerfCounter?
+
+ ;
+ ; So read the timer of P0.
+ ;
+
+ push ebx
+ mov bl, 0
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ; Latch PIT Ctr 0 command.
+ INDEXED_IO_WRITE bl,TIMER1_CONTROL_PORT0,al
+ IODelay
+ INDEXED_IO_READ bl,TIMER1_DATA_PORT0 ; Read PIT Ctr 0, LSByte.
+ movzx ecx, al
+ INDEXED_IO_READ bl,TIMER1_DATA_PORT0 ; Read PIT Ctr 0, MSByte.
+ IODelay
+ mov ch,al ; (CX) = PIT Ctr 0 count.
+ pop ebx
+
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+ jmp short TimerValDone
+
+timer_p0:
+
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+
+
+
+TimerValDone:
+
+ mov al, PCR[PcHal.PcrNumber] ; get current processor #
+
+;
+; This is Belize specific.
+;
+
+ cmp _SpType, SMP_SYSPRO2
+ je NoCPU0Update
+
+;
+; If not on P0 then make sure P0 isn't in the process of
+; of updating its timer. Do this by checking the status
+; of the PIC using indexed_io.
+; Make sure that only one thread at time reads P0 PIC.
+;
+
+ cmp al, 0 ; Are we p0
+ je NoCPU0Update
+
+;
+; Check IRQL at PO before going any further
+;
+
+ push edx
+ mov edx, _HalpProcessorPCR[0] ; PCR of processor 0
+ cmp byte ptr ds:[edx].PcIrql,CLOCK2_LEVEL
+ pop edx
+ jb short NoCPU0Update
+ push ebx
+
+Kqpc11p:
+;
+; Check P0 PIC and confirm Timer Interrupt status.
+; Perform Spin Lock before reading P0 PIC.
+;
+
+ pushfd
+ cli
+ lea ebx, _Halp8254Lock
+ ACQUIRE_SPINLOCK ebx, Kqpc198p ; Spin if another thread is here
+ INDEXED_IO_READ 0,PIC1_PORT1 ; read CPU 0 port 21 for masks
+ RELEASE_SPINLOCK ebx
+ popfd
+ pop ebx
+ test al, 1h ; check for IRQ 0 masked off
+ mov al, PCR[PcHal.PcrNumber] ; get current processor #
+ jz short NoCPU0Update
+
+;
+; Try ReadAgain if below retry count.
+;
+
+ cmp RetryPerfCount+4, MAX_PERF_RETRY
+ ja short NoCPU0Update
+
+ReadAgain:
+;
+; This readagain is only executed when P0 is
+; at CLOCK2_LEVEL or greater.
+; AND when Timer IRQ is active (ie interrupt in progress).
+; This is done to close the window of an interrupt
+; occuring and the irql hasn't been raised yet.
+;
+
+ popfd
+ jmp Kqpc11 ; go back and read again
+
+NoCPU0Update:
+
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+
+ jmp $+2 ; allow interrupt in case counter
+ ; has wrapped
+
+ pushfd
+ cli
+
+;
+; In Belize mode we do not care about this since we use the P0 clock.
+;
+
+ cmp _SpType, SMP_SYSPRO2
+ je short Kqpc35
+
+;
+; If we moved processors while interrupts were enabled, start over
+;
+
+ cmp al, PCR[PcHal.PcrNumber]
+ jne Kqpc20
+Kqpc35:
+
+
+;
+; Fetch the base value again.
+;
+
+@@: mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+ cmp eax, HalpPerfCounterLow ; did it move?
+ jne short @b ; re-read
+
+
+;
+; Compare the two reads of Performance counter. If they are different,
+; start over
+;
+
+ cmp eax, ebx
+ jne Kqpc20
+ cmp edx, esi
+ jne Kqpc20
+
+ neg ecx ; PIT counts down from 0h
+ add ecx, HalpRollOverCount
+
+;
+; In Belize mode we do not care about this since we use the P0 clock.
+;
+
+ cmp _SpType, SMP_SYSPRO2
+ je short Kqpc37
+
+ add ecx, PCR[PcHal.PcrPerfSkew]
+Kqpc37:
+
+ popfd ; restore interrupt flag
+
+ xchg ecx, eax
+ mov ebx, edx
+ cdq
+
+ add eax, ecx
+ adc edx, ebx ; [edx:eax] = Final result
+
+;
+; We only want to execute this code In Belize mode.
+;
+
+ cmp _SpType, SMP_SYSPRO2
+ jne Kqpc50
+
+ ;
+ ; Ok compare this result with the last result.
+ ; We will force the value to be greater than the last value,
+ ; after we have used up all of our retry counts.
+ ;
+ ; This should slam shut that annoying Window that causes
+ ; applications to recieve a 2nd query less then the first.
+ ;
+ ; This is not an most elegant solution, but fortunately
+ ; this situation is hit only on a rare occasions.
+ ;
+ ; Yeah, I know that this value can roll over
+ ; if someone runs some perf tests, and comes back in a
+ ; few weeks and wants to run some more. In this situation
+ ; the the very first call to this function will yield an
+ ; invalid value. This is the price of the fix.
+ ;
+
+ ;
+ ; Protect the global data with a spinlock
+ ;
+
+ push ebx
+Kqpc42: pushfd
+ cli
+ lea ebx, HalpForceDataLock
+ ACQUIRE_SPINLOCK ebx, Kqpc199 ; Spin if another thread is here
+
+;
+; Compare this value to the last value, if less then
+; fix it up.
+;
+
+ cmp edx, HalpLastQueryHighValue
+ ja short Kqpc44
+
+ cmp eax, HalpLastQueryLowValue
+ ja short Kqpc44
+
+;
+; Release the spinlock.
+;
+
+ RELEASE_SPINLOCK ebx
+ popfd
+ pop ebx
+
+;
+; Try Again if below count.
+;
+
+ cmp RetryPerfCount, MAX_PERF_RETRY
+ jbe Kqpc11 ; go back and read again
+
+;
+; Exhausted retry count so Fix up the values and leave.
+;
+
+ mov eax, HalpLastQueryLowValue
+ inc eax
+ mov edx, HalpLastQueryHighValue
+
+ jmp short Kqpc50
+
+Kqpc44:
+;
+; Save off the perf values for next time.
+;
+
+ mov HalpLastQueryLowValue, eax
+ mov HalpLastQueryHighValue, edx
+
+;
+; Release the spinlock.
+;
+
+ RELEASE_SPINLOCK ebx
+ popfd
+ pop ebx
+
+
+;
+; Return the counter
+;
+
+Kqpc50:
+ ; return value is in edx:eax
+
+;
+; Return the freq. if caller wants it.
+;
+
+ or dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc99 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc99:
+ pop edi ; remove locals
+ pop edi ; restore regs
+ pop esi
+ pop ebx
+
+ stdRET _KeQueryPerformanceCounter
+
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc11>
+
+;
+; This is just where we are spinning while we are waiting to read the PIC
+;
+Kqpc198p: popfd
+ SPIN_ON_SPINLOCK ebx,<Kqpc11p>
+;
+; This is just where we are spinning while waiting global last perf data
+;
+Kqpc199: popfd
+ SPIN_ON_SPINLOCK ebx,<Kqpc42>
+
+stdENDP _KeQueryPerformanceCounter
+; endmod
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+;
+; (esp) - base of trap frame
+;
+
+;
+; dismiss interrupt and raise Irql
+;
+
+Hci10:
+ push CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,CLOCK_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; Update performance counter
+;
+
+ mov eax, HalpRollOverCount
+ xor ebx, ebx
+ add HalpPerfCounterLow, eax ; update performace counter
+ adc HalpPerfCounterHigh, ebx
+
+ cmp _HalpClockWork, ebx
+ jz short Hci20
+
+ cmp _HalpClockMcaQueueDpc, bl
+ jz short Hci20
+
+ mov _HalpClockMcaQueueDpc, bl
+
+;
+; Queue MCA Dpc
+;
+ stdCall _HalpMcaQueueDpc
+
+Hci20:
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; (ebp) = address of trap frame
+; (eax) = time increment
+;
+ mov eax, TIME_INCREMENT_10MS
+
+ mov ebx, _HalpIpiClock ; Emulate clock ticks to any processors?
+ or ebx, ebx
+ jz _KeUpdateSystemTime@0
+
+;
+; On the SystemPro we know the processor which needs an emulated clock tick.
+; Just set that processors bit and IPI him
+;
+
+@@:
+ movzx ecx, _HalpFindFirstSetRight[ebx] ; lookup first processor
+ btr ebx, ecx
+ mov ecx, _HalpProcessorPCR[ecx*4] ; PCR of processor
+ mov [ecx].PcHal.PcrIpiClockTick, 1 ; Set internal IPI event
+ or ebx, ebx ; any other processors?
+ jnz short @b ; yes, loop
+
+ stdCall _HalRequestIpi, <_HalpIpiClock> ; IPI the processor(s)
+
+ mov eax, TIME_INCREMENT_10MS
+ jmp _KeUpdateSystemTime@0
+
+Hci100:
+ add esp, 8
+ SPURIOUS_INTERRUPT_EXIT
+
+stdENDP _HalpClockInterrupt
+
+
+ page ,132
+ subttl "NonPrimaryClockTick"
+;++
+;
+; VOID
+; HalpNonPrimaryClockInterrupt (
+; );
+;
+; Routine Description:
+; ISR for clock interrupts for every processor except one.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+ ENTER_DR_ASSIST Hni_a, Hni_t
+cPublicProc _HalpNonPrimaryClockInterrupt ,0
+ ENTER_INTERRUPT Hni_a, Hni_t
+
+; Dismiss interrupt and raise irql
+
+ push CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,CLOCK_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hni100
+
+ ; TOS const PreviousIrql
+ stdCall _KeUpdateRunTime,<dword ptr [esp]>
+
+ INTERRUPT_EXIT ; will do an iret
+
+Hni100:
+ add esp, 8
+ SPURIOUS_INTERRUPT_EXIT
+
+stdENDP _HalpNonPrimaryClockInterrupt
+
+ page ,132
+ subttl "Emulate NonPrimaryClockTick"
+;++
+;
+; VOID
+; HalpSWNonPrimaryClockTick (
+; );
+;
+; Routine Description:
+; On the SystemPro the second processor does not get it's own clock
+; ticks. The HAL emulates them by sending an IPI which sets an overloaded
+; software interrupt level of SWCLOCK_LEVEL. When the processor attempts
+; to lower it's irql level below SWCLOCK_LEVEL the soft interrupt code
+; lands us here as if an interrupt occured.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+ ENTER_DR_ASSIST Hsi_a, Hsi_t
+
+ public _HalpSWNonPrimaryClockTick
+_HalpSWNonPrimaryClockTick proc
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hsi_a, Hsi_t
+
+ public _HalpSWNonPrimaryClockTick2ndEntry
+_HalpSWNonPrimaryClockTick2ndEntry:
+
+; Save previous IRQL and set new priority level
+
+ push fs:PcIrql ; save previous IRQL
+ mov byte ptr fs:PcIrql, SWCLOCK_LEVEL ; set new irql
+ btr dword ptr fs:PcIRR, SWCLOCK_LEVEL ; clear the pending bit in IRR
+
+ sti
+
+ ; TOS const PreviousIrql
+ stdCall _KeUpdateRunTime,<dword ptr [esp]>
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+
+_HalpSWNonPrimaryClockTick endp
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, TIME_INCREMENT_10MS ; yes, use 10ms clock
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+
+_TEXT ends
+ end
+
diff --git a/private/ntos/nthals/halsp/i386/spdetect.asm b/private/ntos/nthals/halsp/i386/spdetect.asm
new file mode 100644
index 000000000..c040fa155
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spdetect.asm
@@ -0,0 +1,559 @@
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+;
+; Module Name:
+;
+; spdetect.asm
+;
+; Abstract:
+;
+; This modules detects a SystemPro or compatible. It is INCLUDED
+; by SPIPI and other binaries whom need to know how to detect a
+; SystemPro type MP machine (ie, setup). It must assemble more or
+; less standalone and run in protect mode.
+;
+; Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+; Revision History:
+;
+;--
+
+include halsp\i386\spmp.inc
+include callconv.inc ; calling convention macros
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+
+; spSystemType: SystemType is read from 0c80-0c83h.
+; 0c80-0c81: 0e11: Compressed CPQ (5 bit encoding).
+; 0c82: System Board type.
+; 0c83: System Board revision level.
+
+spSystemCpuTable dd 0e1101h ; CPQ01xx 386 ASP
+ dd 0e1111h ; CPQ11xx 486 ASP
+ dd 0e1150h ; CPQ50xx plug in processor
+ dd 0e1159h ; CPQ59xx plug in processor
+ dd 0e115bh ; CPQffxx plug in processor
+ dd 0e1115h ; CPQ15xx (smp version)
+ dd 0e1152h ; CPQ15xx (smp version)
+ dd 0e1108h ; CPQ15xx
+ dd 0592a0h ; ALRa0xx PowerPro
+ dd 0592b0h ; ALRb0xx PowerPro plug in processor
+ dd 047232h ; Acer SP clone (4p version)
+ dd 246c00h ; ICL MX
+ dd 246c02h ; ICL (acer 700xx)
+ dd 352310h ; Micronycs MPro motherboard
+ dd 352311h ; Micronycs MPro
+ dd 0592a1h ; ALRa1xx PowerPro (DX2-66 mobo)
+ dd 0592a2h ; ALRa2xx PowerPro (reserved mobos)
+ dd 0592b1h ; ALRb1xx PowerPro (reserved p2's)
+ dd 4dc901h ; Siemens Nixdorf PCE-4T/33
+ dd 4dc950h ; Siemens Nixdorf PCE-4T/33
+ dd 047219h ; AcerFrame 700
+ dd 047232h ; AcerFrame 3000MP560
+ dd 0h
+CPUTABLE_SIZE equ ($-spSystemCpuTable)/4
+
+; Types match up to CpuTable.
+spSystemTypeTable db SMP_SYSPRO1 ; CPQ01xx 386 ASP
+ db SMP_SYSPRO1 ; CPQ11xx 486 ASP
+ db SMP_SYSPRO1 ; CPQ50xx plug in processor
+ db SMP_SYSPRO1 ; CPQ59xx plug in processor
+ db SMP_SYSPRO1 ; CPQffxx plug in processor
+ db SMP_SYSPRO2 ; CPQ15xx (smp version)
+ db SMP_SYSPRO2 ; CPQ15xx (smp version)
+ db SMP_SYSPRO1 ; CPQ15xx
+ db SMP_SYSPRO1 ; ALRa0xx PowerPro
+ db SMP_SYSPRO1 ; ALRb0xx PowerPro
+ db SMP_ACER ; Acer SP clone (4p version)
+ db SMP_ACER ; ICL MX
+ db SMP_ACER ; ICL (acer 700xx)
+ db SMP_SYSPRO1 ; Micronycs MPro motherboard
+ db SMP_SYSPRO1 ; Micronycs MPro
+ db SMP_SYSPRO1 ; ALRa1xx PowerPro (DX2-66 mobo)
+ db SMP_SYSPRO1 ; ALRa2xx PowerPro (reserved mobos)
+ db SMP_SYSPRO1 ; ALRb1xx PowerPro (reserved p2's)
+ db SMP_SYSPRO1 ; Siemens Nixdorf PCE-4T/33
+ db SMP_SYSPRO1 ; Siemens Nixdorf PCE-4T/33
+ db SMP_ACER ; AcerFrame 700
+ db SMP_ACER ; AcerFrame 3000MP560
+
+TYPETABLE_SIZE equ ($-spSystemTypeTable)
+.errnz (CPUTABLE_SIZE - TYPETABLE_SIZE - 1)
+
+;
+; Order to check eisa ports in..
+;
+SpPortOrder dw 0000, 0F000h, 0C000h, 0D000h, -1
+
+ public _SpType, _SpCpuCount, _SpProcessorControlPort
+_SpType db -1 ; Lowest SMP_SYSPRO type found
+_SpCpuCount db 0 ; # of Cpus found
+_SpProcessorControlPort dw 00000h+PCR_OFFSET
+ dw 0F000h+PCR_OFFSET
+ dw 0C000h+PCR_OFFSET
+ dw 0D000h+PCR_OFFSET
+RestoreESP dd 0
+RestoreESP1 dd 0
+SpCOMPAQ db 'COMPAQ'
+SpEISA db 'EISA'
+Sp80386 db '80386'
+Sp80486 db '80486'
+
+_DATA ends
+
+ page ,132
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; BOOLEAN
+; DetectSystemPro (
+; OUT PBOOLEAN IsConfiguredMp
+; );
+;
+; Routine Description:
+; This function is only called on EISA machines
+;
+; Determines the type of system (specifically for eisa machines).
+;
+; Arguments:
+; IsConfiguredMp - If the machine is a SystemPro, then this value is
+; set to TRUE if it's an MP SystemPro, else FALSE.
+;
+; Return Value:
+; FALSE - not a supported machine for this HAL
+; TRUE - is SystemPro
+; etc...
+;
+;--
+cPublicProc _DetectSystemPro ,1
+
+ push edi
+ push esi
+ push ebx ; Save C Runtime
+
+ movzx edx, SpPortOrder[0] ; Check system board for
+ call CheckEisaCard ; SystemPro belize ID
+if 0
+ or eax, eax
+ jz dsp_idnotknown
+endif
+ cmp al, SMP_SYSPRO2
+ je dsp_belize ; if belize, go count belize style
+
+ xor ebx, ebx ; CpuCount
+ xor esi, esi ; Base EisaCard address
+
+dsp10: movzx edx, SpPortOrder[esi*2]
+ cmp dx, -1 ; End of list?
+ je short dsp30 ; Yes, done
+
+ call CheckEisaCard ; Check Eisa card for cpu
+ or eax, eax ; If not cpu, then skip it
+ jz short dsp20
+
+ cmp _SpType, al
+ jc @f
+ mov _SpType, al ; SpType = min(SpType, eax)
+@@:
+ cmp ebx, 4 ; MaxSupported CPUs already found?
+ jae dsp20 ; Yes, then skip this one
+
+ movzx edx, SpPortOrder[esi*2]
+ add edx, PCR_OFFSET
+ mov _SpProcessorControlPort[ebx*2], dx
+
+ inc ebx ; CpuCount += 1
+
+dsp20: inc esi ; Next EisaCard I/O addr to check
+ jmp short dsp10
+
+dsp30: xor eax, eax ; Assume FALSE
+ifdef SETUP
+ cmp bl, 2 ; Did we find at least 2 CPUs?
+else
+ cmp bl, 1 ; Did we find at least 1 CPU?
+endif
+ jc short SpExit ; No, then exit
+
+ mov _SpCpuCount, bl
+ mov al, 1 ; return non-zero
+
+ mov ebx, dword ptr [esp+16]
+ mov byte ptr [ebx], al ; *IsConfiguredMp = TRUE
+
+SpExit: pop ebx
+ pop esi
+ pop edi
+ stdRET _DetectSystemPro
+
+;-----
+
+dsp_belize:
+ mov _SpType, al ; SpType = SYSPRO2
+
+ ;
+ ; Put Belize SystemPro into Symmetric mode
+ ;
+
+ mov dx, SMP_MODE_PORT
+ mov al, SMP_SYMMETRICAL_MODE
+ out dx, al
+
+ ;
+ ; Count CPUs, belize style. And assign logcal IDs to CPUs
+ ;
+ xor ecx,ecx ;physical cpu
+ xor ebx,ebx ;logical cpu
+
+dsp50:
+ mov dx,SMP_INDEX_PORT
+ mov al,cl ; al = physical CPU slot number
+ out dx, al ; select physical CPU slot in al
+ mov dx,SMP_ASSIGNMENT_PORT
+ in al,dx ; read CPU number
+ cmp al,SMP_MAX_PROCESSORS ; Q:Valid CPU?
+ jae short dsp60 ; n:Check next physical CPU slot
+ mov al,bl ; y:Make physical CPU a logical CPU
+ out dx,al
+ inc ebx ; next logical CPU to assign
+dsp60:
+ inc ecx ; next physical CPU slot to check
+ cmp ecx,SMP_MAX_PROCESSORS
+ jb short dsp50 ; look in next cpu slot
+
+ jmp short dsp30 ; ebx = number of cpus found
+
+;-----
+if 0 ; Note: this code is not fully working (did not pass hct's)
+public dsp_idnotknown
+dsp_idnotknown:
+;
+; The eisa ID was not recongonized - attempt to use the protect mode
+; int-15 interface to determine if this is a SystemPro compatible
+; computer. Any SystemPro detected in this manner is assumed to
+; be of type SMP_SYSPRO1 which only has 2 processors.
+;
+; Note: There is a fair amount of paranoia in the following code
+; becuase we trust the rom as little as possible.
+;
+
+ xor eax, eax
+ xor ecx, ecx
+ mov cx, ss ; Verify SS value is what it is
+ cmp ecx, KGDT_R0_DATA ; expect it to be; otherwise this code
+ jne short SpExit ; can't work
+
+ pushf ; Save current DF & EF
+
+ sub esp, 15*8
+ sidt fword ptr [esp] ; get IDT address
+ mov esi, dword ptr [esp+2] ; (esi) = IDT
+ mov edi, esp ; (edi) = address to copy vectors to
+
+ push es ; Save selectors in case rom
+ push ds ; trashes state
+ push fs
+ push gs
+ push esi
+ push ebp
+ cld
+ cli
+ pushf
+
+ ;
+ ; Save and hook some IDT vectors. If we get some type of trap
+ ; here or in the rom, then we will restore the state and return
+ ; back that a systempro was not detected
+ ;
+
+ mov eax, esi
+ mov ecx, 15*8/4
+ rep movsd ; Save IDT vectors
+
+ mov RestoreESP, esp ; Save current ESP for restore
+
+ mov ecx, offset FLAT:dsp_handlefault
+ mov dx, cs
+ shl edx, 16
+ mov dx, cx
+ mov cx, 08E00h ; Install int32 gate for vectors
+
+ mov [eax+0*8+0] , edx
+ mov [eax+0*8+4] , ecx ; Trap IDT 0 Divide Error
+ mov [eax+4*8+0] , edx
+ mov [eax+4*8+4] , ecx ; Trap IDT 4 INTO
+ mov [eax+5*8+0] , edx
+ mov [eax+5*8+4] , ecx ; Trap IDT 5 BOUND
+ mov [eax+6*8+0] , edx
+ mov [eax+6*8+4] , ecx ; Trap IDT 6 Invalid OpCode
+ mov [eax+11*8+0], edx
+ mov [eax+11*8+4], ecx ; Trap IDT 11 Segment not present
+ mov [eax+12*8+0], edx
+ mov [eax+12*8+4], ecx ; Trap IDT 12 Stack fault
+ mov [eax+13*8+0], edx
+ mov [eax+13*8+4], ecx ; Trap IDT 13 GP fault
+ mov [eax+14*8+0], edx
+ mov [eax+14*8+4], ecx ; Trap IDT 14 Page fault
+
+ ;
+ ; Map in 64K of the ROM in order to use protect mode int-15 interface.
+ ; (see Compaq eisa spec)
+ ;
+ stdCall _HalpMapPhysicalMemory, <0f0000h, 16> ; map 64K of ROM
+ mov ebp, eax ; save ROM starting address
+
+ ;
+ ; Verify there is a ROM, search for the word 'COMPAQ' in the ROM
+ ; addresses FE000-FE0FF. (see Compaq eisa spec)
+ ;
+ lea esi, SpCOMPAQ ; 'COMPAQ'
+ mov ebx, 6 ; strlen ('COMPAQ')
+ lea edi, [ebp+0e000h] ; address to scan
+ mov ecx, 0ffh ; length of scan
+ call SpScanForString
+ jne dsp_handlefault ; if not found then abort
+
+ ;
+ ; Also verify the 'EISA' work at rom address FFFD0-FFFFF
+ ; (see Compaq eisa spec)
+ ;
+ lea esi, SpEISA ; 'EISA'
+ mov ebx, 4 ; strlen ('EISA')
+ lea edi, [ebp+0ffd0h] ; address to scan
+ mov ecx, 02fh ; length of scan
+ call SpScanForString
+ jne dsp_handlefault ; if not found then abort
+
+ ;
+ ; Look in slot 11 and slot 15 for processors
+ ;
+ sub esp, 400 ; make space for Config Data Block
+ mov ecx, 11 ; check slot 11 first
+ xor ebx, ebx ; assume no processors found
+
+dsp_95:
+ push ebp ; save virtual rom address
+ push ecx ; save current slot #
+ push ebx ; save # processors found
+
+ xor eax, eax
+ lea edi, [esp+12]
+ mov ecx, 300/4
+ rep stosd ; clear destionation buffer
+
+ mov ax, 0D881h ; Read Config Info, 32bit
+ lea esi, [esp+12] ; destionation address
+
+ mov RestoreESP1, esp ; Some roms don't iret correctly
+ sub esp, 10h ; Some roms clobber some stack
+ pushf
+ push cs
+ lea ebx, [ebp+0f859h] ; 'industry standard' int-15 address
+ call ebx ; INT-15 (trashes most registers)
+ mov esp, RestoreESP1 ; restore ESP
+ jc short dsp_110 ; Not valid, check next slot
+
+ ;
+ ; Check type field
+ ;
+ lea edi, [esp+12+23h] ; address of type string
+ lea esi, Sp80386 ; '80386'
+ mov ebx, 5 ; strlen ('80386')
+ mov ecx, 80
+ call SpScanForString
+ je short dsp_105
+
+ lea edi, [esp+12+23h] ; address of type string
+ lea esi, Sp80486 ; '80486'
+ mov ebx, 5 ; strlen ('80486')
+ mov ecx, 80
+ call SpScanForString
+ jne short dsp_110
+
+dsp_105:
+ ; string was either 80386 or 80486
+ inc dword ptr [esp] ; count one more processor
+
+dsp_110:
+ pop ebx ; (ebx) = number processors found
+ pop ecx ; (ecx) = slot #
+ pop ebp ; (ebp) = virtual rom address
+
+ or ebx, ebx ; if a processor is not in the first
+ jz short dsp_handlefault ; slot, then don't look in second
+
+ cmp ebx, 2 ; if # of processors is trash
+ ja short dsp_handlefault ; then abort
+
+ mov eax, ecx
+ cmp eax, 11 ; Did we just test slot 11?
+ mov ecx, 15
+ je dsp_95 ; Yes, now test 15
+ cmp eax, 15 ; Did we just test slot 15?
+ je short dsp_cleanup ; Yes, then we are done
+
+ ; slot # isn't 11 or 15, abort
+
+dsp_handlefault: ; Sometype of fault, or abort
+ mov eax, KGDT_R0_DATA ; make sure ss has the correct value
+ mov ss, ax
+ xor ebx, ebx ; No processors found
+
+dsp_cleanup:
+; (ebx) = # of processors
+ mov esp, SS:RestoreESP ; Make sure esp is correct
+
+ popf
+ pop ebp
+ pop edi ; (edi) = IDT address
+ pop gs ; restore selectors
+ pop fs
+ pop ds
+ pop es
+ mov esi, esp ; (esi) = original IDT vectors
+ mov ecx, 15*8/4
+ rep movsd ; restore IDT vectors
+ add esp, 15*8 ; cleanup stack
+ popf
+
+ mov _SpType, SMP_SYSPRO1 ; assume original systempro
+
+ cmp ebx, 2 ; at least 2 processors found?
+ jc short dsp_150 ; no, continue
+;
+; Verify that the second processor board is enabled
+;
+ movzx edx, SpPortOrder[1*2]
+ add edx, EBC_OFFSET ; (edx) = 0zC84
+ in al, dx ; Read control bits
+ test al, 1 ; Is Eisa CPU board enabled?
+ jnz short dsp_150 ; Yes, continue
+ dec ebx ; don't count it
+
+dsp_150:
+ jmp dsp30 ; exit
+endif
+
+stdENDP _DetectSystemPro
+
+;++
+; SpScanForString
+;
+; Routine Description:
+; Scans address range looking for matching string
+;
+; Arguments:
+; (edi) = Start of address range to scan
+; (ecx) = Length of address range
+; (esi) = String to scan for
+; (ebx) = Length of string
+;
+; Returns:
+; ZR - String found
+; NZ - String not found
+;
+;--
+SpScanForString proc
+ sub ecx, ebx ; don't go past end
+ inc ecx
+
+ mov al, [esi] ; (al) = first char to scan for
+ inc esi ; skip past first char
+ dec ebx
+
+ss10: repne scasb ; look for first byte
+ jecxz short ss20 ; byte found? No, exit
+
+ push ecx
+ push edi
+ push esi
+ mov ecx, ebx ; length of string to compare
+ repe cmpsb ; is string at this location?
+ or ecx, ecx ; ZF if strings match
+ pop esi
+ pop edi
+ pop ecx
+
+ jnz short ss10 ; continue looking
+ ret ; ZR
+
+ss20: inc ecx ; NZ
+ ret
+
+SpScanForString endp
+
+
+;++
+; CheckEisaCard
+;
+; Routine Description:
+; Used only by DetectSystemPro.
+;
+; Arguments:
+; (edx) = Eisa ID port to check
+;
+; Returns:
+; (eax) = 0 card was not a valid cpu
+; non-zero Cpu type
+;
+;--
+CheckEisaCard proc
+ push edi
+ push esi
+ push ebx
+
+ mov esi, edx
+ add edx, PRODUCT_ID_OFFSET ; Product ID port
+
+ xor eax, eax
+ in al, dx ; 0zC80
+ test al, 80h ; if bit 8 off?
+ jnz short NoMatch ; no, then not an Eisa card
+
+ shl eax, 8
+ inc edx
+ in al, dx ; 0zC81
+ shl eax, 8
+ inc edx
+ in al, dx ; (eax)=dword of ports 0zC80-0zC82
+
+ mov ecx, CPUTABLE_SIZE ; Scan CPU table looking for
+ lea edi, spSystemCpuTable ; matching board ID
+ repne scasd
+ jecxz short NoMatch ; Was it found?
+
+ sub ecx, CPUTABLE_SIZE-1
+ neg ecx ; (ecx) = index CPU was found at
+ movzx ecx, byte ptr spSystemTypeTable[ecx]
+
+ or esi, esi ; SystemBoard?
+ jz short @f ; Yes, then it is assumed enabled
+
+ cmp cl, SMP_ACER ; If acer, assume it's enabled
+ je short @f ; (machine incorrectly reports
+ ; 'disable' on every other proc)
+ mov edx, esi
+ add edx, EBC_OFFSET ; (edx) = 0zC84
+ in al, dx ; Read control bits
+ test al, 1 ; Is Eisa CPU board enabled?
+ jz short NoMatch ; No, then skip it
+@@:
+ mov eax, ecx
+ jmp short cei_exit
+NoMatch:
+ xor eax, eax
+cei_exit:
+ pop ebx
+ pop esi
+ pop edi
+ ret
+
+CheckEisaCard endp
+
+_TEXT ENDS
diff --git a/private/ntos/nthals/halsp/i386/spipi.asm b/private/ntos/nthals/halsp/i386/spipi.asm
new file mode 100644
index 000000000..921c5d0e1
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spipi.asm
@@ -0,0 +1,750 @@
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; spipi.asm
+;
+;Abstract:
+;
+; SystemPro IPI code.
+; Provides the HAL support for Interprocessor Interrupts for hte
+; MP SystemPro implementation.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+;--
+.386p
+; .xlist
+
+;
+; Include SystemPro detection code
+;
+
+include i386\spdetect.asm
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include i386\kimacro.inc
+include i386\ix8259.inc
+include callconv.inc ; calling convention macros
+
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KeRaiseIrql,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalpInitializePICs,0
+ EXTRNP _HalDisplayString,1
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalDisableSystemInterrupt,2
+ EXTRNP _HalpMapPhysicalMemory,2
+ EXTRNP _HalpAcerInitializeCache,0
+ extrn _HalpDefaultInterruptAffinity:DWORD
+ extrn _HalpActiveProcessors:DWORD
+ extrn _HalpCpuCount:DWORD
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ public _HalpFindFirstSetRight, _Sp8259PerProcessorMode
+_HalpFindFirstSetRight db 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+_Sp8259PerProcessorMode db 0
+
+align 4
+ public _HalpProcessorPCR
+_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
+
+_HalpPINTAddrTable label word
+ dw SMP_MPINT0
+ dw SMP_MPINT1
+ dw SMP_MPINT3
+ dw SMP_MPINT4
+ dw SMP_MPINT5
+ dw SMP_MPINT6
+ dw SMP_MPINT7
+ dw SMP_MPINT8
+ dw SMP_MPINT9
+ dw SMP_MPINT10
+ dw SMP_MPINT11
+ dw SMP_MPINT12
+ dw SMP_MPINT13
+ dw SMP_MPINT14
+ dw SMP_MPINT15
+
+HALPPINTADDRTABLESIZE equ ($-_HalpPINTAddrTable)/TYPE(_HalpPINTAddrTable)
+
+BadHalString db 'HAL: SystemPro HAL.DLL cannot be run on non SystemPro'
+ db '/compatible', cr,lf
+ db ' Replace the hal.dll with the correct hal', cr, lf
+ db ' System is HALTING *********', 0
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . Enable IPI interrupt (makes sense for P1, P2, ...).
+; . Save Processor Number in PCR.
+; . if (P0)
+; . determine what kind of system is it,
+; . if (NotSysProCompatible) Halt;
+; . program VECTOR_PORT to accept IPI at IRQ13.
+; . InitializePICs.
+; . if (P1)
+; . Save ProcesserControlPort (PCR) to PCRegion, per processor.
+; . Enable PINTs on CPU.
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor ,1
+ ;
+ ; Initialize various PCR values
+ ; PcIDR in PCR - enable slave IRQ
+ ; PcStallScaleFactor - bogusly large value for now
+ ; PcHal.PcrNumber - logical processor #
+ ; PcHal.PcrPic - Set if processor has it's own pics.
+ ; The SystemPro only defines one pic set on P0, but some clones
+ ; put more pics on each other processor. This isn't vastly
+ ; better, but it is better then processor. This isn't vastly 'em
+ ; PcHal.PcrIpiType - Address to jmp to once ipi is verified.
+ ; This is done to optimize how to deal with a varity of 'work-
+ ; arounds' due to non-smp nature of SP clones
+ ;
+
+ cli
+ mov fs:PcIDR, 0fffffffbh
+ movzx eax, byte ptr [esp+4]
+ mov fs:PcHal.PcrNumber, al ; Save processor # in PCR
+ lock bts _HalpActiveProcessors, eax
+ lock inc _HalpCpuCount
+ mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
+ mov dword ptr fs:PcHal.PcrPerfSkew, 0
+ mov fs:PcHal.PcrIpiSecondLevelDispatch, offset _HalpNo2ndDispatch
+
+ ;
+ ; Initialize IDT vector for IPI interrupts
+ ; KiSetHandlerAddressToIDT(I386_80387_VECTOR, HalpIrq13Handler);
+ ;
+ mov ebx, fs:PcIDT
+ lea ecx, _HalpIrq13Handler
+ add ebx, (PRIMARY_VECTOR_BASE + 13) * 8
+ mov word ptr [ebx+0], cx
+ shr ecx, 16
+ mov word ptr [ebx+6], cx
+
+ ;
+ ; Save away flat address of our PCR - (used in emulating clock ticks
+ ; on systempro p1 which doesn't have it's own clock tick)
+ ;
+ mov ecx, fs:PcSelfPcr ; Flat address of this PCR
+ mov _HalpProcessorPCR[eax*4], ecx ; Save it away
+
+
+ or eax, eax
+ jnz ipi_10 ; If !p0 then ipi_10
+
+ mov fs:PcHal.PcrPic, 1 ; P0 has a pic
+ mov fs:PcHal.PcrIpiType, offset P0Ipi
+
+ ; Run on P0 only
+
+ sub esp, 4
+ stdCall _DetectSystemPro,<esp> ; Which type of SystemPro
+ add esp,4
+
+ or eax, eax
+ jz NotSystemPro
+
+ lock or _HalpDefaultInterruptAffinity, 1
+
+ cmp _SpType, SMP_SYSPRO2 ; Belize SystemPro?
+ je short ipi_belize
+
+ ;
+ ; Set all processors IPI to irq13
+ ;
+
+ mov al, PRIMARY_VECTOR_BASE + 13
+ mov dx, 0FC68h ; Set SystemPro P1 Interrupt
+ out dx, al ; Vector to irq13
+
+ cmp _SpType, SMP_ACER ; Acer? Then set other acer
+ jne short ipi_notacer ; processor ports as well
+
+ mov dx, 0C028h
+ out dx, al ; set P2 Interrupt Vector
+ mov dx, 0C02Ch
+ out dx, al ; set P3 Interrupt Vector
+
+ stdCall _HalpAcerInitializeCache
+
+ mov dx, 0C06h ; Check for ASMP or SMP mode
+ in al, dx
+ test al, 10h ; SMP mode bit set?
+ jz short @f ; No, then ASMP mode
+
+ cmp al, 0ffh ; Ambra doesn't implement
+ je short @f ; this port...
+
+
+;; bugbug - problems with bootup device
+;; mov _Sp8259PerProcessorMode, SP_M8259 + SP_SMPDEVINTS
+
+ mov _Sp8259PerProcessorMode, SP_M8259 ; Set to use multiple pic
+@@: jmp short ipi_05 ; implementation
+
+ipi_belize:
+ ;
+ ; Machine is Belize SystemPro
+ ; Set for multiple 8259s, statically distribute device interrupts, and
+ ; use symmetric clock interrupt.
+ ;
+
+ mov _Sp8259PerProcessorMode, SP_M8259 + SP_SMPDEVINTS + SP_SMPCLOCK
+
+ stdCall HalpInitializeBelizeIC
+
+ipi_notacer:
+ipi_05:
+ ; enable IPI vector
+ stdCall _HalEnableSystemInterrupt,<PRIMARY_VECTOR_BASE+13,IPI_LEVEL,0>
+
+ ; Other P0 initialization would go here
+
+ jmp short ipi_30
+
+ipi_10:
+ mov fs:PcHal.PcrIpiType, offset IpiWithNoPic ; default it
+
+ test _Sp8259PerProcessorMode, SP_M8259 ; 8259 on this processor?
+ jz short ipi_20
+
+ ;
+ ; SP machine is set for SMP mode - which has 2 8259s per processor
+ ;
+ mov fs:PcHal.PcrPic, 1 ; Set to use pic on this proc
+
+ cmp _SpType, SMP_ACER
+ jne short ipi_notacer2
+ ;
+ ; Machine is in ACER "SMP" mode - well, this fine SMP mode happens
+ ; to have an asymmetric clock interrupt, so we need to emulate non-
+ ; P0 clock interrupts to it just like we do on the standard SystemPro
+ ;
+ mov fs:PcHal.PcrIpiType, offset IpiWithPicButNoClock
+ stdCall _HalpInitializePICs ; Init this processors PICs
+
+ipi_notacer2:
+ cmp _SpType, SMP_SYSPRO2
+ jne short ipi_notbelize2
+
+ ;
+ ; Machine is Belize SystemPro
+ ;
+ stdCall HalpInitializeBelizeIC
+
+ipi_notbelize2:
+ ;
+ ; Enable IPI vector for non-P0 cpu
+ ;
+ stdCall _HalEnableSystemInterrupt,<PRIMARY_VECTOR_BASE+13, IPI_LEVEL,0>
+
+ipi_20:
+
+ ; Specific non-P0 initialization would go here
+
+ipi_30:
+ movzx eax, byte ptr [esp+4] ; cpu number
+ mov dx, _SpProcessorControlPort[eax*2] ; Port value for this processor
+
+ mov fs:PcHal.PcrControlPort, dx ; Save port value
+ mov fs:PcHal.PcrIpiClockTick, 0 ; Set to not signaled
+
+ cmp _SpType, SMP_SYSPRO2
+ je short @f
+
+ in al, dx ; remove disabled & signaled
+ and al, not (INTDIS or PINT) ; bits
+ out dx, al
+@@:
+ stdRET _HalInitializeProcessor
+
+NotSystemPro:
+; on a non system pro. Display message and HALT system.
+ stdCall _HalDisplayString, <offset BadHalString>
+ hlt
+
+stdENDP _HalInitializeProcessor
+
+
+;++
+;
+; VOID
+; HalpInitializeBelizeIC(
+; VOID
+; );
+;
+;Routine Description:
+;
+; Initialize interrupt control for the Belize SystemPro
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc HalpInitializeBelizeIC, 0
+ push ebx
+
+ ;
+ ; Belize IPIs go to Belize Irq13 handler
+ ;
+ mov ebx, fs:PcIDT
+ lea ecx, _HalpBelizeIrq13Handler
+ add ebx, (PRIMARY_VECTOR_BASE + 13) * 8
+ mov word ptr [ebx+0], cx
+ shr ecx, 16
+ mov word ptr [ebx+6], cx
+
+ ;
+ ; Disable irq13 sources
+ ;
+
+ mov dx, SMP_MPINT13PORT
+ mov al, (SMP_DSBL_NCPERR + SMP_DSBL_DMACHAIN + SMP_DSBL_MCERR)
+ out dx, al
+
+ ;
+ ; Disable ipi ports
+ ;
+
+ mov ecx, HALPPINTADDRTABLESIZE
+ xor ebx, ebx
+ mov al, SMP_INTx_DISABLE
+@@:
+ mov dx, _HalpPINTAddrTable[ ebx ]
+ out dx, al
+ add ebx, 2
+ loopnz short @b
+
+ stdCall _HalpInitializePICs ; Init this processors PICs
+
+ ;
+ ; Enable PINT
+ ;
+
+ mov dx, SMP_IPI_MPINTx_PORT
+ mov al, SMP_INTx_ENABLE + SMP_INTx_CLR_PINT
+ out dx, al
+
+ pop ebx
+ stdRet HalpInitializeBelizeIC
+stdENDP HalpInitializeBelizeIC
+
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalRequestIpi ,1
+
+ cmp _SpType, SMP_SYSPRO2
+ jne short ripi_10
+
+ mov eax, dword ptr [esp+4] ; (eax) = Processor bitmask
+if DBG
+ or eax, eax ; must ipi somebody
+ jz short ipibad
+
+ movzx ecx, byte ptr fs:PcHal.PcrNumber
+ bt eax, ecx ; cannot ipi yourself
+ jc short ipibad
+endif
+
+ mov dx, SMP_IPI_MASKPORT
+ or eax, (SMP_IPI_VECTOR shl 24)
+ out dx, eax
+ stdRET _HalRequestIpi
+
+
+ALIGN 4
+ripi_10:
+ mov ecx, dword ptr [esp+4] ; (ecx) = Processor bitmask
+
+if DBG
+ or ecx, ecx ; must ipi somebody
+ jz short ipibad
+
+ movzx eax, byte ptr fs:PcHal.PcrNumber
+ bt ecx, eax ; cannot ipi yourself
+ jc short ipibad
+endif
+@@:
+ movzx eax, _HalpFindFirstSetRight[ecx] ; lookup first processor to ipi
+ btr ecx, eax
+ mov dx, _SpProcessorControlPort[eax*2]
+ in al, dx ; (al) = original content of PCP
+ or al, PINT ; generate Ipi on target
+ out dx, al
+ or ecx, ecx ; ipi any other processors?
+ jnz @b ; yes, loop
+
+ stdRET _HalRequestIpi
+
+if DBG
+ipibad: int 3
+ stdRET _HalRequestIpi
+endif
+
+stdENDP _HalRequestIpi
+
+
+ page ,132
+ subttl "SystemPro Irq13 Interrupt Handler"
+;++
+;
+; VOID
+; HalpIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by inter
+; processor communication or coprocessor error.
+; Its function is to determine the sources of the interrupts and to
+; call its handler.
+;
+; If the interrupt is determined to be generated by coprocessor error,
+; this routine will lower irql to its original level, and finally invoke
+; coprocessor error handler. By doing this, the coprocessor
+; error will be handled at Irql 0 as it should be.
+;
+; N.B. This routine is specific to Compaq SystemPro. On SystemPro, the
+; IRQ13 of P0 is also used by DMA buffer chaining interrupt. Currently,
+; NO NT driver uses the DMA buffer chaining capability. For now, this
+; routine simply ignores it.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hi13_a, Hi13_t
+
+cPublicProc _HalpIrq13Handler ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
+;
+; Save previous IRQL
+;
+ push 13 + PRIMARY_VECTOR_BASE ; Vector
+ sub esp, 4 ; space for OldIrql
+;
+; Dismiss interrupt.
+;
+ mov dx, fs:PcHal.PcrControlPort
+
+ in al, dx
+ test al, PINT
+ jz Hi100 ; if not a PINT, then go Hi100
+
+;
+; The interrupt has been identified to be Inter-Processor Interrupt
+; We now dismiss the interprocessor interrupt and call its handler
+;
+
+ and al, not (PINT or INTDIS)
+ out dx, al ; clear PINT
+
+ jmp fs:[PcHal.PcrIpiType] ; Go handle ipi accordingly
+
+align 4
+IpiWithNoPic:
+;
+; This processor doesn't have a PIC
+;
+ cmp byte ptr fs:PcIrql, IPI_LEVEL ; is preview IRQL level
+ jnc short Ksi20 ; >= IPI_LEVEL?
+
+
+ ; WARNING: Some SystemPro's actually don't complete the OUT to the
+ ; ProcessorControlRegister by the return of the OUT instruction. This
+ ; code path can do a 'sti' before the pending interrupt bit is cleared
+ ; on these machines. To get around this problem we do an IN from the
+ ; ProcessorControlPort again which will cause the last OUT to complete
+ ; before the IN can.
+ in al, dx
+
+ stdCall _KeRaiseIrql, <IPI_LEVEL,esp>
+
+;
+; It also doesn't have it's own clock interrupt, see if clock interrupt
+; emulation is requested - if so raise a software interrupt to go emulate
+; it when we reach a lower IRQL
+;
+ cmp fs:PcHal.PcrIpiClockTick, 0 ; Emulate ClockTick?
+ jz short Ksi30 ; No, just go service ipi
+
+ mov fs:PcHal.PcrIpiClockTick, 0 ; yes, reset trigger
+ or dword ptr fs:PcIRR, SWClockTick ; Set SW ClockTick bit
+ jmp short Ksi30 ; go process ipi
+
+Ksi20:
+;
+; This processor is >= IPI_LEVEL, this IPI should not be here.
+;
+ in al, dx
+ or al, PINT ; re-post this IPI
+ out dx, al
+ ; clear IF bit in return EFLAGS
+ add esp, 8
+ and dword ptr [esp].TsEflags, NOT 200h
+ SPURIOUS_INTERRUPT_EXIT
+
+align 4
+IpiWithPicButNoClock:
+ cmp fs:PcHal.PcrIpiClockTick, 0 ; Emulate ClockTick?
+ jz short SymmetricIpi
+
+ mov fs:PcHal.PcrIpiClockTick, 0
+ or dword ptr fs:PcIRR, SWClockTick ; Set SW ClockTick bit
+
+align 4
+P0Ipi:
+SymmetricIpi:
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,13 + PRIMARY_VECTOR_BASE,esp>
+; or eax, eax NOTNOW: To add lazy irql support, this
+; jz short KsiSpuripus needs to be added - and IpiWithNoPic
+; would need fixed as well
+
+Ksi30:
+; Pass Null ExceptionFrame
+; Pass TrapFrame to Ipi service rtn
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+Hi90: call fs:[PcHal.PcrIpiSecondLevelDispatch]
+
+;
+; Do interrupt exit processing
+;
+
+ INTERRUPT_EXIT ; will return to caller
+
+Hi100:
+ mov esi, eax ; save control register
+ mov edi, edx ; save control port
+
+ cmp byte ptr fs:PcHal.PcrPic, 0 ; A pic on this processor?
+ je short Hi120
+
+ stdCall _HalBeginSystemInterrupt, <IPI_LEVEL,13 + PRIMARY_VECTOR_BASE,esp>
+ jmp short Hi130
+Hi120:
+ stdCall _KeRaiseIrql, <IPI_LEVEL,esp>
+Hi130:
+ test esi, ERR387 ; Interrupt from 387?
+ jz short Hi90 ; No, then unkown exit
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+ mov eax, esi
+ and eax, NOT ERR387
+ mov edx, edi
+ out dx, al ; clear ERR387
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbCpuType, 4 ; Is this a 386?
+ jc short Hi40 ; Yes, then don't check CR0_NE
+
+ mov eax, cr0 ; Is CR0_NE set? If so, then
+ test eax, CR0_NE ; we shouldn't be getting NPX
+ jnz short Hi50 ; interrupts.
+Hi40:
+ stdCall _KiCoprocessorError ; call CoprocessorError handler
+Hi50:
+
+;
+; We did an out to the ProcessorControl port which might have cleared a
+; pending interrupt (PINT) bit. Go process ipi handler just in case.
+;
+ jmp Ksi30
+
+stdENDP _HalpIrq13Handler
+
+
+;++
+;
+; VOID
+; HalpBelizeIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; Same as HalpIrql13Handler, expect specific to the Belize SyetemPro
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hib13_a, Hib13_t
+
+cPublicProc _HalpBelizeIrq13Handler ,0
+ ENTER_INTERRUPT Hib13_a, Hib13_t ; (ebp) -> Trap frame
+
+ push 13 + PRIMARY_VECTOR_BASE ; Vector
+ sub esp, 4 ; space for OldIrql
+
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,13 + PRIMARY_VECTOR_BASE,esp>
+
+ mov dx, SMP_IPI_MPINTx_PORT
+ in al, dx ; read clears pending int
+
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+ call fs:[PcHal.PcrIpiSecondLevelDispatch]
+
+
+;
+; Do interrupt exit processing
+;
+
+ INTERRUPT_EXIT ; will return to caller
+
+
+stdENDP _HalpBelizeIrq13Handler
+
+;++
+;
+; VOID
+; HalpNoSecondDispatch (
+; VOID
+; )
+;
+; Routine Description:
+;
+; Does nothing
+;--
+cPublicProc _HalpNo2ndDispatch,0
+ stdRET _HalpNo2ndDispatch
+stdENDP _HalpNo2ndDispatch
+
+
+
+;++
+;
+; ULONG
+; FASTCALL
+; HalSystemVectorDispatchEntry (
+; IN ULONG Vector,
+; OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+; OUT PKINTERRUPT_ROUTINE *NoConnection
+; )
+;
+; Routine Description:
+;
+; If TRUE, returns dispatch address for vector; otherwise, IDT dispatch is
+; assumed
+;
+; Arguments:
+;
+; Vector - System Vector to get dispatch address of
+; FlatDispatch - Returned dispatched address for system vector
+; NoConnection - Returned "no connection" dispatch value for system vector
+;
+;--
+
+cPublicFastCall HalSystemVectorDispatchEntry,3
+
+ xor eax, eax ; reutrn FALSE
+
+ cmp ecx, PRIMARY_VECTOR_BASE + SECOND_IPI_DISPATCH
+ jne short hsvexit
+
+ inc eax ; return TRUE
+
+ mov ecx, PCR[PcSelfPcr] ; return FlatDispatch
+ add ecx, PcHal.PcrIpiSecondLevelDispatch
+ mov [edx], ecx
+
+ mov ecx, [esp+4] ; return NoConnection
+ mov [ecx], offset _HalpNo2ndDispatch
+
+hsvexit:
+ fstRET HalSystemVectorDispatchEntry
+fstENDP HalSystemVectorDispatchEntry
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halsp/i386/spirql.asm b/private/ntos/nthals/halsp/i386/spirql.asm
new file mode 100644
index 000000000..b3249a7e2
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spirql.asm
@@ -0,0 +1,799 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spirql.asm
+;
+; Abstract:
+;
+; SystemPro IRQL
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the 8259 PIC.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; John Vert (jvert) 27-Nov-1991
+; Moved from kernel into HAL
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include i386\spmp.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ extrn _HalpApcInterrupt:near
+ extrn _HalpDispatchInterrupt:near
+ extrn _HalpSWNonPrimaryClockTick:near
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+ extrn _HalpSWNonPrimaryClockTick2ndEntry:NEAR
+ extrn _KiUnexpectedInterrupt:near
+
+;
+; Initialization control words equates for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW2_SET_PRIORITY equ 0c0H
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+
+;
+; Interrupt flag bit maks for EFLAGS
+;
+
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+
+;
+; Define the constants of Edge level Pic control.
+;
+; Background: Compaq Belize systems have an 8259 per processor and
+; their own private Edge Level control registers (4d0,4d1).
+;
+
+EDGELEVEL_CONTROL_1 equ 4D0H
+EDGELEVEL_CONTROL_2 equ 4D1H
+
+;
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; PICsInitializationString - Master PIC initialization command string
+;
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+PS2PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+
+ align 4
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 00000000000000000000000000000000B ; irql 4
+ dd 11111111110000000000000000000000B ; irql 5
+ dd 11111111111000000000000000000000B ; irql 6
+ dd 11111111111100000000000000000000B ; irql 7
+ dd 11111111111110000000000000000000B ; irql 8
+ dd 11111111111111000000000000000000B ; irql 9
+ dd 11111111111111100000000000000000B ; irql 10
+ dd 11111111111111110000000000000000B ; irql 11
+ dd 11111111111111111000000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111100000000000000B ; irql 14
+ dd 11111111111111111101000000000000B ; irql 15
+ dd 11111111111111111101100000000000B ; irql 16
+ dd 11111111111111111101110000000000B ; irql 17
+ dd 11111111111111111101111000000000B ; irql 18
+ dd 11111111111111111101111000000000B ; irql 19
+ dd 11111111111111111101111010000000B ; irql 20
+ dd 11111111111111111101111011000000B ; irql 21
+ dd 11111111111111111101111011100000B ; irql 22
+ dd 11111111111111111101111011110000B ; irql 23
+ dd 11111111111111111101111011111000B ; irql 24
+ dd 11111111111111111101111011111000B ; irql 25
+ dd 11111111111111111101111011111010B ; irql 26
+ dd 11111111111111111101111111111010B ; irql 27
+ dd 11111111111111111101111111111011B ; irql 28
+ dd 11111111111111111111111111111011B ; irql 29
+ dd 11111111111111111111111111111011B ; irql 30
+ dd 11111111111111111111111111111011B ; irql 31
+; |
+; 32109876543210
+; |
+; + - Raise SystemPros IPI vector (13)
+; to IPI_LEVEL
+ align 4
+;
+; The following tables define the addresses of software interrupt routers
+;
+
+;
+; Use this table if there is NO machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:_HalpSWNonPrimaryClockTick ; irql 4
+
+;
+; Use this table if there is a machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable2
+SWInterruptHandlerTable2 label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt2ndEntry ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt2ndEntry ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:_HalpSWNonPrimaryClockTick2ndEntry ; irql 4
+
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+ db 3 ; SWIRR=8, so highest pending SW irql= 3
+ db 3 ; SWIRR=9, so highest pending SW irql= 3
+ db 3 ; SWIRR=A, so highest pending SW irql= 3
+ db 3 ; SWIRR=B, so highest pending SW irql= 3
+ db 3 ; SWIRR=C, so highest pending SW irql= 3
+ db 3 ; SWIRR=D, so highest pending SW irql= 3
+ db 3 ; SWIRR=E, so highest pending SW irql= 3
+ db 3 ; SWIRR=F, so highest pending SW irql= 3
+
+ db 4 ; SWIRR=10, so highest pending SW irql= 4
+ db 4 ; SWIRR=11, so highest pending SW irql= 4
+ db 4 ; SWIRR=12, so highest pending SW irql= 4
+ db 4 ; SWIRR=13, so highest pending SW irql= 4
+ db 4 ; SWIRR=14, so highest pending SW irql= 4
+ db 4 ; SWIRR=15, so highest pending SW irql= 4
+ db 4 ; SWIRR=16, so highest pending SW irql= 4
+ db 4 ; SWIRR=17, so highest pending SW irql= 4
+ db 4 ; SWIRR=18, so highest pending SW irql= 4
+ db 4 ; SWIRR=19, so highest pending SW irql= 4
+ db 4 ; SWIRR=1A, so highest pending SW irql= 4
+ db 4 ; SWIRR=1B, so highest pending SW irql= 4
+ db 4 ; SWIRR=1C, so highest pending SW irql= 4
+ db 4 ; SWIRR=1D, so highest pending SW irql= 4
+ db 4 ; SWIRR=1E, so highest pending SW irql= 4
+ db 4 ; SWIRR=1F, so highest pending SW irql= 4
+
+
+;
+; Only P0 has its Edge Level masks on port 4d0 and port 4d1 setup
+; correctly. We hold the P0 values here for the other processors.
+;
+ align 4
+ public _SpP0EdgeLevelValue
+_SpP0EdgeLevelValue dw 0
+
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,1
+
+ pushfd ; save caller's eflags
+ mov al, fs:PcIrql ; get current irql
+
+if DBG
+ cmp al,cl ; old > new?
+ jbe short Kri99 ; no, we're OK
+ movzx eax, al
+ movzx ecx, cl
+ push ecx ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr fs:PcIrql,0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL>
+align 4
+Kri99:
+endif
+ cli ; disable interrupt
+
+ cmp byte ptr fs:PcHal.PcrPic, 0
+ je PxRaiseIrql ; dispatch according to processor
+
+@@:
+; P0RaiseIrql
+ cmp cl,DISPATCH_LEVEL ; software level?
+ mov fs:PcIrql, cl ; set the new irql
+ jbe short kri10 ; go skip setting 8259 hardware
+
+ movzx ecx, cl
+ mov dl, al ; Save OldIrql
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+ mov al, dl ; Restore OldIrql
+
+kri10: popfd ; restore flags (including interrupts)
+ fstRET KfRaiseIrql
+
+
+align 4
+PxRaiseIrql:
+;
+; Even though SystemPro P2 cannot touch 8259 ports, we still need to
+; make sure interrupts are off when requested to raise to IPI_LEVEL or
+; above.
+;
+ cmp cl, IPI_LEVEL ; If raise to IPI_LEVEL?
+ jb short @f ; if ne, don't edit flag
+
+ and dword ptr [esp], NOT EFLAGS_IF ; clear IF bit in return EFLAGS
+align 4
+@@:
+ mov fs:PcIrql, cl ; set the new irql
+ popfd ; restore flags (including interrupts)
+ fstRET KfRaiseIrql
+
+
+fstENDP KfRaiseIrql
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov ecx, DISPATCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+
+ mov ecx, SYNCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+ page ,132
+ subttl "Lower irql"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall KfLowerIrql,1
+
+ pushfd ; save caller's eflags
+if DBG
+ cmp cl,fs:PcIrql
+ jbe short Kli99
+ movzx ecx, cl
+ push ecx ; new irql for debugging
+ push fs:PcIrql ; old irql for debugging
+ mov byte ptr fs:PcIrql,HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
+align 4
+Kli99:
+endif
+ cli
+
+ cmp byte ptr fs:PcHal.PcrPic, 0
+ je PxLowerIrql ; dispatch according to processor
+
+@@:
+; P1LowerIrql:
+ cmp byte ptr fs:PcIrql,DISPATCH_LEVEL ; Software level?
+ jbe short kli02 ; yes, go skip setting 8259 hw
+
+ movzx ecx, cl
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+kli02: mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja short Kli10 ; yes, go simulate interrupt
+
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql
+
+; When we come to Kli10, (eax) = soft interrupt index
+
+align 4
+Kli10:
+ call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+ popfd
+ fstRET KfLowerIrql
+
+PxLowerIrql:
+ cmp cl, IPI_LEVEL ; If lower to IPI_LEVEL?
+ ; cy = yes
+ sbb edx, edx ; edx = 0 (nc), -1 (cy)
+ and edx, EFLAGS_IF
+ or dword ptr [esp], edx ; set EFLAG_IF if irql<IPI_LEVEL
+
+ mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja short Kli10 ; yes, go simulate interrupt
+
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql
+
+fstENDP KfLowerIrql
+
+;++
+;
+; VOID
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HeiNewIrql equ [esp + 4]
+
+cPublicProc _HalEndSystemInterrupt ,2
+
+ xor ecx, ecx
+ mov cl, byte ptr HeiNewIrql ; get new irql value
+
+ cmp byte ptr fs:PcHal.PcrPic, 0
+ je short Hei02
+
+; P1LowerIrql:
+ cmp byte ptr fs:PcIrql, DISPATCH_LEVEL ; Software level?
+ jbe short Hei02 ; yes, go skip setting 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+;
+; Unlike KeLowerIrql, we don't check if the the irql is lowered to
+; below IPI level and enable interrupt for second processor. This is because
+; the correct interrupt flag is already stored in the TsEflags of Trap frame.
+;
+
+align 4
+Hei02: mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja short Hei10 ; yes, go simulate interrupt
+
+ stdRET _HalEndSystemInterrupt ; cRetURN
+
+; When we come to Kli10, (eax) = soft interrupt index
+align 4
+Hei10: add esp, 12
+ jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+stdENDP _HalEndSystemInterrupt
+
+;++
+;
+; VOID
+; HalpEndSoftwareInterrupt
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL from software interrupt
+; level to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HesNewIrql equ [esp + 4]
+
+cPublicProc _HalpEndSoftwareInterrupt,1
+cPublicFpo 1,0
+ mov ecx, [esp+4]
+ fstCall KfLowerIrql
+ cli
+ stdRet _HalpEndSoftwareInterrupt
+stdENDP _HalpEndSoftwareInterrupt
+
+ page ,132
+ subttl "Get current irql"
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+ movzx eax,byte ptr fs:PcIrql ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+
+ ;
+ ; Raising to HIGH_LEVEL disables interrupts for the SystemPro HAL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine sends the 8259 PIC initialization commands and
+; masks all the interrupts on 8259s.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+
+ pushfd
+ push esi ; save caller's esi
+ cli ; disable interrupt
+ lea esi, PICsInitializationString
+
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ mov al, 0FFH ; mask all 8259 irqs
+ out dx,al ; write mask to PIC
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+ ;
+ ; If P0 then squirrel away 4d0 and 4d1 for the other processor to use.
+ ;
+
+ cmp byte ptr fs:PcHal.PcrNumber, 0 ; Is this processor 0
+ jne short Hip16
+
+ mov dx, EDGELEVEL_CONTROL_2 ; Yes then save 4d0-4d1
+ in al, dx
+ shl eax, 8
+ mov dx, EDGELEVEL_CONTROL_1
+ in al, dx
+ mov _SpP0EdgeLevelValue, ax
+
+ jmp short Hip18
+
+ ;
+ ; If not P0 then program 4d0 and 4d1 to the values P0 used for them!
+ ;
+Hip16:
+ mov ax, _SpP0EdgeLevelValue
+ mov dx, EDGELEVEL_CONTROL_1
+ out dx, al
+ inc edx
+ shr eax, 8
+ mov dx, EDGELEVEL_CONTROL_2
+ out dx, al
+
+Hip18:
+
+ pop esi ; restore caller's esi
+ popfd ; restore interrupts
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halsp/i386/spmp.inc b/private/ntos/nthals/halsp/i386/spmp.inc
new file mode 100644
index 000000000..b50de847a
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spmp.inc
@@ -0,0 +1,258 @@
+;/*
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spmp.inc
+;
+; Abstract:
+;
+; SystemPro MP include file
+;
+; Author:
+;
+;--
+
+if 0 ; */
+
+// ---------------------------------------------------
+// C section
+// ---------------------------------------------------
+
+#ifndef SPMPC_INCLUDE
+#define SPMPC_INCLUDE 1
+
+//
+// All Values in the C section must match with the assembly.
+//
+
+#define SMP_SYSPRO1 1 // Original SystemPro and Compatibles
+#define SMP_SYSPRO2 2 // SystemPro XL and ProLiant 2000,4000,4500
+#define SMP_ACER 3 // Acer SystemPro Style
+
+#define SP_M8259 1 // Each processor has 8259 set
+#define SP_SMPDEVINTS 2 // Distribute device ints amoung all processors
+#define SP_SMPCLOCK 4 // Clock is broadcast to each processor
+
+#define SECOND_IPI_DISPATCH 24 // Vector offset for second level ipi dispatch
+
+#endif
+
+/*
+endif
+
+; ---------------------------------------------------
+; Assembly section
+; ---------------------------------------------------
+
+;*****************************
+; Compaq MP defines
+;
+
+RESET_WO_EOI equ 00ah ; Reset with out EOI
+WarmResetVector equ 467h ; warm reset vector in ROM data segment
+
+; Multi-Processor Control Register I/O Locations:
+PRODUCT_ID_OFFSET equ 0C80h
+EBC_OFFSET equ 0C84h
+PCR_OFFSET equ 0C6Ah
+
+PROC_ID_PORT equ 0c70h ; who am I
+
+; Multi-Processor Control Register Bit Definitions:
+INTDIS equ 080h ; INTDIS bit in Processor control register
+PINT equ 040h ; PINT bit in Processor control register
+ERR387 equ 020h ; 387ERR bit in Processor control register
+FLUSH equ 010h ; flushes the processor's cache
+SLEEP equ 008h ; puts processor in HOLD
+CACHEON equ 004h ; enables cache
+PRES387 equ 002h ; 387PRES bit in Processor control register
+RESET equ 001h ; RESET processor
+
+;*****************************
+; end of list
+
+
+;
+; The kernel leaves some space (64 byte) of the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation
+; dependant.
+;
+
+
+PcrE struc
+ PcrNumber db 0 ; Processor's number
+ PcrPic db 0 ; 1 if processor has an 8259s
+ PcrIpiClockTick db 0 ; Emulate a clock tick
+ db 0 ; (alignment)
+ PcrIpiType dd 0 ; How to handle different IPI implementations
+ PcrIpiSecondLevelDispatch dd 0 ; To exit IPI interrupt
+ PcrControlPort dw 0 ; Processor's control port
+ PcrPerfSkew dd 0 ; Skew to apply to this P perf counter
+PcrE ends
+
+SECOND_IPI_DISPATCH equ 24 ; Vector offset for second level ipi dispatch
+
+SWClockTick equ 10h ; Software level of emulated clock tick
+SWCLOCK_LEVEL equ 4 ; Software level of emulated clock tick
+
+cr equ 0ah
+lf equ 0dh
+
+SMP_SYSPRO1 equ 1
+SMP_SYSPRO2 equ 2
+SMP_ACER equ 3
+
+;
+; 8259PerProcessorMode bit mask
+;
+
+SP_M8259 equ 1 ; Each processor has 8259 set
+SP_SMPDEVINTS equ 2 ; Distribute device ints amoung all processors
+SP_SMPCLOCK equ 4 ; Clock is broadcast to each processor
+
+
+
+;*****************************
+; Compaq SMP defines
+;
+
+;+++EQU+++ Belize Specific defines (Symmetrical SystemProII).
+;
+; INT/MPx local registers, and their initial value. Registers are offseted
+; by 2 (except INT13-INT14) and there is 15 registers (INT does not have one,
+; it is used for cascade).
+;
+
+TIME_DELAY equ 0ffffffh
+
+SMP_MAX_PROCESSORS equ 8 ;BELIZE/PHOENIX supports 8 cpus MAX
+
+SMP_MPINT0 equ 0cb0h
+SMP_MPINT1 equ 0cb2h
+;SMP_MPINT2 **** DOESNOT EXIST ****
+SMP_MPINT3 equ 0cb4h
+SMP_MPINT4 equ 0cb6h
+SMP_MPINT5 equ 0cb8h
+SMP_MPINT6 equ 0cbah
+SMP_MPINT7 equ 0cbch
+SMP_MPINT8 equ 0cbeh
+SMP_MPINT9 equ 0cc0h
+SMP_MPINT10 equ 0cc2h
+SMP_MPINT11 equ 0cc4h
+SMP_MPINT12 equ 0cc6h
+SMP_MPINT13 equ 0cc8h
+SMP_MPINT14 equ 0ccch
+SMP_MPINT15 equ 0cceh
+
+SMP_IPI_MASKPORT equ 0cd0h ; IntrMask and IntrPort..DWORD
+SMP_IPI_PROG_INTRPORT equ 0cd3h ; IntrPort
+
+; IRQ assigned to IPI_LEVEL. It could be any of the above IRQs.
+;
+SMP_IPI_VECTOR equ 13 ; IRQ13 assigned to IPI
+SMP_IPI_MPINTx_PORT equ SMP_MPINT13 ; IRQ13
+
+
+; SymmetricalMpMode registers (belize mode).
+;
+SMP_MODE_PORT equ 0c67h ; Global: ModeSelectPort
+SMP_CSR_PORT equ 0c6ah ; Local: ControlStatusRegPort
+SMP_WHOAMI_PORT equ 0c70h ; Local: Whoami Port
+SMP_INDEX_PORT equ 0c74h ; Global: Index Port
+SMP_ASSIGNMENT_PORT equ 0c71h ; Global: cpu assignment port
+
+
+; Supported Modes on Symmetrical SysPro ...
+;
+SMP_ASYMMETRICAL_MODE equ 0 ; SysPro compatible mode
+SMP_SYMMETRICAL_MODE equ 1 shl 5 ; Belize mode
+
+
+; PCR, ProcessorControl/StatusRegister Port bit pattern.
+;
+SMP_CTRL_SLEEP equ 1 shl 0 ; 1: assert sleep to CPU
+SMP_CTRL_AWAKE equ 1 shl 1 ; 1: Awake processor
+SMP_CTRL_CACHEON equ 1 shl 2 ; 1: enable intr/extr cache
+SMP_CTRL_CACHEOFF equ 1 shl 3 ; 1: disable intr/extr cache
+SMP_CTRL_FLUSH equ 1 shl 4 ; 1: flush 486 secondary cache
+SMP_CTRL_RESET equ 1 shl 5 ; 1: reset CPU
+
+SMP_RESET_CPU equ (SMP_CTRL_RESET+SMP_CTRL_AWAKE+SMP_CTRL_CACHEON)
+
+SMP_STAT_NCPIN equ 1 shl 1 ; NCP installed, always 1
+SMP_STAT_CACHEON equ 1 shl 2 ; 0: in/ex cache off, 1: on
+SMP_STAT_SLEEP equ 1 shl 3 ; 0: awake, 1: Sleeping
+SMP_STAT_NCPERR equ 1 shl 5 ; 0: no NCP error, 1:NCP error
+
+
+SMP_INTx_SET_PINT equ 1 shl 0
+SMP_INTx_CLR_PINT equ 1 shl 1
+SMP_INTx_ENABLE equ 1 shl 2
+SMP_INTx_DISABLE equ 1 shl 3
+
+
+;* MP INT13 Extended Control/Status Port...
+;
+SMP_MPINT13PORT equ 0cc9h
+
+SMP_ENBL_NCPERR equ 1 shl 0
+SMP_DSBL_NCPERR equ 1 shl 1
+SMP_ENBL_DMACHAIN equ 1 shl 2
+SMP_DSBL_DMACHAIN equ 1 shl 3
+SMP_ENBL_MCERR equ 1 shl 4
+SMP_DSBL_MCERR equ 1 shl 5
+
+
+;
+; The following macro performs an indexed IO read to the specified
+; IO address on the specified processor. The result of the read is
+; placed in the 'al' register.
+;
+; Warning: Assumes 8254 lock is owned
+;
+INDEXED_IO_READ macro cpu,ioaddress
+ push edx
+ push eax
+ mov dx, SMP_INDEX_PORT
+
+ mov al, cpu
+ out dx, al ;select cpu
+
+ inc dx
+ mov ax, ioaddress
+ out dx, ax ;select cpu's IO address to read from
+
+ add dx, 2
+ pop eax
+ in al, dx ;read from the target cpu's IO address
+ pop edx
+ jmp $+2
+endm ;INDEXED_IO_READ
+
+
+;
+; The following macro performs an indexed IO write to the specified
+; IO address on the specified processor.
+;
+INDEXED_IO_WRITE macro cpu,ioaddress,data
+ push edx
+ push eax
+
+ mov dx, SMP_INDEX_PORT
+ mov al, data
+ shl eax, 16
+
+ mov ax, ioaddress
+ shl eax, 8
+
+ mov al, cpu
+ out dx, eax
+
+ pop eax
+ pop edx
+ jmp $+2
+endm ;INDEXED_IO_WRITE
+;*/
diff --git a/private/ntos/nthals/halsp/i386/spprofil.asm b/private/ntos/nthals/halsp/i386/spprofil.asm
new file mode 100644
index 000000000..4933bb8b2
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spprofil.asm
@@ -0,0 +1,453 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spprofil.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to initialize,
+; field and process the profile interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+RegisterAProfileValue db 00101000B ; default interval = 3.90625 ms
+
+align 4
+ProfileIntervalTable dd 1221 ; unit = 100 ns
+ dd 2441
+ dd 4883
+ dd 9766
+ dd 19531
+ dd 39063
+ dd 78125
+ dd 156250
+ dd 312500
+ dd 625000
+ dd 1250000
+ dd 2500000
+ dd 5000000
+ dd 5000000 OR 80000000H
+
+ProfileIntervalInitTable db 00100011B
+ db 00100100B
+ db 00100101B
+ db 00100110B
+ db 00100111B
+ db 00101000B
+ db 00101001B
+ db 00101010B
+ db 00101011B
+ db 00101100B
+ db 00101101B
+ db 00101110B
+ db 00101111B
+ db 00101111B
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+HalpProfileInterval dd -1
+HalpProfilingStopped dd 1
+
+;
+; HALs wishing to reuse the code in this module should set the HAL
+; global variable IxProfileVector to their profile vector.
+;
+ public _IxProfileVector
+_IxProfileVector dd PROFILE_VECTOR
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; HalStartProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the slowest thing we can get away with to the value
+; that's been KeSetProfileInterval
+;
+; All processors will run this routine, but it doesn't hurt to have
+; each one reinitialize the CMOS, since none of them will be let go
+; from the stall until they all finish.
+;
+;--
+
+cPublicProc _HalStartProfileInterrupt ,1
+
+;
+; On the SystemPro there is only one profile device, so starting/stopping
+; is only done from one processor.
+;
+; Note: This code uses PbNumber so it doesn't touch any SystemPro specific
+; PCR value (so the code can be re-used by other hals)
+;
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbNumber, 0
+ jne epi_exit
+
+
+; Mark profiling as active
+;
+
+ mov HalpProfilingStopped, 0
+
+;
+; Set the interrupt rate to what is actually needed
+;
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov al, RegisterAProfileValue
+ shl ax, 8
+ mov al, 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+epi_exit:
+ stdRET _HalStartProfileInterrupt
+
+stdENDP _HalStartProfileInterrupt
+
+
+
+;++
+;
+; HalStopProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the high profiling rate to the slowest thing we
+; can get away with for PerformanceCounter rollover notification.
+;
+;--
+
+cPublicProc _HalStopProfileInterrupt ,1
+
+;
+; On the SystemPro there is only one profile device, so starting/stopping
+; is only done from one processor.
+;
+; Note: This code uses PbNumber so it doesn't touch any SystemPro specific
+; PCR value (so the code can be re-used by other hals)
+;
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbNumber, 0
+ jne dpi_exit
+
+;
+; Turn off profiling hit computation and profile interrupt
+;
+
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_DISABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending profiling interrupt
+ mov HalpProfilingStopped, 1
+ stdCall _HalpReleaseCmosSpinLock
+dpi_exit:
+ stdRET _HalStopProfileInterrupt
+
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; If profiling is active (KiProfilingStopped == 0) the actual
+; hardware interrupt rate will be set. Otherwise, a simple
+; rate validation computation is done.
+;
+; Arguments:
+;
+; (TOS+4) - Interval in 100ns unit.
+;
+; Return Value:
+;
+; Interval actually used by system.
+;--
+
+cPublicProc _HalSetProfileInterval ,1
+
+ mov edx, [esp+4] ; [edx] = interval in 100ns unit
+ and edx, 7FFFFFFFh ; Remove highest bit.
+ mov ecx, 0 ; index = 0
+
+Hspi00:
+ mov eax, ProfileIntervalTable[ecx * 4]
+ cmp edx, eax ; if request interval < suport interval
+ jbe short Hspi10 ; if be, find supported interval
+ inc ecx
+ jmp short Hspi00
+
+Hspi10:
+ and eax, 7FFFFFFFh ; remove highest bit from supported interval
+ jecxz short Hspi20 ; If first entry then use it
+
+ push esi ; See which is closer to requested
+ mov esi, eax ; rate - current entry, or preceeding
+ sub esi, edx
+
+ sub edx, ProfileIntervalTable[ecx * 4 - 4]
+ cmp esi, edx
+ pop esi
+ jc short Hspi20
+
+ dec ecx ; use preceeding entry
+ mov eax, ProfileIntervalTable[ecx * 4]
+
+Hspi20:
+ push eax ; save interval value
+ mov al, ProfileIntervalInitTable[ecx]
+ mov RegisterAProfileValue, al
+ test HalpProfilingStopped,-1
+ jnz short Hspi90
+
+ stdCall _HalStartProfileInterrupt,<0> ; Re-start profile interrupt
+ ; with the new interval
+
+Hspi90: pop eax
+ stdRET _HalSetProfileInterval ; (eax) = cReturn interval
+
+stdENDP _HalSetProfileInterval
+
+ page ,132
+ subttl "System Profile Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; PROFILE_LEVEL and transfer control to
+; the standard system routine to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpi_a, Hpi_t
+
+cPublicProc _HalpProfileInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpi_a, Hpi_t
+
+;
+; (esp) - base of trap frame
+;
+; HalBeginSystemInterrupt must be called before any sti's
+;
+;
+
+ push _IxProfileVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,_IxProfileVector,esp>
+
+ or al,al ; check for spurious interrupt
+ jz short Hpi100
+
+;
+; If profiling not enabled, then don't ack device or count this interrupt.
+; (this occurs during bootup when other processors sync PcStallScaleFactor)
+;
+ cmp HalpProfilingStopped,0
+ jne short Hpi90
+
+;
+; On the SystemPro there is only one profile device, so the CMOS is only
+; EOIed once.
+;
+; Note: This code uses PbNumber so it doesn't touch any SystemPro specific
+; PCR value (so the code can be re-used by other hals)
+;
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbNumber, 0
+ jne short _HalpProfileInterrupt2ndEntry@0
+
+
+;
+; This is the RTC interrupt, so we have to clear the
+; interrupt flag on the RTC.
+;
+ stdCall _HalpAcquireCmosSpinLock
+
+;
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+if DBG
+Hpi10: test al, 80h
+ jz short Hpi15
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ jmp short Hpi10
+Hpi15:
+endif ; DBG
+
+ stdCall _HalpReleaseCmosSpinLock
+
+; This entry point is provided for symmetric multiprocessor HALs.
+; Since it only makes sense for one processor to clear the CMOS,
+; all other processors can instead jmp into this entry point.
+;
+
+ align 4
+ public _HalpProfileInterrupt2ndEntry@0
+_HalpProfileInterrupt2ndEntry@0:
+
+ stdCall _KeProfileInterrupt,<ebp> ; (ebp) = trap frame
+
+Hpi90:
+ INTERRUPT_EXIT
+
+Hpi100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpProfileInterrupt
+
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halsp/i386/spreboot.asm b/private/ntos/nthals/halsp/i386/spreboot.asm
new file mode 100644
index 000000000..af936fee1
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spreboot.asm
@@ -0,0 +1,151 @@
+ title "SystemPro reboot"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; spreboot.asm
+;
+;Abstract:
+;
+; SystemPro reboot code.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+;--
+.386p
+ .xlist
+
+include hal386.inc
+include i386\kimacro.inc
+include i386\ix8259.inc
+include callconv.inc ; calling convention macros
+include i386\spmp.inc
+
+ EXTRNP _HalRequestIpi,1
+ EXTRNP _KeStallExecutionProcessor,1
+
+ extrn _SpProcessorControlPort:WORD
+ extrn _SpCpuCount:BYTE
+ extrn _SpType:BYTE
+ extrn _HalpProcessorPCR:DWORD
+
+
+;
+; Defines to let us diddle the CMOS clock and the keyboard
+;
+
+CMOS_CTRL equ 70h
+CMOS_DATA equ 71h
+
+KEYB_RESET equ 0feh
+KEYB_PORT equ 64h
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; HalpResetAllProcessors (
+; VOID
+; );
+;
+;Routine Description:
+;
+; Called at last phase of reboot code.
+;
+; Some SystemPro clones do not reboot properly by having the keyboard
+; issue a reset. (The bootup roms do not reset the other processors
+; properly).
+;
+; To work around this, we attempt to use P0 to halt all the other
+; processors before reseting the computer.
+;
+; Note: P0 may not respond to an IPI if it's stuck or in the debugger.
+; In this case we will just use the current processor to reset the
+; computer. This will not work on every machine, but the machine
+; was in some sort of crashed state to begin with. (it does work
+; on all compaq SystemPros).
+;
+; N.B.
+;
+; will not return
+;
+;--
+
+cPublicProc _HalpResetAllProcessors, 0
+
+;
+; Belize SystemPros can not halt processors in the same manner; however
+; simply resetting the machine via the keyboard controller works - so
+; skip this code on a belize.
+;
+ cmp _SpType, SMP_SYSPRO2
+ je rb20 ; Belize, just reset
+
+ cmp byte ptr fs:PcHal.PcrNumber, 0 ; boot processor?
+ je HalpRebootNow ; Yes, reset everyone
+
+;
+; Try signal the boot processor to perform the reboot
+;
+ mov ecx, offset FLAT:HalpRebootNow ; Zap P0's IPI handler
+ mov eax, _HalpProcessorPCR[0] ; be reboot function
+ xchg [eax].PcHal.PcrIpiType, ecx
+
+ stdCall _HalRequestIpi,<1> ; Send P0 an IPI
+ stdCall _KeStallExecutionProcessor,<50000> ; Let P0 reboot us
+
+;
+; P0 didn't reboot the machine - just do it with the current processor
+;
+
+HalpRebootNow:
+ xor ecx, ecx
+
+rb10: cmp cl, _SpCpuCount ; halt each processor
+ jae short rb20
+
+
+ mov dx, _SpProcessorControlPort[ecx*2]
+ in al, dx ; (al) = original content of PCP
+ or al, INTDIS ; Disable IPI interrupt
+
+ cmp cl, fs:PcHal.PcrNumber ; cl == currentprocessor?
+ je short @f ; don't halt ourselves
+ or al, SLEEP
+
+ cmp _SpType, SMP_ACER ; On acer MP machines
+ jne short @f ; reset other processors
+ or al, RESET ; (not tested to work on other
+ ; other machines)
+@@: out dx, al
+
+ inc ecx
+ jmp short rb10
+
+rb20:
+ xor eax, eax
+
+;
+; Send the reset command to the keyboard controller
+;
+
+ mov edx, KEYB_PORT
+ mov al, KEYB_RESET
+ out dx, al
+
+@@: hlt
+ jmp @b
+
+stdENDP _HalpResetAllProcessors
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halsp/i386/spspin.asm b/private/ntos/nthals/halsp/i386/spspin.asm
new file mode 100644
index 000000000..a5856689e
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spspin.asm
@@ -0,0 +1,382 @@
+if NT_INST
+
+else
+ TITLE "Spin Locks"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spinlock.asm
+;
+; Abstract:
+;
+; This module implements stubbed x86 spinlock functions for
+; any HAL. Some HALs may implement these function directly
+; to minimize the amount of code required to perform a spinlock.
+; (ie, out Raise & Lower irql in the fall through path)
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 13 Dec 89
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ken Reneris (kenr) 22-Jan-1991
+;--
+
+ PAGE
+
+.486p
+
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include hal386.inc
+include mac386.inc
+
+ EXTRNP KfRaiseIrql,1,,FASTCALL
+ EXTRNP KfLowerIrql,1,,FASTCALL
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ PAGE
+ SUBTTL "Acquire Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KfAcquireSpinLock ,1
+cPublicFpo 0,0
+
+
+;
+; On a MP build we raise to dispatch_level
+; and then acquire the spinlock
+;
+
+ push ecx ; Save address of spinlock
+
+ mov ecx, DISPATCH_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ pop ecx ; (ecx) -> spinlock
+
+;
+; Attempt to assert the lock
+;
+
+sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
+
+ fstRET KfAcquireSpinLock
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sl20: SPIN_ON_SPINLOCK ecx,sl10
+
+
+fstENDP KfAcquireSpinLock
+
+ PAGE
+ SUBTTL "Acquire Synch Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired,
+; any spin should occur at OldIrql)
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+;
+; Disable interrupts
+;
+
+sls10: cli
+
+;
+; Try to obtain spinlock. Use non-lock operation first
+;
+ TEST_SPINLOCK ecx,<short sls20>
+ ACQUIRE_SPINLOCK ecx,<short sls20>
+
+
+;
+; Got the lock, raise to SYNCH_LEVEL
+;
+
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+;
+; Enable interrupts and return
+;
+
+ sti
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sls20: sti
+ SPIN_ON_SPINLOCK ecx,sls10
+
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+
+ifndef NT_UP
+ RELEASE_SPINLOCK ecx ; release it
+endif
+ mov ecx, edx ; (ecx) = NewIrql
+ jmp @KfLowerIrql@4 ; to KeLowerIrql
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ push ecx ; Push FAST_MUTEX addr
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql
+
+ pop ecx ; (ecx) = Fast Mutex
+
+cPublicFpo 0,0
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,1
+ push ecx
+ push eax
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax
+ pop ecx
+
+cPublicFpo 0,0
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+
+;
+; Try to acquire
+;
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam25 ; Yes, abort
+
+cPublicFpo 0,1
+ push ecx ; Push FAST_MUTEX
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ mov ecx, [esp] ; Restore FAST_MUTEX
+ mov [esp], eax ; Save OldIrql
+
+ mov eax, 1 ; Value to compare against
+ mov edx, 0 ; Value to set
+ lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire
+ jnz short tam20 ; got it?
+
+cPublicFpo 0,0
+ pop edx ; (edx) = OldIrql
+ mov eax, 1 ; return TRUE
+ mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql
+ fstRet ExTryToAcquireFastMutex
+
+tam20: pop ecx ; (ecx) = OldIrql
+ fstCall KfLowerIrql ; restore OldIrql
+tam25: xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz @KfLowerIrql@4 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+ jmp @KfLowerIrql@4
+
+
+fstENDP ExReleaseFastMutex
+
+
+_TEXT ends
+
+ENDIF ; NT_INST
+
+ end
diff --git a/private/ntos/nthals/halsp/i386/spsproc.c b/private/ntos/nthals/halsp/i386/spsproc.c
new file mode 100644
index 000000000..ca5074944
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spsproc.c
@@ -0,0 +1,501 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ spsproc.c
+
+Abstract:
+
+ SystemPro Start Next Processor c code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ MP Compaq SystemPro
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "SystemPro or compatible MP Hal";
+
+ADDRESS_USAGE HalpSystemProIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0xC70, 1, // WhoAmI
+ 0xC6A, 1, // P0 Processor control register
+ 0xFC6A, 1, // P1 Processor control register
+ 0xFC67, 2, // P1 cache control, interrupt vector
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpAcerIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0xCC67, 2, // P2 cache control, interrupt vector
+ 0xCC6A, 1, // P2 Processor control register
+ 0xDC67, 2, // P3 cache control, interrupt vector
+ 0xDC6A, 1, // P3 Processor control register
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpBelizeIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0xC67, 1, // Mode Select
+ 0xC71, 6, // CPU assignment, reserverd[2], CPU index, address, data
+ 0xCB0, 36, // IRQx Control/Status
+ 0xCC9, 1, // INT13 Extended control/status port
+ 0,0
+ }
+};
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+
+VOID
+HalpNonPrimaryClockInterrupt(
+ VOID
+ );
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitOtherBuses (VOID);
+VOID HalpInitializePciBus (VOID);
+
+#define LOW_MEMORY 0x000100000
+#define MAX_PT 8
+
+extern VOID StartPx_PMStub(VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#pragma alloc_text(INIT,HalpFreeTiledCR3)
+#pragma alloc_text(INIT,HalpMapCR3)
+#pragma alloc_text(INIT,HalpBuildTiledCR3)
+#endif
+
+
+ULONG MpCount; // zero based. 0 = 1, 1 = 2, ...
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR MppIDT; // pointer to physical memory 0:0
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+extern ULONG HalpIpiClock; // bitmask of processors to ipi
+extern UCHAR SpCpuCount;
+extern UCHAR Sp8259PerProcessorMode;
+extern UCHAR SpType;
+extern PKPCR HalpProcessorPCR[];
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG paddress;
+ ULONG adjust;
+ PKPCR pPCR;
+
+ pPCR = KeGetPcr();
+
+ if (Phase == 0) {
+
+ //
+ // Register the IO space used by the SystemPro
+ //
+
+ HalpRegisterAddressUsage (&HalpSystemProIoSpace);
+ switch (SpType) {
+ case 2:
+ HalpRegisterAddressUsage (&HalpBelizeIoSpace);
+ break;
+ case 3:
+ HalpRegisterAddressUsage (&HalpAcerIoSpace);
+ break;
+ }
+
+#if 0
+ //
+ // Register IPI vector
+ //
+
+ HalpRegisterVector (
+ DeviceUsage,
+ 13,
+ 13 + PRIMARY_VECTOR_BASE,
+ IPI_LEVEL );
+#endif
+
+
+ //
+ // Get pointer to real-mode idt table
+ //
+
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress)
+ return TRUE;
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+ MpCount = SpCpuCount-1;
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 for another processor
+ //
+
+
+ if (pPCR->Prcb->Number != 0) {
+ if (Sp8259PerProcessorMode & 1) {
+ //
+ // Each processor has it's own pics - we broadcast profile
+ // interrupts to each processor by enabling it on each
+ // processor
+ //
+
+ HalpInitializeStallExecution( pPCR->Prcb->Number );
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ V2I (PROFILE_VECTOR), // Bus interrupt level
+ PROFILE_VECTOR, // System IDT
+ PROFILE_LEVEL, // System Irql
+ HalpProfileInterrupt, // ISR
+ Latched );
+
+ } else {
+ //
+ // Without a profile interrupt we can not callibrate
+ // KeStallExecutionProcessor, so we inherrit the value from P0.
+ //
+
+ pPCR->StallScaleFactor = HalpProcessorPCR[0]->StallScaleFactor;
+
+ }
+
+ if (Sp8259PerProcessorMode & 4) {
+ //
+ // Each processor can get it's own clock device - we
+ // program each processor's 8254 and enable to interrupt
+ // on each processor
+ //
+
+ HalpInitializeClock ();
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ V2I (CLOCK_VECTOR), // Bus interrupt level
+ CLOCK_VECTOR, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ HalpNonPrimaryClockInterrupt, // ISR
+ Latched );
+
+ } else {
+
+ //
+ // This processor doesn't have a clock, so we emulate it by
+ // sending an ipi at clock intervals.
+ //
+
+ HalpIpiClock |= 1 << pPCR->Prcb->Number;
+ }
+
+ }
+ }
+}
+
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Eisa // SystemPro's are Eisa machines
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Turn on MCA support if present
+ //
+
+ HalpMcaInit();
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+}
+
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other buses
+}
diff --git a/private/ntos/nthals/halsp/i386/spsproca.asm b/private/ntos/nthals/halsp/i386/spsproca.asm
new file mode 100644
index 000000000..47b0e6b04
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spsproca.asm
@@ -0,0 +1,373 @@
+ title "MP primitives for Compaq SystemPro"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; spsproca.asm
+;
+;Abstract:
+;
+; SystemPro Start Next Processor assemble code
+;
+; This module along with mpspro.c implement the code to start
+; off the second processor on the Compaq SystemPro.
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+;Revision History:
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\spmp.inc
+ .list
+
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+
+ extrn _MppIDT:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+ extrn _MpCount:DWORD
+ extrn _SpProcessorControlPort:WORD
+ extrn _SpType:BYTE
+
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_ControlPort dd ?
+ SPx_PB db processorstatelength dup (?)
+PxParamBlock ends
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+
+
+cPublicProc _HalStartNextProcessor ,2
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.SPx_flag, eax
+
+ cmp _MpCount, eax
+ jbe snp_exit ; exit FALSE
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+ mov edi, _MpLowStub ; Copy RMStub to low memory
+ add edi, size PxParamBlock
+ rep movsb
+
+ lea edi, PxFrame.SPx_PB
+ mov esi, pProcessorState
+ mov ecx, processorstatelength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+ stdCall _HalpBuildTiledCR3, <pProcessorState>
+
+ mov PxFrame.SPx_TiledCR3, eax
+ mov PxFrame.SPx_P0EBP, ebp
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+ movzx edx, _SpProcessorControlPort[eax*2] ; Get processor's control port
+ mov PxFrame.SPx_ControlPort, edx ; Pass it along
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _MpLowStub
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx ; patch realmode stub with
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
+
+ mov ebx, _MppIDT
+ add ebx, WarmResetVector
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+
+ mov eax, _MpLowStubPhysicalAddress
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+
+ cmp _SpType, SMP_SYSPRO2 ; Belize?
+ jne short snp10 ; no, reset normal
+
+ mov dx, SMP_INDEX_PORT
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+ or eax, (SMP_RESET_CPU shl 24) + (SMP_CSR_PORT shl 8)
+
+ out dx, eax ; issue Belize reset to processor
+ jmp short snp20 ; go wait
+
+snp10:
+ mov edx, PxFrame.SPx_ControlPort ; Control port of target
+ in al, dx ; processor
+ or al, RESET ; assert RESET
+ and al, NOT SLEEP ; wakeup P1
+ out dx, al ; reset P1
+
+snp20: cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's
+ jz snp20 ; info
+
+ pop dword ptr [ebx] ; restore WarmResetVector
+ sti
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+
+ dec _MpCount ; one less
+ mov eax, 1 ; return TRUE
+
+snp_exit:
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ stdRET _HalStartNextProcessor
+
+stdENDP _HalStartNextProcessor
+
+
+_TEXT ends ; end 32 bit code
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub ,0
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+stdENDP StartPx_RMStub
+
+
+_TEXT16 ends ; End 16 bit code
+
+_TEXT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+ align 16 ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+cPublicProc _StartPx_PMStub ,0
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+ cmp _SpType, SMP_SYSPRO2 ; Don't send old SP
+ je short spxpm01 ; style Cache on enable
+
+ ; eax, ebx, edx are still free
+ mov edx, [PxFrame.SPx_ControlPort] ; our control port
+ in al, dx ; Get register
+ and al, NOT INTDIS ; allow PINTs on this proc
+ or al, CACHEON ; turn cache on
+ out dx, al
+spxpm01:
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with it's data
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ stdRET _StartPx_PMStub ; Set eip
+
+stdENDP _StartPx_PMStub
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/halsp/i386/spswint.asm b/private/ntos/nthals/halsp/i386/spswint.asm
new file mode 100644
index 000000000..712d4f45f
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spswint.asm
@@ -0,0 +1,325 @@
+ title "Software Interrupts"
+
+;++
+;
+; Copyright (c) 1992 Microsoft Corporation
+;
+; Module Name:
+;
+; ixswint.asm
+;
+; Abstract:
+;
+; This module implements the software interrupt handlers
+; for x86 machines
+;
+; Author:
+;
+; John Vert (jvert) 2-Jan-1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+ .list
+
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ extrn SWInterruptHandlerTable:dword
+ extrn SWInterruptLookUpTable:byte
+ifdef IRQL_METRICS
+ extrn HalApcSoftwareIntCount:dword
+ extrn HalDpcSoftwareIntCount:dword
+endif
+
+_TEXT$02 SEGMENT DWORD USE32 PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Request Software Interrupt"
+
+;++
+;
+; VOID
+; FASTCALL
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to request a software interrupt to the
+; system. Also, this routine checks to see if any software
+; interrupt should be generated.
+; The following condition will cause software interrupt to
+; be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; equates for accessing arguments
+;
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+cPublicFpo 0, 1
+ mov eax,1
+ shl eax, cl ; convert to mask
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+ or PCR[PcIRR], eax ; set the request bit
+ mov cl, PCR[PcIrql] ; get current IRQL
+
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ jbe KsiExit ; No, jmp ksiexit
+ call SWInterruptHandlerTable[eax*4] ; yes, simulate interrupt
+ ; to the appropriate handler
+KsiExit:
+ popfd ; restore original interrupt mode
+ fstRET HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+ page ,132
+ subttl "Request Software Interrupt"
+
+;++
+;
+; VOID
+; HalClearSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to clear a possible pending software interrupt.
+; Support for this function is optional, and allows the kernel to
+; reduce the number of spurious software interrupts it receives/
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalClearSoftwareInterrupt ,1
+cPublicFpo 0, 0
+
+ mov eax,1
+ shl eax, cl ; convert to mask
+
+ not eax
+ and PCR[PcIRR], eax ; clear pending irr bit
+
+ fstRET HalClearSoftwareInterrupt
+
+fstENDP HalClearSoftwareInterrupt
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+ align dword
+ public _HalpDispatchInterrupt
+_HalpDispatchInterrupt proc
+ifdef IRQL_METRICS
+ lock inc HalDpcSoftwareIntCount
+endif
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public _HalpDispatchInterrupt2ndEntry
+_HalpDispatchInterrupt2ndEntry:
+
+; Save previous IRQL and set new priority level
+
+ push PCR[PcIrql] ; save previous IRQL
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
+ btr dword ptr PCR[PcIRR], DISPATCH_LEVEL; clear the pending bit in IRR
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; Go do Dispatch Interrupt processing
+;
+ stdCall _KiDispatchInterrupt
+
+;
+; Do interrupt exit processing
+;
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+_HalpDispatchInterrupt endp
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+ align dword
+ public _HalpApcInterrupt
+_HalpApcInterrupt proc
+ifdef IRQL_METRICS
+ lock inc HalApcSoftwareIntCount
+endif
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state in trap frame
+;
+ ENTER_INTERRUPT hapc_a, hapc_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+
+ public _HalpApcInterrupt2ndEntry
+_HalpApcInterrupt2ndEntry:
+
+;
+; Save previous IRQL and set new priority level
+;
+
+ push PCR[PcIrql] ; save previous Irql
+ mov byte ptr PCR[PcIrql], APC_LEVEL ; set new Irql
+ btr dword ptr PCR[PcIRR], APC_LEVEL ; dismiss pending APC
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; call the APC delivery routine.
+;
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
+ jz short @f
+
+ or eax, MODE_MASK ; If v86 frame, then set user_mode
+@@:
+
+;
+; call APC deliver routine
+; Previous mode
+; Null exception frame
+; Trap frame
+
+ stdCall _KiDeliverApc, <eax, 0,ebp>
+
+;
+;
+; Do interrupt exit processing
+;
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+_HalpApcInterrupt endp
+
+_TEXT$02 ends
+
+ end
diff --git a/private/ntos/nthals/halsp/i386/spsysbus.c b/private/ntos/nthals/halsp/i386/spsysbus.c
new file mode 100644
index 000000000..65db51aa9
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spsysbus.c
@@ -0,0 +1,249 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ spsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "spmp.inc"
+
+ULONG HalpDefaultInterruptAffinity;
+ULONG HalpCpuCount;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+extern UCHAR SpCpuCount;
+extern Sp8259PerProcessorMode;
+extern UCHAR RegisteredProcessorCount;
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL pIrql,
+ OUT PKAFFINITY pAffinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+ ULONG Cpu;
+ ULONG Affinity;
+ KIRQL Irql;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // Set default SystemVector, IRQL & CPU
+ //
+
+ SystemVector = BusInterruptLevel + PRIMARY_VECTOR_BASE;
+ Irql = (KIRQL)(HIGHEST_LEVEL_FOR_8259 + PRIMARY_VECTOR_BASE - SystemVector);
+ Cpu = 0;
+
+
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ SystemVector > PRIMARY_VECTOR_BASE + HIGHEST_LEVEL_FOR_8259 ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ //
+ // If this is machine has reported SMP Dev Ints then lets
+ // use them in a static interrupt distribution method.
+ // Notice some devices are kept on P0 for compatibility.
+ // These interrupts and their devices are not generally used
+ // for steady state operations.
+ //
+
+ if (Sp8259PerProcessorMode & SP_SMPDEVINTS) {
+
+ //
+ // This is for overriding some devices that belong on P0.
+ //
+
+ switch (BusInterruptLevel) {
+ case 1: // keyboard
+ case 3: // com2
+ case 4: // com1
+ case 5: // SysMgmt Modem
+ case 6: // floppy
+ case 12: // mouse
+ // use first cpu
+ break;
+
+ case 13: // Health (IPIs on all)
+ // use first cpu, as:
+ Irql = IPI_LEVEL;
+ SystemVector = PRIMARY_VECTOR_BASE + SECOND_IPI_DISPATCH;
+ break;
+
+ default:
+ Cpu = SystemVector % HalpCpuCount;
+ break;
+ }
+ }
+
+ //
+ // Get Affinity for Cpu
+ //
+
+ Affinity = 1 << Cpu;
+ ASSERT (Affinity);
+
+ //
+ // Done
+ //
+
+ *pAffinity = Affinity;
+ *pIrql = Irql;
+ return SystemVector;
+}
diff --git a/private/ntos/nthals/halsp/i386/spsysint.asm b/private/ntos/nthals/halsp/i386/spsysint.asm
new file mode 100644
index 000000000..1f09bbb39
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/spsysint.asm
@@ -0,0 +1,393 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; spsysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts, for the MP systempro implementation
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\spmp.inc
+ .list
+
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeBugCheck,1,IMPORT
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; Macros to Read/Write/Reset CMOS to initialize RTC
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+align dword
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irq 0
+ dd offset FLAT:HalpDismissNormal ; irq 1
+ dd offset FLAT:HalpDismissNormal ; irq 2
+ dd offset FLAT:HalpDismissNormal ; irq 3
+ dd offset FLAT:HalpDismissNormal ; irq 4
+ dd offset FLAT:HalpDismissNormal ; irq 5
+ dd offset FLAT:HalpDismissNormal ; irq 6
+ dd offset FLAT:HalpDismissIrq07 ; irq 7
+ dd offset FLAT:HalpDismissNormal ; irq 8
+ dd offset FLAT:HalpDismissNormal ; irq 9
+ dd offset FLAT:HalpDismissNormal ; irq A
+ dd offset FLAT:HalpDismissNormal ; irq B
+ dd offset FLAT:HalpDismissNormal ; irq C
+ dd offset FLAT:HalpDismissNormal ; irq D
+ dd offset FLAT:HalpDismissNormal ; irq E
+ dd offset FLAT:HalpDismissIrq0f ; irq F
+ dd offset FLAT:HalpDismissNormal ; irq 10
+ dd offset FLAT:HalpDismissNormal ; irq 11
+ dd offset FLAT:HalpDismissNormal ; irq 12
+ dd offset FLAT:HalpDismissNormal ; irq 13
+ dd offset FLAT:HalpDismissNormal ; irq 14
+ dd offset FLAT:HalpDismissNormal ; irq 15
+ dd offset FLAT:HalpDismissNormal ; irq 16
+ dd offset FLAT:HalpDismissNormal ; irq 17
+ dd offset FLAT:HalpDismissNormal ; irq 18
+ dd offset FLAT:HalpDismissNormal ; irq 19
+ dd offset FLAT:HalpDismissNormal ; irq 1A
+ dd offset FLAT:HalpDismissNormal ; irq 1B
+ dd offset FLAT:HalpDismissNormal ; irq 1C
+ dd offset FLAT:HalpDismissNormal ; irq 1D
+ dd offset FLAT:HalpDismissNormal ; irq 1E
+ dd offset FLAT:HalpDismissNormal ; irq 1F
+ dd offset FLAT:HalpDismissNormal ; irq 20
+ dd offset FLAT:HalpDismissNormal ; irq 21
+ dd offset FLAT:HalpDismissNormal ; irq 22
+ dd offset FLAT:HalpDismissNormal ; irq 23
+ dd offset FLAT:HalpDispatch ; irq 24 - 2nd level dispatch from ipi
+
+_DATA ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+; On the SystemPro, since all interrupt go to P0, HalBeing/EndSystem-
+; Interrupt are treated very much like the UP case. All calls to this
+; function will occur from P0.
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+ mov ebx, dword ptr HbsiVector ; (ebx) = System Vector
+ sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ #
+
+ cmp ebx, 25h ; Interrupt in table?
+ jnc hbsi00 ; no go handle
+ jmp HalpSpecialDismissTable[ebx*4]
+
+hbsi00:
+;
+; Interrupt is out of range. There's no EOI here since it wouldn't
+; have been out of range if it occured on either interrupt controller
+; which is known about.
+;
+ xor eax,eax ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ xor eax,eax ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, so this is NOT a spurious int
+ xor eax, eax ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+HalpDismissNormal:
+;
+; Store OldIrql
+;
+ mov eax, HbsiOldIrql
+ mov cl, fs:PcIrql
+ mov byte ptr [eax], cl
+
+;
+; Raise IRQL to requested level
+;
+ xor eax, eax
+ mov al, HbsiIrql ; (eax) = irql
+ ; (ebx) = IRQ #
+
+ mov fs:PcIrql, al ; set new Irql
+
+
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, fs:PcIDR ; mask disabled irqs
+ SET_8259_MASK ; send mask to 8259s
+
+;
+; Dismiss interrupt. Current interrupt is already masked off.
+;
+ mov eax, ebx ; (eax) = IRQ #
+ cmp eax, 8 ; EOI to master or slave?
+
+ jae short Hbsi100 ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short Hbsi200 ; IO delay
+
+align 4
+Hbsi100:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+align 4
+Hbsi200:
+ PIC1DELAY
+
+HalpDispatch:
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt ,2
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or fs:PcIDR, edx
+ xor eax, eax
+
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt ,3
+
+ mov ecx, dword ptr [esp+4] ; (ecx) = vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc hes_error
+ cmp ecx, CLOCK2_LEVEL
+ jnc hes_error
+
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ pushfd
+ cli
+ and fs:PcIDR, eax
+
+;
+; Get the PIC masks for the current Irql
+;
+ movzx eax, byte ptr fs:PcIrql
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, fs:PcIDR
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+ popfd
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+hes_error:
+if DBG
+ int 3
+endif
+ xor eax, eax ; FALSE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halsp/i386/xxbiosa.asm b/private/ntos/nthals/halsp/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halsp/i386/xxbiosc.c b/private/ntos/nthals/halsp/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halsp/i386/xxdisp.c b/private/ntos/nthals/halsp/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halsp/i386/xxflshbf.c b/private/ntos/nthals/halsp/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halsp/i386/xxhal.c b/private/ntos/nthals/halsp/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxhal.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxhal.c"
diff --git a/private/ntos/nthals/halsp/i386/xxioacc.asm b/private/ntos/nthals/halsp/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halsp/i386/xxkdsup.c b/private/ntos/nthals/halsp/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halsp/i386/xxmemory.c b/private/ntos/nthals/halsp/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halsp/i386/xxstubs.c b/private/ntos/nthals/halsp/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halsp/i386/xxtime.c b/private/ntos/nthals/halsp/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halsp/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halsp/makefile b/private/ntos/nthals/halsp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halsp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halsp/makefile.inc b/private/ntos/nthals/halsp/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halsp/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halsp/sources b/private/ntos/nthals/halsp/sources
new file mode 100644
index 000000000..fda506a87
--- /dev/null
+++ b/private/ntos/nthals/halsp/sources
@@ -0,0 +1,106 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halsp
+TARGETPATH=\nt\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io;..
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbusdat.c \
+ i386\ixcmos.asm \
+ i386\ixdat.c \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixinfo.c \
+ i386\ixisabus.c \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\ixmca.c \
+ i386\ixmcaa.asm \
+ i386\ixnmi.c \
+ i386\ixphwsup.c \
+ i386\ixpcibus.c \
+ i386\ixpciint.c \
+ i386\ixpcibrd.c \
+ i386\ixstall.asm \
+ i386\ixthunk.c \
+ i386\ixreboot.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxhal.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c \
+ i386\spacer.c \
+ i386\spclock.asm \
+ i386\spbeep.asm \
+ i386\spipi.asm \
+ i386\spirql.asm \
+ i386\spsysbus.c \
+ i386\spsysint.asm \
+ i386\spprofil.asm \
+ i386\spreboot.asm \
+ i386\spspin.asm \
+ i386\spsproc.c \
+ i386\spsproca.asm \
+ i386\spswint.asm
+
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halsp.lib
+
+!ENDIF
+
diff --git a/private/ntos/nthals/haltimbr/alpha/28f008sa.c b/private/ntos/nthals/haltimbr/alpha/28f008sa.c
new file mode 100644
index 000000000..2865a2061
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/28f008sa.c
@@ -0,0 +1 @@
+#include "../halalpha/28f008sa.c"
diff --git a/private/ntos/nthals/haltimbr/alpha/29f040.c b/private/ntos/nthals/haltimbr/alpha/29f040.c
new file mode 100644
index 000000000..2c2b423af
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/29f040.c
@@ -0,0 +1 @@
+#include "../halalpha/29f040.c"
diff --git a/private/ntos/nthals/haltimbr/alpha/adjust.c b/private/ntos/nthals/haltimbr/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/allstart.c b/private/ntos/nthals/haltimbr/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/apecs.c b/private/ntos/nthals/haltimbr/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/apecserr.c b/private/ntos/nthals/haltimbr/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/apecsio.s b/private/ntos/nthals/haltimbr/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/bios.c b/private/ntos/nthals/haltimbr/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/busdata.c b/private/ntos/nthals/haltimbr/alpha/busdata.c
new file mode 100644
index 000000000..cc2a153c1
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/busdata.c
@@ -0,0 +1,125 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/haltimbr/alpha/cache.c b/private/ntos/nthals/haltimbr/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/cia.c b/private/ntos/nthals/haltimbr/alpha/cia.c
new file mode 100644
index 000000000..7948bfe16
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/cia.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cia.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ciaaddr.c b/private/ntos/nthals/haltimbr/alpha/ciaaddr.c
new file mode 100644
index 000000000..b85818ac0
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ciaaddr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaaddr.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ciaerr.c b/private/ntos/nthals/haltimbr/alpha/ciaerr.c
new file mode 100644
index 000000000..bfb9efc93
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ciaerr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaerr.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ciaio.s b/private/ntos/nthals/haltimbr/alpha/ciaio.s
new file mode 100644
index 000000000..16202a7e1
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ciaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaio.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ciamapio.c b/private/ntos/nthals/haltimbr/alpha/ciamapio.c
new file mode 100644
index 000000000..3e9f7a9c1
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ciamapio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciamapio.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/cmos8k.c b/private/ntos/nthals/haltimbr/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/devintr.s b/private/ntos/nthals/haltimbr/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/eb164.h b/private/ntos/nthals/haltimbr/alpha/eb164.h
new file mode 100644
index 000000000..700aa4e34
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/eb164.h
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ eb164.h
+
+Abstract:
+
+ This file contains definitions specific to the EB164 platform.
+
+Author:
+
+ Joe Notarangelo 06-Sep-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _EB164H_
+#define _EB164H_
+
+//
+// Include definitions for the components that make up EB164.
+//
+
+#include "axp21164.h" // 21164 (EV5) microprocessor definitions
+#include "cia.h" // CIA controller definitions
+
+//
+// Define number of PCI, ISA, and combo slots
+//
+
+#define NUMBER_ISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 4
+#define NUMBER_COMBO_SLOTS 1
+
+//
+// PCI bus address values:
+//
+
+#define PCI_MAX_LOCAL_DEVICE (PCI_MAX_DEVICES - 1)
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+#define PCI_MAX_INTERRUPT (0x15)
+
+//
+// Define numbers and names of cpus.
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0)
+
+//
+// Define default processor frequency.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (250)
+
+//
+// Define EB164-specific routines that are really macros for performance.
+//
+
+#define HalpAcknowledgeEisaInterrupt(x) INTERRUPT_ACKNOWLEDGE(x)
+
+//
+// Define the per-processor data structures allocated in the PCR.
+//
+
+typedef struct _EB164_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+ } EB164_PCR, *PEB164_PCR;
+
+#define HAL_PCR ( (PEB164_PCR)(&(PCR->HalReserved)) )
+
+//
+// Define the locations of the interrupt mask registers.
+//
+
+#define INTERRUPT_MASK0_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + 0x804)
+#define INTERRUPT_MASK1_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + 0x805)
+#define INTERRUPT_MASK2_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + 0x806)
+
+//
+// Define the location of the flash environment block
+//
+
+#define NVRAM_ENVIRONMENT_QVA \
+ ((ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_MEMORY_PHYSICAL) + 0xf0000)
+
+#define CIA_MCR_QVA ((ULONG)HAL_MAKE_QVA(CIA_MEMORY_CSRS_PHYSICAL))
+
+//
+// Define EB164 SIO dispatch
+//
+BOOLEAN
+HalpEB164SioDispatch(
+ PKINTERRUPT Interrupt,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+typedef BOOLEAN (*PEB164_SECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT Interrupt,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+#endif //_EB164H_
+
diff --git a/private/ntos/nthals/haltimbr/alpha/eb164err.c b/private/ntos/nthals/haltimbr/alpha/eb164err.c
new file mode 100644
index 000000000..d305a0704
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/eb164err.c
@@ -0,0 +1,122 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ eb164err.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the EB164 platform.
+
+Author:
+
+ Joe Notarangelo 06-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eb164.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+VOID
+HalpErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for an EB164 machine check interrupt
+ The function calls HalpCiaReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // Report the error and crash the system
+ //
+
+ HalpCiaReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+
+
+ return; // never
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ //
+ // All machine check handling is determined by the CIA
+ //
+
+ return(HalpCiaMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ));
+}
diff --git a/private/ntos/nthals/haltimbr/alpha/eb164io.s b/private/ntos/nthals/haltimbr/alpha/eb164io.s
new file mode 100644
index 000000000..74e586ff2
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/eb164io.s
@@ -0,0 +1,139 @@
+
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ eb164io.s
+
+Abstract:
+
+ This module implements flashrom I/O access routines for EB164.
+
+Author:
+
+ Chao Chen 14-Sep-1994
+ Joe Notarangelo 14-Sep-1994
+ Jeff Wiedermeier 14-Sep-1994
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "halalpha.h"
+
+#define EB164_FLASH_BASE -0x37a9 // negative of 0xc857
+#define CIA_SPARSE_IO_SVA -0x37a8 // negative of 0xc858
+#define IO_BIT_SHIFT 5
+
+
+//++
+//
+// UCHAR
+// EB164_READ_FLASH_BYTE(
+// ULONG Offset
+// )
+//
+// Routine Description:
+//
+// Read a byte of data from the flash rom at the specified offset.
+//
+// Arguments:
+//
+// Offset (a0) - Supplies a byte offset from the base of the flash rom.
+//
+// Return Value:
+//
+// (v0) Returns the byte of data read from the flash rom.
+//
+//--
+
+ LEAF_ENTRY(EB164_READ_FLASH_BYTE)
+
+ and a0, 3, t2 // save byte lane to read
+
+ srl a0, 19,t1 // get bank select to lsb
+ and t1, 1, t1 // mask it
+ lda t3, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t3, 28, t3 // 0xffff fc85 8000 0000
+ lda t4, 0x800(zero) // get port number for bank sel
+ sll t4, IO_BIT_SHIFT, t4 // put it in place
+ or t3, t4, t3 // and merge it
+ stl t1, 0(t3) // write the bank select
+ mb
+
+ lda t0, EB164_FLASH_BASE(zero) // 0xffff ffff ffff c857
+ sll t0, 4, t0 // 0xffff ffff fffc 8570
+ lda t0, 0xf(t0) // 0xffff ffff fffc 857f
+ sll t0, 24, t0 // 0xffff fc85 7f00 0000
+
+ sll a0, IO_BIT_SHIFT, a0 // shift offset to sparse space
+ bis t0, a0, t0 // merge offset and base
+
+ ldl v0, 0(t0) // read flash rom
+ extbl v0, t2, v0 // extract byte from appropriate lane
+
+ ret zero, (ra) // return
+
+ .end EB164_READ_FLASH_BYTE
+
+//++
+//
+// VOID
+// EB164_WRITE_FLASH_BYTE(
+// ULONG Offset,
+// UCHAR Data
+// )
+//
+// Routine Description:
+//
+// Write a byte of data to the flash rom at the specified offset.
+//
+// Arguments:
+//
+// Offset (a0) - Supplies a byte offset from the base of the flash rom.
+//
+// Data (a1) - Supplies the data to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EB164_WRITE_FLASH_BYTE)
+
+ and a0, 3, t2 // save byte lane to read
+
+ srl a0, 19,t1 // get bank select to lsb
+ and t1, 1, t1 // mask it
+ lda t3, CIA_SPARSE_IO_SVA(zero) // 0xffff ffff ffff c858
+ sll t3, 28, t3 // 0xffff fc85 8000 0000
+ lda t4, 0x800(zero) // get port number for bank sel
+ sll t4, IO_BIT_SHIFT, t4 // put it in place
+ or t3, t4, t3 // and merge it
+ stl t1, 0(t3) // write the bank select
+ mb
+
+ lda t0, EB164_FLASH_BASE(zero) // 0xffff ffff ffff c857
+ sll t0, 4, t0 // 0xffff ffff fffc 8570
+ lda t0, 0xf(t0) // 0xffff ffff fffc 857f
+ sll t0, 24, t0 // 0xffff fc85 7f00 0000
+
+ sll a0, IO_BIT_SHIFT, a0 // shift offset to sparse space
+ bis t0, a0, t0 // merge offset and base
+
+ insbl a1, t2, a1 // put data into correct lane
+ stl a1, 0(t0) // write the flash rom
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EB164_WRITE_FLASH_BYTE
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ebinitnt.c b/private/ntos/nthals/haltimbr/alpha/ebinitnt.c
new file mode 100644
index 000000000..2e5c96b79
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ebinitnt.c
@@ -0,0 +1,658 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ebinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an EB164 system.
+
+Author:
+
+ Joe Notarangelo 06-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "eb164.h"
+#include "iousage.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+
+
+//
+// Irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - interval clock
+// irql 6 - not used
+// irql 7 - error, mchk, nmi, performance counters
+//
+//
+
+//
+// The hardware interrupt pins are used as follows for EB164
+//
+// IRQ0 = CIA_INT
+// IRQ1 = SYS_INT (PCI and ESC interrupts)
+// IRQ2 = Interval Clock
+// IRQ3 = Error Interrupts
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// External references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Function prototypes.
+//
+
+BOOLEAN
+HalpInitializeEB164Interrupts (
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpErrorInterrupt(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an EB164 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern ULONG HalpCiaErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+ extern ULONG HalpHaltInterrupt();
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize EB164 interrupts.
+ //
+
+ HalpInitializeEB164Interrupts();
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = (PKINTERRUPT_ROUTINE)HalpCiaErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] = (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = (PKINTERRUPT_ROUTINE)HalpErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_CRD_VECTOR] = (PKINTERRUPT_ROUTINE)Halp21164CorrectedErrorInterrupt;
+
+ HalpStart21164Interrupts();
+
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV4
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any EV4-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+
+ //
+ // Since we have a flash device mapped in PCI memory space, but its
+ // HAL driver is pretending to be a cmos8k driver - override the
+ // HalpCMOSRamBase value set in HalpMapIoSpace (ciamapio.c) with the
+ // correct QVA to reach the environment block in the flash through
+ // the SIO.
+ //
+ HalpCMOSRamBase = (PVOID)NVRAM_ENVIRONMENT_QVA;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+#ifdef HALDBG
+ DbgPrint("LOOK AT THIS ONE\r\n");
+ DumpCia(CiaGeneralRegisters |
+ CiaErrorRegisters |
+ CiaScatterGatherRegisters);
+#endif
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the PCI parity checking.
+ //
+
+ PciParityChecking = (BOOLEAN)(HalDisablePCIParityChecking == 0);
+
+ HalpInitializeCiaMachineChecks(ReportCorrectables = TRUE,
+ PciParityChecking);
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ return;
+
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to EB164 and the call should be
+// ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(CIA_UNCORRECTABLE_FRAME);
+ return;
+}
+
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "eb164";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV5_UNCORRECTABLE processorFrame;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
+
+//
+//jnfix - this variable is needed because the clock interrupt handler
+// - in intsup.s was made to be familiar with ev4prof.c, unfortunate
+// - since we don't use ev4prof.c, so for now this is a hack, later
+// - we will either fix intsup.s or create a new intsup.s that does
+// - not have this hack
+//
+
+ULONG HalpNumberOfTicksReload;
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ebintsup.c b/private/ntos/nthals/haltimbr/alpha/ebintsup.c
new file mode 100644
index 000000000..3beb9df13
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ebintsup.c
@@ -0,0 +1,619 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for EB164 systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Chao Chen (DEC) 06-Sept-1994
+ Adapted from Avanti module for EB164.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "eb164.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+
+//
+// Declare the interrupt masks.
+//
+
+UCHAR IntMask0, IntMask1, IntMask2;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an ISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following functions handle the PCI interrupts.
+//
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitializeEB164Interrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for ISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the ISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the ISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) EB164PCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize the SIO's PICs for ISA interrupts.
+ //
+
+ HalpInitializeSioInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for EB164 comes from a Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the EB164 PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Clear all interrupt masks.
+ // Enable the SIO interrupt in the mask.
+ //
+
+ IntMask0 = 0x10;
+ IntMask1 = 0x00;
+ IntMask2 = 0x00;
+
+ //
+ // Disable interrupts except for SIO.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA, ~IntMask0);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA, ~IntMask1);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA, ~IntMask2);
+
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ if (Vector >= 0 && Vector <= 7) {
+
+ IntMask0 &= (UCHAR)~(1 << Vector);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA, ~IntMask0);
+
+ } else if (Vector >= 8 && Vector <= 0xf) {
+
+ IntMask1 &= (UCHAR)~(1 << (Vector - 8));
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA, ~IntMask1);
+
+ } else if (Vector >= 0x10 && Vector <=0x17) {
+
+ IntMask2 &= (UCHAR)~(1 << (Vector - 16));
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA, ~IntMask2);
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: bad vector!\n");
+#endif
+
+ }
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for EB164 PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to one,
+ // to ensable that PCI interrupt.
+ //
+
+ if (Vector >= 0 && Vector <= 7) {
+
+ IntMask0 |= (UCHAR) (1 << Vector);
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA, ~IntMask0);
+
+ } else if (Vector >= 8 && Vector <= 0xf) {
+
+ IntMask1 |= (UCHAR) (1 << (Vector - 8));
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA, ~IntMask1);
+
+ } else if (Vector >= 0x10 && Vector <= 0x17) {
+
+ IntMask2 |= (UCHAR) (1 << (Vector - 16));
+ WRITE_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA, ~IntMask2);
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpEnablePciInterrupt: bad vector!\n");
+#endif
+
+ }
+}
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ ULONG IdtIndex;
+ ULONG IntNumber;
+ PKINTERRUPT InterruptObject;
+ UCHAR PCIVector;
+
+ //
+ // Read in the 1st interrupt register.
+ //
+
+ PCIVector = READ_PORT_UCHAR((PUCHAR)INTERRUPT_MASK0_QVA) & IntMask0;
+
+ //
+ // Did ISA interrupt occur?
+ //
+
+ if (PCIVector & 0x10) {
+
+ //
+ // ISA interrupt. Call HalpEB164SioDispatch.
+ //
+
+ return (HalpEB164SioDispatch( Interrupt, NULL, TrapFrame ) );
+
+ }
+
+ //
+ // Which PCI interrupt occurred?
+ //
+
+ IdtIndex = PCI_MAX_INTERRUPT + 1;
+
+ if (PCIVector) {
+
+ for (IntNumber = 0; IntNumber < 8; IntNumber++) {
+
+ if (PCIVector & 0x01) {
+ IdtIndex = IntNumber;
+ break;
+ } else {
+ PCIVector = PCIVector >> 1;
+ }
+
+ }
+
+ } else {
+
+ PCIVector = READ_PORT_UCHAR((PUCHAR)INTERRUPT_MASK1_QVA) & IntMask1;
+
+ if (PCIVector) {
+
+ for (IntNumber = 0; IntNumber < 8; IntNumber++) {
+
+ if (PCIVector & 0x01) {
+ IdtIndex = IntNumber + 8;
+ break;
+ } else {
+ PCIVector = PCIVector >> 1;
+ }
+
+ }
+
+ } else {
+
+ PCIVector = READ_PORT_UCHAR((PUCHAR)INTERRUPT_MASK2_QVA) & IntMask2;
+
+ for (IntNumber = 0; IntNumber < 8; IntNumber++) {
+
+ if (PCIVector & 0x01) {
+ IdtIndex = IntNumber + 16;
+ break;
+ } else {
+ PCIVector = PCIVector >> 1;
+ }
+
+ }
+
+ }
+
+ }
+
+ //
+ // If no PCI interrupt is enabled and asserted then this is a passive
+ // release.
+ //
+
+ if( IdtIndex > PCI_MAX_INTERRUPT ){
+
+#if HALDBG
+
+ DbgPrint( "HalpDeviceDispatch: PCI Passive Release.\n" );
+
+#endif //HALDBG
+
+ return FALSE;
+
+ }
+
+ IdtIndex += PCI_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ return( ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame) );
+
+}
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ebsgdma.c b/private/ntos/nthals/haltimbr/alpha/ebsgdma.c
new file mode 100644
index 000000000..80a9fdfd3
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ebsgdma.c
@@ -0,0 +1,6 @@
+//
+// This file includes the source file from the Alcor HAL directory.
+//
+
+#include "..\halalcor\alpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ebsysint.c b/private/ntos/nthals/haltimbr/alpha/ebsysint.c
new file mode 100644
index 000000000..a597a13b9
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ebsysint.c
@@ -0,0 +1,425 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ebsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the EB164 system.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eb164.h"
+
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // disable the ISA interrrupt.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the ISA interrupts, then
+ // enable the ISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= ISA_VECTORS &&
+ Vector < MAXIMUM_ISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnableSioInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnablePciInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus ISA_VECTORS.
+ // N.B.: this encoding technique uses the notion of defining a
+ // base interrupt vector in the space defined by the constant,
+ // ISA_VECTORS, which may or may not differ from EISA_VECTORS or
+ // PCI_VECTORS.
+ //
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR
+ //
+ // N.B. The BusInterruptLevel is one-based while the vectors
+ // themselves are zero-based. The BusInterruptLevel must be
+ // one-based because if scsiport sees a zero vector then it
+ // will believe the interrupt is not connected. So in PCI
+ // configuration we have made the interrupt vector correspond
+ // to the slot and interrupt pin.
+ //
+
+ return( (BusInterruptLevel - 1) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on EB164 systems.
+ //
+
+#if defined(HALDBG)
+
+ DbgPrint("EBSYSINT: InterfaceType (%x) not supported on EB164\n",
+ InterfaceType);
+
+#endif
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an EB164 because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/haltimbr/alpha/eisasup.c b/private/ntos/nthals/haltimbr/alpha/eisasup.c
new file mode 100644
index 000000000..6cec04bf6
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/eisasup.c
@@ -0,0 +1,6 @@
+//
+// This file includes the source file from the Alcor HAL directory.
+//
+
+#include "..\halalcor\alpha\eisasup.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/environ.c b/private/ntos/nthals/haltimbr/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ev5cache.c b/private/ntos/nthals/haltimbr/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ev5int.c b/private/ntos/nthals/haltimbr/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ev5ints.s b/private/ntos/nthals/haltimbr/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ev5mchk.c b/private/ntos/nthals/haltimbr/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ev5mem.s b/private/ntos/nthals/haltimbr/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ev5prof.c b/private/ntos/nthals/haltimbr/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/flash8k.c b/private/ntos/nthals/haltimbr/alpha/flash8k.c
new file mode 100644
index 000000000..4d59fc2f7
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/flash8k.c
@@ -0,0 +1 @@
+#include "../halalpha/flash8k.c"
diff --git a/private/ntos/nthals/haltimbr/alpha/flashdrv.c b/private/ntos/nthals/haltimbr/alpha/flashdrv.c
new file mode 100644
index 000000000..ad0994d4d
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/flashdrv.c
@@ -0,0 +1,3 @@
+#include "../halalpha/flashdrv.c"
+
+
diff --git a/private/ntos/nthals/haltimbr/alpha/fwreturn.c b/private/ntos/nthals/haltimbr/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/haldebug.c b/private/ntos/nthals/haltimbr/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/halpal.s b/private/ntos/nthals/haltimbr/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/haltsup.s b/private/ntos/nthals/haltimbr/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/idle.s b/private/ntos/nthals/haltimbr/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/info.c b/private/ntos/nthals/haltimbr/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/inithal.c b/private/ntos/nthals/haltimbr/alpha/inithal.c
new file mode 100644
index 000000000..a79b38372
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/inithal.c
@@ -0,0 +1,6 @@
+//
+// This file includes the source file from the Alcor HAL directory.
+//
+
+#include "..\halalcor\alpha\inithal.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/intsup.s b/private/ntos/nthals/haltimbr/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/ioproc.c b/private/ntos/nthals/haltimbr/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/iousage.c b/private/ntos/nthals/haltimbr/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/machdep.h b/private/ntos/nthals/haltimbr/alpha/machdep.h
new file mode 100644
index 000000000..8dec64c29
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include EB164 platform-specific definitions.
+//
+
+#include "eb164.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/haltimbr/alpha/memory.c b/private/ntos/nthals/haltimbr/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/nvenv.c b/private/ntos/nthals/haltimbr/alpha/nvenv.c
new file mode 100644
index 000000000..ba5a5c8f7
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/nvenv.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvenv.c"
diff --git a/private/ntos/nthals/haltimbr/alpha/nvram.c b/private/ntos/nthals/haltimbr/alpha/nvram.c
new file mode 100644
index 000000000..879c41c68
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/nvram.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvram.c"
diff --git a/private/ntos/nthals/haltimbr/alpha/pcibus.c b/private/ntos/nthals/haltimbr/alpha/pcibus.c
new file mode 100644
index 000000000..a32e6bfcd
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pcibus.c
@@ -0,0 +1,6 @@
+//
+// This file includes the source file from the Alcor HAL directory.
+//
+
+#include "..\halalcor\alpha\pcibus.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/pcisio.c b/private/ntos/nthals/haltimbr/alpha/pcisio.c
new file mode 100644
index 000000000..43ff9900a
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pcisio.c
@@ -0,0 +1,493 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pic8259.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI SIO
+ programmable interrupt controller.
+
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Import save area for SIO interrupt mask registers.
+//
+
+UCHAR HalpSioInterrupt1Mask;
+UCHAR HalpSioInterrupt2Mask;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+
+VOID
+HalpInitializeSioInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 8259 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ return;
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO bus specified SIO bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2, it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+ }
+
+ }
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO bus specified SIO bus interrupt.
+Arguments:
+
+ Vector - Supplies the vector of the SIO interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= ISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+BOOLEAN
+HalpEB164SioDispatch(
+ PKINTERRUPT Interrupt,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to an interrupt object that
+ describes the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+ TrapFrame - Supplies a pointer to the interrupt trap frame.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR ISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ //ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase);
+ ISAVector = (UCHAR)INTERRUPT_ACKNOWLEDGE(ServiceContext);
+
+
+ if ((ISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return FALSE; // ecrfix - now returns a value
+
+ }
+
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = ISAVector + ISA_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PEB164_SECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (ISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+}
+
+
diff --git a/private/ntos/nthals/haltimbr/alpha/pcisup.c b/private/ntos/nthals/haltimbr/alpha/pcisup.c
new file mode 100644
index 000000000..c4432fd4b
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pcisup.c
@@ -0,0 +1,6 @@
+//
+// This file includes the source file from the Alcor HAL directory.
+//
+
+#include "..\halalcor\alpha\pcisup.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/pcrtc.c b/private/ntos/nthals/haltimbr/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/pcserial.c b/private/ntos/nthals/haltimbr/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/pcspeakr.c b/private/ntos/nthals/haltimbr/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/perfcntr.c b/private/ntos/nthals/haltimbr/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/haltimbr/alpha/pintolin.h b/private/ntos/nthals/haltimbr/alpha/pintolin.h
new file mode 100644
index 000000000..b60949dee
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/pintolin.h
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+ Chao Chen 6-Sept 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for EB164.
+//
+// EB164 PCI interrupts are mapped to arbitrary interrupt numbers
+// in the table below. The values are a 1-1 map of the bit numbers
+// in the EB164 PCI interrupt register that are connected to PCI
+// devices. N.B.: there are two other interrupts in this register,
+// but they are not connected to I/O devices, so they're not
+// represented in the table.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_MIKASA.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG EB164PCIPinToLineTable[][4]=
+{
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0x3, 0x8, 0xc, 0x10 }, // Virtual Slot 5 = PCI_AD[16] bridge
+ { 0x1, 0x6, 0xa, 0xe }, // Virtual Slot 6 = PCI_AD[17] Slot #0
+ { 0x2, 0x7, 0xb, 0xf }, // Virtual Slot 7 = PCI_AD[18] Slot #1
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] SIO
+ { 0x4, 0x9, 0xd, 0x11 }, // Virtual Slot 9 = PCI_AD[20] Slot #2
+ { 0x12, 0x13, 0x14, 0x15 } // Virtual Slot 10 = PCI_AD[21] Slot #3
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+// { 0x03, 0x08, 0x0c, 0x10 }, // Virtual Slot 5 = PCI_AD[16] PCI Slot 2
+// { 0x01, 0x06, 0x0a, 0x0e }, // Virtual Slot 6 = PCI_AD[17] PCI Slot 0
+// { 0x02, 0x07, 0x0b, 0x0f }, // Virtual Slot 7 = PCI_AD[18] PCI Slot 1
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] PCI/ISA Bridge
+// { 0x04, 0x09, 0x0d, 0x11 }, // Virtual Slot 9 = PCI_AD[20] PCI Slot 3
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 11 = PCI_AD[22]
+// { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 12 = PCI_AD[23]
+};
+
diff --git a/private/ntos/nthals/haltimbr/alpha/vga.c b/private/ntos/nthals/haltimbr/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/haltimbr/drivesup.c b/private/ntos/nthals/haltimbr/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haltimbr/hal.rc b/private/ntos/nthals/haltimbr/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haltimbr/hal.src b/private/ntos/nthals/haltimbr/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haltimbr/makefile b/private/ntos/nthals/haltimbr/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haltimbr/makefile.inc b/private/ntos/nthals/haltimbr/makefile.inc
new file mode 100644
index 000000000..07b5f7b33
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ cl /EP hal.src -DALPHA=1 $(C_DEFINES) > obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\haleb164.lib
+ copy $** $@
diff --git a/private/ntos/nthals/haltimbr/sources b/private/ntos/nthals/haltimbr/sources
new file mode 100644
index 000000000..aad59034c
--- /dev/null
+++ b/private/ntos/nthals/haltimbr/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haltimbr
+TARGETPATH=\nt\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DTAGGED_NVRAM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\28f008sa.c \
+ alpha\29f040.c \
+ alpha\adjust.c \
+ alpha\allstart.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cia.c \
+ alpha\ciaaddr.c \
+ alpha\ciaerr.c \
+ alpha\ciaio.s \
+ alpha\ciamapio.c \
+ alpha\devintr.s \
+ alpha\ev5cache.c \
+ alpha\ev5int.c \
+ alpha\ev5mchk.c \
+ alpha\ev5mem.s \
+ alpha\ev5ints.s \
+ alpha\ev5prof.c \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\haltsup.s \
+ alpha\info.s \
+ alpha\idle.s \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\ioproc.c \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\nvenv.c \
+ alpha\nvram.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\pcibus.c \
+ alpha\pcisup.c \
+ alpha\busdata.c \
+ alpha\eb164err.c \
+ alpha\ebinitnt.c \
+ alpha\ebintsup.c \
+ alpha\ebsysint.c \
+ alpha\flash8k.c \
+ alpha\flashdrv.c \
+ alpha\pcisio.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/haltyne/drivesup.c b/private/ntos/nthals/haltyne/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/haltyne/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/haltyne/hal.rc b/private/ntos/nthals/haltyne/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haltyne/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/haltyne/hal.src b/private/ntos/nthals/haltyne/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/haltyne/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/haltyne/makefile b/private/ntos/nthals/haltyne/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haltyne/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/haltyne/makefile.inc b/private/ntos/nthals/haltyne/makefile.inc
new file mode 100644
index 000000000..380081341
--- /dev/null
+++ b/private/ntos/nthals/haltyne/makefile.inc
@@ -0,0 +1,6 @@
+obj\mips\hal.def: hal.src
+ rcpp -P -f hal.src -DMIPS=1 $(C_DEFINES) -g obj\mips\hal.def
+
+$(TARGETPATH)\mips\hal.lib: $(TARGETPATH)\mips\haltyne.lib
+ copy $** $@
+
diff --git a/private/ntos/nthals/haltyne/mips/allstart.c b/private/ntos/nthals/haltyne/mips/allstart.c
new file mode 100644
index 000000000..8d81b6eb8
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/allstart.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haltyne/mips/dtidef.h b/private/ntos/nthals/haltyne/mips/dtidef.h
new file mode 100644
index 000000000..af7640d58
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/dtidef.h
@@ -0,0 +1,112 @@
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jazzdef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 26-Nov-1990
+
+Revision History:
+
+--*/
+
+#ifndef _DTIDEF_
+#define _DTIDEF_
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define the data structure returned by a private vector firmware function
+// that contains a set of system parameters.
+//
+
+typedef struct _HAL_SYSTEM_PARAMETERS {
+ ULONG Version;
+ ULONG SecondaryCacheSize;
+ ULONG DmaCacheSize;
+} HAL_SYSTEM_PARAMETERS, *PHAL_SYSTEM_PARAMETERS;
+
+//
+// Define physical base addresses for system mapping.
+//
+
+#define EISA_CONTROL_PHYSICAL_BASE_HI 0x00000009 // physical base of EISA control TYNE 2.1
+#define EISA_CONTROL_PHYSICAL_BASE_LO 0x00000000 // physical base of EISA control TYNE 2.1
+#define EISA_MEMORY_PHYSICAL_BASE_HI 0x00000001 // physical base of EISA memory
+#define EISA_MEMORY_PHYSICAL_BASE_LO 0x00000000 // physical base of EISA memory
+#define DMA_CACHE_PHYSICAL_BASE_HI 0x00000001 // physical base of DMA cache
+#define DMA_CACHE_PHYSICAL_BASE_LO 0x00800000 // physical base of DMA cache
+
+//
+// Define EISA NMI interrupt level.
+//
+
+#define EISA_NMI_LEVEL 6
+
+//
+// Define the maximum and minimum time increment values in 100ns units.
+//
+// N.B. these values are as close to exact values as possible given the input
+// clock of 1.19318167 hz (14.31818 / 12)
+//
+
+#define MAXIMUM_INCREMENT (99968) // Time increment in 100ns units - Approx 10 ms
+#define MINIMUM_INCREMENT (10032) // Time increment in 100ns units - Approx 1 ms
+
+//
+// Define clock constants and clock levels.
+//
+
+#define AT_BUS_OSC 14318180 // 14.31818 MHz Crystal
+#define CLOCK_LEVEL 32 // Interval clock level
+
+#if defined(R4000)
+
+#define EISA_DEVICE_LEVEL 5 // EISA bus interrupt level
+
+#endif
+
+#define CLOCK2_LEVEL CLOCK_LEVEL //
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define EISA_VECTORS 32
+
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+#endif // _DTIDEF_
diff --git a/private/ntos/nthals/haltyne/mips/halp.h b/private/ntos/nthals/haltyne/mips/halp.h
new file mode 100644
index 000000000..c8a592a89
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/halp.h
@@ -0,0 +1,154 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "dtidef.h"
+#include "hal.h"
+#include "jxhalp.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define function prototypes.
+//
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID HalpResetIsaBus (
+ IN ULONG DelayCount
+ );
+
+VOID HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+VOID HalpProgramIntervalTimer(
+ IN ULONG IntervalCount
+ );
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG1_BASE)) ? TRUE : FALSE)
+
+//
+// Define external references.
+//
+
+extern PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/haltyne/mips/j4cache.s b/private/ntos/nthals/haltyne/mips/j4cache.s
new file mode 100644
index 000000000..a5b557324
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/j4cache.s
@@ -0,0 +1,1326 @@
+#if defined(R4000)
+
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30:
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,ZpA1(sp) // get old color value
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
+
+ SBTTL("Copy Page To Dma Cache")
+//++
+//
+// VOID
+// HalCopyPageToDmaCache (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// IN ULONG Destination,
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the copy.
+//
+// Destination(a3) - Supplies the destination of the copy.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalCopyPageToDmaCache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10:
+ mfc0 t3,wired // get contents of wired register
+ nop // fill
+ addu t5,t3,1 // allocate TB entry
+ mtc0 t5,wired //
+
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ and a3,a3,t6 // compute starting virtual address for destination
+
+//
+// Copy page from memory to DMA cache.
+//
+
+20:
+ ldc1 f0,0x0(t8)
+ ldc1 f2,0x8(t8)
+ ldc1 f4,0x10(t8)
+ ldc1 f6,0x18(t8)
+ sdc1 f0,0x0(a3)
+ sdc1 f2,0x8(a3)
+ sdc1 f4,0x10(a3)
+ sdc1 f6,0x18(a3)
+
+ addu a3,a3,t4
+ bne t8,t9,20b
+ addu t8,t8,t4
+
+ mtc0 t3,wired //
+
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalCopyPageToDmaCache
+
+ SBTTL("Copy Page From Dma Cache")
+//++
+//
+// VOID
+// HalCopyPageFromDmaCache (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// IN ULONG Destination,
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the copy.
+//
+// Destination(a3) - Supplies the destination of the copy.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalCopyPageFromDmaCache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10:
+ mfc0 t3,wired // get contents of wired register
+ nop // fill
+ addu t5,t3,1 // allocate TB entry
+ mtc0 t5,wired //
+
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ and a3,a3,t6 // compute starting virtual address for destination
+
+//
+// Copy page from DMA cache to memory.
+//
+
+20:
+ ldc1 f0,0x0(a3)
+ ldc1 f2,0x8(a3)
+ ldc1 f4,0x10(a3)
+ ldc1 f6,0x18(a3)
+ sdc1 f0,0x0(t8)
+ sdc1 f2,0x8(t8)
+ sdc1 f4,0x10(t8)
+ sdc1 f6,0x18(t8)
+
+
+ addu a3,a3,t4
+ bne t8,t9,20b
+ addu t8,t8,t4
+
+ mtc0 t3,wired //
+
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalCopyPageFromDmaCache
+
+ SBTTL("Reset ISA Bus")
+//++
+//
+// VOID
+// HalpResetIsaBus (
+// IN ULONG DelayCount
+// )
+//
+// Routine Description:
+//
+// This function resets all add in cards in the ISA/VESA bus.
+//
+// Arguments:
+//
+// DelayCount(a0) - Supplies the number of 2 processor cycle iterations to delay
+// from the time at ISA Reset is asserted till ISA Reset is deasserted.
+// DelayCount is choosen so that a 200 MHz ORION will stall for at least
+// 1 ms.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpResetIsaBus)
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts to prevent external processor
+ // transactions during reset.
+ lw t1,HalpEisaControlBase // Get virtual address of ISA/VESA I/O Space
+ li t0,0x20
+ sb t0,0x22(t1) // Select OPTI register 0x20
+ li t0,0x02
+ sb t0,0x24(t1) // Write 0x02 to OPTI register 0x20 : Enable ISA reset
+ j 10f // Jump to a cache line aligned segment of code
+
+ .set noreorder
+ .set noat
+
+//
+// These next 8 instructions(32 byte line) will be loaded on a potential cache refill here.
+// This guarantees that the ISA/VESA reset and delay loop will be be in the primary Icache.
+// This is necessary to prevent any external processor transactions during the reset sequence.
+//
+
+ .align 5 // align code on a cache line boundry
+10:
+ li t0,0xfe
+ sb t0,0x64(t1) // Reset ISA Bus
+ sync // Flush write buffer -> Forces ISA reset NOW.
+
+ or t0,zero,zero // Delay so LogiCore chip set can complete reset
+20:
+ bne t0,a0,20b
+ addiu t0,t0,0x01
+
+//
+// Instruction alignment to cache lines does not matter after this point.
+//
+
+ .set reorder
+ .set at
+
+ li t0,0x00 // Send a value to a post card to gurantee the
+ sb t0,0x80(t1) // generation of a HADS on the ISA/VESA bus.
+ sync // This will deassert ISA reset.
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra
+
+ .end HalpResetIsaBus
+
+#endif
diff --git a/private/ntos/nthals/haltyne/mips/j4flshbf.s b/private/ntos/nthals/haltyne/mips/j4flshbf.s
new file mode 100644
index 000000000..ff3a32f78
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/j4flshbf.s
@@ -0,0 +1,61 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/haltyne/mips/j4flshio.c b/private/ntos/nthals/haltyne/mips/j4flshio.c
new file mode 100644
index 000000000..c17e762d7
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/j4flshio.c
@@ -0,0 +1,166 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, export or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepDcache();
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == TRUE) {
+ if (DmaOperation == FALSE) {
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+
+ } while(Length != 0);
+ }
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/haltyne/mips/j4prof.c b/private/ntos/nthals/haltyne/mips/j4prof.c
new file mode 100644
index 000000000..3fa8ecc4d
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/j4prof.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter;
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter;
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ HalpPerformanceCounter.QuadPart = 0;
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxbeep.c b/private/ntos/nthals/haltyne/mips/jxbeep.c
new file mode 100644
index 000000000..cb04082f4
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxbeep.c
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = (AT_BUS_OSC/12) / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeLowerIrql(oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxdisp.c b/private/ntos/nthals/haltyne/mips/jxdisp.c
new file mode 100644
index 000000000..2673bf403
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxdisp.c
@@ -0,0 +1,249 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ Andre Vachon (andreva) 09-May-1992
+ David N. Cutler (davec) 27-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "string.h"
+
+#define CSI 0x9b
+
+int sprintf();
+
+extern ULONG IoSpaceAlreadyMapped;
+
+static UCHAR DisplayInitializationString[] = {CSI,'3','7',';','4','4','m',CSI,'2','J',0};
+static UCHAR CarriageReturnString[] = {13,0};
+
+static ULONG HalOwnsDisplay = FALSE;
+static ULONG DisplayFile;
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ArcClose(DisplayFile);
+ HalOwnsDisplay = FALSE;
+
+ HalpResetDisplayParameters = ResetDisplayParameters;
+
+ return;
+}
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Count;
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ HalpMapIoSpace();
+ HalpInitializeX86DisplayAdapter();
+ IoSpaceAlreadyMapped = TRUE;
+ }
+
+ if (HalOwnsDisplay==FALSE) {
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+ ArcOpen(ArcGetEnvironmentVariable("ConsoleOut"),ArcOpenWriteOnly,&DisplayFile);
+ ArcWrite(DisplayFile,DisplayInitializationString,strlen(DisplayInitializationString),&Count);
+ HalOwnsDisplay=TRUE;
+
+ }
+
+ ArcWrite(DisplayFile,String,strlen(String),&Count);
+ ArcWrite(DisplayFile,CarriageReturnString,strlen(CarriageReturnString),&Count);
+
+ return;
+
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_DISPLAY_STATUS *DisplayStatus;
+
+ //
+ // Get the display parameter values and return.
+ //
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Make firmware call to get the display's current status
+ //
+
+ DisplayStatus = ArcGetDisplayStatus(DisplayFile);
+
+ *WidthInCharacters = DisplayStatus->CursorMaxXPosition;
+ *HeightInLines = DisplayStatus->CursorMaxYPosition;
+ *CursorColumn = DisplayStatus->CursorXPosition;
+ *CursorRow = DisplayStatus->CursorYPosition;
+
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHAR SetCursorPositionString[20];
+ ULONG Count;
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Build ANSI sequence to set the cursor position.
+ //
+
+ sprintf(SetCursorPositionString,"%c%d;%dH",CSI,CursorRow,CursorColumn);
+ ArcWrite(DisplayFile,SetCursorPositionString,strlen(SetCursorPositionString),&Count);
+
+ return;
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxebsup.c b/private/ntos/nthals/haltyne/mips/jxebsup.c
new file mode 100644
index 000000000..f4ad83dec
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxebsup.c
@@ -0,0 +1,2182 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "dtidef.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+extern PVOID HalpEisaControlBase;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ );
+
+VOID HalCopyPageToDmaCache();
+VOID HalCopyPageFromDmaCache();
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. This field is
+ updated with the number of registers allocated in the event that less
+ were available than requested.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ UCHAR channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+ ULONG maximumLength;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!eisaSystem &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = (UCHAR)(DeviceDescriptor->DmaChannel & 0x03);
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch (channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (eisaSystem) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ adapterObject->MasterDevice = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+ ULONG partialLength;
+ ULONG temp;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) & 0x03ffffff;
+
+ transferLength = *Length;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ // If *pageFrame is less than 4 GB than this is in main memory, and it has to be mapped.
+ // Otherwise, it is a buffer that was allocated with HalAllocateCommonBuffer, and should
+ // not be mapped.
+
+ if (MapRegisterBase != NULL && (*pageFrame < 0x100000)) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+
+ //
+ // Force IoMapTransfer() to use the map buffer.
+ //
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress + pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ temp = transferLength;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= *Length ) {
+
+ HalCopyPageToDmaCache((PUCHAR)CurrentVa,
+ *pageFrame,
+ partialLength,
+ (ULONG)((translationEntry+index)->VirtualAddress)+BYTE_OFFSET(CurrentVa));
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = *Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalCopyPageToDmaCache((PUCHAR)CurrentVa,
+ *pageFrame,
+ partialLength,
+ (ULONG)((translationEntry+index)->VirtualAddress)+BYTE_OFFSET(CurrentVa));
+
+ }
+
+ transferLength = temp;
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+ PVOID OriginalCurrentVa;
+
+ OriginalCurrentVa = CurrentVa;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ //
+ // If there are no map registers being used then just return TRUE.
+ //
+ // If *pageFrame is above 4GB, then the buffer was allocated by HalAllocateCommonBuffer,
+ // and is does not needs to be copied back, so just return TRUE.
+ //
+
+ if (MapRegisterBase == NULL || (*pageFrame >= 0x100000)) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ HalCopyPageFromDmaCache((PUCHAR)CurrentVa,
+ *pageFrame,
+ partialLength,
+ (ULONG)(translationEntry->VirtualAddress)+BYTE_OFFSET(CurrentVa));
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalCopyPageFromDmaCache((PUCHAR)CurrentVa,
+ *pageFrame,
+ partialLength,
+ (ULONG)(translationEntry->VirtualAddress)+BYTE_OFFSET(CurrentVa));
+
+ }
+
+ //
+ // If this is a page read then flush the buffer from the primary data cache so
+ // it can be potentially read into the primary istruction cache.
+ //
+
+ if ( (Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ HalSweepDcache();
+
+ }
+ else {
+
+ CurrentVa = OriginalCurrentVa;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ HalFlushDcachePage(CurrentVa,*pageFrame,partialLength);
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ transferLength += partialLength;
+ pageFrame++;
+ }
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalFlushDcachePage(CurrentVa,*pageFrame,partialLength);
+ }
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+// //
+// // Initialize the EISA NMI interrupt.
+// //
+//
+//
+// PCR->InterruptRoutine[EISA_NMI_LEVEL] = HalHandleNMI;
+//
+// //
+// // Clear the Eisa NMI disable bit. This bit is the high order of the
+// // NMI enable register.
+// //
+//
+// DataByte = 0;
+// //
+// // TEMPTEMP Disable the NMI because this is causing machines in the build
+// // lab to fail.
+// //
+// DataByte = 0x80;
+//
+// WRITE_REGISTER_UCHAR(
+// &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+// DataByte
+// );
+
+ //
+ // Initialize the EISA interrupt dispatcher for ArcStation I/O interrupts.
+ //
+
+
+ PCR->InterruptRoutine[EISA_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch;
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second level
+ interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PULONG dispatchCode;
+ PKINTERRUPT interruptObject;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue;
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector =
+ READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector != 0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset = interruptVector + EISA_VECTORS;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ //
+ // The interrupt vector for CLOCK2_LEVEL is directly connected by the HAL.
+ // If the interrupt is on CLOCK2_LEVEL then vector to the address stored
+ // in the PCR. Otherwise, bypass the thunk code in the interrupt object
+ // whose address is stored in the PCR.
+ //
+
+ if (PCRInOffset == CLOCK2_LEVEL) {
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])
+ (PCR->InterruptRoutine[PCRInOffset]);
+
+ } else {
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+ }
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ } else {
+
+ //
+ // This interrupt is on the second interrupt controller
+ //
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ PCRInOffset = interruptVector + 8 + EISA_VECTORS;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ }
+ }
+ }
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxenvirv.c b/private/ntos/nthals/haltyne/mips/jxenvirv.c
new file mode 100644
index 000000000..3d69ac268
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxenvirv.c
@@ -0,0 +1,98 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+#include "string.h"
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+ CHAR *Value;
+
+ Value = ArcGetEnvironmentVariable(Variable);
+ if (Value==NULL)
+ return(ENOENT);
+ if (strlen(Value)>Length)
+ return(ENOENT);
+ strcpy(Buffer,Value);
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+ return(ArcSetEnvironmentVariable(Variable,Value));
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxhalp.h b/private/ntos/nthals/haltyne/mips/jxhalp.h
new file mode 100644
index 000000000..42d5cdf9a
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxhalp.h
@@ -0,0 +1,105 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/haltyne/mips/jxhwsup.c b/private/ntos/nthals/haltyne/mips/jxhwsup.c
new file mode 100644
index 000000000..bda765bad
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxhwsup.c
@@ -0,0 +1,1882 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+extern PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ BOOLEAN eisaSystem;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(HalpMapBufferSize) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+
+ // On an R4000 system, this space should be mapped with caches
+ // disabled to avoid having to perform page exports on IO writes
+ // and page purges on IO reads.
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disabled.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!eisaSystem &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough HalpMapBufferSize / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject,HalpMapBufferSize))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ UCHAR SavedNeedsMapRegisters;
+ ULONG SavedMapRegistersPerChannel;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMapRegistersPerChannel = AdapterObject->MapRegistersPerChannel;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG)mapRegisterBase & ~NO_SCATTER_GATHER);
+ LogicalAddress->HighPart = 0;
+ LogicalAddress->LowPart = translationEntry->PhysicalAddress;
+ virtualAddress = translationEntry->VirtualAddress; // TYNE
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+
+ return(virtualAddress);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+ UCHAR SavedNeedsMapRegisters;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ if (MasterAdapterObject != NULL) {
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = (LogicalAddress.LowPart - HalpMapBufferPhysicalAddress.LowPart) >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+
+ }
+
+ return;
+
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+
+//
+// Adaptec and Buslogic SCSI Miniport crashes unless EISA addresses can be translated.
+//
+
+//
+// if (InterfaceType != Isa) {
+//
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ TranslatedAddress->HighPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Jazz only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->HighPart = EISA_CONTROL_PHYSICAL_BASE_HI;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE_LO;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart += 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->HighPart = EISA_MEMORY_PHYSICAL_BASE_HI;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE_LO;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart += 1;
+ }
+ return(TRUE);
+
+ }
+}
+
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ return 0;
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ return HalpCreateEisaStructures();
+
+}
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxmapio.c b/private/ntos/nthals/haltyne/mips/jxmapio.c
new file mode 100644
index 000000000..255bc0549
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxmapio.c
@@ -0,0 +1,139 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+typedef
+VOID
+(*PSET_VIRTUAL_BASE) (
+ IN ULONG Number,
+ IN PVOID Base
+ );
+
+PSET_VIRTUAL_BASE PrivateSetVirtualBase;
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase;
+PVOID HalpRealTimeClockBase;
+
+ULONG FirmwareMapped = FALSE;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = (PSYSTEM_PARAMETER_BLOCK)(0x80001000);
+
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.HighPart = EISA_CONTROL_PHYSICAL_BASE_HI;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE_LO;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.HighPart = EISA_CONTROL_PHYSICAL_BASE_HI;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE_LO + 0x71;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map ISA Memory Space.
+ //
+
+ physicalAddress.HighPart = EISA_MEMORY_PHYSICAL_BASE_HI;
+ physicalAddress.LowPart = EISA_MEMORY_PHYSICAL_BASE_LO;
+ HalpEisaMemoryBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase == NULL) ||
+ (HalpRealTimeClockBase == NULL) ||
+ (HalpEisaMemoryBase == NULL)) {
+ return FALSE;
+ }
+
+ //
+ // Call private vector function SetVirtualBase so that the firmware functions for
+ // the display controller can print characters to the screen. If SetVirtualBase does
+ // not exist, then print an error message out the debug port and halt the system.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 28) {
+
+ PrivateSetVirtualBase = *(PSET_VIRTUAL_BASE *)((ULONG)(SystemParameterBlock->VendorVector) + 28*4);
+ PrivateSetVirtualBase(0, HalpEisaControlBase);
+ PrivateSetVirtualBase(1, HalpEisaMemoryBase);
+ FirmwareMapped = TRUE;
+
+ } else {
+
+ KdPrint(("HAL : SetVirtualBase does not exist. Halting\n"));
+ for(;;);
+
+ }
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxport.c b/private/ntos/nthals/haltyne/mips/jxport.c
new file mode 100644
index 000000000..db7e35159
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxport.c
@@ -0,0 +1,878 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+#define SP_VIRTUAL_BASE 0xffffa000
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)(SP_VIRTUAL_BASE + 0x3F8))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SP_VIRTUAL_BASE + 0x3F8))
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 6;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 1843200.
+ //
+
+ BaudClock = 1843200;
+
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = (ULONG)(((EISA_CONTROL_PHYSICAL_BASE_HI << 28) | (EISA_CONTROL_PHYSICAL_BASE_LO >> 4)) >> 8);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry and set the noncached bit in the PTE that will
+ // map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+ HalpPte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+#endif
+
+// KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+ KdComPortInUse=(PUCHAR)0x3f8;
+
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff));
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG KdPortEntry;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+
+#endif
+
+ //
+ // Map the serial controller through a allocated TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
+
+
diff --git a/private/ntos/nthals/haltyne/mips/jxreturn.c b/private/ntos/nthals/haltyne/mips/jxreturn.c
new file mode 100644
index 000000000..77fecf3af
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxreturn.c
@@ -0,0 +1,90 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ UCHAR DataByte;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+ ArcReboot();
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxsysint.c b/private/ntos/nthals/haltyne/mips/jxsysint.c
new file mode 100644
index 000000000..4f0d8865b
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxsysint.c
@@ -0,0 +1,259 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This functionr returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ *Affinity = 1;
+
+//
+// The BusLogic 445 VESA SCSI Host Adapter will not work unless an InterfaceType of
+// Eisa is also allowed here.
+//
+
+//
+// if (InterfaceType != Isa) {
+//
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+
+ }
+
+ //
+ // Jazz only has one I/O bus which is an EISA, so the bus number and the
+ // bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxtime.c b/private/ntos/nthals/haltyne/mips/jxtime.c
new file mode 100644
index 000000000..12f89485a
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxtime.c
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+#define BCDToBinary(D) (10 * (((D) & 0xf0) >>4 ) + ((D) & 0x0f))
+#define BinaryToBCD(B) ((((B) & 0xff) / 10) << 4 ) | (((B) & 0xff) % 10)
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_YEAR));
+ if (TimeFields->Year < 1992)
+ TimeFields->Year += 100;
+ TimeFields->Month = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MONTH));
+ TimeFields->Day = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_MONTH));
+ TimeFields->Weekday = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_WEEK)) - 1;
+ TimeFields->Hour = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_HOUR));
+ TimeFields->Minute = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MINUTE));
+ TimeFields->Second = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_SECOND));
+ TimeFields->Milliseconds = 0;
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN HalSetRealTimeClock (IN PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DayLightSavingsEnable = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(BinaryToBCD(TimeFields->Year - 1900)));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)BinaryToBCD(TimeFields->Month));
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)BinaryToBCD(TimeFields->Day));
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(BinaryToBCD(TimeFields->Weekday + 1)));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)BinaryToBCD(TimeFields->Hour));
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)BinaryToBCD(TimeFields->Minute));
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)BinaryToBCD(TimeFields->Second));
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+
+ return;
+}
diff --git a/private/ntos/nthals/haltyne/mips/jxusage.c b/private/ntos/nthals/haltyne/mips/jxusage.c
new file mode 100644
index 000000000..0c1d01efc
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/jxusage.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+Author:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/haltyne/mips/x4clock.s b/private/ntos/nthals/haltyne/mips/x4clock.s
new file mode 100644
index 000000000..9b20f0e03
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/x4clock.s
@@ -0,0 +1,210 @@
+#if defined(R4000)
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // Get current time increment
+ jal KeUpdateSystemTime // update system time
+ lw t0,HalpNextTimeIncrement // Get NextTimeIncrement
+ sw t0,HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+ lw a0,HalpNextIntervalCount // Get Next Interval Count. If 0, then no change required
+ beq zero,a0,5f // See if time increment is to be changed
+ jal HalpProgramIntervalTimer // Program timer with new interval count value
+ lw t0,HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ sw t0,HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+ sw zero,HalpNextIntervalCount // Set HalpNextIntervalCount to 0
+5:
+ lw t0,KdDebuggerEnabled // check if debugger enabled
+ lbu t0,0(t0) //
+ beq zero,t0,10f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,10f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+10: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ la t1,HalpPerformanceCounter // get performance counter address
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ j KeProfileInterrupt // process profile entries
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+#endif
diff --git a/private/ntos/nthals/haltyne/mips/x4tb.s b/private/ntos/nthals/haltyne/mips/x4tb.s
new file mode 100644
index 000000000..d399da2ac
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/x4tb.s
@@ -0,0 +1,109 @@
+#if defined(R4000)
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/haltyne/mips/x86bios.c b/private/ntos/nthals/haltyne/mips/x86bios.c
new file mode 100644
index 000000000..c31a8baf5
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/x86bios.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+typedef struct FIRMWARE_INT_ARGUMENTS {
+ ULONG pEAX;
+ ULONG pEBX;
+ ULONG pECX;
+ ULONG pEDX;
+ ULONG pESI;
+ ULONG pEDI;
+ ULONG pEBP;
+ USHORT pES;
+ USHORT pDS;
+ USHORT pFlags;
+} FIRMWARE_INT_ARGUMENTS, *PFIRMWARE_INT_ARGUMENTS;
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+ULONG HalpUseFirmwareX86Emulator = FALSE;
+
+typedef
+VOID
+(*PVENDOR_EXECUTE_INT) (
+ IN USHORT Type,
+ IN PFIRMWARE_INT_ARGUMENTS Context
+ );
+
+PVENDOR_EXECUTE_INT VendorX86ExecuteInt;
+
+VOID HalpInitializeX86DisplayAdapter()
+
+{
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = (PSYSTEM_PARAMETER_BLOCK)(0x80001000);
+
+ //
+ // If EISA I/O Ports or EISA Memory could not be mapped, then leave the
+ // X86 BIOS Emulator disabled.
+ //
+
+ if (HalpEisaControlBase == NULL || HalpEisaMemoryBase == NULL) {
+
+// DbgPrint("X86 BIOS Emulator Disabled\n");
+
+ return;
+ }
+
+ //
+ // If Firmware level X86 Bios Emulator exists, then use that instead of the
+ // one built into the HAL.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength/4) >= 34) {
+
+ VendorX86ExecuteInt =
+ *(PVENDOR_EXECUTE_INT *)((ULONG)(SystemParameterBlock->VendorVector) + 34*4);
+
+ if (VendorX86ExecuteInt != NULL) {
+ HalpX86BiosInitialized = TRUE;
+ HalpUseFirmwareX86Emulator = TRUE;
+ HalpEnableInt10Calls = TRUE;
+
+// DbgPrint("Firmware X86 BIOS Emulator Enabled\n");
+// DbgPrint("INT 10 Calls Enabled\n");
+
+ return;
+ }
+ }
+
+// DbgPrint("HAL X86 BIOS Emulator Enabled\n");
+
+ x86BiosInitializeBios(HalpEisaControlBase, HalpEisaMemoryBase);
+
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the Display Adapter by executing the Display Adapters
+ // initialization code in its BIOS. The standard for PC video adapters is for
+ // the BIOS to reside at 0xC000:0000 on the ISA bus.
+ //
+
+// DbgPrint("X86BiosInitializeAdapter(0xc0000)\n");
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+
+// DbgPrint("INT 10 Calls Disabled\n");
+
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+// DbgPrint("INT 10 Calls Enabled\n");
+}
+
+VOID HalpResetX86DisplayAdapter()
+
+{
+ XM86_CONTEXT Context;
+
+ //
+ // Make INT 10 call to initialize 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ FIRMWARE_INT_ARGUMENTS Arguments;
+ XM86_CONTEXT Context;
+
+
+ //
+ // If the X86 BIOS Emulator has not been initialized then fail all INT calls.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return(FALSE);
+ }
+
+ //
+ // If the Video Adapter initialization failed, then we can not make INT 10 calls.
+ //
+
+ if (BiosCommand == 0x10 && HalpEnableInt10Calls == FALSE) {
+ return(FALSE);
+ }
+
+// DbgPrint("HalCallBios(%02X,%04X,%04X,%04X,%04X,%04X,%04X,%04X)\n",BiosCommand,*Eax,*Ebx,*Ecx,*Edx,*Esi,*Edi,*Ebp);
+
+ if (HalpUseFirmwareX86Emulator == TRUE) {
+
+ //
+ // Make private vector call to the emulator in the firmware.
+ //
+
+ Arguments.pEAX = *Eax;
+ Arguments.pEBX = *Ebx;
+ Arguments.pECX = *Ecx;
+ Arguments.pEDX = *Edx;
+ Arguments.pESI = *Esi;
+ Arguments.pEDI = *Edi;
+ Arguments.pEBP = *Ebp;
+ Arguments.pES = 0;
+ Arguments.pDS = 0;
+ Arguments.pFlags = 0;
+
+ VendorX86ExecuteInt((USHORT)BiosCommand,&Arguments);
+
+ *Eax = Arguments.pEAX;
+ *Ebx = Arguments.pEBX;
+ *Ecx = Arguments.pECX;
+ *Edx = Arguments.pEDX;
+ *Esi = Arguments.pESI;
+ *Edi = Arguments.pEDI;
+ *Ebp = Arguments.pEBP;
+
+ }
+ else {
+
+ //
+ // Make call to emulator build into HAL
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+
+ }
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haltyne/mips/x86bios.h b/private/ntos/nthals/haltyne/mips/x86bios.h
new file mode 100644
index 000000000..3989c675b
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/x86bios.h
@@ -0,0 +1,75 @@
+/*++ BUILD Version: 0011 // Increment this if a change has global effects
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.h
+
+Abstract:
+
+ This header file defines the interfaces to the x86 bios emulator.
+
+Author:
+
+ David N. Cutler (davec) 23-Jun-1994
+
+
+Revision History:
+
+--*/
+
+#ifndef _X86BIOS_
+#define _X86BIOS_
+
+#if !defined(_X86_)
+
+//
+// Define x86 bios emulator status codes.
+//
+
+typedef enum _X86BIOS_STATUS {
+ x86BiosSuccess, // X86 Emulator successfully executed adapter initialization or INT call.
+ x86BiosNoVideoBios, // Adapter can not be initialized because a BIOS signature was not found.
+ x86BiosInvalidChecksum, // Bad checksum for Video BIOS.
+ x86BiosInvalidInstruction, // X86 Emulator attempted to execute an invalid instruction.
+ x86BiosHaltInstruction, // X86 Emulator attempted to execute a HALT instruction.
+ x86BiosWaitInstruction, // X86 emulator attempted to execute a WAIT instruction.
+ x86BiosTrapFlagAsserted, // Trap flag became set. An INT 1 handler does not exist.
+ x86BiosDivideByZero // DIV or IDIV instruction attempted to divide by zero.
+ } X86BIOS_STATUS;
+
+//
+// Define x86 bios emulator context structure.
+//
+
+typedef struct _X86BIOS_CONTEXT {
+ ULONG Eax;
+ ULONG Ebx;
+ ULONG Ecx;
+ ULONG Edx;
+ ULONG Esi;
+ ULONG Edi;
+ ULONG Ebp;
+} X86BIOS_CONTEXT, *PX86BIOS_CONTEXT;
+
+X86BIOS_STATUS
+X86BiosInitializeAdapter(
+ ULONG Address
+ );
+
+X86BIOS_STATUS
+X86BiosExecuteInt(
+ USHORT Type,
+ PX86BIOS_CONTEXT Arguments
+ );
+
+VOID
+X86BiosInitialize(
+ ULONG IsaIoVirtualBase,
+ ULONG IsaMemoryVirtualBase
+ );
+
+#endif
+
+#endif // _x86BIOS_
diff --git a/private/ntos/nthals/haltyne/mips/x86lator.c b/private/ntos/nthals/haltyne/mips/x86lator.c
new file mode 100644
index 000000000..a325c1d5c
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/x86lator.c
@@ -0,0 +1,5881 @@
+/*++
+
+Copyright (c) 1994 DeskStation Technology, Inc.
+
+Module Name:
+
+ xxbios.c
+
+Abstract:
+
+ This module is an implementation of an 80286 emulator for performing
+ video adapter initialization and INT 10 video BIOS calls.
+
+ The main component of the emulator makes use of two lookup tables
+ for address and instruction decoding, and two variables of type
+ OPERAND that contain the decoded left and right operands. The
+ emulator looks at the first byte of the instruction. This 8 bit
+ value is used to lookup two functions in the DecodeOperandTable[].
+ The first function is called to decode the left operand, and the
+ second function is called to decode the right operand. The OPERAND
+ data type can contain a register, an immediate value, or a memory
+ location. The functions GetOperand() and PutOperand() allow the
+ values of the left and right operand to be retrieved and stored.
+ The DecodeInstructionTable[] is used to lookup the function to call
+ to execute the instruction once the left and right operands have been
+ decoded. The instruction type can be determined from the 8 bits in
+ the first byte of the instruction and bits 3-5 of the second byte
+ of the instruction. These 11 bits are used to lookup the appropriate
+ function in DecodeInstructionTable[]. This function is called. The
+ function associated with each instruction modifies the state of the
+ 80286's internal registers, and the state of the memory system. The
+ address decode functions will have already moved the instruction
+ pointer to the beginning of the next instruction, so the main loop
+ of the emulator calls the address decode functions and the
+ instruction functions until the exit condition is met.
+
+ The emulator is invoked in two different ways. The first is when
+ the emulator is initialized. This initializes the state of all the
+ internal registers, and the state of the memory system. Then, a
+ check is made to see if a valid video BIOS is present in ISA memory.
+ If one is found, the emulator is invoked on the BIOS's initialization
+ code. The other way is to perform an INT 10 call. When an INT 10
+ call is made, it passes in a data structure containing the inital
+ values for AX,BX,CX,DX,SI,DI, and BP. The internal state of the
+ processor is initialized to these values, and the INT 10 vector
+ is looked up in memory. The CS and IP registers and initialized
+ to start executing the INT 10 call, and the exit condition is
+ initialized to stop the emulator when the INT 10 call returns.
+ When the INT 10 call returns, the values of the internal registers
+ are returned to the calling function. The calling function can
+ examine these registers to get at the INT 10's return value.
+
+ If the emulator encounters an error condition, the variable ErrorCode
+ will contain the reason for the error.
+
+ References:
+
+ Borland International, "Turbo Assembler Quick Reference Guide", 1990.
+
+ Choisser, John P., "The XT-AT Handbook", Annabooks, 1993.
+
+ Duncan, Ray, "IBM ROM BIOS", Microsoft Press, 1988.
+
+ Intel Corporation, "The 8086 Family Users's Manual", October 1979.
+
+ Intel Corporation, "Microprocessors Volume I", 1994.
+
+ "Macro Assembler by Microsoft" IBM Corporation, 1981.
+
+ Norton, Peter, "The New Peter Norton Programmer's Guide to the IBM
+ PC & PS/2", Microsoft Press, 1988.
+
+ Wilton, Richard, "Programmer's Guide to PC & PS/2 Video Systems",
+ Microsft Press, 1987.
+
+Author:
+
+ Michael D. Kinney 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/***************************************************************************/
+/* Include Files */
+/***************************************************************************/
+
+#include "nthal.h"
+#include "hal.h"
+#include "x86bios.h"
+
+//#define X86DEBUG
+//#define X86DEBUG1
+
+/***************************************************************************/
+/* Type Declarations */
+/***************************************************************************/
+
+typedef union REGISTER32
+ {
+ struct
+ {
+ UCHAR L;
+ UCHAR H;
+ };
+ USHORT X;
+ ULONG EX;
+ } REGISTER32;
+
+typedef union REGISTERFLAG
+ {
+ struct
+ {
+ USHORT _cf:1;
+ USHORT _x1:1;
+ USHORT _pf:1;
+ USHORT _x3:1;
+ USHORT _af:1;
+ USHORT _x5:1;
+ USHORT _zf:1;
+ USHORT _sf:1;
+ USHORT _tf:1;
+ USHORT _if:1;
+ USHORT _df:1;
+ USHORT _of:1;
+ USHORT _x12:1;
+ USHORT _x13:1;
+ USHORT _x14:1;
+ USHORT _x15:1;
+ };
+ struct
+ {
+ UCHAR L;
+ UCHAR H;
+ };
+ USHORT X;
+ ULONG EX;
+ } REGISTERFLAG;
+
+typedef enum { NullOperand,
+ Register8Operand, // 8 bit register operand
+ Register16Operand, // 16 bit register operand
+ Memory8Operand, // 8 bit memory reference (BYTE PTR)
+ Memory16Operand, // 16 bit memory reference (WORD PTR)
+ Immediate8Operand, // 8 bit immediate value
+ Immediate16Operand, // 16 bit immediate value
+ ShortLabelOperand, // 8 bit signed immediate value
+ Immediate32Operand // 32 bit immediate value forming a segment:offset memory reference.
+ } OPERANDTYPE;
+
+typedef struct OPERAND
+ {
+ OPERANDTYPE OperandType;
+ UCHAR *Register8; // Pointer to 8 bit register variable
+ USHORT *Register16; // Pointer to 16 bit register variable
+ USHORT *MemorySegment; // Pointer to 16 bit segment register variable for memory address
+ REGISTER32 MemoryOffset; // 16 bit value for memory address
+ REGISTER32 Immediate8; // 8 bit value
+ REGISTER32 Immediate16; // 16 bit value
+ REGISTER32 ShortLabel; // 8 bit signed value
+ REGISTER32 Immediate32Segment; // 16 bit value for immediate address
+ REGISTER32 Immediate32Offset; // 16 bit value for immediate address
+ } OPERAND;
+
+/***************************************************************************/
+/* Register Access Macros */
+/***************************************************************************/
+
+//
+// 16 Bit Instruction Pointer Register
+//
+
+#define IP (ip.X)
+
+//
+// 8 Bit General Purpose Registers
+//
+
+#define AL (a.L)
+#define AH (a.H)
+#define BL (b.L)
+#define BH (b.H)
+#define CL (c.L)
+#define CH (c.H)
+#define DL (d.L)
+#define DH (d.H)
+
+//
+// 16 Bit General Purpose, Base and Index Registers
+//
+
+#define AX (a.X)
+#define BX (b.X)
+#define CX (c.X)
+#define DX (d.X)
+#define SP (sp.X)
+#define BP (bp.X)
+#define SI (si.X)
+#define DI (di.X)
+
+//
+// 32 Bit General Purpose, Base and Index Registers
+//
+
+#define EAX (a.EX)
+#define EBX (b.EX)
+#define ECX (c.EX)
+#define EDX (d.EX)
+#define ESP (sp.EX)
+#define EBP (bp.EX)
+#define ESI (si.EX)
+#define EDI (di.EX)
+
+//
+// 16 Bit Segment Registers
+//
+
+#define CS (cs.X)
+#define DS (ds.X)
+#define SS (ss.X)
+#define ES (es.X)
+
+//
+// Flag Registers
+//
+
+#define CF (Flags._cf)
+#define PF (Flags._pf)
+#define AF (Flags._af)
+#define ZF (Flags._zf)
+#define SF (Flags._sf)
+#define TF (Flags._tf)
+#define IF (Flags._if)
+#define DF (Flags._df)
+#define OF (Flags._of)
+
+//
+// Debugging Macros
+//
+
+#ifdef X86DEBUG
+
+static ULONG DebugOutFile;
+static ULONG DebugInFile;
+static ULONG DebugCount;
+static UCHAR DebugGetChar;
+static UCHAR PrintMessage[512];
+
+static VOID CloseDebugPort()
+
+ {
+ Close(DebugOutFile);
+ }
+
+static void SetBaudRate(ULONG Port,ULONG Rate)
+
+ {
+ ULONG Divisor;
+
+ Divisor = (24000000/13)/(Rate*16);
+ outp(Port+3,0x80);
+ outp(Port+0,Divisor & 0xff);
+ outp(Port+1,(Divisor>>8) & 0xff);
+ outp(Port+3,0x03);
+ }
+
+static VOID OpenDebugPort()
+
+ {
+ ULONG Port = 0x3f8;
+
+ SetBaudRate(Port,9600);
+ outp(Port + 1,0x00);
+ outp(Port + 4,0x03);
+ }
+
+static LONG SERRead(ULONG FileID,void *Buffer,ULONG N,ULONG *Count)
+
+ {
+ ULONG Port = 0x03f8;
+
+ for(*Count=0;*Count<N;(*Count)++)
+ {
+ while (!(inp(Port+5) & 0x0001));
+ *((CHAR *)(Buffer) + (*Count)) = inp(Port+0);
+ }
+ return(ESUCCESS);
+ }
+
+static LONG SERWrite(ULONG FileID,void *Buffer,ULONG N,ULONG *Count)
+
+ {
+ ULONG Port = 0x3f8;
+
+ for(*Count=0;*Count<N;(*Count)++)
+ {
+ while (!(inp(Port+5) & 0x0020));
+ outp(Port,*((CHAR *)(Buffer)+(*Count)));
+ }
+ return(ESUCCESS);
+ }
+
+#define DISPLAY(X) { OpenDebugPort(); SERWrite(DebugOutFile,X,strlen(X),&DebugCount); CloseDebugPort(); }
+#define ERROR(X) DISPLAY(X)
+#define PRINT1(X) sprintf(PrintMessage,X)
+#define PRINT2(X,Y) sprintf(PrintMessage,X,Y)
+#define PRINT3(X,Y,Z) sprintf(PrintMessage,X,Y,Z)
+#define PRINT4(X,Y,Z,A) sprintf(PrintMessage,X,Y,Z,A)
+#define STRCPY(X,Y) strcpy(X,Y)
+#define STRCAT(X,Y) strcat(X,Y)
+#define PAUSE { OpenDebugPort(); SERRead(DebugInFile,&DebugGetChar,1,&DebugCount); CloseDebugPort(); }
+#define GETCHAR(X) { OpenDebugPort(); SERRead(DebugInFile,&X,1,&DebugCount); CloseDebugPort(); }
+#define PUTCHAR(X) { OpenDebugPort(); SERWrite(DebugOutFile,&X,1,&DebugCount); CloseDebugPort(); }
+
+#else
+
+#define DISPLAY(X)
+#define ERROR(X)
+#define PRINT1(X)
+#define PRINT2(X,Y)
+#define PRINT3(X,Y,Z)
+#define PRINT4(X,Y,Z,A)
+#define STRCPY(X,Y)
+#define STRCAT(X,Y)
+#define PAUSE
+
+#endif
+
+#ifdef X86DEBUG1
+
+#define ADDRESSTRACESIZE 80
+static ULONG AddressTrace[ADDRESSTRACESIZE];
+static ULONG AddressTracePosition;
+
+#endif
+
+
+/***************************************************************************/
+/* Constants */
+/***************************************************************************/
+
+#define SUBOPERATION 0
+#define ADDOPERATION 1
+
+//
+// Define table for computing parity.
+//
+
+static const UCHAR ParityTable[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
+
+/***************************************************************************/
+/* Global Variables */
+/***************************************************************************/
+
+static REGISTER32 ip; // x86 Processor Register IP.
+static REGISTER32 a; // x86 Processor Register EAX,AX,AL,AH.
+static REGISTER32 b; // x86 Processor Register EBX,BX,BL,BH.
+static REGISTER32 c; // x86 Processor Register ECX,CX,CL,CH.
+static REGISTER32 d; // x86 Processor Register EDX,DX,DL,DH.
+static REGISTER32 sp; // x86 Processor Register ESP,SP.
+static REGISTER32 bp; // x86 Processor Register EBP,BP.
+static REGISTER32 si; // x86 Processor Register ESI,SI.
+static REGISTER32 di; // x86 Processor Register ESI,DI.
+static REGISTER32 es; // x86 Processor Register ES.
+static REGISTER32 cs; // x86 Processor Register CS.
+static REGISTER32 ss; // x86 Processor Register SS.
+static REGISTER32 ds; // x86 Processor Register DS.
+static REGISTERFLAG Flags; // x86 Processor Register CF,PF,AF,ZF,SF,TF,IF,DF,OF.
+static USHORT msw; // 80286 Protected Mode Processor Register.
+static USHORT gdtLimit; // 80286 Protected Mode Processor Register.
+static ULONG gdtBase; // 80286 Protected Mode Processor Register.
+static USHORT idtLimit; // 80286 Protected Mode Processor Register.
+static ULONG idtBase; // 80286 Protected Mode Processor Register.
+static ULONG CSCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
+static ULONG DSCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
+static ULONG ESCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
+static ULONG SSCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
+
+static ULONG BiosIsaIoBaseAddress; // Base virtual address of 64K ISA I/O space used by emulator.
+static ULONG VDMBaseAddress; // Base virtual address of the 1MB area used by emulator.
+static ULONG ISABaseAddress; // Base virtual address of ISA Memory.
+static OPERAND LeftSource; // Storage area for left operand.
+static OPERAND RightSource; // Storage area for right operand.
+static OPERAND *LSRC = &LeftSource; // Pointer to left operand.
+static OPERAND *RSRC = &RightSource; // Pointer to right operand.
+
+static UCHAR OperationCodeByte; // 1st byte of instruction.
+static UCHAR ExtendedOperationCodeByte; // 2nd byte of special 286 instructions.
+static UCHAR InstructionSubIndex; // Value from 0-7 that is either 0 or the reg field from AddressModeByte.
+static UCHAR AddressModeByte; // 2nd byte of instruction if instruction uses an address mode.
+static UCHAR mod; // Address mode field.
+static UCHAR reg; // Address mode field.
+static UCHAR r_m; // Address mode field.
+static ULONG SegmentOveridePrefix; // TRUE if a segment overide exists (CS:,DS:,ES:,SS:).
+static USHORT *OverideSegmentRegister; // Pointer to 16 bit overide segment register.
+static ULONG RepeatPrefix; // TRUE if a REP prefix exists.
+static ULONG RepeatZeroFlag; // Flag for REPNZ and REPZ instructions.
+static ULONG LockPrefix; // TRUE if a LOCK prefix exists.
+static REGISTER32 CurrentIP; // IP value for the beginning of current instruction.
+static ULONG SSRegisterTouched = FALSE; // TRUE if previous instruction changed the value of the SS register.
+static USHORT Delta; // Increment value for string operations.
+static ULONG ExitFlag; // If TRUE, the interpreter will exit
+static ULONG GoFlag = FALSE; // TRUE if emulator is running. Set to FALSE on breakpoints.
+static USHORT ExitSegment; // Segment of break point that causes the emulator to exit.
+static USHORT ExitOffset; // Offset of break point that causes the emulator to exit.
+static USHORT StopSegment; // Segment of break point.
+static USHORT StopOffset; // Offset of break point.
+static UCHAR MemoryArray[0x0800]; // 2K memory for INT vectors, BIOS data, temp code, and stack.
+static X86BIOS_STATUS ErrorCode; // Reason for exiting emulator
+
+/*++
+
+Memory Access Functions:
+
+ The following functions are used to read and write values to and from
+ memory. Only part of the x86's 1MB address space is actually visible
+ to the emulator. The address range from 0000:0000 to 0000:03FF exists
+ to store INT vectors. The address range from 0000:0400 to 0000:04FF
+ exists for the BIOS data area in case the video bios wants to store
+ and retrieve value from here. The address range from 0000:0500 to
+ 0000:0510 is an area where temporary code segements are build by the
+ emulator for entry and exit points. The address range from
+ 0000:0510 to 0000:07FF is the video BIOS's stack area. The stack
+ pointer is initialized to the top of this area. The address range
+ from A000:0000 to D000:FFFF is visible to the emulator. Memory
+ accesses in this range perform memory read and write cycles to
+ ISA Memory. Memory read to unavailable regions always return 0,
+ and memory writes to unavailable regions perform no actions.
+
+ |----------------------------------------|
+ | |
+ | E000:0000 - F000:FFFF : Unavailable |
+ | |
+ |----------------------------------------|
+ | |
+ | A000:0000 - D000:FFFF : ISA Memory |
+ | |
+ |----------------------------------------|
+ | |
+ | 0000:0800 - 9000:FFFF : Unavailable |
+ | |
+ |----------------------------------------|
+ | |
+ | 0000:0510 - 0000:07FF : Stack |
+ | |
+ |----------------------------------------|
+ | |
+ | 0000:0500 - 0000:050F : Reserved |
+ | |
+ |----------------------------------------|
+ | |
+ | 0000:0400 - 0000:04FF : BIOS Data Area |
+ | |
+ |----------------------------------------|
+ | |
+ | 0000:0000 - 0000:03FF : INT Vectors |
+ | |
+ |----------------------------------------|
+
+--*/
+
+
+static UCHAR GetAbsoluteMem(
+ ULONG Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This is the lowest level function for reading a byte from memory.
+
+Arguments:
+
+ Offset - 20 bit value used to address a byte.
+
+Return Value:
+
+ The byte stored at the address if that address is mapped.
+ Otherwise, return 0.
+
+--*/
+
+ {
+ if (Offset>=0x0a0000 && Offset<0xe0000)
+ return(*(UCHAR *)(ISABaseAddress + Offset));
+ if (Offset<0x800)
+ return(*(UCHAR *)(VDMBaseAddress + Offset));
+ return(0);
+ }
+
+
+static VOID PutAbsoluteMem(
+ ULONG Offset,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This is the lowest level function for writing a byte to memory.
+ The byte is written to the address if that address is mapped.
+ Otherwise, no action is taken.
+
+Arguments:
+
+ Offset - 20 bit value used to address a byte.
+
+ Value - The 8 bit data value that is to be written.
+
+Return Value:
+
+ None
+
+--*/
+
+ {
+ if (Offset>=0x0a0000 && Offset<0xe0000)
+ *(UCHAR *)(ISABaseAddress + Offset) = Value;
+ if (Offset<0x800)
+ *(UCHAR *)(VDMBaseAddress + Offset) = Value;
+ }
+
+
+static UCHAR GetMem(
+ OPERAND *Operand,
+ ULONG Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads a byte from memory. Operand contains the
+ segment part and offset part of the address. If the processor is
+ in protected mode, the segment cache registers are used to compute
+ the address. If the processor is in real mode, the segment register
+ is shifted left four bits, and added to the offset.
+
+Arguments:
+
+ Operand - Contains a memory reference in the MemorySegment and
+ MemoryOffset fields.
+
+ Offset - Additional offset from the memory location described in
+ Operand.
+
+Return Value:
+
+ The byte read from the computed address.
+
+--*/
+
+ {
+ if (msw & 1)
+ {
+ if (Operand->MemorySegment == (PVOID)(&CS))
+ return(GetAbsoluteMem(CSCacheRegister + Operand->MemoryOffset.X + Offset));
+ else if (Operand->MemorySegment == (PVOID)(&ES))
+ return(GetAbsoluteMem(ESCacheRegister + Operand->MemoryOffset.X + Offset));
+ else if (Operand->MemorySegment == (PVOID)(&SS))
+ return(GetAbsoluteMem(SSCacheRegister + Operand->MemoryOffset.X + Offset));
+ else if (Operand->MemorySegment == (PVOID)(&DS))
+ return(GetAbsoluteMem(DSCacheRegister + Operand->MemoryOffset.X + Offset));
+ else
+ DISPLAY("Protected mode GetMem() ERROR\n\r");
+ }
+ else
+ return(GetAbsoluteMem( (((*Operand->MemorySegment)<<4) + Operand->MemoryOffset.X + Offset)&0xfffff ));
+ }
+
+
+static VOID PutMem(
+ OPERAND *Operand,
+ ULONG Offset,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes a byte to memory. Operand contains the
+ segment part and offset part of the address. If the processor is
+ in protected mode, the segment cache registers are used to compute
+ the address. If the processor is in real mode, the segment register
+ is shifted left four bits, and added to the offset.
+
+Arguments:
+
+ Operand - Contains a memory reference in the MemorySegment and
+ MemoryOffset fields.
+
+ Offset - Additional offset from the memory location described in
+ Operand.
+
+ Value - 8 bit data value to be written to the computed address.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (msw & 1)
+ {
+ if (Operand->MemorySegment == (PVOID)(&CS))
+ PutAbsoluteMem(CSCacheRegister + Operand->MemoryOffset.X + Offset,Value);
+ else if (Operand->MemorySegment == (PVOID)(&ES))
+ PutAbsoluteMem(ESCacheRegister + Operand->MemoryOffset.X + Offset,Value);
+ else if (Operand->MemorySegment == (PVOID)(&SS))
+ PutAbsoluteMem(SSCacheRegister + Operand->MemoryOffset.X + Offset,Value);
+ else if (Operand->MemorySegment == (PVOID)(&DS))
+ PutAbsoluteMem(DSCacheRegister + Operand->MemoryOffset.X + Offset,Value);
+ else
+ DISPLAY("Protected mode PutMem() ERROR\n\r");
+ }
+ else
+ PutAbsoluteMem( (((*Operand->MemorySegment)<<4) + Operand->MemoryOffset.X + Offset)&0xfffff , Value);
+ }
+
+
+static ULONG GetSegmentCacheRegister(
+ USHORT SegmentValue
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the 24 bit base address for a memory reference. The value
+ of the segment register is passed in. If the processor is in protected mode,
+ this value is used to lookup a 24 bit base address in the global descriptor
+ table. If the processor is in real mode, the segement register value is shifted
+ left 4 position and the 20 bit value is returned.
+
+Arguments:
+
+ SegmentValue - 16 bit segment register value.
+
+Return Value:
+
+ A 24 bit base address for a memory reference.
+
+--*/
+
+ {
+ if (msw&1)
+ return(GetAbsoluteMem(gdtBase + SegmentValue + 2) | (GetAbsoluteMem(gdtBase + SegmentValue + 3) << 8) | (GetAbsoluteMem(gdtBase + SegmentValue + 4) << 16));
+ else
+ return((SegmentValue<<4)&0xfffff);
+ }
+
+
+static UCHAR GetMemImmediate(
+ USHORT Segment,
+ USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads an 8 bit value from the memory location Segment:Offset.
+
+Arguments:
+
+ Segment - 16 bit segment register value.
+
+ Offset - 16 bit offset within the segment defined by Segment.
+
+Return Value:
+
+ The 8 bit value read from the memory location Segemnt:Offset.
+
+--*/
+
+ {
+ if (msw&1)
+ return(GetAbsoluteMem( GetSegmentCacheRegister(Segment)+Offset ));
+ else
+ return(GetAbsoluteMem((GetSegmentCacheRegister(Segment)+Offset)&0xfffff));
+ }
+
+
+static VOID PutMemImmediate(
+ USHORT Segment,
+ USHORT Offset,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes an 8 bit value to the memory location Segment:Offset.
+
+Arguments:
+
+ Segment - 16 bit segment register value.
+
+ Offset - 16 bit offset within the segment defined by Segment.
+
+ Value - 8 bit value to write to the memory location Segment:Offset.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (msw&1)
+ PutAbsoluteMem(GetSegmentCacheRegister(Segment)+Offset,Value);
+ else
+ PutAbsoluteMem((GetSegmentCacheRegister(Segment)+Offset)&0xfffff,Value);
+ }
+
+
+static UCHAR CodeMem(
+ USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads an 8 bit value from the code area. The location
+ read is CS:Offset.
+
+Arguments:
+
+ Offset - 16 bit offset within the current code segment.
+
+Return Value:
+
+ The 8 bit value read from the code area.
+
+--*/
+
+ {
+ return(GetAbsoluteMem((CSCacheRegister + Offset)&0xfffff));
+ }
+
+
+static UCHAR GetStackMem(
+ USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads an 8 bit value from the stack. The location
+ read is SS:Offset.
+
+Arguments:
+
+ Offset - 16 bit offset within the current stack segment.
+
+Return Value:
+
+ The 8 bit value read from the stack.
+
+--*/
+
+ {
+ return(GetAbsoluteMem((SSCacheRegister + Offset)&0xfffff));
+ }
+
+
+static VOID PutStackMem(
+ USHORT Offset,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function stores a byte onto the stack. The location written is
+ SS:Offset.
+
+Arguments:
+
+ Offset - 16 bit offset within the current stack segment.
+
+ Value - 8 bit value to be stored onto the stack.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ PutAbsoluteMem((SSCacheRegister + Offset)&0xfffff,Value);
+ }
+
+
+//
+// Debugging functions
+//
+
+#ifdef X86DEBUG
+
+static VOID PrintProcessorState(UCHAR *S)
+
+ {
+ UCHAR T[256];
+ ULONG CR;
+ ULONG SR;
+
+ sprintf(S,"AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n\rDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X ",
+ AX,BX,CX,DX,SP,BP,SI,DI,DS,ES,SS,CS,CurrentIP.X);
+ if (OF) strcat(S,"OV "); else strcat(S,"NV ");
+ if (DF) strcat(S,"DN "); else strcat(S,"UP ");
+ if (IF) strcat(S,"EI "); else strcat(S,"DI ");
+ if (SF) strcat(S,"NG "); else strcat(S,"PL ");
+ if (ZF) strcat(S,"ZR "); else strcat(S,"NZ ");
+ if (AF) strcat(S,"AC "); else strcat(S,"NA ");
+ if (PF) strcat(S,"PE "); else strcat(S,"PO ");
+ if (CF) strcat(S,"CY\n\r"); else strcat(S,"NC\n\r");
+ sprintf(T,"EAX=%08X EBX=%08X ECX=%08X EDX=%08X\n\rESP=%08X EBP=%08X ESI=%08X EDI=%08X\n\r",
+ EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI);
+ strcat(S,T);
+ sprintf(T,"MSW=%04X GDTBase=%06X GDTLimit=%04X IDTBase=%06X IDTLimit=%04X\n\r",
+ msw,gdtBase,gdtLimit,idtBase,idtLimit);
+ strcat(S,T);
+ sprintf(T,"DSCache=%04X ESCache=%04X SSCache=%04X CSCache=%04X\n\r",
+ DSCacheRegister,ESCacheRegister,SSCacheRegister,CSCacheRegister);
+ strcat(S,T);
+ CR = GetCauseRegister();
+ SR = GetStatusRegister();
+ sprintf(T,"CR = %08X SR = %08X\n\r",CR,SR);
+ strcat(S,T);
+ }
+
+/***************************************************************************/
+
+static VOID PrintMemorySegmentName(OPERAND *Operand,UCHAR *S)
+
+ {
+ strcpy(S,"");
+ switch (Operand->OperandType)
+ {
+ case Memory8Operand :
+ case Memory16Operand : if (Operand->MemorySegment == (PVOID)(&CS))
+ sprintf(S,"CS");
+ else if (Operand->MemorySegment == (PVOID)(&ES))
+ sprintf(S,"ES");
+ else if (Operand->MemorySegment == (PVOID)(&SS))
+ sprintf(S,"SS");
+ else if (Operand->MemorySegment == (PVOID)(&DS))
+ sprintf(S,"DS");
+ break;
+ default : ERROR("PrintMemorySegmentName()\n\r");
+ break;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID PrintMemoryAccessSize(OPERAND *Operand,UCHAR *S)
+
+ {
+ strcpy(S,"");
+ switch (Operand->OperandType)
+ {
+ case Memory8Operand : sprintf(S,"BYTE PTR");
+ break;
+ case Memory16Operand : sprintf(S,"WORD PTR");
+ break;
+ default : ERROR("PrintMemoryAccessSize()\n\r");
+ break;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID PrintOperandName(OPERAND *Operand,UCHAR *S)
+
+ {
+ strcpy(S,"");
+ switch (Operand->OperandType)
+ {
+ case Register8Operand : if (Operand->Register8 == (PVOID)(&AL))
+ sprintf(S,"AL");
+ else if (Operand->Register8 == (PVOID)(&AH))
+ sprintf(S,"AH");
+ else if (Operand->Register8 == (PVOID)(&BL))
+ sprintf(S,"BL");
+ else if (Operand->Register8 == (PVOID)(&BH))
+ sprintf(S,"BH");
+ else if (Operand->Register8 == (PVOID)(&CL))
+ sprintf(S,"CL");
+ else if (Operand->Register8 == (PVOID)(&CH))
+ sprintf(S,"CH");
+ else if (Operand->Register8 == (PVOID)(&DL))
+ sprintf(S,"DL");
+ else if (Operand->Register8 == (PVOID)(&DH))
+ sprintf(S,"DH");
+ break;
+ case Register16Operand : if (Operand->Register16 == (PVOID)(&AX))
+ sprintf(S,"AX");
+ else if (Operand->Register16 == (PVOID)(&BX))
+ sprintf(S,"BX");
+ else if (Operand->Register16 == (PVOID)(&CX))
+ sprintf(S,"CX");
+ else if (Operand->Register16 == (PVOID)(&DX))
+ sprintf(S,"DX");
+ else if (Operand->Register16 == (PVOID)(&BP))
+ sprintf(S,"BP");
+ else if (Operand->Register16 == (PVOID)(&SP))
+ sprintf(S,"SP");
+ else if (Operand->Register16 == (PVOID)(&SI))
+ sprintf(S,"SI");
+ else if (Operand->Register16 == (PVOID)(&DI))
+ sprintf(S,"DI");
+ else if (Operand->Register16 == (PVOID)(&CS))
+ sprintf(S,"CS");
+ else if (Operand->Register16 == (PVOID)(&ES))
+ sprintf(S,"ES");
+ else if (Operand->Register16 == (PVOID)(&SS))
+ sprintf(S,"SS");
+ else if (Operand->Register16 == (PVOID)(&DS))
+ sprintf(S,"DS");
+ else if (Operand->Register16 == (PVOID)(&IP))
+ sprintf(S,"IP");
+ break;
+ case Memory8Operand : sprintf(S,"[%04X]",Operand->MemoryOffset.X);
+ break;
+ case Memory16Operand : sprintf(S,"[%04X]",Operand->MemoryOffset.X);
+ break;
+ case Immediate8Operand : sprintf(S,"%02X",Operand->Immediate8.L);
+ break;
+ case Immediate16Operand : sprintf(S,"%04X",Operand->Immediate16.X);
+ break;
+ case ShortLabelOperand : sprintf(S,"%02X",Operand->ShortLabel.L);
+ break;
+ case Immediate32Operand : sprintf(S,"%04X:%04X",Operand->Immediate32Segment.X,Operand->Immediate32Offset.X);
+ break;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID PrintOperandValue(OPERAND *Operand,UCHAR *S)
+
+ {
+ strcpy(S,"");
+ switch (Operand->OperandType)
+ {
+ case Register8Operand : if (Operand->Register8 == (PVOID)(&AL))
+ sprintf(S,"%02X",AL);
+ else if (Operand->Register8 == (PVOID)(&AH))
+ sprintf(S,"%02X",AH);
+ else if (Operand->Register8 == (PVOID)(&BL))
+ sprintf(S,"%02X",BL);
+ else if (Operand->Register8 == (PVOID)(&BH))
+ sprintf(S,"%02X",BH);
+ else if (Operand->Register8 == (PVOID)(&CL))
+ sprintf(S,"%02X",CL);
+ else if (Operand->Register8 == (PVOID)(&CH))
+ sprintf(S,"%02X",CH);
+ else if (Operand->Register8 == (PVOID)(&DL))
+ sprintf(S,"%02X",DL);
+ else if (Operand->Register8 == (PVOID)(&DH))
+ sprintf(S,"%02X",DH);
+ break;
+ case Register16Operand : if (Operand->Register16 == (PVOID)(&AX))
+ sprintf(S,"%04X",AX);
+ else if (Operand->Register16 == (PVOID)(&BX))
+ sprintf(S,"%04X",BX);
+ else if (Operand->Register16 == (PVOID)(&CX))
+ sprintf(S,"%04X",CX);
+ else if (Operand->Register16 == (PVOID)(&DX))
+ sprintf(S,"%04X",DX);
+ else if (Operand->Register16 == (PVOID)(&BP))
+ sprintf(S,"%04X",BP);
+ else if (Operand->Register16 == (PVOID)(&SP))
+ sprintf(S,"%04X",SP);
+ else if (Operand->Register16 == (PVOID)(&SI))
+ sprintf(S,"%04X",SI);
+ else if (Operand->Register16 == (PVOID)(&DI))
+ sprintf(S,"%04X",DI);
+ else if (Operand->Register16 == (PVOID)(&CS))
+ sprintf(S,"%04X",CS);
+ else if (Operand->Register16 == (PVOID)(&ES))
+ sprintf(S,"%04X",ES);
+ else if (Operand->Register16 == (PVOID)(&SS))
+ sprintf(S,"%04X",SS);
+ else if (Operand->Register16 == (PVOID)(&DS))
+ sprintf(S,"%04X",DS);
+ else if (Operand->Register16 == (PVOID)(&IP))
+ sprintf(S,"%04X",IP);
+ break;
+ case Memory8Operand : sprintf(S,"%02X",(ULONG)(GetMem(Operand,0)));
+ break;
+ case Memory16Operand : sprintf(S,"%04X",(ULONG)(GetMem(Operand,0)) | (ULONG)(GetMem(Operand,1)<<8));
+ break;
+ case Immediate8Operand : sprintf(S,"%02X",Operand->Immediate8.L);
+ break;
+ case Immediate16Operand : sprintf(S,"%04X",Operand->Immediate16.X);
+ break;
+ case ShortLabelOperand : sprintf(S,"%02X",Operand->ShortLabel.L);
+ break;
+ case Immediate32Operand : sprintf(S,"%04X:%04X",Operand->Immediate32Segment.X,Operand->Immediate32Offset.X);
+ break;
+ }
+ }
+
+#endif
+
+
+static ULONG GetOperand(
+ OPERAND *Operand,
+ ULONG Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to retrieve a value from either a register, a memory
+ location, or an immediate value. The OperandType field of Operand contains
+ the operand's type.
+
+Arguments:
+
+ *Operand - Operand where Value is to be retrieved.
+
+ Offset - For memory operands, Offset is the number of bytes forward of
+ the effective address that Value is to be retrieved.
+Return Value:
+
+ The 8 or 16 bit value retrieved from Operand.
+
+--*/
+
+ {
+ if (Offset!=0)
+ if (Operand->OperandType!=Memory8Operand && Operand->OperandType!=Memory16Operand)
+ {
+ ERROR("GetOperand()\n\r");
+ return(0);
+ }
+ switch (Operand->OperandType)
+ {
+ case Register8Operand : return((ULONG)(*(UCHAR *)(Operand->Register8)));
+ break;
+ case Register16Operand : return((ULONG)(*(USHORT *)(Operand->Register16)));
+ break;
+ case Memory8Operand : return((ULONG)(GetMem(Operand,Offset)));
+ break;
+ case Memory16Operand : return((ULONG)(GetMem(Operand,Offset) | (GetMem(Operand,Offset+1) << 8)));
+ break;
+ case Immediate8Operand : return((ULONG)(Operand->Immediate8.L));
+ break;
+ case Immediate16Operand : return((ULONG)(Operand->Immediate16.X));
+ break;
+ case ShortLabelOperand : return((ULONG)(Operand->ShortLabel.X));
+ break;
+ case Immediate32Operand : return((ULONG)(Operand->Immediate32Segment.X<<16 | Operand->Immediate32Offset.X));
+ break;
+ default : ERROR("GetOperand()\n\r");
+ return(0);
+ break;
+ }
+ }
+
+static VOID PutOperand(
+ OPERAND *Operand,
+ ULONG Offset,
+ ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to store a value to either a register, or a memory
+ location. The OperandType field of Operand contains the operand's type.
+
+Arguments:
+
+ *Operand - Operand where Value is to be written.
+
+ Offset - For memory operands, Offset is the number of bytes forward of
+ the effective address that Value is to be written.
+
+ Value - 8 or 16 bit immediate value that is to be written to Operand.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (Offset!=0)
+ if (Operand->OperandType!=Memory8Operand && Operand->OperandType!=Memory16Operand)
+ {
+ ERROR("PutOperand()\n\r");
+ return;
+ }
+ switch (Operand->OperandType)
+ {
+ case Register8Operand : *(Operand->Register8) = Value;
+ break;
+ case Register16Operand : *(Operand->Register16) = Value;
+ if (Operand->Register16 == (PVOID)(&CS))
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ else if (Operand->Register16 == (PVOID)(&ES))
+ ESCacheRegister = GetSegmentCacheRegister(ES);
+ else if (Operand->Register16 == (PVOID)(&SS))
+ {
+ SSCacheRegister = GetSegmentCacheRegister(SS);
+ SSRegisterTouched = TRUE;
+ }
+ else if (Operand->Register16 == (PVOID)(&DS))
+ DSCacheRegister = GetSegmentCacheRegister(DS);
+ break;
+ case Memory8Operand : PutMem(Operand,Offset,Value);
+ break;
+ case Memory16Operand : PutMem(Operand,Offset+0,Value);
+ PutMem(Operand,Offset+1,Value>>8);
+ break;
+ case Immediate8Operand : Operand->Immediate8.L = Value;
+ break;
+ case Immediate16Operand : Operand->Immediate16.X = Value;
+ break;
+ case ShortLabelOperand : Operand->ShortLabel.L = Value;
+ if (Operand->ShortLabel.L & 0x80)
+ Operand->ShortLabel.H = 0xff;
+ else
+ Operand->ShortLabel.L = 0x00;
+ break;
+ case Immediate32Operand : Operand->Immediate32Segment.X = Value >> 16;
+ Operand->Immediate32Offset.X = Value;
+ break;
+ default : ERROR("PutOperand()\n\r");
+ break;
+ }
+ }
+
+/*++
+
+Address Decoding Support Functions:
+
+ The following functions are used by the address decoding functions
+ to decode operands.
+
+--*/
+
+
+static VOID GetAddressModeByte()
+
+/*++
+
+Routine Description:
+
+ This function parses the address mode byte from the instruction currently
+ being decoded. The mod, reg, and r/m bit fields are also extracted from
+ the address mode byte, so they can be used by the address decoding
+ functions.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ AddressModeByte = CodeMem(IP); IP++;
+ mod = (AddressModeByte >> 6) & 0x03;
+ reg = (AddressModeByte >> 3) & 0x07;
+ r_m = (AddressModeByte >> 0) & 0x07;
+ }
+
+
+USHORT *pGetCurrentSegment(
+ USHORT *DefaultSegmentRegister
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the segment register that is active for
+ the instruction that us currently being decoded. The default
+ segement register for the address mode being parse is passed
+ into this function. If there are no segement overide prefix
+ instructions affecting this instruction, then the default
+ segement register will be returned. Otherwise, the segement
+ regeister referenced in the segment overide prefix instruction
+ will be returned.
+
+Arguments:
+
+ DefaultSegmentRegister - The default segment register for the
+ address mode being decoded.
+
+Return Value:
+
+ The segement register that is valid for the instruction that
+ is currently being decoded.
+
+--*/
+
+ {
+ if (SegmentOveridePrefix)
+ return(OverideSegmentRegister);
+ else
+ return(DefaultSegmentRegister);
+ }
+
+
+static VOID pGetRegister8Operand(
+ OPERAND *Operand,UCHAR reg
+ )
+
+/*++
+
+Routine Description:
+
+ This function builds an 8 bit general purpose register operand.
+
+Arguments:
+
+ *Operand - Used to return the 8 bit genral purpose register operand.
+
+ reg - 3 bit value used to determine which general purpose register
+ is being referenced.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ Operand->OperandType = Register8Operand;
+ switch (reg)
+ {
+ case 0 : Operand->Register8 = &AL;
+ break;
+ case 1 : Operand->Register8 = &CL;
+ break;
+ case 2 : Operand->Register8 = &DL;
+ break;
+ case 3 : Operand->Register8 = &BL;
+ break;
+ case 4 : Operand->Register8 = &AH;
+ break;
+ case 5 : Operand->Register8 = &CH;
+ break;
+ case 6 : Operand->Register8 = &DH;
+ break;
+ case 7 : Operand->Register8 = &BH;
+ break;
+ }
+ }
+
+static VOID pGetRegister16Operand(
+ OPERAND *Operand,
+ UCHAR reg
+ )
+
+/*++
+
+Routine Description:
+
+ This function builds a 16 bit general purpose register operand.
+
+Arguments:
+
+ *Operand - Used to return the 16 bit genral purpose register operand.
+
+ reg - 3 bit value used to determine which general purpose register
+ is being referenced.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ Operand->OperandType = Register16Operand;
+ switch (reg)
+ {
+ case 0 : Operand->Register16 = &AX;
+ break;
+ case 1 : Operand->Register16 = &CX;
+ break;
+ case 2 : Operand->Register16 = &DX;
+ break;
+ case 3 : Operand->Register16 = &BX;
+ break;
+ case 4 : Operand->Register16 = &SP;
+ break;
+ case 5 : Operand->Register16 = &BP;
+ break;
+ case 6 : Operand->Register16 = &SI;
+ break;
+ case 7 : Operand->Register16 = &DI;
+ break;
+ }
+ }
+
+static VOID pGetSegmentRegisterOperand(
+ OPERAND *Operand,
+ UCHAR reg
+ )
+
+/*++
+
+Routine Description:
+
+ This function builds a segment register operand.
+
+Arguments:
+
+ *Operand - Used to return the segment register operand.
+
+ reg - A 2 bit value used to determine which segment register is
+ being referenced.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (reg>=4)
+ {
+ ERROR("GetSegmentRegisterOperand()\n\r");
+ return;
+ }
+ Operand->OperandType = Register16Operand;
+ switch(reg)
+ {
+ case 0 : Operand->Register16 = &ES;
+ break;
+ case 1 : Operand->Register16 = &CS;
+ break;
+ case 2 : Operand->Register16 = &SS;
+ break;
+ case 3 : Operand->Register16 = &DS;
+ break;
+ }
+ }
+
+static VOID pGetMemoryOperand(
+ OPERAND *Operand
+ )
+
+/*++
+
+Routine Description:
+
+ This function examines the bit fields from the address mode byte
+ and computes the effective address of a memory reference. The
+ mod field is used to parse the size and type of displacement from
+ the instruction, and the r_m field is used to determine which
+ registers are combined with the displacement to form the effective
+ address of the memory reference.
+
+Arguments:
+
+ *Operand - The effective address of the memory is returned in this
+ parameter.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ REGISTER32 disp;
+
+ switch (mod)
+ {
+ case 0 : if (r_m==6)
+ {
+ disp.L = CodeMem(IP); IP++;
+ disp.H = CodeMem(IP); IP++;
+ }
+ else
+ disp.X = 0;
+ break;
+ case 1 : disp.L = CodeMem(IP); IP++;
+ if (disp.L & 0x80)
+ disp.H = 0xff;
+ else
+ disp.H = 0x00;
+ break;
+ case 2 : disp.L = CodeMem(IP); IP++;
+ disp.H = CodeMem(IP); IP++;
+ break;
+ }
+ switch (r_m)
+ {
+ case 0 : Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = BX + SI + disp.X;
+ break;
+ case 1 : Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = BX + DI + disp.X;
+ break;
+ case 2 : Operand->MemorySegment = pGetCurrentSegment(&SS);
+ Operand->MemoryOffset.X = BP + SI + disp.X;
+ break;
+ case 3 : Operand->MemorySegment = pGetCurrentSegment(&SS);
+ Operand->MemoryOffset.X = BP + DI + disp.X;
+ break;
+ case 4 : Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = SI + disp.X;
+ break;
+ case 5 : Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = DI + disp.X;
+ break;
+ case 6 : if (mod==0)
+ {
+ Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = disp.X;
+ }
+ else
+ {
+ Operand->MemorySegment = pGetCurrentSegment(&SS);
+ Operand->MemoryOffset.X = BP + disp.X;
+ }
+ break;
+ case 7 : Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = BX + disp.X;
+ break;
+ }
+ }
+
+/*++
+
+Address Decoding Functions:
+
+ The following functions are used to decode the operands from an
+ instruction. They all have an OPERAND variable as a parameter.
+ The decoded operand is returned in the OPERAND variable.
+
+
+static VOID GetMemory8OrRegister8Operand(OPERAND *Operand)
+
+ Decodes an 8 bit general purpose register or a BYTE PTR memory operand
+ from an instruction.
+
+static VOID GetMemory16OrRegister16Operand(OPERAND *Operand)
+
+ Decodes a 16 bit general purpose register or a WORD PTR memory operand
+ from an instruction.
+
+static VOID GetRegister8Operand(OPERAND *Operand)
+
+ Decodes an 8 bit general purpose register from an instruction.
+
+static VOID GetRegister16Operand(OPERAND *Operand)
+
+ Decodes a 16 bit general purpose register from an instruction.
+
+static VOID GetSegmentRegisterOperand(OPERAND *Operand)
+
+ Decodes a 16 bit segment register from an instruction.
+
+static VOID GetEmbeddedRegister8Operand(OPERAND *Operand)
+
+ Decodes an 8 bit general purpose register from an instruction. The
+ register number is embedded in 3 bits of the first byte of the
+ instruction.
+
+static VOID GetEmbeddedRegister16Operand(OPERAND *Operand)
+
+ Decodes a 16 bit general purpose register from an instruction. The
+ register number is embedded in 3 bits of the first byte of the
+ instruction.
+
+static VOID GetAccumulator8Operand(OPERAND *Operand)
+
+ Decodes the 8 bit general purpose register AL.
+
+static VOID GetAccumulator16Operand(OPERAND *Operand)
+
+ Decodes the 16 bit general purpose register AX.
+
+static VOID GetImmediate8Operand(OPERAND *Operand)
+
+ Decodes an 8 bit immediate value from an instruction.
+
+static VOID GetImmediateSignExtend8Operand(OPERAND *Operand)
+
+ Decodes a 16 bit immediate value from an instruction. Only an 8 bit
+ value is encoded in the instruction. The 8 bit value is sign extended
+ to form a 16 bit value.
+
+static VOID GetImmediate16Operand(OPERAND *Operand)
+
+ Decodes a 16 bot immediate value from an instruction.
+
+static VOID GetShortLabelOperand(OPERAND *Operand)
+
+ Decodes an 8 bit signed immediate value from an instruction. This
+ operand is type is only used by branching instructions.
+
+static VOID GetImmediate32Operand(OPERAND *Operand)
+
+ Decodes a 32 bit immediate value from an instruction. This is used
+ as a 16 bit segment and a 16 bit offset to reference a memory location.
+
+static VOID GetMemory8Operand(OPERAND *Operand)
+
+ Decodes an 8 bit BYTE PTR memory operand from an instruction.
+
+static VOID GetMemory16Operand(OPERAND *Operand)
+
+ Decodes an 16 bit WORD PTR memory operand from an instruction.
+
+static VOID GetConstantOneOperand(OPERAND *Operand)
+
+ Decodes a constant operand whose value is 1.
+
+static VOID GetRegisterCLOperand(OPERAND *Operand)
+
+ Decodes the 8 bit general purpose register CL.
+
+static VOID GetRegisterDXOperand(OPERAND *Operand)
+
+ Decodes the 16 bit general purpose register DX.
+
+static VOID GetRegisterESOperand(OPERAND *Operand)
+
+ Decodes the 16 bit segment register ES.
+
+static VOID GetRegisterCSOperand(OPERAND *Operand)
+
+ Decodes the 16 bit segment register CS.
+
+static VOID GetRegisterSSOperand(OPERAND *Operand)
+
+ Decodes the 16 bit segment register SS.
+
+static VOID GetRegisterDSOperand(OPERAND *Operand)
+
+ Decodes the 16 bit segment register DS.
+
+static VOID GetString8DSSIOperand(OPERAND *Operand)
+
+ Decodes the memory location for a string instruction. The operand
+ will be an 8 bit BYTE PTR memory location whose address is DS:SI.
+
+static VOID GetString16DSSIOperand(OPERAND *Operand)
+
+ Decodes the memory location for a string instruction. The operand
+ will be an 16 bit WORD PTR memory location whose address is DS:SI.
+
+static VOID GetString8ESDIOperand(OPERAND *Operand)
+
+ Decodes the memory location for a string instruction. The operand
+ will be an 8 bit BYTE PTR memory location whose address is ES:DI.
+
+static VOID GetString16ESDIOperand(OPERAND *Operand)
+
+ Decodes the memory location for a string instruction. The operand
+ will be an 16 bit WORD PTR memory location whose address is ES:DI.
+
+static VOID NullFunction()
+
+ This function is called when an instruction contains less than two
+ operand. If and instruction has no operands, then this function
+ would be called twice. Once for the left operand, and once for the
+ right operand.
+
+--*/
+
+/***************************************************************************/
+
+static VOID GetMemory8OrRegister8Operand(OPERAND *Operand)
+
+ {
+ if (mod==3)
+ pGetRegister8Operand(Operand,r_m);
+ else
+ {
+ Operand->OperandType = Memory8Operand;
+ pGetMemoryOperand(Operand);
+ }
+ }
+
+/***************************************************************************/
+
+static VOID GetMemory16OrRegister16Operand(OPERAND *Operand)
+
+ {
+ if (mod==3)
+ pGetRegister16Operand(Operand,r_m);
+ else
+ {
+ Operand->OperandType = Memory16Operand;
+ pGetMemoryOperand(Operand);
+ }
+ }
+
+/***************************************************************************/
+
+static VOID GetRegister8Operand(OPERAND *Operand)
+
+ {
+ pGetRegister8Operand(Operand,reg);
+ }
+
+/***************************************************************************/
+
+static VOID GetRegister16Operand(OPERAND *Operand)
+
+ {
+ pGetRegister16Operand(Operand,reg);
+ }
+
+/***************************************************************************/
+
+static VOID GetSegmentRegisterOperand(OPERAND *Operand)
+
+ {
+ pGetSegmentRegisterOperand(Operand,reg);
+ }
+
+/***************************************************************************/
+
+static VOID GetEmbeddedRegister8Operand(OPERAND *Operand)
+
+ {
+ pGetRegister8Operand(Operand,OperationCodeByte & 0x07);
+ }
+
+/***************************************************************************/
+
+static VOID GetEmbeddedRegister16Operand(OPERAND *Operand)
+
+ {
+ pGetRegister16Operand(Operand,OperationCodeByte & 0x07);
+ }
+
+/***************************************************************************/
+
+static VOID GetAccumulator8Operand(OPERAND *Operand)
+
+ {
+ pGetRegister8Operand(Operand,0);
+ }
+
+/***************************************************************************/
+
+static VOID GetAccumulator16Operand(OPERAND *Operand)
+
+ {
+ pGetRegister16Operand(Operand,0);
+ }
+
+/***************************************************************************/
+
+static VOID GetImmediate8Operand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Immediate8Operand;
+ Operand->Immediate8.L = CodeMem(IP); IP++;
+ }
+
+/***************************************************************************/
+
+static VOID GetImmediateSignExtend8Operand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Immediate16Operand;
+ Operand->Immediate16.L = CodeMem(IP); IP++;
+ if (Operand->Immediate16.L & 0x80)
+ Operand->Immediate16.H = 0xff;
+ else
+ Operand->Immediate16.H = 0x00;
+ }
+
+/***************************************************************************/
+
+static VOID GetImmediate16Operand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Immediate16Operand;
+ Operand->Immediate16.L = CodeMem(IP); IP++;
+ Operand->Immediate16.H = CodeMem(IP); IP++;
+ }
+
+/***************************************************************************/
+
+static VOID GetShortLabelOperand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = ShortLabelOperand;
+ Operand->ShortLabel.L = CodeMem(IP); IP++;
+ if (Operand->ShortLabel.L & 0x80)
+ Operand->ShortLabel.H = 0xff;
+ else
+ Operand->ShortLabel.H = 0x00;
+ }
+
+/***************************************************************************/
+
+static VOID GetImmediate32Operand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Immediate32Operand;
+ Operand->Immediate32Offset.L = CodeMem(IP); IP++;
+ Operand->Immediate32Offset.H = CodeMem(IP); IP++;
+ Operand->Immediate32Segment.L = CodeMem(IP); IP++;
+ Operand->Immediate32Segment.H = CodeMem(IP); IP++;
+ }
+
+/***************************************************************************/
+
+static VOID GetMemory8Operand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Memory8Operand;
+ Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.L = CodeMem(IP); IP++;
+ Operand->MemoryOffset.H = CodeMem(IP); IP++;
+ }
+
+/***************************************************************************/
+
+static VOID GetMemory16Operand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Memory16Operand;
+ Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.L = CodeMem(IP); IP++;
+ Operand->MemoryOffset.H = CodeMem(IP); IP++;
+ }
+
+/***************************************************************************/
+
+static VOID GetConstantOneOperand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Immediate8Operand;
+ Operand->Immediate8.L = 1;
+ }
+
+/***************************************************************************/
+
+static VOID GetRegisterCLOperand(OPERAND *Operand)
+
+ {
+ pGetRegister8Operand(Operand,1);
+ }
+
+/***************************************************************************/
+
+static VOID GetRegisterDXOperand(OPERAND *Operand)
+
+ {
+ pGetRegister16Operand(Operand,2);
+ }
+
+/***************************************************************************/
+
+static VOID GetRegisterESOperand(OPERAND *Operand)
+
+ {
+ pGetSegmentRegisterOperand(Operand,0);
+ }
+
+/***************************************************************************/
+
+static VOID GetRegisterCSOperand(OPERAND *Operand)
+
+ {
+ pGetSegmentRegisterOperand(Operand,1);
+ }
+
+/***************************************************************************/
+
+static VOID GetRegisterSSOperand(OPERAND *Operand)
+
+ {
+ pGetSegmentRegisterOperand(Operand,2);
+ }
+
+/***************************************************************************/
+
+static VOID GetRegisterDSOperand(OPERAND *Operand)
+
+ {
+ pGetSegmentRegisterOperand(Operand,3);
+ }
+
+/***************************************************************************/
+
+static VOID GetString8DSSIOperand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Memory8Operand;
+ Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = SI;
+ if (DF)
+ Delta = 0xFFFF;
+ else
+ Delta = 1;
+ }
+
+/***************************************************************************/
+
+static VOID GetString16DSSIOperand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Memory16Operand;
+ Operand->MemorySegment = pGetCurrentSegment(&DS);
+ Operand->MemoryOffset.X = SI;
+ if (DF)
+ Delta = 0xFFFE;
+ else
+ Delta = 2;
+ }
+
+/***************************************************************************/
+
+static VOID GetString8ESDIOperand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Memory8Operand;
+ Operand->MemorySegment = &ES;
+ Operand->MemoryOffset.X = DI;
+ if (DF)
+ Delta = 0xFFFF;
+ else
+ Delta = 1;
+ }
+
+/***************************************************************************/
+
+static VOID GetString16ESDIOperand(OPERAND *Operand)
+
+ {
+ Operand->OperandType = Memory16Operand;
+ Operand->MemorySegment = &ES;
+ Operand->MemoryOffset.X = DI;
+ if (DF)
+ Delta = 0xFFFE;
+ else
+ Delta = 2;
+ }
+
+/***************************************************************************/
+
+static VOID NullFunction()
+
+ {
+ }
+
+/***************************************************************************/
+
+
+/*++
+
+Flag Functions:
+
+ The following functions compute the new values for the FLAGS register
+ after an instruction has been executed. The Sign flag, Zero flag,
+ and Parity flag only depend on the value of the result. However,
+ the Overflow flag, Carry flag, and Auxillary carry flag depend on the
+ values of the left and right operand as well os the result and weather
+ the operation involved addition or subtraction.
+
+--*/
+
+static VOID ComputeFlags8(
+ ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function computes the Sign flag, Zero flag, and Parity flag for the
+ 8 bit result operand Result. If bit 7 is set, the Sign flag is true,
+ otherwise it is false. If all the bits are zero, the Zero flag is true,
+ otherwise it is false. The Parity flag is true if there are an even
+ number of bits set in the 8 bit quantity. ParityTable is used to speed
+ up this computation. Each entry in ParityTable contains the number of
+ bits set for a value that is equivalent to the index. ParityTable is 16
+ entries long, so it can handle 4 bit values. Two look ups are made for
+ bits 0:3 of Result and for bit 4:7 of result. These values are added
+ to get to total number of bits sets in the 8 bit Result operand. If this
+ sum is an even number, the Parity flag is set to true, otherwise it is
+ false.
+
+Arguments:
+
+ Result - 8 bit result operand used to generate flag values.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ SF = (Result>>7) & 1;
+ ZF = (Result & 0xff) == 0x00;
+ if (((ParityTable[Result&0x0f] + ParityTable[(Result>>4) & 0x0f]) & 0x01) == 0)
+ PF = 1;
+ else
+ PF = 0;
+ }
+
+static VOID ComputeFlags16(
+ ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function computes the Sign flag, Zero flag, and Parity flag for the
+ 16 bit result operand Result. If bit 15 is set, the Sign flag is true,
+ otherwise it is false. If all the bits are zero, the Zero flag is true,
+ otherwise it is false. The Parity flag is true if there are an even
+ number of bits set in the lower 8 bits of Result. ParityTable is used to
+ speed up this computation. Each entry in ParityTable contains the number
+ of bits set for a value that is equivalent to the index. ParityTable is
+ 16 entries long, so it can handle 4 bit values. Two look ups are made for
+ bits 0:3 of Result and for bit 4:7 of result. These values are added
+ to get to total number of bits sets in the lower 8 bits of Result. If this
+ sum is an even number, the Parity flag is set to true, otherwise it is
+ false.
+
+Arguments:
+
+ Result - 16 bit result operand used to generate flag values.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ SF = (Result>>15) & 1;
+ ZF = (Result & 0xffff) == 0x0000;
+ if (((ParityTable[Result&0x0f] + ParityTable[(Result>>4) & 0x0f]) & 0x01) == 0)
+ PF = 1;
+ else
+ PF = 0;
+ }
+
+static VOID ComputeSignZeroParityFlags(
+ ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function computes the Sign flag, Zero flag, and Parity flag for
+ the result operand of an instruction. The result operand may be either
+ an 8 bit quntity or a 16 bit quantity. The OperationCodeByte is
+ evaluated to determine the size of the operation, and the approriate
+ flag computation function is called.
+
+Arguments:
+
+ Result - 8 or 16 bit result operand used to compute flag values.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (OperationCodeByte & 0x01) // 16 Bit Operation
+ ComputeFlags16(Result);
+ else // 8 Bit Operation
+ ComputeFlags8(Result);
+ }
+
+static VOID ComputeAllFlags(
+ ULONG Left,
+ ULONG Right,
+ ULONG *Result,
+ ULONG AddFlag,
+ ULONG CarryIn
+ )
+
+/*++
+
+Routine Description:
+
+ This function computes all the flags that can be affected by an ALU
+ instruction. All instructions that use either an addition or a
+ subtraction operation that affect the state of the processors
+ flags use this function to perform the addition or subtraction
+ operation as well as all the flag computations.
+
+Arguments:
+
+ Left - The 8 or 16 bit value for the left operand of the instruction,
+
+ Right - The 8 or 16 bit value for the right operand of the instruction.
+
+ *Result - The 8 or 16 bit Result operand for the instruction
+
+ AddFlag - Flag that is either ADDOPERATION or SUBOPERATION
+
+ CarryIn - Value of Carry flag before the instruction is executed.
+
+Return Value:
+
+ The result of the operation is resturned in *Result..
+
+--*/
+
+ {
+ ULONG SmallResult; // Use to compute Auxillary Carry flag.
+
+ if (AddFlag==ADDOPERATION)
+ {
+ *Result = Left + Right + CarryIn;
+ SmallResult = (Left & 0x0f) + (Right & 0x0f) + CarryIn;
+ }
+ else
+ {
+ *Result = Left - Right - CarryIn;
+ SmallResult = (Left & 0x0f) - (Right & 0x0f) - CarryIn;
+ Right = (~Right) + 1; // Right = (-Right);
+ }
+ if (OperationCodeByte & 0x01) // 16 Bit Operation
+ {
+ if ( (Left&0x8000) == (Right&0x8000) && (Left&0x8000)!=(*Result&0x8000) )
+ OF = 1;
+ else
+ OF = 0;
+ if (*Result & 0x10000)
+ CF = 1;
+ else
+ CF = 0;
+ if (SmallResult & 0x10)
+ AF = 1;
+ else
+ AF = 0;
+ ComputeFlags16(*Result); // Compute Sign, Zero, and Parity flags.
+ }
+ else // 8 Bit Operation
+ {
+ if ( (Left&0x80) == (Right&0x80) && (Left&0x80)!=(*Result&0x80) )
+ OF = 1;
+ else
+ OF = 0;
+ if (*Result & 0x100)
+ CF = 1;
+ else
+ CF = 0;
+ if (SmallResult & 0x10)
+ AF = 1;
+ else
+ AF = 0;
+ ComputeFlags8(*Result); // Compute Sign, Zero, and Parity flags.
+ }
+ }
+
+static VOID
+GenerateINT(
+ UCHAR Type
+ )
+
+/*++
+
+Routine Description:
+
+ This function forces and INT vector call to be made. The flags are saved
+ onto the stack along with the current values of CS and IP. CS and IP are
+ then initialized to the vector for the INT Type being generated.
+
+Arguments:
+
+ Type - 8 bit value for the type of software interrupt to generate.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (SegmentOveridePrefix==TRUE)
+ IP--;
+ if (RepeatPrefix==TRUE)
+ IP--;
+ if (LockPrefix==TRUE)
+ IP--;
+
+#ifdef X86DEBUG1
+ AddressTrace[AddressTracePosition] = CS<<16 | IP;
+ AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
+#endif
+
+ SP = SP - 2;
+ PutStackMem(SP+0,Flags.L & 0xd7);
+ PutStackMem(SP+1,Flags.H & 0x0f);
+ IF = 0;
+ TF = 0;
+ SP = SP - 2;
+ PutStackMem(SP+0,cs.L);
+ PutStackMem(SP+1,cs.H);
+ SP = SP - 2;
+ PutStackMem(SP+0,ip.L);
+ PutStackMem(SP+1,ip.H);
+ cs.L = GetMemImmediate(0,Type*4+2);
+ cs.H = GetMemImmediate(0,Type*4+3);
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ ip.L = GetMemImmediate(0,Type*4+0);
+ ip.H = GetMemImmediate(0,Type*4+1);
+
+#ifdef X86DEBUG1
+ AddressTrace[AddressTracePosition] = CS<<16 | IP;
+ AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
+#endif
+ }
+
+/*++
+
+Instruction Functions:
+
+ The following functions perform the actions for each of the instructions
+ in the 80286 instruction set. The register macros defined at the top
+ of this file make these functions very readable. See an 80286 assembly
+ language book for a description of each of these instructions.
+
+--*/
+
+/***************************************************************************/
+
+static VOID InstInvalid()
+
+ {
+ PRINT4("Invalid Instruction %04X:%04X %02X\n\r",CS,IP,OperationCodeByte);
+ DISPLAY(PrintMessage);
+ ErrorCode = x86BiosInvalidInstruction;
+ ExitFlag = TRUE;
+ }
+
+/***************************************************************************/
+
+static VOID InstAAA()
+
+ {
+ if ( ((AL & 0x0F) > 9) || (AF==1) )
+ {
+ AL = AL + 6;
+ AH = AL + 1;
+ AF = 1;
+ CF = 1;
+ AL = AL & 0x0F;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstAAD()
+
+ {
+ AL = (AH * 0x0A) + AL;
+ AH = 0;
+ ComputeFlags8(AL);
+ }
+
+/***************************************************************************/
+
+static VOID InstAAM()
+
+ {
+ AH = AL / 0x0A;
+ AL = AL % 0x0A;
+ ComputeFlags16(AX);
+ }
+
+/***************************************************************************/
+
+static VOID InstAAS()
+
+ {
+ if ( ((AL & 0x0F) > 9) || (AF == 1) )
+ {
+ AL = AL - 6;
+ AH = AH - 1;
+ AF = 1;
+ CF = 1;
+ AL = AL & 0x0F;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstADC()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,ADDOPERATION,CF);
+ PutOperand(LSRC,0,Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstADD()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,ADDOPERATION,0);
+ PutOperand(LSRC,0,Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstAND()
+
+ {
+ ULONG Result;
+
+ Result = GetOperand(LSRC,0) & GetOperand(RSRC,0);
+ PutOperand(LSRC,0,Result);
+ CF = 0;
+ OF = 0;
+ ComputeSignZeroParityFlags(Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstOR()
+
+ {
+ ULONG Result;
+
+ Result = GetOperand(LSRC,0) | GetOperand(RSRC,0);
+ PutOperand(LSRC,0,Result);
+ CF = 0;
+ OF = 0;
+ ComputeSignZeroParityFlags(Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstCMP()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstSBB()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,CF);
+ PutOperand(LSRC,0,Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstSUB()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
+ PutOperand(LSRC,0,Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstXOR()
+
+ {
+ ULONG Result;
+
+ Result = GetOperand(LSRC,0) ^ GetOperand(RSRC,0);
+ PutOperand(LSRC,0,Result);
+ CF = 0;
+ OF = 0;
+ ComputeSignZeroParityFlags(Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstCBW()
+
+ {
+ if (AL & 0x80)
+ AH = 0xff;
+ else
+ AH = 0x00;
+ }
+
+/***************************************************************************/
+
+static VOID InstCLC()
+
+ {
+ CF = 0;
+ }
+
+/***************************************************************************/
+
+static VOID InstCLD()
+
+ {
+ DF = 0;
+ }
+
+/***************************************************************************/
+
+static VOID InstCLI()
+
+ {
+ IF = 0;
+ }
+
+/***************************************************************************/
+
+static VOID InstCMC()
+
+ {
+ if (CF == 0)
+ CF = 1;
+ else
+ CF = 0;
+ }
+
+/***************************************************************************/
+
+static VOID InstCWD()
+
+ {
+ if (AX & 0x8000)
+ DX = 0xffff;
+ else
+ DX = 0x0000;
+ }
+
+/***************************************************************************/
+
+static VOID InstDAA()
+
+ {
+ if ( ((AL & 0x0F) > 9) || (AF==1) )
+ {
+ AL = AL + 6;
+ AF = 1;
+ }
+ if ( (AL > 0x9f) || (CF==1) )
+ {
+ AL = AL + 0x60;
+ CF = 1;
+ }
+ ComputeFlags8(AL);
+ }
+
+/***************************************************************************/
+
+static VOID InstDAS()
+
+ {
+ if ( ((AL & 0x0F) > 9) || (AF==1) )
+ {
+ AL = AL - 6;
+ AF = 1;
+ }
+ if ( (AL > 0x9f) || (CF==1) )
+ {
+ AL = AL - 0x60;
+ CF = 1;
+ }
+ ComputeFlags8(AL);
+ }
+
+/***************************************************************************/
+
+static VOID InstDEC()
+
+ {
+ ULONG Left;
+
+ Left = GetOperand(LSRC,0);
+ Left = Left - 1;
+ PutOperand(LSRC,0,Left);
+ if (OperationCodeByte==0xfe) // 8 Bit Operation
+ {
+ if (Left==0x7f)
+ OF=1;
+ else
+ OF=0;
+ if ((Left & 0x0f)==0x0f)
+ AF = 1;
+ else
+ AF = 0;
+ ComputeFlags8(Left);
+ }
+ else
+ {
+ if (Left==0x7fff)
+ OF=1;
+ else
+ OF=0;
+ if ((Left & 0x0f)==0x0f)
+ AF = 1;
+ else
+ AF = 0;
+ ComputeFlags16(Left);
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstHLT()
+
+ {
+ ErrorCode = x86BiosHaltInstruction;
+ ExitFlag = TRUE;
+ }
+
+/***************************************************************************/
+
+static VOID InstINC()
+
+ {
+ ULONG Left;
+
+ Left = GetOperand(LSRC,0);
+ Left = Left + 1;
+ PutOperand(LSRC,0,Left);
+ if (OperationCodeByte == 0xfe) // 8 bit operation
+ {
+ if (Left==0x80)
+ OF=1;
+ else
+ OF=0;
+ if ((Left & 0x0f)==0x00)
+ AF = 1;
+ else
+ AF = 0;
+ ComputeFlags8(Left);
+ }
+ else
+ {
+ if (Left==0x8000)
+ OF=1;
+ else
+ OF=0;
+ if ((Left & 0x0f)==0x00)
+ AF = 1;
+ else
+ AF = 0;
+ ComputeFlags16(Left);
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstLAHF()
+
+ {
+ AH = Flags.L & 0xd7;
+ }
+
+/***************************************************************************/
+
+static VOID InstLDS()
+
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ DS = GetOperand(RSRC,2);
+ DSCacheRegister = GetSegmentCacheRegister(DS);
+ }
+
+/***************************************************************************/
+
+static VOID InstSAHF()
+
+ {
+ Flags.L = AH & 0xd7;
+ }
+
+/***************************************************************************/
+
+static VOID InstSTC()
+
+ {
+ CF = 1;
+ }
+
+/***************************************************************************/
+
+static VOID InstSTD()
+
+ {
+ DF = 1;
+ }
+
+/***************************************************************************/
+
+static VOID InstSTI()
+
+ {
+ IF = 1;
+ SSRegisterTouched = TRUE;
+ }
+
+/***************************************************************************/
+
+static VOID InstWAIT()
+
+ {
+ ErrorCode = x86BiosWaitInstruction;
+ ExitFlag = TRUE;
+ }
+
+/***************************************************************************/
+
+static VOID InstPUSH()
+
+ {
+ ULONG Value;
+
+ Value = GetOperand(LSRC,0);
+ SP = SP - 2;
+ PutStackMem(SP+0,Value);
+ PutStackMem(SP+1,Value >> 8);
+ }
+
+/***************************************************************************/
+
+VOID InstPUSHA()
+
+ {
+ USHORT OriginalSP;
+
+ OriginalSP = SP;
+ SP = SP - 2;
+ PutStackMem(SP+0,AL);
+ PutStackMem(SP+1,AH);
+ SP = SP - 2;
+ PutStackMem(SP+0,BL);
+ PutStackMem(SP+1,BH);
+ SP = SP - 2;
+ PutStackMem(SP+0,CL);
+ PutStackMem(SP+1,CH);
+ SP = SP - 2;
+ PutStackMem(SP+0,DL);
+ PutStackMem(SP+1,DH);
+ SP = SP - 2;
+ PutStackMem(SP+0,OriginalSP);
+ PutStackMem(SP+1,OriginalSP >> 8);
+ SP = SP - 2;
+ PutStackMem(SP+0,BP);
+ PutStackMem(SP+1,BP >> 8);
+ SP = SP - 2;
+ PutStackMem(SP+0,SI);
+ PutStackMem(SP+1,SI >> 8);
+ SP = SP - 2;
+ PutStackMem(SP+0,DI);
+ PutStackMem(SP+1,DI >> 8);
+ }
+
+/***************************************************************************/
+
+static VOID InstPOP()
+
+ {
+ ULONG Value;
+
+ Value = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ PutOperand(LSRC,0,Value);
+ }
+
+/***************************************************************************/
+
+VOID InstPOPA()
+
+ {
+ DI = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ SI = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ BP = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ SP = SP + 2;
+ DX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ CX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ BX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ AX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
+ SP = SP + 2;
+ }
+
+/***************************************************************************/
+
+static VOID InstJO()
+
+ {
+ if (OF==1)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNO()
+
+ {
+ if (OF==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJB()
+
+ {
+ if (CF==1)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNB()
+
+ {
+ if (CF==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJE()
+
+ {
+ if (ZF==1)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNE()
+
+ {
+ if (ZF==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJBE()
+
+ {
+ if (CF==1 || ZF==1)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNBE()
+
+ {
+ if (CF==0 && ZF==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJS()
+
+ {
+ if (SF==1)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNS()
+
+ {
+ if (SF==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJP()
+
+ {
+ if (PF==1)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNP()
+
+ {
+ if (PF==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJL()
+
+ {
+ if (SF!=OF)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNL()
+
+ {
+ if (SF==OF)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJLE()
+
+ {
+ if (ZF==1 || SF!=OF)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJNLE()
+
+ {
+ if (ZF==0 && SF==OF)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstTEST()
+
+ {
+ ULONG Result;
+
+ if (OperationCodeByte == 0xf6)
+ GetImmediate8Operand(RSRC);
+ if (OperationCodeByte == 0xf7)
+ GetImmediate16Operand(RSRC);
+ Result = GetOperand(LSRC,0) & GetOperand(RSRC,0);
+ CF = 0;
+ OF = 0;
+ ComputeSignZeroParityFlags(Result);
+ }
+
+/***************************************************************************/
+
+static VOID InstXCHG()
+
+ {
+ ULONG Temp;
+
+ Temp = GetOperand(RSRC,0);
+ PutOperand(RSRC,0,GetOperand(LSRC,0));
+ PutOperand(LSRC,0,Temp);
+ }
+
+/***************************************************************************/
+
+static VOID InstMOV()
+
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ }
+
+/***************************************************************************/
+
+static VOID InstLEA()
+
+ {
+ PutOperand(LSRC,0,RSRC->MemoryOffset.X);
+ }
+
+/***************************************************************************/
+
+static VOID InstCALL()
+
+ {
+ ULONG Value;
+
+ Value = GetOperand(LSRC,0);
+ switch (OperationCodeByte)
+ {
+ case 0xe8 : SP = SP - 2;
+ PutStackMem(SP+0,ip.L);
+ PutStackMem(SP+1,ip.H);
+ IP = IP + Value;
+ break;
+ case 0xff : if ( ((AddressModeByte >> 3) & 0x07) == 0x02)
+ {
+ SP = SP - 2;
+ PutStackMem(SP+0,ip.L);
+ PutStackMem(SP+1,ip.H);
+ IP = Value;
+ }
+ else if ( ((AddressModeByte >> 3) & 0x07) == 0x03)
+ {
+ SP = SP - 4;
+ PutStackMem(SP+0,ip.L);
+ PutStackMem(SP+1,ip.H);
+ PutStackMem(SP+2,cs.L);
+ PutStackMem(SP+3,cs.H);
+ IP = Value;
+ CS = GetOperand(LSRC,2);
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ }
+ break;
+ case 0x9a : SP = SP - 4;
+ PutStackMem(SP+0,ip.L);
+ PutStackMem(SP+1,ip.H);
+ PutStackMem(SP+2,cs.L);
+ PutStackMem(SP+3,cs.H);
+ IP = Value;
+ CS = Value >> 16;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ break;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstPUSHF()
+
+ {
+ SP = SP - 2;
+ PutStackMem(SP+0,Flags.L & 0xd7);
+ PutStackMem(SP+1,Flags.H & 0x0f);
+ }
+
+/**********************************f*****************************************/
+
+static VOID InstPOPF()
+
+ {
+ Flags.L = GetStackMem(SP+0) & 0xd7;
+ Flags.H = GetStackMem(SP+1) & 0x0f;
+ SP = SP + 2;
+ }
+
+/***************************************************************************/
+
+static VOID InstMOVS()
+
+ {
+ if (RepeatPrefix==TRUE)
+ {
+ while(CX!=0)
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ CX = CX - 1;
+ SI += Delta;
+ DI += Delta;
+ LSRC->MemoryOffset.X += Delta;
+ RSRC->MemoryOffset.X += Delta;
+ }
+ }
+ else
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ SI = SI + Delta;
+ DI = DI + Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstCMPS()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ if (RepeatPrefix==TRUE)
+ {
+ while(CX!=0)
+ {
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
+ CX--;
+ SI += Delta;
+ DI += Delta;
+ LSRC->MemoryOffset.X += Delta;
+ RSRC->MemoryOffset.X += Delta;
+ if (ZF != RepeatZeroFlag)
+ return;
+ }
+ }
+ else
+ {
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
+ SI += Delta;
+ DI += Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstSTOS()
+
+ {
+ if (RepeatPrefix==TRUE)
+ {
+ while(CX!=0)
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ CX--;
+ DI += Delta;
+ LSRC->MemoryOffset.X += Delta;
+ }
+ }
+ else
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ DI += Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstLODS()
+
+ {
+ if (RepeatPrefix==TRUE)
+ {
+ while(CX!=0)
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ CX--;
+ SI += Delta;
+ RSRC->MemoryOffset.X += Delta;
+ }
+ }
+ else
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ SI += Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstSCAS()
+
+ {
+ ULONG Left;
+ ULONG Right;
+ ULONG Result;
+
+ if (RepeatPrefix==TRUE)
+ {
+ while(CX!=0)
+ {
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
+ CX--;
+ DI += Delta;
+ RSRC->MemoryOffset.X += Delta;
+ if (ZF != RepeatZeroFlag)
+ return;
+ }
+ }
+ else
+ {
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
+ DI += Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstRET()
+
+ {
+ ip.L = GetStackMem(SP+0);
+ ip.H = GetStackMem(SP+1);
+ SP = SP + 2;
+ switch(OperationCodeByte)
+ {
+ case 0xc2 : SP = SP + GetOperand(LSRC,0);
+ break;
+ case 0xca : cs.L = GetStackMem(SP + 0);
+ cs.H = GetStackMem(SP + 1);
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ SP = SP + 2;
+ SP = SP + GetOperand(LSRC,0);
+ break;
+ case 0xcb : cs.L = GetStackMem(SP + 0);
+ cs.H = GetStackMem(SP + 1);
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ SP = SP + 2;
+ break;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstLES()
+
+ {
+ PutOperand(LSRC,0,GetOperand(RSRC,0));
+ ES = GetOperand(RSRC,2);
+ ESCacheRegister = GetSegmentCacheRegister(ES);
+ }
+
+/***************************************************************************/
+
+static VOID InstINT()
+
+ {
+ if (OperationCodeByte & 0x01)
+ GenerateINT(GetOperand(LSRC,0));
+ else
+ GenerateINT(3);
+ }
+
+/***************************************************************************/
+
+static VOID InstINTO()
+
+ {
+ if (OF == 1)
+ GenerateINT(4);
+ }
+
+/***************************************************************************/
+
+static VOID InstIRET()
+
+ {
+#ifdef X86DEBUG1
+ AddressTrace[AddressTracePosition] = CS<<16 | IP;
+ AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
+#endif
+
+ ip.L = GetStackMem(SP+0);
+ ip.H = GetStackMem(SP+1);
+ SP = SP + 2;
+ cs.L = GetStackMem(SP+0);
+ cs.H = GetStackMem(SP+1);
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ SP = SP + 2;
+ Flags.L = GetStackMem(SP+0) & 0xd7;
+ Flags.H = GetStackMem(SP+1) & 0x0f;
+ SP = SP + 2;
+
+#ifdef X86DEBUG1
+ AddressTrace[AddressTracePosition] = CS<<16 | IP;
+ AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
+#endif
+ }
+
+/***************************************************************************/
+
+static VOID InstROL()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ if (OperationCodeByte & 0x01)
+ CF = (Value>>15) & 1;
+ else
+ CF = (Value>>7) & 1;
+ Value = (Value << 1) | CF;
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>15) & 1;
+ else
+ TempF = (Value>>7) & 1;
+ if (TempF != CF)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstROR()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ CF = Value & 1;
+ if (OperationCodeByte & 0x01)
+ Value = ((Value >> 1) & 0x7fff) | (CF << 15);
+ else
+ Value = ((Value >> 1) & 0x7f) | (CF << 7);
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>14) & 3;
+ else
+ TempF = (Value>>6) & 3;
+ if (TempF==1 || TempF==2)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstRCL()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+ ULONG tmpcf;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ tmpcf = CF;
+ if (OperationCodeByte & 0x01)
+ CF = (Value>>15) & 1;
+ else
+ CF = (Value>>7) & 1;
+ Value = (Value << 1) | tmpcf;
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>15) & 1;
+ else
+ TempF = (Value>>7) & 1;
+ if (TempF != CF)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstRCR()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+ ULONG tmpcf;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ tmpcf = CF;
+ CF = Value & 1;
+ if (OperationCodeByte & 0x01)
+ Value = ((Value >> 1) & 0x7fff) | (tmpcf << 15);
+ else
+ Value = ((Value >> 1) & 0x7f) | (tmpcf << 7);
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>14) & 3;
+ else
+ TempF = (Value>>6) & 3;
+ if (TempF==1 || TempF==2)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstSAL()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ if (OperationCodeByte & 0x01)
+ CF = (Value>>15) & 1;
+ else
+ CF = (Value>>7) & 1;
+ Value = (Value << 1);
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>15) & 1;
+ else
+ TempF = (Value>>7) & 1;
+ if (TempF != CF)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ ComputeSignZeroParityFlags(Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstSHR()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ CF = Value & 1;
+ if (OperationCodeByte & 0x01)
+ Value = ((Value >> 1) & 0x7fff);
+ else
+ Value = ((Value >> 1) & 0x7f);
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>14) & 3;
+ else
+ TempF = (Value>>6) & 3;
+ if (TempF==1 || TempF==2)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ ComputeSignZeroParityFlags(Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstSAR()
+
+ {
+ ULONG Count;
+ ULONG Temp;
+ ULONG Value;
+ ULONG TempF;
+
+ Value = GetOperand(LSRC,0);
+ Count = GetOperand(RSRC,0);
+ Temp = Count;
+ while (Temp!=0)
+ {
+ CF = Value & 1;
+ if (OperationCodeByte & 0x01)
+ Value = ((Value >> 1) & 0x7fff) | (Value & 0x8000);
+ else
+ Value = ((Value >> 1) & 0x7f) | (Value & 0x80);
+ Temp = Temp - 1;
+ }
+ if (Count==1)
+ {
+ if (OperationCodeByte & 0x01)
+ TempF = (Value>>14) & 3;
+ else
+ TempF = (Value>>6) & 3;
+ if (TempF==1 || TempF==2)
+ OF = 1;
+ else
+ OF = 0;
+ }
+ PutOperand(LSRC,0,Value);
+ ComputeSignZeroParityFlags(Value);
+ }
+
+/***************************************************************************/
+
+static VOID InstXLAT()
+
+ {
+ USHORT Segment;
+
+ Segment = *pGetCurrentSegment(&DS);
+ AL = GetMemImmediate(Segment,BX + AL);
+ }
+
+/***************************************************************************/
+
+static VOID InstESC()
+
+ {
+ }
+
+/***************************************************************************/
+
+static VOID InstLOOPNE()
+
+ {
+ CX--;
+ if (ZF==0 && CX!=0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstLOOPE()
+
+ {
+ CX--;
+ if (ZF==1 && CX!=0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstLOOP()
+
+ {
+ CX--;
+ if (CX!=0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstJCXZ()
+
+ {
+ if (CX==0)
+ IP = IP + GetOperand(LSRC,0);
+ }
+
+/***************************************************************************/
+
+static VOID InstIN()
+
+ {
+ ULONG Port;
+ ULONG Value;
+
+ Port = GetOperand(RSRC,0);
+
+ if (LSRC->OperandType == Register16Operand)
+ if (Port & 0x01)
+ {
+ Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port) | (READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port+1)<<8);
+ }
+ else
+ {
+ Value = READ_REGISTER_USHORT(BiosIsaIoBaseAddress+Port);
+ }
+ else
+ {
+ Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port);
+ }
+
+ PutOperand(LSRC,0,Value);
+
+ }
+
+/***************************************************************************/
+
+static VOID InstINS()
+
+ {
+ ULONG Port;
+ ULONG Value;
+
+ Port = GetOperand(RSRC,0);
+ if (RepeatPrefix)
+ {
+ while(CX!=0)
+ {
+ if (OperationCodeByte & 0x01)
+ if (Port & 0x01)
+ {
+ Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port) | (READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port+1)<<8);
+ }
+ else
+ {
+ Value = READ_REGISTER_USHORT(BiosIsaIoBaseAddress+Port);
+ }
+ else
+ {
+ Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port);
+ }
+ PutOperand(LSRC,0,Value);
+ CX--;
+ DI += Delta;
+ LSRC->MemoryOffset.X += Delta;
+ }
+ }
+ else
+ {
+ if (OperationCodeByte & 0x01)
+ if (Port & 0x01)
+ {
+ Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port) | (READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port+1)<<8);
+ }
+ else
+ {
+ Value = READ_REGISTER_USHORT(BiosIsaIoBaseAddress+Port);
+ }
+ else
+ {
+ Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port);
+ }
+ PutOperand(LSRC,0,Value);
+ DI += Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstOUT()
+
+ {
+ ULONG Port;
+ ULONG Value;
+
+ Port = GetOperand(RSRC,0);
+ Value = GetOperand(LSRC,0);
+ if (LSRC->OperandType == Register16Operand)
+ if (Port & 0x01)
+ {
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port + 1,Value>>8);
+ }
+ else
+ {
+ WRITE_REGISTER_USHORT(BiosIsaIoBaseAddress + Port,Value);
+ }
+ else
+ {
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstOUTS()
+
+ {
+ ULONG Port;
+ ULONG Value;
+
+ Port = GetOperand(RSRC,0);
+ if (RepeatPrefix)
+ {
+ while(CX!=0)
+ {
+ Value = GetOperand(LSRC,0);
+ if (OperationCodeByte & 0x01)
+ if (Port & 0x01)
+ {
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port + 1,Value>>8);
+ }
+ else
+ {
+ WRITE_REGISTER_USHORT(BiosIsaIoBaseAddress + Port,Value);
+ }
+ else
+ {
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
+ }
+ CX--;
+ SI += Delta;
+ LSRC->MemoryOffset.X += Delta;
+ }
+ }
+ else
+ {
+ Value = GetOperand(LSRC,0);
+ if (OperationCodeByte & 0x01)
+ if (Port & 0x01)
+ {
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port + 1,Value>>8);
+ }
+ else
+ {
+ WRITE_REGISTER_USHORT(BiosIsaIoBaseAddress + Port,Value);
+ }
+ else
+ {
+ WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
+ }
+ SI += Delta;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstJMP()
+
+ {
+ ULONG Value;
+
+ Value = GetOperand(LSRC,0);
+ switch(OperationCodeByte)
+ {
+ case 0xe9 : IP = IP + Value;
+ break;
+ case 0xea : IP = Value;
+ CS = Value >> 16;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ break;
+ case 0xeb : IP = IP + Value;
+ break;
+ case 0xff : if (reg==4)
+ IP = Value;
+ if (reg==5)
+ {
+ IP = Value;
+ CS = GetOperand(LSRC,2);
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ }
+ break;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstLOCK()
+
+ {
+ LockPrefix = TRUE;
+ }
+
+/***************************************************************************/
+
+static VOID InstREP()
+
+ {
+ RepeatPrefix = TRUE;
+ RepeatZeroFlag = OperationCodeByte & 0x01;
+ }
+
+/***************************************************************************/
+
+static VOID InstNOT()
+
+ {
+ PutOperand(LSRC,0,0xFFFF - GetOperand(LSRC,0));
+ }
+
+/***************************************************************************/
+
+static VOID InstNEG()
+
+ {
+ ULONG Left;
+ ULONG Result;
+
+ Left = GetOperand(LSRC,0);
+ Result = 0xFFFF - Left + 1;
+ PutOperand(LSRC,0,Result);
+ if (Result == 0)
+ CF = 0;
+ else
+ CF = 1;
+ }
+
+/***************************************************************************/
+
+static VOID InstMUL()
+
+ {
+ ULONG Temp;
+
+ if (OperationCodeByte & 0x01)
+ {
+ Temp = (ULONG)(AX) * (ULONG)(GetOperand(LSRC,0));
+ AX = Temp & 0xffff;
+ DX = (Temp >> 16) & 0xffff;
+ if (DX==0)
+ CF = 0;
+ else
+ CF = 1;
+ }
+ else
+ {
+ Temp = (ULONG)(AL) * (ULONG)(GetOperand(LSRC,0));
+ AX = Temp & 0xffff;
+ if (AH==0)
+ CF = 0;
+ else
+ CF = 1;
+ }
+ OF = CF;
+ }
+
+/***************************************************************************/
+
+static VOID InstIMUL()
+
+ {
+ LONG Temp;
+
+ if (OperationCodeByte & 0x01)
+ {
+ if (OperationCodeByte == 0xf7)
+ Temp = (ULONG)(AX) * (ULONG)(GetOperand(LSRC,0));
+ else
+ Temp = (ULONG)(GetOperand(LSRC,0)) * (ULONG)(GetOperand(RSRC,0));
+ AX = Temp & 0xffff;
+ DX = (Temp >> 16) & 0xffff;
+ if ( ((AX & 0x8000)==0 && DX==0) || ((AX & 0x8000)==0x8000 && DX==0xffff))
+ CF = 0;
+ else
+ CF = 1;
+ }
+ else
+ {
+ if (OperationCodeByte == 0xf6)
+ Temp = (ULONG)(AL) * (ULONG)(GetOperand(LSRC,0));
+ else
+ Temp = (ULONG)(GetOperand(LSRC,0)) * (ULONG)(GetOperand(RSRC,0));
+ AX = Temp & 0xffff;
+ if ( ((AL & 0x80)==0 && AH==0) || ((AL & 0x80)==0x80 && AH==0xff))
+ CF = 0;
+ else
+ CF = 1;
+ }
+ OF = CF;
+ }
+
+/***************************************************************************/
+
+static VOID InstDIV()
+
+ {
+ ULONG Numr;
+ ULONG Divr;
+
+ if (OperationCodeByte & 0x01)
+ {
+ Numr = ((ULONG)DX << 16) | AX;
+ Divr = (ULONG)GetOperand(LSRC,0);
+ if (Divr==0)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ if ((Numr/Divr) > 0xffff)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ AX = Numr/Divr;
+ DX = Numr%Divr;
+ }
+ else
+ {
+ Numr = AX;
+ Divr = (ULONG)GetOperand(LSRC,0);
+ if (Divr==0)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ if ((Numr/Divr) > 0xff)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ AL = Numr/Divr;
+ AH = Numr%Divr;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstIDIV()
+
+ {
+ ULONG Numr;
+ ULONG Divr;
+
+ if (OperationCodeByte & 0x01)
+ {
+ Numr = ((ULONG)DX << 16) | AX;
+ Divr = (ULONG)GetOperand(LSRC,0);
+ if (Divr==0)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ if ((Numr/Divr) > 0xffff)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ AX = Numr/Divr;
+ DX = Numr%Divr;
+ }
+ else
+ {
+ Numr = AX;
+ Divr = (ULONG)GetOperand(LSRC,0);
+ if (Divr==0)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ if ((Numr/Divr) > 0xff)
+ {
+ ErrorCode = x86BiosDivideByZero;
+ ExitFlag = TRUE;
+ return;
+ }
+ AL = Numr/Divr;
+ AH = Numr%Divr;
+ }
+ }
+
+/***************************************************************************/
+
+static VOID InstSegmentOveride()
+
+ {
+ SegmentOveridePrefix = TRUE;
+ OverideSegmentRegister = LSRC->Register16;
+ }
+
+/***************************************************************************/
+
+//
+// Most of the 80286 Protected Mode Instructions are sent to this function.
+// Most of these instructions are unimplemented because they are not
+// normally used, and hence are difficult to test. So far, I have not seen
+// any addin card BIOS's use these instructions.
+//
+
+static VOID InstDescriptorTable()
+
+ {
+ if (ExtendedOperationCodeByte==0x00)
+ {
+ switch(reg)
+ {
+ case 0 : DISPLAY("SLDT");
+ break;
+ case 1 : DISPLAY("STR");
+ break;
+ case 2 : DISPLAY("LLDT");
+ break;
+ case 3 : DISPLAY("LTR");
+ break;
+ case 4 : DISPLAY("VERR read");
+ break;
+ case 5 : DISPLAY("VERR write");
+ break;
+ default : DISPLAY("Unknown Instruction");
+ break;
+ }
+ }
+ else if (ExtendedOperationCodeByte==0x01)
+ {
+ switch(reg)
+ {
+ case 0 : PutOperand(LSRC,0,gdtLimit);
+ PutOperand(LSRC,2,(gdtBase & 0x00ffffff));
+ PutOperand(LSRC,4,((gdtBase & 0x00ffffff) | 0xff000000)>>16);
+ return;
+ case 1 : DISPLAY("SIDT");
+ PutOperand(LSRC,0,idtLimit);
+ PutOperand(LSRC,2,(idtBase & 0x00ffffff));
+ PutOperand(LSRC,4,((idtBase & 0x00ffffff) | 0xff000000)>>16);
+ break;
+ case 2 : gdtLimit = GetOperand(LSRC,0);
+ gdtBase = (GetOperand(LSRC,2) | (GetOperand(LSRC,4)<<16)) & 0x00ffffff;
+ return;
+ case 3 : idtLimit = GetOperand(LSRC,0);
+ idtBase = (GetOperand(LSRC,2) | (GetOperand(LSRC,4)<<16)) & 0x00ffffff;
+ return;
+ case 4 : PutOperand(LSRC,0,msw);
+ return;
+ case 6 : msw = GetOperand(LSRC,0);
+ return;
+ default : DISPLAY("Unknown Instruction");
+ break;
+ }
+ }
+ else if (ExtendedOperationCodeByte==0x02)
+ {
+ DISPLAY("LAR");
+ }
+ else if (ExtendedOperationCodeByte==0x03)
+ {
+ DISPLAY("LSL");
+ }
+ else if (ExtendedOperationCodeByte==0x06)
+ {
+ DISPLAY("CTS");
+ }
+ else if (ExtendedOperationCodeByte==0x63)
+ {
+ DISPLAY("ARPL");
+ }
+ else
+ {
+ DISPLAY("Unknown Instruction");
+ }
+ DISPLAY("\n\r");
+ InstInvalid();
+ }
+
+/***************************************************************************/
+
+VOID InstENTER()
+
+ {
+ ULONG Left;
+ ULONG Right;
+
+ Left = GetOperand(LSRC,0);
+ Right = GetOperand(RSRC,0);
+ if (Right==0)
+ {
+ SP = SP - 2;
+ PutStackMem(SP+0,BP);
+ PutStackMem(SP+1,BP>>8);
+ BP = SP;
+ SP = SP - Left;
+ }
+ else
+ {
+ DISPLAY("ENTER with L!=0\n\r");
+ ErrorCode = x86BiosInvalidInstruction;
+ ExitFlag = TRUE;
+ }
+ }
+
+/***************************************************************************/
+
+VOID InstLEAVE()
+
+ {
+ SP = BP;
+ BP = GetStackMem(SP+0) | (GetStackMem(SP+1)<<8);
+ SP = SP + 2;
+ }
+
+/***************************************************************************/
+
+/*++
+
+Address Decoding Tables:
+
+ The size of the address decoding table was reduced by defining 8 bit
+ tokens for the different address decoding functions. These tokens
+ are stored in the address decoding table. When an instruction is
+ being decoded, a token will be retrieved for the left operand and for
+ the right operand. The DecodeOperandFunctionTable[] is used to
+ convert this 8 bit token to a function pointer which can be called.
+
+ The AddressModeByteRequired[] table is used to identify which address
+ modes require and address mode byte to be parsed from an instruction.
+ If either the left operand or the right operand use an address mode
+ for which AddressModeByteRequired[] is true, then the second byte of
+ the instruction is an address mode byte.
+
+--*/
+
+
+#define NULL_OPERAND 0
+#define REG8_MEM8 1 // AddressModeByte required
+#define REG16_MEM16 2 // AddressModeByte required
+#define REG8 3 // AddressModeByte required
+#define REG16 4 // AddressModeByte required
+#define SEGREG 5 // AddressModeByte required
+#define EMBEDDED_REG8 6
+#define EMBEDDED_REG16 7
+#define ACC8 8
+#define ACC16 9
+#define IMMED8 10
+#define IMMED8_SX 11
+#define IMMED16 12
+#define SHORT_LABEL 13
+#define IMMED32 14
+#define MEM8 15
+#define MEM16 16
+#define CONST_1 17
+#define REG_CL 18
+#define REG_DX 19
+#define STRING8_DSSI 20
+#define STRING16_DSSI 21
+#define STRING8_ESDI 22
+#define STRING16_ESDI 23
+#define REG_ES 24
+#define REG_DS 25
+#define REG_SS 26
+#define REG_CS 27
+
+static const UCHAR AddressModeByteRequired[28] = {0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+static const VOID (*DecodeOperandFunctionTable[28])() =
+ {
+ NullFunction,
+ GetMemory8OrRegister8Operand,
+ GetMemory16OrRegister16Operand,
+ GetRegister8Operand,
+ GetRegister16Operand,
+ GetSegmentRegisterOperand,
+ GetEmbeddedRegister8Operand,
+ GetEmbeddedRegister16Operand,
+ GetAccumulator8Operand,
+ GetAccumulator16Operand,
+ GetImmediate8Operand,
+ GetImmediateSignExtend8Operand,
+ GetImmediate16Operand,
+ GetShortLabelOperand,
+ GetImmediate32Operand,
+ GetMemory8Operand,
+ GetMemory16Operand,
+ GetConstantOneOperand,
+ GetRegisterCLOperand,
+ GetRegisterDXOperand,
+ GetString8DSSIOperand,
+ GetString16DSSIOperand,
+ GetString8ESDIOperand,
+ GetString16ESDIOperand,
+ GetRegisterESOperand,
+ GetRegisterDSOperand,
+ GetRegisterSSOperand,
+ GetRegisterCSOperand
+ };
+
+static const UCHAR DecodeOperandsTable[256][2] =
+ {
+ { REG8_MEM8 , REG8 }, // 00 ADD
+ { REG16_MEM16 , REG16 }, // 01 ADD
+ { REG8 , REG8_MEM8 }, // 02 ADD
+ { REG16 , REG16_MEM16 }, // 03 ADD
+ { ACC8 , IMMED8 }, // 04 ADD
+ { ACC16 , IMMED16 }, // 05 ADD
+ { REG_ES , NULL_OPERAND }, // 06 PUSH ES
+ { REG_ES , NULL_OPERAND }, // 07 POP ES
+ { REG8_MEM8 , REG8 }, // 08 OR
+ { REG16_MEM16 , REG16 }, // 09 OR
+ { REG8 , REG8_MEM8 }, // 0A OR
+ { REG16 , REG16_MEM16 }, // 0B OR
+ { ACC8 , IMMED8 }, // 0C OR
+ { ACC16 , IMMED16 }, // 0D OR
+ { REG_CS , NULL_OPERAND }, // 0E PUSH CS
+ { NULL_OPERAND , NULL_OPERAND }, // 0F 286 Extended Operation Codes
+
+ { REG8_MEM8 , REG8 }, // 10 ADC
+ { REG16_MEM16 , REG16 }, // 11 ADC
+ { REG8 , REG8_MEM8 }, // 12 ADC
+ { REG16 , REG16_MEM16 }, // 13 ADC
+ { ACC8 , IMMED8 }, // 14 ADC
+ { ACC16 , IMMED16 }, // 15 ADC
+ { REG_SS , NULL_OPERAND }, // 16 PUSH SS
+ { REG_SS , NULL_OPERAND }, // 17 POP SS
+ { REG8_MEM8 , REG8 }, // 18 SBB
+ { REG16_MEM16 , REG16 }, // 19 SBB
+ { REG8 , REG8_MEM8 }, // 1A SBB
+ { REG16 , REG16_MEM16 }, // 1B SBB
+ { ACC8 , IMMED8 }, // 1C SBB
+ { ACC16 , IMMED16 }, // 1D SBB
+ { REG_DS , NULL_OPERAND }, // 1E PUSH DS
+ { REG_DS , NULL_OPERAND }, // 1F POP DS
+
+ { REG8_MEM8 , REG8 }, // 20 AND
+ { REG16_MEM16 , REG16 }, // 21 AND
+ { REG8 , REG8_MEM8 }, // 22 ANC
+ { REG16 , REG16_MEM16 }, // 23 AND
+ { ACC8 , IMMED8 }, // 24 AND
+ { ACC16 , IMMED16 }, // 25 AND
+ { REG_ES , NULL_OPERAND }, // 26 ES: (segment overide)
+ { NULL_OPERAND , NULL_OPERAND }, // 27 DAA
+ { REG8_MEM8 , REG8 }, // 28 SUB
+ { REG16_MEM16 , REG16 }, // 29 SUB
+ { REG8 , REG8_MEM8 }, // 2A SUB
+ { REG16 , REG16_MEM16 }, // 2B SUB
+ { ACC8 , IMMED8 }, // 2C SUB
+ { ACC16 , IMMED16 }, // 2D SUB
+ { REG_CS , NULL_OPERAND }, // 2E CS: (segment overide)
+ { NULL_OPERAND , NULL_OPERAND }, // 2F DAS
+
+ { REG8_MEM8 , REG8 }, // 30 XOR
+ { REG16_MEM16 , REG16 }, // 31 XOR
+ { REG8 , REG8_MEM8 }, // 32 XOR
+ { REG16 , REG16_MEM16 }, // 33 XOR
+ { ACC8 , IMMED8 }, // 34 XOR
+ { ACC16 , IMMED16 }, // 35 XOR
+ { REG_SS , NULL_OPERAND }, // 36 SS: (segment overide)
+ { NULL_OPERAND , NULL_OPERAND }, // 37 AAA
+ { REG8_MEM8 , REG8 }, // 38 CMP
+ { REG16_MEM16 , REG16 }, // 39 CMP
+ { REG8 , REG8_MEM8 }, // 3A CMP
+ { REG16 , REG16_MEM16 }, // 3B CMP
+ { ACC8 , IMMED8 }, // 3C CMP
+ { ACC16 , IMMED16 }, // 3D CMP
+ { REG_DS , NULL_OPERAND }, // 3E DS: (segment overide)
+ { NULL_OPERAND , NULL_OPERAND }, // 3F AAS
+
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 40 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 41 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 42 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 43 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 44 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 45 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 46 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 47 INC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 48 DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 49 DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 4A DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 4B DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 4C DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 4D DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 4E DEC
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 4F DEC
+
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 50 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 51 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 52 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 53 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 54 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 55 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 56 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 57 PUSH
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 58 POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 59 POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 5A POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 5B POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 5C POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 5D POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 5E POP
+ { EMBEDDED_REG16 , NULL_OPERAND }, // 5F POP
+
+ { NULL_OPERAND , NULL_OPERAND }, // 60 PUSHA
+ { NULL_OPERAND , NULL_OPERAND }, // 61 POPA
+ { NULL_OPERAND , NULL_OPERAND }, // 62 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // 63 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // 64 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // 65 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // 66 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // 67 (not used)
+ { IMMED16 , NULL_OPERAND }, // 68 PUSH
+ { REG16_MEM16 , IMMED16 }, // 69 IMUL
+ { IMMED8_SX , NULL_OPERAND }, // 6A PUSH
+ { REG16_MEM16 , IMMED8_SX }, // 6B IMUL
+ { STRING8_ESDI , REG_DX }, // 6C INS
+ { STRING16_ESDI , REG_DX }, // 6D INS
+ { STRING8_DSSI , REG_DX }, // 6E OUTS
+ { STRING16_DSSI , REG_DX }, // 6F OUTS
+
+ { SHORT_LABEL , NULL_OPERAND }, // 70 JO
+ { SHORT_LABEL , NULL_OPERAND }, // 71 JNO
+ { SHORT_LABEL , NULL_OPERAND }, // 72 JB
+ { SHORT_LABEL , NULL_OPERAND }, // 73 JNB
+ { SHORT_LABEL , NULL_OPERAND }, // 74 JE
+ { SHORT_LABEL , NULL_OPERAND }, // 75 JNE
+ { SHORT_LABEL , NULL_OPERAND }, // 76 JBE
+ { SHORT_LABEL , NULL_OPERAND }, // 77 JNBE
+ { SHORT_LABEL , NULL_OPERAND }, // 78 JS
+ { SHORT_LABEL , NULL_OPERAND }, // 79 JNS
+ { SHORT_LABEL , NULL_OPERAND }, // 7A JP
+ { SHORT_LABEL , NULL_OPERAND }, // 7B JNP
+ { SHORT_LABEL , NULL_OPERAND }, // 7C JL
+ { SHORT_LABEL , NULL_OPERAND }, // 7D JNL
+ { SHORT_LABEL , NULL_OPERAND }, // 7E JLE
+ { SHORT_LABEL , NULL_OPERAND }, // 7F JNLE
+
+ { REG8_MEM8 , IMMED8 }, // 80 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
+ { REG16_MEM16 , IMMED16 }, // 81 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
+ { REG8_MEM8 , IMMED8 }, // 82 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
+ { REG16_MEM16 , IMMED8_SX }, // 83 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
+ { REG8_MEM8 , REG8 }, // 84 TEST
+ { REG16_MEM16 , REG16 }, // 85 TEST
+ { REG8_MEM8 , REG8 }, // 86 XCHG
+ { REG16_MEM16 , REG16 }, // 87 XCHG
+ { REG8_MEM8 , REG8 }, // 88 MOV
+ { REG16_MEM16 , REG16 }, // 89 MOV
+ { REG8 , REG8_MEM8 }, // 8A MOV
+ { REG16 , REG16_MEM16 }, // 8B MOV
+ { REG16_MEM16 , SEGREG }, // 8C MOV
+ { REG16 , REG16_MEM16 }, // 8D LEA
+ { SEGREG , REG16_MEM16 }, // 8E MOV
+ { REG16_MEM16 , NULL_OPERAND }, // 8F POP
+
+ { ACC16 , EMBEDDED_REG16 }, // 90 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 91 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 92 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 93 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 94 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 95 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 96 XCHG
+ { ACC16 , EMBEDDED_REG16 }, // 97 XCHG
+ { NULL_OPERAND , NULL_OPERAND }, // 98 CBW
+ { NULL_OPERAND , NULL_OPERAND }, // 99 CWD
+ { IMMED32 , NULL_OPERAND }, // 9A CALL
+ { NULL_OPERAND , NULL_OPERAND }, // 9B WAIT
+ { NULL_OPERAND , NULL_OPERAND }, // 9C PUSHF
+ { NULL_OPERAND , NULL_OPERAND }, // 9D POPF
+ { NULL_OPERAND , NULL_OPERAND }, // 9E SAHF
+ { NULL_OPERAND , NULL_OPERAND }, // 9F LAHF
+
+ { ACC8 , MEM8 }, // A0 MOV
+ { ACC16 , MEM16 }, // A1 MOV
+ { MEM8 , ACC8 }, // A2 MOV
+ { MEM16 , ACC16 }, // A3 MOV
+ { STRING8_ESDI , STRING8_DSSI }, // A4 MOVS
+ { STRING16_ESDI , STRING16_DSSI }, // A5 MOVS
+ { STRING8_ESDI , STRING8_DSSI }, // A6 CMPS
+ { STRING16_ESDI , STRING16_DSSI }, // A7 CMPS
+ { ACC8 , IMMED8 }, // A8 TEST
+ { ACC16 , IMMED16 }, // A9 TEST
+ { STRING8_ESDI , ACC8 }, // AA STOS
+ { STRING16_ESDI , ACC16 }, // AB STOS
+ { ACC8 , STRING8_DSSI }, // AC LODS
+ { ACC16 , STRING16_DSSI }, // AD LODS
+ { ACC8 , STRING8_ESDI }, // AE SCAS
+ { ACC16 , STRING16_ESDI }, // AF SCAS
+
+ { EMBEDDED_REG8 , IMMED8 }, // B0 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B1 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B2 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B3 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B4 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B5 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B6 MOV
+ { EMBEDDED_REG8 , IMMED8 }, // B7 MOV
+ { EMBEDDED_REG16 , IMMED16 }, // B8 MOV
+ { EMBEDDED_REG16 , IMMED16 }, // B9 MOV
+ { EMBEDDED_REG16 , IMMED16 }, // BA MOV
+ { EMBEDDED_REG16 , IMMED16 }, // BB MOV
+ { EMBEDDED_REG16 , IMMED16 }, // BC MOV
+ { EMBEDDED_REG16 , IMMED16 }, // BD MOV
+ { EMBEDDED_REG16 , IMMED16 }, // BE MOV
+ { EMBEDDED_REG16 , IMMED16 }, // BF MOV
+
+ { REG8_MEM8 , IMMED8 }, // C0 (286) ROL/ROR/RCL/RCR/SAL/SHR/SAR
+ { REG16_MEM16 , IMMED8 }, // C1 (286) ROL/ROR/RCL/RCR/SAL/SHR/SAR
+ { IMMED16 , NULL_OPERAND }, // C2 RET
+ { NULL_OPERAND , NULL_OPERAND }, // C3 RET
+ { REG16 , REG16_MEM16 }, // C4 LES
+ { REG16 , REG16_MEM16 }, // C5 LDS
+ { REG8_MEM8 , IMMED8 }, // C6 MOV
+ { REG16_MEM16 , IMMED16 }, // C7 MOV
+ { IMMED16 , IMMED8 }, // C8 ENTER
+ { NULL_OPERAND , NULL_OPERAND }, // C9 LEAVE
+ { IMMED16 , NULL_OPERAND }, // CA RET
+ { NULL_OPERAND , NULL_OPERAND }, // CB RET
+ { NULL_OPERAND , NULL_OPERAND }, // CC INT 3
+ { IMMED8 , NULL_OPERAND }, // CD INT
+ { NULL_OPERAND , NULL_OPERAND }, // CE INTO
+ { NULL_OPERAND , NULL_OPERAND }, // CF IRET
+
+ { REG8_MEM8 , CONST_1 }, // D0 ROL/ROR/RCL/RCR/SAL/SHR/SAR
+ { REG16_MEM16 , CONST_1 }, // D1 ROL/ROR/RCL/RCR/SAL/SHR/SAR
+ { REG8_MEM8 , REG_CL }, // D2 ROL/ROR/RCL/RCR/SAL/SHR/SAR
+ { REG16_MEM16 , REG_CL }, // D3 ROL/ROR/RCL/RCR/SAL/SHR/SAR
+ { IMMED8 , NULL_OPERAND }, // D4 AAM
+ { IMMED8 , NULL_OPERAND }, // D5 AAD
+ { NULL_OPERAND , NULL_OPERAND }, // D6 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // D7 XLAT
+ { IMMED8 , NULL_OPERAND }, // D8 ESC
+ { REG16_MEM16 , NULL_OPERAND }, // D9 ESC
+ { REG16_MEM16 , NULL_OPERAND }, // DA ESC
+ { REG16_MEM16 , NULL_OPERAND }, // DB ESC
+ { REG16_MEM16 , NULL_OPERAND }, // DC ESC
+ { REG16_MEM16 , NULL_OPERAND }, // DD ESC
+ { REG16_MEM16 , NULL_OPERAND }, // DE ESC
+ { IMMED8 , NULL_OPERAND }, // DF ESC
+
+ { SHORT_LABEL , NULL_OPERAND }, // E0 LOOPNE
+ { SHORT_LABEL , NULL_OPERAND }, // E1 LOOPE
+ { SHORT_LABEL , NULL_OPERAND }, // E2 LOOP
+ { SHORT_LABEL , NULL_OPERAND }, // E3 JCXZ
+ { ACC8 , IMMED8 }, // E4 IN
+ { ACC16 , IMMED8 }, // E5 IN
+ { ACC8 , IMMED8 }, // E6 OUT
+ { ACC16 , IMMED8 }, // E7 OUT
+ { IMMED16 , NULL_OPERAND }, // E8 CALL
+ { IMMED16 , NULL_OPERAND }, // E9 JMP
+ { IMMED32 , NULL_OPERAND }, // EA JMP
+ { SHORT_LABEL , NULL_OPERAND }, // EB JMP
+ { ACC8 , REG_DX }, // EC IN
+ { ACC16 , REG_DX }, // ED IN
+ { ACC8 , REG_DX }, // EE OUT
+ { ACC16 , REG_DX }, // EF OUT
+
+ { NULL_OPERAND , NULL_OPERAND }, // F0 LOCK
+ { NULL_OPERAND , NULL_OPERAND }, // F1 (not used)
+ { NULL_OPERAND , NULL_OPERAND }, // F2 REPNE
+ { NULL_OPERAND , NULL_OPERAND }, // F3 REPE
+ { NULL_OPERAND , NULL_OPERAND }, // F4 HLT
+ { NULL_OPERAND , NULL_OPERAND }, // F5 CMC
+ { REG8_MEM8 , NULL_OPERAND }, // F6 TEST/NOT/NEG/MUL/IMUL/DIV/IDIV/TEST
+ { REG16_MEM16 , NULL_OPERAND }, // F7 TEST/NOT/NEG/MUL/IMUL/DIV/IDIV/TEST
+ { NULL_OPERAND , NULL_OPERAND }, // F8 CLC
+ { NULL_OPERAND , NULL_OPERAND }, // F9 STC
+ { NULL_OPERAND , NULL_OPERAND }, // FA CLI
+ { NULL_OPERAND , NULL_OPERAND }, // FB STI
+ { NULL_OPERAND , NULL_OPERAND }, // FC CLD
+ { NULL_OPERAND , NULL_OPERAND }, // FD STD
+ { REG8_MEM8 , NULL_OPERAND }, // FE INC/DEC
+ { REG16_MEM16 , NULL_OPERAND } // FF INC/DEC/CALL/JMP/PUSH
+ };
+
+/*++
+
+Instruction Decoding Tables:
+
+ The size of the instruction decoding table was reduced by defining 8 bit
+ tokens for the different instruction functions. These tokens are stored
+ in the instruction decoding table. When an instruction is being decoded,
+ a token will be retrieved. For instructions without address mode bytes,
+ the first token for that instruction will be retrieved. For instructions
+ with address mode byes, bits 3-5 of the address mode byte will be used
+ as a sub index into the instruction decoding table. This table has 256
+ rows for each possible operation code value, and is 8 columns wide for
+ each of the 8 possible values for bits 3-5 of the address mode byte.
+ Once an instruction token has been retrieved, the
+ DecodeInstructionFunctionTable[] can be used to convert the token to a
+ function pointer. This function is called to execute the instruction.
+
+--*/
+
+#define NUMINSTRUCTIONTYPES 105
+
+#define INST_INV 0
+#define INST_ADD 1
+#define INST_PUSH 2
+#define INST_POP 3
+#define INST_OR 4
+#define INST_ADC 5
+#define INST_SBB 6
+#define INST_AND 7
+#define INST_ES_ 8
+#define INST_DAA 9
+#define INST_SUB 10
+#define INST_CS_ 11
+#define INST_DAS 12
+#define INST_XOR 13
+#define INST_SS_ 14
+#define INST_AAA 15
+#define INST_CMP 16
+#define INST_DS_ 17
+#define INST_AAS 18
+#define INST_INC 19
+#define INST_DEC 20
+#define INST_JO 21
+#define INST_JNO 22
+#define INST_JB 23
+#define INST_JNB 24
+#define INST_JE 25
+#define INST_JNE 26
+#define INST_JBE 27
+#define INST_JNBE 28
+#define INST_JS 29
+#define INST_JNS 30
+#define INST_JP 31
+#define INST_JNP 32
+#define INST_JL 33
+#define INST_JNL 34
+#define INST_JLE 35
+#define INST_JNLE 36
+#define INST_TEST 37
+#define INST_XCHG 38
+#define INST_MOV 39
+#define INST_LEA 40
+#define INST_CBW 41
+#define INST_CWD 42
+#define INST_CALL 43
+#define INST_WAIT 44
+#define INST_PUSHF 45
+#define INST_POPF 46
+#define INST_SAHF 47
+#define INST_LAHF 48
+#define INST_MOVS 49
+#define INST_CMPS 50
+#define INST_STOS 51
+#define INST_LODS 52
+#define INST_SCAS 53
+#define INST_RET 54
+#define INST_LES 55
+#define INST_LDS 56
+#define INST_INT 57
+#define INST_INTO 58
+#define INST_IRET 59
+#define INST_ROL 60
+#define INST_ROR 61
+#define INST_RCL 62
+#define INST_RCR 63
+#define INST_SAL 64
+#define INST_SHR 65
+#define INST_SAR 66
+#define INST_AAM 67
+#define INST_AAD 68
+#define INST_XLAT 69
+#define INST_ESC 70
+#define INST_LOOPNE 71
+#define INST_LOOPE 72
+#define INST_LOOP 73
+#define INST_JCXZ 74
+#define INST_IN 75
+#define INST_OUT 76
+#define INST_LOCK 77
+#define INST_REP 78
+#define INST_HLT 79
+#define INST_CMC 80
+#define INST_NOT 81
+#define INST_NEG 82
+#define INST_MUL 83
+#define INST_IMUL 84
+#define INST_DIV 85
+#define INST_IDIV 86
+#define INST_CLC 87
+#define INST_STC 88
+#define INST_CLI 89
+#define INST_STI 90
+#define INST_CLD 91
+#define INST_STD 92
+#define INST_JMP 93
+#define INST_SEG 94
+#define INST_PUSHA 95
+#define INST_POPA 96
+#define INST_DT 97
+#define INST_OUTS 98
+#define INST_ENTER 99
+#define INST_LEAVE 100
+#define INST_INS 101
+
+#ifdef X86DEBUG
+
+static const UCHAR *InstructionNames[NUMINSTRUCTIONTYPES] =
+ {
+ "Invalid ",
+ "ADD ",
+ "PUSH ",
+ "POP ",
+ "OR ",
+ "ADC ",
+ "SBB ",
+ "AND ",
+ "ES: ",
+ "DAA ",
+ "SUB ",
+ "CS: ",
+ "DAS ",
+ "XOR ",
+ "SS: ",
+ "AAA ",
+ "CMP ",
+ "DS: ",
+ "AAS ",
+ "INC ",
+ "DEC ",
+ "JO ",
+ "JNO ",
+ "JB ",
+ "JNB ",
+ "JE ",
+ "JNE ",
+ "JBE ",
+ "JNBE ",
+ "JS ",
+ "JNS ",
+ "JP ",
+ "JNP ",
+ "JL ",
+ "JNL ",
+ "JLE ",
+ "JNLE ",
+ "TEST ",
+ "XCHG ",
+ "MOV ",
+ "LEA ",
+ "CBW ",
+ "CWD ",
+ "CALL ",
+ "WAIT ",
+ "PUSHF ",
+ "POPF ",
+ "SAHF ",
+ "LAHF ",
+ "MOVS ",
+ "CMPS ",
+ "STOS ",
+ "LODS ",
+ "SCAS ",
+ "RET ",
+ "LES ",
+ "LDS ",
+ "INT ",
+ "INTO ",
+ "IRET ",
+ "ROL ",
+ "ROR ",
+ "RCL ",
+ "RCR ",
+ "SAL ",
+ "SHR ",
+ "SAR ",
+ "AAM ",
+ "AAD ",
+ "XLAT ",
+ "ESC ",
+ "LOOPNE ",
+ "LOOPE ",
+ "LOOP ",
+ "JCXZ ",
+ "IN ",
+ "OUT ",
+ "LOCK ",
+ "REP ",
+ "HLT ",
+ "CMC ",
+ "NOT ",
+ "NEG ",
+ "MUL ",
+ "IMUL ",
+ "DIV ",
+ "IDIV ",
+ "CLC ",
+ "STC ",
+ "CLI ",
+ "STI ",
+ "CLD ",
+ "STD ",
+ "JMP ",
+ " ",
+ "PUSHA ",
+ "POPA ",
+ "286DT ",
+ "OUTS ",
+ "ENTER ",
+ "LEAVE ",
+ "INS ",
+ };
+
+#endif
+
+static const VOID (*DecodeInstructionFunctionTable[NUMINSTRUCTIONTYPES])() =
+ {
+ InstInvalid,
+ InstADD,
+ InstPUSH,
+ InstPOP,
+ InstOR,
+ InstADC,
+ InstSBB,
+ InstAND,
+ NULL,
+ InstDAA,
+ InstSUB,
+ NULL,
+ InstDAS,
+ InstXOR,
+ NULL,
+ InstAAA,
+ InstCMP,
+ NULL,
+ InstAAS,
+ InstINC,
+ InstDEC,
+ InstJO,
+ InstJNO,
+ InstJB,
+ InstJNB,
+ InstJE,
+ InstJNE,
+ InstJBE,
+ InstJNBE,
+ InstJS,
+ InstJNS,
+ InstJP,
+ InstJNP,
+ InstJL,
+ InstJNL,
+ InstJLE,
+ InstJNLE,
+ InstTEST,
+ InstXCHG,
+ InstMOV,
+ InstLEA,
+ InstCBW,
+ InstCWD,
+ InstCALL,
+ InstWAIT,
+ InstPUSHF,
+ InstPOPF,
+ InstSAHF,
+ InstLAHF,
+ InstMOVS,
+ InstCMPS,
+ InstSTOS,
+ InstLODS,
+ InstSCAS,
+ InstRET,
+ InstLES,
+ InstLDS,
+ InstINT,
+ InstINTO,
+ InstIRET,
+ InstROL,
+ InstROR,
+ InstRCL,
+ InstRCR,
+ InstSAL,
+ InstSHR,
+ InstSAR,
+ InstAAM,
+ InstAAD,
+ InstXLAT,
+ InstESC,
+ InstLOOPNE,
+ InstLOOPE,
+ InstLOOP,
+ InstJCXZ,
+ InstIN,
+ InstOUT,
+ InstLOCK,
+ InstREP,
+ InstHLT,
+ InstCMC,
+ InstNOT,
+ InstNEG,
+ InstMUL,
+ InstIMUL,
+ InstDIV,
+ InstIDIV,
+ InstCLC,
+ InstSTC,
+ InstCLI,
+ InstSTI,
+ InstCLD,
+ InstSTD,
+ InstJMP,
+ InstSegmentOveride,
+ InstPUSHA,
+ InstPOPA,
+ InstDescriptorTable,
+ InstOUTS,
+ InstENTER,
+ InstLEAVE,
+ InstINS,
+ };
+
+static const UCHAR DecodeInstructionTable[256][8] =
+ {
+ { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 00
+ { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 01
+ { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 02
+ { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 03
+ { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 04
+ { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 05
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 06
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 07
+ { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 08
+ { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 09
+ { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0A
+ { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0B
+ { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0C
+ { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0D
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 0E
+ { INST_DT , INST_DT , INST_DT , INST_DT , INST_DT , INST_DT , INST_DT , INST_DT } , // 0F
+
+ { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 10
+ { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 11
+ { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 12
+ { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 13
+ { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 14
+ { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 15
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 16
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 17
+ { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 18
+ { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 19
+ { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1A
+ { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1B
+ { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1C
+ { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1D
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 1E
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 1F
+
+ { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 20
+ { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 21
+ { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 22
+ { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 23
+ { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 24
+ { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 25
+ { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 26
+ { INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA } , // 27
+ { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 28
+ { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 29
+ { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2A
+ { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2B
+ { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2C
+ { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2D
+ { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 2E
+ { INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS } , // 2F
+
+ { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 30
+ { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 31
+ { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 32
+ { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 33
+ { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 34
+ { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 35
+ { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 36
+ { INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA } , // 37
+ { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 38
+ { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 39
+ { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3A
+ { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3B
+ { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3C
+ { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3D
+ { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 3E
+ { INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS } , // 3F
+
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 40
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 41
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 42
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 43
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 44
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 45
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 46
+ { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 47
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 48
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 49
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4A
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4B
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4C
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4D
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4E
+ { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4F
+
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 50
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 51
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 52
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 53
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 54
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 55
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 56
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 57
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 58
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 59
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5A
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5B
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5C
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5D
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5E
+ { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5F
+
+ { INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA} , // 60
+ { INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA} , // 61
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 62
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 63
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 64
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 65
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 66
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 67
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 68
+ { INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL} , // 69
+ { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 6A
+ { INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL} , // 6B
+ { INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS } , // 6C
+ { INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS } , // 6D
+ { INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS} , // 6E
+ { INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS} , // 6F
+
+ { INST_JO , INST_JO , INST_JO , INST_JO , INST_JO , INST_JO , INST_JO , INST_JO } , // 70
+ { INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO } , // 71
+ { INST_JB , INST_JB , INST_JB , INST_JB , INST_JB , INST_JB , INST_JB , INST_JB } , // 72
+ { INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB } , // 73
+ { INST_JE , INST_JE , INST_JE , INST_JE , INST_JE , INST_JE , INST_JE , INST_JE } , // 74
+ { INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE } , // 75
+ { INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE } , // 76
+ { INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE} , // 77
+ { INST_JS , INST_JS , INST_JS , INST_JS , INST_JS , INST_JS , INST_JS , INST_JS } , // 78
+ { INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS } , // 79
+ { INST_JP , INST_JP , INST_JP , INST_JP , INST_JP , INST_JP , INST_JP , INST_JP } , // 7A
+ { INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP } , // 7B
+ { INST_JL , INST_JL , INST_JL , INST_JL , INST_JL , INST_JL , INST_JL , INST_JL } , // 7C
+ { INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL } , // 7D
+ { INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE } , // 7E
+ { INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE} , // 7F
+
+ { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 80
+ { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 81
+ { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 82
+ { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 83
+ { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // 84
+ { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // 85
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 86
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 87
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 88
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 89
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 8A
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 8B
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV } , // 8C
+ { INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA } , // 8D
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV } , // 8E
+ { INST_POP , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 8F
+
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 90
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 91
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 92
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 93
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 94
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 95
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 96
+ { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 97
+ { INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW } , // 98
+ { INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD } , // 99
+ { INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL} , // 9A
+ { INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT} , // 9B
+ { INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF} , // 9C
+ { INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF} , // 9D
+ { INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF} , // 9E
+ { INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF} , // 9F
+
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A0
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A1
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A2
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A3
+ { INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS} , // A4
+ { INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS} , // A5
+ { INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS} , // A6
+ { INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS} , // A7
+ { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // A8
+ { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // A9
+ { INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS} , // AA
+ { INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS} , // AB
+ { INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS} , // AC
+ { INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS} , // AD
+ { INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS} , // AE
+ { INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS} , // AF
+
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B0
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B1
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B2
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B3
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B4
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B5
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B6
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B7
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B8
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B9
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BA
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BB
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BC
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BD
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BE
+ { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BF
+
+ { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // C0
+ { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // C1
+ { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // C2
+ { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // C3
+ { INST_LES , INST_LES , INST_LES , INST_LES , INST_LES , INST_LES , INST_LES , INST_LES } , // C4
+ { INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS } , // C5
+ { INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // C6
+ { INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // C7
+ { INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER} , // C8
+ { INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE} , // C9
+ { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // CA
+ { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // CB
+ { INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT } , // CC
+ { INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT } , // CD
+ { INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO} , // CE
+ { INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET} , // CF
+
+ { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D0
+ { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D1
+ { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D2
+ { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D3
+ { INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM } , // D4
+ { INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD } , // D5
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // D6
+ { INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT} , // D7
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // D8
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // D9
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DA
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DB
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DC
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DD
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DE
+ { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DF
+
+ { INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE} , // E0
+ { INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE} , // E1
+ { INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP} , // E2
+ { INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ} , // E3
+ { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // E4
+ { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // E5
+ { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // E6
+ { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // E7
+ { INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL} , // E8
+ { INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP } , // E9
+ { INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP } , // EA
+ { INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP } , // EB
+ { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // EC
+ { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // ED
+ { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // EE
+ { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // EF
+
+ { INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK} , // F0
+ { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // F1
+ { INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP } , // F2
+ { INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP } , // F3
+ { INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT } , // F4
+ { INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC } , // F5
+ { INST_TEST , INST_INV , INST_NOT , INST_NEG , INST_MUL , INST_IMUL , INST_DIV , INST_IDIV} , // F6
+ { INST_TEST , INST_INV , INST_NOT , INST_NEG , INST_MUL , INST_IMUL , INST_DIV , INST_IDIV} , // F7
+ { INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC } , // F8
+ { INST_STC , INST_STC , INST_STC , INST_STC , INST_STC , INST_STC , INST_STC , INST_STC } , // F9
+ { INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI } , // FA
+ { INST_STI , INST_STI , INST_STI , INST_STI , INST_STI , INST_STI , INST_STI , INST_STI } , // FB
+ { INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD } , // FC
+ { INST_STD , INST_STD , INST_STD , INST_STD , INST_STD , INST_STD , INST_STD , INST_STD } , // FD
+ { INST_INC , INST_DEC , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // FE
+ { INST_INC , INST_DEC , INST_CALL , INST_CALL , INST_JMP , INST_JMP , INST_PUSH , INST_INV } , // FF
+ };
+
+
+//
+// Debugging functions
+//
+
+#ifdef X86DEBUG1
+
+static VOID DisplayProcessorState()
+
+ {
+ UCHAR S[512];
+
+ PrintProcessorState(S);
+ DISPLAY(S);
+ }
+
+static VOID DisplayCurrentInstruction()
+
+ {
+ UCHAR S[256];
+ ULONG i;
+ ULONG Column;
+
+ //
+ // Print Instruction Address
+ //
+
+ sprintf(S,"%04X:%04X ",CS,CurrentIP.X);
+ DISPLAY(S);
+ for(i=0;i<7;i++)
+ if ((CurrentIP.X + i) < IP)
+ {
+ sprintf(S,"%02X",CodeMem(CurrentIP.X+i));
+ DISPLAY(S);
+ }
+ else
+ DISPLAY(" ");
+
+ //
+ // Print Instruction Opcode
+ //
+
+ if (OperationCodeByte==0x26)
+ {
+ sprintf(S,"ES: ");
+ DISPLAY(S);
+ }
+ else if (OperationCodeByte==0x2E)
+ {
+ sprintf(S,"CS: ");
+ DISPLAY(S);
+ }
+ else if (OperationCodeByte==0x36)
+ {
+ sprintf(S,"SS: ");
+ DISPLAY(S);
+ }
+ else if (OperationCodeByte==0x3E)
+ {
+ sprintf(S,"DS: ");
+ DISPLAY(S);
+ }
+ else
+ {
+ sprintf(S,"%s",InstructionNames[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]]);
+ DISPLAY(S);
+
+ //
+ // Print Instruction Operands
+ //
+
+ Column = 0;
+ if (OperationCodeByte == 0xe8 ||
+ OperationCodeByte == 0xe9 ||
+ OperationCodeByte == 0xeb ||
+ (OperationCodeByte >= 0x70 && OperationCodeByte <= 0x7F))
+ {
+ sprintf(S,"%04X",IP+GetOperand(LSRC,0));
+ DISPLAY(S);
+ Column = Column + strlen(S);
+ }
+ else
+ {
+ if (LSRC->OperandType != NullOperand)
+ {
+ PrintOperandName(LSRC,S);
+ DISPLAY(S);
+ Column = Column + strlen(S);
+ }
+ if (RSRC->OperandType != NullOperand)
+ {
+ DISPLAY(",");
+ PrintOperandName(RSRC,S);
+ DISPLAY(S);
+ Column = Column + strlen(S) + 1;
+ }
+ }
+ for(i=Column;i<35;i++)
+ DISPLAY(" ");
+
+ //
+ // Print Memory Operand Value
+ //
+
+ if (LSRC->OperandType == Memory8Operand || LSRC->OperandType==Memory16Operand)
+ {
+ PrintMemorySegmentName(LSRC,S);
+ DISPLAY(S);
+ sprintf(S,":%04X",LSRC->MemoryOffset.X);
+ DISPLAY(S);
+ DISPLAY("=");
+ PrintOperandValue(LSRC,S);
+ DISPLAY(S);
+ }
+ if (RSRC->OperandType == Memory8Operand || RSRC->OperandType==Memory16Operand)
+ {
+ PrintMemorySegmentName(RSRC,S);
+ DISPLAY(S);
+ sprintf(S,":%04X",RSRC->MemoryOffset.X);
+ DISPLAY(S);
+ DISPLAY("=");
+ PrintOperandValue(RSRC,S);
+ DISPLAY(S);
+ }
+ }
+ DISPLAY("\n\r");
+ }
+
+/***************************************************************************/
+
+static VOID DecodeInstruction()
+
+ {
+ LSRC->OperandType = NullOperand;
+ RSRC->OperandType = NullOperand;
+ CurrentIP.X = IP;
+ OperationCodeByte = CodeMem(IP); IP++;
+ if (OperationCodeByte == 0x0f)
+ {
+ ExtendedOperationCodeByte = CodeMem(IP); IP++;
+ if (ExtendedOperationCodeByte == 0x01)
+ GetMemory16OrRegister16Operand(LSRC);
+ }
+ else
+ {
+ if (AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][0]] ||
+ AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][1]] )
+ {
+ GetAddressModeByte();
+ InstructionSubIndex = reg;
+ }
+ else
+ InstructionSubIndex = 0;
+ (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][0]])(LSRC);
+ (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][1]])(RSRC);
+ }
+ }
+
+/***************************************************************************/
+
+static VOID ExecuteInstruction()
+
+ {
+ ULONG SavedSegmentOveridePrefix;
+ ULONG SavedRepeatPrefix;
+ ULONG SavedLockPrefix;
+
+
+ if (SegmentOveridePrefix==TRUE ||
+ RepeatPrefix==TRUE ||
+ LockPrefix==TRUE )
+ {
+ SavedSegmentOveridePrefix = SegmentOveridePrefix;
+ SavedRepeatPrefix = RepeatPrefix;
+ SavedLockPrefix = LockPrefix;
+ (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
+ if (SavedSegmentOveridePrefix==SegmentOveridePrefix &&
+ SavedRepeatPrefix==RepeatPrefix &&
+ SavedLockPrefix==LockPrefix )
+ {
+ SegmentOveridePrefix = FALSE;
+ RepeatPrefix = FALSE;
+ LockPrefix = FALSE;
+ }
+ }
+ else
+ {
+ (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
+ }
+ }
+
+/***************************************************************************/
+
+static VOID CommandMode()
+
+ {
+ UCHAR ch;
+ UCHAR Command[256];
+ ULONG Done = FALSE;
+ REGISTER32 SavedCurrentIP;
+ USHORT SavedIP;
+ USHORT SavedCS;
+ USHORT i;
+ USHORT j;
+ UCHAR Value;
+ ULONG DefaultSegment;
+ ULONG DefaultParameter;
+ USHORT DataSegment;
+ USHORT DataAddress;
+ USHORT Parameter;
+ UCHAR CommandType;
+
+ SavedCurrentIP = CurrentIP;
+ SavedIP = IP;
+ SavedCS = CS;
+ DisplayProcessorState();
+ DecodeInstruction();
+ DisplayCurrentInstruction();
+ CurrentIP = SavedCurrentIP;
+ IP = SavedIP;
+ do
+ {
+ DISPLAY("-");
+
+ i=0;
+ do
+ {
+ GETCHAR(ch);
+ PUTCHAR(ch);
+ if (ch==0x08 && i>0)
+ i--;
+ else if (ch>=32 && ch<=127)
+ {
+ Command[i++] = ch;
+ }
+ }
+ while(ch!=0x0d);
+ Command[i] = 0;
+ DISPLAY("\n\r");
+
+ DefaultSegment = TRUE;
+ DataSegment = 0;
+ i=0;
+ for(;(Command[i]==' ' || Command[i]==':') && Command[i]!=0;i++);
+ for(j=i;Command[i]!=' ' && Command[i]!=':' && Command[i]!=0;i++);
+ CommandType = Command[j];
+ for(;(Command[i]==' ' || Command[i]==':') && Command[i]!=0;i++);
+ for(j=i;Command[i]!=' ' && Command[i]!=':' && Command[i]!=0;i++);
+ if (Command[i]==':')
+ {
+ DefaultSegment = FALSE;
+ Command[i]=0;
+ i++;
+ if (strcmp(&(Command[j]),"ds")==0 || strcmp(&(Command[j]),"DS")==0)
+ DataSegment = DS;
+ else if (strcmp(&(Command[j]),"es")==0 || strcmp(&(Command[j]),"ES")==0)
+ DataSegment = ES;
+ else if (strcmp(&(Command[j]),"ss")==0 || strcmp(&(Command[j]),"SS")==0)
+ DataSegment = SS;
+ else if (strcmp(&(Command[j]),"cs")==0 || strcmp(&(Command[j]),"CS")==0)
+ DataSegment = SavedCS;
+ else
+ DataSegment = atoh(&(Command[j]));
+ for(;(Command[i]==' ' || Command[i]==':') && Command[i]!=0;i++);
+ for(;Command[i]==' ' && Command[i]==':' && Command[i]!=0;i++);
+ for(j=i;(Command[i]!=' ' || Command[i]!=':') && Command[i]!=0;i++);
+ }
+ if (Command[j]==0)
+ {
+ DefaultParameter = TRUE;
+ Parameter = 0;
+ }
+ else
+ {
+ DefaultParameter = FALSE;
+ Parameter = atoh(&(Command[j]));
+ }
+ switch(CommandType)
+ {
+ case 'a' :
+ case 'A' : DISPLAY("Address Trace\n\r");
+ for(i=0;i<ADDRESSTRACESIZE;i+=2)
+ {
+ PRINT3(" Jump FAR from %04X:%04X to ",AddressTrace[AddressTracePosition]>>16,AddressTrace[AddressTracePosition]&0xffff);
+ DISPLAY(PrintMessage);
+ AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
+ PRINT3("%04X:%04X\n\r",AddressTrace[AddressTracePosition]>>16,AddressTrace[AddressTracePosition]&0xffff);
+ DISPLAY(PrintMessage);
+ AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
+ }
+ DISPLAY("\n\r");
+ break;
+ case 'g' :
+ case 'G' : GoFlag = TRUE;
+ if (!DefaultSegment)
+ StopSegment = DataSegment;
+ if (!DefaultParameter)
+ StopOffset = Parameter;
+ Done = TRUE;
+ break;
+ case 'u' :
+ case 'U' : if (!DefaultSegment)
+ {
+ CS = DataSegment;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ }
+ if (!DefaultParameter)
+ IP = Parameter;
+ for(i=0;i<20;i++)
+ {
+ DecodeInstruction();
+ DisplayCurrentInstruction();
+ }
+ break;
+ case 't' :
+ case 'T' : if (!DefaultSegment)
+ SavedCS = DataSegment;
+ if (!DefaultParameter)
+ SavedIP = Parameter;
+ Done = TRUE;
+ GoFlag = FALSE;
+ break;
+ case 'd' :
+ case 'D' : if (DefaultSegment)
+ DataSegment = DS;
+ if (!DefaultParameter)
+ DataAddress = Parameter;
+ for(i=0;i<8;i++)
+ {
+ PRINT3("%04X:%04X ",DataSegment,DataAddress+i*16);
+ DISPLAY(PrintMessage);
+ for(j=0;j<16;j++)
+ {
+ Value = GetMemImmediate(DataSegment,DataAddress+i*16+j);
+ PRINT2("%02X ",Value);
+ DISPLAY(PrintMessage);
+ }
+ DISPLAY(" ");
+ for(j=0;j<16;j++)
+ {
+ Value = GetMemImmediate(DataSegment,DataAddress+i*16+j);
+ if (Value<32 || Value >=128)
+ Value = '.';
+ PRINT2("%c",Value);
+ DISPLAY(PrintMessage);
+ }
+ DISPLAY("\n\r");
+ }
+ break;
+ case 'r' :
+ case 'R' : CurrentIP = SavedCurrentIP;
+ IP = SavedIP;
+ CS = SavedCS;
+ DisplayProcessorState();
+ DecodeInstruction();
+ DisplayCurrentInstruction();
+ CurrentIP = SavedCurrentIP;
+ IP = SavedIP;
+ CS = SavedCS;
+ break;
+ case 'm' :
+ case 'M' : msw = 0;
+ Flags.X = 0;
+ break;
+ case 'i' :
+ case 'I' : if (!DefaultParameter)
+ {
+ PRINT3("in %04X = %02X\n\r",Parameter,inp(Parameter));
+ DISPLAY(PrintMessage);
+ }
+ break;
+ case 'o' :
+ case 'O' : if (!DefaultSegment && !DefaultParameter)
+ {
+ outp(DataSegment,Parameter);
+ PRINT3("out %04X,%02X\n\r",DataSegment,Parameter);
+ DISPLAY(PrintMessage);
+ }
+ break;
+ }
+ }
+ while (Done == FALSE);
+ CurrentIP = SavedCurrentIP;
+ IP = SavedIP;
+ CS = SavedCS;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ }
+
+#endif
+
+static VOID Interpreter()
+
+/*++
+
+Routine Description:
+
+ This function is the main loop for the emulator. It decodes operands
+ and executes the instructions until the exit condition is met, or an
+ error occurs.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ ULONG SavedSegmentOveridePrefix; // Saved state of the SegmentOveridePrefix variable.
+ ULONG SavedRepeatPrefix; // Saved state of the RepeatPrefix variable.
+ ULONG SavedLockPrefix; // Saved state of the LockPrefix variable.
+ ULONG TrapFlagSet;
+
+ ExitFlag = FALSE;
+
+ //
+ // Loop until the exit condition is met.
+ //
+
+ while(ExitFlag==FALSE)
+ {
+
+
+#ifdef X86DEBUG1
+
+ //
+ // See if there is input on the debug serial port
+ //
+
+ if (inp(0x3f8+5) & 0x0001)
+ GoFlag = FALSE;
+#endif
+
+#ifdef X86DEBUG1
+
+ //
+ // See if a break point has been reached.
+ //
+
+ if (CS==StopSegment && IP==StopOffset)
+ GoFlag = FALSE;
+
+ if (GoFlag == FALSE)
+ CommandMode();
+#endif
+
+ //
+ // See if the exit condition has been met.
+ //
+
+ if (CS==ExitSegment && IP==ExitOffset)
+ {
+ ExitFlag = TRUE;
+ return;
+ }
+
+ //
+ // Check the condition of the trap flag. Execute the current instruction
+ // and then check to see if the trap flag was set before the instruction
+ // was executed.
+ //
+
+ if (TF)
+ TrapFlagSet = TRUE;
+ else
+ TrapFlagSet = FALSE;
+
+ //
+ // Initialize source operand variables and save the instruction pointer.
+ //
+
+ LSRC->OperandType = NullOperand;
+ RSRC->OperandType = NullOperand;
+ CurrentIP.X = IP;
+
+ //
+ // Read the operation code byte from memory
+ //
+
+ OperationCodeByte = CodeMem(IP); IP++;
+
+ //
+ // Decode the left and right operands
+ //
+
+ if (OperationCodeByte == 0x0f)
+ {
+
+ //
+ // This is a 286 Protected Mode Instructions
+ //
+
+ ExtendedOperationCodeByte = CodeMem(IP); IP++;
+ if (ExtendedOperationCodeByte == 0x01)
+ GetMemory16OrRegister16Operand(LSRC);
+ }
+ else
+ {
+
+ //
+ // See if an address mode byte needs to be parsed and compute the sub index
+ // into the instruction decoding table.
+ //
+
+ if (AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][0]] ||
+ AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][1]] )
+ {
+ GetAddressModeByte();
+ InstructionSubIndex = reg;
+ }
+ else
+ InstructionSubIndex = 0;
+
+ //
+ // Call address decoding function for the left operand
+ //
+
+ (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][0]])(LSRC);
+
+ //
+ // Call address decoding function for the right operand
+ //
+
+ (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][1]])(RSRC);
+ }
+
+ //
+ // Execute the instruction
+ //
+
+ if (SegmentOveridePrefix==TRUE ||
+ RepeatPrefix==TRUE ||
+ LockPrefix==TRUE )
+ {
+ //
+ // Prefix instructions have been parsed, so handle this in a special case.
+ // Save the state of the prefix variables.
+ //
+
+ SavedSegmentOveridePrefix = SegmentOveridePrefix;
+ SavedRepeatPrefix = RepeatPrefix;
+ SavedLockPrefix = LockPrefix;
+
+ //
+ // Call function to execute the instruction
+ //
+
+ (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
+
+ //
+ // See if this was another prefix instruction by comparing the state of the
+ // prefix variables before and after the current instruction has been executed.
+ //
+
+ if (SavedSegmentOveridePrefix==SegmentOveridePrefix &&
+ SavedRepeatPrefix==RepeatPrefix &&
+ SavedLockPrefix==LockPrefix )
+ {
+ //
+ // If the state did not change, then the current instruction is not a prefix
+ // instruction, so all the prefix variables should be cleared.
+ //
+
+ SegmentOveridePrefix = FALSE;
+ RepeatPrefix = FALSE;
+ LockPrefix = FALSE;
+ }
+ }
+ else
+ {
+ //
+ // Call function to execute the instruction
+ //
+
+ (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
+ }
+
+ //
+ // If the trap flag was set then exit the emulator.
+ //
+
+ if (TrapFlagSet)
+ {
+ ErrorCode = x86BiosTrapFlagAsserted;
+ ExitFlag = TRUE;
+ }
+ }
+ }
+
+
+static VOID x86FarCall(
+ USHORT pCS,
+ USHORT pIP
+ )
+
+/*++
+
+Routine Description:
+
+ This function makes a far call to the instruction at pCS:pIP. The
+ emulator will exit when the far call returns. To set up the exit
+ condition, a far call instruction is built at 0000:0501. CS and IP
+ are then initialized to 0000:0501, and the exit condition is intialized
+ to 0000:0506. When the emulator returns from the far call constructed at
+ 0000:0501, it will attempt to execute the instruction at 0000:0506, but
+ the exit condition has been met, so the emulator exits.
+
+Arguments:
+
+ pCS - Segment of the far call.
+ pIP - Offset of the far call.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+
+ //
+ // Build the far call instruction.
+ //
+
+ PutAbsoluteMem(0x00501,0x9a);
+ PutAbsoluteMem(0x00502,pIP);
+ PutAbsoluteMem(0x00503,pIP >> 8);
+ PutAbsoluteMem(0x00504,pCS);
+ PutAbsoluteMem(0x00505,pCS >> 8);
+
+ //
+ // Initialize the exit condition.
+ //
+
+ ExitSegment = 0x0000;
+ ExitOffset = 0x0506;
+
+ //
+ // Initialize the instruction pointer.
+ //
+
+ CS = 0x0000;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ IP = 0x0501;
+
+ //
+ // Start the emulator
+ //
+
+ Interpreter();
+ }
+
+X86BIOS_STATUS X86BiosInitializeAdapter(
+ ULONG Address
+ )
+
+/*++
+
+Routine Description:
+
+ This function attempts to initialize the adapter whose BIOS starts at
+ Address. First, a BIOS signature is verified. If the byte stored at
+ Address is 0x55 and the byte stored at Address+1 is 0xAA, then a
+ correct BIOS signature is present. Then, the byte at Address+2 encodes
+ the length of the BIOS across which a check sum should be performed. If
+ this check sum is verified, then a far call is made the Address+3.
+
+Arguments:
+
+ Address - 20 bit base address of the adapter BIOS to be initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ ULONG i;
+
+ ErrorCode = x86BiosSuccess;
+
+ //
+ // Check for a valid adapter BIOS signature.
+ //
+
+ if (GetAbsoluteMem(Address)!=0x55 || GetAbsoluteMem(Address+1)!=0xAA)
+ {
+ ErrorCode = x86BiosNoVideoBios;
+ return(ErrorCode);
+ }
+
+ //
+ // Perform checksum using byte 2 as the length of bios to perform check sum across
+ // If not correct set ErrorCode to InvalidBiosChecksum.
+ //
+
+ if (ErrorCode==x86BiosSuccess)
+ {
+
+ //
+ // Not implemented yet.
+ //
+
+ }
+
+ if (ErrorCode==x86BiosSuccess)
+ {
+
+ //
+ // Make a far call to Address + 3.
+ //
+
+ Address+=3;
+ x86FarCall(Address >>4,Address&0x000f);
+ }
+
+ //
+ // If an error occurred, send some info out the debug port.
+ //
+
+ if (ErrorCode!=x86BiosSuccess)
+ {
+ KdPrint(("x86Int() : ErrorCode = %d\n",ErrorCode));
+ KdPrint((" ISA I/O Virtul Base = %08X\n",BiosIsaIoBaseAddress));
+ KdPrint((" ISA Memory Virtual Base = %08x\n",ISABaseAddress));
+ KdPrint((" Main Memory [0-0x800] = %08X\n",VDMBaseAddress));
+ KdPrint((" CS:IP = %04X:%04X\n ",CS,CurrentIP.X));
+ for(i=0;i<16;i++)
+ KdPrint(("%02X ",GetMemImmediate(CS,CurrentIP.X+i)));
+ KdPrint(("\n"));
+ }
+
+ return(ErrorCode);
+
+ }
+
+X86BIOS_STATUS X86BiosExecuteInt(
+ USHORT Type,
+ PX86BIOS_CONTEXT Arguments
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an INT call. It assumes that the interrupt
+ vector table has already been initialized, and that the INT vector
+ for Type is valid. The values for the registers AX,BX,CX,DX,SI,DI, and
+ BP are passed in Arguments. These registers are initialized to
+ their new values, and an INT instruction is constructed at 0000:0506.
+ The exit condition is initialized to 0000:0508. After the INT call
+ completes, the new values of AX,BX,CX,DX,SI,DI,BP are placed back into
+ the Arguments data structure.
+
+Arguments:
+
+ Type - 8 bit interrupt type.
+
+ Arguments - Data structure used to pass in and pass out the values
+ of the registers AX,BX,CX,DX,SI,DI, and BP.
+
+Return Value:
+
+ Success if no error were encountered. Otherwise, an error code from
+ the emulator.
+
+--*/
+
+ {
+ ULONG i;
+
+ ErrorCode = x86BiosSuccess;
+
+ //
+ // Initialize register values
+ //
+
+ EAX = Arguments->Eax;
+ EBX = Arguments->Ebx;
+ ECX = Arguments->Ecx;
+ EDX = Arguments->Edx;
+ ESI = Arguments->Esi;
+ EDI = Arguments->Edi;
+ EBP = Arguments->Ebp;
+ ES = 0;
+ DS = 0;
+ Flags.X = 0;
+
+ //
+ // Build INT Type instruction.
+ //
+
+ PutAbsoluteMem(0x00506,0xcd);
+ PutAbsoluteMem(0x00507,Type);
+
+ //
+ // Initialize exit condition.
+ //
+
+ ExitSegment = 0x0000;
+ ExitOffset = 0x0508;
+
+ //
+ // Initialize instruction pointer.
+ //
+
+ CS = 0x0000;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ IP = 0x0506;
+
+ //
+ // Start the emulator.
+ //
+
+ Interpreter();
+
+ //
+ // Copy the new register values back into Arguments.
+ //
+
+ Arguments->Eax = EAX;
+ Arguments->Ebx = EBX;
+ Arguments->Ecx = ECX;
+ Arguments->Edx = EDX;
+ Arguments->Esi = ESI;
+ Arguments->Edi = EDI;
+ Arguments->Ebp = EBP;
+
+ //
+ // If an error occurred, send some info out the debug port.
+ //
+
+ if (ErrorCode!=x86BiosSuccess) {
+ DbgPrint(("x86Int() : ErrorCode = %d\n",ErrorCode));
+ DbgPrint((" ISA I/O Virtul Base = %08X\n",BiosIsaIoBaseAddress));
+ DbgPrint((" ISA Memory Virtual Base = %08x\n",ISABaseAddress));
+ DbgPrint((" Main Memory [0-0x800] = %08X\n",VDMBaseAddress));
+ DbgPrint((" CS:IP = %04X:%04X\n ",CS,CurrentIP.X));
+ for(i=0;i<16;i++)
+ DbgPrint(("%02X ",GetMemImmediate(CS,CurrentIP.X+i)));
+ DbgPrint(("\n"));
+ DbgBreakPoint();
+ }
+
+ return(ErrorCode);
+ }
+
+VOID X86BiosInitialize(
+ ULONG IsaIoVirtualBase,
+ ULONG IsaMemoryVirtualBase
+ )
+
+/*++
+
+Routine Description:
+
+ This function initialize the state of the 80286 processor, and the
+ state of the available memory.
+
+Arguments:
+
+ IsaIoVirtualBase - Noncached virtual address range that is 64KB long
+ and is mapped to the system's ISA I/O range.
+
+ IsaMemoryVirtualBase - Noncached virtual address ranges that is 1MB
+ long ans is mapped to the system's ISA memory
+ range.
+
+Return Value:
+
+ Success if no error were encountered. Otherwise, an error code from
+ the emulator.
+
+--*/
+
+ {
+ ULONG i;
+
+ //
+ // Initialize state of the 80286 processor.
+ //
+
+ SegmentOveridePrefix = FALSE;
+ RepeatPrefix = FALSE;
+ LockPrefix = FALSE;
+
+ IP = 0;
+ CS = 0;
+ CSCacheRegister = GetSegmentCacheRegister(CS);
+ DS = 0;
+ SS = 0;
+ SSCacheRegister = GetSegmentCacheRegister(SS);
+ ES = 0;
+ AX = 0;
+ BX = 0;
+ CX = 0;
+ DX = 0;
+ SP = 0;
+ BP = 0;
+ SI = 0;
+ DI = 0;
+ Flags.X = 0;
+
+ msw = 0;
+ gdtBase = 0;
+ gdtLimit = 0;
+ idtBase = 0;
+ idtLimit = 0;
+
+ //
+ // Initialize the variables used to perform I/O and memory operations.
+ //
+
+ BiosIsaIoBaseAddress = IsaIoVirtualBase;
+ ISABaseAddress = IsaMemoryVirtualBase;
+ VDMBaseAddress = (ULONG)(&(MemoryArray[0]));
+
+ //
+ // Intiialize all 256 INT vector to jump to 0000:0500
+ //
+
+ for(i=0;i<256;i++)
+ {
+ PutAbsoluteMem(i*4+0,0x00); // Fill in all INT vectors to jump to 0x00500
+ PutAbsoluteMem(i*4+1,0x05);
+ PutAbsoluteMem(i*4+2,0x00);
+ PutAbsoluteMem(i*4+3,0x00);
+ }
+
+ //
+ // Place an IRET instruction at 0000:0500.
+ // This way, if an INT call is made that does not exist, the emulator
+ // will just immediatly reach its exit condition and return.
+ //
+
+ PutAbsoluteMem(0x00500,0xcf);
+
+ //
+ // Intialize the spack pointer to the top of the available memory.
+ //
+
+ SS = 0x0000;
+ SP = 0x07fe;
+
+ }
diff --git a/private/ntos/nthals/haltyne/mips/xxcalstl.c b/private/ntos/nthals/haltyne/mips/xxcalstl.c
new file mode 100644
index 000000000..8060254d1
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/xxcalstl.c
@@ -0,0 +1,291 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Start the system clock to interrupt at MAXIMUM_INCREMENT intervals.
+ //
+ // N.B. MAXIMUM_INCREMENT is in 100ns units.
+ //
+
+ HalSetTimeIncrement(MAXIMUM_INCREMENT);
+ HalpProgramIntervalTimer(HalpNextIntervalCount);
+ HalpEnableEisaInterrupt(CLOCK2_LEVEL,Latched); /* Enable Timer1,Counter0 interrupt */
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+#if defined(R3000)
+
+ HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
+
+#endif
+
+#if defined(R4000)
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+#endif
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (PCR->StallScaleFactor <= 0) {
+ PCR->StallScaleFactor = 1;
+ }
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+// //
+// // Acknowledge the clock interrupt.
+// //
+//
+//#if defined(JAZZ)
+//
+// READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
+//
+//#endif
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+
+#if defined(R4000)
+
+ HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+
+#if defined(R4000)
+
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+#endif
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/haltyne/mips/xxclock.c b/private/ntos/nthals/haltyne/mips/xxclock.c
new file mode 100644
index 000000000..16ef4c83c
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/xxclock.c
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define clock count and time table.
+//
+
+typedef struct _COUNT_ENTRY {
+ ULONG Count;
+ ULONG Time;
+} COUNT_ENTRY, *PCOUNT_ENTRY;
+
+COUNT_ENTRY TimeTable[] = {
+ {1197, 10032},
+ {2394, 20064},
+ {3591, 30096},
+ {4767, 39952},
+ {5964, 49984},
+ {7161, 60016},
+ {8358, 70048},
+ {9555, 80080},
+ {10731, 89936},
+ {11928, 99968}
+ };
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG IntervalCount
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+Arguments:
+
+ IntervalCount - Supplies cound value to be placed in the timer/counter.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+
+ //
+ // Set the system clock timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ controlBase = HalpEisaControlBase;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)IntervalCount);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(IntervalCount >> 8));
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // The new clock count value is selected from a precomputed table of
+ // count/time pairs. The values in the table were selected for their
+ // accuracy and closeness to the values of 1ms, 2ms, 3ms, etc. to 10ms.
+ //
+ // N.B. The NT executive guarantees that this function will never
+ // be called with the desired incrment less than the minimum
+ // increment or greater than the maximum increment.
+ //
+
+ for (Index = 0; Index < sizeof(TimeTable) / sizeof(COUNT_ENTRY); Index += 1) {
+ if (DesiredIncrement <= TimeTable[Index].Time) {
+ break;
+ }
+ }
+
+ if (DesiredIncrement < TimeTable[Index].Time) {
+ Index -= 1;
+ }
+
+ HalpNextIntervalCount = TimeTable[Index].Count;
+ HalpNewTimeIncrement = TimeTable[Index].Time;
+ KeLowerIrql(OldIrql);
+ return HalpNewTimeIncrement;
+}
diff --git a/private/ntos/nthals/haltyne/mips/xxidle.s b/private/ntos/nthals/haltyne/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/haltyne/mips/xxinithl.c b/private/ntos/nthals/haltyne/mips/xxinithl.c
new file mode 100644
index 000000000..24e67c98a
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/xxinithl.c
@@ -0,0 +1,212 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+ULONG HalpBusType = MACHINE_TYPE_ISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG IoSpaceAlreadyMapped = FALSE;
+HAL_SYSTEM_PARAMETERS HalpSystemParameters;
+
+typedef
+VOID
+(*PGET_HAL_SYSTEM_PARAMETERS) (
+ OUT PHAL_SYSTEM_PARAMETERS SystemParameters
+ );
+
+PGET_HAL_SYSTEM_PARAMETERS PrivateGetHalSystemParameters;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = (PSYSTEM_PARAMETER_BLOCK)(0x80001000);
+
+ Prcb = KeGetCurrentPrcb();
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Get System Parameters from the Firmware if the GetHalSystemParameters function exists,
+ // Otherwise, assume a 512K DMA Cache.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 29) {
+ PrivateGetHalSystemParameters = *(PGET_HAL_SYSTEM_PARAMETERS *)((ULONG)(SystemParameterBlock->VendorVector) + 29*4);
+ PrivateGetHalSystemParameters(&HalpSystemParameters);
+ HalpMapBufferSize = HalpSystemParameters.DmaCacheSize;
+
+ } else {
+ DbgPrint("Warning : GetHalSystemParameters does not exist\n");
+ HalpMapBufferSize = 0x80000;
+ }
+
+ HalpMapBufferPhysicalAddress.HighPart = DMA_CACHE_PHYSICAL_BASE_HI;
+ HalpMapBufferPhysicalAddress.LowPart = DMA_CACHE_PHYSICAL_BASE_LO;
+
+ //
+ // Initialize interrupts.
+ //
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ HalpMapIoSpace();
+ HalpInitializeX86DisplayAdapter();
+ IoSpaceAlreadyMapped = TRUE;
+ }
+
+ HalpCreateDmaStructures();
+ HalpCalibrateStall();
+ return TRUE;
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion ()
+{
+
+}
diff --git a/private/ntos/nthals/haltyne/mips/xxinitnt.c b/private/ntos/nthals/haltyne/mips/xxinitnt.c
new file mode 100644
index 000000000..9053b05e9
--- /dev/null
+++ b/private/ntos/nthals/haltyne/mips/xxinitnt.c
@@ -0,0 +1,158 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+#if defined(R4000)
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+#endif
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Connect the clock interrupt to the stall interrupt routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Connect the R4000 count/compare interrupt to the early interrupt
+ // routine.
+ //
+
+#if defined(R4000)
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+#endif
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haltyne/sources b/private/ntos/nthals/haltyne/sources
new file mode 100644
index 000000000..7b5a6f427
--- /dev/null
+++ b/private/ntos/nthals/haltyne/sources
@@ -0,0 +1,84 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haltyne
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\mips\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+!IF $(MIPS)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\x86new;..\..\inc
+
+MIPS_ENABLE_MIPS3=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+MIPS_SOURCES=hal.rc \
+ drivesup.c \
+ mips\allstart.c \
+ mips\jxbeep.c \
+ mips\jxenvirv.c \
+ mips\j4flshbf.s \
+ mips\j4flshio.c \
+ mips\jxdisp.c \
+ mips\jxebsup.c \
+ mips\jxhwsup.c \
+ mips\jxmapio.c \
+ mips\jxport.c \
+ mips\j4cache.s \
+ mips\j4prof.c \
+ mips\x4tb.s \
+ mips\jxreturn.c \
+ mips\jxsysint.c \
+ mips\jxtime.c \
+ mips\jxusage.c \
+ mips\x86bios.c \
+ mips\x4clock.s \
+ mips\xxidle.s \
+ mips\xxcalstl.c \
+ mips\xxclock.c \
+ mips\xxinitnt.c \
+ mips\xxinithl.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(MIPS)
+
+NTTARGETFILES=$(TARGETPATH)\mips\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halvict/hal.rc b/private/ntos/nthals/halvict/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halvict/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halvict/makefile b/private/ntos/nthals/halvict/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halvict/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halvict/ppc/fwnvr.c b/private/ntos/nthals/halvict/ppc/fwnvr.c
new file mode 100644
index 000000000..74d30689e
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/fwnvr.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\fwnvr.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxbbl.c b/private/ntos/nthals/halvict/ppc/pxbbl.c
new file mode 100644
index 000000000..5466a07f1
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbbl.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxbbl.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxbeep.c b/private/ntos/nthals/halvict/ppc/pxbeep.c
new file mode 100644
index 000000000..cb3db8ccc
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbeep.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxbeep.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxbl.c b/private/ntos/nthals/halvict/ppc/pxbl.c
new file mode 100644
index 000000000..c80af0ce0
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbl.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxbl.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxbusdat.c b/private/ntos/nthals/halvict/ppc/pxbusdat.c
new file mode 100644
index 000000000..88573c58d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbusdat.c
@@ -0,0 +1,281 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+ Chris P. Karamatas (ckaramatas@vnet.ibm.com) 2.96 - Merged for common HAL
+
+--*/
+
+#include "halp.h"
+#include "ibmppc.h"
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0);
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ extern UCHAR HalpEpciMin;
+ extern UCHAR HalpEpciMax;
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler(
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool(SPRANGEPOOL, sizeof(SUPPORTED_RANGES));
+ RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ switch (InterfaceType) {
+ case Internal:
+ //
+ // This is a logical mapping of the 60X bus.
+ //
+ Bus->BusAddresses->Memory.Limit = 0xFEFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = 0;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+
+ break;
+
+ case PCIBus:
+
+ if (HalpSystemType == IBM_DORAL) {
+
+ //
+ // DORAL Cpu to PCI Addressing model. (See Doral spec,
+ // PCI Bridge Function).
+ //
+ // CPU Address PCI I/O PCI MEM EPCI I/O EPCI MEM
+ // Addr Addr Addr Addr
+ //
+ // 0x80000000 0
+ // 0x9fffffff 1fffffff
+ // 0xa0000000 20000000
+ // 0xafffffff 2fffffff
+ // 0xb0000000
+ // 0xbfffffff
+ // 0xc0000000 0
+ // 0xdfffffff 1fffffff
+ // 0xe0000000 20000000
+ // 0xfeffffff 3effffff *
+ //
+ // * This is 4GB - 16MB (-1), which is unclear from the spec but
+ // required.
+ //
+
+ if ( (BusNumber < HalpEpciMin) || (BusNumber > HalpEpciMax) ) {
+ //
+ // PCI bus.
+ //
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x1fffffff;
+
+ Bus->BusAddresses->Memory.SystemBase = 0xc0000000;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x1fffffff;
+ } else {
+ //
+ // EPCI bus.
+ //
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Base = 0x20000000;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x2fffffff;
+
+ Bus->BusAddresses->Memory.SystemBase = 0xc0000000;
+ Bus->BusAddresses->Memory.Base = 0x20000000;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x3effffff;
+ }
+
+ } else { // All other (NON-Doral) IBM PPC's Fall through here
+
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+
+ }
+ break;
+
+ default:
+ // EISA, ISA, PCMCIA...
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+
+ }
+ }
+
+ return Bus;
+}
+
diff --git a/private/ntos/nthals/halvict/ppc/pxcache.s b/private/ntos/nthals/halvict/ppc/pxcache.s
new file mode 100644
index 000000000..2c5630a60
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxcache.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcache.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxcalstl.c b/private/ntos/nthals/halvict/ppc/pxcalstl.c
new file mode 100644
index 000000000..3d972b02b
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxcalstl.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcalstl.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxclksup.s b/private/ntos/nthals/halvict/ppc/pxclksup.s
new file mode 100644
index 000000000..8452d5e05
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxclksup.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclksup.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxclock.c b/private/ntos/nthals/halvict/ppc/pxclock.c
new file mode 100644
index 000000000..16cb61886
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxclock.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclock.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxdat.c b/private/ntos/nthals/halvict/ppc/pxdat.c
new file mode 100644
index 000000000..978438ac0
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxdat.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxdat.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxdisp.c b/private/ntos/nthals/halvict/ppc/pxdisp.c
new file mode 100644
index 000000000..103883cc6
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxdisp.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxdisp.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxenviro.c b/private/ntos/nthals/halvict/ppc/pxenviro.c
new file mode 100644
index 000000000..0f822c840
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxenviro.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxenviro.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxfirsup.c b/private/ntos/nthals/halvict/ppc/pxfirsup.c
new file mode 100644
index 000000000..5fd3db1f2
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxfirsup.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxfirsup.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxflshbf.s b/private/ntos/nthals/halvict/ppc/pxflshbf.s
new file mode 100644
index 000000000..b2e4b591d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxflshbf.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshbf.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxflshio.c b/private/ntos/nthals/halvict/ppc/pxflshio.c
new file mode 100644
index 000000000..5817b14f5
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxflshio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshio.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxhwsup.c b/private/ntos/nthals/halvict/ppc/pxhwsup.c
new file mode 100644
index 000000000..9164059ae
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxhwsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxhwsup.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxidle.c b/private/ntos/nthals/halvict/ppc/pxidle.c
new file mode 100644
index 000000000..55114b480
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxidle.c
@@ -0,0 +1,85 @@
+/*++
+TITLE("Processor Idle")
+
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ pxidle.c
+
+abstract:
+
+ This module implements system platform dependent power management
+ support.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxmp.h"
+
+
+VOID
+HalProcessorIdle(
+ VOID
+ )
+
+/*++
+
+ Routine Description:
+
+ This function is called when the current processor is idle with
+ interrupts disabled. There is no thread active and there are no
+ DPCs to process. Therefore, power can be switched to a standby
+ mode until the the next interrupt occurs on the current processor.
+
+ N.B. This routine is entered with EE in MSR clear. This routine
+ must do any power management enabling necessary, set the EE
+ bit in MSR, then either return or wait for an interrupt.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+
+--*/
+
+{
+ //
+ // If this processor is newly IDLE, drop the MPIC TaskPriority register
+ // for this processor to 0 to make it a desirable target for interrupts.
+ //
+
+ if ( HALPCR->HardPriority ) {
+ HALPCR->MpicProcessorBase->TaskPriority = 0;
+ HALPCR->HardPriority = 0;
+ }
+
+#ifdef POWER_MANAGEMENT
+
+ if(HalpProcessorIdleEx != NULL) {
+ HalpProcessorIdleEx();
+ } else {
+ HalpProcessorIdle();
+ }
+
+#else
+
+ HalpEnableInterrupts();
+
+#endif // POWER_MANAGEMENT
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxinfo.c b/private/ntos/nthals/halvict/ppc/pxinfo.c
new file mode 100644
index 000000000..812bd48b4
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxinfo.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxinfo.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxinithl.c b/private/ntos/nthals/halvict/ppc/pxinithl.c
new file mode 100644
index 000000000..ed0de708b
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxinithl.c
@@ -0,0 +1,506 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1993-1996 International Business Machines Corporation
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+ internal DMA contoller.
+
+ Jake Oshins
+ Support Victory machines
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) 2.96
+ Unification
+
+--*/
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxmp.h"
+#include "ibmppc.h"
+
+#if _MSC_VER < 1000
+
+#define UNIQUE_PCR ((KPCR *)__builtin_get_sprg1())
+
+#else
+
+#define UNIQUE_PCR ((KPCR *)__sregister_get(273))
+
+#endif
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+
+extern VOID HalpCopyOEMFontFile();
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+VOID
+HalpConnectFixedInterrupts(
+ VOID
+ );
+
+VOID
+HalpMapMpicProcessorRegisters(
+ VOID
+ );
+
+ULONG
+HalpGetPhysicalProcessorNumber(
+ VOID
+ );
+
+IBM_SYSTEM_TYPE
+HalpSetSystemType(
+ PLOADER_PARAMETER_BLOCK
+ );
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpSetSystemType)
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+PVOID HalpIoMemoryBase = (PVOID) 0;
+
+ULONG HalpInitPhase;
+ULONG HalpPhysicalIpiMask[MAXIMUM_PROCESSORS];
+
+IBM_SYSTEM_TYPE HalpSystemType;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpInitializePciAccess (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+
+IBM_SYSTEM_TYPE
+HalpSetSystemType(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the global variable HalpSystemType according to the type
+ of system we are running on. Also sets pointers to various
+ tables accordingly.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value assigned to HalpSystemType. N.B. A value
+ of IBM_UNKNOWN indicates failure.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ UCHAR *ptr;
+
+#define SYSTEM_IS(x) \
+ (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,(x)))
+
+#define SYSTEM_ID_STARTS(x) \
+ (!strncmp(ConfigurationEntry->ComponentEntry.Identifier, \
+ (x), \
+ strlen(x)))
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ &MatchKey);
+
+ HalpSystemType = IBM_UNKNOWN;
+
+ if (ConfigurationEntry != NULL) {
+
+#if DBG
+
+ DbgPrint("HAL: System configuration = %s\n",
+ ConfigurationEntry->ComponentEntry.Identifier);
+
+#endif
+
+ if ( SYSTEM_IS(SID_IBM_TIGER) ) {
+ HalpSystemType = IBM_TIGER;
+ } else if ( SYSTEM_IS(SID_IBM_VICTORY) ) {
+ HalpSystemType = IBM_VICTORY;
+ } else if ( SYSTEM_IS(SID_IBM_DORAL) ||
+ SYSTEM_IS(SID_IBM_TERLINGUA) ||
+ SYSTEM_ID_STARTS(SID_IBM_DORAL_START) ||
+ SYSTEM_ID_STARTS(SID_IBM_TERLINGUA_START) ) {
+ HalpSystemType = IBM_DORAL;
+ } else {
+ DbgPrint("HAL: UNKNOWN SYSTEM: %s\n", ConfigurationEntry->ComponentEntry.Identifier);
+ }
+ } else {
+ DbgPrint("HAL: No SYSTEM Entry in Loader Block\n");
+ }
+ return HalpSystemType;
+
+#undef SYSTEM_IS
+}
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ ULONG ProcessorNumber;
+
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ HalpInitPhase = Phase;
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ //
+ // Get access to I/O space, check if I/O space has already been
+ // mapped by debbuger initialization.
+ //
+
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE,
+ 0x20000
+ );
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Every processor needs to determine its PHYSICAL processor
+ // number (Prcb->Number is a logical s/w concept) and record
+ // it in the PER Cpu data (HAL reserved space in the PCR).
+ //
+ // Get the physical number from the processor's PIR register
+ // (Processor Id Register).
+ //
+
+ ProcessorNumber = HalpGetPhysicalProcessorNumber();
+ HALPCR->PhysicalProcessor = ProcessorNumber;
+ HalpPhysicalIpiMask[Prcb->Number] = 1 << ProcessorNumber;
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ if ( !HalpSetSystemType(LoaderBlock) ) {
+ KeBugCheck(BAD_SYSTEM_CONFIG_INFO);
+ }
+
+ //
+ // Get access to PCI Configuration Address and Data
+ // registers.
+ //
+
+ HalpInitializePciAccess();
+
+ //
+ // Do very early planar initialization, for example,
+ // get access to the memory controller error status
+ // registers.
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#ifdef POWER_MANAGEMENT
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalSuspendHibernateSystem = HaliSuspendHibernateSystem;
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif // POWER_MANAGEMENT
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // initialize HalpPciMaxBuses (not really used YET)
+ //
+
+ HalpPhase0DiscoverPciBuses(LoaderBlock->ConfigurationRoot);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ if (!HalpInitializeDisplay(LoaderBlock)) {
+ return FALSE;
+ }
+
+ //
+ // Initialize per Machine (as opposed to per Processor)
+ // Interrupt Hardware.
+ //
+
+ if (!HalpInitializeInterrupts()) {
+ return FALSE;
+ }
+ } else {
+
+ //
+ // Processor is not 0.
+ //
+
+ HalpMapMpicProcessorRegisters();
+ HalpConnectFixedInterrupts();
+ }
+
+ //
+ // Calibrate execution stall
+ //
+
+ HalpCalibrateStall();
+
+ //
+ // return success
+ //
+
+ return TRUE;
+
+
+ } else {
+
+ if (Phase != 1)
+ return(FALSE);
+
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+
+ HalpRegisterInternalBusHandlers ();
+
+
+ if (!HalpAllocateMapBuffer()) {
+ return FALSE;
+ }
+
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+
+ if (!HalpMapIoSpace()) {
+ return FALSE;
+ }
+
+ if (!HalpCreateSioStructures()) {
+ return FALSE;
+ }
+
+ //
+ // retain the OEM Font File for later use
+ //
+
+ HalpCopyOEMFontFile();
+ HalpCopyBiosShadow();
+
+ return TRUE;
+
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Define a static structure that KeRaise/LowerIrql can use
+ // until access to the MPIC is initialized.
+ //
+ static MPIC_PER_PROCESSOR_REGS DummyMpicRegs;
+
+ //
+ // If this is the first processor to do so, initialize the cache
+ // sweeping routines depending on type of processor.
+ //
+
+ if ( Number == 0 ) {
+ if ( HalpCacheSweepSetup() ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ }
+
+ //
+ // Set HAL per processor data MpicProcessorBase pointing
+ // to the above structure. This pointer will be overwritten
+ // once access to the MPIC itself is available.
+ // Note: We don't have real access to the PCR yet.
+ //
+
+ ((PPER_PROCESSOR_DATA)&UNIQUE_PCR->HalReserved)->MpicProcessorBase = &DummyMpicRegs;
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halvict/ppc/pxintrpt.c b/private/ntos/nthals/halvict/ppc/pxintrpt.c
new file mode 100644
index 000000000..4cd20cab5
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxintrpt.c
@@ -0,0 +1,1505 @@
+/*++
+
+Copyright (c) 1996 International Business Machines Corporation
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ pxintrpt.c
+
+Abstract:
+
+ This module implements machine specific interrupt functions
+ for IBM's PowerPC Machines.
+
+ Code in this module was largely gathered from other modules
+ in earlier versions of the HAL.
+
+Author:
+
+ Peter Johnston (plj@vnet.ibm.com) Oct 1995.
+
+Environment:
+
+ Kernel mode.
+
+Revision History:
+
+ Jake Oshins
+ Made it support Victory machines
+ Chris Karamatas
+ Merged Victory/Doral/Tiger.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxfirsup.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxmp.h"
+#include "pxmpic2.h"
+#include "ibmppc.h"
+#include "pxintrpt.h"
+
+#if _MSC_VER >= 1000
+
+//
+// VC++ doesn't have the same intrinsics as MCL.
+//
+// Although the MSR is not strictly a SPR, the compiler recognizes
+// all ones (~0) as being the MSR and emits the appropriate code.
+//
+
+#define __builtin_set_msr(x) __sregister_set(_PPC_MSR_,x)
+
+#endif
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+
+extern ADDRESS_USAGE HalpMpicSpace;
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Provide prototype for Decrementer Interrupts on processors other
+// than 0.
+//
+
+BOOLEAN
+HalpHandleDecrementerInterrupt1 (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpMapMpicProcessorRegisters(
+ VOID
+ );
+
+VOID
+HalpMapMpicSpace(
+ VOID
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpConnectFixedInterrupts(
+ VOID
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpConnectFixedInterrupts)
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#pragma alloc_text(INIT,HalpMapMpicProcessorRegisters)
+#pragma alloc_text(INIT,HalpMapMpicSpace)
+#endif
+
+
+//
+// ERRATA: MPIC2 Ipi SelectProcessor registers need their addresses
+// munged.
+//
+
+ULONG Mpic2IpiBugFix;
+
+//
+// ERRATA end.
+//
+
+//
+// Define globals for the pointers to MPIC Global and Interrupt Source
+// address spaces.
+//
+
+PMPIC_GLOBAL_REGS HalpMpicGlobal;
+PMPIC_INTERRUPT_SOURCE_REGS HalpMpicInterruptSource;
+ULONG HalpMpicBasePhysicalAddress;
+ULONG HalpMpicSupportedInts;
+ULONG HalpMpicMaxVector;
+
+
+PVOID
+HalpAssignReservedVirtualSpace(
+ ULONG BasePage,
+ ULONG LengthInPages
+ );
+
+
+#if defined(SOFT_HDD_LAMP)
+
+//
+// On PowerPC machines the HDD lamp is software driven. We
+// turn it on any time we take an interrupt from a Mass Storage
+// Controller (assuming it isn't already on) and turn it off the 2nd
+// clock tick after we turn it on if we have not received
+// any more MSC interrupts since the first clock tick.
+//
+
+HDD_LAMP_STATUS HalpHddLamp;
+
+ULONG HalpMassStorageControllerVectors;
+
+#endif
+
+extern UCHAR IrqlToTaskPriority[]; // in pxirql.c
+
+//
+// Save area for ISA interrupt mask resiters and level\edge control
+// registers. (Declared in pxfirsup.c).
+//
+
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern UCHAR HalpSioInterrupt1Level;
+extern UCHAR HalpSioInterrupt2Level;
+
+
+VOID
+HalpMapMpicProcessorRegisters(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+
+ Map MPIC per-processor registers for this processor. Note
+ that although the logical processor Prcb->Number, may not be
+ the physical processor bt the same number. We must map the
+ registers appropriate to this physical processor.
+ Also, the VA of this space will only ever be used by THIS
+ processor so we will use HAL reserved space rather than an
+ address assigned by MmMapIoSpace, the only reason for this
+ is to save the system a page per processor (not a big deal).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerProcessorRegs;
+ ULONG i;
+ PerProcessorRegs = HalpMpicBasePhysicalAddress + MPIC_PROCESSOR_0_OFFSET +
+ (HALPCR->PhysicalProcessor * MPIC_PROCESSOR_REGS_SIZE);
+
+ HALPCR->MpicProcessorBase = HalpAssignReservedVirtualSpace(
+ PerProcessorRegs >> PAGE_SHIFT,
+ 1);
+
+ if ( !HALPCR->MpicProcessorBase ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set priority for this processor to mask ALL interrupts.
+ //
+
+ HALPCR->MpicProcessorBase->TaskPriority = MPIC_MAX_PRIORITY;
+ HALPCR->HardPriority = MPIC_MAX_PRIORITY;
+ HALPCR->PendingInterrupts = 0;
+ MPIC_SYNC();
+
+ //
+ // Reading the Acknowledge register now would give us the spurious
+ // vector,... but,... clear the In-Service Register just in case
+ // there's something still in it. This is done by writing to the
+ // EOI register.
+ //
+ // There could potentially be one in service interrupt for each
+ // level the MPIC supports, so do it that many times.
+ //
+
+ for ( i = 0 ; i < MPIC_SUPPORTED_IPI ; i++ ) {
+ HALPCR->MpicProcessorBase->EndOfInterrupt = 0;
+ MPIC_SYNC();
+ }
+}
+
+
+VOID
+HalpMapMpicSpace(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Locate and map the MPIC 2 (or 2A) controller. Initialize
+ all interrupts disabled.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG MpicBasePhysicalAddress = 0;
+ ULONG DeviceVendor;
+ ULONG i;
+ ULONG SlotNumber;
+ MPIC_ISVP InterruptSource;
+ MPIC_IPIVP IpiSource;
+
+ //
+ // Find the MPIC controller.
+ // This should probably be passed in in the h/w config, but
+ // neither the configuration nor the PCI bus have been initialized
+ // yet. So, search for it using Phase 0 routines.
+ //
+
+ for ( SlotNumber = 0; SlotNumber < 32 ; SlotNumber++ ) {
+ HalpPhase0GetPciDataByOffset(
+ 0,
+ SlotNumber,
+ &DeviceVendor,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
+ sizeof(DeviceVendor)
+ );
+ if ( (DeviceVendor == MPIC2_PCI_VENDOR_DEVICE) ||
+ (DeviceVendor == MPIC2A_PCI_VENDOR_DEVICE) ||
+ (DeviceVendor == HYDRA_PCI_VENDOR_DEVICE ) ) {
+ HalpPhase0GetPciDataByOffset(
+ 0,
+ SlotNumber,
+ &MpicBasePhysicalAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[0]),
+ sizeof(MpicBasePhysicalAddress)
+ );
+ break;
+ }
+ }
+
+
+ //
+ // Assert that (a) we found it, and (b) if MPIC2, its I/O space
+ // really is I/O space, or, if MPIC2A, its I/O space is PCI
+ // memory space.
+ //
+
+ if ( !MpicBasePhysicalAddress) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ // Default to standard MPIC
+ HalpMpicSupportedInts = MPIC_SUPPORTED_INTS;
+
+ switch ( DeviceVendor ) {
+
+ case MPIC2_PCI_VENDOR_DEVICE:
+ if ( !(MpicBasePhysicalAddress & 0x1) ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ MpicBasePhysicalAddress |= 0x80000000;
+
+ //
+ // ERRATA: MPIC2 bug, the IPI SelectProcessor registers need to be
+ // munged.
+ //
+
+ Mpic2IpiBugFix = 0x2;
+
+ //
+ // ERRATA end.
+ //
+ break;
+
+ case HYDRA_PCI_VENDOR_DEVICE:
+ //
+ // For Tiger: MPIC is within Hydra, so we add 0x40000 to Hydra Base to
+ // reach MPIC space - IBMCPK
+ //
+ MpicBasePhysicalAddress += 0x40000;
+
+ HalpMpicSupportedInts = HYDRA_MPIC_SUPPORTED_INTS;
+
+ // Fall thru.
+
+ case MPIC2A_PCI_VENDOR_DEVICE:
+ if ( MpicBasePhysicalAddress & 0x1 ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ MpicBasePhysicalAddress |= 0xc0000000;
+ break;
+
+ default:
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Remove lower 2 bits, (I/O space indicator and "reserved").
+ //
+
+ MpicBasePhysicalAddress &= ~0x3;
+
+ HalpMpicBasePhysicalAddress = MpicBasePhysicalAddress;
+
+ //
+ // Map MPIC Global Registers and Interrupt Source Configuration
+ // registers.
+
+ HalpMpicGlobal = HalpAssignReservedVirtualSpace(
+ (MpicBasePhysicalAddress + MPIC_GLOBAL_OFFSET) >> PAGE_SHIFT,
+ 1);
+ if ( !HalpMpicGlobal ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ HalpMpicInterruptSource = HalpAssignReservedVirtualSpace(
+ (MpicBasePhysicalAddress + MPIC_INTERRUPT_SOURCE_OFFSET) >> PAGE_SHIFT,
+ 1);
+
+ if ( !HalpMpicInterruptSource ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ HalpMpicGlobal->Configuration.Mode = MPIC_MIXED_MODE;
+
+ if ( DeviceVendor == HYDRA_PCI_VENDOR_DEVICE ) {
+ //
+ // Set Hydra Feature Register bit MpicIsMaster (bit 8).
+ //
+
+ PVOID HydraBase = HalpAssignReservedVirtualSpace(
+ (MpicBasePhysicalAddress - 0x40000) >> PAGE_SHIFT,
+ 1);
+ PULONG HydraFeatureRegister = (PULONG)((ULONG)HydraBase + 0x38);
+ if ( !HydraBase ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ *HydraFeatureRegister |= 0x100;
+
+ HalpReleaseReservedVirtualSpace(HydraBase, 1);
+ }
+
+ //
+ // Disable all interrupt sources.
+ //
+
+ *(PULONG)&InterruptSource = 0;
+
+ InterruptSource.Priority = 0;
+ InterruptSource.Sense = 1;
+ InterruptSource.Polarity = 0;
+
+ for ( i = 0 ; i < HalpMpicSupportedInts ; i++ ) {
+ InterruptSource.Vector = i + MPIC_BASE_VECTOR;
+ MPIC_WAIT_SOURCE(i);
+ HalpMpicInterruptSource->Int[i].VectorPriority = InterruptSource;
+ MPIC_WAIT_SOURCE(i);
+ HalpMpicInterruptSource->Int[i].SelectProcessor = 0;
+ }
+
+ MPIC_SYNC();
+
+ //
+ // Set source 0 (the 8259) to Active High, Level Triggered.
+ //
+
+ MPIC_WAIT_SOURCE(0);
+ HalpMpicInterruptSource->Int[0].VectorPriority.Polarity = 1;
+ MPIC_SYNC();
+
+
+ //
+ // Set IPI Vector/Priority. 0 is the only one we really
+ // use. However, we set 3 to the MAX and NMI so we can
+ // use it to wake the dead when debugging (maybe).
+ //
+ // Set IPI 0 to overload vector 30 which is one of the reserved
+ // vectors on DORAL.
+ // Set IPI 1 & 2 to do nothing.
+ // Set IPI 3 to overload vector 29 which is reserved on DORAL. ALSO,
+ // set IPI 3 NMI. (Priority is irrelevant).
+ //
+
+ *(PULONG)&IpiSource = 0;
+
+ IpiSource.Vector = MPIC_IPI0_VECTOR;
+ IpiSource.Priority = 14;
+ MPIC_WAIT_IPI_SOURCE(0);
+ HalpMpicGlobal->Ipi[0].VectorPriority = IpiSource;
+
+ IpiSource.Vector = MPIC_IPI1_VECTOR;
+ IpiSource.Priority = 0;
+ MPIC_WAIT_IPI_SOURCE(1);
+ HalpMpicGlobal->Ipi[1].VectorPriority = IpiSource;
+
+ IpiSource.Vector = MPIC_IPI2_VECTOR;
+ MPIC_WAIT_IPI_SOURCE(2);
+ HalpMpicGlobal->Ipi[2].VectorPriority = IpiSource;
+
+ IpiSource.Vector = MPIC_IPI3_VECTOR;
+ IpiSource.NMI = 1;
+ MPIC_WAIT_IPI_SOURCE(3);
+ HalpMpicGlobal->Ipi[3].VectorPriority = IpiSource;
+ MPIC_SYNC();
+
+ //
+ // Initialize per processor registers for this processor.
+ //
+
+ HalpMapMpicProcessorRegisters();
+
+ //
+ // Register this I/O space as in-use.
+ //
+
+ MpicBasePhysicalAddress &= 0x7FFFFFFF; // Get bus-relative address
+
+ // Length can only be a USHORT, so we do this four times
+ HalpMpicSpace.Element[0].Start = MpicBasePhysicalAddress;
+ HalpMpicSpace.Element[0].Length = 0xFFFF;
+ HalpMpicSpace.Element[1].Start = MpicBasePhysicalAddress + 0x10000;
+ HalpMpicSpace.Element[1].Length = 0xFFFF;
+ HalpMpicSpace.Element[2].Start = MpicBasePhysicalAddress + 0x20000;
+ HalpMpicSpace.Element[2].Length = 0xFFFF;
+ HalpMpicSpace.Element[3].Start = MpicBasePhysicalAddress + 0x30000;
+ HalpMpicSpace.Element[3].Length = 0xFFFF;
+
+ switch ( DeviceVendor ) {
+ case MPIC2_PCI_VENDOR_DEVICE:
+
+ HalpMpicSpace.Type = CmResourceTypePort;
+ break;
+
+ case HYDRA_PCI_VENDOR_DEVICE:
+ case MPIC2A_PCI_VENDOR_DEVICE:
+
+ HalpMpicSpace.Type = CmResourceTypeMemory;
+ break;
+ }
+
+ HalpRegisterAddressUsage(&HalpMpicSpace);
+}
+
+
+VOID
+HalpConnectFixedInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Set required interrupt vectors in the PCR, called once on each
+ processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Connect the machine check handler
+ //
+
+ PCR->InterruptRoutine[MACHINE_CHECK_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleMachineCheck;
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+
+ //
+ // Connect directly to the decrementer handler. Processor 0 uses
+ // HalpHandleDecrementerInterrupt, other processors use
+ // HalpHandleDecrementerInterrupt1.
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt1;
+
+ //
+ // Connect the Inter-Processor Interrupt (IPI) handler.
+ //
+
+ PCR->InterruptRoutine[MPIC_IPI0_VECTOR + DEVICE_VECTORS] =
+ (PKINTERRUPT_ROUTINE)HalpHandleIpi;
+
+ //
+ // Connect the Profile interrupt (Timer 1 IRQ0) handler.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] =
+ (PKINTERRUPT_ROUTINE)HalpHandleProfileInterrupt;
+
+ //
+ // Enable the clock interrupt
+ //
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+}
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine in entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ USHORT Vector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ ULONG TaskPriority;
+
+ //
+ // Read the MPIC interrupt vector.
+ //
+
+ Vector = (USHORT)(HALPCR->MpicProcessorBase->Acknowledge & 0xff);
+
+ //
+ // Check for cancelled (spurious) interrupts.
+ //
+
+ if ( Vector == 0xff ) {
+ return 0;
+ }
+
+ //
+ // Check for 8259 interrupt.
+ //
+
+ if ( Vector == MPIC_8259_VECTOR ) {
+
+ //
+ // Read the 8259 interrupt vector.
+ //
+
+ Vector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // Acknowledge this interrupt immediately in the MPIC2
+ // controller so higher priority 8259 interrupts can be
+ // delivered.
+ //
+
+ HALPCR->MpicProcessorBase->EndOfInterrupt = 0;
+
+ //
+ // Check for NMI interrupt before we raise irql since we would
+ // raise to a bogus level.
+ //
+
+ if (Vector == 0xFF) {
+
+ HalpHandleMachineCheck(NULL, NULL);
+ }
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (Vector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+ return 0;
+ }
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ } else if ( HalpMassStorageControllerVectors & ( 1 << Vector) ) {
+ //
+ // On any Mass Storage Controller interrupt, light the HDD lamp.
+ // The system timer routines will turn it off again in a little
+ // while.
+ //
+
+ if ( !HalpHddLamp.Count ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1;
+ }
+ HalpHddLamp.Count = 10;
+
+#endif
+
+ }
+
+ //
+ // Raise IRQL - We rely on the MPIC and 8259 controllers to
+ // hold off any lower or equal priority interrupts. Therefore
+ // all we need do is update the PCRs notion of IRQL and re
+ // enable interrupts.
+ //
+
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = HalpVectorToIrql[Vector];
+ HalpEnableInterrupts();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + Vector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Clear the interrupt in the appropriate controller. To
+ // avoid the possibility of being drowned with interrupts
+ // at this level, disable interrupts first (we need to
+ // return to our caller with interrupts disabled anyway).
+ //
+
+ HalpDisableInterrupts();
+
+ if ( Vector < MPIC_8259_VECTOR ) {
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must
+ // be dismissed in both controllers.
+ //
+
+ if (Vector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+
+ } else {
+
+ HALPCR->MpicProcessorBase->EndOfInterrupt = 0;
+ }
+
+ //
+ // Lower IRQL without enabling external interrupts. It is
+ // possible that Irql was raised above this level and lowered
+ // back to this level in the mean time. If so, the TaskPriority
+ // will have been adjusted and we need to adjust it downwards.
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ TaskPriority = IrqlToTaskPriority[OldIrql];
+
+ if ( TaskPriority < HALPCR->HardPriority ) {
+ HALPCR->MpicProcessorBase->TaskPriority = TaskPriority;
+ HALPCR->HardPriority = TaskPriority;
+ }
+
+ return returnValue;
+}
+
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEnableMpicInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the MPIC interrupt at the source.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MPIC_ISVP VectorPriority;
+
+ //
+ // Calculate the MPIC source.
+ //
+
+ ULONG Source = Vector - (DEVICE_VECTORS + MPIC_BASE_VECTOR);
+
+ MPIC_WAIT_SOURCE(Source);
+
+ VectorPriority = HalpMpicInterruptSource->Int[Source].VectorPriority;
+
+ if (Source == 0) { // special 8259 case
+ VectorPriority.Priority = 2;
+ } else if (Source < MPIC_SUPPORTED_INTS) {
+ VectorPriority.Priority = (Source / 2) + 3;
+ } else {
+ // Extra hydra poles get the same (highest) priority
+ VectorPriority.Priority = 10;
+ }
+ HalpMpicInterruptSource->Int[Source].VectorPriority = VectorPriority;
+
+
+ MPIC_WAIT_SOURCE(Source);
+
+ HalpMpicInterruptSource->Int[Source].SelectProcessor =
+ 1 << HALPCR->PhysicalProcessor;
+}
+
+VOID
+HalpDisableMpicInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MPIC_ISVP VectorPriority;
+ //
+ // Calculate the MPIC source.
+ //
+
+ ULONG Source = Vector - (DEVICE_VECTORS + MPIC_BASE_VECTOR);
+
+ MPIC_WAIT_SOURCE(Source);
+
+ VectorPriority = HalpMpicInterruptSource->Int[Source].VectorPriority;
+ VectorPriority.Priority = 0;
+ HalpMpicInterruptSource->Int[Source].VectorPriority = VectorPriority;
+
+ if (HalpSystemType == IBM_DORAL) {
+
+ MPIC_WAIT_SOURCE(Source);
+
+ HalpMpicInterruptSource->Int[Source].SelectProcessor = 0;
+
+ }
+}
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG Vector;
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Map MPIC space and mask interrupts.
+ //
+
+ HalpMapMpicSpace();
+
+ //
+ // Set appropriate Interrupt Vector to Irql mapping for this
+ // machine.
+ //
+
+ HalpMpicMaxVector = MPIC_BASE_VECTOR + DEVICE_VECTORS +
+ HalpMpicSupportedInts - 1;
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+KINTERRUPT_MODE
+HalpGetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ Force interrupt mode for (machine specific) interrupt vectors.
+ If the vector is not one of those hardwired, return the caller's
+ requested mode.
+
+ On Doral, all ISA style interrupts (8259) except 13 (Power
+ Management) are edge sensitive. 13 is level sensitive.
+
+Arguments:
+
+ Vector - Vector for which translation is being requested.
+ Irql - Not used.
+ InterruptMode - Requested mode.
+
+Return Value:
+
+ Interrupt mode for this vector.
+
+--*/
+
+
+{
+ if ((HalpSystemType == IBM_TIGER) &&
+ (Vector == DEVICE_VECTORS + 15)) {
+ return LevelSensitive;
+ } else if ( Vector == (DEVICE_VECTORS + 13) ) {
+ return LevelSensitive;
+ } else {
+ return Latched;
+ }
+}
+
+VOID
+HalpSetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ Correct the interrupt mode for a given vector. This is a no-op
+ as the correct interrupt mode was assigned in HalpGetInterruptMode.
+
+Arguments:
+
+ Vector - Vector to correct. (Not used).
+ Irql - Not used.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ *Affinity = 1;
+
+ //
+ // Set the IRQL level. Map the interrupt controllers priority scheme to
+ // NT irql values. The SIO prioritizes irq's as follows:
+ //
+ // irq0, irq1, irq8, irq9 ... irq15, irq3, irq4 ... irq7.
+ //
+ // The MPIC is a straight mapping.
+ //
+
+ *Irql = HalpVectorToIrql[BusInterruptLevel];
+
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+}
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if (Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ HalpDisableSioInterrupt(Vector);
+
+ } else if ( Vector <= HalpMpicMaxVector ) {
+
+ HalpDisableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if ( Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ //
+ // It's an 8259 vector.
+ //
+ // Get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector,
+ Irql,
+ InterruptMode);
+
+
+ HalpEnableSioInterrupt(Vector, TranslatedInterruptMode);
+
+ } else if ( Vector <= HalpMpicMaxVector ) {
+
+ HalpEnableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ extern ULONG Mpic2IpiBugFix;
+ extern ULONG HalpPhysicalIpiMask[];
+ ULONG BugFix = Mpic2IpiBugFix;
+ ULONG PhysicalMask = 0;
+ PULONG PhysicalIpiMask = HalpPhysicalIpiMask;
+ ULONG OldMsr = __builtin_get_msr();
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ __builtin_set_msr(OldMsr & 0xffff7fff); // Disable Interrupts
+
+ //
+ // Mask is a mask of logical CPUs. Convert it to a mask of
+ // Physical CPUs so the IPI requests will be distributed
+ // properly.
+ //
+
+ do {
+ if ( Mask & 1 ) {
+ PhysicalMask |= *PhysicalIpiMask;
+ }
+ PhysicalIpiMask++;
+ Mask >>= 1;
+ } while ( Mask );
+
+ //
+ // Send the IPI interrupt(s).
+ //
+
+ HALPCR->MpicProcessorBase->Ipi[0 ^ BugFix].SelectProcessor = PhysicalMask;
+
+ __builtin_set_msr(OldMsr); // Restore previous interrupt
+ // setting.
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an Inter-Processor Interrupt
+ being received by this processor. It passes the request onto the
+ kernel.
+
+Arguments:
+
+ Unused0 - Not used.
+ Unused1 - Not used.
+ TrapFrame - Volatile context at time interrupt occured.
+
+Return Value:
+
+ Returns TRUE (this routine always succeeds).
+
+--*/
+
+{
+ KeIpiInterrupt(TrapFrame);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxintrpt.h b/private/ntos/nthals/halvict/ppc/pxintrpt.h
new file mode 100644
index 000000000..e75201f14
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxintrpt.h
@@ -0,0 +1,103 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ vectirql.h
+
+Abstract:
+
+ This module implements machine specific interrupt functions
+ for IBM's PowerPC Machines.
+
+ Code in this module was largely gathered from other modules
+ in earlier versions of the HAL.
+
+Author:
+
+ Chris Karamatas - Collected VectorToIrql Tables into one file.
+
+Environment:
+
+ Kernel mode.
+
+Revision History:
+
+
+--*/
+
+
+//
+// The following table maps Interrupt Vectors to the appropriate
+// IRQL. The MPIC is initialized to assign vectors 16 thru 31
+// to its sources 0 thru 15. The 8259 gives us vectors 0 thru 15.
+//
+// It is possible that we are actually dealing with a Hydra, which
+// is an MPIC with sources 0 through 19, so we have extra entries
+// in the table.
+//
+// The MPIC is also programmed with priority in ascending order by
+// vector (and source).
+//
+// This table should reflect the real mapping of vector to device
+// priority. This implementation assumes that all MPIC sources
+// are at a higher priority than 8259 sources.
+//
+
+UCHAR HalpVectorToIrql[40] = {
+
+ // 8259 Master, Priority 1 - 2
+
+ 18, // 0 Timer 1 Counter 0
+ 17, // 1 Keyboard
+ 16, // 2 Cascade (not translated)
+
+ 7, // 3 Com 2
+ 6, // 4 Com 1
+ 5, // 5 Audio
+ 4, // 6 Floppy
+ 3, // 7 Parallel Port
+
+ // 8259 Slave, Priority 3-10
+
+ 15, // 8 RTC
+ 14, // 9 Audio (MIDI), ISA Slots pin B04
+ 13, // 10 ISA Slots pin D03
+ 12, // 11 ISA Slots pin D04
+ 11, // 12 Mouse, ISA Slots pin D05
+ 10, // 13 Power Management Interrupt
+ 9, // 14 ISA Slots pin D07
+ 8, // 15 ISA Slots pin D06
+
+ // MPIC Sources - The following values are chosen arbitarily. Support
+ // should be added to reprogram the MPIC and this table
+ // once the device configuration is known.
+
+ 0, // 0 8259 interrupt, will get from above
+ 19, // 1
+ 20, // 2
+ 20, // 3
+ 21, // 4
+ 21, // 5
+ 22, // 6
+ 22, // 7
+ 23, // 8
+ 23, // 9
+ 24, // 10
+ 24, // 11
+ 25, // 12
+ 25, // 13
+ 26, // 14
+ 26, // 15
+ 26, // 16 Possible Hydra interrupt source
+ 26, // 17 Hydra
+ 26, // 18 Hydra
+ 26, // 19 Hydra
+ IPI_LEVEL, // 36 Reserved, PLUS IPI[0]
+ IPI_LEVEL, // 37 Reserved, PLUS IPI[1]
+ IPI_LEVEL, // 38 Reserved, PLUS IPI[2]
+ IPI_LEVEL, // 39 Reserved, PLUS IPI[3]
+};
+
diff --git a/private/ntos/nthals/halvict/ppc/pxirql.c b/private/ntos/nthals/halvict/ppc/pxirql.c
new file mode 100644
index 000000000..de9a694e0
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxirql.c
@@ -0,0 +1,337 @@
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright (c) 1995 International Business Machines Corporation
+//
+// Module Name:
+//
+// PXIRQL.C
+//
+// Abstract:
+//
+// This module implements the code necessary to lower and raise the current
+// Interrupt Request Level (IRQL).
+//
+//
+// Author:
+//
+// Jim Wooldridge (IBM)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Peter L Johnston (plj@vnet.ibm.com) August 1995.
+// Rewrote for Lazy IRQL based on MPIC2.
+//
+// Jake Oshins (joshins@vnet.ibm.com)
+// Support Victory machines
+//
+//--
+
+#include "halp.h"
+#include "pxmp.h"
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern BOOLEAN HalpProfilingActive;
+
+#if 0
+//
+// The following is not used with Lazy IRQL/MPIC2 but the informationed
+// contained herein is useful.
+//
+// VICTORY 8259 Interrupt assignments.
+//
+// IRQ Mask Device
+//
+// 0 0001 Timer 1 Counter 0
+// 1 0002 Keyboard
+// 2 0004 2nd 8259 Cascade
+// 3 0008 Serial Port 2, EISA IRQ3
+// 4 0010 Serial Port 1, EISA IRQ4
+// 5 0020 EISA IRQ5
+// 6 0040 Floppy Disk
+// 7 0080 Parallel Port, ISA Slots pin B21
+// 8 0100 Real Time Clock
+// 9 0200 EISA IRQ9
+// 10 0400 EISA IRQ10
+// 11 0800 EISA IRQ11
+// 12 1000 Mouse
+// 13 2000 Power Management Interrupt (also SCSI)
+// 14 4000 EISA IRQ14 (Mini-SP)
+// 15 8000 EISA IRQ15
+//
+// DORAL 8259 Interrupt assignments.
+//
+// IRQ Mask Device
+//
+// 0 0001 Timer 1 Counter 0
+// 1 0002 Keyboard
+// 2 0004 2nd 8259 Cascade
+// 3 0008 Serial Port 2, ISA Slots pin B25
+// 4 0010 Serial Port 1, ISA Slots pin B24
+// 5 0020 Audio, ISA Slots pin B23
+// 6 0040 Floppy Disk
+// 7 0080 Parallel Port, ISA Slots pin B21
+// 8 0100 Real Time Clock
+// 9 0200 Audio (MIDI), ISA Slots pin B04
+// 10 0400 ISA Slots pin D03
+// 11 0800 ISA Slots pin D04
+// 12 1000 Mouse, ISA Slots pin D05
+// 13 2000 Power Management Interrupt
+// 14 4000 ISA Slots pin D07
+// 15 8000 ISA Slots pin D06
+//
+//
+// Victory MPIC2 IRQ assignments:
+// Level Source
+// 0 EISA 8259 Cascade
+// 1 On-board SCSI
+// 2 PCI Slot 1 A&C
+// 3 PCI Slot 1 B&D
+// 4 PCI Slot 2 A&C
+// 5 PCI Slot 2 B&D
+// 6 PCI Slot 3 A&C // this slot doesn't exist on some machines
+// 7 PCI Slot 3 B&D
+// 8 PCI Slot 4 A&C // beginning of secondary PCI bus
+// 9 PCI Slot 4 B&D
+// 10 PCI Slot 5 A&C
+// 11 PCI Slot 5 B&D
+// 12 PCI Slot 6 A&C
+// 13 PCI Slot 6 B&D
+// 14 PCI Slot 7 A&C
+// 15 PCI Slot 7 B&D
+
+//
+// Initialize the 8259 irql mask table.
+//
+
+USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level
+ 0x0000, // irql1 APC
+ 0x0000, // irql2 Dispatch
+ 0x0080, // irql3 parallel
+ 0x00c0, // irql4 floppy
+ 0x00e0, // irql5 audio
+ 0x00f0, // irql6 com 1
+ 0x00f8, // irql7 com 2
+ 0x80f8, // irql8 isa pin D06
+ 0xc0f8, // irql9 isa pin D07
+ 0xe0f8, // irql10 pow
+ 0xf0f8, // irql11 mouse, isa pin D05
+ 0xf8f8, // irql12 isa pin D04
+ 0xfcf8, // irql13 isa pin D03
+ 0xfef8, // irql14 audio (MIDI), isa B04
+ 0xfff8, // irql15 rtc
+ 0xfff8, // irql16 cascade
+ 0xfffa, // irql17 kb
+ 0xfffb, // irql18 timer 1/ profile
+ 0xffff, // irql19 clock level
+ 0xffff, // irql20
+ 0xffff, // irql21
+ 0xffff, // irql22
+ 0xffff, // irql23
+ 0xffff, // irql24
+ 0xffff, // irql25
+ 0xffff, // irql26
+ 0xffff, // irql27
+ 0xffff, // irql28
+ 0xffff, // irql29 IPI Level
+ 0xffff, // irql30
+ 0xffff // irql31 High level
+ };
+#endif
+
+//
+// Map IRQL to MPIC2 TaskPriority. We are somewhat lazy here in that
+// all 8259 interrupts are considered to be at the same level. This
+// is so we can avoid setting the 8259 mask registers for the majority
+// of Raise/Lower Irqls.
+//
+
+UCHAR IrqlToTaskPriority[32] = {
+
+ // User, APC and DISPATCH level all get TaskPriority of 1.
+ // (TaskPriority of 0 is for the IDLE loop).
+
+ 1, // 0
+ 1, // 1
+ 1, // 2
+
+ // 8259 - mask source 0 (at priority 2) in the MPIC
+
+ 2, // 3 - 18
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+
+ // MPIC source 1 (priority 3)
+
+ // Spread this across the Victory
+ // PCI slots, with emphasis on the
+ // secondary PCI bus.
+ 3, // 19
+ 4, // 20
+ 5, // 21
+ 6, // 22
+ 7, // 23
+ 8, // 24
+ 9, // 25
+ 10, // 26
+
+ // The following, except HIGH_LEVEL aren't used by Victory.
+ // Doral needs them.
+
+ 11, // 27
+ 12, // 28 DECREMENTER_LEVEL
+ 14, // 29 IPI_LEVEL
+
+ // MPIC source 15, Power Fail.
+
+ 15, // 30 POWER_LEVEL
+ 15 // 31 HIGH_LEVEL
+};
+
+
+
+
+VOID
+KiDispatchSoftwareInterrupt(
+ VOID
+ );
+
+
+VOID
+KeLowerIrql(
+ KIRQL NewIrql
+ )
+
+//++
+//
+// VOID
+// KeLowerIrql (
+// KIRQL NewIrql
+// )
+//
+// Routine Description:
+//
+// This function lowers the current IRQL to the specified value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+{
+ KIRQL OldIrql;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask;
+
+
+ OldIrql = PCR->CurrentIrql;
+
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (OldIrql > DISPATCH_LEVEL) {
+
+ ULONG TaskPriority = IrqlToTaskPriority[NewIrql];
+
+ HalpDisableInterrupts();
+ HALPCR->MpicProcessorBase->TaskPriority = TaskPriority;
+ PCR->CurrentIrql = NewIrql;
+ HALPCR->HardPriority = TaskPriority;
+
+ if ( NewIrql <= IPI_LEVEL ) {
+
+ HalpEnableInterrupts();
+ }
+ } else {
+ PCR->CurrentIrql = NewIrql;
+ }
+
+ //
+ // check for DPC's
+ //
+
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt) {
+ KiDispatchSoftwareInterrupt();
+ }
+}
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql (
+// KIRQL NewIrql,
+// PKIRQL OldIrql
+// )
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that recieves the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+
+{
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (NewIrql > DISPATCH_LEVEL) {
+
+ ULONG TaskPriority = IrqlToTaskPriority[NewIrql];
+
+ HalpDisableInterrupts();
+
+ HALPCR->MpicProcessorBase->TaskPriority = TaskPriority;
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ HALPCR->HardPriority = TaskPriority;
+
+ if ( NewIrql <= IPI_LEVEL ) {
+
+ HalpEnableInterrupts();
+ }
+ } else {
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ }
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxisabus.c b/private/ntos/nthals/halvict/ppc/pxisabus.c
new file mode 100644
index 000000000..a38788df8
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxisabus.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxisabus.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxmapio.c b/private/ntos/nthals/halvict/ppc/pxmapio.c
new file mode 100644
index 000000000..38b6ef09e
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmapio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxmapio.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxmemctl.c b/private/ntos/nthals/halvict/ppc/pxmemctl.c
new file mode 100644
index 000000000..b3ada428d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmemctl.c
@@ -0,0 +1,706 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ Jake Oshins (joshins@vnet.ibm.com)
+ Support newer Victory machines, (Lightning-2, Thunderbolt)
+ Peter L Johnston (plj@vnet.ibm.com) Handle UNION (aka Doral/Terlingua)
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxdakota.h"
+#include "pci.h"
+#include "pcip.h"
+// #include "pxmp.h"
+#include "ibmppc.h"
+
+#define BYTE_SWAP(x) ((((x) & 0x000000ff) << 24) | \
+ (((x) & 0x0000ff00) << 8 ) | \
+ (((x) & 0x00ff0000) >> 8 ) | \
+ (((x) & 0xff000000) >> 24))
+
+//
+// Device ID/Vendor ID for IBM PCI Host Bridge (in UNION).
+//
+
+#define IBMUNIONPCIBRIDGE 0x003a1014
+
+//
+// Prototype routines to be discarded at end of phase 1.
+//
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitPlanar)
+#pragma alloc_text(INIT,HalpMapPlanarSpace)
+#pragma alloc_text(INIT,HalpMapBusConfigSpace)
+#pragma alloc_text(INIT,HalpPhase0MapBusConfigSpace)
+#pragma alloc_text(INIT,HalpPhase0UnMapBusConfigSpace)
+#endif
+
+
+//
+// Virtual address of UNION System Control Registers (page).
+//
+
+PVOID HalpUnionControlRegs;
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+
+ ULONG pcidata;
+ static Pass = 0;
+
+ if ( Pass++ == 0 ) {
+ //
+ // This would be an error,...
+ //
+ return TRUE;
+ }
+
+ switch (HalpSystemType) {
+ case IBM_VICTORY:
+
+ // Write NMI status and control register NMISC
+ WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x61, 0x04);
+
+ // Write Mode select register PCI-Eisa bridge
+ WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x22, 0x40);
+ WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x23, 0x40);
+
+
+ // Set it so that the memory controller (montana/nevada
+ // will not cause a machine check when he is the initiator
+ // of a transaction when a pci parity error takes place
+ // won't cause a machine check. A server should probably
+ // do things like parity checking
+ // on the PCI bus, but there are lots of broken adapters
+ // out there that don't generate PCI bus parity.
+
+ // Read Montana Enable detection register (and surrounding bytes)
+
+ HalpPhase0GetPciDataByOffset(0, // primary PCI bus
+ 0, // location of Montana/Nevada
+ &pcidata,
+ 0xc0,
+ 4);
+
+ pcidata &= ~(1 << 5);
+
+ // Now write back Montana Enable detection register
+
+ HalpPhase0SetPciDataByOffset(0, // primary PCI bus
+ 0, // location of Montana/Nevada
+ &pcidata,
+ 0xc0,
+ 4);
+ break;
+ case IBM_DORAL:
+ HalpUnionControlRegs = HalpAssignReservedVirtualSpace(
+ UNION_SYSTEM_CONTROL_REG_BASE >> PAGE_SHIFT,
+ 1);
+ //
+ // If the above failed, there's nothing we can do about it now
+ // anyway.
+ //
+ break;
+ case IBM_TIGER:
+ //
+ // CPK? What goes here?
+ //
+ break;
+ }
+ return TRUE;
+}
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge register for the 8259.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map 8259 interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ switch (HalpSystemType) {
+ case IBM_DORAL:
+ physicalAddress.LowPart = UNION_INTERRUPT_PHYSICAL_BASE;
+ break;
+ case IBM_VICTORY:
+ case IBM_TIGER:
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ break;
+ }
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ return TRUE;
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Access to the PCI Configuration and Data registers has already been
+ obtained. This routine does nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Access to the PCI Configuration and Data registers has already been
+ obtained. This routine does nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Return the space mapped above. Except we didn't actually map
+ anything above, so do nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+VOID
+HalpDisplayRegister(
+ PUCHAR RegHex,
+ ULONG Bytes
+ )
+
+/*++
+
+Routine Description:
+
+ Displays (via HalDisplayString) a new-line terminated
+ string of hex digits representing the input value. The
+ input value is pointed to by the first argument is
+ from 1 to 4 bytes in length.
+
+Arguments:
+
+ RegHex Pointer to the value to be displayed.
+ Bytes Length of input value in bytes (1-4).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#define DISP_MAX 4
+
+ UCHAR RegString[(DISP_MAX * 2) + 2];
+ UCHAR Num, High, Low;
+ PUCHAR Byte = &RegString[(DISP_MAX * 2) + 1];
+
+ *Byte = '\0';
+ *--Byte = '\n';
+
+ if ( (unsigned)Bytes > DISP_MAX ) {
+ Bytes = DISP_MAX;
+ }
+
+ while (Bytes--) {
+ Num = *RegHex++;
+ High = (Num >> 4) + '0';
+ Low = (Num & 0xf) + '0';
+ if ( High > '9' ) {
+ High += ('A' - '0' - 0xA);
+ }
+ if ( Low > '9' ) {
+ Low += ('A' - '0' - 0xA);
+ }
+ *--Byte = Low;
+ *--Byte = High;
+ }
+ HalDisplayString(Byte);
+}
+
+VOID
+HalpHandleVictoryMemoryError(
+ VOID
+ )
+{
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+
+ //
+ // Read the error address register first
+ //
+
+
+ ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister);
+
+ //
+ // Check TEA conditions
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->MemoryParityErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString("TEA: Memory Parity Error at Address ");
+ HalpDisplayRegister((PUCHAR)&ErrorAddress, sizeof(ErrorAddress));
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->L2CacheErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: L2 Cache Parity Error\n");
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->TransferErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: Transfer Error at Address ");
+ HalpDisplayRegister((PUCHAR)&ErrorAddress, sizeof(ErrorAddress));
+ }
+}
+
+VOID
+HalpHandleTigerMemoryError(
+ VOID
+ )
+{
+ // CPK: Your turn. (plj).
+}
+
+VOID
+HalpHandleDoralMemoryError(
+ VOID
+ )
+
+{
+ static ULONG RecursionLevel = 0;
+ ULONG Status;
+ ULONG Address;
+ ULONG PciCsr0;
+ ULONG PciCsr1;
+ ULONG PciPlssr0;
+ ULONG PciPlssr1;
+ ULONG MemErrorStatus;
+ ULONG MemErrorAddress;
+ ULONG OldPciConfigAddress;
+ ULONG HostBridgePciAddress = 0x80000000;
+ ULONG PciConfigData;
+ ULONG PciBridgeFound = 0;
+ UCHAR Syndrome = 0;
+ PCHAR PciBusString;
+ extern KSPIN_LOCK HalpPCIConfigLock;
+ extern PVOID HalpPciConfigAddr[];
+ extern PVOID HalpPciConfigData[];
+ extern UCHAR HalpEpciMin;
+
+ switch ( ++RecursionLevel ) {
+ case 1:
+ //
+ // Read the System Error Status Register and try to display
+ // something reasonable based on what's in there.
+ //
+
+ Status = *(PULONG)((ULONG)HalpUnionControlRegs + UNION_SESR);
+ Status = BYTE_SWAP(Status);
+
+ //
+ // Before calling HalDisplayString which will interact with
+ // the PCI bus, try to gather all the pertinent info.
+ //
+ PciCsr0 = *((PULONG)HalpPciConfigAddr[0] + UNION_PCI_CSR_OFFSET);
+ PciCsr1 = *((PULONG)HalpPciConfigAddr[1] + UNION_PCI_CSR_OFFSET);
+ PciPlssr0 = *((PULONG)HalpPciConfigAddr[0] + UNION_PCI_PLSSR_OFFSET);
+ PciPlssr1 = *((PULONG)HalpPciConfigAddr[1] + UNION_PCI_PLSSR_OFFSET);
+
+ if ( Status & ~(UNION_SEAR_NOT_SET) ) {
+ //
+ // Status Error Address Register contains valid data,
+ // display it also.
+ //
+ Address = *(PULONG)((ULONG)HalpUnionControlRegs + UNION_SEAR);
+ Address = BYTE_SWAP(Address);
+
+ } else if ( Status &
+ (UNION_SESR_PCI32_BUS_MASTER | UNION_SESR_PCI64_BUS_MASTER) ) {
+
+ ULONG i = 0;
+ PciBusString = "on the 32 bit PCI bus.\n";
+ if ( Status & UNION_SESR_PCI64_BUS_MASTER ) {
+ i = 1;
+ PciBusString = "on the 64 bit PCI bus.\n";
+ }
+
+ //
+ // The error was a PCI error. It is possible we are still
+ // holding the PCI config access lock, so, unconditionally
+ // blow it away.
+ //
+ // However, we need to access the PCI config space for the
+ // bridge, so we need the lock but cannot acquire it in the
+ // usual way, (a) because it may already be locked, and (b)
+ // KeAcquireSpinLock will change IRQL.
+ //
+ // WARNING: Arcane knowledge about what a KSPIN_LOCK really
+ // is!
+ //
+
+ HalpPCIConfigLock = 0xdeaddead;
+ __builtin_isync();
+
+ //
+ // Get current value of this bridge's PCI CONFIG ADDRESS
+ // register.
+ //
+
+ OldPciConfigAddress = *(PULONG)(HalpPciConfigAddr[i]);
+ __builtin_sync();
+
+ //
+ // Set address for access to the host PCI bridge's config
+ // space.
+ //
+
+ if ( i != 0 ) {
+ //
+ // EPCI Bridge.
+ //
+
+ HostBridgePciAddress |= HalpEpciMin << 16;
+ }
+
+ *(PULONG)(HalpPciConfigAddr[i]) = HostBridgePciAddress;
+ __builtin_sync();
+
+ PciConfigData = *(PULONG)(HalpPciConfigData[i]);
+
+ if ( PciConfigData == IBMUNIONPCIBRIDGE ) {
+ PciBridgeFound = 1;
+ *(PULONG)(HalpPciConfigAddr[i]) = HostBridgePciAddress + 4;
+ __builtin_sync();
+
+ PciConfigData = *(PULONG)(HalpPciConfigData[i]);
+ }
+
+ //
+ // Release spin lock.
+ //
+
+ HalpPCIConfigLock = 0;
+ }
+
+ if ( Status & UNION_SESR_CPU_MEMORY_ACCESS ) {
+ //
+ // Memory Error. Read the Memory Error Status and
+ // Memory Error Address registers as well.
+ //
+ MemErrorStatus = *(PULONG)
+ ((ULONG)HalpUnionControlRegs + UNION_MESR);
+ MemErrorStatus = BYTE_SWAP(MemErrorStatus);
+ MemErrorAddress = *(PULONG)
+ ((ULONG)HalpUnionControlRegs + UNION_MEAR);
+ MemErrorAddress = BYTE_SWAP(MemErrorAddress);
+ Syndrome = (UCHAR)(MemErrorStatus & 0xff);
+ }
+
+ HalDisplayString("Machine Check : System Error Status = 0x");
+ HalpDisplayRegister((PUCHAR)&Status, sizeof(Status));
+
+ if ( Status & ~(UNION_SEAR_NOT_SET) ) {
+ HalDisplayString(" System Error Address = 0x");
+ HalpDisplayRegister((PUCHAR)&Address, sizeof(Address));
+ }
+
+ //
+ // The following strangness is just in case it is possible
+ // for more than one bit to be set.
+ //
+
+ if ( Status & UNION_SESR_CHECKSTOP ) {
+ HalDisplayString("UNION initiated checkstop.\n");
+ }
+
+ if ( Status & UNION_SESR_FLASH_WRITE ) {
+ HalDisplayString("FLASH Write Error. A write to flash\n");
+ HalDisplayString("memory was attempted but is not enabled.\n");
+ }
+
+ if ( Status & UNION_SESR_IGMC_ACCESS ) {
+ HalDisplayString("Access performed to IGMC when not enabled.\n");
+ }
+
+ if ( Status & UNION_SESR_DISABLED_ADDRESS ) {
+ HalDisplayString("Access performed to system I/O\n");
+ HalDisplayString("address space that is not enabled.\n");
+ }
+
+ if ( Status & UNION_SESR_T1_ACCESS ) {
+ HalDisplayString(
+ "T = 1 Access Error, a T = 1 PIO cycle was detected.\n");
+ }
+
+ if ( Status & UNION_SESR_ADDRESS_BUS_PARITY ) {
+ HalDisplayString("Address bus parity error.\n");
+ }
+
+ if ( Status & UNION_SESR_DATA_BUS_PARITY ) {
+ HalDisplayString("Data bus parity error.\n");
+ }
+
+ if ( Status & UNION_SESR_NO_L2_HIT_ACCESS ) {
+ HalDisplayString(
+ "L2_HIT_signal not active after AACK_; Addressing error.\n");
+ }
+
+ if ( Status & UNION_SESR_CPU_TO_PCI_ACCESS ) {
+ HalDisplayString(
+ "An error occurred on PCI bus while processing a load/store request.\n");
+ }
+
+ if ( Status &
+ (UNION_SESR_PCI32_BUS_MASTER | UNION_SESR_PCI64_BUS_MASTER) ) {
+ HalDisplayString(
+ "An error occurred during a PCI master initiated operation\n");
+ HalDisplayString(PciBusString);
+ HalDisplayString("Last PCI Configuration Address = 0x");
+ HalpDisplayRegister((PUCHAR)&OldPciConfigAddress,
+ sizeof(OldPciConfigAddress));
+ if ( PciBridgeFound ) {
+ HalDisplayString("PCI Bridge Status/Command = 0x");
+ HalpDisplayRegister((PUCHAR)&PciConfigData,
+ sizeof(PciConfigData));
+ }
+ }
+ if ( PciCsr0 ) {
+ HalDisplayString("Channel Status [32 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciCsr0, sizeof(PciCsr0));
+ }
+ if ( PciPlssr0 ) {
+ HalDisplayString("Processor Load/Store Status [32 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciPlssr0, sizeof(PciPlssr0));
+ }
+ if ( PciCsr1 ) {
+ HalDisplayString("Channel Status [64 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciCsr1, sizeof(PciCsr1));
+ }
+ if ( PciPlssr1 ) {
+ HalDisplayString("Processor Load/Store Status [32 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciPlssr1, sizeof(PciPlssr1));
+ }
+
+ if ( Status & UNION_SESR_XFERDATA ) {
+ HalDisplayString(
+ "An error occured during an operation in the memory\n");
+ HalDisplayString("controller's XferData unit.\n");
+ }
+
+ if ( Status & UNION_SESR_DATA_BUS_TIMEOUT ) {
+ //
+ // N.B. This error cannot be detected except via JTAG logic
+ // as UNION will checkstop rather than machine check in this
+ // case. This error indicates that the 60x bus did not
+ // respond in 8ms.
+ //
+ HalDisplayString("Data bus timeout.\n");
+ }
+
+ if ( Status & UNION_SESR_CPU_MEMORY_ACCESS ) {
+ HalDisplayString(
+ "An error occurred during a memory access by the CPU.\n");
+ HalDisplayString("Memory Error Status Register = 0x");
+ HalpDisplayRegister((PUCHAR)&MemErrorStatus,
+ sizeof(MemErrorStatus));
+ HalDisplayString("Memory Error Address Register = 0x");
+ HalpDisplayRegister((PUCHAR)&MemErrorAddress,
+ sizeof(MemErrorAddress));
+
+ if ( MemErrorStatus & UNION_MESR_DOUBLE_BIT ) {
+ HalDisplayString(
+ "bit 0 - A double bit memory error was detected.\n");
+ HalDisplayString(
+ " Syndrome bits = 0x");
+ HalpDisplayRegister(&Syndrome, sizeof(UCHAR));
+ }
+
+ if ( MemErrorStatus & UNION_MESR_SINGLE_BIT ) {
+ HalDisplayString(
+ "bit 1 - A single bit memory error was detected/corrected.\n");
+ if ( !(MemErrorStatus & UNION_MESR_SINGLE_BIT) ) {
+ HalDisplayString(
+ " Syndrome bits = 0x");
+ HalpDisplayRegister(&Syndrome, sizeof(UCHAR));
+ } else {
+ HalDisplayString(
+ " Error Address and Syndrome are for the Double bit error only.\n");
+ }
+ }
+
+ if ( MemErrorStatus & UNION_MESR_OVERLAPPED_MEM_EXT ) {
+ HalDisplayString(
+ "bit 3 - An access to an address that is mapped in two different memory\n");
+ HalDisplayString(
+ " extents was detected. This is a System Software error.\n");
+ }
+ }
+ break;
+ case 2:
+ HalDisplayString(
+ "Machine Check while trying to report Machine Check\n");
+ default:
+ //
+ // If we get here we took a second machine check while processing
+ // the first. Just hang.
+ //
+ for (;;);
+ }
+}
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+ switch (HalpSystemType) {
+ case IBM_VICTORY:
+ HalpHandleVictoryMemoryError();
+ return;
+ case IBM_DORAL:
+ HalpHandleDoralMemoryError();
+ return;
+ case IBM_TIGER:
+ HalpHandleTigerMemoryError();
+ return;
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxmemctl.h b/private/ntos/nthals/halvict/ppc/pxmemctl.h
new file mode 100644
index 000000000..569bae171
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmemctl.h
@@ -0,0 +1,143 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+ Peter L Johnston (plj@vnet.ibm.com) August 1995.
+ Doral.
+
+--*/
+
+
+//
+// define physical base addresses of planar registers (non UNION)
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+//
+// define physical base addresses of UNION planar registers
+//
+
+//
+// 8259 Interrupt Source (DORAL)
+//
+
+#define UNION_INTERRUPT_PHYSICAL_BASE 0xbfff7700
+
+//
+// IO Space (ISA)
+//
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000
+
+//
+// UNION System Control Registers
+//
+
+#define UNION_SYSTEM_CONTROL_REG_BASE 0xff001000
+
+//
+// System Error Control Register (offset from UNION_SYSTEM_CONTROL_REG_BASE)
+//
+
+#define UNION_SECR 0x50
+
+//
+// System Error Status Register (offset)
+//
+
+#define UNION_SESR 0x60
+
+//
+// System Error Address Register (offset)
+//
+
+#define UNION_SEAR 0x70
+
+//
+// Memory Error Status Register (offset)
+//
+
+#define UNION_MESR 0x120
+
+//
+// Memory Error Address Register (offset)
+//
+
+#define UNION_MEAR 0x130
+
+//
+// System Error Status Register bit definitions.
+//
+
+// Reserved 0xe0000000
+#define UNION_SESR_CHECKSTOP 0x20000000
+#define UNION_SESR_FLASH_WRITE 0x10000000
+#define UNION_SESR_IGMC_ACCESS 0x08000000
+#define UNION_SESR_DISABLED_ADDRESS 0x04000000
+// Reserved 0x03f00000
+#define UNION_SESR_T1_ACCESS 0x00080000
+#define UNION_SESR_ADDRESS_BUS_PARITY 0x00040000
+#define UNION_SESR_DATA_BUS_PARITY 0x00020000
+#define UNION_SESR_NO_L2_HIT_ACCESS 0x00010000
+#define UNION_SESR_CPU_TO_PCI_ACCESS 0x00008000
+#define UNION_SESR_PCI32_BUS_MASTER 0x00004000
+#define UNION_SESR_PCI64_BUS_MASTER 0x00002000
+#define UNION_SESR_XFERDATA 0x00001000
+#define UNION_SESR_DATA_BUS_TIMEOUT 0x00000800
+#define UNION_SESR_CPU_MEMORY_ACCESS 0x00000400
+// Reserved 0x000003ff
+
+//
+// Bits 17, 18 and 19 above represent PCI initiated errors and
+// the System Error Address Register is not updated. In these
+// cases the PCI bridges or xferdata logic must be interogated
+// to determine the cause of the error. Bit 16 also requires
+// bridge interrogation.
+//
+
+#define UNION_SEAR_NOT_SET (UNION_SESR_PCI32_BUS_MASTER | \
+ UNION_SESR_PCI64_BUS_MASTER | \
+ UNION_SESR_XFERDATA)
+
+//
+// Memory Error Status Register bit definitions
+//
+
+#define UNION_MESR_DOUBLE_BIT 0x80000000
+#define UNION_MESR_SINGLE_BIT 0x40000000
+#define UNION_MESR_ADDRESS 0x20000000
+#define UNION_MESR_OVERLAPPED_MEM_EXT 0x10000000
+//reserved 0x0fffff00
+#define UNION_MESR_SYNDROME 0x000000ff
+
+//
+// UNION Channel Status Register is at offset 0x1800 from the PCI Config
+// Address register. Processor Load/Store Status Register is at offset
+// 0x1810.
+//
+
+#define UNION_PCI_CSR_OFFSET 0x1800
+#define UNION_PCI_PLSSR_OFFSET 0x1810
+
diff --git a/private/ntos/nthals/halvict/ppc/pxmisc.s b/private/ntos/nthals/halvict/ppc/pxmisc.s
new file mode 100644
index 000000000..2afe3e6da
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmisc.s
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxmisc.s"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxnatsup.c b/private/ntos/nthals/halvict/ppc/pxnatsup.c
new file mode 100644
index 000000000..45b71d905
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxnatsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxnatsup.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxp91.c b/private/ntos/nthals/halvict/ppc/pxp91.c
new file mode 100644
index 000000000..0427a3f5f
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxp91.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxp91.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxpcibrd.c b/private/ntos/nthals/halvict/ppc/pxpcibrd.c
new file mode 100644
index 000000000..d10d244dd
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpcibrd.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpcibrd.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxpcibus.c b/private/ntos/nthals/halvict/ppc/pxpcibus.c
new file mode 100644
index 000000000..ae07be2d7
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpcibus.c
@@ -0,0 +1,2318 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) - Updated and merged support for various PPC boxes.
+ Jake Oshins (joshins@vnet.ibm.com) -- Further merging and generalization, support for more boxes.
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "ibmppc.h"
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+ULONG HalpPciMaxBuses = 0;
+extern ULONG HalpPciMaxSlots;
+extern PVOID HalpPciConfigAddr[];
+extern PVOID HalpPciConfigData[];
+extern UCHAR HalpEpciMin;
+extern UCHAR HalpEpciMax;
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ //
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+ ULONG UnionBridge;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ // set defaults
+
+ BusData->GetIrqRange = (PciIrqRange) HalpGetPCIIrq;
+
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ //
+ // If BusNo is in the range of busses supported on UNION's
+ // EPCI bus, initialize the BusData for the appropriate
+ // bridge.
+ //
+ // N.B. Initialization is such that non-UNION machines
+ // correct values are obtained.
+ //
+ if ( (BusNo < HalpEpciMin) || (BusNo > HalpEpciMax) ) {
+ UnionBridge = 0;
+ } else {
+ UnionBridge = 1;
+ }
+ BusData->Config.Type2.Address =
+ HalpPciConfigAddr[UnionBridge];
+ BusData->Config.Type2.Data =
+ HalpPciConfigData[UnionBridge];
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = HalpPciMaxSlots;
+
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+// DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { //IBMCPK: added =
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer = Tmp.Bytes[i];
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer++ = Tmp.Bytes[i++];
+ if ( i == sizeof(ULONG) ) {
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ *Buffer = Tmp.Bytes[i];
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG(BusData->Config.Type2.Data);
+
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i++] = *Buffer++;
+ if ( i == sizeof(ULONG) ) {
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, *((PULONG)Buffer));
+
+ return sizeof(ULONG);
+}
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resources
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resource for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some
+ // location, add that as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK:added -1
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK: added -1
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+ // But don't change video devices, they will be enabled or
+ // disabled by HalpInitializeDisplay()
+ //
+ // (For the moment, that means we are shutting off the
+ // S3 chip so that a plug-in Weitek card can get a chance
+ // to talk to GDI.
+
+ if (!(IsVideoDevice(PciData))) {
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+ } else {
+
+ PciData->Command = PciOrigData->Command;
+ }
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+VOID
+HalpPhase0DiscoverPciBuses(
+ IN PCONFIGURATION_COMPONENT_DATA Component
+ )
+/*
+ This function looks down the LoaderBlock looking for nodes that
+ correspond to PCI buses. When it has found them all, it sets
+ HalpPciMaxBuses.
+*/
+{
+ // Check to see if this component would look like a "multi(x)"
+ // entry in ARC.
+ if ((Component->ComponentEntry.Class == AdapterClass) &&
+ (Component->ComponentEntry.Type == MultiFunctionAdapter)) {
+
+ //
+ // First check to see if Identifier is valid, then
+ // check the string it points to.
+ //
+ if (Component->ComponentEntry.Identifier) {
+
+ if ((Component->ComponentEntry.Identifier[0] == 'P') &&
+ (Component->ComponentEntry.Identifier[1] == 'C') &&
+ (Component->ComponentEntry.Identifier[2] == 'I')) {
+
+ HalpPciMaxBuses++; // Increment the number of PCI buses
+
+ }
+ }
+ }
+
+ //
+ // Look at the Siblings of this component
+ //
+ if (Component->Sibling) {
+ HalpPhase0DiscoverPciBuses(Component->Sibling);
+ }
+
+ //
+ // Look at the Children of this component
+ //
+ if (Component->Child) {
+ HalpPhase0DiscoverPciBuses(Component->Child);
+ }
+
+
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halvict/ppc/pxpciint.c b/private/ntos/nthals/halvict/ppc/pxpciint.c
new file mode 100644
index 000000000..6e7fd7ab8
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpciint.c
@@ -0,0 +1,290 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "ibmppc.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+#define P91_DEVICE_ID 0x9100100E
+extern PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress; // in pxp91.c
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+// This function maps the device's InterruptPin to an InterruptLine
+// value.
+//
+// On Sandalfoot and Polo machines PCI interrupts are statically routed
+// via slot number. This routine just returns and the static routing
+// is done in HalpGetIsaFixedPCIIrq
+//
+
+--*/
+{
+
+
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+
+--*/
+{
+}
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG cnt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("Bad IRQ range\n");
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("Bad HaliAdjustResourceListRange\n");
+ return Status;
+ }
+
+ //
+ // This next part is a major HACK. The Weitek video
+ // adapter (which is one of IBM's favorites) needs
+ // to have its frame buffer enabled by the HAL so
+ // that the HAL can write to the screen. The device
+ // driver for this card needs to touch the frame buffer
+ // during its initialization phase, which overlaps with
+ // the period of time that the HAL is writing to the
+ // screen. So, to avoid breaking one or the other,
+ // we need to force the device driver to use the
+ // same I/O space for the frame buffer that the HAL
+ // was using. Unfortunately, this is the only place
+ // to do it. -- Jake Oshins 1/2/96
+
+ HalpGetPCIData(BusHandler,
+ RootHandler,
+ PciSlot,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // We want to do this only for video devices that are
+ // already decoding a range of memory.
+ //
+ if ((IsVideoDevice(PciData)) &&
+ (PciData->u.type0.BaseAddresses[0] & 0xfffffffe))
+ {
+ for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
+ switch ((*pResourceList)->List->Descriptors->Type) {
+ case CmResourceTypeInterrupt:
+ case CmResourceTypePort:
+ case CmResourceTypeDma:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Set the bottom of the range to the value in the Base Address Register
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0];
+
+ //
+ // Set the top of the range to the BAR plus the requested length
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0] +
+ (*pResourceList)->List->Descriptors->u.Memory.Length;
+ }
+ }
+
+ }
+
+ // JAKETEMP pull this out when reworking Baby Blue code!!!!
+
+ // Yet another MAJOR HACK!
+ //
+ // If this is a Doral/Terlingua, then space on the primary PCI bus is
+ // limited. The Baby Blue card, if it is plugged in, will require the
+ // entire upper half. Although this is ridiculous, we want to support
+ // it. And since all boot devices initialize before video, we have to
+ // make sure that nothing has claimed the upper half of the bus'
+ // address space. -- Jake Oshins 3/7/96
+
+ if ((HalpSystemType == IBM_DORAL) && (BusHandler->BusNumber == 0)) {
+ for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
+ switch ((*pResourceList)->List->Descriptors->Type) {
+ case CmResourceTypeInterrupt:
+ case CmResourceTypePort:
+ case CmResourceTypeDma:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // If the requested range maximum is above the first 256MB of
+ // memory space, then the requested maximum is 256MB and the
+ // minimum is 0. (i.e. Let IoAssignResources place it anywhere
+ // in the first 256MB.
+ //
+
+ if ((*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart > 0x0fffffff) {
+ (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart = 0x0;
+ (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart = 0x0fffffff;
+
+ }
+
+ }
+
+ }
+ }
+ return Status;
+
+}
+
+
diff --git a/private/ntos/nthals/halvict/ppc/pxpcisup.c b/private/ntos/nthals/halvict/ppc/pxpcisup.c
new file mode 100644
index 000000000..14cb7ba41
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpcisup.c
@@ -0,0 +1,708 @@
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ Jake Oshins
+ Support Victory machines
+ Peter Johnston
+ Merge Victory/Doral versions.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxmpic2.h"
+#include "ibmppc.h"
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+//
+// UNION has two top level PCI busses.
+//
+
+#define UNION_PCI_BASE_0 0xbfff8000
+#define UNION_PCI_BASE_1 0xbfef8000
+
+PVOID HalpPciConfigAddr[2];
+PVOID HalpPciConfigData[2];
+UCHAR HalpEpciMin = 0xff;
+UCHAR HalpEpciMax = 0xff;
+
+ULONG HalpPciMaxSlots = PCI_MAX_DEVICES;
+
+typedef struct _PCI_BUS_NODE {
+ struct _PCI_BUS_NODE *Sibling;
+ struct _PCI_BUS_NODE *Child;
+ ULONG BusNumber; // logical bus number
+ ULONG BaseBus; // number of the root bus
+ ULONG BaseSlot; // slot in the base bus that these PPBs are plugged into
+} PCI_BUS_NODE, *PPCI_BUS_NODE;
+
+PPCI_BUS_NODE HalpPciBusTree = NULL;
+
+UCHAR
+HalpSearchPciBridgeMap(
+ IN PPCI_BUS_NODE Node,
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER PciSlot,
+ IN UCHAR InterruptPin
+ );
+
+VOID
+HalpInitializePciAccess (
+ VOID
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#pragma alloc_text(INIT,HalpInitializePciAccess)
+#pragma alloc_text(INIT,HalpPhase0GetPciDataByOffset)
+#pragma alloc_text(INIT,HalpPhase0SetPciDataByOffset)
+#pragma alloc_text(PAGE,HalpSearchPciBridgeMap)
+#endif
+
+
+
+
+VOID
+HalpInitializePciAccess (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Fill the HalpPciConfigAddr and HalpPciConfigData arrays with
+ virtual addresses used to access the various top level PCI
+ busses on this machine.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if ( HalpSystemType != IBM_DORAL ) {
+ HalpPciConfigAddr[0] = (PVOID)((ULONG)HalpIoControlBase + 0xcf8);
+ HalpPciConfigData[0] = (PVOID)((ULONG)HalpIoControlBase + 0xcfc);
+
+ return;
+ }
+
+ //
+ // UNION based systems (eg Doral)
+ //
+
+ HalpPciConfigAddr[0] = HalpAssignReservedVirtualSpace(
+ UNION_PCI_BASE_0 >> PAGE_SHIFT,
+ 2);
+ HalpPciConfigData[0] = (PVOID)((ULONG)HalpPciConfigAddr[0] + 0x10);
+
+ HalpPciConfigAddr[1] = HalpAssignReservedVirtualSpace(
+ UNION_PCI_BASE_1 >> PAGE_SHIFT,
+ 2);
+ HalpPciConfigData[1] = (PVOID)((ULONG)HalpPciConfigAddr[1] + 0x10);
+
+ if ( !HalpPciConfigAddr[0] ||
+ !HalpPciConfigAddr[1] ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+#define EPCI_KLUDGE
+#if defined(EPCI_KLUDGE)
+#define IBMHOSTPCIBRIDGE 0x003a1014
+ //
+ // The EPCI bus on doral is initialized with a bus number of 0x80
+ // for reasons unclear. Reset it so it is the next logical bus
+ // following the max PCI bus.
+ //
+ // The following code is really grungy, we should use PCI
+ // access routines to do it,.... the gist of it is
+ //
+ // (1) Check that we have an IBM Host/PCI bridge.
+ // (2) Check that it thinks it's bus 80 and subordinate
+ // bus 80 also (ie no subordinate busses).
+ // (3) Change to bus 0 subordinate bus 0.
+ //
+
+ {
+ ULONG BusInfo;
+ PULONG PciAddr = (PULONG)(HalpPciConfigAddr[0]);
+ PULONG PciData = (PULONG)(HalpPciConfigData[0]);
+ PULONG EpciAddr = (PULONG)(HalpPciConfigAddr[1]);
+ PULONG EpciData = (PULONG)(HalpPciConfigData[1]);
+ ULONG BusNo;
+ ULONG Found = 0;
+
+ //
+ // First, locate the host bridge on the PCI bus. Hopefully
+ // it's on bus 0.
+ //
+
+ *PciAddr = 0x80000000;
+ __builtin_eieio();
+ BusInfo = *PciData;
+
+ if ( BusInfo == IBMHOSTPCIBRIDGE ) {
+ //
+ // Have bridge, see what the bus range is.
+ //
+ *PciAddr = 0x80000040;
+ __builtin_eieio();
+ BusInfo = *PciData;
+ HalpEpciMin = (UCHAR)(((BusInfo >> 8) & 0xff) + 1);
+ //
+ // Now, find bridge on EPCI bus. Scan for it.
+ //
+ for ( BusNo = 0 ; BusNo < 0x100 ; BusNo++ ) {
+ *EpciAddr = 0x80000000 | (BusNo << 16);
+ __builtin_eieio();
+ BusInfo = *EpciData;
+ if ( BusInfo == IBMHOSTPCIBRIDGE ) {
+ *EpciAddr = 0x80000000 | (BusNo << 16) | 0x40;
+ __builtin_eieio();
+ BusInfo = *EpciData;
+
+ // Subordinate bus number - Primary bus number
+ HalpEpciMax = (UCHAR)(((BusInfo >> 8) & 0xff) - (BusInfo & 0xff));
+ HalpEpciMax += HalpEpciMin;
+
+ BusInfo &= 0xffff0000;
+ BusInfo |= (HalpEpciMax << 8) | HalpEpciMin;
+ *EpciData = BusInfo;
+ Found = 1;
+ break;
+ }
+ }
+ if ( !Found ) {
+ //
+ // No bridge on EPCI bus?
+ //
+ HalpEpciMin = HalpEpciMax = 0xff;
+ }
+ }
+ }
+
+#endif
+
+#define AMD_KLUDGE
+#if defined(AMD_KLUDGE)
+#define AMDPCIETHERNET 0x20001022
+ //
+ // Open firmware is configuring the AMD chip in a way we cannot
+ // deal with. It is possible to issue a hard reset on Doral/Terlingua
+ // so that's what we do here.
+ //
+
+ {
+ PULONG PciAddr = (PULONG)(HalpPciConfigAddr[0]);
+ PULONG PciData = (PULONG)(HalpPciConfigData[0]);
+ PVOID CRRBase;
+ ULONG CfgSpace[16];
+ ULONG Slot;
+ ULONG i;
+
+ for ( Slot = 0 ; Slot < 32 ; Slot++ ) {
+ HalpPhase0GetPciDataByOffset(0,
+ Slot,
+ CfgSpace,
+ 0,
+ 64);
+ if ( CfgSpace[0] == AMDPCIETHERNET ) {
+ //
+ // Change the command (and status) of this puppy
+ // so that when we write it back it's disabled.
+ //
+ CfgSpace[1] = 0;
+
+ //
+ // Ok, now we need to write to UNION's Component
+ // Reset Register for this bridge. Bits of interest
+ // are 0 thru 5 correcponding to devices 1 thru 6
+ // (spec says 0 thru 5 but they seem to want you
+ // to skip the memory controller before you start
+ // counting).
+ //
+ // Also, this register isn't byte reversed so we hit
+ // bits 24 thru 31 instead,... note that setting to
+ // 1 means leave it alone, setting to 0 resets.
+ //
+ // This register is at xxxf7ef0 which isn't mapped.
+ // This is the PCI bridge (not EPCI) so xxx in this
+ // case is bff.
+ //
+ CRRBase = HalpAssignReservedVirtualSpace(0xbfff7, 1);
+
+ if ( !CRRBase ) {
+ //
+ // Bad things happened, give up.
+ //
+ break;
+ }
+
+ *(PULONG)((ULONG)CRRBase + 0xef0) = 0xfc ^ (0x80 >> (Slot - 1));
+ //
+ // Wait a while then unset the reset bit.
+ //
+ for ( i = 0 ; i < 1000000 ; i++ ) {
+ __builtin_eieio();
+ }
+ *(PULONG)((ULONG)CRRBase + 0xef0) = 0xfc;
+ //
+ // Wait a while longer then write back the config space.
+ //
+ for ( i = 0 ; i < 1000000 ; i++ ) {
+ __builtin_eieio();
+ }
+ HalpReleaseReservedVirtualSpace(CRRBase, 1);
+ HalpPhase0SetPciDataByOffset(0,
+ Slot,
+ CfgSpace,
+ 0,
+ 64);
+ //
+ // Assume there's only one.
+ //
+ break;
+ }
+ }
+ }
+
+#endif
+
+
+}
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ PCI_TYPE1_CFG_BITS PciConfig;
+ PCI_SLOT_NUMBER PciSlotNumber;
+
+ PciSlotNumber.u.AsULONG = SlotNumber;
+
+ PciConfig.u.AsULONG = 0;
+ PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber;
+ PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber;
+ PciConfig.u.bits.BusNumber = BusNumber;
+ PciConfig.u.bits.Enable = TRUE;
+
+ return (PciConfig.u.AsULONG);
+}
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler
+ installation.
+
+Arguments:
+
+ BusNumber PCI Bus Number. This is the 8 bit BUS Number which is
+ bits 23-16 of the Configuration Address. In support of
+ multiple top level busses, the upper 24 bits of this
+ argument will supply the index into the table of
+ configuration address registers.
+ SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device
+ number (bits 15-11 of the configuration address) and
+ the 3 bit function number (10-8).
+ Buffer Address of source data.
+ Offset Number of bytes to skip from base of PCI config area.
+ Length Number of bytes to write
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ PCI_TYPE1_CFG_BITS ConfigAddress;
+ ULONG ReturnLength;
+ PVOID ConfigAddressRegister;
+ PVOID ConfigDataRegister;
+ PUCHAR Bfr = (PUCHAR)Buffer;
+
+ if ( BusNumber < HalpEpciMin ) {
+ ConfigAddressRegister = HalpPciConfigAddr[0];
+ ConfigDataRegister = HalpPciConfigData[0];
+ } else {
+ ConfigAddressRegister = HalpPciConfigAddr[1];
+ ConfigDataRegister = HalpPciConfigData[1];
+ }
+
+ ASSERT(!(Offset & ~0xff));
+ ASSERT(Length);
+ ASSERT((Offset + Length) <= 256);
+
+ if ( Length + Offset > 256 ) {
+ if ( Offset > 256 ) {
+ return 0;
+ }
+ Length = 256 - Offset;
+ }
+
+ ReturnLength = Length;
+
+ ConfigAddress.u.AsULONG = HalpTranslatePciSlotNumber(BusNumber,
+ SlotNumber);
+ ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2;
+
+ if ( Offset & 0x3 ) {
+ //
+ // Access begins at a non-register boundary in the config
+ // space. We need to read the register containing the data
+ // and rewrite only the changed data. (I wonder if this
+ // ever really happens?)
+ //
+ ULONG SubOffset = Offset & 0x3;
+ ULONG SubLength = 4 - SubOffset;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ if ( SubLength > Length ) {
+ SubLength = Length;
+ }
+
+ //
+ // Adjust Length (remaining) and (new) Offset bu amount covered
+ // in this first word.
+ //
+ Length -= SubLength;
+ Offset += SubLength;
+
+ //
+ // Get the first word (register), replace only those bytes that
+ // need to be changed, then write the whole thing back out again.
+ //
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+
+ while ( SubLength-- ) {
+ Tmp.Bytes[SubOffset++] = *Bfr++;
+ }
+
+ WRITE_PORT_ULONG(ConfigDataRegister, Tmp.All);
+
+ //
+ // Aim ConfigAddressRegister at the next word (register).
+ //
+ ConfigAddress.u.bits.RegisterNumber++;
+ }
+
+ //
+ // Do the majority of the transfer 4 bytes at a time.
+ //
+ while ( Length > sizeof(ULONG) ) {
+ ULONG Tmp = *(UNALIGNED PULONG)Bfr;
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ WRITE_PORT_ULONG(ConfigDataRegister, Tmp);
+ ConfigAddress.u.bits.RegisterNumber++;
+ Bfr += sizeof(ULONG);
+ Length -= sizeof(ULONG);
+
+ }
+
+ //
+ // Do bytes in last register.
+ //
+ if ( Length ) {
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+ ULONG i = 0;
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+
+ while ( Length-- ) {
+ Tmp.Bytes[i++] = *(PUCHAR)Bfr++;
+ }
+ WRITE_PORT_ULONG(ConfigDataRegister, Tmp.All);
+ }
+
+ return ReturnLength;
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ BusNumber PCI Bus Number. This is the 8 bit BUS Number which is
+ bits 23-16 of the Configuration Address. In support of
+ multiple top level busses, the upper 24 bits of this
+ argument will supply the index into the table of
+ configuration address registers.
+ SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device
+ number (bits 15-11 of the configuration address) and
+ the 3 bit function number (10-8).
+ Buffer Address of source data.
+ Offset Number of bytes to skip from base of PCI config area.
+ Length Number of bytes to write
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PCI_TYPE1_CFG_BITS ConfigAddress;
+ PCI_TYPE1_CFG_BITS ConfigAddressTemp;
+ ULONG ReturnLength;
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+ PVOID ConfigAddressRegister;
+ PVOID ConfigDataRegister;
+
+ if ( BusNumber < HalpEpciMin ) {
+ ConfigAddressRegister = HalpPciConfigAddr[0];
+ ConfigDataRegister = HalpPciConfigData[0];
+ } else {
+ ConfigAddressRegister = HalpPciConfigAddr[1];
+ ConfigDataRegister = HalpPciConfigData[1];
+ }
+
+ ASSERT(!(Offset & ~0xff));
+ ASSERT(Length);
+ ASSERT((Offset + Length) <= 256);
+
+ if ( Length + Offset > 256 ) {
+ if ( Offset > 256 ) {
+ return 0;
+ }
+ Length = 256 - Offset;
+ }
+
+ ReturnLength = Length;
+
+ ConfigAddress.u.AsULONG = HalpTranslatePciSlotNumber(BusNumber,
+ SlotNumber);
+ ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2;
+
+ //
+ // If we are being asked to read data when function != 0, check
+ // first to see if this device decares itself as a multi-function
+ // device. If it doesn't, don't do this read.
+ //
+ if (ConfigAddress.u.bits.FunctionNumber != 0) {
+
+ ConfigAddressTemp.u.bits.RegisterNumber = 3; // contains header type
+ ConfigAddressTemp.u.bits.FunctionNumber = 0; // look at base package
+ ConfigAddressTemp.u.bits.DeviceNumber = ConfigAddress.u.bits.DeviceNumber;
+ ConfigAddressTemp.u.bits.BusNumber = ConfigAddress.u.bits.BusNumber;
+ ConfigAddressTemp.u.bits.Enable = TRUE;
+
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddressTemp.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+
+ if (!(Tmp.Bytes[2] & 0x80)) { // if the Header type field's multi-function bit is not set
+
+ for (i = 0; i < Length; i++) {
+ *((PUCHAR)Buffer)++ = 0xff; // Make this read as if the device isn't populated
+ }
+
+ return Length;
+ }
+ }
+
+ i = Offset & 0x3;
+
+ while ( Length ) {
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+ while ( (i < 4) && Length) {
+ *((PUCHAR)Buffer)++ = Tmp.Bytes[i];
+ i++;
+ Length--;
+ }
+ i = 0;
+ ConfigAddress.u.bits.RegisterNumber++;
+ }
+ return ReturnLength;
+}
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR InterruptPin;
+ UCHAR BaseLimit = 0;
+ UCHAR Class;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+
+ InterruptPin = PciData->u.type0.InterruptPin;
+ Class = PciData->BaseClass;
+
+ if (InterruptPin == 0) { // Device doesn't implement an interrupt
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ BaseLimit = PciData->u.type0.InterruptLine + MPIC_BASE_VECTOR;
+
+ (*Interrupt)->Base = BaseLimit;
+ (*Interrupt)->Limit = BaseLimit;
+
+#if DBG
+ DbgPrint("Interrupt line, by the hardware: 0x%x\n",
+ PciData->u.type0.InterruptLine + MPIC_BASE_VECTOR);
+#endif
+
+ if ( BaseLimit != NOT_MPIC) {
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( Class == 1 ) {
+ //
+ // This device is a Mass Storage Controller, set flag to
+ // turn on the HDD Lamp when interrupts come in on this
+ // vector.
+ //
+ // (Shouldn't there be a constant defined somewhere for
+ // the Class? (plj)).
+ //
+
+ extern ULONG HalpMassStorageControllerVectors;
+
+ HalpMassStorageControllerVectors |= 1 << BaseLimit;
+ }
+
+#endif
+
+ return STATUS_SUCCESS;
+ }
+
+ ASSERT(!(BaseLimit == NOT_MPIC)); // We should never hit this because
+ // there should never be a device
+ // with an interrupt pin != 0 that
+ // has no valid mapping to the MPIC
+ return STATUS_UNSUCCESSFUL;
+}
+
diff --git a/private/ntos/nthals/halvict/ppc/pxport.c b/private/ntos/nthals/halvict/ppc/pxport.c
new file mode 100644
index 000000000..19c0841dc
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxport.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxport.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxpower.s b/private/ntos/nthals/halvict/ppc/pxpower.s
new file mode 100644
index 000000000..39dc14e06
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpower.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpower.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxproc.c b/private/ntos/nthals/halvict/ppc/pxproc.c
new file mode 100644
index 000000000..5a8ee0570
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxproc.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxproc.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxprof.c b/private/ntos/nthals/halvict/ppc/pxprof.c
new file mode 100644
index 000000000..5e9e3dc20
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxprof.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxprof.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxreset.s b/private/ntos/nthals/halvict/ppc/pxreset.s
new file mode 100644
index 000000000..0b6c055f7
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxreset.s
@@ -0,0 +1,557 @@
+//++
+//
+// Copyright (c) 1993, 94, 95, 96 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxreset.s
+//
+// Abstract:
+//
+// This module implements the routine HalpPowerPcReset, which can be
+// used to return the PowerPC to Big Endian with cache flushed and
+// branches to the rom based machine reset handler.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// plj Feb 1995 Zap TLB before resetting, add 603+
+// and 604+ support.
+//
+// jlw Added eagle memory controller support
+// plj Aug 1995 MP version (UNION dependent).
+//
+//
+//--
+
+#include "kxppc.h"
+
+#define HPT_LOCK 0x4fc
+
+
+ .set C_LINE_SZ, 64
+ .set C_LINE_CNT, 64
+ .set C_SETS, 8
+
+ .set C_SIZE, C_LINE_SZ * C_LINE_CNT * C_SETS
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+
+
+ .set H0_603_DCE, 0x4000 // 603 Data Cache Enable
+ .set H0_603_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set H0_603_ICFI, 0x0800 // 603 I-Cache Flash Invalidate
+
+ .set H0_604_DCE, 0x4000 // 604 Data Cache Enable
+ .set H0_604_ICE, 0x8000 // 604 Instruction Cache Enable
+ .set H0_604_DCIA, 0x0400 // 604 I-Cache Invalidate All
+ .set H0_604_ICIA, 0x0800 // 604 I-Cache Invalidate All
+
+ .set TLB_CLASSES_601, 128 // 601 tlb has 128 congruence classes
+ .set TLB_CLASSES_603, 32 // 603 tlb has 32 congruence classes
+ .set TLB_CLASSES_604, 64 // 604 tlb has 64 congruence classes
+
+
+ LEAF_ENTRY(HalpPowerPcReset)
+ li r.6, -1
+ mtdec r.6
+ isync
+
+ bl ..HalpResetHelper
+here:
+ mflr r.9 // r.9 = &here
+
+ LWI(r.4, 0xfff00100) // address of rom reset handler
+ LWI(r.7, 0x80000092) // address of MEM CTLR endian sw
+ li r.6, 0
+
+ bne not_601 // jif processor is not a 601
+
+ //
+ // processor is a 601
+ //
+
+ rlwinm r.5, r.5, 0, ~(0x0008) // turn off little endian
+
+ //
+ // disable instruction and data relocation and switch
+ // interrupt prefix to fetch from ROM
+ //
+
+ andi. r.8, r.8, ~DISABLES & 0xffff
+ ori r.8, r.8, MASK_SPR(MSR_IP,1)
+ mtsrr1 r.8 // this will also be target state
+ nop // for rfi
+
+//
+// Ensure all code from 'cachem' to 'end_little' is in cache by loading a
+// byte in each address line in that range.
+
+ addi r.9, r.9, cachem-here // (r.9) = physical &cachem
+
+ // r.9 now contains the physical address of cachem. (assuming
+ // this code was loaded as part of kernel which is loaded at
+ // physical 0 = virtual 0x80000000). We effect the switch to
+ // physical addressing thru an rfi with the target state set
+ // to resume at cachem with relocation and interrupts disabled.
+
+ mtsrr0 r.9 // address of cachem for rfi
+ addi r.10, r.9, end_little-cachem // (r.10) = &end_little
+ addi r.11, r.9, HalpPowerPcReset.end-cachem // (r.11) = &reset_end
+
+ addi r.12, r.9, -C_LINE_SZ // bias addr for 1st iteration by
+ // amount added by lbzu prior to load
+
+ rfi // switch
+cachem:
+ lbzu r.13, C_LINE_SZ(r.12) // get byte at (r.13)+C_LINE_SZ
+ cmplw r.12, r.10 // bumping r.12 by C_LINE_SZ
+ addi r.13, r.13, 1 // ensure load completed.
+ blt cachem // get all in range here-end_little.
+
+ isync
+ mtsrr0 r.4 // set rom reset target for next rfi
+ lis r.9, 0x87f0 // Segment register base 0x87f00000
+ li r.10, 0xf // Set all 16 segment registers
+
+ li r.11, 0
+ mtibatl 0, r.6 // zero bat 0-3 upper and lower
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+
+ mtibatu 3, r.6
+setsr: rlwimi r.11, r.10, 28, 0, 3 // Shift segment reg. # to bits 0-3
+ or r.12, r.9, r.10 // Segment register value 0x87f000sr
+ mtsrin r.12, r.11
+
+ addic. r.10, r.10, -1 // Next segment register
+ bne setsr
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ sync // quiet the machine down
+ sync
+ sync
+
+ sync
+ stb r.6, 0(r.7) // switch memory
+ eieio // flush io
+ sync
+
+ sync
+ sync
+ sync
+ mtspr HID0, r.5 // switch ends on the cpu
+
+ sync
+ sync
+ sync
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsr 0, r.9 // Set the last segment register
+
+ rfi // head off into the reset handler
+ rfi
+ addi r.0, r.1, 0x138 // we never get here
+ oris r.0, r.0, 0x4c // rfi (big-endian)
+end_little:
+
+ b $
+
+//
+// For the 603 (and hopefully other) processor(s) things are a little
+// easier because little-endianness is controlled by the MSR. We still
+// have to change memory seperately so we still want code from the memory
+// switch thru the cpu switch in cache.
+//
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.6 contains 0.
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the address of "here".
+// r.31 contains the processor type
+
+
+not_601:
+
+//
+// MSR bits ILE and POW must be disabled via mtmsr as rfi only moves
+// the least significant 16 bits into the MSR.
+//
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_POW,1) // -= Power Management
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_ILE,1) // -= Interrupt Little Endian
+ sync
+ mtmsr r.8
+ isync
+
+//
+// Use an rfi to switch to big-endian, untranslated, interrupt prefix on
+// with a target address in the nice harmless pallindromic code below.
+// use another rfi to branch to the rom resident reset handler.
+//
+
+ li r.8, MASK_SPR(MSR_ME,1) | MASK_SPR(MSR_IP,1)
+ addi r.9, r.9, uncached_6034-here
+ mtsrr1 r.8 // state = Machine Check Enabled
+ bl here2
+here2: mflr r.28
+ rlwinm r.28, r.28, 0, 0x7fffffff // convert address to physical
+ lwz r.29, endofroutine - here2(r.28)
+ mtsrr0 r.9 // rfi to uncached_6034
+ b jumpswap
+
+memoryswap:
+ ori r.8, r.28, 0
+ addi r.8, r.8, uncached_6034-here2
+ addi r.9, 0, 0
+ li r.15, swapend - uncached_6034
+ addis r.14, 0, 0
+ addi r.14, 0, 4
+swaploop:
+ lwz r.11, 0(r.8)
+ lwz r.12, 4(r.8)
+ stwbrx r.11, r.14, r.8
+ stwbrx r.12, 0, r.8
+ addi r.8, r.8, 8
+ subi r.15, r.15, 8
+ cmpi 0, 0, r.15, 0
+ bgt swaploop
+
+jumpswap:
+
+//
+// The following bizzareness is to ensure that the memory switch thru
+// the disabling of cache is in cache. There is less than 32 bytes so
+// they must be part of either the cache line we are currently in, or
+// the one at the target of the branch. Therefore, branching over them,
+// doing a little and branching back to them should be enough to enure
+// they're cache resident.
+//
+
+ b fill_icache
+goto_bigendian:
+ sync
+ stb r.6, 0(r.7) // switch memory
+ sync
+ lwz r.30, endofroutine - here2(r.28)
+ cmp 0, 0, r.29, r.30
+ beq memoryswap
+ rfi
+fill_icache:
+ isync
+ sync // complete everything!
+ b goto_bigendian
+
+ .align 5
+
+uncached_6034:
+ .big_endian // out of cache fetches must be
+ // assembled in same mode as processor
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsrr0 r.4 // rfi target = 0xfff00100
+ mtspr HID0, r.10 // DISABLE CACHING
+
+ mtibatl 0, r.6 // invalidate/clear all bats
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+
+ mtdbatl 0, r.6
+ mtdbatu 0, r.6
+ mtdbatl 1, r.6
+ mtdbatu 1, r.6
+
+ mtdbatl 2, r.6
+ mtdbatu 2, r.6
+ mtdbatl 3, r.6
+ mtdbatu 3, r.6
+
+ mtsr 0, r.6
+ mtsr 1, r.6
+ mtsr 2, r.6
+ mtsr 3, r.6
+
+ mtsr 4, r.6
+ mtsr 5, r.6
+ mtsr 6, r.6
+ mtsr 7, r.6
+
+ mtsr 8, r.6
+ mtsr 9, r.6
+ mtsr 10, r.6
+ mtsr 11, r.6
+
+ mtsr 12, r.6
+ mtsr 13, r.6
+ mtsr 14, r.6
+ mtsr 15, r.6
+
+ rfi // go to machine reset handler
+ // never get here
+ rfi // previous rfi on a dword boundary
+ // allow for word swap
+ .little_endian
+endofroutine:
+ sync
+ .globl swapend
+ .long swapend
+swapend:
+
+ LEAF_EXIT(HalpPowerPcReset)
+
+ LEAF_ENTRY(HalpResetUnion)
+
+ bl ..HalpResetHelper
+
+//
+// Union has a Software Power on Reset control register. Any write to
+// this register will send a hard reset to all processors and I/O devices
+// and the memory controller (Union) itself.
+//
+
+ li r.0, -1 // something to write
+ isync
+ lis r.8, 0xff00 // get address of S/R POR reg
+ stw r.0, 0xe8(r.8) // should never get here.
+ sync
+ sync
+ sync
+ sync
+ isync
+
+ LEAF_EXIT(HalpResetUnion)
+
+//++
+//
+// HalpResetHelper
+//
+// This routine locks the HPT, invalidates the TLB, disables the caches
+// and returns to the caller in REAL mode.
+//
+// On entry, interrupts are expected to be disabled.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// cr.0 EQ if processor is a 601
+// r.5 contains HID0 present value.
+// r.8 contains MSR present value.
+// r.31 contains PVR >> 16.
+//
+//--
+
+ LEAF_ENTRY(HalpResetHelper)
+
+ mfspr r.5, HID0
+ mfpvr r.31 // determine processor type
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts
+ mtmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1) // -= Data Relocation
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_IR,1) // -= Inst Relocation
+ mtsrr1 r.8 // rfi target state
+ mflr r.9 // (r.9) = return address
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+ //
+ // Get the processor into real mode. The following assumes
+ // physical = (virtual & 0x7fffffff) for this code. If this
+ // assumption cannot be guaranteed (this code has been paged?)
+ // then we should copy it to low memory,.... we are at high
+ // IRQL so we can't page fault but has it always been locked?
+ // (This question arises as more or the kernel and hal are made
+ // pageable and moved out of BAT protection).
+ //
+ bl almost_real
+almost_real:
+ mflr r.3 // r.3 = &almost_real
+ addi r.3, r.3, real-almost_real
+ rlwinm r.3, r.3, 0, 0x7fffffff // convert address to physical
+ mtsrr0 r.3 // set target address
+ rfi
+real:
+
+ //
+ // The processor is now executing in REAL mode.
+ //
+ mtlr r.9 // set real return address
+
+ //
+ // Attempt to get the HPT lock. If attempt fails 1024 * 1024
+ // times, just take it anyway (the other processor(s) is
+ // probably dead) or this processor already has it.
+ //
+
+ li r.3, HPT_LOCK // get address of HPT LOCK
+ lis r.9, 0x10 // retry count (1024 * 1024)
+ mtctr r.9
+ li r.9, 1 // lock value
+
+lockhpt:
+ lwarx r.10, 0, r.3 // get current lock value
+ cmpwi r.10, 0
+ bne lockretry
+ stwcx. r.9, 0, r.3
+ beq lockedhpt
+lockretry:
+ bdnz lockhpt
+
+ //
+ // Failed to obtain lock. Forcibly lock it.
+ //
+
+ stw r.9, 0(r.3)
+
+lockedhpt:
+
+ //
+ // invalidate all tlb entries
+ //
+
+ li r.3, TLB_CLASSES_601 // use largest known number of
+ // congruence classes
+ mtctr r.3 // number of classes = iteration count
+zaptlb: tlbie r.3 // invalidate tlb congruence class
+ addi r.3, r.3, 4096 // increment to next class address
+ bdnz zaptlb // loop through all classes
+ sync
+
+ srwi r.31, r.31, 16 // isolate processor type
+ cmpwi r.31, 1 // is 601?
+
+ beqlr // return if 601 (no cache control)
+
+ cmpwi cr.0, r.31, 3 // is 603?
+ cmpwi cr.4, r.31, 7 // is 603ev?
+ cmpwi cr.1, r.31, 6 // is 603e?
+ cmpwi cr.2, r.31, 4 // is 604?
+ cmpwi cr.3, r.31, 9 // is 604e?
+ beq cr.0, is_603
+ beq cr.4, is_603
+ bne cr.1, not_603
+
+//
+// 603 I-Cache is invalidated by setting ICFI in HID0. Unlike
+// the 604, this bit is not self clearing.
+//
+
+is_603: rlwinm r.5, r.5, 0, ~H0_603_DCE// turn off D-cache
+ rlwinm r.10, r.5, 0, ~H0_603_ICE// turn off I-cache
+ ori r.10, r.10, H0_603_ICFI // I-Cache Flash Invalidate
+ ori r.5, r.5, H0_603_ICE // I-cache enable
+ isync
+ mtspr HID0, r.10 // invalidate/disable
+ mtspr HID0, r.5 // enable
+ blr // return
+
+not_603:
+ beq cr.2, is_604
+// bne not_604
+
+// Note: the above branch is commented out because we don't
+// currently have any other options,... 620 will probably
+// be different.
+
+
+is_604: tlbsync // wait all processor tlb invalidate
+ sync
+
+//
+// 604 caches must be enabled in order to be invalidated. It
+// is acceptable to enable and invalidate with the same move
+// to hid0. The data cache will be left disabled, the instruction
+// cache enabled.
+//
+
+ ori r.5, r.5, H0_604_DCE | H0_604_ICE
+ ori r.10, r.5, H0_604_DCIA | H0_604_ICIA
+
+ rlwinm r.5, r.5, 0, ~H0_604_DCE
+ rlwinm r.5, r.5, 0, ~H0_604_DCIA
+ rlwinm r.5, r.5, 0, ~H0_604_ICIA
+
+ mtspr HID0, r.10 // enable + invalidate
+ mtspr HID0, r.5 // disable data cache
+
+ rlwinm r.10, r.5, 0, ~H0_604_ICE // disable i-cache later
+
+ LEAF_EXIT(HalpResetHelper)
diff --git a/private/ntos/nthals/halvict/ppc/pxreturn.c b/private/ntos/nthals/halvict/ppc/pxreturn.c
new file mode 100644
index 000000000..8181c91f7
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxreturn.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxreturn.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxs3.c b/private/ntos/nthals/halvict/ppc/pxs3.c
new file mode 100644
index 000000000..0b7211142
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxs3.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxs3.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxshadbf.s b/private/ntos/nthals/halvict/ppc/pxshadbf.s
new file mode 100644
index 000000000..d637a3763
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxshadbf.s
@@ -0,0 +1,2 @@
+#include <..\..\halppc\ppc\pxshadbf.s>
+
diff --git a/private/ntos/nthals/halvict/ppc/pxstall.s b/private/ntos/nthals/halvict/ppc/pxstall.s
new file mode 100644
index 000000000..50d947500
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxstall.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxstall.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxsysbus.c b/private/ntos/nthals/halvict/ppc/pxsysbus.c
new file mode 100644
index 000000000..bbc98ee76
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxsysbus.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxsysbus.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxtime.c b/private/ntos/nthals/halvict/ppc/pxtime.c
new file mode 100644
index 000000000..5fe5a500a
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxtime.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxtime.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxusage.c b/private/ntos/nthals/halvict/ppc/pxusage.c
new file mode 100644
index 000000000..3be115176
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxusage.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxusage.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxvm.c b/private/ntos/nthals/halvict/ppc/pxvm.c
new file mode 100644
index 000000000..d515cb51f
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxvm.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxvm.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxwd.c b/private/ntos/nthals/halvict/ppc/pxwd.c
new file mode 100644
index 000000000..bcfc1f5e9
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxwd.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxwd.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/x86bios.c b/private/ntos/nthals/halvict/ppc/x86bios.c
new file mode 100644
index 000000000..ba7969c5d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/x86bios.c
@@ -0,0 +1 @@
+#include "..\..\halppc\ppc\x86bios.c"
diff --git a/private/ntos/nthals/halvict/sources b/private/ntos/nthals/halvict/sources
new file mode 100644
index 000000000..5985d56c0
--- /dev/null
+++ b/private/ntos/nthals/halvict/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revision Histoy:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halvict
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+
+!IF $(PPC)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_MP_PPC_ -DDAKOTA -DVICTORY -DSOFT_HDD_LAMP -D_HALNVR_
+
+INCLUDES=..\halppc\ppc;..\x86new;$(BASEDIR)\private\ntos\inc
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxfirsup.c \
+ ppc\pxmemctl.c \
+ ppc\pxpcisup.c \
+ ppc\pxdisp.c \
+ ppc\pxp91.c \
+ ppc\pxwd.c \
+ ppc\pxs3.c \
+ ppc\pxbbl.c \
+ ppc\pxbl.c \
+ ppc\pxshadbf.s \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxenviro.c \
+ ppc\pxmapio.c \
+ ppc\pxtime.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxinithl.c \
+ ppc\pxport.c \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\fwnvr.c \
+ ppc\pxflshio.c \
+ ppc\pxinfo.c \
+ ppc\pxpcibrd.c \
+ ppc\pxvm.c \
+ ppc\pxpower.s \
+ ppc\pxintrpt.c \
+ ppc\pxmisc.s \
+ ppc\x86bios.c
+
+DLLDEF=obj\*\hal.def
+
diff --git a/private/ntos/nthals/halwood/hal.rc b/private/ntos/nthals/halwood/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halwood/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halwood/makefile b/private/ntos/nthals/halwood/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halwood/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halwood/ppc/fwnvr.c b/private/ntos/nthals/halwood/ppc/fwnvr.c
new file mode 100644
index 000000000..74d30689e
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/fwnvr.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\fwnvr.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxbeep.c b/private/ntos/nthals/halwood/ppc/pxbeep.c
new file mode 100644
index 000000000..cb3db8ccc
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxbeep.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxbeep.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxbusdat.c b/private/ntos/nthals/halwood/ppc/pxbusdat.c
new file mode 100644
index 000000000..cbc199e71
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxbusdat.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxbusdat.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxcache.s b/private/ntos/nthals/halwood/ppc/pxcache.s
new file mode 100644
index 000000000..2c5630a60
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxcache.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcache.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxcalstl.c b/private/ntos/nthals/halwood/ppc/pxcalstl.c
new file mode 100644
index 000000000..3d972b02b
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxcalstl.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcalstl.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxclksup.s b/private/ntos/nthals/halwood/ppc/pxclksup.s
new file mode 100644
index 000000000..8452d5e05
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxclksup.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclksup.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxclock.c b/private/ntos/nthals/halwood/ppc/pxclock.c
new file mode 100644
index 000000000..16cb61886
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxclock.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclock.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxdat.c b/private/ntos/nthals/halwood/ppc/pxdat.c
new file mode 100644
index 000000000..978438ac0
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxdat.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxdat.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxdisp.c b/private/ntos/nthals/halwood/ppc/pxdisp.c
new file mode 100644
index 000000000..103883cc6
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxdisp.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxdisp.c"
+
diff --git a/private/ntos/nthals/halwood/ppc/pxenviro.c b/private/ntos/nthals/halwood/ppc/pxenviro.c
new file mode 100644
index 000000000..0f822c840
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxenviro.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxenviro.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxflshbf.s b/private/ntos/nthals/halwood/ppc/pxflshbf.s
new file mode 100644
index 000000000..b2e4b591d
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxflshbf.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshbf.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxflshio.c b/private/ntos/nthals/halwood/ppc/pxflshio.c
new file mode 100644
index 000000000..5817b14f5
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxflshio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshio.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxhwsup.c b/private/ntos/nthals/halwood/ppc/pxhwsup.c
new file mode 100644
index 000000000..9164059ae
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxhwsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxhwsup.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxidle.c b/private/ntos/nthals/halwood/ppc/pxidle.c
new file mode 100644
index 000000000..16bfd2a08
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxidle.c
@@ -0,0 +1,62 @@
+/*++
+TITLE("Processor Idle")
+
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ pxidle.c
+
+abstract:
+
+ This module implements system platform dependent power management
+ support.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalProcessorIdle(
+ VOID
+ )
+
+/*++
+
+ Routine Description:
+
+ This function is called when the current processor is idle with
+ interrupts disabled. There is no thread active and there are no
+ DPCs to process. Therefore, power can be switched to a standby
+ mode until the the next interrupt occurs on the current processor.
+
+ N.B. This routine is entered with EE in MSR clear. This routine
+ must do any power management enabling necessary, set the EE
+ bit in MSR, then either return or wait for an interrupt.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+
+--*/
+
+{
+ HalpProcessorIdle();
+}
diff --git a/private/ntos/nthals/halwood/ppc/pxinfo.c b/private/ntos/nthals/halwood/ppc/pxinfo.c
new file mode 100644
index 000000000..812bd48b4
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxinfo.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxinfo.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxinithl.c b/private/ntos/nthals/halwood/ppc/pxinithl.c
new file mode 100644
index 000000000..f99a85307
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxinithl.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxinithl.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxintmod.c b/private/ntos/nthals/halwood/ppc/pxintmod.c
new file mode 100644
index 000000000..a7bfe283c
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxintmod.c
@@ -0,0 +1,78 @@
+/*++
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ This module implements interrupt mode translation for PowerPC machines.
+
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+
+
+#include "halp.h"
+
+
+//
+// Get the translated interrupt mode for the given vector
+//
+
+
+KINTERRUPT_MODE
+HalpGetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+{
+
+ //
+ // On Woodfield irq 15 is reserved for PCI interrupts and must be programmed level sensitive
+ // all other interrupts are edge triggered
+ //
+
+ if (Vector == DEVICE_VECTORS + 15) {
+
+ return LevelSensitive;
+
+ } else {
+
+ return Latched;
+
+ }
+
+
+
+}
+
+//
+// Correct the interrupt mode for the given vector.
+// On Woodfield this function simply returns since all interrupt mode translations can be performed
+// at HalpGetInterruptMode time with the interrupt vector.
+//
+
+
+VOID
+HalpSetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+{
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halwood/ppc/pxintrpt.c b/private/ntos/nthals/halwood/ppc/pxintrpt.c
new file mode 100644
index 000000000..dddf4ce77
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxintrpt.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxintrpt.c"
+
diff --git a/private/ntos/nthals/halwood/ppc/pxintsup.s b/private/ntos/nthals/halwood/ppc/pxintsup.s
new file mode 100644
index 000000000..f72297f65
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxintsup.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxintsup.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxirql.c b/private/ntos/nthals/halwood/ppc/pxirql.c
new file mode 100644
index 000000000..7ad12df0b
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxirql.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxirql.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxisabus.c b/private/ntos/nthals/halwood/ppc/pxisabus.c
new file mode 100644
index 000000000..a0a2942ed
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxisabus.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxisabus.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxmapio.c b/private/ntos/nthals/halwood/ppc/pxmapio.c
new file mode 100644
index 000000000..38b6ef09e
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxmapio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxmapio.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxmemctl.c b/private/ntos/nthals/halwood/ppc/pxmemctl.c
new file mode 100644
index 000000000..8f3fdb04b
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxmemctl.c
@@ -0,0 +1,338 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1994, 1995 International Buisness Machines Corporation.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) - added HalpHandleMemoryError
+
+--*/
+
+
+
+#include "halp.h"
+#include <pxmemctl.h>
+#include "pxidaho.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+ //
+ // Enable Dynamic Power Management on 603 and 603+.
+ //
+
+ HalpSetDpm();
+
+ return TRUE;
+
+}
+
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ HalpPciConfigBase = (PVOID) IO_CONTROL_PHYSICAL_BASE;
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ HalpPciConfigBase = (PVOID) IO_CONTROL_PHYSICAL_BASE;
+
+ if (HalpIoControlBase == NULL) {
+ HalpIoControlBase = (PUCHAR)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x400000);
+ }
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+}
+
+
+VOID
+HalpDisplayRegister(
+ PUCHAR RegHex,
+ int Bytes
+ )
+
+/*++
+
+Routine Description:
+
+ Displays (via HalDisplayString) a new-line terminated
+ string of hex digits representing the input value. The
+ input value is pointed to by the first argument is
+ from 1 to 4 bytes in length.
+
+Arguments:
+
+ RegHex Pointer to the value to be displayed.
+ Bytes Length of input value in bytes (1-4).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#define DISP_MAX 4
+ UCHAR RegString[(DISP_MAX * 2) + 2];
+ UCHAR Num, High, Low;
+ PUCHAR Byte = &RegString[(DISP_MAX * 2) + 1];
+
+ *Byte = '\0';
+ *--Byte = '\n';
+
+ if ( (unsigned)Bytes > DISP_MAX ) {
+ Bytes = DISP_MAX;
+ }
+
+ while (Bytes--) {
+ Num = *RegHex++;
+ High = (Num >> 4) + '0';
+ Low = (Num & 0xf) + '0';
+ if ( High > '9' ) {
+ High += ('A' - '0' - 0xA);
+ }
+ if ( Low > '9' ) {
+ Low += ('A' - '0' - 0xA);
+ }
+ *--Byte = Low;
+ *--Byte = High;
+ }
+ HalDisplayString(Byte);
+}
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+ int byte;
+ IDAHO_CONFIG PCI_Config_Space;
+ UCHAR BusAddress[4];
+
+ //
+ // REM Make sure Options Reg.1 (0xBA) and Enable Detection Reg. (0xC0) are programed
+ // Reset Error Det Reg when done ?
+
+ HalGetBusData(PCIConfiguration, 0, 0, &PCI_Config_Space, sizeof(IDAHO_CONFIG));
+
+ // Dump Error Detection Reg, Bus Address, Status Error,
+
+ HalDisplayString ("TEA/MCP: System Error.\n");
+
+ HalDisplayString ("Error Detection Register 1: ");
+ HalpDisplayRegister (&PCI_Config_Space.ErrorDetection1,1);
+
+ //
+ // The error may have been detected during xfers on: cpu (local), memory, or pci bus
+ //
+ // Idaho will NOT generate/check Local Bus Parity
+
+ if (PCI_Config_Space.ErrorDetection1 & 0x03) { // idaho <-> 603 :Local bus Cycle
+
+ HalDisplayString ("Unsupported Local Bus Cycle\n");
+
+ for (byte = 0; byte < 4; byte++) // Correct endianess if address is local
+ BusAddress[byte] = PCI_Config_Space.ErrorAddress[3-byte];
+ HalDisplayString ("Local Bus Error Address: ");
+ HalpDisplayRegister(BusAddress,4);
+
+ HalDisplayString ("CPU Bus Error Status - TT(0:4);TSIZ(0:2): ");
+ HalpDisplayRegister(&PCI_Config_Space.CpuBusErrorStatus,1);
+
+// if (ErrorDetection & 0x01 {
+// HalDisplayString ("Unsupported Transfer Attributes\n");
+// }
+// if (ErrorDetection & 0x02 {
+// HalDisplay ("Extended Transfer Detected\n");
+// }
+ }
+ else if (PCI_Config_Space.ErrorDetection1 & 0x08) { // PCI Cycle
+ HalDisplayString ("PCI Cycle\n");
+
+ for (byte=0; byte<4; byte++)
+ BusAddress[byte] = PCI_Config_Space.ErrorAddress[byte];
+ HalDisplayString ("PCI Bus Address: ");
+ HalpDisplayRegister(BusAddress,4);
+
+ HalDisplayString ("PCI Bus Error Status: ");
+ HalpDisplayRegister(&PCI_Config_Space.PciBusErrorStatus,1);
+
+// if PCI_Config_Space.PciBusErrorStatus & 0x10
+// HalDisplayString("Memory Controller was Slave on PCI Bus\n");
+// else
+// HalDisplayString("Memory Controller was Master on PCI Bus\n");
+
+ HalDisplayString ("PCI Device Status Register D(15:8): ");
+ HalpDisplayRegister(&PCI_Config_Space.DeviceStatus[1],1);
+
+// if PCI_Config_Space.DeviceStatus[1] & 0x81
+// HalDisplayString("Local Bus Agent Read Cycle\n");
+
+// if ErrorDetection & 0x80 // Local Bus Agent Write Cycle
+// HalDisplayString ("PCI System Error\n");
+// if ErrorDetection & 0x40 // Local Bus Agent Write\Read Address
+// HalDisplayString ("PCI Parity Error\n ");// Parity Error
+// Read PCI status Reg
+
+// if ErrorDetection & 0x20
+// HalDisplayString ("No Such Address in Physical Memory\n");
+
+ }
+// if ErrorDetection & 0x10
+// HalDisplayString ("Refresh Timeout\n");
+
+}
diff --git a/private/ntos/nthals/halwood/ppc/pxmemctl.h b/private/ntos/nthals/halwood/ppc/pxmemctl.h
new file mode 100644
index 000000000..1c0ca1966
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxmemctl.h
@@ -0,0 +1,36 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define physical base addresses of planar
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+
diff --git a/private/ntos/nthals/halwood/ppc/pxnatsup.c b/private/ntos/nthals/halwood/ppc/pxnatsup.c
new file mode 100644
index 000000000..45b71d905
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxnatsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxnatsup.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxpcibrd.c b/private/ntos/nthals/halwood/ppc/pxpcibrd.c
new file mode 100644
index 000000000..d10d244dd
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxpcibrd.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpcibrd.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxpcibus.c b/private/ntos/nthals/halwood/ppc/pxpcibus.c
new file mode 100644
index 000000000..2120ef5f4
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxpcibus.c
@@ -0,0 +1,2404 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) - Updated and merged support for various PPC boxes.
+ Jake Oshins (joshins@vnet.ibm.com) -- Further merging and generalization, support for more boxes.
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+ULONG HalpPciMaxBuses = 0;
+extern ULONG HalpPciMaxSlots;
+#if defined(UNION)
+extern PVOID HalpPciConfigAddr[];
+extern PVOID HalpPciConfigData[];
+#endif
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ //
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+ //
+ // Build a tree that shows the relationship of all the PCI busses
+ // to be used when routing interrupts.
+ //
+ HalpMapPlugInPciBridges (PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ // set defaults
+
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetPCIIrq;
+
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+#if defined(UNION)
+ BusData->Config.Type2.Address = HalpPciConfigAddr[BusNo >> 8];
+ BusData->Config.Type2.Data = HalpPciConfigData[BusNo >> 8];
+#else
+ BusData->Config.Type2.Address = (PUCHAR)HalpIoControlBase + 0xCF8;
+ BusData->Config.Type2.Data = (PUCHAR)HalpIoControlBase + 0xCFC;
+#endif
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = HalpPciMaxSlots;
+
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ ULONG iBuffer[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+//PLJTMP - no really, use kitten gloves! Until the wd90c24a driver is
+// fixed to NOT go read beyond common space on EVERYBODY's chips,
+// if this chip is an NCR 810, lie like a rug!
+
+
+ if ( iBuffer[0] == 0x00011000 ) {
+ //
+ // NCR 810
+ //
+ while ( Len < Length ) {
+ *Buffer++ = 0xff;
+ Len++;
+ }
+ return Len;
+ }
+//PLJTMPend
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+// DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { //IBMCPK: added =
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer = Tmp.Bytes[i];
+
+// WRITE_PORT_ULONG ((PUCHAR) HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR) HalpIoControlBase + 0xCFC + i);
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer++ = Tmp.Bytes[i++];
+ if ( i == sizeof(ULONG) ) {
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ *Buffer = Tmp.Bytes[i];
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)HalpIoControlBase + 0xCFC + i);
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG(BusData->Config.Type2.Data);
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG);
+// *((PULONG) Buffer) = READ_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCFC);
+
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*Buffer);
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i++] = *Buffer++;
+ if ( i == sizeof(ULONG) ) {
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG );
+// WRITE_PORT_USHORT ((PUCHAR)HalpIoControlBase + 0xCFC + (USHORT) i,*((PUSHORT)Buffer));
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, *((PULONG)Buffer));
+
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG);
+// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCFC,*((PULONG)Buffer));
+
+ return sizeof(ULONG);
+}
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK:added -1
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK: added -1
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+ // But don't change video devices, they will be enabled or
+ // disabled by HalpInitializeDisplay()
+ //
+ // (For the moment, that means we are shutting off the
+ // S3 chip so that a plug-in Weitek card can get a chance
+ // to talk to GDI.
+
+ if (!(IsVideoDevice(PciData))) {
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+ } else {
+
+ PciData->Command = PciOrigData->Command;
+ }
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+VOID
+HalpPhase0DiscoverPciBuses(
+ IN PCONFIGURATION_COMPONENT_DATA Component
+ )
+/*
+ This function looks down the LoaderBlock looking for nodes that
+ correspond to PCI buses. When it has found them all, it sets
+ HalpPciMaxBuses.
+*/
+{
+ // Check to see if this component would look like a "multi(x)"
+ // entry in ARC.
+ if ((Component->ComponentEntry.Class == AdapterClass) &&
+ (Component->ComponentEntry.Type == MultiFunctionAdapter)) {
+
+ //
+ // First check to see if Identifier is valid, then
+ // check the string it points to.
+ //
+ if (Component->ComponentEntry.Identifier) {
+
+ if ((Component->ComponentEntry.Identifier[0] == 'P') &&
+ (Component->ComponentEntry.Identifier[1] == 'C') &&
+ (Component->ComponentEntry.Identifier[2] == 'I')) {
+
+ HalpPciMaxBuses++; // Increment the number of PCI buses
+
+ }
+ }
+ }
+
+ //
+ // Look at the Siblings of this component
+ //
+ if (Component->Sibling) {
+ HalpPhase0DiscoverPciBuses(Component->Sibling);
+ }
+
+ //
+ // Look at the Children of this component
+ //
+ if (Component->Child) {
+ HalpPhase0DiscoverPciBuses(Component->Child);
+ }
+
+
+}
+
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halwood/ppc/pxpciint.c b/private/ntos/nthals/halwood/ppc/pxpciint.c
new file mode 100644
index 000000000..089386edd
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxpciint.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpciint.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxpcisup.c b/private/ntos/nthals/halwood/ppc/pxpcisup.c
new file mode 100644
index 000000000..0da9534bb
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxpcisup.c
@@ -0,0 +1,259 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+Copyright (c) 1996 IBM Corporation
+
+Module Name:
+
+ pxpcisup.c
+
+Abstract:
+
+ This module contains machine specific PCI routines.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+extern PVOID HalpPciConfigBase;
+#define PCI_INTERRUPT_ROUTING_SCSI 13
+#define PCI_INTERRUPT_ROUTING_OTHER 15
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#endif
+
+ULONG HalpPciMaxSlots = PCI_MAX_DEVICES;
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ PCI_TYPE1_CFG_BITS PciConfig;
+ PCI_SLOT_NUMBER PciSlotNumber;
+
+ PciSlotNumber.u.AsULONG = SlotNumber;
+
+ PciConfig.u.AsULONG = 0;
+ PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber;
+ PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber;
+ PciConfig.u.bits.BusNumber = BusNumber;
+ PciConfig.u.bits.Enable = TRUE;
+
+ return (PciConfig.u.AsULONG);
+}
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ ULONG to;
+ PUCHAR from;
+ ULONG tmpLength;
+ ULONG i;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ to = HalpTranslatePciSlotNumber(BusNumber, SlotNumber);
+ to += Offset;
+ from = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, to );
+ i = to % sizeof(ULONG);
+ WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*from);
+ to++;
+ from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PUCHAR to;
+ ULONG from;
+ ULONG tmpLength;
+ ULONG i;
+
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+
+ from = HalpTranslatePciSlotNumber(BusNumber, SlotNumber);
+ from += Offset;
+ to = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+
+ WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, from);
+ i = from % sizeof(ULONG);
+ *((PUCHAR) to) = READ_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i);
+ to++;
+ from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+ PciData = (PPCI_COMMON_CONFIG)buffer;
+ HalGetBusData(
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(*Interrupt, sizeof (SUPPORTED_RANGE));
+
+ if ( (PciData->VendorID == 0x1000) && // NCR
+ ( (PciData->DeviceID == 0x0001) || // 810 or 825
+ (PciData->DeviceID == 0x0003) ) ) {
+ (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_SCSI;
+ (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_SCSI;
+ } else {
+ (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_OTHER;
+ (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_OTHER;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpMapPlugInPciBridges(
+ UCHAR NoBuses
+ )
+
+/*++
+
+Routine Description:
+
+ Looks for any unexpected (plug-in) PCI-PCI bridges so
+ that interrupts can be mapped from these buses back
+ into the interrupt controller.
+
+Arguments:
+
+ NoBuses -- This is the number of buses that HalpGetPciBridgeConfig found
+
+Return Value:
+
+ none
+
+--*/
+{
+ // Woodfield doesn't support plug-in PCI busses!!!
+
+ return;
+}
+
+
diff --git a/private/ntos/nthals/halwood/ppc/pxport.c b/private/ntos/nthals/halwood/ppc/pxport.c
new file mode 100644
index 000000000..19c0841dc
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxport.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxport.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxpower.s b/private/ntos/nthals/halwood/ppc/pxpower.s
new file mode 100644
index 000000000..39dc14e06
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxpower.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpower.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxproc.c b/private/ntos/nthals/halwood/ppc/pxproc.c
new file mode 100644
index 000000000..5a8ee0570
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxproc.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxproc.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxprof.c b/private/ntos/nthals/halwood/ppc/pxprof.c
new file mode 100644
index 000000000..5e9e3dc20
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxprof.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxprof.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxreset.s b/private/ntos/nthals/halwood/ppc/pxreset.s
new file mode 100644
index 000000000..5aca035e2
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxreset.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxreset.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxreturn.c b/private/ntos/nthals/halwood/ppc/pxreturn.c
new file mode 100644
index 000000000..f205f2c6b
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxreturn.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxreturn.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxs3.c b/private/ntos/nthals/halwood/ppc/pxs3.c
new file mode 100644
index 000000000..0b7211142
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxs3.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxs3.c"
+
diff --git a/private/ntos/nthals/halwood/ppc/pxshadbf.s b/private/ntos/nthals/halwood/ppc/pxshadbf.s
new file mode 100644
index 000000000..d637a3763
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxshadbf.s
@@ -0,0 +1,2 @@
+#include <..\..\halppc\ppc\pxshadbf.s>
+
diff --git a/private/ntos/nthals/halwood/ppc/pxsiosup.c b/private/ntos/nthals/halwood/ppc/pxsiosup.c
new file mode 100644
index 000000000..1768ca5ad
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxsiosup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxsiosup.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxstall.s b/private/ntos/nthals/halwood/ppc/pxstall.s
new file mode 100644
index 000000000..50d947500
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxstall.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxstall.s>
diff --git a/private/ntos/nthals/halwood/ppc/pxsysbus.c b/private/ntos/nthals/halwood/ppc/pxsysbus.c
new file mode 100644
index 000000000..038371625
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxsysbus.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxsysbus.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxsysint.c b/private/ntos/nthals/halwood/ppc/pxsysint.c
new file mode 100644
index 000000000..ac1891797
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxsysint.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxsysint.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxtime.c b/private/ntos/nthals/halwood/ppc/pxtime.c
new file mode 100644
index 000000000..5fe5a500a
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxtime.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxtime.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxusage.c b/private/ntos/nthals/halwood/ppc/pxusage.c
new file mode 100644
index 000000000..3be115176
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxusage.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxusage.c>
diff --git a/private/ntos/nthals/halwood/ppc/pxwd.c b/private/ntos/nthals/halwood/ppc/pxwd.c
new file mode 100644
index 000000000..bcfc1f5e9
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/pxwd.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxwd.c"
+
diff --git a/private/ntos/nthals/halwood/ppc/wdvga.c b/private/ntos/nthals/halwood/ppc/wdvga.c
new file mode 100644
index 000000000..89d330fcf
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/wdvga.c
@@ -0,0 +1,745 @@
+/******************************************************************************
+
+Copyright (c) 1994 IBM Corporaion
+
+wdvga.c
+
+ This module is a modification of the HAL display initialization and output
+ routines for IBM Woodfield WD90C24A Graphics system. This version of wdvga.c
+ is intended to be used by the OS loader to provide putc capabilities with
+ the WD card.
+
+ This file was created by copying s3vga.c and modifying it to remove
+ everything except the code that initializes the VGA common registers.
+
+Author:
+
+ Hiroshi Itoh 25-Feb-1994
+
+Revision History:
+
+
+******************************************************************************/
+#define USE_VGA_PALETTE 1
+
+# include "halp.h"
+# include "pvgaequ.h"
+# include "wdvga.h"
+
+/*****************************************************************************/
+
+// +++++++ IBM BJB added PCI bus definitions and tab size definition
+
+// PCI slot configuration space addresses
+
+# define UPPER_PCI_SLOT 0x80804000L
+# define LOWER_PCI_SLOT 0x80802000L
+# define PCI_BASE UPPER_PCI_SLOT
+
+// PCI configuration space record offsets
+
+# define VENDOR_ID 0x00
+# define DEVICE_ID 0x02
+# define COMMAND 0X04
+# define DEVICE_STATUS 0X06
+# define REVISION_ID 0x08
+# define PROG_INTERFACE 0x0a
+# define BASE_MEM_ADDRESS 0x10
+
+# define TAB_SIZE 4
+
+/*****************************************************************************/
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+InitializeWD (
+ VOID
+ );
+
+BOOLEAN WDIsPresent (
+ VOID
+ );
+
+VOID
+SetWDVGAConfig (
+ VOID
+ );
+
+VOID
+LockPR (
+ USHORT,
+ PUCHAR
+ );
+
+VOID
+UnlockPR (
+ USHORT,
+ PUCHAR
+ );
+
+VOID
+RestorePR (
+ USHORT,
+ PUCHAR
+ );
+
+//
+// Define paradise registers setting variation
+//
+
+#define pr72_alt (pr72 | 0x8000) // avoid pr30 index conflict
+#define pr1b_ual (pr1b) // pr1b unlock variation
+#define pr1b_ush (pr1b | 0x4000) // pr1b unlock variation
+#define pr1b_upr (pr1b | 0x8000) // pr1b unlock variation
+
+//
+// Define static data (in s3vga.c)
+//
+
+extern
+ULONG
+ Row,
+ Column,
+ ScrollLine,
+ DisplayText;
+
+/******************************************************************************
+
+ This routine initializes the WD display controller chip.
+
+ This is the initialization routine for WD90C24A2. This routine initializes
+ the WD90C24A2 chip in the sequence of VGA BIOS.
+
+******************************************************************************/
+
+VOID
+InitializeWD( VOID )
+
+ {
+
+ ULONG DataLong;
+ USHORT i, j;
+ UCHAR DataByte;
+ UCHAR Index;
+ PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+
+
+ // these lines were moved to here from the original jxdisp.c
+ // routine that called this one
+ //
+ // In the HAL, we just put the video card into text mode.
+
+ DisplayText = 25;
+ ScrollLine = 160;
+
+ // Enable Video Subsystem according to the WD90C24 reference book
+
+ WRITE_WD_UCHAR( SUBSYS_ENB, 0x16 );
+ WRITE_WD_UCHAR( Setup_OP, 0x01 );
+ WRITE_WD_UCHAR( SUBSYS_ENB, 0x0e );
+
+ WRITE_WD_UCHAR( VSub_EnB, VideoParam[0] );
+
+ SetWDVGAConfig();
+
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_WD_UCHAR( Seq_Index, RESET ); // Synchronous Reset !
+ WRITE_WD_UCHAR( Seq_Data, 0x01 );
+
+ // For ATI card (0x63) we may want to change the frequence
+
+ WRITE_WD_UCHAR( MiscOutW, VideoParam[1] );
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+
+ WRITE_WD_UCHAR( Seq_Index, RESET ); // Synchronous Reset !
+ WRITE_WD_UCHAR( Seq_Data, 0x01 );
+
+ // Sequencer Register
+
+ for( Index = 1; Index < 5; Index++ )
+ {
+ WRITE_WD_UCHAR( Seq_Index, Index );
+ WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET + Index] );
+ }
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+
+ WRITE_WD_UCHAR( WD_3D4_Index, VERTICAL_RETRACE_END );
+
+ DataByte = READ_WD_UCHAR( WD_3D5_Data );
+ DataByte = DataByte & 0x7f;
+ WRITE_WD_UCHAR( WD_3D5_Data, DataByte );
+
+ // CRTC controller CR0 - CR18
+
+ for( Index = 0; Index < 25; Index++ )
+ {
+ WRITE_WD_UCHAR( WD_3D4_Index, Index );
+ WRITE_WD_UCHAR( WD_3D5_Data, VideoParam[CRT_OFFSET + Index] );
+ }
+
+ // attribute write
+ // program palettes and mode register
+
+ for( Index = 0; Index < 21; Index++ )
+ {
+ WaitForVSync();
+ DataByte = READ_WD_UCHAR( Stat1_In ); // Initialize Attr. F/F
+ WRITE_WD_UCHAR( Attr_Index, Index );
+
+// KeStallExecutionProcessor( 5 );
+ WRITE_WD_UCHAR( Attr_Data, VideoParam[ATTR_OFFSET + Index] );
+
+// KeStallExecutionProcessor( 5 );
+ WRITE_WD_UCHAR( Attr_Index, 0x20 ); // Set into normal operation
+ }
+
+ WRITE_WD_UCHAR( Seq_Index, RESET ); // reset to normal operation !
+ WRITE_WD_UCHAR( Seq_Data, 0x03 );
+
+ // graphics controller
+
+ for( Index = 0; Index < 9; Index++ )
+ {
+ WRITE_WD_UCHAR( GC_Index, Index );
+ WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + Index] );
+ }
+ // turn off the text mode cursor
+
+ WRITE_WD_UCHAR( WD_3D4_Index, CURSOR_START );
+ WRITE_WD_UCHAR( WD_3D5_Data, 0x2D );
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+
+ WRITE_WD_UCHAR( Seq_Index, 0x02 ); // Enable Write Plane reg
+ WRITE_WD_UCHAR( Seq_Data, 0x04 ); // select plane 2
+
+ WRITE_WD_UCHAR( Seq_Index, 0x04 ); // Memory Mode Control reg
+ WRITE_WD_UCHAR( Seq_Data, 0x06 ); // access to all planes,
+
+ WRITE_WD_UCHAR( GC_Index, 0x05 ); // Graphic, Control Mode reg
+ WRITE_WD_UCHAR( GC_Data, 0x00 );
+
+ WRITE_WD_UCHAR( GC_Index, 0x06 );
+ WRITE_WD_UCHAR( GC_Data, 0x04 );
+
+ WRITE_WD_UCHAR( GC_Index, 0x04 );
+ WRITE_WD_UCHAR( GC_Data, 0x02 );
+
+ MemBase = 0xA0000; // Font Plane 2
+
+ for( i = 0; i < 256; i++ )
+ {
+ for( j = 0; j < 16; j++ )
+ {
+ WRITE_WD_VRAM( MemBase, VGAFont8x16[i * 16 + j] );
+ MemBase++;
+ }
+
+ // 32 bytes each character font
+
+ for( j = 16; j < 32; j++ )
+ {
+ WRITE_WD_VRAM( MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_WD_UCHAR( Seq_Index, 0x01 );
+ DataByte = READ_WD_UCHAR( Seq_Data );
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_WD_UCHAR( Seq_Data, DataByte );
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_WD_UCHAR( DAC_Mask, 0xff );
+
+ for( i = 0; i < 768; i++ )
+ {
+ WRITE_WD_UCHAR( DAC_Data, ColorPalette[i] );
+ }
+
+ //
+ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ // select plane 0, 1
+ WRITE_WD_UCHAR( Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET + 0x02] );
+
+ // access to planes 0, 1.
+ WRITE_WD_UCHAR( Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_WD_UCHAR( GC_Index, 0x05 ); // Graphic, Control Mode reg
+ WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x05] );
+
+ WRITE_WD_UCHAR( GC_Index, 0x04);
+ WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x04] );
+
+ WRITE_WD_UCHAR( GC_Index, 0x06);
+ WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x06] );
+
+ //
+ // Set screen into blue
+ //
+
+ for( DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2 )
+ {
+ WRITE_WD_VRAM( DataLong, 0x20 );
+#ifdef USE_VGA_PALETTE
+ WRITE_WD_VRAM( DataLong + 1, 0x07 );
+#else
+ WRITE_WD_VRAM( DataLong + 1, 0x1F );
+#endif
+ }
+
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ Column = 0;
+ Row = 0;
+
+ return;
+
+ } /* end of InitializeWD() */
+
+
+VOID
+SetWDVGAConfig (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Set WDVGA compatible configuration except DAC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR SavePR5, SavePR10, SavePR11, SavePR20, SavePR72, Temp;
+ PUCHAR pPRtable;
+
+ LockPR( pr1b, NULL );
+ LockPR( pr30, NULL );
+
+ UnlockPR( pr20, NULL );
+ UnlockPR( pr10, &SavePR10 );
+ UnlockPR( pr11, &SavePR11 );
+
+// non-ISO monitor setting clock
+
+ WRITE_WD_UCHAR( Seq_Index, CLOCKING_MODE );
+ Temp = READ_WD_UCHAR( Seq_Data );
+ WRITE_WD_UCHAR( Seq_Data, (Temp | 0x01));
+
+ Temp = READ_WD_UCHAR( MiscOutR );
+ WRITE_WD_UCHAR( MiscOutW, (Temp & 0xf3));
+
+// other clocking chip selects
+ UnlockPR( pr72_alt, &SavePR72 );
+
+ WRITE_WD_UCHAR( Seq_Index, pr68 );
+ Temp = READ_WD_UCHAR( Seq_Data );
+ WRITE_WD_UCHAR( Seq_Data, ((Temp & 0xe7) | 0x08));
+
+ RestorePR( pr72_alt, &SavePR72 );
+
+ RestorePR( pr11, &SavePR11 );
+ RestorePR( pr10, &SavePR10 );
+ LockPR( pr20, NULL );
+
+// start of WD90C24A2 both screen mode table
+
+ pPRtable = wd90c24a_both;
+ while (*pPRtable != END_PVGA) {
+ switch (*pPRtable++) {
+ case W_CRTC :
+ WRITE_WD_UCHAR( WD_3D4_Index, *pPRtable++ );
+ WRITE_WD_UCHAR( WD_3D5_Data, *pPRtable++ );
+ break;
+ case W_SEQ :
+ WRITE_WD_UCHAR( Seq_Index, *pPRtable++ );
+ WRITE_WD_UCHAR( Seq_Data, *pPRtable++ );
+ break;
+ case W_GCR :
+ WRITE_WD_UCHAR( GC_Index, *pPRtable++ );
+ WRITE_WD_UCHAR( GC_Data, *pPRtable++ );
+ break;
+ default :
+ break;
+ }
+ }
+
+ // unlock FLAT registers
+
+ UnlockPR( pr1b_ual, NULL );
+
+ WRITE_WD_UCHAR( WD_3D4_Index, pr19 );
+ WRITE_WD_UCHAR( WD_3D5_Data, ((pr19_s32 & 0xf3) | pr19_CENTER));
+
+ // lock FLAT registers
+
+ LockPR( pr1b, NULL );
+
+#ifndef USE_VGA_PALETTE
+ // PR1/PR4 setting
+
+ UnlockPR( pr5, &SavePR5 );
+
+ WRITE_WD_UCHAR( GCR_Index, pr1 );
+ Temp = READ_WD_UCHAR( GCR_Data );
+ WRITE_WD_UCHAR( GCR_Data, (Temp | 0x30));
+ WRITE_WD_UCHAR( GCR_Index, pr4 );
+ Temp = READ_WD_UCHAR( GCR_Data );
+ WRITE_WD_UCHAR( GCR_Data, (Temp | 0x01));
+
+ RestorePR( pr5, &SavePR5 );
+
+ // PR16 setting
+
+ UnlockPR( pr10, &SavePR10 );
+
+ WRITE_WD_UCHAR( WD_3D4_Index, pr16 );
+ WRITE_WD_UCHAR( WD_3D5_Data, 0);
+
+ RestorePR( pr10, &SavePR10 );
+
+ // PR34a setting
+
+ UnlockPR( pr20, &SavePR20 );
+
+ WRITE_WD_UCHAR( Seq_Index, pr34a );
+ WRITE_WD_UCHAR( Seq_Data, 0x0f);
+
+ RestorePR( pr20, &SavePR20 );
+#endif
+
+
+} /* SetWDVGAConfig */
+
+
+//
+// Internal functions
+//
+
+VOID
+LockPR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = GC_Index;
+ pData = GC_Data;
+ Index = pr5;
+ Data = pr5_lock;
+ break;
+ case pr10:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr10;
+ Data = pr10_lock;
+ break;
+ case pr11:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr11;
+ Data = pr11_lock;
+ break;
+ case pr1b:
+// case pr1b_ual:
+// case pr1b_ush:
+// case pr1b_upr:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_lock;
+ break;
+ case pr20:
+ pIndex = Seq_Index;
+ pData = Seq_Data;
+ Index = pr20;
+ Data = pr20_lock;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ Data = pr30_lock;
+ break;
+ case pr72_alt:
+ pIndex = Seq_Index;
+ pData = Seq_Data;
+ Index = pr72;
+ Data = pr72_lock;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ WRITE_WD_UCHAR( pIndex, Index );
+ if (pPRval!=NULL) {
+ *pPRval = READ_WD_UCHAR( pData );
+ } /* endif */
+ WRITE_WD_UCHAR( pData, Data );
+}
+
+VOID
+UnlockPR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = GC_Index;
+ pData = GC_Data;
+ Index = pr5;
+ Data = pr5_unlock;
+ break;
+ case pr10:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr10;
+ Data = pr10_unlock;
+ break;
+ case pr11:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr11;
+ Data = pr11_unlock;
+ break;
+// case pr1b:
+ case pr1b_ual:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_unlock;
+ break;
+ case pr1b_ush:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_unlock_shadow;
+ break;
+ case pr1b_upr:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ Data = pr1b_unlock_pr;
+ break;
+ case pr20:
+ pIndex = Seq_Index;
+ pData = Seq_Data;
+ Index = pr20;
+ Data = pr20_unlock;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ Data = pr30_unlock;
+ break;
+ case pr72_alt:
+ pIndex = Seq_Index;
+ pData = Seq_Data;
+ Index = pr72;
+ Data = pr72_unlock;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ WRITE_WD_UCHAR( pIndex, Index );
+ if (pPRval!=NULL) {
+ *pPRval = READ_WD_UCHAR( pData );
+ } /* endif */
+ WRITE_WD_UCHAR( pData, Data );
+
+}
+
+VOID
+RestorePR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = GC_Index;
+ pData = GC_Data;
+ Index = pr5;
+ break;
+ case pr10:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr10;
+ break;
+ case pr11:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr11;
+ break;
+ case pr1b:
+// case pr1b_ual:
+// case pr1b_ush:
+// case pr1b_upr:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr1b;
+ break;
+ case pr20:
+ pIndex = Seq_Index;
+ pData = Seq_Data;
+ Index = pr20;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ break;
+ case pr72_alt:
+ pIndex = Seq_Index;
+ pData = Seq_Data;
+ Index = pr72;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ Data = *pPRval;
+ WRITE_WD_UCHAR( pIndex, Index );
+ WRITE_WD_UCHAR( pData, Data );
+
+}
+
+
+BOOLEAN
+WDIsPresent (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns TRUE if an WDVGA is present. It assumes that it's
+ already been established that a VGA is present. It performs the Western
+ Digital recommended ID test. If all this works, then this is indeed an
+ chip from Western Digital.
+
+ All the registers will be preserved either this function fails to find a
+ WD vga or a WD vga is found.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if a WDVGA is present, FALSE if not.
+
+--*/
+
+{
+ UCHAR GraphSave0c;
+ UCHAR GraphSave0f;
+ UCHAR temp1,temp2;
+ BOOLEAN status = TRUE;
+
+ //
+ // write 3ce.0c
+ //
+
+ WRITE_WD_UCHAR( GC_Index, pr2 );
+ GraphSave0c = temp1 = READ_WD_UCHAR( GC_Data );
+ temp1 &= 0xbf;
+ WRITE_WD_UCHAR( GC_Data, temp1 );
+
+ //
+ // check 3ce.09 after lock
+ //
+
+ LockPR( pr5, &GraphSave0f ); // lock it
+// WRITE_WD_UCHAR( GC_Index, pr5 );
+// GraphSave0f = READ_WD_UCHAR( GC_Data );
+// WRITE_WD_UCHAR( GC_Data, pr5_lock ); // lock it
+
+ WRITE_WD_UCHAR( GC_Index, pr0a );
+ temp1 = READ_WD_UCHAR( GC_Data );
+ WRITE_WD_UCHAR( GC_Data, (UCHAR)(temp1+1) );
+ temp2 = READ_WD_UCHAR( GC_Data );
+ WRITE_WD_UCHAR( GC_Data, temp1 );
+
+ if ((temp1+1) == temp2) {
+ status = FALSE;
+ goto NOT_WDVGA; // locked but writable
+ }
+
+ //
+ // check 3ce.09 after unlock
+ //
+
+ UnlockPR( pr5, NULL ); // lock it
+// WRITE_WD_USHORT( GC_Index, (pr5_unlock*0x100+pr5) ); // unlock
+
+ WRITE_WD_UCHAR( GC_Index, pr0a );
+ temp1 = READ_WD_UCHAR( GC_Data );
+ WRITE_WD_UCHAR( GC_Data, (UCHAR)(temp1+1) );
+ temp2 = READ_WD_UCHAR( GC_Data );
+ WRITE_WD_UCHAR( GC_Data, temp1 );
+
+ if ((temp1+1) != temp2) {
+ status = FALSE;
+ goto NOT_WDVGA; // unlocked but not-writable
+ }
+
+NOT_WDVGA:
+
+ //
+ // write 3ce.0c (post-process)
+ //
+
+ WRITE_WD_UCHAR( GC_Index, pr2 );
+ WRITE_WD_UCHAR( GC_Data, GraphSave0c);
+
+ RestorePR( pr5, &GraphSave0f );
+// WRITE_WD_UCHAR( GC_Index, pr5 );
+// WRITE_WD_UCHAR( GC_Data, GraphSave0f);
+
+ return status;
+
+}
+
+/*****************************************************************************/
diff --git a/private/ntos/nthals/halwood/ppc/x86bios.c b/private/ntos/nthals/halwood/ppc/x86bios.c
new file mode 100644
index 000000000..ba7969c5d
--- /dev/null
+++ b/private/ntos/nthals/halwood/ppc/x86bios.c
@@ -0,0 +1 @@
+#include "..\..\halppc\ppc\x86bios.c"
diff --git a/private/ntos/nthals/halwood/sources b/private/ntos/nthals/halwood/sources
new file mode 100644
index 000000000..3e401c82b
--- /dev/null
+++ b/private/ntos/nthals/halwood/sources
@@ -0,0 +1,103 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revision Histoy:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halwood
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+!IF $(PPC)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-DIDAHO -DSAM_256 -DWOODFIELD -D_HALNVR_
+
+INCLUDES=..\halppc\ppc;$(BASEDIR)\private\ntos\nthals\x86new;$(BASEDIR)\private\ntos\inc
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ bushnd.c \
+ rangesup.c \
+ drivesup.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxsiosup.c \
+ ppc\pxmemctl.c \
+ ppc\pxpcisup.c \
+ ppc\pxdisp.c \
+ ppc\pxshadbf.s \
+ ppc\pxs3.c \
+ ppc\pxwd.c \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxenviro.c \
+ ppc\pxmapio.c \
+ ppc\pxsysint.c \
+ ppc\pxtime.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxintsup.s \
+ ppc\pxinithl.c \
+ ppc\pxport.c \
+ ppc\pxpower.s \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\fwnvr.c \
+ ppc\pxinfo.c \
+ ppc\pxflshio.c \
+ ppc\pxintmod.c \
+ ppc\pxpcibrd.c \
+ ppc\pxintrpt.c \
+ ppc\x86bios.c
+
+DLLDEF=obj\*\hal.def
+
diff --git a/private/ntos/nthals/halws3/drivesup.c b/private/ntos/nthals/halws3/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halws3/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halws3/hal.rc b/private/ntos/nthals/halws3/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halws3/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halws3/hal.src b/private/ntos/nthals/halws3/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halws3/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halws3/i386/apic.inc b/private/ntos/nthals/halws3/i386/apic.inc
new file mode 100644
index 000000000..133cb8e8f
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/apic.inc
@@ -0,0 +1,556 @@
+;/*
+;++
+;
+; Copyright (c) 1992 Intel Corporation
+; All rights reserved
+;
+; INTEL CORPORATION PROPRIETARY INFORMATION
+;
+; This software is supplied to Microsoft under the terms
+; of a license agreement with Intel Corporation and may not be
+; copied nor disclosed except in accordance with the terms
+; of that agreement.
+;
+;
+; Module Name:
+;
+; apic.inc
+;
+; Abstract:
+;
+; This module contains the definitions used by HAL to manipulate
+; APIC interrupt controller and APIC-specific constants.
+;
+; WARNING: This file is included by both ASM and C files.
+;
+; Author:
+;
+; Hugh Bynum and Ron Mosgrove Aug-1992
+;
+;--
+if 0 ; Begin C only code */
+
+//
+// APIC defines for C code
+// BE SURE TO CHANGE THESE VALUES IN BOTH TABLES!
+//
+
+#define IO_BASE_ADDRESS 0xFEC00000 // Physical address
+#define IO_REGISTER_SELECT 0x00000000 // offset from IO_BASE_ADDRESS
+#define IO_REGISTER_WINDOW 0x00000010 // offset from IO_BASE_ADDRESS
+
+#define IO_UNIT_0 0x00000000 // adder for IO unit 0
+#define IO_UNIT_1 0x00001000 // adder for IO unit 1
+#define IO_UNIT_2 0x00002000 // adder for IO unit 2
+#define IO_UNIT_3 0x00003000 // adder for IO unit 3
+
+#define IO_ID_REGISTER 0x00000000
+#define IO_VERS_REGISTER 0x00000001
+#define IO_ARB_ID_REGISTER 0x00000002
+#define IO_REDIR_00_LOW 0x00000010
+#define IO_REDIR_00_HIGH 0x00000011
+
+#define IO_MAX_REDIR_MASK 0x00FF0000
+#define IO_VERSION_MASK 0x000000FF
+
+#define LU_BASE_ADDRESS 0xFEE00000 // Physical address
+#define LU_ID_REGISTER 0x00000020 // offset from LU_BASE_ADDRESS
+#define LU_VERS_REGISTER 0x00000030 // offset from LU_BASE_ADDRESS
+#define LU_TPR 0x00000080 // offset from LU_BASE_ADDRESS
+#define LU_APR 0x00000090 // offset from LU_BASE_ADDRESS
+#define LU_PPR 0x000000A0 // offset from LU_BASE_ADDRESS
+#define LU_EOI 0x000000B0 // offset from LU_BASE_ADDRESS
+#define LU_REMOTE_REGISTER 0x000000C0 // offset from LU_BASE_ADDRESS
+
+#define LU_LOGICAL_DEST 0x000000D0 // offset from LU_BASE_ADDRESS
+#define LU_LOGICAL_DEST_MASK 0xFF000000
+
+#define LU_DEST_FORMAT 0x000000E0 // offset from LU_BASE_ADDRESS
+#define LU_DEST_FORMAT_MASK 0xF0000000
+#define LU_DEST_FORMAT_FLAT 0xFFFFFFFF
+
+#define LU_SPURIOUS_VECTOR 0x000000F0 // offset from LU_BASE_ADDRESS
+#define LU_UNIT_ENABLED 0x00000100
+
+#define LU_ISR_0 0x00000100 // offset from LU_BASE_ADDRESS
+#define LU_TMR_0 0x00000180 // offset from LU_BASE_ADDRESS
+#define LU_IRR_0 0x00000200 // offset from LU_BASE_ADDRESS
+#define LU_ERROR_STATUS 0x00000280 // offset from LU_BASE_ADDRESS
+#define LU_INT_CMD_LOW 0x00000300 // offset from LU_BASE_ADDRESS
+#define LU_INT_CMD_HIGH 0x00000310 // offset from LU_BASE_ADDRESS
+#define LU_TIMER_VECTOR 0x00000320 // offset from LU_BASE_ADDRESS
+#define LU_INT_VECTOR_0 0x00000350 // TEMPORARY - do not use
+#define LU_INT_VECTOR_1 0x00000360 // TEMPORARY - do not use
+#define LU_INITIAL_COUNT 0x00000380 // offset from LU_BASE_ADDRESS
+#define LU_CURRENT_COUNT 0x00000390 // offset from LU_BASE_ADDRESS
+#define LU_DIVIDER_CONFIG 0x000003E0 // offset from LU_BASE_ADDRESS
+
+#define APIC_ID_MASK 0x0F000000
+#define APIC_ID_SHIFT 24
+
+#define INT_VECTOR_MASK 0x000000FF
+#define RESERVED_HIGH_INT 0x000000F8
+#define DELIVERY_MODE_MASK 0x00000700
+#define DELIVER_FIXED 0x00000000
+#define DELIVER_LOW_PRIORITY 0x00000100
+#define DELIVER_SMI 0x00000200
+#define DELIVER_REMOTE_READ 0x00000300
+#define DELIVER_NMI 0x00000400
+#define DELIVER_INIT 0x00000500
+#define DELIVER_EXTINT 0x00000700
+#define LOGICAL_DESTINATION 0x00000800
+#define DELIVERY_PENDING 0x00001000
+#define ACTIVE_LOW 0x00002000
+#define REMOTE_IRR 0x00004000
+#define LEVEL_TRIGGERED 0x00008000
+#define INTERRUPT_MASKED 0x00010000
+#define PERIODIC_TIMER 0x00020000
+
+#define ICR_LEVEL_ASSERTED 0x00004000
+#define ICR_RR_STATUS_MASK 0x00030000
+#define ICR_RR_INVALID 0x00000000
+#define ICR_RR_IN_PROGRESS 0x00010000
+#define ICR_RR_VALID 0x00020000
+#define ICR_SHORTHAND_MASK 0x000C0000
+#define ICR_USE_DEST_FIELD 0x00000000
+#define ICR_SELF 0x00040000
+#define ICR_ALL_INCL_SELF 0x00080000
+#define ICR_ALL_EXCL_SELF 0x000C0000
+
+#define DESTINATION_MASK 0xFF000000
+#define DESTINATION_SHIFT 24
+
+/*
+endif
+
+; APIC defines for assembly code
+; BE SURE TO CHANGE THESE VALUES IN BOTH TABLES!
+;
+
+IO_BASE_ADDRESS equ 0FEC00000H ; Physical address
+IO_REGISTER_SELECT equ 00000000H ; offset from IO_BASE_ADDRESS
+IO_REGISTER_WINDOW equ 00000010H ; offset from IO_BASE_ADDRESS
+
+IO_UNIT_0 equ 00000000H ; adder for IO unit 0
+IO_UNIT_1 equ 00001000H ; adder for IO unit 1
+IO_UNIT_2 equ 00002000H ; adder for IO unit 2
+IO_UNIT_3 equ 00003000H ; adder for IO unit 3
+
+IO_ID_REGISTER equ 00000000H ;
+IO_VERS_REGISTER equ 00000001H ;
+IO_ARB_ID_REGISTER equ 00000002H ;
+IO_REDIR_00_LOW equ 00000010H ;
+IO_REDIR_00_HIGH equ 00000011H ;
+
+IO_MAX_REDIR_MASK equ 00FF0000H ;
+IO_VERSION_MASK equ 000000FFH ;
+
+LU_BASE_ADDRESS equ 0FEE00000H ;
+LU_ID_REGISTER equ 00000020H ; offset from LU_BASE_ADDRESS
+LU_VERS_REGISTER equ 00000030H ; offset from LU_BASE_ADDRESS
+LU_TPR equ 00000080H ; offset from LU_BASE_ADDRESS
+LU_APR equ 00000090H ; offset from LU_BASE_ADDRESS
+LU_PPR equ 000000A0H ; offset from LU_BASE_ADDRESS
+LU_EOI equ 000000B0H ; offset from LU_BASE_ADDRESS
+LU_REMOTE_REGISTER equ 000000C0H ; offset from LU_BASE_ADDRESS
+
+LU_LOGICAL_DEST equ 000000D0H ; offset from LU_BASE_ADDRESS
+LU_LOGICAL_DEST_MASK equ 0FF000000H ;
+
+LU_DEST_FORMAT equ 000000E0H ; offset from LU_BASE_ADDRESS
+LU_DEST_FORMAT_MASK equ 0F0000000H ;
+LU_DEST_FORMAT_FLAT equ 0FFFFFFFFH ;
+
+LU_SPURIOUS_VECTOR equ 000000F0H ; offset from LU_BASE_ADDRESS
+LU_UNIT_ENABLED equ 00000100H ;
+
+LU_ISR_0 equ 00000100H ; offset from LU_BASE_ADDRESS
+LU_TMR_0 equ 00000180H ; offset from LU_BASE_ADDRESS
+LU_IRR_0 equ 00000200H ; offset from LU_BASE_ADDRESS
+LU_ERROR_STATUS equ 00000280H ; offset from LU_BASE_ADDRESS
+LU_INT_CMD_LOW equ 00000300H ; offset from LU_BASE_ADDRESS
+LU_INT_CMD_HIGH equ 00000310H ; offset from LU_BASE_ADDRESS
+LU_TIMER_VECTOR equ 00000320H ; offset from LU_BASE_ADDRESS
+LU_INT_VECTOR_0 equ 00000350H ; TEMPORARY - do not use
+LU_INT_VECTOR_1 equ 00000360H ; TEMPORARY - do not use
+LU_INITIAL_COUNT equ 00000380H ; offset from LU_BASE_ADDRESS
+LU_CURRENT_COUNT equ 00000390H ; offset from LU_BASE_ADDRESS
+
+LU_DIVIDER_CONFIG equ 000003E0H ; offset from LU_BASE_ADDRESS
+LU_DIVIDE_BY_1 equ 0000000BH ;
+LU_DIVIDE_BY_2 equ 00000000H ;
+LU_DIVIDE_BY_4 equ 00000001H ;
+LU_DIVIDE_BY_8 equ 00000002H ;
+LU_DIVIDE_BY_16 equ 00000003H ;
+LU_DIVIDE_BY_32 equ 00000008H ;
+LU_DIVIDE_BY_64 equ 00000009H ;
+LU_DIVIDE_BY_128 equ 0000000AH ;
+
+APIC_ID_MASK equ 0F000000H ;
+APIC_ID_SHIFT equ 24 ;
+
+INT_VECTOR_MASK equ 000000FFH ;
+RESERVED_HIGH_INT equ 000000F8H ;
+DELIVERY_MODE_MASK equ 00000700H ;
+DELIVER_FIXED equ 00000000H ;
+DELIVER_LOW_PRIORITY equ 00000100H ;
+DELIVER_SMI equ 00000200H ;
+DELIVER_REMOTE_READ equ 00000300H ;
+DELIVER_NMI equ 00000400H ;
+DELIVER_INIT equ 00000500H ;
+DELIVER_EXTINT equ 00000700H ;
+PHYSICAL_DESTINATION equ 00000000H ;
+LOGICAL_DESTINATION equ 00000800H ;
+DELIVERY_PENDING equ 00001000H ;
+ACTIVE_LOW equ 00002000H ;
+REMOTE_IRR equ 00004000H ;
+LEVEL_TRIGGERED equ 00008000H ;
+INTERRUPT_MASKED equ 00010000H ;
+INTERRUPT_MOT_MASKED equ 00000000H ;
+PERIODIC_TIMER equ 00020000H ;
+
+ICR_LEVEL_ASSERTED equ 00004000H ;
+ICR_RR_STATUS_MASK equ 00030000H ;
+ICR_RR_INVALID equ 00000000H ;
+ICR_RR_IN_PROGRESS equ 00010000H ;
+ICR_RR_VALID equ 00020000H ;
+ICR_SHORTHAND_MASK equ 000C0000H ;
+ICR_USE_DEST_FIELD equ 00000000H ;
+ICR_SELF equ 00040000H ;
+ICR_ALL_INCL_SELF equ 00080000H ;
+ICR_ALL_EXCL_SELF equ 000C0000H ;
+
+DESTINATION_MASK equ 0FF000000H ;
+DESTINATION_SHIFT equ 24 ; shift count for dest. mask
+
+;
+; remaining macro definitions for assembler only
+;
+
+;++
+;
+; WRITE_IO_APIC
+;
+; Macro Description:
+;
+; This macro writes a value to a register in the I/O Apic.
+;
+; Arguments:
+;
+; Register - Register to be written
+;
+; Value - Value to write
+;
+;--
+WRITE_IO_APIC MACRO Register , Value
+
+.errb <Register>
+.errb <Value>
+
+ ; Need two scratch registers
+ push eax ; Save registers
+ push ecx
+
+ push Value ; Save paramters on the stack
+ push Register
+
+ pop eax ; Get the Register
+ mov ecx, _HalpIOunitBase
+ add ecx, IO_REGISTER_SELECT+IO_UNIT_0 ; Register select on I/O Unit
+ mov dword ptr [ecx], eax ; Program register
+
+ pop eax ; Get the Value
+ mov ecx, _HalpIOunitBase
+ add ecx, IO_REGISTER_WINDOW+IO_UNIT_0 ; Register select on I/O Unit
+ mov dword ptr [ecx], eax ; Program register
+
+ pop ecx ; Restore scratch registers
+ pop eax
+
+ ; We're Out'a Here
+
+endm
+
+;++
+;
+; READ_IO_APIC
+;
+; Macro Description:
+;
+; This macro reads a 32 bit register from the I/O Apic.
+;
+; Arguments:
+;
+; Register - Register to be read
+;
+; Return
+;
+; eax - value read from I/O Apic
+;
+;--
+READ_IO_APIC MACRO Register
+
+.errb <Register>
+
+ifndef _HalpIOunitBase
+ extrn _HalpIOunitBase:DWORD
+endif
+
+ push ecx ; Need one scratch register
+ push Register
+
+ pop eax ; Get the Register
+ mov ecx, _HalpIOunitBase
+ add ecx, IO_REGISTER_SELECT+IO_UNIT_0 ; Register select on I/O Unit
+ mov dword ptr [ecx], eax ; Program register
+
+ mov ecx, _HalpIOunitBase
+ add ecx, IO_REGISTER_WINDOW+IO_UNIT_0 ; Register Window on I/O Unit
+ mov eax, dword ptr [ecx] ; Program register
+
+ pop ecx ; Restore scratch register
+
+ ; We're Out'a Here
+
+endm
+
+;++
+;
+; GetIOApicRedirTable
+;
+; Macro Description:
+;
+; This reads a redirection table entry from the I/O APIC (unit 0).
+;
+; Arguments:
+;
+; IoApicInputPin - Interrupt Input (INTI) we're interested in
+; The Caller MUST have locked access to the IO Apic prior to
+; this call.
+;
+; Return
+;
+; 64 Bit redirection table entry in eax [31:0] and edx [63:32]
+;
+;--
+GetIOApicRedirTable MACRO IoApicInputPin
+
+.errb <IoApicInputPin>
+
+ push IoApicInputPin ; Save paramter on the stack
+
+ pop eax ; INTI we're looking for
+ and eax, 0fh ; Make sure we're dealing with
+ ; defined inputs
+ shl eax, 1 ; <IoApicInputPin> * 2
+ add eax, IO_REDIR_00_LOW+IO_UNIT_0 ; eax == low(redir) of INTI
+
+ push eax ; Save the register address
+ inc eax ; Points to high(redir)
+
+ READ_IO_APIC eax ; Read the Upper 32 Bits of the Redir
+
+ mov edx, eax ; Save the High 32 Bits to return
+ pop eax ; Get the low register address
+
+ READ_IO_APIC eax ; Read the Lower 32 Bits of the Redir
+
+ ;
+ ; edx == bits 32-63 of RedirectionTable[IoApicInputPin]
+ ; eax == bits 00-31 of RedirectionTable[IoApicInputPin]
+ ;
+
+endm
+
+;++
+;
+; PutIOApicRedirTable
+;
+; Macro Description:
+;
+; This writes a redirection table entry to the I/O APIC (unit 0)..
+; The Caller MUST have locked access to the IO Apic prior to
+; this call.
+;
+; Arguments:
+;
+; IoApicInputPin - Interrupt Input (INTI) we're interested in
+;
+; LowWord - Low 32 Bits of redirection Table entry
+;
+; HighWord - High 32 Bits of redirection Table entry
+;
+;
+;--
+PutIOApicRedirTable MACRO IoApicInputPin , LowWord , HighWord
+
+.errb <IoApicInputPin>
+.errb <LowWord>
+.errb <HighWord>
+
+ push LowWord ; Save paramter on the stack
+ push HighWord
+ push IoApicInputPin
+
+ pop eax ; INTI we're looking for
+ and eax, 0fh ; Make sure we're dealing with
+ ; defined inputs
+ shl eax, 1 ; <IoApicInputPin> * 2
+ add eax, IO_REDIR_00_LOW+IO_UNIT_0 ; eax == low(redir) of INTI
+
+ pop edx ; edx <= Bits 31-63 of redir
+
+ push eax ; Save the register address
+ inc eax ; Points to high(redir)
+
+ WRITE_IO_APIC eax , edx ; Write the Upper 32 Bits of the Redir
+
+ pop eax ; Get the low register address
+ pop edx ; edx <= Bits 00-31 of redir
+
+ WRITE_IO_APIC eax , edx ; Write the Lower 32 Bits of the Redir
+
+endm
+
+;++
+;
+; GrabHalIoApicSpinLock
+;
+; Macro Description:
+;
+; This macro is used to prevent multiple CPU's from accessing the IO APIC on a MP
+; system. It grabs the IoAPIC Spin lock if available, ifnot then it waits until
+; it is available.
+;
+; The compliment of this macro is ReleaseHalIoApicSpinLock.
+;
+;--
+GrabHalIoApicSpinLock MACRO
+local WaitForRelease, StartSpinLockLoop, Gotit
+
+ifndef _HalpIOunitLock
+ extrn _HalpIOunitLock:DWORD ; IoUnit SpinLock
+endif ; _HalpIOunitLock
+
+StartSpinLockLoop:
+
+ pushfd ; Save Flags
+ cli ; Don't Interrupt us here
+
+ lea eax, _HalpIOunitLock ; The SpinLock we're interested in
+ ACQUIRE_SPINLOCK eax, WaitForRelease ; Try for the lock, if Not successful
+ ; Go and wait till the owner frees it.
+
+ ;
+ ; We now own the spinlock
+ ;
+
+ jmp Gotit
+
+WaitForRelease:
+ sti ; Allow other activity while we wait
+ SPIN_ON_SPINLOCK eax, StartSpinLockLoop ; Stare at it until it's free
+
+ ;
+ ; We'll Never get here
+ ;
+
+Gotit:
+
+ popfd ; restore Original Flags
+
+endm
+
+;++
+;
+; ReleaseHalIoApicSpinLock
+;
+; Macro Description:
+;
+; This macro is used to prevent multiple CPU's from accessing the IO Apic on a MP
+; system. It frees the IoApic Spin lock.
+;
+; The compliment of this macro is GrabHalIoApicSpinLock.
+;--
+ReleaseHalIoApicSpinLock MACRO
+
+ifndef _HalpIOunitLock
+ extrn _HalpIOunitLock:DWORD ; IoUnit SpinLock
+endif ; _HalpIOunitLock
+
+ lea eax, _HalpIOunitLock
+ RELEASE_SPINLOCK eax
+
+endm
+
+;++
+;
+; GrabHal8259SpinLock
+;
+; Macro Description:
+;
+; This macro is used to prevent multiple CPU's from accessing the IO APIC on a MP
+; system. It grabs the 8259 Spin lock if available, ifnot then it waits until
+; it is available.
+;
+; The compliment of this macro is ReleaseHal8259SpinLock.
+;
+;--
+GrabHal8259SpinLock MACRO
+local WaitForRelease, StartSpinLockLoop, Gotit
+
+ifndef _Halp8259Lock
+ extrn _Halp8259Lock:DWORD ; 8259 SpinLock
+endif ; _Halp8259Lock
+
+StartSpinLockLoop:
+
+ pushfd ; Save Flags
+ cli ; Don't Interrupt us here
+
+ lea eax, _Halp8259Lock ; The SpinLock we're interested in
+ ACQUIRE_SPINLOCK eax, WaitForRelease ; Try for the lock, if Not successful
+ ; Go and wait till the owner frees it.
+
+ ;
+ ; We now own the spinlock
+ ;
+
+ jmp Gotit
+
+WaitForRelease:
+ sti ; Allow other activity while we wait
+ SPIN_ON_SPINLOCK eax, StartSpinLockLoop ; Stare at it until it's free
+
+ ;
+ ; We'll Never get here
+ ;
+
+Gotit:
+
+ popfd ; restore Original Flags
+
+endm
+
+;++
+;
+; ReleaseHal8259SpinLock
+;
+; Macro Description:
+;
+; This macro is used to prevent multiple CPU's from accessing the IO Apic on a MP
+; system. It frees the 8259 Spin lock.
+;
+; The compliment of this macro is GrabHal8259SpinLock.
+;--
+ReleaseHal8259SpinLock MACRO
+
+ifndef _Halp8259Lock
+ extrn _Halp8259Lock:DWORD ; 8259 SpinLock
+endif ; _Halp8259Lock
+
+ lea eax, _Halp8259Lock
+ RELEASE_SPINLOCK eax
+
+endm
+;*/
diff --git a/private/ntos/nthals/halws3/i386/halp.h b/private/ntos/nthals/halws3/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halws3/i386/halver.h b/private/ntos/nthals/halws3/i386/halver.h
new file mode 100644
index 000000000..1c18a5540
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/halver.h
@@ -0,0 +1,42 @@
+/*++
+
+Module Name:
+
+ halver.h
+
+Abstract:
+
+ HAL WS3500 version file.
+
+ Update the version number and date in this file before each HAL release.
+ This file is maintained for the benefit of Microsoft builds of our
+ HAL source only. Sequent builds use halver.tmp to create halver.h
+ during the build process. (6/6/94 rlary)
+
+Author:
+
+ Phil Hochstetler (phil@sequent.com)
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#if defined(NT_UP)
+
+#if DBG
+UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL -DNT_UP -DDBG";
+#else
+UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL -DNT_UP";
+#endif
+
+#else // !defined(NT_UP)
+
+#if DBG
+UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL -DDBG";
+#else
+UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL";
+#endif
+
+#endif // defined(NT_UP)
diff --git a/private/ntos/nthals/halws3/i386/ix8259.inc b/private/ntos/nthals/halws3/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halws3/i386/ixbeep.asm b/private/ntos/nthals/halws3/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halws3/i386/ixbusdat.c b/private/ntos/nthals/halws3/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halws3/i386/ixcmos.asm b/private/ntos/nthals/halws3/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halws3/i386/ixcmos.inc b/private/ntos/nthals/halws3/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halws3/i386/ixdat.c b/private/ntos/nthals/halws3/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halws3/i386/ixenvirv.c b/private/ntos/nthals/halws3/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halws3/i386/ixfirm.c b/private/ntos/nthals/halws3/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halws3/i386/ixhwsup.c b/private/ntos/nthals/halws3/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halws3/i386/ixidle.asm b/private/ntos/nthals/halws3/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halws3/i386/ixinfo.c b/private/ntos/nthals/halws3/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halws3/i386/ixisabus.c b/private/ntos/nthals/halws3/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halws3/i386/ixisasup.c b/private/ntos/nthals/halws3/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halws3/i386/ixkdcom.c b/private/ntos/nthals/halws3/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halws3/i386/ixphwsup.c b/private/ntos/nthals/halws3/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halws3/i386/ixreboot.c b/private/ntos/nthals/halws3/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halws3/i386/ixthunk.c b/private/ntos/nthals/halws3/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halws3/i386/ixusage.c b/private/ntos/nthals/halws3/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halws3/i386/w3.inc b/private/ntos/nthals/halws3/i386/w3.inc
new file mode 100644
index 000000000..5eb27638d
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3.inc
@@ -0,0 +1,341 @@
+;/*
+;++
+;
+;Copyright (c) 1992 Sequent Computer Systems, Inc.
+;
+;Module Name:
+;
+; w3hal.h
+;
+;Abstract:
+;
+; This header file contains definitions for the WinServer 3000.
+;
+;Author:
+;
+; Phil Hochstetler (phil@sequent.com)
+;
+;Environment:
+;
+; Kernel mode only.
+;
+;Revision History:
+;
+;--
+if 0 ; Begin C only code */
+
+//
+// Interrupt vector definitions for C
+//
+
+#define APIC_APC_VECTOR 0x30
+#define APIC_DPC_VECTOR 0x40
+
+#define APIC_IRQ16_VECTOR 0x60
+#define APIC_IRQ17_VECTOR 0x61
+#define APIC_IRQ18_VECTOR 0x62
+#define APIC_IRQ19_VECTOR 0x63
+#define APIC_IRQ20_VECTOR 0x64
+#define APIC_IRQ21_VECTOR 0x65
+#define APIC_IRQ22_VECTOR 0x66
+#define APIC_IRQ23_VECTOR 0x67
+
+#define APIC_IRQ8_VECTOR 0x70
+#define APIC_IRQ9_VECTOR 0x71
+#define APIC_IRQ10_VECTOR 0x72
+#define APIC_IRQ11_VECTOR 0x73
+#define APIC_IRQ12_VECTOR 0x74
+#define APIC_IRQ13_VECTOR 0x75
+#define APIC_IRQ14_VECTOR 0x76
+#define APIC_IRQ15_VECTOR 0x77
+
+#define APIC_IRQ0_VECTOR 0x80
+#define APIC_IRQ1_VECTOR 0x81
+#define APIC_IRQ2_VECTOR 0x82
+#define APIC_IRQ3_VECTOR 0x83
+#define APIC_IRQ4_VECTOR 0x84
+#define APIC_IRQ5_VECTOR 0x85
+#define APIC_IRQ6_VECTOR 0x86
+#define APIC_IRQ7_VECTOR 0x87
+
+#define APIC_RTC_VECTOR 0x70
+#define APIC_MOUSE_VECTOR 0x74
+#define APIC_DMA_VECTOR 0x75
+#define APIC_IDE_VECTOR 0x76
+#define APIC_KBD_VECTOR 0x81
+#define APIC_FLOPPY_VECTOR 0x86
+
+#define APIC_PROFILE_VECTOR 0x90
+#define APIC_CLOCK_VECTOR 0xA0
+#define APIC_IPI_VECTOR 0xB0
+#define APIC_POWERFAIL_VECTOR 0xC0
+#define EISA_CLOCK_VECTOR 0xD0
+#define EISA_KBD_VECTOR 0xD1
+#define EISA_IRQ2_VECTOR 0xD2
+#define EISA_FLOPPY_VECTOR 0xD6
+#define EISA_PIC1_SPURIOUS_VECTOR 0xD7
+#define EISA_RTC_VECTOR 0xD8
+#define EISA_MOUSE_VECTOR 0xDC
+#define EISA_DMA_VECTOR 0xDD
+#define EISA_IDE_VECTOR 0xDE
+#define EISA_PIC2_SPURIOUS_VECTOR 0xDF
+#define APIC_SPURIOUS_VECTOR 0xE0
+#define APIC_SYSINT_VECTOR 0xE1
+#define APIC_HIGH_VECTOR 0xF0
+#define APIC_STALL_VECTOR 0xF8
+
+
+#define PIC0_BASE_VECTOR EISA_CLOCK_VECTOR
+#define PIC1_BASE_VECTOR EISA_RTC_VECTOR
+
+#define EISA_SHIFT 12 // EISA slot starts at this offset
+#define EISA_MASK 0xfff // Low bits of EISA slot address
+#define POSTREGISTERPORT 0x80 // BIOS post register
+#define OCW2_SPECIFIC_EOI 0x60
+#define OCW2_NON_SPECIFIC_EOI 0x20
+#define PIC1_PORT0 0x20
+#define PIC1_PORT1 0x21
+#define PIC2_PORT0 0xA0
+#define PIC2_PORT1 0xA1
+#define PIC3_PORT0 0xCC0
+#define PIC3_PORT1 0xCC1
+#define EISA_2_MPIC_POLARITY_REG 0x0C0E
+#define ELCR_MASK 0xDEF8
+#define PIC1_ELCR_PORT 0x04D0
+#define PIC2_ELCR_PORT 0x04D1
+#define DESTINATION_ALL_CPUS 0xff
+#define DESTINATION_CPU_0 0x01
+#define FCR 0x0C84
+#define WarmResetVector 0x467
+#define FCR_RESET_MASK 0x0080
+#define IOMPIC_RT_MASK 0x10000
+#define FIRST_SYSTEM_SLOT 9
+#define LAST_SYSTEM_SLOT 15
+#define SLOT_ID_REG 0x0C80
+#define SLOT_ID_BOARDTYPE 0x00F00000
+#define SLOT_ID_TYPECPU 0x00100000
+#define IOUNIT_APIC_ID 7
+#define IOUNIT2_APIC_ID 8
+#define D_INT032 8E00h
+#define PeriodInUsec 200
+
+
+
+#define IRQL_APIC_KBD 25
+#define IRQL_APIC_FLOPPY 21
+#define IRQL_APIC_RTC 19
+#define IRQL_APIC_DMA 14
+#define IRQL_APIC_IDE 13
+#define IRQL_APIC_MOUSE 15
+
+//
+// Hal private data structures (max 64 bytes in length)
+//
+
+typedef struct _WS3_HAL_PRIVATE {
+ UCHAR PcrNumber; // Logical Processor Number
+ UCHAR ProcLightState; // State of Processor light (1=on,0=off)
+ UCHAR ProcIrql; // Current IRQL
+ UCHAR ProcPad1; // Reserved (for padding)
+ USHORT ProcSlotAddr; // (slot << EISA_SHIFT)
+ USHORT ProcPad2; // Reserved (for padding)
+} WS3_HAL_PRIVATE, *PWS3_HAL_PRIVATE;
+
+/*
+endif
+
+; Start of Assembly only code
+
+;
+; Interrupt vector definitions for ASM
+;
+
+APIC_APC_VECTOR equ 030h
+APIC_DPC_VECTOR equ 040h
+
+APIC_IRQ16_VECTOR equ 060h
+APIC_IRQ17_VECTOR equ 061h
+APIC_IRQ18_VECTOR equ 062h
+APIC_IRQ19_VECTOR equ 063h
+APIC_IRQ20_VECTOR equ 064h
+APIC_IRQ21_VECTOR equ 065h
+APIC_IRQ22_VECTOR equ 066h
+APIC_IRQ23_VECTOR equ 067h
+
+APIC_IRQ8_VECTOR equ 070h
+APIC_IRQ9_VECTOR equ 071h
+APIC_IRQ10_VECTOR equ 072h
+APIC_IRQ11_VECTOR equ 073h
+APIC_IRQ12_VECTOR equ 074h
+APIC_IRQ13_VECTOR equ 075h
+APIC_IRQ14_VECTOR equ 076h
+APIC_IRQ15_VECTOR equ 077h
+
+APIC_IRQ0_VECTOR equ 080h
+APIC_IRQ1_VECTOR equ 081h
+APIC_IRQ2_VECTOR equ 082h
+APIC_IRQ3_VECTOR equ 083h
+APIC_IRQ4_VECTOR equ 084h
+APIC_IRQ5_VECTOR equ 085h
+APIC_IRQ6_VECTOR equ 086h
+APIC_IRQ7_VECTOR equ 087h
+
+APIC_RTC_VECTOR equ 070h
+APIC_MOUSE_VECTOR equ 074h
+APIC_DMA_VECTOR equ 075h
+APIC_IDE_VECTOR equ 076h
+APIC_KBD_VECTOR equ 081h
+APIC_FLOPPY_VECTOR equ 086h
+
+APIC_PROFILE_VECTOR equ 090h
+APIC_CLOCK_VECTOR equ 0A0h
+APIC_IPI_VECTOR equ 0B0h
+APIC_POWERFAIL_VECTOR equ 0C0h
+EISA_CLOCK_VECTOR equ 0D0h
+EISA_KBD_VECTOR equ 0D1h
+EISA_IRQ2_VECTOR equ 0D2h
+EISA_FLOPPY_VECTOR equ 0D6h
+EISA_PIC1_SPURIOUS_VECTOR equ 0D7h
+EISA_RTC_VECTOR equ 0D8h
+EISA_MOUSE_VECTOR equ 0DCh
+EISA_DMA_VECTOR equ 0DDh
+EISA_IDE_VECTOR equ 0DEh
+EISA_PIC2_SPURIOUS_VECTOR equ 0DFh
+APIC_SPURIOUS_VECTOR equ 0E0h
+APIC_SYSINT_VECTOR equ 0E1h
+APIC_HIGH_VECTOR equ 0F0h
+APIC_STALL_VECTOR equ 0F8h
+
+PIC0_BASE_VECTOR equ EISA_CLOCK_VECTOR
+PIC1_BASE_VECTOR equ EISA_RTC_VECTOR
+
+
+EISA_SHIFT equ 12 ; EISA slot starts at this offset
+EISA_MASK equ 0fffh ; Low bits of EISA slot address
+PostRegisterPort equ 080h ; BIOS post register
+OCW2_SPECIFIC_EOI equ 060h
+OCW2_NON_SPECIFIC_EOI equ 020h
+PIC1_PORT0 equ 020h
+PIC1_PORT1 equ 021h
+PIC2_PORT0 equ 0A0h
+PIC2_PORT1 equ 0A1h
+PIC3_PORT0 equ 0CC0h
+PIC3_PORT1 equ 0CC1h
+EISA_2_MPIC_POLARITY_REG equ 0C0Eh
+ELCR_MASK equ 0DEF8h
+PIC1_ELCR_PORT equ 04D0h
+PIC2_ELCR_PORT equ 04D1h
+DESTINATION_ALL_CPUS equ 0ffh
+DESTINATION_CPU_0 equ 1
+FCR equ 0C84h
+WarmResetVector equ 0467h
+FCR_RESET_MASK equ 0080h
+IOMPIC_RT_MASK equ 10000h
+FIRST_SYSTEM_SLOT equ 9
+LAST_SYSTEM_SLOT equ 15
+SLOT_ID_REG equ 0C80h
+SLOT_ID_BOARDTYPE equ 00F00000h
+SLOT_ID_TYPECPU equ 00100000h
+IOUNIT_APIC_ID equ 7
+IOUNIT2_APIC_ID equ 8
+D_INT032 equ 8E00h ; access word for 386 ring 0 interrupt gate
+PeriodInUsec equ 200
+
+
+IRQL_APIC_KBD equ 25
+IRQL_APIC_FLOPPY equ 21
+IRQL_APIC_RTC equ 19
+IRQL_APIC_DMA equ 14
+IRQL_APIC_IDE equ 13
+IRQL_APIC_MOUSE equ 15
+
+;
+; The kernel leaves some space (64 bytes) of the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation-dependent.
+; Must match the preceeding C structure.
+
+PcrE struc
+ PcrNumber db 0 ; Processor's number
+ ProcLightState db 0 ; State of Processor light
+ ProcIrql db 0 ; Current IRQL
+ ProcPad1 db 0 ; Reserved (for padding)
+ ProcSlotAddr dw 0 ; Slot (9-15) << 12
+ ProcPad2 dw 0 ; Reserved (for padding)
+PcrE ends
+
+CR equ 0dh
+LF equ 0ah
+
+IoDelay macro
+ push eax
+ in al, 020h
+ pop eax
+endm
+
+SET_8259_MASK macro
+ out PIC1_PORT1, al ; set master 8259 mask
+ shr eax, 8 ; shift slave 8259 mask to al
+ out PIC2_PORT1, al ; set slave 8259 mask
+endm
+
+PIC1DELAY macro
+ in al, PIC1_PORT1
+endm
+
+PIC2DELAY macro
+ in al, PIC2_PORT1
+endm
+
+DISABLE_INTERRUPTS_AT_CPU macro
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+endm
+
+RESTORE_INTERRUPTS_AT_CPU macro
+ popfd ; restore original interrupt mode
+endm
+
+;++
+;
+; SOFT_INTERRUPT_EXIT
+;
+; Macro Description:
+;
+; This macro is executed on return from the soft interrupt
+; service routine. Its function is to restore privileged processor
+; state, and continue thread execution.
+;
+; Arguments:
+;
+; (TOS) = previous irql
+; (TOS+4 ...) = machine_state frame
+;
+;--
+
+SOFT_INTERRUPT_EXIT macro
+
+ EXTRNP _KeLowerIrql,1
+ cli
+ call _KeLowerIrql@4 ; restore irql
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI
+endm
+
+; Macro for programming IDT entries directly
+
+IDTEntry macro Vector, Handler
+ sub esp, 8 ; allocate temp stack space
+ sidt fword ptr [esp] ; IDT base + limit
+ mov edx, [esp+2] ; IDT linear base address
+ mov ecx, Vector ; get Vector
+ mov eax, offset FLAT:Handler ; Get Handler
+ mov word ptr [edx+8*ecx], ax ; Lower half of handler addr
+ mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*ecx+6], ax
+ add esp, 8 ; deallocate temp stack space
+endm
+
+; End of Assembly only code
+;*/
diff --git a/private/ntos/nthals/halws3/i386/w3clock.asm b/private/ntos/nthals/halws3/i386/w3clock.asm
new file mode 100644
index 000000000..b45761307
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3clock.asm
@@ -0,0 +1,782 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3clock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com)
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\ixcmos.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ extrn _HalpLocalUnitBase:DWORD
+ extrn _HalpW3PostRegisterImage:DWORD
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER2_DATA_PORT0 EQU 48H ; Timer1, channel 0 data port
+TIMER2_CONTROL_PORT0 EQU 4BH ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193182
+
+;
+; ==== Values used for System Clock ====
+;
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+_Halp8254Lock dd 0
+
+
+ public HalpPerfCounterLow, HalpPerfCounterHigh
+ public HalpLastPerfCounterLow, HalpLastPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpLastPerfCounterLow dd 0
+HalpLastPerfCounterHigh dd 0
+
+
+ public HalpCurrentRollOver, HalpCurrentTimeIncrement
+HalpCurrentRollOver dd 0
+HalpCurrentTimeIncrement dd 0
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec.
+;
+;
+; The best fit value closest to 10ms is 10.0144012689ms:
+; ROLLOVER_COUNT 11949
+; TIME_INCREMENT 100144
+; Calculated error is -.0109472 s/day
+;
+;
+; The following table contains 8254 values timer values to use at
+; any given ms setting from 1ms - 15ms. All values work out to the
+; same error per day (-.0109472 s/day).
+;
+
+ public HalpRollOverTable
+
+ ; RollOver Time
+ ; Count Increment MS
+HalpRollOverTable dd 1197, 10032 ; 1ms
+ dd 2394, 20064 ; 2 ms
+ dd 3591, 30096 ; 3 ms
+ dd 4767, 39952 ; 4 ms
+ dd 5964, 49984 ; 5 ms
+ dd 7161, 60016 ; 6 ms
+ dd 8358, 70048 ; 7 ms
+ dd 9555, 80080 ; 8 ms
+ dd 10731, 89936 ; 9 ms
+ dd 11949, 100144 ; 10 ms
+ dd 13125, 110000 ; 11 ms
+ dd 14322, 120032 ; 12 ms
+ dd 15519, 130064 ; 13 ms
+ dd 16695, 139920 ; 14 ms
+ dd 17892, 149952 ; 15 ms
+
+TimeIncr equ 4
+RollOver equ 0
+
+ public HalpLargestClockMS, HalpNextMSRate, HalpPendingMSRate
+HalpLargestClockMS dd 15 ; Table goes to 15MS
+HalpNextMSRate dd 0
+HalpPendingMSRate dd 0
+
+
+_DATA ends
+
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 10ms interval at EISA_CLOCK_VECTOR
+;
+; The Eisa clock interrupt handler then IPIs all processors at
+; APIC_CLOCK_VECTOR
+;
+; See the definitions of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; This routine assumes it runs during Phase 0 on P0.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock ,0
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbCpuType, 4 ; 486 or better?
+ jc short @f ; no, skip
+
+ mov HalpLargestClockMS, 10 ; Limit 486's to 10MS
+@@:
+ mov eax, HalpLargestClockMS
+ mov ecx, HalpRollOverTable.TimeIncr
+ mov edx, HalpRollOverTable[eax*8-8].TimeIncr
+ mov eax, HalpRollOverTable[eax*8-8].RollOver
+
+ mov HalpCurrentTimeIncrement, edx
+
+;
+; (ecx) = Min time_incr
+; (edx) = Max time_incr
+; (eax) = max roll over count
+;
+
+ push eax
+ stdCall _KeSetTimeIncrement, <edx, ecx>
+ pop ecx
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+; (ecx) = RollOverCount
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+ mov HalpCurrentRollOver, ecx ; Set RollOverCount & initialized
+
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+INIT ends
+
+_TEXT$03 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter ,1
+cPublicFpo 1, 0
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before Timer
+; initialization has occured. Reading garbage off the Timer is not reasonable.
+;
+ cmp HalpCurrentRollOver, 0
+ je Kqpc50
+
+ push ebx
+ push esi
+
+Kqpc01: pushfd
+ cli
+Kqpc20:
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+endif
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+
+@@:
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+ cmp ebx, HalpPerfCounterLow
+ jne @b
+
+;
+; Fetch the current counter value from the hardware
+;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IoDelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ IoDelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+endif
+
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+
+ jmp $+2 ; allow interrupt in case counter
+ ; has wrapped
+
+ pushfd
+ cli
+
+;
+; Fetch the base value again.
+;
+
+@@:
+ mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+
+ cmp eax, HalpPerfCounterLow
+ jne @b
+;
+; Compare the two reads of Performance counter. If they are different,
+; start over
+;
+
+ cmp eax, ebx
+ jne Kqpc20
+ cmp edx, esi
+ jne Kqpc20
+
+ neg ecx ; PIT counts down from 0h
+ add ecx, HalpCurrentRollOver
+ jnc short Kqpc60
+
+Kqpc30:
+ add eax, ecx
+ adc edx, 0 ; [edx:eax] = Final result
+
+ cmp edx, HalpLastPerfCounterHigh
+ jc short Kqpc70 ; jmp if edx < lastperfcounterhigh
+ jne short Kqpc35 ; jmp if edx > lastperfcounterhigh
+
+ cmp eax, HalpLastPerfCounterLow
+ jc short Kqpc70 ; jmp if eax < lastperfcounterlow
+
+Kqpc35:
+ mov HalpLastPerfCounterLow, eax
+ mov HalpLastPerfCounterHigh, edx
+
+ popfd ; restore interrupt flag
+
+
+;
+; Return the freq. if caller wants it.
+;
+ cmp dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc40 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc40:
+ pop esi ; restore esi and ebx
+ pop ebx
+ stdRET _KeQueryPerformanceCounter
+
+Kqpc50:
+; Initialization hasn't occured yet, so just return zeroes.
+ mov eax, 0
+ mov edx, 0
+ stdRET _KeQueryPerformanceCounter
+
+Kqpc60:
+;
+; The current count is larger then the HalpCurrentRollOver. The only way
+; that could happen is if there is an interrupt in route to the processor
+; but it was not processed while interrupts were enabled.
+;
+ mov esi, [esp] ; (esi) = flags
+ mov ecx, HalpCurrentRollOver ; (ecx) = max possible value
+ popfd ; restore flags
+
+ test esi, EFLAGS_INTERRUPT_MASK
+ jnz Kqpc01 ; ints are enabled, problem should go away
+
+ pushfd ; fix stack
+ jmp short Kqpc30 ; ints are disabled, use max count (ecx)
+
+Kqpc70:
+;
+; The current count is smaller then the last returned count. The only way
+; this should occur is if there is an interrupt in route to the processor
+; which was not been processed.
+;
+
+ mov ebx, HalpLastPerfCounterLow
+ mov esi, HalpLastPerfCounterHigh
+
+ mov ecx, ebx
+ or ecx, esi ; is last returned value 0?
+ jz short Kqpc35 ; Yes, then just return what we have
+
+ ; sanity check - make sure count is not off by bogus amount
+ sub ebx, eax
+ sbb esi, edx
+ jnz short Kqpc75 ; off by bogus amount
+ cmp ebx, HalpCurrentRollOver
+ jg short Kqpc75 ; off by bogus amount
+
+ sub eax, ebx
+ sbb edx, esi ; (edx:eax) = last returned count
+
+ mov ecx, [esp] ; (ecx) = flags
+ popfd
+
+ test ecx, EFLAGS_INTERRUPT_MASK
+ jnz Kqpc01 ; ints enabled, problem should go away
+
+ pushfd ; fix stack
+ jmp Kqpc35 ; ints disabled, just return last count
+
+Kqpc75:
+ popfd
+ xor eax, eax ; reset bogus values
+ mov HalpLastPerfCounterLow, eax
+ mov HalpLastPerfCounterHigh, eax
+ jmp Kqpc01 ; go try again
+
+ifndef NT_UP
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc01>
+endif
+
+stdENDP _KeQueryPerformanceCounter
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+cPublicFpo 1, 0
+
+ mov eax, [esp+4] ; ponter to Number
+cPublicFpo 1, 1
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ ;
+ ; Nothing to calibrate on this apic based MP machine. There is only
+ ; a single 8254 device in use
+ ;
+
+cPublicFpo 1, 0
+ popfd ; restore interrupt flag
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+; dismiss interrupt and raise Irql
+;
+
+ push APIC_CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,APIC_CLOCK_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; Turn off (on) the processor active light to reflect whether
+; we are (are not) currently executing the Idle Thread.
+;
+
+ mov edi, PCR[PcPrcb] ; (edi) -> Prcb
+ mov eax, [edi].PbCurrentThread
+ cmp eax, [edi].PbIdleThread ; running idle thread?
+ setnz al ; set al to desired light state
+ cmp al, byte ptr PCR[PcHal.ProcLightState]
+ jne Hci05
+Hci10:
+
+ifndef NT_UP
+ cmp byte ptr PCR[PcHal.PcrNumber], 0 ; Only P0 Will update System Time
+ je Do_P0Timer
+
+ ;
+ ; All processors will update RunTime for current thread
+ ;
+
+ sti
+ ; TOS const PreviousIrql
+ stdCall _KeUpdateRunTime,<dword ptr [esp]>
+
+ INTERRUPT_EXIT ; lower irql to old value, iret
+
+ ;
+ ; We don't return here
+ ;
+
+
+Do_P0Timer:
+
+endif
+
+;
+; Update front panel light show
+;
+ mov eax, _HalpW3PostRegisterImage ; get current bits
+ and al, 01111111b ; clear disk error bit
+ out PostRegisterPort, al ; write PostCode Reg
+
+;
+; Update performance counter
+;
+
+ mov eax, HalpCurrentRollOver
+ add HalpPerfCounterLow, eax ; update performace counter
+ adc HalpPerfCounterHigh, dword ptr 0
+
+ mov eax, HalpCurrentTimeIncrement
+Hci30:
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; ebp = trap frame
+; eax = time increment
+;
+ cmp HalpNextMSRate, 0 ; New clock rate desired?
+ jz _KeUpdateSystemTime@0 ; No, process tick
+
+;
+; Time of clock frequency is being changed. See if the 8254 was
+; was reprogrammed for a new rate during last tick
+;
+ cmp HalpPendingMSRate, 0 ; Was a new rate set durning last
+ jnz short Hci50 ; tick? Yes, go update globals
+
+Hci40:
+; (eax) = time increment for current tick
+
+;
+; A new clock rate needs to be set. Setting the rate here will
+; cause the tick after the next tick to be at the new rate.
+; (the next tick is already in progress by the 8254 and will occur
+; at the same rate as this tick)
+;
+Kci01: pushfd
+ cli
+ifndef NT_UP
+ lea ecx, _Halp8254Lock
+ ACQUIRE_SPINLOCK ecx, Kci198
+endif
+ mov ebx, HalpNextMSRate
+ mov HalpPendingMSRate, ebx ; pending rate
+
+ mov ecx, HalpRollOverTable[ebx*8-8].RollOver
+
+;
+; Set clock rate
+; (ecx) = RollOverCount
+;
+
+ push eax ; save current tick's rate
+
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+endif
+
+ pop eax
+ popfd
+ jmp Hci30 ; dispatch this tick
+
+Hci50:
+;
+; The next tick will occur at the rate which was programmed during the last
+; tick. Update globals for new rate which starts with the next tick.
+;
+; (eax) = time increment for current tick
+;
+ mov ebx, HalpPendingMSRate
+ mov ecx, HalpRollOverTable[ebx*8-8].RollOver
+ mov edx, HalpRollOverTable[ebx*8-8].TimeIncr
+
+ mov HalpCurrentRollOver, ecx
+ mov HalpCurrentTimeIncrement, edx ; next tick rate
+ mov HalpPendingMSRate, 0 ; no longer pending, clear it
+
+ cmp ebx, HalpNextMSRate ; new rate == NextRate?
+ jne Hci40 ; no, go set new pending rate
+
+ mov HalpNextMSRate, 0 ; we are at this rate, clear it
+ jmp Hci30 ; process this tick
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+ifndef NT_UP
+Kci198: popfd
+ SPIN_ON_SPINLOCK ecx,<Kqpc01>
+endif
+
+;
+; Update the state of hardware lights and state variable
+;
+Hci05:
+ cmp al, 1 ; identify light going
+ je Hci06 ; on (or going off)
+
+; Turn light off that was on
+
+ xor eax, eax
+ mov al, byte ptr PCR[PcHal.PcrNumber] ; get processor number
+ lock btr _HalpW3PostRegisterImage, eax ; clear the bit
+ mov byte ptr PCR[PcHal.ProcLightState], 0 ; update flag
+ jmp hci10 ; return
+
+; Turn light on that was off
+Hci06:
+ xor eax, eax
+ mov al, byte ptr PCR[PcHal.PcrNumber] ; get processor number
+ lock bts _HalpW3PostRegisterImage, eax ; set the bit
+ mov byte ptr PCR[PcHal.ProcLightState], 1 ; update flag
+ jmp hci10 ; return
+
+stdENDP _HalpClockInterrupt
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, [esp+4] ; desired setting
+ xor edx, edx
+ mov ecx, 10000
+ div ecx ; round to MS
+
+ cmp eax, HalpLargestClockMS ; MS > max?
+ jc short @f
+ mov eax, HalpLargestClockMS ; yes, use max
+@@:
+ or eax, eax ; MS < min?
+ jnz short @f
+ inc eax ; yes, use min
+@@:
+ mov HalpNextMSRate, eax
+
+ mov eax, HalpRollOverTable[eax*8-8].TimeIncr
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+_TEXT$03 ends
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3detect.asm b/private/ntos/nthals/halws3/i386/w3detect.asm
new file mode 100644
index 000000000..0a77c4b3b
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3detect.asm
@@ -0,0 +1,106 @@
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+; Copyright (c) 1993,1994 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3detect.asm
+;
+; Abstract:
+;
+; This module detects a Sequent WinServer 3000. It is included
+; by w3ipi.asm and the setup program. It must assemble more or less
+; standalone and run in protected mode.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Revision History:
+;
+;--
+
+include callconv.inc
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+; W3SystemType: SystemType is read from 0c80-0c83.
+;
+; 0c80-0c81: Compressed "TRI" (5 bit encoding).
+; 0c82: System Board Type.
+; 0c83: System Board Revision Level.
+
+
+W3SystemTypeTable db 052h, 049h, 08h, 00h
+W3SystemType db 5 dup(0)
+
+_DATA ends
+
+ page ,132
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; ULONG
+; DetectWS3000(
+; OUT PBOOLEAN IsConfiguredMp
+; );
+;
+; Routine Description:
+; Determines the type of system (specifically for eisa machine), by reading
+; the system board system ID. It compares the 4 bytes of the ID, to
+; a predefined table <W3SystemTypeTable> and returns the index to the
+; found entry.
+;
+; Arguments:
+; IsConfiguredMp - If detected, then this value is
+; set to TRUE if it's an MP system, else FALSE.
+;
+; Return Value:
+;
+; A value of 1 is returned if a WS3000 machine is detected.
+; Otherwise a value of 0 is returned.
+;--
+cPublicProc _DetectWS3000 ,1
+cPublicFpo 1, 3
+
+ push edi
+ push esi
+ push ebx ; Save C Runtime
+
+ ; A 4 byte value is read from 0c80-0c83, and saved in <W3SystemType>.
+ ; This value is compared to the first 3 bytes of the value in
+ ; <W3SystemTypeTable>.
+
+ cld ; set direction to forward
+ lea edi, W3SystemType
+ mov edx, 0c80h
+ insb ; 52h
+ inc edx
+ insb ; 49h
+ inc edx
+ insb ; 08h - System Board Type
+ inc edx
+ insb ; 00h - Revision Level
+
+ xor eax, eax ; default to return failure
+ lea edi, W3SystemTypeTable ; Type Table
+ mov ecx, 3 ; bytes to compare against
+ lea esi, W3SystemType ; match string against table entry
+ repe cmpsb ; if (ecx == 0 and ZF set)
+ jnz @f ; we have a winner
+ inc al
+ mov ebx, dword ptr [esp+16]
+ mov byte ptr [ebx], 1 ; *IsConfiguredMp = TRUE
+
+@@:
+ pop ebx
+ pop esi
+ pop edi ; Restore C Runtime
+
+ stdRET _DetectWS3000
+
+stdENDP _DetectWS3000
+
+_TEXT ENDS
diff --git a/private/ntos/nthals/halws3/i386/w3hal.c b/private/ntos/nthals/halws3/i386/w3hal.c
new file mode 100644
index 000000000..a0476e92b
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3hal.c
@@ -0,0 +1,660 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993,1994 Sequent Computer Systems, Inc.
+
+Module Name:
+
+ w3hal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Author:
+
+ Phil Hochstetler (phil@sequent.com)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "w3.inc"
+
+UCHAR SequentCopyright[] = "\n\n\
+Copyright (c) 1993,1994\n\
+Sequent Computer Systems, Inc. All rights reserved.\n\
+ \n\
+This software is furnished under a license and may be used\n\
+only in accordance with the terms of that license and with the\n\
+inclusion of the above copyright notice. This software may not\n\
+be provided or otherwise made available to, or used by, any\n\
+other person. No title to or ownership of the software is\n\
+hereby transferred.\n\n";
+
+ULONG HalpBusType;
+ULONG ProcessorsPresent;
+
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+
+ADDRESS_USAGE HalpW3IoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x800, 0x100, // EISA CMOS Page
+ 0xC00, 0x10, // SBC
+ 0xC10, 0x10, // EISA Page Select
+ 0xC20, 0x10, // LCD
+ 0xC30, 0x10, // Cache Flush
+ 0xC80, 0x4, // EISA SBID
+ 0xC84, 0x4, // EISA SBE
+ 0xCC0, 0x2, // PIC 3
+ 0xCC2, 0x3E, // Reserved
+ 0,0
+ }
+};
+
+#ifdef NT_UP
+
+UCHAR UPWarn[] = "\
+HAL: Incorrect system configuration.\n\
+HAL: Uniprocessor HAL.DLL and NTOSKRNL.EXE are running\n\
+HAL: on a system that contains more than one processor.\n\
+HAL: Please install multiprocessor HAL.DLL and NTOSKRNL.EXE to correct.\n\
+HAL: Only using 1 processor to allow system boot to continue.\n";
+
+#else
+
+UCHAR MPWarn[] = "\
+HAL: Incorrect system configuration.\n\
+HAL: Multiprocessor HAL.DLL and NTOSKRNL.EXE are running\n\
+HAL: on a system that contains only one processor.\n\
+HAL: Please install uniprocessor HAL.DLL and NTOSKRNL.EXE to correct.\n";
+
+#endif
+
+#ifndef NT_UP
+ULONG
+HalpInitMP(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+#endif
+
+KSPIN_LOCK HalpSystemHardwareLock;
+
+VOID
+HalpIpiHandler(
+ VOID
+ );
+
+USHORT
+HalpMySlotAddr(
+ );
+
+VOID
+HalpSetProcessorsPresent(
+ );
+
+//
+// CAUTION!! these local vector definitions must match those in w3.inc
+// these are included to avoid conflicts with vectors defined in ix8259.inc
+// (which is included by halp.h)
+//
+#define APIC_PROFILE_VECTOR 0x90
+#define APIC_CLOCK_VECTOR 0xA0
+#define APIC_IPI_VECTOR 0xB0
+
+#define KB_STAT 0x64 // keyboard controller status
+#define KB_IDAT 0x60 // input buffer data write
+#define KB_OUTBF 0x01 // output buffer full
+
+extern UCHAR HalName[];
+extern PKPCR HalpProcessorPCR[];
+
+
+VOID
+HalpGetUserInput (
+ )
+
+{
+ UCHAR i, j;
+ UCHAR byte;
+ UCHAR OldPicMask;
+
+ //
+ // Mask keyboard interrupt directly at the PIC
+ //
+ OldPicMask = READ_PORT_UCHAR((PUCHAR) 0x21);
+ WRITE_PORT_UCHAR((PUCHAR) 0x21, (UCHAR)(OldPicMask | 1));
+
+ j = 1;
+ do {
+ for (i = 0; i < 50; i++) {
+ // flush all keyboard input
+ if (READ_PORT_UCHAR((PUCHAR) KB_STAT) & KB_OUTBF)
+ byte = READ_PORT_UCHAR((PUCHAR) KB_IDAT); // read scan code
+ KeStallExecutionProcessor(1000); // delay 1 ms
+ }
+ if (j == 1) {
+ HalDisplayString("HAL: Press any key to continue ...");
+ while ((READ_PORT_UCHAR((PUCHAR) KB_STAT) & KB_OUTBF) == 0)
+ continue;
+ HalDisplayString("\n");
+ }
+ } while (j-- > 0);
+
+ WRITE_PORT_UCHAR((PUCHAR) 0x21, OldPicMask); // restore mask
+ return;
+}
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for
+ the WINSERVER 3000 x86 SMP system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ KIRQL CurrentIrql;
+ PKPRCB pPRCB;
+
+ pPRCB = KeGetCurrentPrcb();
+
+ if (Phase == 0) {
+
+ HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
+
+ //
+ // Verify Prcb version and build flags conform to
+ // this image
+ //
+
+#if DBG
+ if (!(pPRCB->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL,
+ 2, pPRCB->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (pPRCB->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
+ }
+#endif
+ if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ HalpSetProcessorsPresent();
+ ProcessorsPresent &= ~(1 << (HalpMySlotAddr() >> EISA_SHIFT));
+
+#ifdef NT_UP
+ if (ProcessorsPresent) {
+ HalDisplayString(UPWarn); // UP HAL/NTOSKRNL on MP HW
+ ProcessorsPresent = 0; // Hide procs to allow boot
+ HalpGetUserInput();
+ }
+#else
+ if (ProcessorsPresent == 0) {
+ HalDisplayString(MPWarn); // MP HAL/NTOSKRNL on UP HW
+ HalpGetUserInput();
+ }
+#endif
+
+ //
+ // Phase 0 initialization only called by P0
+ //
+
+ HalpInitializePICs();
+
+ //
+ // Initialize CMOS
+ //
+
+ HalpInitializeCmos();
+
+ //
+ // Register cascade vector
+ //
+
+ HalpRegisterVector (
+ InternalUsage, EISA_IRQ2_VECTOR, EISA_IRQ2_VECTOR, HIGH_LEVEL );
+
+ //
+ // Register PIC vectors
+ //
+
+ HalpRegisterVector (
+ InternalUsage,
+ EISA_PIC1_SPURIOUS_VECTOR,
+ EISA_PIC1_SPURIOUS_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ InternalUsage,
+ EISA_PIC2_SPURIOUS_VECTOR,
+ EISA_PIC2_SPURIOUS_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_CLOCK_VECTOR,
+ EISA_CLOCK_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_KBD_VECTOR,
+ EISA_KBD_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_FLOPPY_VECTOR,
+ EISA_FLOPPY_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_RTC_VECTOR,
+ EISA_RTC_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_MOUSE_VECTOR,
+ EISA_MOUSE_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_DMA_VECTOR,
+ EISA_DMA_VECTOR,
+ HIGH_LEVEL );
+
+ HalpRegisterVector (
+ DeviceUsage,
+ EISA_IDE_VECTOR,
+ EISA_IDE_VECTOR,
+ HIGH_LEVEL );
+
+ //
+ // Register APIC spurious vector
+ //
+
+ HalpRegisterVector (
+ InternalUsage,
+ APIC_SPURIOUS_VECTOR,
+ APIC_SPURIOUS_VECTOR,
+ HIGH_LEVEL );
+
+ //
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ CurrentIrql = KfRaiseIrql(CurrentIrql);
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Register base IO space used by hal
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ HalpRegisterAddressUsage (&HalpW3IoSpace);
+
+ //
+ // P0's stall execution is initialized here to allow the kernel
+ // debugger to work properly before initializing all the other
+ // processors.
+ //
+
+ HalpInitializeStallExecution(0);
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ APIC_CLOCK_VECTOR, // Bus interrupt level
+ APIC_CLOCK_VECTOR, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ HalpClockInterrupt, // IRS
+ Latched );
+
+ HalpInitializeClock();
+
+ //
+ // Initialize the profile interrupt vector.
+ //
+
+ HalStopProfileInterrupt(0);
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ APIC_PROFILE_VECTOR, // Bus interrupt level
+ APIC_PROFILE_VECTOR, // System IDT
+ PROFILE_LEVEL, // System Irql
+ HalpProfileInterrupt, // IRS
+ Latched );
+
+ //
+ // Initialize the IPI handler
+ //
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ APIC_IPI_VECTOR, // Bus interrupt level
+ APIC_IPI_VECTOR, // System IDT
+ IPI_LEVEL, // System Irql
+ HalpIpiHandler, // IRS
+ Latched );
+
+ HalpInitializeDisplay();
+
+ //
+ // Initialize spinlock used by HalGetBusData hardware access routines
+ //
+
+ KeInitializeSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ //
+ // Print copyright notice
+ //
+
+ HalDisplayString(HalName);
+ HalDisplayString(SequentCopyright);
+
+ } else {
+
+ //
+ // Phase 1 initialization
+ //
+
+ if (pPRCB->Number == 0) {
+
+ HalpRegisterInternalBusHandlers ();
+
+ } else {
+
+ //
+ // Other processors inherit P0 stall factor.
+ // This assumes all procs have the same basic speed.
+ //
+
+ KiPcr()->StallScaleFactor = HalpProcessorPCR[0]->StallScaleFactor;
+ }
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ APIC_PROFILE_VECTOR, // Bus interrupt level
+ APIC_PROFILE_VECTOR, // System IDT
+ PROFILE_LEVEL, // System Irql
+ HalpProfileInterrupt, // IRS
+ Latched );
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ APIC_CLOCK_VECTOR, // Bus interrupt level
+ APIC_CLOCK_VECTOR, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ HalpClockInterrupt, // IRS
+ Latched );
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ APIC_IPI_VECTOR, // Bus interrupt level
+ APIC_IPI_VECTOR, // System IDT
+ IPI_LEVEL, // System Irql
+ HalpIpiHandler, // IRS
+ Latched );
+
+ }
+
+#ifndef NT_UP
+ HalpInitMP (Phase, LoaderBlock);
+#endif
+
+ return TRUE;
+}
+
+//
+// XXX, hack for now. Need to remove this code.
+//
+
+static UCHAR tmasterline[] = {0, 2, 5, 0};
+
+static USHORT cmdport[] /* command port addrs for pics */
+ = { PIC1_PORT0, PIC2_PORT0, PIC2_PORT0 };
+
+static USHORT imrport[] /* intr mask port addrs for pics */
+ = { PIC1_PORT1, PIC2_PORT1, PIC2_PORT1 };
+
+VOID
+Halptpicinit()
+{
+ ULONG cmd, imr, pic;
+
+/*
+ * --- Initialize the 8259s
+ */
+
+#define PIC_EDGED 0
+#define PIC_ICW1BASE 0x10
+#define PIC_NEEDICW4 1
+#define PIC_86MODE 1
+#define PIC_READISR 0xb
+#define PIC_SLAVEBUF 0x8
+ /*
+ * Initialize master ICW1-ICW4
+ */
+ WRITE_PORT_UCHAR((PUCHAR)cmdport[0], (UCHAR)PIC_EDGED | PIC_ICW1BASE | PIC_NEEDICW4);
+ WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)PIC0_BASE_VECTOR);
+ WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)0x4); /* Cascade IRQ2 */
+ WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)PIC_86MODE);
+
+ /* OCW1 -- Mask everything for now */
+ WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)0xFF);
+
+ /* OCW3*/
+ WRITE_PORT_UCHAR((PUCHAR)cmdport[0], (UCHAR)PIC_READISR);
+
+ /*
+ * Initialize slave(s) - We only do 1 slave now....
+ */
+ for (pic = 1; pic < 2; pic++)
+ {
+ cmd = cmdport[pic];
+ imr = imrport[pic];
+
+ /*
+ * --- Set up ICW1-ICW4
+ */
+
+ WRITE_PORT_UCHAR((PUCHAR)cmd, (UCHAR)(PIC_EDGED | PIC_ICW1BASE | PIC_NEEDICW4));
+ WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)(PIC0_BASE_VECTOR + (UCHAR)(pic * 8)));
+ WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)tmasterline[pic]);
+ if (pic == 2)
+ WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)(PIC_SLAVEBUF | PIC_86MODE)); /* Tricord PIC buffered */
+ else
+ WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)PIC_86MODE);
+
+ /* OCW1 */
+
+ WRITE_PORT_UCHAR( (PUCHAR)imr, (UCHAR)0xFF);
+
+ /* OCW3 */
+
+ WRITE_PORT_UCHAR((PUCHAR)cmd, (UCHAR)PIC_READISR);
+ }
+}
+
+USHORT
+HalpMySlotAddr(
+ )
+{
+ UCHAR slot;
+ ULONG id;
+ UCHAR stat;
+
+ for (slot=9; slot <= 15 ; slot++)
+ {
+ /*
+ * --- Insure system bus board is a CPU
+ */
+ id = READ_PORT_ULONG((PULONG)((slot<<12) | 0xC80));
+ id = id>>16;
+ if ((id & 0xf0) == 0x10)
+ {
+ stat = READ_PORT_UCHAR((PUCHAR)((slot<<12) | 0xC90));
+
+ /*
+ * --- If bus cycle is active it's us!
+ */
+ if ((stat & 0x40) != 0)
+ break;
+ }
+ }
+ if (slot == 16)
+ slot = 0;
+ return (slot << EISA_SHIFT);
+}
+
+VOID
+HalpSetProcessorsPresent(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets a global 32 bit word "ProcessorsPresent"
+ with a "1" bit for each SYSTEM slot that contains a processor board.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR slot;
+ ULONG cpuid;
+
+ for (slot = FIRST_SYSTEM_SLOT; slot < LAST_SYSTEM_SLOT + 1; slot++) {
+ cpuid = READ_PORT_ULONG((PULONG)((slot << EISA_SHIFT) | SLOT_ID_REG));
+ if ((cpuid & SLOT_ID_BOARDTYPE) == SLOT_ID_TYPECPU)
+ ProcessorsPresent |= (1 << slot);
+ }
+}
diff --git a/private/ntos/nthals/halws3/i386/w3ipi.asm b/private/ntos/nthals/halws3/i386/w3ipi.asm
new file mode 100644
index 000000000..a7084dc11
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3ipi.asm
@@ -0,0 +1,955 @@
+ title "Interprocessor Interrupt"
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3ipi.asm
+;
+; Abstract:
+;
+; Provides the HAL support for Interprocessor Interrupts and
+; the initial processor initialization.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Revision History:
+;
+;--
+.386p
+ .xlist
+
+;
+; Include WinServer 3000 detection code
+;
+
+include i386\w3detect.asm
+
+;
+; Normal includes
+;
+
+include ks386.inc
+include i386\kimacro.inc
+include callconv.inc ; calling convention macros
+include i386\apic.inc
+include i386\w3.inc
+
+;
+; Import/Export
+;
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP _KeRaiseIrql,2
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalDisplayString,1
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalDisableSystemInterrupt,2
+
+ EXTRNP _HalpInitializeLocalUnit,0
+ EXTRNP _DbgBreakPoint,0,IMPORT
+
+ EXTRNP _HalpMapPhysicalMemoryWriteThrough,2
+ EXTRNP _HalpMySlotAddr,0
+ EXTRNP _HalpResetLocalUnits,0
+
+ extrn _HalpDefaultInterruptAffinity:DWORD
+ extrn _HalpActiveProcessors:DWORD
+ extrn _HalpLocalUnitBase:DWORD
+ extrn _HalpIOunitBase:DWORD
+ extrn _HalpIOunitTwoBase:DWORD
+ extrn _HalpELCRImage:WORD
+ extrn _HalpMASKED:WORD
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+HALBadVaddr db 'HAL: No Virtual Address available to map the APIC', CR, LF, 0
+HALMisMatch db 'HAL: This HAL only runs on a WinServer 3000.', CR, LF
+ db ' Please replace the hal.dll with the correct hal', CR, LF
+ db ' System is HALTING.', 0
+
+ ALIGN dword
+ public _HalpProcessorPCR
+_HalpProcessorPCR dd 8 dup (0) ; PCR pointer for each processor
+
+_DATA ENDS
+
+ page ,132
+ subttl "Initialize Processor"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeRaiseIrql/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . Save EISA Slot Address in PCR.
+; . Save Processor Number in PCR.
+; . Set initial StallScaleFactor
+; . Set bit in global data structures for each new processor
+; . if (P0)
+; . determine if the system is a WS3000,
+; . if (!WS3000) Halt;
+; . Enable IPI's on CPU.
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor ,1
+cPublicFpo 1, 0
+
+ mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
+
+ stdCall _HalpMySlotAddr
+ mov PCR[PcHal.ProcSlotAddr], ax ; Save processor slot
+
+ mov eax, [esp+4]
+ mov PCR[PcHal.PcrNumber], al ; Save processor # in PCR
+
+ mov ecx, PCR[PcSelfPcr] ; Flat address of this PCR
+ mov _HalpProcessorPCR[eax * 4], ecx ; Save it away
+
+ lock bts _HalpDefaultInterruptAffinity, eax ; update globals for each
+ lock bts _HalpActiveProcessors, eax ; online processor
+
+ test eax, eax
+ jnz ipi_10
+
+ ; Only Boot Processor executes from here to label ipi_10
+
+ sub esp, 4
+ stdCall _DetectWS3000 <esp>
+ add esp, 4
+
+ test eax, eax
+ jz ipi_notW3
+
+ ; Initialize PICs and IDT for PICs
+
+ mov ax, 0FFFFh
+ SET_8259_MASK
+ stdCall _HalInitPicInterruptHandlers
+
+ ; call HAL memory manager to get a virtual address mapping for the
+ ; APIC(s); virtual addresses are saved in global variables for indirect
+ ; addressing later. This assumes that the page tables are built
+ ; for P0 in Phase 0 are valid for P1.
+
+ stdCall _HalpMapPhysicalMemoryWriteThrough <LU_BASE_ADDRESS,1>
+ test eax, eax
+ jz NoHalVaddr
+ mov _HalpLocalUnitBase, eax
+
+ stdCall _HalpMapPhysicalMemoryWriteThrough <IO_BASE_ADDRESS,1>
+ test eax, eax
+ jz NoHalVaddr
+ mov _HalpIOunitBase, eax
+
+ stdCall _HalpMapPhysicalMemoryWriteThrough <IO_BASE_ADDRESS+020000h,1>
+ test eax, eax
+ jz NoHalVaddr
+ mov _HalpIOunitTwoBase, eax
+
+ ; Reset all other local units to keep them from accepting any
+ ; interrupts until their processor is out of reset. This is a
+ ; problem because starting with Beta 2, not all processors may
+ ; be brought up during install and the WS3000 BIOS enables the
+ ; APICs even though the corresponding processor is held in reset.
+ ; This would not be a bug if setting the FCR to put the processor
+ ; into reset also put the APIC into reset, or if the APIC reset output
+ ; was wired to the processor and used to reset it instead of the FCR.
+
+ stdCall _HalpResetLocalUnits
+
+ipi_10:
+
+ ; For P0-Pn, disable the IO unit so it can't suprise us.
+ ; We have to do this on each CPU on the WS3000 since each CPU can
+ ; only address the IO unit on its local APIC. Each CPU IO unit
+ ; has the same address.
+
+ mov edx, _HalpIOunitTwoBase ; get base address of IO unit
+ mov ecx, IO_REDIR_00_LOW
+ mov eax, INTERRUPT_MASKED
+
+ipi_15:
+ mov [edx+IO_REGISTER_SELECT], ecx ; write mask to redir entry
+ mov [edx+IO_REGISTER_WINDOW], eax
+
+ add ecx, 2 ; increment to next redir entry
+ cmp ecx, IO_REDIR_00_LOW + 32 ; go for 16 entries
+ jb ipi_15 ; more to go
+
+ ;
+ ; initialize the APIC local unit for this Processor
+ ;
+
+ stdCall _HalpInitializeLocalUnit
+
+ stdRET _HalInitializeProcessor
+
+NoHalVaddr:
+ stdCall _HalDisplayString, <offset HALBadVaddr>
+ hlt
+
+ipi_notW3:
+ stdCall _HalDisplayString, <offset HALMisMatch>
+ hlt
+
+stdENDP _HalInitializeProcessor
+
+;++
+;
+; VOID
+; HalInitPicInterruptHandlers(
+; );
+;
+;Routine Description:
+;
+; initialize the EISA IDT entries for the WinServer 3000.
+; This includes installing spurious interrupt handlers for:
+;
+; PIC1 spurious interrupt vector (EISA_IRQ7_VECTOR)
+; PIC2 spurious interrupt vector (EISA_IRQ15_VECTOR)
+;
+; and handlers for
+;
+; CLOCK on PIC1 Vector (EISA_IRQ0_VECTOR)
+; KEYBOARD on PIC1 Vector (EISA_IRQ1_VECTOR)
+; FLOPPY on PIC1 Vector (EISA_IRQ6_VECTOR)
+; RTC on PIC2 Vector (EISA_IRQ8_VECTOR)
+; MOUSE on PIC2 Vector (EISA_IRQ12_VECTOR)
+; DMA on PIC2 Vector (EISA_IRQ13_VECTOR)
+; IDE on PIC2 Vector (EISA_IRQ14_VECTOR)
+;
+; The 82357 ISP on the WinServer 3000 platform does not route the
+; clock and DMA interrupts externally. And the Keyboard, Floppy, Rtc,
+; Mouse, and Ide are not available to the APIC by design. Instead, we
+; must get these interrupts from the integrated PIC (master and
+; slave, actually), whose interrupt output drives INTIN<13> of the 82489DX
+; APIC. This APIC interrupt input is programmed for ExtINT (external
+; interrupt) mode, which causes the integrated PIC to generate the
+; interrupt vector instead of the APIC.
+;
+; Since we want to route all system interrupts through the APIC to take
+; advantage of its prioritization mechanism, we install our own interrupt
+; handlers for the Clock, Keyboard, Floppy, RTC, , Mouse, DMA, and
+; IDE interrupts from the PIC, then redispatch the interrupts through the
+; APIC.
+;
+; Spurious interrupt handlers for the integrated PICs are required because
+; the devices can still generate spurious interrupts.
+;
+;Arguments:
+;
+; None.
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalInitPicInterruptHandlers ,0
+
+ IDTEntry EISA_PIC1_SPURIOUS_VECTOR, EisaPic1SpuriousService
+ IDTEntry EISA_PIC2_SPURIOUS_VECTOR, EisaPic2SpuriousService
+ IDTEntry EISA_CLOCK_VECTOR, EisaClockService
+ IDTEntry EISA_KBD_VECTOR, EisaKbdService
+ IDTEntry EISA_FLOPPY_VECTOR, EisaFloppyService
+ IDTEntry EISA_RTC_VECTOR, EisaRTCService
+ IDTEntry EISA_DMA_VECTOR, EisaDmaService
+ IDTEntry EISA_MOUSE_VECTOR, EisaMouseService
+ IDTEntry EISA_IDE_VECTOR, EisaIDEService
+
+ stdRET _HalInitPicInterruptHandlers
+
+stdENDP _HalInitPicInterruptHandlers
+
+;++
+;
+; VOID
+; ApicSpuriousService(
+; );
+;
+;Routine Description:
+;
+; A place for spurious interrupts to end up.
+;
+;--
+cPublicProc ApicSpuriousService ,0
+ iretd
+stdENDP ApicSpuriousService
+
+;++
+;
+; VOID
+; EisaPic1SpuriousService(
+; );
+;
+;Routine Description:
+;
+; A place for spurious EISA PIC one interrupts to end up.
+;
+;--
+cPublicProc EisaPic1SpuriousService,0
+ iretd
+stdENDP EisaPic1SpuriousService
+
+;++
+;
+; VOID
+; EisaPic2SpuriousService(
+; );
+;
+;Routine Description:
+;
+; A place for spurious EISA PIC two interrupts to end up.
+;
+;--
+cPublicProc EisaPic2SpuriousService,0
+ iretd
+stdENDP EisaPic2SpuriousService
+
+;++
+;
+; VOID
+; EisaClockService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+IPI_CLOCK_ALL equ (DELIVER_FIXED OR ICR_ALL_INCL_SELF OR APIC_CLOCK_VECTOR)
+
+ ENTER_DR_ASSIST H99_a, H99_t
+
+cPublicProc EisaClockService,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H99_a, H99_t ; (esp) - base of trap frame
+
+ ;
+ ; Just IPI All Processors ( this is done from P0 )
+ ;
+
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_CLOCK_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi
+ out PIC1_PORT0, al ; dismiss the interrupt
+ ;
+ ; Make sure the ICR is available
+ ;
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+
+@@:
+ test [ecx+LU_INT_CMD_LOW], DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the Clock IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], IPI_CLOCK_ALL
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaClockService
+
+;++
+;
+; VOID
+; EisaKbdService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+IPI_KBD_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_KBD_VECTOR)
+
+ ENTER_DR_ASSIST H98_a, H98_t
+
+cPublicProc EisaKbdService ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H98_a, H98_t ; (esp) - base of trap frame
+
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_KBD_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi
+ out PIC1_PORT0, al ; dismiss the interrupt
+
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the KEYBOARD IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], IPI_KBD_ALL
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaKbdService
+
+;++
+;
+; VOID
+; EisaFloppyService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+IPI_FLOPPY_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_FLOPPY_VECTOR)
+
+ ENTER_DR_ASSIST H97_a, H97_t
+
+cPublicProc EisaFloppyService ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H97_a, H97_t ; (esp) - base of trap frame
+
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_FLOPPY_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi
+ out PIC1_PORT0, al ; dismiss the interrupt
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the FLOPPY IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], IPI_FLOPPY_ALL
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaFloppyService
+
+;++
+;
+; VOID
+; EisaRTCService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+IPI_RTC_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_RTC_VECTOR)
+
+ ENTER_DR_ASSIST H96_a, H96_t
+
+cPublicProc EisaRTCService ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H96_a, H96_t ; (esp) - base of trap frame
+
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the RTC IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], IPI_RTC_ALL
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaRTCService
+
+;++
+;
+; VOID
+; EisaDmaService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+IPI_DMA_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_DMA_VECTOR)
+
+ ENTER_DR_ASSIST H95_a, H95_t
+
+cPublicProc EisaDmaService ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H95_a, H95_t ; (esp) - base of trap frame
+
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the DMA IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], IPI_DMA_ALL
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaDmaService
+
+;++
+;
+; VOID
+; EisaMouseService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, DMA, Mouse, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+IPI_MOUSE_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_MOUSE_VECTOR)
+
+ ENTER_DR_ASSIST H94_a, H94_t
+
+cPublicProc EisaMouseService ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H94_a, H94_t ; (esp) - base of trap frame
+
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the MOUSE IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], IPI_MOUSE_ALL
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaMouseService
+
+
+;++
+;
+; VOID
+; EisaIDEService(
+; );
+;
+;Routine Description:
+;
+; This handler receives interrupts from the EISA PIC and reissues them via
+; a vector at the proper priority level. This is needed on the WinServer
+; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock,
+; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are
+; received outside of the APIC priority structure we use the APIC ICR
+; to generate interrupts to the proper handler at the proper priority.
+;
+; The EXTINT interrupts are programmed via the CCS APIC IO Unit's
+; redirection table. They are directed to Processor zero only.
+;
+;--
+
+ ENTER_DR_ASSIST H93_a, H93_t
+
+cPublicProc EisaIDEService ,0
+
+ ;
+ ; Save machine state in trap frame
+ ;
+
+ ENTER_INTERRUPT H93_a, H93_t ; (esp) - base of trap frame
+
+ mov ebx, (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_IDE_VECTOR)
+ test _HalpELCRImage, (1 SHL (EISA_IDE_VECTOR - PIC0_BASE_VECTOR))
+ jz short @f
+
+ ; If a level PIC interrupt, mask the interrupt at the PIC until
+ ; the APIC interrupt HalEndSystemInterrupt unmasks it.
+ ; We also only send it to ourselves since it needs to mess with the
+ ; pic in the end of interrupt code.
+
+
+lock or _HalpMASKED, (1 SHL (EISA_IDE_VECTOR - PIC0_BASE_VECTOR))
+ in al, PIC2_PORT1
+ or al, (1 SHL (EISA_IDE_VECTOR - PIC1_BASE_VECTOR))
+ out PIC2_PORT1, al
+ mov ebx, (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_SELF OR APIC_IDE_VECTOR)
+
+@@:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR)
+ ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ mov ecx, _HalpLocalUnitBase ; load base address of CCS
+ ; local unit
+@@: test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Write the IDE IPI Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], ebx
+
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP EisaIDEService
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN KAFFINITY Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+;Return Value:
+;
+; None.
+;
+;--
+APIC_IPI equ (DELIVER_FIXED OR LOGICAL_DESTINATION OR ICR_USE_DEST_FIELD OR APIC_IPI_VECTOR)
+
+cPublicProc _HalRequestIpi ,1
+cPublicFpo 1, 0
+
+ mov eax, dword ptr [esp+4] ; (eax) = Processor bitmask
+ mov ecx, _HalpLocalUnitBase ; load base address of local unit
+
+ DISABLE_INTERRUPTS_AT_CPU
+
+if DBG
+ or eax, eax ; must ipi somebody
+ jz short ipibad
+ movzx edx, byte ptr PCR[PcHal.PcrNumber] ; Get Processor Number
+ bt eax, edx ; cannot ipi yourself
+ jc short ipibad
+endif
+
+ ;
+ ; With an APIC we'll IPI everyone needed at the same time.
+ ; This assumes that:
+ ; (mask passed in) == (APIC logical destination mask) Since we've programmed
+ ; the APIC Local Units to use the Processor ID as the APIC ID this IS true
+ ;
+ ;
+ ; Make sure the ICR is available
+ ;
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ;
+ ; Set the destination address, (eax) = Processor bitmask
+ ;
+
+ mov [ecx+LU_INT_CMD_HIGH], eax
+
+ ;
+ ; Now issue the command by writing to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], APIC_IPI
+
+ RESTORE_INTERRUPTS_AT_CPU
+
+ stdRET _HalRequestIpi
+
+if DBG
+ipibad:
+ RESTORE_INTERRUPTS_AT_CPU
+ stdCall _DbgBreakPoint
+ stdRET _HalRequestIpi
+endif
+
+stdENDP _HalRequestIpi
+
+;++
+;
+; VOID
+; HalIntProcessorAPIC(
+; IN ULONG Mask,
+; IN ULONG ICRCommand
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+; ICRCommand - ICR Command to use
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalIntProcessorAPIC ,2
+
+ mov edx, dword ptr [esp+4] ; (edx) = Processor bitmask
+ mov eax, dword ptr [esp+8] ; (eax) = ICR Command
+
+ mov ecx, _HalpLocalUnitBase ; load base address of local unit
+
+ ;
+ ; Make sure the ICR is available
+ ;
+
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+
+@@:
+ test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING
+ jnz @b
+
+ ; (edx) = Processor bitmask
+ ; (eax) = ICR Command
+
+ mov [ecx+LU_INT_CMD_HIGH], edx
+
+ ;
+ ; Now issue the command by writing the ICR Command to the Memory Mapped Register
+ ;
+
+ mov [ecx+LU_INT_CMD_LOW], eax
+
+ popfd
+
+ stdRET _HalIntProcessorAPIC
+
+stdENDP _HalIntProcessorAPIC
+
+
+ page ,132
+ subttl "IPI Interrupt Handler"
+;++
+;
+; VOID
+; HalpIpiHandler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by inter
+; processor communication.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hipi_a, Hipi_t
+
+cPublicProc _HalpIpiHandler ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+ push APIC_IPI_VECTOR ; Vector
+ sub esp, 4 ; space for OldIrql
+;
+; We now dismiss the interprocessor interrupt and call its handler
+;
+
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,APIC_IPI_VECTOR,esp>
+
+; Pass Null ExceptionFrame
+; Pass TrapFrame to Ipi service rtn
+;
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+;
+; Do interrupt exit processing
+;
+
+ INTERRUPT_EXIT ; will return to caller
+
+stdENDP _HalpIpiHandler
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halws3/i386/w3irql.asm b/private/ntos/nthals/halws3/i386/w3irql.asm
new file mode 100644
index 000000000..9b830dac6
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3irql.asm
@@ -0,0 +1,776 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3irql.asm
+;
+; Abstract:
+;
+; WinServer 3000 IRQL implementation.
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the WinServer APIC/PIC system.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+
+.386p
+ .xlist
+include ks386.inc
+include callconv.inc ; calling convention macros
+include i386\apic.inc
+include i386\kimacro.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _KeBugCheck,1
+ EXTRNP _Halptpicinit,0
+ EXTRNP _HalpDispatchInterrupt,0
+ EXTRNP _HalpApcInterrupt,0
+
+ extrn _HalpIrql2TPR:byte
+ extrn _HalpK2Rdir2Irq:byte
+ extrn _HalpELCRImage:word
+ extrn _HalpW3BaseIOunitRedirectionTable:dword
+ extrn _HalpK2EbsIOunitRedirectionTable:dword
+ extrn _HalpK2EISAIrq2Irql:byte
+ extrn _HalpK2Irql2Eisa:byte
+ extrn _HalpActiveProcessors:DWORD
+ extrn _HalpIrql2IRRMask:dword
+ extrn ApicSpuriousService@0:near
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; Virtual addresses of the APIC Local and IO units.
+; The virtual mapping is done in HalInitializeProcessor.
+;
+ align dword
+ public _HalpLocalUnitBase, _HalpIOunitBase, _HalpIOunitTwoBase
+_HalpLocalUnitBase dd 0
+_HalpIOunitBase dd 0
+_HalpIOunitTwoBase dd 0
+
+SyncIdCommand equ DELIVER_INIT + \
+ LOGICAL_DESTINATION + \
+ LEVEL_TRIGGERED
+ResetAllExclSelf equ DELIVER_INIT + \
+ LEVEL_TRIGGERED + \
+ ICR_LEVEL_ASSERTED + \
+ ICR_ALL_EXCL_SELF
+UnResetLogical equ DELIVER_INIT + \
+ LOGICAL_DESTINATION + \
+ LEVEL_TRIGGERED
+
+;
+; This table is used to mask all pending interrupts below a given Irql
+; out of the IRR
+;
+ align 4
+
+ public FindHigherIrqlMask
+FindHigherIrqlMask label dword
+ dd 11111111111111111111111111111110B ; irql 0
+ dd 11111111111111111111111111111100B ; irql 1
+ dd 11111111111111111111111111111000B ; irql 2
+ dd 11111111111111111111111111110000B ; irql 3
+ dd 11111111111111111111111111100000B ; irql 4
+ dd 11111111111111111111111111000000B ; irql 5
+ dd 11111111111111111111111110000000B ; irql 6
+ dd 11111111111111111111111100000000B ; irql 7
+ dd 11111111111111111111111000000000B ; irql 8
+ dd 11111111111111111111110000000000B ; irql 9
+ dd 11111111111111111111100000000000B ; irql 10
+ dd 11111111111111111111000000000000B ; irql 11
+ dd 11111111111111111110000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111000000000000000B ; irql 14
+ dd 11111111111111110000000000000000B ; irql 15
+ dd 11111111111111100000000000000000B ; irql 16
+ dd 11111111111111000000000000000000B ; irql 17
+ dd 11111111111110000000000000000000B ; irql 18
+ dd 11111111111100000000000000000000B ; irql 19
+ dd 11111111111000000000000000000000B ; irql 20
+ dd 11111111110000000000000000000000B ; irql 21
+ dd 11111111100000000000000000000000B ; irql 22
+ dd 11111111000000000000000000000000B ; irql 23
+ dd 11111110000000000000000000000000B ; irql 24
+ dd 11111100000000000000000000000000B ; irql 25
+ dd 11111000000000000000000000000000B ; irql 26
+ dd 11110000000000000000000000000000B ; irql 27
+ dd 11100000000000000000000000000000B ; irql 28
+ dd 11000000000000000000000000000000B ; irql 29
+ dd 10000000000000000000000000000000B ; irql 30
+ dd 00000000000000000000000000000000B ; irql 31
+
+_DATA ENDS
+
+ page ,132
+ subttl "RaiseIrql"
+
+_TEXT$01 SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; KIRQL
+; KfRaiseIrql (
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+;
+; *** IMPORTANT IMPLEMENTATION NOTE ***
+; Be sure to not write the OldIrql return value until after the
+; IRQL has taken effect (due to poor coding practices).
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+; Return Value:
+;
+; OldIrql - old irql
+;
+;--
+
+cPublicFastCall KfRaiseIrql ,1
+cPublicFpo 0,0
+
+ mov al, PCR[PcHal.ProcIrql] ; (al) = old irql
+if DBG
+ cmp al, cl ; old > new?
+ ja short KriErr1
+endif
+ cmp cl, DISPATCH_LEVEL ; a software level?
+ ja short @f ; if yes, set the hardware
+ mov PCR[PcHal.ProcIrql], cl ; Save new irql
+ fstRET KfRaiseIrql
+@@:
+ mov edx, _HalpLocalUnitBase ; Get address of Local APIC
+ and ecx, 0ffh ; clear upper 3 bytes
+
+ pushfd ; enter critical region
+ cli ;
+
+ mov PCR[PcHal.ProcIrql], cl ; Save new irql
+ mov cl, _HalpIrql2TPR[ecx] ; convert irql to TPR
+ mov [edx+LU_TPR], ecx ; write new irql
+ mov ecx, [edx+LU_TPR] ; Flush CPU write buffer
+
+ popfd ; leave critical region
+
+ fstRET KfRaiseIrql
+if DBG
+cPublicFpo 0, 2
+KriErr1:
+ movzx eax, al
+ movzx ecx, cl
+ push ecx ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr PCR[PcHal.ProcIrql], 0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL>
+endif
+
+fstENDP KfRaiseIrql
+
+ page ,132
+ subttl "LowerIrql"
+;++
+;
+; VOID
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+cPublicFastCall KfLowerIrql ,1
+cPublicFpo 0,0
+
+ movzx ecx, cl ; get new irql value
+if DBG
+ cmp cl, PCR[PcHal.ProcIrql] ; new > old ?
+ ja KliErr ; panic if so
+endif
+ cmp byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL
+ ja short KliHW ; if old irql <= 2, software only
+ mov PCR[PcHal.ProcIrql], cl ; Save new irql
+;
+; Check for any pending DISPATCH interrupts
+;
+KliChkSW:
+ mov edx, PCR[PcIRR] ; get current IRR
+ and edx, FindHigherIrqlMask[ecx*4]
+ jnz KliSW
+KliEnd:
+ fstRET KfLowerIrql ; return
+KliSW:
+ pushfd
+ cli
+ test dword ptr PCR[PcIRR], (1 SHL DISPATCH_LEVEL)
+ jz short @f
+ stdCall _HalpDispatchInterrupt
+ popfd
+ xor ecx, ecx
+ mov cl, PCR[PcHal.ProcIrql] ; restore current irql value
+ jmp short KliChkSW
+@@:
+ cmp cl, APC_LEVEL
+ jae short KliPop
+ test dword ptr PCR[PcIRR], (1 SHL APC_LEVEL)
+ jz short KliPop
+ stdCall _HalpApcInterrupt
+ popfd
+ xor ecx, ecx
+ mov cl, PCR[PcHal.ProcIrql] ; restore current irql value
+ jmp short KliChkSW
+KliPop:
+ popfd
+ jmp short KliEnd
+
+;
+; Lower APIC Task Priority Register to reflect change in IRQL
+; and then check for software interrupts (if below DISPATCH)
+;
+KliHW:
+ mov edx, _HalpLocalUnitBase ; get address of Local APIC
+ pushfd
+ cli
+ mov PCR[PcHal.ProcIrql], cl ; Save new irql
+ mov cl, _HalpIrql2TPR[ecx] ; convert irql to TPR
+ mov [edx+LU_TPR], ecx ; write new TPR value
+ mov ecx, [edx+LU_TPR] ; Flush CPU write buffer
+ popfd
+ mov cl, byte ptr PCR[PcHal.ProcIrql] ; restore current irql value
+ cmp cl, DISPATCH_LEVEL
+ jb KliChkSW
+ fstRET KfLowerIrql ; return
+
+if DBG
+cPublicFpo 1, 2
+KliErr:
+ push ecx ; new irql for debugging
+ mov cl, PCR[PcHal.ProcIrql] ; get old irql
+ push ecx ; old irql for debugging
+ mov byte ptr PCR[PcHal.ProcIrql], HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
+endif
+fstENDP KfLowerIrql
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov ecx, DISPATCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+
+ mov ecx, SYNCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+
+ xor eax, eax
+ mov al, PCR[PcHal.ProcIrql] ; return 32 bits to cover mistakes
+ stdRET _KeGetCurrentIrql
+
+stdENDP _KeGetCurrentIrql
+
+
+;++
+;
+; VOID
+; _HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+
+;
+; Raising to HIGH_LEVEL disables all interrupts
+;
+
+ mov ax, 0FFFFh
+ SET_8259_MASK
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+_TEXT$01 ends
+
+ page ,132
+ subttl "Interrupt Controller Initialization"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; VOID
+; _HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; Call the _Halptpicinit C routine to initialize 8259 and APIC
+;
+;Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+
+ DISABLE_INTERRUPTS_AT_CPU
+
+ stdCall _HalpInitializeEbsIOunit ; Initialize EBS I/O APIC
+ stdCall _HalpInitializeBaseIOunit ; Initialize P0 I/O APIC
+ stdCall _Halptpicinit ; Initialize PICs
+
+ RESTORE_INTERRUPTS_AT_CPU
+
+ stdRET _HalpInitializePICs
+
+stdENDP _HalpInitializePICs
+
+ page ,132
+ subttl "APIC EBS IO Unit Initialization"
+;++
+;
+; VOID
+; HalpInitializeEbsIOUnit (
+; )
+;
+; Routine Description:
+;
+; This routine initializes the interrupt structures for the IO unit of
+; the 82489DX APIC. It masks all interrupt inputs in the redirection
+; table - these will be unmasked when the interrupts are enabled by
+; HalpEnableSystemInterrupt.
+;
+; HalpInitializeIOunit is called by HalpInitializePics during Phase 0
+; initialization. It is executed by P0 only, and executes AFTER the
+; local unit is initialized. This procedure assumes that the APIC virtual
+; address space has been mapped.
+;
+; The I/O unit for external WinServer 3000 interrupts resides on the
+; EBS module.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalpInitializeEbsIOUnit ,0
+
+ push esi ; save regs
+ push ebx ;
+
+;
+; When using the Intel 82350 ISP Chipset the interrupt edge/level definitions
+; are readable from the ISP's edge/level control register (ELCR).
+;
+; Read the ELCR so the input polarity control XOR gates on the APIC interrupt
+; inputs can be programmed. This whole thing works because EISA defines edge
+; -triggered interrupts as active-high and level interrupts as active-low.
+;
+; We will use the ELCR later to set the ACTIVE_LOW bit as required in the
+; IOunit redirection table.
+;
+ mov dx, PIC2_ELCR_PORT ; read the edge/level control reg
+ in al, dx
+ shl ax, 8
+ mov dx, PIC1_ELCR_PORT
+ in al, dx
+ and ax, ELCR_MASK ; clear reserved IRQs
+ mov _HalpELCRImage, ax ; save the image for later
+;
+; load addresses of the register-select register and register-window register
+;
+ mov ecx, _HalpIOunitBase
+ lea edx, [ecx+IO_REGISTER_SELECT]
+ lea ecx, [ecx+IO_REGISTER_WINDOW]
+
+;
+; write the I/O unit APIC-ID - Since we are using the Processor
+; Numbers for the local unit ID's we need to set the IO unit
+; to a high (out of Processor Number range) value.
+;
+ mov dword ptr [edx], IO_ID_REGISTER
+ mov dword ptr [ecx], (IOUNIT_APIC_ID SHL APIC_ID_SHIFT)
+
+;
+; program the redirection table
+;
+ mov ebx, IO_REDIR_00_LOW ; [EBX] has register select
+ lea esi, _HalpK2EbsIOunitRedirectionTable ; [ESI] has address of image
+
+RedirLoop1:
+ lodsd ; load low dword
+ or eax, eax ; end of table?
+ jz RedirLoopExit1 ; yup - we're done
+ push ebx
+ push ecx
+ push eax
+ sub ebx, IO_REDIR_00_LOW
+ shr ebx, 1 ; Form RDIR #
+ xor ecx,ecx
+ mov cl, _HalpK2Rdir2Irq[ebx] ; Form IRQ #
+ xor eax, eax ; clear reg.
+ mov ax, _HalpELCRImage
+ bt eax, ecx
+ pop eax
+ pop ecx
+; Note: 0 will result for all K2 IRQs, this is what we want....
+ jnc @f ; bit is 0 => active high (default)
+ ; eax is val
+ ; ebx in RDIR entry #
+ or eax, LEVEL_TRIGGERED ; This is a level triggered interrupt
+;
+; We must tell the hardware to invert the polarity for level triggered
+; interrupts because APIC is "active HIGH", EISA is active low for level
+; triggered interrupts...so tickle the K2 EISA to APIC Polarity Register..
+;
+ push eax
+ push edx
+ mov dx, EISA_2_MPIC_POLARITY_REG
+ in al, dx
+ bts eax, ebx ;
+ out dx, al
+ pop edx
+ pop eax
+@@:
+ pop ebx
+ mov dword ptr [edx], ebx ; write to select register
+ mov dword ptr [ecx], eax ; write redirection table entry
+ inc ebx ; increment to next entry
+ lodsd ; load high dword
+ mov dword ptr [edx], ebx ; write to select register
+ mov dword ptr [ecx], eax ; write redirection table entry
+ inc ebx ; increment to next entry
+ jmp RedirLoop1 ; continue...
+RedirLoopExit1:
+
+ pop ebx ; restore registers and return
+ pop esi ;
+ stdRET _HalpInitializeEbsIOUnit
+stdENDP _HalpInitializeEbsIOUnit
+ page ,132
+ subttl "APIC Base IO Unit Initialization"
+;++
+;
+; VOID
+; HalpInitializeBaseIOUnit (
+; )
+;
+; Routine Description:
+;
+; This routine initializes the interrupt structures for the IO unit of
+; the 82489DX APIC. It masks all interrupt inputs in the redirection
+; table - these will be unmasked when the interrupts are enabled by
+; HalpEnableSystemInterrupt.
+;
+; HalpInitializeIOunit is called by HalpInitializePics during Phase 0
+; initialization. It is executed by CPU0 only, and executes AFTER the
+; local unit is initialized. This procedure assumes that the APIC virtual
+; address space has been mapped.
+;
+; The I/O unit for external K2 interrupts resides on the EBS module.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalpInitializeBaseIOUnit ,0
+
+ push esi ; save regs
+ push ebx ;
+
+;
+; load addresses of the register-select register and register-window register
+;
+ mov ecx, _HalpIOunitTwoBase
+ lea edx, [ecx+IO_REGISTER_SELECT]
+ lea ecx, [ecx+IO_REGISTER_WINDOW]
+;
+; write the I/O unit APIC-ID - Since we are using the Processor
+; Numbers for the local unit ID's we need to set the 2nd IO unit
+; to a high (out of Processor Number range) value (but != other IO unit).
+;
+ mov dword ptr [edx], IO_ID_REGISTER
+ mov dword ptr [ecx], (IOUNIT2_APIC_ID SHL APIC_ID_SHIFT)
+
+;
+; re-program the redirection table
+;
+ mov ebx, IO_REDIR_00_LOW ; [EBX] has register select
+ lea esi, _HalpW3BaseIOunitRedirectionTable ; [ESI] has address of image
+
+RedirLoop:
+ lodsd ; load low dword
+ or eax, eax ; end of table?
+ jz RedirLoopExit ; yup - we're done
+ mov dword ptr [edx], ebx ; write to select register
+ mov dword ptr [ecx], eax ; write redirection table entry
+ inc ebx ; increment to next entry
+ lodsd ; load high dword
+ mov dword ptr [edx], ebx ; write to select register
+ mov dword ptr [ecx], eax ; write redirection table entry
+ inc ebx ; increment to next entry
+ jmp RedirLoop ; continue...
+RedirLoopExit:
+
+ pop ebx ; restore registers and return
+ pop esi ;
+ stdRET _HalpInitializeBaseIOUnit
+stdENDP _HalpInitializeBaseIOUnit
+
+cPublicProc _HalpUnResetLocalUnit ,1
+
+ movzx ecx, byte ptr [esp+4] ; get CPU logical number
+ xor eax, eax
+ bts eax, ecx ; convert to bit mask of 1 bit
+ mov ecx, _HalpLocalUnitBase ; pointer to local unit
+
+ DISABLE_INTERRUPTS_AT_CPU
+
+@@: test dword ptr [ecx+LU_INT_CMD_LOW], DELIVERY_PENDING
+ jnz short @b
+
+ mov dword ptr [ecx+LU_INT_CMD_HIGH], eax ; destination bit mask
+ mov dword ptr [ecx+LU_INT_CMD_LOW], UnResetLogical
+
+ RESTORE_INTERRUPTS_AT_CPU
+
+ stdRET _HalpUnResetLocalUnit
+
+stdENDP _HalpUnResetLocalUnit
+
+cPublicProc _HalpResetLocalUnits ,0
+
+ mov ecx, _HalpLocalUnitBase ; pointer to local unit
+
+ DISABLE_INTERRUPTS_AT_CPU
+
+@@: test dword ptr [ecx+LU_INT_CMD_LOW], DELIVERY_PENDING
+ jnz short @b
+
+ mov dword ptr [ecx+LU_INT_CMD_LOW], ResetAllExclSelf
+
+ RESTORE_INTERRUPTS_AT_CPU
+
+ stdRET _HalpResetLocalUnits
+stdENDP _HalpResetLocalUnits
+
+ page ,132
+ subttl "APIC Local Unit Initialization"
+;++
+;
+; VOID
+; HalpInitializeLocalUnit (
+; )
+;
+; Routine Description:
+;
+; This routine initializes the interrupt structures for the local unit
+; of the 82489DX APIC. This procedure is called by HalInitializeProcessor
+; as it is executed by each CPU.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+APIC_ENABLE equ (APIC_SPURIOUS_VECTOR OR LU_UNIT_ENABLED)
+
+cPublicProc _HalpInitializeLocalUnit ,0
+cPublicFpo 0, 1
+
+ pushfd
+ cli
+
+ mov edx, _HalpLocalUnitBase ; base address of local unit
+ mov dword ptr [edx+LU_TPR], 0FFh ; Disable all interrupts
+ movzx eax, byte ptr PCR[PcHal.PcrNumber] ; use CPU number for APIC-id
+ mov dword ptr [edx+LU_DEST_FORMAT], LU_DEST_FORMAT_FLAT
+ xor ecx, ecx ; zero bitmask
+ bts ecx, eax ; create logical dest bitmask
+ mov [edx+LU_LOGICAL_DEST], ecx ; and set it
+ shl eax, APIC_ID_SHIFT ; ID_REGISTER has ID in MSB
+ mov dword ptr [edx+LU_ID_REGISTER], eax ; set local unit ID
+;
+; APIC does not seem to see a hardware reset across a reboot thus an interrupt
+; could have been taken but the EOI is never written. The BIOS does not
+; recover from this condition so we must do it here. Many days with a logic
+; analyzer finally found this one. If there are any ISR bits set, clear
+; one by a write to the EOI register and look again.
+;
+@@:
+ mov eax, [edx+LU_ISR_0+000h] ; read ISR 0
+ or eax, [edx+LU_ISR_0+010h] ; read ISR 1
+ or eax, [edx+LU_ISR_0+020h] ; read ISR 2
+ or eax, [edx+LU_ISR_0+030h] ; read ISR 3
+ or eax, [edx+LU_ISR_0+040h] ; read ISR 4
+ or eax, [edx+LU_ISR_0+050h] ; read ISR 5
+ or eax, [edx+LU_ISR_0+060h] ; read ISR 6
+ or eax, [edx+LU_ISR_0+070h] ; read ISR 7
+ jz short @f
+ mov dword ptr [edx+LU_EOI], eax ; clear highest ISR bit
+ jmp short @b
+@@:
+ mov dword ptr [edx+LU_SPURIOUS_VECTOR], APIC_ENABLE
+;
+; Sync all APIC IDs by using Data Sheet recommended procedure
+;
+ xor eax, eax
+ mov dword ptr [edx+LU_INT_CMD_HIGH], eax
+ mov dword ptr [edx+LU_INT_CMD_LOW], SyncIdCommand
+;
+; we're done - set TPR back to zero and return
+;
+ mov PCR[PcHal.ProcIrql], al ; Set CurrentIrql=0
+ mov [edx+LU_TPR], eax
+
+;
+; Program in the spurious interrupt vector into the IDT
+;
+ IDTEntry APIC_SPURIOUS_VECTOR, ApicSpuriousService@0
+
+ popfd
+
+ stdRET _HalpInitializeLocalUnit
+
+stdENDP _HalpInitializeLocalUnit
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3nmi.c b/private/ntos/nthals/halws3/i386/w3nmi.c
new file mode 100644
index 000000000..a368bf610
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3nmi.c
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Sequent Computer Systems, Inc.
+
+Module Name:
+
+ ws3nmi.c
+
+Abstract:
+
+ Provides x86 NMI handler for the WinServer 3000.
+
+Author:
+
+ Phil Hochstetler (phil@sequent.com) 3-30-93
+
+Revision History:
+
+--*/
+#include "halp.h"
+#include "bugcodes.h"
+#include "w3.inc"
+
+
+VOID
+HalHandleNMI(
+ IN OUT PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ Called DURING an NMI. The system will BugCheck when an NMI occurs.
+ This function can return the proper bugcheck code, bugcheck itself,
+ or return success which will cause the system to iret from the nmi.
+
+ This function is called during an NMI - no system services are available.
+ In addition, you don't want to touch any spinlock which is normally
+ used since we may have been interrupted while owning it, etc, etc...
+
+Warnings:
+
+ Do NOT:
+ Make any system calls
+ Attempt to acquire any spinlock used by any code outside the NMI handler
+ Change the interrupt state. Do not execute any IRET inside this code
+
+ Passing data to non-NMI code must be done using manual interlocked
+ functions. (xchg instructions).
+
+Arguments:
+
+ NmiInfo - Pointer to NMI information structure (TBD)
+ - NULL means no NMI information structure was passed
+
+Return Value:
+
+ BugCheck code
+
+--*/
+{
+ //
+ // We can not look at the hardware to determine the source
+ // of the error because reads of many error registers clear
+ // the error and the IMP board is racing with us.
+ //
+ // If support for systems without an IMP board is added, we need
+ // to duplicate all the error reporting of the IMP board here.
+ //
+
+ HalDisplayString (MSG_HARDWARE_ERROR1);
+ HalDisplayString (MSG_HARDWARE_ERROR2);
+ HalDisplayString ("NMI: The system has detected a fatal NMI\n");
+ HalDisplayString (MSG_HALT);
+
+ KeEnterKernelDebugger();
+}
diff --git a/private/ntos/nthals/halws3/i386/w3profil.asm b/private/ntos/nthals/halws3/i386/w3profil.asm
new file mode 100644
index 000000000..8d8c58ff4
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3profil.asm
@@ -0,0 +1,223 @@
+ title "Profile Support"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1994 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3profil.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to initialize,
+; field, and process the profile interrupt.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\ixcmos.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ extrn _HalpLocalUnitBase:DWORD
+
+;
+; APIC Timer Constants
+;
+
+APIC_TIMER_DISABLED equ (INTERRUPT_MASKED OR PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
+APIC_TIMER_ENABLED equ (PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+
+ProfileCountDownValue dd (200 * 11)
+HalpProfileRunning dd 0
+
+_DATA ends
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+;++
+;
+; HalStartProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is set the interrupt rate to the value that's been set
+; by the KeSetProfileInterval routine. Then enable the APIC Timer interrupt.
+; This function gets called on every processor so the hal can enable
+; a profile interrupt on each processor.
+;--
+
+cPublicProc _HalStartProfileInterrupt ,1
+cPublicFpo 1, 0
+
+ mov ecx, _HalpLocalUnitBase ; load base address of local unit
+
+;
+; Set the interrupt rate to what is actually needed.
+;
+
+ mov eax, ProfileCountDownValue
+ mov [ecx+LU_INITIAL_COUNT], eax
+
+;
+; Set the Local APIC Timer to interrupt Periodically at APIC_PROFILE_VECTOR
+;
+
+ mov [ecx+LU_TIMER_VECTOR], APIC_TIMER_ENABLED
+
+
+ stdRET _HalStartProfileInterrupt
+
+stdENDP _HalStartProfileInterrupt
+
+
+
+;++
+;
+; HalStopProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+;--
+
+cPublicProc _HalStopProfileInterrupt ,1
+cPublicFpo 1, 0
+
+ mov ecx, _HalpLocalUnitBase ; load base address of local unit
+ mov [ecx+LU_TIMER_VECTOR], APIC_TIMER_DISABLED
+
+ stdRET _HalStopProfileInterrupt
+
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; Arguments:
+;
+; (TOS+4) - Interval in 100ns unit.
+;
+; Return Value:
+;
+; Interval actually used by system.
+;--
+
+cPublicProc _HalSetProfileInterval ,1
+cPublicFpo 1, 0
+
+;
+; --- On the WinServer 3000, the profile timer uses TBASE on the local APIC
+; Timer zero. The TMBASE clock runs at 11Mhz so each clock tick is
+; equal to 90.9090ns or roughly 91ns. Since this is close to 100ns
+; we will use the 100ns units at the timer counter value directly.
+; To use an accurate muliple of 100ns units the profiler would have
+; to use 1000ns (1usec) intervals, this interval is equal to 11 clock
+; ticks.
+;
+
+ mov eax, [esp+4] ; ecx = interval in 100ns unit
+
+ mov ProfileCountDownValue, eax ; Save the Computed Count Down
+ mov ecx, _HalpLocalUnitBase ; load base address of local unit
+
+ ;
+ ; Set the interrupt rate in the chip.
+ ;
+
+ mov [ecx+LU_INITIAL_COUNT], eax
+
+ stdRET _HalSetProfileInterval
+
+stdENDP _HalSetProfileInterval
+
+ page ,132
+ subttl "System Profile Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; PROFILE_LEVEL and transfer control to
+; the standard system routine to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpi_a, Hpi_t
+
+cPublicProc _HalpProfileInterrupt ,0
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpi_a, Hpi_t
+
+;
+; (esp) - base of trap frame
+;
+
+ push APIC_PROFILE_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,APIC_PROFILE_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hpi100
+
+ stdCall _KeProfileInterrupt,<ebp> ; (ebp) = TrapFrame address
+
+ INTERRUPT_EXIT
+Hpi100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT
+
+stdENDP _HalpProfileInterrupt
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3space.asm b/private/ntos/nthals/halws3/i386/w3space.asm
new file mode 100644
index 000000000..ea6a125dc
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3space.asm
@@ -0,0 +1,1346 @@
+ title "Global Storage and Tables"
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3space.asm
+;
+; Abstract:
+;
+; This module contains global storage and tables
+; used by the WinServer 3000 HAL implementation.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Environment:
+;
+; Kernel Mode
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include ks386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\w3.inc
+ .list
+
+ extrn _HalpBeginW3InvalidInterrupt:near
+ extrn _HalpBeginW3APICInterrupt:near
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; This location is used to store the EISA Edge/Level Register
+; contents read once during initialization.
+;
+ align 4
+ public _HalpELCRImage
+_HalpELCRImage label word
+ dw 0
+
+;
+; This location is used to keep state around when a
+; level PIC interrupt occurs.
+;
+ align 4
+ public _HalpMASKED
+_HalpMASKED label word
+ dw 0
+
+;
+; The following location is used to keep a software copy
+; of the Post Code Register (register is write only). Used
+; to run front panel lights on the WinServer 3000.
+;
+ align 4
+ public _HalpW3PostRegisterImage
+_HalpW3PostRegisterImage label dword
+ dd 0
+
+;
+; Table to convert an Irql to a mask that looks for bits to
+; be exposed in the software copy of the IRR.
+;
+ align 4
+ public _HalpIrql2IRRMask
+_HalpIrql2IRRMask label dword
+ dd 11111111111111111111111111111110B ; irql 0
+ dd 11111111111111111111111111111100B ; irql 1
+ dd 11111111111111111111111111111000B ; irql 2
+ dd 11111111111111111111111111110000B ; irql 3
+ dd 11111111111111111111111111100000B ; irql 4
+ dd 11111111111111111111111111000000B ; irql 5
+ dd 11111111111111111111111110000000B ; irql 6
+ dd 11111111111111111111111100000000B ; irql 7
+ dd 11111111111111111111111000000000B ; irql 8
+ dd 11111111111111111111110000000000B ; irql 9
+ dd 11111111111111111111100000000000B ; irql 10
+ dd 11111111111111111111000000000000B ; irql 11
+ dd 11111111111111111110000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111000000000000000B ; irql 14
+ dd 11111111111111110000000000000000B ; irql 15
+ dd 11111111111111100000000000000000B ; irql 16
+ dd 11111111111111000000000000000000B ; irql 17
+ dd 11111111111110000000000000000000B ; irql 18
+ dd 11111111111100000000000000000000B ; irql 19
+ dd 11111111111000000000000000000000B ; irql 20
+ dd 11111111110000000000000000000000B ; irql 21
+ dd 11111111100000000000000000000000B ; irql 22
+ dd 11111111000000000000000000000000B ; irql 23
+ dd 11111110000000000000000000000000B ; irql 24
+ dd 11111100000000000000000000000000B ; irql 25
+ dd 11111000000000000000000000000000B ; irql 26
+ dd 11110000000000000000000000000000B ; irql 27
+ dd 11100000000000000000000000000000B ; irql 28
+ dd 11000000000000000000000000000000B ; irql 29
+ dd 10000000000000000000000000000000B ; irql 30
+ dd 00000000000000000000000000000000B ; irql 31
+
+;
+;
+; HalpBeginW3Interrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts. Vectors
+; are assigned to accomodate NT IRQL requirements and the APIC task
+; priority register definition.
+;
+ align 4
+ public _HalpBeginW3InterruptTable
+_HalpBeginW3InterruptTable label dword
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; Vector 0
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 10
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 20
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 50 - Wake
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 60 - IRQ16
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 61 - IRQ17
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 62 - IRQ18
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 63 - IRQ19
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 64 - IRQ20
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 65 - IRQ21
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 66 - IRQ22
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 67 - IRQ23
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 70 - IRQ8
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 71 - IRQ9
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 72 - IRQ10
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 73 - IRQ11
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 74 - IRQ12
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 75 - IRQ13
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 76 - IRQ14
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 77 - IRQ15
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 80 - IRQ0
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 81 - IRQ1
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 82 - IRQ2
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 83 - IRQ3
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 84 - IRQ4
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 85 - IRQ5
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 86 - IRQ6
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 87 - IRQ7
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; 90 - Profile
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; A0 - Clock
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; B0 - IPI
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; C0 - Powerfail
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; D0 - IRQ0 8259
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; DF - IRQ15 8259
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; E0 - APIC_SPURIOUS
+ dd offset FLAT:_HalpBeginW3APICInterrupt ; E1 - APIC_SYSINT
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; F0
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; ..
+ dd offset FLAT:_HalpBeginW3InvalidInterrupt ; Vector FF
+;
+; This table is used by KeRaiseIrql and KeLowerIrql to convert an IRQL
+; value to an APIC task priority value. The APIC uses groups of 16
+; interrupt vectors for each task priority. Windows NT has allowed us
+; to use vectors 48-255 for external interrupt processing. This means we
+; actually have 14 hardware priorities available to work with. We only
+; use 11.
+;
+; To simplify the prioritization of PIC interrupts we decided to only create
+; 3 hardware priorities, i.e., 1 for each PIC. This keeps us from using
+; up all of the vectors in case we need them in the future and creates
+; less confusion about IRQ numbers and priority..
+;
+; The hardware priorities, vectors and APIC task priorities for the 32
+; NT IRQLs are established as follows:
+;
+ align 4
+ public _HalpIrql2TPR
+_HalpIrql2TPR label byte
+ db 0 SHL 4 ; IRQL = 0, tpr = 0:0 - Low
+ db 0 SHL 4 ; IRQL = 1, tpr = 0:0 - APC
+ db 0 SHL 4 ; IRQL = 2, tpr = 0:0 - DPC
+ db 0 SHL 4 ; IRQL = 3, tpr = 0:0 - Wake
+;
+; --- Divide the 24 device IRQLs into 3 hardware priority levels
+; ...1 for each 8259 PIC grouping....PIC 1 is highest priority
+;
+; PIC3
+ db 6 SHL 4 ; IRQL = 4, tpr = 6:0 - IRQ23 -
+ db 6 SHL 4 ; IRQL = 5, tpr = 6:0 - IRQ22 -
+ db 6 SHL 4 ; IRQL = 6, tpr = 6:0 - IRQ21 -
+ db 6 SHL 4 ; IRQL = 7, tpr = 6:0 - IRQ20 -
+ db 6 SHL 4 ; IRQL = 8, tpr = 6:0 - IRQ19 -
+ db 6 SHL 4 ; IRQL = 9, tpr = 6:0 - IRQ18 -
+ db 6 SHL 4 ; IRQL = 10, tpr = 6:0 - IRQ17
+ db 6 SHL 4 ; IRQL = 11, tpr = 6:0 - IRQ16 -
+; PIC2
+ db 7 SHL 4 ; IRQL = 12, tpr = 7:0 - IRQ15 -
+ db 7 SHL 4 ; IRQL = 13, tpr = 7:0 - IRQ14 -
+ db 7 SHL 4 ; IRQL = 14, tpr = 7:0 - IRQ13 -
+ db 7 SHL 4 ; IRQL = 15, tpr = 7:0 - IRQ12 -
+ db 7 SHL 4 ; IRQL = 16, tpr = 7:0 - IRQ11 -
+ db 7 SHL 4 ; IRQL = 17, tpr = 7:0 - IRQ10 -
+ db 7 SHL 4 ; IRQL = 18, tpr = 7:0 - IRQ9 -
+ db 7 SHL 4 ; IRQL = 19, tpr = 7:0 - IRQ8 -
+; PIC1
+ db 8 SHL 4 ; IRQL = 20, tpr = 8:0 - IRQ7 -
+ db 8 SHL 4 ; IRQL = 21, tpr = 8:0 - IRQ6 -
+ db 8 SHL 4 ; IRQL = 22, tpr = 8:0 - IRQ5 -
+ db 8 SHL 4 ; IRQL = 23, tpr = 8:0 - IRQ4 -
+ db 8 SHL 4 ; IRQL = 24, tpr = 8:0 - IRQ3 -
+; IRQ2 is dropped due to being invalid
+ db 8 SHL 4 ; IRQL = 25, tpr = 8:0 - IRQ1 -
+ db 8 SHL 4 ; IRQL = 26, tpr = 8:0 - IRQ0 -
+;
+ db 9 SHL 4 ; IRQL = 27, tpr = 9:0 - Profile
+ db 10 SHL 4 ; IRQL = 28, tpr = 10:0 - Clock -
+ db 11 SHL 4 ; IRQL = 29, tpr = 11:0 - IPI -
+ db 12 SHL 4 ; IRQL = 30, tpr = 12:0 - Power
+ db 13 SHL 4 ; IRQL = 31, tpr = 13:0 - High
+;
+ align 4
+;
+; --- The following table is used to convert a given interrupt vector
+; to a specific APIC Redirection table entry address. The redirection
+; table entries are used to mask/unmask interrupts, target interrupts,
+; and specify vectors for APIC interrupts.
+;
+; The value of each table entry is defined as follows:
+;
+; 0ybbbbbbb - RDIR window address
+; y = 0 - EBS RDIR entry
+; y = 1 - Base Processor I/O APIC RDIR entry
+; bbbbbbb = I/O Window address of RDIR entry
+; 00 - Vector unused/invalid
+; FF - Vector used but no RDIR enable mask needed
+;
+
+ public _HalpK2Vector2RdirTabEntry
+_HalpK2Vector2RdirTabEntry label byte
+ db 000H ; Vector 0
+ db 0ACH ; Vector 2 - SYS_NMI - Base I/O APIC
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 10
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 20
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0FFH ; 30 - APC
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0FFH ; 40 - DPC
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 020H ; 60 - EBS RDIR 8 - IRQ16
+ db 02EH ; EBS RDIR 15 - IRQ17
+ db 02CH ; EBS RDIR 14 - IRQ18
+ db 02AH ; EBS RDIR 13 - IRQ19
+ db 028H ; EBS RDIR 12 - IRQ20
+ db 026H ; EBS RDIR 11 - IRQ21
+ db 024H ; EBS RDIR 10 - IRQ22
+ db 022H ; EBS RDIR 9 - IRQ23
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 70
+ db 018H ; EBS RDIR 4 - IRQ9
+ db 01AH ; EBS RDIR 5 - IRQ10
+ db 01CH ; EBS RDIR 6 - IRQ11
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 01EH ; EBS RDIR 7 - IRQ15
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 80
+ db 000H ;
+ db 000H ;
+ db 010H ; EBS RDIR 0 - IRQ3
+ db 012H ; EBS RDIR 1 - IRQ4
+ db 014H ; EBS RDIR 2 - IRQ5
+ db 000H ;
+ db 016H ; EBS RDIR 3 - IRQ7
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0FFH ; 90 - Profile
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; A0
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0FFH ; B0
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0A0H ; C0 - Power Fail, I/O RDIR 8
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; D0 - High
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0FFH ; E0 - APIC Spurious
+ db 0AAH ; E1 - SYS_INT I/O RDIR 13
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; F0
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; FF
+;
+;
+; The following table is used to convert a vector number to an
+; EISA IRQ number. It is used by Begin and End System interrupt
+; to know when to do an EOI for edge and level interrupt considerations
+;
+ align 4
+ public _HalpK2Vector2EISA
+_HalpK2Vector2EISA label byte
+ db 000H ; Vector 0
+ db 000H ; Vector 2 - SYS_NMI - Base I/O APIC
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 16
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 32
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 48 - APC
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 64 - DPC
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 16 ; 96 - IRQ16
+ db 17 ; - IRQ17
+ db 18 ; - IRQ18
+ db 19 ; - IRQ19
+ db 20 ; - IRQ20
+ db 21 ; - IRQ21
+ db 22 ; - IRQ22
+ db 23 ; - IRQ23
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 8 ; 112 - IRQ8
+ db 9 ; - IRQ9
+ db 10 ; - IRQ10
+ db 11 ; - IRQ11
+ db 12 ; - IRQ12
+ db 13 ; - IRQ13
+ db 14 ; - IRQ14
+ db 15 ; - IRQ15
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 0 ; 128 - IRQ0
+ db 1 ; - IRQ1
+ db 2 ; - IRQ2
+ db 3 ; - IRQ3
+ db 4 ; - IRQ4
+ db 5 ; - IRQ5
+ db 6 ; - IRQ6
+ db 7 ; - IRQ7
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 8 ; 144 - Profile
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 160 - IRQ0 , Clock
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 176 - IPI
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 192 - Power Fail, I/O RDIR 8
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 208 - High
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 224 - APIC Spurious
+ db 000H ; 225 - SYS_ATTN I/O RDIR 7
+ db 000H ; 226 - SYS_TIMEOUT " " 9
+ db 000H ; 227 - SYS_ERROR " " 10
+ db 000H ; 228 - SYS_EISA_PERR " 11
+ db 000H ; 229 - SYS_IMS_ATTN " 12
+ db 000H ; 230 - SYS_INT " " 13
+ db 000H ; 231 - LOCAL_RESET " " 15
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 240
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ;
+ db 000H ; 255
+;
+ align 4
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; This table is used to convert a designated IRQL number to
+; a specific interrupt vector. This is used by the generate
+; software interrupt mechanism and HalGetInterruptVector...
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ public _HalpIRQLtoTPR
+_HalpIRQLtoTPR label byte
+ db 0 ; IRQL = 0, tpr = 0 - Low
+ db APIC_APC_VECTOR ; IRQL = 1, tpr = 3 - APC
+ db APIC_DPC_VECTOR ; IRQL = 2, tpr = 4 - DPC
+ db 0 ; IRQL = 3, tpr = 5
+;
+; --- Divide the 24 device IRQLs into 3 hardware priority levels
+; ...1 for each 8259 PIC grouping....PIC 1 is highest priority
+;
+; PIC3
+ db APIC_IRQ23_VECTOR ; IRQL = 4, tpr = 6 - IRQ23
+ db APIC_IRQ22_VECTOR ; IRQL = 5, tpr = 6 - IRQ22
+ db APIC_IRQ21_VECTOR ; IRQL = 6, tpr = 6 - IRQ21
+ db APIC_IRQ20_VECTOR ; IRQL = 7, tpr = 6 - IRQ20
+ db APIC_IRQ19_VECTOR ; IRQL = 8, tpr = 6 - IRQ19
+ db APIC_IRQ18_VECTOR ; IRQL = 9, tpr = 6 - IRQ18
+ db APIC_IRQ17_VECTOR ; IRQL = 10, tpr = 6 - IRQ17
+ db APIC_IRQ16_VECTOR ; IRQL = 11, tpr = 6 - IRQ16
+; PIC2
+ db APIC_IRQ15_VECTOR ; IRQL = 12, tpr = 7 - IRQ15
+ db APIC_IRQ14_VECTOR ; IRQL = 13, tpr = 7 - IRQ14
+ db APIC_IRQ13_VECTOR ; IRQL = 14, tpr = 7 - IRQ13
+ db APIC_IRQ12_VECTOR ; IRQL = 15, tpr = 7 - IRQ12
+ db APIC_IRQ11_VECTOR ; IRQL = 16, tpr = 7 - IRQ11
+ db APIC_IRQ10_VECTOR ; IRQL = 17, tpr = 7 - IRQ10
+ db APIC_IRQ9_VECTOR ; IRQL = 18, tpr = 7 - IRQ9
+ db APIC_IRQ8_VECTOR ; IRQL = 19, tpr = 7 - IRQ8
+; PIC1
+ db APIC_IRQ7_VECTOR ; IRQL = 20, tpr = 8 - IRQ7
+ db APIC_IRQ6_VECTOR ; IRQL = 21, tpr = 8 - IRQ6
+ db APIC_IRQ5_VECTOR ; IRQL = 22, tpr = 8 - IRQ5
+ db APIC_IRQ4_VECTOR ; IRQL = 23, tpr = 8 - IRQ4
+ db APIC_IRQ3_VECTOR ; IRQL = 24, tpr = 8 - IRQ3
+ db APIC_IRQ1_VECTOR ; IRQL = 25, tpr = 8 - IRQ1
+ db APIC_IRQ0_VECTOR ; IRQL = 26, tpr = 8 - IRQ0
+;
+ db APIC_PROFILE_VECTOR ; IRQL = 27, tpr = 9 - Profile
+ db APIC_CLOCK_VECTOR ; IRQL = 28, tpr = 10 - Clock
+ db APIC_IPI_VECTOR ; IRQL = 29, tpr = 11 - IPI
+ db APIC_POWERFAIL_VECTOR ; IRQL = 30, tpr = 12 - Power
+ db APIC_HIGH_VECTOR ; IRQL = 31, tpr = 13 - High
+;
+;
+; This table is used by HalGetInterruptVector to convert a
+; traditional EISA/ISA IRQ to an NT IRQL value.
+;
+ align 4
+ public _HalpK2EISAIrq2Irql
+_HalpK2EISAIrq2Irql label byte
+ db CLOCK2_LEVEL ; INTI 0 - system clock
+ db 25 ; INTI 1 - keyboard
+ db 24 ; INTI 2 - unused
+ db 24 ; INTI 3 - COM2
+ db 23 ; INTI 4 - COM1
+ db 22 ; INTI 5 - LPT2
+ db 21 ; INTI 6 - floppy
+ db 20 ; INTI 7 - LPT1
+ db 19 ; INTI 8 - RTC
+ db 18 ; INTI 9 - EISA IRQ9
+ db 17 ; INTI 10 - EISA IRQ10
+ db 16 ; INTI 11 - EISA IRQ11
+ db 15 ; INTI 12 - Mouse
+ db 14 ; INTI 13 - DMA
+ db 13 ; INTI 14 - IDE disk
+ db 12 ; INTI 15 - EISA IRQ15
+ db 11 ; INTI 16 - K2 IRQ 16
+ db 10 ; INTI 17 - K2 IRQ 17
+ db 9 ; INTI 18 - K2 IRQ 18
+ db 8 ; INIT 19 - K2 IRQ 19
+ db 7 ; INIT 20 - K2 IRQ 20
+ db 6 ; INIT 21 - K2 IRQ 21
+ db 5 ; INIT 22 - K2 IRQ 22
+ db 4 ; INIT 23 - K2 IRQ 23
+;
+; The following table is used to convert an IRQL to a corresponding
+; EISA IRQ. This is used to determine in BeginInterrupt and
+; EndInterrupt how do do EOI processing for edge/level EISA
+; interrupts. IRQ0 is always designated as edge and will not
+; change. We use this for all Irqls which do not correspond
+; to EISA IRQ numbers
+;
+ align 4
+ public _HalpK2Irql2Eisa
+_HalpK2Irql2Eisa label byte
+ db 0 ; IRQL = 0, tpr = 0 - Low
+ db 0 ; IRQL = 1, tpr = 3 - APC
+ db 0 ; IRQL = 2, tpr = 4 - DPC
+ db 0 ; IRQL = 3, tpr = 5
+;
+; --- Divide the 24 device IRQLs into 3 hardware priority levels
+; ...1 for each 8259 PIC grouping....PIC 1 is highest priority
+;
+; PIC3
+ db 0 ; IRQL = 4, tpr = 6 - IRQ23
+ db 0 ; IRQL = 5, tpr = 6 - IRQ22
+ db 0 ; IRQL = 6, tpr = 6 - IRQ21
+ db 0 ; IRQL = 7, tpr = 6 - IRQ20
+ db 0 ; IRQL = 8, tpr = 6 - IRQ19
+ db 0 ; IRQL = 9, tpr = 6 - IRQ18
+ db 0 ; IRQL = 10, tpr = 6 - IRQ17
+ db 0 ; IRQL = 11, tpr = 6 - IRQ16
+; PIC2
+ db 15 ; IRQL = 12, tpr = 7 - IRQ15
+ db 14 ; IRQL = 13, tpr = 7 - IRQ14
+ db 13 ; IRQL = 14, tpr = 7 - IRQ13
+ db 12 ; IRQL = 15, tpr = 7 - IRQ12
+ db 11 ; IRQL = 16, tpr = 7 - IRQ11
+ db 10 ; IRQL = 17, tpr = 7 - IRQ10
+ db 9 ; IRQL = 18, tpr = 7 - IRQ9
+ db 8 ; IRQL = 19, tpr = 7 - IRQ8
+; PIC1
+ db 7 ; IRQL = 20, tpr = 8 - IRQ7
+ db 6 ; IRQL = 21, tpr = 8 - IRQ6
+ db 5 ; IRQL = 22, tpr = 8 - IRQ5
+ db 4 ; IRQL = 23, tpr = 8 - IRQ4
+ db 3 ; IRQL = 24, tpr = 8 - IRQ3
+ db 1 ; IRQL = 25, tpr = 8 - IRQ1
+ db 0 ; IRQL = 26, tpr = 8 - IRQ0
+;
+ db 0 ; IRQL = 27, tpr = 9 - Profile
+ db 0 ; IRQL = 28, tpr = 10 - Clock
+ db 0 ; IRQL = 29, tpr = 11 - IPI
+ db 0 ; IRQL = 30, tpr = 12 - Power
+ db 0 ; IRQL = 31, tpr = 13 - High
+;
+
+;
+; _HalpK2EbsIOunitRedirectionTable is the memory image of the redirection table to be
+; loaded into APIC I/O unit 0 at initialization. there is one 64-bit entry
+; per interrupt input to the I/O unit. the edge/level trigger mode bit will
+; be set dynamically when the table is actually loaded. the mask bit is set
+; initially, and reset by EnableSystemInterrupt.
+;
+ align dword
+ public _HalpK2EbsIOunitRedirectionTable
+_HalpK2EbsIOunitRedirectionTable label dword
+
+ ; INTI0 - EISA IRQ3
+
+ dd APIC_IRQ3_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI1 - EISA IRQ4
+
+ dd APIC_IRQ4_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI2 - EISA IRQ5
+
+ dd APIC_IRQ5_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI3 - EISA IRQ7
+
+ dd APIC_IRQ7_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI4 - EISA IRQ9
+
+ dd APIC_IRQ9_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI5 - EISA IRQ10
+
+ dd APIC_IRQ10_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI6 - EISA IRQ11
+
+ dd APIC_IRQ11_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI7 - EISA IRQ15
+
+ dd APIC_IRQ15_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI8 - PowerBus IRQ16
+
+ dd APIC_IRQ16_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI9 - PowerBus IRQ23
+
+ dd APIC_IRQ23_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI10 - PowerBus IRQ22
+
+ dd APIC_IRQ22_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI11 - PowerBus IRQ21
+
+ dd APIC_IRQ21_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI12 - PowerBus IRQ20
+
+ dd APIC_IRQ20_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI13 - PowerBus IRQ19
+
+ dd APIC_IRQ19_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI14 - PowerBus IRQ18
+
+ dd APIC_IRQ18_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; INTI15 - PowerBus IRQ17
+
+ dd APIC_IRQ17_VECTOR + INTERRUPT_MASKED + \
+ DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION
+ dd DESTINATION_ALL_CPUS
+
+ ; zero entry indicates end of table
+
+ dd 0
+;
+;
+; The following table is used to convert a RDIR # on the EBS
+; I/O APIC to an EISA IRQ
+;
+ align 4
+ public _HalpK2Rdir2Irq
+_HalpK2Rdir2Irq label byte
+ db 3 ; RDIR = 0, IRQ = 3
+ db 4 ; RDIR = 1, IRQ = 4
+ db 5 ; RDIR = 2, IRQ = 5
+ db 7 ; RDIR = 3, IRQ = 7
+ db 9 ; RDIR = 4, IRQ = 9
+ db 10 ; RDIR = 5, IRQ = 10
+ db 11 ; RDIR = 6, IRQ = 11
+ db 15 ; RDIR = 7, IRQ = 15
+ db 16 ; RDIR = 8, IRQ = 16
+ db 23 ; RDIR = 9, IRQ = 23
+ db 22 ; RDIR = 10, IRQ = 22
+ db 21 ; RDIR = 11, IRQ = 21
+ db 20 ; RDIR = 12, IRQ = 20
+ db 19 ; RDIR = 13, IRQ = 19
+ db 18 ; RDIR = 14, IRQ = 18
+ db 17 ; RDIR = 15, IRQ = 17
+;
+; _HalpW3BaseIOunitRedirectionTable is the memory image of the
+; redirection table to be loaded into APIC I/O unit 1 at initialization.
+; there is one 64-bit entry per interrupt input to the I/O unit.
+;
+ align 4
+ public _HalpW3BaseIOunitRedirectionTable
+_HalpW3BaseIOunitRedirectionTable label dword
+
+ ; INTI0 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI1 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI2 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI3 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+
+ ; INTI4 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+
+ ; INTI5 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI6 - Unused
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI7 - SYS_ATTN_L
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI8 - SYS_POWER_FAIL
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI9 - SYS_TIMEOUT
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI10 - SYS_ERROR
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI11 - SYS_EISA_PERR
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI12 - SYS_IMS_ATTN
+
+ dd INTERRUPT_MASKED
+ dd 0
+
+ ; INTI13 - SYS_INT
+
+ dd APIC_SYSINT_VECTOR + DELIVER_EXTINT + LOGICAL_DESTINATION
+ dd DESTINATION_CPU_0
+
+ ; INTI14 - SYS_NMI
+
+ dd DELIVER_NMI + LEVEL_TRIGGERED + LOGICAL_DESTINATION
+ dd DESTINATION_CPU_0
+
+ ; INTI15 - LOC_RESET_CPU
+
+ dd DELIVER_NMI + LEVEL_TRIGGERED + LOGICAL_DESTINATION
+ dd DESTINATION_CPU_0
+
+ ; zero entry indicates end of table
+
+ dd 0
+_DATA ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halws3/i386/w3spin.asm b/private/ntos/nthals/halws3/i386/w3spin.asm
new file mode 100644
index 000000000..32746cfb6
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3spin.asm
@@ -0,0 +1,389 @@
+if NT_INST
+
+else
+ TITLE "Spin Locks"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; spinlock.asm
+;
+; Abstract:
+;
+; This module implements stubbed x86 spinlock functions for
+; any HAL. Some HALs may implement these function directly
+; to minimize the amount of code required to perform a spinlock.
+; (ie, out Raise & Lower irql in the fall through path)
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 13 Dec 89
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ken Reneris (kenr) 22-Jan-1991
+;--
+
+ PAGE
+
+.486p
+
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include hal386.inc
+include mac386.inc
+
+ EXTRNP KfRaiseIrql, 1,,FASTCALL
+ EXTRNP KfLowerIrql, 1,,FASTCALL
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ PAGE
+ SUBTTL "Acquire Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; (al) = OldIrql - old irql
+;
+;--
+
+align 16
+cPublicFastCall KfAcquireSpinLock ,1
+cPublicFpo 0,0
+
+
+ifdef NT_UP ; On up build just perform raiseirql
+
+ jmp @KfRaiseIrql@4 ; (al) = oldIrql
+else
+
+;
+; On a MP build we raise to dispatch_level
+; and then acquire the spinlock
+;
+
+ push ecx ; Save address of spin lock
+
+ mov ecx, DISPATCH_LEVEL ; (cl) = newIrql
+ fstCall KfRaiseIrql ; (al) = oldIrql
+
+ pop ecx ; (ecx) -> spinlock
+
+;
+; Attempt to assert the lock
+;
+
+sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
+
+ fstRET KfAcquireSpinLock ; (al) = oldIrql
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sl20: SPIN_ON_SPINLOCK ecx,sl10
+
+endif
+
+fstENDP KfAcquireSpinLock
+
+
+ PAGE
+ SUBTTL "Acquire Synch Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired,
+; any spin should occur at OldIrql)
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+;
+; Disable interrupts
+;
+
+sls10: cli
+
+;
+; Try to obtain spinlock. Use non-lock operation first
+;
+ TEST_SPINLOCK ecx,<short sls20>
+ ACQUIRE_SPINLOCK ecx,<short sls20>
+
+
+;
+; Got the lock, raise to SYNCH_LEVEL
+;
+
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+;
+; Enable interrupts and return
+;
+
+ sti
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sls20: sti
+ SPIN_ON_SPINLOCK ecx,sls10
+
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+
+ifndef NT_UP
+cPublicFpo 2,0
+
+ RELEASE_SPINLOCK ecx ; release it
+endif
+ mov ecx, edx
+ jmp @KfLowerIrql@4 ; to KeLowerIrql
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ push ecx ; Push FAST_MUTEX addr
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql
+
+ pop ecx ; (ecx) = Fast Mutex
+
+cPublicFpo 0,0
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,1
+ push ecx
+ push eax
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax
+ pop ecx
+
+cPublicFpo 0,0
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+
+;
+; Try to acquire
+;
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam25 ; Yes, abort
+
+cPublicFpo 0,1
+ push ecx ; Push FAST_MUTEX
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ mov ecx, [esp] ; Restore FAST_MUTEX
+ mov [esp], eax ; Save OldIrql
+
+ mov eax, 1 ; Value to compare against
+ mov edx, 0 ; Value to set
+ lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire
+ jnz short tam20 ; got it?
+
+cPublicFpo 0,0
+ pop edx ; (edx) = OldIrql
+ mov eax, 1 ; return TRUE
+ mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql
+ fstRet ExTryToAcquireFastMutex
+
+tam20: pop ecx ; (ecx) = OldIrql
+ fstCall KfLowerIrql ; restore OldIrql
+tam25: xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz @KfLowerIrql@4 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+ jmp @KfLowerIrql@4
+
+
+fstENDP ExReleaseFastMutex
+
+_TEXT ends
+
+ENDIF ; NT_INST
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3sproc.c b/private/ntos/nthals/halws3/i386/w3sproc.c
new file mode 100644
index 000000000..54a5b5395
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3sproc.c
@@ -0,0 +1,710 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Sequent Computer Systems, Inc.
+
+Module Name:
+
+ w3sproc.c
+
+Abstract:
+
+ WinServer 3000 Start Next Processor C code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ WinServer 3000.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+ Phil Hochstetler (phil@sequent.com) 3-30-93
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "apic.inc"
+#include "w3.inc"
+#include "halver.h"
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+ULONG
+HalpGetW3EisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+VOID HalpInitOtherBuses (VOID);
+
+#define LOW_MEMORY 0x000100000
+#define MAX_PT 8
+
+extern VOID StartPx_PMStub(VOID);
+extern PKPCR HalpProcessorPCR[];
+
+
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR MppIDT; // pointer to physical memory 0:0
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+#ifndef NT_UP
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ PKPCR pPCR;
+
+ pPCR = KeGetPcr();
+
+ if (Phase == 0) {
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress)
+ return TRUE;
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 for another processor
+ //
+
+ }
+}
+#endif
+
+VOID
+HalpFatal (
+ IN PCHAR ErrorCode
+ )
+
+/*++
+
+Routine Description:
+
+ Print the fatal error code and direct end user to
+ call service representitive for help.
+
+Arguments:
+
+ ErrorCode - the error code string to print on error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalDisplayString("HAL: FATAL error #");
+ HalDisplayString(ErrorCode);
+ HalDisplayString(" has occured.\n");
+ HalDisplayString("HAL: Call your service representitive for help.\n");
+ HalDisplayString(MSG_HALT);
+ KeEnterKernelDebugger();
+}
+
+
+VOID
+HalpCheckHw (
+ )
+
+/*++
+
+Routine Description:
+
+ Verify different aspects of the hardware to assure
+ the current hardware is both a WinServer and running
+ sufficient level hardware to support Windows NT.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNICODE_STRING unicodeValueName;
+ UNICODE_STRING KeyName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
+ NTSTATUS NtStatus;
+ HANDLE SystemHandle;
+ UCHAR KeyValueBuffer[512];
+ ULONG resultLength;
+ PWSTR s;
+ ULONG m, d, y;
+
+ KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
+
+ RtlInitUnicodeString(
+ &unicodeValueName,
+ L"\\Registry\\Machine\\Hardware\\Description\\System"
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &unicodeValueName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ NtStatus = ZwOpenKey(
+ &SystemHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS( NtStatus ))
+ HalpFatal("1015801");
+
+ RtlInitUnicodeString( &KeyName, L"SystemBiosDate" );
+
+ NtStatus = ZwQueryValueKey(
+ SystemHandle,
+ &KeyName,
+ KeyValuePartialInformation,
+ KeyValueInformation,
+ sizeof(KeyValueBuffer),
+ &resultLength
+ );
+
+ if (!NT_SUCCESS( NtStatus )
+ || KeyValueInformation->Type != REG_SZ
+ || KeyValueInformation->DataLength < 16
+ )
+ HalpFatal("1015802");
+
+ //
+ // Bios date must be greater than or equal to "02/27/93"
+ //
+
+ s = (PWSTR)KeyValueInformation->Data;
+ m = (*s++ - L'0') * 10; m += (*s++ - L'0'); *s++; // skip '/'
+ d = (*s++ - L'0') * 10; d += (*s++ - L'0'); *s++; // skip '/'
+ y = (*s++ - L'0') * 10; y += (*s++ - L'0');
+
+ if ((y * 365) + (m * 31) + d < (93 * 365) + (2 * 31) + 27)
+ HalpFatal("1015803");
+
+ RtlInitUnicodeString( &KeyName, L"VideoBiosVersion" );
+
+ NtStatus = ZwQueryValueKey(
+ SystemHandle,
+ &KeyName,
+ KeyValueBasicInformation,
+ KeyValueInformation,
+ sizeof(KeyValueBuffer),
+ &resultLength
+ );
+
+ if (!NT_SUCCESS( NtStatus )
+ || KeyValueInformation->Type != REG_MULTI_SZ
+ )
+ HalpFatal("1015804");
+
+ ZwClose(SystemHandle);
+
+ RtlInitUnicodeString(
+ &unicodeValueName,
+ L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter\\0\\DiskController"
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &unicodeValueName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ NtStatus = ZwOpenKey(
+ &SystemHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS( NtStatus ))
+ HalpFatal("1015805");
+
+ ZwClose(SystemHandle);
+
+ RtlInitUnicodeString(
+ &unicodeValueName,
+ L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter\\0\\DisplayController"
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &unicodeValueName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ NtStatus = ZwOpenKey(
+ &SystemHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS( NtStatus ))
+ HalpFatal("1015806");
+
+ ZwClose(SystemHandle);
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Eisa // WinServer 3000 is an EISA machine
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Take advantage of the registry being enabled to check
+ // it for a WinServer with the proper hardware support.
+ //
+
+ HalpCheckHw();
+
+}
+
+
+VOID
+HalpRebootNow(
+ )
+/*++
+--*/
+{
+#define KEYBPORT (PUCHAR)0x64
+#define RESET 0xfe
+
+#ifndef NT_UP
+ PKPCR pPCR;
+ PWS3_HAL_PRIVATE pPriv;
+ USHORT FCRAddr;
+ UCHAR i;
+ UCHAR Me;
+
+ pPCR = KeGetPcr();
+ pPriv = (PWS3_HAL_PRIVATE) &pPCR->HalReserved[0];
+ Me = pPriv->PcrNumber;
+
+ //
+ // Reset each of the slaves and issue the reset command.
+ //
+
+ for (i = 1; HalpProcessorPCR[i]; i++) {
+
+ //
+ // Never reset myself
+ //
+
+ if (i == Me)
+ continue;
+
+ //
+ // Put processor into reset by setting the FCR reset bit
+ //
+
+ pPriv = (PWS3_HAL_PRIVATE) &HalpProcessorPCR[i]->HalReserved[0];
+ FCRAddr = pPriv->ProcSlotAddr | FCR;
+ WRITE_PORT_USHORT((PUSHORT) FCRAddr,
+ (USHORT)(READ_PORT_USHORT((PUSHORT) FCRAddr) |
+ ((USHORT) FCR_RESET_MASK)));
+ }
+
+ //
+ // Send the reset command to the keyboard controller
+ //
+
+ for (;;) {
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+ KeStallExecutionProcessor(30 * 1000000);
+ }
+#else
+ //
+ // Send the reset command to the keyboard controller
+ //
+
+ for (;;) {
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+ KeStallExecutionProcessor(30 * 1000000);
+ }
+#endif
+}
+
+VOID
+HalpResetAllProcessors (
+ )
+/*++
+
+Routine Description:
+ Called very late in the process of rebooting the machine
+ from HalpReboot() to attempt to put the machine in a state
+ where sending the reset command to the keyboard controller will
+ actually reboot the machine.
+
+ On a WinServer 3000, only the P0 processor will see the system
+ reset line so we must attempt to shutdown each of the slaves.
+ If the P0 processor is not responding, then we make a best attempt.
+ Also, this has some implication on leaving errors asserted (like
+ the APIC NMI state) which the BIOS does not handle.
+
+ N.B. Is is critical that we do not put P0 into reset by writing
+ the feature control register (FCR) because it will not see the
+ reset and the system will hang.
+
+Arguments:
+ None.
+
+Return Value:
+ None.
+
+--*/
+{
+#ifdef NT_UP
+ HalDisplayString("System Reboot in progress.\n");
+ HalDisplayString("Please wait while the system reboots.\n");
+ HalpRebootNow();
+#else
+ PWS3_HAL_PRIVATE pPriv;
+ PKPCR pPCR;
+
+ pPCR = KeGetPcr();
+ pPriv = (PWS3_HAL_PRIVATE) &pPCR->HalReserved[0];
+
+ HalDisplayString("System Reboot in progress.\n");
+ HalDisplayString("Please wait while the system reboots.\n");
+
+ if (pPriv->PcrNumber == 0)
+ HalpRebootNow();
+
+ //
+ // On P1-PN, so try to signal P0 to reboot the system by
+ // taking over P0's IPI handler and sending an IPI.
+ //
+
+ HalpProcessorPCR[0]->IDT[APIC_IPI_VECTOR].ExtendedOffset = HIGHWORD(HalpRebootNow);
+ HalpProcessorPCR[0]->IDT[APIC_IPI_VECTOR].Offset = LOWWORD(HalpRebootNow);
+ HalRequestIpi(1);
+ KeStallExecutionProcessor(30 * 1000000);
+
+ //
+ // We only reach here if P0 fails to reboot the system.
+ // Try to reset all the slaves but our self and P0 and
+ // then try to reboot. This is the last attempt and
+ // if it fails, we will probably hang the system.
+ //
+
+ HalpRebootNow();
+#endif
+}
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Change GetInterruptVector handler on Eisa Bus 0 to a
+ // Winserver specific handler which supports the Winserver's
+ // Eisa interrupt vectors 16-23.
+ //
+
+ Bus = HalpHandlerForBus (Eisa, 0);
+ Bus->GetInterruptVector = HalpGetW3EisaInterruptVector;
+
+ //
+ // no other internal buses supported
+ //
+}
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halws3/i386/w3sproca.asm b/private/ntos/nthals/halws3/i386/w3sproca.asm
new file mode 100644
index 000000000..8c0fe0b37
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3sproca.asm
@@ -0,0 +1,377 @@
+ title "MP primitives for WinServer 3000"
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3sproca.asm
+;
+; Abstract:
+;
+; WinServer 3000 Start Next Processor assembly code
+;
+; This module along with w3sproc.c implement the code to start
+; off the mulitple processors on the WinServer 3000.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Revision History:
+;
+;--
+.386p
+ .xlist
+include ks386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _ExAllocatePool,2
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+ EXTRNP _HalpUnResetLocalUnit,1
+
+ extrn _MppIDT:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+ extrn _ProcessorsPresent:DWORD
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ WS3_flag dd ?
+ WS3_TiledCR3 dd ?
+ WS3_P0EBP dd ?
+ WS3_ControlPort dd ?
+ WS3_PB db ProcessorStateLength dup (?)
+PxParamBlock ends
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+;
+; CMOS equates for warm boot
+;
+CMOS_ADDR EQU 70h
+CMOS_DATA EQU 71h
+CMOSCTL EQU 0Fh
+CMOSWARMBOOT EQU 0Ah
+;
+
+cPublicProc _HalStartNextProcessor ,2
+
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.WS3_flag, eax
+
+ cmp _ProcessorsPresent, eax ; any processors left to start
+ je snp_exit ; exit FALSE
+;
+ bsf eax, _ProcessorsPresent ; get slot index
+ btr _ProcessorsPresent, eax ; clear slot index
+ shl eax, EISA_SHIFT
+ or eax,FCR ; Create Control Port Address
+ mov PxFrame.WS3_ControlPort, eax ; Store in Frame
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+ mov edi, _MpLowStub ; Copy RMStub to low memory
+ add edi, size PxParamBlock
+ rep movsb
+
+ lea edi, PxFrame.WS3_PB
+ mov esi, pProcessorState
+ mov ecx, ProcessorStateLength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+ stdCall _HalpBuildTiledCR3, <pProcessorState>
+
+ mov PxFrame.WS3_TiledCR3, eax
+ mov PxFrame.WS3_P0EBP, ebp
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _MpLowStub
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.WS3_PB.PsContextFrame.CsSegCs]
+ mov [eax.W3rxFlatCS], bx ; patch realmode stub with
+ mov [eax.W3rxPMStub], offset _StartPx_PMStub ; valid long jump
+
+ mov ebx, _MppIDT
+ add ebx, WarmResetVector
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+
+ mov eax, _MpLowStubPhysicalAddress
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+
+ mov eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+ stdCall _HalpUnResetLocalUnit,<eax>
+
+ mov edx, PxFrame.WS3_ControlPort ; Control port of target
+ mov al,CMOSCTL
+ out CMOS_ADDR,al ; Tell BIOS its warm BOOT
+ mov al,CMOSWARMBOOT
+ out CMOS_DATA,al
+ in ax, dx ; processor
+ and ax, NOT FCR_RESET_MASK ; remove Reset bit
+ out dx, ax ; bring Pn out of reset
+@@:
+ cmp PxFrame.WS3_flag, 0 ; wait for Px to get it's
+ jz @b ; info
+
+; REMOVE THIS CODE FRAGMENT WHEN WE FORCE BIOS REV TO BE 4.0 OR GREATER
+
+ mov al,0 ; Re-enable NMI in ISP
+ out CMOS_ADDR,al ; because pre 4.0 BIOS
+ ; code executed by
+ ; Px leaves it disabled.
+
+; REMOVE THIS CODE FRAGMENT WHEN WE FORCE BIOS REV TO BE 4.0 OR GREATER
+
+ pop dword ptr [ebx] ; restore WarmResetVector
+ sti
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+
+ mov eax, 1 ; return TRUE
+
+snp_exit:
+
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+
+ stdRET _HalStartNextProcessor
+
+stdENDP _HalStartNextProcessor
+
+
+_TEXT ends ; end 32 bit code
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub ,0
+cPublicFpo 0, 0
+
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[WS3_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[WS3_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[WS3_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[WS3_P0EBP]
+ mov ecx, dword ptr cs:[WS3_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[WS3_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[WS3_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ db 0eah ; reload cs:eip
+W3rxPMStub dd 0
+W3rxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+stdENDP StartPx_RMStub
+
+
+_TEXT16 ends ; End 16 bit code
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+
+cPublicProc _StartPx_PMStub ,0
+cPublicFpo 0, 0
+
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.WS3_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.WS3_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+;
+ inc [PxFrame.WS3_flag] ; Signal p0 that we are
+ ; done with it's data
+ ; Set remaining registers
+
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+
+ stdRET _StartPx_PMStub ; Set eip
+
+stdENDP _StartPx_PMStub
+
+_TEXT ends ; end 32 bit code
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3stall.asm b/private/ntos/nthals/halws3/i386/w3stall.asm
new file mode 100644
index 000000000..588878a83
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3stall.asm
@@ -0,0 +1,382 @@
+
+ title "Stall Execution Support"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3stall.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to stall the processor
+; for some specified period of time.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com)
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\ixcmos.inc
+include i386\w3.inc
+
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn _HalpLocalUnitBase:DWORD
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; HalpInitializeStallExecution (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+; Note:
+;
+; This routine is called from the HalInitSystem routine in w3hal.c.
+; It is only called during Phase 0 init on P0
+;
+;--
+
+;
+; Local Variables - These are valid even in the Isr because we're the only thing
+; running on this processor and no-one else will change the ebp
+; register.
+
+StallIDTPointer equ [ebp-6]
+StallIDTArea equ [ebp-8]
+StallInterruptCount equ [ebp-12]
+StallLVTentry equ dword ptr [ebp-16]
+StallDummyentry0 equ dword ptr [ebp-20]
+StallDummyentry1 equ [ebp-24]
+StallApicTpr equ dword ptr [ebp-28]
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+cPublicProc _HalpInitializeStallExecution,1
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 28 bytes for local use
+ sub esp, 32
+
+ pushfd ; save caller's eflag
+
+;
+; --- For an APIC implementaion we use the APIC timer0 and install a
+; --- Local Vector Table entry to point to a high priority
+; --- vector for the Timer0 Interrupt. Then use the TPR in the local APIC
+; --- to mask out every thing below it. To this end we've reserved a vector
+; --- in the highest priority group (0F8) to be used here.
+;
+
+;
+; Since APIC timer interrupt will come from APIC_STALL_VECTOR, we need to
+; Save original APIC_STALL_VECTOR descriptor and set the descriptor
+; to point to our own handler.
+;
+ sidt fword ptr StallIDTArea ; get IDT address
+ mov edx, StallIDTPointer ; (edx)->IDT
+
+;
+; --- Save Original Descriptor on Stack
+;
+ push dword ptr [edx+8*APIC_STALL_VECTOR]; (TOS) = orig. Vector
+ push dword ptr [edx+8*APIC_STALL_VECTOR + 4]
+ push edx ; (TOS) -> IDT
+;
+; --- Install our IDT entry
+;
+ mov eax, offset FLAT:ApicTimer0Handler
+ mov word ptr [edx+8*APIC_STALL_VECTOR], ax ; Low half handler addr
+ mov word ptr [edx+8*APIC_STALL_VECTOR+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [edx+8*APIC_STALL_VECTOR+4], D_INT032 ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*APIC_STALL_VECTOR+6], ax
+;
+; --- Init. interrupt Flag
+;
+ mov dword ptr StallinterruptCount, 0 ; set no interrupt yet
+
+ ;
+ ; Get the Local Vector Table Timer Zero entry and save it
+ ;
+ mov edx, _HalpLocalUnitBase ; get the current TPR
+ mov eax, [edx+LU_TIMER_VECTOR] ; get Timer zero LVT
+ mov StallLVTentry, eax ; Save LVT
+
+ ;
+ ; --- Set the Inital Timer count
+ ; --- Note: we will use TMBASE with No Divider
+ ; --- which runs at 11 Mhz
+ ;
+
+ mov eax,(PeriodInUsec*11) ; Set the initial TIMER0 count
+ mov [edx+LU_INITIAL_COUNT], eax
+ ;
+ ; Save then set the Local APIC's TPR to mask all interrupts except the
+ ; highest priority group
+ ;
+
+ mov eax, [edx+LU_TPR] ; get TPR
+ mov StallApicTpr, eax ; save TPR for later
+
+ ;
+ ; Set TPR (Priority of CPU) = TPR (VECTOR - 16). So that all interrupts
+ ; in VECTOR's priority group will be allowed in.
+ ;
+ mov eax, APIC_STALL_VECTOR-10H
+ mov [edx+LU_TPR], eax ; Write the new TPR
+ ;
+ ;
+ ; --- Create Timer zero entry and store in Local Vector Table
+ ; --- STARTING the clock
+ ;
+ mov eax,(00040000H OR PERIODIC_TIMER)
+ or eax,(INTERRUPT_MOT_MASKED OR APIC_STALL_VECTOR)
+@@:
+ test [edx+LU_TIMER_VECTOR], DELIVERY_PENDING
+ jnz @b
+
+ mov [edx+LU_TIMER_VECTOR], eax
+;
+; --- Now enable the interrupt and start the counter
+;
+
+ xor eax, eax ; (eax) = 0, initialize loopcount
+;
+; --- ENABLE TIMER ZERO INTERRUPT
+;
+ sti
+;
+; --- BEGIN SPIN Calibration LOOP
+;
+
+Stall10:
+ add eax, 1 ; increment the loopcount
+ jnz short Stall10
+;
+; Counter overflowed
+;
+
+ stdCall _DbgBreakPoint
+
+;++
+;
+; VOID
+; ApicTimer0Handler(
+; );
+;
+;Routine Description:
+;
+; APIC Timer zero interrupt Handler for Calibrating Spin Loop for
+; KeStallExecution();
+;
+; Note: we discard first real time clock interrupt and compute the
+; permicrosecond loopcount on receiving of the second real time
+; interrupt. This is because the first interrupt is generated
+; based on the previous real time tick interval.
+;
+;--
+ Public ApicTimer0Handler
+
+ApicTimer0Handler:
+
+ inc dword ptr StallInterruptCount ; increment interrupt count
+ cmp dword ptr StallInterruptCount,1 ; Is this the first interrupt?
+ jnz Stall25 ; no, its the second go process it
+
+ pop eax ; get rid of original ret addr
+ push offset FLAT:Stall10 ; set new ret addr --> top of loop
+
+ ;
+ ; EOI the Local Apic, the value written is immaterial
+ ;
+
+ mov eax, _HalpLocalUnitBase ; write to local unit EOI register
+ mov dword ptr [eax+LU_EOI], 0
+;
+ xor eax, eax ; reset loop counter
+;
+ iretd
+;
+; --- Process EAX for Spin Count
+;
+;
+Stall25:
+
+ifdef DBG
+ cmp eax, 0
+ jnz short Stall30
+
+ stdCall _DbgBreakPoint
+endif
+;
+Stall30:
+
+ xor edx, edx ; (edx:eax) = dividend
+ mov ecx, PeriodInUSec; ; (ecx) = time spent in the loop
+ div ecx ; (eax) = loop count per microsecond
+ cmp edx, 0 ; Is remainder =0?
+ jz short Stall40 ; yes, go Stall40
+ inc eax ; increment loopcount by 1
+;
+Stall40:
+ movzx ecx, byte ptr [ebp+8] ; Current processor number
+
+ mov PCR[PcStallScaleFactor], eax
+;
+; Reset return address to kexit
+;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+
+ ;
+ ; EOI the Local Apic, the value written is immaterial
+ ;
+
+ mov eax, _HalpLocalUnitBase ; write the local unit EOI register
+ mov dword ptr [eax+LU_EOI], 0
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+;
+ iretd
+;
+;
+; --- Calibration is Done Restore all values and exit
+; --- Interrupts are disabled
+;
+kexit:
+ ;
+ ; Turn OFF TIMER ZERO
+ ;
+ ;
+ mov edx, _HalpLocalUnitBase
+ mov eax, StallLVTentry ; get Saved LVT
+
+@@:
+ test [edx+LU_TIMER_VECTOR], DELIVERY_PENDING
+ jnz @b
+
+ mov [edx+LU_TIMER_VECTOR], eax
+;
+; --- Restore the interrupt vector we used
+;
+ pop edx ; (edx)->IDT
+ pop [edx+8*APIC_STALL_VECTOR+4] ; higher half of desc
+ pop [edx+8*APIC_STALL_VECTOR] ; lower half of desc
+
+;
+; --- Restore the Local APIC's TPR
+;
+
+ mov eax, StallApicTpr ; get the saved TPR
+ mov edx, _HalpLocalUnitBase ; write old value to TPR
+ mov [edx+LU_TPR], eax
+
+
+ sub esp, 32
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+
+ stdRET _HalpInitializeStallExecution
+
+stdENDP _HalpInitializeStallExecution
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+cPublicProc _KeStallExecutionProcessor ,1
+cPublicFpo 1, 0
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+
+ mul ecx ; (eax) = desired loop count
+
+ifdef DBG
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short @f
+ int 3
+
+@@: cmp eax,0
+ jnz short @f
+ int 3
+endif
+
+ALIGN 4
+@@:
+ sub eax, 1 ; (eax) = (eax) - 1
+ jnz short @b
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3swint.asm b/private/ntos/nthals/halws3/i386/w3swint.asm
new file mode 100644
index 000000000..1becece07
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3swint.asm
@@ -0,0 +1,317 @@
+ title "Software Interrupts"
+;++
+;
+; Copyright (c) 1992 Microsoft Corporation
+; Copyright (c) 1992 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3swint.asm
+;
+; Abstract:
+;
+; This module implements the software interrupt handlers for the
+; APIC-based WinServer 3000 multiprocessor.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include i386\apic.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _KeBugCheck,1
+ EXTRNP KfLowerIrql,1,IMPORT,FASTCALL
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+
+ extrn _HalpIRQLtoTPR:byte
+ extrn _HalpLocalUnitBase:dword
+ extrn _HalpIrql2IRRMask:dword
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+
+ page ,132
+ subttl "Request Software Interrupt"
+;++
+;
+; VOID
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to issue a software interrupt to the
+; calling processor. Instead of using the hardware to do this,
+; we have observed that emulation in software is *much* faster.
+; This mostly because it takes 30 clocks or so to do a APIC access.
+; The biggest win here is in avoiding having KeRaiseIrql/KeLowerIrql
+; write to the APIC for 75% of the traffic (LOW_LEVEL to APC/DPC LEVEL).
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; equates for accessing argument
+;
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+cPublicFpo 0, 0
+
+ mov eax, 1
+ shl eax, cl ; create IRR bitmask
+
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+
+ or PCR[PcIRR], eax ; request SW interrupt
+ cmp PCR[PcHal.ProcIrql], cl ; take it now?
+ jb short @f
+
+ popfd ; restore interrupt mode
+
+ fstRET HalRequestSoftwareInterrupt ; no, just return
+;
+; Call KfLowerIrql(CurrentIrql) which handles unmasked software interrupts
+;
+@@:
+ mov cl, PCR[PcHal.ProcIrql]
+
+ popfd ; restore interrupt mode
+
+ fstCall KfLowerIrql ; (cl) = CurrentIrql
+ fstRET HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+ page ,132
+ subttl "Clear Software Interrupt"
+;++
+;
+; VOID
+; HalClearSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to clear a possible pending software interrupt.
+; Support for this function is optional, and allows the kernel to
+; reduce the number of spurious software interrupts it receives/
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalClearSoftwareInterrupt ,1
+cPublicFpo 0, 0
+
+ mov eax,1
+ shl eax, cl ; convert to mask
+
+ not eax
+ and PCR[PcIRR], eax ; clear pending irr bit
+
+ fstRET HalClearSoftwareInterrupt
+
+fstENDP HalClearSoftwareInterrupt
+
+
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+cPublicProc _HalpDispatchInterrupt ,0
+
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public HalpDispatchInterrupt2ndEntry
+HalpDispatchInterrupt2ndEntry:
+
+;
+; Save previous IRQL, set new priority level, and clear IRR bit
+;
+ push dword ptr PCR[PcHal.ProcIrql]
+ mov byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL
+ and dword ptr PCR[PcIRR], NOT (1 SHL DISPATCH_LEVEL)
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+ sti
+
+;
+; Go do Dispatch Interrupt processing
+;
+ stdCall _KiDispatchInterrupt
+
+;
+; Do interrupt exit processing
+;
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+stdENDP _HalpDispatchInterrupt
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+cPublicProc _HalpApcInterrupt ,0
+
+;
+; Create IRET frame on stack
+;
+ pop eax ; get caller PC
+ pushfd ; flags
+ push cs ; cs
+ push eax ; ip
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hapc_a, hapc_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public HalpApcInterrupt2ndEntry
+HalpApcInterrupt2ndEntry:
+
+;
+; Save previous IRQL, set new priority level, and clear IRR bit
+;
+ push dword ptr PCR[PcHal.ProcIrql]
+ mov byte ptr PCR[PcHal.ProcIrql], APC_LEVEL
+ and dword ptr PCR[PcIRR], NOT (1 SHL APC_LEVEL)
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+ sti
+
+;
+; call the APC delivery routine.
+;
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
+ jz short @f
+
+ or eax, MODE_MASK ; if v86 frame, then set user_mode
+@@:
+
+; call APC deliver routine
+; Previous mode
+; Null exception frame
+; Trap frame
+
+ stdCall _KiDeliverApc, <eax, 0, ebp>
+
+;
+; Do interrupt exit processing
+;
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+stdENDP _HalpApcInterrupt
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3swint.bak b/private/ntos/nthals/halws3/i386/w3swint.bak
new file mode 100644
index 000000000..669085cf5
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3swint.bak
@@ -0,0 +1,267 @@
+ title "Software Interrupts"
+;++
+;
+; Copyright (c) 1992 Microsoft Corporation
+; Copyright (c) 1992 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3swint.asm
+;
+; Abstract:
+;
+; This module implements the software interrupt handlers for the
+; APIC-based WinServer 3000 multiprocessor.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include i386\apic.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _KeBugCheck,1
+ EXTRNP KfLowerIrql,1,IMPORT,FASTCALL
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+
+ extrn _HalpIRQLtoTPR:byte
+ extrn _HalpLocalUnitBase:dword
+ extrn _HalpIrql2IRRMask:dword
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+
+ page ,132
+ subttl "Request Software Interrupt"
+;++
+;
+; VOID
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to issue a software interrupt to the
+; calling processor. Instead of using the hardware to do this,
+; we have observed that emulation in software is *much* faster.
+; This mostly because it takes 30 clocks or so to do a APIC access.
+; The biggest win here is in avoiding having KeRaiseIrql/KeLowerIrql
+; write to the APIC for 75% of the traffic (LOW_LEVEL to APC/DPC LEVEL).
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; equates for accessing argument
+;
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+cPublicFpo 0, 1
+
+ mov eax, 1
+ shl eax, cl ; create IRR bitmask
+ or PCR[PcIRR], eax ; request SW interrupt
+ cmp PCR[PcHal.ProcIrql], cl ; take it now?
+ jb short @f
+ fstRET HalRequestSoftwareInterrupt ; no, just return
+;
+; Call KfLowerIrql(CurrentIrql) which handles unmasked software interrupts
+;
+@@:
+ mov ecx, dword ptr PCR[PcHal.ProcIrql]
+ fstCall KfLowerIrql ; (cl) = CurrentIrql
+ fstRET HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+cPublicProc _HalpDispatchInterrupt ,0
+
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public HalpDispatchInterrupt2ndEntry
+HalpDispatchInterrupt2ndEntry:
+
+;
+; Save previous IRQL, set new priority level, and clear IRR bit
+;
+ push dword ptr PCR[PcHal.ProcIrql]
+ mov byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL
+ and dword ptr PCR[PcIRR], NOT (1 SHL DISPATCH_LEVEL)
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+ sti
+
+;
+; Go do Dispatch Interrupt processing
+;
+ stdCall _KiDispatchInterrupt
+
+;
+; Do interrupt exit processing
+;
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+stdENDP _HalpDispatchInterrupt
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+cPublicProc _HalpApcInterrupt ,0
+
+;
+; Create IRET frame on stack
+;
+ pop eax ; get caller PC
+ pushfd ; flags
+ push cs ; cs
+ push eax ; ip
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hapc_a, hapc_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public HalpApcInterrupt2ndEntry
+HalpApcInterrupt2ndEntry:
+
+;
+; Save previous IRQL, set new priority level, and clear IRR bit
+;
+ push dword ptr PCR[PcHal.ProcIrql]
+ mov byte ptr PCR[PcHal.ProcIrql], APC_LEVEL
+ and dword ptr PCR[PcIRR], NOT (1 SHL APC_LEVEL)
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+ sti
+
+;
+; call the APC delivery routine.
+;
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
+ jz short @f
+
+ or eax, MODE_MASK ; if v86 frame, then set user_mode
+@@:
+
+; call APC deliver routine
+; Previous mode
+; Null exception frame
+; Trap frame
+
+ stdCall _KiDeliverApc, <eax, 0, ebp>
+
+;
+; Do interrupt exit processing
+;
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+stdENDP _HalpApcInterrupt
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halws3/i386/w3sysbus.c b/private/ntos/nthals/halws3/i386/w3sysbus.c
new file mode 100644
index 000000000..68cd71b7d
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3sysbus.c
@@ -0,0 +1,233 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ w3sysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+extern UCHAR HalpIRQLtoTPR[];
+extern UCHAR HalpK2EISAIrq2Irql[];
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetW3EisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpTranslateSystemBusAddress)
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#pragma alloc_text(PAGE,HalpGetW3EisaInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ if (BusAddress.HighPart != 0 || *AddressSpace > 1) {
+ return (FALSE);
+ }
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+
+ return(TRUE);
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+ KIRQL lIrql;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ lIrql = (KIRQL) HalpK2EISAIrq2Irql[BusInterruptLevel];
+ SystemVector = HalpIRQLtoTPR[lIrql];
+
+ if (BusInterruptLevel > 23 ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = lIrql;
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+ return SystemVector;
+}
+
+ULONG
+HalpGetW3EisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
+ // up on IRQ 9.
+ //
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ if (BusInterruptLevel > 23) {
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
diff --git a/private/ntos/nthals/halws3/i386/w3sysint.asm b/private/ntos/nthals/halws3/i386/w3sysint.asm
new file mode 100644
index 000000000..cc2b79af9
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/w3sysint.asm
@@ -0,0 +1,613 @@
+ title "System Interrupt"
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+; Copyright (c) 1993 Sequent Computer Systems, Inc.
+;
+; Module Name:
+;
+; w3sysint.asm
+;
+; Abstract:
+;
+; This module implements the HAL routines to begin a system interrupt,
+; end a system interrupt, and enable/disable system interrupts
+; for the WinServer 3000.
+;
+; Author:
+;
+; Phil Hochstetler (phil@sequent.com) 3-30-93
+;
+; Environment:
+;
+; Kernel Mode
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\apic.inc
+include i386\w3.inc
+ .list
+
+ EXTRNP _KeBugCheck,1
+ EXTRNP _KeLowerIrql,1
+ extrn _HalpIrql2TPR:byte
+ extrn _HalpLocalUnitBase:dword
+ extrn _HalpIOunitTwoBase:dword
+ extrn _HalpIOunitBase:dword
+ extrn _HalpK2Rdir2Irq:byte
+ extrn _HalpELCRImage:word
+ extrn _HalpK2EbsIOunitRedirectionTable:dword
+ extrn _HalpBeginW3InterruptTable:dword
+ extrn _HalpK2Vector2RdirTabEntry:byte
+ extrn _HalpK2EISAIrq2Irql:byte
+ extrn _HalpK2Irql2Eisa:byte
+ extrn _HalpK2Vector2EISA:byte
+ extrn FindHigherIrqlMask:dword
+ extrn HalpDispatchInterrupt2ndEntry:NEAR
+ extrn HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpMASKED:WORD
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+_DATA ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; BOOLEAN
+; HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine handles the initial interrupt sequence for all
+; external APIC interrupts for both single processor and multiple
+; processor WinServer 3000 systems. On the WinServer 3000 we use
+; the APIC to generate all I/O interrupts and their respective
+; priorities. We do not abstract the prioritization of interrupts
+; from the hardware since the APIC accomodates all Windows NT
+; requirements for IRQLs. In addition to I/O interrupts the APIC
+; is used to generate software interrupts for APCs and DPCs.
+; The APCs and DPCs are generated by a CPU via it's
+; local APIC interrupt command register. The interrupts are sent
+; as a self directed interrupt. It is required by NT that software
+; interrupts are always handled by the CPU which issues them.
+;
+; Note: Wakeup is included also in the above fashion
+;
+; This routine does not process an 8259 generated interrupt which
+; is not tied to the APIC. This processing is done in the w3ipi.asm
+; module. A subset of IRQs 0-15 are not wired through the EBS APIC.
+; This is because the APIC on the EBS only accomodates 16 interrupts
+; We have a total of 24 on a WS3000. We chose to have all system bus
+; generated interrupts 16-23 tied to the EBS APIC. The remaining
+; 8 are divided up for EISA cards. TheHalpK2EbsIounitRedirectionTable
+; in k2space.asm describes the EISA IRQs chosen for the EBS APIC.
+;
+; Prioritization of 8259 interrupts is done by generating an APIC
+; interrupt with the appropriate APIC vector which corresponds to
+; the incoming 8259 IRQ number. Thus, 2 interrupts are always
+; generated by an 8259 interrupt. The first is the 8259 interrupt
+; and the second is the APIC interrupt.
+;
+; The APIC interrupt is then appropriately prioritized by the hardware
+; and received accordingly via this routine.
+;
+
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Valid interrupt and Irql raised appropriately.
+;
+;--
+HbsiOldIrql equ dword ptr [esp+16]
+HbsiVector equ byte ptr [esp+12]
+HbsiIrql equ byte ptr [esp+8]
+
+ align 4
+cPublicProc _HalBeginSystemInterrupt ,3
+ push ebx
+ movzx ebx, HbsiVector ; (ebx) = System Vector
+ jmp _HalpBeginW3InterruptTable[ebx*4]
+;
+; --- Process APIC external interrupt, i.e., generated via EBS I/O APIC
+; - simply raise the Irql to the interrupt level of the
+; current interrupt, EOI APIC, and return TRUE
+;
+ align 4
+ public _HalpBeginW3APICInterrupt
+
+_HalpBeginW3APICInterrupt:
+ mov edx, _HalpLocalUnitBase ; Get address of Local APIC
+ movzx eax, HbsiIrql ; Get New IRQL
+ mov cl, PCR[PcHal.ProcIrql] ; Get current irql
+ cli ; Don't trust caller..
+if DBG
+ cmp al, cl
+ ja @f ; New IRQL is > Current
+ push eax ; New IRQL
+ push ebx ; Vector
+ push ecx ; Old IRQL
+ push [edx+LU_TPR] ;
+ mov dword ptr [edx+LU_TPR], 0FFH
+ mov PCR[PcHal.ProcIrql], HIGH_LEVEL ; Set to avoid recursive error
+ stdCall _KeBugCheck, <0Bh>
+@@:
+endif
+
+;
+; --- Do to the fact that some drivers like the i8042prt driver
+; and possibly other foolhardy drivers which don't use the IRQL
+; returned by the HalGetInterrupt routine when they do an IoConnectInt
+; we have to use the IRQL passed and not use the vector to set the
+; TPR...THESE TYPE OF DRIVERS HAVE TO BE EDGE SENSITIVE DEVICES TO
+; WORK IF THEY DO THIS CRAP....We allow changes in the IRQL as long
+; as it is a higher IRQL than the one returned by the HAL
+;
+ mov PCR[PcHal.ProcIrql], al ; Set new irql
+ movzx eax, _HalpIrql2TPR[eax]
+ mov [edx+LU_TPR], eax ; Set task priority register
+ mov eax, [edx+LU_TPR] ; Read it to make sure write occurs
+ mov eax, HbsiOldIrql ; get addr to store old irql
+ mov [eax], cl ; save old irql in the return variable
+;
+; --- EOI the APIC if the interrupt is not a level sensitive EISA interrupt
+; Level sensitive interrupts are EOI'ed in EndSystemInterrupt
+;
+ xor ah, ah
+ mov al, _HalpK2Vector2EISA[ebx] ; Get EISA IRQ #
+ mov cx, _HalpELCRImage ; Get edge/level register value
+ mov bx, _HalpMASKED ; get PIC level interrupts
+ not bx
+ and cx, bx ; clear level bits from PIC
+ bt cx, ax ; test appropriate bit
+ jc short @f
+ mov [edx+LU_EOI], eax ; EOI APIC
+@@:
+ mov eax, 1 ; True interrupt
+ sti ; Let interrupts go
+ pop ebx
+
+ stdRET _HalBeginSystemInterrupt
+;
+; --- Invalid or illegal vector
+;
+ align 4
+ public _HalpBeginW3InvalidInterrupt
+_HalpBeginW3InvalidInterrupt:
+ mov eax,0 ; return False
+ pop ebx
+
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt via the EBS APIC Redirection table
+; entries or the 8259 Interrupt mask registers
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt ,2
+cPublicFpo 2, 0
+
+;
+; --- Exit if this is not the base processor
+;
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ movzx eax, byte ptr PCR[PcHal.PcrNumber]
+ cmp al, 0
+ jne HalDisableInt999 ; Exit if not base proc
+cPublicFpo 2, 1
+ pushfd
+ cli ; Disable interrupts
+
+;
+; --- Enable/Disable does not get called for the interrupt vectors
+; which are used for the 8259 generated interrupts. It only gets
+; called for the the APIC vectors which correspond to the 8259 ints...
+;
+ cmp ecx, APIC_DMA_VECTOR ; Is this for the 8259 DMA?
+ jne short HalDisableInt10 ; No - branch
+ mov ecx, 13 ; EISA DMA IRQ
+ jmp HalDisableInt60 ; Enable 8259 Int
+HalDisableInt10:
+ cmp ecx, APIC_KBD_VECTOR ; Is this the keyboard vector?
+ jne short HalDisableInt20 ; Yes - branch
+ mov ecx, 1 ; Keyboard IRQ
+ jmp HalDisableInt60 ; Enable 8259 Int
+HalDisableInt20:
+ cmp ecx, APIC_CLOCK_VECTOR ; 8259 clock?
+ jne short HalDisableInt30 ; Yes - branch
+ mov ecx, 0 ; Clock IRQ
+ jmp HalDisableInt60
+HalDisableInt30:
+ cmp ecx, APIC_RTC_VECTOR ; Real-time clock?
+ jne short HalDisableInt31 ; No -branch
+ mov ecx, 8 ; RTC IRQ
+ jmp HalDisableInt60
+HalDisableInt31:
+ cmp ecx, APIC_FLOPPY_VECTOR ; Floppy?
+ jne short HalDisableInt32 ; No -branch
+ mov ecx, 6 ; Floppy IRQ
+ jmp HalDisableInt60
+HalDisableInt32:
+ cmp ecx, APIC_IDE_VECTOR ; IDE Disk?
+ jne short HalDisableInt33 ; No -branch
+ mov ecx, 14 ; IDE Disk IRQ
+ jmp HalDisableInt60
+HalDisableInt33:
+ cmp ecx, APIC_MOUSE_VECTOR ; IRQ12 vector
+ jne short HalDisableInt34 ; No -branch
+ mov ecx, 12 ; IRQ12
+ jmp HalDisableInt60
+HalDisableInt34:
+
+;
+; --- Process other APIC vectors
+;
+ xor eax,eax
+ mov al, _HalpK2Vector2RdirTabEntry[ecx] ; Get EBS RDIR entry
+ cmp al, 0FFH ; No RDIR entry..exit
+ je HalDisableInt50 ; ..exit
+ cmp al, 0 ; Not used vector
+ je HalDisableInt50 ; ..exit
+ btr eax, 7 ; EBS I/O APIC RDIR??
+ jnc HalDisableInt35 ; Yes
+ mov edx, _HalpIOunitTwoBase ; Boot processor I/O APIC RDIR
+ jmp HalDisableInt40 ; continue
+HalDisableInt35:
+ mov edx, _HalpIOunitBase ; Address of EBS I/O APIC
+HalDisableInt40:
+;
+; No need for a lock here since only the base manipulates these registers
+;
+ mov [edx+IO_REGISTER_SELECT], eax ; Select register
+ or dword ptr [edx+IO_REGISTER_WINDOW], IOMPIC_RT_MASK ; mask it
+HalDisableInt50:
+cPublicFpo 2, 0
+ popfd
+ stdRET _HalDisableSystemInterrupt
+;
+; --- 8259 interrupt enable...
+;
+HalDisableInt60:
+;
+; --- 8259 interrupt disable...
+;
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ xor eax, eax
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+cPublicFpo 2, 0
+ popfd
+HalDisableInt999:
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+ ; Enables a system interrupt via PIC or APIC hardware masks
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt ,3
+cPublicFpo 3, 0
+;
+; --- The base processor controls enabling/disabling of all ints
+;
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ movzx eax, byte ptr PCR[PcHal.PcrNumber]
+ cmp al, 0
+ jne HalEnableInt999 ; Exit if not base proc
+cPublicFpo 3, 1
+ pushfd
+ cli
+;
+; --- Enable/Disable does not get called for the interrupt vectors
+; which are used for the 8259 generated interrupts. It only gets
+; called for the the APIC vectors which correspond to the 8259 ints...
+;
+ cmp ecx, APIC_DMA_VECTOR ; Is this for the 8259 DMA?
+ jne short HalEnableInt10 ; No - branch
+ mov ecx, 13 ; EISA DMA IRQ
+ jmp HalEnableInt60 ; Enable 8259 Int
+HalEnableInt10:
+ cmp ecx, APIC_KBD_VECTOR ; Is this the keyboard vector?
+ jne short HalEnableInt20 ; No - branch
+ mov ecx, 1 ; Keyboard IRQ
+ jmp HalEnableInt60 ; Enable 8259 Int
+HalEnableInt20:
+ cmp ecx, APIC_CLOCK_VECTOR ; 8259 clock?
+ jne short HalEnableInt30 ; No - branch
+ mov ecx, 0 ; Clock IRQ
+ jmp HalEnableInt60
+HalEnableInt30:
+ cmp ecx, APIC_RTC_VECTOR ; Real-time clock?
+ jne short HalEnableInt31 ; No -branch
+ mov ecx, 8 ; RTC IRQ
+ jmp HalEnableInt60
+HalEnableInt31:
+ cmp ecx, APIC_FLOPPY_VECTOR ; Floppy?
+ jne short HalEnableInt32 ; No -branch
+ mov ecx, 6 ; Floppy IRQ
+ jmp HalEnableInt60
+HalEnableInt32:
+ cmp ecx, APIC_IDE_VECTOR ; IDE Disk?
+ jne short HalEnableInt33 ; No -branch
+ mov ecx, 14 ; IDE Disk IRQ
+ jmp HalEnableInt60
+HalEnableInt33:
+ cmp ecx, APIC_MOUSE_VECTOR ; IRQ12 vector
+ jne short HalEnableInt34 ; No -branch
+ mov ecx, 12 ; IRQ12
+ jmp HalEnableInt60
+HalEnableInt34:
+
+
+;
+; --- Process APIC vectors
+;
+ xor eax,eax
+ mov al, _HalpK2Vector2RdirTabEntry[ecx] ; Get EBS RDIR entry
+ cmp al, 0FFH ; No RDIR entry..exit
+ je HalEnableInt50 ; ..exit
+ cmp al, 0 ; Not used vector
+ je HalEnableInt50 ; ..exit
+ btr eax, 7 ; EBS I/O APIC RDIR??
+ jnc HalEnableInt35 ; Yes
+ mov edx, _HalpIOunitTwoBase ; Boot processor I/O APIC RDIR
+ jmp HalEnableInt40 ; continue
+HalEnableInt35:
+ mov edx, _HalpIOunitBase ; Address of EBS I/O APIC
+HalEnableInt40:
+;
+; No need for a lock here since only the base manipulates these registers
+;
+ mov [edx+IO_REGISTER_SELECT], eax ; Select register
+ and dword ptr [edx+IO_REGISTER_WINDOW], NOT IOMPIC_RT_MASK ; Unmask it
+HalEnableInt50:
+cPublicFpo 3, 0
+ popfd
+ stdRET _HalEnableSystemInterrupt
+;
+; --- 8259 interrupt enable...
+;
+HalEnableInt60:
+ xor eax, eax
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Unmask the interrupt to be enabled
+;
+ btr eax, ecx
+ btr eax, 2 ; Enable cascaded IRQ2
+
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+cPublicFpo 3, 0
+ popfd
+HalEnableInt999:
+ stdRET _HalEnableSystemInterrupt
+stdENDP _HalEnableSystemInterrupt
+
+
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value just prior
+; to ending interrupt processing.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine.
+;
+; Return Value:
+;
+; None.
+;
+;--
+HeiVector equ [esp+8]
+HeiNewIrql equ [esp+4]
+
+cPublicProc _HalEndSystemInterrupt ,2
+cPublicFpo 2, 0
+
+ mov eax, HeiVector ; Get the current vector
+ mov edx, _HalpLocalUnitBase ; Local APIC address
+if DBG
+ xor ecx, ecx
+ mov cl, byte ptr HeiNewIrql
+ cmp cl, PCR[PcHal.ProcIrql]
+ jbe short @f
+ push dword ptr ecx ; new irql for debugging
+ push dword ptr PCR[PcHal.ProcIrql] ; old irql for debugging
+ mov dword ptr [edx+LU_TPR], 0FFH
+ mov PCR[PcHal.ProcIrql], HIGH_LEVEL ; Set to avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
+@@:
+endif
+;
+; EOI the APIC on level EISA interrupts
+;
+ mov al, _HalpK2Vector2EISA[eax] ; Get EISA IRQ #
+ mov cx, _HalpELCRImage ; Get edge/level register value
+ bt cx, ax ; test appropriate bit
+ jnc short NoEOI ; 1 means level interrupt
+
+ ;
+ ; Level interrupt so we need to determine if the source
+ ; is the PIC or APIC. If the PIC, then we need to unmask the
+ ; source, if the APIC, then we need to do an EOI to the APIC.
+ ;
+
+ mov cx, _HalpMASKED ; get PIC level ints
+ bt cx, ax ; test appropriate bit
+ jnc short @f ; CF=1 means PIC level int
+
+lock btr _HalpMASKED, ax ; atomic clear of bit
+
+ mov cx, ax
+ mov ax, 1
+ shl ax, cl
+ or al, ah
+ not al
+ mov cl, al
+
+ in al, PIC2_PORT1 ; unmask bit in PIC
+ and al, cl
+ out PIC2_PORT1, al
+
+ jmp short NoEOI
+@@:
+ mov [edx+LU_EOI], eax ; EOI APIC
+NoEOI:
+ xor eax, eax
+ mov al, byte ptr HeiNewIrql
+
+;
+; Write new lower priority level into the APIC Task Priority Register
+;
+ pushfd
+ cli
+ mov PCR[PcHal.ProcIrql], al ; set new IRQL
+ mov al, _HalpIrql2TPR[eax] ; get new TPR
+ mov [edx+LU_TPR], eax ; write new TPR
+ mov eax, [edx+LU_TPR] ; Flush CPU write buffer
+ popfd
+
+ mov al, byte ptr HeiNewIrql ; get current irql
+ cmp al, DISPATCH_LEVEL ; SW ints possible?
+ jb short @f
+ stdRET _HalEndSystemInterrupt
+
+;
+; Check for any pending software interrupts
+;
+@@:
+ mov edx, PCR[PcIRR] ; get current IRR
+ and edx, FindHigherIrqlMask[eax*4]
+ jnz short @f
+ stdRET _HalEndSystemInterrupt
+
+;
+; Software interrupt(s) pending, figure out which one(s) and take it
+;
+@@:
+ cli
+ test dword ptr PCR[PcIRR], (1 SHL DISPATCH_LEVEL)
+ jz short @f
+ add esp, 12
+ jmp HalpDispatchInterrupt2ndEntry
+@@:
+ cmp al, APC_LEVEL
+ jae short @f
+ test dword ptr PCR[PcIRR], (1 SHL APC_LEVEL)
+ jz short @f
+ add esp, 12
+ jmp HalpApcInterrupt2ndEntry
+@@:
+ sti
+ stdRET _HalEndSystemInterrupt
+
+stdENDP _HalEndSystemInterrupt
+
+_TEXT ENDS
+
+ END
diff --git a/private/ntos/nthals/halws3/i386/xxbiosa.asm b/private/ntos/nthals/halws3/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halws3/i386/xxbiosc.c b/private/ntos/nthals/halws3/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halws3/i386/xxdisp.c b/private/ntos/nthals/halws3/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halws3/i386/xxioacc.asm b/private/ntos/nthals/halws3/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halws3/i386/xxkdsup.c b/private/ntos/nthals/halws3/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halws3/i386/xxmemory.c b/private/ntos/nthals/halws3/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halws3/i386/xxstubs.c b/private/ntos/nthals/halws3/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halws3/i386/xxtime.c b/private/ntos/nthals/halws3/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halws3/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halws3/makefile b/private/ntos/nthals/halws3/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halws3/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halws3/makefile.inc b/private/ntos/nthals/halws3/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halws3/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halws3/sources b/private/ntos/nthals/halws3/sources
new file mode 100644
index 000000000..b6ee284db
--- /dev/null
+++ b/private/ntos/nthals/halws3/sources
@@ -0,0 +1,98 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halws3
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixdat.c \
+ i386\ixidle.asm \
+ i386\ixbusdat.c \
+ i386\ixisabus.c \
+ i386\ixinfo.c \
+ i386\w3sysbus.c \
+ i386\w3clock.asm \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\w3ipi.asm \
+ i386\w3irql.asm \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\w3nmi.c \
+ i386\ixphwsup.c \
+ i386\w3profil.asm \
+ i386\w3sproc.c \
+ i386\ixreboot.c \
+ i386\w3stall.asm \
+ i386\w3swint.asm \
+ i386\w3sysint.asm \
+ i386\ixthunk.asm \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\w3hal.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c \
+ i386\w3sproca.asm \
+ i386\w3spin.asm \
+ i386\w3space.asm
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halws3.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halwyse7/drivesup.c b/private/ntos/nthals/halwyse7/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halwyse7/hal.rc b/private/ntos/nthals/halwyse7/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halwyse7/hal.src b/private/ntos/nthals/halwyse7/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halwyse7/i386/halnls.h b/private/ntos/nthals/halwyse7/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/halnls.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halnls.h"
diff --git a/private/ntos/nthals/halwyse7/i386/halp.h b/private/ntos/nthals/halwyse7/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/halp.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\halp.h"
diff --git a/private/ntos/nthals/halwyse7/i386/ix8259.inc b/private/ntos/nthals/halwyse7/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ix8259.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ix8259.inc
diff --git a/private/ntos/nthals/halwyse7/i386/ixbeep.asm b/private/ntos/nthals/halwyse7/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixbeep.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixbeep.asm
diff --git a/private/ntos/nthals/halwyse7/i386/ixbusdat.c b/private/ntos/nthals/halwyse7/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixbusdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixbusdat.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixcmos.asm b/private/ntos/nthals/halwyse7/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixcmos.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.asm
diff --git a/private/ntos/nthals/halwyse7/i386/ixcmos.inc b/private/ntos/nthals/halwyse7/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixcmos.inc
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixcmos.inc
diff --git a/private/ntos/nthals/halwyse7/i386/ixdat.c b/private/ntos/nthals/halwyse7/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixdat.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixdat.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixenvirv.c b/private/ntos/nthals/halwyse7/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixenvirv.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixenvirv.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixfirm.c b/private/ntos/nthals/halwyse7/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixfirm.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixfirm.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixhwsup.c b/private/ntos/nthals/halwyse7/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixhwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixhwsup.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixidle.asm b/private/ntos/nthals/halwyse7/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixidle.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixidle.asm
diff --git a/private/ntos/nthals/halwyse7/i386/ixinfo.c b/private/ntos/nthals/halwyse7/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixinfo.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixinfo.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixisa.h b/private/ntos/nthals/halwyse7/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixisa.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisa.h"
diff --git a/private/ntos/nthals/halwyse7/i386/ixisabus.c b/private/ntos/nthals/halwyse7/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixisabus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisabus.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixisasup.c b/private/ntos/nthals/halwyse7/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixisasup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixisasup.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixkdcom.c b/private/ntos/nthals/halwyse7/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixkdcom.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixkdcom.h b/private/ntos/nthals/halwyse7/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixkdcom.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixkdcom.h"
diff --git a/private/ntos/nthals/halwyse7/i386/ixphwsup.c b/private/ntos/nthals/halwyse7/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixphwsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixphwsup.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixreboot.c b/private/ntos/nthals/halwyse7/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixreboot.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixreboot.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixthunk.c b/private/ntos/nthals/halwyse7/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixthunk.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixthunk.c"
diff --git a/private/ntos/nthals/halwyse7/i386/ixusage.c b/private/ntos/nthals/halwyse7/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/ixusage.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixusage.c"
diff --git a/private/ntos/nthals/halwyse7/i386/wy7000mp.inc b/private/ntos/nthals/halwyse7/i386/wy7000mp.inc
new file mode 100644
index 000000000..34222ea50
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wy7000mp.inc
@@ -0,0 +1,368 @@
+;++
+; Copyright (c) 1992, 1993 Wyse Technology
+;
+; Module Name:
+;
+; wy7000mp.inc
+;
+; Abstract:
+;
+; Wyse 7000i MP include file
+;
+; Author:
+; John Nels Fuller (o-johnf) 3-Apr-1992
+;--
+
+;*****************************
+; Wyse 7000i MP defines
+;
+WyModel740 Equ 00170335Fh ;EISA id for model 740 system board
+WyModel760 Equ 00178335Fh ;EISA id for model 760 system board
+WyModel780 Equ 00978335Fh ;EISA id for model 780 system board
+; ;(model hasn't been named, but
+; ; 780 is as good as anything)
+
+WyUPcpu Equ 00171335Fh ;EISA id for UP-cpu (can only be
+ ; read through EISA_ReadId)
+WyMPcpu Equ 00179335Fh ;EISA id for MP-cpu (can only be
+ ; read through EISA_ReadId)
+WyIDmask Equ 00FFFFFFFh ;mask out rev/speed for cpu id
+
+WyShadowArea Equ 0000F0000h ;physical address of BIOS RAM shadow
+WyShadowLength Equ 000010000h ;length of BIOS RAM shadow (64Kb)
+
+WarmResetVector Equ 000000467h ;address of low mem reset variable
+
+EISA_Functions Equ 00000F859h ;offset into BIOS of EISA Int 15h
+EISA_ReadId Equ 00000D884h ;function to read EISA slot ID
+MPFW_FuncTable Equ 0FFFE0100h ;physical address of F/W function table
+ fnICU_Sync_Mstr Equ 25h ;function number of F/W routine to
+ ; cause specified cpu's to sync and
+ ; report back (used to verify that
+ ; installed cpu's are running)
+ fnICU_Send_Mstr Equ 23h ;function number of F/W routine to
+ ; send command/data packtets to other
+ ; cpu's (cpu's must be running in
+ ; F/W or Diag as at boot time).
+ fnOS_Diag_Mon Equ 0Dh ;function number of O/S transfer
+ ; to Diagnostic monitor
+ fnOS_Panic Equ 0Ch ;function number of O/S transfer
+ ; to Diagnostic monitor for NMI/crash
+ ; panic
+
+; These four reigisters access the bus control unit chip (BCU) for the
+; Wyse Wyde Bus(tm) (WWB), CpuIntCmd and CpuPriortyLevel are read only
+; except for the local cpu (i.e. My+CpuIntCmt and My+CpuPriortyLevel).
+
+CpuPtrReg Equ 0800h ;cpu pointer register (add WWB slot*16)
+CpuDataReg Equ 0804h ;cpu data register (add WWB slot*16)
+CpuIntCmd Equ 0802h ;cpu interrupt cmd reg (add WWB slot*16)
+CpuPriortyLevel Equ 0806h ;cpu int priority level (add WWB slot*16)
+
+; These two registers access the cache control unit chip (CCU)
+; (80486 mp-cpu's only)
+
+CpuCCUptr Equ 0C00h ;CCU pointer register (add WWB slot*16)
+CpuCCUdata Equ 0C02h ;CCU data register (add WWB slot*16)
+
+; These three registers access the three Wyde Bus Interface chips (WBI)
+; (80486 mp-cpu's only)
+
+CpuWBIlow Equ 0C04h ;low WBI register (add WWB slot*16)
+CpuWBIhigh Equ 0C06h ;high WBI register (add WWB slot*16)
+CpuWBIaddr Equ 0C08h ;addr WBI register (add WWB slot*16)
+
+; These two registers access the WWB Data Controller chip (WDC)
+; (Pentium cpu's only) (DON'T add WWB slot*16 to these addresses)
+
+MyCpuWDCptr Equ 0CF0h ;WDC pointer register
+MyCpuWDCdata Equ 0CF2h ;WDC data register
+
+; These two registers access the WWB Data Path chip (WDP)
+; (Pentium cpu's only) (DON'T add WWB slot*16 to these addresses)
+
+MyCpuWDPlow Equ 0CF4h ;low WDP register
+MyCpuWDPhigh Equ 0CF6h ;high WDP register
+
+; Each cpu has a 16450 uart connected to the diagnostic serial port
+; on the back of the machine, only one cpu's 16450 is enabled (normally
+; processor 0) so the WWB slot for that cpu must be used for other
+; cpu's to access it. However, not all variations of cpu boards
+; support access to this uart from another cpu.
+
+CpuDiagUart Equ 0808h ;16450 base address (add WWB slot*16)
+
+; Use these fixed WWB slots numbers for modifing above i/o addresses
+
+My Equ 00F0h ;WWB slot number specifies local cpu
+Sys Equ 0000h ;WWB slot number for system board
+ ; use for 760/780 system board only
+ ; and only for BCU/ICU registers
+;
+; The following registers are accessed by writing the register number
+; to CpuPtrReg and then reading or writing the 16-bit data at CpuDataReg
+; each 16-bit access to CpuDataReg toggles bit 1 of CpuPtrReg so, for
+; example to access both ICU_IMR0 and ICU_IMR1 write ICU_IMR0 to
+; CpuPtrReg and do two 16-bit i/o's to CpuDataReg to access first the
+; low word and then the high word of the mask register.
+;
+ICU_SYS_CPU Equ 00h ;system cpu config register
+ICU_CPU_MASTER Equ 04h ;system cpu master register
+ICU_CPU_SYNC Equ 08h ;cpu synchronization register
+BCU_STAT0 Equ 0Ch ;BCU status register 0
+ PERR_LOW Equ 02h ;parity error, low 32-bits of data bus
+ PERR_HIGH Equ 04h ;parity error, high 32-bits of data bus
+ PERR_ADDR Equ 08h ;parity error, address bus
+ PERR_CCU Equ 10h ;cache control unit error
+ PERR_TAG Equ 20h ;snoop tag parity error
+ NOT_FAIL Equ 80h ;when zero red LED on CPU is on
+CPU_STAT Equ 10h ;CPU status register
+BCU_ID Equ 14h ;Slot identification (bits 0-3)
+ WWB_ID_MASK Equ 0Fh ;these bits are WWB slot number
+BCU_GPR Equ 18h ;General purpose register
+BCU_BCTLR Equ 1Ch ;BCU control register
+ A20M_WWB Equ 01h ;when set gate A20 comes from 8042
+ A20M_CPU Equ 02h ;when set forces A20 to be masked
+ SLOW_ENB Equ 04h ;when set allows CPUSlowDown from
+ ; EISA chipset to drive CPU Hold
+ ; (for 8Mhz emulation)
+ SNP_ENB Equ 08h ;when set the cache snoops bus cycles
+ BCU_FWT Equ 10h ;when set two extra clocks are inserted
+ ; in cache line operations
+BCU_ERRCTLR Equ 20h ;BCU error control register
+ ERR_MODE Equ 03h ;error mode field mask
+ ERR_MODE0 Equ 00h ;report no errors
+ ERR_MODE1 Equ 01h ;Local CPU gets NMI (only local CPU
+ ; can see this)
+ ERR_MODE2 Equ 02h ;report to WWB NMI line (all CPU's
+ ; may see this)
+ ERR_MODE3 Equ 03h ;report on WWB PCHK line (all CPU's
+ ; and ISP may see this, ISP may assert
+ ; WWB NMI in response)
+ NMI_ENB Equ 04h ;enable NMI's to CPU
+ WWB_NMI Equ 08h ;enable WWB NMI to cause NMI this CPU
+ WWB_PCHK Equ 10h ;enable WWB PCHK to cause NMI this CPU
+BCU_STAT1 Equ 24h ;BCU status register 1
+ NMISRC_WWB Equ 01h ;NMI source is WWB NMI
+ NMISRC_PCHK Equ 02h ;NMI source is WWB PCHK
+ NMISRC_BTO Equ 04h ;NMI source is WWB bus timeout
+ NMISRC_EXT Equ 08h ;NMI source is NMI button on CPU
+ NMISRC_ICU Equ 10h ;NMI source is ICU (send NMI to Slot)
+ICU_DATA Equ 40h ;ICU data register
+ICU_ICTLR Equ 44h ;ICU control register
+ WWB_INT Equ 01h ;specifies this ICU to be master
+ IACK_MODE Equ 02h ;set for MP interrupt mode
+ ICU_AEOI Equ 04h ;automatic EOI for ICU interrupts
+ INT_ENB Equ 08h ;enable interrupts from ICU
+ TMR_TEST Equ 10h ;select timer test mode
+ IVP_TEST Equ 40h ;select Int Vector Processor test mode
+ MSK_CPURST Equ 80h ;set to prevent 8042 from reseting cpu
+ICU_IMR0 Equ 48h ;ICU int mask register (low 16 bits)
+ICU_IMR1 Equ 4Ah ;ICU int mask register (high 16 bits)
+ IMR_MASK Equ 007FFFFFh ;only bits 0-22 are valid
+ICU_MSKPND0 Equ 4Ch ;ICU masked pending register (low)
+ICU_MSKPND1 Equ 4Eh ;ICU masked pending register (high)
+ICU_VB0 Equ 50h ;vector base register 0
+ICU_VB1 Equ 54h ;vector base register 1
+ICU_VB2 Equ 58h ;vector base register 2
+ICU_STAT Equ 5Ch ;ICU status register
+ INSERV0 Equ 01h ;int in service bit 0
+ INSERV1 Equ 02h ;int in service bit 1
+ICU_PSR0 Equ 60h ;pending status register (low)
+ICU_PSR1 Equ 62h ;pending status register (high)
+ICU_CNT_VAL Equ 64h ;timer count current value
+ICU_CNT_REG Equ 68h ;timer count register
+ICU_LIPTR Equ 6Ch ;local interrupt ptr register
+ ;each field specifies the Local/IPI
+ ;interrupt level of a local bus intr.
+ ;with 0 meaning the intr. is disabled
+ ;Each Local/IPI int level maps to a
+ ;specific CpuPriorityLevel (CPL)--see
+ ;chart in WYIRQL.ASM. CPL is also the
+ ;bit # in ICU_IMR to mask the level.
+ lipSlot Equ 7000h ;mask for slot IPI interrupt
+ lipSlotShl Equ 12 ;shift for slot IPI interrupt field
+ lipSlotVal Equ 1 Shl lipSlotShl ;IPI level used by this Hal
+ lipSlotCPL Equ 1 ;CPL / IMR bit number
+ lipGlobal Equ 0700h ;mask for global IPI interrupt
+ lipGlobalShl Equ 8 ;shift for global IPI interrupt field
+ lipGlobalVal Equ 3 Shl lipGlobalShl ;IPI level used by this Hal
+ lipGlobalCPL Equ 3 ;CPL / IMR bit number
+ lipSerial Equ 0070h ;mask for diagnostic uart interrupt
+ lipSerialShl Equ 4 ;shift for uart interrupt field
+ lipSerialVal Equ (lipGlobalVal Shr lipGlobalShl) Shl lipSerialShl
+ ;use same as Global
+ lipSerialCPL Equ lipGlobalCPL ;CPL / IMR bit number
+ lipTimer Equ 0007h ;mask for local timer interrupt
+ lipTimerShl Equ 0 ;shift for timer interrupt field
+ lipTimerVal Equ 2 Shl lipTimerShl ;IPI level used by this Hal
+ lipTimerCPL Equ 2 ;CPL / IMR bit number
+ lipDefault Equ lipSlotVal+lipTimerVal+lipSerialVal+0 ;Global off
+ICU_CNTREC Equ 70h ;recovery count register
+ICU_VIN Equ 74h ;vector in register
+ICU_VOUT Equ 78h ;vector out register
+SYS_WBI_LOW Equ 0F0h ;low WBI register (system board only)
+SYS_WBI_HIGH Equ 0F4h ;high WBI register (system board only)
+SYS_WBI_ADDR Equ 0F8h ;addr WBI register (system board only)
+
+;
+; The following describes the CpuIntCmd register
+;
+ICU_CMD_BUSY Equ 0100h ;do not issue command while set
+ICU_IPI_SLOT Equ 0060h ;IPI cpu in slot (add WWB slot number)
+ICU_CLR_INSERV0 Equ 00E8h ;clear interrupt in service bit 0
+ICU_CLR_INSERV1 Equ 00E9h ;clear interrupt in service bit 1
+ICU_XMT_INT_SND Equ 0020h ;rebroadcast int (add CPL of int)
+ ;(cannot be used for CLOCK2/IPI)
+ICU_XMT_GLB_INT Equ 00E0h ;Send global interrupt
+
+;
+; The following describes each WBI register
+;
+WBI_SLT_MSK Equ 000Fh ;WWB slot number
+WBI_FPAR_ERR Equ 0010h ;force parity error for diagnostics
+WBI_IACK_MODE Equ 0020h ;set for MP interrupt acknowlege mode
+WBI_FWT Equ 0040h ;force 2 clock cycles on Cpu bus
+; Equ 0080h ;reserved
+WBI_PE_IN_0 Equ 0100h ;for data WBI's:
+ ; parity err in 1st inbound data phase
+ ;for addr WBI:
+ ; parity err in inbound address
+WBI_PE_IN_1 Equ 0200h ;for data WBI's:
+ ; parity err in 2nd inboud data phase
+ ;for addr WBI:
+ ; parity err in inbound address
+WBI_PE_OUT_CPU Equ 0400h ;data parity err outbound data from cpu
+WBI_PE_OUT_CSH Equ 0800h ;data perr outbound data from cache
+WBI_PE_BYTE0 Equ 1000h ;parity error in byte lane 0
+WBI_PE_BYTE1 Equ 2000h ;parity error in byte lane 1
+WBI_PE_BYTE2 Equ 4000h ;parity error in byte lane 2
+WBI_PE_BYTE3 Equ 8000h ;parity error in byte lane 3
+
+; The following describes the bits in the WDP register that concern HAL
+;
+WDP_IACK_MODE Equ 0020h ;set for MP interrupt acknowlege mode
+WDP_FPE_EN Equ 0040h ;enable CPU FERR onto WWB (to IRQ13)
+
+;
+; The following registers are accessed by writing the register number
+; to CpuCCUptr and then reading or writing the 16-bit data at CpuCCUdata.
+;
+CCU_CR Equ 00h ;CCU control register
+ CACHE_EN Equ 0001h ;enable secondary cache
+ BURST_EN Equ 0002h ;enable CPU burst cycles
+ WWB_FPE_EN Equ 0004h ;enable CPU FERR onto WWB (to IRQ13)
+ ;(reset to use int 10h trap for
+ ; floating point errors, thus
+ ; preventing IRQ13's for FP err)
+ TPEN Equ 0008h ;cache tag parity enable
+ SHADOW_ROM_EN Equ 0010h ;enable BIOS ROM shadow in 1st Mb
+ AMOD Equ 0020h ;enable local memory mapped I/O to
+ ; cache data/tags for diagnostics,
+ ; flash rom write area, diagnostic
+ ; ROM area.
+ SRAM_MODE Equ 0040h ;specifies type of SRAM used for
+ ; cache, standard/~synchronous
+ SYSCONFIG Equ 0080h ;allows configuration cycles to be
+ ; run on WWB
+ PCD_EN Equ 0100h ;enables use of cpu PCD output
+ RDWT Equ 0200h ;adds one wait cycle to reads
+ WRWT_MSK Equ 0C00h ;mask for write wait cycle count field
+ BRWT Equ 1000h ;adds one wiat state on cpu burst reads
+ FST_ODD Equ 2000h ;force odd parity on cache state bits
+ ; for diagnostics
+ FTAG_ODD Equ 4000h ;force odd parity on cache tag bits
+ ; for diagnostics
+ CCU_FWT Equ 8000h ;force two clocks for cache-WBI data
+ ; transfers (cache fill, copy back,
+ ; intervention, & snoop update)
+CCU_ERR0 Equ 18h ;CCU latched error status register 0
+ TPAR Equ 0001h ;tag parity bit
+ SNP_ERR Equ 0002h ;snoop error
+ TAG_DATA Equ 1FFCh ;tag data bits
+ CCU_STATE Equ 6000h ;cache line state bits:
+ ; 0=default, 1=exclusive, 2=shared
+ ; 3=modified
+ SPAR Equ 8000h ;state parity bit
+CCU_ERR1 Equ 1Ah ;CCU latched error status register 1
+ TAGINDEX Equ 3FFFh ;tag index address
+ CPU_DPE Equ 4000h ;cpu data parity error
+ VALID_ERROR Equ 8000h ;set when CCU_ERR0,1 have valid info
+CCU_ID Equ 1Ch ;CCU has WWB slot number
+;*****************************
+; end of list
+
+
+;
+; The kernel leaves some space (64 byte) of the PCR for the HAL to use
+; as it needs. Currently this space is used for some efficiency in
+; some of the MP specific code and is highly implementation
+; dependant.
+;
+
+
+PcHalData struc
+; pchStallCnt dd ? ;per processor stall count
+ pchCurLiptr dd ? ;per processor current ICU_LIPTR
+ pchPrNum db ? ;NT's processor number
+ pchPrSlot db ? ;WWB processor slot
+ pchPentiumFlag db ? ;non-zero if current cpu is a Pentium
+ pchHwIrql db ? ;Irql to which CpuPriorityLevel is
+ ;programmed. Due to lazy Irql's this
+ ;may be different than PcIrql
+PcHalData ends
+
+
+cr equ 0ah
+lf equ 0dh
+
+PIC1_BASE equ PRIMARY_VECTOR_BASE
+PIC2_BASE equ PRIMARY_VECTOR_BASE + 8
+IPIv_BASE equ PRIMARY_VECTOR_BASE + 16
+
+PIC_SLAVE_IRQ equ 2
+
+IFDEF STD_CALL
+
+enproc macro pn
+ if DBG
+ %out enproc pn
+ ifndef _ProcSub@4
+ extrn _ProcSub@4:NEAR
+ endif ;_ProcSub
+ push pn ;save routine number
+ call _ProcSub@4 ;write to BCU_GPR
+ endif ;DBG
+ endm
+
+exproc macro pn
+ if DBG
+ %out exproc pn
+ push (pn) or 80h ;save routine number and exit flag
+ call _ProcSub@4 ;write to BCU_GPR
+ endif ;DBG
+ endm
+
+ELSE
+
+enproc macro pn
+ if DBG
+ %out enproc pn
+ ifndef _ProcSub
+ extrn _ProcSub:NEAR
+ endif ;_ProcSub
+ push pn ;save routine number
+ call _ProcSub ;write to BCU_GPR
+ lea esp, [esp][4] ;remove parameter w/o altering flags
+ endif ;DBG
+ endm
+
+exproc macro pn
+ if DBG
+ %out exproc pn
+ push (pn) or 80h ;save routine number and exit flag
+ call _ProcSub ;write to BCU_GPR
+ lea esp, [esp][4] ;remove parameter w/o altering flags
+ endif ;DBG
+ endm
+ENDIF
diff --git a/private/ntos/nthals/halwyse7/i386/wyclock.asm b/private/ntos/nthals/halwyse7/i386/wyclock.asm
new file mode 100644
index 000000000..c2335419b
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wyclock.asm
@@ -0,0 +1,1292 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989-1993 Microsoft Corporation
+; Copyright (c) 1992, 1993 Wyse Technology
+;
+; Module Name:
+;
+; wyclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT. It works on UP and SystemPro.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; John Fuller (o-johnf) 1-Apr-92
+; convert to Wyse 7000i MP system, clock goes to cpu's local timer,
+; profile interrupt and performance counter use 8254 timer1 counter 0,
+; use cpu's local timer to initialize stall execution.
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\wy7000mp.inc
+ .list
+
+ extrn ReadMyCpuReg:NEAR
+ extrn WriteMyCpuReg:NEAR
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ extrn _HalpIRQLtoCPL:BYTE
+ extrn _HalpIRQLtoVector:BYTE
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER2_DATA_PORT0 EQU 48H ; Timer1, channel 0 data port
+TIMER2_CONTROL_PORT0 EQU 4BH ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193000
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+
+RTC_OFFSET_SECOND EQU 0 ; second field of RTC memory
+RTC_OFFSET_MINUTE EQU 2 ; minute field of RTC memory
+RTC_OFFSET_HOUR EQU 4 ; hour field of RTC memory
+RTC_OFFSET_DAY_OF_WEEK EQU 6 ; day-of-week field of RTC memory
+RTC_OFFSET_DATE_OF_MONTH EQU 7 ; date-of-month field of RTC memory
+RTC_OFFSET_MONTH EQU 8 ; month field of RTC memory
+RTC_OFFSET_YEAR EQU 9 ; year field of RTC memory
+RTC_OFFSET_CENTURY EQU 32h ; Century field of RTC memory
+
+;
+; ==== Values used for System Clock ====
+;
+
+; Convert the interval to rollover count for ICU local timer (ltimer) device.
+; Since ltimer counts down a 16 bit value at a one count every 240ns and the
+; interval is in units of 100ns, the computation is:
+; RolloverCount = (Interval*10)/24 = (Interval*5)/12
+; Therefore, for an integral RolloverCount, Interval must be a multiple of
+; 1.2us. Since RolloverCount is a 16-bit count the maximum Interval is
+; (65535*12)/5 or 15.7284ms.
+;
+; For the convience of HalpInitializeStallExecution the TIME_INCREMENT
+; should be chosen to be an integral number of microseconds. Hence
+; TIME_INCREMENT should be a multiple of 60 (6us).
+;
+; The default Interrupt interval is 10.002ms (8335 * 1.2us)
+;
+
+TIME_INCREMENT EQU 100020 ; 10.002ms
+ROLLOVER_COUNT EQU (TIME_INCREMENT*5)/12
+
+;
+; ==== Values used for performance counter
+;
+; Maximum counter value for timer1 (8254) and its corresponding interrupt
+; interval. These values are for profiling and performance counter support.
+;
+; This value is equivalent to a value of zero (counter is 16-bit).
+; So, the rollover rate is approximately 18.2 Hz.
+; Note this value will be used if no profiling support.
+;
+MAXIMUM_ROLLOVER_COUNT Equ 0FFFFh
+MAXIMUM_ROLLOVER_INTERVAL Equ 861D2h ; in 100ns units
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+
+_Halp8254Lock dd 0
+
+;
+; Init Stall count must have a spin lock. This lock is held a long time
+; but only processors tring to initialize the stall count will wait.
+;
+iscSpinLock dd 0
+
+HalpProfileRolloverCnt dd MAXIMUM_ROLLOVER_COUNT
+ public HalpPerfCounterLow
+ public HalpPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpRollOverCount dd 0
+HalpNextRolloverCount dd MAXIMUM_ROLLOVER_COUNT
+HalpProfilingStopped dd -1 ;stopped when this is negative
+HalpPerfCounterInit dd 0
+ public HalpHackEsp
+HalpHackEsp dd 0
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using the local timer
+; to generate an interrupt at every 15ms interval
+;
+; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock ,0
+ enproc 4
+
+;
+; Fill in PCR value with TIME_INCREMENT
+;
+
+ mov eax, TIME_INCREMENT
+ stdCall _KeSetTimeIncrement, <eax, eax>
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate for Wyse local timer
+;
+ mov al, ICU_CNT_REG
+ mov dx, My+CpuPtrReg
+ out dx, al
+ mov dx, My+CpuDataReg
+ mov ax, ROLLOVER_COUNT
+ out dx, ax
+
+;
+; Initialize rollover count for performance counter and profiling
+;
+ cmp fs:PcHal.pchPrNum, 0 ;master cpu?
+ jne short HICexit ;jump if not
+
+;
+; Since this happens only on master cpu before other cpu's are started
+; we do not need to aquire Halp8254Lock.
+;
+ stdCall _HalpSetRolloverCount, <MAXIMUM_ROLLOVER_COUNT>
+
+HICexit:
+
+ exproc 4
+ popfd ; restore caller's eflag
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; HalpInitializeStallExecution (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+; Note:
+;
+; Current implementation assumes that all the processors share
+; the same Real Time Clock. So, the dispatcher database lock is
+; acquired before entering this routine to guarantee only one
+; processor can access the routine.
+;
+;--
+isc00: sti
+ SPIN_ON_SPINLOCK eax, <isc01>
+
+KiseInterruptCount equ [ebp-12] ; local variable
+
+cPublicProc _HalpInitializeStallExecution ,1
+ enproc 7
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 12 bytes for local use
+ sub esp, 12
+
+ pushfd ; save caller's eflag
+
+;
+; Initialize Cpu Local Timer to interrupt us for every 15ms at
+; PROFILE_LEVEL-19
+;
+;
+; acquire spin lock to prevent two processors from doing this routine at
+; the same time
+;
+isc01: cli
+ lea eax, iscSpinLock
+ ACQUIRE_SPINLOCK eax, isc00
+;
+; Get and save current local interrupt pointer register
+;
+
+ push ICU_LIPTR
+ call ReadMyCpuReg
+ push eax ; save for later
+ push lipTimer ; set to only timer at PROFILE_LEVEL-19
+ ;(must use an otherwise unused level
+ ; or at least one that won't generate
+ ; an interrupt until all processors
+ ; have been started)
+ push ICU_LIPTR
+ call WriteMyCpuReg
+
+;
+; Get and save current ICU interrupt masks
+;
+ push ICU_IMR0
+ call ReadMyCpuReg ; get local interrupt masks (low)
+ shl eax, 16
+ in ax, dx ; get local interrupt masks (high)
+ push eax ; save the masks
+
+ movzx ecx, _HalpIRQLtoCPL[PROFILE_LEVEL-19]
+ mov eax, IMR_MASK ; all ints masked out
+ btr eax, ecx ; clear bit for local timer
+ out dx, ax ; set new mask (low)
+ rol eax, 16
+ out dx, ax ; set new mask (high)
+
+;
+; Since RTC interrupt will come from PROFILE_LEVEL-19, we need to
+; Save original IDT descriptor and set the descriptor to point to
+; our own handler.
+;
+ movzx ecx, _HalpIRQLtoVector[PROFILE_LEVEL-19]
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov edx, [ebp-6] ; (edx)->IDT
+
+ push dword ptr [edx+8*ecx]
+ ; (TOS) = original desc of IRQ 8
+ push dword ptr [edx+8*ecx + 4]
+ ; each descriptor has 8 bytes
+ push edx ; (TOS) -> IDT
+ mov eax, offset FLAT:RealTimeClockHandler
+ mov word ptr [edx+8*ecx], ax
+ ; Lower half of handler addr
+ mov word ptr [edx+8*ecx+2], KGDT_R0_CODE
+ ; set up selector
+ mov word ptr [edx+8*ecx+4], D_INT032
+ ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*ecx+6], ax
+ mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet
+
+ mov dx, My+CpuPriortyLevel
+ in ax, dx ;get old CPL
+ shl eax, 16
+ push ICU_CNT_REG
+ call ReadMyCpuReg ;read old tick count
+ push eax ;save for later
+ push ROLLOVER_COUNT
+ push ICU_CNT_REG
+ call WriteMyCpuReg
+ movzx eax, _HalpIRQLtoCPL[PROFILE_LEVEL-19]
+ inc eax ;allow this level interrupt
+ mov dx, My+CpuPriortyLevel
+ out dx, ax
+
+;
+; Now enable the interrupt and start the counter
+; (As a matter of fact, only local timer can come through.)
+;
+
+ xor eax, eax ; (eax) = 0, initialize loopcount
+ sti
+kise10:
+ add eax, 1 ; increment the loopcount
+ jnz short kise10
+;
+; Counter overflowed
+;
+
+ stdCall _DbgBreakPoint
+
+;
+; Our RealTimeClock interrupt handler. The control comes here through
+; irq 8.
+; Note: we discard first two real time clock interrupts and compute the
+; permicrosecond loopcount on receiving of the third real time
+; interrupt. This is because the first interrupt may be already
+; pending in which case the second is generated based on the previous
+; real time tick interval.
+;
+
+RealTimeClockHandler:
+
+ inc dword ptr KiseInterruptCount ; increment interrupt count
+ cmp dword ptr KiseInterruptCount, 2 ; Is this 1st or 2nd interrupt?
+ ja short kise25 ; no, its the third go process it
+ pop eax ; get rid of original ret addr
+ push offset FLAT:kise10 ; set new return addr
+
+;
+; dismiss interrupt at ICU
+;
+ mov dx, My+CpuIntCmd
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz @B
+ mov al, ICU_CLR_INSERV1 ; clear interrupt in service bit
+ out dx, ax
+
+ xor eax, eax ; reset loop counter
+
+cPublicProc _HalpICUSpurious ,0
+ iretd
+stdENDP _HalpICUSpurious
+
+kise25:
+
+;
+; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount
+;
+
+if DBG
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint
+
+endif
+ ; never return
+;
+; ** End temporay code
+;
+
+kise30:
+ xor edx, edx ; (edx:eax) = divident
+ mov ecx, TIME_INCREMENT / 10; (ecx) = time spent in the loop
+ div ecx ; (eax) = loop count per microsecond
+ cmp edx, 0 ; Is remainder =0?
+ jz short kise40 ; yes, go kise40
+ inc eax ; increment loopcount by 1
+kise40:
+ movzx ecx, byte ptr [ebp+8] ; Current processor number
+ mov fs:PcStallScaleFactor, eax ; save in per processor data
+
+;
+; Reset return address to kexit
+;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+ iretd
+
+kexit: ; Interrupts are disabled
+; push original tick count (already on stack)
+ push ICU_CNT_REG
+ call WriteMyCpuReg ; restore original tick count
+ shr eax, 16 ; original CPL to AX
+ mov dx, My+CpuPriortyLevel
+ out dx, ax ; restore original CPL
+
+ pop edx ; (edx)->IDT
+ movzx ecx, _HalpIRQLtoVector[PROFILE_LEVEL-19]
+ pop [edx+8*Ecx+4]
+ ; restore higher half of NMI desc
+ pop [edx+8*Ecx]
+ ; restore lower half of NMI desc
+; push original interrupt masks (already on stack)
+ push ICU_IMR1
+ call WriteMyCpuReg ; restore original mask (high)
+ rol eax, 16
+ out dx, ax ; restore original mask (low)
+
+; push original local interrupt pointer (already on stack)
+ push ICU_LIPTR
+ call WriteMyCpuReg ; restore original LIPTR
+
+;
+; dismiss interrupt at ICU
+;
+ mov dx, My+CpuIntCmd
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz @B
+ mov al, ICU_CLR_INSERV1 ; clear interrupt in service bit
+ out dx, ax
+
+ lea eax, iscSpinLock
+ RELEASE_SPINLOCK eax
+
+ exproc 7
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+ stdRET _HalpInitializeStallExecution
+
+stdENDP _HalpInitializeStallExecution
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+cPublicProc _KeStallExecutionProcessor ,1
+
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+
+ mov eax, fs:PcStallScaleFactor ; get per microsecond
+ ; loop count for the processor
+ mul ecx ; (eax) = desired loop count
+
+if DBG
+
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short kese
+ stdCall _DbgBreakPoint ; stop ...
+;; align 4
+kese: cmp eax,0
+ jnz short kese0
+ stdCall _DbgBreakPoint ; stop ...
+endif
+
+kese0:
+ sub eax, 1 ; (eax) = (eax) - 1
+ jnz short kese0
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+
+
+;++
+;
+; PROFILING AND PERFORMANCE COUNTER SUPPORT
+;
+;--
+
+;++
+;
+; HalStartProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the slowest thing we can get away with to the value
+; that's been KeSetProfileInterval
+;
+;--
+
+cPublicProc _HalStartProfileInterrupt ,1
+
+;
+; Prevent races by aquiring Halp8254Lock
+;
+
+ pushfd
+HStartPI01:
+ cli
+ test fs:PcHal.pchCurLiptr, lipGlobal
+ jnz short HStartPI08 ;jump if already started
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, HStartPI10
+
+;
+; Mark profiling as active
+;
+
+ inc HalpProfilingStopped ;protected by spinlock
+ jnz short HStartPI06 ;jump if RollerCount already set
+
+;
+; Set the interrupt rate to what is actually needed
+;
+
+ stdCall _HalpSetRolloverCount, <HalpProfileRolloverCnt>
+
+HStartPI06:
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+ push lipDefault+lipGlobalVal
+ push ICU_LIPTR
+ call WriteMyCpuReg
+ mov fs:PcHal.pchCurLiptr, eax
+HStartPI08:
+ popfd
+ stdRET _HalStartProfileInterrupt
+
+HStartPI10:
+ sti
+ SPIN_ON_SPINLOCK eax, HStartPI01
+
+stdENDP _HalStartProfileInterrupt
+
+
+
+;++
+;
+; HalStopProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the high profiling rate to the slowest thing we
+; can get away with for PerformanceCounter rollover notification.
+;
+;--
+
+cPublicProc _HalStopProfileInterrupt ,1
+
+;
+; Prevent races
+;
+ pushfd
+HStopPI01:
+ cli
+ test fs:PcHal.pchCurLiptr, lipGlobal
+ jz short HStopPI08 ;jump if already stopped
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, HStopPI10
+
+ dec HalpProfilingStopped ;protected by spinlock
+ jns short HStopPI06 ;jump if still someone doing it
+;
+; Set the interrupt rate to "idle"
+;
+
+ stdCall _HalpSetRolloverCount, <MAXIMUM_ROLLOVER_COUNT>
+
+;
+; Turn off profiling hit computation
+;
+
+
+HStopPI06:
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+ push lipDefault
+ push ICU_LIPTR
+ call WriteMyCpuReg
+ mov fs:PcHal.pchCurLiptr, eax
+HStopPI08:
+ popfd
+ stdRET _HalStopProfileInterrupt
+
+HStopPI10:
+ sti
+ SPIN_ON_SPINLOCK eax, HStopPI01
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; If profiling is active (KiProfilingStopped == 0) the actual
+; hardware interrupt rate will be set. Otherwise, a simple
+; rate validation computation is done.
+;
+; Arguments:
+;
+; (TOS+4) - Interval in 100ns unit.
+;
+; Return Value:
+;
+; Interval actually used by system.
+;
+;--
+
+cPublicProc _HalSetProfileInterval ,1
+
+ mov edx, [esp+4] ; [edx] = interval in 100ns unit
+
+ pushfd
+HSetPI01:
+ cli
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, HSetPI10
+
+ push edx ; [TOS] = interval
+;
+; Convert the interval to rollover count for Timer1 device.
+; Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+; sec, the computation is:
+; RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+; = Interval * 0.1193
+; = Interval * 1193 / 10000
+;
+
+ mov eax, 1193
+ mul edx ; [edx:eax] = interval * 1193
+ mov ecx, 10000
+ div ecx ; [eax] = rollover count
+ test eax, 0FFFF0000H ; Is high word set?
+ jz short Kspi80 ; if z, no , go initialize 8254
+ pop eax ; else discard original interval
+ push MAXIMUM_ROLLOVER_INTERVAL ; set real interval
+ mov eax, MAXIMUM_ROLLOVER_COUNT ; use max. rollover count
+
+Kspi80:
+ mov HalpProfileRolloverCnt, eax
+ test dword ptr HalpProfilingStopped,-1
+ js short Kspi90
+
+ stdCall _HalpSetRolloverCount, <eax>
+
+Kspi90:
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+ pop eax ; (eax) = returned Interval
+
+ Popfd
+
+ stdRET _HalSetProfileInterval ; (eax) = cReturn interval
+
+HSetPI10:
+ sti
+ SPIN_ON_SPINLOCK eax, HSetPI01
+stdENDP _HalSetProfileInterval
+
+ page ,132
+ subttl "Set Performance Counter Rollover count"
+;++
+;
+; VOID
+; HalpSetRolloverCount (
+; IN ULONG RolloverCount
+; )
+;
+; Routine Description:
+;
+; This function initialize 8254 timer chip counter 0 to generate
+; timer interrupt at the rate specified by caller. The timer 1 counter0
+; will be initialized to use binary count down, 16-bit counter, and mode
+; 2.
+;
+; Note that 8254 mode 2 will not use the new count immediately. The
+; new count will be loaded at the end of current counting cycle.
+;
+; NOTE: Interrupts must already be disabled and Halp8254Lock must
+; already be aquired!
+;
+; Arguments:
+;
+; RolloverCount [TOS+4] - Value used to set timer 1 counter 0's
+; rollover counter.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KsrcRolloverCount equ [esp+4]
+
+cPublicProc _HalpSetRolloverCount ,1
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov ecx, KsrcRolloverCount
+ mov HalpNextRolloverCount, ecx ; set new count
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ mov HalpPerfCounterInit, 1 ; indicate performance counter has
+ ; been initialized
+ stdRET _HalpSetRolloverCount
+
+stdENDP _HalpSetRollOverCount
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter ,1
+ push ebx
+ push esi
+
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before 8254
+; initialization has occured. Reading garbage off the 8254 is not reasonable.
+;
+ cmp HalpPerfCounterInit, 0
+ jne Kqpc01 ; ok, perf counter has been initialized
+
+;
+; Initialization hasn't occured yet, so just return zeroes.
+;
+ mov eax, 0
+ mov edx, 0
+ jmp Kqpc20
+
+Kqpc01:
+Kqpc11: pushfd
+ cli
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+; NOTE:
+; Need to watch for Px reading the 'CounterLow', P0 updates both
+; then Px finishes reading 'CounterHigh' [getting the wrong value].
+; After reading both, make sure that 'CounterLow' didn't change.
+; If it did, read it again. This way, we won't have to use a spinlock.
+;
+
+@@:
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+ cmp ebx, HalpPerfCounterLow ;
+ jne @b
+;
+; Fetch the current counter value from the hardware
+;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+ jmp $+2
+
+
+;
+; Fetch the base value again.
+;
+
+@@:
+ mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+
+ cmp eax, HalpPerfCounterLow
+ jne @b
+
+;
+; Compare the two reads of Performance counter. If they are different,
+; simply returns the new Performance counter. Otherwise, we add the hardware
+; count to the performance counter to form the final result.
+;
+
+ cmp eax, ebx
+ jne short Kqpc20
+ cmp edx, esi
+ jne short Kqpc20
+ neg ecx ; PIT counts down from 0h
+ add ecx, HalpRolloverCount
+ add eax, ecx
+ adc edx, 0 ; [edx:eax] = Final result
+
+;
+; Return the counter
+;
+
+Kqpc20:
+ ; return value is in edx:eax
+
+;
+; Return the freq. if caller wants it.
+;
+
+ or dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc99 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc99:
+ pop esi ; restore esi and ebx
+ pop ebx
+ stdRET _KeQueryPerformanceCounter
+
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc11>
+
+stdENDP _KeQueryPerformanceCounter
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ mov eax, [esp+4] ; ponter to Number
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ ;
+ ; Nothing to calibrate on a Wyse MP machine. There is only a single
+ ; 8254 device
+ ;
+
+ popfd ; restore interrupt flag
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+;
+; This routine is entered as the result of an interrupt generated by CLOCK2.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+
+;
+; dismiss interrupt and raise Irql
+;
+
+ movzx eax, _HalpIRQLtoVector[CLOCK2_LEVEL]
+ push eax ; save our interrupt vector number
+ sub esp, 4 ; allocate space to save OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,eax,esp>
+
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; (ebp) = address of trap frame
+;
+ mov eax, TIME_INCREMENT
+
+ cmp fs:PcHal.pchPrNum, 0 ; is this the master cpu?
+ je _KeUpdateSystemTime@0 ; if it is, update system time
+
+ sti
+ stdCall _KeUpdateRunTime,<dword ptr [esp]> ; othewise update runtime
+
+ INTERRUPT_EXIT ; lower irql to old value, iret
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpClockInterrupt
+
+ page ,132
+ subttl "System Profile Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; PROFILE_LEVEL and transfer control to the standard system routine
+; to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpi_a, Hpi_t
+
+cPublicProc _HalpProfileInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpi_a, Hpi_t
+
+;
+; (esp) - base of trap frame
+;
+
+ movzx eax, _HalpIRQLtoVector[PROFILE_LEVEL]
+ push eax
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,eax,esp>
+ or al,al ; check for spurious interrupt
+ jz Hpi100
+;
+; (esp) = OldIrql
+; (esp+4) = H/W vector
+; (esp+8) = base of trap frame
+;
+ test fs:PcHal.pchCurLiptr, lipGlobal
+ je Hpi90 ; if prof disable don't call kernel
+
+ stdCall _KeProfileInterrupt,<ebp> ; (ebp) = trap frame
+
+Hpi90: INTERRUPT_EXIT
+
+Hpi100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpProfileInterrupt
+
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a performance counter interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; PROFILE_LEVEL-1, update the performance counter, and generate the
+; profile interrupts if any there are any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; none
+;
+; Sets Irql = PROFILE_LEVEL-1 and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpci_a, Hpci_t
+
+cPublicProc _HalpPerfCtrInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpci_a, Hpci_t
+
+;
+; (esp) - base of trap frame
+;
+
+ movzx eax, _HalpIRQLtoVector[PROFILE_LEVEL-1]
+ push eax
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL-1,eax,esp>
+ or al,al ; check for spurious interrupt
+ jz Hpci100
+;
+; (esp) = OldIrql
+; (esp+4) = H/W vector
+; (esp+8) = base of trap frame
+;
+
+;
+; Update performance counter
+;
+ mov eax, HalpNextRolloverCount
+ mov ecx, HalpRollOverCount
+ mov HalpRollOverCount, eax ; next rollover count
+ add HalpPerfCounterLow, ecx ; update performace counter
+ adc HalpPerfCounterHigh, 0
+
+;
+; Now check is any profiling stuff to do.
+;
+
+ cmp HalpProfilingStopped, 0 ; Has profiling been stopped?
+; je _KeProfileInterrupt@0 ; if prof enabled, jump to kernel
+ js short Hpci99 ; jump if all stopped
+ cli
+ mov dx, My+CpuIntCmd
+@@: in ax, dx ;wait til ICU not busy
+ test eax, ICU_CMD_BUSY
+ jnz @B
+ mov ax, ICU_XMT_GLB_INT
+ out dx, ax ;set profile interrupt to all interested
+
+Hpci99:
+ INTERRUPT_EXIT
+
+Hpci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpPerfCtrInterrupt
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, TIME_INCREMENT
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+_TEXT ends
+ end
+
diff --git a/private/ntos/nthals/halwyse7/i386/wydetect.asm b/private/ntos/nthals/halwyse7/i386/wydetect.asm
new file mode 100644
index 000000000..b18e643ee
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wydetect.asm
@@ -0,0 +1,167 @@
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+; Copyright (c) 1992, 1993 Wyse Technology
+;
+; Module Name:
+;
+; wydetect.asm
+;
+; Abstract:
+;
+; This modules detects a Wyse7000 or compatible. It is INCLUDED
+; by WYIPI and other binaries whom need to know how to detect a
+; Wyse7000 type MP machine (ie, setup). It must assemble more or
+; less standalone and run in protect mode.
+;
+; Author:
+;
+; John Fuller (o-johnf) 3-Apr-1992 Convert to Wyse7000i MP system.
+;
+;Revision History:
+;
+; John Fuller (o-johnf) 3-Apr-1992 Convert to Wyse7000i MP system.
+;--
+
+include callconv.inc ; calling convention macros
+
+;*****************************
+; Wyse 7000i MP defines from wy7000mp.inc
+; These are copied into this module to allow it to be build standalone
+; by the setup program.
+;
+WyModel740 Equ 00170335Fh ;EISA id for model 740 system board
+WyModel760 Equ 00178335Fh ;EISA id for model 760 system board
+WyModel780 Equ 00978335Fh ;EISA id for model 780 system board
+; ;(model hasn't been named, but
+; ; 780 is as good as anything)
+
+
+My Equ 00F0h ;WWB slot number specifies local cpu
+CpuCCUptr Equ 0C00h ;CCU pointer register (add WWB slot*16)
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+; wySystemType: SystemType is read from 0c80-0c83h.
+; 0c80-0c81: 5F33: Compressed WYS (5 bit encoding).
+; 0c82-0c83: System Board type.
+;
+; SystemType: Is it a Wyse7000i? Gets init'd by P0 ONLY ONCE.
+; 0: not a Wyse7000i
+; 1: 7000i/model 740
+; 2: 7000i/model 760
+; 3: 7000i/model 780
+;
+wySystemTypeTable label dword
+
+ dd WyModel740 ;type 1
+
+; dd ?????????? add here any other non-ICU type system boards
+
+ public SYSTYPE_NO_ICU
+SYSTYPE_NO_ICU equ ($-wySystemTypeTable)/4 ;highest non-ICU type number
+
+ dd WyModel760 ;type 2
+ dd WyModel780 ;type 3
+
+; dd ?????????? add here any other ICU type system boards
+
+WYTABLE_SIZE equ ($-wySystemTypeTable)/4 ;highest system type number
+
+wySystemType dd 0 ;store EISA ID for system board
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; ULONG
+; DetectWyse7 (
+; OUT PBOOLEAN IsConfiguredMp
+; );
+;
+; Routine Description:
+; Determines the type of system (specifically for eisa machines), by reading
+; the system board system ID. It compares the 4 bytes of the ID, to
+; a predefined table <abSystemTypeTable> and returns the index to the
+; found entry.
+;
+; Arguments:
+; IsConfiguredMp - If detected, then this value is
+; set to TRUE if it's an MP system, else FALSE.
+;
+; Return Value:
+; 0 - if not a Wyse7
+; 1 - if type 1
+; 2 - if type 2
+; etc...
+;--
+cPublicProc _DetectWyse7 ,1
+
+ push edi
+ push esi
+ push ebx ; Save C Runtime
+
+ ; 4 byte value is read from 0c80-0c83, and saved in <wySystemType>.
+ ; The value is compared to table in <abSystemTypeTable>, and
+ ; the SystemType is updated accordingly.
+
+ lea edi, wySystemType
+ mov edx, 0c80h
+ cld ; increment edi
+ insb ; 0e CPQ
+ inc edx
+ insb ; 11
+ inc edx
+ insb ; SystemType
+ inc edx
+ insb ; Revision
+
+ mov ebx, wySystemType ;get read EISA ID
+ mov ecx, WYTABLE_SIZE
+@@: cmp ebx, wySystemTypeTable[4*ecx-4]
+ je short @F ;jump if found
+ loop @B
+ jmp short WyNotFound
+
+@@:
+ cmp ecx, SYSTYPE_NO_ICU
+ ja short WyFound ;jump if ICU type system board found
+;
+; We have found an MP-capable system, now we have to verify that
+; we have an actual MP-CPU
+
+ mov eax, 0FFAAh
+ mov edx, My+CpuCCUptr ;register doesn't exist on UP-CPU
+ pushfd ;save interrupt flag
+ cli
+ out dx, al ;write data pattern to register
+ xchg ah, al
+ out 0ECh, al ;precharge bus (non-existant register)
+ in al, dx ;read data pattern again
+ popfd
+ cmp al, ah ;if it's not the data we wrote
+ jne short WyNotFound ; then it's not an MP-CPU
+
+WyFound:
+ mov eax, ecx ; Type found
+ mov ebx, dword ptr [esp+16]
+ mov byte ptr [ebx], 1 ; *IsConfiguredMp = TRUE
+
+WyExit: pop ebx
+ pop esi
+ pop edi
+
+ stdRET _DetectWyse7
+
+WyNotFound:
+ xor eax, eax ; No type
+ jmp short WyExit
+
+stdENDP _DetectWyse7
+
+_TEXT ENDS
diff --git a/private/ntos/nthals/halwyse7/i386/wyhal.c b/private/ntos/nthals/halwyse7/i386/wyhal.c
new file mode 100644
index 000000000..85b724b14
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wyhal.c
@@ -0,0 +1,378 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Wyse Technology
+
+Module Name:
+
+ wyhal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Wyse 7000i x86 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ John Nels Fuller (o-johnf) 26-Mar-1992 convert for Wyse 7000i
+--*/
+
+#include "halp.h"
+
+ADDRESS_USAGE HalpDefaultWyseIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ // Standard PC ISA I/O space used...
+ 0x000, 0x10, // ISA DMA
+ 0x0C0, 0x10, // ISA DMA
+ 0x080, 0x10, // DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ 0x048, 0x4, // Timer2, Failsafe
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+ 0x0F0, 0x10, // coprocessor ports
+
+ // Standard PC EISA I/O space used...
+ 0x0D0, 0x10, // DMA
+ 0x400, 0x10, // DMA
+ 0x480, 0x10, // DMA
+ 0x4C2, 0xE, // DMA
+ 0x4D4, 0x2C, // DMA
+
+ 0x461, 0x2, // Extended NMI
+ 0x464, 0x2, // Last Eisa Bus Muster granted
+
+ 0x4D0, 0x2, // edge/level control registers
+
+ 0xC84, 0x1, // System board enable
+
+ // Wyse I/O Space used...
+
+ 0x8F0, 0x8, // BCU/ICU on cpu boards
+ 0x800, 0x8, // BCU/ICU on system board
+ 0xCF0, 0x4, // 80486 CCU, Pentium WDC
+ 0xCF4, 0x6, // 80486 WBI, Pentium WDP
+
+ 0, 0
+
+ }
+};
+
+
+VOID
+HalpICUSpurious(
+ VOID
+ );
+
+VOID
+HalpIPInterrupt(
+ VOID
+ );
+
+VOID
+HalpReInitProcessor(
+ ULONG ProcessorNumber
+ );
+
+ULONG HalpBusType;
+
+#ifndef NT_UP
+ULONG
+HalpInitMP(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+#endif
+
+
+extern CCHAR HalpIRQLtoVector[];
+
+VOID
+HalpPerfCtrInterrupt(
+ VOID
+ );
+
+KSPIN_LOCK HalpSystemHardwareLock;
+
+//BOOLEAN
+//HalpVerifyMachine (
+// VOID
+// );
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization was successfully
+ completed. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ KIRQL CurrentIrql;
+ PKPRCB pPRCB;
+ ULONG BuildType;
+
+
+ pPRCB = KeGetCurrentPrcb();
+
+ if (Phase == 0) {
+
+ HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
+
+ //
+ // Verify Prcb version and build flags conform to
+ // this image
+ //
+
+ BuildType = 0;
+#if DBG
+ BuildType |= PRCB_BUILD_DEBUG;
+#endif
+#ifdef NT_UP
+ BuildType |= PRCB_BUILD_UNIPROCESSOR;
+#endif
+
+ if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ if (pPRCB->BuildType != BuildType) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 2, pPRCB->BuildType, BuildType, 0);
+ }
+
+
+ //
+ // Phase 0 initialization
+ // only called by P0
+ //
+
+
+ //
+ // Initialize the ICU spurious interrupt vector
+ //
+
+ KiSetHandlerAddressToIDT( PRIMARY_VECTOR_BASE+16, HalpICUSpurious );
+
+ HalpInitializePICs();
+
+ //
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ KfLowerIrql(CurrentIrql);
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Initialize CMOS
+ //
+
+ HalpInitializeCmos();
+
+ //
+ // Register base IO space used by hal
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultWyseIoSpace);
+
+ //
+ // Note that HalpInitializeClock MUST be called after
+ // HalpInitializeStallExecution, because HalpInitializeStallExecution
+ // reprograms the timer.
+ //
+
+ HalpInitializeStallExecution(0);
+
+ HalpInitializeClock();
+
+ //
+ // Initialize the clock interrupt vector for the processor that keeps
+ // the system time.
+ //
+
+ KiSetHandlerAddressToIDT( HalpIRQLtoVector[CLOCK2_LEVEL],
+ HalpClockInterrupt );
+
+ //
+ // Initialize the IPI vector
+ //
+
+ KiSetHandlerAddressToIDT( HalpIRQLtoVector[IPI_LEVEL],
+ HalpIPInterrupt);
+
+ //
+ // Initialize the profile interrupt vector.
+ //
+
+ HalStopProfileInterrupt(0);
+
+ KiSetHandlerAddressToIDT( HalpIRQLtoVector[PROFILE_LEVEL],
+ HalpProfileInterrupt);
+
+ //
+ // Initialize the performance counter interrupt vector
+ //
+
+ KiSetHandlerAddressToIDT( HalpIRQLtoVector[PROFILE_LEVEL-1],
+ HalpPerfCtrInterrupt);
+
+ HalpInitializeDisplay();
+
+ //
+ // Initialize spinlock used by HalGetBusData hardware access routines
+ //
+
+ KeInitializeSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ } else {
+
+ //
+ // Phase 1 initialization
+ //
+
+ if (KeGetPcr()->Prcb->Number == 0) {
+ HalpRegisterInternalBusHandlers ();
+ }
+
+ //
+ // enable PROFILE interrupt
+ //
+ HalEnableSystemInterrupt( HalpIRQLtoVector[PROFILE_LEVEL],
+ PROFILE_LEVEL, Latched);
+ //
+ // enable Performance Counter interrupt
+ //
+ HalEnableSystemInterrupt( HalpIRQLtoVector[PROFILE_LEVEL-1],
+ PROFILE_LEVEL-1, Latched);
+ //
+ // enable CLOCK2 interrupt
+ //
+ HalEnableSystemInterrupt( HalpIRQLtoVector[CLOCK2_LEVEL],
+ CLOCK2_LEVEL, Latched);
+ if (KeGetPcr()->Prcb->Number == 0) {
+
+ //
+ // If P0, then enable IPI, IPI's already enabled on other cpu's
+ //
+ HalEnableSystemInterrupt( HalpIRQLtoVector[IPI_LEVEL],
+ IPI_LEVEL, Latched);
+ }
+
+ }
+
+
+ HalpInitMP (Phase, LoaderBlock);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halwyse7/i386/wyipi.asm b/private/ntos/nthals/halwyse7/i386/wyipi.asm
new file mode 100644
index 000000000..297964749
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wyipi.asm
@@ -0,0 +1,775 @@
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991-1993 Microsoft Corporation
+;Copyright (c) 1992, 1993 Wyse Technology
+;
+;Module Name:
+;
+; wyipi.asm
+;
+;Abstract:
+;
+; Wyse7000i IPI code.
+; Provides the HAL support for Interprocessor Interrupts for the
+; MP Wyse7000i implementation.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+; John Fuller (o-johnf) 3-Apr-1992 Convert to Wyse7000i MP system.
+; John Fuller (o-johnf) 31-Aug-1993 Mods for Lazy IRQLs
+;--
+.386p
+ .xlist
+
+;
+; Include Wyse7 dection code
+;
+
+include i386\wydetect.asm
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include i386\kimacro.inc
+include i386\ix8259.inc
+include i386\wy7000mp.inc
+include callconv.inc
+
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ extrn _HalpDefaultInterruptAffinity:DWORD
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalpInitializeClock,0
+ EXTRNP _HalDisplayString,1
+ EXTRNP _HalpInitializeStallExecution,1
+ extrn _HalpIRQLtoVector:BYTE
+ extrn _ProcessorsPresent:BYTE
+ extrn _HalpActiveProcessors:DWORD
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ public SystemType
+SystemType dd 0
+
+ public _HalpProcessorSlot
+_HalpProcessorSlot db MAXIMUM_PROCESSORS dup (0)
+
+BadHalString db 'HAL: Wyse EISA/MP HAL cannot run on '
+ db 'non-Wyse or non-EISA/MP machine.', cr, lf
+ db ' Replace the hal.dll with the correct hal', cr, lf
+ db ' System is HALTING *********', 0
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ if DBG
+ %out _ProcSub
+;++
+;
+; VOID
+; ProcSub(
+; UCHAR Number
+; );
+;
+;Routine Description:
+;
+; Writes Number to BCU general purpose register, restores all
+; registers and flags.
+;
+;Arguments:
+;
+; Number - Procedure entry/exit code
+;
+;Return Value:
+;
+; None. (restores eax)
+;
+;--
+cPublicProc _ProcSub ,1
+ pushfd
+ push eax
+ push edx
+ mov dx, My+CpuPtrReg
+ mov al, BCU_GPR
+ cli
+ out dx, al
+ add edx, CpuDataReg-CpuPtrReg
+ movzx eax, byte ptr [esp][16]
+ out dx, ax
+ pop edx
+ pop eax
+ popfd
+ stdRET _ProcSub
+stdENDP _ProcSub
+
+ endif ;DBG
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . PcHal.pchPrNum = processor number
+; . PcHal.pchPentiumFlag = processor type (80486=0, Pentium=1)
+; . if (P0)
+; . determine what kind of system is it,
+; . if (Not Wyse7000i) Exit;
+; . HalpDefaultInterruptAffinity[Pn] = 1
+; . if (80486)
+; . WBI IACK_MODE = 1 (all WBIs)
+; . CCU_CR[WWB_FPE_EN, PCD_EN] = 0,1?
+; . else (Pentium)
+; . WDP[IACK_MODE, FPE_EN] = 1, 0 (both WDP's)
+; . CpuDiagUart[MCR] = 7 (DTR, RTS, OUT1, -OUT2, -LOOP)
+; . CpuPriortyLevel = 0
+; . PcHal.pchHwIrql = HIGH_LEVEL
+; . ICU_CNT_REG = 0
+; . ICU_LIPTR = lipDefault
+; . BCU_BCTLR[A20M_WWB, A20M_CPU, SLOW_ENB] = 0,0,0
+; . _HalpProcessorSlot[Pn] = BCU_ID
+; . ICU_PSR0,1 = 0
+; . PcIDR = ICU_IMR0,1 = IMR_MASK
+; . ICU_VB0 = PIC1_BASE
+; . ICU_VB1 = PIC2_BASE
+; . ICU_VB2 = IPIv_BASE
+; . if (P0)
+; . _ProcessorsPresent = ~ICU_SYS_CPU & ~(P0_slot_bit+sys_slot_bit)
+; . if (Model760/780) // Init SysBd ICU/BCU/WBI
+; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,0
+; . clear pending interrupt
+; . Sys ICU_CNT_REG = 0
+; . Sys WBI IACK_MODE = 1 (all WBIs)
+; . Sys ICU_LIPTR = 0
+; . Sys BCU_BCTLR[A20M_WWB, A20M_CPU, SLOW_ENB] = 0,0,0
+; . Sys ICU_PSR0,1 = 0
+; . Sys ICU_IMR0,1 = IMR_MASK & ~1
+; . Sys ICU_VB0 = PIC1_BASE
+; . Sys ICU_VB1 = PIC2_BASE
+; . Sys ICU_VB2 = IPIv_BASE
+; . Sys ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,1,1,1,1
+; . else
+; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,1
+; . ICU_ICTLR[WWB_INT] = 1
+; . PcPDR[0] = 0
+; . clear pending interrupt
+; . else
+; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,1,0
+; . clear pending interrupt
+; . initalize stall count
+; . initialize clock
+; . enable IPI's
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor ,1
+ enproc 1
+ pushfd
+ cli
+
+; . PcHal.pchPrNum = processor number
+ movzx eax, byte ptr [esp+8] ;get processor number
+ mov fs:PcHal.pchPrNum, al ;save for future reference
+ lock bts _HalpActiveProcessors, eax
+
+; . PcHal.pchPentiumFlag = processor type (80486=0, Pentium=1)
+ pushfd
+ pop ecx
+ xor ecx, 1 shl 21 ;toggle CPUID flag
+ push ecx
+ popfd
+ pushfd
+ pop edx
+ cmp ecx, edx
+ sete Fs:PcHal.pchPentiumFlag
+
+; . if (P0)
+ or eax, eax ;test for processor zero
+ jnz short hipAllCpus ;jump if not
+
+; . determine what kind of system is it,
+; . if (Not Wyse7000i) Exit;
+
+ sub esp, 4
+ stdCall _DetectWyse7, <esp> ;doesn't run if not Wyse 7000i
+ add esp, 4
+ or eax, eax
+ jz NotWyse7
+ mov SystemType, eax
+
+ xor eax, eax ;make sure eax is 0 for hipAllCpus
+
+hipAllCpus:
+; . HalpDefaultInterruptAffinity[Pn] = 1
+ lock bts _HalpDefaultInterruptAffinity, eax
+ mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
+
+; . if (80486)
+ cmp Fs:PcHal.pchPentiumFlag, 0
+ Jne Short hipIsPentium
+
+; . WBI IACK_MODE = 1 (all WBIs)
+ mov dx, My+CpuWBIlow ;point to WBI for data bits 0-32
+ in ax, dx
+ or ax, WBI_IACK_MODE ;set MP interrupt mode
+ out dx, ax
+
+ mov dx, My+CpuWBIhigh ;point to WBI for data bits 33-63
+ in ax, dx
+ or ax, WBI_IACK_MODE ;set MP interrupt mode
+ out dx, ax
+
+ mov dx, My+CpuWBIaddr ;point to WBI for address bits
+ in ax, dx
+ or ax, WBI_IACK_MODE ;set MP interrupt mode
+ out dx, ax
+
+; . CCU_CR[WWB_FPE_EN, PCD_EN] = 0,1?
+ mov al, CCU_CR
+ mov dx, My+CpuCCUptr
+ out dx, al
+ mov dx, My+CpuCCUdata
+ in ax, dx
+ and eax, not WWB_FPE_EN
+ or eax, PCD_EN
+ out dx, ax
+ jmp short hipIs80486
+
+; . else (Pentium)
+hipIsPentium:
+; . WDP[IACK_MODE, FPE_EN] = 1, 0 (both WDP's)
+ mov dx, MyCpuWDPlow
+ in ax, dx
+ and eax, not WDP_FPE_EN
+ or eax, WDP_IACK_MODE
+ out dx, ax
+ mov dx, MyCpuWDPhigh
+ in ax, dx
+ and eax, not WDP_FPE_EN
+ or eax, WDP_IACK_MODE
+ out dx, ax
+
+hipIs80486:
+; . CpuDiagUart[MCR] = 7 (DTR, RTS, OUT1, -OUT2, -LOOP)
+ mov dx, My+CpuDiagUart+4
+ mov al, 7
+ out dx, ax ;disable diag port interrupts
+
+; . CpuPriortyLevel = 0
+ xor eax, eax
+ mov dx, My+CpuPriortyLevel
+ out dx, ax
+
+; . PcHal.pchHwIrql = HIGH_LEVEL
+ mov Fs:PcHal.pchHwIrql, HIGH_LEVEL
+
+ mov dx, My+CpuDataReg ;point to my BCU/ICU
+
+; . ICU_CNT_REG = 0
+ push 0
+ push ICU_CNT_REG
+ call WriteCpuReg ;stop local timer
+
+; . ICU_LIPTR = lipDefault
+ push lipDefault
+ push ICU_LIPTR
+ call WriteCpuReg
+ mov fs:PcHal.pchCurLiptr, eax
+
+; . BCU_BCTLR[A20M_WWB, A20M_CPU, SLOW_ENB] = 0,0,0
+ push BCU_BCTLR
+ call ReadCpuReg
+ and eax, not (A20M_WWB + A20M_CPU + SLOW_ENB)
+ push eax
+ push BCU_BCTLR
+ call WriteCpuReg
+
+; . _HalpProcessorSlot[Pn] = BCU_ID
+ push BCU_ID
+ call ReadCpuReg
+ and al, WWB_ID_MASK ;keep only WWB slot number
+ movzx ecx, byte ptr [esp+8] ;get processor number again
+ mov _HalpProcessorSlot[ecx], al
+ mov fs:PcHal.pchPrSlot, al
+
+; . ICU_PSR0,1 = 0
+ push 0
+ push ICU_PSR0
+ call WriteCpuReg ;clear pending bits in ICU_PSR0
+ out dx, ax ;shortcut to clear ICU_PSR1
+
+; . PcIDR = ICU_IMR0,1 = IMR_MASK
+ push IMR_MASK
+ push ICU_IMR0
+ call WriteCpuReg
+ mov fs:PcIDR, eax
+ shr eax, 16
+ out dx, ax ;shortcut to write ICU_IMR1
+
+; . ICU_VB0 = PIC1_BASE
+ push PIC1_BASE
+ push ICU_VB0
+ call WriteCpuReg
+
+; . ICU_VB1 = PIC2_BASE
+ push PIC2_BASE
+ push ICU_VB1
+ call WriteCpuReg
+
+; . ICU_VB2 = IPIv_BASE
+ push IPIv_BASE
+ push ICU_VB2
+ call WriteCpuReg
+
+; . if (P0)
+ cmp byte ptr [esp+8], 0
+ jnz hipNotP0
+
+; . _ProcessorsPresent = ~ICU_SYS_CPU & ~(P0_slot_bit+sys_slot_bit)
+ push ICU_SYS_CPU
+ call ReadCpuReg
+ not al ;make positive true cpu bits
+ and al, not 1 ;clear system board bit
+ movzx ecx, _HalpProcessorSlot[0] ;get P0 slot number
+ btr eax, ecx ;clear our own bit
+ mov _ProcessorsPresent, al ;save for starting others
+
+; . if (Model760/780) // Init SysBd ICU/BCU/WBI
+ cmp SystemType, SYSTYPE_NO_ICU
+ jna hipNotModel760
+
+; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,0
+ push ICU_ICTLR
+ call ReadCpuReg
+ and eax, not (WWB_INT + ICU_AEOI + MSK_CPURST)
+ or eax, IACK_MODE + INT_ENB
+ push eax
+ push ICU_ICTLR
+ call WriteCpuReg
+
+; . clear pending interrupt
+ call ClearPendingInt
+
+ mov dx, Sys+CpuDataReg ;point to system board registers
+
+; . Sys ICU_CNT_REG = 0
+ push 0
+ push ICU_CNT_REG
+ call WriteCpuReg ;disable sys board timer
+
+; . Sys WBI IACK_MODE = 1 (all WBIs)
+ push SYS_WBI_LOW
+ call ReadCpuReg
+ or eax, WBI_IACK_MODE ;set MP interrupt mode
+ push eax
+ push SYS_WBI_LOW
+ call WriteCpuReg
+
+ mov dx, Sys+CpuDataReg ;point to system board registers
+ push SYS_WBI_HIGH
+ call ReadCpuReg
+ or eax, WBI_IACK_MODE ;set MP interrupt mode
+ push eax
+ push SYS_WBI_HIGH
+ call WriteCpuReg
+
+ mov dx, Sys+CpuDataReg ;point to system board registers
+ push SYS_WBI_ADDR
+ call ReadCpuReg
+ or eax, WBI_IACK_MODE ;set MP interrupt mode
+ push eax
+ push SYS_WBI_ADDR
+ call WriteCpuReg
+
+ push 0
+ push ICU_LIPTR
+ call WriteCpuReg
+
+; . Sys ICU_PSR0,1 = 0
+ push 0
+ push ICU_PSR0
+ call WriteCpuReg ;clear pending bits in ICU_PSR0
+
+ push 0
+ push ICU_PSR1
+ call WriteCpuReg ;clear pending bits in ICU_PSR1
+
+; . Sys ICU_IMR0,1 = IMR_MASK & ~1
+ push IMR_MASK and (not 1) ;allow only level 0
+ push ICU_IMR0
+ call WriteCpuReg
+
+ shr eax, 16
+ push eax
+ push ICU_IMR1
+ call WriteCpuReg ;set ICU_IMR1
+
+; . Sys ICU_VB0 = PIC1_BASE
+ push PIC1_BASE
+ push ICU_VB0
+ call WriteCpuReg
+
+; . Sys ICU_VB1 = PIC2_BASE
+ push PIC2_BASE
+ push ICU_VB1
+ call WriteCpuReg
+
+; . Sys ICU_VB2 = IPIv_BASE
+ push IPIv_BASE
+ push ICU_VB2
+ call WriteCpuReg
+
+; . Sys ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,1,1,1,1
+ push ICU_ICTLR
+ call ReadCpuReg
+ or eax, IACK_MODE + INT_ENB + WWB_INT + MSK_CPURST + ICU_AEOI
+ push eax
+ push ICU_ICTLR
+ call WriteCpuReg
+ jmp short hipExit
+
+; . else
+hipNotModel760:
+
+; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,1
+ push ICU_ICTLR
+ call ReadCpuReg
+ and eax, not (ICU_AEOI + MSK_CPURST)
+ or eax, IACK_MODE + INT_ENB + WWB_INT
+ push eax
+ push ICU_ICTLR
+ call WriteCpuReg
+
+; . PcPDR[0] = 0
+ and fs:dword ptr PcIDR, not 1 ;allow 8259 interrupt
+ ; distribution, but not until
+ ; 1st HalEnableSystemInterrupt
+; . clear pending interrupt
+ call ClearPendingInt
+ jmp short hipExit
+
+; . else
+hipNotP0:
+
+; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,1,0
+ push ICU_ICTLR
+ call ReadCpuReg
+ and eax, not (WWB_INT + ICU_AEOI)
+ or eax, IACK_MODE + INT_ENB + MSK_CPURST
+ push eax
+ push ICU_ICTLR
+ call WriteCpuReg
+
+; . clear pending interrupt
+ call ClearPendingInt
+
+; . initialize stall count
+ stdCall _HalpInitializeStallExecution, <[esp+8]>
+
+; . initialize clock
+ stdCall _HalpInitializeClock
+
+; . enable IPI's
+ movzx eax, _HalpIRQLtoVector[IPI_LEVEL]
+ stdCall _HalEnableSystemInterrupt, <eax,IPI_LEVEL,1> ;latched interrupt
+
+hipExit:
+ exproc 1
+ popfd
+ stdRET _HalInitializeProcessor
+
+NotWyse7:
+; on a non-Wyse. Display
+; message and HALT system.
+ stdCall _HalDisplayString, <offset BadHalString>
+ hlt
+
+stdENDP _HalInitializeProcessor
+
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalRequestIpi ,1
+ enproc 2
+
+ movzx eax, byte ptr [esp+4] ; (eax) = Processor bitmask
+if DBG
+ or eax, eax ; must ipi somebody
+ jz short ipibad
+
+ movzx ecx, byte ptr fs:PcHal.pchPrNum
+ bt eax, ecx ; cannot ipi yourself
+ jc short ipibad
+endif
+
+ xchg eax, ecx ;processor list to ecx
+ mov edx, My+CpuIntCmd ;point to ICU cmd register
+hriNextProcessor:
+ pushfd
+ cli
+@@: in ax, dx ;get ICU busy status
+ test eax, ICU_CMD_BUSY
+ jnz @B ;wait for not busy
+ bsf eax, ecx
+ btr ecx, eax
+ mov al, _HalpProcessorSlot[eax]
+ or al, ICU_IPI_SLOT
+ out dx, ax
+ popfd
+ or ecx, ecx
+ jnz hriNextProcessor
+ exproc 2
+ stdRET _HalRequestIpi
+
+if DBG
+ipibad: int 3
+ stdRET _HalRequestIpi
+endif
+
+stdENDP _HalRequestIpi
+
+
+ page ,132
+ subttl "Wyse7000i IPI Handler"
+;++
+;
+; VOID
+; HalpIPInterrupt (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by the
+; IPI hardware.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hipi_a, Hipi_t
+
+cPublicProc _HalpIPInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+ ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
+ enproc 3
+;
+; Save previous IRQL
+;
+ movzx eax, _HalpIRQLtoVector[IPI_LEVEL]
+ push eax ;interrupt vector
+ sub esp, 4 ;space for OldIrql
+
+;raise to new Irql
+
+ stdCall _HalBeginSystemInterrupt, <IPI_LEVEL,eax,esp>
+ or al, al
+ jz Hipi100 ;jump if spurrious interrupt
+
+; Pass TrapFrame to Ipi service rtn
+; Pass Null ExceptionFrame
+
+ stdCall _KiIpiServiceRoutine, <ebp,0>
+
+ exproc 3
+;
+; Do interrupt exit processing
+;
+ INTERRUPT_EXIT ; will return to caller
+
+Hipi100:
+ exproc 3
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpIPInterrupt
+;++
+;
+; VOID
+; HalpIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by the
+; EISA DMA buffer chaining interrupt. Currently, NO NT driver uses the DMA
+; buffer chaining capability. For now, this routine is simply commented
+; out.
+;
+; Note: IRQ13 could also be used for coprocessor error, but the Wyse7000i
+; is a 486 machine so coprocessor error is handled as a processor
+; fault and the FERR output of the 486 is masked off the IRQ13
+; input to the 8259 so that the only possible IRQ13 interrupt is for
+; DMA chaining.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+; public _HalpIrq13Handler
+;_HalpIrq13Handler proc
+;
+;_HalpIrq13Handler endp
+
+;++
+; BOOLEAN
+; HalpVerifyMachine (
+; VOID
+; );
+;
+; Routine Description:
+; Return TRUE if this is a Wyse7000i
+;
+;--
+;cPublicProc _HalpVerifyMachine ,0
+; xor eax, eax
+; cmp SystemType, eax
+; setnz al
+; stdRET _HalpVerifyMachine
+;stdENDP _HalpVerifyMachine
+
+
+ public ReadMyCpuReg
+ReadMyCpuReg proc
+ mov dx, My+CpuDataReg
+ReadCpuReg:
+ add edx, CpuPtrReg - CpuDataReg
+ mov al, [esp+4]
+ out dx, al
+ add edx, CpuDataReg - CpuPtrReg
+ in ax, dx
+ ret 4
+ReadMyCpuReg endp
+
+ public WriteMyCpuReg
+WriteMyCpuReg proc
+ Mov dx, My+CpuDataReg
+WriteCpuReg:
+ add edx, CpuPtrReg - CpuDataReg
+ mov al, [esp+4]
+ out dx, al
+ add edx, CpuDataReg - CpuPtrReg
+ mov eax, [esp+8]
+ out dx, ax
+ ret 8
+WriteMyCpuReg endp
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+
+ClearPendingInt proc
+ enter 8,0 ; setup ebp, reserve 8 bytes of stack
+
+ mov dx, My+CpuDataReg
+ push PIC1_BASE+2 ;set vector out register(unused vector)
+ push ICU_VOUT ;in case of int pending
+ call WriteCpuReg
+
+ xchg ecx, eax ;put vector number in ecx
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov edx, [ebp-6] ; (edx)->IDT
+
+ push dword ptr [edx+8*ecx]
+ ; (TOS) = original desc of IRQ
+ push dword ptr [edx+8*ecx + 4]
+ ; each descriptor has 8 bytes
+ mov eax, offset FLAT:cpiService
+ mov word ptr [edx+8*ecx], ax
+ ; Lower half of handler addr
+ mov word ptr [edx+8*ecx+2], KGDT_R0_CODE
+ ; set up selector
+ mov word ptr [edx+8*ecx+4], D_INT032
+ ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*ecx+6], ax
+
+ sti
+ jmp short $+2 ;allow one pending interrupt
+ cli
+
+ pop [edx+8*ecx+4] ; restore higher half of NMI desc
+ pop [edx+8*ecx] ; restore lower half of NMI desc
+
+ leave
+ ret
+ClearPendingInt endp
+
+cpiService proc
+ push edx
+ push eax
+ mov dx, My+CpuIntCmd
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz @B
+ mov al, ICU_CLR_INSERV1 ; clear interrupt in service bit
+ out dx, ax
+ pop eax
+ pop edx
+ iretd
+cpiService endp
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halwyse7/i386/wyirql.asm b/private/ntos/nthals/halwyse7/i386/wyirql.asm
new file mode 100644
index 000000000..28ef5a777
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wyirql.asm
@@ -0,0 +1,667 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989-1993 Microsoft Corporation
+; Copyright (c) 1992, 1993 Wyse Technology
+;
+; Module Name:
+;
+; wyirql.asm
+;
+; Abstract:
+;
+; Wyse7000i IRQL
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the Wyse ICU hardware.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; John Vert (jvert) 27-Nov-1991
+; Moved from kernel into HAL
+;
+; John Fuller (o-johnf) 2-Apr-1992
+; Converted to Wyse hardware.
+;
+; John Fuller (o-johnf) 31-Aug-1993
+; Mods for Lazy IRQLs
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include i386\wy7000mp.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ extrn _HalpApcInterrupt:near
+ extrn _HalpDispatchInterrupt:near
+ extrn _KiUnexpectedInterrupt:near
+ extrn ReadMyCpuReg:NEAR
+ extrn WriteMyCpuReg:NEAR
+ EXTRNP _HalpClockInterrupt,0
+ EXTRNP _HalpIPInterrupt,0
+
+;
+; Initialization control words equates for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW2_SET_PRIORITY equ 0c0H
+
+;
+; Interrupt flag bit maks for EFLAGS
+;
+
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+
+;
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; PICsInitializationString - Master PIC initialization command string
+;
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ db not (1 shl PIC_SLAVE_IRQ) ;OCW1
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ db 0FFh ;OCW1
+ dw 0 ; end of string
+
+
+ .errnz PROFILE_LEVEL-27 ;error if defines don't match tables
+ .errnz CLOCK2_LEVEL-28 ;error if defines don't match tables
+ .errnz IPI_LEVEL-29 ;error if defines don't match tables
+ .errnz POWER_LEVEL-30 ;error if defines don't match tables
+ .errnz HIGH_LEVEL-31 ;error if defines don't match tables
+;;;;;;;;;;;;;;;;
+;
+; The following tables are generated from this information:
+;
+;KIRQL H/W pri CPL Vector Source Common use Name
+;----- ------- --- ------ ------ ---------- ----
+; 00 31
+; 01 31 APC_LEVEL
+; 02 31 DISPATCH_LEVEL
+; 03 31 WAKE_LEVEL
+; 04 31
+; 05 31
+; 06 31
+; 07 31
+; 08 22 (lo) 22 VB2+7 Local/IPI level 7 reserved
+; 09 21 21 VB2+6 Local/IPI level 6 reserved
+; 10 20 20 VB2+5 Local/IPI level 5 reserved
+; 11 19 19 VB0+7 EISA IRQ7 LPT1
+; 12 18 18 VB0+6 EISA IRQ6 Flpy
+; 13 17 17 VB0+5 EISA IRQ5 LPT2
+; 14 16 16 VB0+4 EISA IRQ4 COM1
+; 15 15 15 VB0+3 EISA IRQ3 COM2
+; 16 14 14 VB1+7 EISA IRQ15
+; 17 13 13 VB1+6 EISA IRQ14 AT disk
+; 18 12 12 VB1+5 EISA IRQ13 DMA chaining
+; 19 11 11 VB1+4 EISA IRQ12
+; 20 10 10 VB1+3 EISA IRQ11
+; 21 9 9 VB1+2 EISA IRQ10
+; 22 8 8 VB1+1 EISA IRQ9
+; 23 7 7 VB1+0 EISA IRQ8 RTC
+; 24 6 6 VB2+4 Local/IPI level 4 reserved
+; 25 5 5 VB0+1 EISA IRQ1 Kbd
+; 26 4 4 VB0+0 EISA IRQ0 8254
+; 27 3 3 VB2+3 Local/IPI level 3 Global IPI PROFILE_LEVEL
+; 28 2 2 VB2+2 Local/IPI level 2 Local Timer CLOCK2_LEVEL
+; 29 1 1 VB2+1 Local/IPI level 1 Slot IPI IPI_LEVEL
+; 30 1 POWER_LEVEL
+; 31 0 (high) 0 VB2+0 Spurious local interrupt HIGH_LEVEL
+;
+;;;;;;;;;;;;;;;;
+
+; CCHAR HalpIRQLtoCPL[36]; this array is used to get the value
+; for the hardware current priority level
+; (CPL) register from the KIRQL.
+ Public _HalpIRQLtoCPL
+_HalpIRQLtoCPL Label Byte ;don't know how to make this symbolic
+ db 31,31,31,31,31,31,31,31,22
+ db 21,20,19,18,17,16,15,14,13
+ db 12,11,10, 9, 8, 7, 6, 5, 4
+ db 3, 2, 1, 1, 0
+ db 0, 0, 0, 0 ;four extra levels for good luck
+
+; CCHAR HalpIRQLtoVector[36]; this array is used to get the interrupt
+; vector used for a given KIRQL, zero
+; means no vector is used for the KIRQL
+ Public _HalpIRQLtoVector
+_HalpIRQLtoVector Label Byte
+ db 0
+ db 0 ;APC_LEVEL
+ db 0 ;DISPATCH_LEVEL
+ db 0 ;WAKE_LEVEL
+ db 0
+ db 0
+ db 0
+ db 0
+ db PRIMARY_VECTOR_BASE+23
+ db PRIMARY_VECTOR_BASE+22
+ db PRIMARY_VECTOR_BASE+21
+ db PRIMARY_VECTOR_BASE+7
+ db PRIMARY_VECTOR_BASE+6
+ db PRIMARY_VECTOR_BASE+5
+ db PRIMARY_VECTOR_BASE+4
+ db PRIMARY_VECTOR_BASE+3
+ db PRIMARY_VECTOR_BASE+15
+ db PRIMARY_VECTOR_BASE+14
+ db PRIMARY_VECTOR_BASE+13
+ db PRIMARY_VECTOR_BASE+12
+ db PRIMARY_VECTOR_BASE+11
+ db PRIMARY_VECTOR_BASE+10
+ db PRIMARY_VECTOR_BASE+9
+ db PRIMARY_VECTOR_BASE+8
+ db PRIMARY_VECTOR_BASE+20
+ db PRIMARY_VECTOR_BASE+1
+ db PRIMARY_VECTOR_BASE
+ db PRIMARY_VECTOR_BASE+19 ;PROFILE_LEVEL
+ db PRIMARY_VECTOR_BASE+18 ;CLOCK2_LEVEL
+ db PRIMARY_VECTOR_BASE+17 ;IPI_LEVEL
+ db 0 ;POWER_LEVEL
+ db 0 ;prevent CPL 0 enable changes ;HIGH_LEVEL
+ db 0, 0, 0, 0 ;four extra levels for good luck
+
+; CCHAR HalpVectorToIRQL[24]; this array is used to obtain the
+; required IRQL from an interrupt
+; vector, it is indexed by
+; interrupt vector-PRIMARY_VECTOR_BASE
+ Public _HalpVectorToIRQL
+_HalpVectorToIRQL Label Byte
+ db PROFILE_LEVEL-1 ;IRQ0
+ db PROFILE_LEVEL-2 ;IRQ1
+ db HIGH_LEVEL ;IRQ2--cascade
+ db PROFILE_LEVEL-12 ;IRQ3
+ db PROFILE_LEVEL-13 ;IRQ4
+ db PROFILE_LEVEL-14 ;IRQ5
+ db PROFILE_LEVEL-15 ;IRQ6
+ db PROFILE_LEVEL-16 ;IRQ7
+
+ db PROFILE_LEVEL-4 ;IRQ8
+ db PROFILE_LEVEL-5 ;IRQ9
+ db PROFILE_LEVEL-6 ;IRQ10
+ db PROFILE_LEVEL-7 ;IRQ11
+ db PROFILE_LEVEL-8 ;IRQ12
+ db PROFILE_LEVEL-9 ;IRQ13
+ db PROFILE_LEVEL-10 ;IRQ14
+ db PROFILE_LEVEL-11 ;IRQ15
+
+ db HIGH_LEVEL ;Local/IPI level 0 (spurious)
+ db IPI_LEVEL ;Local/IPI level 1
+ db CLOCK2_LEVEL ;Local/IPI level 2
+ db PROFILE_LEVEL ;Local/IPI level 3
+ db PROFILE_LEVEL-3 ;Local/IPI level 4
+ db PROFILE_LEVEL-17 ;Local/IPI level 5
+ db PROFILE_LEVEL-18 ;Local/IPI level 6
+ db PROFILE_LEVEL-19 ;Local/IPI level 7
+
+ align 4
+;
+; The following table is a bit map of IRQLs that use ICU local interrpt ptr
+; (it must indicate those IRQLs corresponding to levels used in the ICU_LIPTR)
+;
+ public _HalpLocalInts
+_HalpLocalInts dd (1 shl CLOCK2_LEVEL)+(1 shl IPI_LEVEL)+(1 shl PROFILE_LEVEL)
+
+;
+; The following tables define the addresses of software interrupt routers
+;
+
+;
+; Use this table if there is NO machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 4
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 5
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 6
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 7
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 8
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 9
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 10
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 11
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 12
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 13
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 14
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 15
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 16
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 17
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 18
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 19
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 20
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 21
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 22
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 23
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 24
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 25
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 26
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 27
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 28
+ dd offset FLAT:_KIUnexpectedInterrupt ; irql 29
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+ db 3 ; SWIRR=8, so highest pending SW irql= 3
+ db 3 ; SWIRR=9, so highest pending SW irql= 3
+ db 3 ; SWIRR=A, so highest pending SW irql= 3
+ db 3 ; SWIRR=B, so highest pending SW irql= 3
+ db 3 ; SWIRR=C, so highest pending SW irql= 3
+ db 3 ; SWIRR=D, so highest pending SW irql= 3
+ db 3 ; SWIRR=E, so highest pending SW irql= 3
+ db 3 ; SWIRR=F, so highest pending SW irql= 3
+
+ db 4 ; SWIRR=10, so highest pending SW irql= 4
+ db 4 ; SWIRR=11, so highest pending SW irql= 4
+ db 4 ; SWIRR=12, so highest pending SW irql= 4
+ db 4 ; SWIRR=13, so highest pending SW irql= 4
+ db 4 ; SWIRR=14, so highest pending SW irql= 4
+ db 4 ; SWIRR=15, so highest pending SW irql= 4
+ db 4 ; SWIRR=16, so highest pending SW irql= 4
+ db 4 ; SWIRR=17, so highest pending SW irql= 4
+ db 4 ; SWIRR=18, so highest pending SW irql= 4
+ db 4 ; SWIRR=19, so highest pending SW irql= 4
+ db 4 ; SWIRR=1A, so highest pending SW irql= 4
+ db 4 ; SWIRR=1B, so highest pending SW irql= 4
+ db 4 ; SWIRR=1C, so highest pending SW irql= 4
+ db 4 ; SWIRR=1D, so highest pending SW irql= 4
+ db 4 ; SWIRR=1E, so highest pending SW irql= 4
+ db 4 ; SWIRR=1F, so highest pending SW irql= 4
+
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; FASTCALL
+; KfRaiseIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; The 'lazy irql' algorythm is used, which is to say that the
+; hardware interrupt priority level will not be programmed unless
+; a lower priority interrupt actually comes in.
+;
+; Arguments:
+;
+; (cl) NewIrql - the new irql to be raised to
+;
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+; equates for accessing arguments
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0, 0
+;
+; Note it is very important that we set the OldIrql AFTER we raised to
+; the new irql. Otherwise, if there is an interrupt comes in between and
+; the OldIrql is not a local variable, the caller will get wrong OldIrql.
+; The bottom line is the raising irql and returning old irql has to be
+; atomic to the caller.
+;
+ mov al, Fs:PcIrql ; (al) = Old Irql
+ mov Fs:PcIrql, cl ; set new irql
+
+if DBG
+ cmp al, cl ; old > new?
+ ja short Kri99 ; yes, go bugcheck
+
+ fstRET KfRaiseIrql
+
+cPublicFpo 2, 2
+Kri99:
+ push ecx ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr Fs:PcIrql,0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+ page ,132
+ subttl "Lower irql"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall KfLowerIrql ,1
+cPublicFpo 0,0
+
+ mov al, cl ; get new irql value
+ if DBG
+ cmp al, Fs:PcIrql
+ ja short KliBug
+ endif
+ pushfd
+ cli
+ mov Fs:PcIrql, al ;save new irql
+ cmp al, Fs:PcHal.pchHwIrql ;does hardware need reprogramming?
+ jb short @F ;jump if it does
+ popfd
+ fstRET KfLowerIrql
+
+@@: mov Fs:PcHal.pchHwIrql, al
+ and eax, 0FFh
+ mov al, _HalpIRQLtoCPL[eax]
+ mov dx, My+CpuPriortyLevel
+ out dx, ax ;set hardware level down
+
+@@: mov eax, Fs:PcIRR ;look for software interrupts
+ and eax, 1Fh
+ jz short @F ;jump if none
+
+ mov al, SWInterruptLookUpTable[eax] ;get swint's irql
+ cmp al, Fs:PcIrql ;high enough to do this int?
+ jbe short @F ;jump if not
+
+ call SWInterruptHandlerTable[eax*4]
+ jmp @B
+
+@@: popfd
+ fstRET KfLowerIrql
+
+ if DBG
+KliBug:
+ push eax ; new irql for debugging
+ push Fs:PcIrql ; old irql for debugging
+ mov byte ptr Fs:PcIrql,HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+ endif
+
+fstENDP KfLowerIrql
+
+cPublicProc _HalpEndSoftwareInterrupt,1
+cPublicFpo 1,0
+ mov ecx, [esp+4]
+ fstCall KfLowerIrql
+ stdRet _HalpEndSoftwareInterrupt
+stdENDP _HalpEndSoftwareInterrupt
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov ecx, DISPATCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+; The APIC TPR is used to block all lower-priority HW interrupts.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+
+ mov ecx, SYNCH_LEVEL
+ jmp @KfRaiseIrql
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+
+ page ,132
+ subttl "Get current irql"
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+ movzx eax, byte ptr fs:PcIrql ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+
+ ;
+ ; Raising to HIGH_LEVEL disables interrupts for the Wyse HAL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ mov al, _HalpIRQLtoCPL[HIGH_LEVEL]
+ mov dx, My+CpuPriortyLevel
+ out dx, ax
+ mov Fs:PcHal.pchHwIrql, HIGH_LEVEL
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine sends the 8259 PIC initialization commands and
+; masks all the interrupts on 8259s.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+
+ push esi ; save caller's esi
+ cli ; disable interrupt
+ lea esi, PICsInitializationString
+
+Hip00:
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ outsb ; output OCW1 (interrupt mask)
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+ pop esi ; restore caller's esi
+ sti ; enable interrupt
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halwyse7/i386/wymapint.c b/private/ntos/nthals/halwyse7/i386/wymapint.c
new file mode 100644
index 000000000..6a8d48717
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wymapint.c
@@ -0,0 +1,185 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ wymapint.c
+
+Abstract:
+
+ This module implements the HAL HalGetInterruptVector routine
+ for an x86 system
+
+Author:
+
+ John Vert (jvert) 17-Jul-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ John Fuller (o-johnf) 3-Apr-1992 Modifications for Wyse7000i
+--*/
+#include "halp.h"
+#if DBG
+ULONG
+ProcSub(
+ IN UCHAR RoutineNumber
+ );
+
+#define enproc(x) ProcSub(x)
+#define exproc(x) ProcSub((x)|0x80)
+
+#else //DBG
+
+#define enproc(x)
+#define exproc(x)
+
+#endif //DBG
+
+
+extern CCHAR HalpVectorToIRQL[];
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+
+ if (BusAddress.HighPart != 0 || *AddressSpace > 1) {
+ return (FALSE);
+ }
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+
+ return(TRUE);
+}
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ enproc(0x0F);
+
+ SystemVector = BusInterruptLevel + PRIMARY_VECTOR_BASE;
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ SystemVector > PRIMARY_VECTOR_BASE + HIGHEST_LEVEL_FOR_8259 ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = (KIRQL) HalpVectorToIRQL[BusInterruptLevel];
+
+ //
+ // On most MP systems the interrupt affinity is all processors.
+ //
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+
+ exproc(0x0F);
+ return SystemVector;
+}
+
diff --git a/private/ntos/nthals/halwyse7/i386/wynmi.asm b/private/ntos/nthals/halwyse7/i386/wynmi.asm
new file mode 100644
index 000000000..1bf044c0f
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wynmi.asm
@@ -0,0 +1,108 @@
+ title "Wyse7000i NMI Handler"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; wynmi.asm
+;
+; Abstract:
+;
+; Provides Wyse7000 x86 NMI handler
+;
+; Author:
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+.386p
+
+ .xlist
+include hal386.inc
+include i386\wy7000mp.inc
+include callconv.inc
+
+ extrn ReadMyCpuReg:NEAR
+ extrn WriteMyCpuReg:NEAR
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; NTSTATUS
+; HalHandleNMI(
+; IN OUT PVOID NmiInfo
+; )
+;
+; Routine Description:
+;
+; Called DURING an NMI. The system will BugCheck when an NMI occurs.
+; This function can return the proper bugcheck code, bugcheck itself,
+; or return success which will cause the system to iret from the nmi.
+;
+; This function is called during an NMI - no system services are available.
+; In addition, you don't want to touch any spinlock which is normally
+; used since we may have been interrupted while owning it, etc, etc...
+;
+;Arguments:
+;
+; NmiInfo - Pointer to NMI information structure (TBD)
+; - NULL means no NMI information structure was passed
+;
+;Return Value:
+;
+; BugCheck code
+;
+;--
+cPublicProc _HalHandleNMI,1
+
+ push BCU_STAT1
+ call ReadMyCpuReg
+
+ test al, NMISRC_EXT
+ jnz short WyseDebugNmiButtonPressed
+
+;
+; Decode other Wyse7000 NMI causes here...
+;
+ mov eax, MPFW_FuncTable ;point to firmware entry points
+
+ call dword ptr [eax][fnOS_Panic * 4] ;display NMI code to user
+
+ mov eax, 0f002h ; SYSTEM_FATAL_TRAP
+ stdRET _HalHandleNMI
+
+ public WyseDebugNmiButtonPressed
+WyseDebugNmiButtonPressed:
+;
+; Recessed NMI button on back of CPU card was pressed
+; Go to the debugger, then allow the system to continue
+;
+ int 3
+
+ and eax, NOT NMISRC_EXT
+ push eax
+ push BCU_STAT1
+ call WriteMyCpuReg
+;
+; Re-enable NMIs
+;
+ push BCU_ERRCTLR
+ call ReadMyCpuReg
+ or al, NMI_ENB ;this bit was cleared by the NMI
+ push eax
+ push BCU_ERRCTLR
+ call WriteMyCpuReg
+
+ xor eax, eax ; STATUS_SUCCESS
+ stdRET _HalHandleNMI
+
+stdENDP _HalHandleNMI
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halwyse7/i386/wyspin.asm b/private/ntos/nthals/halwyse7/i386/wyspin.asm
new file mode 100644
index 000000000..b9d320668
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wyspin.asm
@@ -0,0 +1,449 @@
+if NT_INST
+
+else
+ TITLE "Spin Locks"
+;++
+;
+; Copyright (c) 1989-1993 Microsoft Corporation
+; Copyright (c) 1993 Wyse Technology
+;
+; Module Name:
+;
+; wyspin.asm
+;
+; Abstract:
+;
+; This module implements stubbed x86 spinlock functions for
+; any HAL. Some HALs may implement these function directly
+; to minimize the amount of code required to perform a spinlock.
+; (ie, out Raise & Lower irql in the fall through path)
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 13 Dec 89
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; Ken Reneris (kenr) 22-Jan-1991
+; John Fuller (o-johnf) 19-Apr-1993 modify for Wyse 7000i
+; John Fuller (o-johnf) 31-Aug-1993 modify for Lazy IRQLs
+;--
+
+ PAGE
+
+.486p
+
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include hal386.inc
+include mac386.inc
+include i386\wy7000mp.inc
+
+ EXTRNP KfRaiseIrql,1,,FASTCALL
+ EXTRNP KfLowerIrql,1,,FASTCALL
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+ extrn SWInterruptLookUpTable:byte
+ extrn SWInterruptHandlerTable:dword
+ extrn _HalpIRQLtoCPL:byte
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ PAGE
+ SUBTTL "Acquire Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; Arguments:
+;
+; (ecx) SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+align 16
+cPublicFastCall KfAcquireSpinLock ,1
+
+ifdef NT_UP ; On up build just perform raiseirql
+
+ mov ecx, DISPATCH_LEVEL
+ jmp @KfRaiseIrql@4
+else
+cPublicFpo 0,0
+;
+; On a MP build we raise to dispatch_level
+; and then acquire the spinlock
+;
+
+;
+; Since on the Wyse 7000i the hardware priority of DISPATCH_LEVEL
+; is the same as for all levels below DISPATCH_LEVEL we just need
+; to update PcIrql to raise the level and don't need to touch the
+; hardware.
+;
+ mov al, fs:PcIrql ; get current irql
+
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ jbe short @F ; no, we're OK
+ push DISPATCH_LEVEL ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr fs:PcIrql,0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL>
+@@:
+endif
+
+ mov byte ptr fs:PcIrql, DISPATCH_LEVEL
+
+;
+; Attempt to assert the lock
+;
+
+sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
+ fstRET KfAcquireSpinLock
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sl20: SPIN_ON_SPINLOCK ecx,sl10
+
+endif
+
+fstENDP KfAcquireSpinLock
+
+
+ PAGE
+ SUBTTL "Acquire Synch Kernel Spin Lock"
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired,
+; any spin should occur at OldIrql)
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql - pointer to place old irql
+;
+;--
+
+align 16
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+;
+; Disable interrupts
+;
+
+sls10: cli
+
+;
+; Try to obtain spinlock. Use non-lock operation first
+;
+ TEST_SPINLOCK ecx,<short sls20>
+ ACQUIRE_SPINLOCK ecx,<short sls20>
+
+
+;
+; Got the lock, raise to SYNCH_LEVEL
+;
+
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+;
+; Enable interrupts and return
+;
+
+ sti
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+
+;
+; Lock is owned, spin till it looks free, then go get it again.
+;
+
+sls20: sti
+ SPIN_ON_SPINLOCK ecx,sls10
+
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; Arguments:
+;
+; (ecx) SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+
+ifndef NT_UP
+cPublicFpo 2,0
+ RELEASE_SPINLOCK ecx ; release it
+endif
+;
+; NOTE: The following code for the Wyse 7000i does not assume any knowelege
+; of either the current Irql or the new Irql. Therefore, the hardware
+; must be programmed.
+;
+ mov al, dl ; get new irql value
+ if DBG
+ cmp al, Fs:PcIrql
+ ja short KrsBug
+ endif
+ pushfd
+ cli
+ mov Fs:PcIrql, al ;save new irql
+ cmp al, Fs:PcHal.pchHwIrql ;does hardware need reprogramming?
+ jb short @F ;jump if it does
+ popfd
+ fstRET KfReleaseSpinLock
+
+@@: mov Fs:PcHal.pchHwIrql, al
+ and eax, 0FFh
+ mov dx, My+CpuPriortyLevel
+ mov al, _HalpIRQLtoCPL[eax]
+ out dx, ax ;set hardware level down
+
+@@: mov eax, Fs:PcIRR ;look for software interrupts
+ and eax, 1Fh
+ jz short @F ;jump if none
+
+ mov al, SWInterruptLookUpTable[eax] ;get swint's irql
+ cmp al, Fs:PcIrql ;high enough to do this int?
+ jbe short @F ;jump if not
+
+ call SWInterruptHandlerTable[eax*4]
+ jmp @B
+
+@@: popfd
+ fstRET KfReleaseSpinLock
+
+ if DBG
+KrsBug:
+ push eax ; new irql for debugging
+ push Fs:PcIrql ; old irql for debugging
+ mov byte ptr Fs:PcIrql,HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+ endif
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ push ecx ; Push FAST_MUTEX addr
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql
+
+ pop ecx ; (ecx) = Fast Mutex
+
+cPublicFpo 0,0
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,1
+ push ecx
+ push eax
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax
+ pop ecx
+
+cPublicFpo 0,0
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+
+;
+; Try to acquire
+;
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam25 ; Yes, abort
+
+cPublicFpo 0,1
+ push ecx ; Push FAST_MUTEX
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ mov ecx, [esp] ; Restore FAST_MUTEX
+ mov [esp], eax ; Save OldIrql
+
+ mov eax, 1 ; Value to compare against
+ mov edx, 0 ; Value to set
+ lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire
+ jnz short tam20 ; got it?
+
+cPublicFpo 0,0
+ pop edx ; (edx) = OldIrql
+ mov eax, 1 ; return TRUE
+ mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql
+ fstRet ExTryToAcquireFastMutex
+
+tam20: pop ecx ; (ecx) = OldIrql
+ fstCall KfLowerIrql ; restore OldIrql
+tam25: xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz @KfLowerIrql@4 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+ jmp @KfLowerIrql@4
+
+
+fstENDP ExReleaseFastMutex
+
+
+
+_TEXT ends
+
+ENDIF ; NT_INST
+
+ end
diff --git a/private/ntos/nthals/halwyse7/i386/wysproc.c b/private/ntos/nthals/halwyse7/i386/wysproc.c
new file mode 100644
index 000000000..3c8d2ff1e
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wysproc.c
@@ -0,0 +1,465 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Wyse Technology
+
+Module Name:
+
+ spsproc.c
+
+Abstract:
+
+ Wyse7000i Start Next Processor c code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Wyse MP 7000i
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+#include "halp.h"
+
+UCHAR HalName[] = "Wyse7000i MP HAL";
+
+#if DBG
+ULONG
+ProcSub(
+ IN UCHAR RoutineNumber
+ );
+
+#define enproc(x) ProcSub(x)
+#define exproc(x) ProcSub((x)|0x80)
+
+#else //DBG
+
+#define enproc(x)
+#define exproc(x)
+
+#endif //DBG
+
+
+PVOID
+HalpRemapVirtualAddress(
+ IN PVOID VirtualAddress,
+ IN PVOID PhysicalAddress,
+ IN BOOLEAN WriteThrough
+ );
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+VOID HalpInitOtherBuses (VOID);
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+ULONG __cdecl
+icu_sync_master (
+ ULONG i_sync,
+ UCHAR i_exp_cfg,
+ ULONG i_timeout
+ );
+
+
+#define LOW_MEMORY 0x000100000
+
+#define MAX_PT 8
+
+extern VOID StartPx_PMStub(VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#pragma alloc_text(INIT,HalpFreeTiledCR3)
+#pragma alloc_text(INIT,HalpMapCR3)
+#pragma alloc_text(INIT,HalpBuildTiledCR3)
+#endif
+
+UCHAR ProcessorsPresent; // bitmap by WWB slot of cpu's present
+PUCHAR MpLowStub; // pointer to low memory bootup stub
+PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
+PUCHAR MppIDT; // pointer to physical memory 0:0
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG paddress;
+ ULONG adjust;
+ PKPCR pPCR;
+
+ enproc(0x0B);
+
+
+ pPCR = KeGetPcr();
+
+ if (Phase == 0) {
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+ //
+ // Map system firmware to last 128Kb of memory
+ //
+
+ paddress = 0xFFFE0000; // address of last 128Kb of memory
+ for (adjust = 0x20000 / PAGE_SIZE; adjust; --adjust) {
+ HalpRemapVirtualAddress((PVOID) paddress, (PVOID) paddress, FALSE);
+ paddress += PAGE_SIZE;
+ }
+
+ //
+ // Are other processors installed and running?
+ //
+
+ if ( ProcessorsPresent ) { // any other cpu's installed?
+ adjust = icu_sync_master( 0x80, // SYNC_CONTINUE
+ ProcessorsPresent,// cpu's installed
+ 5 ); // 5*15ms timeout
+ ProcessorsPresent = (UCHAR) (adjust >> 8); // running cpu's
+ }
+
+ if ( !ProcessorsPresent ) {
+ exproc(0x0B);
+ return TRUE;
+ }
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress) {
+ ProcessorsPresent = 0; // can't start other cpu's
+ exproc(0x0B);
+ return TRUE;
+ }
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+ exproc(0x0B);
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1
+ //
+
+ ; // nothing to do
+
+ }
+ exproc(0x0B);
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ The registery is now enabled - time to report resources which are
+ used by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Eisa // Wyse7000 is an Eisa machines
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+}
+
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+ enproc(0x0C);
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ exproc(0x0C);
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+ enproc(0x0D);
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+ exproc(0x0D);
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ enproc(0x0E);
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+ exproc(0x0E);
+}
+
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other buses
+}
+
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halwyse7/i386/wysproca.asm b/private/ntos/nthals/halwyse7/i386/wysproca.asm
new file mode 100644
index 000000000..07ec04831
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wysproca.asm
@@ -0,0 +1,436 @@
+ title "MP primitives for Wyse 7000i"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; wysproca.asm
+;
+;Abstract:
+;
+; Wyse7000i Start Next Processor assemble code
+;
+; This module along with wysproc.c implement the code to start
+; off additional processors on the Wyse 7000i.
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+;Revision History:
+;
+; John Fuller (o-johnf) 7-Apr-1992 convert to Wyse 7000i
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\wy7000mp.inc
+ .list
+
+ EXTRNP _ExAllocatePool,2,IMPORT
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+
+ extrn _MppIDT:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+ extrn _ProcessorsPresent:BYTE
+
+
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_PB db processorstatelength dup (?)
+PxParamBlock ends
+
+BootPkg struc
+bpLength db 08h + 80h ;package length + sync flag
+bpDest db ? ;destination bitmap
+bpCode db 08h + 40h+ 80h ;boot_cpu_cmd + mpfw_pkg + cmd_pkg
+ db 0 ;reserved
+bpStartAddr dd ? ;start execution physical addr
+ ;executions starts in flat 32-bit
+ ;non-paged mode.
+BootPkg ends
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+ public _CpuBootPkg
+_CpuBootPkg BootPkg <>
+
+_DATA ends
+
+_TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; BOOLEAN
+; HalStartNextProcessor (
+; IN PLOADER_BLOCK pLoaderBlock,
+; IN PKPROCESSOR_STATE pProcessorState
+; )
+;
+; Routine Description:
+;
+; This routine is called by the kernel durning kernel initialization
+; to obtain more processors. It is called until no more processors
+; are available.
+;
+; If another processor exists this function is to initialize it to
+; the passed in processorstate structure, and return TRUE.
+;
+; If another processor does not exists, then a FALSE is returned.
+;
+; Also note that the loader block has been setup for the next processor.
+; The new processor logical thread number can be obtained from it, if
+; required.
+;
+; Arguments:
+; pLoaderBlock, - Loader block which has been intialized for the
+; next processor.
+;
+; pProcessorState - The processor state which is to be loaded into
+; the next processor.
+;
+;
+; Return Value:
+;
+; TRUE - ProcessorNumber was dispatched.
+; FALSE - A processor was not dispatched. no other processors exists.
+;
+;--
+
+pLoaderBlock equ dword ptr [ebp+8] ; zero based
+pProcessorState equ dword ptr [ebp+12]
+
+;
+; Local variables
+;
+
+PxFrame equ [ebp - size PxParamBlock]
+
+
+cPublicProc _HalStartNextProcessor ,2
+ enproc 8
+
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.SPx_flag, eax
+
+ cmp _ProcessorsPresent, al ; any processors left to start
+ je snp_exit ; exit FALSE
+
+ mov esi, OFFSET FLAT:StartPx_RMStub
+ mov ecx, StartPx_RMStub_Len
+ mov edi, _MpLowStub ; Copy RMStub to low memory
+ add edi, size PxParamBlock
+ rep movsb
+
+ lea edi, PxFrame.SPx_PB
+ mov esi, pProcessorState
+ mov ecx, processorstatelength ; Copy processorstate
+ rep movsb ; to PxFrame
+
+ stdCall _HalpBuildTiledCR3, <pProcessorState>
+
+ mov PxFrame.SPx_TiledCR3, eax
+ mov PxFrame.SPx_P0EBP, ebp
+
+ mov ecx, size PxParamBlock ; copy param block
+ lea esi, PxFrame ; to low memory stub
+ mov edi, _MpLowStub
+ mov eax, edi
+ rep movsb
+
+ add eax, size PxParamBlock
+ mov ebx, OFFSET FLAT:StartPx_RMStub
+ sub eax, ebx ; (eax) = adjusted pointer
+ mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
+ mov [eax.SPrxFlatCS], bx ; patch realmode stub with
+ mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
+
+ mov ebx, _MppIDT
+ add ebx, WarmResetVector
+
+ cli
+ push dword ptr [ebx] ; Save current vector
+ push ebx ; save ptr to it
+
+ mov eax, _MpLowStubPhysicalAddress
+ mov dword ptr [ebx], eax ; copy of PxFrame is here
+
+ add eax, size PxParamBlock ; calc start execution addr
+ mov _CpuBootPkg.bpStartAddr, eax ; put in start cpu package
+@@: movzx eax, _ProcessorsPresent ; get bitmap of processors
+ bsf ecx, eax ; look for next one
+ jz snp_exitA ; jump if blew it
+ btr eax, ecx ; clear its bit
+ xchg al, _ProcessorsPresent ; save new bitmap
+ xor al, _ProcessorsPresent ; leave only one bit
+ mov _CpuBootPkg.bpDest, al ; save as destination of cmd
+
+ mov ebx, eax
+ mov eax, MPFW_FuncTable
+ push ebx
+ push offset _CpuBootPkg
+ call dword ptr [eax][fnICU_Send_Mstr * 4]
+ add esp, 8
+ ror eax, 16
+ cmp al, 1
+ jne @B ; try another cpu if error
+
+@@:
+ cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's
+ jz @b ; info
+
+ mov eax, 1 ; return TRUE
+snp_exitA:
+ pop ebx ; get ptr to WarmResetVector
+ pop dword ptr [ebx] ; restore WarmResetVector
+
+ sti
+
+ push eax ; save true/false return
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+;; if DBG
+ %out generating stall code
+ EXTRNP _KeStallExecutionProcessor,1
+ push ecx
+ push edx
+
+ stdCall _KeStallExecutionProcessor, <75000> ; wait 75 milliseconds
+
+ pop edx
+ pop ecx
+;; endif ;DBG
+ ; CR3
+ pop eax ; restore return value
+
+snp_exit:
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+
+ exproc 8
+
+ stdRET _HalStartNextProcessor
+
+stdENDP _HalStartNextProcessor
+
+;++
+;
+; ULONG
+; icu_sync_master (
+; ULONG i_sync,
+; UCHAR i_exp_cfg,
+; ULONG i_timeout
+; );
+;
+; Routine Description:
+;
+; This routine is called by HalpInitMP during phase 0 to determine
+; if any other processors are running.
+;
+; This routine is just a stub to access the firmware roms.
+;
+; Arguments:
+;
+; i_sync specifies wether to wait or continue???
+;
+; i_exp_cfg specifies bitmap of WWB slot to try communicating with
+;
+; i_timeout specifies maximum time to wait for response
+;
+; Return Value:
+;
+; eax[0:7] remaining length of command
+;
+; eax[8:15] bitmap of WWB slots responding (running)
+;
+; eax[16:23] return code, 1=Ok, 2=timeout
+;
+; eax[24:31] reserved
+;
+;--
+public _icu_sync_master
+_icu_sync_master proc
+ mov eax, MPFW_FuncTable
+ jmp dword ptr [eax][fnICU_Sync_Mstr * 4]
+_icu_sync_master endp
+;_TEXT ends ; end 32 bit code
+
+
+;_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+ align 4
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in 32-bit protected mode
+; with paging disabled and is sent to a copy of this function which has
+; been copied into low memory. (below 1m).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub ,0
+ cli
+
+ mov edi, WarmResetVector
+ mov edi, cs:[edi] ; point to processor block
+ ; load the GDT
+ lgdt fword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrGdtr
+
+ ; load the IDT
+ lidt fword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrIdtr
+
+ mov eax, cs:[edi].SPx_TiledCR3
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[edi].SPx_P0EBP
+ mov ecx, dword ptr cs:[edi].SPx_PB.PsContextFrame.CsSegDs
+ mov ebx, dword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrCr3
+ mov eax, dword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrCr0
+
+ mov cr0, eax ; into prot mode
+
+ db 0eah ; reload cs:eip
+SPrxPMStub dd 0
+SPrxFlatCS dw 0
+
+StartPx_RMStub_Len equ $ - StartPx_RMStub
+stdENDP StartPx_RMStub
+
+
+;_TEXT16 ends ; End 16 bit code
+
+;_TEXT SEGMENT ; Start 32 bit code
+
+
+;++
+;
+; VOID
+; StartPx_PMStub
+;
+; Routine Description:
+;
+; This function completes the processor's state loading, and signals
+; the requesting processor that the state has been loaded.
+;
+; Arguments:
+; ebx - requested CR3 for this processors_state
+; cx - requested ds for this processors_state
+; ebp - EBP of P0
+;
+; Return Value:
+; does not return - completes the loading of the processors_state
+;
+;--
+ align 16 ; to make sure we don't cross a page boundry
+ ; before reloading CR3
+
+cPublicProc _StartPx_PMStub ,0
+
+ ; process is now in the load image copy of this function.
+ ; (ie, it's not the low memory copy)
+
+ mov cr3, ebx ; get real CR3
+ mov ds, cx ; set real ds
+
+ lea esi, PxFrame.SPx_PB.PsSpecialRegisters
+
+ lldt word ptr ds:[esi].SrLdtr ; load ldtr
+ ltr word ptr ds:[esi].SrTr ; load tss
+
+ lea edi, PxFrame.SPx_PB.PsContextFrame
+ mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
+ mov fs, word ptr ds:[edi].CsSegFs
+ mov gs, word ptr ds:[edi].CsSegGs
+ mov ss, word ptr ds:[edi].CsSegSs
+
+ add esi, SrKernelDr0
+ .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
+ .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
+ .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
+ .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
+ .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
+ lodsd
+ mov dr0, eax ; load dr0-dr7
+ lodsd
+ mov dr1, eax
+ lodsd
+ mov dr2, eax
+ lodsd
+ mov dr3, eax
+ lodsd
+ mov dr6, eax
+ lodsd
+ mov dr7, eax
+
+ mov esp, dword ptr ds:[edi].CsEsp
+ mov esi, dword ptr ds:[edi].CsEsi
+ mov ecx, dword ptr ds:[edi].CsEcx
+
+ push dword ptr ds:[edi].CsEflags
+ popfd ; load eflags
+
+ push dword ptr ds:[edi].CsEip ; make a copy of remaining
+ push dword ptr ds:[edi].CsEax ; registers which need
+ push dword ptr ds:[edi].CsEbx ; loaded
+ push dword ptr ds:[edi].CsEdx
+ push dword ptr ds:[edi].CsEdi
+ push dword ptr ds:[edi].CsEbp
+
+ ; eax, ebx, edx are still free
+
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with it's data
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ exproc 0
+ stdRET _StartPx_PMStub ; Set eip
+
+stdENDP _StartPx_PMStub
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/halwyse7/i386/wyswint.asm b/private/ntos/nthals/halwyse7/i386/wyswint.asm
new file mode 100644
index 000000000..2e0fd4201
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wyswint.asm
@@ -0,0 +1,336 @@
+ title "Software Interrupts"
+
+;++
+;
+; Copyright (c) 1992-1993 Microsoft Corporation
+; Copyright (c) 1993 Wyse Technology
+;
+; Module Name:
+;
+; wyswint.asm
+;
+; Abstract:
+;
+; This module implements the software interrupt handlers
+; for x86 machines
+;
+; Author:
+;
+; John Vert (jvert) 2-Jan-1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+; John Fuller (o-johnf) 31-Aug-1993 mods to support Wyse Lazy IRQLs
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include i386\wy7000mp.inc
+ .list
+
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ extrn SWInterruptHandlerTable:dword
+ extrn SWInterruptLookUpTable:byte
+ifdef IRQL_METRICS
+ extrn HalApcSoftwareIntCount:dword
+ extrn HalDpcSoftwareIntCount:dword
+endif
+
+_TEXT$02 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Request Software Interrupt"
+
+;++
+;
+; VOID
+; FASTCALL
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to request a software interrupt to the
+; system. Also, this routine checks to see if any software
+; interrupt should be generated.
+; The following condition will cause software interrupt to
+; be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; ASSUMPTIONS:
+; 1. This routine is only called for IRQL's 1-4.
+; 2. No bits above bit 4 can be set in PcIRR.
+; 3. All hardware interrups are above IRQL 4.
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+cPublicFpo 0, 1
+
+ mov eax,1
+ shl eax, cl ; convert to mask
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+ or PCR[PcIRR], eax ; set the request bit
+
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ and eax, 3 ; mask off pending HW interrupts
+ jz short KsiExit ; exit is none for now
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, PCR[PcIrql] ; Is highest SW int level > irql?
+ jbe KsiExit ; No, jmp ksiexit
+ call SWInterruptHandlerTable[eax*4] ; yes, simulate interrupt
+ ; to the appropriate handler
+@@: popfd ; restore original interrupt mode
+ fstRET HalRequestSoftwareInterrupt
+
+KsiExit:
+ cmp cl, PCR[PcHal.pchHwIrql]; compare with Hardware Irql
+ jbe @B ; jump if hardware already above us
+ mov PCR[PcHal.pchHwIrql], cl; ensure KeLowerIrql checks PcIRR
+ popfd ; restore original interrupt mode
+ fstRET HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+ page ,132
+ subttl "Clear Software Interrupt"
+
+;++
+;
+; VOID
+; HalClearSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to clear a possible pending software interrupt.
+; Support for this function is optional, and allows the kernel to
+; reduce the number of spurious software interrupts it receives/
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalClearSoftwareInterrupt ,1
+cPublicFpo 0, 0
+
+ mov eax,1
+ shl eax, cl ; convert to mask
+
+ not eax
+ and PCR[PcIRR], eax ; clear pending irr bit
+
+ fstRET HalClearSoftwareInterrupt
+fstENDP HalClearSoftwareInterrupt
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+ align dword
+ public _HalpDispatchInterrupt
+_HalpDispatchInterrupt proc
+ifdef IRQL_METRICS
+ lock inc HalDpcSoftwareIntCount
+endif
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public _HalpDispatchInterrupt2ndEntry
+_HalpDispatchInterrupt2ndEntry:
+
+; Save previous IRQL and set new priority level
+
+ push PCR[PcIrql] ; save previous IRQL
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
+ btr dword ptr PCR[PcIRR], DISPATCH_LEVEL; clear the pending bit in IRR
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; Go do Dispatch Interrupt processing
+;
+ stdCall _KiDispatchInterrupt
+
+;
+; Do interrupt exit processing
+;
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+_HalpDispatchInterrupt endp
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+ align dword
+ public _HalpApcInterrupt
+_HalpApcInterrupt proc
+ifdef IRQL_METRICS
+ lock inc HalApcSoftwareIntCount
+endif
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state in trap frame
+;
+ ENTER_INTERRUPT hapc_a, hapc_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+
+ public _HalpApcInterrupt2ndEntry
+_HalpApcInterrupt2ndEntry:
+
+;
+; Save previous IRQL and set new priority level
+;
+
+ push PCR[PcIrql] ; save previous Irql
+ mov byte ptr PCR[PcIrql], APC_LEVEL ; set new Irql
+ btr dword ptr PCR[PcIRR], APC_LEVEL ; dismiss pending APC
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; call the APC delivery routine.
+;
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
+ jz short @f
+
+ or eax, MODE_MASK ; If v86 frame, then set user_mode
+@@:
+
+;
+; call APC deliver routine
+; Previous mode
+; Null exception frame
+; Trap frame
+
+ stdCall _KiDeliverApc, <eax, 0,ebp>
+
+;
+;
+; Do interrupt exit processing
+;
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+_HalpApcInterrupt endp
+
+_TEXT$02 ends
+ end
diff --git a/private/ntos/nthals/halwyse7/i386/wysysint.asm b/private/ntos/nthals/halwyse7/i386/wysysint.asm
new file mode 100644
index 000000000..ebd2feaec
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/wysysint.asm
@@ -0,0 +1,615 @@
+;++
+;
+;Copyright (c) 1991-1993 Microsoft Corporation
+;Copyright (c) 1992, 1993 Wyse Technology
+;
+;Module Name:
+;
+; wysysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts, for the MP Wyse7000i implementation
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\wy7000mp.inc
+ .list
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ extrn WriteMyCpuReg:NEAR
+ EXTRNP _KeLowerIrql,1
+ extrn _HalpVectorToIRQL:BYTE
+ extrn _HalpIRQLtoVector:BYTE
+ extrn _HalpIRQLtoCPL:BYTE
+ extrn _HalpLocalInts:DWORD
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; Macros to Read/Write/Reset CMOS to initialize RTC
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+; NOTE: IODelay's are not needed on EISA machines.
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+; IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+; IODelay ; I/O DELAY
+ENDM
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+align dword
+
+ public _HalpICUlock ;spinlock for rebroadcasting timer & global IPI's
+_HalpICUlock dd 0
+ public _Halp8259Lock ;spinlock for accessing 8259 mask registers
+_Halp8259Lock dd 0
+ public _i8259_IMR ;global 8259 interrupt mask
+_i8259_IMR dd not (1 shl PIC_SLAVE_IRQ)
+ public _i8259_ISR ;global 8259 interrupts in services
+_i8259_ISR dd 0
+ public _Halp8259Counts ;count of cpu's attached to each 8259 interrupt
+_Halp8259Counts db 16 dup(0)
+
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irq 0
+ dd offset FLAT:HalpDismissNormal ; irq 1
+ dd offset FLAT:HalpDismissSpurious ; irq 2
+ dd offset FLAT:HalpDismissNormal ; irq 3
+ dd offset FLAT:HalpDismissNormal ; irq 4
+ dd offset FLAT:HalpDismissNormal ; irq 5
+ dd offset FLAT:HalpDismissNormal ; irq 6
+ dd offset FLAT:HalpDismissIrq07 ; irq 7
+ dd offset FLAT:HalpDismissNormal ; irq 8
+ dd offset FLAT:HalpDismissNormal ; irq 9
+ dd offset FLAT:HalpDismissNormal ; irq A
+ dd offset FLAT:HalpDismissNormal ; irq B
+ dd offset FLAT:HalpDismissNormal ; irq C
+ dd offset FLAT:HalpDismissNormal ; irq D
+ dd offset FLAT:HalpDismissNormal ; irq E
+ dd offset FLAT:HalpDismissIrq0f ; irq F
+ dd offset FLAT:HalpDismissSpurious ; irq 10
+ dd offset FLAT:HalpDismissIPIlevel ; irq 11
+ dd offset FLAT:HalpDismissIPIlevel ; irq 12
+ dd offset FLAT:HalpDismissIPIlevel ; irq 13
+ dd offset FLAT:HalpDismissIPIlevel ; irq 14
+ dd offset FLAT:HalpDismissIPIlevel ; irq 15
+ dd offset FLAT:HalpDismissIPIlevel ; irq 16
+ dd offset FLAT:HalpDismissIPIlevel ; irq 17
+ dd offset FLAT:HalpDismissSpurious ; irq 18
+ dd offset FLAT:HalpDismissSpurious ; irq 19
+ dd offset FLAT:HalpDismissSpurious ; irq 1A
+ dd offset FLAT:HalpDismissSpurious ; irq 1B
+ dd offset FLAT:HalpDismissSpurious ; irq 1C
+ dd offset FLAT:HalpDismissSpurious ; irq 1D
+ dd offset FLAT:HalpDismissSpurious ; irq 1E
+ dd offset FLAT:HalpDismissSpurious ; irq 1F
+ dd offset FLAT:HalpDismissSpurious ; irq 20
+ dd offset FLAT:HalpDismissSpurious ; irq 21
+ dd offset FLAT:HalpDismissSpurious ; irq 22
+ dd offset FLAT:HalpDismissSpurious ; irq 23
+
+_DATA ENDS
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4+8]
+HbsiVector equ byte ptr [esp+8+8]
+HbsiOldIrql equ dword ptr [esp+12+8]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+ push ecx
+ push edx
+ mov ebx, (-PRIMARY_VECTOR_BASE) and 0FFh
+ add bl, HbsiVector ; (ebx) = 8259 IRQ #
+if DBG
+ cmp ebx, 23h
+ jbe hbsi00
+ int 3
+hbsi00:
+
+endif
+ xor ecx, ecx
+ mov cl, _HalpVectorToIRQL[ebx] ; get h/w Irql of interrupt
+ cmp cl, Fs:PcIrql ; int after raise Irql?
+ jbe short HalpIntBelowIRQL ; jump if it is
+ jmp HalpSpecialDismissTable[ebx*4]
+
+HalpIntBelowIRQL:
+ xor eax, eax
+ mov al, Fs:PcIrql
+ mov dx, My+CpuPriortyLevel
+ mov Fs:PcHal.pchHwIrql, al
+ mov al, _HalpIRQLtoCPL[eax]
+ out dx, ax
+ bt _HalpLocalInts, ecx ; EISA or Local interrupt?
+ jnc short HalpRebroadcastEISAint ; jump if EISA interrupt
+
+ cmp cl, IPI_LEVEL ; IPI's are easy
+ jne HalpEmulateClockOrGlobal ; jmp if not an IPI
+
+ mov cl, byte ptr fs:PcHal.pchPrSlot ; IPIs get resent to
+ or cl, ICU_IPI_SLOT ; the current processor
+ jmp short HalpRebroadcastIPI
+
+HalpRebroadcastEISAint:
+ mov cl, _HalpIRQLtoCPL[ecx] ; get hw interrupt level
+ add cl, ICU_XMT_INT_SND ; make ICU command
+HalpRebroadcastIPI:
+ mov dx, My+CpuIntCmd ; point to ICU command register
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz short @B ; wait for ICU not busy
+ xchg eax, ecx ; get ICU command
+ out dx, ax ; rebroadcast EISA interrupt
+ jmp HalpDismissSpurious ; clear ICU in service bit
+
+HalpEmulateClockOrGlobal:
+; The following code resends a clock or global interrupt by mapping the
+; appropriate ICU_LIPTR value to zero and then broadcasting the level.
+; This must be spinlocked since it will not work it two CPUs try it at
+; the same time.
+
+ cmp cl, CLOCK2_LEVEL ; is this CLOCK or GLOBAL?
+ mov cl, _HalpIRQLtoCPL[ecx] ; (get this int's level #)
+ mov ax, not lipTimer ; (assume timer interrupt)
+ je short @F ; jump if timer interrupt
+ mov ax, not (lipGlobal+lipSerial) ; it is global interrupt
+@@: and ax, fs:word ptr PcHal.pchCurLiptr
+ push eax ; save temp LIPTR
+
+ lea eax, _HalpICUlock ; Serialize access to
+Hec10: ACQUIRE_SPINLOCK eax, HecSpin ; remappings
+
+ push ICU_LIPTR ; Point global interrupt to
+ call WriteMyCpuReg ; make it a clock interrupt
+
+ mov dx, My+CpuIntCmd ; wait for ICU not busy
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz short @B
+
+ xchg eax, ecx ; get int level back
+ add al, ICU_XMT_INT_SND ; make send level command
+ out dx, ax ; to make to clock interrupt
+
+@@: in ax, dx ; wait for ICU not busy
+ test eax, ICU_CMD_BUSY ; before resetting GlobalIpi
+ jnz short @B ; value
+
+ push fs:PcHal.pchCurLiptr
+ push ICU_LIPTR ; Put GlobalIpi back to
+ call WriteMyCpuReg ; normal setting
+
+ lea eax, _HalpICUlock
+ RELEASE_SPINLOCK eax
+
+ jmp HalpDismissSpurious
+
+HecSpin:
+ SPIN_ON_SPINLOCK eax, Hec10
+
+
+HalpDismissSpinF:
+ SPIN_ON_SPINLOCK eax, Hbsi10
+
+ align dword
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ lea eax, _Halp8259Lock
+Hbsi10: ACQUIRE_SPINLOCK eax, HalpDismissSpinF
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+; IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz HalpDismissNormal2 ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ lea eax, _Halp8259Lock
+ RELEASE_SPINLOCK eax
+
+HalpDismissSpurious:
+ mov dx, My+CpuIntCmd
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz @B
+ mov al, ICU_CLR_INSERV1
+ out dx, ax
+ xor eax, eax ; return FALSE
+; sti
+ pop edx
+ pop ecx
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissSpin:
+ SPIN_ON_SPINLOCK eax, HalpDismissNormal
+
+HalpDismissSpin7:
+ SPIN_ON_SPINLOCK eax, Hbsi20
+
+ align dword
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ lea eax, _Halp8259Lock
+Hbsi20: ACQUIRE_SPINLOCK eax, HalpDismissSpin7
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+; IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal2 ; No, so this is a spurious int
+
+ lea eax, _Halp8259Lock
+ RELEASE_SPINLOCK eax
+ jmp HalpDismissSpurious
+
+ align dword
+HalpDismissNormal:
+ lea eax, _Halp8259Lock
+ ACQUIRE_SPINLOCK eax, HalpDismissSpin
+
+ align dword
+HalpDismissNormal2:
+ mov eax, _i8259_IMR ;get current 8259 masks
+ bts _i8259_ISR, ebx ;mark this int as in service
+ or eax, _i8259_ISR ;also mask in service ints
+ SET_8259_MASK ;tell 8259's the news
+ lea eax, _Halp8259Lock
+ RELEASE_SPINLOCK eax
+
+;
+; Dismiss interrupt. Current interrupt is already masked off.
+;
+ mov eax, ebx ; (eax) = IRQ #
+ cmp eax, 8 ; EOI to master or slave?
+
+ jae short Hbsi100 ; EIO to both master and slave
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ jmp short Hbsi200 ; IO delay
+
+Hbsi100:
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+Hbsi200:
+ PIC1DELAY
+
+HalpDismissIPIlevel:
+
+ mov bl, HbsiIrql
+ mov dx, My+CpuPriortyLevel
+ mov al, _HalpIRQLtoCPL[ebx]
+ mov cl, Fs:PcIrql ; (cl) = Old Irql
+ out dx, ax
+ mov Fs:PcIrql, bl ; set new irql
+ mov edx, HbsiOldIrql ; get addr to store old irql
+ mov Fs:PcHal.pchHwIrql, bl
+ mov [edx], cl ; save old irql in the return variable
+
+ifdef IRQL_METRICS
+ lock inc HalRaiseIrqlCount
+endif
+
+ mov dx, My+CpuIntCmd
+@@: in ax, dx
+ test eax, ICU_CMD_BUSY
+ jnz @B
+ mov al, ICU_CLR_INSERV1 ; clear this processor's in service bit
+ out dx, ax
+
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ pop edx
+ pop ecx
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;BOOLEAN
+;HalEndSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to complete any interrupt h/w processing and to
+; lower the IRQL to the original value.
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+
+cPublicProc _HalEndSystemInterrupt ,2
+ movzx ecx, byte ptr [esp+8]
+
+ ; change stack to be for KeLowerIrql
+ pop eax ;(eax) = ret addr
+ mov edx, [esp] ;(edx) = new irql
+ mov [esp], eax
+ mov [esp+4], edx
+
+ sub cl, PRIMARY_VECTOR_BASE
+ cmp cl, 16
+ jnb _KeLowerIrql@4 ;jump if not 8259 interrupt
+ pushfd
+ lea eax, _Halp8259Lock
+HesiAquireLock:
+ cli
+ ACQUIRE_SPINLOCK eax, HesiSpin
+ mov eax, _i8259_IMR
+ btr _i8259_ISR, ecx
+ or eax, _i8259_ISR
+ SET_8259_MASK
+ lea eax, _Halp8259Lock
+ RELEASE_SPINLOCK eax
+ popfd
+ jmp _KeLowerIrql@4
+
+HesiSpin:
+ popfd
+ pushfd
+ SPIN_ON_SPINLOCK eax, HesiAquireLock
+stdENDP _HalEndSystemInterrupt
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt ,2
+ enproc 9
+;
+
+ push ebx
+ movzx ebx, byte ptr [esp+12] ;get IRQL
+ movzx ecx, _HalpIRQLtoVector[ebx]
+ or ecx, ecx
+ jz DisSysIntExit ;jump if not H/W interrupt
+ sub cl, PRIMARY_VECTOR_BASE
+ movzx eax, _HalpIRQLtoCPL[ebx]
+ cli
+ bts fs:PcIDR, eax ;disable int locally
+ jc DisSysIntExit ;jump if already disabled
+ push fs:PcIDR
+ push ICU_IMR0 ;write low interrupt masks
+ call WriteMyCpuReg
+ shr eax, 16
+ out dx, ax ;shortcut to high interrupt masks
+ cmp cl, 16 ;is this an 8259 interrupt?
+ jnb DisSysIntExit ;jump if not
+ lea eax, _Halp8259Lock
+DisSysIntAquire:
+ ACQUIRE_SPINLOCK eax, DisSysIntSpin
+ dec _Halp8259Counts[ecx]
+ jnz short DisSysIntRelease
+ mov eax, _i8259_ISR
+ bts _i8259_IMR, ecx
+ or eax, _i8259_IMR
+ SET_8259_MASK
+
+ lea eax, _Halp8259Lock
+DisSysIntRelease:
+ RELEASE_SPINLOCK eax
+
+DisSysIntExit:
+ exproc 9
+ sti
+ pop ebx
+ stdRET _HalDisableSystemInterrupt
+
+DisSysIntSpin:
+ SPIN_ON_SPINLOCK eax, DisSysIntAquire
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt ,3
+ enproc 0Ah
+
+ push ebx
+ movzx ebx, byte ptr [esp+12] ;get IRQL
+ movzx ecx, _HalpIRQLtoVector[ebx]
+ or ecx, ecx
+ jz EnbSysIntError ;jump if not H/W interrupt
+ sub cl, PRIMARY_VECTOR_BASE
+ movzx eax, _HalpIRQLtoCPL[ebx]
+ cli
+ btr fs:PcIDR, eax ;enable int locally
+ jnc EnbSysIntExit ;jump if already enabled
+ push fs:PcIDR
+ push ICU_IMR0
+ call WriteMyCpuReg ;write low interrupt masks
+ shr eax, 16
+ out dx, ax ;shortcut to high interrupt masks
+ cmp cl, 16 ;is this an 8259 interrupt?
+ jnb EnbSysIntExit ;jump if not
+ lea eax, _Halp8259Lock
+EnbSysIntAquire:
+ ACQUIRE_SPINLOCK eax, EnbSysIntSpin
+ inc _Halp8259Counts[ecx]
+ cmp _Halp8259Counts[ecx], 1
+ jnz short EnbSysIntRelease
+ mov eax, _i8259_ISR
+ btr _i8259_IMR, ecx
+ or eax, _i8259_IMR
+ SET_8259_MASK
+
+ lea eax, _Halp8259Lock
+EnbSysIntRelease:
+ RELEASE_SPINLOCK eax
+
+EnbSysIntExit:
+ exproc 0Ah
+ sti
+ pop ebx
+ mov eax, 1
+ stdRET _HalEnableSystemInterrupt
+
+EnbSysIntError:
+ if DBG
+ int 3
+ endif
+ exproc 0Ah
+ sti
+ pop ebx
+ xor eax,eax
+ stdRET _HalEnableSystemInterrupt
+
+EnbSysIntSpin:
+ SPIN_ON_SPINLOCK eax, EnbSysIntAquire
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/halwyse7/i386/xxbiosa.asm b/private/ntos/nthals/halwyse7/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxbiosa.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxbiosa.asm
diff --git a/private/ntos/nthals/halwyse7/i386/xxbiosc.c b/private/ntos/nthals/halwyse7/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxbiosc.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxbiosc.c"
diff --git a/private/ntos/nthals/halwyse7/i386/xxdisp.c b/private/ntos/nthals/halwyse7/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxdisp.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxdisp.c"
diff --git a/private/ntos/nthals/halwyse7/i386/xxflshbf.c b/private/ntos/nthals/halwyse7/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxflshbf.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxflshbf.c"
diff --git a/private/ntos/nthals/halwyse7/i386/xxioacc.asm b/private/ntos/nthals/halwyse7/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxioacc.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\xxioacc.asm
diff --git a/private/ntos/nthals/halwyse7/i386/xxkdsup.c b/private/ntos/nthals/halwyse7/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxkdsup.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxkdsup.c"
diff --git a/private/ntos/nthals/halwyse7/i386/xxmemory.c b/private/ntos/nthals/halwyse7/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxmemory.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxmemory.c"
diff --git a/private/ntos/nthals/halwyse7/i386/xxstubs.c b/private/ntos/nthals/halwyse7/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxstubs.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxstubs.c"
diff --git a/private/ntos/nthals/halwyse7/i386/xxtime.c b/private/ntos/nthals/halwyse7/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"
diff --git a/private/ntos/nthals/halwyse7/makefile b/private/ntos/nthals/halwyse7/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halwyse7/makefile.inc b/private/ntos/nthals/halwyse7/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halwyse7/sources b/private/ntos/nthals/halwyse7/sources
new file mode 100644
index 000000000..1b2a1406b
--- /dev/null
+++ b/private/ntos/nthals/halwyse7/sources
@@ -0,0 +1,96 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halwyse7
+TARGETPATH=\nt\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+NT_UP=0
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+SOURCES=
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixdat.c \
+ i386\ixisabus.c \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixinfo.c \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\ixphwsup.c \
+ i386\ixreboot.c \
+ i386\ixthunk.c \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c \
+ i386\wyclock.asm \
+ i386\wyhal.c \
+ i386\wyipi.asm \
+ i386\wyirql.asm \
+ i386\wymapint.c \
+ i386\wynmi.asm \
+ i386\wyspin.asm \
+ i386\wysproc.c \
+ i386\wysproca.asm \
+ i386\wyswint.asm \
+ i386\wysysint.asm
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halwyse7.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halx86/drivesup.c b/private/ntos/nthals/halx86/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halx86/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halx86/hal.rc b/private/ntos/nthals/halx86/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halx86/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halx86/hal.src b/private/ntos/nthals/halx86/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halx86/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halx86/i386/halnls.h b/private/ntos/nthals/halx86/i386/halnls.h
new file mode 100644
index 000000000..56dc7d557
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/halnls.h
@@ -0,0 +1,29 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ halnls.h
+
+Abstract:
+
+ Strings which are used in the HAL
+
+ English
+
+--*/
+
+#define MSG_HARDWARE_ERROR1 "\n*** Hardware Malfunction\n\n"
+#define MSG_HARDWARE_ERROR2 "Call your hardware vendor for support\n\n"
+#define MSG_HALT "\n*** The system has halted ***\n"
+#define MSG_NMI_PARITY "NMI: Parity Check / Memory Parity Error\n"
+#define MSG_NMI_CHANNEL_CHECK "NMI: Channel Check / IOCHK\n"
+#define MSG_NMI_FAIL_SAFE "NMI: Fail-safe timer\n"
+#define MSG_NMI_BUS_TIMEOUT "NMI: Bus Timeout\n"
+#define MSG_NMI_SOFTWARE_NMI "NMI: Software NMI generated\n"
+#define MSG_NMI_EISA_IOCHKERR "NMI: Eisa IOCHKERR board %\n"
+
+#define MSG_DEBUG_ENABLE "Kernel Debugger Using: COM%x (Port 0x%x, Baud Rate %d)\n"
+#define MSG_DEBUG_9600 "Switching debugger to 9600 baud\n"
+#define MSG_MCE_PENDING "Machine Check Exception pending, MCE exceptions not enabled\n"
diff --git a/private/ntos/nthals/halx86/i386/halp.h b/private/ntos/nthals/halx86/i386/halp.h
new file mode 100644
index 000000000..fb3fed047
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/halp.h
@@ -0,0 +1,428 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces, defines and structures.
+
+Author:
+
+ John Vert (jvert) 11-Feb-92
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "hal.h"
+#include "halnls.h"
+
+#ifndef _HALI_
+#include "..\inc\hali.h"
+#endif
+
+#ifdef RtlMoveMemory
+#undef RtlMoveMemory
+#undef RtlCopyMemory
+#undef RtlFillMemory
+#undef RtlZeroMemory
+
+#define RtlCopyMemory(Destination,Source,Length) RtlMoveMemory((Destination),(Source),(Length))
+VOID
+RtlMoveMemory (
+ PVOID Destination,
+ CONST VOID *Source,
+ ULONG Length
+ );
+
+VOID
+RtlFillMemory (
+ PVOID Destination,
+ ULONG Length,
+ UCHAR Fill
+ );
+
+VOID
+RtlZeroMemory (
+ PVOID Destination,
+ ULONG Length
+ );
+
+#endif
+
+#if MCA
+
+#include "ixmca.h"
+
+#else
+
+#include "ixisa.h"
+
+#endif
+
+#include "ix8259.inc"
+
+//
+// Define map register translation entry structure.
+//
+
+typedef struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+// In this system, the map registers are translation entries which point to
+// map buffers. Map buffers are physically contiguous and have physical memory
+// addresses less than 0x01000000. All of the map registers are allocated
+// initialially; however, the map buffers are allocated base in the number of
+// adapters which are allocated.
+//
+// If the master adapter is NULL in the adapter object then device does not
+// require any map registers.
+//
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern POBJECT_TYPE *IoAdapterObjectType;
+
+extern BOOLEAN LessThan16Mb;
+
+extern BOOLEAN HalpEisaDma;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+extern ULONG HalpCpuType;
+extern UCHAR HalpSerialLen;
+extern UCHAR HalpSerialNumber[];
+
+//
+// The following macros are taken from mm\i386\mi386.h. We need them here
+// so the HAL can map its own memory before memory-management has been
+// initialized, or during a BugCheck.
+//
+
+#define PTE_BASE ((ULONG)0xC0000000)
+#define PDE_BASE ((ULONG)0xC0300000)
+
+//
+// MiGetPdeAddress returns the address of the PDE which maps the
+// given virtual address.
+//
+
+#define MiGetPdeAddress(va) ((PHARDWARE_PTE)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
+
+//
+// MiGetPteAddress returns the address of the PTE which maps the
+// given virtual address.
+//
+
+#define MiGetPteAddress(va) ((PHARDWARE_PTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
+
+//
+// Resource usage information
+//
+
+#pragma pack(1)
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ ULONG Length;
+ } Element[];
+} ADDRESS_USAGE;
+#pragma pack()
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+//
+// Temp definitions to thunk into supporting new bus extension format
+//
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+//
+// Define function prototypes.
+//
+
+VOID
+HalInitSystemPhase2(
+ VOID
+ );
+
+KIRQL
+HaliRaiseIrqlToDpcLevel (
+ VOID
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+VOID
+HalpClockInterrupt(
+ VOID
+ );
+
+VOID
+HalpDisableAllInterrupts (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt(
+ VOID
+ );
+
+VOID
+HalpInitializeClock(
+ VOID
+ );
+
+VOID
+HalpInitializeDisplay(
+ VOID
+ );
+
+VOID
+HalpInitializeStallExecution(
+ IN CCHAR ProcessorNumber
+ );
+
+VOID
+HalpInitializePICs(
+ VOID
+ );
+
+VOID
+HalpIrq13Handler (
+ VOID
+ );
+
+VOID
+HalpFlushTLB (
+ VOID
+ );
+
+VOID
+HalpSerialize (
+ VOID
+ );
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+PVOID
+HalpMapPhysicalMemoryWriteThrough(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+VOID
+HalpBiosDisplayReset(
+ IN VOID
+ );
+
+HAL_DISPLAY_BIOS_INFORMATION
+HalpGetDisplayBiosInformation (
+ VOID
+ );
+
+VOID
+HalpDisplayDebugStatus(
+ IN PUCHAR Status,
+ IN ULONG Length
+ );
+
+VOID
+HalpInitializeCmos (
+ VOID
+ );
+
+VOID
+HalpReadCmosTime (
+ PTIME_FIELDS TimeFields
+ );
+
+VOID
+HalpWriteCmosTime (
+ PTIME_FIELDS TimeFields
+ );
+
+VOID
+HalpAcquireCmosSpinLock (
+ VOID
+ );
+
+VOID
+HalpReleaseCmosSpinLock (
+ VOID
+ );
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ );
+
+VOID
+HalpCpuID (
+ ULONG InEax,
+ PULONG OutEax,
+ PULONG OutEbx,
+ PULONG OutEcx,
+ PULONG OutEdx
+ );
+
+ULONGLONG
+FASTCALL
+RDMSR (
+ IN ULONG MsrAddress
+ );
+
+VOID
+WRMSR (
+ IN ULONG MsrAddress,
+ IN ULONGLONG MsrValue
+ );
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+//
+// Defines for HalpFeatureBits
+//
+
+#define HAL_PERF_EVENTS 0x00000001
+#define HAL_NO_SPECULATION 0x00000002
+#define HAL_MCA_PRESENT 0x00000004 // Intel MCA Available
+#define HAL_MCE_PRESENT 0x00000008 // ONLY Pentium style MCE available
+
+extern ULONG HalpFeatureBits;
+
+//
+// Defines for Processor Features returned from CPUID instruction
+//
+
+#define CPUID_MCA_MASK 0x4000
+#define CPUID_MCE_MASK 0x0080
+
+
+NTSTATUS
+HalpGetMcaLog(
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO pMcaDriverInfo // Info about registering driver
+ );
+
+VOID
+HalpMcaInit(
+ VOID
+ );
+
+
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halx86/i386/ix8259.inc b/private/ntos/nthals/halx86/i386/ix8259.inc
new file mode 100644
index 000000000..d053fbc22
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ix8259.inc
@@ -0,0 +1,199 @@
+;/*
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ix8259.inc
+;
+; Abstract:
+;
+; This module contains the definitions used by HAL to manipulate
+; 8259 interrupt controller and 8259-specific constants.
+;
+; WARNING: This file is included by both ASM and C files.
+;
+; Author:
+;
+; John Vert (jvert) 31-Dec-1991
+;
+; (Moved from ke\i386\kimacro.inc)
+;
+;--
+if 0 ; Begin C only code */
+
+//
+// 8259 defines for C code
+// BE SURE TO CHANGE THESE VALUES IN BOTH TABLES!
+//
+
+#define HIGHEST_LEVEL_FOR_8259 27 // Highest level for standard 8259
+#define PRIMARY_VECTOR_BASE 0x30 // Vector base for standard 8259
+#define PROFILE_VECTOR (PRIMARY_VECTOR_BASE + 8) // standard profile
+#define CLOCK_VECTOR (PRIMARY_VECTOR_BASE + 0) // standard clock
+#define I386_80387_IRQ 0x0d // standard npx
+#define I386_80387_IRQL (HIGHEST_LEVEL_FOR_8259 - I386_80387_IRQ)
+#define I386_80387_VECTOR (PRIMARY_VECTOR_BASE + I386_80387_IRQ)
+#define PIC_SLAVE_IRQ 2
+#define V2I(a) (a-PRIMARY_VECTOR_BASE) // Vector to interrupt macro
+
+/*
+endif
+
+;
+; Same 8259 defines for assemble code
+; BE SURE TO CHANGE THESE VALUES IN BOTH TABLES!
+;
+
+HIGHEST_LEVEL_FOR_8259 equ 27
+PRIMARY_VECTOR_BASE equ 30h
+PROFILE_VECTOR equ (PRIMARY_VECTOR_BASE + 8)
+CLOCK_VECTOR equ (PRIMARY_VECTOR_BASE + 0)
+I386_80387_IRQ equ 0dh
+I386_80387_IRQL equ (HIGHEST_LEVEL_FOR_8259 - I386_80387_IRQ)
+I386_80387_VECTOR equ (PRIMARY_VECTOR_BASE + I386_80387_IRQ)
+I386_80387_BUSY_PORT equ 0f0h ; port to dismiss busy error line
+PIC_SLAVE_IRQ equ 2
+
+
+;
+; The rest of the file are macros used in assemble only.
+;
+
+;++
+;
+; SET_8259_MASK
+;
+; Macro Description:
+;
+; This macro sets 8259 interrupt mask register with the mask
+; passed from eax register.
+;
+; Note: Currently, only two 8259s are support. As a result,
+; only ax contains valid mask.
+;
+; Arguments:
+;
+; (eax) = mask for setting 8259 interrupt mask register
+;
+;--
+
+SET_8259_MASK macro
+local a ; define local labels
+
+ out PIC1_PORT1, al ; set master 8259 mask
+ shr eax, 8 ; shift slave 8259 mask to al
+ out PIC2_PORT1, al ; set slave 8259 mask
+a:
+endm
+
+;
+; Interrupt controller register addresses
+;
+
+PIC1_PORT0 equ 020H
+PIC1_PORT1 equ 021H
+PIC2_PORT0 equ 0A0H
+PIC2_PORT1 equ 0A1H
+
+;
+; Commands for Interrupt controller
+;
+
+PIC1_EOI_MASK equ 060H
+PIC2_EOI equ 062H
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW3_READ_ISR equ 0BH
+OCW3_READ_IRR equ 0AH
+
+
+;++
+;
+; IODELAY
+;
+; Macro Description:
+;
+; This macro simply does a jmp to next instruction to synchronize
+; IO port access.
+;
+; Arguments:
+;
+; None
+;
+;--
+
+IODELAY macro
+ jmp $+2
+endm
+
+
+;++
+;
+; PICDELAY
+;
+; Macro Description:
+;
+; This macro does an inb on interrupt mask register to provide the
+; time for 8259 to get stabled.
+;
+; Why do we need this?
+;
+; This is because:
+; . The 80386 has a delayed write to memory and delayed output to IO
+; capability and
+; . 8259 needs some time to settle
+;
+; It is possible for the actual output cycle to 8259 to occur after
+; the completion of instructions following the out instruction. For
+; example, the STI instruction after SET_MASK and dismiss interrupt
+; macros may complete before 8259 actually drops the interrupt. We don't
+; want this happen in MCA system.
+;
+; You may argue that most OEMS add about 450ns delay to solve the
+; back-to-back IO (delay) problem. But, remember that STI is not an IO
+; instruction.
+;
+; Arguments:
+;
+; None
+;
+; NOTE: * The content of AL will be destroyed on return.
+;
+;--
+
+PIC1DELAY macro
+ in al, PIC1_PORT1
+endm
+
+PIC2DELAY macro
+ in al, PIC2_PORT1
+endm
+
+;++
+;
+; SOFT_INTERRUPT_EXIT
+;
+; Macro Description:
+;
+; This macro is executed on return from the soft interrupt
+; service routine. Its function is to restore privileged processor
+; state, and continue thread execution.
+;
+; Arguments:
+;
+; (TOS) = previous irql
+; (TOS+4 ...) = machine_state frame
+;
+;--
+
+SOFT_INTERRUPT_EXIT macro
+
+ EXTRNP _HalpEndSoftwareInterrupt,1
+ cli
+ call _HalpEndSoftwareInterrupt@4 ; restore irql
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI
+endm
+;*/
+
diff --git a/private/ntos/nthals/halx86/i386/ixbeep.asm b/private/ntos/nthals/halx86/i386/ixbeep.asm
new file mode 100644
index 000000000..0722ca9df
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixbeep.asm
@@ -0,0 +1,181 @@
+ title "Hal Beep"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixbeep.asm
+;
+;Abstract:
+;
+; HAL routine to make noise. It needs to synchronize its access to the
+; 8254, since we also use the 8254 for the profiling interrupt.
+;
+;
+;Author:
+;
+; John Vert (jvert) 31-Jul-1991
+;
+;Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+ extrn _Halp8254Lock:DWORD
+
+;
+; Defines used to program the i8254 for the speaker.
+;
+
+I8254_TIMER_CONTROL_PORT EQU 43h
+I8254_TIMER_DATA_PORT EQU 42h
+I8254_TIMER_CLOCK_IN EQU 1193167
+I8254_TIMER_TONE_MAX EQU 65536
+I8254_TIMER_CONTROL_SELECT EQU 0B6h
+SPEAKER_CONTROL_PORT EQU 61h
+SPEAKER_OFF_MASK EQU 0FCh
+SPEAKER_ON_MASK EQU 03h
+
+_TEXT$03 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "HalMakeBeep"
+;++
+;
+; BOOLEAN
+; HalMakeBeep(
+; IN ULONG Frequency
+; )
+;
+; Routine Description:
+;
+; This function sets the frequency of the speaker, causing it to sound a
+; tone. The tone will sound until the speaker is explicitly turned off,
+; so the driver is responsible for controlling the duration of the tone.
+;
+;Arguments:
+;
+; Frequency - Supplies the frequency of the desired tone. A frequency of
+; 0 means the speaker should be shut off.
+;
+;Return Value:
+;
+; TRUE - Operation was successful (frequency within range or zero)
+; FALSE - Operation was unsuccessful (frequency was out of range)
+; Current tone (if any) is unchanged.
+;
+;--
+
+Frequency equ [ebp + 8]
+
+cPublicProc _HalMakeBeep , 1
+
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ push ebx ; save ebx
+Hmb10: pushfd ; save flags
+ cli ; disable interrupts
+
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax,Hmb99
+endif
+
+ ;
+ ; Stop the speaker.
+ ;
+
+ in al, SPEAKER_CONTROL_PORT
+ jmp $+2
+ and al, SPEAKER_OFF_MASK
+ out SPEAKER_CONTROL_PORT, al
+ jmp $+2
+
+ ;
+ ; Calculate Tone: Tone = 1.193MHz / Frequency.
+ ; N.B. Tone must fit in 16 bits.
+ ;
+
+ mov ecx, DWORD PTR [Frequency] ; ecx <- frequency
+ or ecx, ecx ; (ecx) == 0?
+ je SHORT Hmb30 ; goto Hmb30
+
+ mov eax, I8254_TIMER_CLOCK_IN ; eax <- 1.193MHz, the clockin
+ ; for the speaker tone
+ sub edx, edx ; edx <- zero
+ div ecx ; eax <- 1.193MHz / frequency
+ cmp eax, I8254_TIMER_TONE_MAX ; (eax) < 2**16?
+ jb SHORT Hmb20 ; goto Hmb20
+
+ ;
+ ; Invalid frequency. Return FALSE.
+ ;
+
+ sub al, al
+ jmp SHORT Hmb40
+Hmb20:
+ ;
+ ; Program the 8254 with the calculated tone.
+ ;
+
+ push eax ; save Tone
+ mov al, I8254_TIMER_CONTROL_SELECT
+ out I8254_TIMER_CONTROL_PORT, al ; select timer control register
+ jmp $+2
+
+ pop eax ; restore Tone
+ out I8254_TIMER_DATA_PORT, al ; program 8254 with Tone lsb
+ jmp $+2
+ mov al, ah
+ out I8254_TIMER_DATA_PORT, al ; program 8254 with Tone msb
+ jmp $+2
+
+ ;
+ ; Turn the speaker on.
+ ;
+
+ in al, SPEAKER_CONTROL_PORT
+ jmp $+2
+ or al, SPEAKER_ON_MASK
+ out SPEAKER_CONTROL_PORT, al
+ jmp $+2
+
+Hmb30:
+ ;
+ ; Return TRUE.
+ ;
+
+ mov al, 1
+
+Hmb40:
+ifndef NT_UP
+ lea ebx, _Halp8254Lock
+ RELEASE_SPINLOCK ebx
+endif
+
+ popfd
+ pop ebx ; restore ebx
+ pop ebp ; restore ebp
+ stdRET _HalMakeBeep
+
+ifndef NT_UP
+
+Hmb99: popfd
+ SPIN_ON_SPINLOCK eax,<Hmb10>
+
+endif
+
+stdENDP _HalMakeBeep
+
+_TEXT$03 ends
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixbusdat.c b/private/ntos/nthals/halx86/i386/ixbusdat.c
new file mode 100644
index 000000000..ca7205c68
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixbusdat.c
@@ -0,0 +1,373 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpcGetCmosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpcSetCmosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG HalpGetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+ULONG HalpSetCmosData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+//
+// Prototype for system bus handlers
+//
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+NTSTATUS
+HalpHibernateHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+HalpResumeHal (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+#ifdef MCA
+//
+// Default functionality of MCA handlers is the same as the Eisa handlers,
+// just use them
+//
+
+#define HalpGetMCAInterruptVector HalpGetEisaInterruptVector
+#define HalpAdjustMCAResourceList HalpAdjustEisaResourceList;
+
+HalpGetPosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+#endif
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+#if 0
+ //
+ // Hibernate and resume the hal by getting notifications
+ // for when this bus is hibernated or resumed. Since it's
+ // the first bus to be added, it will be the last to hibernate
+ // and the first to resume
+ //
+
+ Bus->HibernateBus = HalpHibernateHal;
+ Bus->ResumeBus = HalpResumeHal;
+#endif
+
+ //
+ // Add handlers for Cmos config space.
+ //
+
+ Bus = HalpAllocateBusHandler (InterfaceTypeUndefined, Cmos, 0, -1, 0, 0);
+ Bus->GetBusData = HalpcGetCmosData;
+ Bus->SetBusData = HalpcSetCmosData;
+
+ Bus = HalpAllocateBusHandler (InterfaceTypeUndefined, Cmos, 1, -1, 0, 0);
+ Bus->GetBusData = HalpcGetCmosData;
+ Bus->SetBusData = HalpcSetCmosData;
+
+#ifndef MCA
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+
+#else
+
+ //
+ // Build MCA bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (MicroChannel, Pos, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetPosData;
+ Bus->GetInterruptVector = HalpGetMCAInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustMCAResourceList;
+
+#endif
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0xFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 1;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+ return Bus;
+}
+
+
+//
+// C to Asm thunks for CMos
+//
+
+ULONG HalpcGetCmosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ // bugbug: this interface should be rev'ed to support non-zero offsets
+ if (Offset != 0) {
+ return 0;
+ }
+
+ return HalpGetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length);
+}
+
+
+ULONG HalpcSetCmosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ // bugbug: this interface should be rev'ed to support non-zero offsets
+ if (Offset != 0) {
+ return 0;
+ }
+
+ return HalpSetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length);
+}
diff --git a/private/ntos/nthals/halx86/i386/ixclock.asm b/private/ntos/nthals/halx86/i386/ixclock.asm
new file mode 100644
index 000000000..6abb583cb
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixclock.asm
@@ -0,0 +1,760 @@
+
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixclock.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Landy Wang (corollary!landy) 04-Dec-92
+; Move much code into separate modules for easy inclusion by various
+; HAL builds.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _HalpMcaQueueDpc, 0
+
+;
+; Constants used to initialize timer 0
+;
+
+TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port
+TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port
+TIMER2_DATA_PORT0 EQU 48H ; Timer1, channel 0 data port
+TIMER2_CONTROL_PORT0 EQU 4BH ; Timer1, channel 0 control port
+TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt
+
+COMMAND_8254_COUNTER0 EQU 00H ; Select count 0
+COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB
+COMMAND_8254_MODE2 EQU 4 ; Use mode 2
+COMMAND_8254_BCD EQU 0 ; Binary count down
+COMMAND_8254_LATCH_READ EQU 0 ; Latch read command
+
+PERFORMANCE_FREQUENCY EQU 1193182
+
+;
+; ==== Values used for System Clock ====
+;
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+;
+; 8254 spinlock.
+;
+ public _Halp8254Lock
+_Halp8254Lock dd 0
+
+
+ public HalpPerfCounterLow, HalpPerfCounterHigh
+ public HalpLastPerfCounterLow, HalpLastPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpLastPerfCounterLow dd 0
+HalpLastPerfCounterHigh dd 0
+
+ public HalpCurrentRollOver, HalpCurrentTimeIncrement
+HalpCurrentRollOver dd 0
+HalpCurrentTimeIncrement dd 0
+
+ public _HalpClockWork, _HalpClockSetMSRate, _HalpClockMcaQueueDpc
+_HalpClockWork label dword
+ _HalpClockSetMSRate db 0
+ _HalpClockMcaQueueDpc db 0
+ _bReserved1 db 0
+ _bReserved2 db 0
+
+;
+; Convert the interval to rollover count for 8254 Timer1 device.
+; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec.
+; (The main crystal freq is 14.31818, and this is a divide by 12)
+;
+; The best fit value closest to 10ms is 10.0144012689ms:
+; ROLLOVER_COUNT 11949
+; TIME_INCREMENT 100144
+; Calculated error is -.0109472 s/day
+;
+;
+; The following table contains 8254 values timer values to use at
+; any given ms setting from 1ms - 15ms. All values work out to the
+; same error per day (-.0109472 s/day).
+;
+
+ public HalpRollOverTable
+
+ ; RollOver Time
+ ; Count Increment MS
+HalpRollOverTable dd 1197, 10032 ; 1 ms
+ dd 2394, 20064 ; 2 ms
+ dd 3591, 30096 ; 3 ms
+ dd 4767, 39952 ; 4 ms
+ dd 5964, 49984 ; 5 ms
+ dd 7161, 60016 ; 6 ms
+ dd 8358, 70048 ; 7 ms
+ dd 9555, 80080 ; 8 ms
+ dd 10731, 89936 ; 9 ms
+ dd 11949, 100144 ; 10 ms
+ dd 13125, 110000 ; 11 ms
+ dd 14322, 120032 ; 12 ms
+ dd 15519, 130064 ; 13 ms
+ dd 16695, 139920 ; 14 ms
+ dd 17892, 149952 ; 15 ms
+
+TimeIncr equ 4
+RollOver equ 0
+
+ public HalpLargestClockMS, HalpNextMSRate, HalpPendingMSRate
+HalpLargestClockMS dd 15 ; Table goes to 15MS
+HalpNextMSRate dd 0
+HalpPendingMSRate dd 0
+
+_DATA ends
+
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Clock"
+;++
+;
+; VOID
+; HalpInitializeClock (
+; )
+;
+; Routine Description:
+;
+; This routine initialize system time clock using 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0.
+;
+; See the definitions of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock ,0
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbCpuType, 4 ; 486 or better?
+ jc short @f ; no, skip
+
+ mov HalpLargestClockMS, 10 ; Limit 486's to 10MS
+@@:
+ mov eax, HalpLargestClockMS
+ mov ecx, HalpRollOverTable.TimeIncr
+ mov edx, HalpRollOverTable[eax*8-8].TimeIncr
+ mov eax, HalpRollOverTable[eax*8-8].RollOver
+
+ mov HalpCurrentTimeIncrement, edx
+
+;
+; (ecx) = Min time_incr
+; (edx) = Max time_incr
+; (eax) = max roll over count
+;
+
+ push eax
+ stdCall _KeSetTimeIncrement, <edx, ecx>
+ pop ecx
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+; (ecx) = RollOverCount
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ popfd ; restore caller's eflag
+ mov HalpCurrentRollOver, ecx ; Set RollOverCount & initialized
+
+ stdRET _HalpInitializeClock
+
+stdENDP _HalpInitializeClock
+
+INIT ends
+
+_TEXT$03 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Query Performance Counter"
+;++
+;
+; LARGE_INTEGER
+; KeQueryPerformanceCounter (
+; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
+; )
+;
+; Routine Description:
+;
+; This routine returns current 64-bit performance counter and,
+; optionally, the Performance Frequency.
+;
+; Note this routine can NOT be called at Profiling interrupt
+; service routine. Because this routine depends on IRR0 to determine
+; the actual count.
+;
+; Also note that the performace counter returned by this routine
+; is not necessary the value when this routine is just entered.
+; The value returned is actually the counter value at any point
+; between the routine is entered and is exited.
+;
+; Arguments:
+;
+; PerformanceFrequency [TOS+4] - optionally, supplies the address
+; of a variable to receive the performance counter frequency.
+;
+; Return Value:
+;
+; Current value of the performance counter will be returned.
+;
+;--
+
+
+;
+; Parameter definitions
+;
+
+KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence
+
+cPublicProc _KeQueryPerformanceCounter ,1
+;
+; First check to see if the performance counter has been initialized yet.
+; Since the kernel debugger calls KeQueryPerformanceCounter to support the
+; !timer command, we need to return something reasonable before 8254
+; initialization has occured. Reading garbage off the 8254 is not reasonable.
+;
+ cmp HalpCurrentRollOver, 0
+ je Kqpc50
+
+ push ebx
+ push esi
+
+Kqpc01: pushfd
+ cli
+Kqpc20:
+
+;
+; Fetch the base value. Note that interrupts are off.
+;
+
+ mov ebx, HalpPerfCounterLow
+ mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter
+
+;
+; Fetch the current counter value from the hardware
+;
+
+ mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
+ ;Latch PIT Ctr 0 command.
+ out TIMER1_CONTROL_PORT0, al
+ IODelay
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte.
+ IODelay
+ movzx ecx,al ;Zero upper bytes of (ECX).
+ in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte.
+ mov ch, al ;(CX) = PIT Ctr 0 count.
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+ ; (kernel debugger calls this function
+ ; with interrupts disabled)
+
+ jmp $+2 ; allow interrupt in case counter
+ ; has wrapped
+
+ pushfd
+ cli
+
+;
+; Fetch the base value again.
+;
+; Note: it's possible that the counter wrapped before we read the value
+; and that the timer tick interrupt did not occur during while interrupts
+; where enabled. (ie, there's a delay between when the device raises the
+; interrupt and when the processor see it).
+;
+;
+; note *2 -
+
+
+ mov eax, HalpPerfCounterLow
+ mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value
+
+;
+; Compare the two reads of Performance counter. If they are different,
+; start over
+;
+
+ cmp eax, ebx
+ jne short Kqpc20
+ cmp edx, esi
+ jne short Kqpc20
+
+ neg ecx ; PIT counts down from 0h
+ add ecx, HalpCurrentRollOver
+ jnc short Kqpc60
+
+Kqpc30:
+ add eax, ecx
+ adc edx, 0 ; [edx:eax] = Final result
+
+ cmp edx, HalpLastPerfCounterHigh
+ jc short Kqpc70 ; jmp if edx < lastperfcounterhigh
+ jne short Kqpc35 ; jmp if edx > lastperfcounterhigh
+
+ cmp eax, HalpLastPerfCounterLow
+ jc short Kqpc70 ; jmp if eax < lastperfcounterlow
+
+Kqpc35:
+ mov HalpLastPerfCounterLow, eax
+ mov HalpLastPerfCounterHigh, edx
+
+ popfd ; restore interrupt flag
+
+;
+; Return the freq. if caller wants it.
+;
+
+ cmp dword ptr KqpcFrequency, 0 ; is it a NULL variable?
+ jz short Kqpc40 ; if z, yes, go exit
+
+ mov ecx, KqpcFrequency ; (ecx)-> Frequency variable
+ mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency
+ mov DWORD PTR [ecx+4], 0
+
+Kqpc40:
+ pop esi ; restore esi and ebx
+ pop ebx
+ stdRET _KeQueryPerformanceCounter
+
+
+Kqpc50:
+; Initialization hasn't occured yet, so just return zeroes.
+ mov eax, 0
+ mov edx, 0
+ stdRET _KeQueryPerformanceCounter
+
+Kqpc60:
+;
+; The current count is larger then the HalpCurrentRollOver. The only way
+; that could happen is if there is an interrupt in route to the processor
+; but it was not processed while interrupts were enabled.
+;
+ mov esi, [esp] ; (esi) = flags
+ mov ecx, HalpCurrentRollOver ; (ecx) = max possible value
+ popfd ; restore flags
+
+ test esi, EFLAGS_INTERRUPT_MASK
+ jnz Kqpc01 ; ints are enabled, problem should go away
+
+ pushfd ; fix stack
+ jmp short Kqpc30 ; ints are disabled, use max count (ecx)
+
+
+Kqpc70:
+;
+; The current count is smaller then the last returned count. The only way
+; this should occur is if there is an interrupt in route to the processor
+; which was not been processed.
+;
+
+ mov ebx, HalpLastPerfCounterLow
+ mov esi, HalpLastPerfCounterHigh
+
+ mov ecx, ebx
+ or ecx, esi ; is last returned value 0?
+ jz short Kqpc35 ; Yes, then just return what we have
+
+ ; sanity check - make sure count is not off by bogus amount
+ sub ebx, eax
+ sbb esi, edx
+ jnz short Kqpc75 ; off by bogus amount
+ cmp ebx, HalpCurrentRollOver
+ jg short Kqpc75 ; off by bogus amount
+
+ sub eax, ebx
+ sbb edx, esi ; (edx:eax) = last returned count
+
+ mov ecx, [esp] ; (ecx) = flags
+ popfd
+
+ test ecx, EFLAGS_INTERRUPT_MASK
+ jnz Kqpc01 ; ints enabled, problem should go away
+
+ pushfd ; fix stack
+ jmp Kqpc35 ; ints disabled, just return last count
+
+Kqpc75:
+ popfd
+ xor eax, eax ; reset bogus values
+ mov HalpLastPerfCounterLow, eax
+ mov HalpLastPerfCounterHigh, eax
+ jmp Kqpc01 ; go try again
+
+stdENDP _KeQueryPerformanceCounter
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine resets the performance counter value for the current
+; processor to zero. The reset is done such that the resulting value
+; is closely synchronized with other processors in the configuration.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ mov eax, [esp+4] ; ponter to Number
+ pushfd ; save previous interrupt state
+ cli ; disable interrupts (go to high_level)
+
+ lock dec dword ptr [eax] ; count down
+
+@@: cmp dword ptr [eax], 0 ; wait for all processors to signal
+ jnz short @b
+
+ ;
+ ; Nothing to calibrate on a UP machine...
+ ;
+
+ popfd ; restore interrupt flag
+ stdRET _HalCalibratePerformanceCounter
+
+stdENDP _HalCalibratePerformanceCounter
+
+
+
+ page ,132
+ subttl "System Clock Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by CLOCK.
+; Its function is to dismiss the interrupt, raise system Irql to
+; CLOCK2_LEVEL, update performance counter and transfer control to the
+; standard system routine to update the system time and the execution
+; time of the current thread
+; and process.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeUpdateSystemTime, which returns
+;
+; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hci_a, Hci_t
+
+cPublicProc _HalpClockInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hci_a, Hci_t
+
+;
+; (esp) - base of trap frame
+;
+
+ifdef MCA
+
+;
+; Special hack for MCA machines
+;
+
+ in al, 61h
+ jmp $+2
+ or al, 80h
+ out 61h, al
+ jmp $+2
+
+endif ; MCA
+
+
+;
+; Dismiss interrupt and raise irq level to clock2 level
+;
+
+Hci10:
+ push CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL, CLOCK_VECTOR, esp>
+
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; Update performance counter
+;
+
+ xor ebx, ebx
+ mov eax, HalpCurrentRollOver
+ add HalpPerfCounterLow, eax ; update performace counter
+ adc HalpPerfCounterHigh, ebx
+
+;
+; Check for any more work
+;
+ mov eax, HalpCurrentTimeIncrement
+
+ cmp _HalpClockWork, ebx ; Any clock interrupt work desired?
+ jz _KeUpdateSystemTime@0 ; No, process tick
+
+ cmp _HalpClockMcaQueueDpc, bl
+ je short Hci20
+
+ mov _HalpClockMcaQueueDpc, bl
+
+;
+; Queue MCA Dpc
+;
+
+ push eax
+ stdCall _HalpMcaQueueDpc ; Queue MCA Dpc
+ pop eax
+
+
+Hci20:
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; ebp = trap frame
+; eax = time increment
+; ebx = 0
+;
+ cmp _HalpClockSetMSRate, bl ; New clock rate desired?
+ jz _KeUpdateSystemTime@0 ; No, process tick
+
+
+;
+; Time of clock frequency is being changed. See if the 8254 was
+; was reprogrammed for a new rate during last tick
+;
+ cmp HalpPendingMSRate, ebx ; Was a new rate set durning last
+ jnz short Hci50 ; tick? Yes, go update globals
+
+Hci40:
+; (eax) = time increment for current tick
+
+;
+; A new clock rate needs to be set. Setting the rate here will
+; cause the tick after the next tick to be at the new rate.
+; (the next tick is already in progress by the 8254 and will occur
+; at the same rate as this tick)
+;
+ mov ebx, HalpNextMSRate
+ mov HalpPendingMSRate, ebx ; pending rate
+
+ mov ecx, HalpRollOverTable[ebx*8-8].RollOver
+
+;
+; Set clock rate
+; (ecx) = RollOverCount
+;
+ push eax ; save current tick's rate
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov al, cl
+ out TIMER1_DATA_PORT0, al ; program timer 0 LSB count
+ IoDelay
+ mov al,ch
+ out TIMER1_DATA_PORT0, al ; program timer 0 MSB count
+
+ pop eax
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; ebp = trap frame
+; eax = time increment
+;
+ jmp _KeUpdateSystemTime@0 ; dispatch this tick
+
+Hci50:
+;
+; The next tick will occur at the rate which was programmed during the last
+; tick. Update globals for new rate which starts with the next tick.
+;
+; (eax) = time increment for current tick
+;
+ mov ebx, HalpPendingMSRate
+ mov ecx, HalpRollOverTable[ebx*8-8].RollOver
+ mov edx, HalpRollOverTable[ebx*8-8].TimeIncr
+
+ mov HalpCurrentRollOver, ecx
+ mov HalpCurrentTimeIncrement, edx ; next tick rate
+ mov HalpPendingMSRate, 0 ; no longer pending, clear it
+
+ cmp ebx, HalpNextMSRate ; new rate == NextRate?
+ jne short Hci40 ; no, go set new pending rate
+
+ mov _HalpClockSetMSRate, 0 ; all done setting new rate
+ jmp _KeUpdateSystemTime@0 ; dispatch this tick
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpClockInterrupt
+
+;++
+;
+; ULONG
+; HalSetTimeIncrement (
+; IN ULONG DesiredIncrement
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine initialize system time clock to generate an
+; interrupt at every DesiredIncrement interval.
+;
+; Arguments:
+;
+; DesiredIncrement - desired interval between every timer tick (in
+; 100ns unit.)
+;
+; Return Value:
+;
+; The *REAL* time increment set.
+;--
+cPublicProc _HalSetTimeIncrement,1
+
+ mov eax, [esp+4] ; desired setting
+ xor edx, edx
+ mov ecx, 10000
+ div ecx ; round to MS
+
+ cmp eax, HalpLargestClockMS ; MS > max?
+ jc short @f
+ mov eax, HalpLargestClockMS ; yes, use max
+@@:
+ or eax, eax ; MS < min?
+ jnz short @f
+ inc eax ; yes, use min
+@@:
+ mov HalpNextMSRate, eax
+ mov _HalpClockSetMSRate, 1 ; New clock rate desired.
+
+ mov eax, HalpRollOverTable[eax*8-8].TimeIncr
+ stdRET _HalSetTimeIncrement
+
+stdENDP _HalSetTimeIncrement
+_TEXT$03 ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixcmos.asm b/private/ntos/nthals/halx86/i386/ixcmos.asm
new file mode 100644
index 000000000..5cc391076
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixcmos.asm
@@ -0,0 +1,1135 @@
+ title "Cmos Access Routines"
+;++
+;
+; Module Name:
+;
+; ixcmos.asm
+;
+; Abstract:
+;
+; Procedures necessary to access CMOS/ECMOS information.
+;
+; Author:
+;
+; David Risner (o-ncrdr) 20 Apr 1992
+;
+; Revision History:
+;
+; Landy Wang (corollary!landy) 04 Dec 1992
+; - Move much code from ixclock.asm to here so different HALs
+; can reuse the common functionality.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include mac386.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn _HalpSystemHardwareLock:DWORD
+ extrn _HalpBusType:DWORD
+ extrn _HalpSerialLen:BYTE
+ extrn _HalpSerialNumber:BYTE
+
+
+CMOS_STATUS_BUSY EQU 80H ; Time update in progress
+RTC_OFFSET_SECOND EQU 0 ; second field of RTC memory
+RTC_OFFSET_MINUTE EQU 2 ; minute field of RTC memory
+RTC_OFFSET_HOUR EQU 4 ; hour field of RTC memory
+RTC_OFFSET_DAY_OF_WEEK EQU 6 ; day-of-week field of RTC memory
+RTC_OFFSET_DATE_OF_MONTH EQU 7 ; date-of-month field of RTC memory
+RTC_OFFSET_MONTH EQU 8 ; month field of RTC memory
+RTC_OFFSET_YEAR EQU 9 ; year field of RTC memory
+RTC_OFFSET_CENTURY_MCA EQU 37h ; Century field of RTC memory for MCA
+RTC_OFFSET_CENTURY EQU 32h ; Century field of RTC memory
+RTC_OFFSET_CENTURY_DS EQU 148h ; Bank 1, 48. Century field for DS
+BANK1 EQU 100h
+
+;
+; BCD_TO_BIN
+;
+; Description: Convert BCD value to binary
+;
+; Parameter:
+; Input: (AL) = 2 digit BCD number to convert
+; Output: (AX) = Binary equivalent (all in AL)
+;
+; Return: None.
+;
+
+BCD_TO_BIN macro
+
+ xor ah,ah
+ rol ax,4
+ ror al,4
+ aad
+endm
+
+;
+; BIN_TO_BCD
+;
+; Description: Convert binary value to BCD.
+;
+; Parameter:
+; Input: (AL) = binary value to be converted.
+; Output: (AX) = BCD (all in AL)
+;
+; Return: None.
+;
+
+BIN_TO_BCD macro
+
+ aam
+ rol al, 4
+ ror ax, 4
+endm
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; HalpRebootNow is a reboot vector. Set in an MP system, to
+; cause any processors which may be looping in HalpAcquireCmosSinLock
+; to transfer control to the vector in HalpRebootNow
+;
+
+ public _HalpRebootNow
+_HalpRebootNow dd 0
+
+;
+; Holds the value of the eflags register before a cmos spinlock is
+; acquired (used in HalpAcquire/ReleaseCmosSpinLock().
+;
+_HalpHardwareLockFlags dd 0
+
+;
+; Holds the offset to CMOS Century information.
+;
+
+_HalpCmosCenturyOffset dd 0
+
+_DATA ends
+
+ subttl "HalpGetCmosData"
+
+;++
+;
+; CMOS space read and write functions.
+;
+;--
+
+CmosAddressPort equ 70H
+CmosDataPort equ 71H
+
+ECmosAddressLsbPort equ 74H
+ECmosAddressMsbPort equ 75H
+ECmosDataPort equ 76H
+
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; HalpInitializeCmos(
+; VOID
+; )
+;
+; This routine reads CMOS and initializes globals required for
+; CMOS access, such as the location of the century byte.
+;
+;--
+
+cPublicProc _HalpInitializeCmos,0
+
+ push ebx
+ push esi
+ push edi
+
+;
+; Assume default
+;
+
+ mov eax, RTC_OFFSET_CENTURY
+ mov _HalpCmosCenturyOffset, eax
+
+ cmp _HalpBusType, MACHINE_TYPE_ISA
+ jne short icm40
+
+
+;
+; If control comes here, this is ISA machine. We need to check if this is
+; IBM PS/1 or Pc/ValuePoint machine and use RTC_CENTURY_OFFSET_MCA to get
+; Century byte from CMOS.
+;
+
+;
+; Check if the CMOS 2e and 2f contains memory checksum. On PS/1 machine
+; the check should fail.
+;
+
+icm20: mov ecx, 2dh ; from 10h to 2dh
+ mov eax, 0 ; clear ax
+ mov edx, 0
+
+icm30: mov al, cl
+ CMOS_READ
+ add edx, eax
+ dec ecx
+ cmp ecx, 0fh
+ jne short icm30
+
+ mov eax, 2eh
+ CMOS_READ
+ mov ah, al
+ mov al, 2fh
+ CMOS_READ
+ cmp eax, edx
+ je short icm50 ; NOT PS/1
+
+ mov eax, RTC_OFFSET_CENTURY_MCA
+ mov _HalpCmosCenturyOffset, eax
+ jmp icm90
+
+icm40: cmp _HalpBusType, MACHINE_TYPE_MCA
+ jne short icm50
+
+;
+; See if this is a P700 MCA machine
+;
+
+ in al, 07fh ; get PD700 ID byte
+ and al, 0F0h ; Mask high nibble
+ cmp al, 0A0h ; Is the ID Ax?
+ jz short icm50
+ cmp al, 090h ; Or an 9X?
+ jz short icm50 ; Yes, it's a 700
+
+ mov eax, RTC_OFFSET_CENTURY_MCA
+ mov _HalpCmosCenturyOffset, eax
+
+icm50:
+
+if 0
+
+ - Selecting BANK1 causes some devices to mess up their month value
+ - For now, I'm removing this code until this problem can be solved
+
+;
+; See if this is a Dallas Semiconductor DS17285 or later
+; Switch to BANK 1
+;
+ mov al, 0Ah
+ CMOS_READ
+
+ and al, 7fh ; Don't write UIP
+ mov ah, al
+ mov esi, eax ; save it for restore
+ or ah, 10h ; Set DV0 = 1
+
+ mov al, 0Ah ; Write register A
+ CMOS_WRITE
+
+;
+; Check for RTC serial # with matching crc
+; (al) = current byte
+; (ah) = scratch register
+; (bl) = current crc
+; (bh) = zero, non-zero, flag
+; (ecx) = cmos offset
+; (edx) = used by cmos_read macro
+; (esi) = saved register 0A
+;
+ mov ecx, 40h
+ xor ebx, ebx
+
+icm60: mov al, cl
+ CMOS_READ
+ mov byte ptr _HalpSerialNumber+2+-40h[ecx], al
+
+ or bh, al ; or to check for all zeros
+
+ mov ch, 8 ; Bits per byte
+
+icm65: mov ah, bl ; ah = crc
+ xor ah, al ; xor LSb
+ shr bl, 1 ; shift crc
+ shr ah, 1 ; mov LSb to carry
+ sbb ah, ah ; if carry set 1's else 0's
+ and ah, (118h shr 1) ; crc polynomial
+ xor bl, ah ; apply it
+
+ shr al, 1 ; next bit
+ dec ch ;
+ jnz short icm65 ; if ch non-zero, loop
+
+ inc cl ; next cmos location
+ cmp cl, 48h ; at end?
+ jne short icm60 ; no, loop
+;
+; (bh) = zero, non-zero flag
+; (bl) = crc
+;
+
+ mov eax, RTC_OFFSET_CENTURY_DS ; Read century byte
+ CMOS_READ
+
+ BCD_TO_BIN
+ movzx ecx, ax ; save it
+
+;
+; Switch back to BANK 0
+;
+
+ mov eax, esi
+ mov al, 0Ah
+ CMOS_WRITE
+
+;
+; Check for valid DS data
+;
+ cmp bh, 0 ; Was data all zeros?
+ je short icm90
+
+ cmp bl, 0 ; was CRC valid?
+ jnz short icm90
+
+ cmp ecx, 19 ; Is century before 19?
+ jb short icm90
+
+ cmp ecx, 20 ; Is century after 20?
+ ja short icm90
+
+;
+; Setup for DS century byte
+;
+ mov byte ptr _HalpSerialNumber+0, 'D'
+ mov byte ptr _HalpSerialNumber+1, 'S'
+ mov _HalpSerialLen, 10
+
+ mov eax, RTC_OFFSET_CENTURY_DS
+ mov _HalpCmosCenturyOffset, eax
+endif
+
+icm90: pop edi
+ pop esi
+ pop ebx
+ stdRET _HalpInitializeCmos
+
+stdENDP _HalpInitializeCmos
+
+
+INIT ends
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; ULONG
+; HalpGetCmosData(
+; IN ULONG SourceLocation
+; IN ULONG SourceAddress
+; IN ULONG ReturnBuffer
+; IN PUCHAR ByteCount
+; )
+;
+; This routine reads the requested number of bytes from CMOS/ECMOS and
+; stores the data read into the supplied buffer in system memory. If
+; the requested data amount exceeds the allowable extent of the source
+; location, the return data is truncated.
+;
+; Arguments:
+;
+; SourceLocation : where data is to be read from CMOS or ECMOS
+; 0 - CMOS, 1 - ECMOS
+;
+; SourceAddress : address in CMOS/ECMOS where data is to be read from
+;
+; ReturnBuffer : address in system memory for return data
+;
+; ByteCount : number of bytes to be read
+;
+; Returns:
+;
+; Number of byte actually read.
+;
+;--
+
+SourceLocation equ 2*4[ebp]
+SourceAddress equ 3*4[ebp]
+ReturnBuffer equ 4*4[ebp]
+ByteCount equ 5*4[ebp]
+
+cPublicProc _HalpGetCmosData ,4
+
+ push ebp
+ mov ebp, esp
+ push ebx
+ push edi
+
+ ;
+ ; NOTE: The spinlock is needed even in the UP case, because
+ ; the resource is also used in an interrupt handler (profiler).
+ ; If we own the spinlock in this routine, and we service
+ ; the profiler interrupt (which will wait for the spinlock forever),
+ ; then we have a hosed system.
+ ;
+ stdCall _HalpAcquireCmosSpinLock
+
+ xor edx, edx ; initialize return data length
+ mov ecx, ByteCount
+
+ or ecx, ecx ; validate requested byte count
+ jz HalpGetCmosDataExit ; if no work to do, exit
+
+ mov edx, SourceAddress
+ mov edi, ReturnBuffer
+
+ mov eax, SourceLocation ; cmos or extended cmos?
+ cmp eax, 1
+ je ECmosReadByte
+ cmp eax, 0
+ jne HalpGetCmosDataExit
+
+CmosReadByte:
+ cmp edx, 0ffH ; validate cmos source address
+ ja HalpGetCmosDataExit ; if out of range, exit
+ mov al, dl
+ out CmosAddressPort, al
+ in al, CmosDataPort
+ mov [edi], al
+ inc edx
+ inc edi
+ dec ecx
+ jnz CmosReadByte
+ jmp SHORT HalpGetCmosDataExit
+
+ECmosReadByte:
+ cmp edx,0ffffH ; validate ecmos source address
+ ja HalpGetCmosDataExit ; if out of range, exit
+ mov al, dl
+ out ECmosAddressLsbPort, al
+ mov al, dh
+ out ECmosAddressMsbPort, al
+ in al, ECmosDataPort
+ mov [edi], al
+ inc edx
+ inc edi
+ dec ecx
+ jnz ECmosReadByte
+
+HalpGetCmosDataExit:
+ stdCall _HalpReleaseCmosSpinLock
+
+ mov eax, edx ; return bytes read
+
+ pop edi
+ pop ebx
+ pop ebp
+
+ stdRET _HalpGetCmosData
+
+stdENDP _HalpGetCmosData
+
+
+;++
+;
+; VOID
+; HalpSetCmosData(
+; IN ULONG SourceLocation
+; IN ULONG SourceAddress
+; IN ULONG ReturnBuffer
+; IN PUCHAR ByteCount
+; )
+;
+; This routine writes the requested number of bytes to CMOS/ECMOS
+;
+; Arguments:
+;
+; SourceLocation : where data is to be written to CMOS or ECMOS
+; 0 - CMOS, 1 - ECMOS
+;
+; SourceAddress : address in CMOS/ECMOS where data is to write to.
+;
+; ReturnBuffer : address in system memory for data to write
+;
+; ByteCount : number of bytes to be write
+;
+; Returns:
+;
+; Number of byte actually written.
+;
+;--
+
+cPublicProc _HalpSetCmosData ,4
+
+ push ebp
+ mov ebp, esp
+ push ebx
+ push edi
+
+ stdCall _HalpAcquireCmosSpinLock
+
+ xor edx, edx ; initialize return data length
+ mov ecx, ByteCount
+
+ or ecx, ecx ; validate requested byte count
+ jz HalpSetCmosDataExit ; if no work to do, exit
+
+ mov edx, SourceAddress
+ mov edi, ReturnBuffer
+
+ mov eax, SourceLocation ; cmos or extended cmos?
+ cmp eax, 1
+ je ECmosWriteByte
+ cmp eax, 0
+ jne HalpSetCmosDataExit
+
+CmosWriteByte:
+ cmp edx, 0ffH ; validate cmos source address
+ ja HalpSetCmosDataExit ; if out of range, exit
+ mov al, dl
+ out CmosAddressPort, al
+ mov al, [edi]
+ out CmosDataPort, al
+ inc edx
+ inc edi
+ dec ecx
+ jnz CmosWriteByte
+ jmp SHORT HalpSetCmosDataExit
+
+ECmosWriteByte:
+ cmp edx,0ffffH ; validate ecmos source address
+ ja HalpSetCmosDataExit ; if out of range, exit
+ mov al, dl
+ out ECmosAddressLsbPort, al
+ mov al, dh
+ out ECmosAddressMsbPort, al
+ mov al, [edi]
+ out ECmosDataPort, al
+ inc edx
+ inc edi
+ dec ecx
+ jnz ECmosWriteByte
+
+HalpSetCmosDataExit:
+ stdCall _HalpReleaseCmosSpinLock
+
+ mov eax, edx ; return bytes written
+ pop edi
+ pop ebx
+ pop ebp
+
+ stdRET _HalpSetCmosData
+
+stdENDP _HalpSetCmosData
+
+
+ page ,132
+ subttl "Read System Time"
+;++
+;
+; VOID
+; HalpReadCmosTime (
+; PTIME_FIELDS TimeFields
+; )
+;
+; Routine Description:
+;
+; This routine reads current time from CMOS memory and stores it
+; in the TIME_FIELDS structure passed in by caller.
+;
+; Arguments:
+;
+; TimeFields - A pointer to the TIME_FIELDS structure.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+;
+; Parameters:
+;
+
+KrctPTimeFields equ [esp+4]
+
+cPublicProc _HalpReadCmosTime ,1
+
+if DBG
+krctwait0:
+ mov ecx, 100
+krctwait:
+ push ecx
+else
+krctwait:
+endif
+ stdCall _HalpAcquireCmosSpinLock
+ mov ecx, 100
+ align 4
+krct00: mov al, 0Ah ; Specify register A
+ CMOS_READ ; (al) = CMOS register A
+ test al, CMOS_STATUS_BUSY ; Is time update in progress?
+ jz short krct10 ; if z, no, go read CMOS time
+ loop short krct00 ; otherwise, try again.
+
+;
+; CMOS is still busy. Try again ...
+;
+
+ stdCall _HalpReleaseCmosSpinLock
+if DBG
+ pop ecx
+ loop short krctwait
+ stdCall _DbgBreakPoint
+ jmp short krctwait0
+else
+ jmp short krctwait
+endif
+ align 4
+if DBG
+krct10:
+ pop ecx
+else
+krct10:
+endif
+ mov edx, KrctPTimeFields ; (edx)-> TIME_FIELDS structure
+ xor eax, eax ; (eax) = 0
+
+ mov al, RTC_OFFSET_SECOND
+ CMOS_READ ; (al) = second in BCD form
+ BCD_TO_BIN ; (ax) = second
+ mov [edx].TfSecond, ax ; set second in TIME_FIELDS
+
+ mov al, RTC_OFFSET_MINUTE
+ CMOS_READ ; (al) = minute in BCD form
+ BCD_TO_BIN ; (ax) = Minute
+ mov [edx].TfMinute, ax ; set minute in TIME_FIELDS
+
+ mov al, RTC_OFFSET_HOUR
+ CMOS_READ ; (al) = hour in BCD form
+ BCD_TO_BIN ; (ax) = Hour
+ mov [edx].TfHour, ax ; set hour in TIME_FIELDS
+
+ mov al, RTC_OFFSET_DAY_OF_WEEK
+ CMOS_READ ; (al) = day-of-week in BCD form
+ BCD_TO_BIN ; (ax) = day-of-week
+ mov [edx].TfWeekday, ax ; set Weekday in TIME_FIELDS
+
+ mov al, RTC_OFFSET_DATE_OF_MONTH
+ CMOS_READ ; (al) = date-of-month in BCD form
+ BCD_TO_BIN ; (ax) = date_of_month
+ mov [edx].TfDay, ax ; set day in TIME_FIELDS
+
+ mov al, RTC_OFFSET_MONTH
+ CMOS_READ ; (al) = month in BCD form
+ BCD_TO_BIN ; (ax) = month
+ mov [edx].TfMonth, ax ; set month in TIME_FIELDS
+
+ mov al, RTC_OFFSET_YEAR
+ CMOS_READ ; (al) = year in BCD form
+ BCD_TO_BIN ; (ax) = year
+ push eax ; save year in stack
+
+ push edx ; preserve edx
+ call _HalpGetCmosCenturyByte ; (al)= century byte in BCD form
+ BCD_TO_BIN ; (ax) = century
+ pop edx
+
+ mov ah, 100
+ mul ah ; (ax) = century * 100
+ pop ecx ; (cx) = year
+ add ax, cx ; (ax)= year
+
+ cmp ax, 1900 ; Is year > 1900
+ jb short krct40
+ cmp ax, 1920 ; and < 1920
+ jae short krct40
+ add ax, 100 ; Compensate for century field
+
+krct40:
+ mov [edx].TfYear, ax ; set year in TIME_FIELDS
+
+ mov word ptr [edx].TfMilliseconds, 0 ; do not support
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ stdRET _HalpReadCmosTime
+
+stdENDP _HalpReadCmosTime
+
+ page ,132
+ subttl "Write System Time"
+;++
+;
+; VOID
+; HalpWriteCmosTime (
+; PTIME_FIELDS TimeFields
+; )
+;
+; Routine Description:
+;
+; This routine writes current time from TIME_FILEDS structure
+; to CMOS memory.
+;
+; Arguments:
+;
+; TimeFields - A pointer to the TIME_FIELDS structure.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+;
+; Parameters:
+;
+
+KrctPTimeFields equ [esp+4]
+
+cPublicProc _HalpWriteCmosTime ,1
+
+if DBG
+kwctwait0:
+ mov ecx, 100
+kwctwait:
+ push ecx
+else
+kwctwait:
+endif
+ stdCall _HalpAcquireCmosSpinLock
+ mov ecx, 100
+ align 4
+kwct00: mov al, 0Ah ; Specify register A
+ CMOS_READ ; (al) = CMOS register A
+ test al, CMOS_STATUS_BUSY ; Is time update in progress?
+ jz short kwct10 ; if z, no, go write CMOS time
+ loop short kwct00 ; otherwise, try again.
+
+;
+; CMOS is still busy. Try again ...
+;
+
+ stdCall _HalpReleaseCmosSpinLock
+if DBG
+ pop ecx
+ loop short kwctwait
+ stdCall _DbgBreakPoint
+ jmp short kwctwait0
+else
+ jmp short kwctwait
+endif
+ align 4
+if DBG
+kwct10:
+ pop ecx
+else
+kwct10:
+endif
+ mov edx, KrctPTimeFields ; (edx)-> TIME_FIELDS structure
+
+ mov al, [edx].TfSecond ; Read second in TIME_FIELDS
+ BIN_TO_BCD
+ mov ah, al
+ mov al, RTC_OFFSET_SECOND
+ CMOS_WRITE
+
+ mov al, [edx].TfMinute ; Read minute in TIME_FIELDS
+ BIN_TO_BCD
+ mov ah, al
+ mov al, RTC_OFFSET_MINUTE
+ CMOS_WRITE
+
+ mov al, [edx].TfHour ; Read Hour in TIME_FIELDS
+ BIN_TO_BCD
+ mov ah, al
+ mov al, RTC_OFFSET_HOUR
+ CMOS_WRITE
+
+ mov al, [edx].TfWeekDay ; Read WeekDay in TIME_FIELDS
+ BIN_TO_BCD
+ mov ah, al
+ mov al, RTC_OFFSET_DAY_OF_WEEK
+ CMOS_WRITE
+
+ mov al, [edx].TfDay ; Read day in TIME_FIELDS
+ BIN_TO_BCD
+ mov ah, al
+ mov al, RTC_OFFSET_DATE_OF_MONTH
+ CMOS_WRITE
+
+ mov al, [edx].TfMonth ; Read month in TIME_FIELDS
+ BIN_TO_BCD
+ mov ah, al
+ mov al, RTC_OFFSET_MONTH
+ CMOS_WRITE
+
+ mov ax, [edx].TfYear ; Read Year in TIME_FIELDS
+ cmp ax, 9999
+ jbe short kwct15
+ mov ax, 9999
+
+ align 4
+kwct15:
+ mov cl, 100
+ div cl ; [ax]/[cl]->al=quo, ah=rem
+ push eax
+ BIN_TO_BCD
+
+ push eax
+ call _HalpSetCmosCenturyByte
+
+ pop eax
+ mov al, ah ; [al] = Year
+ BIN_TO_BCD
+ mov ah, al ; [ah] = year in BCD
+ mov al, RTC_OFFSET_YEAR
+ CMOS_WRITE
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ stdRET _HalpWriteCmosTime
+
+stdENDP _HalpWriteCmosTime
+
+
+;++
+;
+; Routine Description:
+;
+; Acquires a spinlock to access the cmos chip. The cmos chip is
+; accessed at different irql levels, so to be safe, we 'cli'.
+; We could replace that to raise irql to PROFILE_LEVEL, but that's
+; a lot of code.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; Interrupt is disabled.
+; Irql level not affected.
+; Flags saved in _HalpHardwareLockFlags.
+;--
+
+cPublicProc _HalpAcquireCmosSpinLock ,0
+ push eax
+
+Arsl10: pushfd
+ cli
+ lea eax, _HalpSystemHardwareLock
+ ACQUIRE_SPINLOCK eax, Arsl20
+ pop _HalpHardwareLockFlags ; save flags for release S.L.
+ pop eax
+ stdRET _HalpAcquireCmosSpinLock
+
+Arsl20: popfd
+
+Arsl30:
+ifndef NT_UP
+ cmp _HalpRebootNow, 0
+ jnz short Arsl50
+endif
+ TEST_SPINLOCK eax, <short Arsl30>
+ jmp short ARsl10
+
+Arsl50:
+ifndef NT_UP
+ mov eax, _HalpRebootNow
+ call eax
+ int 3 ; should not return
+endif
+
+stdENDP _HalpAcquireCmosSpinLock
+
+
+;++
+;
+; Routine Description:
+;
+; Release spinlock, and restore flags to the state it was before
+; acquiring the spinlock.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; Interrupts restored to their state before acquiring spinlock.
+; Irql level not affected.
+;
+;--
+
+cPublicProc _HalpReleaseCmosSpinLock ,0
+ push eax
+ ;
+ ; restore eflags as it was before acquiring spinlock. Put it on
+ ; stack before releasing spinlock (so other cpus cannot overwrite
+ ; it with their own eflags).
+ ;
+ push _HalpHardwareLockFlags ; old eflags on stack.
+ lea eax, _HalpSystemHardwareLock
+ RELEASE_SPINLOCK eax
+ popfd ; restore eflags.
+ pop eax
+ stdRET _HalpReleaseCmosSpinLock
+stdENDP _HalpReleaseCmosSpinLock
+
+;++
+;
+; UCHAR
+; HalpGetCmosCenturyByte (
+; VOID
+; )
+;
+; Routine Description:
+;
+; This routine gets Century byte from CMOS.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; (al) = Century byte in BCD form.
+;
+;--
+
+cPublicProc _HalpGetCmosCenturyByte, 0
+
+ mov eax, _HalpCmosCenturyOffset
+
+if DBG
+
+;
+; Make sure the HalpCmosCenturyOffset is initialized
+;
+
+ cmp eax, 0
+ jne short @f
+
+ int 3
+@@:
+endif
+ test eax, BANK1
+ jnz short rcb50
+
+ CMOS_READ ; (al) = century in BCD form
+ stdRET _HalpGetCmosCenturyByte
+
+rcb50: mov edx, eax
+
+ mov al, 0Ah
+ CMOS_READ
+
+ mov dh, al ; save it for restore
+ or al, 10h ; Set DV0 = 1
+
+ mov ah, al
+ mov al, 0Ah ; Write register A
+ CMOS_WRITE
+
+ mov al, dl ; century offset
+ CMOS_READ
+ mov dl, al ; save it
+
+ mov ah, dh ; Restore DV0
+ mov al, 0Ah ; Write register A
+ CMOS_WRITE
+
+ mov al, dl
+ stdRET _HalpGetCmosCenturyByte
+
+stdENDP _HalpGetCmosCenturyByte
+
+
+;++
+;
+; VOID
+; HalpSetCmosCenturyByte (
+; UCHAR Century
+; )
+;
+; Routine Description:
+;
+; This routine sets Century byte in CMOS.
+;
+; Arguments:
+;
+; Century - Supplies the value for CMOS century byte
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalpSetCmosCenturyByte, 1
+
+ mov eax, _HalpCmosCenturyOffset
+if DBG
+
+;
+; Make sure the HalpCmosCenturyOffset is initialized
+;
+
+ cmp eax, 0
+ jne short @f
+
+ int 3
+@@:
+endif
+
+ test eax, BANK1
+ jnz short scb50
+
+ mov ah, [esp+4] ; (ah) = Century in BCD form
+ CMOS_WRITE
+ stdRET _HalpSetCmosCenturyByte
+
+
+scb50: mov edx, eax
+
+ mov al, 0Ah
+ CMOS_READ
+
+ mov dh, al ; save it for restore
+ or al, 10h ; Set DV0 = 1
+
+ mov ah, al
+ mov al, 0Ah ; Write register A
+ CMOS_WRITE
+
+ mov ah, [esp+4] ; (ah) = Century in BCD form
+ mov al, dl ; century offset
+ CMOS_WRITE
+
+ mov ah, dh ; Restore DV0
+ mov al, 0Ah ; Write register A
+ CMOS_WRITE
+ stdRET _HalpSetCmosCenturyByte
+
+stdENDP _HalpSetCmosCenturyByte
+
+
+;++
+;
+; VOID
+; HalpCpuID (
+; ULONG InEax,
+; PULONG OutEax,
+; PULONG OutEbx,
+; PULONG OutEcx,
+; PULONG OutEdx
+; );
+;
+; Routine Description:
+;
+; Executes the CPUID instruction and returns the registers from it
+;
+; Only available at INIT time
+;
+; Arguments:
+;
+; Return Value:
+;
+;--
+cPublicProc _HalpCpuID,5
+
+ push ebx
+ push esi
+
+ mov eax, [esp+12]
+ db 0fh, 0a2h ; CPUID
+
+ mov esi, [esp+16] ; return EAX
+ mov [esi], eax
+
+ mov esi, [esp+20] ; return EBX
+ mov [esi], ebx
+
+ mov esi, [esp+24] ; return ECX
+ mov [esi], ecx
+
+ mov esi, [esp+28] ; return EDX
+ mov [esi], edx
+
+ pop esi
+ pop ebx
+
+ stdRET _HalpCpuID
+
+stdENDP _HalpCpuID
+
+
+;++
+;
+; VOID
+; HalpFlushTLB (
+; VOID
+; );
+;
+; Routine Description:
+;
+; Flush the current TLB.
+;
+; Arguments:
+;
+; Return Value:
+;
+;--
+cPublicProc _HalpFlushTLB, 0
+.586p
+ pushfd
+ push ebx
+ push esi
+
+ cli
+ mov esi, cr3
+
+ mov ecx, PCR[PcPrcb]
+ cmp byte ptr [ecx].PbCpuID, 0
+ jz short ftb50
+
+ mov eax, 1 ; Get feature bits
+ cpuid ; (note "cpuid" between CR3 reload fixes
+ ; P6 B step errata #11)
+
+ test edx, 2000h ; see if 'G' bit is supported
+ jz short ftb50
+
+ mov ecx, cr4 ; 'G' bit is supported, due global flush
+ mov edx, ecx ; Save orginal cr4
+ and ecx, not CR4_PGE ; Make sure global bit is disabled
+ mov cr4, ecx
+ mov cr3, esi ; flush TLB
+ mov cr4, edx ; restore cr4
+ jmp short ftp99
+
+ftb50: mov cr3, esi
+
+ftp99: pop esi
+ pop ebx
+ popfd
+ stdRET _HalpFlushTLB
+
+.486p
+stdENDP _HalpFlushTLB
+
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixcmos.inc b/private/ntos/nthals/halx86/i386/ixcmos.inc
new file mode 100644
index 000000000..1f78de8e7
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixcmos.inc
@@ -0,0 +1,66 @@
+;/*
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixcmos.inc
+;
+; Abstract:
+;
+; This module contains common definitions used by the CMOS.
+;
+; Author:
+;
+; Landy Wang (corollary!landy) 04-Dec-1992
+;
+; (Moved from ixclock.asm)
+;
+;--
+
+;
+; _HalpAcquireCmosSpinLock and _HalpReleaseCmosSpinLock
+; must be called before accessing the CMOS in both uniprocessor
+; and multiprocessor systems.
+
+RTCIRQ EQU 8 ; IRQ number for RTC interrupt
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; CMOS_READ
+;
+; Description: This macro reads a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Returns: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+;
+; CMOS_WRITE
+;
+; Description: This macro reads a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; (AH) = data to be written
+;
+; Return: None
+;
+
+CMOS_WRITE MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ MOV AL,AH ; (AL) = DATA
+ OUT CMOS_DATA_PORT,AL ; PLACE IN REQUESTED CMOS LOCATION
+ IODelay ; I/O DELAY
+ENDM
diff --git a/private/ntos/nthals/halx86/i386/ixdat.c b/private/ntos/nthals/halx86/i386/ixdat.c
new file mode 100644
index 000000000..f6bc9cee3
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixdat.c
@@ -0,0 +1,159 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+#ifndef MCA
+ 0x000, 0x10, // ISA DMA
+ 0x0C0, 0x10, // ISA DMA
+#else
+ 0x000, 0x20, // MCA DMA
+ 0x0C0, 0x20, // MCA DMA
+#endif
+ 0x080, 0x10, // DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ 0x048, 0x4, // Timer2, Failsafe
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+#ifdef MCA
+ 0x074, 0x3, // Extended CMOS
+
+ 0x090, 0x2, // Arbritration Control Port, Card Select Feedback
+ 0x093, 0x2, // Reserved, System board setup
+ 0x096, 0x2, // POS channel select
+#endif
+ 0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x0D0, 0x10, // DMA
+ 0x400, 0x10, // DMA
+ 0x480, 0x10, // DMA
+ 0x4C2, 0xE, // DMA
+ 0x4D4, 0x2C, // DMA
+
+ 0x461, 0x2, // Extended NMI
+ 0x464, 0x2, // Last Eisa Bus Muster granted
+
+ 0x4D0, 0x2, // edge/level control registers
+
+ 0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+//
+// Strings used for boot.ini options
+// from mphal.c
+//
+
+UCHAR HalpSzBreak[] = "BREAK";
+UCHAR HalpSzPciLock[] = "PCILOCK";
+
+//
+// From ixcmos.asm
+//
+
+UCHAR HalpSerialLen;
+UCHAR HalpSerialNumber[31];
+
+//
+// From usage.c
+//
+
+WCHAR HalpSzSystem[] = L"\\Registry\\Machine\\Hardware\\Description\\System";
+WCHAR HalpSzSerialNumber[] = L"Serial Number";
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+//
+// From ixpcibrd.c
+//
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+//
+// From ixinfo.c
+//
+
+WCHAR rgzSuspendCallbackName[] = L"\\Callback\\SuspendHibernateSystem";
+UCHAR HalpGenuineIntel[]= "GenuineIntel";
+
+//
+// From ixmca.c
+//
+UCHAR MsgMCEPending[] = MSG_MCE_PENDING;
+WCHAR rgzSessionManager[] = L"Session Manager";
+WCHAR rgzEnableMCE[] = L"EnableMCE";
+WCHAR rgzEnableMCA[] = L"EnableMCA";
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+ULONG HalpFeatureBits;
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR+1];
diff --git a/private/ntos/nthals/halx86/i386/ixenvirv.c b/private/ntos/nthals/halx86/i386/ixenvirv.c
new file mode 100644
index 000000000..62bdccf01
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixenvirv.c
@@ -0,0 +1,183 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ixenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a x86 system.
+
+ Note that this particular implementation only supports the LastKnownGood
+ environment variable. This is done by using the Daylight Savings Time
+ bit in the Real Time Clock NVRAM. (Not pretty, but it's all we've got)
+
+ Attempts to read or write any environment variable other than
+ LastKnownGood will fail.
+
+Author:
+
+ John Vert (jvert) 22-Apr-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arc.h"
+#include "arccodes.h"
+#include "string.h"
+
+#define CMOS_CONTROL_PORT ((PUCHAR)0x70)
+#define CMOS_DATA_PORT ((PUCHAR)0x71)
+#define CMOS_STATUS_B 0x0B
+#define CMOS_DAYLIGHT_BIT 1
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+ The only environment variable this implementation supports is
+ "LastKnownGood" It uses the Daylight Savings Time bit in the Real
+ TimeClock to indicate the state (TRUE/FALSE only) of this environment
+ variable.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+ UCHAR StatusByte;
+
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( Buffer );
+
+ if (_stricmp(Variable, "LastKnownGood") != 0) {
+ return ENOENT;
+ }
+
+ //
+ // Read the Daylight Savings Bit out of the RTC to determine whether
+ // the LastKnownGood environment variable is TRUE or FALSE.
+ //
+
+ HalpAcquireCmosSpinLock();
+ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, CMOS_STATUS_B);
+ StatusByte = READ_PORT_UCHAR(CMOS_DATA_PORT);
+ HalpReleaseCmosSpinLock ();
+
+ if (StatusByte & CMOS_DAYLIGHT_BIT) {
+ strncpy(Buffer, "TRUE", Length);
+ } else {
+ strncpy(Buffer, "FALSE", Length);
+ }
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+ The only environment variable this implementation supports is
+ "LastKnownGood" It uses the Daylight Savings Time bit in the Real
+ TimeClock to indicate the state (TRUE/FALSE only) of this environment
+ variable.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+ UCHAR StatusByte;
+
+ if (_stricmp(Variable, "LastKnownGood") != 0) {
+ return ENOMEM;
+ }
+
+ if (_stricmp(Value, "TRUE") == 0) {
+
+ HalpAcquireCmosSpinLock();
+ //
+ // Turn Daylight Savings Bit on.
+ //
+ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, CMOS_STATUS_B);
+ StatusByte = READ_PORT_UCHAR(CMOS_DATA_PORT);
+
+ StatusByte |= CMOS_DAYLIGHT_BIT;
+
+ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, CMOS_STATUS_B);
+ WRITE_PORT_UCHAR(CMOS_DATA_PORT, StatusByte);
+
+ HalpReleaseCmosSpinLock();
+
+ } else if (_stricmp(Value, "FALSE") == 0) {
+
+ HalpAcquireCmosSpinLock();
+
+ //
+ // Turn Daylight Savings Bit off.
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, CMOS_STATUS_B);
+ StatusByte = READ_PORT_UCHAR(CMOS_DATA_PORT);
+
+ StatusByte &= ~CMOS_DAYLIGHT_BIT;
+
+ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, CMOS_STATUS_B);
+ WRITE_PORT_UCHAR(CMOS_DATA_PORT, StatusByte);
+
+ HalpReleaseCmosSpinLock();
+
+ } else {
+ return(ENOMEM);
+ }
+
+ return ESUCCESS;
+}
diff --git a/private/ntos/nthals/halx86/i386/ixfirm.c b/private/ntos/nthals/halx86/i386/ixfirm.c
new file mode 100644
index 000000000..1ebf1032a
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixfirm.c
@@ -0,0 +1,79 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixreboot.c
+
+Abstract:
+
+ Provides the interface to the firmware for x86. Since there is no
+ firmware to speak of on x86, this is just reboot support.
+
+Author:
+
+ John Vert (jvert) 12-Aug-1991
+
+Revision History:
+
+--*/
+#include "halp.h"
+
+//
+// Defines to let us diddle the CMOS clock and the keyboard
+//
+
+#define CMOS_CTRL (PUCHAR )0x70
+#define CMOS_DATA (PUCHAR )0x71
+
+#define RESET 0xfe
+#define KEYBPORT (PUCHAR )0x64
+
+VOID HalpVideoReboot(VOID);
+VOID HalpReboot(VOID);
+
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_ENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ Returns control to the firmware routine specified. Since the x86 has
+ no useful firmware, it just stops the system.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ switch (Routine) {
+ case HalHaltRoutine:
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+
+ HalpVideoReboot();
+
+ //
+ // Never returns
+ //
+
+ HalpReboot();
+ break;
+ default:
+ DbgPrint("HalReturnToFirmware called\n");
+ DbgBreakPoint();
+ break;
+ }
+}
diff --git a/private/ntos/nthals/halx86/i386/ixhwsup.c b/private/ntos/nthals/halx86/i386/ixhwsup.c
new file mode 100644
index 000000000..b0f89592d
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixhwsup.c
@@ -0,0 +1,758 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+#if MCA
+#include "mca.h"
+#else
+#include "eisa.h"
+#endif
+
+
+PVOID HalpEisaControlBase;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+
+ PVOID virtualAddress;
+ PVOID virtualAddress2;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ //
+ // Assume below 16M
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS-1;
+
+ //
+ // If the caller support 32bit addresses, and it's a master let
+ // it have any memory below 4G
+ //
+
+ if (AdapterObject->Dma32BitAddresses && AdapterObject->MasterDevice) {
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ }
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (HalpBusType != MACHINE_TYPE_ISA || AdapterObject->MasterDevice) {
+ return(virtualAddress);
+ }
+
+ //
+ // This is an ISA system the common buffer cannot cross a 64 K bountry.
+ //
+
+ if ((LogicalAddress->LowPart + Length & ~0xFFFF) ==
+ (LogicalAddress->LowPart & ~0xFFFF)) {
+
+ //
+ // This buffer is ok so return it.
+ //
+
+ return(virtualAddress);
+
+ }
+
+ //
+ // Try to allocate a buffer agian and see if this is good.
+ //
+
+ virtualAddress2 = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ //
+ // Free the first buffer.
+ //
+
+ MmFreeContiguousMemory(virtualAddress);
+
+ if (virtualAddress2 == NULL) {
+ return(NULL);
+ }
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress2);
+
+ if ((LogicalAddress->LowPart + Length & ~0xFFFF) ==
+ (LogicalAddress->LowPart & ~0xFFFF)) {
+
+ //
+ // This buffer is ok so return it.
+ //
+
+ return(virtualAddress2);
+
+ }
+
+ //
+ // Try our best but just could not do it. Free the buffer.
+ //
+
+ MmFreeContiguousMemory(virtualAddress2);
+
+ return(NULL);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( VirtualAddress );
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ Irql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
+
+ }
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
diff --git a/private/ntos/nthals/halx86/i386/ixidle.asm b/private/ntos/nthals/halx86/i386/ixidle.asm
new file mode 100644
index 000000000..8dea29cd9
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixidle.asm
@@ -0,0 +1,88 @@
+ title "Hal Processor Idle"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixidle.asm
+;
+;Abstract:
+;
+;
+;Author:
+;
+;
+;Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+_TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "HalProcessorIdle"
+;++
+;
+; VOID
+; HalProcessorIdle(
+; VOID
+; )
+;
+; Routine Description:
+;
+; This function is called when the current processor is idle.
+;
+; This function is called with interrupts disabled, and the processor
+; is idle until it receives an interrupt. The does not need to return
+; until an interrupt is received by the current processor.
+;
+; This is the lowest level of processor idle. It occurs frequently,
+; and this function (alone) should not put the processor into a
+; power savings mode which requeres large amount of time to enter & exit.
+;
+; Return Value:
+;
+;--
+
+cPublicProc _HalProcessorIdle, 0
+
+ ;
+ ; the following code sequence "sti-halt" puts the processor
+ ; into a Halted state, with interrupts enabled, without processing
+ ; an interrupt before halting. The STI instruction has a delay
+ ; slot such that it does not take effect until after the instruction
+ ; following it - this has the effect of HALTing without allowing
+ ; a possible interrupt and then enabling interrupts while HALTed.
+ ;
+
+ ;
+ ; On an MP hal we don't stop the processor, since that causes
+ ; the SNOOP to slow down as well
+ ;
+
+ sti
+
+ifdef NT_UP
+ hlt
+endif
+
+ ;
+ ; Now return to the system. If there's still no work, then it
+ ; will call us back to halt again.
+ ;
+
+ stdRET _HalProcessorIdle
+
+stdENDP _HalProcessorIdle
+
+_TEXT$01 ends
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixinfo.c b/private/ntos/nthals/halx86/i386/ixinfo.c
new file mode 100644
index 000000000..d39fdcc35
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixinfo.c
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+extern WCHAR rgzSuspendCallbackName[];
+
+VOID
+HalInitSystemPhase2 (
+ VOID
+ );
+
+VOID
+HalpLockSuspendCode (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ );
+#endif
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#pragma alloc_text(INIT,HalInitSystemPhase2)
+
+#ifdef _PNP_POWER_
+#pragma alloc_text(PAGE,HalpLockSuspendCode)
+#endif
+
+#endif
+
+
+VOID
+HalInitSystemPhase2 (
+ VOID
+ )
+{
+#ifdef _PNP_POWER_
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ UNICODE_STRING unicodeString;
+ PCALLBACK_OBJECT CallbackObject;
+
+ //
+ // Create hal callbacks
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ NULL,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+
+ ExCreateCallback (&HalCallback.SetSystemInformation, &ObjectAttributes, TRUE, TRUE);
+ ExCreateCallback (&HalCallback.BusCheck, &ObjectAttributes, TRUE, TRUE);
+
+ //
+ // Connect to suspend callback to lock hal hibaration code
+ //
+
+ RtlInitUnicodeString(&unicodeString, rgzSuspendCallbackName);
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = ExCreateCallback (&CallbackObject, &ObjectAttributes, FALSE, FALSE);
+
+ if (NT_SUCCESS(Status)) {
+ ExRegisterCallback (
+ CallbackObject,
+ HalpLockSuspendCode,
+ NULL
+ );
+
+ ObDereferenceObject (CallbackObject);
+ }
+#endif
+}
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+ union {
+ HAL_POWER_INFORMATION PowerInf;
+ HAL_PROCESSOR_SPEED_INFORMATION ProcessorInf;
+ MCA_EXCEPTION McaException;
+ HAL_DISPLAY_BIOS_INFORMATION DisplayBiosInf;
+ } U;
+
+ BOOLEAN bUseFrameBufferCaching;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ case HalFrameBufferCachingInformation:
+
+ // Note - we want to return TRUE here to enable USWC in all
+ // cases except in a "Shared Memory Cluster" machine.
+ bUseFrameBufferCaching = TRUE;
+ InternalBuffer = &bUseFrameBufferCaching;
+ Length = sizeof (BOOLEAN);
+ break;
+
+
+ case HalMcaLogInformation:
+ InternalBuffer = &U.McaException;
+ Status = HalpGetMcaLog (&U.McaException, &Length);
+ break;
+
+ case HalDisplayBiosInformation:
+ InternalBuffer = &U.DisplayBiosInf;
+ Length = sizeof(U.DisplayBiosInf);
+ U.DisplayBiosInf = HalpGetDisplayBiosInformation ();
+ break;
+
+#ifdef _PNP_POWER_
+ case HalPowerInformation:
+ RtlZeroMemory (&U.PowerInf, sizeof(HAL_POWER_INFORMATION));
+
+ InternalBuffer = &U.PowerInf;
+ Length = sizeof (HAL_POWER_INFORMATION);
+ break;
+
+
+ case HalProcessorSpeedInformation:
+ RtlZeroMemory (&U.ProcessorInf, sizeof(HAL_POWER_INFORMATION));
+
+ U.ProcessorInf.MaximumProcessorSpeed = 100;
+ U.ProcessorInf.CurrentAvailableSpeed = 100;
+ U.ProcessorInf.ConfiguredSpeedLimit = 100;
+
+ InternalBuffer = &U.PowerInf;
+ Length = sizeof (HAL_PROCESSOR_SPEED_INFORMATION);
+ break;
+
+ case HalCallbackInformation:
+ InternalBuffer = &HalCallback;
+ Length = sizeof (HAL_CALLBACKS);
+ break;
+#endif
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+
+ switch (InformationClass) {
+
+ case HalMcaRegisterDriver:
+ Status = HalpMcaRegisterDriver(
+ (PMCA_DRIVER_INFO) Buffer // Info about registering driver
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
+
+
+
+#ifdef _PNP_POWER_
+
+VOID
+HalpLockSuspendCode (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ static PVOID CodeLock;
+
+ switch ((ULONG) Argument1) {
+ case 0:
+ //
+ // Lock code down which might be needed to perform a suspend
+ //
+
+ ASSERT (CodeLock == NULL);
+ CodeLock = MmLockPagableCodeSection (&HaliSuspendHibernateSystem);
+ break;
+
+ case 1:
+ //
+ // Release the code lock
+ //
+
+ MmUnlockPagableImageSection (CodeLock);
+ CodeLock = NULL;
+ break;
+ }
+}
+
+#endif
diff --git a/private/ntos/nthals/halx86/i386/ixipi.asm b/private/ntos/nthals/halx86/i386/ixipi.asm
new file mode 100644
index 000000000..3eb733e8c
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixipi.asm
@@ -0,0 +1,188 @@
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixipi.asm
+;
+;Abstract:
+;
+; Provides the HAL support for Interprocessor Interrupts.
+; This is the UP version.
+;
+;Author:
+;
+; John Vert (jvert) 16-Jul-1991
+;
+;Revision History:
+;
+;--
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include i386\ix8259.inc
+
+
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ extrn _HalpDefaultInterruptAffinity:DWORD
+ extrn _HalpActiveProcessors:DWORD
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+INIT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+;Arguments:
+;
+; Number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor ,1
+
+;
+; Initialize PcIDR in PCR to enable slave IRQ
+;
+
+ mov fs:PcIDR, 0fffffffbh
+ mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
+
+ mov eax, dword ptr [esp+4]
+ lock bts _HalpDefaultInterruptAffinity, eax
+ lock bts _HalpActiveProcessors, eax
+
+ stdRET _HalInitializeProcessor
+stdENDP _HalInitializeProcessor
+
+INIT ends
+
+
+_TEXT$03 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to interrupt
+;
+;Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalRequestIpi ,1
+
+if DBG
+ int 3
+endif
+ stdRET _HalRequestIpi
+stdENDP _HalRequestIpi
+
+
+ page ,132
+ subttl "80387 Irq13 Interrupt Handler"
+;++
+;
+; VOID
+; HalpIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; When the 80387 detects an error, it raises its error line. This
+; was supposed to be routed directly to the 386 to cause a trap 16
+; (which would actually occur when the 386 encountered the next FP
+; instruction).
+;
+; However, the ISA design routes the error line to IRQ13 on the
+; slave 8259. So an interrupt will be generated whenever the 387
+; discovers an error.
+;
+; This routine handles that interrupt and passes control to the kernel
+; coprocessor error handler.
+;
+; Arguments:
+;
+; None.
+; Interrupt is disabled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hi13_a, Hi13_t
+
+cPublicProc _HalpIrq13Handler ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+
+ push 13 + PRIMARY_VECTOR_BASE ; Vector
+ sub esp, 4 ; make space for OldIrql
+
+ stdCall _HalBeginSystemInterrupt, <I386_80387_IRQL,13 + PRIMARY_VECTOR_BASE,esp>
+
+ stdCall _KiCoprocessorError ; call CoprocessorError handler
+
+;
+; Clear the busy latch so that the 386 doesn't mistakenly think
+; that the 387 is still busy.
+;
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+ INTERRUPT_EXIT ; will return to caller
+
+stdENDP _HalpIrq13Handler
+
+_TEXT$03 ENDS
+
+ END
diff --git a/private/ntos/nthals/halx86/i386/ixirql.asm b/private/ntos/nthals/halx86/i386/ixirql.asm
new file mode 100644
index 000000000..e18a0ce8b
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixirql.asm
@@ -0,0 +1,1297 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixirql.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the 8259 PIC.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 8-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; John Vert (jvert) 27-Nov-1991
+; Moved from kernel into HAL
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+
+ extrn _HalpApcInterrupt:near
+ extrn _HalpDispatchInterrupt:near
+ extrn _KiUnexpectedInterrupt:near
+ extrn _HalpBusType:DWORD
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+ extrn HalpSpecialDismissLevelTable:dword
+ extrn HalpSpecialDismissTable:dword
+ extrn _HalpEisaELCR:dword
+
+;
+; Initialization control words equates for the PICs
+;
+
+ICW1_ICW4_NEEDED equ 01H
+ICW1_CASCADE equ 00H
+ICW1_INTERVAL8 equ 00H
+ICW1_LEVEL_TRIG equ 08H
+ICW1_EDGE_TRIG equ 00H
+ICW1_ICW equ 10H
+
+ICW4_8086_MODE equ 001H
+ICW4_NORM_EOI equ 000H
+ICW4_NON_BUF_MODE equ 000H
+ICW4_SPEC_FULLY_NESTED equ 010H
+ICW4_NOT_SPEC_FULLY_NESTED equ 000H
+
+OCW2_NON_SPECIFIC_EOI equ 020H
+OCW2_SPECIFIC_EOI equ 060H
+OCW2_SET_PRIORITY equ 0c0H
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+
+;
+; Interrupt flag bit maks for EFLAGS
+;
+
+EFLAGS_IF equ 200H
+EFLAGS_SHIFT equ 9
+
+;
+; Hardware irq active masks
+;
+
+IRQ_ACTIVE_MASK equ 0fffffff0h
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; PICsInitializationString - Master PIC initialization command string
+;
+
+ifdef MCA
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+
+else
+
+PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC1_BASE
+ db 1 SHL PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\
+ ICW1_CASCADE + ICW1_ICW4_NEEDED
+ db PIC2_BASE
+ db PIC_SLAVE_IRQ
+ db ICW4_NOT_SPEC_FULLY_NESTED + \
+ ICW4_NON_BUF_MODE + \
+ ICW4_NORM_EOI + \
+ ICW4_8086_MODE
+ dw 0 ; end of string
+endif
+
+ align 4
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 11111111100000000000000000000000B ; irql 4
+ dd 11111111110000000000000000000000B ; irql 5
+ dd 11111111111000000000000000000000B ; irql 6
+ dd 11111111111100000000000000000000B ; irql 7
+ dd 11111111111110000000000000000000B ; irql 8
+ dd 11111111111111000000000000000000B ; irql 9
+ dd 11111111111111100000000000000000B ; irql 10
+ dd 11111111111111110000000000000000B ; irql 11
+ dd 11111111111111111000000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111110000000000000B ; irql 14
+ dd 11111111111111111111000000000000B ; irql 15
+ dd 11111111111111111111100000000000B ; irql 16
+ dd 11111111111111111111110000000000B ; irql 17
+ dd 11111111111111111111111000000000B ; irql 18
+ dd 11111111111111111111111000000000B ; irql 19
+ dd 11111111111111111111111010000000B ; irql 20
+ dd 11111111111111111111111011000000B ; irql 21
+ dd 11111111111111111111111011100000B ; irql 22
+ dd 11111111111111111111111011110000B ; irql 23
+ dd 11111111111111111111111011111000B ; irql 24
+ dd 11111111111111111111111011111000B ; irql 25
+ dd 11111111111111111111111011111010B ; irql 26
+ dd 11111111111111111111111111111010B ; irql 27
+ dd 11111111111111111111111111111011B ; irql 28
+ dd 11111111111111111111111111111011B ; irql 29
+ dd 11111111111111111111111111111011B ; irql 30
+ dd 11111111111111111111111111111011B ; irql 31
+
+;
+; This table is used to mask all pending interrupts below a given Irql
+; out of the IRR
+;
+ align 4
+
+ public FindHigherIrqlMask
+FindHigherIrqlMask label dword
+ dd 11111111111111111111111111111110B ; irql 0
+ dd 11111111111111111111111111111100B ; irql 1 (APC)
+ dd 11111111111111111111111111111000B ; irql 2 (DISPATCH)
+ dd 11111111111111111111111111110000B ; irql 3
+ dd 00000111111111111111111111110000B ; irql 4
+ dd 00000011111111111111111111110000B ; irql 5
+ dd 00000001111111111111111111110000B ; irql 6
+ dd 00000000111111111111111111110000B ; irql 7
+ dd 00000000011111111111111111110000B ; irql 8
+ dd 00000000001111111111111111110000B ; irql 9
+ dd 00000000000111111111111111110000B ; irql 10
+ dd 00000000000011111111111111110000B ; irql 11
+ dd 00000000000001111111111111110000B ; irql 12
+ dd 00000000000000111111111111110000B ; irql 13
+ dd 00000000000000011111111111110000B ; irql 14
+ dd 00000000000000001111111111110000B ; irql 15
+ dd 00000000000000000111111111110000B ; irql 16
+ dd 00000000000000000011111111110000B ; irql 17
+ dd 00000000000000000001111111110000B ; irql 18
+ dd 00000000000000000001111111110000B ; irql 19
+ dd 00000000000000000001011111110000B ; irql 20
+ dd 00000000000000000001001111110000B ; irql 20
+ dd 00000000000000000001000111110000B ; irql 22
+ dd 00000000000000000001000011110000B ; irql 23
+ dd 00000000000000000001000001110000B ; irql 24
+ dd 00000000000000000001000000110000B ; irql 25
+ dd 00000000000000000001000000010000B ; irql 26
+ dd 00000000000000000000000000010000B ; irql 27
+ dd 00000000000000000000000000000000B ; irql 28
+ dd 00000000000000000000000000000000B ; irql 29
+ dd 00000000000000000000000000000000B ; irql 30
+ dd 00000000000000000000000000000000B ; irql 31
+
+ align 4
+;
+; The following tables define the addresses of software interrupt routers
+;
+
+;
+; Use this table if there is NO machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable
+SWInterruptHandlerTable label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt2 ; irql 2
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
+ dd offset FLAT:HalpHardwareInterrupt00 ; 8259 irq#0
+ dd offset FLAT:HalpHardwareInterrupt01 ; 8259 irq#1
+ dd offset FLAT:HalpHardwareInterrupt02 ; 8259 irq#2
+ dd offset FLAT:HalpHardwareInterrupt03 ; 8259 irq#3
+ dd offset FLAT:HalpHardwareInterrupt04 ; 8259 irq#4
+ dd offset FLAT:HalpHardwareInterrupt05 ; 8259 irq#5
+ dd offset FLAT:HalpHardwareInterrupt06 ; 8259 irq#6
+ dd offset FLAT:HalpHardwareInterrupt07 ; 8259 irq#7
+ dd offset FLAT:HalpHardwareInterrupt08 ; 8259 irq#8
+ dd offset FLAT:HalpHardwareInterrupt09 ; 8259 irq#9
+ dd offset FLAT:HalpHardwareInterrupt10 ; 8259 irq#10
+ dd offset FLAT:HalpHardwareInterrupt11 ; 8259 irq#11
+ dd offset FLAT:HalpHardwareInterrupt12 ; 8259 irq#12
+ dd offset FLAT:HalpHardwareInterrupt13 ; 8259 irq#13
+ dd offset FLAT:HalpHardwareInterrupt14 ; 8259 irq#14
+ dd offset FLAT:HalpHardwareInterrupt15 ; 8259 irq#15
+
+;
+; Use this table if there is already a machine state frame on stack
+;
+
+ public SWInterruptHandlerTable2
+SWInterruptHandlerTable2 label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt2ndEntry ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt2ndEntry ; irql 2
+
+;
+; The following table picks up the highest pending software irq level
+; from software irr
+;
+
+ public SWInterruptLookUpTable
+SWInterruptLookUpTable label byte
+ db 0 ; SWIRR=0, so highest pending SW irql= 0
+ db 0 ; SWIRR=1, so highest pending SW irql= 0
+ db 1 ; SWIRR=2, so highest pending SW irql= 1
+ db 1 ; SWIRR=3, so highest pending SW irql= 1
+ db 2 ; SWIRR=4, so highest pending SW irql= 2
+ db 2 ; SWIRR=5, so highest pending SW irql= 2
+ db 2 ; SWIRR=6, so highest pending SW irql= 2
+ db 2 ; SWIRR=7, so highest pending SW irql= 2
+
+ifdef IRQL_METRICS
+
+ public HalRaiseIrqlCount
+ public HalLowerIrqlCount
+ public HalQuickLowerIrqlCount
+ public HalApcSoftwareIntCount
+ public HalDpcSoftwareIntCount
+ public HalHardwareIntCount
+ public HalPostponedIntCount
+ public Hal8259MaskCount
+
+HalRaiseIrqlCount dd 0
+HalLowerIrqlCount dd 0
+HalQuickLowerIrqlCount dd 0
+HalApcSoftwareIntCount dd 0
+HalDpcSoftwareIntCount dd 0
+HalHardwareIntCount dd 0
+HalPostponedIntCount dd 0
+Hal8259MaskCount dd 0
+
+endif
+_DATA ENDS
+
+ page ,132
+ subttl "Raise Irql"
+
+_TEXT$01 SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; KIRQL
+; KfRaiseIrql (
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to the specified value.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0, 0
+
+ xor eax, eax ; Eliminate partial stall on return to caller
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov PCR[PcIrql], cl ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+
+if DBG
+ cmp al, cl ; old > new?
+ ja short Kri99 ; yes, go bugcheck
+
+ fstRET KfRaiseIrql
+
+cPublicFpo 2, 2
+Kri99:
+ movzx eax, al
+ movzx ecx, cl
+ push ecx ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr PCR[PcIrql],0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+;++
+;
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ xor eax, eax ; Eliminate partial stall
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short Krid99 ; yes, go bugcheck
+endif
+
+ stdRET _KeRaiseIrqlToDpcLevel
+
+if DBG
+cPublicFpo 0,1
+Krid99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+ stdRET _KeRaiseIrqlToDpcLevel
+endif
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+
+;++
+;
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+cPublicFpo 0, 0
+
+ xor eax, eax ; Eliminate partial stall
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, SYNCH_LEVEL ; old > new?
+ ja short Kris99 ; yes, go bugcheck
+endif
+
+ stdRET _KeRaiseIrqlToSynchLevel
+
+if DBG
+cPublicFpo 0,1
+Kris99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+ stdRET _KeRaiseIrqlToSynchLevel
+endif
+
+stdENDP _KeRaiseIrqlToSynchLevel
+
+;++
+;
+; VOID
+; KfLowerIrql (
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall KfLowerIrql,1
+cPublicFpo 0, 0
+ and ecx, 0ffh
+
+ifdef IRQL_METRICS
+ inc HalLowerIrqlCount
+endif
+
+if DBG
+ cmp cl,PCR[PcIrql] ; Make sure we are not lowering to
+ ja KliBug ; ABOVE current level
+endif
+ pushfd
+ cli
+ mov PCR[PcIrql], ecx
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+ jnz short Kli10 ; go dispatch pending interrupts
+
+;
+; no interrupts pending, return quickly.
+;
+
+ popfd
+
+ifdef IRQL_METRICS
+ inc HalQuickLowerIrqlCount
+endif
+ fstRET KfLowerIrql
+
+cPublicFpo 1, 1
+align 4
+Kli10:
+
+;
+; If there is a pending hardware interrupt, then the PICs have been
+; masked to reflect the actual Irql.
+;
+
+ bsr ecx, edx ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ ja short Kli40
+
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+ popfd
+
+cPublicFpo 1, 0
+ fstRET KfLowerIrql
+
+Kli40:
+;
+; Clear all the interrupt masks
+;
+
+ mov eax, PCR[PcIDR]
+ SET_8259_MASK
+
+ mov edx, 1
+ shl edx, cl
+ xor PCR[PcIRR], edx ; clear bit in IRR
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+ popfd
+
+cPublicFpo 1, 0
+ fstRET KfLowerIrql
+
+if DBG
+cPublicFpo 1, 2
+KliBug:
+ push ecx ; new irql for debugging
+ push PCR[PcIrql] ; old irql for debugging
+ mov byte ptr PCR[PcIrql],HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+endif
+
+fstENDP KfLowerIrql
+
+;++
+;
+; VOID
+; HalEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+12 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HeiNewIrql equ [esp + 4]
+
+cPublicProc _HalEndSystemInterrupt ,2
+cPublicFpo 2, 0
+
+ xor ecx, ecx
+ mov cl, byte ptr HeiNewIrql ; get new irql value
+
+ifdef IRQL_METRICS
+ inc HalLowerIrqlCount
+endif
+
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+ mov PCR[PcIrql], ecx
+ jnz short Hei10 ; go dispatch pending interrupts
+
+;
+; no interrupts pending, return quickly.
+;
+
+
+ifdef IRQL_METRICS
+ inc HalQuickLowerIrqlCount
+endif
+ stdRET _HalEndSystemInterrupt
+
+align 4
+Hei10:
+
+;
+; If there is any delayed hardware interrupt being serviced, we leave
+; the interrupt masked and simply return.
+;
+
+ test PCR[PcIrrActive], IRQ_ACTIVE_MASK
+ jnz short Hei50
+
+ bsr ecx, edx ; (eax) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ jle short Hei40
+
+;
+; Clear all the interrupt masks
+;
+
+align 4
+Hei15:
+ mov eax, PCR[PcIDR]
+ SET_8259_MASK
+;
+; The pending interrupt is a hardware interrupt. To prevent the delayed
+; interrupts from overflowing stack, we check if the pending level is already
+; active. If yes, we simply return and let the higher level EndSystemInterrupt
+; handle it.
+;
+; (ecx) = pending vector
+;
+
+ mov edx, 1
+ shl edx, cl
+ test PCR[PcIrrActive], edx ; if the pending int is being
+ ; processed, just return.
+ jne short Hei50
+ or PCR[PcIrrActive], edx ; Set Active bit
+ xor PCR[PcIRR], edx ; clear bit in IRR
+ call SWInterruptHandlerTable[ecx*4] ; Note, it destroys eax
+ xor PCR[PcIrrActive], edx ; Clear bit in ActiveIrql
+ mov eax, PCR[PcIRR] ; Reload IRR
+ mov ecx, PCR[PcIrql]
+ and eax, FindHigherIrqlMask[ecx*4] ; Is any interrupt pending
+ jz short Hei50 ; (Most time it will be zero.)
+ bsr ecx, eax ; (edx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ ja short Hei15
+
+Hei40:
+
+;
+; The pending interrupt is at Software Level. We simply make current
+; interrupt frame the new pending software interrupt's frame and
+; jmp to the handler routine.
+;
+
+ add esp, 12
+ jmp SWInterruptHandlerTable2[ecx*4] ; Note, it destroys eax
+
+
+Hei50:
+ stdRET _HalEndSystemInterrupt
+
+stdENDP _HalEndSystemInterrupt
+
+;++
+;
+; VOID
+; HalpEndSoftwareInterrupt
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL from software interrupt
+; leverl to the specified value.
+; The IRQL and PIRQL will be updated accordingly. Also, this
+; routine checks to see if any software interrupt should be
+; generated. The following condition will cause software
+; interrupt to be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; NewIrql - the new irql to be set.
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HesNewIrql equ [esp + 4]
+
+cPublicProc _HalpEndSoftwareInterrupt ,1
+cPublicFpo 1, 0
+
+ movzx ecx, byte ptr HesNewIrql ; get new irql value
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+ mov PCR[PcIrql], ecx
+ jnz short Hes10
+
+ stdRET _HalpEndSoftwareInterrupt
+
+align 4
+Hes10:
+;
+; Check if any delayed hardware interrupt is being serviced. If yes, we
+; simply return.
+;
+
+ test PCR[PcIrrActive], IRQ_ACTIVE_MASK
+ jnz short Hes90
+
+;
+; If there is a pending hardware interrupt, then the PICs have been
+; masked to reflect the actual Irql.
+;
+
+ bsr ecx, edx ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ ja short Hes20
+
+;
+; Pending interrupt is a soft interrupt. Recycle stack frame
+;
+
+ add esp, 8
+ jmp SWInterruptHandlerTable2[ecx*4] ; Note, it destroys eax
+
+Hes20:
+;
+; Clear all the interrupt masks
+;
+
+ mov eax, PCR[PcIDR]
+ SET_8259_MASK
+
+;
+; (ecx) = Pending level
+;
+
+ mov edx, 1
+ shl edx, cl
+
+ or PCR[PcIrrActive], edx ; Set Active bit
+ xor PCR[PcIRR], edx ; clear bit in IRR
+
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+
+ xor PCR[PcIrrActive], edx ; Clear bit in ActiveIrql
+
+ movzx ecx, byte ptr HesNewIrql ; get new irql value
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+ jnz short Hes10
+
+Hes90: stdRET _HalpEndSoftwareInterrupt
+
+stdENDP _HalpEndSoftwareInterrupt
+
+ page ,132
+ subttl "DispatchInterrupt 2"
+
+;++
+;
+; VOID
+; HalpDispatchInterrupt2(
+; VOID
+; );
+;
+; Routine Description:
+;
+; The functional description is the same as HalpDispatchInterrupt.
+;
+; This function differs from HalpDispatchInterrupt in how it has been
+; optimized. This function is optimized for dispatching dispatch interrupts
+; for LowerIrql, ReleaseSpinLock, and RequestSoftwareInterrupt.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; (edx) = 1 shl DISPATCH_LEVEL
+;
+; Warnings:
+;
+; Not all SW int handles this hal uses save all the registers
+; callers to SWInterruptHandler for H/W interrupts assume that
+; ONLY EAX & ECX are destroyed.
+;
+; Note: this function saves EBX since KiDispatchInterrupt uses
+; the value without preserving it.
+;--
+
+cPublicProc _HalpDispatchInterrupt2
+cPublicFpo 0, 2
+
+ xor ecx, ecx
+ and dword ptr PCR[PcIRR], not (1 shl DISPATCH_LEVEL) ; clear the pending bit in IRR
+
+ mov cl, PCR[PcIrql]
+
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
+ push ecx ; Save OldIrql
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+ sti
+
+ push ebx
+ stdCall _KiDispatchInterrupt ; Handle DispatchInterrupt
+ pop ebx
+ pop ecx ; (ecx) = OldIrql
+ mov edx, 1 shl DISPATCH_LEVEL
+
+ cli
+
+ mov eax, PCR[PcIRR]
+ mov PCR[PcIrql], ecx ; restore current irql
+
+ and eax, FindHigherIrqlMask[ecx*4] ; (eax) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+
+ jnz short diq10 ; go dispatch pending interrupts
+ stdRET _HalpDispatchInterrupt2
+
+diq10:
+;
+; If there is a pending hardware interrupt, then the PICs have been
+; masked to reflect the actual Irql.
+;
+
+ bsr ecx, eax ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ jbe short diq20
+
+;
+; Clear all the interrupt masks
+;
+
+ mov eax, PCR[PcIDR]
+ SET_8259_MASK
+
+ mov edx, 1
+ shl edx, cl
+ xor PCR[PcIRR], edx ; clear bit in IRR
+
+diq20:
+;
+; (ecx) = Pending level
+;
+
+ jmp SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+diq90: stdRET _HalpDispatchInterrupt2
+
+stdENDP _HalpDispatchInterrupt2
+
+ page ,132
+ subttl "Get current irql"
+
+;++
+;
+; KIRQL
+; KeGetCurrentIrql (VOID)
+;
+; Routine Description:
+;
+; This routine returns to current IRQL.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The current IRQL.
+;
+;--
+
+cPublicProc _KeGetCurrentIrql ,0
+cPublicFpo 0, 0
+
+ movzx eax, byte ptr PCR[PcIrql] ; Current irql is in the PCR
+ stdRET _KeGetCurrentIrql
+stdENDP _KeGetCurrentIrql
+
+
+
+;++
+;
+; VOID
+; HalpDisableAllInterrupts (VOID)
+;
+; Routine Description:
+;
+; This routine is called during a system crash. The hal needs all
+; interrupts disabled.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None - all interrupts are masked off
+;
+;--
+
+cPublicProc _HalpDisableAllInterrupts,0
+cPublicFpo 0, 0
+
+ ;
+ ; Mask interrupts off at PIC
+ ; (raising to high_level does not work on lazy irql implementation)
+ ;
+ mov eax, KiI8259MaskTable[HIGH_LEVEL*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+ mov byte ptr PCR[PcIrql], HIGH_LEVEL ; set new irql
+
+ stdRET _HalpDisableAllInterrupts
+
+stdENDP _HalpDisableAllInterrupts
+
+ page ,132
+ subttl "Postponed Hardware Interrupt Dispatcher"
+;++
+;
+; VOID
+; HalpHardwareInterruptNN (
+; VOID
+; );
+;
+; Routine Description:
+;
+; These routines branch through the IDT to simulate the appropriate
+; hardware interrupt. They use the "INT nn" instruction to do this.
+;
+; Arguments:
+;
+; None.
+;
+; Returns:
+;
+; None.
+;
+; Environment:
+;
+; IRET frame is on the stack
+;
+;--
+cPublicProc _HalpHardwareInterruptTable, 0
+cPublicFpo 0,0
+
+ public HalpHardwareInterrupt00
+HalpHardwareInterrupt00 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 0
+ ret
+
+ public HalpHardwareInterrupt01
+HalpHardwareInterrupt01 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 1
+ ret
+
+ public HalpHardwareInterrupt02
+HalpHardwareInterrupt02 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 2
+ ret
+
+ public HalpHardwareInterrupt03
+HalpHardwareInterrupt03 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 3
+ ret
+
+ public HalpHardwareInterrupt04
+HalpHardwareInterrupt04 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 4
+ ret
+
+ public HalpHardwareInterrupt05
+HalpHardwareInterrupt05 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 5
+ ret
+
+ public HalpHardwareInterrupt06
+HalpHardwareInterrupt06 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 6
+ ret
+
+ public HalpHardwareInterrupt07
+HalpHardwareInterrupt07 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 7
+ ret
+
+ public HalpHardwareInterrupt08
+HalpHardwareInterrupt08 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 8
+ ret
+
+ public HalpHardwareInterrupt09
+HalpHardwareInterrupt09 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 9
+ ret
+
+ public HalpHardwareInterrupt10
+HalpHardwareInterrupt10 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 10
+ ret
+
+ public HalpHardwareInterrupt11
+HalpHardwareInterrupt11 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 11
+ ret
+
+ public HalpHardwareInterrupt12
+HalpHardwareInterrupt12 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 12
+ ret
+
+ public HalpHardwareInterrupt13
+HalpHardwareInterrupt13 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 13
+ ret
+
+ public HalpHardwareInterrupt14
+HalpHardwareInterrupt14 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 14
+ ret
+
+ public HalpHardwareInterrupt15
+HalpHardwareInterrupt15 label byte
+ifdef IRQL_METRICS
+ lock inc HalHardwareIntCount
+endif
+ int PRIMARY_VECTOR_BASE + 15
+ ret
+
+ public HalpHardwareInterruptLevel
+HalpHardwareInterruptLevel label byte
+cPublicFpo 0,0
+ xor eax, eax
+ mov al, PCR[PcIrql]
+ mov ecx, PCR[PcIRR]
+ and ecx, FindHigherIrqlMask[eax*4] ; (ecx) is the bitmask of
+ ; pending interrupts we need to
+ ; dispatch now.
+ jz short lvl_90 ; no pending ints
+
+ test PCR[PcIrrActive], IRQ_ACTIVE_MASK
+ jnz short lvl_90 ; let guy furture down the stack handle it
+
+ mov eax, ecx ; (eax) = bitmask
+ bsr ecx, eax ; (cl) = set bit
+
+ mov eax, 1
+ shl eax, cl
+ xor PCR[PcIRR], eax ; clear bit in IRR
+
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+align 4
+lvl_90:
+ ret
+
+stdENDP _HalpHardwareInterruptTable
+
+
+_TEXT$01 ends
+
+ page ,132
+ subttl "Interrupt Controller Chip Initialization"
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+;++
+;
+; VOID
+; HalpInitializePICs (
+; )
+;
+; Routine Description:
+;
+; This routine sends the 8259 PIC initialization commands and
+; masks all the interrupts on 8259s.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializePICs ,0
+cPublicFpo 0, 0
+
+ push esi ; save caller's esi
+ cli ; disable interrupt
+ lea esi, PICsInitializationString
+ lodsw ; (AX) = PIC port 0 address
+Hip10: movzx edx, ax
+ outsb ; output ICW1
+ IODelay
+ inc edx ; (DX) = PIC port 1 address
+ outsb ; output ICW2
+ IODelay
+ outsb ; output ICW3
+ IODelay
+ outsb ; output ICW4
+ IODelay
+ mov al, 0FFH ; mask all 8259 irqs
+ out dx,al ; write mask to PIC
+ lodsw
+ cmp ax, 0 ; end of init string?
+ jne short Hip10 ; go init next PIC
+
+;
+; Read EISA defined ELCR. If it looks good save it away.
+; If a PCI interrupts is later connected, the vector will
+; be assumed level if it's in the ELCR.
+;
+ mov edx, 4d1h ; Eisa Edge/Level port
+ in al, dx ; get e/l irq 8-f
+ mov ah, al
+ dec edx
+ in al, dx ; get e/l irq 0-7
+ and eax, 0def8h ; clear reserved bits
+ cmp eax, 0def8h ; all set?
+ je short Hip50 ; Yes, register not implemented
+
+ mov _HalpEisaELCR, eax ; Save possible ELCR settings
+
+
+;
+; If this is an EISA machine, mark all interrupts in the EISA ELCR
+; as level interrupts
+;
+ cmp _HalpBusType, MACHINE_TYPE_EISA
+ jne short Hip50
+
+;
+; Verify this isn't an OPTI chipset machine which claims to be
+; EISA, but neglects to follow the EISA spec...
+;
+
+ mov edx, 0481h ; DmaPageHighPort.Channel2
+ mov al, 055h
+ out dx, al ; out to Eisa DMA register
+ in al, dx ; read it back
+ cmp al, 055h ; if it doesn't stick, then machine
+ jne short Hip50 ; isn't support all eisa registers
+
+;
+; Ok - loop and mark all EISA level interrupts
+;
+
+ mov eax, _HalpEisaELCR
+ xor ecx, ecx ; start at irq 0
+Hip30:
+ test eax, 1 ; is level bit set?
+ jz short Hip40 ; no, go to next
+
+;
+; Found a level sensitive interrupt:
+; Set the SWInterruptHandler for the irql to be a NOP.
+; Set the SpecialDismiss entry for the irq to be the level version
+;
+ mov SWInterruptHandlerTable+4*4[ecx], offset HalpHardwareInterruptLevel
+
+ mov edx, HalpSpecialDismissLevelTable[ecx]
+ mov HalpSpecialDismissTable[ecx], edx
+
+Hip40:
+ add ecx, 4 ; next vector
+ shr eax, 1 ; shift bits down
+ jnz short Hip30 ; more set bits, then loop
+
+
+Hip50:
+ pop esi ; restore caller's esi
+ sti ; enable interrupt
+ stdRET _HalpInitializePICs
+stdENDP _HalpInitializePICs
+
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixisa.h b/private/ntos/nthals/halx86/i386/ixisa.h
new file mode 100644
index 000000000..1389962b9
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixisa.h
@@ -0,0 +1,110 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixisa.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ EISA/ISA specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+Revision History:
+
+--*/
+
+#ifndef _IXISA_
+#define _IXISA_
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IgnoreCount;
+ BOOLEAN Dma32BitAddresses;
+} ADAPTER_OBJECT;
+
+#endif // _IXISA_
diff --git a/private/ntos/nthals/halx86/i386/ixisabus.c b/private/ntos/nthals/halx86/i386/ixisabus.c
new file mode 100644
index 000000000..57d9348f1
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixisabus.c
@@ -0,0 +1,640 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
+#pragma alloc_text(PAGE,HalpGetEisaData)
+#endif
+
+
+ULONG
+HalpGetEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ //
+ // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
+ // up on IRQ 9.
+ //
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+BOOLEAN
+HalpTranslateIsaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's memory space
+ // then we allow the translation as it would occur on it's
+ // corrisponding EISA bus. We're allowing this because
+ // many VLBus drivers are claiming to be ISA devices.
+ // (yes, they should claim to be VLBus devices, but VLBus is
+ // run by video cards and like everything else about video
+ // there's no hope of fixing it. (At least according to
+ // Andre))
+ //
+
+ if (Status == FALSE && *AddressSpace == 0) {
+ Status = HalTranslateBusAddress (
+ Eisa,
+ BusHandler->BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's in the 640k - 1m
+ // range then (for compatibility) try translating it on the
+ // Internal bus for
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 0 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0xA0000 &&
+ BusAddress.LowPart < 0xFFFFF) {
+
+ Status = HalTranslateBusAddress (
+ Internal,
+ 0,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ PAGED_CODE ();
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
diff --git a/private/ntos/nthals/halx86/i386/ixisasup.c b/private/ntos/nthals/halx86/i386/ixisasup.c
new file mode 100644
index 000000000..cc4effc4f
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixisasup.c
@@ -0,0 +1,1980 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalGetAdapter)
+#endif
+
+//
+// The HalpNewAdapter event is used to serialize allocations
+// of new adapter objects, additions to the HalpEisaAdapter
+// array, and some global values (MasterAdapterObject) and some
+// adapter fields modified by HalpGrowMapBuffers.
+// (AdapterObject->NumberOfMapRegisters is assumed not to be
+// growable while this even is held)
+//
+// Note: We don't really need our own an event object for this.
+//
+
+#define HalpNewAdapter HalpBusDatabaseEvent
+extern KEVENT HalpNewAdapter;
+
+PVOID HalpEisaControlBase;
+extern KSPIN_LOCK HalpSystemHardwareLock;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+PHYSICAL_ADDRESS
+HalpMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpMapTransferHelper(
+ IN PMDL Mdl,
+ IN PVOID CurrentVa,
+ IN ULONG TransferLength,
+ IN PULONG PageFrame,
+ IN OUT PULONG Length
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. This field
+ will be updated to reflect the actual number of registers allocated
+ when the number is less than what was requested.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+ UCHAR DataByte;
+
+ PAGED_CODE();
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescriptor->Version > DEVICE_DESCRIPTION_VERSION1) {
+ return( NULL );
+ }
+
+#if DBG
+ if (DeviceDescriptor->Version == DEVICE_DESCRIPTION_VERSION1) {
+ ASSERT (DeviceDescriptor->Reserved1 == FALSE);
+ ASSERT (DeviceDescriptor->Reserved2 == FALSE);
+ }
+#endif
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Support for ISA local bus machines:
+ // If the driver is a Master but really does not want a channel since it
+ // is using the local bus DMA, just don't use an ISA channel.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->DmaChannel > 7) {
+
+ useChannel = FALSE;
+ }
+
+ //
+ // Determine if Eisa DMA is supported.
+ //
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+
+ WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2, 0x55);
+ DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2);
+
+ if (DataByte == 0x55) {
+ HalpEisaDma = TRUE;
+ }
+
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa ||
+ DeviceDescriptor->InterfaceType == PCIBus) ) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!HalpEisaDma &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Serialize before allocating a new adapter
+ //
+
+ KeWaitForSingleObject (
+ &HalpNewAdapter,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+
+ //
+ // Determine if a new adapter object has already been allocated.
+ // If so use it, otherwise allocate a new adapter object
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+ KeSetEvent (&HalpNewAdapter, 0, FALSE);
+ return(NULL);
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ KeSetEvent (&HalpNewAdapter, 0, FALSE);
+
+ }
+
+ adapterObject->IgnoreCount = FALSE;
+ if (DeviceDescriptor->Version >= DEVICE_DESCRIPTION_VERSION1) {
+
+ //
+ // Move version 1 structure flags.
+ // IgnoreCount is used on machines where the DMA Counter
+ // is broken. (Namely PS/1 model 1000s). Setting this
+ // bit informs the hal not to rely on the DmaCount to determine
+ // how much data was DMAed.
+ //
+
+ adapterObject->IgnoreCount = DeviceDescriptor->IgnoreCount;
+ }
+
+ adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (HalpEisaDma) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_PORT_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ ULONG transferLength;
+ PHYSICAL_ADDRESS returnAddress;
+ PULONG pageFrame;
+ ULONG pageOffset;
+
+ //
+ // If the adapter is a 32-bit bus master, take the fast path,
+ // otherwise call HalpMapTransfer for the slow path
+ //
+
+ if (MapRegisterBase == NULL) {
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous
+ //
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ //
+ // Compute the starting address of the transfer
+ //
+ returnAddress.QuadPart = (ULONGLONG)( (*pageFrame << PAGE_SHIFT) + pageOffset);
+
+ //
+ // If the transfer is not completely contained within
+ // a page, call the helper to compute the appropriate
+ // length.
+ //
+ if (transferLength < *Length) {
+ HalpMapTransferHelper(Mdl, CurrentVa, transferLength, pageFrame, Length);
+ }
+ return(returnAddress);
+ }
+
+ return(HalpMapTransfer(AdapterObject,
+ Mdl,
+ MapRegisterBase,
+ CurrentVa,
+ Length,
+ WriteToDevice));
+
+}
+
+
+VOID
+HalpMapTransferHelper(
+ IN PMDL Mdl,
+ IN PVOID CurrentVa,
+ IN ULONG TransferLength,
+ IN PULONG PageFrame,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ Helper routine for bus master transfers that cross a page
+ boundary. This routine is separated out from the IoMapTransfer
+ fast path in order to minimize the total instruction path
+ length taken for the common network case where the entire
+ buffer being mapped is contained within one page.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ TransferLength = Supplies the current transferLength
+
+ PageFrame - Supplies a pointer to the starting page frame of the transfer
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+Return Value:
+
+ None. *Length will be updated
+
+--*/
+
+{
+ do {
+ if (*PageFrame + 1 != *(PageFrame + 1)) {
+ break;
+ }
+ TransferLength += PAGE_SIZE;
+ PageFrame++;
+
+ } while ( TransferLength < *Length );
+
+
+ //
+ // Limit the Length to the maximum TransferLength.
+ //
+
+ if (TransferLength < *Length) {
+ *Length = TransferLength;
+ }
+}
+
+
+PHYSICAL_ADDRESS
+HalpMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous and does not cross a 64 K bountry then
+ // just extend the buffer. The 64 K bountry restriction does not apply
+ // to Eisa systems.
+ //
+
+ if (HalpEisaDma) {
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ } else {
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1) ||
+ (*pageFrame & ~0x0f) != (*(pageFrame + 1) & ~0x0f)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+ }
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ ASSERT(MapRegisterBase != NULL);
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+ if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ if (WriteToDevice) {
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) WRITE_TRANSFER;
+ } else {
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) READ_TRANSFER;
+
+ if (AdapterObject->IgnoreCount) {
+ //
+ // When the DMA is over there will be no way to tell how much
+ // data was transfered, so the entire transfer length will be
+ // copied. To ensure that no stale data is returned to the
+ // caller zero the buffer before hand.
+ //
+
+ RtlZeroMemory (
+ (PUCHAR) translationEntry[index].VirtualAddress + pageOffset,
+ transferLength
+ );
+ }
+ }
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpEisaDma) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpEisaDma) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KfReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice && !AdapterObject->IgnoreCount) {
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // If this is a 16 bit dma the multiply the count by 2.
+ //
+
+ if (AdapterObject->Width16Bits) {
+
+ count *= 2;
+
+ }
+
+ return(count);
+}
diff --git a/private/ntos/nthals/halx86/i386/ixkdcom.c b/private/ntos/nthals/halx86/i386/ixkdcom.c
new file mode 100644
index 000000000..644d3590b
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixkdcom.c
@@ -0,0 +1,684 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixkdcom.c
+
+Abstract:
+
+ This module contains a very simply package to do com I/O on machines
+ with standard AT com-ports. It is C code derived from the debugger's
+ com code. Likely does not work on a PS/2. (Only rewrote the thing
+ into C so we wouldn't have to deal with random debugger macros.)
+
+ Procedures to init a com object, set and query baud rate, output
+ character, input character.
+
+Author:
+
+ Bryan M. Willman (bryanwi) 24-Sep-1990
+
+Revision History:
+
+ John Vert (jvert) 12-Jun-1991
+ Added ability to check for com-port's existence and hook onto the
+ highest com-port available.
+
+ John Vert (jvert) 19-Jul-1991
+ Moved into HAL
+
+--*/
+
+#include "halp.h"
+#include "ixkdcom.h"
+#define TIMEOUT_COUNT 1024 * 200
+
+UCHAR CpReadLsr (PCPPORT, UCHAR);
+
+extern BOOLEAN HalpOwnsDisplay;
+static UCHAR LastLsr, LastMsr;
+
+
+VOID
+CpInitialize (
+ PCPPORT Port,
+ PUCHAR Address,
+ ULONG Rate
+ )
+
+/*++
+
+ Routine Description:
+
+ Fill in the com port port object, set the initial baud rate,
+ turn on the hardware.
+
+ Arguments:
+
+ Port - address of port object
+
+ Address - port address of the com port
+ (CP_COM1_PORT, CP_COM2_PORT)
+
+ Rate - baud rate (CP_BD_150 ... CP_BD_19200)
+
+--*/
+
+{
+ PUCHAR hwport;
+ UCHAR mcr, ier;
+
+ Port->Address = Address;
+ Port->Baud = 0;
+
+ CpSetBaud(Port, Rate);
+
+ //
+ // Assert DTR, RTS.
+ //
+
+ hwport = Port->Address;
+ hwport += COM_MCR;
+
+ mcr = MC_DTRRTS;
+ WRITE_PORT_UCHAR(hwport, mcr);
+
+ hwport = Port->Address;
+ hwport += COM_IEN;
+
+ ier = 0;
+ WRITE_PORT_UCHAR(hwport, ier);
+
+}
+
+
+
+
+VOID
+CpSetBaud (
+ PCPPORT Port,
+ ULONG Rate
+ )
+
+/*++
+
+ Routine Description:
+
+ Set the baud rate for the port and record it in the port object.
+
+ Arguments:
+
+ Port - address of port object
+
+ Rate - baud rate (CP_BD_150 ... CP_BD_56000)
+
+--*/
+
+{
+ ULONG divisorlatch;
+ PUCHAR hwport;
+ UCHAR lcr;
+
+ //
+ // compute the divsor
+ //
+
+ divisorlatch = CLOCK_RATE / Rate;
+
+ //
+ // set the divisor latch access bit (DLAB) in the line control reg
+ //
+
+ hwport = Port->Address;
+ hwport += COM_LCR; // hwport = LCR register
+
+ lcr = READ_PORT_UCHAR(hwport);
+
+ lcr |= LC_DLAB;
+ WRITE_PORT_UCHAR(hwport, lcr);
+
+ //
+ // set the divisor latch value.
+ //
+
+ hwport = Port->Address;
+ hwport += COM_DLM; // divisor latch msb
+ WRITE_PORT_UCHAR(hwport, (UCHAR)((divisorlatch >> 8) & 0xff));
+
+ hwport--; // divisor latch lsb
+ WRITE_PORT_UCHAR(hwport, (UCHAR)(divisorlatch & 0xff));
+
+
+ //
+ // Set LCR to 3. (3 is a magic number in the original assembler)
+ //
+
+ hwport = Port->Address;
+ hwport += COM_LCR;
+ WRITE_PORT_UCHAR(hwport, 3);
+
+
+ //
+ // Remember the baud rate
+ //
+
+ Port->Baud = Rate;
+}
+
+
+
+USHORT
+CpQueryBaud (
+ PCPPORT Port
+ )
+
+/*++
+
+ Routine Description:
+
+ Return the last value baud rate was set to.
+
+ Arguments:
+
+ Port - address of cpport object which describes the hw port of interest.
+
+ Return Value:
+
+ Baud rate. 0 = none has been set.
+
+--*/
+
+{
+ return (USHORT) Port->Baud;
+}
+
+VOID
+CpSendModemString (
+ PCPPORT Port,
+ IN PUCHAR String
+ )
+/*++
+
+ Routine Description:
+
+ Sends a command string to the modem.
+ This is down in order to aid the modem in determining th
+ baud rate the local connect is at.
+
+ Arguments:
+
+ Port - Address of CPPORT
+ String - String to send to modem
+
+--*/
+{
+ static ULONG Delay;
+ TIME_FIELDS CurrentTime;
+ UCHAR i;
+ ULONG l;
+
+ if (Port->Flags & PORT_SENDINGSTRING)
+ return ;
+
+ Port->Flags |= PORT_SENDINGSTRING;
+ if (!Delay) {
+ // see how long 1 second is
+ HalQueryRealTimeClock (&CurrentTime);
+ l = CurrentTime.Second;
+ while (l == (ULONG) CurrentTime.Second) {
+ CpReadLsr(Port, 0);
+ HalQueryRealTimeClock (&CurrentTime);
+ Delay++;
+ }
+ Delay = Delay / 3;
+ }
+
+ l = Delay;
+ while (*String) {
+ HalQueryRealTimeClock (&CurrentTime);
+ i = CpReadLsr (Port, 0);
+ if (i & COM_OUTRDY) {
+ if ((--l) == 0) {
+ WRITE_PORT_UCHAR(Port->Address+COM_DAT, *String);
+ String++;
+ l = Delay;
+ }
+ }
+ if (i & COM_DATRDY)
+ READ_PORT_UCHAR(Port->Address + COM_DAT);
+ }
+ Port->Flags &= ~PORT_SENDINGSTRING;
+}
+
+UCHAR
+CpReadLsr (
+ PCPPORT Port,
+ UCHAR waiting
+ )
+
+/*++
+
+ Routine Description:
+
+ Read LSR byte from specified port. If HAL owns port & display
+ it will also cause a debug status to be kept up to date.
+
+ Handles entering & exiting modem control mode for debugger.
+
+ Arguments:
+
+ Port - Address of CPPORT
+
+ Returns:
+
+ Byte read from port
+
+--*/
+{
+ static UCHAR ringflag = 0;
+ static UCHAR diagout[3];
+ static ULONG diagmsg[3] = { 'TRP ', 'LVO ', 'MRF ' };
+ static UCHAR ModemString[] = "\n\rAT\n\r";
+ TIME_FIELDS CurrentTime;
+ UCHAR lsr, msr, i;
+ ULONG diagstr[12];
+
+ lsr = READ_PORT_UCHAR(Port->Address + COM_LSR);
+
+ if (lsr & COM_PE)
+ diagout[0] = 8; // Parity error
+
+ if (lsr & COM_OE)
+ diagout[1] = 8; // Overflow error
+
+ if (lsr & COM_FE)
+ diagout[2] = 8; // Framing error
+
+ if (lsr & waiting) {
+ LastLsr = ~COM_DATRDY | (lsr & COM_DATRDY);
+ return lsr;
+ }
+
+ msr = READ_PORT_UCHAR (Port->Address + COM_MSR);
+
+ if (Port->Flags & PORT_MODEMCONTROL) {
+ if (msr & SERIAL_MSR_DCD) {
+
+ //
+ // In modem control mode with carrier detect
+ // Reset carrier lost time
+ //
+
+ Port->Flags |= PORT_NOCDLTIME | PORT_MDM_CD;
+
+ } else {
+
+ //
+ // In modem control mode, but no carrier detect. After
+ // 60 seconds drop out of modem control mode
+ //
+
+ if (Port->Flags & PORT_NOCDLTIME) {
+ HalQueryRealTimeClock (&Port->CarrierLostTime);
+ Port->Flags &= ~PORT_NOCDLTIME;
+ ringflag = 0;
+ }
+
+ HalQueryRealTimeClock (&CurrentTime);
+ if (CurrentTime.Minute != Port->CarrierLostTime.Minute &&
+ CurrentTime.Second >= Port->CarrierLostTime.Second) {
+
+ //
+ // It's been at least 60 seconds - drop out of
+ // modem control mode until next RI
+ //
+
+ Port->Flags &= ~PORT_MODEMCONTROL;
+ CpSendModemString (Port, ModemString);
+ }
+
+ if (Port->Flags & PORT_MDM_CD) {
+
+ //
+ // We had a connection - if it's the connection has been
+ // down for a few seconds, then send a string to the modem
+ //
+
+ if (CurrentTime.Second < Port->CarrierLostTime.Second)
+ CurrentTime.Second += 60;
+
+ if (CurrentTime.Second > Port->CarrierLostTime.Second + 10) {
+ Port->Flags &= ~PORT_MDM_CD;
+ CpSendModemString (Port, ModemString);
+ }
+ }
+ }
+ }
+
+ if ((lsr == LastLsr && msr == LastMsr) || !(Port->Flags & PORT_SAVED))
+ return lsr;
+
+ ringflag |= (msr & SERIAL_MSR_RI) ? 1 : 2;
+ if (ringflag == 3) {
+
+ //
+ // The ring indicate line has toggled
+ // Use modem control from now on
+ //
+
+ ringflag = 0;
+ Port->Flags |= PORT_MODEMCONTROL | PORT_NOCDLTIME;
+ Port->Flags &= ~PORT_MDM_CD;
+
+ if (Port->Flags & PORT_DEFAULTRATE && Port->Baud != BD_9600) {
+
+ //
+ // Baud rate was never specified switch
+ // to 9600 baud as default (for modem usage).
+ //
+
+ HalDisplayString (MSG_DEBUG_9600);
+ CpSetBaud (Port, BD_9600);
+ //Port->Flags |= PORT_DISBAUD;
+ }
+ }
+
+ for (i=0; i < 3; i++) {
+ if (diagout[i]) {
+ diagout[i]--;
+ diagstr[10-i] = diagmsg[i];
+ } else {
+ diagstr[10-i] = ' ';
+ }
+ }
+
+ diagstr[7] = (LastLsr & COM_DATRDY) ? 'VCR ' : ' ';
+ diagstr[6] = (lsr & COM_OUTRDY) ? ' ' : 'DNS ';
+ diagstr[5] = (msr & 0x10) ? 'STC ' : ' ';
+ diagstr[4] = (msr & 0x20) ? 'RSD ' : ' ';
+ diagstr[3] = (msr & 0x40) ? ' IR ' : ' ';
+ diagstr[2] = (msr & 0x80) ? ' DC ' : ' ';
+ diagstr[1] = (Port->Flags & PORT_MODEMCONTROL) ? 'MDM ' : ' ';
+ diagstr[0] = ' ';
+#if 0
+ if (Port->Flags & PORT_DISBAUD) {
+ switch (Port->Baud) {
+ case BD_9600: diagstr[0] = ' 69 '; break;
+ case BD_14400: diagstr[0] = 'K41 '; break;
+ case BD_19200: diagstr[0] = 'K91 '; break;
+ case BD_56000: diagstr[0] = 'K65 '; break;
+ }
+ }
+#endif
+
+ HalpDisplayDebugStatus ((PUCHAR) diagstr, 11*4);
+ LastLsr = lsr;
+ LastMsr = msr;
+ return lsr;
+}
+
+
+
+
+VOID
+CpPutByte (
+ PCPPORT Port,
+ UCHAR Byte
+ )
+
+/*++
+
+ Routine Description:
+
+ Write a byte out to the specified com port.
+
+ Arguments:
+
+ Port - Address of CPPORT object
+
+ Byte - data to emit
+
+--*/
+
+{
+ UCHAR msr, lsr;
+
+ //
+ // If modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ while ((Port->Flags & PORT_MODEMCONTROL) &&
+ (msr = READ_PORT_UCHAR(Port->Address + COM_MSR) & MS_DSRCTSCD) != MS_DSRCTSCD) {
+
+ //
+ // If no CD, and there's a charactor ready, eat it
+ //
+
+ lsr = CpReadLsr (Port, 0);
+ if ((msr & MS_CD) == 0 && (lsr & COM_DATRDY) == COM_DATRDY) {
+ READ_PORT_UCHAR(Port->Address + COM_DAT);
+ }
+ }
+
+ //
+ // Wait for port to not be busy
+ //
+
+ while (!(CpReadLsr(Port, COM_OUTRDY) & COM_OUTRDY)) ;
+
+ //
+ // Send the byte
+ //
+
+ WRITE_PORT_UCHAR(Port->Address + COM_DAT, Byte);
+}
+
+USHORT
+CpGetByte (
+ PCPPORT Port,
+ PUCHAR Byte,
+ BOOLEAN WaitForByte
+ )
+
+/*++
+
+ Routine Description:
+
+ Fetch a byte and return it.
+
+ Arguments:
+
+ Port - address of port object that describes hw port
+
+ Byte - address of variable to hold the result
+
+ WaitForByte - flag indicates wait for byte or not.
+
+ Return Value:
+
+ CP_GET_SUCCESS if data returned.
+
+ CP_GET_NODATA if no data available, but no error.
+
+ CP_GET_ERROR if error (overrun, parity, etc.)
+
+--*/
+
+{
+ UCHAR lsr;
+ UCHAR value;
+ ULONG limitcount;
+
+ //
+ // Make sure DTR and CTS are set
+ //
+ // (What does CTS have to do with reading from a full duplex line???)
+
+
+ //
+ // Check to make sure the CPPORT we were passed has been initialized.
+ // (The only time it won't be initialized is when the kernel debugger
+ // is disabled, in which case we just return.)
+ //
+ if (Port->Address == NULL) {
+ return(CP_GET_NODATA);
+ }
+
+ limitcount = WaitForByte ? TIMEOUT_COUNT : 1;
+ while (limitcount != 0) {
+ limitcount--;
+
+ lsr = CpReadLsr(Port, COM_DATRDY);
+ if ((lsr & COM_DATRDY) == COM_DATRDY) {
+
+ //
+ // Check for errors
+ //
+ if (lsr & (COM_FE | COM_PE | COM_OE)) {
+ *Byte = 0;
+ return(CP_GET_ERROR);
+ }
+
+ //
+ // fetch the byte
+ //
+
+ value = READ_PORT_UCHAR(Port->Address + COM_DAT);
+
+ if (Port->Flags & PORT_MODEMCONTROL) {
+
+ //
+ // Using modem control. If no CD, then skip this byte.
+ //
+
+ if ((READ_PORT_UCHAR(Port->Address + COM_MSR) & MS_CD) == 0) {
+ continue;
+ }
+ }
+
+ *Byte = value & (UCHAR)0xff;
+ return CP_GET_SUCCESS;
+ }
+ }
+
+ LastLsr = 0;
+ CpReadLsr (Port, 0);
+ return CP_GET_NODATA;
+}
+
+
+
+BOOLEAN
+CpDoesPortExist(
+ IN PUCHAR Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will attempt to place the port into its
+ diagnostic mode. If it does it will twiddle a bit in
+ the modem control register. If the port exists this
+ twiddling should show up in the modem status register.
+
+ NOTE: This routine must be called before the device is
+ enabled for interrupts, this includes setting the
+ output2 bit in the modem control register.
+
+ This is blatantly stolen from TonyE's code in ntos\dd\serial\serial.c.
+
+Arguments:
+
+ Address - address of hw port.
+
+Return Value:
+
+ TRUE - Port exists. Party on.
+
+ FALSE - Port doesn't exist. Don't use it.
+
+--*/
+
+{
+ UCHAR OldModemStatus;
+ UCHAR ModemStatus;
+ BOOLEAN ReturnValue = TRUE;
+
+ //
+ // Save the old value of the modem control register.
+ //
+
+ OldModemStatus = READ_PORT_UCHAR(Address+COM_MCR);
+
+ //
+ // Set the port into diagnostic mode.
+ //
+
+ WRITE_PORT_UCHAR(
+ Address+COM_MCR,
+ SERIAL_MCR_LOOP
+ );
+
+ //
+ // Bang on it again to make sure that all the lower bits
+ // are clear.
+ //
+
+ WRITE_PORT_UCHAR(
+ Address+COM_MCR,
+ SERIAL_MCR_LOOP
+ );
+
+ //
+ // Read the modem status register. The high for bits should
+ // be clear.
+ //
+
+ ModemStatus = READ_PORT_UCHAR(Address+COM_MSR);
+
+ if (ModemStatus & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
+ SERIAL_MSR_RI | SERIAL_MSR_DCD)) {
+
+ ReturnValue = FALSE;
+ goto AllDone;
+
+ }
+
+ //
+ // So far so good. Now turn on OUT1 in the modem control register
+ // and this should turn on ring indicator in the modem status register.
+ //
+
+ WRITE_PORT_UCHAR(
+ Address+COM_MCR,
+ (SERIAL_MCR_OUT1 | SERIAL_MCR_LOOP)
+ );
+
+ ModemStatus = READ_PORT_UCHAR(Address+COM_MSR);
+
+ if (!(ModemStatus & SERIAL_MSR_RI)) {
+
+ ReturnValue = FALSE;
+ goto AllDone;
+
+ }
+
+AllDone: ;
+
+ //
+ // Put the modem control back into a clean state.
+ //
+
+ WRITE_PORT_UCHAR(
+ Address+COM_MCR,
+ OldModemStatus
+ );
+
+ return ReturnValue;
+
+}
+
diff --git a/private/ntos/nthals/halx86/i386/ixkdcom.h b/private/ntos/nthals/halx86/i386/ixkdcom.h
new file mode 100644
index 000000000..40171040a
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixkdcom.h
@@ -0,0 +1,165 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixkdcom.h
+
+Abstract:
+
+ This module contains the header file for a very simple com port package.
+
+Author:
+
+ Bryan M. Willman (bryanwi) 24-Sep-1990
+
+Revision History:
+
+ John Vert (jvert) 19-Jul-1991
+ Moved into HAL
+--*/
+
+#define COM1_PORT 0x03f8
+#define COM2_PORT 0x02f8
+
+#define COM_DAT 0x00
+#define COM_IEN 0x01 // interrupt enable register
+#define COM_LCR 0x03 // line control registers
+#define COM_MCR 0x04 // modem control reg
+#define COM_LSR 0x05 // line status register
+#define COM_MSR 0x06 // modem status register
+#define COM_DLL 0x00 // divisor latch least sig
+#define COM_DLM 0x01 // divisor latch most sig
+
+#define COM_BI 0x10
+#define COM_FE 0x08
+#define COM_PE 0x04
+#define COM_OE 0x02
+
+#define LC_DLAB 0x80 // divisor latch access bit
+
+#define CLOCK_RATE 0x1C200 // USART clock rate
+
+#define MC_DTRRTS 0x03 // Control bits to assert DTR and RTS
+#define MS_DSRCTSCD 0xB0 // Status bits for DSR, CTS and CD
+#define MS_CD 0x80
+
+#define BD_150 150
+#define BD_300 300
+#define BD_600 600
+#define BD_1200 1200
+#define BD_2400 2400
+#define BD_4800 4800
+#define BD_9600 9600
+#define BD_14400 14400
+#define BD_19200 19200
+#define BD_56000 56000
+
+#define COM_OUTRDY 0x20
+#define COM_DATRDY 0x01
+
+
+//
+// This bit controls the loopback testing mode of the device. Basically
+// the outputs are connected to the inputs (and vice versa).
+//
+#define SERIAL_MCR_LOOP 0x10
+
+//
+// This bit is used for general purpose output.
+//
+#define SERIAL_MCR_OUT1 0x04
+
+//
+// This bit contains the (complemented) state of the clear to send
+// (CTS) line.
+//
+#define SERIAL_MSR_CTS 0x10
+
+//
+// This bit contains the (complemented) state of the data set ready
+// (DSR) line.
+//
+#define SERIAL_MSR_DSR 0x20
+
+//
+// This bit contains the (complemented) state of the ring indicator
+// (RI) line.
+//
+#define SERIAL_MSR_RI 0x40
+
+//
+// This bit contains the (complemented) state of the data carrier detect
+// (DCD) line.
+//
+#define SERIAL_MSR_DCD 0x80
+
+typedef struct _CPPORT {
+ PUCHAR Address;
+ ULONG Baud;
+ USHORT Flags;
+ TIME_FIELDS CarrierLostTime;
+// ULONG LockVar;
+// KSPIN_LOCK Lock;
+} CPPORT, *PCPPORT;
+
+#define PORT_DEFAULTRATE 0x0001 // baud rate not specified, using default
+#define PORT_MODEMCONTROL 0x0002 // using modem controls
+#define PORT_SAVED 0x0004 // port is in saved state
+#define PORT_NOCDLTIME 0x0010 // 'Carrier detect lost' time not set
+#define PORT_DISBAUD 0x0020 // Display baud rate abbrv
+#define PORT_SENDINGSTRING 0x0040 // Sending modem string (don't recurse)
+#define PORT_MDM_CD 0x0080 // CD while in modem control mode
+
+VOID
+CpInitialize (
+ PCPPORT Port,
+ PUCHAR Address,
+ ULONG Rate
+ );
+
+VOID
+CpSetBaud (
+ PCPPORT Port,
+ ULONG Rate
+ );
+
+USHORT
+CpQueryBaud (
+ PCPPORT Port
+ );
+
+VOID
+CpPutByte (
+ PCPPORT Port,
+ UCHAR Byte
+ );
+
+USHORT
+CpGetByte (
+ PCPPORT Port,
+ PUCHAR Byte,
+ BOOLEAN WaitForData
+ );
+
+VOID
+CpLockPort (
+ PCPPORT Port
+ );
+
+VOID
+CpUnlockPort (
+ PCPPORT Port
+ );
+
+VOID
+CpStallExecution (
+ VOID
+ );
+
+BOOLEAN
+CpDoesPortExist(
+ IN PUCHAR Address
+ );
+
diff --git a/private/ntos/nthals/halx86/i386/ixlock.asm b/private/ntos/nthals/halx86/i386/ixlock.asm
new file mode 100644
index 000000000..98cf9c425
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixlock.asm
@@ -0,0 +1,475 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixlock.asm
+;
+; Abstract:
+;
+; This module implements various locking functions optimized for this hal.
+;
+; Author:
+;
+; Ken Reneris (kenr) 21-April-1994
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ extrn FindHigherIrqlMask:DWORD
+ extrn SWInterruptHandlerTable:DWORD
+
+ EXTRNP _KeRaiseIrql,2
+ EXTRNP _KeLowerIrql,1
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+ page ,132
+ subttl "AcquireSpinLock"
+
+_TEXT$01 SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; KIRQL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfAcquireSpinLock,1
+cPublicFpo 0,0
+
+ xor eax, eax ; Eliminate partial stall on return to caller
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifndef NT_UP
+asl10: ACQUIRE_SPINLOCK ecx,<short asl20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short asl99 ; yes, go bugcheck
+endif
+ fstRET KfAcquireSpinLock
+
+ifndef NT_UP
+asl20: SPIN_ON_SPINLOCK ecx,<short asl10>
+endif
+
+if DBG
+cPublicFpo 2,1
+asl99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfAcquireSpinLock
+fstENDP KfAcquireSpinLock
+
+;++
+;
+; KIRQL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired.
+; Any spin should occur at OldIrql; however, since this is a UP hal
+; we don't have the code for it)
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to SYNCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql
+
+ifndef NT_UP
+asls10: ACQUIRE_SPINLOCK ecx,<short asls20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, SYNCH_LEVEL ; old > new?
+ ja short asls99 ; yes, go bugcheck
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+ifndef NT_UP
+asls20: SPIN_ON_SPINLOCK ecx,<short asls10>
+endif
+
+if DBG
+cPublicFpo 2,1
+asls99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we use the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+ifndef NT_UP
+ RELEASE_SPINLOCK ecx ; release it
+endif
+ xor ecx, ecx
+if DBG
+ cmp dl, PCR[PcIrql]
+ ja short rsl99
+endif
+ pushfd
+ cli
+ mov PCR[PcIrql], dl ; store old irql
+ mov cl, dl ; (ecx) = 32bit extended OldIrql
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ jne short rsl20 ; dispatch now.
+
+ popfd
+ fstRet KfReleaseSpinLock ; all done
+
+if DBG
+rsl99: stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+endif
+
+cPublicFpo 0,1
+rsl20: bsr ecx, edx ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ jle short rsl40
+
+ mov eax, PCR[PcIDR] ; Clear all the interrupt
+ SET_8259_MASK ; masks
+rsl40:
+ mov edx, 1
+ shl edx, cl
+ xor PCR[PcIRR], edx ; clear bit in IRR
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+ popfd
+
+cPublicFpo 0, 0
+ fstRet KfReleaseSpinLock ; all done
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,0
+ mov al, PCR[PcIrql] ; (cl) = OldIrql
+if DBG
+ cmp al, APC_LEVEL ; Is OldIrql > NewIrql?
+ ja short afm99 ; Yes, bugcheck
+
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = Current Thread
+ cmp [ecx].FmOwner, edx ; Already owned by this thread?
+ je short afm98 ; Yes, error
+endif
+
+ mov byte ptr PCR[PcIrql], APC_LEVEL ; Set NewIrql
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,2
+ push eax ; save OldIrql
+ push ecx ; Save FAST_MUTEX
+ add ecx, FmEvent ; Wait on Event
+
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+
+ pop ecx ; (ecx) = FAST_MUTEX
+ pop eax ; (al) = OldIrql
+
+cPublicFpo 1,0
+afm_ret:
+
+if DBG
+ cli
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = Current Thread
+ sti
+ mov [ecx].FmOwner, edx ; Save in Fast Mutex
+endif
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+if DBG
+afm98: stdCall _KeBugCheck, <eax> ; never return
+afm99: stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+ fstRet ExAcquireFastMutex
+endif
+
+fstENDP ExAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+cPublicFpo 0,0
+ xor eax, eax
+if DBG
+ cli
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = CurrentThread
+ sti
+ cmp [ecx].FmOwner, edx ; Owner == CurrentThread?
+ jne short rfm_threaderror ; No, bugcheck
+endif
+ or byte ptr [ecx].FmOwner, 1 ; not the owner anymore
+
+ mov al, byte ptr [ecx].FmOldIrql ; (eax) = OldIrql
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ js short rfm05 ; if < 0, set event
+ jnz short rfm10 ; if != 0, don't set event
+
+rfm05:
+cPublicFpo 0,2
+ push eax ; Save OldIrql
+ add ecx, FmEvent
+ stdCall _KeSetEventBoostPriority, <ecx, 0>
+ pop eax
+
+cPublicFpo 0,0
+rfm10:
+ cli
+ mov PCR[PcIrql], eax
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[eax*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ jne short rfm20 ; dispatch now.
+
+ sti
+ fstRet ExReleaseFastMutex ; all done
+if DBG
+rfm_threaderror:
+ stdCall _KeBugCheck, <eax>
+endif
+
+rfm20: bsr ecx, edx ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ jle short rfm40
+
+ mov eax, PCR[PcIDR] ; Clear all the interrupt
+ SET_8259_MASK ; masks
+rfm40:
+ mov edx, 1
+ shl edx, cl
+ xor PCR[PcIRR], edx ; clear bit in IRR
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+ sti
+ fstRet ExReleaseFastMutex ; all done
+fstENDP ExReleaseFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+ mov al, PCR[PcIrql] ; (al) = OldIrql
+
+if DBG
+ cmp al, APC_LEVEL ; Is OldIrql > NewIrql?
+ ja short tam99 ; Yes, bugcheck
+endif
+
+;
+; Try to acquire - but needs to support 386s.
+; *** Warning: This code is NOT MP safe ***
+; But, we know that this hal really only runs on UP machines
+;
+ cli
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam20 ; Yes, abort
+
+ mov dword ptr [ecx].FmCount, 0 ; acquire count
+
+if DBG
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = Current Thread
+ mov [ecx].FmOwner, edx ; Save in Fast Mutex
+endif
+ mov PCR[PcIrql], APC_LEVEL
+ sti
+ mov byte ptr [ecx].FmOldIrql, al
+ mov eax, 1 ; return TRUE
+ fstRet ExTryToAcquireFastMutex
+
+tam20: sti
+ xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+if DBG
+tam99: stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+ xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex
+endif
+
+fstENDP ExTryToAcquireFastMutex
+
+_TEXT$01 ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixmca.c b/private/ntos/nthals/halx86/i386/ixmca.c
new file mode 100644
index 000000000..eea051e49
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixmca.c
@@ -0,0 +1,868 @@
+/*++
+
+Module Name:
+
+ ixmca.c
+
+Abstract:
+
+ HAL component of the Machine Check Architecture.
+ All exported MCA functionality is present in this file.
+
+Author:
+
+ Srikanth Kambhatla (Intel)
+
+Revision History:
+
+ Anil Aggarwal (Intel)
+ Changes incorporated as per design review with Microsoft
+
+--*/
+
+#include <bugcodes.h>
+#include <halp.h>
+
+//
+// Structure to keep track of MCA features available on installed hardware
+//
+
+typedef struct _MCA_INFO {
+ FAST_MUTEX Mutex;
+ UCHAR NumBanks; // Number of Banks present
+ ULONGLONG Bank0Config; // Bank0 configuration setup by BIOS.
+ // This will be used as mask when
+ // setting up bank 0
+ MCA_DRIVER_INFO DriverInfo; // Info about registered driver
+ KDPC Dpc; // DPC object for MCA
+
+} MCA_INFO, *PMCA_INFO;
+
+
+//
+// Default MCA Bank configuration
+//
+#define MCA_DEFAULT_BANK_CONF 0xFFFFFFFFFFFFFFFF
+
+//
+// MCA architecture related defines
+//
+
+#define MCA_NUM_REGS 4
+#define MCA_CNT_MASK 0xFF
+#define MCG_CTL_PRESENT 0x100
+
+#define MCE_VALID 0x01
+
+//
+// MSR register addresses for MCA
+//
+
+#define MCG_CAP 0x179
+#define MCG_STATUS 0x17a
+#define MCG_CTL 0x17b
+#define MC0_CTL 0x400
+#define MC0_STATUS 0x401
+#define MC0_ADDR 0x402
+#define MC0_MISC 0x403
+
+#define PENTIUM_MC_ADDR 0x0
+#define PENTIUM_MC_TYPE 0x1
+
+//
+// Writing all 1's to MCG_CTL register enables logging.
+//
+#define MCA_MCGCTL_ENABLE_LOGGING 0xffffffff
+
+//
+// Bit interpretation of MCG_STATUS register
+//
+#define MCG_MC_INPROGRESS 0x4
+#define MCG_EIP_VALID 0x2
+#define MCG_RESTART_EIP_VALID 0x1
+
+//
+// For the function that reads the error reporting bank log, the type of error we
+// are interested in
+//
+#define MCA_GET_ANY_ERROR 0x1
+#define MCA_GET_NONRESTARTABLE_ERROR 0x2
+
+
+//
+// Global Varibles
+//
+
+MCA_INFO HalpMcaInfo;
+extern KAFFINITY HalpActiveProcessors;
+extern UCHAR HalpClockMcaQueueDpc;
+
+extern UCHAR MsgMCEPending[];
+extern WCHAR rgzSessionManager[];
+extern WCHAR rgzEnableMCE[];
+extern WCHAR rgzEnableMCA[];
+
+
+//
+// External prototypes
+//
+
+VOID
+HalpMcaCurrentProcessorSetTSS (
+ VOID
+ );
+
+VOID
+HalpSetCr4MCEBit (
+ VOID
+ );
+
+//
+// Internal prototypes
+//
+
+VOID
+HalpMcaInit (
+ VOID
+ );
+
+NTSTATUS
+HalpMcaReadProcessorException (
+ OUT PMCA_EXCEPTION Exception,
+ IN BOOLEAN NonRestartableOnly
+ );
+
+VOID
+HalpMcaCurrentProcessorSetConfig (
+ VOID
+ );
+
+VOID
+HalpMcaQueueDpc(
+ VOID
+ );
+
+VOID
+HalpMcaGetConfiguration (
+ OUT PULONG MCEEnabled,
+ OUT PULONG MCAEnabled
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, HalpMcaInit)
+#pragma alloc_text(INIT, HalpMcaCurrentProcessorSetConfig)
+#pragma alloc_text(INIT, HalpMcaGetConfiguration)
+#pragma alloc_text(PAGE, HalpGetMcaLog)
+#pragma alloc_text(PAGE, HalpMcaRegisterDriver)
+#endif
+
+
+//
+// All the initialization code for MCA goes here
+//
+
+VOID
+HalpMcaInit (
+ VOID
+ )
+
+/*++
+ Routine Description:
+ This routine is called to do all the initialization work
+
+ Arguments:
+ None
+
+ Return Value:
+ STATUS_SUCCESS if successful
+ error status otherwise
+--*/
+
+{
+ ULONGLONG MsrCapability;
+ KIRQL OldIrql;
+ PKTHREAD Thread;
+ KAFFINITY ActiveProcessors, CurrentAffinity;
+ ULONGLONG MsrMceType;
+ ULONG MCEEnabled;
+ ULONG MCAEnabled;
+
+ if ( (!(HalpFeatureBits & HAL_MCE_PRESENT)) &&
+ (!(HalpFeatureBits & HAL_MCA_PRESENT)) ) {
+
+ return; // nothing to do
+ }
+
+ HalpMcaGetConfiguration(&MCEEnabled, &MCAEnabled);
+
+ if ( (HalpFeatureBits & HAL_MCE_PRESENT) &&
+ (!(HalpFeatureBits & HAL_MCA_PRESENT)) ) {
+
+ if (MCEEnabled == FALSE) {
+
+ // User has not enabled MCE capability.
+ HalpFeatureBits &= ~(HAL_MCE_PRESENT | HAL_MCA_PRESENT);
+
+ return;
+ }
+
+#if DBG
+ DbgPrint("MCE feature is enabled via registry\n");
+#endif // DBG
+
+ MsrMceType = RDMSR(PENTIUM_MC_TYPE);
+
+ if (((PLARGE_INTEGER)(&MsrMceType))->LowPart & MCE_VALID) {
+
+ //
+ // On an AST PREMMIA MX machine we seem to have a Machine Check Pending
+ // always.
+ //
+
+ HalDisplayString(MsgMCEPending);
+
+ HalpFeatureBits &= ~(HAL_MCE_PRESENT | HAL_MCA_PRESENT);
+
+ return;
+ }
+ }
+
+ //
+ // If MCA is available, find out the number of banks available and
+ // also get the platform specific bank 0 configuration
+ //
+
+ if ( HalpFeatureBits & HAL_MCA_PRESENT ) {
+
+ if (MCAEnabled == FALSE) {
+
+ /* User has disabled MCA capability. */
+#if DBG
+ DbgPrint("MCA feature is disabled via registry\n");
+#endif // DBG
+
+ HalpFeatureBits &= ~(HAL_MCE_PRESENT | HAL_MCA_PRESENT);
+ return;
+ }
+
+ MsrCapability = RDMSR(MCG_CAP);
+ HalpMcaInfo.NumBanks = (UCHAR)(MsrCapability & MCA_CNT_MASK);
+
+ //
+ // Find out the Bank 0 configuration setup by BIOS. This will be used
+ // as a mask when writing to Bank 0
+ //
+
+ HalpMcaInfo.Bank0Config = RDMSR(MC0_CTL);
+ }
+
+ if ( (HalpFeatureBits & HAL_MCA_PRESENT) ||
+ (HalpFeatureBits & HAL_MCE_PRESENT) ) {
+
+ ASSERT(HalpFeatureBits & HAL_MCE_PRESENT);
+
+ //
+ // This lock synchronises access to the log area when we call the
+ // logger on multiple processors.
+ //
+
+ ExInitializeFastMutex (&HalpMcaInfo.Mutex);
+
+ //
+ // Initialize on each processor
+ //
+
+ Thread = KeGetCurrentThread ();
+ ActiveProcessors = HalpActiveProcessors;
+ for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) {
+
+ if (ActiveProcessors & CurrentAffinity) {
+ ActiveProcessors &= ~CurrentAffinity;
+ KeSetAffinityThread (Thread, CurrentAffinity);
+
+ //
+ // Initialize MCA support on this processor
+ //
+
+ OldIrql = KfRaiseIrql(HIGH_LEVEL);
+
+ HalpMcaCurrentProcessorSetTSS();
+ HalpMcaCurrentProcessorSetConfig();
+
+ KfLowerIrql(OldIrql);
+ }
+ }
+
+ //
+ // Restore threads affinity
+ //
+
+ KeSetAffinityThread (Thread, HalpActiveProcessors);
+ }
+}
+
+
+VOID
+HalpMcaCurrentProcessorSetConfig (
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine sets/modifies the configuration of the machine check
+ architecture on the current processor. Input is specification of
+ the control register MCi_CTL for each bank of the MCA architecture.
+ which controls the generation of machine check exceptions for errors
+ logged to that bank.
+
+ If MCA is not available on this processor, check if MCE is available.
+ If so, enable MCE in CR4
+
+ Arguments:
+
+ Context: Array of values of MCi_CTL for each bank of MCA.
+ If NULL, use MCA_DEFAULT_BANK_CONF values for each bank
+
+ Return Value:
+
+ None
+
+--*/
+{
+ ULONGLONG MciCtl;
+ ULONGLONG McgCap;
+ ULONGLONG McgCtl;
+ ULONG BankNum;
+
+
+ if (HalpFeatureBits & HAL_MCA_PRESENT) {
+ //
+ // MCA is available. Initialize MCG_CTL register if present
+ // Writing all 1's enable MCE or MCA Error Exceptions
+ //
+
+ McgCap = RDMSR(MCG_CAP);
+
+ if (McgCap & MCG_CTL_PRESENT) {
+ McgCtl = MCA_MCGCTL_ENABLE_LOGGING;
+ WRMSR(MCG_CTL, McgCtl);
+ }
+
+ //
+ // Enable all MCA errors
+ //
+ for ( BankNum = 0; BankNum < HalpMcaInfo.NumBanks; BankNum++ ) {
+
+ //
+ // Use MCA_DEFAULT_BANK_CONF for each bank
+ //
+
+ MciCtl = MCA_DEFAULT_BANK_CONF;
+
+ //
+ // If this is bank 0, use HalpMcaInfo.Bank0Config as a mask
+ //
+ if (BankNum == 0) {
+ MciCtl &= HalpMcaInfo.Bank0Config;
+ }
+
+ WRMSR(MC0_CTL + (BankNum * MCA_NUM_REGS), MciCtl);
+
+ //
+ // Clear the MCi_STATUS registers also
+ //
+ WRMSR(MC0_STATUS + (BankNum * MCA_NUM_REGS), 0x0);
+ }
+ }
+
+ //
+ // Enable MCE bit in CR4
+ //
+
+ HalpSetCr4MCEBit();
+}
+
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+/*++
+ Routine Description:
+ This routine is called by the driver (via HalSetSystemInformation)
+ to register its presence. Only one driver can be registered at a time.
+
+ Arguments:
+ DriverInfo: Contains info about the callback routine and the DeviceObject
+
+ Return Value:
+ Unless a MCA driver is already registered OR one of the two callback
+ routines are NULL, this routine returns Success.
+--*/
+
+{
+ KIRQL OldIrql;
+ PVOID UnlockHandle;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+
+ Status = STATUS_UNSUCCESSFUL;
+
+ if ((HalpFeatureBits & HAL_MCE_PRESENT) && DriverInfo->DpcCallback) {
+
+ ExAcquireFastMutex (&HalpMcaInfo.Mutex);
+
+ //
+ // Register driver
+ //
+
+ if (!HalpMcaInfo.DriverInfo.DpcCallback) {
+
+ // Initialize the DPC object
+ KeInitializeDpc(
+ &HalpMcaInfo.Dpc,
+ DriverInfo->DpcCallback,
+ DriverInfo->DeviceContext
+ );
+
+ // register driver
+ HalpMcaInfo.DriverInfo.ExceptionCallback = DriverInfo->ExceptionCallback;
+ HalpMcaInfo.DriverInfo.DpcCallback = DriverInfo->DpcCallback;
+ HalpMcaInfo.DriverInfo.DeviceContext = DriverInfo->DeviceContext;
+ Status = STATUS_SUCCESS;
+ }
+
+ ExReleaseFastMutex (&HalpMcaInfo.Mutex);
+ }
+
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+/*++
+ Routine Description:
+ This is the entry point for driver to read the bank logs
+ Called by HaliQuerySystemInformation()
+
+ Arguments:
+ Buffer: into which the error is reported
+ BufferSize: Size of the passed buffer
+ Length: of this buffer
+
+ Return Value:
+ Success or failure
+
+--*/
+{
+ KAFFINITY ActiveProcessors, CurrentAffinity;
+ PKTHREAD Thread;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ if (! (HalpFeatureBits & HAL_MCA_PRESENT)) {
+ return(STATUS_NO_SUCH_DEVICE);
+ }
+
+
+ Thread = KeGetCurrentThread ();
+ ActiveProcessors = HalpActiveProcessors;
+ Status = STATUS_NOT_FOUND;
+
+ ExAcquireFastMutex (&HalpMcaInfo.Mutex);
+
+ for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) {
+
+ if (ActiveProcessors & CurrentAffinity) {
+
+ ActiveProcessors &= ~CurrentAffinity;
+ KeSetAffinityThread (Thread, CurrentAffinity);
+
+ //
+ // Check this processor for an exception
+ //
+
+ Status = HalpMcaReadProcessorException (Exception, FALSE);
+
+ //
+ // If found, return current information
+ //
+
+ if (Status != STATUS_NOT_FOUND) {
+ ASSERT (Status != STATUS_SEVERITY_ERROR);
+
+ *ReturnedLength = sizeof(MCA_EXCEPTION);
+ break;
+ }
+ }
+ }
+
+ //
+ // Restore threads affinity, release mutex, and return
+ //
+
+ KeSetAffinityThread (Thread, HalpActiveProcessors);
+ ExReleaseFastMutex (&HalpMcaInfo.Mutex);
+ return Status;
+}
+
+
+#if DBG
+//
+// In checked build, we allocate 4K stack for ourselves and hence there is
+// no need to switch to the stack of double fault handler. We can
+// directly bugcheck without switching stack.
+//
+#define HalpMcaSwitchMcaExceptionStackAndBugCheck KeBugCheckEx
+#else
+NTKERNELAPI
+VOID
+HalpMcaSwitchMcaExceptionStackAndBugCheck(
+ IN ULONG BugCheckCode,
+ IN ULONG BugCheckParameter1,
+ IN ULONG BugCheckParameter2,
+ IN ULONG BugCheckParameter3,
+ IN ULONG BugCheckParameter4
+ );
+#endif // DBG
+
+// Set the following to check async capability
+
+BOOLEAN NoMCABugCheck = FALSE;
+
+VOID
+HalpMcaExceptionHandler (
+ VOID
+ )
+
+/*++
+ Routine Description:
+ This is the MCA exception handler.
+
+ Arguments:
+ None
+
+ Return Value:
+ None
+--*/
+
+{
+ NTSTATUS Status;
+ MCA_EXCEPTION BankLog;
+ ULONG p1, p2;
+ ULONGLONG McgStatus, p3;
+
+ BankLog.VersionNumber = 1;
+
+ if (!(HalpFeatureBits & HAL_MCA_PRESENT) ) {
+
+ //
+ // If we have ONLY MCE (and not MCA), read the MC_ADDR and MC_TYPE
+ // MSRs, print the values and bugcheck as the errors are not
+ // restartable.
+ //
+
+ BankLog.ExceptionType = HAL_MCE_RECORD;
+ BankLog.u.Mce.Address = RDMSR(PENTIUM_MC_ADDR);
+ BankLog.u.Mce.Type = RDMSR(PENTIUM_MC_TYPE);
+ Status = STATUS_SEVERITY_ERROR;
+
+ //
+ // Parameters for bugcheck
+ //
+
+ p1 = ((PLARGE_INTEGER)(&BankLog.u.Mce.Type))->LowPart;
+ p2 = 0;
+ p3 = BankLog.u.Mce.Address;
+
+ } else {
+
+ McgStatus = RDMSR(MCG_STATUS);
+ ASSERT( (McgStatus & MCG_MC_INPROGRESS) != 0);
+
+ Status = HalpMcaReadProcessorException (&BankLog, TRUE);
+
+ //
+ // Clear MCIP bit in MCG_STATUS register
+ //
+
+ McgStatus = 0;
+ WRMSR(MCG_STATUS, McgStatus);
+
+ //
+ // Parameters for bugcheck
+ //
+
+ p1 = BankLog.u.Mca.BankNumber;
+ p2 = BankLog.u.Mca.Address.Address;
+ p3 = BankLog.u.Mca.Status.QuadPart;
+ }
+
+ if (Status == STATUS_SEVERITY_ERROR) {
+
+ //
+ // Call the exception callback of the driver so that
+ // the error can be logged to NVRAM
+ //
+
+ if (HalpMcaInfo.DriverInfo.ExceptionCallback) {
+ HalpMcaInfo.DriverInfo.ExceptionCallback (
+ HalpMcaInfo.DriverInfo.DeviceContext,
+ &BankLog
+ );
+ }
+
+ if (!NoMCABugCheck) {
+
+ //
+ // Bugcheck
+ //
+
+ HalpMcaSwitchMcaExceptionStackAndBugCheck(
+ MACHINE_CHECK_EXCEPTION,
+ p1,
+ p2,
+ ((PLARGE_INTEGER)(&p3))->HighPart,
+ ((PLARGE_INTEGER)(&p3))->LowPart
+ );
+
+ // NOT REACHED
+ }
+ }
+
+ //
+ // Must be restartable. Indicate to the timer tick routine that a
+ // DPC needs queued for MCA driver.
+ //
+
+ if (HalpMcaInfo.DriverInfo.DpcCallback) {
+ HalpClockMcaQueueDpc = 1;
+ }
+}
+
+VOID
+HalpMcaQueueDpc(
+ VOID
+ )
+/*++
+ Routine Description: Gets called from the timer tick to check if DPC
+ needs to be queued
+
+--*/
+
+{
+ KeInsertQueueDpc(
+ &HalpMcaInfo.Dpc,
+ NULL,
+ NULL
+ );
+}
+
+
+NTSTATUS
+HalpMcaReadProcessorException (
+ OUT PMCA_EXCEPTION Exception,
+ IN BOOLEAN NonRestartableOnly
+ )
+/*++
+
+ Routine Description:
+
+ This routine logs the errors from the MCA banks on one processor.
+ Necessary checks for the restartability are performed. The routine
+ 1> Checks for restartability, and for each bank identifies valid bank
+ entries and logs error.
+ 2> If the error is not restartable provides additional information about
+ bank and the MCA registers.
+ 3> Resets the Status registers for each bank
+
+ Arguments:
+ LogExcept: Into which we log the error if found
+ NonRestartableOnly: Get any error vs. look for error that is not-restartable
+
+ Return Values:
+ STATUS_SEVERITY_ERROR: Detected non-restartable error.
+ STATUS_SUCCESS: Successfully logged bank values
+ STATUS_NOT_FOUND: No error found on any bank
+
+--*/
+{
+ ULONGLONG McgStatus;
+ UCHAR BankNumber;
+ MCI_STATS istatus;
+ NTSTATUS ReturnStatus;
+ ULONG eflags;
+
+ //
+ // Read the global status register
+ //
+
+ McgStatus = RDMSR(MCG_STATUS);
+
+ //
+ // scan banks on current processor and log contents of first valid bank
+ // reporting error. Once we find a valid error, no need to read remaining
+ // banks. It is the application responsibility to read more errors.
+ //
+
+ ReturnStatus = STATUS_NOT_FOUND;
+
+ for (BankNumber = 0; BankNumber < HalpMcaInfo.NumBanks; BankNumber++) {
+
+ //
+ // Read the Status MSR of individual bank
+ //
+
+ istatus.QuadPart = RDMSR(MC0_STATUS + BankNumber * MCA_NUM_REGS);
+
+
+ if (istatus.MciStats.Valid == 0) {
+ // No error in this bank.
+ continue;
+
+ }
+
+ //
+ // When MCIP bit is set, the execution can be restarted when
+ // (MCi_STATUS.DAM == 0) && (MCG_STATUS.RIPV == 1)
+ //
+
+ if ((McgStatus & MCG_MC_INPROGRESS) &&
+ (!(McgStatus & MCG_RESTART_EIP_VALID) ||
+ istatus.MciStats.Damage)) {
+
+ ReturnStatus = STATUS_SEVERITY_ERROR;
+
+ } else if (NonRestartableOnly == FALSE) {
+
+ ReturnStatus = STATUS_SUCCESS;
+
+ } else {
+
+ // Not the desired type error available here
+ continue;
+ }
+
+ //
+ // Complete exception record
+ //
+
+ Exception->VersionNumber = 1;
+ Exception->ExceptionType = HAL_MCA_RECORD;
+ Exception->TimeStamp.QuadPart = 0;
+ Exception->u.Mca.Address.QuadPart = 0;
+ Exception->u.Mca.Misc = 0;
+ Exception->u.Mca.BankNumber = BankNumber;
+ Exception->u.Mca.Status = istatus;
+
+ Exception->ProcessorNumber = KeGetCurrentProcessorNumber();
+
+ if (KeGetCurrentIrql() != CLOCK2_LEVEL) {
+ KeQuerySystemTime(&Exception->TimeStamp);
+ }
+
+ if (istatus.MciStats.AddressValid) {
+ Exception->u.Mca.Address.QuadPart = RDMSR(MC0_ADDR + BankNumber * MCA_NUM_REGS);
+ }
+
+ if (istatus.MciStats.MiscValid) {
+ Exception->u.Mca.Misc = RDMSR(MC0_MISC + BankNumber * MCA_NUM_REGS);
+ }
+
+ if (ReturnStatus != STATUS_SEVERITY_ERROR) {
+
+ // Clear MCi_STATUS register (not a falal error)
+
+ WRMSR(MC0_STATUS + BankNumber * MCA_NUM_REGS, 0);
+ }
+
+ //
+ // When the Valid bit of status register is cleared, hardware may write
+ // a new buffered error report into the error reporting area. The
+ // serializing instruction is required to permit the update to complete
+ //
+
+ HalpSerialize ();
+
+ //
+ // Found entry, done
+ //
+
+ break;
+ }
+
+ return(ReturnStatus);
+}
+
+VOID
+HalpMcaGetConfiguration (
+ OUT PULONG MCEEnabled,
+ OUT PULONG MCAEnabled
+)
+
+/*++
+
+Routine Description:
+
+ This routine stores the Machine Check configuration information.
+
+Arguments:
+
+ MCEEnabled - Pointer to the MCEEnabled indicator.
+ 0 = False, 1 = True (0 if value not present in Registry).
+
+ MCAEnabled - Pointer to the MCAEnabled indicator.
+ 0 = False, 1 = True (1 if value not present in Registry).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ RTL_QUERY_REGISTRY_TABLE Parameters[3];
+ ULONG DefaultDataMCE;
+ ULONG DefaultDataMCA;
+
+
+ RtlZeroMemory(Parameters, sizeof(Parameters));
+ DefaultDataMCE = *MCEEnabled = FALSE;
+ DefaultDataMCA = *MCAEnabled = TRUE;
+
+ //
+ // Gather all of the "user specified" information from
+ // the registry.
+ //
+
+ Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Parameters[0].Name = rgzEnableMCE;
+ Parameters[0].EntryContext = MCEEnabled;
+ Parameters[0].DefaultType = REG_DWORD;
+ Parameters[0].DefaultData = &DefaultDataMCE;
+ Parameters[0].DefaultLength = sizeof(ULONG);
+
+ Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Parameters[1].Name = rgzEnableMCA;
+ Parameters[1].EntryContext = MCAEnabled;
+ Parameters[1].DefaultType = REG_DWORD;
+ Parameters[1].DefaultData = &DefaultDataMCA;
+ Parameters[1].DefaultLength = sizeof(ULONG);
+
+ RtlQueryRegistryValues(
+ RTL_REGISTRY_CONTROL | RTL_REGISTRY_OPTIONAL,
+ rgzSessionManager,
+ Parameters,
+ NULL,
+ NULL
+ );
+}
diff --git a/private/ntos/nthals/halx86/i386/ixmcaa.asm b/private/ntos/nthals/halx86/i386/ixmcaa.asm
new file mode 100644
index 000000000..229621892
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixmcaa.asm
@@ -0,0 +1,420 @@
+;++
+;Module Name
+; imca.asm
+;
+;Abstract:
+; Assembly support needed for Intel MCA
+;
+; Author:
+; Anil Aggarwal (Intel Corp)
+;
+;Revision History:
+;
+;
+;--
+
+.586p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+ .list
+
+ EXTRNP _HalpMcaExceptionHandler,0
+ EXTRNP _KeBugCheckEx,5,IMPORT
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; DATA Segment
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+_DATA SEGMENT PARA PUBLIC 'DATA'
+;
+; MCA Exception task stack
+;
+
+MINIMUM_TSS_SIZE EQU TssIoMaps
+
+if DBG
+;
+; If we use DbgPrint, we need a larger stack
+;
+MCA_EXCEPTION_STACK_SIZE EQU 01000H
+else
+MCA_EXCEPTION_STACK_SIZE EQU 0100H
+endif
+
+KGDT_MCA_TSS EQU 0A0H
+
+
+ ;
+ ; TSS for MCA Exception
+ ;
+ align 16
+
+ public _HalpMcaExceptionTSS
+_HalpMcaExceptionTSS label byte
+ db MINIMUM_TSS_SIZE dup(0)
+
+ ;
+ ; Stack for MCA exception task
+ ;
+
+ public _HalpMcaExceptionStack
+ db MCA_EXCEPTION_STACK_SIZE dup ("*")
+_HalpMcaExceptionStack label byte
+
+_DATA ends
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; TEXT Segment
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ .586p
+
+;++
+;ULONGLONG
+;FASTCALL
+;RDMSR(
+; IN ULONG MsrAddress
+; )
+; Routine Description:
+; This function reads an MSR
+;
+; Arguments:
+; Msr: The address of MSR to be read
+;
+; Return Value:
+; Returns the low 32 bit of MSR in eax and high 32 bits of MSR in edx
+;
+;--
+cPublicFastCall RDMSR,1
+
+ rdmsr
+ fstRET RDMSR
+
+fstENDP RDMSR
+
+;++
+;
+;VOID
+;WRMSR(
+; IN ULONG MsrAddress,
+; IN ULONGLONG MsrValue
+; )
+; Routine Description:
+; This function writes an MSR
+;
+; Arguments:
+; Msr: The address of MSR to be written
+; Data: The value to be written to the MSR register
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _WRMSR,3
+
+ mov ecx, [esp + 4] ; MsrAddress
+ mov eax, [esp + 8] ; Low 32 bits of MsrValue
+ mov edx, [esp + 12] ; High 32 bits of MsrValue
+
+ wrmsr
+ stdRET _WRMSR
+
+stdENDP _WRMSR
+
+;++
+;
+;VOID
+;HalpSerialize(
+; VOID
+; )
+;
+; Routine Description:
+; This function implements the fence operation for out-of-order execution
+;
+; Arguments:
+; None
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _HalpSerialize,0
+
+ push ebx
+ xor eax, eax
+ cpuid
+ pop ebx
+
+ stdRET _HalpSerialize
+
+stdENDP _HalpSerialize
+
+
+;++
+;
+; Routine Description:
+;
+; Machine Check exception handler
+;
+;
+; Arguments:
+;
+; Return value:
+;
+; If the error is non-restartable, we will bugcheck.
+; Otherwise, we just return
+;
+;--
+ ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
+align dword
+ public _HalpMcaExceptionHandlerWrapper
+_HalpMcaExceptionHandlerWrapper proc
+.FPO (0, 0, 0, 0, 0, 2)
+
+ cli
+
+ ;
+ ; Update the TSS pointer in the PCR to point to the MCA TSS
+ ; (which is what we're running on, or else we wouldn't be here)
+ ;
+
+ push dword ptr PCR[PcTss]
+ mov eax, PCR[PcGdt]
+ mov ch, [eax+KGDT_MCA_TSS+KgdtBaseHi]
+ mov cl, [eax+KGDT_MCA_TSS+KgdtBaseMid]
+ shl ecx, 16
+ mov cx, [eax+KGDT_MCA_TSS+KgdtBaseLow]
+ mov PCR[PcTss], ecx
+
+ ;
+ ; Clear the busy bit in the TSS selector
+ ;
+ mov ecx, PCR[PcGdt]
+ lea eax, [ecx] + KGDT_MCA_TSS
+ mov byte ptr [eax+5], 089h ; 32bit, dpl=0, present, TSS32, not busy
+
+ ;
+ ; Clear Nested Task bit in EFLAGS
+ ;
+ pushfd
+ and [esp], not 04000h
+ popfd
+
+ ;
+ ; Check if there is a bugcheck-able error. If need to bugcheck, the
+ ; caller does it.
+ ;
+ stdCall _HalpMcaExceptionHandler
+
+ ;
+ ; We're back which means that the error was restartable.
+ ;
+
+ pop dword ptr PCR[PcTss] ; restore PcTss
+
+ mov ecx, PCR[PcGdt]
+ lea eax, [ecx] + KGDT_TSS
+ mov byte ptr [eax+5], 08bh ; 32bit, dpl=0, present, TSS32, *busy*
+
+ pushfd ; Set Nested Task bit in EFLAGS
+ or [esp], 04000h ; so iretd will do a tast switch
+ popfd
+
+ iretd ; Return from MCA Exception handler
+ jmp short _HalpMcaExceptionHandlerWrapper
+ ; For next Machine check exception
+
+_HalpMcaExceptionHandlerWrapper endp
+
+;++
+;
+; Routine Description:
+;
+; MCA exception is run off a small stack pointed to by MCA TSS. When
+; the error is non-restartable, this routine is called to switch to a larger
+; stack which is the overlay of ZW thunks (as is done for double fault stack)
+;
+; Arguments:
+;
+; The arguments to KeMachineCheck are passed to this function
+;
+; Return value:
+;
+; Never returns. End up doing the bugcheck.
+;
+;--
+
+cPublicProc _HalpMcaSwitchMcaExceptionStackAndBugCheck,5
+
+ ; Get Task gate descriptor for double fault handler
+ mov ecx, PCR[PcIdt] ; Get IDT address
+ lea eax, [ecx] + 040h ; DF Exception is 8
+
+ ; Get to TSS Descriptor of double fault handler TSS
+ xor ecx, ecx
+ mov cx, word ptr [eax+2]
+ add ecx, PCR[PcGdt]
+
+ ; Get the address of TSS from this TSS Descriptor
+ mov ah, [ecx+KgdtBaseHi]
+ mov al, [ecx+KgdtBaseMid]
+ shl eax, 16
+ mov ax, [ecx+KgdtBaseLow]
+
+ ; Get ESP from DF TSS
+ mov ecx, [eax+038h]
+
+ ; Save the passed arguments before we switch the stacks
+ mov eax, [esp+4]
+ mov ebx, [esp+8]
+ mov edx, [esp+12]
+ mov esi, [esp+16]
+ mov edi, [esp+20]
+
+ ; Use the ZW thunk area for the stack to operate on for crash
+ mov esp, ecx
+
+ stdCall _KeBugCheckEx, <eax, ebx, edx, esi, edi>
+
+ stdRET _HalpMcaSwitchMcaExceptionStackAndBugCheck
+
+stdENDP _HalpMcaSwitchMcaExceptionStackAndBugCheck
+
+_TEXT ends
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+
+;++
+;VOID
+;HalpMcaCurrentProcessorSetTSS(
+; VOID
+; )
+; Routine Description:
+; This function sets up the TSS for MCA exception 18
+;
+; Arguments:
+; Context: We don't care about this but is there since HalpGenericCall
+; needs one
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _HalpMcaCurrentProcessorSetTSS,0
+
+ ;
+ ; Edit IDT Entry for MCA Exception (18) to contain a task gate
+ ;
+ mov ecx, PCR[PcIdt] ; Get IDT address
+ lea eax, [ecx] + 090h ; MCA Exception is 18
+ mov byte ptr [eax + 5], 085h ; P=1,DPL=0,Type=5
+ mov word ptr [eax + 2], KGDT_MCA_TSS ; TSS Segment Selector
+
+ mov edx, offset FLAT:_HalpMcaExceptionTSS ; the address of TSS in edx
+
+ ;
+ ; Set various fields in TSS
+ ;
+ mov eax, cr3
+ mov [edx + TssCR3], eax
+
+ mov eax, offset FLAT:_HalpMcaExceptionStack; address of MCA Exception stack
+ mov dword ptr [edx+038h], eax ; Set ESP
+ mov dword ptr [edx+TssEsp0], eax ; Set ESP0
+
+ mov dword ptr [edx+020h], offset FLAT:_HalpMcaExceptionHandlerWrapper ; set EIP
+ mov dword ptr [edx+024h], 0 ; set EFLAGS
+ mov word ptr [edx+04ch],KGDT_R0_CODE ; set value for CS
+ mov word ptr [edx+058h],KGDT_R0_PCR ; set value for FS
+ mov [edx+050h], ss
+ mov word ptr [edx+048h],KGDT_R3_DATA OR RPL_MASK ; Es
+ mov word ptr [edx+054h],KGDT_R3_DATA OR RPL_MASK ; Ds
+
+ ;
+ ; Part that gets done in KiInitialiazeTSS()
+ ;
+ mov word ptr [edx + 08], KGDT_R0_DATA ; Set SS0
+ mov word ptr [edx + 060h],0 ; Set LDT
+ mov word ptr [edx + 064h],0 ; Set T bit
+ mov word ptr [edx + 066h],020adh ; I/O Map base address = sizeof(KTSS)+1
+
+ ;
+ ; Edit GDT entry for KGDT_MCA_TSS to create a valid TSS Descriptor
+ ;
+ mov ecx, PCR[PcGdt] ; Get GDT address
+ lea eax, [ecx] + KGDT_MCA_TSS ; offset of MCA TSS in GDT
+ mov ecx, eax
+
+ ;
+ ; Set Type field of TSS Descriptor
+ ;
+ mov byte ptr [ecx + 5], 089H ; P=1, DPL=0, Type = 9
+
+ ;
+ ; Set Base Address field of TSS Descriptor
+ ;
+ mov eax, edx ; TSS address in eax
+ mov [ecx + KgdtBaseLow], ax
+ shr eax, 16
+ mov [ecx + KgdtBaseHi],ah
+ mov [ecx + KgdtBaseMid],al
+
+ ;
+ ; Set Segment limit for TSS Descriptor
+ ;
+ mov eax, MINIMUM_TSS_SIZE
+ mov [ecx + KgdtLimitLow],ax
+
+ stdRET _HalpMcaCurrentProcessorSetTSS
+
+stdENDP _HalpMcaCurrentProcessorSetTSS
+
+
+;++
+;
+;VOID
+;HalpSetCr4MCEBit(
+; VOID
+; )
+;
+; Routine Description:
+; This function sets the CR4.MCE bit
+;
+; Arguments:
+; None
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _HalpSetCr4MCEBit,0
+
+ mov eax, cr4
+ or eax, CR4_MCE
+ mov cr4, eax
+ stdRET _HalpSetCr4MCEBit
+
+stdENDP _HalpSetCr4MCEBit
+
+
+INIT ends
+
+ end
+
diff --git a/private/ntos/nthals/halx86/i386/ixnmi.c b/private/ntos/nthals/halx86/i386/ixnmi.c
new file mode 100644
index 000000000..e00035bd8
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixnmi.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixnmi.c
+
+Abstract:
+
+ Provides standard x86 NMI handler
+
+Author:
+
+ kenr
+
+Revision History:
+
+--*/
+#include "halp.h"
+#include "bugcodes.h"
+
+#define SYSTEM_CONTROL_PORT_A 0x92
+#define SYSTEM_CONTROL_PORT_B 0x61
+#define EISA_EXTENDED_NMI_STATUS 0x461
+
+UCHAR EisaNMIMsg[] = MSG_NMI_EISA_IOCHKERR;
+
+
+VOID
+HalHandleNMI(
+ IN OUT PVOID NmiInfo
+ )
+/*++
+
+Routine Description:
+
+ Called DURING an NMI. The system will BugCheck when an NMI occurs.
+ This function can return the proper bugcheck code, bugcheck itself,
+ or return success which will cause the system to iret from the nmi.
+
+ This function is called during an NMI - no system services are available.
+ In addition, you don't want to touch any spinlock which is normally
+ used since we may have been interrupted while owning it, etc, etc...
+
+Warnings:
+
+ Do NOT:
+ Make any system calls
+ Attempt to acquire any spinlock used by any code outside the NMI handler
+ Change the interrupt state. Do not execute any IRET inside this code
+
+ Passing data to non-NMI code must be done using manual interlocked
+ functions. (xchg instructions).
+
+Arguments:
+
+ NmiInfo - Pointer to NMI information structure (TBD)
+ - NULL means no NMI information structure was passed
+
+Return Value:
+
+ BugCheck code
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ UCHAR c;
+ ULONG port, i;
+
+ HalDisplayString (MSG_HARDWARE_ERROR1);
+ HalDisplayString (MSG_HARDWARE_ERROR2);
+
+ StatusByte = READ_PORT_UCHAR((PUCHAR) SYSTEM_CONTROL_PORT_B);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_PARITY);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_CHANNEL_CHECK);
+ }
+
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR((PUCHAR) EISA_EXTENDED_NMI_STATUS);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString (MSG_NMI_FAIL_SAFE);
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString (MSG_NMI_BUS_TIMEOUT);
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString (MSG_NMI_SOFTWARE_NMI);
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 1; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2 && StatusByte != 0xff) {
+ c = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ for (i=0; EisaNMIMsg[i]; i++) {
+ if (EisaNMIMsg[i] == '%') {
+ EisaNMIMsg[i] = c;
+ HalDisplayString (EisaNMIMsg);
+ EisaNMIMsg[i] = '%';
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ HalDisplayString (MSG_HALT);
+ KeEnterKernelDebugger();
+}
diff --git a/private/ntos/nthals/halx86/i386/ixpcibrd.c b/private/ntos/nthals/halx86/i386/ixpcibrd.c
new file mode 100644
index 000000000..c8b87d31e
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixpcibrd.c
@@ -0,0 +1,1029 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+// #define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // skip it...
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.SecondaryBus <= CB.BusHandler->BusNumber) {
+
+ // secondary bus number doesn't make any sense. HP Omnibook may
+ // not fill this field in on a virtually disabled pci-pci bridge
+
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 255;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 255 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan+1;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halx86/i386/ixpcibus.c b/private/ntos/nthals/halx86/i386/ixpcibus.c
new file mode 100644
index 000000000..7565c964b
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixpcibus.c
@@ -0,0 +1,2520 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+VOID
+HalpPCISynchronizeOrionB0 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ );
+
+VOID
+HalpPCIReleaseSynchronzationOrionB0 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+extern BOOLEAN HalpDoingCrashDump;
+
+//
+// Orion B0 errata workaround
+//
+
+struct {
+ PBUS_HANDLER Handler;
+ PCI_SLOT_NUMBER Slot;
+} HalpOrionOPB;
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#pragma alloc_text(PAGELK,HalpPCISynchronizeOrionB0)
+#pragma alloc_text(PAGELK,HalpPCIReleaseSynchronzationOrionB0)
+#endif
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+ ULONG OPBNumber;
+ BOOLEAN OPBA2B0Found, COPBInbPostingEnabled;
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return ;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ ZwClose (hMFunc);
+ return ;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ OPBNumber = 0;
+ OPBA2B0Found = FALSE;
+ COPBInbPostingEnabled = FALSE;
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ //
+ // Look for Orion PCI Bridge
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x84c4 ) {
+
+ //
+ // 82450 Orion PCI Bridge Workaround
+ // Need a workaround if following conditions are true:
+ // i) 2 OPBs present
+ // ii)There is an A2/B0 step OPB present.
+ // iii) Inbound posting on the compatibility OPB is
+ // enabled.
+ // NOTE: Inbound Posting on the non-compatibility OPB
+ // MUST BE disabled by BIOS
+ //
+
+ OPBNumber += 1;
+
+ if (PciData->RevisionID <= 4) {
+ OPBA2B0Found = TRUE;
+ }
+
+ if (SlotNumber.u.bits.DeviceNumber == (0xc8>>3)) {
+
+ // Found compatibility OPB. Determine if the compatibility
+ // OPB has inbound posting enabled by testing bit 0 of reg 54
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x54, 2);
+ COPBInbPostingEnabled = (buffer[0] & 0x1) ? TRUE : FALSE;
+
+ } else {
+
+ // The compatibility OPB ALWAYS has a device
+ // number 0xc8. Save the ncOPB slot number
+ // and BusHandler
+
+ HalpOrionOPB.Slot = SlotNumber;
+ HalpOrionOPB.Handler = BusHandler;
+ }
+ }
+ } // next function
+ } // next device
+ } // next bus
+
+ //
+ // Is Orion B0 workaround needed?
+ //
+
+ if (OPBNumber >= 2 && OPBA2B0Found && COPBInbPostingEnabled) {
+
+ //
+ // Replace synchronization functions with Orion specific functions
+ //
+
+ ASSERT (PCIConfigHandler.Synchronize == HalpPCISynchronizeType1);
+ MmLockPagableCodeSection (&HalpPCISynchronizeOrionB0);
+ PCIConfigHandler.Synchronize = HalpPCISynchronizeOrionB0;
+ PCIConfigHandler.ReleaseSynchronzation = HalpPCIReleaseSynchronzationOrionB0;
+ }
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ //
+ // Set defaults
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+ BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+ BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = 0x10;
+
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if 0
+
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit) &&
+ PCI_CONFIG_TYPE (PciData) == PCI_DEVICE_TYPE) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID
+HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ if (!HalpDoingCrashDump) {
+ *Irql = KfRaiseIrql (HIGH_LEVEL);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+VOID
+HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Disable PCI configuration space
+ //
+
+ PciCfg1.u.AsULONG = 0;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
+
+ //
+ // Release spinlock
+ //
+
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KfLowerIrql (Irql);
+ }
+}
+
+
+VOID
+HalpPCISynchronizeOrionB0 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ PCI_TYPE1_CFG_BITS Cfg1;
+ union {
+ ULONG dword;
+ USHORT word;
+ UCHAR byte[4];
+ } Buffer;
+
+ //
+ // First perform normal type 1 synchronization
+ //
+
+ HalpPCISynchronizeType1 (BusHandler, Slot, Irql, PciCfg1);
+
+ //
+ // Apply Orion B0 workaround
+ //
+
+ Cfg1.u.AsULONG=0;
+ Cfg1.u.bits.BusNumber = HalpOrionOPB.Handler->BusNumber;
+ Cfg1.u.bits.DeviceNumber = HalpOrionOPB.Slot.u.bits.DeviceNumber;
+ Cfg1.u.bits.FunctionNumber = HalpOrionOPB.Slot.u.bits.FunctionNumber;
+ Cfg1.u.bits.Enable = TRUE;
+
+ //
+ // Read OPB until we get back the expected Vendor ID and device ID
+ //
+
+ do {
+ HalpPCIReadUlongType1 (HalpOrionOPB.Handler->BusData, &Cfg1, Buffer.byte, 0);
+ } while (Buffer.dword != 0x84c48086);
+
+ //
+ // The bug is that the config read will return whatever value you
+ // happened to read last. Read register 0x54 till we don't read the
+ // last value read any more(Vendor ID/Device ID).
+ //
+
+ do {
+ HalpPCIReadUshortType1 (HalpOrionOPB.Handler->BusData, &Cfg1, Buffer.byte, 0x54);
+ } while (Buffer.word == 0x8086);
+
+ //
+ // Disable inbound posting by clearing bit 0 of register 0x54
+ //
+
+ Buffer.word &= ~0x1;
+ HalpPCIWriteUshortType1 (HalpOrionOPB.Handler->BusData, &Cfg1, Buffer.byte, 0x54);
+}
+
+VOID
+HalpPCIReleaseSynchronzationOrionB0 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+ union {
+ ULONG dword;
+ USHORT word;
+ UCHAR byte[4];
+ } Buffer;
+
+ PciCfg1.u.AsULONG=0;
+ PciCfg1.u.bits.BusNumber = HalpOrionOPB.Handler->BusNumber;
+ PciCfg1.u.bits.DeviceNumber = HalpOrionOPB.Slot.u.bits.DeviceNumber;
+ PciCfg1.u.bits.FunctionNumber = HalpOrionOPB.Slot.u.bits.FunctionNumber;
+ PciCfg1.u.bits.Enable = TRUE;
+
+ HalpPCIReadUshortType1 (HalpOrionOPB.Handler->BusData, &PciCfg1, Buffer.byte, 0x54);
+
+
+ //
+ // Enable Inbound posting by setting bit 0 of register 0x54 of ncOPB
+ //
+
+ Buffer.word |= 0x1;
+ HalpPCIWriteUshortType1 (HalpOrionOPB.Handler->BusData, &PciCfg1, Buffer.byte, 0x54);
+
+ //
+ // Complete type 1 synchronization
+ //
+
+ HalpPCIReleaseSynchronzationType1 (BusHandler, Irql);
+}
+
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
+ return sizeof (ULONG);
+}
+
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Initialize Cfg2Addr
+ //
+
+ PciCfg2Addr->u.AsUSHORT = 0;
+ PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
+ PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
+
+ //
+ // Synchronize with type2 config space - type2 config space
+ // remaps 4K of IO space, so we can not allow other I/Os to occur
+ // while using type2 config space.
+ //
+
+ HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ PciCfg2Cse.u.bits.Enable = TRUE;
+ PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
+ PciCfg2Cse.u.bits.Key = 0xff;
+
+ //
+ // Select bus & enable type 2 configuration space
+ //
+
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ //
+ // disable PCI configuration space
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
+
+ //
+ // Restore interrupts, release spinlock
+ //
+
+ HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
+ return sizeof(ULONG);
+}
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase, RequestedInterrupt;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH * 3;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // For now since there's not PnP support in the OS, if the BIOS hasn't
+ // enable a VGA device don't allow it to get enabled via this interface.
+ //
+
+ if ( (PciData->BaseClass == 0 && PciData->SubClass == 1) ||
+ (PciData->BaseClass == 3 && PciData->SubClass == 0)) {
+
+ if ((PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)) == 0) {
+ ExFreePool (WorkingPool);
+ return STATUS_DEVICE_NOT_CONNECTED;
+ }
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ RequestedInterrupt = FALSE;
+ if (PciData->u.type0.InterruptPin &&
+ PciData->u.type0.InterruptLine != (0 ^ IRQXOR) &&
+ PciData->u.type0.InterruptLine != (0xFF ^ IRQXOR)) {
+
+ RequestedInterrupt = TRUE;
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ // check for hosed PCI configuration requirements
+ if (length & ~m) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (!Is64BitBaseAddress(i) &&
+ PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (RequestedInterrupt) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO, Memory, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halx86/i386/ixpciint.c b/private/ntos/nthals/halx86/i386/ixpciint.c
new file mode 100644
index 000000000..896e141f7
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixpciint.c
@@ -0,0 +1,458 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG PciIsaIrq;
+ULONG HalpEisaELCR;
+BOOLEAN HalpDoingCrashDump;
+BOOLEAN HalpPciLockSettings;
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+#ifndef MCA
+ Isa, 0,
+#else
+ MicroChannel, 0,
+#endif
+ BusInterruptLevel ^ IRQXOR,
+ 0,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+ On a DBG build we adjust InterruptLine just to ensure driver's
+ don't connect to it without translating it on the PCI bus.
+
+--*/
+{
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ //
+ // Set vector as a level vector. (note: this code assumes the
+ // irq is static and does not move).
+ //
+
+ if (PciData->u.type0.InterruptLine >= 1 &&
+ PciData->u.type0.InterruptLine <= 15) {
+
+ //
+ // If this bit was on the in the PIC ELCR register,
+ // then mark it in PciIsaIrq. (for use in hal.dll,
+ // such that we can assume the interrupt controller
+ // has been properly marked as a level interrupt for
+ // this IRQ. Other hals probabily don't care.)
+ //
+
+ PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine);
+ }
+
+ //
+ // On a PC there's no Slot/Pin/Line mapping which needs to
+ // be done.
+ //
+
+ PciData->u.type0.InterruptLine ^= IRQXOR;
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ PciNewData->u.type0.InterruptLine ^= IRQXOR;
+
+#if DBG
+ if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine ||
+ PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) {
+ DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n");
+ DbgBreakPoint ();
+ }
+#endif
+}
+
+#if !defined(SUBCLASSPCI)
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ *Irql = KfRaiseIrql (HIGH_LEVEL);
+ KiAcquireSpinLock (SpinLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (SpinLock);
+ KfLowerIrql (Irql);
+ }
+}
+
+#endif
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+ PSUPPORTED_RANGE Range;
+ PSUPPORTED_RANGES SupportedRanges;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR buffer2[PCI_COMMON_HDR_LENGTH];
+ BOOLEAN UseBusRanges;
+ ULONG i, j, RomIndex, length, ebit;
+ ULONG Base[PCI_TYPE0_ADDRESSES + 1];
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ SupportedRanges = NULL;
+ UseBusRanges = TRUE;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ if (HalpPciLockSettings) {
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PciOrigData = (PPCI_COMMON_CONFIG) buffer2;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // If this is a device, and it current has its decodes enabled,
+ // then use the currently programmed ranges only
+ //
+
+ if (PCI_CONFIG_TYPE(PciData) == 0 &&
+ (PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
+
+ //
+ // Save current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+
+ //
+ // Write all one-bits to determine lengths for each address
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+ Base[j] = *BaseAddress[j];
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // restore original settings
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Build a memory & io range list of just the ranges already
+ // programmed into the device
+ //
+
+ UseBusRanges = FALSE;
+ SupportedRanges = HalpAllocateNewRangeList();
+ if (!SupportedRanges) {
+ goto CleanUp;
+ }
+
+ *BaseAddress[RomIndex] &= ~PCI_ADDRESS_IO_SPACE;
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+
+ i = *BaseAddress[j];
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ length = 1 << 2;
+ Range = &SupportedRanges->IO;
+ ebit = PCI_ENABLE_IO_SPACE;
+
+ } else {
+ length = 1 << 4;
+ Range = &SupportedRanges->Memory;
+ ebit = PCI_ENABLE_MEMORY_SPACE;
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Range = &SupportedRanges->PrefetchMemory;
+ }
+ }
+
+ Base[j] &= ~(length-1);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ if (j == RomIndex &&
+ !(PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)) {
+
+ // range not enabled, don't use it
+ length = 0;
+ }
+
+ if (length) {
+ if (!(PciOrigData->Command & ebit)) {
+ // range not enabled, don't use preprogrammed values
+ UseBusRanges = TRUE;
+ }
+
+ if (Range->Limit >= Range->Base) {
+ Range->Next = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ Range = Range->Next;
+ if (!Range) {
+ goto CleanUp;
+ }
+
+ Range->Next = NULL;
+ }
+
+ Range->Base = Base[j];
+ Range->Limit = Base[j] + length - 1;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ UseBusRanges ? BusHandler->BusAddresses : SupportedRanges,
+ Interrupt,
+ pResourceList
+ );
+
+CleanUp:
+ if (SupportedRanges) {
+ HalpFreeRangeList (SupportedRanges);
+ }
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == (0 ^ IRQXOR) ||
+ PciData->u.type0.InterruptLine == (0xFF ^ IRQXOR)) {
+
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halx86/i386/ixphwsup.c b/private/ntos/nthals/halx86/i386/ixphwsup.c
new file mode 100644
index 000000000..ce04cdbfb
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixphwsup.c
@@ -0,0 +1,535 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#if MCA
+
+#include "mca.h"
+
+#else
+
+#include "eisa.h"
+
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpAllocateAdapter)
+#pragma alloc_text(PAGELK,HalpGrowMapBuffers)
+#endif
+
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+BOOLEAN LessThan16Mb;
+BOOLEAN HalpEisaDma;
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+ Caller owns the HalpNewAdapter event
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ PHYSICAL_ADDRESS physicalAddress;
+ KIRQL Irql;
+ PVOID CodeLockHandle;
+
+ PAGED_CODE();
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+
+ //
+ // No more memory can be allocated.
+ //
+
+ return(FALSE);
+ }
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+ return(FALSE);
+ }
+
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ // Serialize with master adapter object
+ //
+
+ CodeLockHandle = MmLockPagableCodeSection (&HalpGrowMapBuffers);
+ Irql = KfAcquireSpinLock( &AdapterObject->SpinLock );
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (LONG) i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!HalpEisaDma &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ //
+ // Release master adapter object
+ //
+
+ KfReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ MmUnlockPagableImageSection (CodeLockHandle);
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+ Caller owns the HalpNewAdapter event
+
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ PAGED_CODE();
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1 &&
+ MapRegistersPerChannel) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *IoAdapterObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoAdapterObjectType,
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ RtlZeroMemory (AdapterObject, sizeof (ADAPTER_OBJECT));
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
diff --git a/private/ntos/nthals/halx86/i386/ixproc.c b/private/ntos/nthals/halx86/i386/ixproc.c
new file mode 100644
index 000000000..c9782e366
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixproc.c
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixsproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PC Compatible Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpMcaInit (
+ VOID
+ );
+
+VOID HalpInitOtherBuses (VOID);
+VOID HalpInitializePciBus (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ // do nothing
+ return TRUE;
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ // do nothing
+ return TRUE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Turn on MCA support if present
+ //
+
+ HalpMcaInit();
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+#if 0
+ //
+ // Display all buses & ranges
+ //
+
+ HalpDisplayAllBusRanges ();
+#endif
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halx86/i386/ixprofil.asm b/private/ntos/nthals/halx86/i386/ixprofil.asm
new file mode 100644
index 000000000..5758de5d9
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixprofil.asm
@@ -0,0 +1,437 @@
+
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixprofile.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to initialize,
+; field and process the profile interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Landy Wang (landy@corollary.com) 26-Mar-1992
+; Move much code into separate modules for easy inclusion by various
+; HAL builds.
+;
+; Add HalBeginSystemInterrupt() call at beginning of ProfileInterrupt
+; code - this must be done before any sti.
+; Also add HalpProfileInterrupt2ndEntry for additional processors to
+; join the flow of things.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+include mac386.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+RegisterAProfileValue db 00101000B ; default interval = 3.90625 ms
+
+align 4
+ProfileIntervalTable dd 1221 ; unit = 100 ns
+ dd 2441
+ dd 4883
+ dd 9766
+ dd 19531
+ dd 39063
+ dd 78125
+ dd 156250
+ dd 312500
+ dd 625000
+ dd 1250000
+ dd 2500000
+ dd 5000000
+ dd 5000000 OR 80000000H
+
+ProfileIntervalInitTable db 00100011B
+ db 00100100B
+ db 00100101B
+ db 00100110B
+ db 00100111B
+ db 00101000B
+ db 00101001B
+ db 00101010B
+ db 00101011B
+ db 00101100B
+ db 00101101B
+ db 00101110B
+ db 00101111B
+ db 00101111B
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+HalpProfileInterval dd -1
+HalpProfilingStopped dd 1
+
+;
+; HALs wishing to reuse the code in this module should set the HAL
+; global variable IxProfileVector to their profile vector.
+;
+ public _IxProfileVector
+_IxProfileVector dd PROFILE_VECTOR
+
+_DATA ends
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; HalStartProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the slowest thing we can get away with to the value
+; that's been KeSetProfileInterval
+;
+; All processors will run this routine, but it doesn't hurt to have
+; each one reinitialize the CMOS, since none of them will be let go
+; from the stall until they all finish.
+;
+;--
+
+cPublicProc _HalStartProfileInterrupt ,1
+
+; Mark profiling as active
+;
+
+ mov dword ptr HalpProfilingStopped, 0
+
+;
+; Set the interrupt rate to what is actually needed
+;
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov al, RegisterAProfileValue
+ shl ax, 8
+ mov al, 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ stdRET _HalStartProfileInterrupt
+
+stdENDP _HalStartProfileInterrupt
+
+
+
+;++
+;
+; HalStopProfileInterrupt(
+; IN ULONG Reserved
+; );
+;
+; Routine Description:
+;
+; What we do here is change the interrupt
+; rate from the high profiling rate to the slowest thing we
+; can get away with for PerformanceCounter rollover notification.
+;
+;--
+
+cPublicProc _HalStopProfileInterrupt ,1
+
+;
+; Turn off profiling hit computation and profile interrupt
+;
+
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_DISABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending profiling interrupt
+ mov dword ptr HalpProfilingStopped, 1
+ stdCall _HalpReleaseCmosSpinLock
+
+ stdRET _HalStopProfileInterrupt
+
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; If profiling is active (KiProfilingStopped == 0) the actual
+; hardware interrupt rate will be set. Otherwise, a simple
+; rate validation computation is done.
+;
+; Arguments:
+;
+; (TOS+4) - Interval in 100ns unit.
+;
+; Return Value:
+;
+; Interval actually used by system.
+;
+;--
+
+cPublicProc _HalSetProfileInterval ,1
+
+ mov edx, [esp+4] ; [edx] = interval in 100ns unit
+ and edx, 7FFFFFFFh ; Remove highest bit.
+ mov ecx, 0 ; index = 0
+
+Hspi00:
+ mov eax, ProfileIntervalTable[ecx * 4]
+ cmp edx, eax ; if request interval < suport interval
+ jbe short Hspi10 ; if be, find supported interval
+ inc ecx
+ jmp short Hspi00
+
+Hspi10:
+ and eax, 7FFFFFFFh ; remove highest bit from supported interval
+ jecxz short Hspi20 ; If first entry then use it
+
+ push esi ; See which is closer to requested
+ mov esi, eax ; rate - current entry, or preceeding
+ sub esi, edx
+
+ sub edx, ProfileIntervalTable[ecx * 4 - 4]
+ cmp esi, edx
+ pop esi
+ jc short Hspi20
+
+ dec ecx ; use preceeding entry
+ mov eax, ProfileIntervalTable[ecx * 4]
+
+Hspi20:
+ push eax ; save interval value
+ mov al, ProfileIntervalInitTable[ecx]
+ mov RegisterAProfileValue, al
+ test dword ptr HalpProfilingStopped,-1
+ jnz short Hspi90
+
+ stdCall _HalStartProfileInterrupt,<0> ; Re-start profile interrupt
+ ; with the new interval
+
+Hspi90: pop eax
+ stdRET _HalSetProfileInterval ; (eax) = cReturn interval
+
+stdENDP _HalSetProfileInterval
+
+ page ,132
+ subttl "System Profile Interrupt"
+;++
+;
+; Routine Description:
+;
+; This routine is entered as the result of a profile interrupt.
+; Its function is to dismiss the interrupt, raise system Irql to
+; PROFILE_LEVEL and transfer control to
+; the standard system routine to process any active profiles.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; Does not return, jumps directly to KeProfileInterrupt, which returns
+;
+; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
+;
+;--
+ ENTER_DR_ASSIST Hpi_a, Hpi_t
+
+cPublicProc _HalpProfileInterrupt ,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hpi_a, Hpi_t
+
+;
+; (esp) - base of trap frame
+;
+; HalBeginSystemInterrupt must be called before any sti's
+;
+;
+
+ push _IxProfileVector
+ sub esp, 4 ; allocate space to save OldIrql
+ stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,_IxProfileVector,esp>
+
+ or al,al ; check for spurious interrupt
+ jz short Hpi100
+
+
+;
+; This is the RTC interrupt, so we have to clear the
+; interrupt flag on the RTC.
+;
+ stdCall _HalpAcquireCmosSpinLock
+
+;
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+if DBG
+ align 4
+Hpi10: test al, 80h
+ jz short Hpi15
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ jmp short Hpi10
+Hpi15:
+endif ; DBG
+
+ stdCall _HalpReleaseCmosSpinLock
+
+ sti
+;
+; This entry point is provided for symmetric multiprocessor HALs.
+; Since it only makes sense for one processor to clear the CMOS,
+; all other processors can instead jmp into this entry point.
+;
+
+ align 4
+ public _HalpProfileInterrupt2ndEntry@0
+_HalpProfileInterrupt2ndEntry@0:
+
+;
+; (esp) = OldIrql
+; (esp+4) = H/W vector
+; (esp+8) = base of trap frame
+;
+
+;
+; Now check for any profiling stuff to do.
+;
+
+ cmp HalpProfilingStopped, dword ptr 1 ; Has profiling been stopped?
+ jz short Hpi90 ; if z, prof disenabled
+
+ stdCall _KeProfileInterrupt,<ebp> ; (ebp) = trapframe
+
+Hpi90:
+ INTERRUPT_EXIT
+
+ align 4
+Hpi100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+stdENDP _HalpProfileInterrupt
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixreboot.c b/private/ntos/nthals/halx86/i386/ixreboot.c
new file mode 100644
index 000000000..a310dd73d
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixreboot.c
@@ -0,0 +1,143 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixreboot.c
+
+Abstract:
+
+ Provides the interface to the firmware for x86. Since there is no
+ firmware to speak of on x86, this is just reboot support.
+
+Author:
+
+ John Vert (jvert) 12-Aug-1991
+
+Revision History:
+
+--*/
+#include "halp.h"
+
+//
+// Defines to let us diddle the CMOS clock and the keyboard
+//
+
+#define CMOS_CTRL (PUCHAR )0x70
+#define CMOS_DATA (PUCHAR )0x71
+
+#define RESET 0xfe
+#define KEYBPORT (PUCHAR )0x64
+
+//
+// Private function prototypes
+//
+
+VOID
+HalpReboot (
+ VOID
+ );
+
+VOID
+HalpReboot (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure resets the CMOS clock to the standard timer settings
+ so the bios will work, and then issues a reset command to the keyboard
+ to cause a warm boot.
+
+ It is very machine dependent, this implementation is intended for
+ PC-AT like machines.
+
+ This code copied from the "old debugger" sources.
+
+ N.B.
+
+ Will NOT return.
+
+--*/
+
+{
+ UCHAR Scratch;
+ PUSHORT Magic;
+
+ //
+ // By sticking 0x1234 at physical location 0x472, we can bypass the
+ // memory check after a reboot.
+ //
+
+ Magic = HalpMapPhysicalMemory(0, 1);
+ Magic[0x472 / sizeof(USHORT)] = 0x1234;
+
+ //
+ // Turn off interrupts
+ //
+
+ HalpAcquireCmosSpinLock();
+
+ _asm {
+ cli
+ }
+
+ //
+ // Reset the cmos clock to a standard value
+ // (We are setting the periodic interrupt control on the MC147818)
+ //
+
+ //
+ // Disable periodic interrupt
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x0b); // Set up for control reg B.
+ KeStallExecutionProcessor(1);
+
+ Scratch = READ_PORT_UCHAR(CMOS_DATA);
+ KeStallExecutionProcessor(1);
+
+ Scratch &= 0xbf; // Clear periodic interrupt enable
+
+ WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
+ KeStallExecutionProcessor(1);
+
+ //
+ // Set "standard" divider rate
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x0a); // Set up for control reg A.
+ KeStallExecutionProcessor(1);
+
+ Scratch = READ_PORT_UCHAR(CMOS_DATA);
+ KeStallExecutionProcessor(1);
+
+ Scratch &= 0xf0; // Clear rate setting
+ Scratch |= 6; // Set default rate and divider
+
+ WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
+ KeStallExecutionProcessor(1);
+
+ //
+ // Set a "neutral" cmos address to prevent weirdness
+ // (Why is this needed? Source this was copied from doesn't say)
+ //
+
+ WRITE_PORT_UCHAR(CMOS_CTRL, 0x15);
+ KeStallExecutionProcessor(1);
+
+ HalpResetAllProcessors();
+
+ //
+ // If we return, send the reset command to the keyboard controller
+ //
+
+ WRITE_PORT_UCHAR(KEYBPORT, RESET);
+
+ _asm {
+ hlt
+ }
+}
diff --git a/private/ntos/nthals/halx86/i386/ixstall.asm b/private/ntos/nthals/halx86/i386/ixstall.asm
new file mode 100644
index 000000000..3bc27318c
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixstall.asm
@@ -0,0 +1,480 @@
+
+ title "Stall Execution Support"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixstall.asm
+;
+; Abstract:
+;
+; This module implements the code necessary to field and process the
+; interval clock interrupt.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) 12-Jan-1990
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+; bryanwi 20-Sep-90
+;
+; Add KiSetProfileInterval, KiStartProfileInterrupt,
+; KiStopProfileInterrupt procedures.
+; KiProfileInterrupt ISR.
+; KiProfileList, KiProfileLock are delcared here.
+;
+; shielint 10-Dec-90
+; Add performance counter support.
+; Move system clock to irq8, ie we now use RTC to generate system
+; clock. Performance count and Profile use timer 1 counter 0.
+; The interval of the irq0 interrupt can be changed by
+; KiSetProfileInterval. Performance counter does not care about the
+; interval of the interrupt as long as it knows the rollover count.
+; Note: Currently I implemented 1 performance counter for the whole
+; i386 NT.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; shie-lin tzong (shielint) 13-March-92
+; Move System clock back to irq0 and use RTC (irq8) to generate
+; profile interrupt. Performance counter and system clock use time1
+; counter 0 of 8254.
+;
+; Landy Wang (corollary!landy) 04-Dec-92
+; Created this module by moving routines from ixclock.asm to here.
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include i386\ixcmos.inc
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+RTCIRQ EQU 8 ; IRQ number for RTC interrupt
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+;
+; RegisterAInitByte sets 8Hz clock rate, used during init to set up
+; KeStallExecutionProcessor, etc. (See RegASystemClockByte below.)
+;
+
+RegisterAInitByte EQU 00101101B ; RT/CMOS Register 'A' init byte
+ ; 32.768KHz Base divider rate
+ ; 8Hz int rate, period = 125.0ms
+PeriodInMicroSecond EQU 125000 ;
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+HalpP0BugBugStallCount dd 0
+
+_DATA ends
+
+INIT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Initialize Stall Execution Counter"
+;++
+;
+; VOID
+; HalpInitializeStallExecution (
+; IN CCHAR ProcessorNumber
+; )
+;
+; Routine Description:
+;
+; This routine initialize the per Microsecond counter for
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; ProcessorNumber - Processor Number
+;
+; Return Value:
+;
+; None.
+;
+; Note:
+;
+; Current implementation assumes that all the processors share
+; the same Real Time Clock. So, the dispatcher database lock is
+; acquired before entering this routine to guarantee only one
+; processor can access the routine.
+;
+;--
+
+KiseInterruptCount equ [ebp-12] ; local variable
+
+cPublicProc _HalpInitializeStallExecution ,1
+
+ifndef NT_UP
+;;
+;; This function currently doesn't work from any processor but the
+;; boot processor - for now stub out the others
+;;
+
+ mov eax, PCR[PcPrcb]
+ cmp byte ptr [eax].PbNumber, 0
+ je @f
+
+ mov eax, HalpP0BugBugStallCount
+ mov PCR[PcStallScaleFactor], eax
+ stdRET _HalpInitializeStallExecution
+@@:
+endif
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 12 bytes for local use
+ sub esp, 12
+
+ pushfd ; save caller's eflag
+
+;
+; Initialize Real Time Clock to interrupt us for every 125ms at
+; IRQ 8.
+;
+
+ cli ; make sure interrupts are disabled
+
+;
+; Get and save current 8259 masks
+;
+
+ xor eax,eax
+
+;
+; Assume there is no third and fourth PICs
+;
+; Get interrupt Mask on PIC2
+;
+
+ in al,PIC2_PORT1
+ shl eax, 8
+
+;
+; Get interrupt Mask on PIC1
+;
+
+ in al,PIC1_PORT1
+ push eax ; save the masks
+ mov eax, NOT (( 1 SHL PIC_SLAVE_IRQ) + (1 SHL RTCIRQ))
+ ; Mask all the irqs except irq 2 and 8
+ SET_8259_MASK ; Set 8259's int mask register
+
+;
+; Since RTC interrupt will come from IRQ 8, we need to
+; Save original irq 8 descriptor and set the descriptor to point to
+; our own handler.
+;
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov ecx, [ebp-6] ; (ecx)->IDT
+
+ mov eax, (RTCIRQ+PRIMARY_VECTOR_BASE)
+
+ shl eax, 3 ; 8 bytes per IDT entry
+ add ecx, eax ; now at the correct IDT RTC entry
+
+ push dword ptr [ecx] ; (TOS) = original desc of IRQ 8
+ push dword ptr [ecx + 4] ; each descriptor has 8 bytes
+
+ ;
+ ; Pushing the appropriate entry address now (instead of
+ ; the IDT start address later) to make the pop at the end simpler.
+ ;
+ push ecx ; (TOS) -> &IDT[HalProfileVector]
+
+ mov eax, offset FLAT:RealTimeClockHandler
+
+ mov word ptr [ecx], ax ; Lower half of handler addr
+ mov word ptr [ecx+2], KGDT_R0_CODE ; set up selector
+ mov word ptr [ecx+4], D_INT032 ; 386 interrupt gate
+
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [ecx+6], ax
+
+ mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ mov dword ptr [KiseInterruptCount], 0
+
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Now enable the interrupt and start the counter
+; (As a matter of fact, only IRQ8 can come through.)
+;
+ xor eax, eax ; (eax) = 0, initialize loopcount
+ALIGN 16
+ sti
+ jmp kise10
+
+ALIGN 16
+kise10:
+ sub eax, 1 ; increment the loopcount
+ jnz short kise10
+
+if DBG
+;
+; Counter overflowed
+;
+
+ stdCall _DbgBreakPoint
+endif
+ jmp short kise10
+
+;
+; Our RealTimeClock interrupt handler. The control comes here through
+; irq 8.
+; Note: we discard first real time clock interrupt and compute the
+; permicrosecond loopcount on receiving of the second real time
+; interrupt. This is because the first interrupt is generated
+; based on the previous real time tick interval.
+;
+
+RealTimeClockHandler:
+
+ inc dword ptr KiseInterruptCount ; increment interrupt count
+ cmp dword ptr KiseInterruptCount,1 ; Is this the first interrupt?
+ jnz short kise25 ; no, its the second go process it
+ pop eax ; get rid of original ret addr
+ push offset FLAT:kise10 ; set new return addr
+
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+;
+; Don't clobber the Daylight Savings Time bit in register B, because we
+; stash the LastKnownGood "environment variable" there.
+;
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+;
+; Dismiss the interrupt.
+;
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ xor eax, eax ; reset loop counter
+
+ iretd
+
+kise25:
+
+;
+; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount
+;
+
+if DBG
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint
+
+endif
+ ; never return
+;
+; ** End temporay code
+;
+
+kise30:
+ neg eax
+ xor edx, edx ; (edx:eax) = divident
+ mov ecx, PeriodInMicroSecond; (ecx) = time spent in the loop
+ div ecx ; (eax) = loop count per microsecond
+ cmp edx, 0 ; Is remainder =0?
+ jz short kise40 ; yes, go kise40
+ inc eax ; increment loopcount by 1
+kise40:
+ mov PCR[PcStallScaleFactor], eax
+ mov HalpP0BugBugStallCount, eax
+
+;
+; Reset return address to kexit
+;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+ mov eax, (HIGHEST_LEVEL_FOR_8259 - RTCIRQ)
+
+;
+; Shutdown periodic interrupt
+;
+ stdCall _HalpAcquireCmosSpinLock
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax, 0bh
+ CMOS_READ
+ and al, 1
+ mov ah, al
+ or ah, REGISTER_B_DISABLE_PERIODIC_INTERRUPT
+ mov al, 0bh
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending interrupt
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Dismiss the interrupt.
+;
+ mov eax, RTCIRQ
+ mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+ iretd
+
+kexit: ; Interrupts are disabled
+ pop ecx ; (ecx) -> &IDT[HalProfileVector]
+ pop [ecx+4] ; restore higher half of RTC desc
+ pop [ecx] ; restore lower half of RTC desc
+
+ pop eax ; (eax) = origianl 8259 int masks
+ SET_8259_MASK
+
+ popfd ; restore caller's eflags
+ mov esp, ebp
+ pop ebp ; restore ebp
+ stdRET _HalpInitializeStallExecution
+
+stdENDP _HalpInitializeStallExecution
+
+INIT ends
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Stall Execution"
+;++
+;
+; VOID
+; KeStallExecutionProcessor (
+; IN ULONG MicroSeconds
+; )
+;
+; Routine Description:
+;
+; This function stalls execution for the specified number of microseconds.
+; KeStallExecutionProcessor
+;
+; Arguments:
+;
+; MicroSeconds - Supplies the number of microseconds that execution is to be
+; stalled.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+MicroSeconds equ [esp + 4]
+
+
+cPublicProc _KeStallExecutionProcessor ,1
+cPublicFpo 1, 0
+
+ mov ecx, MicroSeconds ; (ecx) = Microseconds
+ jecxz short kese10 ; return if no loop needed
+
+ mov eax, PCR[PcStallScaleFactor] ; get per microsecond
+ ; loop count for the processor
+ mul ecx ; (eax) = desired loop count
+
+if DBG
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short @f
+ int 3
+
+@@: cmp eax,0
+ jnz short @f
+ int 3
+@@:
+endif
+ALIGN 16
+ jmp kese05
+
+ALIGN 16
+kese05: sub eax, 1 ; (eax) = (eax) - 1
+ jnz short kese05
+kese10:
+ stdRET _KeStallExecutionProcessor
+
+stdENDP _KeStallExecutionProcessor
+
+_TEXT ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixswint.asm b/private/ntos/nthals/halx86/i386/ixswint.asm
new file mode 100644
index 000000000..2ca5c88e2
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixswint.asm
@@ -0,0 +1,327 @@
+ title "Software Interrupts"
+
+;++
+;
+; Copyright (c) 1992 Microsoft Corporation
+;
+; Module Name:
+;
+; ixswint.asm
+;
+; Abstract:
+;
+; This module implements the software interrupt handlers
+; for x86 machines
+;
+; Author:
+;
+; John Vert (jvert) 2-Jan-1992
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+ .list
+
+ EXTRNP _KiDeliverApc,3,IMPORT
+ EXTRNP _KiDispatchInterrupt,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ extrn SWInterruptHandlerTable:dword
+ extrn SWInterruptLookUpTable:byte
+ifdef IRQL_METRICS
+ extrn HalApcSoftwareIntCount:dword
+ extrn HalDpcSoftwareIntCount:dword
+endif
+
+_TEXT$02 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "Request Software Interrupt"
+
+;++
+;
+; VOID
+; HalRequestSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to request a software interrupt to the
+; system. Also, this routine checks to see if any software
+; interrupt should be generated.
+; The following condition will cause software interrupt to
+; be simulated:
+; any software interrupt which has higher priority than
+; current IRQL's is pending.
+;
+; NOTE: This routine simulates software interrupt as long as
+; any pending SW interrupt level is higher than the current
+; IRQL, even when interrupts are disabled.
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalRequestSoftwareInterrupt ,1
+cPublicFpo 0, 1
+
+ mov eax,1
+ shl eax, cl ; convert to mask
+ pushfd ; save interrupt mode
+ cli ; disable interrupt
+ or PCR[PcIRR], eax ; set the request bit
+ mov cl, PCR[PcIrql] ; get current IRQL
+
+ mov eax, PCR[PcIRR] ; get SW interrupt request register
+ and eax, 3 ; mask off pending HW interrupts
+
+ xor edx, edx
+ mov dl, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp dl, cl ; Is highest SW int level > irql?
+ jbe short KsiExit ; No, jmp ksiexit
+ call SWInterruptHandlerTable[edx*4] ; yes, simulate interrupt
+ ; to the appropriate handler
+KsiExit:
+ popfd ; restore original interrupt mode
+ fstRET HalRequestSoftwareInterrupt
+
+fstENDP HalRequestSoftwareInterrupt
+
+ page ,132
+ subttl "Request Software Interrupt"
+
+;++
+;
+; VOID
+; HalClearSoftwareInterrupt (
+; IN KIRQL RequestIrql
+; )
+;
+; Routine Description:
+;
+; This routine is used to clear a possible pending software interrupt.
+; Support for this function is optional, and allows the kernel to
+; reduce the number of spurious software interrupts it receives/
+;
+; Arguments:
+;
+; (cl) = RequestIrql - Supplies the request IRQL value
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall HalClearSoftwareInterrupt ,1
+cPublicFpo 0, 0
+
+ mov eax,1
+ shl eax, cl ; convert to mask
+
+ not eax
+ and PCR[PcIRR], eax ; clear pending irr bit
+
+ fstRET HalClearSoftwareInterrupt
+
+fstENDP HalClearSoftwareInterrupt
+
+
+
+ page ,132
+ subttl "Dispatch Interrupt"
+;++
+;
+; VOID
+; HalpDispatchInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is the interrupt handler for a software interrupt generated
+; at DISPATCH_LEVEL. Its function is to save the machine state, raise
+; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
+; delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hdpi_a, hdpi_t
+
+ align dword
+ public _HalpDispatchInterrupt
+_HalpDispatchInterrupt proc
+ifdef IRQL_METRICS
+ lock inc HalDpcSoftwareIntCount
+endif
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state on trap frame
+;
+
+ ENTER_INTERRUPT hdpi_a, hdpi_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+ public _HalpDispatchInterrupt2ndEntry
+_HalpDispatchInterrupt2ndEntry:
+
+; Save previous IRQL and set new priority level
+
+ push PCR[PcIrql] ; save previous IRQL
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
+ and dword ptr PCR[PcIRR], not (1 shl DISPATCH_LEVEL) ; clear the pending bit in IRR
+
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; Go do Dispatch Interrupt processing
+;
+ stdCall _KiDispatchInterrupt
+
+;
+; Do interrupt exit processing
+;
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+_HalpDispatchInterrupt endp
+
+ page ,132
+ subttl "APC Interrupt"
+;++
+;
+; HalpApcInterrupt(
+; VOID
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of a software interrupt generated
+; at APC_LEVEL. Its function is to save the machine state, raise Irql to
+; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
+;
+; Arguments:
+;
+; None
+; Interrupt is Disabled
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST hapc_a, hapc_t
+
+ align dword
+ public _HalpApcInterrupt
+_HalpApcInterrupt proc
+ifdef IRQL_METRICS
+ lock inc HalApcSoftwareIntCount
+endif
+;
+; Create IRET frame on stack
+;
+ pop eax
+ pushfd
+ push cs
+ push eax
+
+;
+; Save machine state in trap frame
+;
+ ENTER_INTERRUPT hapc_a, hapc_t
+.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
+
+
+ public _HalpApcInterrupt2ndEntry
+_HalpApcInterrupt2ndEntry:
+
+;
+; Save previous IRQL and set new priority level
+;
+
+ push PCR[PcIrql] ; save previous Irql
+ mov byte ptr PCR[PcIrql], APC_LEVEL ; set new Irql
+ and dword ptr PCR[PcIRR], not (1 shl APC_LEVEL) ; dismiss pending APC
+;
+; Now it is safe to enable interrupt to allow higher priority interrupt
+; to come in.
+;
+
+ sti
+
+;
+; call the APC delivery routine.
+;
+
+ mov eax, [ebp]+TsSegCs ; get interrupted code's CS
+ and eax, MODE_MASK ; extract the mode
+
+ test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
+ jz short @f
+
+ or eax, MODE_MASK ; If v86 frame, then set user_mode
+@@:
+
+;
+; call APC deliver routine
+; Previous mode
+; Null exception frame
+; Trap frame
+
+ stdCall _KiDeliverApc, <eax, 0,ebp>
+
+;
+;
+; Do interrupt exit processing
+;
+
+ SOFT_INTERRUPT_EXIT ; will do an iret
+
+_HalpApcInterrupt endp
+
+_TEXT$02 ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/ixsysbus.c b/private/ntos/nthals/halx86/i386/ixsysbus.c
new file mode 100644
index 000000000..a5463cb31
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixsysbus.c
@@ -0,0 +1,188 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+ SystemVector = BusInterruptLevel + PRIMARY_VECTOR_BASE;
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ SystemVector > PRIMARY_VECTOR_BASE + HIGHEST_LEVEL_FOR_8259 ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = (KIRQL)(HIGHEST_LEVEL_FOR_8259 + PRIMARY_VECTOR_BASE - SystemVector);
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+ return SystemVector;
+}
+
diff --git a/private/ntos/nthals/halx86/i386/ixsysint.asm b/private/ntos/nthals/halx86/i386/ixsysint.asm
new file mode 100644
index 000000000..e73b40f24
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixsysint.asm
@@ -0,0 +1,582 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixsysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts.
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ifdef IRQL_METRICS
+ extrn HalPostponedIntCount:dword
+endif
+ extrn _PciIsaIrq:dword
+ extrn SWInterruptHandlerTable:dword
+ extrn HalpHardwareInterruptLevel:proc
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; Macros to Read/Write/Reset CMOS to initialize RTC
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+align dword
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irq 0
+ dd offset FLAT:HalpDismissNormal ; irq 1
+ dd offset FLAT:HalpDismissNormal ; irq 2
+ dd offset FLAT:HalpDismissNormal ; irq 3
+ dd offset FLAT:HalpDismissNormal ; irq 4
+ dd offset FLAT:HalpDismissNormal ; irq 5
+ dd offset FLAT:HalpDismissNormal ; irq 6
+ dd offset FLAT:HalpDismissIrq07 ; irq 7
+ dd offset FLAT:HalpDismissNormal ; irq 8
+ dd offset FLAT:HalpDismissNormal ; irq 9
+ dd offset FLAT:HalpDismissNormal ; irq A
+ dd offset FLAT:HalpDismissNormal ; irq B
+ dd offset FLAT:HalpDismissNormal ; irq C
+ dd offset FLAT:HalpDismissIrq0d ; irq D
+ dd offset FLAT:HalpDismissNormal ; irq E
+ dd offset FLAT:HalpDismissIrq0f ; irq F
+ dd offset FLAT:HalpDismissNormal ; irq 10
+ dd offset FLAT:HalpDismissNormal ; irq 11
+ dd offset FLAT:HalpDismissNormal ; irq 12
+ dd offset FLAT:HalpDismissNormal ; irq 13
+ dd offset FLAT:HalpDismissNormal ; irq 14
+ dd offset FLAT:HalpDismissNormal ; irq 15
+ dd offset FLAT:HalpDismissNormal ; irq 16
+ dd offset FLAT:HalpDismissNormal ; irq 17
+ dd offset FLAT:HalpDismissNormal ; irq 18
+ dd offset FLAT:HalpDismissNormal ; irq 19
+ dd offset FLAT:HalpDismissNormal ; irq 1A
+ dd offset FLAT:HalpDismissNormal ; irq 1B
+ dd offset FLAT:HalpDismissNormal ; irq 1C
+ dd offset FLAT:HalpDismissNormal ; irq 1D
+ dd offset FLAT:HalpDismissNormal ; irq 1E
+ dd offset FLAT:HalpDismissNormal ; irq 1F
+ dd offset FLAT:HalpDismissNormal ; irq 20
+ dd offset FLAT:HalpDismissNormal ; irq 21
+ dd offset FLAT:HalpDismissNormal ; irq 22
+ dd offset FLAT:HalpDismissNormal ; irq 23
+
+ public HalpSpecialDismissLevelTable
+HalpSpecialDismissLevelTable label dword
+ dd offset FLAT:HalpDismissLevel ; irq 0
+ dd offset FLAT:HalpDismissLevel ; irq 1
+ dd offset FLAT:HalpDismissLevel ; irq 2
+ dd offset FLAT:HalpDismissLevel ; irq 3
+ dd offset FLAT:HalpDismissLevel ; irq 4
+ dd offset FLAT:HalpDismissLevel ; irq 5
+ dd offset FLAT:HalpDismissLevel ; irq 6
+ dd offset FLAT:HalpDismissIrq07Level ; irq 7
+ dd offset FLAT:HalpDismissLevel ; irq 8
+ dd offset FLAT:HalpDismissLevel ; irq 9
+ dd offset FLAT:HalpDismissLevel ; irq A
+ dd offset FLAT:HalpDismissLevel ; irq B
+ dd offset FLAT:HalpDismissLevel ; irq C
+ dd offset FLAT:HalpDismissIrq0dLevel ; irq D
+ dd offset FLAT:HalpDismissLevel ; irq E
+ dd offset FLAT:HalpDismissIrq0fLevel ; irq F
+
+_DATA ENDS
+
+_TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+; On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
+; This is fine since the irql is being raise to mask it off.
+; HalEndSystemInterrupt is simply a LowerIrql request.
+;
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+.FPO ( 0, 3, 0, 0, 0, 0 )
+ xor ecx, ecx
+ mov cl, HbsiVector ; (ecx) = System Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 IRQ #
+if DBG
+ cmp ecx, 1fh
+ jbe hbsi00
+ int 3
+hbsi00:
+
+endif
+ jmp HalpSpecialDismissTable[ecx*4]
+
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+HalpIrq0fSpurious:
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz HalpDismissNormal ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq0d:
+;
+; Clear the NPX busy latch.
+;
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+align 4
+HalpDismissNormal:
+;
+; Raise IRQL to requested level
+;
+ xor ebx,ebx
+ mov al, HbsiIrql ; (al) = New irql
+ ; (ecx) = IRQ #
+ mov bl, PCR[PcIrql] ; (ebx) = Current Irql
+
+;
+; Now we check to make sure the Irql of this interrupt > current Irql.
+; If it is not, we dismiss it as spurious and set the appropriate bit
+; in the IRR so we can dispatch the interrupt when Irql is lowered
+;
+ cmp al, bl
+ jbe Hdsi300
+
+ mov PCR[PcIrql], al ; set new Irql
+ mov edx, HbsiOldIrql ; save current irql to OldIrql variable
+ mov byte ptr [edx], bl
+
+;
+; Dismiss interrupt.
+;
+ mov eax, ecx ; (eax) = IRQ #
+ cmp eax, 8 ; EOI to master or slave?
+ jae short Hbsi100 ; EIO to both master and slave
+
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+Hbsi100:
+ add al, OCW2_SPECIFIC_EOI - 8 ; specific eoi to slave
+ out PIC2_PORT0, al
+
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+Hdsi300:
+;
+; An interrupt has come in at a lower Irql, so we dismiss it as spurious and
+; set the appropriate bit in the IRR so that KeLowerIrql knows to dispatch
+; it when Irql is lowered.
+;
+; (ecx) = 8259 IRQ#
+; (al) = New Irql
+; (ebx) = Current Irql
+;
+
+ mov eax, 1
+ add ecx, 4 ; (ecx) = Irq # + 4
+ shl eax, cl
+ or PCR[PcIRR], eax
+
+;
+; Raise Irql to prevent it from happening again
+;
+
+;
+; Get the PIC masks for Irql
+;
+
+ mov eax, KiI8259MaskTable[ebx*4]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+Hbsi390:
+
+ifdef IRQL_METRICS
+ lock inc HalPostponedIntCount
+endif
+
+ xor eax, eax ; return FALSE, spurious interrupt
+ stdRET _HalBeginSystemInterrupt
+
+
+HalpDismissIrq0fLevel:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissLevel ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+ jmp HalpIrq0fSpurious
+
+HalpDismissIrq07Level:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissLevel ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq0dLevel:
+;
+; Clear the NPX busy latch.
+;
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+align 4
+HalpDismissLevel:
+;
+; Mask this level interrupt off
+; (ecx) = 8259 IRQ#
+;
+ mov al, HbsiIrql ; (al) = New irql
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, PCR[PcIDR] ; mask disabled irqs
+ SET_8259_MASK ; send mask to 8259s
+;
+; The SWInterruptHandler for this vector has been set to a NOP.
+; Set the vector's IRR so that Lower Irql will clear the 8259 mask for this
+; Irq when the irql is lowered below this level.
+;
+ mov eax, ecx ; (eax) = Irq #
+ mov ebx, 1
+ add ecx, 4 ; (ecx) = Irq # + 4
+ shl ebx, cl
+ or PCR[PcIRR], ebx
+
+;
+; Dismiss interrupt. Current interrupt is already masked off.
+; Then check to make sure the Irql of this interrupt > current Irql.
+; If it is not, we dismiss it as spurious - since this is a level interrupt
+; when the 8259's are unmasked the interrupt will reoccur
+;
+ mov cl, HbsiIrql
+ mov bl, PCR[PcIrql]
+ mov edx, HbsiOldIrql
+
+ cmp eax, 8 ; EOI to master or slave?
+ jae short Hbsi450 ; EIO to both master and slave
+
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+
+ cmp cl, bl
+ jbe short Hbsi390 ; Spurious?
+
+ mov PCR[PcIrql], cl ; raise to new irql
+ mov byte ptr [edx], bl ; return old irql
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+Hbsi450:
+ add al, OCW2_SPECIFIC_EOI - 8 ; specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ cmp cl, bl
+ jbe Hbsi390 ; Spurious?
+
+ mov PCR[PcIrql], cl ; raise to new irql
+ mov byte ptr [edx], bl ; return old irql
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+stdENDP _HalBeginSystemInterrupt
+
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt ,2
+.FPO ( 0, 2, 0, 0, 0, 0 )
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or PCR[PcIDR], edx
+ xor eax, eax
+
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt ,3
+.FPO ( 0, 3, 0, 0, 0, 0 )
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc hes_error
+ cmp ecx, CLOCK2_LEVEL
+ jnc hes_error
+
+;
+; If this interrupt is mapped through ISA via the PCI bus then it's
+; a level interrupt - treat it as such.
+;
+ bt _PciIsaIrq, ecx
+ jnc short @f
+
+;
+; It's OK to treat a level interrupt as an edge interrupt (just a performance
+; slow-down), but it's not OK to treat an edge interrupt as a level interrupt.
+; if the driver didn't say it's level, treat it as an edge
+;
+
+ mov al, [esp+12]
+ cmp al, 0
+ jnz short @f
+
+ mov SWInterruptHandlerTable+4*4[ecx*4], offset HalpHardwareInterruptLevel
+
+ mov edx, HalpSpecialDismissLevelTable[ecx*4]
+ mov HalpSpecialDismissTable[ecx*4], edx
+
+@@:
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ cli
+ and PCR[PcIDR], eax
+
+;
+; Get the PIC masks for Irql 0
+;
+ mov eax, KiI8259MaskTable[0]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+hes_error:
+if DBG
+ int 3
+endif
+ xor eax, eax ; FALSE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT$01 ENDS
+
+ END
diff --git a/private/ntos/nthals/halx86/i386/ixthunk.c b/private/ntos/nthals/halx86/i386/ixthunk.c
new file mode 100644
index 000000000..d365f1933
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixthunk.c
@@ -0,0 +1,82 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixthunk.c
+
+Abstract:
+
+ This module contains the standard call routines which thunk to
+ fastcall routines.
+
+Author:
+
+ Ken Reneris (kenr) 04-May-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+#ifdef KeRaiseIrql
+#undef KeRaiseIrql
+#endif
+
+VOID
+KeRaiseIrql (
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+{
+ *OldIrql = KfRaiseIrql (NewIrql);
+}
+
+
+#ifdef KeLowerIrql
+#undef KeLowerIrql
+#endif
+
+
+VOID
+KeLowerIrql (
+ IN KIRQL NewIrql
+ )
+{
+ KfLowerIrql (NewIrql);
+}
+
+#ifdef KeAcquireSpinLock
+#undef KeAcquireSpinLock
+#endif
+
+VOID
+KeAcquireSpinLock (
+ IN PKSPIN_LOCK SpinLock,
+ OUT PKIRQL OldIrql
+ )
+{
+ *OldIrql = KfAcquireSpinLock (SpinLock);
+}
+
+
+#ifdef KeReleaseSpinLock
+#undef KeReleaseSpinLock
+#endif
+
+VOID
+KeReleaseSpinLock (
+ IN PKSPIN_LOCK SpinLock,
+ IN KIRQL NewIrql
+ )
+{
+ KfReleaseSpinLock (SpinLock, NewIrql);
+}
diff --git a/private/ntos/nthals/halx86/i386/ixusage.c b/private/ntos/nthals/halx86/i386/ixusage.c
new file mode 100644
index 000000000..e0efb9b20
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixusage.c
@@ -0,0 +1,535 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+extern WCHAR HalpSzSystem[];
+extern WCHAR HalpSzSerialNumber[];
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+VOID
+HalpReportSerialNumber (
+ VOID
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportSerialNumber)
+#endif
+
+
+
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Add system's serial number
+ //
+
+ HalpReportSerialNumber ();
+}
+
+VOID
+HalpReportSerialNumber (
+ VOID
+ )
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ UNICODE_STRING unicodeString;
+ HANDLE hSystem;
+ NTSTATUS status;
+
+ if (!HalpSerialLen) {
+ return ;
+ }
+
+ //
+ // Open HKEY_LOCAL_MACHINE\Hardware\Description\System
+ //
+
+ RtlInitUnicodeString (&unicodeString, HalpSzSystem);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+
+ status = ZwOpenKey (&hSystem, KEY_READ | KEY_WRITE, &objectAttributes);
+ if (NT_SUCCESS(status)) {
+
+ //
+ // Add "Serial Number" as REG_BINARY
+ //
+
+ RtlInitUnicodeString (&unicodeString, HalpSzSerialNumber);
+
+ ZwSetValueKey (
+ hSystem,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ HalpSerialNumber,
+ HalpSerialLen
+ );
+
+ ZwClose (hSystem);
+ }
+}
diff --git a/private/ntos/nthals/halx86/i386/ncrdetct.c b/private/ntos/nthals/halx86/i386/ncrdetct.c
new file mode 100644
index 000000000..2baf83ffa
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ncrdetct.c
@@ -0,0 +1,253 @@
+/*++
+
+Copyright (c) 1992 NCR Corporation
+
+Module Name:
+
+ ncrdetect.c
+
+Abstract:
+
+Authors:
+
+ Richard Barton (o-richb) 24-Jan-1992
+ Brian Weischedel 30-Nov-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#ifndef _NTOS_
+#include "nthal.h"
+#endif
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ );
+
+VOID
+ReadCMOS(
+ IN ULONG StartingOffset,
+ IN ULONG Count,
+ IN PUCHAR ReturnValuePtr);
+
+ULONG NCRPlatform;
+
+#define NCR3450 0x35333433 // Copied here to build standalone
+#define NCR3550 0x30353834
+#define NCR3360 0x33333630
+
+// WPD definitions:
+
+PUCHAR WPDStringID = "NCR Voyager-1";
+PUCHAR WPDPlatformName = "System 3360";
+#define WPDStringIDLength 13
+#define WPDStringIDRangeStart (0xE000 << 4) // physical address
+#define WPDStringIDRangeSize 0x10000 // 1 segment (64k)
+
+// MSBU definitions:
+
+PUCHAR MSBUCopyrightString = "Copyright (C) ???? NCR\0";
+#define MSBUCopyrightStringLen 23
+#define MSBUCopyrightPhysicalPtr ((0xF000 << 4) + (0xE020))
+typedef struct {
+ ULONG ClassFromFirmware;
+ PUCHAR PlatformName;
+} MSBUPlatformMapEntry;
+MSBUPlatformMapEntry MSBUPlatformMap[] = {{NCR3450, "System 3450"},
+ {NCR3550, "System 3550"},
+ {0, 0}};
+
+PUCHAR
+NCRDeterminePlatform(
+ OUT PBOOLEAN IsConfiguredMp
+)
+/*++
+
+Routine Description:
+ Determine on which NCR platform we are running. For now just display
+ a message. Later we may not continue the boot if we're on an
+ unrecognized platform.
+
+Arguments:
+ none.
+
+Return Value:
+ Pointer to character string identifying which NCR platform. NULL means
+ it is unrecognized, and we shouldn't continue.
+
+--*/
+{
+ BOOLEAN Matchfound;
+ MSBUPlatformMapEntry *MSBUPlatformMapPtr;
+ PVOID BIOSPagePtr;
+ PUCHAR StringPtr;
+ PUCHAR CopyrightPtr;
+ PUCHAR SearchPtr;
+ UCHAR CpuFlags;
+
+
+ // first check for a WPD platform by searching the 0xE000 BIOS segment
+ // for a ROM string that identifies this system as a 3360
+
+
+ // get virtual address to the BIOS region (assuming region is both
+ // page aligned and multiple pages in size)
+
+ BIOSPagePtr = HalpMapPhysicalMemory((PVOID) WPDStringIDRangeStart,
+ (WPDStringIDRangeSize >> 12));
+
+ if (BIOSPagePtr != NULL) {
+
+ SearchPtr = BIOSPagePtr; // begin search at start of region
+ Matchfound = FALSE;
+
+ // search until string is found or we are beyond the region
+
+ while (!Matchfound && (SearchPtr <= (PUCHAR)((ULONG)BIOSPagePtr +
+ WPDStringIDRangeSize -
+ WPDStringIDLength))) {
+
+ // see if SearchPtr points to the desired string
+
+ StringPtr = (PUCHAR)((ULONG)SearchPtr++);
+ CopyrightPtr = WPDStringID;
+
+ // continue compare as long as characters compare
+ // and not at end of string
+
+ while ((Matchfound = (*CopyrightPtr++ == *StringPtr++)) &&
+ (CopyrightPtr < WPDStringID + WPDStringIDLength));
+ }
+
+ // see if string was found (i.e., if this is a 3360)
+
+ if (Matchfound) {
+
+ // store system identifier ("3360") for later HAL use
+
+ NCRPlatform = NCR3360;
+
+ // read CPU good flags from CMOS and determine if MP
+
+ ReadCMOS(0x88A, 1, &CpuFlags);
+ // *IsConfiguredMp = (CpuFlags & (CpuFlags-1)) ? TRUE : FALSE;
+
+ // This is an MP hal
+ *IsConfiguredMp = TRUE;
+
+ return(WPDPlatformName);
+ }
+
+ }
+
+
+ // now check for an MSBU platform
+
+
+ /*
+ * Map in the BIOS text so we can look for our copyright string.
+ */
+ BIOSPagePtr = (PVOID)((ULONG)MSBUCopyrightPhysicalPtr &
+ ~(PAGE_SIZE - 1));
+ BIOSPagePtr = HalpMapPhysicalMemory(BIOSPagePtr, 2);
+ if (BIOSPagePtr == NULL)
+ return(NULL);
+
+ StringPtr = (PUCHAR)((ULONG)BIOSPagePtr +
+ ((ULONG)MSBUCopyrightPhysicalPtr & (PAGE_SIZE - 1)))
+ + (MSBUCopyrightStringLen - 1);
+ CopyrightPtr = MSBUCopyrightString + (MSBUCopyrightStringLen - 1);
+ do {
+ Matchfound = ((*CopyrightPtr == '?') ||
+ (*CopyrightPtr == *StringPtr));
+ --CopyrightPtr;
+ --StringPtr;
+ } while (Matchfound && (CopyrightPtr >= MSBUCopyrightString));
+
+ //
+ // /*
+ // * Clear the mapping to BIOS. We mapped in two pages.
+ // */
+ // BIOSPagePtr = MiGetPteAddress(BIOSPagePtr);
+ // *(PULONG)BIOSPagePtr = 0;
+ // *(((PULONG)BIOSPagePtr)+1) = 0;
+ // /*
+ // * Flush the TLB.
+ // */
+ // _asm {
+ // mov eax, cr3
+ // mov cr3, eax
+ // }
+ //
+
+ if (Matchfound) {
+ /*
+ * must be an MSBU machine..determine which.
+ */
+ ReadCMOS(0xB16, 4, (PUCHAR)&NCRPlatform);
+ for (MSBUPlatformMapPtr = MSBUPlatformMap;
+ (MSBUPlatformMapPtr->ClassFromFirmware != 0);
+ ++MSBUPlatformMapPtr) {
+ if (MSBUPlatformMapPtr->ClassFromFirmware ==
+ NCRPlatform) {
+
+ *IsConfiguredMp = TRUE;
+ return(MSBUPlatformMapPtr->PlatformName);
+ }
+ }
+
+ /*
+ * prerelease version of firmware had this machine class
+ * at the wrong offset into CMOS. until all those versions
+ * of firmware are extinguished from the face of the earth
+ * we should recognize them with this:
+ */
+ ReadCMOS(0xAB3, 4, (PUCHAR)&NCRPlatform);
+ for (MSBUPlatformMapPtr = MSBUPlatformMap;
+ (MSBUPlatformMapPtr->ClassFromFirmware != 0);
+ ++MSBUPlatformMapPtr) {
+ if (MSBUPlatformMapPtr->ClassFromFirmware ==
+ NCRPlatform) {
+ *IsConfiguredMp = TRUE;
+ return(MSBUPlatformMapPtr->PlatformName);
+ }
+ }
+ }
+
+ return(NULL);
+}
+
+
+#ifndef SETUP // if built with Hal, must provide ReadCMOS routine
+
+ULONG
+HalpGetCmosData (
+ IN ULONG SourceLocation,
+ IN ULONG SourceAddress,
+ IN PUCHAR Buffer,
+ IN ULONG Length);
+
+VOID
+ReadCMOS(
+ IN ULONG StartingOffset,
+ IN ULONG Count,
+ IN PUCHAR ReturnValuePtr
+)
+/*++
+
+Routine Description:
+ This routine simply converts a ReadCMOS call (a routine in setup) to
+ the corresponding routine provided in the Hal (HalpGetCmosData).
+
+--*/
+{
+ HalpGetCmosData(1, StartingOffset, ReturnValuePtr, Count);
+}
+#endif
diff --git a/private/ntos/nthals/halx86/i386/pcip.h b/private/ntos/nthals/halx86/i386/pcip.h
new file mode 100644
index 000000000..c5f09f2e5
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/pcip.h
@@ -0,0 +1,186 @@
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halx86/i386/xxbiosa.asm b/private/ntos/nthals/halx86/i386/xxbiosa.asm
new file mode 100644
index 000000000..e3d5493b6
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxbiosa.asm
@@ -0,0 +1,712 @@
+;++
+;
+; Copyright (c) 1991 Microsoft Corporation
+;
+; Module Name:
+;
+; xxbiosa.asm
+;
+; Abstract:
+;
+; This implements the necessary code to put the processor into
+; V86 mode, make a BIOS call, and return safely to protected mode.
+;
+; Author:
+;
+; John Vert (jvert) 29-Oct-1991
+;
+; Environment:
+;
+; Kernel mode
+;
+; Notes:
+;
+; This module is intended for use in panic situations, such as a bugcheck.
+; As a result, we cannot rely on the integrity of the system so we must
+; handle everything ourselves. Notably, we must map our own memory by
+; adding our own page tables and PTEs.
+;
+; We also cannot call KeBugCheck when we notice something has gone wrong.
+;
+; Revision History:
+;
+;--
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\kimacro.inc
+ .list
+
+ extrn _DbgPrint:proc
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+
+ public _HalpRealModeStart
+ public _HalpRealModeEnd
+;
+; 32-bit override
+;
+OVERRIDE equ 66h
+
+;
+; Reginfo structure
+;
+
+RegInfo struc
+RiSegSs dd 0
+RiEsp dd 0
+RiEFlags dd 0
+RiSegCs dd 0
+RiEip dd 0
+RiTrapFrame dd 0
+RiCsLimit dd 0
+RiCsBase dd 0
+RiCsFlags dd 0
+RiSsLimit dd 0
+RiSsBase dd 0
+RiSsFlags dd 0
+RiPrefixFlags dd 0
+RegInfo ends
+REGINFOSIZE EQU 52
+
+INT_NN_OPCODE EQU 0CDH
+
+ page ,132
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;
+; In order to return to the calling function after we've trapped out of
+; V86 mode, we save our ESP value here.
+;
+HalpSavedEsp dd 0
+
+_DATA ENDS
+
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+if DBG
+ page ,132
+ subttl "Processing Exception occurred in ABIOS code"
+;++
+; VOID
+; KiAbiosException (
+; VOID
+; )
+;
+; Routine Description:
+;
+; This routine is called after an exception being detected
+; in ABIOS ROM code. The system will switch 16 stack to 32 bit
+; stack and bugcheck.
+;
+; N.B. In fact this routine is simply used to resolve a reference
+; to KiAbiosException routine in the Kimacro.inc ENTER_TRAP
+; macro.
+;
+;
+; Arguments:
+;
+; None.
+;
+; Return value:
+;
+; system stopped.
+;
+;--
+ public _KiAbiosException
+_KiAbiosException proc
+_Ki16BitStackException:
+ ret
+
+_KiAbiosException endp
+
+endif
+
+
+;++
+; ULONG
+; HalpBorrowTss (
+; VOID
+; )
+;
+; Routine Description:
+;
+; This routine checks if the current TSS has IO MAP space.
+; if yes, it simply returns. Otherwise, it switches to use
+; the regular TSS.
+;
+; Arguments:
+;
+; None.
+;
+; Return value:
+;
+; Return original TSS selector if the regular Tss is borrowed by us.
+;
+;--
+cPublicProc _HalpBorrowTss, 0
+cPublicFpo 0, 0
+
+ xor eax, eax
+ str ax
+ mov edx, PCR[PcGdt]
+ add edx, eax ; (edx)->Gdt Entry of current
+ ; TSS
+ xor ecx, ecx
+ mov cl, [edx].KgdtLimitHi
+ shl ecx, 16
+ mov cx, [edx].KgdtLimitLow ; (ecx) = TSS limit
+ cmp ecx, 2000H ; Is Io map space available?
+ ja short Hbt99 ; if a, yes, return
+
+ sub edx, eax ; (edx)->GDT table
+ mov ch, [edx+KGDT_TSS+KgdtBaseHi]
+ mov cl, [edx+KGDT_TSS+KgdtBaseMid]
+ shl ecx, 16
+ mov cx, [edx+KGDT_TSS+KgdtBaseLow]
+ mov PCR[PcTss], ecx
+ mov ecx, KGDT_TSS ; switch to use regular TSS
+ mov byte ptr [edx+KGDT_TSS+5], 089h ; 32bit, dpl=0, present, TSS32,
+ ; not busy.
+ ltr cx
+ stdRET _HalpBorrowTss ; (eax) = Original TSS sel
+
+Hbt99:
+ xor eax, eax ; No TSS swapped
+ stdRET _HalpBorrowTss
+
+stdENDP _HalpBorrowTss
+
+
+;++
+; VOID
+; HalpReturnTss (
+; ULONG TssSelector
+; )
+;
+; Routine Description:
+;
+; This routine switches the current TSS from regular TSS back to
+; the panic TSS (NMI TSS or Double fault TSS).
+;
+; Arguments:
+;
+; TssSelector - the TSS selector to return to.
+;
+; Return value:
+;
+; None.
+;
+;--
+cPublicProc _HalpReturnTss, 1
+cPublicFpo 1, 0
+
+ mov edx, PCR[PcGdt] ; (edx)-> Gdt table
+ mov eax, [esp + 4]
+ and eax, 0FFFFh ; (eax)= New TSS sel
+ add edx, eax ; (edx)->Gdt Entry of new TSS
+
+ mov ch, [edx+KgdtBaseHi]
+ mov cl, [edx+KgdtBaseMid]
+ shl ecx, 16
+ mov cx, [edx+KgdtBaseLow]
+ mov PCR[PcTss], ecx
+ mov byte ptr [edx+5], 089h ; 32bit, dpl=0, present, TSS32,
+ ltr ax
+ stdRET _HalpReturnTss ; return and clear stack
+
+stdENDP _HalpReturnTss
+
+;++
+;
+; VOID
+; HalpBiosCall
+; VOID
+; )
+;
+; Routine Description:
+;
+; This routine completes the transition to real mode, calls BIOS, and
+; returns to protected mode.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+;;ALIGN 4096
+cPublicProc _HalpBiosCall ,0
+
+ push ebp
+ mov ebp, esp
+ pushfd
+ push edi
+ push esi
+ push ebx
+ push ds
+ push es
+ push fs
+ push gs
+ push offset FLAT:HbcProtMode ; address where we will start
+ ; protected mode again once
+ ; V86 has completed.
+ mov HalpSavedEsp, esp
+
+ mov eax, cr0 ; make sure alignment
+ and eax, not CR0_AM ; checks are disabled
+ mov cr0, eax
+
+;
+; Create space for the V86 trap frame and update the ESP0 value in the TSS
+; to use this space. We will set this up just below our current stack pointer.
+; The stuff we push on the stack after we set ESP0 is irrelevant once we
+; make it to V86 mode, so it's ok to blast it.
+;
+ mov esi, fs:PcTss ; (esi) -> TSS
+ mov eax, esp
+ sub eax, NPX_FRAME_LENGTH ; skip FP save area
+ mov [esi]+TssEsp0, eax
+
+ push dword ptr 0h ; V86 GS
+ push dword ptr 0h ; V86 FS
+ push dword ptr 0h ; V86 DS
+ push dword ptr 0h ; V86 ES
+ push dword ptr 2000h ; V86 SS
+
+;
+; We calculate the V86 sp by adding the difference between the linear address
+; of the V86 ip (HbcReal) and the linear address of the V86 sp (HbcV86Stack)
+; to the offset of the V86 ip (HbcReal & 0xfff).
+;
+
+ mov eax, offset FLAT:HbcV86Stack-4
+ sub eax, offset FLAT:HbcReal
+ mov edx, offset HbcReal
+ and edx, 0fffh
+ add eax, edx
+ push eax ; V86 esp
+
+ pushfd
+ or dword ptr [esp], EFLAGS_V86_MASK; V86 eflags
+ or [esp], 03000h ; Give IOPL3
+ push dword ptr 2000h ; V86 CS
+ mov eax, offset HbcReal
+ and eax, 0fffh
+
+ push edx ; V86-mode EIP is offset
+ ; into CS.
+ iretd
+
+_HalpRealModeStart label byte
+
+HbcReal:
+ db OVERRIDE ; make mov 32-bits
+ mov eax, 03h ; 80x25 mode, 16 colors
+ int 10h
+
+ db OVERRIDE ; make mov 32-bits
+ mov eax, 1112h ; use 8x8 font (causes 50 line mode)
+ db OVERRIDE
+ mov ebx, 0
+ int 10h
+
+ db 0c4h, 0c4h ; BOP to indicate V86 mode is done.
+
+;
+; V86-mode stack
+;
+align 4
+ db 2048 dup(0)
+HbcV86Stack:
+
+_HalpRealModeEnd label byte
+
+HbcProtMode:
+;
+; We are back from V86 mode, so restore everything we saved and we are done.
+;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop ebx
+ pop esi
+ pop edi
+ popfd
+ pop ebp
+ stdRET _HalpBiosCall
+
+ public _HalpBiosCallEnd
+_HalpBiosCallEnd label byte
+
+
+
+_HalpBiosCall endp
+
+
+ subttl "HAL General Protection Fault"
+;++
+;
+; Routine Description:
+;
+; Handle General protection fault.
+;
+; This fault handler is used by the HAL for V86 mode faults only.
+; It should NEVER be used except when running in V86 mode. The HAL
+; replaces the general-purpose KiTrap0D handler entry in the IDT with
+; this routine. This allows us to emulate V86-mode instructions which
+; cause a fault. After we return from V86 mode, we can restore the
+; KiTrap0D handler in the IDT.
+;
+; Arguments:
+;
+; At entry, the saved CS:EIP point to the faulting instruction
+; Error code (whose value depends on detected condition) is provided.
+;
+; Return value:
+;
+; None
+;
+;--
+ ASSUME DS:FLAT, SS:NOTHING, ES:FLAT
+
+ ENTER_DR_ASSIST Htd_a, Htd_t, NoAbiosAssist
+cPublicProc _HalpTrap0D ,0
+
+ ENTER_TRAP Htd_a, Htd_t
+
+;
+; Did the trap occur in V86 mode? If not, something is completely screwed.
+;
+ test dword ptr [ebp]+TsEFlags,00020000H
+ jnz Ht0d10
+
+;
+; The trap was not from V86 mode, so something is very wrong. We cannot
+; BugCheck, since we are probably already in a BugCheck. So just stop.
+;
+
+if DBG
+_DATA segment
+MsgBadHalTrap db 'HAL: Trap0D while not in V86 mode',0ah,0dh,0
+_DATA ends
+
+ push offset FLAT:MsgBadHalTrap
+ call _DbgPrint
+ add esp,4
+ stdCall _DbgBreakPoint
+endif
+;
+; We can't bugcheck, so just commit suicide. Maybe we should reboot?
+;
+ jmp $
+
+Ht0d10:
+ stdCall HalpDispatchV86Opcode
+ SPURIOUS_INTERRUPT_EXIT
+stdENDP _HalpTrap0d
+
+ subttl "HAL Invalid Opcode Fault"
+;++
+;
+; Routine Description:
+;
+; Handle invalid opcode fault
+;
+; This fault handler is used by the HAL to indicate when V86 mode
+; execution is finished. The V86 code attempts to execute an invalid
+; instruction (BOP) when it is done, and that brings us here.
+; This routine just removes the trap frame from the stack and does
+; a RET. Note that this assumes that ESP0 in the TSS has been set
+; up to point to the top of the stack that we want to be running on
+; when the V86 call has completed.
+;
+; This should NEVER be used except when running in V86 mode. The HAL
+; replaces the general-purpose KiTrap06 handler entry in the IDT with
+; this routine. It also sets up ESP0 in the TSS appropriately. After
+; the V86 call has completed, it restores these to their previous values.
+;
+; Arguments:
+;
+; At entry, the saved CS:EIP point to the faulting instruction
+; Error code (whose value depends on detected condition) is provided.
+;
+; Return value:
+;
+; None
+;
+;--
+ ASSUME DS:FLAT, SS:NOTHING, ES:FLAT
+
+cPublicProc _HalpTrap06 ,0
+ mov eax,KGDT_R3_DATA OR RPL_MASK
+ mov ds,ax
+ mov es,ax
+ mov esp, HalpSavedEsp
+ ret
+
+stdENDP _HalpTrap06
+
+ subttl "Instruction Emulation Dispatcher"
+;++
+;
+; Routine Description:
+;
+; This routine dispatches to the opcode specific emulation routine,
+; based on the first byte of the opcode. Two byte opcodes, and prefixes
+; result in another level of dispatching, from the handling routine.
+;
+; This code blatantly stolen from ke\i386\instemul.asm
+;
+; Arguments:
+;
+; ebp = pointer to trap frame
+;
+; Returns:
+;
+; Nothing
+;
+
+cPublicProc HalpDispatchV86Opcode ,0
+
+RI equ [ebp - REGINFOSIZE]
+ push ebp
+ mov ebp,esp
+ sub esp,REGINFOSIZE
+ push esi
+ push edi
+
+ ; Initialize RegInfo
+
+ mov esi,[ebp]
+ mov RI.RiTrapFrame,esi
+ movzx eax,word ptr [esi].TsHardwareSegSs
+ mov RI.RiSegSs,eax
+ mov eax,[esi].TsHardwareEsp
+ mov RI.RiEsp,eax
+ mov eax,[esi].TsEFlags
+ mov RI.RiEFlags,eax
+ movzx eax,word ptr [esi].TsSegCs
+ mov RI.RiSegCs,eax
+ mov eax,[esi].TsEip
+ mov RI.RiEip,eax
+
+ xor eax,eax
+ mov RI.RiPrefixFlags,eax
+ lea esi,RI
+
+;
+; Convert CS to a linear address
+;
+
+ mov eax,[esi].RiSegCs
+ shl eax,4
+ mov [esi].RiCsBase,eax
+ mov [esi].RiCsLimit,0FFFFh
+ mov [esi].RiCsFlags,0
+
+ mov edi,RI.RiEip
+ cmp edi,RI.RiCsLimit
+ ja doerr
+
+ add edi,RI.RiCsBase
+ mov dl, [edi] ; get faulting opcode
+ cmp dl, INT_NN_OPCODE
+ je short @f
+
+ stdCall HalpOpcodeInvalid
+ jmp short doerr
+
+@@:
+ stdCall HalpOpcodeINTnn
+ test eax,0FFFFh
+ jz do20
+
+ mov edi,RI.RiTrapFrame
+ mov eax,RI.RiEip ; advance eip
+ mov [edi].TsEip,eax
+ mov eax,1
+do20: pop edi
+ pop esi
+ mov esp,ebp
+ pop ebp
+ ret
+
+doerr: xor eax,eax
+ jmp do20
+stdENDP HalpDispatchV86Opcode
+
+ page ,132
+ subttl "Invalid Opcode Handler"
+;++
+;
+; Routine Description:
+;
+; This routine handles invalid opcodes. It prints the invalid
+; opcode message, and breaks into the kernel debugger.
+;
+; Arguments:
+;
+; esi = address of reg info
+; edx = opcode
+;
+; Returns:
+;
+; nothing
+;
+
+cPublicProc HalpOpcodeInvalid ,0
+
+_DATA segment
+HalpMsgInvalidOpcode db 'HAL: An invalid V86 opcode was encountered at '
+ db 'address %x:%x',0ah, 0dh, 0
+_DATA ends
+
+ push [esi].RiEip
+ push [esi].RiSegCs
+ push offset FLAT:HalpMsgInvalidOpcode
+ call _DbgPrint ; display invalid opcode message
+ add esp,12
+ int 3
+ xor eax,eax
+ stdRET HalpOpcodeInvalid
+
+stdENDP HalpOpcodeInvalid
+
+ subttl "INTnn Opcode Handler"
+;++
+;
+; Routine Description:
+;
+; This routine emulates an INTnn opcode. It retrieves the handler
+; from the IVT, pushes the current cs:ip and flags on the stack,
+; and dispatches to the handler.
+;
+; Arguments:
+;
+; esi = address of reg info
+; edx = opcode
+;
+; Returns:
+;
+; Current CS:IP on user stack
+; RiCs:RiEip -> handler from IVT
+;
+
+cPublicProc HalpOpcodeINTnn ,0
+
+ push ebp
+ push edi
+ push ebx
+
+;
+; Convert SS to linear address
+;
+ mov eax,[esi].RiSegSs
+ shl eax,4
+ mov [esi].RiSsBase,eax
+ mov [esi].RiSsLimit,0FFFFh
+ mov [esi].RiSsFlags,0
+
+ inc [esi].RiEip ; point to int #
+ mov edi,[esi].RiEip
+ cmp edi,[esi].RiCsLimit
+ ja oinerr
+
+ add edi,[esi].RiCsBase
+ movzx ecx,byte ptr [edi] ; get int #
+ inc [esi].RiEip ; inc past end of instruction
+ stdCall HalpPushInt
+ test eax,0FFFFh
+ jz oin20 ; error!
+;
+; BugBug Some sort of check for BOP should go here, or in push int.
+;
+
+ mov ebp,[esi].RiTrapFrame
+ mov eax,[esi].RiSegSs
+ mov [ebp].TsHardwareSegSs,eax
+ mov eax,[esi].RiEsp
+ mov [ebp].TsHardwareEsp,eax
+ mov eax,[esi].RiSegCs
+ mov [ebp].TsSegCs,eax
+ mov eax,[esi].RiEFlags
+ mov [ebp].TsEFlags,eax
+ mov eax,1
+oin20: pop ebx
+ pop edi
+ pop ebp
+ stdRET HalpOpcodeINTnn
+
+oinerr: xor eax,eax
+ jmp oin20
+
+stdENDP HalpOpcodeINTnn
+
+ page ,132
+ subttl "Push Interrupt frame on user stack"
+;++
+;
+; Routine Description:
+;
+; This routine pushes an interrupt frame on the user stack
+;
+; Arguments:
+;
+; ecx = interrupt #
+; esi = address of reg info
+; Returns:
+;
+; interrupt frame pushed on stack
+; reg info updated
+;bugbug does this routine trash BX??
+;
+cPublicProc HalpPushInt ,0
+ push ebx
+
+ mov edx,[esi].RiEsp
+ mov ebx,[esi].RiSsBase
+ and edx,0FFFFh ; only use a 16 bit sp
+ sub dx,2
+ mov ax,word ptr [esi].RiEFlags
+ mov [ebx+edx],ax ; push flags
+ sub dx,2
+ mov ax,word ptr [esi].RiSegCs
+ mov [ebx+edx],ax ; push cs
+ sub dx,2
+ mov ax,word ptr [esi].RiEip
+ mov [ebx+edx],ax ; push ip
+ mov eax,[ecx*4] ; get new cs:ip value
+ push eax
+ movzx eax,ax
+ mov [esi].RiEip,eax
+ pop eax
+ shr eax,16
+ mov [esi].RiSegCs,eax
+ mov word ptr [esi].RiEsp,dx
+
+;
+; Convert CS to a linear address
+;
+
+ mov eax,[esi].RiSegCs
+ shl eax,4
+ mov [esi].RiCsBase,eax
+ mov [esi].RiCsLimit,0FFFFh
+ mov [esi].RiCsFlags,0
+
+ mov eax,1 ; success
+pi80: pop ebx
+ stdRET HalpPushInt
+stdENDP HalpPushInt
+
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/halx86/i386/xxbiosc.c b/private/ntos/nthals/halx86/i386/xxbiosc.c
new file mode 100644
index 000000000..6b5f1cc69
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxbiosc.c
@@ -0,0 +1,299 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxbiosc.c
+
+Abstract:
+
+ This module implements the protect-mode routines necessary to make the
+ transition to real mode and return to protected mode.
+
+Author:
+
+ John Vert (jvert) 29-Oct-1991
+
+
+Environment:
+
+ Kernel mode only.
+ Probably a panic-stop, so we cannot use any system services.
+
+Revision History:
+
+--*/
+#include "halp.h"
+
+//
+// Function definitions
+//
+
+
+ULONG
+HalpBorrowTss(
+ VOID
+ );
+
+VOID
+HalpReturnTss(
+ ULONG TssSelector
+ );
+
+VOID
+HalpBiosCall(
+ VOID
+ );
+
+
+VOID
+HalpTrap06(
+ VOID
+ );
+
+
+VOID
+HalpTrap0D(
+ VOID
+ );
+
+VOID
+HalpBiosDisplayReset(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Calls BIOS by putting the machine into V86 mode. This involves setting up
+ a physical==virtual identity mapping for the first 1Mb of memory, setting
+ up V86-specific trap handlers, and granting I/O privilege to the V86
+ process by editing the IOPM bitmap in the TSS.
+
+Environment:
+
+ Interrupts disabled.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HARDWARE_PTE OldPageTable;
+ USHORT OldIoMapBase;
+ ULONG OldEsp0;
+ PHARDWARE_PTE Pte;
+ PHARDWARE_PTE V86CodePte;
+ ULONG cnt;
+ ULONG OldTrap0DHandler;
+ ULONG OldTrap06Handler;
+ PUCHAR IoMap;
+ ULONG Virtual;
+// KIRQL OldIrql;
+ ULONG OriginalTssSelector;
+ extern PVOID HalpRealModeStart;
+ extern PVOID HalpRealModeEnd;
+PHARDWARE_PTE PointerPde;
+ULONG PageFrame;
+ULONG PageFrameEnd;
+
+ //
+ // Interrupts are off, but V86 mode might turn them back on again.
+ //
+ HalpDisableAllInterrupts ();
+
+ //
+ // We need to set up an identity mapping in the first page table. First,
+ // we save away the old page table.
+ //
+ OldPageTable = *MiGetPdeAddress(0);
+
+ //
+ // Now we put the HAL page table into the first slot of the page
+ // directory. Note that this page table is now the first and last
+ // entries in the page directory.
+ //
+ Pte = MiGetPdeAddress(0);
+ Pte->PageFrameNumber = MiGetPdeAddress(0xffc00000)->PageFrameNumber;
+ Pte->Valid = 1;
+ Pte->Write = 1;
+ Pte->Owner = 1; // User-accessible
+
+ //
+ // Flush TLB
+ //
+
+ HalpFlushTLB();
+
+ //
+ // Map the first 1Mb of virtual memory to the first 1Mb of physical
+ // memory
+ //
+ for (Virtual=0; Virtual < 0x100000; Virtual += PAGE_SIZE) {
+ Pte = MiGetPteAddress(Virtual);
+ Pte->PageFrameNumber = ((ULONG)Virtual >> PAGE_SHIFT);
+ Pte->Valid = 1;
+ Pte->Write = 1;
+ Pte->Owner = 1; // User-accessible
+ }
+
+ //
+ // Map our code into the virtual machine
+ //
+
+ Pte = MiGetPteAddress(0x20000);
+ PointerPde = MiGetPdeAddress(&HalpRealModeStart);
+
+ if ( PointerPde->LargePage ) {
+ //
+ // Map real mode PTEs into virtual mapping. The source PDE is
+ // from the indenity large pte map, so map the virtual machine PTEs
+ // based on the base of the large PDE frame.
+ //
+
+ PageFrame = ((ULONG)(&HalpRealModeStart) >> 12) & 0x3FF;
+ PageFrameEnd = ((ULONG)(&HalpRealModeEnd) >> 12) & 0x3FF;
+ do {
+
+ Pte->PageFrameNumber = PointerPde->PageFrameNumber + PageFrame;
+
+ ++Pte;
+ ++PageFrame;
+
+ } while (PageFrame <= PageFrameEnd);
+
+ } else {
+
+ //
+ // Map real mode PTEs into virtual machine PTEs, by copying the
+ // page frames from the source to the virtual machine PTEs.
+ //
+
+ V86CodePte = MiGetPteAddress(&HalpRealModeStart);
+ do {
+ Pte->PageFrameNumber = V86CodePte->PageFrameNumber;
+
+ ++Pte;
+ ++V86CodePte;
+
+ } while ( V86CodePte <= MiGetPteAddress(&HalpRealModeEnd) );
+
+ }
+ //
+ // Flush TLB
+ //
+
+ HalpFlushTLB();
+
+ //
+ // We need to replace the current TRAP D handler with our own, so
+ // we can do instruction emulation for V86 mode
+ //
+
+ OldTrap0DHandler = KiReturnHandlerAddressFromIDT(0xd);
+ KiSetHandlerAddressToIDT(0xd, HalpTrap0D);
+
+ OldTrap06Handler = KiReturnHandlerAddressFromIDT(6);
+ KiSetHandlerAddressToIDT(6, HalpTrap06);
+
+ //
+ // Make sure current TSS has IoMap space available. If no, borrow
+ // Normal TSS.
+ //
+
+ OriginalTssSelector = HalpBorrowTss();
+
+ //
+ // Overwrite the first access map with zeroes, so the V86 code can
+ // party on all the registers.
+ //
+ IoMap = (PUCHAR)&(KeGetPcr()->TSS->IoMaps[0]);
+
+ for (cnt=0; cnt<IOPM_SIZE; cnt++) {
+ IoMap[cnt] = 0;
+ }
+ for (cnt=IOPM_SIZE; cnt<PIOPM_SIZE; cnt++) {
+ IoMap[cnt] = 0xff;
+ }
+ OldIoMapBase = KeGetPcr()->TSS->IoMapBase;
+
+ KeGetPcr()->TSS->IoMapBase = KiComputeIopmOffset(1);
+
+ //
+ // Save the current ESP0, as HalpBiosCall() trashes it.
+ //
+ OldEsp0 = KeGetPcr()->TSS->Esp0;
+
+ //
+ // Call the V86-mode code
+ //
+ HalpBiosCall();
+
+ //
+ // Restore the TRAP handlers
+ //
+
+ KiSetHandlerAddressToIDT(0xd, OldTrap0DHandler);
+ KiSetHandlerAddressToIDT(6, OldTrap06Handler);
+
+ //
+ // Restore Esp0 value
+ //
+ KeGetPcr()->TSS->Esp0 = OldEsp0;
+
+ KeGetPcr()->TSS->IoMapBase = OldIoMapBase;
+
+ //
+ // Return borrowed TSS if any.
+ //
+
+ if (OriginalTssSelector != 0) {
+ HalpReturnTss(OriginalTssSelector);
+ }
+
+ //
+ // Unmap the first 1Mb of virtual memory
+ //
+ for (Virtual = 0; Virtual < 0x100000; Virtual += PAGE_SIZE) {
+ Pte = MiGetPteAddress(Virtual);
+ Pte->PageFrameNumber = 0;
+ Pte->Valid = 0;
+ Pte->Write = 0;
+ }
+
+ //
+ // Restore the original page table that we replaced.
+ //
+ *MiGetPdeAddress(0) = OldPageTable;
+
+ //
+ // Flush TLB
+ //
+
+ HalpFlushTLB();
+
+ //
+ // This function is only used during a system crash. We don't re-
+ // enable interrupts.
+ //
+ // KeLowerIrql(OldIrql);
+}
+
+HAL_DISPLAY_BIOS_INFORMATION
+HalpGetDisplayBiosInformation (
+ VOID
+ )
+{
+ // this hal uses native int-10
+
+ return HalDisplayInt10Bios;
+}
+
diff --git a/private/ntos/nthals/halx86/i386/xxdisp.c b/private/ntos/nthals/halx86/i386/xxdisp.c
new file mode 100644
index 000000000..5806751fc
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxdisp.c
@@ -0,0 +1,476 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a x86 system.
+
+Author:
+
+ David N. Cutler (davec) 27-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Private function prototypes
+//
+VOID
+HalpClearDisplay(
+ VOID
+ );
+
+VOID
+HalpNextLine(
+ VOID
+ );
+
+VOID
+HalpScrollDisplay(
+ VOID
+ );
+
+VOID
+HalpPutCharacter(
+ IN UCHAR Character
+ );
+
+#define REVERSE_ATTRIBUTE 0x17
+#define ROWS 50
+#define COLS 80
+
+ULONG HalpCursorX=0;
+ULONG HalpCursorY=0;
+
+KSPIN_LOCK HalpDisplayLock;
+
+
+PUSHORT VideoBuffer;
+
+//
+// If someone calls HalDisplayString before HalInitSystem, we need to be
+// able to put something up on screen anyway.
+//
+BOOLEAN HalpDisplayInitialized=FALSE;
+
+//
+// This is how we tell if GDI has taken over the display. If so, we are
+// in graphics mode and we need to reset the display to text mode before
+// displaying anything. (Panic stop)
+//
+BOOLEAN HalpOwnsDisplay=TRUE;
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+BOOLEAN HalpDoingCrashDump = FALSE;
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpResetDisplayParameters=ResetDisplayParameters;
+ HalpOwnsDisplay=FALSE;
+ return;
+}
+
+VOID
+HalpVideoReboot()
+{
+ if (HalpResetDisplayParameters && !HalpOwnsDisplay) {
+ //
+ // Video work-around. The video driver has a reset function,
+ // call it before resetting the system in case the bios doesn't
+ // know how to reset the displays video mode.
+ //
+
+ if (HalpResetDisplayParameters(COLS, ROWS)) {
+ // display was reset, make sure it's blank
+ HalpClearDisplay();
+ }
+ }
+}
+
+
+
+VOID
+HalpInitializeDisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Initializes the VGA display. This uses HalpMapPhysicalMemory to map
+ the video buffer at 0xb8000 - 0xba000 into high virtual memory.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (HalpDisplayInitialized == FALSE) {
+
+ HalpDisplayInitialized = TRUE;
+
+ KeInitializeSpinLock(&HalpDisplayLock);
+
+ //
+ // If somebody called HalDisplayString before Phase 0 initialization,
+ // the video buffer has already been mapped and cleared, and a
+ // message has already been displayed. So we don't want to clear
+ // the screen again, or map the screen again.
+ //
+
+ //
+ // Map two pages of memory starting at physical address 0xb8000.
+ //
+
+ VideoBuffer = (PUSHORT)HalpMapPhysicalMemory((PVOID)0xb8000,2);
+
+ HalpClearDisplay();
+ }
+}
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (!HalpDisplayInitialized && HalpOwnsDisplay) {
+
+ //
+ // If somebody has called HalDisplayString before Phase 0
+ // initialization, we need to make sure we get our message out
+ // anyway. So we initialize the display before HalInitSystem does.
+ // HalpInitializeDisplay is smart enough to only map the video
+ // buffer and clear the screen the first time it is called.
+ //
+
+ HalpInitializeDisplay();
+ }
+
+ //
+ // Synchronize access to the display so that MP systems won't
+ // get garbage output due to simultaneous calls. It also prevents
+ // two processors from attempting to call BIOS and reset the display
+ // simultaneously.
+ //
+
+ KiAcquireSpinLock(&HalpDisplayLock);
+
+ if (HalpOwnsDisplay == FALSE) {
+
+ //
+ // The display has been put in graphics mode, and we need to
+ // reset it to text mode before we can display any text on it.
+ //
+
+ if (HalpResetDisplayParameters) {
+ HalpOwnsDisplay = HalpResetDisplayParameters(COLS, ROWS);
+ }
+
+ if (HalpOwnsDisplay == FALSE) {
+ HalpBiosDisplayReset();
+ }
+
+ HalpOwnsDisplay = TRUE;
+ HalpDoingCrashDump = TRUE;
+ HalpClearDisplay();
+ }
+
+ while (*String) {
+
+ switch (*String) {
+ case '\n':
+ HalpNextLine();
+ break;
+ case '\r':
+ HalpCursorX = 0;
+ break;
+ default:
+ HalpPutCharacter(*String);
+ if (++HalpCursorX == COLS) {
+ HalpNextLine();
+ }
+ }
+ ++String;
+ }
+
+ KiReleaseSpinLock(&HalpDisplayLock);
+ return;
+}
+
+VOID
+HalpDisplayDebugStatus (
+ PUCHAR str,
+ ULONG len
+ )
+{
+ PUSHORT p;
+
+ if (!HalpDisplayInitialized || !HalpOwnsDisplay) {
+ return;
+ }
+
+ for (p = &VideoBuffer [COLS - len]; len; str++, p++, len--) {
+ *p = (USHORT)((REVERSE_ATTRIBUTE << 8) | *str);
+ }
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ *WidthInCharacters = COLS;
+ *HeightInLines = ROWS;
+ *CursorColumn = HalpCursorX;
+ *CursorRow = HalpCursorX;
+
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpCursorX = CursorColumn >= COLS ? COLS-1 : CursorColumn;
+ HalpCursorY = CursorRow >= ROWS ? ROWS-1 : CursorRow;
+}
+
+VOID
+HalpNextLine(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Moves the cursor to the start of the next line, scrolling if necessary.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpCursorY==ROWS-1) {
+ HalpScrollDisplay();
+ } else {
+ ++HalpCursorY;
+ }
+ HalpCursorX = 0;
+}
+
+VOID
+HalpScrollDisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Scrolls the text on the display up one line.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUSHORT NewStart;
+ ULONG i;
+
+
+ NewStart = VideoBuffer+COLS;
+ RtlMoveMemory(VideoBuffer, NewStart, (ROWS-1)*COLS*sizeof(USHORT));
+
+ for (i=(ROWS-1)*COLS; i<ROWS*COLS; i++) {
+ VideoBuffer[i] = (REVERSE_ATTRIBUTE << 8) | ' ';
+ }
+}
+
+VOID
+HalpPutCharacter(
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ Places a character on the console screen. It uses the variables
+ HalpCursorX and HalpCursorY to determine the character's location.
+
+Arguments:
+
+ Character - Supplies the character to be displayed
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ VideoBuffer[HalpCursorY*COLS + HalpCursorX] =
+ (USHORT)((REVERSE_ATTRIBUTE << 8) | Character);
+}
+
+VOID
+HalpClearDisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Clears the video display and sets the current cursor position to the
+ upper left-hand corner.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT Attribute;
+ ULONG i;
+
+ Attribute = (REVERSE_ATTRIBUTE << 8) | ' ';
+ for (i=0; i < ROWS*COLS; i++) {
+ VideoBuffer[i] = Attribute;
+ }
+ HalpCursorX=0;
+ HalpCursorY=0;
+
+}
diff --git a/private/ntos/nthals/halx86/i386/xxflshbf.c b/private/ntos/nthals/halx86/i386/xxflshbf.c
new file mode 100644
index 000000000..18a5ff5b4
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxflshbf.c
@@ -0,0 +1,52 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ xxflshbf.c
+
+Abstract:
+
+ This module implements i386 machine dependent kernel functions to flush
+ write buffers.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1990
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+
+VOID
+KeFlushWriteBuffer (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the write buffer on the current processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halx86/i386/xxhal.c b/private/ntos/nthals/halx86/i386/xxhal.c
new file mode 100644
index 000000000..ab8595e5d
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxhal.c
@@ -0,0 +1,462 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxhal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+ULONG HalpBusType;
+
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern UCHAR HalpSzPciLock[];
+extern UCHAR HalpSzBreak[];
+extern BOOLEAN HalpPciLockSettings;
+extern UCHAR HalpGenuineIntel[];
+
+VOID
+HalpGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+ULONG
+HalpGetFeatureBits (
+ VOID
+ );
+
+#ifndef NT_UP
+ULONG
+HalpInitMP(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+#endif
+
+
+extern KSPIN_LOCK Halp8254Lock;
+KSPIN_LOCK HalpSystemHardwareLock;
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetParameters)
+#pragma alloc_text(INIT,HalInitSystem)
+#pragma alloc_text(INIT,HalpGetFeatureBits)
+#endif
+
+
+VOID
+HalpGetParameters (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This gets any parameters from the boot.ini invocation line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PCHAR Options;
+
+ if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
+ Options = LoaderBlock->LoadOptions;
+
+ //
+ // Check if PCI settings are locked down
+ //
+
+ if (strstr(Options, HalpSzPciLock)) {
+ HalpPciLockSettings = TRUE;
+ }
+
+ //
+ // Has the user asked for an initial BreakPoint?
+ //
+
+ if (strstr(Options, HalpSzBreak)) {
+ DbgBreakPoint();
+ }
+ }
+
+ return;
+}
+
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ x86 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ KIRQL CurrentIrql;
+ PKPRCB pPRCB;
+
+ pPRCB = KeGetCurrentPrcb();
+
+ if (Phase == 0) {
+
+ HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
+ HalpGetParameters (LoaderBlock);
+
+ //
+ // Verify Prcb version and build flags conform to
+ // this image
+ //
+
+#if DBG
+ if (!(pPRCB->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL,
+ 2, pPRCB->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (pPRCB->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
+ }
+#endif
+ if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+ //
+ // Phase 0 initialization
+ // only called by P0
+ //
+
+ //
+ // Check to make sure the MCA HAL is not running on an ISA/EISA
+ // system, and vice-versa.
+ //
+#if MCA
+ if (HalpBusType != MACHINE_TYPE_MCA) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 3, HalpBusType, MACHINE_TYPE_MCA, 0);
+ }
+#else
+ if (HalpBusType == MACHINE_TYPE_MCA) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 3, HalpBusType, 0, 0);
+ }
+#endif
+
+ HalpInitializePICs();
+
+ //
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ CurrentIrql = KfRaiseIrql(CurrentIrql);
+
+ //
+ // Initialize CMOS
+ //
+
+ HalpInitializeCmos();
+
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Register cascade vector
+ //
+
+ HalpRegisterVector (
+ InternalUsage,
+ PIC_SLAVE_IRQ + PRIMARY_VECTOR_BASE,
+ PIC_SLAVE_IRQ + PRIMARY_VECTOR_BASE,
+ HIGH_LEVEL );
+
+ //
+ // Register base IO space used by hal
+ //
+
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ if (HalpBusType == MACHINE_TYPE_EISA) {
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ }
+
+ //
+ // Note that HalpInitializeClock MUST be called after
+ // HalpInitializeStallExecution, because HalpInitializeStallExecution
+ // reprograms the timer.
+ //
+
+ HalpInitializeStallExecution(0);
+
+ //
+ // Setup the clock
+ //
+
+ HalpInitializeClock();
+
+ //
+ // Make sure profile is disabled
+ //
+
+ HalStopProfileInterrupt(0);
+
+ HalpInitializeDisplay();
+
+ //
+ // Initialize spinlock used by HalGetBusData hardware access routines
+ //
+
+ KeInitializeSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
+ Descriptor->MemoryType != LoaderSpecialMemory &&
+ Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ break;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only need for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ }
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ }
+
+ } else {
+
+ //
+ // Phase 1 initialization
+ //
+
+ if (pPRCB->Number == 0) {
+
+ //
+ // If P0, then setup global vectors
+ //
+
+ HalpRegisterInternalBusHandlers ();
+
+ //
+ // Set feature bits
+ //
+
+ HalpFeatureBits = HalpGetFeatureBits();
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ V2I (CLOCK_VECTOR), // Bus interrupt level
+ CLOCK_VECTOR, // System IDT
+ CLOCK2_LEVEL, // System Irql
+ HalpClockInterrupt, // ISR
+ Latched );
+
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ V2I (PROFILE_VECTOR), // Bus interrupt level
+ PROFILE_VECTOR, // System IDT
+ PROFILE_LEVEL, // System Irql
+ HalpProfileInterrupt, // ISR
+ Latched );
+
+ //
+ // If 486, the FP error will be routed via trap10. So we
+ // don't enable irq13. Otherwise (CPU=386), we will enable irq13
+ // to handle FP error.
+ //
+
+ if (pPRCB->CpuType == 3) {
+ HalpEnableInterruptHandler (
+ DeviceUsage, // Report as device vector
+ V2I (I386_80387_VECTOR), // Bus interrupt level
+ I386_80387_VECTOR, // System IDT
+ I386_80387_IRQL, // System Irql
+ HalpIrq13Handler, // ISR
+ Latched );
+ }
+ }
+
+ }
+
+
+#ifndef NT_UP
+ HalpInitMP (Phase, LoaderBlock);
+#endif
+
+ return TRUE;
+}
+
+ULONG
+HalpGetFeatureBits (
+ VOID
+ )
+{
+ UCHAR Buffer[50];
+ ULONG Junk, ProcessorFeatures, Bits;
+ PKPRCB Prcb;
+
+ Bits = 0;
+
+ Prcb = KeGetCurrentPrcb();
+
+ if (!Prcb->CpuID) {
+ return Bits;
+ }
+
+ //
+ // Determine the processor type
+ //
+
+ HalpCpuID (0, &Junk, (PULONG) Buffer+0, (PULONG) Buffer+2, (PULONG) Buffer+1);
+ Buffer[12] = 0;
+
+ //
+ // If this is an Intel processor, determine whichNT compatible
+ // features are present
+ //
+
+ if (strcmp (Buffer, HalpGenuineIntel) == 0) {
+
+ HalpCpuID (1, &Junk, &Junk, &Junk, &ProcessorFeatures);
+
+ //
+ // Check Intel feature bits for HAL features needed
+ //
+
+ if (Prcb->CpuType == 6) {
+ Bits |= HAL_PERF_EVENTS;
+ }
+
+ if (Prcb->CpuType < 6) {
+ Bits |= HAL_NO_SPECULATION;
+ }
+
+ if (ProcessorFeatures & CPUID_MCA_MASK) {
+ Bits |= HAL_MCA_PRESENT;
+ }
+
+ if (ProcessorFeatures & CPUID_MCE_MASK) {
+ Bits |= HAL_MCE_PRESENT;
+ }
+
+ }
+
+ return Bits;
+}
diff --git a/private/ntos/nthals/halx86/i386/xxioacc.asm b/private/ntos/nthals/halx86/i386/xxioacc.asm
new file mode 100644
index 000000000..8d53fe90a
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxioacc.asm
@@ -0,0 +1,386 @@
+ title "ix ioaccess"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixioacc.asm
+;
+; Abstract:
+;
+; Procedures to correctly touch I/O registers.
+;
+; Author:
+;
+; Bryan Willman (bryanwi) 16 May 1990
+;
+; Environment:
+;
+; User or Kernel, although privledge (IOPL) may be required.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+ .list
+
+_TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; I/O port space read and write functions.
+;
+; These have to be actual functions on the 386, because we need
+; to use assembler, but cannot return a value if we inline it.
+;
+; This set of functions manipulates I/O registers in PORT space.
+; (Uses x86 in and out instructions)
+;
+; WARNING: Port addresses must always be in the range 0 to 64K, because
+; that's the range the hardware understands.
+;
+;--
+
+
+
+;++
+;
+; UCHAR
+; READ_PORT_UCHAR(
+; PUCHAR Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_UCHAR ,1
+cPublicFpo 1, 0
+
+ xor eax, eax ; Eliminate partial stall on return to caller
+
+ mov edx,[esp+4] ; (dx) = Port
+ in al,dx
+ stdRET _READ_PORT_UCHAR
+
+stdENDP _READ_PORT_UCHAR
+
+
+
+;++
+;
+; USHORT
+; READ_PORT_USHORT(
+; PUSHORT Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_USHORT ,1
+cPublicFpo 1, 0
+
+ xor eax, eax ; Eliminate partial stall on return to caller
+
+ mov edx,[esp+4] ; (dx) = Port
+ in ax,dx
+ stdRET _READ_PORT_USHORT
+
+stdENDP _READ_PORT_USHORT
+
+
+
+;++
+;
+; ULONG
+; READ_PORT_ULONG(
+; PULONG Port
+; )
+;
+; Arguments:
+; (esp+4) = Port
+;
+; Returns:
+; Value in Port.
+;
+;--
+cPublicProc _READ_PORT_ULONG ,1
+cPublicFpo 1, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ in eax,dx
+ stdRET _READ_PORT_ULONG
+
+stdENDP _READ_PORT_ULONG
+
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_UCHAR(
+; PUCHAR Port,
+; PUCHAR Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_UCHAR ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep insb
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_UCHAR
+
+stdENDP _READ_PORT_BUFFER_UCHAR
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_USHORT(
+; PUSHORT Port,
+; PUSHORT Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_USHORT ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep insw
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_USHORT
+
+stdENDP _READ_PORT_BUFFER_USHORT
+
+
+;++
+;
+; VOID
+; READ_PORT_BUFFER_ULONG(
+; PULONG Port,
+; PULONG Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _READ_PORT_BUFFER_ULONG ,3
+cPublicFpo 3, 0
+
+ mov eax, edi ; Save edi
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov edi,[esp+8] ; (edi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep insd
+ mov edi, eax
+ stdRET _READ_PORT_BUFFER_ULONG
+
+stdENDP _READ_PORT_BUFFER_ULONG
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_UCHAR(
+; PUCHAR Port,
+; UCHAR Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_UCHAR ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov al,[esp+8] ; (al) = Value
+ out dx,al
+ stdRET _WRITE_PORT_UCHAR
+
+stdENDP _WRITE_PORT_UCHAR
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_USHORT(
+; PUSHORT Port,
+; USHORT Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_USHORT ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov eax,[esp+8] ; (ax) = Value
+ out dx,ax
+ stdRET _WRITE_PORT_USHORT
+
+stdENDP _WRITE_PORT_USHORT
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_ULONG(
+; PULONG Port,
+; ULONG Value
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Value
+;
+;--
+cPublicProc _WRITE_PORT_ULONG ,2
+cPublicFpo 2, 0
+
+ mov edx,[esp+4] ; (dx) = Port
+ mov eax,[esp+8] ; (eax) = Value
+ out dx,eax
+ stdRET _WRITE_PORT_ULONG
+
+stdENDP _WRITE_PORT_ULONG
+
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_UCHAR(
+; PUCHAR Port,
+; PUCHAR Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_UCHAR ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep outsb
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_UCHAR
+
+stdENDP _WRITE_PORT_BUFFER_UCHAR
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_USHORT(
+; PUSHORT Port,
+; PUSHORT Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_USHORT ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep outsw
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_USHORT
+
+stdENDP _WRITE_PORT_BUFFER_USHORT
+
+
+;++
+;
+; VOID
+; WRITE_PORT_BUFFER_ULONG(
+; PULONG Port,
+; PULONG Buffer,
+; ULONG Count
+; )
+;
+; Arguments:
+; (esp+4) = Port
+; (esp+8) = Buffer address
+; (esp+12) = Count
+;
+;--
+cPublicProc _WRITE_PORT_BUFFER_ULONG ,3
+cPublicFpo 3, 0
+
+ mov eax,esi ; Save esi
+ mov edx,[esp+4] ; (dx) = Port
+ mov esi,[esp+8] ; (esi) = buffer
+ mov ecx,[esp+12] ; (ecx) = transfer count
+ rep outsd
+ mov esi,eax
+ stdRET _WRITE_PORT_BUFFER_ULONG
+
+stdENDP _WRITE_PORT_BUFFER_ULONG
+
+
+_TEXT$00 ends
+
+ end
diff --git a/private/ntos/nthals/halx86/i386/xxkdsup.c b/private/ntos/nthals/halx86/i386/xxkdsup.c
new file mode 100644
index 000000000..62ee9da82
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxkdsup.c
@@ -0,0 +1,404 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ xxkdsup.c
+
+Abstract:
+
+ Com support. Code to init a com port, store port state, map
+ portable procedures to x86 procedures.
+
+Author:
+
+ Bryan M. Willman (bryanwi) 24-Sep-90
+
+Revision History:
+
+ Shielin Tzong (shielint) 10-Apr-91
+ Add packet control protocol.
+
+ John Vert (jvert) 11-Jul-1991
+ Moved from KD/i386 to HAL
+
+--*/
+
+#include "halp.h"
+#include "ixkdcom.h"
+#include "stdio.h"
+
+//
+// This MUST be initialized to zero so we know not to do anything when
+// CpGetByte is called when the kernel debugger is disabled.
+//
+
+CPPORT Port = {NULL, 0, PORT_DEFAULTRATE };
+
+//
+// Remember the debugger port information
+//
+
+CPPORT PortInformation = {NULL, 0, PORT_DEFAULTRATE};
+ULONG ComPort = 0;
+
+//
+// We need this so the serial driver knows that the kernel debugger
+// is using a particular port. The serial driver then knows not to
+// touch this port. KdInitCom fills this in with the number of the
+// COM port it is using (1 or 2)
+//
+// This will go in the registry as soon as the registry is working.
+//
+PUCHAR KdComPortInUse=NULL;
+
+
+BOOLEAN
+KdPortInitialize(
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure checks for which COM port should be used by kernel
+ debugger. If DebugParameter specifies a COM port, we will use it
+ even if we can not find it (we trust user). Otherwise, if COM2
+ is present and there is no mouse attaching to it, we use COM2.
+ If COM2 is not availabe, we check COM1. If both COM1 and COM2 are
+ not present, we give up and return false.
+
+Arguments:
+
+ DebugParameters - Supplies a pointer a structure which optionally
+ sepcified the debugging port information.
+
+ LoaderBlock - supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Returned Value:
+
+ TRUE - If a debug port is found.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry, ChildEntry;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey, i;
+ ULONG BaudRate = BD_19200;
+ PUCHAR PortAddress = NULL;
+ ULONG Com = 0;
+ UCHAR DebugMessage[80];
+
+ //
+ // Check if Port and baudrate have been determined.
+ //
+
+ if (PortInformation.Address == NULL) {
+
+ //
+ // First see if the DebugParameters contains debugging port info.
+ //
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ Port.Flags &= ~PORT_DEFAULTRATE;
+ }
+
+ if (DebugParameters->CommunicationPort != 0) {
+
+ //
+ // Find the configuration information of the specified serial port.
+ //
+
+ Com = DebugParameters->CommunicationPort;
+ MatchKey = Com - 1;
+ if (LoaderBlock != NULL) {
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ } else {
+
+ //
+ // Check if COM2 is present and make sure no mouse attaches to it.
+ //
+
+ MatchKey = 1;
+ if (LoaderBlock != NULL) {
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (ConfigurationEntry != NULL) {
+ ChildEntry = ConfigurationEntry->Child;
+ if ((ChildEntry != NULL) &&
+ (ChildEntry->ComponentEntry.Type == PointerPeripheral)) {
+ ConfigurationEntry = NULL;
+ }
+ }
+
+ //
+ // If COM2 does not exist or a serial mouse attaches to it, try
+ // COM1. If COM1 exists, we will use it no matter what is on
+ // it.
+ //
+
+ if (ConfigurationEntry == NULL) {
+ MatchKey = 0;
+ if (LoaderBlock != NULL) {
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (ConfigurationEntry != NULL) {
+ Com = 1;
+ } else if (CpDoesPortExist((PUCHAR)COM2_PORT)) {
+ PortAddress = (PUCHAR)COM2_PORT;
+ Com = 2;
+ } else if (CpDoesPortExist((PUCHAR)COM1_PORT)) {
+ PortAddress = (PUCHAR)COM1_PORT;
+ Com = 1;
+ } else {
+ return(FALSE);
+ }
+ } else {
+ Com = 2;
+ }
+ }
+
+ //
+ // Get Comport address from the component configuration data.
+ // (If we find the ComponentEntry associated with the com port)
+ //
+
+ if (ConfigurationEntry) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ for (i = 0; i < List->Count ; i++ ) {
+ Descriptor = &List->PartialDescriptors[i];
+ if (Descriptor->Type == CmResourceTypePort) {
+ PortAddress = (PUCHAR)Descriptor->u.Port.Start.LowPart;
+ }
+ }
+ }
+
+ //
+ // If we can not find the port address for the comport, simply use
+ // default value.
+ //
+
+ if (PortAddress == NULL) {
+ switch (Com) {
+ case 1:
+ PortAddress = (PUCHAR)0x3f8;
+ break;
+ case 2:
+ PortAddress = (PUCHAR)0x2f8;
+ break;
+ case 3:
+ PortAddress = (PUCHAR)0x3e8;
+ break;
+ case 4:
+ PortAddress = (PUCHAR)0x2e8;
+ }
+ }
+
+ //
+ // Initialize the port structure.
+ //
+
+ ComPort = Com;
+ PortInformation.Address = PortAddress;
+ PortInformation.Baud = BaudRate;
+ }
+
+ if (Initialize == TRUE) {
+ CpInitialize(&Port,
+ PortInformation.Address,
+ PortInformation.Baud
+ );
+ KdComPortInUse= PortInformation.Address;
+ sprintf(DebugMessage, MSG_DEBUG_ENABLE,
+ ComPort, PortInformation.Address, PortInformation.Baud);
+ HalDisplayString("\n");
+ HalDisplayString(DebugMessage);
+ }
+ return(TRUE);
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ Fetch a byte from the debug port and return it.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level, and
+ necessary multiprocessor synchronization has been performed before this
+ routine is called.
+
+Arguments:
+
+ Input - Returns the data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+ CP_GET_ERROR is returned if error encountered during reading.
+ CP_GET_NODATA is returned if timeout.
+
+--*/
+
+{
+ return CpGetByte(&Port, Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ Fetch a byte from the debug port and return it if one is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level, and
+ necessary multiprocessor synchronization has been performed before this
+ routine is called.
+
+Arguments:
+
+ Input - Returns the data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+ CP_GET_ERROR is returned if error encountered during reading.
+ CP_GET_NODATA is returned if timeout.
+
+--*/
+
+{
+ return CpGetByte(&Port, Input, FALSE);
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ Write a byte to the debug port.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level, and
+ necessary multiprocessor synchronization has been performed before this
+ routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CpPutByte(&Port, Output);
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine does NOTHING on the x86.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level, and
+ necessary multiprocessor synchronization has been performed before this
+ routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ Port.Flags &= ~PORT_SAVED;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine does NOTHING on the x86.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level, and
+ necessary multiprocessor synchronization has been performed before this
+ routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ Port.Flags |= PORT_SAVED;
+}
+
diff --git a/private/ntos/nthals/halx86/i386/xxmemory.c b/private/ntos/nthals/halx86/i386/xxmemory.c
new file mode 100644
index 000000000..c88792a85
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxmemory.c
@@ -0,0 +1,368 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow the HAL to map physical memory.
+
+Author:
+
+ John Vert (jvert) 3-Sep-1991
+
+Environment:
+
+ Phase 0 initialization only.
+
+Revision History:
+
+--*/
+#include "halp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpAllocPhysicalMemory)
+#endif
+
+
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+//
+// Almost all of the last 4Mb of memory are available to the HAL to map
+// physical memory. The kernel may use a couple of PTEs in this area for
+// special purposes, so skip any which are not zero.
+//
+// Note that the HAL's heap only uses the last 3Mb. This is so we can
+// reserve the first 1Mb for use if we have to return to real mode.
+// In order to return to real mode we need to identity-map the first 1Mb of
+// physical memory.
+//
+PVOID HalpHeapStart=(PVOID)0xffd00000;
+
+
+PVOID
+HalpMapPhysicalMemory(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps physical memory into the area of virtual memory
+ reserved for the HAL. It does this by directly inserting the PTE
+ into the Page Table which the OS Loader has provided.
+
+ N.B. This routine does *NOT* update the MemoryDescriptorList. The
+ caller is responsible for either removing the appropriate
+ physical memory from the list, or creating a new descriptor to
+ describe it.
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address of the start of the
+ area of physical memory to be mapped.
+
+ NumberPages - Supplies the number of pages contained in the area of
+ physical memory to be mapped.
+
+Return Value:
+
+ PVOID - Virtual address at which the requested block of physical memory
+ was mapped
+
+ NULL - The requested block of physical memory could not be mapped.
+
+--*/
+
+{
+ PHARDWARE_PTE PTE;
+ ULONG PagesMapped;
+ PVOID VirtualAddress;
+
+ //
+ // The OS Loader sets up hyperspace for us, so we know that the Page
+ // Tables are magically mapped starting at V.A. 0xC0000000.
+ //
+
+ PagesMapped = 0;
+ while (PagesMapped < NumberPages) {
+ //
+ // Look for enough consecutive free ptes to honor mapping
+ //
+
+ PagesMapped = 0;
+ VirtualAddress = HalpHeapStart;
+
+ while (PagesMapped < NumberPages) {
+ PTE=MiGetPteAddress(VirtualAddress);
+ if (*(PULONG)PTE != 0) {
+
+ //
+ // Pte is not free, skip up to the next pte and start over
+ //
+
+ HalpHeapStart = (PVOID) ((ULONG)VirtualAddress + PAGE_SIZE);
+ break;
+ }
+ VirtualAddress = (PVOID) ((ULONG)VirtualAddress + PAGE_SIZE);
+ PagesMapped++;
+ }
+
+ }
+
+
+ PagesMapped = 0;
+ VirtualAddress = (PVOID) ((ULONG) HalpHeapStart | BYTE_OFFSET (PhysicalAddress));
+ while (PagesMapped < NumberPages) {
+ PTE=MiGetPteAddress(HalpHeapStart);
+
+ PTE->PageFrameNumber = ((ULONG)PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ PhysicalAddress = (PVOID)((ULONG)PhysicalAddress + PAGE_SIZE);
+ HalpHeapStart = (PVOID)((ULONG)HalpHeapStart + PAGE_SIZE);
+
+ ++PagesMapped;
+ }
+
+ //
+ // Flush TLB
+ //
+ HalpFlushTLB ();
+ return(VirtualAddress);
+}
+
+PVOID
+HalpMapPhysicalMemoryWriteThrough(
+ IN PVOID PhysicalAddress,
+ IN ULONG NumberPages
+)
+/*++
+
+Routine Description:
+
+ Maps a physical memory address into virtual space, same as
+ HalpMapPhysicalMemory(). The difference is that this routine
+ marks the pages as PCD/PWT so that writes to the memory mapped registers
+ mapped here won't get delayed in the future x86 internal write-back caches.
+
+Arguments:
+
+ PhysicalAddress - Supplies a physical address of the memory to be mapped
+
+ NumberPages - Number of pages to map
+
+Return Value:
+
+ Virtual address pointer to the requested physical address
+
+--*/
+{
+ ULONG Index;
+ PHARDWARE_PTE PTE;
+ PVOID VirtualAddress;
+
+ VirtualAddress = HalpMapPhysicalMemory(PhysicalAddress, NumberPages);
+ PTE = MiGetPteAddress(VirtualAddress);
+
+ for (Index = 0; Index < NumberPages; Index++, PTE++) {
+
+ PTE->CacheDisable = 1;
+ PTE->WriteThrough = 1;
+ }
+
+ return VirtualAddress;
+}
+
+
+PVOID
+HalpRemapVirtualAddress(
+ IN PVOID VirtualAddress,
+ IN PVOID PhysicalAddress,
+ IN BOOLEAN WriteThrough
+ )
+/*++
+
+Routine Description:
+
+ This routine remaps a PTE to the physical memory address provided.
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address of the area to be mapped
+
+ VirtualAddress - Valid address to be remapped
+
+ WriteThrough - Map as cachable or WriteThrough
+
+Return Value:
+
+ PVOID - Virtual address at which the requested block of physical memory
+ was mapped
+
+ NULL - The requested block of physical memory could not be mapped.
+
+--*/
+{
+ PHARDWARE_PTE PTE;
+
+ PTE = MiGetPteAddress (VirtualAddress);
+ PTE->PageFrameNumber = ((ULONG)PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ if (WriteThrough) {
+ PTE->CacheDisable = 1;
+ PTE->WriteThrough = 1;
+ }
+
+ //
+ // Flush TLB
+ //
+ HalpFlushTLB();
+ return(VirtualAddress);
+
+}
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The physical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+
+ PhysicalAddress =
+ (Descriptor->BasePage + AlignmentOffset) << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+ return PhysicalAddress;
+}
diff --git a/private/ntos/nthals/halx86/i386/xxstubs.c b/private/ntos/nthals/halx86/i386/xxstubs.c
new file mode 100644
index 000000000..251bce23c
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxstubs.c
@@ -0,0 +1,131 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ stubs.c
+
+Abstract:
+
+ This implements the HAL routines which don't do anything on x86.
+
+Author:
+
+ John Vert (jvert) 11-Jul-1991
+
+Revision History:
+
+--*/
+#include "nthal.h"
+#include "arc.h"
+#include "arccodes.h"
+
+VOID
+HalSaveState(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Saves the system state into the restart block. Currently does nothing.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Does not return
+
+--*/
+
+{
+ DbgPrint("HalSaveState called - System stopped\n");
+
+ KeBugCheck(0);
+}
+
+
+BOOLEAN
+HalDataBusError(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Called when a data bus error occurs. There is no way to fix this on
+ x86.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ FALSE
+
+--*/
+
+{
+ return(FALSE);
+
+}
+
+BOOLEAN
+HalInstructionBusError(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Called when an instruction bus error occurs. There is no way to fix this
+ on x86.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ FALSE
+
+--*/
+
+{
+ return(FALSE);
+
+}
+
+VOID
+KeFlushWriteBuffer(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Flushes all write buffers and/or other data storing or reordering
+ hardware on the current processor. This ensures that all previous
+ writes will occur before any new reads or writes are completed.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+}
diff --git a/private/ntos/nthals/halx86/i386/xxtime.c b/private/ntos/nthals/halx86/i386/xxtime.c
new file mode 100644
index 000000000..f726cc184
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/xxtime.c
@@ -0,0 +1,91 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ an x86 system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ HalpReadCmosTime(TimeFields);
+ return TRUE;
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ HalpWriteCmosTime(TimeFields);
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halx86/makefile b/private/ntos/nthals/halx86/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halx86/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halx86/makefile.inc b/private/ntos/nthals/halx86/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halx86/makefile.inc
@@ -0,0 +1,2 @@
+obj\i386\hal.def: hal.src
+ $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def
diff --git a/private/ntos/nthals/halx86/sources b/private/ntos/nthals/halx86/sources
new file mode 100644
index 000000000..2976a0745
--- /dev/null
+++ b/private/ntos/nthals/halx86/sources
@@ -0,0 +1,100 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=hal
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+!IF $(386)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\..\inc;..\..\ke;..\..\io
+
+SOURCES=
+
+i386_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ i386\ixbeep.asm \
+ i386\ixbusdat.c \
+ i386\ixclock.asm \
+ i386\ixcmos.asm \
+ i386\ixdat.c \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixinfo.c \
+ i386\ixipi.asm \
+ i386\ixirql.asm \
+ i386\ixisabus.c \
+ i386\ixisasup.c \
+ i386\ixkdcom.c \
+ i386\ixlock.asm \
+ i386\ixmca.c \
+ i386\ixmcaa.asm \
+ i386\ixnmi.c \
+ i386\ixpcibus.c \
+ i386\ixpciint.c \
+ i386\ixpcibrd.c \
+ i386\ixphwsup.c \
+ i386\ixprofil.asm \
+ i386\ixproc.c \
+ i386\ixsysbus.c \
+ i386\ixthunk.asm \
+ i386\ixreboot.c \
+ i386\ixstall.asm \
+ i386\ixswint.asm \
+ i386\ixsysint.asm \
+ i386\ixusage.c \
+ i386\xxbiosa.asm \
+ i386\xxbiosc.c \
+ i386\xxdisp.c \
+ i386\xxhal.c \
+ i386\xxioacc.asm \
+ i386\xxkdsup.c \
+ i386\xxmemory.c \
+ i386\xxstubs.c \
+ i386\xxtime.c
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\hal.lib
+
+!ENDIF
diff --git a/private/ntos/nthals/halxlt/alpha/adjust.c b/private/ntos/nthals/halxlt/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/alcor.h b/private/ntos/nthals/halxlt/alpha/alcor.h
new file mode 100644
index 000000000..90931ecfa
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/alcor.h
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alcor.h
+
+Abstract:
+
+ This file contains definitions specific to the Alcor platform
+
+Author:
+
+ Steve Brooks 11-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _ALCORH_
+#define _ALCORH_
+
+//
+// Include definitions for the components that make up Alcor.
+//
+
+#include "axp21164.h" // 21164 (EV5) microprocessor definitions
+#include "cia.h" // CIA controller definitions
+#include "gru.h" // GRU controller definitions
+
+//
+// Define number of PCI, EISA, and combo slots
+//
+
+#define NUMBER_EISA_SLOTS 4
+#define NUMBER_PCI_SLOTS 5
+#define NUMBER_COMBO_SLOTS 1
+
+//
+// Define the data and csr ports for the I2C bus and OCP.
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x550
+#define I2C_INTERFACE_CSR_PORT 0x551
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+//
+// Define the index and data ports for the NS Super IO chip.
+//
+
+#define SUPERIO_INDEX_PORT 0x398
+#define SUPERIO_DATA_PORT 0x399
+#define SUPERIO_PORT_LENGTH 0x2
+
+//
+// PCI bus address values:
+//
+
+#define PCI_MAX_LOCAL_DEVICE 12
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+//
+// Define numbers and names of cpus.
+//
+
+#define HAL_PRIMARY_PROCESSOR ((ULONG)0)
+#define HAL_MAXIMUM_PROCESSOR ((ULONG)0)
+
+//
+// Define default processor frequency.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (250)
+
+//
+// Define Alcor-specific routines that are really macros for performance.
+//
+
+#define HalpAcknowledgeEisaInterrupt(x) (UCHAR)(INTERRUPT_ACKNOWLEDGE(x))
+
+//
+// Define the per-processor data structures allocated in the PCR.
+//
+
+typedef struct _ALCOR_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+ } ALCOR_PCR, *PALCOR_PCR;
+
+#define HAL_PCR ( (PALCOR_PCR)(&(PCR->HalReserved)) )
+
+#endif //_ALCORH_
diff --git a/private/ntos/nthals/halxlt/alpha/alcorerr.c b/private/ntos/nthals/halxlt/alpha/alcorerr.c
new file mode 100644
index 000000000..dfd3bc8cf
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/alcorerr.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alcorerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Alcor platform.
+
+Author:
+
+ Joe Notarangelo 27-Jul-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "alcor.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+VOID
+HalpAlcorErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for an ALCOR machine check interrupt
+ The function calls HalpCiaReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // If this is a CIA uncorrectable error then report the error and
+ // crash the system.
+ //
+
+ if( HalpCiaUncorrectableError() == TRUE ){
+
+ HalpCiaReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+
+ }
+
+ //
+ // It was not a CIA uncorrectable error, therefore this must be an
+ // NMI interrupt.
+ //
+
+ HalHandleNMI( NULL, NULL );
+
+ return; // never
+
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the CIA chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+ //
+ // All machine check handling on Alcor is determined by the CIA.
+ //
+
+ return( HalpCiaMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ) );
+
+}
diff --git a/private/ntos/nthals/halxlt/alpha/alinitnt.c b/private/ntos/nthals/halxlt/alpha/alinitnt.c
new file mode 100644
index 000000000..04cf746b1
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/alinitnt.c
@@ -0,0 +1,750 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ an Alcor system.
+
+Author:
+
+ Joe Notarangelo 19-Jul-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+#include "alcor.h"
+#include "iousage.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h> // to get the product build number.
+
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpFamilyName = "Alpha XL";
+
+#define MAX_INIT_MSG (80)
+
+
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+//
+// Define external references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Function prototypes.
+//
+
+BOOLEAN
+HalpInitializeAlcorInterrupts (
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpAlcorErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ );
+
+
+//
+// Irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - interval clock
+// irql 6 - not used
+// irql 7 - error, mchk, nmi, performance counters
+//
+//
+
+//
+// The hardware interrupt pins are used as follows for Alcor
+//
+// IRQ0 = CIA_INT
+// IRQ1 = SYS_INT (PCI and ESC interrupts)
+// IRQ2 = Interval Clock
+// IRQ3 = Reserved
+//
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alcor system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern ULONG HalpCiaErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+ extern ULONG HalpHaltInterrupt();
+ ULONG Vector;
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ //
+ // Initialize Alcor interrupts.
+ //
+
+ HalpInitializeAlcorInterrupts();
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpCiaErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpAlcorErrorInterrupt;
+
+ PCR->InterruptRoutine[EV5_CRD_VECTOR] =
+ (PKINTERRUPT_ROUTINE)Halp21164CorrectedErrorInterrupt;
+
+ HalpStart21164Interrupts();
+
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV5
+ based machine via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is a NOOP for Alcor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Platform-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the PCI parity checking.
+ //
+
+ if( HalDisablePCIParityChecking != 0 ){
+ PciParityChecking = FALSE;
+ } else {
+ PciParityChecking = TRUE;
+ }
+
+ HalpInitializeCiaMachineChecks( ReportCorrectables = TRUE,
+ PciParityChecking );
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ sprintf(MsgBuffer,
+ "Digital Equipment Corporation %s %d",
+ HalpFamilyName,
+ HalpClockMegaHertz );
+
+ HalDisplayString( MsgBuffer );
+ HalDisplayString( "\n" );
+
+ //
+ // Build the string to register the HAL.
+ //
+
+ strcat(MsgBuffer, " PCI/ISA HAL");
+
+ HalpRegisterPlatformResources( MsgBuffer );
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Eisa);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ Resource.u.Start = SUPERIO_INDEX_PORT;
+ Resource.u.Length = SUPERIO_PORT_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaChannel = 0x4;
+ Resource.u.DmaPort = 0x0;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function is called from HalpAllocateUncorrectableErrorFrame.
+ This function retuns the size of the system specific error frame
+ sizes.
+
+Arguments:
+
+ RawProcessorSize - Processor-specific uncorrectable frame size.
+
+ RawSystemInfoSize - system-specific uncorrectable frame size.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(CIA_UNCORRECTABLE_FRAME);
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ Fills in the system information structure.
+ NOTE: Must later investigate the Fw call to get the firmware revision
+ ID. Must also figure out a way to get the OS version (preferebly the
+ build number).
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION structure.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char systemtype[] = "XLT";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+
+ return;
+}
+
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to Alcor and the call should be
+// ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+//
+//jnfix - this variable is needed because the clock interrupt handler
+// - in intsup.s was made to be familiar with ev4prof.c, unfortunate
+// - since we don't use ev4prof.c, so for now this is a hack, later
+// - we will either fix intsup.s or create a new intsup.s that does
+// - not have this hack
+//
+
+ULONG HalpNumberOfTicksReload;
diff --git a/private/ntos/nthals/halxlt/alpha/alintsup.c b/private/ntos/nthals/halxlt/alpha/alintsup.c
new file mode 100644
index 000000000..ddb18d70f
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/alintsup.c
@@ -0,0 +1,599 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Alcor systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Chao Chen (DEC) 26-July-1994
+ Adapted from Avanti module for Alcor.
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "alcor.h"
+#include "pcrtc.h"
+#include "pintolin.h"
+
+
+//
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+
+KINTERRUPT HalpPciInterrupt;
+KINTERRUPT HalpEisaInterrupt;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Declare the interrupt handler for the EISA bus. The interrupt dispatch
+// routine, HalpEisaDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following functions handle the PCI interrupts.
+//
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitializeAlcorInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the EISA interrupt controller; the Alcor ESC's interrupt controller is
+ compatible with the EISA interrupt contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) AlcorPCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // Initialize the PCI interrupts.
+ //
+
+ HalpInitializePciInterrupts();
+
+ //
+ // Initialize the ESC's PICs for EISA interrupts.
+ //
+
+ HalpInitializeEisaInterrupts();
+
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Alcor comes from a Dallas real-time clock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Acknowledge the clock interrupt by reading the control register C of
+ // the Real Time Clock.
+ //
+
+ HalpReadClockRegister( RTC_CONTROL_REGISTERC );
+
+ return;
+}
+
+
+//
+// The enable mask for all interrupts sourced from the GRU (all device
+// interrupts, and all from PCI). A "1" indicates the interrupt is enabled.
+//
+
+ULONG HalpPciInterruptMask;
+
+
+VOID
+HalpInitializePciInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Alcor PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Disable interrupts except EISA.
+ //
+
+ HalpPciInterruptMask = GRU_ENABLE_EISA_INT;
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntMask,
+ HalpPciInterruptMask);
+
+ //
+ // Set all interrupts to level.
+ //
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntEdge,
+ GRU_SET_LEVEL_INT);
+
+ //
+ // Set all interrupts to active low except EISA.
+ //
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntHiLo,
+ GRU_SET_LOW_INT);
+
+ //
+ // Clear the interrupt clear register.
+ //
+
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntClear, 0);
+
+
+}
+
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ HalpPciInterruptMask &= (ULONG) ~(1 << Vector);
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntMask,
+ HalpPciInterruptMask);
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Alcor PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the PCI interrupt vector, relative to 0.
+ //
+
+ Vector -= PCI_VECTORS;
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to one,
+ // to ensable that PCI interrupt.
+ //
+
+ HalpPciInterruptMask |= (ULONG) 1 << Vector;
+ WRITE_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntMask,
+ HalpPciInterruptMask);
+
+}
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ ULONG IdtIndex;
+ ULONG IntNumber;
+ PKINTERRUPT InterruptObject;
+ ULONG PCIVector;
+ ULONG Slot;
+
+ //
+ // Read in the interrupt register.
+ //
+
+ PCIVector=READ_GRU_REGISTER(&((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntReq);
+
+ //
+ // Consider only those interrupts which are currently enabled.
+ //
+
+ PCIVector &= HalpPciInterruptMask;
+
+ //
+ // Continue processing interrupts while any are requested.
+ //
+
+ while( (PCIVector & (GRU_EISA_MASK_INT | GRU_PCI_MASK_INT)) != 0 ){
+
+ //
+ // Did PCI or EISA interrupt occur?
+ //
+
+ if (PCIVector & GRU_EISA_MASK_INT) {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ HalpEisaDispatch( Interrupt, (PVOID)CIA_PCI_INTACK_QVA, TrapFrame);
+
+ } else {
+
+ //
+ // PCI interrupt. Find out which slot.
+ //
+
+ for (Slot = 0; Slot < NUMBER_PCI_SLOTS; Slot++) {
+
+ if (PCIVector & 0xf)
+ break;
+ else
+ PCIVector = PCIVector >> 4;
+ }
+
+ //
+ // Find out which of the IntA, IntB, IntC, or IntD occurred.
+ //
+
+ for (IntNumber = 0; IntNumber < 4; IntNumber++) {
+
+ if (PCIVector & 0x1)
+ break;
+ else
+ PCIVector = PCIVector >> 1;
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ IdtIndex = (Slot * (NUMBER_PCI_SLOTS - 1) + IntNumber) +
+ PCI_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+ }
+
+ //
+ // Check for more interrupts.
+ //
+
+ PCIVector = READ_GRU_REGISTER(
+ &((PGRU_INTERRUPT_CSRS)GRU_CSRS_QVA)->IntReq);
+ PCIVector &= HalpPciInterruptMask;
+
+ } //end while( (PCIVector & (GRU_EISA_MASK_INT | GRU_PCI_MASK_INT)) != 0 )
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halxlt/alpha/allstart.c b/private/ntos/nthals/halxlt/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/alsysint.c b/private/ntos/nthals/halxlt/alpha/alsysint.c
new file mode 100644
index 000000000..384133a2e
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/alsysint.c
@@ -0,0 +1,497 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Alcor system.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "alcor.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Disable the correctable error interrupt.
+ //
+
+ {
+ CIA_ERR_MASK CiaErrMask;
+
+ CiaErrMask.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.CorErr = 0x0;
+
+ WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= PCI_VECTORS &&
+ Vector < MAXIMUM_PCI_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpEnablePciInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+
+ case CORRECTABLE_VECTOR:
+
+ //
+ // Enable the correctable error interrupt.
+ //
+
+ {
+ CIA_ERR_MASK CiaErrMask;
+
+ CiaErrMask.all = READ_CIA_REGISTER(
+ &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask);
+
+ CiaErrMask.CorErr = 0x1;
+
+ WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
+ CiaErrMask.all
+ );
+
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ }
+
+ Enabled = TRUE;
+ break;
+
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ ULONG BusNumber = BusHandler->BusNumber;
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG Vector;
+
+ *Affinity = 1;
+
+ switch (InterfaceType) {
+
+ case ProcessorInternal:
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else if ((Vector = HalpGet21164CorrectableVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Correctable error interrupt was sucessfully recognized.
+ //
+
+ *Affinity = 1;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+
+ break;
+
+ case Internal:
+
+ //
+ // This bus type is for things connected to the processor
+ // in some way other than a standard bus, e.g., (E)ISA, PCI.
+ // Since devices on this "bus," apart from the special case of
+ // the processor, above, interrupt via the 82c59 cascade in the
+ // ESC, we assign vectors based on (E)ISA_VECTORS - see below.
+ // Firmware must agree on these vectors, as it puts them in
+ // the CDS.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+ case Isa:
+
+ //
+ // Assumes all ISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus ISA_VECTORS.
+ // N.B.: this encoding technique uses the notion of defining a
+ // base interrupt vector in the space defined by the constant,
+ // ISA_VECTORS, which may or may not differ from EISA_VECTORS or
+ // PCI_VECTORS.
+ //
+
+ return(BusInterruptLevel + ISA_VECTORS);
+ break;
+
+
+ case Eisa:
+
+ //
+ // Assumes all EISA devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+ break;
+
+ case PCIBus:
+
+ //
+ // Assumes all PCI devices coming in on same processor pin
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR
+ //
+ // N.B. The BusInterruptLevel is one-based while the vectors
+ // themselves are zero-based. The BusInterruptLevel must be
+ // one-based because if scsiport sees a zero vector then it
+ // will believe the interrupt is not connected. So in PCI
+ // configuration we have made the interrupt vector correspond
+ // to the slot and interrupt pin.
+ //
+ // N.B - bias for disjoint bus levels
+ //
+
+ return( (BusInterruptLevel - 0x11) + PCI_VECTORS);
+
+ break;
+
+ default:
+
+ //
+ // Not an interface supported on Alcor systems.
+ //
+
+#if defined(HALDBG)
+
+ DbgPrint("ALSYSINT: InterfaceType (%x) not supported on Alcor\n",
+ InterfaceType);
+
+#endif
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ break;
+
+ } //end switch(InterfaceType)
+
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ This routine performs no function on an Alcor because it is a
+ uni-processor system.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/halxlt/alpha/apecs.c b/private/ntos/nthals/halxlt/alpha/apecs.c
new file mode 100644
index 000000000..06eb91348
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/apecs.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecs.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/apecserr.c b/private/ntos/nthals/halxlt/alpha/apecserr.c
new file mode 100644
index 000000000..441154cc9
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/apecserr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecserr.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/apecsio.s b/private/ntos/nthals/halxlt/alpha/apecsio.s
new file mode 100644
index 000000000..27bb7caa7
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/apecsio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\apecsio.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/bios.c b/private/ntos/nthals/halxlt/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/busdata.c b/private/ntos/nthals/halxlt/alpha/busdata.c
new file mode 100644
index 000000000..f3c197f82
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/busdata.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+ Steve Brooks 30-Jun-1994
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halxlt/alpha/cache.c b/private/ntos/nthals/halxlt/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/cia.c b/private/ntos/nthals/halxlt/alpha/cia.c
new file mode 100644
index 000000000..7948bfe16
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/cia.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cia.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ciaaddr.c b/private/ntos/nthals/halxlt/alpha/ciaaddr.c
new file mode 100644
index 000000000..b85818ac0
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ciaaddr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaaddr.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ciaerr.c b/private/ntos/nthals/halxlt/alpha/ciaerr.c
new file mode 100644
index 000000000..bfb9efc93
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ciaerr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaerr.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ciaio.s b/private/ntos/nthals/halxlt/alpha/ciaio.s
new file mode 100644
index 000000000..16202a7e1
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ciaio.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciaio.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ciamapio.c b/private/ntos/nthals/halxlt/alpha/ciamapio.c
new file mode 100644
index 000000000..3e9f7a9c1
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ciamapio.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ciamapio.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/cmos8k.c b/private/ntos/nthals/halxlt/alpha/cmos8k.c
new file mode 100644
index 000000000..091dfa410
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/cmos8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cmos8k.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/devintr.s b/private/ntos/nthals/halxlt/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ebsgdma.c b/private/ntos/nthals/halxlt/alpha/ebsgdma.c
new file mode 100644
index 000000000..e2d35353d
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ebsgdma.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
diff --git a/private/ntos/nthals/halxlt/alpha/eisasup.c b/private/ntos/nthals/halxlt/alpha/eisasup.c
new file mode 100644
index 000000000..1b52e85e7
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/eisasup.c
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
diff --git a/private/ntos/nthals/halxlt/alpha/ev5cache.c b/private/ntos/nthals/halxlt/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ev5int.c b/private/ntos/nthals/halxlt/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ev5ints.s b/private/ntos/nthals/halxlt/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ev5mchk.c b/private/ntos/nthals/halxlt/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ev5mem.s b/private/ntos/nthals/halxlt/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ev5prof.c b/private/ntos/nthals/halxlt/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/fwreturn.c b/private/ntos/nthals/halxlt/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/haldebug.c b/private/ntos/nthals/halxlt/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/halpal.s b/private/ntos/nthals/halxlt/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/haltsup.s b/private/ntos/nthals/halxlt/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/idle.s b/private/ntos/nthals/halxlt/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/info.c b/private/ntos/nthals/halxlt/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/inithal.c b/private/ntos/nthals/halxlt/alpha/inithal.c
new file mode 100644
index 000000000..d0b4b3539
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/inithal.c
@@ -0,0 +1,1063 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inithal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+ 24-Sep-1993 Joe Notarangelo
+ Restructured to make this module platform-independent.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+PERROR_FRAME PUncorrectableError;
+
+//
+// external
+//
+
+ULONG HalDisablePCIParityChecking = 0xffffffff;
+
+//
+// Define HAL spinlocks.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Mask of all of the processors that are currently active.
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// Mapping of the logical processor numbers to the physical processors.
+//
+
+ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ULONG AlreadySet = 0;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ;
+
+ULONGLONG HalpContiguousPhysicalMemorySize;
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ );
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ );
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Perform initialization for the primary processor.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+ if (Phase == 0) {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+ HalpDumpMemoryDescriptors( LoaderBlock );
+
+#endif //HALDBG
+ //
+ // Get the memory Size.
+ //
+ HalpContiguousPhysicalMemorySize = HalpGetContiguousMemorySize(
+ LoaderBlock );
+
+
+ //
+ // Set second level cache size
+ // NOTE: Although we set the PCR with the right cache size this
+ // could be overridden by setting the Registry key
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
+ // \Control\Session Manager
+ // \Memory Management\SecondLevelDataCache.
+ //
+ //
+ //
+ // If the secondlevel cache size is 0 or 512KB then it is
+ // possible that the firmware is an old one. In which case
+ // we determine the cache size here. If the value is anything
+ // other than these then it is a new firmware and probably
+ // reporting the correct cache size hence use this value.
+ //
+
+ if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 ||
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){
+ PCR->SecondLevelCacheSize = HalpGetBCacheSize(
+ HalpContiguousPhysicalMemorySize
+ );
+ } else {
+ PCR->SecondLevelCacheSize =
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize;
+ }
+
+
+ //
+ // Initialize HAL spinlocks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpInitializeCia( LoaderBlock );
+
+ HalpSetTimeIncrement();
+ HalpMapIoSpace();
+ HalpCreateDmaStructures(LoaderBlock);
+ HalpEstablishErrorHandler();
+ HalpInitializeDisplay(LoaderBlock);
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+ HalpInitializeInterrupts();
+ HalpVerifyPrcbVersion();
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+ //
+ // Initialize the logical to physical processor mapping
+ // for the primary processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[0] = HAL_PRIMARY_PROCESSOR;
+
+ return TRUE;
+
+ } else {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpInitializeClockInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Allocate memory for the uncorrectable frame
+ //
+
+ HalpAllocateUncorrectableFrame();
+
+ //
+ // Initialize the Buffer for Uncorrectable Error.
+ //
+
+ HalpInitializeUncorrectableErrorFrame();
+
+ return TRUE;
+
+ }
+ }
+
+ //
+ // Perform necessary processor-specific initialization for
+ // secondary processors. Phase is ignored as this will be called
+ // only once on each secondary processor.
+ //
+
+ HalpMapIoSpace();
+ HalpInitializeInterrupts();
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors |= 1 << Prcb->Number;
+
+#if HALDBG
+
+ DbgPrint( "Secondary %d is alive\n", Prcb->Number );
+
+#endif //HALDBG
+
+ return TRUE;
+}
+
+
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called after the Phase1 Machine Dependent initialization.
+ It must be called only after Phase1 machine dependent initialization.
+ This function allocates the necessary amountof memory for storing the
+ uncorrectable error frame. This function makes a call to a machine
+ dependent function 'HalpGetMachineDependentErrorFrameSizes' for
+ getting the size of the Processor Specific and System Specific error
+ frame size. The machine dependent code will
+ know the size of these frames after the machine depedant Phase1
+ initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG RawProcessorFrameSize;
+ ULONG RawSystemFrameSize;
+ ULONG EntireErrorFrameSize;
+
+ //
+ // First get the machine dependent error frame sizes.
+ //
+ HalpGetMachineDependentErrorFrameSizes(
+ &RawProcessorFrameSize,
+ &RawSystemFrameSize);
+
+ //
+ // Compute the total size of the error frame
+ //
+ EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize +
+ RawSystemFrameSize;
+
+ //
+ // Allocate space to store the error frame.
+ // Not sure if it is OK to use ExAllocatePool at this instant.
+ // We will give this a try if it doesn't work What do we do??!!
+ //
+
+ PUncorrectableError = ExAllocatePool(NonPagedPool,
+ EntireErrorFrameSize);
+ if(PUncorrectableError == NULL) {
+ return;
+ }
+
+ PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize;
+
+ //
+ // if the size is not equal to zero then set the RawInformation pointers
+ // to point to the right place. If not set the pointer to NULL and set
+ // size to 0.
+ //
+
+ //
+ // make Raw processor info to point right after the error frame.
+ //
+ if(RawProcessorFrameSize) {
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ (PVOID)((PUCHAR)PUncorrectableError + sizeof(ERROR_FRAME) );
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ RawProcessorFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ 0;
+ }
+ if(RawSystemFrameSize){
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame.
+ RawProcessorInformation + RawProcessorFrameSize);
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ RawSystemFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ 0;
+ }
+}
+
+
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+)
+/*++
+
+Routine Description:
+
+ Collects the Processor Information and fills in the buffer.
+
+Arguments:
+
+ pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which
+ the processor information will be filled in.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+
+ pProcessorInfo->ProcessorType = PCR->ProcessorType;
+ pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision;
+
+ Prcb = PCR->Prcb;
+ pProcessorInfo->LogicalProcessorNumber = Prcb->Number;
+ pProcessorInfo->PhysicalProcessorNumber =
+ HalpLogicalToPhysicalProcessor[Prcb->Number];
+ return;
+}
+
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ ULONG LogicalNumber;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PhysicalNumber;
+ PKPRCB Prcb;
+
+#if !defined(NT_UP)
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ LogicalNumber = 0;
+ PhysicalNumber = 0;
+ do {
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){
+
+ PhysicalNumber += 1;
+
+ } else {
+
+ //
+ // Check if this processor has already been started.
+ // If it has not then start it now.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){
+
+ RtlZeroMemory( &NextRestartBlock->u.Alpha,
+ sizeof(ALPHA_RESTART_STATE));
+ NextRestartBlock->u.Alpha.IntA0 =
+ ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Alpha.IntSp =
+ ProcessorState->ContextFrame.IntSp;
+ NextRestartBlock->u.Alpha.ReiRestartAddress =
+ (ULONG)ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)LogicalNumber;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Ensure that the logical to physical mapping has been
+ // established for this processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber;
+
+ }
+
+ LogicalNumber += 1;
+ PhysicalNumber += 1;
+ }
+
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+
+ } while (NextRestartBlock != NULL);
+
+#endif // !defined(NT_UP)
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the HAL matches the kernel. If there
+ is a mismatch the HAL bugchecks the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PKPRCB Prcb;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+
+}
+
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PWSTR NameString;
+
+ //
+ // Quick out
+ //
+
+ if (AlreadySet) {
+ return;
+ }
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+ HalDisablePCIParityChecking = Component->Flags.ConsoleOut;
+ AlreadySet = TRUE;
+#if HALDBG
+ DbgPrint("ARC tree sets PCI parity checking to %s\n",
+ HalDisablePCIParityChecking ? "OFF" : "ON");
+#endif
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return (ULONG) ((Count2 - Count1)*(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the processor counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG MHz;
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = MHz = HalpClockFrequency / 1000000;
+
+ //
+ // Hotwire HalpClockMegaHertz to match product name!
+ //
+ if (MHz > 490) HalpClockMegaHertz = 500;
+ else if (MHz > 456) HalpClockMegaHertz = 466;
+ else if (MHz > 423) HalpClockMegaHertz = 433;
+ else if (MHz > 390) HalpClockMegaHertz = 400;
+ else if (MHz > 356) HalpClockMegaHertz = 366;
+ else if (MHz > 323) HalpClockMegaHertz = 333;
+ else if (MHz > 290) HalpClockMegaHertz = 300;
+ else; // there must be some mistake...
+}
+
+
+
+
+#if 0
+VOID
+HalpGatherPerformanceParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
diff --git a/private/ntos/nthals/halxlt/alpha/intsup.s b/private/ntos/nthals/halxlt/alpha/intsup.s
new file mode 100644
index 000000000..a7d9f8f4f
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "pcrtc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halxlt/alpha/ioproc.c b/private/ntos/nthals/halxlt/alpha/ioproc.c
new file mode 100644
index 000000000..36d338384
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/ioproc.c
@@ -0,0 +1,91 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halxlt/alpha/iousage.c b/private/ntos/nthals/halxlt/alpha/iousage.c
new file mode 100644
index 000000000..6ac8f6f4e
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/iousage.c
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/halxlt/alpha/iousage.h b/private/ntos/nthals/halxlt/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/halxlt/alpha/machdep.h b/private/ntos/nthals/halxlt/alpha/machdep.h
new file mode 100644
index 000000000..21a40d2f0
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Alcor platform-specific definitions.
+//
+
+#include "alcor.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halxlt/alpha/memory.c b/private/ntos/nthals/halxlt/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/nvenv.c b/private/ntos/nthals/halxlt/alpha/nvenv.c
new file mode 100644
index 000000000..ba5a5c8f7
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/nvenv.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvenv.c"
diff --git a/private/ntos/nthals/halxlt/alpha/nvram.c b/private/ntos/nthals/halxlt/alpha/nvram.c
new file mode 100644
index 000000000..879c41c68
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/nvram.c
@@ -0,0 +1 @@
+#include "..\halalpha\nvram.c"
diff --git a/private/ntos/nthals/halxlt/alpha/pcibus.c b/private/ntos/nthals/halxlt/alpha/pcibus.c
new file mode 100644
index 000000000..3ce95ed54
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pcibus.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+ Steve Brooks 30-Jun-1994
+ Joe Notarangelo 30-Jun-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+
+extern ULONG PCIMaxBus;
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ if (BusHandler->BusNumber == 0) {
+ return PciConfigType0;
+ } else {
+ return PciConfigType1;
+ }
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+#if HALDBG
+
+ DbgPrint( "PCI Config Access: Bus = %d, Device = %d, Type = %d\n",
+ BusNumber, Slot.u.bits.DeviceNumber, ConfigType );
+
+#endif //HALDBG
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+ // Note that HalpValidPCISlot has already done bounds checking
+ // on DeviceNumber.
+ //
+ // PciAddr can be intialized for different bus numbers
+ // with distinct configuration spaces here.
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+
+ //
+ // Encoding of the configuration addresses differs between
+ // passes of the CIA. Use the pre-determined global HalpCiaRevision
+ // to decide which encoding to use.
+ //
+
+ if( HalpCiaRevision == CIA_REVISION_1 ){
+
+ //
+ // CIA Pass 1
+ //
+
+ pPciAddr->u.AsULONG += ( 1 << (Slot.u.bits.DeviceNumber + 11) );
+
+ } else {
+
+ //
+ // CIA Pass 2 or later.
+ //
+
+ pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 );
+
+ }
+
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+ } else {
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+ //
+
+ pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halxlt/alpha/pciesc.c b/private/ntos/nthals/halxlt/alpha/pciesc.c
new file mode 100644
index 000000000..49142ea83
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pciesc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pciesc.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/pcisup.c b/private/ntos/nthals/halxlt/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/pcrtc.c b/private/ntos/nthals/halxlt/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/pcserial.c b/private/ntos/nthals/halxlt/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/pcspeakr.c b/private/ntos/nthals/halxlt/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/perfcntr.c b/private/ntos/nthals/halxlt/alpha/perfcntr.c
new file mode 100644
index 000000000..6c0a8f892
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/perfcntr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perfcntr.c"
+
diff --git a/private/ntos/nthals/halxlt/alpha/pintolin.h b/private/ntos/nthals/halxlt/alpha/pintolin.h
new file mode 100644
index 000000000..5595b6c19
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/pintolin.h
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+ Steve Brooks 6-July 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for Alcor.
+//
+// Alcor PCI interrupts are mapped to arbitrary interrupt numbers
+// in the table below. The values are a 1-1 map of the bit numbers
+// in the Alcor PCI interrupt register that are connected to PCI
+// devices. N.B.: there are two other interrupts in this register,
+// but they are not connected to I/O devices, so they're not
+// represented in the table.
+//
+// Limit init table to 14 entries, which is the
+// MAX_PCI_LOCAL_DEVICES_MIKASA.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 13 = PCI_AD[24].
+//
+//
+// N.B. - Have biased the bus interrupt vectors/levels for PCI to start
+// at 0x11 so they are disjoint from EISA levels
+//
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG AlcorPCIPinToLineTable[][4]=
+{
+
+//
+// Pin 1 Pin 2 Pin 3 Pin 4
+// ----- ----- ----- -----
+//
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15]
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16]
+ { 0x1e, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] Maverick Ethernet Controller
+ { 0x19, 0x1a, 0x1b, 0x1c }, // Virtual Slot 7 = PCI_AD[18] 64 bit Slot #0
+ { 0x21, 0x22, 0x23, 0x24 }, // Virtual Slot 8 = PCI_AD[19] 32 bit Slot #0
+ { 0x1d, 0x1e, 0x1f, 0x20 }, // Virtual Slot 9 = PCI_AD[20] 32 bit Slot #1
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] Eisa Bridge
+ { 0x11, 0x12, 0x13, 0x14 }, // Virtual Slot 11 = PCI_AD[22] 64 bit Slot #2
+ { 0x15, 0x16, 0x17, 0x18 }, // Virtual Slot 12 = PCI_AD[23] 64 bit Slot #1
+};
diff --git a/private/ntos/nthals/halxlt/alpha/vga.c b/private/ntos/nthals/halxlt/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halxlt/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halxlt/drivesup.c b/private/ntos/nthals/halxlt/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halxlt/drivesup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\drivesup.c"
diff --git a/private/ntos/nthals/halxlt/hal.rc b/private/ntos/nthals/halxlt/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halxlt/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halxlt/hal.src b/private/ntos/nthals/halxlt/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halxlt/hal.src
@@ -0,0 +1,7 @@
+//
+// This file simply includes the common sources from the current HAL
+// directory. When the structure is finally changed, the real file should
+// be in this directory.
+//
+
+#include "..\hal.src"
diff --git a/private/ntos/nthals/halxlt/makefile b/private/ntos/nthals/halxlt/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halxlt/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halxlt/makefile.inc b/private/ntos/nthals/halxlt/makefile.inc
new file mode 100644
index 000000000..31dc4c838
--- /dev/null
+++ b/private/ntos/nthals/halxlt/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: hal.src
+ rcpp -P -f hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halxl.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halxlt/sources b/private/ntos/nthals/halxlt/sources
new file mode 100644
index 000000000..94120dac7
--- /dev/null
+++ b/private/ntos/nthals/halxlt/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halxl
+TARGETPATH=\nt\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+
+#C_DEFINES=-DEV5 -DEISA_PLATFORM -DCIA_PASS1
+C_DEFINES=-DEV5 -DTAGGED_NVRAM
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ bushnd.c \
+ drivesup.c \
+ alpha\adjust.c \
+ alpha\allstart.c \
+ alpha\bios.c \
+ alpha\cache.c \
+ alpha\cia.c \
+ alpha\ciaaddr.c \
+ alpha\ciaerr.c \
+ alpha\ciaio.s \
+ alpha\ciamapio.c \
+ alpha\cmos8k.c \
+ alpha\devintr.s \
+ alpha\nvenv.c \
+ alpha\nvram.c \
+ alpha\ev5cache.c \
+ alpha\ev5int.c \
+ alpha\ev5mchk.c \
+ alpha\ev5mem.s \
+ alpha\ev5prof.c \
+ alpha\ev5ints.s \
+ alpha\fwreturn.c \
+ alpha\haldebug.c \
+ alpha\halpal.s \
+ alpha\haltsup.s \
+ alpha\idle.s \
+ alpha\info.c \
+ alpha\inithal.c \
+ alpha\intsup.s \
+ alpha\iousage.c \
+ alpha\memory.c \
+ alpha\pciesc.c \
+ alpha\pcisup.c \
+ alpha\pcrtc.c \
+ alpha\pcserial.c \
+ alpha\pcspeakr.c \
+ alpha\perfcntr.c \
+ alpha\vga.c \
+ alpha\alcorerr.c \
+ alpha\alinitnt.c \
+ alpha\alintsup.c \
+ alpha\alsysint.c \
+ alpha\busdata.c \
+ alpha\ebsgdma.c \
+ alpha\eisasup.c \
+ alpha\pcibus.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/inc/hali.h b/private/ntos/nthals/inc/hali.h
new file mode 100644
index 000000000..3a47da3ec
--- /dev/null
+++ b/private/ntos/nthals/inc/hali.h
@@ -0,0 +1,109 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ hali.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces for bus range support.
+
+Author:
+
+ David N. Cutler (davec) 28-Mar-95
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALI_
+#define _HALI_
+
+//
+// Define type of memory for bus range allocations.
+//
+
+#define SPRANGEPOOL NonPagedPool
+
+//
+// Define bus range function prototypes.
+//
+
+PSUPPORTED_RANGES
+HalpMergeRanges (
+ IN PSUPPORTED_RANGES Parent,
+ IN PSUPPORTED_RANGES Child
+ );
+
+VOID
+HalpMergeRangeList (
+ PSUPPORTED_RANGE NewList,
+ PSUPPORTED_RANGE Source1,
+ PSUPPORTED_RANGE Source2
+ );
+
+PSUPPORTED_RANGES
+HalpConsolidateRanges (
+ PSUPPORTED_RANGES Ranges
+ );
+
+PSUPPORTED_RANGES
+HalpAllocateNewRangeList (
+ VOID
+ );
+
+VOID
+HalpFreeRangeList (
+ PSUPPORTED_RANGES Ranges
+ );
+
+PSUPPORTED_RANGES
+HalpCopyRanges (
+ PSUPPORTED_RANGES Source
+ );
+
+VOID
+HalpAddRangeList (
+ IN OUT PSUPPORTED_RANGE DRange,
+ OUT PSUPPORTED_RANGE SRange
+ );
+
+VOID
+HalpAddRange (
+ PSUPPORTED_RANGE HRange,
+ ULONG AddressSpace,
+ LONGLONG SystemBase,
+ LONGLONG Base,
+ LONGLONG Limit
+ );
+
+VOID
+HalpRemoveRanges (
+ IN OUT PSUPPORTED_RANGES Minuend,
+ IN PSUPPORTED_RANGES Subtrahend
+ );
+
+VOID
+HalpRemoveRangeList (
+ IN OUT PSUPPORTED_RANGE Minuend,
+ IN PSUPPORTED_RANGE Subtrahend
+ );
+
+
+VOID
+HalpRemoveRange (
+ PSUPPORTED_RANGE HRange,
+ LONGLONG Base,
+ LONGLONG Limit
+ );
+
+VOID
+HalpDisplayAllBusRanges (
+ VOID
+ );
+
+#endif // _HALI_
diff --git a/private/ntos/nthals/rangesup.c b/private/ntos/nthals/rangesup.c
new file mode 100644
index 000000000..d39d7f94d
--- /dev/null
+++ b/private/ntos/nthals/rangesup.c
@@ -0,0 +1,1144 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+All rights reserved
+
+Module Name:
+
+ rangesup.c
+
+Abstract:
+
+ Supplies support function for dealing with SUPPORTED_RANGEs.
+
+Author:
+
+ Ken Reneris (kenr) March-27-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+*/
+
+#include "halp.h"
+
+#define STATIC
+
+STATIC ULONG
+HalpSortRanges (
+ IN PSUPPORTED_RANGE pRange1
+ );
+
+typedef struct tagNRParams {
+ PIO_RESOURCE_DESCRIPTOR InDesc;
+ PIO_RESOURCE_DESCRIPTOR OutDesc;
+ PSUPPORTED_RANGE CurrentPosition;
+ LONGLONG Base;
+ LONGLONG Limit;
+ UCHAR DescOpt;
+ BOOLEAN AnotherListPending;
+} NRPARAMS, *PNRPARAMS;
+
+STATIC PIO_RESOURCE_DESCRIPTOR
+HalpGetNextSupportedRange (
+ IN LONGLONG MinimumAddress,
+ IN LONGLONG MaximumAddress,
+ IN OUT PNRPARAMS PNRParams
+ );
+
+//
+// These following functions are usable at to initialize
+// the supported_ranges information for a bus handler.
+// HalpMergeRanges - merges two bus supported ranges
+// HalpMergeRangeList - merges two single supported ranges lists
+// HalpCopyRanges - copy a bus supported ranges to a new supported ranges structure
+// HalpAddRangeList - adds a supported range list to another
+// HalpAddRange - adds a single range to a supported range list
+// HalpRemoveRanges - removes all ranges from one buses supported ranges from another
+// HalpRemoveRangeList - removes all ranges in one supported range list from another
+// HalpRemoveRange - removes a single range from a supported range list
+// HalpAllocateNewRangeList - allocates a new, "blank" bus supported ranges structure
+// HalpFreeRangeList - frees an entire bus supported ranges
+//
+// HalpConsolidateRanges - cleans up a supported ranges structure to be ready for usage
+//
+//
+// These functions are used to intersect a buses supported ranges
+// to an IO_RESOURCE_REQUIREMENTS_LIST:
+// HaliAdjustResourceListRange
+//
+// These functions are used internal to this module:
+// HalpSortRanges
+// HalpGetNextSupportedRange
+//
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpMergeRanges)
+#pragma alloc_text(INIT,HalpMergeRangeList)
+#pragma alloc_text(INIT,HalpCopyRanges)
+#pragma alloc_text(INIT,HalpAddRangeList)
+#pragma alloc_text(INIT,HalpAddRange)
+#pragma alloc_text(INIT,HalpRemoveRanges)
+#pragma alloc_text(INIT,HalpRemoveRangeList)
+#pragma alloc_text(INIT,HalpRemoveRange)
+#pragma alloc_text(INIT,HalpConsolidateRanges)
+#pragma alloc_text(PAGE,HalpAllocateNewRangeList)
+#pragma alloc_text(PAGE,HalpFreeRangeList)
+#pragma alloc_text(PAGE,HaliAdjustResourceListRange)
+#pragma alloc_text(PAGE,HalpSortRanges)
+#pragma alloc_text(PAGE,HalpGetNextSupportedRange)
+#endif
+
+struct {
+ ULONG Offset;
+} HalpRangeList[] = {
+ FIELD_OFFSET (SUPPORTED_RANGES, IO),
+ FIELD_OFFSET (SUPPORTED_RANGES, Memory),
+ FIELD_OFFSET (SUPPORTED_RANGES, PrefetchMemory),
+ FIELD_OFFSET (SUPPORTED_RANGES, Dma),
+ 0,
+ };
+
+#define RANGE_LIST(a,i) ((PSUPPORTED_RANGE) ((PUCHAR) a + HalpRangeList[i].Offset))
+
+
+PSUPPORTED_RANGES
+HalpMergeRanges (
+ IN PSUPPORTED_RANGES Parent,
+ IN PSUPPORTED_RANGES Child
+ )
+/*++
+Routine Description:
+
+ This function produces a NewList which is a subset of all overlapping
+ ranges in Parent and Child for all range lists.
+
+ The resulting SystemBaseAddresses and SystemAddressSpaces are taken
+ from the Child supported ranges.
+
+ Note: Resulting list needs consolidated
+
+--*/
+{
+ PSUPPORTED_RANGES NewList;
+ PSUPPORTED_RANGES List1;
+
+ NewList = HalpAllocateNewRangeList();
+
+ HalpMergeRangeList (&NewList->IO, &Parent->IO, &Child->IO);
+ HalpMergeRangeList (&NewList->Dma, &Parent->Dma, &Child->Dma);
+ HalpMergeRangeList (&NewList->Memory, &Parent->Memory, &Child->Memory);
+
+ List1 = HalpAllocateNewRangeList();
+ HalpAddRangeList (&List1->Memory, &Parent->Memory);
+ HalpAddRangeList (&List1->Memory, &Parent->PrefetchMemory);
+ HalpMergeRangeList (&NewList->PrefetchMemory, &List1->Memory, &Child->PrefetchMemory);
+ HalpFreeRangeList (List1);
+
+ return NewList;
+}
+
+
+VOID
+HalpMergeRangeList (
+ OUT PSUPPORTED_RANGE NewList,
+ IN PSUPPORTED_RANGE Parent,
+ IN PSUPPORTED_RANGE Child
+ )
+/*++
+Routine Description:
+
+ Completes NewList to be a subset of all overlapping
+ ranges in the Parent and Child list.
+
+ The resulting SystemBaseAddresses and SystemAddressSpaces are
+ taken from the Child supported ranges.
+
+ Note: Resulting list needs consolidated
+
+--*/
+{
+ BOOLEAN HeadCompleted;
+ PSUPPORTED_RANGE List1, List2;
+ LONGLONG Base, Limit;
+
+ HeadCompleted = FALSE;
+
+ for (List1 = Parent; List1; List1 = List1->Next) {
+ for (List2 = Child; List2; List2 = List2->Next) {
+
+ Base = List1->Base;
+ Limit = List1->Limit;
+
+ //
+ // Clip to range supported by List2
+ //
+
+ if (Base < List2->Base) {
+ Base = List2->Base;
+ }
+
+ if (Limit > List2->Limit) {
+ Limit = List2->Limit;
+ }
+
+ //
+ // If valid range, add it
+ //
+
+ if (Base <= Limit) {
+ if (HeadCompleted) {
+ NewList->Next = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGE));
+ RtlZeroMemory (NewList->Next, sizeof (SUPPORTED_RANGE));
+ NewList = NewList->Next;
+ NewList->Next = NULL;
+ }
+
+ HeadCompleted = TRUE;
+ NewList->Base = Base;
+ NewList->Limit = Limit;
+ NewList->SystemBase = List2->SystemBase;
+ NewList->SystemAddressSpace = List2->SystemAddressSpace;
+ }
+ }
+ }
+}
+
+PSUPPORTED_RANGES
+HalpCopyRanges (
+ PSUPPORTED_RANGES Source
+ )
+/*++
+Routine Description:
+
+ Builds a copy of the Source list to the destionation list.
+ Note that an invalid entry lands at the begining of the copy, but
+ that's OK - it will be pulled out at colsolidation time.
+
+ Note: Resulting list needs consolidated
+
+--*/
+{
+ PSUPPORTED_RANGES Dest;
+ ULONG i;
+
+ Dest = HalpAllocateNewRangeList ();
+
+ for (i=0; HalpRangeList[i].Offset; i++) {
+ HalpAddRangeList (RANGE_LIST(Dest, i), RANGE_LIST(Source, i));
+ }
+
+ return Dest;
+}
+
+VOID
+HalpAddRangeList (
+ IN OUT PSUPPORTED_RANGE DRange,
+ OUT PSUPPORTED_RANGE SRange
+ )
+/*++
+Routine Description:
+
+ Adds ranges from SRange to DRange.
+
+--*/
+{
+ while (SRange) {
+ HalpAddRange (
+ DRange,
+ SRange->SystemAddressSpace,
+ SRange->SystemBase,
+ SRange->Base,
+ SRange->Limit
+ );
+
+ SRange = SRange->Next;
+ }
+}
+
+
+VOID
+HalpAddRange (
+ PSUPPORTED_RANGE HRange,
+ ULONG AddressSpace,
+ LONGLONG SystemBase,
+ LONGLONG Base,
+ LONGLONG Limit
+ )
+/*++
+Routine Description:
+
+ Adds a range to the supported list. Here we just add the range, if it's
+ a duplicate it will be removed later at consolidation time.
+
+--*/
+{
+ PSUPPORTED_RANGE Range;
+
+ Range = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGE));
+ RtlZeroMemory (Range, sizeof (SUPPORTED_RANGE));
+ Range->Next = HRange->Next;
+ HRange->Next = Range;
+
+ Range->Base = Base;
+ Range->Limit = Limit;
+ Range->SystemBase = SystemBase;
+ Range->SystemAddressSpace = AddressSpace;
+}
+
+VOID
+HalpRemoveRanges (
+ IN OUT PSUPPORTED_RANGES Minuend,
+ IN PSUPPORTED_RANGES Subtrahend
+ )
+/*++
+Routine Description:
+
+ Returns a list where all ranges from Subtrahend are removed from Minuend.
+
+ Note: Resulting list needs consolidated
+
+--*/
+{
+
+ HalpRemoveRangeList (&Minuend->IO, &Subtrahend->IO);
+ HalpRemoveRangeList (&Minuend->Dma, &Subtrahend->Dma);
+ HalpRemoveRangeList (&Minuend->Memory, &Subtrahend->Memory);
+ HalpRemoveRangeList (&Minuend->Memory, &Subtrahend->PrefetchMemory);
+ HalpRemoveRangeList (&Minuend->PrefetchMemory, &Subtrahend->PrefetchMemory);
+ HalpRemoveRangeList (&Minuend->PrefetchMemory, &Subtrahend->Memory);
+}
+
+VOID
+HalpRemoveRangeList (
+ IN OUT PSUPPORTED_RANGE Minuend,
+ IN PSUPPORTED_RANGE Subtrahend
+ )
+/*++
+Routine Description:
+
+ Removes all ranges from Subtrahend from Minuend
+
+ ranges in Source1 and Source1 list
+
+--*/
+{
+ while (Subtrahend) {
+
+ HalpRemoveRange (
+ Minuend,
+ Subtrahend->Base,
+ Subtrahend->Limit
+ );
+
+ Subtrahend = Subtrahend->Next;
+ }
+}
+
+
+VOID
+HalpRemoveRange (
+ PSUPPORTED_RANGE HRange,
+ LONGLONG Base,
+ LONGLONG Limit
+ )
+/*++
+Routine Description:
+
+ Removes the range Base-Limit from the the HRange list
+
+ Note: The returned list needs consolidated, as some entries
+ may be turned into "null ranges".
+
+--*/
+{
+ PSUPPORTED_RANGE Range;
+
+ //
+ // If range isn't a range at all, then nothing to remove
+ //
+
+ if (Limit < Base) {
+ return ;
+ }
+
+
+ //
+ // Clip any area not to include this range
+ //
+
+ for (Range = HRange; Range; Range = Range->Next) {
+
+ if (Range->Limit < Range->Base) {
+ continue;
+ }
+
+ if (Range->Base < Base) {
+ if (Range->Limit >= Base && Range->Limit <= Limit) {
+ // truncate
+ Range->Limit = Base - 1;
+ }
+
+ if (Range->Limit > Limit) {
+
+ //
+ // Target area is contained totally within this area.
+ // Split into two ranges
+ //
+
+ HalpAddRange (
+ HRange,
+ Range->SystemAddressSpace,
+ Range->SystemBase,
+ Limit + 1,
+ Range->Limit
+ );
+
+ Range->Limit = Base - 1;
+
+ }
+ } else {
+ // Range->Base >= Base
+ if (Range->Base <= Limit) {
+ if (Range->Limit <= Limit) {
+ //
+ // This range is totally within the target area. Remove it.
+ // (make it invalid - it will get remove when colsolidated)
+ //
+
+ Range->Base = 1;
+ Range->Limit = 0;
+
+ } else {
+ // Bump begining
+ Range->Base = Limit + 1;
+ }
+ }
+ }
+ }
+}
+
+PSUPPORTED_RANGES
+HalpConsolidateRanges (
+ IN OUT PSUPPORTED_RANGES Ranges
+ )
+/*++
+Routine Description:
+
+ Cleans the Range list. Consolidates overlapping ranges, removes
+ ranges which don't have any size, etc...
+
+ The returned Ranges list is a clean as possible, and is now ready
+ to be used.
+
+--*/
+{
+ PSUPPORTED_RANGE RangeList, List1, List2;
+ LONGLONG Base, Limit, SystemBase;
+ ULONG i, AddressSpace;
+ LONGLONG l;
+
+ ASSERT (Ranges != NULL);
+
+ for (i=0; HalpRangeList[i].Offset; i++) {
+ RangeList = RANGE_LIST(Ranges, i);
+
+ //
+ // Sort the list by base address
+ //
+
+ for (List1 = RangeList; List1; List1 = List1->Next) {
+ for (List2 = List1->Next; List2; List2 = List2->Next) {
+ if (List2->Base < List1->Base) {
+ Base = List1->Base;
+ Limit = List1->Limit;
+ SystemBase = List1->SystemBase;
+ AddressSpace = List1->SystemAddressSpace;
+
+ List1->Base = List2->Base;
+ List1->Limit = List2->Limit;
+ List1->SystemBase = List2->SystemBase;
+ List1->SystemAddressSpace = List2->SystemAddressSpace;
+
+ List2->Base = Base;
+ List2->Limit = Limit;
+ List2->SystemBase = SystemBase;
+ List2->SystemAddressSpace = AddressSpace;
+ }
+ }
+ }
+
+ //
+ // Check for adjacent/overlapping ranges and combined them
+ //
+
+ List1 = RangeList;
+ while (List1 && List1->Next) {
+
+ if (List1->Limit < List1->Base) {
+ //
+ // This range's limit is less then it's base. This
+ // entry doesn't reprent anything uasable, remove it.
+ //
+
+ List2 = List1->Next;
+
+ List1->Next = List2->Next;
+ List1->Base = List2->Base;
+ List1->Limit = List2->Limit;
+ List1->SystemBase = List2->SystemBase;
+ List1->SystemAddressSpace = List2->SystemAddressSpace;
+
+ ExFreePool (List2);
+ continue;
+ }
+
+ l = List1->Limit + 1;
+ if (l > List1->Limit && l >= List1->Next->Base) {
+
+ //
+ // Overlapping. Combine them.
+ //
+
+ List2 = List1->Next;
+ List1->Next = List2->Next;
+ if (List2->Limit > List1->Limit) {
+ List1->Limit = List2->Limit;
+ ASSERT (List1->SystemBase == List2->SystemBase);
+ ASSERT (List1->SystemAddressSpace == List2->SystemAddressSpace);
+ }
+
+ ExFreePool (List2);
+ continue ;
+ }
+
+ List1 = List1->Next;
+ }
+
+ //
+ // If the last range is invalid, and it's not the only
+ // thing in the list - remove it
+ //
+
+ if (List1 != RangeList && List1->Limit < List1->Base) {
+ for (List2=RangeList; List2->Next != List1; List2 = List2->Next) ;
+ List2->Next = NULL;
+ ExFreePool (List1);
+ }
+ }
+
+ return Ranges;
+}
+
+
+PSUPPORTED_RANGES
+HalpAllocateNewRangeList (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocates a range list
+
+--*/
+{
+ PSUPPORTED_RANGES RangeList;
+ ULONG i;
+
+ RangeList = (PSUPPORTED_RANGES) ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (RangeList, sizeof (SUPPORTED_RANGES));
+ RangeList->Version = BUS_SUPPORTED_RANGE_VERSION;
+
+ for (i=0; HalpRangeList[i].Offset; i++) {
+ // Limit set to zero, set initial base to 1
+ RANGE_LIST(RangeList, i)->Base = 1;
+ }
+ return RangeList;
+}
+
+
+VOID
+HalpFreeRangeList (
+ PSUPPORTED_RANGES Ranges
+ )
+/*++
+
+Routine Description:
+
+ Frees a range list which was allocated via HalpAllocateNewRangeList, and
+ extended / modified via the generic support functions.
+
+
+--*/
+{
+ PSUPPORTED_RANGE Entry, NextEntry;
+ ULONG i;
+
+ for (i=0; HalpRangeList[i].Offset; i++) {
+ Entry = RANGE_LIST(Ranges, i)->Next;
+
+ while (Entry) {
+ NextEntry = Entry->Next;
+ ExFreePool (Entry);
+ Entry = NextEntry;
+ }
+ }
+
+ ExFreePool (Ranges);
+}
+
+
+#if DBG
+STATIC VOID
+HalpDisplayAddressRange (
+ PSUPPORTED_RANGE Address,
+ PUCHAR String
+ )
+/*++
+
+Routine Description:
+
+ Debugging code. Used only by HalpDisplayAllBusRanges
+
+--*/
+{
+ ULONG i;
+
+ i = 0;
+ while (Address) {
+ if (i == 0) {
+ DbgPrint (String);
+ i = 3;
+ }
+
+ i -= 1;
+ DbgPrint (" %x:%08x - %x:%08x ",
+ (ULONG) (Address->Base >> 32),
+ (ULONG) (Address->Base),
+ (ULONG) (Address->Limit >> 32),
+ (ULONG) (Address->Limit)
+ );
+
+ Address = Address->Next;
+ }
+}
+
+VOID
+HalpDisplayAllBusRanges (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Debugging code. Displays the current supported range information
+ for all the registered buses in the system.
+
+--*/
+{
+ PSUPPORTED_RANGES Addresses;
+ PBUS_HANDLER Bus;
+ PUCHAR p;
+ ULONG i, j;
+
+ DbgPrint ("\nHAL - dumping all supported bus ranges");
+
+ for (i=0; i < MaximumInterfaceType; i++) {
+ for (j=0; Bus = HaliHandlerForBus (i, j); j++) {
+ Addresses = Bus->BusAddresses;
+ if (Addresses) {
+ p = NULL;
+ switch (Bus->InterfaceType) {
+ case Internal: p = "Internal"; break;
+ case Isa: p = "Isa"; break;
+ case Eisa: p = "Eisa"; break;
+ case PCIBus: p = "PCI"; break;
+ }
+ if (p) {
+ DbgPrint ("\n%s %d", p, Bus->BusNumber);
+ } else {
+ DbgPrint ("\nBus-%d %d", Bus->InterfaceType, Bus->BusNumber);
+ }
+ HalpDisplayAddressRange (&Addresses->IO, "\n IO......:");
+ HalpDisplayAddressRange (&Addresses->Memory, "\n Memory..:");
+ HalpDisplayAddressRange (&Addresses->PrefetchMemory,"\n PFMemory:");
+ HalpDisplayAddressRange (&Addresses->Dma, "\n Dma.....:");
+ DbgPrint ("\n");
+ }
+ }
+ }
+}
+#endif
+
+NTSTATUS
+HaliAdjustResourceListRange (
+ IN PSUPPORTED_RANGES SRanges,
+ IN PSUPPORTED_RANGE InterruptRange,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ This functions takes an IO_RESOURCE_REQUIREMENT_LIST and
+ adjusts it such that all ranges in the list fit in the
+ ranges specified by SRanges & InterruptRange.
+
+ This function is used by some HALs to clip the possible
+ settings to be contained on what the particular bus supports
+ in reponse to a HalAdjustResourceList call.
+
+Arguments:
+
+ SRanges - Valid IO, Memory, Prefetch Memory, and DMA ranges.
+ InterruptRange - Valid InterruptRanges
+
+ pResourceList - The resource requirements list which needs to
+ be adjusted to only contain the ranges as
+ described by SRanges & InterruptRange.
+
+Return Value:
+
+ STATUS_SUCCESS or an appropiate error return.
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList, OutCompleteList;
+ PIO_RESOURCE_LIST InResourceList, OutResourceList;
+ PIO_RESOURCE_DESCRIPTOR HeadOutDesc, SetDesc;
+ NRPARAMS Pos;
+ ULONG len, alt, cnt, i;
+ ULONG icnt;
+
+ //
+ // Sanity check
+ //
+
+ if (!SRanges || SRanges->Version != BUS_SUPPORTED_RANGE_VERSION) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // If SupportedRanges aren't sorted, sort them and get the
+ // number of ranges for each type
+ //
+
+ if (!SRanges->Sorted) {
+ SRanges->NoIO = HalpSortRanges (&SRanges->IO);
+ SRanges->NoMemory = HalpSortRanges (&SRanges->Memory);
+ SRanges->NoPrefetchMemory = HalpSortRanges (&SRanges->PrefetchMemory);
+ SRanges->NoDma = HalpSortRanges (&SRanges->Dma);
+ SRanges->Sorted = TRUE;
+ }
+
+ icnt = HalpSortRanges (InterruptRange);
+
+ InCompleteList = *pResourceList;
+ len = InCompleteList->ListSize;
+
+ //
+ // Scan input list - verify revision #'s, and increase len varible
+ // by amount output list may increase.
+ //
+
+ i = 0;
+ InResourceList = InCompleteList->List;
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+ if (InResourceList->Version != 1 || InResourceList->Revision < 1) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Pos.InDesc = InResourceList->Descriptors;
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+ switch (Pos.InDesc->Type) {
+ case CmResourceTypeInterrupt: i += icnt; break;
+ case CmResourceTypePort: i += SRanges->NoIO; break;
+ case CmResourceTypeDma: i += SRanges->NoDma; break;
+
+ case CmResourceTypeMemory:
+ i += SRanges->NoMemory;
+ if (Pos.InDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
+ i += SRanges->NoPrefetchMemory;
+ }
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // take one off for the original which is already accounted for in 'len'
+ i -= 1;
+
+ // Next descriptor
+ Pos.InDesc++;
+ }
+
+ // Next Resource List
+ InResourceList = (PIO_RESOURCE_LIST) Pos.InDesc;
+ }
+ len += i * sizeof (IO_RESOURCE_DESCRIPTOR);
+
+ //
+ // Allocate output list
+ //
+
+ OutCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST)
+ ExAllocatePool (PagedPool, len);
+
+ if (!OutCompleteList) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (OutCompleteList, len);
+
+ //
+ // Walk each ResourceList and build output structure
+ //
+
+ InResourceList = InCompleteList->List;
+ *OutCompleteList = *InCompleteList;
+ OutResourceList = OutCompleteList->List;
+
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+ OutResourceList->Version = 1;
+ OutResourceList->Revision = 1;
+
+ Pos.InDesc = InResourceList->Descriptors;
+ Pos.OutDesc = OutResourceList->Descriptors;
+ HeadOutDesc = Pos.OutDesc;
+
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+
+ //
+ // Limit desctiptor to be with the buses supported ranges
+ //
+
+ Pos.DescOpt = Pos.InDesc->Option;
+ Pos.AnotherListPending = FALSE;
+
+ switch (Pos.InDesc->Type) {
+ case CmResourceTypePort:
+
+ //
+ // Get supported IO ranges
+ //
+
+ Pos.CurrentPosition = &SRanges->IO;
+ do {
+ SetDesc = HalpGetNextSupportedRange (
+ Pos.InDesc->u.Port.MinimumAddress.QuadPart,
+ Pos.InDesc->u.Port.MaximumAddress.QuadPart,
+ &Pos
+ );
+
+ if (SetDesc) {
+ SetDesc->u.Port.MinimumAddress.QuadPart = Pos.Base;
+ SetDesc->u.Port.MaximumAddress.QuadPart = Pos.Limit;
+ }
+
+ } while (SetDesc) ;
+ break;
+
+ case CmResourceTypeInterrupt:
+ //
+ // Get supported Interrupt ranges
+ //
+
+ Pos.CurrentPosition = InterruptRange;
+ do {
+ SetDesc = HalpGetNextSupportedRange (
+ Pos.InDesc->u.Interrupt.MinimumVector,
+ Pos.InDesc->u.Interrupt.MaximumVector,
+ &Pos
+ );
+
+ if (SetDesc) {
+ SetDesc->u.Interrupt.MinimumVector = (ULONG) Pos.Base;
+ SetDesc->u.Interrupt.MaximumVector = (ULONG) Pos.Limit;
+ }
+ } while (SetDesc) ;
+ break;
+
+ case CmResourceTypeMemory:
+ //
+ // Get supported memory ranges
+ //
+
+ if (Pos.InDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
+
+ //
+ // This is a Prefetchable range.
+ // First add in any supported prefetchable ranges, then
+ // add in any regualer supported ranges
+ //
+
+ Pos.AnotherListPending = TRUE;
+ Pos.CurrentPosition = &SRanges->PrefetchMemory;
+
+ do {
+ SetDesc = HalpGetNextSupportedRange (
+ Pos.InDesc->u.Memory.MinimumAddress.QuadPart,
+ Pos.InDesc->u.Memory.MaximumAddress.QuadPart,
+ &Pos
+ );
+
+ if (SetDesc) {
+ SetDesc->u.Memory.MinimumAddress.QuadPart = Pos.Base;
+ SetDesc->u.Memory.MaximumAddress.QuadPart = Pos.Limit;
+ SetDesc->Option |= IO_RESOURCE_PREFERRED;
+ }
+ } while (SetDesc) ;
+
+ Pos.AnotherListPending = FALSE;
+ }
+
+ //
+ // Add in supported bus memory ranges
+ //
+
+ Pos.CurrentPosition = &SRanges->Memory;
+ do {
+ SetDesc = HalpGetNextSupportedRange (
+ Pos.InDesc->u.Memory.MinimumAddress.QuadPart,
+ Pos.InDesc->u.Memory.MaximumAddress.QuadPart,
+ &Pos
+ );
+ if (SetDesc) {
+ SetDesc->u.Memory.MinimumAddress.QuadPart = Pos.Base;
+ SetDesc->u.Memory.MaximumAddress.QuadPart = Pos.Limit;
+ }
+ } while (SetDesc);
+ break;
+
+ case CmResourceTypeDma:
+ //
+ // Get supported DMA ranges
+ //
+
+ Pos.CurrentPosition = &SRanges->Dma;
+ do {
+ SetDesc = HalpGetNextSupportedRange (
+ Pos.InDesc->u.Dma.MinimumChannel,
+ Pos.InDesc->u.Dma.MaximumChannel,
+ &Pos
+ );
+
+ if (SetDesc) {
+ SetDesc->u.Dma.MinimumChannel = (ULONG) Pos.Base;
+ SetDesc->u.Dma.MaximumChannel = (ULONG) Pos.Limit;
+ }
+ } while (SetDesc) ;
+ break;
+
+#if DBG
+ default:
+ DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
+ break;
+#endif
+ }
+
+ //
+ // Next descriptor
+ //
+
+ Pos.InDesc++;
+ }
+
+ OutResourceList->Count = Pos.OutDesc - HeadOutDesc;
+
+ //
+ // Next Resource List
+ //
+
+ InResourceList = (PIO_RESOURCE_LIST) Pos.InDesc;
+ OutResourceList = (PIO_RESOURCE_LIST) Pos.OutDesc;
+ }
+
+ //
+ // Free input list, and return output list
+ //
+
+ ExFreePool (InCompleteList);
+
+ OutCompleteList->ListSize = (ULONG) ((PUCHAR) OutResourceList - (PUCHAR) OutCompleteList);
+ *pResourceList = OutCompleteList;
+ return STATUS_SUCCESS;
+}
+
+
+STATIC PIO_RESOURCE_DESCRIPTOR
+HalpGetNextSupportedRange (
+ IN LONGLONG MinimumAddress,
+ IN LONGLONG MaximumAddress,
+ IN OUT PNRPARAMS Pos
+ )
+/*++
+
+Routine Description:
+
+ Support function for HaliAdjustResourceListRange.
+ Returns the next supported range in the area passed in.
+
+Arguments:
+
+ MinimumAddress
+ MaximumAddress - Min & Max address of a range which needs
+ to be clipped to match that of the supported
+ ranges of the current bus.
+
+ Pos - describes the current postion
+
+Return Value:
+
+ NULL is no more returned ranges
+
+ Otherwise, the IO_RESOURCE_DESCRIPTOR which needs to be set
+ with the matching range returned in Pos.
+
+--*/
+{
+ LONGLONG Base, Limit;
+
+ //
+ // Find next range which is supported
+ //
+
+ Base = MinimumAddress;
+ Limit = MaximumAddress;
+
+ while (Pos->CurrentPosition) {
+ Pos->Base = Base;
+ Pos->Limit = Limit;
+
+ //
+ // Clip to current range
+ //
+
+ if (Pos->Base < Pos->CurrentPosition->Base) {
+ Pos->Base = Pos->CurrentPosition->Base;
+ }
+
+ if (Pos->Limit > Pos->CurrentPosition->Limit) {
+ Pos->Limit = Pos->CurrentPosition->Limit;
+ }
+
+ //
+ // set position to next range
+ //
+
+ Pos->CurrentPosition = Pos->CurrentPosition->Next;
+
+ //
+ // If valid range, return it
+ //
+
+ if (Pos->Base <= Pos->Limit) {
+ *Pos->OutDesc = *Pos->InDesc;
+ Pos->OutDesc->Option = Pos->DescOpt;
+
+ //
+ // next descriptor (if any) is an alternative
+ // to the descriptor being returned now
+ //
+
+ Pos->OutDesc += 1;
+ Pos->DescOpt |= IO_RESOURCE_ALTERNATIVE;
+ return Pos->OutDesc - 1;
+ }
+ }
+
+
+ //
+ // There's no overlapping range. If this descriptor is
+ // not an alternative and this descriptor is not going to
+ // be processed by another range list, then return
+ // a descriptor which can't be satisified.
+ //
+
+ if (!(Pos->DescOpt & IO_RESOURCE_ALTERNATIVE) &&
+ Pos->AnotherListPending == FALSE) {
+#if DBG
+ DbgPrint ("HAL: returning impossible range\n");
+#endif
+ Pos->Base = MinimumAddress;
+ Pos->Limit = Pos->Base - 1;
+ if (Pos->Base == 0) { // if wrapped, fix it
+ Pos->Base = 1;
+ Pos->Limit = 0;
+ }
+
+ *Pos->OutDesc = *Pos->InDesc;
+ Pos->OutDesc->Option = Pos->DescOpt;
+
+ Pos->OutDesc += 1;
+ Pos->DescOpt |= IO_RESOURCE_ALTERNATIVE;
+ return Pos->OutDesc - 1;
+ }
+
+ //
+ // No range found (or no more ranges)
+ //
+
+ return NULL;
+}
+
+STATIC ULONG
+HalpSortRanges (
+ IN PSUPPORTED_RANGE RangeList
+ )
+/*++
+
+Routine Description:
+
+ Support function for HaliAdjustResourceListRange.
+ Sorts a supported range list into decending order.
+
+Arguments:
+
+ pRange - List to sort
+
+Return Value:
+
+--*/
+{
+ ULONG cnt;
+ LONGLONG hldBase, hldLimit;
+ PSUPPORTED_RANGE Range1, Range2;
+
+ //
+ // Sort it
+ //
+
+ for (Range1 = RangeList; Range1; Range1 = Range1->Next) {
+ for (Range2 = Range1->Next; Range2; Range2 = Range2->Next) {
+
+ if (Range2->Base > Range1->Base) {
+ hldBase = Range1->Base;
+ hldLimit = Range1->Limit;
+
+ Range1->Base = Range2->Base;
+ Range1->Limit = Range2->Limit;
+
+ Range2->Base = hldBase;
+ Range2->Limit = hldLimit;
+ }
+ }
+ }
+
+ //
+ // Count the number of ranges
+ //
+
+ cnt = 0;
+ for (Range1 = RangeList; Range1; Range1 = Range1->Next) {
+ cnt += 1;
+ }
+
+ return cnt;
+}
diff --git a/private/ntos/nthals/x86new/addops.c b/private/ntos/nthals/x86new/addops.c
new file mode 100644
index 000000000..d5d4f3ec8
--- /dev/null
+++ b/private/ntos/nthals/x86new/addops.c
@@ -0,0 +1,603 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ addops.c
+
+Abstract:
+
+ This module implements the code to emulate the add, sub, adc, sbb,
+ inc, dec, and neg opcodes.
+
+Author:
+
+ David N. Cutler (davec) 2-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+XmAddOperands (
+ IN PRXM_CONTEXT P,
+ IN ULONG Carry
+ );
+
+VOID
+XmSubOperands (
+ IN PRXM_CONTEXT P,
+ IN ULONG Borrow
+ );
+
+VOID
+XmAddOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an add opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Add operands and store result.
+ //
+
+ XmAddOperands(P, 0);
+ return;
+}
+
+VOID
+XmAdcOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an add with carry opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Add operands with carry and store result.
+ //
+
+ XmAddOperands(P, P->Eflags.CF);
+ return;
+}
+
+VOID
+XmSbbOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a subtract with borrow opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Source;
+
+ //
+ // Subtract operands with borrow and store result.
+ //
+
+ XmSubOperands(P, P->Eflags.CF);
+ return;
+}
+
+VOID
+XmSubOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a subtract opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Subtract operands and store result.
+ //
+
+ XmSubOperands(P, 0);
+ return;
+}
+
+VOID
+XmCmpOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cmp opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Subtract operands to perform comparison operation.
+ //
+
+ XmSubOperands(P, 0);
+ return;
+}
+
+VOID
+XmCmpxchgOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cmpxchg opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Accumulator;
+ ULONG Destination;
+
+ //
+ // Compare the destination with the accumulator. If the destination
+ // operand is equal to the accumulator, then set ZF and store the
+ // source operand value in the destination opperand. Otherwise, clear
+ // ZF and store the destination operand in the accumlator.
+ //
+
+ Destination = P->DstValue.Long;
+ if (P->DataType == BYTE_DATA) {
+ Accumulator = P->Gpr[AL].Xl;
+
+ } else if (P->DataType == LONG_DATA) {
+ Accumulator = P->Gpr[EAX].Exx;
+
+ } else {
+ Accumulator = P->Gpr[AX].Xx;
+ }
+
+ if (Destination == Accumulator) {
+ P->Eflags.ZF = 1;
+ XmStoreResult(P, P->SrcValue.Long);
+
+ } else {
+ P->Eflags.ZF = 0;
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
+ XmStoreResult(P, P->DstValue.Long);
+ }
+
+ //
+ // Subtract operands to perform comparison operation.
+ //
+
+ P->SrcValue.Long = P->DstValue.Long;
+ P->DstValue.Long = Accumulator;
+ XmSubOperands(P, 0);
+ return;
+}
+
+VOID
+XmDecOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a decrement opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Subtract operands and store result.
+ //
+ //
+
+ P->SrcValue.Long = 1;
+ XmSubOperands(P, 0);
+ return;
+}
+
+VOID
+XmIncOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an increment opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Add operands and store result.
+ //
+
+ P->SrcValue.Long = 1;
+ XmAddOperands(P, 0);
+ return;
+}
+
+VOID
+XmNegOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a neg opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Subtract operand from zero and store result.
+ //
+
+ P->SrcValue.Long = P->DstValue.Long;
+ P->DstValue.Long = 0;
+ XmSubOperands(P, 0);
+ return;
+}
+
+VOID
+XmXaddOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an xadd opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Destination;
+
+ //
+ // Exchange add operands and store result.
+ //
+
+ Destination = P->DstValue.Long;
+ XmAddOperands(P, 0);
+ P->DstLong = P->SrcLong;
+ XmStoreResult(P, Destination);
+ return;
+}
+
+VOID
+XmAddOperands (
+ IN PRXM_CONTEXT P,
+ IN ULONG Carry
+ )
+
+/*++
+
+Routine Description:
+
+ This function adds two operands and computes the resulting condition
+ codes.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+ Carry - Supplies the carry value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CarryFlag;
+ ULONG Shift;
+ union {
+ UCHAR ResultByte;
+ ULONG ResultLong;
+ USHORT ResultWord;
+ } u;
+
+ u.ResultLong = 0;
+ if (P->DataType == BYTE_DATA) {
+ u.ResultByte = P->SrcValue.Byte + (UCHAR)Carry;
+ CarryFlag = u.ResultByte < (UCHAR)Carry;
+ u.ResultByte += P->DstValue.Byte;
+ CarryFlag |= (u.ResultByte < P->DstValue.Byte);
+ Shift = 7;
+
+ } else if (P->DataType == LONG_DATA) {
+ u.ResultLong = P->SrcValue.Long + Carry;
+ CarryFlag = (u.ResultLong < Carry);
+ u.ResultLong += P->DstValue.Long;
+ CarryFlag |= (u.ResultLong < P->DstValue.Long);
+ Shift = 31;
+
+ } else {
+ u.ResultWord = P->SrcValue.Word + (USHORT)Carry;
+ CarryFlag = (u.ResultWord < (USHORT)Carry);
+ u.ResultWord += P->DstValue.Word;
+ CarryFlag |= (u.ResultWord < P->DstValue.Word);
+ Shift = 15;
+ }
+
+ //
+ // Store the result.
+ //
+
+ XmStoreResult(P, u.ResultLong);
+
+ //
+ // If the function is not an increment, then store the carry flag.
+ //
+
+ if (P->FunctionIndex != X86_INC_OP) {
+ P->Eflags.CF = CarryFlag;
+ }
+
+ //
+ // Compute and store the parity and auxiliary carry flags.
+ //
+
+ P->Eflags.PF = XmComputeParity(u.ResultLong);
+ P->Eflags.AF = ((P->DstValue.Byte & 0xf) +
+ (P->SrcValue.Long & 0xf) + Carry) >> 4;
+
+ //
+ // Compute and store the zero and sign flags.
+ //
+
+ P->Eflags.ZF = (u.ResultLong == 0);
+ P->Eflags.SF = u.ResultLong >> Shift;
+
+ //
+ // The overflow flag is computed as the carry into the sign bit
+ // compared with the carry out of the sign bit.
+ //
+
+ P->Eflags.OF = (((P->SrcValue.Long ^ P->DstValue.Long) ^
+ u.ResultLong) >> Shift) ^ CarryFlag;
+
+ return;
+}
+
+VOID
+XmSubOperands (
+ IN PRXM_CONTEXT P,
+ IN ULONG Borrow
+ )
+
+/*++
+
+Routine Description:
+
+ This function adds to operands and computes the resulting condition
+ codes.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+ Borrow - Supplies the boorow value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CarryFlag;
+ ULONG Shift;
+ union {
+ UCHAR ResultByte;
+ ULONG ResultLong;
+ USHORT ResultWord;
+ } u;
+
+ u.ResultLong = 0;
+ if (P->DataType == BYTE_DATA) {
+ CarryFlag = (P->DstValue.Byte < (UCHAR)Borrow);
+ u.ResultByte = P->DstValue.Byte - (UCHAR)Borrow;
+ CarryFlag |= (u.ResultByte < P->SrcValue.Byte);
+ u.ResultByte -= P->SrcValue.Byte;
+ Shift = 7;
+
+ } else if (P->DataType == LONG_DATA) {
+ CarryFlag = (P->DstValue.Long < Borrow);
+ u.ResultLong = P->DstValue.Long - Borrow;
+ CarryFlag |= (u.ResultLong < P->SrcValue.Long);
+ u.ResultLong -= P->SrcValue.Long;
+ Shift = 31;
+
+ } else {
+ CarryFlag = (P->DstValue.Word < (USHORT)Borrow);
+ u.ResultWord = P->DstValue.Word - (USHORT)Borrow;
+ CarryFlag |= (u.ResultWord < P->SrcValue.Word);
+ u.ResultWord -= P->SrcValue.Word;
+ Shift = 15;
+ }
+
+ //
+ // If the fucntion is not a compare or a compare and swap, then store
+ // result.
+ //
+
+ if ((P->FunctionIndex != X86_CMP_OP) && (P->FunctionIndex != X86_CMPXCHG_OP)) {
+ XmStoreResult(P, u.ResultLong);
+ }
+
+ //
+ // If the function is not a decrement, then store the carry flag.
+ //
+
+ if (P->FunctionIndex != X86_DEC_OP) {
+ P->Eflags.CF = CarryFlag;
+ }
+
+ //
+ // Compute and store the parity and auxiliary carry flags.
+ //
+
+ P->Eflags.PF = XmComputeParity(u.ResultLong);
+ P->Eflags.AF = ((P->DstValue.Byte & 0xf) -
+ (P->SrcValue.Byte & 0xf) - Borrow) >> 4;
+
+ //
+ // If the function is not a compare and swap, then compute the zero flag.
+ //
+
+ if (P->FunctionIndex != X86_CMPXCHG_OP) {
+ P->Eflags.ZF = (u.ResultLong == 0);
+ }
+
+ //
+ // Compute and store the sign flag.
+ //
+
+ P->Eflags.SF = u.ResultLong >> Shift;
+
+ //
+ // The overflow flag is computed as the borrow from the sign bit
+ // compared with the borrow into the sign bit.
+ //
+
+ P->Eflags.OF = (((P->SrcValue.Long ^ P->DstValue.Long) ^ u.ResultLong) >> Shift) ^ CarryFlag;
+ return;
+}
diff --git a/private/ntos/nthals/x86new/asciiops.c b/private/ntos/nthals/x86new/asciiops.c
new file mode 100644
index 000000000..9e4514de5
--- /dev/null
+++ b/private/ntos/nthals/x86new/asciiops.c
@@ -0,0 +1,288 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ asciiops.c
+
+Abstract:
+
+ This module implements the code to emulate the ASCII opcodes.
+
+Author:
+
+ David N. Cutler (davec) 12-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmAaaOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an aaa opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+
+ //
+ // If AL if greater than 9 or AF is set, then adjust ASCII result.
+ //
+
+ if (((P->Gpr[AX].Xl & 0xf) > 9) || (P->Eflags.AF != 0)) {
+ Carry = (P->Gpr[AX].Xl > 0xf9);
+ P->Gpr[AX].Xl = (P->Gpr[AX].Xl + 6) & 0xf;
+ P->Gpr[AX].Xh += (UCHAR)(1 + Carry);
+ P->Eflags.CF = 1;
+ P->Eflags.AF = 1;
+
+ } else {
+ P->Gpr[AX].Xl &= 0xf;
+ P->Eflags.CF = 0;
+ P->Eflags.AF = 0;
+ }
+
+ return;
+}
+
+VOID
+XmAadOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an aad opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Pack AH and AL into AX before division by scaling AH by 10 and
+ // adding AL.
+ //
+
+ P->Gpr[AX].Xl = (P->Gpr[AX].Xh * P->SrcValue.Byte) + P->Gpr[AX].Xl;
+ P->Gpr[AX].Xh = 0;
+ P->Eflags.SF = (P->Gpr[AX].Xx >> 15) & 0x1;
+ P->Eflags.ZF = (P->Gpr[AX].Xx == 0);
+ P->Eflags.PF = XmComputeParity(P->Gpr[AX].Xx);
+ return;
+}
+
+VOID
+XmAamOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an aam opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Unpack AL into AL and AH after multiplication by dividing by 10
+ // and storing the quotient in AH and the remainder in AL.
+ //
+
+ P->Gpr[AX].Xh = P->Gpr[AX].Xl / P->SrcValue.Byte;
+ P->Gpr[AX].Xl = P->Gpr[AX].Xl % P->SrcValue.Byte;
+ P->Eflags.SF = (P->Gpr[AX].Xx >> 15) & 0x1;
+ P->Eflags.ZF = (P->Gpr[AX].Xx == 0);
+ P->Eflags.PF = XmComputeParity(P->Gpr[AX].Xx);
+ return;
+}
+
+VOID
+XmAasOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an aaa opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Borrow;
+
+ //
+ // If AL if greater than 9 or AF is set, then adjust ASCII result.
+ //
+
+ if (((P->Gpr[AX].Xl & 0xf) > 9) || (P->Eflags.AF != 0)) {
+ Borrow = (P->Gpr[AX].Xl < 0x6);
+ P->Gpr[AX].Xl = (P->Gpr[AX].Xl - 6) & 0xf;
+ P->Gpr[AX].Xh -= (UCHAR)(1 + Borrow);
+ P->Eflags.CF = 1;
+ P->Eflags.AF = 1;
+
+ } else {
+ P->Gpr[AX].Xl &= 0xf;
+ P->Eflags.CF = 0;
+ P->Eflags.AF = 0;
+ }
+
+ return;
+}
+
+VOID
+XmDaaOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a daa opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If AL if greater than 9 or AF is set, then adjust ASCII result.
+ //
+
+ if (((P->Gpr[AX].Xl & 0xf) > 0x9) || (P->Eflags.AF != 0)) {
+ P->Gpr[AX].Xl = P->Gpr[AX].Xl + 6;
+ P->Eflags.AF = 1;
+
+ } else {
+ P->Eflags.AF = 0;
+ }
+
+ //
+ // If AL is greater than 9 or CF is set, then adjust ASCII result.
+ //
+
+ if ((P->Gpr[AX].Xl > 9) || (P->Eflags.CF != 0)) {
+ P->Gpr[AX].Xl = P->Gpr[AX].Xl + 0x60;
+ P->Eflags.CF = 1;
+
+ } else {
+ P->Eflags.CF = 0;
+ }
+
+ return;
+}
+
+VOID
+XmDasOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a daa opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If AL if greater than 9 or AF is set, then adjust ASCII result.
+ //
+
+ if (((P->Gpr[AX].Xl & 0xf) > 0x9) || (P->Eflags.AF != 0)) {
+ P->Gpr[AX].Xl = P->Gpr[AX].Xl - 6;
+ P->Eflags.AF = 1;
+
+ } else {
+ P->Eflags.AF = 0;
+ }
+
+ //
+ // If AL is greater than 9 or CF is set, then adjust ASCII result.
+ //
+
+ if ((P->Gpr[AX].Xl > 9) || (P->Eflags.CF != 0)) {
+ P->Gpr[AX].Xl = P->Gpr[AX].Xl - 0x60;
+ P->Eflags.CF = 1;
+
+ } else {
+ P->Eflags.CF = 0;
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/x86new/bitops.c b/private/ntos/nthals/x86new/bitops.c
new file mode 100644
index 000000000..caf36f3d2
--- /dev/null
+++ b/private/ntos/nthals/x86new/bitops.c
@@ -0,0 +1,256 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ bitops.c
+
+Abstract:
+
+ This module implements the code to emulate the bit opcodes.
+
+Author:
+
+ David N. Cutler (davec) 12-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmBsfOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an bsf opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Result;
+ ULONG Source;
+
+ //
+ // If the source operand is zero, then set ZF and set the destination
+ // to zero, Otherwise, find the first bit set scanning from right to
+ // left.
+ //
+
+ Result = 0;
+ Source = P->SrcValue.Long;
+ P->Eflags.ZF = 1;
+ while (Source != 0) {
+ if ((Source & 1) != 0) {
+ P->Eflags.ZF = 0;
+ break;
+ }
+
+ Result += 1;
+ Source >>= 1;
+ };
+
+ XmStoreResult(P, Result);
+ return;
+}
+
+VOID
+XmBsrOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an bsr opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Result;
+ ULONG Source;
+
+ //
+ // If the source operand is zero, then set ZF and set the destination
+ // to zero, Otherwise, find the first bit set scanning from left to
+ // right.
+ //
+
+ Result = ((P->DataType + 1) << 3) - 1;
+ Source = P->SrcValue.Long;
+ P->Eflags.ZF = 1;
+ while (Source != 0) {
+ if (((Source >> Result) & 1) != 0) {
+ P->Eflags.ZF = 0;
+ break;
+ }
+
+ Result -= 1;
+ };
+
+ XmStoreResult(P, Result);
+ return;
+}
+
+VOID
+XmBtOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an bt opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Test the specified bit and store the bit in CF.
+ //
+
+ P->Eflags.CF = P->DstValue.Long >> P->SrcValue.Long;
+ return;
+}
+
+VOID
+XmBtsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an bts opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Test and set the specified bit and store the bit in CF.
+ //
+ //
+
+ P->Eflags.CF = P->DstValue.Long >> P->SrcValue.Long;
+ P->DstValue.Long |= (1 << P->SrcValue.Long);
+ XmStoreResult(P, P->DstValue.Long);
+ return;
+}
+
+VOID
+XmBtrOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an btr opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Test and reset the specified bit and store the bit in CF.
+ //
+ //
+
+ P->Eflags.CF = P->DstValue.Long >> P->SrcValue.Long;
+ P->DstValue.Long &= ~(1 << P->SrcValue.Long);
+ XmStoreResult(P, P->DstValue.Long);
+ return;
+}
+
+VOID
+XmBtcOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an btc opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Test and reset the specified bit and store the bit in CF.
+ //
+ //
+
+ P->Eflags.CF = P->DstValue.Long >> P->SrcValue.Long;
+ P->DstValue.Long ^= (1 << P->SrcValue.Long);
+ XmStoreResult(P, P->DstValue.Long);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/condops.c b/private/ntos/nthals/x86new/condops.c
new file mode 100644
index 000000000..e01cb3457
--- /dev/null
+++ b/private/ntos/nthals/x86new/condops.c
@@ -0,0 +1,310 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ condops.c
+
+Abstract:
+
+ This module implements the code to emulate condition code opcodes.
+
+Author:
+
+ David N. Cutler (davec) 22-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmClcOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a clc opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Clear carry flag.
+ //
+
+ P->Eflags.CF = 0;
+ return;
+}
+
+VOID
+XmCldOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cld opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Clear direction flag.
+ //
+
+ P->Eflags.DF = 0;
+ return;
+}
+
+VOID
+XmCliOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cli opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Clear interrupt flag.
+ //
+
+ P->Eflags.IF = 0;
+ return;
+}
+
+VOID
+XmCmcOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cmc opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Complement carry flag.
+ //
+
+ P->Eflags.CF ^= 1;
+ return;
+}
+
+VOID
+XmStcOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a stc opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set carry flag.
+ //
+
+ P->Eflags.CF = 1;
+ return;
+}
+
+VOID
+XmStdOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a std opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set direction flag.
+ //
+
+ P->Eflags.DF = 1;
+ return;
+}
+
+VOID
+XmStiOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a sti opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set interrupt flag.
+ //
+
+ P->Eflags.IF = 1;
+ return;
+}
+
+VOID
+XmLahfOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a lahf opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Load flags into AH.
+ //
+
+ P->DataType = BYTE_DATA;
+ P->DstByte = &P->Gpr[AX].Xh;
+ XmStoreResult(P, (ULONG)P->AhFlags);
+ return;
+}
+
+VOID
+XmSahfOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a sahf opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Store CF, PF, AF, ZF, SF of AH in flags.
+ //
+
+ P->AhFlags = P->Gpr[AX].Xh;
+ P->Eflags.MBO = 1;
+ P->Eflags.SBZ0 = 0;
+ P->Eflags.SBZ1 = 0;
+ return;
+}
diff --git a/private/ntos/nthals/x86new/ctrlops.c b/private/ntos/nthals/x86new/ctrlops.c
new file mode 100644
index 000000000..e4158f88d
--- /dev/null
+++ b/private/ntos/nthals/x86new/ctrlops.c
@@ -0,0 +1,468 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ ctrlops.c
+
+Abstract:
+
+ This module implements the code to emulate call, retunr, and various
+ control operations.
+
+Author:
+
+ David N. Cutler (davec) 10-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmCallOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a call opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Target;
+ ULONG Source;
+
+ //
+ // Save the target address, push the current segment, if required, and
+ // push the current IP, set the destination segment, if required, and
+ // set the new IP.
+ //
+
+ Target = P->DstValue.Long;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if ((P->CurrentOpcode == 0x9a) || (P->FunctionIndex != X86_CALL_OP)) {
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+ P->SegmentRegister[CS] = P->DstSegment;
+
+ } else {
+ XmPushStack(P, P->Eip);
+ }
+
+ P->Eip = Target;
+ XmTraceJumps(P);
+ return;
+}
+
+VOID
+XmEnterOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an enter opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Allocate;
+ ULONG Frame;
+ ULONG Number;
+
+ //
+ // set the number of bytes to allocate on the stack and the number
+ // of nesting levels.
+ //
+
+ Allocate = P->SrcValue.Long;
+ Number = P->DstValue.Long;
+
+ //
+ // Set the data type and save the frame pointer on the stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ XmPushStack(P, P->Gpr[EBP].Exx);
+ Frame = P->Gpr[ESP].Exx;
+
+ } else {
+ P->DataType = WORD_DATA;
+ XmPushStack(P, P->Gpr[BP].Xx);
+ Frame = P->Gpr[SP].Xx;
+ }
+
+ //
+ // Save the current stack pointer and push parameters on the stack.
+ //
+
+ if (Number != 0) {
+
+ //
+ // If the level number is not one, then raise an exception.
+ //
+ // N.B. Level numbers greater than one are not supported.
+ //
+
+ if (Number != 1) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_LEVEL_NUMBER);
+ }
+
+ XmPushStack(P, Frame);
+ }
+
+ //
+ // Allocate local storage on stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->Gpr[EBP].Exx = Frame;
+ P->Gpr[ESP].Exx = P->Gpr[ESP].Exx - Allocate;
+
+ } else {
+ P->Gpr[BP].Xx = (USHORT)Frame;
+ P->Gpr[SP].Xx = (USHORT)(P->Gpr[SP].Xx - Allocate);
+ }
+
+ return;
+}
+
+VOID
+XmHltOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a hlt opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Halt instructions are not supported by the emulator.
+ //
+
+ longjmp(&P->JumpBuffer[0], XM_HALT_INSTRUCTION);
+ return;
+}
+
+VOID
+XmIntOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an int opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Number;
+ PULONG Vector;
+
+ //
+ // If the int instruction is an int 3, then set the interrupt vector
+ // to 3. Otherwise, if the int instruction is an into, then set the
+ // vector to 4 if OF is set. use the source interrupt vector.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if (P->CurrentOpcode == 0xcc) {
+ Number = 3;
+
+ } else if (P->CurrentOpcode == 0xce) {
+ if (P->Eflags.OF == 0) {
+ return;
+ }
+
+ Number = 4;
+
+ } else {
+ Number = P->SrcValue.Byte;
+ }
+
+ //
+ // If the vector number is 0x42, then nop the interrupt. This is the
+ // standard EGA video driver entry point in a PC's motherboard BIOS
+ // for which there is no code.
+ //
+
+#if !defined(_PURE_EMULATION_)
+
+ if (Number == 0x42) {
+ return;
+ }
+
+#endif
+
+ //
+ // If the vector number is 0x1a, then attempt to emulate the PCI BIOS
+ // if it is enabled.
+ //
+
+#if !defined(_PURE_EMULATION_)
+
+ if ((Number == 0x1a) && (XmExecuteInt1a(P) != FALSE)) {
+ return;
+ }
+
+#endif
+
+ //
+ // Push the current flags, code segment, and EIP on the stack.
+ //
+
+ XmPushStack(P, P->AllFlags);
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+
+ //
+ // Set the new coded segment and IP from the specified interrupt
+ // vector.
+ //
+
+ Vector = (PULONG)(P->TranslateAddress)(0, 0);
+ P->SegmentRegister[CS] = (USHORT)(Vector[Number] >> 16);
+ P->Eip = (USHORT)(Vector[Number] & 0xffff);
+ XmTraceJumps(P);
+ return;
+}
+
+VOID
+XmIretOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an iret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type and restore the return address, code segment,
+ // and flags.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ P->AllFlags = XmPopStack(P);
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
+
+VOID
+XmLeaveOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a leave opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type, restore the stack pointer, and restore the frame
+ // pointer.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ P->Gpr[ESP].Exx = P->Gpr[EBP].Exx;
+ P->Gpr[EBP].Exx = XmPopStack(P);
+
+ } else {
+ P->DataType = WORD_DATA;
+ P->Gpr[SP].Xx = P->Gpr[BP].Xx;
+ P->Gpr[BP].Xx = (USHORT)XmPopStack(P);
+ }
+
+ return;
+}
+
+VOID
+XmRetOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a ret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Adjust;
+
+ //
+ // Compute the number of bytes that are to be removed from the stack
+ // after having removed the return address and optionally the new CS
+ // segment value.
+ //
+
+ if ((P->CurrentOpcode & 0x1) == 0) {
+ Adjust = XmGetWordImmediate(P);
+
+ } else {
+ Adjust = 0;
+ }
+
+ //
+ // Remove the return address from the stack and set the new IP.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+
+ //
+ // If the current opcode is a far return, then remove the new CS segment
+ // value from the stack.
+ //
+
+ if ((P->CurrentOpcode & 0x8) != 0) {
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ }
+
+ //
+ // Remove the specified number of bytes from the stack.
+ //
+
+ P->Gpr[ESP].Exx += Adjust;
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/x86new/data.c b/private/ntos/nthals/x86new/data.c
new file mode 100644
index 000000000..44677f029
--- /dev/null
+++ b/private/ntos/nthals/x86new/data.c
@@ -0,0 +1,1375 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ data.c
+
+Abstract:
+
+ This module contains global data for the x86 bios emulator.
+
+Author:
+
+ David N. Cutler (davec) 10-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define emulator initialized variable.
+//
+
+BOOLEAN XmEmulatorInitialized = FALSE;
+
+//
+// Define emulator context structure.
+//
+
+XM_CONTEXT XmContext;
+
+//
+// Define operand decode table.
+//
+// This table contains the execution routine for each of the operand types.
+//
+// N.B. There is a cross indexing between the operand decode field of the
+// opcode control array and the decode table.
+//
+
+POPERAND_DECODE XmOperandDecodeTable[] = {
+ XmPushPopSegment,
+ XmPushPopSegment,
+ XmPushPopSegment,
+ XmPushPopSegment,
+ XmPushPopSegment,
+ XmPushPopSegment,
+ XmLoadSegment,
+ XmLoadSegment,
+ XmLoadSegment,
+ XmLoadSegment,
+ XmLoadSegment,
+ XmLoadSegment,
+ XmGroup1General,
+ XmGroup1Immediate,
+ XmGroup2By1,
+ XmGroup2ByCL,
+ XmGroup2ByByte,
+ XmGroup3General,
+ XmGroup45General,
+ XmGroup45General,
+ XmGroup8BitOffset,
+ XmOpcodeRegister,
+ XmLongJump,
+ XmShortJump,
+ XmSetccByte,
+ XmAccumImmediate,
+ XmAccumRegister,
+ XmMoveGeneral,
+ XmMoveImmediate,
+ XmMoveRegImmediate,
+ XmSegmentOffset,
+ XmMoveSegment,
+ XmMoveXxGeneral,
+ XmFlagsRegister,
+ XmPushImmediate,
+ XmPopGeneral,
+ XmImulImmediate,
+ XmStringOperands,
+ XmEffectiveOffset,
+ XmImmediateJump,
+ XmImmediateEnter,
+ XmGeneralBitOffset,
+ XmShiftDouble,
+ XmPortImmediate,
+ XmPortDX,
+ XmBitScanGeneral,
+ XmByteImmediate,
+ XmXlatOpcode,
+ XmGeneralRegister,
+ XmNoOperands,
+ XmOpcodeEscape,
+ XmPrefixOpcode
+};
+
+//
+// Define opcode function table.
+//
+// This table contains the execution routine for each opcode.
+//
+// N.B. There is cross indexing between the function index field of the
+// opcode control array and the function table. The function index
+// in the opcode control array may be the index of the execution
+// function, the base index of the execution function, or a switch
+// value to be used in selecting the function (i.e., prefix opcodes).
+//
+
+POPCODE_FUNCTION XmOpcodeFunctionTable[] = {
+
+ //
+ // ASCII operators.
+ //
+
+ XmAaaOp,
+ XmAadOp,
+ XmAamOp,
+ XmAasOp,
+ XmDaaOp,
+ XmDasOp,
+
+ //
+ // Group 1 operators.
+ //
+
+ XmAddOp,
+ XmOrOp,
+ XmAdcOp,
+ XmSbbOp,
+ XmAndOp,
+ XmSubOp,
+ XmXorOp,
+ XmCmpOp,
+
+ //
+ // Group 2 operators.
+ //
+
+ XmRolOp,
+ XmRorOp,
+ XmRclOp,
+ XmRcrOp,
+ XmShlOp,
+ XmShrOp,
+ XmIllOp,
+ XmSarOp,
+
+ //
+ // Group 3 operators.
+ //
+
+ XmTestOp,
+ XmIllOp,
+ XmNotOp,
+ XmNegOp,
+ XmMulOp,
+ XmImulxOp,
+ XmDivOp,
+ XmIdivOp,
+
+ //
+ // Group 4 and 5 operators.
+ //
+
+ XmIncOp,
+ XmDecOp,
+ XmCallOp,
+ XmCallOp,
+ XmJmpOp,
+ XmJmpOp,
+ XmPushOp,
+ XmIllOp,
+
+ //
+ // Group 8 operators.
+ //
+
+ XmBtOp,
+ XmBtsOp,
+ XmBtrOp,
+ XmBtcOp,
+
+ //
+ // Stack push and pop operators.
+ //
+
+ XmPopOp,
+ XmPushaOp,
+ XmPopaOp,
+
+ //
+ // Conditional jump operators.
+ //
+
+ XmJxxOp,
+ XmLoopOp,
+ XmJcxzOp,
+
+ //
+ // Control operators.
+ //
+
+ XmEnterOp,
+ XmHltOp,
+ XmIntOp,
+ XmIretOp,
+ XmLeaveOp,
+ XmRetOp,
+
+ //
+ // Set boolean byte value based on condition.
+ //
+
+ XmSxxOp,
+
+ //
+ // Condition code operators.
+ //
+
+ XmCmcOp,
+ XmClcOp,
+ XmStcOp,
+ XmCliOp,
+ XmStiOp,
+ XmCldOp,
+ XmStdOp,
+ XmLahfOp,
+ XmSahfOp,
+
+ //
+ // General move operators.
+ //
+
+ XmMovOp,
+ XmXchgOp,
+
+ //
+ // Convert operators.
+ //
+
+ XmCbwOp,
+ XmCwdOp,
+
+ //
+ // Single multiply operator.
+ //
+
+ XmImulOp,
+
+ //
+ // String operators.
+ //
+
+ XmCmpsOp,
+ XmInsOp,
+ XmLodsOp,
+ XmMovsOp,
+ XmOutsOp,
+ XmScasOp,
+ XmStosOp,
+
+ //
+ // Effective address operators.
+ //
+
+ XmBoundOp,
+ XmMovOp,
+
+ //
+ // Double Shift operators.
+ //
+
+ XmShldOp,
+ XmShrdOp,
+
+ //
+ // I/O operators.
+ //
+
+ XmInOp,
+ XmOutOp,
+
+ //
+ // Bit scan operators.
+ //
+
+ XmBsfOp,
+ XmBsrOp,
+
+ //
+ // Byte swap operators.
+ //
+
+ XmBswapOp,
+
+ //
+ // Add/Compare exchange operators.
+ //
+
+ XmXaddOp,
+ XmCmpxchgOp,
+
+ //
+ // No operation.
+ //
+
+ XmNopOp,
+
+ //
+ // Illegal opcode.
+ //
+
+ XmIllOp
+};
+
+//
+// Define opcode control table.
+//
+// There are two opcode tables which control the emulation of each x86
+// opcode. One table is for single byte opcodes and the other is for
+// two byte opcodes.
+//
+
+OPCODE_CONTROL XmOpcodeControlTable1[] = {
+ {X86_ADD_OP, FormatGroup1General}, // 0x00 - add Eb,Gb
+ {X86_ADD_OP, FormatGroup1General}, // 0x01 - add Ev,Gv
+ {X86_ADD_OP, FormatGroup1General}, // 0x02 - add Gb,Eb
+ {X86_ADD_OP, FormatGroup1General}, // 0x03 - add Gv,Ev
+ {X86_ADD_OP, FormatAccumImmediate}, // 0x04 - add AL,Ib
+ {X86_ADD_OP, FormatAccumImmediate}, // 0x05 - add eAX,Iv
+ {X86_PUSH_OP, FormatSegmentES}, // 0x06 - push ES
+ {X86_POP_OP, FormatSegmentES}, // 0x07 - pop ES
+ {X86_OR_OP, FormatGroup1General}, // 0x08 - or Eb,Gb
+ {X86_OR_OP, FormatGroup1General}, // 0x09 - or Ev,Gv
+ {X86_OR_OP, FormatGroup1General}, // 0x0a - or Gb,Eb
+ {X86_OR_OP, FormatGroup1General}, // 0x0b - or Gv,Ev
+ {X86_OR_OP, FormatAccumImmediate}, // 0x0c - or AL,Ib
+ {X86_OR_OP, FormatAccumImmediate}, // 0x0d - or eAX,Iv
+ {X86_PUSH_OP, FormatSegmentCS}, // 0x0e - push CS
+ {0, FormatOpcodeEscape}, // 0x0f - escape:
+ {X86_ADC_OP, FormatGroup1General}, // 0x10 - adc Eb,Gb
+ {X86_ADC_OP, FormatGroup1General}, // 0x11 - adc Ev,Gv
+ {X86_ADC_OP, FormatGroup1General}, // 0x12 - adc Gb,Eb
+ {X86_ADC_OP, FormatGroup1General}, // 0x13 - adc Gv,Ev
+ {X86_ADC_OP, FormatAccumImmediate}, // 0x14 - adc AL,Ib
+ {X86_ADC_OP, FormatAccumImmediate}, // 0x15 - adc eAX,Iv
+ {X86_PUSH_OP, FormatSegmentSS}, // 0x16 - push SS
+ {X86_POP_OP, FormatSegmentSS}, // 0x17 - pop SS
+ {X86_SBB_OP, FormatGroup1General}, // 0x18 - sbb Eb,Gb
+ {X86_SBB_OP, FormatGroup1General}, // 0x19 - sbb Ev,Gv
+ {X86_SBB_OP, FormatGroup1General}, // 0x1a - sbb Gb,Eb
+ {X86_SBB_OP, FormatGroup1General}, // 0x1b - sbb Gv,Ev
+ {X86_SBB_OP, FormatAccumImmediate}, // 0x1c - sbb AL,Ib
+ {X86_SBB_OP, FormatAccumImmediate}, // 0x1d - sbb eAX,Iv
+ {X86_PUSH_OP, FormatSegmentDS}, // 0x1e - push DS
+ {X86_POP_OP, FormatSegmentDS}, // 0x1f - pop DS
+ {X86_AND_OP, FormatGroup1General}, // 0x20 - and Eb,Gb
+ {X86_AND_OP, FormatGroup1General}, // 0x21 - and Ev,Gv
+ {X86_AND_OP, FormatGroup1General}, // 0x22 - and Gb,Eb
+ {X86_AND_OP, FormatGroup1General}, // 0x23 - and Gv,Ev
+ {X86_AND_OP, FormatAccumImmediate}, // 0x24 - and AL,Ib
+ {X86_AND_OP, FormatAccumImmediate}, // 0x25 - and eAX,Iv
+ {X86_ES_OP, FormatPrefixOpcode}, // 0x26 - ES:
+ {X86_DAA_OP, FormatNoOperands}, // 0x27 - daa
+ {X86_SUB_OP, FormatGroup1General}, // 0x28 - sub Eb,Gb
+ {X86_SUB_OP, FormatGroup1General}, // 0x29 - sub Ev,Gv
+ {X86_SUB_OP, FormatGroup1General}, // 0x2a - sub Gb,Eb
+ {X86_SUB_OP, FormatGroup1General}, // 0x2b - sub Gv,Ev
+ {X86_SUB_OP, FormatAccumImmediate}, // 0x2c - sub AL,Ib
+ {X86_SUB_OP, FormatAccumImmediate}, // 0x2d - sub eAX,Iv
+ {X86_CS_OP, FormatPrefixOpcode}, // 0x2e - CS:
+ {X86_DAS_OP, FormatNoOperands}, // 0x2f - das
+ {X86_XOR_OP, FormatGroup1General}, // 0x30 - xor Eb,Gb
+ {X86_XOR_OP, FormatGroup1General}, // 0x31 - xor Ev,Gv
+ {X86_XOR_OP, FormatGroup1General}, // 0x32 - xor Gb,Eb
+ {X86_XOR_OP, FormatGroup1General}, // 0x33 - xor Gv,Ev
+ {X86_XOR_OP, FormatAccumImmediate}, // 0x34 - xor AL,Ib
+ {X86_XOR_OP, FormatAccumImmediate}, // 0x35 - xor eAX,Iv
+ {X86_SS_OP, FormatPrefixOpcode}, // 0x36 - SS:
+ {X86_AAA_OP, FormatNoOperands}, // 0x37 - aaa
+ {X86_CMP_OP, FormatGroup1General}, // 0x38 - cmp Eb,Gb
+ {X86_CMP_OP, FormatGroup1General}, // 0x39 - cmp Ev,Gv
+ {X86_CMP_OP, FormatGroup1General}, // 0x3a - cmp Gb,Eb
+ {X86_CMP_OP, FormatGroup1General}, // 0x3b - cmp Gv,Ev
+ {X86_CMP_OP, FormatAccumImmediate}, // 0x3c - cmp AL,Ib
+ {X86_CMP_OP, FormatAccumImmediate}, // 0x3d - cmp eAX,Iv
+ {X86_DS_OP, FormatPrefixOpcode}, // 0x3e - DS:
+ {X86_AAS_OP, FormatNoOperands}, // 0x3f - aas
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x40 - inc eAX
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x41 - inc eCX
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x42 - inc eDX
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x43 - inc eBX
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x44 - inc eSP
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x45 - inc eBP
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x46 - inc eSI
+ {X86_INC_OP, FormatOpcodeRegister}, // 0x47 - inc eDI
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x48 - dec eAX
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x49 - dec eCX
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x4a - dec eDX
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x4b - dec eBX
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x4c - dec eSP
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x4d - dec eBP
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x4e - dec eSI
+ {X86_DEC_OP, FormatOpcodeRegister}, // 0x4f - dec eDI
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x50 - push eAX
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x51 - push eCX
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x52 - push eDX
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x53 - push eBX
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x54 - push eSP
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x55 - push eBP
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x56 - push eSI
+ {X86_PUSH_OP, FormatOpcodeRegister}, // 0x57 - push eDI
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x58 - pop eAX
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x59 - pop eCX
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x5a - pop eDX
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x5b - pop eBX
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x5c - pop eSP
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x5d - pop eBP
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x5e - pop eSI
+ {X86_POP_OP, FormatOpcodeRegister}, // 0x5f - pop eDI
+ {X86_PUSHA_OP, FormatNoOperands}, // 0x60 - pusha
+ {X86_POPA_OP, FormatNoOperands}, // 0x61 - popa
+ {X86_BOUND_OP, FormatEffectiveOffset}, // 0x62 - bound Gv,Ma
+ {X86_ILL_OP, FormatNoOperands}, // 0x63 - arpl Ew,Rw
+ {X86_FS_OP, FormatPrefixOpcode}, // 0x64 - FS:
+ {X86_GS_OP, FormatPrefixOpcode}, // 0x65 - GS:
+ {X86_OPSZ_OP, FormatPrefixOpcode}, // 0x66 - opsize
+ {X86_ADSZ_OP, FormatPrefixOpcode}, // 0x67 - opaddr
+ {X86_PUSH_OP, FormatPushImmediate}, // 0x68 - push iv
+ {X86_IMUL_OP, FormatImulImmediate}, // 0x69 - imul
+ {X86_PUSH_OP, FormatPushImmediate}, // 0x6a - push ib
+ {X86_IMUL_OP, FormatImulImmediate}, // 0x6b - imul
+ {X86_INS_OP, FormatPortDX}, // 0x6c - insb
+ {X86_INS_OP, FormatPortDX}, // 0x6d - insw/d
+ {X86_OUTS_OP, FormatPortDX}, // 0x6e - outsb
+ {X86_OUTS_OP, FormatPortDX}, // 0x6f - outsw/d
+ {X86_JXX_OP, FormatShortJump}, // 0x70 - jo jb
+ {X86_JXX_OP, FormatShortJump}, // 0x71 - jno jb
+ {X86_JXX_OP, FormatShortJump}, // 0x72 - jb jb
+ {X86_JXX_OP, FormatShortJump}, // 0x73 - jnb jb
+ {X86_JXX_OP, FormatShortJump}, // 0x74 - jz jb
+ {X86_JXX_OP, FormatShortJump}, // 0x75 - jnz jb
+ {X86_JXX_OP, FormatShortJump}, // 0x76 - jbe jb
+ {X86_JXX_OP, FormatShortJump}, // 0x77 - jnbe jb
+ {X86_JXX_OP, FormatShortJump}, // 0x78 - js jb
+ {X86_JXX_OP, FormatShortJump}, // 0x79 - jns jb
+ {X86_JXX_OP, FormatShortJump}, // 0x7a - jp jb
+ {X86_JXX_OP, FormatShortJump}, // 0x7b - jnp jb
+ {X86_JXX_OP, FormatShortJump}, // 0x7c - jl jb
+ {X86_JXX_OP, FormatShortJump}, // 0x7d - jnl jb
+ {X86_JXX_OP, FormatShortJump}, // 0x7e - jle jb
+ {X86_JXX_OP, FormatShortJump}, // 0x7f - jnle jb
+ {X86_ADD_OP, FormatGroup1Immediate}, // 0x80 - group1 Eb,Ib
+ {X86_ADD_OP, FormatGroup1Immediate}, // 0x81 - group1 Ev,Iv
+ {X86_ILL_OP, FormatNoOperands}, // 0x82 - illegal
+ {X86_ADD_OP, FormatGroup1Immediate}, // 0x83 - group1 Ev,Ib
+ {X86_TEST_OP, FormatGroup1General}, // 0x84 - test Eb,Gb
+ {X86_TEST_OP, FormatGroup1General}, // 0x85 - test Ev,Gv
+ {X86_XCHG_OP, FormatGroup1General}, // 0x86 - xchg Eb,Gb
+ {X86_XCHG_OP, FormatGroup1General}, // 0x87 = xchg Ev,Gv
+ {X86_MOV_OP, FormatMoveGeneral}, // 0x88 - mov Eb,Gb
+ {X86_MOV_OP, FormatMoveGeneral}, // 0x89 - mov Ev,Gv
+ {X86_MOV_OP, FormatMoveGeneral}, // 0x8a - mov Gb,Eb
+ {X86_MOV_OP, FormatMoveGeneral}, // 0x8b - mov Gv,Ev
+ {X86_MOV_OP, FormatMoveSegment}, // 0x8c - mov Ew,Sw
+ {X86_LEA_OP, FormatEffectiveOffset}, // 0x8d - lea Gv,Ma
+ {X86_MOV_OP, FormatMoveSegment}, // 0x8e - mov Sw,Ew
+ {X86_POP_OP, FormatPopGeneral}, // 0x8f - pop Ev
+ {X86_NOP_OP, FormatNoOperands}, // 0x90 - nop
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x91 - xchg eCX,eAX
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x92 - xchg eDX,eAX
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x93 - xchg eBX,eAX
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x94 - xchg eSP,eAX
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x95 - xchg eBP,eAX
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x96 - xchg eSI,eAX
+ {X86_XCHG_OP, FormatAccumRegister}, // 0x97 - xchg eDI,eAX
+ {X86_CBW_OP, FormatNoOperands}, // 0x98 - cbw
+ {X86_CWD_OP, FormatNoOperands}, // 0x99 - cwd
+ {X86_CALL_OP, FormatImmediateJump}, // 0x9a - call Ap
+ {X86_NOP_OP, FormatNoOperands}, // 0x9b - wait
+ {X86_PUSH_OP, FormatFlagsRegister}, // 0x9c - pushf
+ {X86_POP_OP, FormatFlagsRegister}, // 0x9d - popf
+ {X86_SAHF_OP, FormatNoOperands}, // 0x9e - sahf
+ {X86_LAHF_OP, FormatNoOperands}, // 0x9f - lahf
+ {X86_MOV_OP, FormatSegmentOffset}, // 0xa0 - mov AL,Ob
+ {X86_MOV_OP, FormatSegmentOffset}, // 0xa1 - mov eAX,Ov
+ {X86_MOV_OP, FormatSegmentOffset}, // 0xa2 - mov Ob,AL
+ {X86_MOV_OP, FormatSegmentOffset}, // 0xa3 - mov Ov,eAX
+ {X86_MOVS_OP, FormatStringOperands}, // 0xa4 - movsb
+ {X86_MOVS_OP, FormatStringOperands}, // 0xa5 - movsw/d
+ {X86_CMPS_OP, FormatStringOperands}, // 0xa6 - cmpsb
+ {X86_CMPS_OP, FormatStringOperands}, // 0xa7 - cmpsw/d
+ {X86_TEST_OP, FormatAccumImmediate}, // 0xa8 - test AL,Ib
+ {X86_TEST_OP, FormatAccumImmediate}, // 0xa9 - test eAX,Iv
+ {X86_STOS_OP, FormatStringOperands}, // 0xaa - stosb
+ {X86_STOS_OP, FormatStringOperands}, // 0xab - stosw/d
+ {X86_LODS_OP, FormatStringOperands}, // 0xac - lodsb
+ {X86_LODS_OP, FormatStringOperands}, // 0xad - lodsw.d
+ {X86_SCAS_OP, FormatStringOperands}, // 0xae - scasb
+ {X86_SCAS_OP, FormatStringOperands}, // 0xaf - scasw/d
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb0 mov AL,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb1 mov Cl,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb2 mov DL,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb3 mov BL,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb4 mov AH,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb5 mov CH,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb6 mov DH,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb7 mov BH,Ib
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb8 mov eAX,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xb9 mov eCX,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xba mov eDX,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xbb mov eBX,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xbc mov eSP,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xbd mov eBP,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xbe mov eSI,Iv
+ {X86_MOV_OP, FormatMoveRegImmediate}, // 0xbf mov eDI,Iv
+ {X86_ROL_OP, FormatGroup2ByByte}, // 0xc0 - group2 Eb,Ib
+ {X86_ROL_OP, FormatGroup2ByByte}, // 0xc1 - group2 Ev,Ib
+ {X86_RET_OP, FormatNoOperands}, // 0xc2 - ret Iw (near)
+ {X86_RET_OP, FormatNoOperands}, // 0xc3 - ret (near)
+ {X86_MOV_OP, FormatLoadSegmentES}, // 0xc4 - les Gv,Mp
+ {X86_MOV_OP, FormatLoadSegmentDS}, // 0xc5 - lds Gv,Mp
+ {X86_MOV_OP, FormatMoveImmediate}, // 0xc6 - mov Eb,Ib
+ {X86_MOV_OP, FormatMoveImmediate}, // 0xc7 - mov Ev,Iv
+ {X86_ENTER_OP, FormatImmediateEnter}, // 0xc8 - enter Iw,Ib
+ {X86_LEAVE_OP, FormatNoOperands}, // 0xc9 - leave
+ {X86_RET_OP, FormatNoOperands}, // 0xca - ret Iw (far)
+ {X86_RET_OP, FormatNoOperands}, // 0xcb - ret (far)
+ {X86_INT_OP, FormatNoOperands}, // 0xcc - int 3
+ {X86_INT_OP, FormatByteImmediate}, // 0xcd - int Ib
+ {X86_INT_OP, FormatNoOperands}, // 0xce - into
+ {X86_IRET_OP, FormatNoOperands}, // 0xcf - iret
+ {X86_ROL_OP, FormatGroup2By1}, // 0xd0 - group2 Eb,1
+ {X86_ROL_OP, FormatGroup2By1}, // 0xd1 - group2 Ev,1
+ {X86_ROL_OP, FormatGroup2ByCL}, // 0xd2 - group2 Eb,CL
+ {X86_ROL_OP, FormatGroup2ByCL}, // 0xd3 - group2 Ev,CL
+ {X86_AAM_OP, FormatByteImmediate}, // 0xd4 - aam
+ {X86_AAD_OP, FormatByteImmediate}, // 0xd5 - aad
+ {X86_ILL_OP, FormatNoOperands}, // 0xd6 - illegal
+ {X86_MOV_OP, FormatXlatOpcode}, // 0xd7 - xlat
+ {X86_ILL_OP, FormatNoOperands}, // 0xd8 - esc0
+ {X86_ILL_OP, FormatNoOperands}, // 0xd9 - esc1
+ {X86_ILL_OP, FormatNoOperands}, // 0xda - esc2
+ {X86_ILL_OP, FormatNoOperands}, // 0xdb - esc3
+ {X86_ILL_OP, FormatNoOperands}, // 0xdc - esc4
+ {X86_ILL_OP, FormatNoOperands}, // 0xdd - esc5
+ {X86_ILL_OP, FormatNoOperands}, // 0xde - esc6
+ {X86_ILL_OP, FormatNoOperands}, // 0xdf - esc7
+ {X86_LOOP_OP, FormatShortJump}, // 0xe0 - loopnz
+ {X86_LOOP_OP, FormatShortJump}, // 0xe1 - loopz
+ {X86_LOOP_OP, FormatShortJump}, // 0xe2 - loop
+ {X86_JCXZ_OP, FormatShortJump}, // 0xe3 - jcxz
+ {X86_IN_OP, FormatPortImmediate}, // 0xe4 - inb AL,Ib
+ {X86_IN_OP, FormatPortImmediate}, // 0xe5 - inw/d eAX,Ib
+ {X86_OUT_OP, FormatPortImmediate}, // 0xe6 - outb Ib,AL
+ {X86_OUT_OP, FormatPortImmediate}, // 0xe7 - outw/d Ib,eAX
+ {X86_CALL_OP, FormatLongJump}, // 0xe8 - call Jv
+ {X86_JMP_OP, FormatLongJump}, // 0xe9 - jmp Jv
+ {X86_JMP_OP, FormatImmediateJump}, // 0xea - jmp Ap
+ {X86_JMP_OP, FormatShortJump}, // 0xeb - jmp Jb
+ {X86_IN_OP, FormatPortDX}, // 0xec - inb AL,DX
+ {X86_IN_OP, FormatPortDX}, // 0xed - inw/d eAX,DX
+ {X86_OUT_OP, FormatPortDX}, // 0xee - outb Ib,DX
+ {X86_OUT_OP, FormatPortDX}, // 0xef - outw/d eAX,DX
+ {X86_LOCK_OP, FormatPrefixOpcode}, // 0xf0 - lock
+ {X86_ILL_OP, FormatNoOperands}, // 0xf1 - illegal
+ {X86_REPNZ_OP, FormatPrefixOpcode}, // 0xf2 - repnz
+ {X86_REPZ_OP, FormatPrefixOpcode}, // 0xf3 - repz
+ {X86_HLT_OP, FormatNoOperands}, // 0xf4 - hlt
+ {X86_CMC_OP, FormatNoOperands}, // 0xf5 - cmc
+ {X86_TEST_OP, FormatGroup3General}, // 0xf6 - group3 Eb,?
+ {X86_TEST_OP, FormatGroup3General}, // 0xf7 - group3 Ev,?
+ {X86_CLC_OP, FormatNoOperands}, // 0xf8 - clc
+ {X86_STC_OP, FormatNoOperands}, // 0xf9 - stc
+ {X86_CLI_OP, FormatNoOperands}, // 0xfa - cli
+ {X86_STI_OP, FormatNoOperands}, // 0xfb - sti
+ {X86_CLD_OP, FormatNoOperands}, // 0xfc - cld
+ {X86_STD_OP, FormatNoOperands}, // 0xfd - std
+ {X86_INC_OP, FormatGroup4General}, // 0xfe - group4 Eb
+ {X86_INC_OP, FormatGroup5General}, // 0xff - group5 Ev
+};
+
+OPCODE_CONTROL XmOpcodeControlTable2[] = {
+ {X86_ILL_OP, FormatNoOperands}, // 0x00 - group6
+ {X86_ILL_OP, FormatNoOperands}, // 0x01 - group7
+ {X86_ILL_OP, FormatNoOperands}, // 0x02 - lar
+ {X86_ILL_OP, FormatNoOperands}, // 0x03 - lsl
+ {X86_ILL_OP, FormatNoOperands}, // 0x04 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x05 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x06 - clts
+ {X86_ILL_OP, FormatNoOperands}, // 0x07 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x08 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x09 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x0a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x0b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x0c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x0d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x0e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x0f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x10 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x11 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x12 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x13 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x14 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x15 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x16 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x17 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x18 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x19 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x1a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x1b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x1c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x1d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x1e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x1f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x20 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x21 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x22 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x23 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x34 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x25 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x26 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x27 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x28 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x29 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x2a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x2b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x2c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x2d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x2e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x2f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x30 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x31 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x32 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x33 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x34 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x35 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x36 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x37 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x38 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x39 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x3a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x3b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x3c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x3d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x3e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x3f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x40 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x41 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x42 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x43 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x44 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x45 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x46 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x47 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x48 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x49 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x4a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x4b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x4c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x4d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x4e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x4f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x50 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x51 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x52 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x53 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x54 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x55 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x56 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x57 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x58 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x59 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x5a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x5b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x5c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x5d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x5e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x5f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x60 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x61 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x62 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x63 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x64 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x65 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x66 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x67 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x68 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x69 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x6a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x6b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x6c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x6d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x6e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x6f - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x70 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x71 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x72 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x73 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x74 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x75 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x76 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x77 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x78 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x79 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x7a - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x7b - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x7c - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x7d - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x7e - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0x7f - illegal
+ {X86_JXX_OP, FormatLongJump}, // 0x80 - jo jv
+ {X86_JXX_OP, FormatLongJump}, // 0x81 - jno jv
+ {X86_JXX_OP, FormatLongJump}, // 0x82 - jb jv
+ {X86_JXX_OP, FormatLongJump}, // 0x83 - jnb jv
+ {X86_JXX_OP, FormatLongJump}, // 0x84 - jz jv
+ {X86_JXX_OP, FormatLongJump}, // 0x85 - jnz jv
+ {X86_JXX_OP, FormatLongJump}, // 0x86 - jbe jv
+ {X86_JXX_OP, FormatLongJump}, // 0x87 - jnbe jv
+ {X86_JXX_OP, FormatLongJump}, // 0x88 - js jv
+ {X86_JXX_OP, FormatLongJump}, // 0x89 - jns jv
+ {X86_JXX_OP, FormatLongJump}, // 0x8a - jp jv
+ {X86_JXX_OP, FormatLongJump}, // 0x8b - jnp jv
+ {X86_JXX_OP, FormatLongJump}, // 0x8c - jl jv
+ {X86_JXX_OP, FormatLongJump}, // 0x8d - jnl jv
+ {X86_JXX_OP, FormatLongJump}, // 0x8e - jle jv
+ {X86_JXX_OP, FormatLongJump}, // 0x8f - jnle jv
+ {X86_SXX_OP, FormatSetccByte}, // 0x90 - seto Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x91 - setno Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x92 - setb Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x93 - setnb Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x94 - setz Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x95 - setnz Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x96 - setbe Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x97 - setnbe Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x98 - sets Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x99 - setns Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x9a - setp Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x9b - setnp Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x9c - setl Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x9d - setnl Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x9e - setle Eb
+ {X86_SXX_OP, FormatSetccByte}, // 0x9f - setnle Eb
+ {X86_PUSH_OP, FormatSegmentFS}, // 0xa0 - push FS
+ {X86_POP_OP, FormatSegmentFS}, // 0xa1 - pop FS
+ {X86_ILL_OP, FormatNoOperands}, // 0xa2 - illegal
+ {X86_BT_OP, FormatGeneralBitOffset}, // 0xa3 - bt Ev,Gv
+ {X86_SHLD_OP, FormatShiftDouble}, // 0xa4 - shld Ev,Gv,Ib
+ {X86_SHLD_OP, FormatShiftDouble}, // 0xa5 - shld Ev,Gv,cl
+ {X86_ILL_OP, FormatNoOperands}, // 0xa6 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xa6 - illegal
+ {X86_PUSH_OP, FormatSegmentGS}, // 0xa8 - push GS
+ {X86_POP_OP, FormatSegmentGS}, // 0xa9 - pop GS
+ {X86_ILL_OP, FormatNoOperands}, // 0xaa - illegal
+ {X86_BTS_OP, FormatGeneralBitOffset}, // 0xab - bts Ev,Gv
+ {X86_SHRD_OP, FormatShiftDouble}, // 0xac - shdr Ev,Gv,Ib
+ {X86_SHRD_OP, FormatShiftDouble}, // 0xad - shdr Rv,Gv,cl
+ {X86_ILL_OP, FormatNoOperands}, // 0xae - illegal
+ {X86_IMUL_OP, FormatGroup1General}, // 0xaf - imul Gv,Ev
+ {X86_CMPXCHG_OP, FormatGroup1General}, // 0xb0 - cmpxchg Eb,Gb
+ {X86_CMPXCHG_OP, FormatGroup1General}, // 0xb1 - cmpxchg Ev,Gv
+ {X86_MOV_OP, FormatLoadSegmentSS}, // 0xb2 - lss Gv,Mp
+ {X86_BTR_OP, FormatGeneralBitOffset}, // 0xb3 - btr Ev,Gv
+ {X86_MOV_OP, FormatLoadSegmentFS}, // 0xb4 - lfs Gv,Mp
+ {X86_MOV_OP, FormatLoadSegmentGS}, // 0xb5 - lgd Gv,Mp
+ {X86_MOV_OP, FormatMoveXxGeneral}, // 0xb6 - movzb Gv,Eb
+ {X86_MOV_OP, FormatMoveXxGeneral}, // 0xb7 - movsw Gv,Ew
+ {X86_ILL_OP, FormatNoOperands}, // 0xb8 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xb9 - illegal
+ {X86_BT_OP, FormatGroup8BitOffset}, // 0xba - group8 Ev,Ib
+ {X86_BTC_OP, FormatGeneralBitOffset}, // 0xbb - btc Ev,Gv
+ {X86_BSF_OP, FormatBitScanGeneral}, // 0xbc - bsf Gv,Ev
+ {X86_BSR_OP, FormatBitScanGeneral}, // 0xbd - bsr Gv,Ev
+ {X86_MOV_OP, FormatMoveXxGeneral}, // 0xbe - movsb Gv,Eb
+ {X86_MOV_OP, FormatMoveXxGeneral}, // 0xbf - movsw Gv,Ew
+ {X86_XADD_OP, FormatGroup1General}, // 0xc0 - xadd Eb,Gb
+ {X86_XADD_OP, FormatGroup1General}, // 0xc1 - xadd Ev,Gv
+ {X86_ILL_OP, FormatNoOperands}, // 0xc2 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xc3 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xc4 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xc5 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xc6 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xc7 - illegal
+ {X86_BSWAP_OP, FormatGeneralRegister}, // 0xc8 - bswap Gv
+ {X86_ILL_OP, FormatNoOperands}, // 0xc9 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xca - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xcb - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xcc - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xcd - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xce - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xcf - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd0 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd1 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd2 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd3 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd4 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd5 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd6 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd7 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd8 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xd9 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xda - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xdb - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xdc - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xdd - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xde - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xdf - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe0 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe1 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe2 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe3 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe4 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe5 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe6 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe7 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe8 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xe9 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xea - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xeb - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xec - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xed - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xee - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xef - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf0 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf1 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf2 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf3 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf4 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf5 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf6 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf7 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf8 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xf9 - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xfa - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xfb - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xfc - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xfd - illegal
+ {X86_ILL_OP, FormatNoOperands}, // 0xfe - illegal
+ {X86_ILL_OP, FormatNoOperands} // 0xff - illegal
+};
+
+//
+// Define opcode name tables.
+//
+
+#if defined(XM_DEBUG)
+
+PCHAR XmOpcodeNameTable1[] = {
+ "add Eb,Gb ", // 0x00
+ "add Ev,Gv ", // 0x01
+ "add Gb,Eb ", // 0x02
+ "add Gv,Ev ", // 0x03
+ "add AL,Ib ", // 0x04
+ "add eAX,Iv ", // 0x05
+ "push ES ", // 0x06
+ "pop ES ", // 0x07
+ "or Eb,Gb ", // 0x08
+ "or Ev,Gv ", // 0x09
+ "or Gb,Eb ", // 0x0a
+ "or Gv,Ev ", // 0x0b
+ "or AL,Ib ", // 0x0c
+ "or eAX,Iv ", // 0x0d
+ "push CS ", // 0x0e
+ "escape: ", // 0x0f
+ "adc Eb,Gb ", // 0x10
+ "adc Ev,Gv ", // 0x11
+ "adc Gb,Eb ", // 0x12
+ "adc Gv,Ev ", // 0x13
+ "adc AL,Ib ", // 0x14
+ "adc eAX,Iv ", // 0x15
+ "push SS ", // 0x16
+ "pop SS ", // 0x17
+ "sbb Eb,Gb ", // 0x18
+ "sbb Ev,Gv ", // 0x19
+ "sbb Gb,Eb ", // 0x1a
+ "sbb Gv,Ev ", // 0x1b
+ "sbb AL,Ib ", // 0x1c
+ "sbb eAX,Iv ", // 0x1d
+ "push DS ", // 0x1e
+ "pop DS ", // 0x1f
+ "and Eb,Gb ", // 0x20
+ "and Ev,Gv ", // 0x21
+ "and Gb,Eb ", // 0x22
+ "and Gv,Ev ", // 0x23
+ "and AL,Ib ", // 0x24
+ "and eAX,Iv ", // 0x25
+ "ES: ", // 0x26
+ "daa ", // 0x27
+ "sub Eb,Gb ", // 0x28
+ "sub Ev,Gv ", // 0x29
+ "sub Gb,Eb ", // 0x2a
+ "sub Gv,Ev ", // 0x2b
+ "sub AL,Ib ", // 0x2c
+ "sub eAX,Iv ", // 0x2d
+ "CS: ", // 0x2e
+ "das ", // 0x2f
+ "xor Eb,Gb ", // 0x30
+ "xor Ev,Gv ", // 0x31
+ "xor Gb,Eb ", // 0x32
+ "xor Gv,Ev ", // 0x33
+ "xor AL,Ib ", // 0x34
+ "xor eAX,Iv ", // 0x35
+ "SS: ", // 0x36
+ "aaa ", // 0x37
+ "cmp Eb,Gb ", // 0x38
+ "cmp Ev,Gv ", // 0x39
+ "cmp Gb,Eb ", // 0x3a
+ "cmp Gv,Ev ", // 0x3b
+ "cmp AL,Ib ", // 0x3c
+ "cmp eAX,Iv ", // 0x3d
+ "DS: ", // 0x3e
+ "aas ", // 0x3f
+ "inc eAX ", // 0x40
+ "inc eCX ", // 0x41
+ "inc eDX ", // 0x42
+ "inc eBX ", // 0x43
+ "inc eSP ", // 0x44
+ "inc eBP ", // 0x45
+ "inc eSI ", // 0x46
+ "inc eDI ", // 0x47
+ "dec eAX ", // 0x48
+ "dec eCX ", // 0x49
+ "dec eDX ", // 0x4a
+ "dec eBX ", // 0x4b
+ "dec eSP ", // 0x4c
+ "dec eBP ", // 0x4d
+ "dec eSI ", // 0x4e
+ "dec eDI ", // 0x4f
+ "push eAX ", // 0x50
+ "push eCX ", // 0x51
+ "push eDX ", // 0x52
+ "push eBX ", // 0x53
+ "push eSP ", // 0x54
+ "push eBP ", // 0x55
+ "push eSI ", // 0x56
+ "push eDI ", // 0x57
+ "pop eAX ", // 0x58
+ "pop eCX ", // 0x59
+ "pop eDX ", // 0x5a
+ "pop eBX ", // 0x5b
+ "pop eSP ", // 0x5c
+ "pop eBP ", // 0x5d
+ "pop eSI ", // 0x5e
+ "pop eDI ", // 0x5f
+ "pusha ", // 0x60
+ "popa ", // 0x61
+ "bound Gv,Ma ", // 0x62
+ "arpl Ew,Rw ", // 0x63
+ "FS: ", // 0x64
+ "GS: ", // 0x65
+ "opsize: ", // 0x66
+ "opaddr: ", // 0x67
+ "push Iv ", // 0x68
+ "imul Gv,Ev,Iv ", // 0x69
+ "push Ib ", // 0x6a
+ "imul Gv,Ev,Ib ", // 0x6b
+ "insb ", // 0x6c
+ "insw/d ", // 0x6d
+ "outsb ", // 0x6e
+ "outsw/d ", // 0x6f
+ "jo Jb ", // 0x70
+ "jno Jb ", // 0x71
+ "jb Jb ", // 0x72
+ "jnb Jb ", // 0x73
+ "jz Jb ", // 0x74
+ "jnz Jb ", // 0x75
+ "jbe Jb ", // 0x76
+ "jnbe Jb ", // 0x77
+ "js Jb ", // 0x78
+ "jns Jb ", // 0x79
+ "jp Jb ", // 0x7a
+ "jnp Jb ", // 0x7b
+ "jl Jb ", // 0x7c
+ "jnl Jb ", // 0x7d
+ "jle Jb ", // 0x7e
+ "jnle Jb ", // 0x7f
+ "group1 Eb,Ib ", // 0x80
+ "group1 Ev,Ib ", // 0x81
+ "illegal ", // 0x82
+ "group1 Ev,Ib ", // 0x83
+ "test Eb,Gb ", // 0x84
+ "test Ev,Gv ", // 0x85
+ "xchg Eb,Gb ", // 0x86
+ "xchg Ev,Gv ", // 0x87
+ "mov Eb,Gb ", // 0x88
+ "mov Ev,Gv ", // 0x89
+ "mov Gb,Eb ", // 0x8a
+ "mov Gv,Ev ", // 0x8b
+ "mov Ew,Sw ", // 0x8c
+ "lea Gv,Ma ", // 0x8d
+ "mov Sw,Ew ", // 0x8e
+ "pop Ev ", // 0x8f
+ "nop ", // 0x90
+ "xchg eCX,eAX ", // 0x91
+ "xchg eDX,eAX ", // 0x92
+ "xchg eBX,eAX ", // 0x93
+ "xchg eSP,eAX ", // 0x94
+ "xchg eBP,eAX ", // 0x95
+ "xchg eSI,eAX ", // 0x96
+ "xchg eDI,eAX ", // 0x97
+ "cbw ", // 0x98
+ "cwd ", // 0x99
+ "call Ap ", // 0x9a
+ "wait ", // 0x9b
+ "pushf ", // 0x9c
+ "popf ", // 0x9d
+ "sahf ", // 0x9e
+ "lahf ", // 0x9f
+ "mov AL,Ob ", // 0xa0
+ "mov eAX,Ov ", // 0xa1
+ "mov Ob,AL ", // 0xa2
+ "mov Ov,eAX ", // 0xa3
+ "movsb ", // 0xa4
+ "movsw/d ", // 0xa5
+ "cmpsb ", // 0xa6
+ "cmpsw/d ", // 0xa7
+ "test AL,Ib ", // 0xa8
+ "test eAX,Iv ", // 0xa9
+ "stosb ", // 0xaa
+ "stosw/d ", // 0xab
+ "lodsb ", // 0xac
+ "lodsw/d ", // 0xad
+ "scasb ", // 0xae
+ "scasw/d ", // 0xaf
+ "mov AL,Ib ", // 0xb0
+ "mov Cl,Ib ", // 0xb1
+ "mov DL,Ib ", // 0xb2
+ "mov BL,Ib ", // 0xb3
+ "mov AH,Ib ", // 0xb4
+ "mov CH,Ib ", // 0xb5
+ "mov DH,Ib ", // 0xb6
+ "mov BH,Ib ", // 0xb7
+ "mov eAX,Iv ", // 0xb8
+ "mov eCX,Iv ", // 0xb9
+ "mov eDX,Iv ", // 0xba
+ "mov eBX,Iv ", // 0xbb
+ "mov eSP,Iv ", // 0xbc
+ "mov eBP,Iv ", // 0xbd
+ "mov eSI,Iv ", // 0xbe
+ "mov eDI,Iv ", // 0xbf
+ "group2 Eb,Ib ", // 0xc0
+ "group2 Ev,Ib ", // 0xc1
+ "ret Iw near ", // 0xc2
+ "ret near ", // 0xc3
+ "les Gv,Mp ", // 0xc4
+ "lds Gv,Mp ", // 0xc5
+ "mov Eb,Ib ", // 0xc6
+ "mov Ev,Iv ", // 0xc7
+ "enter Iw,Ib ", // 0xc8
+ "leave ", // 0xc9
+ "ret Iw far ", // 0xca
+ "ret far ", // 0xcb
+ "int 3 ", // 0xcc
+ "int Ib ", // 0xcd
+ "into ", // 0xce
+ "iret ", // 0xcf
+ "group2 Eb,1 ", // 0xd0
+ "group2 Ev,1 ", // 0xd1
+ "group2 Eb,CL ", // 0xd2
+ "group2 Ev,Cl ", // 0xd3
+ "aam ", // 0xd4
+ "aad ", // 0xd5
+ "illegal ", // 0xd6
+ "xlat ", // 0xd7
+ "illegal ", // 0xd8
+ "illegal ", // 0xd9
+ "illegal ", // 0xda
+ "illegal ", // 0xdb
+ "illegal ", // 0xdc
+ "illegal ", // 0xdd
+ "illegal ", // 0xde
+ "illegal ", // 0xdf
+ "loopnz ", // 0xe0
+ "loopz ", // 0xe1
+ "loop ", // 0xe2
+ "jcxz ", // 0xe3
+ "inb AL,Ib ", // 0xe4
+ "inw/d eAX,Ib ", // 0xe5
+ "outb Ib,AL ", // 0xe6
+ "outw/d Ib,eAX ", // 0xe7
+ "call Jv ", // 0xe8
+ "jmp Jv ", // 0xe9
+ "jmp Ap ", // 0xea
+ "jmp Jb ", // 0xeb
+ "inb AL,DX ", // 0xec
+ "inw/d Ib,DX ", // 0xed
+ "outb DX,AL ", // 0xee
+ "outw/d DX,eAX ", // 0xef
+ "lock: ", // 0xf0
+ "illegal ", // 0xf1
+ "repnz: ", // 0xf2
+ "repz: ", // 0xf3
+ "hlt ", // 0xf4
+ "cmc ", // 0xf5
+ "group3 Eb,? ", // 0xf6
+ "group3 Ev,? ", // 0xf7
+ "clc ", // 0xf8
+ "stc ", // 0xf9
+ "cli ", // 0xfa
+ "sti ", // 0xfb
+ "cld ", // 0xfc
+ "std ", // 0xfd
+ "group4 Eb ", // 0xfe
+ "group5 Ev " // 0xff
+};
+
+PCHAR XmOpcodeNameTable2[] = {
+ "group6 ", // 0x00
+ "group7 ", // 0x01
+ "lar ", // 0x02
+ "lsl ", // 0x03
+ "illegal ", // 0x04
+ "illegal ", // 0x05
+ "clts ", // 0x06
+ "illegal ", // 0x07
+ "illegal ", // 0x08
+ "illegal ", // 0x09
+ "illegal ", // 0x0a
+ "illegal ", // 0x0b
+ "illegal ", // 0x0c
+ "illegal ", // 0x0d
+ "illegal ", // 0x0e
+ "illegal ", // 0x0f
+ "illegal ", // 0x10
+ "illegal ", // 0x11
+ "illegal ", // 0x12
+ "illegal ", // 0x13
+ "illegal ", // 0x14
+ "illegal ", // 0x15
+ "illegal ", // 0x16
+ "illegal ", // 0x17
+ "illegal ", // 0x18
+ "illegal ", // 0x19
+ "illegal ", // 0x1a
+ "illegal ", // 0x1b
+ "illegal ", // 0x1c
+ "illegal ", // 0x1d
+ "illegal ", // 0x1e
+ "illegal ", // 0x1f
+ "mov Cd,Rd ", // 0x20
+ "mov Dd,Rd ", // 0x21
+ "mov Rd,Cd ", // 0x22
+ "mov Rd,Dd ", // 0x23
+ "mov Td,Rd ", // 0x24
+ "illegal ", // 0x25
+ "mov Rd,Td ", // 0x26
+ "illegal ", // 0x27
+ "illegal ", // 0x28
+ "illegal ", // 0x29
+ "illegal ", // 0x2a
+ "illegal ", // 0x2b
+ "illegal ", // 0x2c
+ "illegal ", // 0x2d
+ "illegal ", // 0x2e
+ "illegal ", // 0x2f
+ "illegal ", // 0x30
+ "illegal ", // 0x31
+ "illegal ", // 0x32
+ "illegal ", // 0x33
+ "illegal ", // 0x34
+ "illegal ", // 0x35
+ "illegal ", // 0x36
+ "illegal ", // 0x37
+ "illegal ", // 0x38
+ "illegal ", // 0x39
+ "illegal ", // 0x3a
+ "illegal ", // 0x3b
+ "illegal ", // 0x3c
+ "illegal ", // 0x3d
+ "illegal ", // 0x3e
+ "illegal ", // 0x3f
+ "illegal ", // 0x40
+ "illegal ", // 0x41
+ "illegal ", // 0x42
+ "illegal ", // 0x43
+ "illegal ", // 0x44
+ "illegal ", // 0x45
+ "illegal ", // 0x46
+ "illegal ", // 0x47
+ "illegal ", // 0x48
+ "illegal ", // 0x49
+ "illegal ", // 0x4a
+ "illegal ", // 0x4b
+ "illegal ", // 0x4c
+ "illegal ", // 0x4d
+ "illegal ", // 0x4e
+ "illegal ", // 0x4f
+ "illegal ", // 0x50
+ "illegal ", // 0x51
+ "illegal ", // 0x52
+ "illegal ", // 0x53
+ "illegal ", // 0x54
+ "illegal ", // 0x55
+ "illegal ", // 0x56
+ "illegal ", // 0x57
+ "illegal ", // 0x58
+ "illegal ", // 0x59
+ "illegal ", // 0x5a
+ "illegal ", // 0x5b
+ "illegal ", // 0x5c
+ "illegal ", // 0x5d
+ "illegal ", // 0x5e
+ "illegal ", // 0x5f
+ "illegal ", // 0x60
+ "illegal ", // 0x61
+ "illegal ", // 0x62
+ "illegal ", // 0x63
+ "illegal ", // 0x64
+ "illegal ", // 0x65
+ "illegal ", // 0x66
+ "illegal ", // 0x67
+ "illegal ", // 0x68
+ "illegal ", // 0x69
+ "illegal ", // 0x6a
+ "illegal ", // 0x6b
+ "illegal ", // 0x6c
+ "illegal ", // 0x6d
+ "illegal ", // 0x6e
+ "illegal ", // 0x6f
+ "illegal ", // 0x70
+ "illegal ", // 0x71
+ "illegal ", // 0x72
+ "illegal ", // 0x73
+ "illegal ", // 0x74
+ "illegal ", // 0x75
+ "illegal ", // 0x76
+ "illegal ", // 0x77
+ "illegal ", // 0x78
+ "illegal ", // 0x79
+ "illegal ", // 0x7a
+ "illegal ", // 0x7b
+ "illegal ", // 0x7c
+ "illegal ", // 0x7d
+ "illegal ", // 0x7e
+ "illegal ", // 0x7f
+ "jo Jv ", // 0x80
+ "jno Jv ", // 0x81
+ "jb Jv ", // 0x82
+ "jnb Jv ", // 0x83
+ "jz Jv ", // 0x84
+ "jnz Jv ", // 0x85
+ "jbe Jv ", // 0x86
+ "jnbe Jv ", // 0x87
+ "js Jv ", // 0x88
+ "jns Jv ", // 0x89
+ "jp Jv ", // 0x8a
+ "jnp Jv ", // 0x8b
+ "jl Jv ", // 0x8c
+ "jnl Jv ", // 0x8d
+ "jle Jv ", // 0x8e
+ "jnle Jv ", // 0x8f
+ "seto ", // 0x90
+ "setno ", // 0x91
+ "setb ", // 0x92
+ "setnb ", // 0x93
+ "setz ", // 0x94
+ "setnz ", // 0x95
+ "setbe ", // 0x96
+ "setnbe ", // 0x97
+ "sets ", // 0x98
+ "setns ", // 0x99
+ "setp ", // 0x9a
+ "setnp ", // 0x9b
+ "setl ", // 0x9c
+ "setnl ", // 0x9d
+ "setle ", // 0x9e
+ "setnle ", // 0x9f
+ "push FS ", // 0xa0
+ "pop FS ", // 0xa1
+ "illegal ", // 0xa2
+ "bt Ev,Gv ", // 0xa3
+ "shld Ev,Gv,Ib ", // 0xa4
+ "Shld Ev,Gv,vl ", // 0xa5
+ "illegal ", // 0xa6
+ "illegal ", // 0xa7
+ "push GS ", // 0xa8
+ "pop GS ", // 0xa9
+ "illegal ", // 0xaa
+ "bts Ev,Gv ", // 0xab
+ "shrd Ev,Gv,Ib ", // 0xac
+ "shrd Ev,Gv,cl ", // 0xad
+ "illegal ", // 0xae
+ "imul Gv,Ev ", // 0xaf
+ "cmpxchg Eb,Gv ", // 0xb0
+ "cmpxchg Ev,Gv ", // 0xb1
+ "lss Gv,Mp ", // 0xb2
+ "btr Ev,Gv ", // 0xb3
+ "lfs Gv,Mp ", // 0xb4
+ "lgs Gv,Mp ", // 0xb5
+ "movzb Gv,Eb ", // 0xb6
+ "movzw Gv,Ew ", // 0xb7
+ "illegal ", // 0xb8
+ "illegal ", // 0xb9
+ "group8 Ev,Ib ", // 0xba
+ "btc Ev,Gv ", // 0xbb
+ "bsf Gv,Ev ", // 0xbc
+ "bsr Gv,Ev ", // 0xbd
+ "movsb Gv,Eb ", // 0xbe
+ "movsw Gv,Ew ", // 0xbf
+ "xadd Eb,Gb ", // 0xc0
+ "xadd Ev,Gv ", // 0xc1
+ "illegal ", // 0xc2
+ "illegal ", // 0xc3
+ "illegal ", // 0xc4
+ "illegal ", // 0xc5
+ "illegal ", // 0xc6
+ "illegal ", // 0xc7
+ "bswap Gv ", // 0xc8
+ "illegal ", // 0xc9
+ "illegal ", // 0xca
+ "illegal ", // 0xcb
+ "illegal ", // 0xcc
+ "illegal ", // 0xcd
+ "illegal ", // 0xce
+ "illegal ", // 0xcf
+ "illegal ", // 0xd0
+ "illegal ", // 0xd1
+ "illegal ", // 0xd2
+ "illegal ", // 0xd3
+ "illegal ", // 0xd4
+ "illegal ", // 0xd5
+ "illegal ", // 0xd6
+ "illegal ", // 0xd7
+ "illegal ", // 0xd8
+ "illegal ", // 0xd9
+ "illegal ", // 0xda
+ "illegal ", // 0xdb
+ "illegal ", // 0xdc
+ "illegal ", // 0xdd
+ "illegal ", // 0xde
+ "illegal ", // 0xdf
+ "illegal ", // 0xe0
+ "illegal ", // 0xe1
+ "illegal ", // 0xe2
+ "illegal ", // 0xe3
+ "illegal ", // 0xe4
+ "illegal ", // 0xe5
+ "illegal ", // 0xe6
+ "illegal ", // 0xe7
+ "illegal ", // 0xe8
+ "illegal ", // 0xe9
+ "illegal ", // 0xea
+ "illegal ", // 0xeb
+ "illegal ", // 0xec
+ "illegal ", // 0xed
+ "illegal ", // 0xee
+ "illegal ", // 0xef
+ "illegal ", // 0xf0
+ "illegal ", // 0xf1
+ "illegal ", // 0xf2
+ "illegal ", // 0xf3
+ "illegal ", // 0xf4
+ "illegal ", // 0xf5
+ "illegal ", // 0xf6
+ "illegal ", // 0xf7
+ "illegal ", // 0xf8
+ "illegal ", // 0xf9
+ "illegal ", // 0xfa
+ "illegal ", // 0xfb
+ "illegal ", // 0xfc
+ "illegal ", // 0xfd
+ "illegal ", // 0xfe
+ "illegal " // 0xff
+};
+
+ULONG XmDebugFlags = 0x00; //0x7f;
+
+#endif
diff --git a/private/ntos/nthals/x86new/debug.c b/private/ntos/nthals/x86new/debug.c
new file mode 100644
index 000000000..dfc21083f
--- /dev/null
+++ b/private/ntos/nthals/x86new/debug.c
@@ -0,0 +1,443 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ debug.c
+
+Abstract:
+
+ This module implements utility functions.
+
+Author:
+
+ David N. Cutler (davec) 21-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+#if defined(XM_DEBUG)
+
+
+//
+// Define counter used to control flag tracing.
+//
+
+ULONG XmTraceCount = 0;
+
+VOID
+XmTraceDestination (
+ IN PRXM_CONTEXT P,
+ IN ULONG Destination
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces the destination value if the TRACE_OPERANDS
+ flag is set.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Result - Supplies the destination value to trace.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace result of operation.
+ //
+
+ if ((XmDebugFlags & TRACE_OPERANDS) != 0) {
+ if (P->DataType == BYTE_DATA) {
+ DEBUG_PRINT(("\n Dst - %02lx", Destination));
+
+ } else if (P->DataType == WORD_DATA) {
+ DEBUG_PRINT(("\n Dst - %04lx", Destination));
+
+ } else {
+ DEBUG_PRINT(("\n Dst - %08lx", Destination));
+ }
+ }
+
+ return;
+}
+
+VOID
+XmTraceFlags (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces the condition flags if the TRACE_FLAGS flag
+ is set.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace flags.
+ //
+
+ if ((XmDebugFlags & TRACE_OPERANDS) != 0) {
+ DEBUG_PRINT(("\n OF-%lx, DF-%lx, SF-%lx, ZF-%lx, AF-%lx, PF-%lx, CF-%lx",
+ (ULONG)P->Eflags.OF,
+ (ULONG)P->Eflags.DF,
+ (ULONG)P->Eflags.SF,
+ (ULONG)P->Eflags.ZF,
+ (ULONG)P->Eflags.AF,
+ (ULONG)P->Eflags.PF,
+ (ULONG)P->Eflags.CF));
+ }
+
+ //
+ // Increment the trace count and if the result is even, then put
+ // out a new line.
+ //
+
+ XmTraceCount += 1;
+ if (((XmTraceCount & 1) == 0) && (XmDebugFlags != 0)) {
+ DEBUG_PRINT(("\n"));
+ }
+
+ return;
+}
+
+VOID
+XmTraceJumps (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces jump operations if the TRACE_JUMPS flag is set.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace jumps.
+ //
+
+ if ((XmDebugFlags & TRACE_JUMPS) != 0) {
+ DEBUG_PRINT(("\n Jump to %04lx:%04lx",
+ (ULONG)P->SegmentRegister[CS],
+ (ULONG)P->Eip));
+ }
+
+ return;
+}
+
+VOID
+XmTraceInstruction (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN ULONG Instruction
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces instructions if the TRACE_OPERANDS flag is
+ set.
+
+Arguments:
+
+ DataType - Supplies the data type of the instruction value.
+
+ Instruction - Supplies the instruction value to trace.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace instruction stream of operation.
+ //
+
+ if ((XmDebugFlags & TRACE_OPERANDS) != 0) {
+ if (DataType == BYTE_DATA) {
+ DEBUG_PRINT(("%02lx ", Instruction));
+
+ } else if (DataType == WORD_DATA) {
+ DEBUG_PRINT(("%04lx ", Instruction));
+
+ } else {
+ DEBUG_PRINT(("%08lx ", Instruction));
+ }
+ }
+
+ return;
+}
+
+VOID
+XmTraceOverride (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces segment override prefixes.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PCHAR Name = "ECSDFG";
+ ULONG Segment;
+
+ //
+ // Trace segment override.
+ //
+
+ if ((XmDebugFlags & TRACE_OVERRIDE) != 0) {
+ Segment = P->DataSegment;
+ DEBUG_PRINT(("\n %cS:Selector - %04lx, Limit - %04lx",
+ (ULONG)Name[Segment],
+ (ULONG)P->SegmentRegister[Segment],
+ P->SegmentLimit[Segment]));
+ }
+
+ return;
+}
+
+VOID
+XmTraceRegisters (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces emulator registers.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace general register.
+ //
+
+ if ((XmDebugFlags & TRACE_GENERAL_REGISTERS) != 0) {
+ DEBUG_PRINT(("\n EAX-%08lx ECX-%08lx EDX-%08lx EBX-%08lx",
+ P->Gpr[EAX].Exx,
+ P->Gpr[ECX].Exx,
+ P->Gpr[EDX].Exx,
+ P->Gpr[EBX].Exx));
+
+ DEBUG_PRINT(("\n ESP-%08lx EBP-%08lx ESI-%08lx EDI-%08lx",
+ P->Gpr[ESP].Exx,
+ P->Gpr[EBP].Exx,
+ P->Gpr[ESI].Exx,
+ P->Gpr[EDI].Exx));
+
+ DEBUG_PRINT(("\n ES:%04lx CS:%04lx SS:%04lx DS:%04lx FS:%04lx GS:%04lx",
+ (ULONG)P->SegmentRegister[ES],
+ (ULONG)P->SegmentRegister[CS],
+ (ULONG)P->SegmentRegister[SS],
+ (ULONG)P->SegmentRegister[DS],
+ (ULONG)P->SegmentRegister[FS],
+ (ULONG)P->SegmentRegister[GS]));
+ }
+
+ return;
+}
+
+VOID
+XmTraceResult (
+ IN PRXM_CONTEXT P,
+ IN ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces the result value if the TRACE_OPERANDS
+ flag is set.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Result - Supplies the result value to trace.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace result of operation.
+ //
+
+ if ((XmDebugFlags & TRACE_OPERANDS) != 0) {
+ if (P->DataType == BYTE_DATA) {
+ DEBUG_PRINT(("\n Rsl - %02lx", Result));
+
+ } else if (P->DataType == WORD_DATA) {
+ DEBUG_PRINT(("\n Rsl - %04lx", Result));
+
+ } else {
+ DEBUG_PRINT(("\n Rsl - %08lx", Result));
+ }
+ }
+
+ return;
+}
+
+VOID
+XmTraceSpecifier (
+ IN UCHAR Specifier
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces the specifiern if the TRACE_OPERANDS flag is
+ set.
+
+Arguments:
+
+ Specifier - Supplies the specifier value to trace.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace instruction stream of operation.
+ //
+
+ if ((XmDebugFlags & TRACE_OPERANDS) != 0) {
+ DEBUG_PRINT(("%02lx ", Specifier));
+ if ((XmDebugFlags & TRACE_SPECIFIERS) != 0) {
+ DEBUG_PRINT(("(mod-%01lx reg-%01lx r/m-%01lx) ",
+ (Specifier >> 6) & 0x3,
+ (Specifier >> 3) & 0x7,
+ (Specifier >> 0) & 0x7));
+ }
+ }
+
+ return;
+}
+
+VOID
+XmTraceSource (
+ IN PRXM_CONTEXT P,
+ IN ULONG Source
+ )
+
+/*++
+
+Routine Description:
+
+ This function traces the source value if the TRACE_OPERANDS
+ flag is set.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Source - Supplies the source value to trace.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Trace result of operation.
+ //
+
+ if ((XmDebugFlags & TRACE_OPERANDS) != 0) {
+ if (P->DataType == BYTE_DATA) {
+ DEBUG_PRINT(("\n Src - %02lx", Source));
+
+ } else if (P->DataType == WORD_DATA) {
+ DEBUG_PRINT(("\n Src - %04lx", Source));
+
+ } else {
+ DEBUG_PRINT(("\n Src - %08lx", Source));
+ }
+ }
+
+ return;
+}
+
+#endif
diff --git a/private/ntos/nthals/x86new/divops.c b/private/ntos/nthals/x86new/divops.c
new file mode 100644
index 000000000..89b9c84b7
--- /dev/null
+++ b/private/ntos/nthals/x86new/divops.c
@@ -0,0 +1,182 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ mulops.c
+
+Abstract:
+
+ This module implements the code to emulate the div and idiv opcodes.
+
+Author:
+
+ David N. Cutler (davec) 21-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmDivOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an unsigned div opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UNALIGNED ULONG *DstHigh;
+ ULONG Dividend;
+ ULONG Divisor;
+ ULARGE_INTEGER Large;
+ ULONG Quotient;
+ ULONG Remainder;
+
+ //
+ // Divide the unsigned operands and store result.
+ //
+
+ Divisor = P->SrcValue.Long;
+ if (Divisor == 0) {
+ longjmp(&P->JumpBuffer[0], XM_DIVIDE_BY_ZERO);
+ }
+
+ if (P->DataType == BYTE_DATA) {
+ Dividend = (ULONG)P->Gpr[AX].Xx;
+ Quotient = Dividend / Divisor;
+ Remainder = Dividend % Divisor;
+ DstHigh = (UNALIGNED ULONG *)(&P->Gpr[AX].Xh);
+ Dividend >>= 8;
+
+ } else if (P->DataType == WORD_DATA) {
+ Dividend = (P->Gpr[DX].Xx << 16) | P->Gpr[AX].Xx;
+ Quotient = Dividend / Divisor;
+ Remainder = Dividend % Divisor;
+ DstHigh = (UNALIGNED ULONG *)(&P->Gpr[DX].Xx);
+ Dividend >>= 16;
+
+ } else {
+ Dividend = P->Gpr[EDX].Exx;
+ Large.HighPart = Dividend;
+ Large.LowPart = P->Gpr[EAX].Exx;
+ Quotient = (ULONG)(Large.QuadPart / (ULONGLONG)Divisor);
+ Remainder = (ULONG)(Large.QuadPart % (ULONGLONG)Divisor);
+ DstHigh = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
+ }
+
+ if (Dividend >= Divisor) {
+ longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
+ }
+
+ XmStoreResult(P, Quotient);
+ P->DstLong = DstHigh;
+ XmStoreResult(P, Remainder);
+ return;
+}
+
+VOID
+XmIdivOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a signed idiv opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UNALIGNED ULONG *DstHigh;
+ LONG Dividend;
+ LONG Divisor;
+ LARGE_INTEGER Large;
+ LONG Quotient;
+ LONG Remainder;
+ LARGE_INTEGER Result;
+
+ //
+ // Divide the signed operands and store result.
+ //
+
+ if (P->SrcValue.Long == 0) {
+ longjmp(&P->JumpBuffer[0], XM_DIVIDE_BY_ZERO);
+ }
+
+ if (P->DataType == BYTE_DATA) {
+ Divisor = (LONG)((SCHAR)P->SrcValue.Byte);
+ Dividend = (LONG)((SHORT)P->Gpr[AX].Xx);
+ Quotient = Dividend / Divisor;
+ Remainder = Dividend % Divisor;
+ DstHigh = (UNALIGNED ULONG *)(&P->Gpr[AX].Xh);
+ if ((Quotient >> 8) != ((Quotient << 24) >> 31)) {
+ longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
+ }
+
+ Quotient &= 0xff;
+ Remainder &= 0xff;
+
+ } else if (P->DataType == WORD_DATA) {
+ Divisor = (LONG)((SHORT)P->SrcValue.Word);
+ Dividend = (LONG)((P->Gpr[DX].Xx << 16) | P->Gpr[AX].Xx);
+ Quotient = Dividend / Divisor;
+ Remainder = Dividend % Divisor;
+ DstHigh = (UNALIGNED ULONG *)(&P->Gpr[DX].Xx);
+ if ((Quotient >> 16) != ((Quotient << 16) >> 31)) {
+ longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
+ }
+
+ Quotient &= 0xffff;
+ Remainder &= 0xfff;
+
+ } else {
+ Divisor = (LONG)(P->SrcValue.Long);
+ Large.HighPart = (LONG)P->Gpr[EDX].Exx;
+ Large.LowPart = P->Gpr[EAX].Exx;
+ Result.QuadPart = Large.QuadPart / (LONGLONG)Divisor;
+ Quotient = Result.LowPart;
+ Remainder = (LONG)(Large.QuadPart % (LONGLONG)Divisor);
+ DstHigh = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
+ if (Result.HighPart != ((LONG)Result.LowPart >> 31)) {
+ longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
+ }
+ }
+
+ XmStoreResult(P, Quotient);
+ P->DstLong = DstHigh;
+ XmStoreResult(P, Remainder);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/emulate.c b/private/ntos/nthals/x86new/emulate.c
new file mode 100644
index 000000000..2c840f19a
--- /dev/null
+++ b/private/ntos/nthals/x86new/emulate.c
@@ -0,0 +1,410 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ emulate.c
+
+Abstract:
+
+ This module implements an instruction level emulator for the execution
+ of x86 code. It is a complete 386/486 emulator, but only implements
+ real mode execution. Thus 32-bit addressing and operands are supported,
+ but paging and protected mode operations are not supported. The code is
+ written with the primary goals of being complete and small. Thus speed
+ of emulation is not important.
+
+Author:
+
+ David N. Cutler (davec) 2-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmInitializeEmulator (
+ IN USHORT StackSegment,
+ IN USHORT StackOffset,
+ IN PXM_READ_IO_SPACE ReadIoSpace,
+ IN PXM_WRITE_IO_SPACE WriteIoSpace,
+ IN PXM_TRANSLATE_ADDRESS TranslateAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the state of the x86 emulator.
+
+Arguments:
+
+ StackSegment - Supplies the stack segment value.
+
+ StackOffset - Supplies the stack offset value.
+
+ ReadIoSpace - Supplies a pointer to a the function that reads from
+ I/O space given a datatype and port number.
+
+ WriteIoSpace - Supplies a pointer to a function that writes to I/O
+ space given a datatype, port number, and value.
+
+ TranslateAddress - Supplies a pointer to the function that translates
+ segment/offset address pairs into a pointer to memory or I/O space.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LONG Index;
+ PRXM_CONTEXT P = &XmContext;
+ PULONG Vector;
+
+ //
+ // Clear the emulator context.
+ //
+
+ memset((PCHAR)P, 0, sizeof(XM_CONTEXT));
+
+ //
+ // Initialize the segment registers.
+ //
+
+ Index = GS;
+ do {
+ P->SegmentLimit[Index] = 0xffff;
+ Index -= 1;
+ } while (Index >= ES);
+
+ //
+ // Initialize the stack segment register and offset.
+ //
+
+ P->SegmentRegister[SS] = StackSegment;
+ P->Gpr[ESP].Exx = StackOffset;
+
+ //
+ // Set the address of the read I/O space, write I/O space, and translate
+ // functions.
+ //
+
+ P->ReadIoSpace = ReadIoSpace;
+ P->WriteIoSpace = WriteIoSpace;
+ P->TranslateAddress = TranslateAddress;
+
+ //
+ // Get address of interrupt vector table and initialize all vector to
+ // point to an iret instruction at location 0x500.
+ //
+ //
+ // N.B. It is assumed that the vector table is contiguous in emulated
+ // memory.
+ //
+
+ Vector = (PULONG)(P->TranslateAddress)(0, 0);
+ Vector[0x500 / 4] = 0x000000cf;
+ Index = 0;
+ do {
+ Vector[Index] = 0x00000500;
+ Index += 1;
+ } while (Index < 256);
+
+
+ XmEmulatorInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+XmEmulateFarCall (
+ IN USHORT Segment,
+ IN USHORT Offset,
+ IN OUT PXM86_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a far call by pushing a special exit
+ sequence on the stack and then starting instruction execution
+ at the address specified by the respective segment and offset.
+
+Arguments:
+
+ Segment - Supplies the segment in which to start execution.
+
+ Offset - Supplies the offset within the code segment to start
+ execution.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PRXM_CONTEXT P = &XmContext;
+ PUSHORT Stack;
+
+ //
+ // If the emulator has not been initialized, return an error.
+ //
+
+ if (XmEmulatorInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // Get address of current stack pointer, push exit markers, and
+ // update stack pointer.
+ //
+ // N.B. It is assumed that the stack pointer is within range and
+ // contiguous in emulated memory.
+ //
+
+ Stack = (PUSHORT)(P->TranslateAddress)(P->SegmentRegister[SS], P->Gpr[SP].Xx);
+ *--Stack = 0xffff;
+ *--Stack = 0xffff;
+ P->Gpr[SP].Xx -= 4;
+
+ //
+ // Emulate the specified instruction stream and return the final status.
+ //
+
+ return XmEmulateStream(&XmContext, Segment, Offset, Context);
+}
+
+XM_STATUS
+XmEmulateInterrupt (
+ IN UCHAR Interrupt,
+ IN OUT PXM86_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an interrrupt by pushing a special exit
+ sequence on the stack and then starting instruction execution
+ at the address specified by the respective interrupt vector.
+
+Arguments:
+
+ Interrupt - Supplies the number of the interrupt that is emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PRXM_CONTEXT P = &XmContext;
+ USHORT Segment;
+ USHORT Offset;
+ PUSHORT Stack;
+ PULONG Vector;
+
+ //
+ // If the emulator has not been initialized, return an error.
+ //
+
+ if (XmEmulatorInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // Get address of current stack pointer, push exit markers, and
+ // update stack pointer.
+ //
+ // N.B. It is assumed that the stack pointer is within range and
+ // contiguous in emulated memory.
+ //
+
+ Stack = (PUSHORT)(P->TranslateAddress)(P->SegmentRegister[SS], P->Gpr[SP].Xx);
+ *--Stack = 0;
+ *--Stack = 0xffff;
+ *--Stack = 0xffff;
+ P->Gpr[SP].Xx -= 6;
+
+ //
+ // Get address of interrupt vector table and set code segment and IP
+ // values.
+ //
+ //
+ // N.B. It is assumed that the vector table is contiguous in emulated
+ // memory.
+ //
+
+ Vector = (PULONG)(P->TranslateAddress)(0, 0);
+ Segment = (USHORT)(Vector[Interrupt] >> 16);
+ Offset = (USHORT)(Vector[Interrupt] & 0xffff);
+
+ //
+ // Emulate the specified instruction stream and return the final status.
+ //
+
+ return XmEmulateStream(&XmContext, Segment, Offset, Context);
+}
+
+XM_STATUS
+XmEmulateStream (
+ PRXM_CONTEXT P,
+ IN USHORT Segment,
+ IN USHORT Offset,
+ IN OUT PXM86_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function establishes the specfied context and emulates the
+ specified instruction stream until exit conditions are reached..
+
+Arguments:
+
+ Segment - Supplies the segment in which to start execution.
+
+ Offset - Supplies the offset within the code segment to start
+ execution.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // Set the x86 emulator registers from the specified context.
+ //
+
+ P->Gpr[EAX].Exx = Context->Eax;
+ P->Gpr[ECX].Exx = Context->Ecx;
+ P->Gpr[EDX].Exx = Context->Edx;
+ P->Gpr[EBX].Exx = Context->Ebx;
+ P->Gpr[EBP].Exx = Context->Ebp;
+ P->Gpr[ESI].Exx = Context->Esi;
+ P->Gpr[EDI].Exx = Context->Edi;
+
+ //
+ // Set the code segment, offset within segment, and emulate code.
+ //
+
+ P->SegmentRegister[CS] = Segment;
+ P->Eip = Offset;
+ if ((Status = setjmp(&P->JumpBuffer[0])) == 0) {
+
+ //
+ // Emulate x86 instruction stream.
+ //
+
+ do {
+
+ //
+ // Initialize instruction decode variables.
+ //
+
+ P->ComputeOffsetAddress = FALSE;
+ P->DataSegment = DS;
+ P->LockPrefixActive = FALSE;
+ P->OpaddrPrefixActive = FALSE;
+ P->OpsizePrefixActive = FALSE;
+ P->RepeatPrefixActive = FALSE;
+ P->SegmentPrefixActive = FALSE;
+ P->OpcodeControlTable = &XmOpcodeControlTable1[0];
+
+#if defined(XM_DEBUG)
+
+ P->OpcodeNameTable = &XmOpcodeNameTable1[0];
+
+#endif
+
+ //
+ // Get the next byte from the instruction stream and decode
+ // operands. If the byte is a prefix or an escape, then the
+ // next byte will be decoded. Decoding continues until an
+ // opcode byte is reached with a terminal decode condition.
+ //
+ // N.B. There is no checking for legitimate sequences of prefix
+ // and/or two byte opcode escapes. Redundant or invalid
+ // prefixes or two byte escape opcodes have no effect and
+ // are benign.
+ //
+
+ do {
+ P->CurrentOpcode = XmGetCodeByte(P);
+
+#if defined(XM_DEBUG)
+
+ if ((XmDebugFlags & TRACE_INSTRUCTIONS) != 0) {
+ DEBUG_PRINT(("\n%04lx %s %02lx ",
+ P->Eip - 1,
+ P->OpcodeNameTable[P->CurrentOpcode],
+ (ULONG)P->CurrentOpcode));
+ }
+
+#endif
+
+ P->OpcodeControl = P->OpcodeControlTable[P->CurrentOpcode];
+ P->FunctionIndex = P->OpcodeControl.FunctionIndex;
+ } while (XmOperandDecodeTable[P->OpcodeControl.FormatType](P) == FALSE);
+
+ //
+ // Emulate the instruction.
+ //
+
+ XmTraceFlags(P);
+ XmOpcodeFunctionTable[P->FunctionIndex](P);
+ XmTraceFlags(P);
+ XmTraceRegisters(P);
+
+#if defined(XM_DEBUG)
+
+ if ((XmDebugFlags & TRACE_SINGLE_STEP) != 0) {
+ DEBUG_PRINT(("\n"));
+ DbgBreakPoint();
+ }
+
+#endif
+
+ } while (TRUE);
+ }
+
+ //
+ // Set the x86 return context to the current emulator registers.
+ //
+
+ Context->Eax = P->Gpr[EAX].Exx;
+ Context->Ecx = P->Gpr[ECX].Exx;
+ Context->Edx = P->Gpr[EDX].Exx;
+ Context->Ebx = P->Gpr[EBX].Exx;
+ Context->Ebp = P->Gpr[EBP].Exx;
+ Context->Esi = P->Gpr[ESI].Exx;
+ Context->Edi = P->Gpr[EDI].Exx;
+ return Status;
+}
diff --git a/private/ntos/nthals/x86new/emulate.h b/private/ntos/nthals/x86new/emulate.h
new file mode 100644
index 000000000..1da024763
--- /dev/null
+++ b/private/ntos/nthals/x86new/emulate.h
@@ -0,0 +1,1614 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ emulate.h
+
+Abstract:
+
+ This module contains the private header file for the x86 bios
+ emulation.
+
+Author:
+
+ David N. Cutler (davec) 2-Sep-1994
+
+Revision History:
+
+--*/
+
+#ifndef _EMULATE_
+#define _EMULATE_
+
+#include "setjmp.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define debug tracing flags.
+//
+
+//#define XM_DEBUG 1 // ****** temp ******
+
+#define TRACE_INSTRUCTIONS 0x1
+#define TRACE_OPERANDS 0x2
+#define TRACE_GENERAL_REGISTERS 0x4
+#define TRACE_OVERRIDE 0x8
+#define TRACE_JUMPS 0x10
+#define TRACE_SPECIFIERS 0x20
+#define TRACE_SINGLE_STEP 0x40
+
+//
+// Define opcode function table indexes.
+//
+// N.B. This values must correspond exactly one for one with the function
+// table entries. If the C language had indexed initializers this
+// type would not be necessary.
+//
+
+typedef enum _XM_FUNCTION_TABLE_INDEX {
+
+ //
+ // ASCII operators.
+ //
+
+ X86_AAA_OP,
+ X86_AAD_OP,
+ X86_AAM_OP,
+ X86_AAS_OP,
+ X86_DAA_OP,
+ X86_DAS_OP,
+
+ //
+ // Group 1 operators.
+ //
+
+ X86_ADD_OP,
+ X86_OR_OP,
+ X86_ADC_OP,
+ X86_SBB_OP,
+ X86_AND_OP,
+ X86_SUB_OP,
+ X86_XOR_OP,
+ X86_CMP_OP,
+
+ //
+ // Group 2 operators.
+ //
+
+ X86_ROL_OP,
+ X86_ROR_OP,
+ X86_RCL_OP,
+ X86_RCR_OP,
+ X86_SHL_OP,
+ X86_SHR_OP,
+ X86_FILL0_OP,
+ X86_SAR_OP,
+
+ //
+ // Group 3 operators.
+ //
+
+ X86_TEST_OP,
+ X86_FILL1_OP,
+ X86_NOT_OP,
+ X86_NEG_OP,
+ X86_MUL_OP,
+ X86_IMULX_OP,
+ X86_DIV_OP,
+ X86_IDIV_OP,
+
+ //
+ // Group 4 and 5 operators.
+ //
+
+ X86_INC_OP,
+ X86_DEC_OP,
+ X86_CALL_OP,
+ X86_FILL2_OP,
+ X86_JMP_OP,
+ X86_FILL3_OP,
+ X86_PUSH_OP,
+ X86_FILL4_OP,
+
+ //
+ // Group 8 operators.
+ //
+
+ X86_BT_OP,
+ X86_BTS_OP,
+ X86_BTR_OP,
+ X86_BTC_OP,
+
+ //
+ // Stack push and pop operators.
+ //
+
+ X86_POP_OP,
+ X86_PUSHA_OP,
+ X86_POPA_OP,
+
+ //
+ // Jump operators.
+ //
+
+ X86_JXX_OP,
+ X86_LOOP_OP,
+ X86_JCXZ_OP,
+
+ //
+ // Control operators.
+ //
+
+ X86_ENTER_OP,
+ X86_HLT_OP,
+ X86_INT_OP,
+ X86_IRET_OP,
+ X86_LEAVE_OP,
+ X86_RET_OP,
+
+ //
+ // Set boolean byte value based on condition.
+ //
+
+ X86_SXX_OP,
+
+ //
+ // Condition code operators.
+ //
+
+ X86_CMC_OP,
+ X86_CLC_OP,
+ X86_STC_OP,
+ X86_CLI_OP,
+ X86_STI_OP,
+ X86_CLD_OP,
+ X86_STD_OP,
+ X86_LAHF_OP,
+ X86_SAHF_OP,
+
+ //
+ // General move operators.
+ //
+
+ X86_MOV_OP,
+ X86_XCHG_OP,
+
+ //
+ // Convert operations.
+ //
+
+ X86_CBW_OP,
+ X86_CWD_OP,
+
+ //
+ // Single multiply operator.
+ //
+
+ X86_IMUL_OP,
+
+ //
+ // String operators.
+ //
+
+ X86_CMPS_OP,
+ X86_INS_OP,
+ X86_LODS_OP,
+ X86_MOVS_OP,
+ X86_OUTS_OP,
+ X86_SCAS_OP,
+ X86_STOS_OP,
+
+ //
+ // Effective address operators.
+ //
+
+ X86_BOUND_OP,
+ X86_LEA_OP,
+
+ //
+ // Double shift operators.
+ //
+
+ X86_SHLD_OP,
+ X86_SHRD_OP,
+
+ //
+ // I/O operators.
+ //
+
+ X86_IN_OP,
+ X86_OUT_OP,
+
+ //
+ // Bit scan operators.
+ //
+
+ X86_BSF_OP,
+ X86_BSR_OP,
+
+ //
+ // Byte swap operators.
+ //
+
+ X86_BSWAP_OP,
+
+ //
+ // Add/compare and exchange operators.
+ //
+
+ X86_XADD_OP,
+ X86_CMPXCHG_OP,
+
+ //
+ // No operation.
+ //
+
+ X86_NOP_OP,
+
+ //
+ // Illegal opcode.
+ //
+
+ X86_ILL_OP,
+ X86_MAXIMUM_INDEX
+} XM_FUNCTION_TABLE_INDEX;
+
+//
+// Define 8-bit register numbers.
+//
+
+typedef enum _X86_8BIT_REGISTER {
+ AL,
+ CL,
+ DL,
+ BL,
+ AH,
+ CH,
+ DH,
+ BH
+} X86_8BIT_REGISTER;
+
+//
+// Define 16-bit register numbers.
+//
+
+typedef enum _X86_16BIT_REGISTER {
+ AX,
+ CX,
+ DX,
+ BX,
+ SP,
+ BP,
+ SI,
+ DI
+} X86_16BIT_REGISTER;
+
+//
+// Define 32-bit register numbers.
+//
+
+typedef enum _X86_32BIT_REGISTER {
+ EAX,
+ ECX,
+ EDX,
+ EBX,
+ ESP,
+ EBP,
+ ESI,
+ EDI
+} X86_32BIT_REGISTER;
+
+//
+// Define general register structure.
+//
+
+typedef union _X86_GENERAL_REGISTER {
+ ULONG Exx;
+ union {
+ USHORT Xx;
+ struct {
+ UCHAR Xl;
+ UCHAR Xh;
+ };
+ };
+} X86_GENERAL_REGISTER, *PX86_GENERAL_REGISTER;
+
+//
+// Define segment register numbers.
+//
+
+typedef enum _X86_SEGMENT_REGISTER {
+ ES,
+ CS,
+ SS,
+ DS,
+ FS,
+ GS
+} X86_SEGMENT_REGISTER;
+
+//
+// Define instruction format types.
+//
+
+typedef enum _XM_FORMAT_TYPE {
+
+ //
+ // N.B. These format codes MUST be the first codes and MUST be
+ // exactly in this order since the ordering corresponds to
+ // segment numbers.
+ //
+
+ FormatSegmentES,
+ FormatSegmentCS,
+ FormatSegmentSS,
+ FormatSegmentDS,
+ FormatSegmentFS,
+ FormatSegmentGS,
+
+ //
+ // N.B. These format codes MUST be the second codes and MUST be
+ // exactly in this order since the ordering corresponds to
+ // biased segment number. The entry for the code segment is
+ // a dummy entry to make the indexing work right.
+ //
+
+ FormatLoadSegmentES,
+ FormatLoadSegmentCS,
+ FormatLoadSegmentSS,
+ FormatLoadSegmentDS,
+ FormatLoadSegmentFS,
+ FormatLoadSegmentGS,
+
+ //
+ // The following codes can be in any order.
+ //
+
+ FormatGroup1General,
+ FormatGroup1Immediate,
+ FormatGroup2By1,
+ FormatGroup2ByCL,
+ FormatGroup2ByByte,
+ FormatGroup3General,
+ FormatGroup4General,
+ FormatGroup5General,
+ FormatGroup8BitOffset,
+ FormatOpcodeRegister,
+ FormatLongJump,
+ FormatShortJump,
+ FormatSetccByte,
+ FormatAccumImmediate,
+ FormatAccumRegister,
+ FormatMoveGeneral,
+ FormatMoveImmediate,
+ FormatMoveRegImmediate,
+ FormatSegmentOffset,
+ FormatMoveSegment,
+ FormatMoveXxGeneral,
+ FormatFlagsRegister,
+ FormatPushImmediate,
+ FormatPopGeneral,
+ FormatImulImmediate,
+ FormatStringOperands,
+ FormatEffectiveOffset,
+ FormatImmediateJump,
+ FormatImmediateEnter,
+ FormatGeneralBitOffset,
+ FormatShiftDouble,
+ FormatPortImmediate,
+ FormatPortDX,
+ FormatBitScanGeneral,
+ FormatByteImmediate,
+ FormatXlatOpcode,
+ FormatGeneralRegister,
+ FormatNoOperands,
+ FormatOpcodeEscape,
+ FormatPrefixOpcode
+} XM_FORMAT_TYPE;
+
+//
+// Defined opcode modifier bit masks.
+//
+
+#define WIDTH_BIT 0x1 // operand size control
+#define DIRECTION_BIT 0x2 // direction of operation
+#define SIGN_BIT 0x2 // sign extended byte
+
+//
+// Define prefix opcode function index values.
+//
+
+typedef enum _XM_PREFIX_FUNCTION_INDEX {
+ X86_ES_OP = ES,
+ X86_CS_OP = CS,
+ X86_SS_OP = SS,
+ X86_DS_OP = DS,
+ X86_FS_OP = FS,
+ X86_GS_OP = GS,
+ X86_LOCK_OP,
+ X86_ADSZ_OP,
+ X86_OPSZ_OP,
+ X86_REPZ_OP,
+ X86_REPNZ_OP
+} XM_PREFIX_FUNCTION_INDEX;
+
+//
+// Define two byte opcode escape.
+//
+
+#define TWO_BYTE_ESCAPE 0x0f
+
+//
+// Define opcode control table structure.
+//
+// This table controls the decoding of instructions and there operands.
+//
+
+typedef struct _OPCODE_CONTROL {
+ UCHAR FunctionIndex;
+ UCHAR FormatType;
+} OPCODE_CONTROL, *POPCODE_CONTROL;
+
+//
+// Define emulator context structure.
+//
+// This structure holds the global emulator state.
+//
+
+typedef struct _XM_CONTEXT {
+
+ //
+ // Pointers to the opcode control table and the opcode name table.
+ //
+
+ POPCODE_CONTROL OpcodeControlTable;
+ PCHAR *OpcodeNameTable;
+
+ //
+ // x86 extended flags register.
+ //
+
+ union {
+ UCHAR AhFlags;
+ USHORT Flags;
+ ULONG AllFlags;
+ struct {
+ ULONG CF : 1;
+ ULONG MBO : 1;
+ ULONG PF : 1;
+ ULONG SBZ0 : 1;
+ ULONG AF : 1;
+ ULONG SBZ1 : 1;
+ ULONG ZF : 1;
+ ULONG SF : 1;
+ ULONG TF : 1;
+ ULONG IF : 1;
+ ULONG DF : 1;
+ ULONG OF : 1;
+ ULONG IOPL : 2;
+ ULONG NT : 1;
+ ULONG SBZ2 : 1;
+ ULONG RF : 1;
+ ULONG VM : 1;
+ ULONG AC : 1;
+ ULONG SBZ3 : 13;
+ } Eflags;
+ };
+
+ //
+ // x86 instruction pointer.
+ //
+
+ union {
+ USHORT Ip;
+ ULONG Eip;
+ };
+
+ //
+ // x86 general registers.
+ //
+
+ X86_GENERAL_REGISTER Gpr[8];
+
+ //
+ // x86 segment registers.
+ //
+
+ USHORT SegmentRegister[6];
+
+ //
+ // Emulator segment descriptors.
+ //
+
+ USHORT SegmentLimit[6];
+
+ //
+ // Instruction opcode control information read from the opcode
+ // control table.
+ //
+
+ OPCODE_CONTROL OpcodeControl;
+
+ //
+ // Call or jmp destination segment segment.
+ //
+
+ USHORT DstSegment;
+
+ //
+ // Source and destination address and value.
+ //
+
+ union {
+ UCHAR UNALIGNED *DstByte;
+ USHORT UNALIGNED *DstWord;
+ ULONG UNALIGNED *DstLong;
+ };
+
+ union {
+ UCHAR UNALIGNED *SrcByte;
+ USHORT UNALIGNED *SrcWord;
+ ULONG UNALIGNED *SrcLong;
+ };
+
+ union {
+ UCHAR Byte;
+ ULONG Long;
+ USHORT Word;
+ } DstValue;
+
+ union {
+ UCHAR Byte;
+ ULONG Long;
+ USHORT Word;
+ } SrcValue;
+
+ //
+ // Current opcode, data segment register to be used to access
+ // data operands, function index, and operand data type, and
+ // effective address offset.
+ //
+
+ ULONG CurrentOpcode;
+ ULONG DataSegment;
+ ULONG DataType;
+ ULONG FunctionIndex;
+ ULONG Offset;
+
+ //
+ // Prefix control information.
+ //
+
+ BOOLEAN LockPrefixActive;
+ BOOLEAN OpaddrPrefixActive;
+ BOOLEAN OpsizePrefixActive;
+ BOOLEAN RepeatPrefixActive;
+ BOOLEAN SegmentPrefixActive;
+ UCHAR RepeatZflag;
+
+ //
+ // Effective address computation control.
+ //
+
+ BOOLEAN RegisterOffsetAddress;
+ BOOLEAN ComputeOffsetAddress;
+
+ //
+ // Shift count.
+ //
+
+ UCHAR Shift;
+
+ //
+ // Jump buffer.
+ //
+
+ _JBTYPE JumpBuffer[_JBLEN];
+
+ //
+ // Address of read I/O space, write I/O space, and translation address
+ // routines.
+ //
+
+ PXM_READ_IO_SPACE ReadIoSpace;
+ PXM_WRITE_IO_SPACE WriteIoSpace;
+ PXM_TRANSLATE_ADDRESS TranslateAddress;
+} XM_CONTEXT, *PXM_CONTEXT, *RESTRICTED_POINTER PRXM_CONTEXT;
+
+//
+// Define opcode function and decode operand types.
+//
+
+typedef
+ULONG
+(*POPERAND_DECODE) (
+ IN PRXM_CONTEXT P
+ );
+
+typedef
+VOID
+(*POPCODE_FUNCTION) (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Operand decode prototypes.
+//
+
+ULONG
+XmPushPopSegment (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmLoadSegment (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup1General (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup1Immediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup2By1 (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup2ByCL (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup2ByByte (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup3General (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup45General (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGroup8BitOffset (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmOpcodeRegister (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmLongJump (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmShortJump (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmSetccByte (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmAccumImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmAccumRegister (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmMoveGeneral (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmMoveImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmMoveRegImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmSegmentOffset (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmMoveSegment (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmMoveXxGeneral (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmFlagsRegister (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmPushImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmPopGeneral (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmImulImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmStringOperands (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmEffectiveOffset (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmImmediateJump (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmImmediateEnter (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGeneralBitOffset (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmShiftDouble (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmPortImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmPortDX (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmBitScanGeneral (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmByteImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmXlatOpcode (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGeneralRegister (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmOpcodeEscape (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmPrefixOpcode (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmNoOperands (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Define miscellaneous prototypes.
+//
+
+ULONG
+XmComputeParity (
+ IN ULONG Result
+ );
+
+XM_STATUS
+XmEmulateStream (
+ IN PRXM_CONTEXT P,
+ USHORT Segment,
+ USHORT Offset,
+ PXM86_CONTEXT Context
+ );
+
+UCHAR
+XmGetCodeByte (
+ IN PRXM_CONTEXT P
+ );
+
+UCHAR
+XmGetByteImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+USHORT
+XmGetByteImmediateToWord (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGetByteImmediateToLong (
+ IN PRXM_CONTEXT P
+ );
+
+USHORT
+XmGetSignedByteImmediateToWord (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGetSignedByteImmediateToLong (
+ IN PRXM_CONTEXT P
+ );
+
+USHORT
+XmGetWordImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmGetLongImmediate (
+ IN PRXM_CONTEXT P
+ );
+
+ULONG
+XmPopStack (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmPushStack (
+ IN PRXM_CONTEXT P,
+ IN ULONG Value
+ );
+
+VOID
+XmSetDataType (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmStoreResult (
+ IN PRXM_CONTEXT P,
+ IN ULONG Result
+ );
+
+//
+// Define operand specifier prototypes.
+//
+
+PVOID
+XmEvaluateAddressSpecifier (
+ IN PRXM_CONTEXT P,
+ OUT PLONG Register
+ );
+
+PVOID
+XmGetOffsetAddress (
+ IN PRXM_CONTEXT P,
+ IN ULONG Offset
+ );
+
+PVOID
+XmGetRegisterAddress (
+ IN PRXM_CONTEXT P,
+ IN ULONG Number
+ );
+
+PVOID
+XmGetStringAddress (
+ IN PRXM_CONTEXT P,
+ IN ULONG Segment,
+ IN ULONG Register
+ );
+
+VOID
+XmSetDestinationValue (
+ IN PRXM_CONTEXT P,
+ IN PVOID Destination
+ );
+
+VOID
+XmSetSourceValue (
+ IN PRXM_CONTEXT P,
+ IN PVOID Source
+ );
+
+ULONG
+XmGetImmediateSourceValue (
+ IN PRXM_CONTEXT P,
+ IN ULONG ByteFlag
+ );
+
+VOID
+XmSetImmediateSourceValue (
+ IN PRXM_CONTEXT P,
+ IN ULONG Source
+ );
+
+//
+// ASCII operators.
+//
+
+VOID
+XmAaaOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmAadOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmAamOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmAasOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmDaaOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmDasOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Group 1 operations.
+//
+
+VOID
+XmAddOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmOrOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmAdcOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmSbbOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmAndOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmSubOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmXorOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmCmpOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Group 2 operations.
+//
+
+VOID
+XmRolOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmRorOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmRclOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmRcrOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmShlOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmShrOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmSarOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Group 3 operations.
+//
+
+VOID
+XmTestOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmNotOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmNegOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmDivOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmIdivOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmImulOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmImulxOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmMulOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Group 4 and 5 operators.
+//
+
+VOID
+XmIncOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmDecOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmCallOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmJmpOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmPushOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Group 8 operators.
+//
+
+VOID
+XmBtOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmBtsOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmBtrOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmBtcOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Stack operations.
+//
+
+VOID
+XmPopOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmPushaOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmPopaOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Conditional jump and set conditional operations.
+//
+
+VOID
+XmJxxOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmLoopOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmJcxzOp (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmSxxOp (
+ IN PRXM_CONTEXT P
+ );
+
+//
+// Condition code operations.
+//
+
+VOID
+XmClcOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmCldOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmCliOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmCmcOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmStcOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmStdOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmStiOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmLahfOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmSahfOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// Move operations.
+//
+
+VOID
+XmMovOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmXchgOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// Convert operations.
+//
+
+VOID
+XmCbwOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmCwdOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// Control operations.
+//
+
+VOID
+XmEnterOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmHltOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmIntOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmIretOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmLeaveOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmRetOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// String operations.
+//
+
+VOID
+XmCmpsOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmInsOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmLodsOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmMovsOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmOutsOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmScasOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmStosOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// Shift double operators.
+//
+
+VOID
+XmShldOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmShrdOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// I/O operators.
+//
+
+VOID
+XmInOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmOutOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// Bit scan operators.
+//
+
+VOID
+XmBsfOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmBsrOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// MIscellaneous operations.
+//
+
+VOID
+XmXaddOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmBoundOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmBswapOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmCmpxchgOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmIllOp (
+ PRXM_CONTEXT P
+ );
+
+VOID
+XmNopOp (
+ PRXM_CONTEXT P
+ );
+
+//
+// PCI Bios emulation routines.
+//
+
+#if !defined(_PURE_EMULATION_)
+
+BOOLEAN
+XmExecuteInt1a (
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aPciBiosPresent(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aFindPciClassCode(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aFindPciDevice(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aGenerateSpecialCycle(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aGetRoutingOptions(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aSetPciIrq(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aReadConfigRegister(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+VOID
+XmInt1aWriteConfigRegister(
+ IN OUT PRXM_CONTEXT Context
+ );
+
+#endif
+
+//
+// Debug routines.
+//
+
+#if XM_DEBUG
+
+#include "stdio.h"
+//#define DEBUG_PRINT(_X_) DbgPrint _X_
+#define DEBUG_PRINT(_X_) printf _X_
+
+VOID
+XmTraceDestination (
+ IN PRXM_CONTEXT P,
+ IN ULONG Destination
+ );
+
+VOID
+XmTraceFlags (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmTraceInstruction (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN ULONG Instruction
+ );
+
+VOID
+XmTraceJumps (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmTraceOverride (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmTraceRegisters (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmTraceResult (
+ IN PRXM_CONTEXT P,
+ IN ULONG Result
+ );
+
+VOID
+XmTraceSpecifier (
+ IN UCHAR Specifier
+ );
+
+VOID
+XmTraceSource (
+ IN PRXM_CONTEXT P,
+ IN ULONG Source
+ );
+
+#else
+
+#define XmTraceDestination(P, Destination)
+#define XmTraceInstruction(DataType, Instruction)
+#define XmTraceFlags(P)
+#define XmTraceJumps(P)
+#define XmTraceOverride(P)
+#define XmTraceRegisters(P)
+#define XmTraceResult(P, Result)
+#define XmTraceSpecifier(Specifier)
+#define XmTraceSource(P, Source)
+
+#endif
+
+//
+// Define global data.
+//
+
+extern XM_CONTEXT XmContext;
+extern BOOLEAN XmEmulatorInitialized;
+extern OPCODE_CONTROL XmOpcodeControlTable1[];
+extern OPCODE_CONTROL XmOpcodeControlTable2[];
+extern POPCODE_FUNCTION XmOpcodeFunctionTable[];
+POPERAND_DECODE XmOperandDecodeTable[];
+
+#if !defined(_PURE_EMULATION)
+
+extern UCHAR XmNumberPciBusses;
+extern BOOLEAN XmPciBiosPresent;
+extern PGETSETPCIBUSDATA XmGetPciData;
+extern PGETSETPCIBUSDATA XmSetPciData;
+
+#endif
+
+#if XM_DEBUG
+
+extern ULONG XmDebugFlags;
+extern PCHAR XmOpcodeNameTable1[];
+extern PCHAR XmOpcodeNameTable2[];
+
+#endif
+
+#endif // _EMULATE_
diff --git a/private/ntos/nthals/x86new/i386/sources b/private/ntos/nthals/x86new/i386/sources
new file mode 100644
index 000000000..863ac5aef
--- /dev/null
+++ b/private/ntos/nthals/x86new/i386/sources
@@ -0,0 +1,24 @@
+I386_SOURCES=..\emulate.c \
+ ..\addops.c \
+ ..\asciiops.c \
+ ..\bitops.c \
+ ..\condops.c \
+ ..\ctrlops.c \
+ ..\data.c \
+ ..\debug.c \
+ ..\divops.c \
+ ..\inoutops.c \
+ ..\jmpops.c \
+ ..\logops.c \
+ ..\miscops.c \
+ ..\moveops.c \
+ ..\mulops.c \
+ ..\operand.c \
+ ..\pcibios.c \
+ ..\regmode.c \
+ ..\setops.c \
+ ..\shiftops.c \
+ ..\stackops.c \
+ ..\stringop.c \
+ ..\utility.c \
+ ..\x86bios.c
diff --git a/private/ntos/nthals/x86new/inoutops.c b/private/ntos/nthals/x86new/inoutops.c
new file mode 100644
index 000000000..14a46136d
--- /dev/null
+++ b/private/ntos/nthals/x86new/inoutops.c
@@ -0,0 +1,235 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ inoutops.c
+
+Abstract:
+
+ This module implements the code to emulate the in and out opcodes.
+
+Author:
+
+ David N. Cutler (davec) 7-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmInOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a inb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Check if the I/O port number is valid.
+ //
+
+ if ((P->SrcValue.Long + P->DataType) > 0xffff) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_PORT_NUMBER);
+ }
+
+ //
+ // Set the destination address, input from the specified port, and
+ // store the result.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
+ XmStoreResult(P, (P->ReadIoSpace)(P->DataType, P->SrcValue.Word));
+ return;
+}
+
+VOID
+XmInsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a insb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+ USHORT PortNumber;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Move items from the input port to the destination string.
+ //
+
+ PortNumber = P->SrcValue.Word;
+ while (Count != 0) {
+
+ //
+ // Set the destination address, input from the specified port, and
+ // store the result.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
+ XmStoreResult(P, (P->ReadIoSpace)(P->DataType, PortNumber));
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmOutOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a outb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ USHORT PortNumber;
+
+ //
+ // Check if the I/O port number is valid.
+ //
+
+ if ((P->SrcValue.Long + P->DataType) > 0xffff) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_PORT_NUMBER);
+ }
+
+ //
+ // Save the port number, get the source value, and output to the port.
+ //
+
+ PortNumber = P->SrcValue.Word;
+ XmSetSourceValue(P, &P->Gpr[EAX].Exx);
+ (P->WriteIoSpace)(P->DataType, PortNumber, P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmOutsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a outsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+ USHORT PortNumber;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Move items from the source string to the output port.
+ //
+
+ PortNumber = P->SrcValue.Word;
+ while (Count != 0) {
+
+ //
+ // Set the source value and output to the specified port.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ (P->WriteIoSpace)(P->DataType, PortNumber, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/x86new/jmpops.c b/private/ntos/nthals/x86new/jmpops.c
new file mode 100644
index 000000000..abb261865
--- /dev/null
+++ b/private/ntos/nthals/x86new/jmpops.c
@@ -0,0 +1,290 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ jmpops.c
+
+Abstract:
+
+ This module implements the code to emulate jump opcodes.
+
+Author:
+
+ David N. Cutler (davec) 13-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmJcxzOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a jcxz instruction.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Condition;
+
+ //
+ // If eCX is zero, then set the new IP value.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ Condition = P->Gpr[ECX].Exx;
+
+ } else {
+ Condition = P->Gpr[CX].Xx;
+ }
+
+ if (Condition == 0) {
+ P->Eip = P->DstValue.Word;
+ XmTraceJumps(P);
+ }
+
+ return;
+}
+
+VOID
+XmJmpOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a jmp near relative instruction.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the destination segment, if required, and set the new IP.
+ //
+
+ P->Eip = P->DstValue.Long;
+ if ((P->CurrentOpcode == 0xea) || (P->FunctionIndex != X86_JMP_OP)) {
+ P->SegmentRegister[CS] = P->DstSegment;
+ }
+
+ XmTraceJumps(P);
+ return;
+}
+
+VOID
+XmJxxOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates conditional jump instructions.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Complement;
+ ULONG Condition;
+
+ //
+ // Case on the jump control value.
+ //
+
+ Complement = P->SrcValue.Long & 1;
+ switch (P->SrcValue.Long >> 1) {
+
+ //
+ // Jump if overflow/not overflow.
+ //
+
+ case 0:
+ Condition = P->Eflags.OF;
+ break;
+
+ //
+ // Jump if below/not below.
+ //
+
+ case 1:
+ Condition = P->Eflags.CF;
+ break;
+
+ //
+ // Jump if zero/not zero.
+ //
+
+ case 2:
+ Condition = P->Eflags.ZF;
+ break;
+
+ //
+ // Jump if below or equal/not below or equal.
+ //
+
+ case 3:
+ Condition = P->Eflags.CF | P->Eflags.ZF;
+ break;
+
+ //
+ // Jump if signed/not signed.
+ //
+
+ case 4:
+ Condition = P->Eflags.SF;
+ break;
+
+ //
+ // Jump if parity/not parity.
+ //
+
+ case 5:
+ Condition = P->Eflags.PF;
+ break;
+
+ //
+ // Jump if less/not less.
+ //
+
+ case 6:
+ Condition = (P->Eflags.SF ^ P->Eflags.OF);
+ break;
+
+ //
+ // Jump if less or equal/not less or equal.
+ //
+
+ case 7:
+ Condition = (P->Eflags.SF ^ P->Eflags.OF) | P->Eflags.ZF;
+ break;
+ }
+
+ //
+ // If the specified condition is met, then set the new IP value.
+ //
+
+ if ((Condition ^ Complement) != 0) {
+ P->Eip = P->DstValue.Word;
+ XmTraceJumps(P);
+ }
+
+ return;
+}
+
+VOID
+XmLoopOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates loop, loopz, or a loopnz instructions.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Condition;
+ ULONG Result;
+ ULONG Type;
+
+ //
+ // Set the address of the destination and compute the result value.
+ //
+
+ Result = P->Gpr[ECX].Exx - 1;
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[ECX].Exx);
+ if (P->OpaddrPrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ Result &= 0xffff;
+ }
+
+ XmStoreResult(P, Result);
+
+ //
+ // Isolate the loop type and test the appropriate condition.
+ //
+ // Type 0 - loopnz
+ // 1 - loopz
+ // 2 - loop
+ //
+
+ Type = P->CurrentOpcode & 3;
+ if (Type == 0) {
+ Condition = P->Eflags.ZF ^ 1;
+
+ } else if (Type == 1) {
+ Condition = P->Eflags.ZF;
+
+ } else {
+ Condition = TRUE;
+ }
+
+ //
+ // If the loop condition is met, then set the new IP value.
+ //
+
+ if ((Condition != FALSE) && (Result != 0)) {
+ P->Eip = P->DstValue.Word;
+ XmTraceJumps(P);
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/x86new/logops.c b/private/ntos/nthals/x86new/logops.c
new file mode 100644
index 000000000..24072ccc6
--- /dev/null
+++ b/private/ntos/nthals/x86new/logops.c
@@ -0,0 +1,247 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ logops.c
+
+Abstract:
+
+ This module implements the code to emulate the and, or, test, xor,
+ and not opcodes.
+
+Author:
+
+ David N. Cutler (davec) 12-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+XmSetLogicalResult (
+ IN PRXM_CONTEXT P,
+ IN ULONG Result
+ );
+
+VOID
+XmAndOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an and opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // And operands and store result.
+ //
+
+ XmSetLogicalResult(P, P->DstValue.Long & P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmOrOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an or opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Or operands and store result.
+ //
+
+ XmSetLogicalResult(P, P->DstValue.Long | P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmTestOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a test opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // And operands but don't store result.
+ //
+
+ XmSetLogicalResult(P, P->DstValue.Long & P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmXorOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a xor opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Xor operands and store result.
+ //
+
+ XmSetLogicalResult(P, P->DstValue.Long ^ P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmNotOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a not opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Mask;
+ ULONG Shift;
+
+ //
+ // Complement operand and store result.
+ //
+
+ Shift = Shift = ((P->DataType + 1) << 3) - 1;
+ Mask = ((1 << Shift) - 1) | (1 << Shift);
+ XmStoreResult(P, ~P->DstValue.Long & Mask);
+ return;
+}
+
+VOID
+XmSetLogicalResult (
+ IN PRXM_CONTEXT P,
+ IN ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function conditionally stores the result of a logical operation
+ and computes the resultant condtion codes.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+ Result - Supplies the result value (note that the result is always
+ zero extended to a long with no carry bits into the zero extended
+ part).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Shift;
+
+ //
+ // Store the result and compute auxilary carry flag, parity flag, sign
+ // and zero flags.
+ //
+
+ if (P->FunctionIndex != X86_TEST_OP) {
+ XmStoreResult(P, Result);
+ }
+
+ Shift = Shift = ((P->DataType + 1) << 3) - 1;
+ P->Eflags.CF = 0;
+ P->Eflags.PF = XmComputeParity(Result);
+ P->Eflags.AF = 0;
+ P->Eflags.ZF = (Result == 0);
+ P->Eflags.SF = Result >> Shift;
+ P->Eflags.OF = 0;
+ return;
+}
diff --git a/private/ntos/nthals/x86new/main.c b/private/ntos/nthals/x86new/main.c
new file mode 100644
index 000000000..cfadd66cb
--- /dev/null
+++ b/private/ntos/nthals/x86new/main.c
@@ -0,0 +1,1499 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86test.c
+
+Abstract:
+
+ This module implements a series of tests for the x86 ROM Bios emulator.
+
+Author:
+
+ David N. Cutler (davec) 13-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "stdio.h"
+#include "string.h"
+#include "memory.h"
+#include "emulate.h"
+
+//
+// Define global instruction execution data.
+//
+
+UCHAR CodeStream[] = {0xeb, 0x07, // jmp .+7
+ 0xc3, // ret (near)
+ 0xcb, // ret (far)
+ 0x66, 0xc3, // ret (near)
+ 0x66, 0xcb, // ret (far)
+ 0xcf, // iret
+ 0xe9, 0x00, 0x00, // jmp .+1
+ 0x66, 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp .+1
+ 0xea, 0x17, 0x00, 0x00, 0x20, // jmp 0x0017:0x2000
+ 0x66, 0xea, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x20, // jmp 0x0000001f:0x2000
+ 0x66, 0xb8, 0x2e, 0x00, 0x00, 0x20, // mov eax, 0x2000002e
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0xff, 0x26, 0x04, 0x00, // jmp ds:0x0004
+ 0x66, 0xb8, 0x3d, 0x00, 0x00, 0x20, // mov eax, 0x2000003d
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0xff, 0x2e, 0x04, 0x00, // jmp ds:0x0004
+ 0x9b, // wait (nop)
+/* 0x00, 0xc0, // add al, al
+ 0x00, 0xc9, // add cl, cl
+ 0x00, 0xd2, // add dl, dl
+ 0x00, 0xdb, // add bl, bl
+ 0x00, 0xe4, // add ah, ah
+ 0x00, 0xed, // add ch, ch
+ 0x00, 0xf6, // add dh, dh
+ 0x00, 0xff, // add bh, bh
+ 0x01, 0xc0, // add ax, ax
+ 0x01, 0xc9, // add cx, cx
+ 0x01, 0xd2, // add dx, dx
+ 0x01, 0xdb, // add bx, bx
+ 0x01, 0xed, // add bp, bp
+ 0x01, 0xf6, // add si, si
+ 0x01, 0xff, // add di, di
+ 0x66, 0x01, 0xc0, // add eax, eax
+ 0x66, 0x01, 0xc9, // add ecx, ecx
+ 0x66, 0x01, 0xd2, // add edx, edx
+ 0x66, 0x01, 0xdb, // add ebx, ebx
+ 0x66, 0x01, 0xed, // add ebp, ebp
+ 0x66, 0x01, 0xf6, // add esi, esi
+ 0x66, 0x01, 0xff, // add edi, edi
+ 0x66, 0x31, 0xc0, // xor eax, eax
+ 0x66, 0x31, 0xc9, // xor ecx, ecx
+ 0x66, 0x31, 0xd2, // xor edx, edx
+ 0x66, 0x31, 0xdb, // xor ebx, ebx
+ 0x66, 0x31, 0xed, // xor ebp, ebp
+ 0x66, 0x31, 0xf6, // xor esi, esi
+ 0x66, 0x31, 0xff, // xor edi, edi
+ 0x04, 0xf0, // add al, 0xf0
+ 0x41, // inc CX
+ 0x41, // inc CX
+ 0xc0, 0xc0, 0x05, // rol al, 0x05
+ 0xd0, 0xc0, // rol al, 1
+ 0xd2, 0xc0, // rol al, CL
+ 0x05, 0x0f, 0x00, // add ax, 0x000f
+ 0xc1, 0xc0, 0x0d, // rol ax, 0x0d
+ 0xd1, 0xc0, // rol ax, 1
+ 0xd3, 0xc0, // rol ax, CL
+ 0x05, 0x00, 0xff, // add ax, 0xff00
+ 0x66, 0xc1, 0xc0, 0x1d, // rol eax, 0x1d
+ 0x66, 0xd1, 0xc0, // rol eax, 1
+ 0x66, 0xd3, 0xc0, // rol eax, CL
+ 0xf8, // clc
+ 0xf9, // stc
+ 0xf8, // clc
+ 0xf5, // cmc
+ 0xf5, // cmc
+ 0xfa, // cli
+ 0xfb, // sti
+ 0xfc, // cld
+ 0xfd, // std
+ 0xfc, // cld
+ 0x66, 0x31, 0xc0, // xor eax, eax
+ 0x66, 0x31, 0xc9, // xor ecx, ecx
+ 0x66, 0x31, 0xd2, // xor edx, edx
+ 0x66, 0x31, 0xdb, // xor ebx, ebx
+ 0x66, 0x31, 0xed, // xor ebp, ebp
+ 0x66, 0x31, 0xf6, // xor esi, esi
+ 0x66, 0x31, 0xff, // xor edi, edi
+ 0x66, 0x05, 0xf0, 0x3c, 0x0f, 0x0f, // add eax, 0x0f0f3cf0
+ 0x66, 0x89, 0xc2, // mov edx,eax
+ 0x31, 0xd2, // xor dx, dx
+ 0x88, 0xc3, // mov bl, al
+ 0x88, 0xe7, // mov bh, ah
+ 0x89, 0xda, // mov dx, bx
+ 0x66, 0x89, 0xc6, // mov esi, eax
+ 0x66, 0x31, 0xc0, // xor eax, eax
+ 0x66, 0x8b, 0xc6, // mov eax, esi
+ 0x66, 0x31, 0xc0, // xor eax, eax
+ 0x66, 0x31, 0xc9, // xor ecx, ecx
+ 0x66, 0x31, 0xd2, // xor edx, edx
+ 0x66, 0x31, 0xdb, // xor ebx, ebx
+ 0x66, 0x31, 0xed, // xor ebp, ebp
+ 0x66, 0x31, 0xf6, // xor esi, esi
+ 0x66, 0x31, 0xff, // xor edi, edi
+ 0x66, 0xb8, 0x11, 0x11, 0x11, 0x11, // mov EAX, 0x11111111
+ 0x66, 0xb9, 0x22, 0x22, 0x22, 0x22, // mov ECX, 0x22222222
+ 0x66, 0xba, 0x33, 0x33, 0x33, 0x33, // mov EDX, 0x33333333
+ 0x66, 0xbb, 0x44, 0x44, 0x44, 0x44, // mov EBX, 0x44444444
+ 0x66, 0xbd, 0x66, 0x66, 0x66, 0x66, // mov EBP, 0x66666666
+ 0x66, 0xbe, 0x77, 0x77, 0x77, 0x77, // mov ESI, 0x77777777
+ 0x66, 0xbf, 0x88, 0x88, 0x88, 0x88, // mov EDI, 0x88888888
+ 0xb8, 0x08, 0x01, // mov AX, 0x0108
+ 0xb9, 0x09, 0x02, // mov CX, 0x0209
+ 0xba, 0x0a, 0x03, // mov DX, 0x030a
+ 0xbb, 0x0b, 0x04, // mov BX, 0x040b
+ 0xbd, 0x0d, 0x06, // mov BP, 0x060d
+ 0xbe, 0x0e, 0x07, // mov SI, 0x070e
+ 0xbf, 0x0f, 0x08, // mov DI, 0x080f
+ 0xb0, 0x01, // mov al, 0x01
+ 0xb1, 0x02, // mov cl, 0x02
+ 0xb2, 0x03, // mov dl, 0x03
+ 0xb3, 0x04, // mov bl, 0x04
+ 0xb4, 0x05, // mov ah, 0x05
+ 0xb5, 0x06, // mov ch, 0x06
+ 0xb6, 0x07, // mov dh, 0x07
+ 0xb7, 0x08, // mov bh, 0x08
+ 0x91, // xchg cx, ax
+ 0x92, // xchg dx, ax
+ 0x93, // xchg bx, ax
+ 0x95, // xchg bp, ax
+ 0x96, // xchg si, ax
+ 0x97, // xchg di, ax
+ 0x66, 0x91, // xchg ecx, eax
+ 0x66, 0x92, // xchg edx, eax
+ 0x66, 0x93, // xchg ebx, eax
+ 0x66, 0x95, // xchg ebp, eax
+ 0x66, 0x96, // xchg esi, eax
+ 0x66, 0x97, // xchg edi, eax
+ 0x86, 0xd9, // xchg bl, cl
+ 0x87, 0xd9, // xchg bx, cx
+ 0x66, 0x87, 0xd9, // xchg ebx, ecx
+ 0xb0, 0x7f, // mov al, 0x7f
+ 0x98, // cbw
+ 0xb0, 0x83, // mov al, 0x83
+ 0x98, // cbw
+ 0xb8, 0x01, 0x08, // mov AX, 0x0801
+ 0x99, // cwd
+ 0xb8, 0x01, 0x80, // mov AX, 0x8001
+ 0x99, // cwd
+ 0xb4, 0xfd, // mov ah, 0xfd
+ 0x9e, // sahf
+ 0xb4, 0x77, // mov ah, 0x77
+ 0x9f, // lahf
+ 0xc6, 0xc0, 0xed, // mov al, 0xed
+ 0xc6, 0xc4, 0xde, // mov ah, 0xde
+ 0xc7, 0xc0, 0xcc, 0xdd, // mov ax, 0xddcc
+ 0x66, 0xc7, 0xc0, 0xdd, 0xcc, 0xbb, 0xaa, // mov eax, 0xaabbccdd
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x90, 0xc0, // seto al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x91, 0xc0, // setno al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x92, 0xc0, // setb al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x93, 0xc0, // setnb al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x94, 0xc0, // setz al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x95, 0xc0, // setnz al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x96, 0xc0, // setbe al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x97, 0xc0, // setnbe al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x98, 0xc0, // sets al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x99, 0xc0, // setns al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x9a, 0xc0, // setp al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x9b, 0xc0, // setnp al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x9c, 0xc0, // setl al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x9d, 0xc0, // setnl al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x9e, 0xc0, // setle al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x9f, 0xc0, // setnle al
+ 0x66, 0xb8, 0xfe, 0xff, 0x01, 0x00, // mov eax, 0x0001fffe
+ 0x40, // inc ax
+ 0x66, 0x40, // inc eax
+ 0x66, 0x48, // dec eax
+ 0x48, // dec ax
+ 0x66, 0xb9, 0xfe, 0xff, 0x01, 0x00, // mov ecx, 0x0001fffe
+ 0x41, // inc cx
+ 0x66, 0x41, // inc ecx
+ 0x66, 0x49, // dec ecxx
+ 0x49, // dec cx
+ 0x66, 0xba, 0xfe, 0xff, 0x01, 0x00, // mov edx, 0x0001fffe
+ 0x42, // inc dx
+ 0x66, 0x42, // inc edx
+ 0x66, 0x4a, // dec edx
+ 0x4a, // dec dx
+ 0x66, 0xbb, 0xfe, 0xff, 0x01, 0x00, // mov ebx, 0x0001fffe
+ 0x43, // inc bx
+ 0x66, 0x43, // inc ebx
+ 0x66, 0x4b, // dec ebx
+ 0x4b, // dec bx
+ 0x66, 0xbd, 0xfe, 0xff, 0x01, 0x00, // mov ebp, 0x0001fffe
+ 0x45, // inc bp
+ 0x66, 0x45, // inc ebp
+ 0x66, 0x4d, // dec ebp
+ 0x4d, // dec bp
+ 0x66, 0xbe, 0xfe, 0xff, 0x01, 0x00, // mov esi, 0x0001fffe
+ 0x46, // inc si
+ 0x66, 0x46, // inc esi
+ 0x66, 0x4e, // dec esix
+ 0x4e, // dec si
+ 0x66, 0xbf, 0xfe, 0xff, 0x01, 0x00, // mov edi, 0x0001fffe
+ 0x47, // inc di
+ 0x66, 0x47, // inc edi
+ 0x66, 0x4f, // dec edix
+ 0x4f, // dec di
+ 0x26, 0x90, // ES: nop
+ 0x2e, 0x90, // CS: nop
+ 0x36, 0x90, // SS: nop
+ 0x3e, 0x90, // DS: nop
+ 0x64, 0x90, // FS: nop
+ 0x65, 0x90, // GS: nop
+ 0xb8, 0xb8, 0xb8, // mov ax, 0xb8b8
+ 0xb9, 0xb9, 0xb9, // mov cx, 0xb9b9
+ 0xba, 0xba, 0xba, // mov dx, 0xbaba
+ 0xbb, 0xbb, 0xbb, // mov bx, 0xbbbb
+ 0xbd, 0xbd, 0xbd, // mov bp, 0xbdbd
+ 0xbe, 0xbe, 0xbe, // mov si, 0xbebe
+ 0xbf, 0xbf, 0xbf, // mov di, 0xbfbf
+ 0x66, 0x50, // push eax
+ 0x66, 0x51, // push ecx
+ 0x66, 0x52, // push edx
+ 0x66, 0x53, // push ebx
+ 0x66, 0x54, // push esp
+ 0x66, 0x55, // push ebp
+ 0x66, 0x56, // push esi
+ 0x66, 0x57, // push edi
+ 0x50, // push ax
+ 0x51, // push cx
+ 0x52, // push dx
+ 0x53, // push bx
+ 0x54, // push sp
+ 0x55, // push bp
+ 0x56, // push si
+ 0x57, // push di
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0xb9, 0x00, 0x00, // mov cx, 0x0000
+ 0xba, 0x00, 0x00, // mov dx, 0x0000
+ 0xbb, 0x00, 0x00, // mov bx, 0x0000
+ 0xbd, 0x00, 0x00, // mov bp, 0x0000
+ 0xbe, 0x00, 0x00, // mov si, 0x0000
+ 0xbf, 0x00, 0x00, // mov di, 0x0000
+ 0x5f, // pop di
+ 0x5e, // pop si
+ 0x5d, // pop bp
+ 0x5c, // pop sp
+ 0x5b, // pop bx
+ 0x5a, // pop dx
+ 0x59, // pop cx
+ 0x58, // pop ax
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0xb9, 0x00, 0x00, // mov cx, 0x0000
+ 0xba, 0x00, 0x00, // mov dx, 0x0000
+ 0xbb, 0x00, 0x00, // mov bx, 0x0000
+ 0xbd, 0x00, 0x00, // mov bp, 0x0000
+ 0xbe, 0x00, 0x00, // mov si, 0x0000
+ 0xbf, 0x00, 0x00, // mov di, 0x0000
+ 0x66, 0x5f, // pop edi
+ 0x66, 0x5e, // pop esi
+ 0x66, 0x5d, // pop ebp
+ 0x66, 0x5c, // pop esp
+ 0x66, 0x5b, // pop ebx
+ 0x66, 0x5a, // pop edx
+ 0x66, 0x59, // pop ecx
+ 0x66, 0x58, // pop eax
+ 0x06, // push ES
+ 0x0e, // push CS
+ 0x16, // push SS
+ 0x1e, // push DS
+ 0x0f, 0xa0, // push FS
+ 0x0f, 0xa8, // push GS
+ 0x0f, 0xa9, // pop GS
+ 0x0f, 0xa1, // pop FS
+ 0x1f, // pop DS
+ 0x17, // pop SS
+ 0x58, // pop ax
+ 0x07, // pop ES
+ 0x90, // nop
+ 0xb0, 0x81, // mov al, 0x81
+ 0xb1, 0xff, // mov cl, 0xff
+ 0x20, 0xc1, // and cl, al
+ 0xb0, 0x55, // mov al, 0x55
+ 0xb1, 0xff, // mov cl, 0xff
+ 0x20, 0xc1, // and cl, al
+ 0xb0, 0x81, // mov al, 0x81
+ 0xb1, 0x7e, // mov cl, 0x7e
+ 0x20, 0xc1, // and cl, al
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xb9, 0xff, 0xff, // mov cx, 0xffff
+ 0x21, 0xc1, // and cx, ax
+ 0xb8, 0x55, 0x55, // mov ax, 0x5555
+ 0xb9, 0xff, 0xff, // mov cx, 0xffff
+ 0x21, 0xc1, // and cx, ax
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xb9, 0x7e, 0x7e, // mov cx, 0x7e7e
+ 0x21, 0xc1, // and cx, ax
+ 0x66, 0xb8, 0x80, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xb9, 0xff, 0xff, 0xff, 0xff, // mov ecx, 0xffffffff
+ 0x66, 0x21, 0xc1, // and ecx, eax
+ 0x66, 0xb8, 0x55, 0x55, 0x55, 0x55, // mov eax, 0x55555555
+ 0x66, 0xb9, 0xff, 0xff, 0xff, 0xff, // mov ecx, 0xffffffff
+ 0x66, 0x21, 0xc1, // and ecx, eax
+ 0x66, 0xb8, 0x81, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xb9, 0x7e, 0x7e, 0x7e, 0x7e, // mov ecx, 0x7e7e7e7e
+ 0x66, 0x21, 0xc1, // and ecx, eax
+ 0xb1, 0x80, // mov cl, 0x80
+ 0x80, 0xe1, 0xff, // and cl, 0xff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x81, 0xe1, 0xff, 0xff, // and cx, 0xffff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x81, 0xe1, 0xff, 0xff, 0xff, 0xff, // and ecx, 0xffffffff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x83, 0xe1, 0x7f, // and cx, (sign)0xff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x83, 0xe1, 0x7f, // and ecx, (sign)0xff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x83, 0xe1, 0xf7, // and cx, (sign)0xff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x83, 0xe1, 0xf7, // and ecx, (sign)0xff
+ 0xb0, 0x81, // mov al, 0x81
+ 0xb1, 0xff, // mov cl, 0xff
+ 0x08, 0xc1, // or cl, al
+ 0xb0, 0x55, // mov al, 0x55
+ 0xb1, 0xff, // mov cl, 0xff
+ 0x08, 0xc1, // or cl, al
+ 0xb0, 0x81, // mov al, 0x81
+ 0xb1, 0x7e, // mov cl, 0x7e
+ 0x08, 0xc1, // or cl, al
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xb9, 0xff, 0xff, // mov cx, 0xffff
+ 0x09, 0xc1, // or cx, ax
+ 0xb8, 0x55, 0x55, // mov ax, 0x5555
+ 0xb9, 0xff, 0xff, // mov cx, 0xffff
+ 0x09, 0xc1, // or cx, ax
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xb9, 0x7e, 0x7e, // mov cx, 0x7e7e
+ 0x09, 0xc1, // or cx, ax
+ 0x66, 0xb8, 0x80, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xb9, 0xff, 0xff, 0xff, 0xff, // mov ecx, 0xffffffff
+ 0x66, 0x09, 0xc1, // or ecx, eax
+ 0x66, 0xb8, 0x55, 0x55, 0x55, 0x55, // mov eax, 0x55555555
+ 0x66, 0xb9, 0xff, 0xff, 0xff, 0xff, // mov ecx, 0xffffffff
+ 0x66, 0x09, 0xc1, // or ecx, eax
+ 0x66, 0xb8, 0x81, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xb9, 0x7e, 0x7e, 0x7e, 0x7e, // mov ecx, 0x7e7e7e7e
+ 0x66, 0x09, 0xc1, // or ecx, eax
+ 0xb1, 0x80, // mov cl, 0x80
+ 0x80, 0xc9, 0xff, // or cl, 0xff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x81, 0xc9, 0xff, 0xff, // or cx, 0xffff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x81, 0xc9, 0xff, 0xff, 0xff, 0xff, // or ecx, 0xffffffff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x83, 0xc9, 0x7f, // or cx, (sign)0xff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x83, 0xc9, 0x7f, // or ecx, (sign)0xff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x83, 0xc9, 0xf7, // or cx, (sign)0xff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x83, 0xc9, 0xf7, // or ecx, (sign)0xff
+ 0xb0, 0x81, // mov al, 0x81
+ 0xb1, 0xff, // mov cl, 0xff
+ 0x30, 0xc1, // xor cl, al
+ 0xb0, 0x55, // mov al, 0x55
+ 0xb1, 0xff, // mov cl, 0xff
+ 0x30, 0xc1, // xor cl, al
+ 0xb0, 0x81, // mov al, 0x81
+ 0xb1, 0x7e, // mov cl, 0x7e
+ 0x30, 0xc1, // xor cl, al
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xb9, 0xff, 0xff, // mov cx, 0xffff
+ 0x31, 0xc1, // xor cx, ax
+ 0xb8, 0x55, 0x55, // mov ax, 0x5555
+ 0xb9, 0xff, 0xff, // mov cx, 0xffff
+ 0x31, 0xc1, // xor cx, ax
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xb9, 0x7e, 0x7e, // mov cx, 0x7e7e
+ 0x31, 0xc1, // xor cx, ax
+ 0x66, 0xb8, 0x80, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xb9, 0xff, 0xff, 0xff, 0xff, // mov ecx, 0xffffffff
+ 0x66, 0x31, 0xc1, // xor ecx, eax
+ 0x66, 0xb8, 0x55, 0x55, 0x55, 0x55, // mov eax, 0x55555555
+ 0x66, 0xb9, 0xff, 0xff, 0xff, 0xff, // mov ecx, 0xffffffff
+ 0x66, 0x31, 0xc1, // xor ecx, eax
+ 0x66, 0xb8, 0x81, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xb9, 0x7e, 0x7e, 0x7e, 0x7e, // mov ecx, 0x7e7e7e7e
+ 0x66, 0x31, 0xc1, // xor ecx, eax
+ 0xb1, 0x80, // mov cl, 0x80
+ 0x80, 0xf1, 0xff, // xor cl, 0xff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x81, 0xf1, 0xff, 0xff, // xor cx, 0xffff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x81, 0xf1, 0xff, 0xff, 0xff, 0xff, // xor ecx, 0xffffffff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x83, 0xf1, 0x7f, // xor cx, (sign)0xff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x83, 0xf1, 0x7f, // xor ecx, (sign)0xff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0x83, 0xf1, 0xf7, // xor cx, (sign)0xff
+ 0x66, 0xb9, 0x80, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0x83, 0xf1, 0xf7, // xor ecx, (sign)0xff
+ 0xb0, 0x81, // mov al, 0x81
+ 0xa8, 0xff, // test al, 0xff
+ 0xb0, 0x55, // mov al, 0x55
+ 0xa8, 0xff, // test al, 0xff
+ 0xb0, 0x81, // mov al, 0x81
+ 0xa8, 0x7e, // test al, 0x7e
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xa9, 0xff, 0xff, // test ax, 0xffff
+ 0xb8, 0x55, 0x55, // mov ax, 0x5555
+ 0xa9, 0xff, 0xff, // test ax, 0xffff
+ 0xb8, 0x81, 0x81, // mov ax, 0x8181
+ 0xa9, 0x7e, 0x7e, // test ax, 0x7e7e
+ 0x66, 0xb8, 0x80, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xa9, 0xff, 0xff, 0xff, 0xff, // test ecx, 0xffffffff
+ 0x66, 0xb8, 0x55, 0x55, 0x55, 0x55, // mov eax, 0x55555555
+ 0x66, 0xa9, 0xff, 0xff, 0xff, 0xff, // test eax, 0xffffffff
+ 0x66, 0xb8, 0x81, 0x81, 0x81, 0x81, // mov eax, 0x81818181
+ 0x66, 0xa9, 0x7e, 0x7e, 0x7e, 0x7e, // test eax, 0x7e7e7e7e
+ 0xb2, 0x81, // mov dl, 0x81
+ 0xf6, 0xd2, // not dl
+ 0xba, 0x7e, 0x7e, // mov dx, 0xfe7e
+ 0xf7, 0xd2, // not dx
+ 0x66, 0xba, 0x5a, 0xa5, 0x5a, 0xa5, // mov edx, 0xa55aa55a
+ 0x66, 0xf7, 0xd2, // not edx
+ 0xb1, 0x81, // mov cl, 0x81
+ 0xf6, 0xc1, 0xff, // test cl, 0xff
+ 0xb1, 0x55, // mov cl, 0x55
+ 0xf6, 0xc1, 0xff, // test cl, 0xff
+ 0xb1, 0x81, // mov cl, 0x81
+ 0xf6, 0xc1, 0x7e, // test cl, 0x7e
+ 0xb9, 0x81, 0x81, // mov cx, 0x8181
+ 0xf7, 0xc1, 0xff, 0xff, // test cx, 0xffff
+ 0xb9, 0x55, 0x55, // mov cx, 0x5555
+ 0xf7, 0xc1, 0xff, 0xff, // test cx, 0xffff
+ 0xb9, 0x81, 0x81, // mov cx, 0x8181
+ 0xf7, 0xc1, 0x7e, 0x7e, // test cx, 0x7e7e
+ 0x66, 0xb9, 0x81, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0xf7, 0xc1, 0xff, 0xff, 0xff, 0xff, // test ecx, 0xffffffff
+ 0x66, 0xb9, 0x55, 0x55, 0x55, 0x55, // mov ecx, 0x55555555
+ 0x66, 0xf7, 0xc1, 0xff, 0xff, 0xff, 0xff, // test ecx, 0xffffffff
+ 0x66, 0xb9, 0x81, 0x81, 0x81, 0x81, // mov ecx, 0x81818181
+ 0x66, 0xf7, 0xc1, 0x7e, 0x7e, 0x7e, 0x7e, // test ecx, 0x7e7e7e7e
+ 0xb2, 0x81, // mov dl, 0x81
+ 0xf6, 0xda, // neg dl
+ 0xba, 0x7e, 0xfe, // mov dx, 0xfe7e
+ 0xf7, 0xda, // neg dx
+ 0x66, 0xba, 0x5a, 0xa5, 0x5a, 0xa5, // mov edx, 0xa55aa55a
+ 0x66, 0xf7, 0xda, // neg edx
+ 0xb2, 0x7f, // mov dl, 0x7f
+ 0xf6, 0xda, // neg dl
+ 0xba, 0x7e, 0x7e, // mov dx, 0x7e7e
+ 0xf7, 0xda, // neg dx
+ 0x66, 0xba, 0xa5, 0x5a, 0xa5, 0x5a, // mov edx, 0x5aa55aa5
+ 0x66, 0xf7, 0xda, // neg edx
+ 0xb0, 0x7f, // mov al, 0x7f
+ 0x98, // cbw
+ 0xb0, 0x83, // mov al, 0x83
+ 0x98, // cbw
+ 0xb8, 0x01, 0x08, // mov ax, 0x0801
+ 0x99, // cwd
+ 0xb8, 0x01, 0x80, // mov ax, 0x8001
+ 0x99, // cwd
+ 0xb8, 0x7f, 0x7f, // mov ax, 0x7f7f
+ 0x66, 0x98, // cwde
+ 0xb8, 0x83, 0x83, // mov ax, 0x8383
+ 0x66, 0x98, // cwde
+ 0x66, 0xb8, 0x01, 0x08, 0x01, 0x08, // mov eax, 0x08010801
+ 0x66, 0x99, // cdq
+ 0x66, 0xb8, 0x01, 0x80, 0x01, 0x80, // mov eax, 0x80018001
+ 0x66, 0x99, // cdq
+ 0x66, 0x9c, // pushaf
+ 0x9c, // pushf
+ 0x66, 0xb8, 0xd7, 0x0c, 0x06, 0x00, // mov eax, 0x00060cd7
+ 0x66, 0x50, // push eax
+ 0x50, // push ax
+ 0x9d, // popf
+ 0x66, 0x9d, // popaf
+ 0x9d, // popf
+ 0x66, 0x9d, // popaf
+ 0x68, 0xef, 0xfe, // push 0xfeef
+ 0x68, 0x11, 0x11, // push 0x1111
+ 0x66, 0x68, 0xef, 0xfe, 0xef, 0xfe, // push 0xfeeffeef
+ 0x6a, 0xfe, // push 0xfe -> 0xfffe
+ 0x6a, 0x7f, // push 0x7f -> 0x007f
+ 0x66, 0x6a, 0xfe, // push 0xfe -> 0xfffffffe
+ 0x66, 0x6a, 0x7f, // push 0x7f -> 0x0000007f
+ 0x66, 0x9d, // popaf
+ 0x66, 0x9d, // popaf
+ 0x9d, // popf
+ 0x9d, // popf
+ 0x66, 0x9d, // popaf
+ 0x9d, // popf
+ 0x9d, // popf
+ 0x60, // pusha
+ 0x66, 0x60, // pushad
+ 0x66, 0x31, 0xc0, // xor eax, eax
+ 0x66, 0x31, 0xc9, // xor ecx, ecx
+ 0x66, 0x31, 0xd2, // xor edx, edx
+ 0x66, 0x31, 0xdb, // xor ebx, ebx
+ 0x66, 0x31, 0xed, // xor ebp, ebp
+ 0x66, 0x31, 0xf6, // xor esi, esi
+ 0x66, 0x31, 0xff, // xor edi, edi
+ 0x66, 0x61, // popad
+ 0x66, 0x31, 0xc0, // xor eax, eax
+ 0x66, 0x31, 0xc9, // xor ecx, ecx
+ 0x66, 0x31, 0xd2, // xor edx, edx
+ 0x66, 0x31, 0xdb, // xor ebx, ebx
+ 0x66, 0x31, 0xed, // xor ebp, ebp
+ 0x66, 0x31, 0xf6, // xor esi, esi
+ 0x66, 0x31, 0xff, // xor edi, edi
+ 0x61, // popa
+ 0xb4, 0x40, // mov ah, 0x40 (ZF)
+ 0x9e, // sahf
+ 0x74, 0x00, // jz Ib .+1
+ 0x75, 0x00, // jnz Ib .+1
+ 0x0f, 0x84, 0x00, 0x00, // jz Iv .+1
+ 0x0f, 0x85, 0x00, 0x00, // jnz Iv .+1
+ 0x66, 0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, // jz Iv .+1
+ 0x66, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, // jnz Iv .+1
+ 0xb4, 0x01, // mov ah, 0x01 (CF)
+ 0x9e, // sahf
+ 0x72, 0x00, // jb Ib .+1
+ 0x73, 0x00, // jnb Ib .+1
+ 0x0f, 0x82, 0x00, 0x00, // jb Iv .+1
+ 0x0f, 0x83, 0x00, 0x00, // jnb Iv .+1
+ 0x66, 0x0f, 0x82, 0x00, 0x00, 0x00, 0x00, // jb Iv .+1
+ 0x66, 0x0f, 0x83, 0x00, 0x00, 0x00, 0x00, // jnb Iv .+1
+ 0xb4, 0x41, // mov ah, 0x41 (ZF-CF)
+ 0x9e, // sahf
+ 0x76, 0x00, // jbe Ib .+1
+ 0x77, 0x00, // jnbe Ib .+1
+ 0x0f, 0x86, 0x00, 0x00, // jbe Iv .+1
+ 0x0f, 0x87, 0x00, 0x00, // jnbe Iv .+1
+ 0x66, 0x0f, 0x86, 0x00, 0x00, 0x00, 0x00, // jbe Iv .+1
+ 0x66, 0x0f, 0x87, 0x00, 0x00, 0x00, 0x00, // jnbe Iv .+1
+ 0xb4, 0x80, // mov ah, 0x80 (SF)
+ 0x9e, // sahf
+ 0x78, 0x00, // js Ib .+1
+ 0x79, 0x00, // jns Ib .+1
+ 0x0f, 0x88, 0x00, 0x00, // js Iv .+1
+ 0x0f, 0x89, 0x00, 0x00, // jns Iv .+1
+ 0x66, 0x0f, 0x88, 0x00, 0x00, 0x00, 0x00, // js Iv .+1
+ 0x66, 0x0f, 0x89, 0x00, 0x00, 0x00, 0x00, // jns Iv .+1
+ 0xb4, 0x04, // mov ah, 0x04 (PF)
+ 0x9e, // sahf
+ 0x7a, 0x00, // jp Ib .+1
+ 0x7b, 0x00, // jnp Ib .+1
+ 0x0f, 0x8a, 0x00, 0x00, // jp Iv .+1
+ 0x0f, 0x8b, 0x00, 0x00, // jnp Iv .+1
+ 0x66, 0x0f, 0x8a, 0x00, 0x00, 0x00, 0x00, // jp Iv .+1
+ 0x66, 0x0f, 0x8b, 0x00, 0x00, 0x00, 0x00, // jnp Iv .+1
+ 0xb4, 0x80, // mov ah, 0x80 (SF)
+ 0x9e, // sahf
+ 0x7c, 0x00, // jl Ib .+1
+ 0x7d, 0x00, // jnl Ib .+1
+ 0x0f, 0x8c, 0x00, 0x00, // jl Iv .+1
+ 0x0f, 0x8d, 0x00, 0x00, // jnl Iv .+1
+ 0x66, 0x0f, 0x8c, 0x00, 0x00, 0x00, 0x00, // jl Iv .+1
+ 0x66, 0x0f, 0x8d, 0x00, 0x00, 0x00, 0x00, // jnl Iv .+1
+ 0xb4, 0xc0, // mov ah, 0xc0 (SF-ZF)
+ 0x9e, // sahf
+ 0x7e, 0x00, // jle Ib .+1
+ 0x7f, 0x00, // jnle Ib .+1
+ 0x0f, 0x8e, 0x00, 0x00, // jle Iv .+1
+ 0x0f, 0x8f, 0x00, 0x00, // jnle Iv .+1
+ 0x66, 0x0f, 0x8e, 0x00, 0x00, 0x00, 0x00, // jle Iv .+1
+ 0x66, 0x0f, 0x8f, 0x00, 0x00, 0x00, 0x00, // jnle Iv .+1
+ 0xb0, 0x80, // mov al, 0x80
+ 0xd0, 0xc0, // rol al, 1
+ 0x70, 0x00, // jo Ib .+1
+ 0x71, 0x00, // jno Ib .+1
+ 0x0f, 0x80, 0x00, 0x00, // jo Iv .+1
+ 0x0f, 0x81, 0x00, 0x00, // jno Iv .+1
+ 0x66, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, // jo Iv .+1
+ 0x66, 0x0f, 0x81, 0x00, 0x00, 0x00, 0x00, // jno Iv .+1
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0x40, // inc ax
+ 0xe2, 0xfd, // loop .-3
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0x66, 0xb9, 0x02, 0x00, 0x00, 0x00, // mov ecx, 0x00000001
+ 0x66, 0x40, // inc eax
+ 0x67, 0xe2, 0xfb, // loop .-5
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0x40, // inc ax
+ 0xe1, 0xfd, // loopz .-3
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0x40, // inc ax
+ 0xe0, 0xfd, // loopnz .-3
+ 0x31, 0xc0, // xor ax, ax
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0x40, // inc ax
+ 0xe0, 0xfd, // loopnz .-3
+ 0x31, 0xc0, // xor ax, ax
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0x90, // nop
+ 0xe1, 0xfd, // loopz .-3
+ 0xeb, 0x00, // jmp .+1
+ 0xe9, 0x00, 0x00, // jmp .+1
+ 0x66, 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp .+1
+ 0xb0, 0x7f, // mov al, 0x7f
+ 0x0f, 0xb6, 0xc8, // movzb cx,al
+ 0x0f, 0xbe, 0xc8, // movsb cx,al
+ 0xb0, 0x8f, // mov al, 0x8f
+ 0x0f, 0xb6, 0xc8, // movzb cx,al
+ 0x0f, 0xbe, 0xc8, // movsb cx,al
+ 0xb0, 0x7f, // mov al, 0x7f
+ 0x66, 0x0f, 0xb6, 0xc8, // movzb ecx,al
+ 0x66, 0x0f, 0xbe, 0xc8, // movsb ecx,al
+ 0xb0, 0x8f, // mov al, 0x8f
+ 0x66, 0x0f, 0xb6, 0xc8, // movzb ecx,al
+ 0x66, 0x0f, 0xbe, 0xc8, // movsb ecx,al
+ 0xb8, 0x00, 0x7f, // mov ax, 0x7f00
+ 0x0f, 0xb7, 0xc8, // movzw cx,ax
+ 0x0f, 0xbf, 0xc8, // movsw cx,ax
+ 0xb8, 0x00, 0x8f, // mov ax, 0x8f00
+ 0x66, 0x0f, 0xb7, 0xc8, // movzw ecx,ax
+ 0x66, 0x0f, 0xbf, 0xc8, // movsw ecx,ax
+ 0xb8, 0x55, 0xaa, // mov ax, 0xaa55
+ 0x8e, 0xe0, // mov fs, ax
+ 0x8c, 0xe1, // mov cx, fs
+ 0x8e, 0xe9, // mov gs, cx
+ 0x68, 0xef, 0xfe, // push 0xfeef
+ 0x68, 0x11, 0x11, // push 0x1111
+ 0x66, 0x68, 0xef, 0xfe, 0xef, 0xfe, // push 0xfeeffeef
+ 0x66, 0x8f, 0xc1, // pop ecx
+ 0x8f, 0xc1, // pop cx
+ 0x8f, 0xc2, // pop dx
+ 0xb0, 0x03, // mov al, 0x03
+ 0xb1, 0x05, // mov cl, 0x05
+ 0xf6, 0xe1, // mul al, cl
+ 0xb0, 0xff, // mov al, 0xff
+ 0xb1, 0x10, // mov cl, 0x10
+ 0xf6, 0xe1, // mul al, cl
+ 0xb8, 0x03, 0x00, // mov ax, 0x03
+ 0xb9, 0x05, 0x00, // mov cx, 0x05
+ 0xf7, 0xe1, // mul ax, cx
+ 0xb8, 0x00, 0xff, // mov ax, 0xff00
+ 0xb9, 0x10, 0x00, // mov cx, 0x0010
+ 0xf7, 0xe1, // mul ax, cx
+ 0x66, 0xb8, 0x03, 0x00, 0x00, 0x00, // mov eax, 0x00000003
+ 0x66, 0xb9, 0x05, 0x00, 0x00, 0x00, // mov ecx, 0x00000005
+ 0x66, 0xf7, 0xe1, // mul eax, ecx
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xff, // mov eax, 0xff000000
+ 0x66, 0xb9, 0x10, 0x00, 0x00, 0x00, // mov ecx, 0x00000010
+ 0x66, 0xf7, 0xe1, // mul eax, ecx
+ 0xb0, 0x03, // mov al, 0x03
+ 0xb1, 0x05, // mov cl, 0x05
+ 0xf6, 0xe9, // imul al, cl
+ 0xb0, 0xff, // mov al, 0xff
+ 0xb1, 0x10, // mov cl, 0x10
+ 0xf6, 0xe9, // imul al, cl
+ 0xb8, 0x03, 0x00, // mov ax, 0x03
+ 0xb9, 0x05, 0x00, // mov cx, 0x05
+ 0xf7, 0xe9, // imul ax, cx
+ 0xb8, 0xff, 0xff, // mov ax, 0xffff
+ 0xb9, 0x10, 0x00, // mov cx, 0x0010
+ 0xf7, 0xe9, // imul ax, cx
+ 0xb8, 0x00, 0xf0, // mov ax, 0xf000
+ 0xb9, 0x10, 0x00, // mov cx, 0x0010
+ 0xf7, 0xe9, // imul ax, cx
+ 0x66, 0xb8, 0x03, 0x00, 0x00, 0x00, // mov eax, 0x00000003
+ 0x66, 0xb9, 0x05, 0x00, 0x00, 0x00, // mov ecx, 0x00000005
+ 0x66, 0xf7, 0xe9, // imul eax, ecx
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xf0, // mov eax, 0xf0000000
+ 0x66, 0xb9, 0x10, 0x00, 0x00, 0x00, // mov ecx, 0x00000010
+ 0x66, 0xf7, 0xe9, // imul eax, ecx
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x6b, 0xc8, 0x05, // imul cx, ax, 0x05
+ 0xb8, 0x00, 0xff, // mov ax, 0xff00
+ 0x6b, 0xc8, 0x10, // imul cx, ax, 0x10
+ 0xb8, 0x00, 0xf0, // mov ax, 0xf000
+ 0x6b, 0xc8, 0x10, // imul cx, ax, 0x10
+ 0xb8, 0x00, 0x10, // mov ax, 0x1000
+ 0x6b, 0xc8, 0xf0, // imul cx, ax, 0xf0
+ 0x66, 0xb8, 0x03, 0x00, 0x00, 0x00, // mov eax, 0x00000003
+ 0x66, 0x6b, 0xc8, 0x05, // imul ecx, eax, 0x05
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xff, // mov eax, 0xff000000
+ 0x66, 0x6b, 0xc8, 0x10, // imul ecx, eax, 0x10
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xf0, // mov eax, 0xf0000000
+ 0x66, 0x6b, 0xc8, 0x10, // imul ecx, eax, 0x10
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x10, // mov eax, 0x1000
+ 0x66, 0x6b, 0xc8, 0xf0, // imul ecx, eax, 0xf0
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x69, 0xc8, 0x05, 0x00, // imul cx, ax, 0x0005
+ 0xb8, 0x00, 0xff, // mov ax, 0xff00
+ 0x69, 0xc8, 0x10, 0x00, // imul cx, ax, 0x0010
+ 0xb8, 0x00, 0xf0, // mov ax, 0xf000
+ 0x69, 0xc8, 0x10, 0x00, // imul cx, ax, 0x0010
+ 0xb8, 0x00, 0x10, // mov ax, 0x1000
+ 0x69, 0xc8, 0x00, 0xf0, // imul cx, ax, 0xf000
+ 0x66, 0xb8, 0x03, 0x00, 0x00, 0x00, // mov eax, 0x00000003
+ 0x66, 0x69, 0xc8, 0x05, 0x00, 0x00, 0x00, // imul ecx, eax, 0x00000005
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xff, // mov eax, 0xff000000
+ 0x66, 0x69, 0xc8, 0x10, 0x00, 0x00, 0x00, // imul ecx, eax, 0x00000010
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xf0, // mov eax, 0xf0000000
+ 0x66, 0x69, 0xc8, 0x10, 0x00, 0x00, 0x00, // imul ecx, eax, 0x00000010
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x10, // mov eax, 0x10000000
+ 0x66, 0x69, 0xc8, 0xf0, 0xff, 0xff, 0xff, // imul ecx, eax, 0xfffffff0
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0xb9, 0x05, 0x00, // mov cx, 0x0005
+ 0x0f, 0xaf, 0xc8, // imul cx, ax
+ 0xb8, 0x00, 0xff, // mov ax, 0xff00
+ 0xb9, 0x10, 0x00, // mov cx, 0x0010
+ 0x0f, 0xaf, 0xc8, // imul cx,ax
+ 0xb8, 0x00, 0xf0, // mov ax, 0xf000
+ 0xb9, 0x10, 0x00, // mov cx, 0x0010
+ 0x0f, 0xaf, 0xc8, // imul cx,ax
+ 0xb8, 0x00, 0x10, // mov ax, 0x1000
+ 0xb9, 0x00, 0xf0, // mov cx, 0xf000
+ 0x0f, 0xaf, 0xc8, // imul cx,ax
+ 0x66, 0xb8, 0x03, 0x00, 0x00, 0x00, // mov eax, 0x00000003
+ 0x66, 0xb9, 0x05, 0x00, 0x00, 0x00, // mov ecx, 0x00000005
+ 0x66, 0x0f, 0xaf, 0xc8, // imul ecx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xff, // mov eax, 0xff000000
+ 0x66, 0xb9, 0x10, 0x00, 0x00, 0x00, // mov ecx, 0x00000010
+ 0x66, 0x0f, 0xaf, 0xc8, // imul ecx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xf0, // mov eax, 0xf0000000
+ 0x66, 0xb9, 0x10, 0x00, 0x00, 0x00, // mov ecx, 0x00000010
+ 0x66, 0x0f, 0xaf, 0xc8, // imul ecx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x10, // mov eax, 0x10000000
+ 0x66, 0xb9, 0xf0, 0xff, 0xff, 0xff, // mov ecx, 0xfffffff0
+ 0x66, 0x0f, 0xaf, 0xc8, // imul ecx, eax
+ 0xb1, 0xfe, // mov cl, 0xfe
+ 0xfe, 0xc1, // inc cl
+ 0xfe, 0xc1, // inc cl
+ 0xfe, 0xc9, // dec cl
+ 0xfe, 0xc9, // dec cl
+ 0xb9, 0xfe, 0xff, // mov cx, 0xfffe
+ 0xff, 0xc1, // inc cx
+ 0xff, 0xc1, // inc cx
+ 0xff, 0xc9, // dec cx
+ 0xff, 0xc9, // dec cx
+ 0x66, 0xb9, 0xfe, 0xff, 0xff, 0xff, // mov ecx, 0xfffffffe
+ 0x66, 0xff, 0xc1, // inc ecx
+ 0x66, 0xff, 0xc1, // inc ecx
+ 0x66, 0xff, 0xc9, // dec ecx
+ 0x66, 0xff, 0xc9, // dec ecx
+ 0xff, 0xf2, // push dx
+ 0x8f, 0xc3, // pop bx
+ 0x66, 0xff, 0xf5, // push ebp
+ 0x66, 0x8f, 0xc6, // pop esi
+ 0xb8, 0x7f, 0x00, // mov ax, 0x007f
+ 0xb1, 0x04, // mov cl, 0x04
+ 0xf6, 0xf1, // div ah:al, cl
+ 0xb8, 0x80, 0x00, // mov ax, 0x0080
+ 0xb1, 0x10, // mov cl, 0x10
+ 0xf6, 0xf1, // div ah:al, cl
+ 0xb8, 0x0f, 0x7f, // mov ax, 0x7f0f
+ 0xba, 0x00, 0x00, // mov dx, 0x0000
+ 0xb9, 0x04, 0x00, // mov cx, 0x04
+ 0xf7, 0xf1, // div dx:ax, cx
+ 0xb8, 0x00, 0x80, // mov ax, 0x8000
+ 0xba, 0x00, 0x00, // mov dx, 0x0000
+ 0xb9, 0x10, 0x00, // mov cx, 0x10
+ 0xf7, 0xf1, // div dx:ax, cx
+ 0x66, 0xb8, 0x0f, 0x00, 0x00, 0x7f, // mov eax, 0x7f00000f
+ 0x66, 0xba, 0x00, 0x00, 0x00, 0x00, // mov edx, 0x00000000
+ 0x66, 0xb9, 0x04, 0x00, 0x00, 0x00, // mov ecx, 0x00000004
+ 0x66, 0xf7, 0xf1, // div edx:eax, ecx
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x80, // mov eax, 0x80000000
+ 0x66, 0xba, 0x00, 0x00, 0x00, 0x00, // mov edx, 0x00000000
+ 0x66, 0xb9, 0x10, 0x00, 0x00, 0x00, // mov ecx, 0x00000010
+ 0x66, 0xf7, 0xf1, // div edx:eax, ecx
+ 0xb8, 0x7f, 0x00, // mov ax, 0x007f
+ 0xb1, 0x04, // mov cl, 0x04
+ 0xf6, 0xf9, // idiv ah:al, cl
+ 0xb8, 0x81, 0xff, // mov ax, 0xff81
+ 0xb1, 0x10, // mov cl, 0x10
+ 0xf6, 0xf9, // idiv ah:al, cl
+ 0xb8, 0x0f, 0x7f, // mov ax, 0x7f0f
+ 0xba, 0x00, 0x00, // mov dx, 0x0000
+ 0xb9, 0x04, 0x00, // mov cx, 0x04
+ 0xf7, 0xf9, // idiv dx:ax, cx
+ 0xb8, 0x01, 0x80, // mov ax, 0x8001
+ 0xba, 0xff, 0xff, // mov dx, 0xffff
+ 0xb9, 0x10, 0x00, // mov cx, 0x10
+ 0xf7, 0xf9, // idiv dx:ax, cx
+ 0x66, 0xb8, 0x0f, 0x00, 0x00, 0x7f, // mov eax, 0x7f00000f
+ 0x66, 0xba, 0x00, 0x00, 0x00, 0x00, // mov edx, 0x00000000
+ 0x66, 0xb9, 0x04, 0x00, 0x00, 0x00, // mov ecx, 0x00000004
+ 0x66, 0xf7, 0xf9, // idiv edx:eax, ecx
+ 0x66, 0xb8, 0x01, 0x00, 0x00, 0x80, // mov eax, 0x80000001
+ 0x66, 0xba, 0xff, 0xff, 0xff, 0xff, // mov edx, 0xffffffff
+ 0x66, 0xb9, 0x10, 0x00, 0x00, 0x00, // mov ecx, 0x00000010
+ 0x66, 0xf7, 0xf9, // idiv edx:eax, ecx
+ 0x66, 0xb8, 0x05, 0x50, 0x0a, 0xa0, // mov eax, 0xa00a5005
+ 0xa2, 0x00, 0x00, // mov 0x0000, al
+ 0x67, 0xa2, 0x04, 0x00, 0x00, 0x00, // mov 0x00000004, al
+ 0xa3, 0x08, 0x00, // mov 0x0008, ax
+ 0x67, 0xa3, 0x0c, 0x00, 0x00, 0x00, // mov 0x0000000c, ax
+ 0x66, 0xa3, 0x10, 0x00, // mov 0x0010, eax
+ 0x66, 0x67, 0xa3, 0x14, 0x00, 0x00, 0x00, // mov 0x00000014, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0xa0, 0x00, 0x00, // mov al, ds:0x0000
+ 0xb0, 0x00, // mov al, 0x00
+ 0x67, 0xa0, 0x04, 0x00, 0x00, 0x00, // al, mov ds:0x00000004
+ 0xb0, 0x00, // mov al, 0x00
+ 0xa1, 0x08, 0x00, // mov ax, ds:0x0008
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0x67, 0xa1, 0x0c, 0x00, 0x00, 0x00, // mov ax, ds:0x0000000c
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0x66, 0xa1, 0x10, 0x00, // mov eax, ds:0x0010
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0x66, 0x67, 0xa1, 0x14, 0x00, 0x00, 0x00, // eax, ds:mov 0x00000014
+ 0x66, 0xb9, 0x00, 0x00, 0x10, 0x10, // mov ecx, 0x10100000
+ 0xe3, 0x00, // jcxz .+1
+ 0xb9, 0x01, 0x01, // mov cx, 0x0101
+ 0xe3, 0x00, // jcxz .+1
+ 0x66, 0xe3, 0x00, // jecxz .+1
+ 0x66, 0xb9, 0x00, 0x00, 0x00, 0x00, // mov ecx, 0x00000000
+ 0x66, 0xe3, 0x00, // jecxz .+1
+ 0xb8, 0x01, 0x00, // mov ax, 0x0001
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0xba, 0x03, 0x00, // mov dx, 0x0003
+ 0xbb, 0x04, 0x00, // mov bx, 0x0004
+ 0xbd, 0x06, 0x00, // mov bp, 0x0006
+ 0xbe, 0x07, 0x00, // mov si, 0x0007
+ 0xbf, 0x08, 0x00, // mov di, 0x0008
+ 0x66, 0x8d, 0x80, 0x10, 0x10, // lea eax,[bx + si + 0x1010]
+ 0x66, 0x8d, 0x81, 0x10, 0x10, // lea eax,[bx + di + 0x1010]
+ 0x66, 0x8d, 0x82, 0x10, 0x10, // lea eax,[bp + si + 0x1010]
+ 0x66, 0x8d, 0x83, 0x10, 0x10, // lea eax,[bp + di + 0x1010]
+ 0x66, 0x8d, 0x84, 0x10, 0x10, // lea eax,[si + 0x1010]
+ 0x66, 0x8d, 0x85, 0x10, 0x10, // lea eax,[di + 0x1010]
+ 0x66, 0x8d, 0x86, 0x10, 0x10, // lea eax,[bp + 0x1010]
+ 0x66, 0x8d, 0x87, 0x10, 0x10, // lea eax,[bx + 0x1010]
+ 0x66, 0x8d, 0x40, 0x10, // lea eax,[bx + si + 0x10]
+ 0x66, 0x8d, 0x41, 0x10, // lea eax,[bx + di + 0x10]
+ 0x66, 0x8d, 0x42, 0x10, // lea eax,[bp + si + 0x10]
+ 0x66, 0x8d, 0x43, 0x10, // lea eax,[bp + di + 0x10]
+ 0x66, 0x8d, 0x44, 0x10, // lea eax,[si + 0x10]
+ 0x66, 0x8d, 0x45, 0x10, // lea eax,[di + 0x10]
+ 0x66, 0x8d, 0x46, 0x10, // lea eax,[bp + 0x10]
+ 0x66, 0x8d, 0x47, 0x10, // lea eax,[bx + 0x10]
+ 0x66, 0x8d, 0x00, // lea eax,[bx + si]
+ 0x66, 0x8d, 0x01, // lea eax,[bx + di]
+ 0x66, 0x8d, 0x02, // lea eax,[bp + si]
+ 0x66, 0x8d, 0x03, // lea eax,[bp + di]
+ 0x66, 0x8d, 0x04, // lea eax,[si]
+ 0x66, 0x8d, 0x05, // lea eax,[di]
+ 0x66, 0x8d, 0x06, 0xff, 0xee, // lea eax,[0xffee]
+ 0x66, 0x8d, 0x07, // lea eax,[bx]
+ 0x8d, 0x80, 0x10, 0x10, // lea ax,[bx + si + 0x1010]
+ 0x8d, 0x81, 0x10, 0x10, // lea ax,[bx + di + 0x1010]
+ 0x8d, 0x82, 0x10, 0x10, // lea ax,[bp + si + 0x1010]
+ 0x8d, 0x83, 0x10, 0x10, // lea ax,[bp + di + 0x1010]
+ 0x8d, 0x84, 0x10, 0x10, // lea ax,[si + 0x1010]
+ 0x8d, 0x85, 0x10, 0x10, // lea ax,[di + 0x1010]
+ 0x8d, 0x86, 0x10, 0x10, // lea ax,[bp + 0x1010]
+ 0x8d, 0x87, 0x10, 0x10, // lea ax,[bx + 0x1010]
+ 0x8d, 0x40, 0x10, // lea ax,[bx + si + 0x10]
+ 0x8d, 0x41, 0x10, // lea ax,[bx + di + 0x10]
+ 0x8d, 0x42, 0x10, // lea ax,[bp + si + 0x10]
+ 0x8d, 0x43, 0x10, // lea ax,[bp + di + 0x10]
+ 0x8d, 0x44, 0x10, // lea ax,[si + 0x10]
+ 0x8d, 0x45, 0x10, // lea ax,[di + 0x10]
+ 0x8d, 0x46, 0x10, // lea ax,[bp + 0x10]
+ 0x8d, 0x47, 0x10, // lea ax,[bx + 0x10]
+ 0x8d, 0x00, // lea ax,[bx + si]
+ 0x8d, 0x01, // lea ax,[bx + di]
+ 0x8d, 0x02, // lea ax,[bp + si]
+ 0x8d, 0x03, // lea ax,[bp + di]
+ 0x8d, 0x04, // lea ax,[si]
+ 0x8d, 0x05, // lea ax,[di]
+ 0x8d, 0x06, 0xff, 0xee, // lea ax,[0xffee]
+ 0x8d, 0x07, // lea ax,[bx]
+ 0xb8, 0x01, 0x00, // mov ax, 0x0001
+ 0xb9, 0x02, 0x00, // mov cx, 0x0002
+ 0xba, 0x03, 0x00, // mov dx, 0x0003
+ 0xbb, 0x04, 0x00, // mov bx, 0x0004
+ 0xbd, 0x06, 0x00, // mov bp, 0x0006
+ 0xbe, 0x07, 0x00, // mov si, 0x0007
+ 0xbf, 0x08, 0x00, // mov di, 0x0008
+ 0x67, 0x8d, 0x00, // lea ax,[eax]
+ 0x67, 0x8d, 0x01, // lea ax,[ecx]
+ 0x67, 0x8d, 0x02, // lea ax,[edx]
+ 0x67, 0x8d, 0x03, // lea ax,[ebx]
+ 0x67, 0x8d, 0x05, 0xff, 0xee, 0xdd, 0xcc, // lea ax,[0xccddeeff]
+ 0x67, 0x8d, 0x06, // lea ax,[esi]
+ 0x67, 0x8d, 0x07, // lea ax,[edi]
+ 0x67, 0x8d, 0x40, 0x10, // lea ax,[eax + 0x10]
+ 0x67, 0x8d, 0x41, 0x10, // lea ax,[ecx + 0x10]
+ 0x67, 0x8d, 0x42, 0x10, // lea ax,[edx + 0x10]
+ 0x67, 0x8d, 0x43, 0x10, // lea ax,[ebx + 0x10]
+ 0x67, 0x8d, 0x45, 0x10, // lea ax,[ebp + 0x10]
+ 0x67, 0x8d, 0x46, 0x10, // lea ax,[esi + 0x10]
+ 0x67, 0x8d, 0x47, 0x10, // lea ax,[edi + 0x10]
+ 0x67, 0x8d, 0x80, 0x10, 0x10, 0x10, 0x10, // lea ax,[eax + 0x10101010]
+ 0x67, 0x8d, 0x81, 0x10, 0x10, 0x10, 0x10, // lea ax,[ecx + 0x10101010]
+ 0x67, 0x8d, 0x82, 0x10, 0x10, 0x10, 0x10, // lea ax,[edx + 0x10101010]
+ 0x67, 0x8d, 0x83, 0x10, 0x10, 0x10, 0x10, // lea ax,[ebx + 0x10101010]
+ 0x67, 0x8d, 0x85, 0x10, 0x10, 0x10, 0x10, // lea ax,[ebp + 0x10101010]
+ 0x67, 0x8d, 0x86, 0x10, 0x10, 0x10, 0x10, // lea ax,[esi + 0x10101010]
+ 0x67, 0x8d, 0x87, 0x10, 0x10, 0x10, 0x10, // lea ax,[edi + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x00, // lea eax,[eax]
+ 0x66, 0x67, 0x8d, 0x01, // lea eax,[ecx]
+ 0x66, 0x67, 0x8d, 0x02, // lea eax,[edx]
+ 0x66, 0x67, 0x8d, 0x03, // lea eax,[ebx]
+ 0x66, 0x67, 0x8d, 0x05, 0x10, 0x10, 0x10, 0x10, // lea eax,[0x10101010]
+ 0x66, 0x67, 0x8d, 0x06, // lea eax,[esi]
+ 0x66, 0x67, 0x8d, 0x07, // lea eax,[edi]
+ 0x66, 0x67, 0x8d, 0x40, 0x10, // lea eax,[eax + 0x10]
+ 0x66, 0x67, 0x8d, 0x41, 0x10, // lea eax,[ecx + 0x10]
+ 0x66, 0x67, 0x8d, 0x42, 0x10, // lea eax,[edx + 0x10]
+ 0x66, 0x67, 0x8d, 0x43, 0x10, // lea eax,[ebx + 0x10]
+ 0x66, 0x67, 0x8d, 0x45, 0x10, // lea eax,[ebp + 0x10]
+ 0x66, 0x67, 0x8d, 0x46, 0x10, // lea eax,[esi + 0x10]
+ 0x66, 0x67, 0x8d, 0x47, 0x10, // lea eax,[edi + 0x10]
+ 0x66, 0x67, 0x8d, 0x80, 0x10, 0x10, 0x10, 0x10, // lea eax,[eax + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x81, 0x10, 0x10, 0x10, 0x10, // lea eax,[ecx + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x82, 0x10, 0x10, 0x10, 0x10, // lea eax,[edx + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x83, 0x10, 0x10, 0x10, 0x10, // lea eax,[ebx + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x85, 0x10, 0x10, 0x10, 0x10, // lea eax,[ebp + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x86, 0x10, 0x10, 0x10, 0x10, // lea eax,[esi + 0x10101010]
+ 0x66, 0x67, 0x8d, 0x87, 0x10, 0x10, 0x10, 0x10, // lea eax,[edi + 0x10101010]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x80, // lea ax,[eax + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x81, // lea ax,[ecx + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x82, // lea ax,[edx + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x83, // lea ax,[ebx + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x84, // lea ax,[esp + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x85, 0x10, 0x10, 0x10, 0x10, // lea ax,[0x10101010 + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x86, // lea ax,[esi + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x8d, 0x04, 0x87, // lea ax,[edi + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x80, // lea eax,[eax + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x81, // lea eax,[ecx + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x82, // lea eax,[edx + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x83, // lea eax,[ebx + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x84, // lea eax,[esp + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x85, 0x10, 0x10, 0x10, 0x10, // lea eax,[0x10101010 + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x86, // lea eax,[esi + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0xff, 0x00, // mov eax, 0x00ff0002
+ 0x67, 0x66, 0x8d, 0x04, 0x87, // lea eax,[edi + eax * 2]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x80, 0x10, // lea eax,[eax + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x81, 0x10, // lea eax,[ecx + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x82, 0x10, // lea eax,[edx + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x83, 0x10, // lea eax,[ebx + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x84, 0x10, // lea eax,[esp + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x85, 0x10, // lea eax,[ebp + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x86, 0x10, // lea eax,[esi + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x44, 0x87, 0x10, // lea eax,[edi + eax * 2 + 0x10]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x80, 0x10, 0x00, 0x00, 0x10, // lea eax,[eax + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x81, 0x10, 0x00, 0x00, 0x10, // lea eax,[ecx + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x82, 0x10, 0x00, 0x00, 0x10, // lea eax,[edx + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x83, 0x10, 0x00, 0x00, 0x10, // lea eax,[ebx + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x84, 0x10, 0x00, 0x00, 0x10, // lea eax,[esp + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x85, 0x10, 0x00, 0x00, 0x10, // lea eax,[ebp + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x86, 0x10, 0x00, 0x00, 0x10, // lea eax,[esi + eax * 2 + 0x10000010]
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x00, // mov eax, 0x00000002
+ 0x66, 0x67, 0x8d, 0x84, 0x87, 0x10, 0x00, 0x00, 0x10, // lea eax,[edi + eax * 2 + 0x10000010]
+ 0x90, // nop
+ 0xfc, // cld
+ 0xbe, 0x00, 0x00, // mov si, 0x0000
+ 0xbf, 0x02, 0x00, // mov di, 0x0002
+ 0xa4, // movsb
+ 0x66, 0xb8, 0xaa, 0x55, 0xf0, 0x0f, // mov eax, 0x0ff055aa
+ 0xbf, 0x00, 0x00, // mov di, 0x0000
+ 0xaa, // stosb
+ 0xaa, // stosb
+ 0xab, // stosw
+ 0x66, 0xab, // stosd
+ 0xb9, 0x04, 0x00, // mov cx, 0x0004
+ 0xf3, 0x66, 0xab, // rep stosd
+ 0x66, 0xb8, 0x5a, 0xa5, 0x00, 0xff, // mov eax, 0x0ff055aa
+ 0xb9, 0x06, 0x00, // mov cx, 0x0006
+ 0xbf, 0x2c, 0x00, // mov di, 0x002c
+ 0xfd, // std
+ 0xf3, 0x66, 0xab, // rep stosd
+ 0xc8, 0x00, 0x02, 0x00, // enter 0x0200, 0x00
+ 0xc9, // leave
+ 0xc8, 0x00, 0x02, 0x01, // enter 0x0200, 0x01
+ 0xc9, // leave
+ 0x66, 0xc8, 0x00, 0x02, 0x00, // enter 0x0200, 0x00
+ 0x66, 0xc9, // leave
+ 0x66, 0xc8, 0x00, 0x02, 0x01, // enter 0x0200, 0x01
+ 0x66, 0xc9, // leave
+ 0x66, 0xb8, 0x02, 0x00, 0xfe, 0xfe, // mov eax, 0xfefe0002
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0x66, 0x89, 0x06, 0x08, 0x00, // mov ds:0x0008, eax
+ 0xc4, 0x06, 0x04, 0x00, // les ax,d:0x0004
+ 0x0f, 0xb4, 0x0e, 0x04, 0x00, // lfs cx,d:0x0004
+ 0x0f, 0xb5, 0x16, 0x04, 0x00, // lgs dx,d:0x0004
+ 0x66, 0xc4, 0x1e, 0x04, 0x00, // les ebx,d:0x0004
+ 0x66, 0x0f, 0xb4, 0x36, 0x04, 0x00, // lfs esi,d:0x0004
+ 0x66, 0x0f, 0xb5, 0x3e, 0x04, 0x00, // lgs edi,d:0x0004
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x10, 0x00, // push 0x0010
+ 0x9d, // popf
+ 0x37, // aaa
+ 0xd5, 0x0a, // aad
+ 0xd4, 0x0a, // aam
+ 0x27, // daa
+ 0x2f, // das
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x01, 0x00, // push 0x0001
+ 0x9d, // popf
+ 0x37, // aaa
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x10, 0x00, // push 0x0010
+ 0x9d, // popf
+ 0x3f, // aas
+ 0xd5, 0x0a, // aad
+ 0xd4, 0x0a, // aam
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x01, 0x00, // push 0x0001
+ 0x9d, // popf
+ 0x3f, // aas
+ 0xb8, 0x05, 0x00, // mov ax, 0x0005
+ 0xb9, 0x20, 0x00, // mov cx, 0x0020
+ 0xf8, // clc
+ 0x0f, 0xa3, 0xc1, // bt cx, ax
+ 0xf8, // clc
+ 0x0f, 0xb3, 0xc1, // btr cx, ax
+ 0xf9, // stc
+ 0x0f, 0xab, 0xc1, // bts cx, ax
+ 0xf8, // clc
+ 0x0f, 0xbb, 0xc1, // btc cx, ax
+ 0x66, 0xb8, 0x15, 0x00, 0x00, 0x00, // mov eax, 0x00000015
+ 0x66, 0xb9, 0x00, 0x00, 0x20, 0x00, // mov ecx, 0x00200000
+ 0xf8, // clc
+ 0x66, 0x0f, 0xa3, 0xc1, // bt ecx, eax
+ 0xf8, // clc
+ 0x66, 0x0f, 0xb3, 0xc1, // btr ecx, eax
+ 0xf9, // stc
+ 0x66, 0x0f, 0xab, 0xc1, // bts ecx, eax
+ 0xf8, // clc
+ 0x66, 0x0f, 0xbb, 0xc1, // btc ecx, eax
+ 0xb9, 0x20, 0x00, // mov cx, 0x0020
+ 0xf8, // clc
+ 0x0f, 0xba, 0xe1, 0x05, // bt cx, 0x05
+ 0xf8, // clc
+ 0x0f, 0xba, 0xf1, 0x05, // btr cx, 0x05
+ 0xf9, // stc
+ 0x0f, 0xba, 0xe9, 0x05, // bts cx, 0x05
+ 0xf8, // clc
+ 0x0f, 0xba, 0xf9, 0x05, // btc cx, 0x05
+ 0x66, 0xb9, 0x00, 0x00, 0x20, 0x00, // mov ecx, 0x00200000
+ 0xf8, // clc
+ 0x66, 0x0f, 0xba, 0xe1, 0x15, // bt ecx, 0x15
+ 0xf8, // clc
+ 0x66, 0x0f, 0xba, 0xf1, 0x15, // btr ecx, 0x15
+ 0xf9, // stc
+ 0x66, 0x0f, 0xba, 0xe9, 0x15, // bts ecx, 0x15
+ 0xf8, // clc
+ 0x66, 0x0f, 0xba, 0xf9, 0x15, // btc ecx, 0x15
+ 0x66, 0xb8, 0x20, 0x00, 0x00, 0x00, // mov eax, 0x00000020
+ 0x66, 0x89, 0x06, 0x08, 0x00, // mov ds:0x0008, eax
+ 0xb8, 0x45, 0x00, // mov ax, 0x0045
+ 0xf8, // clc
+ 0x0f, 0xa3, 0x06, 0x00, 0x00, // bt ds:0x0000, ax
+ 0xf8, // clc
+ 0x0f, 0xb3, 0x06, 0x00, 0x00, // btr ds:0x0000, ax
+ 0xf9, // stc
+ 0x0f, 0xab, 0x06, 0x00, 0x00, // bts ds:0x0000, ax
+ 0xf8, // clc
+ 0x0f, 0xbb, 0x06, 0x00, 0x00, // btc ds:0x0000, ax
+ 0x66, 0xb8, 0x00, 0x00, 0x20, 0x00, // mov eax, 0x00200000
+ 0x66, 0x89, 0x06, 0x08, 0x00, // mov ds:0x0008, eax
+ 0x66, 0xb8, 0x55, 0x00, 0x00, 0x00, // mov eax, 0x00000055
+ 0xf8, // clc
+ 0x66, 0x0f, 0xa3, 0x06, 0x00, 0x00, // bt ds:0x0000, eax
+ 0xf8, // clc
+ 0x66, 0x0f, 0xb3, 0x06, 0x00, 0x00, // btr ds:0x0000, eax
+ 0xf9, // stc
+ 0x66, 0x0f, 0xab, 0x06, 0x00, 0x00, // bts ds:0x0000, eax
+ 0xf8, // clc
+ 0x66, 0x0f, 0xbb, 0x06, 0x00, 0x00, // btc ds:0x0000, eax
+ 0xb8, 0xab, 0xab, // mov ax, 0xabab
+ 0xb9, 0x08, 0x00, // mov cx, 0x0008
+ 0xba, 0xfe, 0xfe, // mov dx, 0xfefe
+ 0x0f, 0xa4, 0xc2, 0x04, // shld dx, ax, 0x04
+ 0x0f, 0xa5, 0xc2, // shld dx, ax, cl
+ 0x66, 0xb8, 0xab, 0xab, 0xa5, 0x5a, // mov eax, 0x5aa5abab
+ 0xb9, 0x08, 0x00, // mov cx, 0x0008
+ 0x66, 0xba, 0xfe, 0xfe, 0x12, 0x21, // mov edx, 0x2112fefe
+ 0x66, 0x0f, 0xa4, 0xc2, 0x04, // shld edx, eax, 0x04
+ 0x66, 0x0f, 0xa5, 0xc2, // shld edx, eax, cl
+ 0xb8, 0xab, 0xab, // mov ax, 0xabab
+ 0xb9, 0x08, 0x00, // mov cx, 0x0008
+ 0xba, 0xfe, 0xfe, // mov dx, 0xfefe
+ 0x0f, 0xac, 0xd0, 0x04, // shld ax, dx, 0x04
+ 0x0f, 0xad, 0xd0, // shld ax, dx, cl
+ 0x66, 0xb8, 0xab, 0xab, 0xa5, 0x5a, // mov eax, 0x5aa5abab
+ 0xb9, 0x08, 0x00, // mov cx, 0x0008
+ 0x66, 0xba, 0xfe, 0xfe, 0x12, 0x21, // mov edx, 0x2112fefe
+ 0x66, 0x0f, 0xac, 0xd0, 0x04, // shld eax, edx, 0x04
+ 0x66, 0x0f, 0xad, 0xd0, // shld eax, edx, cl
+ 0xb0, 0xaa, // mov al, 0xaa
+ 0xc0, 0xe0, 0x02, // shl al, 0x02
+ 0xb0, 0xaa, // mov al, 0xaa
+ 0xc0, 0xe8, 0x03, // shl al, 0x03
+ 0xb0, 0xaa, // mov al, 0xaa
+ 0xc0, 0xf8, 0x04, // shl al, 0x04
+// 0xe8, 0x02, 0x00, // call 0x0002
+ 0x9a, 0x03, 0x00, 0x00, 0x20, // call 0x0003:0x2000
+// 0x66, 0xe8, 0x04, 0x00, 0x00, 0x00, // call 0x00000004
+ 0x66, 0x9a, 0x06, 0x00, 0x00, 0x00, 0x00, 0x20, // call 0x00000006:0x2000
+ 0x66, 0xb8, 0x02, 0x00, 0x00, 0x20, // mov eax, 0x20000002
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0xff, 0x16, 0x04, 0x00, // call ds:0x0004
+ 0x66, 0xb8, 0x03, 0x00, 0x00, 0x20, // mov eax, 0x20000003
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0xff, 0x1e, 0x04, 0x00, // call ds:0x0004
+ 0xb8, 0xaa, 0xaa, // mov ax, 0xaaaa
+ 0xc1, 0xe0, 0x02, // shl ax, 0x02
+ 0xb8, 0xaa, 0xaa, // mov ax, 0xaaaa
+ 0xc1, 0xe8, 0x03, // shl ax, 0x03
+ 0xb8, 0xaa, 0xaa, // mov ax, 0xaaaa
+ 0xc1, 0xf8, 0x04, // shl ax, 0x04
+ 0x66, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, // mov eax, 0xaaaaaaaa
+ 0x66, 0xc1, 0xe0, 0x02, // shl eax, 0x02
+ 0x66, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, // mov eax, 0xaaaaaaaa
+ 0x66, 0xc1, 0xe8, 0x03, // shl eax, 0x03
+ 0x66, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, // mov eax, 0xaaaaaaaa
+ 0x66, 0xc1, 0xf8, 0x04, // shl eax, 0x04
+ 0xf0, 0x90, // lock nop
+ 0x66, 0xb8, 0x12, 0x34, 0x56, 0x78, // mov eax, 0x78563412
+ 0xe6, 0x04, // outb 0x04, al
+ 0xe7, 0x08, // outw 0x09, ax
+ 0x66, 0xe7, 0x0c, // outd 0x0c, eax
+ 0xba, 0x40, 0x00, // mov dx, 0x0040
+ 0xee, // outb dx, al
+ 0x42, // inc dx
+ 0x42, // inc dx
+ 0xef, // outw dx, ax
+ 0x42, // inc dx
+ 0x42, // inc dx
+ 0x66, 0xef, // outd dx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0xe4, 0x04, // inb al, 0x04
+ 0xe5, 0x08, // inw ax, 0x08
+ 0x66, 0xe5, 0x0c, // ind eax, 0x0c
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0xba, 0x40, 0x00, // mov dx, 0x0040
+ 0xec, // inb al, dx
+ 0x42, // inc dx
+ 0x42, // inc dx
+ 0xed, // inw ax, dx
+ 0x42, // inc dx
+ 0x42, // inc dx
+ 0x66, 0xed, // ind eax, dx
+// 0xf4, // hlt (nop)
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0x0f,0xbc, 0xc8, // bsf cx, ax
+ 0xb8, 0x00, 0x10, // mov ax, 0x1000
+ 0x0f,0xbc, 0xc8, // bsf cx, ax
+ 0xb8, 0x00, 0x00, // mov ax, 0x0000
+ 0x0f,0xbd, 0xc8, // bsr cx, ax
+ 0xb8, 0x10, 0x10, // mov ax, 0x1010
+ 0x0f,0xbd, 0xc8, // bsr cx, ax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0x66, 0x0f,0xbc, 0xc8, // bsf ecx, eax
+ 0x66, 0xb8, 0x00, 0x10, 0x00, 0x00, // mov eax, 0x00001000
+ 0x66, 0x0f,0xbc, 0xc8, // bsf ecx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x00000000
+ 0x66, 0x0f,0xbd, 0xc8, // bsr ecx, eax
+ 0x66, 0xb8, 0x10, 0x10, 0x00, 0x00, // mov eax, 0x00001010
+ 0x66, 0x0f,0xbd, 0xc8, // bsr ecx, eax
+ 0xcc, // int 3
+ 0xcd, 0x04, // int 0x04
+ 0xcd, 0x05, // int 0x05
+*/ 0x90, // nop
+ 0x66, 0xb8, 0x11, 0x22, 0x33, 0x44, // mov eax, 0x44332211
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0xb0, 0x01, // mov al, 0x01
+ 0xbb, 0x03, 0x00, // mov bx, 0x0003
+ 0xd7, // xlat
+ 0xb0, 0x02, // mov al, 0x01
+ 0x66, 0xbb, 0x04, 0x00, 0x00, 0x00, // mov ebx, 0x00000004
+ 0x67, 0xd7, // xlat
+ 0x66, 0xb8, 0x04, 0x00, 0x08, 0x00, // mov eax, 0x00080004
+ 0x66, 0x89, 0x06, 0x04, 0x00, // mov ds:0x0004, eax
+ 0x66, 0xb8, 0x04, 0x00, 0x08, 0x01, // mov eax, 0x01080004
+ 0x66, 0x89, 0x06, 0x08, 0x00, // mov ds:0x0008, eax
+ 0xb9, 0x04, 0x00, // mov cx, 0x0004
+ 0x62, 0x0e, 0x04, 0x00, // bound cx, ds:0x0004
+ 0x66, 0xb9, 0x04, 0x00, 0x08, 0x01, // mov ecx, 0x01080004
+ 0x66, 0x62, 0x0e, 0x04, 0x00, // bound ecx, ds:0x0004
+ 0x66, 0xb8, 0x11, 0x22, 0x33, 0x44, // mov eax, 0x44332211
+ 0x0f, 0xc8, 0xc0, // bswap ax
+ 0x66, 0xb8, 0x11, 0x22, 0x33, 0x44, // mov eax, 0x44332211
+ 0x66, 0x0f, 0xc8, 0xc0, // bswap eax
+ 0xb0, 0x01, // mov al, 0x01
+ 0xb1, 0x01, // mov cl, 0x01
+ 0xb2, 0xff, // mov dl, 0xff
+ 0x0f, 0xb0, 0xd1, // cmpxchg cl,dl
+ 0xb0, 0x01, // mov al, 0x01
+ 0xb1, 0x02, // mov cl, 0x02
+ 0xb2, 0xff, // mov dl, 0xff
+ 0x0f, 0xb0, 0xd1, // cmpxchg cl,dl
+ 0xb8, 0x01, 0x00, // mov ax, 0x01
+ 0xb9, 0x01, 0x00, // mov cx, 0x01
+ 0xba, 0xff, 0x00, // mov dx, 0xff
+ 0x0f, 0xb1, 0xd1, // cmpxchg cx,dx
+ 0xb8, 0x01, 0x00, // mov ax, 0x01
+ 0xb9, 0x02, 0x00, // mov cx, 0x02
+ 0xba, 0xff, 0x00, // mov dx, 0xff
+ 0x0f, 0xb1, 0xd1, // cmpxchg cx,dx
+ 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 0x00000001
+ 0x66, 0xb9, 0x01, 0x00, 0x00, 0x00, // mov ecx, 0x00000001
+ 0x66, 0xba, 0xff, 0x00, 0x00, 0x00, // mov edx, 0x000000ff
+ 0x66, 0x0f, 0xb1, 0xd1, // cmpxchg ecx,edx
+ 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 0x00000001
+ 0x66, 0xb9, 0x02, 0x00, 0x00, 0x00, // mov ecx, 0x00000002
+ 0x66, 0xba, 0xff, 0x00, 0x00, 0x00, // mov edx, 0x000000ff
+ 0x66, 0x0f, 0xb1, 0xd1, // cmpxchg ecx,edx
+ 0xb0, 0x01, // mov al, 0x01
+ 0xb1, 0x02, // mov cl, 0x02
+ 0x0f, 0xc0, 0xc8, // xadd al,cl
+ 0xb8, 0x01, 0x01, // mov ax, 0x0101
+ 0xb9, 0x02, 0x02, // mov cx, 0x0202
+ 0x0f, 0xc1, 0xc8, // xadd ax,cx
+ 0x66, 0xb8, 0x01, 0x01, 0x01, 0x01, // mov eax, 0x01010101
+ 0x66, 0xb9, 0x02, 0x02, 0x02, 0x02, // mov ecx, 0x02020202
+ 0x66, 0x0f, 0xc1, 0xc8, // xadd eax,ecx
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x10, 0x00, // push 0x0010
+ 0x9d, // popf
+ 0x37, // aaa
+ 0xd5, 0x0a, // aad
+ 0xd4, 0x0a, // aam
+ 0x27, // daa
+ 0x2f, // das
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x01, 0x00, // push 0x0001
+ 0x9d, // popf
+ 0x37, // aaa
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x10, 0x00, // push 0x0010
+ 0x9d, // popf
+ 0x3f, // aas
+ 0xd5, 0x0a, // aad
+ 0xd4, 0x0a, // aam
+ 0xb8, 0x03, 0x00, // mov ax, 0x0003
+ 0x68, 0x01, 0x00, // push 0x0001
+ 0x9d, // popf
+ 0x3f, // aas
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x90, 0xc0, // seto al
+ 0xb0, 0x83, // mov al, 0x83
+ 0x0f, 0x91, 0xc0, // setno al
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x80, // mov eax, 0x80000000
+ 0x66, 0xb9, 0x00, 0x00, 0x00, 0x80, // mov ecx, 0x80000000
+ 0x66, 0x01, 0xc1, // add ecx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0x80, // mov eax, 0x80000000
+ 0x66, 0xb9, 0x00, 0x00, 0x00, 0x80, // mov ecx, 0x80000000
+ 0x66, 0x29, 0xc1, // sub ecx, eax
+ 0x66, 0xb8, 0x00, 0x00, 0x00, 0xb0, // mov eax, 0xb0000000
+ 0x66, 0xb9, 0x00, 0x00, 0x00, 0x50, // mov ecx, 0x50000000
+ 0x66, 0x01, 0xc1, // add ecx, eax
+ 0x66, 0xb8, 0xac, 0x08, 0x02, 0x08, // mov eax, 0x080208ac
+ 0x66, 0xb9, 0x9b, 0x2a, 0xa4, 0xc8, // mov ecx, 0xc8a42a9b
+ 0xf9, // stc
+ 0x66, 0x1b, 0xc1, // sbb eax, ecx
+ 0x66, 0xb8, 0xcf, 0x33, 0xeb, 0xaf, // mov eax, 0xafeb33cf
+ 0x66, 0xb9, 0x85, 0xed, 0xa5, 0xd0, // mov ecx, 0xd0a5ed85
+ 0x66, 0x09, 0xc1, // or ecx, eax
+ 0xb4, 0xb3, // mov ah, 0xb3
+ 0xb5, 0x0e, // mov ch, 0x0e
+ 0x28, 0xe5, // sub ch, ah
+ 0x66, 0xbf, 0x64, 0x4b, 0x7d, 0xdc, // mov edi, 0xdc7d4b64
+ 0x66, 0xd1, 0xc7, // rol edi, 1
+ 0x66, 0xbe, 0xe7, 0x8b, 0x26, 0x34, // mov esi, 0x34268be7
+ 0x66, 0xb9, 0x88, 0x00, 0x00, 0x00, // mov ecx, 0x00000088
+ 0x66, 0xbf, 0x64, 0x4b, 0x7d, 0x8c, // mov edi, 0x8c7d4b64
+ 0x66, 0xd1, 0xc7, // rol edi, 1
+ 0x66, 0x0f, 0xa4, 0xce, 0x1b, // shld esi, ecx, 0x1b
+ 0x66, 0xbe, 0x98, 0x07, 0xe1, 0xeb, // mov esi, 0xebe10798
+ 0x66, 0xb9, 0xa6, 0x50, 0x9b, 0xee, // mov ecx, 0xee9b50a6
+ 0x66, 0xbf, 0x64, 0x4b, 0x7d, 0xdc, // mov edi, 0xdc7d4b64
+ 0x66, 0xd1, 0xc7, // rol edi, 1
+ 0x66, 0x0f, 0xac, 0xce, 0x17, // shrd esi, ecx, 0x17
+ 0xb0, 0x01, // mov al, 0x01
+ 0xb7, 0x04, // mov bh, 0x04
+ 0x0f, 0xb0, 0xc7, // cmpxchg bh, al
+ 0xcf, // iret
+ 0xff};
+
+//
+// Define stack storage space.
+//
+
+ULONG StackSpace[4096 / 4];
+ULONG DataSpace[4096 / 4];
+ULONG IoSpace[4096 / 4];
+
+//
+// Define read and write I/O space functions.
+//
+
+ULONG
+ReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+{
+ if (DataType == BYTE_DATA) {
+ return *((UCHAR UNALIGNED *)((PUCHAR)(&IoSpace) + PortNumber));
+
+ } else if (DataType == LONG_DATA) {
+ return *((ULONG UNALIGNED *)((PUCHAR)(&IoSpace) + PortNumber));
+
+ } else {
+ return *((USHORT UNALIGNED *)((PUCHAR)(&IoSpace) + PortNumber));
+ }
+}
+
+VOID
+WriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+{
+
+ if (DataType == BYTE_DATA) {
+ *((UCHAR UNALIGNED *)((PUCHAR)(&IoSpace) + PortNumber)) = (UCHAR)Value;
+
+ } else if (DataType == LONG_DATA) {
+ *((ULONG UNALIGNED *)((PUCHAR)(&IoSpace) + PortNumber)) = Value;
+
+ } else {
+ *((USHORT UNALIGNED *)((PUCHAR)(&IoSpace) + PortNumber)) = (USHORT)Value;
+ }
+
+ return;
+}
+
+//
+// Define address translation routine.
+//
+
+PVOID
+TranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+{
+
+ ULONG Value;
+
+ //
+ // Case on high hex digit of segment.
+ //
+
+ Value = Offset + (Segment << 4);
+ Offset = (USHORT)Value;
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ return (PVOID)((PUCHAR)&StackSpace + Offset);
+
+ //
+ // Data space.
+ //
+
+ case 0x1:
+ return (PVOID)((PUCHAR)&DataSpace + Offset);
+
+ //
+ // Code space.
+ //
+
+ case 0x2:
+ return (PVOID)((PUCHAR)&CodeStream + Offset);
+
+ //
+ // No valid translation.
+ //
+
+ default:
+ return NULL;
+ }
+}
+
+VOID
+__cdecl
+main(
+ int argc,
+ char *argv[]
+ )
+
+{
+
+ XM86_CONTEXT Context;
+ PULONG Vector = &StackSpace[0];
+
+ //
+ // Initialize the emulator.
+ //
+
+ XmInitializeEmulator(0,
+ 0x1000,
+ ReadIoSpace,
+ WriteIoSpace,
+ TranslateAddress);
+
+ //
+ // Initialize vector 255 and emulate an interrupt through that
+ // vector.
+ //
+
+ Vector[3] = (0x2000 << 16) | 0x0008;
+ Vector[4] = (0x2000 << 16) | 0x0008;
+ Vector[5] = (0x2000 << 16) | 0x0008;
+ Vector[255] = (0x2000 << 16) | 0x0000;
+ Context.Eax = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Ebx = 0;
+ Context.Ebp = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ XmContext.SegmentRegister[DS] = 0x1000;
+ XmEmulateInterrupt(255, &Context);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/makefile b/private/ntos/nthals/x86new/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/x86new/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/x86new/mips/sources b/private/ntos/nthals/x86new/mips/sources
new file mode 100644
index 000000000..2d172b717
--- /dev/null
+++ b/private/ntos/nthals/x86new/mips/sources
@@ -0,0 +1,24 @@
+MIPS_SOURCES=..\emulate.c \
+ ..\addops.c \
+ ..\asciiops.c \
+ ..\bitops.c \
+ ..\condops.c \
+ ..\ctrlops.c \
+ ..\data.c \
+ ..\debug.c \
+ ..\divops.c \
+ ..\inoutops.c \
+ ..\jmpops.c \
+ ..\logops.c \
+ ..\miscops.c \
+ ..\moveops.c \
+ ..\mulops.c \
+ ..\operand.c \
+ ..\pcibios.c \
+ ..\regmode.c \
+ ..\setops.c \
+ ..\shiftops.c \
+ ..\stackops.c \
+ ..\stringop.c \
+ ..\utility.c \
+ ..\x86bios.c
diff --git a/private/ntos/nthals/x86new/miscops.c b/private/ntos/nthals/x86new/miscops.c
new file mode 100644
index 000000000..5cfd3cf2c
--- /dev/null
+++ b/private/ntos/nthals/x86new/miscops.c
@@ -0,0 +1,179 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ miscops.c
+
+Abstract:
+
+ This module implements the code to emulate miscellaneous opcodes.
+
+Author:
+
+ David N. Cutler (davec) 22-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmBoundOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a bound opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ union {
+ LONG Long;
+ SHORT Word;
+ } LowerBound;
+
+ union {
+ LONG Long;
+ SHORT Word;
+ } UpperBound;
+
+ ULONG Offset;
+
+ //
+ // Get lower and upper bounds and check index against index value.
+ //
+
+ Offset = P->SrcValue.Long;
+ XmSetSourceValue(P, XmGetOffsetAddress(P, Offset));
+ LowerBound.Long = P->SrcValue.Long;
+ XmSetSourceValue(P, XmGetOffsetAddress(P, Offset + P->DataType + 1));
+ UpperBound.Long = P->SrcValue.Long;
+ if (P->DataType == LONG_DATA) {
+ if (((LONG)(*P->DstLong) < LowerBound.Long) ||
+ ((LONG)(*P->DstLong) > (UpperBound.Long + (LONG)(P->DataType + 1)))) {
+ longjmp(&P->JumpBuffer[0], XM_INDEX_OUT_OF_BOUNDS);
+ }
+
+ } else {
+ if (((SHORT)(*P->DstWord) < LowerBound.Word) ||
+ ((SHORT)(*P->DstWord) > (UpperBound.Word + (SHORT)(P->DataType + 1)))) {
+ longjmp(&P->JumpBuffer[0], XM_INDEX_OUT_OF_BOUNDS);
+ }
+ }
+
+ return;
+}
+
+VOID
+XmBswapOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a bswap opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Result;
+
+ //
+ // Swap bytes and set result value.
+ //
+
+ Result = (P->SrcValue.Long << 24) | ((P->SrcValue.Long & 0xff00) << 8) |
+ (P->SrcValue.Long >> 24) | ((P->SrcValue.Long >> 8) & 0xff00);
+
+ XmStoreResult(P, Result);
+ return;
+}
+
+VOID
+XmIllOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an illegal opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Raise an illegal opcode exception.
+ //
+
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_INSTRUCTION_OPCODE);
+ return;
+}
+
+VOID
+XmNopOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a nop opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/x86new/moveops.c b/private/ntos/nthals/x86new/moveops.c
new file mode 100644
index 000000000..d0f6b315a
--- /dev/null
+++ b/private/ntos/nthals/x86new/moveops.c
@@ -0,0 +1,179 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ movops.c
+
+Abstract:
+
+ This module implements the code to emulate the move and exchange
+ opcodes.
+
+Author:
+
+ David N. Cutler (davec) 22-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmCbwOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cbw opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sign extend byte to word or word to double.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ XmStoreResult(P, (ULONG)((LONG)((SHORT)P->Gpr[AX].Xx)));
+
+ } else {
+ P->DataType = WORD_DATA;
+ XmStoreResult(P, (ULONG)((USHORT)((SCHAR)P->Gpr[AL].Xl)));
+ }
+
+ return;
+}
+
+VOID
+XmCwdOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cwd opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sign extend word to double or double to quad.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EDX].Exx);
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ XmStoreResult(P, (ULONG)((LONG)P->Gpr[EAX].Exx >> 31));
+
+ } else {
+ P->DataType = WORD_DATA;
+ XmStoreResult(P, (ULONG)((USHORT)((SHORT)P->Gpr[AX].Xx >> 16)));
+ }
+
+ return;
+}
+
+VOID
+XmMovOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a move general opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Move source to destination.
+ //
+
+ XmStoreResult(P, P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmXchgOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a xchg opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Exchange source with destination.
+ //
+
+ if (P->DataType == BYTE_DATA) {
+ *P->SrcByte = P->DstValue.Byte;
+
+ } else if (P->DataType == LONG_DATA) {
+ *P->SrcLong = P->DstValue.Long;
+
+ } else {
+ *P->SrcWord = P->DstValue.Word;
+ }
+
+ XmStoreResult(P, P->SrcValue.Long);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/mulops.c b/private/ntos/nthals/x86new/mulops.c
new file mode 100644
index 000000000..cc020d392
--- /dev/null
+++ b/private/ntos/nthals/x86new/mulops.c
@@ -0,0 +1,202 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ mulops.c
+
+Abstract:
+
+ This module implements the code to emulate the mul and imul opcodes.
+
+Author:
+
+ David N. Cutler (davec) 21-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmImulOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an imul opcode with a single destination.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LARGE_INTEGER Product;
+ ULONG UpperEqual;
+
+ //
+ // Multiply the signed operands and store result.
+ //
+
+ if (P->DataType == BYTE_DATA) {
+ Product.QuadPart = Int32x32To64((LONG)((SCHAR)P->DstValue.Byte),
+ (LONG)((SCHAR)P->SrcValue.Byte));
+
+ XmStoreResult(P, Product.LowPart & 0xff);
+ UpperEqual = ((UCHAR)((Product.LowPart >> 8) & 0xff) !=
+ (UCHAR)((SCHAR)Product.LowPart >> 7));
+
+ } else if (P->DataType == LONG_DATA) {
+ Product.QuadPart = Int32x32To64((LONG)P->DstValue.Long,
+ (LONG)P->SrcValue.Long);
+
+ XmStoreResult(P, Product.LowPart);
+ UpperEqual = (Product.HighPart != (LONG)Product.LowPart >> 31);
+
+ } else {
+ Product.QuadPart = Int32x32To64((LONG)((SHORT)P->DstValue.Word),
+ (LONG)((SHORT)P->SrcValue.Word));
+
+ XmStoreResult(P, Product.LowPart & 0xffff);
+ UpperEqual = ((USHORT)((Product.LowPart >> 16) & 0xffff) !=
+ (USHORT)((SHORT)Product.LowPart >> 15));
+ }
+
+ P->Eflags.CF = UpperEqual;
+ P->Eflags.OF = UpperEqual;
+ return;
+}
+
+VOID
+XmImulxOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an imul opcode with an extended destination.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LARGE_INTEGER Product;
+ ULONG UpperEqual;
+
+ //
+ // Multiply the signed operands and store the result and the extended
+ // result.
+ //
+
+ if (P->DataType == BYTE_DATA) {
+ Product.QuadPart = Int32x32To64((LONG)((SCHAR)P->DstValue.Byte),
+ (LONG)((SCHAR)P->SrcValue.Byte));
+
+ P->DataType = WORD_DATA;
+ XmStoreResult(P, Product.LowPart & 0xffff);
+ UpperEqual = (P->Gpr[AX].Xh != (UCHAR)((SCHAR)P->Gpr[AX].Xl >> 7));
+
+ } else if (P->DataType == LONG_DATA) {
+ Product.QuadPart = Int32x32To64((LONG)P->DstValue.Long,
+ (LONG)P->SrcValue.Long);
+
+ XmStoreResult(P, Product.LowPart);
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
+ XmStoreResult(P, (ULONG)Product.HighPart);
+ UpperEqual = (Product.HighPart != (LONG)Product.LowPart >> 31);
+
+ } else {
+ Product.QuadPart = Int32x32To64((LONG)((SHORT)P->DstValue.Word),
+ (LONG)((SHORT)P->SrcValue.Word));
+
+ XmStoreResult(P, Product.LowPart & 0xffff);
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[DX].Exx);
+ XmStoreResult(P, Product.LowPart >> 16);
+ UpperEqual = (P->Gpr[DX].Xx != (USHORT)((SHORT)P->Gpr[AX].Xx >> 15));
+ }
+
+ P->Eflags.CF = UpperEqual;
+ P->Eflags.OF = UpperEqual;
+ return;
+}
+
+VOID
+XmMulOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a mul opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULARGE_INTEGER Product;
+ ULONG UpperZero;
+
+ //
+ // Multiply the unsigned operands and store result.
+ //
+
+ Product.QuadPart = UInt32x32To64(P->DstValue.Long, P->SrcValue.Long);
+ if (P->DataType == BYTE_DATA) {
+ P->DataType = WORD_DATA;
+ XmStoreResult(P, Product.LowPart);
+ UpperZero = (P->Gpr[AX].Xh != 0);
+
+ } else if (P->DataType == LONG_DATA) {
+ XmStoreResult(P, Product.LowPart);
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
+ XmStoreResult(P, Product.HighPart);
+ UpperZero = (Product.HighPart != 0);
+
+ } else {
+ XmStoreResult(P, Product.LowPart & 0xffff);
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[DX].Exx);
+ XmStoreResult(P, Product.LowPart >> 16);
+ UpperZero = (P->Gpr[DX].Xx != 0);
+ }
+
+ P->Eflags.CF = UpperZero;
+ P->Eflags.OF = UpperZero;
+ return;
+}
diff --git a/private/ntos/nthals/x86new/operand.c b/private/ntos/nthals/x86new/operand.c
new file mode 100644
index 000000000..bc2b617b5
--- /dev/null
+++ b/private/ntos/nthals/x86new/operand.c
@@ -0,0 +1,2026 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ operand.c
+
+Abstract:
+
+ This module implements the operand functions necessary to decode x86
+ instruction operands.
+
+Author:
+
+ David N. Cutler (davec) 3-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+ULONG
+XmPushPopSegment (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Push or pop segment register.
+ //
+
+ Index = P->OpcodeControl.FormatType;
+ P->DataType = WORD_DATA;
+ if (P->FunctionIndex == X86_PUSH_OP) {
+ XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Index]));
+
+ } else {
+ XmSetDestinationValue(P, (PVOID)(&P->SegmentRegister[Index]));
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmLoadSegment (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Index;
+ ULONG DataType;
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Load a segment register and a displacement value into register.
+ //
+
+ Index = P->OpcodeControl.FormatType;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if (P->RegisterOffsetAddress != FALSE) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
+ }
+
+ XmSetSourceValue(P, Operand);
+ DataType = P->DataType;
+ P->DataType = WORD_DATA;
+ Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1);
+ XmSetDestinationValue(P, Operand);
+ P->SegmentRegister[Index - FormatLoadSegmentES] = P->DstValue.Word;
+ P->DataType = DataType;
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
+ return TRUE;
+}
+
+ULONG
+XmGroup1General (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Group 1 opcodes with general operand specifier and a direction
+ // bit.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
+ XmSetDestinationValue(P, Operand);
+ XmSetSourceValue(P, XmGetRegisterAddress(P, Number));
+
+ } else {
+ XmSetDestinationValue(P, XmGetRegisterAddress(P, Number));
+ XmSetSourceValue(P, Operand);
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmGroup1Immediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Group 1 opcode with general operand specifier and an immediate
+ // operand.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
+ XmSetDestinationValue(P, Operand);
+ XmSetImmediateSourceValue(P, Source);
+ P->FunctionIndex += Number;
+ return TRUE;
+}
+
+ULONG
+XmGroup2By1 (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Group 2 shift opcodes with a general operand specifier and a
+ // shift count of 1.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ Source = 1;
+ XmSetImmediateSourceValue(P, Source);
+ XmSetDestinationValue(P, Operand);
+ P->FunctionIndex += Number;
+ return TRUE;
+}
+
+ULONG
+XmGroup2ByCL (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Group 2 shift opcodes with a general operand specifier and a
+ // CL shift count.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ Source = (ULONG)P->Gpr[CL].Xl & 0x1f;
+ XmSetImmediateSourceValue(P, Source);
+ XmSetDestinationValue(P, Operand);
+ P->FunctionIndex += Number;
+ return TRUE;
+}
+
+ULONG
+XmGroup2ByByte (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Group 2 shift opcodes with a general operand specifier and a
+ // byte immediate shift count.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ Source = XmGetByteImmediate(P) & 0x1f;
+ XmSetImmediateSourceValue(P, Source);
+ XmSetDestinationValue(P, Operand);
+ P->FunctionIndex += Number;
+ return TRUE;
+}
+
+ULONG
+XmGroup3General (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Group 3 opcodes with general operand specifier.
+ //
+ // N.B. The test operator for this group has an immediate operand
+ // and the multiply and divide operators use the accumulator
+ // as a source. The not and neg operators are unary.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ P->FunctionIndex += Number;
+ if (P->FunctionIndex == X86_TEST_OP) {
+ Source = XmGetImmediateSourceValue(P, 0);
+ XmSetDestinationValue(P, Operand);
+ XmSetImmediateSourceValue(P, Source);
+
+ } else {
+
+ //
+ // If the operation is a mulitply or divide, then there is an
+ // implied operand which is AL, AX, or EAX. If the operation is
+ // a divide, then there is an additional implied operand which
+ // is AH, DX, or EDX.
+ //
+
+ if ((Number & 0x4) != 0) {
+ if ((Number & 0x2) == 0) {
+ XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
+
+ } else {
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EAX].Exx);
+ }
+
+ XmSetSourceValue(P, Operand);
+
+ } else {
+ XmSetDestinationValue(P, Operand);
+ }
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmGroup45General (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG DataType;
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Group 4 and group 5 unary opcodes with general operand specifier.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if (P->OpcodeControl.FormatType == FormatGroup4General) {
+ Number &= 0x1;
+ }
+
+ P->FunctionIndex += Number;
+ if (P->FunctionIndex == X86_PUSH_OP) {
+ XmSetSourceValue(P, Operand);
+
+ } else {
+
+ //
+ // If the operation is a call or jump that specifies a segment,
+ // then get the segment value.
+ //
+
+ XmSetDestinationValue(P, Operand);
+ if ((Number == 3) || (Number == 5)) {
+ if (P->RegisterOffsetAddress != FALSE) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
+ }
+
+ DataType = P->DataType;
+ P->DataType = WORD_DATA;
+ Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1);
+ XmSetSourceValue(P, Operand);
+ P->DstSegment = P->SrcValue.Word;
+ P->DataType = DataType;
+ }
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmGroup8BitOffset (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Offset;
+ ULONG Number;
+
+ //
+ // Bit test opcodes with an immediate bit offset and a memory or
+ // register operand.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ Offset = XmGetByteImmediate(P);
+ XmSetImmediateSourceValue(P, Offset);
+ if (P->RegisterOffsetAddress == FALSE) {
+ if (P->DataType == LONG_DATA) {
+ Offset = (P->SrcValue.Long >> 5) << 2;
+
+ } else {
+ Offset = (P->SrcValue.Long >> 4) << 1;
+ }
+
+ Operand = XmGetOffsetAddress(P, Offset + P->Offset);
+ }
+
+ if (P->DataType == LONG_DATA) {
+ P->SrcValue.Long &= 0x1f;
+
+ } else {
+ P->SrcValue.Long &= 0xf;
+ }
+
+ XmSetDestinationValue(P, Operand);
+ P->FunctionIndex += (Number & 0x3);
+ return TRUE;
+}
+
+ULONG
+XmOpcodeRegister (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Number;
+
+ //
+ // Unary opodes with a general register encoded in the low
+ // 3 bits of the opcode value.
+ //
+
+ Number = P->CurrentOpcode & 0x7;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if (P->FunctionIndex == X86_PUSH_OP) {
+ XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
+
+ } else {
+ XmSetDestinationValue(P, (PVOID)(&P->Gpr[Number].Exx));
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmLongJump (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Offset;
+
+ //
+ // Long jump with opcode containing the control for conditional
+ // jumps. The destination of the jump is stored in the destination
+ // value and the jump control is stored in the sources value.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ Offset = XmGetLongImmediate(P);
+ P->DstValue.Long = P->Eip + Offset;
+
+ } else {
+ Offset = XmGetWordImmediate(P);
+ P->DstValue.Long = (USHORT)(Offset + P->Eip);
+ }
+
+ P->SrcValue.Long = P->CurrentOpcode & 0xf;
+ return TRUE;
+}
+
+ULONG
+XmShortJump (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Offset;
+
+ //
+ // Short jump with opcode containing the control for conditional
+ // jumps. The destination of the jump is stored in the destination
+ // value and the jump control is stored in the sources value.
+ //
+
+ Offset = (ULONG)XmGetSignedByteImmediateToWord(P);
+ P->DstValue.Long = (USHORT)(Offset + P->Eip);
+ P->SrcValue.Long = P->CurrentOpcode & 0xf;
+ return TRUE;
+}
+
+ULONG
+XmSetccByte (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Number;
+
+ //
+ // General byte destination with reg field ignored and the opcode
+ // containing the condition control.
+ //
+
+ P->DataType = BYTE_DATA;
+ P->DstByte = (UCHAR UNALIGNED *)XmEvaluateAddressSpecifier(P, &Number);
+ P->SrcValue.Long = P->CurrentOpcode & 0xf;
+ return TRUE;
+}
+
+ULONG
+XmAccumImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Source;
+
+ //
+ // Accumulator destination and immediate source operands.
+ //
+
+ XmSetDataType(P);
+ Source = XmGetImmediateSourceValue(P, 0);
+ XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
+ XmSetImmediateSourceValue(P, Source);
+ return TRUE;
+}
+
+ULONG
+XmAccumRegister (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Number;
+
+ //
+ // Accumulator destination and a general register source encoded in
+ // the low 3-bits of the opcode value.
+ //
+
+ Number = P->CurrentOpcode & 0x7;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
+ XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
+ return TRUE;
+}
+
+ULONG
+XmMoveGeneral (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Move opcodes with general operand specifier and a direction bit.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
+ P->DstLong = (ULONG UNALIGNED *)Operand;
+ XmSetSourceValue(P, XmGetRegisterAddress(P, Number));
+
+ } else {
+ P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number);
+ XmSetSourceValue(P, Operand);
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmMoveImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Move opcodes with general operand specifier and an immediate
+ // operand.
+ //
+
+ XmSetDataType(P);
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ P->DstLong = (ULONG UNALIGNED *)Operand;
+ Source = XmGetImmediateSourceValue(P, 0);
+ XmSetImmediateSourceValue(P, Source);
+ return TRUE;
+}
+
+ULONG
+XmMoveRegImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Number;
+
+ //
+ // Move register immediate opcodes with a general register encoded
+ // in the low 3-bits of the opcode value and an immediate operand.
+ //
+
+ Number = P->CurrentOpcode & 0x7;
+ if ((P->CurrentOpcode & 0x8) == 0) {
+ P->DataType = BYTE_DATA;
+
+ } else {
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+ }
+
+ P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number);
+ XmSetImmediateSourceValue(P, XmGetImmediateSourceValue(P, 0));
+ return TRUE;
+}
+
+ULONG
+XmSegmentOffset (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Offset;
+
+ //
+ // Move opcodes with an implied accumlator operand and an immediate
+ // segment offset and a direction bit.
+ //
+
+ XmSetDataType(P);
+ if (P->OpaddrPrefixActive != FALSE) {
+ Offset = XmGetLongImmediate(P);
+
+ } else {
+ Offset = XmGetWordImmediate(P);
+ }
+
+ Operand = XmGetOffsetAddress(P, Offset);
+ if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
+ XmSetSourceValue(P, Operand);
+
+ } else {
+ P->DstLong = (ULONG UNALIGNED *)Operand;
+ XmSetSourceValue(P, &P->Gpr[EAX].Exx);
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmMoveSegment (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Move segment opcodes with general operand specifier and a direction
+ // bit.
+ //
+
+ P->DataType = WORD_DATA;
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
+ P->DstLong = (ULONG UNALIGNED *)Operand;
+ XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Number]));
+
+ } else {
+ P->DstLong = (ULONG UNALIGNED *)(&P->SegmentRegister[Number]);
+ XmSetSourceValue(P, Operand);
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmMoveXxGeneral (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Move zero or sign extended opcodes with general operand specifier.
+ //
+
+ if ((P->CurrentOpcode & WIDTH_BIT) == 0) {
+ P->DataType = BYTE_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ XmSetSourceValue(P, Operand);
+ if (P->DataType == BYTE_DATA) {
+ if ((P->CurrentOpcode & 0x8) == 0) {
+ P->SrcValue.Long = (ULONG)P->SrcValue.Byte;
+
+ } else {
+ P->SrcValue.Long = (ULONG)((LONG)((SCHAR)P->SrcValue.Byte));
+ }
+
+ } else {
+ if ((P->CurrentOpcode & 0x8) == 0) {
+ P->SrcValue.Long = (ULONG)P->SrcValue.Word;
+
+ } else {
+ P->SrcValue.Long = (ULONG)((LONG)((SHORT)P->SrcValue.Word));
+ }
+ }
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ P->SrcValue.Long &= 0xffff;
+ }
+
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx);
+ return TRUE;
+}
+
+ULONG
+XmFlagsRegister (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Flags register source or destination with a stack source or
+ // destination.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if (P->FunctionIndex == X86_PUSH_OP) {
+ XmSetSourceValue(P, (PVOID)(&P->AllFlags));
+
+ } else {
+ XmSetDestinationValue(P, (PVOID)(&P->AllFlags));
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmPushImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Source;
+
+ //
+ // Push opcode with an immediate operand.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
+ XmSetImmediateSourceValue(P, Source);
+ return TRUE;
+}
+
+ULONG
+XmPopGeneral (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Pop opcode with a general specifier.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ XmSetDestinationValue(P, Operand);
+ return TRUE;
+}
+
+ULONG
+XmImulImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Number;
+ PVOID Operand;
+ ULONG Source;
+
+ //
+ // Multiply signed opcode with a general specifier and an immediate
+ // operand.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
+ XmSetImmediateSourceValue(P, Source);
+ XmSetDestinationValue(P, Operand);
+ P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx);
+ return TRUE;
+}
+
+ULONG
+XmStringOperands (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // String opcode with implicit operands of eSI and eDI.
+ //
+
+ XmSetDataType(P);
+ return TRUE;
+}
+
+ULONG
+XmEffectiveOffset (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Effective offset opcodes with general operand specifier.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->ComputeOffsetAddress = TRUE;
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if (P->RegisterOffsetAddress != FALSE) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
+ }
+
+ P->SrcValue.Long = (ULONG)Operand;
+ XmTraceSource(P, P->SrcValue.Long);
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
+ return TRUE;
+}
+
+ULONG
+XmImmediateJump (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Immediate long jump with the destination offset and new CS
+ // segment value. The destination of the jump is stored in the
+ // destination value and the new CS segment value is stored in
+ // destination segment.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DstValue.Long = XmGetLongImmediate(P);
+
+ } else {
+ P->DstValue.Long = XmGetWordImmediate(P);
+ }
+
+ P->DstSegment = XmGetWordImmediate(P);
+ return TRUE;
+}
+
+ULONG
+XmImmediateEnter (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ enter
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Enter operands with an allocation size and level number.
+ //
+
+ P->SrcValue.Long = XmGetWordImmediate(P);
+ P->DstValue.Long = XmGetByteImmediate(P) & 0x1f;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ return TRUE;
+}
+
+ULONG
+XmGeneralBitOffset (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Offset;
+ ULONG Number;
+
+ //
+ // Bit test opcodes with a register bit offset and a memory or
+ // register operand.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
+ if (P->RegisterOffsetAddress == FALSE) {
+ if (P->DataType == LONG_DATA) {
+ Offset = (P->SrcValue.Long >> 5) << 2;
+
+ } else {
+ Offset = (P->SrcValue.Long >> 4) << 1;
+ }
+
+ Operand = XmGetOffsetAddress(P, Offset + P->Offset);
+ }
+
+ if (P->DataType == LONG_DATA) {
+ P->SrcValue.Long &= 0x1f;
+
+ } else {
+ P->SrcValue.Long &= 0xf;
+ }
+
+ XmSetDestinationValue(P, Operand);
+ return TRUE;
+}
+
+ULONG
+XmShiftDouble (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ shld shrd
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+ ULONG Source;
+
+ //
+ // Shift double operators with an immediate byte or cl shift count.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if ((P->CurrentOpcode & 0x1) == 0) {
+ Source = XmGetByteImmediate(P);
+
+ } else {
+ Source = P->Gpr[CX].Xl;
+ }
+
+ if (P->DataType == LONG_DATA) {
+ P->Shift = (UCHAR)(Source & 0x1f);
+
+ } else {
+ P->Shift = (UCHAR)(Source & 0xf);
+ }
+
+ XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
+ XmSetDestinationValue(P, Operand);
+ return TRUE;
+}
+
+ULONG
+XmPortImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Source;
+
+ //
+ // In/out opcodes with an immediate port and all other operands implied.
+ //
+
+ Source = (ULONG)XmGetByteImmediate(P);
+ P->DataType = WORD_DATA;
+ XmSetImmediateSourceValue(P, Source);
+ XmSetDataType(P);
+ return TRUE;
+}
+
+ULONG
+XmPortDX (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Source;
+
+ //
+ // In/out opcodes with a port in DX with all other operands implied.
+ //
+
+ Source = P->Gpr[DX].Xx;
+ P->DataType = WORD_DATA;
+ XmSetImmediateSourceValue(P, Source);
+ XmSetDataType(P);
+ return TRUE;
+}
+
+ULONG
+XmBitScanGeneral (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // Bit scan general opcodes with general operand specifier.
+ // bit.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
+ XmSetSourceValue(P, Operand);
+ return TRUE;
+}
+
+ULONG
+XmByteImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ int xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ ULONG Source;
+
+ //
+ // int opcode with an immediate operand.
+ //
+
+ P->DataType = BYTE_DATA;
+ Source = XmGetImmediateSourceValue(P, 0);
+ XmSetImmediateSourceValue(P, Source);
+ return TRUE;
+}
+
+ULONG
+XmXlatOpcode (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xlat
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Offset;
+
+ //
+ // xlat opcode with zero extended [AL] + [eBX] as the effective
+ // address.
+ //
+
+ P->DataType = BYTE_DATA;
+ if (P->OpaddrPrefixActive != FALSE) {
+ Offset = P->Gpr[EBX].Exx + P->Gpr[AL].Xl;
+
+ } else {
+ Offset = P->Gpr[BX].Xx + P->Gpr[AL].Xl;
+ }
+
+ Operand = XmGetOffsetAddress(P, Offset);
+ XmSetSourceValue(P, Operand);
+ P->DstByte = (UCHAR UNALIGNED *)(&P->Gpr[AL].Xl);
+ return TRUE;
+}
+
+ULONG
+XmGeneralRegister (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ bswap
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ PVOID Operand;
+ ULONG Number;
+
+ //
+ // General register source and destination.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Operand = XmEvaluateAddressSpecifier(P, &Number);
+ if (P->RegisterOffsetAddress == FALSE) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_GENERAL_SPECIFIER);
+ }
+
+ XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
+ P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
+ return TRUE;
+}
+
+ULONG
+XmOpcodeEscape (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ 2-byte escape
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of xx is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Two byte opcode escape.
+ //
+
+ P->OpcodeControlTable = &XmOpcodeControlTable2[0];
+
+#if defined(XM_DEBUG)
+
+ P->OpcodeNameTable = &XmOpcodeNameTable2[0];
+
+#endif
+
+ return FALSE;
+}
+
+ULONG
+XmPrefixOpcode (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ CS: DS; ES: SS: FS: GS: lock adrsize
+ opsize repz repnz
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of FALSE is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Case on the function index.
+ //
+
+ switch (P->FunctionIndex) {
+
+ //
+ // Segment override prefix.
+ //
+ // Set the segment override prefix flags and the data segment
+ // number.
+ //
+
+ case X86_ES_OP:
+ case X86_CS_OP:
+ case X86_SS_OP:
+ case X86_DS_OP:
+ case X86_FS_OP:
+ case X86_GS_OP:
+ P->SegmentPrefixActive = TRUE;
+ P->DataSegment = P->FunctionIndex;
+ XmTraceOverride(P);
+ break;
+
+ //
+ // Lock prefix.
+ //
+ // Set the lock prefix flags.
+ //
+
+ case X86_LOCK_OP:
+ P->LockPrefixActive = TRUE;
+ break;
+
+ //
+ // Address size prefix.
+ //
+ // Set the address size prefix flag.
+ //
+
+ case X86_ADSZ_OP:
+ P->OpaddrPrefixActive = TRUE;
+ break;
+
+ //
+ // Operand size prefix.
+ //
+ // Set the operand size prefix flag.
+ //
+
+
+ case X86_OPSZ_OP:
+ P->OpsizePrefixActive = TRUE;
+ break;
+
+ //
+ // Repeat until ECX or ZF equals zero
+ //
+ // Set up repeat until ECX or ZF equals zero prefix flags.
+ //
+
+ case X86_REPZ_OP:
+ P->RepeatPrefixActive = TRUE;
+ P->RepeatZflag = 1;
+ break;
+
+ //
+ // Repeat until ECX equals zero or ZF equals one.
+ //
+ // Set up repeat until ECX equals zero or ZF equals one prefix
+ // flags.
+ //
+
+ case X86_REPNZ_OP:
+ P->RepeatPrefixActive = TRUE;
+ P->RepeatZflag = 0;
+ break;
+ }
+
+ return FALSE;
+}
+
+ULONG
+XmNoOperands (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers for the following opcodes:
+
+ xxxxxx
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ A completion status of TRUE is returned as the function value.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/x86new/pcibios.c b/private/ntos/nthals/x86new/pcibios.c
new file mode 100644
index 000000000..8415f0b5c
--- /dev/null
+++ b/private/ntos/nthals/x86new/pcibios.c
@@ -0,0 +1,618 @@
+/*++
+
+Module Name:
+
+ pcibios.c
+
+Abstract:
+
+ This module implements the INT 1a functions of the
+ PCI BIOS Specification revision 2.1, which makes
+ it possible to support video BIOSes that expect
+ to be able to read and write PCI configuration
+ space.
+
+ In order to read and write to PCI configuration
+ space, this code needs to call functions in the
+ HAL that know how configuration space is
+ implemented in the specific machine. There are
+ standard functions exported by the HAL to do
+ this, but they aren't usually available (i.e.
+ the bus handler code hasn't been set up yet) by
+ the time that the video needs to be initialized.
+ So the PCI BIOS functions in the emulator make
+ calls to XmGetPciData and XmSetPciData, which
+ are pointers to functions passed into the
+ emulator by the HAL. It is the responsibility of
+ the calling code to provide functions which match
+ these prototypes.
+
+Author:
+
+ Jake Oshins (joshins@vnet.ibm.com) 3-15-96
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+#include "pci.h"
+
+BOOLEAN
+XmExecuteInt1a (
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ The function calls the specific worker functions
+ based upon the contents of the registers in Context.
+
+Arguments:
+
+ Context - State of the emulator
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // If we aren't emulating PCI BIOS,
+ // return.
+ if (!XmPciBiosPresent) {
+ return FALSE;
+ }
+
+ //
+ // If this is not a call to PCI BIOS,
+ // ignore it.
+ //
+ if (Context->Gpr[EAX].Xh != PCI_FUNCTION_ID) {
+ return FALSE;
+ }
+
+ //
+ // Switch on AL to see which PCI BIOS function
+ // has been requested.
+ //
+ switch (Context->Gpr[EAX].Xl) {
+ case PCI_BIOS_PRESENT:
+
+ XmInt1aPciBiosPresent(Context);
+ break;
+
+ case PCI_FIND_DEVICE:
+
+ XmInt1aFindPciDevice(Context);
+ break;
+
+ case PCI_FIND_CLASS_CODE:
+
+ XmInt1aFindPciClassCode(Context);
+ break;
+
+ case PCI_GENERATE_CYCLE:
+
+ XmInt1aGenerateSpecialCycle(Context);
+ break;
+
+ case PCI_GET_IRQ_ROUTING:
+
+ XmInt1aGetRoutingOptions(Context);
+ break;
+
+ case PCI_SET_IRQ:
+
+ XmInt1aSetPciIrq(Context);
+ break;
+
+ case PCI_READ_CONFIG_BYTE:
+ case PCI_READ_CONFIG_WORD:
+ case PCI_READ_CONFIG_DWORD:
+
+ XmInt1aReadConfigRegister(Context);
+ break;
+
+ case PCI_WRITE_CONFIG_BYTE:
+ case PCI_WRITE_CONFIG_WORD:
+ case PCI_WRITE_CONFIG_DWORD:
+
+ XmInt1aWriteConfigRegister(Context);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID
+XmInt1aPciBiosPresent(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements PCI_BIOS_PRESENT.
+
+Arguments:
+
+ Context - State of the emulator
+
+Return Value:
+
+ None.
+
+--*/
+{
+ Context->Gpr[EDX].Exx = *(UNALIGNED PULONG)(&"PCI ");
+
+ // Present status is good:
+ Context->Gpr[EAX].Xh = 0x0;
+
+ // Hardware mechanism is:
+ // Standard config mechanisms not supported,
+ // Special cycles not supported
+ // i.e. We want all accesses to be done through software
+ Context->Gpr[EAX].Xl = 0x0;
+
+ // Interface level major version
+ Context->Gpr[EBX].Xh = 0x2;
+
+ // Interface level minor version
+ Context->Gpr[EBX].Xl = 0x10;
+
+ // Number of last PCI bus in system: TBD
+ // Context->Gpr[ECX].Xl = last PCI bus
+
+ // Present status good:
+ Context->Eflags.CF = 0x0;
+}
+
+VOID
+XmInt1aFindPciDevice(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements FIND_PCI_DEVICE.
+
+Arguments:
+
+ Context - State of the emulator
+ [AH] PCI_FUNCTION_ID
+ [AL] FIND_PCI_DEVICE
+ [CX] Device ID (0...65535)
+ [DX] Vendor ID (0...65534)
+ [SI] Index (0..N)
+
+
+Return Value:
+
+ [BH] Bus Number
+ [BL] Device Number, Function Number
+ [AH] return code
+ [CF] completion status
+--*/
+{
+ UCHAR Bus;
+ PCI_SLOT_NUMBER Slot;
+ ULONG Device;
+ ULONG Function;
+ ULONG Index = 0;
+ ULONG buffer;
+
+ if (Context->Gpr[EAX].Xx == PCI_ILLEGAL_VENDOR_ID) {
+ Context->Gpr[EAX].Xh = PCI_BAD_VENDOR_ID;
+ Context->Eflags.CF = 1;
+ return;
+ }
+
+ Slot.u.AsULONG = 0;
+
+ for (Bus = 0; Bus < XmNumberPciBusses; Bus++) {
+ for (Device = 0; Device < 32; Device++) {
+ for (Function = 0; Function < 8; Function++) {
+
+ Slot.u.bits.DeviceNumber = Device;
+ Slot.u.bits.FunctionNumber = Function;
+
+ if (4 != XmGetPciData(Bus,
+ Slot.u.AsULONG,
+ &buffer,
+ 0, //offset of vendor ID
+ 4)) {
+
+ buffer = 0xffffffff;
+ }
+
+ //
+ // Did we find the right one?
+ //
+ if (((buffer & 0xffff) == Context->Gpr[EDX].Xx) &&
+ (((buffer >> 16) & 0xffff) == Context->Gpr[ECX].Xx)) {
+
+ //
+ // Did we find the right occurrence?
+ //
+ if (Index++ == Context->Gpr[ESI].Xx) {
+
+ Context->Gpr[EBX].Xh = Bus;
+ Context->Gpr[EBX].Xl = (UCHAR)((Device << 3) | Function);
+ Context->Gpr[EAX].Xh = PCI_SUCCESS;
+ Context->Eflags.CF = 0;
+
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ Context->Gpr[EAX].Xh = PCI_DEVICE_NOT_FOUND;
+ Context->Eflags.CF = 1;
+
+}
+
+VOID
+XmInt1aFindPciClassCode(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements FIND_PCI_CLASS_CODE.
+
+Arguments:
+
+ Context - State of the emulator
+ [AH] PCI_FUNCTION_ID
+ [AL] FIND_PCI_CLASS_CODE
+ [ECX] Class Code (in lower three bytes)
+ [SI] Index (0..N)
+
+
+Return Value:
+
+ [BH] Bus Number
+ [BL] Device Number, Function Number
+ [AH] return code
+ [CF] completion status
+--*/
+{
+ UCHAR Bus;
+ PCI_SLOT_NUMBER Slot;
+ ULONG Index = 0;
+ ULONG class_code;
+ ULONG Device;
+ ULONG Function;
+
+ Slot.u.AsULONG = 0;
+
+ for (Bus = 0; Bus < XmNumberPciBusses; Bus++) {
+ for (Device = 0; Device < 32; Device++) {
+ for (Function = 0; Function < 8; Function++) {
+
+ Slot.u.bits.DeviceNumber = Device;
+ Slot.u.bits.FunctionNumber = Function;
+
+ if (4 != XmGetPciData(Bus,
+ Slot.u.AsULONG,
+ &class_code,
+ 8, //offset of vendor ID
+ 4)) {
+
+ class_code = 0xffffffff;
+ }
+
+ class_code >>= 8;
+
+ //
+ // Did we find the right one?
+ //
+ if (class_code == (Context->Gpr[ECX].Exx & 0xFFFFFF)) {
+
+ //
+ // Did we find the right occurrence?
+ //
+ if (Index++ == Context->Gpr[ESI].Xx) {
+
+ Context->Gpr[EBX].Xh = Bus;
+ Context->Gpr[EBX].Xl = (UCHAR)((Device << 3) | (Function));
+ Context->Gpr[EAX].Xh = PCI_SUCCESS;
+ Context->Eflags.CF = 0;
+
+ return;
+
+ }
+ }
+ }
+ }
+ }
+
+ Context->Gpr[EAX].Xh = PCI_DEVICE_NOT_FOUND;
+ Context->Eflags.CF = 1;
+
+}
+
+VOID
+XmInt1aGenerateSpecialCycle(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements GENERATE_SPECIAL_CYCLE. Since
+ there is no uniform way to support special cycles from
+ the NT HAL, we won't support this function.
+
+Arguments:
+
+ Context - State of the emulator
+
+Return Value:
+
+ [AH] PCI_NOT_SUPPORTED
+
+--*/
+{
+ Context->Gpr[EAX].Xh = PCI_NOT_SUPPORTED;
+ Context->Eflags.CF = 1;
+}
+
+VOID
+XmInt1aGetRoutingOptions(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements GET_IRQ_ROUTING_OPTIONS. We
+ won't allow devices to try to specify their own interrupt
+ routing, partly because there isn't an easy way to do it,
+ partly because this is done later by the HAL, and partly
+ because almost no video devices generate interrupts.
+
+Arguments:
+
+ Context - State of the emulator
+
+Return Value:
+
+ [AH] PCI_NOT_SUPPORTED
+
+--*/
+{
+ Context->Gpr[EAX].Xh = PCI_NOT_SUPPORTED;
+ Context->Eflags.CF = 1;
+}
+
+VOID
+XmInt1aSetPciIrq(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements SET_PCI_IRQ. We
+ won't allow devices to try to specify their own interrupt
+ routing, partly because there isn't an easy way to do it,
+ partly because this is done later by the HAL, and partly
+ because almost no video devices generate interrupts.
+
+Arguments:
+
+ Context - State of the emulator
+
+Return Value:
+
+ [AH] PCI_NOT_SUPPORTED
+
+--*/
+{
+ Context->Gpr[EAX].Xh = PCI_NOT_SUPPORTED;
+ Context->Eflags.CF = 1;
+}
+
+
+
+VOID
+XmInt1aReadConfigRegister(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements READ_CONFIG_BYTE,
+ READ_CONFIG_WORD and READ_CONFIG_DWORD.
+
+Arguments:
+
+ Context - State of the emulator
+ [AH] PCI_FUNCTION_ID
+ [AL] function
+ [BH] bus number
+ [BL] device number/function number
+ [DI] Register number
+
+
+Return Value:
+
+ [ECX] data read
+ [AH] return code
+ [CF] completion status
+--*/
+{
+ UCHAR length;
+ PCI_SLOT_NUMBER Slot;
+ ULONG buffer;
+
+ //
+ // First, make sure that the register number is valid.
+ //
+ if (((Context->Gpr[EAX].Xl == PCI_READ_CONFIG_WORD) &&
+ (Context->Gpr[EBX].Xl % 2)) ||
+ ((Context->Gpr[EAX].Xl == PCI_READ_CONFIG_DWORD) &&
+ (Context->Gpr[EBX].Xl % 4))
+ )
+ {
+ Context->Gpr[EAX].Xh = PCI_BAD_REGISTER;
+ Context->Eflags.CF = 1;
+ }
+
+ switch (Context->Gpr[EAX].Xl) {
+ case PCI_READ_CONFIG_BYTE:
+ length = 1;
+ break;
+
+ case PCI_READ_CONFIG_WORD:
+ length = 2;
+ break;
+
+ case PCI_READ_CONFIG_DWORD:
+ length = 4;
+ }
+
+ Slot.u.AsULONG = 0;
+ Slot.u.bits.DeviceNumber = Context->Gpr[EBX].Xl >> 3;
+ Slot.u.bits.FunctionNumber = Context->Gpr[EBX].Xl;
+
+ if (XmGetPciData(Context->Gpr[EBX].Xh,
+ Slot.u.AsULONG,
+ &buffer,
+ Context->Gpr[EDI].Xx,
+ length
+ ) == 0)
+ {
+ // This is the only error code supported by this function
+ Context->Gpr[EAX].Xh = PCI_BAD_REGISTER;
+ Context->Eflags.CF = 1;
+ return;
+ }
+
+ switch (Context->Gpr[EAX].Xl) {
+ case PCI_READ_CONFIG_BYTE:
+ Context->Gpr[ECX].Xl = (UCHAR)(buffer & 0xff);
+ break;
+
+ case PCI_READ_CONFIG_WORD:
+ Context->Gpr[ECX].Xx = (USHORT)(buffer & 0xffff);
+ break;
+
+ case PCI_READ_CONFIG_DWORD:
+ Context->Gpr[ECX].Exx = buffer;
+ }
+
+ Context->Gpr[EAX].Xh = PCI_SUCCESS;
+ Context->Eflags.CF = 0;
+
+}
+
+
+VOID
+XmInt1aWriteConfigRegister(
+ IN OUT PRXM_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function implements WRITE_CONFIG_BYTE,
+ WRITE_CONFIG_WORD and WRITE_CONFIG_DWORD.
+
+Arguments:
+
+ Context - State of the emulator
+ [AH] PCI_FUNCTION_ID
+ [AL] function
+ [BH] bus number
+ [BL] device number/function number
+ [DI] Register number
+
+
+Return Value:
+
+ [ECX] data read
+ [AH] return code
+ [CF] completion status
+--*/
+{
+ UCHAR length;
+ PCI_SLOT_NUMBER Slot;
+ ULONG buffer;
+
+ //
+ // First, make sure that the register number is valid.
+ //
+ if (((Context->Gpr[EAX].Xl == PCI_WRITE_CONFIG_WORD) &&
+ (Context->Gpr[EBX].Xl % 2)) ||
+ ((Context->Gpr[EAX].Xl == PCI_WRITE_CONFIG_DWORD) &&
+ (Context->Gpr[EBX].Xl % 4))
+ )
+ {
+ Context->Gpr[EAX].Xh = PCI_BAD_REGISTER;
+ Context->Eflags.CF = 1;
+ }
+
+ //
+ // Find out how many bytes to write
+ //
+ switch (Context->Gpr[EAX].Xl) {
+ case PCI_WRITE_CONFIG_BYTE:
+ length = 1;
+ buffer = Context->Gpr[ECX].Xl;
+ break;
+
+ case PCI_WRITE_CONFIG_WORD:
+ length = 2;
+ buffer = Context->Gpr[ECX].Xx;
+ break;
+
+ case PCI_WRITE_CONFIG_DWORD:
+ length = 4;
+ buffer = Context->Gpr[ECX].Exx;
+ }
+
+ //
+ // Unpack the Slot/Function information
+ //
+ Slot.u.AsULONG = 0;
+ Slot.u.bits.DeviceNumber = Context->Gpr[EBX].Xl >> 3;
+ Slot.u.bits.FunctionNumber = Context->Gpr[EBX].Xl;
+
+ if (XmSetPciData(Context->Gpr[EBX].Xh,
+ Slot.u.AsULONG,
+ &buffer,
+ Context->Gpr[EDI].Xx,
+ length
+ ) == 0)
+ {
+ Context->Gpr[EAX].Xh = PCI_SUCCESS;
+ Context->Eflags.CF = 0;
+ } else {
+ // This is the only error code supported by this function
+ Context->Gpr[EAX].Xh = PCI_BAD_REGISTER;
+ Context->Eflags.CF = 1;
+ }
+
+
+}
+
+
diff --git a/private/ntos/nthals/x86new/ppc/sources b/private/ntos/nthals/x86new/ppc/sources
new file mode 100644
index 000000000..e6ac0f65a
--- /dev/null
+++ b/private/ntos/nthals/x86new/ppc/sources
@@ -0,0 +1,24 @@
+PPC_SOURCES=..\emulate.c \
+ ..\addops.c \
+ ..\asciiops.c \
+ ..\bitops.c \
+ ..\condops.c \
+ ..\ctrlops.c \
+ ..\data.c \
+ ..\debug.c \
+ ..\divops.c \
+ ..\inoutops.c \
+ ..\jmpops.c \
+ ..\logops.c \
+ ..\miscops.c \
+ ..\moveops.c \
+ ..\mulops.c \
+ ..\operand.c \
+ ..\pcibios.c \
+ ..\regmode.c \
+ ..\setops.c \
+ ..\shiftops.c \
+ ..\stackops.c \
+ ..\stringop.c \
+ ..\utility.c \
+ ..\x86bios.c
diff --git a/private/ntos/nthals/x86new/regmode.c b/private/ntos/nthals/x86new/regmode.c
new file mode 100644
index 000000000..167c66ad5
--- /dev/null
+++ b/private/ntos/nthals/x86new/regmode.c
@@ -0,0 +1,1239 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ regmode.c
+
+Abstract:
+
+ This module implements the code necessary to decode the address
+ mode specifier byte.
+
+ N.B. This routine could be probably be more tightly encoded with a
+ loss of clarity.
+
+Author:
+
+ David N. Cutler (davec) 10-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define forward referenced function prototypes.
+//
+
+ULONG
+XmEvaluateIndexSpecifier (
+ IN PRXM_CONTEXT P,
+ IN ULONG Mode
+ );
+
+PVOID
+XmEvaluateAddressSpecifier (
+ IN PRXM_CONTEXT P,
+ OUT PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function decodes x86 operand specifiers.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Number - Supplies a pointer to a variable that receives the register
+ number selected by the reg field of the operand specifier.
+
+ Operand - Supplies a pointer to a variable that receives the address
+ of the operand specified by the mod-r/m field of the operand
+ specifier.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG DispatchIndex;
+ ULONG Mode;
+ ULONG Modifier;
+ ULONG Offset;
+ ULONG Register;
+ UCHAR SpecifierByte;
+
+ //
+ // Get the next byte from the instruction stream and isolate
+ // the fields. The format of an operand specifier byte is:
+ //
+ // <7:6> - Mode
+ // <5:3> - Operand Register
+ // <2:0> - Modifier
+ //
+
+ SpecifierByte = XmGetCodeByte(P);
+ XmTraceSpecifier(SpecifierByte);
+ Mode = (SpecifierByte >> 6) & 0x3;
+ Modifier = SpecifierByte & 0x7;
+ Register = (SpecifierByte >> 3) & 0x7;
+ DispatchIndex = (Mode << 3) | (Modifier);
+ P->RegisterOffsetAddress = FALSE;
+
+ //
+ // Set the segment base address and select between 16- and 32-bit
+ // addressing.
+ //
+
+ *Number = Register;
+ if (P->OpaddrPrefixActive != FALSE) {
+
+ //
+ // 32-bit addressing.
+ //
+ // Case on dispatch index.
+ //
+
+ switch (DispatchIndex) {
+
+ //
+ // 00-000 DS:[EAX]
+ //
+
+ case 0:
+ Offset = P->Gpr[EAX].Exx;
+ break;
+
+ //
+ // 00-001 DS:[ECX]
+ //
+
+ case 1:
+ Offset = P->Gpr[ECX].Exx;
+ break;
+
+ //
+ // 00-010 DS:[EDX]
+ //
+
+ case 2:
+ Offset = P->Gpr[EDX].Exx;
+ break;
+
+ //
+ // 00-011 DS:[EBX]
+ //
+
+ case 3:
+ Offset = P->Gpr[EBX].Exx;
+ break;
+
+ //
+ // 00-100 - scale index byte
+ //
+
+ case 4:
+ Offset = XmEvaluateIndexSpecifier(P, Mode);
+ break;
+
+ //
+ // 00-101 DS:d32
+ //
+
+ case 5:
+ Offset = XmGetLongImmediate(P);
+ break;
+
+ //
+ // 00-110 DS:[ESI]
+ //
+
+ case 6:
+ Offset = P->Gpr[ESI].Exx;
+ break;
+
+ //
+ // 00-111 DS:[EDI]
+ //
+
+ case 7:
+ Offset = P->Gpr[EDI].Exx;
+ break;
+
+ //
+ // 01-000 DS:[EAX + d8]
+ //
+
+ case 8:
+ Offset = P->Gpr[EAX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-001 DS:[ECX + d8]
+ //
+
+ case 9:
+ Offset = P->Gpr[ECX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-010 DS:[EDX + d8]
+ //
+
+ case 10:
+ Offset = P->Gpr[EDX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-011 DS:[EBX + d8]
+ //
+
+ case 11:
+ Offset = P->Gpr[EBX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-100 - scale index byte
+ //
+
+ case 12:
+ Offset = XmEvaluateIndexSpecifier(P, Mode);
+ break;
+
+ //
+ // 01-101 DS:[EBP + d8]
+ //
+
+ case 13:
+ Offset = P->Gpr[EBP].Exx + XmGetSignedByteImmediateToLong(P);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 01-110 DS:[ESI + d8]
+ //
+
+ case 14:
+ Offset = P->Gpr[ESI].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-111 DS:[EDI + d8]
+ //
+
+ case 15:
+ Offset = P->Gpr[EDI].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 10-000 DS:[EAX + d32]
+ //
+
+ case 16:
+ Offset = P->Gpr[EAX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-001 DS:[ECX + d32]
+ //
+
+ case 17:
+ Offset = P->Gpr[ECX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-010 DS:[EDX + d32]
+ //
+
+ case 18:
+ Offset = P->Gpr[EDX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-011 DS:[EBX + d32]
+ //
+
+ case 19:
+ Offset = P->Gpr[EBX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-100 - scale index byte
+ //
+
+ case 20:
+ Offset = XmEvaluateIndexSpecifier(P, Mode);
+ break;
+
+ //
+ // 10-101 DS:[EBP + d32]
+ //
+
+ case 21:
+ Offset = P->Gpr[EBP].Exx + XmGetLongImmediate(P);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 10-110 DS:[ESI + d32]
+ //
+
+ case 22:
+ Offset = P->Gpr[ESI].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-111 DS:[EDI + d32]
+ //
+
+ case 23:
+ Offset = P->Gpr[EDI].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 11-xxx - Register mode.
+ //
+
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ P->RegisterOffsetAddress = TRUE;
+ return XmGetRegisterAddress(P, Modifier);
+ }
+
+ } else {
+
+ //
+ // 16-bit addressing.
+ //
+ // Case on dispatch index.
+ //
+
+ switch (DispatchIndex) {
+
+ //
+ // 00-000 DS:[BX + SI]
+ //
+
+ case 0:
+ Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[SI].Xx);
+ break;
+
+ //
+ // 00-001 DS:[BX + DI]
+ //
+
+ case 1:
+ Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[DI].Xx);
+ break;
+
+ //
+ // 00-010 SS:[BP + SI]
+ //
+
+ case 2:
+ Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[SI].Xx);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 00-011 SS:[BP + DI]
+ //
+
+ case 3:
+ Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[DI].Xx);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 00-100 DS:[SI]
+ //
+
+ case 4:
+ Offset = (USHORT)(P->Gpr[SI].Xx);
+ break;
+
+ //
+ // 00-101 DS:[DI]
+ //
+
+ case 5:
+ Offset = (USHORT)(P->Gpr[DI].Xx);
+ break;
+
+ //
+ // 00-110 DS:d16
+ //
+
+ case 6:
+ Offset = XmGetWordImmediate(P);
+ break;
+
+ //
+ // 00-111 DS:[BX]
+ //
+
+ case 7:
+ Offset = (USHORT)(P->Gpr[BX].Xx);
+ break;
+
+ //
+ // 01-000 DS:[BX + SI + d8]
+ //
+
+ case 8:
+ Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[SI].Xx + XmGetSignedByteImmediateToWord(P));
+ break;
+
+ //
+ // 01-001 DS:[BX + DI + d8]
+ //
+
+ case 9:
+ Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[DI].Xx + XmGetSignedByteImmediateToWord(P));
+ break;
+
+ //
+ // 01-010 SS:[BP + SI + d8]
+ //
+
+ case 10:
+ Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[SI].Xx + XmGetSignedByteImmediateToWord(P));
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 01-011 SS:[BP + DI + d8]
+ //
+
+ case 11:
+ Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[DI].Xx + XmGetSignedByteImmediateToWord(P));
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 01-100 DS:[SI + d8]
+ //
+
+ case 12:
+ Offset = (USHORT)(P->Gpr[SI].Xx + XmGetSignedByteImmediateToWord(P));
+ break;
+
+ //
+ // 01-101 DS:[DI + d8]
+ //
+
+ case 13:
+ Offset = (USHORT)(P->Gpr[DI].Xx + XmGetSignedByteImmediateToWord(P));
+ break;
+
+ //
+ // 01-110 DS:[BP + d8]
+ //
+
+ case 14:
+ Offset = (USHORT)(P->Gpr[BP].Xx + XmGetSignedByteImmediateToWord(P));
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 01-111 DS:[BX + d8]
+ //
+
+ case 15:
+ Offset = (USHORT)(P->Gpr[BX].Xx + XmGetSignedByteImmediateToWord(P));
+ break;
+
+ //
+ // 10-000 DS:[BX + SI + d16]
+ //
+
+ case 16:
+ Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[SI].Xx + XmGetWordImmediate(P));
+ break;
+
+ //
+ // 10-001 DS:[BX + DI + d16]
+ //
+
+ case 17:
+ Offset = (USHORT)(P->Gpr[BX].Xx + P->Gpr[DI].Xx + XmGetWordImmediate(P));
+ break;
+
+ //
+ // 10-010 SS:[BP + SI + d16]
+ //
+
+ case 18:
+ Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[SI].Xx + XmGetWordImmediate(P));
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 10-011 SS:[BP + DI + d16]
+ //
+
+ case 19:
+ Offset = (USHORT)(P->Gpr[BP].Xx + P->Gpr[DI].Xx + XmGetWordImmediate(P));
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 10-100 DS:[SI + d16]
+ //
+
+ case 20:
+ Offset = (USHORT)(P->Gpr[SI].Xx + XmGetWordImmediate(P));
+ break;
+
+ //
+ // 10-101 DS:[DI + d16]
+ //
+
+ case 21:
+ Offset = (USHORT)(P->Gpr[DI].Xx + XmGetWordImmediate(P));
+ break;
+
+ //
+ // 10-110 DS:[BP + d16]
+ //
+
+ case 22:
+ Offset = (USHORT)(P->Gpr[BP].Xx + XmGetWordImmediate(P));
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 10-111 DS:[BX + d16]
+ //
+
+ case 23:
+ Offset = (USHORT)(P->Gpr[BX].Xx + XmGetWordImmediate(P));
+ break;
+
+ //
+ // 11-xxx - Register mode.
+ //
+
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ P->RegisterOffsetAddress = TRUE;
+ return XmGetRegisterAddress(P, Modifier);
+ }
+ }
+
+ //
+ // If an effective offset is being calculated, then return the offset
+ // value. Otherwise, If the offset displacement value plus the datum
+ // size is not within the segment limits, then raise an exception.
+ // Otherwise, compute the operand address.
+ //
+
+ if (P->ComputeOffsetAddress != FALSE) {
+ if (P->DataType == WORD_DATA) {
+ Offset &= 0xffff;
+ }
+
+ P->Offset = Offset;
+
+ } else {
+ if ((Offset > P->SegmentLimit[P->DataSegment]) ||
+ ((Offset + P->DataType) > P->SegmentLimit[P->DataSegment])) {
+ longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
+
+ } else {
+ P->Offset = Offset;
+ Offset = (ULONG)(P->TranslateAddress)(P->SegmentRegister[P->DataSegment],
+ (USHORT)Offset);
+ }
+ }
+
+ return (PVOID)Offset;
+}
+
+ULONG
+XmEvaluateIndexSpecifier (
+ IN PRXM_CONTEXT P,
+ IN ULONG Mode
+ )
+
+/*++
+
+Routine Description:
+
+ This function evaluates a index specifier byte.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Mode - Supplies the mode of the address specifier.
+
+Return Value:
+
+ The offset value computes from the index specifier.
+
+--*/
+
+{
+
+ ULONG DispatchIndex;
+ ULONG Modifier;
+ ULONG Offset;
+ ULONG Register;
+ ULONG Scale;
+ UCHAR SpecifierByte;
+
+ //
+ // Get the next byte from the instruction stream and isolate the
+ // specifier fields. The format of an scale/index byte is:
+ //
+ // <7:6> - Scale
+ // <5:3> - Index register
+ // <2:0> - Modifier
+ //
+
+ SpecifierByte = XmGetCodeByte(P);
+ XmTraceInstruction(BYTE_DATA, (ULONG)SpecifierByte);
+ Scale = (SpecifierByte >> 6) & 0x3;
+ Modifier = SpecifierByte & 0x7;
+ Register = (SpecifierByte >> 3) & 0x7;
+ DispatchIndex = (Mode << 3) | (Modifier);
+
+ //
+ // Case of dispatch index.
+ //
+
+ switch (DispatchIndex) {
+
+ //
+ // 00-000 DS:[EAX + scaled index]
+ //
+
+ case 0:
+ Offset = P->Gpr[EAX].Exx;
+ break;
+
+ //
+ // 00-001 DS:[ECX + scaled index]
+ //
+
+ case 1:
+ Offset = P->Gpr[ECX].Exx;
+ break;
+
+ //
+ // 00-010 DS:[EDX + scaled index]
+ //
+
+ case 2:
+ Offset = P->Gpr[EDX].Exx;
+ break;
+
+ //
+ // 00-011 DS:[EBX + scaled index]
+ //
+
+ case 3:
+ Offset = P->Gpr[EBX].Exx;
+ break;
+
+ //
+ // 00-100 SS:[ESP + scaled index]
+ //
+
+ case 4:
+ Offset = P->Gpr[ESP].Exx;
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 00-101 DS:[d32 + scaled index]
+ //
+
+ case 5:
+ Offset = XmGetLongImmediate(P);
+ break;
+
+ //
+ // 00-110 DS:[ESI + scaled index]
+ //
+
+ case 6:
+ Offset = P->Gpr[ESI].Exx;
+ break;
+
+ //
+ // 00-111 DS:[EDI + scaled index]
+ //
+
+ case 7:
+ Offset = P->Gpr[EDI].Exx;
+ break;
+
+ //
+ // 01-000 DS:[EAX + scaled index + d8]
+ //
+
+ case 8:
+ Offset = P->Gpr[EAX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-001 DS:[ECX + scaled index + d8]
+ //
+
+ case 9:
+ Offset = P->Gpr[ECX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-010 DS:[EDX + scaled index + d8]
+ //
+
+ case 10:
+ Offset = P->Gpr[EDX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-011 DS:[EBX + scaled index + d8]
+ //
+
+ case 11:
+ Offset = P->Gpr[EBX].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-100 SS:[ESP + scaled index + d8]
+ //
+
+ case 12:
+ Offset = P->Gpr[ESP].Exx + XmGetSignedByteImmediateToLong(P);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 01-101 DS:[EBP + scaled index + d8]
+ //
+
+ case 13:
+ Offset = P->Gpr[EBP].Exx + XmGetSignedByteImmediateToLong(P);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+ break;
+
+ //
+ // 01-110 DS:[ESI + scaled index + d8]
+ //
+
+ case 14:
+ Offset = P->Gpr[ESI].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 01-111 DS:[EDI + scaled index + d8]
+ //
+
+ case 15:
+ Offset = P->Gpr[EDI].Exx + XmGetSignedByteImmediateToLong(P);
+ break;
+
+ //
+ // 10-000 DS:[EAX + scaled index + d32]
+ //
+
+ case 16:
+ Offset = P->Gpr[EAX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-001 DS:[ECX + scaled index + d32]
+ //
+
+ case 17:
+ Offset = P->Gpr[ECX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-010 DS:[EDX + scaled index + d32]
+ //
+
+ case 18:
+ Offset = P->Gpr[EDX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-011 DS:[EBX + scaled index + d32]
+ //
+
+ case 19:
+ Offset = P->Gpr[EBX].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-100 SS:[ESP + scaled index + d32]
+ //
+
+ case 20:
+ Offset = P->Gpr[ESP].Exx + XmGetLongImmediate(P);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 10-101 DS:[EBP + scaled index + d32]
+ //
+
+ case 21:
+ Offset = P->Gpr[EBP].Exx + XmGetLongImmediate(P);
+ if (P->SegmentPrefixActive == FALSE) {
+ P->DataSegment = SS;
+ }
+
+ break;
+
+ //
+ // 10-110 DS:[ESI + scaled index + d32]
+ //
+
+ case 22:
+ Offset = P->Gpr[ESI].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // 10-111 DS:[EDI + scaled index + d32]
+ //
+
+ case 23:
+ Offset = P->Gpr[EDI].Exx + XmGetLongImmediate(P);
+ break;
+
+ //
+ // Illegal mode specifier.
+ //
+
+ default:
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_INDEX_SPECIFIER);
+ }
+
+ //
+ // Compute the total offset value.
+ //
+
+ return Offset + (P->Gpr[Register].Exx << Scale);
+}
+
+PVOID
+XmGetOffsetAddress (
+ IN PRXM_CONTEXT P,
+ IN ULONG Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This function evaluates a data segment address given a specified
+ offset.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Offset - Supplies the offset value.
+
+Return Value:
+
+ A pointer to the operand value.
+
+--*/
+
+{
+
+ //
+ // If the offset displacement value plus the datum size is not within
+ // the segment limits, then raise an exception. Otherwise, compute the
+ // operand address.
+ //
+
+ if ((Offset > P->SegmentLimit[P->DataSegment]) ||
+ ((Offset + P->DataType) > P->SegmentLimit[P->DataSegment])) {
+ longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
+ }
+
+ return (P->TranslateAddress)(P->SegmentRegister[P->DataSegment], (USHORT)Offset);
+}
+
+PVOID
+XmGetRegisterAddress (
+ IN PRXM_CONTEXT P,
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function computes the address of a register value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Number - Supplies the register number.
+
+Return Value:
+
+ A pointer to the register value.
+
+--*/
+
+{
+
+ PVOID Value;
+
+ //
+ // If the operand width is a byte, then the register is a
+ // byte register. Otherwise, the register is a word register.
+ //
+
+ if (P->DataType == BYTE_DATA) {
+ if (Number < 4) {
+ Value = (PVOID)&P->Gpr[Number].Xl;
+
+ } else {
+ Value = (PVOID)&P->Gpr[Number - 4].Xh;
+ }
+
+ } else if (P->DataType == WORD_DATA) {
+ Value = (PVOID)&P->Gpr[Number].Xx;
+
+ } else {
+ Value = (PVOID)&P->Gpr[Number].Exx;
+ }
+
+ return Value;
+}
+
+PVOID
+XmGetStringAddress (
+ IN PRXM_CONTEXT P,
+ IN ULONG Segment,
+ IN ULONG Register
+ )
+
+/*++
+
+Routine Description:
+
+ This function evaluates a string address.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Segment - Supplies the segment number of the string operand.
+
+ Register - Supplies the register number of the string operand.
+
+Return Value:
+
+ A pointer to the string value.
+
+--*/
+
+{
+
+ ULONG Increment;
+ ULONG Offset;
+
+ //
+ // Get the offset of the specified address and increment the specified
+ // register.
+ //
+
+ Increment = P->DataType + 1;
+ if (P->Eflags.DF != 0) {
+ Increment = ~Increment + 1;
+ }
+
+ if (P->OpaddrPrefixActive != FALSE) {
+ Offset = P->Gpr[Register].Exx;
+ P->Gpr[Register].Exx += Increment;
+
+ } else {
+ Offset = P->Gpr[Register].Xx;
+ P->Gpr[Register].Xx += (USHORT)Increment;
+ }
+
+ //
+ // If the offset displacement value plus the datum size is not within
+ // the segment limits, then raise an exception. Otherwise, compute the
+ // operand address.
+ //
+
+ if ((Offset > P->SegmentLimit[Segment]) ||
+ ((Offset + P->DataType) > P->SegmentLimit[Segment])) {
+ longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
+ }
+
+ return (P->TranslateAddress)(P->SegmentRegister[Segment], (USHORT)Offset);
+}
+
+VOID
+XmSetDestinationValue (
+ IN PRXM_CONTEXT P,
+ IN PVOID Destination
+ )
+
+/*++
+
+Routine Description:
+
+ This function stores the destination operand value in the emulator
+ context.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Destination - Supplies a pointer to the destination operand value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set address and value of destination.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)Destination;
+ if (P->DataType == BYTE_DATA) {
+ P->DstValue.Long = *(UCHAR *)Destination;
+
+ } else if (P->DataType == WORD_DATA) {
+ if (((ULONG)Destination & 0x1) == 0) {
+ P->DstValue.Long = *(USHORT *)Destination;
+
+ } else {
+ P->DstValue.Long = *(USHORT UNALIGNED *)Destination;
+ }
+
+ } else {
+ if (((ULONG)Destination & 0x3) == 0) {
+ P->DstValue.Long = *(ULONG *)Destination;
+
+ } else {
+ P->DstValue.Long = *(ULONG UNALIGNED *)Destination;
+ }
+ }
+
+ XmTraceDestination(P, P->DstValue.Long);
+ return;
+}
+
+VOID
+XmSetSourceValue (
+ IN PRXM_CONTEXT P,
+ IN PVOID Source
+ )
+
+/*++
+
+Routine Description:
+
+ This function stores the source operand value in the emulator
+ context.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Source - Supplies a pointer to the source operand value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set address and value of source.
+ //
+
+ P->SrcLong = (ULONG UNALIGNED *)Source;
+ if (P->DataType == BYTE_DATA) {
+ P->SrcValue.Long = *(UCHAR UNALIGNED *)Source;
+
+ } else if (P->DataType == WORD_DATA) {
+ P->SrcValue.Long = *(USHORT UNALIGNED *)Source;
+
+ } else {
+ P->SrcValue.Long = *(ULONG UNALIGNED *)Source;
+ }
+
+ XmTraceSource(P, P->SrcValue.Long);
+ return;
+}
+
+ULONG
+XmGetImmediateSourceValue (
+ IN PRXM_CONTEXT P,
+ IN ULONG ByteFlag
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an immediate source from the instruction stream.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ ByteFlag - Supplies a flag value that determines whether the
+ immediate value is a sign extended byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Get source value.
+ //
+
+ if (P->DataType == BYTE_DATA) {
+ Value = XmGetByteImmediate(P);
+
+ } else if (P->DataType == WORD_DATA) {
+ if (ByteFlag == 0) {
+ Value = XmGetWordImmediate(P);
+
+ } else {
+ Value = XmGetSignedByteImmediateToWord(P);
+ }
+
+ } else {
+ if (ByteFlag == 0) {
+ Value = XmGetLongImmediate(P);
+
+ } else {
+ Value = XmGetSignedByteImmediateToLong(P);
+ }
+ }
+
+ return Value;
+}
+
+VOID
+XmSetImmediateSourceValue (
+ IN PRXM_CONTEXT P,
+ IN ULONG Source
+ )
+
+/*++
+
+Routine Description:
+
+ This function stores the immediate source operand value in the
+ emulator context.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Source - Supplies the source value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set source value.
+ //
+
+ P->SrcValue.Long = Source;
+ XmTraceSource(P, Source);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/setops.c b/private/ntos/nthals/x86new/setops.c
new file mode 100644
index 000000000..e58492190
--- /dev/null
+++ b/private/ntos/nthals/x86new/setops.c
@@ -0,0 +1,133 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ setops.c
+
+Abstract:
+
+ This module implements the code to emulate set opcodes.
+
+Author:
+
+ David N. Cutler (davec) 13-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmSxxOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates set byte on condition opcodes.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Complement;
+ ULONG Condition;
+
+ //
+ // Case on the set control value.
+ //
+
+ Complement = P->SrcValue.Long & 1;
+ switch (P->SrcValue.Long >> 1) {
+
+ //
+ // Set if overflow/not overflow.
+ //
+
+ case 0:
+ Condition = P->Eflags.OF;
+ break;
+
+ //
+ // Set if below/not below.
+ //
+
+ case 1:
+ Condition = P->Eflags.CF;
+ break;
+
+ //
+ // Set if zero/not zero.
+ //
+
+ case 2:
+ Condition = P->Eflags.ZF;
+ break;
+
+ //
+ // Set if below or equal/not below or equal.
+ //
+
+ case 3:
+ Condition = P->Eflags.CF | P->Eflags.ZF;
+ break;
+
+ //
+ // Set if signed/not signed.
+ //
+
+ case 4:
+ Condition = P->Eflags.SF;
+ break;
+
+ //
+ // Set if parity/not parity.
+ //
+
+ case 5:
+ Condition = P->Eflags.PF;
+ break;
+
+ //
+ // Set if less/not less.
+ //
+
+ case 6:
+ Condition = (P->Eflags.SF ^ P->Eflags.OF);
+ break;
+
+ //
+ // Set if less or equal/not less or equal.
+ //
+
+ case 7:
+ Condition = (P->Eflags.SF ^ P->Eflags.OF) | P->Eflags.ZF;
+ break;
+ }
+
+ //
+ // If the specified condition is met, then set the byte destination
+ // value to one. Otherwise, set the byte destination value to zero.
+ //
+
+ XmStoreResult(P, (ULONG)(Condition ^ Complement));
+ return;
+}
diff --git a/private/ntos/nthals/x86new/shiftops.c b/private/ntos/nthals/x86new/shiftops.c
new file mode 100644
index 000000000..2e4a61745
--- /dev/null
+++ b/private/ntos/nthals/x86new/shiftops.c
@@ -0,0 +1,580 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ mulops.c
+
+Abstract:
+
+ This module implements the code to emulate the shift opcodes.
+
+Author:
+
+ David N. Cutler (davec) 21-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmRolOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a rol opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Mask;
+ ULONG Shift;
+ ULONG Value;
+
+ //
+ // Rotate destination left and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Mask = ((1 << Shift) - 1) | (1 << Shift);
+ Value = P->DstValue.Long;
+ Count = P->SrcValue.Long & Shift;
+ if (Count != 0) {
+ if (Count == 1) {
+ P->Eflags.OF = (Value >> Shift) ^ (Value >> (Shift - 1));
+ }
+
+ do {
+ Carry = Value >> Shift;
+ Value = Carry | ((Value << 1) & Mask);
+ Count -= 1;
+ } while (Count != 0);
+
+ P->Eflags.CF = Carry;
+ }
+
+ XmStoreResult(P, Value);
+ return;
+}
+
+VOID
+XmRorOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a ror opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Shift;
+ ULONG Value;
+
+ //
+ // Rotate destination right and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Value = P->DstValue.Long;
+ Count = P->SrcValue.Long & Shift;
+ if (Count != 0) {
+ if (Count == 1) {
+ P->Eflags.OF = (Value >> Shift) ^ (Value & 0x1);
+ }
+
+ do {
+ Carry = Value & 1;
+ Value = (Carry << Shift) | (Value >> 1);
+ Count -= 1;
+ } while (Count != 0 );
+
+ P->Eflags.CF = Carry;
+ }
+
+ XmStoreResult(P, Value);
+ return;
+}
+
+VOID
+XmRclOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a rcl opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Mask;
+ ULONG Shift;
+ ULONG Temp;
+ ULONG Value;
+
+ //
+ // Rotate destination left through carry and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Mask = ((1 << Shift) - 1) | (1 << Shift);
+ Value = P->DstValue.Long;
+ Count = P->SrcValue.Long & Shift;
+ Carry = P->Eflags.CF;
+ if (Count != 0) {
+ if (Count == 1) {
+ P->Eflags.OF = (Value >> Shift) ^ (Value >> (Shift - 1));
+ }
+
+ do {
+ Temp = Value >> Shift;
+ Value = ((Value << 1) & Mask) | Carry;
+ Carry = Temp;
+ Count -= 1;
+ } while (Count != 0);
+ }
+
+ XmStoreResult(P, Value);
+ P->Eflags.CF = Carry;
+ return;
+}
+
+VOID
+XmRcrOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a rcr opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Shift;
+ ULONG Temp;
+ ULONG Value;
+
+ //
+ // Rotate destination right through carry and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Value = P->DstValue.Long;
+ Count = P->SrcValue.Long & Shift;
+ Carry = P->Eflags.CF;
+ if (Count != 0) {
+ if (Count == 1) {
+ P->Eflags.OF = (Value >> Shift) ^ Carry;
+ }
+
+ do {
+ Temp = Value & 1;
+ Value = (Carry << Shift) | (Value >> 1);
+ Carry = Temp;
+ Count -= 1;
+ } while (Count != 0);
+ }
+
+ XmStoreResult(P, Value);
+ P->Eflags.CF = Carry;
+ return;
+}
+
+VOID
+XmShlOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a shl opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Overflow;
+ ULONG Shift;
+ ULONG Value;
+
+ //
+ // Shift destination left logical and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Value = P->DstValue.Long;
+ Count = P->SrcValue.Long;
+ if (Count != 0) {
+ if (P->DataType == LONG_DATA) {
+ Overflow = (Value ^ (Value << 1)) >> 31;
+ Carry = Value >> (32 - Count);
+ Value <<= Count;
+
+ } else if (P->DataType == WORD_DATA) {
+ Overflow = (Value ^ (Value << 1)) >> 15;
+ Carry = Value >> (16 - Count);
+ Value = (Value << Count) & 0xffff;
+
+ } else {
+ Overflow = (Value ^ (Value << 1)) >> 7;
+ Carry = Value >> (8 - Count);
+ Value = (Value << Count) & 0xff;
+ }
+
+ P->Eflags.CF = Carry;
+ P->Eflags.OF = Overflow;
+ P->Eflags.PF = XmComputeParity(Value);
+ P->Eflags.ZF = (Value == 0);
+ P->Eflags.SF = Value >> Shift;
+ }
+
+ XmStoreResult(P, Value);
+ return;
+}
+
+VOID
+XmShrOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a shr opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Overflow;
+ ULONG Shift;
+ ULONG Value;
+
+ //
+ // Shift destination right logical and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Value = P->DstValue.Long;
+ Count = P->SrcValue.Long;
+ if (Count != 0) {
+ if (P->DataType == LONG_DATA) {
+ Overflow = Value >> 31;
+ Carry = Value >> (Count - 1);
+ Value >>= Count;
+
+ } else if (P->DataType == WORD_DATA) {
+ Overflow = Value >> 15;
+ Carry = Value >> (Count - 1);
+ Value >>= Count;
+
+ } else {
+ Overflow = Value >> 7;
+ Carry = Value >> (Count - 1);
+ Value >>= Count;
+ }
+
+ P->Eflags.CF = Carry;
+ P->Eflags.OF = Overflow;
+ P->Eflags.PF = XmComputeParity(Value);
+ P->Eflags.ZF = (Value == 0);
+ P->Eflags.SF = Value >> Shift;
+ }
+
+ XmStoreResult(P, Value);
+ return;
+}
+
+VOID
+XmSarOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a sar opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG Shift;
+ LONG Value;
+
+ //
+ // Shift destination right arithmetic and store result.
+ //
+
+ Shift = ((P->DataType + 1) << 3) - 1;
+ Value = (LONG)P->DstValue.Long;
+ Count = P->SrcValue.Long;
+ if (Count != 0) {
+ if (P->DataType == LONG_DATA) {
+ Carry = Value >> (Count - 1);
+ Value >>= Count;
+
+ } else if (P->DataType == WORD_DATA) {
+ Carry = Value >> (Count - 1);
+ Value = ((Value << 16) >> (Count + 16)) & 0xffff;
+
+ } else {
+ Carry = Value >> (Count - 1);
+ Value = ((Value << 24) >> (Count + 24)) & 0xff;
+ }
+
+ P->Eflags.CF = Carry;
+ P->Eflags.OF = 0;
+ P->Eflags.PF = XmComputeParity(Value);
+ P->Eflags.ZF = (Value == 0);
+ P->Eflags.SF = Value >> Shift;
+ }
+
+ XmStoreResult(P, (ULONG)Value);
+ return;
+}
+
+VOID
+XmShldOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a shld opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG High;
+ ULONG Low;
+ ULONG Sign;
+
+ //
+ // Double shift left logical and store result.
+ //
+ // The low 32-bits of the shift are the source.
+ // The high 32-bits of the shift are the destination.
+ // The shift count has been masked modulo the datatype.
+ //
+ // This shift is equivalent to extracting the high 32-bits of the left
+ // shifted result.
+ //
+
+ Low = P->SrcValue.Long;
+ High = P->DstValue.Long;
+ Count = P->Shift;
+ if (Count != 0) {
+ if (P->DataType == LONG_DATA) {
+ if (Count == 1) {
+ P->Eflags.OF = (High ^ (High << 1)) >> 31;
+ }
+
+ Carry = High >> (32 - Count);
+ High = (High << Count) | (Low >> (32 - Count));
+ Sign = High >> 31;
+
+ } else {
+ if (Count == 1) {
+ P->Eflags.OF = (High ^ (High << 1)) >> 15;
+ }
+
+ Carry = High >> (16 - Count);
+ High = ((High << Count) | (Low >> (16 - Count))) & 0xffff;
+ Sign = High >> 15;
+ }
+
+ P->Eflags.CF = Carry;
+ P->Eflags.PF = XmComputeParity(High);
+ P->Eflags.ZF = (High == 0);
+ P->Eflags.SF = Sign;
+ }
+
+ XmStoreResult(P, High);
+ return;
+}
+
+VOID
+XmShrdOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a shrd opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Carry;
+ ULONG Count;
+ ULONG High;
+ ULONG Low;
+ ULONG Sign;
+
+ //
+ // Double shift right logical and store result.
+ //
+ // The high 32-bits of the shift are the source.
+ // The low 32-bits of the shift are the destination.
+ // The shift count has been masked modulo the datatype.
+ //
+ // This shift is equivalent to extracting the low 32-bits of the right
+ // shifted result.
+ //
+
+ High = P->SrcValue.Long;
+ Low = P->DstValue.Long;
+ Count = P->Shift;
+ if (Count != 0) {
+ if (P->DataType == LONG_DATA) {
+ if (Count == 1) {
+ P->Eflags.OF = High ^ (Low >> 31);
+ }
+
+ Carry = Low >> (Count - 1);
+ Low = (High << (32 - Count)) | (Low >> Count);
+ Sign = Low >> 31;
+
+ } else {
+ if (Count == 1) {
+ P->Eflags.OF = High ^ (Low >> 15);
+ }
+
+ Carry = Low >> (Count - 1);
+ Low = ((High << (16 - Count)) | (Low >> Count)) & 0xffff;
+ Sign = Low >> 15;
+ }
+
+ P->Eflags.CF = Carry;
+ P->Eflags.PF = XmComputeParity(Low);
+ P->Eflags.ZF = (Low == 0);
+ P->Eflags.SF = Sign;
+ }
+
+ XmStoreResult(P, Low);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/sources b/private/ntos/nthals/x86new/sources
new file mode 100644
index 000000000..a9714a340
--- /dev/null
+++ b/private/ntos/nthals/x86new/sources
@@ -0,0 +1,46 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=hal
+MINORCOMP=x86new
+
+TARGETNAME=x86new
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=..;..\..\inc
+
+NTPROFILEINPUT=yes
+
+SYNCHRONIZE_BLOCK=1
+
+NTDEBUGTYPE=coff
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=
+
+UMTYPE=console
+UMLIBS=obj\*\x86new.lib \nt\public\sdk\lib\*\ntdll.lib
+UMTEST=main
diff --git a/private/ntos/nthals/x86new/stackops.c b/private/ntos/nthals/x86new/stackops.c
new file mode 100644
index 000000000..33ae35b77
--- /dev/null
+++ b/private/ntos/nthals/x86new/stackops.c
@@ -0,0 +1,195 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ stackops.c
+
+Abstract:
+
+ This module implements the code to emulate the push, pop, pushf, popf,
+ pusha, popa, pushSeg, and popSeg.
+
+Author:
+
+ David N. Cutler (davec) 6-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+VOID
+XmPushOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a push opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Push source value onto stack.
+ //
+
+ XmPushStack(P, P->SrcValue.Long);
+ return;
+}
+
+VOID
+XmPopOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a pop opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Pop the stack and store the result value.
+ //
+
+ XmStoreResult(P, XmPopStack(P));
+ return;
+}
+
+VOID
+XmPushaOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a pusha opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+ ULONG Temp;
+
+ //
+ // Push all registers onto the stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Index = EAX;
+ Temp = P->Gpr[ESP].Exx;
+ do {
+ if (Index == ESP) {
+ XmSetSourceValue(P, (PVOID)&Temp);
+
+ } else {
+ XmSetSourceValue(P, (PVOID)(&P->Gpr[Index].Exx));
+ }
+
+ XmPushOp(P);
+ Index += 1;
+ } while (Index <= EDI);
+ return;
+}
+
+VOID
+XmPopaOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a popa opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+ ULONG Temp;
+
+ //
+ // Pop all register from the stack, but skip over ESP.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ Index = EDI + 1;
+ Temp = P->Gpr[ESP].Exx;
+ do {
+ Index -= 1;
+ if (Index == ESP) {
+ XmSetDestinationValue(P, (PVOID)&Temp);
+
+ } else {
+ XmSetDestinationValue(P, (PVOID)(&P->Gpr[Index].Exx));
+ }
+
+ XmPopOp(P);
+ } while (Index > EAX);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/stringop.c b/private/ntos/nthals/x86new/stringop.c
new file mode 100644
index 000000000..61fc6998a
--- /dev/null
+++ b/private/ntos/nthals/x86new/stringop.c
@@ -0,0 +1,496 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ stringop.c
+
+Abstract:
+
+ This module implements the code to emulate the string opcodes.
+
+Author:
+
+ David N. Cutler (davec) 7-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+XmCompareOperands (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmCmpsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cmpsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ }
+ }
+
+ //
+ // Compare items from source and destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set source and destination values.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ XmSetDestinationValue(P, XmGetStringAddress(P, ES, EDI));
+
+ //
+ // Compare source with destination operand and decrement loop count.
+ // If ZF is not equal to the repeat Z flag condition, then terminate
+ // the loop.
+ //
+
+ XmCompareOperands(P);
+ Count -= 1;
+ if (P->Eflags.ZF != P->RepeatZflag) {
+ break;
+ }
+ }
+
+ //
+ // If a repeat prefix is active, then set the final count value.
+ //
+
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ P->Gpr[ECX].Exx = Count;
+
+ } else {
+ P->Gpr[CX].Xx = (USHORT)Count;
+ }
+ }
+
+ return;
+}
+
+VOID
+XmLodsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a lodsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Set destination address.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)&P->Gpr[EAX].Exx;
+
+ //
+ // Move items from source to destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set source value and store result.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ XmStoreResult(P, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmMovsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a movsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Move items from source to destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set source value, set destination address, and store result.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
+ XmStoreResult(P, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmScasOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a scasb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ }
+ }
+
+ //
+ // Set source value.
+ //
+
+ XmSetSourceValue(P, (PVOID)&P->Gpr[EAX].Exx);
+
+ //
+ // Compare items from source and destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set destination value.
+ //
+
+ XmSetDestinationValue(P, XmGetStringAddress(P, ES, EDI));
+
+ //
+ // Compare source with destination operand and decrement loop count.
+ // If ZF is not equal to the repeat Z flag condition, then terminate
+ // the loop.
+ //
+
+ XmCompareOperands(P);
+ Count -= 1;
+ if (P->Eflags.ZF != P->RepeatZflag) {
+ break;
+ }
+ }
+
+ //
+ // If a repeat prefix is active, then set the final count value.
+ //
+
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ P->Gpr[ECX].Exx = Count;
+
+ } else {
+ P->Gpr[CX].Xx = (USHORT)Count;
+ }
+ }
+
+ return;
+}
+
+VOID
+XmStosOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a stosb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Set source value.
+ //
+
+ XmSetSourceValue(P, (PVOID)&P->Gpr[EAX].Exx);
+
+ //
+ // Move items from source to destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set destination address and store result.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
+ XmStoreResult(P, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmCompareOperands (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function compares two operands and computes the resulting condition
+ codes.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CarryFlag;
+ ULONG OverflowFlag;
+ ULONG SignFlag;
+ ULONG ZeroFlag;
+ union {
+ UCHAR ResultByte;
+ ULONG ResultLong;
+ USHORT ResultWord;
+ } u;
+
+ //
+ // Switch on data type.
+ //
+
+ switch (P->DataType) {
+
+ //
+ // The operation datatype is byte.
+ //
+
+ case BYTE_DATA:
+ CarryFlag = (P->SrcValue.Byte < P->DstValue.Byte);
+ u.ResultByte = P->SrcValue.Byte - P->DstValue.Byte;
+ OverflowFlag = (((u.ResultByte ^ P->SrcValue.Byte) &
+ (u.ResultByte ^ P->DstValue.Byte)) >> 7) & 0x1;
+
+ SignFlag = (u.ResultByte >> 7) & 0x1;
+ ZeroFlag = (u.ResultByte == 0);
+ u.ResultLong = u.ResultByte;
+ break;
+
+ //
+ // The operation datatype is word.
+ //
+
+ case WORD_DATA:
+ CarryFlag = (P->SrcValue.Word < P->DstValue.Word);
+ u.ResultWord = P->SrcValue.Word - P->DstValue.Word;
+ OverflowFlag = (((u.ResultWord ^ P->SrcValue.Word) &
+ (u.ResultWord ^ P->DstValue.Word)) >> 15) & 0x1;
+
+ SignFlag = (u.ResultWord >> 15) & 0x1;
+ ZeroFlag = (u.ResultWord == 0);
+ u.ResultLong = u.ResultWord;
+ break;
+
+ //
+ // The operation datatype is long.
+ //
+
+ case LONG_DATA:
+ CarryFlag = (P->SrcValue.Long < P->DstValue.Long);
+ u.ResultLong = P->SrcValue.Long - P->DstValue.Long;
+ OverflowFlag = (((u.ResultLong ^ P->SrcValue.Long) &
+ (u.ResultLong ^ P->DstValue.Long)) >> 31) & 0x1;
+
+ SignFlag = (u.ResultLong >> 31) & 0x1;
+ ZeroFlag = (u.ResultLong == 0);
+ break;
+ }
+
+ //
+ // Compute auxilary carry flag, parity flag, and store all flags in
+ // the flags register.
+ //
+
+ P->Eflags.CF = CarryFlag;
+ P->Eflags.PF = XmComputeParity(u.ResultLong);
+ P->Eflags.AF = ((P->DstValue.Byte & 0xf) + (P->SrcValue.Byte & 0xf)) >> 4;
+ P->Eflags.ZF = ZeroFlag;
+ P->Eflags.SF = SignFlag;
+ P->Eflags.OF = OverflowFlag;
+ return;
+}
diff --git a/private/ntos/nthals/x86new/utility.c b/private/ntos/nthals/x86new/utility.c
new file mode 100644
index 000000000..530c45e23
--- /dev/null
+++ b/private/ntos/nthals/x86new/utility.c
@@ -0,0 +1,541 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ utility.c
+
+Abstract:
+
+ This module implements utility functions.
+
+Author:
+
+ David N. Cutler (davec) 7-Sep-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define bit count array.
+//
+
+UCHAR XmBitCount[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+
+ULONG
+XmComputeParity (
+ IN ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function computes the parity of the low byte of the specified
+ result.
+
+Arguments:
+
+ Result - Supplies the result for which the parity flag is computed.
+
+Return Value:
+
+ The parity flag value.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // Sum the bits in the result and return the complement of the low bit.
+ //
+
+ Count = XmBitCount[Result & 0xf];
+ Count += XmBitCount[(Result >> 4) & 0xf];
+ return (~Count) & 1;
+}
+
+UCHAR
+XmGetCodeByte (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the next code byte from the instruction stream.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next byte form the instruction stream.
+
+--*/
+
+{
+
+ ULONG Offset;
+
+ //
+ // If the current IP is within the code segment, then return the
+ // next byte from the instrcution stream and increment the IP value.
+ // Otherwise, raise an exception.
+ //
+
+ Offset = P->Eip;
+ if (Offset > P->SegmentLimit[CS]) {
+ longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
+ }
+
+ P->Ip += 1;
+ return *(PUCHAR)((P->TranslateAddress)(P->SegmentRegister[CS], (USHORT)Offset));
+}
+
+UCHAR
+XmGetByteImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate byte operand from the
+ code stream and returns a byte value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next byte from the instruction stream.
+
+--*/
+
+{
+
+ UCHAR Byte;
+
+ //
+ // Get immediate byte from the code stream.
+ //
+
+ Byte = XmGetCodeByte(P);
+ XmTraceInstruction(BYTE_DATA, (ULONG)Byte);
+ return Byte;
+}
+
+USHORT
+XmGetByteImmediateToWord (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate byte operand from the
+ code stream and returns a zero extended byte to word value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next byte from the instruction stream zero extended to a word.
+
+--*/
+
+{
+
+ USHORT Word;
+
+ //
+ // Get immediate byte from the code stream.
+ //
+
+ Word = XmGetCodeByte(P);
+ XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Word));
+ return Word;
+}
+
+ULONG
+XmGetByteImmediateToLong (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate byte operand from the
+ code stream and returns a zero extended byte to long value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next byte from the instruction stream zero extended to a long.
+
+--*/
+
+{
+
+ ULONG Long;
+
+ //
+ // Get immediate byte from the code stream.
+ //
+
+ Long = XmGetCodeByte(P);
+ XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Long));
+ return Long;
+}
+
+USHORT
+XmGetSignedByteImmediateToWord (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate byte operand from the
+ code stream and returns a sign extended byte to word value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next byte from the instruction stream sign extended to a word.
+
+--*/
+
+{
+
+ USHORT Word;
+
+ //
+ // Get immediate byte from the code stream.
+ //
+
+ Word = (USHORT)((SHORT)((SCHAR)XmGetCodeByte(P)));
+ XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Word));
+ return Word;
+}
+
+ULONG
+XmGetSignedByteImmediateToLong (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate byte operand from the
+ code stream and returns a sign extended byte to long value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next byte from the instruction stream sign extended to a long.
+
+--*/
+
+{
+
+ ULONG Long;
+
+ //
+ // Get immediate byte from the code stream.
+ //
+
+ Long = (ULONG)((LONG)((SCHAR)XmGetCodeByte(P)));
+ XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Long));
+ return Long;
+}
+
+USHORT
+XmGetWordImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate word operand from the
+ code stream and returns a word value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next word from the instruction stream.
+
+--*/
+
+{
+
+ USHORT Word;
+
+ //
+ // Get immediate word from the code stream.
+ //
+
+ Word = XmGetCodeByte(P);
+ Word += XmGetCodeByte(P) << 8;
+ XmTraceInstruction(WORD_DATA, (ULONG)Word);
+ return Word;
+}
+
+ULONG
+XmGetLongImmediate (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an unsigned immediate long operand from the
+ code stream and returns a long value.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ The next long from the instruction stream.
+
+--*/
+
+{
+
+ ULONG Long;
+
+ //
+ // Get immediate long from the code stream.
+ //
+
+ Long = XmGetCodeByte(P);
+ Long += XmGetCodeByte(P) << 8;
+ Long += XmGetCodeByte(P) << 16;
+ Long += XmGetCodeByte(P) << 24;
+ XmTraceInstruction(LONG_DATA, Long);
+ return Long;
+}
+
+ULONG
+XmPopStack (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function pops an operand from the stack.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Offset;
+
+ //
+ // Compute the new stack address and compare against the segment limit.
+ // If the new address is greater than the limit, then raise an exception.
+ // Otherwise, perform the push operation.
+ //
+
+ Offset = P->Gpr[ESP].Exx;
+ if (Offset > (ULONG)(P->SegmentLimit[SS] - P->DataType)) {
+ longjmp(&P->JumpBuffer[0], XM_STACK_UNDERFLOW);
+ }
+
+ P->Gpr[ESP].Exx += (P->DataType + 1);
+ XmSetSourceValue(P, (P->TranslateAddress)(P->SegmentRegister[SS], (USHORT)Offset));
+ return P->SrcValue.Long;
+}
+
+VOID
+XmPushStack (
+ IN PRXM_CONTEXT P,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function pushes an operand on the stack.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+ Value - Supplies the value to be pushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Offset;
+
+ //
+ // Compute the new stack address and compare against the segment limit.
+ // If the new address is greater than the limit, then raise an exception.
+ // Otherwise, perform the push operation.
+ //
+
+ Offset = P->Gpr[ESP].Exx - P->DataType - 1;
+ if (Offset > (ULONG)(P->SegmentLimit[SS] - P->DataType)) {
+ longjmp(&P->JumpBuffer[0], XM_STACK_OVERFLOW);
+ }
+
+ P->Gpr[ESP].Exx = Offset;
+ P->DstLong = (ULONG UNALIGNED *)((P->TranslateAddress)(P->SegmentRegister[SS],
+ (USHORT)Offset));
+
+ XmStoreResult(P, Value);
+ return;
+}
+
+VOID
+XmSetDataType (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the data type of the operation based on the width
+ bit of the current opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If the width bit is zero, then the data type is byte. Otherwise,
+ // the datatype is determined by the presence of absence of a operand
+ // size prefix.
+ //
+
+ if ((P->CurrentOpcode & WIDTH_BIT) == 0) {
+ P->DataType = BYTE_DATA;
+
+ } else if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ return;
+}
+
+VOID
+XmStoreResult (
+ IN PRXM_CONTEXT P,
+ IN ULONG Result
+ )
+
+/*++
+
+Routine Description:
+
+ This function stores the result of an operation.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+ Result - Supplies the result value to store.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Store result of operation.
+ //
+
+ if (P->DataType == BYTE_DATA) {
+ *P->DstByte = (UCHAR)Result;
+
+ } else if (P->DataType == WORD_DATA) {
+ if (((ULONG)P->DstWord & 0x1) == 0) {
+ *((PUSHORT)(P->DstWord)) = (USHORT)Result;
+
+ } else {
+ *P->DstWord = (USHORT)Result;
+ }
+
+ } else {
+ if (((ULONG)P->DstLong & 0x3) == 0) {
+ *((PULONG)(P->DstLong)) = Result;
+
+ } else {
+ *P->DstLong = Result;
+ }
+ }
+
+ XmTraceResult(P, Result);
+ return;
+}
diff --git a/private/ntos/nthals/x86new/x86bios.c b/private/ntos/nthals/x86new/x86bios.c
new file mode 100644
index 000000000..62f07e91e
--- /dev/null
+++ b/private/ntos/nthals/x86new/x86bios.c
@@ -0,0 +1,837 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space, the base address
+// of I/O memory space, and the base address of the video frame buffer.
+//
+
+ULONG x86BiosFrameBuffer;
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+//
+// Define storage for PCI BIOS initialization state.
+//
+
+UCHAR XmNumberPciBusses = 0;
+BOOLEAN XmPciBiosPresent = FALSE;
+PGETSETPCIBUSDATA XmGetPciData;
+PGETSETPCIBUSDATA XmSetPciData;
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ if (DataType == BYTE_DATA) {
+ Result = READ_PORT_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_PORT_UCHAR(u.Byte + 0)) |
+ (READ_PORT_UCHAR(u.Byte + 1) << 8) |
+ (READ_PORT_UCHAR(u.Byte + 2) << 16) |
+ (READ_PORT_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ Result = READ_PORT_ULONG(u.Long);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_PORT_UCHAR(u.Byte + 0)) |
+ (READ_PORT_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_PORT_USHORT(u.Word);
+ }
+ }
+
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ if (DataType == BYTE_DATA) {
+ WRITE_PORT_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_PORT_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_PORT_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_PORT_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_PORT_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_PORT_ULONG(u.Long, Value);
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_PORT_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_PORT_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_PORT_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ if (x86BiosFrameBuffer != 0) {
+ return (PVOID)(x86BiosFrameBuffer + Offset + Value);
+ }
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Initialize x86 BIOS emulation.
+ //
+
+ x86BiosInitializeBiosShadowed(BiosIoSpace,
+ BiosIoMemory,
+ NULL);
+
+ return;
+}
+
+VOID
+x86BiosInitializeBiosShadowed (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory,
+ IN PVOID BiosFrameBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+ BiosFrameBuffer - Supplies the base address of the video frame buffer
+ to be used for bios emulation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ x86BiosFrameBuffer = (ULONG)BiosFrameBuffer;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+VOID
+x86BiosInitializeBiosShadowedPci (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory,
+ IN PVOID BiosFrameBuffer,
+ IN UCHAR NumberPciBusses,
+ IN PGETSETPCIBUSDATA GetPciData,
+ IN PGETSETPCIBUSDATA SetPciData
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes x86 BIOS emulation and also sets up the
+ emulator with BIOS shadowed and PCI functions enabled. Since the
+ PCI specification requires BIOS shadowing, there isn't any need
+ to provide a function that turns on the PCI functions, but doesn't
+ shadow the BIOS.
+
+Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+ BiosFrameBuffer - Supplies the base address of the video frame buffer
+ to be used for bios emulation.
+
+ NumberPciBusses - Supplies the number of PCI busses in the system.
+
+ GetPciData - Supplies the address of a function to read the PCI
+ configuration space.
+
+ SetPciData - Supplies the address of a function to write the PCI
+ configuration space.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Enable PCI BIOS support.
+ //
+
+ XmPciBiosPresent = TRUE;
+ XmGetPciData = GetPciData;
+ XmSetPciData = SetPciData;
+ XmNumberPciBusses = NumberPciBusses;
+
+ //
+ // Initialize x86 BIOS emulation.
+ //
+
+ x86BiosInitializeBiosShadowed(BiosIoSpace,
+ BiosIoMemory,
+ BiosFrameBuffer);
+
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+ BiosIoSpace - Supplies an optional base address of the I/O space
+ to be used for BIOS emulation.
+
+ BiosIoMemory - Supplies an optional base address of the I/O memory
+ to be used for BIOS emulation.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ //
+ // Execute x86 interrupt.
+ //
+
+ return x86BiosExecuteInterruptShadowed(Number,
+ Context,
+ BiosIoSpace,
+ BiosIoMemory,
+ NULL);
+}
+
+XM_STATUS
+x86BiosExecuteInterruptShadowed (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+ BiosIoSpace - Supplies an optional base address of the I/O space
+ to be used for BIOS emulation.
+
+ BiosIoMemory - Supplies an optional base address of the I/O memory
+ to be used for BIOS emulation.
+
+ BiosFrameBuffer - Supplies an optional base address of the video
+ frame buffer to be used for bios emulation.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ if (BiosFrameBuffer != NULL) {
+ x86BiosFrameBuffer = (ULONG)BiosFrameBuffer;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosExecuteInterruptShadowedPci (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL,
+ IN UCHAR NumberPciBusses,
+ IN PGETSETPCIBUSDATA GetPciData,
+ IN PGETSETPCIBUSDATA SetPciData
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+ BiosIoSpace - Supplies an optional base address of the I/O space
+ to be used for BIOS emulation.
+
+ BiosIoMemory - Supplies an optional base address of the I/O memory
+ to be used for BIOS emulation.
+
+ NumberPciBusses - Supplies the number of PCI busses in the system.
+
+ GetPciData - Supplies the address of a function to read the PCI
+ configuration space.
+
+ SetPciData - Supplies the address of a function to write the PCI
+ configuration space.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ //
+ // Enable PCI BIOS support.
+ //
+
+ XmPciBiosPresent = TRUE;
+ XmGetPciData = GetPciData;
+ XmSetPciData = SetPciData;
+ XmNumberPciBusses = NumberPciBusses;
+
+ //
+ // Execute x86 interrupt.
+ //
+
+ return x86BiosExecuteInterruptShadowed(Number,
+ Context,
+ BiosIoSpace,
+ BiosIoMemory,
+ BiosFrameBuffer);
+}
+
+XM_STATUS
+x86BiosInitializeAdapter(
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ //
+ // Initialize the specified adapter.
+ //
+
+ return x86BiosInitializeAdapterShadowed(Adapter,
+ Context,
+ BiosIoSpace,
+ BiosIoMemory,
+ NULL);
+}
+
+XM_STATUS
+x86BiosInitializeAdapterShadowed (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ if (BiosFrameBuffer != NULL) {
+ x86BiosFrameBuffer = (ULONG)BiosFrameBuffer;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
+ }
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapterShadowedPci(
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL,
+ IN UCHAR NumberPciBusses,
+ IN PGETSETPCIBUSDATA GetPciData,
+ IN PGETSETPCIBUSDATA SetPciData
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+Return Value:
+
+ The emulation completion status.
+
+--*/
+
+{
+
+ //
+ // Enable PCI BIOS support.
+ //
+
+ XmPciBiosPresent = TRUE;
+ XmGetPciData = GetPciData;
+ XmSetPciData = SetPciData;
+ XmNumberPciBusses = NumberPciBusses;
+
+ //
+ // Initialize the specified adapter.
+ //
+
+ return x86BiosInitializeAdapterShadowed(Adapter,
+ Context,
+ BiosIoSpace,
+ BiosIoMemory,
+ BiosFrameBuffer);
+}
diff --git a/private/ntos/nthals/x86new/x86new.h b/private/ntos/nthals/x86new/x86new.h
new file mode 100644
index 000000000..3f5664cc8
--- /dev/null
+++ b/private/ntos/nthals/x86new/x86new.h
@@ -0,0 +1,168 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86new.h
+
+Abstract:
+
+ This module contains the public header file that describes the
+ HAL interfaces to the 386/486 BIOS emulation.
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Revision History:
+
+--*/
+
+#ifndef _X86NEW_
+#define _X86NEW_
+
+//
+// PCI Bios function code defintitions.
+//
+// AH:
+//
+
+#define PCI_FUNCTION_ID 0xb1
+
+//
+// AL:
+//
+
+#define PCI_BIOS_PRESENT 0x01
+#define PCI_FIND_DEVICE 0x02
+#define PCI_FIND_CLASS_CODE 0x03
+#define PCI_GENERATE_CYCLE 0x06
+#define PCI_READ_CONFIG_BYTE 0x08
+#define PCI_READ_CONFIG_WORD 0x09
+#define PCI_READ_CONFIG_DWORD 0x0a
+#define PCI_WRITE_CONFIG_BYTE 0x0b
+#define PCI_WRITE_CONFIG_WORD 0x0c
+#define PCI_WRITE_CONFIG_DWORD 0x0d
+#define PCI_GET_IRQ_ROUTING 0x0e
+#define PCI_SET_IRQ 0x0f
+
+//
+// PCI Bios function return code values.
+//
+
+#define PCI_SUCCESS 0x00
+#define PCI_NOT_SUPPORTED 0x81
+#define PCI_BAD_VENDOR_ID 0x83
+#define PCI_DEVICE_NOT_FOUND 0x86
+#define PCI_BAD_REGISTER 0x87
+#define PCI_SET_FAILED 0x88
+#define PCI_BUFFER_TOO_SMALL 0x89
+
+//
+// Miscellaneous PCI codes.
+//
+
+#define PCI_CONFIG_MECHANISM_2 0x02
+#define PCI_ILLEGAL_VENDOR_ID 0xffff
+
+//
+// Define PCI get/set function type.
+//
+
+typedef
+ULONG
+(*PGETSETPCIBUSDATA)(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// Define BIOS emulation interfaces.
+//
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ );
+
+VOID
+x86BiosInitializeBiosShadowed (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory,
+ IN PVOID BiosFrameBuffer
+ );
+
+VOID
+x86BiosInitializeBiosShadowedPci (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory,
+ IN PVOID BiosFrameBuffer,
+ IN UCHAR NumberPciBusses,
+ IN PGETSETPCIBUSDATA GetPciData,
+ IN PGETSETPCIBUSDATA SetPciData
+ );
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ );
+
+XM_STATUS
+x86BiosExecuteInterruptShadowed (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL
+ );
+
+XM_STATUS
+x86BiosExecuteInterruptShadowedPci (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL,
+ IN UCHAR NumberPciBusses,
+ IN PGETSETPCIBUSDATA GetPciData,
+ IN PGETSETPCIBUSDATA SetPciData
+ );
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ );
+
+XM_STATUS
+x86BiosInitializeAdapterShadowed (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL
+ );
+
+XM_STATUS
+x86BiosInitializeAdapterShadowedPci(
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL,
+ IN PVOID BiosFrameBuffer OPTIONAL,
+ IN UCHAR NumberPciBusses,
+ IN PGETSETPCIBUSDATA GetPciData,
+ IN PGETSETPCIBUSDATA SetPciData
+ );
+
+#endif // _X86NEW_
diff --git a/private/ntos/nthals/x86new/xm86.h b/private/ntos/nthals/x86new/xm86.h
new file mode 100644
index 000000000..f0e994d88
--- /dev/null
+++ b/private/ntos/nthals/x86new/xm86.h
@@ -0,0 +1,129 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xm86.h
+
+Abstract:
+
+ This module contains the public header file that describes the
+ interfaces to the 386/486 real mode emulator.
+
+Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+Revision History:
+
+--*/
+
+#ifndef _XM86_
+#define _XM86_
+
+//
+// Define internal error codes.
+//
+
+typedef enum _XM_STATUS {
+ XM_SUCCESS = 1,
+ XM_DIVIDE_BY_ZERO,
+ XM_DIVIDE_QUOTIENT_OVERFLOW,
+ XM_EMULATOR_NOT_INITIALIZED,
+ XM_HALT_INSTRUCTION,
+ XM_ILLEGAL_CODE_SEGMENT,
+ XM_ILLEGAL_INDEX_SPECIFIER,
+ XM_ILLEGAL_LEVEL_NUMBER,
+ XM_ILLEGAL_PORT_NUMBER,
+ XM_ILLEGAL_GENERAL_SPECIFIER,
+ XM_ILLEGAL_REGISTER_SPECIFIER,
+ XM_ILLEGAL_INSTRUCTION_OPCODE,
+ XM_INDEX_OUT_OF_BOUNDS,
+ XM_SEGMENT_LIMIT_VIOLATION,
+ XM_STACK_OVERFLOW,
+ XM_STACK_UNDERFLOW,
+ XM_MAXIMUM_INTERNAL_CODE
+} XM_STATUS;
+
+//
+// Define operand data types.
+//
+
+typedef enum _XM_OPERATION_DATATYPE {
+ BYTE_DATA = 0,
+ WORD_DATA = 1,
+ LONG_DATA = 3
+} XM_OPERATION_DATATYPE;
+
+//
+// Define emulator context structure.
+//
+
+typedef struct _XM86_CONTEXT {
+ ULONG Eax;
+ ULONG Ecx;
+ ULONG Edx;
+ ULONG Ebx;
+ ULONG Ebp;
+ ULONG Esi;
+ ULONG Edi;
+} XM86_CONTEXT, *PXM86_CONTEXT;
+
+//
+// Define address translation callback function type.
+//
+
+typedef
+PVOID
+(*PXM_TRANSLATE_ADDRESS) (
+ IN USHORT Segment,
+ IN USHORT Offset
+ );
+
+//
+// Define read and write I/O space callback function types.
+//
+
+typedef
+ULONG
+(*PXM_READ_IO_SPACE) (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ );
+
+typedef
+VOID
+(*PXM_WRITE_IO_SPACE) (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ );
+
+//
+// Define emulator public interface function prototypes.
+//
+
+XM_STATUS
+XmEmulateFarCall (
+ IN USHORT Segment,
+ IN USHORT Offset,
+ IN OUT PXM86_CONTEXT Context
+ );
+
+XM_STATUS
+XmEmulateInterrupt (
+ IN UCHAR Interrupt,
+ IN OUT PXM86_CONTEXT Context
+ );
+
+VOID
+XmInitializeEmulator (
+ IN USHORT StackSegment,
+ IN USHORT StackOffset,
+ IN PXM_READ_IO_SPACE ReadIoSpace,
+ IN PXM_WRITE_IO_SPACE WriteIoSpace,
+ IN PXM_TRANSLATE_ADDRESS TranslateAddress
+ );
+
+#endif // _XM86_